This is the multi-page printable view of this section. Click here to print.

Return to the regular view of this page.

Docs

Documentation

1 - Projects

Project tree

This tree contains first-party products and reusable project code. All tracked content follows the repository’s public-source policy.

  • Bazel targets MAY use public visibility when their owner intends external reuse.
  • Project artifacts MAY be published through an explicit release workflow.
  • Project targets MAY be used by production build targets.

These configured site addresses use project names with underscores replaced by hyphens. The alwaldend.com project uses the main website.

Project documentation Description Landing page
Agents Repository-wide agent-system architecture, goals, and skills agents.alwaldend.com
Al Repository command runner and Bazel configuration rules al.alwaldend.com
Alwaldend.com Main website and project documentation alwaldend.com
Android launcher Text-only Android launcher built with Kotlin and Jetpack Compose android-launcher.alwaldend.com
Ansible collection Ansible collection alwaldend.main with Bazel source packaging ansible-collection.alwaldend.com
Autoscroll Mouse-driven autoscroll CLI with reloadable configuration autoscroll.alwaldend.com
Bazel agent Bazel runner for repository agents bazel-agent.alwaldend.com
Ci platform Abandoned CI platform with a Go backend and Vue frontend ci-platform.alwaldend.com
Dotfiles Personal configuration files with installation and comparison commands dotfiles.alwaldend.com
Goal Versioned goal resources, local storage, and agent workflow goal.alwaldend.com
Hugo Landing Reusable Hugo landing site for project pages hugo-landing.alwaldend.com
Infinitime InfiniTime firmware fork with a text watchface and Pomodoro app infinitime.alwaldend.com
Kustomization Kubernetes resources for Flux, Traefik, and cert-manager kustomization.alwaldend.com
Leetcode downloader LeetCode submission export and documentation tools leetcode-downloader.alwaldend.com
MCP Cordis Workspace-local runtime packages behind a stable MCP server mcp-cordis.alwaldend.com
Nexus security plugin Security plugin for Sonatype Nexus 3 nexus-security-plugin.alwaldend.com
Renders Repository-owned render assets and their acceptance evidence renders.alwaldend.com
Rules binary toolchain Bazel toolchains for packaged executable binaries rules-binary-toolchain.alwaldend.com
Rules Dnscontrol Bazel-aware DNSControl configuration packaging rules-dnscontrol.alwaldend.com
Rules docs Bazel documentation packaging rules rules-docs.alwaldend.com
Rules docs Gazelle Gazelle extension for Bazel documentation packaging rules rules-docs-gazelle.alwaldend.com
Rules Hugo Bazel rules for Hugo sites rules-hugo.alwaldend.com
rules_iso ISO image download and flash rules rules-iso.alwaldend.com
Rules Promptfoo A pinned Bazel runner for Promptfoo skill evaluations rules-promptfoo.alwaldend.com
Rules Promptfoo Gazelle Gazelle extension for offline Promptfoo validation tests rules-promptfoo-gazelle.alwaldend.com
Rules skill Bazel rules and validation for Codex skills rules-skill.alwaldend.com
Rules skill Gazelle Gazelle extension for Bazel skill libraries rules-skill-gazelle.alwaldend.com
Rules template Bazel rules and a Go command for rendering template files rules-template.alwaldend.com
Sri Command-line Subresource Integrity calculator using OpenSSL sri.alwaldend.com
Tf modules Reusable Terraform modules for Vault, virtual machines, and storage tf-modules.alwaldend.com
Useless QT GUI Desktop GUI application built with C++ and Qt useless-qt-gui.alwaldend.com

1.1 - Agents

Repository-wide agent-system architecture, goals, and skills

Repository agent system

This project owns the repository-wide agent-system contract, its durable improvement goals, and reusable cross-repository skills. It does not centralize component facts or runtime state: each fact remains canonical at its natural owner, and system-wide views are derived projections.

Document Purpose
Current state Evidence-backed baseline and material seams
Architecture Canonical abstraction tower, authorities, and invariants
Roadmap Dependency-ordered future work and acceptance signals
Durable goals Versioned attempts, evidence, and acceptance state
Root agent guide Current repository-wide operating policy

The current-state document describes supported entry points and their evidence boundaries. Dated audits remain in the goal records. The architecture defines the intended composition contract; the roadmap does not claim that proposed interfaces already exist.

  • docs/ owns the cross-layer system model and plan, not duplicated component configuration.
  • goals/ owns durable repository-agent work records and evidence.
  • skills/ owns reusable repository-wide agent procedures and their development-time evaluations.
  • Product-specific skills remain with their project at projects/<project>/skills/<name>.
  • Repository-internal executors and build integrations may live under tools/; their behavior remains owned and documented there.

Every canonical skill is packaged as a skill_library in its owning directory.

The repository discovery directory .agents/skills/ contains one relative symlink per skill. Each link points directly to its canonical project-owned directory. Bazel ignores the discovery directory and builds only canonical targets, preventing duplicate packages while allowing skills from more than one owning project.

Skill evaluation data is not part of the runtime skill_library unless a skill explicitly declares otherwise. Every new or updated skill includes an offline Promptfoo configuration-validation target. That target checks the eval harness, not answer correctness. Live behavioral evaluations are manual, networked tests and must not be included in ordinary wildcard test runs; they may be omitted when representative coverage requires tool calls or external state that cannot be provided safely and reproducibly, with the gap documented beside the eval configuration.

1.1.1 - Repository agent goals

Durable goals, attempts, and evidence for the repository agent system

Repository agent goals

Each child directory is an owner-local durable goal record. Canonical resource files and attempt artifacts are created and validated through the repository goal workflow; do not edit generated records or projections directly.

Goal evidence may contain source and operational analysis, including non-secret live or generated facts. It must never contain credentials, other secrets, or personal information. Inspect raw artifacts before promoting their content. Structured task artifacts such as FrictionRecord and LearningProposal JSON files are task scratch: keep them under out/<task>/ and cite them from goal evidence Markdown rather than committing them into evidence/, which accepts only .md files.

Discover current open work through the goal catalog and its bounded resume view; status is owned by each goal record. The agent-system-phase-six-ergonomics/ goal records a completed friction-reduction attempt, with the original evidence and its limitations preserved.

The current-state document describes supported interfaces and current evidence boundaries. Closed attempts remain historical records; later implementation reviews may narrow claims they made without rewriting those immutable records.

1.1.2 - Repository agent system current state

Supported agent entry points, evidence boundaries, and limitations

Repository agent system current state

This is the maintained guide to the checked-in interfaces. Source links below identify their owners; runtime availability must be observed in the current session. Historical audits and acceptance claims remain in the immutable goal records. Their dates and evidence tiers limit what they prove.

Read applicable AGENTS.md instructions and the nearest owner README. Use the available Cordis repository-context handlers for bounded reads and searches, or the native tools when Cordis is unavailable. Cordis availability does not determine whether offline repository work is possible.

The offline context command provides a bounded advisory view:

bazel_agent bazel run //tools/agents/cmd/agent_system -- \
  --workspace-root "$PWD" --path projects/goal

Its owner documentation describes the supported flags and limitations. Catalog declarations identify source facts; they do not establish live provider health, action authorization, successful validation, or a task’s association with a goal. Missing observations remain explicit. A source digest proves identity, not freshness against a live system.

Need Entry point Boundary
Policy and layout Applicable AGENTS.md, owner README, BUILD and MODULE files The user request owns intended outcome and authorization.
Procedure Canonical skill selected from .agents/skills Load only the procedure needed for the task.
Build or test bazel_agent bazel <command> Start with the affected package and avoid redundant compatible invocations.
Context //tools/agents/cmd/agent_system Offline, advisory source projection.
Stored runtime status //tools/agents/cmd/control_status Stored package observations do not prove present runtime health.
Durable work //projects/goal/cmd/goal Use workspace records for task coordination and owner-local project records when maintained history is needed.
Delivery //tools/repo_delivery Prepare, establish applicable validation, then explicitly publish the exact candidate.

The Bazel runner also supports cached control-tool execution in current builds. If an installed runner lacks that subcommand, the supported bazel run targets remain available. Updating a shared host installation is a separate operation from changing repository source.

Simple tasks need no durable goal. For work that needs a resume point, the goal checkpoint accepts a short summary, the current candidate, evidence references, and the next action. The store maintains the record’s identity and digests; show includes the active continuation. Detailed attempt review remains available for repeated failures and maintained project history. Local progress checkpoints do not trigger publication. Deliver at a meaningful review boundary or final handoff, with explicit remote backups when needed.

Delivery can execute a caller-selected Bazel validation plan and retain its results against the prepared candidate. Its continue command reports the next state; continue --publish explicitly requests publication using those results. The tool carries the candidate and receipt between steps. It does not decide task ownership, semantic sufficiency, or whether representative output satisfies the request. Changed candidates and rebases require fresh validation; uncertain publication outcomes require inspection before another mutation. Follow the owning README’s launcher instructions when validation itself invokes Bazel.

  • Skill packaging validates canonical artifacts and discovery links. Evaluation payloads are separate from runtime skill bodies.
  • Goal storage validates resource revisions and artifact digests, provides bounded continuation information, and supports recovery from interrupted publication. These checks establish record integrity; criterion verdicts still require appropriate evidence.
  • Delivery binds the prepared candidate, scope, remote expectations, and pull-request identity. Exact leases and state checks protect publication. The caller selects and establishes the required validation; a preparation receipt is not a test result.
  • Cordis provides bounded repository tools and supervised subprocess cleanup. Its package code is trusted. The documented process boundary is not a security sandbox.

The coverage projection inventories configured cases. It does not measure successful routing or task completion. Offline configuration checks are useful hygiene; stronger claims require actual result artifacts identifying the source, fixture, execution, and judge where applicable.

The shared control contracts include admission and runtime-control libraries with unit tests. Their existence does not establish enforcement by production providers. Earlier phase acceptance records describe broader gateway and runtime guarantees than those unit tests demonstrate. Treat provider integration, process isolation, and runtime fault containment as unverified until a concrete consumer and corresponding integration evidence establish them. The roadmap retains that future work.

Stored control snapshots contain package observations. Their age, missing writer identity, and lack of a live heartbeat limit their interpretation. The status reader preserves those limitations and does not create a runtime or its storage directories merely to inspect them.

Measure representative questions, edits, recovery, and delivery tasks before claiming an instruction or workflow is faster or more reliable. Compare task success, unauthorized actions, context bytes, commands, duration, and resume steps against the prior behavior. Keep model and fixture identities with observations; do not infer measured improvement from configuration checks or the presence of a new schema.

The local comparison fixtures provide four bounded scenarios and an observer protocol. They cover question answering, a local prose edit, recovery after a changed postcondition, and a delivery validation decision. Their simulated observations do not exercise real publication. Unobservable routing, command, context, or token metrics remain unavailable; available instruction bytes are not the same as consumed context. Results belong with the exact task candidate, not in the configured coverage inventory.

Preserve useful safeguards while reducing repeated consumer instructions. Retire obsolete workarounds and completed tracking when justified. Clean runs after a fix are not a reason to remove useful diagnostics or regression tests. Historical proposals suggesting otherwise do not define current policy.

The architecture describes composition responsibilities. It does not replace these implementation boundaries or authorize new work.

1.1.3 - Repository agent-system architecture

Canonical composition contract for repository-wide agent work, evidence, delivery, and learning

Repository agent-system architecture

This document defines the target composition contract for the repository as one agent-driven system. It is normative about boundaries, invariants, and ownership. A named interface or record is not a current capability merely because it appears here. The current-state snapshot describes implemented behavior; the roadmap orders the work needed to reach this design.

The objective is to let an agent form an accurate situation model, choose the least costly safe action, prove the exact result, and make later work cheaper. The design must remain useful with no daemon, network, credential, runtime extension, or active durable goal.

The repository should have one composition protocol, not one mutable brain.

Each fact stays at its narrow natural owner. Typed, versioned references join facts across owners. Deterministic bounded projections make those joins cheap to read. An execution gateway enforces effects at the point where they occur. No catalog, agent, skill, plan, or receipt may silently become an independent authority.

This yields four structural rules:

  1. One mutation authority per fact. A fact changes only at its owner.
  2. Many derived views. Human maps, JSON catalogs, context capsules, and status views are replaceable projections with provenance.
  3. Typed transitions. Cross-layer claims carry stable identities, versions or digests, completeness, and limitations.
  4. Effects are admitted at execution. Selection and planning advise; explicit authority plus an executable contract controls mutation.

Physical co-location is not required for logical cohesion. Repository-agent documents and goals belong under projects/agents. A future repository-internal controller or executor may belong under tools/agents. Component declarations remain with their component.

Fact Mutation authority System projection
Requested outcome and granted authority Current user/task interaction Task authority envelope
Applicable agent policy Nearest AGENTS.md chain Policy slice with source digests
Component purpose and local boundary Nearest owner README.md Topology record
Review accountability CODEOWNERS Effective reviewer record
Workspace and dependency structure MODULE.bazel, BUILD, and owning macros Workspace and action catalogs
Reusable procedure and routing intent Canonical project-owned skill Capability record
Durable outcome, criteria, and attempts Owner-local goal resources Goal catalog and resume packet
Task-local scratch and worker ownership Task manifest below ignored out/<task>/ Bounded task-status record
Desired runtime configuration Owning checked-in or task-local config Desired-state reference
Observed runtime state Live provider instance Provider-health observation
Source candidate Git plus an explicit dirty-input declaration Subject reference
Check execution Executing provider Action receipt
Acceptance judgment Goal criterion or task acceptance policy Evidence assertion
Feature publication and review Git, forge, and repository delivery Delivery and review receipts
Version and release identity Versioning and release owners Release identity and manifest
Durable adopted learning Destination owner through normal review Updated contract and regression

The architecture owns only this composition model. It must not restate mutable component values. If two authorities conflict, a projection reports the conflict and its sources; it does not choose a winner. A relevant unresolved conflict blocks effectful admission.

Cross-layer artifacts should share a small logical envelope. The roadmap owns the eventual schema and migration; payloads remain subsystem-specific.

ArtifactEnvelope
  apiVersion, kind, id
  producerRef
  authorityRefs[]?
  inputRefs[]: {kind, id, version?, digest, role}
  subjectRef?
  completeness: complete | partial | truncated | unknown
  limitations[]
  informationClass
  retentionClass
  digest

Observation or expiry times belong on live observations. Deterministic catalog content must not contain nondeterministic generation timestamps. Artifacts never contain credentials, secret-value hashes, personal information, environment dumps, absolute checkout paths, unreviewed raw logs, or full transcripts.

An authority reference is optional and repeatable. A deterministic catalog or ordinary observation does not gain authority merely by using this envelope. The artifact digest covers canonical schema-defined bytes without recursively including its own digest field.

A SubjectRef identifies the thing a claim is about. Depending on the claim, it can bind repository identity, base/commit/tree OIDs, the explicit task-owned dirty input set, relevant configuration and toolchain digests, an environment or remote resource selector, and a timed remote observation. Claims must not use a weaker subject merely because it is easier to obtain.

Each layer consumes contracts from the layer above, adds one kind of fact, and produces a bounded contract for the layer below.

Owner: the user interaction; durable acceptance belongs to the goal when one exists.

Input: the request, explicit constraints, and prior accepted context.

Output: an outcome, acceptance questions, scope, authority envelope, and resource limits.

Invariant: a question, skill selection, plan, prior permission, or tool availability never widens authority. Conditional authority is usable only after its condition is evidenced. Missing authority is unknown, not permission.

Repository policy may define an explicit implementation request to include ordinary feature-branch commit, publication, and review through the delivery workflow. That default must be visible in the authority envelope and never extends to tags, releases, deployments, infrastructure changes, or destruction.

Simple bounded tasks may keep this state in the active interaction. Iterative, delegated, or resumable work uses a durable goal and attempt.

Owners: paths, nearest READMEs, CODEOWNERS, MODULE.bazel, BUILD files, and explicit boundary declarations.

Input: workspace identity plus affected paths or labels.

Output: component and workspace identity, applicable policy sources, review accountability, dependency role, and classification axes.

Invariant: keep these axes independent:

  • checked-in source disclosure;
  • log and evidence handling;
  • Bazel target visibility;
  • allowed build consumers;
  • artifact and documentation publication; and
  • secret or personal-information presence and live-environment association.

Checked-in content in this public repository is public information unless it contains an accidental secret or personal information. Operational facts do not become confidential merely because they are generated or live, but raw artifacts require inspection because they can contain prohibited content. Public information status does not make a target eligible for production consumption or artifact publication.

Owners: applicable AGENTS.md, owner-local policy, and the executable provider or owning build macro.

Input: authority envelope, topology slice, and requested operation.

Output: an admission decision with stable reason codes, required preconditions, and an exact allowed effect set.

Invariant: every runnable operation declares atomic effects such as:

source.read       source.write       task_state.write
host.write        history.write      code.execute
credential.consume
network.read      remote.write       remote.destroy

The executable/provider owns effects; a skill references them rather than copying them. Unknown effects fail closed. Known read-only discovery may degrade visibly. Remote writes and destruction require exact resource, environment, candidate, pre-state, authority, and expiry bindings.

history.write is distinct from source.write: commits, local ref moves, tags, and rewrites alter history even when worktree bytes do not change. Operation scopes such as edit, commit, feature publication, review mutation, release-ref publication, deployment, and destruction map to additive atomic effects rather than substituting for them.

Review accountability, component ownership, task path/hunk or commit ownership, goal-storage ownership, remote-ref ownership, external-resource ownership, and user authority are separate relations. Unknown ownership fails closed for history rewrite, credential expansion, publication, remote mutation, and destruction.

Owners: canonical skills for routing and procedure; executable and runtime providers for actual capability contracts.

Input: intent, policy slice, available providers, effects, evidence maturity, and cost.

Output: the smallest sufficient capability set, ordering, exclusions, fallbacks, and an explanation of every choice.

Invariant: selection is advisory and never grants authority. Required dependencies are acyclic. Conflicts, unavailable providers, unsupported platforms, and unverified behavior are explicit. Full instructions and schemas load only after compact metadata selects them.

Owner: the current task coordinator and, for durable work, owner-local goal resources.

Input: intent, criteria, context slice, capability choices, prior evidence, and relevant defects.

Output: a WorkPacket or goal attempt plus CapabilityPlan and ActionPlan, with exact inputs, affected criteria, hypotheses where needed, checks, omissions, fallbacks, fixed regressions, budgets, stop conditions, and a strategy-reset condition.

Invariant: a plan does not authorize and does not prove. Delegated workers receive immutable bindings and disjoint output ownership; only the coordinator mutates canonical goal state. A repeated stable defect changes strategy rather than accumulating indistinguishable retries.

Owners: Bazel and bazel_agent, native repository tools, Cordis or another runtime provider, and explicit external adapters.

Input: admitted operation, exact subject and inputs, task/run identity, deadline, quotas, and cancellation contract.

Output: immutable ActionReceipt records plus bounded task-local raw-log pointers.

Invariant: executors remain thin and signal-transparent. Scratch is isolated by workspace, task, run, and worker; generated execution receives only declared filesystem, environment, process, network, and credential capabilities. Desired and observed state remain separate. A control kernel must stay responsive when optional data-plane extensions fail.

Owners: providers own observations; the task or goal acceptance policy owns semantic sufficiency.

Input: receipts, subject, validation profile, declared policy, known limitations, and—only for semantic judgment—a criterion revision.

Output: three distinct records:

  • EvidenceEvaluation derives applicable, stale, insufficient, unavailable, or unverifiable with stable reasons;
  • execution-owned, criterion-neutral ValidationSet aggregates exact candidate, plan/check identities, sanitized invocations, provider/configuration provenance, results, coverage, and limitations; and
  • goal/task-owned EvidenceAssertion applies evidence to an exact criterion and subject with satisfied, not_satisfied, or unknown.

Invariant: receipts prove what ran and what was observed; they do not prove that selected checks were semantically sufficient. One immutable validation set may support non-goal delivery and multiple criterion assertions. Partial, truncated, skipped, or unknown evidence cannot support complete coverage. Reuse requires matching relevant input, policy, contract, configuration, toolchain, and subject-class digests.

Owners: Git and the forge own remote facts; repository delivery owns feature publication and review operations; versioning and release keep their separate identities.

Input: exact candidate, authority, an applicable criterion-neutral ValidationSet, expected remote state, and operation-specific policy.

Output: delivery, synchronization, review, version, release, and deployment receipts linked by exact subject references.

Invariant: use the effectful protocol:

inspect -> prepare -> immutable candidate -> validate -> authorize
        -> execute -> verify -> receipt

Delivery validates candidate-bound evidence but does not select semantic checks. Feature publication does not imply tag or deployment authority. Version identity and release snapshot identity are joined by a typed handoff, not by assuming that any Git tag has the same meaning.

Owner: the component that will adopt the lesson through ordinary review and delivery.

Input: exact task evidence, review dispositions, stable defect identity, measured friction, and regression results.

Output: a LearningProposal, then—only after acceptance—an owner-local document, contract, check, evaluation, skill, or global invariant.

Invariant: learning is never automatic mutation. It is minimized, public, reviewed, regression-backed, measurable, reversible, and given a retirement path. Runtime promotion creates a normal candidate; it does not write project source or goal state directly.

The complete traversable chain is:

ContextCapsule
  -> GoalAttempt / WorkPacket
  -> CapabilityPlan / ActionPlan
  -> AuthorityBinding + AdmissionDecision
  -> ActionReceipt(s)
  -> EvidenceEvaluation + ValidationSet + EvidenceAssertion(s)
  -> accepted candidate
  -> Delivery / Review / ReleaseRef / ReleaseManifest / Deployment receipts
  -> GoalOutcome
  -> LearningProposal / LearningAdoption

The logical records serve distinct purposes:

  • ContextCapsule says what was known, applicable, authorized, available, stale, and omitted before planning.
  • WorkPacket says what outcome and criteria a bounded unit will pursue.
  • CapabilityPlan and ActionPlan say what was selected, omitted, ordered, budgeted, and expected to prove the result.
  • AuthorityBinding and AdmissionDecision say which exact effects, subject, environment, policy, pre-state, and expiry were checked before execution.
  • ActionReceipt says what provider executed or observed against which exact inputs and with what result and resource use.
  • ValidationSet records criterion-neutral check execution and coverage; EvidenceAssertion makes the separate criterion judgment.
  • Delivery, review, release-ref, manifest, and deployment receipts say which external transition occurred and which postcondition was observed.
  • GoalOutcome records durable acceptance or the honest terminal state.
  • LearningProposal requests owner review; LearningAdoption identifies the exact accepted change, regression, delivery, and measured effect.

Plans do not authorize. Receipts do not judge semantic sufficiency. Delivery receipts do not prove that validation selection was complete. Learning proposals do not edit policy.

Every edge binds the relevant subject and catalog-slice, policy, contract, and input digests.

The tower defines composition; this loop defines control over time:

Orient -> Bind -> Plan -> Admit -> Act -> Prove -> Decide
                                              |-> replan
                                              |-> deliver -> verify -> close
                                              |-> wait or escalate
                                              `-> stop
                                                     |
                                                   Learn

Orientation obtains the smallest context capable of exposing uncertainty. Binding freezes the intended outcome, exact subject, authority, criteria, and budgets. Planning names omissions, fallback, stop conditions, and the cheapest evidence capable of falsifying the current hypothesis. Admission checks the exact plan against current policy and pre-state. Decision either accepts, changes strategy, waits for named external state, escalates authority, or stops honestly.

A declared transient failure permits at most one same-input retry. A deterministic recurrence requires a changed hypothesis or strategy. A remote operation with unknown postcondition is observed and reconciled before any second write.

The target zero-context interface is one read-only, bounded projection. It may be a repository tool and optionally an MCP surface, but it cannot require MCP to function. It contains:

  • repository, workspace, worktree, revision, and dirty-input identity;
  • task/session, coordinator, worker, and run identity;
  • requested outcome, authority, budgets, and durable goal binding if any;
  • applicable instruction and owner-document paths with digests;
  • component, workspace, review owner, and classification slice;
  • candidate capabilities with effects, cost, dependencies, providers, and evidence maturity;
  • provider boot/incarnation ID, catalog ETag, desired/observed revisions, action-contract hashes, observation time, expiry, and unavailable reasons;
  • relevant checks and reusable evidence, not raw logs; and
  • provenance, observation time, freshness, completeness, truncation, and safe next discovery actions.

The capsule is a join over owner-local catalogs and observations. It stores no independent truth. A missing optional provider yields a structured unavailable field; it does not make the whole capsule fail.

An agent climbs this cost ladder only when existing evidence cannot answer the acceptance question:

  1. checked, cached metadata and narrow source reads;
  2. targeted static queries and reusable subject-bound receipts;
  3. narrow local builds and tests;
  4. broad or uncached validation;
  5. external reads and stochastic/model-assisted evaluation; and
  6. authorized remote mutation or destructive work.

Budgets inherit from repository defaults to task to plan to operation/worker. A child may narrow but never silently expand a hard bound. Reserve capacity for cancellation cleanup and final verification. Track context/input bytes, compute and target/workspace scope, elapsed time, output/log/artifact bytes, retention, retries, worker fan-out, concurrency, and cacheability. Use measured p50/p95 workloads to set numeric defaults.

Credentials, network access, history or remote writes, and destruction are non-fungible authority scopes, never spendable budget. Compatible Bazel work is batched. Context loads summaries and digests first, then full bodies, schemas, source, or logs only on demand. A global catalog change triggers cheap applicability reevaluation, not automatic reruns of unrelated evidence.

sanitized bounded friction event
  -> aggregation by stable signature and consequence
  -> LearningProposal with destination owner
  -> minimized regression or routing fixture
  -> destination-owner review
  -> one appropriate contract, policy, tool, test, or skill change
  -> normal validation and delivery
  -> LearningAdoption and regenerated evidence status
  -> recurrence and resource measurement

Raw transcripts, credentials, unreviewed runtime values, secret-bearing logs, personal information, and accidental local state never enter the promotion path. Ignored task-private out/<task>/ may temporarily contain secret-bearing material under restrictive access and cleanup, but that material is not tracked or imported as durable evidence. A global invariant is an exceptional owner-approved destination, not the automatic final rung of the sequence.

  • unknown means the system lacks a fact; it is not false, safe, or allowed.
  • unavailable names a provider or source that could not be observed.
  • stale means a once-valid observation no longer matches its applicability inputs.
  • partial and truncated bound what a result can prove.
  • Desired state and observed state are always separate fields.
  • Runtime observations identify boot/incarnation, catalog, desired and observed revisions, action contract, observation time, and expiry.
  • Provider lifecycle is explicit: loading, ready, degraded, failed, timed_out, draining, or disabled.
  • Shared mutable task, goal, and runtime state uses a cross-process lock or lease plus expected version/digest; atomic rename alone is not concurrency control.
  • Nested work uses one absolute deadline with cancellation and cleanup margin.
  • Failures carry phase, stable code/signature, subject, observed state, valid partial result, retry class, cost spent, redacted artifact references, and next safe action. Retry class is never, same-input-once, after-state-change, or requires-human.
  • Read-only discovery returns the useful safe subset with explicit gaps.
  • Effectful admission fails closed on unknown effects, authority, environment, subject, policy conflicts, or relevant stale state.
  • Secret-bearing raw output stays in task-private scratch and only a bounded allowlisted summary may cross into ordinary evidence.

Optimization is evaluated with representative zero-context tasks, not by file count or architectural novelty. Track at least:

  • task correctness and unsupported-claim rate;
  • unauthorized or incorrectly scoped mutation rate;
  • reads, tool calls, context bytes or tokens, and elapsed/resource cost before the first correct action;
  • redundant checks and exact evidence reuse rate;
  • steps and missing facts required to resume durable work;
  • stale, partial, and conflict detection accuracy;
  • provider startup and degraded-status latency; and
  • the rate at which repeated defects gain a regression, owner, delivery identity, and eventual retirement.
  • No hand-maintained central manifest duplicating owner-local facts.
  • No universal mega-skill or always-loaded copy of every procedure.
  • No mandatory daemon, database, vector store, or runtime extension for basic orientation and safe degradation.
  • No raw transcript ingestion, secret promotion, or automatic doctrine edits.
  • No inference of authority from selection, planning, receipts, ownership, or tool availability.
  • No durable goal requirement for a simple one-step task.
  • No broad //... validation or live model evaluation by default.
  • No physical repository reorganization merely to make the conceptual model look centralized.

1.1.4 - Repository agent-system roadmap

Remaining work ordered by observed task friction and evidence

Repository agent-system roadmap

This document records intentional future work. The current-state guide owns the supported interface summary; component documentation and executable tests establish implementation details. The architecture describes composition responsibilities. Historical phase plans and acceptance records remain in the immutable goals. A completed historical phase does not establish a current runtime guarantee.

Use representative question, edit, recovery, and delivery scenarios to compare the current workflow with a candidate. Keep source, instructions, fixture, model, observation method, and execution identity with each result. Measure task success, unauthorized actions, commands, context actually consumed, duration, and resume steps where the observer can establish them. Record unavailable measurements explicitly. Configuration validation and shorter documents do not establish behavioral improvement.

Local simulated delivery scenarios can exercise candidate selection and validation decisions without publishing anything. They do not prove forge integration, remote concurrency, or successful real publication. Use the owning delivery integration tests for their encoded cases, and distinguish those tests from model behavior.

Reduce repeated common-path instructions and load exceptional procedures only when their triggering condition occurs. Keep exact candidate, task ownership, authority, leases, recovery, and review completion requirements. Improve entrypoint capability detection and workspace-relative path handling before introducing another execution interface.

Acceptance requires measured task outcomes with no new critical boundary failures. A small exploratory comparison is useful evidence, not a universal performance claim. Retain useful diagnostics and regressions after clean runs; remove obsolete workarounds and completed tracking when their purpose expires.

Extend bounded offline context only with facts that have an identifiable owner and observation method. Prefer observed Git state and direct routes to applicable policy, owner documentation, build declarations, and explicit goal records. Never infer authorization or task-to-goal association from proximity, ownership, a catalog entry, or an available tool.

Check suggestions must explain their selection basis and uncovered scope. Nearest-package selection is not dependency analysis. Root configuration, build-graph changes, ignored paths, and nested workspaces can require explicit checks beyond the returned labels. Avoid accidental broad builds while keeping the mandatory repository quality and affected semantic checks.

Delivery preparation binds the candidate and publication expectations. The caller selects applicable validation. The delivery tool can execute that plan, record candidate-bound results, and carry them into explicitly requested publication. The manual publication path also remains supported. Neither a preparation receipt nor an asserted commit ID proves that tests ran. Broader evidence imports must specify their trust boundary and preserve caller responsibility for semantic sufficiency.

Reuse observations only while their relevant inputs remain unchanged. Reuse test evidence across a message-only amendment only when tree, configuration, toolchain, environment, and every other relevant input are stable. Rerun commit-sensitive or uncertain checks. A receipt alone never establishes reuse.

Acceptance requires representative edits to select sufficient checks, explain omissions, and invalidate evidence when a relevant input changes. Preserve cheap read-only discovery when optional providers are unavailable.

The configured coverage inventory is not a successful-run ledger. Extend routing scenarios across positive, adjacent-negative, inert-payload, exclusion, conflict, and composition cases when the corresponding skill is changed or a recurring failure demonstrates a gap.

Stronger aggregated evidence needs actual execution artifacts bound to the source, fixture, model or provider, and judge where applicable. Keep live stochastic evaluations manual or scheduled and separate from normal wildcard tests. Use isolated writable fixtures for Git, Bazel, forge, infrastructure, secret-handling, and runtime trajectories before making claims about them. Never reuse shared authentication in a mode that requires exclusive access while concurrent sessions are active.

Promote a repeated lesson only with an owner, minimized public reproducer, regression, supported contract, fallback, measured cost, delivered revision, and a reasoned retirement rule. A schema or proposal does not establish that this learning loop runs automatically.

Shared admission and control libraries have unit-test coverage. Production provider enforcement, process isolation, and runtime fault containment remain unverified. Build further runtime machinery only for an identified consumer whose required behavior and failure modes justify it.

For that consumer, test bounded status during a stuck extension, package deadlines, desired versus observed revision, cancellation and cleanup, cross-task storage isolation, and the actual filesystem, process, network, credential, and output boundaries. Trusted in-process code is not a security sandbox. A source contract cannot substitute for consumer integration evidence.

Keep bounded native and offline fallbacks available. A missing optional provider must produce an explicit unavailable result rather than preventing ordinary repository work.

  • Facts remain at their owning sources; generated views carry provenance and limits rather than becoming new mutation authorities.
  • Keep goals, delivery, release, review, and provider state separate. Add joins through typed references only when a real workflow needs them.
  • Do not add a mandatory daemon, database, vector store, network call, or central orchestrator for basic orientation.
  • Do not relocate components merely to match conceptual diagrams.
  • Keep reviewed evidence bounded and free of credentials and personal data.
  • Use workspace goals for temporary coordination and owner-local maintained records only when durable project history is justified.
  • Choose the least costly check that answers acceptance; broad audits remain separately scoped work.

1.2 - Al

Repository command runner and Bazel configuration rules

AL is a command runner that prepares credentials and environment variables through plugins, runs your command, and cleans up afterward. Its Bazel rules package commands with their configuration and required plugins.

1.2.1 - Command and plugin lifecycle

Startup, shutdown, and secret cleanup guarantees

al run starts selected plugins, passes their environment to a command, and keeps plugin resources available until that command exits. On cancellation it asks the command to terminate and waits up to ten seconds before killing it. Plugin shutdown then drains requests, releases resources in reverse registration order, and waits for plugin exit. Startup failure cancels sibling starts and rolls back partially initialized resources. Cleanup errors fail the invocation.

The injector creates secret files with owner-only permissions and removes them after consumers stop. Vault stores revoke AppRole tokens they issue; failed AppRole login attempts destroy their unused single-use SecretID. The role’s bootstrap policy must permit secret-id-accessor/destroy, as declared by projects/tf_modules/vault_approle. The user’s existing token-helper credential is never erased or revoked. Secret inputs and remote response bodies are omitted from diagnostic messages. OIDC authorization uses the configured Vault HTTPS origin and TLS transport, rejecting alternate origins and redirects. Explicit config dumps still contain the requested configuration; file outputs use owner-only permissions and truncate previous contents.

no_auth prevents AL’s Vault client from loading credentials. For environment injection it clears inherited VAULT_TOKEN; it does not sandbox the command or prevent a command from independently reading the user’s token helper. Plugins and invoked commands remain trusted programs with the user’s filesystem access.

Cleanup is observable best effort, not secure erasure. Memory copies are not zeroized. Forced termination, host failure, unresponsive cleanup code, or an unavailable service can prevent deletion or revocation. Subprocess signaling targets direct children, not arbitrary descendants. Credential expiry remains a fallback; service-specific logout requirements are documented with each plugin.

1.2.2 - Releases

Releases

1.2.2.1 - head

Release head

1.2.3 - Rules

Bazel rules

1.2.3.1 - Bzl

Bazel rules

1.2.3.1.1 - al_config

al_config

load("@com_alwaldend_src//projects/al/rules/al:al_config.bzl", "al_config")

al_config(name, deps, srcs, data)

Dump al config

ATTRIBUTES

Name Description Type Mandatory Default
name A unique name for this target. Name required
deps Al configs (targets) List of labels optional []
srcs Al configs (source files) List of labels optional []
data Data List of labels optional []

load("@com_alwaldend_src//projects/al/rules/al:al_config.bzl", "AlConfigInfo")

AlConfigInfo(config)

Config info

FIELDS

Name Description
config Merged config file

1.2.3.1.2 - al_toolchain

al_toolchain

load("@com_alwaldend_src//projects/al/rules/al:al_toolchain.bzl", "al_toolchain")

al_toolchain(name, al)

Al toolchain

ATTRIBUTES

Name Description Type Mandatory Default
name A unique name for this target. Name required
al Al binary Label required

1.2.3.1.3 - al_toolchain_resolved

al_toolchain_resolved

load("@com_alwaldend_src//projects/al/rules/al:al_toolchain_resolved.bzl", "al_toolchain_resolved")

al_toolchain_resolved(name)

Resolved al toolchain (for genrules)

ATTRIBUTES

Name Description Type Mandatory Default
name A unique name for this target. Name required

1.3 - Alwaldend.com

Main website and project documentation

Alwaldend.com is the repository’s main website and documentation site. It uses Hugo with Docsy to publish project documentation on GitHub Pages.

Run from the repository root:

bazel_agent bazel build //projects/alwaldend.com:site
bazel_agent bazel test //projects/alwaldend.com:site_test \
  //projects/alwaldend.com/test/site:site_test
bazel_agent bazel run //projects/alwaldend.com:site_serve

The preview serves the local build at http://127.0.0.1:1313. The generated-site test checks internal links, image paths, fragment targets, duplicate IDs, and selected page markup. It does not check external destination availability.

Markdown links and images resolve relative to their source directory. README.md and _index.md links resolve to generated pages; packaged resources use their published URLs, including when embedded in print pages. Link files that exist only in the repository with explicit GitHub URLs. Unknown internal destinations remain unchanged and are reported by the generated-site test; they are not silently redirected to GitHub.

Print pages scope IDs and their fragment and control references to each source document, keeping anchors distinct when documents are combined.

  • DNS setup: infra/dns
  • This project’s DNS declaration owns the shared pages address. Each other project owns its landing CNAME pointing directly to alwaldend.github.io.. Hostnames use hyphens while docs paths keep underscores. The project directory links to all sites. The apex and www records stay managed centrally.
  • Deploy to the Github Pages repo (the pages branch of alwaldend/alwaldend.github.io, which GitHub Pages serves):
    tools/versioning/cmd/versioning/versioning.sh bazel -- \
      run --config=release //projects/alwaldend.com:deploy
    
    The deploy script clones the pages branch, replaces its contents with the built site, writes .nojekyll, and pushes only when the output changed.
bazel run //projects/alwaldend.com/tf # Apply tf
bazel run //projects/alwaldend.com/tf:update_pve_disk # Update the disk
Taxonomy Meaning
Categories General category
Languages Programming language
Sites Sites
Statuses Project status
Tags Generic tags
{{< alwaldend/alert >}}
Alert body
{{< /alwaldend/alert >}}

Create a link using a bazel label

Usage:

{{% alwaldend/label_link "//tools/qt" %}}

Render common links

Usage:

{{% alwaldend/links %}}

Render a packaged SVG using its published URL. Set alt to describe the image; the page title is the fallback.

Usage:

{{< alwaldend/svg_file file="local_file.svg" alt="Project architecture" >}}

Include a local html file

Usage:

{{< alwaldend/include_html "file.html" >}}

Render books

Usage:

{{< alwaldend/docs_misc_books >}}

1.3.1 - Releases

Releases

1.3.1.1 - head

Release head

1.3.2 - Tf

Terraform

1.4 - Android launcher

Text-only Android launcher built with Kotlin and Jetpack Compose

A text-only Android launcher built with Kotlin and Jetpack Compose. It lets you hide apps and runs without ads, tracking, or internet access.

  • Android app
  • Kotlin, Jetpack Compose
  • Only text
  • FOSS, no ads, no internet access, no tracking, minimal dependencies
  • Allows you to hide apps

1.4.1 - Releases

Releases

1.4.1.1 - head

Release head

1.5 - Ansible collection

Ansible collection alwaldend.main with Bazel source packaging

alwaldend.main is the repository’s Ansible collection. Bazel packages its Ansible source for reuse in repository automation.

  • Ansible collection
  • Bazel-managed Ansible source packaging.
namespace: alwaldend
name: main
version: 0.0.0
readme: README.md
authors:
-  <example@domain.com>
description: main alwaldend ansible collection
license:
  - AGPL-3.0-or-later
license_file: LICENSE.txt
tags: []
dependencies:
  ansible.posix: 1.5.4
  community.crypto: 2.17.0
  community.general: 11.3.0
  devsec.hardening: 9.0.1
  community.docker: 3.11.0
repository: https://git.alwaldend.com/src
documentation: https://collection-main.docs.alwaldend.com
homepage: https://collection-main.docs.alwaldend.com
issues: ""
build_ignore: []

1.5.1 - Playbooks

Ansible playbooks

1.5.2 - Roles

Ansible roles

1.5.2.1 - Adguard

Role to deploy adguard

1.5.2.1.1 - Defaults

Defaults for adguard
adguard_dir: /etc/adguard
adguard_work_dir: "{{ adguard_dir }}"
adguard_gpg_key_url: https://keys.openpgp.org/vks/v1/by-fingerprint/28645AC9776EC4C00BCE2AFC0FE641E7235E2EC6
adguard_gpg_key_src: files/key.asc
adguard_gpg_key_path: "{{ adguard_dir }}/release-key.asc"
adguard_gpg_key_checksum: "22d78dbacb461667861ee7d2dd13d13240ee003d"
adguard_release_source_url: https://github.com/AdguardTeam/AdGuardHome/releases/download
adguard_release_version: v0.107.48
adguard_release_checksum: "sha512:c0a336212e3792ae6fc6b8de976befce0038c5d6ddde919a00994c43a929349958c7bd65f7fb7fdd471962afa20855ecbf5830cc7a1d26f3037a716db638c101"
adguard_release_distrib: AdGuardHome_linux_amd64.tar.gz
adguard_release_url: "{{ adguard_release_source_url }}/{{ adguard_release_version }}/{{ adguard_release_distrib }}"
adguard_release_archive_dest: "{{ adguard_dir }}/release-{{ adguard_release_version }}-{{ adguard_release_distrib }}" 
adguard_release_dest: "{{ adguard_dir }}/release-{{ adguard_release_version }}" 
adguard_release_dir: "{{ adguard_release_dest }}/AdGuardHome"
adguard_release_bin: "{{ adguard_release_dir }}/AdGuardHome"
adguard_release_sig: "{{ adguard_release_bin }}.sig"

1.5.2.2 - Caddy

Role to deploy caddy

1.5.2.2.1 - Defaults

Defaults for caddy
caddy_enabled: false
caddy_user: caddy
caddy_config_path: /etc/caddy/Caddyfile
caddy_config_dir: /etc/caddy/configs
caddy_config: |
  import {{ caddy_config_dir }}/*

1.5.2.3 - CIFS

Setup cifs

1.5.2.3.1 - Defaults

Defaults for cifs
cifs_enabled: false
cifs_systemd_dir: /etc/systemd/system
cifs_mounts: []

1.5.2.4 - Consul

Consul

1.5.2.4.1 - Defaults

Defaults for consul
consul_user: consul
consul_user_uid: 4266
consul_dir: "/opt/consul"
consul_data_dir: "{{ consul_dir }}/data"
consul_config_dir: "{{ consul_dir }}/configs"
consul_config_path: "{{ consul_config_dir }}/consul.hcl"
consul_config_local_path: "files/consul.hcl"
consul_log_dir: "{{ consul_dir }}/logs"
consul_tls_dir: "{{ consul_dir }}/tls"
consul_service_path: "/lib/systemd/system/consul.service"
consul_tls_ca_file_local_path: files/pki_ca_servers.crt
consul_tls_ca_file_path: "{{ consul_tls_dir }}/tls_ca_file.crt"
consul_tls_cert_file_path: "{{ consul_tls_dir }}/cert_file.crt"
consul_tls_key_file_path: "{{ consul_tls_dir }}/key_file.crt"
consul_tls_common_name: "{{ inventory_hostname }}"
consul_tls_ttl: "2629746" # month
consul_tls_alt_names: ""
consul_vault_local_path: "{{ role_path }}/files/vault"
consul_bin_local_path: "{{ role_path }}/files/consul"
consul_bin_path: /usr/bin/consul

1.5.2.5 - Consul

Setup consul

1.5.2.5.1 - Defaults

Defaults for consul_old
consul_is_server: false
consul_user_name: consul
consul_user_uid:
consul_dir: "/opt/consul"
consul_persistence_dir: "{{ consul_dir }}"
consul_releases_dir: "{{ consul_dir }}/releases"
consul_config_symlink_dir: "{{ consul_configs_dir }}/current"
consul_config_symlink_data_dir: "{{ consul_config_symlink_dir }}/configs"
consul_configs_dir: "{{ consul_persistence_dir }}/configs/{{ inventory_hostname }}"
consul_data_dir: "{{ consul_persistence_dir }}/data/{{ inventory_hostname }}"
consul_config_path: "{{ consul_config_config_dir }}/consul.json"
consul_config_dir: "{{ consul_configs_dir }}/{{ consul_config_dir_name }}" 
consul_config_data_dir: "{{ consul_config_dir }}/data"
consul_config_config_dir: "{{ consul_config_dir }}/configs"
consul_config_dir_name: "{{ consul_config_version }}"
consul_config_version: "{{ lookup('ansible.builtin.pipe', 'git rev-parse HEAD') }}"
consul_env: {}
consul_configs: []
consul_env_path: "{{ consul_config_data_dir }}/consul.env"
consul_env_symlink_path: "{{ consul_config_symlink_dir }}/data/consul.env"
consul_release_dir: "{{ consul_releases_dir }}/{{ consul_release_dir_name }}"
consul_release_dir_name: "{{ consul_release_version }}"
consul_release_symlink_path: "{{ consul_releases_dir }}/current"
consul_release_symlink_bin_path: "{{ consul_release_symlink_path }}/consul"
consul_release_version: 1.20.2
consul_release_archive_name: "consul_{{ consul_release_version }}_linux_amd64"
consul_release_archive_fullname: "{{ consul_release_archive_name }}.zip"
consul_release_bin_path: "{{ consul_release_dir }}/consul"
consul_release_url: "https://releases.hashicorp.com/consul/{{ consul_release_version }}/{{ consul_release_archive_fullname }}"
consul_release_checksum: "sha256:1bf7ddf332f02e6e36082b0fdf6c3e8ce12a391e7ec7dafd3237bb12766a7fd5"
consul_agent_ca_cert_path: "{{ consul_config_data_dir }}/agent_ca_cert.pub"
consul_agent_ca_cert:
consul_server_cert_path: "{{ consul_config_data_dir }}/server_cert_{{ inventory_hostname }}.pub"
consul_server_cert:
consul_server_key_path: "{{ consul_config_data_dir }}/server_cert_{{ inventory_hostname }}.key"
consul_server_key:

1.5.2.6 - Consul envoy

Setup envoy for consul

1.5.2.6.1 - Defaults

Defaults for consul_envoy
consul_envoy_dir: "/opt/consul_envoy"
consul_envoy_deployments_dir: "{{ consul_envoy_dir }}/deployments"
consul_envoy_releases_dir: "{{ consul_envoy_dir }}/releases"
consul_envoy_deployment_dir: "{{ consul_envoy_deployments_dir }}/{{ consul_envoy_deployment_version }}"
consul_envoy_release_dir: "{{ consul_envoy_releases_dir }}/{{ consul_envoy_release_version }}"
consul_envoy_configs_dir: "{{ consul_envoy_deployment_dir }}/configs"
consul_envoy_bootstrap_config_path: "{{ consul_envoy_configs_dir }}/bootstrap.json"
consul_envoy_deployment_version: "{{ lookup('ansible.builtin.pipe', 'git rev-parse HEAD') }}"
consul_envoy_user_name: consul_envoy
consul_envoy_release_version: 1.31.0
consul_envoy_release_archive_fullname: "envoy_{{ consul_envoy_release_version }}_linux_amd64.zip"
consul_envoy_release_url: "https://releases.hashicorp.com/envoy/{{ consul_envoy_release_version }}/{{ consul_envoy_release_archive_fullname }}"
consul_envoy_release_bin_path: "{{ consul_envoy_release_dir }}/envoy"
consul_envoy_release_symlink_path: "{{ consul_envoy_releases_dir }}/current"
consul_envoy_release_checksum: "sha256:350782275de0fe50699844b4f9096d77a0193a5bcf205e14b8ad964ec429d45e"

1.5.2.7 - Dev VM

Set up repositories and packages for a development VM

The default task entry point configures package repositories and development packages. It uses the same dev_vm_packages list with either the ordinary package manager or RPM-OSTree layering. dev_vm_package_backend accepts auto, package, or rpm_ostree; auto selects RPM-OSTree when /run/ostree-booted exists. Set dev_vm_install_packages to false to skip repository and package management entirely.

RPM-OSTree changes are staged for the next boot by default. The role reports a pending deployment but does not reboot the host. Set dev_vm_rpm_ostree_apply_live to true only when live application is known to be safe for the selected packages.

The packaged Fedora mirror and Bazelisk tool currently make this role specific to Linux x86-64 development hosts.

The packages task entry point exposes package management separately from other role tasks. The bazel task entry point installs a caller-provided Bazel rc, Bazelisk, and the repository’s bazel_agent runner for one developer account.

Import the Bazel entry point with tasks_from: bazel and set:

  • dev_vm_bazel_user: owner of the installed files.
  • dev_vm_bazel_group: group of the installed files; defaults to the user.
  • dev_vm_bazel_home: absolute home directory for the developer account.
  • dev_vm_bazelrc_src: controller-side Bazel rc source; defaults to bazelrc.
  • dev_vm_bazelisk_src: controller-side Bazelisk source; defaults to bazelisk.
  • dev_vm_bazel_agent_src: controller-side bazel_agent source; defaults to bazel_agent.

The role packages its default Linux x86-64 Bazelisk and bazel_agent sources. The calling playbook must package the Bazel rc, plus any overridden binary sources, in an Ansible file search path. Cache storage and machine-specific Bazel settings remain the caller’s responsibility.

1.5.2.7.1 - Defaults

Defaults for dev_vm
---
dev_vm_install_packages: true
dev_vm_package_backend: auto
dev_vm_rpm_ostree_apply_live: false
dev_vm_packages:
  - clang
  - clang-tools-extra
  - java-latest-openjdk-devel
  - rust
  - cargo
  - mesa-libGL-devel
  - go
  - Xvfb
  - python3
  - gmp-devel
  - patch
  - podman
  - git
  - git-lfs
  - fuse
  - fuse-libs
  - pcsc-lite
  - pcsc-lite-devel
  - openssl
  - gnutls-utils
  - opensc
  - openssl-pkcs11
  - libdnet
  - qemu-kvm
  - qemu-img
dev_vm_bazel_user: "{{ undefined() }}"
dev_vm_bazel_group: "{{ dev_vm_bazel_user }}"
dev_vm_bazel_home: "{{ undefined() }}"
dev_vm_bazelrc_src: bazelrc
dev_vm_bazelisk_src: bazelisk
dev_vm_bazel_agent_src: bazel_agent

1.5.2.8 - DNS

Setup dns records

1.5.2.8.1 - Defaults

Defaults for dns
dns_records: []
dns_domains: []
dns_njalla_api_url: https://njal.la/api/1/
dns_njalla_token:

1.5.2.9 - Docker

Setup docker

1.5.2.9.1 - Defaults

Defaults for docker
docker_enabled: false

1.5.2.10 - Facts

Setup ansible facts

1.5.2.10.1 - Defaults

Defaults for facts
facts_debug: false

1.5.2.11 - Filesystem

Setup filesystems

1.5.2.11.1 - Defaults

Defaults for filesystem
filesystem_setup: []

1.5.2.12 - Firewall

Setup firewall

1.5.2.12.1 - Defaults

Defaults for firewall
firewall_state: enabled
firewall_enabled: true
firewall_allow_port_from: []
firewall_allow_forward: []

1.5.2.13 - Forgejo

Forgejo

1.5.2.13.1 - Defaults

Defaults for forgejo
forgejo_user: forgejo
forgejo_user_uid: 5157
forgejo_dir: "/opt/forgejo"
forgejo_data_dir: "{{ forgejo_dir }}/data"
forgejo_config_dir: "{{ forgejo_dir }}/configs"
forgejo_work_dir: "{{ forgejo_dir }}/work"
forgejo_config_path: "{{ forgejo_config_dir }}/forgejo.ini"
forgejo_config_local_path: "files/forgejo.ini"
forgejo_disk:
forgejo_log_dir: "{{ forgejo_dir }}/logs"
forgejo_service_path: "/lib/systemd/system/forgejo.service"
forgejo_vault_local_path: "{{ role_path }}/files/vault"
forgejo_bin_local_path: "{{ role_path }}/files/forgejo"
forgejo_bin_path: /usr/bin/forgejo

1.5.2.14 - Forgejo

Forgejo

1.5.2.14.1 - Defaults

Defaults for threexui
threexui_user: threexui
threexui_user_uid: 6468
threexui_dir: "/opt/threexui"
threexui_data_dir: "{{ threexui_dir }}/data"
threexui_work_dir: "{{ threexui_dir }}/work"
threexui_disk:
threexui_log_dir: "{{ threexui_dir }}/logs"
threexui_service_path: "/lib/systemd/system/threexui.service"
threexui_vault_local_path: "{{ role_path }}/files/vault"
threexui_bin_dir: "{{ threexui_dir }}/bin"
threexui_bin_local_dir: "{{ role_path }}/files/threexui_bin"
threexui_config_dir: "{{ threexui_dir }}/configs"
threexui_env_path: "{{ threexui_config_dir }}/threexui.env"
threexui_env_override: {}
threexui_base_path: /
threexui_username: "{{ undefined() }}"
threexui_password: "{{ undefined() }}"
threexui_port: "2053"
threexui_debug: "false"
threexui_env:
  # https://docs.sanaei.dev/docs/reference/env-vars/
  XUI_DB_TYPE: sqlite
  XUI_DB_FOLDER: "{{ threexui_data_dir }}"
  XUI_PORT: "{{ threexui_port }}"
  XUI_INIT_WEB_BASE_PATH: "{{ threexui_base_path }}"
  XUI_ENABLE_FAIL2BAN: "true"
  XUI_SKIP_HSTS: "true"
  XUI_LOG_LEVEL: info
  XUI_DEBUG: "{{ threexui_debug }}"
  XUI_LOG_FOLDER: "{{ threexui_log_dir }}"
  XUI_BIN_FOLDER: "{{ threexui_bin_dir }}/bin"
  XRAY_VMESS_AEAD_FORCED: "false"
  XUI_ACCESS_URL: "https://{{ inventory_hostname }}{{ threexui_base_path }}"
  XUI_USERNAME: "{{ threexui_username }}"
  XUI_PASSWORD: "{{ threexui_password }}"

1.5.2.15 - Forgejo runner

Install and register a Forgejo Actions runner

1.5.2.15.1 - Defaults

Defaults for forgejo_runner
forgejo_runner_user: forgejo-runner
forgejo_runner_user_uid: 5721
forgejo_runner_dir: /opt/forgejo-runner
forgejo_runner_disk:
forgejo_runner_home_dir: /opt/forgejo-runner/home
forgejo_runner_work_dir: /opt/forgejo-runner/work
forgejo_runner_bin_local_path: "{{ role_path }}/files/forgejo-runner"
forgejo_runner_bin_path: /usr/bin/forgejo-runner
forgejo_runner_service_path: /lib/systemd/system/forgejo-runner.service
forgejo_runner_instance: "{{ undefined() }}"
forgejo_runner_token: "{{ undefined() }}"
forgejo_runner_name: "{{ inventory_hostname }}"
forgejo_runner_labels:
  - "self-hosted:host"

1.5.2.16 - Gpg

Setup GPG

1.5.2.16.1 - Defaults

Defaults for gpg
gpg_users: []

1.5.2.17 - Harboer

Harbor

1.5.2.17.1 - Defaults

Defaults for harbor
harbor_user: harbor
harbor_user_uid: 7049
harbor_dir: "/opt/harbor"
harbor_installer_dir: "{{ harbor_dir }}/installer"
harbor_logs_dir: "{{ harbor_dir }}/logs"
harbor_data_dir: "{{ harbor_dir }}/data"
harbor_installer_local_dir: "{{ role_path }}/files/harbor_installer"
harbor_config_path: "{{ harbor_installer_dir }}/harbor.yml"
harbor_config_local_path: "files/harbor.yaml"
harbor_domain: "{{ undefined() }}"
harbor_ca_local_path: "{{ role_path }}/files/pki_ca_servers.crt"
harbor_ca_path: /etc/docker/certs.d/{{ harbor_domain }}/ca.crt
harbor_root_ca_local_path: "{{ role_path }}/files/pki_ca_root.crt"

1.5.2.18 - Hermes

Install and run the Hermes Agent gateway

1.5.2.18.1 - Defaults

Defaults for hermes
hermes_user: hermes
hermes_user_uid: 8150
hermes_dir: /opt/hermes
hermes_home_dir: "{{ hermes_dir }}/home"
hermes_install_dir: "{{ hermes_dir }}/hermes-agent"
hermes_disk:
hermes_port: 8642
hermes_commit: "{{ undefined() }}"
hermes_installer_local_path: "{{ role_path }}/files/install.sh"
hermes_installer_path: "{{ hermes_dir }}/install.sh"
hermes_config_local_path: "files/hermes.yaml"
hermes_config_path: "{{ hermes_home_dir }}/.hermes/config.yaml"
hermes_env_path: "{{ hermes_home_dir }}/.hermes/.env"
hermes_env: {}
hermes_bin_path: "{{ hermes_home_dir }}/.local/bin/hermes"
hermes_dashboard_service_path: /lib/systemd/system/hermes-dashboard.service

1.5.2.19 - Hiddify manager

Setup hiddify manager

1.5.2.19.1 - Defaults

Defaults for hiddify_manager
hiddify_manager_env:
  HIDDIFY_MANAGER_IMAGE: ghcr.io/hiddify/hiddify-manager:main@sha256:d5edef06d2133ffa26f0fcbb67e711f4356dba44c44a41a96570c4e03845a84c
  HIDDIFY_MANAGER_REDIS_IMAGE: redis:7.4.1@sha256:bb142a9c18ac18a16713c1491d779697b4e107c22a97266616099d288237ef47
  HIDDIFY_MANAGER_MARIADB_IMAGE: mariadb:11.6.2@sha256:a9547599cd87d7242435aea6fda22a9d83e2c06d16c658ef70d2868b3d3f6a80
  HIDDIFY_MANAGER_REDIS_PASSWORD: "{{ lookup('ansible.builtin.env', 'HIDDIFY_MANAGER_REDIS_PASSWORD', default=undef()) }}"
  HIDDIFY_MANAGER_MYSQL_PASSWORD: "{{ lookup('ansible.builtin.env', 'HIDDIFY_MANAGER_MYSQL_PASSWORD', default=undef()) }}"
  HIDDIFY_MANAGER_MARIADB_PASSWORD: "{{ lookup('ansible.builtin.env', 'HIDDIFY_MANAGER_MARIADB_PASSWORD', default=undef()) }}"
hiddify_manager_env_override: {}
hiddify_manager_dir: /opt/hiddify_manager

1.5.2.20 - Hiddify manager with host

Setup host and then hiddify manager

1.5.2.20.1 - Defaults

Defaults for hiddify_manager_host

1.5.2.21 - Host

Common host setup

1.5.2.21.1 - Defaults

Defaults for host

1.5.2.22 - Install CA

Install a certificate authority

1.5.2.22.1 - Defaults

Defaults for install_ca
install_ca:
  - path: "{{ role_path }}/files/pki_ca_root.crt"
  - path: "{{ role_path }}/files/pki_ca_servers.crt"

1.5.2.23 - K3s

Setup k3s

1.5.2.23.1 - Defaults

Defaults for k3s
k3s_data_dir: /srv/k3s_data
k3s_service_name: k3s
k3s_data_disk: /dev/sdb
k3s_storage_dir: /srv/k3s_storage
k3s_storage_disk: /dev/sdc
k3s_config_path: "/etc/rancher/k3s/config.yaml"
k3s_config_local_path: "files/k3s.yaml"
k3s_admission_config_path: "/etc/rancher/k3s/admission.yaml"
k3s_admission_config_local_path: "files/k3s_admission.yaml"
k3s_auth_config_path: "{{ [(k3s_config_path | dirname), 'k3s_auth.yaml'] | path_join }}"
k3s_auth_config_local_path: "files/k3s_auth.yaml"
k3s_manifests_local_path: "files/k3s_manifests.yaml"
k3s_manifests_path: "{{ k3s_data_dir }}/server/manifests/k3s-manifests.yaml"
k3s_bin_local_path: "{{ role_path }}/files/k3s"
k3s_bin_path: /usr/local/bin/k3s
k3s_install_script_local_path: "{{ role_path }}/files/k3s_install"
k3s_install_script_path: /usr/local/bin/k3s_install

1.5.2.24 - K3s bootstrap

Bootstrap k3s cluster

1.5.2.24.1 - Defaults

Defaults for k3s_bootstrap
k3s_bootstrap_apply_path:
k3s_bootstrap_token_name: "{{ lookup('ansible.builtin.env', 'USER', default=undef()) }}"
k3s_bootstrap_token_namespace: kube-system
k3s_bootstrap_venv_dir: "/opt/bootstrap-venv"
k3s_bootstrap_venv_bin: "{{ k3s_bootstrap_venv_dir | mandatory }}/bin/python"
k3s_bootstrap_kubeconfig: /etc/rancher/k3s/k3s.yaml
k3s_bootstrap_cluster_name: "{{ inventory_hostname }}"
k3s_bootstrap_cluster_ca_path: "{{ lookup('ansible.builtin.env', 'HOME', default=undef()) }}/.kube/ca-{{ k3s_bootstrap_cluster_name | mandatory }}.ca.crt"
k3s_bootstrap_user_ca_path: "{{ k3s_bootstrap_cluster_ca_path | mandatory | dirname }}/ca-{{ k3s_bootstrap_cluster_name | mandatory }}-{{ k3s_bootstrap_token_name | mandatory }}.ca.crt"
k3s_bootstrap_user_name: "{{ k3s_bootstrap_cluster_name | mandatory }}-{{ k3s_bootstrap_token_name | mandatory }}"
k3s_bootstrap_cluster_port:

1.5.2.25 - K3s cluster

Setup k3s cluster

1.5.2.25.1 - Defaults

Defaults for k3s_cluster

1.5.2.26 - K3s kubeconfig

Write k3s kubeconfig to a secret

1.5.2.26.1 - Defaults

Defaults for k3s_kubeconfig
k3s_kubeconfig_secret_path: "{{ undefined() }}"
k3s_kubeconfig_secret_mount: "{{ undefined() }}"
k3s_kubeconfig_path: /etc/rancher/k3s/k3s.yaml
k3s_kubeconfig_vault_bin_local_path: "{{ role_path }}/files/vault"

1.5.2.27 - lvg

Setup LVM volume groups

lvg_volume_groups describes the complete desired physical-volume list for each volume group. Extra physical volumes are not removed unless a caller sets remove_extra_pvs: true.

Creating a volume group initializes every listed device as an LVM physical volume. Callers must resolve stable device paths and verify that each device is the intended, unused disk before applying this role; pvcreate may overwrite an existing disk signature.

1.5.2.27.1 - Defaults

Defaults for lvg
lvg_volume_groups: []

1.5.2.28 - lvol

Setup LVM logical volumes

Each lvol_volumes entry can constrain allocation with pvs, pass creation arguments with opts, and disable shrinking with shrink: false.

1.5.2.28.1 - Defaults

Defaults for lvol
lvol_volumes: []

1.5.2.29 - Mount

Setup posix mounts

Mount entries can set opts, dump, and passno; state: mounted keeps the mount active and writes its persistent /etc/fstab entry.

1.5.2.29.1 - Defaults

Defaults for mount
mount_points: []

1.5.2.30 - Opencode

Opencode

1.5.2.30.1 - Defaults

Defaults for opencode
opencode_user: opencode
opencode_user_uid: 8149
opencode_dir: "/opt/opencode"
opencode_port: 4096
opencode_domain: "{{ undefined() }}"
opencode_log_dir: "{{ opencode_dir }}/logs"
opencode_work_dir: "{{ opencode_dir }}/work"
opencode_home_dir: "{{ opencode_dir }}/home"
opencode_config_dir: "{{ opencode_home_dir }}/.config/opencode"
opencode_config_path: "{{ opencode_config_dir }}/opencode.json"
opencode_config_local_path: "files/opencode.json"
opencode_disk:
opencode_service_path: "/lib/systemd/system/opencode.service"
opencode_bin_local_path: "{{ role_path }}/files/opencode"
opencode_bin_path: /usr/bin/opencode
opencode_env_path: "{{ opencode_config_dir }}/opencode.env"
opencode_env_override: {}
opencode_ssh_public_key: "{{ undefined() }}"
opencode_ssh_private_key: "{{ undefined() }}"
opencode_server_username: "{{ undefined() }}"
opencode_server_password: "{{ undefined() }}"
opencode_env:
  OPENCODE_SERVER_USERNAME: "{{ opencode_server_username }}"
  OPENCODE_SERVER_PASSWORD: "{{ opencode_server_password }}"

1.5.2.31 - OS

Common os setup

1.5.2.31.1 - Defaults

Defaults for os
os_hardening_enabled: true

1.5.2.32 - Posgresql

Setup Postgresql

1.5.2.32.1 - Defaults

Defaults for postgresql
postgresql_packages:
  - postgresql-server
  - postgresql-contrib
postgresql_service: postgresql

1.5.2.33 - Pve

Proxmox Virtual Environment deploy

1.5.2.33.1 - Defaults

Defaults for pve
pve_repo_keyring_path: /usr/share/keyrings/proxmox-archive-keyring.gpg
pve_repo_path: /etc/apt/sources.list.d/pve-install-repo.sources
pve_repo_keyring_url: https://enterprise.proxmox.com/debian/proxmox-archive-keyring-trixie.gpg
pve_repo_keyring_checksum: "sha256:136673be77aba35dcce385b28737689ad64fd785a797e57897589aed08db6e45"
pve_snippets_dir: /var/lib/vz/snippets
pve_snippets: []
pve_repo_content: |
  Types: deb
  URIs: http://download.proxmox.com/debian/pve
  Suites: trixie
  Components: pve-no-subscription
  Signed-By: {{ pve_repo_keyring_path }}

1.5.2.34 - PVE cluster

Setup PVE cluster

1.5.2.34.1 - Defaults

Defaults for pve_cluster
pve_cluster_remove_repos:
  - pve-enterprise.list 
  - ceph.list
pve_cluster_add_repos:
  - name: pve-no-subscription
    value: deb http://download.proxmox.com/debian/pve bookworm pve-no-subscription
  - name: ceph-squid
    value: deb http://download.proxmox.com/debian/ceph-squid bookworm no-subscription
pve_cluster_node_config: []
pve_cluster_admins: []
pve_cluster_cluster_name:
pve_cluster_acme_accounts: []
pve_cluster_acme_plugins: []
pve_cluster_venv_dir: /opt/ansible/pve_cluster_venv
pve_cluster_venv_packages: 
  - pexpect
pve_cluster_base_image_dir: /var/lib/vz/template
pve_cluster_node_name: "{{ inventory_hostname | mandatory | split('.') | first }}"
pve_cluster_ceph_enabled: false
pve_cluster_ceph_repository: no-subscription
pve_cluster_ceph_osd: []
pve_cluster_ceph_pools: []
pve_cluster_ceph_mon: []
pve_cluster_ceph_mgr: []
pve_cluster_ceph_mds: []
pve_cluster_storages: []
pve_cluster_storage_config_path: /etc/pve/storage.cfg

1.5.2.35 - PVE VM

Setup PVE VM

1.5.2.35.1 - Defaults

Defaults for pve_vm
pve_vm_agent: 
pve_vm_name: "{{ inventory_hostname }}"
pve_vm_delegate_update_known_hosts: localhost
pve_vm_delegate_pve: 
pve_vm_set: "{{ pve_vm_set_default + pve_vm_set_additional }}"
pve_vm_set_default: []
pve_vm_set_additional: []
pve_vm_set_creation: "{{ pve_vm_set_creation_default + pve_vm_set_creation_additional }}"
pve_vm_set_creation_default: []
pve_vm_set_creation_additional: []
pve_vm_resize: []
pve_vm_venv_dir: "/opt/ansible/pve_vm_venv"
pve_vm_init_user:
pve_vm_venv_packages:
  - proxmoxer
  - requests

1.5.2.36 - PVE VM remove

Remove PVE VM

1.5.2.36.1 - Defaults

Defaults for pve_vm_remove

1.5.2.37 - Raspberry pi

Setup raspberry pi

1.5.2.37.1 - Defaults

Defaults for raspberry_pi
raspberry_pi_argon_enabled: false
raspberry_pi_containers_enabled: false
raspberry_pi_argon_eeprom_script_path: /usr/local/bin/argon_argon_eeprom.sh
raspberry_pi_argon_argon1_script_path: /usr/local/bin/argon_argon1.sh
raspberry_pi_cmdline_path: /boot/firmware/cmdline.txt

1.5.2.38 - SSH

Setup ssh

1.5.2.38.1 - Defaults

Defaults for ssh
ssh_hardening_enabled: true
ssh_vault_mount: ssh/servers
ssh_vault_role: "{{ undefined }}"
ssh_sign_ignore_errors: false
ssh_valid_principals: []

1.5.2.39 - SSH port forwarding

Setup SSH port forwarding

1.5.2.39.1 - Defaults

Defaults for ssh_port_forward
ssh_port_forward_local_addr: 127.0.0.1
ssh_port_forward_script_path: /usr/local/bin/ssh-port-forward

1.5.2.40 - SSH update known hosts

Update known hosts

1.5.2.40.1 - Defaults

Defaults for ssh_update_known_hosts
ssh_update_known_hosts_hosts: []

1.5.2.41 - T3 Code

Run the T3 Code server as a systemd service

1.5.2.41.1 - Defaults

Defaults for t3code
t3code_user: t3code
t3code_user_uid: 8151
t3code_dir: /opt/t3code
t3code_home_dir: "{{ t3code_dir }}/home"
t3code_work_dir: "{{ t3code_dir }}/work"
t3code_disk:
t3code_port: 5120
t3code_version: "{{ undefined() }}"
t3code_state_dir: "{{ t3code_dir }}/state"
t3code_auth_token: "{{ undefined() }}"
t3code_service_path: /lib/systemd/system/t3code.service
t3code_env_path: "{{ t3code_dir }}/.env"
t3code_env: {}

1.5.2.42 - Traefik

Traefik

1.5.2.42.1 - Defaults

Defaults for traefik
traefik_user: traefik
traefik_no_user: false
traefik_owner: root
traefik_user_uid: 3578
traefik_dir: "/opt/traefik"
traefik_log_dir: "{{ traefik_dir }}/logs"
traefik_data_dir: "{{ traefik_dir }}/data"
traefik_tls_dir: "{{ traefik_dir }}/tls"
traefik_disk:
traefik_mtls_ca_local_path: "{{ role_path }}/files/traefik_mtls_ca.crt"
traefik_mtls_ca_path: "{{ traefik_tls_dir }}/mtls_ca.crt"
traefik_acme_path: "{{ undefined }}"
traefik_config_dir: "{{ traefik_dir }}/configs"
traefik_config_path: "{{ traefik_config_dir }}/traefik.toml"
traefik_disable_eab: false
traefik_config_local_path: "files/traefik.toml"
traefik_dynamic_config_path: "{{ traefik_config_dir }}/traefik_dynamic.toml"
traefik_dynamic_config_local_path: "files/traefik_dynamic.toml"
traefik_service_path: "/lib/systemd/system/traefik.service"
traefik_service_scope: system
traefik_bin_local_path: "{{ role_path }}/files/traefik"
traefik_bin_path: /usr/bin/traefik
traefik_vault_bin_local_path: "{{ role_path }}/files/vault"

1.5.2.43 - Traefik (old)

Old traefik role

1.5.2.43.1 - Defaults

Defaults for traefik_old
traefik_user: traefik
traefik_user_uid: 3653
traefik_env: {}
traefik_data_dir: /mnt/traefik
traefik_log_dir: "/var/log/traefik"
traefik_certificates_dir: "{{ traefik_data_dir }}/certificates"
traefik_configs_dir: "{{ traefik_data_dir }}/configs"
traefik_configs_version: "{{ lookup('ansible.builtin.pipe', 'git rev-parse HEAD') }}"
traefik_configs_dynamic_dir: "{{ traefik_configs_cur_dir }}/dynamic"
traefik_configs_dynamic_dir_symlink: "{{ traefik_configs_symlink }}/dynamic"
traefik_configs_cur_dir_name: "{{ traefik_configs_version }}"
traefik_configs_cur_dir: "{{ traefik_configs_dir }}/{{ traefik_configs_cur_dir_name }}"
traefik_configs_symlink: "{{ traefik_configs_dir }}/current"
traefik_static_config_path: "{{ traefik_configs_symlink }}/traefik.yaml"
traefik_releases_dir: /opt/traefik/releases
traefik_static_config:
traefik_dynamic_configs: []
traefik_release_version: v3.3.1
traefik_release_dir_name: "{{ traefik_release_version }}"
traefik_release_dir: "{{ traefik_releases_dir }}/{{ traefik_release_dir_name }}"
traefik_release_symlink: "{{ traefik_releases_dir }}/current"
traefik_release_symlink_bin: "{{ traefik_release_symlink }}/traefik"
traefik_release_archive_name: "traefik_{{ traefik_release_version }}_linux_amd64"
traefik_release_archive_full: "traefik_{{ traefik_release_version }}_linux_amd64.tar.gz"
traefik_release_bin_path: "{{ traefik_release_dir }}/traefik"
traefik_release_download_url: "https://github.com/traefik/traefik/releases/download/{{ traefik_release_version }}/{{ traefik_release_archive_full }}"
traefik_release_download_checksum: sha256:27fd502a8d80fc81b97faf5cebd7a1cbc1a2c5369d18e0f4471a66d1a8c139ce

1.5.2.44 - Update all packages

Update all system packages

1.5.2.44.1 - Defaults

Defaults for update_all_packages

1.5.2.45 - Users

Setup system users

1.5.2.45.1 - Defaults

Defaults for users
users_regular: {}
users_remove: {}
users_admins:
  ansible:
    name: ansible
    disable_passwd: true
    sudo_no_passwd: true
users_ssh_keys: {}

1.5.2.46 - Vault

Setup Hashicorp Vault

1.5.2.46.1 - Defaults

Defaults for vault
vault_user: vault
vault_user_uid: 3123
vault_dir: "/opt/vault"
vault_data_dir: "{{ vault_dir }}/data"
vault_raft_dir: "{{ vault_dir }}/raft"
vault_config_dir: "{{ vault_dir }}/configs"
vault_config_path: "{{ vault_config_dir }}/vault.hcl"
vault_config_local_path: "files/vault.hcl"
vault_log_dir: "{{ vault_dir }}/logs"
vault_tls_dir: "{{ vault_dir }}/tls"
vault_service_path: "/lib/systemd/system/vault.service"
vault_tls_client_ca_file_local_path: files/tls_client_ca_file.pem
vault_tls_client_ca_file_path: "{{ vault_tls_dir }}/tls_client_ca_file.pem"
vault_tls_cert_file_path: "{{ vault_tls_dir }}/tls_cert_file.pem"
vault_tls_key_file_path: "{{ vault_tls_dir }}/tls_key_file.pem"
vault_tls_issue_path:
vault_tls_alt_names: ""
vault_bin_local_path: "{{ role_path }}/files/vault"
vault_bin_path: /usr/bin/vault
vault_peers_write: false
vault_peers_local_path:
vault_peers_remote_path: "{{ vault_raft_dir }}/raft/peers.json"

1.5.2.47 - Wireguard

Setup wireguard

1.5.2.47.1 - Defaults

Defaults for wireguard
wireguard_dir: "/etc/wireguard"
wireguard_local_config_paths: []

1.5.2.48 - Xray

Setup xray

Links:

1.5.2.48.1 - Defaults

Defaults for xray
xray_enabled: false
xray_config_dir: /usr/local/etc/xray
xray_log_dir: /var/log/xray
xray_config_path: "{{ xray_config_dir }}/0-main.json"
xray_client_id:
xray_wireguard_relays: []
xray_wireguard_ipv4_address:
xray_wireguard_ipv6_address:
xray_wireguard_private_key:
xray_config:
xray_configs: {}
xray_user: xray
xray_socket_dir: /var/shm/xray
xray_caddy_config_path: /etc/caddy/configs/xray.Caddyfile
xray_subscriptions_dir: /usr/local/etc/xray-subscriptions
xray_caddy_user: caddy

1.6 - Autoscroll

Mouse-driven autoscroll CLI with reloadable configuration

Autoscroll is a Python and PyQt6 command-line application that turns mouse movement into horizontal and vertical scrolling. It supports configurable buttons, scroll speed, and configuration changes without restarting.

  • Platfrom-independent autoscroll
  • Config file with hot-reload
  • Some argparse tinkering
  • Python3, PyQt6

By default, the icon is disabled, to enable it pass --icon-enable

You can pass file contents as command line arguments using @path/to/the/file syntax. Arguments in that case can be placed wherever - on one line, on several lines

If you want to dynamically pass runtime arguments (without restarting the process), you can use --config options for it

Once you press --buttons-start, you can scroll vertically or horizontally just by moving your mouse untill you press --buttons-end

If --buttons-hold is set, the srolling ends once you release --buttons-start

Once --buttons-start is pressed, the scroll thread starts looping Every loop consists of sleeping for an interval, then scrolling for either 0, 1, or -1 pixels on both axis towards the starting point Starting point is the point where --buttons-start was pressed Sleep interval is recalculated on every mouse move as such:

    100 / (--scrolling-acceleration * max(distance) + --scrolling-speed)

If --scrolling-acceleration is not 0, the speed of scrolling will be faster the farther away you are from the starting point If --scrolling-acceleration is 0, the speed of scrolling will be constant

python3 -m venv venv
. venv/bin/activate
pip install autoscroll
autoscroll
autoscroll --buttons-start 1 --debug-click --icon-disable
autoscroll --icon-enable @config.txt

If config.txt is defined like this, its contents will be used as command line arguments - they will be loaded only once Arguments can be placed wherever - on one line, on several lines For example,

--buttons-start 1
--buttons-hold --debug-click
autoscroll --config-enable --config-path config.txt

If config.txt is defined like this, the process will listen for changes in that file and update itself Arguments can be placed wherever - on one line, on several lines The file is checked for changess every --config-interval For example:

--buttons-start 1 --buttons-hold
--debug_click
usage: autoscroll [-h] [-ss SCROLLING_SPEED] [-sd SCROLLING_DEAD_AREA]
                  [-sa SCROLLING_ACCELERATION] [-bh] [-bs BUTTONS_START] [-be BUTTONS_END]
                  [-ce] [-cp CONFIG_PATH] [-ci CONFIG_INTERVAL] [-ie] [-ip ICON_PATH]
                  [-is ICON_SIZE] [-df] [-dc] [-ds] [-di]

...

options:
  -h, --help            show this help message and exit

scrolling:

  -ss, --scrolling-speed int
                        constant part of the scrolling speed
                        [default: 300]
  -sd, --scrolling-dead-area int
                        size of the square area aroung the starting point where scrolling will stop, in
                        pixels
                        [default: 50]
  -sa, --scrolling-acceleration int
                        dynamic part of the scrolling speed, depends on the distance from the point
                        where the scrolling started, can be set to 0
                        [default: 10]

buttons:

  -bh, --buttons-hold   if set, the scrolling will end once you release --buttons-start
  -bs, --buttons-start int
                        button that starts the scrolling
                        [default: 2]
  -be, --buttons-end int
                        button that ends the scrolling
                        [default: --buttons-start]

config:

  -ce, --config-enable  if set, arguments from the configuration file on --config-path will be loaded
                        every --config-interval
  -cp, --config-path str
                        path to the configuration file
                        [default: ~/.config/autoscroll/config.txt]
  -ci, --config-interval int
                        how often the config file should be checked for changes, in seconds
                        [default: 5]

icon:

  -ie, --icon-enable    if set, the icon will be enabled
  -ip, --icon-path str  path to the icon
                        [default: resources/img/icon.svg]
  -is, --icon-size int  size of the icon, in pixels
                        [default: 30]

debug:

  -df, --debug-file     if set, every time the config file is parsed, information will be printed to
                        stdout
  -dc, --debug-click    if set, click info will be printed to stdout
  -ds, --debug-scroll   if set, scroll info will be printed to stdout
  -di, --debug-initial  if set, startup configuration will be printed to stdout

1.6.1 - Releases

Releases

1.6.1.1 - head

Release head

1.7 - Bazel agent

Bazel runner for repository agents

bazel_agent is the repository Bazel entry point for agents. It keeps the Bazel invocation behind a validated subcommand while consistently applying the agent configuration:

bazel_agent bazel test //path/to/package:all
    ->
bazel test --config=agent //path/to/package:all

bazel is the only Bazel entry point, and it is a validated subcommand. The runner accepts a known Bazel command after the bazel keyword, rejects arbitrary leading arguments, and places --config=agent after the command. Targets, command options, and arguments after the -- separator of a bazel run invocation pass through unchanged. Later options therefore retain Bazel’s normal precedence and can override settings supplied by the agent configuration. The runner resolves bazel from PATH and replaces itself with that process, so signals and the final exit status are not mediated by another wrapper process. Uses of the persistent Bazel server follow the host Codex network policy; the host-bot profile allows loopback so the client-server connection is not blocked.

The runner does not create or inject a host temporary directory. Bazel actions use declared outputs and Bazel-managed temporary storage, and tests use their test temporary-directory contract. Repository-updating host tools that need scratch must accept or derive an explicit task/run path under out/<task>/ instead of relying on ambient TMPDIR, TMP, or TEMP values propagated to the whole build.

Frequently used repository control tools can bypass Bazel analysis after one exact build:

bazel_agent tool run repo_delivery -- provider
bazel_agent tool warm mcp_cordis repo_delivery
bazel_agent tool path repo_delivery

The runner hashes its own binary plus each tool’s declared source, dependency locks, Bazel pins, repository rc files, optional user and host rc files, their transitive imports, any BAZELRC environment files, and the platform. A cache miss takes an exclusive per-key lock, builds the target with runfiles enabled, and copies the complete runnable output into an atomically installed entry. A hit executes that entry directly without starting a Bazel client or loading a worktree graph. Concurrent misses for the same exact key share one build. Inputs are hashed again under the lock and after the build; an in-flight source change selects a new key instead of publishing stale output under the old one.

BAZEL_AGENT_TOOL_CACHE or --cache-root can select the cache. The default is /var/cache/bazel/tool_cache when that managed directory exists, otherwise the user’s cache directory. Because entries contain executable code, the cache root must not be writable by group or others. Source changes select a new key, so a dirty relevant source file cannot silently reuse an older executable.

bazel_agent doctor --workspace-root PATH --task-scratch out/<task>/<run> is a read-only, bounded JSON diagnostic. It reports runner and built-source identity, Bazelisk pins, platform, rc/profile composition, task scratch classification, and stale host-install state without dumping the environment.

Bootstrap the host installation with the underlying Bazel command:

bazel run --config=agent //projects/bazel_agent:install

Once installed, update it with:

bazel_agent bazel run //projects/bazel_agent:install

The install target atomically replaces ~/.local/bin/bazel_agent. After every code update to this project, rerun the install target; the installed binary is not updated automatically. Repository launchers probe the installed runner’s tool-cache support before using it, so an older host installation retains its documented Bazel fallback during rollout.

1.8 - Ci platform

Abandoned CI platform with a Go backend and Vue frontend

An abandoned continuous integration platform with a Go backend and a Vue single-page frontend. The source retains its job, pipeline, and project management components.

  • Clean architecture
  • Backend: Golang, Gorm, Fiber, Hcl, Postgresql
  • Frontend: SPA, VueJS with PrimeVue

Arch

ci_platform
├── api [Interface Adapters]
│   ├── controller
│   ├── middleware
│   └── presenter
├── cmd (CLI interface)
├── docs (OpenAPI Specification and other documentation)
│   └── diagrams
├── entity [Enterprise Business Rules]
├── infrastructure [Frameworks and Drivers]
│   ├── access
│   ├── branch
│   ├── config
│   ├── job
│   ├── jwt
│   ├── lifecycle
│   ├── pipeline
│   ├── pool
│   ├── project
│   ├── schedule
│   ├── session
│   └── user
├── pkg (Support packages)
│   └── error
└── usecase [Application Business Rules]
│   ├── access
│   ├── branch
│   ├── job
│   ├── jwt
│   ├── lifecycle
│   ├── pipeline
│   ├── pool
│   ├── project
│   ├── schedule
│   ├── session
│   └── user
└── web (Web interface)

1.8.1 - Releases

Releases

1.8.1.1 - head

Release head

1.9 - Dotfiles

Personal configuration files with installation and comparison commands

This project packages personal configuration files into an installable archive. Make and Bazel entry points compare the packaged files with the local system and install selected configurations.

  • Archive with dotfiles that can be installed using make
bazel run //projects/dotfiles:help # Show help
bazel run //projects/dotfiles:diff # Show diff
bazel run //projects/dotfiles:install # Install files
oras pull --output "${PWD}" docker.io/alwaldend/src:projects_dotfiles_dotfiles_tar_head
cd releases/projects/dotfiles/head/files
tar -xf dotfiles.tar
cd dotfiles
make help # Show help
make diff # Check diff between system files and those from the archive
make diff/nvim # Check diff for all nvim files
make diff/nvim/.config/nvim/lazy-lock.json # Diff specific file
make install # Install all files from the archive
make install/nvim # Install nvim files
make install/nvim/.config/nvim/lazy-lock.json # Install a specific file
help: Show help
install: Install files from the archive
diff: Show diff between archive files and system files
install/bin: Install bin files
diff/bin: Diff bin files
install/home: Install home files
diff/home: Diff home files
install/nvim: Install nvim files
diff/nvim: Diff nvim files
make: Nothing to be done for 'help'.

1.9.1 - Releases

Releases

1.9.1.1 - head

Release head

1.10 - Goal

Versioned goal resources, local storage, and agent workflow

This project owns the goal execution skill and the deterministic local store that supports it. Ordinary tasks use init for the objective and acceptance, checkpoint --summary --subject --next-action for local progress, and show for bounded continuation. The store derives IDs and digests while retaining explicit resource-version checks. Detailed attempt plans and histories remain available for maintained goals, repeated failures, and complex coordination.

projects/goal/
  api/v1alpha1/      Portable resource types and domain validation
  cmd/goal/          Cobra command wiring and command tests
  docs/              Current architecture and generated diagrams
  internal/fsstore/  Local persistence, per-goal locking, and store tests
  skills/goal/       Model-facing execution protocol and evaluations

Go dependencies flow from cmd/goal to internal/fsstore to api/v1alpha1. The API package has no filesystem or command dependency. The Go toolchain is Bazel’s @rules_go//go; run the package targets below rather than a host-installed go.

The command stores Kubernetes-inspired goals.alwaldend.com/v1alpha1 YAML resources and canonical, digest-bound attempt Markdown in ordinary repository files. Each attempt.yaml binds plan.md, result.md, and evidence/*.md by SHA-256. Goal.status.plans records durable plans with one active plan at a time and states active, accepted, rejected, or superseded; attempts can bind to a plan with spec.planID. Each goal record’s README.md is a generated, bounded, replaceable projection. The portable API treats resource versions as opaque and excludes local ownership paths from desired state. The filesystem backend supplies one cooperative lock per goal, local numeric resource versions, atomic file replacement by sibling temporary-file rename, session bindings, promotion, non-destructive unversioned-record import, and recoverable multi-file publication. Before a multi-file mutation, the backend stages exact after-images and installs a .goal-publication.yaml intent in the goal record; goal doctor classifies the publication state and goal recover replays or discards a pending intent. It is a local file editor with atomic per-file replacement; it does not claim cross-file transaction semantics without the publication intent.

These files are not installed CRDs. A future Kubernetes adapter can convert the API types after adding Kubernetes metadata types, structural schemas, status-subresource behavior, generated runtime methods, and reconciliation of API-server-owned metadata.

Run the command through Bazel:

bazel_agent bazel run //projects/goal/cmd/goal -- --help

Diagnose and finish an interrupted publication:

bazel_agent bazel run //projects/goal/cmd/goal -- doctor --goal-dir $GOAL_DIR
bazel_agent bazel run //projects/goal/cmd/goal -- recover --goal-dir $GOAL_DIR

The canonical skill lives at skills/goal; .agents/skills/goal is only its repository discovery symlink.

1.10.1 -

Goal graph organization

Use this reference when one objective may need related goals, parallel work, or dependency-aware resumption. The graph is a view over ordinary local Goal resources. The execution harness remains responsible for scheduling and permissions.

Keep ordinary ordered steps in one attempt plan. Create a separate goal only when the subgoal benefits from at least one independent property:

  • lifecycle or resumption;
  • acceptance criteria and evidence;
  • ownership or retention;
  • substantial parallel execution; or
  • reuse by more than one objective.

The coordination cost of another goal and edge must be lower than the value of making that boundary explicit.

Goal.spec.relationships supports three same-catalog references:

  • parentGoalRef expresses hierarchy, not execution order;
  • dependsOnGoalRefs names prerequisites; and
  • supersedesGoalRefs records lineage.

A parent is not a Kubernetes owner reference and never implies garbage collection. Supersession does not redirect dependencies or authorize mutation of the older goal. Only an achieved prerequisite satisfies a dependency; an open prerequisite waits, while an abandoned or superseded prerequisite blocks until the relationship is explicitly revised.

Keep each relationship kind acyclic independently. Do not test the union of different edge kinds as one directed acyclic graph. Missing targets make a catalog view unknown, rather than making one otherwise well-formed Goal resource invalid.

Treat inferred relationships as proposals, never facts. Bind a proposal to its source evidence and the goal generation it inspected. A coordinator must review it, analyze the complete catalog for cycles, and publish it through the normal resource-version compare-and-swap path. A worker must not rewrite canonical relationships.

Relationship publication completely replaces the dependency and supersession lists. Omitting the parent preserves it; clearing the parent is an explicit operation. Close an active attempt before changing relationships: each attempt is bound to the goal generation and portable goal-state digest that existed when work began. An accepted relationship request advances generation and resource version even when normalization makes it a semantic no-op.

Per-goal locks do not make a catalog transaction. Cycle prevention checks a snapshot assembled by reading each goal under its own lock. Concurrent writes to different goals can both pass against older snapshots and jointly create a cycle. The single coordinator must avoid those conflicting writes; always run the deterministic graph projection again after parallel structural changes and repair any reported cycle.

Dispatch only goals whose prerequisites are satisfied. Agent selection, capability discovery, delegation, communication topology, and runtime scheduling belong to the execution harness.

Use the complete deterministic graph analysis for inspection. A catalog with unresolved references is Unknown; a cyclic catalog is Invalid. Graph analysis does not truncate its input, so report a catalog read or validation failure instead of inferring readiness from a partial view.

Attempt input bindings, criteria and goal-state digests, structured reviews, and artifact digests form the provenance graph for evidence.

1.10.2 -

Attempt lifecycle and evidence

Use this reference for maintained goals, repeated failures, and complex coordination. Ordinary progress uses the compact checkpoint workflow in the skill entry point.

One attempt is a bounded work unit with one reviewable outcome. Establish before implementation:

  • the observed Goal resource version as the next checkpoint’s compare-and-swap token; the store derives generation, lifecycle, criteria, and digest bindings rather than requiring manual transcription;
  • the uncertainty or stable defect being targeted;
  • work type and hypothesis when the work tests one;
  • the smallest high-leverage module or question, its stop condition, and the minimum whole-result context needed to detect interface or integration harm;
  • the plan, inputs, parameters, intended result identity, and review packet;
  • affected criteria and the fixed regression checks; and
  • parent checkpoint or prior attempt when one exists.

Preflight deterministic geometry, numeric gates, controlling references, paths, APIs, tools, permissions, and whether the proposed artifact can satisfy its own acceptance gate. Preserve material preflight evidence without turning discarded prose drafts into fake attempts.

Prefer a bounded module whose result can change the next decision. Do not polish it in isolation: retain enough surrounding context to judge composition, interfaces, and fixed regressions. If a cheap check decisively falsifies the module, interface, or approach, stop work and close the attempt with that evidence rather than completing the original plan mechanically.

A criterion verdict is one of pass, fail, or unverified. Evidence must identify its criterion revision and the exact tested subject:

  • content: a digest or immutable version;
  • source change: source revision and relevant configuration;
  • stateful operation: target identity, environment/config revision, operation receipt, and observed postcondition;
  • research or decision: source set, retrieval date where relevant, analysis artifact, and review method.

A later change that can affect a verdict invalidates it until rerun. Never combine visual evidence from one candidate with technical evidence from another. Command success alone is not evidence of the desired postcondition.

For a monolithic shared artifact without stable mergeable interfaces, derive each candidate from an exact immutable baseline and keep it isolated. Use an approved baseline when the task requires approval. Compare the candidate in the minimum whole-result context needed to detect integration regressions. Bind acceptance or approval evidence to its exact identity; the canonical writer may promote it only with existing mutation authority and when the task’s acceptance and approval policy permits. Do not manufacture a permanent file split solely to make concurrent editing possible.

Inspect likely failure views and edge cases, not only the best output. For subjective work, use consistent comparisons and independent review when available. Judge absolute quality against the target rather than improvement from a weak predecessor.

Close the attempt with:

  1. work actually performed;
  2. artifacts and raw verification evidence;
  3. a verdict for every affected criterion and regression check;
  4. the dominant remaining failure;
  5. the decision to accept, refine, or reset; and
  6. a process audit covering measurable movement and feedback bottlenecks.

Publish the close only if the goal resource version and lifecycle generation still match. A stale attempt remains useful evidence, but it cannot silently become canonical or reopen a closed lifecycle.

When a required criterion fails or remains unverified, keep the outcome open, update the stable failure count, and choose the highest-leverage next attempt. After the same defect survives twice, materially change strategy.

At least every three closed attempts, and immediately on a stalled trend, examine the complete attempt history and the end-to-end process, not only the latest failure. Identify systemic delays, repeated assumptions, weak evidence, poor decomposition, and unhelpful tooling. Process changes are justified only when they improve the speed or reliability of producing the requested result. Record the review and the last attempt it covers in attempt evidence or the attempt result so its cadence survives a session change.

For final acceptance, freeze one exact result, run every required criterion and the complete regression set, deliver or export it, and verify that delivery did not change its identity. If delivery changes the tested subject, rerun the full evidence plan.

1.10.3 -

Promotion and migration

Use this reference only when promoting a workspace goal or importing an unversioned record.

Promotion changes storage and retention, not goal identity. It must:

  1. require an explicit maintained-project decision and an owning project root;
  2. lock the source and destination paths in canonical order, then validate the source at an expected resource version;
  3. preserve the goal ID and closed attempt history;
  4. record source scope and promotion provenance;
  5. require repository-relative or stable external links;
  6. retain, copy, or make reproducible every acceptance-critical artifact;
  7. scan for absolute local paths, credentials, private environment details, and ignored evidence that would become broken; and
  8. validate and render the destination before making it canonical.

Do not promote caches or routine coordination logs. Refuse a destination that would shadow another goal with the same ID or that cannot retain critical evidence. Leave the workspace source intact until the destination is verified.

A README-only goal has no claimed schema version. Migration is intentionally conservative and is always a non-destructive import. Supply a distinct legacy source directory and destination goals root; the command never converts the source in place.

  • keep every source byte and source directory entry unchanged;
  • derive the stable goal ID from the source directory name and publish only to <destination-goals-root>/<goal-id>;
  • reject canonical source/target equality or ancestry overlap, then lock both paths in canonical sorted order;
  • preserve the original prose as an immutable legacy snapshot;
  • import only fields that are unambiguous;
  • mark imported criteria unverified in the closed migration attempt and begin a new structured lifecycle at the migration checkpoint;
  • build a complete <goal-id> directory in hidden staging under the destination root and run the normal record validator there;
  • re-read and digest the source immediately before publishing the staged directory with one rename;
  • make rerunning the same provenance and options idempotent; and
  • refuse an existing target with different provenance, options, ownership, or invalid content.

Do not pretend a prose history can be losslessly normalized. The snapshot is evidence of what was recorded; new structured attempts begin from the migration checkpoint.

1.10.4 -

Goal resource format v1alpha1

Use this reference for checkpoint payloads, criteria changes, record semantics, or validation errors. Ordinary resume uses the CLI’s bounded view. The files use Kubernetes-style resource envelopes for familiar versioning and evolution; they are portable local records, not Kubernetes objects or CRDs.

The same directory shape is used in both scopes:

<goal-id>/
  goal.yaml
  criteria.yaml
  criteria-revisions/
    <revision>.yaml
  README.md
  attempts/
    <attempt-id>/
      attempt.yaml
      plan.md
      result.md
      evidence/

Workspace records normally live at out/<task>/goals/<goal-id>/. The recommended direct-initialization layout for project records is <owner-root>/goals/<goal-id>/. This is guidance rather than a CLI constraint; direct initialization, promotion, and migration accept other safe in-workspace roots. A goal ID is stable across promotion and must not be reused.

Every canonical YAML resource uses the Kubernetes-style envelope. For example, a newly initialized local Goal has this shape:

apiVersion: goals.alwaldend.com/v1alpha1
kind: Goal
metadata:
  name: example-goal
  resourceVersion: "1"
  generation: 1
  creationTimestamp: "2026-08-30T00:00:00Z"
  annotations:
    goals.alwaldend.com/local-owner-root: out/example
spec:
  title: Example goal
  scope: workspace
  retention:
    policy: ephemeral
  relationships:
    dependsOnGoalRefs: []
    supersedesGoalRefs: []
status:
  lifecycleGeneration: 1
  outcome: open
  execution: active
  criteriaRevision: 1
  observedAt: "2026-08-30T00:00:00Z"

The allowed kinds are Goal, GoalCriteria, GoalAttempt, and GoalSessionBinding. metadata.name is a DNS-compatible stable resource identity. Use only standard Kubernetes ObjectMeta field names. In the local store, metadata.resourceVersion emulates an API-server optimistic-concurrency token: carry it literally and do not perform arithmetic on it. The local CLI advances metadata.generation for spec changes and for every accepted relationship replacement, including a normalized no-op. Lifecycle generation is separate because criteria replacements and outcome or execution changes can invalidate in-flight work without changing desired relationships.

goal.yaml, criteria.yaml, immutable criteria-revisions/<revision>.yaml snapshots, each attempt.yaml, and the exact plan.md, result.md, and evidence/*.md bytes bound by its artifact manifest are canonical. Validation checks those Markdown sidecars against their SHA-256 digests. README.md is generated, bounded, and replaceable. It is never canonical input; regenerate it from the canonical record instead of editing it by hand.

Use the repository tool for canonical operations when it is available:

bazel_agent bazel run //projects/goal/cmd/goal -- <command> --help

The command owns IDs, resource validation, per-goal locking, resource-version checks, atomic file replacement, path normalization, and rendering. Do not emulate those mechanics with direct YAML edits. If the tool is unavailable, keep exactly one writer and state that revision and concurrency safety were not verified.

The local adapter keeps a deterministic, persistent per-goal lock file under $XDG_RUNTIME_DIR/alwaldend/goal/locks/. It is outside the workspace and cannot be committed. While held, it contains the current process PID for diagnostics; clean release clears it, while a crash can leave a stale PID. flock, never the PID text, is authoritative, and the tool never unlinks a lock based on that text. The lock is not a resource or part of the portable record format. A mutation writes a sibling temporary file, closes it, and renames it over the destination while holding that goal’s lock. Each file replacement is atomic; a command that changes several files does not claim a cross-file transaction.

Goal.spec owns the requested configuration: title, workspace or project scope, retention policy, and stable parentGoalRef, dependsOnGoalRefs, and supersedesGoalRefs relationships. The workspace-relative owner root is local adapter metadata in the goals.alwaldend.com/local-owner-root annotation. The filesystem backend requires it, but portable goal-state digests exclude it. Each local goal reference is an object containing name, rather than a path or bare ID. Relations do not grant permission to change related goals or imply a scheduler in v1alpha1.

Goal.status owns observed state: outcome, execution, active and accepted attempt IDs, accepted result digest, current criteria revision, lifecycle generation, promotion or migration provenance, and update time. Criteria replacement and accepted outcome or execution changes advance lifecycle generation. Starting, updating, or closing an attempt without such a transition changes goal state but does not advance lifecycle generation.

GoalCriteria.spec identifies its goal by a {name: ...} reference and a revision. Each item has a stable criterion ID, its own revision, a required flag, statement, and evidence method. Every accepted complete criteria replacement advances the criteria resource version, generation, and spec revision. An item’s revision advances only when its meaning changes. Evidence proves exactly one item revision; an earlier pass becomes historical rather than current.

Keep a fixed regression set in the criteria resource. Run it after every attempt that can affect it and against the frozen final result.

GoalAttempt.spec binds the work to a {name: ...} goal reference, goal and lifecycle generations, criteria revision, portable criteria and goal-state digests, optional planID, and work type. It does not store a Goal resource version: that value is the checkpoint caller’s mutation-time compare-and-swap token, not a durable attempt input. Attempt status records whether it is open or closed, relevant timestamps, the SHA-256 artifact manifest, and the structured close review. Review evidence references may name only the manifest’s plan, result, or evidence paths. The digest-bound Markdown bytes live beside the resource.

An attempt may carry optional structured resume fields so a fresh agent can resume an open goal without free-form archaeology:

  • stableDefect: the reproducible problem under investigation.
  • hypothesis: the candidate explanation being tested.
  • subject: the exact system, artifact, or reference under test.
  • affectedCriteria: criterion IDs this attempt exercises; unique and sorted.
  • regressionRefs: reviewed regression set or fixtures; unique and sorted.
  • priorAttemptID: an earlier attempt this one resumes or corrects.
  • dominantFailure: the single most useful failure signal observed.
  • measurableDelta: the measured difference this attempt produces.
  • nextAction: the deterministic next step for a resuming agent.
  • blocker: an external condition preventing progress, if any.
  • resumeCondition: what must hold before a resuming agent resumes this attempt.

Goal.status.plans stores durable plan summaries. Each entry has a portable planID, a bounded strategy, and a state of active, accepted, rejected, or superseded. A rejected plan carries a bounded rejectionReason. At most one plan is active. Create or transition a plan with goal checkpoint --plan-id ... --plan-strategy ... or --plan-state ... --plan-only; a new plan supersedes the previous active plan. An attempt may bind to one of these summaries with spec.planID; the plan is input context and the attempt review remains the acceptance evidence.

These fields are advisory input, not acceptance evidence: a closed attempt may omit them entirely. Prose fields must be trimmed, bounded, and free of NUL; identifiers must be portable record IDs; lists must be unique, sorted, and bounded. The generated README projection surfaces stableDefect, dominantFailure, nextAction, blocker, and resumeCondition for open attempts so an agent can resume directly from the goal record.

For the registered repository goals root, use the goal command’s catalog-backed resume view instead of scanning goal directories:

bazel_agent bazel run //projects/goal/cmd/goal -- resume \
  --goals-root projects/agents/goals \
  --catalog ../../../tools/agents/catalogs/goal.json

The output is a bounded GoalResumePacket decoded from the checked, digest-verified goal catalog. It contains only open goals with a resumable open attempt and their exact candidate paths and continuation fields. --catalog is required and resolves relative to --goals-root; a task-specific root needs its own generated catalog. The command validates catalog structure and its stored digest, not freshness against owning goal records. Revalidate the selected record before acting on its continuation fields.

Goal.status.acceptedResultDigest is the accepted attempt’s result.md SHA-256, not automatically the identity of an external deliverable. Record an external subject’s exact identity in the result or evidence when acceptance depends on it.

Allowed work types are investigation, candidate, change, integration, validation, and decision. Not every work unit has a file candidate or hypothesis. Stateful work should identify source revision, target and environment/config revision, plus an operation receipt.

An open attempt may receive isolated evidence. Closing it publishes its final resource, plan, result, and evidence set. After close, treat its directory as immutable; a correction or additional evidence is a new attempt that refers to the old one.

checkpoint --close-attempt --review-file <path> takes plain YAML with exactly two keys, decision and criteria; do not add resource-envelope headers. Use the actual IDs and revisions returned by show:

decision: accept
criteria:
  - criterionID: criterion-001
    criterionRevision: 1
    verdict: pass
    evidenceRefs:
      - evidence/acceptance.md

Decisions are accept, refine, or reset. Verdicts are pass, fail, or unverified; passing or failing requires a reference to plan.md, result.md, or an imported evidence/*.md artifact. Sort criteria by ID and keep evidence references unique and sorted. Evidence must describe the exact tested candidate and actual observations. To mark the goal achieved, add --outcome achieved only when this accepting close passes every current required criterion. Ordinary summaries do not supply these verdicts.

List, goal-detail, and README views have explicit item or byte limits and report truncation. Graph analysis instead consumes the complete accepted catalog or fails. Prefer useful recent entries in bounded views over failing because history is large. Canonical and migrated Markdown files must be bounded regular files containing valid UTF-8 and no NUL bytes. Store links relative to the workspace or owner root, or as stable external URLs. Never place local absolute paths, credentials, or private environment values in a project goal.

The resources deliberately follow Kubernetes API conventions, but the local files are not directly managed by a Kubernetes API server. The filesystem adapter supplies resourceVersion, generation, and local annotations. A future Kubernetes adapter must let the API server populate its read-only metadata, install structural OpenAPI schemas, enable the status subresource, and reconcile or strip local-only annotations during import and export.

Keep portable identity and desired state in the resource. Store a session’s workspace-relative goal path only in the namespaced annotation goals.alwaldend.com/local-goal-ref; GoalSessionBinding.spec.goalRef remains a normal {name: ...} object. Digest-bound plan, result, and evidence sidecars are a local storage representation; a cluster adapter must map their bytes to cluster-accessible objects or artifact references.

This boundary lets a future CRD/controller reuse the API types. Do not claim that a local record can be passed to kubectl apply without that adapter and the CRDs.

When implementing that adapter, verify the current Kubernetes custom-resource and ObjectMeta contracts rather than copying the local store’s metadata behavior blindly.

1.10.5 -

Sessions and concurrency

Use this reference when resuming, switching goals, delegating, or reconciling a stale update.

A goal is identified by its stable goal ID and scope, not by a chat thread. A GoalSessionBinding is a replaceable pointer to the current goal. Its attachment-time generation, revision, and digest fields only detect whether that pointer’s view has become stale. List and inspect stored goals before attaching when identity is uncertain. Starting a new session must not create a duplicate merely because the old thread is unavailable.

Attaching does not mutate the goal. Detaching or switching focus does not pause, close, or delete it. Verify the goal resource version and current attempt after every fresh attach or context recovery.

Use one coordinator for canonical state. For an attempt or lifecycle checkpoint mutation within one existing goal record, the goal tool:

  1. acquires the selected goal’s cooperative cross-process file lock;
  2. rereads canonical state under the lock;
  3. checks the caller’s expected resource version; when publishing an existing attempt, it also verifies its goal reference, lifecycle generation, and digest-bound criteria snapshot;
  4. validates the complete prospective state and fully stages a new attempt in a hidden sibling directory when needed;
  5. advances goal.yaml as the optimistic-concurrency commit point;
  6. publishes the staged directory with one rename, or replaces existing attempt files through sibling temporary-file renames;
  7. finalizes an immediately closed new attempt in goal.yaml at the same resource version; and
  8. writes the derived projection last and releases the lock.

The intermediate Goal for an immediately closed new attempt keeps an active pointer until that attempt exists. An interruption before attempt publication or Goal finalization therefore fails validation rather than silently dropping the attempt. After the commit point, an error returns the committed Goal reference and names its advanced resource version. Validate before resuming; never retry with the caller’s stale token.

A checkpoint --criteria-file update uses the same goal lock and expected resource version. It installs the immutable criteria snapshot, replaces the current criteria, advances goal.yaml, and writes the projection last.

Atomic rename prevents torn files; it does not prevent lost updates by itself. The lock and expected resource version are both required for this compare-and-swap path. A process that ignores the lock is outside this cooperative trust boundary.

The lock is keyed by the canonical goal path under $XDG_RUNTIME_DIR/alwaldend/goal/locks/, so it is never tracked and work on one goal does not block an unrelated sibling goal. If a process exits between two file renames, validate the record before resuming instead of inferring state from temporary files or generated Markdown.

The lock file contains the current holder PID for diagnostics. Clean release truncates the PID while still holding flock; a crash releases the kernel lock automatically and leaves the PID for diagnosis. The next holder overwrites a stale PID. flock, not PID existence or process liveness, is the authority. Never unlink and recreate a lock path based on PID metadata while other processes may be waiting on its existing inode.

The key uses the full canonical absolute goal path rather than only its ID. Same-named goals in parallel workspaces are independent; symlink aliases of one path share a lock.

Other commands use locks according to the paths they coordinate. Promotion and migration acquire distinct source and destination locks in canonical-path order. Attachment reads the goal under its goal lock, then writes the session binding under a separate path lock.

This is cooperative same-user coordination, not a hostile-process sandbox. The runtime lock inode is checked without following a final symlink, but the workspace and goal pathnames must remain stable for the duration of a command. A process with the same user identity that races workspace renames or symlink replacement is outside the tool’s trust boundary.

When an error reports goal publication is incomplete, run goal doctor on the goal directory to classify the pending intent, then goal recover to replay or discard it. Doctor states: stable, committed-projection-stale (a README-only refresh), discardable-intent (nothing canonical changed; recover removes it), staged-intent or partial-intent (recover replays the after-images), and conflict (refused). Never retry a mutation over a pending intent and never delete the intent or staging directory by hand.

On a stale update, retain the isolated attempt output, reread the new canonical state, and decide whether to rebase the evidence into a new attempt, revise the plan, or discard publication. Never retry blindly with a newly read version.

Workers receive immutable inputs: goal ID, resource version, lifecycle generation, criteria revision, attempt ID, bounded task, and an isolated scratch/output location. They do not write into the canonical goal directory. The coordinator reviews their output and imports selected Markdown evidence through the canonical checkpoint.

For a long-running goal, the coordinator explicitly lists ready independent workstreams at start, resume, and before each attempt. If at least two can produce useful reviewable outputs without racing canonical state, delegate them concurrently. Remaining sequential requires a concrete reason recorded with the attempt, such as an unresolved dependency, unsafe shared mutation, or an integration queue that would erase the latency benefit. Recheck when an attempt closes, stalls, changes strategy, or exposes another independent workstream.

For a monolithic artifact with no stable mergeable interfaces, give each worker an isolated copy of the same exact frozen baseline instead of splitting the canonical artifact; use an approved baseline when the task requires approval. Bound each copy to one falsifiable change and enough whole-result context to expose integration regressions. The coordinator may promote a candidate only when the task already authorizes the mutation and the task’s acceptance and approval policy permits it; workers never merge competing copies directly. Copy only data permitted for that worker boundary and minimize unrelated context.

Before publication, recheck that the goal remains open, the execution state permits publication, and all versions still match. This prevents a late worker from publishing after pause, completion, abandonment, or supersession.

Parallelize only independent work with disjoint output locations. Allocate workers and compute to critical-path uncertainty, and cap work in progress at the coordinator’s review and integration capacity. Idle slots are not a failure when no additional useful workstream is ready. Suitable work includes bounded candidate variants, research, disjoint modules, blind review, verification, and artifact preparation. Bound fanout and depth; do not split trivial operations merely to fill slots, and require a separate benefit for recursive delegation. Stop workers whose output can no longer affect the next decision or required acceptance and delivery evidence.

For registered repository goals, use the explicit checked catalog:

bazel_agent bazel run //projects/goal/cmd/goal -- resume \
  --goals-root projects/agents/goals \
  --catalog ../../../tools/agents/catalogs/goal.json

--catalog is required and resolves relative to --goals-root. The bounded view selects open goals with resumable attempts and verifies the catalog’s stored digest, not freshness against current records. Use show --goal-dir for a selected local record or workspace goal before continuing its next action.

1.10.6 -

Persist resumable research or implementation work with local checkpoints and evidence. Use when work benefits from state that survives interruption; skip simple tasks and one-response questions.

Goal

Keep the objective, acceptance check, current candidate, evidence, and next action inspectable. The CLI owns record identity, revisions, digests, locking, and interrupted-write recovery. Use it instead of editing canonical YAML or generated README projections.

Use an ignored workspace goal under out/<task>/goals/<goal-id>/. A project goal under <owner-root>/goals/<goal-id>/ is appropriate only when the user requests, or the project establishes, maintained history. Length alone does not justify committed records. A question grants no new mutation authority.

Select an existing goal by stable ID and path before initializing another. When identity is uncertain, use list --goals-root <root>. Initialize once:

bazel_agent bazel run //projects/goal/cmd/goal -- init \
  --goals-root "out/<task>/goals" \
  --title "Requested outcome" --criterion "Observable acceptance check"

For routine progress, supply a short summary, the exact candidate identity, and the next action. Mark missing checks and inferred criteria honestly:

bazel_agent bazel run //projects/goal/cmd/goal -- checkpoint \
  --goal-dir "<record>" --expected-resource-version "<observed-version>" \
  --subject "<exact candidate>" \
  --summary "<work performed, evidence, and checks still needed>" \
  --next-action "<next concrete step>"
bazel_agent bazel run //projects/goal/cmd/goal -- show --goal-dir "<record>"

--summary accepts up to 8192 bytes of inline Markdown and creates ordinary plan/result artifacts internally. Optional --evidence <file.md> imports immutable evidence. Later checkpoints replace the open attempt’s result and update its candidate and next action. The initial plan and imported evidence remain intact. Routine progress needs no separate plan ID, payload file, process audit, or new attempt.

show returns objective, criteria, current resource version, and active attempt progress with a bounded result preview, source paths, and digests. Inspect the referenced result when truncated. Candidate and prose fields are caller declarations, not live observations or proof of acceptance. Revalidate only mutable inputs required by the recorded next action after interruption.

Carry the literal observed --expected-resource-version into each write. If stale, reread and reconcile the intervening changes; never blindly replace it with the latest version. Keep one coordinator for canonical goal writes. A changed candidate needs a new summary or result; old evidence applies only to the candidate it tested. Neither a checkpoint nor a successful command establishes acceptance.

Keep outcome (open, achieved, abandoned, superseded) separate from execution (active, paused, waiting, blocked). Questions and scheduling interruptions do not silently pause a goal or expand its authority. Honor explicit pause or cancellation and resume authorized work after incidental interruptions. Difficulty alone is not a blocker.

At acceptance, verify the exact result against every required criterion and applicable regression. Close the attempt with checkpoint --close-attempt --review-file <review.yaml> and the final result/evidence; use --outcome achieved only when all required criteria pass. The review records criterion IDs, revisions, verdicts, and evidence references. Read the close review format when preparing it. Closed attempts are immutable; corrections use a new attempt.

Checkpoint locally when work needs a reliable continuation point. A conversational yield does not require committing, pushing, or running the full delivery workflow. Use repo-delivery at a meaningful review-ready milestone or final implementation handoff, and for an explicitly requested remote backup. Deliver all legitimate source changes before final handoff; keep scratch and workspace records ignored. Report a blocked or incomplete publication honestly and distinguish a local checkpoint from a verified remote copy.

For maintained project goals, repeated failures, or complex coordination, read lifecycle and evidence for bounded plans, attempt histories, review, and strategy changes. After the same defect survives two attempts, change the approach and preserve its failure evidence. Process reviews support that work; they are not routine checkpoint fields.

1.10.7 - Goal architecture

Local storage, locking, formats, and graph boundaries

Goal architecture

The goal tool is a local CLI for one coordinator working on a goal at a time. It edits ordinary files inside the workspace. It does not require a service, daemon, database, controller, or network connection.

The tool release is 0.0.1. The independent resource-schema version is goals.alwaldend.com/v1alpha1; v1alpha1 describes schema stability and does not imply a stable tool release.

The pursuit loop belongs to the goal skill and its coordinator. The CLI does not schedule or perform the work; it validates and checkpoints the state transitions chosen by the coordinator.

Goal pursuit loop

The editable Mermaid source is goal-loop.mmd.

Goal tool architecture

The editable Mermaid source is goal-tool.mmd.

Structured resources use Kubernetes-style YAML envelopes. Attempt plans, results, and evidence are canonical, digest-bound Markdown artifacts; README.md is a generated Markdown projection. A publication intent is backend recovery metadata written before each multi-file mutation. A catalog has this shape:

goals/
  <goal-id>/
    goal.yaml
    criteria.yaml
    criteria-revisions/<revision>.yaml
    README.md
    .goal-publication.yaml
    .goal-publication-stage/
    attempts/<attempt-id>/
      attempt.yaml
      plan.md
      result.md
      evidence/*.md

Lock files live under $XDG_RUNTIME_DIR/alwaldend/goal/locks/, outside the workspace. They are local adapter state, not Kubernetes resources, and can never be added to version control.

The orchestrator assigns one coordinator to a goal. The CLI independently prevents overlapping cooperating processes. An attempt or lifecycle mutation through checkpoint, a criteria update, or a relationship update follows this path:

  1. Resolve the canonical goal path, hash it into a lock path under $XDG_RUNTIME_DIR/alwaldend/goal/locks/, and take an exclusive flock for that goal.
  2. Refuse to run while a publication intent is pending; read and validate the current resources under the lock.
  3. Reject a stale expected resourceVersion.
  4. Build and validate the proposed resource values in memory.
  5. Stage the exact after-images under .goal-publication-stage/ and install a .goal-publication.yaml intent recording each path and its before/after digest. The new-attempt directory is staged as one directory tree.
  6. Publish goal.yaml with the advanced resource version as the optimistic- concurrency commit point.
  7. Publish the staged attempt directory with one rename when a new attempt exists, or replace existing attempt files through sibling temporary-file renames.
  8. For a newly created attempt closed by the same checkpoint, finalize goal.yaml at the same resource version.
  9. Write the replaceable README.md projection last, remove the intent and staging directory, and release the lock.

The first goal write for an immediately closed new attempt deliberately keeps an active-attempt pointer until the attempt directory exists. The intent remains on disk until the projection writes; after the commit point, an error returns the committed Goal reference, names its advanced resource version, and leaves the intent pending for recovery. A failure before the first goal.yaml rename discards the intent and preserves the exact prior record.

goal doctor is a read-only classification command. With a pending intent it reports the per-target state: stable, discardable-intent, staged-intent, partial-intent, or conflict. Without one it reports stable, a committed-projection-stale README-only issue, or a validation failure. goal recover replays every remaining after-image for a staged or partial intent, refuses a conflict, or discards a discardable intent to restore the prior record. Normal mutations fail closed with a goal publication is incomplete error while an intent is pending, so the coordinator must run goal doctor then goal recover before continuing.

Reads and mutations use the same exclusive per-goal lock, matching the single-coordinator ownership model and leaving one unambiguous holder PID. Different canonical goal paths have different lock files and therefore do not block one another. Lock files are never deleted as part of normal operation; deleting a lock pathname while a process holds its inode would allow a second, unrelated lock to be created. The holder writes its PID into the lock file after acquiring flock for diagnostics. The kernel lock, not PID-file existence, remains authoritative; a clean release truncates the PID while still holding flock, while a crash releases the kernel lock and leaves the last PID for diagnosis. The next holder overwrites that stale PID. A PID is never authority to unlink or recreate the persistent lock path because another waiter may already have its inode open. The operating system may clear XDG_RUNTIME_DIR after all processes have stopped; no canonical state lives there. The command fails clearly when a usable XDG_RUNTIME_DIR is unavailable.

The key includes the full canonical absolute path, not only the goal ID. Two parallel workspaces can therefore operate on same-named goals independently, while two symlink spellings of the same goal still coordinate through one lock.

Legacy migration is a non-destructive two-path operation. It rejects equal or overlapping canonical source and target paths, acquires their locks in sorted order, and never writes into the source. The command builds a complete <goal-id> below a hidden staging directory in the destination goals root, runs the normal record validator there, rechecks that the target is absent, and re-digests the source. It then publishes the staged goal with one directory rename. A matching existing target is an idempotent result; any other existing target is refused.

Promotion likewise acquires the distinct source and destination goal locks in canonical-path order before it validates and publishes the destination.

The runtime directory is private to the current user. Each lock path is opened without following a final symlink, then checked to be a regular, same-user, single-link inode before use. The workspace side remains a cooperative pathname boundary: the workspace and goal path must remain stable during a command. The CLI rejects path escapes and observed symlinks, but it is not a sandbox against another process running as the same user that races pathname replacement.

Atomic rename prevents a reader from seeing a partially written file. A command that replaces multiple files publishes them in a defined order; if it is interrupted between renames, the pending publication intent records exactly which after-images remain. Canonical state consists of validated YAML resources and the exact plan.md, result.md, and evidence/*.md bytes whose SHA-256 digests are stored in each attempt.yaml. Recognized temporary-file residue is removed before validation; the generated README.md projection is replaceable and non-canonical, and .goal-publication.yaml plus .goal-publication-stage/ are transitive recovery state that must never be committed to version control.

Goal relationships are typed references in Goal.spec: parent, dependency, and supersession. Catalog graph analysis is a pure, deterministic projection of fully validated goal records, including their digest-bound Markdown artifacts. Each edge kind is checked separately for cycles; missing references remain unknown instead of being invented or silently accepted as resolved.

set-relationships replaces the dependency and supersession lists completely; omitting the parent flag preserves the parent, while --clear-parent removes it. Every accepted request advances metadata.generation and metadata.resourceVersion, even when the requested normalized relationships equal the current values. The command fully validates the target record under its goal lock and rejects relationship changes while an attempt is active, because attempts are bound to the goal generation and portable state digest. It writes the authoritative goal.yaml first and refreshes the replaceable README projection last.

Relationship updates reject a newly introduced cycle or an expansion of an existing cycle for the affected edge kind. Existing unrelated cycles do not block a repair, and shrinking the target’s existing cycle is allowed.

Cycle prevention is deliberately snapshot-scoped. The command assembles a catalog view by reading each member under that member’s per-goal lock, then validates and writes the target under its lock; it does not take a catalog-wide lock. Two coordinators that concurrently change different goals can therefore each validate before the other write and jointly create a cycle. This is the accepted consequence of independent per-goal locking and the single- coordinator ownership model, not a serializable graph transaction. After the writers settle, a subsequent graph call reports the cycle deterministically so a coordinator can revise one edge.

Task scheduling, live agent topology, messages, and runtime state remain responsibilities of the agent harness. The local tool stores durable goal relationships and evidence provenance as ordinary resources.

The YAML resources follow Kubernetes API conventions so a future adapter can map them to CRDs. Local files are not directly applicable cluster objects. Cluster use would still require structural CRDs, API-server-owned metadata, status-subresource behavior, and a controller or client that maps Markdown artifacts and local annotations.

That adapter would replace the filesystem lock and rename mechanism with API-server concurrency. It must not carry the local lock files or emulate the filesystem backend inside Kubernetes.

1.10.8 - Goal command

CLI for versioned local goal records

goal is the command surface for the repository goal skill. Portable resource types and domain validation live in api/v1alpha1; deterministic local persistence lives in internal/fsstore. The command keeps authoritative Kubernetes-inspired YAML envelopes and digest-bound attempt Markdown separate from the bounded generated README.md projection, uses the same record format for workspace and project goals, and stores session focus separately under ignored workspace scratch.

The record layout is:

goals/<goal-id>/
  goal.yaml
  criteria.yaml
  criteria-revisions/<revision>.yaml
  README.md
  attempts/<attempt-id>/
    attempt.yaml
    plan.md
    result.md
    evidence/

<owner-root>/goals/<goal-id>/ is the preferred project placement, not a CLI constraint. Direct initialization, promotion, and migration also accept other safe in-workspace goals roots while recording the explicit owner root.

The YAML objects use apiVersion: goals.alwaldend.com/v1alpha1 and the kinds Goal, GoalCriteria, GoalAttempt, and GoalSessionBinding. Their envelopes validate Kubernetes-compatible qualified metadata keys and label values and use object-shaped local goal references. The shared API treats resourceVersion as opaque. The filesystem backend allocates canonical local numeric versions and requires complete persisted metadata. The files are not raw kubectl input, and this project supplies neither CRDs nor a controller.

Run it through Bazel:

bazel_agent bazel run //projects/goal/cmd/goal -- init \
  --goals-root out/example/goals \
  --goal-id verify-the-release \
  --title "Verify the release" \
  --criterion "All affected tests pass"

Use a task-specific binding directory when changing session focus:

bazel_agent bazel run //projects/goal/cmd/goal -- attach \
  --session-root out/example/goal-sessions \
  --session-id current \
  --goal-dir out/example/goals/verify-the-release

GoalSessionBinding.spec.goalRef contains the stable object name. The namespaced annotation goals.alwaldend.com/local-goal-ref contains the workspace-relative storage path. Session bindings never create a repository- global catalog.

Goal.metadata.annotations[goals.alwaldend.com/local-owner-root] contains the workspace-relative owner used only by the local adapter. It is deliberately absent from portable Goal.spec and portable digests.

Commands are init, list, resume, show, attach, checkpoint, learning-proposal, graph, set-relationships, validate, promote, render, and migrate. set-relationships replaces the complete dependency and supersession lists; the parent is preserved unless explicitly set or cleared. It requires no active attempt, advances Goal generation and resource version on every accepted request, and refreshes the bounded README projection. Its cycle check is a per-goal-locked catalog snapshot rather than a catalog-wide transaction, so a graph call after concurrent writes settle is authoritative.

resume requires --catalog, resolved relative to --goals-root, and prints a bounded GoalResumePacket containing only open goals with a resumable attempt. The packet carries candidate paths and structured continuation fields; it never mutates records or opens goal plans, results, or evidence. The strict decoder validates catalog structure and its stored digest, not freshness against current goal records. Use show --goal-dir for current local state.

learning-proposal validates one Phase 5 proposal. Repeated friction references are required, but the command never promotes the proposal or edits source; the owning project adopts it through ordinary review and delivery.

checkpoint starts or publishes an attempt, changes execution/outcome state, or applies a complete desired criteria-items file with --criteria-file.

For ordinary work, initialize the objective and acceptance once with init --title ... --criterion ..., then use an inline checkpoint:

bazel_agent bazel run //projects/goal/cmd/goal -- checkpoint \
  --goal-dir out/example/goals/fix-parser \
  --expected-resource-version 1 \
  --subject "candidate digest or source revision" \
  --summary "Parser repaired; focused checks remain unverified." \
  --next-action "Run the parser acceptance check."
bazel_agent bazel run //projects/goal/cmd/goal -- show \
  --goal-dir out/example/goals/fix-parser

--summary is nonblank UTF-8 Markdown, limited to 8192 bytes, and requires --subject and --next-action. It cannot combine with --plan-file or --result-file. The store generates the initial plan from the objective, criteria, and next action, then writes progress into the existing canonical result.md. Later checkpoints reuse the open attempt, preserve its initial plan and imported evidence, and update the declared subject and next action. Changing an existing subject requires a replacement summary or result; retained evidence applies only to the candidate identified in that evidence. A next-action-only checkpoint is also supported.

show includes activeAttempt with current continuation fields, an 8192-byte UTF-8 result preview, complete result byte count/digest, evidence digests, observation time, and source paths relative to the goal directory. Its resultTruncated field indicates when the canonical result needs a separate read. Subject and progress are caller declarations, not live Git observations or criterion verdicts. Initialization, summary checkpoints, and bounded views use the same store and recovery protocol as detailed attempts; there is no separate compact record format. Closing still requires an explicit --close-attempt --review-file with criterion verdicts and evidence; a summary does not imply acceptance.

Detailed attempts can provide separate plan, result, and review payloads. Plans are durable summaries in Goal.status.plans. Create one with --plan-id ... --plan-strategy ... --plan-only; transition the active plan with --plan-id ... --plan-state accepted|rejected|superseded --plan-only, adding --plan-rejection-reason for a rejection. A newly created active plan supersedes the prior active plan. Attempts may bind to a plan with --plan-id when starting or by using the active plan of an existing attempt. Criteria updates require paused execution and use ordinary atomic file replacement. Immutable criteria snapshots retain the exact canonical criteria revision for historical attempts; portable, domain-separated criteria and goal-state digests avoid binding durable records to local resource-version tokens. Closing an attempt requires --review-file with an accept, refine, or reset decision and per-criterion verdicts linked to frozen plan, result, or evidence artifacts. The review file is plain YAML with exactly two keys. Criteria entries must be sorted by criterionID, and evidenceRefs must be unique, sorted, and name only frozen artifacts (plan.md, result.md, or files under evidence/). Verdicts are pass, fail, or unverified; a non-unverified verdict requires at least one evidence reference. Do not add apiVersion or kind headers:

decision: accept
criteria:
  - criterionID: friction-baseline
    criterionRevision: 1
    verdict: pass
    evidenceRefs:
      - evidence/friction-baseline.md
  - criterionID: optimization-pipeline
    criterionRevision: 1
    verdict: pass
    evidenceRefs:
      - evidence/optimization-pipeline.md

An achieved outcome must close an accepting attempt whose exact passes cover every current required criterion. Structured verdicts are kept in attempt.yaml; richer narrative stays in result.md.

For attempt and lifecycle checkpoints, a new attempt is fully staged before goal.yaml advances its resource version. That goal write is the optimistic- concurrency commit point; canonical attempt content follows, and README.md is last. An immediately closed new attempt uses an intermediate active pointer until its directory is published and the Goal is finalized at the same resource version, so interruption at either gap fails validation. The store returns the committed Goal reference after any post-commit failure, and the CLI error identifies that resource version.

Promotion also requires a paused workspace goal and preserves the goal name, portable input bindings, immutable criteria history, and content-digest provenance. It rejects known absolute workspace/file links in promoted attempt artifacts; callers remain responsible for semantic privacy and credential review.

Migration is a non-destructive import, not an in-place conversion. The legacy source remains unchanged, while a complete validated record is published at <destination-goals-root>/<goal-id> with one final directory rename. Repeating the same import is idempotent only while source provenance and import options match the existing target.

bazel_agent bazel run //projects/goal/cmd/goal -- migrate \
  --source-goal-dir out/example/legacy/verify-the-release \
  --destination-goals-root out/example/imported/goals

Mutations to an existing Goal’s canonical state take an exact expected local resource version. Cooperating processes serialize them with an advisory lock keyed to the canonical goal path under $XDG_RUNTIME_DIR/alwaldend/goal/locks/, reread the manifest while holding the lock, and replace individual files by renaming sibling temporary files. Lock files are outside the workspace and cannot enter version control. Different goals do not share a lock. Local owner and session-link annotations are workspace-relative normalized paths; absolute host paths are never written to manifests or command output.

Each individual file replacement is atomic; commands that update several files do not claim cross-file transaction semantics. README.md is a derived projection and is written last. Plan, result, and evidence Markdown is instead canonical through the SHA-256 artifact manifest in attempt.yaml. Direct file writers are outside this cooperative trust boundary, and digest validation makes later edits detectable. Execution and outcome transitions advance status.lifecycleGeneration, invalidating in-flight attempt input bindings.

This experimental v1alpha1 format is a local file protocol. One coordinator should own a goal record. Delegated workers write only to isolated scratch; the coordinator imports selected artifacts through checkpoint.

1.10.9 - Goal evaluations

Goal evaluations

This suite records the semantic contract for persistent, evidence-backed goal pursuit. The required offline Bazel target validates the Promptfoo configuration, referenced cases, and staged skill without making a model call. The cases cover research routing, workspace-versus-project ownership, explicit session focus, stale-update reconciliation, honest acceptance, result-prioritized modular work, isolated candidate promotion, and critical-path delegation, compact local checkpoints, meaningful publication milestones, and explicitly requested remote backup. Concurrency cases require active delegation when a long-running goal exposes multiple independently reviewable workstreams, require a recorded reason for sequential execution, and reject fanout whose only purpose is occupying available slots. The interruption case distinguishes turn priority from lifecycle state: questions and additional tasks do not silently stop an already-authorized active goal or expand its authority.

A live target is omitted because representative behavior spans multiple turns and requires filesystem tools, safe writable fixtures, and fresh-session resume. A tool-free single response cannot verify those longitudinal postconditions. Promptfoo validation therefore proves only that these assets load. Deterministic store behavior is covered by //projects/goal/internal/fsstore:go_test; a future model eval still needs an isolated multi-turn workspace fixture.

The static storage case covers the ordinary one-goal boundary: one path-keyed goal lock plus atomic per-file rename. Promotion and migration use a separate two-path protocol that acquires distinct source and destination locks in canonical-path order.

1.11 - Hugo Landing

Reusable Hugo landing site for project pages

hugo_landing packages a reusable Hugo landing site. al_hugo_landing combines the shared source with one project README and emits a Hugo-ready source archive. al_hugo_landing_site also builds the rendered site.

al_hugo_landing(
    name = "landing_site",
    docs = "//projects/goal:docs",
    project = "goal",
    title = "Goal",
    docs_url = "https://alwaldend.com/docs/projects/goal/",
    repository_url = "https://github.com/alwaldend/src",
)
al_hugo_landing_site(
    name = "site",
    docs = "//projects/goal/docs:docs",
    project = "goal",
    title = "Goal",
    docs_url = "https://alwaldend.com/docs/projects/goal/",
    repository_url = "https://github.com/alwaldend/src",
)

Each project owns its rendered landing target at //projects/<project>/landing:site. The shared macro remains in hugo_landing so the visual shell and README-to-site transformation stay reusable.

Agent workflow: Add a project site.

projects/projects.bzl lists the dedicated project sites; the project directory links to each site. The existing alwaldend.com apex site covers that project. Nested rules modules use //projects/hugo_landing/landing:<project> targets in the root workspace.

README-relative links lead to their source files on GitHub, and relative images load from the matching source directory. Literal template examples are preserved; Hugo shortcodes requiring the full documentation site are omitted.

Build and validate all sites from the repository root:

bazel_agent bazel test //projects:landings //infra/dns:config_test

The authenticated deployment command uses the operator’s Git executable and GitHub authentication. It intentionally accesses GitHub at runtime; builds do not deploy. Supply an absolute, task-owned scratch directory:

bazel_agent bazel run //projects:deploy_landings -- --scratch /absolute/worktree/out/site-rollout/git

Each site is pushed to alwaldend/<project-slug>-landing on the pages branch with CNAME and .nojekyll. Existing branch history is preserved, unchanged sites produce no commit, and empty repositories can be bootstrapped. Use --dry-run to stage and compare without pushing. The deployment tool validates every input before publishing and stops on the first failed project. Add --project <project_id> to publish only one registered site.

Repository creation and Pages settings belong to GitHub Terraform. DNS records belong to projects/<project>/dnsconfig.json and are applied through DNSControl. Review each plan or preview and apply only the authorized project-site changes. Verify the published commit, Pages build, DNS, and HTTPS response before calling a rollout complete.

1.12 - Infinitime

InfiniTime firmware fork with a text watchface and Pomodoro app

This InfiniTime firmware fork adds a text watchface and a Pomodoro app. The repository packages the pinned firmware source and its build dependencies.

  • Extra Watchface: Text
  • Extra app: Pomodoro
  • C++, embedded

The root workspace declares the pinned firmware with use_repo_rule in include.MODULE.bazel, preserving recursive Git submodules and the CMake toolchain patch. Firmware source is fetched when referenced, rather than during module resolution. Its Python/npm lockfiles and SDK archives retain the upstream pins; Python and Node runtimes use the root workspace toolchains. The project re-exports pip and npm with separate extension identities so unrelated Python/npm targets do not fetch firmware to read those lockfiles. The isolated pip extension declares the Linux x86_64 host platform used by the pinned ARM compiler archive. bazel mod deps deliberately evaluates all extensions and can still fetch it.

Validate the firmware with bazel test //projects/infinitime:build_test.

  • Install Gadgetbridge
  • Download the firmware:
    oras pull docker.io/alwaldend/src:projects_infinitime_pinetime_mcuboot_app_dfu_1_15_0_zip_head
    
  • Pair the watch in Gadgetbridge
  • Install the firmware

1.12.1 - Releases

Releases

1.12.1.1 - head

Release head

1.13 - Kustomization

Kubernetes resources for Flux, Traefik, and cert-manager

This project contains Kubernetes Kustomization resources for Flux, Traefik, and cert-manager. It is still in progress.

1.13.1 - Releases

Releases

1.13.1.1 - head

Release head

1.14 - Leetcode downloader

LeetCode submission export and documentation tools

This project exports LeetCode submissions and generates documentation from submission files using a CLI and Bazel rules. A Tampermonkey script provides a browser-based download path; direct CLI downloads are currently blocked by LeetCode bot protection.

  • CLI and bzl code to generate submission docs
  • Tampermonkey script to download submissions
  • CLI to download submissions (Doesn’t work because of bot protection)
bazel run //projects/leetcode_downloader -- \
    --submissions-file "${PWD}/out/submissions.json" \
    --root-dir "${PWD}" \
    generate
Usage of flags:
  -base_url string
    	 (default "https://leetcode.com")
  -cookie string

  -limit uint
    	 (default 20)
  -offset uint

  -root-dir string
    	 (default "${PWD}")
  -submissions-file string

1.14.1 - Bzl

Bazel code

1.14.1.1 - al_leetcode_submissions

al_leetcode_submissions

load("@com_alwaldend_src//projects/leetcode_downloader/main/bzl:al_leetcode_submissions.bzl", "al_leetcode_submissions")

al_leetcode_submissions(name, srcs, visibility, **kwargs)

Generate leetcode submission targets

PARAMETERS

Name Description Default Value
name generated md archive name none
srcs leetcode submission configs none
visibility visibility None
kwargs kwargs for template_files none

1.14.2 - Proto

Protobuf contracts

1.14.2.1 - contracts

Proto docs for contracts.proto
load("@rules_java//java:defs.bzl", "java_library")

java_library(
    name = "name",
    deps = [
        "@com_alwaldend_src//projects/leetcode_downloader/main/proto/contracts:contracts_java_library",
    ],
)
load("@rules_go//go:def.bzl", "go_library")

go_library(
    name = "name",
    deps = [
        "@com_alwaldend_src//projects/leetcode_downloader/main/proto/contracts:contracts",
    ],
)
syntax = "proto3";

option go_package = "git.alwaldend.com/alwaldend/src/projects/leetcode_downloader/main/proto/contracts";

enum CliAction {
  DOWNLOAD = 0;
  GENERATE = 1;
  UPDATE = 2;
}

message Config {
  string base_url = 1;
  string cookie = 2;
  repeated string action_args = 4;
  CliAction action = 5;
  uint64 offset = 6;
  uint64 limit = 7;
  map<string, SubmissionConfig> submissions = 8;
  string root_dir = 9;
  map<string, string> headers = 11;
  string submissions_file = 12;
  bool write_code = 13;
}

message SubmissionConfig {
  string dir = 1;
  string extension = 2;
  repeated string types = 3;
}

message Submission {
  uint64 id = 1;
  string status_display = 2;
  string lang = 3;
  uint64 question_id = 4;
  string title_slug = 5;
  string code = 6;
  string title = 7;
  string url = 8;
  string lang_name = 9;
  // string time = 10;
  uint64 timestamp = 11;
  uint64 status = 12;
  string runtime = 13;
  string is_pending = 14;
  string memory = 15;
  string compare_result = 16;
  bool has_notes = 17;
  uint64 flag_type = 18;
}

message SubmissonsResponse {
  repeated Submission submissions_dump = 1;
  bool has_next = 2;
  string last_key = 3;
}
message SubmissonsStorage {
  repeated Submission submissions = 1;
}

1.14.3 - Releases

Releases

1.14.3.1 - head

Release head

1.15 - MCP Cordis

Workspace-local runtime packages behind a stable MCP server

mcp_cordis is a standalone stdio MCP server that mounts runtime JavaScript packages through Cordis. It is intentionally an MCP server, not a Codex plugin bundle.

Reusable definitions are ordinary ESM files in projects/mcp_cordis/plugins, listed by projects/mcp_cordis/cordis.yaml. Disposable definitions use the same layout under out/<task>/mcp_cordis/runs/<run>/. Each run writes a bounded manifest with explicit task, run, worker, information, budget, retention, lock, and cleanup fields. AGENT_TASK_ID, AGENT_RUN_ID, and AGENT_WORKER_ID may provide stable identities; the launcher otherwise creates process-scoped identities. Every package is addressed by both scope and name, so a scratch package never silently shadows a reusable package.

The repository’s .codex/config.toml registers mcp_cordis as a project-scoped stdio server. Codex loads that file for a trusted workspace and finds the active Git worktree before starting the server. Separate clones and worktrees therefore use their own source, projects/mcp_cordis packages, and task/run-namespaced scratch packages. Trusting the repository’s root checkout also covers its linked worktrees; a glob trust entry is neither needed nor supported. A new Codex session is needed after the MCP registration itself is first added; package changes after that do not require another session.

The registration calls cmd/mcp_cordis/launch.sh. With a current installed bazel_agent, the launcher selects a content-addressed runtime from the per-user tool cache and executes it directly. The first exact source version is built and atomically installed under a per-key lock; subsequent worktrees with the same inputs do not start Bazel or load a configured graph. An older runner falls back to asking Bazel for a launch script under the task’s ignored out directory. Either path releases Bazel’s output-base lock before the long-lived stdio server starts, so builds and tests can run normally while Codex remains connected.

The cached artifact contains the stable server runtime and pinned JavaScript dependencies, but not cordis.yaml or reusable plugins. It always reads those from the explicit active workspace, so editing a package changes live behavior without repackaging the runtime or selecting a new cache key.

The same project configuration starts an optional asynchronous SessionStart hook that starts the worktree’s Bazel server and warms repo_delivery. It produces no session context, ignores failure, and never queries the whole workspace graph. Cordis itself is already warmed by its MCP launch path, so the hook does not start a duplicate Cordis build.

To build and run the server directly from the repository root:

bazel_agent bazel run //projects/mcp_cordis:mcp_cordis -- \
  --workspace-root "$PWD" \
  --task-id example-task \
  --run-id example-run

The workspace root is mandatory unless BUILD_WORKSPACE_DIRECTORY is present. The checked-in launcher resolves the current Git worktree explicitly and supplies that path to the server.

The fixed cordis_* tools define, start, inspect, invoke, update, stop, remove, and promote packages without reconnecting the MCP client. Package handlers are called through cordis_invoke; this remains reliable even when an MCP client caches its initial tool list.

cordis.yaml uses the standard Cordis Include entry-list format:

- id: hello
  name: ./plugins/hello.mjs

The referenced file is a normal ESM Cordis plugin:

const plugin = {
  description: "Provide a greeting.",
  apply(ctx) {
    ctx.tool(
      {
        name: "hello_world",
        description: "Return a greeting.",
        inputSchema: {
          type: "object",
          properties: { name: { type: "string" } },
          additionalProperties: false,
        },
      },
      ({ name = "world" }) => ({ greeting: `Hello, ${name}!` }),
    );
  },
};

plugin.apply.description = plugin.description;

export default plugin;

Cordis normalizes an object plugin to its apply callback. Attaching the optional package description to that callback exposes it through cordis_list and cordis_inspect; tool descriptions remain part of each ctx.tool() definition.

The server mounts the official Cordis Loader, Include, and HMR services. cordis_define syntax-checks and atomically persists the ordinary module. Creating or enabling an entry refreshes any cached module through Cordis HMR, then uses the public Include refresh API and waits for activation. Updating an already-running entry returns activation: "pending"; poll cordis_invoke or cordis_list_tools until the new behavior is visible. The reproducibly pinned HMR package carries a focused pnpm patch that serializes module reloads and drains source changes arriving during an in-flight reload, so the latest persisted source is not lost.

Syntax errors are rejected before the file changes. Evaluation and apply() failures follow native Cordis HMR behavior; the wrapper does not add a second activation transaction around them. It also does not inject source markers, inspect Loader caches, correlate watcher events, or maintain its own source rollback/version store. Reusable history is normal Git history. Manual edits to watched plugin files are also picked up by Cordis HMR.

Runtime modules use normal Cordis semantics, including static imports, top-level await, and asynchronous apply(ctx, config). Package code is trusted: a never-settling module evaluation or activation can therefore stall Cordis lifecycle work. The stdio launcher reserves its protocol stream and redirects package stdout to stderr, keeping accidental console.log() calls off the JSON-RPC wire.

The package context exposes ctx.workspaceRoot, ctx.resolveWorkspace(), ctx.readText(), and structured ctx.exec() in addition to ctx.tool(). ctx.exec() returns code, signal, stdout, stderr, truncated, and outputLimitExceeded; maxBytes is a combined stdout/stderr budget. By default, exceeding that budget or producing invalid UTF-8 rejects with EXEC_OUTPUT_LIMIT or EXEC_INVALID_UTF8. Packages that explicitly set allowTruncatedOutput: true instead receive the valid retained prefix with truncated set; outputLimitExceeded distinguishes the byte cap from UTF-8 loss. A Fiber-owned supervisor admits each launch atomically, and results settle only after the direct child and every live member of its original Linux process group have stopped. Limits, timeouts, and plugin disposal use the same cleanup path. A process that deliberately creates a new session escapes that group and is outside this trusted-package contract. ctx.exec() therefore fails closed with EXEC_UNSUPPORTED_PLATFORM away from Linux. Package code also has normal Node built-ins; this host is a reliability boundary, not a security sandbox.

cordis_invoke.timeout_ms bounds how long the gateway waits for a result; it does not cancel an already admitted JavaScript handler. The handler keeps its Fiber lease until it finishes, so stop, remove, and shutdown wait for it. Cordis HMR waits for a retired Fiber to finish draining before it activates and publishes the replacement, so a live invocation can delay a reload. Any ctx.exec() launched by a timed-out invocation is cancelled and its process group is confirmed stopped before the timeout response settles.

  • repo_context: bounded repository reads and searches.
  • git_worktree: read-only branch, status, log, and comparison snapshots.
  • network_probe: DNS, TCP/TLS, and HTTP diagnostics.

These were selected from aggregate recurring task categories in recent local sessions. No transcript content, credentials, or private outputs are included.

Future runtime-extension work should resume from the maintained runtime extensions goal, which records acceptance criteria, decisions, failed attempts, and supporting evidence.

The runtime directly uses @deepseek-ai/cordis, its official Loader, Include, HMR, and Timer plugins, and the Model Context Protocol TypeScript SDK. Their license texts are retained in the resolved package artifacts by the pinned pnpm/Bazel dependency graph.

1.15.1 -

MCP Cordis goal

This is a durable project goal. Future work should resume from the current attempt and preserve accepted evidence and strategy changes here.

Deliver a standalone, workspace-local MCP server at projects/mcp_cordis that reuses Cordis for hot runtime packages, persists reusable packages in the project, stores disposable packages under out/mcp_cordis, and ships useful non-sensitive starter packages derived from recurring past-session work.

Complete: the delivered MCP is a thin wrapper around official Cordis Loader, Include, HMR, and Timer packages. Reusable modules use project-local cordis.yaml; disposable modules use ignored workspace output. The final hosted review corrections bind repository reads, searches, directory inspection, and Git commands to verified file or directory handles, bound permanent process-inspection failures, and remove a process-start timing assumption from cleanup coverage.

  • Delivered candidate: attempt-11/exact-consolidated-rebase
  • Rejected parent commit: 7cfef0719075ad372c3bb257ad216b35770356b2
  • Rejected parent tree: 34153eca0f582af5c641f81bf8c7209b0045ab9a
  • Current fetched and rebased base: 63e7b9f0be1e054373415914ff3d2ea2282aa3da
  • Published candidate: PR 32
  • Stage: delivered and review-reconciled
  • Last accepted checkpoint: exact aggregate published on PR 32 with the delivery receipt verified against the remote branch and PR
  • Failing or unverified criteria: none
  • Dominant issue: none
  • Exact next action: merge PR 32 when desired
  1. Complete: complete read-only preflight and choose the package/build boundary.
  2. Complete: scaffold the project and pin dependencies reproducibly.
  3. Complete: implement runtime lifecycle, stable MCP tools, and two-tier persistence.
  4. Complete: make all starter packages pass executable tests.
  5. Complete: make lifecycle evidence deterministic and publish PR 32.
  6. Complete: integrate PR 24’s projects/agents changes without regressing newer main-branch guidance.
  7. Complete: correct all three valid review findings with regression tests.
  8. Complete: independently review Attempt 4; verdict was refine.
  9. Complete: correct the independent-review gaps in Attempt 5 and pass the focused, integrated, build, validation-aspect, and Buildifier gates.
  10. Complete: obtain independent review; verdict was refine.
  11. Complete: implement Attempt 6’s lifecycle, compatibility, package, and skill-policy corrections, including the second-review strategy reset.
  12. Complete: reject the custom package-manager architecture after the user’s standard-solution review and freeze Attempt 7.
  13. Complete: implement official Cordis Loader, Include, HMR, normal modules, and standard cordis.yaml storage.
  14. Complete: rerun every invalidated focused and integrated validation gate and obtain fresh independent review. Review accepted c05bd45a with no actionable findings.
  15. Complete: rebase, validate the exact aggregate commit, republish PR 32, resolve its review threads, and verify the remote candidate. The remote head matched the accepted local candidate after publication.
  16. Complete: correct the hosted review’s recursive fallback, byte-offset, and UTF-8 preview findings; pass focused regressions and the complete MCP test/build/Buildifier packet.
  17. Complete: correct the follow-up review’s Unicode case-fold, explicit file/glob, and partial-startup listing findings; rerun the same gates.
  18. Complete: correct unavailable-scope and bounded-read endpoint findings; use fresh diff scrutiny to fix repeated-startup error loss and natural-body UTF-8 handling; update repo-delivery to require correctness revalidation after code changes.
  19. Complete: replace the rejected transactional source-HMR protocol with atomic persistence plus Cordis HMR and reproduce the remaining native HMR overlap race independently.
  20. Complete: serialize and drain HMR reload work in the reproducibly pinned dependency, retain the fallback corrections, and rerun every invalidated local delivery gate.
  21. Complete: consolidate the exact owned range, reconcile the advanced base’s skill-discovery and goal layout, validate the literal rebased candidate, publish it, and reconcile hosted review.

1.15.1.1 -

Acceptance criteria

Back to durable goal

  1. projects/mcp_cordis is a documented, Bazel-built standalone MCP stdio server and is not coupled to a Codex plugin manifest.
  2. The server demonstrably uses Cordis lifecycle primitives rather than a separately invented plugin framework.
  3. One connected MCP client can define, start, inspect, invoke, update, stop, and remove a runtime package without restarting the server.
  4. MCP source writes are syntax-checked and atomically persisted. Existing running entries are handed to Cordis HMR without a private acknowledgement protocol. The MCP does not promise synchronous activation, broad activation rollback, or restoration of prior on-disk bytes. Native Cordis failure behavior remains intact. The pinned HMR dependency serializes reload work and drains later observed writes so an in-flight replacement cannot discard the latest persisted source. Git owns reusable source history; the runtime does not invent a second version store.
  5. Reusable package source is stored beneath projects/mcp_cordis/plugins; disposable source and configuration resolve beneath the current workspace’s out/mcp_cordis.
  6. Reusable packages reload after an MCP server restart. Disposable packages have an explicit promotion path into the reusable library.
  7. At least three useful, non-sensitive starter packages are justified by recurring prior-session tasks and have executable tests.
  8. Stable gateway tools allow immediate invocation even if a particular MCP client does not refresh dynamically registered schemas.
  9. Focused tests, builds, repository formatting checks, and an end-to-end MCP transcript pass for the exact delivered candidate.
  10. On Linux, ctx.exec() results, execution timeouts, and plugin disposal settle only after the direct child and live members of its original process group stop. A trusted package that deliberately creates a new session is explicitly outside that guarantee; unsupported platforms fail closed. cordis_invoke.timeout_ms is a response deadline, not handler cancellation; the admitted handler retains its Fiber lease until completion.
  11. Trusted Codex sessions discover the MCP from the checked-in .codex/config.toml in the active clone or linked worktree. Server startup releases Bazel’s output-base lock before serving stdio, and source plus disposable state remain scoped to that worktree.
  • Unit tests cover validation, standard Cordis entries, lifecycle disposal, persistence roots, eventual reload, and promotion.
  • An MCP integration test drives initialize/list/define/run/invoke/update/stop over stdio without restarting the process.
  • A restart test proves reusable package recovery.
  • Package tests execute every starter package through the same runtime path.
  • Process regressions cover normal results, output limits, valid UTF-8 prefix retention, timeout, disposal, and rejection of launches after disposal.
  • HMR regressions write a second generation during slow top-level evaluation and slow asynchronous activation, then require convergence to the latest persisted generation.
  • Bazel query, test, build, Buildifier, and git diff --check cover repository integration.
  • A launcher probe starts the generated-script MCP and runs a second Bazel command concurrently in the same linked worktree.
  • git diff --check
  • Focused //projects/mcp_cordis:all Bazel tests and build
  • //:buildifier_test after every BUILD or Bzlmod change
  • End-to-end stdio lifecycle and restart tests

1.15.1.2 -

Artifact log

Back to durable goal

  • Attempt 10 plan: dependency-owned reload serialization with deterministic slow-evaluation and slow-activation regressions. Review verdict: focused tests pass; complete delivery evidence remains open.
  • Pinned HMR patch: standard pnpm patch that serializes the package’s module reload task and drains newly stashed URLs. Review verdict: exact-package apply check and focused regressions pass.
  • Attempt 9 plan: atomic persistence plus official Cordis Include/HMR, with the custom source-marker and acknowledgement transaction removed. Review verdict: refine after reproducing an HMR overlap race.
  • Attempt 8 review corrections: fail-closed recursive fallback, UTF-8 byte offsets, and valid-prefix HTTP previews. Review verdict: accepted locally with focused and complete package evidence.

  • Attempt 7 current record: official Loader, Include, and HMR architecture using cordis.yaml and normal ESM modules. Review verdict: active replacement candidate; exact delivery gates remain open.

  • Attempt 6 historical record: rejected worker/version-store architecture, its package hashes, and focused evidence. Review verdict: superseded by the standard Cordis architecture in Attempt 7.

  • Attempt 5 candidate and validation packet: exact implementation, immutable hashes, and current test/build results. Review verdict: rejected by the completed independent review.

  • Attempt 5 plan: exact response to independent review’s semantic and evidence gaps. Review verdict: proceed.

  • Current MCP Cordis README: documents standard Cordis config, ordinary reusable modules, disposable out modules, HMR, and the bounded ctx.exec() contract. Review verdict: current working-tree interface.

  • Imported decision-review skill: immutable PR 24 instruction payload, now packaged with current offline validation. Review verdict: Bazel validation passes.

  • Attempt 3 commit: immutable published candidate. Review verdict: rejected as final after review.

  • PR 32: evolving delivery vehicle for the runtime-extension goal.

  • PR 24: provenance for the newly requested projects/agents subtree. Review verdict: import its four scoped changes only, merged against the current base.

  • Attempt 4 plan: frozen hypotheses, boundaries, and gates for the import and initial review corrections. Review verdict: rejected as a final candidate by independent source review.

  • Attempt 3 evidence: OIDs, direct rebase parent, forced test/build/format results, and the historical delivery state. Review verdict at the time: accepted locally, then superseded after publication by three valid review findings.
  • Attempt 3 record: preserved implementation and user-facing interface evidence for that historical local candidate. Review verdict: accepted at the time, then superseded by review findings.
  • Attempt 2 evidence: exact task-only rebase evidence for commit e3e74cb1 onto 7ad2704c. Review verdict: accepted as rebase evidence, not as the final candidate because integrated lifecycle evidence was nondeterministic.
  • Attempt 2 record: preserved documentation and evidence for the rebased server and runtime interface. Review verdict: implementation retained for Attempt 3; final validation was pending.
  • Attempt 1 record: preserved runtime/interface artifact. Review verdict: rejected as a final candidate because one included package had an undeclared runtime dependency.

1.15.1.3 -

Attempt history

Back to durable goal

  • Attempt 11: consolidate the owned range, reconcile the advanced base, validate and publish the exact rebased candidate, then incorporate and reconcile the final hosted review. Complete.
  • Attempt 10: keep the thin wrapper and patch pinned Cordis HMR to serialize reloads and drain writes arriving during an in-flight reload. Complete locally and carried into Attempt 11.
  • Attempt 9: simplify source updates to validated atomic persistence plus Cordis HMR, deleting the private acknowledgement transaction. Refined after independent review reproduced a lost overlapping update.
  • Attempt 8: correct the final hosted review’s fallback filtering, byte-offset, and UTF-8 body-preview findings. Complete locally.
  • Attempt 7: replace the custom manifest/version store and worker generations with official Cordis Loader, Include, HMR, standard cordis.yaml, and normal modules. Delivered, then refined by Attempt 8.
  • Attempt 6: make bounded execution backward-compatible, close process/lifecycle admission races, publish exact package completeness, and replace worker-side spawning after independent review. Rejected because its package persistence model was custom rather than standard Cordis.
  • Attempt 5: make every output-loss signal and bounded Git result exact, then cover the imported skill behaviors. Refine after independent review found lifecycle, compatibility, and policy defects.
  • Attempt 4: import PR 24’s scoped agent guidance, then correct the three valid PR 32 review findings. Refine after independent review.
  • Attempt 3: replace a lifecycle test’s elapsed-time inference with a deterministic started/release handshake. Published, then superseded by review findings.
  • Attempt 2: retained the proven runtime and added a bounded search fallback for hermetic portability. Starter packages pass; refine because the integrated lifecycle evidence was timing-dependent.
  • Attempt 1: direct Cordis runtime with MCP v2, worker-isolated generations, two-tier immutable persistence, and three starter packages. Rejected because one starter package required an unavailable executable.

1.15.1.3.1 -

Attempt 1

Back to durable goal · Attempt history

A small adapter around @deepseek-ai/cordis@4.0.1 can provide durable, transactional runtime packages behind a fixed MCP stdio surface without embedding DeepSeek Harness or restarting the MCP connection.

  • Parent checkpoint: task-start state of branch t3code/runtime-modifiable-plugin
  • Cordis: @deepseek-ai/cordis@4.0.1
  • MCP server/client: @modelcontextprotocol/server@2.0.0 and @modelcontextprotocol/client@2.0.0
  • Node: repository-pinned Node 24.13.0
  • Package source contract: one import-free JavaScript expression returning a Cordis plugin with apply(ctx)
  1. Add an ordinary Bazel package with a dedicated exact pnpm lock.
  2. Persist definitions as content-addressed immutable source plus atomic manifests under explicit project and scratch roots.
  3. Evaluate each generation in a worker, mount it through a real Cordis Context and Fiber, and register handlers through Cordis effects.
  4. Activate transactionally: prove the candidate ready, swap the active pointer, drain in-flight calls, then dispose the prior Fiber exactly once.
  5. Expose fixed MCP tools for list, inspect, define, run/reload, invoke, stop, remove, and promote; never rely on dynamic MCP schema refresh.
  6. Seed and execute repo_context, git_worktree, and network_probe through the same runtime path.
  • Explicit (scope, name) identities prevent hidden scratch/project shadowing.
  • Workspace root is an explicit CLI argument or BUILD_WORKSPACE_DIRECTORY, never inferred from a runfiles cwd.
  • A failed candidate never changes the active manifest or runtime pointer.
  • Package stdout/stderr cannot corrupt MCP stdout.
  • Disposable state remains under ignored out/mcp_cordis; reusable source is public project code.

Refine. Candidate c9300c9887104777c8915e3d4f390196604e9bd18497bbec319415d1a4ad057f proved the architecture but failed acceptance criterion 7.

  • Added the exact pnpm/Bzlmod/Bazel package and documentation.
  • Implemented content-addressed storage, worker-isolated Cordis Fibers, transactional generation replacement, fixed MCP gateways, and stdio entry.
  • Added project and scratch scopes, promotion, recovery, and three starter package definitions.
  • Added lifecycle, in-memory MCP, subprocess stdio, and package execution tests.
  • bazel_agent bazel query //projects/mcp_cordis:all: pass after the pnpm v10 declaration and starter catalog were present.
  • bazel_agent bazel test //projects/mcp_cordis:runtime_test: pass. This covers real Cordis contexts/effects, immutable versions, rollback, drain, scopes, promotion, restart, removal, isolation, and fixed MCP invocation.
  • bazel_agent bazel test //projects/mcp_cordis:stdio_test: pass. One stdio client hot-updated v1 to v2 without a process change; a new server process recovered the project package.
  • bazel_agent bazel test //projects/mcp_cordis:starter_packages_test: fail because repo_context_search received spawn rg ENOENT in the hermetic test PATH.
  1. Pass: documented standalone stdio server built and exercised by Bazel.
  2. Pass: source and runtime tests use Cordis Context, Fiber await/dispose, and effect cleanup.
  3. Pass for implemented lifecycle operations; fixed MCP use is proven on one connection.
  4. Pass: content hashes, failed syntax/startup rollback, and v1/v2/v3 behavior are exercised.
  5. Pass: roots and exact scope identity are exercised in isolated workspaces.
  6. Pass: promotion and server-only project recovery are exercised.
  7. Fail: the Git and network package paths were not reached after the repository search package required an unavailable rg executable.
  8. Pass: in-memory and real stdio tests invoke new handlers through the stable gateway without reconnecting.
  9. Unverified: the full integrated fixed regression set has not run.
  • Criteria 1–6 and 8 improved from unverified to measured passes. Criterion 7 is an absolute portability failure, not merely a weaker result.
  • Passing lifecycle and stdio tests support retaining the direct Cordis, worker, storage, and fixed-gateway representation.
  • The highest-leverage problem is removing the starter package’s undeclared executable assumption while retaining ripgrep as a fast path.
  • Continue the architecture but revise repo_context_search; no evidence supports discarding the runtime foundation.
  • The largest avoidable delay was 144 seconds in a failed test whose worker was not registered for unconditional teardown. node:test cleanup now registers before assertions, reducing the next failure cycle to under a second.
  • The next feedback loop starts with the single starter target and only then returns to the integrated regression set.

1.15.1.3.2 -

Attempt 2

Back to durable goal · Attempt history

Attempt 1’s repo_context_search cannot execute when ripgrep is unavailable from the runtime PATH, preventing all starter packages from passing their portable Bazel execution test.

Keeping ripgrep as the preferred engine but falling back on a bounded Node filesystem search will preserve normal-machine speed and make the reusable package functional in hermetic or minimal environments.

  • Parent candidate: c9300c9887104777c8915e3d4f390196604e9bd18497bbec319415d1a4ad057f
  • Preserve all runtime, storage, MCP, and other starter-package code.
  • Add a bounded fallback with workspace path checks, file/byte/result limits, fixed or regex matching, context lines, and basic glob filtering.
  • Store it as a new immutable repo_context version; retain Attempt 1’s source version in its manifest history.
  • Rerun the starter test first, then the complete focused package checks.
  • Search succeeds without rg in Bazel’s test PATH.
  • Traversal outside the workspace remains rejected.
  • All eight starter tools execute through loaded Cordis Fibers.
  • Previously passing lifecycle and real stdio checks remain green.

Refine. The rebased candidate commit e3e74cb1e573867825347292bf17220a5b9a4a0c fixes criterion 7, but its final integrated regression failed because the lifecycle test used elapsed time to infer that an invocation remained in flight.

  • Added a bounded pure-JavaScript fallback as immutable repo_context version fd10633b1569665764e9a526f2cfaf38d1847ee9842934258cefc25f08ea9050 while preserving ripgrep as the preferred engine and retaining the original version in manifest history.
  • Rebased the complete task commit onto fetched remote master 7ad2704cd27757355ab36ec8eb1bb27ef9e1d91d with no conflicts. The resulting tree is 079a0c27b86527c6950cc75b0c8b9dbf572d3e4b.
  • Pre-rebase bazel_agent bazel test //projects/mcp_cordis:starter_packages_test: pass. All eight tools executed, including search without rg.
  • Post-rebase bazel_agent bazel query //projects/mcp_cordis:all: pass.
  • Post-rebase bazel_agent bazel test //projects/mcp_cordis:all: three of four test targets pass. runtime_test fails at its drain-count assertion with actual 0, expected 1.
  • The test starts a 150 ms invocation, waits only 20 ms, and then starts a new worker before swapping generations. Candidate startup has no upper bound below the old invocation’s delay, so the test does not prove the invocation is still active at the swap.
  1. Pass in the integrated build test.
  2. Unverified for final acceptance because the lifecycle regression did not complete.
  3. Unverified for final acceptance for the same reason.
  4. Unverified for final acceptance for the same reason.
  5. Pass in the previously focused storage/lifecycle evidence; final rerun is still required.
  6. Pass in the subprocess stdio target; final rerun is still required.
  7. Pass on the exact rebased candidate through the starter-package target.
  8. Pass on the exact rebased candidate through the stdio target.
  9. Fail: the complete fixed regression set is not green.
  • Criterion 7 measurably improved from fail to pass; no starter package now assumes ripgrep is installed.
  • The runtime representation did not regress. The failing value demonstrates that the old request finished before the atomic swap, which is permitted; the test’s elapsed-time setup failed to establish its own precondition.
  • The highest-leverage issue is evidence quality, not another runtime rewrite.
  • Attempt 3 should preserve all delivered runtime bytes and replace only the drain test’s wall-clock inference with a deterministic cross-worker latch.
  • The requested rebase and adapter compilation dominated this cycle’s wall time. Focused query feedback fell to under two seconds once caches were warm.

1.15.1.3.3 -

Attempt 3

Back to durable goal · Attempt history

The integrated lifecycle test assumes that a 150 ms invocation remains active after a new worker has started. Under parallel Bazel execution, the candidate can become ready only after that invocation has completed, making the expected drain count nondeterministic.

A file-backed started/release handshake in the test package will establish the in-flight precondition independently of worker startup speed and prove that a generation swap reports and drains exactly one old invocation.

  • Parent commit: e3e74cb1e573867825347292bf17220a5b9a4a0c
  • Parent tree: 079a0c27b86527c6950cc75b0c8b9dbf572d3e4b
  • Base commit: 7ad2704cd27757355ab36ec8eb1bb27ef9e1d91d
  • Preserve all product runtime, storage, MCP, package, and build files.
  • Extend only the lifecycle test fixture with optional started/release paths.
  • Wait for the started marker before activation, keep the old handler blocked until after the drain count is observed, and release it in finally so a failed assertion cannot strand teardown.
  • Rerun the focused lifecycle target first, then the entire recorded regression set on one amended candidate.
  • The test contains no fixed request duration or startup race.
  • Replacement reports exactly one draining call.
  • The old call returns v2 and the next call returns v3.
  • Cordis cleanup still runs exactly once.
  • All project, buildifier, and diff checks pass on the same commit tree.

Accept as the final local candidate. Commit 7cfef0719075ad372c3bb257ad216b35770356b2 and tree 34153eca0f582af5c641f81bf8c7209b0045ab9a pass the entire evidence plan. Remote delivery is pending separate authorization.

  • Replaced the 150 ms elapsed-time assumption with workspace-local started and release markers in the lifecycle test fixture.
  • Proved the new v3 generation serves calls while the old v2 invocation remains blocked, then released v2 and proved its Cordis effect disposes exactly once.
  • Applied Buildifier’s mechanical label ordering to the runtime test data.
  • Amended the sole feature commit through the delivery adapter without changing its direct base parent.
  • git diff --check HEAD^..HEAD: pass on the prepared commit.
  • bazel_agent bazel query //projects/mcp_cordis:all: pass.
  • bazel_agent bazel test //projects/mcp_cordis:runtime_test: pass after the deterministic gate.
  • bazel_agent bazel test //projects/mcp_cordis:all --nocache_test_results: pass, four of four tests executed on the exact commit.
  • bazel_agent bazel build //projects/mcp_cordis:all: pass, all nine targets.
  • bazel_agent bazel test //:buildifier_test --nocache_test_results: pass.
  • The delivery receipt records direct base 7ad2704cd27757355ab36ec8eb1bb27ef9e1d91d, prepared head 7cfef071, and prepared tree 34153eca.
  1. Pass: documented standalone Bazel-built stdio MCP server.
  2. Pass: lifecycle tests exercise real Cordis contexts, Fibers, and effects.
  3. Pass: one runtime and one stdio connection exercise the complete mutable package lifecycle.
  4. Pass: immutable versions, rollback, deterministic drain, and exact cleanup are exercised.
  5. Pass: isolated project and scratch roots are exercised.
  6. Pass: promotion and subprocess restart recovery are exercised.
  7. Pass: three justified starter packages and all eight tools execute.
  8. Pass: fixed discovery/invocation gateways work without reconnecting.
  9. Pass locally: all recorded checks and the real stdio transcript pass on the exact candidate tree. Remote repository handoff remains pending authority.
  • Criterion 9 improved from a nondeterministic failure to a forced, exact-tree pass; no technical criterion regressed.
  • The explicit gate improves evidence in absolute terms: candidate startup can take arbitrarily longer than the old call without changing the assertion.
  • Independent code review and the measured zero drain count both supported retaining transactional start-before-swap behavior.
  • No defect survived two attempts. The elapsed-time test and Buildifier order are resolved in their first corrective cycle.
  • Adapter and root Buildifier startup dominated wall time; warmed focused tests remained under ten seconds. Further local optimization would not change the delivery critical path.
  • The only remaining action is remote publication, which cannot proceed from a rebase-only authorization.

1.15.1.3.4 -

Attempt 4

Back to durable goal · Attempt history

PR 32 commit 7cfef071 is remotely reproducible but is not a final candidate: three review findings are valid. The user also requires the four projects/agents changes from PR 24, whose missing decision-review package explains the current base’s dangling instruction reference.

  1. Applying PR 24’s changes three-way will preserve newer goal guidance while importing its result-first additions, Bazel batching guidance, and decision-review package.
  2. Treating command overflow as bounded success will preserve useful prefixes for search and diff consumers without leaking child processes or invalid UTF-8.
  3. Enforcing max_changes before every porcelain status record will bound all record kinds uniformly.
  4. Closing admission, draining registered package locks, then disposing active workers will make shutdown linearizable with concurrent run/reload.
  • Current and published task commit: 7cfef0719075ad372c3bb257ad216b35770356b2.
  • Current base/direct parent: 7ad2704cd27757355ab36ec8eb1bb27ef9e1d91d.
  • PR 24 base/head: ada3ed90123c224729f9174c6127c50b933d2f48 / da2085f1807bfea1c7f3979730f6b7df0033fdce.
  • Import boundary: only paths beneath projects/agents changed by PR 24.
  • Review boundary: the three existing PR 32 threads and directly required regression coverage; no unrelated runtime redesign.
  • Preserve all immutable package versions already referenced by manifests.
  1. Merge the PR 24 bazel-agent and goal hunks into current files; add decision-review plus the offline eval structure required today.
  2. Add black-box execution overflow coverage and implement bounded UTF-8-safe truncation while preserving timeout/spawn errors.
  3. Add table-driven status-limit coverage and publish a new immutable git_worktree version with the limit check before record parsing.
  4. Add a deterministic concurrent activation/shutdown gate and memoized shutdown sequence that waits for admitted locks before disposal.
  5. Run focused tests first, then both affected packages, Buildifier, exact diff checks, delivery preparation, exact-candidate validation, publication, and review-thread replies/resolution.
  • PR 24 provenance maps exactly to the imported agent changes; newer main guidance remains present.
  • decision-review validates and its Promptfoo configuration loads offline.
  • Output at and beyond the cap is bounded, UTF-8 valid, truncation-marked, and stopped; under-cap and timeout behavior remain correct.
  • Every porcelain-v2 record kind obeys max_changes.
  • Shutdown cannot resolve before an already-admitted activation is owned and disposed, and later calls reject runtime_closed.
  • All previous MCP lifecycle, restart, package, and stdio regressions remain green on the exact delivered commit.
  • Remote publication improved delivery evidence but exposed three absolute correctness failures; validation success alone was insufficient.
  • The PR 24 request resolves an upstream packaging inconsistency and is independent enough to integrate before runtime corrections.
  • The current representation remains viable: every defect has a narrow controlling mechanism and deterministic test. No evidence supports replacing Cordis, the worker boundary, or content-addressed persistence.
  • Imported all four PR 24 agent-tree changes three-way and added the offline validation files required by current repository policy.
  • Changed ctx.exec() overflow from an output-limit rejection to a bounded, UTF-8-valid success result with explicit process-group cleanup and a truncation flag.
  • Published the corrected Git parser as new immutable version de978... while retaining 70d8... as permanent rollback history.
  • Made shutdown join admitted activation locks before its final active-worker snapshot and added closure checks around initialization storage awaits.
  • Added direct regressions plus an actual git_compare cap integration case.
  • Four focused Bazel tests: pass.
  • Complete MCP package plus three skill eval-config targets: ten of ten pass.
  • Complete MCP package build plus three skill libraries: pass; all skill validation aspects pass.
  • Root //:buildifier_test: pass.
  • JavaScript syntax, exact new version SHA-256, quick skill validation, and git diff --check: pass.

Refine. The product and packaging gates were green, but independent review found silent output-loss and exact-limit semantics that those gates did not exercise. Preserve the architectural changes; Attempt 5 changes the affected contracts and tests rather than discarding the worker/runtime design.

1.15.1.3.5 -

Attempt 5

Back to durable goal · Attempt history

Attempt 4 passed every recorded command but independent review disproved four completeness claims: malformed UTF-8 loss was unmarked, built-in consumers silently accepted partial host output, Git status truncation was inferred from capacity rather than omission and missed newline paths, and imported skill evals did not cover their added behavior.

  1. Have UTF-8 decoding report whether it dropped any retained bytes and OR that fact into truncated; cover malformed output below and above the cap.
  2. Publish new immutable versions for each reusable package whose result fields need host-truncation propagation. Preserve every previously tracked version byte-for-byte and make partial fields explicit rather than hiding signal termination as ordinary success.
  3. Parse status records before deciding whether an additional logical change was omitted, capture NUL-delimited paths with newline-safe expressions, and cover exact-one, max-two, max-one-of-two, copy, and newline cases.
  4. Add offline cases that exercise compatible multi-target Bazel batching, immutable exact-hash candidate promotion/regression, and durable task-owned push behavior that excludes disposable output and reports blockers.
  5. Track disposal of an activation removed by #handleUnavailable() as a retirement so shutdown cannot return before its worker teardown completes.
  6. Rerun each focused target, all affected package/skill tests and builds, Buildifier, and another independent review before freezing a commit.
  • Retain the Cordis/worker/storage architecture and the shutdown correction.
  • Do not modify historical hash-named version bytes.
  • Do not import any PR 24 path outside projects/agents.
  • Do not add live, billable eval targets; these cases extend the existing offline-validated behavioral configurations.
  • Do not prepare, commit, or publish until the new review is clean.
  • Every discarded output byte makes truncated true.
  • Each Git/context field that can be partial exposes that fact; bounded diff and search remain successful.
  • Shutdown joins teardown for generations that become unavailable immediately before shutdown, not only those still present in the active map.
  • Exactly maximum status changes reports complete, while an actual additional parseable change reports truncated; valid newline paths round-trip.
  • Eval configs validate with cases for every material imported behavior.
  • A second independent read-only review reports no remaining actionable issue.
  • ctx.exec() now retains a combined bounded prefix, marks byte overflow and malformed UTF-8 loss as truncated, and stops the child before resolving.
  • repo_context activates immutable version abd0db3e...; root, HEAD, status, and ripgrep results propagate host truncation explicitly.
  • git_worktree retains original version 70d8f28d... unchanged and activates sole new version 8853aa20.... The rejected intermediate de978... file is absent. Exact-limit status, newline paths, incomplete NUL records, revision discovery, history, name-status, diff, and aggregate flags are covered.
  • Runtime shutdown is memoized, closes admission, joins admitted package operations, and tracks disposal after an unavailable activation leaves the active map.
  • PR 24’s projects/agents subtree is integrated as bazel-agent, goal, and packaged decision-review changes only. Newer goal-record and delegation policy is preserved; added eval cases exercise every material imported rule.
  • Focused Bazel regression/eval batch: 8 of 8 tests pass.
  • Entire affected MCP package plus skill evals: 12 of 12 tests pass.
  • Entire MCP package and all three skill libraries build; every skill validation aspect passes.
  • Root //:buildifier_test: 1 of 1 passes.
  • git diff --check, JavaScript syntax checks, and every retained/new reusable package content hash pass.

Attempt 5 materially closes every falsified completeness claim from Attempt 4 without replacing the accepted architecture. New versions are confined to the two reusable packages whose public result contract changed; historical bytes remain intact. The test packet now observes semantic completeness rather than only byte caps or array lengths. The remaining critical path is review and exact-candidate delivery, not additional implementation.

Verdict: proceed to independent review. Do not freeze or publish the candidate until that review is clean.

The agent-skill review found that PR 24’s absolute “commit and push every turn” wording contradicted the preserved throwaway-record policy when a rejected attempt leaves no durable tracked change. The merged skill now makes delivery conditional on authorized, nonempty durable tracked progress and explicitly forbids empty/cosmetic commits or promoting disposable out/ evidence merely to manufacture a checkpoint. A new offline case covers the no-durable-output rejection. This changes the candidate and invalidates the prior goal eval result; rerun the affected skill and integrated gates after the remaining reviewers report.

The follow-up review also found that the durable-progress eval incorrectly required preparation while remote-ref ownership was unknown. Its oracle now requires exact inspection followed by a safe stop before preparation, rewrite, or publication until ownership is established.

The review then found that decision-review’s self-contained case could run meaningfully with the available provider, so offline validation alone did not satisfy current skill-package policy. A manual, credentialed promptfoo_test target now complements the ordinary offline validation target; it is declared but will not be executed as part of normal or delivery validation.

The generic goal skill also carried Blender-specific scene, topology, datablock, and linked-library mechanics from PR 24. Those details could misroute domain policy into software and documentation goals. The merged text now retains only the cross-domain invariant: immutable candidate copies, one writer per candidate, exact or deterministic component promotion, and post-promotion regression. Its eval uses a generic protected deliverable. The bazel-agent eval documentation now correctly describes its plural cases.

The generalized component-promotion rule initially tried to compare a component-merged aggregate with a whole-candidate hash, which is impossible. It now distinguishes exact whole-candidate promotion from independently hashed component promotion and always reruns affected aggregate gates.

The first manual decision-review target reused credentials without isolating subject and judge state. Its config now uses separate runner-provided Codex homes and workspaces, an explicit executable override, and isolated proxy inheritance; its README documents the required absolute-path invocation.

1.15.1.3.6 -

Attempt 6

Back to durable goal · Attempt history

Attempt 5 passed every repository gate, but the required second independent review found release-blocking lifecycle and compatibility defects: worker termination could orphan detached ctx.exec() children, promotion was outside shutdown admission, unavailable candidates could cross the persistence/swap boundary, and the new always-partial output contract made retained package versions lie about completeness. The same review found narrower package and imported-skill correctness gaps. The candidate is rejected despite green tests.

  1. Preserve backward compatibility by making partial output an explicit ctx.exec() option. Existing package versions retain rejection on overflow; new versions opt in and receive an explicit output-limit reason alongside truncated.
  2. Close worker disposal admission before spawning, clean child process groups both before and after admitted handlers settle, and replace immediate parent termination with graceful disposal followed by the existing bounded forced fallback.
  3. Track complete promotion operations in the runtime admission barrier and stage candidate availability across persistence so a failed candidate cannot replace or persist over the working generation.
  4. Publish sole new immutable starter versions after correcting unexpected signal/error handling, exact-boundary flags, omitted-record flags, Git read-only behavior, robust history framing, and containment checks. Delete every rejected untracked hash candidate rather than retaining it as history.
  5. Pin LF checkout semantics for hash-addressed source and test retained-version compatibility, exact output boundaries, outer timeouts, settlement-after- group-confirmed settlement, late-spawn disposal, promotion shutdown, and candidate failure.
  6. Finish the PR 24 merge by keeping generic goal invariants generic and making the manual decision-review eval isolate subject and judge state.
  • Do not change any previously tracked hash-named source bytes.
  • Do not add PR 24 paths outside projects/agents.
  • Do not run the credentialed manual Promptfoo target.
  • Linux is the supported supervised-execution platform for this repository target. The guarantee covers the direct child and live descendants that stay in its original process group; deliberate new sessions are excluded.
  • Keep one writer per runtime source group and one writer for all active content-addressed package candidates/manifests.
  • No live member of a supervised original process group survives inner timeout, outer invocation timeout, disposal, shutdown, or successful truncation settlement.
  • Shutdown waits for every admitted mutation, including promotion, and never publishes a candidate observed unavailable during persistence.
  • Historical package versions reject overflow under their original contract; only explicit opt-in versions return a marked partial prefix.
  • Every result field distinguishes complete, locally clipped, host-limited, failed, and unexpectedly signaled outcomes.
  • Exact limits are complete until one additional logical record is observed.
  • All content hashes, LF attributes, skill validation, offline eval configs, focused regressions, integrated tests/build, and Buildifier pass.
  • A fresh review of the final Attempt 6 diff reports no release-blocking issue.
  • Restored the historical ctx.exec() contract: overflow and invalid UTF-8 reject by default, while new packages opt into a bounded marked prefix.
  • Moved process launch and output accounting from the disposable worker into a parent-owned Linux supervisor. Launch admission is atomic in the parent’s event loop, direct exit terminates the original process group before inherited pipes can hold settlement open, and timeout/disposal results wait for group non-liveness.
  • Narrowed the documented contract honestly: a package that deliberately calls setsid() or otherwise creates a new session is outside the trusted original- group guarantee; non-Linux execution fails closed.
  • Made shutdown actively dispose both active and draining retired generations, and staged candidate persistence so an unavailable candidate rolls back without displacing the working generation.
  • Published one current source candidate per starter package. The hashes are 04b06a7d6277c4a6e8513d970f549ad980a780b68755f28d7b402fe8be26c279 for git_worktree and 94131e058f82328f091613dc68d2717484378066a9c64940d99522c14b48b4d7 for repo_context; historical source bytes remain unchanged.
  • Made ripgrep byte-valued JSON fields explicitly incomplete rather than returning empty text under a false completeness claim.
  • Imported PR 24’s agent skills, added current validation/eval packaging, generalized goal policy, and moved this complete goal directory into the reusable project docs hierarchy.
  • Static syntax, manifest/hash, LF-attribute, local-link, and git diff --check checks pass on the corrected working tree.
  • Focused process, unavailable-shutdown, and retired-generation tests pass 3/3 in Bazel invocation 9b1b2d34-8490-474a-b12c-e2052bf2d90b.
  • Process, package-byte-field, and retired-generation tests pass 3/3 in Bazel invocation 7c680be8-e2a6-4b5b-9b45-4a0390f39a5a.
  • The earlier 14/14 integrated packet, complete affected build, validation aspects, and Buildifier passed before the supervisor and final package-byte corrections. Those results are preserved as progress evidence but are invalidated for final acceptance and must be rerun.

The first final review rejected the candidate despite green tests. It found that outer timeouts settled before cleanup, a signal was mislabeled as reaping, the shared PID publication window made disposal unbounded, inherited pipes could delay successful commands, retired generations were not actively disposed by shutdown, ripgrep byte fields could masquerade as text, and the durable records were stale. The strategy changed from worker-side process ownership to parent-owned supervision; every other finding has a direct source or regression correction. Fresh review of that new strategy is pending.

  • Criteria 1-8: pass on implementation and existing executable evidence.
  • Criterion 9: unverified after the latest source changes; full exact-candidate validation and delivery remain.
  • Criterion 10: focused regressions pass; fresh adversarial source review is still pending.

Attempt 6 improved compatibility, package completeness, promotion admission, and teardown coverage in absolute terms. The repeated late lifecycle findings showed that PID publication inside a terminable worker was the wrong ownership boundary, not merely an under-tested implementation. Moving execution to the parent removes that race and makes cleanup ordering directly observable. The highest-leverage remaining work is review and full validation of this new boundary, not more feature expansion. The attempt remains open until that review accepts one frozen candidate and delivery verifies the same bytes.

Refine within Attempt 6: the review changed an implementation strategy without changing the recorded goal or acceptance contract. Do not freeze or deliver until fresh review and the complete invalidated regression set pass.

1.15.1.3.7 -

Attempt 7

Back to durable goal · Attempt history

The user correctly identified that each package’s manifest.json, content-addressed versions/ directory, and active/latest pointers were a custom package manager rather than an MCP or Cordis standard. That mechanism made reusable source look temporary, duplicated Cordis loader responsibilities, and drove much of the worker-generation complexity. Green tests cannot justify shipping the wrong extension model.

Verdict: revise and proceed. The published DeepSeek Cordis packages provide the missing standard mechanisms directly:

  • @deepseek-ai/cordis-plugin-loader owns runtime entries and lifecycle;
  • @deepseek-ai/cordis-plugin-include persists entries in cordis.yaml and transactionally refreshes them with rollback; and
  • @deepseek-ai/cordis-plugin-hmr watches normal modules, imports changed code before replacement, and restores the prior runtime when reload fails.

The strongest objection is that HMR is event-driven and failed source reloads are logged rather than returned to the file writer. MCP-driven updates must therefore retain prior bytes, wait for a correlated reload result, and restore the prior source on failure or timeout. Manual external edits retain Cordis HMR’s normal behavior and diagnostics.

  1. Pin the exact released Loader, Include, HMR, Timer, and required peer dependencies through the project-owned npm lock.
  2. Replace package manifests and hash-named versions with normal ESM modules: reusable modules under projects/mcp_cordis/plugins/, disposable modules under out/mcp_cordis/plugins/.
  3. Make projects/mcp_cordis/cordis.yaml and out/mcp_cordis/cordis.yaml the authoritative standard entry lists.
  4. Mount the official Cordis Loader, two Include trees, Timer, and HMR in the stdio server. Keep the stable MCP gateway, workspace helpers, bounded process execution, and tool-registration effects as host services.
  5. Implement MCP define, update, start, stop, remove, and promotion as atomic source/config changes followed by Cordis lifecycle acknowledgement and rollback. Use Git for reusable history; do not create a second version database.
  6. Replace version-store tests with standard-config, restart, HMR rollback, manual-edit reload, and project/scratch promotion tests.
  7. Run the complete affected test/build/Buildifier packet, obtain a fresh independent review of the standard design, then rebase and deliver PR 32.
  • Do not add an MCP Registry server.json unless the server is actually being prepared for registry publication; it describes the whole server, not its internal Cordis entries.
  • Do not retain committed hash-named source snapshots or custom package manifests.
  • Keep reusable source and config in the project and all disposable modules, atomic-write scratch, state, and logs under out/mcp_cordis.
  • Keep one normal module per package and one stable entry id per scope.
  • Preserve PR 24’s scoped projects/agents import and the accepted process execution corrections that remain relevant to the in-process host.

Implementation and working-tree validation are complete; exact post-rebase delivery gates remain open. The final architecture adds four narrow host guards around the official Cordis services: synchronous activation admission to prevent a never-settling apply(), source-token HMR correlation, a private stdio protocol stream, and Fiber/invocation-owned Linux process supervision. The real stdio regression covers define, inspect, run, invoke, update, failed update rollback, stop, remove, logging isolation, and restart recovery.

Bazel invocation 39711671-375a-413f-8a72-e6f9ff892bd3 passes all 11 affected tests on the rebased implementation after the import-boundary review corrections, including Buildifier and all three imported skill configurations. Invocation 153467fd-e62d-4eab-b260-6754d17fe8e2 builds all 26 affected targets. Those receipts bind implementation commit 0a93e487; the following amendments change only this durable goal record, with proportional diff and format validation required before publication. Fresh independent review accepted durable-record commit c05bd45a with no actionable findings. PR 32 was republished at the verified rebased head, its obsolete description was replaced, and all three prior review threads were resolved.

1.15.1.3.8 -

Attempt 8

Back to durable goal · Attempt history

The fresh hosted review of the delivered standard-Cordis candidate found three valid starter-package defects: the JavaScript search fallback recursively read ignored and hidden files when ripgrep was absent, fallback submatch offsets used UTF-16 code units instead of ripgrep-compatible UTF-8 bytes, and a bounded textual HTTP body could end with a replacement character when the byte limit split a multibyte sequence.

  • The JavaScript fallback now fails closed for directory searches and supports only explicitly selected files. This preserves hermetic single-file fallback without silently weakening ripgrep’s hidden and ignore filtering.
  • Fixed-string and regular-expression fallback matches calculate start and end from UTF-8 byte lengths.
  • Textual HTTP previews discard only an incomplete trailing UTF-8 sequence; the raw retained-byte count and truncation signal remain exact.
  • Follow-up review found that case-insensitive fixed matching could still use a length-changing lowercased index, explicit files did not override globs as they do in ripgrep, and unfiltered listing reparsed a malformed scope instead of returning the healthy scope with an error.
  • Case-insensitive fixed fallback now matches against the original line with a Unicode regular expression, explicit files bypass fallback glob filtering, and unfiltered listing returns per-scope errors alongside healthy packages. Explicitly listing a malformed scope continues to fail directly.
  • Final hosted review showed that a valid config with an unavailable module still bypassed the malformed-config catch, and bounded reads reported the requested range end instead of the last retained line. Unfiltered listing now skips every scope whose Include failed to mount, and bounded reads derive endLine from retained content.
  • Fresh diff-focused correctness scrutiny then found that repeated initialize() calls lost the original partial-startup errors. The runtime now preserves and clones those errors across idempotent initialization.
  • The same scrutiny found that incomplete UTF-8 suffix removal also ran for a naturally completed malformed textual body. It now runs only when the local byte cap truncates the response; naturally malformed bytes retain the prior replacement-character preview.
  • The repository’s repo-delivery skill now invalidates prior correctness verdicts after behavior-changing edits and requires proportional adversarial scrutiny in addition to test reruns.
  • Exact-thread reconciliation after the final hosted review exposed one older unresolved finding and one new finding: the explicit-file regex fallback matched UTF-16 surrogate halves, and cordis_define plus cordis_promote advertised overwriting operations as non-destructive. Regex fallback now uses Unicode scalar mode, and both source-overwriting tools carry the destructive MCP hint.
  • The next exact-commit review found two more fallback-boundary defects: adjacent matches were also emitted as context, and a retained empty line was reported like a request past EOF. Fallback search now plans a single ordered event stream from all matching lines, and bounded reads track range existence independently from textual content.
  • Focused invocation b73ce3b4-bfb6-4081-b84f-29c3f763b3a4 passes both corrected starter-package test targets.
  • Complete MCP test invocation 93845f08-cd10-4dfb-88c5-034497dea58a passes all 7 tests; build invocation d7716a48-9509-44fe-9e37-b5c44904fffd builds all 16 targets.
  • Buildifier invocation 1fb561cc-d336-49db-813f-de26b7fedbe4 passes.
  • Regression cases prove directory fallback fails closed while an explicitly selected hidden file remains available, both fallback engines report byte offsets for éneedle, and a one-byte preview of é returns an empty valid UTF-8 prefix rather than U+FFFD.
  • Follow-up focused invocation c07704be-cdf8-4045-a0c0-4626ebc0d1e7 passes both affected targets. Complete test invocation 3fbaa4e1-8ea1-4b3f-a533-51e1ad01f87b passes all 7 tests, build invocation f87e45b6-765e-49c8-a618-cd2eb1efa1ad builds all 16 targets, and Buildifier invocation 8542838d-92ae-4999-b1e8-fac631629f6f passes.
  • Final-cycle focused invocation 99866999-c31d-457f-b64b-c7a15073e7a2 passes both affected MCP tests. Combined affected invocation e86a5d1c-cadf-4ff6-9647-3e1050e461e6 passes all 8 MCP and skill tests; 083fbf55-851e-4db4-b8e5-e5871c874faa builds all 19 affected targets. Skill quick validation and Buildifier both pass.
  • Focused starter invocation e80439df-bddd-4a76-b9e1-be6c7f1ed649 distinguishes a cap-split multibyte prefix from a naturally completed malformed textual body.
  • Exact aggregate validation exposed timing-sensitive evidence: a wall-clock admission bound failed under load, and the expected invocation timeout could reject before its assertion was attached. The test now asserts the wrapped synchronous-admission semantics and attaches the expected rejection before waiting for its PID fixture. Invocation e7d69598-b843-4da4-833b-e024d406b8ca passes three consecutive runs.
  • A later loaded aggregate run exposed a real HMR rollback race. Cordis restores the prior module cache after a failed import without emitting a reload event; the host unnecessarily waited for a second filesystem reload that could be absent. Rollback now accepts the already-restored prior source marker and waits for HMR only when the failed candidate actually reached the cache. Invocation 5f9b49e0-d3d3-4f9e-84ec-602dfbe38c77 passes three runs.
  • Focused invocation 132e2f33-837c-40b2-83b5-4b06ceadfd0f passes the Unicode fallback and real-stdio MCP annotation regressions.
  • Complete affected invocation b19d303e-0aca-4097-a191-e81015dc2982 passes all 8 MCP and skill tests; build invocation 1c8aa274-dd72-4e6f-9491-de5e283b2c5c builds all 19 targets, and Buildifier invocation 34f6f5c7-7f44-478b-b939-63ac03c3bbb1 passes.
  • Focused invocation 2528b6ee-7d82-48c9-a607-298a4cef0b9b proves adjacent matches remain ordered match events and empty retained lines report their actual endpoint while a request past EOF reports null.

Accept locally. Publish the exact follow-up correction commit, resolve the hosted review threads, and verify the remote head before final handoff.

1.15.1.3.9 -

Attempt 9

Back to durable goal · Attempt history

The user rejected the growing HMR race-handling layer and explicitly requested the simplest robust way for an MCP server to load DeepSeek/Cordis plugins. The published parent is bc4e5ae97ef9ea968c01b1b2a55403ae032a6a8d. An unpublished polling experiment is rejected rather than promoted.

Atomic persistence plus the official Cordis Include and HMR services is the smallest reliable boundary. If MCP source mutations stop claiming synchronous activation or transactional on-disk rollback, the runtime can delete its source-marker protocol and every dependency on Loader internals while still loading, invoking, and eventually hot-reloading normal Cordis plugins without restarting the MCP connection.

  1. Keep standard cordis.yaml, ordinary plugins/*.mjs, and the two project and out/mcp_cordis scopes.
  2. Keep the fixed MCP list/invoke gateway and the existing package context API.
  3. Validate module syntax before an MCP write and use atomic file replacement.
  4. For an existing running module, return after persistence with persisted: true, sourceChanged: true, and activation: "pending"; official Cordis HMR owns eventual activation. Do not claim that every evaluation or apply() failure restores the prior live entry.
  5. Keep public Include refresh for entry-list changes, because it is the official transactional API for starting, stopping, adding, and removing entries.
  6. Delete injected source markers, HMR acknowledgement waiters, polling, Loader loadCache inspection, and MCP-owned source rollback.
  7. Update documentation and tests so success means persisted/configured, while live update is verified by bounded eventual observation.
  8. Retain and validate the two pending repo_context review corrections for ordered context events and empty-line endpoints.
  9. Register the server in the trusted workspace’s .codex/config.toml. Use a worktree-resolving launcher and Bazel’s run --script_path handoff so the long-lived MCP does not retain the Bazel output-base lock.
  10. Rebase onto d29f9d471ea467e8dfc75db4eedeedbbae43dc2d, preserve its projects/goal redesign, and discard the superseded in-place goal-skill edits rather than replaying them.
  • Focused runtime, stdio, and repo_context tests.
  • Complete //projects/mcp_cordis:all tests and build.
  • repo-delivery skill tests and root Buildifier.
  • Fresh diff-focused scrutiny of update failure, disabled-entry, promotion, restart, shutdown, and watcher timing paths.
  • Independent review and exact PR 32 thread reconciliation before delivery.

Refine. Removing wrapper-side acknowledgement machinery was correct, but an independent reproduction proved that unmodified HMR 1.0.16 can lose a source change arriving during an in-flight reload. Attempt 10 keeps the thin wrapper and moves serialization into a focused, reproducibly pinned dependency patch. The separate delivery-adapter refusal still prevents the history rewrite.

1.15.1.3.10 -

Attempt 10

Back to durable goal · Attempt history

Independent review of Attempt 9 reproduced a lost update in pinned @deepseek-ai/cordis-plugin-hmr 1.0.16. A slow top-level-await replacement followed by a second source write left the latest bytes on disk while the earlier generation remained live. The public HMR surface has no module-failure event, so a wrapper-side single-flight gate cannot be both safe and recoverable.

The narrowest robust correction belongs in HMR’s own reload scheduler. A standard pnpm dependency patch can serialize partialReload() calls, snapshot each observed change set, and drain changes arriving during an in-flight reload. mcp_cordis then remains a thin persistence and invocation gateway without source markers, Loader-cache inspection, polling, or acknowledgement state.

  1. Keep the standard Cordis Loader, Include, Timer, and HMR services and normal cordis.yaml plus ESM plugin files.
  2. Patch the exact HMR 1.0.16 artifact through pnpm patchedDependencies. Track one module-refresh task, snapshot its stashed URLs before each reload, and drain any URLs observed while that reload is running.
  3. Patch both the published JavaScript and TypeScript source shipped in the package; bind the patch through the generated lockfile and Bazel module extension data.
  4. Add explicit release-gated overlapping-update regressions for slow top-level module evaluation and slow asynchronous apply() activation.
  5. Refresh a disabled entry’s exact cached module through HMR before enabling it, so activation returns only after the latest persisted source is live.
  6. Adopt the fetched base’s role-based layout: command files under cmd/mcp_cordis, private implementation under internal, and the separate suite under test.
  7. Preserve the two accepted repo_context review corrections and the worktree-local launcher.
  8. Stop before Git history mutation until the delivery adapter has an authorized, guarded path for the nine-commit feature range.
  • The package registry and upstream repository both expose 1.0.16 as the latest official HMR release; its source still invokes untracked concurrent partialReload() work and clears the shared stash after one successful run.
  • git apply --check accepts patches/hmr@1.0.16.patch against the exact resolved package bytes. Its SHA-256 and lockfile patch hash are both ec800d86298faacc86c7717ffa1dce7c28116ab1393b8abc198be6ac02c38489.
  • The patch serializes module reloads through complete Cordis Fiber cleanup and activation, drains newly stashed URLs, preserves and retries changes after unexpected scheduler failures, and declares its public refresh API in the shipped TypeScript declarations.
  • Bazel invocation ac79a8e4-f5d9-4dd7-a821-29bce3d8ece6 passes the focused runtime suite with explicit top-level-evaluation and asynchronous-apply overlap gates, failed-apply rollback and recovery, manual-edit, and disabled activation regressions.
  • Bazel invocation 65c1932a-896b-470d-9462-086dd93beaff passes ten runs each of runtime_test and starter_packages_test.
  • Bazel invocations 6490dd57-49e0-4558-b280-f5625db07208, 218e5797-b2d7-44bc-aded-f5df8139ca1c, and 09d4ec2c-aac1-4509-8579-5ef8c5eebe39 pass the complete project tests, complete project build, and root Buildifier check respectively.
  • Final independent HMR review accepts the patch identity, stashed-change draining, complete Fiber cleanup join, public declarations, causal overlap tests, rollback and recovery, and disabled-entry activation behavior. Its sole remaining finding was the corrected README publication-order wording.
  • The checked-in workspace launcher completed MCP initialization and returned all ten gateway tools while concurrent Bazel query invocation 7739c14e-1b22-40c7-94af-b81143e84d4a completed successfully; SIGINT then produced a clean server shutdown.
  • Preliminary current-tree Bazel invocations 95d37231-63f9-44f6-9eee-3f0fe8fb4107, d70f61a2-57e5-4ce9-b8fd-27b06bd02a6d, and 1e186c82-3bcd-4048-a534-fe747e1cf79c pass the complete affected test packet (10/10), affected build packet, and root Buildifier check.
  • Guarded delivery inspection found local and remote feature OID bc4e5ae97ef9ea968c01b1b2a55403ae032a6a8d, base OID d29f9d471ea467e8dfc75db4eedeedbbae43dc2d, same-repository PR 32, SSH transport, and nine linear commits all authored and committed by the task bot. Its sole refusal is version 1’s unconditional multi-commit range refusal; the fetched base contains the same limitation and no explicit consolidation authorization.
  • The user then explicitly authorized extending the adapter. The new prepare --consolidate <exact-head> path retains every other refusal and requires a single-parent chain, identical author and committer identities, the oldest commit’s ownership marker, unchanged pull-request projection, and signature preservation. It creates one aggregate commit while binding the original remote head into the normal publication receipt.
  • Bazel invocations 574dadd5-51b1-443e-b8c2-50ca5d257eb2 and 030a8bb4-2a22-4ece-b632-b3c75572bcee pass the complete adapter suite once, then its Go, skill-validation, and root Buildifier targets three times.
  • Independent adapter review found that the first implementation required an extra staged edit and therefore could not consolidate an already-clean range. The corrected gate permits an unchanged index only after exact consolidation evidence; parent-to-tree scope validation still rejects an empty aggregate. A clean --path integration case proves tree preservation and one final commit. Bazel invocation 0d715375-6a8d-4269-ad3e-f8a002888808 passes the corrected suite, and the independent re-review accepts it with no remaining findings.
  • Upstream incorporation review preserves the new projects/goal project, drops the deleted predecessor skill under projects/agents, adopts the role-based MCP layout, and adds root-consumer visibility to the branch-owned decision-review skill. The root discovery-link entry must be added after the new base is applied.
  • After that visibility correction, Bazel invocations 6099d90d-0ade-43b2-b50b-8f7050c26c32 and 7f4b37a4-b970-46ea-bc76-b4a60aeeab59 pass the focused skill validation and root Buildifier check; git diff --check also passes.

Proceed. The dependency-layer correction addresses the reproduced race and failure recovery at Cordis’s owning lifecycle boundary while the MCP wrapper remains a thin persistence and invocation gateway. The complete local project packet and focused independent review pass. Exact-candidate validation, rebase, publication, and hosted-thread reconciliation remain open.

1.15.1.3.11 -

Attempt 11: exact consolidated rebase

Back to attempt history | Back to durable goal

Replace the nine task-owned feature commits with one aggregate commit, rebase that exact candidate onto the current remote base, preserve the incoming goal and skill-discovery layouts, and establish publish-ready evidence without bypassing repo_delivery.

  • The fetched base advanced to 63e7b9f0be1e054373415914ff3d2ea2282aa3da and added the reusable projects/goal project, per-skill discovery links, decision-review, and exact-head remote-review waiting rules.
  • The old agent-local goal skill remains deleted. The durable MCP goal stays under projects/mcp_cordis/goals/runtime_extensions.
  • The branch keeps the upstream root discovery target, including decision-review and projects/goal/skills/goal, and combines the incoming review-waiting policy with the branch’s correctness-revalidation policy.

The authorized consolidation path exposed four fail-closed edge cases during the real rebase:

  1. Existing PR text must match the requested aggregate projection, rather than the obsolete first commit’s projection.
  2. Explicit staging must handle deleted paths, partial directory deletions, and a tracked symlink replaced by a directory.
  3. Patch files need the standard repository-wide whitespace exceptions for structural context prefixes.
  4. A rebased aggregate path may disappear only when the prior candidate and new base contain the exact same Git tree entry. The receipt then records the reduced path set; added paths, non-identical loss, and an empty aggregate remain refusals.

Each case has focused integration coverage. Every failed preparation restored the original branch, index, and worktree before the next correction.

  • repo_delivery prepare --consolidate produced one commit on the fetched base. The first exact code candidate before the final adapter-and-record update was f1c313b0920cb92f2d643dcb5c7d79ab364df058.
  • Bazel query invocation 5ad9400e-f7b8-4688-9b8c-e962f3de8e66 discovered the affected MCP, delivery, and skill targets.
  • Bazel test invocation 13588b19-1f8a-43a7-8006-f9d5d4652670 passed all 12 affected tests, including Buildifier and discovery-link validation.
  • Bazel build invocation 5863ac24-3bb2-47be-99fb-50141e933018 passed all 29 affected targets.
  • The real launcher initialized, listed all ten gateway tools, and remained live while Bazel query invocation 4637f187-d05e-4905-8153-18fca8644ea1 completed. SIGINT then terminated the server as expected.
  • git diff --check passed and the worktree remained clean after validation.

The aggregate was published as a single commit on PR 32 and its delivery receipt verified the local tree, remote feature ref, current base ancestry, and PR projection. The exact-head hosted review found three additional issues:

  • repository reads reopened a checked symlink through its lexical alias;
  • permanent /proc inspection failures could prevent shutdown from settling;
  • the process-tree timeout regression assumed Node could start within 100 ms.

The final correction reads through a canonical, no-follow file handle and verifies that handle through /proc/self/fd before consuming bytes, turns repeated process-inspection failures into a bounded EXEC_CLEANUP result, and uses a startup-safe timeout in the process-tree regression. The full MCP test and build packets pass, and both focused targets pass three repeated runs. The review threads are reconciled through the receipt-bound delivery adapter. The follow-up exact-head review found the same replaceable-path class in git_worktree: discovery verified one repository directory, but later Git commands reopened its lexical path. Git discovery and every subsequent command now use /proc/<pid>/fd/<fd> paths backed by verified open directory handles, while the subprocess working directory remains workspace-local. Focused mock coverage checks every Git -C path and the real Cordis starter package integration passes. The next pass found the same class in repo_context’s ripgrep and Git metadata branches; both now use verified descriptor paths for the complete subprocess lifetime, and directory listing uses the selected directory handle as well. Attempt 11 is accepted and the goal is complete. The terminal exact-head review then identified that the JavaScript regular-expression fallback could both block the MCP event loop on pathological backtracking and disagree with ripgrep’s Unicode semantics. The fallback now fails closed for regex requests when ripgrep is unavailable; bounded fixed-string search remains available. Focused and complete MCP test and build packets pass after that correction. The next exact-head pass found that replacement decoding of invalid UTF-8 also changed fixed-search raw byte offsets. The fallback now fails closed for such files as well, leaving raw-byte search semantics to ripgrep; the focused, complete test, and build packets again pass.

1.15.1.4 -

Evidence manifest

Back to durable goal

  • Recursive JavaScript fallback fails closed when ripgrep is unavailable; explicitly selected files remain supported.
  • Fallback fixed and regular-expression submatches use UTF-8 byte offsets.
  • Bounded textual HTTP previews omit an incomplete UTF-8 suffix.
  • Focused tests pass 2/2 in invocation b73ce3b4-bfb6-4081-b84f-29c3f763b3a4; the complete MCP package passes 7/7 tests in 93845f08-cd10-4dfb-88c5-034497dea58a and builds all 16 targets in d7716a48-9509-44fe-9e37-b5c44904fffd.
  • Buildifier passes in invocation 1fb561cc-d336-49db-813f-de26b7fedbe4.
  • Follow-up review corrections preserve original-line indexes for Unicode case-insensitive matching, make explicit fallback files override globs, and return healthy scopes plus structured errors from unfiltered listing after partial startup.
  • Follow-up focused tests pass 2/2 in c07704be-cdf8-4045-a0c0-4626ebc0d1e7; complete MCP tests pass 7/7 in 3fbaa4e1-8ea1-4b3f-a533-51e1ad01f87b, all 16 targets build in f87e45b6-765e-49c8-a618-cd2eb1efa1ad, and Buildifier passes in 8542838d-92ae-4999-b1e8-fac631629f6f.
  • Final review corrections skip every unavailable Include scope and report only retained line endpoints. Fresh correctness scrutiny also preserves startup errors across repeated initialization and limits UTF-8 suffix removal to locally truncated HTTP bodies.
  • Focused tests pass 2/2 in 99866999-c31d-457f-b64b-c7a15073e7a2. Combined MCP and repo-delivery tests pass 8/8 in e86a5d1c-cadf-4ff6-9647-3e1050e461e6; all 19 affected targets build in 083fbf55-851e-4db4-b8e5-e5871c874faa. Skill quick validation and Buildifier pass.
  • Focused HTTP evidence passes in e80439df-bddd-4a76-b9e1-be6c7f1ed649.
  • Runtime evidence uses semantic admission assertions and eagerly attaches the expected timeout rejection; three consecutive runs pass in e7d69598-b843-4da4-833b-e024d406b8ca.
  • HMR rollback accepts an already-restored prior cache marker after failed import; otherwise it still waits for an exact correlated reload. Three runtime runs pass in 5f9b49e0-d3d3-4f9e-84ec-602dfbe38c77.
  • Regex fallback uses Unicode scalar mode, so . reports one four-byte match for 😀, and the real MCP tool catalog marks cordis_define and cordis_promote as potentially destructive. Both focused regressions pass in 132e2f33-837c-40b2-83b5-4b06ceadfd0f.
  • The complete affected packet passes 8/8 tests in b19d303e-0aca-4097-a191-e81015dc2982, builds all 19 targets in 1c8aa274-dd72-4e6f-9491-de5e283b2c5c, and passes Buildifier in 34f6f5c7-7f44-478b-b939-63ac03c3bbb1.
  • Fallback context is emitted once in line order and never reclassifies a matching line as context. Bounded reads distinguish a retained empty line from EOF. Focused invocation 2528b6ee-7d82-48c9-a607-298a4cef0b9b passes both regressions.
  • The custom manifest.json, hash-named versions/, storage layer, activation worker, and package worker have been removed.
  • Official @deepseek-ai/cordis-plugin-loader, -include, -hmr, and -timer packages are pinned. Bazel launches Node with the HMR package’s documented --expose-internals requirement.
  • Project entries use projects/mcp_cordis/cordis.yaml and ordinary modules under plugins/; scratch entries use the same layout under out/mcp_cordis.
  • Runtime integration proves create, live HMR update, failed activation with on-disk/live rollback, stop, run, promotion, removal, and restart recovery.
  • Direct starter-module tests and the complete starter runtime test pass. A real stdio client proves the complete lifecycle, failed-update rollback, package-log isolation, and restart recovery without replacing the MCP process during an update.
  • Runtime regressions prove exact source-limit round-trip, invalid-timeout side-effect exclusion, never-settling activation rejection, handler-lease draining, and direct/descendant process-group non-liveness at settlement.
  • Affected test and Buildifier invocation 39711671-375a-413f-8a72-e6f9ff892bd3 passed 11/11 on the rebased implementation after the final import-boundary corrections. Affected build invocation 153467fd-e62d-4eab-b260-6754d17fe8e2 passed all 26 targets.
  • These full receipts bind implementation commit 0a93e487. Later amendments are confined to the durable goal record and require proportional diff and formatting validation before publication.
  • Fresh independent review accepted durable-record commit c05bd45a with no actionable findings.
  • PR 32 was republished at the verified rebased head. Its description now records the standard Cordis architecture, and all three obsolete review threads are resolved.
  • Official OpenAI documentation confirms local Codex clients can connect directly to stdio MCP servers and read server instructions.
  • Official DeepSeek documentation states that its dynamic Cordis definitions are process-local and memory-only, establishing the need for the requested persistence layer.
  • Cordis 4.0.1 exposes the required Context, plugin, Fiber.await, Fiber.dispose, and effect-scoped cleanup primitives without depending on DeepSeek Harness’s agent/session/browser packages.
  • MCP SDK v2 provides a stable stdio server and fixed tool registration. Codex does not reliably refresh dynamically added tool schemas, so the accepted design keeps a fixed list/invoke gateway.
  • Repository review selected an ordinary root-workspace Bazel package with a project-owned pnpm lock and Bzlmod dependency fragment.
  • Safe aggregate analysis of 40 top-level recent sessions selected repo_context, git_worktree, and network_probe as the initial reusable packages. No transcript or secret-bearing content will be copied.
  • Architecture: one worker and Cordis root/fiber per active package generation.
  • Storage: immutable content-addressed source and atomic manifests in explicit project or scratch scopes.
  • Update rule: start and validate a candidate, atomically swap the active generation, then drain and dispose the previous generation.
  • MCP rule: stdout is protocol-only; package output is redirected to stderr and out/mcp_cordis/logs.
  • Candidate hash: c9300c9887104777c8915e3d4f390196604e9bd18497bbec319415d1a4ad057f.
  • Focused query, lifecycle/in-memory MCP, and subprocess stdio tests pass.
  • Starter execution test fails at repo_context_search with spawn rg ENOENT; candidate rejected and Attempt 2 opened.
  • Candidate commit: e3e74cb1e573867825347292bf17220a5b9a4a0c.
  • Candidate tree: 079a0c27b86527c6950cc75b0c8b9dbf572d3e4b.
  • Fetched base and direct parent: 7ad2704cd27757355ab36ec8eb1bb27ef9e1d91d.
  • The delivery preparation receipt confirms an exact, conflict-free rebase, task-only path scope, and absence of a remote feature ref or pull request.
  • Focused post-rebase query passes.
  • Integrated post-rebase result: three of four tests pass. Starter packages, stdio, and build coverage pass; lifecycle evidence fails at an elapsed-time drain precondition with actual 0, expected 1.
  • Verdict: refine the test evidence in Attempt 3; do not change the runtime architecture based on this measurement.
  • Final local commit: 7cfef0719075ad372c3bb257ad216b35770356b2.
  • Final local tree: 34153eca0f582af5c641f81bf8c7209b0045ab9a.
  • Direct parent and fetched base: 7ad2704cd27757355ab36ec8eb1bb27ef9e1d91d.
  • Forced project tests: four of four pass on the exact commit.
  • Complete project build: nine of nine targets pass.
  • Forced root Buildifier and exact commit diff check: pass.
  • Review verdict: accept as the final local candidate. Publication was stopped before execution because a rebase-only request does not authorize remote push/PR mutation.
  • PR 32 was published at exact commit 7cfef071; remote branch and PR tree matched the local receipt.
  • Current remote master is 7ad2704c, the direct parent of the published task commit; repository inspection reports needs_rebase: false.
  • PR 24 head is da2085f1, based on ada3ed90. Its projects/agents diff is exactly four files: one bazel-agent update, one goal update, and two new decision-review files.
  • Three PR 32 review threads were independently diagnosed as valid. Their controlling fixes are bounded-success execution, pre-record change limits, and shutdown admission closure followed by lock draining.
  • Verdict: reject 7cfef071 as final; proceed with the scoped three-way import and three behavior-changing corrections in Attempt 4.
  • PR 24 import: bazel-agent batching guidance, result-first goal guidance, and the exact decision-review instruction blob are present. Newer throwaway-record and bounded-delegation guidance remains intact.
  • Execution overflow now retains a combined arrival-order byte prefix, returns only valid UTF-8, stops live process-group members, and reports truncated rather than rejecting. Timeout and spawn errors retain rejection semantics.
  • git_worktree keeps 70d8... as immutable history and activates new exact content hash de978...; its record limit is checked before every porcelain record matcher.
  • Shutdown closes admission, joins the exact admitted package-lock snapshot, then disposes the final active set and awaits retirements through one memoized promise. Initialization rechecks closure after awaited storage boundaries.
  • Four focused Bazel tests pass, including all new regression targets and decision-review offline validation.
  • Integrated Bazel test invocation passes ten of ten tests: the whole MCP package plus all three imported/updated skill configurations.
  • Full affected build passes and validates bazel-agent, goal, and decision-review; root Buildifier passes.
  • Verdict: behaviorally acceptable as a working-tree candidate. Independent diff review and exact commit-bound validation are still required.
  • Max-change review proved the bound placement but rejected the completeness flag when exactly maximum records exist, the missing second-record test, and newline-unsafe pathname capture.
  • Execution review accepted byte bounding, process-group cleanup, and runfiles, but rejected silent invalid-UTF-8 loss and incomplete propagation of host truncation through reusable package result fields.
  • PR 24 provenance review accepted the three-way import and packaging, but found no eval cases for compatible Bazel batching, immutable candidate promotion, or durable-versus-throwaway push behavior.
  • Verdict: refine; passing Attempt 4 checks do not qualify it for commit.
  • Execution tests cover ASCII overflow, multi-byte boundary overflow, malformed UTF-8 both below and above the byte cap, combined stdout/stderr budgeting, timeout rejection, normal nonzero exit, and process-group non-liveness at settlement.
  • git_worktree active hash is 8853aa20665778aeec43e03f2fe975445002d56ed33ea1cf38bef3946381f60d; its manifest retains only that version and unchanged historical hash 70d8f28dc947d19410b8e79bad90cb416303107243d72d062dd70e30f97a2c3b.
  • repo_context active hash is abd0db3e26ec970dcf5cc3ec21b9f2b2c452f9302edc0e10c5231a140b92fbc0; all three manifest version hashes match their exact source bytes.
  • Focused MCP regressions and three skill eval configurations pass 8/8.
  • Full affected test packet passes 12/12; full affected build and three rules_skill validation aspects pass; root Buildifier passes 1/1.
  • Exact commit and post-rebase evidence remain pending, so this is a green working-tree candidate rather than a delivered checkpoint.
  • Current immutable starter hashes are 04b06a7d6277c4a6e8513d970f549ad980a780b68755f28d7b402fe8be26c279 for git_worktree and 94131e058f82328f091613dc68d2717484378066a9c64940d99522c14b48b4d7 for repo_context; line wrapping does not introduce whitespace into the first identifier.
  • Historical version bytes retain their exact filename hashes. The checkout enforces LF for every hash-addressed JavaScript source.
  • The parent activation now owns every ctx.exec() child handle. Focused tests prove immediate live-process absence after inner timeout, outer timeout, startup timeout, output overflow, normal completion with a background child, and a background child inheriting output pipes.
  • Runtime regressions prove shutdown admits complete promotion, rolls back a candidate that fails during active-version persistence, and actively disposes a retired generation whose admitted handler remains gated.
  • Bazel invocation 9b1b2d34-8490-474a-b12c-e2052bf2d90b passes the current process, unavailable-shutdown, and runtime-admission targets 3/3.
  • Bazel invocation 7c680be8-e2a6-4b5b-9b45-4a0390f39a5a passes the current process, ripgrep-byte-field, and runtime-admission targets 3/3.
  • Fresh whole-diff and adversarial supervisor reviews are running. Full integrated, build, skill-aspect, Buildifier, exact-commit, rebase, and remote verification remain unverified after the latest changes.
  • Subject: dirty Attempt 10 tree using @deepseek-ai/cordis-plugin-hmr 1.0.16 with pnpm patch hash ec800d86298faacc86c7717ffa1dce7c28116ab1393b8abc198be6ac02c38489.
  • Primary dependency evidence: the npm registry lists 1.0.16 as the latest release, and current upstream vendor/hmr/src/index.ts retains the same untracked debounced partialReload() plus shared-stash reset behavior.
  • Independent reproduction: a slow top-level-await generation followed by a second write reached {live: "slow", diskLatest: true} with the unpatched package.
  • Patch applicability: git apply --check accepts patches/hmr@1.0.16.patch against the exact resolved 1.0.16 package files.
  • Lock generation: Bazel-managed pnpm invocation a1c50484-20c6-4935-8832-92029d0de3c6 completed successfully with no unrelated dependency resolution changes.
  • Causal runtime regressions: Bazel invocation ac79a8e4-f5d9-4dd7-a821-29bce3d8ece6 passed explicit release-gated top-level evaluation and asynchronous activation overlaps, failed apply rollback and recovery, manual editing, and deterministic disabled activation.
  • Repetition: Bazel invocation 65c1932a-896b-470d-9462-086dd93beaff passed ten runs each of runtime_test and starter_packages_test.
  • Complete project packet: invocations 6490dd57-49e0-4558-b280-f5625db07208, 218e5797-b2d7-44bc-aded-f5df8139ca1c, and 09d4ec2c-aac1-4509-8579-5ef8c5eebe39 passed all project tests, all project builds, and root Buildifier respectively.
  • Project-layout adaptation: Bazel invocation ea2c6c6e-b2e1-425d-bedb-2ac9679de6c5 passed runtime_test after moving the command, internal implementation, launcher, and test suite to their role-based directories.
  • Independent final HMR review accepted patch identity, stashed-change draining, complete Fiber cleanup join, declarations, causal overlap tests, rollback and recovery, and disabled-entry activation. Its only finding was a README sentence describing the superseded publication order; that contract text is corrected in the current tree.
  • The real cmd/mcp_cordis/launch.sh completed MCP initialization and listed all ten tools. While that stdio server remained live, Bazel query invocation 7739c14e-1b22-40c7-94af-b81143e84d4a completed successfully, proving the launcher releases the workspace Bazel lock before serving; SIGINT shut the server down cleanly.
  • Preliminary current-tree Bazel invocations 95d37231-63f9-44f6-9eee-3f0fe8fb4107, d70f61a2-57e5-4ce9-b8fd-27b06bd02a6d, and 1e186c82-3bcd-4048-a534-fe747e1cf79c pass the complete affected test packet (10/10), affected build packet, and root Buildifier check.
  • Guarded delivery inspection bound same-repository PR 32 to local and remote feature OID bc4e5ae97ef9ea968c01b1b2a55403ae032a6a8d, fetched base OID d29f9d471ea467e8dfc75db4eedeedbbae43dc2d, and SSH transport. All nine linear feature commits have the task-bot author and committer identity; the only refusal is version 1’s unconditional multi-commit consolidation guard, which is unchanged on the fetched base.
  • The user explicitly authorized the narrow adapter extension. Its exact-head consolidation path verifies linearity, identity, oldest ownership marker, pull-request metadata matching the requested aggregate projection, signature requirements, and every other inspection refusal before creating one aggregate commit. Integration coverage proves that the pre-consolidation remote head remains the receipt-bound publication lease.
  • Bazel invocations 574dadd5-51b1-443e-b8c2-50ca5d257eb2 and 030a8bb4-2a22-4ece-b632-b3c75572bcee pass the complete adapter suite once, then its Go, skill-validation, and root Buildifier targets three times.
  • Independent adapter review rejected the first implementation because clean ranges had no staged delta. The correction permits an unchanged index only behind validated exact consolidation evidence, while parent-to-tree scope validation continues to reject an empty aggregate. A clean --path regression proves tree preservation and one final commit; Bazel invocation 0d715375-6a8d-4269-ad3e-f8a002888808 passes, and independent re-review accepts the corrected adapter with no remaining findings.
  • After adding upstream-compatible root-consumer visibility to the branch-owned decision-review skill, Bazel invocations 6099d90d-0ade-43b2-b50b-8f7050c26c32 and 7f4b37a4-b970-46ea-bc76-b4a60aeeab59 pass its focused validation and the root Buildifier check; git diff --check also passes.
  • Guarded consolidation and rebase produced one candidate commit on fetched base 63e7b9f0be1e054373415914ff3d2ea2282aa3da. The adapter now stages deletions and symlink-to-directory changes and permits a rebased path to vanish only when the old candidate and new base have the exact same Git tree entry.
  • Exact code-candidate Bazel invocations 13588b19-1f8a-43a7-8006-f9d5d4652670 and 5863ac24-3bb2-47be-99fb-50141e933018 passed all 12 affected tests and all 29 affected builds, including Buildifier and discovery-link validation. Live launcher initialization listed all ten gateway tools while concurrent query invocation 4637f187-d05e-4905-8153-18fca8644ea1 passed.
  • Verdict: the focused race, recovery, layout, repeated-run, project-wide, consolidation, and exact code-candidate evidence pass. The final adapter-and-record rewrite, remote publication, hosted review reconciliation, and final receipt verification remain open.
  • Guarded publication and receipt verification established a clean, single-commit feature branch on base 63e7b9f0be1e054373415914ff3d2ea2282aa3da, with the local and remote tree identical and PR 32 synchronized.
  • The exact-head hosted review completed against the published aggregate and reported three actionable findings: lexical symlink reopening, unbounded /proc inspection retries, and a 100 ms process-start assumption.
  • Repository reads now open the canonical target with O_NOFOLLOW, validate the opened descriptor through /proc/self/fd, inspect and read through that same handle, and retain the existing byte bound. A regression proves an internal symlink read never reopens the lexical alias through ctx.readText.
  • Process-group verification now skips inaccessible per-PID entries and turns three consecutive inspection failures into EXEC_CLEANUP; a direct regression proves the retry bound. The timeout cleanup fixture now allows a five-second startup window before exercising forced group cleanup.
  • Bazel invocation d32cccf7-b5b9-427c-93a1-6b612e32a0aa passed all seven MCP tests. Invocation 9d11ce11-1f79-4077-b61a-efa95a5fc3de built all 16 MCP targets. Invocation aadcc7f6-e2b3-4480-8b76-0607b2017415 passed three runs each of the process-supervisor and repository-context regression targets.
  • Final publication, exact-head review completion, thread reconciliation, and receipt verification are performed by the guarded delivery workflow; the ignored receipt is the authoritative mutable delivery record.
  • Follow-up exact-head review identified lexical reopening in git_worktree. Repository selection and discovered-root use now retain verified directory handles for the complete tool call, and all Git -C arguments address those handles through /proc/<pid>/fd. The focused command-contract test and real Cordis starter-package integration pass together in Bazel invocation 4c3eba8d-32c9-47e9-a257-f8af92ef0c19; invocation 6c638120-90cb-446c-b76e-6d39df3640e5 repeats both targets three times. Invocations ef83ec38-84ed-466e-abbd-ffd6cef892c1 and 16e0c322-adc7-4763-8ff4-11d5f38a4172 pass the complete seven-test and sixteen-target MCP packets.
  • The next exact-head pass identified the same lexical reopening in repo_context’s ripgrep and Git metadata branches. Selected search paths and repository directories now remain open while subprocesses address them through /proc/<pid>/fd; reported ripgrep paths are mapped back to stable workspace-relative names. Directory kind and entry inspection also use the selected handle. Bazel invocation a3f4ed56-a44b-46d6-8717-c38ecc7f05eb passes the focused context contract and real ripgrep/Git starter integration together. Invocation e7af6e8f-823e-40ef-a833-dcb0a704f46f repeats both three times, while invocations 9fd4d465-957a-424f-9bb8-f6e10eb93009 and 4a464ddd-f646-4b9a-aaab-a411bf930ee0 pass the complete seven-test and sixteen-target MCP packets.
  • The terminal exact-head review found that the JavaScript regex fallback could monopolize the MCP event loop through backtracking and could not match ripgrep’s Unicode regex semantics. Regex search now requires ripgrep when the executable is unavailable, while the bounded fixed-string fallback is preserved. Bazel invocation b98534c0-1667-462b-81d5-ee393fca343b passes the focused context and real starter integration targets; invocations 4689e7cb-9600-4b35-ad7a-97e02cd6730c and 557f322c-4fad-4358-bf5f-98ad9b8972b0 pass the complete seven-test and sixteen-target MCP packets.
  • The next exact-head pass found that invalid UTF-8 replacement decoding changed fixed-search byte offsets when ripgrep was unavailable. The fallback now verifies that decoded text round-trips to the original bytes and fails closed otherwise. Bazel invocation 449ea2c4-4d52-44d2-b7d1-b1e9745359bd passes the focused context and real starter integration targets; invocations 77bae252-af20-4242-89d8-7d6bc242b64f and 3a0bd136-a327-416a-8128-aaaec171bd9c pass the complete seven-test and sixteen-target MCP packets.

1.15.1.5 -

Failure ledger

Back to durable goal

  • Candidate: published standard-Cordis commit deaa2dcd.
  • Result: hosted review found three valid defects after the earlier local whole-diff review had accepted the runtime architecture.
  • Causes: the no-ripgrep fallback recursively traversed ignored and hidden files, JavaScript string indexes were exposed as byte offsets, and a bounded textual HTTP body decoded an incomplete trailing UTF-8 sequence.
  • Strategy delta: fail closed for directory fallback, retain explicit-file fallback with true UTF-8 offsets, and decode only a complete UTF-8 prefix.
  • Regression guard: explicit hidden-file versus directory cases, fixed and regex non-ASCII offsets, and a one-byte multibyte HTTP preview must pass with the complete MCP test/build packet.
  • Follow-up causes: lowercasing a line could change UTF-16 length before offset projection, fallback glob filtering contradicted ripgrep’s explicit-path precedence, and unfiltered listing did not preserve a healthy scope after partial startup.
  • Follow-up guard: length-changing İx, explicit file plus excluding glob, and malformed-project/healthy-scratch listing cases pass with the complete MCP packet.
  • Final-review causes: config parsing alone did not identify a scope whose Include never mounted, and bounded reads reused the requested endpoint after clipping content.
  • Fresh-scrutiny cause: idempotent initialization returned an empty error list after partial startup because only the first call retained local failures.
  • Additional fresh-scrutiny cause: UTF-8 suffix trimming did not distinguish a byte-cap split from a naturally completed malformed response body.
  • Final guard: missing-module and malformed-config scopes are both skipped by unfiltered listing, clipped reads report retained endpoints, and repeated initialization preserves structured scope errors. Textual bodies trim an incomplete suffix only when locally truncated. repo-delivery now makes this correctness scrutiny an explicit post-edit gate.
  • Candidate: post-review Attempt 8 aggregate validation.
  • Result: the complete packet failed only when system load delayed a wall-clock <400 ms assertion and allowed an expected 300 ms rejection to occur before its assertion was attached.
  • Cause: the test inferred synchronous admission from elapsed time and created a temporary unhandled-rejection window while waiting for a PID file.
  • Strategy delta: assert the wrapped synchronous-admission error semantics and attach the expected rejection before awaiting the fixture handshake.
  • Regression guard: the complete runtime target passes three consecutive concurrent runs without loosening production deadlines.
  • Candidate: loaded exact aggregate validation after the evidence correction.
  • Result: a failed source update occasionally reported reload_rollback_failed even though Cordis had already restored the prior module cache.
  • Cause: failed HMR import restores its cache and returns without emitting hmr/reload; the host always required a second reload event after restoring prior bytes.
  • Strategy delta: after restoring bytes, accept the exact prior cache marker immediately; retain correlated HMR waiting when the failed candidate marker actually reached the cache.
  • Regression guard: three concurrent runtime runs prove failed-update rollback, source restoration, and subsequent healthy invocation.
  • Command: bazel_agent bazel query //projects/mcp_cordis:all
  • Result: failed before target analysis.
  • Cause: rules_js requires pnpm v10 workspaces to declare onlyBuiltDependencies, including when lifecycle actions are disabled.
  • Evidence: repository fetch failed in verify_lifecycle_hooks_specified with that exact requirement.
  • Strategy delta: declare an empty lifecycle allowlist in the project-owned workspace and regenerate its exact lock before rerunning the same query.
  • Regression guard: successful focused query and build of the translated npm repository.
  • Command: bazel_agent bazel query //projects/mcp_cordis:all
  • Result: npm translation succeeded; target loading stopped because the deliberately non-empty starter-package glob had not yet been populated.
  • Cause: implementation was queried while the parallel starter-package draft was still outstanding.
  • Strategy delta: retain the non-empty invariant and add the three accepted packages before rerunning the same query.
  • Regression guard: the starter_packages target must contain real files and the focused query must succeed.
  • Command: bazel_agent bazel test //projects/mcp_cordis:runtime_test
  • Result: both test bodies completed in under 400 ms, one failed, but a worker retained by the failing test kept the process alive until the run was interrupted at 144 seconds.
  • Cause: the test registered cleanup only along its success path, so the first assertion failure leaked its runtime and obscured the underlying defect.
  • Strategy delta: register unconditional node:test teardown before the first assertion, then rerun to expose the real behavioral failure promptly.
  • Regression guard: the target must terminate normally on both passing and failing assertions.
  • Command: focused runtime test after unconditional teardown.
  • Result: target terminated in 0.8 seconds; the MCP gateway test passed and the lifecycle test stopped at its syntax-rollback assertion.
  • Cause: the runtime correctly exposed activation_failed as the error’s machine-readable code, while the test searched only its human message.
  • Strategy delta: assert the stable code and separately check the underlying syntax diagnostic.
  • Regression guard: failed activation retains the working v2 generation and reports both the stable wrapper code and candidate cause.
  • Command: bazel_agent bazel test //projects/mcp_cordis:starter_packages_test.
  • Result: failed in 0.4 seconds with spawn rg ENOENT.
  • Cause: repo_context_search invoked the preferred ripgrep engine without a fallback, while the Bazel test PATH intentionally does not expose the host installation.
  • Attempted strategy: none before this measurement.
  • Strategy delta: Attempt 2 adds a bounded in-process fallback while retaining ripgrep when available.
  • Regression guard: the unchanged hermetic starter test must exercise a successful search and all remaining package handlers.
  • Latest result: resolved in Attempt 2. The unchanged hermetic test passes with the new bounded JavaScript fallback and executes all eight tools.
  • Command: bazel_agent bazel test //projects/mcp_cordis:all on rebased commit e3e74cb1e573867825347292bf17220a5b9a4a0c.
  • Result: three test targets pass; runtime_test reports actual drain count 0, expected 1.
  • Cause: the test delays the old request for 150 ms but must start and validate a replacement worker before retirement. Nothing guarantees the swap occurs before the fixed request delay expires.
  • Attempted strategy: a 20 ms sleep before starting replacement; this proves that the old request started, not that it remains active at the later swap.
  • Strategy delta: Attempt 3 uses an explicit started marker and release latch.
  • Regression guard: run the focused lifecycle test and complete suite with no wall-clock assumption controlling the drain-count assertion.
  • Command: bazel_agent bazel test //:buildifier_test during Attempt 3.
  • Result: failed with an exact three-line ordering diff in projects/mcp_cordis/BUILD.bazel.
  • Cause: the external-style :node_modules/... label followed the two shorter local labels in runtime_test.data.
  • Strategy delta: apply Buildifier’s exact lexical ordering and rerun the same repository formatter target.
  • Regression guard: //:buildifier_test must pass on the frozen candidate.
  • Latest result: resolved. The forced Buildifier test passes on commit 7cfef071.
  • Intended command: repository delivery publish using the exact preparation receipt and validated head 7cfef071.
  • Result: the approval gate rejected execution before any push or pull request mutation.
  • Cause: the latest user instruction explicitly requested a rebase and did not authorize the separate consequential remote publication operation.
  • Safe attempts: preparation, exact-tree validation, and local commit are complete; no workaround or indirect mutation was attempted.
  • Exact unblocker: explicit user authorization to push this branch and create or update its pull request.
  • Latest result: resolved. The user explicitly requested push and continued goal execution; PR 32 was published at 7cfef071 and remains the authorized delivery vehicle for the corrected candidate.
  • Candidate: PR 32 commit 7cfef0719075ad372c3bb257ad216b35770356b2.
  • Result: automated review found three independently reproducible defects.
  • Causes: output overflow rejects instead of returning bounded data with a truncation marker; branch records bypass max_changes; shutdown snapshots active workers before an admitted activation finishes.
  • Strategy delta: Attempt 4 changes each controlling mechanism and adds a black-box regression for each, rather than suppressing or merely replying to the review.
  • Regression guard: republish only when all focused tests, the full MCP Cordis package, imported skill validation, and Buildifier pass on one exact commit.
  • Latest result: resolved in the Attempt 4 working tree. Four focused tests, all ten integrated tests, the complete package build, three skill-validation aspects, and root Buildifier pass. Exact-commit rerun remains required.
  • Candidate: uncommitted Attempt 4 working tree after all recorded tests passed.
  • Result: four directly related semantic and evidence gaps survived.
  • Causes: invalid UTF-8 loss did not set truncated; several starter fields ignored host truncation; Git status inferred truncation from result length instead of actual omission and used newline-unsafe path regexes; imported skill eval cases did not exercise their new contracts.
  • Strategy delta: Attempt 5 makes loss explicit, propagates truncation by field, parses one-record lookahead semantics, adds newline/exact-limit tests, and expands offline eval cases before another integrated run.
  • Regression guard: independent review must find no correctness issue before delivery preparation; a green test suite alone is insufficient.
  • Evidence: independent shutdown review of Attempt 4.
  • Cause: #handleUnavailable() removes the activation from #active, while its worker termination is asynchronous and was not added to #retirements.
  • Strategy delta: track the activation’s idempotent dispose() promise as a retirement at the same moment it is removed.
  • Regression guard: a deterministic unavailable-then-shutdown scenario must prove shutdown does not finish before the teardown promise.
  • Evidence: current base 7ad2704c mentions decision-review in AGENTS.md, but the referenced package is absent from that tree.
  • Cause: the skill exists in open PR 24, not in the rebased master commit.
  • Strategy delta: import only PR 24’s four projects/agents changes, merged against current guidance, and supply validation assets required by current repository policy.
  • Regression guard: build and validate the imported skill through its Bazel skill_library and offline Promptfoo target.
  • Latest result: resolved in the working tree. decision-review matches PR 24’s instruction blob and passes quick validation, offline Promptfoo loading, and the repository skill-validation aspect.
  • Candidate: green uncommitted Attempt 5 working tree.
  • Result: focused tests passed 8/8, integrated tests passed 12/12, the affected build and skill aspects passed, and Buildifier passed; independent review nevertheless found release-blocking defects.
  • Causes: immediate Worker.terminate() can bypass detached-child cleanup; already-admitted handlers can spawn after one-shot disposal cleanup; promotion is outside the shutdown lock snapshot; an unavailable candidate’s one-shot notification can be ignored during persistence; and always-success output truncation silently changes retained package-version semantics.
  • Additional gaps: command signals/failures, exact-bound search and omitted records, Git optional writes/history framing, LF hash portability, weak integration assertions, and contradictory or domain-specific imported-skill rules.
  • Strategy delta: Attempt 6 versions partial-output behavior explicitly, closes process and runtime admission, creates sole final package candidates, and binds every completeness claim to a direct regression.
  • Regression guard: no delivery preparation until a fresh review accepts the new candidate after all invalidated gates pass.
  • Candidate: green Attempt 6 working tree before parent-owned supervision.
  • Result: focused tests, the 14/14 integrated packet, build, skill validation, and Buildifier passed; independent reviews still rejected release.
  • Causes: outer timeouts settled before cleanup; signaling a process group was called reaping; the worker’s native-spawn/PID-publication window could not be both bounded and orphan-safe; direct exit could leave inherited pipes open; shutdown awaited but did not dispose retired generations; ripgrep byte fields could be returned as empty complete text; and durable records were stale.
  • Strategy delta: the parent activation now owns process spawning and group cleanup, runtime tracks retired activations rather than only their promises, byte fields set explicit truncation, and the durable goal records every verdict and invalidated gate.
  • Regression guard: immediate non-liveness assertions, inherited-pipe cleanup, fatal cleanup ordering, retired-generation shutdown, byte-field cases, and a fresh adversarial review must pass before final integrated validation.
  • Candidate: published PR 32 checkpoint 7cfef071 and its Attempt 6 descendants.
  • Result: the user rejected the per-package manifest.json, immutable versions/, and active-pointer design as nonstandard and temporary-looking.
  • Cause: the runtime had grown a second package manager instead of using Cordis Loader entries, Include-backed configuration, HMR, and Git history.
  • Strategy delta: Attempt 7 deletes the custom store and workers, pins the official services, and uses cordis.yaml plus ordinary ESM modules.
  • Regression guard: no package manifest, hash-named source snapshot, custom storage layer, or version-file .gitattributes rule may remain.
  • Candidate: independently reviewed Attempt 7 working tree.
  • Result: review found that accidental stdout writes could corrupt stdio, Promise/async-iterator activation or top-level await could wedge lifecycle mutation, filename-only HMR events could acknowledge the wrong write, and response timeout could leave invocation-owned children running.
  • Strategy delta: reserve a private protocol stream, use Node’s ESM parser to reject top-level await, require synchronous object activation, correlate managed source with a named-export token, and use an invocation-scoped supervisor that cancels and joins ctx.exec().
  • Regression guard: real stdio logging, hung activation, source round-trip, invalid/expired invocation, and descendant non-liveness tests all pass.
  • Command: first Attempt 7 runtime_test initialization.
  • Result: HMR rejected startup with --expose-internals is required for HMR service.
  • Cause: the optional native fallback peer was not reliably visible through Bazel’s strict pnpm layout.
  • Strategy delta: every runtime-bearing Bazel launcher passes the official package’s supported --expose-internals Node flag. Automatic peer install is disabled because all required peers are pinned explicitly and the optional native fallback is unnecessary.
  • Regression guard: the complete project build and all runtime tests must boot through the Bazel launchers.
  • Command: runtime and starter tests without Node’s force-exit option.
  • Result: both test bodies passed but timed out with live FSEventWrap resources after runtime.shutdown().
  • Cause: shutdown guarded root.fiber.dispose() with root.fiber.uid; Cordis assigns the root Fiber uid 0, so the truthiness check skipped every root-owned cleanup effect, including HMR watchers.
  • Strategy delta: dispose whenever the root Fiber exists, independent of its numeric uid. Remove force-exit workarounds from tests and keep stdio shutdown graceful.
  • Regression guard: runtime, starter, and real stdio tests must exit normally without --test-force-exit or process.exit().
  • Candidate: published commit cfab0fb5 after a completed hosted review.
  • Result: the review summary completed, but GraphQL thread inspection exposed one unresolved older regex-parity finding and one new annotation finding.
  • Cause: regex fallback omitted JavaScript Unicode mode and matched surrogate halves; source-overwriting MCP tools declared destructiveHint: false.
  • Strategy delta: enable Unicode scalar matching, mark both potentially overwriting tools destructive, and treat the review-thread graph—not the summary state—as the authoritative review ledger.
  • Regression guard: an astral . fallback match must be one UTF-8 span, and real stdio tool discovery must expose both destructive annotations.
  • Candidate: published review correction bc4e5ae9.
  • Result: the next hosted review found duplicate, out-of-order fallback context around adjacent matches and a null endpoint for an existing empty line.
  • Cause: context filtering knew only the current matching line, while bounded reads inferred range existence from non-empty selected text.
  • Strategy delta: precompute match classifications, emit the union of match and context lines once in source order, and track whether the requested range exists separately from its content.
  • Regression guard: adjacent matches followed by context must emit match/match/context in line order; a selected empty line reports its line number while a start past EOF reports null.
  • Candidate: local Attempt 9 changes above published head bc4e5ae9, with fetched base d29f9d47.
  • Result: read-only delivery inspection reports nine feature commits and refuses preparation; version 1 will not infer consolidation ownership.
  • Cause: only the first commit carries the adapter’s ownership disclaimer, while the adapter supports preparation of at most one feature commit.
  • Rejected workaround: direct rebase, reset, cherry-pick, or a replacement branch would bypass the GitHub adapter’s explicit safety refusal.
  • Required strategy delta: obtain scope to add a guarded exact-head, merge-base-aware consolidation path to repo_delivery, or have that support land separately before resuming the rebase.
  • Resolution: the user explicitly authorized a guarded adapter extension. repo_delivery prepare --consolidate <exact-inspected-head> now verifies a merge-free linear range, identical author and committer identities, the oldest commit’s ownership marker, unchanged pull-request projection, signature preservation, and every unrelated refusal before replacing the range. Its integration test also proves the prior remote tip remains the receipt-bound publication lease.
  • Candidate: Attempt 9 with unmodified @deepseek-ai/cordis-plugin-hmr 1.0.16.
  • Result: a deterministic slow top-level-await replacement followed by a second write left the latest source on disk but the first replacement live.
  • Cause: debounced partialReload() work was not serialized; each successful run reset one shared stash even when a later change arrived during import.
  • Rejected wrapper workaround: public HMR emits neither import-failure nor settled-activation events, so a wrapper gate would either reopen unsafely on a timeout or wedge permanently after failure.
  • Strategy delta: Attempt 10 uses standard pnpm patching to serialize the owning HMR task, snapshot each change set, and drain changes observed while it runs.
  • Regression guard: overlapping writes during both slow module evaluation and slow asynchronous activation must converge to the latest persisted source.

1.15.1.6 -

Requirements and constraints

Back to durable goal

  • The project is named mcp_cordis and lives under projects/.
  • Reuse Cordis itself rather than reimplementing its lifecycle architecture.
  • Keep reusable runtime code under the project for later reuse.
  • Keep disposable runtime code under out.
  • Seed the project with packages based on recurring past-session needs.
  • Security hardening is not the priority on this dedicated LLM machine.
  • Codex must load the MCP from project-scoped configuration so different clones and linked worktrees use their own source and disposable state.
  • Use bazel_agent for every Bazel command.
  • Pin external dependencies reproducibly and retain required notices.
  • Keep disposable task scratch under out/mcp_cordis; maintain this explicitly requested reusable goal under projects/mcp_cordis/goals.
  • Preserve unrelated working-tree changes.
  • Prefer a narrowly scoped project and focused validation.
  • “Based on past sessions” means extracting generic recurring workflows, not copying private conversation text, credentials, or secret-bearing data.
  • Host-only JavaScript packages are the initial scope; browser UI packages are not required for the first working server.
  • A stable gateway invocation tool is required because MCP clients differ in when they consume tool-list change notifications.
  • 2026-08-30: project name changed from agent_extension_host to codex_cordis, then finally to the client-neutral mcp_cordis.
  • 2026-08-30: storage clarified as two-tier: reusable project packages and disposable out packages.
  • 2026-08-30: the user promoted the runtime-extension goal directory from disposable out coordination to durable project documentation for future reuse.
  • 2026-08-30: remote master advanced and the user explicitly requested a rebase before implementation continued. The task commit was rebased from 775f44d3b56146005e44980f3cf948785f963ba0 onto 7ad2704cd27757355ab36ec8eb1bb27ef9e1d91d; all prior checks were treated as invalid until rerun.
  • 2026-08-30: after publication, the user explicitly expanded the delivery to include only the projects/agents subtree changes from PR 24. PR 24 changes four files there: bazel-agent, goal, and the new decision-review package. Import those changes three-way against current master; do not import its unrelated render or infrastructure content.
  • 2026-08-30: the user rejected the custom per-package manifests and requested standard solutions. Runtime persistence must use official Cordis loader entries and cordis.yaml; normal reusable files and Git replace committed content-addressed source history.
  • 2026-08-30: after review-driven fixes exposed additional correctness gaps, the user required repo-delivery to invalidate prior correctness verdicts after code changes and require fresh diff-focused scrutiny beyond green tests.
  • 2026-08-30: the user rejected the HMR race-handling complexity and explicitly required the simplest robust MCP wrapper for loading DeepSeek/Cordis plugins. Source-tool success therefore means validated atomic persistence and an official Cordis load/reload request, not a custom synchronous activation transaction or on-disk rollback protocol.
  • 2026-08-30: the user required per-workspace Codex loading. The checked-in .codex/config.toml must resolve the active linked worktree; the launcher must release Bazel’s output-base lock before the MCP begins serving stdio.
  • 2026-08-30: remote master advanced again to d29f9d471ea467e8dfc75db4eedeedbbae43dc2d. The user requested another rebase and incorporation review. Preserve the new projects/goal redesign and do not resurrect its deleted predecessor under projects/agents.
  • 2026-08-30: after the delivery adapter refused the exact nine-commit task range, the user explicitly authorized extending repo_delivery with a guarded exact-head consolidation operation and then repeated the request to rebase, review, and incorporate the upstream changes.

1.16 - Nexus security plugin

Security plugin for Sonatype Nexus 3

This plugin allows you to perform a check every time an artifact is requested from a repository

  • A request handler that checks all requests to repositories
  • Capability controlling the request handler
  • A task that periodically updates the capability using a remote source
  • Sonatype Nexus 3 plugin
  • Java

diagram

1.16.1 - Model

Attributes of some classes
etag: c849a44121f823c806f604d6568d9e89 (class java.lang.String)
last_modified: 2021-10-22T15:57:10.000Z (class org.joda.time.DateTime)
hashCodesMap: (class java.util.HashMap)
    org.sonatype.nexus.common.hash.HashAlgorithm@7ce01bd8: bcbb583a5a4b4767de8ac020dea3d54011fee961
    org.sonatype.nexus.common.hash.HashAlgorithm@5a3efc26: deaf32dcd9ab821e359cd8330786bcd077604b5c5730c0b096eda46f95c24a2d
    org.sonatype.nexus.common.hash.HashAlgorithm@5b0c0740: c849a44121f823c806f604d6568d9e89
org.sonatype.nexus.repository.storage.Asset:
  metadata: (AttachedEntityMetadata)
    schema: assetPath
    document:
      "#74:0": >-
        bucket:#57:1,format:pypi,last_updated:Fri Jul 01 12:46:21 UTC 2022,attributes:[5],component:#65:0,
        name:packages/pip/21.3.1/pip-21.3.1-py3-none-any.whl,size:1723581,content_type:application/zip,created_by:anonymous,
        created_by_ip:80.78.253.49,blob_ref:default@E1F281C2-0A159DAD-4208CEFD-524F990B-0B4DDE11:739a4ecb-73fc-4422-a7d7-c93c8ad069c6,
        last_downloaded:Fri Jul 01 04:44:03 UTC 2022,blob_created:Wed Jun 29 07:01:34 UTC 2022,blob_updated:Wed Jun 29 07:01:34 UTC 2022
    name: packages/pip/21.3.1/pip-21.3.1-py3-none-any.whl
org.sonatype.nexus.repository.cache.CacheInfo:
  lastVerified: 2022-07-01T12:46:21.457Z
  cacheToken: 'null'
org.apache.shiro.subject.support.DefaultSubjectContext.SESSION_CREATION_ENABLED: false (class java.lang.Boolean)
Key[type=org.sonatype.nexus.security.SecurityFilter, annotation=[none]].FILTERED: true (class java.lang.Boolean)
authcAntiCsrf.FILTERED: true (class java.lang.Boolean)
nx-authc.FILTERED: true (class java.lang.Boolean)
org.apache.shiro.web.servlet.ShiroHttpServletRequest_SESSION_ID_URL_REWRITING_ENABLED: false (class java.lang.Boolean)
javax.servlet.include.servlet_path: /repository/pypi/packages/pip/21.3.1/pip-21.3.1-py3-none-any.whl (class java.lang.String)
nexus.user.principal: admin (class java.lang.String)
nx-anonymous.FILTERED: true (class java.lang.Boolean)
nexus.user.id: admin (class java.lang.String)
nx-apikey-authc.FILTERED: true (class java.lang.Boolean)
security.authorized: true (class java.lang.Boolean)
nexus.analytics.format_request_rates.marked: true (class java.lang.Boolean)
com.sonatype.nexus.repository.pypi.AssetKind: PACKAGE (class com.sonatype.nexus.repository.pypi.AssetKind)
local.attribute.org.sonatype.nexus.repository.view.handlers.HandlerContributor.extended: true (class java.lang.Boolean)
org.sonatype.nexus.repository.view.matchers.token.TokenMatcher$State: >-
  org.sonatype.nexus.repository.view.matchers.token.TokenMatcher$1@19f23c0b ((class org.sonatype.nexus.repository.view.matchers.token.TokenMatcher$1))
proxy: (class java.util.HashMap)
  contentMaxAge: 0.0
  remoteUrl: https://pypi.org
  metadataMaxAge: 0.0
negativeCache: (class java.util.HashMap)
  timeToLive: 0.0
  enabled: false
storage: (class java.util.HashMap)
  strictContentTypeValidation: false
  blobStoreName: default
httpclient: (class java.util.HashMap)
  blocked: false
  connection:
    useTrustStore: true
    autoBlock: false
checksum: (class org.sonatype.nexus.common.collect.DetachingMap)
  sha1: bcbb583a5a4b4767de8ac020dea3d54011fee961
  sha256: deaf32dcd9ab821e359cd8330786bcd077604b5c5730c0b096eda46f95c24a2d
  md5: c849a44121f823c806f604d6568d9e89
cache: (class org.sonatype.nexus.common.collect.DetachingMap)
  last_verified: Fri Jul 01 13:07:08 UTC 2022
provenance: (class org.sonatype.nexus.common.collect.DetachingMap)
  hashes_not_verified: false
pypi: (class org.sonatype.nexus.common.collect.DetachingMap)
  summary: The PyPA recommended tool for installing Python packages
  author: The pip developers
  description: ...
content:
  etag: c849a44121f823c806f604d6568d9e89
  last_modified: Fri Oct 22 15:57:10 UTC 2021
etag: c849a44121f823c806f604d6568d9e89
last_modified: 2021-10-22T15:57:10.000Z (class org.joda.time.DateTime)
hashCodesMap: (class java.util.HashMap)
  org.sonatype.nexus.common.hash.HashAlgorithm@3d97cbd0: deaf32dcd9ab821e359cd8330786bcd077604b5c5730c0b096eda46f95c24a2d, org.sonatype.nexus.common.hash.HashAlgorithm@675317cb=c849a44121f823c806f604d6568d9e89
  org.sonatype.nexus.common.hash.HashAlgorithm@67bcbee7: bcbb583a5a4b4767de8ac020dea3d54011fee961
  org.sonatype.nexus.repository.storage.Asset: (class org.sonatype.nexus.repository.storage.Asset)
    metadata: (AttachedEntityMetadata)
      schema: assetPath
      document: (#74:0)
        bucket: #57:1
        format: pypi
        last_updated: Fri Jul 01 13:25:15 UTC 2022
        attributes: [5]
        component: #65:0
        name: packages/pip/21.3.1/pip-21.3.1-py3-none-any.whl
        size: 1723581
        content_type: application/zip
        created_by: anonymous
        created_by_ip: 80.78.253.49
        blob_ref: default@E1F281C2-0A159DAD-4208CEFD-524F990B-0B4DDE11:739a4ecb-73fc-4422-a7d7-c93c8ad069c6
        last_downloaded: Fri Jul 01 04:44:03 UTC 2022
        blob_created: Wed Jun 29 07:01:34 UTC 2022
        blob_updated: Wed Jun 29 07:01:34 UTC 2022
      name: packages/pip/21.3.1/pip-21.3.1-py3-none-any.whl
org.sonatype.nexus.repository.cache.CacheInfo: (class org.sonatype.nexus.repository.cache.CacheInfo)
  lastVerified: 2022-07-01T13:25:14.841Z
  cacheToken: 'null'

1.16.2 - Releases

Releases

1.16.2.1 - head

Release head

1.17 - Renders

Repository-owned render assets and their acceptance evidence

This project owns reusable Blender assets, their controlling references, and compact goal records that bind acceptance evidence to exact candidate bytes.

The Reimu Fumo work lives under assets/reimu_fumo/. Its reusable asset target will be added only after a candidate passes the visual, structural, animation, and exact-byte delivery gates in goals/reimu-fumo-finish/.

Working candidates and intermediate renders belong under the repository-root out/reimu_fumo_finish/ directory. They are not accepted or durable merely because they exist there. A historical packet may move into the source tree only when exact bytes and provenance are verified and it is labeled with its actual rejected or accepted state.

1.18 - Rules binary toolchain

Bazel toolchains for packaged executable binaries

rules_binary_toolchain creates Bazel toolchains and runnable targets for packaged executable binaries. Archive entries can include runtime files, which the generated binary targets expose through Bazel runfiles.

1.18.1 - Bzl

Bazel code

Each archive binaries entry requires a name and path. It can also set runtime_files to a list of Bazel glob patterns relative to the unpacked archive. The generated <name>_native_binary exposes matching files as runfiles; <name>_filegroup exposes the binary and those same files.

Omit runtime_files when the binary needs no extra runtime files.

1.19 - Rules Dnscontrol

Bazel-aware DNSControl configuration packaging

rules_dnscontrol packages a DNSControl JavaScript entrypoint together with its record configuration files and emits a generated requires.json manifest of relative paths matching the Bazel runfiles tree. Record symlinks retain a .json suffix so DNSControl parses them as JSON. Load the manifest with require() and load each listed path with another require() call; DNSControl’s JavaScript loader does not implement CommonJS module.exports.

1.20 - Rules docs

Bazel documentation packaging rules

rules_docs packages Markdown documentation under a common archive prefix.

Add the module dependency:

bazel_dep(name = "rules_docs", version = "<VERSION>")

Then declare the package documentation. srcs defaults to glob(["*.md"]); visibility is optional.

load("@rules_docs//docs:defs.bzl", "docs_filegroup")

docs_filegroup(
    name = "docs",
    deps = ["child"],
)

Relative dependency names without a colon are normalized to the child package’s docs target. prefix defaults to the current package beneath content/docs/.

Generation support is packaged separately so consumers of the documentation rule do not inherit Gazelle and Go dependencies. Add it as a development-only module dependency:

bazel_dep(
    name = "rules_docs_gazelle",
    version = "<VERSION>",
    dev_dependency = True,
)

Add the public language target to the repository’s custom Gazelle binary:

load("@gazelle//:def.bzl", "gazelle_binary")

gazelle_binary(
    name = "gazelle_binary",
    languages = [
        "@rules_docs_gazelle//gazelle",
    ],
)

The extension only operates in directories where both a BUILD file and a README.md already exist. Newly generated rules use glob(["*.md"]) and are visible only to their nearest ancestor Bazel package. Existing srcs, deps, visibility, and prefix attributes are preserved.

The public @rules_docs_gazelle//gazelle:gazelle_docs binary contains only this extension and can update a nested workspace without initializing unrelated language plugins from its parent repository.

1.21 - Rules docs Gazelle

Gazelle extension for Bazel documentation packaging rules

rules_docs_gazelle adds a docs_filegroup to existing Bazel packages that contain a README.md. The generated rule loads its macro from rules_docs.

Add rules_docs as a normal dependency and this generator as a development dependency:

bazel_dep(name = "rules_docs", version = "<VERSION>")
bazel_dep(
    name = "rules_docs_gazelle",
    version = "<VERSION>",
    dev_dependency = True,
)

Add the public language target to the repository’s custom Gazelle binary:

load("@gazelle//:def.bzl", "gazelle_binary")

gazelle_binary(
    name = "gazelle_binary",
    languages = [
        "@rules_docs_gazelle//gazelle",
    ],
)

The extension only operates in directories where both a BUILD file and a README.md already exist. Newly generated rules use glob(["*.md"]) and are visible only to their nearest ancestor Bazel package. Existing srcs, deps, visibility, and prefix attributes are preserved.

The public @rules_docs_gazelle//gazelle:gazelle_docs binary contains only this extension and can update a nested workspace without initializing unrelated language plugins from its parent repository.

1.22 - Rules Hugo

Bazel rules for Hugo sites

rules_hugo builds Hugo sites with a registered Hugo toolchain. It keeps the site archive in the target configuration and the Hugo binary in the execution configuration so site sources are not rebuilt for the execution platform.

al_hugo_site wraps a site source archive and its PostCSS tooling. al_hugo_run_binary builds the site with the registered Hugo toolchain and al_hugo_binary exposes a runnable Hugo command for a site. The optional al_hugo_worker rule runs the build through a persistent worker.

bazel_dep(name = "rules_hugo", version = "<VERSION>")

The Hugo toolchain is generated by the al_hugo_extension module extension, not declared in @rules_hugo//pkg/bzl. Declare the extension in the root module, request the toolchain archives for the Hugo version, and register the generated toolchain repository:

al_hugo_extension = use_extension(
    "@rules_hugo//pkg/bzl:al_hugo_extension.bzl",
    "al_hugo_extension",
)
al_hugo_extension.toolchains(
    name = "my_hugo_toolchain",
    version = "0.165.0",
)
use_repo(
    al_hugo_extension,
    "my_hugo_toolchain_os_linux_cpu_x86_64",
)
register_toolchains("@my_hugo_toolchain_os_linux_cpu_x86_64")

The generated repository name is "<name>_<os>_<cpu>" for each platform in the requested version’s archive set. See projects/alwaldend.com/include.MODULE.bazel for a complete example that also wires the Hugo lock file and remote themes.

1.23 - Rules Promptfoo

A pinned Bazel runner for Promptfoo skill evaluations

rules_promptfoo runs repository skills through a pinned Promptfoo CLI. It keeps dependency resolution reproducible in Bazel while deliberately running model calls only at test runtime.

Add the module and its skill-provider dependency:

bazel_dep(name = "rules_promptfoo", version = "<VERSION>")
bazel_dep(name = "rules_skill", version = "<VERSION>")

The development checkout uses sibling local_path_override declarations. Published releases must replace those local overrides with registry versions.

load("@rules_promptfoo//promptfoo:defs.bzl", "promptfoo_test")

promptfoo_test(
    name = "answer_question_eval",
    config = "promptfooconfig.yaml",
    skills = ["//projects/agents/skills/answer-question:skill"],
    env_inherit = [
        "CODEX_HOME",
        "CODEX_PATH_OVERRIDE",
    ],
    reuse_codex_login = True,
)

The runner physically copies each selected SkillInfo.files_by_path bundle to an isolated Bazel test-temporary workspace/.agents/skills/<name>/ tree. Point the Codex SDK provider at the exported workspace and, when using a compatible host Codex executable, at the exported executable path:

prompts:
  - "{{ question }}"
providers:
  - id: openai:codex-sdk
    config:
      codex_path_override: "{{ env.CODEX_PATH_OVERRIDE }}"
      working_dir: "{{ env.PROMPTFOO_SKILL_WORKSPACE }}"
      cli_env:
        CODEX_HOME: "{{ env.PROMPTFOO_SUBJECT_CODEX_HOME }}"
tests:
  - vars:
      question: Why is the sky blue?
    assert:
      - type: skill-used
        value: answer-question

Live eval targets are tagged manual, requires-network, no-cache, no-remote, and local. They also pass --no-cache, --no-write, and --no-share to Promptfoo; local prevents sandboxed or remote execution when the caller opts into host Codex credentials. The runner exports a separate empty PROMPTFOO_JUDGE_WORKSPACE so a model judge need not discover the skill it grades. Explicit results are preserved as the Bazel undeclared output results.json; Promptfoo configuration, cache, isolated workspaces, and subprocess temporary files stay in a mode-0700 directory below Bazel’s absolute TEST_TMPDIR and are removed on exit. Bazel owns and cleans that private parent directory as a second cleanup boundary. Callers that must redirect test scratch can use Bazel’s --test_tmpdir option.

The runner deliberately uses Bazel-managed temporary storage instead of a source-checkout out/ directory. Putting a no-skill control below the source tree would expose the checkout’s .agents directory through an ancestor and invalidate the isolation that the control is meant to measure. This is the repository policy’s operating-system-temporary exception for a tool that cannot safely use task-local source storage; the runner still removes its randomized child directory on normal exit and handled signals. The runner rejects a TEST_TMPDIR below any ancestor containing .agents, so do not redirect --test_tmpdir into a source checkout or another agent tree.

results.json contains the evaluated prompts and model outputs. CI may collect undeclared outputs when a manual eval is explicitly run, so treat the artifact as potentially sensitive even though the target is no-cache and no-remote.

Run a live target explicitly and pass the absolute path to an existing Codex login and a compatible host Codex executable through the test environment, never credential contents through env or a checked-in config. Set the provider’s codex_path_override from CODEX_PATH_OVERRIDE:

bazel_agent bazel test //path/to:answer_question_eval \
  --test_env=CODEX_HOME=/absolute/path/to/.codex \
  --test_env=CODEX_PATH_OVERRIDE=/absolute/path/to/codex \
  --test_output=errors

If that Codex installation reaches OpenAI through host proxy variables, pass only the needed names as well (for example, --test_env=HTTPS_PROXY and --test_env=NO_PROXY) and declare the same names in the rule’s env_inherit. Do not put proxy values in checked-in files.

With reuse_codex_login = True, the runner links only the writable CODEX_HOME/auth.json into distinct, otherwise empty subject and judge Codex homes inside its mode-0700 state directory. Provider configs can select them through PROMPTFOO_SUBJECT_CODEX_HOME and PROMPTFOO_JUDGE_CODEX_HOME. The runner holds an exclusive advisory lock on the stable login directory for the complete test, serializing repository eval targets that use the same login. With a compatible Codex executable, an automatic refresh writes through either link to the persistent host file, while the host’s config.toml, skills, plugins, memories, and MCP configuration remain unstaged and cannot contaminate the subject, no-skill control, or judge. This reuses the caller’s existing login state; it does not mint or export a token. An API-key-backed target may instead inherit OPENAI_API_KEY without enabling login reuse.

For this purpose, compatible means that file-backed auth updates open and truncate $CODEX_HOME/auth.json, preserving the symlink. The bundled Codex 0.144.0 implementation and the tested host Codex 0.150.1 do this. Do not override the executable with an implementation that atomically replaces the isolated auth.json path: that would replace the symlink, split subject and judge state, and fail to persist a rotated refresh token. See the corresponding OpenAI Codex file-storage implementations for 0.144.0 and 0.150.1.

Login reuse also forces Promptfoo’s CLI, assertion-worker, and prompt-suggestion concurrency to one, overriding higher configuration values so subject and judge Codex processes cannot race the same single-use refresh token within one test.

Do not run another Codex process against the same auth.json concurrently; unrelated processes do not honor the runner’s advisory lock. ChatGPT-managed auth can rotate its refresh token, so the refreshed file must remain persistent and have a single serialized user. The local-login mode is unsuitable for shared or untrusted CI; use an API key or supported workload identity there. In this public repository it is strictly a manual, trusted-developer workflow; never seed or persist ChatGPT-managed auth in repository CI or artifacts. See OpenAI’s managed-auth guidance for the refresh and serialization requirements.

Run credentialed live targets only from a reviewed, trusted revision. The isolated working directory and read-only provider setting reduce accidental writes, but Codex still has whatever host read access its enforced sandbox policy permits and can send prompt context to the configured service.

Files in data are placed in the test runfiles. args are passed literally; they do not expand Bazel location expressions. Prefer keeping checked-in Promptfoo prompt and dataset files beside the config and list them in data so Promptfoo’s own config-relative path resolution remains portable. The env and env_inherit attributes cannot override Bazel’s test temporary directories or the runner-owned TMPDIR, TMP, and TEMP values.

load(
    "@rules_promptfoo//promptfoo:defs.bzl",
    "promptfoo_validate_test",
)

promptfoo_validate_test(
    name = "promptfoo_config_test",
    config = "promptfooconfig.yaml",
)

Validation is an ordinary offline Bazel test and does not receive the live eval tags. It rejects env_inherit so validation cannot accidentally receive host credentials.

The module pins Promptfoo and the Codex SDK with a dedicated pnpm lock. npm lifecycle hooks and optional dependencies are disabled. The Codex executable and Promptfoo’s libSQL binding are promoted to explicit Linux x86-64 dependencies. AJV is also promoted because ajv-formats declares its runtime peer as optional, which would otherwise be removed by no_optional. The bundled real CLI target is intentionally compatible only with glibc-based Linux x86-64. Bazel enforces the OS and CPU constraints, but this repository does not currently expose a libc constraint. Other Promptfoo providers that rely on omitted optional packages or install scripts must be reviewed and promoted explicitly before use.

The pinned Promptfoo distribution is patched so PROMPTFOO_DISABLE_TELEMETRY=1 also suppresses its best-effort request to r.promptfoo.app. The upstream 0.122.2 telemetry implementation otherwise records a “telemetry disabled” event through that separate endpoint. The same patch makes Promptfoo’s otherwise hard-coded prompt-suggestion concurrency honor the runner’s serialization setting.

1.24 - Rules Promptfoo Gazelle

Gazelle extension for offline Promptfoo validation tests

rules_promptfoo_gazelle generates required, offline promptfoo_validate_test targets for Promptfoo configurations below an evals/ directory. It never creates an evals subpackage and never generates live promptfoo_test targets.

Add rules_promptfoo as a normal dependency and this generator as a development dependency:

bazel_dep(name = "rules_promptfoo", version = "<VERSION>")
bazel_dep(
    name = "rules_promptfoo_gazelle",
    version = "<VERSION>",
    dev_dependency = True,
)

For one-pass skill package creation, also add rules_skill as a normal dependency and rules_skill_gazelle as a development dependency:

bazel_dep(name = "rules_skill", version = "<VERSION>")
bazel_dep(
    name = "rules_skill_gazelle",
    version = "<VERSION>",
    dev_dependency = True,
)

Add both public language targets to the repository’s custom Gazelle binary:

load("@gazelle//:def.bzl", "gazelle_binary")

gazelle_binary(
    name = "gazelle_binary",
    languages = [
        "@rules_promptfoo_gazelle//gazelle",
        "@rules_skill_gazelle//gazelle",
    ],
)

With both extensions installed, a fresh directory containing SKILL.md and a conventional Promptfoo configuration receives both skill_library and promptfoo_validate_test targets in one Gazelle run; it does not need an existing BUILD file.

The extension recognizes these conventional configuration paths:

evals/promptfooconfig.yaml
evals/promptfooconfig.<variant>.yaml
evals/promptfooconfig.yml
evals/promptfooconfig.<variant>.json

The default file produces eval_config_test; a variant produces eval_<sanitized_variant>_config_test. Variants are lowercased, and runs of characters other than ASCII letters and digits become underscores. Colliding sanitized names receive a stable path-derived __<8 lowercase hex digits> suffix. The double underscore cannot be produced by the sanitizer, so a variant cannot claim a collision target’s namespace.

When a non-root containing package has a SKILL.md, each ordinary validation target stages that package’s conventional :skill target. Repository-root skills are unsupported by rules_skill, so a root-package SKILL.md does not infer that label. The exact no_skill variant omits skills so it remains a control. A generic Promptfoo package without SKILL.md receives no inferred skill label. Every non-configuration regular file under evals/, including README.md and test cases, is added to data in sorted order. Directories containing BUILD, BUILD.bazel, or an additional filename configured as valid in Gazelle are package boundaries and are not traversed.

The extension reconciles config, data, and skills when a discovered configuration matches a conventionally named validation target. Adding or editing eval files therefore updates those attributes on the next run. Removing or renaming a configuration does not delete the old target: a name shape is not reliable proof that Gazelle created a rule, so stale targets must be removed explicitly. Gazelle’s # keep semantics remain available at the rule, attribute, and individual list-item levels for intentional overrides. Other attributes, including args, env, tags, and visibility, remain manual and are preserved while the generated target exists. Existing manual or live promptfoo_test rules are also left intact. The extension does not follow a symlink used as the package’s evals directory, because it could escape the repository. Such a symlink, or another unexpected filesystem scan error including an error while checking a candidate package boundary, is a non-destructive no-op rather than a signal to remove targets. Before scanning, it also resolves the repository root and package directory and refuses a package whose resolved path escapes the workspace, including a package reached through Gazelle’s symlink-following support. The extension manages the shared load for both Promptfoo rule symbols and uses Bzlmod’s apparent repository name.

The public @rules_promptfoo_gazelle//gazelle:gazelle_promptfoo binary contains only this extension and can update a nested workspace without initializing unrelated language plugins from its parent repository.

1.25 - Rules skill

Bazel rules and validation for Codex skills

rules_skill packages all files belonging to a Codex skill and validates its instructions and optional OpenAI metadata with a hermetic Bazel aspect.

Add the module and register the validation aspect:

bazel_dep(name = "rules_skill", version = "<VERSION>")
build --aspects @rules_skill//skill:defs.bzl%skill_validation_aspect
build --output_groups=+skill_validation

Declare one library in the skill’s named, non-root package:

load("@rules_skill//skill:defs.bzl", "skill_library")

skill_library(
    name = "skill",
    srcs = glob(
        ["**"],
        exclude = [
            "BUILD.bazel",
            "BUILD",
            "evals/**",
        ],
    ),
)

The package’s final path segment is the skill name, so a skill_library cannot be declared in a repository root package. Move a root-level skill into a named subpackage before declaring it.

Building the library materializes the skill_validation output group. The aspect checks SKILL.md, verifies that the frontmatter name matches its package directory, and validates agents/openai.yaml when it is present.

Rules that install or evaluate skills can require the public SkillInfo provider:

load("@rules_skill//skill:defs.bzl", "SkillInfo")

attrs = {
  "skill": attr.label(providers = [SkillInfo]),
}

SkillInfo exposes these fields:

  • name is the logical skill name derived from the final segment of root. The validation aspect verifies that the SKILL.md frontmatter uses the same name.
  • root is the owning Bazel package path within the skill’s repository, such as projects/agents/skills/answer-question. It has no repository, execution-path, or runfiles prefix. It is always non-empty because repository root packages are unsupported.
  • files_by_path maps slash-separated paths relative to root to Bazel File values. It includes SKILL.md, preserves nested paths such as agents/openai.yaml, and has the same shape for source and generated files.
  • files remains the depset of all skill files. skill is the distinguished SKILL.md file, and openai_yaml is the optional distinguished agents/openai.yaml file.

Consumers should use files_by_path when staging a bundle instead of parsing File.path or File.short_path. Every source must belong to the skill’s Bazel package, and duplicate logical paths are rejected during analysis.

Use skill_discovery_links when a repository exposes canonical skill directories through a local discovery index such as .agents/skills. Pass the skill_library labels directly; the BUILD declaration is the complete source of truth, so there is no separate link manifest or configuration file.

load(
    "@rules_skill//skill:defs.bzl",
    "skill_discovery_links",
)

skill_discovery_links(
    name = "write_skill_links",
    skills = [
        "//projects/agents/skills/answer-question:skill",
        "//projects/example/skills/example:skill",
    ],
)

Reconcile the checkout with the runnable target:

bazel run //:write_skill_links

The macro also declares //:write_skill_links_test. That local, uncached test reads the source checkout and requires the discovery directory to contain exactly the skill names passed in BUILD, each as a direct relative symlink to its canonical SkillInfo.root. It rejects missing, stale, extra, absolute, or indirect links. Run the updater before the test after changing the label list:

bazel test //:write_skill_links_test

Both targets intentionally accept only source SKILL.md files from the same repository. The exact-state test is a pinned-local checkout check rather than a hermetic or remotely executable test: it resolves a source runfile back to the workspace and then inspects the local symlinks. The generated programs require Bash and POSIX symlink support and work on ordinary Linux and macOS checkouts; native Windows checkouts are not supported.

The updater holds a sibling <discovery_dir>.lock directory while it changes links, so concurrent declarations cannot produce a mixed set. A process killed without running its exit trap can leave that lock behind; after confirming no updater is active, remove the empty lock directory and rerun the updater. The exact-state test detects any interrupted partial reconciliation.

1.26 - Rules skill Gazelle

Gazelle extension for Bazel skill libraries

rules_skill_gazelle adds a skill_library(name = "skill") to each named subpackage that contains a SKILL.md. The generated rule loads its macro from the apparent rules_skill repository, so Bzlmod repository mappings are respected.

Add rules_skill as a normal dependency and this generator as a development dependency:

bazel_dep(name = "rules_skill", version = "<VERSION>")
bazel_dep(
    name = "rules_skill_gazelle",
    version = "<VERSION>",
    dev_dependency = True,
)

Add the public language target to the repository’s custom Gazelle binary:

load("@gazelle//:def.bzl", "gazelle_binary")

gazelle_binary(
    name = "gazelle_binary",
    languages = [
        "@rules_skill_gazelle//gazelle",
    ],
)

The generated source bundle is:

load("@rules_skill//skill:defs.bzl", "skill_library")

skill_library(
    name = "skill",
    srcs = glob(
        ["**"],
        exclude = [
            "BUILD.bazel",
            "BUILD",
            "evals/**",
        ],
    ),
)

The generator always excludes BUILD.bazel and BUILD, plus every custom BUILD filename configured in Gazelle. Duplicate configured names are removed.

SKILL.md is sufficient for Gazelle to create a new BUILD file below the repository root. A root-level SKILL.md is ignored because rules_skill requires a named package from which it can derive the skill name. Existing attributes on a manually maintained skill_library(name = "skill") are preserved, and a missing SKILL.md does not delete a manual rule.

The public @rules_skill_gazelle//gazelle:gazelle_skills binary contains only this extension and can update a nested workspace without initializing unrelated language plugins from its parent repository.

1.27 - Rules template

Bazel rules and a Go command for rendering template files

rules_template provides Bazel rules and a Go command for rendering template files. A registered toolchain supplies the templating executable to build actions.

MODULE.bazel:

bazel_dep(name = "rules_template", version = "<VERSION>")
register_toolchains("@rules_template//main/bzl:all")

BUILD.bazel:

1.27.1 - Bzl

Bazel code

1.28 - rules_iso

ISO image download and flash rules

Module extension that downloads ISO images with http_file and adds a runnable iso_flash target next to each image.

1.29 - Sri

Command-line Subresource Integrity calculator using OpenSSL

sri calculates Subresource Integrity hashes for files using OpenSSL. Its command-line interface accepts an input file and a digest algorithm, such as SHA-256.

  • Cli app that calculates SRI using OpenSSL
  • C, OpenSSL
Usage: sri [OPTION...]
Generate sri of a file

Example:
    bazel run //projects/sri -- --digest sha256 --file ${PWD}/README.md

  -d, --digest=String        Digest type (sha256, for example)
  -f, --file=Path            Path to the file to parse
  -?, --help                 Give this help list
      --usage                Give a short usage message

1.29.1 - Releases

Releases

1.29.1.1 - head

Release head

1.30 - Tf modules

Reusable Terraform modules for Vault, virtual machines, and storage

This project contains reusable Terraform modules for Vault configuration, Proxmox virtual machines, backup storage, and related infrastructure. The module collection is still in progress.

  • Terraform modules

1.30.1 - Backup bucket

S3 bucket for backups

1.30.2 - Pve vm qemu

Create a proxmox vm

1.30.3 - Releases

Releases

1.30.3.1 - head

Release head

1.30.4 - Terraform backend

Module that sets up an S3 terraform backend

1.30.5 - Vault approle

Create a vault approle

1.30.6 - Vault approle

Create a vault approle

1.30.7 - Vault OIDC provider

Vault OIDC provider

1.30.8 - Vault pki server

Create a pki config for a server

1.30.9 - Vault ssh server role

Create an ssh role for a server

1.30.10 - Vault transit key

Vault transit key

1.30.11 - Yc folder

Folder for Yandex Cloud

1.31 - Useless QT GUI

Desktop GUI application built with C++ and Qt

Useless QT GUI is a desktop application built with C++ and Qt. Its Bazel build uses a pinned Qt distribution without requiring a system Qt installation.

  • Desktop GUI
  • C++, Qt

The Bazel build downloads a SHA-256-pinned Qt 6.8.3 distribution through rules_qt; a system Qt installation is not required. The project previously targeted Qt 6.9.0. Using 6.8.3 is a deliberate downgrade to the LTS version supported and tested by the pinned rules_qt release.

  • Add some screenshots

2 - Infra

Infrastructure tree

This tree contains infrastructure as code. Tracked source follows the repository’s public-source policy. Infrastructure facts are not confidential merely because they are operational, generated, or live. Reports may include them unless they contain credentials, other secrets, or personal information. Inspect raw state, plans, inventories, and decrypted configuration because those artifacts can contain prohibited content; do not track the artifacts themselves.

  • Bazel targets MUST use repository-internal visibility.
  • Infrastructure definitions MUST NOT be published as production artifacts.
  • Infrastructure targets MUST NOT be dependencies of production build targets.
  • Public checked-in documentation MAY be included in the repository documentation site, including non-secret, non-personal operational facts.

The commands below are state-changing operator examples. An agent must use bazel_agent, apply the repository Terraform and secret-handling procedures, and receive explicit authority for the exact operation and environment before running an equivalent command.

  • Create an approle: example
  • Add it to approles: example
  • Run apply:
    bazel_agent bazel run //infra/vault/tf:tf.apply
    
  • Update Yandex Cloud folders:
    bazel_agent bazel run //infra/yandex_cloud/org1/tf:tf.apply
    
  • Update Proxmox resource pools:
    bazel_agent bazel run //infra/pve/tf:tf.apply
    
  • Set up al config: example
  • Set up a bucket for Terraform state: example

2.1 - Architecture

Rendered infrastructure architecture diagrams

These diagrams render every page of the checked-in Drawio source. They describe the source document, not a live inventory or health check. Pages marked Archive retain the source’s historical classification. Open an image for its full-size SVG.

DC1 infrastructure diagram

Vault infrastructure diagram

Flux infrastructure diagram

Forgejo infrastructure diagram

www infrastructure diagram

Threexui infrastructure diagram

DNS infrastructure diagram

Ingress infrastructure diagram

T3code infrastructure diagram

Truenas infrastructure diagram

Archive/Harvester infrastructure diagram

Archive/Opencode infrastructure diagram

Archive/Hermes infrastructure diagram

Archive/Proxmox infrastructure diagram

Archive/Harbor infrastructure diagram

Open the canonical source with the pinned Drawio desktop tool:

bazel_agent bazel run //infra/arch

Regenerate the maintained SVGs after editing arch.drawio:

bazel_agent bazel run //infra/arch:update
bazel_agent bazel test //infra/arch:update_tests

The update target renders all 15 named pages in Bazel sandboxes with Drawio 30.2.6 web assets from the pinned desktop archive and the repository’s pinned headless Chrome. A pinned Liberation font set and isolated Fontconfig configuration keep text measurement independent of host fonts. The renderer loads only local assets, fails on missing pages and export errors, and records the source SHA-256 in each SVG. No display server, live infrastructure access, or runtime download is required. The freshness test compares rendered output with the maintained SVGs; documentation consumes those checked-in images.

2.2 - Ceph

Ceph

Go to Nodes -> Host -> Ceph -> Configuration

Ssh to the PVE host and update the map:

sudo ceph osd getcrushmap -o crushmap.cm
sudo crushtool --decompile crushmap.cm -o crushmap.txt
sudo vim crushmap.txt
sudo crushtool --compile crushmap.txt -o new_crushmap.cm
sudo ceph osd setcrushmap -i new_crushmap.cm
sudo ceph -s

2.3 - Dns

Dns setup for alwaldend.com

//infra/dns:config_test validates the generated configuration with the pinned DNSControl check command. It requires no credentials and does not access DNS providers.

Operational wrappers pass providers.json explicitly. Its environment references are populated by the AL Vault injector; DNSControl reads the values directly without a rendered credentials file.

Project landing records live next to their projects in projects/<project>/dnsconfig.json. Project files own their subdomain CNAMEs, which point directly to alwaldend.github.io. as required by GitHub Pages custom-domain setup.

Interactive:

bazel run //infra/dns

Just preview:

bazel run //infra/dns:dns.preview

Just deploy:

bazel run //infra/dns:dns.deploy

{{/< readfile file=“zones/dc1/alwaldend.com.zone” code=“true” lang=“zone” >/}}

{{/< readfile file=“zones/global/alwaldend.com.zone” code=“true” lang=“zone” >/}}

2.3.1 - Tf

Terraform config

2.4 - flux

Fluxcd deployment
ssh -L 6443:127.0.0.1:6443 -N flux.alwaldend.com
bazel run //infra/flux/cl:flux
bazel run infra/flux/cl:flux -- get all -A
bazel run //infra/flux/cl:flux.bootstrap
bazel run //infra/flux/cl:op
bazel run //infra/flux/cl:oidc
bazel run //infra/flux/cl:cmctl -- renew traefik-gateway-websecure-tls -n traefik
  • Generate secret id and the token:
    SECRET_ID=$(bazel run //infra/flux/cl:vault.secret_id | jq -r .data.secret_id)
    TOKEN=$(echo "${SECRET_ID}" | bazel run //infra/flux/cl:vault.ops_token | jq -r .auth.client_token)
    echo "Secret id: ${SECRET_ID}, Token: ${TOKEN}"
    
  • Patch secret-id in ./cl/cert-manager/issuer-approle.yaml
  • Patch token in projects/kustomization/flux-repo/flux-sops-secret.yaml
  • Encrypt:
    bazel run //infra/flux/cl:sops.encrypt infra/flux/cl/cert-manager/issuer-approle.yaml
    bazel run //infra/flux/cl:sops.encrypt projects/kustomization/flux-repo/flux-sops-secret.yaml
    bazel run //infra/flux/cl:sops.encrypt projects/kustomization/flux-repo/flux-git-src-secret.yaml
    

2.4.1 - Ansible

Ansible setup

2.4.2 - cl

Cluster manifests

2.4.3 - Tf setup

Terraform setup

2.5 - forgejo

forgejo.alwaldend.com
bazel run //infra/forgejo/tf_setup # Create hosts
bazel run //infra/forgejo/ansible # Configure hosts
bazel run //infra/forgejo/tf # Configure forgejo

2.5.1 - Ansible

Ansible setup

2.5.2 - Tf

Terraform config

2.5.3 - Tf setup

Terraform setup

2.6 - Forgejo runner

Forgejo Actions runner deployment
bazel run //infra/forgejo_runner/tf_setup # Create VMs
bazel run //infra/forgejo_runner/ansible # Configure VMs

2.6.1 - Ansible

Forgejo runner configuration

2.6.2 - Terraform setup

Forgejo runner VM

2.7 - GitHub

GitHub Pages repositories for project landing sites

2.7.1 - GitHub Terraform

GitHub Pages repositories for project landing sites

This package creates the public repositories that host the project landing pages. Each repository receives its built Hugo site from the reusable deploy target //projects:deploy_landings in the root workspace. Terraform also manages the custom domain and Pages source (pages, /).

For a new site, first plan and apply with bootstrap_projects containing only the new projects whose pages branches do not yet exist. For example, pass -var='bootstrap_projects=["new_project"]' to //infra/github/tf:tf.plan and the reviewed tf.apply. This creates the repository without trying to enable Pages on a nonexistent branch. Do not include an existing live site: doing so would remove its Pages configuration.

Publish the built site with //projects:deploy_landings, then plan and apply with the default empty bootstrap_projects to enable Pages. Keep all applies limited to reviewed, authorized repository and Pages changes. DNS is managed separately by //infra/dns; validate the public custom domain after rollout.

2.8 - harbor

Harbor deployment
  • Go to User Profile, copy CLI secret
  • Run:
    podman login harbor.alwaldend.com
    
  • Generate approle secret id:
    SECRET_ID=$(bazel run //infra/harbor/cl:vault.secret_id | jq -r .data.secret_id)
    echo "Secret id: ${SECRET_ID}"
    
  • Patch secret-id in ./cl/cert-manager/issuer-approle.yaml
  • Encrypt:
    bazel run //infra/flux/cl:sops.encrypt infra/harbor/cl/cert-manager/issuer-approle.yaml
    

2.8.1 - Ansible

Ansible setup

2.8.2 - cl

Cluster manifests

2.8.3 - Tf

Terraform config

2.8.4 - Tf setup

Terraform setup

2.9 - ingress

ingress
bazel run //infra/ingress/ansible

Services in traefik_services must use a backend target that resolves from the ingress hosts without resolving back to ingress. Define a dedicated site-local address, conventionally prefixed with dc1., in the owning service’s DNS configuration and use that address as the target.

bazel run //infra/ingress/tf
bazel run infra/ingress/tf -- -replace 'yandex_compute_disk.vpc["*"]'
  • Regenerate private and public keys:
    wg genkey | tee host1.privatekey.txt | wg pubkey >host1.publickey.txt
    wg genkey | tee host2.privatekey.txt | wg pubkey >host2.publickey.txt
    wg genkey | tee router.privatekey.txt | wg pubkey >router.publickey.txt
    cat - >data.json <<EOF
    {
      "wg_public_keys": {
        "host1": "$(cat host1.publickey.txt)",
        "host2": "$(cat host2.publickey.txt)",
        "router": "$(cat router.publickey.txt)"
      },
      "wg_private_keys": {
        "host1": "$(cat host1.privatekey.txt)",
        "host2": "$(cat host2.privatekey.txt)",
        "router": "$(cat router.privatekey.txt)"
      },
      "wg_preshared_keys": {
        "host1": "$(openssl rand 32 | base64)",
        "host2": "$(openssl rand 32 | base64)"
      }
    }
    EOF
    bazel run infra/ingress:vault.kv_put -- -format json alwaldend.com/vault1/approles/src_infra_ingress/wireguard "@${PWD}/data.json"
    rm data.json *.privatekey.txt *.publickey.txt
    

2.9.1 - Ansible

Ansible setup

2.9.2 - Tf

Terraform config

2.10 - Mikrotik

Mikrotik setup for dc1.alwaldend.com
  • Open Winbox
  • Open new terminal
  • Run /export
  • Copy output
/interface bridge
add admin-mac=78:9A:18:38:6C:CA auto-mac=no comment="bridge1 (wired)" name=bridge1
add comment="bridge2 (wireless)" name=bridge2
/interface wifi
set [ find default-name=wifi1 ] channel.frequency=5000-5400 .skip-dfs-channels=10min-cac comment="wifi1 (5GHz)" configuration.country=Russia .mode=ap .ssid=divinity-5GHz datapath.client-isolation=yes disabled=no security.authentication-types=wpa2-psk,wpa3-psk .connect-priority=0 .ft=yes .ft-over-ds=yes
set [ find default-name=wifi2 ] channel.skip-dfs-channels=10min-cac comment="wifi2 (2GHz)" configuration.country=Russia .mode=ap .ssid=divinity-2GHz datapath.client-isolation=yes disabled=no security.authentication-types=wpa2-psk,wpa3-psk .connect-priority=0 .ft=yes .ft-over-ds=yes
/interface ethernet
set [ find default-name=ether1 ] comment=ether1 l2mtu=1500 mac-address=F4:28:53:7F:A4:59
set [ find default-name=ether2 ] comment=ether2
set [ find default-name=ether3 ] comment=ether3
set [ find default-name=ether4 ] comment=ether4
set [ find default-name=ether5 ] comment=ether5
/interface wireguard
add comment="tf[users/simeonwarren/hermes/tf_setup]" disabled=yes listen-port=13232 mtu=1420 name=hermes-vpc
add comment="tf[infra/ingress/tf]" listen-port=13231 mtu=1420 name=ingress-vpc
/interface ethernet switch
set switch1 cpu-flow-control=yes
/interface list
add comment=defconf name=WAN
add comment=defconf name=LAN
add name=accept-forward-WAN
add name=accept-input-DNS
add name=accept-input-DHCP-server
add name=accept-input-ICMP
add name=accept-input-winbox
add name=accept-input-web-ui
add name=accept-input-mikrotik-neighbor-discovery
add name=accept-forward-LAN
add name=accept-output-LAN
add name=accept-input-NTP
add name=accept-input-API
/ip pool
add comment=bridge1 name=bridge1 ranges=192.168.1.10-192.168.1.254
add comment=bridge2 name=bridge2 ranges=192.168.2.10-192.168.2.254
/ip dhcp-server
add address-pool=bridge1 comment=bridge1 interface=bridge1 lease-time=10m name=bridge1
add address-pool=bridge2 interface=bridge2 name=bridge2
/ipv6 pool
add name=dc01 prefix=fd2e:546d:5738::/48 prefix-length=64
/user group
add comment=src_infra_dns name=src_infra_dns policy=read,write,api,rest-api,!local,!telnet,!ssh,!ftp,!reboot,!policy,!test,!winbox,!password,!web,!sniff,!sensitive,!romon
add comment=src_infra_ingress name=src_infra_ingress policy=read,write,api,rest-api,!local,!telnet,!ssh,!ftp,!reboot,!policy,!test,!winbox,!password,!web,!sniff,!sensitive,!romon
add comment=users_simeonwarren name=users_simeonwarren policy=read,write,api,rest-api,!local,!telnet,!ssh,!ftp,!reboot,!policy,!test,!winbox,!password,!web,!sniff,!sensitive,!romon
/interface bridge port
add bridge=bridge1 comment=bridge1-ether2 interface=ether2
add bridge=bridge1 comment=bridge1-ether3 interface=ether3
add bridge=bridge1 comment=bridge1-ether4 interface=ether4
add bridge=bridge1 comment=bridge1-ether5 interface=ether5
add bridge=bridge2 comment=bridge2-wifi1 interface=wifi1
add bridge=bridge2 comment=bridge2-wifi2 interface=wifi2
/ip neighbor discovery-settings
set discover-interface-list=LAN
/interface detect-internet
set detect-interface-list=WAN
/interface list member
add interface=bridge1 list=LAN
add interface=ether1 list=WAN
add interface=bridge2 list=LAN
add interface=bridge2 list=accept-forward-WAN
add interface=bridge1 list=accept-forward-WAN
add interface=bridge1 list=accept-input-DNS
add interface=bridge2 list=accept-input-DNS
add interface=bridge1 list=accept-input-DHCP-server
add interface=bridge2 list=accept-input-DHCP-server
add interface=bridge1 list=accept-input-ICMP
add interface=bridge2 list=accept-input-ICMP
add interface=bridge1 list=accept-input-winbox
add interface=bridge1 list=accept-input-web-ui
add interface=bridge1 list=accept-input-mikrotik-neighbor-discovery
add interface=bridge1 list=accept-forward-LAN
add interface=bridge1 list=accept-output-LAN
add interface=bridge1 list=accept-input-NTP
add interface=bridge1 list=accept-input-API
add comment="tf[infra/ingress/tf]" interface=ingress-vpc list=accept-input-ICMP
add comment="tf[infra/ingress/tf]" interface=ingress-vpc list=LAN
add comment="tf[infra/ingress/tf]" interface=ingress-vpc list=accept-forward-LAN
add comment="tf[users/simeonwarren/hermes/tf_setup]" interface=hermes-vpc list=accept-forward-LAN
add comment="tf[users/simeonwarren/hermes/tf_setup]" interface=hermes-vpc list=accept-input-ICMP
add comment="tf[users/simeonwarren/hermes/tf_setup]" interface=hermes-vpc list=LAN
/interface ovpn-server server
add mac-address=FE:B3:B4:C4:A4:48 name=ovpn-server1
/interface wireguard peers
add allowed-address=10.10.0.2/24 comment=host2 endpoint-address=103.76.53.6 endpoint-port=51820 interface=ingress-vpc name=ingress-vpc-host2 persistent-keepalive=5s public-key="Z2JamOjZYOGaf4tPZzchyHjLw/XlOtUtQObyROEQ9DM="
add allowed-address=10.10.0.1/24 comment=host1 endpoint-address=158.160.196.128 endpoint-port=51820 interface=ingress-vpc name=ingress-vpc-host1 persistent-keepalive=5s public-key="xmyl+frvngmzRB9z5yEURxQj4vTw47tKQV7EZrTAREw="
add allowed-address=10.20.0.1/24 comment=host1 endpoint-address=158.160.220.223 endpoint-port=51820 interface=hermes-vpc name=hermes-vpc-host1 persistent-keepalive=5s public-key="oA4ZpsmrclIOIWh3ECsb4ZFKH1hQMDtuW3xNXat3IyQ="
/ip address
add address=192.168.1.1/24 comment="bridge1 (LAN)" interface=bridge1 network=192.168.1.0
add address=192.168.2.1/24 comment="bridge2 (Wireless)" interface=bridge2 network=192.168.2.0
add address=192.168.10.1/24 comment=host1.pve1.dc1.alwaldend.com interface=bridge1 network=192.168.10.0
add address=10.10.0.0/24 comment="tf[infra/ingress/tf]" interface=ingress-vpc network=10.10.0.0
add address=10.20.0.0/24 comment="tf[users/simeonwarren/hermes/tf_setup]" interface=hermes-vpc network=10.20.0.0
/ip dhcp-client
add comment=defconf interface=ether1 name=ether1 use-peer-dns=no
/ip dhcp-server lease
add address=192.168.1.250 client-id=1:2c:cf:67:67:b5:13 mac-address=2C:CF:67:67:B5:13 server=bridge1
add address=192.168.1.218 client-id=1:e0:be:3:2b:9a:1a mac-address=E0:BE:03:2B:9A:1A server=bridge1
add address=192.168.1.216 client-id=ff:60:8:6d:aa:0:1:0:1:31:93:31:1a:34:5a:60:8:6d:aa mac-address=34:5A:60:08:6D:AA server=bridge1
/ip dhcp-server network
add address=192.168.1.0/24 comment=defconf dns-server=192.168.1.1 gateway=192.168.1.1
add address=192.168.2.0/24 dns-server=192.168.2.1 gateway=192.168.2.1
/ip dns
set allow-remote-requests=yes servers=1.1.1.2,1.0.0.2 use-doh-server=https://odoh.cloudflare-dns.com/dns-query verify-doh-cert=yes
/ip dns static
add address=185.199.108.153 name=alwaldend.com ttl=5m type=A
add address=185.199.109.153 name=alwaldend.com ttl=5m type=A
add address=185.199.110.153 name=alwaldend.com ttl=5m type=A
add address=185.199.111.153 name=alwaldend.com ttl=5m type=A
add address=2606:50c0:8000::153 name=alwaldend.com ttl=5m type=AAAA
add address=2606:50c0:8001::153 name=alwaldend.com ttl=5m type=AAAA
add address=2606:50c0:8002::153 name=alwaldend.com ttl=5m type=AAAA
add address=2606:50c0:8003::153 name=alwaldend.com ttl=5m type=AAAA
add mx-exchange=mail.protonmail.ch mx-preference=10 name=alwaldend.com ttl=5m type=MX
add mx-exchange=mailsec.protonmail.ch mx-preference=20 name=alwaldend.com ttl=5m type=MX
add name=alwaldend.com text="_globalsign-domain-verification=0QBJgVV_uwcFLTi1Rot3bb1LyJ5uW1WD0ygvIS4OM5" ttl=5m type=TXT
add name=alwaldend.com text="protonmail-verification=bdcd133d3f472fa17f66328950d02fbeae1bef75" ttl=5m type=TXT
add name=alwaldend.com text="v=spf1 include:_spf.protonmail.ch ~all" ttl=5m type=TXT
add name=_dmarc.alwaldend.com text="v=DMARC1; p=quarantine; adkim=s" ttl=5m type=TXT
add cname=protonmail.domainkey.djgwfzcu5fgjtpoijqqomgifmqj6zeiuwdd4mzim4hrxab3zsgwkq.domains.proton.ch name=protonmail._domainkey.alwaldend.com ttl=5m type=CNAME
add cname=protonmail2.domainkey.djgwfzcu5fgjtpoijqqomgifmqj6zeiuwdd4mzim4hrxab3zsgwkq.domains.proton.ch name=protonmail2._domainkey.alwaldend.com ttl=5m type=CNAME
add cname=protonmail3.domainkey.djgwfzcu5fgjtpoijqqomgifmqj6zeiuwdd4mzim4hrxab3zsgwkq.domains.proton.ch name=protonmail3._domainkey.alwaldend.com ttl=5m type=CNAME
add address=192.168.1.222 name=bm1.dc1.alwaldend.com ttl=5m type=A
add address=192.168.1.216 name=bm2.dc1.alwaldend.com ttl=5m type=A
add address=fd2e:546d:5738:0:365a:60ff:fe08:6daa name=bm2.dc1.alwaldend.com ttl=10m type=AAAA
add address=192.168.1.218 name=bm3.dc1.alwaldend.com ttl=5m type=A
add address=fd2e:546d:5738:0:e2be:3ff:fe2b:9a1a name=bm3.dc1.alwaldend.com ttl=10m type=AAAA
add cname=bm2.dc1.alwaldend.com name=host1.pve1.dc1.alwaldend.com ttl=10m type=CNAME
add address=192.168.10.10 name=cloudinit-test.vm.pve1.dc1.alwaldend.com ttl=5m type=A
add address=192.168.1.1 name=router1.dc1.alwaldend.com ttl=5m type=A
add address=fd2e:546d:5738::1 name=router1.dc1.alwaldend.com ttl=10m type=AAAA
add address=192.168.1.254 name=switch1.dc1.alwaldend.com ttl=5m type=A
add address=192.168.1.218 name=vault.dc1.alwaldend.com ttl=5m type=A
add mx-exchange=mx1.simplelogin.co mx-preference=10 name=simplelogin.alwaldend.com ttl=3h type=MX
add mx-exchange=mx2.simplelogin.co mx-preference=20 name=simplelogin.alwaldend.com ttl=3h type=MX
add name=simplelogin.alwaldend.com text="sl-verification=bxfzzfjiggzsxyzxhhmkmjqkaskjgy" ttl=3h type=TXT
add name=simplelogin.alwaldend.com text="v=spf1 include:simplelogin.co ~all" ttl=3h type=TXT
add name=_dmarc.simplelogin.alwaldend.com text="v=DMARC1; p=quarantine; pct=100; adkim=s; aspf=s" ttl=3h type=TXT
add cname=dkim._domainkey.simplelogin.co name=dkim._domainkey.simplelogin.alwaldend.com ttl=3h type=CNAME
add cname=dkim02._domainkey.simplelogin.co name=dkim02._domainkey.simplelogin.alwaldend.com ttl=3h type=CNAME
add cname=dkim03._domainkey.simplelogin.co name=dkim03._domainkey.simplelogin.alwaldend.com ttl=3h type=CNAME
add cname=alwaldend.com name=www.alwaldend.com ttl=5m type=CNAME
add mx-exchange=mx.yandex.net mx-preference=10 name=yandex.alwaldend.com ttl=6h type=MX
add name=yandex.alwaldend.com text="v=spf1 redirect=_spf.yandex.net" ttl=5m type=TXT
add name=yandex.alwaldend.com text="yandex-verification: b83672f59b3dbe16" ttl=5m type=TXT
add name=mail._domainkey.yandex.alwaldend.com text="v=DKIM1; k=rsa; t=s; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCcYzFVgkeDOhaIIkWM8gNQjxVsv0/aXfU+ax5urB5y6hA6lSjRnjRo6tm0bXbkOJf41GmiwMNgdXpwRtzgzAlX1i2aJbtEr4b9jzibEGLQ7Cvqs44bOYES9f/K3ueQpnvdTOJmFqlRReFL7ZrUyDFCoQ7f4+7h4i8s01cCcRrt5wIDAQAB" ttl=5m type=TXT
add address=192.168.1.218 name=host1.vault.dc1.alwaldend.com ttl=5m type=A
add address=192.168.10.60 name=flux.alwaldend.com ttl=5m type=A
add address=192.168.10.60 name=host1.flux.alwaldend.com ttl=5m type=A
add cname=flux.alwaldend.com name=openid.flux.alwaldend.com ttl=10m type=CNAME
add cname=flux.alwaldend.com name=operator.flux.alwaldend.com ttl=10m type=CNAME
add address=192.168.10.40 name=forgejo.alwaldend.com ttl=5m type=A
add address=192.168.10.40 name=host1.forgejo.alwaldend.com ttl=5m type=A
add address=192.168.10.50 name=harbor.alwaldend.com ttl=5m type=A
add address=192.168.10.50 name=host1.harbor.alwaldend.com ttl=5m type=A
add address=192.168.1.216 name=pve.alwaldend.com ttl=5m type=A
add address=192.168.10.80 name=threexui.alwaldend.com ttl=5m type=A
add address=192.168.10.80 name=host1.threexui.alwaldend.com ttl=5m type=A
add address=45.142.141.133 name=njalla1.nodes.threexui.alwaldend.com ttl=5m type=A
add address=2a0a:3840:8078:141:0:2d8e:8d85:1337 name=njalla1.nodes.threexui.alwaldend.com ttl=10m type=AAAA
add address=192.168.1.218 name=vault.alwaldend.com ttl=5m type=A
add address=103.76.53.6 name=ingress.alwaldend.com ttl=5m type=A
add address=158.160.196.128 name=ingress.alwaldend.com ttl=5m type=A
add address=158.160.196.128 name=host1.ingress.alwaldend.com ttl=5m type=A
add address=103.76.53.6 name=host2.ingress.alwaldend.com ttl=5m type=A
add name=yc.threexui.alwaldend.com ns=ns1.yandexcloud.net ttl=5m type=NS
add name=yc.threexui.alwaldend.com ns=ns2.yandexcloud.net ttl=5m type=NS
add cname=host1.nodes.yc.threexui.alwaldend.com name=yc1.nodes.threexui.alwaldend.com ttl=10m type=CNAME
add address=192.168.10.100 name=runner1.forgejo-runner.alwaldend.com ttl=5m type=A
add cname=host1.yc.hermes.simeonwarren.users.alwaldend.com name=hermes.simeonwarren.users.alwaldend.com ttl=10m type=CNAME
add cname=host1.yc.hermes.simeonwarren.users.alwaldend.com name=host1.hermes.simeonwarren.users.alwaldend.com ttl=10m type=CNAME
add name=yc.hermes.simeonwarren.users.alwaldend.com ns=ns1.yandexcloud.net ttl=5m type=NS
add name=yc.hermes.simeonwarren.users.alwaldend.com ns=ns2.yandexcloud.net ttl=5m type=NS
/ip firewall filter
add action=accept chain=input comment="defconf: accept established,related,untracked" connection-state=established,related,untracked
add action=drop chain=input comment="defconf: drop invalid" connection-state=invalid log-prefix=drop-invalid
add action=accept chain=input comment="defconf: accept ICMP" in-interface-list=accept-input-ICMP protocol=icmp
add action=accept chain=input comment="defconf: accept to local loopback (for CAPsMAN)" dst-address=127.0.0.1
add action=drop chain=input comment="defconf: drop all not coming from LAN" in-interface-list=!LAN log-prefix=drop-not-coming-from-lan
add action=accept chain=forward comment="defconf: accept in ipsec policy" ipsec-policy=in,ipsec
add action=accept chain=forward comment="defconf: accept out ipsec policy" ipsec-policy=out,ipsec
add action=fasttrack-connection chain=forward comment="defconf: fasttrack" connection-state=established,related
add action=accept chain=forward comment="defconf: accept established,related, untracked" connection-state=established,related,untracked
add action=drop chain=forward comment="defconf: drop invalid" connection-state=invalid log-prefix=drop-invalid
add action=drop chain=forward comment="defconf: drop all from WAN not DSTNATed" connection-nat-state=!dstnat connection-state=new in-interface-list=WAN log-prefix=drop-from-wan-not-dstnated
add action=accept chain=input in-interface-list=WAN protocol=gre
add action=accept chain=forward comment="accept forward WAN" in-interface-list=accept-forward-WAN out-interface-list=WAN
add action=accept chain=forward comment="accept forward LAN" in-interface-list=accept-forward-LAN out-interface-list=LAN
add action=accept chain=input comment="accept input DNS (udp)" dst-port=53 in-interface-list=accept-input-DNS protocol=udp
add action=accept chain=input comment="accept input DNS (tcp)" dst-port=53 in-interface-list=accept-input-DNS protocol=tcp
add action=accept chain=input comment=accept-input-NTP dst-port=123 in-interface-list=accept-input-NTP protocol=udp
add action=accept chain=input comment="accept input DHCP-server" dst-port=67 in-interface-list=accept-input-DHCP-server log-prefix=accept-DHCP protocol=udp
add action=accept chain=input comment="accept input winbox (tcp)" dst-port=8291 in-interface-list=accept-input-winbox protocol=tcp
add action=accept chain=input comment="accept input winbox (udp)" dst-port=20561 in-interface-list=accept-input-winbox protocol=udp
add action=accept chain=input comment="accept input web ui" dst-port=80,443 in-interface-list=accept-input-web-ui protocol=tcp
add action=accept chain=input comment="accept input mikrotik neighbor discovery" dst-port=5678 in-interface-list=accept-input-mikrotik-neighbor-discovery protocol=udp
add action=drop chain=forward comment="drop forward" log=yes log-prefix=drop-forward
add action=drop chain=input comment="drop input" log=yes log-prefix=drop-input
add action=accept chain=output comment=accept-output-LAN out-interface-list=LAN
/ip firewall nat
add action=masquerade chain=srcnat comment="defconf: masquerade" ipsec-policy=out,none out-interface-list=WAN
/ip ipsec profile
set [ find default=yes ] dpd-interval=2m dpd-maximum-failures=5
/ip service
set www-ssl certificate=alwaldend.com_acme disabled=no
set reverse-proxy certificate=alwaldend.com_acme
set api-ssl certificate=alwaldend.com_acme
/ipv6 address
add address=::1 from-pool=dc01 interface=bridge1
add address=::1:0:0:0:1 from-pool=dc01 interface=bridge2
/ipv6 firewall address-list
add address=::/128 comment="defconf: unspecified address" list=bad_ipv6
add address=::1/128 comment="defconf: lo" list=bad_ipv6
add address=fec0::/10 comment="defconf: site-local" list=bad_ipv6
add address=::ffff:0.0.0.0/96 comment="defconf: ipv4-mapped" list=bad_ipv6
add address=::/96 comment="defconf: ipv4 compat" list=bad_ipv6
add address=100::/64 comment="defconf: discard only " list=bad_ipv6
add address=2001:db8::/32 comment="defconf: documentation" list=bad_ipv6
add address=2001:10::/28 comment="defconf: ORCHID" list=bad_ipv6
add address=3ffe::/16 comment="defconf: 6bone" list=bad_ipv6
/ipv6 firewall filter
add action=accept chain=input comment="defconf: accept established,related,untracked" connection-state=established,related,untracked
add action=drop chain=input comment="defconf: drop invalid" connection-state=invalid
add action=accept chain=input comment="defconf: accept ICMPv6" in-interface-list=accept-input-ICMP protocol=icmpv6
add action=accept chain=input comment="defconf: accept UDP traceroute" dst-port=33434-33534 protocol=udp
add action=accept chain=input comment="defconf: accept DHCPv6-Client prefix delegation." dst-port=546 protocol=udp src-address=fe80::/10
add action=accept chain=input comment="defconf: accept IKE" dst-port=500,4500 protocol=udp
add action=accept chain=input comment="defconf: accept ipsec AH" protocol=ipsec-ah
add action=accept chain=input comment="defconf: accept ipsec ESP" protocol=ipsec-esp
add action=accept chain=input comment="defconf: accept all that matches ipsec policy" ipsec-policy=in,ipsec
add action=drop chain=input comment="defconf: drop everything else not coming from LAN" in-interface-list=!LAN
add action=accept chain=forward comment="defconf: accept established,related,untracked" connection-state=established,related,untracked
add action=drop chain=forward comment="defconf: drop invalid" connection-state=invalid
add action=drop chain=forward comment="defconf: drop packets with bad src ipv6" src-address-list=bad_ipv6
add action=drop chain=forward comment="defconf: drop packets with bad dst ipv6" dst-address-list=bad_ipv6
add action=drop chain=forward comment="defconf: rfc4890 drop hop-limit=1" hop-limit=equal:1 protocol=icmpv6
add action=accept chain=forward comment="defconf: accept ICMPv6" in-interface-list=accept-input-ICMP protocol=icmpv6
add action=accept chain=forward comment="defconf: accept HIP" protocol=139
add action=accept chain=forward comment="defconf: accept IKE" dst-port=500,4500 protocol=udp
add action=accept chain=forward comment="defconf: accept ipsec AH" protocol=ipsec-ah
add action=accept chain=forward comment="defconf: accept ipsec ESP" protocol=ipsec-esp
add action=accept chain=forward comment="defconf: accept all that matches ipsec policy" ipsec-policy=in,ipsec
add action=drop chain=forward comment="defconf: drop everything else not coming from LAN" in-interface-list=!LAN
add action=accept chain=forward comment="accept forward WAN" in-interface-list=accept-forward-WAN out-interface-list=WAN
add action=accept chain=forward comment="accept forward LAN" in-interface-list=accept-forward-LAN out-interface-list=LAN
add action=accept chain=input comment="accept input DNS (udp)" dst-port=53 in-interface-list=accept-input-DNS protocol=udp
add action=accept chain=input comment="accept input DNS (tcp)" dst-port=53 in-interface-list=accept-input-DNS protocol=tcp
add action=accept chain=input comment=accept-input-NTP dst-port=123 in-interface-list=accept-input-NTP protocol=udp
add action=accept chain=input comment="accept input winbox (tcp)" dst-port=8291 in-interface-list=accept-input-winbox protocol=tcp
add action=accept chain=input comment="accept input winbox (udp)" dst-port=20561 in-interface-list=accept-input-winbox protocol=udp
add action=accept chain=input comment="accept input web ui" dst-port=80,443 in-interface-list=accept-input-web-ui protocol=tcp
add action=accept chain=input comment="accept input mikrotik neighbor discovery" dst-port=5678 in-interface-list=accept-input-mikrotik-neighbor-discovery protocol=udp
add action=drop chain=forward comment="drop forward" log=yes log-prefix=drop-forward-ipv6
add action=drop chain=input comment="drop input" log=yes log-prefix=drop-input-ipv6
add action=accept chain=output comment=accept-output-LAN out-interface-list=LAN
/ipv6 nd
set [ find default=yes ] advertise-dns=yes interface=bridge1
add advertise-dns=yes interface=bridge2
/system clock
set time-zone-name=Europe/Moscow
/system identity
set name=router1.dc1.alwaldend.com
/system ntp server
set enabled=yes
/system routerboard settings
set auto-upgrade=yes
/tool mac-server
set allowed-interface-list=LAN
/tool mac-server mac-winbox
set allowed-interface-list=LAN
# 2025-09-07 11:04:01 by RouterOS 7.19.4
# model = L009UiGS-2HaxD
/interface bridge
add name=bridge01
/port
set 0 name=serial0
/interface bridge port
add bridge=bridge01 interface=ether2
add bridge=bridge01 interface=ether3
add bridge=bridge01 interface=ether4
add bridge=bridge01 interface=ether5
add bridge=bridge01 interface=ether6
add bridge=bridge01 interface=ether7
add bridge=bridge01 interface=ether8
add bridge=bridge01 interface=ether1
/ip neighbor discovery-settings
set discover-interface-list=!dynamic
/ipv6 settings
set accept-router-advertisements=yes
/ip dhcp-client
add interface=bridge01
/system clock
set time-zone-name=Europe/Moscow
/system identity
set name=router02.dc01.alwaldend.com
/system routerboard settings
set enter-setup-on=delete-key

2.11 - Nas

TrueNAS deploy

2.12 - Pve

Proxmox cluster pve.alwaldend.com
bazel run //infra/pve/ansible # host setup
bazel run //infra/pve/tf/tf.apply # tf setup
bazel run //infra/pve/tf:tf.apply -- --replace module.vm_cloudinit_test.proxmox_vm_qemu.vm
bazel run //infra/pve/ansible -- --tags pve_snippets
  • Create an EAB:
    bazel run //infra/dc1/vault -- write -f pki/ica_servers/roles/src_infra_dc1_pve1_pki_server/acme/new-eab
    
  • Login as root@pam
  • Go to Datacenter -> ACME
  • Create a new account with the EAB and a directory:
    https://vault.dc1.alwaldend.com:8200/v1/pki/ica_servers/roles/src_infra_dc1_pve1_pki_server/acme/directory
    
  • Create a token with Privilege Separation
  • Grant it required roles
  • Create json:
    {
      "token_id": "",
      "token_secret": ""
    }
    
  • Write the data:
    bazel run //infra/pve:vault.kv_put alwaldend.com/vault1/approles/src_infra_dc1_pve1/pve_token @"${PWD}/data.json"
    

2.12.1 - Ansible

Ansible setup

2.12.2 - Tf

Terraform config

2.13 - threexui

3x-ui
bazel run //infra/threexui:fix_subs -- --hosts njalla1.nodes.threexui.alwaldend.com,yc1.nodes.threexui.alwaldend.com --sub_id subid
bazel run //infra/threexui:fix_subs -- --sub_file path_to_file

2.13.1 - Ansible

Ansible setup

2.13.2 - sub

Fetch subscriptions and fix them

2.13.3 - Tf

Terraform config

2.13.4 - Tf setup

Terraform setup

2.14 - Vault

Setup for vault.dc1.alwaldend.com
bazel run //infra/vault/tf_setup:tf.apply # Create VMs (requires an active Vault host)
bazel run //infra/vault/ansible # Set up hosts (BM and VMs)
bazel run //infra/vault/tf:tf.apply # Configure vault
bazel run //infra/vault:backup

With a working Vault:

bazel run //infra/vault:unseal

Without a working Vault:

bazel run //infra/vault:unseal_standalone
bazel run //infra/vault/ansible:fix_quorum
bazel run //infra/vault/ansible:ansible.vm # Set up only VMs
bazel run //infra/vault/ansible:ansible.bm # Set up only bare metal

Plan:

bazel run //infra/vault/tf:tf.plan

Apply:

bazel run //infra/vault/tf:tf.apply

Run terraform directly:

bazel run //infra/vault/tf:tf.direct -- -chdir="${PWD}" plan
bazel run //infra/vault/tf:tf.apply -- -replace 'module.vm_ha["host2"].proxmox_vm_qemu.vm' -replace 'module.vm_ha["host3"].proxmox_vm_qemu.vm
username="username"
bazel run //infra/vault:gen_client_cert -- --user "${username}" --output_dir "${PWD}"
bazel run //tools/ykman -- piv certificates import 9A "${PWD}/${username}.pfx"
bazel run //tools/ykman -- piv keys import 9A "${PWD}/${username}.pfx"
bazel run //infra/vault:gen_client_cert -- --host some-host --output_dir "${HOME}/.al/client_cert"
bazel run //infra/vault:gen_client_cert -- --host some-host --user username --output_dir "${HOME}/.al/client_cert"
  • Prepare encrypted unseal token
  • Run and input the encrypted token:
    bazel run //infra/vault:unseal
    
  • Prepare encrypted unseal token
  • Run and input the encrypted token:
    bazel run //infra/vault:gen_root_token -- --pgp_key path_to_public_gpg_key_in_base64
    
bazel run //infra/vault -- write -f pki/ica_servers/roles/ica_servers_dc1_pve1/acme/new-eab
bazel run //:vault -- write ssh/clients/sign/admins ttl=30000000  public_key=@"${HOME}/.ssh/key"
bazel run //infra/vault -- token revoke -mode=path auth

Vault certificates (tls_cert_file, tls_key_file) should be updated manually

bazel run //infra/vault -- read identity/oidc/client/src_infra_dc1_forgejo1_provider
 bazel run //infra/vault -- list -format json identity/entity-alias/id | jq ".[]" | xargs "-I{}" bazel run //infra/vault -- read "identity/entity-alias/id/{}"

2.14.1 - Ansible

Ansible setup

2.14.2 - Tf

Terraform config

2.14.2.1 - Output

Output files

2.14.3 - Tf setup

Terraform setup

2.15 - XCP-ng

XCP-ng infrastructure

The dc1 DNS configuration maps xcp-ng.alwaldend.com and host1.xcp-ng.alwaldend.com to 192.168.1.213.

Terraform lives in internal/tf and declares the pinned vatesfr/xenorchestra provider. It includes empty provider and HTTP backend blocks, with no resources, endpoints, or credentials. The provider requires Xen Orchestra connected to the XCP-ng pool when resources are added.

al.lua authenticates with the src_infra_xcp_ng Vault AppRole and configures the HTTP backend using secrets/alwaldend.com/vault1/approles/src_infra_xcp_ng/tf_backend. The AppRole is declared in infra/vault/tf and must be provisioned before running the Terraform commands. Provider connection settings are left to the operator.

Check Terraform formatting with:

bazel_agent bazel test //infra/xcp_ng/internal/tf:tf_tests.fmt_test

The formatting test does not authenticate to Vault.

2.16 - Yandex Cloud

Yandex Cloud (yandex.cloud)

2.16.1 - Org1

Organization 1

2.16.1.1 - Tf

Terraform config

3 - Tools

Tools tree

This tree contains tools used inside the repository. All tracked content follows the repository’s public-source policy.

  • Bazel targets MUST use repository-internal visibility except for toolchain types whose owner explicitly exposes a public build API.
  • Tool artifacts MUST NOT be published as first-party product artifacts.
  • Tool targets MUST NOT be used as dependencies of production build targets.
  • Tool targets intended for repository-wide use MUST use visibility = ["//:__subpackages__"].
  • Tool targets MAY be used in tests and explicit source-generation/update targets.

An explicit source-generation/update target is a developer workflow, not part of the production build graph. It may depend on a tool from this tree and use write_source_file to update a checked-in source artifact. Normal production and documentation targets must consume that checked-in artifact directly; they must not depend on the generator, its tool, or an action-generated copy.

3.1 -

Bazel session cleanup

The repository’s .codex/config.toml queues asynchronous Bazel expunge when a Codex session ends. Review and trust the hook with /hooks in Codex; project hooks do not run until trusted. A completed assistant turn does not trigger cleanup.

If /hooks is empty in a linked Git worktree, check the primary checkout’s .codex/config.toml. In Codex CLI 0.153.4, observed on 2026-09-06, config/read returned the primary checkout’s configuration even though its project-layer metadata named the linked worktree. That primary configuration had no hooks, so hooks/list returned an empty list. The exact worktree TOML listed both hooks in an isolated normal checkout; separate user-config probes also accepted both TOML and JSON. Changing formats is therefore not an established fix. Merge the hook configuration and update the primary checkout, then start a new CLI session and check /hooks to trust it. Recheck configuration resolution after upgrading Codex; this is an observed version-specific behavior, not a guarantee for every release.

The shell hook launches a transient user systemd service, which runs bazel --noblock_for_lock clean --config=agent --expunge_async in each built, tracked Bazel workspace in the linked Git worktree. It skips the primary checkout, submodules, workspaces without a bazel-out symlink, and busy Bazel instances. Source files, Git worktrees, and shared disk caches are preserved. Nested workspaces are discovered from tracked MODULE.bazel, WORKSPACE, and WORKSPACE.bazel files. Custom convenience-symlink prefixes are not supported.

This Linux hook requires Bash, Git, Bazelisk’s bazel on PATH, and a running user systemd manager. The service inherits PATH, not the session’s full environment. KillMode=process allows Bazel’s asynchronous deletion child to finish after the service exits. Failures appear in the user journal; failure to enqueue is reported by Codex as a hook failure. There is no automatic retry or orphan-cache sweep. Concurrent sessions sharing a worktree may lose warm build state when one ends; the Bazel lock protects running builds, not idle sessions. Resuming a cleaned session rebuilds its outputs normally.

The hook uses shell because it must run from a fresh checkout without first building a helper. It invokes Bazel directly to supply the startup lock flag, which bazel_agent does not currently accept. Tests replace Git, systemd, and Bazel with fixtures and never clean real caches.

Codex’s SessionEnd hook is synchronous even with async: true and permits at most three seconds. Systemd owns the longer-running cleanup; the hook does not wait for it. See the Codex hook documentation.

3.2 - Agent control contracts

Repository-internal shared contracts for agent-system composition

Agent control contracts

This project owns the repository-internal shared vocabulary used to compose agent-system declarations and derived catalogs. It does not own component payload schemas, user authority, runtime observations, or generated catalogs.

The initial api/v1alpha1 package defines stable references, atomic effects, authority and budget envelopes, independent path-policy axes, information and retention classes, availability reasons, evidence applicability, and the common operation and artifact envelopes. Validation fails closed for unknown effects and malformed identities. JSON decoding is strict and canonical encoding is deterministic.

The Phase 1 registry names the closed registration authorities, declares skill metadata and supported direct binaries, links owner-local operation files, and records generated-artifact ownership. Run the report-only completeness check with:

bazel_agent bazel run //tools/agents/cmd/phase1_check -- \
  --workspace-root "$PWD" \
  --report out/<task>/phase1-report.json

The adjacent criteria-revision-bound resource baseline records numeric ceilings separately from observations. Unavailable observations carry a reason instead of an estimate.

Project roots use exactly one lifecycle value from active, in_progress, maintenance, experimental, finished, or abandoned. These values describe project maintenance state; they do not imply publication or information policy.

The topology compiler derives a deterministic, offline TopologyCatalog from the registered projects/* universe, top-level boundary READMEs, and tracked MODULE.bazel roots. The portable JSON at tools/agents/catalogs/topology.json is authoritative; the adjacent Markdown renders the same data and states the JSON digest.

Regenerate with:

bazel_agent bazel run //tools/agents/cmd/topology_check:topology_update

Verify the checked artifacts are current with:

bazel_agent bazel test //tools/agents/cmd/topology_check:topology_check_check

The catalog contains no timestamps, absolute checkout paths, or nested authority; every input is bound by a content digest and the catalog digest covers the canonical bytes. Completeness is complete only when every eligible registered project, workspace, and boundary tree is emitted without conflicts or limitations.

The agent_system command emits a bounded offline context capsule for a workspace-relative path or local Bazel label. It joins checked catalogs with the applicable AGENTS.md chain, nearest owner README, and policy source paths. Its digest-bound document links include the nearest package BUILD.bazel or BUILD, include.MODULE.bazel, and workspace MODULE.bazel when present. These locate the source to inspect; they do not select targets. JSON is the default; --markdown or --json=false renders Markdown. Existing symlinks resolve to their canonical workspace paths before ownership and policy selection. Escaping, dangling, or cyclic symlinks are refused; new paths may extend a verified existing parent.

bazel_agent bazel run //tools/agents/cmd/agent_system -- \
  --workspace-root "$PWD" --path projects/agents --markdown

The legacy agent_system_update wrapper also forwards these query flags and does not update tracked files. --task records a caller-supplied task ID; it does not select a goal. Input digests bind accepted catalog and document inputs.

Relative --workspace-root values resolve against BUILD_WORKSPACE_DIRECTORY under bazel run, so --workspace-root . means the source workspace. Outside Bazel they resolve against the current directory. normalize, coverage, and aggregate apply the same rule to relative input, catalog, and output file flags, with optional --workspace-root selecting another base. Absolute file paths retain their meaning; output parent directories must already exist. For example:

bazel_agent bazel run //tools/agents/cmd/agent_system -- aggregate \
  --catalog tools/agents/catalogs/capability.json \
  --input tools/agents/catalogs/skill-cases.json \
  --output out/<task>/coverage.json

The context command observes local Git HEAD and dirty state under the selected workspace, including untracked files and excluding ignored files. The identity.git object separates these observations from optional caller --revision and --dirty-inputs declarations. Without overrides, successful observations populate the existing identity fields; revisionSource and dirtyInputsSource name their basis. Failed Git reads leave git.dirty: null or the revision absent with explicit reasons. Legacy identity fields then retain an input digest and a conservative dirty default, clearly labelled.

Git commands have a combined three-second deadline and a 65,536-byte output limit each, disable optional index writes and fsmonitor hooks, and ignore ambient GIT_* variables. The report contains no changed-path list or Git stderr. Git and catalog reads are separate observations, not an atomic snapshot or proof that generated catalogs match HEAD.

The capsule reports the actual read time, unknown catalog freshness, and partial completeness. It does not observe runtime health, infer authority, resolve effective CODEOWNERS, or associate an unrelated active goal. Its capability list is an inventory of root-workspace and selected-workspace candidates, not task-intent routing or a complete cross-workspace dependency closure. Workspace check phases are references, not instructions to run a broad check.

identity.byteSize measures the complete canonical JSON, including its final newline. --max-bytes caps the selected JSON or Markdown output at 65,536 bytes by default; oversized output fails before writing a partial document. The limit may be set explicitly between 1,024 and 1,048,576 bytes. Verification:

bazel_agent bazel test //tools/agents/cmd/agent_system:agent_system_check

The tools/agents/control package owns the fixed runtime control kernel: per-package states and deadlines, account/lock acquisition, expires-checked leases, and expected-revision asset publication with namespace isolation. It persists an offline-readable packages.json snapshot.

Package registration preserves the caller’s scope, desired revision, and contract hash. Activation deadlines are fixed at registration time; KernelOptions.Deadlines are fixed at kernel creation for packages introduced through Mark. Reading status does not extend those deadlines. Lifecycle transitions do not establish revision identity, so observedRevision remains empty: the current API has no observed revision input.

The control_status command renders the snapshot/asset status for a control root without creating directories or starting a kernel (Markdown with --markdown):

bazel_agent bazel run //tools/agents/cmd/control_status:control_status -- \
  --workspace-root "$PWD" [--markdown]

The JSON healthy field describes the persisted package observations, with healthBasis: persisted-package-snapshot. Ready, degraded, and disabled packages count as healthy, matching the kernel. Missing, empty, malformed, or rejected observations produce healthy: null; consumers must support this unavailable value rather than assuming a boolean is always present. snapshotPath identifies the source. The report’s observedAt is its read time; each package retains the writer’s observationTime.

Freshness is unknown unless the caller supplies a positive duration such as --max-snapshot-age 5m. That bound yields within-age-bound or stale; stale observations make snapshot health unavailable. This is an explicit caller policy, not a heartbeat or runtime liveness guarantee. Live runtime health remains unavailable even when every observation is within the bound. The snapshot format does not identify its writer, so report runtimeId is empty with an unavailable reason. An asset’s runtimeId identifies its publisher only.

Verification:

bazel_agent bazel test //tools/agents/control:all //tools/agents/cmd/control_status:all

3.3 - Android

Android

3.4 - Android cmdtools

Android Command Line Tools

3.5 - Ansible

Bazel rules for ansible

ansible_lint runs ansible-lint from Bazel-managed Python dependencies. A Go test runner exposes the CLI binaries under their hyphenated names, configures writable Ansible paths, and invokes the linter against workspace-relative sources.

Molecule is not integrated yet. The likely path is to add Molecule to these Python requirements and invoke it through a Bazel-native Go runner, but practical scenarios require choosing and provisioning a Molecule driver before any scenarios can run.

3.6 - Ast-grep

Ast-grep

3.7 - Bazel configs

Bazel config targets

Targets that pull from the private Harbor registry are disabled by default so repository-wide builds work while Harbor is unavailable. Enable them with --config=harbor when the registry is reachable.

3.8 - Bazel shell worker

Bazel worker that runs shell commands

3.8.1 - Bzl

Bazel code

3.8.1.1 - al_genrule

al_genrule

load("@com_alwaldend_src//tools/shell_worker/main/bzl:al_genrule.bzl", "al_genrule")

al_genrule(test, executable, **kwargs)

Generate al_genrule target

PARAMETERS

Name Description Default Value
test If set, use al_genrule_test False
executable if set, use al_genrule_executable False
kwargs kwargs for the rule none

3.8.1.2 - al_genrule_rule

al_genrule_executable

load("@com_alwaldend_src//tools/shell_worker/main/bzl:al_genrule_rule.bzl", "al_genrule_executable")

al_genrule_executable(name, srcs, data, outs, cmd, set_flags, shell, tools, worker)

Build executable using shell worker

ATTRIBUTES

Name Description Type Mandatory Default
name A unique name for this target. Name required
srcs Sources, will not be added to runfiles List of labels optional []
data Data, will be added to runfiles List of labels optional []
outs Outputs List of labels; nonconfigurable required
cmd Script to execute String required
set_flags set flags List of strings optional ["-eux"]
shell shell to use String optional "/bin/sh"
tools Tools, will be added to runfiles List of labels optional []
worker Worker binary Label optional "@com_alwaldend_src//tools/shell_worker"

al_genrule_regular

load("@com_alwaldend_src//tools/shell_worker/main/bzl:al_genrule_rule.bzl", "al_genrule_regular")

al_genrule_regular(name, srcs, data, outs, cmd, set_flags, shell, tools, worker)

Build shell worker rule

ATTRIBUTES

Name Description Type Mandatory Default
name A unique name for this target. Name required
srcs Sources, will not be added to runfiles List of labels optional []
data Data, will be added to runfiles List of labels optional []
outs Outputs List of labels; nonconfigurable required
cmd Script to execute String required
set_flags set flags List of strings optional ["-eux"]
shell shell to use String optional "/bin/sh"
tools Tools, will be added to runfiles List of labels optional []
worker Worker binary Label optional "@com_alwaldend_src//tools/shell_worker"

al_genrule_test

load("@com_alwaldend_src//tools/shell_worker/main/bzl:al_genrule_rule.bzl", "al_genrule_test")

al_genrule_test(name, srcs, data, outs, cmd, set_flags, shell, tools, worker)

Test using shell worker

ATTRIBUTES

Name Description Type Mandatory Default
name A unique name for this target. Name required
srcs Sources, will not be added to runfiles List of labels optional []
data Data, will be added to runfiles List of labels optional []
outs Outputs List of labels; nonconfigurable required
cmd Script to execute String required
set_flags set flags List of strings optional ["-eux"]
shell shell to use String optional "/bin/sh"
tools Tools, will be added to runfiles List of labels optional []
worker Worker binary Label optional "@com_alwaldend_src//tools/shell_worker"

3.9 - Bazelrc

Bazelrc files
bazel run //tools/bazelrc:preset.update

The agent profile must not propagate ambient TEMP, TMP, or TMPDIR values into repository rules, actions, host actions, or tests. Those execution contexts use Bazel-managed temporary storage; host tools own any explicit task/run scratch they require.

Agent tests use Bazel’s normal result cache. Tests that inspect undeclared workspace files must opt out with the no-cache tag.

Agent commands use Bazel’s default lockfile update mode. Review and commit generated lockfile changes with dependency changes. CI retains strict lockfile checking; use --lockfile_mode=error for an explicit reproducibility check.

In the root workspace, lint actions fail on violations. Their failure setting is identical across normal and lint configurations to preserve the analysis cache when switching modes. --config=lint enables the linter aspects and requests only lint reports and skill validation, not ordinary target outputs.

3.10 - Black

Black

3.11 - Blender

Blender

3.12 - Buf

Buf

3.14 - Bzl

Bazel rules related to Bazel itself

3.14.1 - Bzl

Bazel code

3.14.1.1 - al_alias_map

al_alias_map

load("@com_alwaldend_src//tools/bzl/main/bzl:al_alias_map.bzl", "al_alias_map")

al_alias_map(aliases, visibility)

Generate aliases from an alias map

PARAMETERS

Name Description Default Value
aliases alias map, keys are names, values are alias arguments none
visibility default visibility ["//:__subpackages__"]

3.14.1.2 - al_bzl_generate_repository

al_bzl_generate_repository

load("@com_alwaldend_src//tools/bzl/main/bzl:al_bzl_generate_repository.bzl", "al_bzl_generate_repository")

al_bzl_generate_repository(name, files, repo_mapping)

Generate a repository

ATTRIBUTES

Name Description Type Mandatory Default
name A unique name for this repository. Name required
files Files to generate, keys are paths, values are file contents Dictionary: String -> String optional {}
repo_mapping In WORKSPACE context only: a dictionary from local repository name to global repository name. This allows controls over workspace dependency resolution for dependencies of this repository.

For example, an entry "@foo": "@bar" declares that, for any time this repository depends on @foo (such as a dependency on @foo//some:target, it should actually resolve that dependency within globally-declared @bar (@bar//some:target).

This attribute is not supported in MODULE.bazel context (when invoking a repository rule inside a module extension’s implementation function).
Dictionary: String -> String optional

3.14.1.3 - al_bzl_library_map

al_bzl_library_map

load("@com_alwaldend_src//tools/bzl/main/bzl:al_bzl_library_map.bzl", "al_bzl_library_map")

al_bzl_library_map(name, visibility, libs, deps, **kwargs)

Create bzl_library targets from a map

PARAMETERS

Name Description Default Value
name combined bzl_library target name none
visibility

-

None
libs bzl_library names {}
deps other al_bzl_library_map targets []
kwargs bzl_library kwargs none

3.14.1.4 - al_bzl_target_doc

al_bzl_target_doc

load("@com_alwaldend_src//tools/bzl/main/bzl:al_bzl_target_doc.bzl", "al_bzl_target_doc")

al_bzl_target_doc(name, visibility, subpackages)

Document bazel targets

PARAMETERS

Name Description Default Value
name target name none
visibility

-

none
subpackages list of subpackages []

3.14.1.5 - al_genquery_write_to_source_file

al_genquery_write_to_source_file

load("@com_alwaldend_src//tools/bzl/main/bzl:al_genquery_write_to_source_file.bzl", "al_genquery_write_to_source_file")

al_genquery_write_to_source_file(name, expression, scope, var_name, out_file)

Write genquery result to a bzl file

Example:

    al_genquery_write_to_source_file(
        name = "al_bzl_libs",
        expression = """
            filter(
                "^//",
                attr(
                    "srcs",
                    ".{3,}",
                    kind(
                        "bzl_library",
                        deps("//bzl")
                    )
                )
            )
        """,
        out_file = "al_bzl_libs.bzl",
        scope = ["//bzl"],
        var_name = "AL_BZL_LIBS",
    )

PARAMETERS

Name Description Default Value
name name prefix none
expression genquery expression none
scope genquery scope none
var_name variable name in the generated .bzl file none
out_file output bzl file none

3.15 - Bzlenv

Setup bazel environment

Rules to create a bazel environment which functions similar to venv

  • Adds bazel-built tools to ${PATH}
  • Exports .env

Create env and activate:

. "$(bazel run //tools/bzlenv)"

Activate existing env:

. .bzlenv/bin/activate

Deactivate env:

bzlenv_deactivate

3.15.1 - Bzl

Bazel code

3.15.1.1 - al_bzlenv_binary

al_bzlenv_binary

load("@com_alwaldend_src//tools/bzlenv/main/bzl:al_bzlenv_binary.bzl", "al_bzlenv_binary")

al_bzlenv_binary(name, activate, tools)

Dev shell binary

ATTRIBUTES

Name Description Type Mandatory Default
name A unique name for this target. Name required
activate Activation script Label optional "@com_alwaldend_src//tools/bzlenv/main/sh:activate"
tools Tools, keys are tool names, values are tool labels Dictionary: String -> Label optional {}

3.16 - Cc

Cc

//:refresh_compile_commands uses the pinned Hedron extractor. Its archive is declared through use_repo_rule and fetched when the extractor’s package is loaded, rather than during module resolution. LLVM toolchain registration remains automatic.

3.17 - Cloc

Cloc

3.18 - Cmctl

Cert Manager cmctl

3.19 - Consul

Consul

3.19.1 - Gen gossip key

Generate a gossip key and write it to a kv secret

3.20 - Dart Sass

Dart Sass toolchain

Dart Sass binary toolchain, used by Hugo for toCSS "dartsass" builds.

3.21 - Dnscontrol

Dnscontrol tool

3.22 - Drawio

Bazel rules for drawio

drawio_svg in defs.bzl renders named pages from a .drawio file with the pinned Drawio web exporter and the existing pinned Chrome-for-Testing browser. The extraction action unpacks the web application from the Drawio AppImage; rendering uses a small Puppeteer bridge for its export messages. Neither action uses a host display server or accesses the network. JavaScript keeps this adapter close to Drawio’s browser API and the existing Puppeteer dependency.

Use the rule from an explicit source-update target with write_source_files, as in //infra/arch:update. Normal documentation consumes the maintained SVGs, not the rendering tool. The generated freshness tests catch stale output.

Exports use a light theme with an opaque white canvas, keeping labels and connectors readable in both light and dark documentation themes and standalone image viewers. The renderer adds this canvas on every export.

Chrome’s inner sandbox is disabled because it cannot nest within the Bazel Linux sandbox used for these actions. The Bazel sandbox remains enabled; requests outside local files and embedded data are rejected. The renderer is intended for checked-in, reviewed diagram sources and propagates export failures.

The repeat-render test checks byte equality, including stable SVG identifiers. Rendering uses only the declared Liberation Fonts 2.1.5 through an isolated Fontconfig configuration. Helvetica/Arial map to Liberation Sans, Times to Liberation Serif, and Courier to Liberation Mono. The fonts are licensed under the SIL Open Font License 1.1; their archive retains LICENSE.

3.22.1 - Bzl

Bazel code

3.22.1.1 - al_drawio_run_binary

al_drawio_run_binary

load("@com_alwaldend_src//tools/drawio/main/bzl:al_drawio_run_binary.bzl", "al_drawio_run_binary")

al_drawio_run_binary(name, srcs, out, arguments, cmd_timeout)

Run drawio a a build action

ATTRIBUTES

Name Description Type Mandatory Default
name A unique name for this target. Name required
srcs Sources List of labels optional []
out Output Label; nonconfigurable required
arguments Arguments, location statements are expanded List of strings required
cmd_timeout Drawio command timeout String optional "1m"

3.22.1.2 - al_drawio_toolchain

al_drawio_toolchain

load("@com_alwaldend_src//tools/drawio/main/bzl:al_drawio_toolchain.bzl", "al_drawio_toolchain")

al_drawio_toolchain(name, drawio)

Drawio toolchain

ATTRIBUTES

Name Description Type Mandatory Default
name A unique name for this target. Name required
drawio Drawio binary Label required

3.23 - File installer

CLI tool to install files

3.25 - Flake8

Flake8

3.27 - Flux operator

Flux operator

3.28 - Forgejo

Forgejo

3.29 - Gazelle

Repository BUILD file generation

//tools/gazelle:gazelle runs the repository’s Gazelle language plugins. Repository-wide directives remain in root BUILD.bazel, where Gazelle discovers them for all packages. Root //:gazelle and //:gazelle_bin remain compatibility entry points.

//tools/gazelle:gazelle_python_manifest.update refreshes root gazelle_python.yaml; //tools/gazelle:gazelle_python_manifest.test validates its integrity against root requirements.txt. Keeping the manifest at the repository root preserves Python dependency discovery in every package.

3.30 - Git

Git rules

3.30.1 - Bzl

Bazel rules

3.30.1.1 - al_git_binary

al_git_binary

load("@com_alwaldend_src//tools/git/main/bzl:al_git_binary.bzl", "al_git_binary")

al_git_binary(name, arguments)

Run git binary

ATTRIBUTES

Name Description Type Mandatory Default
name A unique name for this target. Name required
arguments Git arguments (templated) List of strings optional []

3.30.1.2 - al_git_changelog

al_git_changelog

load("@com_alwaldend_src//tools/git/main/bzl:al_git_changelog.bzl", "al_git_changelog")

al_git_changelog(name, visibility, git_binary, subpackages)

Create changelog target

PARAMETERS

Name Description Default Value
name target name prefix none
visibility visibility none
git_binary

-

"@git//:git"
subpackages subpackages []

3.30.1.3 - al_git_current_state

3.30.1.4 - al_git_extension

al_git_extension

al_git_extension = use_extension("@com_alwaldend_src//tools/git/main/bzl:al_git_extension.bzl", "al_git_extension")
al_git_extension.local_git(name)

Create git repos

TAG CLASSES

Attributes

Name Description Type Mandatory Default
name Name Name required

3.30.1.5 - al_git_info_file

al_git_info_file

load("@com_alwaldend_src//tools/git/main/bzl:al_git_info_file.bzl", "al_git_info_file")

al_git_info_file(name, git_state, git_tool, timeout)

Generate git info file

ATTRIBUTES

Name Description Type Mandatory Default
name A unique name for this target. Name required
git_state Files that should invalidate the cache on new commit List of labels optional []
git_tool Git tool to use Label optional "@com_alwaldend_src//tools/git/main/go"
timeout Timeout in seconds Integer optional 60

3.30.1.6 - al_git_repo

al_git_repo

load("@com_alwaldend_src//tools/git/main/bzl:al_git_repo.bzl", "al_git_repo")

al_git_repo(name, repo_mapping)

Git repo

ATTRIBUTES

Name Description Type Mandatory Default
name A unique name for this repository. Name required
repo_mapping In WORKSPACE context only: a dictionary from local repository name to global repository name. This allows controls over workspace dependency resolution for dependencies of this repository.

For example, an entry "@foo": "@bar" declares that, for any time this repository depends on @foo (such as a dependency on @foo//some:target, it should actually resolve that dependency within globally-declared @bar (@bar//some:target).

This attribute is not supported in MODULE.bazel context (when invoking a repository rule inside a module extension’s implementation function).
Dictionary: String -> String optional

3.30.1.7 - al_git_resolved_toolchain

al_git_resolved_toolchain

load("@com_alwaldend_src//tools/git/main/bzl:al_git_resolved_toolchain.bzl", "al_git_resolved_toolchain")

al_git_resolved_toolchain(name)

Resolved git toolchain

ATTRIBUTES

Name Description Type Mandatory Default
name A unique name for this target. Name required

3.30.1.8 - al_git_run_binary

al_git_run_binary

load("@com_alwaldend_src//tools/git/main/bzl:al_git_run_binary.bzl", "al_git_run_binary")

al_git_run_binary(name, srcs, outs, arguments, git)

Run a git binary as a build action

ATTRIBUTES

Name Description Type Mandatory Default
name A unique name for this target. Name required
srcs Files to be made available List of labels optional []
outs Outputs List of labels; nonconfigurable required
arguments Arguments (Location is expanded) List of strings optional []
git Git binary Label required

3.30.1.9 - al_git_toolchain

al_git_toolchain

load("@com_alwaldend_src//tools/git/main/bzl:al_git_toolchain.bzl", "al_git_toolchain")

al_git_toolchain(name, git_dir, git_path, git_root, invalidation)

Local git toolchain

ATTRIBUTES

Name Description Type Mandatory Default
name A unique name for this target. Name required
git_dir Git directory path String required
git_path Git binary path String required
git_root Git workspace path String required
invalidation Files that should invalidate git actions List of labels optional []

3.30.2 - Proto

Protobuf contracts

3.30.2.1 - contracts

Proto docs for contracts.proto
load("@rules_java//java:defs.bzl", "java_library")

java_library(
    name = "name",
    deps = [
        "@com_alwaldend_src//tools/git/main/proto/contracts:contracts_java_library",
    ],
)
load("@rules_go//go:def.bzl", "go_library")

go_library(
    name = "name",
    deps = [
        "@com_alwaldend_src//tools/git/main/proto/contracts:contracts",
    ],
)
syntax = "proto3";

package git;

option go_package = "git.alwaldend.com/alwaldend/src/tools/git/main/proto/contracts";

message GitSignature {
  string name = 1;
  string email = 2;
  int64 when = 3;
}

message GitCommit {
  string hash = 1;
  GitSignature author = 2;
  GitSignature committer = 3;
  string merge_tag = 4;
  string pgp_signature = 5;
  string message = 6;
  repeated string tags = 7;
  map<string, bool> changed_files = 8;
}

message GitTagAnnotated {
  GitSignature tagger = 1;
  string hash = 2;
  string message = 3;
  string pgp_signature = 4;
}

message GitTag {
  string name = 1;
  string target = 2;
  GitTagAnnotated annotated = 3;
}

message GitRemote {
  string name = 1;
  repeated string urls = 2;
}

message GitInfo {
  map<string, GitCommit> commits = 1;
  repeated string commits_order = 2;
  map<string, GitTag> tags = 3;
  repeated GitRemote remotes = 4;
}

3.31 - Git filter repo

Git filter repo

3.32 - Gitea

Gitea

3.33 - Go

Go rules

3.33.1 - Bzl

Bazel code

3.33.1.1 - al_go_repository

al_go_repository

al_go_repository = use_extension("@com_alwaldend_src//tools/go/main/bzl:al_go_repository.bzl", "al_go_repository")
al_go_repository.go_repository(name, importpath, sum, version)

Extension wrapper around go_repository (useless because you can just call use_repo_rule)

TAG CLASSES

Attributes

Name Description Type Mandatory Default
name Name Name required
importpath importpath String required
sum checksum String optional ""
version - String required

3.34 - Gzip

Gzip rules

3.34.1 - Bzl

Bazel code

3.34.1.1 - al_gzip_extension

al_gzip_extension

al_gzip_extension = use_extension("@com_alwaldend_src//tools/gzip/main/bzl:al_gzip_extension.bzl", "al_gzip_extension")
al_gzip_extension.download(name, integrity, url)

Extension for gzip repos

TAG CLASSES

Attributes

Name Description Type Mandatory Default
name Name Name required
integrity Integrity String optional ""
url Url String required

3.34.1.2 - al_gzip_repo

al_gzip_repo

load("@com_alwaldend_src//tools/gzip/main/bzl:al_gzip_repo.bzl", "al_gzip_repo")

al_gzip_repo(name, integrity, repo_mapping, url)

Gzip repo

ATTRIBUTES

Name Description Type Mandatory Default
name A unique name for this repository. Name required
integrity Integrity String optional ""
repo_mapping In WORKSPACE context only: a dictionary from local repository name to global repository name. This allows controls over workspace dependency resolution for dependencies of this repository.

For example, an entry "@foo": "@bar" declares that, for any time this repository depends on @foo (such as a dependency on @foo//some:target, it should actually resolve that dependency within globally-declared @bar (@bar//some:target).

This attribute is not supported in MODULE.bazel context (when invoking a repository rule inside a module extension’s implementation function).
Dictionary: String -> String optional
url Url String required

3.35 - Harbor

Harbor CLI

3.36 - Helm

Bazel rules for helm

3.36.1 - Bzl

Bazel code

3.36.1.1 - al_helm_binary

al_helm_binary

load("@com_alwaldend_src//tools/helm/main/bzl:al_helm_binary.bzl", "al_helm_binary")

al_helm_binary(name, data, arguments, cd)

Helm binary

ATTRIBUTES

Name Description Type Mandatory Default
name A unique name for this target. Name required
data Helm chart List of labels optional []
arguments Helm arguments List of strings optional []
cd Cd to a directory before running bazel String optional "."

3.36.1.2 - al_helm_chart

al_helm_chart

load("@com_alwaldend_src//tools/helm/main/bzl:al_helm_chart.bzl", "al_helm_chart")

al_helm_chart(name, deps, package, source)

Helm chart

ATTRIBUTES

Name Description Type Mandatory Default
name A unique name for this target. Name required
deps Helm chart deps List of labels optional []
package Helm chart package Label optional None
source Helm chart source Label optional None

3.36.1.3 - al_helm_chart_info

load("@com_alwaldend_src//tools/helm/main/bzl:al_helm_chart_info.bzl", "AlHelmChartInfo")

AlHelmChartInfo(source, package, deps, files_info)

Information about a helm chart

FIELDS

Name Description
source Chart sources (PackageFilegroupInfo, optional)
package Chart package (tgz file)
deps Chart deps (depset of AlHelmChartInfo)
files_info Chart file structure (PackageFilesInfo)

3.36.1.4 - al_helm_chart_lock

al_helm_chart_lock

load("@com_alwaldend_src//tools/helm/main/bzl:al_helm_chart_lock.bzl", "al_helm_chart_lock")

al_helm_chart_lock(name, lock, lock_out)

Generate targets for a chart lock

PARAMETERS

Name Description Default Value
name name none
lock lock label none
lock_out parsed lock filename none

3.36.1.5 - al_helm_cmds

3.36.1.6 - al_helm_deps

al_helm_deps

al_helm_deps = use_extension("@com_alwaldend_src//tools/helm/main/bzl:al_helm_deps.bzl", "al_helm_deps")
al_helm_deps.from_locks(name, integrity, locks)

Extension to download helm dependencies

TAG CLASSES

Attributes

Name Description Type Mandatory Default
name Repo name Name required
integrity Intergrity for locks, keys are packages, values are integrity Dictionary: String -> String optional {}
locks Helm lock labels List of labels optional []

3.36.1.7 - al_helm_deps_repo

al_helm_deps_repo

load("@com_alwaldend_src//tools/helm/main/bzl:al_helm_deps_repo.bzl", "al_helm_deps_repo")

al_helm_deps_repo(name, integrity, locks, repo_mapping)

Helm deps repo

ATTRIBUTES

Name Description Type Mandatory Default
name A unique name for this repository. Name required
integrity Intergrity for locks, keys are packages, values are integrity Dictionary: String -> String optional {}
locks Lock labels to parse List of labels optional []
repo_mapping In WORKSPACE context only: a dictionary from local repository name to global repository name. This allows controls over workspace dependency resolution for dependencies of this repository.

For example, an entry "@foo": "@bar" declares that, for any time this repository depends on @foo (such as a dependency on @foo//some:target, it should actually resolve that dependency within globally-declared @bar (@bar//some:target).

This attribute is not supported in MODULE.bazel context (when invoking a repository rule inside a module extension’s implementation function).
Dictionary: String -> String optional

3.36.1.8 - al_helm_toolchain

al_helm_toolchain

load("@com_alwaldend_src//tools/helm/main/bzl:al_helm_toolchain.bzl", "al_helm_toolchain")

al_helm_toolchain(name, helm)

Helm toolchain

ATTRIBUTES

Name Description Type Mandatory Default
name A unique name for this target. Name required
helm Helm binary Label required

3.37 - Hermes install

Run the Hermes Agent install script

Run the pinned Hermes Agent install script:

bazel run //tools/hermes_install

3.38 - Hooks

Git hooks

The hook installer resolves the repository’s effective hooks directory through Git. This supports linked worktrees and repositories that configure core.hooksPath.

The installed pre-commit hook requires bazel_agent. Bootstrap it before installing the hook:

bazel run --config=agent //projects/bazel_agent:install

Install or update the checked-in hooks:

bazel_agent bazel run //:write_git_hooks

Verify that every hook is current and executable without changing it:

bazel_agent bazel run //:write_git_hooks -- test

3.39 - Http server

Bazel rules for running http.server

3.39.1 - Bzl

Bazel code

3.39.1.1 - al_http_server_binary

al_http_server_binary

load("@com_alwaldend_src//tools/http_server/main/bzl:al_http_server_binary.bzl", "al_http_server_binary")

al_http_server_binary(name, srcs, arguments)

Run a http server

ATTRIBUTES

Name Description Type Mandatory Default
name A unique name for this target. Name required
srcs Files to symlink List of labels optional []
arguments Arguments List of strings optional []

3.40 - Hugo

Hugo toolchain

Hugo binary toolchain for the repository. Build rules live in rules_hugo.

3.41 - Install file

Bazel rules to install files

3.41.1 - Bzl

Bazel code

3.41.1.1 - al_install_file

al_install_file

load("@com_alwaldend_src//tools/install_file/main/bzl:al_install_file.bzl", "al_install_file")

al_install_file(name, args, install_file_label, visibility, **py_binary_kwargs)

Create py_binary target to install file

PARAMETERS

Name Description Default Value
name target name none
args install-file args []
install_file_label

-

"//tools/install_file/main/py:install_file_lib"
visibility

-

["//:__subpackages__"]
py_binary_kwargs

-

none

3.42 - Isort

Isort

3.43 - Js

Js

Repository JavaScript tooling dependencies belong to the pnpm workspace in tools/. Its package.json and pnpm-lock.yaml own their requested and resolved versions. //tools:node_modules owns the Bazel package store and links; loading the repository root package does not load the npm extension’s generated rules.

Run pnpm with //tools/pnpm, passing --dir with the absolute path to tools/ for dependency updates. Keep lifecycle scripts disabled (--ignore-scripts) when updating the lockfile.

3.44 - Kt

Kotlin

3.46 - Lua

Lua rules

3.46.1 - Bzl

Bazel code

3.46.1.1 - al_lua_library

al_lua_library

load("@com_alwaldend_src//tools/lua/main/bzl:al_lua_library.bzl", "al_lua_library")

al_lua_library(name, srcs, check, stylua_config_label, stylua_label, pkg_kwargs, visibility)

Generate targets for a lua library

PARAMETERS

Name Description Default Value
name library name none
srcs library sources none
check if set, only these files will be checked []
stylua_config_label

-

"//tools/stylua:stylua_config"
stylua_label

-

"//tools/stylua"
pkg_kwargs

-

{}
visibility visibility ["//:__subpackages__"]

3.47 - Make install

Rules to create tar archives that can be installed with make

3.47.1 - Bzl

Bazel code

3.47.1.1 - al_make_install

al_make_install

load("@com_alwaldend_src//tools/make_install/main/bzl:al_make_install.bzl", "al_make_install")

al_make_install(name, srcs)

Create the make install executable and a filegroup

ATTRIBUTES

Name Description Type Mandatory Default
name A unique name for this target. Name required
srcs Make install filegroups List of labels optional []

3.47.1.2 - al_make_install_binary

al_make_install_binary

load("@com_alwaldend_src//tools/make_install/main/bzl:al_make_install_binary.bzl", "al_make_install_binary")

al_make_install_binary(name, src, arguments)

Create a binary target for a make install

ATTRIBUTES

Name Description Type Mandatory Default
name A unique name for this target. Name required
src Make install target Label required
arguments Arugments for the executable List of strings optional []

3.47.1.3 - al_make_install_filegroup

al_make_install_filegroup

load("@com_alwaldend_src//tools/make_install/main/bzl:al_make_install_filegroup.bzl", "al_make_install_filegroup")

al_make_install_filegroup(name, deps, srcs, diff_args, install_args, install_dir, pkg_prefix)

Create a make install filegroup

ATTRIBUTES

Name Description Type Mandatory Default
name A unique name for this target. Name required
deps Deps List of labels optional []
srcs Sources to install List of labels optional []
diff_args Diff args List of strings optional []
install_args Install args List of strings optional ["--compare", "-D"]
install_dir Install directory String optional "${HOME}"
pkg_prefix Ignore that prefix for srcs String required

3.47.1.4 - al_make_install_filegroup_info

load("@com_alwaldend_src//tools/make_install/main/bzl:al_make_install_filegroup_info.bzl", "AlMakeInstallFilegroupInfo")

AlMakeInstallFilegroupInfo(srcs, deps, install_dir, origin, install_args, diff_args, pkg_prefix)

Describe install info for a single filegrop

FIELDS

Name Description
srcs depset of PackageFilegroupInfo
deps depset of AlMakeInstallFilegroupInfo
install_dir Install directory
origin Rule label
install_args Args for the install command
diff_args Args for the diff command
pkg_prefix Ignore that prefix for srcs

3.48 - Md

Md rules

3.48.1 - Bzl

Bazel code

3.48.1.1 - al_md_data

al_md_data

load("@com_alwaldend_src//tools/md/main/bzl:al_md_data.bzl", "al_md_data")

al_md_data(name, srcs, deps, **kwargs)

Markdown data backed by a filegroup

Targets:

  • ${name}: filegroup

PARAMETERS

Name Description Default Value
name filegroup name none
srcs markdown files none
deps deps []
kwargs filegroup kwargs none

3.49 - Mermaid

Bazel-managed Mermaid diagram renderer

This package exposes the Mermaid CLI as a repository-wide Bazel tool. Bazel provisions the pinned Node toolchain, JavaScript dependency graph, Mermaid CLI, and Chrome-for-Testing browser used by Puppeteer. Rendering runs as a Bazel target or action; it does not use a host browser or download one during an npm lifecycle hook.

The JavaScript launcher runs from Bazel’s output tree. Pass absolute paths when rendering source-tree files directly:

repo_root="$PWD"
bazel_agent bazel run //tools/mermaid:mmdc -- \
  -i "${repo_root}/path/to/diagram.mmd" \
  -o "${repo_root}/path/to/diagram.svg"

Prefer a mermaid_svg action plus write_source_file for maintained diagrams; those targets use declared Bazel paths and need no absolute-path handling.

3.50 - Minisign

Minisign

3.51 - Mypy

Mypy

3.52 - Nc

Netcat

3.53 - Nmap

Nmap

3.55 - Nping

Nping - Network packet generation tool & ping utility

3.56 - Oci

Oci

3.57 - openbao

Openbao

3.58 - Opencode

Opencode - The open source AI coding agent

3.59 - Ops

Ops CLI binary

3.60 - Oras

Oras rules

3.61 - Patch

Patch rules

3.61.1 - Bzl

Bazel code

3.61.1.1 - al_apply_patches

al_apply_patches

load("@com_alwaldend_src//tools/patch/main/bzl:al_apply_patches.bzl", "al_apply_patches")

al_apply_patches(name, src, patches, visibility, **kwargs)

Create a genrule applying patches

PARAMETERS

Name Description Default Value
name genrule name none
src source archive label none
patches patches label none
visibility visibility ["//:__subpackages__"]
kwargs other genrule kwargs none

3.62 - Pkg

Package rules

3.62.1 - Bzl

Bazel code

3.62.1.1 - al_genrule_src

al_genrule_src

load("@com_alwaldend_src//tools/pkg/main/bzl:al_genrule_src.bzl", "al_genrule_src")

al_genrule_src(name, srcs, visibility)

Create a filegroup and a genrule generating a tar archive

PARAMETERS

Name Description Default Value
name genrule name none
srcs source labels []
visibility

-

["//:__subpackages"]

3.62.1.2 - al_pkg_basic_naming

al_pkg_basic_naming

load("@com_alwaldend_src//tools/pkg/main/bzl:al_pkg_basic_naming.bzl", "al_pkg_basic_naming")

al_pkg_basic_naming(name, deps)

Variables for @rules_pkg

ATTRIBUTES

Name Description Type Mandatory Default
name A unique name for this target. Name required
deps Deps to merge List of labels optional []

3.62.1.3 - al_pkg_extract_dir

al_pkg_extract_dir

load("@com_alwaldend_src//tools/pkg/main/bzl:al_pkg_extract_dir.bzl", "al_pkg_extract_dir")

al_pkg_extract_dir(name, src, out, arguments)

Extract an archive into a TreeArtifact

ATTRIBUTES

Name Description Type Mandatory Default
name A unique name for this target. Name required
src Archive to unpack Label required
out Output directory name String optional ""
arguments Additional arguments List of strings optional []

3.62.1.4 - al_pkg_tar_combined

al_pkg_tar_combined

load("@com_alwaldend_src//tools/pkg/main/bzl:al_pkg_tar_combined.bzl", "al_pkg_tar_combined")

al_pkg_tar_combined(name, srcs, strip_components, **kwargs)

Create a genrule combining several tars into one

PARAMETERS

Name Description Default Value
name genrule name none
srcs dicts tar archives ({“label”: “tar label”, “dir”: “target dir”}) []
strip_components value of –stip-components 2
kwargs other genrule kwargs none

3.62.1.5 - al_unpack_archives

al_unpack_archives

load("@com_alwaldend_src//tools/pkg/main/bzl:al_unpack_archives.bzl", "al_unpack_archives")

al_unpack_archives(name, srcs, out)

Unpack several archives using tar into a directory

ATTRIBUTES

Name Description Type Mandatory Default
name A unique name for this target. Name required
srcs - List of labels required
out - String optional ""

3.63 - Pkgsite

Pkgsite

3.64 - Pnpm

Pnpm

3.65 - Postcss

Postcss

3.66 - Prettier

Prettier

3.67 - Print deps

Aspect to print deps

3.67.1 - Bzl

Bazel code

3.67.1.1 - al_print_deps

al_print_deps

load("@com_alwaldend_src//tools/print_deps/main/bzl:al_print_deps.bzl", "al_print_deps")

al_print_deps()

ASPECT ATTRIBUTES

Name Type
deps String

ATTRIBUTES

3.68 - Proto

Protobuf rules

3.68.1 - Bzl

Bazel code

3.68.1.1 - al_proto_docs

al_proto_docs

load("@com_alwaldend_src//tools/proto/main/bzl:al_proto_docs.bzl", "al_proto_docs")

al_proto_docs(name, src, prefix, visibility, renames)

Generate protobuf documentation

PARAMETERS

Name Description Default Value
name name none
src protobuf source file none
prefix

-

None
visibility visibility None
renames

-

None

3.69 - Py

Python rules

The repository Python dependency lock remains in root requirements.txt, next to pyproject.toml. Update it with //tools/py:requirements.update and validate it with //tools/py:requirements.test; the root labels remain compatibility entry points. These upstream pip-tools workflows require network access to resolve and validate package versions and run outside the action sandbox.

3.69.1 - Bzl

Bazel code

3.69.1.1 - al_compile_pip_requirements_combined

al_compile_pip_requirements_combined

load("@com_alwaldend_src//tools/py/main/bzl:al_compile_pip_requirements_combined.bzl", "al_compile_pip_requirements_combined")

al_compile_pip_requirements_combined(name, srcs, **kwargs)

Create compile_pip_requirements target for several requirement files

PARAMETERS

Name Description Default Value
name compile_pip_requirements name none
srcs list of labels of requirement files to combine none
kwargs kwargs for compile_pip_requirements none

3.69.1.2 - al_genrule_with_wheels

al_genrule_with_wheels

load("@com_alwaldend_src//tools/py/main/bzl:al_genrule_with_wheels.bzl", "al_genrule_with_wheels")

al_genrule_with_wheels(name, wheels, srcs, cmd, **kwargs)

Regular genrule with wheels added to ${PYTHONPATH}

PARAMETERS

Name Description Default Value
name genrule name none
wheels list of wheel labels none
srcs srcs for the genrule []
cmd genrule cmd []
kwargs other genrule kwargs none

3.69.1.3 - al_py_binary_shell

al_py_binary_shell

load("@com_alwaldend_src//tools/py/main/bzl:al_py_binary_shell.bzl", "al_py_binary_shell")

al_py_binary_shell(name, deps, srcs, shell_type, shell_label, **kwargs)

Create a py_binary target that allows you to run commands in proper python environment

PARAMETERS

Name Description Default Value
name target name none
deps py_binary deps []
srcs py_binary srcs []
shell_type ${BAZEL_PYTHON_SHELL_TYPE} "python"
shell_label

-

"//tools/py/main/py:bazel_python_shell_lib"
kwargs other py_binary kwargs none

3.69.1.4 - al_py_checker

al_py_checker

load("@com_alwaldend_src//tools/py/main/bzl:al_py_checker.bzl", "al_py_checker")

al_py_checker(name, tool, args_bin, args_test, test_size, disable_fix, **kwargs)

Create -fix and -test targets for a python checker

PARAMETERS

Name Description Default Value
name Name prefix None
tool Tool label None
args_bin Args for the binary target None
args_test Args for the test None
test_size

-

"small"
disable_fix If set, do not create fix target False
kwargs Kwargs for both targets none

3.69.1.5 - al_py_checkers

al_py_checkers

load("@com_alwaldend_src//tools/py/main/bzl:al_py_checkers.bzl", "al_py_checkers")

al_py_checkers(name, srcs, isort_label, black_label, mypy_label, flake8_label, pyproject_label)

Generate -fix and -test targets for python checkers

PARAMETERS

Name Description Default Value
name

-

none
srcs list of source file labels none
isort_label

-

"//tools/isort"
black_label

-

"//tools/black"
mypy_label

-

"//tools/mypy"
flake8_label

-

"//tools/flake8"
pyproject_label

-

"//tools/py:pyproject"

3.70 - Qt

Qt rules

The module configuration downloads SHA-256-pinned Qt 6.8.3 distributions via rules_qt and registers its build tools. Bazel builds do not require Qt under /opt or another host installation.

3.70.1 - Bzl

Bazel code

3.71 - Rclone

Rclone

3.72 - Readme tree

Tool to parse README.md files
bazel run tools/readme_tree -- parse -g -C "${PWD}" .

3.73 - Release

Release rules

3.73.1 - Bzl

Bazel bindings for the release tool

3.73.1.1 - al_release

al_release

load("@com_alwaldend_src//tools/release/main/bzl:al_release.bzl", "al_release")

al_release(name, srcs, git_bundle, git_state, manifest, project, release_name, release_tool,
           root_prefix)

Rule describing a release

ATTRIBUTES

Name Description Type Mandatory Default
name A unique name for this target. Name required
srcs Sources List of labels optional []
git_bundle Deterministic Git bundle used to generate release metadata Label optional "@com_alwaldend_src_tools_git//:release_git_state"
git_state Additional declared Git state used to generate release metadata List of labels optional []
manifest Load manifest from a file instead of generating it from srcs Label optional None
project Project package_name String required
release_name Release name String required
release_tool Release tool Label optional "@com_alwaldend_src//tools/release/main/go"
root_prefix Root prefix String optional "content/docs"

3.73.1.2 - al_release_binary

al_release_binary

load("@com_alwaldend_src//tools/release/main/bzl:al_release_binary.bzl", "al_release_binary")

al_release_binary(name, srcs, arguments, cmd, oras, release_tool)

Release binary

ATTRIBUTES

Name Description Type Mandatory Default
name A unique name for this target. Name required
srcs Releases List of labels optional []
arguments Arguments List of strings optional []
cmd Cmd String optional "deploy"
oras Oras binary Label optional "@com_alwaldend_src//tools/oras"
release_tool Release tool Label optional "@com_alwaldend_src//tools/release/main/go"

3.73.1.3 - al_release_deployment

al_release_deployment

load("@com_alwaldend_src//tools/release/main/bzl:al_release_deployment.bzl", "al_release_deployment")

al_release_deployment(name, oci_repository)

Deployment info

ATTRIBUTES

Name Description Type Mandatory Default
name A unique name for this target. Name required
oci_repository OCI repository url String optional ""

3.73.1.4 - al_release_deployment_info

load("@com_alwaldend_src//tools/release/main/bzl:al_release_deployment_info.bzl", "AlReleaseDeploymentInfo")

AlReleaseDeploymentInfo(info, info_file)

Deployment info

FIELDS

Name Description
info Deployment info struct
info_file Deployment info file

3.73.1.5 - al_release_deps

al_release_deps

load("@com_alwaldend_src//tools/release/main/bzl:al_release_deps.bzl", "al_release_deps")

al_release_deps(name, srcs, visibility, **kwargs)

Generate a dependency diagram using genquery

PARAMETERS

Name Description Default Value
name name none
srcs list of labels to generate deps for (should be full labels) none
visibility visibility None
kwargs kwargs for al_release_files none

3.73.1.6 - al_release_files

al_release_files

load("@com_alwaldend_src//tools/release/main/bzl:al_release_files.bzl", "al_release_files")

al_release_files(name, deps, srcs, deployments, ignore_suffixes, release_tool)

ATTRIBUTES

Name Description Type Mandatory Default
name A unique name for this target. Name required
deps Deps List of labels optional []
srcs Sources List of labels optional []
deployments Deployment info List of labels optional []
ignore_suffixes Ignore src files ending with these suffixes List of strings optional []
release_tool Release tool Label optional "@com_alwaldend_src//tools/release/main/go"

3.73.1.7 - al_release_files_info

load("@com_alwaldend_src//tools/release/main/bzl:al_release_files_info.bzl", "AlReleaseFilesInfo")

AlReleaseFilesInfo(files, manifest)

Release files

FIELDS

Name Description
files File dict, keys are filenames, values are Files
manifest Release manifest for srcs

3.73.1.8 - al_release_info

load("@com_alwaldend_src//tools/release/main/bzl:al_release_info.bzl", "AlReleaseInfo")

AlReleaseInfo(release_name, project, files, manifest)

Release information

FIELDS

Name Description
release_name Release name (string)
project Project subdir (string)
files File dict, keys are filenames, values are Files
manifest Release manifest (File)

3.73.2 - Proto

Protobuf contracts

3.73.2.1 - contracts

Proto docs for contracts.proto
load("@rules_java//java:defs.bzl", "java_library")

java_library(
    name = "name",
    deps = [
        "@com_alwaldend_src//tools/release/main/proto/contracts:contracts_java_library",
    ],
)
load("@rules_go//go:def.bzl", "go_library")

go_library(
    name = "name",
    deps = [
        "@com_alwaldend_src//tools/release/main/proto/contracts:contracts",
    ],
)
syntax = "proto3";

package release;

import "tools/git/main/proto/contracts/contracts.proto";

option go_package = "git.alwaldend.com/alwaldend/src/tools/release/main/proto/contracts";

message ReleaseHash {
  string algo = 1;
  string content = 2;
}

message ReleaseFile {
  repeated ReleaseHash hashes = 1;
  string name = 2;
  string safe_name = 6;
  string url = 3;
  int64 size = 4;
  string local_path = 5;
}

message ReleaseItem {
  ReleaseFile file = 1;
  repeated ReleaseDeployment deployments = 2;
}

message Project {
  string subdir = 1;
  string safe_subdir = 2;
}

message Git {
  git.GitCommit revision = 1;
  repeated git.GitCommit commits = 2;
}

message ReleasePageSectionItemAttr {
  string name = 1;
  string content = 2;
}

message ReleasePageSectionItem {
  string content = 1;
  string content_url = 2;
  repeated ReleasePageSectionItemAttr attrs = 3;
}

message ReleasePageSection {
  string title = 1;
  repeated ReleasePageSectionItem items = 2;
}

message ReleasePage {
  repeated ReleasePageSection sections = 1;
}

message ReleaseDeploymentOci {
  string repository = 1;
  repeated string tags = 2;
}

message ReleaseDeployment {
  ReleaseDeploymentOci oci = 1;
}

message Release {
  repeated ReleaseItem items = 1;
  string name = 2;
  Project project = 3;
  Git git = 4;
}

3.74 - Replace section

Replace sections of files

3.75 - Repo map

Extension to download several versions of a repository depending on a platform

3.75.1 - Bzl

Bazel code

3.75.1.1 - al_repo_map

al_repo_map

al_repo_map = use_extension("@com_alwaldend_src//tools/repo_map/main/bzl:al_repo_map.bzl", "al_repo_map")
al_repo_map.download(name, build_file_content, build_file_native_binary, download_type, executable,
                     repos, strip_prefix)

Extension to create several repos from a map

TAG CLASSES

Attributes

Name Description Type Mandatory Default
name Name Name required
build_file_content Build file content String optional ""
build_file_native_binary Args for a native binary build file Dictionary: String -> String optional {}
download_type Download type String optional "http_archive"
executable Field executable for http_file Boolean optional False
repos Map of repos Dictionary: String -> List of strings required
strip_prefix Strip prefix String optional ""

3.76 - Repository AL configuration

Shared configuration for repository command wrappers

//tools/al:config packages the repository’s shared AL configuration. The root //:al label remains a compatibility alias. The Lua source files stay at the repository root so existing CLI configuration discovery and require("al_lib") imports retain their paths.

3.77 - Repository delivery

Guarded Git and pull-request delivery

repo_delivery implements the deterministic part of repository delivery. It invokes native Git and a selected forge CLI; it does not infer task ownership, choose validation commands, resolve conflicts, or judge review feedback.

Run delivery commands from this Git worktree’s repository root, which owns the root MODULE.bazel and tools/repo_delivery. This also applies when changed files belong to a nested Bazel module: its workspace does not own the delivery target. Use the same feature worktree, not another checkout. The baseline works with older installed runners. Detect the provider without printing a credential-bearing remote URL:

bazel_agent bazel run //tools/repo_delivery -- provider

The optional cached form is bazel_agent tool run repo_delivery -- .... Follow the bazel-agent skill’s one-time capability check before using it: reuse the known result for this runner binary, or inspect bazel_agent tool --help once. Unsupported tool means use the baseline without updating the host; an execution failure or delivery refusal still requires diagnosis. All examples below use the baseline.

The sanitized report distinguishes forge support from Git transport support. adapter_available reports whether the forge has an adapter; git_transport reports ssh, https, or mixed_or_unsupported; and delivery_transport_available is true only when both captured endpoints are canonical SSH endpoints. It never reports either endpoint.

For validation that invokes Bazel, use the cached entry point or generate a task-local launcher once from the repository root. Ordinary bazel run can retain the Bazel lock while its target runs; --script_path releases it before the generated launcher is executed. Refresh the launcher after changing the delivery tool. This requires no installed runner update:

bazel_agent bazel run --script_path=out/task/repo_delivery \
  //tools/repo_delivery

For the supported GitHub adapter, the normal workflow is:

bazel_agent bazel run //tools/repo_delivery -- inspect --base master
bazel_agent bazel run //tools/repo_delivery -- prepare \
  --base master \
  --message-file out/task/commit.md \
  --receipt-file out/task/prepare.json \
  --path path/to/task/file \
  --rewrite <inspect.local_head_oid> # omit when the range has no commit
# For an explicitly reviewed task-owned multi-commit range, use
# --consolidate <inspect.local_head_oid> instead of --rewrite.
out/task/repo_delivery validate \
  --receipt-file out/task/prepare.json --plan-file out/task/checks.json
out/task/repo_delivery continue \
  --receipt-file out/task/prepare.json --publish
out/task/repo_delivery continue \
  --receipt-file out/task/prepare.json

checks.json is an explicitly selected validation plan. Keep it mode 0600 in the same ignored out/<task>/ directory as the preparation receipt. For example, a change confined to the delivery Go package can use:

{
  "schema": "repo_delivery/validation_plan/v1",
  "checks": [
    {
      "workspace": ".",
      "kind": "test",
      "targets": [
        "//tools/repo_delivery/cmd/repo_delivery:go_test",
        "//:repo_quality_test"
      ],
      "timeout_seconds": 3600
    },
    {
      "workspace": ".",
      "kind": "lint",
      "targets": ["//tools/repo_delivery/cmd/repo_delivery:all"],
      "timeout_seconds": 3600
    }
  ],
  "gap_decisions": []
}

Allowed kinds are test, build, and lint (build with --config=lint). The plan accepts 1–32 sequential checks, 1–128 explicit local labels per check, and a 1–3600 second deadline per check. Package :all is supported outside the root package; recursive target patterns, arbitrary run targets, shell commands, and free-form flags are not. Workspace paths are relative to the Git worktree root and must name real Bazel workspace roots. Nested checks execute there; the required //:repo_quality_test check executes in .. The plan must lint every suggested non-root affected package and resolve each validation gap with exactly one { "path": "...", "reason": "..." } decision. The caller still selects sufficient consumer checks and verifies representative output.

validate runs aggregate git diff --check first, then the selected checks. It requires a fully clean worktree and ordinary index flags before and after checks. It records exact head/tree, preparation revision, plan bytes, inherited environment digest, check outcomes, and log digests beside the receipt, using mode 0600 files. Each output stream is capped at 96 KiB; truncation fails the check. The same receipt lock protects validation and continuation. Keep all these files trusted and unedited; they are consistency evidence, not security tokens. Tool binaries, ignored configuration, external services, and other inputs outside the recorded Git tree/environment still require the caller’s input-stability judgment before publication. No passing checks are reused automatically by a new validation run.

continue reports readiness without publishing. Only continue --publish uses the captured passing result to call the existing guarded publication and verification path; it never substitutes the current mutable HEAD as evidence. Changed candidate, receipt, plan, environment, incomplete results, altered logs, and dirty inputs refuse publication. A base rebase records revalidation_required and stops before pushing: rerun validate against the updated receipt, then explicitly continue. An interrupted or failed publication remains publication_attempted; further continuation only verifies its remote postcondition and never blindly repeats a push or metadata mutation. Diagnose an incomplete result before using the existing manual recovery API. A new validation run cannot reset an uncertain attempt for the same candidate.

prepare derives affected_bazel_labels from the prepared aggregate changed paths, selecting each nearest non-root Bazel package. It never infers //:all from a root-owned file. The reported bazel_selection_basis is nearest_non_root_package_without_dependency_analysis: this bounds discovery but does not establish downstream impact. Shared build inputs may need explicit consumer checks.

bazel_validation_gaps lists paths requiring a separate decision, with reasons root_package_requires_explicit_targets, ignored_by_root_workspace, nested_workspace, or no_bazel_package. For each gap, select appropriate targets or record why no target check applies. Validate nested or ignored workspaces through their owner, then return to the repository root for delivery. The suggested commands always include the root-workspace gate bazel_agent bazel test //:repo_quality_test; that gate does not establish semantic correctness for BUILD, MODULE, or configuration changes. Run semantic lint for the selected affected targets in addition to that mandatory gate.

To synchronize a prepared, task-owned, single-commit feature branch with an advanced base before prepare, use the guarded adapter workflow:

bazel_agent bazel run //tools/repo_delivery -- rebase --base master

The command refuses dirty trees, divergent remote feature tips, multi-commit or merge-containing ranges, and pull-request metadata changes. It fetches fresh refs, replays the commit in an isolated worktree, preserves signature requirements, pushes only with the captured remote feature lease, verifies base advancement, and reports the literal resulting head. Run required validations against that head before prepare and publish.

Remote rewrites use rewrite-authorize to write a typed, non-authorizing authorization receipt (old remote OID, new head OID, owner root, task paths, provider ownership), then prepare --rewrite-authorization <file> instead of raw --replace-remote handoff. Review replies accept --goal-ref, --delivery-ref, and --defect-id durable join references.

prepare refuses a divergent remote feature tip by default. Use --replace-remote <literal-inspect.remote_head_oid> only after the git-rebase-remote workflow has preserved that exact old tip and established that it is task-owned history the user authorized rewriting. Never infer the OID or use this escape hatch for shared, stacked, human-owned, unrelated, or ambiguous history. A mismatched, malformed, absent, or unnecessary authorization is refused. The final fresh snapshot and preparation receipt bind the same old remote OID for the later exact force-with-lease push.

prepare --consolidate <literal-inspect.local_head_oid> is the explicit ownership authorization for replacing a multi-commit feature range with one aggregate commit. It is not inferred from author names. The adapter still requires a merge-free linear chain, one author and committer identity across the range, the ownership disclaimer on its oldest commit, pull-request metadata matching the requested aggregate message, and the exact inspected head. It preserves any signature requirement found in the range and keeps the fetched remote feature tip as the publication lease. --consolidate and --rewrite are mutually exclusive.

When a clean replay onto an advanced base makes an expected aggregate path disappear from the resulting diff, the adapter accepts that shrink only when the prior candidate and the new base have byte-identical Git tree entries at that path. A new path, a non-identical disappearance, or an entirely empty aggregate remains a refusal. The derived receipt records the reduced exact aggregate path set.

The manual publish --receipt-file <path> --validated-head <literal-head_oid> API remains available for validations outside the structured plan and diagnosed recovery. Never populate that flag by resolving current HEAD: carry the literal candidate that the checks covered. A preparation receipt alone does not establish validation. The structured continuation path supplies that literal value from its recorded passing results instead.

For message-only amendments, deliver --message-file <path> --receipt-file <path> --owner-root <root> --task-path <path> combines inspection, any needed rewrite authorization, and preparation. It stops before publication with a nonzero exit and a revalidation_required report containing the exact head, tree, receipt, affected labels, and suggested checks. Establish validation for that candidate using validate, then use continue --publish, or use the manual publish API and verify. Do not repeat deliver to continue, because that prepares another candidate.

Version 1 delivery accepts only SCP-style or ssh:// Git fetch and push endpoints. The gh CLI is still used for the GitHub forge API, but the tool does not import mutable global credential-helper configuration installed by gh auth setup-git. An HTTPS Git remote is therefore rejected before inspect, preparation, or publication performs network access. Configure an SSH remote explicitly before using delivery; the tool will not rewrite the repository’s remote configuration for you.

prepare writes a strict versioned receipt under an ignored out/<task>/ directory. The receipt binds the prepared head and tree to the exact worktree and Git directories, fetch and push endpoint digests, sanitized repository identity, forge adapter, base and head refs, fetched base, expected remote feature ref, expected pull-request identity or absence, and immutable aggregate path scope. The file contains no remote URL, must remain untracked, and is installed with mode 0600 by atomic rename. It is a consistency record, not an unforgeable authorization token.

The adjacent receipt lock serializes receipt transitions and reads performed by cooperating repo_delivery processes. Keep the ignored receipt path trusted and do not edit, replace, copy over, or otherwise write it while prepare, publish, or receipt-bound verify is running. Stable byte and revision checks detect changes visible before their checks, but operating systems do not provide a portable atomic pathname-content compare-and-swap. A same-user process that ignores the lock can race the final comparison and rename; the tool does not claim to exclude that writer. A persistent exclusive revision-claim sidecar would have the same trust boundary, while a crash before installation could strand the receipt without a safe automatic cleanup decision, so it is not used.

Use repeated --path flags for fully task-owned paths, or pre-stage only task-owned hunks and use --use-index. Both modes bind the complete existing feature diff, not merely the paths newly staged by that invocation. --message-only --rewrite <exact-oid> preserves the tree but changes the commit OID. Consolidation also changes the commit OID and parent structure. Every prepare, consolidation, or message-only amendment therefore requires a validation decision bound to its returned exact head. Run required checks after preparation by default. For a tree-preserving amendment, prior passing evidence may be reused only after recording its exact prior candidate, the matching tree OID, the new OID, and unchanged inputs relevant to each check. Those inputs include commands, tools, configuration, and environment. Rerun checks affected by commit identity, history, or stamping, and any check whose input stability is unknown. The caller owns and records this applicability judgment; the receipt neither proves validation nor authorizes reuse. When an authorized remote replacement is pending, rewrite evidence accepts an existing pull request only if its metadata matches the exact projectable local or fetched-remote commit projection. A legacy remote tail that lacks an aggregate disclaimer cannot block a matching local aggregate, and unrelated pull-request text remains a refusal.

Publish and receipt-bound verify require a clean index and reject staged, unstaged, or untracked changes in the prepared task scope. They preserve unrelated unstaged and untracked files when no rebase is needed. A required rebase demands a fully clean worktree and index. Run validation from a clean checkout at the literal head_oid whenever unrelated dirty files could affect the check; the tool cannot infer a check’s input set.

If the base advances after preparation, publish rebases the exact captured commit in an isolated ignored worktree. It then exits nonzero before pushing and emits a revalidation_required JSON report containing the new exact head, tree, and derived receipt. Validate that returned head directly, then retry publish with the same receipt file and the new literal OID. Do not run prepare again unless content or the commit message must change. A receipt also supports a guarded retry when the remote already equals its prepared head but pull-request creation or metadata synchronization stopped partway through. Replacement pull-request identities and any state other than the exact prior or desired projection are refused. Multi-commit consolidation likewise requires an existing pull request to equal the requested aggregate message’s projection, so consolidation cannot silently replace independently edited pull-request text.

The tool creates commits with Git plumbing and pushes one exact ref with hooks disabled. It rejects shallow, promisor, or grafted history and ignores replacement objects. Each network operation runs in a fresh private, config-free bare Git directory bound to the captured SSH endpoint and the repository’s canonical object database. It does not load mutable main-repo local/worktree URL rewriting, proxy, TLS, SSH-command, or remote configuration. Normal DNS resolution and SSH host-key verification still apply; the tool does not claim to pin an IP address or server key. Ordinary local Git operations still intentionally use repository identity and signing configuration. Fetches use isolated temporary refs without pruning, then install exact private refs locally; pushes use an exact force-with-lease. Repository-required hook checks remain the caller’s responsibility and must complete before recording the validated OID.

The feature-ref lease and base-ref checks are separate because Git forges do not offer a cross-ref compare-and-swap. If the base advances in the narrow push window, the feature ref may be visible briefly before the tool detects the race and attempts an exact guarded rollback. Coordinate consumers that react immediately to branch-update webhooks.

Start with a bounded structured inventory:

bazel_agent bazel run //tools/repo_delivery -- review inspect

Carry values from the latest inspection literally. All mutations require the pull-request node ID, expected head, and pull-request expectation digest. A top-level reply also requires the reported last-comment sentinel and top-level inventory digest:

bazel_agent bazel run //tools/repo_delivery -- review comment \
  --pull-request-id <pull_request.id> \
  --expected-head <pull_request.head_ref_oid> \
  --expected-pull-request-digest <pull_request_expectation_digest> \
  --expected-last-top-level-comment \
    <expected_last_top_level_comment> \
  --expected-top-level-comments-digest \
    <expected_top_level_comments_digest> \
  --body-file out/task/comment.md

Thread replies and resolutions additionally bind the thread, its last comment, and its complete expectation digest:

bazel_agent bazel run //tools/repo_delivery -- review reply \
  --pull-request-id <pull_request.id> \
  --expected-head <pull_request.head_ref_oid> \
  --expected-pull-request-digest <pull_request_expectation_digest> \
  --thread-id <review_threads[index].id> \
  --expected-last-comment-id <review_threads[index].comments[-1].id> \
  --expected-thread-digest <review_threads[index].expectation_digest> \
  --body-file out/task/reply.md \
  --reply-receipt-file out/task/reply.json

bazel_agent bazel run //tools/repo_delivery -- review resolve \
  --pull-request-id <pull_request.id> \
  --expected-head <pull_request.head_ref_oid> \
  --expected-pull-request-digest <pull_request_expectation_digest> \
  --thread-id <review_threads[index].id> \
  --expected-last-comment-id <review_threads[index].comments[-1].id> \
  --expected-thread-digest <review_threads[index].expectation_digest> \
  --reply-receipt-file out/task/reply.json

bazel_agent bazel run //tools/repo_delivery -- review request \
  --pull-request-id <pull_request.id> \
  --expected-head <pull_request.head_ref_oid> \
  --expected-pull-request-digest <pull_request_expectation_digest> \
  --reviewer <login>

Comment and reply bodies must be ignored files under out/<task>/; the tool adds the exact comment disclaimer. Resolution requires the strict reply receipt written by review reply, and the receipt must still match the exact pull request, head, thread, reply, body, and complete bounded review inventory projection. The parent pull-request UpdatedAt is a nondecreasing floor, rather than an exact value, because reply side effects can advance it asynchronously; every review, top-level comment, thread and thread comment, and review request remains bound. Reinspect after every mutation and use the newly reported IDs and digests for the next one. The one-use reply authority expires no more than five minutes after issuance. Resolution verifies the authority window and atomically consumes the receipt before contacting the provider. If a provider read fails before any resolution mutation is attempted, the tool can restore the original unexpired receipt without replacing another file or extending its authority window. Only an explicit restoration report permits retry with that receipt; no additional public reply is needed for that read failure. Expiration, semantic or full-inventory mismatch, mutation failure, and an unknown mutation outcome still consume authority. Never recreate the receipt yourself. Reinspect the remote state and, if resolution remains appropriate, leave a fresh reasoned reply to obtain new one-use authority.

GitHub provides neither compare-and-swap resolution nor a documented monotonic review-thread epoch. A human resolve followed by unresolve can therefore be unobservable if it restores identical thread and pull-request state inside the five-minute authority window. The exact-state checks, short expiration, and one-use consumption narrow that risk; they do not prove that such an ABA or a change to provider metadata omitted from the bounded projection did not occur. Do not resolve a thread that may be concurrently moderated.

GitHub does not expose atomic compare-and-swap mutations for pull-request metadata, comments, replies, resolutions, or review requests. The adapter checks exact expectations before each mutation and verifies the complete result afterward, but a concurrent human change can still occur inside that narrow provider-side window. Do not mutate an actively coedited pull request. Post-mutation inspection failures are reported as outcome unknown; reinspect instead of retrying blindly.

GitHub is supported through the gh CLI. Forge behavior is selected behind a Go interface and uses argument-vector subprocess calls, so another structured CLI adapter can be added without changing delivery policy. --forge auto selects GitHub for github.com; use --forge github --forge-cli <gh-path> to select an explicit executable. Unknown or unsupported forges fail before any commit rewrite or push.

Version 1 is limited to same-repository pull requests. It cannot reliably discover or map an upstream pull request whose head lives in a fork. Treat same-repository topology as a caller-enforced precondition: do not use the delivery or review commands for a fork-based or otherwise cross-repository pull request, and stop when remote or pull-request ownership is uncertain. The adapter fails closed when it observes an unsupported or inconsistent topology, but that refusal is not a substitute for this caller check.

The read-only provider command recognizes known Forgejo hosts, but there is currently no Forgejo delivery adapter. Use the repository’s documented Forgejo compatibility workflow instead of pretending GitHub operations are portable.

3.78 - Repository quality

Whole-index formatting, linting and validation coordinator

This package uses upstream aspect_rules_lint formatting and linting rules to discover Git-tracked files and inspect declared source targets with established tools acquired by Bazel. It does not implement a formatter or linter and does not download tools at runtime. Thin workspace adapters extend the upstream language list with the official Go SDK for module and workspace manifests, StyLua and Selene for Lua, and the existing Prettier XML plugin for Qt .ui and .qrc files.

Format all safe, hand-maintained files:

bazel_agent bazel run //:format

Run the non-mutating repository check:

bazel_agent bazel test //:repo_quality_test

The suite also parses root BUILD.bazel and rejects load() statements to keep unrelated tool dependencies out of root package loading. Run this check alone with bazel_agent bazel test //tools/repo_quality/test/root_build:root_build_test.

Run semantic source linters over declared targets:

bazel_agent bazel build --config=lint //...

The CSS formatter bucket includes CSS, Less and SCSS. The JavaScript bucket includes JavaScript, JSON, JSON-with-comments, JSON5, TypeScript, TSX and Vue. Go source uses gofumpt; go.mod and go.work use the official Go SDK. Lua checks cover every tracked file not excluded by Git attributes, using StyLua for canonical formatting and Selene for correctness diagnostics.

Explicit templates (.j2, .tmpl, .tpl, and the Hugo layout tree), generic application configuration, and non-Terraform HCL are deliberately excluded from general formatting. Ordinary Markdown, YAML, HTML and other files remain covered even when their contents include template expressions. Generated, vendored, lock, binary, diagram and exact-content files likewise retain their owning regeneration, validation or integrity workflow.

The integration test intentionally uses the upstream rule’s no_sandbox mode so it can inspect files that are tracked by Git but not declared in BUILD files. This is a local-checkout guarantee, like the root Buildifier test; tool acquisition remains hermetic and pinned through Bazel.

3.79 - Resolved toolchain

Helper rule to create a resolved toolchain

3.79.1 - Bzl

Bazel code

3.79.1.1 - al_resolved_toolchain

al_resolved_toolchain

load("@com_alwaldend_src//tools/resolved_toolchain/main/bzl:al_resolved_toolchain.bzl", "al_resolved_toolchain")

al_resolved_toolchain(toolchain_label, **kwargs)

Create a resolved toolchain

PARAMETERS

Name Description Default Value
toolchain_label

-

none
kwargs rule kwargs none

RETURNS

Resolved toolchain rule

3.80 - Rfc

Rfc tools

3.80.1 - Bzl

Bazel code

3.80.1.1 - al_rfc_extension

al_rfc_extension

al_rfc_extension = use_extension("@com_alwaldend_src//tools/rfc/main/bzl:al_rfc_extension.bzl", "al_rfc_extension")
al_rfc_extension.download(name, integrity, rfcs)

Rfc extension

TAG CLASSES

Attributes

Name Description Type Mandatory Default
name Name Name required
integrity Rfc integrity Dictionary: String -> String optional {}
rfcs Rfcs List of strings optional []

3.80.1.2 - al_rfc_repo

al_rfc_repo

load("@com_alwaldend_src//tools/rfc/main/bzl:al_rfc_repo.bzl", "al_rfc_repo")

al_rfc_repo(name, integrity, repo_mapping, rfcs, url)

Rfc repository

ATTRIBUTES

Name Description Type Mandatory Default
name A unique name for this repository. Name required
integrity Rfc integrity Dictionary: String -> String optional {}
repo_mapping In WORKSPACE context only: a dictionary from local repository name to global repository name. This allows controls over workspace dependency resolution for dependencies of this repository.

For example, an entry "@foo": "@bar" declares that, for any time this repository depends on @foo (such as a dependency on @foo//some:target, it should actually resolve that dependency within globally-declared @bar (@bar//some:target).

This attribute is not supported in MODULE.bazel context (when invoking a repository rule inside a module extension’s implementation function).
Dictionary: String -> String optional
rfcs Rfcs List of strings optional []
url Url format String optional "https://www.rfc-editor.org/rfc/{postfix}"

3.81 - Root Bazel module

Generate the root module’s owning include list

MODULE.bazel is generated directly from include.MODULE.bazel files:

bazel run //tools/bazel_module:update

Dependency declarations and pins stay in their owning include files. The small root module(...) header lives in the Go generator. Discovery uses the existing //tools/git host Git wrapper to include tracked and untracked files while respecting Git ignore rules. Deleted files, symlinks, .bazelignore directories, and standalone workspaces beneath MODULE.bazel, WORKSPACE, or WORKSPACE.bazel boundaries are excluded.

Includes are ordered by owning directory, with third_party, tools, then projects before other trees. This keeps the existing precedence between those trees, including toolchain registrations. A parent directory precedes its children. Keep any order-sensitive declarations together in one owning include.

//tools/bazel_module/cmd/update:freshness_test checks the current checkout and is included in //:repo_quality_test. It intentionally disables sandboxing and result caching to detect new or removed files outside declared Bazel inputs. The generator’s unit tests remain sandboxed and cacheable.

Before deleting or moving an existing include, retain a launcher so regeneration does not need to load the old module after its include disappears:

mkdir -p out/bazel_module
bazel run --script_path=out/bazel_module/update //tools/bazel_module:update
# Delete or move the include, then regenerate:
out/bazel_module/update

3.82 - Run tool

Run tool rules

3.82.1 - Bzl

Bazel code

3.82.1.1 - al_run_tool

al_run_tool

load("@com_alwaldend_src//tools/run_tool/main/bzl:al_run_tool.bzl", "al_run_tool")

al_run_tool(name, tool, executable, test, **kwargs)

Generate either native_test, native_binary, or run_binary target

PARAMETERS

Name Description Default Value
name Target name (required) none
tool Tool label to run (required) none
executable If True, generate native_binary False
test If True, generate native_test False
kwargs kwargs for rules none

3.83 - Selene

Hermetic Selene Lua linter

Selene provides correctness-oriented linting for the repository’s hand-maintained Lua files. The repository standard-library description permits the intentional al configuration DSL and Neovim’s vim global while keeping Selene’s ordinary Lua diagnostics enabled.

3.84 - Sh

Shell rules

3.84.1 - Bzl

Bazel code

3.84.1.1 - al_sh_library

al_sh_library

load("@com_alwaldend_src//tools/sh/main/bzl:al_sh_library.bzl", "al_sh_library")

al_sh_library(name, shfmt_src, editorconfig_src, shellcheck_src, run_args_src, visibility,
              test_data, **sh_kwargs)

Create targets for a shell library

Targets:

  • ${name}.shfmt_fix: executable to run shfmt
  • ${name}.shfmt_test: test whether the script is formatted
  • ${name}.shellcheck_test: shellcheck test

PARAMETERS

Name Description Default Value
name target name none
shfmt_src

-

"//tools/shfmt"
editorconfig_src

-

"//tools/shfmt:editorconfig"
shellcheck_src

-

"//tools/shellcheck"
run_args_src

-

"//tools/sh/main/sh:run_args_lib"
visibility

-

["//:__subpackages__"]
test_data

-

[]
sh_kwargs kwargs for sh targets none

3.84.1.2 - al_write_script

al_write_script

load("@com_alwaldend_src//tools/sh/main/bzl:al_write_script.bzl", "al_write_script")

al_write_script(name, out, content, make_vars, set_flags, shebang)

Write a script and make it executable

ATTRIBUTES

Name Description Type Mandatory Default
name A unique name for this target. Name required
out Output file Label; nonconfigurable required
content Script content String required
make_vars Additional make vars Dictionary: String -> String optional {}
set_flags Flags to pass to set List of strings optional ["-eu"]
shebang Sheband to use String optional "#!/usr/bin/env sh"

3.85 - Shellcheck

Shellcheck wrapper

3.86 - Shfmt

Shfmt

3.87 - Sops

Sops

3.88 - Stylua

Stylua wrapper

3.89 - Taplo

Taplo

3.90 - Terraform

Terraform
  • Terraform binaries use explicit operation suffixes. In particular, apply is <name>.apply; the unnamed <name> mutating alias is intentionally absent.
  • Root //:tf.* commands delegate to //tools/terraform/cmd/workspace:tf.*. They retain the repository root as Terraform’s working directory. Other packages default to their own directory; terraform_binary accepts an explicit chdir for relocated command wrappers.

3.90.1 - Runner

Golang code for the terraform runner

3.91 - Toml

Toml rules

3.91.1 - Bzl

Bazel code

3.91.1.1 - al_toml_data

al_toml_data

load("@com_alwaldend_src//tools/toml/main/bzl:al_toml_data.bzl", "al_toml_data")

al_toml_data(name, deps, srcs, tomlv)

ATTRIBUTES

Name Description Type Mandatory Default
name A unique name for this target. Name required
deps Toml data targets List of labels optional []
srcs Toml files List of labels optional []
tomlv Tomlv target to use for validation Label optional "@com_alwaldend_src//tools/tomlv"

3.91.1.2 - al_toml_info

load("@com_alwaldend_src//tools/toml/main/bzl:al_toml_info.bzl", "AlTomlInfo")

AlTomlInfo(srcs, deps)

Provide toml data info

FIELDS

Name Description
srcs Toml files
deps Toml data targets

3.91.1.3 - al_toml_validate

al_toml_validate

load("@com_alwaldend_src//tools/toml/main/bzl:al_toml_validate.bzl", "al_toml_validate")

al_toml_validate()

Aspect adding linters for toml files

ASPECT ATTRIBUTES

Name Type
deps String

ATTRIBUTES

3.92 - Tomlv

Tomlv

3.93 - Traefik

Traefik

3.94 - Transitive sources

Provider and a rule to extract transitive sources

3.94.1 - Bzl

Bazel code

3.94.1.1 - al_transitive_sources

load("@com_alwaldend_src//tools/transitive_sources/main/bzl:al_transitive_sources.bzl", "AlTransitiveSources")

AlTransitiveSources(transitive_sources)

Provide transitive sources

FIELDS

Name Description
transitive_sources -

al_transitive_sources

load("@com_alwaldend_src//tools/transitive_sources/main/bzl:al_transitive_sources.bzl", "al_transitive_sources")

al_transitive_sources(srcs, deps)

Obtain the source files for a target and its transitive dependencies.

PARAMETERS

Name Description Default Value
srcs a list of source files none
deps a list of targets that are direct dependencies none

RETURNS

a collection of the transitive sources

3.95 - Trufflehog

Trufflehog

The normal //tools/trufflehog:repo_test scans the history reachable from the checked-out HEAD and skips unrelated local refs. Run the manual //tools/trufflehog:repo_all_refs_test target explicitly when an audit must include every local Git ref, such as T3 checkpoint refs from other worktrees.

3.96 - Twine

Twine

3.97 - Txt

Text rules

3.97.1 - Bzl

Bazel code

3.97.1.1 - al_combine_files

al_combine_files

load("@com_alwaldend_src//tools/txt/main/bzl:al_combine_files.bzl", "al_combine_files")

al_combine_files(name, srcs, **kwargs)

Create a genrule combining several files into one

PARAMETERS

Name Description Default Value
name genrule target none
srcs list of labels to combine none
kwargs other genrule kwargs none

3.97.1.2 - al_txt_data

al_txt_data

load("@com_alwaldend_src//tools/txt/main/bzl:al_txt_data.bzl", "al_txt_data")

al_txt_data(name, srcs, **kwargs)

Text data

PARAMETERS

Name Description Default Value
name target name none
srcs sources none
kwargs filegroup kwargs none

3.98 - Vault

Vault

The root //:vault and //:vault.* labels delegate to wrappers in //tools/vault/cmd/workspace, using //tools/al:config. //tools/vault:vault is the standalone CLI; the wrappers add the existing AL environment injection.

3.98.1 - Backup

Run backup for Vault

3.98.2 - Forgejo login

Get a short-lived Forgejo token using OIDC

The plugin registers token removal before issuance, using a unique token name. Startup failure and normal shutdown attempt removal through the authenticated Forgejo browser session, including when creation did not return a usable token. Cleanup parses the complete applications settings page and verifies token absence after deletion. It then logs out the invocation’s browser session and verifies that the retained original cookie no longer accesses authenticated settings. Cleanup failures are reported.

The parser follows the Forgejo 15.0.3 applications template: all tokens appear on one page, each in a flex-item row with a title and a matching delete button. It requires the applications page marker and new-token link before accepting an empty list. Login pages, invalid token IDs, duplicates, and responses larger than 4 MiB fail closed. A changed upstream template may require a parser update. Network requests have a ten-second timeout and honor cancellation. Forced process termination or an unavailable Forgejo server can prevent cleanup; Forgejo tokens do not acquire an expiry merely because this plugin created them.

3.98.2.1 - api

Proto docs for api.proto
load("@rules_java//java:defs.bzl", "java_library")

java_library(
    name = "name",
    deps = [
        "@com_alwaldend_src//tools/vault/forgejo_login:api_java_library",
    ],
)
load("@rules_go//go:def.bzl", "go_library")

go_library(
    name = "name",
    deps = [
        "@com_alwaldend_src//tools/vault/forgejo_login:forgejo_login",
    ],
)
syntax = "proto3";

package com.alwaldend.src.tools.vault.forgejo_login.forgejo_login_proto;

option go_package = "git.alwaldend.com/alwaldend/src/tools/vault/forgejo_login/forgejo_login_proto";

message Config {
  string forgejo_url = 1;
  string forgejo_oauth_name = 2;
  string vault_conn = 3;
  string vault_auth = 4;
}

3.98.3 - Gen client cert

Generate a client certificate

3.98.4 - Gen root token

Generate a root token for Vault

3.98.5 - Harbor login

Create a harbor session using OIDC

The plugin destroys its Harbor session on normal shutdown and checks that the original session ID is rejected by the current-user API. Cleanup uses Harbor’s /c/oidc/logout endpoint (available in newer Harbor releases) and does not follow the optional identity-provider logout redirect. Unsupported endpoints, network failures, or sessions that remain valid are reported as cleanup errors. Session expiry remains server-controlled; forced termination cannot guarantee logout.

The session destruction behavior is defined by Harbor’s OIDC controller. Vault tokens created by the invocation are revoked after session cleanup.

3.98.5.1 - api

Proto docs for api.proto
load("@rules_java//java:defs.bzl", "java_library")

java_library(
    name = "name",
    deps = [
        "@com_alwaldend_src//tools/vault/harbor_login:api_java_library",
    ],
)
load("@rules_go//go:def.bzl", "go_library")

go_library(
    name = "name",
    deps = [
        "@com_alwaldend_src//tools/vault/harbor_login:harbor_login",
    ],
)
syntax = "proto3";

package com.alwaldend.src.tools.vault.harbor_login.harbor_login_proto;

option go_package = "git.alwaldend.com/alwaldend/src/tools/vault/harbor_login/harbor_login_proto";

message Config {
  string harbor_url = 1;
  string vault_conn = 2;
  string vault_auth = 3;
}

3.98.6 - Injector

Secret injector

Shutdown first drains plugin requests, then stops and waits for resource processes, revokes invocation-owned Vault credentials, and deletes temporary files and SSH key directories. Failed cleanup is reported. Registration after shutdown is rejected; a fetcher removes any unregistered temporary material. Temporary files use mode 0600 and directories use 0700. Deletion is filesystem unlinking, not secure erasure, and cannot run after SIGKILL or host failure.

no_auth explicitly sets the injected VAULT_TOKEN to an empty value so an inherited token is overridden. This does not remove the user’s token-helper file; commands that independently consult that helper may still authenticate. Template errors and OIDC status errors omit input and response contents. OIDC requests honor cancellation and do not follow redirects.

3.98.6.1 - api

Proto docs for api.proto
load("@rules_java//java:defs.bzl", "java_library")

java_library(
    name = "name",
    deps = [
        "@com_alwaldend_src//tools/vault/injector:api_java_library",
    ],
)
load("@rules_go//go:def.bzl", "go_library")

go_library(
    name = "name",
    deps = [
        "@com_alwaldend_src//tools/vault/injector:injector",
    ],
)
syntax = "proto3";

package com.alwaldend.src.tools.vault.injector.injector_proto;

option go_package = "git.alwaldend.com/alwaldend/src/tools/vault/injector/injector_proto";

message File {
  string value = 1;
  string from_file = 2;
  map<string, string> extra = 3;
}

message Env {
  string value = 1;
}

message Kv {
  // Secret path
  string path = 1;
  // Secret mount
  string mount = 2;
}

message Op {
  string method = 1;
  string path = 4;
  map<string, string> data = 5;
}

message VaultSsh {
  string backend = 1;
  int64 ttl = 2;
}

message Process {
  string name = 1;
  repeated string args = 2;
}

message Oidc {
  string name = 1;
  string scope = 2;
  string client_id = 3;
  string redirect_uri = 4;
}

message VaultEnv {
  // Vault connection
  string conn = 1;
  // Vault auth
  string auth = 2;
}

message Resource {
  // Resource name
  string name = 1;
  // Vault connection for the resource
  string vault_conn = 2;
  // Vault auth for the resource
  string vault_auth = 3;
  // Dependencies
  repeated string deps = 8;

  oneof res {
    // Vault operation
    Op op = 4;
    // Vault KV secret
    Kv kv = 5;
    // Environment variable
    Env env = 6;
    // File
    File file = 7;
    // Vault environment variables
    VaultEnv vault_env = 9;
    // Ssh key signed by Vautl
    VaultSsh vault_ssh = 10;
    // Run a cmd
    Process process = 11;
    // Create an OIDC token
    Oidc oidc = 12;
  }
}

message Config {
  // Resources
  repeated Resource res = 1;
}

3.98.7 - Login

Login to vault using the yubikey
bazel run //tools/vault/login

3.98.8 - PVE login

Get a login ticket using OIDC

The plugin requests an API token with a one-hour expiry and deletes that token on shutdown using the retained login ticket and CSRF token. The token name is registered for cleanup before creation, so cleanup is attempted even when a creation response is lost or malformed. Failures to delete are reported; expiry is the fallback when shutdown cannot complete. Pre-existing credentials are not revoked. Vault tokens created by the invocation are revoked after token cleanup.

Token deletion uses the Proxmox user token API.

3.98.8.1 - api

Proto docs for api.proto
load("@rules_java//java:defs.bzl", "java_library")

java_library(
    name = "name",
    deps = [
        "@com_alwaldend_src//tools/vault/pve_login:api_java_library",
    ],
)
load("@rules_go//go:def.bzl", "go_library")

go_library(
    name = "name",
    deps = [
        "@com_alwaldend_src//tools/vault/pve_login:pve_login",
    ],
)
syntax = "proto3";

package com.alwaldend.src.tools.vault.pve_login.pve_login_proto;

option go_package = "git.alwaldend.com/alwaldend/src/tools/vault/pve_login/pve_login_proto";

message Config {
  string pve_base_url = 1;
  string pve_redirect_url = 2;
  string pve_realm = 3;
  string vault_conn = 4;
  string vault_auth = 5;
}

3.98.9 - Tf backend

Http terraform backend backed by Vault

The plugin tracks each running backend for shutdown, including backends created before a later call fails. Shutdown drains HTTP requests before revoking the backend’s invocation-owned Vault credentials. If the shutdown deadline expires, connections are forcibly closed and the timeout is reported. Normal HTTP server closure is not an error. Vault requests use their incoming request context.

3.98.9.1 - api

Proto docs for api.proto
load("@rules_java//java:defs.bzl", "java_library")

java_library(
    name = "name",
    deps = [
        "@com_alwaldend_src//tools/vault/tf_backend:api_java_library",
    ],
)
load("@rules_go//go:def.bzl", "go_library")

go_library(
    name = "name",
    deps = [
        "@com_alwaldend_src//tools/vault/tf_backend:tf_backend",
    ],
)
syntax = "proto3";

package com.alwaldend.src.tools.vault.tf_backend.tf_backend_proto;

option go_package = "git.alwaldend.com/alwaldend/src/tools/vault/tf_backend/tf_backend_proto";

message Config {
  string vault_conn = 1;
  string vault_auth = 2;
  string vault_secret = 3;
  string vault_secret_mount = 4;
}

3.98.10 - Unseal

Unseal the vault

3.99 - Versioning

Global repository and project versioning

versioning owns versions for this repository and its first-party projects. It deliberately does not manage versions of third-party dependencies.

The repository uses SemVer-compatible calendar versions:

  • ordinary development: 0.0.0-dev;
  • nightly trunk tag: vYYYY.W.0-nightly.YYYYMMDD;
  • weekly release branch: releases/YYYY.W;
  • release tag: vYYYY.W.PATCH.

YYYY and W are the ISO week-year and week. The week is not zero-padded, because SemVer forbids leading zeroes in numeric identifiers. Patch zero is the release branch point. Every first-parent commit after that point advances the calculated patch number by one.

Calculated versions and Bazel status omit the Git tag’s leading v.

A commit may carry one nightly tag and one release tag when a nightly is promoted. Branch context selects the channel automatically. On detached HEAD, pass --channel release or --channel nightly for that exact co-tagged commit. For an untagged detached commit from a release branch, pass --release YYYY.W so the tool can calculate its patch from the correct branch-point tag.

Build and inspect the tool with:

bazel_agent bazel run //tools/versioning/cmd/versioning -- show

For a stamped build, use the bootstrap entry point. It generates a source-current Bazel launcher under out/versioning/, then the Go tool runs Bazel with itself as workspace status:

tools/versioning/cmd/versioning/versioning.sh bazel -- \
  build --config=release //path/to:artifact

Read $versioning for the guarded nightly, release, and Bazel stamping workflows.

versioning also owns a typed, reviewed release-ref plan and a provider-neutral guarded publisher for the generated nightly and release tags. It never merges versioning, delivery, or goal authority; the tool retains its own release-refs authority.

Generate a deterministic plan from the resolved version state:

bazel_agent bazel run //tools/versioning/cmd/versioning -- release-plan \
  --plan out/delivery/release-plan.json

The plan records the exact version, channel, commit, tree state, target refs (tag-only for nightly, branch-plus-tag for release), the expected remote preconditions, and whether atomic multi-ref publication is required. It is reviewed before consumption and is not an authorization.

Publish the reviewed plan only after explicit release scope:

bazel_agent bazel run //tools/versioning/cmd/versioning -- release-publish \
  --plan out/delivery/release-plan.json \
  --receipt out/delivery/release-ref-receipt.json

The guarded publisher fetches expected remote state, acquires a distinct release-refs lease, publishes the refs (atomically when required and supported), and verifies the remote before emitting a ReleaseRefReceipt. An existing immutable release tag never moves; a remote that cannot guarantee atomic multi-ref publication is an explicit refusal, never a generic success.

3.100 - Vial

Bazel rules for Vial

3.100.1 - Bzl

Bazel code

3.100.1.1 - al_vial_configs

al_vial_configs

load("@com_alwaldend_src//tools/vial/main/bzl:al_vial_configs.bzl", "al_vial_configs")

al_vial_configs(name, srcs, visibility, **kwargs)

Generate vial config targets

PARAMETERS

Name Description Default Value
name generated docs archive name none
srcs vial config none
visibility visibility None
kwargs kwargs for template_files none

3.101 - Word lists

Word lists

3.102 - Workspace status

Workspace status script

4 - Misc

Miscellaneous pages

4.1 - Android

Android

Android has some built-in tests for the display and other components in Settings -> System -> Device diagnostics

4.2 - Bazel

  • Hermetic builds
  • Dependency graph
  • Local build and test cache
  • Remote cache
  • Remote execution
  • Unified API for builds, tasks, and tests
  • Additional layer of abstraction and complexity
  • Weird edge cases and occasional bugs
  • Lack of support, documentation, and information on the internet
  • The majority of advantages are irrelevant for the majority of codebases
  • %workspace%: Workspace directory

https://bazel.build/run/bazelrc

If you changed a local registry module, but bazel still uses the old version, restart bazel: bazel shutdown

https://github.com/bazelbuild/bazel/issues/20477#issuecomment-1851057077

Bazel checks ownership of the output root at startup, so it will fail with mkdir('/path/to/dir'): (error: 13): Permission denied if the current user does not own the directory.

Example:

$ bazel --client_debug
...
[FATAL 15:19:33.457 src/main/cpp/blaze_util_posix.cc:499] mkdir('/path/to/dir'): (error: 13): Permission denied

Traceback:

One of possible errors:

FATAL: aspect_rules_js[js_binary]: RUNFILES environment variable is not set
bazel run //tools/postcss
bazel run //tools/pnpm -- --dir "${PWD}/tools" install --ignore-scripts

4.3 - Books

Books
Cover of Sky Pride Title
Quality Good
Authors Warby Picus
Reading Dropped, B6C25
Links royalroad , royalroad (author)
Title (少女終末旅行)
Quality Good
Authors Tsukumizu (つくみず)
Reading Finished, V6C43.6
Links wikipedia , wikipedia (author)
Cover of Surviving as a Talent in the Primordial Saint Sect Title (苟在初圣魔门当人材) (Lying Low as the First Saint Demonic Sect’s ‘Top Talent’)
Quality Decent
Authors Crane by the Moonlit Pond (鹤守月满池)
Reading Finished, C1537 (C1441)
Links novelupdates , novelupdates (author)
Cover of How Can You Cultivate Immortality Without Money? Title (没钱修什么仙?) (No Money to Cultivate Immortality?)
Quality Decent
Authors 熊狼狗
Reading Dropped, C827 (C815)
Links novelupdates , novelupdates (author)
Cover of Corpse Retriever Title (捞尸人)
Quality Decent?
Authors 纯洁滴小龙
Reading Dropped, C26
Links novelupdates , novelupdates (author)
Cover of The Mirror Legacy Title (玄鉴仙族)
Quality Decent?
Authors 季越人
Reading Dropped, C10
Links novelupdates , novelupdates (author)
Cover of Book Of The Dead Title
Quality Decent
Authors RinoZ
Reading Dropped, B6C8
Links royalroad , royalroad (author)
Cover of Hell Difficulty Tutorial Title
Quality Decent
Authors Cerim
Reading Dropped, C841
Links royalroad
Cover of Reforged from Ruin Title
Quality Decent
Authors Silv3rtongue
Reading Dropped, C390
Links royalroad , royalroad (author)
Cover of Re:Cursed Title
Quality Decent
Authors Joroboros
Reading Dropped, C176
Links royalroad , royalroad (author)
Cover of The Legend of William Oh Title
Quality Decent
Authors Macronomicon
Reading Dropped, C264
Links royalroad , royalroad (author)
Cover of Path of the Deathless Title
Quality Decent
Authors
Reading Dropped, C333
Links royalroad
Cover of Throne of Time Title
Quality Ok, bland
Authors Cognosticon
Reading Dropped, C23
Links royalroad , royalroad (author)
Cover of [Grave Robber] Title
Quality Ok, mediorce
Authors DisheveledVagabond
Reading Dropped, C6
Links royalroad , royalroad (author)
Cover of To Walk The Red Path Title
Quality Ok, bland
Authors Jman8763 C. Ashen
Reading Dropped, F6P2C10
Links royalroad , royalroad (author)
Cover of Shadow Clone Sorcery Title
Quality Ok, bland
Authors JPwrites
Reading Dropped, C110
Links royalroad , royalroad (author)
Cover of DIE TRYING Title
Quality Ok, bland
Authors Mark Arrows
Reading Dropped, C47
Links royalroad , royalroad (author)
Cover of No More Heroes Title
Quality Ok, boring
Authors LokiTheQuick
Reading Dropped, C22
Links royalroad , royalroad (author)
Cover of Explorer of Edregon Title
Quality Ok, bland
Authors Wizardly Dude
Reading Dropped, C20
Links royalroad , royalroad (author)
Cover of Mysterious Revival Title
Quality Ok
Authors Offering flowers before the Buddha
Reading Dropped, C54
Links webnovel
Cover of Staring directly at the ancient gods for a whole year Title (直视古神一整年)
Quality Slop
Authors 三藏的左轮
Reading Dropped, C100
Links wtrlab , wtrlab (author)
Cover of Shan He Ji Title (山河稷) (Mountains, Rivers, and the Grain God)
Quality Ok
Authors 姬叉
Reading Dropped, C27
Links novelupdates , novelupdates (author)
Cover of I Am a Demon Cultivator, Not a Conscientious Capitalist Title (我是魔修,不是良心资本家)
Quality Slop
Authors 窗边的鸽子
Reading Dropped, C19
Links novelupdates , novelupdates (author)
Cover of I Cultivate Legally, Why Call Me a Demon? Title (我合法修仙,凭什么叫我魔头?)
Quality Slop
Authors 一辈子小说家
Reading Dropped, C89
Links novelupdates , novelupdates (author)
Cover of Shadow Slave Title
Quality Decent
Authors Guiltythree
Reading Dropped, chapter 2777
Links webnovel
Cover of Pale Lights Title
Quality Good
Authors ErraticErrata
Reading Dropped, V3C37
Links royalroad , royalroad (author)
Cover of The Tower of Infinite Evil Title
Quality Decent
Authors Lit Homunculus
Reading Dropped, C127
Links royalroad , royalroad (author)
Cover of Changeling Title
Quality Decent
Authors Mecanimus
Reading Dropped, C103
Links royalroad
Cover of Mask of Humanity Title
Quality Decent
Authors SlaughterBot
Reading Dropped, C366
Links royalroad , royalroad (author)
Cover of Afterlife 2.0 Title
Quality Decent
Authors QuickDuckling
Reading Finished available (hiatus), C86
Links royalroad , royalroad (author)
Cover of The Hundred Reigns Title
Quality Ok
Authors Maxime J. Durand
Reading Dropped, C183
Links royalroad , royalroad (author)
Cover of Grotesqueries of the Old Domain Title (旧域怪诞) (The Grotesque Old Domain)
Quality Good?
Authors Foxtail Quill (狐尾的笔)
Reading Dropped, C268
Links novelupdates , novelupdates (author)
Cover of Magical Girl Mechanical Heart Title
Quality Ok
Authors Thundamoo
Reading Dropped, C52
Links royalroad
Cover of This Magical Girl is Mine Title
Quality Ok
Authors VoraVora
Reading Dropped, V5C1.2
Links royalroad , royalroad (author)
Cover of Magical Girl Gunslinger Title
Quality Ok
Authors Mikasane
Reading Finished available (hiatus), C37
Links royalroad , royalroad (author)
Cover of For the Glory of Rome Title
Quality Ok
Authors zaifyr
Reading Dropped, V3C12
Links royalroad , royalroad (author)
Cover of Throne Hunters Title
Quality Ok
Authors Phill Tucker
Reading Dropped, V1C44
Links royalroad , royalroad (author)
Cover of Young Master's PoV: Woke Up As A Villain In A Game One Day Title
Quality Ok
Authors The_One_Who_Was
Reading Dropped, C293
Links webnovel , webnovel (author)
Cover of Unsong Title
Quality Good, disgusting ending
Authors Scott Alexander
Reading Finished
Links site , goodreads (author)
Cover of A Gamer's Guide To Beating The Tutorial Title
Quality Ok
Authors
Reading Dropped, C352
Links royalroad
Cover of Are You Even Human Title
Quality Decent
Authors Thundamoo
Reading Dropped, C54
Links royalroad
Cover of The Crazy Knight’s Age of the Universe Title (疯骑士的宇宙时代)
Quality Ok, lost the vibe of the first book
Authors Angry Squirrel (愤怒的松鼠)
Reading Dropped, C167
Links wtr-lab
Cover of Diary of a Dead Wizard Title (死亡巫师日记)
Quality Good
Authors Jin Nai (今奈)
Reading Finished, C1037
Links novelupdates , novelupdates (author)
Cover of Shrouded Seascape Title (诡秘地海)
Quality Good
Authors Foxtail Quill (狐尾的笔)
Reading Finished, C1149
Links novelupdates , novelupdates (author)
Cover of Salvage System Title
Quality Slop
Authors Nicholas Sansbury Smith
Reading Dropped, V1C11
Links aethonbooks , aethonbooks (author)
Cover of Mage Tank Title
Quality Slop
Authors Cornman
Reading Dropped, V1C50
Links royalroad , royalroad (author)
Cover of Nightmare Realm Summoner Title
Quality Ok
Authors Actus
Reading Dropped, C278
Links royalroad
Cover of All the Dust that Falls Title
Quality Ok
Authors zaifyr
Reading Finished, V4
Links royalroad , royalroad (author)
Cover of Dear Spellbook Title
Quality Ok
Authors TK523
Reading Dropped, V3C13
Links royalroad , royalroad (author)
Cover of I Became The Necromancer Of The Academy Title
Quality Slop
Authors _172
Reading Dropped, C37
Links novelupdates , novelupdates (author)
Cover of The Shards of Etherious Title
Quality Bad
Authors Colin J.D. Crooks
Reading Dropped, V1C9
Links goodreads , goodreads (author)
Cover of Etherious Title
Quality Ok
Authors EmEs
Reading Dropped, finished V4
Links royalroad , royalroad (author)
Cover of Only at the Mahayana Stage Does the Reversal System Appear Title
Quality Ok, bad translation
Authors The Whitest Crow (最白的乌鸦)
Reading Dropped, C164
Links novelupdates , novelupdates (author)
Cover of New Life As A Max Level Archmage Title
Quality Ok
Authors ArcaneCadence
Reading Dropped, C44
Links royalroad , royalroad (author)
Cover of I Just Want to Slack Off in Cultivation Title (我只想安静的做个苟道中人)
Quality Slop
Authors Exploding Small Latte (爆炸小拿铁)
Reading Dropped, C54
Links novelupdates , novelupdates (author)
Cover of Kill the Sun Title
Quality Decent
Authors Warmaisach
Reading Finished, C992
Links webnovel , webnovel (author)
Cover of The System is Abstract, Luckily, So Am I Title
Quality Slop
Authors Pū jiē tiānxiàn (扑街天线)
Reading Dropped, C311
Links novelupdates , novelupdates (author)
Cover of Theos Title
Quality Decent
Authors Arthur Wordsmith
Reading Hiatus, B3C4
Links royalroad , royalroad (author)
Cover of Saving the school would have been easier as a cafeteria worker Title
Quality Decent
Authors CluelessRR
Reading Finished available (hiatus), chapter 90
Links royalroad , royalroad (author)
Cover of 1% Lifesteal Title
Quality Ok, boring protagonist
Authors Robert Blaise
Reading Dropped, C128 (volume 2)
Links royalroad
Cover of Versatile Mage Title (全职法师)
Quality Slop
Authors Chaos (乱)
Reading Dropped, chapter 8
Links novelupdates
Cover of Why Are the Talismans I Drawn Banned Again?! Title (我画的符箓必被禁用)
Quality Slop, rushed ending
Authors Quiet Support (安静捧场)
Reading Finshed, chapter 258
Links novelupdates , novelupdates (author)
Cover of Dungeon Inspector Title
Quality Ok, mediocre
Authors Flossindune
Reading Dropped, finished volume 1
Links royalroad , royalorad (author)
Cover of The Perfect Run Title
Quality Decent
Authors Maxime J. Durand
Reading Finished
Links royalroad , royalroad (author)
Cover of Blood & Fur Title
Quality Good
Authors Maxime J. Durand
Reading Finished
Links royalroad , royalroad (author)
Cover of Dao of the Bizarre Immortal Title (道诡异仙)
Quality Decent
Authors Foxtail Quill (狐尾的笔)
Reading Finished
Links novelupdates , novelupdates (author)
Cover of Cultivation Chat Group Title (修真聊天群)
Quality Decent
Authors Legend of the Paladin (圣骑士的传说)
Reading Finished
Links novelupdates
Cover of The Strongest System Title (最强的系统)
Quality Ok
Summary Shallow
Authors Xin Feng (新丰)
Reading Dropped, chapter 113
Links novelupdates
Cover of Solo Leveling Title (我独自升级)
Quality Ok
Summary Shallow litrpg slop
Authors Chugong (추공)
Reading Dropped, chapter 52
Links novelupdates
Cover of I Shall Be Everlasting In the World of Immortals Title (我在修仙界万古长青)
Quality Ok
Summary Shallow
Authors Fast Food Restaurant (快餐店)
Reading Dropped, chapter 241
Links novelupdates
Cover of The Stubborn Skill-Grinder In A Time Loop Title
Quality Ok
Summary Shallow litrpg slop
Authors X-RHODEN-X
Reading Dropped, chapter 44
Links royalroad
Cover of Unbound Title
Quality Ok
Summary Shallow
Authors Necariin
Reading Dropped, finisehd volume 3
Links royalroad , royalroad (author)
Cover of The Spiritual Attainment of Minghe Title (明和的精神境界)
Quality Ok
Summary Shallow, bad translation
Authors God Loves The World (神仙爱凡尘)
Reading Dropped, chapter 8
Links novelupdates
Cover of My House of Horrors Title (我有一座冒险屋)
Quality Ok
Summary Repetitive
Authors Can Fix Air-Conditioners (我会修空调)
Reading Dropped at some point
Links novelupdates
Cover of Chrysalis Title
Quality Ok
Authors RinoZ
Reading Dropped, C1654
Links royalroad , royalroad (author)
Cover of Rune Seeker Title
Quality Ok
Summary Shallow
Authors J.M. Clarke (U Juggernaut)
Reading Dropped, volume 2, chapter 12
Links royalroad
Cover of The Empty Box and Zeroth Maria Title (Utsuro no Hako to Zero no Maria) (空ろの箱と零のマリア)
Quality Decent?
Summary Don't remember
Authors Mikage Eiji
Reading Finished
Links novelupdates
Cover of Forty Millenniums of Cultivation Title (Forty Thousand Years Of Cultivation) (修真四万年)
Quality Ok
Summary Good worldbuilding, but too many empty exclamations and not enough substance
Authors The Enlightened Master Crouching Cow (卧牛真人)
Reading Dropped, chapter 2935
Links novelupdates
Cover of Trash of the Count’s Family Title
Quality Bad
Summary Korean slop, the same stuff happens over and over again, endless saving of useless garbage, humble bragging
Authors Yu Ryeo Han (유려한)
Reading Dropped, chapter 215
Links novelupdates
Cover of Perfect World Title
Quality Don't remember, children are boring
Authors Chen Dong (辰东)
Reading Dropped, chapter 75
Links novelupdates
Cover of Warlock of the Magus World Title
Quality Bad, edgy slop, too much 'AI chip, do the thing'
Authors The Plagiarist
Reading Dropped, chapter 58
Links novelupdates
Cover of Shen Yin Wang Zuo Title (Sealed Divine Throne) (神印王座)
Quality Bad, too bland
Authors Tang Jia San Shao (唐家三少)
Reading Dropped, chapter 101
Links novelupdates
Cover of Corpo Age Title
Quality Ok, feels basic
Authors RandomBlueCat
Reading Dropped, volume 1, chapter 2
Links royalroad
Cover of SSS-Class Suicide Hunter Title
Quality Ok, too much emotional bullshit
Authors Sinnoa
Reading Dropped at some point
Links novelupdates
Cover of The Divine Dungeon Title
Quality Ok, a bit basic
Authors Dakota Krout
Reading Finished
Links goodreads
Cover of Full Murderhobo Title
Quality Ok, a bit basic
Authors Dakota Krout
Reading Finished, volume 3
Links goodreads
Cover of Worm Title
Quality Decent
Authors Wildbow
Reading Finished
Links website
Cover of 12 Miles Below Title
Quality Decent
Authors Mark Arrows
Reading Dropped at some point
Links royalroad
Cover of The Charm of Soul Pets Title
Quality Don't remember
Authors Chaos (乱)
Reading Dropped, chapter 42
Links novelupdates
Cover of Throne of Magical Arcana Title
Quality Decent, a bit mediocre
Authors Cuttlefish That Loves Diving (爱潜水的乌贼)
Reading Dropped near the end when the main plot ended
Links novelupdates
Cover of The Jester of Apocalypse Title
Quality Ok, basic and a bit edgy
Authors Robert Blaise
Reading Finished available chapters
Links royalroad
Cover of Accel World Title
Quality Bad, japanese slop
Authors Kawahara Reki
Reading Dropped at some point
Links novelupdates
Cover of Reborn as a Demonic Tree Title
Quality Ok, mediocre
Authors XKARNATION
Reading Dropped, volume 8, chapter 421
Links royalroad
Cover of System Breaker Title
Quality Decent, MC is a bit immature
Authors
Reading Dropped, volume 2, chapter 55
Links royalroad
Cover of DIE. RESPAWN. REPEAT. Title
Quality Decent, a bit bland
Authors SilverLinings
Reading Dropped, volume 4, chapter 8 (chapter 222)
Links royalroad
Cover of Mark of the Fool Title
Quality Decent, not enough progression
Authors J.M. Clarke (U Juggernaut)
Reading Finished
Links royalroad
Cover of If It’s for My Daughter, I’d Even Defeat a Demon Lord Title
Quality Bad, Japanese slice-of-life litrpg fantasy slop
Authors Chirolu
Reading Dropped, V4C2
Links novelupdates
Cover of Ultimate Level 1 Title
Quality Bad, litrpg slop
Authors Dads Bedtime Stories
Reading Dropped, V1C17
Links royalroad
Cover of Vigor Mortis Title
Quality Ok
Authors Thundamoo
Reading Dropped, V4C27
Links royalroad
Cover of Rise of the Living Forge Title
Quality Ok
Authors Actus
Reading Dropped, C509
Links royalroad
Cover of The Beginning After the End Title
Quality Bad, isekai slop
Authors TurtleMe
Reading Dropped, volume 1, chapter 13
Links wikipedia
Cover of Ghost of the Truthseeker Title
Quality Ok
Authors Strungbound
Reading Dropped, chapter 220
Links royalroad
Cover of I Am Become Death Title
Quality Decent
Summary Nothing exceptional
Authors J.M. Clarke (U Juggernaut)
Reading Dropped, chapter 55
Links royalroard
Cover of Return of the Runebound Professor Title
Quality Ok
Authors Actus
Reading Reading, B7C749
Links royalroad
Title (修真世界)
Quality Good
Authors Fang Xiang (方想)
Reading Finished
Links novelupdates
Cover of I Shall Seal the Heavens Title
Quality Good
Authors Er Gen (耳根)
Reading Finished
Links novelupdates , novelupdates (author)
Cover of Beware Of Chicken Title
Quality Decent
Authors Casualfarmer
Reading Dropped, V4(V6)C68
Links royalroad
Cover of Dungeon Crawler Carl Title
Quality Good
Authors DoctorHepa
Reading Finished available, B7
Links royalroad
Cover of A Practical Guide to Sorcery Title
Quality Decent, slow upload
Authors Azalea Ellis
Reading Dropped, C262
Links azaleaellis
Cover of Downtown Druid Title
Quality Decent
Authors seersucker
Reading Finished volume 1
Links royalroad
Cover of The Years of Apocalypse Title
Quality Decent
Authors UraniumPhoenix
Reading Dropped, C226
Links royalroad
Cover of Renegade Immortal Title
Quality Good
Authors Er Gen (耳根)
Reading Finished
Links novelupdates , novelupdates (author)
Cover of Matabar Title
Quality Good
Authors Kirill Klevanski
Reading Dropped, chapter 120
Links royalroad
Cover of Defiance of the Fall Title
Quality Decent
Authors TheFirstDefier
Reading Dropped, C1370
Links royalroad
Cover of Godclads Title
Quality Good, a bit too dramatic
Authors OstensibleMammal
Reading Dropped, C37-11
Links royalroad , royalroad (author)
Cover of Archfiend Title (最强妖孽)
Quality Decent
Authors Nocturnal Stranger (厄夜怪客)
Reading Finished translated chapters, chapter 528
Links novelupdates
Cover of Outside of time Title (光阴之外)
Quality Ok
Authors Er Gen (耳根)
Reading Dropped, C1470
Links novelupdates , novelupdates (author)
Cover of The Sage Who Transcended Samsara Title (一世之尊)
Quality Good
Authors Cuttlefish That Loves Diving (爱潜水的乌贼)
Reading Finished, dropped at the end
Links novelupdates
Cover of The Experimental Log of the Crazy Lich Title (疯巫妖的实验日志)
Quality Good
Authors Angry Squirrel (愤怒的松鼠)
Reading Finished volume 1
Links novelupdates
Cover of Nightfall Title (Ever Night) (将夜)
Quality Good
Authors Mao Ni (猫腻)
Reading Finished
Links novelupdates
Cover of The Path Toward Heaven Title (大道朝天)
Quality Good
Authors Mao Ni (猫腻)
Reading Finished available chapters
Links novelupdates
Cover of Ze Tian Ji Title (Way of Choices) (择天记)
Quality Good
Authors Mao Ni (猫腻)
Reading Finished
Links novelupdates
Cover of Lord of the Mysteries Title
Quality Good
Authors Cuttlefish That Loves Diving (爱潜水的乌贼)
Reading Finished volume 2
Links novelupdates
Cover of Unintended Immortality Title (The Unintentional Path to Immortality) (我本无意成仙)
Quality Good
Authors Golden Jasmine (金色茉莉花)
Reading Finished, C713
Links novelupdates , novelfile
Cover of My Longevity Simulation Title
Quality Good
Authors Angry Squid (愤怒的乌贼)
Reading Dropped, C838
Links novelupdates , novelbin
Cover of Virtuous Sons Title
Quality Peak
Authors Ya Boy
Reading Finished available (hiatus), C2.22
Links royalroad , royalroad (author)
Cover of Reverend Insanity Title (Gu Daoist Master) (蛊真人)
Quality Peak
Authors Gu Zhen Ren (蛊真人)
Reading Finished available, C2334
Links novelupdates

4.4 - Glossary

An advanced persistent threat (APT) refers to an attack that continues, secretively, using innovative hacking methods to access a system and stay inside for a long period of time. Typical attackers are cyber criminals, like the Iranian group APT34, the Russian organization APT28, and others. Although they can come from all over the world, some of the most notable attackers come from Iran, other areas of the Middle East, and North Korea.

Docs: https://www.fortinet.com/resources/cyberglossary/advanced-persistent-threat

Subresource Integrity (SRI) is a security feature that enables browsers to verify that resources they fetch (for example, from a CDN) are delivered without unexpected manipulation. It works by allowing you to provide a cryptographic hash that a fetched resource must match.

Docs: https://developer.mozilla.org/en-US/docs/Web/Security/Subresource_Integrity

A Conflict-free Replicated Data Type (CRDT) is a data structure that simplifies distributed data storage systems and multi-user applications.

In many systems, copies of some data need to be stored on multiple computers (known as replicas). Examples of such systems include:

Mobile apps that store data on the local device, and that need to sync that data to other devices belonging to the same user (such as calendars, notes, contacts, or reminders); Distributed databases, which maintain multiple replicas of the data (in the same datacenter or in different locations) so that the system continues working correctly if some of the replicas are offline; Collaboration software, such as Google Docs, Trello, Figma, or many others, in which several users can concurrently make changes to the same file or data; Large-scale data storage and processing systems, which replicate data in order to achieve global scalability.

Docs: https://crdt.tech/

4.5 - Gnome boxes

Gnome boxes is a hypervisor.

The default cpu doesn’t have a lot of capabilities, so you might need to patch the config:

  <!-- https://www.qemu.org/docs/master/system/i386/cpu.html -->
  <cpu mode="host-model" />

Default libvirt network interferes with gnome-boxes, you might need to disable it:

sudo systemctl disable --now libvirtd

Just increasing the disk size is not enough, you need to increase the logical volume size:

sudo growpart /dev/vda 3
sudo lvextend -l +100%FREE /dev/fedora/root
sudo xfs_growfs /dev/fedora/root

Links:

4.6 - Hugo

Hugo is a static site builder

Hugo has an allowlist of environment variables, and js_binary rules do not work because they need a BAZEL_BINDIR variable

Fix:

[security.exec]
osEnv = [
    '(?i)^((HTTPS?|NO)_PROXY|PATH(EXT)?|APPDATA|TE?MP|TERM|GO\w+|(XDG_CONFIG_)?HOME|USERPROFILE|SSH_AUTH_SOCK|DISPLAY|LANG|SYSTEMDRIVE|BAZEL.+)$',
]

Configuration reference: https://gohugo.io/configuration/security/

4.7 - Leetcode submissions

Leetcode submissions

4.7.1 - 2026-04-11 20:57:04 +0300 MSK

Minimum Distance Between Three Equal Elements II
class Solution:
    def minimumDistance(self, nums: List[int]) -> int:
        n = len(nums)
        nxt = [-1] * n
        occur = {}
        ans = n + 1

        for i in range(n - 1, -1, -1):
            if nums[i] in occur:
                nxt[i] = occur[nums[i]]
            occur[nums[i]] = i

        for i in range(n):
            second_pos = nxt[i]
            if second_pos != -1:
                third_pos = nxt[second_pos]
                if third_pos != -1:
                    ans = min(ans, third_pos - i)

        return -1 if ans == n + 1 else ans * 2

4.7.2 - 2026-04-10 21:12:54 +0300 MSK

Minimum Distance Between Three Equal Elements I
class Solution:
    def minimumDistance(self, nums: List[int]) -> int:
        n = len(nums)
        ans = n + 1

        for i in range(n - 2):
            for j in range(i + 1, n - 1):
                if nums[i] != nums[j]:
                    continue
                for k in range(j + 1, n):
                    if nums[j] == nums[k]:
                        ans = min(ans, k - i)
                        break

        return -1 if ans == n + 1 else ans * 2

4.7.3 - 2026-04-09 22:31:40 +0300 MSK

XOR After Range Multiplication Queries II
class Solution:
    def xorAfterQueries(self, nums: List[int], queries: List[List[int]]) -> int:
        mod = 10**9 + 7
        n = len(nums)
        T = int(n**0.5)

        groups = [[] for _ in range(T)]
        for l, r, k, v in queries:
            if k < T:
                groups[k].append((l, r, v))
            else:
                for i in range(l, r + 1, k):
                    nums[i] = nums[i] * v % mod

        dif = [1] * (n + T)
        for k in range(1, T):
            if not groups[k]:
                continue
            dif[:] = [1] * len(dif)
            for l, r, v in groups[k]:
                dif[l] = dif[l] * v % mod
                R = ((r - l) // k + 1) * k + l
                dif[R] = dif[R] * pow(v, mod - 2, mod) % mod

            for i in range(k, n):
                dif[i] = dif[i] * dif[i - k] % mod
            for i in range(n):
                nums[i] = nums[i] * dif[i] % mod

        res = 0
        for x in nums:
            res ^= x
        return res

4.7.4 - 2026-04-08 20:09:31 +0300 MSK

XOR After Range Multiplication Queries I
class Solution:
    MOD = 10**9 + 7

    def xorAfterQueries(self, nums: List[int], queries: List[List[int]]) -> int:
        for l, r, k, v in queries:
            for i in range(l, r + 1, k):
                nums[i] = (nums[i] * v) % self.MOD

        res = 0
        for x in nums:
            res ^= x

        return res

4.7.5 - 2026-04-07 20:43:50 +0300 MSK

Walking Robot Simulation II
class Robot:

    TO_DIR = {
        0: "East",
        1: "North",
        2: "West",
        3: "South",
    }

    def __init__(self, width: int, height: int):
        self.moved = False
        self.idx = 0
        self.pos = list()
        self.dirs = list()

        pos_, dirs_ = self.pos, self.dirs

        for i in range(width):
            pos_.append((i, 0))
            dirs_.append(0)
        for i in range(1, height):
            pos_.append((width - 1, i))
            dirs_.append(1)
        for i in range(width - 2, -1, -1):
            pos_.append((i, height - 1))
            dirs_.append(2)
        for i in range(height - 2, 0, -1):
            pos_.append((0, i))
            dirs_.append(3)

        dirs_[0] = 3

    def step(self, num: int) -> None:
        self.moved = True
        self.idx = (self.idx + num) % len(self.pos)

    def getPos(self) -> List[int]:
        return list(self.pos[self.idx])

    def getDir(self) -> str:
        if not self.moved:
            return "East"
        return Robot.TO_DIR[self.dirs[self.idx]]

4.7.6 - 2026-04-06 20:15:21 +0300 MSK

Walking Robot Simulation
class Solution:
    def __init__(self):
        self.HASH_MULTIPLIER = (
            60013  # Slightly larger than 2 * max coordinate value
        )

    def robotSim(self, commands: List[int], obstacles: List[List[int]]) -> int:
        # Store obstacles in an set for efficient lookup
        obstacle_set = {self._hash_coordinates(x, y) for x, y in obstacles}

        # Define direction vectors: North, East, South, West
        directions = [(0, 1), (1, 0), (0, -1), (-1, 0)]

        x, y = 0, 0
        max_distance_squared = 0
        current_direction = 0  # 0: North, 1: East, 2: South, 3: West

        for command in commands:
            if command == -1:  # Turn right
                current_direction = (current_direction + 1) % 4
                continue

            if command == -2:  # Turn left
                current_direction = (current_direction + 3) % 4
                continue

            # Move forward
            dx, dy = directions[current_direction]
            for _ in range(command):
                next_x, next_y = x + dx, y + dy
                if self._hash_coordinates(next_x, next_y) in obstacle_set:
                    break
                x, y = next_x, next_y

            max_distance_squared = max(max_distance_squared, x * x + y * y)

        return max_distance_squared

    # Hash function to convert (x, y) coordinates to a unique integer value
    def _hash_coordinates(self, x: int, y: int) -> int:
        return x + self.HASH_MULTIPLIER * y

4.7.7 - 2026-04-06 20:14:55 +0300 MSK

Robot Return to Origin
class Solution(object):
    def judgeCircle(self, moves):
        x = y = 0
        for move in moves:
            if move == 'U': y -= 1
            elif move == 'D': y += 1
            elif move == 'L': x -= 1
            elif move == 'R': x += 1

        return x == y == 0

4.7.8 - 2026-04-04 20:41:56 +0300 MSK

Decode the Slanted Ciphertext
class Solution:
    def decodeCiphertext(self, encodedText: str, rows: int) -> str:
        if rows == 1:
            return encodedText

        n = len(encodedText)
        cols = n // rows
        res = []

        for c in range(cols):
            r, j = 0, c
            while r < rows and j < cols:
                res.append(encodedText[r * cols + j])
                r += 1
                j += 1

        return "".join(res).rstrip()

4.7.9 - 2026-04-03 22:48:45 +0300 MSK

Maximum Walls Destroyed by Robots
class Solution:
    def maxWalls(
        self, robots: List[int], distance: List[int], walls: List[int]
    ) -> int:
        n = len(robots)
        robot_dist = list(zip(robots, distance))
        robot_dist.sort(key=lambda x: x[0])
        walls.sort()

        m = len(walls)
        right_ptr = left_ptr = cur_ptr = robot_ptr = 0

        prev_left = prev_right = prev_num = 0
        sub_left = sub_right = 0

        for i in range(n):
            robot_pos, robot_dist_val = robot_dist[i]

            while right_ptr < m and walls[right_ptr] <= robot_pos:
                right_ptr += 1
            pos1 = right_ptr

            while cur_ptr < m and walls[cur_ptr] < robot_pos:
                cur_ptr += 1
            pos2 = cur_ptr

            if i >= 1:
                left_bound = max(
                    robot_pos - robot_dist_val, robot_dist[i - 1][0] + 1
                )
            else:
                left_bound = robot_pos - robot_dist_val

            while left_ptr < m and walls[left_ptr] < left_bound:
                left_ptr += 1
            left_pos = left_ptr
            current_left = pos1 - left_pos

            if i < n - 1:
                right_bound = min(
                    robot_pos + robot_dist_val, robot_dist[i + 1][0] - 1
                )
            else:
                right_bound = robot_pos + robot_dist_val

            while right_ptr < m and walls[right_ptr] <= right_bound:
                right_ptr += 1
            right_pos = right_ptr
            current_right = right_pos - pos2

            current_num = 0
            if i > 0:
                while robot_ptr < m and walls[robot_ptr] < robot_dist[i - 1][0]:
                    robot_ptr += 1
                pos3 = robot_ptr
                current_num = pos1 - pos3

            if i == 0:
                sub_left = current_left
                sub_right = current_right
            else:
                new_sub_left = max(
                    sub_left + current_left,
                    sub_right
                    - prev_right
                    + min(current_left + prev_right, current_num),
                )
                new_sub_right = max(
                    sub_left + current_right, sub_right + current_right
                )
                sub_left = new_sub_left
                sub_right = new_sub_right

            prev_left = current_left
            prev_right = current_right
            prev_num = current_num

        return max(sub_left, sub_right)

4.7.10 - 2026-04-02 19:46:57 +0300 MSK

Maximum Amount of Money Robot Can Earn
class Solution:
    def maximumAmount(self, coins: List[List[int]]) -> int:
        n = len(coins[0])
        dp = [[-inf] * 3 for _ in range(n + 1)]

        dp[1] = [0] * 3
        for row in coins:
            for j, x in enumerate(row):
                dp[j + 1][2] = max(
                    dp[j][2] + x, dp[j + 1][2] + x, dp[j][1], dp[j + 1][1]
                )
                dp[j + 1][1] = max(
                    dp[j][1] + x, dp[j + 1][1] + x, dp[j][0], dp[j + 1][0]
                )
                dp[j + 1][0] = max(dp[j][0], dp[j + 1][0]) + x

        return dp[n][2]

4.7.11 - 2026-04-01 20:54:07 +0300 MSK

Robot Collisions
class Solution:
    def survivedRobotsHealths(
        self, positions: List[int], healths: List[int], directions: str
    ) -> List[int]:
        n = len(positions)
        indices = list(range(n))
        result = []
        stack = deque()

        # Sort indices based on their positions
        indices.sort(key=lambda x: positions[x])

        for current_index in indices:
            # Add right-moving robots to the stack
            if directions[current_index] == "R":
                stack.append(current_index)
            else:
                while stack and healths[current_index] > 0:
                    # Pop the top robot from the stack for collision check
                    top_index = stack.pop()

                    if healths[top_index] > healths[current_index]:
                        # Top robot survives, current robot is destroyed
                        healths[top_index] -= 1
                        healths[current_index] = 0
                        stack.append(top_index)
                    elif healths[top_index] < healths[current_index]:
                        # Current robot survives, top robot is destroyed
                        healths[current_index] -= 1
                        healths[top_index] = 0
                    else:
                        # Both robots are destroyed
                        healths[current_index] = 0
                        healths[top_index] = 0

        # Collect surviving robots
        for index in range(n):
            if healths[index] > 0:
                result.append(healths[index])

        return result

4.7.12 - 2026-03-31 23:43:31 +0300 MSK

Lexicographically Smallest Generated String
class Solution:
    def generateString(self, str1: str, str2: str) -> str:
        n, m = len(str1), len(str2)
        s = ["a"] * (n + m - 1)
        fixed = [False] * (n + m - 1)

        # process the case of 'T'
        for i, ch in enumerate(str1):
            if ch == "T":
                for j, c in enumerate(str2, i):
                    if fixed[j] and s[j] != c:
                        return ""
                    s[j], fixed[j] = c, True

        # process the case of 'F'
        for i, ch in enumerate(str1):
            if ch == "F":
                # check if there are already different characters
                if any(str2[j - i] != s[j] for j in range(i, i + m)):
                    continue

                # find the first modifiable position
                for j in range(i + m - 1, i - 1, -1):
                    if not fixed[j]:
                        s[j] = "b"
                        break
                else:
                    return ""

        return "".join(s)

4.7.13 - 2026-03-30 19:50:10 +0300 MSK

Check if Strings Can be Made Equal With Operations II
class Solution:
    def checkStrings(self, s1: str, s2: str) -> bool:
        return Counter(s1[::2]) == Counter(s2[::2]) and Counter(
            s1[1::2]
        ) == Counter(s2[1::2])

4.7.14 - 2026-03-29 23:45:59 +0300 MSK

Check if Strings Can be Made Equal With Operations I
class Solution:
    def canBeEqual(self, s1: str, s2: str) -> bool:
        a = sorted([s1[0], s1[2]])
        b = sorted([s1[1], s1[3]])
        c = sorted([s2[0], s2[2]])
        d = sorted([s2[1], s2[3]])
        return a == c and b == d

4.7.15 - 2026-03-28 19:49:17 +0300 MSK

Find the String with LCP
class Solution:
    def findTheString(self, lcp: List[List[int]]) -> str:
        n = len(lcp)
        word = [""] * n
        current = ord("a")

        # construct the string starting from 'a' to 'z' sequentially
        for i in range(n):
            if not word[i]:
                if current > ord("z"):
                    return ""
                word[i] = chr(current)
                for j in range(i + 1, n):
                    if lcp[i][j]:
                        word[j] = word[i]
                current += 1

        # verify if the constructed string meets the LCP matrix requirements
        for i in range(n - 1, -1, -1):
            for j in range(n - 1, -1, -1):
                if word[i] != word[j]:
                    if lcp[i][j]:
                        return ""
                else:
                    if i == n - 1 or j == n - 1:
                        if lcp[i][j] != 1:
                            return ""
                    else:
                        if lcp[i][j] != lcp[i + 1][j + 1] + 1:
                            return ""

        return "".join(word)

4.7.16 - 2026-03-27 09:35:17 +0300 MSK

Matrix Similarity After Cyclic Shifts
class Solution:
    def areSimilar(self, mat: List[List[int]], k: int) -> bool:
        m, n = len(mat), len(mat[0])
        for i in range(m):
            is_even = i % 2 == 0
            for j in range(n):
                if is_even:
                    new_j = (j - k) % n    
                else:
                    new_j = (j + k) % n
                if mat[i][j] != mat[i][new_j]:
                    return False
        return True

4.7.17 - 2026-03-26 21:00:59 +0300 MSK

Equal Sum Grid Partition II
class Solution:
    def canPartitionGrid(self, grid: List[List[int]]) -> bool:
        total = 0
        m = len(grid)
        n = len(grid[0])
        for i in range(m):
            for j in range(n):
                total += grid[i][j]
        for _ in range(4):
            exist = set()
            exist.add(0)
            sum_val = 0
            m = len(grid)
            n = len(grid[0])
            if m < 2:
                grid = self.rotation(grid)
                continue
            if n == 1:
                for i in range(m - 1):
                    sum_val += grid[i][0]
                    tag = sum_val * 2 - total
                    if tag == 0 or tag == grid[0][0] or tag == grid[i][0]:
                        return True
                grid = self.rotation(grid)
                continue
            for i in range(m - 1):
                for j in range(n):
                    exist.add(grid[i][j])
                    sum_val += grid[i][j]
                tag = sum_val * 2 - total
                if i == 0:
                    if tag == 0 or tag == grid[0][0] or tag == grid[0][n - 1]:
                        return True
                    continue
                if tag in exist:
                    return True
            grid = self.rotation(grid)
        return False

    def rotation(self, grid: List[List[int]]) -> List[List[int]]:
        m = len(grid)
        n = len(grid[0])
        tmp = [[0] * m for _ in range(n)]
        for i in range(m):
            for j in range(n):
                tmp[j][m - 1 - i] = grid[i][j]
        return tmp

4.7.18 - 2026-03-25 23:26:40 +0300 MSK

Construct Product Matrix
class Solution:
    def constructProductMatrix(self, grid: List[List[int]]) -> List[List[int]]:
        MOD = 12345
        n, m = len(grid), len(grid[0])
        p = [[0] * m for _ in range(n)]

        suffix = 1
        for i in range(n - 1, -1, -1):
            for j in range(m - 1, -1, -1):
                p[i][j] = suffix
                suffix = (suffix * grid[i][j]) % MOD

        prefix = 1
        for i in range(n):
            for j in range(m):
                p[i][j] = (p[i][j] * prefix) % MOD
                prefix = (prefix * grid[i][j]) % MOD

        return p

4.7.19 - 2026-03-25 23:26:14 +0300 MSK

Equal Sum Grid Partition I
class Solution:
    def canPartitionGrid(self, grid: List[List[int]]) -> bool:
        m, n = len(grid), len(grid[0])
        total = sum(sum(row) for row in grid)
        
        if total % 2:
            return False
        
        target = total // 2
        s = 0
        
        for i in range(m - 1):
            s += sum(grid[i])
            if s == target:
                return True
        
        s = 0
        
        for j in range(n - 1):
            for i in range(m):
                s += grid[i][j]
            if s == target:
                return True
        
        return False

4.7.20 - 2026-03-23 21:09:09 +0300 MSK

Maximum Non Negative Product in a Matrix
class Solution:
    def maxProductPath(self, grid: List[List[int]]) -> int:
        mod = 10**9 + 7
        m, n = len(grid), len(grid[0])
        maxgt = [[0] * n for _ in range(m)]
        minlt = [[0] * n for _ in range(m)]

        maxgt[0][0] = minlt[0][0] = grid[0][0]
        for i in range(1, n):
            maxgt[0][i] = minlt[0][i] = maxgt[0][i - 1] * grid[0][i]
        for i in range(1, m):
            maxgt[i][0] = minlt[i][0] = maxgt[i - 1][0] * grid[i][0]

        for i in range(1, m):
            for j in range(1, n):
                if grid[i][j] >= 0:
                    maxgt[i][j] = (
                        max(maxgt[i][j - 1], maxgt[i - 1][j]) * grid[i][j]
                    )
                    minlt[i][j] = (
                        min(minlt[i][j - 1], minlt[i - 1][j]) * grid[i][j]
                    )
                else:
                    maxgt[i][j] = (
                        min(minlt[i][j - 1], minlt[i - 1][j]) * grid[i][j]
                    )
                    minlt[i][j] = (
                        max(maxgt[i][j - 1], maxgt[i - 1][j]) * grid[i][j]
                    )

        if maxgt[m - 1][n - 1] < 0:
            return -1
        return maxgt[m - 1][n - 1] % mod

4.7.21 - 2026-03-22 15:36:46 +0300 MSK

Determine Whether Matrix Can Be Obtained By Rotation
class Solution:
    def findRotation(
        self, mat: List[List[int]], target: List[List[int]]
    ) -> bool:
        n = len(mat)
        # at most 4 rotations
        for k in range(4):
            # rotation operation
            for i in range(n // 2):
                for j in range((n + 1) // 2):
                    (
                        mat[i][j],
                        mat[n - 1 - j][i],
                        mat[n - 1 - i][n - 1 - j],
                        mat[j][n - 1 - i],
                    ) = (
                        mat[n - 1 - j][i],
                        mat[n - 1 - i][n - 1 - j],
                        mat[j][n - 1 - i],
                        mat[i][j],
                    )

            if mat == target:
                return True
        return False

4.7.22 - 2026-03-21 19:43:30 +0300 MSK

Flip Square Submatrix Vertically
class Solution:
    def reverseSubmatrix(
        self, grid: List[List[int]], x: int, y: int, k: int
    ) -> List[List[int]]:
        i0, i1 = x, x + k - 1
        while i0 < i1:
            for j in range(y, y + k):
                grid[i0][j], grid[i1][j] = grid[i1][j], grid[i0][j]
            i0, i1 = i0 + 1, i1 - 1
        return grid

4.7.23 - 2026-03-20 19:36:10 +0300 MSK

Minimum Absolute Difference in Sliding Submatrix
class Solution:
    def minAbsDiff(self, grid: List[List[int]], k: int) -> List[List[int]]:
        m, n = len(grid), len(grid[0])
        res = [[0] * (n - k + 1) for _ in range(m - k + 1)]
        for i in range(m - k + 1):
            for j in range(n - k + 1):
                kgrid = []
                for x in range(i, i + k):
                    for y in range(j, j + k):
                        kgrid.append(grid[x][y])
                kmin = float("inf")
                kgrid.sort()
                for t in range(1, len(kgrid)):
                    if kgrid[t] == kgrid[t - 1]:
                        continue
                    kmin = min(kmin, kgrid[t] - kgrid[t - 1])
                if kmin != float("inf"):
                    res[i][j] = kmin
        return res

4.7.24 - 2026-03-19 23:36:34 +0300 MSK

Count Submatrices With Equal Frequency of X and Y
class Solution:
    def numberOfSubmatrices(self, grid: List[List[str]]) -> int:
        n, m = len(grid), len(grid[0])
        ans = 0
        sum = [[[0, 0] for _ in range(m + 1)] for _ in range(n + 1)]

        for i in range(n):
            for j in range(m):
                if grid[i][j] == "X":
                    sum[i + 1][j + 1][0] = (
                        sum[i + 1][j][0] + sum[i][j + 1][0] - sum[i][j][0] + 1
                    )
                    sum[i + 1][j + 1][1] = 1
                elif grid[i][j] == "Y":
                    sum[i + 1][j + 1][0] = (
                        sum[i + 1][j][0] + sum[i][j + 1][0] - sum[i][j][0] - 1
                    )
                    sum[i + 1][j + 1][1] = sum[i + 1][j][1] | sum[i][j + 1][1]
                else:
                    sum[i + 1][j + 1][0] = (
                        sum[i + 1][j][0] + sum[i][j + 1][0] - sum[i][j][0]
                    )
                    sum[i + 1][j + 1][1] = sum[i + 1][j][1] | sum[i][j + 1][1]
                if sum[i + 1][j + 1][0] == 0 and sum[i + 1][j + 1][1] == 1:
                    ans += 1

        return ans

4.7.25 - 2026-03-18 20:01:58 +0300 MSK

Count Submatrices with Top-Left Element and Sum Less Than k
class Solution:
    def countSubmatrices(self, grid: List[List[int]], k: int) -> int:
        n, m = len(grid), len(grid[0])
        cols = [0] * m
        res = 0

        for i in range(n):
            row_sum = 0
            for j in range(m):
                cols[j] += grid[i][j]
                row_sum += cols[j]
                if row_sum <= k:
                    res += 1

        return res

4.7.26 - 2026-03-17 21:22:16 +0300 MSK

Largest Submatrix With Rearrangements
class Solution:
    def largestSubmatrix(self, matrix: List[List[int]]) -> int:
        m = len(matrix)
        n = len(matrix[0])
        prev_heights = []
        ans = 0

        for row in range(m):
            heights = []
            seen = [False] * n
            
            for height, col in prev_heights:
                if matrix[row][col] == 1:
                    heights.append((height + 1, col))
                    seen[col] = True

            for col in range(n):
                if seen[col] == False and matrix[row][col] == 1:
                    heights.append((1, col))
            
            for i in range(len(heights)):
                ans = max(ans, heights[i][0] * (i + 1))
                
            prev_heights = heights

        return ans

4.7.27 - 2026-03-16 21:13:19 +0300 MSK

Get Biggest Three Rhombus Sums in a Grid
class Answer:
    def __init__(self):
        self.ans = [0, 0, 0]

    def put(self, x: int):
        _ans = self.ans

        if x > _ans[0]:
            _ans[0], _ans[1], _ans[2] = x, _ans[0], _ans[1]
        elif x != _ans[0] and x > _ans[1]:
            _ans[1], _ans[2] = x, _ans[1]
        elif x != _ans[0] and x != _ans[1] and x > _ans[2]:
            _ans[2] = x

    def get(self) -> List[int]:
        _ans = self.ans

        return [num for num in _ans if num != 0]


class Solution:
    def getBiggestThree(self, grid: List[List[int]]) -> List[int]:
        m, n = len(grid), len(grid[0])
        sum1 = [[0] * (n + 2) for _ in range(m + 1)]
        sum2 = [[0] * (n + 2) for _ in range(m + 1)]

        for i in range(1, m + 1):
            for j in range(1, n + 1):
                sum1[i][j] = sum1[i - 1][j - 1] + grid[i - 1][j - 1]
                sum2[i][j] = sum2[i - 1][j + 1] + grid[i - 1][j - 1]

        ans = Answer()
        for i in range(m):
            for j in range(n):
                # a single cell is also a rhombus
                ans.put(grid[i][j])
                for k in range(i + 2, m, 2):
                    ux, uy = i, j
                    dx, dy = k, j
                    lx, ly = (i + k) // 2, j - (k - i) // 2
                    rx, ry = (i + k) // 2, j + (k - i) // 2

                    if ly < 0 or ry >= n:
                        break

                    ans.put(
                        (sum2[lx + 1][ly + 1] - sum2[ux][uy + 2])
                        + (sum1[rx + 1][ry + 1] - sum1[ux][uy])
                        + (sum1[dx + 1][dy + 1] - sum1[lx][ly])
                        + (sum2[dx + 1][dy + 1] - sum2[rx][ry + 2])
                        - (
                            grid[ux][uy]
                            + grid[dx][dy]
                            + grid[lx][ly]
                            + grid[rx][ry]
                        )
                    )

        return ans.get()

4.7.28 - 2026-03-15 16:53:42 +0300 MSK

Fancy Sequence
class Fancy:

    def __init__(self):
        self.mod = 10**9 + 7
        self.v = list()
        self.a = 1
        self.b = 0

    # fast exponentiation
    def quickmul(self, x: int, y: int) -> int:
        return pow(x, y, self.mod)

    # multiplicative inverse
    def inv(self, x: int) -> int:
        return self.quickmul(x, self.mod - 2)

    def append(self, val: int) -> None:
        self.v.append((val - self.b) * self.inv(self.a) % self.mod)

    def addAll(self, inc: int) -> None:
        self.b = (self.b + inc) % self.mod

    def multAll(self, m: int) -> None:
        self.a = self.a * m % self.mod
        self.b = self.b * m % self.mod

    def getIndex(self, idx: int) -> int:
        if idx >= len(self.v):
            return -1
        return (self.a * self.v[idx] + self.b) % self.mod

4.7.29 - 2026-03-14 21:37:31 +0300 MSK

The k-th Lexicographical String of All Happy Strings of Length n
class Solution:
    def getHappyString(self, n: int, k: int) -> str:
        # Calculate the total number of happy strings of length n
        total = 3 * (1 << (n - 1))

        # If k is greater than the total number of happy strings, return an empty string
        if k > total:
            return ""

        result = ["a"] * n  # Initialize result with 'a' characters

        # Define mappings for the next smallest and greatest valid characters
        next_smallest = {"a": "b", "b": "a", "c": "a"}
        next_greatest = {"a": "c", "b": "c", "c": "b"}

        # Calculate the starting indices for strings beginning with 'a', 'b', and 'c'
        start_a = 1
        start_b = start_a + (1 << (n - 1))
        start_c = start_b + (1 << (n - 1))

        # Determine the first character based on the value of k
        if k < start_b:
            result[0] = "a"
            k -= start_a
        elif k < start_c:
            result[0] = "b"
            k -= start_b
        else:
            result[0] = "c"
            k -= start_c

        # Iterate through the remaining positions in the result string
        for char_index in range(1, n):
            # Calculate the midpoint of the group for the current character position
            midpoint = 1 << (n - char_index - 1)

            # Determine the next character based on the value of k
            if k < midpoint:
                result[char_index] = next_smallest[result[char_index - 1]]
            else:
                result[char_index] = next_greatest[result[char_index - 1]]
                k -= midpoint

        return "".join(result)

4.7.30 - 2026-03-13 20:46:12 +0300 MSK

Minimum Number of Seconds to Make Mountain Height Zero
class Solution:
    def minNumberOfSeconds(
        self, mountainHeight: int, workerTimes: List[int]
    ) -> int:
        maxWorkerTimes = max(workerTimes)
        l, r, ans = (
            1,
            maxWorkerTimes * mountainHeight * (mountainHeight + 1) // 2,
            0,
        )
        eps = 1e-7

        while l <= r:
            mid = (l + r) // 2
            cnt = 0
            for t in workerTimes:
                work = mid // t
                # find the largest k such that 1+2+...+k <= work
                k = int((-1 + ((1 + work * 8) ** 0.5)) / 2 + eps)
                cnt += k
            if cnt >= mountainHeight:
                ans = mid
                r = mid - 1
            else:
                l = mid + 1

        return ans

4.7.31 - 2026-03-12 19:11:46 +0300 MSK

Maximize Spanning Tree Stability with Upgrades
class DSU:
    def __init__(self, parent):
        self.parent = parent

    def find(self, x):
        if self.parent[x] == x:
            return x
        self.parent[x] = self.find(self.parent[x])
        return self.parent[x]

    def join(self, x, y):
        px = self.find(x)
        py = self.find(y)
        self.parent[px] = py


MAX_STABILITY = 200000


class Solution:
    def maxStability(self, n: int, edges: List[List[int]], k: int) -> int:
        ans = -1

        if len(edges) < n - 1:
            return -1

        mustEdges = [e for e in edges if e[3] == 1]
        optionalEdges = [e for e in edges if e[3] != 1]

        if len(mustEdges) > n - 1:
            return -1

        optionalEdges.sort(key=lambda x: x[2], reverse=True)

        selectedInit = 0
        mustMinStability = MAX_STABILITY
        dsuInit = DSU(list(range(n)))

        for u, v, s, must in mustEdges:
            if dsuInit.find(u) == dsuInit.find(v) or selectedInit == n - 1:
                return -1
            dsuInit.join(u, v)
            selectedInit += 1
            mustMinStability = min(mustMinStability, s)

        l = 0
        r = mustMinStability

        while l < r:
            mid = l + ((r - l + 1) >> 1)
            dsu = DSU(dsuInit.parent[:])
            selected = selectedInit
            doubledCount = 0

            for u, v, s, must in optionalEdges:
                if dsu.find(u) == dsu.find(v):
                    continue

                if s >= mid:
                    dsu.join(u, v)
                    selected += 1
                elif doubledCount < k and s * 2 >= mid:
                    doubledCount += 1
                    dsu.join(u, v)
                    selected += 1
                else:
                    break

                if selected == n - 1:
                    break

            if selected != n - 1:
                r = mid - 1
            else:
                ans = l = mid

        return ans

4.7.32 - 2026-03-11 21:48:29 +0300 MSK

Complement of Base 10 Integer
class Solution:
    def bitwiseComplement(self, n: int) -> int:
        if n == 0: return 1
        mask = n
        for i in (1, 2, 4, 8, 16):
            mask |= mask >> i
        return ~n & mask

4.7.33 - 2026-03-10 21:15:05 +0300 MSK

Find All Possible Stable Binary Arrays II
class Solution:
    def numberOfStableArrays(self, zero: int, one: int, limit: int) -> int:
        mod = 10**9 + 7

        dp = [[[0, 0] for _ in range(one + 1)] for _ in range(zero + 1)]
        for i in range(zero + 1):
            for j in range(one + 1):
                for lastBit in range(2):
                    if i == 0:
                        if lastBit == 0 or j > limit:
                            dp[i][j][lastBit] = 0
                        else:
                            dp[i][j][lastBit] = 1
                    elif j == 0:
                        if lastBit == 1 or i > limit:
                            dp[i][j][lastBit] = 0
                        else:
                            dp[i][j][lastBit] = 1
                    elif lastBit == 0:
                        dp[i][j][lastBit] = dp[i - 1][j][0] + dp[i - 1][j][1]
                        if i > limit:
                            dp[i][j][lastBit] -= dp[i - limit - 1][j][1]
                    else:
                        dp[i][j][lastBit] = dp[i][j - 1][0] + dp[i][j - 1][1]
                        if j > limit:
                            dp[i][j][lastBit] -= dp[i][j - limit - 1][0]
                    dp[i][j][lastBit] %= mod
        return (dp[-1][-1][0] + dp[-1][-1][1]) % mod

4.7.34 - 2026-03-09 19:32:26 +0300 MSK

Find All Possible Stable Binary Arrays I
class Solution:
    def numberOfStableArrays(self, zero: int, one: int, limit: int) -> int:
        dp = [[[0, 0] for _ in range(one + 1)] for _ in range(zero + 1)]
        mod = int(1e9 + 7)
        for i in range(min(zero, limit) + 1):
            dp[i][0][0] = 1
        for j in range(min(one, limit) + 1):
            dp[0][j][1] = 1
        for i in range(1, zero + 1):
            for j in range(1, one + 1):
                if i > limit:
                    dp[i][j][0] = (
                        dp[i - 1][j][0]
                        + dp[i - 1][j][1]
                        - dp[i - limit - 1][j][1]
                    )
                else:
                    dp[i][j][0] = dp[i - 1][j][0] + dp[i - 1][j][1]
                dp[i][j][0] = (dp[i][j][0] % mod + mod) % mod
                if j > limit:
                    dp[i][j][1] = (
                        dp[i][j - 1][1]
                        + dp[i][j - 1][0]
                        - dp[i][j - limit - 1][0]
                    )
                else:
                    dp[i][j][1] = dp[i][j - 1][1] + dp[i][j - 1][0]
                dp[i][j][1] = (dp[i][j][1] % mod + mod) % mod
        return (dp[zero][one][0] + dp[zero][one][1]) % mod

4.7.35 - 2026-03-08 19:12:47 +0300 MSK

Find Unique Binary String
class Solution:
    def findDifferentBinaryString(self, nums: List[str]) -> str:
        ans = []
        for i in range(len(nums)):
            curr = nums[i][i]
            ans.append("1" if curr == "0" else "0")
        
        return "".join(ans)

4.7.36 - 2026-03-07 13:13:17 +0300 MSK

Minimum Number of Flips to Make the Binary String Alternating
class Solution:
    def minFlips(self, s: str) -> int:
        # Characteristic function
        I = lambda ch, x: int(ord(ch) - ord("0") == x)

        n = len(s)
        pre = [[0, 0] for _ in range(n)]
        # Note the boundary case when i=0
        for i in range(n):
            pre[i][0] = (0 if i == 0 else pre[i - 1][1]) + I(s[i], 1)
            pre[i][1] = (0 if i == 0 else pre[i - 1][0]) + I(s[i], 0)

        ans = min(pre[n - 1][0], pre[n - 1][1])
        if n % 2 == 1:
            # If n is an odd number, it is also necessary to calculate suf
            suf = [[0, 0] for _ in range(n)]
            # Note the boundary case when i = n - 1
            for i in range(n - 1, -1, -1):
                suf[i][0] = (0 if i == n - 1 else suf[i + 1][1]) + I(s[i], 1)
                suf[i][1] = (0 if i == n - 1 else suf[i + 1][0]) + I(s[i], 0)

            for i in range(n - 1):
                ans = min(ans, pre[i][0] + suf[i + 1][0])
                ans = min(ans, pre[i][1] + suf[i + 1][1])

        return ans

4.7.37 - 2026-03-06 19:47:33 +0300 MSK

Check if Binary String Has at Most One Segment of Ones
class Solution:
    def checkOnesSegment(self, s: str) -> bool:
        found_1, cur_1 = False, False
        for char in s:
            if char == "1":
                if found_1 and not cur_1:
                    return False
                elif not found_1:
                    found_1 = True
                    cur_1 = True
            elif cur_1:
                cur_1 = False
        return True

4.7.38 - 2026-03-05 21:05:59 +0300 MSK

Minimum Changes To Make Alternating Binary String
class Solution:
    def minOperations(self, s: str) -> int:
        if len(s) < 2:
            return 0
        prev1 = int(s[0])
        prev2 = prev1 ^ 1
        count1, count2 = 0, 1
        for char in s[1:]:
            cur = int(char)
            if cur == prev1:
                count1 += 1
                prev1 = cur ^ 1
            else:
                prev1 = cur
            if cur == prev2:
                count2 += 1
                prev2 = cur ^ 1
            else:
                prev2 = cur
        return min(count1, count2)
                

4.7.39 - 2026-03-04 20:10:10 +0300 MSK

Special Positions in a Binary Matrix
class Solution:
    def numSpecial(self, mat: List[List[int]]) -> int:
        m = len(mat)
        n = len(mat[0])
        row_count = [0] * m
        col_count = [0] * n
        ones = []
        for row in range(m):
            for col in range(n):
                if mat[row][col] == 1:
                    row_count[row] += 1
                    col_count[col] += 1
                    ones.append((row, col))
        res = 0
        while ones:
            row, col = ones.pop()
            if row_count[row] == 1 and col_count[col] == 1:
                res += 1
        return res

4.7.40 - 2026-03-03 20:16:05 +0300 MSK

Find Kth Bit in Nth Binary String
class Solution:
    def findKthBit(self, n: int, k: int) -> str:
        # Find the position of the rightmost set bit in k
        # This helps determine which "section" of the string we're in
        position_in_section = k & -k

        # Determine if k is in the inverted part of the string
        # This checks if the bit to the left of the rightmost set bit is 1
        is_in_inverted_part = ((k // position_in_section) >> 1 & 1) == 1

        # Determine if the original bit (before any inversion) would be 1
        # This is true if k is even (i.e., its least significant bit is 0)
        original_bit_is_one = (k & 1) == 0

        if is_in_inverted_part:
            # If we're in the inverted part, we need to flip the bit
            return "0" if original_bit_is_one else "1"
        else:
            # If we're not in the inverted part, return the original bit
            return "1" if original_bit_is_one else "0"

4.7.41 - 2026-03-03 09:50:42 +0300 MSK

Minimum Swaps to Arrange a Binary Grid
class Solution:
    def minSwaps(self, grid: List[List[int]]) -> int:
        n = len(grid)
        pos = [-1] * n
        for i in range(n):
            for j in range(n - 1, -1, -1):
                if grid[i][j] == 1:
                    pos[i] = j
                    break

        ans = 0
        for i in range(n):
            k = -1
            for j in range(i, n):
                if pos[j] <= i:
                    ans += j - i
                    k = j
                    break

            if k != -1:
                for j in range(k, i, -1):
                    pos[j], pos[j - 1] = pos[j - 1], pos[j]
            else:
                return -1

        return ans

4.7.42 - 2026-03-03 09:49:36 +0300 MSK

Minimum Swaps to Arrange a Binary Grid
class Solution:
    def minSwaps(self, grid: List[List[int]]) -> int:
        n = len(grid)
        pos = [-1] * n
        for i in range(n):
            for j in range(n - 1, -1, -1):
                if grid[i][j] == 1:
                    pos[i] = j
                    break

        ans = 0
        for i in range(n):
            k = -1
            for j in range(i, n):
                if pos[j] <= i:
                    ans += j - i
                    k = j
                    break

            if k != -1:
                for j in range(k, i, -1):
                    pos[j], pos[j - 1] = pos[j - 1], pos[j]
            else:
                return -1

        return ans

4.7.43 - 2026-03-03 09:49:19 +0300 MSK

Minimum Swaps to Arrange a Binary Grid
class Solution:
    def minSwaps(self, grid: List[List[int]]) -> int:
        n = len(grid)
        pos = [-1] * n
        for i in range(n):
            for j in range(n - 1, -1, -1):
                if grid[i][j] == 1:
                    pos[i] = j
                    break

        ans = 0
        for i in range(n):
            k = -1
            for j in range(i, n):
                if pos[j] <= i:
                    ans += j - i
                    k = j
                    break

            if k != -1:
                for j in range(k, i, -1):
                    pos[j], pos[j - 1] = pos[j - 1], pos[j]
            else:
                return -1

        return ans

4.7.44 - 2026-03-01 18:20:27 +0300 MSK

Partitioning Into Minimum Number Of Deci-Binary Numbers
class Solution:
    def minPartitions(self, n: str) -> int:
        return int(max(n))

4.7.45 - 2026-03-01 18:20:02 +0300 MSK

Partitioning Into Minimum Number Of Deci-Binary Numbers
class Solution:
    def minPartitions(self, n: str) -> int:
        res = 0
        for num in n:
            res = max(res, int(num))
        return res

4.7.46 - 2026-02-28 10:54:54 +0300 MSK

Concatenation of Consecutive Binary Numbers
class Solution:
    def concatenatedBinary(self, n: int) -> int:
        cur = 0
        mod = (10 ** 9) + 7
        for i in range(1, n + 1):
            cur_i = i
            while cur_i > 0:
                cur = (cur << 1)
                cur_i //= 2
            cur = (cur + i) % mod
        return cur

4.7.47 - 2026-02-27 21:53:34 +0300 MSK

Minimum Operations to Equalize Binary String
class Solution:
    def minOperations(self, s: str, k: int) -> int:
        n, m = len(s), s.count("0")
        dist = [math.inf] * (n + 1)
        nodeSets = [
            SortedList(range(0, n + 1, 2)),
            SortedList(range(1, n + 1, 2)),
        ]
        q = deque([m])
        dist[m] = 0
        nodeSets[m % 2].remove(m)
        while q:
            m = q.popleft()
            c1, c2 = max(k - n + m, 0), min(m, k)
            lnode, rnode = m + k - 2 * c2, m + k - 2 * c1
            nodeSet = nodeSets[lnode % 2]
            idx = nodeSet.bisect_left(lnode)
            while idx < len(nodeSet) and nodeSet[idx] <= rnode:
                m2 = nodeSet[idx]
                dist[m2] = dist[m] + 1
                q.append(m2)
                nodeSet.pop(idx)
        return -1 if dist[0] == math.inf else dist[0]

4.7.48 - 2026-02-26 20:44:53 +0300 MSK

Number of Steps to Reduce a Number in Binary Representation to One
class Solution:
    def numSteps(self, s: str) -> int:
        N = len(s)

        operations = 0
        carry = 0
        for i in range(N - 1, 0, -1):
            digit = int(s[i]) + carry
            if digit % 2 == 1:
                operations += 2
                carry = 1
            else:
                operations += 1

        return operations + carry

4.7.49 - 2026-02-25 21:05:52 +0300 MSK

Sort Integers by The Number of 1 Bits
class Solution:
    def sortByBits(self, arr: List[int]) -> List[int]:
        def find_weight(num):
            weight = 0
            
            while num:
                weight += 1
                num &= (num - 1)
            
            return weight
        
        arr.sort(key = lambda num: (find_weight(num), num))
        return arr

4.7.50 - 2026-02-24 19:51:26 +0300 MSK

Sum of Root To Leaf Binary Numbers
class Solution:
    def sumRootToLeaf(self, root: TreeNode) -> int:

        def dfs(node: TreeNode, n = 0)-> None:
            if not node: return

            n = 2 * n + node.val
            if not node.left and not node.right:
                self.ans+= n
                return
                
            dfs(node.left , n)
            dfs(node.right, n)
            return
            

        self.ans = 0
        dfs(root)
        return self.ans

4.7.51 - 2026-02-23 18:14:19 +0300 MSK

Check If a String Contains All Binary Codes of Size K
class Solution:
    def hasAllCodes(self, s: str, k: int) -> bool:
        req = 1 << k
        seen = [False] * req
        mask = req - 1
        h = 0

        for i, ch in enumerate(s):
            h = ((h << 1) & mask) | (ord(ch) & 1)

            if i >= k - 1 and not seen[h]:
                seen[h] = True
                req -= 1
                if req == 0:
                    return True

        return False

4.7.52 - 2026-02-22 17:40:07 +0300 MSK

Binary Gap
class Solution(object):
    def binaryGap(self, N):
        last = None
        ans = 0
        for i in range(32):
            if (N >> i) & 1:
                if last is not None:
                    ans = max(ans, i - last)
                last = i
        return ans

4.7.53 - 2026-02-21 18:56:25 +0300 MSK

Prime Number of Set Bits in Binary Representation
class Solution(object):
    def countPrimeSetBits(self, L, R):
        primes = {2, 3, 5, 7, 11, 13, 17, 19}
        return sum(bin(x).count('1') in primes
                   for x in range(L, R+1))

4.7.54 - 2026-02-21 18:55:40 +0300 MSK

Special Binary String
class Solution:
    def makeLargestSpecial(self, s: str) -> str:
        count = 0
        i = 0
        res = []
        
        for j in range(len(s)):
            # Track balance: +1 for '1', -1 for '0'
            count += 1 if s[j] == '1' else -1
            
            # Found a balanced chunk when count returns to 0
            if count == 0:
                # Recursively maximize inner part, wrap with 1...0
                res.append('1' + self.makeLargestSpecial(s[i + 1:j]) + '0')
                i = j + 1  # Move to next potential chunk
        
        # Sort chunks in descending order for largest arrangement
        res.sort(reverse=True)
        return ''.join(res)

4.7.55 - 2026-02-19 20:42:48 +0300 MSK

Count Binary Substrings
class Solution:
    def countBinarySubstrings(self, s):
        ans, prev, cur = 0, 0, 1
        for i in range(1, len(s)):
            if s[i-1] != s[i]:
                ans += min(prev, cur)
                prev, cur = cur, 1
            else:
                cur += 1

        return ans + min(prev, cur)

4.7.56 - 2026-02-18 20:35:40 +0300 MSK

Binary Number with Alternating Bits
class Solution(object):
    def hasAlternatingBits(self, n):
        n, cur = divmod(n, 2)
        while n:
            if cur == n % 2: return False
            n, cur = divmod(n, 2)
        return True

4.7.57 - 2026-02-17 20:18:33 +0300 MSK

Binary Watch
class Solution:
    def readBinaryWatch(self, turnedOn: int) -> List[str]:
        ans = list()
        for h in range(12):
            for m in range(60):
                if bin(h).count("1") + bin(m).count("1") == turnedOn:
                    ans.append(f"{h}:{m:02d}")
        return ans

4.7.58 - 2026-02-16 19:40:12 +0300 MSK

Reverse Bits
class Solution:
    def reverseBits(self, n: int) -> int:
        res = 0
        count = 32
        while n > 0 or count > 0:
            res = (res << 1) | (n & 1)
            n >>= 1
            count -= 1
        return res

4.7.59 - 2026-02-15 20:58:12 +0300 MSK

Add Binary
class Solution:
    def addBinary(self, a, b) -> str:
        x, y = int(a, 2), int(b, 2)
        while y:
            x, y = x ^ y, (x & y) << 1
        return bin(x)[2:]

4.7.60 - 2026-02-14 12:54:19 +0300 MSK

Champagne Tower
class Solution:
    def champagneTower(self, poured, query_row, query_glass):
        A = [[0] * k for k in range(1, 102)]
        A[0][0] = poured
        for r in range(query_row + 1):
            for c in range(r+1):
                q = (A[r][c] - 1.0) / 2.0
                if q > 0:
                    A[r+1][c] += q
                    A[r+1][c+1] += q

        return min(1, A[query_row][query_glass])

4.7.61 - 2026-02-13 09:19:20 +0300 MSK

Longest Balanced Substring II
class Solution:
    def longestBalanced(self, s: str) -> int:
        n=len(s)
        # Deal with 1-letter balance
        ans, Len=1, 1
        for c0, c1 in pairwise(s):
            if c0==c1: Len+=1
            else:
                ans=max(ans, Len)
                Len=1
        ans=max(ans, Len)

        ab, bc, ca, abc={},{},{},{}
        abc[(0, 0)]=ab[(0, 0)]=bc[(0, 0)]=ca[(0, 0)]=-1

        cnt=[0, 0, 0]
        for i, c in enumerate(s):
            cnt[ord(c)-97]+=1
            A, B, C=cnt

            # 3-letter balance: A=B=C
            key=(B-A, C-A)
            if  key in abc: ans=max(ans, i-abc[key])
            else: abc[key]=i

            # 2-letter balance:
            key=(A-B, C)
            if  key in ab: ans=max(ans, i-ab[key])
            else: ab[key]=i

            key=(B-C, A)
            if  key in bc: ans=max(ans, i-bc[key])
            else: bc[key]=i

            key=(C-A, B)
            if  key in ca: ans=max(ans, i-ca[key])
            else: ca[key]=i
        return ans    

4.7.62 - 2026-02-12 19:02:27 +0300 MSK

Longest Balanced Substring I
class Solution:
    def longestBalanced(self, s: str) -> int:
        n = len(s)
        res = 0
        for i in range(n):
            cnt = defaultdict(int)
            for j in range(i, n):
                cnt[s[j]] += 1
                if len(set(cnt.values())) == 1:
                    res = max(res, j - i + 1)
        return res

4.7.63 - 2026-02-11 20:12:38 +0300 MSK

Longest Balanced Subarray II
class LazyTag:
    def __init__(self):
        self.to_add = 0

    def add(self, other):
        self.to_add += other.to_add
        return self

    def has_tag(self):
        return self.to_add != 0

    def clear(self):
        self.to_add = 0


class SegmentTreeNode:
    def __init__(self):
        self.min_value = 0
        self.max_value = 0
        self.lazy_tag = LazyTag()


class SegmentTree:
    def __init__(self, data):
        self.n = len(data)
        self.tree = [SegmentTreeNode() for _ in range(self.n * 4 + 1)]
        self._build(data, 1, self.n, 1)

    def add(self, l, r, val):
        tag = LazyTag()
        tag.to_add = val
        self._update(l, r, tag, 1, self.n, 1)

    def find_last(self, start, val):
        if start > self.n:
            return -1
        return self._find(start, self.n, val, 1, self.n, 1)

    def _apply_tag(self, i, tag):
        self.tree[i].min_value += tag.to_add
        self.tree[i].max_value += tag.to_add
        self.tree[i].lazy_tag.add(tag)

    def _pushdown(self, i):
        if self.tree[i].lazy_tag.has_tag():
            tag = LazyTag()
            tag.to_add = self.tree[i].lazy_tag.to_add
            self._apply_tag(i << 1, tag)
            self._apply_tag((i << 1) | 1, tag)
            self.tree[i].lazy_tag.clear()

    def _pushup(self, i):
        self.tree[i].min_value = min(
            self.tree[i << 1].min_value, self.tree[(i << 1) | 1].min_value
        )
        self.tree[i].max_value = max(
            self.tree[i << 1].max_value, self.tree[(i << 1) | 1].max_value
        )

    def _build(self, data, l, r, i):
        if l == r:
            self.tree[i].min_value = data[l - 1]
            self.tree[i].max_value = data[l - 1]
            return

        mid = l + ((r - l) >> 1)
        self._build(data, l, mid, i << 1)
        self._build(data, mid + 1, r, (i << 1) | 1)
        self._pushup(i)

    def _update(self, target_l, target_r, tag, l, r, i):
        if target_l <= l and r <= target_r:
            self._apply_tag(i, tag)
            return

        self._pushdown(i)
        mid = l + ((r - l) >> 1)
        if target_l <= mid:
            self._update(target_l, target_r, tag, l, mid, i << 1)
        if target_r > mid:
            self._update(target_l, target_r, tag, mid + 1, r, (i << 1) | 1)
        self._pushup(i)

    def _find(self, target_l, target_r, val, l, r, i):
        if self.tree[i].min_value > val or self.tree[i].max_value < val:
            return -1

        if l == r:
            return l

        self._pushdown(i)
        mid = l + ((r - l) >> 1)

        if target_r >= mid + 1:
            res = self._find(target_l, target_r, val, mid + 1, r, (i << 1) | 1)
            if res != -1:
                return res

        if l <= target_r and mid >= target_l:
            return self._find(target_l, target_r, val, l, mid, i << 1)

        return -1


class Solution:
    def longestBalanced(self, nums: List[int]) -> int:
        occurrences = defaultdict(deque)

        def sgn(x):
            return 1 if x % 2 == 0 else -1

        length = 0
        prefix_sum = [0] * len(nums)
        prefix_sum[0] = sgn(nums[0])
        occurrences[nums[0]].append(1)

        for i in range(1, len(nums)):
            prefix_sum[i] = prefix_sum[i - 1]
            occ = occurrences[nums[i]]
            if not occ:
                prefix_sum[i] += sgn(nums[i])
            occ.append(i + 1)

        seg = SegmentTree(prefix_sum)
        for i in range(len(nums)):
            length = max(length, seg.find_last(i + length, 0) - i)
            next_pos = len(nums) + 1
            occurrences[nums[i]].popleft()
            if occurrences[nums[i]]:
                next_pos = occurrences[nums[i]][0]

            seg.add(i + 1, next_pos - 1, -sgn(nums[i]))

        return length

4.7.64 - 2026-02-10 13:02:01 +0300 MSK

Longest Balanced Subarray I
import collections

class Solution:
    def longestBalanced(self, nums: List[int]) -> int:
        count_even, count_odd = 0, 0
        res = 0
        freqs = collections.defaultdict(int)
        for i in range(len(nums)):
            num_i = nums[i]
            for j in range(i, len(nums)):
                num = nums[j]
                freqs[num] += 1
                if freqs[num] == 1:
                    if num % 2 == 0:
                        count_even += 1
                    else:
                        count_odd += 1
                if count_even == count_odd:
                    res = max(res, j - i + 1)
            freqs.clear()
            count_even, count_odd = 0, 0
        return res

4.7.65 - 2026-02-09 20:09:17 +0300 MSK

Balance a Binary Search Tree
class Solution:
    def balanceBST(self, root: TreeNode) -> TreeNode:
        if not root:
            return None

        # Step 1: Create the backbone (vine)
        # Temporary dummy node
        vine_head = TreeNode(0)
        vine_head.right = root
        current = vine_head
        while current.right:
            if current.right.left:
                self.right_rotate(current, current.right)
            else:
                current = current.right

        # Step 2: Count the nodes
        node_count = 0
        current = vine_head.right
        while current:
            node_count += 1
            current = current.right

        # Step 3: Create a balanced BST
        m = 2 ** math.floor(math.log2(node_count + 1)) - 1
        self.make_rotations(vine_head, node_count - m)
        while m > 1:
            m //= 2
            self.make_rotations(vine_head, m)

        balanced_root = vine_head.right
        # Delete the temporary dummy node
        vine_head = None
        return balanced_root

    # Function to perform a right rotation
    def right_rotate(self, parent: TreeNode, node: TreeNode):
        tmp = node.left
        node.left = tmp.right
        tmp.right = node
        parent.right = tmp

    # Function to perform a left rotation
    def left_rotate(self, parent: TreeNode, node: TreeNode):
        tmp = node.right
        node.right = tmp.left
        tmp.left = node
        parent.right = tmp

    # Function to perform a series of left rotations to balance the vine
    def make_rotations(self, vine_head: TreeNode, count: int):
        current = vine_head
        for _ in range(count):
            tmp = current.right
            self.left_rotate(current, tmp)
            current = current.right

4.7.66 - 2026-02-08 13:23:59 +0300 MSK

Balanced Binary Tree
# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def isBalanced(self, root: Optional[TreeNode]) -> bool:
        return self.dfs(root) != -1

    def dfs(self, node: Optional[TreeNode]) -> int:
        if node is None:
            return 0
        depth1, depth2 = self.dfs(node.left), self.dfs(node.right)
        if depth1 == -1 or depth2 == -1 or abs(depth2 - depth1) > 1:
            return -1
        return 1 + max(depth1, depth2)

4.7.67 - 2026-02-07 18:17:37 +0300 MSK

Minimum Deletions to Make String Balanced
class Solution:
    def minimumDeletions(self, s: str) -> int:
        left_a, right_a = 0, s.count("a")
        left_b, right_b = 0, len(s) - right_a
        res = min(right_a, right_b)
        for char in s:
            if char == "a":
                left_a += 1
                right_a -= 1
            else:
                left_b += 1
                right_b -= 1
            res = min(res, left_b + right_a)
        return res

4.7.68 - 2026-02-06 20:36:14 +0300 MSK

Minimum Removals to Balance Array
class Solution:
    def minRemoval(self, nums: List[int], k: int) -> int:
        n = len(nums)
        nums.sort()

        ans = n
        right = 0
        for left in range(n):
            while right < n and nums[right] <= nums[left] * k:
                right += 1
            ans = min(ans, n - (right - left))

        return ans

4.7.69 - 2026-02-05 15:26:43 +0300 MSK

Transformed Array
class Solution:
    def constructTransformedArray(self, nums: List[int]) -> List[int]:
        res = [0] * len(nums)
        for i, num in enumerate(nums):
            res[i] = nums[(i + num) % len(nums)]
        return res

4.7.70 - 2026-02-04 18:39:04 +0300 MSK

Trionic Array II
class Solution:
    def maxSumTrionic(self, nums: List[int]) -> int:
        n = len(nums)
        ans = float("-inf")
        i = 0

        while i < n:
            j = i + 1
            res = 0

            # first segment: increasing segment
            while j < n and nums[j - 1] < nums[j]:
                j += 1
            p = j - 1

            if p == i:  # 没有有效的increasing segment
                i += 1
                continue

            # second segment: decreasing segment
            res += nums[p] + nums[p - 1]
            while j < n and nums[j - 1] > nums[j]:
                res += nums[j]
                j += 1
            q = j - 1

            if q == p or q == n - 1 or (j < n and nums[j] <= nums[q]):
                i = q
                continue

            # third segment: increasing segment
            res += nums[q + 1]

            # find the maximum sum of the third segment
            max_sum = 0
            curr_sum = 0
            k = q + 2
            while k < n and nums[k] > nums[k - 1]:
                curr_sum += nums[k]
                max_sum = max(max_sum, curr_sum)
                k += 1
            res += max_sum

            # find the maximum sum of the first segment
            max_sum = 0
            curr_sum = 0
            for k in range(p - 2, i - 1, -1):
                curr_sum += nums[k]
                max_sum = max(max_sum, curr_sum)
            res += max_sum

            # update answer
            ans = max(ans, res)
            i = q

        return ans

4.7.71 - 2026-02-03 21:24:01 +0300 MSK

Trionic Array I
class Solution:
    def isTrionic(self, nums: List[int]) -> bool:
        if nums[0] >= nums[1] or nums[-2] >= nums[-1] :
            return False
        seg = 1
        for i in range(2, len(nums)):
            cur, prev = nums[i], nums[i - 1]
            if cur == prev:
                return False
            if cur > prev:
                if seg == 2:
                    seg = 3
            else:
                if seg == 1:
                    seg = 2
                elif seg == 3:
                    return False
        return seg == 3

4.7.72 - 2026-02-03 14:14:39 +0300 MSK

Count Monobit Integers
class Solution:
    def countMonobit(self, n: int) -> int:
        res = 0
        cur = 0
        while cur <= n:
            res += 1
            cur = (cur << 1) | 1
        return res

4.7.73 - 2026-02-03 14:11:12 +0300 MSK

Reverse Letters Then Special Characters in a String
class Solution:
    def reverseByType(self, s: str) -> str:
        res = list(s)
        length = len(s)
        alpha, spec = length - 1, length - 1
        for i, char in enumerate(s):
            if char.isalpha():
                while not s[alpha].isalpha():
                    alpha -= 1
                target = alpha
                alpha -= 1
            else:
                while s[spec].isalpha():
                    spec -= 1
                target = spec
                spec -= 1
            res[i], res[target] = s[target], char
        return "".join(res)

4.7.74 - 2026-02-03 14:06:32 +0300 MSK

Reverse Letters Then Special Characters in a String
class Solution:
    def reverseByType(self, s: str) -> str:
        alpha, spec, res = [], [], []
        for char in s:
            if char.isalpha():
                alpha.append(char)
            else:
                spec.append(char)
        for char in s:
            if char.isalpha():
                res.append(alpha.pop())
            else:
                res.append(spec.pop())
        return "".join(res)

4.7.75 - 2026-02-03 13:54:07 +0300 MSK

Vowel-Consonant Score
class Solution:
    def vowelConsonantScore(self, s: str) -> int:
        length = len(s)
        vow = {"a", "e", "i", "o", "u"}
        vows = 0
        cons = 0
        for char in s:
            if char in vow:
                vows += 1
            elif char.isalpha():
                cons += 1
        if cons == 0:
            return 0
        return vows // cons

4.7.76 - 2026-02-03 12:24:12 +0300 MSK

Count Residue Prefixes
class Solution:
    def residuePrefixes(self, s: str) -> int:
        freqs = [0] * 26
        dist = 0
        res = 0
        for i in range(len(s)):
            target = (i + 1) % 3
            chr = ord(s[i]) - 97
            freqs[chr] += 1
            if freqs[chr] == 1:
                dist += 1
            if dist == target:
                res += 1
        return res

4.7.77 - 2026-02-02 18:52:16 +0300 MSK

Divide an Array Into Subarrays With Minimum Cost II
class Container:
    def __init__(self, k: int):
        self.k = k
        self.st1 = SortedList()
        self.st2 = SortedList()
        self.sm = 0

    def adjust(self):
        while len(self.st1) < self.k and len(self.st2) > 0:
            x = self.st2[0]
            self.st1.add(x)
            self.st2.remove(x)
            self.sm += x

        while len(self.st1) > self.k:
            x = self.st1[-1]
            self.st2.add(x)
            self.st1.remove(x)
            self.sm -= x

    # insert element x
    def add(self, x: int):
        if len(self.st2) > 0 and x >= self.st2[0]:
            self.st2.add(x)
        else:
            self.st1.add(x)
            self.sm += x
        self.adjust()

    # delete element x
    def erase(self, x: int):
        if x in self.st1:
            self.st1.remove(x)
            self.sm -= x
        elif x in self.st2:
            self.st2.remove(x)
        self.adjust()

    # sum of the first k smallest elements
    def sum(self) -> int:
        return self.sm


class Solution:
    def minimumCost(self, nums: List[int], k: int, dist: int) -> int:
        n = len(nums)
        cnt = Container(k - 2)
        for i in range(1, k - 1):
            cnt.add(nums[i])

        ans = cnt.sum() + nums[k - 1]
        for i in range(k, n):
            j = i - dist - 1
            if j > 0:
                cnt.erase(nums[j])
            cnt.add(nums[i - 1])
            ans = min(ans, cnt.sum() + nums[i])

        return ans + nums[0]

4.7.78 - 2026-02-01 19:46:21 +0300 MSK

Divide an Array Into Subarrays With Minimum Cost I
class Solution:
    def minimumCost(self, nums: List[int]) -> int:
        num1, num2 = float("inf"), float("inf")
        heap = []
        for i in range(1, len(nums)):
            heapq.heappush(heap, nums[i])
        return nums[0] + heapq.heappop(heap) + heapq.heappop(heap)

4.7.79 - 2026-02-01 19:45:22 +0300 MSK

Divide an Array Into Subarrays With Minimum Cost I
class Solution:
    def minimumCost(self, nums: List[int]) -> int:
        num1, num2 = float("inf"), float("inf")
        for i in range(1, len(nums)):
            num = nums[i]
            if num <= num1:
                num1, num2 = num, min(num1, num2)
            elif num <= num2:
                num1, num2 = min(num1, num2), num
        return nums[0] + num1 + num2

4.7.80 - 2026-01-31 21:17:17 +0300 MSK

Find Smallest Letter Greater Than Target
class Solution:
    def nextGreatestLetter(self, letters: List[str], target: str) -> str:
        for ch in letters:
            if ch > target:
                return ch
        return letters[0]

4.7.81 - 2026-01-30 20:30:09 +0300 MSK

Minimum Cost to Convert String II
INF = 10**18
INF_INT = 10**9


class Solution:
    def minimumCost(
        self,
        source: str,
        target: str,
        original: List[str],
        changed: List[str],
        cost: List[int],
    ) -> int:
        n = len(source)
        m = len(original)

        child = [[-1] * 26]
        tid = [-1]

        def new_node() -> int:
            child.append([-1] * 26)
            tid.append(-1)
            return len(child) - 1

        idx = -1

        def add(word: str) -> int:
            nonlocal idx
            node = 0
            for ch in word:
                c = ord(ch) - 97
                nxt = child[node][c]
                if nxt == -1:
                    nxt = new_node()
                    child[node][c] = nxt
                node = nxt
            if tid[node] == -1:
                idx += 1
                tid[node] = idx
            return tid[node]

        edges = []
        for i in range(m):
            x = add(original[i])
            y = add(changed[i])
            edges.append((x, y, cost[i]))

        P = idx + 1
        if P == 0:
            return 0 if source == target else -1

        dist = [[INF_INT] * P for _ in range(P)]
        for i in range(P):
            dist[i][i] = 0
        for x, y, w in edges:
            if w < dist[x][y]:
                dist[x][y] = w

        for k in range(P):
            dk = dist[k]
            for i in range(P):
                di = dist[i]
                dik = di[k]
                if dik == INF_INT:
                    continue
                base = dik
                for j in range(P):
                    nd = base + dk[j]
                    if nd < di[j]:
                        di[j] = nd

        dp = [INF] * (n + 1)
        dp[0] = 0

        s_arr = [ord(c) - 97 for c in source]
        t_arr = [ord(c) - 97 for c in target]

        for j in range(n):
            if dp[j] >= INF:
                continue

            base = dp[j]

            if source[j] == target[j] and base < dp[j + 1]:
                dp[j + 1] = base

            u = 0
            v = 0
            for i in range(j, n):
                u = child[u][s_arr[i]]
                v = child[v][t_arr[i]]
                if u == -1 or v == -1:
                    break
                uid = tid[u]
                vid = tid[v]
                if uid != -1 and vid != -1:
                    w = dist[uid][vid]
                    if w != INF_INT:
                        ni = i + 1
                        cand = base + w
                        if cand < dp[ni]:
                            dp[ni] = cand

        ans = dp[n]
        return -1 if ans >= INF else ans

4.7.82 - 2026-01-29 22:21:59 +0300 MSK

Minimum Cost to Convert String I
class Solution:
    def minimumCost(
        self,
        source: str,
        target: str,
        original: List[str],
        changed: List[str],
        cost: List[int],
    ) -> int:
        # Initialize result to store the total minimum cost
        total_cost = 0

        # Initialize a 2D list to store the minimum transformation cost
        # between any two characters
        min_cost = [[float("inf")] * 26 for _ in range(26)]

        # Fill the initial transformation costs from the given original,
        # changed, and cost arrays
        for orig, chg, cst in zip(original, changed, cost):
            start_char = ord(orig) - ord("a")
            end_char = ord(chg) - ord("a")
            min_cost[start_char][end_char] = min(
                min_cost[start_char][end_char], cst
            )

        # Use Floyd-Warshall algorithm to find the shortest path between any
        # two characters
        for k in range(26):
            for i in range(26):
                for j in range(26):
                    min_cost[i][j] = min(
                        min_cost[i][j], min_cost[i][k] + min_cost[k][j]
                    )

        # Calculate the total minimum cost to transform the source string to
        # the target string
        for src, tgt in zip(source, target):
            if src == tgt:
                continue
            source_char = ord(src) - ord("a")
            target_char = ord(tgt) - ord("a")

            # If the transformation is not possible, return -1
            if min_cost[source_char][target_char] == float("inf"):
                return -1
            total_cost += min_cost[source_char][target_char]

        return total_cost

4.7.83 - 2026-01-28 20:51:42 +0300 MSK

Minimum Cost Path with Teleportations
class Solution:
    def minCost(self, grid: list[list[int]], k: int) -> int:
        m, n = len(grid), len(grid[0])
        points = [(i, j) for i in range(m) for j in range(n)]
        points.sort(key=lambda p: grid[p[0]][p[1]])
        costs = [[float("inf")] * n for _ in range(m)]
        for t in range(k + 1):
            minCost = float("inf")
            j = 0
            for i in range(len(points)):
                minCost = min(minCost, costs[points[i][0]][points[i][1]])
                if (
                    i + 1 < len(points)
                    and grid[points[i][0]][points[i][1]]
                    == grid[points[i + 1][0]][points[i + 1][1]]
                ):
                    i += 1
                    continue
                for r in range(j, i + 1):
                    costs[points[r][0]][points[r][1]] = minCost
                j = i + 1
            for i in range(m - 1, -1, -1):
                for j in range(n - 1, -1, -1):
                    if i == m - 1 and j == n - 1:
                        costs[i][j] = 0
                        continue
                    if i != m - 1:
                        costs[i][j] = min(
                            costs[i][j], costs[i + 1][j] + grid[i + 1][j]
                        )
                    if j != n - 1:
                        costs[i][j] = min(
                            costs[i][j], costs[i][j + 1] + grid[i][j + 1]
                        )
        return costs[0][0]

4.7.84 - 2026-01-27 22:11:38 +0300 MSK

Minimum Cost Path with Edge Reversals
class Solution:
    def dijkstra(self, n: int) -> int:
        INF  = 10**9
        vis  = [False] * n
        dist = [INF] * n

        pq: List[Tuple[int, int]] = [(0, 0)]
        dist[0] = 0

        while pq:
            du, u = heapq.heappop(pq)
            if vis[u]:
                continue
            vis[u] = True

            for v, w in self.G[u]:
                nd = du + w
                if nd < dist[v]:
                    dist[v] = nd
                    heapq.heappush(pq, (nd, v))

        return -1 if dist[n - 1] == INF else dist[n - 1]

    def minCost(self, n: int, edges: List[List[int]]) -> int:
        self.G = [[] for _ in range(n)]

        for u, v, w in edges:
            self.G[u].append((v, w))
            self.G[v].append((u, 2 * w))

        return self.dijkstra(n)

4.7.85 - 2026-01-26 20:02:52 +0300 MSK

Minimum Absolute Difference
class Solution:
    def minimumAbsDifference(self, arr: List[int]) -> List[List[int]]:
        arr.sort()
        res = []
        min_diff = float("inf")
        for i in range(len(arr) - 1):
            cur, nxt = arr[i], arr[i + 1]
            diff = nxt - cur
            if diff < min_diff:
                min_diff = diff
                res.clear()
            if diff == min_diff:
                res.append((cur, nxt))
        return res

4.7.86 - 2026-01-25 21:10:14 +0300 MSK

Minimum Difference Between Highest and Lowest of K Scores
class Solution:
    def minimumDifference(self, nums: List[int], k: int) -> int:
        nums.sort()
        return min(nums[i + k - 1] - nums[i] for i in range(len(nums) - k + 1))

4.7.87 - 2026-01-24 19:43:56 +0300 MSK

Minimize Maximum Pair Sum in Array
class Solution:
    def minPairSum(self, nums: List[int]) -> int:
        nums.sort()
        res = float("-inf")
        for i in range((len(nums) // 2) + 1):
            res = max(res, nums[i] + nums[-i - 1])
        return res

4.7.88 - 2026-01-23 20:09:20 +0300 MSK

Minimum Pair Removal to Sort Array II
class Node:
    def __init__(self, value, left):
        self.value = value
        self.left = left
        self.prev = None
        self.next = None


class Solution:
    def minimumPairRemoval(self, nums: List[int]) -> int:
        class PQItem:
            def __init__(self, first, second, cost):
                self.first = first
                self.second = second
                self.cost = cost

            def __lt__(self, other):
                if self.cost == other.cost:
                    return self.first.left < other.first.left
                return self.cost < other.cost

        pq = []
        head = Node(nums[0], 0)
        current = head
        merged = [False] * len(nums)
        decrease_count = 0
        count = 0

        for i in range(1, len(nums)):
            new_node = Node(nums[i], i)
            current.next = new_node
            new_node.prev = current
            heapq.heappush(
                pq, PQItem(current, new_node, current.value + new_node.value)
            )

            if nums[i - 1] > nums[i]:
                decrease_count += 1

            current = new_node

        while decrease_count > 0:
            item = heapq.heappop(pq)
            first, second, cost = item.first, item.second, item.cost

            if (
                merged[first.left]
                or merged[second.left]
                or first.value + second.value != cost
            ):
                continue
            count += 1

            if first.value > second.value:
                decrease_count -= 1

            prev_node = first.prev
            next_node = second.next
            first.next = next_node
            if next_node:
                next_node.prev = first

            if prev_node:
                if prev_node.value > first.value and prev_node.value <= cost:
                    decrease_count -= 1
                elif prev_node.value <= first.value and prev_node.value > cost:
                    decrease_count += 1

                heapq.heappush(
                    pq, PQItem(prev_node, first, prev_node.value + cost)
                )

            if next_node:
                if second.value > next_node.value and cost <= next_node.value:
                    decrease_count -= 1
                elif second.value <= next_node.value and cost > next_node.value:
                    decrease_count += 1
                heapq.heappush(
                    pq, PQItem(first, next_node, cost + next_node.value)
                )

            first.value = cost
            merged[second.left] = True

        return count

4.7.89 - 2026-01-22 19:21:03 +0300 MSK

Remove Element
class Solution:
    def removeElement(self, nums: List[int], val: int) -> int:
        length = len(nums)
        if length < 2:
            return length - nums.count(val)
        left, right = 0, length - 1
        res = 0
        while left <= right:
            if nums[left] != val:
                res += 1
                left += 1
                continue
            if left == right:
                break
            while right > left:
                if nums[right] == val:
                    right -= 1
                else:
                    nums[left] = nums[right]
                    right -= 1
                    left += 1
                    res += 1
                    break
            
        return res

4.7.90 - 2026-01-22 18:45:34 +0300 MSK

Merge Sorted Array
class Solution:
    def merge(self, nums1: List[int], m: int, nums2: List[int], n: int) -> None:
        """
        Do not return anything, modify nums1 in-place instead.
        """
        target, idx1, idx2 = m + n - 1, m - 1, n - 1
        neg_inf = float("-inf")
        while target >= 0:
            if idx1 >= 0:
                num1 = nums1[idx1]
            else:
                num1 = neg_inf
            if idx2 >= 0:
                num2 = nums2[idx2]
            else:
                num2 = neg_inf
            if num1 >= num2:
                nums1[target] = num1
                idx1 -= 1
                target -= 1
            else:
                nums1[target] = num2
                idx2 -= 1
                target -= 1

4.7.91 - 2026-01-22 18:41:51 +0300 MSK

Merge Sorted Array
class Solution:
    def merge(self, nums1: List[int], m: int, nums2: List[int], n: int) -> None:
        """
        Do not return anything, modify nums1 in-place instead.
        """
        if not nums2:
            return nums1
        for i in reversed(range(m)):
            nums1[i + n] = nums1[i]
        target, idx1, idx2 = 0, 0, 0
        inf = float("inf")
        while target < m + n:
            if idx1 < m:
                num1 = nums1[idx1 + n]
            else:
                num1 = inf
            if idx2 < n:
                num2 = nums2[idx2]
            else:
                num2 = inf
            if num1 < num2:
                nums1[target] = num1
                target += 1
                idx1 += 1
            else:
                nums1[target] = num2
                target += 1
                idx2 += 1

4.7.92 - 2026-01-22 18:07:41 +0300 MSK

Minimum Pair Removal to Sort Array I
class Solution:
    def minimumPairRemoval(self, nums: List[int]) -> int:
        count = 0

        while len(nums) > 1:
            isAscending = True
            minSum = float("inf")
            targetIndex = -1

            for i in range(len(nums) - 1):
                pair_sum = nums[i] + nums[i + 1]

                if nums[i] > nums[i + 1]:
                    isAscending = False

                if pair_sum < minSum:
                    minSum = pair_sum
                    targetIndex = i

            if isAscending:
                break

            count += 1
            nums[targetIndex] = minSum
            nums.pop(targetIndex + 1)

        return count

4.7.93 - 2026-01-22 10:20:58 +0300 MSK

Construct the Minimum Bitwise Array II
class Solution:
    def minBitwiseArray(self, nums: List[int]) -> List[int]:
        for i in range(len(nums)):
            res = -1
            d = 1
            while (nums[i] & d) != 0:
                res = nums[i] - d
                d <<= 1
            nums[i] = res
        return nums

4.7.94 - 2026-01-20 11:39:04 +0300 MSK

Construct the Minimum Bitwise Array I
class Solution:
    def minBitwiseArray(self, nums: List[int]) -> List[int]:
        for i in range(len(nums)):
            res = -1
            d = 1
            while (nums[i] & d) != 0:
                res = nums[i] - d
                d <<= 1
            nums[i] = res
        return nums

4.7.95 - 2026-01-19 12:02:06 +0300 MSK

Maximum Side Length of a Square with Sum Less than or Equal to Threshold
class Solution:
    def maxSideLength(self, mat: List[List[int]], threshold: int) -> int:
        m, n = len(mat), len(mat[0])
        P = [[0] * (n + 1) for _ in range(m + 1)]
        for i in range(1, m + 1):
            for j in range(1, n + 1):
                P[i][j] = (
                    P[i - 1][j]
                    + P[i][j - 1]
                    - P[i - 1][j - 1]
                    + mat[i - 1][j - 1]
                )

        def getRect(x1, y1, x2, y2):
            return P[x2][y2] - P[x1 - 1][y2] - P[x2][y1 - 1] + P[x1 - 1][y1 - 1]

        r, ans = min(m, n), 0
        for i in range(1, m + 1):
            for j in range(1, n + 1):
                for c in range(ans + 1, r + 1):
                    if (
                        i + c - 1 <= m
                        and j + c - 1 <= n
                        and getRect(i, j, i + c - 1, j + c - 1) <= threshold
                    ):
                        ans += 1
                    else:
                        break
        return ans

4.7.96 - 2026-01-18 17:30:31 +0300 MSK

Largest Magic Square
class Solution:
    def largestMagicSquare(self, grid: List[List[int]]) -> int:
        m, n = len(grid), len(grid[0])

        rowsum = [[0] * n for _ in range(m)]
        for i in range(m):
            rowsum[i][0] = grid[i][0]
            for j in range(1, n):
                rowsum[i][j] = rowsum[i][j - 1] + grid[i][j]

        colsum = [[0] * n for _ in range(m)]
        for j in range(n):
            colsum[0][j] = grid[0][j]
            for i in range(1, m):
                colsum[i][j] = colsum[i - 1][j] + grid[i][j]

        for edge in range(min(m, n), 1, -1):
            for i in range(m - edge + 1):
                for j in range(n - edge + 1):
                    stdsum = rowsum[i][j + edge - 1] - (
                        0 if j == 0 else rowsum[i][j - 1]
                    )
                    check = True
                    
                    for ii in range(i + 1, i + edge):
                        if (
                            rowsum[ii][j + edge - 1]
                            - (0 if j == 0 else rowsum[ii][j - 1])
                            != stdsum
                        ):
                            check = False
                            break
                    if not check:
                        continue
                    
                    for jj in range(j, j + edge):
                        if (
                            colsum[i + edge - 1][jj]
                            - (0 if i == 0 else colsum[i - 1][jj])
                            != stdsum
                        ):
                            check = False
                            break
                    if not check:
                        continue

                    d1 = d2 = 0
                    for k in range(edge):
                        d1 += grid[i + k][j + k]
                        d2 += grid[i + k][j + edge - 1 - k]
                    if d1 == stdsum and d2 == stdsum:
                        return edge

        return 1

4.7.97 - 2026-01-18 16:48:45 +0300 MSK

Find the Largest Area of Square Inside Two Rectangles
class Solution:
    def largestSquareArea(
        self, bottomLeft: List[List[int]], topRight: List[List[int]]
    ) -> int:
        max_size = 0
        for (bottom_left_i, top_right_i), (
            bottom_left_j,
            top_right_j,
        ) in combinations(zip(bottomLeft, topRight), 2):
            w = min(top_right_i[0], top_right_j[0]) - max(
                bottom_left_i[0], bottom_left_j[0]
            )
            h = min(top_right_i[1], top_right_j[1]) - max(
                bottom_left_i[1], bottom_left_j[1]
            )

            max_size = max(max_size, min(w, h))

        return max_size * max_size

4.7.98 - 2026-01-16 19:37:40 +0300 MSK

Maximum Square Area by Removing Fences From a Field
class Solution:
    def get_edges(self, fences: List[int], border: int) -> set:
        points = sorted([1] + fences + [border])
        return {
            points[j] - points[i]
            for i in range(len(points))
            for j in range(i + 1, len(points))
        }

    def maximizeSquareArea(
        self, m: int, n: int, hFences: List[int], vFences: List[int]
    ) -> int:
        MOD = 10**9 + 7
        h_edges = self.get_edges(hFences, m)
        v_edges = self.get_edges(vFences, n)

        max_edge = max(h_edges & v_edges, default=0)
        return (max_edge * max_edge) % MOD if max_edge else -1

4.7.99 - 2026-01-15 17:40:29 +0300 MSK

Maximize Area of Square Hole in Grid
class Solution:
    def maximizeSquareHoleArea(
        self, n: int, m: int, hBars: List[int], vBars: List[int]
    ) -> int:
        hBars.sort()
        vBars.sort()
        hmax, vmax = 1, 1
        hcur, vcur = 1, 1
        for i in range(1, len(hBars)):
            if hBars[i] == hBars[i - 1] + 1:
                hcur += 1
            else:
                hcur = 1
            hmax = max(hmax, hcur)
        for i in range(1, len(vBars)):
            if vBars[i] == vBars[i - 1] + 1:
                vcur += 1
            else:
                vcur = 1
            vmax = max(vmax, vcur)
        side = min(hmax, vmax) + 1
        return side * side

4.7.100 - 2026-01-14 22:52:51 +0300 MSK

Separate Squares II
from typing import List
import bisect


class SegmentTree:
    def __init__(self, xs: List[int]):
        self.xs = xs
        self.n = len(xs) - 1
        self.count = [0] * (4 * self.n)
        self.covered = [0] * (4 * self.n)

    def update(self, qleft, qright, qval, left, right, pos):
        if self.xs[right + 1] <= qleft or self.xs[left] >= qright:
            return
        if qleft <= self.xs[left] and self.xs[right + 1] <= qright:
            self.count[pos] += qval
        else:
            mid = (left + right) // 2
            self.update(qleft, qright, qval, left, mid, pos * 2 + 1)
            self.update(qleft, qright, qval, mid + 1, right, pos * 2 + 2)

        if self.count[pos] > 0:
            self.covered[pos] = self.xs[right + 1] - self.xs[left]
        else:
            if left == right:
                self.covered[pos] = 0
            else:
                self.covered[pos] = (
                    self.covered[pos * 2 + 1] + self.covered[pos * 2 + 2]
                )

    def query(self):
        return self.covered[0]


class Solution:
    def separateSquares(self, squares: List[List[int]]) -> float:
        events = []
        xs_set = set()
        for x, y, l in squares:
            events.append((y, 1, x, x + l))
            events.append((y + l, -1, x, x + l))
            xs_set.update([x, x + l])
        xs = sorted(xs_set)

        seg_tree = SegmentTree(xs)
        events.sort()

        psum = []
        widths = []
        total_area = 0.0
        prev_y = events[0][0]

        # scan: calculate total area and record intermediate states
        for y, delta, xl, xr in events:
            length = seg_tree.query()
            total_area += length * (y - prev_y)
            seg_tree.update(xl, xr, delta, 0, seg_tree.n - 1, 0)
            # record prefix sums and widths
            psum.append(total_area)
            widths.append(seg_tree.query())
            prev_y = y

        # calculate the target area (half rounded up)
        target = (total_area + 1) // 2
        # find the first position greater than or equal to target using binary search
        i = bisect.bisect_left(psum, target) - 1
        # get the corresponding area, width, and height
        area = psum[i]
        width = widths[i]
        height = events[i][0]

        return height + (total_area - area * 2) / (width * 2.0)

4.7.101 - 2026-01-13 19:03:15 +0300 MSK

Separate Squares I
class Solution:
    def separateSquares(self, squares: List[List[int]]) -> float:
        total_area = 0
        events = []

        for sq in squares:
            y, l = sq[1], sq[2]
            total_area += l * l
            events.append((y, l, 1))
            events.append((y + l, l, -1))

        # sort by y-coordinate
        events.sort(key=lambda x: x[0])

        covered_width = (
            0.0  # sum of all bottom edges under the current scanning line
        )
        curr_area = 0.0  # current cumulative area
        prev_height = 0.0  # height of the previous scanning line

        for y, l, delta in events:
            diff = y - prev_height
            # additional area between two scanning lines
            area = covered_width * diff
            # if this part of the area exceeds more than half of the total area
            if 2 * (curr_area + area) >= total_area:
                return prev_height + (total_area - 2 * curr_area) / (
                    2 * covered_width
                )
            # update width: add width at the start event, subtract width at the end event
            covered_width += delta * l
            curr_area += area
            prev_height = y

        return 0.0

4.7.102 - 2026-01-12 10:11:59 +0300 MSK

Minimum Time Visiting All Points
class Solution:
    def minTimeToVisitAllPoints(self, points: List[List[int]]) -> int:
        pos_x, pos_y = points[0]
        res = 0
        for x, y in points[1:]:
            diff_x, diff_y = abs(pos_x - x), abs(pos_y - y)
            diff_min, diff_max = min(diff_x, diff_y), max(diff_x, diff_y)
            res += diff_min + (diff_max - diff_min)
            pos_x, pos_y = x, y
        return res

4.7.103 - 2026-01-11 13:52:04 +0300 MSK

Maximal Rectangle
class Solution:
    def maximalRectangle(self, matrix: List[List[str]]) -> int:
        m, n = len(matrix), len(matrix[0])
        dp = [[0] * (n + 1)  for _ in range(m + 1)]
        max_area = 0

        for i in range(m):
            for j in range(n):
                if matrix[i][j] == "0":
                    continue
                dp_i, dp_j = i + 1, j + 1
                width = dp[dp_i][dp_j - 1] + 1
                dp[dp_i][dp_j] = width
                max_area = max(max_area, width)
                for cur_dp_i in reversed(range(1, dp_i)):
                    height = dp_i - cur_dp_i + 1
                    width = min(width, dp[cur_dp_i][dp_j])
                    if width == 0:
                        break
                    max_area = max(max_area, height * width)
        
        return max_area

4.7.104 - 2026-01-11 08:25:47 +0300 MSK

Shortest Palindrome
class Solution:
    def shortestPalindrome(self, s: str) -> str:
        length = len(s)
        reversed_string = s[::-1]  # Reverse the string
        for i in range(length):
            if s[: length - i] == reversed_string[i:]:
                return reversed_string[:i] + s
        return ""

4.7.105 - 2026-01-10 14:26:29 +0300 MSK

Shortest Palindrome
class Solution:
    def shortestPalindrome(self, s: str) -> str:
        reversed_string = s[::-1]
        combined_string = "#".join((s, reversed_string))
        prefix_table = self._kmp_table(combined_string)
        palindrome_length = prefix_table[-1]
        suffix = reversed_string[: len(s) - palindrome_length]
        return suffix + s

    def _kmp_table(self, s: str) -> list[int]:
        prefix_table = [0] * len(s)
        length = 0
        for i in range(1, len(s)):
            while length > 0 and s[i] != s[length]:
                length = prefix_table[length - 1]
            if s[i] == s[length]:
                length += 1
            prefix_table[i] = length
        return prefix_table

4.7.106 - 2026-01-10 14:23:41 +0300 MSK

Shortest Palindrome
class Solution:
    def shortestPalindrome(self, s: str) -> str:
        length = len(s)
        if length == 0:
            return s
        left = 0
        for right in range(length - 1, -1, -1):
            if s[right] == s[left]:
                left += 1
        if left == length:
            return s
        non_palindrome_suffix = s[left:]
        reverse_suffix = non_palindrome_suffix[::-1]
        return (
            reverse_suffix
            + self.shortestPalindrome(s[:left])
            + non_palindrome_suffix
        )

4.7.107 - 2026-01-10 14:04:15 +0300 MSK

Shortest Palindrome
class Solution:
    def shortestPalindrome(self, s: str) -> str:
        length = len(s)
        if length < 2:
            return s
        left = 0
        for right in reversed(range(length)):
            if s[left] == s[right]:
                left += 1
        if left == length:
            return s
        non_palindrome_suffix = s[left:]
        reverse_suffix = non_palindrome_suffix[::-1]
        return (
            reverse_suffix
            + self.shortestPalindrome(s[:left])
            + non_palindrome_suffix
        )

4.7.108 - 2026-01-10 12:50:38 +0300 MSK

Minimum ASCII Delete Sum for Two Strings
class Solution:
    def minimumDeleteSum(self, s1: str, s2: str) -> int:
        length1, length2 = len(s1), len(s2)
        dp = [[-1] * (length2 + 1) for _ in range(length1 + 1)]
        inf = float("inf")

        def dfs(i: int, j: int) -> int:
            if dp[i][j] != -1:
                return dp[i][j]
            elif i == length1:
                res = sum(ord(char) for char in s2[j:])
            elif j == length2:
                res = sum(ord(char) for char in s1[i:])
            else:
                char1, char2 = ord(s1[i]), ord(s2[j]) 
                res = min(char1 + dfs(i + 1, j), char2 + dfs(i, j + 1))
                if char1 == char2:
                    res = min(res, dfs(i + 1, j + 1))
            dp[i][j] = res
            return res
    
        return dfs(0, 0)

4.7.109 - 2026-01-10 12:34:56 +0300 MSK

Largest Even Number
class Solution:
    def largestEven(self, s: str) -> str:
        last = len(s) - 1
        while last >= 0 and s[last] == "1":
            last -= 1
        return s[:last + 1]

4.7.110 - 2026-01-10 12:32:09 +0300 MSK

Reverse String Prefix
class Solution:
    def reversePrefix(self, s: str, k: int) -> str:
        return s[k - 1::-1] + s[k:]

4.7.111 - 2026-01-10 12:31:07 +0300 MSK

Reverse String Prefix
class Solution:
    def reversePrefix(self, s: str, k: int) -> str:
        return s[:k][::-1] + s[k:]

4.7.112 - 2026-01-10 12:28:57 +0300 MSK

Find Users with High Token Usage
SELECT 
    user_id, 
    COUNT(prompt) AS "prompt_count", 
    ROUND(AVG(tokens),2) AS "avg_tokens"
FROM 
    prompts
GROUP BY 
    user_id
HAVING 
    COUNT(prompt) > 2 
    AND MAX(tokens) > AVG(tokens)
ORDER BY 
    avg_tokens DESC, 
    user_id;

4.7.113 - 2026-01-09 15:34:38 +0300 MSK

Dungeon Game
def solve(i: int, j: int, dungeon: list[list[int]], dp: list[list[int]]) -> int:
    m, n = len(dungeon), len(dungeon[0])
    if i == m - 1 and j == n - 1:
        return max(1, 1 - dungeon[i][j])
    if i >= m or j >= n:
        return float("inf")
    if dp[i][j] != -1:
        return dp[i][j]
    right = solve(i, j + 1, dungeon, dp)
    down = solve(i + 1, j, dungeon, dp)
    min_health = min(right, down) - dungeon[i][j]
    dp[i][j] = max(1, min_health)
    return dp[i][j]

class Solution:

    def calculateMinimumHP(self, dungeon):
        m, n = len(dungeon), len(dungeon[0])
        dp = [[-1] * n for _ in range(m)]
        return solve(0, 0, dungeon, dp)

4.7.114 - 2026-01-09 13:31:31 +0300 MSK

Find Minimum in Rotated Sorted Array II
import functools

class Solution:
    def findMin(self, nums: List[int]) -> int:
        length = len(nums)
        if length < 3:
            return min(nums)
        inf = float("inf")

        @functools.cache
        def check(i: int) -> int:
            if i == 0:
                prev, nxt = length - 1, 1
            elif i == length - 1:
                prev, nxt = length - 2, 0
            else:
                prev, nxt = i - 1, i + 1
            num_prev, num_cur, num_nxt = nums[prev], nums[i], nums[nxt]
            if num_cur < num_prev:
                return num_cur
            if num_nxt < num_cur:
                return num_nxt
            return -1

        @functools.cache
        def dp(left: int, right: int) -> int:
            if left < 0 or right == length or left > right:
                return  inf
            mid = left + (right - left) // 2
            num_left, num_mid, num_right = nums[left], nums[mid], nums[right]
            for idx in (left, mid, right):
                check_res = check(idx)
                if check_res != -1:
                    return check_res
            if num_left == num_mid == num_right:
                return min(num_left, dp(left + 1, mid - 1), dp(mid + 1, right - 1))
            if num_mid < num_left:
                return dp(left + 1, mid - 1)
            return dp(mid + 1, right - 1)
        
        return dp(0, length - 1)
            
              

4.7.115 - 2026-01-09 11:15:58 +0300 MSK

Smallest Subtree with all the Deepest Nodes
# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def subtreeWithAllDeepest(self, root: Optional[TreeNode]) -> Optional[TreeNode]:
        if root is None:
            return None
        neg_inf = float("-inf")

        def dfs(node: TreeNode, depth: int) -> tuple[TreeNode, int]:
            if node.left is None and node.right is None:
                return node, depth
            if node.left is None:
                return dfs(node.right, depth + 1)
            if node.right is None:
                return dfs(node.left, depth + 1)
            left_node, left_depth = dfs(node.left, depth + 1)
            right_node, right_depth = dfs(node.right, depth + 1)
            if left_depth == right_depth:
                return node, left_depth
            if left_depth > right_depth:
                return left_node, left_depth
            return right_node, right_depth
        
        return dfs(root, 0)[0]

4.7.116 - 2026-01-08 22:11:32 +0300 MSK

Palindrome Partitioning II
class Solution:
    def minCut(self, s: str) -> int:
        n = len(s)
        cuts = [i for i in range(n)] 

        for center in range(n):
            for left, right in ((center, center), (center, center + 1)):
                while left >= 0 and right < n and s[left] == s[right]:
                    if left == 0:
                        cuts[right] = 0 
                    else:
                        cuts[right] = min(cuts[right], cuts[left - 1] + 1)
                    left -= 1
                    right += 1

        return cuts[-1]

4.7.117 - 2026-01-08 19:05:53 +0300 MSK

Word Ladder II
class Solution:
    def findLadders(self, beginWord: str, endWord: str, wordList: List[str]) -> int:
        words, mp, ans = set(wordList), defaultdict(list), []
        
        def bfs(words: set[str]) -> None:
            letters = [chr(97 + x) for x in range(26)]
            ws, q, next_lev = len(beginWord), deque([beginWord]), set()
            while q:
                size = len(q)
                for _ in range(size):
                    w = q.popleft()
                    for i in range(ws):
                        pre, suf = w[:i], w[i+1:]
                        for l in letters:
                            nw = pre + l + suf
                            if nw in words:
                                mp[nw].append(w)
                                next_lev.add(nw)
                q.extend(next_lev)
                words -= next_lev
                next_lev.clear()

        bfs(words)

        def dfs(w: str, arr):
            if w == beginWord:
                ans.append(list(arr))
                return
            for nw in mp[w]:
                arr.appendleft(nw)
                dfs(nw,arr)
                arr.popleft()

        if endWord in mp:
            dfs(endWord, deque([endWord]))

        return ans

4.7.118 - 2026-01-08 17:17:32 +0300 MSK

Distinct Subsequences
class Solution:
    def numDistinct(self, s: str, t: str) -> int:
        cache = {}
        length1, length2 = len(s), len(t)

        def dp(i: int, j: int) -> int:
            if j == length2:
                return 1
            if i == length1:
                return 0
            key = (i, j)
            if key in cache:
                return cache[key]
            res = 0
            if s[i] == t[j]:
                res += dp(i + 1, j+ 1)
            res += dp(i + 1, j)
            cache[key] = res
            return res

        return dp(0, 0)

4.7.119 - 2026-01-08 15:42:20 +0300 MSK

Max Dot Product of Two Subsequences
class Solution:
    def maxDotProduct(self, nums1: List[int], nums2: List[int]) -> int:
        cache = {}

        def dp(i: int, j: int):
            if i == len(nums1) or j == len(nums2):
                return float("-inf")
            if (i, j) in cache:
                return cache[(i, j)]
            take = nums1[i] * nums2[j]
            res = max(take + dp(i+1, j+1), take, dp(i+1,j), dp(i,j+1))
            cache[(i, j)] = res
            return cache[(i, j)]

        return dp(0,0)

4.7.120 - 2026-01-07 21:40:08 +0300 MSK

Scramble String
class Solution:
    def isScramble(self, s1: str, s2: str) -> bool:
        cache = {}

        def check(s1: str, s2: str) -> bool:
            key = (s1, s2)
            if key in cache:
                return cache[key]
            if s1 == s2:
                cache[key] = True
                return True
            res = False
            for middle in range(1, len(s1)):    
                if (
                    check(s1[:middle], s2[:middle]) 
                    and check(s1[middle:], s2[middle:])    
                ) or (
                    check(s1[:middle], s2[-middle:])
                    and check(s1[middle:], s2[:len(s1) - middle])
                ):
                    res = True
                    break
            cache[key] = res
            return res

        return check(s1, s2)

4.7.121 - 2026-01-07 19:46:02 +0300 MSK

Largest Rectangle in Histogram
class Solution:
    def largestRectangleArea(self, heights: List[int]) -> int:
        stack = []
        area = 0
        length = len(heights)

        for i in range(length):
            while stack and heights[i] < heights[stack[-1]]:
                bar = stack.pop()
                if stack:
                    pse = stack[-1]
                else:
                    pse =  -1
                nse = i
                area = max(area, heights[bar] * (nse - pse - 1))
            stack.append(i)

        while stack:
            bar = stack.pop()
            if stack:
                pse = stack[-1] 
            else:
                pse =  -1
            nse = length
            area = max(area, heights[bar] * (nse - pse - 1))

        return area

4.7.122 - 2026-01-07 18:35:43 +0300 MSK

Orderly Queue
class Solution:
    def orderlyQueue(self, s: str, k: int) -> str:
        if k > 1:
            return "".join(sorted(s))
        min_string = s
        for i in range(1, len(s)):
            min_string = min(min_string, s[i:] + s[:i])
        return min_string

4.7.123 - 2026-01-07 15:39:17 +0300 MSK

Permutation Sequence
import itertools

class Solution:
    def getPermutation(self, n: int, k: int) -> str:
        for nums in itertools.permutations(range(1, n + 1), n):
            if k == 1:
                return "".join(map(str, nums))
            k -= 1
        raise Exception

4.7.124 - 2026-01-07 15:23:44 +0300 MSK

N-Queens
class Solution:
    def solveNQueens(self, n: int) -> List[List[str]]:
        res = []
        state = [["."] * n for _ in range(n)]
    
        def backtrack(row: int, col: int, left: int) -> None:
            if left == 0: 
                res.append(tuple("".join(cur_row) for cur_row in state))
                return
            if row >= n or col >= n:
                return

            place = True
            for i in range(row):
                if state[i][col] == "Q":
                    place = False
                    break

            if place:
                cur_i, cur_j = row, col
                while cur_i >= 0 and cur_j >= 0:
                    if state[cur_i][cur_j] == "Q":
                        place = False
                        break
                    cur_i -= 1
                    cur_j -= 1
            
            if place:
                cur_i, cur_j = row, col
                while cur_i >= 0 and cur_j < n:
                    if state[cur_i][cur_j] == "Q":
                        place = False
                        break
                    cur_i -= 1
                    cur_j += 1

            if place:    
                state[row][col] = "Q"
                backtrack(row + 1, 0, left - 1)
                state[row][col] = "."
            
            if col + 1 == n:
                nxt_row, nxt_col = row + 1, 0
            else:
                nxt_row, nxt_col = row, col + 1
            backtrack(nxt_row, nxt_col, left)

        backtrack(0, 0, n)
        
        return res

4.7.125 - 2026-01-07 14:29:52 +0300 MSK

Longest Valid Parentheses
class Solution:
    def longestValidParentheses(self, s: str) -> int:
        stack = []
        lengths = [0] * len(s)
        max_length = 0
        for i, char in enumerate(s):
            stack.append((i, char))
            while len(stack) > 1 and stack[-2][1] == "(" and stack[-1][1] == ")":
                start, end = stack[-2][0], stack[-1][0]
                length = end - start + 1
                if start > 1:
                    length += lengths[start - 1]
                lengths[end] = length
                max_length = max(max_length, length)
                stack.pop()
                stack.pop()

        return max_length

4.7.126 - 2026-01-07 13:23:43 +0300 MSK

Regular Expression Matching
class Solution:
    def isMatch(self, s: str, p: str) -> bool:
        length1, length2 = len(s), len(p)

        def match(i: int, j: int) -> bool:
            if i < length1:
                char = s[i]
            else:
                char = None
            if j < length2:
                pat = p[j]
            else:
                pat = None
            
            if char is None and pat is None:
                res = True
            elif pat is None:
                res = False
            elif char is None:
                res = (length2 - j) % 2 == 0
                if res:
                    for cur_j in range(j, length2, 2):
                        if p[cur_j] == "*" or p[cur_j + 1] != "*":
                            res = False
                            break
            else:
                if j + 1 < length2:
                    pat_nxt = p[j + 1]
                else:
                    pat_nxt = None
                valid = pat == "." or char == pat
                if pat_nxt and pat_nxt == "*":
                    res = (valid and match(i + 1, j)) or match(i, j + 2)
                else:
                    res = valid and match(i + 1, j + 1)

            return res

        return match(0, 0)

4.7.127 - 2026-01-07 13:23:17 +0300 MSK

Regular Expression Matching
class Solution:
    def isMatch(self, s: str, p: str) -> bool:
        length1, length2 = len(s), len(p)
        cache = {}

        def match(i: int, j: int) -> bool:
            if (i, j) in cache:
                return cache[(i, j)]
            if i < length1:
                char = s[i]
            else:
                char = None
            if j < length2:
                pat = p[j]
            else:
                pat = None
            
            if char is None and pat is None:
                res = True
            elif pat is None:
                res = False
            elif char is None:
                res = (length2 - j) % 2 == 0
                if res:
                    for cur_j in range(j, length2, 2):
                        if p[cur_j] == "*" or p[cur_j + 1] != "*":
                            res = False
                            break
            else:
                if j + 1 < length2:
                    pat_nxt = p[j + 1]
                else:
                    pat_nxt = None
                valid = pat == "." or char == pat
                if pat_nxt and pat_nxt == "*":
                    res = (valid and match(i + 1, j)) or match(i, j + 2)
                else:
                    res = valid and match(i + 1, j + 1)

            cache[(i, j)] = res
            return res

        return match(0, 0)

4.7.128 - 2026-01-07 12:50:50 +0300 MSK

Wildcard Matching
class Solution:
    def isMatch(self, s: str, p: str) -> bool:
        length1, length2 = len(s), len(p)
        cache = {}
        def search(i: int, j: int) -> bool:
            if (i, j) in cache:
                return cache[(i, j)]
            if i < length1:
                char = s[i]
            else:
                char = None
            if j < length2:
                pat = p[j]
            else:
                pat = None
            if char is None and pat is None:
                res = True
            elif char is None:
                res = pat == "*" and search(i, j + 1)
            elif pat is None:
                res = False
            elif pat == "?":
                res = search(i + 1, j + 1)
            elif pat == "*":
                nxt = j + 1
                while nxt < length2 and p[nxt] == "*":
                    nxt += 1
                res = search(i, nxt) or search(i + 1, nxt) or search(i + 1, j)
            else:
                res = pat == char and search(i + 1, j + 1)
            cache[(i, j)] = res
            return res

        return search(0, 0)

4.7.129 - 2026-01-07 11:11:18 +0300 MSK

Maximum Product of Splitted Binary Tree
# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def maxProduct(self, root: Optional[TreeNode]) -> int:
        if root is None:
            return 0
        sums = {}
        def dfs_sum(node: Optional[TreeNode]) -> int:
            if node is None:
                return 0
            node_id = id(node)
            if node_id in sums:
                return sums[node_id]
            res = node.val + dfs_sum(node.left) + dfs_sum(node.right)
            sums[node_id] = res
            return res
        dfs_sum(root)
        root_sum = sums[id(root)]
        def dfs(node: Optional[TreeNode]) -> int:
            if node is None:
                return 0
            tree1 = sums[id(node)]
            tree2 = root_sum - tree1 
            res = max(tree1 * tree2, dfs(node.left), dfs(node.right))
            return res
        return max(dfs(root.left), dfs(root.right)) % (10 ** 9 + 7)

4.7.130 - 2026-01-06 23:04:34 +0300 MSK

Valid Number
import re

PATTERN = r"^[-+]?(\d+|[.]\d+|\d+[.]\d*)([eE][-+]?\d+)?$"

class Solution:
    def isNumber(self, s: str) -> bool:
        return re.match(PATTERN, s) is not None

4.7.131 - 2026-01-06 22:19:43 +0300 MSK

Encrypt and Decrypt Strings
class Encrypter:

    def __init__(self, keys: List[str], values: List[str], dictionary: List[str]):
        self.key_to_i = {}
        self.keys = keys
        self.values = values
        self.value_to_i = collections.defaultdict(list)
        for i, key in enumerate(keys):
            self.key_to_i[key] = i
        for i, value in enumerate(values):
            self.value_to_i[value].append(i)
        self.trie = {}
        for word in dictionary:
            trie = self.trie
            for char in word:
                if char not in trie:
                    trie[char] = {}
                trie = trie[char]
            trie[""] = True

    def encrypt(self, word1: str) -> str:
        res = []
        for char in word1:
            if char not in self.key_to_i:
                return ""
            res.append(self.values[self.key_to_i[char]])
        return "".join(res)

    def decrypt(self, word2: str) -> int:
        def backtrack(i: int, trie: dict[str, dict]) -> int:
            if i >= len(word2):
                if trie.get(""):
                    return 1
                return 0
            res = 0
            for idx in self.value_to_i[word2[i:i+ 2]]:
                key = self.keys[idx]
                if key in trie:
                    res += backtrack(i + 2, trie[key])
            return res

        return backtrack(0, self.trie)

# Your Encrypter object will be instantiated and called as such:
# obj = Encrypter(keys, values, dictionary)
# param_1 = obj.encrypt(word1)
# param_2 = obj.decrypt(word2)

4.7.132 - 2026-01-06 21:39:35 +0300 MSK

Sequentially Ordinal Rank Tracker
class MaxString:
    __slots__ = ("s")
    def __init__(self, s):
        self.s = s

    def __lt__(self, other):
        return self.s > other.s


class SORTracker:
    def __init__(self):
        self.right = []
        self.left = []

    def add(self, name: str, score: int) -> None:
        _, name, score = heapq.heappushpop(
            self.left, 
            ((score, MaxString(name)), name, score)
        )
        heapq.heappush(self.right, ((-score, name), name, score))

    def get(self) -> str:
        _, name, score = heapq.heappop(self.right)
        heapq.heappush(self.left, ((score, MaxString(name)), name, score))
        return name

4.7.133 - 2026-01-06 21:10:32 +0300 MSK

Sequentially Ordinal Rank Tracker
from sortedcontainers import SortedList

class SORTracker:

    def __init__(self):
        self.cnt = 0 
        self.data = SortedList()

    def add(self, location: str, score: int) -> None:
        self.data.add((-score, location))

    def get(self) -> str:
        _, location = self.data[self.cnt]
        self.cnt+= 1
        return location

4.7.134 - 2026-01-06 19:37:48 +0300 MSK

Prefix and Suffix Search
class WordFilter:

    def __init__(self, words: List[str]):
        self.prefix = {}
        self.postfix = {}
        for i, word in enumerate(words):
            prefix = self.prefix
            for char in word:
                if char not in prefix:
                    prefix[char] = {}
                prefix = prefix[char]
            prefix[""] = i
            postfix = self.postfix
            for char in reversed(word):
                if char not in postfix:
                    postfix[char] = {}
                postfix = postfix[char]
            if "" not in postfix:
                postfix[""] = set()
            postfix[""] = i

    def f(self, pref: str, suff: str) -> int:
        prefixes, postfixes = set(), set()
        postfix, prefix = self.postfix, self.prefix
        for char in pref:
            if char not in prefix:
                return -1
            prefix = prefix[char]
        for char in reversed(suff):
            if char not in postfix:
                return -1
            postfix = postfix[char]
        postfix_queue = [postfix]
        prefix_queue = [prefix]
        while postfix_queue:
            for key, value in postfix_queue.pop().items():
                if key == "":
                    postfixes.add(value)
                else:
                    postfix_queue.append(value)
        while prefix_queue:
            for key, value in prefix_queue.pop().items():
                if key == "":
                    prefixes.add(value)
                else:
                    prefix_queue.append(value)
        res = prefixes & postfixes
        if not res:
            return -1
        return max(res)

# Your WordFilter object will be instantiated and called as such:
# obj = WordFilter(words)
# param_1 = obj.f(pref,suff)

4.7.135 - 2026-01-06 12:16:09 +0300 MSK

Maximum Frequency Stack
class FreqStack:

    def __init__(self):
        self.levels = [None]
        self.last_level = 0
        self.freqs = collections.defaultdict(int)

    def push(self, val: int) -> None:
        freq = self.freqs[val] + 1
        if freq >= len(self.levels):
            self.levels.append([])
        self.levels[freq].append(val)
        self.freqs[val] = freq

    def pop(self) -> int:
        for i in reversed(range(len(self.levels))):
            level = self.levels[i]
            if level:
                val = level.pop()
                self.freqs[val] -= 1
                return val
        raise Exception


# Your FreqStack object will be instantiated and called as such:
# obj = FreqStack()
# obj.push(val)
# param_2 = obj.pop()

4.7.136 - 2026-01-06 10:05:37 +0300 MSK

Maximum Level Sum of a Binary Tree
# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def maxLevelSum(self, root: Optional[TreeNode]) -> int:
        cur, nxt = [root], []
        level = 1
        min_level, max_sum = 1, root.val
        while cur or nxt:
            cur_sum = 0
            while cur:
                node = cur.pop()
                cur_sum += node.val
                if node.left:
                    nxt.append(node.left)
                if node.right:
                    nxt.append(node.right)
            if cur_sum > max_sum:
                min_level, max_sum = level, cur_sum
            cur, nxt = nxt, cur
            level += 1
        return min_level

4.7.137 - 2026-01-05 18:58:31 +0300 MSK

Kth Ancestor of a Tree Node
class TreeAncestor:

    def __init__(self, n: int, parent: List[int]):
        m = 1 + int(log2(n)) #at most 16 for this problem 
        self.dp = [[-1] * m for _ in range(n)] #ith node's 2^j parent
        for j in range(m):
            for i in range(n):
                if j == 0: 
                    self.dp[i][0] = parent[i] 
                elif self.dp[i][j-1] != -1: 
                    self.dp[i][j] = self.dp[self.dp[i][j-1]][j-1]
    
    def getKthAncestor(self, node: int, k: int) -> int:
        while k > 0 and node != -1: 
            i = int(log2(k))
            node = self.dp[node][i]
            k -= (1 << i)
        return node 

4.7.138 - 2026-01-05 14:24:49 +0300 MSK

Design a Text Editor
class Node:
    def __init__(
        self, 
        char: str, 
        prev: Optional["Node"], 
        nxt: Optional["Node"]
    ) -> None:
        self.char = char
        self.prev = prev
        self.nxt = nxt

class TextEditor:

    def __init__(self):
        self.length = 0
        self.root = Node("", None, None)
        self.cursor = self.root

    def addText(self, text: str) -> None:
        node = self.cursor
        self.length += len(text)
        for char in text:
            cur = Node(char, node, node.nxt)
            nxt = node.nxt
            node.nxt = cur
            if nxt:
                nxt.prev = cur
            node = cur
            self.cursor = cur

    def deleteText(self, k: int) -> int:
        res = 0
        while self.cursor is not self.root and k > 0:
            res += 1
            k -= 1
            if self.cursor.nxt:
                self.cursor.nxt.prev = self.cursor.prev
            self.cursor.prev.nxt = self.cursor.nxt
            self.cursor = self.cursor.prev
        return res

    def last_ten(self) -> str:
        res = []
        node = self.cursor
        while node is not self.root and len(res) < 10:
            res.append(node.char)
            node = node.prev
        res.reverse()
        return "".join(res)

    def cursorLeft(self, k: int) -> str:
        while self.cursor is not self.root and k > 0:
            k -= 1
            self.cursor = self.cursor.prev
        res = self.last_ten()
        return res

    def cursorRight(self, k: int) -> str:
        while self.cursor.nxt  and k > 0:
            k -= 1
            self.cursor = self.cursor.nxt
        res = self.last_ten()
        return res

# Your TextEditor object will be instantiated and called as such:
# obj = TextEditor()
# obj.addText(text)
# param_2 = obj.deleteText(k)
# param_3 = obj.cursorLeft(k)
# param_4 = obj.cursorRight(k)

4.7.139 - 2026-01-05 12:30:08 +0300 MSK

Maximum Matrix Sum
class Solution:
    def maxMatrixSum(self, matrix: List[List[int]]) -> int:
        heap = []
        min_pos = float("inf")
        res = 0
        for row in matrix:
            for col in row:
                if col < 0:
                    heapq.heappush(heap, col)
                else:
                    res += col
                    min_pos = min(min_pos, col)
        while len(heap) >= 2:
            res += -(heapq.heappop(heap) + heapq.heappop(heap))
        if not heap:
            return res
        last = heap.pop()
        if min_pos == float("inf"):
            return res + last
        return max(res + last, (res - min_pos) - (min_pos + last))
         

4.7.140 - 2026-01-04 21:18:13 +0300 MSK

Four Divisors
class Solution:
    def sumFourDivisors(self, nums: list[int]) -> int:
        res = 0
        for n in nums:
            val = self.sumOne(n)
            if val != -1:
                res += val
        return res

    def sumOne(self, n: int) -> int:
        p = round(n ** (1/3))
        if p ** 3 == n and self.isPrime(p):
            return 1 + p + p*p + p*p*p

        for i in range(2, int(n ** 0.5) + 1):
            if n % i == 0:
                a, b = i, n // i
                if a != b and self.isPrime(a) and self.isPrime(b):
                    return 1 + a + b + n
                return -1
        return -1

    def isPrime(self, x: int) -> bool:
        if x < 2:
            return False
        for i in range(2, int(x ** 0.5) + 1):
            if x % i == 0:
                return False
        return True

4.7.141 - 2026-01-03 13:57:12 +0300 MSK

Number of Ways to Paint N × 3 Grid
class Solution:
    def numOfWays(self, n: int) -> int:
        MOD = 10**9 + 7
        A = B = 6

        for _ in range(2, n + 1):
            A, B = (2*A + 2*B) % MOD, (2*A + 3*B) % MOD

        return (A + B) % MOD

4.7.142 - 2026-01-02 16:54:09 +0300 MSK

Stream of Characters
class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = {}
        self.min_length = float("inf")
        for word in words:
            node = self.trie
            self.min_length = min(self.min_length, len(word))
            for char in reversed(word):
                if char not in node:
                    node[char] = {}
                node = node[char]
            node["is_word"] = True 
        self.letters = []

    def query(self, letter: str) -> bool:
        self.letters.append(letter)
        if len(self.letters) < self.min_length:
            return False
        node = self.trie
        for letter in reversed(self.letters):
            if letter not in node:
                return False
            if node[letter].get("is_word"):
                return True
            node = node[letter]
        return False
            



# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

4.7.143 - 2026-01-02 16:49:02 +0300 MSK

Stream of Characters
class StreamChecker:

    def __init__(self, words: List[str]):
        self.trie = {}
        self.lengths = set() 
        for word in words:
            node = self.trie
            self.lengths.add(len(word))
            for char in word:
                if char not in node:
                    node[char] = {}
                node = node[char]
            node["is_word"] = True 
        self.letters = []

    def query(self, letter: str) -> bool:
        self.letters.append(letter)
        
        for length in self.lengths:
            if length > len(self.letters):
                continue
            node = self.trie
            was_break = False
            for letter in self.letters[-length:]:
                if letter not in node:
                    was_break = True
                    break
                node = node[letter]
            if was_break:
                continue
            if node.get("is_word", False):
                return True

        return False
            



# Your StreamChecker object will be instantiated and called as such:
# obj = StreamChecker(words)
# param_1 = obj.query(letter)

4.7.144 - 2026-01-02 10:21:34 +0300 MSK

N-Repeated Element in Size 2N Array
class Solution:
    def repeatedNTimes(self, nums: List[int]) -> int:
        enc = set()
        for num in nums:
            if num in enc:
                return num
            enc.add(num)
        raise Exception

4.7.145 - 2026-01-01 13:06:44 +0300 MSK

RLE Iterator
class RLEIterator:

    def __init__(self, encoding: List[int]):
        self.i, self.enc, self.length = 0, encoding, len(encoding)

    def next(self, n: int) -> int:
        while self.i < self.length and  n > 0:
            count = self.enc[self.i]
            if count == 0:
                self.i += 2
            elif count >= n:
                self.enc[self.i] -= n
                return self.enc[self.i + 1]
            else:
                n -= count
                self.i += 2
        return -1

# Your RLEIterator object will be instantiated and called as such:
# obj = RLEIterator(encoding)
# param_1 = obj.next(n)

4.7.146 - 2026-01-01 13:05:15 +0300 MSK

RLE Iterator
class RLEIterator:

    def __init__(self, encoding: List[int]):
        self.enc = encoding
        self.enc.reverse()

    def next(self, n: int) -> int:
        while self.enc and n > 0:
            count = self.enc[-1]
            if count == 0:
                self.enc.pop()
                self.enc.pop()
            elif count >= n:
                self.enc[-1] -= n
                return self.enc[-2]
            else:
                n -= count
                self.enc.pop()
                self.enc.pop()
        return -1

# Your RLEIterator object will be instantiated and called as such:
# obj = RLEIterator(encoding)
# param_1 = obj.next(n)

4.7.147 - 2026-01-01 12:27:10 +0300 MSK

Plus One
class Solution:
    def plusOne(self, digits: List[int]) -> List[int]:
        for i in reversed(range(len(digits))):
            dig = digits[i] + 1
            if dig == 10:
                digits[i] = 0
                if i == 0:
                    digits.insert(0, 1)
            else:
                digits[i] = dig
                break
        return digits

4.7.148 - 2025-12-31 18:07:08 +0300 MSK

Last Day Where You Can Still Cross
class Solution:
    def latestDayToCross(self, row: int, col: int, cells: list[list[int]]) -> int:
        dsu = DSU(row * col + 2)
        grid = [[0] * col for _ in range(row)]
        dirs = [(0, 1), (0, -1), (1, 0), (-1, 0), (1, 1), (1, -1), (-1, 1), (-1, -1)]

        for i in range(row * col):
            r = cells[i][0] - 1
            c = cells[i][1] - 1
            grid[r][c] = 1

            id1 = r * col + c + 1
            for dr, dc in dirs:
                nr, nc = r + dr, c + dc
                if 0 <= nr < row and 0 <= nc < col and grid[nr][nc] == 1:
                    id2 = nr * col + nc + 1
                    dsu.union(id1, id2)

            if c == 0:
                dsu.union(0, id1)
            if c == col - 1:
                dsu.union(row * col + 1, id1)

            if dsu.find(0) == dsu.find(row * col + 1):
                return i
        return -1


class DSU:
    def __init__(self, n):
        self.root = list(range(n))
        self.size = [1] * n

    def find(self, x):
        if self.root[x] != x:
            self.root[x] = self.find(self.root[x])
        return self.root[x]

    def union(self, x, y):
        rx = self.find(x)
        ry = self.find(y)
        if rx == ry:
            return
        if self.size[rx] > self.size[ry]:
            rx, ry = ry, rx
        self.root[rx] = ry
        self.size[ry] += self.size[rx]

4.7.149 - 2025-12-30 21:07:43 +0300 MSK

Magic Squares In Grid
class Solution:
    def numMagicSquaresInside(self, grid: List[List[int]]) -> int:
        ans = 0
        m = len(grid)
        n = len(grid[0])
        for row in range(m - 2):
            for col in range(n - 2):
                if self._isMagicSquare(grid, row, col):
                    ans += 1
        return ans

    def _isMagicSquare(self, grid, row, col):
        # The sequences are each repeated twice to account for
        # the different possible starting points of the sequence
        # in the magic square
        sequence = "2943816729438167"
        sequenceReversed = "7618349276183492"

        border = []
        # Flattened indices for bordering elements of 3x3 grid
        borderIndices = [0, 1, 2, 5, 8, 7, 6, 3]
        for i in borderIndices:
            num = grid[row + i // 3][col + (i % 3)]
            border.append(str(num))

        borderConverted = "".join(border)

        # Make sure the sequence starts at one of the corners
        return (
            grid[row][col] % 2 == 0
            and (
                sequence.find(borderConverted) != -1
                or sequenceReversed.find(borderConverted) != -1
            )
            and grid[row + 1][col + 1] == 5
        )

4.7.150 - 2025-12-29 19:39:26 +0300 MSK

Pyramid Transition Matrix

from functools import cache


class Solution:
    def pyramidTransition(self, bottom: str, allowed: List[str]) -> bool:
        # build up potential values for next rows based on allowed values
        tops = defaultdict(list)
        for key in allowed:
            tops[key[:2]].append(key[2])

        def gen_next_rows(full_items, all_valid=set(), i=0, cur=''):
            # handle when a base pair does not have a top option in allowed
            if any([item == [] for item in full_items]):
                return []

            # generated a full new line, add to set of valid options
            if i == len(full_items):
                all_valid.add(cur)
                return

            # full line is not complete, for each top option of current base pair,
            # use it and look at the options for the next base pair.
            for item in full_items[i]:
                gen_next_rows(full_items, all_valid, i + 1, cur + item)

            # all row options generated, return the options
            return all_valid

        seen = set()

        def find_next_row(last):
            n = len(last)
            # made it to the top with a valid top option for the row of length 2
            if n == 1:
                return True

            # Generate all potential options for the next row and try them.
            # For example 2: the list comprehension used in gen_next_rows would be
            # [['B', 'C'], ['B', 'C'], ['B', 'C']] for the next row choices after bottom
            options = gen_next_rows([tops[last[i:i + 2]] for i in range(n - 1)], set())

            # cache is useful here because the same sequence may appear more than once
            # as the pyramid builds up.
            for option in options:
                if option in seen:
                    continue
                if find_next_row(option):
                    return True
                seen.add(option)
            return False
        return find_next_row(bottom)

4.7.151 - 2025-12-28 16:38:30 +0300 MSK

Count Negative Numbers in a Sorted Matrix
class Solution:
    def countNegatives(self, grid: List[List[int]]) -> int:
        count = 0
        for row in reversed(grid):
            for col in reversed(row):
                if col < 0:
                    count += 1
                else:
                    break
        return count
                

4.7.152 - 2025-12-27 17:07:34 +0300 MSK

Meeting Rooms III
class Solution:
    def mostBooked(self, n: int, meetings: List[List[int]]) -> int:
        unused_rooms, used_rooms = list(range(n)), []
        heapify(unused_rooms)
        meeting_count = [0] * n
        for start, end in sorted(meetings):
            while used_rooms and used_rooms[0][0] <= start:
                _, room = heappop(used_rooms)
                heappush(unused_rooms, room)
            if unused_rooms:
                room = heappop(unused_rooms)
                heappush(used_rooms, [end, room])
            else:
                room_availability_time, room = heappop(used_rooms)
                heappush(
                    used_rooms,
                    [room_availability_time + end - start, room]
                )
            meeting_count[room] += 1
        return meeting_count.index(max(meeting_count))

4.7.153 - 2025-12-27 16:57:55 +0300 MSK

Throne Inheritance
class Node:
    def __init__(self,  name: str, parent: Optional["Node"] = None) -> None:
        self.name: str = name
        self.parent: Optional["Node"] = parent
        self.children: list[Node] = []
        self.dead: bool = False

    def __iter__(self) -> Generator["Node", None, None]:
        if not self.dead:
            yield self
        for child in self.children:
            yield from child

class ThroneInheritance:

    def __init__(self, kingName: str):
        self._root: Node = Node(kingName)
        self._nodes: dict[str, Node] = {
            kingName: self._root
        }

    def birth(self, parentName: str, childName: str) -> None:
        parent = self._nodes[parentName]
        child = Node(childName, parent)
        parent.children.append(child)
        self._nodes[childName] = child

    def death(self, name: str) -> None:
        node = self._nodes.pop(name)
        node.dead = True

    def getInheritanceOrder(self) -> List[str]:
        return list(node.name for node in self._root)


# Your ThroneInheritance object will be instantiated and called as such:
# obj = ThroneInheritance(kingName)
# obj.birth(parentName,childName)
# obj.death(name)
# param_3 = obj.getInheritanceOrder()

4.7.154 - 2025-12-27 16:45:10 +0300 MSK

Longest Uploaded Prefix
class LUPrefix:
    def __init__(self, n: int):
        self._start = {}
        self._end = {}

    def upload(self, video: int) -> None:
        if video - 1 not in self._end and video + 1 not in self._start:
            self._start[video] = video
            self._end[video] = video
        elif video - 1 in self._end and video + 1 in self._start:
            end = self._start.pop(video + 1)
            start = self._end.pop(video - 1)
            self._start[start] = end
            self._end[end] = start
        elif video -1 in self._end:
            start = self._end.pop(video - 1)
            self._start[start] = video
            self._end[video] = start
        elif video + 1 in self._start:
            end = self._start.pop(video + 1)
            self._start[video] = end
            self._end[end] = video

    def longest(self) -> int:
        return self._start.get(1, 0)

# Your LUPrefix object will be instantiated and called as such:
# obj = LUPrefix(n)
# obj.upload(video)
# param_2 = obj.longest()

4.7.155 - 2025-12-26 21:12:54 +0300 MSK

Iterator for Combination
class CombinationIterator:

    def __init__(self, characters: str, combinationLength: int):
        self._length: int = combinationLength
        self._chars: str = characters
        self._cur: list[str] = []
        self._gen = self._generator(0)
        self._nxt: Optional[str] = next(self._gen, None)
    
    def _generator(self, i: int) -> Generator[str, None, None]:
        if len(self._cur) == self._length:
            yield "".join(self._cur)
            return
        if i >= len(self._chars):
            return
        char = self._chars[i]
        self._cur.append(char)
        yield from self._generator(i + 1)
        self._cur.pop()
        yield from self._generator(i + 1)

    def next(self) -> str:
        nxt = self._nxt
        self._nxt = next(self._gen, None)
        return nxt

    def hasNext(self) -> bool:
        return self._nxt is not  None


# Your CombinationIterator object will be instantiated and called as such:
# obj = CombinationIterator(characters, combinationLength)
# param_1 = obj.next()
# param_2 = obj.hasNext()

4.7.156 - 2025-12-26 14:01:28 +0300 MSK

Minimum Penalty for a Shop
class Solution:
    def bestClosingTime(self, customers: str) -> int:
        j, min_pen = len(customers), customers.count("N")
        cur_pen = min_pen
        for i in reversed(range(len(customers))):
            if customers[i] == "Y":
                cur_pen += 1
            else:
                cur_pen -= 1
            if cur_pen <= min_pen:
                j, min_pen = i, cur_pen
        return j

4.7.157 - 2025-12-25 20:08:37 +0300 MSK

Maximize Happiness of Selected Children
class Solution:
    def maximumHappinessSum(self, happiness: List[int], k: int) -> int:
        happiness.sort()
        res = 0
        for i in range(k):
            res += max(0, happiness.pop() - i)
        return res

4.7.158 - 2025-12-25 20:05:52 +0300 MSK

Maximize Happiness of Selected Children
class Solution:
    def maximumHappinessSum(self, happiness: List[int], k: int) -> int:
        happiness.sort(reverse=True)
        happiness = happiness[:k]
        res = 0
        for i in range(len(happiness)):
            res += max(0, happiness[i] - i)
        return res

4.7.159 - 2025-12-24 15:28:01 +0300 MSK

Apple Redistribution into Boxes
class Solution:
    def minimumBoxes(self, apple: List[int], capacity: List[int]) -> int:
        count = sum(apple)
        capacity.sort()
        res = 0
        while count > 0:
            res += 1
            count -= capacity.pop()
        return res

4.7.160 - 2025-12-24 14:24:51 +0300 MSK

House Robber II
class Solution:
    def rob(self, nums: List[int]) -> int:
        n = len(nums)
        if n == 1:
            return nums[0]

        def dp(i, j, memo: dict):
            if i == j:
                return 0
            if i == j-1:
                return nums[j-1]
            if (i, j) not in memo:
                rob = nums[i] + dp(i+2, j, memo)
                skip = dp(i+1, j, memo)
                memo[(i, j)] = max(rob, skip)
            return memo[(i, j)]
        return max(dp(0, n-1, {}), dp(1, n, {}))

4.7.161 - 2025-12-24 13:58:01 +0300 MSK

Path Sum II
# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def pathSum(self, root: Optional[TreeNode], targetSum: int) -> List[List[int]]:
        res, cur = [], []
        
        def dfs(node: Optional[TreeNode], cur_sum: int) -> None:
            if node is None:
                return
            cur_sum += node.val
            cur.append(node.val)
            if node.right or node.left:
                dfs(node.left, cur_sum)
                dfs(node.right, cur_sum)
            elif cur_sum == targetSum:
                res.append(cur.copy())
            cur.pop()

        dfs(root, 0)
        return res

4.7.162 - 2025-12-24 13:51:10 +0300 MSK

Recover Binary Search Tree
class Solution:
    def recoverTree(self, root: Optional[TreeNode]) -> None:
        self.first = self.second = self.prev = None

        def inorder(node):
            if not node:
                return
            inorder(node.left)
            if self.prev and self.prev.val > node.val:
                if not self.first:
                    self.first = self.prev
                self.second = node
            self.prev = node
            inorder(node.right)

        inorder(root)

        # Swap the values
        self.first.val, self.second.val = self.second.val, self.first.val

4.7.163 - 2025-12-24 13:44:07 +0300 MSK

Top K Frequent Elements
class Solution:
    def topKFrequent(self, nums: List[int], k: int) -> List[int]:
        heap = []
        freqs = defaultdict(int)
        for num in nums:
            freqs[num] += 1
            freq = freqs[num]
            heapq.heappush(heap, (-freq, num))
        res = set()
        while k > 0:
            _, num = heapq.heappop(heap)
            if num not in res:
                k -= 1
                res.add(num)
        return list(res)

4.7.164 - 2025-12-24 12:18:23 +0300 MSK

H-Index II
class Solution:
    def hIndex(self, citations: List[int]) -> int:
        left, right = 0, len(citations) - 1
        h = 0
        while left <= right:
            mid = left + (right - left) // 2
            count = len(citations) - mid
            val = citations[mid]
            h = max(h, min(count, val))
            if count >= val:
                left = mid + 1
            else:
                right = mid - 1
        return h

4.7.165 - 2025-12-23 19:29:34 +0300 MSK

Search a 2D Matrix II
class Solution:
    def searchMatrix(self, matrix: List[List[int]], target: int) -> bool:
        r = 0
        c = len(matrix[0])-1

        while r < len(matrix) and c >= 0:
            if matrix[r][c] == target:
                return True
            elif matrix[r][c] > target:
                c -= 1
            else:
                r += 1

        return False                

4.7.166 - 2025-12-23 18:39:29 +0300 MSK

Two Best Non-Overlapping Events
class Solution:
    def maxTwoEvents(self, events):
        times = []
        for e in events:
            # 1 denotes start time.
            times.append([e[0], 1, e[2]])
            # 0 denotes end time.
            times.append([e[1] + 1, 0, e[2]])

        ans, max_value = 0, 0
        times.sort()

        for time_value in times:
            # If current time is a start time, find maximum sum of maximum end
            # time till now.
            if time_value[1]:
                ans = max(ans, time_value[2] + max_value)
            else:
                max_value = max(max_value, time_value[2])

        return ans

4.7.167 - 2025-12-22 19:27:46 +0300 MSK

Delete Columns to Make Sorted III
class Solution(object):
    def minDeletionSize(self, A):
        W = len(A[0])
        dp = [1] * W
        for i in range(W-2, -1, -1):
            for j in range(i+1, W):
                if all(row[i] <= row[j] for row in A):
                    dp[i] = max(dp[i], 1 + dp[j])

        return W - max(dp)

4.7.168 - 2025-12-22 16:40:19 +0300 MSK

Minimum Deletion Cost to Make All Characters Equal
class Solution:
    def minCost(self, s: str, cost: List[int]) -> int:
        costs = [0] * 26
        for i in range(len(s)):
            char, cur_cost = s[i], cost[i]
            char_val = ord(char) - ord("a")
            for j in range(26):
                if j != char_val:
                    costs[j] += cur_cost
        res = float("inf")
        for cost in costs:
            res = min(res, cost)
        return res

4.7.169 - 2025-12-22 16:34:47 +0300 MSK

Mirror Distance of an Integer
class Solution:
    def mirrorDistance(self, n: int) -> int:
        dig = []
        orig = n
        while n > 0:
            dig.append(n % 10)
            n //= 10
        res = 0
        cur = 0
        while dig:
            res += dig.pop() * (10 ** cur)
            cur += 1
        return abs(orig - res)

4.7.170 - 2025-12-21 20:30:45 +0300 MSK

Delete Columns to Make Sorted II
class Solution(object):
    def minDeletionSize(self, A):
        cuts = [False] * (len(A) - 1)
        ans = 0
        for col in zip(*A):
            if all(cuts[i] or col[i] <= col[i+1] for i in range(len(col) - 1)):
                for i in range(len(col) - 1):
                    if col[i] < col[i+1]:
                        cuts[i] = True
            else:
                ans += 1
        return ans

4.7.171 - 2025-12-20 19:15:02 +0300 MSK

Delete Columns to Make Sorted
class Solution:
    def minDeletionSize(self, strs: List[str]) -> int:
        res = 0
        for col in range(len(strs[0])):
            prev = 0
            for row in range(len(strs)):
                char = ord(strs[row][col])
                if char >= prev:
                    prev = char
                else:
                    res += 1
                    break
        return res

4.7.172 - 2025-12-20 19:14:25 +0300 MSK

Find All People With Secret
package main

import (
	"sort"
)

func find(groups []int, index int) int {
	for index != groups[index] {
		index = groups[index]
	}
	return index
}

func findAllPeople(n int, meetings [][]int, firstPerson int) []int {
	groups := make([]int, 100000)
	var result []int
	var temp []int

	for i := 0; i < n; i++ {
		groups[i] = i
	}
	groups[firstPerson] = 0

	sort.Slice(meetings, func(i, j int) bool {
		return meetings[i][2] < meetings[j][2]
	})

	i := 0
	for i < len(meetings) {
		currentTime := meetings[i][2]
		temp = temp[:0]
		for i < len(meetings) && meetings[i][2] == currentTime {
			g1 := find(groups, meetings[i][0])
			g2 := find(groups, meetings[i][1])
			groups[max(g1, g2)] = min(g1, g2)
			temp = append(temp, meetings[i][0], meetings[i][1])
			i++
		}
		for _, j := range temp {
			if find(groups, j) != 0 {
				groups[j] = j
			}
		}
	}

	for j := 0; j < n; j++ {
		if find(groups, j) == 0 {
			result = append(result, j)
		}
	}

	return result
}

func max(a, b int) int {
	if a > b {
		return a
	}
	return b
}

func min(a, b int) int {
	if a < b {
		return a
	}
	return b
}

4.7.173 - 2025-12-18 21:06:02 +0300 MSK

Best Time to Buy and Sell Stock using Strategy
class Solution:
    def maxProfit(self, prices: List[int], strategy: List[int], k: int) -> int:
        native_profit = 0
        native_segment = 0
        changed_segment = 0
        max_changed_segment = 0
        for i in range(len(prices)):
            price = prices[i]
            native_profit += price * strategy[i]
            native_segment += price * strategy[i]
            if i + 1 <= k // 2:
                pass
            elif i + 1 < k :
                changed_segment += price
            elif i  + 1 == k:
                changed_segment += price
                max_changed_segment = max(max_changed_segment, changed_segment - native_segment)
            else:
                changed_segment += price - prices[i - (k // 2)]
                native_segment -= prices[i - k] * strategy[i - k]
                max_changed_segment = max(max_changed_segment, changed_segment - native_segment)

        return max(native_profit, native_profit + max_changed_segment)                

4.7.174 - 2025-12-17 08:08:52 +0300 MSK

Best Time to Buy and Sell Stock V
class Solution:
    def maximumProfit(self, prices: List[int], k: int) -> int:
        n = len(prices)
        dp = [[0] * 3 for _ in range(k + 1)]
        # initialize the state on day 0
        for j in range(1, k + 1):
            dp[j][1] = -prices[0]
            dp[j][2] = prices[0]

        for i in range(1, n):
            for j in range(k, 0, -1):
                dp[j][0] = max(
                    dp[j][0], max(dp[j][1] + prices[i], dp[j][2] - prices[i])
                )
                dp[j][1] = max(dp[j][1], dp[j - 1][0] - prices[i])
                dp[j][2] = max(dp[j][2], dp[j - 1][0] + prices[i])

        return dp[k][0]

4.7.175 - 2025-12-16 20:00:23 +0300 MSK

Absolute Difference Between Maximum and Minimum K Elements
class Solution:
    def absDifference(self, nums: List[int], k: int) -> int:
        nums.sort()
        return abs(sum(nums[:k]) - sum(nums[-k:]))

4.7.176 - 2025-12-16 19:58:35 +0300 MSK

Sort Integers by Binary Reflection
class Solution:
    def sortByReflection(self, nums: List[int]) -> List[int]:

        reverse = lambda num: int(bin(num)[-1:1:-1], 2)     # <--1)
        nums.sort(key = lambda x: (reverse(x), x))          # <--2)

        return nums

4.7.177 - 2025-12-16 19:57:10 +0300 MSK

Concatenate Non-Zero Digits and Multiply by Sum I
class Solution:
    def sumAndMultiply(self, n: int) -> int:
        cur = 0
        dig_sum, num = 0, 0
        while n > 0:
            dig = n % 10
            n //= 10
            if dig != 0:
                dig_sum += dig
                num += dig * (10 ** cur)
                cur += 1
        return num * dig_sum

4.7.178 - 2025-12-16 19:53:04 +0300 MSK

Minimum Number of Flips to Reverse Binary String
class Solution:
    def minimumFlips(self, n: int) -> int:
        bits = []
        while n > 0:
            bits.append(n % 2)
            n //= 2
        print(bits)
        res = 0
        for i in range(len(bits) // 2):
            if bits[i] != bits[-i-1]:
                res += 2
        return res

4.7.179 - 2025-12-16 19:48:24 +0300 MSK

Maximize Expression of Three Elements
class Solution:
    def maximizeExpressionOfThree(self, nums: List[int]) -> int:
        nums.sort()
        return  nums.pop() + nums.pop() - nums[0]

4.7.180 - 2025-12-16 19:46:51 +0300 MSK

Minimum Distance Between Three Equal Elements I
import collections

class Solution:
    def minimumDistance(self, nums: list[int]) -> int:
        idx1 = {}
        idx2 = {}
        res = float("inf")
        for i, num in enumerate(nums):
            if num in idx2:
                dist = abs(idx1[num] - idx2[num]) + abs(idx2[num] - i) + abs(i - idx1[num])
                res = min(res, dist)
                idx1[num] = idx2[num]
                idx2[num] = i
            elif num in idx1:
                idx2[num] = i
            else:
                idx1[num] = i
        if res == float("inf"):
            return -1
        return res

4.7.181 - 2025-12-16 19:33:50 +0300 MSK

Minimum Moves to Equal Array Elements III
class Solution:
    def minMoves(self, nums: List[int]) -> int:
        target = max(nums)
        res = 0
        for num in nums:
            res += target - num
        return res

4.7.182 - 2025-12-16 19:32:04 +0300 MSK

Find Missing Elements
class Solution:
    def findMissingElements(self, nums: List[int]) -> List[int]:
        nums.sort()
        res = []
        for i in range(1, len(nums)):
            cur, prev = nums[i], nums[i - 1]
            res.extend(range(prev + 1, cur))
        return res

4.7.183 - 2025-12-16 19:29:16 +0300 MSK

Remove Zeros in Decimal Representation
class Solution:
    def removeZeros(self, n: int) -> int:
        cur = 0
        res = 0
        while n > 0:
            dig = n % 10
            if dig != 0:
                res += dig * (10 ** cur)
                cur += 1
            n //= 10
        return res 

4.7.184 - 2025-12-16 19:26:34 +0300 MSK

Smallest Missing Multiple of K
class Solution:
    def missingMultiple(self, nums: List[int], k: int) -> int:
        enc = set(nums)
        cur = k
        while True:
            if cur in enc:
                cur += k
            else:
                return cur

4.7.185 - 2025-12-16 19:23:42 +0300 MSK

Sum of Elements With Frequency Divisible by K
class Solution:
    def sumDivisibleByK(self, nums: List[int], k: int) -> int:
        freq = [0] * 101
        for num in nums:
            freq[num] += 1
        res = 0
        for num, freq in enumerate(freq):
            if freq != 0 and freq % k == 0:
                res += num * freq
        return res
        

4.7.186 - 2025-12-16 19:02:03 +0300 MSK

Maximum Profit from Trading Stocks with Discounts
class Solution:
    def maxProfit(
        self,
        n: int,
        present: List[int],
        future: List[int],
        hierarchy: List[List[int]],
        budget: int,
    ) -> int:
        g = [[] for _ in range(n)]
        for e in hierarchy:
            g[e[0] - 1].append(e[1] - 1)

        def dfs(u: int):
            cost = present[u]
            dCost = present[u] // 2

            # dp[u][state][budget]
            # state = 0: Do not purchase parent node, state = 1: Must purchase parent node
            dp0 = [0] * (budget + 1)
            dp1 = [0] * (budget + 1)

            # subProfit[state][budget]
            # state = 0: discount not available, state = 1: discount available
            subProfit0 = [0] * (budget + 1)
            subProfit1 = [0] * (budget + 1)
            uSize = cost

            for v in g[u]:
                child_dp0, child_dp1, vSize = dfs(v)
                uSize += vSize
                for i in range(budget, -1, -1):
                    for sub in range(min(vSize, i) + 1):
                        if i - sub >= 0:
                            subProfit0[i] = max(
                                subProfit0[i],
                                subProfit0[i - sub] + child_dp0[sub],
                            )
                            subProfit1[i] = max(
                                subProfit1[i],
                                subProfit1[i - sub] + child_dp1[sub],
                            )

            for i in range(budget + 1):
                dp0[i] = subProfit0[i]
                dp1[i] = subProfit0[i]
                if i >= dCost:
                    dp1[i] = max(
                        subProfit0[i], subProfit1[i - dCost] + future[u] - dCost
                    )
                if i >= cost:
                    dp0[i] = max(
                        subProfit0[i], subProfit1[i - cost] + future[u] - cost
                    )

            return dp0, dp1, uSize

        return dfs(0)[0][budget]

4.7.187 - 2025-12-15 21:33:29 +0300 MSK

Number of Smooth Descent Periods of a Stock
class Solution:
    def getDescentPeriods(self, prices: List[int]) -> int:
        n = len(prices)
        res = 1  # total number of smooth descending periods, initial value is dp[0]
        prev = 1  # total number of smooth descending periods ending with the previous element, initial value is dp[0]
        # traverse the array starting from 1, and update prev and the total res according to the recurrence relation
        for i in range(1, n):
            if prices[i] == prices[i - 1] - 1:
                prev += 1
            else:
                prev = 1
            res += prev
        return res

4.7.188 - 2025-12-14 20:42:06 +0300 MSK

Number of Ways to Divide a Long Corridor
class Solution {
public:
    // Store 1000000007 in a variable for convenience
    const int MOD = 1e9 + 7;
    
    // Count the number of ways to divide from "index" to the last index
    // with "seats" number of "S" in the current section
    int count(int index, int seats, string& corridor, int cache[][3]) {
        // If we have reached the end of the corridor, then
        // the current section is valid only if "seats" is 2
        if (index == corridor.length()) {
            return seats == 2 ? 1 : 0;
        }

        // If we have already computed the result of this sub-problem,
        // then return the cached result
        if (cache[index][seats] != -1) {
            return cache[index][seats];
        }

        // Result of the sub-problem
        int result = 0;

        // If the current section has exactly 2 "S"
        if (seats == 2) {
            // If the current element is "S", then we have to close the
            // section and start a new section from this index. Next index
            // will have one "S" in the current section
            if (corridor[index] == 'S') {
                result = count(index + 1, 1, corridor, cache);
            } else {
                // If the current element is "P", then we have two options
                // 1. Close the section and start a new section from this index
                // 2. Keep growing the section
                result = (count(index + 1, 0, corridor, cache) + count(index + 1, 2, corridor, cache)) % MOD;  
            }
        } else {
            // Keep growing the section. Increment "seats" if present
            // element is "S"
            if (corridor[index] == 'S') {
                result = count(index + 1, seats + 1, corridor, cache);
            } else {
                result = count(index + 1, seats, corridor, cache);
            }
        }

        // Memoize the result, and return it
        cache[index][seats] = result;
        return cache[index][seats];
    }

    int numberOfWays(string corridor) {
        // Cache the result of each sub-problem
        int cache[corridor.length()][3];
        memset(cache, -1, sizeof(cache));

        // Call the count function
        return count(0, 0, corridor, cache);
    }
};

4.7.189 - 2025-12-13 20:21:05 +0300 MSK

Coupon Code Validator
class Solution:
    def validateCoupons(self, code: List[str], businessLine: List[str], isActive: List[bool]) -> List[str]:
        res, n = [], len(code)
        b_order = {"electronics": 0, "grocery": 1, "pharmacy": 2, "restaurant": 3}
        for i in range(n):
            if (
                isActive[i] 
                and code[i] 
                and re.match("^[a-zA-Z0-9_]+$", code[i]) 
                and businessLine[i] in (
                    "electronics", "grocery", "pharmacy", "restaurant"
                )
            ):
                res.append(i)
        def sort(i: int) -> tuple[str, str]:
            return (b_order[businessLine[i]], code[i])
        res.sort(key=sort)
        for i in range(len(res)):
            res[i] = code[res[i]]
        return res

4.7.190 - 2025-12-13 20:20:09 +0300 MSK

Count Mentions Per User
class Solution:
    def countMentions(
        self, numberOfUsers: int, events: List[List[str]]
    ) -> List[int]:
        events.sort(key=lambda e: (int(e[1]), e[0] == "MESSAGE"))
        count = [0] * numberOfUsers
        next_online_time = [0] * numberOfUsers
        for event in events:
            cur_time = int(event[1])
            if event[0] == "MESSAGE":
                if event[2] == "ALL":
                    for i in range(numberOfUsers):
                        count[i] += 1
                elif event[2] == "HERE":
                    for i, t in enumerate(next_online_time):
                        if t <= cur_time:
                            count[i] += 1
                else:
                    for idx in event[2].split():
                        count[int(idx[2:])] += 1
            else:
                next_online_time[int(event[2])] = cur_time + 60
        return count

4.7.191 - 2025-12-11 14:20:50 +0300 MSK

Count Covered Buildings
class Solution:
    def countCoveredBuildings(self, n: int, buildings: List[List[int]]) -> int:
        max_row = [0] * (n + 1)
        min_row = [n + 1] * (n + 1)
        max_col = [0] * (n + 1)
        min_col = [n + 1] * (n + 1)

        for p in buildings:
            x, y = p[0], p[1]
            max_row[y] = max(max_row[y], x)
            min_row[y] = min(min_row[y], x)
            max_col[x] = max(max_col[x], y)
            min_col[x] = min(min_col[x], y)

        res = 0
        for p in buildings:
            x, y = p[0], p[1]
            if (
                x > min_row[y]
                and x < max_row[y]
                and y > min_col[x]
                and y < max_col[x]
            ):
                res += 1

        return res

4.7.192 - 2025-12-10 20:14:13 +0300 MSK

Count the Number of Computer Unlocking Permutations
class Solution:
    def countPermutations(self, complexity: List[int]) -> int:
        n = len(complexity)
        for i in range(1, n):
            if complexity[i] <= complexity[0]:
                return 0

        ans, mod = 1, 10**9 + 7
        for i in range(2, n):
            ans = ans * i % mod
        return ans

4.7.193 - 2025-12-09 20:31:56 +0300 MSK

Count Special Triplets
class Solution:
    def specialTriplets(self, nums: List[int]) -> int:
        MOD = 10**9 + 7
        pos = defaultdict(list)

        for i, v in enumerate(nums):
            pos[v].append(i)

        def upper_bound(arr, i):
            l, r = 0, len(arr) - 1
            while l < r:
                mid = l + ((r - l + 1) >> 1)
                if i >= arr[mid]:
                    l = mid
                else:
                    r = mid - 1
            return l + 1, len(arr) - 1 - l

        ans = 0
        for i in range(1, len(nums) - 1):
            target = nums[i] * 2
            if target in pos and len(pos[target]) > 1 and pos[target][0] < i:
                l, r = upper_bound(pos[target], i)
                if nums[i] == 0:
                    l -= 1
                ans = (ans + l * r) % MOD

        return ans

4.7.194 - 2025-12-08 20:20:12 +0300 MSK

Count Square Sum Triples
class Solution:
    def countTriples(self, n: int) -> int:
        res = 0
        for a in range(1, n):
            for b in range(a + 1, n):
                c = math.sqrt(a * a + b * b)
                if c % 1 == 0 and c <= n:
                    res += 2
        return res

4.7.195 - 2025-12-07 19:27:13 +0300 MSK

Count Odd Numbers in an Interval Range

func countOdds(low int, high int) int {
	low_even, high_even, half := (low&1) == 0, (high&1) == 0, (high-low)/2
	if low_even && high_even  {
		return half
	}
	return half + 1
}

4.7.196 - 2025-12-06 19:08:58 +0300 MSK

Count Partitions with Even Sum Difference
class Solution:
    def countPartitions(self, nums: List[int]) -> int:
        sm, n = [0] * len(nums), len(nums)
        sm[0] = nums[0]
        for i in range(n):
            sm[i] = sm[i - 1] + nums[i]
        res = 0
        for i in range(n - 1):
            left = sm[i]
            right = sm[-1] - left
            res += abs(right - left) % 2 == 0
        return res

4.7.197 - 2025-12-06 19:07:24 +0300 MSK

Count Partitions With Max-Min Difference at Most K
class Solution:
    def countPartitions(self, nums: List[int], k: int) -> int:
        n = len(nums)
        mod = 10**9 + 7
        dp = [0] * (n + 1)
        prefix = [0] * (n + 1)
        min_q = deque()
        max_q = deque()

        dp[0] = 1
        prefix[0] = 1
        j = 0

        for i in range(n):
            # maintain the maximum value queue
            while max_q and nums[max_q[-1]] <= nums[i]:
                max_q.pop()
            max_q.append(i)

            # maintain the minimum value queue
            while min_q and nums[min_q[-1]] >= nums[i]:
                min_q.pop()
            min_q.append(i)

            # adjust window
            while max_q and min_q and nums[max_q[0]] - nums[min_q[0]] > k:
                if max_q[0] == j:
                    max_q.popleft()
                if min_q[0] == j:
                    min_q.popleft()
                j += 1

            if j > 0:
                dp[i + 1] = (prefix[i] - prefix[j - 1] + mod) % mod
            else:
                dp[i + 1] = prefix[i] % mod
            prefix[i + 1] = (prefix[i] + dp[i + 1]) % mod

        return dp[n]

4.7.198 - 2025-12-04 19:31:16 +0300 MSK

Count Collisions on a Road
class Solution:
    def countCollisions(self, directions: str) -> int:
        dirs = directions.lstrip("L").rstrip("R")
        return len(dirs) - dirs.count("S")

4.7.199 - 2025-12-03 21:01:12 +0300 MSK

Count Number of Trapezoids II
class Solution:
    def countTrapezoids(self, points: List[List[int]]) -> int:
        n = len(points)
        inf = 10**9 + 7
        slope_to_intercept = defaultdict(list)
        mid_to_slope = defaultdict(list)
        ans = 0

        for i in range(n):
            x1, y1 = points[i]
            for j in range(i + 1, n):
                x2, y2 = points[j]
                dx = x1 - x2
                dy = y1 - y2

                if x2 == x1:
                    k = inf
                    b = x1
                else:
                    k = (y2 - y1) / (x2 - x1)
                    b = (y1 * dx - x1 * dy) / dx

                mid = (x1 + x2) * 10000 + (y1 + y2)
                slope_to_intercept[k].append(b)
                mid_to_slope[mid].append(k)

        for sti in slope_to_intercept.values():
            if len(sti) == 1:
                continue

            cnt = defaultdict(int)
            for b_val in sti:
                cnt[b_val] += 1

            total_sum = 0
            for count in cnt.values():
                ans += total_sum * count
                total_sum += count

        for mts in mid_to_slope.values():
            if len(mts) == 1:
                continue

            cnt = defaultdict(int)
            for k_val in mts:
                cnt[k_val] += 1

            total_sum = 0
            for count in cnt.values():
                ans -= total_sum * count
                total_sum += count

        return ans

4.7.200 - 2025-12-02 19:36:01 +0300 MSK

Count Number of Trapezoids I
class Solution:
    def countTrapezoids(self, points: List[List[int]]) -> int:
        point_num = defaultdict(int)
        mod = 10**9 + 7
        ans, total_sum = 0, 0
        for point in points:
            point_num[point[1]] += 1
        for p_num in point_num.values():
            edge = p_num * (p_num - 1) // 2
            ans = (ans + edge * total_sum) % mod
            total_sum = (total_sum + edge) % mod
        return ans

4.7.201 - 2025-12-01 19:36:43 +0300 MSK

Maximum Running Time of N Computers
class Solution:
    # n = 2, batteries = [3,3,3], Output: 4
    # n = 2, batteries = [1,1,1,1], Output: 2
    def maxRunTime(self, n: int, batteries: List[int]) -> int:
        length = len(batteries)

        if length < n:
            return 0
        
        if length == n:
            return min(batteries)

        batteries.sort()
        extra = sum(batteries[:-n])
        live = batteries[-n:]

        
        # We increase the total running time using 'extra' by increasing 
        # the running time of the computer with the smallest battery.
        for i in range(n - 1):
            # If the target running time is between live[i] and live[i + 1].
            if extra // (i + 1) < live[i + 1] - live[i]:
                return live[i] + extra // (i + 1)
            
            # Reduce 'extra' by the total power used.
            extra -= (i + 1) * (live[i + 1] - live[i])
        
        # If there is power left, we can increase the running time 
        # of all computers.
        return live[-1] + extra // n

4.7.202 - 2025-11-30 20:53:29 +0300 MSK

Make Sum Divisible by P
class Solution:
    def minSubarray(self, nums: List[int], p: int) -> int:
        n = len(nums)
        total_sum = 0

        # Step 1: Calculate total sum and target remainder
        for num in nums:
            total_sum = (total_sum + num) % p

        target = total_sum % p
        if target == 0:
            return 0  # The array is already divisible by p

        # Step 2: Use a dict to track prefix sum mod p
        mod_map = {
            0: -1
        }  # To handle the case where the whole prefix is the answer
        current_sum = 0
        min_len = n

        # Step 3: Iterate over the array
        for i in range(n):
            current_sum = (current_sum + nums[i]) % p

            # Calculate what we need to remove
            needed = (current_sum - target + p) % p

            # If we have seen the needed remainder, we can consider this subarray
            if needed in mod_map:
                min_len = min(min_len, i - mod_map[needed])

            # Store the current remainder and index
            mod_map[current_sum] = i

        # Step 4: Return result
        return -1 if min_len == n else min_len

4.7.203 - 2025-11-29 21:07:28 +0300 MSK

Minimum Operations to Make Array Sum Divisible by K
class Solution:
    def minOperations(self, nums: List[int], k: int) -> int:
        return sum(nums) % k

4.7.204 - 2025-11-28 20:52:48 +0300 MSK

Maximum Number of K-Divisible Components
class Solution:
    def maxKDivisibleComponents(
        self, n: int, edges: List[List[int]], values: List[int], k: int
    ) -> int:
        if n < 2:
            return 1
        component_count = 0
        graph = defaultdict(list)
        in_degree = [0 for _ in range(n)]

        # Build the graph and calculate in-degrees
        for node1, node2 in edges:
            graph[node1].append(node2)
            graph[node2].append(node1)
            in_degree[node1] += 1
            in_degree[node2] += 1

        # Initialize the queue with nodes having in-degree of 1 (leaf nodes)
        queue = deque(node for node in range(n) if in_degree[node] == 1)

        while queue:
            current_node = queue.popleft()
            in_degree[current_node] -= 1
            add_value = 0

            # Check if the current node's value is divisible by k
            if values[current_node] % k == 0:
                component_count += 1
            else:
                add_value = values[current_node]

            # Propagate the value to the neighbor nodes
            for neighbor_node in graph[current_node]:
                if in_degree[neighbor_node] == 0:
                    continue
                in_degree[neighbor_node] -= 1
                values[neighbor_node] += add_value

                # If the neighbor node's in-degree becomes 1, add it to the queue
                if in_degree[neighbor_node] == 1:
                    queue.append(neighbor_node)

        return component_count

4.7.205 - 2025-11-27 17:52:11 +0300 MSK

Maximum Subarray Sum With Length Divisible by K
class Solution:
    def maxSubarraySum(self, nums: List[int], k: int) -> int:
        n = len(nums)
        prefixSum = 0
        maxSum = -sys.maxsize
        kSum = [sys.maxsize // 2] * k
        kSum[k - 1] = 0
        for i in range(n):
            prefixSum += nums[i]
            maxSum = max(maxSum, prefixSum - kSum[i % k])
            kSum[i % k] = min(kSum[i % k], prefixSum)
        return maxSum

4.7.206 - 2025-11-26 18:06:00 +0300 MSK

Paths in Matrix Whose Sum Is Divisible by K
class Solution:
    def numberOfPaths(self, grid: List[List[int]], k: int) -> int:
        MOD = 10**9 + 7
        m, n = len(grid), len(grid[0])

        dp = [[[0] * k for _ in range(n + 1)] for _ in range(m + 1)]

        for i in range(1, m + 1):
            for j in range(1, n + 1):
                if i == 1 and j == 1:
                    dp[i][j][grid[0][0] % k] = 1
                    continue

                value = grid[i - 1][j - 1] % k
                for r in range(k):
                    prev_mod = (r - value + k) % k
                    dp[i][j][r] = (
                        dp[i - 1][j][prev_mod] + dp[i][j - 1][prev_mod]
                    ) % MOD

        return dp[m][n][0]

4.7.207 - 2025-11-25 19:49:04 +0300 MSK

Smallest Integer Divisible by K
class Solution:
    def smallestRepunitDivByK(self, K: int) -> int:
        remainder = 0
        for length_N in range(1,K+1):
            remainder = (remainder*10+1) % K
            if remainder == 0:
                return length_N
        return -1

4.7.208 - 2025-11-24 18:58:12 +0300 MSK

Binary Prefix Divisible By 5
class Solution:
    def prefixesDivBy5(self, nums: List[int]) -> List[bool]:
        cur = 0
        for i in range(len(nums)):
            cur <<= 1
            cur |= nums[i]
            nums[i] = cur % 5 == 0
        return nums

4.7.209 - 2025-11-23 18:20:29 +0300 MSK

Greatest Sum Divisible by Three
class Solution:
    def maxSumDivThree(self, nums: List[int]) -> int:
        f = [0, -float("inf"), -float("inf")]
        for num in nums:
            g = f[:]
            for i in range(3):
                g[(i + num % 3) % 3] = max(g[(i + num % 3) % 3], f[i] + num)
            f = g
        return f[0]

4.7.210 - 2025-11-22 17:51:32 +0300 MSK

Find Minimum Operations to Make All Elements Divisible by Three
class Solution:
    def minimumOperations(self, nums: List[int]) -> int:
        res = 0
        for i in range(len(nums)):
            res += nums[i] % 3 != 0
        return res

4.7.211 - 2025-11-21 17:40:54 +0300 MSK

Unique Length-3 Palindromic Subsequences
class Solution {
public:
    int countPalindromicSubsequence(string s) {
        unordered_set<char> letters;
        for (char c : s) {
            letters.insert(c);
        }
        int ans = 0;
        for (char letter : letters) {
            int i = -1;
            int j = 0;
            for (int k = 0; k < s.size(); k++) {
                if (s[k] == letter) {
                    if (i == -1) {
                        i = k;
                    }
                    
                    j = k;
                }
            }
            unordered_set<char> between;
            for (int k = i + 1; k < j; k++) {
                between.insert(s[k]);
            }
            
            ans += between.size();
        }
        return ans;
    }
};

4.7.212 - 2025-11-20 18:30:09 +0300 MSK

Set Intersection Size At Least Two
class Solution(object):
    def intersectionSizeTwo(self, intervals):
        intervals.sort(key =lambda val: (val[0], -val[1]))
        todo = [2] * len(intervals)
        ans = 0
        while intervals:
            (s, e), t = intervals.pop(), todo.pop()
            for p in range(s, s+t):
                for i, (s0, e0) in enumerate(intervals):
                    if todo[i] and p <= e0:
                        todo[i] -= 1
                ans += 1
        return ans

4.7.213 - 2025-11-19 18:01:12 +0300 MSK

Keep Multiplying Found Values by Two
class Solution:
    def findFinalValue(self, nums: List[int], original: int) -> int:
        nums.sort()
        length = len(nums)
        left, right = 0, length - 1
        while left <= right:
            i = left + (right - left) // 2
            val = nums[i]
            if val > original:
                right = i - 1
            elif val == original:
                original *= 2
                left = i + 1
                right = length - 1
            else:
                left = i + 1
        return original

4.7.214 - 2025-11-18 19:16:52 +0300 MSK

1-bit and 2-bit Characters
class Solution(object):
    def isOneBitCharacter(self, bits):
        i = 0
        while i < len(bits) - 1:
            i += bits[i] + 1
        return i == len(bits) - 1

4.7.215 - 2025-11-17 18:59:11 +0300 MSK

Check If All 1’s Are at Least Length K Places Away
class Solution:
    def kLengthApart(self, nums: List[int], k: int) -> bool:
        prev = -k - 1
        for i, num in enumerate(nums):
            if num == 0:
                continue
            if i - prev - 1 >= k:
                prev = i
            else:
                return False
        return True

4.7.216 - 2025-11-16 18:07:29 +0300 MSK

Number of Substrings With Only 1s
class Solution:
    def numSub(self, s: str) -> int:
        total, consecutive = 0, 0
        length = len(s)
        for i in range(length):
            if s[i] == "0":
                total += consecutive * (consecutive + 1) // 2
                consecutive = 0
            else:
                consecutive += 1

        total += consecutive * (consecutive + 1) // 2
        total %= 10**9 + 7
        return total

4.7.217 - 2025-11-15 18:41:02 +0300 MSK

Count the Number of Substrings With Dominant Ones
class Solution:
    def numberOfSubstrings(self, s: str) -> int:
        n = len(s)
        pre = [-1] * (n + 1)
        for i in range(n):
            if i == 0 or s[i - 1] == "0":
                pre[i + 1] = i
            else:
                pre[i + 1] = pre[i]

        res = 0
        for i in range(1, n + 1):
            cnt0 = 1 if s[i - 1] == "0" else 0
            j = i
            while j > 0 and cnt0 * cnt0 <= n:
                cnt1 = (i - pre[j]) - cnt0
                if cnt0 * cnt0 <= cnt1:
                    res += min(j - pre[j], cnt1 - cnt0 * cnt0 + 1)
                j = pre[j]
                cnt0 += 1
        return res

4.7.218 - 2025-11-14 15:39:54 +0300 MSK

Maximum Number of Operations to Move Ones to the End
class Solution:
    def maxOperations(self, s: str) -> int:
        count_one = 0
        ans = 0
        i = 0
        while i < len(s):
            if s[i] == "0":
                while i + 1 < len(s) and s[i + 1] == "0":
                    i += 1
                ans += count_one
            else:
                count_one += 1
            i += 1
        return ans

4.7.219 - 2025-11-14 15:39:21 +0300 MSK

Minimum Number of Operations to Make All Array Elements Equal to 1
class Solution:
    def minOperations(self, nums: List[int]) -> int:
        n = len(nums)
        num1 = 0
        g = 0

        for x in nums:
            if x == 1:
                num1 += 1
            g = gcd(g, x)

        if num1 > 0:
            return n - num1
        if g > 1:
            return -1

        min_len = n
        for i in range(n):
            g = 0
            for j in range(i, n):
                g = gcd(g, nums[j])
                if g == 1:
                    min_len = min(min_len, j - i + 1)
                    break

        return min_len + n - 2

4.7.220 - 2025-11-14 15:38:45 +0300 MSK

Increment Submatrices by One
class Solution:
    def rangeAddQueries(
        self, n: int, queries: List[List[int]]
    ) -> List[List[int]]:
        diff = [[0] * (n + 1) for _ in range(n + 1)]
        for row1, col1, row2, col2 in queries:
            diff[row1][col1] += 1
            diff[row2 + 1][col1] -= 1
            diff[row1][col2 + 1] -= 1
            diff[row2 + 1][col2 + 1] += 1

        mat = [[0] * n for _ in range(n)]
        for i in range(n):
            for j in range(n):
                x1 = 0 if i == 0 else mat[i - 1][j]
                x2 = 0 if j == 0 else mat[i][j - 1]
                x3 = 0 if i == 0 or j == 0 else mat[i - 1][j - 1]
                mat[i][j] = diff[i][j] + x1 + x2 - x3
        return mat

4.7.221 - 2025-11-11 19:43:26 +0300 MSK

Ones and Zeroes
class Solution:
    def findMaxForm(self, strs: List[str], m: int, n: int) -> int:
        dp = {(0, 0): 0}

        for s in strs:
            ones = 0
            zeroes = 0
            for ch in s:
                if ch == "0":
                    zeroes += 1
                else:
                    ones += 1
            newdp = {}

            for k, v in dp.items():
                prevzeroes, prevones = k
                newzeroes, newones = prevzeroes + zeroes, prevones + ones
                if newzeroes <= m and newones <= n:
                    if (newzeroes, newones) not in dp:
                        newdp[(newzeroes, newones)] = v + 1

                    elif dp[(newzeroes, newones)] < v + 1:
                        newdp[(newzeroes, newones)] = v + 1
            dp.update(newdp)
        return max(dp.values())

4.7.222 - 2025-11-10 19:49:56 +0300 MSK

Minimum Operations to Convert All Elements to Zero
class Solution:
    def minOperations(self, nums: List[int]) -> int:
        s = []
        res = 0
        for a in nums:
            while s and s[-1] > a:
                s.pop()
            if a == 0:
                continue
            if not s or s[-1] < a:
                res += 1
                s.append(a)
        return res

4.7.223 - 2025-11-09 17:05:22 +0300 MSK

Count Operations to Obtain Zero
class Solution:
    def countOperations(self, num1: int, num2: int) -> int:
        count = 0
        while num1 > 0 and num2 > 0:
            if num1 >= num2:
                count += num1 // num2
                num1 %= num2
            else:
                count += num2 // num1
                num2 %= num1
        return count

4.7.224 - 2025-11-08 22:09:46 +0300 MSK

Minimum One Bit Operations to Make Integers Zero
class Solution:
    def minimumOneBitOperations(self, n: int) -> int:
        if n == 0:
            return 0
        
        k = 0
        curr = 1
        while (curr * 2) <= n:
            curr *= 2
            k += 1

        return 2 ** (k + 1) - 1 - self.minimumOneBitOperations(n ^ curr)

4.7.225 - 2025-11-07 20:28:33 +0300 MSK

Maximize the Minimum Powered City
class Solution:
    def maxPower(self, stations: List[int], r: int, k: int) -> int:
        n = len(stations)
        cnt = [0] * (n + 1)

        for i in range(n):
            left = max(0, i - r)
            right = min(n, i + r + 1)
            cnt[left] += stations[i]
            cnt[right] -= stations[i]

        def check(val: int) -> bool:
            diff = cnt.copy()
            total = 0
            remaining = k

            for i in range(n):
                total += diff[i]
                if total < val:
                    add = val - total
                    if remaining < add:
                        return False
                    remaining -= add
                    end = min(n, i + 2 * r + 1)
                    diff[end] -= add
                    total += add
            return True

        lo, hi = min(stations), sum(stations) + k
        res = 0
        while lo <= hi:
            mid = (lo + hi) // 2
            if check(mid):
                res = mid
                lo = mid + 1
            else:
                hi = mid - 1
        return res

4.7.226 - 2025-11-06 20:39:45 +0300 MSK

Power Grid Maintenance
class DSU:
    def __init__(self, size):
        self.parent = list(range(size))

    def find(self, x):
        if self.parent[x] != x:
            self.parent[x] = self.find(self.parent[x])
        return self.parent[x]

    def join(self, u, v):
        self.parent[self.find(v)] = self.find(u)


class Solution:
    def processQueries(
        self, c: int, connections: List[List[int]], queries: List[List[int]]
    ) -> List[int]:
        dsu = DSU(c + 1)
        for p in connections:
            dsu.join(p[0], p[1])

        online = [True] * (c + 1)
        offline_counts = [0] * (c + 1)
        minimum_online_stations = {}

        for q in queries:
            op, x = q[0], q[1]
            if op == 2:
                online[x] = False
                offline_counts[x] += 1

        for i in range(1, c + 1):
            root = dsu.find(i)
            if root not in minimum_online_stations:
                minimum_online_stations[root] = -1

            station = minimum_online_stations[root]
            if online[i]:
                if station == -1 or station > i:
                    minimum_online_stations[root] = i

        ans = []
        for i in range(len(queries) - 1, -1, -1):
            op, x = queries[i][0], queries[i][1]
            root = dsu.find(x)
            station = minimum_online_stations[root]

            if op == 1:
                if online[x]:
                    ans.append(x)
                else:
                    ans.append(station)

            if op == 2:
                if offline_counts[x] > 1:
                    offline_counts[x] -= 1
                else:
                    online[x] = True
                    if station == -1 or station > x:
                        minimum_online_stations[root] = x

        return ans[::-1]

4.7.227 - 2025-11-05 20:31:23 +0300 MSK

Find X-Sum of All K-Long Subarrays II
class Helper:
    def __init__(self, x):
        self.x = x
        self.result = 0
        self.large = SortedList()
        self.small = SortedList()
        self.occ = defaultdict(int)

    def insert(self, num):
        if self.occ[num] > 0:
            self.internal_remove((self.occ[num], num))
        self.occ[num] += 1
        self.internal_insert((self.occ[num], num))

    def remove(self, num):
        self.internal_remove((self.occ[num], num))
        self.occ[num] -= 1
        if self.occ[num] > 0:
            self.internal_insert((self.occ[num], num))

    def get(self):
        return self.result

    def internal_insert(self, p):
        if len(self.large) < self.x or p > self.large[0]:
            self.result += p[0] * p[1]
            self.large.add(p)
            if len(self.large) > self.x:
                to_remove = self.large[0]
                self.result -= to_remove[0] * to_remove[1]
                self.large.remove(to_remove)
                self.small.add(to_remove)
        else:
            self.small.add(p)

    def internal_remove(self, p):
        if p >= self.large[0]:
            self.result -= p[0] * p[1]
            self.large.remove(p)
            if self.small:
                to_add = self.small[-1]
                self.result += to_add[0] * to_add[1]
                self.small.remove(to_add)
                self.large.add(to_add)
        else:
            self.small.remove(p)


class Solution:
    def findXSum(self, nums, k, x):
        helper = Helper(x)
        ans = []

        for i in range(len(nums)):
            helper.insert(nums[i])
            if i >= k:
                helper.remove(nums[i - k])
            if i >= k - 1:
                ans.append(helper.get())

        return ans

4.7.228 - 2025-11-04 17:04:32 +0300 MSK

Find X-Sum of All K-Long Subarrays I
class Solution:
    def findXSum(self, nums: List[int], k: int, x: int) -> List[int]:

        def do_sum (idx: int)-> int:

            ctr = Counter(nums[idx:idx + k])
            most_freq = nlargest(x, ctr, key = lambda y: (ctr[y], y))

            return sum(map(lambda y: y * ctr[y], most_freq))


        return tuple(map(do_sum,range(len(nums)+1 - k)))

4.7.229 - 2025-11-03 17:26:21 +0300 MSK

Minimum Time to Make Rope Colorful
class Solution:
    def minCost(self, colors: str, neededTime: list[int]) -> int:
        total_time, curr_max_time = 0, 0

        for i in range(len(colors)):
            if i > 0 and colors[i] != colors[i - 1]:
                curr_max_time = 0
            total_time += min(curr_max_time, neededTime[i])
            curr_max_time = max(curr_max_time, neededTime[i])

        return total_time

4.7.230 - 2025-11-02 19:37:10 +0300 MSK

Delete Nodes From Linked List Present in Array
class Solution:
    def modifiedList(
        self, nums: List[int], head: Optional[ListNode]
    ) -> Optional[ListNode]:
        # Create a set for efficient lookup of values in nums
        values_to_remove = set(nums)

        # Handle the case where the head node needs to be removed
        while head and head.val in values_to_remove:
            head = head.next

        # If the list is empty after removing head nodes, return None
        if not head:
            return None

        # Iterate through the list, removing nodes with values in the set
        current = head
        while current.next:
            if current.next.val in values_to_remove:
                # Skip the next node by updating the pointer
                current.next = current.next.next
            else:
                # Move to the next node
                current = current.next

        return head

4.7.231 - 2025-11-02 19:36:12 +0300 MSK

Delete Nodes From Linked List Present in Array
class Solution:
    def modifiedList(
        self, nums: List[int], head: Optional[ListNode]
    ) -> Optional[ListNode]:
        # Create a set for efficient lookup of values in nums
        values_to_remove = set(nums)

        # Handle the case where the head node needs to be removed
        while head and head.val in values_to_remove:
            head = head.next

        # If the list is empty after removing head nodes, return None
        if not head:
            return None

        # Iterate through the list, removing nodes with values in the set
        current = head
        while current.next:
            if current.next.val in values_to_remove:
                # Skip the next node by updating the pointer
                current.next = current.next.next
            else:
                # Move to the next node
                current = current.next

        return head

4.7.232 - 2025-11-02 19:35:07 +0300 MSK

Count Unguarded Cells in the Grid
class Solution:
    UNGUARDED = 0
    GUARDED = 1
    GUARD = 2
    WALL = 3

    # Depth-First Search to mark guarded cells
    def _recurse(
        self, row: int, col: int, grid: List[List[int]], direction: str
    ) -> None:
        if (
            row < 0
            or row >= len(grid)
            or col < 0
            or col >= len(grid[0])
            or grid[row][col] == self.GUARD
            or grid[row][col] == self.WALL
        ):
            return

        grid[row][col] = self.GUARDED  # Mark cell as guarded
        if direction == "U":
            self._recurse(row - 1, col, grid, "U")  # Up
        if direction == "D":
            self._recurse(row + 1, col, grid, "D")  # Down
        if direction == "L":
            self._recurse(row, col - 1, grid, "L")  # Left
        if direction == "R":
            self._recurse(row, col + 1, grid, "R")  # Right

    def countUnguarded(
        self, m: int, n: int, guards: List[List[int]], walls: List[List[int]]
    ) -> int:
        grid = [[self.UNGUARDED] * n for _ in range(m)]

        # Mark guards' positions
        for guard in guards:
            grid[guard[0]][guard[1]] = self.GUARD

        # Mark walls' positions
        for wall in walls:
            grid[wall[0]][wall[1]] = self.WALL

        # Mark cells as guarded by traversing from each guard
        for guard in guards:
            self._recurse(guard[0] - 1, guard[1], grid, "U")  # Up
            self._recurse(guard[0] + 1, guard[1], grid, "D")  # Down
            self._recurse(guard[0], guard[1] - 1, grid, "L")  # Left
            self._recurse(guard[0], guard[1] + 1, grid, "R")  # Right

        # Count unguarded cells
        count = sum(row.count(self.UNGUARDED) for row in grid)
        return count

4.7.233 - 2025-10-31 21:10:44 +0300 MSK

The Two Sneaky Numbers of Digitville
class Solution:
    def getSneakyNumbers(self, nums: List[int]) -> List[int]:
        n = len(nums) - 2
        xor_all = 0
        for num in nums:
            xor_all ^= num
        for num in range(n):
            xor_all ^= num
        rightmost_bit = xor_all & -xor_all
        dup1, dup2 = 0, 0
        for num in nums:
            if num & rightmost_bit:
                dup1 ^= num
            else:
                dup2 ^= num
        for num in range(n):
            if num & rightmost_bit:
                dup1 ^= num
            else:
                dup2 ^= num
        return [dup1, dup2]

4.7.234 - 2025-10-30 20:34:31 +0300 MSK

Minimum Number of Increments on Subarrays to Form a Target Array
class Solution:
    def minNumberOperations(self, target: List[int]) -> int:
        n = len(target)
        ans = target[0]
        for i in range(1, n):
            ans += max(target[i] - target[i - 1], 0)
        return ans

4.7.235 - 2025-10-29 19:40:08 +0300 MSK

Smallest Number With All Set Bits
class Solution:
    def smallestNumber(self, n: int) -> int:
        res = 0
        while n > 0:
            res = (res << 1) | 1
            n //= 2
        return res

4.7.236 - 2025-10-28 17:46:01 +0300 MSK

Equal Score Substrings
class Solution:
    def scoreBalance(self, s: str) -> bool:
        right, left = 0, 0
        for char in s:
            right += ord(char) - ord('a') + 1
        for char in s:
            val = ord(char) - ord('a') + 1
            left += val
            right -= val
            if left == right:
                return True
            if left > right:
                return False
        return False

4.7.237 - 2025-10-28 17:19:30 +0300 MSK

Make Array Elements Equal to Zero
class Solution:
    def countValidSelections(self, nums: List[int]) -> int:
        n, res = len(nums), 0
        left, right = [0 for _ in range(n)], [0 for _ in range(n)]
        for i in range(1, n):
            left[i] = left[i - 1] + nums[i - 1]
            right[-i - 1] = right[-i] + nums[-i]
        for i, num in enumerate(nums):
            if num != 0: continue
            if left[i] == right[i]: res += 2
            if abs(left[i] - right[i]) == 1: res += 1
        return res

4.7.238 - 2025-10-27 20:43:34 +0300 MSK

Number of Laser Beams in a Bank
class Solution:
    def numberOfBeams(self, bank):
        ans, temp = 0, 0
        for s in bank:
            n = s.count('1')
            if n == 0:
                continue
            ans += temp * n
            temp = n
        return ans

4.7.239 - 2025-10-27 12:49:36 +0300 MSK

Simple Bank System
class Bank:
    def __init__(self, balance: List[int]):
        self.balance = balance

    def transfer(self, account1: int, account2: int, money: int) -> bool:
        if (
            account1 > len(self.balance)
            or account2 > len(self.balance)
            or self.balance[account1 - 1] < money
        ):
            return False
        self.balance[account1 - 1] -= money
        self.balance[account2 - 1] += money
        return True

    def deposit(self, account: int, money: int) -> bool:
        if account > len(self.balance):
            return False
        self.balance[account - 1] += money
        return True

    def withdraw(self, account: int, money: int) -> bool:
        if account > len(self.balance) or self.balance[account - 1] < money:
            return False
        self.balance[account - 1] -= money
        return True

4.7.240 - 2025-10-27 12:48:19 +0300 MSK

Simple Bank System
class Bank:
    def __init__(self, balance: List[int]):
        self.balance = balance

    def transfer(self, account1: int, account2: int, money: int) -> bool:
        if (
            account1 > len(self.balance)
            or account2 > len(self.balance)
            or self.balance[account1 - 1] < money
        ):
            return False
        self.balance[account1 - 1] -= money
        self.balance[account2 - 1] += money
        return True

    def deposit(self, account: int, money: int) -> bool:
        if account > len(self.balance):
            return False
        self.balance[account - 1] += money
        return True

    def withdraw(self, account: int, money: int) -> bool:
        if account > len(self.balance) or self.balance[account - 1] < money:
            return False
        self.balance[account - 1] -= money
        return True

4.7.241 - 2025-10-25 13:13:55 +0300 MSK

Calculate Money in Leetcode Bank
class Solution {
public:
    int totalMoney(int n) {
        int ans {0};
        int monday {1};
        
        while (n > 0) {
            for (int day {0}; day < min(n, 7); ++day) {
                ans += monday + day;
            }
            n -= 7;
            ++monday;
        }
        
        return ans;
    }
};

4.7.242 - 2025-10-24 19:02:20 +0300 MSK

Next Greater Numerically Balanced Number
class Solution:
    def nextBeautifulNumber(self, n: int) -> int:
        for i in range(n + 1, 1224445):
            count = Counter(str(i))
            if all(count[d] == int(d) for d in count):
                return i

4.7.243 - 2025-10-23 19:12:54 +0300 MSK

Check If Digits Are Equal in String After Operations I
class Solution:
    def hasSameDigits(self, s: str) -> bool:
        stack = list(map(int, s))
        stack.reverse()
        while len(stack) > 2:
            prev = stack.pop()
            for i in reversed(range(len(stack))):
                stack[i], prev = (prev + stack[i]) % 10, stack[i]
        return stack[0] == stack[1]

4.7.244 - 2025-10-22 16:36:23 +0300 MSK

Maximum Frequency of an Element After Performing Operations II
class Solution:
    def maxFrequency(self, nums: List[int], k: int, numOperations: int) -> int:
        nums.sort()
        ans = 0
        num_count = defaultdict(int)
        modes = set()

        def add_mode(value):
            modes.add(value)
            if value - k >= nums[0]:
                modes.add(value - k)
            if value + k <= nums[-1]:
                modes.add(value + k)

        last_num_index = 0
        for i in range(len(nums)):
            if nums[i] != nums[last_num_index]:
                num_count[nums[last_num_index]] = i - last_num_index
                ans = max(ans, i - last_num_index)
                add_mode(nums[last_num_index])
                last_num_index = i

        num_count[nums[last_num_index]] = len(nums) - last_num_index
        ans = max(ans, len(nums) - last_num_index)
        add_mode(nums[last_num_index])

        for mode in sorted(modes):
            l = bisect.bisect_left(nums, mode - k)
            r = bisect.bisect_right(nums, mode + k) - 1
            if mode in num_count:
                temp_ans = min(r - l + 1, num_count[mode] + numOperations)
            else:
                temp_ans = min(r - l + 1, numOperations)
            ans = max(ans, temp_ans)

        return ans

4.7.245 - 2025-10-21 20:51:47 +0300 MSK

Maximum Frequency of an Element After Performing Operations I
class Solution:
    def maxFrequency(self, nums: List[int], k: int, numOperations: int) -> int:
        nums.sort()
        ans = 0
        num_count = {}
        last_num_index = 0
        for i in range(len(nums)):
            if nums[i] != nums[last_num_index]:
                num_count[nums[last_num_index]] = i - last_num_index
                ans = max(ans, i - last_num_index)
                last_num_index = i

        num_count[nums[last_num_index]] = len(nums) - last_num_index
        ans = max(ans, len(nums) - last_num_index)

        for i in range(nums[0], nums[-1] + 1):
            l = bisect.bisect_left(nums, i - k)
            r = bisect.bisect_right(nums, i + k) - 1
            if i in num_count:
                temp_ans = min(r - l + 1, num_count[i] + numOperations)
            else:
                temp_ans = min(r - l + 1, numOperations)
            ans = max(ans, temp_ans)

        return ans

4.7.246 - 2025-10-20 21:06:38 +0300 MSK

Final Value of Variable After Performing Operations
class Solution:
    def finalValueAfterOperations(self, operations: List[str]) -> int:
        res = 0
        for op in operations:
            if op.startswith("++") or op.endswith("++"):
                res += 1
            else:
                res -= 1
        return res

4.7.247 - 2025-10-19 18:18:20 +0300 MSK

Lexicographically Smallest String After Applying Operations
class Solution:
    def findLexSmallestString(self, s: str, a: int, b: int) -> str:
        n = len(s)
        vis = [False] * n
        res = s
        # double the length of s for convenience in extracting the rotated string t
        s = s + s
        i = 0
        while not vis[i]:
            vis[i] = True
            for j in range(10):
                k_limit = 0 if b % 2 == 0 else 9
                for k in range(k_limit + 1):
                    # before each accumulation, re-truncate t
                    t = list(s[i : i + n])
                    for p in range(1, n, 2):
                        t[p] = str((int(t[p]) + j * a) % 10)
                    for p in range(0, n, 2):
                        t[p] = str((int(t[p]) + k * a) % 10)
                    t_str = "".join(t)
                    if t_str < res:
                        res = t_str
            i = (i + b) % n
        return res

4.7.248 - 2025-10-18 20:20:30 +0300 MSK

Maximum Number of Distinct Elements After Operations
class Solution:
    def maxDistinctElements(self, nums: List[int], k: int) -> int:
        nums.sort()

        cnt = 0
        prev = -math.inf

        for num in nums:
            curr = min(max(num - k, prev + 1), num + k)
            if curr > prev:
                cnt += 1
                prev = curr

        return cnt

4.7.249 - 2025-10-17 20:03:35 +0300 MSK

Maximize the Number of Partitions After Operations
class Solution:
    def maxPartitionsAfterOperations(self, s: str, k: int) -> int:
        n = len(s)
        left = [[0] * 3 for _ in range(n)]
        right = [[0] * 3 for _ in range(n)]

        num, mask, count = 0, 0, 0
        for i in range(n - 1):
            binary = 1 << (ord(s[i]) - ord("a"))
            if not (mask & binary):
                count += 1
                if count <= k:
                    mask |= binary
                else:
                    num += 1
                    mask = binary
                    count = 1
            left[i + 1][0] = num
            left[i + 1][1] = mask
            left[i + 1][2] = count

        num, mask, count = 0, 0, 0
        for i in range(n - 1, 0, -1):
            binary = 1 << (ord(s[i]) - ord("a"))
            if not (mask & binary):
                count += 1
                if count <= k:
                    mask |= binary
                else:
                    num += 1
                    mask = binary
                    count = 1
            right[i - 1][0] = num
            right[i - 1][1] = mask
            right[i - 1][2] = count

        max_val = 0
        for i in range(n):
            seg = left[i][0] + right[i][0] + 2
            tot_mask = left[i][1] | right[i][1]
            tot_count = bin(tot_mask).count("1")
            if left[i][2] == k and right[i][2] == k and tot_count < 26:
                seg += 1
            elif min(tot_count + 1, 26) <= k:
                seg -= 1
            max_val = max(max_val, seg)
        return max_val

4.7.250 - 2025-10-16 21:12:42 +0300 MSK

Smallest Missing Non-negative Integer After Operations
class Solution:
    def findSmallestInteger(self, nums: List[int], value: int) -> int:
        mp = Counter(x % value for x in nums)
        mex = 0
        while mp[mex % value] > 0:
            mp[mex % value] -= 1
            mex += 1
        return mex

4.7.251 - 2025-10-15 21:05:53 +0300 MSK

Adjacent Increasing Subarrays Detection II
class Solution:
    def maxIncreasingSubarrays(self, nums: List[int]) -> int:
        n = len(nums)
        cnt, precnt, ans = 1, 0, 0
        for i in range(1, n):
            if nums[i] > nums[i - 1]:
                cnt += 1
            else:
                precnt, cnt = cnt, 1
            ans = max(ans, min(precnt, cnt))
            ans = max(ans, cnt // 2)
        return ans

4.7.252 - 2025-10-14 21:36:00 +0300 MSK

Adjacent Increasing Subarrays Detection I
class Solution:
    def hasIncreasingSubarrays(self, nums: List[int], k: int) -> bool:
        n = len(nums)
        cnt = 1
        prv_cnt = 0
        for i in range(1, n):
            cur, prv = nums[i], nums[i - 1]
            if cur > prv:
                cnt += 1
            else:
                prv_cnt, cnt = cnt, 1
            if cnt >= 2 * k or prv_cnt >= k and cnt >= k:
                return True
        return False

4.7.253 - 2025-10-13 21:06:28 +0300 MSK

Find Resultant Array After Removing Anagrams
class Solution:
    def removeAnagrams(self, words: List[str]) -> List[str]:
        freqs1, freqs2 = bytearray(26), bytearray(26)
        res = []
        for i, word in enumerate(words):
            for i in range(26):
                freqs2[i] = 0
            for char in word:
                freqs2[ord(char) - 97] += 1
            if i != 0 and freqs1 == freqs2:
                continue
            freqs1, freqs2 = freqs2, freqs1
            res.append(word)
        return res

4.7.254 - 2025-10-12 18:25:03 +0300 MSK

Find Sum of Array Product of Magical Sequences
class Solution:
    def quickmul(self, x: int, y: int, mod: int) -> int:
        res, cur = 1, x % mod
        while y:
            if y & 1:
                res = res * cur % mod
            y >>= 1
            cur = cur * cur % mod
        return res

    def magicalSum(self, m: int, k: int, nums: List[int]) -> int:
        n = len(nums)
        mod = 10**9 + 7

        fac = [1] * (m + 1)
        for i in range(1, m + 1):
            fac[i] = fac[i - 1] * i % mod

        ifac = [1] * (m + 1)
        for i in range(2, m + 1):
            ifac[i] = self.quickmul(i, mod - 2, mod)
        for i in range(2, m + 1):
            ifac[i] = ifac[i - 1] * ifac[i] % mod

        numsPower = [[1] * (m + 1) for _ in range(n)]
        for i in range(n):
            for j in range(1, m + 1):
                numsPower[i][j] = numsPower[i][j - 1] * nums[i] % mod

        f = [
            [[[0] * (k + 1) for _ in range(m * 2 + 1)] for _ in range(m + 1)]
            for _ in range(n)
        ]

        for j in range(m + 1):
            f[0][j][j][0] = numsPower[0][j] * ifac[j] % mod

        for i in range(n - 1):
            for j in range(m + 1):
                for p in range(m * 2 + 1):
                    for q in range(k + 1):
                        if f[i][j][p][q] == 0:
                            continue
                        q2 = (p % 2) + q
                        if q2 > k:
                            break
                        for r in range(m - j + 1):
                            p2 = (p // 2) + r
                            if p2 > m * 2:
                                continue
                            f[i + 1][j + r][p2][q2] = (
                                f[i + 1][j + r][p2][q2]
                                + f[i][j][p][q]
                                * numsPower[i + 1][r]
                                % mod
                                * ifac[r]
                                % mod
                            ) % mod

        res = 0
        for p in range(m * 2 + 1):
            for q in range(k + 1):
                if bin(p).count("1") + q == k:
                    res = (res + f[n - 1][m][p][q] * fac[m] % mod) % mod
        return res

4.7.255 - 2025-10-11 21:08:12 +0300 MSK

Maximum Total Damage With Spell Casting
class Solution:
    def maximumTotalDamage(self, power):
        count = Counter(power)
        vec = [(-(10**9), 0)]
        for k in sorted(count.keys()):
            vec.append((k, count[k]))
        n = len(vec)
        f = [0] * n
        mx = 0
        j = 1
        for i in range(1, n):
            while j < i and vec[j][0] < vec[i][0] - 2:
                mx = max(mx, f[j])
                j += 1
            f[i] = mx + vec[i][0] * vec[i][1]
        return max(f)

4.7.256 - 2025-10-10 19:31:54 +0300 MSK

Taking Maximum Energy From the Mystic Dungeon
class Solution:
    def maximumEnergy(self, energy: List[int], k: int) -> int:
        n = len(energy)
        ans = -inf

        for i in range(n - k, n):
            total = 0
            j = i
            while j >= 0:
                total += energy[j]
                ans = max(ans, total)
                j -= k

        return ans

4.7.257 - 2025-10-09 21:03:44 +0300 MSK

Find the Minimum Amount of Time to Brew Potions
class Solution:
    def minTime(self, skill: List[int], mana: List[int]) -> int:
        n, m = len(skill), len(mana)
        times = [0] * n
        for j in range(m):
            cur_time = 0
            for i in range(n):
                cur_time = max(cur_time, times[i]) + skill[i] * mana[j]
            times[n - 1] = cur_time
            for i in range(n - 2, -1, -1):
                times[i] = times[i + 1] - skill[i + 1] * mana[j]
        return times[n - 1]

4.7.258 - 2025-10-08 20:28:20 +0300 MSK

Successful Pairs of Spells and Potions
class Solution:
    def successfulPairs(self, spells: List[int], potions: List[int], success: int) -> List[int]:
        freq=Counter(potions)
        pMax=max(freq)
        F=[0]*(1+pMax)
        for p, f in freq.items():
            F[p]=f
        freq=list(accumulate(F))
        n, m=len(spells), len(potions)
        res=[0]*n
        for i, x in enumerate(spells):
            k=(success+x-1)//x
            if k<=pMax:
                res[i]=m-freq[k-1]
        return res

        

4.7.259 - 2025-10-07 19:48:34 +0300 MSK

Avoid Flood in The City
from sortedcontainers import SortedList


class Solution:
    def avoidFlood(self, rains: List[int]) -> List[int]:
        ans = [1] * len(rains)
        st = SortedList()
        mp = {}
        for i, rain in enumerate(rains):
            if rain == 0:
                st.add(i)
            else:
                ans[i] = -1
                if rain in mp:
                    it = st.bisect(mp[rain])
                    if it == len(st):
                        return []
                    ans[st[it]] = rain
                    st.discard(st[it])
                mp[rain] = i
        return ans

4.7.260 - 2025-10-06 20:51:45 +0300 MSK

Swim in Rising Water
class Solution:
    def swimInWater(self, grid: List[List[int]]) -> int:
        m, n = len(grid), len(grid[0])
        pq = [(grid[0][0], 0, 0)]
        directions = [(0, 1), (1, 0), (0, -1), (-1, 0)]
        seen = set()
        
        while pq:
            max_d, r, c = heapq.heappop(pq)
            if (r, c) in seen: continue
            seen.add((r, c))
            if r == m-1 and c == n-1:
                return max_d
            
            for dr, dc in directions:
                nr, nc = r + dr, c + dc
                if 0 <= nr < m and 0 <= nc < n and (nr, nc) not in seen:
                    new_d = max(max_d, grid[nr][nc])
                    heapq.heappush(pq, (new_d, nr, nc))
        
        return -1

4.7.261 - 2025-10-05 19:06:52 +0300 MSK

Pacific Atlantic Water Flow
class Solution:
    def pacificAtlantic(self, heights: List[List[int]]) -> List[List[int]]:
        def dfs(cell, visited):
            if cell in visited:
                return
            visited.add(cell)
            r, c = cell
            for nr, nc in [(r-1, c), (r+1, c), (r, c-1), (r, c+1)]:
                if 0 <= nr < rows and 0 <= nc < cols and heights[nr][nc] >= heights[r][c]:
                    dfs((nr, nc), visited)

        rows, cols = len(heights), len(heights[0])
        pacific, atlantic = set(), set()

        for r in range(rows):
            dfs((r, 0), pacific)
            dfs((r, cols - 1), atlantic)
        for c in range(cols):
            dfs((0, c), pacific)
            dfs((rows - 1, c), atlantic)

        return list(pacific & atlantic)

4.7.262 - 2025-10-05 18:56:55 +0300 MSK

Compute Alternating Sum
class Solution:
    def alternatingSum(self, nums: List[int]) -> int:
        res = 0
        for i, num in enumerate(nums):
            if i % 2 == 0:
                res += num
            else:
                res -= num
        return res

4.7.263 - 2025-10-04 21:18:06 +0300 MSK

Container With Most Water
class Solution:
    def maxArea(self, height: list[int]) -> int:
        i = 0
        j = len(height) - 1
        res = 0

        while i < j:
            res = max(res, (j - i) * min(height[i], height[j]))
            if height[i] < height[j]:
                i += 1
            else:
                j -= 1

        return res

4.7.264 - 2025-10-03 16:57:28 +0300 MSK

Trapping Rain Water II
class Solution:
    # Class to store the height and coordinates of a cell in the grid
    class Cell:
        def __init__(self, height, row, col):
            self.height = height
            self.row = row
            self.col = col

        # Comparison method for the priority queue (min-heap)
        def __lt__(self, other):
            return self.height < other.height

    # Helper function to check if a cell is valid (within grid bounds)
    def _is_valid_cell(self, row, col, num_of_rows, num_of_cols):
        return 0 <= row < num_of_rows and 0 <= col < num_of_cols

    def trapRainWater(self, height_map):
        # Direction arrays
        d_row = [0, 0, -1, 1]
        d_col = [-1, 1, 0, 0]

        num_of_rows = len(height_map)
        num_of_cols = len(height_map[0])

        visited = [[False] * num_of_cols for _ in range(num_of_rows)]

        # Priority queue (min-heap) to process boundary cells in increasing height order
        boundary = []

        # Add the first and last column cells to the boundary and mark them as visited
        for i in range(num_of_rows):
            heapq.heappush(boundary, self.Cell(height_map[i][0], i, 0))
            heapq.heappush(
                boundary,
                self.Cell(height_map[i][num_of_cols - 1], i, num_of_cols - 1),
            )
            visited[i][0] = visited[i][num_of_cols - 1] = True

        # Add the first and last row cells to the boundary and mark them as visited
        for i in range(num_of_cols):
            heapq.heappush(boundary, self.Cell(height_map[0][i], 0, i))
            heapq.heappush(
                boundary,
                self.Cell(height_map[num_of_rows - 1][i], num_of_rows - 1, i),
            )
            visited[0][i] = visited[num_of_rows - 1][i] = True

        # Initialize the total water volume to 0
        total_water_volume = 0

        # Process cells in the boundary (min-heap will always pop the smallest height)
        while boundary:
            # Pop the cell with the smallest height from the boundary
            current_cell = heapq.heappop(boundary)

            current_row = current_cell.row
            current_col = current_cell.col
            min_boundary_height = current_cell.height

            # Explore all 4 neighboring cells
            for direction in range(4):
                # Calculate the row and column of the neighbor
                neighbor_row = current_row + d_row[direction]
                neighbor_col = current_col + d_col[direction]

                # Check if the neighbor is within the grid bounds and not yet visited
                if (
                    self._is_valid_cell(
                        neighbor_row, neighbor_col, num_of_rows, num_of_cols
                    )
                    and not visited[neighbor_row][neighbor_col]
                ):
                    # Get the height of the neighbor cell
                    neighbor_height = height_map[neighbor_row][neighbor_col]

                    # If the neighbor's height is less than the current boundary height, water can be trapped
                    if neighbor_height < min_boundary_height:
                        # Add the trapped water volume
                        total_water_volume += (
                            min_boundary_height - neighbor_height
                        )

                    # Push the neighbor into the boundary with updated height (to prevent water leakage)
                    heapq.heappush(
                        boundary,
                        self.Cell(
                            max(neighbor_height, min_boundary_height),
                            neighbor_row,
                            neighbor_col,
                        ),
                    )
                    visited[neighbor_row][neighbor_col] = True

        # Return the total amount of trapped water
        return total_water_volume

4.7.265 - 2025-10-02 17:45:08 +0300 MSK

Water Bottles II
class Solution:
    def maxBottlesDrunk(self, numBottles: int, numExchange: int) -> int:
        res, empty = numBottles, numBottles
        while empty >= numExchange:
            empty = (empty - numExchange) + 1
            numExchange += 1
            res += 1
        return res 

4.7.266 - 2025-10-01 09:21:36 +0300 MSK

Compute Decimal Representation
class Solution:
    def decimalRepresentation(self, n: int) -> List[int]:
        res = []
        count = 0
        while n > 0:
            val = (n % 10) * (10 ** count)
            if val != 0:
                res.append(val)
            count += 1
            n //= 10
        res.reverse()
        return res

4.7.267 - 2025-10-01 09:19:12 +0300 MSK

Majority Frequency Characters
class Solution:
    def majorityFrequencyGroup(self, s: str) -> str:
        freqs = [0] * 26
        groups = [([], 0) for _ in range(101)]
        for char in s:
            freqs[ord(char) - 97] += 1
        for i, freq in enumerate(freqs):
            if freq == 0:
                continue
            chars, _ = groups[freq]
            chars.append(chr(i + 97))
            groups[freq] = (chars, freq)
        groups.sort(key=lambda val: (len(val[0]), val[1]))
        return "".join(groups[-1][0])
        

4.7.268 - 2025-10-01 08:50:51 +0300 MSK

Bitwise OR of Even Numbers in an Array
class Solution:
    def evenNumberBitwiseORs(self, nums: List[int]) -> int:
        res = 0
        for num in nums:
            if num % 2 == 0:
                res |= num
        return res

4.7.269 - 2025-10-01 08:48:37 +0300 MSK

Maximize Sum of At Most K Distinct Elements
class Solution:
    def maxKDistinct(self, nums: List[int], k: int) -> List[int]:
        nums.sort(reverse=True)
        res = []
        for i in range(len(nums)):
            if i == 0 or nums[i] != nums[i - 1]:
                res.append(nums[i])
                if len(res) == k:
                    break
        return res

4.7.270 - 2025-10-01 08:46:25 +0300 MSK

Earliest Time to Finish One Task
class Solution:
    def earliestTime(self, tasks: List[List[int]]) -> int:
        res = math.inf
        for start, dur in tasks:
            res = min(res, start + dur)
        return res

4.7.271 - 2025-10-01 08:43:05 +0300 MSK

Water Bottles
class Solution:
    def numWaterBottles(self, numBottles: int, numExchange: int) -> int:
        res, empty = 0, 0
        while numBottles > 0:
            res += numBottles
            empty += numBottles
            numBottles, empty = empty // numExchange, empty % numExchange
        return res

4.7.272 - 2025-09-30 19:51:05 +0300 MSK

Find Triangular Sum of an Array
class Solution:
    def triangularSum(self, nums: List[int]) -> int:
        while len(nums) > 1:
            new_nums = list()
            for i in range(len(nums) - 1):
                new_nums.append((nums[i] + nums[i + 1]) % 10)
            nums = new_nums
        return nums[0]

4.7.273 - 2025-09-29 18:59:55 +0300 MSK

Minimum Score Triangulation of Polygon
class Solution:
    def minScoreTriangulation(self, values: List[int]) -> int:
        @lru_cache(None)
        def dp(i, j):
            if i + 2 > j:
                return 0
            if i + 2 == j:
                return values[i] * values[i + 1] * values[j]
            return min(
                (values[i] * values[k] * values[j] + dp(i, k) + dp(k, j))
                for k in range(i + 1, j)
            )

        return dp(0, len(values) - 1)

4.7.274 - 2025-09-28 17:19:33 +0300 MSK

Largest Perimeter Triangle
class Solution:
    def largestPerimeter(self, nums: List[int]) -> int:
        nums.sort(reverse=True)
        for i in range(len(nums) - 2):
            if nums[i + 1] + nums[i + 2] > nums[i]:
                return nums[i] + nums[i + 1] + nums[i + 2]
        return 0

4.7.275 - 2025-09-27 17:16:05 +0300 MSK

Smallest Absent Positive Greater Than Average
class Solution:
    def smallestAbsent(self, nums: List[int]) -> int:
        enc = set(nums)
        avg = max(sum(nums) // len(nums), 0) + 1
        while True:
            if avg in enc:
                avg += 1
            else:
                return avg

4.7.276 - 2025-09-27 10:04:38 +0300 MSK

Largest Triangle Area
class Solution(object):
    def largestTriangleArea(self, points):
        def area(p, q, r):
            return .5 * abs(p[0]*q[1]+q[0]*r[1]+r[0]*p[1]
                           -p[1]*q[0]-q[1]*r[0]-r[1]*p[0])

        return max(area(*triangle)
            for triangle in itertools.combinations(points, 3))

4.7.277 - 2025-09-26 19:59:24 +0300 MSK

Valid Triangle Number
class Solution:
    def triangleNumber(self, nums: List[int]) -> int:
        nums.sort()
        n = len(nums)
        count = 0

        for i in range(n - 1, -1, -1):
            left, right = 0, i - 1
            while left < right:
                if nums[left] + nums[right] > nums[i]:
                    count += right - left
                    right -= 1
                else:
                    left += 1
        return count

4.7.278 - 2025-09-25 17:15:32 +0300 MSK

Triangle
class Solution:
    def minimumTotal(self, triangle: List[List[int]]) -> int:
        cur, prev = [], triangle[0]
        for row in range(1, len(triangle)):
            for col in range(row + 1):
                if col == 0:
                    val = prev[col]
                elif col == row:
                    val = prev[col - 1]
                else:
                    val = min(prev[col - 1], prev[col])
                cur.append(val + triangle[row][col])
            prev.clear()
            cur, prev = prev, cur
        return min(prev)

4.7.279 - 2025-09-24 18:51:01 +0300 MSK

Fraction to Recurring Decimal
class Solution:
    def fractionToDecimal(self, numerator: int, denominator: int) -> str:
        if numerator == 0:
            return "0"
        fraction = []
        if (numerator < 0) ^ (denominator < 0):
            fraction.append("-")
        dividend = abs(numerator)
        divisor = abs(denominator)
        fraction.append(str(dividend // divisor))
        remainder = dividend % divisor
        if remainder == 0:
            return "".join(fraction)
        fraction.append(".")
        map_dict = {}
        while remainder != 0:
            if remainder in map_dict:
                fraction.insert(map_dict[remainder], "(")
                fraction.append(")")
                break
            map_dict[remainder] = len(fraction)
            remainder *= 10
            fraction.append(str(remainder // divisor))
            remainder %= divisor

        return "".join(fraction)

4.7.280 - 2025-09-23 16:55:31 +0300 MSK

Compare Version Numbers
class Solution:
    def compareVersion(self, version1: str, version2: str) -> int:
        digs1, digs2 = list(map(int, version1.split("."))), list(map(int, version2.split(".")))
        while digs1 and digs1[-1] == 0:
            digs1.pop()
        while digs2 and digs2[-1] == 0:
            digs2.pop()
        length1, length2 = len(digs1), len(digs2)
        for i in range(max(length1, length2)):
            if i == length1:
                return -1
            if i == length2:
                return 1
            dig1, dig2 = digs1[i], digs2[i]
            if dig1 > dig2:
                return 1
            elif dig2 > dig1:
                return -1
        return 0

4.7.281 - 2025-09-22 19:34:44 +0300 MSK

Count Elements With Maximum Frequency
class Solution:
    def maxFrequencyElements(self, nums: List[int]) -> int:
        max_freq, max_freq_count = 0, 0
        freqs = [0] * 101
        for num in nums:
            freqs[num] += 1
        for num, freq in enumerate(freqs):
            if freq > max_freq:
                max_freq, max_freq_count = freq, freq
            elif freq == max_freq:
                max_freq_count += freq
        return max_freq_count

4.7.282 - 2025-09-21 19:30:58 +0300 MSK

Design Movie Rental System
class MovieRentingSystem:

    def __init__(self, n: int, entries: List[List[int]]):
        self.available = {}  # (shop, movie) -> price
        self.movie_shops = {}  # movie -> list of (price, shop)
        self.rented = set()  # (shop, movie) that are currently rented

        for shop, movie, price in entries:
            self.available[(shop, movie)] = price
            if movie not in self.movie_shops:
                self.movie_shops[movie] = []
            self.movie_shops[movie].append((price, shop))

        # Sort shops by price for each movie initially
        for movie in self.movie_shops:
            self.movie_shops[movie].sort()

    def search(self, movie: int) -> List[int]:
        result = []
        for price, shop in self.movie_shops.get(movie, []):
            if (shop, movie) not in self.rented:
                result.append(shop)
            if len(result) == 5:
                break
        return result

    def rent(self, shop: int, movie: int) -> None:
        self.rented.add((shop, movie))

    def drop(self, shop: int, movie: int) -> None:
        self.rented.discard((shop, movie))

    def report(self) -> List[List[int]]:
        rented_list = []
        for shop, movie in self.rented:
            price = self.available[(shop, movie)]
            rented_list.append((price, shop, movie))

        rented_list.sort()
        return [[shop, movie] for price, shop, movie in rented_list[:5]]

4.7.283 - 2025-09-20 19:25:16 +0300 MSK

Implement Router
class Router:
    def __init__(self, memoryLimit: int):
        self.size = memoryLimit
        self.packets = {}  # key -> [source, destination, timestamp]
        self.counts = defaultdict(list)  # destination -> sorted list of timestamps
        self.queue = deque()  # FIFO order of packets

    def addPacket(self, source: int, destination: int, timestamp: int) -> bool:
        key = self._encode(source, destination, timestamp)

        # Duplicate check
        if key in self.packets:
            return False

        # If memory full, forward oldest packet
        if len(self.packets) >= self.size:
            self.forwardPacket()

        # Add packet
        self.packets[key] = [source, destination, timestamp]
        self.queue.append(key)
        self.counts[destination].append(timestamp)

        return True

    def forwardPacket(self):
        if not self.packets:
            return []

        key = self.queue.popleft()
        packet = self.packets.pop(key)

        dest = packet[1]
        self.counts[dest].pop(0)  # remove the earliest timestamp

        return packet

    def getCount(self, destination: int, startTime: int, endTime: int) -> int:
        timestamps = self.counts.get(destination, [])
        if not timestamps:
            return 0

        # Binary search for range
        left = bisect.bisect_left(timestamps, startTime)
        right = bisect.bisect_right(timestamps, endTime)

        return right - left

    def _encode(self, source: int, destination: int, timestamp: int) -> int:
        # Encode uniquely into 1 number
        return (source << 40) | (destination << 20) | timestamp

4.7.284 - 2025-09-19 18:44:46 +0300 MSK

Design Spreadsheet
class Spreadsheet:

    def __init__(self, rows: int):
        self._grid = [[0] * 26 for _ in range(rows)]

    def _coord(self, cell: str) -> tuple[int, int]:
        return int(cell[1:]) - 1, ord(cell[0]) - ord("A")

    def setCell(self, cell: str, value: int) -> None:
        row, col = self._coord(cell)
        self._grid[row][col] = value

    def resetCell(self, cell: str) -> None:
        row, col = self._coord(cell)
        self._grid[row][col] = 0

    def getValue(self, formula: str) -> int:
        res = 0
        for cell in formula[1:].split("+"):
            if cell[0].isdigit():
                res += int(cell)
            else:
                row, col = self._coord(cell)
                res += self._grid[row][col]
        return res

# Your Spreadsheet object will be instantiated and called as such:
# obj = Spreadsheet(rows)
# obj.setCell(cell,value)
# obj.resetCell(cell)
# param_3 = obj.getValue(formula)

4.7.285 - 2025-09-18 19:58:25 +0300 MSK

Design Task Manager
class TaskManager:
    def __init__(self, tasks: List[List[int]]):
        self.tasks = SortedSet()
        self.task_to_users = {}
        self.task_to_priority = {}
        for user_id, task_id, priority in tasks:
            self.add(user_id, task_id, priority)
    def add(self, userId: int, taskId: int, priority: int) -> None:
        self.tasks.add((priority, taskId, userId))
        self.task_to_users[taskId] = userId
        self.task_to_priority[taskId] = priority
    def edit(self, taskId: int, newPriority: int) -> None:
        user = self.task_to_users[taskId]
        self.rmv(taskId)
        self.add(user, taskId, newPriority)        
    def rmv(self, taskId: int) -> None:
        user = self.task_to_users[taskId]        
        priority = self.task_to_priority[taskId]
        self.tasks.remove((priority, taskId, user))
        del self.task_to_users[taskId]
        del self.task_to_priority[taskId]
    def execTop(self) -> int:
        if not self.tasks:
            return -1
        _, task_id, user_id = self.tasks[-1]
        self.rmv(task_id)
        return user_id

4.7.286 - 2025-09-17 20:39:54 +0300 MSK

Design a Food Rating System
from sortedcontainers import SortedSet

class FoodRatings:
    def __init__(self, foods: List[str], cuisines: List[str], ratings: List[int]):
        # Map food with its rating.
        self.food_rating_map = {}
        # Map food with the cuisine it belongs to.
        self.food_cuisine_map = {}

        # Store all food of cuisine in a set (to sort them on ratings/name)
        # Set element -> Tuple: (-1 * food_rating, food_name)
        self.cuisine_food_map = defaultdict(SortedSet)

        for i in range(len(foods)):
            # Store 'rating' and 'cuisine' of the current 'food' in 'food_rating_map' and 'food_cuisine_map' maps.
            self.food_rating_map[foods[i]] = ratings[i]
            self.food_cuisine_map[foods[i]] = cuisines[i]
            # Insert the '(-1 * rating, name)' element in the current cuisine's set.
            self.cuisine_food_map[cuisines[i]].add((-ratings[i], foods[i]))

    def changeRating(self, food: str, newRating: int) -> None:
        # Fetch cuisine name for food.
        cuisine_name = self.food_cuisine_map[food]

        # Find and delete the element from the respective cuisine's set.
        old_element = (-self.food_rating_map[food], food)
        self.cuisine_food_map[cuisine_name].remove(old_element)

        # Update food's rating in 'food_rating' map.
        self.food_rating_map[food] = newRating
        # Insert the '(-1 * new rating, name)' element in the respective cuisine's set.
        self.cuisine_food_map[cuisine_name].add((-newRating, food))

    def highestRated(self, cuisine: str) -> str:
        highest_rated = self.cuisine_food_map[cuisine][0]
        # Return name of the highest-rated 'food' of 'cuisine'.
        return highest_rated[1]

4.7.287 - 2025-09-16 18:41:40 +0300 MSK

Replace Non-Coprime Numbers in Array
from math import gcd

class Solution(object):
    def replaceNonCoprimes(self, nums):
        stack = []

        for num in nums:
            while stack:
                g = gcd(stack[-1], num)
                if g == 1:
                    break
                num = (stack.pop() * num) // g
            stack.append(num)

        return stack

4.7.288 - 2025-09-15 18:04:52 +0300 MSK

Maximum Number of Words You Can Type
class Solution:
    def canBeTypedWords(self, text: str, brokenLetters: str) -> int:
        ignore = False
        res = 0
        for char in itertools.chain(text, " "):
            if char == " ":
                if ignore:
                    ignore = False
                else:
                    res += 1
            elif char in brokenLetters:
                ignore = True
        return res

4.7.289 - 2025-09-14 19:11:43 +0300 MSK

Vowel Spellchecker
class Solution(object):
    def spellchecker(self, wordlist, queries):
        def devowel(word):
            return "".join('*' if c in 'aeiou' else c
                           for c in word)

        words_perfect = set(wordlist)
        words_cap = {}
        words_vow = {}

        for word in wordlist:
            wordlow = word.lower()
            words_cap.setdefault(wordlow, word)
            words_vow.setdefault(devowel(wordlow), word)

        def solve(query):
            if query in words_perfect:
                return query

            queryL = query.lower()
            if queryL in words_cap:
                return words_cap[queryL]

            queryLV = devowel(queryL)
            if queryLV in words_vow:
                return words_vow[queryLV]
            return ""

        return tuple(map(solve, queries))

4.7.290 - 2025-09-13 18:48:49 +0300 MSK

Find Most Frequent Vowel and Consonant
class Solution:
    def maxFreqSum(self, s: str) -> int:
        freqs = [0] * 26
        for char in s:
            freqs[ord(char) - 97] += 1
        max_vow, max_con = 0, 0
        for i in range(26):
            if chr(i + 97) in ("a", "e", "i", "o", "u"):
                max_vow = max(max_vow, freqs[i])
            else:
                max_con = max(max_con, freqs[i])
        return max_vow + max_con

4.7.291 - 2025-09-12 21:22:49 +0300 MSK

Vowels Game in a String
class Solution:
    def doesAliceWin(self, s: str) -> bool:
        return any(c in "aeiou" for c in s)

4.7.292 - 2025-09-11 20:29:02 +0300 MSK

Sort Vowels in a String
class Solution:
    def sortVowels(self, s: str) -> str:
        vowels = []

        s_list = list(s)

        # collect all vowels
        for i in s_list:
            if i in "AEIOUaeiou":
                vowels.append(i)
        
        if vowels == []:
            return s

        # sort the vowels
        vowels.sort()

        count = 0

        # replace original vowels with sorted ones
        for j in range(len(s)):
            if s_list[j] in "AEIOUaeiou":
                s_list[j] = vowels[count]
                count += 1

        return "".join(s_list)

4.7.293 - 2025-09-10 18:11:04 +0300 MSK

Minimum Number of People to Teach
class Solution:
    def minimumTeachings(
        self, n: int, languages: List[List[int]], friendships: List[List[int]]
    ) -> int:
        cncon = set()
        for friendship in friendships:
            mp = {}
            conm = False
            for lan in languages[friendship[0] - 1]:
                mp[lan] = 1
            for lan in languages[friendship[1] - 1]:
                if lan in mp:
                    conm = True
                    break
            if not conm:
                cncon.add(friendship[0] - 1)
                cncon.add(friendship[1] - 1)

        max_cnt = 0
        cnt = [0] * (n + 1)
        for friendship in cncon:
            for lan in languages[friendship]:
                cnt[lan] += 1
                max_cnt = max(max_cnt, cnt[lan])

        return len(cncon) - max_cnt

4.7.294 - 2025-09-09 18:44:51 +0300 MSK

Number of People Aware of a Secret
class Solution:
    def peopleAwareOfSecret(self, n: int, delay: int, forget: int) -> int:
        know, share = deque([(1, 1)]), deque([])
        know_cnt, share_cnt = 1, 0
        for i in range(2, n + 1):
            if know and know[0][0] == i - delay:
                know_cnt -= know[0][1]
                share_cnt += know[0][1]
                share.append(know[0])
                know.popleft()
            if share and share[0][0] == i - forget:
                share_cnt -= share[0][1]
                share.popleft()
            if share:
                know_cnt += share_cnt
                know.append((i, share_cnt))
        return (know_cnt + share_cnt) % (10**9 + 7)

4.7.295 - 2025-09-08 18:09:53 +0300 MSK

Convert Integer to the Sum of Two No-Zero Integers
class Solution:
    def getNoZeroIntegers(self, n: int) -> List[int]:
        for A in range(1, n):
            B = n - A
            if "0" not in str(A) + str(B):
                return [A, B]
        return []

4.7.296 - 2025-09-07 11:16:52 +0300 MSK

Minimum Operations to Equalize Array
class Solution:
    def minOperations(self, nums: List[int]) -> int:
        num1 = nums[0]
        for num in nums[1:]:
            if num != num1:
                return 1
        return 0

4.7.297 - 2025-09-07 11:00:41 +0300 MSK

Find N Unique Integers Sum up to Zero
class Solution:
    def sumZero(self, n: int) -> List[int]:
        res = []
        for i in range(1, n, 2):
            res.extend((i, -i))
        if len(res) < n:
            res.append(0)
        return res

4.7.298 - 2025-09-06 17:38:19 +0300 MSK

Minimum Operations to Make Array Elements Zero
class Solution:
    def get(self, num: int) -> int:
        i = 1
        base = 1
        cnt = 0
        while base <= num:
            cnt += ((i + 1) // 2) * (min(base * 2 - 1, num) - base + 1)
            i += 1
            base *= 2
        return cnt

    def minOperations(self, queries: List[List[int]]) -> int:
        res = 0
        for q in queries:
            res += (self.get(q[1]) - self.get(q[0] - 1) + 1) // 2
        return res

4.7.299 - 2025-09-05 19:23:51 +0300 MSK

Minimum Operations to Make the Integer Zero
class Solution:
    def makeTheIntegerZero(self, num1: int, num2: int) -> int:
        k = 1
        while True:
            x = num1 - num2 * k
            if x < k:
                return -1
            if k >= x.bit_count():
                return k
            k += 1

4.7.300 - 2025-09-04 22:15:30 +0300 MSK

Find Closest Person
class Solution:
    def findClosest(self, x: int, y: int, z: int) -> int:
        dxz = abs(x - z)
        dyz = abs(y - z)
        if dxz < dyz:
            return 1
        elif dxz > dyz:
            return 2
        else:
            return 0

4.7.301 - 2025-09-03 18:20:51 +0300 MSK

Find the Number of Ways to Place People II
class Solution:
    def numberOfPairs(self, points: List[List[int]]) -> int:
        ans = 0
        points.sort(key=lambda x: (x[0], -x[1]))

        for i in range(len(points) - 1):
            pointA = points[i]
            xMin = pointA[0] - 1
            xMax = math.inf
            yMin = -math.inf
            yMax = pointA[1] + 1

            for j in range(i + 1, len(points)):
                pointB = points[j]
                if (
                    pointB[0] > xMin
                    and pointB[0] < xMax
                    and pointB[1] > yMin
                    and pointB[1] < yMax
                ):
                    ans += 1
                    xMin = pointB[0]
                    yMin = pointB[1]

        return ans

4.7.302 - 2025-09-02 20:18:23 +0300 MSK

Find the Number of Ways to Place People I
class Solution:
    def numberOfPairs(self, points: List[List[int]]) -> int:
        ans = 0
        n = len(points)

        for i in range(n):
            pointA = points[i]
            for j in range(n):
                pointB = points[j]
                if i == j or not (
                    pointA[0] <= pointB[0] and pointA[1] >= pointB[1]
                ):
                    continue
                if n == 2:
                    ans += 1
                    continue

                illegal = False
                for k in range(n):
                    if k == i or k == j:
                        continue

                    pointTmp = points[k]
                    isXContained = (
                        pointTmp[0] >= pointA[0] and pointTmp[0] <= pointB[0]
                    )
                    isYContained = (
                        pointTmp[1] <= pointA[1] and pointTmp[1] >= pointB[1]
                    )
                    if isXContained and isYContained:
                        illegal = True
                        break
                if not illegal:
                    ans += 1
        return ans

4.7.303 - 2025-09-01 17:35:05 +0300 MSK

Maximum Average Pass Ratio
class Solution:
    def maxAverageRatio(self, classes: List[List[int]], extraStudents: int) -> float:
        n = len(classes)
        res = 0
        for i in range(n):
            pass_, total = classes[i]
            profit = ((pass_ + 1) / (total + 1)) - (pass_ / total)
            classes[i] = (-profit, pass_, total)
        heapq.heapify(classes)
        while classes and extraStudents > 0:
            _, pass_, total = heapq.heappop(classes)
            if pass_ == total:
                res += 1
            else:
                pass_ += 1
                total += 1
                profit = ((pass_ + 1) / (total + 1)) - (pass_ / total)
                heapq.heappush(classes, (-profit, pass_, total))
                extraStudents -= 1
        for _, pass_, total in classes:
            res += pass_ / total
        return res / n

4.7.304 - 2025-08-31 15:07:32 +0300 MSK

Sudoku Solver
class Solution:
    def solveSudoku(self, board: list[list[str]]) -> None:
        n, N = 3, 9
        rows = [[0] * (N + 1) for _ in range(N)]
        cols = [[0] * (N + 1) for _ in range(N)]
        boxes = [[0] * (N + 1) for _ in range(N)]
        sudokuSolved = False

        def couldPlace(d, row, col):
            idx = (row // n) * n + col // n
            return (rows[row][d] + cols[col][d] + boxes[idx][d]) == 0

        def placeNumber(d, row, col):
            idx = (row // n) * n + col // n
            rows[row][d] += 1
            cols[col][d] += 1
            boxes[idx][d] += 1
            board[row][col] = str(d)

        def removeNumber(d, row, col):
            idx = (row // n) * n + col // n
            rows[row][d] -= 1
            cols[col][d] -= 1
            boxes[idx][d] -= 1
            board[row][col] = '.'

        def placeNextNumbers(row, col):
            nonlocal sudokuSolved
            if row == N - 1 and col == N - 1:
                sudokuSolved = True
            elif col == N - 1:
                backtrack(row + 1, 0)
            else:
                backtrack(row, col + 1)

        def backtrack(row, col):
            nonlocal sudokuSolved
            if board[row][col] == '.':
                for d in range(1, 10):
                    if couldPlace(d, row, col):
                        placeNumber(d, row, col)
                        placeNextNumbers(row, col)
                        if not sudokuSolved:
                            removeNumber(d, row, col)
            else:
                placeNextNumbers(row, col)

        for i in range(N):
            for j in range(N):
                if board[i][j] != '.':
                    placeNumber(int(board[i][j]), i, j)
        backtrack(0, 0)

4.7.305 - 2025-08-31 14:18:46 +0300 MSK

Restore Finishing Order
class Solution:
    def recoverOrder(self, order: List[int], friends: List[int]) -> List[int]:
        for i in range(len(order)):
            if order[i] in friends:
                order[i] = (i, order[i])
            else:
                order[i] = (101, 101)
        order.sort()
        while order[-1] == (101, 101):
            order.pop()
        for i in range(len(order)):
            order[i] = order[i][1]
        return order

4.7.306 - 2025-08-31 14:13:40 +0300 MSK

Find The Least Frequent Digit
class Solution:
    def getLeastFrequentDigit(self, n: int) -> int:
        freqs = [0] * 10
        while n > 0:
            freqs[n % 10] += 1
            n //= 10
        min_freq, min_num = math.inf, -math.inf
        for i in range(10):
            if freqs[i] != 0 and (
                freqs[i] < min_freq or (freqs[i] == min_freq and i < min_num)
            ):
                min_freq, min_num = freqs[i], i
        return min_num

4.7.307 - 2025-08-30 20:16:00 +0300 MSK

Valid Sudoku
class Solution:
    def isValidSudoku(self, board: List[List[str]]) -> bool:
        rows = [[False] * 9 for _ in range(9)]
        cols = [[False] * 9 for _ in range(9)]
        boxes = [[False] * 9 for _ in range(9)]

        for i in range(9):
            for j in range(9):
                if board[i][j] != '.':
                    num = ord(board[i][j]) - ord('1')
                    boxIndex = (i // 3) * 3 + (j // 3)
                    if rows[i][num] or cols[j][num] or boxes[boxIndex][num]:
                        return False
                    rows[i][num] = cols[j][num] = boxes[boxIndex][num] = True
        return True

4.7.308 - 2025-08-29 19:59:52 +0300 MSK

Alice and Bob Playing Flower Game
class Solution:
    def flowerGame(self, n: int, m: int) -> int:
        return (m * n) // 2

4.7.309 - 2025-08-28 16:59:23 +0300 MSK

Sort Matrix by Diagonals
class Solution:
    def sortMatrix(self, grid: List[List[int]]) -> List[List[int]]:
        n = len(grid)

        for i in range(n):
            tmp = [grid[i + j][j] for j in range(n - i)]
            tmp.sort(reverse=True)
            for j in range(n - i):
                grid[i + j][j] = tmp[j]

        for j in range(1, n):
            tmp = [grid[i][j + i] for i in range(n - j)]
            tmp.sort()
            for i in range(n - j):
                grid[i][j + i] = tmp[i]

        return grid

4.7.310 - 2025-08-27 16:22:50 +0300 MSK

Length of Longest V-Shaped Diagonal Segment
class Solution:
    def lenOfVDiagonal(self, grid: List[List[int]]) -> int:
        DIRS = [(1, 1), (1, -1), (-1, -1), (-1, 1)]
        m, n = len(grid), len(grid[0])

        @cache
        def dfs(cx, cy, direction, turn, target):
            nx, ny = cx + DIRS[direction][0], cy + DIRS[direction][1]
            # If it goes beyond the boundary or the next node's value is not the target value, then return
            if nx < 0 or ny < 0 or nx >= m or ny >= n or grid[nx][ny] != target:
                return 0
            turn_int = 1 if turn else 0
            # Continue walking in the original direction.
            max_step = dfs(nx, ny, direction, turn, 2 - target)
            if turn:
                # Clockwise rotate 90 degrees turn
                max_step = max(
                    max_step,
                    dfs(nx, ny, (direction + 1) % 4, False, 2 - target),
                )
            return max_step + 1

        res = 0
        for i in range(m):
            for j in range(n):
                if grid[i][j] == 1:
                    for direction in range(4):
                        res = max(res, dfs(i, j, direction, True, 2) + 1)
        return res

4.7.311 - 2025-08-26 09:10:25 +0300 MSK

String to Integer (atoi)
class Solution:
    def myAtoi(self, s: str) -> int:
        digits = []
        sign = None
        found_dig = False
        for char in s:
            if char.isdigit():
                digits.append(int(char))
                found_dig = True
            elif not found_dig and sign is None and char == " ":
                continue
            elif not found_dig and sign is None and char in ("+", "-"):
                sign = 1
                if char == "-":
                    sign = -1
            else:
                break
        if sign is None:
            sign = 1
        res = 0
        cnt = 0
        while digits:
            res += digits.pop() * (10 ** cnt)
            cnt += 1
            if res > 2 ** 31 - 1 and sign == 1:
                return 2 ** 31 - 1
            elif res > 2 ** 31 and sign == -1:
                return -(2 ** 31)
        return res * sign 

4.7.312 - 2025-08-26 08:16:39 +0300 MSK

Reverse Integer
class Solution:
    def reverse(self, x: int) -> int:
        digits = []
        neg = 1
        if x < 0:
            neg = -1
            x = -x
        while x > 0:
            digits.append(x % 10)
            x //= 10
        cnt, res = 0, 0
        while digits:
            res += digits.pop() * (10 ** cnt)
            cnt += 1
            if res > 2 ** 31:
                return 0
        return res * neg

4.7.313 - 2025-08-26 08:11:15 +0300 MSK

Maximum Area of Longest Diagonal Rectangle
class Solution:
    def areaOfMaxDiagonal(self, dimensions: List[List[int]]) -> int:
        max_diag, max_area = 0, 0
        for ln, wdth in dimensions:
            diag, area = ln ** 2 + wdth ** 2, ln * wdth
            if diag > max_diag or (diag == max_diag and area > max_area):
                max_diag, max_area = diag, area
        return max_area

4.7.314 - 2025-08-25 17:00:38 +0300 MSK

My Calendar I
class MyCalendar:
    def __init__(self): 
        self.events = SortedList()

    def book(self, startTime: int, endTime: int) -> bool:
        insert_index = self.events.bisect_left((startTime, endTime))
        if (
            insert_index - 1 >= 0 
            and startTime < self.events[insert_index - 1][1]
        ) or (
            insert_index < len(self.events) 
            and self.events[insert_index][0] < endTime
        ):
            return False
        self.events.add((startTime, endTime))
        return True


# Your MyCalendar object will be instantiated and called as such:
# obj = MyCalendar()
# param_1 = obj.book(startTime,endTime)

4.7.315 - 2025-08-25 11:40:44 +0300 MSK

Diagonal Traverse
class Solution:
    def findDiagonalOrder(self, mat: List[List[int]]) -> List[int]:
        res, rows, cols, cur = [], len(mat), len(mat[0]), []
        for i in range(rows + cols):
            if i < rows:
                row, col = i, 0
            else:
                row, col = rows - 1, (i - rows) + 1 
            while row >= 0 and col < cols:
                cur.append(mat[row][col])
                row, col = row - 1, col + 1
            if i % 2 != 0:
                cur.reverse()
            res.extend(cur)
            cur.clear()
        return res
        

             

4.7.316 - 2025-08-24 20:51:14 +0300 MSK

Design Circular Queue
class MyCircularQueue:

    def __init__(self, k: int):
        self._k = k
        self._q = [-1] * k
        self._i = 0
        self._len = 0

    def enQueue(self, value: int) -> bool:
        if self.isFull():
            return False
        self._q[self._i] = value
        self._i = (self._i + 1) % self._k
        self._len += 1
        return True

    def deQueue(self) -> bool:
        if self._len > 0:
            self._len -= 1
            return True
        return False

    def Front(self) -> int:
        if self.isEmpty():
            return -1
        return self._q[(self._i - self._len + self._k) % self._k]  
        
    def Rear(self) -> int:
        if self.isEmpty():
            return -1
        return self._q[(self._i - 1 + self._k) % self._k]

    def isEmpty(self) -> bool:
        return self._len == 0

    def isFull(self) -> bool:
        return self._len == self._k


# Your MyCircularQueue object will be instantiated and called as such:
# obj = MyCircularQueue(k)
# param_1 = obj.enQueue(value)
# param_2 = obj.deQueue()
# param_3 = obj.Front()
# param_4 = obj.Rear()
# param_5 = obj.isEmpty()
# param_6 = obj.isFull()

4.7.317 - 2025-08-24 19:54:22 +0300 MSK

Serialize and Deserialize BST
# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

class Codec:

    def serialize(self, root: Optional[TreeNode]) -> str:
        """Encodes a tree to a single string.
        """
        if root is None:
            return ""
        left, right = self.serialize(root.left), self.serialize(root.right)
        return f"{root.val}|{len(left)}|{left}{right}"

    def deserialize(self, data: str) -> Optional[TreeNode]:
        """Decodes your encoded data to tree.
        """
        if not data:
            return None
        val, left_len, rest = data.split("|", 2)
        root = TreeNode(int(val))
        root.left = self.deserialize(rest[:int(left_len)])
        root.right = self.deserialize(rest[int(left_len):])
        return root    

# Your Codec object will be instantiated and called as such:
# Your Codec object will be instantiated and called as such:
# ser = Codec()
# deser = Codec()
# tree = ser.serialize(root)
# ans = deser.deserialize(tree)
# return ans

4.7.318 - 2025-08-24 19:38:13 +0300 MSK

Shuffle an Array
class Solution:

    def __init__(self, nums: List[int]):
        self._orig = nums
        self._cur = nums.copy()

    def reset(self) -> List[int]:
        return self._orig

    def shuffle(self) -> List[int]:
        return random.sample(self._orig, k=len(self._orig))


# Your Solution object will be instantiated and called as such:
# obj = Solution(nums)
# param_1 = obj.reset()
# param_2 = obj.shuffle()

4.7.319 - 2025-08-24 19:30:45 +0300 MSK

Maximum Height of a Triangle
class Solution:
    def maxHeightOfTriangle(self, red: int, blue: int) -> int:
        return max(self.helper(red, blue), self.helper(blue, red))
    
    def helper(self, red: int, blue: int) -> int:
        h = 0
        i = 1
        
        while True:
            if i % 2 == 1:
                if red >= i:
                    red -= i
                else:
                    break
            else:
                if blue >= i:
                    blue -= i
                else:
                    break
            h += 1
            i += 1
        
        return h

4.7.320 - 2025-08-24 19:28:22 +0300 MSK

Count the Number of Incremovable Subarrays I
class Solution:
    def incremovableSubarrayCount(self, nums: List[int]) -> int:
        result = 0
        n = len(nums)
        if n == 0:
            return 0
        prefix_idx, suffix_idx = 0, n - 1
        while prefix_idx + 1 < n and nums[prefix_idx + 1] > nums[prefix_idx]:
            prefix_idx += 1
        if prefix_idx == n - 1:
            return (n * (n + 1)) // 2
        while suffix_idx > 0 and nums[suffix_idx] > nums[suffix_idx - 1]:
            suffix_idx -= 1
        result += prefix_idx + 1
        result += n - suffix_idx + 1
        i = 0
        j = suffix_idx
        while i <= prefix_idx:
            while j < n and nums[i] >= nums[j]:
                j += 1
            result += n - j
            i += 1
        return result

4.7.321 - 2025-08-24 19:26:17 +0300 MSK

GCD of Odd and Even Sums
class Solution:
    def gcdOfOddEvenSums(self, n: int) -> int:
        odd_num = 1 + (n - 1) * 2
        even_num = 2 + (n - 1) * 2
        odd_sum = (n * (1 + odd_num)) // 2
        even_sum = (n * (2 + even_num)) // 2
        return math.gcd(odd_sum, even_sum)

4.7.322 - 2025-08-24 19:18:26 +0300 MSK

Flip Square Submatrix Vertically
class Solution:
    def reverseSubmatrix(self, grid: List[List[int]], x: int, y: int, k: int) -> List[List[int]]:
        rows, cols = len(grid), len(grid[0])
        for col in range(y, y + k):
            for row_dlt in range(k // 2):
                row1 = x + row_dlt
                row2 = (x + k - 1) - row_dlt
                grid[row1][col], grid[row2][col] = grid[row2][col], grid[row1][col]
        return grid

4.7.323 - 2025-08-24 19:07:06 +0300 MSK

Find Books with Polarized Opinions
 SELECT r.book_id,
       b.title,
       b.author,
       b.genre,
       b.pages,
       Max(r.session_rating) - Min(r.session_rating) rating_spread,
       Round(( Sum(CASE WHEN r.session_rating < 3 THEN 1 ELSE 0 END + CASE WHEN
                           r.session_rating >
                           3 THEN 1 ELSE 0 END) ) / COUNT(r.session_id) ::
             Decimal(10, 2), 2)                      polarization_score
FROM   reading_sessions r
       INNER JOIN books b USING(book_id)
GROUP  BY r.book_id,
          b.title,
          b.author,
          b.genre,
          b.pages
HAVING COUNT(r.session_id) > 4
       AND Max(r.session_rating) > 3
       AND Min(r.session_rating) < 3
       AND Round(( Sum(CASE WHEN r.session_rating < 3 THEN 1 ELSE 0 END + CASE
                       WHEN
                                   r.session_rating >
                                   3 THEN 1 ELSE 0 END) ) / COUNT(r.session_id)
                 ::
                 Decimal(
                     10, 2), 2) >= 0.6
ORDER  BY polarization_score desc,
          b.title desc  

4.7.324 - 2025-08-24 19:02:12 +0300 MSK

Trionic Array I
class Solution:
    def isTrionic(self, nums: List[int]) -> bool:
        seg, n = 0, len(nums)
        for i in range(1, n):
            cur, prv = nums[i], nums[i - 1]
            if cur == prv:
                return False
            if seg == 0:
                if cur < prv:
                    if i == 1:
                        return False
                    seg = 1
            elif seg == 1:
                if cur > prv:
                    seg = 2
            elif seg == 2:
                if cur < prv:
                    return False
        return seg == 2 

4.7.325 - 2025-08-24 18:57:13 +0300 MSK

Earliest Finish Time for Land and Water Rides I
from typing import List

class Solution:
    def earliestFinishTime(self,landStartTime: List[int],landDuration: List[int],waterStartTime: List[int],waterDuration: List[int]) -> int:
        res = float('inf')
        n, m = len(landStartTime), len(waterStartTime)
        for i in range(n):
            a, d = landStartTime[i], landDuration[i]
            for j in range(m):
                b, e = waterStartTime[j], waterDuration[j]
                land_end = a + d
                start_water = max(land_end, b)
                finish1 = start_water + e
                water_end = b + e
                start_land = max(water_end, a)
                finish2 = start_land + d
                res = min(res, finish1, finish2)
        return res

4.7.326 - 2025-08-24 18:52:47 +0300 MSK

Check Divisibility by Digit Sum and Product
class Solution:
    def checkDivisibility(self, n: int) -> bool:
        sm, pr, num = 0, 1, n
        while num > 0:
            dig = num % 10
            num //= 10
            sm += dig
            pr *= dig
        return n % (sm + pr) == 0

4.7.327 - 2025-08-24 18:50:32 +0300 MSK

Coupon Code Validator
class Solution:
    def validateCoupons(self, code: List[str], businessLine: List[str], isActive: List[bool]) -> List[str]:
        res, n = [], len(code)
        b_order = {"electronics": 0, "grocery": 1, "pharmacy": 2, "restaurant": 3}
        for i in range(n):
            if (
                isActive[i] 
                and code[i] 
                and re.match("^[a-zA-Z0-9_]+$", code[i]) 
                and businessLine[i] in (
                    "electronics", "grocery", "pharmacy", "restaurant"
                )
            ):
                res.append(i)
        def sort(i: int) -> tuple[str, str]:
            return (b_order[businessLine[i]], code[i])
        res.sort(key=sort)
        for i in range(len(res)):
            res[i] = code[res[i]]
        return res

4.7.328 - 2025-08-24 18:39:15 +0300 MSK

Hexadecimal and Hexatrigesimal Conversion
class Solution:
    def concatHex36(self, n: int) -> str:
        res = []
        for num, base in ((n ** 3, 36), (n ** 2, 16)):
            while num > 0:
                dig = num % base
                if dig < 10:
                    res.append(str(dig))
                else:
                    res.append(chr((dig - 10) + 65))
                num //= base
        res.reverse()
        return "".join(res)

4.7.329 - 2025-08-24 18:38:15 +0300 MSK

Hexadecimal and Hexatrigesimal Conversion
class Solution:
    def concatHex36(self, n: int) -> str:
        res, cur = [], []
        for num, base in ((n ** 2, 16), (n ** 3, 36)):
            while num > 0:
                dig = num % base
                if dig < 10:
                    cur.append(str(dig))
                else:
                    cur.append(chr((dig - 10) + 65))
                num //= base
            cur.reverse()
            res.extend(cur)
            cur.clear()
        return "".join(res)

4.7.330 - 2025-08-24 18:22:04 +0300 MSK

Check if Any Element Has Prime Frequency
class Solution:
    def checkPrimeFrequency(self, nums: List[int]) -> bool:
        def is_prime(v: int) -> bool:
            for i in range(2, int(math.sqrt(v)) + 1):
                if v % i == 0:
                    return False
            return True
        freqs = [0] * 101
        for num in nums:
            freqs[num] += 1
        for freq in freqs:
            if freq > 1 and is_prime(freq):
                return True
        return False

4.7.331 - 2025-08-24 18:15:48 +0300 MSK

Generate Tag for Video Caption
class Solution:
    def generateTag(self, caption: str) -> str:
        res, n, cur = [], len(caption), []
        for i in range(n):
            ch = caption[i]
            if ch.isalpha():
                cur.append(ch.lower())
            if (ch == " " or i + 1 == n) and cur:
                if res:
                    cur[0] = cur[0].upper()
                res.append("".join(cur))
                cur.clear()
        return "".join(itertools.chain("#", res))[:100]
        

4.7.332 - 2025-08-24 18:07:04 +0300 MSK

Find Books with No Available Copies
SELECT 
    book_id, 
    MAX(title) AS title, 
    MAX(author) AS author, 
    MAX(genre) AS genre, 
    MAX(publication_year) AS publication_year, 
    MAX(total_copies) AS current_borrowers 
FROM
    (
        SELECT 
            book_id,
            title,
            author, 
            genre,publication_year, 
            total_copies,
            total_copies AS total_remain 
        FROM 
            library_books
        UNION 
            ALL
        SELECT 
            book_id, 
            '', 
            '', 
            '', 
            1000, 
            0, 
            -1 
        FROM 
            borrowing_records 
        WHERE 
            return_date IS NULL
    ) sub
GROUP BY 
    book_id
HAVING 
    SUM(total_remain) = 0
ORDER BY 
    current_borrowers DESC, 
    title;

4.7.333 - 2025-08-24 18:01:04 +0300 MSK

Find Minimum Log Transportation Cost
class Solution:
    def minCuttingCost(self, n: int, m: int, k: int) -> int:
        ans = 0
        if m <= k and n <= k:
            return 0
        if m > k and n <= k:
            ans += (m - k) * k
        if n > k and m <= k:
            ans += (n - k) * k
        return ans

4.7.334 - 2025-08-24 17:55:59 +0300 MSK

Smallest Index With Digit Sum Equal to Index
class Solution:
    def smallestIndex(self, nums: List[int]) -> int:
        for i in range(len(nums)):
            num = nums[i]
            sm = 0
            while num > 0:
                sm += num % 10
                num //= 10
            if sm == i:
                return i
        return -1

4.7.335 - 2025-08-24 17:54:29 +0300 MSK

Minimum Deletions for At Most K Distinct Characters
class Solution:
    def minDeletion(self, s: str, k: int) -> int:
        freqs, n = [0] * 26, len(s)
        for i in range(n):
            freqs[ord(s[i]) - 97] += 1
        freqs.sort()
        res = 0
        for i in range(26 - k):
            res += freqs[i]
        return res

4.7.336 - 2025-08-24 17:52:40 +0300 MSK

Minimum Deletions for At Most K Distinct Characters
class Solution:
    def minDeletion(self, s: str, k: int) -> int:
        freqs, n = [0] * 26, len(s)
        for i in range(n):
            freqs[ord(s[i]) - 97] += 1
        freqs.sort(reverse=True)
        res = 0
        while len(freqs) > k:
            res += freqs.pop()
        return res

4.7.337 - 2025-08-24 17:46:18 +0300 MSK

Find Most Frequent Vowel and Consonant
class Solution:
    def maxFreqSum(self, s: str) -> int:
        freqs, n = [0] * 26, len(s)
        for i in range(n):
            freqs[ord(s[i]) - 97] += 1
        max_vow, max_con = 0, 0
        vow = tuple(ord(ch) - 97 for ch in ("a", "e", "i", "o", "u"))
        for i in range(26):
            if i in vow:
                max_vow = max(max_vow, freqs[i])
            else:
                max_con = max(max_con, freqs[i])
        return max_vow + max_con

4.7.338 - 2025-08-24 17:42:32 +0300 MSK

Maximum Product of Two Digits
class Solution:
    def maxProduct(self, n: int) -> int:
        num1, num2 = -math.inf, -math.inf
        while n > 0:
            dig = n % 10
            if dig > num2:
                num1, num2 = num2, dig
            elif dig > num1:
                num1 = dig
            n //= 10
        return num1 * num2

4.7.339 - 2025-08-24 17:41:29 +0300 MSK

Maximum Product of Two Digits
class Solution:
    def maxProduct(self, n: int) -> int:
        dig = []
        while n > 0:
            heapq.heappush(dig, -(n % 10))
            n //= 10
        return abs(heapq.heappop(dig) * heapq.heappop(dig))

4.7.340 - 2025-08-24 17:40:23 +0300 MSK

Find Closest Person
class Solution:
    def findClosest(self, x: int, y: int, z: int) -> int:
        diff1, diff2 = abs(z - x), abs(z - y)
        if diff1 == diff2:
            return 0
        if diff1 < diff2:
            return 1
        return 2

4.7.341 - 2025-08-24 17:38:35 +0300 MSK

Minimum Operations to Make Array Sum Divisible by K
class Solution:
    def minOperations(self, nums: List[int], k: int) -> int:
        return sum(nums) % k

4.7.342 - 2025-08-24 17:36:34 +0300 MSK

Minimum Pair Removal to Sort Array I
class Solution:
    def minimumPairRemoval(self, nums: List[int], ans = 0) -> int:
        def notSorted(nums: List[int]) -> bool:
            for a, b in pairwise(nums):
                if a > b: 
                    return True
            return False
        
        while notSorted(nums):
            minSum, mnIdx = inf, -1
            for i, pair in enumerate(pairwise(nums)):
                if sum(pair) < minSum:
                    minSum, mnIdx, delIdx = sum(pair), i, i + 1
            nums[mnIdx] = minSum
            del nums[delIdx]
            ans += 1
        return ans 

4.7.343 - 2025-08-24 17:22:24 +0300 MSK

Minimum Cost to Reach Every Position
class Solution:
    def minCosts(self, cost: List[int]) -> List[int]:
        
        return list(accumulate(cost, min))

4.7.344 - 2025-08-24 17:12:42 +0300 MSK

Reverse Degree of a String
class Solution:
    def reverseDegree(self, s: str) -> int:
        res, n = 0, len(s)
        for i in range(n):
            res += (i + 1) * (26 - (ord(s[i]) - 97))
        return res

4.7.345 - 2025-08-24 17:10:49 +0300 MSK

Maximum Containers on a Ship
class Solution:
    def maxContainers(self, n: int, w: int, maxWeight: int) -> int:
        return min(maxWeight // w, n * n)

4.7.346 - 2025-08-24 17:08:09 +0300 MSK

Unique 3-Digit Even Numbers
class Solution:
    def totalNumbers(self, digits: List[int]) -> int:
        enc = set()
        p = [a * 100 + b * 10 + c for a, b, c in itertools.permutations(digits, 3)]
        for num in p:
            if num not in enc and len(str(num)) == 3:
                if num % 2 == 0:
                    enc.add(num)
        return len(enc)

4.7.347 - 2025-08-24 17:02:11 +0300 MSK

Find the Largest Almost Missing Integer
class Solution:
    def largestInteger(self, nums: List[int], k: int) -> int:
        n = len(nums)
        subarray_count = defaultdict(int)
        for i in range(n - k + 1):
            for num in set(nums[i:i+k]):
                subarray_count[num] += 1
        res = -1
        for num, count in subarray_count.items():
            if count == 1:
                res = max(res, num)
        return res

4.7.348 - 2025-08-24 16:02:46 +0300 MSK

Transform Array by Parity
class Solution:
    def transformArray(self, nums: List[int]) -> List[int]:
        for i in range(len(nums)):
            val = nums[i]
            if val % 2 == 0:
                nums[i] = 0
            else:
                nums[i] = 1
        nums.sort()
        return nums

4.7.349 - 2025-08-24 16:00:53 +0300 MSK

Find Products with Valid Serial Numbers
SELECT 
    *
FROM 
    Products
WHERE 
    description ~ '\mSN[0-9]{4}-[0-9]{4}\M'
ORDER BY 
    product_id ASC;

4.7.350 - 2025-08-24 15:55:14 +0300 MSK

Check If Digits Are Equal in String After Operations I
class Solution:
    def hasSameDigits(self, s: str) -> bool:
        stack = list(map(int, s))
        stack.reverse()
        while len(stack) > 2:
            prev = stack.pop()
            for i in reversed(range(len(stack))):
                stack[i], prev = (prev + stack[i]) % 10, stack[i]
        return stack[0] == stack[1]

4.7.351 - 2025-08-24 15:40:47 +0300 MSK

Find Special Substring of Length K
class Solution:
    def hasSpecialSubstring(self, s: str, k: int) -> bool:
        cnt, n = 0, len(s)
        for i in range(n):
            if i > 0 and s[i] == s[i - 1]:
                cnt += 1
            else:
                cnt = 1
            if cnt != k:
                continue
            if (
                i - cnt >= 0 and s[i - cnt] == s[i]
            ) or (
                i + 1 < n and s[i + 1] == s[i]
            ):
                cnt = 1
            else:
                return True
        return False

4.7.352 - 2025-08-24 15:35:22 +0300 MSK

Sum of Good Numbers
class Solution:
    def sumOfGoodNumbers(self, nums: List[int], k: int) -> int:
        res, n = 0, len(nums)
        for i in range(n):
            left, right, cur = -1, -1, nums[i]
            if i - k >= 0:
                left = nums[i - k]
            if i + k < n:
                right = nums[i + k]
            if left < cur > right:
                res += cur
        return res

4.7.353 - 2025-08-24 15:32:58 +0300 MSK

Maximum Difference Between Even and Odd Frequency I
class Solution:
    def maxDifference(self, s: str) -> int:
        freqs, n = [0] * 26, len(s)
        for i in range(n):
            freqs[ord(s[i]) - 97] += 1
        max_odd, min_even = -math.inf, math.inf
        for i in range(26):
            freq = freqs[i]
            if freq == 0:
                continue
            if freq % 2 == 0:
                min_even =  min(min_even, freq)
            else:
                max_odd = max(max_odd, freq)
        return max_odd - min_even

4.7.354 - 2025-08-24 15:21:21 +0300 MSK

Find Valid Pair of Adjacent Digits in String
class Solution:
    def findValidPair(self, s: str) -> str:
        freqs, n = [0] * 10, len(s)
        for i in range(n):
            freqs[int(s[i])] += 1
        for i in range(1, n):
            cur, prv = int(s[i]), int(s[i - 1])
            if cur != prv and freqs[cur] == cur and freqs[prv] == prv:
                return f"{prv}{cur}"
        return ""

4.7.355 - 2025-08-24 15:17:24 +0300 MSK

Find Valid Emails
SELECT 
    user_id,
    email
FROM 
    users
WHERE 
    email ~ '^\w+@[A-Za-z]+\.com$'
ORDER BY 
    user_id ASC;

4.7.356 - 2025-08-24 15:14:50 +0300 MSK

Count Partitions with Even Sum Difference
class Solution:
    def countPartitions(self, nums: List[int]) -> int:
        sm, n = [0] * len(nums), len(nums)
        sm[0] = nums[0]
        for i in range(n):
            sm[i] = sm[i - 1] + nums[i]
        res = 0
        for i in range(n - 1):
            left = sm[i]
            right = sm[-1] - left
            res += abs(right - left) % 2 == 0
        return res

4.7.357 - 2025-08-24 15:11:09 +0300 MSK

Sum of Variable Length Subarrays
class Solution:
    def subarraySum(self, nums: List[int]) -> int:
        sm, n = [0] * len(nums), len(nums)
        sm[0] = nums[0]
        for i in range(1, n):
            sm[i] = sm[i - 1] + nums[i]
        res = 0
        for i in range(n):
            left = max(0, i - nums[i])
            left_sum = 0
            if left > 0:
                left_sum = sm[left - 1]
            res += sm[i] - left_sum
        return res

4.7.358 - 2025-08-24 15:07:53 +0300 MSK

Maximum Difference Between Adjacent Elements in a Circular Array
class Solution:
    def maxAdjacentDistance(self, nums: List[int]) -> int:
        res = abs(nums[0] - nums[-1])
        for i in range(1, len(nums)):
            res = max(res, abs(nums[i] - nums[i - 1]))
        return res

4.7.359 - 2025-08-24 15:06:30 +0300 MSK

Zigzag Grid Traversal With Skip
class Solution:
    def zigzagTraversal(self, grid: List[List[int]]) -> List[int]:
        m, n = len(grid), len(grid[0])
        res = []
        skip = False
        for row in range(m):
            if row % 2 == 0:
                start, end, step = 0, n, 1
            else:
                start, end, step = n - 1, -1, -1
            for col in range(start, end, step):
                if not skip:
                    res.append(grid[row][col])
                skip = not skip
        return res

4.7.360 - 2025-08-24 15:00:31 +0300 MSK

Maximum Subarray With Equal Products
class Solution:
    def maxLength(self, A: List[int]) -> int:
        N = len(A)
        ans = 2
        last = {}
        i = 0
        for j, x in enumerate(A):
            for p in prime_divisors(x):
                i = max(i, last.get(p, -1) + 1)
                last[p] = j
            ans = max(ans, j - i + 1)
        
        return ans

def prime_divisors(x):
    d = 2
    while d * d <= x:
        if x % d == 0:
            x //= d
            while x % d == 0:
                x //= d
            yield d
        d += 1 + d & 1
    
    if x > 1:
        yield x

4.7.361 - 2025-08-24 14:57:30 +0300 MSK

Substring Matching Pattern
class Solution:
    def hasMatch(self, string: str, pattern: str) -> bool:
        left_part, right_part = pattern.split("*")
        left_idx = string.find(left_part)
        right_idx = string.find(right_part, left_idx + len(left_part))
        return left_idx != -1 and right_idx != -1

4.7.362 - 2025-08-24 14:47:52 +0300 MSK

Minimum Operations to Make Columns Strictly Increasing
class Solution:
    def minimumOperations(self, grid: List[List[int]]) -> int:
        m, n = len(grid), len(grid[0])
        res = 0
        for col in range(n):
            prv = grid[0][col]
            for row in range(1, m):
                val = grid[row][col]
                if val > prv:
                    prv = val
                else:
                    diff = (prv + 1) - val
                    res += diff
                    prv += 1
        return res

4.7.363 - 2025-08-24 14:42:38 +0300 MSK

Minimum Number of Operations to Make Elements in Array Distinct
class Solution:
    def minimumOperations(self, nums: List[int]) -> int:
        freqs, n = [0] * 101, len(nums)
        for i in range(n):
            freqs[nums[i]] += 1
        res = 0
        for i in range(0, n, 3):
            if max(freqs) == 1:
                return res
            res += 1
            for j in range(i, min(i + 3, n)):
                freqs[nums[j]] -= 1
        return res

4.7.364 - 2025-08-24 14:38:49 +0300 MSK

Count Subarrays of Length Three With a Condition
class Solution:
    def countSubarrays(self, nums: List[int]) -> int:
        res, n = 0, len(nums)
        for i in range(n - 2):
            if nums[i] + nums[i + 2] == nums[i + 1] / 2:
                res += 1
        return res

4.7.365 - 2025-08-24 14:36:54 +0300 MSK

Button with Longest Push Time
class Solution:
    def buttonWithLongestTime(self, events: List[List[int]]) -> int:
        (mx_idx, mx_time), n = events[0], len(events)
        for i in range(n):
            (cur_idx, cur_time), (prv_idx, prv_time) = events[i], events[i - 1]
            diff = cur_time - prv_time
            if diff > mx_time or (diff == mx_time and cur_idx < mx_idx):
                mx_idx, mx_time = cur_idx, diff
        return mx_idx

4.7.366 - 2025-08-24 14:33:39 +0300 MSK

Transformed Array
class Solution:
    def constructTransformedArray(self, nums: List[int]) -> List[int]:
        n = len(nums)
        res = [0] * n
        for i in range(n):
            num = nums[i]
            if num == 0:
                val = 0
            elif num > 0:
                val = nums[(i + num) % n]
            else:
                val = nums[(i - -num + n) % n]
            res[i] = val
        return res

4.7.367 - 2025-08-24 14:28:25 +0300 MSK

Smallest Number With All Set Bits
class Solution:
    def smallestNumber(self, n: int) -> int:
        res = 0
        while n > 0:
            res = (res << 1) | 1
            n //= 2
        return res

4.7.368 - 2025-08-24 14:25:47 +0300 MSK

Minimum Positive Sum Subarray
class Solution:
    def minimumSumSubarray(self, nums: List[int], l: int, r: int) -> int:
        sm, n = [0] * len(nums), len(nums)
        cur = 0
        for i in range(n):
            cur += nums[i]
            sm[i] = cur
        res = math.inf
        for i in range(n):
            left = 0
            if i > 0:
                left = sm[i - 1]
            for j in range(i + l - 1, min(i + r, n)):
                cur = sm[j] - left
                if cur > 0:
                    res = min(res, cur)
        if res == math.inf:
            return -1
        return res

4.7.369 - 2025-08-24 14:09:37 +0300 MSK

Stone Removal Game
class Solution:
    def canAliceWin(self, n: int) -> bool:
        cnt = 10
        while True:
            if n >= cnt:
                n -= cnt
                cnt -= 1
            else:
                return False
            if n >= cnt:
                n -= cnt
                cnt -= 1
            else:
                return True

4.7.370 - 2025-08-24 14:03:51 +0300 MSK

Make Array Elements Equal to Zero
class Solution:
    def countValidSelections(self, nums: List[int]) -> int:
        n, res = len(nums), 0
        left, right = [0 for _ in range(n)], [0 for _ in range(n)]
        for i in range(1, n):
            left[i] = left[i - 1] + nums[i - 1]
            right[-i - 1] = right[-i] + nums[-i]
        for i, num in enumerate(nums):
            if num != 0: continue
            if left[i] == right[i]: res += 2
            if abs(left[i] - right[i]) == 1: res += 1
        return res

4.7.371 - 2025-08-24 13:57:16 +0300 MSK

Adjacent Increasing Subarrays Detection I
class Solution:
    def hasIncreasingSubarrays(self, nums: List[int], k: int) -> bool:
        n = len(nums)
        cnt = 1
        prv_cnt = 0
        for i in range(1, n):
            cur, prv = nums[i], nums[i - 1]
            if cur > prv:
                cnt += 1
            else:
                prv_cnt, cnt = cnt, 1
            if cnt >= 2 * k or prv_cnt >= k and cnt >= k:
                return True
        return False

4.7.372 - 2025-08-24 13:46:58 +0300 MSK

Smallest Divisible Digit Product I
class Solution:
    def smallestNumber(self, n: int, t: int) -> int:
        while True:
            cur = n
            prd = 1
            while cur > 0:
                prd *= cur % 10
                if prd == 0:
                    break
                cur //= 10
            if prd % t == 0:
                return n
            n += 1

4.7.373 - 2025-08-24 13:33:19 +0300 MSK

Check Balanced String
class Solution:
    def isBalanced(self, num: str) -> bool:
        sm, n = 0, len(num)
        for i in range(n):
            if i % 2 == 0:
                sm += int(num[i])
            else:
                sm -= int(num[i])
        return sm == 0

4.7.374 - 2025-08-24 13:31:22 +0300 MSK

Find the Original Typed String I
class Solution:
    def possibleStringCount(self, word: str) -> int:
        res, n = 1, len(word)
        for i in range(1, n):
            cur, prev = word[i], word[i - 1]
            if cur == prev:
                res += 1
        return res

4.7.375 - 2025-08-24 13:27:05 +0300 MSK

Find X-Sum of All K-Long Subarrays I
class Solution:
    def findXSum(self, nums: List[int], k: int, x: int) -> List[int]:

        def do_sum (idx: int)-> int:

            ctr = Counter(nums[idx:idx + k])
            most_freq = nlargest(x, ctr, key = lambda y: (ctr[y], y))

            return sum(map(lambda y: y * ctr[y], most_freq))


        return tuple(map(do_sum,range(len(nums)+1 - k)))

4.7.376 - 2025-08-24 13:21:47 +0300 MSK

Construct the Minimum Bitwise Array I
class Solution:
    def minBitwiseArray(self, nums: List[int]) -> List[int]:
        ans = []
        for i in nums:
            for j in range(i):
                if j | (j + 1) == i:
                    ans.append(j)
                    break
            else:
                ans.append(-1)
        return ans

4.7.377 - 2025-08-24 13:10:51 +0300 MSK

Find the K-th Character in String Game I
class Solution:
    def kthCharacter(self, k: int) -> str:
        res = 0
        while k != 1:
            ln = k.bit_length() - 1
            if (1 << ln) == k:
                ln -= 1
            k -= 1 << ln
            res += 1
        return chr(res + 97)

4.7.378 - 2025-08-24 13:05:10 +0300 MSK

Minimum Element After Replacement With Digit Sum
class Solution:
    def minElement(self, nums: List[int]) -> int:
        res = math.inf
        for num in nums:
            cur = 0
            while num > 0:
                cur += num % 10
                num //= 10
            res = min(res, cur)
        return res

4.7.379 - 2025-08-24 12:59:57 +0300 MSK

The Two Sneaky Numbers of Digitville
class Solution:
    def getSneakyNumbers(self, nums: List[int]) -> List[int]:
        n = len(nums) - 2
        xor_all = 0
        for num in nums:
            xor_all ^= num
        for num in range(n):
            xor_all ^= num
        rightmost_bit = xor_all & -xor_all
        dup1, dup2 = 0, 0
        for num in nums:
            if num & rightmost_bit:
                dup1 ^= num
            else:
                dup2 ^= num
        for num in range(n):
            if num & rightmost_bit:
                dup1 ^= num
            else:
                dup2 ^= num
        return [dup1, dup2]

4.7.380 - 2025-08-24 12:47:23 +0300 MSK

Find Indices of Stable Mountains
class Solution:
    def stableMountains(self, height: List[int], threshold: int) -> List[int]:
        res, n = [], len(height)
        for i in range(1, n):
            cur, prv = height[i], height[i - 1]
            if prv > threshold:
                res.append(i)
        return res

4.7.381 - 2025-08-24 12:44:46 +0300 MSK

Convert Date to Binary
class Solution:
    def convertDateToBinary(self, date: str) -> str:
        res, cur = [], []
        for num in map(int, (date[:4], date[5:7], date[-2:])):
            while num > 0:
                cur.append(num & 1)
                num >>= 1
            cur.reverse()
            res.append("".join(map(str, cur)))
            cur.clear()
        return "-".join(res)

4.7.382 - 2025-08-24 12:44:03 +0300 MSK

Convert Date to Binary
class Solution:
    def convertDateToBinary(self, date: str) -> str:
        res, cur = [], []
        for num in map(int, (date[:4], date[5:7], date[-2:])):
            while num > 0:
                cur.append(num % 2)
                num //= 2
            cur.reverse()
            res.append("".join(map(str, cur)))
            cur.clear()
        return "-".join(res)

4.7.383 - 2025-08-24 12:38:10 +0300 MSK

Check if Two Chessboard Squares Have the Same Color
class Solution:
    def checkTwoChessboards(self, coordinate1: str, coordinate2: str) -> bool:
        row1, col1 = ord(coordinate1[0]) - 97, int(coordinate1[1]) - 1
        row2, col2 = ord(coordinate2[0]) - 97, int(coordinate2[1]) - 1
        if row1 % 2 == 0:
            is_black1 = col1 % 2 == 0
        else:
            is_black1 = col1 % 2 != 0
        if row2 % 2 == 0:
            is_black2 = col2 % 2 == 0
        else:
            is_black2 = col2 % 2 != 0
        return is_black1 == is_black2

4.7.384 - 2025-08-24 12:34:32 +0300 MSK

Find the Key of the Numbers
class Solution:
    def generateKey(self, num1: int, num2: int, num3: int) -> int:
        res = 0
        cnt = 0
        while num1 > 0 and num2 > 0 and num3 > 0:
            res += min(num1 % 10, num2 % 10, num3 % 10) * (10 ** cnt)
            cnt += 1
            num1 //= 10
            num2 //= 10
            num3 //= 10
        return res

4.7.385 - 2025-08-24 12:31:27 +0300 MSK

Final Array State After K Multiplication Operations I
class Solution:
    def getFinalState(self, nums: List[int], k: int, multiplier: int):
        hp = [(val, i) for i, val in enumerate(nums)]
        heapq.heapify(hp)
        for _ in range(k):
            _, i = heapq.heappop(hp)
            nums[i] *= multiplier
            heapq.heappush(hp, (nums[i], i))
        return nums

4.7.386 - 2025-08-24 12:29:48 +0300 MSK

Final Array State After K Multiplication Operations I
class Solution:
    def getFinalState(self, nums: List[int], k: int, multiplier: int) -> List[int]:
        pos, n = defaultdict(list), len(nums)
        hp = nums.copy()
        heapq.heapify(hp)
        for i in reversed(range(n)):
            heapq.heappush(pos[nums[i]], i)
        while k > 0:
            k -= 1
            val = heapq.heappop(hp)
            new_val = val * multiplier
            heapq.heappush(hp, new_val)
            idx = heapq.heappop(pos[val])
            nums[idx] = new_val
            heapq.heappush(pos[new_val], idx)
        return nums

        

4.7.387 - 2025-08-24 12:20:45 +0300 MSK

Count Substrings That Satisfy K-Constraint I
class Solution:
    def countKConstraintSubstrings(self, s: str, k: int) -> int:
        res, n, ones, l = 0, len(s), 0, 0
        for r in range(n):
            ones += int(s[r])
            while (ones > k) and ((r - l + 1) - ones) > k:
                ones -= int(s[l])
                l += 1
            res += r - l + 1
        return res

4.7.388 - 2025-08-24 11:46:23 +0300 MSK

Snake in Matrix
class Solution:
    def finalPositionOfSnake(self, n: int, commands: List[str]) -> int:
        col, row = 0, 0
        for cmd in commands:
            if cmd == "RIGHT":
                col += 1
            elif cmd == "UP":
                row -= 1
            elif cmd == "DOWN":
                row += 1
            else:
                col -= 1
        return row * n + col

4.7.389 - 2025-08-24 11:43:54 +0300 MSK

Find the Number of Winning Players
class Solution:
    def winningPlayerCount(self, n: int, pick: List[List[int]]) -> int:
        res, n, freqs = 0, len(pick), [[0] * 11 for _ in range(11)]
        for i in range(n):
            pl, cl = pick[i]
            freqs[pl][cl] += 1
        for i in range(len(freqs)):
            if max(freqs[i]) > i:
                res += 1
        return res

4.7.390 - 2025-08-24 10:55:08 +0300 MSK

Longest Subarray of 1’s After Deleting One Element
class Solution:
    def longestSubarray(self, nums: List[int]) -> int:
        res, n, cnt1, cnt2 = 0, len(nums), 0, 0
        for i in range(len(nums)):
            cur = nums[i]
            if cur == 1:
                cnt2 += 1
                res = max(res, cnt1 + cnt2)
            elif cur == 0:
                cnt1, cnt2 = cnt2, 0
        if res == n:
            return res - 1
        return res

4.7.391 - 2025-08-23 20:17:19 +0300 MSK

Find if Digit Game Can Be Won
class Solution:
    def canAliceWin(self, nums: List[int]) -> bool:
        sm_single, sm_double, sm_all = 0, 0, 0
        for num in nums:
            if num < 10:
                sm_single += num
            elif num < 100:
                sm_double += num
            sm_all += num
        return sm_single > (sm_all - sm_single) or sm_double > (sm_all - sm_double) 

4.7.392 - 2025-08-23 19:28:34 +0300 MSK

Number of Bit Changes to Make Two Integers Equal
class Solution:
    def minChanges(self, n: int, k: int) -> int:
        res = 0
        if n < k:
            return -1
        while k > 0 or n > 0:
            n1, k1 = n & 1, k & 1
            if n1 != k1 and n1 == 0 and k1 == 1:
                return -1
            if n1 != k1:
                res += 1
            n >>= 1
            k >>= 1
        return res

4.7.393 - 2025-08-23 18:30:08 +0300 MSK

Find the Minimum Area to Cover All Ones II
class Solution:
    def minimumSum2(
        self, grid: List[List[int]], u: int, d: int, l: int, r: int
    ) -> int:
        min_i = len(grid)
        max_i = 0
        min_j = len(grid[0])
        max_j = 0

        for i in range(u, d + 1):
            for j in range(l, r + 1):
                if grid[i][j] == 1:
                    min_i = min(min_i, i)
                    min_j = min(min_j, j)
                    max_i = max(max_i, i)
                    max_j = max(max_j, j)

        return (
            (max_i - min_i + 1) * (max_j - min_j + 1)
            if min_i <= max_i
            else sys.maxsize // 3
        )

    def rotate(self, vec: List[List[int]]) -> List[List[int]]:
        n = len(vec)
        m = len(vec[0]) if n > 0 else 0
        ret = [[0] * n for _ in range(m)]

        for i in range(n):
            for j in range(m):
                ret[m - j - 1][i] = vec[i][j]

        return ret

    def solve(self, grid: List[List[int]]) -> int:
        n = len(grid)
        m = len(grid[0]) if n > 0 else 0
        res = n * m

        for i in range(n - 1):
            for j in range(m - 1):
                res = min(
                    res,
                    self.minimumSum2(grid, 0, i, 0, m - 1)
                    + self.minimumSum2(grid, i + 1, n - 1, 0, j)
                    + self.minimumSum2(grid, i + 1, n - 1, j + 1, m - 1),
                )

                res = min(
                    res,
                    self.minimumSum2(grid, 0, i, 0, j)
                    + self.minimumSum2(grid, 0, i, j + 1, m - 1)
                    + self.minimumSum2(grid, i + 1, n - 1, 0, m - 1),
                )

        for i in range(n - 2):
            for j in range(i + 1, n - 1):
                res = min(
                    res,
                    self.minimumSum2(grid, 0, i, 0, m - 1)
                    + self.minimumSum2(grid, i + 1, j, 0, m - 1)
                    + self.minimumSum2(grid, j + 1, n - 1, 0, m - 1),
                )

        return res

    def minimumSum(self, grid: List[List[int]]) -> int:
        rgrid = self.rotate(grid)
        return min(self.solve(grid), self.solve(rgrid))

4.7.394 - 2025-08-22 21:36:17 +0300 MSK

Find the Winning Player in Coin Game
class Solution:
    def winningPlayer(self, x: int, y: int) -> str:
        y //= 4
        x = min(x, y)
        if x % 2 == 1:
            return "Alice"
        else:
            return "Bob"

4.7.395 - 2025-08-22 21:29:25 +0300 MSK

Lexicographically Smallest String After a Swap
class Solution:
    def getSmallestString(self, s: str) -> str:
        res = list(s)
        for i in range(len(s) - 1):
            cur, nxt = int(s[i]), int(s[i + 1])
            if cur % 2 == nxt % 2 and cur > nxt:
                res[i], res[i + 1] = s[i + 1], s[i]
                break        
        return "".join(res)

4.7.396 - 2025-08-22 21:16:52 +0300 MSK

Find the Encrypted String
class Solution:
    def getEncryptedString(self, s: str, k: int) -> str:
        res = []
        for i in range(len(s)):
            res.append(s[(i + k) % len(s)])
        return "".join(res)

4.7.397 - 2025-08-22 21:13:56 +0300 MSK

Alternating Groups I
class Solution:
    def numberOfAlternatingGroups(self, colors: List[int]) -> int:
        res = 0
        if colors[0] != colors[-1] and colors[0] != colors[1]:
            res += 1
        if colors[-1] != colors[-2] and colors[-1] != colors[0]:
            res += 1
        for i in range(1, len(colors) - 1):
            if colors[i] != colors[i - 1] and colors[i] != colors[i + 1]:
                res += 1
        return res

4.7.398 - 2025-08-22 21:08:45 +0300 MSK

Minimum Average of Smallest and Largest Elements
class Solution:
    def minimumAverage(self, nums: List[int]) -> float:
        av = []
        nums.sort()
        for i in range(len(nums) // 2):
            heapq.heappush(av, nums[i] + nums[len(nums) - i - 1])
        return heapq.heappop(av) / 2

4.7.399 - 2025-08-22 21:06:36 +0300 MSK

Find Minimum Operations to Make All Elements Divisible by Three
class Solution:
    def minimumOperations(self, nums: List[int]) -> int:
        res = 0
        for i in range(len(nums)):
            res += nums[i] % 3 != 0
        return res

4.7.400 - 2025-08-22 21:05:07 +0300 MSK

Find Minimum Operations to Make All Elements Divisible by Three
class Solution:
    def minimumOperations(self, nums: List[int]) -> int:
        res = 0
        for i in range(len(nums)):
            res += min(nums[i] % 3, ((nums[i] // 3) + 1) * 3 - nums[i])
        return res

4.7.401 - 2025-08-22 21:02:15 +0300 MSK

Count Pairs That Form a Complete Day I
class Solution:
    def countCompleteDayPairs(self, hours: List[int]) -> int:
        freqs = [0] * 24
        for i in range(len(hours)):
            freqs[hours[i] % 24] += 1
        res = 0
        for i in range(len(hours)):
            hr = hours[i] % 24
            freqs[hr] -= 1
            if hr == 0:
                res += freqs[hr]
            else:
                res += freqs[24 - hr]
        return res

4.7.402 - 2025-08-22 20:53:33 +0300 MSK

Find the Child Who Has the Ball After K Seconds
class Solution:
    def numberOfChild(self, n: int, k: int) -> int:
        circleback = (n - 1) * 2
        k %= circleback
        if k < n:
            return k
        return circleback - k

4.7.403 - 2025-08-22 20:44:21 +0300 MSK

Clear Digits
class Solution:
    def clearDigits(self, s: str) -> str:
        res = []
        for i in range(len(s)):
            ch = s[i]
            if not ch.isdigit():
                res.append(ch)
            elif res:
                res.pop()
        return "".join(res)

4.7.404 - 2025-08-22 20:41:37 +0300 MSK

Minimum Number of Chairs in a Waiting Room
class Solution:
    def minimumChairs(self, s: str) -> int:
        left = 0
        res = 0
        for i in range(len(s)):
            if s[i] == "E":
                if left > 0:
                    left -= 1
                else:
                    res += 1
            else:
                left += 1
        return res

4.7.405 - 2025-08-22 20:34:34 +0300 MSK

Find the Number of Good Pairs I
class Solution:
    def numberOfPairs(self, nums1: List[int], nums2: List[int], k: int) -> int:
        freqs = [0] * 51
        for i in range(len(nums2)):
            freqs[nums2[i]] += 1
        res = 0
        for i in range(len(nums1)):
            for num2 in range(1, len(freqs)):
                if nums1[i] % (num2 * k) == 0:
                    res += freqs[num2]
        return res

4.7.406 - 2025-08-22 20:29:48 +0300 MSK

Find the XOR of Numbers Which Appear Twice
class Solution:
    def duplicateNumbersXOR(self, nums: List[int]) -> int:
        freqs = [0] * 51
        res = 0
        for i in range(len(nums)):
            freqs[nums[i]] += 1
            if freqs[nums[i]] == 2:
                res ^= nums[i]
        return res

4.7.407 - 2025-08-22 20:27:37 +0300 MSK

Special Array I
class Solution:
    def isArraySpecial(self, nums: List[int]) -> bool:
        for i in range(1, len(nums)):
            cur, prev = nums[i] % 2 == 0, nums[i - 1] % 2 == 0
            if cur == prev:
                return False
        return True

4.7.408 - 2025-08-22 20:25:28 +0300 MSK

Permutation Difference between Two Strings
class Solution:
    def findPermutationDifference(self, s: str, t: str) -> int:
        pos = [0] * 26
        for i in range(len(s)):
            pos[ord(s[i]) - 97] += i
        res = 0
        for i in range(len(t)):
            res += abs(i - pos[ord(t[i]) - 97])
        return res
        

4.7.409 - 2025-08-22 20:22:48 +0300 MSK

Check if Grid Satisfies Conditions
class Solution:
    def satisfiesConditions(self, grid: List[List[int]]) -> bool:
        rows, cols = len(grid), len(grid[0])
        for row in range(rows):
            for col in range(cols):
                val = grid[row][col]
                if row + 1 < rows and val != grid[row + 1][col]:
                    return False
                if col + 1 < cols and val == grid[row][col + 1]:
                    return False
        return True 

4.7.410 - 2025-08-22 20:20:58 +0300 MSK

Valid Word
class Solution:
    def isValid(self, word: str) -> bool:
        vws = ('a', 'e', 'i', 'o', 'u')
        if len(word) < 3:
            return False
        has_vw, has_cons = False, False
        for i in range(len(word)):
            ch = word[i]
            if ch.isalpha():
                if ch.lower() in vws:
                    has_vw = True
                else:
                    has_cons = True
            elif not ch.isdigit():
                return False
        return has_vw and has_cons

4.7.411 - 2025-08-22 20:15:56 +0300 MSK

Find the Integer Added to Array I
class Solution:
    def addedInteger(self, nums1: List[int], nums2: List[int]) -> int:
        nums1.sort()
        nums2.sort()
        return nums2[0] - nums1[0]

4.7.412 - 2025-08-22 20:12:59 +0300 MSK

Make a Square with the Same Color
class Solution:
    def canMakeSquare(self, grid: List[List[str]]) -> bool:
        rows, cols = len(grid), len(grid[0])
        moves = ((0, 0), (0, -1), (-1, -1), (-1, 0))
        for row in range(1, rows):
            for col in range(1, cols):
                cnt = 0
                for row_dlt, col_dlt in moves:
                    if grid[row + row_dlt][col + col_dlt] == "W":
                        cnt += 1
                    else:
                        cnt -= 1
                if cnt in (2, -2, 4, -4):
                    return True
        return False

4.7.413 - 2025-08-22 20:03:50 +0300 MSK

Count the Number of Special Characters I
class Solution:
    def numberOfSpecialChars(self, word: str) -> int:
        freqs = [0] * 26
        res = 0
        for i in range(len(word)):
            char = word[i]
            idx = ord(char)
            if char.isupper():
                idx -= 65
                freqs[idx] |= 0x01
            else:
                idx -= 97
                freqs[idx] |= 0x10
        for i in range(len(freqs)):
            freq = freqs[i]
            if freq ^ 0x11 == 0:
                res += 1
        return res

4.7.414 - 2025-08-22 19:58:17 +0300 MSK

Latest Time You Can Obtain After Replacing Characters
class Solution:
    def findLatestTime(self, time_str):
        len_time_str = len(time_str)
        ret_val = ''
        i = 0
        while (i < len_time_str):
            c = time_str[i]
            if (c == '?'):
                if (i == 0):
                    if (time_str[i+1] == '?'):
                        ret_val += '1'
                    elif (time_str[i+1] in ('0', '1')):
                        ret_val += '1'
                    else:
                        ret_val += '0'
                elif (i == 1):
                    if (time_str[i-1] == '?'):
                        ret_val += '1'
                    elif (time_str[i-1] in ('0')):
                        ret_val += '9'
                    elif (time_str[i-1] in ('1')):
                        ret_val += '1'
                    else:
                        ret_val += '0'
                elif (i == 3):
                    ret_val += '5'
                elif (i == 4):
                    ret_val += '9'
            else:
                ret_val += c
            i += 1
        return ret_val

4.7.415 - 2025-08-22 19:49:07 +0300 MSK

Longest Strictly Increasing or Strictly Decreasing Subarray
class Solution:
    def longestMonotonicSubarray(self, nums: List[int]) -> int:
        inc_len, dec_len, cur_len, cur_state = 1, 1, 1, 0
        for i in range(1, len(nums)):
            cur, prev = nums[i], nums[i - 1]
            if cur > prev:
                if cur_state == 1:
                    cur_len += 1
                else:
                    cur_state = 1
                    cur_len = 2
                inc_len = max(inc_len, cur_len)
            elif cur == prev:
                cur_len = 1
                cur_state = 0
            else:
                if cur_state == -1:
                    cur_len += 1
                else:
                    cur_state = -1
                    cur_len = 2
                dec_len = max(dec_len, cur_len)
        return max(inc_len, dec_len)
            

4.7.416 - 2025-08-22 19:43:35 +0300 MSK

Harshad Number
class Solution:
    def sumOfTheDigitsOfHarshadNumber(self, x: int) -> int:
        cur = x
        sm = 0
        while cur > 0:
            sm += cur % 10
            cur //= 10
        if x % sm == 0:
            return sm
        return -1

4.7.417 - 2025-08-22 19:42:24 +0300 MSK

Shortest Subarray With OR at Least K I
class Solution:
    def minimumSubarrayLength(self, nums: List[int], k: int) -> int:
        n = len(nums)
        min_len = math.inf
        for i in range(n):
            curr = 0
            for j in range(i, n):
                curr |= nums[j]
                if curr >= k:
                    min_len = min(min_len , j - i + 1)
                    break
        if min_len == math.inf:
            return -1
        return min_len

4.7.418 - 2025-08-22 19:24:16 +0300 MSK

Maximum Length Substring With Two Occurrences
class Solution:
    def maximumLengthSubstring(self, s: str) -> int:
        ans = ii = 0 
        freq = Counter()
        for i, ch in enumerate(s): 
            freq[ch] += 1
            while freq[ch] == 3: 
                freq[s[ii]] -= 1
                ii += 1
            ans = max(ans, i - ii + 1)
        return ans

4.7.419 - 2025-08-22 19:19:46 +0300 MSK

Existence of a Substring in a String and Its Reverse
class Solution:
    def isSubstringPresent(self, s: str) -> bool:
        for i in range(1, len(s)):
            cur, prev = s[i], s[i - 1]
            for j in range(i, len(s)):
                cur2, prev2 = s[j], s[j - 1]
                if cur == prev2 and prev == cur2:
                    return True
        return False

4.7.420 - 2025-08-22 19:14:44 +0300 MSK

Find the Sum of Encrypted Integers
class Solution:
    def sumOfEncryptedInt(self, nums: List[int]) -> int:
        res = 0
        for i in range(len(nums)):
            cur = nums[i]
            max_dig = 0
            enc = 0
            cnt = 0
            while cur > 0:
                max_dig = max(max_dig, cur % 10)
                cur //= 10
                enc += 10 ** cnt
                cnt += 1
            enc *= max_dig
            res += enc
        return res

4.7.421 - 2025-08-22 19:10:19 +0300 MSK

Apple Redistribution into Boxes
class Solution:
    def minimumBoxes(self, apple: List[int], capacity: List[int]) -> int:
        apples = sum(apple)
        capacity.sort(reverse=True)
        for i in range(len(capacity)):
            apples = max(apples - capacity[i], 0)
            if apples == 0:
                return i + 1
        raise Exception

4.7.422 - 2025-08-22 19:03:00 +0300 MSK

Distribute Elements Into Two Arrays I
class Solution:
    def resultArray(self, nums):
        len_nums = len(nums)
        arr1 = [nums[0]]
        arr2 = [nums[1]]
        for i in range(2, len(nums)):
            if arr1[-1] > arr2[-1]:
                arr1.append(nums[i])
            else:
                arr2.append(nums[i])
        arr1.extend(arr2)
        return arr1

4.7.423 - 2025-08-22 18:58:03 +0300 MSK

Minimum Operations to Exceed Threshold Value I
class Solution:
    def minOperations(self, nums: List[int], k: int) -> int:
        nums.sort()
        for i in range(len(nums)):
            if nums[i] >= k:
                return i
        return len(nums)

4.7.424 - 2025-08-22 18:56:27 +0300 MSK

Split the Array
class Solution:
    def isPossibleToSplit(self, nums: List[int]) -> bool:
        freqs = [0] * 101
        for num in nums:
            freqs[num] += 1
            if freqs[num] == 3:
                return False
        return True

4.7.425 - 2025-08-22 18:53:34 +0300 MSK

Count Prefix and Suffix Pairs I
class Solution:
    def countPrefixSuffixPairs(self, words: List[str]) -> int:
        res = 0
        for i in range(len(words)):
            w1 = words[i]
            for j in range(i + 1, len(words)):
                w2 = words[j]
                if w2.startswith(w1) and w2.endswith(w1):
                    res += 1
        return res

4.7.426 - 2025-08-22 18:48:54 +0300 MSK

Maximum Number of Operations With the Same Score I
class Solution:
    def maxOperations(self, nums: List[int]) -> int:
        target = sum(nums[:2])
        res = 1
        for i in range(2, len(nums) - 1, 2):
            if sum(nums[i:i + 2]) == target:
                res += 1
            else:
                break
        return res

4.7.427 - 2025-08-22 18:46:45 +0300 MSK

Modify the Matrix
class Solution:
    def modifiedMatrix(self, matrix: List[List[int]]) -> List[List[int]]:
        rows, cols = len(matrix), len(matrix[0])
        for col in range(cols):
            max_val = -1
            for row in range(rows):
                max_val = max(max_val, matrix[row][col])
            for row in range(rows):
                if matrix[row][col] == -1:
                    matrix[row][col] = max_val
        return matrix

4.7.428 - 2025-08-22 18:44:22 +0300 MSK

Ant on the Boundary
class Solution:
    def returnToBoundaryCount(self, nums: List[int]) -> int:
        res = 0
        pos = nums[0]
        for num in nums[1:]:
            pos += num
            if pos == 0:
                res += 1
        return res

4.7.429 - 2025-08-22 18:43:10 +0300 MSK

Type of Triangle
class Solution:
    def triangleType(self, nums: List[int]) -> str:
        s1, s2, s3 = nums
        if s1 == s2 == s3:
            return "equilateral"
        if s1 + s2 <= s3 or s1 + s3 <= s2 or s2 + s3 <= s1:
            return "none"
        if s1 == s2 or s2 == s3 or s1 == s3:
            return "isosceles"
        if s1 != s2 and s2 != s3 and s1 != s3:
            return "scalene"
        return "none"

4.7.430 - 2025-08-22 18:39:40 +0300 MSK

Number of Changing Keys
class Solution:
    def countKeyChanges(self, s: str) -> int:
        res = 0
        for i in range(1, len(s)):
            cur, prev = ord(s[i]), ord(s[i - 1])
            if cur < 97:
                cur += 32
            if prev < 97:
                prev += 32
            if cur != prev:
                res += 1
        return res

4.7.431 - 2025-08-22 18:38:14 +0300 MSK

Number of Changing Keys
class Solution:
    def countKeyChanges(self, s: str) -> int:
        res = 0
        for i in range(1, len(s)):
            cur, prev = s[i].lower(), s[i - 1].lower()
            if cur != prev:
                res += 1
        return res

4.7.432 - 2025-08-22 18:36:52 +0300 MSK

Minimum Number of Pushes to Type Word I
class Solution:
    def minimumPushes(self, word: str) -> int:
        freqs = [0] * 26
        for char in word:
            freqs[ord(char) - 97] += 1
        freqs.sort()
        res = 0
        for i in range(26):
            freq = freqs[26 - i - 1]
            if freq == 0:
                break
            res += freq * (i // 8 + 1)
        return res

4.7.433 - 2025-08-22 18:30:44 +0300 MSK

Minimum Number of Pushes to Type Word I
class Solution:
    def minimumPushes(self, word: str) -> int:
        freqs = [0] * 26
        for char in word:
            freqs[ord(char) - 97] += 1
        freqs.sort()
        cost = 1
        res = 0
        while freqs and freqs[-1] != 0:
            for _ in range(8):
                if not freqs:
                    break
                freq = freqs.pop()
                if freq == 0:
                    break
                res += freq * cost
            cost += 1
        return res

4.7.434 - 2025-08-22 18:25:20 +0300 MSK

Divide an Array Into Subarrays With Minimum Cost I
class Solution:
    def minimumCost(self, nums: List[int]) -> int:
        nums.reverse()
        first = nums.pop()
        nums.sort()
        return first + sum(nums[:2])

4.7.435 - 2025-08-22 18:22:55 +0300 MSK

Maximum Area of Longest Diagonal Rectangle
class Solution:
    def areaOfMaxDiagonal(self, dimensions: List[List[int]]) -> int:
        max_diag, max_area = 0, 0
        for length, width in dimensions:
            diag = length ** 2 + width ** 2
            area = length * width
            if diag > max_diag or (diag == max_diag and area > max_area):
                max_diag, max_area = diag, area
        return max_area

4.7.436 - 2025-08-22 18:19:44 +0300 MSK

Smallest Missing Integer Greater Than Sequential Prefix Sum
class Solution:
    def missingInteger(self, nums: List[int]) -> int:
        s = set(nums)
        x = nums[0] - 1
        seqSum = 0
        for i in nums:
            if i - x == 1:
                seqSum += i
                x = i
            else:
                break
        index = seqSum
        while True:
            if index not in s:
                return index
            index += 1

4.7.437 - 2025-08-22 17:02:28 +0300 MSK

Check if Bitwise OR Has Trailing Zeros
class Solution:
    def hasTrailingZeros(self, nums: List[int]) -> bool:
        cnt = 0
        for num in nums:
            if num & 1 == 0:
                cnt += 1
                if cnt == 2:
                    return True
        return False

4.7.438 - 2025-08-22 16:56:33 +0300 MSK

Minimum Number Game
class Solution:
    def numberGame(self, nums: List[int]) -> List[int]:
        res = []
        nums.sort(reverse=True)
        while nums:
            al, bob = nums.pop(), nums.pop()
            res.extend((bob, al))
        return res

4.7.439 - 2025-08-22 14:49:18 +0300 MSK

Find Missing and Repeated Values
class Solution:
    def findMissingAndRepeatedValues(self, grid: List[List[int]]) -> List[int]:
        n = len(grid)
        freqs = [0] * (n ** 2 + 1)
        res1 = None
        for row in grid:
            for num in row:
                freqs[num] += 1
                if freqs[num] == 2:
                    res1 = num
        return res1, freqs[1:].index(0) + 1

4.7.440 - 2025-08-22 14:41:39 +0300 MSK

Count Tested Devices After Test Operations
class Solution:
    def countTestedDevices(self, batteryPercentages: List[int]) -> int:
        res = 0
        for i, perc in enumerate(batteryPercentages):
            if perc - res > 0:
                res += 1
        return res

4.7.441 - 2025-08-22 14:33:33 +0300 MSK

Find Common Elements Between Two Arrays
class Solution:
    def findIntersectionValues(self, nums1: List[int], nums2: List[int]) -> List[int]:
        freqs1, freqs2 = [0] * 101, [0] * 101
        for num in nums1:
            freqs1[num] += 1
        for num in nums2:
            freqs2[num] += 1
        res1, res2 = 0, 0
        for num, freq in enumerate(freqs1):
            if freqs2[num] > 0:
                res1 += freq
        for num, freq in enumerate(freqs2):
            if freqs1[num] > 0:
                res2 += freq
        return res1, res2

4.7.442 - 2025-08-22 14:30:04 +0300 MSK

Find the Peaks
class Solution:
    def findPeaks(self, mountain: List[int]) -> List[int]:
        res = []
        for i in range(1, len(mountain) - 1):
            if mountain[i - 1] < mountain[i] > mountain[i + 1]:
                res.append(i)
        return res

4.7.443 - 2025-08-22 14:28:05 +0300 MSK

Matrix Similarity After Cyclic Shifts
class Solution:
    def areSimilar(self, mat: List[List[int]], k: int) -> bool:
        cols = len(mat[0])
        for row in range(len(mat)):
            is_even = row % 2 == 0
            for col in range(cols):
                if is_even:
                    new_col = (col - k + cols) % cols
                else:
                    new_col = (col + k) % cols
                if mat[row][col] != mat[row][new_col]:
                    return False
        return True

4.7.444 - 2025-08-22 14:23:13 +0300 MSK

Find Words Containing Character
class Solution:
    def findWordsContaining(self, words: List[str], x: str) -> List[int]:
        for i in range(len(words)):
            if x in words[i]:
                words[i] = i
            else:
                words[i] = -1
        words.sort(reverse=True)
        while words and words[-1] == -1:
            words.pop()
        return words

4.7.445 - 2025-08-22 14:20:44 +0300 MSK

Find Words Containing Character
class Solution:
    def findWordsContaining(self, words: List[str], x: str) -> List[int]:
        res = []
        for i, word in enumerate(words):
            if x in word:
                res.append(i)
        return res 

4.7.446 - 2025-08-22 14:19:56 +0300 MSK

Make Three Strings Equal
class Solution:
    def findMinimumOperations(self, s1: str, s2: str, s3: str) -> int:
        n1, n2, n3 = len(s1), len(s2), len(s3)
        for i in range(max(n1, n2, n3)):
            fail = True
            if i < n1 and i < n2 and i < n3:
                c1, c2, c3 = s1[i], s2[i], s3[i]
                if c1 == c2 and c2 == c3:
                    fail = False
            if not fail:
                continue
            if i == 0:
                return -1
            return max(n1 - i, 0) + max(n2 - i, 0) + max(n3 - i, 0)
        return 0

4.7.447 - 2025-08-22 14:06:34 +0300 MSK

Maximum Strong Pair XOR I
class Solution:
    def maximumStrongPairXor(self, nums: List[int]) -> int:
        nums.sort()
        n, l, r, res = len(nums), 0, 0, 0
        while r < n:
            num1, num2 = nums[l], nums[r]
            if num2 - num1 > num1:
                l += 1
                continue
            for i in range(l, r):
                res = max(res, nums[i] ^ num2)
            r += 1
        return res

4.7.448 - 2025-08-22 13:59:13 +0300 MSK

Maximum Strong Pair XOR I
class Solution:
    def maximumStrongPairXor(self, nums: List[int]) -> int:
        max_xor = 0
        for i in range(len(nums)):
            for j in range(i + 1, len(nums)):
                num1, num2 = nums[i], nums[j]
                if abs(num2 - num1) <= min(num1, num2):
                    max_xor = max(max_xor, num1 ^ num2)
        return max_xor 

4.7.449 - 2025-08-22 13:58:21 +0300 MSK

Maximum Strong Pair XOR I
class Solution:
    def maximumStrongPairXor(self, nums: List[int]) -> int:
        max_xor = 0
        for num1, num2 in itertools.permutations(nums, 2):
            if abs(num2 - num1) <= min(num1, num2):
                max_xor = max(max_xor, num1 ^ num2)
        return max_xor 

4.7.450 - 2025-08-22 13:53:08 +0300 MSK

Distribute Candies Among Children I
class Solution:
    def distributeCandies(self, n: int, limit: int) -> int:
        min_first = max(0, n - 2 * limit)
        max_first = min(n, limit)
        ways = 0
        for i in range(min_first, max_first + 1):
            N = n - i
            min_ch2 = max(0, N - limit)
            max_ch2 = min(N, limit)
            ways += max_ch2 - min_ch2 + 1
        return ways

4.7.451 - 2025-08-22 13:44:20 +0300 MSK

Find Champion I
class Solution:
    def findChampion(self, grid: List[List[int]]) -> int:
        loses = [False] * len(grid)
        for row in range(len(grid)):
            for col in range(len(grid)):
                if row == col:
                    continue
                val = grid[row][col]
                if val == 1:
                    loses[col] = True
                else:
                    loses[row] = True
        return loses.index(False)

4.7.452 - 2025-08-22 13:37:11 +0300 MSK

Find the K-or of an Array
class Solution:
    def findKOr(self, nums: List[int], k: int) -> int:
        freqs = [0] * 31
        for num in nums:
            i = 0    
            while num > 0:
                if num & 1 == 1:
                    freqs[i] += 1
                i += 1
                num >>= 1
        res = 0
        for i, freq in enumerate(freqs):
            if freq >= k:
                res |= 1 << i
        return res

4.7.453 - 2025-08-22 09:54:03 +0300 MSK

Find the Minimum Area to Cover All Ones I
class Solution:
    def minimumArea(self, grid: List[List[int]]) -> int:
        min_row, max_row = math.inf, -math.inf
        min_col, max_col = math.inf, -math.inf
        for row in range(len(grid)):
            for col in range(len(grid[0])):
                if grid[row][col] == 0:
                    continue
                min_row, max_row = min(min_row, row), max(max_row, row)
                min_col, max_col = min(min_col, col), max(max_col, col)
        return (max_row - min_row + 1) * (max_col - min_col + 1)

4.7.454 - 2025-08-21 19:04:22 +0300 MSK

Subarrays Distinct Element Sum of Squares I
class Solution:
    def sumCounts(self, nums: List[int]) -> int:
        n = len(nums)
        result = 0
        for i in range(n):
            s = set()
            for j in range(i, n):
                s.add(nums[j])
                result += len(s) ** 2
        return result

4.7.455 - 2025-08-21 19:01:40 +0300 MSK

Method Chaining
import pandas as pd

def findHeavyAnimals(animals: pd.DataFrame) -> pd.DataFrame:
    return animals[animals['weight'] > 100].sort_values(by='weight', ascending=False)[['name']]

4.7.456 - 2025-08-21 18:59:14 +0300 MSK

Reshape Data: Melt
import pandas as pd

def meltTable(report: pd.DataFrame) -> pd.DataFrame:
    report = report.melt(
        id_vars=["product"],
        value_vars=["quarter_1", "quarter_2", "quarter_3", "quarter_4"],
        var_name="quarter",
        value_name="sales",
    )
    return report

4.7.457 - 2025-08-21 18:58:06 +0300 MSK

Reshape Data: Pivot
import pandas as pd

def pivotTable(weather: pd.DataFrame) -> pd.DataFrame:
    ans = weather.pivot(index='month', columns='city', values='temperature')
    return ans

4.7.458 - 2025-08-21 18:57:41 +0300 MSK

Minimum Sum of Mountain Triplets I
class Solution:
    def minimumSum(self, nums: List[int]) -> int:
        n = len(nums)
        min_left, min_right = [0] * n, [0] * n
        cur_min = math.inf
        for i in range(n):
            cur_min = min(cur_min, nums[i])
            min_left[i] = cur_min
        cur_min = math.inf
        for i in reversed(range(n)):
            cur_min = min(cur_min, nums[i])
            min_right[i] = cur_min
        min_sum = math.inf
        for i in range(1, n - 1):
            left, mid, right = min_left[i - 1], nums[i], min_right[i + 1]
            if left < mid > right:
                min_sum = min(min_sum, left + mid + right)
        if min_sum == math.inf:
            return -1
        return min_sum

4.7.459 - 2025-08-21 18:50:35 +0300 MSK

Reshape Data: Concatenate
import pandas as pd

def concatenateTables(df1: pd.DataFrame, df2: pd.DataFrame) -> pd.DataFrame:
    return pd.concat([df1, df2], axis=0)

4.7.460 - 2025-08-21 18:50:21 +0300 MSK

Find Indices With Index and Value Difference I
class Solution:
    def findIndices(self, A: List[int], d: int, valueDifference: int) -> List[int]:
        mini = maxi = 0
        for i in range(d, len(A)):
            if A[i - d] < A[mini]: 
                mini = i - d
            if A[i - d] > A[maxi]: 
                maxi = i - d
            if A[i] - A[mini] >= valueDifference: 
                return [mini, i]
            if A[maxi] - A[i] >= valueDifference: 
                return [maxi, i]
        return [-1, -1]

4.7.461 - 2025-08-21 18:45:02 +0300 MSK

Fill Missing Data
import pandas as pd

def fillMissingValues(products: pd.DataFrame) -> pd.DataFrame:
    products['quantity'].fillna(0, inplace=True)
    return products

4.7.462 - 2025-08-21 18:35:19 +0300 MSK

Change Data Type
import pandas as pd

def changeDatatype(students: pd.DataFrame) -> pd.DataFrame:
    students = students.astype({'grade': int})
    return students

4.7.463 - 2025-08-21 18:35:00 +0300 MSK

Longest Unequal Adjacent Groups Subsequence I
class Solution:
    def getLongestSubsequence(self, words: List[str], groups: List[int]) -> List[str]:
        res = [words[0]]
        prev = groups[0]
        for i in range(1, len(groups)):
            cur = groups[i]
            if cur == prev:
                continue
            prev = cur
            res.append(words[i])
        return res

4.7.464 - 2025-08-21 18:34:31 +0300 MSK

Rename Columns
import pandas as pd

def renameColumns(students: pd.DataFrame) -> pd.DataFrame:
    students = students.rename(
        columns={
            "id": "student_id",
            "first": "first_name",
            "last": "last_name",
            "age": "age_in_years",
        }
    )
    return students

4.7.465 - 2025-08-21 18:30:25 +0300 MSK

Modify Columns
import pandas as pd

def modifySalaryColumn(employees: pd.DataFrame) -> pd.DataFrame:
    employees['salary'] = employees['salary'] * 2
    return employees

4.7.466 - 2025-08-21 18:30:11 +0300 MSK

Last Visited Integers
class Solution:
    def lastVisitedIntegers(self, nums: List[int]) -> List[int]:
        enc = []
        res = []
        m1_cnt = 0
        for num in nums:
            if num != -1:
                m1_cnt = 0
                enc.append(num)
                continue
            m1_cnt += 1
            if m1_cnt <= len(enc):
                res.append(enc[len(enc) - (m1_cnt - 1) - 1])
            else:
                res.append(-1)
        return res

4.7.467 - 2025-08-21 18:24:42 +0300 MSK

Drop Missing Data
import pandas as pd

def dropMissingData(students: pd.DataFrame) -> pd.DataFrame:
    students.dropna(subset=['name'], inplace=True)
    return students

4.7.468 - 2025-08-21 18:24:23 +0300 MSK

Divisible and Non-divisible Sums Difference
class Solution:
    def differenceOfSums(self, n: int, m: int) -> int:
        al = n * (1 + n) // 2
        div = (n // m) * (m + (n - (n % m))) // 2
        non_div = al - div
        return (al - div) - div

4.7.469 - 2025-08-21 18:18:09 +0300 MSK

Drop Duplicate Rows
import pandas as pd

def dropDuplicateEmails(customers: pd.DataFrame) -> pd.DataFrame:
    customers.drop_duplicates(subset='email', keep='first', inplace=True)
    return customers

4.7.470 - 2025-08-21 18:17:44 +0300 MSK

Create a New Column
import pandas as pd

def createBonusColumn(employees: pd.DataFrame) -> pd.DataFrame:
    employees['bonus'] = employees['salary'] * 2
    return employees

4.7.471 - 2025-08-21 18:17:05 +0300 MSK

Select Data
import pandas as pd

def selectData(students: pd.DataFrame) -> pd.DataFrame:
    return students.loc[students["student_id"] == 101, ["name", "age"]]

4.7.472 - 2025-08-21 18:16:46 +0300 MSK

Display the First Three Rows
import pandas as pd

def selectFirstRows(employees: pd.DataFrame) -> pd.DataFrame:
    return employees.head(3)

4.7.473 - 2025-08-21 18:16:25 +0300 MSK

Get the Size of a DataFrame
import pandas as pd

def getDataframeSize(players: pd.DataFrame) -> List:
    return [players.shape[0], players.shape[1]]

4.7.474 - 2025-08-21 18:16:06 +0300 MSK

Create a DataFrame from List
import pandas as pd

def createDataframe(student_data: List[List[int]]) -> pd.DataFrame:
    column_names = ["student_id", "age"]
    result_dataframe = pd.DataFrame(student_data, columns=column_names)
    return result_dataframe

4.7.475 - 2025-08-21 18:15:24 +0300 MSK

Maximum Value of an Ordered Triplet I
from typing import List

class Solution:
    def maximumTripletValue(self, nums: List[int]) -> int:
        n = len(nums)
        if n < 3:
            return 0
        left_max = [0] * n
        left_max[0] = nums[0]
        for i in range(1, n):
            left_max[i] = max(left_max[i - 1], nums[i])
        right_max = [0] * n
        right_max[-1] = nums[-1]
        for i in reversed(range(1, n - 1)):
            right_max[i] = max(right_max[i + 1], nums[i])
        ans = 0
        for i in range(1, n - 1):
            left = left_max[i - 1]
            right = right_max[i + 1]
            ans = max(ans, (left - nums[i]) * right)
        return ans

4.7.476 - 2025-08-21 17:56:20 +0300 MSK

Minimum Operations to Collect Elements
class Solution:
    def minOperations(self, nums: List[int], k: int) -> int:
        enc = [False] * (k + 1)
        res = 0
        rem = k
        for num in reversed(nums):
            res += 1
            if 1 <= num <= k and not enc[num]:
                enc[num] = True
                rem -= 1
                if rem == 0:
                    return res
        raise Exception

4.7.477 - 2025-08-21 17:51:03 +0300 MSK

Minimum Right Shifts to Sort the Array
class Solution:
    def minimumRightShifts(self, nums: List[int]) -> int:
        drop = -1
        for i, num in enumerate(nums[1:], 1):
            if num > nums[i - 1]:
                continue
            if drop != -1:
                return -1
            drop = i
        if drop == -1:
            return 0
        if nums[0] <= nums[-1]:
            return -1
        return len(nums) - drop

4.7.478 - 2025-08-21 17:41:49 +0300 MSK

Points That Intersect With Cars
class Solution:
    def numberOfPoints(self, nums: List[List[int]]) -> int:
        line = [0] * 102
        points_on_line = 0
        for start, end in nums:
            line[start] += 1
            line[end + 1] -= 1
        for i in range(1, 102):
            line[i] += line[i - 1]
            if line[i] != 0:
                points_on_line += 1
        return points_on_line

4.7.479 - 2025-08-21 17:35:46 +0300 MSK

Check if Strings Can be Made Equal With Operations I
class Solution:
    def canBeEqual(self, s1: str, s2: str) -> bool:
        freqs_even = [0] * 26
        freqs_odd = [0] * 26
        for i, (char1, char2) in enumerate(zip(s1, s2)):
            if i % 2 == 0:
                trg = freqs_even
            else:
                trg = freqs_odd
            trg[ord(char1) - 97] += 1
            trg[ord(char2) - 97] -= 1
        for freq1, freq2 in zip(freqs_even, freqs_odd):
            if freq1 != 0 or freq2 != 0:
                return False
        return True

4.7.480 - 2025-08-21 17:31:03 +0300 MSK

Furthest Point From Origin
class Solution:
    def furthestDistanceFromOrigin(self, moves: str) -> int:
        cnt_left, cnt_right, cnt_any = 0, 0, 0
        for char in moves:
            if char == "L":
                cnt_left += 1
            elif char == "R":
                cnt_right += 1
            else:
                cnt_any += 1
        if cnt_right > cnt_left:
            return cnt_right - cnt_left + cnt_any
        return cnt_left - cnt_right + cnt_any

4.7.481 - 2025-08-21 17:26:29 +0300 MSK

Check if a String Is an Acronym of Words
class Solution:
    def isAcronym(self, words: List[str], s: str) -> bool:
        if len(words) != len(s):
            return False
        for i in range(len(words)):
            if words[i][0] != s[i]:
                return False
        return True

4.7.482 - 2025-08-21 17:15:57 +0300 MSK

Max Pair Sum in an Array
class Solution:
    def maxSum(self, nums: List[int]) -> int:
        freqs = [[] for _ in range(10)]
        for num in nums:
            dig = 0
            orig = num
            while num > 0:
                dig = max(dig, num % 10)
                num //= 10
            heapq.heappush(freqs[dig], -orig)
        res = -1
        for nms in freqs:
            if len(nms) < 2:
                continue
            res = max(res, -(heapq.heappop(nms) + heapq.heappop(nms)))
        return res

4.7.483 - 2025-08-21 17:07:52 +0300 MSK

Split Strings by Separator
class Solution:
    def splitWordsBySeparator(self, words: List[str], separator: str) -> List[str]:
        res = []
        cur = []
        for word in words:
            for char in itertools.chain(word, separator):
                if char != separator:
                    cur.append(char)
                elif cur:
                    res.append("".join(cur))
                    cur.clear()
        return res

4.7.484 - 2025-08-21 17:05:33 +0300 MSK

Check if Array is Good
class Solution:
    def isGood(self, nums: list[int]) -> bool:
        mx = max(nums)
        if len(nums) != mx + 1:
            return False
        freqs = defaultdict(int)
        for num in nums:
            freqs[num] += 1
        if freqs[mx] != 2:
            return False
        for i in range(1, mx):
            if freqs[i] != 1:
                return False
        return True

4.7.485 - 2025-08-21 17:00:40 +0300 MSK

Sum of Squares of Special Elements
class Solution:
    def sumOfSquares(self, nums: List[int]) -> int:
        n = len(nums)
        res = 0
        for i in range(1, int(math.sqrt(n)) + 1):
            if n % i != 0:
                continue
            idx1, idx2 = i - 1, (n // i) - 1
            res += nums[idx1] ** 2
            if idx2 != idx1:
                res += nums[idx2] ** 2
        return res

4.7.486 - 2025-08-21 16:51:13 +0300 MSK

Sum of Squares of Special Elements
class Solution:
    def sumOfSquares(self, nums: List[int]) -> int:
        n = len(nums)
        res = 0
        for i in range(n):
            if n % (i + 1) == 0:
                res += nums[i] ** 2
        return res

4.7.487 - 2025-08-21 16:50:01 +0300 MSK

Find the Maximum Achievable Number
class Solution:
    def theMaximumAchievableX(self, num: int, t: int) -> int:
        return num + (t * 2) 

4.7.488 - 2025-08-21 16:46:44 +0300 MSK

Longest Alternating Subarray
class Solution:
    def alternatingSubarray(self, nums: list[int]) -> int:
        n = len(nums)
        maxi = 0
        for i in range(n - 1):
            if nums[i + 1] != nums[i] + 1:
                continue
            curr, prev = 2, 1
            for j in range(i + 2, n):
                diff = nums[j] - nums[j - 1]
                if diff == -prev:
                    curr += 1
                    prev = -prev
                else:
                    break
            maxi = max(maxi, curr)
        return maxi if maxi > 0 else -1

4.7.489 - 2025-08-21 16:44:37 +0300 MSK

Longest Even Odd Subarray With Threshold
class Solution:
    def longestAlternatingSubarray(self, nums: list[int], threshold: int) -> int:
        n = len(nums)
        if n == 1:
            if nums[0] % 2 == 0 and nums[0] <= threshold:
                return 1
            return 0
        length = 0
        for l in range(n):
            if nums[l] % 2 != 0:
                continue
            for r in range(l, n):
                if nums[r] > threshold:
                    break
                ok = True
                for i in range(l, r):
                    if nums[i] % 2 == nums[i + 1] % 2:
                        ok = False
                        break
                if ok:
                    length = max(length, r - l + 1)
        return length

4.7.490 - 2025-08-21 16:42:44 +0300 MSK

Number of Beautiful Pairs
class Solution:
    def countBeautifulPairs(self, nums: List[int]) -> int:
        def check(num1: int, num2: int) -> bool: 
            first, last = 0, num2 % 10
            while num1 > 0:
                first = num1 % 10
                num1 //= 10
            return math.gcd(first, last) == 1
        res = 0
        for i in range(len(nums)):
            for j in range(i + 1, len(nums)):
                if check(nums[i], nums[j]):
                    res += 1
        return res

4.7.491 - 2025-08-21 16:38:20 +0300 MSK

Find Maximum Number of String Pairs
class Solution:
    def maximumNumberOfStringPairs(self, words: List[str]) -> int:
        enc = set()
        res = 0
        for word in words:
            if word in enc:
                res += 1
            else:
                enc.add(word[::-1])
        return res

4.7.492 - 2025-08-21 16:26:55 +0300 MSK

Total Distance Traveled
class Solution:
    def distanceTraveled(self, mainTank: int, additionalTank: int) -> int:
        res = 0
        while mainTank > 4:
            count = mainTank // 5
            res += count * 5
            mainTank %= 5
            add_count = min(count, additionalTank)
            additionalTank -= add_count
            mainTank += add_count
        res += mainTank
        return res * 10

4.7.493 - 2025-08-21 16:19:42 +0300 MSK

Neither Minimum nor Maximum
class Solution:
    def findNonMinOrMax(self, nums: List[int]) -> int:
        nums.sort()
        min_val, max_val = nums[0], nums[-1]
        if nums[0] == nums[-1]:
            return -1
        if len(nums) < 3:
            return -1
        left, right = 0, len(nums) - 1
        while left <= right:
            mid = left + (right - left) // 2
            val = nums[mid]
            if val == min_val:
                left = mid + 1
            elif val == max_val:
                right = mid - 1
            return val
        return -1

4.7.494 - 2025-08-21 16:16:56 +0300 MSK

Check if The Number is Fascinating
class Solution:
    def isFascinating(self, n: int) -> bool:
        freqs = [False] * 9
        for num in (n, n * 2, n * 3):
            while num > 0:
                dig = num % 10
                if dig == 0:
                    return False
                if freqs[dig - 1]:
                    return False
                freqs[dig - 1] = True
                num //= 10
        return sum(freqs) == 9

4.7.495 - 2025-08-21 16:07:01 +0300 MSK

Is Object Empty
/**
 * @param {Object|Array} obj
 * @return {boolean}
 */
var isEmpty = function(obj) {
    if (Array.isArray(obj)) {
        return obj.length === 0;
    } else {
        return Object.keys(obj).length === 0;
    }
};

4.7.496 - 2025-08-21 16:06:09 +0300 MSK

Calculator with Method Chaining
class Calculator {
    
    /** 
     * @param {number} value
     */
    constructor(value) {
        this.result = value 
    }
    
    /** 
     * @param {number} value
     * @return {Calculator}
     */
    add(value){
        this.result += value 
        return this 
    }
    
    /** 
     * @param {number} value
     * @return {Calculator}
     */
    subtract(value){
        this.result -= value 
        return this 
    }
    
    /** 
     * @param {number} value
     * @return {Calculator}
     */  
    multiply(value) {
        this.result *= value 
        return this 
    }
    
    /** 
     * @param {number} value
     * @return {Calculator}
     */
    divide(value) {

   if(value === 0){
     throw new Error("Division by zero is not allowed")
        }
        this.result /= value 
        return this 
    }
    
    /** 
     * @param {number} value
     * @return {Calculator}
     */
    power(value) {
        this.result **= value 
        return this 
    }
    
    /** 
     * @return {number}
     */
    getResult() {
        return this.result 
    }
}

4.7.497 - 2025-08-21 16:01:02 +0300 MSK

Interval Cancellation
/**
 * @param {Function} fn
 * @param {Array} args
 * @param {number} t
 * @return {Function}
 */
var cancellable = function(fn, args, t) {
    fn(...args);
    const timer = setInterval(() => fn(...args), t);
    const cancelFn = () => clearInterval(timer);
    return cancelFn;
};

/**
 *  const result = [];
 *
 *  const fn = (x) => x * 2;
 *  const args = [4], t = 35, cancelTimeMs = 190;
 *
 *  const start = performance.now();
 *
 *  const log = (...argsArr) => {
 *      const diff = Math.floor(performance.now() - start);
 *      result.push({"time": diff, "returned": fn(...argsArr)});
 *  }
 *       
 *  const cancel = cancellable(log, args, t);
 *
 *  setTimeout(cancel, cancelTimeMs);
 *   
 *  setTimeout(() => {
 *      console.log(result); // [
 *                           //     {"time":0,"returned":8},
 *                           //     {"time":35,"returned":8},
 *                           //     {"time":70,"returned":8},
 *                           //     {"time":105,"returned":8},
 *                           //     {"time":140,"returned":8},
 *                           //     {"time":175,"returned":8}
 *                           // ]
 *  }, cancelTimeMs + t + 15)    
 */

4.7.498 - 2025-08-21 15:58:36 +0300 MSK

Sort By
/**
 * @param {Array} arr
 * @param {Function} fn
 * @return {Array}
 */
var sortBy = function(arr, fn) {
    return arr.toSorted((a, b) => fn(a) - fn(b));
};

4.7.499 - 2025-08-21 15:55:14 +0300 MSK

Add Two Promises
/**
 * @param {Promise} promise1
 * @param {Promise} promise2
 * @return {Promise}
 */
var addTwoPromises = async function(promise1, promise2) {
    const [value1, value2] = await Promise.all([promise1, promise2]);
    return value1 + value2;
};

// // Example usage:
// var promise1 = new Promise(resolve => setTimeout(() => resolve(2), 20));
// var promise2 = new Promise(resolve => setTimeout(() => resolve(5), 60));

// addTwoPromises(promise1, promise2)
//   .then(console.log); // Output: 7

4.7.500 - 2025-08-21 15:49:02 +0300 MSK

Semi-Ordered Permutation
class Solution:
    def semiOrderedPermutation(self, nums: List[int]) -> int:
        i1, i2 = 0, 0
        n = len(nums)
        for i, num in enumerate(nums):
            if num == 1:
                i1 = i
            elif num == n:
                i2 = i
            if i1 and i2:
                break
        res = i1 + (n - i2 - 1)
        if i2 < i1:
            res -= 1
        return res

4.7.501 - 2025-08-21 15:45:35 +0300 MSK

Minimize String Length
class Solution:
    def minimizedStringLength(self, s: str) -> int:
        freqs = [False] * 26
        for char in s:
            freqs[ord(char) - 97] = True
        return sum(freqs)

4.7.502 - 2025-08-21 15:42:45 +0300 MSK

Timeout Cancellation
/**
 * @param {Function} fn
 * @param {Array} args
 * @param {number} t
 * @return {Function}
 */
const cancellable = function(fn, args, t) {
    const timer = setTimeout(() => {
        fn(...args)
    }, t);
    const cancelFn = function() {
        clearTimeout(timer);
    };
    return cancelFn;
};


/**
 *  const result = []
 *
 *  const fn = (x) => x * 5
 *  const args = [2], t = 20, cancelT = 50
 *
 *  const log = (...argsArr) => {
 *      result.push(fn(...argsArr))
 *  }
 *       
 *  const cancel = cancellable(fn, args, t);
 *           
 *  setTimeout(() => {
 *     cancel()
 *     console.log(result) // [{"time":20,"returned":10}]
 *  }, cancelT)
 */

4.7.503 - 2025-08-21 15:40:49 +0300 MSK

Remove Trailing Zeros From a String
class Solution:
    def removeTrailingZeros(self, num: str) -> str:
        val = int(num)
        while val > 0 and val % 10 == 0:
            val //= 10
        return str(val)

4.7.504 - 2025-08-21 15:37:36 +0300 MSK

To Be Or Not To Be
class Check {
    constructor(val) {
        this.val = val;
    }
    toBe(val) {
        if (val === this.val) {
            return true;
        }
        throw new Error("Not Equal");
    }
    notToBe(val) {
        if (val !== this.val) {
            return true;
        }
        throw new Error("Equal");
    }
}

/**
 * @param {string} val
 * @return {Object}
 */
var expect = function(val) {
    return new Check(val);  
};

/**
 * expect(5).toBe(5); // true
 * expect(5).notToBe(5); // throws "Equal"
 */

4.7.505 - 2025-08-21 15:33:15 +0300 MSK

Return Length of Arguments Passed
/**
 * @param {...(null|boolean|number|string|Array|Object)} args
 * @return {number}
 */
var argumentsLength = function(...args) {
    return args.length;
};

/**
 * argumentsLength(1, 2, 3); // 3
 */

4.7.506 - 2025-08-21 15:32:49 +0300 MSK

Lexicographically Smallest Palindrome
class Solution:
    def makeSmallestPalindrome(self, s: str) -> str:
        letters = list(s)
        for i in range(len(s) // 2):
            letters[i] = letters[~i] = min(letters[i], letters[~i])
        return ''.join(letters)

4.7.507 - 2025-08-21 15:03:03 +0300 MSK

Minimum String Length After Removing Substrings
class Solution:
    def minLength(self, s: str) -> int:
        stack = []
        for char in s:
            if not stack or char not in "ABCD":
                stack.append(char)
                continue
            if (
                (stack[-1] == "A" and char == "B") 
                or (stack[-1] == "C" and char == "D")
            ):
                stack.pop()
            else:
                stack.append(char)
        return len(stack)

4.7.508 - 2025-08-21 14:57:54 +0300 MSK

Minimum String Length After Removing Substrings
class Solution:
    def minLength(self, s: str) -> int:
        while "AB" in s or "CD" in s:
            s = s.replace("AB", "").replace("CD", "")
        return len(s)

4.7.509 - 2025-08-21 14:56:18 +0300 MSK

Array Wrapper
/**
 * @param {number[]} nums
 * @return {void}
 */
var ArrayWrapper = function(nums) {
    this.sum = nums.reduce((a, b) => a + b, 0);
    this.string = `[${nums.toString()}]`;
};

/**
 * @return {number}
 */
ArrayWrapper.prototype.valueOf = function() {
    return this.sum;
}

/**
 * @return {string}
 */
ArrayWrapper.prototype.toString = function() {
    return this.string;
}

/**
 * const obj1 = new ArrayWrapper([1,2]);
 * const obj2 = new ArrayWrapper([3,4]);
 * obj1 + obj2; // 10
 * String(obj1); // "[1,2]"
 * String(obj2); // "[3,4]"
 */

4.7.510 - 2025-08-21 14:52:44 +0300 MSK

Find the Losers of the Circular Game
class Solution:
    def circularGameLosers(self, n: int, k: int) -> List[int]:
        count = 1
        i = 0
        enc = set((0, ))
        while True:
            i = (i + k * count) % n
            if i in enc:
                break
            enc.add(i)
            count += 1
        res = []
        for i in range(n):
            if i not in enc:
                res.append(i + 1)
        return res

4.7.511 - 2025-08-21 14:47:10 +0300 MSK

Number of Senior Citizens
class Solution:
    def countSeniors(self, details: List[str]) -> int:
        count = 0
        for detail in details:
            if int(detail[-4:-2]) > 60:
                count += 1
        return count

4.7.512 - 2025-08-21 14:44:56 +0300 MSK

Chunk Array
/**
 * @param {Array} arr
 * @param {number} size
 * @return {Array}
 */
var chunk = function(arr, size) {
    const chunkedArray = [];
    let index = 0;
    while (index < arr.length) {
        chunkedArray.push(arr.slice(index, index + size));
        index += size;
    }
    return chunkedArray;
};

4.7.513 - 2025-08-21 14:42:42 +0300 MSK

Find the Distinct Difference Array
class Solution:
    def distinctDifferenceArray(self, nums: List[int]) -> List[int]:
        left, right = set(), defaultdict(int)
        for num in nums:
            right[num] += 1
        res = []
        for num in nums:
            left.add(num)
            right[num] -= 1
            if right[num] == 0:
                del right[num]
            res.append(len(left) - len(right))
        return res

4.7.514 - 2025-08-21 14:32:28 +0300 MSK

Create Hello World Function
/**
 * @return {Function}
 */
var createHelloWorld = function() {
    
    return function(...args) {
        return "Hello World";
    }
};

/**
 * const f = createHelloWorld();
 * f(); // "Hello World"
 */

4.7.515 - 2025-08-21 14:31:55 +0300 MSK

Allow One Function Call
/**
 * @param {Function} fn
 * @return {Function}
 */
var once = function(fn) {
    let called = false;
    return function(...args){
        if (called) {
            return undefined;
        }
        called = true;
        return fn(...args);
    }
};

/**
 * let fn = (a,b,c) => (a + b + c)
 * let onceFn = once(fn)
 *
 * onceFn(1,2,3); // 6
 * onceFn(2,3,6); // returns undefined without calling fn
 */

4.7.516 - 2025-08-21 14:30:46 +0300 MSK

Counter II
class Counter {
    constructor(init) {
        this.init = init;
        this.val = init;
    }
    increment() {
        let val = this.val + 1;
        this.val = val;
        return val;
    }
    decrement() {
        let val = this.val - 1;
        this.val = val;
        return val;
    }
    reset() {
        let val = this.init;
        this.val = val;
        return val;
    }
}

/**
 * @param {integer} init
 * @return { increment: Function, decrement: Function, reset: Function }
 */
var createCounter = function(init) {
    return new Counter(init)
};

/**
 * const counter = createCounter(5)
 * counter.increment(); // 6
 * counter.reset(); // 5
 * counter.decrement(); // 4
 */

4.7.517 - 2025-08-21 14:28:11 +0300 MSK

Determine the Winner of a Bowling Game
class Solution:
    def isWinner(self, player1: List[int], player2: List[int]) -> int:
        last_10_1, last_10_2 = -10, -10
        score = 0
        for i, (hit1, hit2) in enumerate(zip(player1, player2)):
            mult1, mult2 = 1, 1
            if i - last_10_1 < 3:
                mult1 = 2
            if i - last_10_2 < 3:
                mult2 = 2
            score += hit1 * mult1 - hit2 * mult2
            if hit1 == 10:
                last_10_1 = i
            if hit2 == 10:
                last_10_2 = i
        if score > 0:
            return 1
        elif score < 0:
            return 2
        return 0

4.7.518 - 2025-08-21 14:14:45 +0300 MSK

Maximum Sum With Exactly K Elements
class Solution:
    def maximizeSum(self, nums: List[int], k: int) -> int:
        first = max(nums)
        last = first + (k - 1) * 1
        return (k * (first + last)) // 2

4.7.519 - 2025-08-21 14:03:34 +0300 MSK

Sum Multiples
class Solution:
    def sumOfMultiples(self, n: int) -> int:
        enc = set()
        for num in range(3, n + 1, 3):
            enc.add(num)
        for num in range(5, n + 1, 5):
            enc.add(num)
        for num in range(7, n + 1, 7):
            enc.add(num)
        return sum(enc)

4.7.520 - 2025-08-21 13:59:45 +0300 MSK

Calculate Delayed Arrival Time
class Solution:
    def findDelayedArrivalTime(self, arrivalTime: int, delayedTime: int) -> int:
        return (arrivalTime + delayedTime) % 24

4.7.521 - 2025-08-21 13:58:37 +0300 MSK

Generate Fibonacci Sequence
/**
 * @return {Generator<number>}
 */
var fibGenerator = function*() {
    let num1 = 0;
    let num2 = 1;
    yield num1;
    yield num2;
    while (true) {
        const num3 = num1 + num2;
        num1 = num2;
        num2 = num3;
        yield num3; 
    }
};

/**
 * const gen = fibGenerator();
 * gen.next().value; // 0
 * gen.next().value; // 1
 */

4.7.522 - 2025-08-21 13:56:09 +0300 MSK

Find the Maximum Divisibility Score
class Solution:
    def maxDivScore(self, nums: List[int], divisors: List[int]) -> int:
        freqs = defaultdict(int)
        for num in nums:
            freqs[num] += 1
        divisors.sort()
        max_div, max_count = divisors[0], 0
        for div in divisors:
            count = 0
            for num, freq in freqs.items():
                if num % div == 0:
                    count += freq
            if count > max_count:
                max_div, max_count = div, count
        return max_div

4.7.523 - 2025-08-21 13:42:53 +0300 MSK

Row With Maximum Ones
class Solution:
    def rowAndMaximumOnes(self, mat: List[List[int]]) -> List[int]:
        max_row, max_count = 0, sum(mat[0])
        for i, row in enumerate(mat[1:], 1):
            count = sum(row)
            if count > max_count:
                max_row, max_count = i, count
        return max_row, max_count

4.7.524 - 2025-08-21 13:40:48 +0300 MSK

Find the Width of Columns of a Grid
class Solution:
    def findColumnWidth(self, grid: List[List[int]]) -> List[int]:
        res = []
        for col in range(len(grid[0])):
            max_len = 0
            for row in range(len(grid)):
                val = grid[row][col]
                if val == 0:
                    count = 1
                elif val < 0:
                    count = 1
                    val = -val
                else:
                    count = 0
                while val > 0:
                    count += 1
                    val //= 10
                max_len = max(max_len, count)
            res.append(max_len)
        return res

4.7.525 - 2025-08-21 13:31:24 +0300 MSK

Range Sum Query - Mutable
class TreeNode:
    def __init__(self, val, start, end, left_child = None, right_child = None):
        self.val = val
        self.start = start
        self.end = end
        self.left_child = left_child
        self.right_child = right_child
        
class SegmentTree:
    def __init__(self, nums):
        self.nums = nums
        self.root = self.build(0, len(nums) - 1)
    
    def build(self, start, end):
        if start == end:
            return TreeNode(self.nums[start], start, end)
        left_child = self.build(start, (start + end) //2)
        right_child = self.build((start+end) // 2 + 1, end)
        return TreeNode(left_child.val + right_child.val, start, end, left_child, right_child)
    
    def update(self, root, index, value):
        if root.start == root.end and index == root.start: # target
            root.val = value
            return value
        if root.start > index or root.end < index:
            return root.val
        root.val = self.update(root.left_child, index, value) + self.update(root.right_child, index, value)
        return root.val

    def query(self, root, left, right):
        if root.start > right or root.end < left: return 0
        if root.start >= left and root.end <= right: return root.val
        return self.query(root.left_child, left, right) + self.query(root.right_child, left, right)

class NumArray:
    def __init__(self, nums: List[int]):
        self.tree = SegmentTree(nums)
        self.root = self.tree.root

    def update(self, index: int, val: int) -> None:
        self.tree.update(self.root, index, val)

    def sumRange(self, left: int, right: int) -> int:
        return self.tree.query(self.root, left, right)

4.7.526 - 2025-08-21 13:26:07 +0300 MSK

Online Election
class TopVotedCandidate:

    def __init__(self, persons: List[int], times: List[int]):
        self._lead = times
        freqs = [0] * 5001
        prev = persons[0]
        freqs[prev] = 1
        times[0] = (times[0], prev)
        for i in range(1, len(times)):
            person = persons[i]
            freq = freqs[person] + 1
            freqs[person] = freq
            if freq >= freqs[prev]:
                prev = person
            times[i] = (times[i], prev)
        
    def q(self, t: int) -> int:
        left, right = 0, len(self._lead) - 1
        res = None
        while left <= right:
            mid = left + (right - left) // 2
            lead_time, lead_person = self._lead[mid]
            if lead_time > t:
                right = mid - 1
            elif lead_time == t:
                return lead_person
            else:
                res = lead_person
                left = mid + 1
        return res


# Your TopVotedCandidate object will be instantiated and called as such:
# obj = TopVotedCandidate(persons, times)
# param_1 = obj.q(t)

4.7.527 - 2025-08-21 12:41:54 +0300 MSK

Walking Robot Simulation II
class Robot:

    def __init__(self, width: int, height: int):
        self.cur = (0, 0)
        self.cur_dir = 0
        self.width = width
        self.height = height
        self.dir_mapping = {
            0: "East",
            1: "North",
            2: "West",
            3: "South"
        }
        self.mod = 2 * (self.width + self.height - 2)

    def step(self, num: int) -> None:
        if num >= self.mod:
            num %= self.mod
            if self.cur == (0, 0) and self.cur_dir == 0:
                self.cur_dir = 3
        row, col = self.cur
        while num > 0:
            if self.cur_dir == 0:
                steps = min(num, self.width - row -1)
                num -= steps
                row += steps
            elif self.cur_dir == 1:
                steps = min(num, self.height -1 - col)
                num -= steps
                col += steps
            elif self.cur_dir == 2:
                steps = min(num, row)
                num -= steps
                row -= steps
            else:
                steps = min(num, col)
                num -= steps
                col -= steps
            if num > 0:
                self.cur_dir = (self.cur_dir + 1) % 4
        self.cur = row, col

    def getPos(self) -> List[int]:
        return self.cur

    def getDir(self) -> str:
        return self.dir_mapping[self.cur_dir]

# Your Robot object will be instantiated and called as such:
# obj = Robot(width, height)
# obj.step(num)
# param_2 = obj.getPos()
# param_3 = obj.getDir()

4.7.528 - 2025-08-21 12:07:22 +0300 MSK

Number of Beautiful Integers in the Range
class Solution:
    def numberOfBeautifulIntegers(self, low: int, high: int, k: int) -> int:
        low, hgh = str(low), str(high)  
        n = len(hgh)                    
        low = low.rjust(n,'0')          
        @lru_cache(None)
        def dfs(idx,
                belowHgh,                
                aboveLow,                
                init0,
                parity,
                rem):                    
            if idx == n: 
                return rem == 0 == parity  
            lowD, hghD = int(low[idx]), int(hgh[idx])
            res = 0
            for digit in range(0 if aboveLow else lowD,
                               (9 if belowHgh else hghD) + 1):
                res += dfs(idx + 1,
                           belowHgh or digit < hghD,
                           aboveLow or digit > lowD,
                           init0 and not digit,
                           parity + digit % 2 - (
                                    not init0 and not digit or
                                    digit and not digit % 2),
                           (rem * 10 + digit) % k)
            return res
        return dfs(0, False, False, True, 0, 0)

4.7.529 - 2025-08-21 11:45:30 +0300 MSK

Minimum Seconds to Equalize a Circular Array
class Solution:
    def minimumSeconds(self, nums: List[int]) -> int:
        nums += nums
        indices = defaultdict(list)
        for i, num in enumerate(nums):
            indices[num].append(i)
        min_diff = math.inf
        for idxs in indices.values():
            max_diff = -math.inf
            for i1, i2 in itertools.pairwise(idxs):
                max_diff = max(max_diff, i2 - i1)
            min_diff = min(min_diff, max_diff // 2)
        return min_diff

4.7.530 - 2025-08-21 11:32:12 +0300 MSK

Longest Arithmetic Subsequence of Given Difference
class Solution:
    def longestSubsequence(self, arr: List[int], difference: int) -> int:
        dp = {}
        for num in arr:
            prv = num - difference 
            if prv in dp:
                dp[num] = dp[prv] + 1
            else:
                dp[num] = 1
        return max(dp.values())

4.7.531 - 2025-08-21 11:29:38 +0300 MSK

Longest Arithmetic Subsequence of Given Difference
class Solution:
    def longestSubsequence(self, arr: List[int], difference: int) -> int:
        n = len(arr)
        freqs = defaultdict(list)
        for i, num in enumerate(arr):
            freqs[num].append(i)
        dp = [1] * n
        for i in reversed(range(n - 1)):
            cur, nxt = arr[i], arr[i] + difference
            if nxt not in freqs:
                continue
            cnt = 0
            for j in freqs[nxt]:
                if j > i:
                    cnt = max(cnt, dp[j])
            dp[i] = cnt + 1
        return max(dp)

4.7.532 - 2025-08-21 11:16:33 +0300 MSK

Shortest String That Contains Three Strings
class Solution:
    def minimumString(self, a: str, b: str, c: str) -> str:
        res, l = '', float('inf')
        def merge(s1: str, s2: str) -> str:
            if s2 in s1:
                return s1
            for i in range(len(s1)):
                if s2.startswith(s1[i:]):
                    return s1[:i] + s2
            return s1 + s2
        for s1, s2, s3 in itertools.permutations((a, b ,c)): 
            merged = merge(merge(s1, s2), s3)
            if len(merged) < l:
                res, l = merged, len(merged)
            elif len(merged) == l:
                res = min(res, merged)
        return res

4.7.533 - 2025-08-21 11:08:30 +0300 MSK

Design Neighbor Sum Service
class NeighborSum:

    def __init__(self, grid: List[List[int]]):
        self._adj = [0] * 101
        self._diag = [0] * 101
        rows, cols = len(grid), len(grid[0])
        adj_moves = ((0, 1), (0, -1), (-1, 0), (1, 0))
        diag_moves = ((-1, -1), (-1, 1), (1, -1), (1, 1))
        for row in range(rows):
            for col in range(cols):
                val = grid[row][col]
                for row_dlt, col_dlt in adj_moves:
                    adj_row, adj_col = row + row_dlt, col + col_dlt
                    if 0 <= adj_row < rows and 0 <= adj_col < cols:
                        self._adj[grid[adj_row][adj_col]] += val
                for row_dlt, col_dlt in diag_moves:
                    diag_row, diag_col = row + row_dlt, col + col_dlt
                    if 0 <= diag_row < rows and 0 <= diag_col < cols:
                        self._diag[grid[diag_row][diag_col]] += val

    def adjacentSum(self, value: int) -> int:
        return self._adj[value]

    def diagonalSum(self, value: int) -> int:
        return self._diag[value]


# Your NeighborSum object will be instantiated and called as such:
# obj = NeighborSum(grid)
# param_1 = obj.adjacentSum(value)
# param_2 = obj.diagonalSum(value)

4.7.534 - 2025-08-21 08:52:21 +0300 MSK

Count Submatrices With All Ones
class Solution:
    def numSubmat(self, mat: List[List[int]]) -> int:
        heights = [0] * len(mat[0])
        res = 0
        for row in mat:
            for i, x in enumerate(row):
                heights[i] = 0 if x == 0 else heights[i] + 1
            stack = [[-1, 0, -1]]
            for i, h in enumerate(heights):
                while stack[-1][2] >= h:
                    stack.pop()
                j, prev, _ = stack[-1]
                cur = prev + (i - j) * h
                stack.append([i, cur, h])
                res += cur
        return res

4.7.535 - 2025-08-20 20:41:08 +0300 MSK

Apply Transform Over Each Element in Array
/**
 * @param {number[]} arr
 * @param {Function} fn
 * @return {number[]}
 */
var map = function(arr, fn) {
  const transformedArr = [];
  let index = 0;
  for (const element of arr) {
    transformedArr[index] = fn(element, index);
    index++;
  }
  return transformedArr;
};

4.7.536 - 2025-08-20 20:38:27 +0300 MSK

Filter Elements from Array
/**
 * @param {number[]} arr
 * @param {Function} fn
 * @return {number[]}
 */
var filter = function(arr, fn) {
    let res = [];
    for (const [i, val] of arr.entries()) {
        if (fn(val, i)) {
            res.push(val);
        }
    }
    return res;
};

4.7.537 - 2025-08-20 20:36:18 +0300 MSK

Function Composition
/**
 * @param {Function[]} functions
 * @return {Function}
 */
var compose = function(functions) {
	if (functions.length === 0) {
        return function(x) { return x; };
    }
    return functions.reduceRight(function(prevFn, nextFn) {
        return function(x) {
            return nextFn(prevFn(x));
        };
    });
};

4.7.538 - 2025-08-20 20:31:33 +0300 MSK

Array Reduce Transformation
/**
 * @param {number[]} nums
 * @param {Function} fn
 * @param {number} init
 * @return {number}
 */
var reduce = function(nums, fn, init) {
    let res = init;
    for (const num of nums) {
        res = fn(res, num);
    }
    return res;
};

4.7.539 - 2025-08-20 20:28:21 +0300 MSK

Sleep
/**
 * @param {number} millis
 * @return {Promise}
 */
async function sleep(millis) {
    return new Promise((resolve) => setTimeout(resolve, millis));   
}

/** 
 * let t = Date.now()
 * sleep(100).then(() => console.log(Date.now() - t)) // 100
 */

4.7.540 - 2025-08-20 20:26:57 +0300 MSK

Counter
/**
 * @param {number} n
 * @return {Function} counter
 */
var createCounter = function(n) {
    val = n - 1;
    return function() {
        val += 1;
        return val;
    };
};

/** 
 * const counter = createCounter(10)
 * counter() // 10
 * counter() // 11
 * counter() // 12
 */

4.7.541 - 2025-08-20 20:25:45 +0300 MSK

Array Prototype Last
/**
 * @return {null|boolean|number|string|Array|Object}
 */
Array.prototype.last = function() {
    if (this.length > 0) {
        return this[this.length - 1];
    }
    return -1;
};

/**
 * const arr = [1, 2, 3];
 * arr.last(); // 3
 */

4.7.542 - 2025-08-20 20:20:02 +0300 MSK

Prime In Diagonal
class Solution:
    def diagonalPrime(self, nums: List[List[int]]) -> int:
        def is_prime(num: int) -> int:
            if num <= 1:
                return 0
            for i in range(2, int(math.sqrt(num)) + 1):
                if num % i == 0:
                    return 0
            return num
        res = 0
        n = len(nums)
        for i in range(n):
            res = max(res, is_prime(nums[i][i]), is_prime(nums[i][n - i - 1]))
        return res

4.7.543 - 2025-08-20 20:15:03 +0300 MSK

Find the Longest Balanced Substring of a Binary String
class Solution:
    def findTheLongestBalancedSubstring(self, s: str) -> int:
        res = 0
        cnt_0, cnt_1 = 0, 0
        for char in s:
            if char == "0":
                if cnt_1 != 0:
                    cnt_0 = 0
                cnt_0 += 1
                cnt_1 = 0
            else:
                cnt_1 += 1
                res = max(res, min(cnt_0, cnt_1) * 2)
        return res

4.7.544 - 2025-08-20 20:10:18 +0300 MSK

Form Smallest Number From Two Digit Arrays
class Solution:
    def minNumber(self, nums1: List[int], nums2: List[int]) -> int:
        freqs1 = [False] * 10
        freqs2 = [False] * 10
        for num in nums1:
            freqs1[num] = True
        for num in nums2:
            freqs2[num] = True
        min1, min2 = None, None
        for i in range(10):
            if freqs1[i] and freqs2[i]:
                return i
            if min1 is None and freqs1[i]:
                min1 = i
            if min2 is None and freqs2[i]:
                min2 = i
        return min(min1, min2) * 10 + max(min1, min2) 
        

4.7.545 - 2025-08-20 19:48:54 +0300 MSK

K Items With the Maximum Sum
class Solution:
    def kItemsWithMaximumSum(self, numOnes: int, numZeros: int, numNegOnes: int, k: int) -> int:
        res = 0
        for val, cnt in ((1, numOnes), (0, numZeros), (-1, numNegOnes)):
            if k == 0:
                break
            cnt = min(k, cnt)
            k -= cnt
            res += val * cnt
        return res

4.7.546 - 2025-08-20 19:41:49 +0300 MSK

Distribute Money to Maximum Children
class Solution:
    def distMoney(self, money: int, children: int) -> int:
        if money < children: 
            return -1 
        n = 8 * children - money
        if n <= 0: 
            return children - (n < 0)
        ans, rem = divmod(money - children, 7)
        return ans - ((ans, rem) == (children - 1, 3))

4.7.547 - 2025-08-20 19:24:46 +0300 MSK

Count the Number of Vowel Strings in Range
class Solution:
    def vowelStrings(self, words: List[str], left: int, right: int) -> int:
        res = 0
        vowels = ("a", "e", "i", "o", "u")
        for i in range(left, right + 1):
            word = words[i]
            if word[0] in vowels and word[-1] in vowels:
                res += 1
        return res

4.7.548 - 2025-08-20 19:22:34 +0300 MSK

Pass the Pillow
class Solution:
    def passThePillow(self, n, time):
        full_rounds = time // (n - 1)
        extra_time = time % (n - 1)
        if full_rounds % 2 == 0:
            return extra_time + 1
        else:
            return n - extra_time

4.7.549 - 2025-08-20 19:11:13 +0300 MSK

Split With Minimum Sum
class Solution:
    def splitNum(self, num: int) -> int:
        count = 0
        digits = []
        while num > 0:
            digits.append(num % 10)
            num //= 10
        digits.sort()
        res = 0
        while digits:
            for _ in range(2):
                if digits:    
                    res += digits.pop() * (10 ** count)
            count += 1
        return res

4.7.550 - 2025-08-20 19:07:59 +0300 MSK

Left and Right Sum Differences
class Solution:
    def leftRightDifference(self, nums: List[int]) -> List[int]:
        left, right = 0, sum(nums)
        for i in range(len(nums)):
            val = nums[i]
            right -= val
            nums[i] = abs(left - right)
            left += val
        return nums

4.7.551 - 2025-08-20 19:05:44 +0300 MSK

Merge Two 2D Arrays by Summing Values
class Solution:
    def mergeArrays(self, nums1: List[List[int]], nums2: List[List[int]]) -> List[List[int]]:
        freqs = [0] * 1001
        for idx, val in itertools.chain(nums1, nums2):
            freqs[idx] += val
        res = []
        for i, freq in enumerate(freqs):
            if freq > 0:
                res.append((i, freq))
        return res

4.7.552 - 2025-08-20 19:01:55 +0300 MSK

Maximum Difference by Remapping a Digit
class Solution:
    def minMaxDifference(self, num: int) -> int:
        s = str(num)
        t = s
        pos = 0
        while pos < len(s) and s[pos] == "9":
            pos += 1
        if pos < len(s):
            s = s.replace(s[pos], "9")
        t = t.replace(t[0], "0")
        return int(s) - int(t)

4.7.553 - 2025-08-20 18:54:48 +0300 MSK

Find the Array Concatenation Value
class Solution:
    def findTheArrayConcVal(self, nums: List[int]) -> int:
        def concat(num1: int, num2: int) -> int:
            res = 0
            count = 0
            for num in (num2, num1):
                while num > 0:
                    res += (num % 10) * (10 ** count)
                    count += 1
                    num //= 10
            return res
        left, right = 0, len(nums) - 1
        res = 0
        while left <= right:
            num1, num2 = nums[left], nums[right]
            if left == right:
                res += num1
            else:
                res += concat(num1, num2)
            left += 1
            right -= 1
        return res

4.7.554 - 2025-08-20 18:49:12 +0300 MSK

Take Gifts From the Richest Pile
class Solution:
    def pickGifts(self, gifts: List[int], k: int) -> int:
        for i in range(len(gifts)):
            gifts[i] = -gifts[i]
        heapq.heapify(gifts)
        for _ in range(k):
            val = int(math.sqrt(-heapq.heappop(gifts)))
            heapq.heappush(gifts, -val)
        return -sum(gifts)

4.7.555 - 2025-08-20 18:45:47 +0300 MSK

Separate the Digits in an Array
class Solution:
    def separateDigits(self, nums: List[int]) -> List[int]:
        res = []
        cur = []
        for num in nums:
            while num > 0:
                cur.append(num % 10)
                num //= 10
            cur.reverse()
            res.extend(cur)
            cur.clear()
        return res

4.7.556 - 2025-08-20 18:44:00 +0300 MSK

Count Distinct Numbers on Board
class Solution:
    def distinctIntegers(self, n: int) -> int:
        if n == 1:
            return 1
        return n - 1

4.7.557 - 2025-08-20 18:28:35 +0300 MSK

Alternating Digit Sum
class Solution:
    def alternateDigitSum(self, n: int) -> int:
        sign = 1
        count = 0
        res = 0
        while n > 0: 
            res += (n % 10) * sign
            sign *= -1
            count += 1
            n //= 10
        if count % 2 == 0:
            return -res
        return res

4.7.558 - 2025-08-20 18:24:20 +0300 MSK

Difference Between Element Sum and Digit Sum of an Array
class Solution:
    def differenceOfSum(self, nums: List[int]) -> int:
        el_sum, dig_sum = 0, 0
        for num in nums:
            el_sum += num
            while num > 0:
                dig_sum += num % 10
                num //= 10
        return abs(el_sum - dig_sum)

4.7.559 - 2025-08-20 18:23:07 +0300 MSK

Maximum Count of Positive Integer and Negative Integer
class Solution:
    def maximumCount(self, nums: List[int]) -> int:
        left, right = 0, len(nums) - 1
        start_neg, start_pos = -1, len(nums)
        while left <= right:
            mid = left + (right - left) // 2
            if nums[mid] >= 0:
                right = mid - 1
            else:
                start_neg = mid
                left = mid + 1
        left, right = start_neg + 1, len(nums) - 1
        while left <= right:
            mid = left + (right - left) // 2
            if nums[mid] > 0:
                start_pos = mid
                right = mid - 1
            else:
                left = mid + 1
        return max(start_neg + 1, len(nums) - start_pos)

4.7.560 - 2025-08-20 18:22:39 +0300 MSK

Maximum Count of Positive Integer and Negative Integer
class Solution:
    def maximumCount(self, nums: List[int]) -> int:
        left, right = 0, len(nums) - 1
        start_neg, start_pos = -1, len(nums)
        while left <= right:
            mid = left + (right - left) // 2
            if nums[mid] >= 0:
                right = mid - 1
            else:
                start_neg = mid
                left = mid + 1
        left, right = start_neg + 1, len(nums) - 1
        while left <= right:
            mid = left + (right - left) // 2
            if nums[mid] > 0:
                start_pos = mid
                right = mid - 1
            else:
                left = mid + 1
        print(start_neg, start_pos)
        return max(start_neg + 1, len(nums) - start_pos)

4.7.561 - 2025-08-20 17:57:07 +0300 MSK

Categorize Box According to Criteria
class Solution:
    def categorizeBox(self, length: int, width: int, height: int, mass: int) -> str:
        is_bulky = (
            max(length, width, height) >= 10 ** 4
            or length * width * height >= 10 ** 9
        )
        is_heavy = mass >= 100
        if is_bulky and is_heavy:
            return "Both"
        if is_bulky and not is_heavy:
            return "Bulky"
        if is_heavy and not is_bulky:
            return "Heavy"
        return "Neither"
        

4.7.562 - 2025-08-20 17:48:38 +0300 MSK

Count the Digits That Divide a Number
class Solution:
    def countDigits(self, num: int) -> int:
        cur = num
        res = 0
        while cur > 0:
            dig = cur % 10
            if num % dig == 0:
                res += 1
            cur //= 10
        return res

4.7.563 - 2025-08-20 17:47:52 +0300 MSK

Shortest Distance to Target String in a Circular Array
class Solution:
    def closestTarget(self, words: List[str], target: str, startIndex: int) -> int:
        n = len(words)
        for i in range(n):
            left, right = (startIndex - i + n) % n, (startIndex + i) % n
            if words[left] == target or words[right] == target:
                return i
        return -1

4.7.564 - 2025-08-20 17:43:24 +0300 MSK

Maximum Enemy Forts That Can Be Captured
class Solution:
    def captureForts(self, forts: List[int]) -> int:
        start = None
        max_capt = 0
        for i, fort in enumerate(forts):
            if fort == 0:
                continue
            if start is None:
                start = i
                continue
            start_val = forts[start]
            if (start_val == 1 and fort == -1) or (start_val == -1 and fort == 1):
                max_capt = max(max_capt, i - start - 1)
            start = i
        return max_capt

4.7.565 - 2025-08-20 17:23:29 +0300 MSK

Count Pairs Of Similar Strings
class Solution:
    def similarPairs(self, words: List[str]) -> int:
        freqs = defaultdict(int)
        res = 0
        for word in words:
            freq = 0
            for char in word:
                freq |= 1 << (ord(char) - 97)
            res += freqs[freq]
            freqs[freq] += 1
        return res

4.7.566 - 2025-08-20 17:18:47 +0300 MSK

Count Pairs Of Similar Strings
class Solution:
    def similarPairs(self, words: List[str]) -> int:
        freqs = [False] * 26
        freqs2 = defaultdict(int)
        for word in words:
            for char in word:
                freqs[ord(char) - 97] = True
            freqs2[tuple(freqs)] += 1
            for i in range(26):
                freqs[i] = False
        res = 0
        for freq in freqs2.values():
            for i in range(freq):
                res += (freq - i - 1)
        return res

4.7.567 - 2025-08-20 15:09:02 +0300 MSK

Delete Greatest Value in Each Row
class Solution:
    def deleteGreatestValue(self, grid: List[List[int]]) -> int:
        for row in grid:
            row.sort()
        res = 0
        for _ in range(len(grid[0])):
            cur_sum = 0
            for row in grid:
                cur_sum = max(cur_sum, row.pop())
            res += cur_sum
        return res

4.7.568 - 2025-08-20 13:48:16 +0300 MSK

Maximum Value of a String in an Array
class Solution:
    def maximumValue(self, strs: List[str]) -> int:
        max_val = 0
        for s in strs:
            if s.isdigit():
                val = int(s)
            else:
                val = len(s)
            if val > max_val:
                max_val = val
        return max_val

4.7.569 - 2025-08-20 13:45:38 +0300 MSK

Circular Sentence
class Solution:
    def isCircularSentence(self, sentence: str) -> bool:
        if sentence[0] != sentence[-1]:
            return False
        for i, char in enumerate(sentence):
            if char == " " and sentence[i - 1] != sentence[i + 1]:
                return False
        return True
            

4.7.570 - 2025-08-20 13:41:05 +0300 MSK

Minimum Cuts to Divide a Circle
class Solution:
    def numberOfCuts(self, n: int) -> int:
        if n == 1:
            return 0
        if n % 2 == 0:
            return n // 2
        return n

4.7.571 - 2025-08-20 13:36:58 +0300 MSK

Number of Unequal Triplets in Array
class Solution:
    def unequalTriplets(self, nums: List[int]) -> int:
        freqs = [0] * 1001
        for num in nums:
            freqs[num] += 1
        res = 0
        left = 0
        right = len(nums)
        for freq in freqs:
            if freq == 0:
                continue
            right -= freq
            res += left * freq * right
            left += freq
        return res

4.7.572 - 2025-08-20 13:29:30 +0300 MSK

Number of Unequal Triplets in Array
class Solution:
    def unequalTriplets(self, nums: List[int]) -> int:
        freqs = [0] * 1001
        for num in nums:
            freqs[num] += 1
        res = 0
        left = 0
        right = len(nums)
        for freq in freqs:
            if freq == 0:
                continue
            right -= freq
            res += left * freq * right
            left += freq
        return res

4.7.573 - 2025-08-20 13:16:55 +0300 MSK

Convert the Temperature
class Solution:
    def convertTemperature(self, celsius: float) -> List[float]:
        return (celsius + 273.15, (celsius * 1.80 + 32.00))

4.7.574 - 2025-08-20 13:13:48 +0300 MSK

Number of Distinct Averages
class Solution:
    def distinctAverages(self, nums: List[int]) -> int:
        nums.sort()
        freqs = [False] * 201
        n = len(nums)
        res = 0
        for i in range(n // 2 + 1):
            freq = nums[i] + nums[n - i - 1]
            if not freqs[freq]:
                res += 1
                freqs[freq] = True
        return res

4.7.575 - 2025-08-20 13:06:17 +0300 MSK

Apply Operations to an Array
class Solution:
    def applyOperations(self, nums: List[int]) -> List[int]:
        n = len(nums)
        for i in range(1, n):
            cur, prev = nums[i], nums[i - 1]
            if prev != 0 and cur == prev:
                nums[i], nums[i - 1] = 0, prev * 2
        left, right = 0, 1
        while left < n and right < n:
            num1, num2 = nums[left], nums[right]
            if num1 != 0:
                left += 1
            elif num2 == 0:
                right += 1
            elif left >= right:
                right += 1
            else:
                nums[left], nums[right] = num2, 0
                left += 1
                right += 1
        return nums

4.7.576 - 2025-08-20 12:43:09 +0300 MSK

Average Value of Even Numbers That Are Divisible by Three
class Solution:
    def averageValue(self, nums: List[int]) -> int:
        res = 0
        cnt = 0
        for num in nums:
            if num % 2 == 0 and num % 3 == 0:
                cnt += 1
                res += num
        if cnt == 0:
            return 0
        return res // cnt

4.7.577 - 2025-08-20 12:38:03 +0300 MSK

Odd String Difference
class Solution:
    def oddString(self, words: List[str]) -> str:
        freq1, freq2, cur = None, None, []
        freq1_word, freq2_word = None, None
        freq1_cnt, freq2_cnt = 0, 0
        for word in words:
            for i in range(1, len(word)):
                cur.append(ord(word[i]) - ord(word[i - 1]))
            if freq1 is None:
                freq1, freq1_word, freq1_cnt = cur, word, 1
                cur = []
            elif cur == freq1:
                freq1_cnt += 1
            elif freq2 is None:
                freq2, freq2_word, freq2_cnt = cur, word, 1
                cur = []
            elif cur == freq2:
                freq2_cnt += 1
            cur.clear()
            if min(freq1_cnt, freq2_cnt) == 1 and max(freq1_cnt, freq2_cnt) > 1:
                if freq1_cnt == 1:
                    return freq1_word
                return freq2_word
        raise Exception

4.7.578 - 2025-08-20 12:08:13 +0300 MSK

Count Square Submatrices with All Ones
class Solution:
    def countSquares(self, matrix: List[List[int]]) -> int:
        rows, cols = len(matrix), len(matrix[0])
        dp = [[0] * (cols + 1) for _ in range(rows + 1)]
        res = 0
        for row in range(rows):
            for col in range(cols):
                val = matrix[row][col]
                if val == 0:
                    continue
                dp_row, dp_col = row + 1, col + 1
                dp_val = min(
                    dp[dp_row - 1][dp_col], 
                    dp[dp_row][dp_col - 1], 
                    dp[dp_row - 1][dp_col - 1]
                ) + 1
                dp[dp_row][dp_col] = dp_val
                res += dp_val
        return res

4.7.579 - 2025-08-19 20:23:46 +0300 MSK

Determine if Two Events Have Conflict
class Solution:
    def haveConflict(self, event1: List[str], event2: List[str]) -> bool:
        def parse(clock: str) -> int:
            hh, mm = clock[:2], clock[2:]
            return hh * 60 + mm
        start1, end1 = map(parse, event1)
        start2, end2 = map(parse, event2)
        if start1 == start2:
            return True
        if start1 > start2:
            return start1 <= end2
        return end1 >= start2

4.7.580 - 2025-08-19 20:13:25 +0300 MSK

Number of Valid Clock Times
class Solution:
    def countTime(self, time: str) -> int:
        hh, mm = time.split(':')
        count_possible_hours = 1
        if (hh == '??'):
            count_possible_hours = 24
        elif (hh[0] == '?' and int(hh[1]) >= 4):
            count_possible_hours = 2
        elif (hh[0] == '?' and int(hh[1]) <= 4):
            count_possible_hours = 3
        elif (int(hh[0]) <= 1 and hh[1] == '?'):
            count_possible_hours = 10
        elif (int(hh[0]) == 2 and hh[1] == '?'):
            count_possible_hours = 4
        count_possible_minutes = 1
        if (mm == '??'):
            count_possible_minutes = 60
        elif (mm[0] == '?'):
            count_possible_minutes = 6
        elif (mm[1] == '?'):
            count_possible_minutes = 10
        return count_possible_hours * count_possible_minutes

4.7.581 - 2025-08-19 20:11:33 +0300 MSK

The Employee That Worked on the Longest Task
class Solution:
    def hardestWorker(self, n: int, logs: List[List[int]]) -> int:
        max_id, max_dur = logs[0]
        for i, (emp_id, leave) in enumerate(logs[1:], 1):
            dur = leave - logs[i - 1][1]
            if dur > max_dur:
                max_id, max_dur = emp_id, dur
            elif dur == max_dur and emp_id < max_id:
                max_id = emp_id
        return max_id

4.7.582 - 2025-08-19 20:00:15 +0300 MSK

Number of Common Factors
class Solution:
    def commonFactors(self, a: int, b: int) -> int:
        res = 0
        for i in range(1, min(a, b) + 1):
            if a % i == 0 and b % i == 0:
                res += 1
        return res
        

4.7.583 - 2025-08-19 19:47:47 +0300 MSK

Remove Letter To Equalize Frequency
class Solution:
    def equalFrequency(self, word: str) -> bool:
        freqs1, freqs2 = defaultdict(int), defaultdict(int)
        for char in word:
            freqs1[char] += 1
        for freq in freqs1.values():
            freqs2[freq] += 1
        if len(freqs2) == 1:
            return next(iter(freqs2.keys())) == 1 or next(iter(freqs2.values())) == 1
        if len(freqs2) == 2:
            f1, f2 = min(freqs2.keys()), max(freqs2.keys())
            return (
                f1 + 1 == f2 and freqs2[f2] == 1
            ) or (
                f1 == 1 and freqs2[f1] == 1
            )
        return False

4.7.584 - 2025-08-19 16:10:29 +0300 MSK

Sort the People
class Solution:
    def sortPeople(self, names: List[str], heights: List[int]) -> List[str]:
        for i in range(len(names)):
            names[i] = (heights[i], names[i])
        names.sort(reverse=True)
        for i in range(len(names)):
            names[i] = names[i][1]
        return names

4.7.585 - 2025-08-19 15:27:24 +0300 MSK

Smallest Even Multiple
class Solution:
    def smallestEvenMultiple(self, n: int) -> int:
        if n % 2 == 0:
            return n
        return n * 2

4.7.586 - 2025-08-19 15:24:40 +0300 MSK

Count Days Spent Together
class Solution:
    def countDaysTogether(self, arriveAlice: str, leaveAlice: str, arriveBob: str, leaveBob: str) -> int:
        months = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
        def count(date: str) -> int:
            month = int(date[:2])
            days = int(date[3:])
            return sum(months[:month - 1]) + days
        return max(0, count(min(leaveAlice, leaveBob)) - count(max(arriveAlice, arriveBob)) + 1)
    

4.7.587 - 2025-08-19 15:04:21 +0300 MSK

Most Frequent Even Element
class Solution:
    def mostFrequentEven(self, nums: List[int]) -> int:
        nums.sort()
        max_freq, max_freq_num = 0, -1
        cur_freq = 0
        prev = -1
        for num in nums:
            if num % 2 != 0:
                continue
            if num == prev:
                cur_freq += 1
            else:
                cur_freq, prev = 1, num
            if cur_freq > max_freq:
                max_freq, max_freq_num = cur_freq, num
        return max_freq_num

4.7.588 - 2025-08-19 14:58:59 +0300 MSK

Check Distances Between Same Letters
class Solution:
    def checkDistances(self, s: str, distance: List[int]) -> bool:
        for i, char in enumerate(s):
            idx = ord(char) - 97
            dist = distance[idx]
            if dist == -1:
                continue
            nxt = i + dist + 1
            if nxt >= len(s) or s[nxt] != char:
                return False
            distance[idx] = -1
        return True

4.7.589 - 2025-08-19 14:42:34 +0300 MSK

Find Subarrays With Equal Sum
class Solution:
    def findSubarrays(self, nums: List[int]) -> bool:
        enc = set()
        for i in range(1, len(nums)):
            val = nums[i] + nums[i - 1]
            if val in enc:
                return True
            enc.add(val)
        return False

4.7.590 - 2025-08-19 14:37:35 +0300 MSK

Longest Subsequence With Limited Sum
class Solution:
    def answerQueries(self, nums: List[int], queries: List[int]) -> List[int]:
        nums.sort()
        for i in range(1, len(nums)):
            nums[i] += nums[i - 1]
        for i in range(len(queries)):
            target = queries[i]
            count = 0
            for num in nums:
                if num <= target:
                    count += 1
                else:
                    break
            queries[i] = count
        return queries

4.7.591 - 2025-08-19 14:29:00 +0300 MSK

Minimum Hours of Training to Win a Competition
class Solution:
    def minNumberOfHours(self, initialEnergy: int, initialExperience: int, energy: List[int], experience: List[int]) -> int:
        res = max(0, sum(energy) - initialEnergy + 1)
        for exp in experience:
            if initialExperience <= exp:
                diff = exp - initialExperience + 1
                res += diff
                initialExperience += diff
            initialExperience += exp
        return res

4.7.592 - 2025-08-19 14:04:31 +0300 MSK

Minimum Recolors to Get K Consecutive Black Blocks
class Solution:
    def minimumRecolors(self, blocks: str, k: int) -> int:
        left = 0
        num_whites = 0
        num_recolors = math.inf
        for right in range(len(blocks)):
            if blocks[right] == "W":
                num_whites += 1
            if right - left + 1 == k:
                num_recolors = min(num_recolors, num_whites)
                if blocks[left] == "W":
                    num_whites -= 1
                left += 1
        return num_recolors

4.7.593 - 2025-08-19 13:54:21 +0300 MSK

Number of Arithmetic Triplets
class Solution:
    def arithmeticTriplets(self, nums: List[int], diff: int) -> int:
        freqs = [[] for _ in range(201)]
        for i, num in enumerate(nums):
            freqs[num].append(i)
        length = len(nums)
        res = 0
        for i in range(length):
            num1 = nums[i]
            for j in range(i + 1, length):
                num2 = nums[j]
                if num2 - num1 != diff:
                    continue
                num3 = num2 + diff 
                if num3 > 200:
                    continue
                for k in freqs[num3]:
                    if k > j:
                        res += 1
                        break
        return res

4.7.594 - 2025-08-19 13:40:19 +0300 MSK

Merge Similar Items
class Solution:
    def mergeSimilarItems(self, items1: List[List[int]], items2: List[List[int]]) -> List[List[int]]:
        freqs = [0] * 1001
        for val, weight in itertools.chain(items1, items2):
            freqs[val] += weight
        res = [(num, weight) for num, weight in enumerate(freqs) if weight != 0]
        return res

4.7.595 - 2025-08-19 13:37:47 +0300 MSK

Merge Similar Items
class Solution:
    def mergeSimilarItems(self, items1: List[List[int]], items2: List[List[int]]) -> List[List[int]]:
        freqs = [(i, 0) for i in range(1001)]
        for val, weight in itertools.chain(items1, items2):
            _, cur_weight = freqs[val]
            freqs[val] = (val, weight + cur_weight)
        freqs.sort(reverse=True, key=lambda val: val[1])
        while freqs and freqs[-1][1] == 0:
            freqs.pop()
        freqs.sort()
        return freqs

4.7.596 - 2025-08-19 13:11:40 +0300 MSK

Make Array Zero by Subtracting Equal Amounts
class Solution:
    def minimumOperations(self, nums: List[int]) -> int:
        nums.sort(reverse=True)
        res = 0
        while nums:
            num = nums.pop()
            if num == 0:
                continue
            for i in range(len(nums)):
                nums[i] = max(0, nums[i] - num)
            res += 1
        return res

4.7.597 - 2025-08-19 11:34:12 +0300 MSK

Number of Unique Subjects Taught by Each Teacher
SELECT
    teacher_id,
    COUNT(DISTINCT subject_id) AS "cnt"
FROM
    Teacher
GROUP BY
    teacher_id

4.7.598 - 2025-08-19 09:58:54 +0300 MSK

First Letter to Appear Twice
class Solution:
    def repeatedCharacter(self, s: str) -> str:
        freqs = [0] * 26
        for char in s:
            idx = ord(char) - 97
            freq = freqs[idx] + 1
            if freq == 2:
                return char
            freqs[idx] = freq
        raise Exception

4.7.599 - 2025-08-19 08:52:54 +0300 MSK

Best Poker Hand
class Solution:
    def bestHand(self, ranks: List[int], suits: List[str]) -> str:
        ranks.sort()
        suits.sort()
        same_suit = 1
        cur_same_suit = 1
        same_rank = 1
        cur_same_rank = 1
        for i in range(1, len(ranks)):
            if ranks[i] == ranks[i - 1]:
                cur_same_rank += 1
                same_rank = max(same_rank, cur_same_rank)
            else:
                cur_same_rank = 1
            if suits[i] == suits[i - 1]:
                cur_same_suit += 1
                same_suit = max(same_suit, cur_same_suit)
            else:
                cur_same_suit = 1
        print(same_suit, same_rank)
        if same_suit == 5:
            return "Flush"
        if same_rank >= 3:
            return "Three of a Kind"
        if same_rank >= 2:
            return "Pair"
        return "High Card"

4.7.600 - 2025-08-19 08:18:09 +0300 MSK

Number of Zero-Filled Subarrays
class Solution:
    def zeroFilledSubarray(self, nums: List[int]) -> int:
        res = 0
        cur = 0
        for num in nums:
            if num == 0:
                cur += 1
                res += cur
            elif cur != 0:
                cur = 0
        return res

4.7.601 - 2025-08-18 21:10:17 +0300 MSK

Maximum Number of Pairs in Array
class Solution:
    def numberOfPairs(self, nums: List[int]) -> List[int]:
        cnt_pair, cnt_rest = 0, 0
        nums.sort()
        length = len(nums)
        i = 0
        while i < length:
            cur = nums[i]
            nxt = nums[i + 1] if i + 1 < length else -1
            if nxt == cur:
                cnt_pair += 1
                i += 2
            else:
                cnt_rest += 1
                i += 1
        return cnt_pair, cnt_rest

4.7.602 - 2025-08-18 21:06:45 +0300 MSK

Minimum Amount of Time to Fill Cups
class Solution:
    def fillCups(self, amount: List[int]) -> int:
        res = 0
        for i in range(len(amount)):
            amount[i] = -amount[i]
        heapq.heapify(amount)
        while len(amount) > 2:
            num1, num2 = heapq.heappop(amount), heapq.heappop(amount)
            if num1 < 0 or num2 < 0:
                res += 1
            if num1 < 0:
                num1 += 1
                heapq.heappush(amount, num1)
            if num2 < 0:
                num2 += 1
                heapq.heappush(amount, num2)
        if len(amount) == 1:
            return res - amount[0]
        num1, num2 = amount
        res += min(-num1, -num2) + abs(num1 - num2)
        return res

4.7.603 - 2025-08-18 20:23:18 +0300 MSK

Decode the Message
class Solution:
    def decodeMessage(self, key: str, message: str) -> str:
        subst = [-1] * 26
        res = []
        count = 0
        for char in key:
            if char == " ":
                continue
            idx = ord(char) - 97
            if subst[idx] == -1:
                subst[idx] = count
                count += 1
        for char in message:
            if char == " ":
                val = char
            else:
                val = chr(subst[ord(char) - 97] + 97)
            res.append(val)
        return "".join(res)

4.7.604 - 2025-08-18 20:18:16 +0300 MSK

Check if Matrix Is X-Matrix
class Solution:
    def checkXMatrix(self, grid: List[List[int]]) -> bool:
        length = len(grid)
        for row in range(length):
            for col in range(length):
                is_diag = row == col or length - row - 1 == col
                val = grid[row][col]
                if (is_diag and val == 0) or (not is_diag and val != 0):
                    return False
        return True

4.7.605 - 2025-08-18 20:07:07 +0300 MSK

Count Asterisks
class Solution:
    def countAsterisks(self, s: str) -> int:
        start = False
        res = 0
        for char in s:
            if char == "|":
                start = not start
            elif char == "*" and not start:
                res += 1
        return res

4.7.606 - 2025-08-18 20:04:04 +0300 MSK

Greatest English Letter in Upper and Lower Case
class Solution:
    def greatestLetter(self, s: str) -> str:
        freqs = [(False, False)] * 26
        for char in reversed(s):
            if char.islower():
                idx = ord(char) - 97
                is_lower = True
            else:
                idx = ord(char) - 65
                is_lower = False
            enc_lower, enc_upper = freqs[idx]
            new_val = (enc_lower or is_lower, enc_upper or not is_lower)
            if new_val != (enc_lower, enc_upper):
                freqs[idx] = new_val
        for i in reversed(range(len(freqs))):
            if all(freqs[i]):
                return chr(i + 65)
        return ""

4.7.607 - 2025-08-18 19:52:53 +0300 MSK

Calculate Amount Paid in Taxes
class Solution:
    def calculateTax(self, brackets: List[List[int]], income: int) -> float:
        tax = prev = 0
        for upper, perc in brackets:
            if income >= upper:
                tax += (upper - prev) * perc / 100
                prev = upper
            else:
                tax += (income - prev) * perc / 100
                return tax
        return tax

4.7.608 - 2025-08-18 19:41:27 +0300 MSK

Strong Password Checker II
class Solution:
    def strongPasswordCheckerII(self, password: str) -> bool:
        if len(password) < 8:
            return False
        has_lower, has_upper, has_digit, has_spec = False, False, False, False
        prev = None
        spec = "!@#$%^&*()-+"
        for char in password:
            if char.islower():
                has_lower = True
            elif char.isupper():
                has_upper = True
            elif char.isdigit():
                has_digit = True
            elif char in spec:
                has_spec = True
            if prev is not None and char == prev:
                return False
            prev = char
        return has_lower and has_upper and has_digit and has_spec

4.7.609 - 2025-08-18 19:36:10 +0300 MSK

Min Max Game
class Solution:
    def minMaxGame(self, nums: List[int]) -> int:
        while len(nums) > 1:
            length = len(nums) // 2
            for i in range(length):
                if i % 2 == 0:
                    nums[i] = min(nums[i * 2], nums[i * 2 + 1])
                else:
                    nums[i] = max(nums[i * 2], nums[i * 2 + 1])
            while len(nums) > length:
                nums.pop()
        return nums[0]

4.7.610 - 2025-08-18 19:26:10 +0300 MSK

Rearrange Characters to Make Target String
class Solution:
    def rearrangeCharacters(self, s: str, target: str) -> int:
        freqs1, freqs2 = [0] * 26, [0] * 26
        for char in s:
            freqs1[ord(char) - 97] += 1
        for char in target:
            freqs2[ord(char) - 97] += 1
        count = math.inf
        for i in range(26):
            freq1, freq2 = freqs1[i], freqs2[i]
            if freq2 == 0:
                continue
            cur_count = freq1 // freq2
            if cur_count == 0:
                return 0
            if cur_count < count:
                count = cur_count
        return count

4.7.611 - 2025-08-18 19:21:41 +0300 MSK

Check if Number Has Equal Digit Count and Digit Value
class Solution:
    def digitCount(self, num: str) -> bool:
        freqs = [0] * 10
        for char in num:
            freqs[int(char)] += 1
        for i, char in enumerate(num):
            if freqs[i] != int(char):
                return False
        return True

4.7.612 - 2025-08-18 19:16:20 +0300 MSK

Percentage of Letter in String
class Solution:
    def percentageLetter(self, s: str, letter: str) -> int:
        count = 0
        for char in s:
            if char == letter:
                count += 1
        return (count * 100) // len(s)

4.7.613 - 2025-08-18 19:11:33 +0300 MSK

Find Resultant Array After Removing Anagrams
class Solution:
    def removeAnagrams(self, words: List[str]) -> List[str]:
        freqs1, freqs2 = bytearray(26), bytearray(26)
        res = []
        for i, word in enumerate(words):
            for i in range(26):
                freqs2[i] = 0
            for char in word:
                freqs2[ord(char) - 97] += 1
            if i != 0 and freqs1 == freqs2:
                continue
            freqs1, freqs2 = freqs2, freqs1
            res.append(word)
        return res

4.7.614 - 2025-08-18 19:02:01 +0300 MSK

Find Resultant Array After Removing Anagrams
class Solution:
    def removeAnagrams(self, words: List[str]) -> List[str]:
        prev = ()
        res = []
        for word in words:
            word_sorted = sorted(word)
            if prev != word_sorted:
                res.append(word)
                prev = word_sorted
        return res

4.7.615 - 2025-08-18 18:43:22 +0300 MSK

Find the K-Beauty of a Number
class Solution:
    def divisorSubstrings(self, num: int, k: int) -> int:
        digits = []
        cur_num = num
        while cur_num > 0:
            digits.append(cur_num % 10)
            cur_num //= 10
        digits.reverse()
        length = len(digits)
        if length < k:
            return 0
        cur_sum = 0
        res = 0
        for i in range(k):
            cur_sum += digits[i] * (10 ** (k - i - 1))
        if num % cur_sum == 0:
            res += 1 
        i = k
        while i < length:
            cur_sum -= digits[i - k] * (10 ** (k - 1))
            cur_sum = cur_sum * 10 + digits[i]
            if cur_sum != 0 and num % cur_sum == 0:
                res += 1
            i += 1
        return res

4.7.616 - 2025-08-18 15:12:00 +0300 MSK

Remove Digit From Number to Maximize Result
class Solution:
    def removeDigit(self, number: str, digit: str) -> str:
        last_index = 0
        digit_int = int(digit)
        for i in range(1, len(number)):
            cur, prev = int(number[i]), int(number[i - 1])
            if prev == digit_int:
                if cur > prev:
                    return "".join((number[:i-1], number[i:]))
                else:
                    last_index = i - 1
        if number[-1] == digit:
            last_index = len(number) - 1
        return "".join((number[:last_index], number[last_index + 1:]))

4.7.617 - 2025-08-18 15:03:06 +0300 MSK

Count Prefixes of a Given String
class Solution:
    def countPrefixes(self, words: List[str], s: str) -> int:
        res = 0
        for word in words:
            if s.startswith(word):
                res += 1
        return res

4.7.618 - 2025-08-18 14:55:52 +0300 MSK

Intersection of Multiple Arrays
class Solution:
    def intersection(self, nums: List[List[int]]) -> List[int]:
        length = len(nums)
        freqs = [[False] * length for _ in range(1002)] 
        for i, arr in enumerate(nums):
            for num in arr:
                if not freqs[num][i]:
                    freqs[num][i] = True
        nums.clear()
        for num, freq in enumerate(freqs):
            if all(freq):
                nums.append(num)
        return nums

4.7.619 - 2025-08-18 14:48:14 +0300 MSK

Intersection of Multiple Arrays
class Solution:
    def intersection(self, nums: List[List[int]]) -> List[int]:
        enc = set(nums[0])
        for arr in nums[1:]:
            enc.intersection_update(arr)
        return sorted(enc)

4.7.620 - 2025-08-18 14:43:36 +0300 MSK

Calculate Digit Sum of a String
class Solution:
    def digitSum(self, s: str, k: int) -> str:
        res, cur, group = list(map(int, s)), [], []
        i = 0
        def add_digits(num: int) -> None:
            if num == 0:
                cur.append(0)
                return
            while num > 0:
                group.append(num % 10)
                num //= 10
            group.reverse()
            cur.extend(group)
            group.clear()
        while len(res) > k:
            while i < len(res):
                add_digits(sum(res[i:i + k]))
                i += k
            res, cur = cur, res
            cur.clear()
            i = 0
        return "".join(map(str, res))

4.7.621 - 2025-08-18 13:44:46 +0300 MSK

Find Closest Number to Zero
class Solution:
    def findClosestNumber(self, nums: List[int]) -> int:
        max_diff, max_num = math.inf, 0
        for num in nums:
            diff = abs(num)
            if diff < max_diff or (diff == max_diff and num > max_num):
                max_diff, max_num = diff, num
        return max_num

4.7.622 - 2025-08-18 13:40:40 +0300 MSK

Largest Number After Digit Swaps by Parity
class Solution:
    def largestInteger(self, num: int) -> int:
        odd, even, digits = [], [], []
        while num > 0:
            dig = num % 10
            if dig % 2 == 0:
                heapq.heappush(even, dig)
                digits.append(True)
            else:
                heapq.heappush(odd, dig)
                digits.append(False)
            num //= 10
        res = 0
        for i in range(len(digits)):
            if digits[i]:
                target = even
            else:
                target = odd
            res += heapq.heappop(target) * (10 ** i)
        return res
        

4.7.623 - 2025-08-18 13:34:09 +0300 MSK

Largest Number After Digit Swaps by Parity
class Solution:
    def largestInteger(self, num: int) -> int:
        odd, even, res = [], [], []
        while num > 0:
            dig = num % 10
            if dig % 2 == 0:
                even.append(dig)
                res.append(True)
            else:
                odd.append(dig)
                res.append(False)
            num //= 10
        odd.sort(reverse=True)
        even.sort(reverse=True)
        res.reverse()
        length = len(res)
        num = 0
        for i in reversed(range(length)):
            if res[i]:
                num += even.pop() * (10 ** (length - i - 1))
            else:
                num += odd.pop() * (10 ** (length - i - 1))
        return num
        

4.7.624 - 2025-08-18 10:06:49 +0300 MSK

24 Game
from typing import List
import math

class Solution:
    def judgePoint24(self, cards: List[int]) -> bool:
        EPS = 1e-6

        def backtrack(nums: List[float]) -> bool:
            if len(nums) == 1:
                return abs(nums[0] - 24.0) < EPS

            n = len(nums)
            for i in range(n):
                for j in range(i + 1, n):
                    rest = [nums[k] for k in range(n) if k != i and k != j]
                    a, b = nums[i], nums[j]

                    candidates = []
                    candidates.append(a + b)
                    candidates.append(a * b)
                    candidates.append(a - b)
                    candidates.append(b - a)

                    if abs(b) > EPS:
                        candidates.append(a / b)
                    if abs(a) > EPS:
                        candidates.append(b / a)

                    for x in candidates:
                        if backtrack(rest + [x]):
                            return True
            return False

        return backtrack([float(x) for x in cards])

4.7.625 - 2025-08-17 20:02:56 +0300 MSK

Minimum Number of Operations to Convert Time
class Solution:
    def convertTime(self, current: str, correct: str) -> int:
        current_time = 60 * int(current[0:2]) + int(current[3:5])
        target_time = 60 * int(correct[0:2]) + int(correct[3:5])
        diff = target_time - current_time
        count = 0
        for i in (60, 15, 5, 1):
            count += diff // i
            diff %= i
        return count

4.7.626 - 2025-08-17 19:56:52 +0300 MSK

Divide Array Into Equal Pairs
class Solution:
    def divideArray(self, nums: List[int]) -> bool:
        nums.sort()
        prev = nums[0]
        count = 1
        for num in nums[1:]:
            if num == prev:
                count += 1
            elif count % 2 != 0:
                return False
            else:
                count = 1
                prev = num
        return count % 2 == 0

4.7.627 - 2025-08-17 19:54:48 +0300 MSK

Divide Array Into Equal Pairs
class Solution:
    def divideArray(self, nums: List[int]) -> bool:
        freqs = defaultdict(int)
        for num in nums:
            freqs[num] += 1
        for freq in freqs.values():
            if freq % 2 != 0:
                return False
        return True

4.7.628 - 2025-08-17 19:44:55 +0300 MSK

Find All K-Distant Indices in an Array
class Solution:
    def findKDistantIndices(
        self, nums: List[int], key: int, k: int
    ) -> List[int]:
        res = []
        right = 0 
        length = len(nums)
        for j in range(length):
            if nums[j] != key:
                continue
            left = max(right, j - k)
            right = min(length - 1, j + k) + 1
            res.extend(range(left, right))
        return res

4.7.629 - 2025-08-17 19:21:20 +0300 MSK

Cells in a Range on an Excel Sheet
class Solution:
    def cellsInRange(self, s: str) -> List[str]:
        cell1, cell2 = s.split(":")
        row1, col1 = cell1[0], int(cell1[1:])
        row2, col2 = cell2[0], int(cell2[1:])
        res = []
        while row1 <= row2:
            for col in range(col1, col2 + 1):
                res.append(f"{row1}{col}")
            row1 = chr(ord(row1) + 1)
        return res

4.7.630 - 2025-08-17 19:15:00 +0300 MSK

Most Frequent Number Following Key In an Array
class Solution:
    def mostFrequent(self, nums: List[int], key: int) -> int:
        freqs = [0] * 1001
        prev = nums[0]
        max_freq, max_freq_num = 0, 0
        res = 0
        for num in nums[1:]:
            if prev == key:
                freq = freqs[num] + 1 
                freqs[num] = freq
                if freq > max_freq:
                    max_freq, max_freq_num = freq, num
            prev = num
        return max_freq_num

4.7.631 - 2025-08-17 19:10:32 +0300 MSK

Counting Words With a Given Prefix
class Solution:
    def prefixCount(self, words: List[str], pref: str) -> int:
        res = 0
        for word in words:
            if word.startswith(pref):
                res += 1
        return res

4.7.632 - 2025-08-17 19:08:02 +0300 MSK

Count Integers With Even Digit Sum
class Solution:
    def countEven(self, num: int) -> int:
        dig_sum = 0
        val = num
        while val > 0:
            dig_sum += val % 10
            val //= 10
        if dig_sum % 2 == 0:
            return num // 2
        return (num - 1) // 2

4.7.633 - 2025-08-17 18:51:40 +0300 MSK

Count Equal and Divisible Pairs in an Array
class Solution:
    def countPairs(self, nums: List[int], k: int) -> int:
        freqs = tuple([] for i in range(101))
        res = 0
        for j, num in enumerate(nums):
            for i in freqs[num]:
                if (i * j) % k == 0:
                    res += 1
            freqs[num].append(j)
        return res

4.7.634 - 2025-08-17 18:46:10 +0300 MSK

Count Equal and Divisible Pairs in an Array
class Solution:
    def countPairs(self, nums: List[int], k: int) -> int:
        length = len(nums)
        res = 0
        for i in range(length):
            num1 = nums[i]
            for j in range(i + 1, length):
                if (i * j) % k == 0 and num1 == nums[j]:
                    res += 1
        return res

4.7.635 - 2025-08-17 18:44:14 +0300 MSK

Count Equal and Divisible Pairs in an Array
class Solution:
    def countPairs(self, nums: List[int], k: int) -> int:
        length = len(nums)
        res = 0
        for i in range(length):
            num1 = nums[i]
            for j in range(i + 1, length):
                if num1 == nums[j] and (i * j) % k == 0:
                    res += 1
        return res

4.7.636 - 2025-08-17 18:40:15 +0300 MSK

Count Operations to Obtain Zero
class Solution:
    def countOperations(self, num1: int, num2: int) -> int:
        count = 0
        while num1 > 0 and num2 > 0:
            if num1 >= num2:
                count += num1 // num2
                num1 %= num2
            else:
                count += num2 // num1
                num2 %= num1
        return count

4.7.637 - 2025-08-17 18:38:02 +0300 MSK

Count Operations to Obtain Zero
class Solution:
    def countOperations(self, num1: int, num2: int) -> int:
        count = 0
        while num1 > 0 and num2 > 0:
            if num1 >= num2:
                num1 -= num2
            else:
                num2 -= num1
            count += 1
        return count

4.7.638 - 2025-08-17 18:25:12 +0300 MSK

Sort Even and Odd Indices Independently
class Solution:
    def sortEvenOdd(self, nums: List[int]) -> List[int]:
        odd, even = [], []
        for i, num in enumerate(nums):
            if i % 2 == 0:
                heapq.heappush(even, num)
            else:
                heapq.heappush(odd, -num)
        for i in range(len(nums)):
            if i % 2 == 0:
                nums[i] = heapq.heappop(even)
            else:
                nums[i] = -heapq.heappop(odd)
        return nums

4.7.639 - 2025-08-17 18:16:02 +0300 MSK

Minimum Sum of Four Digit Number After Splitting Digits
class Solution:
    def minimumSum(self, num: int) -> int:
        digits = []
        while num > 0:
            digits.append(num % 10)
            num //= 10
        digits.sort()
        return digits[0] * 10 + digits[1] * 10 + digits[2] + digits[3]

4.7.640 - 2025-08-17 18:06:00 +0300 MSK

Keep Multiplying Found Values by Two
class Solution:
    def findFinalValue(self, nums: List[int], original: int) -> int:
        nums.sort()
        length = len(nums)
        left, right = 0, length - 1
        while left <= right:
            i = left + (right - left) // 2
            val = nums[i]
            if val > original:
                right = i - 1
            elif val == original:
                original *= 2
                left = i + 1
                right = length - 1
            else:
                left = i + 1
        return original

4.7.641 - 2025-08-17 17:56:42 +0300 MSK

Keep Multiplying Found Values by Two
class Solution:
    def findFinalValue(self, nums: List[int], original: int) -> int:
        nums = set(nums)
        while original in nums:
            original *= 2
        return original

4.7.642 - 2025-08-17 17:28:49 +0300 MSK

Count Elements With Strictly Smaller and Greater Elements
class Solution:
    def countElements(self, nums: List[int]) -> int:
        if len(nums) < 3:
            return 0
        nums.sort()
        res = 0
        prev, cur, cur_count = None, nums[0], 1
        for num in nums:
            if num == cur:
                cur_count += 1
            elif prev is None:
                prev = cur
                cur = num
                cur_count = 1
            else:
                res += cur_count
                prev = cur
                cur = num
                cur_count = 1
        return res

4.7.643 - 2025-08-17 17:16:59 +0300 MSK

Minimum Cost of Buying Candies With Discount
class Solution:
    def minimumCost(self, cost: List[int]) -> int:
        cost.sort()
        res = 0
        while cost:
            if len(cost) > 2:
                res += cost.pop() + cost.pop()
                cost.pop()
            else:
                res += cost.pop()
        return res

4.7.644 - 2025-08-17 17:04:01 +0300 MSK

Divide a String Into Groups of Size k
class Solution:
    def divideString(self, s: str, k: int, fill: str) -> List[str]:
        res = []
        cur = []
        for char in s:
            cur.append(char)
            if len(cur) == k:
                res.append("".join(cur))
                cur.clear()
        if cur and len(cur) < k:
            cur.append(fill * (k - len(cur)))
            res.append("".join(cur))
            cur.clear()
        return res

4.7.645 - 2025-08-17 16:00:07 +0300 MSK

Check if Every Row and Column Contains All Numbers
class Solution:
    def checkValid(self, matrix: List[List[int]]) -> bool:
        length = len(matrix)
        rows = bytearray(length + 1)
        cols = bytearray(length + 1)
        for row in range(length):    
            for col in range(length):
                row_col, col_row = matrix[row][col], matrix[col][row]
                rows[row_col] += 1
                cols[col_row] += 1
                if rows[row_col] > 1 or cols[col_row] > 1:
                    return False
            for i in range(length + 1):
                rows[i] = 0
                cols[i] = 0
        return True

4.7.646 - 2025-08-17 13:53:56 +0300 MSK

Capitalize the Title
class Solution:
    def capitalizeTitle(self, title: str) -> str:
        res = []
        cur = []
        for char in itertools.chain(title, " "):
            if char != " ":
                cur.append(char)
                continue
            for i in range(len(cur)):
                cur[i] = cur[i].lower()
            if len(cur) > 2:
                cur[0] = cur[0].upper()
            res.append("".join(cur))
            cur.clear()
        return " ".join(res) 

4.7.647 - 2025-08-17 13:41:15 +0300 MSK

Check if All A’s Appears Before All B’s
class Solution:
    def checkString(self, s: str) -> bool:
        found_a = False
        found_b = False
        for char in s:
            if char == "a":
                if found_b:
                    return False
                if not found_a:
                    found_a = True
            else:
                if not found_b:
                    found_b = True
        return True

4.7.648 - 2025-08-17 13:38:02 +0300 MSK

A Number After a Double Reversal
class Solution:
    def isSameAfterReversals(self, num: int) -> bool:
        if num == 0:
            return True
        return num % 10 != 0

4.7.649 - 2025-08-17 13:36:24 +0300 MSK

Maximum Number of Words Found in Sentences
class Solution:
    def mostWordsFound(self, sentences: List[str]) -> int:
        res = 0
        for sentence in sentences:
            count = sentence.count(" ") + 1
            if count > res:
                res = count
        return res

4.7.650 - 2025-08-17 13:34:11 +0300 MSK

Rings and Rods
class Solution:
    def countPoints(self, rings: str) -> int:
        rods = [(False, False, False)] * 10
        res = 0
        for i in range(0, len(rings), 2):
            rod = int(rings[i + 1])
            color = rings[i]
            has_red, has_green, has_blue = rods[rod]
            if color == "R":
                has_red = True
            elif color == "G":
                has_green = True
            else:
                has_blue = True
            rods[rod] = (has_red, has_green, has_blue)
        for vals in rods:
            if all(vals):
                res += 1
        return res

4.7.651 - 2025-08-17 13:25:54 +0300 MSK

Find Subsequence of Length K With the Largest Sum
class Solution:
    def maxSubsequence(self, nums: List[int], k: int) -> List[int]:
        length = len(nums)
        for i in range(length):
            nums[i] = (i, nums[i])
        nums.sort(key=lambda num: -num[1])
        while len(nums) > k:
            nums.pop()
        nums.sort()
        for i in range(k):
            nums[i] = nums[i][1]
        return nums

4.7.652 - 2025-08-17 13:10:43 +0300 MSK

Finding 3-Digit Even Numbers
class Solution:
    def findEvenNumbers(self, digits: List[int]) -> List[int]:
        res = []
        freq = Counter(digits)  
        for i in range(100, 1000, 2):
            freq1 = Counter([int(d) for d in str(i)])
            if all(freq[d] >= freq1[d] for d in freq1.keys()):
                res.append(i)
        return res

4.7.653 - 2025-08-17 12:55:05 +0300 MSK

Find Target Indices After Sorting Array
class Solution:
    def targetIndices(self, nums: List[int], target: int) -> List[int]:
        count_eq = 0
        count_less = 0
        for num in nums:
            if num == target:
                count_eq += 1
            elif num < target:
                count_less += 1
        return tuple(range(count_less, count_less + count_eq))

4.7.654 - 2025-08-17 12:47:03 +0300 MSK

Find Target Indices After Sorting Array
class Solution:
    def targetIndices(self, nums: List[int], target: int) -> List[int]:
        nums.sort()
        if nums[0] > target or nums[-1] < target:
            return []
        res = []
        for i, num in enumerate(nums):
            if num == target:
                res.append(i)
        return res

4.7.655 - 2025-08-17 12:39:05 +0300 MSK

Count Common Words With One Occurrence
class Solution:
    def countWords(self, words1: List[str], words2: List[str]) -> int:
        freqs = defaultdict(lambda: (0, 0))
        for word in words1:
            freq1, _ = freqs[word]
            if freq1 in (0, 1):
                freqs[word] = (freq1 + 1, 0)
        for word in words2:
            freq1, freq2 = freqs[word]
            if freq2 in (0, 1):
                freqs[word] = (freq1, freq2 + 1)
        res = 0
        for freq1, freq2 in freqs.values():
            if freq1 == freq2 == 1:
                res += 1
        return res
        

4.7.656 - 2025-08-17 11:54:12 +0300 MSK

Two Furthest Houses With Different Colors
class Solution:
    def maxDistance(self, colors: List[int]) -> int:
        prev, res = math.inf, 0
        start = colors[0]
        for i, color in enumerate(colors):
            if color != start:
                res = i
                prev = min(prev, i)
            else:
                res = max(res, i - prev)
        return res

4.7.657 - 2025-08-17 09:23:21 +0300 MSK

New 21 Game
class Solution:
    def new21Game(self, n: int, k: int, maxPts: int) -> float:
        dp = [0] * (n + 1)
        dp[0] = 1
        s = 1 if k > 0 else 0
        for i in range(1, n + 1):
            dp[i] = s / maxPts
            if i < k:
                s += dp[i]
            if i - maxPts >= 0 and i - maxPts < k:
                s -= dp[i - maxPts]
        return sum(dp[k:])

4.7.658 - 2025-08-16 18:43:20 +0300 MSK

Check Whether Two Strings are Almost Equivalent
class Solution:
    def checkAlmostEquivalent(self, word1: str, word2: str) -> bool:
        freqs = [0] * 26
        for char in word1:
            freqs[ord(char) - 97] += 1
        for char in word2:
            freqs[ord(char) - 97] -= 1
        for freq in freqs:
            if freq > 3 or freq < -3:
                return False
        return True

4.7.659 - 2025-08-16 16:51:28 +0300 MSK

Count Vowel Substrings of a String
from collections import defaultdict

class Solution:
    def countVowelSubstrings(self, word):
        vowels_map = {'a': True, 'e': True, 'i': True, 'o': True, 'u': True}
        len_word = len(word)
        left_index = 0
        right_index = 0
        ret_val = 0
        char_to_freq_map = defaultdict(int)
        i = 0
        while i < len_word:
            c = word[i]
            if c in vowels_map.keys():
                char_to_freq_map[c] += 1
                while set(char_to_freq_map.keys()) == set(vowels_map.keys()):
                    c = word[right_index]
                    char_to_freq_map[c] -= 1
                    if (char_to_freq_map[c] <= 0):
                        char_to_freq_map.pop(c)
                    right_index += 1
                ret_val += (right_index - left_index)
            else:
                char_to_freq_map.clear()
                left_index = i + 1
                right_index = i + 1
            i += 1
        return ret_val

4.7.660 - 2025-08-16 16:11:23 +0300 MSK

Smallest Index With Equal Value
class Solution:
    def smallestEqual(self, nums: List[int]) -> int:
        for i, num in enumerate(nums):
            if i % 10 == num:
                return i
        return -1

4.7.661 - 2025-08-16 14:42:51 +0300 MSK

Kth Distinct String in an Array
class Solution:
    def kthDistinct(self, arr: List[str], k: int) -> str:
        freqs = defaultdict(int)
        for string in arr:
            if freqs[string] in (0, 1):
                freqs[string] += 1
        for string in arr:
            if freqs[string] == 1:
                if k == 1:
                    return string
                k -= 1
        return ""

4.7.662 - 2025-08-16 14:31:57 +0300 MSK

Number of Valid Words in a Sentence
class Solution:
    def countValidWords(self, sentence: str) -> int:
        def is_valid_word(token):
            len_token = len(token)
            
            i = 0
            while (i < len_token):
                c = token[i]
                if (ord(c) not in range(ord('a'), ord('z') + 1)
                    and c != '-'
                    and c not in ('!', '.', ',')):
                    return False
                elif (c == '-'
                      and i > 1
                      and not token[:i].isalpha()):
                    return False
                elif (c == '-'
                      and i < len_token - 1
                      and (not token[i+1:].isalpha() and not (token[i+1:-1].isalpha() and token[-1] in ('!', '.', ',')))):
                    return False
                elif (c == '-'
                      and (i == 0 or i == len_token-1)):
                    return False
                elif (c in ('!', '.', ',')
                      and i < len_token - 1):
                    return False

                i += 1

            return True

        tokens = [t for t in sentence.split(' ') if t != '']
        count_valid_words = 0
        for token in tokens:
            print(token, is_valid_word(token))
            if (is_valid_word(token)):
                count_valid_words += 1
        
        return count_valid_words

4.7.663 - 2025-08-16 14:30:59 +0300 MSK

Check if Numbers Are Ascending in a Sentence
class Solution:
    def areNumbersAscending(self, s: str) -> bool:
        cur = []
        prev = 0
        for char in itertools.chain(s, " "):
            if char.isdigit():
                cur.append(char)
            elif cur:
                val = 0
                count = 0
                while cur:
                    val += int(cur.pop()) * (10 ** count)
                    count += 1
                if val <= prev:
                    return False
                prev = val
        return True

4.7.664 - 2025-08-16 14:27:06 +0300 MSK

Two Out of Three
class Solution:
    def twoOutOfThree(self, nums1: List[int], nums2: List[int], nums3: List[int]) -> List[int]:
        freqs = [(False, False, False)] * 102
        for num in nums1:
            freqs[num] = (True, False, False)
        for num in nums2:
            stat1, stat2, _ = freqs[num]
            if not stat2:
                freqs[num] = (stat1, True, False)
        for num in nums3:
            stat1, stat2, stat3 = freqs[num]
            if not stat3:
                freqs[num] = (stat1, stat2, True) 
        nums1.clear()
        for num in range(1, len(freqs)):
            if sum(freqs[num]) >= 2:
                nums1.append(num)
        return nums1

4.7.665 - 2025-08-16 14:19:48 +0300 MSK

Minimum Moves to Convert String
class Solution:
    def minimumMoves(self, s: str) -> int:
        i = 0
        length = len(s)
        res = 0
        while i < length:
            if s[i] == "X":
                res += 1
                i += 3
            else:
                i += 1
        return res 

4.7.666 - 2025-08-16 14:16:53 +0300 MSK

Convert 1D Array Into 2D Array
class Solution:
    def construct2DArray(self, original: List[int], m: int, n: int) -> List[List[int]]:
        i = 0
        if len(original) != m * n:
            return []
        res = [[None] * n for _ in range(m)]
        for row in range(m):
            for col in range(n):
                res[row][col] = original[i]
                i += 1
        return res

4.7.667 - 2025-08-16 14:14:34 +0300 MSK

Maximum Difference Between Increasing Elements
class Solution:
    def maximumDifference(self, nums: List[int]) -> int:
        res, left = -1, nums[0]
        for num in nums[1:]:
            if num > left:
                diff = num - left
                if diff > res:
                    res = diff
            else:
                left = num
        return res

4.7.668 - 2025-08-16 14:05:37 +0300 MSK

Final Value of Variable After Performing Operations
class Solution:
    def finalValueAfterOperations(self, operations: List[str]) -> int:
        res = 0
        for op in operations:
            if op.startswith("++") or op.endswith("++"):
                res += 1
            else:
                res -= 1
        return res

4.7.669 - 2025-08-16 14:04:12 +0300 MSK

Count Number of Pairs With Absolute Difference K
class Solution:
    def countKDifference(self, nums: List[int], k: int) -> int:
        freqs = [0] * 102
        count = 0
        for num in nums:
            freqs[num] += 1
        for num in nums:
            freqs[num] = max(freqs[num] - 1, 0)
            target = num + k
            for target in (num - k, num + k):
                if target >= 0 and target < 102 and freqs[target] > 0:
                    count += freqs[target]
        return count

4.7.670 - 2025-08-16 13:53:07 +0300 MSK

Count Special Quadruplets
class Solution:
    def countQuadruplets(self, nums: List[int]) -> int:
        count = 0
        numbers = defaultdict(list)
        length = len(nums)
        for i in range(length - 1):
            for j in range(i + 1, length):
                numbers[nums[i] + nums[j]].append(j)
        for i in range(2, length - 1):
            for j in range(i + 1, length):
                target = nums[j] - nums[i]
                for idx in numbers[target]:
                    if i > idx:
                        count += 1
        return count

4.7.671 - 2025-08-16 13:39:08 +0300 MSK

Find the Middle Index in Array
class Solution:
    def findMiddleIndex(self, nums: List[int]) -> int:
        left, right = 0, sum(nums)
        for i, num in enumerate(nums):
            right -= num
            if left == right:
                return i
            left += num
        return -1

4.7.672 - 2025-08-16 13:35:39 +0300 MSK

Minimum Difference Between Highest and Lowest of K Scores
class Solution:
    def minimumDifference(self, nums: list[int], k: int) -> int:
        if (k < 2 or k > len(nums)):
            return 0
        nums.sort()
        lowest = float('inf')
        for i in range(len(nums) - k + 1):
            diff = nums[i + k - 1] - nums[i]
            if diff < lowest:
                lowest = diff
        return lowest

4.7.673 - 2025-08-16 13:22:50 +0300 MSK

Find Greatest Common Divisor of Array
class Solution:
    def findGCD(self, nums: List[int]) -> int:
        nums.sort()
        small, big = nums[0], nums[-1]
        for i in range(1, small + 1):
            if small % i != 0:
                continue
            val = small // i
            if big % val == 0:
                return val
        raise Exception

4.7.674 - 2025-08-16 13:15:31 +0300 MSK

Employees Whose Manager Left the Company
SELECT
    employee_id
FROM
    Employees
WHERE
    manager_id NOT IN (
        SELECT
            employee_id
        FROM
            Employees
    ) 
    AND salary < 30000
ORDER BY
    employee_id

4.7.675 - 2025-08-16 13:13:30 +0300 MSK

Minimum Time to Type Word Using Special Typewriter
class Solution:
    def minTimeToType(self, word: str) -> int:
        pos = 97
        res = 0
        for char in word:
            cur_pos = ord(char)
            diff = abs(cur_pos - pos) 
            res += min(diff, 26 - diff) + 1
            pos = cur_pos
        return res

4.7.676 - 2025-08-16 12:59:52 +0300 MSK

Number of Strings That Appear as Substrings in Word
class Solution:
    def numOfStrings(self, patterns: List[str], word: str) -> int:
        count = 0
        for pattern in patterns:
            if pattern in word:
                count += 1
        return count

4.7.677 - 2025-08-16 12:54:52 +0300 MSK

Employees With Missing Information
SELECT 
    COALESCE(
        t1.employee_id, 
        t2.employee_id
    ) AS employee_id
FROM
    Employees t1 
FULL JOIN
    Salaries t2
ON 
    t1.employee_id = t2.employee_id
WHERE 
    t1.name IS NULL 
    OR t2.salary IS NULL
ORDER BY 
    employee_id;

4.7.678 - 2025-08-16 12:42:27 +0300 MSK

Check If String Is a Prefix of Array
class Solution:
    def isPrefixString(self, s: str, words: List[str]) -> bool:
        i = 0
        length = len(s)
        for word in words:
            if i >= length:
                return True
            word_length = len(word)
            if word_length > length - i:
                return False
            if word != s[i:i+word_length]:
                return False
            i += word_length
        return i >= length

4.7.679 - 2025-08-16 12:24:35 +0300 MSK

Three Divisors
class Solution:
    def isThree(self, n: int) -> bool:
        count = 1
        for num in range(2, n // 2 + 1):
            if n % num == 0:
                count += 2
            if count > 3:
                break
        return count == 3

4.7.680 - 2025-08-16 12:19:08 +0300 MSK

Sum of Digits of String After Convert
class Solution:
    def getLucky(self, s: str, k: int) -> int:
        def trans(val: int, count: int) -> int:
            if count == 0:
                return val
            res = 0
            while val > 0:
                res += val % 10
                val //= 10
            return trans(res, count - 1)
        val = 0
        for char in s:
            val += trans(ord(char) - 97 + 1, 1)
        return trans(val, k - 1)

4.7.681 - 2025-08-16 12:12:54 +0300 MSK

Check if All Characters Have Equal Number of Occurrences
class Solution:
    def areOccurrencesEqual(self, s: str) -> bool:
        freqs = defaultdict(int)
        for char in s:
            freqs[char] += 1
        target = freqs[s[0]]
        for freq in freqs.values():
            if freq != target:
                return False
        return True

4.7.682 - 2025-08-16 12:11:17 +0300 MSK

Maximum Number of Words You Can Type
class Solution:
    def canBeTypedWords(self, text: str, brokenLetters: str) -> int:
        ignore = False
        res = 0
        for char in itertools.chain(text, " "):
            if char == " ":
                if ignore:
                    ignore = False
                else:
                    res += 1
            elif char in brokenLetters:
                ignore = True
        return res

4.7.683 - 2025-08-16 12:07:23 +0300 MSK

Concatenation of Array
class Solution:
    def getConcatenation(self, nums: List[int]) -> List[int]:
        for i in range(len(nums)):
            nums.append(nums[i])
        return nums

4.7.684 - 2025-08-16 12:06:11 +0300 MSK

Count Square Sum Triples
class Solution:
    def countTriples(self, n: int) -> int:
        res = 0
        for a in range(1, n):
            for b in range(a + 1, n):
                c = math.sqrt(a * a + b * b)
                if c % 1 == 0 and c <= n:
                    res += 2
        return res

4.7.685 - 2025-08-16 11:58:38 +0300 MSK

Build Array from Permutation
class Solution:
    def buildArray(self, nums: List[int]) -> List[int]:
        length = len(nums)
        for i in range(length):
            val = nums[i] % 1000
            res = 1000 * (nums[val] % 1000)
            nums[i] = res + val
        for i in range(length):
            nums[i] //= 1000
        return nums

4.7.686 - 2025-08-16 11:50:13 +0300 MSK

Build Array from Permutation
class Solution:
    def buildArray(self, nums: List[int]) -> List[int]:
        res = [None] * len(nums)
        for i, num in enumerate(nums):
            res[i] = nums[num]
        return res

4.7.687 - 2025-08-16 11:32:58 +0300 MSK

Remove One Element to Make the Array Strictly Increasing
class Solution:
    def canBeIncreasing(self, nums: List[int]) -> bool:
        removed = False
        length = len(nums)
        for i in range(length - 1):
            cur, nxt = nums[i], nums[i + 1]
            if nxt > cur:
                continue
            if removed:
                return False
            removed = True
            if (
                i > 0 and nums[i - 1] >= nxt
            ) and (
                i + 2 < length and cur >= nums[i + 2]
            ):
                return False
        return True

4.7.688 - 2025-08-16 11:14:35 +0300 MSK

Check if All the Integers in a Range Are Covered
class Solution:
    def isCovered(self, ranges: List[List[int]], left: int, right: int) -> bool:
        cov = [False] * (right - left + 1)
        for start, end in ranges:
            for num in range(max(left, start), min(end, right) + 1):
                i = num - left
                if not cov[i]:
                    cov[i] = True
        return False not in cov

4.7.689 - 2025-08-16 11:13:51 +0300 MSK

Check if All the Integers in a Range Are Covered
class Solution:
    def isCovered(self, ranges: List[List[int]], left: int, right: int) -> bool:
        cov = [False] * (right - left + 1)
        for start, end in ranges:
            for num in range(max(left, start), min(end, right) + 1):
                cov[num - left] = True
        return False not in cov

4.7.690 - 2025-08-16 11:09:17 +0300 MSK

The Latest Login in 2020
SELECT 
    user_id, 
    MAX(time_stamp) AS last_stamp
FROM 
    Logins 
WHERE 
    time_stamp >= '2020-01-01'
    AND time_stamp < '2021-01-01'
GROUP BY 
    user_id

4.7.691 - 2025-08-16 10:49:39 +0300 MSK

Determine Whether Matrix Can Be Obtained By Rotation
class Solution:
    def findRotation(self, mat: List[List[int]], target: List[List[int]]) -> bool:
        length = len(mat)
        count_0, count_90, count_180, count_270 = 0, 0, 0, 0
        for i in range(length):
            for j in range(length):
                val = mat[i][j]
                if val == target[i][j]:
                    count_0 += 1
                if val == target[j][length - i - 1]:
                    count_90 += 1
                if val == target[length - i - 1][length - j - 1]:
                    count_180 += 1
                if val == target[length - j - 1][i]:
                    count_270 += 1
        return length * length in {count_0, count_90, count_180, count_270}

4.7.692 - 2025-08-16 10:22:08 +0300 MSK

Check if Word Equals Summation of Two Words
class Solution:
    def isSumEqual(self, firstWord: str, secondWord: str, targetWord: str) -> bool:
        def count(word: str) -> int:
            length = len(word)
            res = 0
            for i in reversed(range(length)):
                res += (ord(word[i]) - 97) * (10 ** (length - i - 1))
            return res
        return count(firstWord) + count(secondWord) == count(targetWord)

4.7.693 - 2025-08-16 10:19:18 +0300 MSK

Check if Word Equals Summation of Two Words
class Solution:
    def isSumEqual(self, firstWord: str, secondWord: str, targetWord: str) -> bool:
        digits = []
        def count(word: str) -> int:
            for char in word:
                digits.append(ord(char) - 97)
            res = 0
            count = 0
            while digits:
                res += digits.pop() * (10 ** count)
                count += 1
            return res
        return count(firstWord) + count(secondWord) == count(targetWord)

4.7.694 - 2025-08-16 10:09:43 +0300 MSK

Maximum 69 Number
class Solution:
    def maximum69Number (self, num: int) -> int:
        digits = []
        while num > 0:
            digits.append(num % 10)
            num //= 10
        digits.reverse()
        for i in range(len(digits)):
            if digits[i] == 6:
                digits[i] = 9
                break
        res = 0
        count = 0
        while digits:
            res += digits.pop() * (10 ** count)
            count += 1
        return res

4.7.695 - 2025-08-15 17:31:44 +0300 MSK

Substrings of Size Three with Distinct Characters
class Solution:
    def countGoodSubstrings(self, s: str) -> int:
        res = 0
        for i in range(len(s) - 2):
            char1, char2, char3 = s[i:i+3]
            if char1 != char2 and char1 != char3 and char2 != char3:
                res += 1
        return res

4.7.696 - 2025-08-15 16:57:42 +0300 MSK

Calculate Special Bonus
SELECT
    employee_id,
    (
        CASE 
            WHEN
                employee_id % 2 != 0
                AND NOT STARTS_WITH(name, 'M')
            THEN
                salary
            ELSE
                0
        END

    ) AS "bonus"
FROM
    Employees
ORDER BY
    employee_id

4.7.697 - 2025-08-15 16:43:07 +0300 MSK

Longer Contiguous Segments of Ones than Zeros
class Solution:
    def checkZeroOnes(self, s: str) -> bool:
        max_length = [0, 0]
        cur = 0
        prev = -1
        for char in s:
            val = int(char)
            if val == prev:
                cur += 1
            else:
                cur = 1
            if cur > max_length[val]:
                max_length[val] = cur
            prev = val
        return max_length[1] > max_length[0]

4.7.698 - 2025-08-15 16:35:39 +0300 MSK

Sorting the Sentence
class Solution:
    def sortSentence(self, s: str) -> str:
        res = [None] * 9
        cur = []
        for char in s:
            if char.isalpha():
                cur.append(char)
            elif char.isdigit():
                res[int(char) - 1] = "".join(cur)
                cur.clear()
        return " ".join(word for word in res if word is not None)

4.7.699 - 2025-08-15 16:30:08 +0300 MSK

Maximum Population Year
class Solution:
    def maximumPopulation(self, logs: List[List[int]]) -> int:
        population = [0] * 102
        max_population = 0
        for birth, death in logs:
            for year in range(birth, death):
                i = year - 1950
                new_population = population[i] + 1
                population[i] = new_population
                if new_population > max_population:
                    max_population = new_population
        for i, count in enumerate(population):
            if count == max_population:
                return 1950 + i
        raise Exception

4.7.700 - 2025-08-15 16:25:44 +0300 MSK

Minimum Distance to the Target Element
class Solution:
    def getMinDistance(self, nums: List[int], target: int, start: int) -> int:
        length = len(nums)
        dist = 0
        while dist < length:
            left, right = start - dist, start + dist
            if left >= 0 and nums[left] == target:
                return dist
            if right < length and nums[right] == target:
                return dist
            dist += 1
        raise Exception

4.7.701 - 2025-08-15 16:20:07 +0300 MSK

Replace All Digits with Characters
class Solution:
    def replaceDigits(self, s: str) -> str:
        res = []
        for i in range(0, len(s) - 1, 2):
            char, digit = s[i], int(s[i + 1])
            res.append(char)
            res.append(chr(ord(char) + digit))
        if len(s) % 2 != 0:
            res.append(s[-1])
        return "".join(res)

4.7.702 - 2025-08-15 16:13:25 +0300 MSK

Sum of Digits in Base K
class Solution:
    def sumBase(self, n: int, k: int) -> int:
        digits = []
        while n > 0:
            digits.append(n % k)
            n //= k
        return sum(digits)

4.7.703 - 2025-08-15 16:11:57 +0300 MSK

Check if the Sentence Is Pangram
class Solution:
    def checkIfPangram(self, sentence: str) -> bool:
        freqs = [0] * 26
        for char in sentence:
            freqs[ord(char) - 97] += 1
        return 0 not in freqs

4.7.704 - 2025-08-15 16:11:03 +0300 MSK

Minimum Operations to Make the Array Increasing
class Solution:
    def minOperations(self, nums: List[int]) -> int:
        res = 0
        prev = nums[0]
        for num in nums[1:]:
            if num > prev:
                prev = num
            else:
                new = prev + 1
                res += new - num
                prev = new
        return res

4.7.705 - 2025-08-15 16:06:24 +0300 MSK

Truncate Sentence
class Solution:
    def truncateSentence(self, s: str, k: int) -> str:
        res = s.split(" ")
        while len(res) > k:
            res.pop()
        return " ".join(res)

4.7.706 - 2025-08-15 16:05:32 +0300 MSK

Truncate Sentence
class Solution:
    def truncateSentence(self, s: str, k: int) -> str:
        res = []
        cur = []
        for char in itertools.chain(s, " "):
            if char.isalpha():
                cur.append(char)
            else:
                res.append("".join(cur))
                cur.clear()
                if len(res) == k:
                    return " ".join(res)
        raise Exception

4.7.707 - 2025-08-15 16:03:03 +0300 MSK

Determine Color of a Chessboard Square
class Solution:
    def squareIsWhite(self, coordinates: str) -> bool:
        col = ord(coordinates[0]) - 97
        row = int(coordinates[1])
        if row % 2 == 0:
            return col % 2 == 0
        return col % 2 != 0
        

4.7.708 - 2025-08-15 15:54:30 +0300 MSK

Number of Different Integers in a String
class Solution:
    def numDifferentIntegers(self, word: str) -> int:
        enc = set()
        cur = []
        for char in itertools.chain(word, "a"):
            if char.isalpha():
                if cur:
                    count = 0
                    num = 0
                    while cur:
                        num += cur.pop() * (10 ** count)
                        count += 1
                    enc.add(num)
            else:
                cur.append(int(char))
        return len(enc)
        
            

4.7.709 - 2025-08-15 15:47:22 +0300 MSK

Maximum Ascending Subarray Sum
class Solution:
    def maxAscendingSum(self, nums: List[int]) -> int:
        max_sum, cur_sum, prev = nums[0], nums[0], nums[0]
        for num in nums[1:]:
            if num > prev:
                cur_sum += num
            else:
                cur_sum = num
            if cur_sum > max_sum:
                max_sum = cur_sum
            prev = num
        return max_sum

4.7.710 - 2025-08-15 15:44:11 +0300 MSK

Second Largest Digit in a String
class Solution:
    def secondHighest(self, s: str) -> int:
        num1, num2 = -1, -1
        for char in s:
            if not char.isdigit():
                continue
            num = int(char)
            if num > num2:
                num1, num2 = num2, num
            elif num != num2 and num > num1:
                num1 = num
        return num1

4.7.711 - 2025-08-15 15:38:40 +0300 MSK

Rearrange Products Table
(
    SELECT 
        product_id,
        'store1' AS store,
        store1 AS price
    FROM 
        Products
    WHERE 
        store1 IS NOT NULL
) UNION (
    SELECT 
        product_id,
        'store2' AS store,
        store2 AS price
    FROM 
        Products
    WHERE 
        store2 IS NOT NULL
) UNION (
    SELECT 
        product_id,
       'store3' AS store,
       store3 AS price
    FROM 
        Products
    WHERE 
        store3 IS NOT NULL
)
ORDER BY 
    product_id, 
    store;

4.7.712 - 2025-08-15 15:32:17 +0300 MSK

Find Center of Star Graph
class Solution:
    def findCenter(self, edges: List[List[int]]) -> int:
        num1, num2 = edges[0]
        num3, num4 = edges[1]
        if num1 == num3 or num1 == num4:
            return num1
        return num2

4.7.713 - 2025-08-15 15:28:53 +0300 MSK

Check if One String Swap Can Make Strings Equal
class Solution:
    def areAlmostEqual(self, s1: str, s2: str) -> bool:
        if s1 == s2:
            return True
        length = len(s1)
        if length != len(s2):
            return False
        i1, i2 = -1, -1
        for i, (char1, char2) in enumerate(zip(s1, s2)):
            if char1 == char2:
                continue
            if i1 == -1:
                i1 = i
            elif i2 == -1:
                i2 = i
            else:
                return False
        if i2 == -1:
            return False
        return s1[i1] == s2[i2] and s1[i2] == s2[i1]

4.7.714 - 2025-08-15 15:12:21 +0300 MSK

Primary Department for Each Employee
SELECT 
    employee_id, 
    department_id
FROM 
    (
        SELECT 
            employee_id,
            department_id,
            primary_flag,
            COUNT(employee_id) OVER(
                PARTITION BY 
                    employee_id
            ) AS employee_count
        FROM 
            Employee
    ) EmployeePartition
WHERE 
    employee_count = 1 
    OR primary_flag = 'Y';

4.7.715 - 2025-08-15 15:04:18 +0300 MSK

Check if Binary String Has at Most One Segment of Ones
class Solution:
    def checkOnesSegment(self, s: str) -> bool:
        enc = False
        for char in s:
            if char == "1":
                if enc:
                    return False
            elif not enc:
                enc = True
        return True

4.7.716 - 2025-08-15 15:03:12 +0300 MSK

Check if Binary String Has at Most One Segment of Ones
class Solution:
    def checkOnesSegment(self, s: str) -> bool:
        enc = False
        for char in s[1:]:
            if char == "1" and enc:
                return False
            elif char == "1":
                continue
            enc = True
        return True

4.7.717 - 2025-08-15 14:37:22 +0300 MSK

Count Items Matching a Rule
class Solution:
    def countMatches(self, items: List[List[str]], ruleKey: str, ruleValue: str) -> int:
        count = 0
        for type, color, name in items:
            if (
                (ruleKey == "type" and ruleValue == type)
                or (ruleKey == "color" and ruleValue == color)
                or (ruleKey == "name" and ruleValue == name)
            ):
                count += 1
        return count 

4.7.718 - 2025-08-15 14:34:58 +0300 MSK

Recyclable and Low Fat Products
SELECT
    Products.product_id
FROM
    Products
WHERE
    Products.low_fats = 'Y'
    AND Products.recyclable = 'Y';

4.7.719 - 2025-08-15 14:33:22 +0300 MSK

Check if Array Is Sorted and Rotated
class Solution:
    def check(self, nums: List[int]) -> bool:
        prev = nums[0]
        count = 0
        for num in nums[1:]:
            if num >= prev:
                pass
            elif count == 0:
                count = 1
            else:
                return False
            prev = num
        if count == 0:
            return True
        return nums[0] >= nums[-1]

4.7.720 - 2025-08-15 14:31:10 +0300 MSK

Check if Array Is Sorted and Rotated
class Solution:
    def check(self, nums: List[int]) -> bool:
        prev = nums[0]
        new_start = 0
        for num in nums[1:]:
            if num >= prev:
                pass
            elif new_start == 0:
                new_start = num
            else:
                return False
            prev = num
        if new_start == 0:
            return True
        return nums[0] >= nums[-1]

4.7.721 - 2025-08-15 14:21:42 +0300 MSK

Sum of Unique Elements
class Solution:
    def sumOfUnique(self, nums: List[int]) -> int:
        enc = [0] * 101
        res = 0
        for num in nums:
            count = enc[num]
            if count == 1:
                res -= num
                enc[num] = 2
            elif count == 0:
                res += num
                enc[num] = 1
        return res

4.7.722 - 2025-08-15 14:17:27 +0300 MSK

Maximum Number of Balls in a Box
class Solution:
    def countBalls(self, lowLimit: int, highLimit: int) -> int:
        freqs = [0] * 100
        max_freq = 0
        for num in range(lowLimit, highLimit + 1):
            box = 0
            while num > 0:
                box += num % 10
                num //= 10
            freqs[box] += 1
            max_freq = max(max_freq, freqs[box])
        return max_freq

4.7.723 - 2025-08-15 14:14:49 +0300 MSK

Maximum Number of Balls in a Box
class Solution:
    def countBalls(self, lowLimit: int, highLimit: int) -> int:
        freqs = defaultdict(int)
        max_freq = 0
        for num in range(lowLimit, highLimit + 1):
            box = 0
            while num > 0:
                box += num % 10
                num //= 10
            freqs[box] += 1
            max_freq = max(max_freq, freqs[box])
        return max_freq

4.7.724 - 2025-08-15 13:38:16 +0300 MSK

Find Total Time Spent by Each Employee
SELECT
    Employees.event_day AS "day",
    Employees.emp_id,
    SUM(Employees.out_time - Employees.in_time) AS "total_time"
FROM
    Employees
GROUP BY
    Employees.event_day,
    Employees.emp_id

4.7.725 - 2025-08-15 13:31:41 +0300 MSK

Latest Time by Replacing Hidden Digits
class Solution:
    def maximumTime(self, time: str) -> str:
        hours, minutes = time.split(":")
        hour1, hour2 = hours
        minute1, minute2 = minutes
        if hour1 == "?" and hour2 == "?":
            hour1, hour2 = "2", "3"
        elif hour1 == "?" and hour2 < "4":
            hour1 = "2"
        elif hour1 == "?":
            hour1 = "1"
        elif hour1 == "2" and hour2 == "?":
            hour2 = "3"
        elif hour2 == "?":
            hour2 = "9"
        if minute1 == "?":
            minute1 = "5"
        if minute2 == "?":
            minute2 = "9"
        return ":".join(("".join((hour1, hour2)), "".join((minute1, minute2)))) 

4.7.726 - 2025-08-15 13:23:40 +0300 MSK

The Number of Employees Which Report to Each Employee
SELECT 
    managers.employee_id, 
    managers.name, 
    COUNT(reports.employee_id) AS reports_count, 
    ROUND(AVG(reports.age)) AS average_age
FROM 
    Employees managers
INNER JOIN 
    Employees reports
ON
    managers.employee_id = reports.reports_to
GROUP BY 
    managers.employee_id, 
    managers.name
ORDER BY 
    managers.employee_id;

4.7.727 - 2025-08-15 13:09:22 +0300 MSK

Find Followers Count
SELECT 
    Followers.user_id, 
    COUNT(Followers.user_id) AS followers_count
FROM 
    Followers
GROUP BY 
    Followers.user_id
ORDER BY
    Followers.user_id ASC;

4.7.728 - 2025-08-15 13:07:52 +0300 MSK

Find Followers Count
SELECT
    followers1.user_id,
    COUNT(DISTINCT followers1.follower_id) AS "followers_count"
FROM
    Followers followers1
LEFT JOIN
    Followers followers2
ON
    followers1.user_id = followers2.user_id
GROUP BY
    followers1.user_id;

4.7.729 - 2025-08-15 12:54:27 +0300 MSK

Number Of Rectangles That Can Form The Largest Square
class Solution:
    def countGoodRectangles(self, rectangles: List[List[int]]) -> int:
        max_len, res = 0, 0
        for length, width in rectangles:
            side = min(length, width)
            if side < max_len:
                continue
            elif side == max_len:
                res += 1
            else:
                max_len = side
                res = 1
        return res

4.7.730 - 2025-08-15 12:49:02 +0300 MSK

Decode XORed Array
class Solution:
    def decode(self, encoded: List[int], first: int) -> List[int]:
        prev_encoded = encoded[0]
        encoded[0] = first
        for i in range(1, len(encoded)):
            encoded[i], prev_encoded = prev_encoded ^ encoded[i - 1], encoded[i]
        encoded.append(prev_encoded ^ encoded[-1])
        return encoded

4.7.731 - 2025-08-15 12:36:30 +0300 MSK

Decode XORed Array
class Solution:
    def decode(self, encoded: List[int], first: int) -> List[int]:
        prev = first
        for i in range(len(encoded)):
            prev = encoded[i] ^ prev
            encoded[i] = prev
        encoded.insert(0, first)
        return encoded

4.7.732 - 2025-08-15 12:28:46 +0300 MSK

Maximum Units on a Truck
class Solution:
    def maximumUnits(self, boxTypes: List[List[int]], truckSize: int) -> int:
        boxTypes.sort(key=lambda item: item[1])
        res = 0
        while boxTypes and truckSize > 0:
            boxes, units = boxTypes.pop()
            count = min(boxes, truckSize)
            truckSize -= count
            res += count * units
        return res

4.7.733 - 2025-08-15 12:22:34 +0300 MSK

Reformat Phone Number
class Solution:
    def reformatNumber(self, number: str) -> str:
        digits = []
        for char in number:
            if char == " " or char == "-":
                continue
            digits.append(char)
        res = []
        digits.reverse()
        while len(digits) > 4:
            res.append("".join((digits.pop(), digits.pop(), digits.pop())))
        length = len(digits)
        if length == 4:
            res.append("".join((digits.pop(), digits.pop())))
            res.append("".join((digits.pop(), digits.pop())))
        elif length == 3:
            res.append("".join((digits.pop(), digits.pop(), digits.pop())))
        elif length == 2:
            res.append("".join((digits.pop(), digits.pop())))
        return "-".join(res)

4.7.734 - 2025-08-15 11:52:01 +0300 MSK

Power of Four
class Solution:
    def isPowerOfFour(self, n: int) -> bool:
        if n <= 0:
            return False
        if n & (n - 1) != 0:
            return False
        while n % 4 == 0:
            n //= 4
        return n == 1

4.7.735 - 2025-08-15 11:51:01 +0300 MSK

Power of Four
class Solution:
    def isPowerOfFour(self, n: int) -> bool:
        if n <= 0:
            return False
        while n % 4 == 0:
            n //= 4
        return n == 1

4.7.736 - 2025-08-14 20:09:09 +0300 MSK

Largest 3-Same-Digit Number in String
class Solution:
    def largestGoodInteger(self, num: str) -> str:
        max_digit = "\0"
        for index in range(len(num) - 2):
            if num[index] == num[index + 1] == num[index + 2]:
                max_digit = max(max_digit, num[index])
        if max_digit == "\0":
            return ""
        return max_digit * 3

4.7.737 - 2025-08-13 17:56:30 +0300 MSK

Power of Three
class Solution:
    def isPowerOfThree(self, n: int) -> bool:
        if n <= 0:
            return False
        while n % 3 == 0:
            n //= 3
        return n == 1 

4.7.738 - 2025-08-13 17:55:25 +0300 MSK

Power of Three
class Solution:
    def isPowerOfThree(self, n: int) -> bool:
        if n <= 0:
            return False
        if n == 1:
            return True
        while n > 1:
            if n % 3 != 0:
                return False
            n //= 3
        return True

4.7.739 - 2025-08-12 17:49:12 +0300 MSK

Ways to Express an Integer as Sum of Powers
class Solution:
    def numberOfWays(self, n: int, x: int) -> int:
        MOD = 10**9 + 7
        dp = [0] * (n + 1)
        dp[0] = 1

        for i in range(1, n + 1):
            val = i**x
            if val > n:
                break
            for j in range(n, val - 1, -1):
                dp[j] = (dp[j] + dp[j - val]) % MOD

        return dp[n]

4.7.740 - 2025-08-11 18:03:04 +0300 MSK

Range Product Queries of Powers
class Solution:
    def productQueries(self, n: int, queries: List[List[int]]) -> List[int]:
        mod = 10**9 + 7

        bins, rep = [], 1
        while n > 0:
            if n % 2 == 1:
                bins.append(rep)
            n //= 2
            rep *= 2

        m = len(bins)
        results = [[0] * m for _ in range(m)]
        for i in range(m):
            cur = 1
            for j in range(i, m):
                cur = cur * bins[j] % mod
                results[i][j] = cur

        ans = []
        for left, right in queries:
            ans.append(results[left][right])
        return ans

4.7.741 - 2025-08-10 13:14:07 +0300 MSK

Daily Leads and Partners
SELECT 
    DailySales.date_id,
    DailySales.make_name,
    COUNT(DISTINCT DailySales.lead_id) AS unique_leads,
    COUNT(DISTINCT DailySales.partner_id) AS unique_partners
FROM 
    DailySales
GROUP BY 
    DailySales.date_id,
    DailySales.make_name;

4.7.742 - 2025-08-10 13:10:37 +0300 MSK

Invalid Tweets
SELECT
    Tweets.tweet_id
FROM
    Tweets
WHERE
    LENGTH(Tweets.content) > 15

4.7.743 - 2025-08-10 13:08:24 +0300 MSK

Goal Parser Interpretation
class Solution:
    def interpret(self, command: str) -> str:
        stack = []
        res = []
        for char in command:
            if char == ")":
                if stack:
                    res.extend(stack)
                    stack.clear()
                else:
                    res.append("o")
            elif char == "G":
                res.append("G")
            elif char != "(":
                stack.append(char)
        return "".join(res)

4.7.744 - 2025-08-10 13:03:22 +0300 MSK

Maximum Repeating Substring
class Solution:
    def maxRepeating(self, sequence: str, word: str) -> int:
        temp, res = word, 0
        while temp in sequence:
            res += 1
            temp += word
        return res

4.7.745 - 2025-08-10 12:56:18 +0300 MSK

Fix Names in a Table
SELECT 
    Users.user_id,
    UPPER(LEFT(Users.name, 1)) 
        || LOWER(SUBSTRING(Users.name FROM 2)) AS name
FROM 
    Users
ORDER BY 
    Users.user_id;

4.7.746 - 2025-08-10 12:52:07 +0300 MSK

Average Time of Process per Machine
SELECT 
    act1.machine_id, 
    ROUND(AVG(act2.timestamp - act1.timestamp)::decimal, 3) AS processing_time
FROM
    Activity act1,
    Activity act2
WHERE 
    act1.machine_id = act2.machine_id
    AND act1.process_id = act2.process_id
    AND act1.activity_type = 'start'
    AND act2.activity_type = 'end'
GROUP BY 
    act1.machine_id;

4.7.747 - 2025-08-10 12:45:06 +0300 MSK

Defuse the Bomb
class Solution:
    def decrypt(self, code: List[int], k: int) -> List[int]:
        length = len(code)
        result = [0 for _ in range(length)]
        if k == 0:
            return result
        start, end, window_sum = 1, k + 1, 0
        if k < 0:
            start = length - (-k)
            end = length
        for i in range(start, end):
            window_sum += code[i]
        for i in range(length):
            result[i] = window_sum
            window_sum -= code[start % length]
            window_sum += code[end % length]
            start += 1
            end += 1
        return result

4.7.748 - 2025-08-10 12:15:52 +0300 MSK

Get Maximum in Generated Array
class Solution:
    def getMaximumGenerated(self, n: int) -> int:
        if n == 0 or n == 1:
            return n
        nums = [0] * (n + 1)
        nums[1] = 1
        res = 1
        for i in range(2, n + 1):
            if i % 2 == 0:
                val = nums[i // 2]
            else:
                val = nums[i // 2] + nums[(i // 2) + 1]
            nums[i] = val
            res = max(res, val)
        return res

4.7.749 - 2025-08-10 11:45:24 +0300 MSK

Check Array Formation Through Concatenation
class Solution:
    def canFormArray(self, arr: List[int], pieces: List[List[int]]) -> bool:
        num_to_piece = {}
        for i, nums in enumerate(pieces):
            for num in nums:
                num_to_piece[num] = i
        i = 0
        length = len(arr)
        while i < length:
            num1 = arr[i]
            if num1 not in num_to_piece:
                return False
            piece = pieces[num_to_piece[num1]]
            for j, num2 in enumerate(piece):
                if i + j >= length:
                    return False
                num1 = arr[i + j]
                if num1 != num2:
                    return False
            i += len(piece)
        return True

4.7.750 - 2025-08-10 11:25:09 +0300 MSK

Sort Array by Increasing Frequency
class Solution:
    def frequencySort(self, nums: List[int]) -> List[int]:
        freqs = collections.defaultdict(int)
        for num in nums:
            freqs[num] += 1
        nums.sort(key=lambda val: (freqs[val], -val))
        return nums

4.7.751 - 2025-08-10 11:14:30 +0300 MSK

Percentage of Users Attended a Contest
WITH total_users AS (
    SELECT 
        COUNT(DISTINCT user_id) AS total_count
    FROM 
        Users
)
SELECT 
    Register.contest_id,
    ROUND(
        COUNT(DISTINCT Register.user_id) * 100.0 / total_users.total_count,
        2
    ) AS percentage
FROM
    Register
CROSS JOIN 
    total_users
GROUP BY 
    Register.contest_id, 
    total_users.total_count
ORDER BY 
    percentage DESC, 
    Register.contest_id;

4.7.752 - 2025-08-10 11:02:20 +0300 MSK

Slowest Key
class Solution:
    def slowestKey(self, releaseTimes: List[int], keysPressed: str) -> str:
        max_key, max_dur = keysPressed[0], releaseTimes[0]
        for i, num in enumerate(releaseTimes[1:], 1):
            dur = num - releaseTimes[i - 1]
            cur_key = keysPressed[i]
            if dur > max_dur or (dur == max_dur and cur_key > max_key):
                max_dur = dur
                max_key = cur_key
        return max_key

4.7.753 - 2025-08-10 10:27:29 +0300 MSK

Reordered Power of 2
class Solution:
    def reorderedPowerOf2(self, n: int) -> bool:
        if n > 0 and n & (n - 1) == 0:
            return True
        def count_digits(num: int, out: list[int]) -> None:
            while num > 0:
                out.append(num % 10)
                num //= 10
            out.sort()
        target = []
        count_digits(n, target)
        cur = []
        for i in range(31):
            cur.clear()
            count_digits(1 << i, cur)
            if cur == target:
                return True
        return False

4.7.754 - 2025-08-09 16:43:21 +0300 MSK

Mean of Array After Removing Some Elements
class Solution:
    def trimMean(self, arr: List[int]) -> float:
        arr.sort()
        length = len(arr)
        interval = length // 20
        res = sum(arr[interval:length - interval])
        res = (res / (length - interval * 2))
        return res

4.7.755 - 2025-08-09 16:34:28 +0300 MSK

Crawler Log Folder
class Solution:
    def minOperations(self, logs: List[str]) -> int:
        depth = 0
        for op in logs:
            if op == "../":
                depth = max(depth - 1, 0)
            elif op == "./":
                pass
            else:
                depth += 1
        return depth

4.7.756 - 2025-08-09 16:31:49 +0300 MSK

Rearrange Spaces Between Words
class Solution:
    def reorderSpaces(self, text: str) -> str:
        res = []
        cur_word = []
        space_count = 0
        for char in text:
            if char == " ":
                space_count += 1
                if cur_word:
                    res.append("".join(cur_word))
                    cur_word.clear()
            else:
                cur_word.append(char)
        if cur_word:
            res.append("".join(cur_word))
        words = len(res) - 1
        if words == 0:
            join_str = ""
            rem_str = " " * space_count
        else:
            join_str = " " * (space_count // words) 
            rem_str = " " * (space_count % words)
        return "".join((join_str.join(res), rem_str))

4.7.757 - 2025-08-09 16:17:16 +0300 MSK

Sum of All Odd Length Subarrays
class Solution:
    def sumOddLengthSubarrays(self, arr: List[int]) -> int:
        length = len(arr)
        answer = 0
        for i, num in enumerate(arr):
            left, right = i, length - i - 1
            odd_left, odd_right = (left // 2) + 1, (right // 2) + 1
            even_left, even_right = (left + 1) // 2, (right + 1) // 2
            sub_count = (odd_left * odd_right) + (even_left * even_right)
            answer += num * sub_count
        return answer

4.7.758 - 2025-08-09 15:53:09 +0300 MSK

Sum of All Odd Length Subarrays
class Solution:
    def sumOddLengthSubarrays(self, arr: List[int]) -> int:
        res = 0
        for i in range(len(arr)):
            cur_sum = 0
            for j in range(i, len(arr)):
                cur_sum += arr[j]
                if (j - i + 1) % 2 != 0:
                    res += cur_sum
        return res

4.7.759 - 2025-08-09 11:14:40 +0300 MSK

Power of Two
class Solution:
    def isPowerOfTwo(self, n: int) -> bool:
        return n > 0 and (n & (n - 1)) == 0

4.7.760 - 2025-08-08 18:19:33 +0300 MSK

Soup Servings
class Solution:
    def soupServings(self, n: int) -> float:
        m = ceil(n / 25)
        dp = collections.defaultdict(dict)

        def calculate_dp(i: int, j: int) -> float:
            if i <= 0 and j <= 0:
                return 0.5
            if i <= 0:
                return 1.0
            if j <= 0:
                return 0.0
            if i in dp and j in dp[i]:
                return dp[i][j]

            dp[i][j] = (
                calculate_dp(i - 4, j)
                + calculate_dp(i - 3, j - 1)
                + calculate_dp(i - 2, j - 2)
                + calculate_dp(i - 1, j - 3)
            ) / 4.0
            return dp[i][j]

        for k in range(1, m + 1):
            if calculate_dp(k, k) > 1 - 1e-5:
                return 1.0
        return calculate_dp(m, m)

4.7.761 - 2025-08-07 17:57:34 +0300 MSK

Bank Account Summary II
SELECT
    Users.name AS "NAME",
    SUM(Transactions.amount) AS "BALANCE"
FROM
    Users
LEFT JOIN
    Transactions
ON
    Users.account = Transactions.account
GROUP BY
    Users.account, Users.name
HAVING
    SUM(Transactions.amount) > 10000

4.7.762 - 2025-08-07 17:15:08 +0300 MSK

Find the Maximum Number of Fruits Collected
class Solution:
    def maxCollectedFruits(self, fruits):
        n = len(fruits)
        ans = sum(fruits[i][i] for i in range(n))

        def dp():
            prev = [float("-inf")] * n
            curr = [float("-inf")] * n
            prev[n - 1] = fruits[0][n - 1]
            for i in range(1, n - 1):
                for j in range(max(n - 1 - i, i + 1), n):
                    best = prev[j]
                    if j - 1 >= 0:
                        best = max(best, prev[j - 1])
                    if j + 1 < n:
                        best = max(best, prev[j + 1])
                    curr[j] = best + fruits[i][j]
                prev, curr = curr, prev
            return prev[n - 1]

        ans += dp()

        for i in range(n):
            for j in range(i):
                fruits[i][j], fruits[j][i] = fruits[j][i], fruits[i][j]

        ans += dp()
        return ans

4.7.763 - 2025-08-06 19:26:47 +0300 MSK

Customer Who Visited but Did Not Make Any Transactions
SELECT
    Visits.customer_id,
    COUNT(Visits.visit_id) AS "count_no_trans"
FROM
    Visits
LEFT JOIN
    Transactions
ON
    Visits.visit_id = Transactions.visit_id
WHERE
    Transactions.visit_id IS NULL
GROUP BY
    Visits.customer_id

4.7.764 - 2025-08-06 16:17:09 +0300 MSK

Fruits Into Baskets III
class Solution:
    def numOfUnplacedFruits(self, fruits: List[int], baskets: List[int]) -> int:
        length = len(baskets)
        section_length = int(math.sqrt(length))
        sections = (length + section_length - 1) // section_length
        count = 0
        sections_max = [0] * sections
        for i in range(length):
            section = i // section_length
            sections_max[section] = max(sections_max[section], baskets[i])
        for fruit in fruits:
            unset = 1
            for section in range(sections):
                if sections_max[section] < fruit:
                    continue
                choose = 0
                sections_max[section] = 0
                for i in range(section_length):
                    pos = section * section_length + i
                    if pos < length and baskets[pos] >= fruit and not choose:
                        baskets[pos] = 0
                        choose = 1
                    if pos < length:
                        sections_max[section] = max(sections_max[section], baskets[pos])
                unset = 0
                break
            count += unset
        return count

4.7.765 - 2025-08-05 20:11:10 +0300 MSK

Fruits Into Baskets II
class Solution:
    def numOfUnplacedFruits(self, fruits: List[int], baskets: List[int]) -> int:
        count = 0
        length = len(baskets)
        for fruit in fruits:
            unset = 1
            for i in range(length):
                if fruit <= baskets[i]:
                    baskets[i] = 0
                    unset = 0
                    break
            count += unset
        return count

4.7.766 - 2025-08-04 19:06:02 +0300 MSK

Fruit Into Baskets
class Solution:
    def totalFruit(self, fruits: list[int]) -> int:
        start = 0
        max_len = 0
        fruit_count = defaultdict(int)

        for end in range(len(fruits)):
            fruit_count[fruits[end]] += 1

            while len(fruit_count) > 2:
                fruit_count[fruits[start]] -= 1
                if fruit_count[fruits[start]] == 0:
                    del fruit_count[fruits[start]]
                start += 1

            max_len = max(max_len, end - start + 1)

        return max_len

4.7.767 - 2025-08-03 16:36:16 +0300 MSK

Replace All ?’s to Avoid Consecutive Repeating Characters
class Solution:
    def modifyString(self, s: str) -> str:
        res = list(s)
        length = len(s)

        for i in range(length):
            char = res[i]
            if char != "?":
                continue
            for char_ascii in string.ascii_lowercase:
                if (
                    (i > 0 and res[i - 1] == char_ascii) 
                    or (i < length - 1 and res[i + 1] == char_ascii)
                ):
                    continue
                res[i] = char_ascii
                break
        return "".join(res)

4.7.768 - 2025-08-03 16:21:01 +0300 MSK

Matrix Diagonal Sum
class Solution:
    def diagonalSum(self, mat: List[List[int]]) -> int:
        length = len(mat)
        res = 0
        for i in range(length):
            row1, col1 = i, i
            row2, col2 = i, length - i - 1
            res += mat[row1][col1]
            if row2 != row1 or col2 != col1:
                res += mat[row2][col2]
        return res

4.7.769 - 2025-08-03 16:03:54 +0300 MSK

Detect Pattern of Length M Repeated K or More Times
class Solution:
    def containsPattern(self, arr: List[int], m: int, k: int) -> bool:
        length = len(arr)
        if length < m * k:
            return False
        for i in range(length - m + 1):
            cur_pat = arr[i:i+m]
            count = 1
            for j in range(i + m, length, m):
                if arr[j:j+m] == cur_pat:
                    count += 1
                else:
                    break
            if count >= k:
                return True
        return False

4.7.770 - 2025-08-03 15:13:16 +0300 MSK

Most Visited Sector in a Circular Track
class Solution:
    def mostVisited(self, n: int, rounds: List[int]) -> List[int]:
        start_sector, end_sector = rounds[0], rounds[-1]

        if start_sector <= end_sector:
            return tuple(range(start_sector, end_sector + 1))
            
        return tuple(
            itertools.chain(
                range(1, end_sector + 1),
                range(start_sector, n + 1)
            )
        )

4.7.771 - 2025-08-03 15:01:18 +0300 MSK

Thousand Separator
class Solution:
    def thousandSeparator(self, n: int) -> str:
        if n < 1000:
            return str(n)
        res = []
        count = 0
        while n > 0:
            res.append(str(n % 10))
            count += 1
            n //= 10
            if count % 3 == 0 and n > 0:
                res.append(".")
        res.reverse()
        return "".join(res)

4.7.772 - 2025-08-03 14:57:57 +0300 MSK

Three Consecutive Odds
class Solution:
    def threeConsecutiveOdds(self, arr: List[int]) -> bool:
        count = 0
        for num in arr:
            if num % 2 == 0:
                count = 0
            else:
                count += 1
            if count == 3:
                return True
        return False

4.7.773 - 2025-08-03 14:56:16 +0300 MSK

Kth Missing Positive Number
class Solution:
    def findKthPositive(self, arr: List[int], k: int) -> int:
        prev = 0
        for num in arr:
            diff = num - prev - 1
            if k > diff:
                k -= diff
            else:
                return prev + k
            prev = num
        return prev + k

4.7.774 - 2025-08-03 14:39:49 +0300 MSK

Shuffle String
class Solution:
    def restoreString(self, s: str, indices: List[int]) -> str:
        res = [None] * len(s)
        for i, char in zip(indices, s):
            res[i] = char
        return "".join(res)

4.7.775 - 2025-08-03 14:36:46 +0300 MSK

Patients With a Condition
SELECT
    Patients.patient_id,
    Patients.patient_name,
    Patients.conditions
FROM
    Patients
WHERE
    Patients.conditions ~ '(^|\s)DIAB1'

4.7.776 - 2025-08-03 14:33:50 +0300 MSK

Water Bottles
class Solution:
    def numWaterBottles(self, numBottles: int, numExchange: int) -> int:
        res = 0
        empty = 0
        while numBottles > 0:
            res += numBottles
            empty += numBottles
            numBottles = empty // numExchange
            empty %= numExchange
        return res

4.7.777 - 2025-08-03 14:29:35 +0300 MSK

Find Users With Valid E-Mails
SELECT 
    *
FROM 
    Users
WHERE 
    Users.mail ~ '^[a-zA-Z][a-zA-Z0-9\.\-_]*@leetcode\.com$';

4.7.778 - 2025-08-03 14:27:36 +0300 MSK

Reformat Date
class Solution:
    def reformatDate(self, date: str) -> str:
        day_str, mnth_str, year_str = date.split()
        if len(day_str) == 3:
            day = int(day_str[0:1])
        else:
            day = int(day_str[0:2])
        mnth = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"].index(mnth_str) + 1
        year = int(year_str)
        return f"{year}-{mnth:02}-{day:02}"

4.7.779 - 2025-08-03 14:18:22 +0300 MSK

Can Make Arithmetic Progression From Sequence
class Solution:
    def canMakeArithmeticProgression(self, arr: List[int]) -> bool:
        arr.sort()
        diff = abs(arr[0] - arr[1])
        for i in range(1, len(arr) - 1):
            if abs(arr[i] - arr[i+1]) != diff:
                return False
        return True

4.7.780 - 2025-08-03 14:14:27 +0300 MSK

Group Sold Products By The Date
SELECT 
    Activities.sell_date, 
    COUNT(
        DISTINCT (Activities.product, Activities.sell_date)
    ) AS num_sold, 
    STRING_AGG(
        DISTINCT Activities.product, ',' ORDER BY product
    ) AS products
FROM 
    Activities
GROUP BY 
    Activities.sell_date
ORDER BY 
    Activities.sell_date;

4.7.781 - 2025-08-03 13:56:55 +0300 MSK

Final Prices With a Special Discount in a Shop
class Solution:
    def finalPrices(self, prices: List[int]) -> List[int]:
        stack = deque()
        for i in range(len(prices)):
            price = prices[i]
            while True:
                if not stack:
                    break
                last_i, last_price = stack[-1]
                if last_price >= price:
                    prices[last_i] -= price
                    stack.pop()
                else:
                    break
            stack.append((i, price))
        return prices

4.7.782 - 2025-08-03 13:42:44 +0300 MSK

Shuffle the Array
class Solution:
    def shuffle(self, nums: List[int], n: int) -> List[int]:
        res = []
        for j in range(n, 2 * n):
            res.extend((nums[j - n], nums[j]))
        return res

4.7.783 - 2025-08-03 13:35:23 +0300 MSK

Make Two Arrays Equal by Reversing Subarrays
class Solution:
    def canBeEqual(self, target: List[int], arr: List[int]) -> bool:
        freqs = defaultdict(int)
        length = len(target)
        if length != len(arr):
            return False
        for i in range(length):
            freqs[target[i]] += 1
            freqs[arr[i]] -= 1
        for count in freqs.values():
            if count != 0:
                return False
        return True

4.7.784 - 2025-08-03 13:30:55 +0300 MSK

Check If a Word Occurs As a Prefix of Any Word in a Sentence
class Solution:
    def isPrefixOfWord(self, sentence: str, searchWord: str) -> int:
        for i, word in enumerate(sentence.split()):
            if word.startswith(searchWord):
                return i + 1
        return -1

4.7.785 - 2025-08-03 13:25:11 +0300 MSK

Consecutive Characters
class Solution:
    def maxPower(self, s: str) -> int:
        prev = s[0]
        count = 1
        max_count= 1
        for char in s[1:]:
            if char == prev:
                count += 1
                max_count = max(max_count, count)
            else:
                count = 1
                prev = char
        return max_count

4.7.786 - 2025-08-03 13:22:53 +0300 MSK

Check If All 1’s Are at Least Length K Places Away
class Solution:
    def kLengthApart(self, nums: List[int], k: int) -> bool:
        prev = -k - 1
        for i, num in enumerate(nums):
            if num == 0:
                continue
            if i - prev - 1 >= k:
                prev = i
            else:
                return False
        return True

4.7.787 - 2025-08-03 13:19:10 +0300 MSK

Reformat The String
class Solution:
    def reformat(self, s: str) -> str:
        res, digits, al = [""], [], []
        for char in s:
            if char.isalpha():
                al.append(char)
            else:
                digits.append(char)
            while digits and al:
                res.extend((digits.pop(), al.pop()))
        if digits:
            res.append(digits.pop())
        elif al:
            res[0] = al.pop()
        if digits or al:
            return ""
        return "".join(res)

4.7.788 - 2025-08-03 11:38:37 +0300 MSK

Minimum Value to Get Positive Step by Step Sum
class Solution:
    def minStartValue(self, nums: List[int]) -> int:
        min_sum = float('inf')
        cur_sum = 0
        for num in nums:
            cur_sum += num
            min_sum = min(min_sum, cur_sum)
        return max(1 - min_sum, 1)

4.7.789 - 2025-08-03 10:42:15 +0300 MSK

String Matching in an Array
class Solution:

    class TrieNode:
        def __init__(self):
            # Tracks how many times this substring appears in the Trie.
            self.frequency = 0
            # Maps characters to their respective child nodes.
            self.child_nodes = {}

    def stringMatching(self, words: List[str]) -> List[str]:
        matching_words = []
        root = self.TrieNode()  # Initialize the root of the Trie.

        # Insert all suffixes of each word into the Trie.
        for word in words:
            for start_index in range(len(word)):
                # Insert each suffix starting from index start_index.
                self._insert_word(root, word[start_index:])

        # Check each word to see if it exists as a substring in the Trie.
        for word in words:
            if self._is_substring(root, word):
                matching_words.append(word)

        return matching_words

    def _insert_word(self, root: "TrieNode", word: str) -> None:
        current_node = root
        for char in word:
            if char not in current_node.child_nodes:
                # Create a new node if the character does not exist.
                current_node.child_nodes[char] = self.TrieNode()
            current_node = current_node.child_nodes[char]
            current_node.frequency += 1  # Increment the frequency of the node.

    def _is_substring(self, root: "TrieNode", word: str) -> bool:
        current_node = root
        for char in word:
            # Traverse the Trie following the characters of the word.
            current_node = current_node.child_nodes[char]
        # A word is a substring if its frequency in the Trie is greater than 1.
        return current_node.frequency > 1

4.7.790 - 2025-08-03 10:26:28 +0300 MSK

Maximum Fruits Harvested After at Most K Steps
class Solution:
    def maxTotalFruits(
        self, fruits: List[List[int]], startPos: int, k: int
    ) -> int:
        n = len(fruits)
        sum_ = [0] * (n + 1)
        indices = [0] * n

        for i in range(n):
            sum_[i + 1] = sum_[i] + fruits[i][1]
            indices[i] = fruits[i][0]

        ans = 0
        for x in range(k // 2 + 1):
            # move left x steps, then right (k - 2x) steps
            y = k - 2 * x
            left = startPos - x
            right = startPos + y
            start = bisect_left(indices, left)
            end = bisect_right(indices, right)
            ans = max(ans, sum_[end] - sum_[start])

            # move right x steps, then left (k - 2x) steps
            y = k - 2 * x
            left = startPos - y
            right = startPos + x
            start = bisect_left(indices, left)
            end = bisect_right(indices, right)
            ans = max(ans, sum_[end] - sum_[start])

        return ans

4.7.791 - 2025-08-02 20:09:46 +0300 MSK

Top Travellers
SELECT
    Users.name, 
    COALESCE(SUM(Rides.distance), 0) AS "travelled_distance"
FROM
    Users
LEFT JOIN
    Rides
ON
    Users.id = Rides.user_id
GROUP BY
    Users.id, Users.name
ORDER BY
    travelled_distance DESC,
    Users.name ASC

4.7.792 - 2025-08-02 20:03:30 +0300 MSK

Minimum Subsequence in Non-Increasing Order
class Solution:
    def minSubsequence(self, nums: List[int]) -> List[int]:
        max_sum = sum(nums)
        nums.sort(reverse=True)
        cur_sum = 0
        res = []
        for num in nums:
            cur_sum += num
            res.append(num)
            if cur_sum > max_sum - cur_sum:
                break
        return res

4.7.793 - 2025-08-02 19:58:48 +0300 MSK

Count Largest Group
class Solution:
    def countLargestGroup(self, n: int) -> int:
        freqs = defaultdict(int)
        def count(num: int) -> int:
            res = 0
            while num > 0:
                res += num % 10
                num //= 10
            return res
        max_freq = 0
        for i in range(1, n + 1):
            group = count(i)
            freq = freqs[group] + 1
            freqs[group] = freq
            if freq > max_freq:
                max_freq = freq
        res = 0
        for freq in freqs.values():
            if freq == max_freq:
                res += 1
        return res

4.7.794 - 2025-08-02 19:54:21 +0300 MSK

Find Lucky Integer in an Array
class Solution:
    def findLucky(self, arr: List[int]) -> int:
        freqs = defaultdict(int)
        for num in arr:
            freqs[num] += 1
        max_num = -1
        for num, freq in freqs.items():
            if num == freq:
                max_num = max(max_num, num)
        return max_num

4.7.795 - 2025-08-02 19:50:44 +0300 MSK

Create Target Array in the Given Order
class Solution:
    def createTargetArray(self, nums: List[int], index: List[int]) -> List[int]:
        res = []
        for i, num in zip(index, nums):
            res.insert(i, num)
        return res

4.7.796 - 2025-08-02 19:45:12 +0300 MSK

Lucky Numbers in a Matrix
class Solution:
    def luckyNumbers(self, matrix: List[List[int]]) -> List[int]:
        rows = len(matrix)
        cols = len(matrix[0])
        min_row = float("-inf")
        max_col = float("inf")
        for row in range(rows):
            min_row = max(min_row, min(matrix[row]))
        for col in range(cols):
            cur_max_col = float("-inf")
            for row in range(rows):
                cur_max_col = max(cur_max_col, matrix[row][col])
            max_col = min(max_col, cur_max_col)
        if min_row == max_col:
            return [min_row]
        return []

4.7.797 - 2025-08-02 19:36:06 +0300 MSK

Lucky Numbers in a Matrix
class Solution:
    def luckyNumbers(self, matrix: List[List[int]]) -> List[int]:
        rows = len(matrix)
        cols = len(matrix[0])
        min_row = [None] * rows
        max_col = [None] * cols
        for row in range(rows):
            min_row[row] = min(matrix[row])
        for col in range(cols):
            num_max = float("-inf")
            for row in range(rows):
                num = matrix[row][col]
                if num > num_max:
                    num_max = num
            max_col[col] = num_max
        res = []
        for row in range(rows):
            for col in range(cols):
                num = matrix[row][col]
                if num == min_row[row] and num == max_col[col]:
                    res.append(num)
        return res

4.7.798 - 2025-08-02 19:28:39 +0300 MSK

Replace Employee ID With The Unique Identifier
SELECT
    EmployeeUNI.unique_id, Employees.name
FROM
    Employees
LEFT JOIN
    EmployeeUNI
ON
    Employees.id = EmployeeUNI.id

4.7.799 - 2025-08-02 19:24:42 +0300 MSK

Generate a String With Characters That Have Odd Counts
class Solution:
    def generateTheString(self, n: int) -> str:
        if n % 2 == 0:
            return ("a" * (n - 1)) + "b"
        return "a" * n

4.7.800 - 2025-08-02 19:22:20 +0300 MSK

Increasing Decreasing String
class Solution:
    def sortString(self, s: str) -> str:
        freqs = defaultdict(int)
        for char in s:
            freqs[char] += 1
        keys = list(freqs.keys())
        keys.sort(key = ord)
        length = len(keys)
        res = []
        while freqs:
            for i in itertools.chain(range(length), reversed(range(length))):
                key = keys[i]
                if key not in freqs:
                    continue
                res.append(key)
                freqs[key] -= 1
                if freqs[key] == 0:
                    freqs.pop(key)
        return "".join(res)

4.7.801 - 2025-08-02 19:12:42 +0300 MSK

How Many Numbers Are Smaller Than the Current Number
class Solution:
    def smallerNumbersThanCurrent(self, nums: List[int]) -> List[int]:
        num_to_count = {}
        for i, num in enumerate(sorted(nums)):
            if num not in num_to_count:
                num_to_count[num] = i
        for i in range(len(nums)):
            nums[i] = num_to_count[nums[i]]
        return nums

4.7.802 - 2025-08-02 19:08:24 +0300 MSK

Number of Days Between Two Dates
class Solution:
    def daysBetweenDates(self, date1: str, date2: str) -> int:
        year1, month1, day1 = map(int, date1.split('-'))
        year2, month2, day2 = map(int, date2.split('-'))
        date1 = datetime.date(year1, month1, day1)
        date2 = datetime.date(year2, month2, day2) 
        return abs((date2 - date1).days)

4.7.803 - 2025-08-02 18:59:52 +0300 MSK

Check If N and Its Double Exist
class Solution:
    def checkIfExist(self, arr: List[int]) -> bool:
        enc = set()
        for num in arr:
            if num == 0 and 0 in enc:
                return True
            if num % 2 == 0 and num // 2 in enc:
                return True
            if num * 2 in enc:
                return True
            enc.add(num)
        return False

4.7.804 - 2025-08-02 18:49:48 +0300 MSK

Remove Palindromic Subsequences
class Solution:
    def removePalindromeSub(self, s: str) -> int:
        if s == s[::-1]:
            return 1
        return 2

4.7.805 - 2025-08-02 18:45:57 +0300 MSK

Rank Transform of an Array
class Solution:
    def arrayRankTransform(self, arr: List[int]) -> List[int]:
        num_to_rank = defaultdict(int)
        nums = sorted(set(arr))
        for rank, num in enumerate(nums, 1):
            num_to_rank[num] = rank
        for i in range(len(arr)):
            arr[i] = num_to_rank[arr[i]]
        return arr

4.7.806 - 2025-08-02 18:40:13 +0300 MSK

Rank Transform of an Array
class Solution:
    def arrayRankTransform(self, arr: List[int]) -> List[int]:
        ind = defaultdict(list)
        for i, num in enumerate(arr):
            ind[num].append(i)
        for rank, num in enumerate(sorted(ind.keys()), 1):
            for i in ind[num]:
                arr[i] = rank
        return arr

4.7.807 - 2025-08-02 18:33:48 +0300 MSK

List the Products Ordered in a Period
SELECT 
    Products.product_name, SUM(Orders.unit) as "unit"
FROM 
    Products
JOIN 
    Orders
ON 
    Orders.product_id = Products.product_id
WHERE 
    Orders.order_date BETWEEN '2020-02-01' AND '2020-02-29'
GROUP BY 
    Products.product_name
HAVING 
    SUM(Orders.unit) >= 100;

4.7.808 - 2025-08-02 18:22:51 +0300 MSK

Maximum 69 Number
class Solution:
    def maximum69Number(self, num: int) -> int:
        digits = []
        while num > 0:
            digits.append(num % 10)
            num //= 10
        digits.reverse()
        res = 0
        enc = False
        length = len(digits)
        for i, digit in enumerate(digits):
            if digit == 6 and not enc:
                digit = 9
                enc = True
            res += (10 ** (length - i - 1)) * digit
        return res

4.7.809 - 2025-08-02 18:14:37 +0300 MSK

Convert Integer to the Sum of Two No-Zero Integers
class Solution:
    def getNoZeroIntegers(self, n: int) -> List[int]:
        if n <= 10:
            return [1, n - 1]
        def check(num: int) -> bool:
            while num > 0:
                if num % 10 == 0:
                    return False
                num //= 10
            return True
        for i in range(1, (n + 1) // 2):
            num1, num2 = i, n - i
            if check(num1) and check(num2):
                return [num1, num2]
        raise Exception

4.7.810 - 2025-08-02 18:07:54 +0300 MSK

Decompress Run-Length Encoded List
class Solution:
    def decompressRLElist(self, nums: List[int]) -> List[int]:
        res = []
        i = 0
        length = len(nums)
        while i < length:
            freq, val = nums[i], nums[i + 1]
            i += 2
            res.extend((val, ) * freq)
        return res

4.7.811 - 2025-08-02 18:04:04 +0300 MSK

Decrypt String from Alphabet to Integer Mapping
class Solution:
    def freqAlphabets(self, s: str) -> str:
        res = []
        length = len(s)
        i = 0
        while i < length:
            if i + 2 <  length and s[i + 2] == "#":
                res.append(chr(int(s[i:i+2]) + 97 - 1))
                i += 3
            else:
                res.append(chr(int(s[i]) + 97 - 1))
                i += 1
        return "".join(res)

4.7.812 - 2025-08-02 17:59:03 +0300 MSK

Find N Unique Integers Sum up to Zero
class Solution:
    def sumZero(self, n: int) -> List[int]:
        if n == 1:
            return [0]
        res = []
        if n % 2 != 0:
            res.append(0)
            n -= 1
        for i in range(1, (n // 2) + 1):
            res.extend((i, -i))
        return res

4.7.813 - 2025-08-02 17:54:14 +0300 MSK

Replace Elements with Greatest Element on Right Side
class Solution:
    def replaceElements(self, arr: List[int]) -> List[int]:
        greatest = -1
        for i in reversed(range(len(arr))):
            current = arr[i]
            arr[i] = greatest
            if current > greatest:
                greatest = current
        return arr

4.7.814 - 2025-08-02 17:28:54 +0300 MSK

Find Numbers with Even Number of Digits
class Solution:
    def findNumbers(self, nums: List[int]) -> int:
        def count(num: int) -> int:
            res = 0
            while num:
                res += 1
                num //= 10
            return res
        res = 0
        for num in nums:
            if count(num) % 2 == 0:
                res += 1
        return res

4.7.815 - 2025-08-02 17:26:28 +0300 MSK

Convert Binary Number in a Linked List to Integer
# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:
    def getDecimalValue(self, head: Optional[ListNode]) -> int:
        res = 0
        while head:
            res <<= 1
            res |= head.val
            head = head.next
        return res

4.7.816 - 2025-08-02 17:24:46 +0300 MSK

Students and Examinations
SELECT
    Students.student_id, 
    Students.student_name,
    Subjects.subject_name,
    COUNT(Examinations.subject_name) as "attended_exams"
FROM
    Students
CROSS JOIN
    Subjects
LEFT JOIN
    Examinations
ON
    Students.student_id = Examinations.student_id
    AND Subjects.subject_name = Examinations.subject_name
GROUP BY
    Students.student_id, 
    Students.student_name, 
    Subjects.subject_name
ORDER BY
    Students.student_id, 
    Subjects.subject_name

4.7.817 - 2025-08-02 17:06:00 +0300 MSK

Find Winner on a Tic Tac Toe Game
class Solution:
    def tictactoe(self, moves: List[List[int]]) -> str:
        cols = [[0] * 3 for _ in range(2)]
        rows = [[0] * 3 for _ in range(2)]
        diags = [[0] * 2 for _ in range(2)]
        players = ["A", "B"]
        for i, (row, col) in enumerate(moves):
            if i % 2 == 0:
                player = 0
            else:
                player = 1
            rows[player][row] += 1
            cols[player][col] += 1
            if row == col:
                diags[player][0] += 1
            if row == 2 - col:
                diags[player][1] += 1
        for player in range(2):
            for win in (cols, rows, diags):
                if 3 in win[player]:
                    return players[player]
        if len(moves) == 9:
            return "Draw"
        return "Pending"

4.7.818 - 2025-08-02 16:50:59 +0300 MSK

Shift 2D Grid
class Solution:
    def shiftGrid(self, grid: List[List[int]], k: int) -> List[List[int]]:
        if not grid or not grid[0]:
            return grid
        
        row_length = len(grid)
        col_length = len(grid[0])
        num_count = row_length * col_length
        k %= num_count
        res = [[0] * col_length for _ in range(row_length)]
        
        for row in range(row_length):
            for col in range(col_length):
                flat_mat_index = (row * col_length) + col
                new_flat_mat_index = (flat_mat_index + k) % num_count
                new_row = new_flat_mat_index // col_length
                new_col = new_flat_mat_index % col_length
                res[new_row][new_col] = grid[row][col]
        return res

4.7.819 - 2025-08-02 16:38:17 +0300 MSK

Cells with Odd Values in a Matrix
class Solution:
    def oddCells(self, m: int, n: int, indices: List[List[int]]) -> int:
        mat = [[0] * n for _ in range(m)]
        for row, col in indices:
            for cur_col in range(n):
                mat[row][cur_col] += 1
            for cur_row in range(m):
                mat[cur_row][col] += 1
        count = 0
        for row in range(m):
            for col in range(n):
                if mat[row][col] % 2 != 0:
                    count += 1
        return count

4.7.820 - 2025-08-02 16:29:04 +0300 MSK

Rearranging Fruits
class Solution:
    def minCost(self, basket1: List[int], basket2: List[int]) -> int:
        freq = Counter()
        m = float("inf")
        for b1 in basket1:
            freq[b1] += 1
            m = min(m, b1)
        for b2 in basket2:
            freq[b2] -= 1
            m = min(m, b2)

        merge = []
        for k, c in freq.items():
            if c % 2 != 0:
                return -1
            merge.extend([k] * (abs(c) // 2))

        if not merge:
            return 0
        merge.sort()
        return sum(min(2 * m, x) for x in merge[: len(merge) // 2])

4.7.821 - 2025-08-02 16:25:49 +0300 MSK

Average Selling Price
SELECT 
    Prices.product_id,
    CASE
        WHEN 
            SUM(UnitsSold.units) is null
        THEN 
            0
        ELSE
            ROUND(SUM(UnitsSold.units * Prices.price) / SUM(UnitsSold.units)::numeric, 2)
    END AS average_price
FROM 
    Prices
LEFT JOIN 
    UnitsSold
ON 
    UnitsSold.product_id = Prices.product_id 
    AND UnitsSold.purchase_date 
        BETWEEN Prices.start_date AND Prices.end_date
GROUP BY 
    Prices.product_id;

4.7.822 - 2025-08-02 16:11:25 +0300 MSK

Check If It Is a Straight Line
class Solution:
    def checkStraightLine(self, coordinates: List[List[int]]) -> bool:
        x1, y1 = coordinates[0]
        x2, y2 = coordinates[1]
        for x3, y3 in coordinates[2:]:
            if (x3 - x1) * (y2 - y1) != (x2 - x1) * (y3 - y1):
                return False
        return True

4.7.823 - 2025-08-02 16:04:47 +0300 MSK

Split a String in Balanced Strings
class Solution:
    def balancedStringSplit(self, s: str) -> int:
        count_l, count_r = 0, 0
        count = 0
        for char in s:
            if char == "R":
                count_r += 1
            else:
                count_l += 1
            if count_l == count_r:
                count += 1
        return count
            

4.7.824 - 2025-08-02 15:56:06 +0300 MSK

Minimum Cost to Move Chips to The Same Position
class Solution:
    def minCostToMoveChips(self, position: List[int]) -> int:
        length = len(position)
        odd, even = 0, 0
        for pos in position:
            if pos % 2 == 0:
                even += 1
            else:
                odd += 1
        return min(odd, even)

4.7.825 - 2025-08-02 15:46:47 +0300 MSK

Queries Quality and Percentage
SELECT 
    query_name,  
    ROUND(SUM(rating * 1.0 / position) / COUNT(*), 2) AS quality,
    ROUND(
        COUNT(CASE WHEN rating < 3 THEN 1 END) * 1.0 / COUNT(*), 
        4
    ) * 100 AS poor_query_percentage
FROM 
    Queries
GROUP BY 
    query_name;

4.7.826 - 2025-08-02 15:43:09 +0300 MSK

Minimum Absolute Difference
class Solution:
    def minimumAbsDifference(self, arr: List[int]) -> List[List[int]]:
        arr.sort()
        min_diff = float("inf")
        res = []
        for i, num in enumerate(arr[:-1]):
            nxt = arr[i + 1]
            diff = abs(nxt - num)
            if diff < min_diff:
                res.clear()
                res.append((num, nxt))
                min_diff = diff
            elif diff == min_diff:
                res.append((num, nxt))
        return res

4.7.827 - 2025-08-02 15:41:03 +0300 MSK

Minimum Absolute Difference
class Solution:
    def minimumAbsDifference(self, arr: List[int]) -> List[List[int]]:
        arr.sort()
        min_diff = float("inf")
        diffs = defaultdict(list)
        for i, num in enumerate(arr[:-1]):
            nxt = arr[i + 1]
            diff = abs(nxt - num)
            diffs[diff].append((num, nxt))
            min_diff = min(min_diff, diff)
        return diffs[min_diff]

4.7.828 - 2025-08-02 15:39:53 +0300 MSK

Minimum Absolute Difference
class Solution:
    def minimumAbsDifference(self, arr: List[int]) -> List[List[int]]:
        arr.sort()
        min_diff = float("inf")
        res = []
        for i, num in enumerate(arr[:-1]):
            nxt = arr[i + 1]
            diff = abs(nxt - num)
            min_diff = min(min_diff, diff)
        for i, num in enumerate(arr[:-1]):
            nxt = arr[i + 1]
            diff = abs(nxt - num)
            if diff == min_diff:
                res.append((num, nxt))
        return res

4.7.829 - 2025-08-02 15:34:16 +0300 MSK

Maximum Number of Balloons
class Solution:
    def maxNumberOfBalloons(self, text: str) -> int:
        freqs = defaultdict(int)
        for char in text:
            freqs[char] += 1
        res = min(
            freqs["b"],
            freqs["a"],
            freqs["l"] // 2,
            freqs["o"] // 2,
            freqs["n"]
        )
        return res

4.7.830 - 2025-08-02 15:27:49 +0300 MSK

Day of the Week
class Solution:
    def dayOfTheWeek(self, day: int, month: int, year: int) -> str:
        return [
            "Monday", "Tuesday", "Wednesday", 
            "Thursday", "Friday", "Saturday", 
            "Sunday"
        ][datetime.date(year, month, day).weekday()]

4.7.831 - 2025-08-02 15:19:46 +0300 MSK

Distance Between Bus Stops
class Solution:
    def distanceBetweenBusStops(self, distance: List[int], start: int, destination: int) -> int:
        length = len(distance)
        forward_dist, back_dist = 0, 0
        forward, back = start, start
        while True:
            if forward == destination:
                return forward_dist
            if back == destination or length + back == destination:
                return back_dist
            forward_dist += distance[forward]
            forward = (forward + 1) % length
            back_dist += distance[back - 1]
            back -= 1
        raise Exception

4.7.832 - 2025-08-02 15:01:25 +0300 MSK

Reformat Department Table
SELECT id,
        SUM(
            CASE 
                WHEN 
                    month = 'Jan' 
                THEN 
                    revenue 
                ELSE 
                    NULL 
            END
        ) AS Jan_Revenue,
        SUM(
            CASE 
                WHEN 
                    month = 'Feb' 
                THEN 
                    revenue 
                ELSE 
                    NULL 
                END
        ) AS Feb_Revenue,
        SUM(
            CASE 
                WHEN 
                    month = 'Mar' 
                THEN 
                    revenue 
                ELSE 
                    NULL 
                END
        ) AS Mar_Revenue,
        SUM(
            CASE 
                WHEN 
                    month = 'Apr' 
                THEN 
                    revenue 
                ELSE 
                    NULL 
                END
        ) AS Apr_Revenue,
        SUM(
            CASE 
                WHEN 
                    month = 'May' 
                THEN 
                    revenue 
                ELSE 
                    NULL 
                END
        ) AS May_Revenue,
        SUM(
            CASE 
                WHEN 
                    month = 'Jun' 
                THEN 
                    revenue 
                ELSE 
                    NULL 
                END
        ) AS Jun_Revenue,
        SUM(
            CASE 
                WHEN 
                    month = 'Jul'
                THEN 
                    revenue 
                ELSE 
                    NULL 
                END
        ) AS Jul_Revenue,
        SUM(
            CASE 
                WHEN 
                    month = 'Aug'
                THEN 
                    revenue 
                ELSE 
                    NULL
                END
        ) AS Aug_Revenue,
        SUM(
            CASE 
                WHEN 
                    month = 'Sep' 
                THEN 
                    revenue 
                ELSE 
                    NULL 
                END
        ) AS Sep_Revenue,
        SUM(
            CASE 
                WHEN 
                    month = 'Oct' 
                THEN 
                    revenue 
                ELSE 
                    NULL 
            END
        ) AS Oct_Revenue,
        SUM(
            CASE 
                WHEN 
                    month = 'Nov' 
                THEN 
                    revenue 
                ELSE 
                    NULL 
            END
        ) AS Nov_Revenue,
        SUM(
            CASE 
                WHEN 
                    month = 'Dec' 
                THEN 
                    revenue 
                ELSE 
                    NULL 
            END
        ) AS Dec_Revenue
FROM 
    Department
GROUP BY 
    id;

4.7.833 - 2025-08-02 14:54:02 +0300 MSK

Prime Arrangements
class Solution:
    def numPrimeArrangements(self, n: int) -> int:
        prime = [True] * (n + 1)
        prime[0] = prime[1] = False
        for i in range(2, int(n ** 0.5) + 1):
            if not prime[i]:
                continue
            for j in range(i * i, n + 1, i):
                prime[j] = False
                    
        prime_count = sum(prime)
        mod = 10**9 + 7
        fact_primes = math.factorial(prime_count)
        fact_norm = math.factorial(n - prime_count)
        return (fact_primes * fact_norm) % mod

        

4.7.834 - 2025-08-02 14:25:28 +0300 MSK

Day of the Year
class Solution:
    def dayOfYear(self, date: str) -> int:
        year, month, day = map(int, date.split('-'))
        days_in_month = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
        if (year % 4 == 0 and year % 100 != 0) or (year % 400 == 0):
            days_in_month[1] = 29
        day_number = sum(days_in_month[:month - 1]) + day
        return day_number

4.7.835 - 2025-08-02 14:21:50 +0300 MSK

Article Views I
SELECT DISTINCT
    views1.author_id as "id"
FROM
    Views views1
CROSS JOIN
    Views views2
WHERE
    views1.author_id = views2.viewer_id
    AND views1.author_id = views2.author_id
ORDER BY
    views1.author_id ASC

4.7.836 - 2025-08-02 14:15:20 +0300 MSK

User Activity for the Past 30 Days I
SELECT 
    activity_date AS day, 
    COUNT(DISTINCT(user_id)) AS active_users  
FROM 
    Activity 
WHERE 
    activity_date 
        BETWEEN '2019-07-27'::DATE - INTERVAL '29 DAYS' 
        AND '2019-07-27'::DATE
GROUP BY 
    activity_date

4.7.837 - 2025-08-02 14:10:21 +0300 MSK

Number of Equivalent Domino Pairs
class Solution:
    def numEquivDominoPairs(self, dominoes: List[List[int]]) -> int:
        freqs = [0] * 100
        res = 0
        for num1, num2 in dominoes:
            if num1 > num2:
                val = num1 * 10 + num2
            else:
                val = num2 * 10 + num1
            res += freqs[val]
            freqs[val] += 1
        return res

4.7.838 - 2025-08-02 14:00:42 +0300 MSK

Print in Order
class Foo:
    def __init__(self):
        self._lock1 = threading.Lock()
        self._lock2 = threading.Lock()
        self._lock1.acquire()
        self._lock2.acquire()

    def first(self, printFirst: 'Callable[[], None]') -> None:
        printFirst()
        self._lock1.release()


    def second(self, printSecond: 'Callable[[], None]') -> None:
        with self._lock1:
            printSecond()
        self._lock2.release()


    def third(self, printThird: 'Callable[[], None]') -> None:
        with self._lock2:
            printThird()

4.7.839 - 2025-08-02 13:55:22 +0300 MSK

Defanging an IP Address
class Solution:
    def defangIPaddr(self, address: str) -> str:
        return address.replace(".", "[.]")

4.7.840 - 2025-08-02 13:54:26 +0300 MSK

Distribute Candies to People
class Solution:
    def distributeCandies(self, candies: int, num_people: int) -> List[int]:
        res = [0] * num_people
        i = 0
        while candies > 0:
            loss = min(i + 1, candies)
            res[i % num_people] += loss
            i += 1
            candies -= loss
        return res

4.7.841 - 2025-08-02 13:48:16 +0300 MSK

Distribute Candies to People
class Solution:
    def distributeCandies(self, candies: int, num_people: int) -> List[int]:
        res = [0] * num_people
        mult = 0
        while candies > 0:
            for i in range(num_people):
                target = min((mult * num_people) + (i + 1), candies)
                if candies > 0: 
                    res[i] += target
                    candies -= target
                else:
                    break
            mult += 1
        return res

4.7.842 - 2025-08-02 13:02:23 +0300 MSK

Duplicate Zeros
class Solution:
    def duplicateZeros(self, arr: List[int]) -> None:
        """
        Do not return anything, modify arr in-place instead.
        """

        possible_dups = 0
        length_ = len(arr) - 1

        for left in range(length_ + 1):
            if left > length_ - possible_dups:
                break
            if arr[left] == 0:
                if left == length_ - possible_dups:
                    arr[length_] = 0
                    length_ -= 1
                    break
                possible_dups += 1

        last = length_ - possible_dups
        for i in range(last, -1, -1):
            if arr[i] == 0:
                arr[i + possible_dups] = 0
                possible_dups -= 1
                arr[i + possible_dups] = 0
            else:
                arr[i + possible_dups] = arr[i]

4.7.843 - 2025-08-02 12:36:15 +0300 MSK

Duplicate Zeros
class Solution:
    def duplicateZeros(self, arr: List[int]) -> None:
        """
        Do not return anything, modify arr in-place instead.
        """
        queue = deque()
        for i in range(len(arr)):
            num = arr[i]
            if queue:
                arr[i] = queue.popleft()
                queue.append(num)
            if num == 0:
                queue.append(0)

4.7.844 - 2025-08-02 12:22:49 +0300 MSK

Sales Analysis III
SELECT 
    Product.product_id, Product.product_name
FROM 
    Sales
JOIN 
    Product 
ON 
    Product.product_id = Sales.product_id
GROUP BY 
    Product.product_id, Product.product_name
HAVING
    MIN(Sales.sale_date) >= '2019-01-01' 
    AND MAX(Sales.sale_date) <= '2019-03-31'

4.7.845 - 2025-08-02 11:12:11 +0300 MSK

Occurrences After Bigram
class Solution:
    def findOcurrences(self, text: str, first: str, second: str) -> List[str]:
        words = text.split()
        length = len(words)
        if length < 3:
            return []
        res = []
        i = 0
        while i + 2 < length:
            if words[i] == first and words[i+1] == second:
                res.append(words[i+2])
            i += 1
        return res

4.7.846 - 2025-08-02 10:56:41 +0300 MSK

Project Employees I
SELECT 
    project_id,
    ROUND(AVG(experience_years), 2) AS average_years
FROM 
    Project
JOIN 
    Employee
ON 
    Project.employee_id = Employee.employee_id
GROUP BY 
    project_id

4.7.847 - 2025-08-02 10:53:44 +0300 MSK

Project Employees I
SELECT 
    project_id,
    ROUND(AVG(experience_years), 2) AS average_years
FROM 
    Project
JOIN 
    Employee
ON 
    Project.employee_id = Employee.employee_id
GROUP BY 
    project_id

4.7.848 - 2025-08-02 10:46:44 +0300 MSK

Product Sales Analysis I
SELECT
    product_name, year, price
FROM 
    Sales
LEFT JOIN
    Product
ON
    Sales.product_id = Product.product_id

4.7.849 - 2025-08-02 10:41:17 +0300 MSK

Actors and Directors Who Cooperated At Least Three Times
SELECT 
    actor_id, director_id
FROM 
    ActorDirector
GROUP BY 
    actor_id, director_id
HAVING 
    COUNT(actor_id) >= 3;

4.7.850 - 2025-08-02 10:38:33 +0300 MSK

Remove All Adjacent Duplicates In String
class Solution:
    def removeDuplicates(self, s: str) -> str:
        stack = []
        for char in s:
            if stack and char == stack[-1]:
                stack.pop()
            else:
                stack.append(char)
        return "".join(stack)

4.7.851 - 2025-08-02 10:31:09 +0300 MSK

Last Stone Weight
class Solution:
    def lastStoneWeight(self, stones: List[int]) -> int:
        for i, num in enumerate(stones):
            stones[i] = -num
        heapq.heapify(stones)
        while stones:
            last = -heapq.heappop(stones)
            if not stones:
                return last
            prev = -heapq.heappop(stones)
            if last > prev:
                heapq.heappush(stones, -(last - prev))
        return 0

4.7.852 - 2025-08-02 10:28:21 +0300 MSK

Last Stone Weight
class Solution:
    def lastStoneWeight(self, stones: List[int]) -> int:
        stones.sort()
        while stones:
            last = stones.pop()
            if not stones:
                return last
            prev = stones[-1]
            if last == prev:
                stones.pop()
            else:
                stones[-1] = last - prev
                stones.sort()
        return 0

4.7.853 - 2025-08-02 09:19:39 +0300 MSK

Valid Boomerang
class Solution:
    def isBoomerang(self, points: List[List[int]]) -> bool:
        x1, y1 = points[0]
        x2, y2 = points[1]
        x3, y3 = points[2]
        return (y2 - y1) * (x3 - x2) != (y3 - y2) * (x2 - x1)

4.7.854 - 2025-08-02 09:15:14 +0300 MSK

Matrix Cells in Distance Order
class Solution:
    def allCellsDistOrder(self, rows: int, cols: int, rCenter: int, cCenter: int) -> List[List[int]]:
        res = []
        for row in range(rows):
            for col in range(cols):
                res.append((row, col))
        def key(point: tuple[int, int]) -> int:
            row, col = point
            return abs(row - rCenter) + abs(col - cCenter)
        res.sort(key=key) 
        return res

4.7.855 - 2025-08-02 09:11:31 +0300 MSK

Matrix Cells in Distance Order
class Solution:
    def allCellsDistOrder(self, rows: int, cols: int, rCenter: int, cCenter: int) -> List[List[int]]:
        res = []
        for row in range(rows):
            for col in range(cols):
                dist = abs(row - rCenter) + abs(col - cCenter)
                res.append((dist, row, col))
        res.sort()
        for i in range(len(res)):
            res[i] = res[i][1:] 
        return res

4.7.856 - 2025-08-02 09:03:11 +0300 MSK

Divisor Game
class Solution:
    def divisorGame(self, n: int) -> bool:
        return n % 2 == 0

4.7.857 - 2025-08-02 08:55:10 +0300 MSK

Sum of Root To Leaf Binary Numbers
# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def sumRootToLeaf(self, root: Optional[TreeNode]) -> int:
        res = 0
        queue = [(root, 0)]
        while queue:
            node, parent = queue.pop()
            if node is None:
                continue
            val = (parent << 1) | node.val
            if not node.left and not node.right:
                res += val
            queue.extend(((node.left, val), (node.right, val)))
        return res

4.7.858 - 2025-08-02 08:53:28 +0300 MSK

Sum of Root To Leaf Binary Numbers
# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def sumRootToLeaf(self, root: Optional[TreeNode]) -> int:
        def dfs(node: Optional[TreeNode], parent: int) -> int:
            if node is None:
                return 0
            cur_val = (parent << 1) | node.val
            if not node.left and not node.right:
                return cur_val
            return dfs(node.left, cur_val) + dfs(node.right, cur_val)
        return dfs(root, 0)

4.7.859 - 2025-08-02 08:48:51 +0300 MSK

Remove Outermost Parentheses
class Solution:
    def removeOuterParentheses(self, s: str) -> str:
        res = []
        balance = 0
        start = 0

        for i, char in enumerate(s):
            if char == '(':
                balance += 1
            else:
                balance -= 1
            if balance == 0:
                res.append(s[start + 1:i])
                start = i + 1
        return "".join(res)

4.7.860 - 2025-08-02 08:38:26 +0300 MSK

Binary Prefix Divisible By 5
class Solution:
    def prefixesDivBy5(self, nums: List[int]) -> List[bool]:
        cur = 0
        for i in range(len(nums)):
            cur <<= 1
            cur |= nums[i]
            nums[i] = cur % 5 == 0
        return nums

4.7.861 - 2025-08-02 08:34:40 +0300 MSK

Partition Array Into Three Parts With Equal Sum
class Solution:
    def canThreePartsEqualSum(self, arr: List[int]) -> bool:
        total = sum(arr)
        if total % 3 != 0:
            return False
        length = len(arr)
        target = total // 3
        cur = 0
        count = 0
        for i, num in enumerate(arr):
            cur += num
            if cur == target:
                cur = 0
                count += 1
            if count == 2 and i + 1 < length:
                return True
        return False

4.7.862 - 2025-08-01 21:34:49 +0300 MSK

Complement of Base 10 Integer
class Solution:
    def bitwiseComplement(self, n: int) -> int:
        if n == 0:
            return 1
        res, count = 0, 0
        while n > 0:
            if n & 1 == 0:
                res += 2 ** count
            count += 1
            n >>= 1
        return res

4.7.863 - 2025-08-01 21:23:46 +0300 MSK

Maximize Sum Of Array After K Negations
class Solution:
    def largestSumAfterKNegations(self, nums: List[int], k: int) -> int:
        nums.sort()
        for i in range(len(nums)):
            num = nums[i]
            if num < 0 and k > 0:
                nums[i] = -num
                k -= 1
            else:
                break
        if k == 0 or k % 2 == 0:
            return sum(nums)
        nums.sort()
        nums[0] = -nums[0]
        return sum(nums)

4.7.864 - 2025-08-01 20:49:53 +0300 MSK

Available Captures for Rook
class Solution:
    def numRookCaptures(self, board: List[List[str]]) -> int:
        bishop_row, bishop_col = -1, -1
        length = len(board)
        delta = (
            (0, 1), (0, -1), (1, 0), (-1, 0)            
        )
        for row in range(length):
            for col in range(length):
                if board[row][col] == "R":
                    bishop_row, bishop_col = row, col
                    break
            if bishop_row != -1:
                break
        count = 0
        for delta_row, delta_col in delta:
            row, col = bishop_row, bishop_col
            while 0 <= row < length and 0 <= col < length:
                char = board[row][col]
                if char == "p":
                    count += 1
                    break
                elif char == "B":
                    break
                row, col = row + delta_row, col + delta_col
        return count

4.7.865 - 2025-08-01 20:14:01 +0300 MSK

Cousins in Binary Tree
# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def isCousins(self, root: Optional[TreeNode], x: int, y: int) -> bool:
        def dfs(node: Optional[TreeNode], depth: int) -> tuple[int, int]:
            if node is None:
                return 0, 0
            if node.val == x:
                return depth, 0
            if node.val == y:
                return 0, depth
            depth1_x, depth1_y = dfs(node.left, depth + 1)
            depth2_x, depth2_y = dfs(node.right, depth + 1)
            depth1, depth2 = depth1_x or depth2_x, depth1_y or depth2_y
            if depth1 and depth2 and depth1 == depth + 1:
                return 0, 0
            return depth1, depth2

        depth1, depth2 = dfs(root, 0)
        return depth1 == depth2 and depth1 > 1

4.7.866 - 2025-08-01 19:32:18 +0300 MSK

Univalued Binary Tree
# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def isUnivalTree(self, root: Optional[TreeNode]) -> bool:
        queue = [root]
        while queue:
            node = queue.pop()
            if node.right and node.val != node.right.val:
                return False
            if node.left and node.val != node.left.val:
                return False
            if node.left:
                queue.append(node.left)
            if node.right:
                queue.append(node.right)
        return True

4.7.867 - 2025-08-01 19:30:30 +0300 MSK

Univalued Binary Tree
# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def isUnivalTree(self, root: Optional[TreeNode]) -> bool:
        def dfs(node: Optional[TreeNode]) -> bool:
            if node is None:
                return True
            if node.left and node.val != node.left.val:
                return False
            if node.right and node.val != node.right.val:
                return False
            return dfs(node.left) and dfs(node.right)
        return dfs(root)

4.7.868 - 2025-08-01 19:27:17 +0300 MSK

N-Repeated Element in Size 2N Array
class Solution:
    def repeatedNTimes(self, nums: List[int]) -> int:
        length = len(nums)
        for k in range(1, 4):
            for i in range(length - k):
                if nums[i] == nums[i+k]:
                    return nums[i]
        raise Exception

4.7.869 - 2025-08-01 19:18:48 +0300 MSK

N-Repeated Element in Size 2N Array
class Solution:
    def repeatedNTimes(self, nums: List[int]) -> int:
        enc = set()
        for num in nums:
            if num in enc:
                return num
            enc.add(num)
        raise Exception

4.7.870 - 2025-08-01 19:16:55 +0300 MSK

Verifying an Alien Dictionary
class Solution:
    def isAlienSorted(self, words: List[str], order: str) -> bool:
        pos = {}
        for i, char in enumerate(order):
            pos[char] = i
        for i in range(len(words) - 1):
            cur, nxt = words[i], words[i + 1]
            cur_length, nxt_length = len(cur), len(nxt)
            for j in range(cur_length):
                if j >= nxt_length:
                    return False
                cur_char, nxt_char = cur[j], nxt[j]
                if cur_char == nxt_char:
                    continue
                if pos[cur_char] > pos[nxt_char]: 
                    return False
                break
        return True

4.7.871 - 2025-08-01 17:46:26 +0300 MSK

Delete Columns to Make Sorted
class Solution:
    def minDeletionSize(self, strs: List[str]) -> int:
        res = 0
        for col in range(len(strs[0])):
            prev = 0
            for row in range(len(strs)):
                char = ord(strs[row][col])
                if char >= prev:
                    prev = char
                else:
                    res += 1
                    break
        return res

4.7.872 - 2025-08-01 17:40:59 +0300 MSK

DI String Match
class Solution:
    def diStringMatch(self, s: str) -> List[int]:
        length = len(s)
        res = [None] * (length + 1)
        num_i, num_d = 0, length
        for i, char in enumerate(s):
            if char == "I":
                res[i] = num_i
                num_i += 1
            else:
                res[i] = num_d
                num_d -= 1
        res[-1] = num_i
        return res

4.7.873 - 2025-08-01 17:39:13 +0300 MSK

DI String Match
class Solution:
    def diStringMatch(self, s: str) -> List[int]:
        length = len(s)
        res = [None] * (length + 1)
        num_i, num_d = 0, length
        for i, char in enumerate(s):
            is_i = char == "I"
            if is_i:
                res[i] = num_i
                num_i += 1
            else:
                res[i] = num_d
                num_d -= 1
            if i != length - 1:
                continue
            if is_i:
                res[i+1] = num_d
            else:
                res[i+1] = num_i
        return res

4.7.874 - 2025-08-01 17:12:58 +0300 MSK

Valid Mountain Array
class Solution:
    def validMountainArray(self, arr: List[int]) -> bool:
        length = len(arr)
        if length < 3:
            return False
        enc_peak = False
        prev = arr[0]
        for i, num in enumerate(arr[1:], 1):
            if num == prev:
                return False
            if not enc_peak and num < prev:
                enc_peak = True
            if enc_peak and (num > prev or i == 1):
                return False   
            prev = num
        return enc_peak

4.7.875 - 2025-08-01 16:57:25 +0300 MSK

Unique Email Addresses
class Solution:
    def numUniqueEmails(self, emails: List[str]) -> int:
        enc = set()
        for email in emails:
            name, domain = email.rsplit("@", 1)
            name = name.split("+", 1)[0].replace(".", "")
            enc.add("@".join((name, domain)))
        return len(enc)

4.7.876 - 2025-08-01 16:53:59 +0300 MSK

Long Pressed Name
class Solution:
    def isLongPressedName(self, name: str, typed: str) -> bool:
        name_i, typed_i = 0, 0
        name_length, typed_length = len(name), len(typed)

        while name_i < name_length and typed_i < typed_length:
            if name[name_i] == typed[typed_i]:
                name_i += 1
                typed_i += 1
            elif typed_i >= 1 and typed[typed_i] == typed[typed_i - 1]:
                typed_i += 1
            else:
                return False

        if name_i != name_length:
            return False

        while typed_i < typed_length:
            if typed[typed_i] != typed[typed_i - 1]:
                return False
            typed_i += 1

        return True

4.7.877 - 2025-08-01 16:43:05 +0300 MSK

Sort Array By Parity II
class Solution:
    def sortArrayByParityII(self, nums: List[int]) -> List[int]:
        res = [None] * len(nums)
        i1, i2 = 0, 1
        for num in nums:
            if num % 2 == 0:
                res[i1] = num
                i1 += 2
            else:
                res[i2] = num
                i2 += 2
        return res

4.7.878 - 2025-08-01 16:39:51 +0300 MSK

Sort Array By Parity II
class Solution:
    def sortArrayByParityII(self, nums: List[int]) -> List[int]:
        stack_even, stack_odd = [], []
        for num in nums:
            if num % 2 == 0:
                stack_even.append(num)
            else:
                stack_odd.append(num)
        for i in range(len(nums)):
            if i % 2 == 0:
                nums[i] = stack_even.pop()
            else:
                nums[i] = stack_odd.pop()
        return nums

4.7.879 - 2025-08-01 16:33:40 +0300 MSK

Reverse Only Letters
class Solution:
    def reverseOnlyLetters(self, s: str) -> str:
        i, j = 0, len(s) - 1
        res = [None] * len(s)
        while i <= j:
            char1, char2 = s[i], s[j]
            if not char1.isalpha():
                res[i] = char1
                i += 1
            elif not char2.isalpha():
                res[j] = char2
                j -= 1
            else:
                res[i], res[j] = char2, char1
                i += 1
                j -= 1
        return "".join(res)

4.7.880 - 2025-08-01 16:24:11 +0300 MSK

X of a Kind in a Deck of Cards
import math
import functools

class Solution:
    def hasGroupsSizeX(self, deck: List[int]) -> bool:
        freqs = collections.defaultdict(int)
        for num in deck:
            freqs[num] += 1
        gcd = functools.reduce(math.gcd, freqs.values())
        return gcd > 1

4.7.881 - 2025-08-01 16:02:30 +0300 MSK

Smallest Range I
class Solution:
    def smallestRangeI(self, nums: List[int], k: int) -> int:
        min_num, max_num = min(nums), max(nums)
        diff = max_num - min_num
        res = max(diff - 2 * k, 0)
        return res

4.7.882 - 2025-08-01 16:01:56 +0300 MSK

Smallest Range I
class Solution:
    def smallestRangeI(self, nums: List[int], k: int) -> int:
        min_num, max_num = float("inf"), float("-inf")
        for num in nums:
            if num > max_num:
                max_num = num
            if num < min_num:
                min_num = num
        diff = max_num - min_num
        res = max(diff - 2 * k, 0)
        return res

4.7.883 - 2025-08-01 15:50:58 +0300 MSK

Increasing Order Search Tree
# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def increasingBST(self, root: Optional[TreeNode]) -> Optional[TreeNode]:
        if root is None:
            return None
        def dfs(node: TreeNode) -> tuple[TreeNode, TreeNode]:
            if node.left:
                root, tail = dfs(node.left)
                tail.right = node
                tail = node
                node.left = None
            else:
                root, tail = node, node
            if node.right:
                right_root, right_tail = dfs(node.right)
                tail.right = right_root
                tail = right_tail
            return root, tail

        root, tail = dfs(root)
        return root

4.7.884 - 2025-08-01 15:30:00 +0300 MSK

Surface Area of 3D Shapes
class Solution:
    def surfaceArea(self, grid: list[list[int]]) -> int:
        length = len(grid)
        res = 0
        adj_delta = (
            (-1, 0), (1, 0), (0, -1), (0, 1)
        )
        for row in range(length):
            for col in range(length):
                height = grid[row][col]
                if height == 0:
                    continue
                res += 2
                for row_delta, col_delta in adj_delta:
                    adj_row, adj_col = row + row_delta, col + col_delta
                    if 0 <= adj_row < length and 0 <= adj_col < length:
                        adj_height = grid[adj_row][adj_col]
                    else:
                        adj_height = 0
                    if height > adj_height:
                        res += grid[row][col] - adj_height
        return res

4.7.885 - 2025-08-01 14:50:20 +0300 MSK

Fair Candy Swap
class Solution:
    def fairCandySwap(self, aliceSizes: List[int], bobSizes: List[int]) -> List[int]:
        count1, count2 = sum(aliceSizes), sum(bobSizes)
        delta = (count2 - count1) // 2
        set2 = set(bobSizes)
        for ex1 in aliceSizes:
            ex2 = ex1 + delta
            if ex2 in set2:
                return ex1, ex2
        raise Exception

4.7.886 - 2025-08-01 13:28:24 +0300 MSK

Uncommon Words from Two Sentences
class Solution:
    def uncommonFromSentences(self, s1: str, s2: str) -> List[str]:
        freqs = collections.defaultdict(int)
        res = []
        for word in s1.split():
            freqs[word] += 1
        for word in s2.split():
            freqs[word] += 1
        for word, freq in freqs.items():
            if freq == 1:
                res.append(word)
        return res

4.7.887 - 2025-08-01 13:24:00 +0300 MSK

Uncommon Words from Two Sentences
class Solution:
    def uncommonFromSentences(self, s1: str, s2: str) -> List[str]:
        freqs1, freqs2 = defaultdict(int), defaultdict(int)
        words1, words2 = s1.split(" "), s2.split(" ")
        for word in words1:
            freqs1[word] += 1
        for word in words2:
            freqs2[word] += 1
        res = []
        for word, freq in freqs1.items():
            if freq != 1 or word in freqs2:
                continue
            res.append(word)
        for word, freq in freqs2.items():
            if freq != 1 or word in freqs1:
                continue
            res.append(word)
        return res

4.7.888 - 2025-08-01 13:12:38 +0300 MSK

Projection Area of 3D Shapes
class Solution:
    def projectionArea(self, grid: list[list[int]]) -> int:
        res = 0
        length = len(grid)

        for i in range(length):
            best_row = 0
            best_col = 0 
            for j in range(length):
                if grid[i][j]: 
                    res += 1 
                best_row = max(best_row, grid[i][j])
                best_col = max(best_col, grid[j][i])

            res += best_row + best_col

        return res

4.7.889 - 2025-08-01 09:59:43 +0300 MSK

Lemonade Change
class Solution:
    def lemonadeChange(self, bills: List[int]) -> bool:
        change_5, change_10 = 0, 0
        for bill in bills:
            if bill == 5:
                change_5 += 1
            elif bill == 10 and change_5 > 0:
                change_5 -= 1
                change_10 += 1
            elif bill == 10 and change_5 <= 0:
                return False
            elif bill == 20 and change_10 > 0 and change_5 > 0:
                change_10 -= 1
                change_5 -= 1
            elif bill == 20 and change_5 >= 3:
                change_5 -= 3
            else:
                return False
        return True

4.7.890 - 2025-08-01 09:40:56 +0300 MSK

Rectangle Overlap
class Solution:
    def isRectangleOverlap(self, rec1: List[int], rec2: List[int]) -> bool:
        def intersect(p_left: int, p_right: int, q_left: int, q_right: int) -> bool:
            return min(p_right, q_right) > max(p_left, q_left)
        return (
            intersect(rec1[0], rec1[2], rec2[0], rec2[2]) # width > 0 
            and intersect(rec1[1], rec1[3], rec2[1], rec2[3]) # height > 0
        )

4.7.891 - 2025-08-01 08:25:54 +0300 MSK

Flipping an Image
class Solution:
    def flipAndInvertImage(self, image: List[List[int]]) -> List[List[int]]:
        for row in image:
            row.reverse()
            for i in range(len(row)):
                row[i] ^= 1
        return image

4.7.892 - 2025-08-01 08:21:20 +0300 MSK

Flipping an Image
class Solution:
    def flipAndInvertImage(self, image: List[List[int]]) -> List[List[int]]:
        for row in image:
            row.reverse()
            for i in range(len(row)):
                if row[i] == 0:
                    row[i] = 1
                else:
                    row[i] = 0
        return image

4.7.893 - 2025-08-01 08:13:47 +0300 MSK

Positions of Large Groups
class Solution:
    def largeGroupPositions(self, s: str) -> List[List[int]]:
        res = []
        start = 0
        prev = s[0]
        for i, char in enumerate(itertools.chain(s[1:], " "), 1):
            if char == prev:
                continue
            if i - 1 - start >= 2:
                res.append((start, i - 1))
            start = i
            prev = char
        return res

4.7.894 - 2025-08-01 07:59:37 +0300 MSK

Goat Latin
class Solution:
    def toGoatLatin(self, sentence: str) -> str:
        cur_word = []
        res = []
        i = 0
        for char in itertools.chain(sentence, " "):
            if char != " ":
                cur_word.append(char)
                continue
            if not cur_word:
                continue
            i += 1
            if cur_word[0].lower() in ("a", "e", "i", "o", "u"):
                cur_word.append("ma")
            else:
                cur_word.append(cur_word[0])
                cur_word.append("ma")
                cur_word[0] = ""
            cur_word.append("a" * i)
            res.append("".join(cur_word))
            cur_word.clear()
        return " ".join(res)

4.7.895 - 2025-08-01 07:51:03 +0300 MSK

Shortest Distance to a Character
class Solution:
    def shortestToChar(self, s: str, c: str) -> List[int]:
        indexes = []
        for i, char in enumerate(s):
            if char == c:
                indexes.append(i)
        length = len(indexes)
        res = []
        i = 0
        max_diff = float("inf")
        for j, char in enumerate(s):
            diff1 = abs(indexes[i] - j)
            if i + 1 >= length:
                diff2 = max_diff
            else:
                diff2 = abs(indexes[i + 1] - j)
            if diff1 <= diff2:
                res.append(diff1)
            else:
                res.append(diff2)
                i += 1
        return res

            

4.7.896 - 2025-08-01 07:33:33 +0300 MSK

Most Common Word
class Solution:
    def mostCommonWord(self, paragraph: str, banned: List[str]) -> str:
        freqs = defaultdict(int)
        banned_set = set(banned)
        cur_word = []
        for char in itertools.chain(paragraph, "."):
            if char.isalpha():
                cur_word.append(char.lower())
                continue
            if not cur_word:
                continue
            word = "".join(cur_word)
            if word not in banned_set:
                freqs[word] += 1
            cur_word.clear()
        most_freq = ""
        most_freq_freq = 0
        for word, freq in freqs.items():
            if freq > most_freq_freq:
                most_freq, most_freq_freq = word, freq
        return most_freq

4.7.897 - 2025-08-01 07:15:40 +0300 MSK

Pascal’s Triangle
class Solution:
    def generate(self, numRows: int) -> List[List[int]]:
        res = [(1, )]
        cur_row = []
        for row in range(1, numRows):
            cur_row.append(1)
            prev_row = res[-1]
            for i in range(1, row):
                cur_row.append(prev_row[i] + prev_row[i - 1])
            cur_row.append(1)
            res.append(tuple(cur_row))
            cur_row.clear()
        return res
                

4.7.898 - 2025-07-31 21:28:35 +0300 MSK

Largest Triangle Area
class Solution:
    def largestTriangleArea(self, points: list[int]) -> float:
        def area(p: tuple[int, int], q: tuple[int, int], r: tuple[int, int]) -> float:
            return 0.5 * abs(
                (p[0] * q[1]) 
                + (q[0] * r[1]) 
                + (r[0] * p[1])
                - (p[1] * q[0]) 
                - (q[1] * r[0]) 
                - (r[1] * p[0])
            )

        res = max(
            area(p, q, r)
            for p, q, r in itertools.combinations(points, 3)
        )
        return res

4.7.899 - 2025-07-31 18:46:45 +0300 MSK

Number of Lines To Write String
class Solution:
    def numberOfLines(self, widths: List[int], s: str) -> List[int]:
        line_count = 1
        line_width = 0
        for char in s:
            char_width = widths[ord(char) - 97]
            line_width += char_width
            if line_width > 100:
                line_width = char_width
                line_count += 1
        return line_count, line_width

4.7.900 - 2025-07-31 18:31:00 +0300 MSK

Unique Morse Code Words
MORSE = (".-","-...","-.-.","-..",".","..-.","--.","....","..",".---","-.-",".-..","--","-.","---",".--.","--.-",".-.","...","-","..-","...-",".--","-..-","-.--","--..")

class Solution:
    def uniqueMorseRepresentations(self, words: List[str]) -> int:
        enc = set()
        for word in words:
            enc.add("".join(MORSE[ord(char) - 97] for char in word))
        return len(enc)

4.7.901 - 2025-07-31 18:29:59 +0300 MSK

Unique Morse Code Words
class Solution:
    def uniqueMorseRepresentations(self, words: List[str]) -> int:
        morse = [".-","-...","-.-.","-..",".","..-.","--.","....","..",".---","-.-",".-..","--","-.","---",".--.","--.-",".-.","...","-","..-","...-",".--","-..-","-.--","--.."]
        enc = set()
        cur_morse = []
        for word in words:
            cur_morse.clear()
            for char in word:
                cur_morse.append(morse[ord(char) - 97])
            enc.add("".join(cur_morse))
        return len(enc)

4.7.902 - 2025-07-31 18:14:30 +0300 MSK

Rotate String
class Solution:
    def rotateString(self, s: str, goal: str) -> bool:
        if len(s) != len(goal):
            return False
        return goal in "".join((s, s))

4.7.903 - 2025-07-31 17:53:16 +0300 MSK

Minimum Distance Between BST Nodes
class Solution:
    def minDiffInBST(self, root: TreeNode) -> int:
        self.ans = float('inf')
        self.pred = None
        self.inorder(root)
        return self.ans

    def inorder(self, root: TreeNode) -> None:
        if root is None:
            return
        
        self.inorder(root.left)
        if self.pred is not None:
            self.ans = min(self.ans, root.val - self.pred)
        self.pred = root.val
        self.inorder(root.right)

4.7.904 - 2025-07-31 17:18:00 +0300 MSK

Jewels and Stones
class Solution:
    def numJewelsInStones(self, jewels: str, stones: str) -> int:
        jewels_set = set(jewels)
        count = 0
        for char in stones:
            if char in jewels:
                count += 1
        return count

4.7.905 - 2025-07-31 17:16:38 +0300 MSK

Toeplitz Matrix
class Solution:
    def isToeplitzMatrix(self, matrix: List[List[int]]) -> bool:
        for i in range(1, len(matrix)):
            for j in range(1, len(matrix[0])):
                if matrix[i-1][j-1] != matrix[i][j]:
                    return False
        return True

4.7.906 - 2025-07-31 17:05:37 +0300 MSK

Shortest Completing Word
class Solution:
    def shortestCompletingWord(self, licensePlate: str, words: List[str]) -> str:
        freq = defaultdict(int)
        for char in licensePlate:
            if char == " " or char.isnumeric():
                continue
            freq[char.lower()] += 1
        cur_freq = {}
        shortest = None
        for word in words:
            cur_freq.clear()
            cur_freq.update(freq)
            for char in word:
                if not cur_freq:
                    break
                if char not in cur_freq:
                    continue
                new_freq = cur_freq[char] - 1
                if new_freq <= 0:
                    cur_freq.pop(char)
                else:
                    cur_freq[char] = new_freq
            if not cur_freq and (shortest is None or len(word) < len(shortest)):
                shortest = word
        return shortest

4.7.907 - 2025-07-31 14:35:36 +0300 MSK

Largest Number At Least Twice of Others
class Solution:
    def dominantIndex(self, nums: List[int]) -> int:
        largest1, largest2 = -1, -1
        largest_i = -1
        for i, num in enumerate(nums):
            if num == largest2 or num == largest1:
                continue
            if num > largest2:
                largest1 = largest2
                largest2 = num
                largest_i = i
            elif num > largest1:
                largest1 = num
        if largest1 * 2 <= largest2:
            return largest_i
        return -1

4.7.908 - 2025-07-31 13:54:58 +0300 MSK

Flood Fill
class Solution:
    def floodFill(self, image: List[List[int]], sr: int, sc: int, color: int) -> List[List[int]]:
        target_color = image[sr][sc]
        if target_color == color:
            return image
        length_row = len(image)
        length_col = len(image[0])
        dirs = ((1, 0), (-1, 0), (0, 1), (0, -1))
        queue = [(sr, sc)]
        while queue:
            row, col = queue.pop()
            if row < 0 or row >= length_row:
                continue
            if col < 0 or col >= length_col:
                continue
            if image[row][col] != target_color:
                continue
            image[row][col] = color
            for row_delta, col_delta in dirs:
                queue.append((row + row_delta, col + col_delta))
        return image

4.7.909 - 2025-07-31 13:46:42 +0300 MSK

Flood Fill
class Solution:
    def floodFill(self, image: List[List[int]], sr: int, sc: int, color: int) -> List[List[int]]:
        target_color = image[sr][sc]
        enc = set()
        length_row = len(image)
        length_col = len(image[0])
        dirs = ((1, 0), (-1, 0), (0, 1), (0, -1))
        queue = [(sr, sc)]
        while queue:
            row, col = queue.pop()
            if row < 0 or row >= length_row:
                continue
            if col < 0 or col >= length_col:
                continue
            if (row, col) in enc:
                continue
            if image[row][col] != target_color:
                continue
            image[row][col] = color
            enc.add((row, col))
            for row_delta, col_delta in dirs:
                queue.append((row + row_delta, col + col_delta))
        return image

4.7.910 - 2025-07-31 13:03:46 +0300 MSK

Self Dividing Numbers
class Solution:
    def selfDividingNumbers(self, left: int, right: int) -> List[int]:
        def self_dividing(num: int) -> bool:
            if num == 0:
                return False
            cur_num = num
            while cur_num > 0:
                mod = cur_num % 10
                cur_num //= 10
                if mod == 0 or num % mod > 0:
                    return False
            return True
        ans = []
        for n in range(left, right + 1):
            if self_dividing(n):
                ans.append(n)
        return ans

4.7.911 - 2025-07-31 11:07:49 +0300 MSK

Degree of an Array
class Solution:
    def findShortestSubArray(self, nums: List[int]) -> int:
        left, right, freq = defaultdict(int), defaultdict(int), defaultdict(int)
        max_freq = 0
        for i, num in enumerate(nums):
            if num not in left:
                left[num] = i
            right[num] = i
            freq[num] += 1
            max_freq = max(max_freq, freq[num])
        min_length = len(nums)
        for num, num_freq in freq.items():
            if num_freq != max_freq:
                continue
            min_length = min(min_length, right[num] - left[num] + 1)
        return min_length

4.7.912 - 2025-07-31 11:00:20 +0300 MSK

Count Binary Substrings
class Solution:
    def countBinarySubstrings(self, s: str) -> int:
        groups = [1]
        for i in range(1, len(s)):
            if s[i-1] != s[i]:
                groups.append(1)
            else:
                groups[-1] += 1

        ans = 0
        for i in range(1, len(groups)):
            ans += min(groups[i-1], groups[i])
        return ans

4.7.913 - 2025-07-31 10:28:31 +0300 MSK

Baseball Game
class Solution:
    def calPoints(self, operations: List[str]) -> int:
        stack = []
        stack_sum = 0
        for op in operations:
            if op.isnumeric() or op.startswith("-"):
                new_score = int(op)
                stack.append(new_score)
                stack_sum += new_score
            elif op == "+":
                new_score = stack[-1] + stack[-2]
                stack_sum += new_score
                stack.append(new_score)
            elif op == "D":
                new_score = stack[-1] * 2
                stack_sum += new_score
                stack.append(new_score)
            elif op == "C":
                stack_sum -= stack[-1]
                stack.pop()
            else:
                raise Exception(op)
        return stack_sum

4.7.914 - 2025-07-31 10:04:49 +0300 MSK

Bitwise ORs of Subarrays
class Solution:
    def subarrayBitwiseORs(self, arr: List[int]) -> int:
        ors = set()
        cur = {0}
        for num in arr:
            cur = {num | cur_num for cur_num in cur} | {num}
            ors |= cur
        return len(ors)

4.7.915 - 2025-07-30 22:05:38 +0300 MSK

Valid Palindrome II
class Solution:
    def validPalindrome(self, s: str) -> bool:
        def check(i: int, j: int) -> bool:
            while i < j:
                if s[i] != s[j]:
                    return False
                i, j = i + 1, j - 1
            return True

        i, j = 0, len(s) - 1
        while i < j:
            if s[i] != s[j]:
                return check(i + 1, j) or check(i, j - 1)
            i, j = i + 1, j - 1
        return True

4.7.916 - 2025-07-30 22:00:12 +0300 MSK

Longest Continuous Increasing Subsequence
class Solution:
    def findLengthOfLCIS(self, nums: List[int]) -> int:
        prev = nums[0]
        length = 1
        max_length = 1
        for num in nums[1:]:
            if num > prev:
                length += 1
            else:
                max_length = max(length, max_length)
                length = 1
            prev = num
        return max(length, max_length)

4.7.917 - 2025-07-30 21:55:12 +0300 MSK

Second Minimum Node In a Binary Tree
# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def findSecondMinimumValue(self, root):
        self.ans = float('inf')
        min1 = root.val

        def dfs(node):
            if node:
                if min1 < node.val < self.ans:
                    self.ans = node.val
                elif node.val == min1:
                    dfs(node.left)
                    dfs(node.right)

        dfs(root)
        return self.ans if self.ans < float('inf') else -1

4.7.918 - 2025-07-30 21:02:37 +0300 MSK

Robot Return to Origin
class Solution:
    def judgeCircle(self, moves: str) -> bool:
        row, col = 0, 0
        coords = {
            "R": (0, 1),
            "L": (0, -1),
            "U": (1, 0),
            "D": (-1, 0)           
        }
        for move in moves:
            row_delta, col_delta = coords[move]
            row += row_delta
            col += col_delta
        return row == 0 and col == 0

4.7.919 - 2025-07-30 20:59:49 +0300 MSK

Maximum Product of Three Numbers
class Solution:
    def maximumProduct(self, nums: List[int]) -> int:
        nums.sort()
        pos_res = nums[-1] * nums[-2] * nums[-3]
        if nums[0] >= 0:
            return pos_res
        neg_res = nums[0] * nums[1] * nums[-1]
        return max(pos_res, neg_res)

4.7.920 - 2025-07-30 20:52:44 +0300 MSK

Swap Sex of Employees
UPDATE
    Salary
SET
    sex = (
        CASE
            WHEN
                sex = 'f'
            THEN
                'm'
            ELSE
                'f'
        END
    );

4.7.921 - 2025-07-30 20:47:51 +0300 MSK

Not Boring Movies
SELECT
    id, movie, description, rating
FROM
    Cinema
WHERE
    description != 'boring'
    AND id % 2 != 0
ORDER BY
    rating DESC;

4.7.922 - 2025-07-30 20:42:31 +0300 MSK

Biggest Single Number
WITH nums AS (
    SELECT 
        num
    FROM 
        MyNumbers
    GROUP BY 
        num
    HAVING 
        COUNT(num) = 1
) 
SELECT 
    MAX(num) AS num
FROM 
    nums;

4.7.923 - 2025-07-30 20:35:12 +0300 MSK

Merge Two Binary Trees
# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def mergeTrees(self, root1: Optional[TreeNode], root2: Optional[TreeNode]) -> Optional[TreeNode]:
        if root1 is None:
            return root2
        if root2 is None:
            return root1
        queue = [(root1, root2)]
        while queue:
            node1, node2 = queue.pop()
            if node1 is None or node2 is None:
                continue
            node1.val += node2.val
            if node1.left is None:
                node1.left = node2.left
            else:
                queue.append((node1.left, node2.left))
            if node1.right is None:
                node1.right = node2.right
            else:
                queue.append((node1.right, node2.right))
        return root1

4.7.924 - 2025-07-30 20:27:09 +0300 MSK

Merge Two Binary Trees
# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def mergeTrees(self, root1: Optional[TreeNode], root2: Optional[TreeNode]) -> Optional[TreeNode]:
        def dfs(node1: Optional[TreeNode], node2: Optional[TreeNode]) -> None:
            if node1 is None:
                return node2
            if node2 is None:
                return node1
            node1.val += node2.val
            node1.left = dfs(node1.left, node2.left)
            node1.right = dfs(node1.right, node2.right)
            return node1
        
        return dfs(root1, root2)

4.7.925 - 2025-07-30 20:12:39 +0300 MSK

Triangle Judgement
SELECT
    x, y, z, ( 
        CASE
            WHEN 
                ((x+y+z) - GREATEST(x,y,z)) > GREATEST(x,y,z) 
            THEN 
                'Yes' 
            ELSE 
                'No'
        END
    ) AS triangle
FROM 
    Triangle;

4.7.926 - 2025-07-30 20:09:55 +0300 MSK

Triangle Judgement
(
    SELECT
        x, y, z, 'Yes' AS triangle
    FROM
        Triangle
    WHERE 
        (x + y > z) AND (y + z > x) AND (z + x > y)
) UNION (
    SELECT 
        x, y, z, 'No' AS triangle
    FROM
        Triangle
    WHERE (x + y <= z) OR (y + z <= x) OR (z + x <= y)
);

4.7.927 - 2025-07-30 20:05:18 +0300 MSK

Sales Person
SELECT 
    sales_person.name
FROM (
    Orders orders
    JOIN 
        Company company
    ON 
        orders.com_id = company.com_id
        AND company.name = 'RED'
    RIGHT JOIN 
        SalesPerson sales_person
    ON 
        sales_person.sales_id = orders.sales_id
)
WHERE
    orders.sales_id IS NULL;

4.7.928 - 2025-07-30 19:52:43 +0300 MSK

Minimum Index Sum of Two Lists
class Solution:
    def findRestaurant(self, list1: List[str], list2: List[str]) -> List[str]:
        indexes = {}
        res = []
        if len(list1) > len(list2):
            first, second = list2, list1
        else:
            first, second = list1, list2
        for i, string in enumerate(first):
            indexes[string] = i
        min_sum = float("inf")
        res = []
        for j, string in enumerate(second):
            if string not in indexes:
                continue
            cur_sum = indexes[string] + j
            if cur_sum < min_sum:
                res.clear()
                res.append(string)
                min_sum = cur_sum
            elif cur_sum == min_sum:
                res.append(string)
        return res

4.7.929 - 2025-07-30 19:27:05 +0300 MSK

Range Addition II
class Solution:
    def maxCount(self, m: int, n: int, ops: List[List[int]]) -> int:
        min_row = m
        min_col = n
        for range_row, range_col in ops:
            min_row = min(min_row, range_row)
            min_col = min(min_col, range_col)
        return min_row * min_col

4.7.930 - 2025-07-30 19:18:29 +0300 MSK

Classes With at Least 5 Students
SELECT 
    class
FROM 
    Courses
GROUP BY 
    class
HAVING 
    COUNT(class) >= 5;

4.7.931 - 2025-07-30 19:14:46 +0300 MSK

Big Countries
SELECT
    World.name, World.population, World.area
FROM
    World
WHERE
    World.area >= 3000000
    OR World.population >= 25000000;

4.7.932 - 2025-07-30 19:11:57 +0300 MSK

Longest Harmonious Subsequence
class Solution:
    def findLHS(self, nums):
        freq = defaultdict(int)
        max_length = 0
        for num in nums:
            freq[num] += 1
        for num in freq:
            nxt = num + 1
            if nxt not in freq:
                continue
            cur_length = freq[num] + freq[nxt]
            max_length = max(max_length, cur_length)
        return max_length 

4.7.933 - 2025-07-30 18:59:58 +0300 MSK

N-ary Tree Postorder Traversal
"""
# Definition for a Node.
class Node:
    def __init__(self, val: Optional[int] = None, children: Optional[List['Node']] = None):
        self.val = val
        self.children = children
"""

class Solution:
    def postorder(self, root: 'Node') -> List[int]:
        if root is None:
            return []
        res = []
        queue = [root]
        while queue:
            node = queue.pop()
            res.append(node.val)
            for child in node.children:
                queue.append(child)
        res.reverse()
        return res

4.7.934 - 2025-07-30 18:49:52 +0300 MSK

N-ary Tree Postorder Traversal
"""
# Definition for a Node.
class Node:
    def __init__(self, val: Optional[int] = None, children: Optional[List['Node']] = None):
        self.val = val
        self.children = children
"""

class Solution:
    def postorder(self, root: 'Node') -> List[int]:
        res = []
        def dfs(node: Node, res: list[int]) -> None:
            if node is None:
                return
            for child in node.children:
                dfs(child, res)
            res.append(node.val)
        dfs(root, res)
        return res

4.7.935 - 2025-07-30 18:45:39 +0300 MSK

N-ary Tree Preorder Traversal
"""
# Definition for a Node.
class Node:
    def __init__(self, val: Optional[int] = None, children: Optional[List['Node']] = None):
        self.val = val
        self.children = children
"""

class Solution:
    def preorder(self, root: 'Node') -> List[int]:
        if root is None:
            return []
        res = []
        queue = [root]
        while queue:
            node = queue.pop()
            res.append(node.val)
            queue.extend(reversed(node.children))
        return res

4.7.936 - 2025-07-30 18:44:00 +0300 MSK

N-ary Tree Preorder Traversal
"""
# Definition for a Node.
class Node:
    def __init__(self, val: Optional[int] = None, children: Optional[List['Node']] = None):
        self.val = val
        self.children = children
"""

class Solution:
    def preorder(self, root: 'Node') -> List[int]:
        if root is None:
            return []
        res = []
        queue = deque((root, ))
        while queue:
            node = queue.popleft()
            res.append(node.val)
            queue.extendleft(reversed(node.children))
        return res

4.7.937 - 2025-07-30 18:35:45 +0300 MSK

N-ary Tree Preorder Traversal
"""
# Definition for a Node.
class Node:
    def __init__(self, val: Optional[int] = None, children: Optional[List['Node']] = None):
        self.val = val
        self.children = children
"""

class Solution:
    def preorder(self, root: 'Node') -> List[int]:
        res = []
        def dfs(node: Optional[Node], res: list[int]) -> None:
            if node is None:
                return
            res.append(node.val)
            for child in node.children:
                dfs(child, res)
        dfs(root, res)
        return res

4.7.938 - 2025-07-30 18:32:15 +0300 MSK

Customer Placing the Largest Number of Orders
SELECT 
    Orders.customer_number
FROM 
    Orders
GROUP BY 
    Orders.customer_number
ORDER BY 
    COUNT(Orders.customer_number) DESC
LIMIT 
    1;

4.7.939 - 2025-07-30 18:31:28 +0300 MSK

Customer Placing the Largest Number of Orders
SELECT 
    Orders.customer_number
FROM 
    Orders
GROUP BY 
    Orders.customer_number
ORDER BY 
    COUNT(*) DESC
LIMIT 
    1;

4.7.940 - 2025-07-30 18:25:43 +0300 MSK

Find Customer Referee
SELECT
    Customer.name
FROM 
    Customer
WHERE
    Customer.referee_id != 2
    OR Customer.referee_id IS NULL

4.7.941 - 2025-07-30 18:19:10 +0300 MSK

Employee Bonus
SELECT
    Employee.name, Bonus.bonus
FROM
    Employee
LEFT JOIN
    Bonus
ON 
    Employee.empId = Bonus.empId
WHERE
    Bonus.bonus IS NULL
    OR Bonus.bonus < 1000

4.7.942 - 2025-07-30 18:07:19 +0300 MSK

Distribute Candies
class Solution:
    def distributeCandies(self, candyType: List[int]) -> int:
        types = set()
        max_length = len(candyType) // 2
        for candy in candyType:
            types.add(candy)
            if len(types) >= max_length:
                return max_length
        return len(types)

4.7.943 - 2025-07-30 17:54:50 +0300 MSK

Subtree of Another Tree
# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def isSubtree(self, root: Optional[TreeNode], subRoot: Optional[TreeNode]) -> bool:
        def dfs(node: Optional[TreeNode], sub_node: Optional[TreeNode]) -> bool:
            if not node and not sub_node:
                return True
            if not node or not sub_node:
                return False
            if node.val != sub_node.val:
                return False
            return dfs(node.left, sub_node.left) and dfs(node.right, sub_node.right)
        
        def dfs2(node: Optional[TreeNode], sub_node: Optional[TreeNode]) -> bool:
            if dfs(node, sub_node):
                return True
            if not node or not sub_node:
                return False
            return dfs2(node.left, sub_node) or dfs2(node.right, sub_node)

        return dfs2(root, subRoot)

4.7.944 - 2025-07-30 17:36:45 +0300 MSK

Reshape the Matrix
class Solution:
    def matrixReshape(self, mat: List[List[int]], r: int, c: int) -> List[List[int]]:
        if len(mat) * len(mat[0]) != r * c:
            return mat
        new_mat = [[None] * c for _ in range(r)]
        new_row = 0
        new_col = 0
        for row in mat:
            for col in row:
                if new_col == c:
                    new_col = 0
                    new_row += 1
                new_mat[new_row][new_col] = col
                new_col += 1
        return new_mat
                

4.7.945 - 2025-07-30 16:27:11 +0300 MSK

Binary Tree Tilt
# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def findTilt(self, root: Optional[TreeNode]) -> int:
        def dfs(node: Optional[TreeNode]) -> tuple[int, int]:
            if node is None:
                return 0, 0
            left_sum, left_tilt = dfs(node.left)
            right_sum, right_tilt = dfs(node.right)
            tilt_sum = left_tilt + right_tilt + abs(left_sum - right_sum)
            node_sum = node.val + left_sum + right_sum
            return node_sum, tilt_sum
        _, tilt_sum = dfs(root)
        return tilt_sum

4.7.946 - 2025-07-30 16:07:35 +0300 MSK

Array Partition
class Solution:
    def arrayPairSum(self, nums: List[int]) -> int:
        nums.sort()
        length = len(nums)
        i = 0
        sum = 0
        while i < length:
            sum += nums[i]
            i += 2
        return sum

4.7.947 - 2025-07-30 16:04:16 +0300 MSK

Maximum Depth of N-ary Tree
"""
# Definition for a Node.
class Node:
    def __init__(self, val: Optional[int] = None, children: Optional[List['Node']] = None):
        self.val = val
        self.children = children
"""

class Solution:
    def maxDepth(self, root: 'Node') -> int:
        if root is None:
            return 0
        queue: deque[tuple[Node, int]] = deque(((root, 1),))
        max_depth = 0
        while queue:
            node, depth = queue.popleft()
            max_depth = depth
            for child in node.children:
                queue.append((child, 1 + depth))
        return max_depth

4.7.948 - 2025-07-30 15:53:02 +0300 MSK

Maximum Depth of N-ary Tree
"""
# Definition for a Node.
class Node:
    def __init__(self, val: Optional[int] = None, children: Optional[List['Node']] = None):
        self.val = val
        self.children = children
"""

class Solution:
    def maxDepth(self, root: 'Node') -> int:
        def dfs(node: Node) -> int:
            if not node:
                return 0
            if not node.children:
                return 1
            return 1 + max(dfs(child) for child in node.children)
        return dfs(root)

4.7.949 - 2025-07-30 15:50:06 +0300 MSK

Student Attendance Record I
class Solution:
    def checkRecord(self, s: str) -> bool:
        a_count = 0
        l_count = 0
        for char in s:
            if char == "P":
                l_count = 0
            elif char == "A":
                a_count += 1
                l_count = 0
            elif char == "L":
                l_count += 1
            if l_count >= 3 or a_count >= 2:
                return False
        return True

4.7.950 - 2025-07-30 15:40:51 +0300 MSK

Reverse String II
class Solution:
    def reverseStr(self, s: str, k: int) -> str:
        length = len(s)
        if length == 1:
            return s
        if length <= k:
            return s[::-1]
        res = []
        i = 0
        while i < length:
            new_i = i + 2 * k
            res.append(s[i+k-1:i:-1])
            res.append(s[i])
            res.append(s[i+k:new_i])
            i = new_i
        return "".join(res)

4.7.951 - 2025-07-30 15:11:27 +0300 MSK

Longest Uncommon Subsequence I
class Solution:
    def findLUSlength(self, a: str, b: str) -> int:
        if a == b:
            return -1
        else:
            return max(len(a), len(b))

4.7.952 - 2025-07-30 15:08:16 +0300 MSK

Longest Subarray With Maximum Bitwise AND
class Solution:
    def longestSubarray(self, nums: List[int]) -> int:
        max_val = ans = current_streak = 0
        for num in nums:
            if max_val < num:
                max_val = num
                ans = current_streak = 0
            if max_val == num:
                current_streak += 1
            else:
                current_streak = 0
            ans = max(ans, current_streak)
        return ans

4.7.953 - 2025-07-30 15:06:29 +0300 MSK

Longest Subarray With Maximum Bitwise AND
class Solution:
    def longestSubarray(self, nums: List[int]) -> int:
        max_and = max(nums)
        max_length = 0        
        cur_length = 0
        for num in nums:
            if num == max_and:
                cur_length += 1
            else:
                max_length = max(max_length, cur_length)
                cur_length = 0
        return max(max_length, cur_length)

4.7.954 - 2025-07-30 14:49:28 +0300 MSK

Detect Capital
class Solution:
    def detectCapitalUse(self, word: str) -> bool:
        length = len(word)
        if length == 1:
            return True
        def is_cap(char: str) -> bool:
            res = 65 <= ord(char) <= 90
            return res
        first_cap, second_cap = is_cap(word[0]), is_cap(word[1])
        if first_cap and second_cap:
            should_be_cap = True
        elif first_cap and not second_cap:
            should_be_cap = False
        elif not first_cap and second_cap:
            return False
        elif not first_cap and not second_cap:
            should_be_cap = False
        else:
            raise Exception
        for char in word[2:]:
            if is_cap(char) != should_be_cap:
                return False
        return True

4.7.955 - 2025-07-29 21:27:41 +0300 MSK

Game Play Analysis I
SELECT
    player_id, MIN(event_date) as "first_login"
FROM
    Activity
GROUP BY
    player_id

4.7.956 - 2025-07-29 21:05:02 +0300 MSK

Perfect Number
class Solution:
    def checkPerfectNumber(self, num: int) -> bool:
        if num == 1:
            return False
        count = 1
        for i in range(2, int(num**0.5) + 1):
            if num % i == 0:
                count += i + (num // i)
        return num == count

4.7.957 - 2025-07-29 20:50:01 +0300 MSK

Base 7
class Solution:
    def convertToBase7(self, num: int) -> str:
        if num > -7 and num < 7:
            return str(num)
        res_arr = []
        sign = ""
        if num < 0:
            sign = "-"
            num = -num
        while num:
            res_arr.append(str(num % 7))
            num //= 7
        res = sign + "".join(reversed(res_arr))
        return res

4.7.958 - 2025-07-29 20:45:22 +0300 MSK

Next Greater Element I
class Solution:
    def nextGreaterElement(self, nums1: list[int], nums2: list[int]) -> list[int]:
        stack = []
        greater = {}
        for num in nums2:
            while stack and num > stack[-1]:
                greater[stack.pop()] = num
            stack.append(num)
        for num in stack:
            greater[num] = -1
        return [greater[num] for num in nums1]

4.7.959 - 2025-07-29 19:17:54 +0300 MSK

Teemo Attacking
class Solution:
    def findPoisonedDuration(self, timeSeries: List[int], duration: int) -> int:
        total = 0
        cur_end = -1
        for second in timeSeries:
            if second > cur_end:
                total += duration
            else:
                total += duration - (cur_end - second) - 1
            cur_end = second + duration - 1
        return total

4.7.960 - 2025-07-29 18:55:38 +0300 MSK

Hamming Distance
class Solution:
    def hammingDistance(self, x: int, y: int) -> int:
        count = 0
        while x or y:
            if x % 2 != y % 2:
                count += 1
            x //= 2
            y //= 2
        return count

4.7.961 - 2025-07-29 18:52:23 +0300 MSK

Number of Segments in a String
class Solution:
    def countSegments(self, s: str) -> int:
        length = len(s)
        count = 0
        is_segment = False
        for char in s:
            is_space = char == " "
            if not is_segment and not is_space:
                is_segment = True
                count += 1
            elif is_space:
                is_segment = False
        return count

4.7.962 - 2025-07-29 18:27:23 +0300 MSK

Convert a Number to Hexadecimal
class Solution:
    def toHex(self, num: int) -> str:
        if num >=0 and num < 10:
            return str(num)
        if num < 0:
            num = (1 << 32) + num
        symbols = "0123456789abcdef"
        res = []
        while num > 0:
            mod = num % 16
            res.append(symbols[mod])
            num //= 16
        return "".join(reversed(res))

4.7.963 - 2025-07-29 17:59:54 +0300 MSK

Binary Watch
class Solution:
    def readBinaryWatch(self, num: int) -> list[str]:
        times = []

        for h in range(12):
            for m in range(60):
                hOnes = bin(h).count('1')
                mOnes = bin(m).count('1')
                if hOnes + mOnes == num:
                    times.append(f"{h}:{m:02d}")

        return times

4.7.964 - 2025-07-29 17:38:44 +0300 MSK

Nim Game
class Solution:
    def canWinNim(self, n: int) -> bool:
        return n % 4 != 0

4.7.965 - 2025-07-29 17:38:31 +0300 MSK

Nim Game
class Solution:
    def canWinNim(self, n: int) -> bool:
        if n < 3:
            return True
        True, True, True, False, True, True, True
        1,    2,    3,    4,     5,    6,    7    
        return n % 4 != 0

4.7.966 - 2025-07-29 16:37:09 +0300 MSK

Delete Duplicate Emails
DELETE FROM
    Person
WHERE 
    id NOT IN (
        SELECT MIN(id) FROM Person 
        GROUP BY email
    )
;

4.7.967 - 2025-07-29 16:11:49 +0300 MSK

Rising Temperature
SELECT 
    today.id
FROM 
    Weather today
CROSS JOIN 
    Weather yesterday
WHERE 
    (today.recordDate - yesterday.recordDate = 1)
    AND today.temperature > yesterday.temperature

4.7.968 - 2025-07-29 13:59:48 +0300 MSK

Smallest Subarrays With Maximum Bitwise OR
class Solution:
    def smallestSubarrays(self, nums: List[int]) -> List[int]:
        n = len(nums)
        pos = [-1] * 31
        ans = [0] * n
        for i in range(n - 1, -1, -1):
            j = i
            for bit in range(31):
                if (nums[i] & (1 << bit)) == 0:
                    if pos[bit] != -1:
                        j = max(j, pos[bit])
                else:
                    pos[bit] = i
            ans[i] = j - i + 1
        return ans

4.7.969 - 2025-07-28 20:06:14 +0300 MSK

Employees Earning More Than Their Managers
SELECT employee.name AS Employee
FROM Employee employee
JOIN Employee manager
ON employee.managerId = manager.id
WHERE employee.salary > manager.salary;

4.7.970 - 2025-07-28 19:28:55 +0300 MSK

Tenth Line
awk 'NR == 10 { print $0 }' file.txt

4.7.971 - 2025-07-28 16:53:12 +0300 MSK

Valid Phone Numbers
awk '
/^[0-9]{3}-[0-9]{3}-[0-9]{4}$/ { print $0 }
/^\([0-9]{3}\) [0-9]{3}-[0-9]{4}$/ { print $0 }
' file.txt

4.7.972 - 2025-07-28 16:52:43 +0300 MSK

Valid Phone Numbers
cat file.txt | awk '
/^[0-9]{3}-[0-9]{3}-[0-9]{4}$/ { print $0 }
/^\([0-9]{3}\) [0-9]{3}-[0-9]{4}$/ { print $0 }
'

4.7.973 - 2025-07-28 16:45:20 +0300 MSK

Customers Who Never Order
SELECT name as "Customers"
FROM Customers
WHERE id NOT IN (
    SELECT customerId 
    FROM Orders
);

4.7.974 - 2025-07-28 16:35:55 +0300 MSK

Duplicate Emails
SELECT email FROM Person
GROUP BY email
HAVING COUNT(email) > 1;

4.7.975 - 2025-07-28 16:25:34 +0300 MSK

Count Number of Maximum Bitwise-OR Subsets
class Solution:
    def countMaxOrSubsets(self, nums: List[int]) -> int:
        max_or_value = 0
        n = len(nums)
        for num in nums:
            max_or_value |= num
        memo = [[-1] * (max_or_value + 1) for _ in range(n)]
        return self._count_subsets_recursive(nums, 0, 0, max_or_value, memo)

    def _count_subsets_recursive(
        self,
        nums: List[int],
        index: int,
        current_or: int,
        target_or: int,
        memo: List[List[int]],
    ) -> int:
        if index == len(nums):
            return 1 if current_or == target_or else 0
        if memo[index][current_or] != -1:
            return memo[index][current_or]
        count_without = self._count_subsets_recursive(
            nums, index + 1, current_or, target_or, memo
        )
        count_with = self._count_subsets_recursive(
            nums, index + 1, current_or | nums[index], target_or, memo
        )
        res = count_without + count_with
        memo[index][current_or] = res
        return res

4.7.976 - 2025-07-27 19:03:38 +0300 MSK

Count Hills and Valleys in an Array
class Solution:
    def countHillValley(self, nums: List[int]) -> int:
        res = 0
        length = len(nums)
        for i in range(1, length - 1):
            if nums[i] == nums[i - 1]:
                continue
            left = 0
            for j in range(i - 1, -1, -1):
                if nums[j] > nums[i]:
                    left = 1
                    break
                elif nums[j] < nums[i]:
                    left = -1
                    break
            right = 0
            for j in range(i + 1, length):
                if nums[j] > nums[i]:
                    right = 1
                    break
                elif nums[j] < nums[i]:
                    right = -1
                    break
            if left == right and left != 0:
                res += 1
        return res

4.7.977 - 2025-07-26 18:50:49 +0300 MSK

Maximize Subarrays After Removing One Conflicting Pair
class Solution:
    def maxSubarrays(self, n: int, conflictingPairs: List[List[int]]) -> int:
        bMin1 = [2**31 - 1] * (n + 1)
        bMin2 = [2**31 - 1] * (n + 1)
        for pair in conflictingPairs:
            a = min(pair[0], pair[1])
            b = max(pair[0], pair[1])
            if bMin1[a] > b:
                bMin2[a] = bMin1[a]
                bMin1[a] = b
            elif bMin2[a] > b:
                bMin2[a] = b
        res = 0
        ib1 = n
        b2 = 0x3FFFFFFF
        delCount = [0] * (n + 1)
        for i in range(n, 0, -1):
            if bMin1[ib1] > bMin1[i]:
                b2 = min(b2, bMin1[ib1])
                ib1 = i
            else:
                b2 = min(b2, bMin1[i])
            res += min(bMin1[ib1], n + 1) - i
            delCount[ib1] += min(min(b2, bMin2[ib1]), n + 1) - min(
                bMin1[ib1], n + 1
            )
        return res + max(delCount)

4.7.978 - 2025-07-26 18:48:20 +0300 MSK

Ugly Number
class Solution(object):
    def isUgly(self, n):
        if n <= 0:
            return False
        
        while n % 2 == 0:
            n //= 2
        while n % 3 == 0:
            n //= 3
        while n % 5 == 0:
            n //= 5
        
        return n == 1

4.7.979 - 2025-07-25 13:23:28 +0300 MSK

1-bit and 2-bit Characters
class Solution(object):
    def isOneBitCharacter(self, bits):
        i = 0
        while i < len(bits) - 1:
            i += bits[i] + 1
        return i == len(bits) - 1

4.7.980 - 2025-07-25 13:15:13 +0300 MSK

To Lower Case
class Solution:
    def toLowerCase(self, s: str) -> str:
        return s.lower()

4.7.981 - 2025-07-25 13:14:11 +0300 MSK

Kth Largest Element in a Stream
class KthLargest:

    def __init__(self, k: int, nums: List[int]):
        if len(nums) < k:
            nums.extend((float("-inf"),) * (k - len(nums)))
        nums.sort()
        self._nums: list[int] = nums[-k:]
        self._k: int = k
        
    def add(self, val: int) -> int:
        if val > self._nums[0]:
            self._nums[0] = val
            self._nums.sort()
        return self._nums[-self._k]

# Your KthLargest object will be instantiated and called as such:
# obj = KthLargest(k, nums)
# param_1 = obj.add(val)

4.7.982 - 2025-07-25 12:37:39 +0300 MSK

Number of Students Doing Homework at a Given Time
class Solution:
    def busyStudent(self, startTime: List[int], endTime: List[int], queryTime: int) -> int:
        count = 0
        for start, end in zip(startTime, endTime):
            if queryTime >= start and queryTime <= end:
                count += 1
        return count

4.7.983 - 2025-07-25 12:29:53 +0300 MSK

Count Negative Numbers in a Sorted Matrix
class Solution:
    def countNegatives(self, grid: List[List[int]]) -> int:
        count = 0
        for i, row in enumerate(grid):
            for j, num in enumerate(row):
                if num < 0:
                    count += len(row) - j
                    break 
        return count

4.7.984 - 2025-07-25 12:18:12 +0300 MSK

Combine Two Tables
SELECT firstName, lastName, city, state 
FROM Person LEFT JOIN Address 
    ON Person.personId = Address.personId

4.7.985 - 2025-07-25 12:07:53 +0300 MSK

Delete Characters to Make Fancy String
class Solution:
    def makeFancyString(self, s: str) -> str:
        length = len(s)
        if length < 3:
            return s
        prev_char, prev_char_count = "", 0
        res = []
        for char in s:
            if char != prev_char:
                prev_char = char
                prev_char_count = 1
                res.append(char)
            elif prev_char_count < 2:
                prev_char_count += 1
                res.append(char)
        return "".join(res)

4.7.986 - 2025-07-25 11:57:05 +0300 MSK

Maximum Erasure Value
class Solution:
    def maximumUniqueSubarray(self, nums: List[int]) -> int:
        sub: deque[int] = deque()
        sub_nums: set[int] = set()
        cur_sum: int = 0
        max_sum: int = 0
        for num in nums:
            while num in sub_nums:
                sub_num = sub.popleft()
                sub_nums.remove(sub_num)
                cur_sum -= sub_num
            sub.append(num)
            sub_nums.add(num)
            cur_sum += num
            max_sum = max(cur_sum, max_sum)
        return max_sum
                
            

4.7.987 - 2025-07-25 09:50:01 +0300 MSK

Maximum Unique Subarray Sum After Deletion
class Solution:
    def maxSum(self, nums: List[int]) -> int:
        if len(nums) == 1:
            return nums[0]
        nums.sort()
        if nums[-1] <= 0:
            return nums[-1]
        res = 0
        if nums[0] > 0:
            res = nums[0]
        for i, num in enumerate(nums[1:], 1):
            if num <= 0 or num == nums[i - 1]:
                continue
            res += num
        return res

4.7.988 - 2025-07-24 18:52:24 +0300 MSK

Maximum Score From Removing Substrings
class Solution:
    def maximumGain(self, s: str, x: int, y: int) -> int:
        total_score = 0
        high_priority_pair = "ab" if x > y else "ba"
        low_priority_pair = "ba" if high_priority_pair == "ab" else "ab"

        # First pass: remove high priority pair
        string_after_first_pass = self.remove_substring(s, high_priority_pair)
        removed_pairs_count = (len(s) - len(string_after_first_pass)) // 2

        # Calculate score from first pass
        total_score += removed_pairs_count * max(x, y)

        # Second pass: remove low priority pair
        string_after_second_pass = self.remove_substring(
            string_after_first_pass, low_priority_pair
        )
        removed_pairs_count = (
            len(string_after_first_pass) - len(string_after_second_pass)
        ) // 2

        # Calculate score from second pass
        total_score += removed_pairs_count * min(x, y)

        return total_score

    def remove_substring(self, input: str, target_pair: str) -> str:
        char_stack = []

        # Iterate through each character in the input string
        for current_char in input:
            # Check if current character forms the target pair with the top of the stack
            if (
                current_char == target_pair[1]
                and char_stack
                and char_stack[-1] == target_pair[0]
            ):
                char_stack.pop()  # Remove the matching character from the stack
            else:
                char_stack.append(current_char)

        # Reconstruct the remaining string after removing target pairs
        return "".join(char_stack)

4.7.989 - 2025-07-24 17:40:53 +0300 MSK

Minimum Score After Removals on a Tree
class Solution:
    def calc(self, part1: int, part2: int, part3: int) -> int:
        return max(part1, part2, part3) - min(part1, part2, part3)

    def minimumScore(self, nums: List[int], edges: List[List[int]]) -> int:
        length = len(nums)
        parent_to_child: list[int] = [[] for _ in range(length)]
        for node_1, node_2 in edges:
            parent_to_child[node_1].append(node_2)
            parent_to_child[node_2].append(node_1)

        total = 0
        for num in nums:
            total ^= num

        res = float("inf")

        def dfs2(node: int, parent: int, oth: int, anc: int) -> int:
            son = nums[node]
            for child in parent_to_child[node]:
                if child == parent:
                    continue
                son ^= dfs2(child, node, oth, anc)
            if parent == anc:
                return son
            nonlocal res
            res = min(res, self.calc(oth, son, total ^ oth ^ son))
            return son

        def dfs(node: int, parent: int) -> int:
            son = nums[node]
            for child in parent_to_child[node]:
                if child == parent:
                    continue
                son ^= dfs(child, node)
            for child in parent_to_child[node]:
                if child == parent:
                    dfs2(child, node, son, node)
            return son

        dfs(0, -1)
        return res

4.7.990 - 2025-07-20 16:53:28 +0300 MSK

Delete Duplicate Folders in System
class Trie:
    serial: str = ""
    children: dict[str, "Trie"]

    def __init__(self) -> None:
        self.children = dict()


class Solution:
    def deleteDuplicateFolder(self, paths: List[List[str]]) -> List[List[str]]:
        root = Trie()
        freq = Counter()

        for path in paths:
            cur = root
            for node in path:
                if node not in cur.children:
                    cur.children[node] = Trie()
                cur = cur.children[node]

        
        def construct(node: Trie) -> None:
            if not node.children:
                return

            serial: list[str] = []
            for folder, child in node.children.items():
                construct(child)
                serial.append(f"{folder}({child.serial})")

            serial.sort()
            node.serial = "".join(serial)
            freq[node.serial] += 1

        construct(root)

        ans = list()
        path = list()

        def operate(node: Trie) -> None:
            if freq[node.serial] > 1:
                return
            if path:
                ans.append(path[:])

            for folder, child in node.children.items():
                path.append(folder)
                operate(child)
                path.pop()

        operate(root)
        return ans

4.7.991 - 2025-04-15 16:14:06 +0300 MSK

Count Good Triplets in an Array
from sortedcontainers import SortedList
from typing import List

class Solution:
    def goodTriplets(self, nums1: List[int], nums2: List[int]) -> int:

        index_map = {num: i for i, num in enumerate(nums2)}
  
        indices = [index_map[num] for num in nums1]

        left_counts = []
        left_sorted = SortedList()
        for idx in indices:
            left_counts.append(left_sorted.bisect_left(idx))
            left_sorted.add(idx)

        right_counts = []
        right_sorted = SortedList()
        for idx in reversed(indices):
            right_counts.append(len(right_sorted) - right_sorted.bisect_right(idx))
            right_sorted.add(idx)
        right_counts.reverse() 
        
        return sum(left * right for left, right in zip(left_counts, right_counts))

4.7.992 - 2025-04-14 19:45:07 +0300 MSK

Count Good Triplets
class Solution:
    def countGoodTriplets(self, arr: List[int], a: int, b: int, c: int) -> int:
        ans = 0
        n = len(arr)
        total = [0] * 1001
        for j in range(n):
            for k in range(j + 1, n):
                if abs(arr[j] - arr[k]) <= b:
                    lj, rj = arr[j] - a, arr[j] + a
                    lk, rk = arr[k] - c, arr[k] + c
                    l = max(0, lj, lk)
                    r = min(1000, rj, rk)
                    if l <= r:
                        ans += total[r] if l == 0 else total[r] - total[l - 1]
            for k in range(arr[j], 1001):
                total[k] += 1

        return ans

4.7.993 - 2025-04-13 17:10:23 +0300 MSK

Count Good Numbers
class Solution:
    def countGoodNumbers(self, n: int) -> int:
        mod = 10**9 + 7

        # use fast exponentiation to calculate x^y % mod
        def quickmul(x: int, y: int) -> int:
            ret, mul = 1, x
            while y > 0:
                if y % 2 == 1:
                    ret = ret * mul % mod
                mul = mul * mul % mod
                y //= 2
            return ret

        return quickmul(5, (n + 1) // 2) * quickmul(4, n // 2) % mod

4.7.994 - 2025-04-12 19:10:13 +0300 MSK

Find the Count of Good Integers
class Solution(object):
    def __init__(self):
        self.res = 0
        self.visited = set()

    def vectorToNumber(self, digits):
        return int(''.join(map(str, digits)))

    def totalPermutations(self, freqMap, total):
        res = factorial(total)
        for count in freqMap.values():
            res //= factorial(count)
        return res

    def permsWithZero(self, freqMap, total):
        if freqMap.get(0, 0) == 0:
            return 0
        freqMap[0] -= 1
        res = factorial(total - 1)
        for count in freqMap.values():
            res //= factorial(count)
        return res

    def genPal(self, palin, left, right, divisor, total):
        if left > right:
            palinVal = self.vectorToNumber(palin)
            if palinVal % divisor == 0:
                freq = Counter(palin)
                key = tuple(sorted(freq.items()))
                if key not in self.visited:
                    self.res += self.totalPermutations(freq, total) - self.permsWithZero(freq.copy(), total)
                    self.visited.add(key)
            return

        for dig in range(1 if left == 0 else 0, 10):
            palin[left] = palin[right] = dig
            self.genPal(palin, left + 1, right - 1, divisor, total)

    def countGoodIntegers(self, n, k):
        self.res = 0
        self.visited.clear()
        self.genPal([0] * n, 0, n - 1, k, n)
        return self.res

4.7.995 - 2025-04-11 20:06:54 +0300 MSK

Count Symmetric Integers
class Solution:
    def countSymmetricIntegers(self, low: int, high: int) -> int:
        count = 0
        for num in range(low, high + 1):
            s = str(num)
            if len(s) % 2 == 0:
                mid = len(s) // 2
                if sum(map(int, s[:mid])) == sum(map(int, s[mid:])):
                    count += 1
        return count

4.7.996 - 2025-04-10 19:50:16 +0300 MSK

Count the Number of Powerful Integers
class Solution:
    def numberOfPowerfulInt(self, start: int, finish: int, limit: int, suffix: str) -> int:
        def count_powerful_up_to(num: int) -> int:
            num_str = str(num)
            suffix_len = len(suffix)
            prefix_len = len(num_str) - suffix_len

            if prefix_len < 0:
                return 0

            dp = [[0] * 2 for _ in range(prefix_len + 1)]

            dp[prefix_len][0] = 1
            suffix_from_num = num_str[prefix_len:]
            dp[prefix_len][1] = int(suffix_from_num) >= int(suffix)

            for i in range(prefix_len - 1, -1, -1):
                digit = int(num_str[i])
                dp[i][0] = (limit + 1) * dp[i + 1][0]
                if digit <= limit:
                    dp[i][1] = digit * dp[i + 1][0] + dp[i + 1][1]
                else:
                    dp[i][1] = (limit + 1) * dp[i + 1][0]

            return dp[0][1]

        return count_powerful_up_to(finish) - count_powerful_up_to(start - 1)

4.7.997 - 2025-04-09 19:33:13 +0300 MSK

Minimum Operations to Make Array Values Equal to K
class Solution:
    def minOperations(self, nums: List[int], k: int) -> int:
        if not nums:
            return -1
        nums.sort(reverse=True)
        if nums[-1] < k:
            return -1
        prev = nums[0]
        if prev == k:
            return 0
        ops = 0
        for num in nums[1:]:
            if num == prev:
                continue
            ops += 1
            prev = num
            if num == k:
                return ops
        return ops + 1

4.7.998 - 2024-06-28 19:53:30 +0300 MSK

Maximum Total Importance of Roads
class Solution:
    def maximumImportance(self, n: int, roads: List[List[int]]) -> int:
        res = 0
        cost = 1
        conn = [0] * n
        for road in roads:
            conn[road[0]] += 1
            conn[road[1]] += 1

        conn.sort()
        for con in conn:
            res += con * cost
            cost += 1
        return res

4.7.999 - 2024-06-26 18:39:14 +0300 MSK

Balance a Binary Search Tree
# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def balanceBST(self, root: TreeNode) -> TreeNode:
        self.sortedArr = []
        self.inorderTraverse(root)
        return self.sortedArrayToBST(0, len(self.sortedArr) - 1)

    def inorderTraverse(self, root: TreeNode) -> None:
        if not root:
            return
        self.inorderTraverse(root.left)
        self.sortedArr.append(root)
        self.inorderTraverse(root.right)

    def sortedArrayToBST(self, start: int, end: int) -> TreeNode:
        if start > end:
            return None
        mid = (start + end) // 2
        root = self.sortedArr[mid]
        root.left = self.sortedArrayToBST(start, mid - 1)
        root.right = self.sortedArrayToBST(mid + 1, end)
        return root        

4.7.1000 - 2024-06-25 20:07:01 +0300 MSK

Binary Search Tree to Greater Sum Tree
# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def bstToGst(self, root: TreeNode) -> TreeNode:
        self.val = 0
        
        def dfs(node):
            if not node:
                return
            
            dfs(node.right)
            self.val += node.val
            node.val = self.val
            dfs(node.left)
        
        dfs(root)
        return root

4.7.1001 - 2024-06-24 15:55:17 +0300 MSK

Minimum Number of K Consecutive Bit Flips
class Solution:
    def minKBitFlips(self, A: List[int], K: int) -> int:
        n, flipped, res = len(A), 0, 0
        fp = [0] * n
        for i in range(n):
            if i >= K:
                flipped ^= fp[i - K]
            if flipped == A[i]:
                if i + K > n:
                    return -1
                fp[i] = 1
                flipped ^= 1
                res += 1
        return res

4.7.1002 - 2024-06-23 14:38:18 +0300 MSK

Longest Continuous Subarray With Absolute Diff Less Than or Equal to Limit
class Solution:
    def longestSubarray(self, nums: List[int], limit: int) -> int:
        decQ = collections.deque() 
        incQ = collections.deque() 
        ans = 0
        left = 0

        for right, num in enumerate(nums):
            while decQ and num > decQ[-1]:
                decQ.pop()

            decQ.append(num)

            while incQ and num < incQ[-1]:
                incQ.pop()

            incQ.append(num)

            while decQ[0] - incQ[0] > limit:
                if decQ[0] == nums[left]:
                    decQ.popleft()

                if incQ[0] == nums[left]:
                    incQ.popleft()

                left += 1

            ans = max(ans, right - left + 1)

        return ans

4.7.1003 - 2024-06-22 16:33:20 +0300 MSK

Count Number of Nice Subarrays
class Solution:
    def numberOfSubarrays(self, nums: List[int], k: int) -> int:
        for i in range(len(nums)):
            nums[i] %= 2
        
        prefix_count = [0] * (len(nums) + 1)
        prefix_count[0] = 1
        s = 0
        ans = 0
        
        for num in nums:
            s += num
            if s >= k:
                ans += prefix_count[s - k]
            prefix_count[s] += 1
        
        return ans

4.7.1004 - 2024-06-21 19:21:07 +0300 MSK

Grumpy Bookstore Owner
class Solution:
    def maxSatisfied(self, customers: List[int], grumpy: List[int], minutes: int) -> int:
        ans = 0
        total = sum((1 - grumpy[i]) * customers[i] for i in range(len(customers)))

        window_all = 0
        window_partial = 0
        for i in range(len(customers)):
            window_all += customers[i]
            window_partial += (1 - grumpy[i]) * customers[i]
            if i + 1 >= minutes:
                ans = max(ans, total - window_partial + window_all)
                left = i - minutes + 1
                window_all -= customers[left]
                window_partial -= (1 - grumpy[left]) * customers[left]

        return ans

4.7.1005 - 2024-06-19 19:59:31 +0300 MSK

Minimum Number of Days to Make m Bouquets
class Solution:
    def minDays(self, bloomDay: List[int], m: int, k: int) -> int:
        n=len(bloomDay)
        if m*k>n: return -1

        def f(d):
            len, bouquet=0, 0
            i=0
            while i<n:
                while i<n and bloomDay[i]<=d:
                    len+=1
                    if len==k:
                        bouquet+=1
                        len=0
                    i+=1
                if i<n and bloomDay[i]>d: len=0
                if bouquet>m: return True
                i+=1
            return bouquet>=m

        l, r = min(bloomDay), max(bloomDay)
        while l < r:
            mid = l + (r - l) // 2
            if f(mid):
                r = mid
            else:
                l = mid + 1
        return l
        

4.7.1006 - 2024-06-17 15:39:57 +0300 MSK

Sum of Square Numbers
from math import sqrt

class Solution:
    def judgeSquareSum(self, c: int) -> bool:
        for a in range(int(sqrt(c)) + 1):  # Iterate through all possible values of `a`
            b = sqrt(c - a * a)  # Compute `b` as the square root of `c - a^2`
            if b == int(b):  # Check if `b` is an integer
                return True  # If `b` is an integer, return true
        return False  # If no such pair `(a, b)` is found, return false

4.7.1007 - 2024-06-15 13:32:54 +0300 MSK

IPO
class Solution:
    def findMaximizedCapital(
        self, k: int, w: int, profits: List[int], capital: List[int]
    ) -> int:
        n = len(profits)
        projects = [(capital[i], profits[i]) for i in range(n)]
        projects.sort()
        maxHeap = []
        i = 0
        for _ in range(k):
            while i < n and projects[i][0] <= w:
                heapq.heappush(maxHeap, -projects[i][1])
                i += 1
            if not maxHeap:
                break
            w -= heapq.heappop(maxHeap)

        return w

4.7.1008 - 2024-06-14 18:54:35 +0300 MSK

Minimum Increment to Make Array Unique
class Solution:
    def minIncrementForUnique(self, nums: List[int]) -> int:
        # nums = [3,2,1,2,1,7]
        #        [1,1,2,2,3,7]

        # mySet = set({ num for num in nums }), 2+4
        nums.sort()
        numTracker = 0
        minIncreament = 0

        for num in nums:
            numTracker = max(numTracker, num)
            minIncreament += numTracker - num
            numTracker += 1
        return minIncreament

4.7.1009 - 2024-06-13 10:32:12 +0300 MSK

Minimum Number of Moves to Seat Everyone
class Solution:
    def minMovesToSeat(self, seats: List[int], students: List[int]) -> int:
        seats.sort()
        students.sort()
        moves = 0

        for i in range(len(seats)) :
            moves += abs(seats[i] - students[i])

        return moves

4.7.1010 - 2024-06-12 19:59:15 +0300 MSK

Sort Colors
class Solution:
    def sortColors(self, nums: List[int]) -> None:
        """
        Do not return anything, modify nums in-place instead.
        """
        zeros, ones, n = 0, 0, len(nums)
        for num in nums:
            if num == 0:
                zeros += 1
            elif num == 1:
                ones += 1

        for i in range(0, zeros):
            nums[i] = 0

        for i in range(zeros, zeros + ones):
            nums[i] = 1

        for i in range(zeros + ones, n):
            nums[i] = 2

4.7.1011 - 2024-06-11 20:57:06 +0300 MSK

Relative Sort Array
class Solution:
    def relativeSortArray(self, arr1, arr2):
        result = []
        
        for i in range(len(arr2)):
            for j in range(len(arr1)):
                if arr1[j] == arr2[i]:
                    result.append(arr1[j])
                    arr1[j] = -1
        
        arr1.sort()
        
        for num in arr1:
            if num != -1:
                result.append(num)
                
        return result

4.7.1012 - 2024-06-10 13:15:44 +0300 MSK

Height Checker
class Solution:
    def heightChecker(self, heights: List[int]) -> int:
        return sum(h!=s for h, s in zip(heights, sorted(heights)))

4.7.1013 - 2024-06-09 13:56:45 +0300 MSK

Subarray Sums Divisible by K
class Solution:
    def subarraysDivByK(self, nums: List[int], k: int) -> int:
        count = 0
        prefix_sum = 0
        prefix_map = {0: 1}  
        
        for num in nums:
            prefix_sum += num
            mod = prefix_sum % k
            if mod < 0:  
                mod += k
            if mod in prefix_map:
                count += prefix_map[mod]
                prefix_map[mod] += 1
            else:
                prefix_map[mod] = 1
        
        return count

4.7.1014 - 2024-06-08 22:13:27 +0300 MSK

Continuous Subarray Sum
class Solution:
    def checkSubarraySum(self, nums: List[int], k: int) -> bool:
        remainder_map = {0: -1}  
        cumulative_sum = 0
        
        for i, num in enumerate(nums):
            cumulative_sum += num
            remainder = cumulative_sum % k
            if remainder in remainder_map:
                if i - remainder_map[remainder] > 1:
                    return True
            else:
                remainder_map[remainder] = i
        return False

4.7.1015 - 2024-06-07 18:18:51 +0300 MSK

Replace Words
class Solution:
    def replaceWords(self, dict: List[str], sentence: str) -> str:
        roots = set(dict)
        words = sentence.split()
        result = []

        for word in words:
            for i in range(len(word) + 1):
                prefix = word[:i]
                if prefix in roots:
                    result.append(prefix)
                    break
            else:
                result.append(word)

        return ' '.join(result)

4.7.1016 - 2024-06-06 18:22:03 +0300 MSK

Hand of Straights
class Solution:
    def isNStraightHand(self, hand: List[int], groupSize: int) -> bool:
        # Step 1: Check if grouping is possible
        if len(hand) % groupSize != 0:
            return False
        
        # Step 2: Count the occurrences of each card
        count = Counter(hand)
        
        # Step 3: Sort the unique card values
        sorted_keys = sorted(count.keys())
        
        # Step 4: Form consecutive groups
        for key in sorted_keys:
            if count[key] > 0:  # If this card is still available
                start_count = count[key]
                # Check and form a group starting from `key`
                for i in range(key, key + groupSize):
                    if count[i] < start_count:
                        return False
                    count[i] -= start_count
        
        # Step 5: Return True if all groups are formed successfully
        return True

4.7.1017 - 2024-06-05 10:32:36 +0300 MSK

Find Common Characters
class Solution:
    def commonChars(self, words: List[str]) -> List[str]:
        result = []
        
        # Check each character from 'a' to 'z'
        for char in range(ord('a'), ord('z') + 1):
            char = chr(char)
            min_count = float('inf')  # Start with a very high number
            
            # Find the minimum count of the character in all words
            for word in words:
                count = word.count(char)  # Count the current character in the current word
                min_count = min(min_count, count)  # Keep track of the smallest count
                if min_count == 0:
                    break  # If the character is not in one of the words, we can skip further checking
            
            # Add the character to the result list the required number of times
            result.extend([char] * min_count)
        
        return result

4.7.1018 - 2024-06-03 15:40:20 +0300 MSK

Append Characters to String to Make Subsequence
class Solution:
    def appendCharacters(self, s: str, t: str) -> int:
        i, j = 0, 0  # Start both pointers at the beginning of s and t
        
        while i < len(s) and j < len(t):  # Continue until one of the strings is fully scanned
            if s[i] == t[j]:  # If characters match
                j += 1  # Move the pointer in t forward
            i += 1  # Always move the pointer in s forward
        
        return len(t) - j  # The number of characters in t not matched in s
               

4.7.1019 - 2024-06-02 21:31:18 +0300 MSK

Student Attendance Record II
class Solution:
    def checkRecord(self, n: int) -> int:
        # Recursion + Cache
        mod=10**9+7
        #only @cache will lead to MLE
        dp=[[[-1]*3 for _ in range(2)] for _ in range(n+1)]
        def f(i, absent, late):
            if absent>=2 or late>=3: return 0
            if i==0: return 1
            if dp[i][absent][late]!=-1:
                return dp[i][absent][late]
            ans=f(i-1, absent, 0)
            ans+=f(i-1, absent, late+1)
            ans+=f(i-1, absent+1, 0)
            dp[i][absent][late]=ans%mod
            return dp[i][absent][late]
        return f(n, 0, 0)

4.7.1020 - 2024-06-01 22:04:19 +0300 MSK

Single Number III
class Solution:
    def singleNumber(self, nums: list[int]) -> list[int]:
        n: int = len(nums)
        result: list[int] = [0, 0]
        index = 0

        for i in range(n):
            found = False
            for j in range(n):
                if i != j and nums[i] == nums[j]:
                    found = True
                    break
            if not found:
                result[index] = nums[i]
                index += 1
                if index == 2:
                    break

        return result

4.7.1021 - 2024-06-01 22:04:02 +0300 MSK

Count Triplets That Can Form Two Arrays of Equal XOR
class Solution:
    def countTriplets(self, arr: List[int]) -> int:
        n = len(arr)
        prefix = [0] * (n + 1)
        
        for i in range(n):
            prefix[i + 1] = prefix[i] ^ arr[i]
        
        count = 0
        for i in range(n):
            for k in range(i + 1, n):
                if prefix[i] == prefix[k + 1]:
                    count += (k - i)
        
        return count

4.7.1022 - 2024-06-01 22:03:45 +0300 MSK

Maximum Score Words Formed by Letters
class Solution:
    def maxScoreWords(
        self, words: List[str], letters: List[str], score: List[int]
    ) -> int:
        lettersCounter = Counter(letters)
        totalScore = 0

        def explore(index, letterCounter, currScore):
            nonlocal totalScore

            totalScore = max(totalScore, currScore)
            if index == len(words):
                return

            for i in range(index, len(words)):
                tmpCounter = copy.deepcopy(letterCounter)
                word = words[i]
                wordScore = 0
                isValid = True

                for ch in word:
                    if ch in tmpCounter and tmpCounter[ch] > 0:
                        tmpCounter[ch] -= 1
                        wordScore += score[ord(ch) - ord("a")]
                    else:
                        isValid = False
                        break
                if isValid:
                    explore(i + 1, tmpCounter, currScore + wordScore)

        explore(0, lettersCounter, 0)
        return totalScore

4.7.1023 - 2024-06-01 22:01:30 +0300 MSK

Score of a String
class Solution:
    def scoreOfString(self, s: str) -> int:
        score = 0
        for i in range(len(s) - 1):
            score += abs(ord(s[i]) - ord(s[i + 1]))
        return score               

4.7.1024 - 2024-05-29 12:47:46 +0300 MSK

Number of Steps to Reduce a Number in Binary Representation to One
class Solution:
    def numSteps(self, s: str) -> int:
        steps = 0
        carry = 0
        n = len(s) - 1
        for i in range(n, 0, -1):
            if int(s[i]) + carry == 1:
                carry = 1
                steps += 2
            else:
                steps += 1
        return steps + carry

        

4.7.1025 - 2024-05-28 20:05:20 +0300 MSK

Get Equal Substrings Within Budget
class Solution:
    def equalSubstring(self, s: str, t: str, maxCost: int) -> int:
        n = len(s)
        start = 0
        current_cost = 0
        max_length = 0

        for end in range(n):
            current_cost += abs(ord(s[end]) - ord(t[end]))

            while current_cost > maxCost:
                current_cost -= abs(ord(s[start]) - ord(t[start]))
                start += 1

            max_length = max(max_length, end - start + 1)
        
        return max_length

4.7.1026 - 2024-05-27 10:56:18 +0300 MSK

Special Array With X Elements Greater Than or Equal X
class Solution:
    def specialArray(self, nums: list[int]) -> int:
        nums.sort()
        n: int = len(nums)

        def find_number_of_nums(cur_num) -> int:
            left: int = 0
            right: int = n - 1

            first_index: int = n
            while left <= right:
                mid: int = (left + right) // 2

                if nums[mid] >= cur_num:
                    first_index = mid
                    right = mid - 1
                else:
                    left = mid + 1

            return n - first_index

        for candidate_number in range(1, n + 1, 1):
            if candidate_number == find_number_of_nums(candidate_number):
                return candidate_number

        return -1

4.7.1027 - 2024-05-26 20:44:15 +0300 MSK

Student Attendance Record II
class Solution:
    def checkRecord(self, n: int) -> int:
        temp: list[list[list[int]]] = [
            [[-1 for _ in range(3)] for _ in range(2)] for _ in range(n)
        ]  # temp[cur_ind][count_a][count_l]
        MOD: int = 10**9 + 7

        def check_all_records(cur_ind, count_a, count_l) -> int:
            if cur_ind == n:
                return 1
            if temp[cur_ind][count_a][count_l] != -1:
                return temp[cur_ind][count_a][count_l]
            with_a_next: int = check_all_records(cur_ind + 1, count_a + 1, 0) if count_a == 0 else 0
            with_l_next: int = 0 if count_l == 2 else check_all_records(cur_ind + 1, count_a, count_l + 1)
            with_p_next: int = check_all_records(cur_ind + 1, count_a, 0)
            total: int = (with_a_next + with_l_next + with_p_next) % MOD

            temp[cur_ind][count_a][count_l] = total
            return total

        return check_all_records(0, 0, 0)

4.7.1028 - 2024-05-25 22:59:58 +0300 MSK

Word Break II
class Solution:
    def wordBreak(self, s: str, wordDict: List[str]) -> List[str]:
        wordSet = set(wordDict)
        @cache
        def helper(t):
            combos = []
            if not t:
                return [""]
            for i, _ in enumerate(t):
                w = t[:i+1] 
                if w in wordSet:
                    combos.extend([
                        f'{w} {sentence}' if sentence else w 
                        for sentence in helper(t[i+1:])
                    ])
            return combos
        return helper(s)

4.7.1029 - 2024-05-21 21:02:08 +0300 MSK

Subsets
class Solution:
    def subsets(self, nums: List[int]) -> List[List[int]]:
        def backtrack(start, path):
            result.append(path)
            for i in range(start, len(nums)):
                backtrack(i + 1, path + [nums[i]])

        result = []
        backtrack(0, [])
        return result

4.7.1030 - 2024-05-20 13:28:49 +0300 MSK

Sum of All Subset XOR Totals
class Solution:
    def subsetXORSum(self, nums: List[int]) -> int:
        return reduce(operator.or_, nums) * 1 << (len(nums) - 1)
        

4.7.1031 - 2024-05-19 15:08:43 +0300 MSK

Find the Maximum Sum of Node Values
class Solution:
    def maximumValueSum(self, nums: list[int], k: int, edges: list[list[int]]) -> int:
        n: int = len(nums)
        temp: list[list[int]] = [[-1 for _ in range(2)] for _ in range(n)]  # temp[current_index(node)][is_even]

        def calculate_max(cur_ind, is_even) -> int:  # cur_ind -> cur_index of the tree and is_even represents whether we have already changed (XOR) even or odd number of nodes 
            if cur_ind == n:  # if we go to node which doesn't exist
                return 0 if is_even else -float("inf")
            if temp[cur_ind][is_even] != -1:  # if we've already encountered this state
                return temp[cur_ind][is_even]

            # checking all possible variants (no XOR or XOR)
            no_xor = nums[cur_ind] + calculate_max(cur_ind + 1, is_even)  # we don't change the number of XOR nodes
            with_xor = (nums[cur_ind] ^ k) + calculate_max(cur_ind + 1, not is_even)  # we added 1 XORed node

            mx_possible = max(no_xor, with_xor)
            temp[cur_ind][is_even] = mx_possible
            return mx_possible

        return calculate_max(0, 1)  # is_even == 1 because we have XORed 0 nodes which is even

4.7.1032 - 2024-05-18 20:24:14 +0300 MSK

Distribute Coins in Binary Tree
# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def distributeCoins(self, root: Optional[TreeNode]) -> int:
        #move coins to parent DFS
        def f(root, parent):
            if root==None: return 0
            moves=f(root.left, root)+f(root.right, root)
            x=root.val-1
            if parent!=None: parent.val+=x
            moves+=abs(x)
            return moves
        return f(root, None)

4.7.1033 - 2024-05-17 21:25:39 +0300 MSK

Delete Leaves With a Given Value
# Definition for a binary tree node.
# class TreeNode(object):
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right

class Solution(object):
    def removeLeafNodes(self, root, target):
        """
        :type root: TreeNode
        :type target: int
        :rtype: TreeNode
        """
        if not root:
            return None
        root.left = self.removeLeafNodes(root.left, target)
        root.right = self.removeLeafNodes(root.right, target)
        if not root.left and not root.right and root.val == target:
            return None
        return root

4.7.1034 - 2024-05-16 18:11:33 +0300 MSK

Evaluate Boolean Binary Tree
# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def helper(self, root):
        if root.val == 0 or root.val == 1:
            return root.val == 1
        elif root.val == 2:
            return self.helper(root.left) or self.helper(root.right)
        elif root.val == 3:
            return self.helper(root.left) and self.helper(root.right)
        return False
        
    def evaluateTree(self, root: Optional[TreeNode]) -> bool:
        return self.helper(root)

4.7.1035 - 2024-05-14 12:06:07 +0300 MSK

Path with Maximum Gold
class Solution:
    roww = [1, -1, 0, 0]
    coll = [0, 0, -1, 1]

    def dfs(self, grid, x, y, n, m):
        if x < 0 or x >= n or y < 0 or y >= m or grid[x][y] == 0:
            return 0
        
        curr = grid[x][y]
        grid[x][y] = 0
        localMaxGold = curr

        for i in range(4):
            newX = x + self.roww[i]
            newY = y + self.coll[i]
            localMaxGold = max(localMaxGold, curr + self.dfs(grid, newX, newY, n, m))

        grid[x][y] = curr
        return localMaxGold

    def getMaximumGold(self, grid):
        n = len(grid)
        m = len(grid[0])
        maxGold = 0

        for i in range(n):
            for j in range(m):
                if grid[i][j] != 0:
                    maxGold = max(maxGold, self.dfs(grid, i, j, n, m))

        return maxGold

4.7.1036 - 2024-05-13 10:22:15 +0300 MSK

Score After Flipping Matrix
class Solution:
    def matrixScore(self, grid: List[List[int]]) -> int:
        n, m = len(grid), len(grid[0])
        res = (1 << (m - 1)) * n

        for j in range(1, m):
            val = 1 << (m - 1 - j)
            set_count = 0

            for i in range(n):
                if grid[i][j] == grid[i][0]:
                    set_count += 1

            res += max(set_count, n - set_count) * val

        return res

4.7.1037 - 2024-05-12 21:39:08 +0300 MSK

Largest Local Values in a Matrix
class Solution:
    def largestLocal(self, grid: List[List[int]]) -> List[List[int]]:
        n, res = len(grid), []

        for i in range(1, n - 1):
            temp_row = []
            for j in range(1, n - 1):
                temp = 0

                for k in range(i - 1, i + 2):
                    for l in range(j - 1, j + 2):
                        temp = max(temp, grid[k][l])

                temp_row.append(temp)
            res.append(temp_row)

        return res

4.7.1038 - 2024-05-08 10:50:28 +0300 MSK

Relative Ranks
import heapq

class Solution:
    def findRelativeRanks(self, score: List[int]) -> List[str]:
        heap = []
        length = len(score)
        scores = [0] * length
        for i in range(length):
            scores[i] = (score[i], i)
        scores.sort(reverse=True)
        ranks = {0: "Gold Medal", 1: "Silver Medal", 2: "Bronze Medal"}
        for i in range(length):
            _, idx = scores[i]
            score[idx] = ranks.get(i, str(i + 1))
        return score

4.7.1039 - 2024-05-08 10:39:08 +0300 MSK

Relative Ranks
import heapq

class Solution:
    def findRelativeRanks(self, score: List[int]) -> List[str]:
        heap = []
        for i, athlete_score in enumerate(score):
            heapq.heappush(heap, (-athlete_score, i))
        i = 0
        ranks = {0: "Gold Medal", 1: "Silver Medal", 2: "Bronze Medal"}
        while heap:
            _, athlete = heapq.heappop(heap)
            rank = ranks.get(i, str(i + 1))
            score[athlete] = rank
            i += 1
        return score

4.7.1040 - 2024-05-07 10:56:39 +0300 MSK

Double a Number Represented as a Linked List
# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:
    def doubleIt(self, head: Optional[ListNode]) -> Optional[ListNode]:
        def func(head):
            a=head.val*2
            if head.next:
                a+=func(head.next)
            head.val=a%10
            return a//10
        a=func(head)
        if a:
            return ListNode(a,head)
        return head
                

4.7.1041 - 2024-05-06 16:47:26 +0300 MSK

Remove Nodes From Linked List
class Solution:
    def removeNodes(self, head: Optional[ListNode]) -> Optional[ListNode]:
        cur = head
        stack = []
        while cur:
            while stack and stack[-1].val < cur.val:
                stack.pop()
            stack.append(cur)
            cur = cur.next
        
        nxt = None
        while stack:
            cur = stack.pop()
            cur.next = nxt
            nxt = cur
        
        return cur

4.7.1042 - 2024-05-04 18:08:36 +0300 MSK

Boats to Save People
func numRescueBoats(people []int, limit int) int {
    sort.Ints(people)

    numberOfBouts := 0

    start := 0
    end := len(people)-1

    for start < end {
        if people[start] + people[end] <= limit {
            numberOfBouts++
            start++
        }else{
            numberOfBouts++
        }
        end--
    }

    if start == end {
        numberOfBouts++
    }

    return numberOfBouts
}

4.7.1043 - 2024-05-03 17:41:51 +0300 MSK

Compare Version Numbers
func compareVersion(version1 string, version2 string) int {

	rev1 := strings.Split(version1, ".")
	rev2 := strings.Split(version2, ".")
    // fmt.Println(rev1, rev2)

	revInt1 := make([]int, len(rev1))
	revInt2 := make([]int, len(rev2))

	for i := 0; i < len(rev1); i++ {
		revInt1[i], _ = strconv.Atoi(rev1[i])
	}
	for i := 0; i < len(rev2); i++ {
		revInt2[i], _ = strconv.Atoi(rev2[i])
	}
    // fmt.Println(revInt1, revInt2)

	i := 0
	j := 0

	for i < len(revInt1) && j < len(revInt2) {

		if revInt1[i] < revInt2[j] {
			return -1
		} else if revInt1[i] > revInt2[j] {
			return 1
		}
		i++
		j++
	}

	for i < len(revInt1) {
		if revInt1[i] > 0 {
			return 1
		}
		i++
	}
	for j < len(revInt2) {
		if revInt2[j] > 0 {
			return -1
		}
		j++
	}
	return 0
}

4.7.1044 - 2024-05-02 19:49:20 +0300 MSK

Largest Positive Integer That Exists With Its Negative
func findMaxK(nums []int) int {
    alreadySeenNums := map[int]bool{}
    res := -1

    for _, num := range nums {
        numAbs := int(math.Abs(float64(num)))

        if numAbs < res {
            continue
        }

        if alreadySeenNums[-num] {
            res = numAbs
        } else {
            alreadySeenNums[num] = true
        }
    }

    return res
}

4.7.1045 - 2024-05-01 12:05:11 +0300 MSK

Find if Path Exists in Graph
type UnionFind struct {
    parent []int
    rank   []int
}

func NewUnionFind(n int) *UnionFind {
    parent := make([]int, n)
    rank := make([]int, n)
    for i := 0; i < n; i++ {
        parent[i] = i
    }
    return &UnionFind{parent, rank}
}

func (uf *UnionFind) Find(u int) int {
    if uf.parent[u] != u {
        uf.parent[u] = uf.Find(uf.parent[u])
    }
    return uf.parent[u]
}

func (uf *UnionFind) UnionByRank(u, v int) {
    i := uf.Find(u)
    j := uf.Find(v)
    if i == j {
        return
    }
    if uf.rank[i] < uf.rank[j] {
        uf.parent[i] = j
    } else if uf.rank[i] > uf.rank[j] {
        uf.parent[j] = i
    } else {
        uf.parent[i] = j
        uf.rank[j]++
    }
}

func validPath(n int, edges [][]int, source int, destination int) bool {
    uf := NewUnionFind(n)
    for _, edge := range edges {
        u, v := edge[0], edge[1]
        uf.UnionByRank(u, v)
    }
    return uf.Find(source) == uf.Find(destination)
}

4.7.1046 - 2024-05-01 12:04:46 +0300 MSK

Number of Wonderful Substrings
func get(c rune) int {

    return int(c - 'a')

}



func wonderfulSubstrings(word string) int64 {

    cnt := make([]int64, 1024)

    cnt[0] = 1



    curState := 0

    res := int64(0)



    for _, c := range word {

        curState ^= 1 << get(c)



        res += cnt[curState]

        for odd := 'a'; odd <= 'j'; odd++ {

            oddState := curState ^ (1 << get(odd))

            res += cnt[oddState]

        }



        cnt[curState]++

    }



    return res

}

4.7.1047 - 2024-05-01 12:04:24 +0300 MSK

Sum of Distances in Tree

func sumOfDistancesInTree(n int, edges [][]int) []int {
	graph := make(map[int][]int)
	count := make([]int, n)
	res := make([]int, n)

	for _, edge := range edges {
		u, v := edge[0], edge[1]
		graph[u] = append(graph[u], v)
		graph[v] = append(graph[v], u)
	}

	var dfs1 func(cur, parent int)
	dfs1 = func(cur, parent int) {
		count[cur] = 1
		for _, child := range graph[cur] {
			if child != parent {
				dfs1(child, cur)
				count[cur] += count[child]
				res[cur] += res[child] + count[child]
			}
		}
	}

	var dfs2 func(cur, parent int)
	dfs2 = func(cur, parent int) {
		for _, child := range graph[cur] {
			if child != parent {
				res[child] = res[cur] + n - 2*count[child]
				dfs2(child, cur)
			}
		}
	}

	dfs1(0, -1)
	dfs2(0, -1)

	return res
}

4.7.1048 - 2024-05-01 12:02:52 +0300 MSK

Reverse Prefix of Word
func reversePrefix(word string, ch byte) string {
    var natija string
    for i := 0; i < len(word); i++ {
        if word[i] == ch { 
            ch_index := i
            for i >= 0 {
                natija += string(word[i])
                i--
            } 
            return natija + word[ch_index + 1 : ]
        }
    }    
    return word
}

4.7.1049 - 2024-04-29 21:04:33 +0300 MSK

Minimum Number of Operations to Make Array XOR Equal to K
func minOperations(nums []int, k int) int {
    res := k
    for _, n := range nums {
        res ^= n
    }
    var ans int
    for res > 0 {
        ans += res%2
        res = res >> 1
    }
    return ans
}

4.7.1050 - 2024-04-26 10:34:22 +0300 MSK

Minimum Falling Path Sum II


type Triplet struct {
	minSum       int
	secondMinSum int
	minSumIndex  int
}

func minFallingPathSum(grid [][]int) int {
	return minFallingPathSumHelper(0, grid).minSum
}

func minFallingPathSumHelper(row int, grid [][]int) Triplet {
	if row == len(grid) {
		return Triplet{0, 0, 0}
	}

	nextRowTriplet := minFallingPathSumHelper(row+1, grid)
	currentTriplet := Triplet{math.MaxInt32, math.MaxInt32, -1}

	for col := 0; col < len(grid[0]); col++ {
		var value int
		if col != nextRowTriplet.minSumIndex {
			value = grid[row][col] + nextRowTriplet.minSum
		} else {
			value = grid[row][col] + nextRowTriplet.secondMinSum
		}

		if value <= currentTriplet.minSum {
			currentTriplet.secondMinSum = currentTriplet.minSum
			currentTriplet.minSum = value
			currentTriplet.minSumIndex = col
		} else if value < currentTriplet.secondMinSum {
			currentTriplet.secondMinSum = value
		}
	}

	return currentTriplet
}

4.7.1051 - 2024-04-25 20:32:24 +0300 MSK

Longest Ideal Subsequence
func longestIdealString(s string, k int) int {
	dp := make([]int, 27)
	n := len(s)

	for i := n - 1; i >= 0; i-- {
		cc := s[i]
		idx := int(cc - 'a')
		maxi := -1 << 31

		left := max(idx-k, 0)
		right := min(idx+k, 26)

		for j := left; j <= right; j++ {
			maxi = max(maxi, dp[j])
		}

		dp[idx] = maxi + 1
	}

	max := -1 << 31
	for _, val := range dp {
		if val > max {
			max = val
		}
	}

	return max
}

func max(a, b int) int {
	if a > b {
		return a
	}
	return b
}

func min(a, b int) int {
	if a < b {
		return a
	}
	return b
}

4.7.1052 - 2024-04-24 15:06:12 +0300 MSK

N-th Tribonacci Number
func tribonacci(n int) int {
	if n < 2 {
		return n
	}

	dp := []int{0, 1, 1}

	for i := 3; i <= n; i++ {
		next := dp[0] + dp[1] + dp[2]
		dp[0], dp[1], dp[2] = dp[1], dp[2], next
	}

	return dp[2]
}

4.7.1053 - 2024-04-23 18:14:09 +0300 MSK

Minimum Height Trees


func findMinHeightTrees(n int, edges [][]int) []int {
	counts := make([]int, n)
	links := make([]int, n)
	for _, edge := range edges {
		links[edge[0]] ^= edge[1]
		counts[edge[0]]++
		links[edge[1]] ^= edge[0]
		counts[edge[1]]++
	}
	Qu := make([]int, 0)
	dists := make([]int, n)
	for i := 0; i < n; i++ {
		if counts[i] == 1 {
			Qu = append(Qu, i)
		}
	}
	stp := 1
	for len(Qu) > 0 {
		size := len(Qu)
		for j := 0; j < size; j++ {
			tmp := Qu[0]
			Qu = Qu[1:]
			links[links[tmp]] ^= tmp
			counts[links[tmp]]--
			if counts[links[tmp]] == 1 {
				dists[links[tmp]] = int(math.Max(float64(stp), float64(dists[links[tmp]])))
				Qu = append(Qu, links[tmp])
			}
		}
		stp++
	}
	maxDist := 0
	for _, dist := range dists {
		if dist > maxDist {
			maxDist = dist
		}
	}
	res := make([]int, 0)
	for i, dist := range dists {
		if dist == maxDist {
			res = append(res, i)
		}
	}
	return res
}

4.7.1054 - 2024-04-22 10:35:20 +0300 MSK

Find if Path Exists in Graph
type UnionFind struct {
    parent []int
    rank   []int
}

func NewUnionFind(n int) *UnionFind {
    parent := make([]int, n)
    rank := make([]int, n)
    for i := 0; i < n; i++ {
        parent[i] = i
    }
    return &UnionFind{parent, rank}
}

func (uf *UnionFind) Find(u int) int {
    if uf.parent[u] != u {
        uf.parent[u] = uf.Find(uf.parent[u])
    }
    return uf.parent[u]
}

func (uf *UnionFind) UnionByRank(u, v int) {
    i := uf.Find(u)
    j := uf.Find(v)
    if i == j {
        return
    }
    if uf.rank[i] < uf.rank[j] {
        uf.parent[i] = j
    } else if uf.rank[i] > uf.rank[j] {
        uf.parent[j] = i
    } else {
        uf.parent[i] = j
        uf.rank[j]++
    }
}

func validPath(n int, edges [][]int, source int, destination int) bool {
    uf := NewUnionFind(n)
    for _, edge := range edges {
        u, v := edge[0], edge[1]
        uf.UnionByRank(u, v)
    }
    return uf.Find(source) == uf.Find(destination)
}

4.7.1055 - 2024-04-22 10:16:09 +0300 MSK

Open the Lock
import "strconv"

func openLock(deadends []string, target string) int {
    pow10 := []int{1, 10, 100, 1000}
    visit := make([]int, 10000) // 0: not visited, 1: visited through forward direction, -1: visited through backward direction, 2: deadends
    for _, dead := range deadends {
        num, _ := strconv.Atoi(dead)
        visit[num] = 2
    }
    src := 0
    dest, _ := strconv.Atoi(target)
    steps := 0
    dir := 1
    if visit[src] == 2 || visit[dest] == 2 {
        return -1
    }
    if src == dest {
        return 0
    }
    forward := make([]int, 0)
    backward := make([]int, 0)
    forward = append(forward, src)
    visit[src] = 1
    backward = append(backward, dest)
    visit[dest] = -1
    for len(forward) > 0 && len(backward) > 0 {
        if len(forward) > len(backward) {
            forward, backward = backward, forward
            dir = -dir
        }
        steps++
        size := len(forward)
        for j := 0; j < size; j++ {
            cur := forward[0]
            forward = forward[1:]
            for _, p := range pow10 {
                d := (cur / p) % 10
                for _, i := range []int{-1, 1} {
                    z := d + i
                    if z == -1 {
                        z = 9
                    } else if z == 10 {
                        z = 0
                    }
                    next := cur + (z-d)*p
                    if visit[next] == -dir {
                        return steps
                    }
                    if visit[next] == 0 {
                        forward = append(forward, next)
                        visit[next] = dir
                    }
                }
            }
        }
    }
    return -1
}

4.7.1056 - 2024-04-20 21:02:52 +0300 MSK

Find All Groups of Farmland
func findFarmland(land [][]int) [][]int {
	result := [][]int{}
	m, n := len(land), len(land[0])
	findFarmlandCoordinates := func(row, col int) []int {
		coordinates := []int{row, col}
		r, c := row, col
		for r < m && land[r][col] == 1 {
			r++
		}
		for c < n && land[row][c] == 1 {
			c++
		}
		coordinates = append(coordinates, r-1, c-1)
		for i := row; i < r; i++ {
			for j := col; j < c; j++ {
				land[i][j] = 0
			}
		}
		return coordinates
    }
	for i := 0; i < m; i++ {
		for j := 0; j < n; j++ {
			if land[i][j] == 1 {
				result = append(result, findFarmlandCoordinates(i, j))
			}
		}
	}
	return result
}

4.7.1057 - 2024-04-19 10:37:47 +0300 MSK

Island Perimeter
func islandPerimeter(grid [][]int) int {
    islands := 0
    neighbors := 0

    for i := 0; i < len(grid); i++ {
        for j := 0; j < len(grid[0]); j++ {
            if grid[i][j] == 1 {
                islands++
                if i-1 >= 0 && grid[i-1][j] == 1 {
                    neighbors++
                }
                if j-1 >= 0 && grid[i][j-1] == 1 {
                    neighbors++
                }
            }
        }
    }

    return islands*4 - neighbors*2
}

4.7.1058 - 2024-04-19 10:37:20 +0300 MSK

Number of Islands
func numIslands(grid [][]byte) int {
    if len(grid) == 0 || len(grid[0]) == 0 {
        return 0
    }
    
    rows := len(grid)
    cols := len(grid[0])
    islands := 0
    
    var dfs func(row, col int)
    dfs = func(row, col int) {
        if row < 0 || col < 0 || row >= rows || col >= cols || grid[row][col] != '1' {
            return
        }
        grid[row][col] = '0'
        dfs(row-1, col)
        dfs(row+1, col)
        dfs(row, col-1)
        dfs(row, col+1)
    }
    
    for row := 0; row < rows; row++ {
        for col := 0; col < cols; col++ {
            if grid[row][col] == '1' {
                dfs(row, col)
                islands++
            }
        }
    }
    
    return islands
}

4.7.1059 - 2024-04-17 10:49:35 +0300 MSK

Smallest String Starting From Leaf
/**
 * Definition for a binary tree node.
 * type TreeNode struct {
 *     Val int
 *     Left *TreeNode
 *     Right *TreeNode
 * }
 */
func smallestFromLeaf(root *TreeNode) string {
	ans := ""
	var dfs func(node *TreeNode, text string)
	dfs = func(node *TreeNode, text string) {
		if node == nil {
			return
		}
		text = string(rune(node.Val + 97)) + text
		if node.Right == nil && node.Left == nil {
			if ans == "" || ans > text {
				ans = text
			}
			return
		}
		dfs(node.Left, text)
		dfs(node.Right, text)
	}

	dfs(root, "")
	return ans
}

4.7.1060 - 2024-04-16 22:16:34 +0300 MSK

Add One Row to Tree
/**
 * Definition for a binary tree node.
 * type TreeNode struct {
 *     Val int
 *     Left *TreeNode
 *     Right *TreeNode
 * }
 */
func addOneRow(root *TreeNode, val int, depth int) *TreeNode {
    if root == nil {
        return nil
    }

    if depth == 1 {
        root = &TreeNode{Val: val, Left: root}
    } else if (depth == 2) {
        root.Left = &TreeNode{Val: val, Left: root.Left}
        root.Right = &TreeNode{Val: val, Right: root.Right}
    } else {
        addOneRow(root.Left, val, depth - 1)
        addOneRow(root.Right, val, depth - 1)
    }

    return root;
}

4.7.1061 - 2024-04-15 09:51:02 +0300 MSK

Sum Root to Leaf Numbers
/**
 * Definition for a binary tree node.
 * type TreeNode struct {
 *     Val int
 *     Left *TreeNode
 *     Right *TreeNode
 * }
 */
func sumNumbers(root *TreeNode) int {
    return dfs(root, 0)
}

func dfs(node *TreeNode, num int) int {
    if node == nil {
        return 0
    }
    if node.Left == nil && node.Right == nil {
        return num * 10 + node.Val
    }
    return dfs(node.Left, num * 10 + node.Val) + dfs(node.Right, num * 10 + node.Val)
}

4.7.1062 - 2024-04-15 09:49:56 +0300 MSK

Sum of Left Leaves
/**
 * Definition for a binary tree node.
 * type TreeNode struct {
 *     Val int
 *     Left *TreeNode
 *     Right *TreeNode
 * }
 */
func sumOfLeftLeaves(root *TreeNode) int {
    if root == nil {
        return 0
    }

    left := 0
    if root.Left != nil && root.Left.Left == nil && root.Left.Right == nil {
        left = root.Left.Val
    }

    return left + sumOfLeftLeaves(root.Left) + sumOfLeftLeaves(root.Right)
}

4.7.1063 - 2024-04-13 18:32:47 +0300 MSK

Maximal Rectangle
func maximalRectangle(matrix [][]byte) int {
    heights := make([]int, len(matrix[0]) + 1)
    heights[len(heights)-1] = -1
    mx := 0
    for _, row := range matrix {
        for i := range row {
            if row[i] == '1' {
                heights[i]++
            } else {
                heights[i] = 0
            }
        }

        stack := []int{}
        for i, currentHeight := range heights {
            for len(stack) > 0 && heights[stack[len(stack)-1]] > currentHeight {
                prev := heights[stack[len(stack)-1]]
                stack = stack[:len(stack)-1]

                width := i
                if len(stack) > 0 {
                    width = i - stack[len(stack)-1] - 1
                }
                mx = max(mx, prev * width)
            }
            stack = append(stack, i)
        } 
    }
    return mx
}

4.7.1064 - 2024-04-12 10:40:19 +0300 MSK

Trapping Rain Water
func trap(height []int) int {
	var waterStored int
	leftElevationPoint, rightElevationPoint := 0, len(height)-1                                    // pointers for left and right elevations
	maxLeftElevation, maxRightElevation := height[leftElevationPoint], height[rightElevationPoint] // max value of left and right elevation points

	for leftElevationPoint < rightElevationPoint { // until left elevation point reaches right elevation point or right elevation point reaches left elevation point
		if maxLeftElevation < maxRightElevation { // if max left elevation is smaller than max right elevation
			leftElevationPoint++                               // move the left elevation point by 1
			if height[leftElevationPoint] > maxLeftElevation { // if height of current left elevation after moving is greater than max left elevation
				maxLeftElevation = height[leftElevationPoint] // swap the max left elevation with current left elevation point value
			}
			waterStored += maxLeftElevation - height[leftElevationPoint] // store water with delta of max left elevation and current left elevation
		} else {
			rightElevationPoint--                                // decrease the right elevation by 1
			if height[rightElevationPoint] > maxRightElevation { // if height of current right elevation after decreasing is greater than max right elevation
				maxRightElevation = height[rightElevationPoint] // swap the max right elevation with current right elevation point value
			}
			waterStored += maxRightElevation - height[rightElevationPoint] // store water with delta of max right elevation and current right elevation
		}
	}

	return waterStored
}

4.7.1065 - 2024-04-11 13:44:41 +0300 MSK

Remove K Digits
func removeKdigits(num string, k int) string {
	res := make([]rune, 0)
    
	for _, c := range num {
		for len(res) > 0 && res[len(res) - 1] > c && k > 0 {
			res = res[:len(res) - 1]
			k--
		}

		if len(res) > 0 || c != '0' {
			res = append(res, c)
		}
	}

	for len(res) > 0 && k > 0 {
		res = res[:len(res) - 1]
		k--
	}

	if len(res) == 0 {
		return "0"
	}
	return string(res)
}

4.7.1066 - 2024-04-10 13:25:18 +0300 MSK

Reveal Cards In Increasing Order
func deckRevealedIncreasing(deck []int) []int {
	n := len(deck)
	sort.Ints(deck)

	res := make([]int, n)
	queue := make([]int, n)

	for i := range queue {
		queue[i] = i
	}

	for _, card := range deck {
		idx := queue[0]
		queue = queue[1:]
		res[idx] = card

		if len(queue) > 0 {
			queue = append(queue, queue[0])
			queue = queue[1:]
		}
	}

	return res
}

4.7.1067 - 2024-04-09 14:21:46 +0300 MSK

Time Needed to Buy Tickets
func timeRequiredToBuy(tickets []int, k int) int {
    n := len(tickets)
    d := tickets[k]
    res := 0
    for i := 0; i <= k; i++ {
        res += min(d, tickets[i])
    }
    for i := k + 1; i < n; i++ {
        res += min(d - 1, tickets[i])
    }
    return res
}

4.7.1068 - 2024-04-08 11:25:34 +0300 MSK

Number of Students Unable to Eat Lunch
func countStudents(students []int, sandwiches []int) int {
    req := make([]int, 2)
    for _, student := range students {
        req[student]++
    }

    for _, sandwich := range sandwiches {
        if req[sandwich] == 0 {
            return req[1 - sandwich]
        } else {
            req[sandwich]--
        }
    }

    return 0
}

4.7.1069 - 2024-04-07 11:42:18 +0300 MSK

Valid Parenthesis String
func checkValidString(s string) bool {
    open := 0
    openMax := 0
    for _, char := range s {
        switch char {
        case '(':
            open++
            openMax++
        case ')':
            open--
            openMax--
        default:
            open--
            openMax++
        }
        if openMax < 0 {
            return false
        }
        if open < 0 {
            open = 0
        }
    }
    return open == 0
}

4.7.1070 - 2024-04-07 11:41:54 +0300 MSK

Minimum Remove to Make Valid Parentheses
type stack struct {
    top   int
    v     []byte
    index []int
}

func minRemoveToMakeValid(s string) string {
    stc := stack{top: -1}

    // collect bad brackets
    for i, v := range s {
        if v == '(' {
            stc.v = append(stc.v, '(')
            stc.index = append(stc.index, i)
            stc.top++
        } else if v == ')' {
            if stc.top > -1 && stc.v[stc.top] == '(' {
                stc.v = stc.v[:stc.top]
                stc.index = stc.index[:stc.top]
                stc.top--
            } else {
                stc.v = append(stc.v, ')')
                stc.index = append(stc.index, i)
                stc.top++
            }
        }
    }

    // remove them
    res := []byte{}
    i := 0
    for _, v := range stc.index {
        res = append(res, s[i:v]...)
        i = v + 1
    }

    // checking of end
    if len(res) + len(stc.index) < len(s) {
        res = append(res, s[i:]...)
    }

    return string(res)
}

4.7.1071 - 2024-04-05 17:17:39 +0300 MSK

Make The String Great
func makeGood(s string) string {
	stack := make([]byte, 0, len(s))
	stack = append(stack, s[0])
	for i := 1; i < len(s); i++ {
		if len(stack) > 0 && getDiff(stack[len(stack)-1], s[i]) == 32 {
			stack = stack[:len(stack)-1]
			continue
		}
		stack = append(stack, s[i])
	}
	return string(stack)
}

func getDiff(a, b uint8) uint8 {
	if b > a {
		return b - a
	}
	return a - b
}

4.7.1072 - 2024-04-04 16:06:45 +0300 MSK

Maximum Nesting Depth of the Parentheses
func maxDepth(s string) int {
    maxDepth := 0
    curDepth := 0
    for _, ch := range s {
        if ch == '(' {
            curDepth++
            maxDepth = max(maxDepth, curDepth)
        } else if ch == ')' {
            curDepth--
        }
    }
    return maxDepth
}

4.7.1073 - 2024-04-03 10:52:54 +0300 MSK

Word Search
func exist(board [][]byte, word string) bool {
    if nLetters := len(board) * len(board[0]); nLetters < len(word) {
        return false
    }

    for i := range board {
        for j := range board[i] {
            if dfs(i, j, 0, board, word, make(map[pair]struct{})) {
                return true
            }
        }
    }

    return false
}

type pair struct {
    r, c int
}

func dfs(r, c, i int, board [][]byte, word string, visited map[pair]struct{}) bool {
    if i == len(word) {
        return true
    }

    inBounds := r >= 0 && r < len(board) && c >= 0 && c < len(board[0])
    if _, ok := visited[pair{r, c}]; !inBounds || ok || word[i] != board[r][c] {
        return false
    }

    visited[pair{r, c}] = struct{}{}

    up := dfs(r+1, c, i+1, board, word, visited)
    down := dfs(r-1, c, i+1, board, word, visited)
    right := dfs(r, c+1, i+1, board, word, visited)
    left := dfs(r, c-1, i+1, board, word, visited)

    delete(visited, pair{r, c})

    return up || down || right || left
}

4.7.1074 - 2024-04-02 17:28:57 +0300 MSK

Isomorphic Strings
func isIsomorphic(s string, t string) bool {
    map1 := make([]int, 128) // Stores frequency of s
    map2 := make([]int, 128) // Stores frequency of t

    for i := 0; i < len(s); i++ {
        sCh := s[i]
        tCh := t[i]

        if map1[sCh] == 0 && map2[tCh] == 0 {
            map1[sCh] = int(tCh)
            map2[tCh] = int(sCh)
        } else if map1[sCh] != int(tCh) || map2[tCh] != int(sCh) {
            return false
        }
    }
    return true
}

4.7.1075 - 2024-04-01 18:03:03 +0300 MSK

Length of Last Word
func lengthOfLastWord(s string) int {
    length := len(s)
    count := 0
    for i := length - 1; i >= 0; i-- {
        isSpace := s[i] == ' '
        if isSpace && count != 0 {
            return count
        } else if isSpace {
            continue
        }
        count++
    }
    return count
}

4.7.1076 - 2024-03-31 10:58:30 +0300 MSK

Count Subarrays With Fixed Bounds
func countSubarrays(nums []int, minK int, maxK int) int64 {
    var res int64
	left := 0
	pmin := -1
	pmax := -1

	for right, num := range nums {
		if num < minK || num > maxK {
			left = right + 1
			pmin = -1
			pmax = -1
		} else {
			if num == minK {
				pmin = right
			}
			if num == maxK {
				pmax = right
			}
			res += int64(max(0, min(pmin, pmax) - left + 1))
		}
	}

	return res
}

4.7.1077 - 2024-03-30 19:24:47 +0300 MSK

Subarrays with K Different Integers
func subarraysWithAtMostKDistinct(nums []int, k int) int {
    if k == 0 {
        return 0
    }

    countOccurrence := make(map[int]int)
    differentIntegers := 0
    left := 0
    result := 0

    for right := 0; right < len(nums); right++ {
        countOccurrence[nums[right]]++
        if countOccurrence[nums[right]] == 1 {
            differentIntegers++
        }

        for differentIntegers > k {
            countOccurrence[nums[left]]--
            if countOccurrence[nums[left]] == 0 {
                differentIntegers--
            }
            left++
        }

        result += right - left + 1
    }
    return result
}

func subarraysWithKDistinct(nums []int, k int) int {
    return subarraysWithAtMostKDistinct(nums, k) - subarraysWithAtMostKDistinct(nums, k-1)
}

4.7.1078 - 2024-03-29 14:30:16 +0300 MSK

Count Subarrays Where Max Element Appears at Least K Times
func countSubarrays(nums []int, k int) int64 {
	maxValue := 0
	var maxValueIds []int
	var ans int64

	for i, x := range nums {
		if x > maxValue {
			maxValue, ans, maxValueIds = x, 0, []int{}
		}

		if x == maxValue {
			maxValueIds = append(maxValueIds, i)
		}

		if len(maxValueIds) >= k {
			ans += int64(maxValueIds[len(maxValueIds)-k]) + 1
		}
	}

	return ans
}

4.7.1079 - 2024-03-28 19:02:58 +0300 MSK

Length of Longest Subarray With at Most K Frequency
func maxSubarrayLength(nums []int, k int) int {
    i := 0
    j := 0
    n := len(nums)
    ans := 1
    mp := make(map[int]int)

    for i < n {
        mp[nums[i]]++
        for mp[nums[i]] > k {
            mp[nums[j]]--
            j++
        }
        if i-j+1 > ans {
            ans = i - j + 1
        }
        i++
    }
    return ans
}

4.7.1080 - 2024-03-27 18:55:43 +0300 MSK

Subarray Product Less Than K
func numSubarrayProductLessThanK(nums []int, k int) int {
	if k <= 1 {
		return 0
	}

	l := 0
	p := 1
	res := 0
	for r, num := range nums {
		p *= num
		for p >= k {
			p /= nums[l]
			l++
		}
        
		res += r - l + 1
	}

	return res
}

4.7.1081 - 2024-03-26 10:04:37 +0300 MSK

First Missing Positive
func firstMissingPositive(nums []int) int {
    n := len(nums)

	for i := 0; i < n; i++ {
		if nums[i] <= 0 || nums[i] > n {
			nums[i] = n + 1
		}
	}

	for i := 0; i < n; i++ {
		val := abs(nums[i])
		if val >= 1 && val <= n {
			flagIndex := val - 1
			if nums[flagIndex] > 0 {
				nums[flagIndex] *= -1
			}
		}
	}

	for i := 1; i <= n; i++ {
		if nums[i - 1] > 0 {
			return i
		}
	}

	return n + 1
}

func abs(x int) int {
    if x < 0 {
        return -x
    }
    return x
}

4.7.1082 - 2024-03-25 19:23:11 +0300 MSK

Find All Duplicates in an Array
func findDuplicates(nums []int) []int {
    output := []int{}
    for _, num := range nums {
        idx := abs(num)
        if nums[idx-1] < 0 {
            output = append(output, idx)
        } else {
            nums[idx-1] *= -1
        }
    }
    return output
}
func abs(num int) int {
    if num < 0 {
        return -num
    }
    return num
}

4.7.1083 - 2024-03-24 14:27:34 +0300 MSK

Find the Duplicate Number
func findDuplicate(nums []int) int {
    seen := make(map[int]struct{})
    for _, num := range nums {
        if _, ok := seen[num]; ok {
            return num
        }
        seen[num] = struct{}{}
    }
    return -1
}

4.7.1084 - 2024-03-24 14:27:17 +0300 MSK

Find the Duplicate Number
func findDuplicate(nums []int) int {
    seen := make(map[int]struct{}, len(nums) - 1)
    for _, num := range nums {
        if _, ok := seen[num]; ok {
            return num
        }
        seen[num] = struct{}{}
    }
    return -1
}

4.7.1085 - 2024-03-23 20:51:44 +0300 MSK

Reorder List
func reorderList(head *ListNode) {
    if head == nil || head.Next == nil {
        return
    }

    middle := midNode(head)
    newHead := middle.Next
    middle.Next = nil

    newHead = reverseLinkedList(newHead)

    c1 := head
    c2 := newHead
    var f1, f2 *ListNode

    for c1 != nil && c2 != nil {
        // Backup
        f1 = c1.Next
        f2 = c2.Next

        // Linking
        c1.Next = c2
        c2.Next = f1

        // Move
        c1 = f1
        c2 = f2
    }
}

func midNode(head *ListNode) *ListNode {
    slow := head
    fast := head

    for fast.Next != nil && fast.Next.Next != nil {
        slow = slow.Next
        fast = fast.Next.Next
    }
    return slow
}

func reverseLinkedList(head *ListNode) *ListNode {
    var prev, curr, forw *ListNode = nil, head, nil

    for curr != nil {
        forw = curr.Next
        curr.Next = prev
        prev = curr
        curr = forw
    }
    return prev
}

4.7.1086 - 2024-03-22 11:45:00 +0300 MSK

Palindrome Linked List
/**
 * Definition for singly-linked list.
 * type ListNode struct {
 *     Val int
 *     Next *ListNode
 * }
 */
func isPalindrome(head *ListNode) bool {
    nodes := []int{}
    for head != nil {
        nodes = append(nodes, head.Val)
        head = head.Next
    }
    length := len(nodes)
    for i := range(length / 2) {
        start, end := nodes[i], nodes[length-i-1]
        if start != end {
            return false
        }
    }
    return true
}

4.7.1087 - 2024-03-22 11:41:12 +0300 MSK

Reverse Linked List
/**
 * Definition for singly-linked list.
 * type ListNode struct {
 *     Val int
 *     Next *ListNode
 * }
 */
func reverseList(head *ListNode) *ListNode {
    if head == nil {
        return nil
    }
    cur, next := head, head.Next
    head.Next = nil
    for next != nil {
        cur, next, next.Next = next, next.Next, cur
    }
    return cur
}

4.7.1088 - 2024-03-21 14:09:24 +0300 MSK

Reverse Linked List
/**
 * Definition for singly-linked list.
 * type ListNode struct {
 *     Val int
 *     Next *ListNode
 * }
 */
func reverseList(head *ListNode) *ListNode {
    if head == nil {
        return nil
    }
    cur, next := head, head.Next
    head.Next = nil
    for next != nil {
        cur, next, next.Next = next, next.Next, cur
    }
    return cur
}

4.7.1089 - 2024-03-21 14:05:27 +0300 MSK

Reverse Linked List
/**
 * Definition for singly-linked list.
 * type ListNode struct {
 *     Val int
 *     Next *ListNode
 * }
 */
func reverseList(head *ListNode) *ListNode {
    if head == nil {
        return nil
    }
    cur, next := head, head.Next
    cur.Next = nil
    for next != nil {
        cur, next, next.Next = next, next.Next, cur
    }
    return cur
}

4.7.1090 - 2024-03-21 13:53:28 +0300 MSK

Merge In Between Linked Lists
/**
 * Definition for singly-linked list.
 * type ListNode struct {
 *     Val int
 *     Next *ListNode
 * }
 */
func mergeInBetween(list1 *ListNode, a int, b int, list2 *ListNode) *ListNode {
    if list1 == nil {
        return list2 
    }
    list2Head, list2Tail := list2, list2
    for list2 != nil {
        list2Tail = list2
        list2 = list2.Next
    }
    count := 0
    list1Head := list1
    for list1 != nil {
        next := list1.Next
        if count == a - 1 {
            list1.Next = list2Head
        } else if count == b {
            list2Tail.Next = list1.Next
        }
        list1 = next
        count++
    }
    return list1Head
}

4.7.1091 - 2024-03-20 21:13:36 +0300 MSK

Task Scheduler
func leastInterval(tasks []byte, n int) int {
	if n == 0 {
		return len(tasks)
	}

	cnt := make([]int, 26)
	for _, task := range tasks {
		cnt[task - 'A']++
	}

	var maxCount, sameMaxCount int
	for _, c := range cnt {
		if c > maxCount {
			maxCount = c
			sameMaxCount = 1
		} else if c == maxCount {
			sameMaxCount++
		}
	}

	res := (n + 1) * (maxCount - 1) + sameMaxCount
    if (res > len(tasks)) {
        return res
    } else {
        return len(tasks)
    }
}

4.7.1092 - 2024-03-20 21:12:54 +0300 MSK

Merge In Between Linked Lists
/**
 * Definition for singly-linked list.
 * type ListNode struct {
 *     Val int
 *     Next *ListNode
 * }
 */
func mergeInBetween(list1 *ListNode, a int, b int, list2 *ListNode) *ListNode {
    l := list1
    for i := 1; i <= a - 1; i++ {
        l = l.Next
    }

    prev := l
    r := l
    for i := a; i <= b + 1; i++ {
        r = r.Next
        prev.Next = nil
        prev = r
    }

    list2Tail := list2
    for list2Tail.Next != nil {
        list2Tail = list2Tail.Next
    }

    l.Next = list2
    list2Tail.Next = r

    return list1
}

4.7.1093 - 2024-03-18 19:30:56 +0300 MSK

Minimum Number of Arrows to Burst Balloons
func findMinArrowShots(points [][]int) int {
    // Sort the balloons based on their end coordinates
    sort.Slice(points, func(i, j int) bool {
        return points[i][1] < points[j][1]
    })

    arrows := 1
    prevEnd := points[0][1]

    // Count the number of non-overlapping intervals
    for i := 1; i < len(points); i++ {
        if points[i][0] > prevEnd {
            arrows++
            prevEnd = points[i][1]
        }
    }

    return arrows
}

4.7.1094 - 2024-03-17 12:32:47 +0300 MSK

Contiguous Array
func findMaxLength(nums []int) int {
    hashmap := make(map[int]int)
    zeros, ones, maxLen := 0, 0, 0
    hashmap[0] = -1 
    for i, num := range nums {
        if num == 0 {
            zeros++
        } else {
            ones++
        }
        diff := zeros - ones
        if val, ok := hashmap[diff]; ok {
            maxLen = max(maxLen, i - val)
        } else {
            hashmap[diff] = i
        }
    }
    return maxLen
}

4.7.1095 - 2024-03-17 12:32:06 +0300 MSK

Insert Interval
func insert(intervals [][]int, newInterval []int) [][]int {
	var result [][]int

    // Iterate through intervals and add non-overlapping intervals before newInterval
	i := 0
	for i < len(intervals) && intervals[i][1] < newInterval[0] {
		result = append(result, intervals[i])
		i++
	}

    // Merge overlapping intervals
	for i < len(intervals) && intervals[i][0] <= newInterval[1] {
		newInterval[0] = int(math.Min(float64(newInterval[0]), float64(intervals[i][0])))
		newInterval[1] = int(math.Max(float64(newInterval[1]), float64(intervals[i][1])))
		i++
	}

    // Add merged newInterval
	result = append(result, newInterval)

    // Add non-overlapping intervals after newInterval
	for i < len(intervals) {
		result = append(result, intervals[i])
		i++
	}

	return result
}

4.7.1096 - 2024-03-15 20:15:18 +0300 MSK

Product of Array Except Self
func productExceptSelf(nums []int) []int {
    n := len(nums)
    res := make([]int, n)

    preProduct := 1
    for i := 0; i < n; i++ {
        res[i] = preProduct
        preProduct *= nums[i]
    }

    sufProduct := 1
    for i := n - 1; i >= 0; i-- {
        res[i] *= sufProduct
        sufProduct *= nums[i]
    }

    return res
}

4.7.1097 - 2024-03-14 19:06:22 +0300 MSK

Binary Subarrays With Sum
func numSubarraysWithSum(nums []int, goal int) int {

    hashmap := make(map[int]int)

    hashmap[0] = 1

    sum := 0

    count := 0



    for _, num := range nums {

        sum += num

        rem := sum - goal

        if val, ok := hashmap[rem]; ok {

            count += val

        }

        hashmap[sum]++

    }



    return count

}

4.7.1098 - 2024-03-13 19:53:19 +0300 MSK

Find the Pivot Integer
func getSum(x int) int {
	return x * (x + 1) / 2
}

func pivotInteger(n int) int {
    sum := getSum(n)

	l, r := 1, n
	for l <= r {
		m := (l + r) / 2
		firstPart := getSum(m)
		secondPart := sum - firstPart + m

		if firstPart == secondPart {
			return m
		} else if firstPart > secondPart {
			r = m - 1
		} else {
			l = m + 1
		}
	}

	return -1
}

4.7.1099 - 2024-03-12 19:08:41 +0300 MSK

Remove Zero Sum Consecutive Nodes from Linked List
/**
 * Definition for singly-linked list.
 * type ListNode struct {
 *     Val int
 *     Next *ListNode
 * }
 */
func removeZeroSumSublists(head *ListNode) *ListNode {
    dummy := &ListNode{0, head}
    prefixSumToNode := make(map[int]*ListNode)
    prefixSum := 0
    for current := dummy; current != nil; current = current.Next {
        prefixSum += current.Val
        if prev, found := prefixSumToNode[prefixSum]; found {
            toRemove := prev.Next
            p := prefixSum
            if toRemove != nil {
                p += toRemove.Val
            }
            for toRemove != nil && p != prefixSum {
                delete(prefixSumToNode, p)
                toRemove = toRemove.Next
                if toRemove != nil {
                    p += toRemove.Val
                }
            }
            prev.Next = current.Next
        } else {
            prefixSumToNode[prefixSum] = current
        }
    }
    return dummy.Next
}

4.7.1100 - 2024-03-11 19:30:24 +0300 MSK

Custom Sort String
func customSortString(order string, s string) string {
    count := make([]int, 26)

    for _, c := range s {
        count[c-'a']++
    }

    var result strings.Builder

    for _, c := range order {
        result.WriteString(strings.Repeat(string(c), count[c-'a']))
        count[c-'a'] = 0
    }

    for i := 0; i < 26; i++ {
        result.WriteString(strings.Repeat(string('a'+i), count[i]))
    }
    // UPVOTE :)
    return result.String()
}

4.7.1101 - 2024-03-10 22:58:44 +0300 MSK

Intersection of Two Arrays
func intersection(nums1 []int, nums2 []int) []int {
    seen := make([]int, 1000)
    for i := range nums1 {
        seen[nums1[i]]++
    }

    res := make([]int, 0)
    for i := range nums2 {
        if seen[nums2[i]] > 0 {
            res = append(res, nums2[i])
            seen[nums2[i]] = 0
        }
    }

    return res
}

4.7.1102 - 2024-03-09 19:01:11 +0300 MSK

Count Elements With Maximum Frequency
func maxFrequencyElements(nums []int) int {
    mapCount := make(map[int]int)

    for _, val := range nums {
        mapCount[val]++
    }

    count := 0
    max := -1
    for _, freq := range mapCount {
        if freq > max {
            max = freq
        }
    }

    for _, freq := range mapCount {
        if freq == max {
            count += max
        }
    }
    return count
}

4.7.1103 - 2024-03-09 18:59:53 +0300 MSK

Minimum Common Value
func getCommon(nums1 []int, nums2 []int) int {
    var l, r int
    for l < len(nums1) && r < len(nums2) {
        switch {
        case nums1[l] == nums2[r]:
            return nums1[l]
        case nums1[l] < nums2[r]:
            l++
        default:
            r++
        }
    }
    return -1
}

4.7.1104 - 2024-03-07 19:08:46 +0300 MSK

Middle of the Linked List
/**
 * Definition for singly-linked list.
 * type ListNode struct {
 *     Val int
 *     Next *ListNode
 * }
 */
func middleNode(head *ListNode) *ListNode {
    if head.Next == nil {
        return head
    }
    slow, fast := head, head.Next
    move := true
    for fast.Next != nil {
        if move {
            slow = slow.Next
            move = false
        } else {
            move = true
        }
        fast = fast.Next
    }
    if move {
        return slow.Next
    }
    return slow
}

4.7.1105 - 2024-03-07 19:07:46 +0300 MSK

Middle of the Linked List
/**
 * Definition for singly-linked list.
 * type ListNode struct {
 *     Val int
 *     Next *ListNode
 * }
 */
func middleNode(head *ListNode) *ListNode {
    if head.Next == nil {
        return head
    }
    slow, fast := head, head.Next
    move := true
    for fast.Next != nil {
        if move {
            slow = slow.Next
            move = false
        } else {
            move = true
        }
        fast = fast.Next
    }
    if move {
        slow = slow.Next
    }
    return slow
}

4.7.1106 - 2024-03-06 16:05:23 +0300 MSK

Linked List Cycle
/**
 * Definition for singly-linked list.
 * type ListNode struct {
 *     Val int
 *     Next *ListNode
 * }
 */
func hasCycle(head *ListNode) bool {
    nodes := map[*ListNode]struct{}{}
    for head != nil {
        if _, ok := nodes[head]; ok {
            return true
        }
        nodes[head] = struct{}{}
        head = head.Next
    }
    return false
}

4.7.1107 - 2024-03-05 11:52:38 +0300 MSK

Minimum Length of String After Deleting Similar Ends
func minimumLength(s string) int {
    left := 0
    right := len(s) - 1
    
    for left < right {
        lc := s[left]
        rc := s[right]
        
        if lc != rc {
            return right - left + 1
        }
        
        for left + 1 < right && lc == s[left + 1] {
            left++
        }
        
        for left < right - 1 && rc == s[right - 1] {
            right--
        }
        
        right--
        left++
    }
    
    return right - left + 1
}

4.7.1108 - 2024-03-04 16:21:41 +0300 MSK

Bag of Tokens
func bagOfTokensScore(tokens []int, power int) int {
    n := len(tokens)
	sort.Ints(tokens)
	res := 0

	l := 0
	r := n - 1

	for l <= r {
		for l <= r && power >= tokens[l] {
			power -= tokens[l]
			l++
			res++
		}
		
		if res == 0 {
			break
		}

        if r - l + 1 <= 2 {
			break
		}

		power += tokens[r]
		r--
		res--
	}

	return res
}

4.7.1109 - 2024-03-03 10:57:46 +0300 MSK

Remove Nth Node From End of List
/**
 * Definition for singly-linked list.
 * type ListNode struct {
 *     Val int
 *     Next *ListNode
 * }
 */
func removeNthFromEnd(head *ListNode, n int) *ListNode {
    res := &ListNode{0, head}

    lead := res
    for i := 0; i <= n; i++ {
        lead = lead.Next
    }

    cur := res
    for lead != nil {
        cur = cur.Next
        lead = lead.Next
    }

    cur.Next = cur.Next.Next
    return res.Next
}

4.7.1110 - 2024-03-02 15:59:13 +0300 MSK

Squares of a Sorted Array
func sortedSquares(nums []int) []int {
    for i, num := range nums {
        if num < 0 {
            nums[i] = -num
        } else { 
            break
        }
    }
    slices.Sort(nums)
    for i, num := range nums {
        nums[i] = num * num
    }
    return nums
}

4.7.1111 - 2024-03-02 15:57:16 +0300 MSK

Squares of a Sorted Array
func sortedSquares(nums []int) []int {
    for i, num := range nums {
        nums[i] = num * num
    }
    slices.Sort(nums)
    return nums
}

4.7.1112 - 2024-03-02 15:56:40 +0300 MSK

Squares of a Sorted Array
func sortedSquares(nums []int) []int {
    for i, num := range nums {
        if num < 0 {
            nums[i] = -num
        }
    }
    slices.Sort(nums)
    for i, num := range nums {
        nums[i] = num * num
    }
    return nums
}

4.7.1113 - 2024-03-01 18:28:31 +0300 MSK

Maximum Odd Binary Number
func maximumOddBinaryNumber(s string) string {
	l := len(s)
	res := make([]byte, l)
	index0, index1 := l-2, l-1
	for i := 0; i < l; i++ {
		if s[i] == '0' {
			res[index0] = '0'
			index0--
		} else {
			res[index1] = '1'
			index1 = (index1 + 1) % l
		}
	}
	return string(res)
}

4.7.1114 - 2024-02-29 17:38:44 +0300 MSK

Even Odd Tree
/**
 * Definition for a binary tree node.
 * type TreeNode struct {
 *     Val int
 *     Left *TreeNode
 *     Right *TreeNode
 * }
 */
func isEvenOddTree(root *TreeNode) bool {
    q := []*TreeNode{root}
    for i:= 0; len(q) > 0; i++ {
        var prev *TreeNode
        for _, node := range q {
            q = q[1:]

            if i % 2 == 0 && node.Val % 2 != 1 {
                return false
            }

            if i % 2 == 1 && node.Val % 2 != 0 {
                return false
            }

            if prev != nil && i % 2 == 0 && prev.Val >= node.Val {
                return false
            }

            if prev != nil && i % 2 == 1 && prev.Val <= node.Val {
                return false
            }
           
            prev = node
            if node.Left != nil {
                q = append(q, node.Left)
            }

            if node.Right != nil {
                q = append(q, node.Right)
            }
        }
    }
    return true
}

4.7.1115 - 2024-02-28 12:31:13 +0300 MSK

Find Bottom Left Tree Value
/**
 * Definition for a binary tree node.
 * type TreeNode struct {
 *     Val int
 *     Left *TreeNode
 *     Right *TreeNode
 * }
 */
func findBottomLeftValue(root *TreeNode) int {
    _, val := getBottomLeft(root)
    return val
}

func getBottomLeft(root *TreeNode) (int, int) {
    left, right := root.Left, root.Right
    if right == nil && left == nil {
        return 0, root.Val
    }
    if right == nil {
        depth, val := getBottomLeft(root.Left)
        return 1 + depth, val
    }
    if left == nil {
        depth, val := getBottomLeft(root.Right)
        return 1 + depth, val
    }
    leftDepth, leftVal := getBottomLeft(root.Left)
    rightDepth, rightVal := getBottomLeft(root.Right)
    if rightDepth > leftDepth {
        return 1 + rightDepth, rightVal
    }
    return 1 + leftDepth, leftVal
}

4.7.1116 - 2024-02-27 19:25:53 +0300 MSK

Diameter of Binary Tree
var maxD int

func diameterOfBinaryTree(root *TreeNode) int {
    maxD = 0
    find(root)
    return maxD
}

func find(root *TreeNode) int {
    if root == nil {
        return 0
    }
    left := find(root.Left)
    right := find(root.Right)
    localMax := left + right
    maxD = max(maxD, localMax)
    return max(left, right) + 1
}

func max(a, b int) int {
    if a > b {
        return a
    }
    return b
}

4.7.1117 - 2024-02-26 19:57:46 +0300 MSK

Same Tree
/**
 * Definition for a binary tree node.
 * type TreeNode struct {
 *     Val int
 *     Left *TreeNode
 *     Right *TreeNode
 * }
 */
func isSameTree(p *TreeNode, q *TreeNode) bool {
    if p == nil && q == nil {
        return true
    }
    if p == nil || q == nil || p.Val != q.Val {
        return false
    }
    return isSameTree(p.Left, q.Left) && isSameTree(p.Right, q.Right)
}

4.7.1118 - 2024-02-25 20:04:05 +0300 MSK

Greatest Common Divisor Traversal
func canTraverseAllPairs(nums []int) bool {
    if len(nums) == 1 {
        return true
    }
    n := len(nums)
    maxElement := nums[0]
    minElement := nums[0]
    for _, num := range nums {
        if num > maxElement {
            maxElement = num
        }
        if num < minElement {
            minElement = num
        }
    }
    if minElement == 1 {
        return false
    }
    factorArray := factorsCalculator(maxElement)

    parent := make([]int, maxElement+1)
    rank := make([]int, maxElement+1)
    for i := 0; i <= maxElement; i++ {
        parent[i] = i
        rank[i] = 1
    }

    for _, num := range nums {
        x := num
        for x > 1 {
            p := factorArray[x]
            union(parent, rank, p, num)
            for x%p == 0 {
                x = x / p
            }
        }
    }

    p := find(parent, nums[0])
    for i := 1; i < n; i++ {
        if find(parent, nums[i]) != p {
            return false
        }
    }

    return true
}

func factorsCalculator(n int) []int {
    dp := make([]int, n+2)
    for i := 0; i < len(dp); i++ {
        dp[i] = i
    }
    for i := 2; i <= n; i++ {
        if dp[i] == i {
            for j := i * 2; j <= n; j += i {
                if dp[j] == j {
                    dp[j] = i
                }
            }
        }
    }
    return dp
}

func find(parent []int, a int) int {
    if parent[a] == a {
        return a
    }
    parent[a] = find(parent, parent[a])
    return parent[a]
}

func union(parent []int, rank []int, a int, b int) {
    a = find(parent, a)
    b = find(parent, b)
    if a == b {
        return
    }
    if rank[a] < rank[b] {
        a, b = b, a
    }
    parent[b] = a
    rank[a] += rank[b]
}

4.7.1119 - 2024-02-24 15:45:37 +0300 MSK

Find All People With Secret
package main

import (
	"sort"
)

func find(groups []int, index int) int {
	for index != groups[index] {
		index = groups[index]
	}
	return index
}

func findAllPeople(n int, meetings [][]int, firstPerson int) []int {
	groups := make([]int, 100000)
	var result []int
	var temp []int

	for i := 0; i < n; i++ {
		groups[i] = i
	}
	groups[firstPerson] = 0

	sort.Slice(meetings, func(i, j int) bool {
		return meetings[i][2] < meetings[j][2]
	})

	i := 0
	for i < len(meetings) {
		currentTime := meetings[i][2]
		temp = temp[:0]
		for i < len(meetings) && meetings[i][2] == currentTime {
			g1 := find(groups, meetings[i][0])
			g2 := find(groups, meetings[i][1])
			groups[max(g1, g2)] = min(g1, g2)
			temp = append(temp, meetings[i][0], meetings[i][1])
			i++
		}
		for _, j := range temp {
			if find(groups, j) != 0 {
				groups[j] = j
			}
		}
	}

	for j := 0; j < n; j++ {
		if find(groups, j) == 0 {
			result = append(result, j)
		}
	}

	return result
}

func max(a, b int) int {
	if a > b {
		return a
	}
	return b
}

func min(a, b int) int {
	if a < b {
		return a
	}
	return b
}

4.7.1120 - 2024-02-23 12:30:25 +0300 MSK

Cheapest Flights Within K Stops
type Connection struct {
	city int
	cost int
}

type queue []Connection

func (q *queue) push(c Connection) {
	q1 := []Connection{c}
	*q = append(*q, q1...)
}

func (q *queue) pop() (bool, Connection) {

	if q.isEmpty() {
		return false, Connection{}
	} else {
		elem := (*q)[0]
		*q = (*q)[1:]
		return true, elem
	}
}

func (q queue) isEmpty() bool {
	return q.size() <= 0
}

func (q queue) size() int {
	return len(q)
}

func findCheapestPrice(n int, flights [][]int, src int, dst int, k int) int {

	minCost := math.MaxInt64

	fQueue := new(queue)
	fQueue.push(Connection{src, 0})

	maxStops := k + 1

	costOfFlights := make([][]int, n)
	for i := range costOfFlights {
		costOfFlights[i] = make([]int, n)
	}

	flightsMap := make(map[int][]int)
	for _, v := range flights {
		if _, ok := flightsMap[v[0]]; ok {
			flightsMap[v[0]] = append(flightsMap[v[0]], v[1])
		} else {
			flightsMap[v[0]] = []int{v[1]}
		}

		costOfFlights[v[0]][v[1]] = v[2]
	}

	cityPathCost := make([]int, n) // path cost from source
	for i := range cityPathCost {
		cityPathCost[i] = math.MaxInt64
	}

	cityPathCost[src] = 0

	for !fQueue.isEmpty() && maxStops >= 0 {

		size := fQueue.size()
		maxStops--

		for size > 0 {
			_, c := fQueue.pop()
			size--

			if c.city == dst {
				if minCost > c.cost {
					minCost = c.cost
				}
				continue
			}

			for _, v := range flightsMap[c.city] {

				newCost := c.cost + costOfFlights[c.city][v]

				if cityPathCost[v] > newCost {
					fQueue.push(Connection{v, newCost})
					cityPathCost[v] = newCost
				}
			}
		}
	}

	if minCost == math.MaxInt64 {
		minCost = -1
	}

	return minCost
}

4.7.1121 - 2024-02-22 11:20:36 +0300 MSK

Find the Town Judge
func findJudge(n int, trust [][]int) int {
    fromTo := make([][]int, n)
    toFrom := make([][]int, n)
    for _, trustArray := range trust {
        from, to := trustArray[0], trustArray[1]
        fromTo[from-1] = append(fromTo[from-1], to)
        toFrom[to-1] = append(toFrom[to-1], from)
    }
    for i, from := range toFrom {
        if len(from) == n - 1 && len(fromTo[i]) == 0 {
            return i + 1
        }
    }
    return -1
}

4.7.1122 - 2024-02-21 11:42:07 +0300 MSK

Bitwise AND of Numbers Range
class Solution:
    def rangeBitwiseAnd(self, left: int, right: int) -> int:
        shift = 0
        while left != right:
            left >>= 1
            right >>= 1
            shift += 1
        return left << shift

4.7.1123 - 2024-02-20 18:21:21 +0300 MSK

Missing Number
import operator
class Solution:
    def missingNumber(self, nums: List[int]) -> int:
        return reduce(
            operator.xor, 
            nums, 
            reduce(operator.xor, tuple(range(len(nums) + 1)), 0)
        )

4.7.1124 - 2024-02-20 18:19:05 +0300 MSK

Missing Number
import operator
class Solution:
    def missingNumber(self, nums: List[int]) -> int:
        nums.extend(range(len(nums) + 1))
        return reduce(operator.xor, nums, 0)

4.7.1125 - 2024-02-20 18:16:37 +0300 MSK

Missing Number
import operator
class Solution:
    def missingNumber(self, nums: List[int]) -> int:
        length = len(nums)
        return reduce(operator.xor, range(length), reduce(operator.xor, nums, length))

4.7.1126 - 2024-02-20 15:10:36 +0300 MSK

Missing Number
class Solution:
    def missingNumber(self, nums: List[int]) -> int:
        def xor(total: int, i: int) -> int:
            return total ^ nums[i] ^ (i + 1)
        return reduce(xor, chain((0, ), range(len(nums))))

4.7.1127 - 2024-02-19 11:56:55 +0300 MSK

Power of Two
class Solution:
    def isPowerOfTwo(self, n: int) -> bool:
        return n > 0 and n & (n - 1) == 0

4.7.1128 - 2024-02-18 12:45:46 +0300 MSK

Meeting Rooms III
class Solution:
    def mostBooked(self, n: int, meetings: List[List[int]]) -> int:
        unused_rooms, used_rooms = list(range(n)), []
        heapify(unused_rooms)
        meeting_count = [0] * n
        for start, end in sorted(meetings):
            while used_rooms and used_rooms[0][0] <= start:
                _, room = heappop(used_rooms)
                heappush(unused_rooms, room)
            if unused_rooms:
                room = heappop(unused_rooms)
                heappush(used_rooms, [end, room])
            else:
                room_availability_time, room = heappop(used_rooms)
                heappush(
                    used_rooms,
                    [room_availability_time + end - start, room]
                )
            meeting_count[room] += 1
        return meeting_count.index(max(meeting_count))

4.7.1129 - 2024-02-17 15:07:38 +0300 MSK

Furthest Building You Can Reach
class Solution:
    def furthestBuilding(self, heights: List[int], bricks: int, ladders: int) -> int:
        heap = []
        i = 0
        length = len(heights)
        for i in range(length - 1):
            diff = heights[i + 1] - heights[i]           
            if diff <= 0:
                continue
            bricks -= diff
            heapq.heappush(heap, -diff)
            if bricks < 0:
                bricks += -heapq.heappop(heap)
                ladders -= 1
            if ladders < 0:
                return i
        return length - 1
  

4.7.1130 - 2024-02-17 15:03:52 +0300 MSK

Furthest Building You Can Reach
class Solution:
   def furthestBuilding(self, h: List[int], b: int, l: int) -> int:
       p = []
       
       i = 0
       for i in range(len(h) - 1):
           diff = h[i + 1] - h[i]
           
           if diff <= 0:
               continue
           
           b -= diff
           x = heapq.heappush(p, -diff)
           print(x)
           if b < 0:
               b += -heapq.heappop(p)
               l -= 1
               
           if l < 0:
               return i
       return len(h)-1
  

4.7.1131 - 2024-02-16 18:29:09 +0300 MSK

Least Number of Unique Integers after K Removals
class Solution:
    def findLeastNumOfUniqueInts(self, arr: List[int], k: int) -> int:
        counter = defaultdict(int)
        for num in arr:
            counter[num] += 1
        nums = [(count, num) for num, count in counter.items()]
        nums.sort()
        removed = 0
        for count, num in nums:
            if k < count:
                break
            k -= count
            removed += 1
        return len(counter) - removed

4.7.1132 - 2024-02-15 12:51:25 +0300 MSK

Find Polygon With the Largest Perimeter
class Solution:
    def largestPerimeter(self, nums: List[int]) -> int:
        nums.sort()
        previous_elements_sum = 0
        ans = -1
        for num in nums:
            if num < previous_elements_sum:
                ans = num + previous_elements_sum
            previous_elements_sum += num
        return ans

4.7.1133 - 2024-02-14 10:48:17 +0300 MSK

Rearrange Array Elements by Sign
class Solution:
    def rearrangeArray(self, nums: List[int]) -> List[int]:
        res = []
        pos, neg = [], []
        length = len(nums)
        for i in range(length):
            num = nums[i]
            if num > 0:
                pos.append(num)
            else:
                neg.append(num)
        pos.reverse()
        neg.reverse()
        while pos and neg:
            res.extend((pos.pop(), neg.pop()))
        return res

4.7.1134 - 2024-02-13 16:10:55 +0300 MSK

Find First Palindromic String in the Array
class Solution:
    def firstPalindrome(self, words: List[str]) -> str:
        for s in words:
            for i in range(len(s) // 2):
                if s[i] != s[-i - 1]:
                    break
            else:
                return s
        return ""

4.7.1135 - 2024-02-12 12:50:44 +0300 MSK

Majority Element
class Solution:
    def majorityElement(self, nums: List[int]) -> int:
        counter = defaultdict(int)
        half = len(nums) // 2
        for num in nums:
            counter[num] += 1
            if counter[num] > half:
                return num
        raise Exception()

4.7.1136 - 2024-02-11 16:20:27 +0300 MSK

Cherry Pickup II
class Solution:
    def cherryPickup(self, grid: List[List[int]]) -> int:
        n = len(grid)
        m = len(grid[0])

        # Create 3D DP table with initial values of 0
        dp = [[[0] * m for _ in range(m)] for _ in range(n)]

        # Set the starting point value (top-left and top-right corner)
        cherries = 0
        dp[0][0][m - 1] = grid[0][0] + grid[0][m - 1]

        # Iterate through each row from second onwards
        for i in range(1, n):
            # Iterate through each column for robot 1
            for j in range(m):
                # Iterate through each column for robot 2
                for k in range(m):
                    # Skip invalid states:
                    # - Both robots in the same row (j > i)
                    # - Robot 2 left of robot 1 (k < m - i - 1)
                    # - Robot 1 further right than robot 2 (j > k)
                    if j > i or k < m - i - 1 or j > k:
                        continue
                    # Base case: no moves possible, use previous state
                    dp[i][j][k] = dp[i - 1][j][k]
                    # Explore moves for robot 1:
                    # - Up-diagonal with robot 2 at same position
                    if j - 1 >= 0:
                        dp[i][j][k] = max(dp[i][j][k], dp[i - 1][j - 1][k])
                    # - Up-diagonal with robot 2 one step left/right
                    if j - 1 >= 0 and k - 1 >= 0:
                        dp[i][j][k] = max(dp[i][j][k], dp[i - 1][j - 1][k - 1])
                    if j - 1 >= 0 and k + 1 < m:
                        dp[i][j][k] = max(dp[i][j][k], dp[i - 1][j - 1][k + 1])
                    # Explore moves for robot 2:
                    # - Up-diagonal with robot 1 at same position
                    if j + 1 < m:
                        dp[i][j][k] = max(dp[i][j][k], dp[i - 1][j + 1][k])
                    # - Up-diagonal with robot 1 one step left/right
                    if j + 1 < m and k - 1 >= 0:
                        dp[i][j][k] = max(dp[i][j][k], dp[i - 1][j + 1][k - 1])
                    if j + 1 < m and k + 1 < m:
                        dp[i][j][k] = max(dp[i][j][k], dp[i - 1][j + 1][k + 1])
                    # Explore horizontal moves for both robots:
                    # - Both robots move left
                    if k - 1 >= 0:
                        dp[i][j][k] = max(dp[i][j][k], dp[i - 1][j][k - 1])
                    # - Both robots move right
                    if k + 1 < m:
                        dp[i][j][k] = max(dp[i][j][k], dp[i - 1][j][k + 1])
                    # Add cherries only if robots are in different positions
                    if j != k:
                        dp[i][j][k] += grid[i][j] + grid[i][k]
                    else:
                        dp[i][j][k] += grid[i][j]  # Only one robot picks if they land in the same cell
                    # Update maximum cherries collected so far
                    cherries = max(cherries, dp[i][j][k])

        return cherries

4.7.1137 - 2024-02-10 15:12:54 +0300 MSK

Palindromic Substrings
class Solution:
    def countSubstrings(self, s: str) -> int:
        n = len(s)
        palindrome = [[False] * n for _ in range(n)]
        ans = 0

        for i in range(n):
            palindrome[i][i] = True
            ans += 1

        for i in range(n - 1):
            if s[i] == s[i + 1]:
                palindrome[i][i + 1] = True
                ans += 1

        for length in range(3, n + 1):
            for i in range(n - length + 1):
                if s[i] == s[i + length - 1] and palindrome[i + 1][i + length - 2]:
                    palindrome[i][i + length - 1] = True
                    ans += 1

        return ans

4.7.1138 - 2024-02-09 19:12:32 +0300 MSK

Largest Divisible Subset
class Solution:
    def largestDivisibleSubset(self, nums: List[int]) -> List[int]:
        nums.sort()
        n = len(nums)
        dp = [1] * n
        max_size, max_index = 1, 0

        for i in range(1, n):
            for j in range(i):
                if nums[i] % nums[j] == 0:
                    dp[i] = max(dp[i], dp[j] + 1)
                    if dp[i] > max_size:
                        max_size = dp[i]
                        max_index = i

        result = []
        num = nums[max_index]
        for i in range(max_index, -1, -1):
            if num % nums[i] == 0 and dp[i] == max_size:
                result.append(nums[i])
                num = nums[i]
                max_size -= 1

        return result

4.7.1139 - 2024-02-08 15:50:03 +0300 MSK

Perfect Squares
class Solution:
    def numSquares(self, n: int) -> int:
        dp = [float('inf')] * (n + 1)
        dp[0] = 0
        for i in range(1, n + 1):
            min_val = float('inf')
            j = 1
            while j * j <= i:
                min_val = min(min_val, dp[i - j * j] + 1)
                j += 1
            dp[i] = min_val
        return dp[n]

4.7.1140 - 2024-02-07 10:59:44 +0300 MSK

Sort Characters By Frequency
class Solution:
    def frequencySort(self, s: str) -> str:
        counter = defaultdict(int)
        for char in s:
            counter[char] += 1
        pq = [(-freq, char) for char, freq in counter.items()]
        heapq.heapify(pq)
        result = []
        while pq:
            freq, char = heapq.heappop(pq)
            result.append(char * -freq)
        return "".join(result)

4.7.1141 - 2024-02-07 10:54:21 +0300 MSK

Sort Characters By Frequency
class Solution:
    def frequencySort(self, s: str) -> str:
        counter = {}
        for char in s:
            if char not in counter:
                counter[char] = -ord(char)
            counter[char] -= 100
        return "".join(sorted(s, key=lambda val: counter[val]))

4.7.1142 - 2024-02-07 10:52:55 +0300 MSK

Sort Characters By Frequency
class Solution:
    def frequencySort(self, s: str) -> str:
        counter = {}
        for char in s:
            if char not in counter:
                counter[char] = ord(char)
            counter[char] += 100
        return "".join(sorted(s, key=lambda val: -counter[val]))

4.7.1143 - 2024-02-07 10:49:08 +0300 MSK

Sort Characters By Frequency
class Solution:
    def frequencySort(self, s: str) -> str:
        counter = defaultdict(int)
        for char in s:
            counter[char] += 1
        return "".join(sorted(s, key=lambda val: -(ord(val) + counter[val] * 100)))

4.7.1144 - 2024-02-06 09:02:52 +0300 MSK

Group Anagrams
class Solution:
    def groupAnagrams(self, strs: List[str]) -> List[List[str]]:
        anagrams = defaultdict(list)
        for anagram in strs:
            anagrams[tuple(sorted(anagram))].append(anagram)
        return anagrams.values()

4.7.1145 - 2024-02-05 10:12:58 +0300 MSK

First Unique Character in a String
class Solution:
    def firstUniqChar(self, s: str) -> int:
        counter = [0] * 26

        for char in s:
            idx = ord(char) - ord('a')
            if counter[idx] in (0, 1):
                counter[idx] += 1
        for i in range(len(s)):
            if counter[ord(s[i]) - ord('a')] == 1:
                return i
        return -1

4.7.1146 - 2024-02-04 15:38:07 +0300 MSK

Partition Array for Maximum Sum
class Solution:
    def maxSumAfterPartitioning(self, arr: List[int], k: int) -> int:
        min_num = -1
        length = len(arr)
        last_idx = length - 1
        cache = [-1] * length

        def dp(start: int) -> int:
            cached = cache[start]
            if cached != -1:
                return cached
            max_num = min_num
            max_sum = 0
            for i in range(start, min(start + k, length)):
                max_num = max(max_num, arr[i])
                cur_sum = max_num * (i - start + 1)
                if i != last_idx:
                    cur_sum += dp(i + 1)
                max_sum = max(max_sum, cur_sum)
            cache[start] = max_sum
            return max_sum
        
        return dp(0)
            

4.7.1147 - 2024-02-04 15:17:08 +0300 MSK

Minimum Window Substring
class Solution:
    def minWindow(self, s: str, t: str) -> str:
        if not s or not t:
            return ""

        dictT = defaultdict(int)
        for c in t:
            dictT[c] += 1

        required = len(dictT)
        l, r = 0, 0
        formed = 0

        windowCounts = defaultdict(int)
        ans = [-1, 0, 0]

        while r < len(s):
            c = s[r]
            windowCounts[c] += 1

            if c in dictT and windowCounts[c] == dictT[c]:
                formed += 1

            while l <= r and formed == required:
                c = s[l]

                if ans[0] == -1 or r - l + 1 < ans[0]:
                    ans[0] = r - l + 1
                    ans[1] = l
                    ans[2] = r

                windowCounts[c] -= 1
                if c in dictT and windowCounts[c] < dictT[c]:
                    formed -= 1

                l += 1

            r += 1

        return "" if ans[0] == -1 else s[ans[1]:ans[2] + 1]

4.7.1148 - 2024-02-02 19:53:06 +0300 MSK

Divide Array Into Arrays With Max Difference
class Solution:
    def divideArray(self, nums, k):
        size = len(nums)
        if size % 3 != 0:
            return []

        nums.sort()

        result = []
        group_index = 0
        for i in range(0, size, 3):
            if i + 2 < size and nums[i + 2] - nums[i] <= k:
                result.append([nums[i], nums[i + 1], nums[i + 2]])
                group_index += 1
            else:
                return []
        return result

4.7.1149 - 2024-02-02 19:52:11 +0300 MSK

Divide Array Into Arrays With Max Difference
class Solution:
    def divideArray(self, nums, k):
        size = len(nums)
        if size % 3 != 0:
            return []

        nums.sort()

        result = []
        group_index = 0
        for i in range(0, size, 3):
            if i + 2 < size and nums[i + 2] - nums[i] <= k:
                result.append([nums[i], nums[i + 1], nums[i + 2]])
                group_index += 1
            else:
                return []
        return result

4.7.1150 - 2024-02-02 19:51:07 +0300 MSK

Sequential Digits
class Solution:
    def sequentialDigits(self, low, high):
        a = []

        for i in range(1, 10):
            num = i
            next_digit = i + 1

            while num <= high and next_digit <= 9:
                num = num * 10 + next_digit
                if low <= num <= high:
                    a.append(num)
                next_digit += 1

        a.sort()
        return a

4.7.1151 - 2024-01-31 11:09:51 +0300 MSK

Daily Temperatures
class Solution:
    def dailyTemperatures(self, temperatures: List[int]) -> List[int]:
        temps_left = defaultdict(list)
        to_pop = []
        length = len(temperatures)
        ans = [0] * length
        for i in range(length):
            temp = temperatures[i]
            for temp_left, ids in temps_left.items():
                if temp <= temp_left:
                    continue
                for id in ids:
                    ans[id] = i - id
                to_pop.append(temp_left)
            temps_left[temp].append(i)
            for temp in to_pop:
                temps_left.pop(temp)
            to_pop.clear()
        
        return ans

4.7.1152 - 2024-01-30 15:36:53 +0300 MSK

Evaluate Reverse Polish Notation
class Solution:
    def evalRPN(self, tokens: List[str]) -> int:
        stack: list[int] = []
        for token in tokens:
            match token:
                case "+":
                    stack.append(stack.pop() + stack.pop())
                case "-":
                    last, prev = stack.pop(), stack.pop()
                    stack.append(prev - last)
                case "*":
                    stack.append(stack.pop() * stack.pop())
                case "/": 
                    last, prev = stack.pop(), stack.pop()
                    stack.append(int(prev / last))
                case _:
                    stack.append(int(token))
        return stack[0]

4.7.1153 - 2024-01-29 09:44:33 +0300 MSK

Implement Queue using Stacks
class MyQueue:

    def __init__(self):
        self.stack_in = []
        self.stack_out = []

    def push(self, x: int) -> None:
        self.stack_in.append(x)

    def pop(self) -> int:
        self.peek()
        return self.stack_out.pop()

    def peek(self) -> int:
        if self.stack_out:
            return self.stack_out[-1]
        
        while self.stack_in:
            self.stack_out.append(self.stack_in.pop())

        return self.stack_out[-1]

    def empty(self) -> bool:
        return not self.stack_out and not self.stack_in


# Your MyQueue object will be instantiated and called as such:
# obj = MyQueue()
# obj.push(x)
# param_2 = obj.pop()
# param_3 = obj.peek()
# param_4 = obj.empty()

4.7.1154 - 2024-01-28 13:34:03 +0300 MSK

Number of Submatrices That Sum to Target
class Solution:
    def numSubmatrixSumTarget(self, matrix, target):
        m, n = len(matrix), len(matrix[0])

        for row in range(m):
            for col in range(1, n):
                matrix[row][col] += matrix[row][col - 1]

        count = 0

        for c1 in range(n):
            for c2 in range(c1, n):
                prefix_sum_count = {0: 1}
                sum_val = 0

                for row in range(m):
                    sum_val += matrix[row][c2] - (matrix[row][c1 - 1] if c1 > 0 else 0)
                    count += prefix_sum_count.get(sum_val - target, 0)
                    prefix_sum_count[sum_val] = prefix_sum_count.get(sum_val, 0) + 1

        return count

4.7.1155 - 2024-01-27 10:05:52 +0300 MSK

K Inverse Pairs Array
class Solution:
    def kInversePairs(self, n: int, k: int) -> int:
        MOD = 10**9 + 7
        dp = [[0] * (k + 1) for _ in range(n + 1)]

        for i in range(1, n + 1):
            for j in range(k + 1):
                if j == 0:
                    dp[i][j] = 1
                else:
                    val = (dp[i - 1][j] + MOD - (dp[i - 1][j - i] if j - i >= 0 else 0)) % MOD
                    dp[i][j] = (dp[i][j - 1] + val) % MOD

        return (dp[n][k] + MOD - (dp[n][k - 1] if k > 0 else 0)) % MOD

4.7.1156 - 2024-01-26 11:02:15 +0300 MSK

Out of Boundary Paths
class Solution:

    def findPaths(self, m: int, n: int, N: int, x: int, y: int) -> int:

        M = 1000000000 + 7

        dp = [[0] * n for _ in range(m)]

        dp[x][y] = 1

        count = 0



        for moves in range(1, N + 1):

            temp = [[0] * n for _ in range(m)]



            for i in range(m):

                for j in range(n):

                    if i == m - 1:

                        count = (count + dp[i][j]) % M

                    if j == n - 1:

                        count = (count + dp[i][j]) % M

                    if i == 0:

                        count = (count + dp[i][j]) % M

                    if j == 0:

                        count = (count + dp[i][j]) % M

                    temp[i][j] = (

                        ((dp[i - 1][j] if i > 0 else 0) + (dp[i + 1][j] if i < m - 1 else 0)) % M +

                        ((dp[i][j - 1] if j > 0 else 0) + (dp[i][j + 1] if j < n - 1 else 0)) % M

                    ) % M



            dp = temp



        return count

4.7.1157 - 2024-01-25 17:31:23 +0300 MSK

Longest Common Subsequence
class Solution:
    def longestCommonSubsequence(self, text1: str, text2: str) -> int:
        # Get the lengths of both input strings
        len_text1, len_text2 = len(text1), len(text2)
      
        # Initialize a 2D array (list of lists) with zeros for dynamic programming
        # The array has (len_text1 + 1) rows and (len_text2 + 1) columns
        dp_matrix = [[0] * (len_text2 + 1) for _ in range(len_text1 + 1)]
      
        # Loop through each character index of text1 and text2
        for i in range(1, len_text1 + 1):
            for j in range(1, len_text2 + 1):
                # If the characters match, take the diagonal value and add 1
                if text1[i - 1] == text2[j - 1]:
                    dp_matrix[i][j] = dp_matrix[i - 1][j - 1] + 1
                else:
                    # If the characters do not match, take the maximum of the value from the left and above
                    dp_matrix[i][j] = max(dp_matrix[i - 1][j], dp_matrix[i][j - 1])
      
        # The bottom-right value in the matrix contains the length of the longest common subsequence
        return dp_matrix[len_text1][len_text2]

4.7.1158 - 2024-01-24 10:39:27 +0300 MSK

Pseudo-Palindromic Paths in a Binary Tree
# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def pseudoPalindromicPaths (self, root: Optional[TreeNode]) -> int:
        if not root:
            return 0
        
        num_count = defaultdict(int)
        perm_count = 0

        def traverse(node: TreeNode) -> int:
            val, left, right = node.val, node.left, node.right
            num_count[val] += 1
            res = 0
            if not left and not right:
                non_even = 0
                for num in num_count.values():
                    if num % 2 == 0:
                        continue
                    if non_even == 1:
                        break
                    non_even += 1
                else:
                    res += 1
            if left:
                res += traverse(left)
            if right: 
                res += traverse(right)
            num_count[val] = max(0, num_count[val] - 1)
            return res 

        return traverse(root)

4.7.1159 - 2024-01-24 10:27:08 +0300 MSK

Pseudo-Palindromic Paths in a Binary Tree
# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def pseudoPalindromicPaths (self, root: Optional[TreeNode]) -> int:
        if not root:
            return 0
        
        num_count = defaultdict(int)
        perm_count = 0

        def traverse(node: TreeNode) -> int:
            if not node:
                return 0
            val, left, right = node.val, node.left, node.right
            num_count[val] += 1
            res = 0
            if not left and not right:
                non_even = 0
                for num in num_count.values():
                    if num % 2 == 0:
                        continue
                    non_even += 1
                    if non_even > 1:
                        break
                else:
                    res += 1
            res += traverse(left) + traverse(right)
            num_count[val] = max(0, num_count[val] - 1)
            return res 

        return traverse(root)

4.7.1160 - 2024-01-23 10:54:38 +0300 MSK

Maximum Length of a Concatenated String with Unique Characters
class Solution:
    def maxLength(self, arr: List[str]) -> int:
        cur = set()
        length = len(arr)
        max_length = 0

        def backtrack(start: int) -> None:
            nonlocal max_length 
            
            for i in range(start, length):
                new_subs = arr[i]
                new = set(new_subs)
                if len(new_subs) != len(new) or len(cur.intersection(new)) != 0:
                    continue
                cur.update(new)
                backtrack(i + 1)
                cur.difference_update(new)

            max_length = max(max_length, len(cur))

        backtrack(0)

        return max_length

4.7.1161 - 2024-01-22 12:39:06 +0300 MSK

Set Mismatch
class Solution:
    def findErrorNums(self, nums: List[int]) -> List[int]:
        length = len(nums)
        # dupl_xor_miss = duplicate ^ missing
        dupl_xor_miss = reduce(lambda total, i: total ^ i ^ nums[i - 1], range(length + 1))
        rightmost_set_bit = dupl_xor_miss & -dupl_xor_miss
        xor_group1 = xor_group2 = 0
        for i in range(1, length + 1):
            if i & rightmost_set_bit:
                xor_group1 ^= i
            else:
                xor_group2 ^= i
            if nums[i - 1] & rightmost_set_bit:
                xor_group1 ^= nums[i - 1]
            else:
                xor_group2 ^= nums[i - 1]
        for num in nums:
            if num == xor_group1:
                return num, xor_group2
            if num == xor_group2:
                return num, xor_group1 
        
        raise Exception()

4.7.1162 - 2024-01-21 21:12:22 +0300 MSK

House Robber
class Solution:
    def rob(self, nums: List[int]) -> int:
        length = len(nums)
        cache = {}

        def dp(i: int) -> int:
            if i >= length:
                return 0
            val = nums[i]
            if i in cache:
                return cache[i]
            res = max(dp(i + 1), val + dp(i + 2))
            cache[i] = res
            return res 

        return dp(0)

4.7.1163 - 2024-01-20 17:21:44 +0300 MSK

Sum of Subarray Minimums
class Solution:
    def sumSubarrayMins(self, arr: List[int]) -> int:
        n = len(arr)
        left = [-1] * n 
        right = [n] * n
        stack = []

        for i, value in enumerate(arr):
            while stack and arr[stack[-1]] >= value:  
                stack.pop()  
            if stack:
                left[i] = stack[-1]  
            stack.append(i) 

        stack = [] 

        
        for i in range(n - 1, -1, -1):  
            while stack and arr[stack[-1]] > arr[i]: 
                stack.pop()  
            if stack:
                right[i] = stack[-1]  
            stack.append(i) 

        mod = 10**9 + 7 

        result = sum((i - left[i]) * (right[i] - i) * value for i, value in enumerate(arr)) % mod
      
        return result 

4.7.1164 - 2024-01-19 11:46:22 +0300 MSK

Minimum Falling Path Sum
class Solution:
    def minFallingPathSum(self, matrix: List[List[int]]) -> int:
        length = len(matrix)
        cache = {}
        deltas = ((1, 0), (1, 1), (1, -1))
        last_row = length - 1

        def dp(row: int, col: int) -> int:
            if (row, col) in cache:
                return cache[(row, col)]
            val = matrix[row][col]
            if row == last_row:
                return val
            min_cost = None
            for delta_row, delta_col in deltas:
                new_row, new_col = row + delta_row, col + delta_col
                if new_col == length or new_col == -1:
                    continue
                cost = dp(new_row, new_col)
                min_cost = cost if min_cost is None else min(min_cost, cost)
            res = val + min_cost
            cache[(row, col)] = res
            return res

        return min(dp(0, col) for col in range(length))

4.7.1165 - 2024-01-19 11:45:33 +0300 MSK

Minimum Falling Path Sum
class Solution:
    def minFallingPathSum(self, matrix: List[List[int]]) -> int:
        length = len(matrix)
        max_val = 101 * length * length
        cache = {}
        deltas = ((1, 0), (1, 1), (1, -1))
        last_row = length - 1

        def dp(row: int, col: int) -> int:
            if (row, col) in cache:
                return cache[(row, col)]
            val = matrix[row][col]
            if row == last_row:
                return val
            min_cost = max_val
            for delta_row, delta_col in deltas:
                new_row, new_col = row + delta_row, col + delta_col
                if new_col == length or new_col == -1:
                    continue
                cost = dp(new_row, new_col)
                min_cost = min(min_cost, cost)
            res = val + min_cost
            cache[(row, col)] = res
            return res

        return min(dp(0, col) for col in range(length))

4.7.1166 - 2024-01-18 13:27:10 +0300 MSK

Climbing Stairs
class Solution:
    def climbStairs(self, n: int) -> int:
        prev, cur = 1, 2
        if n == prev:
            return prev
        if n == cur:
            return cur
        for i in range(2, n):
            new = prev + cur
            cur, prev = new, cur
        return cur

4.7.1167 - 2024-01-17 19:14:04 +0300 MSK

Unique Number of Occurrences
class Solution:
    def uniqueOccurrences(self, arr: List[int]) -> bool:
        counts = defaultdict(int)
        for num in arr:
            counts[num] += 1

        viewed = set()
        for _, count in counts.items():
            if count in viewed:
                return False
            viewed.add(count)
        return True

4.7.1168 - 2024-01-16 11:04:01 +0300 MSK

Insert Delete GetRandom O(1)
import random

class RandomizedSet:

    def __init__(self):
        self._nums_map = {}
        self._nums = []
        

    def insert(self, val: int) -> bool:
        if val in self._nums_map:
            return False
        self._nums_map[val] = len(self._nums)
        self._nums.append(val)
        return True

    def remove(self, val: int) -> bool:
        if val not in self._nums_map:
            return False
        last = self._nums[-1]
        idx = self._nums_map[val]
        self._nums_map[last] = idx
        self._nums[idx] = last
        self._nums.pop()
        self._nums_map.pop(val)
        return True
        
    def getRandom(self) -> int:
        return random.choice(self._nums) 


# Your RandomizedSet object will be instantiated and called as such:
# obj = RandomizedSet()
# param_1 = obj.insert(val)
# param_2 = obj.remove(val)
# param_3 = obj.getRandom()

4.7.1169 - 2024-01-15 11:45:13 +0300 MSK

Find Players With Zero or One Losses
class Solution:
    def findWinners(self, matches):
        losses = [0] * 100001

        for winner, loser in matches:
            if losses[winner] == 0:
                losses[winner] = -1

            if losses[loser] == -1:
                losses[loser] = 1
            else:
                losses[loser] += 1

        zero_loss = [i for i in range(1, 100001) if losses[i] == -1]
        one_loss = [i for i in range(1, 100001) if losses[i] == 1]

        return [zero_loss, one_loss]

4.7.1170 - 2024-01-14 17:27:29 +0300 MSK

Determine if Two Strings Are Close

class Solution:
    def closeStrings(self, word1: str, word2: str) -> bool:
        freq1 = [0] * 26
        freq2 = [0] * 26

        for ch in word1:
            freq1[ord(ch) - ord('a')] += 1

        for ch in word2:
            freq2[ord(ch) - ord('a')] += 1

        for i in range(26):
            if (freq1[i] == 0 and freq2[i] != 0) or (freq1[i] != 0 and freq2[i] == 0):
                return False

        freq1.sort()
        freq2.sort()

        for i in range(26):
            if freq1[i] != freq2[i]:
                return False

        return True

4.7.1171 - 2024-01-13 17:33:48 +0300 MSK

Minimum Number of Steps to Make Two Strings Anagram
class Solution:
    def minSteps(self, s: str, t: str) -> int:
        count_s = [0] * 26
        count_t = [0] * 26

        for char in s:
            count_s[ord(char) - ord('a')] += 1

        for char in t:
            count_t[ord(char) - ord('a')] += 1

        steps = 0
        for i in range(26):
            steps += abs(count_s[i] - count_t[i])

        return steps // 2

4.7.1172 - 2024-01-12 23:55:40 +0300 MSK

Determine if String Halves Are Alike
class Solution:
    def halvesAreAlike(self, s: str) -> bool:
        def count_vowels(string):
            vowels = set('aeiouAEIOU')
            return sum(1 for char in string if char in vowels)

        length = len(s)
        mid_point = length // 2

        first_half = s[:mid_point]
        second_half = s[mid_point:]

        return count_vowels(first_half) == count_vowels(second_half)

4.7.1173 - 2024-01-11 12:15:51 +0300 MSK

Maximum Difference Between Node and Ancestor
# Definition for a binary tree node.
# class TreeNode(object):
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution(object):
    def maxAncestorDiff(self, root):
        if not root:
            return 0
        self.diff = 0
        self.helper(root, root.val, root.val)
        return self.diff
    
    def helper(self, root, min_val, max_val):
        if not root:
            return
        self.diff = max(self.diff, max(abs(min_val - root.val), abs(max_val - root.val)))
        min_val = min(min_val, root.val)
        max_val = max(max_val, root.val)
        self.helper(root.left, min_val, max_val)
        self.helper(root.right, min_val, max_val)
        

4.7.1174 - 2024-01-10 11:34:26 +0300 MSK

Amount of Time for Binary Tree to Be Infected
class Solution:
    def amountOfTime(self, root: Optional[TreeNode], start: int) -> int:
        def dfs(node):
            if node is None:
                return
            if node.left:
                graph[node.val].append(node.left.val)
                graph[node.left.val].append(node.val)
            if node.right:
                graph[node.val].append(node.right.val)
                graph[node.right.val].append(node.val)
            dfs(node.left)
            dfs(node.right)

        graph = defaultdict(list)
        dfs(root)
        visited = set()
        queue = deque([start])
        time = -1
        while queue:
            time += 1
            for _ in range(len(queue)):
                current_node = queue.popleft()
                visited.add(current_node)
                for neighbor in graph[current_node]:
                    if neighbor not in visited:
                        queue.append(neighbor)
        return time

4.7.1175 - 2024-01-09 19:45:41 +0300 MSK

Leaf-Similar Trees
class Solution:
    def leafSimilar(self, root1, root2):
        def dfs(node):
            if node:
                if not node.left and not node.right:
                    yield node.val
                yield from dfs(node.left)
                yield from dfs(node.right)

        return list(dfs(root1)) == list(dfs(root2))

4.7.1176 - 2024-01-08 17:44:21 +0300 MSK

Range Sum of BST
class Solution:
    def rangeSumBST(self, root: Optional[TreeNode], low: int, high: int) -> int:
        def dfs(node):
            if not node:
                return 0
            
            current_val = 0
            if low <= node.val <= high:
                current_val = node.val
            
            left_sum = dfs(node.left)
            right_sum = dfs(node.right)
            
            return current_val + left_sum + right_sum
        
        return dfs(root)

4.7.1177 - 2024-01-07 12:26:09 +0300 MSK

Maximum Profit in Job Scheduling
class Solution:
    def jobScheduling(self, startTime: List[int], endTime: List[int], profit: List[int]) -> int:
        jobs = sorted(zip(endTime, startTime, profit))
      
        number_of_jobs = len(profit)
      
        dp = [0] * (number_of_jobs + 1)
      
        for i, (current_end_time, current_start_time, current_profit) in enumerate(jobs):
            index = bisect_right(jobs, current_start_time, hi=i, key=lambda x: x[0])
            dp[i + 1] = max(dp[i], dp[index] + current_profit)
      
        return dp[number_of_jobs]

4.7.1178 - 2024-01-07 12:23:04 +0300 MSK

Arithmetic Slices II - Subsequence
class Solution:
    def numberOfArithmeticSlices(self, nums: List[int]) -> int:
        n = len(nums)
        total_count = 0  
        dp = [defaultdict(int) for _ in range(n)]

        for i in range(1, n):
            for j in range(i):
                diff = nums[i] - nums[j]
                dp[i][diff] += 1  
                if diff in dp[j]:
                    dp[i][diff] += dp[j][diff]
                    total_count += dp[j][diff]

        return total_count

4.7.1179 - 2024-01-05 13:00:49 +0300 MSK

Longest Increasing Subsequence
class Solution:
    def lengthOfLIS(self, nums: List[int]) -> int:
        if not nums:
            return 0

        n = len(nums)
        dp = [1] * n

        for i in range(1, n):
            for j in range(i):
                if nums[i] > nums[j]:
                    dp[i] = max(dp[i], dp[j] + 1)

        return max(dp)

4.7.1180 - 2024-01-04 14:11:50 +0300 MSK

Minimum Number of Operations to Make Array Empty
class Solution:
    def minOperations(self, nums: List[int]) -> int:
        counter = Counter(nums)
        ans = 0
        for c in counter.values():
            if c == 1: 
                return -1
            ans += ceil(c / 3)
        return ans

4.7.1181 - 2024-01-03 14:46:50 +0300 MSK

Number of Laser Beams in a Bank
class Solution:
    def numberOfBeams(self, bank):
        ans, temp = 0, 0
        for s in bank:
            n = s.count('1')
            if n == 0:
                continue
            ans += temp * n
            temp = n
        return ans

4.7.1182 - 2024-01-02 15:20:19 +0300 MSK

Convert an Array Into a 2D Array With Conditions
class Solution:
    def findMatrix(self, v: List[int]) -> List[List[int]]:
        um = {}
        for i in v:
            um[i] = um.get(i, 0) + 1
        
        ans = []
        while um:
            temp = []
            to_erase = []
            for f, s in um.items():
                temp.append(f)
                s -= 1
                if s == 0:
                    to_erase.append(f)
                um[f] = s
            ans.append(temp)
            for i in to_erase:
                del um[i]
        return ans

4.7.1183 - 2024-01-01 16:10:42 +0300 MSK

Assign Cookies
class Solution:
    def findContentChildren(self, g: List[int], s: List[int]) -> int:
        g.sort()
        s.sort()
        content_children = 0
        cookie_index = 0
        while cookie_index < len(s) and content_children < len(g):
            if s[cookie_index] >= g[content_children]:
                content_children += 1
            cookie_index += 1
        return content_children

4.7.1184 - 2023-12-31 13:19:35 +0300 MSK

Largest Substring Between Two Equal Characters
class Solution:
    def maxLengthBetweenEqualCharacters(self, s: str) -> int:
        ans = -1
        
        for left in range(len(s)):
            for right in range(left + 1, len(s)):
                if s[left] == s[right]:
                    ans = max(ans, right - left - 1)
        
        return ans

4.7.1185 - 2023-12-30 14:22:38 +0300 MSK

Redistribute Characters to Make All Strings Equal
class Solution:
    def makeEqual(self, words: List[str]) -> bool:
        counts = defaultdict(int)
        for word in words:
            for c in word:
                counts[c] += 1
        
        n = len(words)
        for val in counts.values():
            if val % n != 0:
                return False
        
        return True

4.7.1186 - 2023-12-29 10:09:26 +0300 MSK

Minimum Difficulty of a Job Schedule
class Solution:
    def minDifficulty(self, jobDifficulty, days):
        length = len(jobDifficulty)
        if days > length:
            return -1

        min_difficulties = [[float('inf')] * length for _ in range(days)]

        max_diff = 0
        i = 0
        while i <= length - days:
            max_diff = max(max_diff, jobDifficulty[i])
            min_difficulties[0][i] = max_diff
            i += 1

        current_day = 1
        while current_day < days:
            to = current_day
            while to <= length - days + current_day:
                current_job_difficulty = jobDifficulty[to]
                result = float('inf')
                j = to - 1
                while j >= current_day - 1:
                    result = min(result, min_difficulties[current_day - 1][j] + current_job_difficulty)
                    current_job_difficulty = max(current_job_difficulty, jobDifficulty[j])
                    j -= 1
                min_difficulties[current_day][to] = result
                to += 1
            current_day += 1

        return min_difficulties[days - 1][length - 1]

4.7.1187 - 2023-12-28 10:12:36 +0300 MSK

String Compression II
class Solution:
    def getLengthOfOptimalCompression(self, s: str, k: int) -> int:
        n = len(s)
        dp = [[9999] * 110 for _ in range(110)]
        dp[0][0] = 0

        for i in range(1, n + 1):
            for j in range(0, k + 1):
                cnt, del_ = 0, 0
                for l in range(i, 0, -1):
                    if s[l - 1] == s[i - 1]:
                        cnt += 1
                    else:
                        del_ += 1

                    if j - del_ >= 0:
                        dp[i][j] = min(dp[i][j], dp[l - 1][j - del_] + 1 + (3 if cnt >= 100 else 2 if cnt >= 10 else 1 if cnt >= 2 else 0))

                if j > 0:
                    dp[i][j] = min(dp[i][j], dp[i - 1][j - 1])

        return dp[n][k]

4.7.1188 - 2023-12-27 11:51:17 +0300 MSK

Minimum Time to Make Rope Colorful
class Solution:
    def minCost(self, colors: str, neededTime: List[int]) -> int:
        totalTime = 0
        i = 0
        j = 0

        while i < len(neededTime) and j < len(neededTime):
            currTotal = 0
            currMax = 0

            while j < len(neededTime) and colors[i] == colors[j]:
                currTotal += neededTime[j]
                currMax = max(currMax, neededTime[j])
                j += 1

            totalTime += currTotal - currMax
            i = j

        return totalTime

4.7.1189 - 2023-12-26 11:08:25 +0300 MSK

Number of Dice Rolls With Target Sum
class Solution:
    mod = 10 ** 9 + 7

    def numRollsToTarget(self, n: int, k: int, target: int) -> int:
        dp = [[-1] * (target + 1) for _ in range(n + 1)]
        return self.recursion(dp, n, k, target)

    def recursion(self, dp: list, n: int, k: int, target: int) -> int:
        if target == 0 and n == 0:
            return 1
        if n == 0 or target <= 0:
            return 0

        if dp[n][target] != -1:
            return dp[n][target] % self.mod

        ways = 0
        for i in range(1, k + 1):
            ways = (ways + self.recursion(dp, n - 1, k, target - i)) % self.mod

        dp[n][target] = ways % self.mod
        return dp[n][target]

4.7.1190 - 2023-12-25 10:53:55 +0300 MSK

Decode Ways
class Solution:
    def numDecodings(self, s):
        if s == "0":
            return 0
        
        # dp_0 = dp[i]
        # dp_1 = dp[i + 1]
        # dp_2 = dp[i + 2]
        dp_2 = 1
        dp_1 = int(s[-1] != "0")

        i = len(s) - 2
        while i >= 0:
            if s[i] == "0":
                dp_0 = 0
            else:
                dp_0 = dp_1
                if (s[i] == "1") or (s[i] == "2" and eval(s[i + 1]) < 7):
                    dp_0 += dp_2
            i -= 1
            dp_0, dp_1, dp_2 = 0, dp_0, dp_1
        
        return dp_1

4.7.1191 - 2023-12-24 12:54:15 +0300 MSK

Minimum Changes To Make Alternating Binary String
class Solution:
    def minOperations(self, s: str) -> int:
        start0 = 0
        start1 = 0
        
        for i in range(len(s)):
            if i % 2 == 0:
                if s[i] == "0":
                    start1 += 1
                else:
                    start0 += 1
            else:
                if s[i] == "1":
                    start1 += 1
                else:
                    start0 += 1
        
        return min(start0, start1)

4.7.1192 - 2023-12-24 00:41:36 +0300 MSK

Path Crossing
class Solution:
    def isPathCrossing(self, path: str) -> bool:
        moves = {
            "N": (0, 1),
            "S": (0, -1),
            "W": (-1, 0),
            "E": (1, 0)
        }
        
        visited = {(0, 0)}
        x = 0
        y = 0

        for c in path:
            dx, dy = moves[c]
            x += dx
            y += dy
            
            if (x, y) in visited:
                return True

            visited.add((x, y))
        
        return False

4.7.1193 - 2023-12-22 11:52:14 +0300 MSK

Maximum Score After Splitting a String
class Solution:
    def maxScore(self, s: str) -> int:
        ones = s.count("1")
        zeros = 0
        ans = 0 

        for i in range(len(s) - 1):
            if s[i] == "1":
                ones -= 1
            else:
                zeros += 1
        
            ans = max(ans, zeros + ones)
        
        return ans

4.7.1194 - 2023-12-21 08:42:34 +0300 MSK

Widest Vertical Area Between Two Points Containing No Points
class Solution:
    def maxWidthOfVerticalArea(self, points: List[List[int]]) -> int:
        points.sort(key=lambda x: x[0])

        max_width = 0

        for i in range(1, len(points)):
            width = points[i][0] - points[i-1][0]
            max_width = max(max_width, width)

        return max_width

4.7.1195 - 2023-12-20 14:05:16 +0300 MSK

Buy Two Chocolates
class Solution:
    def buyChoco(self, prices: List[int], money: int) -> int:
        # Assume the Minimum Cost to be Infinity
        min_cost = float('inf')

        # Number of Chocolates
        n = len(prices)

        # Check Every Pair of Chocolates
        for first_choco in range(n):
            for second_choco in range(first_choco + 1, n):
                # Sum of Prices of the Two Chocolates
                cost = prices[first_choco] + prices[second_choco]

                # If the Sum of Prices is Less than the Minimum Cost
                if cost < min_cost:
                    # Update the Minimum Cost
                    min_cost = cost
        
        # We can buy chocolates only if we have enough money
        if min_cost <= money:
            # Return the Amount of Money Left
            return money - min_cost
        else:
            # We cannot buy chocolates. Return the initial amount of money
            return money

4.7.1196 - 2023-12-19 11:24:47 +0300 MSK

Image Smoother
class Solution:
    def imageSmoother(self, img: List[List[int]]) -> List[List[int]]:
        # Save the dimensions of the image.
        m = len(img)
        n = len(img[0])

        # Create a new image of the same dimension as the input image.
        smooth_img = [[0] * n for _ in range(m)]

        # Iterate over the cells of the image.
        for i in range(m):
            for j in range(n):
                # Initialize the sum and count 
                sum = 0
                count = 0

                # Iterate over all plausible nine indices.
                for x in (i - 1, i, i + 1):
                    for y in (j - 1, j, j + 1):
                        # If the indices form valid neighbor
                        if 0 <= x < m and 0 <= y < n:
                            sum += img[x][y]
                            count += 1

                # Store the rounded down value in smooth_img[i][j].
                smooth_img[i][j] = sum // count
        
        # Return the smooth image.
        return smooth_img

4.7.1197 - 2023-12-18 13:27:09 +0300 MSK

Maximum Product Difference Between Two Pairs
class Solution:
    def maxProductDifference(self, nums: List[int]) -> int:
        nums.sort()
        return nums[-1] * nums[-2] - nums[0] * nums[1]

4.7.1198 - 2023-12-17 12:09:37 +0300 MSK

Design a Food Rating System
class Food:
    def __init__(self, food_rating, food_name):
        # Store the food's rating.
        self.food_rating = food_rating
        # Store the food's name.
        self.food_name = food_name

    def __lt__(self, other):
        # Overload the less than operator for comparison.
        # If food ratings are the same, sort based on their name (lexicographically smaller name food will be on top).
        if self.food_rating == other.food_rating:
            return self.food_name < other.food_name
        # Sort based on food rating (bigger rating food will be on top).
        return self.food_rating > other.food_rating

class FoodRatings:
    def __init__(self, foods: List[str], cuisines: List[str], ratings: List[int]):
        # Map food with its rating.
        self.food_rating_map = {}
        # Map food with the cuisine it belongs to.
        self.food_cuisine_map = {}
        # Store all food of a cuisine in a priority queue (to sort them on ratings/name).
        # Priority queue element -> Food: (food_rating, food_name)
        self.cuisine_food_map = defaultdict(list)

        for i in range(len(foods)):
            # Store 'rating' and 'cuisine' of the current 'food' in 'food_rating_map' and 'food_cuisine_map' maps.
            self.food_rating_map[foods[i]] = ratings[i]
            self.food_cuisine_map[foods[i]] = cuisines[i]
            # Insert the '(rating, name)' element into the current cuisine's priority queue.
            heapq.heappush(self.cuisine_food_map[cuisines[i]], Food(ratings[i], foods[i]))

    def changeRating(self, food: str, newRating: int) -> None:
        # Update food's rating in 'food_rating' map.
        self.food_rating_map[food] = newRating
        # Insert the '(new rating, name)' element in the respective cuisine's priority queue.
        cuisineName = self.food_cuisine_map[food]
        heapq.heappush(self.cuisine_food_map[cuisineName], Food(newRating, food))

    def highestRated(self, cuisine: str) -> str:
        # Get the highest rated 'food' of 'cuisine'.
        highest_rated = self.cuisine_food_map[cuisine][0]

        # If the latest rating of 'food' doesn't match with the 'rating' on which it was sorted in the priority queue,
        # then we discard this element from the priority queue.
        while self.food_rating_map[highest_rated.food_name] != highest_rated.food_rating:
            heapq.heappop(self.cuisine_food_map[cuisine])
            highest_rated = self.cuisine_food_map[cuisine][0]

        # Return the name of the highest-rated 'food' of 'cuisine'.
        return highest_rated.food_name

4.7.1199 - 2023-12-16 13:01:55 +0300 MSK

Valid Anagram
class Solution:
    def isAnagram(self, s: str, t: str) -> bool:
        if (len(s) != len(t)):
            return False
            
        letters = [0] * 26
        for char in s:
            letters[ord(char) - ord('a')] += 1
        
        for char in t:
            i = ord(char) - ord('a')
            letters[i] -= 1
            if letters[i] < 0:
                return False

        return True

4.7.1200 - 2023-12-15 10:56:18 +0300 MSK

Destination City
class Solution:
    def destCity(self, paths: List[List[str]]) -> str:
        paths_from = set()
        for path_from, path_to in paths:
            paths_from.add(path_from)
        
        ans = ""
        for _, path_to in paths:
            if path_to not in paths_from:
                ans = path_to
                break
        
        return ans

4.7.1201 - 2023-12-15 10:54:52 +0300 MSK

Destination City
class Solution:
    def destCity(self, paths: List[List[str]]) -> str:
        paths_from, paths_to = set(), set()
        for path_from, path_to in paths:
            paths_from.add(path_from)
            paths_to.add(path_to)
        
        return (paths_to - paths_from).pop()

4.7.1202 - 2023-12-14 12:30:55 +0300 MSK

Difference Between Ones and Zeros in Row and Column
class Solution:
    def onesMinusZeros(self, grid: List[List[int]]) -> List[List[int]]:
        m = len(grid)
        n = len(grid[0])

        rows = {}
        for r in range(m):        
            row_sum = 0
            for c in range(n):
                row_sum += grid[r][c]
            
            rows[r] = row_sum

        cols = {}
        for c in range(n):
            col_sum = 0
            for r in range(m):
                col_sum += grid[r][c]
            
            cols[c] = col_sum

        res = [[0] * n for _ in range(m)]

        for r in range(m):
            for c in range(n):
                res[r][c] = rows[r] + cols[c] - (m - rows[r]) - (n - cols[c])
        
        return res

4.7.1203 - 2023-12-13 11:11:00 +0300 MSK

Special Positions in a Binary Matrix
class Solution:
    def numSpecial(self, mat: List[List[int]]) -> int:
        def get_column_sum(col_idx):
            return sum(row[col_idx] for row in mat)

        special = 0
        for row in mat:
            if sum(row) == 1:
                col_idx = row.index(1)
                special += get_column_sum(col_idx) == 1

        return special

4.7.1204 - 2023-12-12 10:39:45 +0300 MSK

Maximum Product of Two Elements in an Array
class Solution:
    def maxProduct(self, nums: List[int]) -> int:
        biggest = 0
        second_biggest = 0
        for num in nums:
            if num > biggest:
                second_biggest = biggest
                biggest = num
            else:
                second_biggest = max(second_biggest, num)
        
        return (biggest - 1) * (second_biggest - 1)

4.7.1205 - 2023-12-11 15:30:35 +0300 MSK

Keyboard Row
class Solution:
    def findWords(self, words: List[str]) -> List[str]:
        ans = []
        rows = [
            set("qwertyuiop"),
            set("asdfghjkl"), 
            set("zxcvbnm")
        ]
        for word in words:
            for row in rows:
                if len(row.union(word.lower())) == len(row):
                    ans.append(word)
                    break
        return ans

4.7.1206 - 2023-12-11 10:26:55 +0300 MSK

Element Appearing More Than 25% In Sorted Array
class Solution:
    def findSpecialInteger(self, arr: List[int]) -> int:
        prev, count = arr[0], 1
        quarter = len(arr) / 4
        for num in arr[1:]:
            if num == prev:
                count += 1
            else:
                prev = num
                count = 1
            if count > quarter:
                break
        return prev

4.7.1207 - 2023-12-10 13:46:54 +0300 MSK

Binary Tree Inorder Traversal
/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    vector<int> inorderTraversal(TreeNode* root) {
        vector<int> result;
        helper(root, result);
        return result;
    }

    void helper(TreeNode* root, vector<int>& result) {
        if (root != nullptr) {
            helper(root->left, result);
            result.push_back(root->val);
            helper(root->right, result);
        }
    }
};

4.7.1208 - 2023-12-10 13:46:22 +0300 MSK

Binary Tree Inorder Traversal
/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    vector<int> inorderTraversal(TreeNode* root) {
        vector<int> result;
        helper(root, result);
        return result;
    }

    void helper(TreeNode* root, vector<int>& result) {
        if (root != nullptr) {
            helper(root->left, result);
            result.push_back(root->val);
            helper(root->right, result);
        }
    }
};

4.7.1209 - 2023-12-10 13:45:46 +0300 MSK

Transpose Matrix
class Solution {
public:
    vector<vector<int>> transpose(vector<vector<int>>& matrix) {
        int row = matrix.size();
        int col = matrix[0].size();
        vector<vector<int>> result(col, vector<int>(row, 0));
        
        for (int i = 0; i < col; ++i) {
            for (int j = 0; j < row; ++j) {
                result[i][j] = matrix[j][i];
            }
        }
        
        return result;
    }
};

4.7.1210 - 2023-12-08 21:03:57 +0300 MSK

Construct String from Binary Tree
class Solution {
public:
    string tree2str(TreeNode* root) {
        string str = "";
         check(root, str);
         return str;
    }
    void check(TreeNode* root, string &str) {
        if (root == NULL) {
            return;
        }
        str += to_string(root->val);
        if (root->left || root->right) {
            str += '(';
            check(root->left, str);
            str += ')';
        }
        if (root->right) {
            str += '(';
            check(root->right, str);
            str += ')';
        }
        
    }
    
};

4.7.1211 - 2023-12-07 19:20:48 +0300 MSK

Largest Odd Number in String
class Solution {
public:
    string largestOddNumber(string num) {
        size_t length {num.size()};
        for (int i = length - 1; i >= 0; --i) {
            if ((num[i] - '0') % 2 != 0) {
                return num.substr(0, i + 1);
            }
        }
        return "";
    }
};

4.7.1212 - 2023-12-06 12:45:40 +0300 MSK

Palindrome Linked List
class Solution {
public:
    bool isPalindrome(ListNode* head) {
        ListNode* slow {head};
        ListNode* fast {head};
        ListNode* next;
        ListNode* prev {new ListNode()};

        while(fast && fast->next) {
            slow = slow->next;
            fast = fast->next->next; 

            next = head->next;
            head->next = prev;
            prev = head;
            head = next;
        }
    
        if (fast) {
            slow = slow->next;
        }
        head = prev;

        while (slow) {
            if (head->val != slow->val) {
                return false;
            }
            head = head->next;
            slow = slow->next;
        }
        return true;
    }
};

4.7.1213 - 2023-12-06 09:43:04 +0300 MSK

Calculate Money in Leetcode Bank
class Solution {
public:
    int totalMoney(int n) {
        int ans {0};
        int monday {1};
        
        while (n > 0) {
            for (int day {0}; day < min(n, 7); ++day) {
                ans += monday + day;
            }
            n -= 7;
            ++monday;
        }
        
        return ans;
    }
};

4.7.1214 - 2023-12-05 16:12:24 +0300 MSK

Count of Matches in Tournament
class Solution {
public:
    int numberOfMatches(int n) {
        int ans = 0;
        while (n > 1) {
            if (n % 2 == 0) {
                int matches {n / 2};
                ans += matches;
                n = matches;
            } else {
                int matches {(n - 1) / 2};
                ans += matches;
                n = matches + 1;
            }
        }
        
        return ans;
    }
};

4.7.1215 - 2023-12-04 11:09:00 +0300 MSK

Largest 3-Same-Digit Number in String
class Solution {
public:
    string largestGoodInteger(string num) {
        int cur {-1};
        int max {-1};
        int count {0};
        for (const char& ch : num) {
            int i {ch - '0'};
            if (i == cur) {
                ++count;
            } else {
                cur = i;
                count = 1; 
            }
            if (count == 3) {
                max = std::max(i, max);
            }
        }
        if (max == -1) {
            return "";
        }
        std::string ans {std::to_string(max)};
        return ans + ans + ans;
    }
};

4.7.1216 - 2023-12-03 17:53:13 +0300 MSK

Minimum Time Visiting All Points
class Solution {
public:
    int minTimeToVisitAllPoints(vector<vector<int>>& points) {
        int ans = 0;
        for (int i = 0; i < points.size() - 1; i++) {
            int currX = points[i][0];
            int currY = points[i][1];
            int targetX = points[i + 1][0];
            int targetY = points[i + 1][1];
            ans += max(abs(targetX - currX), abs(targetY - currY));
        }
        
        return ans;
    }
};

4.7.1217 - 2023-12-02 23:40:09 +0300 MSK

Find Words That Can Be Formed by Characters
class Solution {
public:
    int countCharacters(vector<string>& words, string chars) {
        std::vector<int> count {};
        int ans {};
        count.resize(26);
        for (const char& ch : chars) {
            ++count[ch - 'a'];
        }
        for (const string& word : words) {
            std::vector<int> wordCount {};
            wordCount.resize(26);
            bool failure {false};
            for (const char& ch : word) {
                int i {ch - 'a'};
                int cur {++wordCount[i]};
                if (cur > count[i]) {
                    failure = true;
                    break;
                }
            }
            if (!failure) {
                ans += word.length();
            }
        }
        return ans;
    }
};

4.7.1218 - 2023-12-01 11:21:29 +0300 MSK

Check If Two String Arrays are Equivalent
class Solution {
public:
    bool arrayStringsAreEqual(vector<string>& word1, vector<string>& word2) {
        string s1 = "";
        string s2 = "";

        for(const string& s : word1) {
            s1 += s;
        }
        for(const string& s : word2) {
            s2 += s;
        }
        return s1==s2;
    }
};

4.7.1219 - 2023-11-30 10:50:12 +0300 MSK

Minimum One Bit Operations to Make Integers Zero
class Solution {
public:
    int minimumOneBitOperations(int n) {
        if (n == 0) {
            return 0;
        }
        
        int k = 0;
        int curr = 1;
        while (curr * 2 <= n) {
            curr *= 2;
            k++;
        }
        
        return (1 << (k + 1)) - 1 - minimumOneBitOperations(n ^ curr);
    }
};

4.7.1220 - 2023-11-29 12:01:45 +0300 MSK

Number of 1 Bits
class Solution {
public:
    int hammingWeight(uint32_t n) {
        int ans {};
        while (n) {
            if (n & 1) {
                ++ans;
            }
            n >>= 1;
        }
        return ans;
    }
};

4.7.1221 - 2023-11-28 13:04:41 +0300 MSK

Number of Ways to Divide a Long Corridor
class Solution {
public:
    // Store 1000000007 in a variable for convenience
    const int MOD = 1e9 + 7;
    
    // Count the number of ways to divide from "index" to the last index
    // with "seats" number of "S" in the current section
    int count(int index, int seats, string& corridor, int cache[][3]) {
        // If we have reached the end of the corridor, then
        // the current section is valid only if "seats" is 2
        if (index == corridor.length()) {
            return seats == 2 ? 1 : 0;
        }

        // If we have already computed the result of this sub-problem,
        // then return the cached result
        if (cache[index][seats] != -1) {
            return cache[index][seats];
        }

        // Result of the sub-problem
        int result = 0;

        // If the current section has exactly 2 "S"
        if (seats == 2) {
            // If the current element is "S", then we have to close the
            // section and start a new section from this index. Next index
            // will have one "S" in the current section
            if (corridor[index] == 'S') {
                result = count(index + 1, 1, corridor, cache);
            } else {
                // If the current element is "P", then we have two options
                // 1. Close the section and start a new section from this index
                // 2. Keep growing the section
                result = (count(index + 1, 0, corridor, cache) + count(index + 1, 2, corridor, cache)) % MOD;  
            }
        } else {
            // Keep growing the section. Increment "seats" if present
            // element is "S"
            if (corridor[index] == 'S') {
                result = count(index + 1, seats + 1, corridor, cache);
            } else {
                result = count(index + 1, seats, corridor, cache);
            }
        }

        // Memoize the result, and return it
        cache[index][seats] = result;
        return cache[index][seats];
    }

    int numberOfWays(string corridor) {
        // Cache the result of each sub-problem
        int cache[corridor.length()][3];
        memset(cache, -1, sizeof(cache));

        // Call the count function
        return count(0, 0, corridor, cache);
    }
};

4.7.1222 - 2023-11-27 10:32:44 +0300 MSK

Largest Submatrix With Rearrangements
class Solution {
public:
    int largestSubmatrix(vector<vector<int>>& matrix) {
        int m = matrix.size();
        int n = matrix[0].size();
        int ans = 0;
        
        for (int row = 0; row < m; row++) {
            for (int col = 0; col < n; col++) {
                if (matrix[row][col] != 0 && row > 0) {
                    matrix[row][col] += matrix[row - 1][col];
                }
            }
            
            vector<int> currRow = matrix[row];
            sort(currRow.begin(), currRow.end(), greater());
            for (int i = 0; i < n; i++) {
                ans = max(ans, currRow[i] * (i + 1));
            }
        }
        
        return ans;
    }
};

4.7.1223 - 2023-11-27 10:32:13 +0300 MSK

Knight Dialer
class Solution {
public:
    vector<vector<int>> memo;
    int n;
    int MOD = 1e9 + 7;
    vector<vector<int>> jumps = {
        {4, 6},
        {6, 8},
        {7, 9},
        {4, 8},
        {3, 9, 0},
        {},
        {1, 7, 0},
        {2, 6},
        {1, 3},
        {2, 4}
    };
    
    int dp(int remain, int square) {
        if (remain == 0) {
            return 1;
        }
        
        if (memo[remain][square] != 0) {
            return memo[remain][square];
        }
        
        int ans = 0;
        for (int nextSquare : jumps[square]) {
            ans = (ans + dp(remain - 1, nextSquare)) % MOD;
        }
        
        memo[remain][square] = ans;
        return ans;
    }
    
    int knightDialer(int n) {
        this->n = n;
        memo = vector(n + 1, vector(10, 0));
        int ans = 0;
        for (int square = 0; square < 10; square++) {
            ans = (ans + dp(n - 1, square)) % MOD;
        }
        
        return ans;
    }
};

4.7.1224 - 2023-11-25 22:00:45 +0300 MSK

Sum of Absolute Differences in a Sorted Array
class Solution {
public:
    vector<int> getSumAbsoluteDifferences(vector<int>& nums) {
        int n = nums.size();
        int totalSum = accumulate(nums.begin(), nums.end(), 0);
        
        int leftSum = 0;
        vector<int> ans;
        for (int i = 0; i < n; i++) {
            int rightSum = totalSum - leftSum - nums[i];
            
            int leftCount = i;
            int rightCount = n - 1 - i;
            
            int leftTotal = leftCount * nums[i] - leftSum;
            int rightTotal = rightSum - rightCount * nums[i];
            
            ans.push_back(leftTotal + rightTotal);
            leftSum += nums[i];
        }
        
        return ans;
    }
};

4.7.1225 - 2023-11-25 22:00:22 +0300 MSK

Sum of Absolute Differences in a Sorted Array
class Solution {
public:
    vector<int> getSumAbsoluteDifferences(vector<int>& nums) {
        int n = nums.size();
        vector<int> prefix = {nums[0]};
        for (int i = 1; i < n; i++) {
            prefix.push_back(prefix[i - 1] + nums[i]);
        }
        vector<int> ans;
        for (int i = 0; i < n; i++) {
            int leftSum = prefix[i] - nums[i];
            int rightSum = prefix[n - 1] - prefix[i];
            
            int leftCount = i;
            int rightCount = n - 1 - i;
            
            int leftTotal = leftCount * nums[i] - leftSum;
            int rightTotal = rightSum - rightCount * nums[i];
            
            ans.push_back(leftTotal + rightTotal);
        }
        return ans;
    }
};

4.7.1226 - 2023-11-24 16:49:32 +0300 MSK

Kids With the Greatest Number of Candies
class Solution {
public:
    std::vector<bool> kidsWithCandies(std::vector<int>& candies, int extraCandies) {
        size_t length {candies.size()};        
        std::vector<bool> ans {};
        ans.resize(length);
        const int maxCandy {*std::max_element(candies.begin(), candies.end())};
        for (size_t i = 0; i < length; ++i) {
            ans[i] = (candies[i] + extraCandies) >= maxCandy;
        }
        return ans;
    }
};

4.7.1227 - 2023-11-24 16:37:41 +0300 MSK

Greatest Common Divisor of Strings
class Solution {
public:
    string gcdOfStrings(string str1, string str2) {
        if (str1 + str2 == str2 + str1) {
            return str1.substr(0, std::gcd(str1.size(), str2.size()));
        }
        return "";
    }
};

4.7.1228 - 2023-11-24 16:36:38 +0300 MSK

Greatest Common Divisor of Strings
class Solution {
public:
    string gcdOfStrings(string str1, string str2) {
        if (str1 + str2 != str2 + str1) {
            return "";
        }
        unsigned long gcdLength {std::gcd(str1.size(), str2.size())};
        return str1.substr(0, gcdLength);
    }
};

4.7.1229 - 2023-11-24 16:32:52 +0300 MSK

Greatest Common Divisor of Strings
class Solution {
public:
    bool valid(string str1, string str2, size_t k) {
        size_t len1 {str1.size()}, len2 {str2.size()};
        if (len1 % k != 0 || len2 % k != 0) {
            return false;
        }
        string base = str1.substr(0, k);
        size_t n1 {len1 / k}, n2 {len2 / k};
        if (n1 == n2) {
            return str1 == str2 && joinWords(base, n1) == str1;
        }
        return str1 == joinWords(base, n1) && str2 == joinWords(base, n2);
    }

    string joinWords(string str, size_t k) {
        string ans = "";
        for (size_t i = 0; i < k; ++i) {
            ans += str;
        }
        return ans;
    }
    
    
    string gcdOfStrings(string str1, string str2) {
        for (size_t i = min(str1.size(), str2.size()); i > 0; --i) {
            if (valid(str1, str2, i)) {
                return str1.substr(0, i);
            }
        }
        return "";
    }
};

4.7.1230 - 2023-11-24 11:07:37 +0300 MSK

Maximum Number of Coins You Can Get
class Solution {
public:
    int maxCoins(vector<int>& piles) {
        std::sort(piles.begin(), piles.end());
        size_t length {piles.size()};
        size_t picks {length / 3};
        int count {};
        for (size_t i {length - 2}; picks > 0; i -= 2, --picks) {
            count += piles[i];
        }
        return count;
    }
};

4.7.1231 - 2023-11-23 13:41:25 +0300 MSK

Arithmetic Subarrays
class Solution {
public:
    bool check(vector<int>& arr) {
        sort(arr.begin(), arr.end());
        int diff = arr[1] - arr[0];
        
        for (int i = 2; i < arr.size(); i++) {
            if (arr[i] - arr[i - 1] != diff) {
                return false;
            }
        }
        
        return true;
    }
    
    vector<bool> checkArithmeticSubarrays(vector<int>& nums, vector<int>& l, vector<int>& r) {
        vector<bool> ans;
        for (int i = 0; i < l.size(); i++) {
            vector<int> arr(begin(nums) + l[i], begin(nums) + r[i] + 1);
            ans.push_back(check(arr));
        }
        
        return ans;
    }
};

4.7.1232 - 2023-11-22 18:49:02 +0300 MSK

Diagonal Traverse II
class Solution {
public:
    vector<int> findDiagonalOrder(vector<vector<int>>& nums) {
        unordered_map<int, vector<int>> groups;
        for (int row = nums.size() - 1; row >= 0; row--) {
            for (int col = 0; col < nums[row].size(); col++) {
                int diagonal = row + col;
                groups[diagonal].push_back(nums[row][col]);
            }
        }
        
        vector<int> ans;
        int curr = 0;
        
        while (groups.find(curr) != groups.end()) {
            for (int num : groups[curr]) {
                ans.push_back(num);
            }
            
            curr++;
        }
        
        return ans;
    }
};

4.7.1233 - 2023-11-21 12:51:21 +0300 MSK

Binary Tree Paths
/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    vector<string> binaryTreePaths(TreeNode* root) {
        vector<string> ans;
        dfs(*root, ans, "");
        return ans;
    }

    void dfs(TreeNode& root, vector<string> &ans, string path){
        path += (path.size() ? "->" : "") + std::to_string(root.val);
        if(!root.left && !root.right) {
            ans.push_back(path);
            return;
        }
        if(root.left) {
            dfs(*root.left, ans, path);
        }
        if(root.right) {
            dfs(*root.right, ans, path);
        }
    }
};

4.7.1234 - 2023-11-21 12:44:04 +0300 MSK

Count Nice Pairs in an Array
class Solution {
public:
    int countNicePairs(vector<int>& nums) {
        std::unordered_map<int, int> diffs{};
        int ans{};
        double mod{1e9 + 7};
        for (const int& num : nums) {
            int revNum{};
            int tempNum{num};
            while(tempNum) {
                revNum = (revNum * 10) + (tempNum % 10);
                tempNum /= 10;
            }
            int diff{num-revNum};
            if (diffs.contains(diff)) {
                ans = std::fmod(ans + diffs[diff], mod);
            }
            ++diffs[diff];
        }
        return ans;
    }

};

4.7.1235 - 2023-11-21 12:33:13 +0300 MSK

Count Nice Pairs in an Array
class Solution {
public:
    int countNicePairs(vector<int>& nums) {
        std::unordered_map<int, int> diffs{};
        for (const int& num : nums) {
            int revNum{};
            int tempNum{num};
            while(tempNum) {
                revNum = (revNum * 10) + (tempNum % 10);
                tempNum /= 10;
            }
            ++diffs[num - revNum];
        }
        int ans{};
        double mod{std::pow(10, 9) + 7};
        for (const auto& [num, count] : diffs) {
            long pairs{(1L * count * count - count) / 2};
            ans = std::fmod(ans + pairs, mod);
        }
        return ans;
    }

};

4.7.1236 - 2023-11-20 18:30:57 +0300 MSK

Excel Sheet Column Number
class Solution {
public:
    int titleToNumber(string columnTitle) {
        int ans{0};
        for (const char& ch : columnTitle) {
            ans = (ans * 26) + (ch - 'A') + 1;
        }
        return ans;
    }
};

4.7.1237 - 2023-11-20 14:40:36 +0300 MSK

Binary Tree Postorder Traversal
/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    vector<int> postorderTraversal(TreeNode* root) {
        if (root == nullptr) {
            return {};
        }
        std::vector<int> ans{};
        addNodes(*root, ans);
        return ans;
    }

    void addNodes(TreeNode& node, std::vector<int>& ans) {
        if (node.left != nullptr) {
            addNodes(*node.left, ans);
        }
        if (node.right != nullptr) {
            addNodes(*node.right, ans);
        }
        ans.push_back(node.val);
    }
};

4.7.1238 - 2023-11-20 14:38:40 +0300 MSK

Binary Tree Postorder Traversal
/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    vector<int> postorderTraversal(TreeNode* root) {
        if (root == nullptr) {
            return {};
        }
        std::vector<int> ans{};
        addNodes(root, ans);
        return ans;
    }

    void addNodes(TreeNode* node, std::vector<int>& ans) {
        auto left{node->left}, right{node->right};
        if (left != nullptr) {
            addNodes(left, ans);
        }
        if (right != nullptr) {
            addNodes(right, ans);
        }
        ans.push_back(node->val);
    }
};

4.7.1239 - 2023-11-20 14:31:25 +0300 MSK

Binary Tree Preorder Traversal
/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    vector<int> preorderTraversal(TreeNode* root) {
        if (root == nullptr) {
            return {};
        }
        std::vector<int> ans{};
        std::vector<TreeNode*> q{root};
        while (q.size() != 0) {
            auto node = q.back();
            auto left{node->left}, right{node->right};
            q.pop_back();
            ans.push_back(node->val);
            if (right != nullptr) {
                q.push_back(right);
            }
            if (left != nullptr) {
                q.push_back(left);
            }
        }
        return ans;
    }
};

4.7.1240 - 2023-11-20 14:29:40 +0300 MSK

Binary Tree Preorder Traversal
/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    vector<int> preorderTraversal(TreeNode* root) {
        if (root == nullptr) {
            return {};
        }
        std::vector<int> ans{};
        std::deque<TreeNode*> q{root};
        while (q.size() != 0) {
            auto node = q.front();
            auto left{node->left}, right{node->right};
            q.pop_front();
            ans.push_back(node->val);
            if (right != nullptr) {
                q.push_front(right);
            }
            if (left != nullptr) {
                q.push_front(left);
            }
        }
        return ans;
    }
};

4.7.1241 - 2023-11-20 14:27:13 +0300 MSK

Binary Tree Preorder Traversal
/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    vector<int> preorderTraversal(TreeNode* root) {
        std::vector<int> ans{};
        std::deque<TreeNode*> q{root};
        while (q.size() != 0) {
            auto node = q.front();
            q.pop_front();
            if (node == nullptr) {
                continue;
            }
            ans.push_back(node->val);
            q.push_front(node->right);
            q.push_front(node->left);
        }
        return ans;
    }
};

4.7.1242 - 2023-11-20 14:11:47 +0300 MSK

Minimum Amount of Time to Collect Garbage
class Solution {
public:
    int garbageCollection(vector<string>& garbage, vector<int>& travel) {
        vector<int> prefixSum(travel.size() + 1, 0);
        prefixSum[1] = travel[0];
        for (int i = 1; i < travel.size(); i++) {
            prefixSum[i + 1] = prefixSum[i] + travel[i];
        }
        unordered_map<char, int> garbageLastPos;
        unordered_map<char, int> garbageCount;
        for (int i = 0; i < garbage.size(); i++) {
            for (char c : garbage[i]) {
                garbageLastPos[c] = i;
                garbageCount[c]++;
            }
        }
        char garbageTypes[3] = {'M', 'P', 'G'};
        int ans = 0;
        for (char c : garbageTypes) {
            if (garbageCount[c]) {
                ans += prefixSum[garbageLastPos[c]] + garbageCount[c];
            }
        }
        return ans;
    }
};

4.7.1243 - 2023-11-19 11:31:05 +0300 MSK

Reduction Operations to Make the Array Elements Equal
class Solution {
public:
    int reductionOperations(vector<int>& nums) {
        sort(nums.begin(), nums.end());
        int ans = 0;
        int up = 0;
        auto length {nums.size()};
        for (int i = 1; i < length; ++i) {
            if (nums[i] != nums[i - 1]) {
                ++up;
            }
            ans += up;
        }
        return ans;
    }
};

4.7.1244 - 2023-11-18 19:23:48 +0300 MSK

Frequency of the Most Frequent Element
class Solution {
public:
    int maxFrequency(vector<int>& nums, int k) {
        sort(nums.begin(), nums.end());
        int left = 0;
        int ans = 0;
        long curr = 0;
        
        for (int right = 0; right < nums.size(); right++) {
            long target = nums[right];
            curr += target;
            
            while ((right - left + 1) * target - curr > k) {
                curr -= nums[left];
                left++;
            }
            
            ans = max(ans, right - left + 1);
        }
        
        return ans;
    }
};

4.7.1245 - 2023-11-17 17:25:22 +0300 MSK

Odd Even Linked List
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
    ListNode* oddEvenList(ListNode* head) {
        if(!head || !head->next || !head->next->next) {
            return head;
        } 
        
        ListNode* odd {head};
        ListNode* even {head->next};
        ListNode* even_start {head->next};
        
        while(odd->next && even->next) {
            ListNode* next {even->next}; 
            odd->next = next;
            even->next = next->next;
            odd = odd->next;
            even = even->next;
        }
        odd->next = even_start;
        return head; 
    }
};

4.7.1246 - 2023-11-17 16:41:37 +0300 MSK

Dota2 Senate
class Solution {
public:
    string predictPartyVictory(string senate) {
        std::queue<int> rad, dir;
        unsigned long length {senate.size()};
        for (int i = 0; i < length; ++i){
            if (senate[i] == 'R'){
                rad.push(i);
            } else {
                dir.push(i);
            }
        }
        while (!rad.empty() && !dir.empty()) {
            if (rad.front() < dir.front()) {
                rad.push(length);
            } else {
                dir.push(length);
            }
            ++length;
            rad.pop();
            dir.pop();
        }
        return rad.empty() ? "Dire" : "Radiant";
    }
};

4.7.1247 - 2023-11-17 14:05:35 +0300 MSK

Decode String
class Solution {
public:
    string decodeString(string s) {
        return std::get<1>(decode(0, s));
    }
    
    std::tuple<int, string> decode(int pos, string s) {
        int num {0};
        string word {""};
        unsigned long length {s.size()};
        for(; pos < length; ++pos) {
            char c = s[pos];
            if(c == '[') {
                auto [newPos, repeat] {decode(++pos, s)};
                for(; num > 0; --num) {
                    word += repeat;
                }
                pos = newPos;
            } else if (c >= '0' && c <='9') {
                num = num * 10 + (c - '0');
            } else if (c == ']') {
                return {pos, word};
            } else {
                word += c;
            }
        }
        return {pos, word};
    }
};

4.7.1248 - 2023-11-17 14:02:06 +0300 MSK

Decode String
class Solution {
public:
    string decodeString(string s) {
        int pos = 0;
        return decode(pos, s);
    }
    
    string decode(int& pos, string s) {
        int num {0};
        string word {""};
        unsigned long length {s.size()};
        for(; pos < length; ++pos) {
            char c = s[pos];
            if(c == '[') {
                string repeat {decode(++pos, s)};
                for(; num > 0; --num) {
                    word += repeat;
                }
            } else if (c >= '0' && c <='9') {
                num = num * 10 + (c - '0');
            } else if (c == ']') {
                return word;
            } else {
                word += c;
            }
        }
        return word;
    }
};

4.7.1249 - 2023-11-17 13:13:32 +0300 MSK

Removing Stars From a String
class Solution {
public:
    string removeStars(string s) {
        std::string ans;
        int remove {0};
        for (int i = s.size() - 1; i >= 0; --i) {
            char c = s[i];
            if (c == '*') {
                ++remove;
            } else if (remove == 0) {
                ans += c;
            } else {
                --remove;
            }
        }
        std::reverse(ans.begin(), ans.end());
        return ans;
    }
};

4.7.1250 - 2023-11-17 13:12:34 +0300 MSK

Removing Stars From a String
class Solution {
public:
    string removeStars(string s) {
        std::string ans;
        unsigned long length {s.size()};
        int remove {0};
        for (int i = length - 1; i >= 0; --i) {
            char c = s[i];
            if (c == '*') {
                ++remove;
                continue;
            }
            if (remove == 0) {
                ans += c;
            } else {
                --remove;
            }
        }
        std::reverse(ans.begin(), ans.end());
        return ans;
    }
};

4.7.1251 - 2023-11-17 13:02:26 +0300 MSK

Minimize Maximum Pair Sum in Array
class Solution {
public:
    int minPairSum(vector<int>& nums) {
        std::sort(nums.begin(), nums.end());
        unsigned long length {nums.size()};
        int maxSum {0};
        for (int i = 0; i < length / 2; ++i) {
            maxSum = max(maxSum, nums[i] + nums[length - i - 1]);
        }
        return maxSum;
    }
};

4.7.1252 - 2023-11-16 16:43:00 +0300 MSK

Unique Number of Occurrences
class Solution {
public:
    bool uniqueOccurrences(vector<int>& arr) {
        std::unordered_map<int, int> counts;
        std::unordered_set<int> encountered;
        for (int num : arr) {
            counts[num] += 1;
        }
        for (const auto [num, count] : counts) {
            if (encountered.find(count) == encountered.end()) {
                encountered.insert(count);
            } else {
                return false;
            }
        }
        return true;
    }
};

4.7.1253 - 2023-11-16 16:22:50 +0300 MSK

N-th Tribonacci Number
class Solution {
public:
    int tribonacci(int n) {
        if (n == 0) {
            return 0;
        }
        if (n == 1 || n == 2) {
            return 1;
        }
        int num1 {0}, num2 {1}, num3 {1};
        for (int i = 3; i <= n; ++i) {
            int newNum3 = num1 + num2 + num3; 
            num1 = num2;
            num2 = num3;
            num3 = newNum3;
        }
        return num3;
    }
};

4.7.1254 - 2023-11-16 14:30:47 +0300 MSK

Kth Largest Element in an Array
class Solution {
public:
    int findKthLargest(vector<int>& nums, int k) {
        std::sort(nums.begin(), nums.end(), std::greater<int>());
        return nums[k-1];
    }
};

4.7.1255 - 2023-11-16 14:18:16 +0300 MSK

Search in a Binary Search Tree
/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    TreeNode* searchBST(TreeNode* root, int val) {
        while (root != nullptr) {
            if (root->val == val) {
                return root;
            }
            if (root->val > val) {
                root = root->left;
            } else {
                root = root->right;
            }
        }
        return root;
    }
};

4.7.1256 - 2023-11-16 14:15:58 +0300 MSK

Search in a Binary Search Tree
/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    TreeNode* searchBST(TreeNode* root, int val) {
        if (root == nullptr || root->val == val) {
            return root;
        }
        if (val > root->val) {
            return searchBST(root->right, val);
        }
        return searchBST(root->left, val);
    }
};

4.7.1257 - 2023-11-16 14:13:23 +0300 MSK

Find Pivot Index
class Solution {
public:
    int pivotIndex(vector<int>& nums) {
        int left {0}, right {std::accumulate(nums.begin() + 1, nums.end(), 0)};
        unsigned long length {nums.size()};
        if (right == 0) {
            return 0;
        }
        for (int i = 1; i < length; ++i) {
            left += nums[i-1];
            right -= nums[i];
            if (left == right) {
                return i;
            }
        }
        return -1;
    }
};

4.7.1258 - 2023-11-16 14:06:30 +0300 MSK

Find the Highest Altitude
class Solution {
public:
    int largestAltitude(vector<int>& gain) {
        int att {0}, maxAtt {0};
        for (int num : gain) {
            att += num;
            maxAtt = max(maxAtt, att);
        }
        return maxAtt;
    }
};

4.7.1259 - 2023-11-16 11:22:37 +0300 MSK

Find Unique Binary String
class Solution {
public:
    string findDifferentBinaryString(vector<string>& nums) {
        unordered_set<int> integers;
        for (string num : nums) {
            integers.insert(stoi(num, 0, 2));
        }

        int n = nums.size();
        string ans;
        for (int num = 0; num <= n; num++) {
            if (integers.find(num) == integers.end()) {
                ans = bitset<16>(num).to_string();
                break;
            }
        }
        return ans.substr(16 - n);
    }
};

4.7.1260 - 2023-11-15 16:53:47 +0300 MSK

Find the Difference of Two Arrays
class Solution {
public:
    vector<int> getElementsOnlyInFirstList(vector<int>& nums1, vector<int>& nums2) {
        unordered_set<int> onlyInNums1;
        for (int num : nums1) {
            bool existInNums2 = false;
            for (int x : nums2) {
                if (x == num) {
                    existInNums2 = true;
                    break;
                }
            }
            if (!existInNums2) {
                onlyInNums1.insert(num);
            }
        }
        return vector<int> (onlyInNums1.begin(), onlyInNums1.end());
    }
    
    vector<vector<int>> findDifference(vector<int>& nums1, vector<int>& nums2) {
        return {getElementsOnlyInFirstList(nums1, nums2), getElementsOnlyInFirstList(nums2, nums1)};
    }
};

4.7.1261 - 2023-11-15 16:12:27 +0300 MSK

Increasing Triplet Subsequence
class Solution {
public:
    bool increasingTriplet(vector<int>& nums) {
        auto length{nums.size()};
        int num1{INT_MAX}, num2{INT_MAX}; 
        for (int num : nums) {
            if (num <= num1) {
                num1 = num;
            } else if (num <= num2) {
                num2 = num;
            } else {
                return true;
            }
        }
        return false;
    }
};

4.7.1262 - 2023-11-15 15:18:40 +0300 MSK

Maximum Element After Decreasing and Rearranging
class Solution {
public:
    int maximumElementAfterDecrementingAndRearranging(vector<int>& arr) {
        std::sort(arr.begin(), arr.end());
        auto length{arr.size()};
        int prev{1};
        for (int i = 1; i < length; ++i) {
            if (arr[i] != prev) {
                ++prev;
            }
        }
        return prev;
    }
};

4.7.1263 - 2023-11-15 15:17:30 +0300 MSK

Maximum Element After Decreasing and Rearranging
class Solution {
public:
    int maximumElementAfterDecrementingAndRearranging(vector<int>& arr) {
        std::sort(arr.begin(), arr.end());
        auto length{arr.size()};
        int prev{1};
        for (int i = 1; i < length; ++i) {
            if (arr[i] == prev) {
                continue;
            }
            ++prev;
        }
        return prev;
    }
};

4.7.1264 - 2023-11-14 15:39:29 +0300 MSK

Unique Length-3 Palindromic Subsequences
class Solution {
public:
    int countPalindromicSubsequence(string s) {
        unordered_set<char> letters;
        for (char c : s) {
            letters.insert(c);
        }
        int ans = 0;
        for (char letter : letters) {
            int i = -1;
            int j = 0;
            for (int k = 0; k < s.size(); k++) {
                if (s[k] == letter) {
                    if (i == -1) {
                        i = k;
                    }
                    
                    j = k;
                }
            }
            unordered_set<char> between;
            for (int k = i + 1; k < j; k++) {
                between.insert(s[k]);
            }
            
            ans += between.size();
        }
        return ans;
    }
};

4.7.1265 - 2023-11-13 20:24:55 +0300 MSK

Reverse Vowels of a String
class Solution {
public:
    bool isVowel(char ch) {
        return ch == 'a' || ch == 'e' || ch == 'i' || ch == 'o' || ch == 'u' ||
               ch == 'A' || ch == 'E' || ch == 'I' || ch == 'O' || ch == 'U';
    }

    string reverseVowels(string s) {
        unsigned long length{s.size()};
        unsigned long left{0}, right{length-1};
        while (left < right) {
            char chLeft{s[left]};
            char chRight{s[right]};
            if (!isVowel(chLeft)) {
                ++left;
            } else if (!isVowel(chRight)) {
                --right;
            } else {
                s[left] = chRight;
                s[right] = chLeft;
                ++left;
                --right;
            }
        }
        return s;
    }
};

4.7.1266 - 2023-11-13 10:42:13 +0300 MSK

Sort Vowels in a String
class Solution {
public:
    // Returns true if the character is a vowel.
    bool isVowel(char c) {
        return c == 'a' || c == 'e' || c == 'o'|| c == 'u'|| c == 'i' 
            || c == 'A' || c == 'E' || c == 'O'|| c == 'U'|| c == 'I';
    }
    
    string sortVowels(string s) {
        unordered_map<char, int> count;

        // Store the frequencies for each character.
        for (char c : s) {
            if (isVowel(c)) {
                count[c]++;
            }
        }

        // Sorted string having all the vowels.
        string sortedVowel = "AEIOUaeiou";
        string ans;
        int j = 0;
        for (int i = 0; i < s.size(); i++) {
            if (!isVowel(s[i])) {
                ans += s[i];
            } else {
                // Skip to the character which is having remaining count.
                while (count[sortedVowel[j]] == 0) {
                    j++;
                }

                ans += sortedVowel[j];
                count[sortedVowel[j]]--;
            }
        }
        return ans;
    }
};

4.7.1267 - 2023-11-13 10:40:23 +0300 MSK

Sort Vowels in a String
class Solution {
public:
    string sortVowels(string s) {
        std::map<char, int> vowels{
            {'A', 0}, {'E', 0}, {'I', 0}, {'O', 0}, {'U', 0},
            {'a', 0}, {'e', 0}, {'i', 0}, {'o', 0}, {'u', 0}
        };
        unsigned long length{ s.size() };
        for (char ch : s) {
            if (vowels.contains(ch)) {
                ++vowels[ch];
            }
        }
        for (int i = 0; i < length; ++i) {
            const char ch = s[i];
            if (!vowels.contains(ch)) {
                continue;
            }
            for (const auto& [orderChar, count] : vowels) {
                if (count > 0) {
                    s[i] = orderChar;
                    --vowels[orderChar];
                    break;
                }
            }
        }
        return s;
    }
};

4.7.1268 - 2023-11-13 10:38:46 +0300 MSK

Sort Vowels in a String
class Solution {
public:
    string sortVowels(string s) {
        std::map<char, int> vowels{
            {'A', 0}, {'E', 0}, {'I', 0}, {'O', 0}, {'U', 0},
            {'a', 0}, {'e', 0}, {'i', 0}, {'o', 0}, {'u', 0}
        };
        const char order[10]{ 'A', 'E', 'I', 'O', 'U', 'a', 'e', 'i', 'o', 'u' };
        unsigned long length{ s.size() };
        for (char ch : s) {
            if (vowels.contains(ch)) {
                ++vowels[ch];
            }
        }
        for (int i = 0; i < length; ++i) {
            const char ch = s[i];
            if (!vowels.contains(ch)) {
                continue;
            }
            for (char orderChar : order) {
                if (vowels[orderChar] > 0) {
                    s[i] = orderChar;
                    --vowels[orderChar];
                    break;
                }
            }
        }
        return s;
    }
};

4.7.1269 - 2023-11-12 17:00:22 +0300 MSK

Maximum Average Subarray I
class Solution {
public:
    double findMaxAverage(vector<int>& nums, int k) {
        int length = nums.size();
        double sum = std::accumulate(nums.begin(), nums.begin() + k , 0);
        double maxSum = sum;
        for (int i = k; i < length; ++i) {
            sum += nums[i] - nums[i-k];
            maxSum = max(sum, maxSum);
        }
        return maxSum / k;
    }
};

4.7.1270 - 2023-11-12 16:08:04 +0300 MSK

String Compression
class Solution {
public:
    int compress(vector<char>& chars) {
        int i = 0, res = 0;
        int length = chars.size();
        while (i < length) {
            int groupLength = 1;
            while (i + groupLength < length && chars[i + groupLength] == chars[i]) {
                groupLength++;
            }
            chars[res++] = chars[i];
            if (groupLength > 1) {
                for (char c : to_string(groupLength)) {
                    chars[res++] = c;
                }
            }
            i += groupLength;
        }
        return res;
    }
};

4.7.1271 - 2023-11-12 15:43:55 +0300 MSK

Can Place Flowers
class Solution {
public:
    bool canPlaceFlowers(vector<int>& flowerbed, int n) {
        int curZeros = flowerbed[0] == 0 ? 2 : 0;
        int length = flowerbed.size();
        int ans = 0;
        for (int i = 1; i < length; ++i) { 
            if (flowerbed[i] == 0) {
                curZeros += 1;
                continue;
            }
            ans += (curZeros - 1) / 2;
            curZeros = 0;
            if (ans >= n) {
                return true;
            }
        }
        ans += curZeros / 2;
        return ans >= n;
    }
};

4.7.1272 - 2023-11-12 15:41:26 +0300 MSK

Can Place Flowers
class Solution {
public:
    bool canPlaceFlowers(vector<int>& flowerbed, int n) {
        int curZeros = 0, length = flowerbed.size();
        if (flowerbed[0] == 0) {
            curZeros = 2;
        }
        int ans = 0;
        for (int i = 1; i < length; ++i) {
            bool isFlower = flowerbed[i] == 1; 
            if (!isFlower) {
                curZeros += 1;
                continue;
            }
            ans += (curZeros - 1) / 2;
            curZeros = 0;
            if (ans >= n) {
                return true;
            }
        }
        ans += curZeros / 2;
        return ans >= n;
    }
};

4.7.1273 - 2023-11-12 11:40:25 +0300 MSK

Bus Routes
class Solution {
public:
    int numBusesToDestination(vector<vector<int>>& routes, int source, int target) {
        if (source == target) {
            return 0;
        }

        unordered_map<int, vector<int>> adjList;
        // Create a map from the bus stop to all the routes that include this stop.
        for (int route = 0; route < routes.size(); route++) {
            for (auto stop : routes[route]) {
                // Add all the routes that have this stop.
                adjList[stop].push_back(route);
            }
        }

        queue<int> q;
        unordered_set<int> vis;
        // Insert all the routes in the queue that have the source stop.
        for (auto route : adjList[source]){
            q.push(route);
            vis.insert(route);
        }

        int busCount = 1;
        while (q.size()) {
            int size = q.size();

            for (int i = 0; i < size; i++) {
                int route = q.front(); q.pop();

                // Iterate over the stops in the current route.
                for (auto stop: routes[route]) {
                    // Return the current count if the target is found.
                    if (stop == target) {
                        return busCount;
                    }

                    // Iterate over the next possible routes from the current stop.
                    for (auto nextRoute : adjList[stop]) {
                        if (!vis.count(nextRoute)) {
                            vis.insert(nextRoute);
                            q.push(nextRoute);
                        }
                    }
                }
            }
            busCount++;
        }
        return -1;
    }
};

4.7.1274 - 2023-11-11 16:10:00 +0300 MSK

Fibonacci Number
class Solution {
public:
    int fib(int n) {
        if (n < 2) {
            return n;
        }
        int cur = 1, prev = 0;
        for (int i = 2; i <= n; ++i) {
            int newVal = cur + prev;
            prev = cur;
            cur = newVal;
        }
        return cur;
    }
};

4.7.1275 - 2023-11-11 16:06:23 +0300 MSK

Remove Linked List Elements
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
    ListNode* removeElements(ListNode* head, int val) {
        head = new ListNode(-1, head);
        auto ans = head;
        while (head) {
            auto next = head->next;
            if (next && next->val == val) {
                head->next = next->next;
            } else {
                head = next;
            }
        }
        return ans->next;
    }
};

4.7.1276 - 2023-11-11 16:06:11 +0300 MSK

Remove Linked List Elements
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
    ListNode* removeElements(ListNode* head, int val) {
        head = new ListNode(-1, head);
        auto ans = head;
        while (head) {
            auto next = head->next;
            if (next && next->val == val) {
                head->next = next->next;
            } else {
                head = head->next;
            }
        }
        return ans->next;
    }
};

4.7.1277 - 2023-11-11 15:52:58 +0300 MSK

Valid Parentheses
class Solution {
public:
    bool isValid(string s) {
        std::vector<char> stack;
        for (const auto& ch : s) {
            switch (ch){
                case '[':
                case '{':
                case '(':
                    stack.push_back(ch);
                    break;
                case ')':
                    if (stack.empty() || stack.back() != '(') {
                        return false;
                    }
                    stack.pop_back();
                    break;
                case '}':
                    if (stack.empty() || stack.back() != '{') {
                        return false;
                    }
                    stack.pop_back();
                    break;
                case ']':
                    if (stack.empty() || stack.back() != '[') {
                        return false;
                    }
                    stack.pop_back();
                    break;
            }
        }
        return stack.size() == 0;
    }
};

4.7.1278 - 2023-11-11 15:43:36 +0300 MSK

Two Sum
class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) {
        std::map<int, int> numToIndex;
        int length = nums.size();
        std::vector<int> ans;
        for (int i = 0; i < length; ++i) {
            int num = nums[i];
            int diff = target - num;
            if (numToIndex.contains(diff)) {
                ans = {numToIndex[diff], i};
                break;
            }
            numToIndex[num] = i;
        }
        return ans;
    }
};

4.7.1279 - 2023-11-11 15:32:34 +0300 MSK

Reverse Words in a String
class Solution {
public:
    string reverseWords(string s) {
        string ans = "";
        string temp = "";
        int length = s.length();
        int j = 0;
        for (j = 0; s[j] == ' ' && j < length; ++j) { }
        for (int i = length - 1; i >= j; --i) {
            if(s[i] == ' '){
                if(temp != ""){                  
                    ans = ans + temp + ' ';
                    temp = "";
                }
                continue;
            }
            else{
                temp = s[i] + temp;
            }
        }
        return ans + temp;
    }
};

4.7.1280 - 2023-11-11 15:18:39 +0300 MSK

Reverse Linked List

class Solution {
public:
    ListNode* reverseList(ListNode* head) {
        ListNode* prev = NULL;
        ListNode* curr = head;
        while(curr != NULL){
            ListNode* next = curr->next;
            curr->next = prev;
            prev = curr;
            curr = next;
        }
        return prev;
    }
};

4.7.1281 - 2023-11-11 15:08:55 +0300 MSK

Move Zeroes
class Solution {
public:
    void moveZeroes(vector<int>& nums) {
        int length = nums.size();
        int lastNonZeroFoundAt = 0;
        for (int i = 0; i < length; ++i) {
            if (nums[i] != 0) {
                swap(nums[lastNonZeroFoundAt], nums[i]);
                lastNonZeroFoundAt += 1;
            }
        }
    }
};

4.7.1282 - 2023-11-11 15:06:06 +0300 MSK

Move Zeroes
class Solution {
public:
    void moveZeroes(vector<int>& nums) {
    int lastNonZeroFoundAt = 0;
    int length = nums.size();
    for (int i = 0; i < length; ++i) {
        int num = nums[i];
        if (num == 0) {
            continue;
        }
        if (i != lastNonZeroFoundAt) {
            nums[lastNonZeroFoundAt] = num;
        }
        lastNonZeroFoundAt += 1;
    }
 	for (int i = lastNonZeroFoundAt; i < length; i++) {
        nums[i] = 0;
    }
}
};

4.7.1283 - 2023-11-11 14:51:09 +0300 MSK

Design Graph With Shortest Path Calculator
class Graph {
public:
    vector<vector<pair<int, int>>> adjList;
    Graph(int n, vector<vector<int>>& edges) {
        adjList.resize(n);
        for (auto& e: edges)
            adjList[e[0]].push_back(make_pair(e[1], e[2]));
    }

    void addEdge(vector<int> edge) {
        adjList[edge[0]].push_back(make_pair(edge[1], edge[2]));
    }

    int shortestPath(int node1, int node2) {
        int n = adjList.size();
        priority_queue<vector<int>, vector<vector<int>>, greater<vector<int>>> pq;
        vector<int> costForNode(n, INT_MAX);
        costForNode[node1] = 0;
        pq.push({0, node1});

        while (!pq.empty()) {
            int currCost = pq.top()[0];
            int currNode = pq.top()[1];
            pq.pop();

            if (currCost > costForNode[currNode]) {
                continue;
            }
            if (currNode == node2) {
                return currCost;
            }
            for (auto& neighbor : adjList[currNode]) {
                int neighborNode = neighbor.first;
                int cost = neighbor.second;
                int newCost = currCost + cost;

                if (newCost < costForNode[neighborNode]) {
                    costForNode[neighborNode] = newCost;
                    pq.push({newCost, neighborNode});
                }
            }
        }
        return -1;
    }
};

4.7.1284 - 2023-11-10 19:50:03 +0300 MSK

Merge Strings Alternately
class Solution {
public:
    string mergeAlternately(string word1, string word2) {
        int m = word1.size();
        int n = word2.size();
        string result = "";

        for (int i = 0; i < max(m, n); i++) {
            if (i < m) {
                result.push_back(word1[i]);
            }
            if (i < n) {
                result.push_back(word2[i]);
            }
        }

        return result;
    }
};

4.7.1285 - 2023-11-10 19:49:28 +0300 MSK

Merge Strings Alternately
class Solution {
public:
    string mergeAlternately(string word1, string word2) {
        int l1 = word1.size(), l2 = word2.size();
        string result = "";
        int i = 0, j = 0;
        while (i < l1 || j < l2) {
            if (i < l1) {
                result.push_back(word1[i++]);
            }
            if (j < l2) {
                result.push_back(word2[j++]);
            }
        }
        return result;
    }
};

4.7.1286 - 2023-11-10 19:47:59 +0300 MSK

Merge Strings Alternately
class Solution {
public:
    string mergeAlternately(string word1, string word2) {
        std::stringstream ans;
        int l1 = word1.size(), l2 = word2.size();
        int lMax = max(l1, l2);
        for (int i = 0; i < lMax; ++i) {
            if (i < l1) {
                ans << word1[i];
            } else {
                ans << word2.substr(i);
                break;
            }
            if (i < l2) {
                ans << word2[i];
            } else {
                ans << word1.substr(i + 1);
                break;
            }
        }
        return ans.str();
    }
};

4.7.1287 - 2023-11-10 19:34:50 +0300 MSK

Subrectangle Queries
class SubrectangleQueries {
    vector<vector<int>> res;
public:
    SubrectangleQueries(vector<vector<int>>& rectangle) {
        res=rectangle;
    }
    
    void updateSubrectangle(int row1, int col1, int row2, int col2, int newValue) {
        for(int i = row1; i <= row2; ++i) {
            for(int j= col1; j <= col2; ++j) {
                res[i][j] = newValue;
            }
        }
    }
    
    int getValue(int row, int col) {
        return res[row][col];
    }
};

/**
 * Your SubrectangleQueries object will be instantiated and called as such:
 * SubrectangleQueries* obj = new SubrectangleQueries(rectangle);
 * obj->updateSubrectangle(row1,col1,row2,col2,newValue);
 * int param_2 = obj->getValue(row,col);
 */

4.7.1288 - 2023-11-10 19:18:28 +0300 MSK

Subrectangle Queries
class SubrectangleQueries {
public:
    std::vector<std::vector<int>> rectangle;
    std::vector<std::array<int, 5>> updates;
    SubrectangleQueries(vector<vector<int>>& rectangle) {
        this->rectangle = rectangle;
    }
    
    void updateSubrectangle(int row1, int col1, int row2, int col2, int newValue) {
        this->updates.push_back({row1, col1, row2, col2, newValue});
    }
    
    int getValue(int row, int col) {
        int length = this->updates.size();
        for (int i = length - 1; i >= 0; --i) {
            auto const [row1, col1, row2, col2, newValue] = this->updates[i];
            if (row < row1 || row > row2 || col < col1 || col > col2) {
                continue;
            }
            return newValue;
        }
        return this->rectangle[row][col];
    }
};

/**
 * Your SubrectangleQueries object will be instantiated and called as such:
 * SubrectangleQueries* obj = new SubrectangleQueries(rectangle);
 * obj->updateSubrectangle(row1,col1,row2,col2,newValue);
 * int param_2 = obj->getValue(row,col);
 */

4.7.1289 - 2023-11-10 18:37:59 +0300 MSK

Operations on Tree
class LockingTree {
public:
    std::vector<int> parents, locked;
    std::vector<std::vector<int>> children;
    LockingTree(vector<int>& parent) {
        int length = parent.size();
        this->children.resize(length);
        this->locked.resize(length, -1);
        this->parents = parent;
        for (int i = 1; i < length; ++i) {
            this->children[this->parents[i]].push_back(i);
        }
    }
    
    bool lock(int num, int user) {
        if (this->locked[num] != -1) {
            return false;
        }
        this->locked[num] = user;
        return true;
    }
    
    bool unlock(int num, int user) {
        if (this->locked[num] != user) {
            return false;
        }
        this->locked[num] = -1;
        return true;
    }

    bool upgrade(int num, int user) {
        if (this->locked[num] != -1) {
            return false;
        }
        int parent = this->parents[num];
        while (parent != -1) {
            if (this->locked[parent] != -1) {
                return false;
            }
            parent = this->parents[parent];
        }
        if (!this->unlockDesc(num)) {
            return false;
        }
        this->locked[num] = user;
        return true;
    }

    bool unlockDesc(int parent) {
        bool hasLocked = false;
        for (auto const& child : this->children[parent]) {
            if (this->locked[child] != -1) {
                this->locked[child] = -1;
                hasLocked = true;
            }
            bool descHasLocked = unlockDesc(child);
            if (descHasLocked) {
                hasLocked = true;
            }
        }
        return hasLocked;
    }
};

/**
 * Your LockingTree object will be instantiated and called as such:
 * LockingTree* obj = new LockingTree(parent);
 * bool param_1 = obj->lock(num,user);
 * bool param_2 = obj->unlock(num,user);
 * bool param_3 = obj->upgrade(num,user);
 */

4.7.1290 - 2023-11-10 16:30:33 +0300 MSK

Implement Stack using Queues
class MyStack {
public:
    std::vector<int> v;

    MyStack() {
        this->v = {};
    }
    
    void push(int x) {
        this->v.push_back(x);
    }
    
    int pop() {
        int last = this->v.back();
        this->v.pop_back();
        return last;
    }
    
    int top() {
        return this->v.back();
    }
    
    bool empty() {
        return this->v.empty();
    }
};

/**
 * Your MyStack object will be instantiated and called as such:
 * MyStack* obj = new MyStack();
 * obj->push(x);
 * int param_2 = obj->pop();
 * int param_3 = obj->top();
 * bool param_4 = obj->empty();
 */

4.7.1291 - 2023-11-10 13:30:38 +0300 MSK

Restore the Array From Adjacent Pairs
func restoreArray(adjacentPairs [][]int) []int {
    // [[2,1],[3,4],[3,2]]
    // 1: [2]
    // 2: [1, 3]
    // 3: [2, 4]
    // 4: [3]
    // Output: [1,2,3,4]
    graph := map[int][]int{}
    length := len(adjacentPairs) + 1
    ans := make([]int, length)
    for _, pair := range adjacentPairs {
        num1, num2 := pair[0], pair[1]
        graph[num1] = append(graph[num1], num2)
        graph[num2] = append(graph[num2], num1)
    }
    for node, edges := range graph {
        if len(edges) == 1 {
            ans[0], ans[1] = node, edges[0]
            break
        }
    }
    cur, prev := ans[1], ans[0]
    for i := 2; i < length; i++ {
        for _, target := range graph[cur] {
            if target != prev {
                ans[i] = target
                cur, prev = target, cur
                break
            }
        }
    }
    return ans
}

4.7.1292 - 2023-11-10 13:24:56 +0300 MSK

Restore the Array From Adjacent Pairs
func restoreArray(adjacentPairs [][]int) []int {
    // [[2,1],[3,4],[3,2]]
    // 1: [2]
    // 2: [1, 3]
    // 3: [2, 4]
    // 4: [3]
    // Output: [1,2,3,4]
    graph := map[int][]int{}
    for _, pair := range adjacentPairs {
        num1, num2 := pair[0], pair[1]
        graph[num1] = append(graph[num1], num2)
        graph[num2] = append(graph[num2], num1)
    }
    length := len(adjacentPairs) + 1
    ans := make([]int, length)
    for node, edges := range graph {
        if len(edges) == 1 {
            ans[0], ans[1] = node, edges[0]
            break
        }
    }
    for i := 2; i < length; i++ {
        cur, prev := ans[i-1], ans[i-2]
        for _, target := range graph[cur] {
            if target != prev {
                ans[i] = target
            }
        }
    }
    return ans
}

4.7.1293 - 2023-11-09 10:03:41 +0300 MSK

Count Number of Homogenous Substrings
func countHomogenous(s string) int {
    var (
        mod int64 = 1000000007 
        total int64 = 0
        count int64 = 0
        cur = s[0]
    )
    
    for i := 0; i < len(s); i++ {
        char := s[i]
        if char == cur {
            count++
        } else {
            count = 1
            cur = char
        }
        total += count
    }
    
    return int(total % mod)
}

4.7.1294 - 2023-11-08 11:09:02 +0300 MSK

Determine if a Cell Is Reachable at a Given Time
func isReachableAtTime(sx int, sy int, fx int, fy int, t int) bool {
    vert := abs(sy, fy)
    dist := vert + max(0, abs(sx, fx) - vert)
    if dist == 0 && t == 1 {
        return false
    }
    return dist <= t
}

func abs(x, y int) int {
    if x > y {
        return x - y
    }
    return y - x
}

4.7.1295 - 2023-11-07 21:56:45 +0300 MSK

Design HashSet
type MyHashSet struct {
    m map[int]struct{}
}


func Constructor() MyHashSet {
    return MyHashSet{map[int]struct{}{}}
}


func (this *MyHashSet) Add(key int)  {
    this.m[key] = struct{}{}
}


func (this *MyHashSet) Remove(key int)  {
    delete(this.m, key)
}


func (this *MyHashSet) Contains(key int) bool {
    _, ok := this.m[key]
    return ok
}


/**
 * Your MyHashSet object will be instantiated and called as such:
 * obj := Constructor();
 * obj.Add(key);
 * obj.Remove(key);
 * param_3 := obj.Contains(key);
 */

4.7.1296 - 2023-11-07 21:50:49 +0300 MSK

Merge Strings Alternately
func mergeAlternately(word1 string, word2 string) string {
    var sb strings.Builder
    length1, length2 := len(word1), len(word2)
    for i := 0; i < max(length1, length2); i++ {
        if i == length1 {
            sb.WriteString(word2[i:length2])
            break
        }
        if i == length2 {
            sb.WriteString(word1[i:length1])
            break
        }
        sb.WriteByte(word1[i])
        sb.WriteByte(word2[i])
    }
    return sb.String()
}

4.7.1297 - 2023-11-07 19:07:48 +0300 MSK

Eliminate Maximum Number of Monsters
func eliminateMaximum(dist []int, speed []int) int {
    arrival := []float32{}
    length := len(dist)
    for i := 0; i < length; i++ {
        arrival = append(arrival, float32(dist[i]) / float32(speed[i]))
    }
    slices.Sort(arrival)
    ans := 0
    for i := 0; i < length; i++ {
        if arrival[i] <= float32(i) {
            break
        }
        ans += 1
    }
    return ans
}

4.7.1298 - 2023-11-06 18:41:34 +0300 MSK

Design Circular Deque
type MyCircularDeque struct {
    list []int
    size int
}


func Constructor(k int) MyCircularDeque {
    return MyCircularDeque{[]int{}, k}
}


func (this *MyCircularDeque) InsertFront(value int) bool {
    if this.IsFull() {
        return false
    }
    this.list = append([]int{value}, this.list...)
    return true
}


func (this *MyCircularDeque) InsertLast(value int) bool {
    if this.IsFull() {
        return false
    }
    this.list = append(this.list, value)
    return true
}


func (this *MyCircularDeque) DeleteFront() bool {
    if this.IsEmpty() {
        return false
    }
    this.list = this.list[1:]
    return true
}


func (this *MyCircularDeque) DeleteLast() bool {
    if this.IsEmpty() {
        return false
    }
    this.list = this.list[:len(this.list) - 1]
    return true
}


func (this *MyCircularDeque) GetFront() int {
    if this.IsEmpty() {
        return -1
    }
    return this.list[0]   
}


func (this *MyCircularDeque) GetRear() int {
    if this.IsEmpty() {
        return -1
    }
    return this.list[len(this.list) - 1]
}


func (this *MyCircularDeque) IsEmpty() bool {
    return len(this.list) == 0
}


func (this *MyCircularDeque) IsFull() bool {
    return len(this.list) == this.size
}


/**
 * Your MyCircularDeque object will be instantiated and called as such:
 * obj := Constructor(k);
 * param_1 := obj.InsertFront(value);
 * param_2 := obj.InsertLast(value);
 * param_3 := obj.DeleteFront();
 * param_4 := obj.DeleteLast();
 * param_5 := obj.GetFront();
 * param_6 := obj.GetRear();
 * param_7 := obj.IsEmpty();
 * param_8 := obj.IsFull();
 */

4.7.1299 - 2023-11-06 14:57:33 +0300 MSK

Seat Reservation Manager
type SeatManager struct {
    heap *binaryheap.Heap
}


func Constructor(n int) SeatManager {
    heap := binaryheap.NewWithIntComparator()
    for i := 1; i <= n; i++ {
        heap.Push(i)
    }
    return SeatManager{heap}
}


func (this *SeatManager) Reserve() int {
    val, _ := this.heap.Pop()
    return val.(int)
}


func (this *SeatManager) Unreserve(seatNumber int)  {
    this.heap.Push(seatNumber)
}


/**
 * Your SeatManager object will be instantiated and called as such:
 * obj := Constructor(n);
 * param_1 := obj.Reserve();
 * obj.Unreserve(seatNumber);
 */

4.7.1300 - 2023-11-06 14:49:27 +0300 MSK

Seat Reservation Manager
type SeatManager struct {
    seats []bool
}


func Constructor(n int) SeatManager {
    return SeatManager{make([]bool, n)}
}


func (this *SeatManager) Reserve() int {
    for i, num := range this.seats {
        if !num {
            this.seats[i] = true
            return i + 1
        }
    }
    return -1
}


func (this *SeatManager) Unreserve(seatNumber int)  {
    this.seats[seatNumber-1] = false
}


/**
 * Your SeatManager object will be instantiated and called as such:
 * obj := Constructor(n);
 * param_1 := obj.Reserve();
 * obj.Unreserve(seatNumber);
 */

4.7.1301 - 2023-11-05 21:02:40 +0300 MSK

Serialize and Deserialize Binary Tree
/**
 * Definition for a binary tree node.
 * type TreeNode struct {
 *     Val int
 *     Left *TreeNode
 *     Right *TreeNode
 * }
 */

type Codec struct {
    
}

func Constructor() Codec {
    return Codec{}
}

// Serializes a tree to a single string.
func (this *Codec) serialize(root *TreeNode) string {
    if root == nil {
        return ""
    }
    var buffer bytes.Buffer
    queue := []*TreeNode{root}
    for length := len(queue); length > 0; length = len(queue) {
        for i := 0; i < length; i++ {
            node := queue[i]
            if node != nil {
                buffer.WriteString(strconv.Itoa(node.Val))
                queue = append(queue, node.Left, node.Right)
            }
            buffer.WriteString(",")
        }
        queue = queue[length:]
    }
    ans := buffer.String()
    return ans[:len(ans)-1]
}

// Deserializes your encoded data to tree.
func (this *Codec) deserialize(data string) *TreeNode {    
    nodes := []*TreeNode{}
    for _, str := range strings.Split(data, ",") {
        if str == "" {
            nodes = append(nodes, nil)
        } else {
            num, _ := strconv.Atoi(str)
            nodes = append(nodes, &TreeNode{num, nil, nil})
        }
    }
    start := 0
    length := len(nodes)
    for _, node := range nodes {
        if node == nil {
            continue
        }
        left, right := 2 * start + 1, 2 * start + 2
        if left < length {
            node.Left = nodes[left]
        }
        if right < length {
            node.Right = nodes[right]
        }
        start++
    }
    return nodes[0]
}


/**
 * Your Codec object will be instantiated and called as such:
 * ser := Constructor();
 * deser := Constructor();
 * data := ser.serialize(root);
 * ans := deser.deserialize(data);
 */

4.7.1302 - 2023-11-05 12:06:04 +0300 MSK

Find the Winner of an Array Game
func getWinner(arr []int, k int) int {
    if k == 1 {
        return max(arr[0], arr[1])
    }
    length := len(arr)
    if k >= length {
        return slices.Max(arr)
    }
    curWinner, winCount := arr[0], 0
    for _, num := range arr[1:] {
        if curWinner > num {
            winCount++
        } else {
            curWinner = num
            winCount = 1
        }
        if winCount == k {
            return curWinner
        }
    }
    return curWinner
}

4.7.1303 - 2023-11-05 12:01:59 +0300 MSK

Find the Winner of an Array Game
func getWinner(arr []int, k int) int {
    curMax, winCount := arr[0], 0
    i, length := 1, len(arr)
    for {
        num := arr[i]
        if num > curMax {
            curMax = num
            winCount = 1
        } else {
            winCount++
        }
        if winCount == k {
            return curMax
        }
        i = (i + 1) % length
    }
    return -1
}

4.7.1304 - 2023-11-04 13:31:04 +0300 MSK

Find Median from Data Stream
type MaxHeap []int
func (m MaxHeap) Len() int { return len(m) }
func (m MaxHeap) Less(i, j int) bool { return m[i] > m[j] }
func (m MaxHeap) Swap(i, j int) { m[i], m[j] = m[j], m[i] }
func (m *MaxHeap) Pop() interface{} {
    v := (*m)[len(*m)-1]
    *m = (*m)[:len(*m)-1]
    return v
}
func (m *MaxHeap) Push(v interface{}) { *m = append(*m, v.(int)) }
func (m MaxHeap) Top() int { return m[0] }

type MinHeap []int
func (m MinHeap) Len() int { return len(m) }
func (m MinHeap) Less(i, j int) bool { return m[i] < m[j] }
func (m MinHeap) Swap(i, j int) { m[i], m[j] = m[j], m[i] }
func (m *MinHeap) Pop() interface{} {
    v := (*m)[len(*m)-1]
    *m = (*m)[:len(*m)-1]
    return v
}
func (m *MinHeap) Push(v interface{}) { *m = append(*m, v.(int)) }
func (m MinHeap) Top() int { return m[0] }

type MedianFinder struct {
    left MaxHeap
    right MinHeap    
}

func Constructor() MedianFinder {
    return MedianFinder{}    
}

func (mf *MedianFinder) AddNum(num int)  {
    if len(mf.left) + len(mf.right) == 0 {
        heap.Push(&(mf.left), num)
        return
    }
    for {
        if len(mf.left) < len(mf.right) {
            if num <= mf.right.Top() {
                heap.Push(&(mf.left), num)
                return
            } else {
                v := heap.Pop(&(mf.right))
                heap.Push(&(mf.left), v)
            }
        } else {
            if num >= mf.left.Top() {
                heap.Push(&(mf.right), num)
                return
            } else {
                v := heap.Pop(&(mf.left))
                heap.Push(&(mf.right), v)
            }
        }
    }
}

func (mf *MedianFinder) FindMedian() float64 {
    if len(mf.left) == len(mf.right) {
        return float64(mf.left.Top() + mf.right.Top()) / 2.0
    } else if len(mf.left) > len(mf.right) {
        return float64(mf.left.Top())
    } else {
        return float64(mf.right.Top())
    }   
}

4.7.1305 - 2023-11-04 13:30:46 +0300 MSK

IPO
type Project struct {
    profit, capital int
}

type IntHeap []int
func (h IntHeap) Len() int           { return len(h) }
func (h IntHeap) Less(i, j int) bool { return h[i] > h[j] }
func (h IntHeap) Swap(i, j int)      { h[i], h[j] = h[j], h[i] }
func (h *IntHeap) Push(x interface{}) { *h = append(*h, x.(int)) }
func (h *IntHeap) Pop() interface{} {
	old := *h
	n := len(old)
	x := old[n-1]
	*h = old[0 : n-1]
	return x
}

func findMaximizedCapital(k int, w int, profits []int, capital []int) int {
    n := len(profits)
    projects := make([]Project, n)
    for i := range profits {
        projects[i] = Project{profits[i], capital[i]}
    }
    sort.Slice(projects, func (i, j int) bool {
        return projects[i].capital < projects[j].capital
    })
    
    q := &IntHeap{}
    heap.Init(q)

    ptr := 0
    for i := 0; i < k; i++ {
        for ptr < n && projects[ptr].capital <= w {
            heap.Push(q, projects[ptr].profit)
            ptr++
        }
        if q.Len() == 0 {
            break
        }
        w += heap.Pop(q).(int)
    }
    return w
}

4.7.1306 - 2023-11-04 13:30:28 +0300 MSK

Find Peak Element
func findPeakElement(nums []int) int {
    left := 0
    right := len(nums) - 1
    
    for left < right {
        mid := left + (right - left) / 2
        
        if nums[mid] > nums[mid+1] {
            // The peak is in the left half
            right = mid
        } else {
            // The peak is in the right half
            left = mid + 1
        }
    }
    
    return left
}

4.7.1307 - 2023-11-04 13:30:08 +0300 MSK

Merge k Sorted Lists
/**
 * Definition for singly-linked list.
 * type ListNode struct {
 *     Val int
 *     Next *ListNode
 * }
 */
func mergeKLists(lists []*ListNode) *ListNode {
    n:=len(lists)
    if n==0{
        return nil
    }
    curr:=lists[0]
    if n==1{
        return curr
    }
    for i:=1;i<n;i++{
        curr=mergeList(curr,lists[i])
    }
    return curr
}

func mergeList(l1,l2 *ListNode) *ListNode {
    head:=&ListNode{}
    curr:=head
    for l1!=nil && l2!=nil{
        if l1.Val<l2.Val{
            curr.Next=l1
            l1=l1.Next
            curr=curr.Next
        }else{
            curr.Next=l2
            l2=l2.Next
            curr=curr.Next
        }
    }
    if l1 != nil {
        curr.Next = l1
    } else if l2 != nil {
        curr.Next = l2
    }
    return head.Next
}

4.7.1308 - 2023-11-04 13:29:52 +0300 MSK

Construct Quad Tree
/**
 * Definition for a QuadTree node.
 * type Node struct {
 *     Val bool
 *     IsLeaf bool
 *     TopLeft *Node
 *     TopRight *Node
 *     BottomLeft *Node
 *     BottomRight *Node
 * }
 */

func construct(grid [][]int) *Node {
	var dfs func(y0, x0, width int) *Node
	dfs = func(y0, x0, width int) *Node {
		if width == 1 {
			return &Node{
				Val:    grid[y0][x0] == 1,
				IsLeaf: true,
			}
		}

		w := width / 2
		topLeft := dfs(y0, x0, w)
		topRight := dfs(y0, x0+w, w)
		bottomLeft := dfs(y0+w, x0, w)
		bottomRight := dfs(y0+w, x0+w, w)
		var node *Node

		if topLeft.Val == topRight.Val && bottomLeft.Val == bottomRight.Val && topLeft.Val == bottomLeft.Val &&
			topLeft.IsLeaf && topRight.IsLeaf && bottomLeft.IsLeaf && bottomRight.IsLeaf {
			node = &Node{
				Val:    topLeft.Val,
				IsLeaf: true,
			}
		} else {
			node = &Node{
				Val:         true,
				IsLeaf:      false,
				TopLeft:     topLeft,
				TopRight:    topRight,
				BottomLeft:  bottomLeft,
				BottomRight: bottomRight,
			}
		}
		return node
	}
	return dfs(0, 0, len(grid))
}

4.7.1309 - 2023-11-04 13:29:35 +0300 MSK

N-Queens II
func totalNQueens(n int) int {
    sCol:=make([]bool,n)
    sD1:=make([]bool,2*n)
    sD2:=make([]bool,2*n)
    return helper(0,n,sCol,sD1,sD2)
}
func helper(r,n int,sCol,sD1,sD2 []bool) int{
    if r==n{
        return 1
    }
    res:=0
    for i:=0; i < n; i++ {
        if !sCol[i] && !sD1[i+r] && !sD2[(r-i)+n]{
          // board[r][i]=true
            sCol[i]=true
            sD1[i+r]=true
            sD2[(r-i)+n]=true
            res=res+helper(r+1,n,sCol,sD1,sD2)
          //  board[r][i]=false
            sCol[i]=false
            sD1[i+r]=false
            sD2[(r-i)+n]=false
        }
    }
    return res
}

4.7.1310 - 2023-11-04 13:29:17 +0300 MSK

Word Search II
type Node struct {
	children [26]*Node
	word     string
}

func (n *Node) Insert(word string) {
	cur := n
	for _, c := range word {
		idx := c - 'a'
		if cur.children[idx] == nil {
			cur.children[idx] = &Node{}
		}
		cur = cur.children[idx]
	}
	cur.word = word
}

func (n *Node) IsEmpty() bool {
	for _, child := range n.children {
		if child != nil {
			return false
		}
	}
	return true
}

func (n *Node) Remove(word string) bool {
	if len(word) == 0 {
		n.word = ""
		return n.IsEmpty()
	}
	child := n.children[word[0]-'a']
	if child.Remove(word[1:]) {
		n.children[word[0]-'a'] = nil
		return n.IsEmpty()
	}
	return false
}

func dfs(board [][]byte, r, c int, root, cur *Node, res *[]string) {
	rc := board[r][c]
	board[r][c] = 0
    
	if cur.word != "" {
		*res = append(*res, cur.word)
		root.Remove(cur.word)
	}
	ds := [5]int{0, 1, 0, -1, 0}
	for i := 0; i < len(ds)-1; i++ {
		dr, dc := r+ds[i], c+ds[i+1]
		if dr < 0 || dr >= len(board) || dc < 0 || dc >= len(board[0]) {
			continue
		}
		b := board[dr][dc]
		if b == 0 || cur.children[b-'a'] == nil {
			continue
		}
		dfs(board, dr, dc, root, cur.children[b-'a'], res)
	}
	board[r][c] = rc
}

func findWords(board [][]byte, words []string) []string {
	m, n := len(board), len(board[0])
	res, trie, has := []string{}, &Node{}, map[string]bool{}

	for r := 0; r < m; r++ {
		for c := 0; c < n-1; c++ {
			p := string(board[r][c]) + string(board[r][c+1])
			has[p] = true
		}
	}
	for r := 0; r < m-1; r++ {
		for c := 0; c < n; c++ {
			p := string(board[r][c]) + string(board[r+1][c])
			has[p] = true
		}
	}
	for _, word := range words {
		valid := true
		for i := 0; i < len(word)-1; i++ {
			a, b := string(word[i]), string(word[i+1])
			if !has[a+b] && !has[b+a] {
				valid = false
				break
			}
		}
		if valid {
			trie.Insert(word)
		}
	}
	for r := 0; r < m; r++ {
		for c := 0; c < n; c++ {
			b := board[r][c]
			if trie.children[b-'a'] != nil {
				dfs(board, r, c, trie, trie.children[b-'a'], &res)
			}
		}
	}
	return res
}

4.7.1311 - 2023-11-04 13:28:50 +0300 MSK

Word Ladder
func ladderLength(beginWord string, endWord string, wordList []string) int {
    
    set := make(map[string]struct{}, len(wordList))
    
    present := false
    
    for _, v := range wordList {
        if endWord == v {
            present = true
        } 
        
        set[v] = struct{}{} 
    }
    
    if !present {
        return 0
    }
    
    set[beginWord] = struct{}{}
    q := []string{beginWord}
    
    depth := 1
    breadth := 0
    
    breadth = len(q)
    
    for ;breadth > 0; {
        s := q[0]
        
        if s == endWord {
            return depth
        }
        
        for i:='a'; i <= 'z'; i += 1 {
                        
            for j := 0; j<len(s); j++ {
 
                if rune(s[j]) != i {
                    
                    temp := s[:j] + string(i) + s[j+1:]
                    if _, ok := set[temp]; !ok {
                        continue
                    }
                    
                    q = append(q, temp)
                    delete(set, s)
                }
            }
        }
        
        q = q[1:]
        
        breadth -= 1
        if breadth == 0 {
            breadth = len(q)
            depth += 1
        }
    }
    
    return 0 
}

4.7.1312 - 2023-11-04 13:28:04 +0300 MSK

Course Schedule II
func findOrder(numCourses int, prerequisites [][]int) []int {
    //build the graph
    graph := make([][]int,numCourses)
    in_degree := make([]int,numCourses)
    for _,v := range prerequisites{
        graph[v[1]] = append(graph[v[1]], v[0])
        in_degree[v[0]]++
    }

    frontier := []int{}
    for i,v := range in_degree{
        if v==0{
            frontier = append(frontier,i)
        }
    }

    result := []int{}
    for len(frontier)!=0{
        cur := frontier[0]
        frontier = frontier[1:]
        result = append(result,cur)
        for _,v := range graph[cur]{
            in_degree[v]--
            if in_degree[v]==0{
                frontier = append(frontier,v)
            }
        }
    }

    if len(result)==numCourses{
        return result
    }
    return []int{}
}

4.7.1313 - 2023-11-04 13:27:48 +0300 MSK

Binary Tree Maximum Path Sum
/**
 * Definition for a binary tree node.
 * type TreeNode struct {
 *     Val int
 *     Left *TreeNode
 *     Right *TreeNode
 * }
 */
func maxPathSum(root *TreeNode) int {
    ans := -1 << 63
    maxPath(root, &ans)
    return ans
}

func maxPath(root *TreeNode, ans *int) int {
    if root == nil {
        return 0
    }
    leftPathSum := maxPath(root.Left, ans)
    rightPathSum := maxPath(root.Right, ans)
    *ans = max(*ans, leftPathSum + rightPathSum + root.Val)
    return max(max(leftPathSum+root.Val, rightPathSum+root.Val), 0)
}

func max(a int, b int) int {
    if (a >= b) {
        return a
    }
    return b
}

4.7.1314 - 2023-11-04 13:27:29 +0300 MSK

Construct Binary Tree from Inorder and Postorder Traversal
func buildTree(inorder []int, postorder []int) *TreeNode {
	n := len(postorder)
	if n == 0 {
		return nil
	}

	pivotId := 0
	for pivotId < n && inorder[pivotId] != postorder[n-1] {
		pivotId++
	}

	root := new(TreeNode)
	root.Val = postorder[n-1]
	root.Left = buildTree(inorder[:pivotId], postorder[:pivotId])
	root.Right = buildTree(inorder[pivotId+1:], postorder[pivotId:n-1])
	return root
}

4.7.1315 - 2023-11-04 13:27:12 +0300 MSK

Construct Binary Tree from Preorder and Inorder Traversal
func buildTree(preorder []int, inorder []int) *TreeNode {
	n := len(inorder)

	if n == 0 {
		return nil
	}

	pv := preorder[0]
	pi := 0
	for pi < n && inorder[pi] != pv {
		pi++
	}

	ans := new(TreeNode)
	ans.Val = pv
	ans.Left = buildTree(preorder[1:], inorder[:pi])
	ans.Right = buildTree(preorder[1+pi:], inorder[pi+1:])

	return ans
}

4.7.1316 - 2023-11-04 13:26:43 +0300 MSK

Reverse Nodes in k-Group
func reverseKGroup(head *ListNode, k int) *ListNode {
	node, cnt := head, 0
	for cnt < k {
		if node == nil {
			return head
		}
		node = node.Next
		cnt++
	}

	prev := reverseKGroup(node, k)
	for cnt > 0 {
		next := head.Next
		head.Next = prev
		prev = head
		head = next
		cnt--
	}

	return prev
}

4.7.1317 - 2023-11-04 13:25:42 +0300 MSK

Minimum Number of Arrows to Burst Balloons
func findMinArrowShots(points [][]int) int {
	// greedy solution
	sort.Slice(points, func(i, j int) bool {
		return points[i][1] < points[j][1]
	})
	count := 1
	end := points[0][1]
	for i := 1; i < len(points); i++ {
		if points[i][0] > end {
			count++
			end = points[i][1]
		}
	}
	return count
}

4.7.1318 - 2023-11-04 13:25:15 +0300 MSK

Minimum Window Substring
func minWindow(s string, t string) string {
    m := len(s)
    n := len(t)
    
    if m == 0 || n == 0 || m < n {
        return ""
    }

    dict := make(map[byte]int)
    for i := 0; i < n; i++ {
        dict[t[i]]++
    }
    
    // required unique chars
    required := len(dict)
    actual := 0
    window := make(map[byte]int)
    minSize := math.MaxInt64
    start := 0
    left, right := 0, 0
    
    for end := 0; end < m; end++ {
        c := s[end]
        window[c]++
        
        if value, ok := dict[c]; ok {
            if value == window[c] {
                actual++
            }
        }
        
        for start <= end && actual == required {
            size := end-start+1
            if size < minSize {
                minSize = size
                left = start
                right = end
            }
            
            rc := s[start]
            window[rc]--
            if value, ok := dict[rc]; ok {
                if value > window[rc] {
                    actual--
                }
            }
            start++
        }
    }
    
    if minSize == math.MaxInt64 {
        return ""
    }
    return s[left:right+1]
}

4.7.1319 - 2023-11-04 13:24:58 +0300 MSK

Substring with Concatenation of All Words
func findSubstring(s string, words []string) []int {
    
    wordLen := len(words[0])
    totalWords := len(words)
    mem := make(map[string]int, totalWords)
    
    
    for _, str := range words {
        mem[str] += 1
    }
    
    temp := make(map[string]int, totalWords)
    var found bool
    result := make([]int, 0)
    
    for i:=0; i + wordLen*totalWords <= len(s);  {
            
        found = true
        temp = make(map[string]int, totalWords)

        for j := i; j < i + wordLen*totalWords; j += wordLen {
            if _, ok := mem[ s[j:j+wordLen] ]; ok {
                temp[ s[j:j+wordLen] ] += 1
            } else {
                found = false
                break
            }
        }

        if found {
            for key, _ := range mem {
                if val, ok := temp[key]; !ok || val != mem[key]{
                    i++
                    found = false
                    break
                }
            }

            if found {
                result = append(result, i)
                i += 1    
            }

        } else {
            i++
        }
    }
    
    return result
    
}

4.7.1320 - 2023-11-04 13:23:30 +0300 MSK

Insert Interval
func insert(intervals [][]int, new []int) [][]int {
    n := len(intervals)
    i := sort.Search(n, func(i int) bool { return intervals[i][0] > new[0] })
    j := sort.Search(n, func(j int) bool { return intervals[j][1] > new[1] })
    if i >= 1 && new[0] <= intervals[i-1][1] {
        new[0] = intervals[i-1][0]
        i--
    }
    if j < n && new[1] >= intervals[j][0] {
        new[1] = intervals[j][1]
        j++
    }
    return append(intervals[:i], append([][]int{new}, intervals[j:]...)...)
}

4.7.1321 - 2023-11-04 13:22:41 +0300 MSK

Basic Calculator
func calculate(s string) int {
	result, _ := calculateFrom(s, 0)
	return result
}

func calculateFrom(s string, idFrom int) (result, idEnd int) {
	result, currNum, sign := 0, 0, 1

	for idEnd = idFrom; idEnd < len(s) && s[idEnd] != ')'; idEnd++ {
		switch {
		case s[idEnd] >= '0':
			currNum = currNum*10 + int(s[idEnd]-'0')
		case s[idEnd] == '(':
			currNum, idEnd = calculateFrom(s, idEnd+1)
		case s[idEnd] == '-' || s[idEnd] == '+':
			result, currNum = result+currNum*sign, 0
			sign = 44 - int(s[idEnd]) // '-'=45; '+'=43
		}
	}

	return result + currNum*sign, idEnd
}

4.7.1322 - 2023-11-04 10:36:18 +0300 MSK

Last Moment Before All Ants Fall Out of a Plank

func getLastMoment(n int, left []int, right []int) int {
    return max(slices.Max(append(left, 0)), n - slices.Min(append(right, n)))
}

4.7.1323 - 2023-11-04 10:30:12 +0300 MSK

Last Moment Before All Ants Fall Out of a Plank
func getLastMoment(n int, left []int, right []int) int {
    maxLeft := 0
    for _, val := range left {
        if val > maxLeft {
            maxLeft = val
        }
    }
    minRight := n
    for _, val := range right {
        if val < minRight {
            minRight = val
        }
    }
    return max(maxLeft, n - minRight)
}

4.7.1324 - 2023-11-04 10:29:26 +0300 MSK

Last Moment Before All Ants Fall Out of a Plank
func getLastMoment(n int, left []int, right []int) int {
    maxLeft := 0
    for _, val := range left {
        if val > maxLeft {
            maxLeft = val
        }
    }
    
    minRight := n
    for _, val := range right {
        if val < minRight {
            minRight = val
        }
    }
    return max(maxLeft, n - minRight)
}

4.7.1325 - 2023-11-03 15:20:27 +0300 MSK

Kth Smallest Element in a BST
/**
 * Definition for a binary tree node.
 * type TreeNode struct {
 *     Val int
 *     Left *TreeNode
 *     Right *TreeNode
 * }
 */
func kthSmallest(root *TreeNode, k int) int {
    heap := binaryheap.NewWithIntComparator()
    queue := []*TreeNode{root}

    for length := len(queue); length > 0; length = len(queue) {
        for i := 0; i < length; i++ {
            node := queue[i]
            if node == nil {
                continue
            }
            heap.Push(node.Val)
            queue = append(queue, node.Left, node.Right)
        }
        queue = queue[length:]
    }
    var answer any
    for i := 0; i < k; i++ {
        answer, _ = heap.Pop()
    }
    return answer.(int)
}

4.7.1326 - 2023-11-03 12:40:06 +0300 MSK

Flatten Binary Tree to Linked List
/**
 * Definition for a binary tree node.
 * type TreeNode struct {
 *     Val int
 *     Left *TreeNode
 *     Right *TreeNode
 * }
 */
func flatten(root *TreeNode)  {
    if root == nil {
        return
    }
    right := root.Right
    root.Right = nil
    list := &TreeNode{0, nil, nil}
    listTail := flattenNode(root, list)
    if right != nil {
        flattenNode(right, listTail)
    }
}

func flattenNode(node, listTail *TreeNode) *TreeNode {
    left, right := node.Left, node.Right
    node.Left, node.Right = nil, nil
    listTail.Right = node
    listTail = listTail.Right
    if left != nil {
        listTail = flattenNode(left, listTail)
    }
    if right != nil {
        listTail = flattenNode(right, listTail)
    }
    return listTail
}

4.7.1327 - 2023-11-03 12:14:46 +0300 MSK

Build an Array With Stack Operations
func buildArray(target []int, n int) []string {
    ops := []string{}
    length := len(target)
    matchNext, matchNextVal := 0, target[0]
    for i := 1; i <= n; i++ {
        if i == matchNextVal {
            ops = append(ops, "Push")
            matchNext += 1
            if matchNext == length {
                break
            }
            matchNextVal = target[matchNext]
        } else {
            ops = append(ops, "Push", "Pop")
        }
    }
    return ops
}

4.7.1328 - 2023-11-03 12:13:05 +0300 MSK

Build an Array With Stack Operations
func buildArray(target []int, n int) []string {
    ops := []string{}
    length := len(target)
    matchNext := 0
    for i := 1; i <= n; i++ {
        if matchNext == length {
            break
        }
        ops = append(ops, "Push")
        if i == target[matchNext] {
            matchNext += 1
        } else {
            ops = append(ops, "Pop")
        }
    }
    return ops
}

4.7.1329 - 2023-11-02 14:33:34 +0300 MSK

Sort List

func sortList(head *ListNode) *ListNode {
	if head == nil || head.Next == nil {
		return head
	}
	if head.Next.Next == nil {
		a := head
		b := head.Next
		if a.Val <= b.Val {
			a.Next = b
			b.Next = nil
			return a
		} else {
			b.Next = a
			a.Next = nil
			return b
		}
	}
	slow := head
	fast := head
	for fast != nil && fast.Next != nil {
		slow = slow.Next
		fast = fast.Next.Next
	}
	nextList := slow.Next
	slow.Next = nil
	list1 := sortList(head)
	list2 := sortList(nextList)
	dummy := &ListNode{Val: -1, Next: nil}
	it := dummy
	for list1 != nil && list2 != nil {
		if list1.Val <= list2.Val {
			it.Next = list1
			list1 = list1.Next
		} else {
			it.Next = list2
			list2 = list2.Next
		}
		it = it.Next
	}
	if list1 != nil {
		it.Next = list1
	} else {
		it.Next = list2
	}
	return dummy.Next
}

4.7.1330 - 2023-11-02 13:32:46 +0300 MSK

Count Nodes Equal to Average of Subtree
/**
 * Definition for a binary tree node.
 * type TreeNode struct {
 *     Val int
 *     Left *TreeNode
 *     Right *TreeNode
 * }
 */
func averageOfSubtree(root *TreeNode) int {
    _, _, answer := getAverage(root)
    return answer
}

func getAverage(root *TreeNode) (int, int, int) {
    if root == nil {
        return 0, 0, 0
    }
    sum, count, validNodes := root.Val, 1, 0
    leftSum, leftCount, leftValidNodes := getAverage(root.Left)
    rightSum, rightCount, rightValidNodes := getAverage(root.Right)
    validNodes += leftValidNodes + rightValidNodes
    sum += leftSum + rightSum
    count += leftCount + rightCount
    if sum / count == root.Val {
        validNodes += 1
    }
    return sum, count, validNodes
}

4.7.1331 - 2023-11-01 15:59:19 +0300 MSK

Sum Root to Leaf Numbers
/**
 * Definition for a binary tree node.
 * type TreeNode struct {
 *     Val int
 *     Left *TreeNode
 *     Right *TreeNode
 * }
 */

type queueItem struct {
    node *TreeNode
    sum int
}
func sumNumbers(root *TreeNode) int {
    if root == nil {
        return 0
    }
    queue := []queueItem{queueItem{root, 0}}
    sum := 0
    for length := len(queue); length > 0; length = len(queue) {
        for i := 0; i < length; i++ {
            item := queue[i]
            if item.node == nil {
                continue
            }
            left, right, newVal := item.node.Left, item.node.Right, item.node.Val + item.sum * 10
            if left == nil && right == nil {
                sum += newVal
            } else {
                queue = append(queue, queueItem{left, newVal}, queueItem{right, newVal})
            }
        }
        queue = queue[length:]
    }
    return sum
}

4.7.1332 - 2023-11-01 15:51:19 +0300 MSK

Sum Root to Leaf Numbers
/**
 * Definition for a binary tree node.
 * type TreeNode struct {
 *     Val int
 *     Left *TreeNode
 *     Right *TreeNode
 * }
 */
func sumNumbers(root *TreeNode) int {
    return getSum(root, 0)
}

func getSum(root *TreeNode, parentVal int) int {
    if root == nil {
        return 0
    }
    newVal := root.Val + parentVal * 10
    if root.Left == nil && root.Right == nil {
        return newVal
    }
    return getSum(root.Left, newVal) + getSum(root.Right, newVal)
}

4.7.1333 - 2023-11-01 15:01:54 +0300 MSK

Lowest Common Ancestor of a Binary Tree
/**
 * Definition for a binary tree node.
 * type TreeNode struct {
 *     Val int
 *     Left *TreeNode
 *     Right *TreeNode
 * }
 */
 func lowestCommonAncestor(root, p, q *TreeNode) *TreeNode {
    if root == nil {
		return nil
	}
    if root == p || root == q {
		return root
	}
    left, right := lowestCommonAncestor(root.Left, p, q), lowestCommonAncestor(root.Right, p, q)
    if left != nil && right != nil {
		return root
	}
	if left != nil {
		return left
	}
	return right
}

4.7.1334 - 2023-11-01 15:00:05 +0300 MSK

Lowest Common Ancestor of a Binary Tree
/**
 * Definition for a binary tree node.
 * type TreeNode struct {
 *     Val int
 *     Left *TreeNode
 *     Right *TreeNode
 * }
 */

func lowestCommonAncestor(root, p, q *TreeNode) *TreeNode {
    isAncestorMap := map[int][2]bool{}
    dfs(root, p, q, isAncestorMap)
    isAncestor := func (node *TreeNode) bool {
        if node == nil {
            return false
        }
        hasNodes := isAncestorMap[node.Val]
        return hasNodes[0] && hasNodes[1]
    }

    for {
        left, right := root.Left, root.Right
        if isAncestor(left) {
            root = left
        } else if isAncestor(right) {
            root = right
        } else {
            break
        }
    }
    return root
}

func dfs(root, p, q *TreeNode, isAncestorMap map[int][2]bool) (bool, bool)  {
    if root == nil {
        return false, false
    }
    hasPLeft, hasQLeft := dfs(root.Left, p, q, isAncestorMap)
    hasPRight, hasQRight := dfs(root.Right, p, q, isAncestorMap)
    hasP, hasQ := hasPLeft || hasPRight, hasQLeft || hasQRight
    if root == p {
        hasP = true
    }
    if root == q {
        hasQ = true
    }
    isAncestorMap[root.Val] = [2]bool{hasP, hasQ}
    return hasP, hasQ
}

4.7.1335 - 2023-11-01 12:34:06 +0300 MSK

Find Mode in Binary Search Tree
/**
 * Definition for a binary tree node.
 * type TreeNode struct {
 *     Val int
 *     Left *TreeNode
 *     Right *TreeNode
 * }
 */
func findMode(root *TreeNode) []int {
    if root == nil {
        return []int{}
    }
    counter := map[int]int{}
    queue := []*TreeNode{root}
    for length := len(queue); length > 0; length = len(queue) {
        for i := 0; i < length; i++ {
            node := queue[i]
            if node == nil {
                continue
            }
            left, right, val := node.Left, node.Right, node.Val
            if _, ok := counter[val]; ok {
                counter[val] +=  1
            } else {
                counter[val] = 1
            }
            queue = append(queue, left, right)
        }
        queue = queue[length:]
    }
    maxCount, answer := 0, []int{}
    for key, count := range counter {
        if count < maxCount {
            continue
        }
        if count > maxCount {
            answer = answer[:0]
            maxCount = count
        }
        answer = append(answer, key)
    }
    return answer
}

4.7.1336 - 2023-11-01 12:32:26 +0300 MSK

Find Mode in Binary Search Tree
/**
 * Definition for a binary tree node.
 * type TreeNode struct {
 *     Val int
 *     Left *TreeNode
 *     Right *TreeNode
 * }
 */
func findMode(root *TreeNode) []int {
    if root == nil {
        return []int{}
    }
    counter := map[int]int{}
    queue := []*TreeNode{root}
    for length := len(queue); length > 0; length = len(queue) {
        for i := 0; i < length; i++ {
            node := queue[i]
            if node == nil {
                continue
            }
            if val, ok := counter[node.Val]; ok {
                counter[node.Val] = val + 1
            } else {
                counter[node.Val] = 1
            }
            queue = append(queue, node.Left, node.Right)
        }
        queue = queue[length:]
    }
    maxCount, answer := 0, []int{}
    for key, count := range counter {
        if count < maxCount {
            continue
        }
        if count > maxCount {
            answer = answer[:0]
            maxCount = count
        }
        answer = append(answer, key)
    }
    return answer
}

4.7.1337 - 2023-11-01 12:28:17 +0300 MSK

Find Mode in Binary Search Tree
/**
 * Definition for a binary tree node.
 * type TreeNode struct {
 *     Val int
 *     Left *TreeNode
 *     Right *TreeNode
 * }
 */
func findMode(root *TreeNode) []int {
    if root == nil {
        return []int{}
    }
    counter := map[int]int{}
    dfs(root, counter)
    maxCount, answer := 0, []int{}
    for key, count := range counter {
        if count < maxCount {
            continue
        }
        if count > maxCount {
            answer = answer[:0]
            maxCount = count
        }
        answer = append(answer, key)
    }
    return answer
}

func dfs(root *TreeNode, counter map[int]int) {
    if root == nil {
        return
    }
    if _, ok := counter[root.Val]; ok {
        counter[root.Val] += 1
    } else {
        counter[root.Val] = 1
    }
    dfs(root.Left, counter)
    dfs(root.Right, counter)
}

4.7.1338 - 2023-11-01 12:20:58 +0300 MSK

Find Mode in Binary Search Tree
/**
 * Definition for a binary tree node.
 * type TreeNode struct {
 *     Val int
 *     Left *TreeNode
 *     Right *TreeNode
 * }
 */
func findMode(root *TreeNode) []int {
    if root == nil {
        return []int{}
    }
    counter := map[int]int{}
    queue := []*TreeNode{root}
    for length := len(queue); length > 0; length = len(queue) {
        for i := 0; i < length; i++ {
            node := queue[i]
            if _, ok := counter[node.Val]; ok {
                counter[node.Val] += 1
            } else {
                counter[node.Val] = 1
            }
            if node.Left != nil {
                queue = append(queue, node.Left)
            }
            if node.Right != nil {
                queue = append(queue, node.Right)
            }
        }
        queue = queue[length:]
    }
    maxCount, answer := 0, []int{}
    for key, count := range counter {
        if count < maxCount {
            continue
        }
        if count > maxCount {
            answer = answer[:0]
            maxCount = count
        }
        answer = append(answer, key)
    }
    return answer
}

4.7.1339 - 2023-10-31 19:12:05 +0300 MSK

Validate Binary Search Tree
/**
 * Definition for a binary tree node.
 * type TreeNode struct {
 *     Val int
 *     Left *TreeNode
 *     Right *TreeNode
 * }
 */
type queueItem struct  {
    node *TreeNode
    max *int
    min *int
}

func isValidBST(root *TreeNode) bool {
    queue := []queueItem{queueItem{root, nil, nil}}
    for length := len(queue); length > 0; length = len(queue) {
        for i := 0; i < length; i++ {
            item := queue[i]
            if item.node == nil {
                continue
            }
            node := item.node
            if (item.max != nil && node.Val >= *item.max) || (item.min != nil && node.Val <= *item.min) {
                return false
            }
            queue = append(
                queue, 
                queueItem{node.Left, &node.Val, item.min}, 
                queueItem{node.Right, item.max, &node.Val},
            )
        }
        queue = queue[length:]
    }
    return true
}

4.7.1340 - 2023-10-31 19:11:41 +0300 MSK

Validate Binary Search Tree
/**
 * Definition for a binary tree node.
 * type TreeNode struct {
 *     Val int
 *     Left *TreeNode
 *     Right *TreeNode
 * }
 */
type queueItem struct  {
    node *TreeNode
    max *int
    min *int
}

func isValidBST(root *TreeNode) bool {
    queue := []queueItem{queueItem{root, nil, nil}}
    for length := len(queue); length > 0; length = len(queue) {
        for i := 0; i < length; i++ {
            item := queue[i]
            if item.node == nil {
                continue
            }
            node := item.node
            if (item.max != nil && node.Val >= *item.max) || (item.min != nil && node.Val <= *item.min) {
                return false
            }
            queue = append(
                queue, 
                queueItem{node.Left, &node.Val, item.min}, 
                queueItem{node.Right, item.max, &node.Val},
            )
        }
        queue = queue[length:]
    }
    return true
}

4.7.1341 - 2023-10-31 18:59:17 +0300 MSK

Validate Binary Search Tree
/**
 * Definition for a binary tree node.
 * type TreeNode struct {
 *     Val int
 *     Left *TreeNode
 *     Right *TreeNode
 * }
 */
func isValidBST(root *TreeNode) bool {
    if root == nil {
        return false
    }
    return dfs(root.Left, &root.Val, nil) && dfs(root.Right, nil, &root.Val)
}

func dfs(root *TreeNode, max *int, min *int) bool {
    if root == nil {
        return true
    }
    if (max != nil && root.Val >= *max) || (min != nil && root.Val <= *min) {
        return false
    }
    return dfs(root.Left, &root.Val, min) && dfs(root.Right, max, &root.Val)
}

4.7.1342 - 2023-10-31 18:18:34 +0300 MSK

Maximum Sum Circular Subarray
func max(a, b int) int {
    if a > b {
        return a
    }
    return b
}

func min(a, b int) int {
    if a < b {
        return a
    }
    return b
}

func maxSubarraySumCircular(nums []int) int {
    var (
        max_sum_ending_here = 0
        min_sum_ending_here = 0
        max_sum_so_far = math.MinInt
        min_sum_so_far = math.MaxInt
        total = 0
    )
    for i := 0; i < len(nums); i++ {
        num := nums[i]
        total += num
        max_sum_ending_here += num
        min_sum_ending_here += num
        max_sum_so_far = max(max_sum_so_far, max_sum_ending_here)
        min_sum_so_far = min(min_sum_so_far, min_sum_ending_here)
        max_sum_ending_here = max(max_sum_ending_here, 0)
        min_sum_ending_here = min(min_sum_ending_here, 0)
    }
    if max_sum_so_far < 0 {
        return max_sum_so_far
    }
    return max(max_sum_so_far, total - min_sum_so_far)
}

4.7.1343 - 2023-10-31 18:15:28 +0300 MSK

Maximum Sum Circular Subarray
func max(a, b int) int {
    if a > b {
        return a
    }
    return b
}

func min(a, b int) int {
    if a < b {
        return a
    }
    return b
}

func maxSubarraySumCircular(nums []int) int {
    var (
        max_sum_ending_here = 0
        min_sum_ending_here = 0
        max_sum_so_far = math.MinInt
        min_sum_so_far = math.MaxInt
        total = 0
    )
    for i := 0; i < len(nums); i++ {
        total += nums[i]
        max_sum_ending_here += nums[i]
        min_sum_ending_here += nums[i]
        max_sum_so_far = max(max_sum_so_far, max_sum_ending_here)
        min_sum_so_far = min(min_sum_so_far, min_sum_ending_here)
        max_sum_ending_here = max(max_sum_ending_here, 0)
        min_sum_ending_here = min(min_sum_ending_here, 0)
    }
    if max_sum_so_far < 0 {
        return max_sum_so_far
    }
    return max(max_sum_so_far, total - min_sum_so_far)
}

4.7.1344 - 2023-10-31 18:13:57 +0300 MSK

Maximum Sum Circular Subarray
func max(a, b int) int {
    if a > b {
        return a
    }
    return b
}

func min(a, b int) int {
    if a < b {
        return a
    }
    return b
}

func maxSubarraySumCircular(nums []int) int {
    var max_sum_ending_here int = 0
    var min_sum_ending_here int = 0
    var max_sum_so_far int = math.MinInt
    var min_sum_so_far int = math.MaxInt
    var total = 0
    for i := 0; i < len(nums); i++ {
        total += nums[i]
        max_sum_ending_here += nums[i]
        min_sum_ending_here += nums[i]
        max_sum_so_far = max(max_sum_so_far, max_sum_ending_here)
        min_sum_so_far = min(min_sum_so_far, min_sum_ending_here)
        max_sum_ending_here = max(max_sum_ending_here, 0)
        min_sum_ending_here = min(min_sum_ending_here, 0)
    }
    if max_sum_so_far < 0 {
        return max_sum_so_far
    }
    return max(max_sum_so_far, total - min_sum_so_far)
}

4.7.1345 - 2023-10-31 11:33:38 +0300 MSK

Find The Original Array of Prefix Xor
func findArray(pref []int) []int {
    prev := pref[0]
    for i := 1; i < len(pref); i++ {
        cur := pref[i]
        prev, pref[i] = cur, prev ^ cur 
    }
    return pref
}

4.7.1346 - 2023-10-31 11:32:41 +0300 MSK

Find The Original Array of Prefix Xor
func findArray(pref []int) []int {
    prev := pref[0]
    for i := 1; i < len(pref); i++ {
        prev, pref[i] = pref[i], prev ^ pref[i] 
    }
    return pref
}

4.7.1347 - 2023-10-30 16:28:30 +0300 MSK

Trapping Rain Water
func trap(height []int) int {
    left, right := 0, len(height) - 1
    res := 0
    leftMax, rightMax := 0, 0

    for left < right {
        if height[left] < height[right] {
            if height[left] >= leftMax {
                leftMax = height[left]
            } else {
                res += (leftMax-height[left])
            }
            left++
        } else {
            if height[right] >= rightMax {
                rightMax = height[right]
            } else {
                res += (rightMax-height[right])
            }
            right--
        }
    }

    return res
}

4.7.1348 - 2023-10-30 16:16:38 +0300 MSK

Find First and Last Position of Element in Sorted Array
class Solution:
    def searchRange(self, nums: List[int], target: int) -> List[int]:
        def binary_search(nums, target, left):
            low, high = 0, len(nums) - 1
            index = -1
            while low <= high:
                mid = (low + high) // 2
                if nums[mid] == target:
                    index = mid
                    if left:
                        high = mid - 1
                    else:
                        low = mid + 1
                elif nums[mid] < target:
                    low = mid + 1
                else:
                    high = mid - 1
            return index

        left_index = binary_search(nums, target, left=True)
        right_index = binary_search(nums, target, left=False)

        return [left_index, right_index]

4.7.1349 - 2023-10-30 16:03:18 +0300 MSK

Minimum Genetic Mutation
func minMutation(startGene string, endGene string, bank []string) int {
    if startGene == endGene {
        return 0
    }

    bank = append(bank, startGene)

    isMut := func (gene1 string, gene2 string) bool {
        foundDiff := false
        for i := 0; i < len(gene1); i++ {
            if gene1[i] == gene2[i] {
                continue
            }
            if foundDiff {
                return false
            }
            foundDiff = true
        } 
        return foundDiff
    }

    graph := map[string][]string{}

    for i, gene1 := range bank {
        for _, gene2 := range bank[i+1:] {
            if !isMut(gene1, gene2) {
                continue
            }
            if _, ok := graph[gene1]; !ok {
                graph[gene1] = []string{}
            }
            if _, ok := graph[gene2]; !ok {
                graph[gene2] = []string{}
            }
            graph[gene1] = append(graph[gene1], gene2)
            graph[gene2] = append(graph[gene2], gene1)
        }
    }

    queue, ok := graph[endGene]
    if !ok {
        return -1
    }
    delete(graph, endGene)
    num := 1
    for length := len(queue); length > 0; length = len(queue) {
        for i := 0; i < length; i++ {
            gene := queue[i]
            muts, ok := graph[gene]
            if !ok {
                continue
            }
            if gene == startGene {
                return num 
            }
            delete(graph, gene)
            queue = append(queue, muts...)
        }
        num += 1
        queue = queue[length:]
    }

    return -1
}

4.7.1350 - 2023-10-30 15:58:41 +0300 MSK

Minimum Genetic Mutation
func minMutation(startGene string, endGene string, bank []string) int {
    if startGene == endGene {
        return 0
    }

    bank = append(bank, startGene)

    isMut := func (gene1 string, gene2 string) bool {
        foundDiff := false
        for i := 0; i < len(gene1); i++ {
            if gene1[i] == gene2[i] {
                continue
            }
            if foundDiff {
                return false
            }
            foundDiff = true
        } 
        return foundDiff
    }

    graph := map[string][]string{}

    for i, gene1 := range bank {
        for _, gene2 := range bank[i+1:] {
            if !isMut(gene1, gene2) {
                continue
            }
            if _, ok := graph[gene1]; !ok {
                graph[gene1] = []string{}
            }
            if _, ok := graph[gene2]; !ok {
                graph[gene2] = []string{}
            }
            graph[gene1] = append(graph[gene1], gene2)
            graph[gene2] = append(graph[gene2], gene1)
        }
    }

    queue, ok := graph[endGene]
    if !ok {
        return -1
    }
    visited := map[string]struct{}{endGene: struct{}{}}
    num := 1
    for length := len(queue); length > 0; length = len(queue) {
        for i := 0; i < length; i++ {
            gene := queue[i]
            if _, ok := visited[gene]; ok {
                continue
            }
            if gene == startGene {
                return num 
            }
            visited[gene] = struct{}{}
            queue = append(queue, graph[gene]...)
        }
        num += 1
        queue = queue[length:]
    }

    return -1
}

4.7.1351 - 2023-10-30 14:32:47 +0300 MSK

Binary Tree Zigzag Level Order Traversal
/**
 * Definition for a binary tree node.
 * type TreeNode struct {
 *     Val int
 *     Left *TreeNode
 *     Right *TreeNode
 * }
 */
func zigzagLevelOrder(root *TreeNode) [][]int {
    if root == nil {
        return [][]int{}
    }

    queue, answer := []*TreeNode{root}, [][]int{}
    ltr := true

    for length := len(queue); length != 0; length = len(queue) {
        answerRow := []int{}
        for i := 0; i < length; i++ {
            node := queue[i]
            if node.Left != nil {
                queue = append(queue, node.Left)
            }
            if node.Right != nil {
                queue = append(queue, node.Right)
            }
            answerRow = append(answerRow, node.Val)
        }
        if !ltr {
            slices.Reverse(answerRow)
        }
        queue = queue[length:]
        ltr = !ltr
        answer = append(answer, answerRow)
    }

    return answer
}

4.7.1352 - 2023-10-30 14:31:36 +0300 MSK

Binary Tree Zigzag Level Order Traversal
/**
 * Definition for a binary tree node.
 * type TreeNode struct {
 *     Val int
 *     Left *TreeNode
 *     Right *TreeNode
 * }
 */
func zigzagLevelOrder(root *TreeNode) [][]int {
    if root == nil {
        return [][]int{}
    }

    queue, answer := []*TreeNode{root}, [][]int{}
    ltr := true

    for length := len(queue); length != 0; length = len(queue) {
        answerRow := []int{}
        for i := 0; i < length; i++ {
            node := queue[i]
            if node.Left != nil {
                queue = append(queue, node.Left)
            }
            if node.Right != nil {
                queue = append(queue, node.Right)
            }
            if ltr {
                answerRow = append(answerRow, node.Val)
            } else {
                answerRow = append([]int{node.Val}, answerRow...)
            }
        }
        queue = queue[length:]
        ltr = !ltr
        answer = append(answer, answerRow)
    }

    return answer
}

4.7.1353 - 2023-10-30 14:14:48 +0300 MSK

Binary Tree Zigzag Level Order Traversal
/**
 * Definition for a binary tree node.
 * type TreeNode struct {
 *     Val int
 *     Left *TreeNode
 *     Right *TreeNode
 * }
 */
func zigzagLevelOrder(root *TreeNode) [][]int {
    if root == nil {
        return [][]int{}
    }

    queue, answer := []*TreeNode{root}, [][]int{}
    leftToRight := true

    for length := len(queue); length != 0; length = len(queue) {
        answerRow := []int{}

        for i := 0; i < length; i++ {
            node := queue[0]
            queue = queue[1:]

            answerRow = append(answerRow, node.Val)
            if left := node.Left; left != nil {
                queue = append(queue, left)
            }
            if right := node.Right; right != nil {
                queue = append(queue, right)
            }
        }
        if !leftToRight {
            slices.Reverse(answerRow)
        }
        leftToRight = !leftToRight
        answer = append(answer, answerRow)
    }

    return answer
}

4.7.1354 - 2023-10-30 13:59:23 +0300 MSK

Binary Tree Level Order Traversal
/**
 * Definition for a binary tree node.
 * type TreeNode struct {
 *     Val int
 *     Left *TreeNode
 *     Right *TreeNode
 * }
 */
func levelOrder(root *TreeNode) [][]int {
    queue, answer := []*TreeNode{root}, [][]int{}

    for length := len(queue); length != 0; length = len(queue) {
        answerRow := []int{}
        for i := 0; i < length; i++ {
            node := queue[0]
            queue = queue[1:]
            if node == nil {
                continue
            }
            answerRow = append(answerRow, node.Val)
            queue = append(queue, node.Left, node.Right)
        }
        if len(answerRow) != 0 {
            answer = append(answer, answerRow)
        }
    }

    return answer
}

4.7.1355 - 2023-10-30 13:51:15 +0300 MSK

Binary Tree Level Order Traversal
/**
 * Definition for a binary tree node.
 * type TreeNode struct {
 *     Val int
 *     Left *TreeNode
 *     Right *TreeNode
 * }
 */
func levelOrder(root *TreeNode) [][]int {
    if root == nil {
        return [][]int{}
    }

    stack, answer := []*TreeNode{root}, [][]int{}

    for length := len(stack); length != 0; length = len(stack) {
        answerRow := []int{}
        for i := 0; i < length; i++ {
            node := stack[0]
            answerRow = append(answerRow, node.Val)
            stack = stack[1:]
            if left := node.Left; left != nil {
                stack = append(stack, node.Left)
            }
            if right := node.Right; right != nil {
                stack = append(stack, node.Right)
            }
        }
        answer = append(answer, answerRow)
    }

    return answer
}

4.7.1356 - 2023-10-30 13:39:35 +0300 MSK

Binary Tree Right Side View
/**
 * Definition for a binary tree node.
 * type TreeNode struct {
 *     Val int
 *     Left *TreeNode
 *     Right *TreeNode
 * }
 */
func rightSideView(root *TreeNode) []int {
    if root == nil {
        return []int{}
    }

    queue, answer := []*TreeNode{root}, []int{}

    for length := len(queue); length != 0; length = len(queue) {
        for i := 0; i < length; i++ {
            node := queue[0]
            queue = queue[1:]
            if i == length - 1 {
                answer = append(answer, node.Val)
            }
            if left := node.Left; left != nil {
                queue = append(queue, left)
            }
            if right := node.Right; right != nil {
                queue = append(queue, right)
            }
        }
    }

    return answer
} 

4.7.1357 - 2023-10-30 13:33:19 +0300 MSK

Average of Levels in Binary Tree
/**
 * Definition for a binary tree node.
 * type TreeNode struct {
 *     Val int
 *     Left *TreeNode
 *     Right *TreeNode
 * }
 */
func averageOfLevels(root *TreeNode) []float64 {
    if root == nil {
        return []float64{}
    }
    queue, answer := []*TreeNode{root}, []float64{}

    for length := len(queue); length != 0; length = len(queue) {
        av := 0
        for i := 0; i < length; i++ {
            node := queue[0]
            queue = queue[1:]
            av += node.Val
            if left := node.Left; left != nil {
                queue = append(queue, left)
            }
            if right := node.Right; right != nil {
                queue = append(queue, right)
            }
        }
        answer = append(answer, float64(av) / float64(length))
    }

    return answer
}

4.7.1358 - 2023-10-30 13:26:37 +0300 MSK

Average of Levels in Binary Tree
/**
 * Definition for a binary tree node.
 * type TreeNode struct {
 *     Val int
 *     Left *TreeNode
 *     Right *TreeNode
 * }
 */
func averageOfLevels(root *TreeNode) []float64 {
    if root == nil {
        return []float64{}
    }
    qCur, qNext, answer := []*TreeNode{root}, []*TreeNode{}, []float64{}

    for len(qCur) != 0 {
        av := 0
        for _, node := range qCur {
            av += node.Val
            if left := node.Left; left != nil {
                qNext = append(qNext, left)
            }
            if right := node.Right; right != nil {
                qNext = append(qNext, right)
            }
        }
        answer = append(answer, float64(av) / float64(len(qCur)))
        qCur = qCur[:0]
        qCur, qNext = qNext, qCur
    }

    return answer
}

4.7.1359 - 2023-10-30 13:17:08 +0300 MSK

Binary Tree Right Side View
/**
 * Definition for a binary tree node.
 * type TreeNode struct {
 *     Val int
 *     Left *TreeNode
 *     Right *TreeNode
 * }
 */
func rightSideView(root *TreeNode) []int {
    if root == nil {
        return []int{}
    }

    q_cur, q_next, answer := []*TreeNode{root}, []*TreeNode{}, []int{}

    for len(q_cur) != 0 {
        for _, node := range q_cur {
            if left := node.Left; left != nil {
                q_next = append(q_next, left)
            }
            if right := node.Right; right != nil {
                q_next = append(q_next, right)
            }
        }

        answer = append(answer, q_cur[len(q_cur) - 1].Val)
        q_cur = q_cur[:0]
        q_cur, q_next = q_next, q_cur
    }

    return answer
} 

4.7.1360 - 2023-10-30 13:16:47 +0300 MSK

Binary Tree Right Side View
/**
 * Definition for a binary tree node.
 * type TreeNode struct {
 *     Val int
 *     Left *TreeNode
 *     Right *TreeNode
 * }
 */
func rightSideView(root *TreeNode) []int {
    if root == nil {
        return []int{}
    }

    q_cur, q_next, answer := []*TreeNode{root}, []*TreeNode{}, []int{}

    for len(q_cur) != 0 {
        var last int
        for _, node := range q_cur {
            if left := node.Left; left != nil {
                q_next = append(q_next, left)
            }
            if right := node.Right; right != nil {
                q_next = append(q_next, right)
            }
            last = node.Val
        }

        answer = append(answer, last)
        q_cur = q_cur[:0]
        q_cur, q_next = q_next, q_cur
    }

    return answer
} 

4.7.1361 - 2023-10-30 13:16:38 +0300 MSK

Binary Tree Right Side View
/**
 * Definition for a binary tree node.
 * type TreeNode struct {
 *     Val int
 *     Left *TreeNode
 *     Right *TreeNode
 * }
 */
func rightSideView(root *TreeNode) []int {
    if root == nil {
        return []int{}
    }

    q_cur, q_next, answer := []*TreeNode{root}, []*TreeNode{}, []int{}

    for len(q_cur) != 0 {
        var last int
        for _, node := range q_cur {
            if left := node.Left; left != nil {
                q_next = append(q_next, left)
            }
            if right := node.Right; right != nil {
                q_next = append(q_next, right)
            }
            last = node.Val
        }

        answer = append(answer, last)
        q_cur = q_cur[:0]
        q_cur, q_next = q_next, q_cur
    }

    return answer
} 

4.7.1362 - 2023-10-30 13:13:00 +0300 MSK

Binary Tree Right Side View
/**
 * Definition for a binary tree node.
 * type TreeNode struct {
 *     Val int
 *     Left *TreeNode
 *     Right *TreeNode
 * }
 */
func rightSideView(root *TreeNode) []int {
    if root == nil {
        return []int{}
    }

    q_cur, q_next, answer := []*TreeNode{root}, []*TreeNode{}, []int{}

    for length := len(q_cur); length > 0; length = len(q_cur) {
        for _, node := range q_cur {
            if left := node.Left; left != nil {
                q_next = append(q_next, left)
            }
            if right := node.Right; right != nil {
                q_next = append(q_next, right)
            }
        }

        answer = append(answer, q_cur[length - 1].Val)
        q_cur = q_cur[:0]
        q_cur, q_next = q_next, q_cur
    }

    return answer
} 

4.7.1363 - 2023-10-30 12:17:05 +0300 MSK

Binary Tree Right Side View
# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def rightSideView(self, root: Optional[TreeNode]) -> List[int]:
        if not root:
            return []
        
        q_cur, q_next, answer = deque(), deque(), []
        q_cur.append(root)

        while q_cur:
            last_val = None
            
            while q_cur:
                node = q_cur.popleft()
                last_val = node.val
                if node.left:
                    q_next.append(node.left)
                if node.right:
                    q_next.append(node.right)
            
            q_cur, q_next = q_next, q_cur
            answer.append(last_val)
    
        return answer

4.7.1364 - 2023-10-30 12:10:35 +0300 MSK

Binary Tree Right Side View
# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def rightSideView(self, root: Optional[TreeNode]) -> List[int]:
        if not root:
            return []
        cur, nxt = [root], []
        answer = []
        
        while cur:
            last_node = cur.pop()
            if last_node.right:
                nxt.append(last_node.right)
            if last_node.left:
                nxt.append(last_node.left)
            answer.append(last_node.val)
            
            while cur:
                node = cur.pop()
                if node.right:
                    nxt.append(node.right)
                if node.left:
                    nxt.append(node.left)
            
            cur.clear()
            nxt.reverse()
            cur, nxt = nxt, cur

        return answer

4.7.1365 - 2023-10-30 10:51:12 +0300 MSK

Sort Integers by The Number of 1 Bits
class Solution:
    def sortByBits(self, arr: List[int]) -> List[int]:
        return tuple(num for num in sorted(arr, key=lambda num: (num.bit_count(), num)))

4.7.1366 - 2023-10-29 19:36:33 +0300 MSK

Poor Pigs
class Solution:
    def poorPigs(self, buckets: int, a: int, b: int) -> int:
        pigs = 0
        while (b / a + 1) ** pigs < buckets:
            pigs += 1

        return pigs 

4.7.1367 - 2023-10-28 17:51:04 +0300 MSK

Count Vowels Permutation
class Solution:
    def countVowelPermutation(self, n: int) -> int:
        MOD = 10**9 + 7
        
        a, e, i, o, u = 1, 1, 1, 1, 1
        
        for _ in range(1, n):
            a_next = e
            e_next = (a + i) % MOD
            i_next = (a + e + o + u) % MOD
            o_next = (i + u) % MOD
            u_next = a
            
            a, e, i, o, u = a_next, e_next, i_next, o_next, u_next
        
        return (a + e + i + o + u) % MOD

4.7.1368 - 2023-10-27 17:47:50 +0300 MSK

Longest Palindromic Substring
class Solution:
    def longestPalindrome(self, s: str) -> str:
        n = len(s)
        dp = [[False] * n for _ in range(n)]
        ans = [0, 0]
        
        for i in range(n):
            dp[i][i] = True
        
        for i in range(n - 1):
            if s[i] == s[i + 1]:
                dp[i][i + 1] = True
                ans = [i, i + 1]

        for diff in range(2, n):
            for i in range(n - diff):
                j = i + diff
                if s[i] == s[j] and dp[i + 1][j - 1]:
                    dp[i][j] = True
                    ans = [i, j]

        i, j = ans
        return s[i:j + 1]

4.7.1369 - 2023-10-26 23:07:22 +0300 MSK

Binary Trees With Factors
MOD = 10**9 + 7

class Solution:
    def numFactoredBinaryTrees(self, arr: List[int]) -> int:
        arr.sort()
        s = set(arr)
        dp = {x: 1 for x in arr}
        
        for i in arr:
            for j in arr:
                if j > i**0.5:
                    break
                if i % j == 0 and i // j in s:
                    if i // j == j:
                        dp[i] += dp[j] * dp[j]
                    else:
                        dp[i] += dp[j] * dp[i // j] * 2
                    dp[i] %= MOD
        
        return sum(dp.values()) % MOD

4.7.1370 - 2023-10-25 13:37:39 +0300 MSK

Design Add and Search Words Data Structure
class TrieNode:
    def __init__(self):
        self.children = {}
        self.is_word = False

class WordDictionary:

    def __init__(self):
        self.root = TrieNode()

    def addWord(self, word: str) -> None:
        cur = self.root
        for char in word:
            cur = cur.children.setdefault(char, TrieNode())
        cur.is_word = True

    def search(self, word: str) -> bool:
        cur, nxt = [self.root], []
        
        for char in word:
            if not cur:
                return False

            if char == ".":
                for node in cur:
                    nxt.extend(node.children.values())
            else:
                for node in cur:
                    if char in node.children:
                        nxt.append(node.children[char]) 
                
            cur.clear()
            cur, nxt = nxt, cur

        return any(node.is_word for node in cur)
            



# Your WordDictionary object will be instantiated and called as such:
# obj = WordDictionary()
# obj.addWord(word)
# param_2 = obj.search(word)

4.7.1371 - 2023-10-25 11:31:06 +0300 MSK

K-th Symbol in Grammar
class Solution:
    def kthGrammar(self, n: int, k: int) -> int:

        def get(row: int, column: int) -> int:
            if column == 0 or column == 1:
                return column
            
            prev_row_length = 2 ** (row - 1)
            if column >= prev_row_length:
                return 1 ^ get(row - 1, column - prev_row_length)
            return get(row - 1, column)

        return get(n - 1, k - 1)

        # 0
        # 0 1
        # 0 1 1 0
        # 0 1 1 0 1 0 0 1
        # 0 1 1 0 1 0 0 1

4.7.1372 - 2023-10-24 14:55:16 +0300 MSK

Find Largest Value in Each Tree Row
# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def largestValues(self, root: Optional[TreeNode]) -> List[int]:
        if not root:
            return []

        largest = []
        cur, nxt = [root], []
        cur_val = None
        while cur or nxt:
            while cur:
                node = cur.pop()
                if cur_val is None or node.val > cur_val:
                    cur_val = node.val
                if node.left:
                    nxt.append(node.left)
                if node.right:
                    nxt.append(node.right)
            largest.append(cur_val)
            cur.clear()
            cur_val = None
            cur, nxt = nxt, cur
        return largest

4.7.1373 - 2023-10-23 12:26:07 +0300 MSK

Power of Four
class Solution:
    def isPowerOfFour(self, n: int) -> bool:
        # Check if the number is greater than zero and is a power of two
        if n > 0 and (n & (n - 1)) == 0:
            # Check if the number is of the form 4^x
            return n & 0x55555555 == n
        else:
            return False

4.7.1374 - 2023-10-22 13:57:47 +0300 MSK

Maximum Score of a Good Subarray
class Solution:
    def maximumScore(self, nums: List[int], k: int) -> int:
        n = len(nums)
        left = k
        right = k
        ans = nums[k]
        curr_min = nums[k]
        
        while left > 0 or right < n - 1:
            if (nums[left - 1] if left else 0) < (nums[right + 1] if right < n - 1 else 0):
                right += 1
                curr_min = min(curr_min, nums[right])
            else:
                left -= 1
                curr_min = min(curr_min, nums[left])

            ans = max(ans, curr_min * (right - left + 1))
        
        return ans

4.7.1375 - 2023-10-21 14:20:53 +0300 MSK

Constrained Subsequence Sum
import heapq

class Solution:
    def constrainedSubsetSum(self, nums: List[int], k: int) -> int:
        heap = [(-nums[0], 0)]
        ans = nums[0]
        
        for i in range(1, len(nums)):
            while i - heap[0][1] > k:
                heapq.heappop(heap)

            curr = max(0, -heap[0][0]) + nums[i]
            ans = max(ans, curr)
            heapq.heappush(heap, (-curr, i))

        return ans

4.7.1376 - 2023-10-20 16:11:39 +0300 MSK

Flatten Nested List Iterator
# """
# This is the interface that allows for creating nested lists.
# You should not implement it, or speculate about its implementation
# """
#class NestedInteger:
#    def isInteger(self) -> bool:
#        """
#        @return True if this NestedInteger holds a single integer, rather than a nested list.
#        """
#
#    def getInteger(self) -> int:
#        """
#        @return the single integer that this NestedInteger holds, if it holds a single integer
#        Return None if this NestedInteger holds a nested list
#        """
#
#    def getList(self) -> [NestedInteger]:
#        """
#        @return the nested list that this NestedInteger holds, if it holds a nested list
#        Return None if this NestedInteger holds a single integer
#        """

class NestedIterator:
    def __init__(self, nestedList: [NestedInteger]):
        self.get_next = self.get_next_gen(nestedList)
        self.next_val = next(self.get_next, None)

    def get_next_gen(self, nestedList: List[NestedInteger]) -> Generator[None, None, int]:
        for ni in nestedList:
            if ni.isInteger():
                yield ni.getInteger()
            else:
                yield from self.get_next_gen(ni.getList())

    def next(self) -> int: 
        answer, self.next_val = self.next_val, next(self.get_next, None)
        return answer
    
    def hasNext(self) -> bool:
        return self.next_val is not None

# Your NestedIterator object will be instantiated and called as such:
# i, v = NestedIterator(nestedList), []
# while i.hasNext(): v.append(i.next())

4.7.1377 - 2023-10-20 16:06:36 +0300 MSK

Flatten Nested List Iterator
# """
# This is the interface that allows for creating nested lists.
# You should not implement it, or speculate about its implementation
# """
#class NestedInteger:
#    def isInteger(self) -> bool:
#        """
#        @return True if this NestedInteger holds a single integer, rather than a nested list.
#        """
#
#    def getInteger(self) -> int:
#        """
#        @return the single integer that this NestedInteger holds, if it holds a single integer
#        Return None if this NestedInteger holds a nested list
#        """
#
#    def getList(self) -> [NestedInteger]:
#        """
#        @return the nested list that this NestedInteger holds, if it holds a nested list
#        Return None if this NestedInteger holds a single integer
#        """

class NestedIterator:
    def __init__(self, nestedList: [NestedInteger]):
        self.list = []
        self.flatten(self.list, nestedList)
        self.cur = 0
        self.length = len(self.list)

    def flatten(self, flatList: List[int], nestedList: List[NestedInteger]):
        for ni in nestedList:
            if ni.isInteger():
                flatList.append(ni.getInteger())
            else:
                self.flatten(flatList, ni.getList())

    def next(self) -> int: 
        answer = self.list[self.cur]
        self.cur += 1
        return answer
    
    def hasNext(self) -> bool:
        return self.cur < self.length

# Your NestedIterator object will be instantiated and called as such:
# i, v = NestedIterator(nestedList), []
# while i.hasNext(): v.append(i.next())

4.7.1378 - 2023-10-19 17:09:46 +0300 MSK

Backspace String Compare
class Solution:
    def backspaceCompare(self, s: str, t: str) -> bool:
        i1, i2 = len(s) - 1, len(t) - 1
        skip1, skip2 = 0, 0

        while i1 >= 0 or i2 >= 0:
            char1, char2 = s[i1] if i1 >= 0 else "", t[i2] if i2 >= 0 else ""
            if char1 == "#":
                i1 -= 1
                skip1 += 1
            elif char2 == "#":
                i2 -= 1
                skip2 += 1
            elif skip1 > 0:
                i1 -= 1
                skip1 -= 1
            elif skip2 > 0:
                i2 -= 1
                skip2 -= 1
            elif char1 != char2:
                return False
            else:
                i1 -= 1
                i2 -= 1
        
        return True 

4.7.1379 - 2023-10-18 19:38:53 +0300 MSK

Parallel Courses III
class Solution:
    def minimumTime(self, n: int, relations: List[List[int]], time: List[int]) -> int:
        graph = defaultdict(list)
        indegree = [0] * n
        
        for (x, y) in relations:
            graph[x - 1].append(y - 1)
            indegree[y - 1] += 1
        
        queue = deque()
        max_time = [0] * n
        for node in range(n):
            if indegree[node] == 0:
                queue.append(node)
                max_time[node] = time[node]

        while queue:
            node = queue.popleft()
            for neighbor in graph[node]:
                max_time[neighbor] = max(max_time[neighbor], max_time[node] + time[neighbor])
                indegree[neighbor] -= 1
                if indegree[neighbor] == 0:
                    queue.append(neighbor)

        return max(max_time)

4.7.1380 - 2023-10-17 18:45:21 +0300 MSK

Validate Binary Tree Nodes
class Solution:
    def validateBinaryTreeNodes(self, n: int, leftChild: List[int], rightChild: List[int]) -> bool:
        parents = [-1] * n

        for i in range(n):
            left, right = leftChild[i], rightChild[i] 
            left_valid, right_valid = left != -1, right != -1
            if (left_valid and parents[left] != -1) or (
                right_valid and parents[right] != -1
            ):
                return False
            if left_valid:
                parents[left] = i
            if right_valid:
                parents[right] = i

            parent = parents[i]
            if parent != -1 and (parent == left or parent == right):
                return False

        root = None
        for i, node in enumerate(parents):
            if node == -1 and root is not None:
                return False
            if node == -1:
                root = i

        if root is None:
            return False

        to_visit = [root]
        visited = set()

        while to_visit:
            node = to_visit.pop()
            if node in visited:
                return False
            visited.add(node)
            left, right = leftChild[node], rightChild[node]
            if left != -1:
                to_visit.append(left)
            if right != -1:
                to_visit.append(right)

        return len(visited) == n 
        

4.7.1381 - 2023-10-16 20:32:07 +0300 MSK

Pascal’s Triangle II
class Solution:
    def getRow(self, rowIndex: int) -> List[int]:
        cur, prev = [], [1]
        row = 0

        while row < rowIndex:
            cur.append(1)
            for i in range(1, len(prev)):
                cur.append(prev[i] + prev[i-1])
            cur.append(1)
            prev.clear()
            cur, prev = prev, cur
            row += 1
        
        return prev 

4.7.1382 - 2023-10-15 13:05:28 +0300 MSK

Number of Ways to Stay in the Same Place After Some Steps
class Solution:
    def numWays(self, steps: int, arrLen: int) -> int:
        @cache
        def dp(curr, remain):
            if remain == 0:
                if curr == 0:
                    return 1
                
                return 0
            
            ans = dp(curr, remain - 1)
            if curr > 0:
                ans = (ans + dp(curr - 1, remain - 1)) % MOD
            
            if curr < arrLen - 1:
                ans = (ans + dp(curr + 1, remain - 1)) % MOD
                
            return ans
        
        MOD = 10 ** 9 + 7
        return dp(0, steps)

4.7.1383 - 2023-10-14 19:53:26 +0300 MSK

Painting the Walls
class Solution:
    def paintWalls(self, cost: List[int], time: List[int]) -> int:
        @cache
        def dp(i, remain):
            if remain <= 0:
                return 0
            if i == n:
                return inf
            
            paint = cost[i] + dp(i + 1, remain - 1 - time[i])
            dont_paint = dp(i + 1, remain)
            return min(paint, dont_paint)
    
        n = len(cost)
        return dp(0, n)

4.7.1384 - 2023-10-14 10:14:40 +0300 MSK

Min Cost Climbing Stairs
class Solution:
    def minCostClimbingStairs(self, cost):
        n = len(cost)
        dp = [0] * n
        dp[0] = cost[0]
        dp[1] = cost[1]
        
        for i in range(2, n):
            dp[i] = cost[i] + min(dp[i-1], dp[i-2])
        
        return min(dp[n-1], dp[n-2])

4.7.1385 - 2023-10-12 12:09:45 +0300 MSK

Find in Mountain Array
class Solution:
    def findInMountainArray(self, target: int, mountain_arr: 'MountainArray') -> int:
        # Save the length of the mountain array
        length = mountain_arr.length()

        # 1. Find the index of the peak element
        low = 1
        high = length - 2
        while low != high:
            test_index = (low + high) // 2
            if mountain_arr.get(test_index) < mountain_arr.get(test_index + 1):
                low = test_index + 1
            else:
                high = test_index
        peak_index = low

        # 2. Search in the strictly increasing part of the array
        low = 0
        high = peak_index
        while low != high:
            test_index = (low + high) // 2
            if mountain_arr.get(test_index) < target:
                low = test_index + 1
            else:
                high = test_index    
        # Check if the target is present in the strictly increasing part
        if mountain_arr.get(low) == target:
            return low
        
        # 3. Otherwise, search in the strictly decreasing part
        low = peak_index + 1
        high = length - 1
        while low != high:
            test_index = (low + high) // 2
            if mountain_arr.get(test_index) > target:
                low = test_index + 1
            else:
                high = test_index
        # Check if the target is present in the strictly decreasing part
        if mountain_arr.get(low) == target:
            return low
        
        # Target is not present in the mountain array
        return -1

4.7.1386 - 2023-10-11 16:06:35 +0300 MSK

Number of Flowers in Full Bloom
class Solution:
    def fullBloomFlowers(self, flowers: List[List[int]], people: List[int]) -> List[int]:
        flowers.sort()
        sorted_people = sorted(people)
        dic = {}
        heap = []
        
        i = 0
        for person in sorted_people:
            while i < len(flowers) and flowers[i][0] <= person:
                heapq.heappush(heap, flowers[i][1])
                i += 1
            
            while heap and heap[0] < person:
                heapq.heappop(heap)
            
            dic[person] = len(heap)

        return [dic[x] for x in people]

4.7.1387 - 2023-10-10 08:23:28 +0300 MSK

Minimum Number of Operations to Make Array Continuous
class Solution:
    def minOperations(self, nums: List[int]) -> int:
        n = len(nums)
        ans = n
        new_nums = sorted(set(nums))
        
        for i in range(len(new_nums)):
            left = new_nums[i]
            right = left + n - 1
            j = bisect_right(new_nums, right)
            count = j - i
            ans = min(ans, n - count)

        return ans

4.7.1388 - 2023-10-09 14:15:25 +0300 MSK

Find First and Last Position of Element in Sorted Array
class Solution:
    def searchRange(self, nums: List[int], target: int) -> List[int]:
        def binary_search(nums, target, left):
            low, high = 0, len(nums) - 1
            index = -1
            while low <= high:
                mid = (low + high) // 2
                if nums[mid] == target:
                    index = mid
                    if left:
                        high = mid - 1
                    else:
                        low = mid + 1
                elif nums[mid] < target:
                    low = mid + 1
                else:
                    high = mid - 1
            return index

        left_index = binary_search(nums, target, left=True)
        right_index = binary_search(nums, target, left=False)

        return [left_index, right_index]

4.7.1389 - 2023-10-08 10:39:44 +0300 MSK

Max Dot Product of Two Subsequences
class Solution:
    def maxDotProduct(self, nums1: List[int], nums2: List[int]) -> int:
        @cache
        def dp(i, j):
            if i == len(nums1) or j == len(nums2):
                return 0
            
            use = nums1[i] * nums2[j] + dp(i + 1, j + 1)
            return max(use, dp(i + 1, j), dp(i, j + 1))
            
        if max(nums1) < 0 and min(nums2) > 0:
            return max(nums1) * min(nums2)
        
        if min(nums1) > 0 and max(nums2) < 0:
            return min(nums1) * max(nums2)
        
        return dp(0, 0)

4.7.1390 - 2023-10-07 19:48:10 +0300 MSK

Build Array Where You Can Find The Maximum Exactly K Comparisons
class Solution:
    def numOfArrays(self, n: int, m: int, k: int) -> int:
        @cache
        def dp(i, max_so_far, remain):
            if i == n:
                if remain == 0:
                    return 1
                
                return 0
            
            ans = (max_so_far * dp(i + 1, max_so_far, remain)) % MOD
            for num in range(max_so_far + 1, m + 1):
                ans = (ans + dp(i + 1, num, remain - 1)) % MOD
                
            return ans
        
        MOD = 10 ** 9 + 7
        return dp(0, 0, k)

4.7.1391 - 2023-10-06 12:24:39 +0300 MSK

Integer Break
class Solution:
    def integerBreak(self, n: int) -> int:
        if n < 4:
            return n - 1
        
        @cache
        def dp(num: int) -> int:
            if num <= 3:
                return num
            ans = num
            for i in range(2, num):
                ans = max(ans, i * dp(num - i))
            return ans

        return dp(n)

4.7.1392 - 2023-10-06 12:24:09 +0300 MSK

Integer Break
class Solution:
    def integerBreak(self, n: int) -> int:
        @cache
        def dp(num: int) -> int:
            if num <= 3:
                return num
            ans = num
            for i in range(2, num):
                ans = max(ans, i * dp(num - i))
            return ans

        return dp(n) if n > 3 else n - 1

4.7.1393 - 2023-10-05 09:46:37 +0300 MSK

Majority Element II
class Solution:
    def majorityElement(self, nums: List[int]) -> List[int]:
        nums.sort()
        threshold = len(nums) // 3
        cur_num, cur_count = nums[0], 1
        answer = []
        for num in nums[1:]:
            if num == cur_num:
                cur_count += 1
                continue
            if cur_count > threshold:
                answer.append(cur_num)
            cur_num, cur_count = num, 1
        if cur_count > threshold:
            answer.append(cur_num)
        return answer

4.7.1394 - 2023-10-04 09:00:01 +0300 MSK

Design HashMap
class ListNode:
    def __init__(self, key, value):
        self.key = key
        self.value = value
        self.next = None

class MyHashMap:

    def __init__(self):
        self.size = 1000
        self.table = [None] * self.size

    def _index(self, key: int) -> int:
        return key % self.size

    def put(self, key: int, value: int) -> None:
        idx = self._index(key)
        if not self.table[idx]:
            self.table[idx] = ListNode(key, value)
            return
        current = self.table[idx]
        while current:
            if current.key == key:
                current.value = value
                return
            if not current.next:
                current.next = ListNode(key, value)
                return
            current = current.next

    def get(self, key: int) -> int:
        idx = self._index(key)
        current = self.table[idx]
        while current:
            if current.key == key:
                return current.value
            current = current.next
        return -1

    def remove(self, key: int) -> None:
        idx = self._index(key)
        current = self.table[idx]
        if not current:
            return
        if current.key == key:
            self.table[idx] = current.next
            return
        while current.next:
            if current.next.key == key:
                current.next = current.next.next
                return
            current = current.next


# Your MyHashMap object will be instantiated and called as such:
# obj = MyHashMap()
# obj.put(key,value)
# param_2 = obj.get(key)
# obj.remove(key)

4.7.1395 - 2023-10-04 08:57:26 +0300 MSK

Design HashMap
class MyHashMap:
    def __init__(self):
        self.data = [None] * 1000001

    def put(self, key: int, val: int) -> None:
        self.data[key] = val
        
    def get(self, key: int) -> int:
        val = self.data[key]
        return -1 if val is None else val

    def remove(self, key: int) -> None:
        self.data[key] = None
        


# Your MyHashMap object will be instantiated and called as such:
# obj = MyHashMap()
# obj.put(key,value)
# param_2 = obj.get(key)
# obj.remove(key)

4.7.1396 - 2023-10-03 09:14:03 +0300 MSK

Number of Good Pairs
class Solution:
    def numIdenticalPairs(self, nums: List[int]) -> int:
        counter = Counter(nums)
        return sum((count ** 2 - count) // 2 for count in counter.values() if count > 1)

4.7.1397 - 2023-10-03 09:13:40 +0300 MSK

Number of Good Pairs
class Solution:
    def numIdenticalPairs(self, nums: List[int]) -> int:        
        return sum((count ** 2 - count) // 2 for count in Counter(nums).values() if count > 1)

4.7.1398 - 2023-10-03 09:13:11 +0300 MSK

Number of Good Pairs
class Solution:
    def numIdenticalPairs(self, nums: List[int]) -> int:
        counter = Counter(nums)
        
        return sum((count ** 2 - count) // 2 for count in counter.values() if count > 1)

4.7.1399 - 2023-10-02 15:20:53 +0300 MSK

Remove Colored Pieces if Both Neighbors are the Same Color
class Solution:
    def winnerOfGame(self, colors: str) -> bool:
        cur_char, cur_conseq = colors[0], 1
        moves = {"A": 0, "B": 0}
        for char in colors[1:]:
            if char == cur_char:
                cur_conseq += 1
            else:
                moves[cur_char] += max(0, cur_conseq - 2)
                cur_char, cur_conseq = char, 1
        if cur_conseq > 2:
            moves[cur_char] += cur_conseq - 2
        return moves["A"] > moves["B"]

4.7.1400 - 2023-10-01 16:29:08 +0300 MSK

Reverse Words in a String III
class Solution:
    def reverseWords(self, s: str) -> str:
        return ' '.join(map(lambda word: word[::-1], s.split()))

4.7.1401 - 2023-09-30 10:17:26 +0300 MSK

Merge Intervals
class Solution:
    def merge(self, intervals: List[List[int]]) -> List[List[int]]:

        intervals.sort(key=lambda item: item[0])

        merged = []
        for start, end in intervals:
            # if the list of merged intervals is empty or if the current
            # interval does not overlap with the previous, simply append it.
            if not merged or merged[-1][1] < start:
                merged.append([start, end])
            else:
            # otherwise, there is overlap, so we merge the current and previous
            # intervals.
                merged[-1][1] = max(merged[-1][1], end)

        return merged

4.7.1402 - 2023-09-30 10:09:04 +0300 MSK

132 Pattern
class Solution:
    def find132pattern(self, nums: List[int]) -> bool:
        if len(nums) < 3:
            return False
        min_array = [-1] * len(nums)
        min_array[0] = nums[0]
        for i in range(1, len(nums)):
            min_array[i] = min(min_array[i - 1], nums[i])

        k = len(nums)
        for j in range(len(nums) - 1, -1, -1):
            if nums[j] <= min_array[j]:
                continue
            while k < len(nums) and nums[k] <= min_array[j]:
                k += 1
            if k < len(nums) and nums[k] < nums[j]:
                return True
            k -= 1
            nums[k] = nums[j]
        return False

4.7.1403 - 2023-09-30 10:05:56 +0300 MSK

132 Pattern
class Solution:
    def find132pattern(self, nums: List[int]) -> bool:
        if len(nums) < 3:
            return False
        stack = []
        min_array = [-1] * len(nums)
        min_array[0] = nums[0]
        for i in range(1, len(nums)):
            min_array[i] = min(min_array[i - 1], nums[i])

        for j in reversed(range(len(nums))):
            if nums[j] <= min_array[j]:
                continue
            while stack and stack[-1] <= min_array[j]:
                stack.pop()
            if stack and stack[-1] < nums[j]:
                return True
            stack.append(nums[j])
        return False

4.7.1404 - 2023-09-29 08:36:09 +0300 MSK

Monotonic Array
class Solution:
    def isMonotonic(self, nums: List[int]) -> bool:
        length = len(nums)
        if length < 3:
            return True
        is_increasing = None
        for i in range(1, length):
            cur, prev = nums[i], nums[i-1]
            if cur == prev:
                continue
            is_increasing_cur = cur > prev
            if is_increasing is None:
                is_increasing = is_increasing_cur
                continue
            if is_increasing and not is_increasing_cur or (
                not is_increasing and is_increasing_cur
            ):
                return False
        return True

4.7.1405 - 2023-09-28 10:17:33 +0300 MSK

Sort Array By Parity
class Solution:
    def sortArrayByParity(self, nums: List[int]) -> List[int]:
        left, right = 0, len(nums) - 1
        while left < right:
            while left < right and nums[left] % 2 == 0:
                left += 1
            while left < right and nums[right] % 2 == 1:
                right -= 1
            nums[left], nums[right] = nums[right], nums[left]
        return nums

4.7.1406 - 2023-09-28 10:13:16 +0300 MSK

Sort Array By Parity
class Solution:
    def sortArrayByParity(self, nums: List[int]) -> List[int]:
        length = len(nums)
        left, right = 0, length - 1
        answer = [None] * length
        for num in nums:
            if num % 2 == 0:
                answer[left] = num
                left += 1
            else:
                answer[right] = num
                right -= 1
        return answer

4.7.1407 - 2023-09-27 18:11:20 +0300 MSK

Decoded String at Index
class Solution:
    def decodeAtIndex(self, s: str, k: int) -> str:
        length = 0
        i = 0
        
        while length < k:
            if s[i].isdigit():
                length *= int(s[i])
            else:
                length += 1
            i += 1
        
        for j in range(i-1, -1, -1):
            char = s[j]
            if char.isdigit():
                length //= int(char)
                k %= length
            else:
                if k == 0 or k == length:
                    return char
                length -= 1

4.7.1408 - 2023-09-26 13:43:09 +0300 MSK

Remove Duplicate Letters
class Solution:
    def removeDuplicateLetters(self, s: str) -> str:
        stack = []
        seen = set() 
        last_occ = {char: i for i, char in enumerate(s)}
        
        for i, char in enumerate(s):
            if char in seen:
                continue
                
            while stack and char < stack[-1] and i < last_occ[stack[-1]]:
                seen.discard(stack.pop())
            seen.add(char)
            stack.append(char)
        
        return ''.join(stack)

4.7.1409 - 2023-09-25 09:17:00 +0300 MSK

Find Minimum in Rotated Sorted Array
class Solution:
    def findMin(self, nums: List[int]) -> int:
        length = len(nums)
        if length == 1:
            return nums[0]
        first, last = nums[0], nums[-1]
        if first < last:
            return first
        left, right = 0, length - 1
        while left <= right:
            mid = left + (right - left) // 2
            left_num = nums[mid - 1] if mid > 0 else first
            mid_num = nums[mid] 
            right_num = nums[mid + 1] if mid + 1 < length else last
            if left_num > mid_num <= right_num:
                return mid_num
            if left_num > mid_num or (left_num <= mid_num and mid_num >= first):
                left = mid + 1
            else:
                right = mid
        return nums[left]

4.7.1410 - 2023-09-25 08:28:38 +0300 MSK

Find the Difference
class Solution:
    def findTheDifference(self, s: str, t: str) -> str:
        return chr(reduce(operator.xor, (ord(char) for char in chain(s, t))))

4.7.1411 - 2023-09-25 08:26:39 +0300 MSK

Find the Difference
class Solution:
    def findTheDifference(self, s: str, t: str) -> str:
        count = Counter(s)
        for char in t:
            count[char] -= 1
            if count[char] == -1:
                return char

4.7.1412 - 2023-09-24 14:37:54 +0300 MSK

Bitwise AND of Numbers Range
class Solution:
    def rangeBitwiseAnd(self, left: int, right: int) -> int:
        shift = 0        
        while left < right:
            left >>= 1
            right >>= 1
            shift += 1
        return left << shift

4.7.1413 - 2023-09-24 13:28:55 +0300 MSK

Container With Most Water
class Solution:
    def maxArea(self, height: List[int]) -> int:
        left = 0
        right = len(height) - 1
        maxArea = 0

        while left < right:
            currentArea = min(height[left], height[right]) * (right - left)
            if currentArea > maxArea:
                maxArea = currentArea

            if height[left] < height[right]:
                left += 1
            else:
                right -= 1

        return maxArea

4.7.1414 - 2023-09-24 13:26:28 +0300 MSK

Max Points on a Line
class Solution:
    def maxPoints(self, points: List[List[int]]) -> int:
        lines = defaultdict(set)
        length = len(points)
        if length < 3:
            return length
        for i in range(length):
            x1, y1 = points[i]
            for j in range(i + 1, length):
                x2, y2 = points[j]
                k1, k2 = None, None
                if y1 == y2:
                    k2 = y1
                elif x1 == x2:
                    k1 = x1
                else: 
                    k1 = (y2 - y1) / (x2 - x1)
                    k2 = y1 - k1 * x1
                lines[(k1, k2)].update(((x1, y1), (x2, y2)))
        return max((len(points) for points in lines.values()), default=0)

4.7.1415 - 2023-09-24 13:00:11 +0300 MSK

Candy
class Solution:
    def candy(self, ratings: List[int]) -> int:
        child_count = len(ratings)
        candies = [1] * child_count 

        for i in range(1, child_count):
            if ratings[i] > ratings[i-1]:
                candies[i] = candies[i-1] + 1

        for i in reversed(range(child_count - 1)):
            if ratings[i] > ratings[i+1]:
                candies[i] = max(candies[i], candies[i+1] + 1)
        
        return sum(candies)

4.7.1416 - 2023-09-24 12:59:51 +0300 MSK

Longest Substring Without Repeating Characters
class Solution:
    def lengthOfLongestSubstring(self, s: str) -> int:
        length = len(s)
        if length < 2:
            return length
        
        max_length, left, charset = 1, 0, set([s[0]])
        for right in range(1, length):
            letter = s[right]
            if letter not in charset:
                charset.add(letter)
                continue

            this_length = right - left
            if this_length > max_length:
                max_length = this_length
            
            while letter in charset:
                charset.remove(s[left])
                left += 1
            
            charset.add(letter)

        return max(max_length, length - left)

4.7.1417 - 2023-09-24 12:59:24 +0300 MSK

Populating Next Right Pointers in Each Node II
from collections import deque

class Solution:
  def connect(self, root: 'Node') -> 'Node':
    # Edge case - If the root is None, then return None
    if root is None:
        return None
    
    # Create a queue and enqueue the root node
    q = deque([root])
    
    # Traverse the tree level by level
    while q:
        
        # Get the number of nodes of the current level
        level_size = len(q)
        
        # Process the nodes of the current level
        for i in range(level_size):
            
            # Dequeue a node from the front of the queue
            node = q.popleft()
            
            # Assign the next pointer of the node
            if i < level_size - 1:
                node.next = q[0]
            
            # Enqueue the children of the node (if any)
            if node.left is not None:
                q.append(node.left)
            if node.right is not None:
                q.append(node.right)
    
    # Return the root node
    return root

4.7.1418 - 2023-09-24 12:56:43 +0300 MSK

Binary Search Tree Iterator
# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class BSTIterator:

    def __init__(self, root: Optional[TreeNode]):
        def generate(node: TreeNode) -> int:
            if not node:
                return
            yield from generate(node.left)
            yield node
            yield from generate(node.right)

        self._generate = generate(root)
        self._next = next(self._generate)

    def next(self) -> int:
        next_val = self._next.val
        self._next = next(self._generate, None)
        return next_val 

    def hasNext(self) -> bool:
        return self._next is not None


# Your BSTIterator object will be instantiated and called as such:
# obj = BSTIterator(root)
# param_1 = obj.next()
# param_2 = obj.hasNext()

4.7.1419 - 2023-09-24 12:56:22 +0300 MSK

Implement Trie (Prefix Tree)
class Trie:

    def __init__(self):
        self.root = {}

    def insert(self, word: str) -> None:
        cur = self.root
        for char in word:
            if char not in cur:
                cur[char] = {}
            cur = cur[char]
        
        cur["_is_word"] = None

    def search(self, word: str) -> bool:
        cur = self.root
        for char in word:
            if char not in cur:
                return False
            cur = cur[char]
        
        return "_is_word" in cur

    def startsWith(self, prefix: str) -> bool:
        cur = self.root
        for char in prefix:
            if char not in cur:
                return False
            cur = cur[char]
            
        return True


# Your Trie object will be instantiated and called as such:
# obj = Trie()
# obj.insert(word)
# param_2 = obj.search(word)
# param_3 = obj.startsWith(prefix)

4.7.1420 - 2023-09-24 12:55:57 +0300 MSK

Combinations
class Solution:
    def combine(self, n: int, k: int) -> List[List[int]]:
        current = []
        
        def backtrack(first: int) -> Generator[None, None, List[int]]:
            if len(current) == k:
                yield tuple(current[:])
                return

            for i in range(first, n + 1):
                current.append(i)
                yield from backtrack(i + 1)
                current.pop()
            
            return

        return tuple(combination for combination in backtrack(1)) 

4.7.1421 - 2023-09-24 12:55:41 +0300 MSK

Permutations
class Solution:
    def permute(self, nums: List[int]) -> List[List[int]]:

        length = len(nums)
        current = []
        current_contains = [False] * length

        def backtrack() -> Generator[None, None, List[int]]:
            if len(current) == length:
                yield tuple(current[:])
                return

            for i in range(length):
                if current_contains[i]:
                    continue

                current_contains[i] = True
                current.append(nums[i])

                yield from backtrack()

                current_contains[i] = False
                current.pop()
            
            return

        return tuple(combination for combination in backtrack()) 

4.7.1422 - 2023-09-24 12:55:19 +0300 MSK

Generate Parentheses
class Solution:
    def generateParenthesis(self, n: int) -> List[str]:

        current = []
        current_max = n * 2
        chars = "()"


        def backtrack(open: int, closed: int) -> Generator[None, None, List[str]]:
            if len(current) == current_max:
                yield "".join(current)
            
            if open:
                current.append(chars[0])
                yield from backtrack(open - 1, closed)
                current.pop()
            
            if closed and closed > open:
                current.append(chars[1])
                yield from backtrack(open, closed - 1)
                current.pop()
        
        return tuple(combination for combination in backtrack(n, n))

4.7.1423 - 2023-09-24 12:54:51 +0300 MSK

Maximum Subarray
class Solution:
    def maxSubArray(self, nums: List[int]) -> int:
        length = len(nums)
        if length == 0:
            return 0
        if length == 1:
            return nums[0]
        max_cur, max_overall = 0, float("-inf")
        for num in nums:
            max_cur += num
            if max_cur > max_overall:
                max_overall = max_cur
            if max_cur < 0:
                max_cur = 0
        return max_overall
        

4.7.1424 - 2023-09-24 12:53:12 +0300 MSK

Median of Two Sorted Arrays
class Solution:
    def findMedianSortedArrays(self, nums1: List[int], nums2: List[int]) -> float:
        m, n = len(nums1), len(nums2)
        p1, p2 = 0, 0
        
        # Get the smaller value between nums1[p1] and nums2[p2].
        def get_min():
            nonlocal p1, p2
            if p1 < m and p2 < n:
                if nums1[p1] < nums2[p2]:
                    ans = nums1[p1]
                    p1 += 1
                else:
                    ans = nums2[p2]
                    p2 += 1
            elif p2 == n:
                ans = nums1[p1]
                p1 += 1
            else:
                ans = nums2[p2]
                p2 += 1
            return ans
        
        if (m + n) % 2 == 0:
            for _ in range((m + n) // 2 - 1):
                _ = get_min()
            return (get_min() + get_min()) / 2
        else:
            for _ in range((m + n) // 2):
                _ = get_min()
            return get_min()

4.7.1425 - 2023-09-24 12:52:56 +0300 MSK

Search in Rotated Sorted Array
class Solution:
    def search(self, nums: List[int], target: int) -> int:
        nums_count = len(nums)
        left, right = 0, len(nums) - 1

        first_num, last_num = nums[0], nums[-1]
        if first_num == target:
            return 0
        if last_num == target:
            return nums_count - 1
        
        # Find the index of the pivot element (the smallest element)
        while left <= right:
            mid = left + (right - left) // 2
            if nums[mid] > last_num:
                left = mid + 1
            else:
                right = mid - 1
        
        pivot_num = nums[left]
        if pivot_num == target:
            return left
        
        if pivot_num < target < last_num:
            right = nums_count - 1
        else:
            left = 0
        
        while left <= right:
            mid = left + (right - left) // 2
            mid_num = nums[mid]
            if mid_num == target:
                return mid
            elif mid_num > target:
                right = mid - 1
            else:
                left = mid + 1
        
        return -1

4.7.1426 - 2023-09-24 12:52:34 +0300 MSK

Single Number II
class Solution:
    def singleNumber(self, nums: List[int]) -> int:
        nums.sort()
        length = len(nums)
        for i in range(0, length, 3):
            if i == length - 1:
                return nums[i]
    
            num_1, num_2, num_3 = nums[i], nums[i+1], nums[i+2]

            if num_1 == num_2 == num_3:
                continue
            
            if num_2 == num_3:
                return num_1
            
            if num_1 == num_3:
                return num_2
            
            return num_3
            

4.7.1427 - 2023-09-24 12:52:13 +0300 MSK

Single Number
class Solution:
    def singleNumber(self, nums: List[int]) -> int:
        return reduce(xor, nums)

4.7.1428 - 2023-09-24 12:51:48 +0300 MSK

Number of 1 Bits
class Solution:
    def hammingWeight(self, n: int) -> int:
        count = 0
        while n > 0:
            if n & 1 != 0:
                count += 1
            n >>= 1
        return count

4.7.1429 - 2023-09-24 12:50:52 +0300 MSK

Reverse Bits
class Solution:
    def reverseBits(self, n: int) -> int:
        # Initialize the reversed number to 0
        reversed_num = 0
        
        # Iterate over all 32 bits of the given number
        for i in range(32):
            # Left shift the reversed number by 1 and add the last bit of the given number to it
            reversed_num = (reversed_num << 1) | (n & 1)
            # remove the last bit from the original number
            n >>= 1
        
        # Return the reversed number
        return reversed_num

4.7.1430 - 2023-09-24 12:50:33 +0300 MSK

Add Binary
class Solution:
    def addBinary(self, a: str, b: str) -> str:
        answer = []
        carry = 0
        for char1, char2 in zip_longest(reversed(a), reversed(b)):
            num1, num2 = int(char1) if char1 else 0, int(char2) if char2 else 0
            cur_sum = num1 + num2 + carry
            carry = 0
            if cur_sum > 1:
                cur_sum -= 2
                carry = 1
            
            answer.append(str(cur_sum))
        
        if carry:
            answer.append("1")

        return "".join(reversed(answer))

4.7.1431 - 2023-09-24 12:47:07 +0300 MSK

Factorial Trailing Zeroes
class Solution:
    def trailingZeroes(self, n: int) -> int:
        zeros = 0
        while n != 0:
            new_n = n // 5
            zeros += new_n
            n = new_n
        return zeros
        

4.7.1432 - 2023-09-24 12:44:33 +0300 MSK

Factorial Trailing Zeroes
class Solution:
    def trailingZeroes(self, n: int) -> int:
        a, b, zeros = 1, 5, 0
        while (5**a) <= n:
            zeros += n // b
            a += 1
            b *= 5
        return zeros

4.7.1433 - 2023-09-24 12:41:55 +0300 MSK

Pow(x, n)
class Solution:
    def myPow(self, x: float, n: int) -> float:
        if n == 0:
            return 1

        if n < 0:
            n *= -1
            x = 1 / x

        result = 1
        while n:
            if n % 2:
                result *= x
                n -= 1
            x *= x
            n //= 2
        
        return result

4.7.1434 - 2023-09-24 12:41:37 +0300 MSK

Plus One
class Solution:
    def plusOne(self, digits: List[int]) -> List[int]:
        carry = 1
        for i in reversed(range(len(digits))):
            new_digit = digits[i] + carry
            if new_digit > 9:
                carry = 1
                new_digit %= 10
            else:
                carry = 0
            digits[i] = new_digit
        
        if carry:
            digits.insert(0, carry)
        
        return digits

4.7.1435 - 2023-09-24 12:40:45 +0300 MSK

Partition List
# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:
    def partition(self, head: Optional[ListNode], x: int) -> Optional[ListNode]:
        before_head, after_head = ListNode(0), ListNode(0)
        before_tail, after_tail = before_head, after_head
        
        while head: 
            if head.val < x:
                before_tail.next, before_tail = head, head
            else:
                after_tail.next, after_tail = head, head
            head = head.next
        
        after_tail.next, before_tail.next = None, after_head.next
        
        return before_head.next

4.7.1436 - 2023-09-24 12:40:14 +0300 MSK

Reverse Linked List II
# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:
    def reverseBetween(self, head: Optional[ListNode], left: int, right: int) -> Optional[ListNode]:
        cur_node = 1
        left_head, left_tail = head if left > 1 else None, None

        while cur_node < left:
            cur_node += 1
            head, left_tail = head.next, head

        cur_node += 1
        mid_head, mid_tail, head = head, head, head.next
        mid_head.next = None

        while cur_node <= right:
            cur_node += 1
            mid_head, head.next, head = head, mid_head, head.next
    
        mid_tail.next = head
        if left_head:
            left_tail.next = mid_head
        else:
            left_head = mid_head

        return left_head

4.7.1437 - 2023-09-24 12:39:52 +0300 MSK

Copy List with Random Pointer
"""
# Definition for a Node.
class Node:
    def __init__(self, x: int, next: 'Node' = None, random: 'Node' = None):
        self.val = int(x)
        self.next = next
        self.random = random
"""

class Solution:
    def copyRandomList(self, head: 'Optional[Node]') -> 'Optional[Node]':
        
        copied = {None: None}

        def copy_node(node: Node) -> Node:
            if node in copied:
                return copied[node]
            
            new_node = Node(node.val)
            copied[node] = new_node
            new_node.next = copy_node(node.next)
            new_node.random = copy_node(node.random)
            return new_node
        
        return copy_node(head)

4.7.1438 - 2023-09-24 12:38:31 +0300 MSK

Remove Duplicates from Sorted List II
# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:
    def deleteDuplicates(self, head: Optional[ListNode]) -> Optional[ListNode]:
        tail, before_tail = head, None
        remove_tail = False
        while tail:
            if tail.next and tail.val == tail.next.val:
                tail.next = tail.next.next
                remove_tail = True
                continue
            if not remove_tail:
                before_tail, tail = tail, tail.next
                continue
            remove_tail = False
            if before_tail is None:
                tail = head.next
                head.next, head = None, head.next
            else:
                before_tail.next = tail.next
                tail = tail.next
        return head

4.7.1439 - 2023-09-24 12:09:18 +0300 MSK

Champagne Tower
class Solution:
    def champagneTower(self, poured: int, query_row: int, query_glass: int) -> float:
        if query_row == 0:
            return min(1, poured)
        if query_glass in (0, query_row):
            while query_row and poured:
                poured = (poured - 1) / 2 if poured > 1 else 0
                query_row -= 1
            return min(1, poured)

        cur_row, next_row = [0] * (query_row + 2), [0] * (query_row + 2)
        cur_row[0] = poured
        for row in range(query_row + 1):
            next_row[0] = 0
            for col in range(row + 1):
                overflow = (cur_row[col] - 1) / 2
                if overflow > 0:
                    next_row[col] += overflow
                    next_row[col + 1] = overflow
                else:
                    next_row[col + 1] = 0
            cur_row, next_row = next_row, cur_row
        return min(1, next_row[query_glass])

4.7.1440 - 2023-09-23 21:54:59 +0300 MSK

Remove Nth Node From End of List
# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:
    def removeNthFromEnd(self, head: Optional[ListNode], n: int) -> Optional[ListNode]:
        cur_length, target_length, before_removed = 0, n + 1, head
        tail = head
        while tail and cur_length != target_length:
            tail = tail.next
            cur_length += 1
        if not tail and cur_length != target_length:
            return head.next
        while tail:
            before_removed = before_removed.next
            tail = tail.next
        before_removed.next = before_removed.next.next
        return head

4.7.1441 - 2023-09-23 18:06:03 +0300 MSK

Rotate List
# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:
    def rotateRight(self, head: Optional[ListNode], k: int) -> Optional[ListNode]:
        if k == 0 or not head:
            return head
        temp_head, tail, length = head, head, 0
        while temp_head:
            length += 1
            tail, temp_head = temp_head, temp_head.next
        rotation = k % length
        if rotation == 0:
            return head
        new_head_idx = length - rotation
        new_tail_idx = new_head_idx - 1 
        i, new_head, new_tail = 0, None, None
        temp_head = head
        while temp_head:
            if i == new_head_idx:
                new_head = temp_head
                break
            if i == new_tail_idx:
                new_tail = temp_head
            i += 1
            temp_head = temp_head.next
        tail.next = head
        new_tail.next = None
        return new_head

            

4.7.1442 - 2023-09-23 13:19:00 +0300 MSK

Longest String Chain
class Solution:
    def longestStrChain(self, words: List[str]) -> int:
        words.sort(key=len)
        dp = {}
        max_chain = 0
        for word in words:
            dp[word] = 1
            for i in range(len(word)):
                prev_word = word[:i] + word[i+1:]
                if prev_word in dp:
                    dp[word] = max(dp[word], dp[prev_word] + 1)
            max_chain = max(max_chain, dp[word])
        return max_chain

4.7.1443 - 2023-09-22 18:29:58 +0300 MSK

Minimum Bit Flips to Convert Number
class Solution:
    def minBitFlips(self, start: int, goal: int) -> int:
        flips_count = 0
        while start or goal:
            start_is_one, goal_is_one = start & 1, goal & 1
            if start_is_one and not goal_is_one or (not start_is_one and goal_is_one):
                flips_count += 1
            start >>= 1
            goal >>= 1
        return flips_count

4.7.1444 - 2023-09-22 13:51:50 +0300 MSK

Sum of All Subset XOR Totals
class Solution:
    def subsetXORSum(self, nums: List[int]) -> int:
        return reduce(operator.or_, nums) * 1 << (len(nums) - 1)
        

4.7.1445 - 2023-09-22 13:49:11 +0300 MSK

Sum of All Subset XOR Totals
class Solution:
    def subsetXORSum(self, nums: List[int]) -> int:
        subsets_count = 2**(len(nums) - 1)
        return reduce(operator.or_, nums) * subsets_count
        

4.7.1446 - 2023-09-22 12:14:22 +0300 MSK

Longest Nice Substring
class Solution:
    def longestNiceSubstring(self, s: str) -> str:
        sSet = set(s)
        for i in range(len(s)):
            if s[i].lower() not in sSet or s[i].upper() not in sSet:
                lns1 = self.longestNiceSubstring(s[:i])
                lns2 = self.longestNiceSubstring(s[i+1:])

                return max(lns1, lns2, key=len)

        return s

4.7.1447 - 2023-09-22 11:34:42 +0300 MSK

Count the Number of Consistent Strings
class Solution:
    def countConsistentStrings(self, allowed: str, words: List[str]) -> int:
        allowed = set(allowed)
        count = 0
        for word in words:
            if all(char in allowed for char in word):
                count += 1
        return count

4.7.1448 - 2023-09-22 11:27:41 +0300 MSK

Count the Number of Consistent Strings
class Solution:
    def countConsistentStrings(self, allowed: str, words: List[str]) -> int:
        allowed = set(allowed)
        count = 0
        for word in words:
            if not set(word) - allowed:
                count += 1
        return count

4.7.1449 - 2023-09-22 11:23:55 +0300 MSK

XOR Operation in an Array
class Solution:
    def xorOperation(self, n: int, start: int) -> int:
        return reduce(lambda total, i: total ^ (start + 2 * i), chain((0, ), range(n)))

4.7.1450 - 2023-09-22 10:24:39 +0300 MSK

Binary Gap
class Solution:
    def binaryGap(self, n: int) -> int:
        i, first_bit = 0, None
        max_distance = 0
        while n:
            is_one = n & 1 == 1
            if is_one and first_bit is None:
                first_bit = i
            elif is_one:
                max_distance, first_bit = max(max_distance, i - first_bit), i
            n >>= 1
            i += 1
        
        return max_distance 

4.7.1451 - 2023-09-22 08:57:07 +0300 MSK

Is Subsequence
class Solution:
    def isSubsequence(self, s: str, t: str) -> bool:
        i = 0
        length = len(s)
        for char in t:
            if i == length:
                break
            if s[i] == char:
                i += 1
            
        return i == length

4.7.1452 - 2023-09-22 08:51:25 +0300 MSK

Prime Number of Set Bits in Binary Representation
class Solution:
    def countPrimeSetBits(self, left: int, right: int) -> int:
        prime_bits = (2, 3, 5, 7, 11, 13, 17, 19)
        answer = 0
        for num in range(left, right + 1):
            bit_count = num.bit_count()
            if bit_count in prime_bits:
                answer += 1
            
        return answer

4.7.1453 - 2023-09-21 19:36:09 +0300 MSK

Set Mismatch
class Solution:
    def findErrorNums(self, nums: List[int]) -> List[int]:
        length = len(nums)
        # dupl_xor_miss = duplicate ^ missing
        dupl_xor_miss = reduce(lambda total, i: total ^ i ^ nums[i - 1], range(length + 1))
        rightmost_set_bit = dupl_xor_miss & -dupl_xor_miss
        xor_group1 = xor_group2 = 0
        for i in range(1, length + 1):
            if i & rightmost_set_bit:
                xor_group1 ^= i
            else:
                xor_group2 ^= i
            if nums[i - 1] & rightmost_set_bit:
                xor_group1 ^= nums[i - 1]
            else:
                xor_group2 ^= nums[i - 1]
        for num in nums:
            if num == xor_group1:
                return num, xor_group2
            if num == xor_group2:
                return num, xor_group1 
        
        raise Exception()

4.7.1454 - 2023-09-21 19:11:34 +0300 MSK

Set Mismatch
class Solution:
    def findErrorNums(self, nums: List[int]) -> List[int]:
        n = len(nums)
        dupl_xor_miss = 0
        for i in range(1, n+1):
            dupl_xor_miss ^= i ^ nums[i-1]
        
        # example for get rightmost set bit
        # x:             01110000
        # ~x:            10001111
        # -x or ~x + 1:  10010000
        # x & -x:        00010000

        # example for unset rightmost set bit
        # x:             01110000
        # x-1:           01101111
        # x & (x-1):     01100000
        rightmost_set_bit = dupl_xor_miss & -dupl_xor_miss
        xor_group1 = xor_group2 = 0
        for i in range(1, n + 1):
            if i & rightmost_set_bit:
                xor_group1 ^= i
            else:
                xor_group2 ^= i
            if nums[i-1] & rightmost_set_bit:
                xor_group1 ^= nums[i-1]
            else:
                xor_group2 ^= nums[i-1]
        
        for num in nums:
            if num == xor_group1:
                return [num, xor_group2]
            if num == xor_group2:
                return [num, xor_group1]

        return []

4.7.1455 - 2023-09-21 18:33:03 +0300 MSK

Number Complement
class Solution:
    def findComplement(self, num: int) -> int:
        return ~num + (1 << num.bit_length())

4.7.1456 - 2023-09-21 09:51:52 +0300 MSK

Median of Two Sorted Arrays
class Solution:
    def findMedianSortedArrays(self, nums1: List[int], nums2: List[int]) -> float:
        m, n = len(nums1), len(nums2)
        p1, p2 = 0, 0
        
        # Get the smaller value between nums1[p1] and nums2[p2].
        def get_min():
            nonlocal p1, p2
            if p1 < m and p2 < n:
                if nums1[p1] < nums2[p2]:
                    ans = nums1[p1]
                    p1 += 1
                else:
                    ans = nums2[p2]
                    p2 += 1
            elif p2 == n:
                ans = nums1[p1]
                p1 += 1
            else:
                ans = nums2[p2]
                p2 += 1
            return ans
        
        if (m + n) % 2 == 0:
            for _ in range((m + n) // 2 - 1):
                _ = get_min()
            return (get_min() + get_min()) / 2
        else:
            for _ in range((m + n) // 2):
                _ = get_min()
            return get_min()

4.7.1457 - 2023-09-20 22:32:26 +0300 MSK

Sum of Values at Indices With K Set Bits
class Solution:
    def sumIndicesWithKSetBits(self, nums: List[int], k: int) -> int:
        return sum(num for i, num in enumerate(nums) if i.bit_count() == k)

4.7.1458 - 2023-09-20 22:28:16 +0300 MSK

Sort Integers by The Number of 1 Bits
class Solution:
    def sortByBits(self, arr: List[int]) -> List[int]:
        return tuple(num for num in sorted(arr, key=lambda num: (num.bit_count(), num)))

4.7.1459 - 2023-09-20 22:22:48 +0300 MSK

Number of Even and Odd Bits
class Solution:
    def evenOddBit(self, n: int) -> List[int]:
        return (n & 0x55555555).bit_count(), (n & 0xaaaaaaaa).bit_count()

4.7.1460 - 2023-09-20 22:20:17 +0300 MSK

Number of Even and Odd Bits
class Solution:
    def evenOddBit(self, n: int) -> List[int]:
        even, odd = n & 0x55555555, n & 0xaaaaaaaa
        even_count, odd_count = 0, 0
        while even:
            if even & 1 == 1:
                even_count += 1
            even >>= 1
            
        while odd:
            if odd & 1 == 1:
                odd_count += 1
            odd >>= 1
        
        return even_count, odd_count

4.7.1461 - 2023-09-20 19:50:56 +0300 MSK

Binary Number with Alternating Bits
class Solution:
    def hasAlternatingBits(self, n: int) -> bool:
        return n & (n >> 1) == 0 and n & (n >> 2) == n >> 2

4.7.1462 - 2023-09-20 19:35:10 +0300 MSK

Power of Three
class Solution:
    def isPowerOfThree(self, n: int) -> bool:
        #                3 ** 20
        return n > 0 and 3486784401 % n == 0

4.7.1463 - 2023-09-20 19:07:10 +0300 MSK

Power of Two
class Solution:
    def isPowerOfTwo(self, n: int) -> bool:
        return n > 0 and n & (n - 1) == 0

4.7.1464 - 2023-09-20 18:36:36 +0300 MSK

Power of Four
class Solution:
    def isPowerOfFour(self, n: int) -> bool:
        # Check if the number is greater than zero and is a power of two
        if n > 0 and (n & (n - 1)) == 0:
            # Check if the number is of the form 4^x
            return n & 0x55555555 == n
        else:
            return False

4.7.1465 - 2023-09-20 18:32:58 +0300 MSK

Power of Four
class Solution:
    def isPowerOfFour(self, n: int) -> bool:
        return n and not (n & (n - 1)) and (n & 0x55555555)

4.7.1466 - 2023-09-20 18:32:51 +0300 MSK

Power of Four
class Solution:
    def isPowerOfFour(self, n: int) -> bool:
        return n and not (n & (n - 1)) and (n & 0x55555555)

4.7.1467 - 2023-09-20 18:32:34 +0300 MSK

Power of Four
class Solution:
    def isPowerOfFour(self, n: int) -> bool:
        return n and not (n & (n - 1)) and (n & 0x55555555)

4.7.1468 - 2023-09-20 18:02:39 +0300 MSK

Missing Number
class Solution:
    def missingNumber(self, nums: List[int]) -> int:
        def xor(total: int, i: int) -> int:
            return total ^ nums[i] ^ (i + 1)
        return reduce(xor, chain((0, ), range(len(nums))))

4.7.1469 - 2023-09-20 18:01:50 +0300 MSK

Missing Number
class Solution:
    def missingNumber(self, nums: List[int]) -> int:
        return reduce(lambda total, i: total ^ nums[i] ^ (i + 1), chain((0, ), range(len(nums))))

4.7.1470 - 2023-09-20 17:28:42 +0300 MSK

Missing Number
class Solution:
    def missingNumber(self, nums: List[int]) -> int:
        length = len(nums)
        return ((length + 1) * length) // 2 - sum(nums)

4.7.1471 - 2023-09-20 17:07:50 +0300 MSK

Reverse Bits
class Solution:
    def reverseBits(self, n: int) -> int:
        # Initialize the reversed number to 0
        reversed_num = 0
        
        # Iterate over all 32 bits of the given number
        for i in range(32):
            # Left shift the reversed number by 1 and add the last bit of the given number to it
            reversed_num = (reversed_num << 1) | (n & 1)
            # remove the last bit from the original number
            n >>= 1
        
        # Return the reversed number
        return reversed_num

4.7.1472 - 2023-09-20 16:31:32 +0300 MSK

Add Binary
class Solution:
    def addBinary(self, a: str, b: str) -> str:
        answer = []
        carry = 0
        for char1, char2 in zip_longest(reversed(a), reversed(b)):
            num1, num2 = int(char1) if char1 else 0, int(char2) if char2 else 0
            cur_sum = num1 + num2 + carry
            carry = 0
            if cur_sum > 1:
                cur_sum -= 2
                carry = 1
            
            answer.append(str(cur_sum))
        
        if carry:
            answer.append("1")

        return "".join(reversed(answer))

4.7.1473 - 2023-09-20 11:47:24 +0300 MSK

Minimum Operations to Reduce X to Zero
class Solution:
    def minOperations(self, nums: List[int], x: int) -> int:
        target, length = sum(nums) - x, len(nums)
        max_len = cur_sum = left = 0
        
        if target == 0:
            return length
        
        for right, val in enumerate(nums):
            cur_sum += val
            while left <= right and cur_sum > target:
                cur_sum -= nums[left]
                left += 1
            if cur_sum == target:
                max_len = max(max_len, right - left + 1)
        
        return length - max_len if max_len else -1

4.7.1474 - 2023-09-19 21:08:16 +0300 MSK

Design Bitset
class Bitset:

    def __init__(self, size: int):
        self.bits = [0] * size
        self.ones_count = 0
        self.do_flip = False
        self.size = size

    def fix(self, idx: int) -> None:
        cur = self.bits[idx]
        if self.do_flip and cur == 1:
            self.ones_count -= 1
            self.bits[idx] = 0
        elif not self.do_flip and cur == 0:
            self.ones_count += 1
            self.bits[idx] = 1

    def unfix(self, idx: int) -> None:
        cur = self.bits[idx]
        if self.do_flip and cur == 0:
            self.ones_count += 1
            self.bits[idx] = 1
        elif not self.do_flip and cur == 1:
            self.ones_count -= 1
            self.bits[idx] = 0

    def flip(self) -> None:
        self.do_flip = not self.do_flip

    def all(self) -> bool:
        return self.count() == self.size

    def one(self) -> bool:
        return self.count() > 0

    def count(self) -> int:
        return self.size - self.ones_count if self.do_flip else self.ones_count

    def toString(self) -> str:
        target = (bit ^ 1 for bit in self.bits) if self.do_flip else self.bits
        return "".join(str(num) for num in target)


# Your Bitset object will be instantiated and called as such:
# obj = Bitset(size)
# obj.fix(idx)
# obj.unfix(idx)
# obj.flip()
# param_4 = obj.all()
# param_5 = obj.one()
# param_6 = obj.count()
# param_7 = obj.toString()

4.7.1475 - 2023-09-19 20:00:19 +0300 MSK

Find the Duplicate Number
class Solution:
    def findDuplicate(self, nums: List[int]) -> int:
        freqs = [False] * (10**5 + 1)
        for num in nums:
            if freqs[num] == True:
                return num
            freqs[num] = True

        raise Exception()

4.7.1476 - 2023-09-19 19:58:37 +0300 MSK

Find the Duplicate Number
class Solution:
    def findDuplicate(self, nums: List[int]) -> int:
        freqs = [0] * (10**5 + 1)
        for num in nums:
            freqs[num] += 1
            if freqs[num] > 1:
                return num

        raise Exception()

4.7.1477 - 2023-09-18 15:46:36 +0300 MSK

Product of the Last K Numbers
class ProductOfNumbers:

    def __init__(self):
        self.products = [1]

    def add(self, num: int) -> None:
        if num == 0:
            self.products.clear()
            self.products.append(1)
            return
        self.products.append(num * self.products[-1])

    def getProduct(self, k: int) -> int:
        if len(self.products) - 1 < k:
            return 0
        return self.products[-1] // self.products[-(k + 1)]


# Your ProductOfNumbers object will be instantiated and called as such:
# obj = ProductOfNumbers()
# obj.add(num)
# param_2 = obj.getProduct(k)

4.7.1478 - 2023-09-18 15:46:14 +0300 MSK

Product of the Last K Numbers
class ProductOfNumbers:

    def __init__(self):
        self.products = [1]

    def add(self, num: int) -> None:
        if num == 0:
            self.products = [1]
            return
        self.products.append(num * self.products[-1])

    def getProduct(self, k: int) -> int:
        if len(self.products) - 1 < k:
            return 0
        return self.products[-1] // self.products[-(k + 1)]


# Your ProductOfNumbers object will be instantiated and called as such:
# obj = ProductOfNumbers()
# obj.add(num)
# param_2 = obj.getProduct(k)

4.7.1479 - 2023-09-18 15:38:04 +0300 MSK

Product of the Last K Numbers
class ProductOfNumbers:

    def __init__(self):
        self.products, self.last_zero, self.length = [], -1, 0

    def add(self, num: int) -> None:
        if num == 0:
            self.last_zero = self.length
            num = 1
        self.products.append(num * (self.products[-1] if self.products else 1))
        self.length += 1

    def getProduct(self, k: int) -> int:
        first_elem = self.length - k
        if self.last_zero >= first_elem:
            return 0
        if first_elem == 0:
            return self.products[-1]
        return self.products[-1] // self.products[first_elem - 1]


# Your ProductOfNumbers object will be instantiated and called as such:
# obj = ProductOfNumbers()
# obj.add(num)
# param_2 = obj.getProduct(k)

4.7.1480 - 2023-09-18 15:35:47 +0300 MSK

Product of the Last K Numbers
class ProductOfNumbers:

    def __init__(self):
        self.products, self.zero_indexes = [], []

    def add(self, num: int) -> None:
        if num == 0:
            self.zero_indexes.append(len(self.products))
            num = 1
        new_product = num * (self.products[-1] if self.products else 1)
        self.products.append(new_product)

    def getProduct(self, k: int) -> int:
        first_elem = len(self.products) - k
        if self.zero_indexes and self.zero_indexes[-1] >= first_elem:
            return 0
        if first_elem == 0:
            return self.products[-1]
        return self.products[-1] // self.products[first_elem - 1]


# Your ProductOfNumbers object will be instantiated and called as such:
# obj = ProductOfNumbers()
# obj.add(num)
# param_2 = obj.getProduct(k)

4.7.1481 - 2023-09-18 15:12:57 +0300 MSK

Find Consecutive Integers from a Data Stream
class DataStream:

    def __init__(self, value: int, k: int):
        self.required, self.value, self.value_count = k, value, 0

    def consec(self, num: int) -> bool:
        if num != self.value:
            self.value_count = 0
            return False
        self.value_count += 1
        return self.value_count >= self.required


# Your DataStream object will be instantiated and called as such:
# obj = DataStream(value, k)
# param_1 = obj.consec(num)

4.7.1482 - 2023-09-18 15:12:07 +0300 MSK

Find Consecutive Integers from a Data Stream
class DataStream:

    def __init__(self, value: int, k: int):
        self.required, self.value, self.value_count = k, value, 0
        

    def consec(self, num: int) -> bool:
        if num != self.value:
            self.value_count = 0
            return False
        
        self.value_count += 1
        return self.value_count >= self.required


# Your DataStream object will be instantiated and called as such:
# obj = DataStream(value, k)
# param_1 = obj.consec(num)

4.7.1483 - 2023-09-18 15:00:25 +0300 MSK

Smallest Number in Infinite Set
class SmallestInfiniteSet:

    def __init__(self):
        self.heap, self.next_num, self.nums = [], 1, set() 

    def popSmallest(self) -> int:
        if self.heap:
            val = heappop(self.heap)
            self.nums.remove(val)
            return val
        self.next_num += 1
        return self.next_num - 1

    def addBack(self, num: int) -> None:
        if num in self.nums or num >= self.next_num:
            return
        self.nums.add(num)
        heappush(self.heap, num)


# Your SmallestInfiniteSet object will be instantiated and called as such:
# obj = SmallestInfiniteSet()
# param_1 = obj.popSmallest()
# obj.addBack(num)

4.7.1484 - 2023-09-18 14:59:16 +0300 MSK

Smallest Number in Infinite Set
class SmallestInfiniteSet:

    def __init__(self):
        self.heap, self.next_num, self.nums = [], 1, set() 


    def popSmallest(self) -> int:
        if not self.heap:
            self.next_num += 1
            return self.next_num - 1
            
        val = heappop(self.heap)
        if val < self.next_num:
            self.nums.remove(val)
            return val
        heappush(self.heap, val)
        self.next_num += 1
        return self.next_num - 1
        

    def addBack(self, num: int) -> None:
        if num in self.nums or num >= self.next_num:
            return
        self.nums.add(num)
        heappush(self.heap, num)


# Your SmallestInfiniteSet object will be instantiated and called as such:
# obj = SmallestInfiniteSet()
# param_1 = obj.popSmallest()
# obj.addBack(num)

4.7.1485 - 2023-09-18 14:37:29 +0300 MSK

Find Elements in a Contaminated Binary Tree
# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class FindElements:

    def __init__(self, root: Optional[TreeNode]):
        root.val = 0
        nodes = [root]
        self.values = set((0, )) 
        while nodes:
            node = nodes.pop()
            if node.left:
                val = 2 * node.val + 1
                node.left.val = val
                nodes.append(node.left)
                self.values.add(val)
            if node.right:
                val = 2 * node.val + 2
                node.right.val = val
                nodes.append(node.right)
                self.values.add(val)

    def find(self, target: int) -> bool:
        return target in self.values

# Your FindElements object will be instantiated and called as such:
# obj = FindElements(root)
# param_1 = obj.find(target)

4.7.1486 - 2023-09-18 14:34:48 +0300 MSK

Find Elements in a Contaminated Binary Tree
# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class FindElements:

    def __init__(self, root: Optional[TreeNode]):
        self.root = root
        root.val = 0
        nodes = [root]
        while nodes:
            node = nodes.pop()
            new_val = 2 * node.val
            if node.left:
                node.left.val = new_val + 1
                nodes.append(node.left)
            if node.right:
                node.right.val = new_val + 2
                nodes.append(node.right)

    def dfs(self, node: TreeNode, target: int) -> bool:
        if not node or node.val > target:
            return False
        if node.val == target:
            return True
        return self.dfs(node.left, target) or self.dfs(node.right, target)

    def find(self, target: int) -> bool:
        return self.dfs(self.root, target)

# Your FindElements object will be instantiated and called as such:
# obj = FindElements(root)
# param_1 = obj.find(target)

4.7.1487 - 2023-09-18 13:54:11 +0300 MSK

Range Frequency Queries
class RangeFreqQuery:
    def __init__(self, arr: List[int]):
        self.l = [[] for _ in range(10001)]
        for i, v in enumerate(arr):
            self.l[v].append(i)
            
    def query(self, left: int, right: int, v: int) -> int:
        return bisect_right(self.l[v], right) - bisect_left(self.l[v], left)

# Your RangeFreqQuery object will be instantiated and called as such:
# obj = RangeFreqQuery(arr)
# param_1 = obj.query(left,right,value)

4.7.1488 - 2023-09-18 09:47:53 +0300 MSK

The K Weakest Rows in a Matrix
class Solution:
    def kWeakestRows(self, mat: List[List[int]], k: int) -> List[int]:
        rows_count, cols_count = len(mat), len(mat[0])
        heap = []

        for i, row in enumerate(mat):
            count = 0
            for j, val in enumerate(row):
                if val == 0:
                    count = j
                    break
            else:
                count = cols_count
        
            heappush(heap, (count, i))
        
        return tuple(item[1] for item in nsmallest(k, heap))

4.7.1489 - 2023-09-17 16:27:05 +0300 MSK

Implement Magic Dictionary
class MagicDictionary:

    def __init__(self):
        self.dict = []

    def buildDict(self, dictionary: List[str]) -> None:
        self.dict = dictionary

    def search(self, searchWord: str) -> bool:
        target_length = len(searchWord)
        for word in self.dict:
            if len(word) != target_length or word == searchWord:
                continue
            found_diff = False
            for i in range(target_length):
                if word[i] == searchWord[i]:
                    continue
                if found_diff:
                    break

                found_diff = True
            else:
                return True

        return False

# Your MagicDictionary object will be instantiated and called as such:
# obj = MagicDictionary()
# obj.buildDict(dictionary)
# param_2 = obj.search(searchWord)

4.7.1490 - 2023-09-17 16:16:53 +0300 MSK

Encode and Decode TinyURL
class Codec:

    def __init__(self):
        self.urls = []

    def encode(self, longUrl: str) -> str:
        """Encodes a URL to a shortened URL.
        """
        self.urls.append(longUrl)
        return len(self.urls)
        

    def decode(self, shortUrl: str) -> str:
        """Decodes a shortened URL to its original URL.
        """
        return self.urls[shortUrl - 1]
        

# Your Codec object will be instantiated and called as such:
# codec = Codec()
# codec.decode(codec.encode(url))

4.7.1491 - 2023-09-17 16:14:59 +0300 MSK

Encode and Decode TinyURL
class Codec:

    def __init__(self):
        self.urls = {}
        self.id = 0

    def encode(self, longUrl: str) -> str:
        """Encodes a URL to a shortened URL.
        """
        id = self.id
        self.urls[id] = longUrl
        self.id += 1
        return id
        

    def decode(self, shortUrl: str) -> str:
        """Decodes a shortened URL to its original URL.
        """
        return self.urls[int(shortUrl)]
        

# Your Codec object will be instantiated and called as such:
# codec = Codec()
# codec.decode(codec.encode(url))

4.7.1492 - 2023-09-17 16:12:53 +0300 MSK

Encode and Decode TinyURL
class Codec:

    def __init__(self):
        self.urls = []

    def encode(self, longUrl: str) -> str:
        """Encodes a URL to a shortened URL.
        """
        self.urls.append(longUrl)
        return str(len(self.urls) - 1)
        

    def decode(self, shortUrl: str) -> str:
        """Decodes a shortened URL to its original URL.
        """
        return self.urls[int(shortUrl)]
        

# Your Codec object will be instantiated and called as such:
# codec = Codec()
# codec.decode(codec.encode(url))

4.7.1493 - 2023-09-17 16:08:12 +0300 MSK

Design Twitter
class Twitter:

    def __init__(self):
        self.tweets = []
        self.following = defaultdict(set)

    def postTweet(self, userId: int, tweetId: int) -> None:
        self.tweets.append((userId, tweetId))

    def getNewsFeed(self, userId: int) -> List[int]:
        tweets, following = [], self.following[userId]
        for poster, tweet in reversed(self.tweets):
            if poster != userId and poster not in following:
                continue
            tweets.append(tweet)
            if len(tweets) == 10:
                break
            
        return tweets

    def follow(self, followerId: int, followeeId: int) -> None:
        self.following[followerId].add(followeeId)

    def unfollow(self, followerId: int, followeeId: int) -> None:
        self.following[followerId].discard(followeeId)

# Your Twitter object will be instantiated and called as such:
# obj = Twitter()
# obj.postTweet(userId,tweetId)
# param_2 = obj.getNewsFeed(userId)
# obj.follow(followerId,followeeId)
# obj.unfollow(followerId,followeeId)

4.7.1494 - 2023-09-17 11:45:39 +0300 MSK

Shortest Path Visiting All Nodes
from collections import deque, namedtuple

class Solution:
    def shortestPathLength(self, graph):
        n = len(graph)
        all_mask = (1 << n) - 1
        visited = set()
        Node = namedtuple('Node', ['node', 'mask', 'cost'])

        q = deque()
        for i in range(n):
            mask_value = (1 << i)
            this_node = Node(i, mask_value, 1)
            q.append(this_node)
            visited.add((i, mask_value))

        while q:
            curr = q.popleft()

            if curr.mask == all_mask:
                return curr.cost - 1

            for adj in graph[curr.node]:
                both_visited_mask = curr.mask | (1 << adj)
                this_node = Node(adj, both_visited_mask, curr.cost + 1)

                if (adj, both_visited_mask) not in visited:
                    visited.add((adj, both_visited_mask))
                    q.append(this_node)

        return -1

4.7.1495 - 2023-09-17 11:44:04 +0300 MSK

Implement Trie (Prefix Tree)
class Trie:

    def __init__(self):
        self.root = {}

    def insert(self, word: str) -> None:
        cur = self.root
        for char in word:
            if char not in cur:
                cur[char] = {}
            cur = cur[char]
        
        cur["_is_word"] = None

    def search(self, word: str) -> bool:
        cur = self.root
        for char in word:
            if char not in cur:
                return False
            cur = cur[char]
        
        return "_is_word" in cur

    def startsWith(self, prefix: str) -> bool:
        cur = self.root
        for char in prefix:
            if char not in cur:
                return False
            cur = cur[char]
            
        return True


# Your Trie object will be instantiated and called as such:
# obj = Trie()
# obj.insert(word)
# param_2 = obj.search(word)
# param_3 = obj.startsWith(prefix)

4.7.1496 - 2023-09-17 11:40:01 +0300 MSK

Implement Trie (Prefix Tree)
class Node:
    def __init__(self):
        self.ch, self.is_word = [None] * 128, False

class Trie:

    def __init__(self):
        self.head = Node()

    def insert(self, word: str) -> None:
        cur_node = self.head
        for i in range(len(word)):
            char = ord(word[i])
            if cur_node.ch[char] is None:
                cur_node.ch[char] = Node()
            cur_node = cur_node.ch[char]
        cur_node.is_word = True

    def search(self, word: str) -> bool:
        cur_node = self.head
        for i in range(len(word)):
            char = ord(word[i])
            if cur_node.ch[char] is None:
                return False
            cur_node = cur_node.ch[char]
        
        return cur_node.is_word

    def startsWith(self, prefix: str) -> bool:
        cur_node = self.head
        for i in range(len(prefix)):
            char = ord(prefix[i])
            if cur_node.ch[char] is None:
                return False
            cur_node = cur_node.ch[char]
        
        return True


# Your Trie object will be instantiated and called as such:
# obj = Trie()
# obj.insert(word)
# param_2 = obj.search(word)
# param_3 = obj.startsWith(prefix)

4.7.1497 - 2023-09-16 21:10:06 +0300 MSK

Apply Discount Every n Orders
class Cashier:

    def __init__(self, n: int, discount: int, products: List[int], prices: List[int]):
        self.freq, self.discount = n, (100 - discount) / 100
        self.cur = 0
        self.products = {id: price for id, price in zip(products, prices)}

    def getBill(self, product: List[int], amount: List[int]) -> float:
        self.cur += 1
        total = sum(amount[i] * self.products[product[i]] for i in range(len(product)))
        if self.cur < self.freq:
            return total
        self.cur = 0
        return total * self.discount
        


# Your Cashier object will be instantiated and called as such:
# obj = Cashier(n, discount, products, prices)
# param_1 = obj.getBill(product,amount)

4.7.1498 - 2023-09-16 21:07:33 +0300 MSK

Apply Discount Every n Orders
class Cashier:

    def __init__(self, n: int, discount: int, products: List[int], prices: List[int]):
        self.freq, self.discount = n, (100 - discount) / 100
        self.cur = 0
        self.products = {id: price for id, price in zip(products, prices)}

    def getBill(self, product: List[int], amount: List[int]) -> float:
        self.cur += 1
        multiplier = 1
        if self.cur == self.freq:
            self.cur, multiplier = 0, self.discount
        total = sum(amount[i] * self.products[product[i]] for i in range(len(product)))
        return total * multiplier
        


# Your Cashier object will be instantiated and called as such:
# obj = Cashier(n, discount, products, prices)
# param_1 = obj.getBill(product,amount)

4.7.1499 - 2023-09-16 20:44:34 +0300 MSK

Design Underground System
class UndergroundSystem:

    def __init__(self):
        self.from_to = defaultdict(lambda: defaultdict(list))
        self.in_transit = {}

    def checkIn(self, id: int, stationName: str, t: int) -> None:
        self.in_transit[id] = (stationName, t)

    def checkOut(self, id: int, stationName: str, t: int) -> None:
        station_from, time_from = self.in_transit.pop(id)
        self.from_to[station_from][stationName].append(t - time_from)

    def getAverageTime(self, startStation: str, endStation: str) -> float:
        times = self.from_to[startStation][endStation]
        return sum(times) / len(times)


# Your UndergroundSystem object will be instantiated and called as such:
# obj = UndergroundSystem()
# obj.checkIn(id,stationName,t)
# obj.checkOut(id,stationName,t)
# param_3 = obj.getAverageTime(startStation,endStation)

4.7.1500 - 2023-09-16 20:20:21 +0300 MSK

Design an Ordered Stream
class OrderedStream:

    def __init__(self, n: int):
        self.data = [None]*n
        self.ptr = 0 # 0-indexed 

    def insert(self, id: int, value: str) -> List[str]:
        id -= 1 # 0-indexed 
        self.data[id] = value 
        if id > self.ptr: return [] # not reaching ptr 
        
        while self.ptr < len(self.data) and self.data[self.ptr]: self.ptr += 1 # update self.ptr 
        return self.data[id:self.ptr]



# Your OrderedStream object will be instantiated and called as such:
# obj = OrderedStream(n)
# param_1 = obj.insert(idKey,value)

4.7.1501 - 2023-09-16 20:18:19 +0300 MSK

Design an Ordered Stream
class OrderedStream:

    def __init__(self, n: int):
        self.values = [None] * n
        self.length = n
        self.cur = 0

    def insert(self, idKey: int, value: str) -> List[str]:
        self.values[idKey - 1] = value
        for i in range(self.cur, self.length):
            if self.values[i] is not None:
                continue
            
            self.cur, answer = i, self.values[self.cur:i]
            return answer

        return self.values[self.cur:]



# Your OrderedStream object will be instantiated and called as such:
# obj = OrderedStream(n)
# param_1 = obj.insert(idKey,value)

4.7.1502 - 2023-09-16 15:46:43 +0300 MSK

Design Authentication Manager
class AuthenticationManager:

    def __init__(self, timeToLive: int):
        self.ttl = timeToLive
        self.tokens = {}

    def generate(self, tokenId: str, currentTime: int) -> None:
        self.tokens[tokenId] = currentTime + self.ttl

    def renew(self, tokenId: str, currentTime: int) -> None:
        if currentTime < self.tokens.get(tokenId, currentTime):
            self.generate(tokenId, currentTime)
        else:
            self.tokens.pop(tokenId, None)

    def countUnexpiredTokens(self, currentTime: int) -> int:
        count = 0
        remove_tokens = []
        for token, expir_time in self.tokens.items():
            if currentTime < expir_time:
                count += 1
            else:
                remove_tokens.append(token)
        
        for token in remove_tokens:
            self.tokens.pop(token)
        
        return count


# Your AuthenticationManager object will be instantiated and called as such:
# obj = AuthenticationManager(timeToLive)
# obj.generate(tokenId,currentTime)
# obj.renew(tokenId,currentTime)
# param_3 = obj.countUnexpiredTokens(currentTime)

4.7.1503 - 2023-09-16 15:35:37 +0300 MSK

Seat Reservation Manager
class SeatManager:

    def __init__(self, n: int):
        self.heap = list(range(1, n + 1))  

    def reserve(self) -> int:
        return heappop(self.heap)

    def unreserve(self, seatNumber: int) -> None:
        heappush(self.heap, seatNumber)


# Your SeatManager object will be instantiated and called as such:
# obj = SeatManager(n)
# param_1 = obj.reserve()
# obj.unreserve(seatNumber)

4.7.1504 - 2023-09-16 15:34:15 +0300 MSK

Seat Reservation Manager
class SeatManager:

    def __init__(self, n: int):
        self.heap = list(range(1, n + 1))
        heapify(self.heap)        

    def reserve(self) -> int:
        return heappop(self.heap)

    def unreserve(self, seatNumber: int) -> None:
        heappush(self.heap, seatNumber)


# Your SeatManager object will be instantiated and called as such:
# obj = SeatManager(n)
# param_1 = obj.reserve()
# obj.unreserve(seatNumber)

4.7.1505 - 2023-09-16 11:35:52 +0300 MSK

Simple Bank System
class Bank:

    def __init__(self, balance: List[int]):
        self.balance = balance
        self.size = len(balance)

    def transfer(self, account1: int, account2: int, money: int) -> bool:
        if not 0 < account1 <= self.size or not 0 < account2 <= self.size or (
            self.balance[account1-1] < money
        ):
            return False
        self.balance[account2-1] += money
        self.balance[account1-1] -= money
        return True

    def deposit(self, account: int, money: int) -> bool:
        if not 0 < account <= self.size:
            return False
        self.balance[account-1] += money
        return True

    def withdraw(self, account: int, money: int) -> bool:
        if not 0 < account <= self.size or self.balance[account-1] < money:
            return False
        self.balance[account-1] -= money
        return True


# Your Bank object will be instantiated and called as such:
# obj = Bank(balance)
# param_1 = obj.transfer(account1,account2,money)
# param_2 = obj.deposit(account,money)
# param_3 = obj.withdraw(account,money)

4.7.1506 - 2023-09-16 11:25:54 +0300 MSK

Path With Minimum Effort
class Solution:

    def minimumEffortPath(self, heights: List[List[int]]) -> int:
        rows, cols = len(heights), len(heights[0])
        directions = [(0, 1), (0, -1), (1, 0), (-1, 0)]
        dist = [[math.inf for _ in range(cols)] for _ in range(rows)]
        dist[0][0] = 0
        minHeap = [(0, 0, 0)] 
        while minHeap:
            effort, x, y = heappop(minHeap)
            if x == rows - 1 and y == cols - 1:
                return effort
            for dx, dy in directions:
                nx, ny = x + dx, y + dy
                if 0 <= nx < rows and 0 <= ny < cols:
                    new_effort = max(effort, abs(heights[x][y] - heights[nx][ny]))
                    if new_effort < dist[nx][ny]:
                        dist[nx][ny] = new_effort
                        heappush(minHeap, (new_effort, nx, ny))

4.7.1507 - 2023-09-15 19:59:56 +0300 MSK

Design a Number Container System
class NumberContainers:

    def __init__(self):
        self.num_indices = defaultdict(list)
        self.num_at_index = {}
        

    def change(self, index: int, number: int) -> None:
        self.num_at_index[index] = number
        heapq.heappush(self.num_indices[number], index)
        

    def find(self, number: int) -> int:
        while self.num_indices[number] and self.num_at_index[self.num_indices[number][0]] != number:
            heapq.heappop(self.num_indices[number])
        
        return self.num_indices[number][0] if len(self.num_indices[number]) > 0 else -1
        


# Your NumberContainers object will be instantiated and called as such:
# obj = NumberContainers()
# obj.change(index,number)
# param_2 = obj.find(number)

4.7.1508 - 2023-09-15 19:53:02 +0300 MSK

Design a Number Container System
import sortedcontainers

class NumberContainers:

    def __init__(self):
        self._idx_number = {}
        self._number_idx = defaultdict(sortedcontainers.SortedSet)

    def change(self, index: int, number: int) -> None:
        cur_number = self._idx_number.get(index, -1)
        if cur_number != -1:
            self._number_idx[cur_number].remove(index)
        self._idx_number[index] = number
        self._number_idx[number].add(index)

    def find(self, number: int) -> int:
        ids = self._number_idx[number]
        return ids[0] if ids else -1


# Your NumberContainers object will be instantiated and called as such:
# obj = NumberContainers()
# obj.change(index,number)
# param_2 = obj.find(number)

4.7.1509 - 2023-09-15 19:34:44 +0300 MSK

Finding Pairs With a Certain Sum
class FindSumPairs:

    def __init__(self, nums1: List[int], nums2: List[int]):
        self._nums1, self._nums2, self._nums2_raw = Counter(nums1), Counter(nums2), nums2

    def add(self, index: int, val: int) -> None:
        nums2_raw, nums2 = self._nums2_raw, self._nums2
        cur_val = nums2_raw[index]
        new_val = cur_val + val
        if nums2[cur_val] > 0:
            nums2[cur_val] -= 1
        
        nums2_raw[index] = new_val
        nums2[new_val] += 1

    def count(self, tot: int) -> int:       
        return sum(num1_count * self._nums2.get(tot - num1, 0) 
                   for num1, num1_count in self._nums1.items())


# Your FindSumPairs object will be instantiated and called as such:
# obj = FindSumPairs(nums1, nums2)
# obj.add(index,val)
# param_2 = obj.count(tot)

4.7.1510 - 2023-09-15 19:33:23 +0300 MSK

Finding Pairs With a Certain Sum
class FindSumPairs:

    def __init__(self, nums1: List[int], nums2: List[int]):
        self._nums1, self._nums2, self._nums2_raw = Counter(nums1), Counter(nums2), nums2

    def add(self, index: int, val: int) -> None:
        nums2_raw, nums2 = self._nums2_raw, self._nums2
        cur_val = nums2_raw[index]
        new_val = cur_val + val
        if nums2[cur_val] > 0:
            nums2[cur_val] -= 1
        
        nums2_raw[index] = new_val
        nums2[new_val] += 1

    def count(self, tot: int) -> int:
        sum_count = 0
        nums2 = self._nums2
        for num1, num1_count in self._nums1.items():
            sum_count += num1_count * nums2.get(tot - num1, 0) 

        return sum_count


# Your FindSumPairs object will be instantiated and called as such:
# obj = FindSumPairs(nums1, nums2)
# obj.add(index,val)
# param_2 = obj.count(tot)

4.7.1511 - 2023-09-15 19:12:52 +0300 MSK

Design Browser History
class BrowserHistory:

    def __init__(self, homepage: str):
        self._history = [homepage]
        self._cur = 0

    def visit(self, url: str) -> None:
        self._history[self._cur+1:] = (url, )
        self._cur += 1

    def back(self, steps: int) -> str:
        self._cur = max(0, self._cur - steps)
        return self._history[self._cur]

    def forward(self, steps: int) -> str:
        self._cur = min(len(self._history) - 1, self._cur + steps)
        return self._history[self._cur]


# Your BrowserHistory object will be instantiated and called as such:
# obj = BrowserHistory(homepage)
# obj.visit(url)
# param_2 = obj.back(steps)
# param_3 = obj.forward(steps)

4.7.1512 - 2023-09-15 19:05:16 +0300 MSK

Design a Stack With Increment Operation
class CustomStack:

    def __init__(self, maxSize: int):
        self._stack = []
        self._max_size = maxSize

    def push(self, x: int) -> None:
        if len(self._stack) != self._max_size:
            self._stack.append(x)

    def pop(self) -> int:
        return self._stack.pop() if self._stack else -1 
        
    def increment(self, k: int, val: int) -> None:
        for i in range(min(k, len(self._stack))):
            self._stack[i] += val


# Your CustomStack object will be instantiated and called as such:
# obj = CustomStack(maxSize)
# obj.push(x)
# param_2 = obj.pop()
# obj.increment(k,val)

4.7.1513 - 2023-09-15 19:02:42 +0300 MSK

Design a Stack With Increment Operation
class CustomStack:

    def __init__(self, maxSize: int):
        self._stack = []
        self._max_size = maxSize
        self._size = 0

    def push(self, x: int) -> None:
        if self._size == self._max_size:
            return
        self._stack.append(x)
        self._size += 1

    def pop(self) -> int:
        if self._size == 0:
            return -1
        last = self._stack.pop()
        self._size -= 1
        return last

    def increment(self, k: int, val: int) -> None:
        for i in range(min(k, self._size)):
            self._stack[i] += val


# Your CustomStack object will be instantiated and called as such:
# obj = CustomStack(maxSize)
# obj.push(x)
# param_2 = obj.pop()
# obj.increment(k,val)

4.7.1514 - 2023-09-15 18:53:00 +0300 MSK

Design Linked List
class Node:
    def __init__(self, val: int = 0, prev_node: 'Node' = None, next_node: 'Node' = None):
        self.val, self.prev, self.next = val, prev_node, next_node

class MyLinkedList:

    def __init__(self):
        self._head, self._tail = Node(float("-inf")), Node(float("inf"))
        self._head.next, self._tail.prev = self._tail, self._head
        self._length = 0

    def _getNode(self, index: int) -> Node:
        if not 0 <= index < self._length:
            return None
        if index == 0:
            return self._head.next
        if index == self._length - 1:
            return self._tail.prev

        cur_idx, cur_node = 0, self._head.next
        while cur_idx < index:
            cur_node = cur_node.next
            cur_idx += 1

        return cur_node
    
    def get(self, index: int) -> int:
        node = self._getNode(index)
        return node.val if node else -1

    def addAtHead(self, val: int) -> None:
        old_first = self._head.next
        new_node = Node(val, self._head, old_first)
        self._head.next, old_first.prev = new_node, new_node
        self._length += 1

    def addAtTail(self, val: int) -> None:
        old_tail = self._tail.prev
        new_node = Node(val, old_tail, self._tail)
        self._tail.prev, old_tail.next = new_node, new_node
        self._length += 1

    def addAtIndex(self, index: int, val: int) -> None:
        if not 0 <= index <= self._length:
            return
        if index == 0:
            self.addAtHead(val)
            return
        if index == self._length:
            self.addAtTail(val)
            return
        
        target_node = self._getNode(index)
        prev_node = target_node.prev
        new_node = Node(val, prev_node, target_node)
        prev_node.next, target_node.prev = new_node, new_node
        self._length += 1

    def deleteAtIndex(self, index: int) -> None:
        if not 0 <= index < self._length:
            return
        
        target_node = self._getNode(index)
        old_prev, old_next = target_node.prev, target_node.next
        old_prev.next, old_next.prev = old_next, old_prev
        self._length -= 1

# Your MyLinkedList object will be instantiated and called as such:
# obj = MyLinkedList()
# param_1 = obj.get(index)
# obj.addAtHead(val)
# obj.addAtTail(val)
# obj.addAtIndex(index,val)
# obj.deleteAtIndex(index)

4.7.1515 - 2023-09-15 17:07:59 +0300 MSK

Range Sum Query 2D - Immutable
class NumMatrix:

    def __init__(self, matrix: List[List[int]]):
        self.dp=[[0] * (len(matrix[0])+1) for _ in range(len(matrix)+1)]
        
		# calculate prefix sum
        for r in range(len(self.dp)-1):
            for c in range(len(self.dp[0])-1):
                self.dp[r+1][c+1]=matrix[r][c] + self.dp[r][c+1] + self.dp[r+1][c] - self.dp[r][c]
        
    def sumRegion(self, row1: int, col1: int, row2: int, col2: int) -> int:
        return self.dp[row2+1][col2+1] - self.dp[row1][col2+1] - self.dp[row2+1][col1] + self.dp[row1][col1]
                

4.7.1516 - 2023-09-15 12:51:11 +0300 MSK

Peeking Iterator
# Below is the interface for Iterator, which is already defined for you.
#
# class Iterator:
#     def __init__(self, nums):
#         """
#         Initializes an iterator object to the beginning of a list.
#         :type nums: List[int]
#         """
#
#     def hasNext(self):
#         """
#         Returns true if the iteration has more elements.
#         :rtype: bool
#         """
#
#     def next(self):
#         """
#         Returns the next element in the iteration.
#         :rtype: int
#         """

class PeekingIterator:
    def __init__(self, iterator):
        """
        Initialize your data structure here.
        :type iterator: Iterator
        """
        self._iter = iterator
        self._next = iterator.next()
        

    def peek(self):
        """
        Returns the next element in the iteration without advancing the iterator.
        :rtype: int
        """
        return self._next
        

    def next(self):
        """
        :rtype: int
        """
        cur_next = self._next
        self._next = self._iter.next() if self._iter.hasNext() else None
        return cur_next
        

    def hasNext(self):
        """
        :rtype: bool
        """
        return self._next is not None
        

# Your PeekingIterator object will be instantiated and called as such:
# iter = PeekingIterator(Iterator(nums))
# while iter.hasNext():
#     val = iter.peek()   # Get the next element but not advance the iterator.
#     iter.next()         # Should return the same value as [val].

4.7.1517 - 2023-09-15 09:59:15 +0300 MSK

Min Cost to Connect All Points
def manhattan_distance(p1: List[int], p2: List[int]) -> int:
    return abs(p1[0] - p2[0]) + abs(p1[1] - p2[1])

class Solution:
    def minCostConnectPoints(self, points: List[List[int]]) -> int:
        n = len(points)
        visited = [False] * n
        heap_dict = {0: 0}  
        min_heap = [(0, 0)]
        
        mst_weight = 0
        
        while min_heap:
            w, u = heappop(min_heap)
            
            if visited[u] or heap_dict.get(u, float('inf')) < w:
                continue
            
            visited[u] = True
            mst_weight += w
            
            for v in range(n):
                if not visited[v]:
                    new_distance = manhattan_distance(points[u], points[v])
      
                    if new_distance < heap_dict.get(v, float('inf')):
                        heap_dict[v] = new_distance
                        heappush(min_heap, (new_distance, v))
        
        return mst_weight

4.7.1518 - 2023-09-14 19:02:15 +0300 MSK

Frequency Tracker
class FrequencyTracker:

    def __init__(self):
        self._num_freq = defaultdict(int)
        self._freq_nums = defaultdict(set)    

    def add(self, number: int) -> None:
        cur_freq = self._num_freq[number]
        self._num_freq[number] = cur_freq + 1
        self._freq_nums[cur_freq].discard(number)
        self._freq_nums[cur_freq + 1].add(number)

    def deleteOne(self, number: int) -> None:
        cur_freq = self._num_freq[number]
        if cur_freq == 0:
            return    
        self._num_freq[number] = cur_freq - 1 
        self._freq_nums[cur_freq].discard(number)
        if cur_freq != 1:
            self._freq_nums[cur_freq - 1].add(number)

    def hasFrequency(self, frequency: int) -> bool:
        return len(self._freq_nums[frequency]) != 0


# Your FrequencyTracker object will be instantiated and called as such:
# obj = FrequencyTracker()
# obj.add(number)
# obj.deleteOne(number)
# param_3 = obj.hasFrequency(frequency)

4.7.1519 - 2023-09-14 18:45:02 +0300 MSK

Design an ATM Machine
class ATM:

    def __init__(self):
        self._banknotes = (0, ) * 5
        self._values = (20, 50, 100, 200, 500)

    def deposit(self, banknotesCount: List[int]) -> None:
        self._banknotes = tuple(banknotesCount[i] + self._banknotes[i] for i in range(5))

    def withdraw(self, amount: int) -> List[int]:
        withdrawn = [0] * 5
        for i in reversed(range(5)):
            value, notes_left = self._values[i], self._banknotes[i]
            notes_need = min(notes_left, amount // value)
            
            if notes_need == 0:
                continue
            
            amount -= value * notes_need
            withdrawn[i] = notes_need

            if amount == 0:
                self._banknotes = tuple(self._banknotes[i] - withdrawn[i] 
                                        for i in range(5))
                return withdrawn

        return (-1, )


# Your ATM object will be instantiated and called as such:
# obj = ATM()
# obj.deposit(banknotesCount)
# param_2 = obj.withdraw(amount)

4.7.1520 - 2023-09-14 18:44:27 +0300 MSK

Design an ATM Machine
class ATM:

    def __init__(self):
        self._banknotes = (0, ) * 5
        self._values = (20, 50, 100, 200, 500)

    def deposit(self, banknotesCount: List[int]) -> None:
        self._banknotes = tuple(banknotesCount[i] + self._banknotes[i] for i in range(5))

    def withdraw(self, amount: int) -> List[int]:
        withdrawn = [0] * 5
        for i in reversed(range(5)):
            value, notes_left = self._values[i], self._banknotes[i]
            notes_need = min(notes_left, amount // value)
            
            if notes_need == 0:
                continue
            
            amount -= value * notes_need
            withdrawn[i] = notes_need

            if amount == 0:
                self._banknotes = tuple(self._banknotes[i] - withdrawn[i] 
                                        for i in range(5))
                return withdrawn

        return (-1, )


# Your ATM object will be instantiated and called as such:
# obj = ATM()
# obj.deposit(banknotesCount)
# param_2 = obj.withdraw(amount)

4.7.1521 - 2023-09-14 18:40:55 +0300 MSK

Design an ATM Machine
class ATM:

    def __init__(self):
        self._banknotes = [0] * 5
        self._values = (20, 50, 100, 200, 500)

    def deposit(self, banknotesCount: List[int]) -> None:
        for i in range(5):
            self._banknotes[i] += banknotesCount[i]

    def withdraw(self, amount: int) -> List[int]:
        withdrawn = [0] * 5
        for i in reversed(range(5)):
            value, notes_left = self._values[i], self._banknotes[i]
            notes_need = min(notes_left, amount // value)
            
            if notes_need == 0:
                continue
            
            amount -= value * notes_need
            withdrawn[i] = notes_need

            if amount == 0:
                for i in range(5):
                    self._banknotes[i] -= withdrawn[i]
                return withdrawn

        return [-1]


# Your ATM object will be instantiated and called as such:
# obj = ATM()
# obj.deposit(banknotesCount)
# param_2 = obj.withdraw(amount)

4.7.1522 - 2023-09-14 18:08:10 +0300 MSK

Design Memory Allocator
class Allocator:

    def __init__(self, n: int):
      self._units = [1] * n
      self._units[0] = n
      self._id_units = defaultdict(list)
      self._units_count = n

    def find_avail_units(self, start: int, size: int) -> Tuple[int, int]:
        i = start
        count = 0
        while i < self._units_count and i - start < size:
            units_avail = self._units[i]
            if units_avail < 0:
                return i + units_avail if i == start else i, count
            i += units_avail
            count += units_avail

        return i, count
            

    def allocate(self, size: int, mID: int) -> int:
        i = 0
        units_start, units_count = None, 0
        while i < self._units_count and units_count < size:
            units_avail = self._units[i]
            if units_avail < 0:
                i += -units_avail
                units_start, units_count = None, 0
                continue

            if units_start is None:
                units_start = i
            units_count += units_avail
            i += units_avail

        if units_count < size:
            return -1 

        self._units[units_start] = -size
        if units_count > size:
            self._units[units_start + size] = units_count - size
        self._id_units[mID].append(units_start)
        return units_start

    def free(self, mID: int) -> int:
        count = 0
        conseq_units = self._id_units[mID]
        while conseq_units:
            units_start = conseq_units.pop()
            units_freed = -self._units[units_start]
            count += units_freed
            self._units[units_start] = units_freed

        return count


# Your Allocator object will be instantiated and called as such:
# obj = Allocator(n)
# param_1 = obj.allocate(size,mID)
# param_2 = obj.free(mID)

4.7.1523 - 2023-09-14 14:41:43 +0300 MSK

Reconstruct Itinerary
class Solution:
    def findItinerary(self, tickets: List[List[str]]) -> List[str]:
        graph = defaultdict(list)
        
        for src, dst in sorted(tickets, reverse=True):
            graph[src].append(dst)
            
        itinerary = []
        def dfs(airport: str) -> None:
            while graph[airport]:
                dfs(graph[airport].pop())
            
            itinerary.append(airport)
        
        dfs("JFK")
        
        return itinerary[::-1]

4.7.1524 - 2023-09-13 19:20:05 +0300 MSK

Detect Squares
class DetectSquares:

    def __init__(self):
        self._row_col = defaultdict(lambda: defaultdict(int))

    def add(self, point: List[int]) -> None:
        self._row_col[point[0]][point[1]] += 1

    def count(self, point: List[int]) -> int:
        ways_count = 0
        row1, col1 = point
        for col2, col2_count in self._row_col[row1].items():
            if col2 == col1:
                continue

            side = col2 - col1
            for row2 in (row1 + side, row1 - side):
                point3_count = self._row_col[row2][col1]
                point4_count = self._row_col[row2][col2]
                ways_count += col2_count * point3_count * point4_count

        return ways_count

# Your DetectSquares object will be instantiated and called as such:
# obj = DetectSquares()
# obj.add(point)
# param_2 = obj.count(point)

4.7.1525 - 2023-09-13 11:18:48 +0300 MSK

Candy
class Solution:
    def candy(self, ratings: List[int]) -> int:
        child_count = len(ratings)
        candies = [1] * child_count 

        for i in range(1, child_count):
            if ratings[i] > ratings[i-1]:
                candies[i] = candies[i-1] + 1

        for i in reversed(range(child_count - 1)):
            if ratings[i] > ratings[i+1]:
                candies[i] = max(candies[i], candies[i+1] + 1)
        
        return sum(candies)

4.7.1526 - 2023-09-12 19:36:36 +0300 MSK

Tweet Counts Per Frequency
class TweetCounts:

    def __init__(self):
        self._tweets = defaultdict(list)
        self._chunk_ranges = {
            "minute": 60, 
            "hour": 3600, 
            "day": 86400
        }

    def recordTweet(self, tweetName: str, time: int) -> None:
        self._tweets[tweetName].append(time)

    def getTweetCountsPerFrequency(self, freq: str, tweetName: str, startTime: int, endTime: int) -> List[int]:
        chunk_range = self._chunk_ranges[freq]
        chunks = [0] * (1 + (endTime - startTime) // chunk_range)

        for tweet in self._tweets[tweetName]:
            if not startTime <= tweet <= endTime:
                continue
            chunks[(tweet - startTime) // chunk_range] += 1
        
        return chunks




# Your TweetCounts object will be instantiated and called as such:
# obj = TweetCounts()
# obj.recordTweet(tweetName,time)
# param_2 = obj.getTweetCountsPerFrequency(freq,tweetName,startTime,endTime)

4.7.1527 - 2023-09-12 16:32:10 +0300 MSK

Snapshot Array
class SnapshotArray:

    def __init__(self, length: int):
        self._cur_snap = 0
        self._elems = [[(0, 0)] for _ in range(length)]

    def set(self, index: int, val: int) -> None:
        values = self._elems[index]
        if values[-1][0] == self._cur_snap:
            values.pop()
        values.append((self._cur_snap, val))

    def snap(self) -> int:
        self._cur_snap += 1
        return self._cur_snap - 1 

    def get(self, index: int, snap_id: int) -> int:
        for cur_snap_id, val in reversed(self._elems[index]):
            if cur_snap_id > snap_id:
                continue
            return val
        
        return -1
        


# Your SnapshotArray object will be instantiated and called as such:
# obj = SnapshotArray(length)
# obj.set(index,val)
# param_2 = obj.snap()
# param_3 = obj.get(index,snap_id)

4.7.1528 - 2023-09-12 15:42:35 +0300 MSK

Time Based Key-Value Store
class TimeMap:

    def __init__(self):
        self._cache = defaultdict(list)
        

    def set(self, key: str, value: str, timestamp: int) -> None:
        self._cache[key].append((timestamp, value))

    def get(self, key: str, timestamp: int) -> str:
        for cur_timestamp, value in reversed(self._cache[key]):
            if cur_timestamp > timestamp:
                continue
            return value

        return ""

# Your TimeMap object will be instantiated and called as such:
# obj = TimeMap()
# obj.set(key,value,timestamp)
# param_2 = obj.get(key,timestamp)

4.7.1529 - 2023-09-12 15:27:56 +0300 MSK

Design Parking System
class ParkingSystem:

    def __init__(self, big: int, medium: int, small: int):
        self._slots = [0, big, medium, small]

    def addCar(self, carType: int) -> bool:
        slots_avail = self._slots[carType]
        if not slots_avail:
            return False
        self._slots[carType] = slots_avail - 1
        return True


# Your ParkingSystem object will be instantiated and called as such:
# obj = ParkingSystem(big, medium, small)
# param_1 = obj.addCar(carType)

4.7.1530 - 2023-09-12 15:23:56 +0300 MSK

Design Parking System
class ParkingSystem:

    def __init__(self, big: int, medium: int, small: int):
        self._slots = [big, medium, small]

    def addCar(self, carType: int) -> bool:
        if self._slots[carType-1] == 0:
            return False
        self._slots[carType-1] -= 1
        return True


# Your ParkingSystem object will be instantiated and called as such:
# obj = ParkingSystem(big, medium, small)
# param_1 = obj.addCar(carType)

4.7.1531 - 2023-09-12 15:21:06 +0300 MSK

Number of Recent Calls
class RecentCounter:

    def __init__(self):
        self._queue = deque()

    def ping(self, t: int) -> int:
        self._queue.append(t)
        while self._queue:
            if t - self._queue[0] > 3000:
                self._queue.popleft()
            else:
                break

        return len(self._queue) 


# Your RecentCounter object will be instantiated and called as such:
# obj = RecentCounter()
# param_1 = obj.ping(t)

4.7.1532 - 2023-09-12 14:23:58 +0300 MSK

Range Sum Query - Immutable
class NumArray:

    def __init__(self, nums: List[int]):
        self._sums = tuple(accumulate(nums))

    def sumRange(self, left: int, right: int) -> int:
        # [-2, 0, 3, -5, 2, -1], [-2, -2, 1, -4, -2, -3]
        # [0, 2] -> 1
        if left == 0:
            return self._sums[right]

        return self._sums[right] - self._sums[left-1]


# Your NumArray object will be instantiated and called as such:
# obj = NumArray(nums)
# param_1 = obj.sumRange(left,right)

4.7.1533 - 2023-09-12 14:12:53 +0300 MSK

Range Sum Query - Immutable
class NumArray:

    def __init__(self, nums: List[int]):
        self._nums = nums

    @cache
    def sumRange(self, left: int, right: int) -> int:
        if right == left:
            return self._nums[left]
        if right - left == 1:
            return self._nums[right] + self._nums[left]
        mid = left + (right - left) // 2
        return self.sumRange(left, mid) + self.sumRange(mid + 1, right)


# Your NumArray object will be instantiated and called as such:
# obj = NumArray(nums)
# param_1 = obj.sumRange(left,right)

4.7.1534 - 2023-09-12 14:07:17 +0300 MSK

Range Sum Query - Immutable
class NumArray:

    def __init__(self, nums: List[int]):
        self._nums = nums

    def sumRange(self, left: int, right: int) -> int:
        return sum(self._nums[left:right+1])


# Your NumArray object will be instantiated and called as such:
# obj = NumArray(nums)
# param_1 = obj.sumRange(left,right)

4.7.1535 - 2023-09-12 14:05:44 +0300 MSK

Binary Search Tree Iterator
# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class BSTIterator:

    def __init__(self, root: Optional[TreeNode]):
        def generate(node: TreeNode) -> int:
            if not node:
                return
            yield from generate(node.left)
            yield node
            yield from generate(node.right)

        self._generate = generate(root)
        self._next = next(self._generate)

    def next(self) -> int:
        next_val = self._next.val
        self._next = next(self._generate, None)
        return next_val 

    def hasNext(self) -> bool:
        return self._next is not None


# Your BSTIterator object will be instantiated and called as such:
# obj = BSTIterator(root)
# param_1 = obj.next()
# param_2 = obj.hasNext()

4.7.1536 - 2023-09-12 14:05:12 +0300 MSK

Binary Search Tree Iterator
# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class BSTIterator:

    def __init__(self, root: Optional[TreeNode]):
        def generate(node: TreeNode) -> int:
            if not node:
                return
            yield from generate(node.left)
            yield node
            yield from generate(node.right)

        self._generate = generate(root)
        self._next = next(self._generate)

    def next(self) -> int:
        next_val = self._next.val
        self._next = next(self._generate, None)
        return next_val 

    def hasNext(self) -> bool:
        return not self._next is None


# Your BSTIterator object will be instantiated and called as such:
# obj = BSTIterator(root)
# param_1 = obj.next()
# param_2 = obj.hasNext()

4.7.1537 - 2023-09-12 14:01:45 +0300 MSK

Binary Search Tree Iterator
# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class BSTIterator:

    def __init__(self, root: Optional[TreeNode]):
        self._stack = []
        while root:
            self._stack.append(root)
            root = root.left

    def next(self) -> int:
        node = self._stack.pop()
        right = node.right
        while right:
            self._stack.append(right)
            right = right.left
        
        return node.val

    def hasNext(self) -> bool:
        return self._stack


# Your BSTIterator object will be instantiated and called as such:
# obj = BSTIterator(root)
# param_1 = obj.next()
# param_2 = obj.hasNext()

4.7.1538 - 2023-09-12 11:17:46 +0300 MSK

Balanced Binary Tree
# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def isBalanced(self, root: Optional[TreeNode]) -> bool:
        def get_height(node: TreeNode) -> int:
            if not node:
                return 0
            
            h_left = get_height(node.left)
            if h_left < 0:
                return -1
            h_right = get_height(node.right)
            if h_right < 0 or abs(h_left - h_right) > 1:
                return -1

            return max(h_left, h_right) + 1
        
        return get_height(root) >= 0

4.7.1539 - 2023-09-12 10:55:04 +0300 MSK

Minimum Deletions to Make Character Frequencies Unique
class Solution:
    def minDeletions(self, s: str) -> int:
        length = len(s)
        char_count = Counter(s)
        counts = set()
        deleted_chars = 0

        for char, count in char_count.items():
            while count != 0 and count in counts:
                count -= 1
                deleted_chars += 1
            if count != 0:
                counts.add(count)
            
        return deleted_chars

4.7.1540 - 2023-09-11 19:32:16 +0300 MSK

Intersection of Two Linked Lists
class Solution:
    def getIntersectionNode(self, headA: ListNode, headB: ListNode) -> Optional[ListNode]:
        if not headA or not headB:
            return None
        
        tail1, tail2 = headA, headB
        while tail1 != tail2:
            tail1 = tail1.next if tail1 else headB
            tail2 = tail2.next if tail2 else headA
        
        return tail2
    

4.7.1541 - 2023-09-11 19:31:11 +0300 MSK

Intersection of Two Linked Lists
class Solution:
    def getIntersectionNode(self, headA: ListNode, headB: ListNode) -> Optional[ListNode]:
        if headA and headB:
            A, B = headA, headB
            while A != B:
                A = A.next if A else headB
                B = B.next if B else headA
            return B
        

4.7.1542 - 2023-09-11 19:16:39 +0300 MSK

Pascal’s Triangle II
class Solution:
    def getRow(self, rowIndex: int) -> List[int]:
        prev_row = (1,)
        
        for i in range(1, rowIndex + 1):
            prev_row = (1, *(prev_row[j] + prev_row[j+1] for j in range(len(prev_row) - 1)), 1)
        
        return prev_row

4.7.1543 - 2023-09-11 19:06:00 +0300 MSK

Single Number
class Solution:
    def singleNumber(self, nums: List[int]) -> int:
        return reduce(xor, nums)

4.7.1544 - 2023-09-11 18:58:15 +0300 MSK

Single Number
class Solution:
    def singleNumber(self, nums: List[int]) -> int:
        return reduce(lambda total, element: total ^ element, nums)

4.7.1545 - 2023-09-11 18:55:49 +0300 MSK

Single Number
class Solution:
    def singleNumber(self, nums: List[int]) -> int:
        nums_count = len(nums)
        if nums_count == 1:
            return nums[0]
        
        nums.sort()
        for i in range(0, nums_count, 2):
            if i + 1 == nums_count:
                return nums[i]

            cur_num, next_num = nums[i], nums[i+1]
            if cur_num == next_num:
                continue
            
            return cur_num
        
        return 0

4.7.1546 - 2023-09-11 18:46:11 +0300 MSK

Minimum Depth of Binary Tree
# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def minDepth(self, root: Optional[TreeNode]) -> int:
        
        def dfs(node: TreeNode) -> int:
            if not node:
                return 0

            return 1 + min((depth for depth in (dfs(node.left), dfs(node.right)) if depth > 0),
                           default=0)

        return dfs(root)

4.7.1547 - 2023-09-11 18:31:16 +0300 MSK

Binary Tree Inorder Traversal
# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def inorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
        def get_nodes(root: TreeNode) -> Generator[None, None, TreeNode]:
            if not root:
                return

            yield from get_nodes(root.left)
            yield root.val
            yield from get_nodes(root.right)
        
        return tuple(get_nodes(root))

4.7.1548 - 2023-09-11 18:30:56 +0300 MSK

Binary Tree Inorder Traversal
# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def inorderTraversal(self, root: Optional[TreeNode]) -> List[int]:
        def get_nodes(root: TreeNode) -> Generator[None, None, TreeNode]:
            if not root:
                return

            if root.left:
                yield from get_nodes(root.left)
            
            yield root.val

            if root.right:
                yield from get_nodes(root.right)
        
        return tuple(get_nodes(root))

4.7.1549 - 2023-09-11 15:06:55 +0300 MSK

Group the People Given the Group Size They Belong To
class Solution:
    def groupThePeople(self, groupSizes: List[int]) -> List[List[int]]:
        answer = []
        cur_groups = defaultdict(list)
        
        for i in range(len(groupSizes)):
            size = groupSizes[i]
            group = cur_groups[size]
            group.append(i)
            if len(group) == size:
                answer.append(group)
                del cur_groups[size]
        
        return answer

4.7.1550 - 2023-09-10 12:48:15 +0300 MSK

Count All Valid Pickup and Delivery Options
class Solution:
    def countOrders(self, n: int) -> int:
        # P1, D1                 [01] -> (P1, D1)
        # P1, D1, P2, D2         [06] -> (P1, P2, D1, D2), (P1, P2, D2, D1), 
        #                                (P1, D1, P2, D2), (P2, P1, D1, D2), 
        #                                (P2, P1, D2, D1), (P2, D2, P1, D1).
        # P1, D1, P2, D2, P3, D3 [90]
        
        ways_count = 1
        mod = 10**9 + 7
        for order in range(2, n + 1):
            pos_avail_count = 1 + (order - 1) * 2
            cur_ways_count = pos_avail_count * (pos_avail_count + 1) // 2
            ways_count = (ways_count * cur_ways_count) % mod

        return ways_count

4.7.1551 - 2023-09-10 12:37:39 +0300 MSK

Count All Valid Pickup and Delivery Options
class Solution:
    def countOrders(self, n: int) -> int:
        # P1, D1                 [01] -> (P1, D1)
        # P1, D1, P2, D2         [06] -> (P1, P2, D1, D2), (P1, P2, D2, D1), 
        #                                (P1, D1, P2, D2), (P2, P1, D1, D2), 
        #                                (P2, P1, D2, D1), (P2, D2, P1, D1).
        # P1, D1, P2, D2, P3, D3 [90]
        
        ways_count = 1
        for order in range(2, n + 1):
            avail_pos_count = 1 + (order - 1) * 2
            ways_count *= sum(avail_pos_count - pos for pos in range(avail_pos_count))

        return ways_count % (10**9 + 7)

4.7.1552 - 2023-09-09 20:12:03 +0300 MSK

Decode Ways
class Solution:
    def numDecodings(self, s: str) -> int:
        char_count = len(s)

        @cache
        def dfs(i: int) -> int:
            if i == char_count: 
                return 1
            if s[i] == "0": 
                return 0
            return dfs(i + 1) + (
                dfs(i + 2) if i + 1 < char_count and s[i:i+2] < "27" else 0
            )

        return dfs(0)

4.7.1553 - 2023-09-09 20:11:23 +0300 MSK

Decode Ways
class Solution:
    def numDecodings(self, s: str) -> int:
        char_count = len(s)

        @cache
        def dfs(i: int) -> int:
            if i == char_count: 
                return 1
            if s[i] == "0": 
                return 0
            return dfs(i + 1) + (dfs(i + 2) if i + 1 < char_count and s[i:i+2] < "27" else 0)

        return dfs(0)

4.7.1554 - 2023-09-09 20:10:19 +0300 MSK

Decode Ways
class Solution:
    def numDecodings(self, s: str) -> int:
        char_count = len(s)

        @cache
        def dfs(i: int) -> int:
            if i == char_count: 
                return 1
            if s[i] == "0": 
                return 0
            ways_count = dfs(i + 1)
            if i + 1 < char_count and s[i:i+2] < "27":
                ways_count += dfs(i + 2)
            return ways_count

        return dfs(0)

4.7.1555 - 2023-09-09 16:06:56 +0300 MSK

Snakes and Ladders
class Solution:
    def snakesAndLadders(self, board: List[List[int]]) -> int:
        n = len(board)
        board.reverse()

        def intToPos(square):
            r = (square - 1) // n
            c = (square - 1) % n
            if r % 2:
                c = n - 1 - c
            return [r, c]

        q = deque()
        q.append([1, 0]) 
        visit = set()
        while q:
            square, moves = q.popleft()
            for i in range(1, 7):
                nextSquare = square + i
                r, c = intToPos(nextSquare)
                if board[r][c] != -1:
                    nextSquare = board[r][c]
                if nextSquare == n * n:
                    return moves + 1
                if nextSquare not in visit:
                    visit.add(nextSquare)
                    q.append([nextSquare, moves + 1])
        return -1

4.7.1556 - 2023-09-09 10:20:58 +0300 MSK

Combination Sum IV
class Solution:
    def combinationSum4(self, nums: List[int], target: int) -> int:

        @cache
        def dp(cur_sum: int) -> int:
            if cur_sum == target:
                return 1
            if cur_sum > target:
                return 0
            
            return sum(dp(cur_sum + num) for num in nums)

        return dp(0)
            

4.7.1557 - 2023-09-09 10:20:26 +0300 MSK

Combination Sum IV
class Solution:
    def combinationSum4(self, nums: List[int], target: int) -> int:

        @cache
        def backtrack(cur_sum: int) -> int:
            if cur_sum == target:
                return 1
            if cur_sum > target:
                return 0
            
            return sum(backtrack(cur_sum + num) for num in nums)

        return backtrack(0)
            

4.7.1558 - 2023-09-08 13:41:10 +0300 MSK

Pascal’s Triangle
class Solution:
    def generate(self, numRows: int) -> List[List[int]]:
        answer = [[1]]
        numRows -= 1

        while numRows > 0:
            cur, prev = [1], answer[-1]
            for i in range(len(prev) - 1):
                cur.append(prev[i] + prev[i+1])
            cur.append(1)
            answer.append(cur)
            numRows -= 1
        
        return answer

4.7.1559 - 2023-09-07 20:09:04 +0300 MSK

Word Search
class Solution:
    def exist(self, board: List[List[str]], word: str) -> bool:
        row_count, col_count = len(board), len(board[0])
        word_length = len(word)
        delta = ((0, 1), (0, -1), (1, 0), (-1, 0))

        if word_length == 1:
            return any(word in row for row in board)
        if word_length > row_count * col_count:
            return False

        visited = set()

        def backtrack(row: int, col: int, target: int) -> bool:
            if target == word_length:
                return True
            if not 0 <= row < row_count or not 0 <= col < col_count or (
                (row, col) in visited or board[row][col] != word[target]
            ):
                return False

            visited.add((row, col))
            answer = any(backtrack(row + delta_row, col + delta_col, target + 1)
                         for delta_row, delta_col in delta)
            visited.remove((row, col))
            return answer

        return any(backtrack(row, col, 0) 
                   for row in range(row_count) 
                   for col in range(col_count))

4.7.1560 - 2023-09-07 20:00:09 +0300 MSK

Word Search
class Solution:
    def exist(self, board: List[List[str]], word: str) -> bool:
        row_count, col_count = len(board), len(board[0])
        word_length = len(word)
        delta = ((0, 1), (0, -1), (1, 0), (-1, 0))

        if word_length == 1:
            return any(word in row for row in board)

        def backtrack(row: int, col: int, visited: Set, target: int) -> bool:
            if (row, col) in visited or not 0 <= row < row_count or not 0 <= col < col_count:
                return False

            if board[row][col] != word[target]:
                return False
            
            if target == word_length - 1:
                return True

            visited.add((row, col))
            if any(backtrack(row + delta_row, col + delta_col, visited, target + 1)
                   for delta_row, delta_col in delta):
                return True
            visited.remove((row, col))
            return False
        
        start_char = word[0]

        return any(backtrack(row, col, set(), 0) 
                   for row in range(row_count) 
                   for col in range(col_count)
                   if board[row][col] == start_char)

4.7.1561 - 2023-09-07 19:55:32 +0300 MSK

Word Search
class Solution:
    def exist(self, board: List[List[str]], word: str) -> bool:
        row_count, col_count = len(board), len(board[0])
        word_length = len(word)
        delta = ((0, 1), (0, -1), (1, 0), (-1, 0))

        if word_length == 1:
            return any(word in row for row in board)

        def backtrack(row: int, col: int, visited: Set, target: int) -> bool:
            if (row, col) in visited or not 0 <= row < row_count or not 0 <= col < col_count:
                return False

            if board[row][col] != word[target]:
                return False
            
            if target == word_length - 1:
                return True

            visited.add((row, col))
            if any(backtrack(row + delta_row, col + delta_col, visited, target + 1)
                   for delta_row, delta_col in delta):
                return True
            visited.remove((row, col))
            return False
        
        for row in range(row_count):
            for col in range(col_count):
                if backtrack(row, col, set(), 0):
                    return True
        
        return False

4.7.1562 - 2023-09-07 17:13:51 +0300 MSK

Reverse Linked List II
# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:
    def reverseBetween(self, head: Optional[ListNode], left: int, right: int) -> Optional[ListNode]:
        cur_node = 1
        left_head, left_tail = head if left > 1 else None, None

        while cur_node < left:
            cur_node += 1
            head, left_tail = head.next, head

        cur_node += 1
        mid_head, mid_tail, head = head, head, head.next
        mid_head.next = None

        while cur_node <= right:
            cur_node += 1
            mid_head, head.next, head = head, mid_head, head.next
    
        mid_tail.next = head
        if left_head:
            left_tail.next = mid_head
        else:
            left_head = mid_head

        return left_head

4.7.1563 - 2023-09-07 17:13:34 +0300 MSK

Reverse Linked List II
# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:
    def reverseBetween(self, head: Optional[ListNode], left: int, right: int) -> Optional[ListNode]:
        cur_node = 1
        left_head, left_tail = head if left > 1 else None, None

        while cur_node < left:
            cur_node += 1
            head, left_tail = head.next, head

        cur_node += 1
        mid_head, mid_tail, head = head, head, head.next
        mid_head.next = None

        while cur_node <= right:
            cur_node += 1
            next_node = head.next
            mid_head, head.next = head, mid_head
            head = next_node
    
        mid_tail.next = head
        if left_head:
            left_tail.next = mid_head
        else:
            left_head = mid_head

        return left_head

4.7.1564 - 2023-09-07 17:12:50 +0300 MSK

Reverse Linked List II
# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:
    def reverseBetween(self, head: Optional[ListNode], left: int, right: int) -> Optional[ListNode]:
        cur_node = 1
        left_head, left_tail = head if left > 1 else None, None

        while cur_node < left:
            cur_node += 1
            head, left_tail = head.next, head

        cur_node += 1
        mid_head, mid_tail, head = head, head, head.next
        mid_head.next = None

        while cur_node <= right:
            cur_node += 1
            next_node = head.next
            head.next = mid_head
            mid_head = head
            head = next_node
    
        mid_tail.next = head
        if left_head:
            left_tail.next = mid_head
        else:
            left_head = mid_head

        return left_head

4.7.1565 - 2023-09-06 14:59:03 +0300 MSK

Split Linked List in Parts
class Solution:
    def splitListToParts(self, head: Optional[ListNode], k: int) -> List[Optional[ListNode]]:        
        nodes_count = 0
        tail = head
        while tail:
            tail = tail.next
            nodes_count += 1
        
        quotient, remainder = divmod(nodes_count, k)
        answer = []
        for i in range(k):
            size = quotient + 1 if (remainder := remainder - 1) >= 0 else quotient

            answer.append(head)
            last = None
            while size > 0:
                last = head
                head = head.next
                size -= 1
            if last: 
                last.next = None
                
        return answer

4.7.1566 - 2023-09-05 11:41:23 +0300 MSK

Copy List with Random Pointer
"""
# Definition for a Node.
class Node:
    def __init__(self, x: int, next: 'Node' = None, random: 'Node' = None):
        self.val = int(x)
        self.next = next
        self.random = random
"""

class Solution:
    def copyRandomList(self, head: 'Optional[Node]') -> 'Optional[Node]':
        
        copied = {None: None}

        def copy_node(node: Node) -> Node:
            if node in copied:
                return copied[node]
            
            new_node = Node(node.val)
            copied[node] = new_node
            new_node.next = copy_node(node.next)
            new_node.random = copy_node(node.random)
            return new_node
        
        return copy_node(head)

4.7.1567 - 2023-09-04 15:54:45 +0300 MSK

Combination Sum
class Solution:
    def combinationSum(self, candidates: List[int], target: int) -> List[List[int]]:
        result = set()
        cur_nums = []

        def backtrack(cur_sum: int) -> None:
            if cur_sum == target:
                result.add(tuple(sorted(cur_nums[:])))
            if cur_sum >= target:
                return

            for num in candidates:
                cur_nums.append(num)
                backtrack(num + cur_sum)
                cur_nums.pop() 

        backtrack(0)

        return result

4.7.1568 - 2023-09-04 12:44:01 +0300 MSK

Convert Sorted Array to Binary Search Tree
# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def sortedArrayToBST(self, nums: List[int]) -> Optional[TreeNode]:
        nums_count = len(nums)
        if nums_count == 0:
            return None
        
        mid = nums_count // 2
        return TreeNode(nums[mid], 
                        self.sortedArrayToBST(nums[:mid]), 
                        self.sortedArrayToBST(nums[mid+1:]))

4.7.1569 - 2023-09-04 09:37:09 +0300 MSK

Linked List Cycle
# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution:
    def hasCycle(self, head: Optional[ListNode]) -> bool:
        slow_p, fast_p = head, head.next if head else None
        while fast_p and fast_p.next:
            if slow_p == fast_p:
                return True
            slow_p, fast_p = slow_p.next, fast_p.next.next

        return False

4.7.1570 - 2023-09-03 20:06:29 +0300 MSK

Game of Life
class Solution:
    def gameOfLife(self, board: List[List[int]]) -> None:
        """
        Do not return anything, modify board in-place instead.
        """
        rows_count, cols_count = len(board), len(board[0])
        moves = ((0, 1), (0, -1), (1, 0), (-1, 0), (1, 1), (1, -1), (-1, 1), (-1, -1))
        flip_cells = set()
        
        for row in range(rows_count):
            for col in range(cols_count):
                live_neighbors = 0
                is_alive = board[row][col] == 1

                for row_delta, col_delta in moves:
                    new_row, new_col = row + row_delta, col + col_delta
                    if not 0 <= new_row < rows_count or not 0 <= new_col < cols_count:
                        continue
                    if board[new_row][new_col] == 1:
                        live_neighbors += 1

                if (is_alive and (live_neighbors < 2 or live_neighbors > 3)) or (
                    not is_alive and live_neighbors == 3
                ):
                    flip_cells.add((row, col))
        
        while flip_cells:
            row, col = flip_cells.pop()
            board[row][col] = 0 if board[row][col] == 1 else 1

4.7.1571 - 2023-09-03 19:49:38 +0300 MSK

Set Matrix Zeroes
class Solution:
    def setZeroes(self, matrix: List[List[int]]) -> None:
        """
        Do not return anything, modify matrix in-place instead.
        """
        rows_count, cols_count = len(matrix), len(matrix[0])
        flip_rows, flip_cols = set(), set()

        for row in range(rows_count):
            for col in range(cols_count):
                if matrix[row][col] == 0:
                    flip_rows.add(row)
                    flip_cols.add(col)

        while flip_rows:
            row = flip_rows.pop()
            for col in range(cols_count):
                if matrix[row][col] != 0:
                    matrix[row][col] = 0
        
        while flip_cols:
            col = flip_cols.pop()
            for row in range(rows_count):
                if matrix[row][col] != 0:
                    matrix[row][col] = 0
        
            

4.7.1572 - 2023-09-03 11:23:58 +0300 MSK

Unique Paths
class Solution:
    def uniquePaths(self, m: int, n: int) -> int:

        @cache
        def dp(row: int, col: int) -> int:
            if not 0 <= row < m or not 0 <= col < n:
                return 0
            
            if row == m - 1 and col == n - 1:
                return 1
            
            return dp(row + 1, col) + dp(row, col + 1)

        return dp(0, 0)

4.7.1573 - 2023-09-02 16:26:14 +0300 MSK

Rotate Image
class Solution:
    def rotate(self, matrix: List[List[int]]) -> None:
        """
        Do not return anything, modify matrix in-place instead.
        """
        side_length = len(matrix)

        for row in range(side_length // 2):
            matrix[row], matrix[-row-1] = matrix[-row-1], matrix[row]
        
        for i in range(side_length):
            for j in range(i):
                matrix[i][j], matrix[j][i] = matrix[j][i], matrix[i][j]

4.7.1574 - 2023-09-02 10:50:42 +0300 MSK

Extra Characters in a String
class Solution:
    def minExtraChar(self, s: str, dictionary: List[str]) -> int:
        chars_count = len(s)

        @cache
        def dp(i: int) -> int:
            chars_left = chars_count - i
            if chars_left == 0:
                return 0
            
            min_extra_chars = chars_left

            for word in dictionary:
                word_length = len(word)

                if word_length > chars_left or s[i:i+word_length] != word:
                    continue
                
                if word_length == chars_left:
                    return 0

                min_extra_chars = min(min_extra_chars, dp(i + word_length))

            return min(min_extra_chars, 1 + dp(i + 1))
        
        return dp(0)

                

4.7.1575 - 2023-09-01 18:41:17 +0300 MSK

Text Justification
class Solution:
    def fullJustify(self, words: List[str], maxWidth: int) -> List[str]:
        words_count = len(words)
        
        def get_line(word_idx: int) -> Tuple[List[str], int]:
            line = []
            line_length = 0

            for i in range(word_idx, words_count):
                word = words[i]
                word_length = len(word)
                if line_length + word_length > maxWidth:
                    break

                line.append(word)
                line_length += word_length + 1 

            return line, line_length
        
        def create_line(line: List[str], line_length: int, word_idx: int) -> str:
            base_length = line_length - 1
            extra_spaces = maxWidth - base_length

            if len(line) == 1 or word_idx == words_count:
                return " ".join(line) + " " * extra_spaces

            word_count = len(line) - 1
            spaces_per_word = extra_spaces // word_count
            needs_extra_space = extra_spaces % word_count

            for j in range(needs_extra_space):
                line[j] += " "

            for j in range(word_count):
                line[j] += " " * spaces_per_word

            return " ".join(line)

        result = []
        i = 0
        while i < words_count:
            line, line_length = get_line(i)
            i += len(line)
            result.append(create_line(line, line_length, i))

        return result

4.7.1576 - 2023-09-01 18:38:28 +0300 MSK

Course Schedule
class Solution:
    def canFinish(self, numCourses: int, prerequisites: List[List[int]]) -> bool:
        
        nodes = [[] for _ in range(numCourses)]
        for target, required in prerequisites:
            nodes[target].append(required)

        visited = set()

        @cache
        def dfs(course: int) -> bool:
            if course in visited:
                return False
    
            edges = nodes[course]
            if not edges:
                return True
            
            visited.add(course)
            return all(dfs(edge) for edge in edges)

        for course in range(numCourses):
            if not dfs(course):
                return False
            visited.clear()
        
        return True

4.7.1577 - 2023-09-01 18:37:48 +0300 MSK

Course Schedule
class Solution:
    def canFinish(self, numCourses: int, prerequisites: List[List[int]]) -> bool:
        
        nodes = [[] for _ in range(numCourses)]
        for target, required in prerequisites:
            nodes[target].append(required)

        visited = set()

        @cache
        def dfs(course: int) -> bool:
            if course in visited:
                return False
    
            edges = nodes[course]
            if not edges:
                return True
            
            visited.add(course)
            return all(dfs(edge) for edge in edges)

        for course in range(numCourses):
            if not dfs(course):
                return False
            visited.clear()
        
        return True

4.7.1578 - 2023-09-01 09:58:21 +0300 MSK

Counting Bits
class Solution:
    def countBits(self, n: int) -> List[int]:
        ans = [0] * (n + 1)
        for i in range(1, n + 1):
            ans[i] = ans[i >> 1] + (i & 1)
        return ans

4.7.1579 - 2023-09-01 09:55:13 +0300 MSK

Counting Bits
class Solution:
    def countBits(self, n: int) -> List[int]:
        return tuple(bin(i).count("1") for i in range(n + 1))

4.7.1580 - 2023-08-31 22:14:58 +0300 MSK

Evaluate Division
class Solution:
    def calcEquation(self, equations: List[List[str]], values: List[float], queries: List[List[str]]) -> List[float]:
        equations_count = len(equations)
        queries_count = len(queries) 
        edges = defaultdict(dict)
        seen_nodes = set()
        invalid = -1.0

        def dfs(val1: str, val2: str) -> float:
            if val1 == val2:
                return 1.0

            if val2 in edges[val1]:
                return edges[val1][val2]

            if val1 in seen_nodes:
                return invalid

            seen_nodes.add(val1)

            for connected_node in edges[val1]:
                new_edge_res = dfs(connected_node, val2)
                if new_edge_res == invalid:
                    continue
                new_edge_res *= edges[val1][connected_node]
                edges[val1][val2] = new_edge_res
                return new_edge_res
            
            return invalid

        for i in range(equations_count):
            (val1, val2), res = equations[i], values[i]
            edges[val1][val2], edges[val2][val1] = res, 1 / res
        
        for i in range(queries_count):
            res, (val1, val2) = -1, queries[i]
            if val1 in edges and val2 in edges:
                seen_nodes.clear()
                res = dfs(val1, val2)
            queries[i] = res

        return queries

4.7.1581 - 2023-08-31 20:45:02 +0300 MSK

Clone Graph
"""
# Definition for a Node.
class Node:
    def __init__(self, val = 0, neighbors = None):
        self.val = val
        self.neighbors = neighbors if neighbors is not None else []
"""

class Solution:
    def cloneGraph(self, node: 'Node') -> 'Node':
        old_to_new = {}
        
        def clone(node: Node) -> Node:
            if node in old_to_new:
                return old_to_new[node]
            
            new_node = Node(node.val)
            old_to_new[node] = new_node
            new_node.neighbors = [clone(neighbor) for neighbor in node.neighbors]

            return new_node

        return clone(node) if node else node

4.7.1582 - 2023-08-31 20:35:52 +0300 MSK

Surrounded Regions
class Solution:
    def solve(self, board: List[List[str]]) -> None:
        """
        Do not return anything, modify board in-place instead.
        """
        row_count, col_count = len(board), len(board[0])
        moves = ((0, 1), (0, -1), (1, 0), (-1, 0))
        ignore_cells = set()

        def bfs(row: int, col: int) -> None:
            if not 0 <= row < row_count or not 0 <= col < col_count:
                return
            if (row, col) in ignore_cells or board[row][col] == "X":
                return

            ignore_cells.add((row, col))
            for row_delta, col_delta in moves:
                bfs(row + row_delta, col + col_delta)
        
        for row, col in itertools.chain(
            ((0, col) for col in range(col_count)),
            ((row_count - 1, col) for col in range(col_count)),
            ((row, 0) for row in range(row_count)),
            ((row, col_count - 1) for row in range(row_count))
        ):
            bfs(row, col)
        
        for row in range(1, row_count - 1):
            for col in range(1, col_count - 1):
                if (row, col) in ignore_cells:
                    continue

                board[row][col] = "X"
        

4.7.1583 - 2023-08-31 20:35:00 +0300 MSK

Surrounded Regions
class Solution:
    def solve(self, board: List[List[str]]) -> None:
        """
        Do not return anything, modify board in-place instead.
        """
        row_count, col_count = len(board), len(board[0])
        moves = ((0, 1), (0, -1), (1, 0), (-1, 0))
        ignore_stack = set()

        def bfs(row: int, col: int) -> None:
            if not 0 <= row < row_count or not 0 <= col < col_count:
                return
            if (row, col) in ignore_stack or board[row][col] == "X":
                return

            ignore_stack.add((row, col))
            for row_delta, col_delta in moves:
                bfs(row + row_delta, col + col_delta)
        
        for row, col in itertools.chain(
            ((0, col) for col in range(col_count)),
            ((row_count - 1, col) for col in range(col_count)),
            ((row, 0) for row in range(row_count)),
            ((row, col_count - 1) for row in range(row_count))
        ):
            bfs(row, col)
        
        flip_x = True
        for row in range(1, row_count - 1):
            for col in range(1, col_count - 1):
                if (row, col) in ignore_stack:
                    continue

                board[row][col] = "X"
        

4.7.1584 - 2023-08-31 20:34:31 +0300 MSK

Surrounded Regions
class Solution:
    def solve(self, board: List[List[str]]) -> None:
        """
        Do not return anything, modify board in-place instead.
        """
        row_count, col_count = len(board), len(board[0])
        moves = ((0, 1), (0, -1), (1, 0), (-1, 0))
        ignore_stack = set()

        @cache
        def bfs(row: int, col: int) -> None:
            if not 0 <= row < row_count or not 0 <= col < col_count:
                return
            if (row, col) in ignore_stack or board[row][col] == "X":
                return

            ignore_stack.add((row, col))
            for row_delta, col_delta in moves:
                bfs(row + row_delta, col + col_delta)
        
        for row, col in itertools.chain(
            ((0, col) for col in range(col_count)),
            ((row_count - 1, col) for col in range(col_count)),
            ((row, 0) for row in range(row_count)),
            ((row, col_count - 1) for row in range(row_count))
        ):
            bfs(row, col)
        
        flip_x = True
        for row in range(1, row_count - 1):
            for col in range(1, col_count - 1):
                if (row, col) in ignore_stack:
                    continue

                board[row][col] = "X"
        

4.7.1585 - 2023-08-31 15:29:43 +0300 MSK

Minimum Number of Taps to Open to Water a Garden
class Solution:
    def minTaps(self, n: int, ranges: List[int]) -> int:
        inf = float("inf")
        dp = [inf] * (n + 1)
        dp[0] = 0
        
        for i in range(n + 1):
            cur_range = ranges[i]
            tap_start, tap_end = max(0, i - cur_range), min(n, i + cur_range)
            
            for j in range(tap_start, tap_end + 1):
                dp[tap_end] = min(dp[tap_end], dp[j] + 1)
        
        min_taps = dp[n]
        return -1 if min_taps == inf else min_taps 

4.7.1586 - 2023-08-31 12:14:40 +0300 MSK

Minimum Number of Taps to Open to Water a Garden
class Solution:
    def minTaps(self, n: int, ranges: List[int]) -> int:
        arr = [0] * (n + 1)
        for i, r in enumerate(ranges):
            if r == 0:
                continue
            left = max(0, i - r)
            arr[left] = max(arr[left], i + r)

        end, far_can_reach, cnt = 0, 0, 0
        
        for i, reach in enumerate(arr):
            if i > end:
                if far_can_reach <= end:
                    return -1
                end, cnt = far_can_reach, cnt + 1
            far_can_reach = max(far_can_reach, reach)

        return cnt + (end < n)

4.7.1587 - 2023-08-30 19:06:25 +0300 MSK

Minimum Replacements to Sort the Array
class Solution:
    def minimumReplacement(self, nums: List[int]) -> int:
        nums_count = len(nums)
        operations_count = 0
        for i in reversed(range(nums_count - 1)):
            cur, prev = nums[i], nums[i+1]
            if cur <= prev:
                continue
            
            elements_count = (cur + prev - 1) // prev
            operations_count += elements_count - 1
            nums[i] //= elements_count

        return operations_count

4.7.1588 - 2023-08-29 19:00:49 +0300 MSK

Number of Islands
class Solution:
    def numIslands(self, grid: List[List[str]]) -> int:
        row_count, col_count = len(grid), len(grid[0])
        island_count = 0
        moves = ((0, 1), (0, -1), (1, 0), (-1, 0))

        @cache
        def dfs(row: int, col: int) -> None:
            if not 0 <= row < row_count or not 0 <= col < col_count or grid[row][col] == "0":
                return
            
            grid[row][col] = "0"
            for row_delta, col_delta in moves:
                dfs(row + row_delta, col + col_delta)

        for row in range(row_count):
            for col in range(col_count):
                if grid[row][col] == "0":
                    continue

                dfs(row, col)
                island_count += 1

        return island_count

            

4.7.1589 - 2023-08-29 18:48:22 +0300 MSK

Number of Islands
class Solution:
    def numIslands(self, grid: List[List[str]]) -> int:
        row_count, col_count = len(grid), len(grid[0])
        island_count = 0
        moves = ((0, 1), (0, -1), (1, 0), (-1, 0))
        queue = set((row, col) 
                    for row in range(row_count) 
                    for col in range(col_count) 
                    if grid[row][col] == "1")

        @cache
        def remove_island(row: int, col: int) -> None:
            if not 0 <= row < row_count or not 0 <= col < col_count:
                return

            for row_delta, col_delta in moves:
                new_cell = (row + row_delta, col + col_delta)
                if new_cell in queue:
                    queue.remove(new_cell)
                    remove_island(*new_cell)

        while queue:
            remove_island(*queue.pop())
            island_count += 1

        return island_count

            

4.7.1590 - 2023-08-29 18:48:09 +0300 MSK

Number of Islands
class Solution:
    def numIslands(self, grid: List[List[str]]) -> int:
        row_count, col_count = len(grid), len(grid[0])
        island_count = 0
        moves = ((0, 1), (0, -1), (1, 0), (-1, 0))
        queue = set((row, col) 
                    for row in range(row_count) 
                    for col in range(col_count) 
                    if grid[row][col] == "1")

        @cache
        def remove_island(row: int, col: int) -> None:
            if not 0 <= row < row_count or not 0 <= col < col_count:
                return

            for row_delta, col_delta in moves:
                new_cell = (row + row_delta, col + col_delta)
                if new_cell in queue:
                    queue.remove(new_cell)
                    remove_island(*new_cell)

        while queue:
            remove_island(*queue.pop())
            island_count += 1

        return island_count

            

4.7.1591 - 2023-08-29 18:44:17 +0300 MSK

Number of Islands
class Solution:
    def numIslands(self, grid: List[List[str]]) -> int:
        row_count, col_count = len(grid), len(grid[0])
        island_count = 0
        moves = ((0, 1), (0, -1), (1, 0), (-1, 0))
        queue = set((row, col) 
                    for row in range(row_count) 
                    for col in range(col_count) 
                    if grid[row][col] == "1")

        def remove_island(row: int, col: int) -> None:
            if not 0 <= row < row_count or not 0 <= col < col_count or (row, col) not in queue:
                return

            queue.remove((row, col))

            for row_delta, col_delta in moves:
                remove_island(row + row_delta, col + col_delta)    

        while queue:
            remove_island(*next(iter(queue)))
            island_count += 1

        return island_count

            

4.7.1592 - 2023-08-29 18:43:22 +0300 MSK

Number of Islands
class Solution:
    def numIslands(self, grid: List[List[str]]) -> int:
        row_count, col_count = len(grid), len(grid[0])
        island_count = 0
        moves = ((0, 1), (0, -1), (1, 0), (-1, 0))
        queue = set((row, col) 
                    for row in range(row_count) 
                    for col in range(col_count) 
                    if grid[row][col] == "1")

        @cache
        def remove_island(row: int, col: int) -> None:
            if not 0 <= row < row_count or not 0 <= col < col_count or (row, col) not in queue:
                return

            queue.remove((row, col))

            for row_delta, col_delta in moves:
                remove_island(row + row_delta, col + col_delta)    

        while queue:
            remove_island(*next(iter(queue)))
            island_count += 1

        return island_count

            

4.7.1593 - 2023-08-29 11:50:54 +0300 MSK

Minimum Penalty for a Shop
class Solution:
    def bestClosingTime(self, customers: str) -> int:
        # Start with closing at hour 0, the penalty equals all 'Y' in closed hours.
        cur_penalty = min_penalty = customers.count("Y")
        earliest_hour = 0
        
        for hour, customer in enumerate(customers):
            # If status in hour i is 'Y', moving it to open hours decrement
            # penalty by 1. Otherwise, moving 'N' to open hours increment
            # penatly by 1.
            cur_penalty += 1 if customer == "N" else -1

            # Update earliest_hour if a smaller penatly is encountered
            if cur_penalty < min_penalty:
                earliest_hour = hour + 1
                min_penalty = cur_penalty
                
        return earliest_hour

4.7.1594 - 2023-08-28 13:37:58 +0300 MSK

Map Sum Pairs
class MapSum:

    def __init__(self):
        self._map = {}

    def insert(self, key: str, val: int) -> None:
        self._map[key] = val

    def sum(self, prefix: str) -> int:
        return sum(value for key, value in self._map.items() if key.startswith(prefix))


# Your MapSum object will be instantiated and called as such:
# obj = MapSum()
# obj.insert(key,val)
# param_2 = obj.sum(prefix)

4.7.1595 - 2023-08-28 13:35:54 +0300 MSK

Implement Stack using Queues
class MyStack:

    def __init__(self):
        self._queue = []

    def push(self, x: int) -> None:
        self._queue.append(x)

    def pop(self) -> int:
        return self._queue.pop()

    def top(self) -> int:
        return self._queue[-1]

    def empty(self) -> bool:
        return len(self._queue) == 0 


# Your MyStack object will be instantiated and called as such:
# obj = MyStack()
# obj.push(x)
# param_2 = obj.pop()
# param_3 = obj.top()
# param_4 = obj.empty()

4.7.1596 - 2023-08-27 18:09:36 +0300 MSK

Minimum Absolute Difference in BST
# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def getMinimumDifference(self, root: Optional[TreeNode]) -> int:
        
        def min_node_diff(node: TreeNode, low: int, high: int) -> int:
            if not node:
                return high - low

            return min(min_node_diff(node.left, low, node.val),
                       min_node_diff(node.right, node.val, high))
    
        return min_node_diff(root, -maxsize, maxsize)

4.7.1597 - 2023-08-27 18:03:23 +0300 MSK

Minimum Absolute Difference in BST
# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def getMinimumDifference(self, root: Optional[TreeNode]) -> int:
        values = []
        def fall(node: TreeNode) -> None:
            if not node:
                return
            values.append(node.val)
            if node.left:
                fall(node.left)
            if node.right:
                fall(node.right)
        
        fall(root)
        values.sort()
        min_diff = abs(values[1] - values[0])
        for i in range(1, len(values) - 1):
            min_diff = min(min_diff, abs(values[i] - values[i+1]))
        
        return min_diff

4.7.1598 - 2023-08-27 17:55:09 +0300 MSK

Frog Jump
class Solution:
    def canCross(self, stones: List[int]) -> bool:
        m = set(stones)
        @cache
        def dfs(i, j):
            if i == stones[-1]: return True
            return any(x and x + i in m and dfs(x + i, x) for x in range(j - 1, j + 2))
        return dfs(0, 0)

4.7.1599 - 2023-08-26 16:17:44 +0300 MSK

Count Complete Tree Nodes
# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def countNodes(self, root: Optional[TreeNode]) -> int:
        def left_height(root: TreeNode) -> int:
            return 0 if not root else 1 + left_height(root.left)
        
        def right_height(root: TreeNode) -> int:
            return 0 if not root else 1 + right_height(root.right)
        
        left, right = left_height(root), right_height(root)
        if left > right:
            return 1 + self.countNodes(root.left) + self.countNodes(root.right)
        
        return 2**left - 1

        

4.7.1600 - 2023-08-26 16:17:28 +0300 MSK

Count Complete Tree Nodes
# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def countNodes(self, root: Optional[TreeNode]) -> int:
        def left_height(root: TreeNode) -> int:
            return 0 if not root else 1 + left_height(root.left)
        
        def right_height(root: TreeNode) -> int:
            return 0 if not root else 1+ right_height(root.right)
        
        left, right = left_height(root), right_height(root)
        if left > right:
            return 1 + self.countNodes(root.left) + self.countNodes(root.right)
        
        return 2**left - 1

        

4.7.1601 - 2023-08-26 16:16:46 +0300 MSK

Count Complete Tree Nodes
# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def countNodes(self, root: Optional[TreeNode]) -> int:
        if not root:
            return 0
        
        def left_height(root: TreeNode) -> int:
            return 0 if not root else 1 + left_height(root.left)
        
        def right_height(root: TreeNode) -> int:
            return 0 if not root else 1+ right_height(root.right)
        
        left, right = left_height(root), right_height(root)
        if left > right:
            return 1 + self.countNodes(root.left) + self.countNodes(root.right)
        
        return 2**left - 1

        

4.7.1602 - 2023-08-26 16:06:04 +0300 MSK

Path Sum
# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def hasPathSum(self, root: Optional[TreeNode], targetSum: int) -> bool:
        node_stack = [(root, 0)]
        while node_stack:
            node, curr_sum = node_stack.pop()
            if not node:
                continue
            
            new_sum = curr_sum + node.val
            if new_sum == targetSum and not node.left and not node.right:
                return True
            
            node_stack.extend(((node.left, new_sum), (node.right, new_sum)))
                
        return False

4.7.1603 - 2023-08-26 15:38:12 +0300 MSK

Symmetric Tree
# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def isSymmetric(self, root: Optional[TreeNode]) -> bool:
        comparison_stack = [(root.left, root.right)]
        while comparison_stack:
            left, right = comparison_stack.pop()
            
            if not left and not right:
                continue
            if not left or not right or left.val != right.val:
                return False

            comparison_stack.extend(((left.left, right.right), (left.right, right.left)))
        
        return True

4.7.1604 - 2023-08-26 15:24:31 +0300 MSK

Symmetric Tree
# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def isSymmetric(self, root: Optional[TreeNode]) -> bool:
        return self.check(root.left, root.right)

    def check(self, left: TreeNode, right: TreeNode) -> bool:
        if not left and not right:
            return True
        
        if not left or not right or left.val != right.val:
            return False
        
        return self.check(left.left, right.right) and self.check(left.right, right.left)

4.7.1605 - 2023-08-26 15:20:18 +0300 MSK

Invert Binary Tree
# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def invertTree(self, root: Optional[TreeNode]) -> Optional[TreeNode]:
        if root:
            root.left, root.right = self.invertTree(root.right), self.invertTree(root.left)
        return root

4.7.1606 - 2023-08-26 15:20:08 +0300 MSK

Invert Binary Tree
# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def invertTree(self, root: Optional[TreeNode]) -> Optional[TreeNode]:
        if root:
            root.left, root.right = self.invertTree(root.right), self.invertTree(root.left)
        return root 

4.7.1607 - 2023-08-26 15:19:33 +0300 MSK

Invert Binary Tree
# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def invertTree(self, root: Optional[TreeNode]) -> Optional[TreeNode]:
        if not root:
            return None

        root.left, root.right = self.invertTree(root.right), self.invertTree(root.left)
        return root 

4.7.1608 - 2023-08-26 15:18:57 +0300 MSK

Invert Binary Tree
# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def invertTree(self, root: Optional[TreeNode]) -> Optional[TreeNode]:
        if not root:
            return None

        self.invertTree(root.left)
        self.invertTree(root.right) 
        root.left, root.right = root.right, root.left
        
        return root 

4.7.1609 - 2023-08-26 12:16:27 +0300 MSK

Maximum Length of Pair Chain
class Solution:
    def findLongestChain(self, pairs: List[List[int]]) -> int:
        pairs_count = len(pairs)
        if pairs_count < 2:
            return pairs_count
        
        pairs.sort()
        
        @cache
        def dp(curr_pair: int) -> int:
            right = pairs[curr_pair][1]
            max_length = 1

            for new_pair in range(curr_pair + 1, pairs_count):
                new_left = pairs[new_pair][0]
                new_length = dp(new_pair) + (1 if new_left > right else 0)

                if new_length > max_length:
                    max_length = new_length
            
            return max_length
        
        return dp(0)

4.7.1610 - 2023-08-25 10:04:50 +0300 MSK

Interleaving String
class Solution:
    def isInterleave(self, s1: str, s2: str, s3: str) -> bool:
        length_1, length_2, length_3 = len(s1), len(s2), len(s3)
        if length_1 + length_2 != length_3:
            return False

        @cache
        def dp(i_1: int, i_2: int, i_3: int) -> bool:
            if i_3 == length_3:
                return True

            target = s3[i_3]
            return (
                i_1 != length_1 and s1[i_1] == target and dp(i_1 + 1, i_2, i_3 + 1)
            ) or (
                i_2 != length_2 and s2[i_2] == target and dp(i_1, i_2 + 1, i_3 + 1)
            )

        return dp(0, 0, 0)

4.7.1611 - 2023-08-24 16:42:07 +0300 MSK

Find K Pairs with Smallest Sums
class Solution:
    def kSmallestPairs(self, nums1: List[int], nums2: List[int], k: int) -> List[List[int]]:
        nums1_count, nums2_count = len(nums1), len(nums2)
        result = []
        visited = set(((0, 0)))
        min_heap = [(nums1[0] + nums2[0], (0, 0))]
        count = 0

        while k > 0 and min_heap:
            _, (i, j) = heappop(min_heap)
            new_i, new_j = i + 1, j + 1
            new_pair1, new_pair2 = (new_i, j), (i, new_j)
            num1, num2 = nums1[i], nums2[j]
            result.append((num1, num2))

            if new_i < nums1_count and new_pair1 not in visited:
                heappush(min_heap, (nums1[new_i] + num2, new_pair1))
                visited.add(new_pair1)

            if new_j < nums2_count and new_pair2 not in visited:
                heappush(min_heap, (num1 + nums2[new_j], new_pair2))
                visited.add(new_pair2)

            k -= 1
        
        return result

4.7.1612 - 2023-08-24 13:45:42 +0300 MSK

Text Justification
class Solution:
    def fullJustify(self, words: List[str], maxWidth: int) -> List[str]:
        words_count = len(words)
        
        def get_line(word_idx: int) -> Tuple[List[str], int]:
            line = []
            line_length = 0

            for i in range(word_idx, words_count):
                word = words[i]
                word_length = len(word)
                if line_length + word_length > maxWidth:
                    break

                line.append(word)
                line_length += word_length + 1 

            return line, line_length
        
        def create_line(line: List[str], line_length: int, word_idx: int) -> str:
            base_length = line_length - 1
            extra_spaces = maxWidth - base_length

            if len(line) == 1 or word_idx == words_count:
                return " ".join(line) + " " * extra_spaces

            word_count = len(line) - 1
            spaces_per_word = extra_spaces // word_count
            needs_extra_space = extra_spaces % word_count

            for j in range(needs_extra_space):
                line[j] += " "

            for j in range(word_count):
                line[j] += " " * spaces_per_word

            return " ".join(line)

        result = []
        i = 0
        while i < words_count:
            line, line_length = get_line(i)
            i += len(line)
            result.append(create_line(line, line_length, i))

        return result

4.7.1613 - 2023-08-23 22:56:37 +0300 MSK

Summary Ranges
class Solution:
    def summaryRanges(self, nums: List[int]) -> List[str]:
        nums_count = len(nums)
        if nums_count == 0:
            return []
        if nums_count == 1:
            return [str(nums[0])]

        ranges = [[nums[0]] * 2]
        for i, num in enumerate(nums[1:]):
            if ranges[-1][1] == num - 1:
                ranges[-1][1] = num
            else:
                ranges.append([num, num])

        return [f"{start}->{end}" if start != end else str(start) for start, end in ranges]

4.7.1614 - 2023-08-23 12:45:05 +0300 MSK

Reorganize String
class Solution:
    def reorganizeString(self, s: str) -> str:
        result = []
        # Min heap ordered by character counts, so we will use
        # negative values for count
        priority_queue = [(-count, char) for char, count in Counter(s).items()]
        heapify(priority_queue)

        while priority_queue:
            count_first, char_first = heappop(priority_queue)
            if not result or char_first != result[-1]:
                result.append(char_first)
                if count_first != -1: 
                    heappush(priority_queue, (count_first + 1, char_first))
                continue
            
            if not priority_queue: 
                return ""
            
            count_second, char_second = heappop(priority_queue)
            result.append(char_second)
            if count_second != -1:
                heappush(priority_queue, (count_second + 1, char_second))
            heappush(priority_queue, (count_first, char_first))

        return "".join(result)

4.7.1615 - 2023-08-22 10:32:27 +0300 MSK

Excel Sheet Column Title
class Solution:
    def convertToTitle(self, columnNumber: int) -> str:
        result = []
        while columnNumber:
            columnNumber, remainder = divmod(columnNumber - 1, 26)
            result.append(chr(65 + remainder))
        return ''.join(reversed(result))

4.7.1616 - 2023-08-21 23:38:46 +0300 MSK

Spiral Matrix
class Solution:
    def spiralOrder(self, matrix: List[List[int]]) -> List[int]:
        row_count, col_count = len(matrix), len(matrix[0])
        if row_count == 1:
            return matrix[0]
        if col_count == 1:
            return [row[0] for row in matrix]


        result = []
        top, bot, left, right = 0, row_count - 1, 0, col_count - 1
        capacity = row_count * col_count

        while len(result) < capacity:
            for col in range(left, right + 1):
                result.append(matrix[top][col])
            top += 1

            for row in range(top, bot + 1):
                result.append(matrix[row][right])
            right -= 1

            if top <= bot:
                for col in range(right, left - 1, -1):
                    result.append(matrix[bot][col])
                bot -= 1
            
            if left <= right:
                for row in range(bot, top - 1, -1):
                    result.append(matrix[row][left])
                left += 1

        return result

4.7.1617 - 2023-08-21 21:08:48 +0300 MSK

Valid Sudoku
class Solution:
    def isValidSudoku(self, board: List[List[str]]) -> bool:
        row_count, column_count = 9, 9
        row_counters = [defaultdict(bool) for _ in range(row_count)]
        column_counters = [defaultdict(bool) for _ in range(column_count)]
        subbox_counters = [[defaultdict(bool) for _ in range(column_count//3)] 
                            for _ in range(row_count//3)]

        for row in range(row_count):
            for column in range(column_count):
                char = board[row][column]
                if char == ".":
                    continue

                counters = (
                    row_counters[row], column_counters[column], 
                    subbox_counters[row//3][column//3]
                )
                for counter in counters:
                    if counter[char]:
                        return False

                    counter[char] = True
        
        return True

        

4.7.1618 - 2023-08-21 21:08:11 +0300 MSK

Valid Sudoku
class Solution:
    def isValidSudoku(self, board: List[List[str]]) -> bool:
        row_count, column_count = 9, 9

        

        row_counters = [defaultdict(bool) for _ in range(row_count)]
        column_counters = [defaultdict(bool) for _ in range(column_count)]
        subbox_counters = [[defaultdict(bool) for _ in range(column_count//3)] 
                            for _ in range(row_count//3)]

        for row in range(row_count):
            for column in range(column_count):
                char = board[row][column]
                if char == ".":
                    continue

                counters = (
                    row_counters[row], column_counters[column], 
                    subbox_counters[row//3][column//3]
                )
                for counter in counters:
                    if counter[char]:
                        return False

                    counter[char] = True
        
        return True

        

4.7.1619 - 2023-08-21 09:29:54 +0300 MSK

Repeated Substring Pattern
class Solution:
    def repeatedSubstringPattern(self, s: str) -> bool:
        length = len(s)
        for i in range(1, length // 2 + 1):
            if length % i != 0:
                continue
            
            if s == s[:i] * (length // i):
                return True
        
        return False

4.7.1620 - 2023-08-20 14:34:41 +0300 MSK

Sort Items by Groups Respecting Dependencies
class Solution:
    def sortItems(self, n, m, group, beforeItems):
        # If an item belongs to zero group, assign it a unique group id.
        group_id = m
        for i in range(n):
            if group[i] == -1:
                group[i] = group_id
                group_id += 1
        
        # Sort all item regardless of group dependencies.
        item_graph = [[] for _ in range(n)]
        item_indegree = [0] * n
        
        # Sort all groups regardless of item dependencies.
        group_graph = [[] for _ in range(group_id)]
        group_indegree = [0] * group_id      
        
        for curr in range(n):
            for prev in beforeItems[curr]:
                # Each (prev -> curr) represents an edge in the item graph.
                item_graph[prev].append(curr)
                item_indegree[curr] += 1
                
                # If they belong to different groups, add an edge in the group graph.
                if group[curr] != group[prev]:
                    group_graph[group[prev]].append(group[curr])
                    group_indegree[group[curr]] += 1      
        
        # Tologlogical sort nodes in graph, return [] if a cycle exists.
        def topologicalSort(graph, indegree):
            visited = []
            stack = [node for node in range(len(graph)) if indegree[node] == 0]
            while stack:
                cur = stack.pop()
                visited.append(cur)
                for neib in graph[cur]:
                    indegree[neib] -= 1
                    if indegree[neib] == 0:
                        stack.append(neib)
            return visited if len(visited) == len(graph) else []

        item_order = topologicalSort(item_graph, item_indegree)
        group_order = topologicalSort(group_graph, group_indegree)
        
        if not item_order or not group_order: 
            return []
        
        # Items are sorted regardless of groups, we need to 
        # differentiate them by the groups they belong to.
        ordered_groups = collections.defaultdict(list)
        for item in item_order:
            ordered_groups[group[item]].append(item)
        
        # Concatenate sorted items in all sorted groups.
        # [group 1, group 2, ... ] -> [(item 1, item 2, ...), (item 1, item 2, ...), ...]
        answer = []
        for group_index in group_order:
            answer += ordered_groups[group_index]
        return answer

4.7.1621 - 2023-08-19 18:48:22 +0300 MSK

Sorting Three Groups
class Solution:
    def minimumOperations(self, nums: List[int]) -> int:
        nums_count = len(nums)
        
        if nums_count == 1:
            return 0
            
        @cache
        def dp(i: int, start_group: int) -> int:
            if i == nums_count:
                return 0
            
            curr_group = nums[i] - 1
            actions_min = None
            
            for group_available in range(start_group, 3):
                actions = dp(i + 1, group_available) + (0 if group_available == curr_group else 1)
                if actions_min is None or actions < actions_min:
                    actions_min = actions
            
            return actions_min
        
        return dp(0, 0)

4.7.1622 - 2023-08-19 18:13:19 +0300 MSK

Make String a Subsequence Using Cyclic Increments
class Solution:
    def canMakeSubsequence(self, str1: str, str2: str) -> bool:
        length1, length2 = len(str1), len(str2)
        
        for i in range(length1):
            if i + length2 > length1:
                break
            
            idx2 = 0
            for idx1 in range(i, length1):
                if ord(str2[idx2]) - ord(str1[idx1]) in (0, 1, -25):
                    idx2 += 1
                
                if idx2 == length2:
                    return True
            
            
        return False

4.7.1623 - 2023-08-19 17:36:50 +0300 MSK

Count Pairs Whose Sum is Less than Target
class Solution:
    def countPairs(self, nums: List[int], target: int) -> int:
        pairs_count = 0
        nums_count = len(nums)
        for i in range(nums_count): 
            num1 = nums[i]
            for j in range(i + 1, nums_count):
                if num1 + nums[j] < target:
                    pairs_count += 1
        
        return pairs_count

4.7.1624 - 2023-08-19 17:13:39 +0300 MSK

Find Critical and Pseudo-Critical Edges in Minimum Spanning Tree
class Solution:

    class UnionFind:
        def __init__(self, n):
            self.parent = list(range(n))
            self.size = [1] * n
            self.max_size = 1

        def find(self, x):
            # Finds the root of x
            if x != self.parent[x]:
                self.parent[x] = self.find(self.parent[x])
            return self.parent[x]

        def union(self, x, y):
            # Connects x and y
            root_x = self.find(x)
            root_y = self.find(y)
            if root_x != root_y:
                if self.size[root_x] < self.size[root_y]:
                    root_x, root_y = root_y, root_x
                self.parent[root_y] = root_x
                self.size[root_x] += self.size[root_y]
                self.max_size = max(self.max_size, self.size[root_x])
                return True
            return False

    def findCriticalAndPseudoCriticalEdges(self, n, edges):
        new_edges = [edge.copy() for edge in edges]
        # Add index to edges for tracking
        for i, edge in enumerate(new_edges):
            edge.append(i)
        # Sort edges based on weight
        new_edges.sort(key=lambda x: x[2])

        # Find MST weight using union-find
        uf_std = self.UnionFind(n)
        std_weight = 0
        for u, v, w, _ in new_edges:
            if uf_std.union(u, v):
                std_weight += w

        # Check each edge for critical and pseudo-critical
        critical = []
        pseudo_critical = []
        for (u, v, w, i) in new_edges:
            # Ignore this edge and calculate MST weight
            uf_ignore = self.UnionFind(n)
            ignore_weight = 0
            for (x, y, w_ignore, j) in new_edges:
                if i != j and uf_ignore.union(x, y):
                    ignore_weight += w_ignore
            # If the graph is disconnected or the total weight is greater,
            # the edge is critical
            if uf_ignore.max_size < n or ignore_weight > std_weight:
                critical.append(i)
                continue

            # Force this edge and calculate MST weight
            uf_force = self.UnionFind(n)
            force_weight = w
            uf_force.union(u, v)
            for (x, y, w_force, j) in new_edges:
                if i != j and uf_force.union(x, y):
                    force_weight += w_force
            # If total weight is the same, the edge is pseudo-critical
            if force_weight == std_weight:
                pseudo_critical.append(i)

        return [critical, pseudo_critical]

4.7.1625 - 2023-08-18 10:52:33 +0300 MSK

Maximal Network Rank
class Solution:
    def maximalNetworkRank(self, n: int, roads: List[List[int]]) -> int:
        city_roads = [set() for _ in range(n)]

        for city_one, city_two in roads:
            city_roads[city_one].add(city_two)
            city_roads[city_two].add(city_one)
        
        max_rank = 0

        for city_one in range(n):
            for city_two in range(city_one + 1, n):
                rank = len(city_roads[city_one]) + len(city_roads[city_two])
                if city_one in city_roads[city_two]:
                    rank -= 1
                
                if rank > max_rank:
                    max_rank = rank
        
        return max_rank

4.7.1626 - 2023-08-17 16:52:59 +0300 MSK

01 Matrix
class Solution:
    def updateMatrix(self, mat: List[List[int]]) -> List[List[int]]:
        if not mat or not mat[0]:
            return []

        row_count, column_count = len(mat), len(mat[0])
        queue = set()
        MAX_VALUE = row_count * column_count
        
        # Initialize the queue with all 0s and set cells with 1s to MAX_VALUE.
        for row in range(row_count):
            for column in range(column_count):
                if mat[row][column] == 0:
                    queue.add((row, column))
                else:
                    mat[row][column] = MAX_VALUE
        
        directions = ((1, 0), (-1, 0), (0, 1), (0, -1))
        
        while queue:
            center_row, center_column = queue.pop()
            distance_from_center = mat[center_row][center_column] + 1

            for delta_row, delta_column in directions:
                new_row, new_column = center_row + delta_row, center_column + delta_column
                if not 0 <= new_row < row_count or not 0 <= new_column < column_count:
                    continue
    
                if mat[new_row][new_column] > distance_from_center:
                    queue.add((new_row, new_column))
                    mat[new_row][new_column] = distance_from_center
        
        return mat

4.7.1627 - 2023-08-16 14:36:21 +0300 MSK

Sliding Window Maximum
import sortedcontainers

class Solution:
    def maxSlidingWindow(self, nums: List[int], k: int) -> List[int]:
        nums_count = len(nums)
        if nums_count <= k:
            return [max(nums)]

        counter = defaultdict(int)
        elems = sortedcontainers.SortedSet()
        
        for num in nums[:k]:
            counter[num] += 1
            elems.add(num)
        
        result = [elems[-1]]
        
        for i in range(k, nums_count):
            new_num = nums[i]
            remove_num = nums[i-k]

            counter[new_num] += 1
            elems.add(new_num)

            counter[remove_num] -= 1
            if counter[remove_num] == 0:
                elems.discard(remove_num)

            result.append(elems[-1])

        return result

4.7.1628 - 2023-08-15 17:06:49 +0300 MSK

Partition List
# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:
    def partition(self, head: Optional[ListNode], x: int) -> Optional[ListNode]:
        before_head, after_head = ListNode(0), ListNode(0)
        before_tail, after_tail = before_head, after_head
        
        while head: 
            if head.val < x:
                before_tail.next, before_tail = head, head
            else:
                after_tail.next, after_tail = head, head
            head = head.next
        
        after_tail.next, before_tail.next = None, after_head.next
        
        return before_head.next

4.7.1629 - 2023-08-15 17:02:49 +0300 MSK

Partition List
# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:
    def partition(self, head: Optional[ListNode], x: int) -> Optional[ListNode]:
        first_left, last_left, first_right, last_right = None, None, None, None

        while head:
            is_left = head.val < x
            is_right = not is_left
            next_node = head.next
            head.next = first_right if is_left else None
            
            if is_left and last_left:
                last_left.next = head
                last_left = head
            elif is_left and not first_left:
                first_left, last_left = head, head

            if is_right and first_right:
                last_right.next = head
                last_right = head
            elif is_right and not first_right:
                first_right, last_right = head, head
                if last_left:
                    last_left.next = head

            head = next_node

        return first_left if first_left else first_right

4.7.1630 - 2023-08-14 11:17:39 +0300 MSK

Kth Largest Element in an Array
class Solution:
    def findKthLargest(self, nums, k):
        heap = []
        for num in nums:
            heapq.heappush(heap, num)
            if len(heap) > k:
                heapq.heappop(heap)
        
        return heap[0]

4.7.1631 - 2023-08-13 18:35:13 +0300 MSK

Check if There is a Valid Partition For The Array
class Solution:
    def validPartition(self, nums: List[int]) -> bool:
        n = len(nums)
        dp = [True] + [False] * n

        # Determine if the prefix array nums[0 ~ i] has a valid partition
        for i in range(n):
            dp_index = i + 1

            # Check 3 possibilities
            if i > 0 and nums[i] == nums[i - 1]:
                dp[dp_index] |= dp[dp_index - 2]
            if i > 1 and nums[i] == nums[i - 1] == nums[i - 2]:
                dp[dp_index] |= dp[dp_index - 3]
            if i > 1 and nums[i] == nums[i - 1] + 1 == nums[i - 2] + 2:
                dp[dp_index] |= dp[dp_index - 3]
 
        return dp[n]

4.7.1632 - 2023-08-12 17:50:41 +0300 MSK

Unique Paths II
class Solution:
    def uniquePathsWithObstacles(self, obstacleGrid: List[List[int]]) -> int:
        row_count = len(obstacleGrid)
        column_count = len(obstacleGrid[0])
        
        if obstacleGrid[0][0] == 1 or obstacleGrid[-1][-1] == 1:
            return 0

        dp = [[0] * column_count for _ in range(row_count)]
        dp[0][0] = 1

        for column in range(1, column_count):
            if obstacleGrid[0][column] == 1:
                break

            dp[0][column] = dp[0][column-1]

        for row in range(1, row_count):
            if obstacleGrid[row][0] == 0:
                dp[row][0] = dp[row-1][0]

            for column in range(1, column_count):
                if obstacleGrid[row][column] == 1:
                    continue
                
                dp[row][column] = dp[row-1][column] + dp[row][column-1]
                     
        return dp[-1][-1]

4.7.1633 - 2023-08-11 17:52:07 +0300 MSK

3Sum
class Solution:
    def threeSum(self, nums: List[int]) -> List[List[int]]:
        result = set()

        #1. Split nums into three lists: negative numbers, positive numbers, and zeros
        negatives, positives, zeros = [], [], []
        for num in nums:
            if num > 0:
                positives.append(num)
            elif num < 0: 
                negatives.append(num)
            else:
                zeros.append(num)

        #2. Create a separate set for negatives and positives for O(1) look-up times
        negatives_count, positives_count, zeros_count = len(negatives), len(positives), len(zeros)
        negatives_set, positives_set = set(negatives), set(positives)

        #3. If there is at least 1 zero in the list, add all cases where -num exists in N and num exists in P
        #   i.e. (-3, 0, 3) = 0
        for num in positives_set if zeros else []:
            negative = -1 * num
            if negative in negatives_set:
                result.add((negative, 0, num))

        #3. If there are at least 3 zeros in the list then also include (0, 0, 0) = 0
        if zeros_count >= 3:
            result.add((0, 0, 0))

        #4. For all pairs of negative numbers (-3, -1), check to see if their complement (4)
        #   exists in the positive number set
        for i in range(negatives_count):
            negative_1 = negatives[i]
            for j in range(i + 1, negatives_count):
                negative_2 = negatives[j]
                target = -1 * (negative_1 + negative_2)
                if target in positives_set:
                    result.add(tuple(sorted([negative_1, negative_2, target])))

        #5. For all pairs of positive numbers (1, 1), check to see if their complement (-2)
        #   exists in the negative number set
        for i in range(positives_count):
            positive_1 = positives[i]
            for j in range(i + 1, positives_count):
                positive_2 = positives[j]
                target = -1 * (positive_1 + positive_2)
                if target in negatives_set:
                    result.add(tuple(sorted([positive_1, positive_2, target])))

        return result

4.7.1634 - 2023-08-11 12:05:33 +0300 MSK

Product of Array Except Self
class Solution:
    def productExceptSelf(self, nums: List[int]) -> List[int]:
        nums_count = len(nums)
        result = [1] * nums_count
        prefix = 1
        postfix = 1
        for i in range(nums_count):
            result[i] *= prefix
            prefix *= nums[i]

            from_end = -1 * (i + 1)
            result[from_end] *= postfix
            postfix *= nums[from_end]
        
        return result

4.7.1635 - 2023-08-11 12:01:50 +0300 MSK

Product of Array Except Self
class Solution:
    def productExceptSelf(self, nums: List[int]) -> List[int]:
        nums_count = len(nums)
        result = [1] * nums_count
        prefix = 1
        postfix = 1
        for i in range(nums_count):
            result[i] *= prefix
            prefix *= nums[i]
            result[nums_count-i-1] *= postfix
            postfix *= nums[nums_count-i-1]
        
        return result

4.7.1636 - 2023-08-11 11:17:35 +0300 MSK

Coin Change II
class Solution:
    def change(self, amount: int, coins: List[int]) -> int:
        n = len(coins)
        dp = [[0] * (amount + 1) for _ in range(n + 1)]
        for i in range(n):
            dp[i][0] = 1

        for i in range(n - 1, -1, -1):
            for j in range(1, amount + 1):
                if coins[i] > j:
                    dp[i][j] = dp[i + 1][j]
                else:
                    dp[i][j] = dp[i + 1][j] + dp[i][j - coins[i]]

        return dp[0][amount]

4.7.1637 - 2023-08-11 11:12:31 +0300 MSK

Coin Change II
class Solution:
    def change(self, amount: int, coins: List[int]) -> int:
        coins_count = len(coins)
        memo = [[-1] * (amount + 1) for _ in range(coins_count)]
        
        def dp(i: int, amount: int) -> int:
            if amount == 0:
                return 1
            if i == coins_count:
                return 0
            if memo[i][amount] != -1:
                return memo[i][amount]

            value = None

            if coins[i] > amount:
                value = dp(i + 1, amount)
            else:
                value = dp(i, amount - coins[i]) + dp(i + 1, amount)

            memo[i][amount] = value
            return value

        return dp(0, amount)

4.7.1638 - 2023-08-10 17:04:38 +0300 MSK

Search in Rotated Sorted Array II
class Solution:
    def search(self, nums: List[int], target: int) -> bool:
        left, right = 0, len(nums) - 1
        
        while left <= right:
            mid = (left + right) // 2
            
            if nums[mid] == target:
                return True
            
            if nums[mid] == nums[left]:
                left += 1
                continue

            if nums[left] <= nums[mid]:
                if nums[left] <= target < nums[mid]:
                    right = mid - 1
                else:
                    left = mid + 1
            else:
                if nums[mid] < target <= nums[right]:
                    left = mid + 1
                else:
                    right = mid - 1
        
        return False

4.7.1639 - 2023-08-09 15:13:28 +0300 MSK

Best Time to Buy and Sell Stock IV
class Solution:
    def maxProfit(self, k: int, prices: List[int]) -> int:
        # no transaction, no profit
        if k == 0: return 0
        # dp[k][0] = min cost you need to spend at most k transactions
        # dp[k][1] = max profit you can achieve at most k transactions
        dp = [[1000, 0] for _ in range(k + 1)]
        for price in prices:
            for i in range(1, k + 1):
                # price - dp[i - 1][1] is how much you need to spend
                # i.e use the profit you earned from previous transaction to buy the stock
                # we want to minimize it
                dp[i][0] = min(dp[i][0], price - dp[i - 1][1])
                # price - dp[i][0] is how much you can achieve from previous min cost
                # we want to maximize it
                dp[i][1] = max(dp[i][1], price - dp[i][0])
        # return max profit at most k transactions
		# or you can write `return dp[-1][1]`
        return dp[k][1]

4.7.1640 - 2023-08-09 12:05:47 +0300 MSK

Minimize the Maximum Difference of Pairs
class Solution:
    def minimizeMax(self, nums: List[int], p: int) -> int:
        nums.sort()
        nums_count = len(nums)
        
        # Find the number of valid pairs by greedy approach
        def countValidPairs(threshold: int) -> int:
            index, count = 0, 0
            while index < nums_count - 1:
                # If a valid pair is found, skip both numbers.
                if nums[index + 1] - nums[index] <= threshold:
                    count += 1
                    index += 1
                index += 1
            return count
        
        left, right = 0, nums[-1] - nums[0]
        while left < right:
            mid = left + (right - left) // 2

            # If there are enough pairs, look for a smaller threshold.
            # Otherwise, look for a larger threshold.
            if countValidPairs(mid) >= p:
                right = mid
            else:
                left = mid + 1

        return left       

4.7.1641 - 2023-08-08 23:40:50 +0300 MSK

Best Time to Buy and Sell Stock III
class Solution:
	def maxProfit(self, prices: List[int]) -> int:
				
		'''
		dp_2_hold: max profit with 2 transactions, and in hold state
		dp_2_not_hold: max profit with 2 transactions, and not in hold state
		
		dp_1_hold: max profit with 1 transaction, and in hold state
		dp_1_not_hold: max profit with 1 transaction, and not in hold state
		
		Note: it is impossible to have stock in hand and sell on first day, therefore -infinity is set as initial profit value for hold state
		'''
		
		dp_2_hold, dp_2_not_hold = -float('inf'), 0
		dp_1_hold, dp_1_not_hold = -float('inf'), 0
		
		for stock_price in prices:
				
			# either keep being in not-hold state, or sell with stock price today
			dp_2_not_hold = max( dp_2_not_hold, dp_2_hold + stock_price )
	
			# either keep being in hold state, or just buy with stock price today ( add one more transaction )
			dp_2_hold = max( dp_2_hold, dp_1_not_hold - stock_price )
				
			# either keep being in not-hold state, or sell with stock price today
			dp_1_not_hold = max( dp_1_not_hold, dp_1_hold + stock_price )
	
			# either keep being in hold state, or just buy with stock price today ( add one more transaction )
			dp_1_hold = max( dp_1_hold, 0 - stock_price )
				
		return dp_2_not_hold

4.7.1642 - 2023-08-08 23:36:48 +0300 MSK

Best Time to Buy and Sell Stock III
class Solution:
    def maxProfit(self, prices: List[int]) -> int:
        if not prices:
            return 0

        # initialize variables for first buy, first sell, second buy, and second sell
        buy1, buy2 = float('inf'), float('inf')
        sell1, sell2 = 0, 0

        # iterate over prices to update buy and sell values
        for price in prices:
            # update first buy and sell values
            buy1 = min(buy1, price)
            sell1 = max(sell1, price - buy1)
            # update second buy and sell values
            buy2 = min(buy2, price - sell1)
            sell2 = max(sell2, price - buy2)

        return sell2

4.7.1643 - 2023-08-08 22:57:16 +0300 MSK

Longest Palindromic Substring
class Solution:
    def longestPalindrome(self, s: str) -> str:
        n = len(s)
        dp = [[False] * n for _ in range(n)]
        ans = [0, 0]
        
        for i in range(n):
            dp[i][i] = True
        
        for i in range(n - 1):
            if s[i] == s[i + 1]:
                dp[i][i + 1] = True
                ans = [i, i + 1]

        for diff in range(2, n):
            for i in range(n - diff):
                j = i + diff
                if s[i] == s[j] and dp[i + 1][j - 1]:
                    dp[i][j] = True
                    ans = [i, j]

        i, j = ans
        return s[i:j + 1]

4.7.1644 - 2023-08-08 22:56:36 +0300 MSK

Maximal Square
class Solution:
    def maximalSquare(self, matrix: List[List[str]]) -> int:
        row_count, column_count = len(matrix), len(matrix[0])
        
        dp = [[0] * column_count for _ in range(row_count)]
        
        max_size = 0
        for column in range(column_count):
            if matrix[0][column] == "0":
                continue
            dp[0][column] = 1
            max_size = 1

        for row in range(row_count):
            if matrix[row][0] == "0":
                continue
            dp[row][0] = 1
            max_size = 1
        
        for row in range(1, row_count):
            for column in range(1, column_count):
                if matrix[row][column] == "0":
                    continue
                
                value = min(dp[row-1][column], dp[row][column-1], dp[row-1][column-1]) + 1
                dp[row][column] = value
                max_size = max(max_size, value)
        
        return max_size * max_size

4.7.1645 - 2023-08-08 21:50:31 +0300 MSK

Edit Distance
class Solution:
    def minDistance(self, word1: str, word2: str) -> int:
        length1, length2 = len(word1), len(word2)

        @cache
        def dp(i1: int, i2: int) -> int:
            if i1 == length1:
                return length2 - (i2 + 1)

            if i2 == length2:
                return length1 - (i1 + 1)
            
            if word1[i1] == word2[i2]:
                return dp(i1 + 1, i2 + 1)

            return 1 + min((
                # replace or insert
                dp(i1 + 1, i2 + 1),
                # remove from i1
                dp(i1 + 1, i2),
                # remove from i2
                dp(i1, i2 + 1)
            ))
        
        return dp(0, 0) + 1

4.7.1646 - 2023-08-08 21:27:42 +0300 MSK

Interleaving String
class Solution:
    def isInterleave(self, s1: str, s2: str, s3: str) -> bool:
        length_1, length_2, length_3 = len(s1), len(s2), len(s3)
        if length_1 + length_2 != length_3:
            return False
        
        @cache
        def dp(i_1: int, i_2: int, i_3: int) -> bool:
            if i_3 == length_3:
                return True

            target = s3[i_3]
            return (
                i_1 != length_1 and s1[i_1] == target and dp(i_1 + 1, i_2, i_3 + 1)
            ) or (
                i_2 != length_2 and s2[i_2] == target and dp(i_1, i_2 + 1, i_3 + 1)
            )

        return dp(0, 0, 0)

4.7.1647 - 2023-08-08 21:02:11 +0300 MSK

Unique Paths II
class Solution:
    def uniquePathsWithObstacles(self, obstacleGrid: List[List[int]]) -> int:
        row_count = len(obstacleGrid)
        column_count = len(obstacleGrid[0])
        
        if obstacleGrid[0][0] == 1 or obstacleGrid[-1][-1] == 1:
            return 0

        dp = [[0] * column_count for _ in range(row_count)]
        dp[0][0] = 1

        for column in range(1, column_count):
            if obstacleGrid[0][column] == 1:
                break

            dp[0][column] = dp[0][column-1]

        for row in range(1, row_count):
            if obstacleGrid[row][0] == 0:
                dp[row][0] = dp[row-1][0]

            for column in range(1, column_count):
                if obstacleGrid[row][column] == 1:
                    continue
                
                dp[row][column] = dp[row-1][column] + dp[row][column-1]
                     
        return dp[-1][-1]

4.7.1648 - 2023-08-08 20:47:19 +0300 MSK

Unique Paths II
class Solution:
    def uniquePathsWithObstacles(self, obstacleGrid: List[List[int]]) -> int:
        row_count = len(obstacleGrid)
        column_count = len(obstacleGrid[0])
        # dp = [[0] * column_count for _ in range(row_count)]

        # for row in range(row_count):
        #     for column in range(column_count):

        @cache
        def dp(row: int, column: int) -> int:
            if row == row_count or column == column_count or obstacleGrid[row][column] == 1:
                return 0
            
            if row == row_count - 1 and column == column_count - 1:
                return 1
            
            return dp(row + 1, column) + dp(row, column + 1)
        
        return dp(0, 0)

4.7.1649 - 2023-08-08 20:31:21 +0300 MSK

Minimum Path Sum
class Solution:
    def minPathSum(self, grid: List[List[int]]) -> int:
        row_count = len(grid)
        column_count = len(grid[0]) if grid else None
        if not row_count or not column_count:
            return 0

        dp = [[0] * column_count for _ in range(row_count)]
        dp[0][0] = grid[0][0]

        for column in range(1, column_count):
            dp[0][column] = grid[0][column] + dp[0][column - 1]

        for row in range(1, row_count):
            dp[row][0] = grid[row][0] + dp[row - 1][0]

            for column in range(1, column_count):
                dp[row][column] = grid[row][column] + min(
                    dp[row - 1][column], dp[row][column-1]
                )

        # @cache
        # def dp(row: int, column: int) -> int:
        #     if row == row_count or column == column_count:
        #         return 0
        #     return grid[row][column] + min(dp(row + 1, column), dp(row, column + 1))
        #return dp(0, 0)

        return dp[-1][-1]

4.7.1650 - 2023-08-08 19:53:50 +0300 MSK

Triangle
class Solution:
    def minimumTotal(self, triangle: List[List[int]]) -> int:
        row_count = len(triangle)
        dp = [[0] * row_count for _ in range(row_count)]
        dp[0][0] = triangle[0][0]

        for row in range(1, row_count):
            dp[row][0] = triangle[row][0] + dp[row-1][0]
            dp[row][row] = triangle[row][row] + dp[row-1][row-1]

            for column in range(1, row):
                dp[row][column] = triangle[row][column] + min(
                    dp[row-1][column], dp[row-1][column-1]
                )

        return min(dp[-1])

4.7.1651 - 2023-08-08 19:34:48 +0300 MSK

Triangle
class Solution:
    def minimumTotal(self, triangle: List[List[int]]) -> int:
        row_count = len(triangle)


        @cache
        def dp(row: int, column: int) -> int:
            if row == row_count or column == row + 1:
                return 0
        
            return triangle[row][column] + min(dp(row + 1, column), dp(row + 1, column + 1))

        return dp(0, 0)

4.7.1652 - 2023-08-08 14:36:45 +0300 MSK

Kth Largest Element in an Array
class Solution:
    def findKthLargest(self, nums, k):
        heap = []
        for num in nums:
            heapq.heappush(heap, num)
            if len(heap) > k:
                heapq.heappop(heap)
        
        return heap[0]

4.7.1653 - 2023-08-08 13:55:40 +0300 MSK

Search in Rotated Sorted Array
class Solution:
    def search(self, nums: List[int], target: int) -> int:
        nums_count = len(nums)
        left, right = 0, len(nums) - 1

        first_num, last_num = nums[0], nums[-1]
        if first_num == target:
            return 0
        if last_num == target:
            return nums_count - 1
        
        # Find the index of the pivot element (the smallest element)
        while left <= right:
            mid = left + (right - left) // 2
            if nums[mid] > last_num:
                left = mid + 1
            else:
                right = mid - 1
        
        pivot_num = nums[left]
        if pivot_num == target:
            return left
        
        if pivot_num < target < last_num:
            right = nums_count - 1
        else:
            left = 0
        
        while left <= right:
            mid = left + (right - left) // 2
            mid_num = nums[mid]
            if mid_num == target:
                return mid
            elif mid_num > target:
                right = mid - 1
            else:
                left = mid + 1
        
        return -1

4.7.1654 - 2023-08-08 13:55:01 +0300 MSK

Search in Rotated Sorted Array
class Solution:
    def search(self, nums: List[int], target: int) -> int:
        nums_count = len(nums)
        left, right = 0, len(nums) - 1

        first_num, last_num = nums[0], nums[-1]
        if first_num == target:
            return 0
        if last_num == target:
            return nums_count - 1
        
        # Find the index of the pivot element (the smallest element)
        while left <= right:
            mid = left + (right - left) // 2
            if nums[mid] > last_num:
                left = mid + 1
            else:
                right = mid - 1
        
        pivot_num = nums[left]
        if pivot_num == target:
            return left
        
        if pivot_num < target < last_num:
            right = nums_count - 1
        else:
            left = 0
        
        while left <= right:
            mid = (left + right) // 2
            mid_num = nums[mid]
            if mid_num == target:
                return mid
            elif mid_num > target:
                right = mid - 1
            else:
                left = mid + 1
        
        return -1

4.7.1655 - 2023-08-07 17:24:07 +0300 MSK

Longest Increasing Subsequence
class Solution:
    def lengthOfLIS(self, nums: List[int]) -> int:
        nums_count = len(nums)
        dp = [0] * nums_count
        dp[0] = 1
        for i in range(1, nums_count):
            length = 0
            start = nums[i]

            for j in range(0, i):
                if start > nums[j]:
                    length = max(length, dp[j])

            dp[i] = 1 + length
            
        return max(dp)

4.7.1656 - 2023-08-07 14:39:05 +0300 MSK

Coin Change
class Solution:
    def coinChange(self, coins: List[int], amount: int) -> int:
        dp = [amount + 1] * (amount + 1)
        dp[0] = 0

        for current_amount in range(1, amount + 1):
            for coin in coins:
                diff = current_amount - coin
                if diff < 0:
                    continue
                
                dp[current_amount] = min(dp[current_amount], dp[diff] + 1)

        return dp[-1] if dp[-1] != amount + 1 else -1

4.7.1657 - 2023-08-07 14:27:07 +0300 MSK

Coin Change
class Solution:
    def coinChange(self, coins: List[int], amount: int) -> int:
        if amount == 0:
            return 0
        
        @cache
        def dp(coins_value: int) -> int:
            if coins_value == amount:
                return 0
            
            if coins_value > amount:
                return -1
            
            min_coins_count = -1

            for coin in coins:
                new_count = 1 + dp(coin + coins_value)
                if new_count == 0:
                    continue
                
                if min_coins_count == -1 or new_count < min_coins_count:
                    min_coins_count = new_count
            
            return min_coins_count

        return dp(0)

4.7.1658 - 2023-08-07 13:27:10 +0300 MSK

Word Break
class Solution:
    def wordBreak(self, s: str, wordDict: List[str]) -> bool:
        n = len(s)
        words = set(wordDict)
        dp = [False] * (n + 1)
        dp[0] = True
        
        for i in range(1, n + 1):
            for j in range(i):
                if dp[j] and s[j:i] in words:
                    dp[i] = True
                    break
        
        return dp[-1]

4.7.1659 - 2023-08-07 13:25:04 +0300 MSK

Word Break
class Solution:
    def wordBreak(self, s: str, wordDict: List[str]) -> bool:
        @cache
        def dp(i):
            if i < 0: 
                return True

            for word in wordDict:
                if s[i - len(word) + 1:i + 1] == word and dp(i - len(word)):
                    return True
            
            return False
        
        return dp(len(s) - 1)

4.7.1660 - 2023-08-07 13:10:04 +0300 MSK

House Robber
class Solution:
    def rob(self, nums: List[int]) -> int:
        house_count = len(nums)

        prev_1, prev_2 = 0, 0

        for house in range(0, house_count):
            prev_1, prev_2 = max(prev_2 + nums[house], prev_1), prev_1

        return prev_1

4.7.1661 - 2023-08-07 13:07:20 +0300 MSK

House Robber
class Solution:
    def rob(self, nums: List[int]) -> int:
        house_count = len(nums)

        dp = [0 for _ in range(house_count + 1)]
        dp[1] = nums[0]

        for house in range(1, house_count):
            dp[house+1] = max(dp[house-1] + nums[house], dp[house])

        return dp[-1]

4.7.1662 - 2023-08-07 12:57:18 +0300 MSK

House Robber
class Solution:
    def rob(self, nums: List[int]) -> int:
        house_count = len(nums)
        
        @cache
        def dp(house: int) -> int:
            if house >= house_count:
                return 0

            return max(dp(house + 1), nums[house] + dp(house + 2)) 

        return dp(0)

4.7.1663 - 2023-08-07 12:49:57 +0300 MSK

Climbing Stairs
class Solution:
    def climbStairs(self, n: int) -> int:
        if n < 3:
            return n

        minus_one, minus_two = 2, 1
        for step in range(3, n + 1):
            minus_one, minus_two = minus_one + minus_two, minus_one
        
        return minus_one

4.7.1664 - 2023-08-07 12:45:54 +0300 MSK

Climbing Stairs
class Solution:
    def climbStairs(self, n: int) -> int:

        @cache
        def dp(step: int) -> int:
            if step <= 2:
                return step
            
            return dp(step - 1) + dp(step - 2) 
 
        return dp(n)

4.7.1665 - 2023-08-07 12:17:58 +0300 MSK

Search a 2D Matrix
class Solution:
    def searchMatrix(self, matrix: List[List[int]], target: int) -> bool:
        length_vertical, length_horizontal = len(matrix), len(matrix[0])


        left, right = 0, length_vertical - 1
        while left <= right:
            mid = left + (right - left) // 2
            mid_number = matrix[mid][0]
            
            if mid_number == target:
                return True
            
            if mid_number > target:
                right = mid - 1
            else:
                left = mid + 1
        
        vertical_index = right
        left, right = 0, length_horizontal - 1
        while left <= right:
            mid = left + (right - left) // 2
            mid_number = matrix[vertical_index][mid]

            if mid_number == target:
                return True
            
            if mid_number > target:
                right = mid - 1
            else:
                left = mid + 1
            
        return False

4.7.1666 - 2023-08-06 18:05:41 +0300 MSK

Faulty Keyboard
class Solution:
    def finalString(self, s: str) -> str:
        result = []
        for char in s:
            if char == "i":
                result.reverse()
            else:
                result.append(char)
        
        return "".join(result)

4.7.1667 - 2023-08-06 18:00:12 +0300 MSK

Maximum Number of Events That Can Be Attended II
class Solution:
    def maxValue(self, events: List[List[int]], k: int) -> int:        
        events.sort()
        n = len(events)
        starts = [start for start, end, value in events]
        dp = [[-1] * n for _ in range(k + 1)]
        
        def dfs(cur_index, count):
            if count == 0 or cur_index == n:
                return 0
            if dp[count][cur_index] != -1:
                return dp[count][cur_index]

            # Find the nearest available event after attending event 0.

            next_index = bisect_right(starts, events[cur_index][1])
            dp[count][cur_index] = max(dfs(cur_index + 1, count), events[cur_index][2] + dfs(next_index, count - 1))
            return dp[count][cur_index]
        
        return dfs(0, k)

4.7.1668 - 2023-08-06 17:37:57 +0300 MSK

Number of Music Playlists
class Solution:
    def numMusicPlaylists(self, n: int, goal: int, k: int) -> int:
        MOD = 10**9 + 7

        # Initialize the DP table
        dp = [[0 for _ in range(n + 1)] for _ in range(goal + 1)]
        dp[0][0] = 1

        for i in range(1, goal + 1):
            for j in range(1, min(i, n) + 1):
                # The i-th song is a new song
                dp[i][j] = dp[i - 1][j - 1] * (n - j + 1) % MOD
                # The i-th song is a song we have played before
                if j > k:
                    dp[i][j] = (dp[i][j] + dp[i - 1][j] * (j - k)) % MOD

        return dp[goal][n]

4.7.1669 - 2023-08-06 17:18:41 +0300 MSK

Smallest Sufficient Team
class Solution:
    def smallestSufficientTeam(self, req_skills: List[str], people: List[List[str]]) -> List[int]:
        req_skills_count = len(req_skills)
        skill_to_people = defaultdict(set)
        for i, person in enumerate(people):
            for skill in person:
                skill_to_people[skill].add(i)

        current = set()
        
        def backtrack(skill: int) -> Tuple[int]:
            if skill == req_skills_count:
                return tuple(current)
            
            suff_team = None
            people_with_skill = skill_to_people[req_skills[skill]] 
            
            if current & people_with_skill:
                return backtrack(skill + 1)
        
            for person in people_with_skill:
                current.add(person)
                new_team = backtrack(skill + 1)
                current.remove(person)

                if suff_team is None or len(new_team) < len(suff_team):
                    suff_team = new_team

            return suff_team

        return backtrack(0)
        

4.7.1670 - 2023-08-05 17:53:24 +0300 MSK

Insert Greatest Common Divisors in Linked List
# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:
    def insertGreatestCommonDivisors(self, head: Optional[ListNode]) -> Optional[ListNode]:
        root = head
        
        while head and head.next:
            next = head.next
            new_node = ListNode(math.gcd(head.val, head.next.val), next)
            head.next = new_node
            head = next
        
        return root

4.7.1671 - 2023-08-05 17:40:38 +0300 MSK

Account Balance After Rounded Purchase
class Solution:
    def accountBalanceAfterPurchase(self, purchaseAmount: int) -> int:
        remainder = purchaseAmount % 10
        if remainder == 0:
            return 100 - purchaseAmount

        if remainder >= 5:
            return 100 - ((purchaseAmount // 10) + 1) * 10 
        
        return 100 - (purchaseAmount // 10) * 10

4.7.1672 - 2023-08-05 12:39:41 +0300 MSK

Unique Binary Search Trees II
class Solution:
    def generateTrees(self, n: int) -> List[Optional[TreeNode]]:
        @cache
        def generate_trees(l, r):
            return [None] if l > r else [
                TreeNode(val, left, right)
                for val in range(l, r + 1)
                for left in generate_trees(l, val - 1)
                for right in generate_trees(val + 1, r)
            ]
        
        return generate_trees(1, n)

4.7.1673 - 2023-08-04 19:40:16 +0300 MSK

Maximum Number of Achievable Transfer Requests
class Solution:
    def maximumRequests(self, n, requests):
        current = [0] * n
        length = len(requests)
        
        def backtrack(req_index: int, count: int) -> int:
            if req_index == length:
                return 0 if any(current) else count

            req_from, req_to = requests[req_index]
            
            current[req_from] -= 1
            current[req_to] += 1
            take = backtrack(req_index + 1, count + 1)

            current[req_from] += 1
            current[req_to] -= 1
            non_take = backtrack(req_index + 1, count)
            
            return max(take, non_take)
        
        return backtrack(0, 0)

4.7.1674 - 2023-08-04 19:38:00 +0300 MSK

Word Break
class Solution:
    def wordBreak(self, s: str, wordDict: List[str]) -> bool:

        @cache
        def calculate(i: int) -> bool:
            if i < 0:
                return True
            
            for word in wordDict:
                length = len(word)
                if s[i-length+1:i+1] == word and calculate(i-length):
                    return True
            
            return False

        return calculate(len(s) - 1)
        

4.7.1675 - 2023-08-04 19:37:15 +0300 MSK

Word Break
class Solution:
    def wordBreak(self, s: str, wordDict: List[str]) -> bool:
        words = set(wordDict)
    
        @cache
        def calculate(i: int) -> bool:
            if i < 0:
                return True
            
            for word in wordDict:
                length = len(word)
                if s[i-length+1:i+1] == word and calculate(i-length):
                    return True
            
            return False

        return calculate(len(s) - 1)
        

4.7.1676 - 2023-08-03 12:33:31 +0300 MSK

Letter Combinations of a Phone Number
class Solution:
    def letterCombinations(self, digits: str) -> List[str]:
        length = len(digits)
        if length == 0:
            return []

        digit_map: Dict[int, str] = {
            "1": [],
            "2": ["a", "b", "c"],
            "3": ["d", "e", "f"],
            "4": ["g", "h", "i"],
            "5": ["j", "k", "l"],
            "6": ["m", "n", "o"],
            "7": ["p", "q", "r", "s"],
            "8": ["t", "u", "v"],
            "9": ["w", "x", "y", "z"],
            "0": [" "]
        }

        current = []
        
        def backtrack(digit: int) -> Generator[None, None, str]:
            if digit == length:
                yield "".join(current[:])
                return
            
            for char in digit_map[digits[digit]]:
                current.append(char)
                yield from backtrack(digit + 1)
                current.pop()

        return tuple(combination for combination in backtrack(0))

4.7.1677 - 2023-08-03 12:32:00 +0300 MSK

Letter Combinations of a Phone Number
class Solution:
    def letterCombinations(self, digits: str) -> List[str]:
        length = len(digits)
        if length == 0:
            return []

        digit_map: Dict[int, str] = {
            "1": [],
            "2": ["a", "b", "c"],
            "3": ["d", "e", "f"],
            "4": ["g", "h", "i"],
            "5": ["j", "k", "l"],
            "6": ["m", "n", "o"],
            "7": ["p", "q", "r", "s"],
            "8": ["t", "u", "v"],
            "9": ["w", "x", "y", "z"],
            "0": [" "]
        }

        current = []
        
        def backtrack(digit: int) -> Generator[None, None, str]:
            if digit == length:
                yield "".join(current[:])
                return
            
            for char in digit_map[digits[digit]]:
                current.append(char)
                yield from backtrack(digit + 1)
                current.pop()

        return tuple(combination for combination in backtrack(0))

4.7.1678 - 2023-08-02 19:02:58 +0300 MSK

Course Schedule
class Solution:
    def canFinish(self, numCourses: int, prerequisites: List[List[int]]) -> bool:
        courses = defaultdict(set)

        for course, prereq in prerequisites:
            courses[course].add(prereq)

        if not courses:
            return True
        
        stack = set()

        @cache
        def check(course: int) -> bool:
            if course not in courses:
                return True
            
            if course in stack:
                return False

            prereqs = courses[course]

            if prereqs & stack:
                return False

            stack.add(course)

            for prereq in prereqs:
                if not check(prereq):
                    return False
    
            stack.remove(course)
            
            return True

        for course in courses:
            if not check(course):
                return False

        return True

4.7.1679 - 2023-08-02 18:11:45 +0300 MSK

Find Eventual Safe States
class Solution:
    def eventualSafeNodes(self, graph: List[List[int]]) -> List[int]:
        length = len(graph)
        indegree = [0] * length
        adj = [[] for _ in range(length)]

        for i in range(length):
            for edge in graph[i]:
                adj[edge].append(i)
                indegree[i] += 1

        q = deque()
        # Push all the nodes with indegree zero in the queue.
        for i in range(length):
            if indegree[i] == 0:
                q.append(i)

        safe = [False] * length
        while q:
            node = q.popleft()
            safe[node] = True

            for neighbor in adj[node]:
                # Delete the edge "node -> neighbor".
                indegree[neighbor] -= 1
                if indegree[neighbor] == 0:
                    q.append(neighbor)

        safe_nodes = []
        for i in range(length):
            if safe[i]:
                safe_nodes.append(i)

        return safe_nodes

4.7.1680 - 2023-08-02 17:33:24 +0300 MSK

Maximize the Confusion of an Exam
class Solution:
    def maxConsecutiveAnswers(self, answerKey: str, k: int) -> int:
        length = len(answerKey)
        char_t, char_f = "T", "F"
        max_size = k
        count = defaultdict(int)
        
        for char in answerKey[:k]:
            count[char] += 1

        left = 0
        for right in range(k, length):
            count[answerKey[right]] += 1
            
            while min(count[char_t], count[char_f]) > k: 
                count[answerKey[left]] -= 1
                left += 1
            
            size = right - left + 1
            if size > max_size:
                max_size = size
                    
        return max_size



        

4.7.1681 - 2023-08-02 11:09:23 +0300 MSK

Minimum Size Subarray Sum
class Solution:
    def minSubArrayLen(self, target: int, nums: List[int]) -> int:
        left = 0
        sum_of_subarray = 0
        min_length = float('inf')
        
        for right in range(len(nums)):
            sum_of_subarray += nums[right]
            
            while sum_of_subarray >= target:
                min_length = min(min_length, right - left + 1)
                sum_of_subarray -= nums[left]
                left += 1

        if min_length == float('inf'):
            return 0

        return min_length

4.7.1682 - 2023-08-02 11:07:07 +0300 MSK

Single Number II
class Solution:
    def singleNumber(self, nums: List[int]) -> int:
        nums.sort()
        length = len(nums)
        for i in range(0, length, 3):
            if i == length - 1:
                return nums[i]
    
            num_1, num_2, num_3 = nums[i], nums[i+1], nums[i+2]

            if num_1 == num_2 == num_3:
                continue
            
            if num_2 == num_3:
                return num_1
            
            if num_1 == num_3:
                return num_2
            
            return num_3
            

4.7.1683 - 2023-08-02 11:00:07 +0300 MSK

Buddy Strings
class Solution:
    def buddyStrings(self, s: str, goal: str) -> bool:
        length_1, length_2 = len(s), len(goal)

        if length_1 != length_2:
            return False
        
        if s == goal:
            freq = defaultdict(int)
            for char in s:
                freq[char] += 1
                if freq[char] == 2:
                    return True
            return False
        
        swap_1, swap_2 = -1, -1
        
        for i in range(length_1):
            char_1, char_2 = s[i], goal[i]
            
            if char_1 == char_2:
                continue
            
            if swap_1 == -1:
                swap_1 = i
            elif swap_2 == -1:
                swap_2 = i
            else:
                return False
            

        return swap_2 != -1 and s[swap_1] == goal[swap_2] and s[swap_2] == goal[swap_1]

4.7.1684 - 2023-08-02 10:39:16 +0300 MSK

Generate Parentheses
class Solution:
    def generateParenthesis(self, n: int) -> List[str]:

        current = []
        current_max = n * 2
        chars = "()"


        def backtrack(open: int, closed: int) -> Generator[None, None, List[str]]:
            if len(current) == current_max:
                yield "".join(current)
            
            if open:
                current.append(chars[0])
                yield from backtrack(open - 1, closed)
                current.pop()
            
            if closed and closed > open:
                current.append(chars[1])
                yield from backtrack(open, closed - 1)
                current.pop()
        
        return tuple(combination for combination in backtrack(n, n))

4.7.1685 - 2023-08-02 10:26:02 +0300 MSK

Permutations
class Solution:
    def permute(self, nums: List[int]) -> List[List[int]]:

        length = len(nums)
        current = []
        current_contains = [False] * length

        def backtrack() -> Generator[None, None, List[int]]:
            if len(current) == length:
                yield tuple(current[:])
                return

            for i in range(length):
                if current_contains[i]:
                    continue

                current_contains[i] = True
                current.append(nums[i])

                yield from backtrack()

                current_contains[i] = False
                current.pop()
            
            return

        return tuple(combination for combination in backtrack()) 

4.7.1686 - 2023-08-01 20:38:09 +0300 MSK

Maximum Number of Achievable Transfer Requests
class Solution:
    def maximumRequests(self, n, requests):
        current = [0] * n
        length = len(requests)
        
        def backtrack(req_index: int, count: int) -> int:
            if req_index == length:
                return 0 if any(current) else count

            req_from, req_to = requests[req_index]
            
            current[req_from] -= 1
            current[req_to] += 1
            take = backtrack(req_index + 1, count + 1)

            current[req_from] += 1
            current[req_to] -= 1
            non_take = backtrack(req_index + 1, count)
            
            return max(take, non_take)
        
        return backtrack(0, 0)

4.7.1687 - 2023-08-01 20:19:26 +0300 MSK

Maximum Number of Achievable Transfer Requests
class Solution:
    def __init__(self):
        self.ans = 0

    def helper(self, start, requests, indegree, n, count):
        if start == len(requests):
            for i in range(n):
                if indegree[i] != 0:
                    return
            self.ans = max(self.ans, count)
            return

        # Take 
        indegree[requests[start][0]] -= 1
        indegree[requests[start][1]] += 1
        self.helper(start + 1, requests, indegree, n, count + 1)

        # Not-take
        indegree[requests[start][0]] += 1
        indegree[requests[start][1]] -= 1
        self.helper(start + 1, requests, indegree, n, count)

    def maximumRequests(self, n, requests):
        indegree = [0] * n
        self.helper(0, requests, indegree, n, 0)
        return self.ans

4.7.1688 - 2023-08-01 18:39:03 +0300 MSK

Count Complete Subarrays in an Array
class Solution:
    def countCompleteSubarrays(self, nums: List[int]) -> int:
        length = len(nums)
        elems_count = len(set(nums))
        
        if elems_count == length:
            return 1
        
        if elems_count == 1:
            return length + sum(i for i in range(1, length))
        
        result, elems, min_j = 0, defaultdict(int), 0
        for i in range(length):
            left = nums[i]
            
            for j in range(min_j, length):
                right = nums[j]
                elems[right] += 1
                
                if len(elems) != elems_count:
                    continue
                
                if elems[right] == 1:
                    elems.pop(right)
                else:
                    elems[right] -= 1 
    
                result += length - j
                min_j = j
                break
            else:
                return result
            
            if elems[left] == 1:
                elems.pop(left)
            else:
                elems[left] -= 1
                    
        return result

4.7.1689 - 2023-08-01 17:52:16 +0300 MSK

Number of Employees Who Met the Target
class Solution:
    def numberOfEmployeesWhoMetTarget(self, hours: List[int], target: int) -> int:
        count = 0
        for hour in hours:
            if hour < target:
                continue
            count += 1
        
        return count

4.7.1690 - 2023-08-01 17:35:47 +0300 MSK

Combinations
class Solution:
    def combine(self, n: int, k: int) -> List[List[int]]:
        current = []
        
        def backtrack(first: int) -> Generator[None, None, List[int]]:
            if len(current) == k:
                yield tuple(current[:])
                return

            for i in range(first, n + 1):
                current.append(i)
                yield from backtrack(i + 1)
                current.pop()
            
            return

        return tuple(combination for combination in backtrack(1)) 

4.7.1691 - 2023-08-01 17:33:23 +0300 MSK

Combinations
class Solution:
    def combine(self, n: int, k: int) -> List[List[int]]:
        current, result = [], []
        
        def backtrack(first: int) -> None:
            if len(current) == k:
                result.append(tuple(current[:]))
                return

            for i in range(first, n + 1):
                current.append(i)
                backtrack(i + 1)
                current.pop()
            
            return

        backtrack(1)

        return result 

4.7.1692 - 2023-08-01 17:14:55 +0300 MSK

Combinations
class Solution:
    def combine(self, n: int, k: int) -> List[List[int]]:
        def generate_combinations(elems: List[int], num: int):
            total = len(elems)
            if num > total:
                return
            curr_indices = list(range(num))
            reversed_num = tuple(reversed(range(num)))

            while True:
                yield list(elems[i] for i in curr_indices)
                
                for idx in reversed_num:
                    if curr_indices[idx] != idx + total - num:
                        break
                else:
                    return

                curr_indices[idx] += 1
                for j in range(idx+1, num):
                    curr_indices[j] = curr_indices[j-1] + 1

        return [combination for combination in generate_combinations(tuple(range(1, n+1)), k)]

4.7.1693 - 2023-07-31 19:28:12 +0300 MSK

Container With Most Water
class Solution:
    def maxArea(self, height: List[int]) -> int:
        left = 0
        right = len(height) - 1
        maxArea = 0

        while left < right:
            currentArea = min(height[left], height[right]) * (right - left)
            if currentArea > maxArea:
                maxArea = currentArea

            if height[left] < height[right]:
                left += 1
            else:
                right -= 1

        return maxArea

4.7.1694 - 2023-07-31 17:17:46 +0300 MSK

Longest Palindromic Substring
class Solution:
    def longestPalindrome(self, s: str) -> str:
        n = len(s)
        dp = [[False] * n for _ in range(n)]
        ans = [0, 0]
        
        for i in range(n):
            dp[i][i] = True
        
        for i in range(n - 1):
            if s[i] == s[i + 1]:
                dp[i][i + 1] = True
                ans = [i, i + 1]

        for diff in range(2, n):
            for i in range(n - diff):
                j = i + diff
                if s[i] == s[j] and dp[i + 1][j - 1]:
                    dp[i][j] = True
                    ans = [i, j]

        i, j = ans
        return s[i:j + 1]

4.7.1695 - 2023-07-31 14:46:40 +0300 MSK

Minimum ASCII Delete Sum for Two Strings
class Solution:
    def minimumDeleteSum(self, s1: str, s2: str) -> int:
        length_1, length_2 = len(s1), len(s2)

        @cache
        def calculate(i: int, j: int) -> int:    
            if i >= length_1 and j >= length_2:
                return 0
            
            if i >= length_1:
                return sum(ord(char) for char in s2[j:])
            
            if j >= length_2:
                return sum(ord(char) for char in s1[i:])
            
            if s1[i] == s2[j]:
                return calculate(i + 1, j + 1)
            
            return min(
                ord(s1[i]) + calculate(i + 1, j),
                ord(s2[j]) + calculate(i, j + 1)
            )

        return calculate(0, 0)

4.7.1696 - 2023-07-30 20:11:15 +0300 MSK

Strange Printer
class Solution:
    def strangePrinter(self, s: str) -> int:
        n = len(s)
        dp = [[n] * n for _ in range(n)]
        for length in range(1, n + 1):
            for left in range(n - length + 1):
                right = left + length - 1
                j = -1
                for i in range(left, right):
                    if s[i] != s[right] and j == -1:
                        j = i
                    if j != -1:
                        dp[left][right] = min(dp[left][right], 1 + dp[j][i] + dp[i + 1][right])
        
                if j == -1:
                    dp[left][right] = 0

        return dp[0][n - 1] + 1

4.7.1697 - 2023-07-30 10:12:02 +0300 MSK

Predict the Winner
class Solution:
    def PredictTheWinner(self, nums: List[int]) -> bool:
        length = len(nums)
        is_even = length % 2 == 0

        if length < 3:
            return True
        
        @cache
        def max_diff(left: int, right: int) -> int:
            left_num, right_num = nums[left], nums[right]
            
            if left == right:
                return left_num
            
            score_by_left = left_num - max_diff(left + 1, right)
            score_by_right = right_num - max_diff(left, right - 1)
            return max(score_by_left, score_by_right)

        return max_diff(0, length - 1) >= 0

4.7.1698 - 2023-07-29 18:54:20 +0300 MSK

Predict the Winner
class Solution:
    def PredictTheWinner(self, nums: List[int]) -> bool:
        length = len(nums)
        is_even = length % 2 == 0

        if length < 3:
            return True
        
        @cache
        def max_diff(left: int, right: int) -> int:
            left_num, right_num = nums[left], nums[right]
            
            if left == right:
                return left_num
            
            score_by_left = left_num - max_diff(left + 1, right)
            score_by_right = right_num - max_diff(left, right - 1)
            return max(score_by_left, score_by_right)

        return max_diff(0, length - 1) >= 0

4.7.1699 - 2023-07-29 18:51:41 +0300 MSK

Predict the Winner
class Solution:
    def PredictTheWinner(self, nums: List[int]) -> bool:
        length = len(nums)
        is_even = length % 2 == 0

        if length < 3:
            return True
        
        def max_diff(left: int, right: int) -> int:
            left_num, right_num = nums[left], nums[right]
            
            if left == right:
                return left_num
            
            score_by_left = left_num - max_diff(left + 1, right)
            score_by_right = right_num - max_diff(left, right - 1)
            return max(score_by_left, score_by_right)

        return max_diff(0, length - 1) >= 0

4.7.1700 - 2023-07-29 13:24:33 +0300 MSK

Soup Servings
class Solution:
    def soupServings(self, n: int) -> float:
        servings = ceil(n / 25)

        states = defaultdict(dict)
        moves = [[-4, 0], [-3, -1], [-2, -2], [-1, -3]]
    
        @cache
        def calculate(soup_a: int, soup_b: int) -> float:
            if soup_a <= 0 and soup_b <= 0:
                return 0.5
            if soup_a <= 0:
                return 1.0
            if soup_b <= 0:
                return 0.0
            if soup_a in states and soup_b in states[soup_a]:
                return states[soup_a][soup_b]
            
            state = sum(calculate(soup_a + move[0], soup_b + move[1]) for move in moves) / 4.0
            states[soup_a][soup_b] = state

            return state

        max_probability = 1 - 1e-5

        for serving in range(1, servings + 1):
            state = calculate(serving, serving)
            if state > max_probability:
                return 1.0
        
        return calculate(servings, servings)
       

4.7.1701 - 2023-07-27 11:41:11 +0300 MSK

Fair Distribution of Cookies
class Solution:
    def distributeCookies(self, cookies: List[int], k: int) -> int:
        cur = [0] * k
        n = len(cookies)

        def dfs(i, zero_count):
            # If there are not enough cookies remaining, return `float('inf')` 
            # as it leads to an invalid distribution.
            if n - i < zero_count:
                return float('inf')
            
            # After distributing all cookies, return the unfairness of this
            # distribution.
            if i == n:
                return max(cur)
            
            # Try to distribute the i-th cookie to each child, and update answer
            # as the minimum unfairness in these distributions.
            answer = float('inf')
            for j in range(k):
                zero_count -= int(cur[j] == 0)
                cur[j] += cookies[i]
                
                # Recursively distribute the next cookie.
                answer = min(answer, dfs(i + 1, zero_count))
                
                cur[j] -= cookies[i]
                zero_count += int(cur[j] == 0)
            
            return answer
        
        return dfs(0, k)

4.7.1702 - 2023-07-27 11:39:36 +0300 MSK

Fair Distribution of Cookies
class Solution:
    def distributeCookies(self, cookies: List[int], k: int) -> int:
        cur = [0] * k
        n = len(cookies)

        def dfs(i, zero_count):
            # If there are not enough cookies remaining, return `float('inf')` 
            # as it leads to an invalid distribution.
            if n - i < zero_count:
                return float('inf')
            
            # After distributing all cookies, return the unfairness of this
            # distribution.
            if i == n:
                return max(cur)
            
            # Try to distribute the i-th cookie to each child, and update answer
            # as the minimum unfairness in these distributions.
            answer = float('inf')
            for j in range(k):
                zero_count -= int(cur[j] == 0)
                cur[j] += cookies[i]
                
                # Recursively distribute the next cookie.
                answer = min(answer, dfs(i + 1, zero_count))
                
                cur[j] -= cookies[i]
                zero_count += int(cur[j] == 0)
            
            return answer
        
        return dfs(0, k)

4.7.1703 - 2023-07-27 11:28:33 +0300 MSK

Maximum Running Time of N Computers
class Solution:
    # n = 2, batteries = [3,3,3], Output: 4
    # n = 2, batteries = [1,1,1,1], Output: 2
    def maxRunTime(self, n: int, batteries: List[int]) -> int:
        length = len(batteries)

        if length < n:
            return 0
        
        if length == n:
            return min(batteries)

        batteries.sort()
        extra = sum(batteries[:-n])
        live = batteries[-n:]

        
        # We increase the total running time using 'extra' by increasing 
        # the running time of the computer with the smallest battery.
        for i in range(n - 1):
            # If the target running time is between live[i] and live[i + 1].
            if extra // (i + 1) < live[i + 1] - live[i]:
                return live[i] + extra // (i + 1)
            
            # Reduce 'extra' by the total power used.
            extra -= (i + 1) * (live[i + 1] - live[i])
        
        # If there is power left, we can increase the running time 
        # of all computers.
        return live[-1] + extra // n

4.7.1704 - 2023-07-26 22:56:56 +0300 MSK

Minimum Speed to Arrive on Time
class Solution:
    def minSpeedOnTime(self, dist: List[int], hour: float) -> int:
        length = len(dist)
        if hour >= sum(dist):
            return 1
        
        if hour <= length - 1:
            return -1
        
        time_remaining = hour - length + 1
        max_speed = int(max(
            max(dist), dist[-1] // time_remaining + 1
        ))
        min_speed = 1
        result = -1
        while min_speed < max_speed:
            speed = min_speed + (max_speed - min_speed) // 2
            time = dist[-1] / speed + sum(
                (distance + speed - 1) // speed 
                for distance in dist[:-1]
            )
            
            if time > hour:
                min_speed = speed + 1
            else:
                max_speed = speed
        
        return min_speed

4.7.1705 - 2023-07-25 16:45:40 +0300 MSK

Peak Index in a Mountain Array
class Solution:
    # [0,3,2,1,0]
    def peakIndexInMountainArray(self, arr: List[int]) -> int:
        length = len(arr)

        left, right = 0, length - 1
        while left < right:
            mid = left + (right - left) // 2

            if arr[mid] < arr[mid + 1]:
                left = mid + 1
            else:
                right = mid

        return left
        

4.7.1706 - 2023-07-25 16:38:25 +0300 MSK

Peak Index in a Mountain Array
class Solution:
    # [0,3,2,1,0]
    def peakIndexInMountainArray(self, arr: List[int]) -> int:
        length = len(arr)

        left, right = 0, length - 1
        while left <= right:
            peak = left + (right - left) // 2
            left_val, right_val = arr[peak-1], arr[peak+1]
            peak_val = arr[peak]

            if left_val < peak_val > right_val:
                return peak
            
            if right_val > peak_val:
                left = peak + 1
            else:
                right = peak - 1
        
        return left
        

4.7.1707 - 2023-07-24 21:17:10 +0300 MSK

Longest Substring Without Repeating Characters
class Solution:
    def lengthOfLongestSubstring(self, s: str) -> int:
        length = len(s)
        if length < 2:
            return length
        
        max_length, left, charset = 1, 0, set([s[0]])
        for right in range(1, length):
            letter = s[right]
            if letter not in charset:
                charset.add(letter)
                continue

            this_length = right - left
            if this_length > max_length:
                max_length = this_length
            
            while letter in charset:
                charset.remove(s[left])
                left += 1
            
            charset.add(letter)

        return max(max_length, length - left)

4.7.1708 - 2023-07-24 21:04:18 +0300 MSK

Longest Substring Without Repeating Characters
class Solution:
    def lengthOfLongestSubstring(self, s: str) -> int:
        length = len(s)
        if length < 2:
            return length
        
        max_length = 0
        start = 0
        indexes = {s[0]: 0}
        for end in range(1, length):
            letter = s[end]
            if letter not in indexes:
                indexes[letter] = end
                continue

            this_length = end - start
            if this_length > max_length:
                max_length = this_length
            
            letter_index = indexes[letter]
            
            for remove_letter in s[start:letter_index]:
                indexes.pop(remove_letter)

            indexes[letter], start = end, letter_index + 1

        return max(max_length, length - start)

4.7.1709 - 2023-07-24 20:07:58 +0300 MSK

Construct the Rectangle
class Solution:
    def constructRectangle(self, area: int) -> List[int]:
        return next([area//width, width] 
                    for width in range(int(area**0.5), 0, -1) 
                    if area % width == 0)

4.7.1710 - 2023-07-24 19:52:59 +0300 MSK

Max Consecutive Ones
class Solution:
    def findMaxConsecutiveOnes(self, nums: List[int]) -> int:
        max_count, count = 0, 0
        for number in nums:
            if not number:
                max_count = max(max_count, count)
                count = 0
                continue
            
            count += 1
        
        return max(max_count, count)

4.7.1711 - 2023-07-24 19:34:48 +0300 MSK

License Key Formatting
class Solution:
    def licenseKeyFormatting(self, s: str, k: int) -> str:
        result = []
        count = 0
        for letter in reversed(s):
            if letter == "-":
                continue

            if count == k:
                result.append("-")
                count = 0
            
            count += 1
            result.append(letter.upper())

        return "".join(reversed(result))

4.7.1712 - 2023-07-24 19:02:15 +0300 MSK

License Key Formatting
class Solution:
    # "5F3Z-2e-9-w" -> "5F3Z2E9W" -> "5F3Z2E9W"
    def licenseKeyFormatting(self, s: str, k: int) -> str:
        letters = s.replace("-", "").upper()
        result = []
        end = len(letters)
        while end > 0:
            start = end - k
            if start < 0:
                start = 0
            result.append(letters[start:end])
            end -= k

        return "-".join(reversed(result))

4.7.1713 - 2023-07-24 18:47:17 +0300 MSK

Island Perimeter
class Solution:
    def islandPerimeter(self, grid: List[List[int]]) -> int:
        perimeter = 0
        last_row = len(grid) - 1        
        last_cell = len(grid[0]) - 1
        for i, row in enumerate(grid):
            for j, cell in enumerate(row):
                if cell == 0:
                    continue
                
                if j == 0 or row[j-1] == 0:
                    perimeter += 1
                
                if j == last_cell or row[j+1] == 0:
                    perimeter += 1
                
                if i == 0 or grid[i-1][j] == 0:
                    perimeter += 1

                if i == last_row or grid[i+1][j] == 0:
                    perimeter += 1
        
        return perimeter
                

4.7.1714 - 2023-07-24 16:56:56 +0300 MSK

Intersection of Two Arrays
class Solution:
    def intersection(self, nums1: List[int], nums2: List[int]) -> List[int]:
        return set(nums1).intersection(nums2)

4.7.1715 - 2023-07-24 16:56:13 +0300 MSK

Intersection of Two Arrays
class Solution:
    def intersection(self, nums1: List[int], nums2: List[int]) -> List[int]:
        return set(nums1) & set(nums2)

4.7.1716 - 2023-07-24 16:54:39 +0300 MSK

Find the Difference
class Solution:
    def findTheDifference(self, s: str, t: str) -> str:
        letters = defaultdict(int)
        for letter in s:
            letters[letter] += 1

        for letter in t:
            if letters[letter] == 0:
                return letter
            
            letters[letter] -= 1
        
        return None

4.7.1717 - 2023-07-24 16:51:33 +0300 MSK

First Unique Character in a String
class Solution:
    def firstUniqChar(self, s: str) -> int:
        counts = defaultdict(int)
        repeated_index = len(s)
        for letter in s:
            counts[letter] += 1
        
        for i, letter in enumerate(s):
            if counts[letter] != 1:
                continue
            
            return i
        
        return -1

4.7.1718 - 2023-07-24 16:49:38 +0300 MSK

First Unique Character in a String
class Solution:
    def firstUniqChar(self, s: str) -> int:
        counts = {}
        repeated_index = len(s)
        for i, letter in enumerate(s):
            if letter in counts:
                counts[letter] = repeated_index
                continue
            
            counts[letter] = i
        
        result = repeated_index

        for letter, index in counts.items():
            if index == repeated_index:
                continue
            
            if index < result:
                result = index

        return result if result != repeated_index else -1

4.7.1719 - 2023-07-24 16:32:14 +0300 MSK

Sum of Left Leaves
# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def sumOfLeftLeaves(self, root: Optional[TreeNode]) -> int:
        nodes = set([root])
        result = 0

        while nodes:
            node = nodes.pop()
            
            if node.left and not node.left.left and not node.left.right:
                result += node.left.val
            elif node.left:
                nodes.add(node.left)
            
            if node.right:
                nodes.add(node.right)
            
        return result

4.7.1720 - 2023-07-24 16:19:40 +0300 MSK

Longest Palindrome
class Solution:
    def longestPalindrome(self, s: str) -> int:
        counts = defaultdict(int)

        for letter in s:
            counts[letter] += 1
        
        result = sum(count if count % 2 == 0 else count - 1
                     for symbol, count in counts.items())

        if result < len(s):
            result += 1

        return result

4.7.1721 - 2023-07-24 16:17:10 +0300 MSK

Longest Palindrome
class Solution:
    def longestPalindrome(self, s: str) -> int:
        counts = defaultdict(int)

        for letter in s:
            counts[letter] += 1
        
        result = 0
        used_odd_letter = False
        for letter, count in counts.items():
            is_odd = count % 2 != 0 
            if is_odd and used_odd_letter:
                result -= 1
            elif is_odd:
                used_odd_letter = True
            result += count

        return result

4.7.1722 - 2023-07-24 13:04:29 +0300 MSK

Third Maximum Number
class Solution:
    def thirdMax(self, nums: List[int]) -> int:
        nums.sort(reverse=True)
        number_max = nums[0]
        count = 1
        for i in range(1, len(nums)):
            number = nums[i]
            if number == nums[i-1]:
                continue
            
            count += 1

            if count == 3:
                return number 
        
        return number_max

4.7.1723 - 2023-07-24 13:03:31 +0300 MSK

Third Maximum Number
class Solution:
    def thirdMax(self, nums: List[int]) -> int:
        nums.sort(reverse=True)
        number_max = nums[0]
        count = 1
        for i in range(1, len(nums)):
            number = nums[i]
            if number == nums[i-1]:
                continue
            
            count += 1

            if count == 3:
                return number 

            if number > number_max:
                number_max = number
        
        return number_max

4.7.1724 - 2023-07-24 12:58:41 +0300 MSK

Add Strings
class Solution:
    def addStrings(self, num1: str, num2: str) -> str:
        result = []
        index_1, index_2 = len(num1) - 1, len(num2) - 1


        carry = 0
        while index_1 >= 0 or index_2 >= 0 or carry:
            digit_1 = num1[index_1] if index_1 >= 0 else 0
            digit_2 = num2[index_2] if index_2 >= 0 else 0
            digit = int(digit_1) + int(digit_2) + carry
            if digit > 9:
                carry = 1
                digit %= 10
            else:
                carry = 0

            result.append(str(digit))
            index_1 -= 1
            index_2 -= 1 

        return "".join(reversed(result))

4.7.1725 - 2023-07-24 12:56:22 +0300 MSK

Add Strings
class Solution:
    def addStrings(self, num1: str, num2: str) -> str:
        result = []
        length_1, length_2 = len(num1), len(num2)
        index_1, index_2 = length_1 - 1, length_2 - 1


        carry = 0
        while index_1 >= 0 or index_2 >= 0 or carry:
            digit_1 = num1[index_1] if index_1 >= 0 else 0
            digit_2 = num2[index_2] if index_2 >= 0 else 0
            digit = int(digit_1) + int(digit_2) + carry
            if digit > 9:
                carry = 1
                digit %= 10
            else:
                carry = 0

            result.append(str(digit))
            index_1 -= 1
            index_2 -= 1 

        return "".join(reversed(result))

4.7.1726 - 2023-07-24 12:44:43 +0300 MSK

Assign Cookies
class Solution:
    def findContentChildren(self, g: List[int], s: List[int]) -> int:
        g.sort(reverse=True)
        s.sort(reverse=True)
        count = 0
        cookie_index = 0
        cookie_count = len(s)
        for greed in g:
            if cookie_index >= cookie_count or greed > s[cookie_index]:
                continue

            count += 1
            cookie_index += 1
            
        return count

4.7.1727 - 2023-07-24 12:40:04 +0300 MSK

Assign Cookies
class Solution:
    def findContentChildren(self, g: List[int], s: List[int]) -> int:
        greed = 0
        g.sort(reverse=True)
        s.sort(reverse=True)
        children_count = len(g)
        count = 0
        for cookie_size in s:
            while greed < children_count and g[greed] > cookie_size:
                greed += 1
            
            if greed >= children_count:
                break

            count += 1
            greed += 1
            
        return count

4.7.1728 - 2023-07-24 11:13:00 +0300 MSK

Pow(x, n)
class Solution:
    def myPow(self, x: float, n: int) -> float:
        if n == 0:
            return 1

        if n < 0:
            n *= -1
            x = 1 / x

        result = 1
        while n:
            if n % 2:
                result *= x
                n -= 1
            x *= x
            n //= 2
        
        return result

4.7.1729 - 2023-07-23 21:12:51 +0300 MSK

Find All Numbers Disappeared in an Array
class Solution:
    # [1,1,3,4], [1,2,3,4] -> [2]
    def findDisappearedNumbers(self, nums: List[int]) -> List[int]:
        for number in nums:
            index = abs(number) - 1
            nums[index] = -1 * abs(nums[index])
        
        return [number
                for number in range(1, len(nums) + 1) 
                if nums[number-1] > 0]
        

4.7.1730 - 2023-07-23 21:01:06 +0300 MSK

Find All Numbers Disappeared in an Array
class Solution:
    # [1,1,3,4], [1,2,3,4] -> [2]
    def findDisappearedNumbers(self, nums: List[int]) -> List[int]:
        result = {number: True for number in range(1, len(nums) + 1)}

        for number in nums:
            result[number] = False
        
        return [number for number, valid in result.items() if valid]

4.7.1731 - 2023-07-23 20:55:57 +0300 MSK

Find All Numbers Disappeared in an Array
class Solution:
    # [1,1,3,4], [1,2,3,4] -> [2]
    def findDisappearedNumbers(self, nums: List[int]) -> List[int]:
        nums.sort()
        result = []
        length = len(nums)
        j = 0
        for i in range(1, length + 1):
            while j < length and nums[j] < i:
                j += 1
            
            if j < length and nums[j] == i:
                continue

            result.append(i)

        return result

4.7.1732 - 2023-07-23 20:18:00 +0300 MSK

Arranging Coins
class Solution:
    def arrangeCoins(self, n: int) -> int:
        left, right = 0, n

        while left <= right:
            middle = left + (right - left) // 2
            coins = middle * (middle + 1) // 2

            if coins == n:
                return middle
            
            if coins > n:
                right = middle - 1
            else:
                left = middle + 1
        
        return right

4.7.1733 - 2023-07-23 20:03:43 +0300 MSK

Arranging Coins
class Solution:
    def arrangeCoins(self, n: int) -> int:
        count = 0
        row = 1
        while n >= row:
            n -= row
            row += 1
            count += 1

        return count

4.7.1734 - 2023-07-23 19:57:13 +0300 MSK

Middle of the Linked List
# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:
    def middleNode(self, head: Optional[ListNode]) -> Optional[ListNode]:
        slow = fast = head
        while fast and fast.next:
            slow = slow.next
            fast = fast.next.next
        
        return slow

4.7.1735 - 2023-07-23 19:55:42 +0300 MSK

Middle of the Linked List
# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:
    def middleNode(self, head: Optional[ListNode]) -> Optional[ListNode]:
        middle = head.next if head else None 
        tail = middle.next if middle else None
        move = True
        while tail and tail.next:
            tail = tail.next
            if move:
                middle = middle.next
            
            move = not move

        return middle if middle else head

4.7.1736 - 2023-07-23 16:50:34 +0300 MSK

All Possible Full Binary Trees
# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def allPossibleFBT(self, n: int) -> List[TreeNode]:
        if n % 2 == 0:
            return []
        if n == 1:
            return [TreeNode()]

        res = []
        for i in range(1, n, 2):
            left = self.allPossibleFBT(i)
            right = self.allPossibleFBT(n - i - 1)

            for l in left:
                for r in right:
                    root = TreeNode(0, l, r)
                    res.append(root)

        return res

4.7.1737 - 2023-07-22 19:09:00 +0300 MSK

Knight Probability in Chessboard
class Solution:
    # y x x
    # x x x
    # x x x: (2 / 8) * (4 / 16) = 0.0625
    #        (1/8, 1/8), (2/8, 2/8)
    # 
    # x x x
    # x y x
    # x x x: 0
    def __init__(self):
        self.available_moves = (
            (2, 1), (1, 2), (-2, 1), (-1, 2), (2, -1), (1, -2), 
            (-2, -1), (-1, -2)
        )
    

    def knightProbability(self, n: int, k: int, row: int, column: int) -> float:
        if k < 1:
            return 1
        
        if n < 3:
            return 0

        return self.calculate(row, column, n, k)
    
    @cache
    def calculate(self, row: int, column: int, size: int, 
                       moves_left: int) -> float:
       
        if moves_left < 1:
            return 1

        probability = 0

        for row_add, column_add in self.available_moves:
            new_row = row_add + row
            new_column = column_add + column

            if new_row < 0 or new_row >= size or (
                new_column < 0 or new_column >= size
            ):
                continue

            probability += self.calculate(
                new_row, new_column, size, moves_left - 1
            ) / 8

        return probability

4.7.1738 - 2023-07-22 17:36:35 +0300 MSK

Knight Probability in Chessboard
class Solution:
    def knightProbability(self, n: int, k: int, row: int, column: int) -> float:
        # Define possible directions for the knight's moves
        directions = [(1, 2), (1, -2), (-1, 2), (-1, -2),
                      (2, 1), (2, -1), (-2, 1), (-2, -1)]

        # Initialize the dynamic programming table
        dp = [[[0] * n for _ in range(n)] for _ in range(k + 1)]
        dp[0][row][column] = 1

        # Iterate over the number of moves
        for moves in range(1, k + 1):
            # Iterate over the cells on the chessboard
            for i in range(n):
                for j in range(n):
                    # Iterate over possible directions
                    for direction in directions:
                        prev_i, prev_j = i - direction[0], j - direction[1]
                        # Check if the previous cell is within the chessboard
                        if 0 <= prev_i < n and 0 <= prev_j < n:
                            # Add the previous probability
                            dp[moves][i][j] += dp[moves - 1][prev_i][prev_j]
                    # Divide by 8
                    dp[moves][i][j] /= 8

        # Calculate total probability by summing probabilities for all cells
        total_probability = sum(
            dp[k][i][j]
            for i in range(n)
            for j in range(n)
        )
        return total_probability

4.7.1739 - 2023-07-21 16:55:34 +0300 MSK

Repeated Substring Pattern
class Solution:
    def repeatedSubstringPattern(self, s: str) -> bool:
        length = len(s)
        for i in range(1, length // 2 + 1):
            if length % i != 0:
                continue
            
            if s == s[:i] * (length // i):
                return True
        
        return False

4.7.1740 - 2023-07-21 16:53:22 +0300 MSK

Repeated Substring Pattern
class Solution:
    def repeatedSubstringPattern(self, s: str) -> bool:
        length = len(s)
        for i in range(length-1):
            if length % (i + 1) != 0:
                continue
            
            if s == s[:i+1] * (length // (i + 1)):
                return True
        
        return False

4.7.1741 - 2023-07-21 16:40:56 +0300 MSK

Add Digits
class Solution:
    def addDigits(self, num: int) -> int:
        sum = 0
        while num > 0:
            sum += num % 10
            num //= 10
        
            if num == 0 and sum > 9:
                num, sum = sum, 0
                
        return sum

4.7.1742 - 2023-07-21 16:40:33 +0300 MSK

Add Digits
class Solution:
    def addDigits(self, num: int) -> int:
        sum = 0
        while num > 0:
            sum += num % 10
            num //= 10
        
            if num == 0 and sum > 9:
                num, sum = sum, 0
                
        return sum

4.7.1743 - 2023-07-21 16:40:14 +0300 MSK

Add Digits
class Solution:
    def addDigits(self, num: int) -> int:
        sum = 0
        while num > 0:
            sum += num % 10
            num //= 10
        
            if num == 0 and sum > 9:
                num, sum = sum, 0
                
        return sum

4.7.1744 - 2023-07-21 16:36:57 +0300 MSK

Add Digits
class Solution:
    def addDigits(self, num: int) -> int:
        sum = num
        while sum > 9:
            current_number, current_sum = sum, 0
            while current_number:
                current_sum += current_number % 10
                current_number //= 10
            sum = current_sum
        return sum

4.7.1745 - 2023-07-21 16:30:39 +0300 MSK

Implement Queue using Stacks
class MyQueue:

    def __init__(self):
        self.stack_in = []
        self.stack_out = []

    def push(self, x: int) -> None:
        self.stack_in.append(x)

    def pop(self) -> int:
        self.peek()
        return self.stack_out.pop()

    def peek(self) -> int:
        if self.stack_out:
            return self.stack_out[-1]
        
        while self.stack_in:
            self.stack_out.append(self.stack_in.pop())

        return self.stack_out[-1]

    def empty(self) -> bool:
        return not self.stack_out and not self.stack_in


# Your MyQueue object will be instantiated and called as such:
# obj = MyQueue()
# obj.push(x)
# param_2 = obj.pop()
# param_3 = obj.peek()
# param_4 = obj.empty()

4.7.1746 - 2023-07-21 16:20:49 +0300 MSK

Implement Queue using Stacks
class MyQueue:

    def __init__(self):
        self.queue = []

    def push(self, x: int) -> None:
        self.queue.insert(0, x)

    def pop(self) -> int:
        return self.queue.pop()

    def peek(self) -> int:
        return self.queue[-1]

    def empty(self) -> bool:
        return len(self.queue) == 0


# Your MyQueue object will be instantiated and called as such:
# obj = MyQueue()
# obj.push(x)
# param_2 = obj.pop()
# param_3 = obj.peek()
# param_4 = obj.empty()

4.7.1747 - 2023-07-21 16:09:40 +0300 MSK

Implement Queue using Stacks
class MyQueue:

    def __init__(self):
        self.queue = deque()

    def push(self, x: int) -> None:
        self.queue.appendleft(x)

    def pop(self) -> int:
        return self.queue.pop()

    def peek(self) -> int:
        return self.queue[-1]

    def empty(self) -> bool:
        return len(self.queue) == 0


# Your MyQueue object will be instantiated and called as such:
# obj = MyQueue()
# obj.push(x)
# param_2 = obj.pop()
# param_3 = obj.peek()
# param_4 = obj.empty()

4.7.1748 - 2023-07-21 16:06:08 +0300 MSK

Power of Two
class Solution:
    def isPowerOfTwo(self, n: int) -> bool:
        if n == 1:
            return True

        while n > 2 and not n % 2:
            n //= 2
        return n == 2

4.7.1749 - 2023-07-21 15:59:33 +0300 MSK

Remove Duplicates from Sorted List
# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:
    def deleteDuplicates(self, head: Optional[ListNode]) -> Optional[ListNode]:
        result = head
        
        while head and head.next:
            if head.next.val == head.val:
                head.next = head.next.next
                continue
            
            head = head.next
        
        return result

4.7.1750 - 2023-07-21 15:52:55 +0300 MSK

Climbing Stairs
class Solution:
    # 1: 1
    # 2: 2
    # 3: 3 [2(2), 1(1)]
    # 4: 5 [3(3), (2)]
    def climbStairs(self, n: int) -> int:
        if n < 3:
            return n

        count, count_prev = 2, 1
        for number in range(3, n + 1):
            count, count_prev = count + count_prev, count
        return count

4.7.1751 - 2023-07-21 15:33:25 +0300 MSK

Plus One
class Solution:
    def plusOne(self, digits: List[int]) -> List[int]:
        carry = 1
        for i in reversed(range(len(digits))):
            new_digit = digits[i] + carry
            if new_digit > 9:
                carry = 1
                new_digit %= 10
            else:
                carry = 0
            digits[i] = new_digit
        
        if carry:
            digits.insert(0, carry)
        
        return digits

4.7.1752 - 2023-07-21 13:34:45 +0300 MSK

Number of Steps to Reduce a Number to Zero
class Solution:
    def numberOfSteps(self, num: int) -> int:
        count = 0
        while num:
            count += 1
            if num % 2 == 0:
                num /= 2
            else:
                num -= 1
        
        return count
            

4.7.1753 - 2023-07-21 13:33:01 +0300 MSK

Fizz Buzz
class Solution:
    def fizzBuzz(self, n: int) -> List[str]:
        result = []

        for i in range(1, n + 1):
            div_by_3, div_by_5 = i % 3 == 0, i % 5 == 0
            value = None

            if div_by_3 and div_by_5:
                value = "FizzBuzz"
            elif div_by_3:
                value = "Fizz"
            elif div_by_5:
                value = "Buzz"
            else:
                value = str(i)
            
            result.append(value)
        
        return result

4.7.1754 - 2023-07-21 13:26:34 +0300 MSK

Richest Customer Wealth
class Solution:
    def maximumWealth(self, accounts: List[List[int]]) -> int:
        max_wealth = 0
        for i in range(len(accounts)):
            wealth = 0
            for j in range(len(accounts[i])):
                wealth += accounts[i][j]
            
            if wealth > max_wealth:
                max_wealth = wealth
        
        return max_wealth

4.7.1755 - 2023-07-21 13:23:06 +0300 MSK

Running Sum of 1d Array
class Solution:
    def runningSum(self, nums: List[int]) -> List[int]:
        for i in range(1, len(nums)):
            nums[i] += nums[i-1]
        return nums

4.7.1756 - 2023-07-21 13:19:55 +0300 MSK

Root Equals Sum of Children
# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def checkTree(self, root: Optional[TreeNode]) -> bool:
        return root.val == (root.left.val + root.right.val)

4.7.1757 - 2023-07-21 13:18:37 +0300 MSK

Add Two Integers
class Solution:
    def sum(self, num1: int, num2: int) -> int:
        return num1 + num2

4.7.1758 - 2023-07-21 13:11:37 +0300 MSK

Number of Longest Increasing Subsequence
class Solution:
    def findNumberOfLIS(self, nums: List[int]) -> int:
        n = len(nums)
        if n <= 1:
            return n

        lengths = [1] * n
        counts = [1] * n

        for i in range(1, n):
            for j in range(i):
                if nums[i] > nums[j]:
                    if lengths[j] + 1 > lengths[i]:
                        lengths[i] = lengths[j] + 1
                        counts[i] = counts[j]
                    elif lengths[j] + 1 == lengths[i]:
                        counts[i] += counts[j]

        max_length = max(lengths)
        return sum(count for length, count in zip(lengths, counts) if length == max_length)

4.7.1759 - 2023-07-20 12:12:22 +0300 MSK

Asteroid Collision
class Solution:
    def asteroidCollision(self, asteroids: List[int]) -> List[int]:
        stack = []
        for asteroid in asteroids:
            if asteroid > 0:
                stack.append(asteroid)
                continue
            
            asteroid_abs = abs(asteroid)
            while stack and stack[-1] > 0 and stack[-1] < asteroid_abs:
                stack.pop()
            
            if stack and stack[-1] == asteroid_abs:
                stack.pop()
            elif not stack or stack[-1] < 0:
                stack.append(asteroid)

        return stack

4.7.1760 - 2023-07-20 11:41:51 +0300 MSK

Asteroid Collision
class Solution:
    def asteroidCollision(self, asteroids: List[int]) -> List[int]:
        length = len(asteroids)

        if length < 2:
            return asteroids

        stack = [asteroids[0]]
        for i in range(1, length):
            asteroid = asteroids[i]
            asteroid_last = stack[-1] if stack else 0
            stack.append(asteroid)

            if asteroid > 0 or (
                asteroid < 0 and asteroid_last < 0
            ):
                continue

            while len(stack) >= 2 and stack[-1] < 0 and stack[-2] > 0:
                last, prev = abs(stack[-1]), abs(stack[-2])
                if last == prev:
                    stack.pop()
                elif last > prev:
                    stack[-1], stack[-2] = stack[-2], stack[-1]

                stack.pop()

        return stack

4.7.1761 - 2023-07-19 14:35:52 +0300 MSK

Best Time to Buy and Sell Stock II
class Solution:
    def maxProfit(self, prices: List[int]) -> int:
		# It is impossible to sell stock on first day, set -infinity as initial value for cur_hold
        cur_hold, cur_not_hold = -float('inf'), 0
        
        for stock_price in prices:
            prev_hold, prev_not_hold = cur_hold, cur_not_hold
			# either keep hold, or buy in stock today at stock price
            cur_hold = max(prev_hold, prev_not_hold - stock_price)
			
			# either keep not-hold, or sell out stock today at stock price
            cur_not_hold = max(prev_not_hold, 
                               prev_hold + stock_price)
            
        # maximum profit must be in not-hold state
        return cur_not_hold

4.7.1762 - 2023-07-19 14:26:39 +0300 MSK

Gas Station
class Solution:
    def canCompleteCircuit(self, gas: List[int], cost: List[int]) -> int:
        if sum(gas) < sum(cost): 
            return -1
        
        tank, idx = 0, 0
        for i in range(len(gas)):
            tank += gas[i] - cost[i] 
            if tank < 0: 
                tank, idx = 0, i+1
        return idx 

4.7.1763 - 2023-07-19 14:19:51 +0300 MSK

Jump Game II
class Solution:
    def jump(self, nums: List[int]) -> int:
        length = len(nums)
        result = 0
        end = 0
        farthest = 0

        for i in range(length - 1):
            number = nums[i]
            max_jump = i + number
            if max_jump > farthest:
                farthest = max_jump

            if farthest >= length - 1:
                result += 1
                break
            
            if i == end:
                result += 1
                end = farthest


        return result

4.7.1764 - 2023-07-19 14:19:26 +0300 MSK

Minimum Size Subarray Sum
class Solution:
    def minSubArrayLen(self, target: int, nums: List[int]) -> int:
        left = 0
        sum_of_subarray = 0
        min_length = float('inf')
        
        for right in range(len(nums)):
            sum_of_subarray += nums[right]
            
            while sum_of_subarray >= target:
                min_length = min(min_length, right - left + 1)
                sum_of_subarray -= nums[left]
                left += 1

        if min_length == float('inf'):
            return 0

        return min_length

4.7.1765 - 2023-07-19 13:39:31 +0300 MSK

H-Index
class Solution:
    # [3,0,6,1,5]
    # [0,1,3,5,6]
    def hIndex(self, citations: List[int]) -> int:
        citations = sorted(citations)
        length = len(citations)

        h = 0
        for i in reversed(range(length)):
            citations_count = citations[i]
            published_count = length - i

            if citations_count == 0 or published_count < h:
                break

            if published_count <= citations_count:
                h = published_count
            
        return h

4.7.1766 - 2023-07-19 12:33:23 +0300 MSK

Zigzag Conversion
class Solution:
    def convert(self, s: str, numRows: int) -> str:
        if numRows < 2:
            return s
        
        result: List[List[str]] = [[] for _ in range(numRows)]
    
        row, is_ascending, last = 0, True, numRows - 1
        for symbol in s:
            result[row].append(symbol)
            
            if is_ascending and row < last:
                row += 1
            elif is_ascending:
                is_ascending = False
            
            if is_ascending:
                continue

            if row > 0:
                row -= 1
            else:
                is_ascending = True
                row = 1
    
        
        return "".join("".join(row) for row in result)

4.7.1767 - 2023-07-19 11:49:03 +0300 MSK

Insert Delete GetRandom O(1)
class RandomizedSet:

    def __init__(self):
        self._set = set()
        self._items = []
        self._indexes = {}
        

    def insert(self, val: int) -> bool:
        is_in = val in self._set
        if not is_in:
            self._set.add(val)
            self._items.append(val)
            self._indexes[val] = len(self._items) - 1
        return not is_in

    def remove(self, val: int) -> bool:
        if val not in self._set:
            return False

        last = self._items[-1]
        val_index = self._indexes[val]
        self._items[val_index] = last
        self._indexes[last] = val_index
        
        self._set.remove(val)
        self._items.pop()
        self._indexes.pop(val)

        return True

    def getRandom(self) -> int:
        return random.choice(self._items)


# Your RandomizedSet object will be instantiated and called as such:
# obj = RandomizedSet()
# param_1 = obj.insert(val)
# param_2 = obj.remove(val)
# param_3 = obj.getRandom()

4.7.1768 - 2023-07-19 11:34:17 +0300 MSK

Jump Game
class Solution:
    def canJump(self, nums: List[int]) -> bool:
        length = len(nums)

        if length < 2:
            return True
        
        current = nums[0]

        for i in range(1, length):
            if current == 0:
                return False
            current -= 1
            current = max(current, nums[i])
        
        return True
            

4.7.1769 - 2023-07-19 11:26:05 +0300 MSK

Letter Combinations of a Phone Number
class Solution:
    def letterCombinations(self, digits: str) -> List[str]:
        length = len(digits)
        if length == 0:
            return []
        
        digit_map: Dict[int, str] = {
            1: [],
            2: ["a", "b", "c"],
            3: ["d", "e", "f"],
            4: ["g", "h", "i"],
            5: ["j", "k", "l"],
            6: ["m", "n", "o"],
            7: ["p", "q", "r", "s"],
            8: ["t", "u", "v"],
            9: ["w", "x", "y", "z"],
            0: [" "]
        }
        result: List[List[str]] = [
            digit_map[int(digit)] for digit in digits
        ]
        return ["".join(i) for i in product(*result)]

4.7.1770 - 2023-07-19 11:25:19 +0300 MSK

Letter Combinations of a Phone Number
class Solution:
    def letterCombinations(self, digits: str) -> List[str]:
        length = len(digits)
        if length == 0:
            return []
        
        digit_map: Dict[int, str] = {
            1: [],
            2: ["a", "b", "c"],
            3: ["d", "e", "f"],
            4: ["g", "h", "i"],
            5: ["j", "k", "l"],
            6: ["m", "n", "o"],
            7: ["p", "q", "r", "s"],
            8: ["t", "u", "v"],
            9: ["w", "x", "y", "z"],
            0: [" "]
        }
        result: List[List[str]] = [
            digit_map[int(digit)] for digit in digits
        ]
        return ["".join(i) for i in product(*result)]

4.7.1771 - 2023-07-19 11:14:44 +0300 MSK

Non-overlapping Intervals
class Solution:
    def eraseOverlapIntervals(self, intervals: List[List[int]]) -> int:
        intervals = sorted(intervals, key=lambda element: element[1])
        length = len(intervals)
        prev, count = 0, 1

        for i in range(1, length):
            if intervals[i][0] < intervals[prev][1]:
                continue
            
            prev = i
            count += 1
        
        return length - count

4.7.1772 - 2023-07-18 18:51:03 +0300 MSK

Add Two Numbers
# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:
    # create the result pointer that points towards one of the lists
    # create the result root pointer that will point towards the root of the result list
    # 1. start infinite loop
    # 2. if result is false - break, we reached the end
    # 3. get values from non-empty pointers
    # 4. add values together, store the carry in a variable
    # 5. store the value in the result pointer
    # 6. move the result pointer to the next node, if there is no next node, use a node from
    #    another list
    # 7. move list pointers
    # 8. if we have a carry left, add a node to the result list
    def addTwoNumbers(self, l1: Optional[ListNode], 
                            l2: Optional[ListNode]) -> Optional[ListNode]:
        carry = 0
        result, result_root = l1, l1

        while True:
            if not l1 and not l2:
                break
            
            number_1 = l1.val if l1 else 0
            number_2 = l2.val if l2 else 0
            result_val = number_1 + number_2 + carry
            if result_val > 9:
                carry, result_val = 1, result_val - 10
            else:
                carry = 0
            
            result.val = result_val
            if not result.next and l2:
                l1 = None
                result.next = l2.next

            if result.next:
                result = result.next
            if l1:
                l1 = l1.next
            if l2:
                l2 = l2.next

        if carry:
            result.next = ListNode(carry)

        return result_root

4.7.1773 - 2023-07-18 18:50:17 +0300 MSK

LRU Cache
class LRUCache:
    class Node:
        def __init__(self, key: str, val: int) -> None:
            self.key = key
            self.val = val
            self.prev: Node = None
            self.next: Node = None

    def __init__(self, capacity: int) -> None:
        self.cap = capacity
        self.head = self.Node(-1, -1)
        self.tail = self.Node(-1, -1)
        self.head.next = self.tail
        self.tail.prev = self.head
        self.cache = {}

    def add_node(self, new_node: Node) -> None:
        old_first_node = self.head.next
        new_node.next = old_first_node
        new_node.prev = self.head
        self.head.next = new_node
        old_first_node.prev = new_node

    def delete_node(self, delete_node: Node) -> None:
        prev = delete_node.prev
        next = delete_node.next
        prev.next = next
        next.prev = prev

    def get(self, key: int) -> int:
        if key not in self.cache:
            return -1
        result_node = self.cache[key]
        result = result_node.val
        del self.cache[key]
        self.delete_node(result_node)
        self.add_node(result_node)
        self.cache[key] = self.head.next
        return result
    

    def put(self, key: int, value: int) -> None:
        if key in self.cache:
            current = self.cache[key]
            del self.cache[key]
            self.delete_node(current)

        if len(self.cache) == self.cap:
            del self.cache[self.tail.prev.key]
            self.delete_node(self.tail.prev)

        self.add_node(self.Node(key, value))
        self.cache[key] = self.head.next

# Your LRUCache object will be instantiated and called as such:
# obj = LRUCache(capacity)
# param_1 = obj.get(key)
# obj.put(key,value)

4.7.1774 - 2023-07-18 18:39:57 +0300 MSK

LRU Cache
class LRUCache:
    class Node:
        def __init__(self, key: str, val: int) -> None:
            self.key = key
            self.val = val
            self.prev: Node = None
            self.next: Node = None

    def __init__(self, capacity: int) -> None:
        self.cap = capacity
        self.head = self.Node(-1, -1)
        self.tail = self.Node(-1, -1)
        self.head.next = self.tail
        self.tail.prev = self.head
        self.cache = {}

    def add_node(self, new_node: Node) -> None:
        old_first_node = self.head.next
        new_node.next = old_first_node
        new_node.prev = self.head
        self.head.next = new_node
        old_first_node.prev = new_node

    def delete_node(self, delete_node: Node) -> None:
        prev = delete_node.prev
        next = delete_node.next
        prev.next = next
        next.prev = prev

    def get(self, key: int) -> int:
        if key not in self.cache:
            return -1
        result_node = self.cache[key]
        result = result_node.val
        del self.cache[key]
        self.delete_node(result_node)
        self.add_node(result_node)
        self.cache[key] = self.head.next
        return result
    

    def put(self, key: int, value: int) -> None:
        if key in self.cache:
            current = self.cache[key]
            del self.cache[key]
            self.delete_node(current)

        if len(self.cache) == self.cap:
            del self.cache[self.tail.prev.key]
            self.delete_node(self.tail.prev)

        self.add_node(self.Node(key, value))
        self.cache[key] = self.head.next

# Your LRUCache object will be instantiated and called as such:
# obj = LRUCache(capacity)
# param_1 = obj.get(key)
# obj.put(key,value)

4.7.1775 - 2023-07-18 18:25:23 +0300 MSK

Search a 2D Matrix
class Solution:
    def searchMatrix(self, matrix: List[List[int]], target: int) -> bool:
        length_vertical, length_horizontal = len(matrix), len(matrix[0])


        left, right = 0, length_vertical - 1
        while left <= right:
            mid = left + (right - left) // 2
            mid_number = matrix[mid][0]
            
            if mid_number == target:
                return True
            
            if mid_number > target:
                right = mid - 1
            else:
                left = mid + 1
        
        vertical_index = right
        left, right = 0, length_horizontal - 1
        while left <= right:
            mid = left + (right - left) // 2
            mid_number = matrix[vertical_index][mid]

            if mid_number == target:
                return True
            
            if mid_number > target:
                right = mid - 1
            else:
                left = mid + 1
            
        return False

4.7.1776 - 2023-07-18 18:14:47 +0300 MSK

Search Insert Position
class Solution:
    def searchInsert(self, nums: List[int], target: int) -> int:
        length = len(nums)
        left, right = 0, length - 1

        while left <= right:
            mid = left + (right - left) // 2
            mid_number = nums[mid]

            if mid_number == target:
                return mid

            if mid_number > target:
                right = mid - 1
            else:
                left = mid + 1

        return left

4.7.1777 - 2023-07-18 18:10:20 +0300 MSK

Sqrt(x)
class Solution:
    def mySqrt(self, x: int) -> int:
        if x == 0 or x == 1:
            return x

        left, right = 1, x

        while left <= right:
            mid = left + (right - left) // 2
            square = mid * mid

            if square == x:
                return mid
            
            if square > x:
                right = mid - 1 
            else:
                left = mid + 1
            
        return right

4.7.1778 - 2023-07-18 18:02:32 +0300 MSK

Palindrome Number
class Solution:
    def isPalindrome(self, x: int) -> bool:
        if x < 0:
            return False
        
        if x < 10:
            return True
        
        number = []

        while x:
            remainder = x % 10
            x = x // 10
            number.append(remainder)
            
        length = len(number)
        half_index = length // 2

        for i, digit in enumerate(number):
            last_digit = number[length - i - 1]

            if digit != last_digit:
                return False
            
            if i != half_index:
                continue
            
            return True

4.7.1779 - 2023-07-18 18:01:12 +0300 MSK

Palindrome Number
class Solution:
    def isPalindrome(self, x: int) -> bool:
        if x < 0:
            return False
        
        if x < 10:
            return True
        
        number = []

        while x:
            remainder = x % 10
            x = x // 10
            number.append(remainder)
            
        length = len(number)
        half_index = length // 2

        for i, digit in enumerate(number):
            last_digit = number[length - i - 1]

            if digit != last_digit:
                return False
            
            if i != half_index:
                continue
            
            return True

4.7.1780 - 2023-07-18 17:58:35 +0300 MSK

Evaluate Reverse Polish Notation
class Solution:
    def evalRPN(self, tokens: List[str]) -> int:
        stack = []
        operations = {
            "+": lambda first, second: first + second,
            "-": lambda first, second: first - second,
            "*": lambda first, second: first * second,
            "/": lambda first, second: int(first / second)
        }
        for token in tokens:
            if token not in operations:
                stack.append(int(token))
                continue

            second, first = stack.pop(), stack.pop()
            result = operations[token](first, second)
            stack.append(result)
            
        return stack[-1]

4.7.1781 - 2023-07-18 17:57:21 +0300 MSK

Add Two Numbers II
# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:
    def reverse(self, head: ListNode) -> ListNode:
        previous = None
        while head:
            next, head.next = head.next, previous
            previous, head = head, next
        return previous

    def addTwoNumbers(self, l1: Optional[ListNode], l2: Optional[ListNode]) -> Optional[ListNode]:
        l1, l2 = self.reverse(l1), self.reverse(l2)
        head, tail, carry = l1, l1, 0

        while l1 or l2 or carry:
            val_1 = l1.val if l1 else 0
            val_2 = l2.val if l2 else 0
            sum = val_1 + val_2 + carry
            if sum > 9:
                carry = 1
                sum %= 10
            else:
                carry = 0

            tail.val = sum
            l1, l2 = l1.next if l1 else None, l2.next if l2 else None
            if not tail.next and l2:
                tail.next = l2
                l1 = None

            if not tail.next and carry:
                tail.next = ListNode(carry)
                carry = 0
                l2 = None

            if tail.next:
                tail = tail.next
            
        return self.reverse(head)

4.7.1782 - 2023-07-18 17:10:30 +0300 MSK

Reverse Linked List
# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:
    def reverseList(self, head: Optional[ListNode]) -> Optional[ListNode]:
        previous = None
        while head:
            next, head.next = head.next, previous
            previous, head = head, next

        return previous

4.7.1783 - 2023-07-18 16:55:29 +0300 MSK

Two Sum II - Input Array Is Sorted
class Solution:
    def twoSum(self, numbers: List[int], target: int) -> List[int]:
        numbers_map: Dict[str, int] = {}

        for i, number in enumerate(numbers):
            diff = target - number
            if diff in numbers_map:
                return [numbers_map[diff] + 1, i + 1]
            numbers_map[number] = i
        
        return []

4.7.1784 - 2023-07-18 16:41:40 +0300 MSK

Reverse Words in a String
class Solution:
    def reverseWords(self, s: str) -> str:
        return " ".join(s.split()[::-1])

4.7.1785 - 2023-07-18 16:37:43 +0300 MSK

Integer to Roman
class Solution:
    def intToRoman(self, num: int) -> str:
        result: List[str] = []
        stack: List[int] = deque([
            1, 4, 5, 9, 10, 40, 50, 90, 100, 400, 500, 900, 1000
        ])
        values = {
            1000: "M",
            900: "CM",
            500: "D",
            400: "CD",
            100: "C",
            90: "XC",
            50: "L",
            40: "XL",
            10: "X",
            9: "IX",
            5: "V",
            4: "IV",  
            1: "I"
        }

        while num:
            roman = stack[-1]
            if num < roman:
                stack.pop()
                continue

            result.append(values[roman])
            num -= roman

        return "".join(result)

4.7.1786 - 2023-07-18 16:15:43 +0300 MSK

Evaluate Reverse Polish Notation
class Solution:
    def evalRPN(self, tokens: List[str]) -> int:
        stack = []
        operations = {
            "+": lambda first, second: first + second,
            "-": lambda first, second: first - second,
            "*": lambda first, second: first * second,
            "/": lambda first, second: int(first / second)
        }
        for token in tokens:
            if token not in operations:
                stack.append(int(token))
                continue

            second, first = stack.pop(), stack.pop()
            result = operations[token](first, second)
            stack.append(result)
            
        return stack[-1]

4.7.1787 - 2023-07-18 15:49:17 +0300 MSK

Min Stack
from sortedcontainers import sortedset

class MinStack:

    def __init__(self):
        self.stack: List[int] = []
        self.min_stack: List[int] = []

    def push(self, val: int) -> None:
        self.stack.append(val)
        if not self.min_stack or val <= self.min_stack[-1]:
            self.min_stack.append(val)

    def pop(self) -> None:
        if not self.stack:
            return
        pop = self.stack.pop()
        if pop == self.min_stack[-1]:
            self.min_stack.pop()

    def top(self) -> int:
        return self.stack[-1]

    def getMin(self) -> int:
        return self.min_stack[-1]


# Your MinStack object will be instantiated and called as such:
# obj = MinStack()
# obj.push(val)
# obj.pop()
# param_3 = obj.top()
# param_4 = obj.getMin()

4.7.1788 - 2023-07-18 15:46:05 +0300 MSK

Min Stack
from sortedcontainers import sortedset

class MinStack:
    class Node:
        def __init__(self, val: int, prev: 'Node'):
            self.val = val
            self.prev = prev


    def __init__(self):
        self.stack: List[Node] = []
        self.min_node = None

    def push(self, val: int) -> None:
        new_node = self.Node(val, None)
        self.stack.append(new_node)
        if self.min_node is None or val <= self.min_node.val:
            new_node.prev = self.min_node
            self.min_node = new_node

    def pop(self) -> None:
        pop = self.stack.pop()
        if pop == self.min_node:
            self.min_node = self.min_node.prev

    def top(self) -> int:
        return self.stack[-1].val

    def getMin(self) -> int:
        return self.min_node.val


# Your MinStack object will be instantiated and called as such:
# obj = MinStack()
# obj.push(val)
# obj.pop()
# param_3 = obj.top()
# param_4 = obj.getMin()

4.7.1789 - 2023-07-18 15:23:22 +0300 MSK

Simplify Path
class Solution:
    def simplifyPath(self, path: str) -> str:
        canonical = []
        for directory in path.split("/"):
            if not directory or directory == ".":
                continue
            
            if directory != "..":
                canonical.append(directory)
                continue
            
            if len(canonical):
                canonical.pop()

        return "/" + "/".join(canonical)

4.7.1790 - 2023-07-18 15:15:34 +0300 MSK

Longest Consecutive Sequence
class Solution:
    def longestConsecutive(self, nums: List[int]) -> int:
        length = len(nums)
        if length < 2:
            return length
        
        nums = set(nums)
        longest = 1
        for number in nums:
            if number - 1 in nums:
                continue
            consequent = 1
            while number + consequent in nums:
                consequent += 1
            longest = max(longest, consequent)
        
        return longest

4.7.1791 - 2023-07-18 15:08:44 +0300 MSK

Longest Consecutive Sequence
from sortedcontainers import SortedSet

class Solution:
    def longestConsecutive(self, nums: List[int]) -> int:
        nums = SortedSet(nums)
        longest, current = 0, 0
        for number in nums:
            if number - 1 in nums:
                current += 1
                continue
            if current > longest:
                longest = current
            current = 1
        return max(current, longest)
            

4.7.1792 - 2023-07-18 14:53:17 +0300 MSK

Group Anagrams
class Solution:
    def groupAnagrams(self, strs: List[str]) -> List[List[str]]:
        anagrams: Dict[str, List[str]] = defaultdict(list)

        for string in strs:
            anagrams["".join(sorted(string))].append(string)
        
        return anagrams.values()

4.7.1793 - 2023-07-18 14:46:38 +0300 MSK

LRU Cache
class LRUCache:
    class Node:
        def __init__(self, key: str, val: int) -> None:
            self.key = key
            self.val = val
            self.prev: Node = None
            self.next: Node = None

    def __init__(self, capacity: int) -> None:
        self.cap = capacity
        self.head = self.Node(-1, -1)
        self.tail = self.Node(-1, -1)
        self.head.next = self.tail
        self.tail.prev = self.head
        self.cache = {}

    def add_node(self, new_node: Node) -> None:
        old_first_node = self.head.next
        new_node.next = old_first_node
        new_node.prev = self.head
        self.head.next = new_node
        old_first_node.prev = new_node

    def delete_node(self, delete_node: Node) -> None:
        prev = delete_node.prev
        next = delete_node.next
        prev.next = next
        next.prev = prev

    def get(self, key: int) -> int:
        if key not in self.cache:
            return -1
        result_node = self.cache[key]
        result = result_node.val
        del self.cache[key]
        self.delete_node(result_node)
        self.add_node(result_node)
        self.cache[key] = self.head.next
        return result
    

    def put(self, key: int, value: int) -> None:
        if key in self.cache:
            current = self.cache[key]
            del self.cache[key]
            self.delete_node(current)

        if len(self.cache) == self.cap:
            del self.cache[self.tail.prev.key]
            self.delete_node(self.tail.prev)

        self.add_node(self.Node(key, value))
        self.cache[key] = self.head.next

# Your LRUCache object will be instantiated and called as such:
# obj = LRUCache(capacity)
# param_1 = obj.get(key)
# obj.put(key,value)

4.7.1794 - 2023-07-18 13:48:20 +0300 MSK

Rotate Array
class Solution:
    def rotate(self, nums: List[int], k: int) -> None:
        """
        Do not return anything, modify nums in-place instead.
        """
        length = len(nums)
        k %= length
        nums[length - k:] = nums[length - k:][::-1]  
        nums[:length - k] = nums[:length - k][::-1]   
        nums[:] = nums[::-1] 

4.7.1795 - 2023-07-16 19:26:31 +0300 MSK

Remove Duplicates from Sorted Array II
class Solution:
    def removeDuplicates(self, nums: List[int]) -> int:
        length = len(nums)

        if length < 2:
            return length
        
        current_index = 2

        for number in nums[2:]:
            if number == nums[current_index-2]:
                continue
            
            nums[current_index] = number
            current_index += 1

        return current_index

4.7.1796 - 2023-07-16 19:19:33 +0300 MSK

Remove Duplicates from Sorted Array II
class Solution:
    def removeDuplicates(self, nums: List[int]) -> int:
        length = len(nums)

        if length < 2:
            return length
        
        current_number, unique, current_index = nums[0], True, 1
        for number in nums[1:]:
            if current_number != number:
                current_number = number
                unique = True
                nums[current_index] = number
                current_index += 1
                continue

            if unique:
                nums[current_index] = number
                current_index += 1
                unique = False

        return current_index

4.7.1797 - 2023-07-16 18:35:46 +0300 MSK

Same Tree
# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def isSameTree(self, p: Optional[TreeNode], q: Optional[TreeNode]) -> bool:
        if p and not q or (q and not p):
            return False
        
        if not p and not q:
            return True
        
        if p.val != q.val:
            return False
        
        return self.isSameTree(p.left, q.left) and self.isSameTree(p.right, q.right)

4.7.1798 - 2023-07-16 15:06:38 +0300 MSK

Maximum Depth of Binary Tree
# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def maxDepth(self, root: Optional[TreeNode], depth: int = 0) -> int:
        if not root:
            return depth

        return max(self.maxDepth(root.left, depth + 1), self.maxDepth(root.right, depth + 1))
        

4.7.1799 - 2023-07-16 15:04:36 +0300 MSK

Maximum Depth of Binary Tree
# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def maxDepth(self, root: Optional[TreeNode], count: int = 0) -> int:
        if not root:
            return 0
        
        if not root.left and not root.right:
            return count + 1

        return max(self.maxDepth(root.left, count + 1), self.maxDepth(root.right, count + 1))
        

4.7.1800 - 2023-07-16 13:34:50 +0300 MSK

Merge Two Sorted Lists
# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next

class Solution:
    def mergeTwoLists(self, list1: Optional[ListNode], list2: Optional[ListNode]) -> Optional[ListNode]:
        if not list1:
            return list2
        
        if not list2:
            return list1
        
        head = None
        if list1.val < list2.val:
            head, list1 = list1, list1.next 
        else:
            head, list2 = list2, list2.next
        
        current = head
        while list1 and list2:
            if list1.val < list2.val:
                current.next, list1 = list1, list1.next
            else:
                current.next, list2 = list2, list2.next
            
            current = current.next

        if list1 or list2:
            current.next = list1 if list1 else list2

        return head

4.7.1801 - 2023-07-16 12:53:42 +0300 MSK

Linked List Cycle
# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution:
    def hasCycle(self, head: Optional[ListNode]) -> bool:
        slow_p, fast_p = head, head.next if head else None
        while fast_p and fast_p.next:
            if slow_p == fast_p:
                return True
            slow_p, fast_p = slow_p.next, fast_p.next.next

        return False

4.7.1802 - 2023-07-16 12:51:01 +0300 MSK

Linked List Cycle
# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution:
    def hasCycle(self, head: Optional[ListNode]) -> bool:
        slow_p, fast_p = head, head.next if head else None
        while slow_p and fast_p:
            if slow_p == fast_p:
                return True
            slow_p = slow_p.next
            fast_p = fast_p.next if fast_p else None
            fast_p = fast_p.next if fast_p else None
        
        return False

4.7.1803 - 2023-07-16 12:38:36 +0300 MSK

Valid Parentheses
class Solution:
    def isValid(self, s: str) -> bool:
        length = len(s)
        if length < 2:
            return False

        brackets_open = {
            "{": "}",
            "(": ")",
            "[": "]"
        }
        brackets_close = brackets_open.values()
        stack = [s[0]]

        for bracket in s[1:]:
            if bracket not in brackets_close:
                stack.append(bracket)
                continue

            if len(stack) == 0 or brackets_open.get(stack[-1]) != bracket:
                return False
            
            stack.pop()

        return not len(stack) 

4.7.1804 - 2023-07-16 12:17:02 +0300 MSK

Contains Duplicate II
class Solution:
    def containsNearbyDuplicate(self, nums: List[int], k: int) -> bool:
        indexes = {}
        for i, number in enumerate(nums):
            if number in indexes and abs(i - indexes[number]) <= k:
                return True
            indexes[number] = i
        return False

            

4.7.1805 - 2023-07-16 12:16:10 +0300 MSK

Contains Duplicate II
class Solution:
    def containsNearbyDuplicate(self, nums: List[int], k: int) -> bool:
        indexes = defaultdict(set)
        for i, number in enumerate(nums):
            if number in indexes and any(abs(i - j) <= k for j in indexes[number]):
                return True
            indexes[number].add(i)
        return False

            

4.7.1806 - 2023-07-16 10:47:21 +0300 MSK

Happy Number
class Solution:
    def isHappy(self, n: int) -> bool:
        sums = set()
        while n != 1:
            if n in sums:
                return False
            sums.add(n)
            
            sum = 0
            while n > 0:
                sum += (n % 10 )**2
                n = n // 10
            n = sum

        return True

4.7.1807 - 2023-07-16 10:41:43 +0300 MSK

Happy Number
class Solution:
    def isHappy(self, n: int) -> bool:
        while True:
            sum = 0
            while n > 0:
                sum += (n % 10 )**2
                n = n // 10
            n = sum
            if sum < 10:
                break

        return n in [1, 7]

4.7.1808 - 2023-07-16 10:41:26 +0300 MSK

Happy Number
class Solution:
    def isHappy(self, n: int) -> bool:
        while True:
            sum = 0
            while n > 0:
                sum += (n % 10 )**2
                n = n // 10
            n = sum
            print(n)
            if sum < 10:
                break

        return n in [1, 7]

4.7.1809 - 2023-07-15 21:24:48 +0300 MSK

Two Sum
class Solution:
    def twoSum(self, nums: List[int], target: int) -> List[int]:
        indexes = {}
        for i, number in enumerate(nums):
            diff = target - number
            if diff in indexes: 
                return [indexes[diff], i]
            indexes[number] = i

4.7.1810 - 2023-07-15 21:22:16 +0300 MSK

Valid Anagram
class Solution:
    def isAnagram(self, s: str, t: str) -> bool:
        s_length, t_length = len(s), len(t)

        if s_length != t_length:
            return False
        
        count = defaultdict(int)
        for i, s_symbol in enumerate(s):
            t_symbol = t[i]
            count[s_symbol] += 1
            count[t_symbol] -= 1

        return not any((i != 0 for i in count.values())) 

4.7.1811 - 2023-07-15 21:11:36 +0300 MSK

Word Pattern
class Solution:
    def wordPattern(self, pattern: str, s: str) -> bool:
        words = s.split()
        words_length, pattern_length = len(words), len(pattern)

        if words_length != pattern_length:
            return False
        
        symbol_to_word = {}
        word_to_symbol = {}

        for i, symbol in enumerate(pattern):
            word = words[i]
            symbol_in, word_in = symbol in symbol_to_word, word in word_to_symbol

            if symbol_in and word_in and symbol_to_word[symbol] == word:
                continue

            if not symbol_in and not word_in:
                symbol_to_word[symbol] = word
                word_to_symbol[word] = symbol
                continue

            return False
        
        return True
            

4.7.1812 - 2023-07-15 20:53:31 +0300 MSK

Isomorphic Strings
class Solution:
    def isIsomorphic(self, s: str, t: str) -> bool:
        s_length, t_length = len(s), len(t)
        if s_length != t_length:
            return False
        
        s_to_t = {}
        t_to_s = {}
        for i, s_symbol in enumerate(s):
            t_symbol = t[i]

            if s_symbol not in s_to_t and t_symbol not in t_to_s:
                s_to_t[s_symbol] = t_symbol
                t_to_s[t_symbol] = s_symbol
            elif s_symbol in s_to_t and s_to_t[s_symbol] == t_symbol:
                continue
            else:
                return False
                
        return True

4.7.1813 - 2023-07-15 20:49:31 +0300 MSK

Isomorphic Strings
class Solution:
    def isIsomorphic(self, s: str, t: str) -> bool:
        return list(map(s.index, s)) == list(map(t.index, t))

4.7.1814 - 2023-07-15 20:05:44 +0300 MSK

Ransom Note
class Solution:
    def canConstruct(self, ransomNote: str, magazine: str) -> bool:
        ransom_i, magazine_i = 0, 0
        ransom_length, magazine_length = len(ransomNote), len(magazine)

        if magazine_length < ransom_length:
            return False
        
        if ransom_length == 1:
            return ransomNote in magazine

        symbols = [0 for _ in range(26)]

        for symbol in magazine:
            symbols[ord(symbol)-97] += 1

        for symbol in ransomNote:
            symbols[ord(symbol)-97] -= 1
        
        
        return not any((count < 0 for count in symbols))

4.7.1815 - 2023-07-15 19:55:32 +0300 MSK

Ransom Note
class Solution:
    # two indexes: ransom_i, magazine_i
    # sort both ransomNote and magazine (ascending order)
    # while indexes have not reached the end:
    # - if ransom symbol is equal to the magazine_symbol: increase both indexes
    # - if it is not equal, increase only magazine index
    # return wheter the ranson index is equal to the length of the ransom
    def canConstruct(self, ransomNote: str, magazine: str) -> bool:
        ransom_i, magazine_i = 0, 0
        ransom_length, magazine_length = len(ransomNote), len(magazine)

        if magazine_length < ransom_length:
            return False
        
        if ransom_length == 1:
            return ransomNote in magazine

        ransomNote = sorted(ransomNote)
        magazine = sorted(magazine)

        while ransom_i < ransom_length and magazine_i < magazine_length:
            ransom_symbol, magazine_symbol = ransomNote[ransom_i], magazine[magazine_i]
            
            if magazine_symbol > ransom_symbol:
                return False

            if ransom_symbol == magazine_symbol:
                ransom_i += 1
            
            magazine_i += 1

        return ransom_i == ransom_length

4.7.1816 - 2023-07-15 19:35:16 +0300 MSK

Ransom Note
class Solution:
    # two indexes: ransom_i, magazine_i
    # sort both ransomNote and magazine (ascending order)
    # while indexes have not reached the end:
    # - if ransom symbol is equal to the magazine_symbol: increase both indexes
    # - if it is not equal, increase only magazine index
    # return wheter the ranson index is equal to the length of the ransom
    def canConstruct(self, ransomNote: str, magazine: str) -> bool:
        ransom_i, magazine_i = 0, 0
        ransom_length, magazine_length = len(ransomNote), len(magazine)
        ransomNote = sorted(ransomNote)
        magazine = sorted(magazine)

        if magazine_length < ransom_length:
            return False

        while ransom_i < ransom_length and magazine_i < magazine_length:
            ransom_symbol, magazine_symbol = ransomNote[ransom_i], magazine[magazine_i]
            
            if ransom_symbol == magazine_symbol:
                ransom_i += 1
                
            magazine_i += 1

        return ransom_i == ransom_length

4.7.1817 - 2023-07-13 21:11:33 +0300 MSK

Is Subsequence
class Solution:
    # create two pointers, original and sub, both are zero
    # while either of those pointers have not reached the end:
    # - if original symbol is equal to the sub, move both pointer to the right
    # - if not, move original pointer to the right
    # if sub pointer reached the end, return True, otherwise False
    def isSubsequence(self, s: str, t: str) -> bool:
        original, sub = 0, 0
        original_length, sub_length = len(t), len(s)

        while original < original_length and sub < sub_length:
            if s[sub] == t[original]:
                original += 1
                sub += 1
                continue
            
            original += 1

        return sub == sub_length

4.7.1818 - 2023-07-13 20:57:51 +0300 MSK

Longest Common Prefix
class Solution:
    
    def longestCommonPrefix(self, strs: List[str]) -> str:
        if len(strs) == 1:
            return strs[0]

        min_length = min([len(string) for string in strs])
        prefix = strs[0][0:min_length]
        for string in strs:
            if not prefix:
                return ""
            
            while not string.startswith(prefix):
                prefix = prefix[0:-1]
            
        return prefix

4.7.1819 - 2023-07-13 20:49:03 +0300 MSK

Longest Common Prefix
class Solution:
    
    def longestCommonPrefix(self, strs: List[str]) -> str:
        if len(strs) == 1:
            return strs[0]

        min_length = min([len(string) for string in strs])
        for i in range(min_length, -1, -1):
            current = strs[0][0:i+1]
            for string in strs[1:]:
                if string[0:i+1] != current:
                    break
            else:
                return current

        return ""    

4.7.1820 - 2023-07-13 20:34:54 +0300 MSK

Roman to Integer
class Solution:
    def romanToInt(self, input_numbers: str) -> int:
        result = 0
        previous = None
        values = {
            "I": 1,
            "V": 5,
            "X": 10,
            "L": 50,
            "C": 100,
            "D": 500,
            "M": 1000,
        }
        subtractions = set(["IV", "IX", "XL", "XC", "CD", "CM"])

        for number in input_numbers:
            if f"{previous}{number}" in subtractions:
                result += values[number] - values[previous] * 2
            else:
                result += values[number]
            previous = number
        
        return result
            

4.7.1821 - 2023-07-13 20:32:03 +0300 MSK

Majority Element
class Solution:
    def majorityElement(self, nums: List[int]) -> int:
        return sorted(nums)[len(nums)//2]
                

4.7.1822 - 2023-07-13 20:30:18 +0300 MSK

Best Time to Buy and Sell Stock
class Solution:
    # Input: prices = [7,1,5,3,6,4]
    # Output: 5
    # Explanation: Buy on day 2 (price = 1) and sell on day 5 (price = 6), profit = 6-1 = 5.
    # Note that buying on day 2 and selling on day 1 is not allowed because you must buy 
    # before you sell.
    def maxProfit(self, prices: List[int]) -> int:
        length = len(prices)
        if length < 2:
            return 0

        left, right, profit = 0, 1, 0
        while right < length:
            current_profit = prices[right] - prices[left]
            is_profitable = current_profit > 0
            if is_profitable and current_profit > profit:
                profit = current_profit
            elif not is_profitable:
                left = right
            
            right += 1

        return profit

4.7.1823 - 2023-07-13 20:19:45 +0300 MSK

Best Time to Buy and Sell Stock
class Solution:
    # Input: prices = [7,1,5,3,6,4]
    # Output: 5
    # Explanation: Buy on day 2 (price = 1) and sell on day 5 (price = 6), profit = 6-1 = 5.
    # Note that buying on day 2 and selling on day 1 is not allowed because you must buy 
    # before you sell.
    def maxProfit(self, prices: List[int]) -> int:
        length = len(prices)
        if length < 2:
            return 0

        left, right, profit = 0, 1, 0
        while right < length:
            current_profit = prices[right] - prices[left]
            if current_profit > 0:
                profit = max(current_profit, profit)
            else:
                left = right
            right += 1

        return profit

4.7.1824 - 2023-07-13 19:37:36 +0300 MSK

Majority Element
class Solution:
    def majorityElement(self, nums: List[int]) -> int:
        return sorted(nums)[len(nums)//2]
                

4.7.1825 - 2023-07-13 19:13:31 +0300 MSK

Remove Duplicates from Sorted Array
class Solution:
    # non-decreasing order, so to remove the duplicates we just need to remove all 
    #    consequent duplicates
    # create replace index, set it to 1 - the first element is always unique
    # check if length is more than 1 to avoid out-of-bounds - 
    #   if the length is one, just return 1
    # iterate over nums starting from the second element:
    # - if the current number is not equal to the previous, 
    #   set nums[replace] to it, move the replace index
    # - if the current number is equal to the previous one, continue 
    # return replace 
    def removeDuplicates(self, nums: List[int]) -> int:
        replace = 1
        for i, number in enumerate(nums[1:], 1): 
            if number == nums[i-1]:
                continue
            nums[replace] = number
            replace += 1
        
        return replace

4.7.1826 - 2023-07-13 19:03:15 +0300 MSK

Remove Duplicates from Sorted Array
class Solution:
    # non-decreasing order, so to remove the duplicates we just need to remove all 
    #    consequent duplicates
    # create replace index, set it to 0
    # create a set of duplicates
    # iterate over nums:
    # - if the number is in the set, continue
    # - if the number is not in the set, set nums[replace] to that number, add it to the set
    # return replace
    def removeDuplicates(self, nums: List[int]) -> int:
        replace, duplicates = 0, set()
        for i, number in enumerate(nums): 
            if number in duplicates:
                continue
            nums[replace] = number
            replace += 1
            duplicates.add(number)
        
        return replace

4.7.1827 - 2023-07-13 18:52:44 +0300 MSK

Remove Element
class Solution:
    # create replace index
    # iterate over nums:
    # - if the current number is equal to val, continue
    # - set nums[replace] to that number, increase the index

    def removeElement(self, nums: List[int], val: int) -> int:
        replace = 0
        for i, number in enumerate(nums):
            if number == val:
                continue
            nums[replace] = number
            replace += 1
        
        return replace

4.7.1828 - 2023-07-13 18:46:43 +0300 MSK

Remove Element
class Solution:
    # create two indexes, current and replace
    # create non_val_count
    # while to-be-replaced has not reached the end:
    # - if the current number is a regular number, move the current index, 
    #   increase non_val_count
    # - if the replace index is equal or less than the current, move it and continue
    # - if the replace number is a non-regular number, move the replace index and continue
    # - if the current number is a non-regular, replace it with the replace number, 
    #   replace the replace number with val, move both indexes
    # return the current index + 1

    def removeElement(self, nums: List[int], val: int) -> int:
        current, replace, val_count, length = 0, 0, 0, len(nums)
        non_val_count = 0
        
        while replace < length and current < length:
            current_number, replace_number = nums[current], nums[replace]
            
            if current_number != val:
                current += 1
                non_val_count += 1
                continue

            if replace <= current:
                replace = current + 1
                continue

            if replace_number == val:
                replace += 1
                continue

            nums[current], nums[replace] = replace_number, val
            replace += 1
            current += 1
            non_val_count += 1
            
        return non_val_count

4.7.1829 - 2023-07-12 20:34:00 +0300 MSK

Merge Sorted Array
class Solution:
    # have three indexes: nums1 (end of array 1), nums2 (from the end), 
    # and current (nums1 from the end) 
    # if nums2 number is bigger or equal than nums1 number, put the number at the current index,
    # move both indexes
    # if nums1 number is smaller than nums2 number, put the number at the current index, 
    # move both indexes  
    def merge(self, nums1: List[int], m: int, nums2: List[int], n: int) -> None:
        """
        Do not return anything, modify nums1 in-place instead.
        """

        nums1_i, nums2_i = m - 1, n - 1
        for i in range(m + n - 1, -1, -1):
            nums1_number  = nums1[nums1_i] if nums1_i >= 0 else nums2[0] - 1
            nums2_number = nums2[nums2_i] if nums2_i >= 0 else nums1[0] - 1
            if nums1_number >= nums2_number:
                nums1[i] = nums1_number
                nums1_i -= 1
                continue
            
            nums1[i] = nums2_number
            nums2_i -= 1

4.7.1830 - 2023-07-11 17:42:28 +0300 MSK

Valid Palindrome
class Solution:
    def isPalindrome(self, s: str) -> bool:
        length = len(s)

        # if the sring has only one symbol and it is alphanumeric, it is a palyndrom
        if s.isalnum() and length == 1:
            return True 
        
        i, j = 0, length - 1
        # iterate from the start and from the end using two indexes:
        # - if one the symbols is not alphanumeric, move the corresponding index
        # - if symbols are alphanumeric and not equal, return False
        # - move indexes
        while i < j:
            symbol_start, symbol_end = s[i].lower(), s[j].lower()
            if not symbol_start.isalnum():
                i += 1
                continue
            if not symbol_end.isalnum():
                j -= 1
                continue
            
            if symbol_start != symbol_end:
                return False
            
            i += 1
            j -= 1
        
        return True

4.7.1831 - 2023-07-11 17:40:20 +0300 MSK

Valid Palindrome
class Solution:
    def isPalindrome(self, s: str) -> bool:
        length = len(s)

        # if the sring has only one symbol and it is alphanumeric, it is a palyndrom
        if s.isalnum() and length == 1:
            return True 
        
        i, j = 0, length - 1
        # iterate from start and from end:
    # - if the symbol is not alphanumeric, skip
    # - if the symbol is alphanumeric, compare
    # - if indexes are equal or reversed, return
        while i < j:
            symbol_start, symbol_end = s[i].lower(), s[j].lower()
            if not symbol_start.isalnum():
                i += 1
                continue
            if not symbol_end.isalnum():
                j -= 1
                continue
            
            if symbol_start != symbol_end:
                return False
            
            i += 1
            j -= 1
        
        return True

4.7.1832 - 2023-07-10 15:59:08 +0300 MSK

Find the Index of the First Occurrence in a String
class Solution:
    # check edge cases:
    # - if length of the needle is less than the length of the haystack: -1
    # - if strings are equal: 0
    # - if length of the needle is equal to the length of the haystack, but 
    #   strings are not equal: -1
    # iterate over haystack and needle cheking if a substring starting with the current symbol
    # is equal to the needle
    def strStr(self, haystack: str, needle: str) -> int:
        length_needle, length_haystack = len(needle), len(haystack)
        last_needle_index = length_needle - 1

        if length_needle > length_haystack:
            return -1
        
        if haystack == needle:
            return 0

        if length_needle == length_haystack:
            return -1
        
        if needle == haystack:
            return 0

        for i, _ in enumerate(haystack):
            current_needle = haystack[i:i+length_needle]
            if current_needle == needle:
                return i
        return -1

4.7.1833 - 2023-07-10 15:57:30 +0300 MSK

Find the Index of the First Occurrence in a String
class Solution:
    # check edge cases:
    # - if length of the needle is less than the length of the haystack: -1
    # - if strings are equal: 0
    # - if length of the needle is equal to the length of the haystack, but 
    #   strings are not equal: -1
    # iterate over haystack and needle cheking if a symbol from haystack 
    #   corresponds to the symbol in needle
    def strStr(self, haystack: str, needle: str) -> int:
        length_needle, length_haystack = len(needle), len(haystack)
        last_needle_index = length_needle - 1

        if length_needle > length_haystack:
            return -1
        
        if haystack == needle:
            return 0

        if length_needle == length_haystack:
            return -1
        
        if needle == haystack:
            return 0

        j = length_needle
        for i, _ in enumerate(haystack):
            current_needle = haystack[i:j]
            if current_needle == needle:
                return i
            j += 1
        
        return -1

4.7.1834 - 2023-07-10 15:49:18 +0300 MSK

Find the Index of the First Occurrence in a String
class Solution:
    # check edge cases:
    # - if length of the needle is less than the length of the haystack: -1
    # - if strings are equal: 0
    # - if length of the needle is equal to the length of the haystack, but 
    #   strings are not equal: -1
    # iterate over haystack and needle cheking if a symbol from haystack 
    #   corresponds to the symbol in needle
    def strStr(self, haystack: str, needle: str) -> int:
        length_needle, length_haystack = len(needle), len(haystack)
        last_needle_index = length_needle - 1

        if length_needle > length_haystack:
            return -1
        
        if haystack == needle:
            return 0

        if length_needle == length_haystack:
            return -1
        
        if needle == haystack:
            return 0

        i, j = 0, length_needle
        while j <= len(haystack):
            current_needle = haystack[i:j]
            if current_needle == needle:
                return i

            i += 1
            j += 1
        
        return -1

4.7.1835 - 2023-07-08 18:57:18 +0300 MSK

Length of Last Word
class Solution:
    # we need to iterate over the string searching for words
    # add a whitespace to the end to avoid the situation when the last symbol is non-whitespace 
    # possible combinations:
    # 1. a whitespace after a symbol: end of the word
    # 2. a whitespace after a whitespace: ignore
    # 3. a symbol after a symbol: ignore
    def lengthOfLastWord(self, s: str) -> int:
        s += " "
        result, word_length = 0, 0

        for i, symbol in enumerate(s):
            if symbol != " ":
                word_length += 1
                continue
            
            if word_length > 0:
                result = word_length
                word_length = 0
        
        return result

4.7.1836 - 2023-07-08 18:48:01 +0300 MSK

Length of Last Word
class Solution:
    # we need to iterate over the string searching for words
    # possible combinations:
    # 1. a whitespace after a symbol: end of the word
    # 2. a whitespace after a whitespace: ignore
    # 3. a symbol after a symbol, but it's the last symbol: end of the last word
    # 4. a symbol after a symbol: ignore
    def lengthOfLastWord(self, s: str) -> int:
        length = len(s)
        if length == 1:
            return 1

        word_start, word_end, in_word = 0, 0, False

        for i, symbol in enumerate(s):
            is_whitespace = symbol == " "
            is_last = i == length - 1
            
            if is_whitespace and in_word:
                in_word = False
                word_end = i - 1
                continue
            
            if is_whitespace and not in_word:
                continue

            if not is_whitespace and in_word and is_last:
                word_end = i
                continue

            if not is_whitespace and not in_word and is_last:
                word_end = i
                word_start = i
                continue

            if not is_whitespace and in_word:
                continue

            if not is_whitespace and not in_word:
                word_start = i
                in_word = True
                continue
            
        return word_end - word_start + 1

4.7.1837 - 2023-07-08 18:25:39 +0300 MSK

Length of Last Word
class Solution:
    def lengthOfLastWord(self, s: str) -> int:
        return len(s.split()[-1])

4.7.1838 - 2023-07-06 20:44:21 +0300 MSK

Add Two Numbers
# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:
    # create the result pointer that points towards one of the lists
    # create the result root pointer that will point towards the root of the result list
    # 1. start infinite loop
    # 2. if result is false - break, we reached the end
    # 3. get values from non-empty pointers
    # 4. add values together, store the carry in a variable
    # 5. store the value in the result pointer
    # 6. move the result pointer to the next node, if there is no next node, use a node from
    #    another list
    # 7. move list pointers
    # 8. if we have a carry left, add a node to the result list
    def addTwoNumbers(self, l1: Optional[ListNode], 
                            l2: Optional[ListNode]) -> Optional[ListNode]:
        carry = 0
        result, result_root = l1, l1

        while True:
            if not l1 and not l2:
                break
            
            number_1 = l1.val if l1 else 0
            number_2 = l2.val if l2 else 0
            result_val = number_1 + number_2 + carry
            if result_val > 9:
                carry, result_val = 1, result_val - 10
            else:
                carry = 0
            
            result.val = result_val
            if not result.next and l2:
                l1 = None
                result.next = l2.next

            if result.next:
                result = result.next
            if l1:
                l1 = l1.next
            if l2:
                l2 = l2.next

        if carry:
            result.next = ListNode(carry)

        return result_root

4.7.1839 - 2023-07-06 15:43:40 +0300 MSK

Roman to Integer
class Solution:
    def romanToInt(self, input_numbers: str) -> int:
        result = 0
        previous = None
        values = {
            "I": 1,
            "V": 5,
            "X": 10,
            "L": 50,
            "C": 100,
            "D": 500,
            "M": 1000,
        }
        subtractions = set(["IV", "IX", "XL", "XC", "CD", "CM"])

        for number in input_numbers:
            if f"{previous}{number}" in subtractions:
                result = result - values[previous] * 2 + values[number]
            else:
                result += values[number]
            previous = number
        
        return result
            

4.7.1840 - 2023-05-24 13:25:03 +0300 MSK

Remove Element
class Solution:
    def removeElement(self, nums: List[int], val: int) -> int:
        length = len(nums)

        if not length: 
            return 0

        first = nums[0]
        if length == 1 and first == val:
            nums.pop()
            return 0
        if length == 1 and first != val:
            return 1
        
        not_equal_index = -1 if first == val else 0
        for i, number in enumerate(nums[1:], 1):
            if number == val:
                continue

            not_equal_index += 1
            nums[not_equal_index] = number

        return not_equal_index + 1
            

4.7.1841 - 2023-05-24 13:11:40 +0300 MSK

Remove Duplicates from Sorted Array
class Solution:
    def removeDuplicates(self, nums: List[int]) -> int:
        length = len(nums)
        if length == 1:
            return 1
        
        unique_count = 1
        last_unique_index = 0
        for i, number in enumerate(nums[1:], 1):
            last_unique = nums[last_unique_index]
            if number == last_unique:
                continue
            
            unique_count += 1
            last_unique_index += 1
            nums[last_unique_index] = number

        nums = nums[:last_unique_index+1]

        return unique_count

4.7.1842 - 2023-05-24 12:54:30 +0300 MSK

Merge Two Sorted Lists
# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next

class Solution:
    def mergeTwoLists(self, list1: Optional[ListNode], list2: Optional[ListNode]) -> Optional[ListNode]:
        result = ListNode()
        current = result
        while list1 and list2:               
            if list1.val < list2.val:
                current.next = list1
                list1, current = list1.next, list1
                continue

            current.next = list2
            list2, current = list2.next, list2
                
        if list1 or list2:
            current.next = list1 if list1 else list2
            
        return result.next

4.7.1843 - 2023-05-24 12:13:29 +0300 MSK

Valid Parentheses
class Solution:
    def isValid(self, s: str) -> bool:
        brackets = []

        symbols = {
            "{": "}",
            "(": ")",
            "[": "]"
        }

        open = symbols.keys()
        closed = symbols.values()

        for bracket in s:
            if bracket in open:
                brackets.append(bracket)
                continue

            if not brackets:
                return False

            last_bracket = brackets[-1]
            if last_bracket in closed: 
                return False

            correct_closing_bracket = symbols[last_bracket]
            if bracket != correct_closing_bracket:
                return False
            
            brackets.pop()

        return not len(brackets)

4.7.1844 - 2023-05-24 11:52:15 +0300 MSK

Palindrome Number
class Solution:
    def isPalindrome(self, x: int) -> bool:
        if x < 0:
            return False
        
        if x < 10:
            return True
        
        number = []

        while True:
            remainder = x % 10
            x = int(x / 10)
            number.append(remainder)
            if not x:
                break
            
        
        number.reverse()
        print(number)
        length = len(number)
        half_index = int(length / 2)

        for i, digit in enumerate(number):
            last_digit = number[length - i - 1]

            if digit != last_digit:
                return False
            
            if i != half_index:
                continue
            
            return True

4.7.1845 - 2023-05-24 11:37:01 +0300 MSK

Longest Common Prefix
class Solution:
    def longestCommonPrefix(self, strs: List[str]) -> str:
        answer = []
        strings = sorted(strs)
        first = strings[0]
        last = strings[-1]
        min_length = min(len(first), len(last))
        for i in range(min_length):
            first_symbol = first[i]
            last_symbol = last[i]
            if first_symbol == last_symbol:
                answer.append(first_symbol)
                continue
            
            return "".join(answer)

        return "".join(answer)


        

4.7.1846 - 2023-05-24 11:26:20 +0300 MSK

Roman to Integer
class Solution:
    def romanToInt(self, s: str) -> int:
        result = 0
        skip = False

        values = {
            "I": 1,
            "V": 5,
            "X": 10,
            "L": 50,
            "C": 100,
            "D": 500,
            "M": 1000
        }
        special_cases = {
            "I": ["V", "X"],
            "X": ["L", "C"],
            "C": ["D", "M"]
        }

        for i, symbol in enumerate(s):
            if skip:
                skip = False
                continue

            next = None
            if i < (len(s) - 1):
                next = s[i+1]

            if next in special_cases.get(symbol, []):
                skip = True
                result += values[next] - values[symbol]
                continue
            
            result += values[symbol]

        return result
            

4.7.1847 - 2023-05-24 11:15:01 +0300 MSK

Roman to Integer
class Solution:
    def romanToInt(self, s: str) -> int:
        result = 0
        skip = False
        for i, symbol in enumerate(s):
            if skip:
                skip = False
                continue

            next = ""
            if i < len(s) - 1:
                next = s[i+1]
            
            if symbol == "I" and next == "V":
                result += 4
                skip = True
                continue

            if symbol == "I" and next == "X":
                result += 9
                skip = True
                continue
            
            if symbol == "I":
                result += 1
                continue

            if symbol == "X" and next == "L":
                result += 40
                skip = True
                continue

            if symbol == "X" and next == "C":
                result += 90
                skip = True
                continue
            
            if symbol == "X":
                result += 10
                continue

            if symbol == "C" and next == "D":
                result += 400
                skip = True
                continue
            
            if symbol == "C" and next == "M":
                result += 900
                skip = True
                continue
            
            if symbol == "C":
                result += 100
                continue
            
            if symbol == "V":
                result += 5
                continue
            
            if symbol == "D":
                result += 500
                continue
            
            if symbol == "M":
                result += 1000
                continue
            
            if symbol == "L":
                result += 50
                continue
            
            raise Exception(f"unexpected situation: {symbol}, {next}")

        return result
            

4.7.1848 - 2023-05-23 12:36:30 +0300 MSK

Two Sum
class Solution:
    def twoSum(self, nums: List[int], target: int) -> List[int]:
        indexes = {}
        for i, number in enumerate(nums):
            diff = target - number
            if diff in indexes: 
                return [indexes[diff], i]
            indexes[number] = i

4.7.1849 - 2023-05-23 12:30:44 +0300 MSK

Two Sum
class Solution:
    def twoSum(self, nums: List[int], target: int) -> List[int]:
        for i, number in enumerate(nums):
            for j, number_inner in enumerate(nums[i+1:]):
                if number + number_inner == target:
                    return [i, i+j+1]

4.7.1850 - 2022-05-17 07:59:02 +0300 MSK

Find a Corresponding Node of a Binary Tree in a Clone of That Tree
class Solution {
TreeNode ans;

public void inorder(TreeNode c,TreeNode target) {
if (c != null) {
inorder(c.left, target);
if (c.val == target.val) {
ans = c;
}
inorder(c.right, target);
}
}

public final TreeNode getTargetCopy(final TreeNode original, final TreeNode cloned, final TreeNode target)
{
inorder(cloned,target);
return ans;
}
}

4.7.1851 - 2022-05-15 18:44:33 +0300 MSK

Deepest Leaves Sum
/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    public int deepestLeavesSum(TreeNode root) {
        MaxDepthInfo maxDepthInfo = new MaxDepthInfo(0 ,0);
        sumAtLevel(root, 0, maxDepthInfo);
        return maxDepthInfo.getSumAtMaxDepth();
    }

    public void sumAtLevel(TreeNode root, int currentDepth, MaxDepthInfo maxDepthInfo) {
        if (root == null) return;

        if (currentDepth > maxDepthInfo.getMaxDepth()) {
            maxDepthInfo.setMaxDepth(currentDepth);
            maxDepthInfo.setSumAtMaxDepth(root.val);
        }

        else if (currentDepth == maxDepthInfo.getMaxDepth())
            maxDepthInfo.setSumAtMaxDepth(maxDepthInfo.getSumAtMaxDepth() + root.val);

        sumAtLevel(root.left, currentDepth + 1, maxDepthInfo);
        sumAtLevel(root.right, currentDepth + 1, maxDepthInfo);
    }

    public static class MaxDepthInfo {
        private int maxDepth;
        private int sumAtMaxDepth;

        public MaxDepthInfo(int maxDepth, int sumAtMaxDepth) {
            this.maxDepth = maxDepth;
            this.sumAtMaxDepth = sumAtMaxDepth;
        }

        public int getMaxDepth() { return maxDepth;}

        public void setMaxDepth(int maxDepth) { this.maxDepth = maxDepth;}

        public int getSumAtMaxDepth() { return sumAtMaxDepth;}

        public void setSumAtMaxDepth(int sumAtMaxDepth) { this.sumAtMaxDepth = sumAtMaxDepth;}
    }
}

4.7.1852 - 2022-05-14 15:28:36 +0300 MSK

Network Delay Time
class Solution {
   private final Map<Integer, List<Node>> connected = new HashMap<>();

    public int networkDelayTime(int[][] times, int n, int k) {
        for (int[] time : times) {
            connected.putIfAbsent(time[0], new ArrayList<>());
            connected.get(time[0]).add(new Node(time[2], time[1]));
        }
        connected.forEach((source, nodes) -> nodes.sort(Comparator.comparing(Node::travelTime)));
        int[] receivedTime = new int[n + 1]; Arrays.fill(receivedTime, 1, receivedTime.length, Integer.MAX_VALUE);
        dfs(receivedTime, 0, k);
        
        int max = Arrays.stream(receivedTime).max().orElseThrow(RuntimeException::new);
        return max == Integer.MAX_VALUE ? -1 : max;
    }

    private void dfs(int[] receivedTime, int currentTime, int currentNode) {
        if (receivedTime[currentNode] <= currentTime) return;
        receivedTime[currentNode] = currentTime;
        if (connected.containsKey(currentNode))
            connected.get(currentNode).forEach(node -> dfs(receivedTime, currentTime + node.travelTime(), node.destination()));
    }

    public record Node(int travelTime, int destination) {}
}

4.7.1853 - 2022-05-13 07:19:10 +0300 MSK

Letter Combinations of a Phone Number
class Solution {
    public List<String> letterCombinations(String digits) {
        if(digits.length() == 0){
            List<String> result = new ArrayList<>();
            return result;
        }
        List<String> res = combine(digits); 
        return res;
    }
    
    public List<String> combine(String digit){
        if(digit.length() == 0 ){
            List<String> result = new ArrayList<>();
            result.add("");
            return result;
        }
        
        String[] codes = {"","","abc","def","ghi","jkl","mno","pqrs","tuv","wxyz"};
        
        char c = digit.charAt(0);
        
        String  digits_left = digit.substring(1);
        
        List<String> res = combine(digits_left);
        
        List<String> result = new ArrayList<>();
        
        String code_for_current_digit = codes[c-'0'];
        
        for(int i=0;i<code_for_current_digit.length();i++){
            char code_char = code_for_current_digit.charAt(i);
            
            if(!res.isEmpty()){
                for(String s : res){
                    result.add(code_char + s);
                }    
            }
            else{
                res.add(String.valueOf(code_char));
            }
            
        }
        
        
        return result;
    }
}

4.7.1854 - 2022-05-13 07:17:45 +0300 MSK

Populating Next Right Pointers in Each Node II
class Solution {
    public Node connect(Node root) {
        Node leftMost = root;
        while (leftMost != null) {
            Node cur = leftMost;
            leftMost = null;
            Node pre = null;
            while (cur != null) {
                if (leftMost == null) {
                    leftMost = cur.left == null ? cur.right: cur.left;
                }
                if (pre != null) {
                    pre.next = cur.left == null ? cur.right : cur.left;
                }
                if (cur.left != null && cur.right != null) {
                    cur.left.next = cur.right;
                }
                pre = cur.right == null ? (cur.left == null ? pre : cur.left) : cur.right;
                cur = cur.next;
            }
        }
        return root;
    }
}

4.7.1855 - 2022-05-12 18:05:33 +0300 MSK

Permutations II
class Solution {
public List<List<Integer>> permuteUnique(int[] nums) {
        List<List<Integer>> permutations = new ArrayList<>();
        Arrays.sort(nums);
        backtracking(permutations, new ArrayList<>(), nums, new boolean[nums.length]);
        return permutations;
    }

    private void backtracking(List<List<Integer>> permutations, List<Integer> current, int[] nums, boolean[] used) {
        if (current.size() == nums.length)
            permutations.add(new ArrayList<>(current));
        else {
            for (int i = 0; i < nums.length; i++) {
                if (used[i] || (i > 0 && nums[i] == nums[i - 1] && !used[i - 1])) continue;
                current.add(nums[i]);
                used[i] = true;
                backtracking(permutations, current, nums, used);
                used[i] = false;
                current.remove(current.size() - 1);
            }
        }
    }
}

4.7.1856 - 2022-05-11 18:03:06 +0300 MSK

Count Sorted Vowel Strings
class Solution {
    public int countVowelStrings(int n) {
        int a,e,i,o,u;
        a = e = i = o = u = 1;
        
        for(int t = 1; t < n; t++){
            
            a = a + e + i + o + u;
            e = e + i + o + u;
            i = i + o + u;
            o = o + u;
            u = u;
        }
        return a + e + i + o + u;
    }
}

4.7.1857 - 2022-05-08 17:27:21 +0300 MSK

Flatten Nested List Iterator
public class NestedIterator implements Iterator<Integer> {

    private List<Integer> integerList = new ArrayList<>();
    private int index = 0;
    public NestedIterator(List<NestedInteger> nestedList) {
        for (NestedInteger nestedInteger : nestedList) {
            flatten(nestedInteger);
        }
    }
    
    private void flatten(NestedInteger nested) {
        if (nested.isInteger()) 
            integerList.add(nested.getInteger());
        else 
            for (NestedInteger nestedFromList : nested.getList()) {
                flatten(nestedFromList);
        }
    }

    @Override
    public boolean hasNext() {
        return index < integerList.size();
    }

    @Override
    public Integer next() {
        return integerList.get(index++);
    }
}

4.7.1858 - 2022-05-07 13:44:16 +0300 MSK

132 Pattern

func find132pattern(numbers []int) bool {
	length := len(numbers)
	if length < 3 {
		// if the array doesn't have at least three numbers, it cannot have
		// '123' pattern
		return false
	}
	list, third_element := list.List{}, math.MinInt
	for index := length - 1; index >= 0; index-- {
		current := numbers[index]
		if current < third_element {
			return true
		}
		for list.Len() != 0 && list.Front().Value.(int) < current {
			third_element = list.Front().Value.(int)
			list.Remove(list.Front())
		}
		list.PushFront(current)
	}
	return false
}

4.7.1859 - 2022-05-07 13:05:13 +0300 MSK

Backspace String Compare

func backspaceCompare(string_1 string, string_2 string) bool {
	length_1, length_2 := len(string_1), len(string_2)
	list_1, list_2, length_biggest := list.List{}, list.List{}, length_1
	if length_2 > length_1 {
		length_biggest = length_2
	}
	for index := 0; index < length_biggest; index++ {
		if index < length_1 {
			backspace_action(&list_1, string_1[index])
		}
		if index < length_2 {
			backspace_action(&list_2, string_2[index])
		}
	}
	// lists are not equal, there is no need to check
	if list_1.Len() != list_2.Len() {
		return false
	}
	// checking elements after all deletions
	element_1, element_2 := list_1.Back(), list_2.Back()
	for element_1 != nil {
		if element_1.Value != element_2.Value {
			// elements are not equal -> strings are not equal
			return false
		}
		element_1, element_2 = element_1.Next(), element_2.Next()
	}
	// checked all elements, strings are equal
	return true
}

func backspace_action(list *list.List, character byte) {
	switch {
	case character == '#' && list.Len() != 0:
		// delete last character
		list.Remove(list.Front())
		fallthrough
	case character == '#' && list.Len() == 0:
		// just return if the list is empty
		return
	}
	list.PushFront(character)
}

4.7.1860 - 2022-05-06 20:02:58 +0300 MSK

Backspace String Compare
class Solution {
    public boolean backspaceCompare(String S, String T) {
        return build(S).equals(build(T));
    }

    public String build(String S) {
        Stack<Character> ans = new Stack();
        for (char c: S.toCharArray()) {
            if (c != '#')
                ans.push(c);
            else if (!ans.empty())
                ans.pop();
        }
        return String.valueOf(ans);
    }
}

4.7.1861 - 2022-05-06 19:50:38 +0300 MSK

Remove Duplicates from Sorted Array
func removeDuplicates(numbers []int) int {
	// ensure there are at least two numbers
	length := len(numbers)
	if length == 1 {
		return 1
	}
	index_non_duplicate := 1
	for index := 1; index < length; index++ {
		current, previous := numbers[index], numbers[index-1]
		if current == previous {
			// it is a duplicate - ignore it
			continue
		}
		// it is not a duplicate -> place it and move the index
		numbers[index_non_duplicate] = current
		index_non_duplicate++
	}
	return index_non_duplicate
}

4.7.1862 - 2022-05-06 19:25:00 +0300 MSK

Remove All Adjacent Duplicates in String II
class Solution {
    public String removeDuplicates(String s, int k) {
        Stack<int []> Master = new Stack<>();
        
        for(char ch : s.toCharArray()){
            if(!Master.isEmpty() && Master.peek()[0] == ch){
                Master.peek()[1]++;
            }
            else Master.push(new int[]{ch, 1});
            if(Master.peek()[1] == k) Master.pop();
        }
        StringBuilder sb = new StringBuilder();
        while(!Master.isEmpty()){
            int top[] = Master.pop();
            while(top[1] --> 0)
                sb.append((char)top[0]);
        }
        return sb.reverse().toString();
    }
}

4.7.1863 - 2022-05-05 18:39:53 +0300 MSK

Sign of the Product of an Array

func arraySign(numbers []int) int {
	negative_count := 0
	for _, number := range numbers {
		switch {
		// the number is 0 -> product of all numbers is definitely zero
		case number == 0:
			return 0
			// the number is negative -> add to count
		case number < 0:
			negative_count++
		}
	}
	// even amount of negative numbers -> result is positive
	if negative_count&1 == 0 {
		return 1
	}
	// uneven amount of negative numbers -> result is negative
	return -1
}

4.7.1864 - 2022-05-05 18:26:39 +0300 MSK

Find Smallest Letter Greater Than Target


func nextGreatestLetter(letters []byte, target byte) byte {
	length := len(letters)
	left, right := 0, length-1
	for right >= left {
		index := left + (right-left)/2
		character := letters[index]
		// the character is bigger, we found at least one result
		// smaller characters are to the left -> discard right
		if character > target {
			right = index - 1
			continue
		}
		// character is either equal or smaller -> there is no results to the
		// left -> discard left
		left = index + 1
	}
	return letters[left%length]
}

4.7.1865 - 2022-05-05 15:37:11 +0300 MSK

Sqrt(x)

func mySqrt(number int) int {
	left, right := 0, number
	for right >= left {
		current := left + (right-left)/2
		square_current := current * current
		square_next := (current + 1) * (current + 1)
		switch {
		case square_current <= number && square_next > number:
			// found the target
			return current
		case square_current > number:
			// target is to the left -> discard right
			right = current - 1
		case square_current < number:
			// target is to the right -> discard left
			left = current + 1
		}
	}
	return -1
}

4.7.1866 - 2022-05-05 15:10:54 +0300 MSK

Reverse Words in a String III
func reverseWords(_string string) string {
	index_word_start, length, result := 0, len(_string), []rune(_string)
	for index, character := range result {
		// ignore normal characters
		if character != ' ' {
			continue
		}
		// word ended -> reverse characters from the start of the word to the
		//end of it
		reverse_word(result, length, index_word_start, index)
		index_word_start = index + 1
	}
	reverse_word(result, length, index_word_start, length)
	return string(result)
}

func reverse_word(_string []rune, length int, start int, end int) {
	//fmt.Println("reversing", string(_string), start, "->", end)
	length_word := end - start
	for index := start; index < start+length_word/2; index++ {
		index_last := end - (index - start) - 1
		current, last := _string[index], _string[index_last]
		_string[index], _string[index_last] = last, current
	}
	//fmt.Println("result", string(_string), start, "->", end)
}

4.7.1867 - 2022-05-05 13:50:33 +0300 MSK

Reverse String
func reverseString(characters []byte) {
	length := len(characters)
	for index := 0; index < length/2; index++ {
		index_last := length - index -1 
		current, last := characters[index], characters[index_last]
		characters[index_last] = current
		characters[index] = last
	}
}

4.7.1868 - 2022-05-05 13:43:47 +0300 MSK

Two Sum II - Input Array Is Sorted
func twoSum(numbers []int, target int) []int {
	numbers_len := len(numbers)
	for index, number := range numbers {
		for index_inner := index + 1; index_inner < numbers_len; index_inner++ {
			if numbers[index_inner]+number == target {
				return []int{index + 1, index_inner + 1}
			}
		}
	}
	return []int{}
}

4.7.1869 - 2022-05-05 13:39:30 +0300 MSK

Move Zeroes
func moveZeroes(numbers []int) {
	index_zero := -1
	// sliding window algorithm
	for index, number := range numbers {
		// if index_zero is not set, then the first zero is index_zero
		if index_zero == -1 && number == 0 {
			index_zero = index
		}
		// there is no need to move numbers if there were no zeros before
		// there is no need to move zeros
		if index_zero == -1 || number == 0 {
			continue
		}
		// after some zeros we encounter a non-zero number
		// moving that number to the beginning of zeros
		numbers[index_zero] = number
		// current number becomes zero
		numbers[index] = 0
		// moving the index
		index_zero++
	}
}

4.7.1870 - 2022-05-05 13:39:06 +0300 MSK

Move Zeroes
func moveZeroes(nums []int)  {
    count:=0
    for i:=0; i<len(nums);i++{
        if nums[i] == 0{
            count++
        }else{
            nums[i-count]=nums[i]
        }
    }
    for count>0{
        nums[len(nums)-count] = 0
        count--
    }
    
    
}

4.7.1871 - 2022-05-05 13:38:25 +0300 MSK

Move Zeroes
func moveZeroes(nums []int)  {
    	if len(nums) < 2 {
		return
	}

	for z, p := 0, 1; p < len(nums) && z < len(nums); {
		if nums[z] == 0 && nums[p] != 0 {
			if p > z {
				nums[z], nums[p] = nums[p], nums[z]
				z++
			}
			p = z+1
		} else {
			if nums[z] != 0 {
				z++
			}
			if nums[p] == 0 {
				p++
			}
		}
	}

}

4.7.1872 - 2022-05-05 13:32:58 +0300 MSK

Move Zeroes

func moveZeroes(numbers []int) {
	index_zero := -1
	// sliding window algorithm
	for index, number := range numbers {
		// if index_zero is not set, then the first zero is index_zero
		if index_zero == -1 && number == 0 {
			index_zero = index
		}
		// there is no need to move numbers if there were no zeros before
		// there is no need to move zeros
		if index_zero == -1 || number == 0 {
			continue
		}
		// after some zeros we encounter a non-zero number
		// moving that number to the beginning of zeros
		numbers[index_zero] = number
		// current number becomes zero
		numbers[index] = 0
		// moving the index
		index_zero++
	}
}

4.7.1873 - 2022-05-05 13:14:51 +0300 MSK

Move Zeroes

func moveZeroes(numbers []int) {
	// ensure there are at least two numbers
	length := len(numbers)
	if length == 1 {
		return
	}
	result, index_result := make([]int, length), 0
	for _, number := range numbers {
		if number == 0 {
			continue
		}
		result[index_result] = number
		index_result++
	}
	copy(numbers, result)
}

4.7.1874 - 2022-05-05 07:01:33 +0300 MSK

Implement Stack using Queues

type MyStack struct{ queue *list.List }

func Constructor() MyStack           { return MyStack{&list.List{}} }
func (this *MyStack) Push(value int) { this.queue.PushFront(value) }
func (this *MyStack) Top() int       { return this.queue.Front().Value.(int) }
func (this *MyStack) Empty() bool    { return this.queue.Len() == 0 }
func (this *MyStack) Pop() int {
	return this.queue.Remove(this.queue.Front()).(int)
}

4.7.1875 - 2022-05-04 13:13:54 +0300 MSK

Best Time to Buy and Sell Stock

func maxProfit(prices []int) int {
	profit, index_buy := 0, 0
	for index, price := range prices {
		if prices[index_buy] > price {
			index_buy = index
		}
		new_profit := price - prices[index_buy]
		if new_profit > profit {
			profit = new_profit
		}
	}
	return profit
}

4.7.1876 - 2022-05-04 12:54:11 +0300 MSK

Intersection of Two Arrays II

func intersect(numbers_1 []int, numbers_2 []int) (result []int) {
	// 0 <= nums1[i], nums2[i] <= 1000
	count := make([]int, 1001)
	// counting how many times a number occured in the first array
	for _, number := range numbers_1 {
		count[number]++
	}
	for _, number := range numbers_2 {
		// the number did not occur in the first array
		// -> ignoring it
		if count[number] <= 0 {
			continue
		}
		count[number]--
		result = append(result, number)
	}
	return
}

4.7.1877 - 2022-05-04 12:36:38 +0300 MSK

Intersection of Two Arrays II

func intersect(numbers_1 []int, numbers_2 []int) []int {
	length_1, length_2 := len(numbers_1), len(numbers_2)
	length_biggest, result := length_1, make([]int, length_1+length_2)
	if length_2 > length_1 {
		length_biggest = length_2
	}
	occurences := make(map[int][]int, length_biggest)

	for index := 0; index < length_biggest; index++ {
		if index < length_1 {
			add_to_occurences(numbers_1[index], 0, occurences)
		}
		if index < length_2 {
			add_to_occurences(numbers_2[index], 1, occurences)
		}
	}
	index := 0
	for number, occurence := range occurences {
		repeat := occurence[0]
		if occurence[1] < repeat {
			repeat = occurence[1]
		}
		for ; repeat > 0; repeat-- {
			result[index] = number
			index++
		}
	}
    return result[0 : index]
}
func add_to_occurences(number int, index int, occurences map[int][]int) {
	if _, occured := occurences[number]; !occured {
		occurences[number] = make([]int, 2)
	}
	occurences[number][index]++
}

4.7.1878 - 2022-05-04 08:33:36 +0300 MSK

Merge Sorted Array

func merge(array1 []int, length1 int, array2 []int, length2 int) {
	if length2 == 0 {
		return
	}
	if length1 == 0 {
		for index, number := range array2 {
			array1[index] = number
		}
		return
	}
	index1, index2, array1Copy := 0, 0, make([]int, length1)
	copy(array1Copy, array1)
	for index := 0; index < length1+length2; index++ {
		fmt.Println(index, index1, index2, array1, array2)
		for index2 < length2 && (index1 >= length1 || array2[index2] <= array1Copy[index1]) {
			array1[index] = array2[index2]
			index2++
			index++
		}
		if index1 >= length1 {
			continue
		}
		array1[index] = array1Copy[index1]
		index1++
	}
}

4.7.1879 - 2022-05-04 08:32:16 +0300 MSK

Two Sum

func twoSum(numbers []int, target int) []int {
	numbers_len := len(numbers)
	for index, number := range numbers {
		for index_inner := index + 1; index_inner < numbers_len; index_inner++ {
			if numbers[index_inner]+number == target {
				return []int{index, index_inner}
			}
		}
	}
	return []int{}
}

4.7.1880 - 2022-05-04 08:30:20 +0300 MSK

Find the Distance Value Between Two Arrays

func findTheDistanceValue(array_1 []int, array_2 []int, target int) int {
	// sorting it to use binary search
	sort.Ints(array_2)
	length_2, count := len(array_2), 0
	for _, current_1 := range array_1 {
		left, right, add_to_count := 0, length_2-1, true
		for right >= left {
			index := left + (right-left)/2
			current_2 := array_2[index]
			if abs(current_1, current_2) <= target {
				// current_1 is inside |arr1[i]-arr2[j]| <= d
				// -> ignore it
				add_to_count = false
				break
			}
			switch {
			case current_2 > current_1:
				// current_2 is bigger than current_1
				// -> all numbers to the right are bigger
				// -> discard right, add to count
				right = index - 1
			case current_2 < current_1:
				// current_2 is smaller than current_1
				// -> all numbers to the left are smaller
				// -> discard left, add to count
				left = index + 1
			}
		}
		if add_to_count {
			count++
		}
	}
	return count
}

func abs(number_1 int, number_2 int) int {
	difference := number_1 - number_2
	if difference < 0 {
		return difference * -1
	}
	return difference
}

4.7.1881 - 2022-05-04 07:34:24 +0300 MSK

Valid Perfect Square

func isPerfectSquare(number int) bool {
	left, right := 1, number
	for right >= left {
		current := left + (right-left)/2
		square := current * current
		switch {
		case square == number:
			// found the target
			return true
		case square > number:
			// square is bigger -> root is to the left -> discard right
			right = current - 1
		case square < number:
			// square is smaller -> root is to the right -> discard left
			left = current + 1
		}
	}
	return false
}

4.7.1882 - 2022-05-04 07:03:31 +0300 MSK

Find Nearest Point That Has the Same X or Y Coordinate
func nearestValidPoint(x int, y int, points [][]int) int {
	point_target, smallest_distance, smallest_index := []int{x, y}, math.MaxInt, -1
	for index, point := range points {
		// ignore the point if it is not valid
		if !valid(point_target, point) {
			continue
		}
		distance := distance(point_target, point)
		// ignore the point if its Manhattan distance is bigger
		if distance >= smallest_distance {
			continue
		}
		// the distance is smaller, update the index and the distance
		smallest_index, smallest_distance = index, distance
	}
	// there are no valid points
	if smallest_index == -1 {
		return -1
	}
	return smallest_index
}

func valid(point_target []int, point []int) bool {
	switch {
	case point_target[0] == point[0]:
		fallthrough
	case point_target[1] == point[1]:
		return true
	default:
		return false
	}
}

func distance(point_target []int, point []int) int {
	return abs(point_target[0]-point[0]) + abs(point_target[1]-point[1])
}

func abs(number int) int {
	if number < 0 {
		return number * -1
	}
	return number
}

4.7.1883 - 2022-05-04 06:39:29 +0300 MSK

Largest Perimeter Triangle

func largestPerimeter(numbers []int) int {
	sort.Ints(numbers)
	for index := len(numbers) - 1; index > 1; index-- {
		current, sum_previous := numbers[index], numbers[index-1]+numbers[index-2]
		if current >= sum_previous {
			continue
		}
		return current + sum_previous
	}
	return 0
}

4.7.1884 - 2022-05-04 06:26:24 +0300 MSK

Max Number of K-Sum Pairs

func maxOperations(numbers []int, sum int) int {
	count, previous := 0, make(map[int]int, len(numbers))
	for _, current := range numbers {
		target := sum - current
		target_unmatched, target_occured := previous[target]
		// if the current number has not occured before, then it is not in the map
		// -> it needs to be initialized
		if _, current_occured := previous[current]; !current_occured {
			previous[current] = 0
		}
		// number of duplicates of the current number has increased
		previous[current]++
		switch {
		case target_occured && target_unmatched == 0:
			// the target has occured before but there are no unmatched duplicates
			fallthrough
		case !target_occured:
			// in order to get the sum we need the target, but it has not appeared yet
			continue
		case target_occured && target_unmatched > 0:
			// the target has appeared before and there are some unmached duplicates left
			// -> removing the current number and the target from possible matches
			previous[current]--
			previous[target]--
			count++
		}
	}
	return count
}

4.7.1885 - 2022-05-04 05:57:55 +0300 MSK

Subtract the Product and Sum of Digits of an Integer
func subtractProductAndSum(number int) int {
	fist_digit := number % 10
	factorial, sum := fist_digit, fist_digit
	number /= 10
	for number > 0 {
		digit := number % 10
		factorial *= digit
		sum += digit
		number /= 10
	}
	return factorial - sum
}

4.7.1886 - 2022-05-04 05:49:11 +0300 MSK

Number of 1 Bits

func hammingWeight(number uint32) (result int) {
	for number > 0 {
		if number&1 != 0 {
			result++
		}
		number >>= 1
	}
	return
}

4.7.1887 - 2022-05-03 18:34:04 +0300 MSK

Peak Index in a Mountain Array

func peakIndexInMountainArray(array []int) int {
	left, right := 0, len(array)-1
	for right > left {
		// overflow protection
		index := left + (right-left)/2
		// next element is bigger -> top is to the right -> discard left
		if array[index+1] > array[index] {
			left = index + 1
			continue
		}
		// next element is equal or smaller -> discard right
		// 'index' could be the answer, so it should not be discarded
		right = index
	}
	return right
}

4.7.1888 - 2022-05-03 17:44:29 +0300 MSK

Search Insert Position
func searchInsert(numbers []int, target int) int {
	// checking edge cases
	length := len(numbers)
	if numbers[0] == target {
		return 0
	} else if numbers[length-1] == target {
		return length - 1
	}
	left, right, index, was_bigger := 0, length-1, 0, false
	for right >= left {
		// overflow protection
		index = left + (right-left)/2
		number := numbers[index]
		//fmt.Println("index", index, "left", left, "right", right)
		switch {
		case number == target:
			// found the target
			return index
		case number > target:
			// the number is bigger -> the target is to the left -> discard right
			right = index - 1
			was_bigger = true
		case number < target:
			// the number is smaller -> the target is to the right -> discard left
			left = index + 1
			was_bigger = false
		}
	}
	// the target is not in the array

	// the last number was bigger -> target should be to the left
	if was_bigger {
		return index
	}
	// the last number was smaller -> target should be to the right
	return index + 1
}

4.7.1889 - 2022-05-03 17:39:58 +0300 MSK

Rotate Array

func rotate(numbers []int, steps int) {
	length := len(numbers)
	// removing unnecessary steps
	if steps >= length {
		steps %= length
	}
	// checking edge cases
	if length == 1 || steps == 0 {
		return
	}
	results := make([]int, length)
	for index, number := range numbers {
		results[(index+steps)%length] = number
	}
	copy(numbers, results)
}

4.7.1890 - 2022-05-03 15:28:52 +0300 MSK

Rotate Array

func rotate(numbers []int, steps int) {
	length := len(numbers)
	// removing unnecessary steps
	if steps >= length {
		steps %= length
	}
	// checking edge cases
	if length == 1 || steps == 0 {
		return
	}
	remainder, rotation_start := make([]int, steps), length-steps
	// copy everything that needs to be shifted to another array
	copy(remainder, numbers[rotation_start:])
	// move everything to the right
	copy(numbers[steps:], numbers[0:rotation_start])
	// move shifted elements to the beginning
	copy(numbers[0:steps], remainder)
}

4.7.1891 - 2022-05-03 15:08:53 +0300 MSK

Squares of a Sorted Array
func sortedSquares(numbers []int) []int {
	length := len(numbers)
	if length == 0 || length == 1 {
		return square(numbers, false)
	}
	negativesIndex := -1
	for index, number := range numbers {
		if number >= 0 {
			negativesIndex = index
			break
		}
	}
	if negativesIndex == 0 || negativesIndex == -1 {
		return square(numbers, negativesIndex == -1)
	}
//	fmt.Println("negativesIndex", negativesIndex)
	result, resultIndex, negativesIndex := make([]int, length), 0, negativesIndex-1
	for positivesIndex := negativesIndex + 1; resultIndex < length; positivesIndex++ {
		positiveOverflow := positivesIndex >= length
		for {
			if negativesIndex < 0 || resultIndex >= length {
				break
			}
			if !positiveOverflow && numbers[negativesIndex]*-1 > numbers[positivesIndex] {
				break
			}
			result[resultIndex] = numbers[negativesIndex]
			resultIndex++
//			fmt.Println("negative", negativesIndex, resultIndex, numbers[negativesIndex], result, numbers)
			negativesIndex--
		}
		if resultIndex < length && !positiveOverflow {
//			fmt.Println("positivesIndex", positivesIndex, resultIndex, numbers[positivesIndex], result, numbers)
			result[resultIndex] = numbers[positivesIndex]
			resultIndex++
		}
	}
	return square(result, false)
}

func square(array []int, reverse bool) []int {
	if reverse {
		length := len(array)
		reversed := make([]int, length)
		for index := length - 1; index >= 0; index-- {
			reversed[length-index-1] = array[index] * array[index]
		}
		return reversed
	} else {
		for index, number := range array {
			array[index] = number * number
		}
		return array
	}
}

4.7.1892 - 2022-05-03 15:05:02 +0300 MSK

Squares of a Sorted Array

func sortedSquares(numbers []int) []int {
	length := len(numbers)
	switch length {
	case 0:
		return numbers
	case 1:
		return []int{numbers[0] * numbers[0]}
	}
	index_left, index_right := 0, length-1
	results := make([]int, length)
	for index := index_right; index_left <= index_right; index-- {
		left_square := numbers[index_left] * numbers[index_left]
		right_square := numbers[index_right] * numbers[index_right]
		if right_square > left_square {
			results[index] = right_square
			index_right--
			continue
		}
		results[index] = left_square
		index_left++
	}
	return results
}

4.7.1893 - 2022-05-03 13:17:41 +0300 MSK

Shortest Unsorted Continuous Subarray

func findUnsortedSubarray(numbers []int) int {
	length := len(numbers)
	// checking edge cases
	if length == 1 {
		return 0
	}
	result := make([]int, length)
	// initializing to MaxInt because zeros will impact future sorting
	for index := range result {
		result[index] = math.MaxInt
	}
	index_sort_start, index_sort_end := length, length
	result[0] = numbers[0]
	for index := 1; index < length; index++ {
//		fmt.Println(result, index_sort_start, "->", index_sort_end)
		// current is not sorted -> from numbers
		// previous is sorted -> from result
		current, previous := numbers[index], result[index-1]
		// just push the current number in the result array because if it is
		// bigger
		if current >= previous {
			result[index] = current
			continue
		}
		// current number is not sorted -> moving the end index
		index_sort_end = index + 1
		// current < previous -> find the number bigger than the current
		//
		// the current number is smaller than the starting number of the unsorted subarray
		// (or the starting index is not set)
		// -> start index is invalid, finding new start index in numbers
		if index_sort_start == length || current < result[index_sort_start] {
			// insert the number in the correct place and move index_sort_start
			// to the correct place
			if index_sort_start == length {
				// index_sort_start is not set -> setting to the last sorted number
				index_sort_start = index - 1
			}
			index_sort_start = insert_smaller(result, current, index_sort_start, 0)
			continue
		}
		// the current number is bigger than the starting number of the unsorted
		// subarray, so it should be placed inside of it
		insert_smaller(result, current, index, index_sort_start)
		// set start index (if not already set)
		if index < index_sort_start {
			index_sort_start = index - 1
		}
	}
//	fmt.Println(result, index_sort_start, "->", index_sort_end)
	// return length of the sorted subarray
	return index_sort_end - index_sort_start
}

func insert_smaller(numbers []int, target int, index_start int, index_end int) int {
	index_result := index_end
	for index := index_start; index >= index_end; index-- {
		if target >= numbers[index] {
			// target is bigger -> it should be placed after this index
			index_result = index + 1
			break
		}
	}
//	fmt.Println("index for", target, "-", index_result)
	// target should be placed after index_result, so move everything after
	// it to the right and insert the current number
	// if index_result is the last item, then just push it
	copy(numbers[index_result+1:], numbers[index_result:])
	numbers[index_result] = target
	return index_result
}

4.7.1894 - 2022-05-03 13:17:21 +0300 MSK

Shortest Unsorted Continuous Subarray

func findUnsortedSubarray(numbers []int) int {
	length := len(numbers)
	// checking edge cases
	if length == 1 {
		return 0
	}
	result := make([]int, length)
	// initializing to MaxInt because zeros will impact future sorting
	for index := range result {
		result[index] = math.MaxInt
	}
	index_sort_start, index_sort_end := length, length
	result[0] = numbers[0]
	for index := 1; index < length; index++ {
//		fmt.Println(result, index_sort_start, "->", index_sort_end)
		// current is not sorted -> from numbers
		// previous is sorted -> from result
		current, previous := numbers[index], result[index-1]
		// just push the current number in the result array because if it is
		// bigger
		if current >= previous {
			result[index] = current
			continue
		}
		// current number is not sorted -> moving the end index
		index_sort_end = index + 1
		// current < previous -> find the number bigger than the current
		//
		// the current number is smaller than the starting number of the unsorted subarray
		// (or the starting index is not set)
		// -> start index is invalid, finding new start index in numbers
		if index_sort_start == length || current < result[index_sort_start] {
			// insert the number in the correct place and move index_sort_start
			// to the correct place
			if index_sort_start == length {
				// index_sort_start is not set -> setting to the last sorted number
				index_sort_start = index - 1
			}
			index_sort_start = insert_smaller(result, current, index_sort_start, 0)
			continue
		}
		// the current number is bigger than the starting number of the unsorted
		// subarray, so it should be placed inside of it
		insert_smaller(result, current, index, index_sort_start)
		// set start index (if not already set)
		if index < index_sort_start {
			index_sort_start = index - 1
		}
	}
//	fmt.Println(result, index_sort_start, "->", index_sort_end)
	// return length of the sorted subarray
	return index_sort_end - index_sort_start
}

func insert_smaller(numbers []int, target int, index_start int, index_end int) int {
	index_result := index_end
	for index := index_start; index >= index_end; index-- {
		if target >= numbers[index] {
			// target is bigger -> it should be placed after this index
			index_result = index + 1
			break
		}
	}
//	fmt.Println("index for", target, "-", index_result)
	// target should be placed after index_result, so move everything after
	// it to the right and insert the current number
	// if index_result is the last item, then just push it
	copy(numbers[index_result+1:], numbers[index_result:])
	numbers[index_result] = target
	return index_result
}

4.7.1895 - 2022-05-02 19:07:40 +0300 MSK

Sort Array By Parity

func sortArrayByParity(numbers []int) []int {
	length := len(numbers)
	if length == 1 {
		return numbers
	}
	results, index_even, index_odd := make([]int, length), 0, length-1
	for _, number := range numbers {
		if (number & 1) == 0 {
			// number is even -> place it from the beginning
			results[index_even] = number
			index_even++
		} else {
			// number is odd -> place it from the end
			results[index_odd] = number
			index_odd--
		}
	}
	return results
}

4.7.1896 - 2022-05-02 18:49:07 +0300 MSK

Search Insert Position
func searchInsert(numbers []int, target int) int {
	// checking edge cases
	length := len(numbers)
	if numbers[0] == target {
		return 0
	} else if numbers[length-1] == target {
		return length - 1
	}
	left, right, index, was_bigger := 0, length-1, 0, false
	for right >= left {
		// overflow protection
		index = left + (right-left)/2
		number := numbers[index]
		//fmt.Println("index", index, "left", left, "right", right)
		switch {
		case number == target:
			// found the target
			return index
		case number > target:
			// the number is bigger -> the target is to the left -> discard right
			right = index - 1
			was_bigger = true
		case number < target:
			// the number is smaller -> the target is to the right -> discard left
			left = index + 1
			was_bigger = false
		}
	}
	// the target is not in the array

	// the last number was bigger -> target should be to the left
	if was_bigger {
		return index
	}
	// the last number was smaller -> target should be to the right
	return index + 1
}

4.7.1897 - 2022-05-02 18:02:36 +0300 MSK

First Bad Version

func firstBadVersion(n int) int {
	// checking edge cases
	if isBadVersion(1) {
		return 1
	}
	left, right, bad_version := 1, n, math.MaxInt
	for right >= left {
		// overflow protection
		version := left + (right-left)/2
		switch isBadVersion(version) {
		case false:
			// it is good -> versions to the left are good -> discard left
			left = version + 1
		case true:
			// it is bad -> the first bad version is either this one or to the left
			// discard right
			bad_version = version
			right = version - 1
		}
	}
	// the search space is empty
	return bad_version
}

4.7.1898 - 2022-05-02 17:51:33 +0300 MSK

Binary Search
/* https://leetcode.com/problems/binary-search/

Given an array of integers nums which is sorted in ascending order, and an integer target, write a function to search target in nums. If target exists, then return its index. Otherwise, return -1.

You must write an algorithm with O(log n) runtime complexity.



Example 1:

Input: nums = [-1,0,3,5,9,12], target = 9
Output: 4
Explanation: 9 exists in nums and its index is 4

Example 2:

Input: nums = [-1,0,3,5,9,12], target = 2
Output: -1
Explanation: 2 does not exist in nums so return -1



Constraints:

    1 <= nums.length <= 104
    -104 < nums[i], target < 104
    All the integers in nums are unique.
    nums is sorted in ascending order.

*/
package main

func search(numbers []int, target int) int {
	length := len(numbers)
	switch {
	case numbers[0] > target:
		// smallet number > target = there is no target in the array
		fallthrough
	case numbers[length-1] < target:
		// biggest number < target = there is no target in the array
		return -1
	case numbers[length-1] == target:
		// checking just in case, can save time
		return length - 1
	case numbers[0] == target:
		// checking just in case, can save time
		return 0
	}

	left, right := 0, length-1
	for right >= left {
		// overflow protection
		index := left + (right-left)/2
		number := numbers[index]
		switch {
		case number == target:
			// found the target
			return index
		case number > target:
			// array is in the ascending order, the number is bigger
			// -> the target is to the left -> discard right
			right = index - 1
		case number < target:
			// array is in the ascending order, the number is smaller
			// -> the target is to the right -> discard left
			left = index + 1
		}
	}
	// search space is empty, there is no target
	return -1
}

4.7.1899 - 2022-05-02 17:49:22 +0300 MSK

Guess Number Higher or Lower

func guessNumber(n int) int {
	// checking edge cases
	if guess(1) == 0 {
		return 1
	} else if guess(n) == 0 {
		return n
	}
	left, right := 1, n
	for right >= left {
		// overflow protection
		number := left + (right-left)/2
		switch guess(number) {
		case 0:
			// found the target
			return number
		case -1:
			// the number is bigger -> the target is to the left -> discard right
			right = number - 1
		case 1:
			// the number is smaller -> the target is to the right -> discard left
			left = number + 1
		}
	}
	// ide shows an error, this return is unreachable in this issue
	return 0
}

4.7.1900 - 2022-05-02 17:34:04 +0300 MSK

Binary Search
/* https://leetcode.com/problems/binary-search/

Given an array of integers nums which is sorted in ascending order, and an integer target, write a function to search target in nums. If target exists, then return its index. Otherwise, return -1.

You must write an algorithm with O(log n) runtime complexity.



Example 1:

Input: nums = [-1,0,3,5,9,12], target = 9
Output: 4
Explanation: 9 exists in nums and its index is 4

Example 2:

Input: nums = [-1,0,3,5,9,12], target = 2
Output: -1
Explanation: 2 does not exist in nums so return -1



Constraints:

    1 <= nums.length <= 104
    -104 < nums[i], target < 104
    All the integers in nums are unique.
    nums is sorted in ascending order.

*/
package main

func search(numbers []int, target int) int {
	length := len(numbers)
	switch {
	case numbers[0] > target:
		// smallet number > target = there is no target in the array
		fallthrough
	case numbers[length-1] < target:
		// biggest number < target = there is no target in the array
		return -1
	case numbers[length-1] == target:
		// checking just in case, can save time
		return length - 1
	case numbers[0] == target:
		// checking just in case, can save time
		return 0
	}

	left, right := 0, length-1
	for right >= left {
		// overflow protection
		index := left + (right-left)/2
		number := numbers[index]
		switch {
		case number == target:
			// found the target
			return index
		case number > target:
			// array is in the ascending order, the number is bigger
			// -> the target is to the left -> discard right
			right = index - 1
		case number < target:
			// array is in the ascending order, the number is smaller
			// -> the target is to the right -> discard left
			left = index + 1
		}
	}
	// search space is empty, there is no target
	return -1
}

4.7.1901 - 2022-05-02 16:35:35 +0300 MSK

Average Salary Excluding the Minimum and Maximum Salary

func average(salary []int) float64 {
	length := len(salary)
	highest, lowest := math.MinInt, math.MaxInt
	result := 0
	for _, number := range salary {
		result += number
		if number > highest {
			highest = number
		}
		if number < lowest {
			lowest = number
		}
	}
	return float64(result-highest-lowest) / float64(length-2)
}

4.7.1902 - 2022-05-02 16:28:49 +0300 MSK

Count Odd Numbers in an Interval Range

func countOdds(low int, high int) int {
	low_even, high_even, half := (low&1) == 0, (high&1) == 0, (high-low)/2
	if low_even && high_even  {
		return half
	}
	return half + 1
}

4.7.1903 - 2022-05-02 14:58:45 +0300 MSK

Maximum Subarray

func maxSubArray(numbers []int) int {
	length := len(numbers)
	switch length {
	case 0:
		return 0
	case 1:
		return numbers[0]
	}
	maxCurrent, maxOverall := 0, math.MinInt
	for _, number := range numbers {
		maxCurrent += number
		if maxCurrent > maxOverall {
			maxOverall = maxCurrent
		}
		if maxCurrent < 0 {
			maxCurrent = 0
		}
	}
	return maxOverall
}

4.7.1904 - 2022-05-02 07:24:29 +0300 MSK

Contains Duplicate

func containsDuplicate(numbers []int) bool {
	if len(numbers) == 0 || len(numbers) == 1 {
		return false
	}
	occured := make(map[int]bool)
	for _, number := range numbers {
		_, isDuplicate := occured[number]
		if isDuplicate {
			return true
		}
		occured[number] = true
	}
	return false
}

4.7.1905 - 2022-05-01 16:23:58 +0300 MSK

Add to Array-Form of Integer
func addToArrayForm(number1 []int, add int) []int {
	if add == 0 {
		return number1
	}
	if len(number1) == 0 {
		return convert(add)
	}
	number2 := convert(add)
	length1, length2, carry := len(number1), len(number2), 0
	hightest := length1
	if length2 > length1 {
		hightest = length2
	}
	result := make([]int, hightest)
	index1, index2, indexResult := length1-1, 0, hightest-1
	for {
		index1Valid, index2Valid := index1 >= 0, index2 < length2
		if !index1Valid && !index2Valid && carry==0 {
			break
		}
		digit1, digit2 := 0, 0
		if index1Valid {
			digit1 = number1[index1]
			index1--
		}
		if index2Valid {
			digit2 = number2[index2]
			index2++
		}
		digitResult := digit1 + digit2 + carry
		if digitResult > 9 {
			carry = 1
			digitResult -= 10
		} else {
			carry = 0
		}
		if indexResult == -1 {
			result = append(result, 0)
			copy(result[1:], result[0:hightest])
            indexResult=0
		}
		result[indexResult] = digitResult
		indexResult--
	}
	return result
}

func convert(number int) (result []int) {
	for {
		if number == 0 {
			return
		}
		result = append(result, number%10)
		number /= 10
	}
}

4.7.1906 - 2022-05-01 15:41:08 +0300 MSK

Squares of a Sorted Array

func sortedSquares(numbers []int) []int {
	length := len(numbers)
	if length == 0 || length == 1 {
		return square(numbers, false)
	}
	negativesIndex := -1
	for index, number := range numbers {
		if number >= 0 {
			negativesIndex = index
			break
		}
	}
	if negativesIndex == 0 || negativesIndex == -1 {
		return square(numbers, negativesIndex == -1)
	}
	//fmt.Println("negativesIndex", negativesIndex)
	result, resultIndex, negativesIndex := make([]int, length), 0, negativesIndex-1
	for positivesIndex := negativesIndex + 1; resultIndex < length; positivesIndex++ {
		positiveOverflow := positivesIndex >= length
		for {
			if negativesIndex < 0 || resultIndex >= length {
				break
			}
			if !positiveOverflow && numbers[negativesIndex]*-1 > numbers[positivesIndex] {
				break
			}
			
			result[resultIndex] = numbers[negativesIndex]
			resultIndex++
			//fmt.Println("negative", negativesIndex, resultIndex, numbers[negativesIndex], result, numbers)
            negativesIndex--
		}
		if resultIndex < length && !positiveOverflow {
	//		fmt.Println("positivesIndex", positivesIndex, resultIndex, numbers[positivesIndex], result, numbers)
			result[resultIndex] = numbers[positivesIndex]
			resultIndex++
		}
	}
	return square(result, false)
}

func square(array []int, reverse bool) []int {
	if reverse {
		length := len(array)
		reversed := make([]int, length)
		for index := length - 1; index >= 0; index-- {
			reversed[length-index-1] = array[index] * array[index]
		}
		return reversed
	} else {
		for index, number := range array {
			array[index] = number * number
		}
		return array
	}
}

4.7.1907 - 2022-05-01 13:28:32 +0300 MSK

Merge Sorted Array

func merge(array1 []int, length1 int, array2 []int, length2 int) {
	if length2 == 0 {
		return
	} 
    if length1 == 0 {
		for index, number := range array2 {
			array1[index] = number
		}
		return
	}
	index1, index2, array1Copy := 0, 0, make([]int, length1)
	copy(array1Copy, array1)
	for index := 0; index < length1+length2; index++ {
		//fmt.Println(index, index1, index2, array1, array2)
		for index2 < length2 && (index1 >= length1 || array2[index2] <= array1Copy[index1]) {
			array1[index] = array2[index2]
			index2++
			index++
		}
		if index1 >= length1 {
			continue
		}
		array1[index] = array1Copy[index1]
		index1++
	}
}

4.7.1908 - 2022-05-01 13:12:45 +0300 MSK

Merge Sorted Array

func merge(array1 []int, length1 int, array2 []int, length2 int) {
	index1, index2, array1Copy := 0, 0, make([]int, length1)
	copy(array1Copy, array1)
	for index := 0; index < length1+length2; index++ {
		fmt.Println(index, index1, index2, array1, array2)
		if index2 < length2 && (index1 >= length1 || array2[index2] <= array1Copy[index1]) {
			array1[index] = array2[index2]
			index2++
			continue
		}
		array1[index] = array1Copy[index1]
		index1++

	}
}

4.7.1909 - 2022-05-01 09:06:49 +0300 MSK

Merge Two Sorted Lists
func mergeTwoLists(list1 *ListNode, list2 *ListNode) *ListNode {
	// ensure both lists are valid
	switch {
	case list1 == nil && list2 == nil:
		return nil
	case list1 == nil && list2 != nil:
		return list2
	case list1 != nil && list2 == nil:
		return list1
	}
	var root *ListNode
	if list1.Val < list2.Val {
		root = &ListNode{list1.Val, nil}
		list1 = list1.Next
	} else {
		root = &ListNode{list2.Val, nil}
		list2 = list2.Next
	}
	current := &root
	for {
		switch {
		case list1 == nil && list2 == nil:
			return root
		case list1 != nil && list2 != nil && list1.Val <= list2.Val:
			fallthrough
		case list1 != nil && list2 == nil:
			fmt.Println("1", list1.Val)
			updateResult(&current, &list1)
		case list1 != nil && list2 != nil && list1.Val > list2.Val:
			fallthrough
		case list1 == nil && list2 != nil:
			fmt.Println("2", list2.Val)
			updateResult(&current, &list2)
		}
	}
}
func updateResult(current ***ListNode, node **ListNode) {
	// modify the current result node
	(**current).Next = &ListNode{(*node).Val, nil}
	// move the current pointer
	*current = &(**current).Next
	// there is no next node -> nill it
	// there is next -> move it
	if (*node).Next == nil {
		*node = nil
	} else {
		*node = (*node).Next
	}
}

4.7.1910 - 2022-04-30 22:06:12 +0300 MSK

Valid Parentheses

func isValid(inputString string) bool {
	if len(inputString) == 0 || (len(inputString)&1) != 0 {
		return false
	}
	occurences := []rune{}
	ends := map[rune]rune{')': '(', '}': '{', ']': '['}
	for _, character := range inputString {
		length := len(occurences)
		last_valid, is_end := ends[character]
		if (is_end && length == 0) || (is_end && occurences[length-1] != last_valid) {
			return false
		}
		if is_end {
			occurences = occurences[0 : length-1]
		} else {
			occurences = append(occurences, character)
		}
	}
	if len(occurences) > 0 {
		return false
	}
	return true
}

4.7.1911 - 2022-04-30 20:27:04 +0300 MSK

Find Palindrome With Fixed Length
func kthPalindrome(queries []int, intLength int) (answer []int64) {
	for _, query := range queries {
		answer = append(answer, getPalindrom(query, intLength))
	}
	return
}

func getPalindrom(query int, length int) (result int64) {
	is_even := (length & 1) == 0
	power := length / 2
	if is_even {
		power -= 1
	}
	palindrome := int64(math.Pow10(power)) + int64(query) - 1
	result = palindrome
	if !is_even {
		palindrome /= 10
	}
	for palindrome > 0 {
		result = result*10 + palindrome%10
		palindrome /= 10
	}
	if len(fmt.Sprint(result)) != length {
		return -1
	}
	return
}

4.7.1912 - 2022-04-30 18:34:48 +0300 MSK

Find Palindrome With Fixed Length
class Solution {
    public long[] kthPalindrome(int[] queries, int intLength) {
        long[] res= new long[queries.length];
        for(int i=0;i<queries.length;i++){
            res[i]=nthPalindrome(queries[i],intLength);
        }
        return res;
    }
    public long nthPalindrome(int nth, int kdigit)
    {
    long temp = (kdigit & 1)!=0 ? (kdigit / 2) : (kdigit/2 - 1);
    long palindrome = (long)Math.pow(10, temp);
    palindrome += nth - 1;
    long res1=palindrome;
    if ((kdigit & 1)>0)
        palindrome /= 10;
    while (palindrome>0)
    {
        res1=res1*10+(palindrome % 10);
        palindrome /= 10;
    }
    String g="";
    g+=res1;
    if(g.length()!=kdigit)
        return -1;
    return res1;
}
}

4.7.1913 - 2022-04-30 09:12:31 +0300 MSK

Palindrome Number

func isPalindrome(number int) (result bool) {
	if number < 0 {
		return false
	} else if number/10 == 0 {
		return true
	}
	current := number
	digits := []int{}
	for {
		if current == 0 {
			break
		}
		digit := current % 10
		current /= 10
		digits = append(digits, digit)
	}
	digits_length := len(digits)
	skip := -1
	if digits_length%2 != 0 {
		skip = digits_length / 2
	}
	for index, digit := range digits {
		if index != skip && digit != digits[digits_length-index-1] {
			return false
		}
	}
	return true
}

4.7.1914 - 2022-04-30 08:49:48 +0300 MSK

Two Sum IV - Input is a BST
import "sort"
func construct(root *TreeNode, results map[int]int) {
	if root == nil {
		return
	}
	if results[root.Val] < 2 {
		results[root.Val] += 1
	}
	construct(root.Left, results)
	construct(root.Right, results)
}

func sorted(input_map map[int]int) (results []int) {
	for key := range input_map {
		results = append(results, key)
	}
	return
}

func findTarget(root *TreeNode, target int) bool {
	if root == nil {
		return false
	}
	results := map[int]int{}
	construct(root, results)
	if target%2 == 0 && results[target/2] == 2 {
		return true
	}
	results_sorted := sorted(results)
	results_sorted_len := len(results_sorted)
	sort.Ints(results_sorted)
	for index, number := range results_sorted {
		for index_inner := index + 1; index_inner < results_sorted_len; index_inner++ {
			if number+results_sorted[index_inner] == target {
				return true
			}
		}
	}
	return false
}

4.7.1915 - 2022-04-30 08:49:00 +0300 MSK

Two Sum IV - Input is a BST
import "sort"

func construct(root *TreeNode, results map[int]bool, doubles map[int]bool) {
	if root == nil {
		return
	}
	_, exists := results[root.Val]
	if !exists {
		results[root.Val] = true
	} else if _, double := doubles[root.Val]; exists && double {
		doubles[root.Val] = true
	}
	construct(root.Left, results, doubles)
	construct(root.Right, results, doubles)
}

func sorted(input_map map[int]bool) (results []int) {
	for key := range input_map {
		results = append(results, key)
	}
	return
}

func findTarget(root *TreeNode, target int) bool {
	if root == nil {
		return false
	}
	results := map[int]bool{}
	doubles := map[int]bool{}
	construct(root, results, doubles)
	if _, double_exists := doubles[target/2]; target%2 == 0 && double_exists {
		return true
	}
	results_sorted := sorted(results)
	results_sorted_len := len(results_sorted)
	sort.Ints(results_sorted)
	for index, number := range results_sorted {
		for index_inner := index + 1; index_inner < results_sorted_len; index_inner++ {
			if number+results_sorted[index_inner] == target {
				return true
			}
		}
	}
	return false
}

4.7.1916 - 2022-04-30 08:30:40 +0300 MSK

Two Sum IV - Input is a BST
import "sort"

func construct(root *TreeNode, results map[int]int) {
	if root == nil {
		return
	}
	if results[root.Val] < 2 {
		results[root.Val] += 1
	}
	construct(root.Left, results)
	construct(root.Right, results)
}

func sorted(input_map map[int]int) (results []int) {
	for key := range input_map {
		results = append(results, key)
	}
	return
}

func findTarget(root *TreeNode, target int) bool {
	if root == nil {
		return false
	}
	results := map[int]int{}
	construct(root, results)
	if target%2 == 0 && results[target/2] == 2 {
		return true
	}
	results_sorted := sorted(results)
	results_sorted_len := len(results_sorted)
	sort.Ints(results_sorted)
	for index, number := range results_sorted {
		for index_inner := index + 1; index_inner < results_sorted_len; index_inner++ {
			if number+results_sorted[index_inner] == target {
				return true
			}
		}
	}
	return false
}

4.7.1917 - 2022-04-30 07:52:06 +0300 MSK

Two Sum IV - Input is a BST

func construct(root *TreeNode, results map[int]int) {
	if root == nil {
		return
	}
	if results[root.Val] < 2 {
		results[root.Val] += 1
	}
	construct(root.Left, results)
	construct(root.Right, results)
}

func findTarget(root *TreeNode, target int) bool {
	results := map[int]int{}
	construct(root, results)
	for number, count := range results {
		if count == 2 && number*2 == target {
			return true
		}
		for number_inner := range results {
			if number_inner <= number {
				continue
			}
			if number+number_inner == target {
				return true
			}
		}
	}
	return false
}

4.7.1918 - 2022-04-30 06:41:23 +0300 MSK

Two Sum II - Input Array Is Sorted
func twoSum(numbers []int, target int) []int {
	numbers_len := len(numbers)
	for index, number := range numbers {
		for index_inner := index + 1; index_inner < numbers_len; index_inner++ {
			if numbers[index_inner]+number == target {
				return []int{index + 1, index_inner + 1}
			}
		}
	}
	return []int{}
}

4.7.1919 - 2022-04-30 06:29:16 +0300 MSK

Two Sum
func twoSum(numbers []int, target int) []int {
	numbers_len := len(numbers)
	for index, number := range numbers {
		for index_inner := index + 1; index_inner < numbers_len; index_inner++ {
			if numbers[index_inner]+number == target {
				return []int{index, index_inner}
			}
		}
	}
	return []int{}
}

4.7.1920 - 2022-04-30 05:36:04 +0300 MSK

Add Two Numbers II
func reverse(list *ListNode) *ListNode {
	if list == nil || list.Next == nil {
		return list
	}
	result := &ListNode{list.Val, nil}
	current := list.Next
	for {
		if current == nil {
			return result
		}
		result = &ListNode{current.Val, result}
        current = current.Next
	}
}

func addTwoNumbers(list_1 *ListNode, list_2 *ListNode) *ListNode {
	current_1, current_2, result := reverse(list_1), reverse(list_2), &ListNode{}
	var carry int
	result_current := result
	for {
		var value_1, value_2 int
		if current_1 != nil {
			value_1 = current_1.Val
			current_1 = current_1.Next
		}
		if current_2 != nil {
			value_2 = current_2.Val
			current_2 = current_2.Next
		}
		sum := value_1 + value_2 + carry
		if sum > 9 {
			sum -= 10
			carry = 1
		} else {
			carry = 0
		}
		result_current.Val = sum
		if current_1 == nil && current_2 == nil && carry == 0 {
			result_current.Next = nil
			return reverse(result)
		} else if current_1 == nil && current_2 == nil && carry != 0 {
			current_1 = &ListNode{}
		}
		result_current.Next = &ListNode{}
		result_current = result_current.Next
	}
}

4.7.1921 - 2022-04-29 22:10:38 +0300 MSK

Add Two Numbers

func addTwoNumbers(list_1 *ListNode, list_2 *ListNode) *ListNode {
	current_1, current_2, result := list_1, list_2, &ListNode{}
	var carry int
	result_current := result
	for {
		var value_1, value_2 int
		if current_1 != nil {
			value_1 = current_1.Val
			current_1 = current_1.Next
		}
		if current_2 != nil {
			value_2 = current_2.Val
			current_2 = current_2.Next
		}
		sum := value_1 + value_2 + carry
		if sum > 9 {
			sum -= 10
			carry = 1
		} else {
			carry = 0
		}
		result_current.Val = sum
		if current_1 == nil && current_2 == nil && carry == 0 {
			result_current.Next = nil
			return result
		} else if current_1 == nil && current_2 == nil && carry != 0 {
			current_1 = &ListNode{}
		}
		result_current.Next = &ListNode{}
		result_current = result_current.Next
	}
}

4.7.1922 - 2022-04-29 19:52:46 +0300 MSK

Longest Common Prefix
func longestCommonPrefix(strings []string) string {
	switch len(strings) {
	case 0:
		return ""
	case 1:
		return strings[0]
	}
	result := strings[0]
for index := 1; index < len(strings); index++ {
		current := strings[index]
		previous := strings[index-1]
		current_max := len(current)
		result_max := len(result)
		var slice_max int
		if result_max > current_max {
			slice_max = current_max
			result = result[0:slice_max]
		} else {
			slice_max = result_max
		}
		for ; slice_max >= 0; slice_max-- {
			current_slice := current[0:slice_max]
			if current_slice == previous[0:slice_max] {
				result = current_slice
				break
			}
			if slice_max == 0 {
				return ""
			}
		}
	}	
    return result
}

4.7.1923 - 2022-04-29 18:51:04 +0300 MSK

Longest Common Prefix

func substrings(input string) map[string]bool {
	results := make(map[string]bool)
	for index := range input {
		results[input[0:index+1]] = true
	}
	return results
}

func string_in_maps(
	source map[string]bool,
	target map[string]bool,
	results map[string]bool) {
	for string := range source {
		is_valid, exists_in_results := results[string]
		_, exists_in_target := target[string]
		switch {
		case !exists_in_target:
			fallthrough
		case exists_in_target && (is_valid || !exists_in_results):
			results[string] = exists_in_target
		}
	}
}

func longestCommonPrefix(strings []string) (result string) {
	results := make(map[string]bool)
	var previous map[string]bool
	for index, string := range strings {
		current := substrings(string)
		if index == 0 {
			previous = current
		}
		string_in_maps(previous, current, results)
		string_in_maps(current, previous, results)
		previous = current
	}
	for string, valid := range results {
		if valid && len(string) > len(result) {
			result = string
		}
	}
	return
}

4.7.1924 - 2022-04-29 18:09:02 +0300 MSK

Longest Common Prefix

import "fmt"


func substrings(input string) map[string]bool {
	results := make(map[string]bool)
	for index := range input {
		results[string(input[0:index+1])] = true
	}
	return results
}

func string_in_maps(
	source map[string]bool,
	target map[string]bool,
	results map[string]bool) {
	for string := range source {
		if result, exists_in_results := results[string]; exists_in_results && !result {
			continue
		}
		_, exists_in_target := target[string]
		results[string] = exists_in_target
	}
}

func longestCommonPrefix(strings []string) (result string) {
	results := make(map[string]bool)
	previous := make(map[string]bool)
	for index, string := range strings {
		current := substrings(string)
		if index == 0 {
			previous = current
		}
		string_in_maps(current, previous, results)
		string_in_maps(previous, current, results)
		fmt.Println("current string", string, current, "results", results)
		previous = current
	}
	for string, valid := range results {
		if !valid || len(string) < len(result) {
			continue
		}
		if len(string) == len(result) && string < result {
			result = string
			continue
		}
		result = string
	}
	fmt.Println("result", result)
	return
}

4.7.1925 - 2022-04-28 09:04:20 +0300 MSK

Roman to Integer
func romanToInt(input string) int {
	var result int
	types := map[rune]int{
		'I': 1, 'V': 5, 'X': 10, 'L': 50, 'C': 100, 'D': 500, 'M': 1000,
	}
	var previous rune
	for _, character := range input {
		result += types[character]
		switch {
		case previous == 'I' && (character == 'V' || character == 'X'):
			fallthrough
		case previous == 'X' && (character == 'L' || character == 'C'):
			fallthrough
		case previous == 'C' && (character == 'D' || character == 'M'):
			result -= types[previous] * 2
		}
		previous = character
	}
	return result
}

4.7.1926 - 2022-04-28 08:59:35 +0300 MSK

Roman to Integer

func in(character rune, targets string) bool {
	for _, target := range targets {
		if character == target {
			return true
		}
	}
	return false
}

func romanToInt(roman string) int {
	type dict map[rune]int
	var result int
	input := []rune(roman)
	types := dict{
		'I': 1, 'V': 5, 'X': 10, 'L': 50, 'C': 100, 'D': 500, 'M': 1000,
	}
	var previous rune
	for _, character := range input {
		result += types[character]
		switch {
		case previous == 'I' && in(character, "VX"):
			fallthrough
		case previous == 'X' && in(character, "LC"):
			fallthrough
		case previous == 'C' && in(character, "DM"):
			result -= types[previous] * 2
		}
		previous = character
	}
	return result
}

4.7.1927 - 2022-04-28 08:59:06 +0300 MSK

Roman to Integer

func in(character rune, targets string) bool {
	for _, target := range targets {
		if character == target {
			return true
		}
	}
	return false
}

func romanToInt(roman string) int {
	type dict map[rune]int
	var result int
	types := dict{
		'I': 1, 'V': 5, 'X': 10, 'L': 50, 'C': 100, 'D': 500, 'M': 1000,
	}
	for index, character := range roman {
		result += types[character]
        if index < 1 {
            continue}
        switch {
		case roman[index-1] == 'I' && in(character, "VX"):
			fallthrough
		case roman[index-1] == 'X' && in(character, "LC"):
			fallthrough
		case roman[index-1] == 'C' && in(character, "DM"):
			result -= types[rune(roman[index-1])] * 2
		}
	}
	return result
}

4.7.1928 - 2022-04-28 08:55:16 +0300 MSK

Roman to Integer

func in(character rune, targets string) bool {
	for _, target := range targets {
		if character == target {
			return true
		}
	}
	return false
}

func romanToInt(roman string) int {
	type dict map[rune]int
	var result int
	input := []rune(roman)
	types := dict{
		'I': 1, 'V': 5, 'X': 10, 'L': 50, 'C': 100, 'D': 500, 'M': 1000,
	}
	var previous rune
	for _, character := range input {
		result += types[character]
		switch {
		case previous == 'I' && in(character, "VX"):
			fallthrough
		case previous == 'X' && in(character, "LC"):
			fallthrough
		case previous == 'C' && in(character, "DM"):
			result -= types[previous] * 2
		}
		previous = character
	}
	return result
}

4.8 - Mullvad

Mullvad will invalidate a key If a host connects to many vpns with it at the same time

4.9 - Old diagrams

Old drawio diagrams
Architecture of an HTTP cube-root service: DNS and load balancers route requests to cached workers in two replicated locations. Anki desktop and Android clients use a GraphQL service to enrich Chinese flashcards with dictionary definitions, translations, sentence examples, and audio.

4.10 - Pgp

PGP

https://support.yubico.com/s/article/Using-Your-YubiKey-with-OpenPGP

https://github.com/drduh/YubiKey-Guide

4.11 - Ping

This problem can be caused by vpns with “kill-switch” enabled, so you might need to disable them.

Disable Mullvad VPN:

sudo systemctl disable --now mullvad-daemon

4.12 - Qubes OS

Run in dom0:

qmv-prefs <VM NAME> qrexec_timeout <seconds>

4.13 - Repo

Repository-specific information
  • Install packages:
    sudo dnf install \
      clang clang-tools-extra java-latest-openjdk-devel rust cargo mesa-libGL-devel \
      go Xvfb python3 gmp-devel patch podman git git-lfs fuse fuse-libs pcsc-lite pcsc-lite-devel \
      openssl gnutls-utils opensc openssl-pkcs11 libdnet qemu-kvm qemu-img
    
  • Install bazelisk: https://bazel.build/install/bazelisk
  • Symlink bazel:
    ln -s ~/.local/bin/bazelisk ~/.local/bin/bazel
    
  • Install git hooks:
    bazel run //:write_git_hooks
    
  • Install android tools:
    ANDROID_HOME="${HOME}/Android/Sdk" \
      bazel run --config=agent \
        --repo_env=ANDROID_HOME= \
        //tools/android:install
    
    The empty repository environment is required for the first installation so Bazel does not try to load the SDK before sdkmanager installs it. Afterwards, export ANDROID_HOME and ANDROID_NDK_HOME, or set both with --repo_env in the ignored user.bazelrc. The repository dotfiles export the expected paths.
  • Setup dotfiles (optional):
    bazel run //projects/dotfiles:install
    
  • Install nvm: https://github.com/nvm-sh/nvm
  • Install node:
    nvm install node
    
  • Qt is downloaded by Bazel; no host installation is required.
bazel run //tools/vault -- login --method=userpass username="${USER}"
. "$(bazel run //tools/bzlenv)"

Build compile_commands.json:

bazel run :refresh_compile_commands

This requires around 90G

bazel build //...
bazel test //...
find \
  "(" -name "*.bazel" -o -name "*.bzl" -o -name ".bazelrc" -o -name "*.md" ")" \
  -type f \
  -exec sed -i 's|//bzl/rules/txt|//tools/txt|g' "{}" ";"`
bazel build //projects/alwaldend.com:site_source_archive && \
  cat bazel-bin/projects/alwaldend.com/site_source_archive.manifest | \
  jq -r --slurp ". | flatten | .[].dest" | \
  grep "^content"
find -name "BUILD.bazel" -type f -exec sed -i '/al_readme(/,/)/d' "{}" ";"
bazel query 'attr(visibility, "//visibility:public", //...)'
mkdir projects/project_name
cd projects/project_name
ln -s ../../.bazelignore
ln -s ../../.bazeliskrc
ln -s ../../tools/bazelrc/bzl_project.bazelrc .bazelrc

Agent restart helps:

gpg-connect-agent updatestartuptty /bye

Check the key:

bazel run //tools/ykman -- info

If some repo rules are timing out (java ones, for example), you can add --remote_timeout 1000000

bazel run //tools/pnpm -- --dir "${PWD}" install

Documentation: https://github.com/aspect-build/rules_js/blob/main/docs/pnpm.md#update_pnpm_lock

Proxmox VMs have Kerberos enabled, which slows SSH down, you need to disable it locally

~/.ssh/config.d/config:

GSSAPIAuthentication no
sudo cp infra/vault/tf/output/pki_ca_servers.crt /etc/pki/ca-trust/source/anchors/
sudo update-ca-trust
find -name "go.mod" -exec sh -c 'cd "$(dirname "{}")" && bazel run @rules_go//go -- mod tidy' ";"

4.14 - Rfc

Some useful rfcs

4.14.1 - Rfc2119

Rfc2119






Network Working Group                                         S. Bradner
Request for Comments: 2119                            Harvard University
BCP: 14                                                       March 1997
Category: Best Current Practice


        Key words for use in RFCs to Indicate Requirement Levels

Status of this Memo

   This document specifies an Internet Best Current Practices for the
   Internet Community, and requests discussion and suggestions for
   improvements.  Distribution of this memo is unlimited.

Abstract

   In many standards track documents several words are used to signify
   the requirements in the specification.  These words are often
   capitalized.  This document defines these words as they should be
   interpreted in IETF documents.  Authors who follow these guidelines
   should incorporate this phrase near the beginning of their document:

      The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL
      NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED",  "MAY", and
      "OPTIONAL" in this document are to be interpreted as described in
      RFC 2119.

   Note that the force of these words is modified by the requirement
   level of the document in which they are used.

1. MUST   This word, or the terms "REQUIRED" or "SHALL", mean that the
   definition is an absolute requirement of the specification.

2. MUST NOT   This phrase, or the phrase "SHALL NOT", mean that the
   definition is an absolute prohibition of the specification.

3. SHOULD   This word, or the adjective "RECOMMENDED", mean that there
   may exist valid reasons in particular circumstances to ignore a
   particular item, but the full implications must be understood and
   carefully weighed before choosing a different course.

4. SHOULD NOT   This phrase, or the phrase "NOT RECOMMENDED" mean that
   there may exist valid reasons in particular circumstances when the
   particular behavior is acceptable or even useful, but the full
   implications should be understood and the case carefully weighed
   before implementing any behavior described with this label.





Bradner                  Best Current Practice                  [Page 1]

RFC 2119                     RFC Key Words                    March 1997


5. MAY   This word, or the adjective "OPTIONAL", mean that an item is
   truly optional.  One vendor may choose to include the item because a
   particular marketplace requires it or because the vendor feels that
   it enhances the product while another vendor may omit the same item.
   An implementation which does not include a particular option MUST be
   prepared to interoperate with another implementation which does
   include the option, though perhaps with reduced functionality. In the
   same vein an implementation which does include a particular option
   MUST be prepared to interoperate with another implementation which
   does not include the option (except, of course, for the feature the
   option provides.)

6. Guidance in the use of these Imperatives

   Imperatives of the type defined in this memo must be used with care
   and sparingly.  In particular, they MUST only be used where it is
   actually required for interoperation or to limit behavior which has
   potential for causing harm (e.g., limiting retransmisssions)  For
   example, they must not be used to try to impose a particular method
   on implementors where the method is not required for
   interoperability.

7. Security Considerations

   These terms are frequently used to specify behavior with security
   implications.  The effects on security of not implementing a MUST or
   SHOULD, or doing something the specification says MUST NOT or SHOULD
   NOT be done may be very subtle. Document authors should take the time
   to elaborate the security implications of not following
   recommendations or requirements as most implementors will not have
   had the benefit of the experience and discussion that produced the
   specification.

8. Acknowledgments

   The definitions of these terms are an amalgam of definitions taken
   from a number of RFCs.  In addition, suggestions have been
   incorporated from a number of people including Robert Ullmann, Thomas
   Narten, Neal McBurnett, and Robert Elz.












Bradner                  Best Current Practice                  [Page 2]

RFC 2119                     RFC Key Words                    March 1997


9. Author's Address

      Scott Bradner
      Harvard University
      1350 Mass. Ave.
      Cambridge, MA 02138

      phone - +1 617 495 3864

      email - sob@harvard.edu









































Bradner                  Best Current Practice                  [Page 3]


4.15 - Shell

A subshell doesn’t have the deactivate function, so you have to use a workaround:

. .venv/bin/activate
(
    echo "subshell, still in venv: $(which python)" && \
    . "$(dirname "$(which python)")/activate" && \
    deactivate && \
    echo "subshell, out of venv: $(which python)"
)

https://unix.stackexchange.com/a/138498

A subshell starts out as an almost identical copy of the original shell process. Under the hood, the shell calls the fork system call1, which creates a new process whose code and memory are copies2. When the subshell is created, there are very few differences between it and its parent. In particular, they have the same variables. Even the $$ special variable keeps the same value in subshells: it’s the original shell’s process ID. Similarly $PPID is the PID of the parent of the original shell.

A few shells change a few variables in the subshell. Bash ≥4.0 sets BASHPID to the PID of the shell process, which changes in subshells. Bash, zsh and mksh arrange for $RANDOM to yield different values in the parent and in the subshell. But apart from built-in special cases like these, all variables have the same value in the subshell as in the original shell, the same export status, the same read-only status, etc. All function definitions, alias definitions, shell options and other settings are inherited as well.

A subshell created by (…) has the same file descriptors as its creator. Some other means of creating subshells modify some file descriptors before executing user code; for example, the left-hand side of a pipe runs in a subshell3 with standard output connected to the pipe. The subshell also starts out with the same current directory, the same signal mask, etc. One of the few exceptions is that subshells do not inherit custom traps: ignored signals (trap ’’ SIGNAL) remain ignored in the subshell, but other traps (trap CODE SIGNAL) are reset to the default action4.

A subshell is thus different from executing a script. A script is a separate program. This separate program might coincidentally be also a script which is executed by the same interpreter as the parent, but this coincidence doesn’t give the separate program any special visibility on internal data of the parent. Non-exported variables are internal data, so when the interpreter for the child shell script is executed, it doesn’t see these variables. Exported variables, i.e. environment variables, are transmitted to executed programs.

4.18 - Todo

Todo

//projects builds should not depend on //tools, etc

Maybe wth aspects, aspect hints? Or check deps using genquery?

4.19 - Vault

Hashicorp Vault

https://arminreiter.com/2022/01/create-your-own-certificate-authority-ca-using-openssl/

  • Get the encrypted unseal key
  • Unencrypt it: cat unseal.txt | base64 --decode | gpg -dq
  • Run vault operator unseal

4.20 - Waydroid

chmod 777 file
sudo cp file ~/.local/share/waydroid/data/media/0/Download/

Docs: https://docs.waydro.id/faq/setting-up-a-shared-folder

5 - Data

Data tree

This tree contains repository-owned data and documentation assets. All tracked content follows the repository’s public-source policy. Actual credentials, personal information, and secret-bearing generated values remain prohibited.

  • Bazel targets MUST use repository-internal visibility.
  • The tree MUST NOT be independently published as a product artifact.
  • Data and documentation assets MAY be used in builds and MAY be embedded in an explicitly owned published artifact when that owner permits it.

5.1 - Blender

Blender

5.2 - Books

Book data
[[book]]
title = "Reverend Insanity"
alt_titles = ["Gu Daoist Master", "蛊真人"]
thumbnail = "https://cdn.novelupdates.com/images/2025/06/Reverend-Insanity.jpg"
quality = "Peak"
reading = "Finished available, C2334"
authors = ["gu-zhen-ren"]
links = [
  { title = "novelupdates", url = "https://www.novelupdates.com/series/reverend-insanity/" },
]

[[book]]
title = "Virtuous Sons"
thumbnail = "https://www.royalroadcdn.com/public/covers-large/41330-virtuous-sons-a-greco-roman-xianxia.jpg"
quality = "Peak"
reading = "Finished available (hiatus), C2.22"
authors = ["ya-boy"]
links = [
  { title = "royalroad", url = "https://www.royalroad.com/fiction/41330/virtuous-sons-a-greco-roman-xianxia" },
]

[[book]]
title = "My Longevity Simulation"
thumbnail = "https://cdn.novelupdates.com/images/2024/08/My-Longevity-Simulation.jpg"
quality = "Good"
reading = "Dropped, C838"
authors = ["angry-squid"]
links = [
  { title = "novelupdates", url = "https://www.novelupdates.com/series/my-longevity-simulation/" },
  { title = "novelbin", url = "https://novelbin.com/b/my-longevity-simulation/chapter-724" },
]

[[book]]
title = "Unintended Immortality"
alt_titles = ["The Unintentional Path to Immortality", "我本无意成仙"]
thumbnail = "https://cdn.novelupdates.com/images/2024/11/The-Unintentional-Path-to-Immortality.jpg"
quality = "Good"
reading = "Finished, C713"
authors = ["golden-jasmine"]
links = [
  { title = "novelupdates", url = "https://www.novelupdates.com/series/the-unintentional-path-to-immortality/" },
  { title = "novelfile", url = "https://novelfire.net/book/unintended-immortality/chapter-447" },
]

[[book]]
title = "Lord of the Mysteries"
thumbnail = "https://cdn.novelupdates.com/images/2018/11/Lord-of-the-Mysteries.jpeg"
quality = "Good"
reading = "Finished volume 2"
authors = ["cuttlefish-that-loves-diving"]
links = [
  { title = "novelupdates", url = "https://www.novelupdates.com/series/lord-of-the-mysteries/" },
]

[[book]]
title = "Ze Tian Ji"
alt_titles = ["Way of Choices", "择天记"]
thumbnail = "https://cdn.novelupdates.com/images/2015/06/Zetianji.jpg"
quality = "Good"
reading = "Finished"
authors = ["mao-ni"]
links = [
  { title = "novelupdates", url = "https://www.novelupdates.com/series/ze-tian-ji/" },
]

[[book]]
title = "The Path Toward Heaven"
alt_titles = ["大道朝天"]
thumbnail = "https://cdn.novelupdates.com/images/2017/10/pathtowardheaven.jpg"
quality = "Good"
reading = "Finished available chapters"
authors = ["mao-ni"]
links = [
  { title = "novelupdates", url = "https://www.novelupdates.com/series/the-path-toward-heaven/" },
]

[[book]]
title = "Nightfall"
alt_titles = ["Ever Night", "将夜"]
thumbnail = "https://cdn.novelupdates.com/images/2015/06/JiangYe-.jpg"
quality = "Good"
reading = "Finished"
authors = ["mao-ni"]
links = [
  { title = "novelupdates", url = "https://www.novelupdates.com/series/nightfall/" },
]

[[book]]
title = "The Experimental Log of the Crazy Lich"
alt_titles = ["疯巫妖的实验日志"]
thumbnail = "https://cdn.novelupdates.com/images/2017/11/The-Experimental-Log-of-the-Crazy-Lich.jpg"
quality = "Good"
reading = "Finished volume 1"
authors = ["angry-squirrel"]
links = [
  { title = "novelupdates", url = "https://www.novelupdates.com/series/the-experimental-log-of-the-crazy-lich/" },
]

[[book]]
title = "The Sage Who Transcended Samsara"
alt_titles = ["一世之尊"]
thumbnail = "https://cdn.novelupdates.com/images/2019/05/17435126d0d51135aa4a70eb4c00f08bc818d0de901c670ce979f03a966bf10f.jpg"
quality = "Good"
reading = "Finished, dropped at the end"
authors = ["cuttlefish-that-loves-diving"]
links = [
  { title = "novelupdates", url = "https://www.novelupdates.com/series/the-sage-who-transcended-samsara/" },
]

[[book]]
title = "Outside of time"
alt_titles = ["光阴之外"]
thumbnail = "https://cdn.novelupdates.com/images/2024/08/Outside-of-Time.jpg"
quality = "Ok"
reading = "Dropped, C1470"
authors = ["er-gen"]
links = [
  { title = "novelupdates", url = "https://www.novelupdates.com/series/beyond-the-timescape/" },
]

[[book]]
title = "Archfiend"
alt_titles = ["最强妖孽"]
thumbnail = "https://cdn.novelupdates.com/images/2017/11/strongest-evildoer.jpeg"
quality = "Decent"
reading = "Finished translated chapters, chapter 528"
authors = ["nocturnal-stranger"]
links = [
  { title = "novelupdates", url = "https://www.novelupdates.com/series/archfiend/" },
]

[[book]]
title = "Godclads"
thumbnail = "https://www.royalroadcdn.com/public/covers-large/59663-godclads.jpg"
quality = "Good, a bit too dramatic"
reading = "Dropped, C37-11"
authors = ["ostensible-mammal"]
links = [
  { title = "royalroad", url = "https://www.royalroad.com/fiction/59663/godclads" },
]

[[book]]
title = "Defiance of the Fall"
thumbnail = "https://www.royalroadcdn.com/public/covers-large/24709-defiance-of-the-fall.jpg"
quality = "Decent"
reading = "Dropped, C1370"
authors = ["thefirstdefier"]
links = [
  { title = "royalroad", url = "https://www.royalroad.com/fiction/24709/defiance-of-the-fall" },
]

[[book]]
title = "Matabar"
thumbnail = "https://www.royalroadcdn.com/public/covers-large/matabar-aaaa9rj72ru.jpg"
quality = "Good"
reading = "Dropped, chapter 120"
authors = ["kirill-klevanski"]
links = [
  { title = "royalroad", url = "https://www.royalroad.com/fiction/94398/matabar" },
]

[[book]]
title = "Renegade Immortal"
thumbnail = "https://cdn.novelupdates.com/images/2016/03/xianni-1.jpg"
quality = "Good"
reading = "Finished"
authors = ["er-gen"]
links = [
  { title = "novelupdates", url = "https://www.novelupdates.com/series/renegade-immortal/" },
]

[[book]]
title = "The Years of Apocalypse"
thumbnail = "https://www.royalroadcdn.com/public/covers-large/the-years-of-apocalypse-a-time-loop-progression.jpg"
quality = "Decent"
reading = "Dropped, C226"
authors = ["uraniumphoenix"]
links = [
  { title = "royalroad", url = "https://www.royalroad.com/fiction/81002/the-years-of-apocalypse-a-time-loop-progression" },
]

[[book]]
title = "Downtown Druid"
thumbnail = "https://www.royalroadcdn.com/public/covers-large/79173-downtown-druid.jpg"
quality = "Decent"
reading = "Finished volume 1"
authors = ["seersucker"]
links = [
  { title = "royalroad", url = "https://www.royalroad.com/fiction/79173/downtown-druid-book-1-stubbed" },
]

[[book]]
title = "A Practical Guide to Sorcery"
thumbnail = "https://www.azaleaellis.com/wp-content/uploads/2022/10/A-Conjuring-of-Ravens-Web-800w-683x1024.jpg"
quality = "Decent, slow upload"
reading = "Dropped, C262"
authors = ["azalea-ellis"]
links = [
  { title = "azaleaellis", url = "https://www.azaleaellis.com/a-practical-guide-to-sorcery/" },
]

[[book]]
title = "Dungeon Crawler Carl"
thumbnail = "https://www.royalroadcdn.com/public/covers-full/29358-dungeon-crawler-carl.jpg"
quality = "Good"
reading = "Finished available, B7"
authors = ["doctorhepa"]
links = [
  { title = "royalroad", url = "https://www.royalroad.com/fiction/29358/dungeon-crawler-carl-book-6-the-ghosts-of-earth" },
]

[[book]]
title = "Beware Of Chicken"
thumbnail = "https://www.royalroadcdn.com/public/covers-full/beware-of-chicken-aacav1xoeg8.jpg"
quality = "Decent"
reading = "Dropped, V4(V6)C68"
authors = ["casualfarmer"]
links = [
  { title = "royalroad", url = "https://www.royalroad.com/fiction/39408/beware-of-chicken" },
]

[[book]]
title = "I Shall Seal the Heavens"
thumbnail = "https://cdn.novelupdates.com/images/2015/06/15_ISSTH.jpg"
quality = "Good"
reading = "Finished"
authors = ["er-gen"]
links = [
  { title = "novelupdates", url = "https://www.novelupdates.com/series/i-shall-seal-the-heavens/" },
]

[[book]]
title = "World of Cultivation"
alt_titles = ["修真世界"]
quality = "Good"
reading = "Finished"
authors = ["fang-xiang"]
links = [
  { title = "novelupdates", url = "https://www.novelupdates.com/series/world-of-cultivation/" },
]

[[book]]
title = "Return of the Runebound Professor"
thumbnail = "https://www.royalroadcdn.com/public/covers-large/68679-return-of-the-runebound-professor.jpg"
quality = "Ok"
reading = "Reading, B7C749"
authors = ["actus"]
links = [
  { title = "royalroad", url = "https://www.royalroad.com/fiction/68679/return-of-the-runebound-professor-book-6-stubbed" },
]

[[book]]
title = "I Am Become Death"
thumbnail = "https://www.royalroadcdn.com/public/covers-large/109537-i-am-become-death-a-progression-fantasy.jpg"
quality = "Decent"
summary = "Nothing exceptional"
reading = "Dropped, chapter 55"
authors = ["clarke"]
links = [
  { title = "royalroard", url = "https://www.royalroad.com/fiction/109537/i-am-become-death-a-progression-fantasy-cultivation-based" },
]

[[book]]
title = "Ghost of the Truthseeker"
thumbnail = "https://www.royalroadcdn.com/public/covers-large/56136-ghost-of-the-truthseeker.jpg"
quality = "Ok"
reading = "Dropped, chapter 220"
authors = ["strungbound"]
links = [
  { title = "royalroad", url = "https://www.royalroad.com/fiction/56136/ghost-of-the-truthseeker-book-4-being-released" },
]

[[book]]
title = "The Beginning After the End"
thumbnail = "https://upload.wikimedia.org/wikipedia/en/c/cc/The_Beginning_After_the_End_webtoon_volume_1_cover.jpg"
quality = "Bad, isekai slop"
reading = "Dropped, volume 1, chapter 13"
authors = ["turtleme"]
links = [
  { title = "wikipedia", url = "https://en.wikipedia.org/wiki/The_Beginning_After_the_End" },
]

[[book]]
title = "Rise of the Living Forge"
thumbnail = "https://www.royalroadcdn.com/public/covers-large/79094-rise-of-the-living-forge-stubbing-in-october.jpg"
quality = "Ok"
reading = "Dropped, C509"
authors = ["actus"]
links = [
  { title = "royalroad", url = "https://www.royalroad.com/fiction/79094/rise-of-the-living-forge-a-blacksmith-litrpg" },
]

[[book]]
title = "Vigor Mortis"
thumbnail = "https://www.royalroadcdn.com/public/covers-large/40373-vigor-mortis.jpg"
quality = "Ok"
reading = "Dropped, V4C27"
authors = ["thundamoo"]
links = [
  { title = "royalroad", url = "https://www.royalroad.com/fiction/40373/vigor-mortis" },
]

[[book]]
title = "Ultimate Level 1"
thumbnail = "https://www.royalroadcdn.com/public/covers-large/76259-ultimate-level-1-litrpg-book-8-stubs-531.jpg"
quality = "Bad, litrpg slop"
reading = "Dropped, V1C17"
authors = ["dads-bedtime-stories"]
links = [
  { title = "royalroad", url = "https://www.royalroad.com/fiction/76259/ultimate-level-1-litrpg" },
]

[[book]]
title = "If It’s for My Daughter, I’d Even Defeat a Demon Lord"
thumbnail = "https://cdn.novelupdates.com/images/2020/05/uchimusuLNv2.jpg"
quality = "Bad, Japanese slice-of-life litrpg fantasy slop"
reading = "Dropped, V4C2"
authors = ["chirolu"]
links = [
  { title = "novelupdates", url = "https://www.novelupdates.com/series/if-its-for-my-daughter-id-even-defeat-a-demon-lord/" },
]

[[book]]
title = "Mark of the Fool"
thumbnail = "https://www.royalroadcdn.com/public/covers-large/41618-mark-of-the-fool.jpg"
quality = "Decent, not enough progression"
reading = "Finished"
authors = ["clarke"]
links = [
  { title = "royalroad", url = "https://www.royalroad.com/fiction/41618/mark-of-the-fool" },
]

[[book]]
title = "DIE. RESPAWN. REPEAT."
thumbnail = "https://www.royalroadcdn.com/public/covers-large/66643-die-respawn-repeat.jpg"
quality = "Decent, a bit bland"
reading = "Dropped, volume 4, chapter 8 (chapter 222)"
authors = ["silverlinings"]
links = [
  { title = "royalroad", url = "https://www.royalroad.com/fiction/66643/die-respawn-repeat" },
]

[[book]]
title = "System Breaker"
thumbnail = "https://www.royalroadcdn.com/public/covers-large/89249-system-breaker-xianxia-system-apocalypse.jpg"
quality = "Decent, MC is a bit immature"
reading = "Dropped, volume 2, chapter 55"
authors = ["ostensiblemammal"]
links = [
  { title = "royalroad", url = "https://www.royalroad.com/fiction/89249/system-breaker-xianxia-system-apocalypse-litrpg" },
]

[[book]]
title = "Reborn as a Demonic Tree"
thumbnail = "https://www.royalroadcdn.com/public/covers-large/62881-reborn-as-a-demonic-tree.jpg"
quality = "Ok, mediocre"
reading = "Dropped, volume 8, chapter 421"
authors = ["xkarnation"]
links = [
  { title = "royalroad", url = "https://www.royalroad.com/fiction/62881/reborn-as-a-demonic-tree" },
]

[[book]]
title = "Accel World"
thumbnail = "https://cdn.novelupdates.com/images/2023/08/Accel-World.jpg"
quality = "Bad, japanese slop"
reading = "Dropped at some point"
authors = ["kawahara-reki"]
links = [
  { title = "novelupdates", url = "https://www.novelupdates.com/series/accel-world/" },
]

[[book]]
title = "The Jester of Apocalypse"
thumbnail = "https://www.royalroadcdn.com/public/covers-large/62411-the-jester-of-apocalypse.jpg"
quality = "Ok, basic and a bit edgy"
reading = "Finished available chapters"
authors = ["robert-blaise"]
links = [
  { title = "royalroad", url = "https://www.royalroad.com/fiction/62411/the-jester-of-apocalypse" },
]

[[book]]
title = "Throne of Magical Arcana"
thumbnail = "https://cdn.novelupdates.com/images/2017/04/Throne-of-Magical-Arcana.jpg"
quality = "Decent, a bit mediocre"
reading = "Dropped near the end when the main plot ended"
authors = ["cuttlefish-that-loves-diving"]
links = [
  { title = "novelupdates", url = "https://www.novelupdates.com/series/throne-of-magical-arcana/" },
]

[[book]]
title = "The Charm of Soul Pets"
thumbnail = "https://cdn.novelupdates.com/images/2016/08/The-Charm-of-Soul-Pets-1.jpg"
quality = "Don't remember"
reading = "Dropped, chapter 42"
authors = ["chaos"]
links = [
  { title = "novelupdates", url = "https://www.novelupdates.com/series/the-charm-of-soul-pets/" },
]

[[book]]
title = "12 Miles Below"
thumbnail = "https://www.royalroadcdn.com/public/covers-large/42367-12-miles-below.jpg"
quality = "Decent"
reading = "Dropped at some point"
authors = ["mark-arrows"]
links = [
  { title = "royalroad", url = "https://www.royalroad.com/fiction/42367/12-miles-below" },
]

[[book]]
title = "Worm"
thumbnail = "https://parahumans.wordpress.com/wp-content/uploads/2011/06/cityscape2.jpg"
quality = "Decent"
reading = "Finished"
authors = ["wildbow"]
links = [{ title = "website", url = "https://parahumans.wordpress.com/" }]

[[book]]
title = "Full Murderhobo"
thumbnail = "https://i.gr-assets.com/images/S/compressed.photo.goodreads.com/books/1598478055i/55134991._SX120_.jpg"
quality = "Ok, a bit basic"
reading = "Finished, volume 3"
authors = ["dakota-krout"]
links = [
  { title = "goodreads", url = "https://www.goodreads.com/series/298351-full-murderhobo" },
]

[[book]]
title = "The Divine Dungeon"
thumbnail = "https://images-na.ssl-images-amazon.com/images/S/compressed.photo.goodreads.com/books/1476063034i/32509131.jpg"
quality = "Ok, a bit basic"
reading = "Finished"
authors = ["dakota-krout"]
links = [
  { title = "goodreads", url = "https://www.goodreads.com/series/192510-the-divine-dungeon" },
]

[[book]]
title = "SSS-Class Suicide Hunter"
thumbnail = "https://cdn.novelupdates.com/images/2021/05/SSSClass-Suicide-Hunter.jpg"
quality = "Ok, too much emotional bullshit"
reading = "Dropped at some point"
authors = ["sinnoa"]
links = [
  { title = "novelupdates", url = "https://www.novelupdates.com/series/sss-class-suicide-hunter" },
]

[[book]]
title = "Corpo Age"
thumbnail = "https://www.royalroadcdn.com/public/covers-large/75446-corpo-age-cyberpunk-progression-litrpg.jpg"
quality = "Ok, feels basic"
reading = "Dropped, volume 1, chapter 2"
authors = ["randombluecat"]
links = [
  { title = "royalroad", url = "https://www.royalroad.com/fiction/75446/corpo-age" },
]

[[book]]
title = "Shen Yin Wang Zuo"
alt_titles = ["Sealed Divine Throne", "神印王座"]
thumbnail = "https://cdn.novelupdates.com/images/2015/06/sywz.jpg"
quality = "Bad, too bland"
reading = "Dropped, chapter 101"
authors = ["tang-jia-san-shao"]
links = [
  { title = "novelupdates", url = "https://www.novelupdates.com/series/shen-yin-wang-zuo/" },
]

[[book]]
title = "Warlock of the Magus World"
thumbnail = "https://cdn.novelupdates.com/images/2022/05/Warlock-of-the-Magus-World_1653417756.jpg"
quality = "Bad, edgy slop, too much 'AI chip, do the thing'"
reading = "Dropped, chapter 58"
authors = ["the-plagiarist"]
links = [
  { title = "novelupdates", url = "https://www.novelupdates.com/series/warlock-of-the-magus-world/" },
]

[[book]]
title = "Perfect World"
thumbnail = "https://cdn.novelupdates.com/images/2018/03/perfectworld.jpeg"
quality = "Don't remember, children are boring"
reading = "Dropped, chapter 75"
authors = ["chen-dong"]
links = [
  { title = "novelupdates", url = "https://www.novelupdates.com/series/perfect-world/" },
]

[[book]]
title = "Trash of the Count’s Family"
thumbnail = "https://cdn.novelupdates.com/images/2022/10/Trash-of-the-Counts-Family.jpg"
quality = "Bad"
summary = "Korean slop, the same stuff happens over and over again, endless saving of useless garbage, humble bragging"
reading = "Dropped, chapter 215"
authors = ["yu-ryeo-han"]
links = [
  { title = "novelupdates", url = "https://www.novelupdates.com/series/trash-of-the-counts-family/" },
]

[[book]]
title = "Forty Millenniums of Cultivation"
alt_titles = ["Forty Thousand Years Of Cultivation", "修真四万年"]
thumbnail = "https://cdn.novelupdates.com/images/2017/03/Forty-Millenniums-of-Cultivation.jpg"
quality = "Ok"
summary = "Good worldbuilding, but too many empty exclamations and not enough substance"
reading = "Dropped, chapter 2935"
authors = ["the-enlightened-master-crouching-cow"]
links = [
  { title = "novelupdates", url = "https://www.novelupdates.com/series/forty-millenniums-of-cultivation/" },
]

[[book]]
title = "The Empty Box and Zeroth Maria"
alt_titles = ["Utsuro no Hako to Zero no Maria", "空ろの箱と零のマリア"]
thumbnail = "https://cdn.novelupdates.com/images/2023/04/Utsuro-no-Hako-to-Zero-no-Maria.jpg"
quality = "Decent?"
summary = "Don't remember"
reading = "Finished"
authors = ["mikage-eiji"]
links = [
  { title = "novelupdates", url = "https://www.novelupdates.com/series/utsuro-no-hako-to-zero-no-maria/" },
]

[[book]]
title = "Rune Seeker"
thumbnail = "https://www.royalroadcdn.com/public/covers-large/73095-rune-seeker-a-progression-fantasy-litrpg.jpg"
quality = "Ok"
summary = "Shallow"
reading = "Dropped, volume 2, chapter 12"
authors = ["clarke"]
links = [
  { title = "royalroad", url = "https://www.royalroad.com/fiction/73095/rune-seeker-a-progression-fantasy-litrpg-book" },
]

[[book]]
title = "Chrysalis"
thumbnail = "https://www.royalroadcdn.com/public/covers-full/22518-chrysalis.jpg"
quality = "Ok"
reading = "Dropped, C1654"
authors = ["rinoz"]
links = [
  { title = "royalroad", url = "https://www.royalroad.com/fiction/22518/chrysalis" },
]

[[book]]
title = "My House of Horrors"
alt_titles = ["我有一座冒险屋"]
thumbnail = "https://cdn.novelupdates.com/images/2024/09/My-House-of-Horrors.jpg"
quality = "Ok"
summary = "Repetitive"
reading = "Dropped at some point"
authors = ["can-fix-air-conditioners"]
links = [
  { title = "novelupdates", url = "https://www.novelupdates.com/series/my-house-of-horrors/" },
]

[[book]]
title = "The Spiritual Attainment of Minghe"
alt_titles = ["明和的精神境界"]
thumbnail = "https://cdn.novelupdates.com/images/2018/02/attain1.jpg"
quality = "Ok"
summary = "Shallow, bad translation"
reading = "Dropped, chapter 8"
authors = ["god-loves-the-world"]
links = [
  { title = "novelupdates", url = "https://www.novelupdates.com/series/the-spiritual-attainment-of-minghe/" },
]

[[book]]
title = "Unbound"
thumbnail = "https://www.royalroadcdn.com/public/covers-large/30321-unbound.jpg"
quality = "Ok"
summary = "Shallow"
reading = "Dropped, finisehd volume 3"
authors = ["necariin"]
links = [
  { title = "royalroad", url = "https://www.royalroad.com/fiction/30321/unbound" },
]

[[book]]
title = "The Stubborn Skill-Grinder In A Time Loop"
thumbnail = "https://www.royalroadcdn.com/public/covers-large/83294-the-stubborn-skill-grinder-in-a-time-loop.jpg"
quality = "Ok"
summary = "Shallow litrpg slop"
reading = "Dropped, chapter 44"
authors = ["x-rhoden-x"]
links = [
  { title = "royalroad", url = "https://www.royalroad.com/fiction/83294/the-stubborn-skill-grinder-in-a-time-loop" },
]

[[book]]
title = "I Shall Be Everlasting In the World of Immortals"
alt_titles = ["我在修仙界万古长青"]
thumbnail = "https://cdn.novelupdates.com/images/2024/08/I-Shall-Be-Everlasting-In-the-World-of-Immortals.jpg"
quality = "Ok"
summary = "Shallow"
reading = "Dropped, chapter 241"
authors = ["fast-food-restaurant"]
links = [
  { title = "novelupdates", url = "https://www.novelupdates.com/series/i-shall-be-everlasting-in-the-world-of-immortals/" },
]

[[book]]
title = "Solo Leveling"
alt_titles = ["我独自升级"]
thumbnail = "https://cdn.novelupdates.com/images/2019/01/Solo-Leveling.jpg"
quality = "Ok"
summary = "Shallow litrpg slop"
reading = "Dropped, chapter 52"
authors = ["chugong"]
links = [
  { title = "novelupdates", url = "https://www.novelupdates.com/series/solo-leveling/" },
]

[[book]]
title = "The Strongest System"
alt_titles = ["最强的系统"]
thumbnail = "https://cdn.novelupdates.com/images/2022/06/The-Strongest-System.jpg"
quality = "Ok"
summary = "Shallow"
reading = "Dropped, chapter 113"
authors = ["xin-feng"]
links = [
  { title = "novelupdates", url = "https://www.novelupdates.com/series/the-strongest-system/" },
]

[[book]]
title = "Cultivation Chat Group"
alt_titles = ["修真聊天群"]
thumbnail = "https://cdn.novelupdates.com/images/2017/10/Cultivation-Chat-Group.jpg"
quality = "Decent"
reading = "Finished"
authors = ["legend-of-the-paladin"]
links = [
  { title = "novelupdates", url = "https://www.novelupdates.com/series/cultivation-chat-group/" },
]

[[book]]
title = "Dao of the Bizarre Immortal"
alt_titles = ["道诡异仙"]
thumbnail = "https://cdn.novelupdates.com/images/2023/10/Mutated-Tao.jpg"
quality = "Decent"
reading = "Finished"
authors = ["foxtail-quill"]
links = [
  { title = "novelupdates", url = "https://www.novelupdates.com/series/dao-of-the-bizarre-immortal/" },
]

[[book]]
title = "Blood & Fur"
thumbnail = "https://www.royalroadcdn.com/public/covers-large/70234-blood-fur.jpg"
quality = "Good"
reading = "Finished"
authors = ["maxime-j-durand"]
links = [
  { title = "royalroad", url = "https://www.royalroad.com/fiction/70234/blood-fur" },
]

[[book]]
title = "The Perfect Run"
thumbnail = "https://www.royalroadcdn.com/public/covers-full/36735-the-perfect-run.jpg"
quality = "Decent"
reading = "Finished"
authors = ["maxime-j-durand"]
links = [
  { title = "royalroad", url = "https://www.royalroad.com/fiction/36735/the-perfect-run" },
]

[[book]]
title = "Dungeon Inspector"
thumbnail = "https://www.royalroadcdn.com/public/covers-large/63331-dungeon-inspector-book-2-complete.jpg"
quality = "Ok, mediocre"
reading = "Dropped, finished volume 1"
authors = ["flossindune"]
links = [
  { title = "royalroad", url = "https://www.royalroad.com/fiction/63331/dungeon-inspector-book-1-complete-book-2-starts" },
]

[[book]]
title = "Why Are the Talismans I Drawn Banned Again?!"
alt_titles = ["我画的符箓必被禁用"]
thumbnail = "https://cdn.novelupdates.com/images/2024/11/Why-are-the-Talismans-I-Drawn-Banned-Again.jpg"
quality = "Slop, rushed ending"
reading = "Finshed, chapter 258"
authors = ["quiet-support"]
links = [
  { title = "novelupdates", url = "https://www.novelupdates.com/series/why-are-the-talismans-i-drawn-banned-again/" },
]

[[book]]
title = "Versatile Mage"
alt_titles = ["全职法师"]
thumbnail = "https://cdn.novelupdates.com/images/2017/08/Versatile-Mage.jpg"
quality = "Slop"
reading = "Dropped, chapter 8"
authors = ["chaos"]
links = [
  { title = "novelupdates", url = "https://www.novelupdates.com/series/versatile-mage/" },
]

[[book]]
title = "1% Lifesteal"
thumbnail = "https://www.royalroadcdn.com/public/covers-large/72301-1-lifesteal.jpg"
quality = "Ok, boring protagonist"
reading = "Dropped, C128 (volume 2)"
authors = ["robert-blaise"]
links = [
  { title = "royalroad", url = "https://www.royalroad.com/fiction/72301/1-lifesteal" },
]

[[book]]
title = "Saving the school would have been easier as a cafeteria worker"
thumbnail = "https://www.royalroadcdn.com/public/covers-large/86874-saving-the-school-would-have-been-easier.jpg"
quality = "Decent"
reading = "Finished available (hiatus), chapter 90"
authors = ["cluelessrr"]
links = [
  { title = "royalroad", url = "https://www.royalroad.com/fiction/86874/saving-the-school-would-have-been-easier-as-a" },
]

[[book]]
title = "Theos"
thumbnail = "https://www.royalroadcdn.com/public/covers-large/64789-theos.jpg"
quality = "Decent"
reading = "Hiatus, B3C4"
authors = ["arthur-wordsmith"]
links = [
  { title = "royalroad", url = "https://www.royalroad.com/fiction/64789/theos" },
]

[[book]]
title = "The System is Abstract, Luckily, So Am I"
thumbnail = "https://cdn.novelupdates.com/images/2025/02/The-System-is-Abstract-Luckily-So-Am-I.png"
quality = "Slop"
reading = "Dropped, C311"
authors = ["pu-jie-tianxian"]
links = [
  { title = "novelupdates", url = "https://www.novelupdates.com/series/the-system-is-abstract-luckily-so-am-i/" },
]

[[book]]
title = "Kill the Sun"
thumbnail = "https://book-pic.webnovel.com/bookcover/27467949206850305?imageMogr2/thumbnail/180x|imageMogr2/quality/70!&imageId=1732809259404"
quality = "Decent"
reading = "Finished, C992"
authors = ["warmaisach"]
links = [
  { title = "webnovel", url = "https://m.webnovel.com/book/kill-the-sun_27467949206850305" },
]

[[book]]
title = "I Just Want to Slack Off in Cultivation"
thumbnail = "https://cdn.novelupdates.com/images/2023/10/I-just-want-to-slack-off-in-cultivation.jpg"
alt_titles = ["我只想安静的做个苟道中人"]
quality = "Slop"
reading = "Dropped, C54"
authors = ["exploding-small-latte"]
links = [
  { title = "novelupdates", url = "https://www.novelupdates.com/series/__trashed-43/" },
]

[[book]]
title = "New Life As A Max Level Archmage"
thumbnail = "https://www.royalroadcdn.com/public/covers-large/118891-new-life-as-a-max-level-archmage.jpg"
quality = "Ok"
reading = "Dropped, C44"
authors = ["arcanecadence"]
links = [
  { title = "royalroad", url = "https://www.royalroad.com/fiction/118891/new-life-as-a-max-level-archmage" },
]

[[book]]
title = "Only at the Mahayana Stage Does the Reversal System Appear"
thumbnail = "https://cdn.novelupdates.com/images/2025/02/Only-at-the-Mahayana-Stage-Does-the-Reversal-System-Appear.jpeg"
quality = "Ok, bad translation"
reading = "Dropped, C164"
authors = ["the-whitest-crow"]
links = [
  { title = "novelupdates", url = "https://www.novelupdates.com/series/only-at-the-mahayana-stage-does-the-reversal-system-appear/" },
]

[[book]]
title = "Etherious"
thumbnail = "https://www.royalroadcdn.com/public/covers-large/52083-etherious--a-litrpg-story-book-2-stubbing.jpg"
quality = "Ok"
reading = "Dropped, finished V4"
authors = ["emes"]
links = [
  { title = "royalroad", url = "https://www.royalroad.com/fiction/52083/etherious--a-litrpg-story" },
]

[[book]]
title = "The Shards of Etherious"
thumbnail = "https://images-na.ssl-images-amazon.com/images/S/compressed.photo.goodreads.com/books/1611195421i/56769296.jpg"
quality = "Bad"
reading = "Dropped, V1C9"
authors = ["colin-j-d-crooks"]
links = [
  { title = "goodreads", url = "https://www.goodreads.com/book/show/56769296-arisen" },
]

[[book]]
title = "I Became The Necromancer Of The Academy"
thumbnail = "https://cdn.novelupdates.com/images/2024/03/I-Became-The-Necromancer-Of-The-Academy.jpg"
quality = "Slop"
reading = "Dropped, C37"
authors = ["_172"]
links = [
  { title = "novelupdates", url = "https://www.novelupdates.com/series/i-became-the-necromancer-of-the-academy/" },
]

[[book]]
title = "Dear Spellbook"
thumbnail = "https://www.royalroadcdn.com/public/covers-large/49881-dear-spellbook.jpg"
quality = "Ok"
reading = "Dropped, V3C13"
authors = ["tk523"]
links = [
  { title = "royalroad", url = "https://www.royalroad.com/fiction/49881/dear-spellbook" },
]

[[book]]
title = "All the Dust that Falls"
thumbnail = "https://www.royalroadcdn.com/public/covers-large/60292-all-the-dust-that-falls.jpg"
quality = "Ok"
reading = "Finished, V4"
authors = ["zaifyr"]
links = [
  { title = "royalroad", url = "https://www.royalroad.com/fiction/60292/all-the-dust-that-falls" },
]

[[book]]
title = "Nightmare Realm Summoner"
thumbnail = "https://www.royalroadcdn.com/public/covers-large/89034-nightmare-realm-summoner-stubbing-in-1-week.jpg"
quality = "Ok"
reading = "Dropped, C278"
authors = ["actus"]
links = [
  { title = "royalroad", url = "https://www.royalroad.com/fiction/89034/nightmare-realm-summoner" },
]

[[book]]
title = "Mage Tank"
thumbnail = "https://www.royalroadcdn.com/public/covers-large/mage-tank-aacalggbnhq.jpg"
quality = "Slop"
reading = "Dropped, V1C50"
authors = ["cornman"]
links = [
  { title = "royalroad", url = "https://www.royalroad.com/fiction/76463/mage-tank" },
]

[[book]]
title = "Salvage System"
thumbnail = "https://b2419162.smushcdn.com/2419162/wp-content/uploads/2025/09/81bMdsFQzCL._SL1500_-1.jpg?lossy=2&strip=1&webp=1"
quality = "Slop"
reading = "Dropped, V1C11"
authors = ["nicholas_sansbury_smith"]
links = [
  { title = "aethonbooks", url = "https://aethonbooks.com/book/salvage-system/" },
]

[[book]]
title = "Shrouded Seascape"
alt_titles = ["诡秘地海"]
thumbnail = "./shrouded_seascape.jpg"
quality = "Good"
reading = "Finished, C1149"
authors = ["foxtail-quill"]
links = [
  { title = "novelupdates", url = "https://www.novelupdates.com/series/shrouded-seascape/" },
]

[[book]]
title = "Diary of a Dead Wizard"
alt_titles = ["死亡巫师日记"]
thumbnail = "./diary_of_a_dead_wizard.jpeg"
quality = "Good"
reading = "Finished, C1037"
authors = ["jin-nai"]
links = [
  { title = "novelupdates", url = "https://www.novelupdates.com/series/diary-of-a-dead-wizard/" },
]

[[book]]
title = "The Crazy Knight’s Age of the Universe"
alt_titles = ["疯骑士的宇宙时代"]
thumbnail = "https://img.wtr-lab.com/cdn/series/V59LQYUDTF-TfhZh1GsBO6WG1VvW3p6MTAOqKYwFyFA.jpeg"
quality = "Ok, lost the vibe of the first book"
reading = "Dropped, C167"
authors = ["angry-squirrel"]
links = [
  { title = "wtr-lab", url = "https://wtr-lab.com/en/novel/21563/the-crazy-knights-age-of-the-universe/" },
]

[[book]]
title = "Are You Even Human"
thumbnail = "https://www.royalroadcdn.com/public/covers-large/are-you-even-human-aabawaw0tbu.jpg"
quality = "Decent"
reading = "Dropped, C54"
authors = ["thundamoo"]
links = [
  { title = "royalroad", url = "https://www.royalroad.com/fiction/92549/are-you-even-human" },
]

[[book]]
title = "A Gamer's Guide To Beating The Tutorial"
thumbnail = "https://www.royalroadcdn.com/public/covers-large/73205-a-gamers-guide-to-beating-the-tutorial.jpg"
quality = "Ok"
reading = "Dropped, C352"
authors = ["palt"]
links = [
  { title = "royalroad", url = "https://www.royalroad.com/fiction/73205/a-gamers-guide-to-beating-the-tutorial" },
]

[[book]]
title = "Unsong"
thumbnail = "https://m.media-amazon.com/images/S/compressed.photo.goodreads.com/books/1632785897i/28589297.jpg"
quality = "Good, disgusting ending"
reading = "Finished"
authors = ["scott_alexander"]
links = [{ title = "site", url = "https://unsongbook.com/" }]

[[book]]
title = "Young Master's PoV: Woke Up As A Villain In A Game One Day"
thumbnail = "./young_masters_pov_woke_up_as_a_villain_in_a_game_one_day.jpg"
quality = "Ok"
reading = "Dropped, C293"
authors = ["the-one-who-was"]
links = [
  { title = "webnovel", url = "https://www.webnovel.com/book/young-master's-pov-woke-up-as-a-villain-in-a-game-one-day_30581672200350205" },
]

[[book]]
title = "Throne Hunters"
thumbnail = "https://www.royalroadcdn.com/public/covers-large/85769-throne-hunters-dungeon-focused-progression.jpg"
quality = "Ok"
reading = "Dropped, V1C44"
authors = ["phill_tucker"]
links = [
  { title = "royalroad", url = "https://www.royalroad.com/fiction/85769/throne-hunters-dungeon-focused-progression-fantasystubbed" },
]

[[book]]
title = "For the Glory of Rome"
thumbnail = "https://www.royalroadcdn.com/public/covers-large/104561-for-the-glory-of-rome-chronicles-of-an.jpg"
quality = "Ok"
reading = "Dropped, V3C12"
authors = ["zaifyr"]
links = [
  { title = "royalroad", url = "https://www.royalroad.com/fiction/104561/for-the-glory-of-rome-chronicles-of-an-isekaid" },
]

[[book]]
title = "Magical Girl Gunslinger"
thumbnail = "https://www.royalroadcdn.com/public/covers-large/48402-magical-girl-gunslinger.jpg?time=1693597835"
quality = "Ok"
reading = "Finished available (hiatus), C37"
authors = ["mikasane"]
links = [
  { title = "royalroad", url = "https://www.royalroad.com/fiction/48402/magical-girl-gunslinger" },
]

[[book]]
title = "This Magical Girl is Mine"
thumbnail = "https://www.royalroadcdn.com/public/covers-large/this-magical-girl-is-mine-aacauifwgrc.jpg"
quality = "Ok"
reading = "Dropped, V5C1.2"
authors = ["voravora"]
links = [
  { title = "royalroad", url = "https://www.royalroad.com/fiction/118714/this-magical-girl-is-mine" },
]

[[book]]
title = "Magical Girl Mechanical Heart"
thumbnail = "https://www.royalroadcdn.com/public/covers-large/magical-girl-mechanical-heart-aadaukdlry.jpg"
quality = "Ok"
reading = "Dropped, C52"
authors = ["thundamoo"]
links = [
  { title = "royalroad", url = "https://www.royalroad.com/fiction/106438/magical-girl-mechanical-heart" },
]

[[book]]
title = "Grotesqueries of the Old Domain"
alt_titles = ["旧域怪诞", "The Grotesque Old Domain"]
thumbnail = "./grotesqueries_of_the_old_domain.jpg"
quality = "Good?"
reading = "Dropped, C268"
authors = ["foxtail-quill"]
links = [
  { title = "novelupdates", url = "https://www.novelupdates.com/series/grotesqueries-of-the-old-domain/" },
]

[[book]]
title = "The Hundred Reigns"
thumbnail = "https://www.royalroadcdn.com/public/covers-large/the-hundred-reigns-timeloop-litrpg-aabay6rm6bc.jpg"
quality = "Ok"
reading = "Dropped, C183"
authors = ["maxime-j-durand"]
links = [
  { title = "royalroad", url = "https://www.royalroad.com/fiction/139212/the-hundred-reigns-timeloop-litrpg" },
]

[[book]]
title = "Afterlife 2.0"
thumbnail = "https://www.royalroadcdn.com/public/covers-large/111416-afterlife-20-litrpg-in-hell.jpg"
quality = "Decent"
reading = "Finished available (hiatus), C86"
authors = ["quickduckling"]
links = [
  { title = "royalroad", url = "https://www.royalroad.com/fiction/111416/afterlife-20-litrpg-in-hell" },
]

[[book]]
title = "Mask of Humanity"
thumbnail = "https://www.royalroadcdn.com/public/covers-large/80031-mask-of-humanity-grimdark-cultivation-litrpg.jpg"
quality = "Decent"
reading = "Dropped, C366"
authors = ["slaughterbot"]
links = [
  { title = "royalroad", url = "https://www.royalroad.com/fiction/80031/mask-of-humanity" },
]

[[book]]
title = "Changeling"
thumbnail = "https://www.royalroadcdn.com/public/covers-large/75345-changeling.jpg"
quality = "Decent"
reading = "Dropped, C103"
authors = ["mecanimus"]
links = [
  { title = "royalroad", url = "https://www.royalroad.com/fiction/75345/changeling" },
]

[[book]]
title = "The Tower of Infinite Evil"
thumbnail = "https://www.royalroadcdn.com/public/covers-large/122142-the-tower-of-infinite-evil-a-litrpg-horror.jpg"
quality = "Decent"
reading = "Dropped, C127"
authors = ["lit-homunculus"]
links = [
  { title = "royalroad", url = "https://www.royalroad.com/fiction/122142/the-tower-of-infinite-evil-a-litrpg-horror-comedy" },
]

[[book]]
title = "Pale Lights"
thumbnail = "https://www.royalroadcdn.com/public/covers-large/65058-pale-lights.jpg?time=1745679158"
quality = "Good"
reading = "Dropped, V3C37"
authors = ["erraticerrata"]
links = [
  { title = "royalroad", url = "https://www.royalroad.com/fiction/65058/pale-lights" },
]

[[book]]
title = "Shadow Slave"
thumbnail = "./shadow_slave.jpg"
quality = "Decent"
reading = "Dropped, chapter 2777"
authors = ["guilty-three"]
links = [
  { title = "webnovel", url = "https://www.webnovel.com/book/shadow-slave_22196546206090805" },
]

[[book]]
title = "I Cultivate Legally, Why Call Me a Demon?"
alt_titles = ["我合法修仙,凭什么叫我魔头?"]
thumbnail = "https://cdn.novelupdates.com/images/2025/09/I-Cultivate-Legally-Why-Call-Me-a-Demon.jpg"
quality = "Slop"
reading = "Dropped, C89"
authors = ["一辈子小说家"]
links = [
  { title = "novelupdates", url = "https://www.novelupdates.com/series/i-cultivate-legally-why-call-me-a-demon/" },
]

[[book]]
title = "I Am a Demon Cultivator, Not a Conscientious Capitalist"
alt_titles = ["我是魔修,不是良心资本家"]
thumbnail = "https://cdn.novelupdates.com/images/2025/09/I-Am-a-Demon-Cultivator-Not-a-Conscientious-Capitalist.jpg"
quality = "Slop"
reading = "Dropped, C19"
authors = ["窗边的鸽子"]
links = [
  { title = "novelupdates", url = "https://www.novelupdates.com/series/i-am-a-demon-cultivator-not-a-conscientious-capitalist/" },
]

[[book]]
title = "Shan He Ji"
alt_titles = ["山河稷", "Mountains, Rivers, and the Grain God"]
thumbnail = "https://cdn.novelupdates.com/images/2025/07/Shan-He-Ji.jpg"
quality = "Ok"
reading = "Dropped, C27"
authors = ["姬叉"]
links = [
  { title = "novelupdates", url = "https://www.novelupdates.com/series/shan-he-ji/" },
]

[[book]]
title = "Staring directly at the ancient gods for a whole year"
alt_titles = ["直视古神一整年"]
thumbnail = "https://img.wtr-lab.com/dSO3hnkuy2rqyLSKcLj1gjd_4jLT-ZU_4KetR6Aj99Y/rs:fit:344:0:0/q:80/g:no/czM6Ly93dHJpbWcvc2VyaWVzLzFFdXZOQ0EyS2ZsT2NmUlczYVlQZUEud2VicA"
quality = "Slop"
reading = "Dropped, C100"
authors = ["三藏的左轮"]
links = [
  { title = "wtrlab", url = "https://wtr-lab.com/en/novel/5006/staring-directly-at-the-ancient-gods-for-a-whole-year" },
]

[[book]]
title = "Mysterious Revival"
thumbnail = "https://book-pic.webnovel.com/bookcover/19115759305319405?imageMogr2/thumbnail/180x|imageMogr2/format/webp|imageMogr2/quality/70!&imageId=1721123894271"
quality = "Ok"
reading = "Dropped, C54"
authors = ["offering-flowers-before-the-buddha"]
links = [
  { title = "webnovel", url = "https://m.webnovel.com/book/mysterious-revival_19115759305319405" },
]

[[book]]
title = "Explorer of Edregon"
thumbnail = "https://www.royalroadcdn.com/public/covers-large/100744-explorer-of-edregon.jpg?time=1763178307"
quality = "Ok, bland"
reading = "Dropped, C20"
authors = ["wizardly_dude"]
links = [
  { title = "royalroad", url = "https://www.royalroad.com/fiction/100744/explorer-of-edregon-book-5-complete" },
]

[[book]]
title = "No More Heroes"
thumbnail = "https://www.royalroadcdn.com/public/covers-large/89019-no-more-heroes-superhero-litrpg.jpg?time=1721951587"
quality = "Ok, boring"
reading = "Dropped, C22"
authors = ["lokithequick"]
links = [
  { title = "royalroad", url = "https://www.royalroad.com/fiction/89019/no-more-heroes-superhero-litrpg" },
]

[[book]]
title = "DIE TRYING"
thumbnail = "https://www.royalroadcdn.com/public/covers-large/124235-die-trying-a-roguelite-extraction-litrpg.jpg?time=1759079259"
quality = "Ok, bland"
reading = "Dropped, C47"
authors = ["markarrows"]
links = [
  { title = "royalroad", url = "https://www.royalroad.com/fiction/124235/die-trying-a-roguelite-extraction-litrpg" },
]

[[book]]
title = "Shadow Clone Sorcery"
thumbnail = "https://www.royalroadcdn.com/public/covers-large/117529-shadow-clone-sorcery.jpg?time=1748092724"
quality = "Ok, bland"
reading = "Dropped, C110"
authors = ["jpwrites"]
links = [
  { title = "royalroad", url = "https://www.royalroad.com/fiction/117529/shadow-clone-sorcery-book-1-complete" },
]

[[book]]
title = "To Walk The Red Path "
thumbnail = "https://www.royalroadcdn.com/public/covers-large/to-walk-the-red-path-a-story-of-dungeon-crawling.jpg?time=1741212789"
quality = "Ok, bland"
reading = "Dropped, F6P2C10"
authors = ["cashen"]
links = [
  { title = "royalroad", url = "https://www.royalroad.com/fiction/107964/to-walk-the-red-path-a-story-of-dungeon-crawling" },
]

[[book]]
title = "[Grave Robber]"
thumbnail = "https://www.royalroadcdn.com/public/covers-large/178197-grave-robber.jpg?time=1783922076"
quality = "Ok, mediorce"
reading = "Dropped, C6"
authors = ["disheveledvagabond"]
links = [
  { title = "royalroad", url = "https://www.royalroad.com/fiction/178197/grave-robber" },
]

[[book]]
title = "Throne of Time"
thumbnail = "https://www.royalroadcdn.com/public/covers-large/throne-of-time-aabavht89hg.jpg?time=1780498434"
quality = "Ok, bland"
reading = "Dropped, C23"
authors = ["cognosticon"]
links = [
  { title = "royalroad", url = "https://www.royalroad.com/fiction/172653/throne-of-time-magical-academy-time-loop-mystery" },
]

[[book]]
title = "Path of the Deathless"
thumbnail = "https://www.royalroadcdn.com/public/covers-large/122502-path-of-the-deathless-book-4-completed.jpg"
quality = "Decent"
reading = "Dropped, C333"
authors = ["ostensiblemammal"]
links = [
  { title = "royalroad", url = "https://www.royalroad.com/fiction/122502/path-of-the-deathless-book-4-completed" },
]

[[book]]
title = "The Legend of William Oh"
thumbnail = "https://www.royalroadcdn.com/public/covers-large/the-legend-of-william-oh-aadavnw8qxu.jpg"
quality = "Decent"
reading = "Dropped, C264"
authors = ["macronomicon"]
links = [
  { title = "royalroad", url = "https://www.royalroad.com/fiction/92144/the-legend-of-william-oh" },
]

[[book]]
title = "Re:Cursed"
thumbnail = "https://www.royalroadcdn.com/public/covers-large/104556-recursed.jpg?time=1763017950"
quality = "Decent"
reading = "Dropped, C176"
authors = ["joroboros"]
links = [
  { title = "royalroad", url = "https://www.royalroad.com/fiction/104556/recursed" },
]

[[book]]
title = "Reforged from Ruin"
thumbnail = "https://www.royalroadcdn.com/public/covers-large/78756-reforged-from-ruin-eldritch-xianxia-cultivation.jpg"
quality = "Decent"
reading = "Dropped, C390"
authors = ["silv3rtongue"]
links = [
  { title = "royalroad", url = "https://www.royalroad.com/fiction/78756/reforged-from-ruin-eldritch-xianxia-cultivation" },
]

[[book]]
title = "Hell Difficulty Tutorial"
thumbnail = "https://www.royalroadcdn.com/public/covers-large/64916-hell-difficulty-tutorial.jpg"
quality = "Decent"
reading = "Dropped, C841"
authors = ["cerim"]
links = [
  { title = "royalroad", url = "https://www.royalroad.com/fiction/64916/hell-difficulty-tutorial" },
]

[[book]]
title = "Book Of The Dead"
thumbnail = "https://www.royalroadcdn.com/public/covers-full/47038-book-of-the-dead.jpg"
quality = "Decent"
reading = "Dropped, B6C8"
authors = ["rinoz"]
links = [
  { title = "royalroad", url = "https://www.royalroad.com/fiction/47038/book-of-the-dead" },
]

[[book]]
title = "The Mirror Legacy"
thumbnail = "https://cdn.novelupdates.com/images/2024/06/The-Mirror-Legacy.jpg"
alt_titles = ["玄鉴仙族"]
quality = "Decent?"
reading = "Dropped, C10"
authors = ["季越人"]
links = [
  { title = "novelupdates", url = "https://www.novelupdates.com/series/the-mirror-legacy/" },
]

[[book]]
title = "Corpse Retriever"
alt_titles = ["捞尸人"]
thumbnail = "https://cdn.novelupdates.com/images/2025/04/Corpse-Retriever.jpg"
quality = "Decent?"
reading = "Dropped, C26"
authors = ["纯洁滴小龙"]
links = [
  { title = "novelupdates", url = "https://www.novelupdates.com/series/corpse-retriever/" },
]

[[book]]
title = "How Can You Cultivate Immortality Without Money?"
alt_titles = ["没钱修什么仙?", "No Money to Cultivate Immortality?"]
thumbnail = "https://cdn.novelupdates.com/images/2024/11/No-Money-to-Cultivate-Immortality.png"
quality = "Decent"
reading = "Dropped, C827 (C815)"
authors = ["熊狼狗"]
links = [
  { title = "novelupdates", url = "https://www.novelupdates.com/series/no-money-to-cultivate-immortality/" },
]

[[book]]
title = "Surviving as a Talent in the Primordial Saint Sect"
alt_titles = [
  "苟在初圣魔门当人材",
  "Lying Low as the First Saint Demonic Sect’s ‘Top Talent’",
]
thumbnail = "./struggling_to_survive_with_regression_power_in_the_primordial_saint_sect.png"
quality = "Decent"
reading = "Finished, C1537 (C1441)"
authors = ["crane-by-the-moonlit-pond"]
links = [
  { title = "novelupdates", url = "https://www.novelupdates.com/series/struggling-to-survive-with-regression-power-in-the-primordial-saint-sect/" },
]

[[book]]
title = "Girls' Last Tour"
alt_titles = ["少女終末旅行"]
quality = "Good"
reading = "Finished, V6C43.6"
authors = ["tsukumizu"]
links = [
  { title = "wikipedia", url = "https://en.wikipedia.org/wiki/Girls%27_Last_Tour" },
]

[[book]]
title = "Sky Pride"
thumbnail = "https://www.royalroadcdn.com/public/covers-large/107917-sky-pride.jpg"
quality = "Good"
reading = "Dropped, B6C25"
authors = ["warby-picus"]
links = [
  { title = "royalroad", url = "https://www.royalroad.com/fiction/107917/sky-pride" },
]
[author.mao-ni]
name = "Mao Ni"
alt_names = ["猫腻"]

[author.gu-zhen-ren]
name = "Gu Zhen Ren"
alt_names = ["蛊真人"]

[author.angry-squid]
name = "Angry Squid"
alt_names = ["愤怒的乌贼"]

[author.angry-squirrel]
name = "Angry Squirrel"
alt_names = ["愤怒的松鼠"]

[author.golden-jasmine]
name = "Golden Jasmine"
alt_names = ["金色茉莉花"]

[author.cuttlefish-that-loves-diving]
name = "Cuttlefish That Loves Diving"
alt_names = ["爱潜水的乌贼"]

[author.er-gen]
name = "Er Gen"
alt_names = ["耳根"]
links = [
  { title = "novelupdates", url = "https://www.novelupdates.com/nauthor/er-gen/" },
]

[author.fang-xiang]
name = "Fang Xiang"
alt_names = ["方想"]

[author.chaos]
name = "Chaos"
alt_names = ["乱"]

[author.tang-jia-san-shao]
name = "Tang Jia San Shao"
alt_names = ["唐家三少"]

[author.can-fix-air-conditioners]
name = "Can Fix Air-Conditioners"
alt_names = ["我会修空调"]

[author.thefirstdefier]
name = "TheFirstDefier"

[author.kirill-klevanski]
name = "Kirill Klevanski"

[author.ostensible-mammal]
name = "OstensibleMammal"
links = [
  { title = "royalroad", url = "https://www.royalroad.com/profile/293473" },
]

[author.rinoz]
name = "RinoZ"
links = [
  { title = "royalroad", url = "https://www.royalroad.com/profile/97247" },
]

[author.guilty-three]
name = "Guiltythree"

[author.uraniumphoenix]
name = "UraniumPhoenix"

[author.seersucker]
name = "seersucker"

[author.azalea-ellis]
name = "Azalea Ellis"

[author.doctorhepa]
name = "DoctorHepa"

[author.casualfarmer]
name = "Casualfarmer"

[author.cerim]
name = "Cerim"

[author.actus]
name = "Actus"

[author.clarke]
name = "J.M. Clarke"
alt_names = ["U Juggernaut"]

[author.thundamoo]
name = "Thundamoo"

[author.strungbound]
name = "Strungbound"

[author.mecanimus]
name = "Mecanimus"

[author.turtleme]
name = "TurtleMe"

[author.dads-bedtime-stories]
name = "Dads Bedtime Stories"

[author.chirolu]
name = "Chirolu"

[author.silverlinings]
name = "SilverLinings"

[author.xkarnation]
name = "XKARNATION"

[author.kawahara-reki]
name = "Kawahara Reki"

[author.robert-blaise]
name = "Robert Blaise"

[author.mark-arrows]
name = "Mark Arrows"

[author.wildbow]
name = "Wildbow"

[author.dakota-krout]
name = "Dakota Krout"

[author.sinnoa]
name = "Sinnoa"

[author.randombluecat]
name = "RandomBlueCat"

[author.the-plagiarist]
name = "The Plagiarist"

[author.chen-dong]
name = "Chen Dong"
alt_names = ["辰东"]

[author.yu-ryeo-han]
name = "Yu Ryeo Han"
alt_names = ["유려한"]

[author.the-enlightened-master-crouching-cow]
name = "The Enlightened Master Crouching Cow"
alt_names = ["卧牛真人"]

[author.mikage-eiji]
name = "Mikage Eiji"

[author.nocturnal-stranger]
name = "Nocturnal Stranger"
alt_names = ["厄夜怪客"]

[author.ya-boy]
name = "Ya Boy"
links = [
  { title = "royalroad", url = "https://www.royalroad.com/profile/202632" },
]

[author.god-loves-the-world]
name = "God Loves The World"
alt_names = ["神仙爱凡尘"]

[author.necariin]
name = "Necariin"
links = [
  { title = "royalroad", url = "https://www.royalroad.com/profile/122394" },
]

[author.x-rhoden-x]
name = "X-RHODEN-X"

[author.fast-food-restaurant]
name = "Fast Food Restaurant"
alt_names = ["快餐店"]

[author.chugong]
name = "Chugong"
alt_names = ["추공"]

[author.xin-feng]
name = "Xin Feng"
alt_names = ["新丰"]

[author.legend-of-the-paladin]
name = "Legend of the Paladin"
alt_names = ["圣骑士的传说"]

[author.foxtail-quill]
name = "Foxtail Quill"
alt_names = ["狐尾的笔"]
links = [
  { title = "novelupdates", url = "https://www.novelupdates.com/nauthor/foxtail-quill/" },
]

[author.maxime-j-durand]
name = "Maxime J. Durand"
links = [
  { title = "royalroad", url = "https://www.royalroad.com/profile/107213" },
]

[author.jin-nai]
name = "Jin Nai"
alt_names = ["今奈"]
links = [
  { title = "novelupdates", url = "https://www.novelupdates.com/nauthor/jin-nai/" },
]

[author.warby-picus]
name = "Warby Picus"
links = [
  { title = "royalroad", url = "https://www.royalroad.com/profile/261544" },
]

[author.flossindune]
name = "Flossindune"
links = [
  { title = "royalorad", url = "https://www.royalroad.com/profile/299461" },
]

[author.quiet-support]
name = "Quiet Support"
alt_names = ["安静捧场"]
links = [
  { title = "novelupdates", url = "https://www.novelupdates.com/nauthor/quiet-support/" },
]

[author.cluelessrr]
name = "CluelessRR"
links = [
  { title = "royalroad", url = "https://www.royalroad.com/profile/471901" },
]

[author.arthur-wordsmith]
name = "Arthur Wordsmith"
links = [
  { title = "royalroad", url = "https://www.royalroad.com/profile/323423" },
]

[author.pu-jie-tianxian]
name = "Pū jiē tiānxiàn"
alt_names = ["扑街天线"]
links = [
  { title = "novelupdates", url = "https://www.novelupdates.com/nauthor/%e6%89%91%e8%a1%97%e5%a4%a9%e7%ba%bf/" },
]

[author.warmaisach]
name = "Warmaisach"
links = [
  { title = "webnovel", url = "https://m.webnovel.com/profile/3286855836" },
]

[author.exploding-small-latte]
name = "Exploding Small Latte"
alt_names = ["爆炸小拿铁"]
links = [
  { title = "novelupdates", url = "https://www.novelupdates.com/nauthor/exploding-small-latte/" },
]

[author.arcanecadence]
name = "ArcaneCadence"
links = [
  { title = "royalroad", url = "https://www.royalroad.com/profile/729989" },
]

[author.the-whitest-crow]
name = "The Whitest Crow"
alt_names = ["最白的乌鸦"]
links = [
  { title = "novelupdates", url = "https://www.novelupdates.com/nauthor/%e6%9c%80%e7%99%bd%e7%9a%84%e4%b9%8c%e9%b8%a6/" },
]

[author.emes]
name = "EmEs"
links = [
  { title = "royalroad", url = "https://www.royalroad.com/profile/235726" },
]

[author.colin-j-d-crooks]
name = "Colin J.D. Crooks"
links = [
  { title = "goodreads", url = "https://www.goodreads.com/author/show/21106941.Colin_J_D_Crooks" },
]

[author._172]
name = "_172"
links = [
  { title = "novelupdates", url = "https://www.novelupdates.com/nauthor/_172/" },
]

[author.tk523]
name = "TK523"
links = [
  { title = "royalroad", url = "https://www.royalroad.com/profile/112902" },
]

[author.zaifyr]
name = "zaifyr"
links = [
  { title = "royalroad", url = "https://www.royalroad.com/profile/285838" },
]

[author.cornman]
name = "Cornman"
links = [
  { title = "royalroad", url = "https://www.royalroad.com/profile/394190" },
]

[author.the-one-who-was]
name = "The_One_Who_Was"
links = [
  { title = "webnovel", url = "https://www.webnovel.com/profile/4324450853" },
]

[author.lit-homunculus]
name = "Lit Homunculus"
links = [
  { title = "royalroad", url = "https://www.royalroad.com/profile/56125" },
]

[author.macronomicon]
name = "Macronomicon"
links = [
  { title = "royalroad", url = "https://www.royalroad.com/profile/100060" },
]

[author.crane-by-the-moonlit-pond]
name = "Crane by the Moonlit Pond"
alt_names = ["鹤守月满池"]
links = [
  { title = "novelupdates", url = "https://www.novelupdates.com/nauthor/crane-by-the-moonlit-pond/" },
]

[author.nicholas_sansbury_smith]
name = "Nicholas Sansbury Smith"
links = [
  { title = "aethonbooks", url = "https://aethonbooks.com/book-author/nicholas-sansbury-smith/" },
]

[author.scott_alexander]
name = "Scott Alexander"
links = [
  { title = "goodreads", url = "https://www.goodreads.com/author/show/10866248.Scott_Alexander" },
]

[author.erraticerrata]
name = "ErraticErrata"
links = [
  { title = "royalroad", url = "https://www.royalroad.com/profile/21586" },
]

[authors.palt]
name = "Palt"
links = [
  { title = "royalroad", url = "https://www.royalroad.com/profile/35937" },
]

[author.phill_tucker]
name = "Phill Tucker"
links = [
  { title = "royalroad", url = "https://www.royalroad.com/profile/73941" },
]

[author.slaughterbot]
name = "SlaughterBot"
links = [
  { title = "royalroad", url = "https://www.royalroad.com/profile/413099" },
]

[author.mikasane]
name = "Mikasane"
links = [
  { title = "royalroad", url = "https://www.royalroad.com/profile/244859" },
]

[author.voravora]
name = "VoraVora"
links = [
  { title = "royalroad", url = "https://www.royalroad.com/profile/236517" },
]

[author.quickduckling]
name = "QuickDuckling"
links = [
  { title = "royalroad", url = "https://www.royalroad.com/profile/472328" },
]

[author."一辈子小说家"]
name = "一辈子小说家"
links = [
  { title = "novelupdates", url = "https://www.novelupdates.com/nauthor/%e4%b8%80%e8%be%88%e5%ad%90%e5%b0%8f%e8%af%b4%e5%ae%b6/" },
]

[author."姬叉"]
name = "姬叉"
links = [
  { title = "novelupdates", url = "https://www.novelupdates.com/nauthor/%e5%a7%ac%e5%8f%89/" },
]

[author."窗边的鸽子"]
name = "窗边的鸽子"
links = [
  { title = "novelupdates", url = "https://www.novelupdates.com/nauthor/%e7%aa%97%e8%be%b9%e7%9a%84%e9%b8%bd%e5%ad%90/" },
]

[author."熊狼狗"]
name = "熊狼狗"
links = [
  { title = "novelupdates", url = "https://www.novelupdates.com/nauthor/%e7%86%8a%e7%8b%bc%e7%8b%97/" },
]

[author.joroboros]
name = "Joroboros"
links = [
  { title = "royalroad", url = "https://www.royalroad.com/profile/115230" },
]

[author.silv3rtongue]
name = "Silv3rtongue"
links = [
  { title = "royalroad", url = "https://www.royalroad.com/profile/418109" },
]

[author."纯洁滴小龙"]
name = "纯洁滴小龙"
links = [
  { title = "novelupdates", url = "https://www.novelupdates.com/nauthor/%e7%ba%af%e6%b4%81%e6%bb%b4%e5%b0%8f%e9%be%99/" },
]

[author."三藏的左轮"]
name = "三藏的左轮"
links = [
  { title = "wtrlab", url = "https://wtr-lab.com/en/author/%E4%B8%89%E8%97%8F%E7%9A%84%E5%B7%A6%E8%BD%AE" },
]

[author.offering-flowers-before-the-buddha]
name = "Offering flowers before the Buddha"
links = []

[author."季越人"]
name = "季越人"
links = [
  { title = "novelupdates", url = "https://www.novelupdates.com/nauthor/%e5%ad%a3%e8%b6%8a%e4%ba%ba/" },
]

[author.tsukumizu]
name = "Tsukumizu"
alt_names = ["つくみず"]
links = [
  { title = "wikipedia", url = "https://en.wikipedia.org/wiki/Tsukumizu" },
]

[author.wizardly_dude]
name = "Wizardly Dude"
links = [
  { title = "royalroad", url = "https://www.royalroad.com/profile/559659" },
]

[author.lokithequick]
name = "LokiTheQuick"
links = [
  { title = "royalroad", url = "https://www.royalroad.com/profile/456668" },
]

[author.markarrows]
name = "Mark Arrows"
links = [
  { title = "royalroad", url = "https://www.royalroad.com/profile/150899" },
]

[author.jpwrites]
name = "JPwrites "
links = [
  { title = "royalroad", url = "https://www.royalroad.com/profile/9705" },
]

[author.cashen]
name = "Jman8763 C. Ashen"
links = [
  { title = "royalroad", url = "https://www.royalroad.com/profile/210709" },
]

[author.disheveledvagabond]
name = "DisheveledVagabond "
links = [
  { title = "royalroad", url = "https://www.royalroad.com/profile/192594" },
]

[author.cognosticon]
name = "Cognosticon"
links = [
  { title = "royalroad", url = "https://www.royalroad.com/profile/270595" },
]

5.3 - Countries

Countries
# source: https://gist.github.com/ssskip/5a94bfcd2835bf1dea52?permalink_comment_id=4690725#gistcomment-4690725

[AF]
"Country Name" = "Afghanistan"
ISO2 = "AF"
ISO3 = "AFG"
"Top Level Domain" = "af"
FIPS = "AF"
"ISO Numeric" = "004"
GeoNameID = 1_149_361
E164 = 93
"Phone Code" = 93
Continent = "Asia"
Capital = "Kabul"
"Time Zone in Capital" = "Asia/Kabul"
Currency = "Afghani"
"Language Codes" = "fa-AF,ps,uz-AF,tk"
Languages = "Afghan Persian or Dari (official) 50%, Pashto (official) 35%, Turkic languages (primarily Uzbek and Turkmen) 11%, 30 minor languages (primarily Balochi and Pashai) 4%, much bilingualism, but Dari functions as the lingua franca"
"Area KM2" = 647_500
"Internet Hosts" = 223
"Internet Users" = 1_000_000
"Phones (Mobile)" = 18_000_000
"Phones (Landline)" = 13_500
GDP = 20_650_000_000
englishShortName = "Afghanistan"
frenchShortName = "Afghanistan (l')"
numeric = 4
japaneseShortName = "アフガニスタン"

[AL]
"Country Name" = "Albania"
ISO2 = "AL"
ISO3 = "ALB"
"Top Level Domain" = "al"
FIPS = "AL"
"ISO Numeric" = "008"
GeoNameID = 783_754
E164 = 355
"Phone Code" = 355
Continent = "Europe"
Capital = "Tirana"
"Time Zone in Capital" = "Europe/Tirane"
Currency = "Lek"
"Language Codes" = "sq,el"
Languages = "Albanian 98.8% (official - derived from Tosk dialect), Greek 0.5%, other 0.6% (including Macedonian, Roma, Vlach, Turkish, Italian, and Serbo-Croatian), unspecified 0.1% (2011 est.)"
"Area KM2" = 28_748
"Internet Hosts" = 15_528
"Internet Users" = 1_300_000
"Phones (Mobile)" = 3_500_000
"Phones (Landline)" = 312_000
GDP = 12_800_000_000
englishShortName = "Albania"
frenchShortName = "Albanie (l')"
numeric = 8
japaneseShortName = "アルバニア"

[DZ]
"Country Name" = "Algeria"
ISO2 = "DZ"
ISO3 = "DZA"
"Top Level Domain" = "dz"
FIPS = "AG"
"ISO Numeric" = "012"
GeoNameID = 2_589_581
E164 = 213
"Phone Code" = 213
Continent = "Africa"
Capital = "Algiers"
"Time Zone in Capital" = "Africa/Algiers"
Currency = "Dinar"
"Language Codes" = "ar-DZ"
Languages = "Arabic (official), French (lingua franca), Berber dialects: Kabylie Berber (Tamazight), Chaouia Berber (Tachawit), Mzab Berber, Tuareg Berber (Tamahaq)"
"Area KM2" = 2_381_740
"Internet Hosts" = 676
"Internet Users" = 4_700_000
"Phones (Mobile)" = 37_692_000
"Phones (Landline)" = 3_200_000
GDP = 215_700_000_000
englishShortName = "Algeria"
frenchShortName = "Algérie (l')"
numeric = 12
japaneseShortName = "アルジェリア"

[AS]
"Country Name" = "American Samoa"
ISO2 = "AS"
ISO3 = "ASM"
"Top Level Domain" = "as"
FIPS = "AQ"
"ISO Numeric" = "016"
GeoNameID = 5_880_801
E164 = 1
"Phone Code" = "1-684"
Continent = "Oceania"
Capital = "Pago Pago"
"Time Zone in Capital" = "Pacific/Pago_Pago"
Currency = "Dollar"
"Language Codes" = "en-AS,sm,to"
Languages = "Samoan 90.6% (closely related to Hawaiian and other Polynesian languages), English 2.9%, Tongan 2.4%, other Pacific islander 2.1%, other 2%"
"Area KM2" = 199
"Internet Hosts" = 2_387
"Internet Users" = ""
"Phones (Mobile)" = ""
"Phones (Landline)" = 10_000
GDP = 462_200_000
englishShortName = "American Samoa"
frenchShortName = "Samoa américaines (les)"
numeric = 16
japaneseShortName = "アメリカ領サモア"

[AD]
"Country Name" = "Andorra"
ISO2 = "AD"
ISO3 = "AND"
"Top Level Domain" = "ad"
FIPS = "AN"
"ISO Numeric" = "020"
GeoNameID = 3_041_565
E164 = 376
"Phone Code" = 376
Continent = "Europe"
Capital = "Andorra la Vella"
"Time Zone in Capital" = "Europe/Andorra"
Currency = "Euro"
"Language Codes" = "ca"
Languages = "Catalan (official), French, Castilian, Portuguese"
"Area KM2" = 468
"Internet Hosts" = 28_383
"Internet Users" = 67_100
"Phones (Mobile)" = 65_000
"Phones (Landline)" = 39_000
GDP = 4_800_000_000
englishShortName = "Andorra"
frenchShortName = "Andorre (l')"
numeric = 20
japaneseShortName = "アンドラ"

[AO]
"Country Name" = "Angola"
ISO2 = "AO"
ISO3 = "AGO"
"Top Level Domain" = "ao"
FIPS = "AO"
"ISO Numeric" = "024"
GeoNameID = 3_351_879
E164 = 244
"Phone Code" = 244
Continent = "Africa"
Capital = "Luanda"
"Time Zone in Capital" = "Africa/Lagos"
Currency = "Kwanza"
"Language Codes" = "pt-AO"
Languages = "Portuguese (official), Bantu and other African languages"
"Area KM2" = 1_246_700
"Internet Hosts" = 20_703
"Internet Users" = 606_700
"Phones (Mobile)" = 9_800_000
"Phones (Landline)" = 303_000
GDP = 124_000_000_000
englishShortName = "Angola"
frenchShortName = "Angola (l')"
numeric = 24
japaneseShortName = "アンゴラ"

[AI]
"Country Name" = "Anguilla"
ISO2 = "AI"
ISO3 = "AIA"
"Top Level Domain" = "ai"
FIPS = "AV"
"ISO Numeric" = 660
GeoNameID = 3_573_511
E164 = 1
"Phone Code" = "1-264"
Continent = "North America"
Capital = "The Valley"
"Time Zone in Capital" = "America/Port_of_Spain"
Currency = "Dollar"
"Language Codes" = "en-AI"
Languages = "English (official)"
"Area KM2" = 102
"Internet Hosts" = 269
"Internet Users" = 3_700
"Phones (Mobile)" = 26_000
"Phones (Landline)" = 6_000
GDP = 175_400_000
englishShortName = "Anguilla"
frenchShortName = "Anguilla"
numeric = 660
japaneseShortName = "アンギラ"

[AQ]
"Country Name" = "Antarctica"
ISO2 = "AQ"
ISO3 = "ATA"
"Top Level Domain" = "aq"
FIPS = "AY"
"ISO Numeric" = "010"
GeoNameID = 6_697_173
E164 = 672
"Phone Code" = 672
Continent = "Antarctica"
Capital = ""
"Time Zone in Capital" = "Antarctica/Troll"
Currency = ""
"Language Codes" = ""
Languages = ""
"Area KM2" = 14_000_000
"Internet Hosts" = 7_764
"Internet Users" = ""
"Phones (Mobile)" = ""
"Phones (Landline)" = ""
GDP = ""
englishShortName = "Antarctica"
frenchShortName = "Antarctique (l')"
numeric = 10
japaneseShortName = "南極大陸"

[AG]
"Country Name" = "Antigua and Barbuda"
ISO2 = "AG"
ISO3 = "ATG"
"Top Level Domain" = "ag"
FIPS = "AC"
"ISO Numeric" = "028"
GeoNameID = 3_576_396
E164 = 1
"Phone Code" = "1-268"
Continent = "North America"
Capital = "St. John's"
"Time Zone in Capital" = "America/Antigua"
Currency = "Dollar"
"Language Codes" = "en-AG"
Languages = "English (official), local dialects"
"Area KM2" = 443
"Internet Hosts" = 11_532
"Internet Users" = 65_000
"Phones (Mobile)" = 179_800
"Phones (Landline)" = 35_000
GDP = 1_220_000_000
englishShortName = "Antigua and Barbuda"
frenchShortName = "Antigua-et-Barbuda"
numeric = 28
japaneseShortName = "アンティグア・バーブーダ"

[AR]
"Country Name" = "Argentina"
ISO2 = "AR"
ISO3 = "ARG"
"Top Level Domain" = "ar"
FIPS = "AR"
"ISO Numeric" = "032"
GeoNameID = 3_865_483
E164 = 54
"Phone Code" = 54
Continent = "South America"
Capital = "Buenos Aires"
"Time Zone in Capital" = "America/Argentina/Buenos_Aires"
Currency = "Peso"
"Language Codes" = "es-AR,en,it,de,fr,gn"
Languages = "Spanish (official), Italian, English, German, French, indigenous (Mapudungun, Quechua)"
"Area KM2" = 2_766_890
"Internet Hosts" = 11_232_000
"Internet Users" = 13_694_000
"Phones (Mobile)" = 58_600_000
"Phones (Landline)" = 1
GDP = 484_600_000_000
englishShortName = "Argentina"
frenchShortName = "Argentine (l')"
numeric = 32
japaneseShortName = "アルゼンチン"

[AM]
"Country Name" = "Armenia"
ISO2 = "AM"
ISO3 = "ARM"
"Top Level Domain" = "am"
FIPS = "AM"
"ISO Numeric" = "051"
GeoNameID = 174_982
E164 = 374
"Phone Code" = 374
Continent = "Asia"
Capital = "Yerevan"
"Time Zone in Capital" = "Asia/Yerevan"
Currency = "Dram"
"Language Codes" = "hy"
Languages = "Armenian (official) 97.9%, Kurdish (spoken by Yezidi minority) 1%, other 1% (2011 est.)"
"Area KM2" = 29_800
"Internet Hosts" = 194_142
"Internet Users" = 208_200
"Phones (Mobile)" = 3_223_000
"Phones (Landline)" = 584_000
GDP = 10_440_000_000
englishShortName = "Armenia"
frenchShortName = "Arménie (l')"
numeric = 51
japaneseShortName = "アルメニア"

[AW]
"Country Name" = "Aruba"
ISO2 = "AW"
ISO3 = "ABW"
"Top Level Domain" = "aw"
FIPS = "AA"
"ISO Numeric" = 533
GeoNameID = 3_577_279
E164 = 297
"Phone Code" = 297
Continent = "North America"
Capital = "Oranjestad"
"Time Zone in Capital" = "America/Curacao"
Currency = "Guilder"
"Language Codes" = "nl-AW,es,en"
Languages = "Papiamento (a Spanish-Portuguese-Dutch-English dialect) 69.4%, Spanish 13.7%, English (widely spoken) 7.1%, Dutch (official) 6.1%, Chinese 1.5%, other 1.7%, unspecified 0.4% (2010 est.)"
"Area KM2" = 193
"Internet Hosts" = 40_560
"Internet Users" = 24_000
"Phones (Mobile)" = 135_000
"Phones (Landline)" = 43_000
GDP = 2_516_000_000
englishShortName = "Aruba"
frenchShortName = "Aruba"
numeric = 533
japaneseShortName = "アルバ"

[AU]
"Country Name" = "Australia"
ISO2 = "AU"
ISO3 = "AUS"
"Top Level Domain" = "au"
FIPS = "AS"
"ISO Numeric" = "036"
GeoNameID = 2_077_456
E164 = 61
"Phone Code" = 61
Continent = "Oceania"
Capital = "Canberra"
"Time Zone in Capital" = "Australia/Sydney"
Currency = "Dollar"
"Language Codes" = "en-AU"
Languages = "English 76.8%, Mandarin 1.6%, Italian 1.4%, Arabic 1.3%, Greek 1.2%, Cantonese 1.2%, Vietnamese 1.1%, other 10.4%, unspecified 5% (2011 est.)"
"Area KM2" = 7_686_850
"Internet Hosts" = 17_081_000
"Internet Users" = 15_810_000
"Phones (Mobile)" = 24_400_000
"Phones (Landline)" = 10_470_000
GDP = 1_488_000_000_000
englishShortName = "Australia"
frenchShortName = "Australie (l')"
numeric = 36
japaneseShortName = "オーストラリア"

[AT]
"Country Name" = "Austria"
ISO2 = "AT"
ISO3 = "AUT"
"Top Level Domain" = "at"
FIPS = "AU"
"ISO Numeric" = "040"
GeoNameID = 2_782_113
E164 = 43
"Phone Code" = 43
Continent = "Europe"
Capital = "Vienna"
"Time Zone in Capital" = "Europe/Vienna"
Currency = "Euro"
"Language Codes" = "de-AT,hr,hu,sl"
Languages = "German (official nationwide) 88.6%, Turkish 2.3%, Serbian 2.2%, Croatian (official in Burgenland) 1.6%, other (includes Slovene, official in Carinthia, and Hungarian, official in Burgenland) 5.3% (2001 census)"
"Area KM2" = 83_858
"Internet Hosts" = 3_512_000
"Internet Users" = 6_143_000
"Phones (Mobile)" = 13_590_000
"Phones (Landline)" = 3_342_000
GDP = 417_900_000_000
englishShortName = "Austria"
frenchShortName = "Autriche (l')"
numeric = 40
japaneseShortName = "オーストリア"

[AZ]
"Country Name" = "Azerbaijan"
ISO2 = "AZ"
ISO3 = "AZE"
"Top Level Domain" = "az"
FIPS = "AJ"
"ISO Numeric" = "031"
GeoNameID = 587_116
E164 = 994
"Phone Code" = 994
Continent = "Asia"
Capital = "Baku"
"Time Zone in Capital" = "Asia/Baku"
Currency = "Manat"
"Language Codes" = "az,ru,hy"
Languages = "Azerbaijani (Azeri) (official) 92.5%, Russian 1.4%, Armenian 1.4%, other 4.7% (2009 est.)"
"Area KM2" = 86_600
"Internet Hosts" = 46_856
"Internet Users" = 2_420_000
"Phones (Mobile)" = 10_125_000
"Phones (Landline)" = 1_734_000
GDP = 76_010_000_000
englishShortName = "Azerbaijan"
frenchShortName = "Azerbaïdjan (l')"
numeric = 31
japaneseShortName = "アゼルバイジャン"

[BS]
"Country Name" = "Bahamas"
ISO2 = "BS"
ISO3 = "BHS"
"Top Level Domain" = "bs"
FIPS = "BF"
"ISO Numeric" = "044"
GeoNameID = 3_572_887
E164 = 1
"Phone Code" = "1-242"
Continent = "North America"
Capital = "Nassau"
"Time Zone in Capital" = "America/Nassau"
Currency = "Dollar"
"Language Codes" = "en-BS"
Languages = "English (official), Creole (among Haitian immigrants)"
"Area KM2" = 13_940
"Internet Hosts" = 20_661
"Internet Users" = 115_800
"Phones (Mobile)" = 254_000
"Phones (Landline)" = 137_000
GDP = 8_373_000_000
englishShortName = "Bahamas (the)"
frenchShortName = "Bahamas (les)"
numeric = 44
japaneseShortName = "バハマ"

[BH]
"Country Name" = "Bahrain"
ISO2 = "BH"
ISO3 = "BHR"
"Top Level Domain" = "bh"
FIPS = "BA"
"ISO Numeric" = "048"
GeoNameID = 290_291
E164 = 973
"Phone Code" = 973
Continent = "Asia"
Capital = "Manama"
"Time Zone in Capital" = "Asia/Bahrain"
Currency = "Dinar"
"Language Codes" = "ar-BH,en,fa,ur"
Languages = "Arabic (official), English, Farsi, Urdu"
"Area KM2" = 665
"Internet Hosts" = 47_727
"Internet Users" = 419_500
"Phones (Mobile)" = 2_125_000
"Phones (Landline)" = 290_000
GDP = 28_360_000_000
englishShortName = "Bahrain"
frenchShortName = "Bahreïn"
numeric = 48
japaneseShortName = "バーレーン"

[BD]
"Country Name" = "Bangladesh"
ISO2 = "BD"
ISO3 = "BGD"
"Top Level Domain" = "bd"
FIPS = "BG"
"ISO Numeric" = "050"
GeoNameID = 1_210_997
E164 = 880
"Phone Code" = 880
Continent = "Asia"
Capital = "Dhaka"
"Time Zone in Capital" = "Asia/Dhaka"
Currency = "Taka"
"Language Codes" = "bn-BD,en"
Languages = "Bangla (official, also known as Bengali), English"
"Area KM2" = 144_000
"Internet Hosts" = 71_164
"Internet Users" = 617_300
"Phones (Mobile)" = 97_180_000
"Phones (Landline)" = 962_000
GDP = 140_200_000_000
englishShortName = "Bangladesh"
frenchShortName = "Bangladesh (le)"
numeric = 50
japaneseShortName = "バングラデシュ"

[BB]
"Country Name" = "Barbados"
ISO2 = "BB"
ISO3 = "BRB"
"Top Level Domain" = "bb"
FIPS = "BB"
"ISO Numeric" = "052"
GeoNameID = 3_374_084
E164 = 1
"Phone Code" = "1-246"
Continent = "North America"
Capital = "Bridgetown"
"Time Zone in Capital" = "America/Barbados"
Currency = "Dollar"
"Language Codes" = "en-BB"
Languages = "English (official), Bajan (English-based creole language, widely spoken in informal settings)"
"Area KM2" = 431
"Internet Hosts" = 1_524
"Internet Users" = 188_000
"Phones (Mobile)" = 347_000
"Phones (Landline)" = 144_000
GDP = 4_262_000_000
englishShortName = "Barbados"
frenchShortName = "Barbade (la)"
numeric = 52
japaneseShortName = "バルバドス"

[BY]
"Country Name" = "Belarus"
ISO2 = "BY"
ISO3 = "BLR"
"Top Level Domain" = "by"
FIPS = "BO"
"ISO Numeric" = 112
GeoNameID = 630_336
E164 = 375
"Phone Code" = 375
Continent = "Europe"
Capital = "Minsk"
"Time Zone in Capital" = "Europe/Minsk"
Currency = "Ruble"
"Language Codes" = "be,ru"
Languages = "Belarusian (official) 23.4%, Russian (official) 70.2%, other 3.1% (includes small Polish- and Ukrainian-speaking minorities), unspecified 3.3% (2009 est.)"
"Area KM2" = 207_600
"Internet Hosts" = 295_217
"Internet Users" = 2_643_000
"Phones (Mobile)" = 10_675_000
"Phones (Landline)" = 4_407_000
GDP = 69_240_000_000
englishShortName = "Belarus"
frenchShortName = "Bélarus (le)"
numeric = 112
japaneseShortName = "ベラルーシ"

[BE]
"Country Name" = "Belgium"
ISO2 = "BE"
ISO3 = "BEL"
"Top Level Domain" = "be"
FIPS = "BE"
"ISO Numeric" = "056"
GeoNameID = 2_802_361
E164 = 32
"Phone Code" = 32
Continent = "Europe"
Capital = "Brussels"
"Time Zone in Capital" = "Europe/Brussels"
Currency = "Euro"
"Language Codes" = "nl-BE,fr-BE,de-BE"
Languages = "Dutch (official) 60%, French (official) 40%, German (official) less than 1%, legally bilingual (Dutch and French)"
"Area KM2" = 30_510
"Internet Hosts" = 5_192_000
"Internet Users" = 8_113_000
"Phones (Mobile)" = 12_880_000
"Phones (Landline)" = 4_631_000
GDP = 507_400_000_000
englishShortName = "Belgium"
frenchShortName = "Belgique (la)"
numeric = 56
japaneseShortName = "ベルギー"

[BZ]
"Country Name" = "Belize"
ISO2 = "BZ"
ISO3 = "BLZ"
"Top Level Domain" = "bz"
FIPS = "BH"
"ISO Numeric" = "084"
GeoNameID = 3_582_678
E164 = 501
"Phone Code" = 501
Continent = "North America"
Capital = "Belmopan"
"Time Zone in Capital" = "America/Belize"
Currency = "Dollar"
"Language Codes" = "en-BZ,es"
Languages = "Spanish 46%, Creole 32.9%, Mayan dialects 8.9%, English 3.9% (official), Garifuna 3.4% (Carib), German 3.3%, other 1.4%, unknown 0.2% (2000 census)"
"Area KM2" = 22_966
"Internet Hosts" = 3_392
"Internet Users" = 36_000
"Phones (Mobile)" = 164_200
"Phones (Landline)" = 25_400
GDP = 1_637_000_000
englishShortName = "Belize"
frenchShortName = "Belize (le)"
numeric = 84
japaneseShortName = "ベリーズ"

[BJ]
"Country Name" = "Benin"
ISO2 = "BJ"
ISO3 = "BEN"
"Top Level Domain" = "bj"
FIPS = "BN"
"ISO Numeric" = 204
GeoNameID = 2_395_170
E164 = 229
"Phone Code" = 229
Continent = "Africa"
Capital = "Porto-Novo"
"Time Zone in Capital" = "Africa/Lagos"
Currency = "Franc"
"Language Codes" = "fr-BJ"
Languages = "French (official), Fon and Yoruba (most common vernaculars in south), tribal languages (at least six major ones in north)"
"Area KM2" = 112_620
"Internet Hosts" = 491
"Internet Users" = 200_100
"Phones (Mobile)" = 8_408_000
"Phones (Landline)" = 156_700
GDP = 8_359_000_000
englishShortName = "Benin"
frenchShortName = "Bénin (le)"
numeric = 204
japaneseShortName = "ベナン"

[BM]
"Country Name" = "Bermuda"
ISO2 = "BM"
ISO3 = "BMU"
"Top Level Domain" = "bm"
FIPS = "BD"
"ISO Numeric" = "060"
GeoNameID = 3_573_345
E164 = 1
"Phone Code" = "1-441"
Continent = "North America"
Capital = "Hamilton"
"Time Zone in Capital" = "Atlantic/Bermuda"
Currency = "Dollar"
"Language Codes" = "en-BM,pt"
Languages = "English (official), Portuguese"
"Area KM2" = 53
"Internet Hosts" = 20_040
"Internet Users" = 54_000
"Phones (Mobile)" = 91_000
"Phones (Landline)" = 69_000
GDP = 5_600_000_000
englishShortName = "Bermuda"
frenchShortName = "Bermudes (les)"
numeric = 60
japaneseShortName = "バミューダ"

[BT]
"Country Name" = "Bhutan"
ISO2 = "BT"
ISO3 = "BTN"
"Top Level Domain" = "bt"
FIPS = "BT"
"ISO Numeric" = "064"
GeoNameID = 1_252_634
E164 = 975
"Phone Code" = 975
Continent = "Asia"
Capital = "Thimphu"
"Time Zone in Capital" = "Asia/Thimphu"
Currency = "Ngultrum"
"Language Codes" = "dz"
Languages = "Sharchhopka 28%, Dzongkha (official) 24%, Lhotshamkha 22%, other 26% (includes foreign languages) (2005 est.)"
"Area KM2" = 47_000
"Internet Hosts" = 14_590
"Internet Users" = 50_000
"Phones (Mobile)" = 560_000
"Phones (Landline)" = 27_000
GDP = 2_133_000_000
englishShortName = "Bhutan"
frenchShortName = "Bhoutan (le)"
numeric = 64
japaneseShortName = "ブータン"

[BO]
"Country Name" = "Bolivia"
ISO2 = "BO"
ISO3 = "BOL"
"Top Level Domain" = "bo"
FIPS = "BL"
"ISO Numeric" = "068"
GeoNameID = 3_923_057
E164 = 591
"Phone Code" = 591
Continent = "South America"
Capital = "Sucre"
"Time Zone in Capital" = "America/La_Paz"
Currency = "Boliviano"
"Language Codes" = "es-BO,qu,ay"
Languages = "Spanish (official) 60.7%, Quechua (official) 21.2%, Aymara (official) 14.6%, Guarani (official), foreign languages 2.4%, other 1.2%"
"Area KM2" = 1_098_580
"Internet Hosts" = 180_988
"Internet Users" = 1_103_000
"Phones (Mobile)" = 9_494_000
"Phones (Landline)" = 880_600
GDP = 30_790_000_000
englishShortName = "Bolivia (Plurinational State of)"
frenchShortName = "Bolivie (État plurinational de)"
numeric = 68
japaneseShortName = "ボリビア"

[BA]
"Country Name" = "Bosnia and Herzegovina"
ISO2 = "BA"
ISO3 = "BIH"
"Top Level Domain" = "ba"
FIPS = "BK"
"ISO Numeric" = "070"
GeoNameID = 3_277_605
E164 = 387
"Phone Code" = 387
Continent = "Europe"
Capital = "Sarajevo"
"Time Zone in Capital" = "Europe/Belgrade"
Currency = "Marka"
"Language Codes" = "bs,hr-BA,sr-BA"
Languages = "Bosnian (official), Croatian (official), Serbian (official)"
"Area KM2" = 51_129
"Internet Hosts" = 155_252
"Internet Users" = 1_422_000
"Phones (Mobile)" = 3_350_000
"Phones (Landline)" = 878_000
GDP = 18_870_000_000
englishShortName = "Bosnia and Herzegovina"
frenchShortName = "Bosnie-Herzégovine (la)"
numeric = 70
japaneseShortName = "ボスニア・ヘルツェゴビナ"

[BW]
"Country Name" = "Botswana"
ISO2 = "BW"
ISO3 = "BWA"
"Top Level Domain" = "bw"
FIPS = "BC"
"ISO Numeric" = "072"
GeoNameID = 933_860
E164 = 267
"Phone Code" = 267
Continent = "Africa"
Capital = "Gaborone"
"Time Zone in Capital" = "Africa/Maputo"
Currency = "Pula"
"Language Codes" = "en-BW,tn-BW"
Languages = "Setswana 78.2%, Kalanga 7.9%, Sekgalagadi 2.8%, English (official) 2.1%, other 8.6%, unspecified 0.4% (2001 census)"
"Area KM2" = 600_370
"Internet Hosts" = 1_806
"Internet Users" = 120_000
"Phones (Mobile)" = 3_082_000
"Phones (Landline)" = 160_500
GDP = 15_530_000_000
englishShortName = "Botswana"
frenchShortName = "Botswana (le)"
numeric = 72
japaneseShortName = "ボツワナ"

[BR]
"Country Name" = "Brazil"
ISO2 = "BR"
ISO3 = "BRA"
"Top Level Domain" = "br"
FIPS = "BR"
"ISO Numeric" = "076"
GeoNameID = 3_469_034
E164 = 55
"Phone Code" = 55
Continent = "South America"
Capital = "Brasilia"
"Time Zone in Capital" = "America/Sao_Paulo"
Currency = "Real"
"Language Codes" = "pt-BR,es,en,fr"
Languages = "Portuguese (official and most widely spoken language)"
"Area KM2" = 8_511_965
"Internet Hosts" = 26_577_000
"Internet Users" = 75_982_000
"Phones (Mobile)" = 248_324_000
"Phones (Landline)" = 44_300_000
GDP = 2_190_000_000_000
englishShortName = "Brazil"
frenchShortName = "Brésil (le)"
numeric = 76
japaneseShortName = "ブラジル"

[IO]
"Country Name" = "British Indian Ocean Territory"
ISO2 = "IO"
ISO3 = "IOT"
"Top Level Domain" = "io"
FIPS = "IO"
"ISO Numeric" = "086"
GeoNameID = 1_282_588
E164 = 246
"Phone Code" = 246
Continent = "Asia"
Capital = "Diego Garcia"
"Time Zone in Capital" = "Indian/Chagos"
Currency = "Dollar"
"Language Codes" = "en-IO"
Languages = "English"
"Area KM2" = 60
"Internet Hosts" = 75_006
"Internet Users" = ""
"Phones (Mobile)" = ""
"Phones (Landline)" = ""
GDP = ""
englishShortName = "British Indian Ocean Territory (the)"
frenchShortName = "Indien (le Territoire britannique de l'océan)"
numeric = 86
japaneseShortName = "イギリス領インド洋地域"

[VG]
"Country Name" = "British Virgin Islands"
ISO2 = "VG"
ISO3 = "VGB"
"Top Level Domain" = "vg"
FIPS = "VI"
"ISO Numeric" = "092"
GeoNameID = 3_577_718
E164 = 1
"Phone Code" = "1-284"
Continent = "North America"
Capital = "Road Town"
"Time Zone in Capital" = "America/Port_of_Spain"
Currency = "Dollar"
"Language Codes" = "en-VG"
Languages = "English (official)"
"Area KM2" = 153
"Internet Hosts" = 505
"Internet Users" = 4_000
"Phones (Mobile)" = 48_700
"Phones (Landline)" = 12_268
GDP = 1_095_000_000
englishShortName = "Virgin Islands (British)"
frenchShortName = "Vierges britanniques (les Îles)"
numeric = 92
japaneseShortName = "イギリス領ヴァージン諸島"

[BN]
"Country Name" = "Brunei"
ISO2 = "BN"
ISO3 = "BRN"
"Top Level Domain" = "bn"
FIPS = "BX"
"ISO Numeric" = "096"
GeoNameID = 1_820_814
E164 = 673
"Phone Code" = 673
Continent = "Asia"
Capital = "Bandar Seri Begawan"
"Time Zone in Capital" = "Asia/Brunei"
Currency = "Dollar"
"Language Codes" = "ms-BN,en-BN"
Languages = "Malay (official), English, Chinese"
"Area KM2" = 5_770
"Internet Hosts" = 49_457
"Internet Users" = 314_900
"Phones (Mobile)" = 469_700
"Phones (Landline)" = 70_933
GDP = 16_560_000_000
englishShortName = "Brunei Darussalam"
frenchShortName = "Brunéi Darussalam (le)"
numeric = 96
japaneseShortName = "ブルネイ・ダルサラーム"

[BG]
"Country Name" = "Bulgaria"
ISO2 = "BG"
ISO3 = "BGR"
"Top Level Domain" = "bg"
FIPS = "BU"
"ISO Numeric" = 100
GeoNameID = 732_800
E164 = 359
"Phone Code" = 359
Continent = "Europe"
Capital = "Sofia"
"Time Zone in Capital" = "Europe/Sofia"
Currency = "Lev"
"Language Codes" = "bg,tr-BG"
Languages = "Bulgarian (official) 76.8%, Turkish 8.2%, Roma 3.8%, other 0.7%, unspecified 10.5% (2011 est.)"
"Area KM2" = 110_910
"Internet Hosts" = 976_277
"Internet Users" = 3_395_000
"Phones (Mobile)" = 10_780_000
"Phones (Landline)" = 2_253_000
GDP = 53_700_000_000
englishShortName = "Bulgaria"
frenchShortName = "Bulgarie (la)"
numeric = 100
japaneseShortName = "ブルガリア"

[BF]
"Country Name" = "Burkina Faso"
ISO2 = "BF"
ISO3 = "BFA"
"Top Level Domain" = "bf"
FIPS = "UV"
"ISO Numeric" = 854
GeoNameID = 2_361_809
E164 = 226
"Phone Code" = 226
Continent = "Africa"
Capital = "Ouagadougou"
"Time Zone in Capital" = "Africa/Abidjan"
Currency = "Franc"
"Language Codes" = "fr-BF"
Languages = "French (official), native African languages belonging to Sudanic family spoken by 90% of the population"
"Area KM2" = 274_200
"Internet Hosts" = 1_795
"Internet Users" = 178_100
"Phones (Mobile)" = 9_980_000
"Phones (Landline)" = 141_400
GDP = 12_130_000_000
englishShortName = "Burkina Faso"
frenchShortName = "Burkina Faso (le)"
numeric = 854
japaneseShortName = "ブルキナファソ"

[BI]
"Country Name" = "Burundi"
ISO2 = "BI"
ISO3 = "BDI"
"Top Level Domain" = "bi"
FIPS = "BY"
"ISO Numeric" = 108
GeoNameID = 433_561
E164 = 257
"Phone Code" = 257
Continent = "Africa"
Capital = "Bujumbura"
"Time Zone in Capital" = "Africa/Maputo"
Currency = "Franc"
"Language Codes" = "fr-BI,rn"
Languages = "Kirundi 29.7% (official), Kirundi and other language 9.1%, French (official) and French and other language 0.3%, Swahili and Swahili and other language 0.2% (along Lake Tanganyika and in the Bujumbura area), English and English and other language 0.06%, more than 2 languages 3.7%, unspecified 56.9% (2008 est.)"
"Area KM2" = 27_830
"Internet Hosts" = 229
"Internet Users" = 157_800
"Phones (Mobile)" = 2_247_000
"Phones (Landline)" = 17_400
GDP = 2_676_000_000
englishShortName = "Burundi"
frenchShortName = "Burundi (le)"
numeric = 108
japaneseShortName = "ブルンジ"

[KH]
"Country Name" = "Cambodia"
ISO2 = "KH"
ISO3 = "KHM"
"Top Level Domain" = "kh"
FIPS = "CB"
"ISO Numeric" = 116
GeoNameID = 1_831_722
E164 = 855
"Phone Code" = 855
Continent = "Asia"
Capital = "Phnom Penh"
"Time Zone in Capital" = "Asia/Phnom_Penh"
Currency = "Riels"
"Language Codes" = "km,fr,en"
Languages = "Khmer (official) 96.3%, other 3.7% (2008 est.)"
"Area KM2" = 181_040
"Internet Hosts" = 13_784
"Internet Users" = 78_500
"Phones (Mobile)" = 19_100_000
"Phones (Landline)" = 584_000
GDP = 15_640_000_000
englishShortName = "Cambodia"
frenchShortName = "Cambodge (le)"
numeric = 116
japaneseShortName = "カンボジア"

[CM]
"Country Name" = "Cameroon"
ISO2 = "CM"
ISO3 = "CMR"
"Top Level Domain" = "cm"
FIPS = "CM"
"ISO Numeric" = 120
GeoNameID = 2_233_387
E164 = 237
"Phone Code" = 237
Continent = "Africa"
Capital = "Yaounde"
"Time Zone in Capital" = "Africa/Lagos"
Currency = "Franc"
"Language Codes" = "en-CM,fr-CM"
Languages = "24 major African language groups, English (official), French (official)"
"Area KM2" = 475_440
"Internet Hosts" = 10_207
"Internet Users" = 749_600
"Phones (Mobile)" = 13_100_000
"Phones (Landline)" = 737_400
GDP = 27_880_000_000
englishShortName = "Cameroon"
frenchShortName = "Cameroun (le)"
numeric = 120
japaneseShortName = "カメルーン"

[CA]
"Country Name" = "Canada"
ISO2 = "CA"
ISO3 = "CAN"
"Top Level Domain" = "ca"
FIPS = "CA"
"ISO Numeric" = 124
GeoNameID = 6_251_999
E164 = 1
"Phone Code" = 1
Continent = "North America"
Capital = "Ottawa"
"Time Zone in Capital" = "America/Toronto"
Currency = "Dollar"
"Language Codes" = "en-CA,fr-CA,iu"
Languages = "English (official) 58.7%, French (official) 22%, Punjabi 1.4%, Italian 1.3%, Spanish 1.3%, German 1.3%, Cantonese 1.2%, Tagalog 1.2%, Arabic 1.1%, other 10.5% (2011 est.)"
"Area KM2" = 9_984_670
"Internet Hosts" = 8_743_000
"Internet Users" = 26_960_000
"Phones (Mobile)" = 26_263_000
"Phones (Landline)" = 18_010_000
GDP = 1_825_000_000_000
englishShortName = "Canada"
frenchShortName = "Canada (le)"
numeric = 124
japaneseShortName = "カナダ"

[CV]
"Country Name" = "Cape Verde"
ISO2 = "CV"
ISO3 = "CPV"
"Top Level Domain" = "cv"
FIPS = "CV"
"ISO Numeric" = 132
GeoNameID = 3_374_766
E164 = 238
"Phone Code" = 238
Continent = "Africa"
Capital = "Praia"
"Time Zone in Capital" = "Atlantic/Cape_Verde"
Currency = "Escudo"
"Language Codes" = "pt-CV"
Languages = "Portuguese (official), Crioulo (a blend of Portuguese and West African words)"
"Area KM2" = 4_033
"Internet Hosts" = 38
"Internet Users" = 150_000
"Phones (Mobile)" = 425_300
"Phones (Landline)" = 70_200
GDP = 1_955_000_000
englishShortName = "Cabo Verde"
frenchShortName = "Cabo Verde"
numeric = 132
japaneseShortName = "カーボベルデ"

[KY]
"Country Name" = "Cayman Islands"
ISO2 = "KY"
ISO3 = "CYM"
"Top Level Domain" = "ky"
FIPS = "CJ"
"ISO Numeric" = 136
GeoNameID = 3_580_718
E164 = 1
"Phone Code" = "1-345"
Continent = "North America"
Capital = "George Town"
"Time Zone in Capital" = "America/Cayman"
Currency = "Dollar"
"Language Codes" = "en-KY"
Languages = "English (official) 90.9%, Spanish 4%, Filipino 3.3%, other 1.7%, unspecified 0.1% (2010 est.)"
"Area KM2" = 262
"Internet Hosts" = 23_472
"Internet Users" = 23_000
"Phones (Mobile)" = 96_300
"Phones (Landline)" = 37_400
GDP = 2_250_000_000
englishShortName = "Cayman Islands (the)"
frenchShortName = "Caïmans (les Îles)"
numeric = 136
japaneseShortName = "ケイマン諸島"

[CF]
"Country Name" = "Central African Republic"
ISO2 = "CF"
ISO3 = "CAF"
"Top Level Domain" = "cf"
FIPS = "CT"
"ISO Numeric" = 140
GeoNameID = 239_880
E164 = 236
"Phone Code" = 236
Continent = "Africa"
Capital = "Bangui"
"Time Zone in Capital" = "Africa/Lagos"
Currency = "Franc"
"Language Codes" = "fr-CF,sg,ln,kg"
Languages = "French (official), Sangho (lingua franca and national language), tribal languages"
"Area KM2" = 622_984
"Internet Hosts" = 20
"Internet Users" = 22_600
"Phones (Mobile)" = 1_070_000
"Phones (Landline)" = 5_600
GDP = 2_050_000_000
englishShortName = "Central African Republic (the)"
frenchShortName = "République centrafricaine (la)"
numeric = 140
japaneseShortName = "中央アフリカ共和国"

[TD]
"Country Name" = "Chad"
ISO2 = "TD"
ISO3 = "TCD"
"Top Level Domain" = "td"
FIPS = "CD"
"ISO Numeric" = 148
GeoNameID = 2_434_508
E164 = 235
"Phone Code" = 235
Continent = "Africa"
Capital = "N'Djamena"
"Time Zone in Capital" = "Africa/Ndjamena"
Currency = "Franc"
"Language Codes" = "fr-TD,ar-TD,sre"
Languages = "French (official), Arabic (official), Sara (in south), more than 120 different languages and dialects"
"Area KM2" = 1_284_000
"Internet Hosts" = 6
"Internet Users" = 168_100
"Phones (Mobile)" = 4_200_000
"Phones (Landline)" = 29_900
GDP = 13_590_000_000
englishShortName = "Chad"
frenchShortName = "Tchad (le)"
numeric = 148
japaneseShortName = "チャド"

[CL]
"Country Name" = "Chile"
ISO2 = "CL"
ISO3 = "CHL"
"Top Level Domain" = "cl"
FIPS = "CI"
"ISO Numeric" = 152
GeoNameID = 3_895_114
E164 = 56
"Phone Code" = 56
Continent = "South America"
Capital = "Santiago"
"Time Zone in Capital" = "America/Santiago"
Currency = "Peso"
"Language Codes" = "es-CL"
Languages = "Spanish 99.5% (official), English 10.2%, indigenous 1% (includes Mapudungun, Aymara, Quechua, Rapa Nui), other 2.3%, unspecified 0.2%"
"Area KM2" = 756_950
"Internet Hosts" = 2_152_000
"Internet Users" = 7_009_000
"Phones (Mobile)" = 24_130_000
"Phones (Landline)" = 3_276_000
GDP = 281_700_000_000
englishShortName = "Chile"
frenchShortName = "Chili (le)"
numeric = 152
japaneseShortName = "チリ"

[CN]
"Country Name" = "China"
ISO2 = "CN"
ISO3 = "CHN"
"Top Level Domain" = "cn"
FIPS = "CH"
"ISO Numeric" = 156
GeoNameID = 1_814_991
E164 = 86
"Phone Code" = 86
Continent = "Asia"
Capital = "Beijing"
"Time Zone in Capital" = "Asia/Shanghai"
Currency = "Yuan Renminbi"
"Language Codes" = "zh-CN,yue,wuu,dta,ug,za"
Languages = "Standard Chinese or Mandarin (official; Putonghua, based on the Beijing dialect), Yue (Cantonese), Wu (Shanghainese), Minbei (Fuzhou), Minnan (Hokkien-Taiwanese), Xiang, Gan, Hakka dialects, minority languages"
"Area KM2" = 9_596_960
"Internet Hosts" = 20_602_000
"Internet Users" = 389_000_000
"Phones (Mobile)" = 1_100_000_000
"Phones (Landline)" = 278_860_000
GDP = 9_330_000_000_000
englishShortName = "China"
frenchShortName = "Chine (la)"
numeric = 156
japaneseShortName = "中国"

[CX]
"Country Name" = "Christmas Island"
ISO2 = "CX"
ISO3 = "CXR"
"Top Level Domain" = "cx"
FIPS = "KT"
"ISO Numeric" = 162
GeoNameID = 2_078_138
E164 = 61
"Phone Code" = 61
Continent = "Asia"
Capital = "Flying Fish Cove"
"Time Zone in Capital" = "Indian/Christmas"
Currency = "Dollar"
"Language Codes" = "en,zh,ms-CC"
Languages = "English (official), Chinese, Malay"
"Area KM2" = 135
"Internet Hosts" = 3_028
"Internet Users" = 464
"Phones (Mobile)" = ""
"Phones (Landline)" = ""
GDP = ""
englishShortName = "Christmas Island"
frenchShortName = "Christmas (l'Île)"
numeric = 162
japaneseShortName = "クリスマス島"

[CC]
"Country Name" = "Cocos Islands"
ISO2 = "CC"
ISO3 = "CCK"
"Top Level Domain" = "cc"
FIPS = "CK"
"ISO Numeric" = 166
GeoNameID = 1_547_376
E164 = 61
"Phone Code" = 61
Continent = "Asia"
Capital = "West Island"
"Time Zone in Capital" = "Indian/Cocos"
Currency = "Dollar"
"Language Codes" = "ms-CC,en"
Languages = "Malay (Cocos dialect), English"
"Area KM2" = 14
"Internet Hosts" = ""
"Internet Users" = ""
"Phones (Mobile)" = ""
"Phones (Landline)" = ""
GDP = ""
englishShortName = "Cocos (Keeling) Islands (the)"
frenchShortName = "Cocos (les Îles)/ Keeling (les Îles)"
numeric = 166
japaneseShortName = "ココス諸島"

[CO]
"Country Name" = "Colombia"
ISO2 = "CO"
ISO3 = "COL"
"Top Level Domain" = "co"
FIPS = "CO"
"ISO Numeric" = 170
GeoNameID = 3_686_110
E164 = 57
"Phone Code" = 57
Continent = "South America"
Capital = "Bogota"
"Time Zone in Capital" = "America/Bogota"
Currency = "Peso"
"Language Codes" = "es-CO"
Languages = "Spanish (official)"
"Area KM2" = 1_138_910
"Internet Hosts" = 4_410_000
"Internet Users" = 22_538_000
"Phones (Mobile)" = 49_066_000
"Phones (Landline)" = 6_291_000
GDP = 369_200_000_000
englishShortName = "Colombia"
frenchShortName = "Colombie (la)"
numeric = 170
japaneseShortName = "コロンビア"

[KM]
"Country Name" = "Comoros"
ISO2 = "KM"
ISO3 = "COM"
"Top Level Domain" = "km"
FIPS = "CN"
"ISO Numeric" = 174
GeoNameID = 921_929
E164 = 269
"Phone Code" = 269
Continent = "Africa"
Capital = "Moroni"
"Time Zone in Capital" = "Indian/Comoro"
Currency = "Franc"
"Language Codes" = "ar,fr-KM"
Languages = "Arabic (official), French (official), Shikomoro (a blend of Swahili and Arabic)"
"Area KM2" = 2_170
"Internet Hosts" = 14
"Internet Users" = 24_300
"Phones (Mobile)" = 250_000
"Phones (Landline)" = 24_000
GDP = 658_000_000
englishShortName = "Comoros (the)"
frenchShortName = "Comores (les)"
numeric = 174
japaneseShortName = "コモロ"

[CK]
"Country Name" = "Cook Islands"
ISO2 = "CK"
ISO3 = "COK"
"Top Level Domain" = "ck"
FIPS = "CW"
"ISO Numeric" = 184
GeoNameID = 1_899_402
E164 = 682
"Phone Code" = 682
Continent = "Oceania"
Capital = "Avarua"
"Time Zone in Capital" = "Pacific/Rarotonga"
Currency = "Dollar"
"Language Codes" = "en-CK,mi"
Languages = "English (official) 86.4%, Cook Islands Maori (Rarotongan) (official) 76.2%, other 8.3%"
"Area KM2" = 240
"Internet Hosts" = 3_562
"Internet Users" = 6_000
"Phones (Mobile)" = 7_800
"Phones (Landline)" = 7_200
GDP = 183_200_000
englishShortName = "Cook Islands (the)"
frenchShortName = "Cook (les Îles)"
numeric = 184
japaneseShortName = "クック諸島"

[CR]
"Country Name" = "Costa Rica"
ISO2 = "CR"
ISO3 = "CRI"
"Top Level Domain" = "cr"
FIPS = "CS"
"ISO Numeric" = 188
GeoNameID = 3_624_060
E164 = 506
"Phone Code" = 506
Continent = "North America"
Capital = "San Jose"
"Time Zone in Capital" = "America/Costa_Rica"
Currency = "Colon"
"Language Codes" = "es-CR,en"
Languages = "Spanish (official), English"
"Area KM2" = 51_100
"Internet Hosts" = 147_258
"Internet Users" = 1_485_000
"Phones (Mobile)" = 6_151_000
"Phones (Landline)" = 1_018_000
GDP = 48_510_000_000
englishShortName = "Costa Rica"
frenchShortName = "Costa Rica (le)"
numeric = 188
japaneseShortName = "コスタリカ"

[HR]
"Country Name" = "Croatia"
ISO2 = "HR"
ISO3 = "HRV"
"Top Level Domain" = "hr"
FIPS = "HR"
"ISO Numeric" = 191
GeoNameID = 3_202_326
E164 = 385
"Phone Code" = 385
Continent = "Europe"
Capital = "Zagreb"
"Time Zone in Capital" = "Europe/Belgrade"
Currency = "Kuna"
"Language Codes" = "hr-HR,sr"
Languages = "Croatian (official) 95.6%, Serbian 1.2%, other 3% (including Hungarian, Czech, Slovak, and Albanian), unspecified 0.2% (2011 est.)"
"Area KM2" = 56_542
"Internet Hosts" = 729_420
"Internet Users" = 2_234_000
"Phones (Mobile)" = 4_970_000
"Phones (Landline)" = 1_640_000
GDP = 59_140_000_000
englishShortName = "Croatia"
frenchShortName = "Croatie (la)"
numeric = 191
japaneseShortName = "クロアチア"

[CU]
"Country Name" = "Cuba"
ISO2 = "CU"
ISO3 = "CUB"
"Top Level Domain" = "cu"
FIPS = "CU"
"ISO Numeric" = 192
GeoNameID = 3_562_981
E164 = 53
"Phone Code" = 53
Continent = "North America"
Capital = "Havana"
"Time Zone in Capital" = "America/Havana"
Currency = "Peso"
"Language Codes" = "es-CU"
Languages = "Spanish (official)"
"Area KM2" = 110_860
"Internet Hosts" = 3_244
"Internet Users" = 1_606_000
"Phones (Mobile)" = 1_682_000
"Phones (Landline)" = 1_217_000
GDP = 72_300_000_000
englishShortName = "Cuba"
frenchShortName = "Cuba"
numeric = 192
japaneseShortName = "キューバ"

[CW]
"Country Name" = "Curacao"
ISO2 = "CW"
ISO3 = "CUW"
"Top Level Domain" = "cw"
FIPS = "UC"
"ISO Numeric" = 531
GeoNameID = 7_626_836
E164 = 599
"Phone Code" = 599
Continent = "North America"
Capital = "Willemstad"
"Time Zone in Capital" = "America/Curacao"
Currency = "Guilder"
"Language Codes" = "nl,pap"
Languages = "Papiamentu (a Spanish-Portuguese-Dutch-English dialect) 81.2%, Dutch (official) 8%, Spanish 4%, English 2.9%, other 3.9% (2001 census)"
"Area KM2" = 444
"Internet Hosts" = ""
"Internet Users" = ""
"Phones (Mobile)" = ""
"Phones (Landline)" = ""
GDP = 5_600_000_000
englishShortName = "Curaçao"
frenchShortName = "Curaçao"
numeric = 531

[CY]
"Country Name" = "Cyprus"
ISO2 = "CY"
ISO3 = "CYP"
"Top Level Domain" = "cy"
FIPS = "CY"
"ISO Numeric" = 196
GeoNameID = 146_669
E164 = 357
"Phone Code" = 357
Continent = "Europe"
Capital = "Nicosia"
"Time Zone in Capital" = "Asia/Nicosia"
Currency = "Euro"
"Language Codes" = "el-CY,tr-CY,en"
Languages = "Greek (official) 80.9%, Turkish (official) 0.2%, English 4.1%, Romanian 2.9%, Russian 2.5%, Bulgarian 2.2%, Arabic 1.2%, Filippino 1.1%, other 4.3%, unspecified 0.6% (2011 est.)"
"Area KM2" = 9_250
"Internet Hosts" = 252_013
"Internet Users" = 433_900
"Phones (Mobile)" = 1_110_000
"Phones (Landline)" = 373_200
GDP = 21_780_000_000
englishShortName = "Cyprus"
frenchShortName = "Chypre"
numeric = 196
japaneseShortName = "キプロス"

[CZ]
"Country Name" = "Czech Republic"
ISO2 = "CZ"
ISO3 = "CZE"
"Top Level Domain" = "cz"
FIPS = "EZ"
"ISO Numeric" = 203
GeoNameID = 3_077_311
E164 = 420
"Phone Code" = 420
Continent = "Europe"
Capital = "Prague"
"Time Zone in Capital" = "Europe/Prague"
Currency = "Koruna"
"Language Codes" = "cs,sk"
Languages = "Czech 95.4%, Slovak 1.6%, other 3% (2011 census)"
"Area KM2" = 78_866
"Internet Hosts" = 4_148_000
"Internet Users" = 6_681_000
"Phones (Mobile)" = 12_973_000
"Phones (Landline)" = 2_100_000
GDP = 194_800_000_000
englishShortName = "Czechia"
frenchShortName = "Tchéquie (la)"
numeric = 203
japaneseShortName = "チェコ共和国"

[CD]
"Country Name" = "Democratic Republic of the Congo"
ISO2 = "CD"
ISO3 = "COD"
"Top Level Domain" = "cd"
FIPS = "CG"
"ISO Numeric" = 180
GeoNameID = 203_312
E164 = 243
"Phone Code" = 243
Continent = "Africa"
Capital = "Kinshasa"
"Time Zone in Capital" = "Africa/Lagos"
Currency = "Franc"
"Language Codes" = "fr-CD,ln,kg"
Languages = "French (official), Lingala (a lingua franca trade language), Kingwana (a dialect of Kiswahili or Swahili), Kikongo, Tshiluba"
"Area KM2" = 2_345_410
"Internet Hosts" = 2_515
"Internet Users" = 290_000
"Phones (Mobile)" = 19_487_000
"Phones (Landline)" = 58_200
GDP = 18_560_000_000
englishShortName = "Congo (the Democratic Republic of the)"
frenchShortName = "Congo (la République démocratique du)"
numeric = 180
japaneseShortName = "コンゴ民主共和国"

[DK]
"Country Name" = "Denmark"
ISO2 = "DK"
ISO3 = "DNK"
"Top Level Domain" = "dk"
FIPS = "DA"
"ISO Numeric" = 208
GeoNameID = 2_623_032
E164 = 45
"Phone Code" = 45
Continent = "Europe"
Capital = "Copenhagen"
"Time Zone in Capital" = "Europe/Copenhagen"
Currency = "Krone"
"Language Codes" = "da-DK,en,fo,de-DK"
Languages = "Danish, Faroese, Greenlandic (an Inuit dialect), German (small minority)"
"Area KM2" = 43_094
"Internet Hosts" = 4_297_000
"Internet Users" = 4_750_000
"Phones (Mobile)" = 6_600_000
"Phones (Landline)" = 2_431_000
GDP = 324_300_000_000
englishShortName = "Denmark"
frenchShortName = "Danemark (le)"
numeric = 208
japaneseShortName = "デンマーク"

[DJ]
"Country Name" = "Djibouti"
ISO2 = "DJ"
ISO3 = "DJI"
"Top Level Domain" = "dj"
FIPS = "DJ"
"ISO Numeric" = 262
GeoNameID = 223_816
E164 = 253
"Phone Code" = 253
Continent = "Africa"
Capital = "Djibouti"
"Time Zone in Capital" = "Africa/Djibouti"
Currency = "Franc"
"Language Codes" = "fr-DJ,ar,so-DJ,aa"
Languages = "French (official), Arabic (official), Somali, Afar"
"Area KM2" = 23_000
"Internet Hosts" = 215
"Internet Users" = 25_900
"Phones (Mobile)" = 209_000
"Phones (Landline)" = 18_000
GDP = 1_459_000_000
englishShortName = "Djibouti"
frenchShortName = "Djibouti"
numeric = 262
japaneseShortName = "ジブチ"

[DM]
"Country Name" = "Dominica"
ISO2 = "DM"
ISO3 = "DMA"
"Top Level Domain" = "dm"
FIPS = "DO"
"ISO Numeric" = 212
GeoNameID = 3_575_830
E164 = 1
"Phone Code" = "1-767"
Continent = "North America"
Capital = "Roseau"
"Time Zone in Capital" = "America/Port_of_Spain"
Currency = "Dollar"
"Language Codes" = "en-DM"
Languages = "English (official), French patois"
"Area KM2" = 754
"Internet Hosts" = 723
"Internet Users" = 28_000
"Phones (Mobile)" = 109_300
"Phones (Landline)" = 14_600
GDP = 495_000_000
englishShortName = "Dominica"
frenchShortName = "Dominique (la)"
numeric = 212
japaneseShortName = "ドミニカ"

[DO]
"Country Name" = "Dominican Republic"
ISO2 = "DO"
ISO3 = "DOM"
"Top Level Domain" = "do"
FIPS = "DR"
"ISO Numeric" = 214
GeoNameID = 3_508_796
E164 = 1
"Phone Code" = "1-809, 1-829, 1-849"
Continent = "North America"
Capital = "Santo Domingo"
"Time Zone in Capital" = "America/Santo_Domingo"
Currency = "Peso"
"Language Codes" = "es-DO"
Languages = "Spanish (official)"
"Area KM2" = 48_730
"Internet Hosts" = 404_500
"Internet Users" = 2_701_000
"Phones (Mobile)" = 9_038_000
"Phones (Landline)" = 1_065_000
GDP = 59_270_000_000
englishShortName = "Dominican Republic (the)"
frenchShortName = "dominicaine (la République)"
numeric = 214
japaneseShortName = "ドミニカ共和国"

[TL]
"Country Name" = "East Timor"
ISO2 = "TL"
ISO3 = "TLS"
"Top Level Domain" = "tl"
FIPS = "TT"
"ISO Numeric" = 626
GeoNameID = 1_966_436
E164 = 670
"Phone Code" = 670
Continent = "Oceania"
Capital = "Dili"
"Time Zone in Capital" = "Asia/Dili"
Currency = "Dollar"
"Language Codes" = "tet,pt-TL,id,en"
Languages = "Tetum (official), Portuguese (official), Indonesian, English"
"Area KM2" = 15_007
"Internet Hosts" = 252
"Internet Users" = 2_100
"Phones (Mobile)" = 621_000
"Phones (Landline)" = 3_000
GDP = 6_129_000_000
englishShortName = "Timor-Leste"
frenchShortName = "Timor-Leste (le)"
numeric = 626
japaneseShortName = "東ティモール"

[EC]
"Country Name" = "Ecuador"
ISO2 = "EC"
ISO3 = "ECU"
"Top Level Domain" = "ec"
FIPS = "EC"
"ISO Numeric" = 218
GeoNameID = 3_658_394
E164 = 593
"Phone Code" = 593
Continent = "South America"
Capital = "Quito"
"Time Zone in Capital" = "America/Guayaquil"
Currency = "Dollar"
"Language Codes" = "es-EC"
Languages = "Spanish (Castillian) 93% (official), Quechua 4.1%, other indigenous 0.7%, foreign 2.2%"
"Area KM2" = 283_560
"Internet Hosts" = 170_538
"Internet Users" = 3_352_000
"Phones (Mobile)" = 16_457_000
"Phones (Landline)" = 2_310_000
GDP = 91_410_000_000
englishShortName = "Ecuador"
frenchShortName = "Équateur (l')"
numeric = 218
japaneseShortName = "エクアドル"

[EG]
"Country Name" = "Egypt"
ISO2 = "EG"
ISO3 = "EGY"
"Top Level Domain" = "eg"
FIPS = "EG"
"ISO Numeric" = 818
GeoNameID = 357_994
E164 = 20
"Phone Code" = 20
Continent = "Africa"
Capital = "Cairo"
"Time Zone in Capital" = "Africa/Cairo"
Currency = "Pound"
"Language Codes" = "ar-EG,en,fr"
Languages = "Arabic (official), English and French widely understood by educated classes"
"Area KM2" = 1_001_450
"Internet Hosts" = 200_430
"Internet Users" = 20_136_000
"Phones (Mobile)" = 96_800_000
"Phones (Landline)" = 8_557_000
GDP = 262_000_000_000
englishShortName = "Egypt"
frenchShortName = "Égypte (l')"
numeric = 818
japaneseShortName = "エジプト"

[SV]
"Country Name" = "El Salvador"
ISO2 = "SV"
ISO3 = "SLV"
"Top Level Domain" = "sv"
FIPS = "ES"
"ISO Numeric" = 222
GeoNameID = 3_585_968
E164 = 503
"Phone Code" = 503
Continent = "North America"
Capital = "San Salvador"
"Time Zone in Capital" = "America/El_Salvador"
Currency = "Dollar"
"Language Codes" = "es-SV"
Languages = "Spanish (official), Nahua (among some Amerindians)"
"Area KM2" = 21_040
"Internet Hosts" = 24_070
"Internet Users" = 746_000
"Phones (Mobile)" = 8_650_000
"Phones (Landline)" = 1_060_000
GDP = 24_670_000_000
englishShortName = "El Salvador"
frenchShortName = "El Salvador"
numeric = 222
japaneseShortName = "エルサルバドル"

[GQ]
"Country Name" = "Equatorial Guinea"
ISO2 = "GQ"
ISO3 = "GNQ"
"Top Level Domain" = "gq"
FIPS = "EK"
"ISO Numeric" = 226
GeoNameID = 2_309_096
E164 = 240
"Phone Code" = 240
Continent = "Africa"
Capital = "Malabo"
"Time Zone in Capital" = "Africa/Lagos"
Currency = "Franc"
"Language Codes" = "es-GQ,fr"
Languages = "Spanish (official) 67.6%, other (includes French (official), Fang, Bubi) 32.4% (1994 census)"
"Area KM2" = 28_051
"Internet Hosts" = 7
"Internet Users" = 14_400
"Phones (Mobile)" = 501_000
"Phones (Landline)" = 14_900
GDP = 17_080_000_000
englishShortName = "Equatorial Guinea"
frenchShortName = "Guinée équatoriale (la)"
numeric = 226
japaneseShortName = "赤道ギニア"

[ER]
"Country Name" = "Eritrea"
ISO2 = "ER"
ISO3 = "ERI"
"Top Level Domain" = "er"
FIPS = "ER"
"ISO Numeric" = 232
GeoNameID = 338_010
E164 = 291
"Phone Code" = 291
Continent = "Africa"
Capital = "Asmara"
"Time Zone in Capital" = "Africa/Asmara"
Currency = "Nakfa"
"Language Codes" = "aa-ER,ar,tig,kun,ti-ER"
Languages = "Tigrinya (official), Arabic (official), English (official), Tigre, Kunama, Afar, other Cushitic languages"
"Area KM2" = 121_320
"Internet Hosts" = 701
"Internet Users" = 200_000
"Phones (Mobile)" = 305_300
"Phones (Landline)" = 60_000
GDP = 3_438_000_000
englishShortName = "Eritrea"
frenchShortName = "Érythrée (l')"
numeric = 232
japaneseShortName = "エリトリア"

[EE]
"Country Name" = "Estonia"
ISO2 = "EE"
ISO3 = "EST"
"Top Level Domain" = "ee"
FIPS = "EN"
"ISO Numeric" = 233
GeoNameID = 453_733
E164 = 372
"Phone Code" = 372
Continent = "Europe"
Capital = "Tallinn"
"Time Zone in Capital" = "Europe/Tallinn"
Currency = "Euro"
"Language Codes" = "et,ru"
Languages = "Estonian (official) 68.5%, Russian 29.6%, Ukrainian 0.6%, other 1.2%, unspecified 0.1% (2011 est.)"
"Area KM2" = 45_226
"Internet Hosts" = 865_494
"Internet Users" = 971_700
"Phones (Mobile)" = 2_070_000
"Phones (Landline)" = 448_200
GDP = 24_280_000_000
englishShortName = "Estonia"
frenchShortName = "Estonie (l')"
numeric = 233
japaneseShortName = "エストニア"

[ET]
"Country Name" = "Ethiopia"
ISO2 = "ET"
ISO3 = "ETH"
"Top Level Domain" = "et"
FIPS = "ET"
"ISO Numeric" = 231
GeoNameID = 337_996
E164 = 251
"Phone Code" = 251
Continent = "Africa"
Capital = "Addis Ababa"
"Time Zone in Capital" = "Africa/Addis_Ababa"
Currency = "Birr"
"Language Codes" = "am,en-ET,om-ET,ti-ET,so-ET,sid"
Languages = "Oromo (official working language in the State of Oromiya) 33.8%, Amharic (official national language) 29.3%, Somali (official working language of the State of Sumale) 6.2%, Tigrigna (Tigrinya) (official working language of the State of Tigray) 5.9%, Sidamo 4%, Wolaytta 2.2%, Gurage 2%, Afar (official working language of the State of Afar) 1.7%, Hadiyya 1.7%, Gamo 1.5%, Gedeo 1.3%, Opuuo 1.2%, Kafa 1.1%, other 8.1%, English (major foreign language taught in schools), Arabic (2007 est.)"
"Area KM2" = 1_127_127
"Internet Hosts" = 179
"Internet Users" = 447_300
"Phones (Mobile)" = 20_524_000
"Phones (Landline)" = 797_500
GDP = 47_340_000_000
englishShortName = "Ethiopia"
frenchShortName = "Éthiopie (l')"
numeric = 231
japaneseShortName = "エチオピア"

[FK]
"Country Name" = "Falkland Islands"
ISO2 = "FK"
ISO3 = "FLK"
"Top Level Domain" = "fk"
FIPS = "FK"
"ISO Numeric" = 238
GeoNameID = 3_474_414
E164 = 500
"Phone Code" = 500
Continent = "South America"
Capital = "Stanley"
"Time Zone in Capital" = "Atlantic/Stanley"
Currency = "Pound"
"Language Codes" = "en-FK"
Languages = "English 89%, Spanish 7.7%, other 3.3% (2006 est.)"
"Area KM2" = 12_173
"Internet Hosts" = 110
"Internet Users" = 2_900
"Phones (Mobile)" = 3_450
"Phones (Landline)" = 1_980
GDP = 164_500_000
englishShortName = "Falkland Islands (the) [Malvinas]"
frenchShortName = "Falkland (les Îles)/Malouines (les Îles)"
numeric = 238
japaneseShortName = "フォークランド諸島(マルビナス)"

[FO]
"Country Name" = "Faroe Islands"
ISO2 = "FO"
ISO3 = "FRO"
"Top Level Domain" = "fo"
FIPS = "FO"
"ISO Numeric" = 234
GeoNameID = 2_622_320
E164 = 298
"Phone Code" = 298
Continent = "Europe"
Capital = "Torshavn"
"Time Zone in Capital" = "Atlantic/Faroe"
Currency = "Krone"
"Language Codes" = "fo,da-FO"
Languages = "Faroese (derived from Old Norse), Danish"
"Area KM2" = 1_399
"Internet Hosts" = 7_575
"Internet Users" = 37_500
"Phones (Mobile)" = 61_000
"Phones (Landline)" = 24_000
GDP = 2_320_000_000
englishShortName = "Faroe Islands (the)"
frenchShortName = "Féroé (les Îles)"
numeric = 234
japaneseShortName = "フェロー諸島"

[FJ]
"Country Name" = "Fiji"
ISO2 = "FJ"
ISO3 = "FJI"
"Top Level Domain" = "fj"
FIPS = "FJ"
"ISO Numeric" = 242
GeoNameID = 2_205_218
E164 = 679
"Phone Code" = 679
Continent = "Oceania"
Capital = "Suva"
"Time Zone in Capital" = "Pacific/Fiji"
Currency = "Dollar"
"Language Codes" = "en-FJ,fj"
Languages = "English (official), Fijian (official), Hindustani"
"Area KM2" = 18_270
"Internet Hosts" = 21_739
"Internet Users" = 114_200
"Phones (Mobile)" = 858_800
"Phones (Landline)" = 88_400
GDP = 4_218_000_000
englishShortName = "Fiji"
frenchShortName = "Fidji (les)"
numeric = 242
japaneseShortName = "フィジー"

[FI]
"Country Name" = "Finland"
ISO2 = "FI"
ISO3 = "FIN"
"Top Level Domain" = "fi"
FIPS = "FI"
"ISO Numeric" = 246
GeoNameID = 660_013
E164 = 358
"Phone Code" = 358
Continent = "Europe"
Capital = "Helsinki"
"Time Zone in Capital" = "Europe/Helsinki"
Currency = "Euro"
"Language Codes" = "fi-FI,sv-FI,smn"
Languages = "Finnish (official) 94.2%, Swedish (official) 5.5%, other (small Sami- and Russian-speaking minorities) 0.2% (2012 est.)"
"Area KM2" = 337_030
"Internet Hosts" = 4_763_000
"Internet Users" = 4_393_000
"Phones (Mobile)" = 9_320_000
"Phones (Landline)" = 890_000
GDP = 259_600_000_000
englishShortName = "Finland"
frenchShortName = "Finlande (la)"
numeric = 246
japaneseShortName = "フィンランド"

[FR]
"Country Name" = "France"
ISO2 = "FR"
ISO3 = "FRA"
"Top Level Domain" = "fr"
FIPS = "FR"
"ISO Numeric" = 250
GeoNameID = 3_017_382
E164 = 33
"Phone Code" = 33
Continent = "Europe"
Capital = "Paris"
"Time Zone in Capital" = "Europe/Paris"
Currency = "Euro"
"Language Codes" = "fr-FR,frp,br,co,ca,eu,oc"
Languages = "French (official) 100%, rapidly declining regional dialects and languages (Provencal, Breton, Alsatian, Corsican, Catalan, Basque, Flemish)"
"Area KM2" = 547_030
"Internet Hosts" = 17_266_000
"Internet Users" = 45_262_000
"Phones (Mobile)" = 62_280_000
"Phones (Landline)" = 39_290_000
GDP = 2_739_000_000_000
englishShortName = "France"
frenchShortName = "France (la)"
numeric = 250
japaneseShortName = "フランス"

[PF]
"Country Name" = "French Polynesia"
ISO2 = "PF"
ISO3 = "PYF"
"Top Level Domain" = "pf"
FIPS = "FP"
"ISO Numeric" = 258
GeoNameID = 4_030_656
E164 = 689
"Phone Code" = 689
Continent = "Oceania"
Capital = "Papeete"
"Time Zone in Capital" = "Pacific/Tahiti"
Currency = "Franc"
"Language Codes" = "fr-PF,ty"
Languages = "French (official) 61.1%, Polynesian (official) 31.4%, Asian languages 1.2%, other 0.3%, unspecified 6% (2002 census)"
"Area KM2" = 4_167
"Internet Hosts" = 37_949
"Internet Users" = 120_000
"Phones (Mobile)" = 226_000
"Phones (Landline)" = 55_000
GDP = 5_650_000_000
englishShortName = "French Polynesia"
frenchShortName = "Polynésie française (la)"
numeric = 258
japaneseShortName = "フランス領ポリネシア"

[GA]
"Country Name" = "Gabon"
ISO2 = "GA"
ISO3 = "GAB"
"Top Level Domain" = "ga"
FIPS = "GB"
"ISO Numeric" = 266
GeoNameID = 2_400_553
E164 = 241
"Phone Code" = 241
Continent = "Africa"
Capital = "Libreville"
"Time Zone in Capital" = "Africa/Lagos"
Currency = "Franc"
"Language Codes" = "fr-GA"
Languages = "French (official), Fang, Myene, Nzebi, Bapounou/Eschira, Bandjabi"
"Area KM2" = 267_667
"Internet Hosts" = 127
"Internet Users" = 98_800
"Phones (Mobile)" = 2_930_000
"Phones (Landline)" = 17_000
GDP = 19_970_000_000
englishShortName = "Gabon"
frenchShortName = "Gabon (le)"
numeric = 266
japaneseShortName = "ガボン"

[GM]
"Country Name" = "Gambia"
ISO2 = "GM"
ISO3 = "GMB"
"Top Level Domain" = "gm"
FIPS = "GA"
"ISO Numeric" = 270
GeoNameID = 2_413_451
E164 = 220
"Phone Code" = 220
Continent = "Africa"
Capital = "Banjul"
"Time Zone in Capital" = "Africa/Abidjan"
Currency = "Dalasi"
"Language Codes" = "en-GM,mnk,wof,wo,ff"
Languages = "English (official), Mandinka, Wolof, Fula, other indigenous vernaculars"
"Area KM2" = 11_300
"Internet Hosts" = 656
"Internet Users" = 130_100
"Phones (Mobile)" = 1_526_000
"Phones (Landline)" = 64_200
GDP = 896_000_000
englishShortName = "Gambia (the)"
frenchShortName = "Gambie (la)"
numeric = 270
japaneseShortName = "ガンビア"

[GE]
"Country Name" = "Georgia"
ISO2 = "GE"
ISO3 = "GEO"
"Top Level Domain" = "ge"
FIPS = "GG"
"ISO Numeric" = 268
GeoNameID = 614_540
E164 = 995
"Phone Code" = 995
Continent = "Asia"
Capital = "Tbilisi"
"Time Zone in Capital" = "Asia/Tbilisi"
Currency = "Lari"
"Language Codes" = "ka,ru,hy,az"
Languages = "Georgian (official) 71%, Russian 9%, Armenian 7%, Azeri 6%, other 7%"
"Area KM2" = 69_700
"Internet Hosts" = 357_864
"Internet Users" = 1_300_000
"Phones (Mobile)" = 4_699_000
"Phones (Landline)" = 1_276_000
GDP = 15_950_000_000
englishShortName = "Georgia"
frenchShortName = "Géorgie (la)"
numeric = 268
japaneseShortName = "ジョージア"

[DE]
"Country Name" = "Germany"
ISO2 = "DE"
ISO3 = "DEU"
"Top Level Domain" = "de"
FIPS = "GM"
"ISO Numeric" = 276
GeoNameID = 2_921_044
E164 = 49
"Phone Code" = 49
Continent = "Europe"
Capital = "Berlin"
"Time Zone in Capital" = "Europe/Berlin"
Currency = "Euro"
"Language Codes" = "de"
Languages = "German (official)"
"Area KM2" = 357_021
"Internet Hosts" = 20_043_000
"Internet Users" = 65_125_000
"Phones (Mobile)" = 107_700_000
"Phones (Landline)" = 50_700_000
GDP = 3_593_000_000_000
englishShortName = "Germany"
frenchShortName = "Allemagne (l')"
numeric = 276
japaneseShortName = "ドイツ"

[GH]
"Country Name" = "Ghana"
ISO2 = "GH"
ISO3 = "GHA"
"Top Level Domain" = "gh"
FIPS = "GH"
"ISO Numeric" = 288
GeoNameID = 2_300_660
E164 = 233
"Phone Code" = 233
Continent = "Africa"
Capital = "Accra"
"Time Zone in Capital" = "Africa/Accra"
Currency = "Cedi"
"Language Codes" = "en-GH,ak,ee,tw"
Languages = "Asante 14.8%, Ewe 12.7%, Fante 9.9%, Boron (Brong) 4.6%, Dagomba 4.3%, Dangme 4.3%, Dagarte (Dagaba) 3.7%, Akyem 3.4%, Ga 3.4%, Akuapem 2.9%, other (includes English (official)) 36.1% (2000 census)"
"Area KM2" = 239_460
"Internet Hosts" = 59_086
"Internet Users" = 1_297_000
"Phones (Mobile)" = 25_618_000
"Phones (Landline)" = 285_000
GDP = 45_550_000_000
englishShortName = "Ghana"
frenchShortName = "Ghana (le)"
numeric = 288
japaneseShortName = "ガーナ"

[GI]
"Country Name" = "Gibraltar"
ISO2 = "GI"
ISO3 = "GIB"
"Top Level Domain" = "gi"
FIPS = "GI"
"ISO Numeric" = 292
GeoNameID = 2_411_586
E164 = 350
"Phone Code" = 350
Continent = "Europe"
Capital = "Gibraltar"
"Time Zone in Capital" = "Europe/Gibraltar"
Currency = "Pound"
"Language Codes" = "en-GI,es,it,pt"
Languages = "English (used in schools and for official purposes), Spanish, Italian, Portuguese"
"Area KM2" = 7
"Internet Hosts" = 3_509
"Internet Users" = 20_200
"Phones (Mobile)" = 34_750
"Phones (Landline)" = 23_100
GDP = 1_106_000_000
englishShortName = "Gibraltar"
frenchShortName = "Gibraltar"
numeric = 292
japaneseShortName = "ジブラルタル"

[GR]
"Country Name" = "Greece"
ISO2 = "GR"
ISO3 = "GRC"
"Top Level Domain" = "gr"
FIPS = "GR"
"ISO Numeric" = 300
GeoNameID = 390_903
E164 = 30
"Phone Code" = 30
Continent = "Europe"
Capital = "Athens"
"Time Zone in Capital" = "Europe/Athens"
Currency = "Euro"
"Language Codes" = "el-GR,en,fr"
Languages = "Greek (official) 99%, other (includes English and French) 1%"
"Area KM2" = 131_940
"Internet Hosts" = 3_201_000
"Internet Users" = 4_971_000
"Phones (Mobile)" = 13_354_000
"Phones (Landline)" = 5_461_000
GDP = 243_300_000_000
englishShortName = "Greece"
frenchShortName = "Grèce (la)"
numeric = 300
japaneseShortName = "ギリシャ"

[GL]
"Country Name" = "Greenland"
ISO2 = "GL"
ISO3 = "GRL"
"Top Level Domain" = "gl"
FIPS = "GL"
"ISO Numeric" = 304
GeoNameID = 3_425_505
E164 = 299
"Phone Code" = 299
Continent = "North America"
Capital = "Nuuk"
"Time Zone in Capital" = "America/Godthab"
Currency = "Krone"
"Language Codes" = "kl,da-GL,en"
Languages = "Greenlandic (East Inuit) (official), Danish (official), English"
"Area KM2" = 2_166_086
"Internet Hosts" = 15_645
"Internet Users" = 36_000
"Phones (Mobile)" = 59_455
"Phones (Landline)" = 18_900
GDP = 2_160_000_000
englishShortName = "Greenland"
frenchShortName = "Groenland (le)"
numeric = 304
japaneseShortName = "グリーンランド"

[GD]
"Country Name" = "Grenada"
ISO2 = "GD"
ISO3 = "GRD"
"Top Level Domain" = "gd"
FIPS = "GJ"
"ISO Numeric" = 308
GeoNameID = 3_580_239
E164 = 1
"Phone Code" = "1-473"
Continent = "North America"
Capital = "St. George's"
"Time Zone in Capital" = "America/Port_of_Spain"
Currency = "Dollar"
"Language Codes" = "en-GD"
Languages = "English (official), French patois"
"Area KM2" = 344
"Internet Hosts" = 80
"Internet Users" = 25_000
"Phones (Mobile)" = 128_000
"Phones (Landline)" = 28_500
GDP = 811_000_000
englishShortName = "Grenada"
frenchShortName = "Grenade (la)"
numeric = 308
japaneseShortName = "グレナダ"

[GU]
"Country Name" = "Guam"
ISO2 = "GU"
ISO3 = "GUM"
"Top Level Domain" = "gu"
FIPS = "GQ"
"ISO Numeric" = 316
GeoNameID = 4_043_988
E164 = 1
"Phone Code" = "1-671"
Continent = "Oceania"
Capital = "Hagatna"
"Time Zone in Capital" = "Pacific/Guam"
Currency = "Dollar"
"Language Codes" = "en-GU,ch-GU"
Languages = "English 43.6%, Filipino 21.2%, Chamorro 17.8%, other Pacific island languages 10%, Asian languages 6.3%, other 1.1% (2010 est.)"
"Area KM2" = 549
"Internet Hosts" = 23
"Internet Users" = 90_000
"Phones (Mobile)" = 98_000
"Phones (Landline)" = 67_000
GDP = 4_600_000_000
englishShortName = "Guam"
frenchShortName = "Guam"
numeric = 316
japaneseShortName = "グアム島"

[GT]
"Country Name" = "Guatemala"
ISO2 = "GT"
ISO3 = "GTM"
"Top Level Domain" = "gt"
FIPS = "GT"
"ISO Numeric" = 320
GeoNameID = 3_595_528
E164 = 502
"Phone Code" = 502
Continent = "North America"
Capital = "Guatemala City"
"Time Zone in Capital" = "America/Guatemala"
Currency = "Quetzal"
"Language Codes" = "es-GT"
Languages = "Spanish (official) 60%, Amerindian languages 40%"
"Area KM2" = 108_890
"Internet Hosts" = 357_552
"Internet Users" = 2_279_000
"Phones (Mobile)" = 20_787_000
"Phones (Landline)" = 1_744_000
GDP = 53_900_000_000
englishShortName = "Guatemala"
frenchShortName = "Guatemala (le)"
numeric = 320
japaneseShortName = "グアテマラ"

[GG]
"Country Name" = "Guernsey"
ISO2 = "GG"
ISO3 = "GGY"
"Top Level Domain" = "gg"
FIPS = "GK"
"ISO Numeric" = 831
GeoNameID = 3_042_362
E164 = 44
"Phone Code" = "44-1481"
Continent = "Europe"
Capital = "St Peter Port"
"Time Zone in Capital" = "Europe/London"
Currency = "Pound"
"Language Codes" = "en,fr"
Languages = "English, French, Norman-French dialect spoken in country districts"
"Area KM2" = 78
"Internet Hosts" = 239
"Internet Users" = 48_300
"Phones (Mobile)" = 43_800
"Phones (Landline)" = 45_100
GDP = 2_742_000_000
englishShortName = "Guernsey"
frenchShortName = "Guernesey"
numeric = 831
japaneseShortName = "ガーンジー"

[GN]
"Country Name" = "Guinea"
ISO2 = "GN"
ISO3 = "GIN"
"Top Level Domain" = "gn"
FIPS = "GV"
"ISO Numeric" = 324
GeoNameID = 2_420_477
E164 = 224
"Phone Code" = 224
Continent = "Africa"
Capital = "Conakry"
"Time Zone in Capital" = "Africa/Abidjan"
Currency = "Franc"
"Language Codes" = "fr-GN"
Languages = "French (official)"
"Area KM2" = 245_857
"Internet Hosts" = 15
"Internet Users" = 95_000
"Phones (Mobile)" = 4_781_000
"Phones (Landline)" = 18_000
GDP = 6_544_000_000
englishShortName = "Guinea"
frenchShortName = "Guinée (la)"
numeric = 324
japaneseShortName = "ギニア"

[GW]
"Country Name" = "Guinea-Bissau"
ISO2 = "GW"
ISO3 = "GNB"
"Top Level Domain" = "gw"
FIPS = "PU"
"ISO Numeric" = 624
GeoNameID = 2_372_248
E164 = 245
"Phone Code" = 245
Continent = "Africa"
Capital = "Bissau"
"Time Zone in Capital" = "Africa/Bissau"
Currency = "Franc"
"Language Codes" = "pt-GW,pov"
Languages = "Portuguese (official), Crioulo, African languages"
"Area KM2" = 36_120
"Internet Hosts" = 90
"Internet Users" = 37_100
"Phones (Mobile)" = 1_100_000
"Phones (Landline)" = 5_000
GDP = 880_000_000
englishShortName = "Guinea-Bissau"
frenchShortName = "Guinée-Bissau (la)"
numeric = 624
japaneseShortName = "ギニアビサウ"

[GY]
"Country Name" = "Guyana"
ISO2 = "GY"
ISO3 = "GUY"
"Top Level Domain" = "gy"
FIPS = "GY"
"ISO Numeric" = 328
GeoNameID = 3_378_535
E164 = 592
"Phone Code" = 592
Continent = "South America"
Capital = "Georgetown"
"Time Zone in Capital" = "America/Guyana"
Currency = "Dollar"
"Language Codes" = "en-GY"
Languages = "English, Amerindian dialects, Creole, Caribbean Hindustani (a dialect of Hindi), Urdu"
"Area KM2" = 214_970
"Internet Hosts" = 24_936
"Internet Users" = 189_600
"Phones (Mobile)" = 547_000
"Phones (Landline)" = 154_200
GDP = 3_020_000_000
englishShortName = "Guyana"
frenchShortName = "Guyana (le)"
numeric = 328
japaneseShortName = "ガイアナ"

[HT]
"Country Name" = "Haiti"
ISO2 = "HT"
ISO3 = "HTI"
"Top Level Domain" = "ht"
FIPS = "HA"
"ISO Numeric" = 332
GeoNameID = 3_723_988
E164 = 509
"Phone Code" = 509
Continent = "North America"
Capital = "Port-au-Prince"
"Time Zone in Capital" = "America/Port-au-Prince"
Currency = "Gourde"
"Language Codes" = "ht,fr-HT"
Languages = "French (official), Creole (official)"
"Area KM2" = 27_750
"Internet Hosts" = 555
"Internet Users" = 1_000_000
"Phones (Mobile)" = 6_095_000
"Phones (Landline)" = 50_000
GDP = 8_287_000_000
englishShortName = "Haiti"
frenchShortName = "Haïti"
numeric = 332
japaneseShortName = "ハイチ"

[HN]
"Country Name" = "Honduras"
ISO2 = "HN"
ISO3 = "HND"
"Top Level Domain" = "hn"
FIPS = "HO"
"ISO Numeric" = 340
GeoNameID = 3_608_932
E164 = 504
"Phone Code" = 504
Continent = "North America"
Capital = "Tegucigalpa"
"Time Zone in Capital" = "America/Tegucigalpa"
Currency = "Lempira"
"Language Codes" = "es-HN"
Languages = "Spanish (official), Amerindian dialects"
"Area KM2" = 112_090
"Internet Hosts" = 30_955
"Internet Users" = 731_700
"Phones (Mobile)" = 7_370_000
"Phones (Landline)" = 610_000
GDP = 18_880_000_000
englishShortName = "Honduras"
frenchShortName = "Honduras (le)"
numeric = 340
japaneseShortName = "ホンジュラス"

[HK]
"Country Name" = "Hong Kong"
ISO2 = "HK"
ISO3 = "HKG"
"Top Level Domain" = "hk"
FIPS = "HK"
"ISO Numeric" = 344
GeoNameID = 1_819_730
E164 = 852
"Phone Code" = 852
Continent = "Asia"
Capital = "Hong Kong"
"Time Zone in Capital" = "Asia/Hong_Kong"
Currency = "Dollar"
"Language Codes" = "zh-HK,yue,zh,en"
Languages = "Cantonese (official) 89.5%, English (official) 3.5%, Putonghua (Mandarin) 1.4%, other Chinese dialects 4%, other 1.6% (2011 est.)"
"Area KM2" = 1_092
"Internet Hosts" = 870_041
"Internet Users" = 4_873_000
"Phones (Mobile)" = 16_403_000
"Phones (Landline)" = 4_362_000
GDP = 272_100_000_000
englishShortName = "Hong Kong"
frenchShortName = "Hong Kong"
numeric = 344
japaneseShortName = "香港"

[HU]
"Country Name" = "Hungary"
ISO2 = "HU"
ISO3 = "HUN"
"Top Level Domain" = "hu"
FIPS = "HU"
"ISO Numeric" = 348
GeoNameID = 719_819
E164 = 36
"Phone Code" = 36
Continent = "Europe"
Capital = "Budapest"
"Time Zone in Capital" = "Europe/Budapest"
Currency = "Forint"
"Language Codes" = "hu-HU"
Languages = "Hungarian (official) 99.6%, English 16%, German 11.2%, Russian 1.6%, Romanian 1.3%, French 1.2%, other 4.2%"
"Area KM2" = 93_030
"Internet Hosts" = 3_145_000
"Internet Users" = 6_176_000
"Phones (Mobile)" = 11_580_000
"Phones (Landline)" = 2_960_000
GDP = 130_600_000_000
englishShortName = "Hungary"
frenchShortName = "Hongrie (la)"
numeric = 348
japaneseShortName = "ハンガリー"

[IS]
"Country Name" = "Iceland"
ISO2 = "IS"
ISO3 = "ISL"
"Top Level Domain" = "is"
FIPS = "IC"
"ISO Numeric" = 352
GeoNameID = 2_629_691
E164 = 354
"Phone Code" = 354
Continent = "Europe"
Capital = "Reykjavik"
"Time Zone in Capital" = "Atlantic/Reykjavik"
Currency = "Krona"
"Language Codes" = "is,en,de,da,sv,no"
Languages = "Icelandic, English, Nordic languages, German widely spoken"
"Area KM2" = 103_000
"Internet Hosts" = 369_969
"Internet Users" = 301_600
"Phones (Mobile)" = 346_000
"Phones (Landline)" = 189_000
GDP = 14_590_000_000
englishShortName = "Iceland"
frenchShortName = "Islande (l')"
numeric = 352
japaneseShortName = "アイスランド"

[IN]
"Country Name" = "India"
ISO2 = "IN"
ISO3 = "IND"
"Top Level Domain" = "in"
FIPS = "IN"
"ISO Numeric" = 356
GeoNameID = 1_269_750
E164 = 91
"Phone Code" = 91
Continent = "Asia"
Capital = "New Delhi"
"Time Zone in Capital" = "Asia/Kolkata"
Currency = "Rupee"
"Language Codes" = "en-IN,hi,bn,te,mr,ta,ur,gu,kn,ml,or,pa,as,bh,sat,ks,ne,sd,kok,doi,mni,sit,sa,fr,lus,inc"
Languages = "Hindi 41%, Bengali 8.1%, Telugu 7.2%, Marathi 7%, Tamil 5.9%, Urdu 5%, Gujarati 4.5%, Kannada 3.7%, Malayalam 3.2%, Oriya 3.2%, Punjabi 2.8%, Assamese 1.3%, Maithili 1.2%, other 5.9%"
"Area KM2" = 3_287_590
"Internet Hosts" = 6_746_000
"Internet Users" = 61_338_000
"Phones (Mobile)" = 893_862_000
"Phones (Landline)" = 31_080_000
GDP = 1_670_000_000_000
englishShortName = "India"
frenchShortName = "Inde (l')"
numeric = 356
japaneseShortName = "インド"

[ID]
"Country Name" = "Indonesia"
ISO2 = "ID"
ISO3 = "IDN"
"Top Level Domain" = "id"
FIPS = "ID"
"ISO Numeric" = 360
GeoNameID = 1_643_084
E164 = 62
"Phone Code" = 62
Continent = "Asia"
Capital = "Jakarta"
"Time Zone in Capital" = "Asia/Jakarta"
Currency = "Rupiah"
"Language Codes" = "id,en,nl,jv"
Languages = "Bahasa Indonesia (official, modified form of Malay), English, Dutch, local dialects (of which the most widely spoken is Javanese)"
"Area KM2" = 1_919_440
"Internet Hosts" = 1_344_000
"Internet Users" = 20_000_000
"Phones (Mobile)" = 281_960_000
"Phones (Landline)" = 37_983_000
GDP = 867_500_000_000
englishShortName = "Indonesia"
frenchShortName = "Indonésie (l')"
numeric = 360
japaneseShortName = "インドネシア"

[IR]
"Country Name" = "Iran"
ISO2 = "IR"
ISO3 = "IRN"
"Top Level Domain" = "ir"
FIPS = "IR"
"ISO Numeric" = 364
GeoNameID = 130_758
E164 = 98
"Phone Code" = 98
Continent = "Asia"
Capital = "Tehran"
"Time Zone in Capital" = "Asia/Tehran"
Currency = "Rial"
"Language Codes" = "fa-IR,ku"
Languages = "Persian (official) 53%, Azeri Turkic and Turkic dialects 18%, Kurdish 10%, Gilaki and Mazandarani 7%, Luri 6%, Balochi 2%, Arabic 2%, other 2%"
"Area KM2" = 1_648_000
"Internet Hosts" = 197_804
"Internet Users" = 8_214_000
"Phones (Mobile)" = 58_160_000
"Phones (Landline)" = 28_760_000
GDP = 411_900_000_000
englishShortName = "Iran (Islamic Republic of)"
frenchShortName = "Iran (République Islamique d')"
numeric = 364
japaneseShortName = "イラン"

[IQ]
"Country Name" = "Iraq"
ISO2 = "IQ"
ISO3 = "IRQ"
"Top Level Domain" = "iq"
FIPS = "IZ"
"ISO Numeric" = 368
GeoNameID = 99_237
E164 = 964
"Phone Code" = 964
Continent = "Asia"
Capital = "Baghdad"
"Time Zone in Capital" = "Asia/Baghdad"
Currency = "Dinar"
"Language Codes" = "ar-IQ,ku,hy"
Languages = "Arabic (official), Kurdish (official), Turkmen (a Turkish dialect) and Assyrian (Neo-Aramaic) are official in areas where they constitute a majority of the population), Armenian"
"Area KM2" = 437_072
"Internet Hosts" = 26
"Internet Users" = 325_900
"Phones (Mobile)" = 26_760_000
"Phones (Landline)" = 1_870_000
GDP = 221_800_000_000
englishShortName = "Iraq"
frenchShortName = "Iraq (l')"
numeric = 368
japaneseShortName = "イラク"

[IE]
"Country Name" = "Ireland"
ISO2 = "IE"
ISO3 = "IRL"
"Top Level Domain" = "ie"
FIPS = "EI"
"ISO Numeric" = 372
GeoNameID = 2_963_597
E164 = 353
"Phone Code" = 353
Continent = "Europe"
Capital = "Dublin"
"Time Zone in Capital" = "Europe/Dublin"
Currency = "Euro"
"Language Codes" = "en-IE,ga-IE"
Languages = "English (official, the language generally used), Irish (Gaelic or Gaeilge) (official, spoken mainly in areas along the western coast)"
"Area KM2" = 70_280
"Internet Hosts" = 1_387_000
"Internet Users" = 3_042_000
"Phones (Mobile)" = 4_906_000
"Phones (Landline)" = 2_007_000
GDP = 220_900_000_000
englishShortName = "Ireland"
frenchShortName = "Irlande (l')"
numeric = 372
japaneseShortName = "アイルランド"

[IM]
"Country Name" = "Isle of Man"
ISO2 = "IM"
ISO3 = "IMN"
"Top Level Domain" = "im"
FIPS = "IM"
"ISO Numeric" = 833
GeoNameID = 3_042_225
E164 = 44
"Phone Code" = "44-1624"
Continent = "Europe"
Capital = "Douglas, Isle of Man"
"Time Zone in Capital" = "Europe/London"
Currency = "Pound"
"Language Codes" = "en,gv"
Languages = "English, Manx Gaelic (about 2% of the population has some knowledge)"
"Area KM2" = 572
"Internet Hosts" = 895
"Internet Users" = ""
"Phones (Mobile)" = ""
"Phones (Landline)" = ""
GDP = 4_076_000_000
englishShortName = "Isle of Man"
frenchShortName = "Île de Man"
numeric = 833
japaneseShortName = "マン島"

[IL]
"Country Name" = "Israel"
ISO2 = "IL"
ISO3 = "ISR"
"Top Level Domain" = "il"
FIPS = "IS"
"ISO Numeric" = 376
GeoNameID = 294_640
E164 = 972
"Phone Code" = 972
Continent = "Asia"
Capital = "Jerusalem"
"Time Zone in Capital" = "Asia/Jerusalem"
Currency = "Shekel"
"Language Codes" = "he,ar-IL,en-IL,"
Languages = "Hebrew (official), Arabic (used officially for Arab minority), English (most commonly used foreign language)"
"Area KM2" = 20_770
"Internet Hosts" = 2_483_000
"Internet Users" = 4_525_000
"Phones (Mobile)" = 9_225_000
"Phones (Landline)" = 3_594_000
GDP = 272_700_000_000
englishShortName = "Israel"
frenchShortName = "Israël"
numeric = 376
japaneseShortName = "イスラエル"

[IT]
"Country Name" = "Italy"
ISO2 = "IT"
ISO3 = "ITA"
"Top Level Domain" = "it"
FIPS = "IT"
"ISO Numeric" = 380
GeoNameID = 3_175_395
E164 = 39
"Phone Code" = 39
Continent = "Europe"
Capital = "Rome"
"Time Zone in Capital" = "Europe/Rome"
Currency = "Euro"
"Language Codes" = "it-IT,de-IT,fr-IT,sc,ca,co,sl"
Languages = "Italian (official), German (parts of Trentino-Alto Adige region are predominantly German-speaking), French (small French-speaking minority in Valle d'Aosta region), Slovene (Slovene-speaking minority in the Trieste-Gorizia area)"
"Area KM2" = 301_230
"Internet Hosts" = 25_662_000
"Internet Users" = 29_235_000
"Phones (Mobile)" = 97_225_000
"Phones (Landline)" = 21_656_000
GDP = 2_068_000_000_000
englishShortName = "Italy"
frenchShortName = "Italie (l')"
numeric = 380
japaneseShortName = "イタリア"

[CI]
"Country Name" = "Ivory Coast"
ISO2 = "CI"
ISO3 = "CIV"
"Top Level Domain" = "ci"
FIPS = "IV"
"ISO Numeric" = 384
GeoNameID = 2_287_781
E164 = 225
"Phone Code" = 225
Continent = "Africa"
Capital = "Yamoussoukro"
"Time Zone in Capital" = "Africa/Abidjan"
Currency = "Franc"
"Language Codes" = "fr-CI"
Languages = "French (official), 60 native dialects of which Dioula is the most widely spoken"
"Area KM2" = 322_460
"Internet Hosts" = 9_115
"Internet Users" = 967_300
"Phones (Mobile)" = 19_827_000
"Phones (Landline)" = 268_000
GDP = 28_280_000_000
englishShortName = "Côte d'Ivoire"
frenchShortName = "Côte d'Ivoire (la)"
numeric = 384
japaneseShortName = "コートジボワール"

[JM]
"Country Name" = "Jamaica"
ISO2 = "JM"
ISO3 = "JAM"
"Top Level Domain" = "jm"
FIPS = "JM"
"ISO Numeric" = 388
GeoNameID = 3_489_940
E164 = 1
"Phone Code" = "1-876"
Continent = "North America"
Capital = "Kingston"
"Time Zone in Capital" = "America/Jamaica"
Currency = "Dollar"
"Language Codes" = "en-JM"
Languages = "English, English patois"
"Area KM2" = 10_991
"Internet Hosts" = 3_906
"Internet Users" = 1_581_000
"Phones (Mobile)" = 2_665_000
"Phones (Landline)" = 265_000
GDP = 14_390_000_000
englishShortName = "Jamaica"
frenchShortName = "Jamaïque (la)"
numeric = 388
japaneseShortName = "ジャマイカ"

[JP]
"Country Name" = "Japan"
ISO2 = "JP"
ISO3 = "JPN"
"Top Level Domain" = "jp"
FIPS = "JA"
"ISO Numeric" = 392
GeoNameID = 1_861_060
E164 = 81
"Phone Code" = 81
Continent = "Asia"
Capital = "Tokyo"
"Time Zone in Capital" = "Asia/Tokyo"
Currency = "Yen"
"Language Codes" = "ja"
Languages = "Japanese"
"Area KM2" = 377_835
"Internet Hosts" = 64_453_000
"Internet Users" = 99_182_000
"Phones (Mobile)" = 138_363_000
"Phones (Landline)" = 64_273_000
GDP = 5_007_000_000_000
englishShortName = "Japan"
frenchShortName = "Japon (le)"
numeric = 392
japaneseShortName = "日本"

[JE]
"Country Name" = "Jersey"
ISO2 = "JE"
ISO3 = "JEY"
"Top Level Domain" = "je"
FIPS = "JE"
"ISO Numeric" = 832
GeoNameID = 3_042_142
E164 = 44
"Phone Code" = "44-1534"
Continent = "Europe"
Capital = "Saint Helier"
"Time Zone in Capital" = "Europe/London"
Currency = "Pound"
"Language Codes" = "en,pt"
Languages = "English 94.5% (official), Portuguese 4.6%, other 0.9% (2001 census)"
"Area KM2" = 116
"Internet Hosts" = 264
"Internet Users" = 29_500
"Phones (Mobile)" = 108_000
"Phones (Landline)" = 73_800
GDP = 5_100_000_000
englishShortName = "Jersey"
frenchShortName = "Jersey"
numeric = 832
japaneseShortName = "ジャージー"

[JO]
"Country Name" = "Jordan"
ISO2 = "JO"
ISO3 = "JOR"
"Top Level Domain" = "jo"
FIPS = "JO"
"ISO Numeric" = 400
GeoNameID = 248_816
E164 = 962
"Phone Code" = 962
Continent = "Asia"
Capital = "Amman"
"Time Zone in Capital" = "Asia/Amman"
Currency = "Dinar"
"Language Codes" = "ar-JO,en"
Languages = "Arabic (official), English (widely understood among upper and middle classes)"
"Area KM2" = 92_300
"Internet Hosts" = 69_473
"Internet Users" = 1_642_000
"Phones (Mobile)" = 8_984_000
"Phones (Landline)" = 435_000
GDP = 34_080_000_000
englishShortName = "Jordan"
frenchShortName = "Jordanie (la)"
numeric = 400
japaneseShortName = "ヨルダン"

[KZ]
"Country Name" = "Kazakhstan"
ISO2 = "KZ"
ISO3 = "KAZ"
"Top Level Domain" = "kz"
FIPS = "KZ"
"ISO Numeric" = 398
GeoNameID = 1_522_867
E164 = 7
"Phone Code" = 7
Continent = "Asia"
Capital = "Astana"
"Time Zone in Capital" = "Asia/Almaty"
Currency = "Tenge"
"Language Codes" = "kk,ru"
Languages = 'Kazakh (official, Qazaq) 64.4%, Russian (official, used in everyday business, designated the "language of interethnic communication") 95% (2001 est.)'
"Area KM2" = 2_717_300
"Internet Hosts" = 67_464
"Internet Users" = 5_299_000
"Phones (Mobile)" = 28_731_000
"Phones (Landline)" = 4_340_000
GDP = 224_900_000_000
englishShortName = "Kazakhstan"
frenchShortName = "Kazakhstan (le)"
numeric = 398
japaneseShortName = "カザフスタン"

[KE]
"Country Name" = "Kenya"
ISO2 = "KE"
ISO3 = "KEN"
"Top Level Domain" = "ke"
FIPS = "KE"
"ISO Numeric" = 404
GeoNameID = 192_950
E164 = 254
"Phone Code" = 254
Continent = "Africa"
Capital = "Nairobi"
"Time Zone in Capital" = "Africa/Nairobi"
Currency = "Shilling"
"Language Codes" = "en-KE,sw-KE"
Languages = "English (official), Kiswahili (official), numerous indigenous languages"
"Area KM2" = 582_650
"Internet Hosts" = 71_018
"Internet Users" = 3_996_000
"Phones (Mobile)" = 30_732_000
"Phones (Landline)" = 251_600
GDP = 45_310_000_000
englishShortName = "Kenya"
frenchShortName = "Kenya (le)"
numeric = 404
japaneseShortName = "ケニア"

[KI]
"Country Name" = "Kiribati"
ISO2 = "KI"
ISO3 = "KIR"
"Top Level Domain" = "ki"
FIPS = "KR"
"ISO Numeric" = 296
GeoNameID = 4_030_945
E164 = 686
"Phone Code" = 686
Continent = "Oceania"
Capital = "Tarawa"
"Time Zone in Capital" = "Pacific/Tarawa"
Currency = "Dollar"
"Language Codes" = "en-KI,gil"
Languages = "I-Kiribati, English (official)"
"Area KM2" = 811
"Internet Hosts" = 327
"Internet Users" = 7_800
"Phones (Mobile)" = 16_000
"Phones (Landline)" = 9_000
GDP = 173_000_000
englishShortName = "Kiribati"
frenchShortName = "Kiribati"
numeric = 296
japaneseShortName = "キリバス"

[XK]
"Country Name" = "Kosovo"
ISO2 = "XK"
ISO3 = "XKX"
"Top Level Domain" = ""
FIPS = "KV"
"ISO Numeric" = 0
GeoNameID = 831_053
E164 = 383
"Phone Code" = 383
Continent = "Europe"
Capital = "Pristina"
"Time Zone in Capital" = "Europe/Belgrade"
Currency = "Euro"
"Language Codes" = "sq,sr"
Languages = "Albanian (official), Serbian (official), Bosnian, Turkish, Roma"
"Area KM2" = 10_887
"Internet Hosts" = ""
"Internet Users" = ""
"Phones (Mobile)" = 562_000
"Phones (Landline)" = 106_300
GDP = 7_150_000_000

[KW]
"Country Name" = "Kuwait"
ISO2 = "KW"
ISO3 = "KWT"
"Top Level Domain" = "kw"
FIPS = "KU"
"ISO Numeric" = 414
GeoNameID = 285_570
E164 = 965
"Phone Code" = 965
Continent = "Asia"
Capital = "Kuwait City"
"Time Zone in Capital" = "Asia/Kuwait"
Currency = "Dinar"
"Language Codes" = "ar-KW,en"
Languages = "Arabic (official), English widely spoken"
"Area KM2" = 17_820
"Internet Hosts" = 2_771
"Internet Users" = 1_100_000
"Phones (Mobile)" = 5_526_000
"Phones (Landline)" = 510_000
GDP = 179_500_000_000
englishShortName = "Kuwait"
frenchShortName = "Koweït (le)"
numeric = 414
japaneseShortName = "クウェート"

[KG]
"Country Name" = "Kyrgyzstan"
ISO2 = "KG"
ISO3 = "KGZ"
"Top Level Domain" = "kg"
FIPS = "KG"
"ISO Numeric" = 417
GeoNameID = 1_527_747
E164 = 996
"Phone Code" = 996
Continent = "Asia"
Capital = "Bishkek"
"Time Zone in Capital" = "Asia/Bishkek"
Currency = "Som"
"Language Codes" = "ky,uz,ru"
Languages = "Kyrgyz (official) 64.7%, Uzbek 13.6%, Russian (official) 12.5%, Dungun 1%, other 8.2% (1999 census)"
"Area KM2" = 198_500
"Internet Hosts" = 115_573
"Internet Users" = 2_195_000
"Phones (Mobile)" = 6_800_000
"Phones (Landline)" = 489_000
GDP = 7_234_000_000
englishShortName = "Kyrgyzstan"
frenchShortName = "Kirghizistan (le)"
numeric = 417
japaneseShortName = "キルギス"

[LA]
"Country Name" = "Laos"
ISO2 = "LA"
ISO3 = "LAO"
"Top Level Domain" = "la"
FIPS = "LA"
"ISO Numeric" = 418
GeoNameID = 1_655_842
E164 = 856
"Phone Code" = 856
Continent = "Asia"
Capital = "Vientiane"
"Time Zone in Capital" = "Asia/Vientiane"
Currency = "Kip"
"Language Codes" = "lo,fr,en"
Languages = "Lao (official), French, English, various ethnic languages"
"Area KM2" = 236_800
"Internet Hosts" = 1_532
"Internet Users" = 300_000
"Phones (Mobile)" = 6_492_000
"Phones (Landline)" = 112_000
GDP = 10_100_000_000
englishShortName = "Lao People's Democratic Republic (the)"
frenchShortName = "Lao (la République démocratique populaire)"
numeric = 418
japaneseShortName = "ラオス"

[LV]
"Country Name" = "Latvia"
ISO2 = "LV"
ISO3 = "LVA"
"Top Level Domain" = "lv"
FIPS = "LG"
"ISO Numeric" = 428
GeoNameID = 458_258
E164 = 371
"Phone Code" = 371
Continent = "Europe"
Capital = "Riga"
"Time Zone in Capital" = "Europe/Riga"
Currency = "Euro"
"Language Codes" = "lv,ru,lt"
Languages = "Latvian (official) 56.3%, Russian 33.8%, other 0.6% (includes Polish, Ukrainian, and Belarusian), unspecified 9.4% (2011 est.)"
"Area KM2" = 64_589
"Internet Hosts" = 359_604
"Internet Users" = 1_504_000
"Phones (Mobile)" = 2_310_000
"Phones (Landline)" = 501_000
GDP = 30_380_000_000
englishShortName = "Latvia"
frenchShortName = "Lettonie (la)"
numeric = 428
japaneseShortName = "ラトビア"

[LB]
"Country Name" = "Lebanon"
ISO2 = "LB"
ISO3 = "LBN"
"Top Level Domain" = "lb"
FIPS = "LE"
"ISO Numeric" = 422
GeoNameID = 272_103
E164 = 961
"Phone Code" = 961
Continent = "Asia"
Capital = "Beirut"
"Time Zone in Capital" = "Asia/Beirut"
Currency = "Pound"
"Language Codes" = "ar-LB,fr-LB,en,hy"
Languages = "Arabic (official), French, English, Armenian"
"Area KM2" = 10_400
"Internet Hosts" = 64_926
"Internet Users" = 1_000_000
"Phones (Mobile)" = 4_000_000
"Phones (Landline)" = 878_000
GDP = 43_490_000_000
englishShortName = "Lebanon"
frenchShortName = "Liban (le)"
numeric = 422
japaneseShortName = "レバノン"

[LS]
"Country Name" = "Lesotho"
ISO2 = "LS"
ISO3 = "LSO"
"Top Level Domain" = "ls"
FIPS = "LT"
"ISO Numeric" = 426
GeoNameID = 932_692
E164 = 266
"Phone Code" = 266
Continent = "Africa"
Capital = "Maseru"
"Time Zone in Capital" = "Africa/Johannesburg"
Currency = "Loti"
"Language Codes" = "en-LS,st,zu,xh"
Languages = "Sesotho (official) (southern Sotho), English (official), Zulu, Xhosa"
"Area KM2" = 30_355
"Internet Hosts" = 11_030
"Internet Users" = 76_800
"Phones (Mobile)" = 1_312_000
"Phones (Landline)" = 43_100
GDP = 2_457_000_000
englishShortName = "Lesotho"
frenchShortName = "Lesotho (le)"
numeric = 426
japaneseShortName = "レソト"

[LR]
"Country Name" = "Liberia"
ISO2 = "LR"
ISO3 = "LBR"
"Top Level Domain" = "lr"
FIPS = "LI"
"ISO Numeric" = 430
GeoNameID = 2_275_384
E164 = 231
"Phone Code" = 231
Continent = "Africa"
Capital = "Monrovia"
"Time Zone in Capital" = "Africa/Monrovia"
Currency = "Dollar"
"Language Codes" = "en-LR"
Languages = "English 20% (official), some 20 ethnic group languages few of which can be written or used in correspondence"
"Area KM2" = 111_370
"Internet Hosts" = 7
"Internet Users" = 20_000
"Phones (Mobile)" = 2_394_000
"Phones (Landline)" = 3_200
GDP = 1_977_000_000
englishShortName = "Liberia"
frenchShortName = "Libéria (le)"
numeric = 430
japaneseShortName = "リベリア"

[LY]
"Country Name" = "Libya"
ISO2 = "LY"
ISO3 = "LBY"
"Top Level Domain" = "ly"
FIPS = "LY"
"ISO Numeric" = 434
GeoNameID = 2_215_636
E164 = 218
"Phone Code" = 218
Continent = "Africa"
Capital = "Tripolis"
"Time Zone in Capital" = "Africa/Tripoli"
Currency = "Dinar"
"Language Codes" = "ar-LY,it,en"
Languages = "Arabic (official), Italian, English (all widely understood in the major cities); Berber (Nafusi, Ghadamis, Suknah, Awjilah, Tamasheq)"
"Area KM2" = 1_759_540
"Internet Hosts" = 17_926
"Internet Users" = 353_900
"Phones (Mobile)" = 9_590_000
"Phones (Landline)" = 814_000
GDP = 70_920_000_000
englishShortName = "Libya"
frenchShortName = "Libye (la)"
numeric = 434
japaneseShortName = "リビア国"

[LI]
"Country Name" = "Liechtenstein"
ISO2 = "LI"
ISO3 = "LIE"
"Top Level Domain" = "li"
FIPS = "LS"
"ISO Numeric" = 438
GeoNameID = 3_042_058
E164 = 423
"Phone Code" = 423
Continent = "Europe"
Capital = "Vaduz"
"Time Zone in Capital" = "Europe/Zurich"
Currency = "Franc"
"Language Codes" = "de-LI"
Languages = "German 94.5% (official) (Alemannic is the main dialect), Italian 1.1%, other 4.3% (2010 est.)"
"Area KM2" = 160
"Internet Hosts" = 14_278
"Internet Users" = 23_000
"Phones (Mobile)" = 38_000
"Phones (Landline)" = 20_000
GDP = 5_113_000_000
englishShortName = "Liechtenstein"
frenchShortName = "Liechtenstein (le)"
numeric = 438
japaneseShortName = "リヒテンシュタイン"

[LT]
"Country Name" = "Lithuania"
ISO2 = "LT"
ISO3 = "LTU"
"Top Level Domain" = "lt"
FIPS = "LH"
"ISO Numeric" = 440
GeoNameID = 597_427
E164 = 370
"Phone Code" = 370
Continent = "Europe"
Capital = "Vilnius"
"Time Zone in Capital" = "Europe/Vilnius"
Currency = "Euro"
"Language Codes" = "lt,ru,pl"
Languages = "Lithuanian (official) 82%, Russian 8%, Polish 5.6%, other 0.9%, unspecified 3.5% (2011 est.)"
"Area KM2" = 65_200
"Internet Hosts" = 1_205_000
"Internet Users" = 1_964_000
"Phones (Mobile)" = 5_000_000
"Phones (Landline)" = 667_300
GDP = 46_710_000_000
englishShortName = "Lithuania"
frenchShortName = "Lituanie (la)"
numeric = 440
japaneseShortName = "リトアニア"

[LU]
"Country Name" = "Luxembourg"
ISO2 = "LU"
ISO3 = "LUX"
"Top Level Domain" = "lu"
FIPS = "LU"
"ISO Numeric" = 442
GeoNameID = 2_960_313
E164 = 352
"Phone Code" = 352
Continent = "Europe"
Capital = "Luxembourg"
"Time Zone in Capital" = "Europe/Luxembourg"
Currency = "Euro"
"Language Codes" = "lb,de-LU,fr-LU"
Languages = "Luxembourgish (official administrative language and national language (spoken vernacular)), French (official administrative language), German (official administrative language)"
"Area KM2" = 2_586
"Internet Hosts" = 250_900
"Internet Users" = 424_500
"Phones (Mobile)" = 761_300
"Phones (Landline)" = 266_700
GDP = 60_540_000_000
englishShortName = "Luxembourg"
frenchShortName = "Luxembourg (le)"
numeric = 442
japaneseShortName = "ルクセンブルク"

[MO]
"Country Name" = "Macau"
ISO2 = "MO"
ISO3 = "MAC"
"Top Level Domain" = "mo"
FIPS = "MC"
"ISO Numeric" = 446
GeoNameID = 1_821_275
E164 = 853
"Phone Code" = 853
Continent = "Asia"
Capital = "Macao"
"Time Zone in Capital" = "Asia/Macau"
Currency = "Pataca"
"Language Codes" = "zh,zh-MO,pt"
Languages = "Cantonese 83.3%, Mandarin 5%, Hokkien 3.7%, English 2.3%, other Chinese dialects 2%, Tagalog 1.7%, Portuguese 0.7%, other 1.3%"
"Area KM2" = 254
"Internet Hosts" = 327
"Internet Users" = 270_200
"Phones (Mobile)" = 1_613_000
"Phones (Landline)" = 162_500
GDP = 51_680_000_000
englishShortName = "Macao"
frenchShortName = "Macao"
numeric = 446
japaneseShortName = "マカオ"

[MK]
"Country Name" = "Macedonia"
ISO2 = "MK"
ISO3 = "MKD"
"Top Level Domain" = "mk"
FIPS = "MK"
"ISO Numeric" = 807
GeoNameID = 718_075
E164 = 389
"Phone Code" = 389
Continent = "Europe"
Capital = "Skopje"
"Time Zone in Capital" = "Europe/Belgrade"
Currency = "Denar"
"Language Codes" = "mk,sq,tr,rmm,sr"
Languages = "Macedonian (official) 66.5%, Albanian (official) 25.1%, Turkish 3.5%, Roma 1.9%, Serbian 1.2%, other 1.8% (2002 census)"
"Area KM2" = 25_333
"Internet Hosts" = 62_826
"Internet Users" = 1_057_000
"Phones (Mobile)" = 2_235_000
"Phones (Landline)" = 407_900
GDP = 10_650_000_000
englishShortName = "North Macedonia"
frenchShortName = "Macédoine du Nord (la)"
numeric = 807
japaneseShortName = "マケドニア"

[MG]
"Country Name" = "Madagascar"
ISO2 = "MG"
ISO3 = "MDG"
"Top Level Domain" = "mg"
FIPS = "MA"
"ISO Numeric" = 450
GeoNameID = 1_062_947
E164 = 261
"Phone Code" = 261
Continent = "Africa"
Capital = "Antananarivo"
"Time Zone in Capital" = "Indian/Antananarivo"
Currency = "Ariary"
"Language Codes" = "fr-MG,mg"
Languages = "French (official), Malagasy (official), English"
"Area KM2" = 587_040
"Internet Hosts" = 38_392
"Internet Users" = 319_900
"Phones (Mobile)" = 8_564_000
"Phones (Landline)" = 143_700
GDP = 10_530_000_000
englishShortName = "Madagascar"
frenchShortName = "Madagascar"
numeric = 450
japaneseShortName = "マダガスカル"

[MW]
"Country Name" = "Malawi"
ISO2 = "MW"
ISO3 = "MWI"
"Top Level Domain" = "mw"
FIPS = "MI"
"ISO Numeric" = 454
GeoNameID = 927_384
E164 = 265
"Phone Code" = 265
Continent = "Africa"
Capital = "Lilongwe"
"Time Zone in Capital" = "Africa/Maputo"
Currency = "Kwacha"
"Language Codes" = "ny,yao,tum,swk"
Languages = "English (official), Chichewa (common), Chinyanja, Chiyao, Chitumbuka, Chilomwe, Chinkhonde, Chingoni, Chisena, Chitonga, Chinyakyusa, Chilambya"
"Area KM2" = 118_480
"Internet Hosts" = 1_099
"Internet Users" = 716_400
"Phones (Mobile)" = 4_420_000
"Phones (Landline)" = 227_300
GDP = 3_683_000_000
englishShortName = "Malawi"
frenchShortName = "Malawi (le)"
numeric = 454
japaneseShortName = "マラウイ"

[MY]
"Country Name" = "Malaysia"
ISO2 = "MY"
ISO3 = "MYS"
"Top Level Domain" = "my"
FIPS = "MY"
"ISO Numeric" = 458
GeoNameID = 1_733_045
E164 = 60
"Phone Code" = 60
Continent = "Asia"
Capital = "Kuala Lumpur"
"Time Zone in Capital" = "Asia/Kuala_Lumpur"
Currency = "Ringgit"
"Language Codes" = "ms-MY,en,zh,ta,te,ml,pa,th"
Languages = "Bahasa Malaysia (official), English, Chinese (Cantonese, Mandarin, Hokkien, Hakka, Hainan, Foochow), Tamil, Telugu, Malayalam, Panjabi, Thai"
"Area KM2" = 329_750
"Internet Hosts" = 422_470
"Internet Users" = 15_355_000
"Phones (Mobile)" = 41_325_000
"Phones (Landline)" = 4_589_000
GDP = 312_400_000_000
englishShortName = "Malaysia"
frenchShortName = "Malaisie (la)"
numeric = 458
japaneseShortName = "マレーシア"

[MV]
"Country Name" = "Maldives"
ISO2 = "MV"
ISO3 = "MDV"
"Top Level Domain" = "mv"
FIPS = "MV"
"ISO Numeric" = 462
GeoNameID = 1_282_028
E164 = 960
"Phone Code" = 960
Continent = "Asia"
Capital = "Male"
"Time Zone in Capital" = "Indian/Maldives"
Currency = "Rufiyaa"
"Language Codes" = "dv,en"
Languages = "Dhivehi (official, dialect of Sinhala, script derived from Arabic), English (spoken by most government officials)"
"Area KM2" = 300
"Internet Hosts" = 3_296
"Internet Users" = 86_400
"Phones (Mobile)" = 560_000
"Phones (Landline)" = 23_140
GDP = 2_270_000_000
englishShortName = "Maldives"
frenchShortName = "Maldives (les)"
numeric = 462
japaneseShortName = "モルディブ"

[ML]
"Country Name" = "Mali"
ISO2 = "ML"
ISO3 = "MLI"
"Top Level Domain" = "ml"
FIPS = "ML"
"ISO Numeric" = 466
GeoNameID = 2_453_866
E164 = 223
"Phone Code" = 223
Continent = "Africa"
Capital = "Bamako"
"Time Zone in Capital" = "Africa/Abidjan"
Currency = "Franc"
"Language Codes" = "fr-ML,bm"
Languages = "French (official), Bambara 46.3%, Peul/foulfoulbe 9.4%, Dogon 7.2%, Maraka/soninke 6.4%, Malinke 5.6%, Sonrhai/djerma 5.6%, Minianka 4.3%, Tamacheq 3.5%, Senoufo 2.6%, unspecified 0.6%, other 8.5%"
"Area KM2" = 1_240_000
"Internet Hosts" = 437
"Internet Users" = 249_800
"Phones (Mobile)" = 14_613_000
"Phones (Landline)" = 112_000
GDP = 11_370_000_000
englishShortName = "Mali"
frenchShortName = "Mali (le)"
numeric = 466
japaneseShortName = "マリ"

[MT]
"Country Name" = "Malta"
ISO2 = "MT"
ISO3 = "MLT"
"Top Level Domain" = "mt"
FIPS = "MT"
"ISO Numeric" = 470
GeoNameID = 2_562_770
E164 = 356
"Phone Code" = 356
Continent = "Europe"
Capital = "Valletta"
"Time Zone in Capital" = "Europe/Malta"
Currency = "Euro"
"Language Codes" = "mt,en-MT"
Languages = "Maltese (official) 90.1%, English (official) 6%, multilingual 3%, other 0.9% (2005 est.)"
"Area KM2" = 316
"Internet Hosts" = 14_754
"Internet Users" = 240_600
"Phones (Mobile)" = 539_500
"Phones (Landline)" = 229_700
GDP = 9_541_000_000
englishShortName = "Malta"
frenchShortName = "Malte"
numeric = 470
japaneseShortName = "マルタ"

[MH]
"Country Name" = "Marshall Islands"
ISO2 = "MH"
ISO3 = "MHL"
"Top Level Domain" = "mh"
FIPS = "RM"
"ISO Numeric" = 584
GeoNameID = 2_080_185
E164 = 692
"Phone Code" = 692
Continent = "Oceania"
Capital = "Majuro"
"Time Zone in Capital" = "Pacific/Majuro"
Currency = "Dollar"
"Language Codes" = "mh,en-MH"
Languages = "Marshallese (official) 98.2%, other languages 1.8% (1999 census)"
"Area KM2" = 181
"Internet Hosts" = 3
"Internet Users" = 2_200
"Phones (Mobile)" = 3_800
"Phones (Landline)" = 4_400
GDP = 193_000_000
englishShortName = "Marshall Islands (the)"
frenchShortName = "Marshall (les Îles)"
numeric = 584
japaneseShortName = "マーシャル諸島"

[MR]
"Country Name" = "Mauritania"
ISO2 = "MR"
ISO3 = "MRT"
"Top Level Domain" = "mr"
FIPS = "MR"
"ISO Numeric" = 478
GeoNameID = 2_378_080
E164 = 222
"Phone Code" = 222
Continent = "Africa"
Capital = "Nouakchott"
"Time Zone in Capital" = "Africa/Abidjan"
Currency = "Ouguiya"
"Language Codes" = "ar-MR,fuc,snk,fr,mey,wo"
Languages = "Arabic (official and national), Pulaar, Soninke, Wolof (all national languages), French, Hassaniya (a variety of Arabic)"
"Area KM2" = 1_030_700
"Internet Hosts" = 22
"Internet Users" = 75_000
"Phones (Mobile)" = 4_024_000
"Phones (Landline)" = 65_100
GDP = 4_183_000_000
englishShortName = "Mauritania"
frenchShortName = "Mauritanie (la)"
numeric = 478
japaneseShortName = "モーリタニア"

[MU]
"Country Name" = "Mauritius"
ISO2 = "MU"
ISO3 = "MUS"
"Top Level Domain" = "mu"
FIPS = "MP"
"ISO Numeric" = 480
GeoNameID = 934_292
E164 = 230
"Phone Code" = 230
Continent = "Africa"
Capital = "Port Louis"
"Time Zone in Capital" = "Indian/Mauritius"
Currency = "Rupee"
"Language Codes" = "en-MU,bho,fr"
Languages = "Creole 86.5%, Bhojpuri 5.3%, French 4.1%, two languages 1.4%, other 2.6% (includes English, the official language, which is spoken by less than 1% of the population), unspecified 0.1% (2011 est.)"
"Area KM2" = 2_040
"Internet Hosts" = 51_139
"Internet Users" = 290_000
"Phones (Mobile)" = 1_485_000
"Phones (Landline)" = 349_100
GDP = 11_900_000_000
englishShortName = "Mauritius"
frenchShortName = "Maurice"
numeric = 480
japaneseShortName = "モーリシャス"

[YT]
"Country Name" = "Mayotte"
ISO2 = "YT"
ISO3 = "MYT"
"Top Level Domain" = "yt"
FIPS = "MF"
"ISO Numeric" = 175
GeoNameID = 1_024_031
E164 = 262
"Phone Code" = 262
Continent = "Africa"
Capital = "Mamoudzou"
"Time Zone in Capital" = "Indian/Mayotte"
Currency = "Euro"
"Language Codes" = "fr-YT"
Languages = "French"
"Area KM2" = 374
"Internet Hosts" = ""
"Internet Users" = ""
"Phones (Mobile)" = ""
"Phones (Landline)" = ""
GDP = ""
englishShortName = "Mayotte"
frenchShortName = "Mayotte"
numeric = 175
japaneseShortName = "マヨット"

[MX]
"Country Name" = "Mexico"
ISO2 = "MX"
ISO3 = "MEX"
"Top Level Domain" = "mx"
FIPS = "MX"
"ISO Numeric" = 484
GeoNameID = 3_996_063
E164 = 52
"Phone Code" = 52
Continent = "North America"
Capital = "Mexico City"
"Time Zone in Capital" = "America/Mexico_City"
Currency = "Peso"
"Language Codes" = "es-MX"
Languages = "Spanish only 92.7%, Spanish and indigenous languages 5.7%, indigenous only 0.8%, unspecified 0.8%"
"Area KM2" = 1_972_550
"Internet Hosts" = 16_233_000
"Internet Users" = 31_020_000
"Phones (Mobile)" = 100_786_000
"Phones (Landline)" = 20_220_000
GDP = 1_327_000_000_000
englishShortName = "Mexico"
frenchShortName = "Mexique (le)"
numeric = 484
japaneseShortName = "メキシコ"

[FM]
"Country Name" = "Micronesia"
ISO2 = "FM"
ISO3 = "FSM"
"Top Level Domain" = "fm"
FIPS = "FM"
"ISO Numeric" = 583
GeoNameID = 2_081_918
E164 = 691
"Phone Code" = 691
Continent = "Oceania"
Capital = "Palikir"
"Time Zone in Capital" = "Pacific/Pohnpei"
Currency = "Dollar"
"Language Codes" = "en-FM,chk,pon,yap,kos,uli,woe,nkr,kpg"
Languages = "English (official and common language), Chuukese, Kosrean, Pohnpeian, Yapese, Ulithian, Woleaian, Nukuoro, Kapingamarangi"
"Area KM2" = 702
"Internet Hosts" = 4_668
"Internet Users" = 17_000
"Phones (Mobile)" = 27_600
"Phones (Landline)" = 8_400
GDP = 339_000_000
englishShortName = "Micronesia (Federated States of)"
frenchShortName = "Micronésie (États fédérés de)"
numeric = 583
japaneseShortName = "ミクロネシア連邦"

[MD]
"Country Name" = "Moldova"
ISO2 = "MD"
ISO3 = "MDA"
"Top Level Domain" = "md"
FIPS = "MD"
"ISO Numeric" = 498
GeoNameID = 617_790
E164 = 373
"Phone Code" = 373
Continent = "Europe"
Capital = "Chisinau"
"Time Zone in Capital" = "Europe/Chisinau"
Currency = "Leu"
"Language Codes" = "ro,ru,gag,tr"
Languages = "Moldovan 58.8% (official; virtually the same as the Romanian language), Romanian 16.4%, Russian 16%, Ukrainian 3.8%, Gagauz 3.1% (a Turkish language), Bulgarian 1.1%, other 0.3%, unspecified 0.4%"
"Area KM2" = 33_843
"Internet Hosts" = 711_564
"Internet Users" = 1_333_000
"Phones (Mobile)" = 4_080_000
"Phones (Landline)" = 1_206_000
GDP = 7_932_000_000
englishShortName = "Moldova (the Republic of)"
frenchShortName = "Moldova (la République de)"
numeric = 498
japaneseShortName = "モルドバ共和国"

[MC]
"Country Name" = "Monaco"
ISO2 = "MC"
ISO3 = "MCO"
"Top Level Domain" = "mc"
FIPS = "MN"
"ISO Numeric" = 492
GeoNameID = 2_993_457
E164 = 377
"Phone Code" = 377
Continent = "Europe"
Capital = "Monaco"
"Time Zone in Capital" = "Europe/Monaco"
Currency = "Euro"
"Language Codes" = "fr-MC,en,it"
Languages = "French (official), English, Italian, Monegasque"
"Area KM2" = 2
"Internet Hosts" = 26_009
"Internet Users" = 23_000
"Phones (Mobile)" = 33_200
"Phones (Landline)" = 44_500
GDP = 5_748_000_000
englishShortName = "Monaco"
frenchShortName = "Monaco"
numeric = 492
japaneseShortName = "モナコ"

[MN]
"Country Name" = "Mongolia"
ISO2 = "MN"
ISO3 = "MNG"
"Top Level Domain" = "mn"
FIPS = "MG"
"ISO Numeric" = 496
GeoNameID = 2_029_969
E164 = 976
"Phone Code" = 976
Continent = "Asia"
Capital = "Ulan Bator"
"Time Zone in Capital" = "Asia/Ulaanbaatar"
Currency = "Tugrik"
"Language Codes" = "mn,ru"
Languages = "Khalkha Mongol 90% (official), Turkic, Russian (1999)"
"Area KM2" = 1_565_000
"Internet Hosts" = 20_084
"Internet Users" = 330_000
"Phones (Mobile)" = 3_375_000
"Phones (Landline)" = 176_700
GDP = 11_140_000_000
englishShortName = "Mongolia"
frenchShortName = "Mongolie (la)"
numeric = 496
japaneseShortName = "モンゴル"

[ME]
"Country Name" = "Montenegro"
ISO2 = "ME"
ISO3 = "MNE"
"Top Level Domain" = "me"
FIPS = "MJ"
"ISO Numeric" = 499
GeoNameID = 3_194_884
E164 = 382
"Phone Code" = 382
Continent = "Europe"
Capital = "Podgorica"
"Time Zone in Capital" = "Europe/Belgrade"
Currency = "Euro"
"Language Codes" = "sr,hu,bs,sq,hr,rom"
Languages = "Serbian 42.9%, Montenegrin (official) 37%, Bosnian 5.3%, Albanian 5.3%, Serbo-Croat 2%, other 3.5%, unspecified 4% (2011 est.)"
"Area KM2" = 14_026
"Internet Hosts" = 10_088
"Internet Users" = 280_000
"Phones (Mobile)" = 1_126_000
"Phones (Landline)" = 163_000
GDP = 4_518_000_000
englishShortName = "Montenegro"
frenchShortName = "Monténégro (le)"
numeric = 499
japaneseShortName = "モンテネグロ"

[MS]
"Country Name" = "Montserrat"
ISO2 = "MS"
ISO3 = "MSR"
"Top Level Domain" = "ms"
FIPS = "MH"
"ISO Numeric" = 500
GeoNameID = 3_578_097
E164 = 1
"Phone Code" = "1-664"
Continent = "North America"
Capital = "Plymouth"
"Time Zone in Capital" = "America/Port_of_Spain"
Currency = "Dollar"
"Language Codes" = "en-MS"
Languages = "English"
"Area KM2" = 102
"Internet Hosts" = 2_431
"Internet Users" = 1_200
"Phones (Mobile)" = 4_000
"Phones (Landline)" = 3_000
GDP = ""
englishShortName = "Montserrat"
frenchShortName = "Montserrat"
numeric = 500
japaneseShortName = "モントセラト"

[MA]
"Country Name" = "Morocco"
ISO2 = "MA"
ISO3 = "MAR"
"Top Level Domain" = "ma"
FIPS = "MO"
"ISO Numeric" = 504
GeoNameID = 2_542_007
E164 = 212
"Phone Code" = 212
Continent = "Africa"
Capital = "Rabat"
"Time Zone in Capital" = "Africa/Casablanca"
Currency = "Dirham"
"Language Codes" = "ar-MA,fr"
Languages = "Arabic (official), Berber languages (Tamazight (official), Tachelhit, Tarifit), French (often the language of business, government, and diplomacy)"
"Area KM2" = 446_550
"Internet Hosts" = 277_338
"Internet Users" = 13_213_000
"Phones (Mobile)" = 39_016_000
"Phones (Landline)" = 3_280_000
GDP = 104_800_000_000
englishShortName = "Morocco"
frenchShortName = "Maroc (le)"
numeric = 504
japaneseShortName = "モロッコ"

[MZ]
"Country Name" = "Mozambique"
ISO2 = "MZ"
ISO3 = "MOZ"
"Top Level Domain" = "mz"
FIPS = "MZ"
"ISO Numeric" = 508
GeoNameID = 1_036_973
E164 = 258
"Phone Code" = 258
Continent = "Africa"
Capital = "Maputo"
"Time Zone in Capital" = "Africa/Maputo"
Currency = "Metical"
"Language Codes" = "pt-MZ,vmw"
Languages = "Emakhuwa 25.3%, Portuguese (official) 10.7%, Xichangana 10.3%, Cisena 7.5%, Elomwe 7%, Echuwabo 5.1%, other Mozambican languages 30.1%, other 4% (1997 census)"
"Area KM2" = 801_590
"Internet Hosts" = 89_737
"Internet Users" = 613_600
"Phones (Mobile)" = 8_108_000
"Phones (Landline)" = 88_100
GDP = 14_670_000_000
englishShortName = "Mozambique"
frenchShortName = "Mozambique (le)"
numeric = 508
japaneseShortName = "モザンビーク"

[MM]
"Country Name" = "Myanmar"
ISO2 = "MM"
ISO3 = "MMR"
"Top Level Domain" = "mm"
FIPS = "BM"
"ISO Numeric" = 104
GeoNameID = 1_327_865
E164 = 95
"Phone Code" = 95
Continent = "Asia"
Capital = "Nay Pyi Taw"
"Time Zone in Capital" = "Asia/Rangoon"
Currency = "Kyat"
"Language Codes" = "my"
Languages = "Burmese (official)"
"Area KM2" = 678_500
"Internet Hosts" = 1_055
"Internet Users" = 110_000
"Phones (Mobile)" = 5_440_000
"Phones (Landline)" = 556_000
GDP = 59_430_000_000
englishShortName = "Myanmar"
frenchShortName = "Myanmar (le)"
numeric = 104
japaneseShortName = "ミャンマー"

[NA]
"Country Name" = "Namibia"
ISO2 = "NA"
ISO3 = "NAM"
"Top Level Domain" = "na"
FIPS = "WA"
"ISO Numeric" = 516
GeoNameID = 3_355_338
E164 = 264
"Phone Code" = 264
Continent = "Africa"
Capital = "Windhoek"
"Time Zone in Capital" = "Africa/Windhoek"
Currency = "Dollar"
"Language Codes" = "en-NA,af,de,hz,naq"
Languages = "Oshiwambo languages 48.9%, Nama/Damara 11.3%, Afrikaans 10.4% (common language of most of the population and about 60% of the white population), Otjiherero languages 8.6%, Kavango languages 8.5%, Caprivi languages 4.8%, English (official) 3.4%, other African languages 2.3%, other 1.7%"
"Area KM2" = 825_418
"Internet Hosts" = 78_280
"Internet Users" = 127_500
"Phones (Mobile)" = 2_435_000
"Phones (Landline)" = 171_000
GDP = 12_300_000_000
englishShortName = "Namibia"
frenchShortName = "Namibie (la)"
numeric = 516
japaneseShortName = "ナミビア"

[NR]
"Country Name" = "Nauru"
ISO2 = "NR"
ISO3 = "NRU"
"Top Level Domain" = "nr"
FIPS = "NR"
"ISO Numeric" = 520
GeoNameID = 2_110_425
E164 = 674
"Phone Code" = 674
Continent = "Oceania"
Capital = "Yaren"
"Time Zone in Capital" = "Pacific/Nauru"
Currency = "Dollar"
"Language Codes" = "na,en-NR"
Languages = "Nauruan 93% (official, a distinct Pacific Island language), English 2% (widely understood, spoken, and used for most government and commercial purposes), other 5% (includes I-Kiribati 2% and Chinese 2%)"
"Area KM2" = 21
"Internet Hosts" = 8_162
"Internet Users" = ""
"Phones (Mobile)" = 6_800
"Phones (Landline)" = 1_900
GDP = ""
englishShortName = "Nauru"
frenchShortName = "Nauru"
numeric = 520
japaneseShortName = "ナウル"

[NP]
"Country Name" = "Nepal"
ISO2 = "NP"
ISO3 = "NPL"
"Top Level Domain" = "np"
FIPS = "NP"
"ISO Numeric" = 524
GeoNameID = 1_282_988
E164 = 977
"Phone Code" = 977
Continent = "Asia"
Capital = "Kathmandu"
"Time Zone in Capital" = "Asia/Kathmandu"
Currency = "Rupee"
"Language Codes" = "ne,en"
Languages = "Nepali (official) 44.6%, Maithali 11.7%, Bhojpuri 6%, Tharu 5.8%, Tamang 5.1%, Newar 3.2%, Magar 3%, Bajjika 3%, Urdu 2.6%, Avadhi 1.9%, Limbu 1.3%, Gurung 1.2%, other 10.4%, unspecified 0.2%"
"Area KM2" = 140_800
"Internet Hosts" = 41_256
"Internet Users" = 577_800
"Phones (Mobile)" = 18_138_000
"Phones (Landline)" = 834_000
GDP = 19_340_000_000
englishShortName = "Nepal"
frenchShortName = "Népal (le)"
numeric = 524
japaneseShortName = "ネパール"

[NL]
"Country Name" = "Netherlands"
ISO2 = "NL"
ISO3 = "NLD"
"Top Level Domain" = "nl"
FIPS = "NL"
"ISO Numeric" = 528
GeoNameID = 2_750_405
E164 = 31
"Phone Code" = 31
Continent = "Europe"
Capital = "Amsterdam"
"Time Zone in Capital" = "Europe/Amsterdam"
Currency = "Euro"
"Language Codes" = "nl-NL,fy-NL"
Languages = "Dutch (official)"
"Area KM2" = 41_526
"Internet Hosts" = 13_699_000
"Internet Users" = 14_872_000
"Phones (Mobile)" = 19_643_000
"Phones (Landline)" = 7_086_000
GDP = 722_300_000_000
englishShortName = "Netherlands (the)"
frenchShortName = "Pays-Bas (les)"
numeric = 528
japaneseShortName = "オランダ王国"

[AN]
"Country Name" = "Netherlands Antilles"
ISO2 = "AN"
ISO3 = "ANT"
"Top Level Domain" = "an"
FIPS = "NT"
"ISO Numeric" = 530
GeoNameID = ""
E164 = 599
"Phone Code" = 599
Continent = "North America"
Capital = "Willemstad"
"Time Zone in Capital" = "America/Curacao"
Currency = "Guilder"
"Language Codes" = "nl-AN,en,es"
Languages = "Dutch, English, Spanish"
"Area KM2" = 960
"Internet Hosts" = ""
"Internet Users" = ""
"Phones (Mobile)" = ""
"Phones (Landline)" = ""
GDP = ""
japaneseShortName = "オランダ領アンティル"

[NC]
"Country Name" = "New Caledonia"
ISO2 = "NC"
ISO3 = "NCL"
"Top Level Domain" = "nc"
FIPS = "NC"
"ISO Numeric" = 540
GeoNameID = 2_139_685
E164 = 687
"Phone Code" = 687
Continent = "Oceania"
Capital = "Noumea"
"Time Zone in Capital" = "Pacific/Noumea"
Currency = "Franc"
"Language Codes" = "fr-NC"
Languages = "French (official), 33 Melanesian-Polynesian dialects"
"Area KM2" = 19_060
"Internet Hosts" = 34_231
"Internet Users" = 85_000
"Phones (Mobile)" = 231_000
"Phones (Landline)" = 80_000
GDP = 9_280_000_000
englishShortName = "New Caledonia"
frenchShortName = "Nouvelle-Calédonie (la)"
numeric = 540
japaneseShortName = "ニューカレドニア"

[NZ]
"Country Name" = "New Zealand"
ISO2 = "NZ"
ISO3 = "NZL"
"Top Level Domain" = "nz"
FIPS = "NZ"
"ISO Numeric" = 554
GeoNameID = 2_186_224
E164 = 64
"Phone Code" = 64
Continent = "Oceania"
Capital = "Wellington"
"Time Zone in Capital" = "Pacific/Auckland"
Currency = "Dollar"
"Language Codes" = "en-NZ,mi"
Languages = "English (de facto official) 89.8%, Maori (de jure official) 3.5%, Samoan 2%, Hindi 1.6%, French 1.2%, Northern Chinese 1.2%, Yue 1%, Other or not stated 20.5%, New Zealand Sign Language (de jure official)"
"Area KM2" = 268_680
"Internet Hosts" = 3_026_000
"Internet Users" = 3_400_000
"Phones (Mobile)" = 4_922_000
"Phones (Landline)" = 1_880_000
GDP = 181_100_000_000
englishShortName = "New Zealand"
frenchShortName = "Nouvelle-Zélande (la)"
numeric = 554
japaneseShortName = "ニュージーランド"

[NI]
"Country Name" = "Nicaragua"
ISO2 = "NI"
ISO3 = "NIC"
"Top Level Domain" = "ni"
FIPS = "NU"
"ISO Numeric" = 558
GeoNameID = 3_617_476
E164 = 505
"Phone Code" = 505
Continent = "North America"
Capital = "Managua"
"Time Zone in Capital" = "America/Managua"
Currency = "Cordoba"
"Language Codes" = "es-NI,en"
Languages = "Spanish (official) 95.3%, Miskito 2.2%, Mestizo of the Caribbean coast 2%, other 0.5%"
"Area KM2" = 129_494
"Internet Hosts" = 296_068
"Internet Users" = 199_800
"Phones (Mobile)" = 5_346_000
"Phones (Landline)" = 320_000
GDP = 11_260_000_000
englishShortName = "Nicaragua"
frenchShortName = "Nicaragua (le)"
numeric = 558
japaneseShortName = "ニカラグア"

[NE]
"Country Name" = "Niger"
ISO2 = "NE"
ISO3 = "NER"
"Top Level Domain" = "ne"
FIPS = "NG"
"ISO Numeric" = 562
GeoNameID = 2_440_476
E164 = 227
"Phone Code" = 227
Continent = "Africa"
Capital = "Niamey"
"Time Zone in Capital" = "Africa/Lagos"
Currency = "Franc"
"Language Codes" = "fr-NE,ha,kr,dje"
Languages = "French (official), Hausa, Djerma"
"Area KM2" = 1_267_000
"Internet Hosts" = 454
"Internet Users" = 115_900
"Phones (Mobile)" = 5_400_000
"Phones (Landline)" = 100_500
GDP = 7_304_000_000
englishShortName = "Niger (the)"
frenchShortName = "Niger (le)"
numeric = 562
japaneseShortName = "ニジェール"

[NG]
"Country Name" = "Nigeria"
ISO2 = "NG"
ISO3 = "NGA"
"Top Level Domain" = "ng"
FIPS = "NI"
"ISO Numeric" = 566
GeoNameID = 2_328_926
E164 = 234
"Phone Code" = 234
Continent = "Africa"
Capital = "Abuja"
"Time Zone in Capital" = "Africa/Lagos"
Currency = "Naira"
"Language Codes" = "en-NG,ha,yo,ig,ff"
Languages = "English (official), Hausa, Yoruba, Igbo (Ibo), Fulani, over 500 additional indigenous languages"
"Area KM2" = 923_768
"Internet Hosts" = 1_234
"Internet Users" = 43_989_000
"Phones (Mobile)" = 112_780_000
"Phones (Landline)" = 418_200
GDP = 502_000_000_000
englishShortName = "Nigeria"
frenchShortName = "Nigéria (le)"
numeric = 566
japaneseShortName = "ナイジェリア"

[NU]
"Country Name" = "Niue"
ISO2 = "NU"
ISO3 = "NIU"
"Top Level Domain" = "nu"
FIPS = "NE"
"ISO Numeric" = 570
GeoNameID = 4_036_232
E164 = 683
"Phone Code" = 683
Continent = "Oceania"
Capital = "Alofi"
"Time Zone in Capital" = "Pacific/Niue"
Currency = "Dollar"
"Language Codes" = "niu,en-NU"
Languages = "Niuean (official) 46% (a Polynesian language closely related to Tongan and Samoan), Niuean and English 32%, English (official) 11%, Niuean and others 5%, other 6% (2011 est.)"
"Area KM2" = 260
"Internet Hosts" = 79_508
"Internet Users" = 1_100
"Phones (Mobile)" = ""
"Phones (Landline)" = ""
GDP = 10_010_000
englishShortName = "Niue"
frenchShortName = "Niue"
numeric = 570
japaneseShortName = "ニウエ"

[KP]
"Country Name" = "North Korea"
ISO2 = "KP"
ISO3 = "PRK"
"Top Level Domain" = "kp"
FIPS = "KN"
"ISO Numeric" = 408
GeoNameID = 1_873_107
E164 = 850
"Phone Code" = 850
Continent = "Asia"
Capital = "Pyongyang"
"Time Zone in Capital" = "Asia/Pyongyang"
Currency = "Won"
"Language Codes" = "ko-KP"
Languages = "Korean"
"Area KM2" = 120_540
"Internet Hosts" = 8
"Internet Users" = ""
"Phones (Mobile)" = 1_700_000
"Phones (Landline)" = 1_180_000
GDP = 28_000_000_000
englishShortName = "Korea (the Democratic People's Republic of)"
frenchShortName = "Corée (la République populaire démocratique de)"
numeric = 408
japaneseShortName = "北朝鮮"

[MP]
"Country Name" = "Northern Mariana Islands"
ISO2 = "MP"
ISO3 = "MNP"
"Top Level Domain" = "mp"
FIPS = "CQ"
"ISO Numeric" = 580
GeoNameID = 4_041_468
E164 = 1
"Phone Code" = "1-670"
Continent = "Oceania"
Capital = "Saipan"
"Time Zone in Capital" = "Pacific/Saipan"
Currency = "Dollar"
"Language Codes" = "fil,tl,zh,ch-MP,en-MP"
Languages = "Philippine languages 32.8%, Chamorro (official) 24.1%, English (official) 17%, other Pacific island languages 10.1%, Chinese 6.8%, other Asian languages 7.3%, other 1.9% (2010 est.)"
"Area KM2" = 477
"Internet Hosts" = 17
"Internet Users" = ""
"Phones (Mobile)" = ""
"Phones (Landline)" = ""
GDP = 733_000_000
englishShortName = "Northern Mariana Islands (the)"
frenchShortName = "Mariannes du Nord (les Îles)"
numeric = 580
japaneseShortName = "北マリアナ諸島"

[NO]
"Country Name" = "Norway"
ISO2 = "NO"
ISO3 = "NOR"
"Top Level Domain" = "no"
FIPS = "NO"
"ISO Numeric" = 578
GeoNameID = 3_144_096
E164 = 47
"Phone Code" = 47
Continent = "Europe"
Capital = "Oslo"
"Time Zone in Capital" = "Europe/Oslo"
Currency = "Krone"
"Language Codes" = "no,nb,nn,se,fi"
Languages = "Bokmal Norwegian (official), Nynorsk Norwegian (official), small Sami- and Finnish-speaking minorities"
"Area KM2" = 324_220
"Internet Hosts" = 3_588_000
"Internet Users" = 4_431_000
"Phones (Mobile)" = 5_732_000
"Phones (Landline)" = 1_465_000
GDP = 515_800_000_000
englishShortName = "Norway"
frenchShortName = "Norvège (la)"
numeric = 578
japaneseShortName = "ノルウェー"

[OM]
"Country Name" = "Oman"
ISO2 = "OM"
ISO3 = "OMN"
"Top Level Domain" = "om"
FIPS = "MU"
"ISO Numeric" = 512
GeoNameID = 286_963
E164 = 968
"Phone Code" = 968
Continent = "Asia"
Capital = "Muscat"
"Time Zone in Capital" = "Asia/Muscat"
Currency = "Rial"
"Language Codes" = "ar-OM,en,bal,ur"
Languages = "Arabic (official), English, Baluchi, Urdu, Indian dialects"
"Area KM2" = 212_460
"Internet Hosts" = 14_531
"Internet Users" = 1_465_000
"Phones (Mobile)" = 5_278_000
"Phones (Landline)" = 305_000
GDP = 81_950_000_000
englishShortName = "Oman"
frenchShortName = "Oman"
numeric = 512
japaneseShortName = "オマーン"

[PK]
"Country Name" = "Pakistan"
ISO2 = "PK"
ISO3 = "PAK"
"Top Level Domain" = "pk"
FIPS = "PK"
"ISO Numeric" = 586
GeoNameID = 1_168_579
E164 = 92
"Phone Code" = 92
Continent = "Asia"
Capital = "Islamabad"
"Time Zone in Capital" = "Asia/Karachi"
Currency = "Rupee"
"Language Codes" = "ur-PK,en-PK,pa,sd,ps,brh"
Languages = "Punjabi 48%, Sindhi 12%, Saraiki (a Punjabi variant) 10%, Pashto (alternate name, Pashtu) 8%, Urdu (official) 8%, Balochi 3%, Hindko 2%, Brahui 1%, English (official; lingua franca of Pakistani elite and most government ministries), Burushaski, and other 8%"
"Area KM2" = 803_940
"Internet Hosts" = 365_813
"Internet Users" = 20_431_000
"Phones (Mobile)" = 125_000_000
"Phones (Landline)" = 5_803_000
GDP = 236_500_000_000
englishShortName = "Pakistan"
frenchShortName = "Pakistan (le)"
numeric = 586
japaneseShortName = "パキスタン"

[PW]
"Country Name" = "Palau"
ISO2 = "PW"
ISO3 = "PLW"
"Top Level Domain" = "pw"
FIPS = "PS"
"ISO Numeric" = 585
GeoNameID = 1_559_582
E164 = 680
"Phone Code" = 680
Continent = "Oceania"
Capital = "Melekeok"
"Time Zone in Capital" = "Pacific/Palau"
Currency = "Dollar"
"Language Codes" = "pau,sov,en-PW,tox,ja,fil,zh"
Languages = "Palauan (official on most islands) 66.6%, Carolinian 0.7%, other Micronesian 0.7%, English (official) 15.5%, Filipino 10.8%, Chinese 1.8%, other Asian 2.6%, other 1.3%"
"Area KM2" = 458
"Internet Hosts" = 4
"Internet Users" = ""
"Phones (Mobile)" = 17_150
"Phones (Landline)" = 7_300
GDP = 221_000_000
englishShortName = "Palau"
frenchShortName = "Palaos (les)"
numeric = 585
japaneseShortName = "パラオ"

[PS]
"Country Name" = "Palestine"
ISO2 = "PS"
ISO3 = "PSE"
"Top Level Domain" = "ps"
FIPS = "WE"
"ISO Numeric" = 275
GeoNameID = 6_254_930
E164 = 970
"Phone Code" = 970
Continent = "Asia"
Capital = "East Jerusalem"
"Time Zone in Capital" = "Asia/Hebron"
Currency = "Shekel"
"Language Codes" = "ar-PS"
Languages = "Arabic, Hebrew, English"
"Area KM2" = 5_970
"Internet Hosts" = ""
"Internet Users" = 1_379_000
"Phones (Mobile)" = 3_041_000
"Phones (Landline)" = 406_000
GDP = 6_641_000_000
englishShortName = "Palestine, State of"
frenchShortName = "Palestine, État de"
numeric = 275
japaneseShortName = "パレスチナ国"

[PA]
"Country Name" = "Panama"
ISO2 = "PA"
ISO3 = "PAN"
"Top Level Domain" = "pa"
FIPS = "PM"
"ISO Numeric" = 591
GeoNameID = 3_703_430
E164 = 507
"Phone Code" = 507
Continent = "North America"
Capital = "Panama City"
"Time Zone in Capital" = "America/Panama"
Currency = "Balboa"
"Language Codes" = "es-PA,en"
Languages = "Spanish (official), English 14%"
"Area KM2" = 78_200
"Internet Hosts" = 11_022
"Internet Users" = 959_800
"Phones (Mobile)" = 6_770_000
"Phones (Landline)" = 640_000
GDP = 40_620_000_000
englishShortName = "Panama"
frenchShortName = "Panama (le)"
numeric = 591
japaneseShortName = "パナマ"

[PG]
"Country Name" = "Papua New Guinea"
ISO2 = "PG"
ISO3 = "PNG"
"Top Level Domain" = "pg"
FIPS = "PP"
"ISO Numeric" = 598
GeoNameID = 2_088_628
E164 = 675
"Phone Code" = 675
Continent = "Oceania"
Capital = "Port Moresby"
"Time Zone in Capital" = "Pacific/Port_Moresby"
Currency = "Kina"
"Language Codes" = "en-PG,ho,meu,tpi"
Languages = "Tok Pisin (official), English (official), Hiri Motu (official), some 836 indigenous languages spoken (about 12% of the world's total); most languages have fewer than 1,000 speakers"
"Area KM2" = 462_840
"Internet Hosts" = 5_006
"Internet Users" = 125_000
"Phones (Mobile)" = 2_709_000
"Phones (Landline)" = 139_000
GDP = 16_100_000_000
englishShortName = "Papua New Guinea"
frenchShortName = "Papouasie-Nouvelle-Guinée (la)"
numeric = 598
japaneseShortName = "パプアニューギニア"

[PY]
"Country Name" = "Paraguay"
ISO2 = "PY"
ISO3 = "PRY"
"Top Level Domain" = "py"
FIPS = "PA"
"ISO Numeric" = 600
GeoNameID = 3_437_598
E164 = 595
"Phone Code" = 595
Continent = "South America"
Capital = "Asuncion"
"Time Zone in Capital" = "America/Asuncion"
Currency = "Guarani"
"Language Codes" = "es-PY,gn"
Languages = "Spanish (official), Guarani (official)"
"Area KM2" = 406_750
"Internet Hosts" = 280_658
"Internet Users" = 1_105_000
"Phones (Mobile)" = 6_790_000
"Phones (Landline)" = 376_000
GDP = 30_560_000_000
englishShortName = "Paraguay"
frenchShortName = "Paraguay (le)"
numeric = 600
japaneseShortName = "パラグアイ"

[PE]
"Country Name" = "Peru"
ISO2 = "PE"
ISO3 = "PER"
"Top Level Domain" = "pe"
FIPS = "PE"
"ISO Numeric" = 604
GeoNameID = 3_932_488
E164 = 51
"Phone Code" = 51
Continent = "South America"
Capital = "Lima"
"Time Zone in Capital" = "America/Lima"
Currency = "Sol"
"Language Codes" = "es-PE,qu,ay"
Languages = "Spanish (official) 84.1%, Quechua (official) 13%, Aymara (official) 1.7%, Ashaninka 0.3%, other native languages (includes a large number of minor Amazonian languages) 0.7%, other (includes foreign languages and sign language) 0.2% (2007 est.)"
"Area KM2" = 1_285_220
"Internet Hosts" = 234_102
"Internet Users" = 9_158_000
"Phones (Mobile)" = 29_400_000
"Phones (Landline)" = 3_420_000
GDP = 210_300_000_000
englishShortName = "Peru"
frenchShortName = "Pérou (le)"
numeric = 604
japaneseShortName = "ペルー"

[PH]
"Country Name" = "Philippines"
ISO2 = "PH"
ISO3 = "PHL"
"Top Level Domain" = "ph"
FIPS = "RP"
"ISO Numeric" = 608
GeoNameID = 1_694_008
E164 = 63
"Phone Code" = 63
Continent = "Asia"
Capital = "Manila"
"Time Zone in Capital" = "Asia/Manila"
Currency = "Peso"
"Language Codes" = "tl,en-PH,fil"
Languages = "Filipino (official; based on Tagalog) and English (official); eight major dialects - Tagalog, Cebuano, Ilocano, Hiligaynon or Ilonggo, Bicol, Waray, Pampango, and Pangasinan"
"Area KM2" = 300_000
"Internet Hosts" = 425_812
"Internet Users" = 8_278_000
"Phones (Mobile)" = 103_000_000
"Phones (Landline)" = 3_939_000
GDP = 272_200_000_000
englishShortName = "Philippines (the)"
frenchShortName = "Philippines (les)"
numeric = 608
japaneseShortName = "フィリピン"

[PN]
"Country Name" = "Pitcairn"
ISO2 = "PN"
ISO3 = "PCN"
"Top Level Domain" = "pn"
FIPS = "PC"
"ISO Numeric" = 612
GeoNameID = 4_030_699
E164 = 64
"Phone Code" = 64
Continent = "Oceania"
Capital = "Adamstown"
"Time Zone in Capital" = "Pacific/Pitcairn"
Currency = "Dollar"
"Language Codes" = "en-PN"
Languages = "English"
"Area KM2" = 47
"Internet Hosts" = ""
"Internet Users" = ""
"Phones (Mobile)" = ""
"Phones (Landline)" = ""
GDP = ""
englishShortName = "Pitcairn"
frenchShortName = "Pitcairn"
numeric = 612
japaneseShortName = "ピトケアン"

[PL]
"Country Name" = "Poland"
ISO2 = "PL"
ISO3 = "POL"
"Top Level Domain" = "pl"
FIPS = "PL"
"ISO Numeric" = 616
GeoNameID = 798_544
E164 = 48
"Phone Code" = 48
Continent = "Europe"
Capital = "Warsaw"
"Time Zone in Capital" = "Europe/Warsaw"
Currency = "Zloty"
"Language Codes" = "pl"
Languages = "Polish (official) 96.2%, Polish and non-Polish 2%, non-Polish 0.5%, unspecified 1.3%"
"Area KM2" = 312_685
"Internet Hosts" = 13_265_000
"Internet Users" = 22_452_000
"Phones (Mobile)" = 50_840_000
"Phones (Landline)" = 6_125_000
GDP = 513_900_000_000
englishShortName = "Poland"
frenchShortName = "Pologne (la)"
numeric = 616
japaneseShortName = "ポーランド"

[PT]
"Country Name" = "Portugal"
ISO2 = "PT"
ISO3 = "PRT"
"Top Level Domain" = "pt"
FIPS = "PO"
"ISO Numeric" = 620
GeoNameID = 2_264_397
E164 = 351
"Phone Code" = 351
Continent = "Europe"
Capital = "Lisbon"
"Time Zone in Capital" = "Europe/Lisbon"
Currency = "Euro"
"Language Codes" = "pt-PT,mwl"
Languages = "Portuguese (official), Mirandese (official, but locally used)"
"Area KM2" = 92_391
"Internet Hosts" = 3_748_000
"Internet Users" = 5_168_000
"Phones (Mobile)" = 12_312_000
"Phones (Landline)" = 4_558_000
GDP = 219_300_000_000
englishShortName = "Portugal"
frenchShortName = "Portugal (le)"
numeric = 620
japaneseShortName = "ポルトガル"

[PR]
"Country Name" = "Puerto Rico"
ISO2 = "PR"
ISO3 = "PRI"
"Top Level Domain" = "pr"
FIPS = "RQ"
"ISO Numeric" = 630
GeoNameID = 4_566_966
E164 = 1
"Phone Code" = "1-787, 1-939"
Continent = "North America"
Capital = "San Juan"
"Time Zone in Capital" = "America/Puerto_Rico"
Currency = "Dollar"
"Language Codes" = "en-PR,es-PR"
Languages = "Spanish, English"
"Area KM2" = 9_104
"Internet Hosts" = 469
"Internet Users" = 1_000_000
"Phones (Mobile)" = 3_060_000
"Phones (Landline)" = 780_200
GDP = 93_520_000_000
englishShortName = "Puerto Rico"
frenchShortName = "Porto Rico"
numeric = 630
japaneseShortName = "プエルトリコ"

[QA]
"Country Name" = "Qatar"
ISO2 = "QA"
ISO3 = "QAT"
"Top Level Domain" = "qa"
FIPS = "QA"
"ISO Numeric" = 634
GeoNameID = 289_688
E164 = 974
"Phone Code" = 974
Continent = "Asia"
Capital = "Doha"
"Time Zone in Capital" = "Asia/Qatar"
Currency = "Rial"
"Language Codes" = "ar-QA,es"
Languages = "Arabic (official), English commonly used as a second language"
"Area KM2" = 11_437
"Internet Hosts" = 897
"Internet Users" = 563_800
"Phones (Mobile)" = 2_600_000
"Phones (Landline)" = 327_000
GDP = 213_100_000_000
englishShortName = "Qatar"
frenchShortName = "Qatar (le)"
numeric = 634
japaneseShortName = "カタール"

[CG]
"Country Name" = "Republic of the Congo"
ISO2 = "CG"
ISO3 = "COG"
"Top Level Domain" = "cg"
FIPS = "CF"
"ISO Numeric" = 178
GeoNameID = 2_260_494
E164 = 242
"Phone Code" = 242
Continent = "Africa"
Capital = "Brazzaville"
"Time Zone in Capital" = "Africa/Lagos"
Currency = "Franc"
"Language Codes" = "fr-CG,kg,ln-CG"
Languages = "French (official), Lingala and Monokutuba (lingua franca trade languages), many local languages and dialects (of which Kikongo is the most widespread)"
"Area KM2" = 342_000
"Internet Hosts" = 45
"Internet Users" = 245_200
"Phones (Mobile)" = 4_283_000
"Phones (Landline)" = 14_900
GDP = 14_250_000_000
englishShortName = "Congo (the)"
frenchShortName = "Congo (le)"
numeric = 178
japaneseShortName = "コンゴ"

[RE]
"Country Name" = "Reunion"
ISO2 = "RE"
ISO3 = "REU"
"Top Level Domain" = "re"
FIPS = "RE"
"ISO Numeric" = 638
GeoNameID = 935_317
E164 = 262
"Phone Code" = 262
Continent = "Africa"
Capital = "Saint-Denis"
"Time Zone in Capital" = "Indian/Reunion"
Currency = "Euro"
"Language Codes" = "fr-RE"
Languages = "French"
"Area KM2" = 2_517
"Internet Hosts" = ""
"Internet Users" = ""
"Phones (Mobile)" = ""
"Phones (Landline)" = ""
GDP = ""
englishShortName = "Réunion"
frenchShortName = "Réunion (La)"
numeric = 638
japaneseShortName = "レユニオン"

[RO]
"Country Name" = "Romania"
ISO2 = "RO"
ISO3 = "ROU"
"Top Level Domain" = "ro"
FIPS = "RO"
"ISO Numeric" = 642
GeoNameID = 798_549
E164 = 40
"Phone Code" = 40
Continent = "Europe"
Capital = "Bucharest"
"Time Zone in Capital" = "Europe/Bucharest"
Currency = "Leu"
"Language Codes" = "ro,hu,rom"
Languages = "Romanian (official) 85.4%, Hungarian 6.3%, Romany (Gypsy) 1.2%, other 1%, unspecified 6.1% (2011 est.)"
"Area KM2" = 237_500
"Internet Hosts" = 2_667_000
"Internet Users" = 7_787_000
"Phones (Mobile)" = 22_700_000
"Phones (Landline)" = 4_680_000
GDP = 188_900_000_000
englishShortName = "Romania"
frenchShortName = "Roumanie (la)"
numeric = 642
japaneseShortName = "ルーマニア"

[RU]
"Country Name" = "Russia"
ISO2 = "RU"
ISO3 = "RUS"
"Top Level Domain" = "ru"
FIPS = "RS"
"ISO Numeric" = 643
GeoNameID = 2_017_370
E164 = 7
"Phone Code" = 7
Continent = "Europe"
Capital = "Moscow"
"Time Zone in Capital" = "Europe/Moscow"
Currency = "Ruble"
"Language Codes" = "ru,tt,xal,cau,ady,kv,ce,tyv,cv,udm,tut,mns,bua,myv,mdf,chm,ba,inh,tut,kbd,krc,ava,sah,nog"
Languages = "Russian (official) 96.3%, Dolgang 5.3%, German 1.5%, Chechen 1%, Tatar 3%, other 10.3%"
"Area KM2" = 17_100_000
"Internet Hosts" = 14_865_000
"Internet Users" = 40_853_000
"Phones (Mobile)" = 261_900_000
"Phones (Landline)" = 42_900_000
GDP = 2_113_000_000_000
englishShortName = "Russian Federation (the)"
frenchShortName = "Russie (la Fédération de)"
numeric = 643
japaneseShortName = "ロシア連邦"

[RW]
"Country Name" = "Rwanda"
ISO2 = "RW"
ISO3 = "RWA"
"Top Level Domain" = "rw"
FIPS = "RW"
"ISO Numeric" = 646
GeoNameID = 49_518
E164 = 250
"Phone Code" = 250
Continent = "Africa"
Capital = "Kigali"
"Time Zone in Capital" = "Africa/Maputo"
Currency = "Franc"
"Language Codes" = "rw,en-RW,fr-RW,sw"
Languages = "Kinyarwanda only (official, universal Bantu vernacular) 93.2%, Kinyarwanda and other language(s) 6.2%, French (official) and other language(s) 0.1%, English (official) and other language(s) 0.1%, Swahili (or Kiswahili, used in commercial centers) 0.02%, other 0.03%, unspecified 0.3% (2002 est.)"
"Area KM2" = 26_338
"Internet Hosts" = 1_447
"Internet Users" = 450_000
"Phones (Mobile)" = 5_690_000
"Phones (Landline)" = 44_400
GDP = 7_700_000_000
englishShortName = "Rwanda"
frenchShortName = "Rwanda (le)"
numeric = 646
japaneseShortName = "ルワンダ"

[BL]
"Country Name" = "Saint Barthelemy"
ISO2 = "BL"
ISO3 = "BLM"
"Top Level Domain" = "gp"
FIPS = "TB"
"ISO Numeric" = 652
GeoNameID = 3_578_476
E164 = 590
"Phone Code" = 590
Continent = "North America"
Capital = "Gustavia"
"Time Zone in Capital" = "America/Port_of_Spain"
Currency = "Euro"
"Language Codes" = "fr"
Languages = "French (primary), English"
"Area KM2" = 21
"Internet Hosts" = ""
"Internet Users" = ""
"Phones (Mobile)" = ""
"Phones (Landline)" = ""
GDP = ""
englishShortName = "Saint Barthélemy"
frenchShortName = "Saint-Barthélemy"
numeric = 652
japaneseShortName = "サン・バルテルミー"

[SH]
"Country Name" = "Saint Helena"
ISO2 = "SH"
ISO3 = "SHN"
"Top Level Domain" = "sh"
FIPS = "SH"
"ISO Numeric" = 654
GeoNameID = 3_370_751
E164 = 290
"Phone Code" = 290
Continent = "Africa"
Capital = "Jamestown"
"Time Zone in Capital" = "Africa/Abidjan"
Currency = "Pound"
"Language Codes" = "en-SH"
Languages = "English"
"Area KM2" = 410
"Internet Hosts" = ""
"Internet Users" = ""
"Phones (Mobile)" = ""
"Phones (Landline)" = ""
GDP = ""
englishShortName = "Saint Helena, Ascension and Tristan da Cunha"
frenchShortName = "Sainte-Hélène, Ascension et Tristan da Cunha"
numeric = 654
japaneseShortName = "セントヘレナ"

[KN]
"Country Name" = "Saint Kitts and Nevis"
ISO2 = "KN"
ISO3 = "KNA"
"Top Level Domain" = "kn"
FIPS = "SC"
"ISO Numeric" = 659
GeoNameID = 3_575_174
E164 = 1
"Phone Code" = "1-869"
Continent = "North America"
Capital = "Basseterre"
"Time Zone in Capital" = "America/Port_of_Spain"
Currency = "Dollar"
"Language Codes" = "en-KN"
Languages = "English (official)"
"Area KM2" = 261
"Internet Hosts" = 54
"Internet Users" = 17_000
"Phones (Mobile)" = 84_000
"Phones (Landline)" = 20_000
GDP = 767_000_000
englishShortName = "Saint Kitts and Nevis"
frenchShortName = "Saint-Kitts-et-Nevis"
numeric = 659
japaneseShortName = "セントクリストファー・ネイビス連邦"

[LC]
"Country Name" = "Saint Lucia"
ISO2 = "LC"
ISO3 = "LCA"
"Top Level Domain" = "lc"
FIPS = "ST"
"ISO Numeric" = 662
GeoNameID = 3_576_468
E164 = 1
"Phone Code" = "1-758"
Continent = "North America"
Capital = "Castries"
"Time Zone in Capital" = "America/Port_of_Spain"
Currency = "Dollar"
"Language Codes" = "en-LC"
Languages = "English (official), French patois"
"Area KM2" = 616
"Internet Hosts" = 100
"Internet Users" = 142_900
"Phones (Mobile)" = 227_000
"Phones (Landline)" = 36_800
GDP = 1_377_000_000
englishShortName = "Saint Lucia"
frenchShortName = "Sainte-Lucie"
numeric = 662
japaneseShortName = "セントルシア"

[MF]
"Country Name" = "Saint Martin"
ISO2 = "MF"
ISO3 = "MAF"
"Top Level Domain" = "gp"
FIPS = "RN"
"ISO Numeric" = 663
GeoNameID = 3_578_421
E164 = 1
"Phone Code" = 590
Continent = "North America"
Capital = "Marigot"
"Time Zone in Capital" = "America/Port_of_Spain"
Currency = "Euro"
"Language Codes" = "fr"
Languages = "French (official), English, Dutch, French Patois, Spanish, Papiamento (dialect of Netherlands Antilles)"
"Area KM2" = 53
"Internet Hosts" = ""
"Internet Users" = ""
"Phones (Mobile)" = ""
"Phones (Landline)" = ""
GDP = 561_500_000
englishShortName = "Saint Martin (French part)"
frenchShortName = "Saint-Martin (partie française)"
numeric = 663
japaneseShortName = "セント・マーチン"

[PM]
"Country Name" = "Saint Pierre and Miquelon"
ISO2 = "PM"
ISO3 = "SPM"
"Top Level Domain" = "pm"
FIPS = "SB"
"ISO Numeric" = 666
GeoNameID = 3_424_932
E164 = 508
"Phone Code" = 508
Continent = "North America"
Capital = "Saint-Pierre"
"Time Zone in Capital" = "America/Miquelon"
Currency = "Euro"
"Language Codes" = "fr-PM"
Languages = "French (official)"
"Area KM2" = 242
"Internet Hosts" = 15
"Internet Users" = ""
"Phones (Mobile)" = ""
"Phones (Landline)" = 4_800
GDP = 215_300_000
englishShortName = "Saint Pierre and Miquelon"
frenchShortName = "Saint-Pierre-et-Miquelon"
numeric = 666
japaneseShortName = "サンピエール島およびミクロン島"

[VC]
"Country Name" = "Saint Vincent and the Grenadines"
ISO2 = "VC"
ISO3 = "VCT"
"Top Level Domain" = "vc"
FIPS = "VC"
"ISO Numeric" = 670
GeoNameID = 3_577_815
E164 = 1
"Phone Code" = "1-784"
Continent = "North America"
Capital = "Kingstown"
"Time Zone in Capital" = "America/Port_of_Spain"
Currency = "Dollar"
"Language Codes" = "en-VC,fr"
Languages = "English, French patois"
"Area KM2" = 389
"Internet Hosts" = 305
"Internet Users" = 76_000
"Phones (Mobile)" = 135_500
"Phones (Landline)" = 19_400
GDP = 742_000_000
englishShortName = "Saint Vincent and the Grenadines"
frenchShortName = "Saint-Vincent-et-les Grenadines"
numeric = 670
japaneseShortName = "セントビンセント及びグレナディーン諸島"

[WS]
"Country Name" = "Samoa"
ISO2 = "WS"
ISO3 = "WSM"
"Top Level Domain" = "ws"
FIPS = "WS"
"ISO Numeric" = 882
GeoNameID = 4_034_894
E164 = 685
"Phone Code" = 685
Continent = "Oceania"
Capital = "Apia"
"Time Zone in Capital" = "Pacific/Apia"
Currency = "Tala"
"Language Codes" = "sm,en-WS"
Languages = "Samoan (Polynesian) (official), English"
"Area KM2" = 2_944
"Internet Hosts" = 18_013
"Internet Users" = 9_000
"Phones (Mobile)" = 167_400
"Phones (Landline)" = 35_300
GDP = 705_000_000
englishShortName = "Samoa"
frenchShortName = "Samoa (le)"
numeric = 882
japaneseShortName = "サモア"

[SM]
"Country Name" = "San Marino"
ISO2 = "SM"
ISO3 = "SMR"
"Top Level Domain" = "sm"
FIPS = "SM"
"ISO Numeric" = 674
GeoNameID = 3_168_068
E164 = 378
"Phone Code" = 378
Continent = "Europe"
Capital = "San Marino"
"Time Zone in Capital" = "Europe/Rome"
Currency = "Euro"
"Language Codes" = "it-SM"
Languages = "Italian"
"Area KM2" = 61
"Internet Hosts" = 11_015
"Internet Users" = 17_000
"Phones (Mobile)" = 36_000
"Phones (Landline)" = 18_700
GDP = 1_866_000_000
englishShortName = "San Marino"
frenchShortName = "Saint-Marin"
numeric = 674
japaneseShortName = "サンマリノ"

[ST]
"Country Name" = "Sao Tome and Principe"
ISO2 = "ST"
ISO3 = "STP"
"Top Level Domain" = "st"
FIPS = "TP"
"ISO Numeric" = 678
GeoNameID = 2_410_758
E164 = 239
"Phone Code" = 239
Continent = "Africa"
Capital = "Sao Tome"
"Time Zone in Capital" = "Africa/Abidjan"
Currency = "Dobra"
"Language Codes" = "pt-ST"
Languages = "Portuguese 98.4% (official), Forro 36.2%, Cabo Verdian 8.5%, French 6.8%, Angolar 6.6%, English 4.9%, Lunguie 1%, other (including sign language) 2.4%"
"Area KM2" = 1_001
"Internet Hosts" = 1_678
"Internet Users" = 26_700
"Phones (Mobile)" = 122_000
"Phones (Landline)" = 8_000
GDP = 311_000_000
englishShortName = "Sao Tome and Principe"
frenchShortName = "Sao Tomé-et-Principe"
numeric = 678
japaneseShortName = "サントメ・プリンシペ"

[SA]
"Country Name" = "Saudi Arabia"
ISO2 = "SA"
ISO3 = "SAU"
"Top Level Domain" = "sa"
FIPS = "SA"
"ISO Numeric" = 682
GeoNameID = 102_358
E164 = 966
"Phone Code" = 966
Continent = "Asia"
Capital = "Riyadh"
"Time Zone in Capital" = "Asia/Riyadh"
Currency = "Rial"
"Language Codes" = "ar-SA"
Languages = "Arabic (official)"
"Area KM2" = 1_960_582
"Internet Hosts" = 145_941
"Internet Users" = 9_774_000
"Phones (Mobile)" = 53_000_000
"Phones (Landline)" = 4_800_000
GDP = 718_500_000_000
englishShortName = "Saudi Arabia"
frenchShortName = "Arabie saoudite (l')"
numeric = 682
japaneseShortName = "サウジアラビア"

[SN]
"Country Name" = "Senegal"
ISO2 = "SN"
ISO3 = "SEN"
"Top Level Domain" = "sn"
FIPS = "SG"
"ISO Numeric" = 686
GeoNameID = 2_245_662
E164 = 221
"Phone Code" = 221
Continent = "Africa"
Capital = "Dakar"
"Time Zone in Capital" = "Africa/Abidjan"
Currency = "Franc"
"Language Codes" = "fr-SN,wo,fuc,mnk"
Languages = "French (official), Wolof, Pulaar, Jola, Mandinka"
"Area KM2" = 196_190
"Internet Hosts" = 237
"Internet Users" = 1_818_000
"Phones (Mobile)" = 11_470_000
"Phones (Landline)" = 338_200
GDP = 15_360_000_000
englishShortName = "Senegal"
frenchShortName = "Sénégal (le)"
numeric = 686
japaneseShortName = "セネガル"

[RS]
"Country Name" = "Serbia"
ISO2 = "RS"
ISO3 = "SRB"
"Top Level Domain" = "rs"
FIPS = "RI"
"ISO Numeric" = 688
GeoNameID = 6_290_252
E164 = 381
"Phone Code" = 381
Continent = "Europe"
Capital = "Belgrade"
"Time Zone in Capital" = "Europe/Belgrade"
Currency = "Dinar"
"Language Codes" = "sr,hu,bs,rom"
Languages = "Serbian (official) 88.1%, Hungarian 3.4%, Bosnian 1.9%, Romany 1.4%, other 3.4%, undeclared or unknown 1.8%"
"Area KM2" = 88_361
"Internet Hosts" = 1_102_000
"Internet Users" = 4_107_000
"Phones (Mobile)" = 9_138_000
"Phones (Landline)" = 2_977_000
GDP = 43_680_000_000
englishShortName = "Serbia"
frenchShortName = "Serbie (la)"
numeric = 688
japaneseShortName = "セルビア"

[SC]
"Country Name" = "Seychelles"
ISO2 = "SC"
ISO3 = "SYC"
"Top Level Domain" = "sc"
FIPS = "SE"
"ISO Numeric" = 690
GeoNameID = 241_170
E164 = 248
"Phone Code" = 248
Continent = "Africa"
Capital = "Victoria"
"Time Zone in Capital" = "Indian/Mahe"
Currency = "Rupee"
"Language Codes" = "en-SC,fr-SC"
Languages = "Seychellois Creole (official) 89.1%, English (official) 5.1%, French (official) 0.7%, other 3.8%, unspecified 1.4% (2010 est.)"
"Area KM2" = 455
"Internet Hosts" = 247
"Internet Users" = 32_000
"Phones (Mobile)" = 138_300
"Phones (Landline)" = 28_900
GDP = 1_271_000_000
englishShortName = "Seychelles"
frenchShortName = "Seychelles (les)"
numeric = 690
japaneseShortName = "セーシェル"

[SL]
"Country Name" = "Sierra Leone"
ISO2 = "SL"
ISO3 = "SLE"
"Top Level Domain" = "sl"
FIPS = "SL"
"ISO Numeric" = 694
GeoNameID = 2_403_846
E164 = 232
"Phone Code" = 232
Continent = "Africa"
Capital = "Freetown"
"Time Zone in Capital" = "Africa/Abidjan"
Currency = "Leone"
"Language Codes" = "en-SL,men,tem"
Languages = "English (official, regular use limited to literate minority), Mende (principal vernacular in the south), Temne (principal vernacular in the north), Krio (English-based Creole, spoken by the descendants of freed Jamaican slaves who were settled in the Freetown area, a lingua franca and a first language for 10% of the population but understood by 95%)"
"Area KM2" = 71_740
"Internet Hosts" = 282
"Internet Users" = 14_900
"Phones (Mobile)" = 2_210_000
"Phones (Landline)" = 18_000
GDP = 4_607_000_000
englishShortName = "Sierra Leone"
frenchShortName = "Sierra Leone (la)"
numeric = 694
japaneseShortName = "シエラレオネ"

[SG]
"Country Name" = "Singapore"
ISO2 = "SG"
ISO3 = "SGP"
"Top Level Domain" = "sg"
FIPS = "SN"
"ISO Numeric" = 702
GeoNameID = 1_880_251
E164 = 65
"Phone Code" = 65
Continent = "Asia"
Capital = "Singapore"
"Time Zone in Capital" = "Asia/Singapore"
Currency = "Dollar"
"Language Codes" = "cmn,en-SG,ms-SG,ta-SG,zh-SG"
Languages = "Mandarin (official) 36.3%, English (official) 29.8%, Malay (official) 11.9%, Hokkien 8.1%, Tamil (official) 4.4%, Cantonese 4.1%, Teochew 3.2%, other Indian languages 1.2%, other Chinese dialects 1.1%, other 1.1% (2010 est.)"
"Area KM2" = 693
"Internet Hosts" = 1_960_000
"Internet Users" = 3_235_000
"Phones (Mobile)" = 8_063_000
"Phones (Landline)" = 1_990_000
GDP = 295_700_000_000
englishShortName = "Singapore"
frenchShortName = "Singapour"
numeric = 702
japaneseShortName = "シンガポール"

[SX]
"Country Name" = "Sint Maarten"
ISO2 = "SX"
ISO3 = "SXM"
"Top Level Domain" = "sx"
FIPS = "NN"
"ISO Numeric" = 534
GeoNameID = 7_609_695
E164 = 1
"Phone Code" = "1-721"
Continent = "North America"
Capital = "Philipsburg"
"Time Zone in Capital" = "America/Curacao"
Currency = "Guilder"
"Language Codes" = "nl,en"
Languages = "English (official) 67.5%, Spanish 12.9%, Creole 8.2%, Dutch (official) 4.2%, Papiamento (a Spanish-Portuguese-Dutch-English dialect) 2.2%, French 1.5%, other 3.5% (2001 census)"
"Area KM2" = 34
"Internet Hosts" = ""
"Internet Users" = ""
"Phones (Mobile)" = ""
"Phones (Landline)" = ""
GDP = 794_700_000
englishShortName = "Sint Maarten (Dutch part)"
frenchShortName = "Saint-Martin (partie néerlandaise)"
numeric = 534

[SK]
"Country Name" = "Slovakia"
ISO2 = "SK"
ISO3 = "SVK"
"Top Level Domain" = "sk"
FIPS = "LO"
"ISO Numeric" = 703
GeoNameID = 3_057_568
E164 = 421
"Phone Code" = 421
Continent = "Europe"
Capital = "Bratislava"
"Time Zone in Capital" = "Europe/Prague"
Currency = "Euro"
"Language Codes" = "sk,hu"
Languages = "Slovak (official) 78.6%, Hungarian 9.4%, Roma 2.3%, Ruthenian 1%, other or unspecified 8.8% (2011 est.)"
"Area KM2" = 48_845
"Internet Hosts" = 1_384_000
"Internet Users" = 4_063_000
"Phones (Mobile)" = 6_095_000
"Phones (Landline)" = 975_000
GDP = 96_960_000_000
englishShortName = "Slovakia"
frenchShortName = "Slovaquie (la)"
numeric = 703
japaneseShortName = "スロバキア"

[SI]
"Country Name" = "Slovenia"
ISO2 = "SI"
ISO3 = "SVN"
"Top Level Domain" = "si"
FIPS = "SI"
"ISO Numeric" = 705
GeoNameID = 3_190_538
E164 = 386
"Phone Code" = 386
Continent = "Europe"
Capital = "Ljubljana"
"Time Zone in Capital" = "Europe/Belgrade"
Currency = "Euro"
"Language Codes" = "sl,sh"
Languages = "Slovenian (official) 91.1%, Serbo-Croatian 4.5%, other or unspecified 4.4%, Italian (official, only in municipalities where Italian national communities reside), Hungarian (official, only in municipalities where Hungarian national communities reside) (2002 census)"
"Area KM2" = 20_273
"Internet Hosts" = 415_581
"Internet Users" = 1_298_000
"Phones (Mobile)" = 2_246_000
"Phones (Landline)" = 825_000
GDP = 46_820_000_000
englishShortName = "Slovenia"
frenchShortName = "Slovénie (la)"
numeric = 705
japaneseShortName = "スロベニア"

[SB]
"Country Name" = "Solomon Islands"
ISO2 = "SB"
ISO3 = "SLB"
"Top Level Domain" = "sb"
FIPS = "BP"
"ISO Numeric" = "090"
GeoNameID = 2_103_350
E164 = 677
"Phone Code" = 677
Continent = "Oceania"
Capital = "Honiara"
"Time Zone in Capital" = "Pacific/Guadalcanal"
Currency = "Dollar"
"Language Codes" = "en-SB,tpi"
Languages = "Melanesian pidgin (in much of the country is lingua franca), English (official but spoken by only 1%-2% of the population), 120 indigenous languages"
"Area KM2" = 28_450
"Internet Hosts" = 4_370
"Internet Users" = 10_000
"Phones (Mobile)" = 302_100
"Phones (Landline)" = 8_060
GDP = 1_099_000_000
englishShortName = "Solomon Islands"
frenchShortName = "Salomon (les Îles)"
numeric = 90
japaneseShortName = "ソロモン諸島"

[SO]
"Country Name" = "Somalia"
ISO2 = "SO"
ISO3 = "SOM"
"Top Level Domain" = "so"
FIPS = "SO"
"ISO Numeric" = 706
GeoNameID = 51_537
E164 = 252
"Phone Code" = 252
Continent = "Africa"
Capital = "Mogadishu"
"Time Zone in Capital" = "Africa/Mogadishu"
Currency = "Shilling"
"Language Codes" = "so-SO,ar-SO,it,en-SO"
Languages = "Somali (official), Arabic (official, according to the Transitional Federal Charter), Italian, English"
"Area KM2" = 637_657
"Internet Hosts" = 186
"Internet Users" = 106_000
"Phones (Mobile)" = 658_000
"Phones (Landline)" = 100_000
GDP = 2_372_000_000
englishShortName = "Somalia"
frenchShortName = "Somalie (la)"
numeric = 706
japaneseShortName = "ソマリア"

[ZA]
"Country Name" = "South Africa"
ISO2 = "ZA"
ISO3 = "ZAF"
"Top Level Domain" = "za"
FIPS = "SF"
"ISO Numeric" = 710
GeoNameID = 953_987
E164 = 27
"Phone Code" = 27
Continent = "Africa"
Capital = "Pretoria"
"Time Zone in Capital" = "Africa/Johannesburg"
Currency = "Rand"
"Language Codes" = "zu,xh,af,nso,en-ZA,tn,st,ts,ss,ve,nr"
Languages = "IsiZulu (official) 22.7%, IsiXhosa (official) 16%, Afrikaans (official) 13.5%, English (official) 9.6%, Sepedi (official) 9.1%, Setswana (official) 8%, Sesotho (official) 7.6%, Xitsonga (official) 4.5%, siSwati (official) 2.5%, Tshivenda (official) 2.4%, isiNdebele (official) 2.1%, sign language 0.5%, other 1.6% (2011 est.)"
"Area KM2" = 1_219_912
"Internet Hosts" = 4_761_000
"Internet Users" = 4_420_000
"Phones (Mobile)" = 68_400_000
"Phones (Landline)" = 4_030_000
GDP = 353_900_000_000
englishShortName = "South Africa"
frenchShortName = "Afrique du Sud (l')"
numeric = 710
japaneseShortName = "南アフリカ"

[KR]
"Country Name" = "South Korea"
ISO2 = "KR"
ISO3 = "KOR"
"Top Level Domain" = "kr"
FIPS = "KS"
"ISO Numeric" = 410
GeoNameID = 1_835_841
E164 = 82
"Phone Code" = 82
Continent = "Asia"
Capital = "Seoul"
"Time Zone in Capital" = "Asia/Seoul"
Currency = "Won"
"Language Codes" = "ko-KR,en"
Languages = "Korean, English (widely taught in junior high and high school)"
"Area KM2" = 98_480
"Internet Hosts" = 315_697
"Internet Users" = 39_400_000
"Phones (Mobile)" = 53_625_000
"Phones (Landline)" = 30_100_000
GDP = 1_198_000_000_000
englishShortName = "Korea (the Republic of)"
frenchShortName = "Corée (la République de)"
numeric = 410
japaneseShortName = "韓国"

[SS]
"Country Name" = "South Sudan"
ISO2 = "SS"
ISO3 = "SSD"
"Top Level Domain" = "ss"
FIPS = "OD"
"ISO Numeric" = 728
GeoNameID = 7_909_807
E164 = 211
"Phone Code" = 211
Continent = "Africa"
Capital = "Juba"
"Time Zone in Capital" = "Africa/Khartoum"
Currency = "Pound"
"Language Codes" = "en"
Languages = "English (official), Arabic (includes Juba and Sudanese variants), regional languages include Dinka, Nuer, Bari, Zande, Shilluk"
"Area KM2" = 644_329
"Internet Hosts" = ""
"Internet Users" = ""
"Phones (Mobile)" = 2_000_000
"Phones (Landline)" = 2_200
GDP = 11_770_000_000
englishShortName = "South Sudan"
frenchShortName = "Soudan du Sud (le)"
numeric = 728

[ES]
"Country Name" = "Spain"
ISO2 = "ES"
ISO3 = "ESP"
"Top Level Domain" = "es"
FIPS = "SP"
"ISO Numeric" = 724
GeoNameID = 2_510_769
E164 = 34
"Phone Code" = 34
Continent = "Europe"
Capital = "Madrid"
"Time Zone in Capital" = "Europe/Madrid"
Currency = "Euro"
"Language Codes" = "es-ES,ca,gl,eu,oc"
Languages = "Castilian Spanish (official) 74%, Catalan 17%, Galician 7%, and Basque 2%"
"Area KM2" = 504_782
"Internet Hosts" = 4_228_000
"Internet Users" = 28_119_000
"Phones (Mobile)" = 50_663_000
"Phones (Landline)" = 19_220_000
GDP = 1_356_000_000_000
englishShortName = "Spain"
frenchShortName = "Espagne (l')"
numeric = 724
japaneseShortName = "スペイン"

[LK]
"Country Name" = "Sri Lanka"
ISO2 = "LK"
ISO3 = "LKA"
"Top Level Domain" = "lk"
FIPS = "CE"
"ISO Numeric" = 144
GeoNameID = 1_227_603
E164 = 94
"Phone Code" = 94
Continent = "Asia"
Capital = "Colombo"
"Time Zone in Capital" = "Asia/Colombo"
Currency = "Rupee"
"Language Codes" = "si,ta,en"
Languages = "Sinhala (official and national language) 74%, Tamil (national language) 18%, other 8%"
"Area KM2" = 65_610
"Internet Hosts" = 9_552
"Internet Users" = 1_777_000
"Phones (Mobile)" = 19_533_000
"Phones (Landline)" = 2_796_000
GDP = 65_120_000_000
englishShortName = "Sri Lanka"
frenchShortName = "Sri Lanka"
numeric = 144
japaneseShortName = "スリランカ"

[SD]
"Country Name" = "Sudan"
ISO2 = "SD"
ISO3 = "SDN"
"Top Level Domain" = "sd"
FIPS = "SU"
"ISO Numeric" = 729
GeoNameID = 366_755
E164 = 249
"Phone Code" = 249
Continent = "Africa"
Capital = "Khartoum"
"Time Zone in Capital" = "Africa/Khartoum"
Currency = "Pound"
"Language Codes" = "ar-SD,en,fia"
Languages = "Arabic (official), English (official), Nubian, Ta Bedawie, Fur"
"Area KM2" = 1_861_484
"Internet Hosts" = 99
"Internet Users" = 4_200_000
"Phones (Mobile)" = 27_659_000
"Phones (Landline)" = 425_000
GDP = 52_500_000_000
englishShortName = "Sudan (the)"
frenchShortName = "Soudan (le)"
numeric = 729
japaneseShortName = "スーダン"

[SR]
"Country Name" = "Suriname"
ISO2 = "SR"
ISO3 = "SUR"
"Top Level Domain" = "sr"
FIPS = "NS"
"ISO Numeric" = 740
GeoNameID = 3_382_998
E164 = 597
"Phone Code" = 597
Continent = "South America"
Capital = "Paramaribo"
"Time Zone in Capital" = "America/Paramaribo"
Currency = "Dollar"
"Language Codes" = "nl-SR,en,srn,hns,jv"
Languages = "Dutch (official), English (widely spoken), Sranang Tongo (Surinamese, sometimes called Taki-Taki, is native language of Creoles and much of the younger population and is lingua franca among others), Caribbean Hindustani (a dialect of Hindi), Javanese"
"Area KM2" = 163_270
"Internet Hosts" = 188
"Internet Users" = 163_000
"Phones (Mobile)" = 977_000
"Phones (Landline)" = 83_000
GDP = 5_009_000_000
englishShortName = "Suriname"
frenchShortName = "Suriname (le)"
numeric = 740
japaneseShortName = "スリナム"

[SJ]
"Country Name" = "Svalbard and Jan Mayen"
ISO2 = "SJ"
ISO3 = "SJM"
"Top Level Domain" = "sj"
FIPS = "SV"
"ISO Numeric" = 744
GeoNameID = 607_072
E164 = 47
"Phone Code" = 47
Continent = "Europe"
Capital = "Longyearbyen"
"Time Zone in Capital" = "Europe/Oslo"
Currency = "Krone"
"Language Codes" = "no,ru"
Languages = "Norwegian, Russian"
"Area KM2" = 62_049
"Internet Hosts" = ""
"Internet Users" = ""
"Phones (Mobile)" = ""
"Phones (Landline)" = ""
GDP = ""
englishShortName = "Svalbard and Jan Mayen"
frenchShortName = "Svalbard et l'Île Jan Mayen (le)"
numeric = 744
japaneseShortName = "スヴァールバル諸島およびヤンマイエン島"

[SZ]
"Country Name" = "Swaziland"
ISO2 = "SZ"
ISO3 = "SWZ"
"Top Level Domain" = "sz"
FIPS = "WZ"
"ISO Numeric" = 748
GeoNameID = 934_841
E164 = 268
"Phone Code" = 268
Continent = "Africa"
Capital = "Mbabane"
"Time Zone in Capital" = "Africa/Johannesburg"
Currency = "Lilangeni"
"Language Codes" = "en-SZ,ss-SZ"
Languages = "English (official, used for government business), siSwati (official)"
"Area KM2" = 17_363
"Internet Hosts" = 2_744
"Internet Users" = 90_100
"Phones (Mobile)" = 805_000
"Phones (Landline)" = 48_600
GDP = 3_807_000_000
englishShortName = "Eswatini"
frenchShortName = "Eswatini (l')"
numeric = 748
japaneseShortName = "スワジランド"

[SE]
"Country Name" = "Sweden"
ISO2 = "SE"
ISO3 = "SWE"
"Top Level Domain" = "se"
FIPS = "SW"
"ISO Numeric" = 752
GeoNameID = 2_661_886
E164 = 46
"Phone Code" = 46
Continent = "Europe"
Capital = "Stockholm"
"Time Zone in Capital" = "Europe/Stockholm"
Currency = "Krona"
"Language Codes" = "sv-SE,se,sma,fi-SE"
Languages = "Swedish (official), small Sami- and Finnish-speaking minorities"
"Area KM2" = 449_964
"Internet Hosts" = 5_978_000
"Internet Users" = 8_398_000
"Phones (Mobile)" = 11_643_000
"Phones (Landline)" = 4_321_000
GDP = 552_000_000_000
englishShortName = "Sweden"
frenchShortName = "Suède (la)"
numeric = 752
japaneseShortName = "スウェーデン"

[CH]
"Country Name" = "Switzerland"
ISO2 = "CH"
ISO3 = "CHE"
"Top Level Domain" = "ch"
FIPS = "SZ"
"ISO Numeric" = 756
GeoNameID = 2_658_434
E164 = 41
"Phone Code" = 41
Continent = "Europe"
Capital = "Berne"
"Time Zone in Capital" = "Europe/Zurich"
Currency = "Franc"
"Language Codes" = "de-CH,fr-CH,it-CH,rm"
Languages = "German (official) 64.9%, French (official) 22.6%, Italian (official) 8.3%, Serbo-Croatian 2.5%, Albanian 2.6%, Portuguese 3.4%, Spanish 2.2%, English 4.6%, Romansch (official) 0.5%, other 5.1%"
"Area KM2" = 41_290
"Internet Hosts" = 5_301_000
"Internet Users" = 6_152_000
"Phones (Mobile)" = 10_460_000
"Phones (Landline)" = 4_382_000
GDP = 646_200_000_000
englishShortName = "Switzerland"
frenchShortName = "Suisse (la)"
numeric = 756
japaneseShortName = "スイス"

[SY]
"Country Name" = "Syria"
ISO2 = "SY"
ISO3 = "SYR"
"Top Level Domain" = "sy"
FIPS = "SY"
"ISO Numeric" = 760
GeoNameID = 163_843
E164 = 963
"Phone Code" = 963
Continent = "Asia"
Capital = "Damascus"
"Time Zone in Capital" = "Asia/Damascus"
Currency = "Pound"
"Language Codes" = "ar-SY,ku,hy,arc,fr,en"
Languages = "Arabic (official), Kurdish, Armenian, Aramaic, Circassian (widely understood); French, English (somewhat understood)"
"Area KM2" = 185_180
"Internet Hosts" = 416
"Internet Users" = 4_469_000
"Phones (Mobile)" = 12_928_000
"Phones (Landline)" = 4_425_000
GDP = 64_700_000_000
englishShortName = "Syrian Arab Republic (the)"
frenchShortName = "République arabe syrienne (la)"
numeric = 760
japaneseShortName = "シリア"

[TW]
"Country Name" = "Taiwan"
ISO2 = "TW"
ISO3 = "TWN"
"Top Level Domain" = "tw"
FIPS = "TW"
"ISO Numeric" = 158
GeoNameID = 1_668_284
E164 = 886
"Phone Code" = 886
Continent = "Asia"
Capital = "Taipei"
"Time Zone in Capital" = "Asia/Taipei"
Currency = "Dollar"
"Language Codes" = "zh-TW,zh,nan,hak"
Languages = "Mandarin Chinese (official), Taiwanese (Min), Hakka dialects"
"Area KM2" = 35_980
"Internet Hosts" = 6_272_000
"Internet Users" = 16_147_000
"Phones (Mobile)" = 29_455_000
"Phones (Landline)" = 15_998_000
GDP = 484_700_000_000
englishShortName = "Taiwan (Province of China)"
frenchShortName = "Taïwan (Province de Chine)"
numeric = 158
japaneseShortName = "台湾"

[TJ]
"Country Name" = "Tajikistan"
ISO2 = "TJ"
ISO3 = "TJK"
"Top Level Domain" = "tj"
FIPS = "TI"
"ISO Numeric" = 762
GeoNameID = 1_220_409
E164 = 992
"Phone Code" = 992
Continent = "Asia"
Capital = "Dushanbe"
"Time Zone in Capital" = "Asia/Dushanbe"
Currency = "Somoni"
"Language Codes" = "tg,ru"
Languages = "Tajik (official), Russian widely used in government and business"
"Area KM2" = 143_100
"Internet Hosts" = 6_258
"Internet Users" = 700_000
"Phones (Mobile)" = 6_528_000
"Phones (Landline)" = 393_000
GDP = 8_513_000_000
englishShortName = "Tajikistan"
frenchShortName = "Tadjikistan (le)"
numeric = 762
japaneseShortName = "タジキスタン"

[TZ]
"Country Name" = "Tanzania"
ISO2 = "TZ"
ISO3 = "TZA"
"Top Level Domain" = "tz"
FIPS = "TZ"
"ISO Numeric" = 834
GeoNameID = 149_590
E164 = 255
"Phone Code" = 255
Continent = "Africa"
Capital = "Dodoma"
"Time Zone in Capital" = "Africa/Dar_es_Salaam"
Currency = "Shilling"
"Language Codes" = "sw-TZ,en,ar"
Languages = "Kiswahili or Swahili (official), Kiunguja (name for Swahili in Zanzibar), English (official, primary language of commerce, administration, and higher education), Arabic (widely spoken in Zanzibar), many local languages"
"Area KM2" = 945_087
"Internet Hosts" = 26_074
"Internet Users" = 678_000
"Phones (Mobile)" = 27_220_000
"Phones (Landline)" = 161_100
GDP = 31_940_000_000
englishShortName = "Tanzania, the United Republic of"
frenchShortName = "Tanzanie (la République-Unie de)"
numeric = 834
japaneseShortName = "タンザニア"

[TH]
"Country Name" = "Thailand"
ISO2 = "TH"
ISO3 = "THA"
"Top Level Domain" = "th"
FIPS = "TH"
"ISO Numeric" = 764
GeoNameID = 1_605_651
E164 = 66
"Phone Code" = 66
Continent = "Asia"
Capital = "Bangkok"
"Time Zone in Capital" = "Asia/Bangkok"
Currency = "Baht"
"Language Codes" = "th,en"
Languages = "Thai (official) 90.7%, Burmese 1.3%, other 8%"
"Area KM2" = 514_000
"Internet Hosts" = 3_399_000
"Internet Users" = 17_483_000
"Phones (Mobile)" = 84_075_000
"Phones (Landline)" = 6_391_000
GDP = 400_900_000_000
englishShortName = "Thailand"
frenchShortName = "Thaïlande (la)"
numeric = 764
japaneseShortName = "タイ"

[TG]
"Country Name" = "Togo"
ISO2 = "TG"
ISO3 = "TGO"
"Top Level Domain" = "tg"
FIPS = "TO"
"ISO Numeric" = 768
GeoNameID = 2_363_686
E164 = 228
"Phone Code" = 228
Continent = "Africa"
Capital = "Lome"
"Time Zone in Capital" = "Africa/Abidjan"
Currency = "Franc"
"Language Codes" = "fr-TG,ee,hna,kbp,dag,ha"
Languages = "French (official, the language of commerce), Ewe and Mina (the two major African languages in the south), Kabye (sometimes spelled Kabiye) and Dagomba (the two major African languages in the north)"
"Area KM2" = 56_785
"Internet Hosts" = 1_168
"Internet Users" = 356_300
"Phones (Mobile)" = 3_518_000
"Phones (Landline)" = 225_000
GDP = 4_299_000_000
englishShortName = "Togo"
frenchShortName = "Togo (le)"
numeric = 768
japaneseShortName = "トーゴ"

[TK]
"Country Name" = "Tokelau"
ISO2 = "TK"
ISO3 = "TKL"
"Top Level Domain" = "tk"
FIPS = "TL"
"ISO Numeric" = 772
GeoNameID = 4_031_074
E164 = 690
"Phone Code" = 690
Continent = "Oceania"
Capital = ""
"Time Zone in Capital" = "Pacific/Fakaofo"
Currency = "Dollar"
"Language Codes" = "tkl,en-TK"
Languages = "Tokelauan 93.5% (a Polynesian language), English 58.9%, Samoan 45.5%, Tuvaluan 11.6%, Kiribati 2.7%, other 2.5%, none 4.1%, unspecified 0.6%"
"Area KM2" = 10
"Internet Hosts" = 2_069
"Internet Users" = 800
"Phones (Mobile)" = ""
"Phones (Landline)" = ""
GDP = ""
englishShortName = "Tokelau"
frenchShortName = "Tokelau (les)"
numeric = 772
japaneseShortName = "トケラウ"

[TO]
"Country Name" = "Tonga"
ISO2 = "TO"
ISO3 = "TON"
"Top Level Domain" = "to"
FIPS = "TN"
"ISO Numeric" = 776
GeoNameID = 4_032_283
E164 = 676
"Phone Code" = 676
Continent = "Oceania"
Capital = "Nuku'alofa"
"Time Zone in Capital" = "Pacific/Tongatapu"
Currency = "Pa'anga"
"Language Codes" = "to,en-TO"
Languages = "English and Tongan 87%, Tongan (official) 10.7%, English (official) 1.2%, other 1.1%, uspecified 0.03% (2006 est.)"
"Area KM2" = 748
"Internet Hosts" = 5_367
"Internet Users" = 8_400
"Phones (Mobile)" = 56_000
"Phones (Landline)" = 30_000
GDP = 477_000_000
englishShortName = "Tonga"
frenchShortName = "Tonga (les)"
numeric = 776
japaneseShortName = "トンガ王国"

[TT]
"Country Name" = "Trinidad and Tobago"
ISO2 = "TT"
ISO3 = "TTO"
"Top Level Domain" = "tt"
FIPS = "TD"
"ISO Numeric" = 780
GeoNameID = 3_573_591
E164 = 1
"Phone Code" = "1-868"
Continent = "North America"
Capital = "Port of Spain"
"Time Zone in Capital" = "America/Port_of_Spain"
Currency = "Dollar"
"Language Codes" = "en-TT,hns,fr,es,zh"
Languages = "English (official), Caribbean Hindustani (a dialect of Hindi), French, Spanish, Chinese"
"Area KM2" = 5_128
"Internet Hosts" = 241_690
"Internet Users" = 593_000
"Phones (Mobile)" = 1_884_000
"Phones (Landline)" = 287_000
GDP = 27_130_000_000
englishShortName = "Trinidad and Tobago"
frenchShortName = "Trinité-et-Tobago (la)"
numeric = 780
japaneseShortName = "トリニダード・トバゴ"

[TN]
"Country Name" = "Tunisia"
ISO2 = "TN"
ISO3 = "TUN"
"Top Level Domain" = "tn"
FIPS = "TS"
"ISO Numeric" = 788
GeoNameID = 2_464_461
E164 = 216
"Phone Code" = 216
Continent = "Africa"
Capital = "Tunis"
"Time Zone in Capital" = "Africa/Tunis"
Currency = "Dinar"
"Language Codes" = "ar-TN,fr"
Languages = "Arabic (official, one of the languages of commerce), French (commerce), Berber (Tamazight)"
"Area KM2" = 163_610
"Internet Hosts" = 576
"Internet Users" = 3_500_000
"Phones (Mobile)" = 12_840_000
"Phones (Landline)" = 1_105_000
GDP = 48_380_000_000
englishShortName = "Tunisia"
frenchShortName = "Tunisie (la)"
numeric = 788
japaneseShortName = "チュニジア"

[TR]
"Country Name" = "Turkey"
ISO2 = "TR"
ISO3 = "TUR"
"Top Level Domain" = "tr"
FIPS = "TU"
"ISO Numeric" = 792
GeoNameID = 298_795
E164 = 90
"Phone Code" = 90
Continent = "Asia"
Capital = "Ankara"
"Time Zone in Capital" = "Europe/Istanbul"
Currency = "Lira"
"Language Codes" = "tr-TR,ku,diq,az,av"
Languages = "Turkish (official), Kurdish, other minority languages"
"Area KM2" = 780_580
"Internet Hosts" = 7_093_000
"Internet Users" = 27_233_000
"Phones (Mobile)" = 67_680_000
"Phones (Landline)" = 13_860_000
GDP = 821_800_000_000
englishShortName = "Turkey"
frenchShortName = "Turquie (la)"
numeric = 792
japaneseShortName = "トルコ"

[TM]
"Country Name" = "Turkmenistan"
ISO2 = "TM"
ISO3 = "TKM"
"Top Level Domain" = "tm"
FIPS = "TX"
"ISO Numeric" = 795
GeoNameID = 1_218_197
E164 = 993
"Phone Code" = 993
Continent = "Asia"
Capital = "Ashgabat"
"Time Zone in Capital" = "Asia/Ashgabat"
Currency = "Manat"
"Language Codes" = "tk,ru,uz"
Languages = "Turkmen (official) 72%, Russian 12%, Uzbek 9%, other 7%"
"Area KM2" = 488_100
"Internet Hosts" = 714
"Internet Users" = 80_400
"Phones (Mobile)" = 3_953_000
"Phones (Landline)" = 575_000
GDP = 40_560_000_000
englishShortName = "Turkmenistan"
frenchShortName = "Turkménistan (le)"
numeric = 795
japaneseShortName = "トルクメニスタン"

[TC]
"Country Name" = "Turks and Caicos Islands"
ISO2 = "TC"
ISO3 = "TCA"
"Top Level Domain" = "tc"
FIPS = "TK"
"ISO Numeric" = 796
GeoNameID = 3_576_916
E164 = 1
"Phone Code" = "1-649"
Continent = "North America"
Capital = "Cockburn Town"
"Time Zone in Capital" = "America/Grand_Turk"
Currency = "Dollar"
"Language Codes" = "en-TC"
Languages = "English (official)"
"Area KM2" = 430
"Internet Hosts" = 73_217
"Internet Users" = ""
"Phones (Mobile)" = ""
"Phones (Landline)" = ""
GDP = ""
englishShortName = "Turks and Caicos Islands (the)"
frenchShortName = "Turks-et-Caïcos (les Îles)"
numeric = 796
japaneseShortName = "タークス・カイコス諸島"

[TV]
"Country Name" = "Tuvalu"
ISO2 = "TV"
ISO3 = "TUV"
"Top Level Domain" = "tv"
FIPS = "TV"
"ISO Numeric" = 798
GeoNameID = 2_110_297
E164 = 688
"Phone Code" = 688
Continent = "Oceania"
Capital = "Funafuti"
"Time Zone in Capital" = "Pacific/Funafuti"
Currency = "Dollar"
"Language Codes" = "tvl,en,sm,gil"
Languages = "Tuvaluan (official), English (official), Samoan, Kiribati (on the island of Nui)"
"Area KM2" = 26
"Internet Hosts" = 145_158
"Internet Users" = 4_200
"Phones (Mobile)" = 2_800
"Phones (Landline)" = 1_450
GDP = 38_000_000
englishShortName = "Tuvalu"
frenchShortName = "Tuvalu (les)"
numeric = 798
japaneseShortName = "ツバル"

[VI]
"Country Name" = "U.S. Virgin Islands"
ISO2 = "VI"
ISO3 = "VIR"
"Top Level Domain" = "vi"
FIPS = "VQ"
"ISO Numeric" = 850
GeoNameID = 4_796_775
E164 = 1
"Phone Code" = "1-340"
Continent = "North America"
Capital = "Charlotte Amalie"
"Time Zone in Capital" = "America/Port_of_Spain"
Currency = "Dollar"
"Language Codes" = "en-VI"
Languages = "English 74.7%, Spanish or Spanish Creole 16.8%, French or French Creole 6.6%, other 1.9% (2000 census)"
"Area KM2" = 352
"Internet Hosts" = 4_790
"Internet Users" = 30_000
"Phones (Mobile)" = 80_300
"Phones (Landline)" = 75_800
GDP = ""
englishShortName = "Virgin Islands (U.S.)"
frenchShortName = "Vierges des États-Unis (les Îles)"
numeric = 850
japaneseShortName = "アメリカ領ヴァージン諸島"

[UG]
"Country Name" = "Uganda"
ISO2 = "UG"
ISO3 = "UGA"
"Top Level Domain" = "ug"
FIPS = "UG"
"ISO Numeric" = 800
GeoNameID = 226_074
E164 = 256
"Phone Code" = 256
Continent = "Africa"
Capital = "Kampala"
"Time Zone in Capital" = "Africa/Kampala"
Currency = "Shilling"
"Language Codes" = "en-UG,lg,sw,ar"
Languages = "English (official national language, taught in grade schools, used in courts of law and by most newspapers and some radio broadcasts), Ganda or Luganda (most widely used of the Niger-Congo languages, preferred for native language publications in the capital and may be taught in school), other Niger-Congo languages, Nilo-Saharan languages, Swahili, Arabic"
"Area KM2" = 236_040
"Internet Hosts" = 32_683
"Internet Users" = 3_200_000
"Phones (Mobile)" = 16_355_000
"Phones (Landline)" = 315_000
GDP = 22_600_000_000
englishShortName = "Uganda"
frenchShortName = "Ouganda (l')"
numeric = 800
japaneseShortName = "ウガンダ"

[UA]
"Country Name" = "Ukraine"
ISO2 = "UA"
ISO3 = "UKR"
"Top Level Domain" = "ua"
FIPS = "UP"
"ISO Numeric" = 804
GeoNameID = 690_791
E164 = 380
"Phone Code" = 380
Continent = "Europe"
Capital = "Kiev"
"Time Zone in Capital" = "Europe/Kiev"
Currency = "Hryvnia"
"Language Codes" = "uk,ru-UA,rom,pl,hu"
Languages = "Ukrainian (official) 67%, Russian (regional language) 24%, other (includes small Romanian-, Polish-, and Hungarian-speaking minorities) 9%"
"Area KM2" = 603_700
"Internet Hosts" = 2_173_000
"Internet Users" = 7_770_000
"Phones (Mobile)" = 59_344_000
"Phones (Landline)" = 12_182_000
GDP = 175_500_000_000
englishShortName = "Ukraine"
frenchShortName = "Ukraine (l')"
numeric = 804
japaneseShortName = "ウクライナ"

[AE]
"Country Name" = "United Arab Emirates"
ISO2 = "AE"
ISO3 = "ARE"
"Top Level Domain" = "ae"
FIPS = "AE"
"ISO Numeric" = 784
GeoNameID = 290_557
E164 = 971
"Phone Code" = 971
Continent = "Asia"
Capital = "Abu Dhabi"
"Time Zone in Capital" = "Asia/Dubai"
Currency = "Dirham"
"Language Codes" = "ar-AE,fa,en,hi,ur"
Languages = "Arabic (official), Persian, English, Hindi, Urdu"
"Area KM2" = 82_880
"Internet Hosts" = 337_804
"Internet Users" = 3_449_000
"Phones (Mobile)" = 13_775_000
"Phones (Landline)" = 1_967_000
GDP = 390_000_000_000
englishShortName = "United Arab Emirates (the)"
frenchShortName = "Émirats arabes unis (les)"
numeric = 784
japaneseShortName = "アラブ首長国連邦"

[GB]
"Country Name" = "United Kingdom"
ISO2 = "GB"
ISO3 = "GBR"
"Top Level Domain" = "uk"
FIPS = "UK"
"ISO Numeric" = 826
GeoNameID = 2_635_167
E164 = 44
"Phone Code" = 44
Continent = "Europe"
Capital = "London"
"Time Zone in Capital" = "Europe/London"
Currency = "Pound"
"Language Codes" = "en-GB,cy-GB,gd"
Languages = "English"
"Area KM2" = 244_820
"Internet Hosts" = 8_107_000
"Internet Users" = 51_444_000
"Phones (Mobile)" = 82_109_000
"Phones (Landline)" = 33_010_000
GDP = 2_490_000_000_000
englishShortName = "United Kingdom of Great Britain and Northern Ireland (the)"
frenchShortName = "Royaume-Uni de Grande-Bretagne et d'Irlande du Nord (le)"
numeric = 826
japaneseShortName = "イギリス"

[US]
"Country Name" = "United States"
ISO2 = "US"
ISO3 = "USA"
"Top Level Domain" = "us"
FIPS = "US"
"ISO Numeric" = 840
GeoNameID = 6_252_001
E164 = 1
"Phone Code" = 1
Continent = "North America"
Capital = "Washington"
"Time Zone in Capital" = "America/New_York"
Currency = "Dollar"
"Language Codes" = "en-US,es-US,haw,fr"
Languages = "English 82.1%, Spanish 10.7%, other Indo-European 3.8%, Asian and Pacific island 2.7%, other 0.7% (2000 census)"
"Area KM2" = 9_629_091
"Internet Hosts" = 505_000_000
"Internet Users" = 245_000_000
"Phones (Mobile)" = 310_000_000
"Phones (Landline)" = 139_000_000
GDP = 16_720_000_000_000
englishShortName = "United States of America (the)"
frenchShortName = "États-Unis d'Amérique (les)"
numeric = 840
japaneseShortName = "アメリカ合衆国"

[UY]
"Country Name" = "Uruguay"
ISO2 = "UY"
ISO3 = "URY"
"Top Level Domain" = "uy"
FIPS = "UY"
"ISO Numeric" = 858
GeoNameID = 3_439_705
E164 = 598
"Phone Code" = 598
Continent = "South America"
Capital = "Montevideo"
"Time Zone in Capital" = "America/Montevideo"
Currency = "Peso"
"Language Codes" = "es-UY"
Languages = "Spanish (official), Portunol, Brazilero (Portuguese-Spanish mix on the Brazilian frontier)"
"Area KM2" = 176_220
"Internet Hosts" = 1_036_000
"Internet Users" = 1_405_000
"Phones (Mobile)" = 5_000_000
"Phones (Landline)" = 1_010_000
GDP = 57_110_000_000
englishShortName = "Uruguay"
frenchShortName = "Uruguay (l')"
numeric = 858
japaneseShortName = "ウルグアイ"

[UZ]
"Country Name" = "Uzbekistan"
ISO2 = "UZ"
ISO3 = "UZB"
"Top Level Domain" = "uz"
FIPS = "UZ"
"ISO Numeric" = 860
GeoNameID = 1_512_440
E164 = 998
"Phone Code" = 998
Continent = "Asia"
Capital = "Tashkent"
"Time Zone in Capital" = "Asia/Tashkent"
Currency = "Som"
"Language Codes" = "uz,ru,tg"
Languages = "Uzbek (official) 74.3%, Russian 14.2%, Tajik 4.4%, other 7.1%"
"Area KM2" = 447_400
"Internet Hosts" = 56_075
"Internet Users" = 4_689_000
"Phones (Mobile)" = 20_274_000
"Phones (Landline)" = 1_963_000
GDP = 55_180_000_000
englishShortName = "Uzbekistan"
frenchShortName = "Ouzbékistan (l')"
numeric = 860
japaneseShortName = "ウズベキスタン"

[VU]
"Country Name" = "Vanuatu"
ISO2 = "VU"
ISO3 = "VUT"
"Top Level Domain" = "vu"
FIPS = "NH"
"ISO Numeric" = 548
GeoNameID = 2_134_431
E164 = 678
"Phone Code" = 678
Continent = "Oceania"
Capital = "Port Vila"
"Time Zone in Capital" = "Pacific/Efate"
Currency = "Vatu"
"Language Codes" = "bi,en-VU,fr-VU"
Languages = "local languages (more than 100) 63.2%, Bislama (official; creole) 33.7%, English (official) 2%, French (official) 0.6%, other 0.5% (2009 est.)"
"Area KM2" = 12_200
"Internet Hosts" = 5_655
"Internet Users" = 17_000
"Phones (Mobile)" = 137_000
"Phones (Landline)" = 5_800
GDP = 828_000_000
englishShortName = "Vanuatu"
frenchShortName = "Vanuatu (le)"
numeric = 548
japaneseShortName = "バヌアツ"

[VA]
"Country Name" = "Vatican"
ISO2 = "VA"
ISO3 = "VAT"
"Top Level Domain" = "va"
FIPS = "VT"
"ISO Numeric" = 336
GeoNameID = 3_164_670
E164 = 39
"Phone Code" = 379
Continent = "Europe"
Capital = "Vatican City"
"Time Zone in Capital" = "Europe/Rome"
Currency = "Euro"
"Language Codes" = "la,it,fr"
Languages = "Latin, Italian, French"
"Area KM2" = 0
"Internet Hosts" = ""
"Internet Users" = ""
"Phones (Mobile)" = ""
"Phones (Landline)" = ""
GDP = ""
englishShortName = "Holy See (the)"
frenchShortName = "Saint-Siège (le)"
numeric = 336
japaneseShortName = "バチカン市国"

[VE]
"Country Name" = "Venezuela"
ISO2 = "VE"
ISO3 = "VEN"
"Top Level Domain" = "ve"
FIPS = "VE"
"ISO Numeric" = 862
GeoNameID = 3_625_428
E164 = 58
"Phone Code" = 58
Continent = "South America"
Capital = "Caracas"
"Time Zone in Capital" = "America/Caracas"
Currency = "Bolivar"
"Language Codes" = "es-VE"
Languages = "Spanish (official), numerous indigenous dialects"
"Area KM2" = 912_050
"Internet Hosts" = 1_016_000
"Internet Users" = 8_918_000
"Phones (Mobile)" = 30_520_000
"Phones (Landline)" = 7_650_000
GDP = 367_500_000_000
englishShortName = "Venezuela (Bolivarian Republic of)"
frenchShortName = "Venezuela (République bolivarienne du)"
numeric = 862
japaneseShortName = "ベネズエラ"

[VN]
"Country Name" = "Vietnam"
ISO2 = "VN"
ISO3 = "VNM"
"Top Level Domain" = "vn"
FIPS = "VM"
"ISO Numeric" = 704
GeoNameID = 1_562_822
E164 = 84
"Phone Code" = 84
Continent = "Asia"
Capital = "Hanoi"
"Time Zone in Capital" = "Asia/Ho_Chi_Minh"
Currency = "Dong"
"Language Codes" = "vi,en,fr,zh,km"
Languages = "Vietnamese (official), English (increasingly favored as a second language), some French, Chinese, and Khmer, mountain area languages (Mon-Khmer and Malayo-Polynesian)"
"Area KM2" = 329_560
"Internet Hosts" = 189_553
"Internet Users" = 23_382_000
"Phones (Mobile)" = 134_066_000
"Phones (Landline)" = 10_191_000
GDP = 170_000_000_000
englishShortName = "Viet Nam"
frenchShortName = "Viet Nam (le)"
numeric = 704
japaneseShortName = "ベトナム"

[WF]
"Country Name" = "Wallis and Futuna"
ISO2 = "WF"
ISO3 = "WLF"
"Top Level Domain" = "wf"
FIPS = "WF"
"ISO Numeric" = 876
GeoNameID = 4_034_749
E164 = 681
"Phone Code" = 681
Continent = "Oceania"
Capital = "Mata Utu"
"Time Zone in Capital" = "Pacific/Wallis"
Currency = "Franc"
"Language Codes" = "wls,fud,fr-WF"
Languages = "Wallisian (indigenous Polynesian language) 58.9%, Futunian 30.1%, French (official) 10.8%, other 0.2% (2003 census)"
"Area KM2" = 274
"Internet Hosts" = 2_760
"Internet Users" = 1_300
"Phones (Mobile)" = ""
"Phones (Landline)" = ""
GDP = ""
englishShortName = "Wallis and Futuna"
frenchShortName = "Wallis-et-Futuna"
numeric = 876
japaneseShortName = "ウォリス・フツナ"

[EH]
"Country Name" = "Western Sahara"
ISO2 = "EH"
ISO3 = "ESH"
"Top Level Domain" = "eh"
FIPS = "WI"
"ISO Numeric" = 732
GeoNameID = 2_461_445
E164 = 212
"Phone Code" = 212
Continent = "Africa"
Capital = "El-Aaiun"
"Time Zone in Capital" = "Africa/El_Aaiun"
Currency = "Dirham"
"Language Codes" = "ar,mey"
Languages = "Standard Arabic (national), Hassaniya Arabic, Moroccan Arabic"
"Area KM2" = 266_000
"Internet Hosts" = ""
"Internet Users" = ""
"Phones (Mobile)" = ""
"Phones (Landline)" = ""
GDP = ""
englishShortName = "Western Sahara*"
frenchShortName = "Sahara occidental (le)*"
numeric = 732
japaneseShortName = "西サハラ"

[YE]
"Country Name" = "Yemen"
ISO2 = "YE"
ISO3 = "YEM"
"Top Level Domain" = "ye"
FIPS = "YM"
"ISO Numeric" = 887
GeoNameID = 69_543
E164 = 967
"Phone Code" = 967
Continent = "Asia"
Capital = "Sanaa"
"Time Zone in Capital" = "Asia/Aden"
Currency = "Rial"
"Language Codes" = "ar-YE"
Languages = "Arabic (official)"
"Area KM2" = 527_970
"Internet Hosts" = 33_206
"Internet Users" = 2_349_000
"Phones (Mobile)" = 13_900_000
"Phones (Landline)" = 1_100_000
GDP = 43_890_000_000
englishShortName = "Yemen"
frenchShortName = "Yémen (le)"
numeric = 887
japaneseShortName = "イエメン"

[ZM]
"Country Name" = "Zambia"
ISO2 = "ZM"
ISO3 = "ZMB"
"Top Level Domain" = "zm"
FIPS = "ZA"
"ISO Numeric" = 894
GeoNameID = 895_949
E164 = 260
"Phone Code" = 260
Continent = "Africa"
Capital = "Lusaka"
"Time Zone in Capital" = "Africa/Maputo"
Currency = "Kwacha"
"Language Codes" = "en-ZM,bem,loz,lun,lue,ny,toi"
Languages = "Bembe 33.4%, Nyanja 14.7%, Tonga 11.4%, Lozi 5.5%, Chewa 4.5%, Nsenga 2.9%, Tumbuka 2.5%, Lunda (North Western) 1.9%, Kaonde 1.8%, Lala 1.8%, Lamba 1.8%, English (official) 1.7%, Luvale 1.5%, Mambwe 1.3%, Namwanga 1.2%, Lenje 1.1%, Bisa 1%, other 9.2%, unspecified 0.4%"
"Area KM2" = 752_614
"Internet Hosts" = 16_571
"Internet Users" = 816_200
"Phones (Mobile)" = 10_525_000
"Phones (Landline)" = 82_500
GDP = 22_240_000_000
englishShortName = "Zambia"
frenchShortName = "Zambie (la)"
numeric = 894
japaneseShortName = "ザンビア"

[ZW]
"Country Name" = "Zimbabwe"
ISO2 = "ZW"
ISO3 = "ZWE"
"Top Level Domain" = "zw"
FIPS = "ZI"
"ISO Numeric" = 716
GeoNameID = 878_675
E164 = 263
"Phone Code" = 263
Continent = "Africa"
Capital = "Harare"
"Time Zone in Capital" = "Africa/Maputo"
Currency = "Dollar"
"Language Codes" = "en-ZW,sn,nr,nd"
Languages = "English (official), Shona, Sindebele (the language of the Ndebele, sometimes called Ndebele), numerous but minor tribal dialects"
"Area KM2" = 390_580
"Internet Hosts" = 30_615
"Internet Users" = 1_423_000
"Phones (Mobile)" = 12_614_000
"Phones (Landline)" = 301_600
GDP = 10_480_000_000
englishShortName = "Zimbabwe"
frenchShortName = "Zimbabwe (le)"
numeric = 716
japaneseShortName = "ジンバブエ"

[AX]
"Country Name" = "Aland Islands"
englishShortName = "Åland Islands"
frenchShortName = "Åland(les Îles)"
numeric = 248
japaneseShortName = "アランド諸島"

[BV]
"Country Name" = "Bouvet Island"
englishShortName = "Bouvet Island"
frenchShortName = "Bouvet (l'Île)"
numeric = 74
japaneseShortName = "ブーベ島"

[GF]
"Country Name" = "French Guiana"
englishShortName = "French Guiana"
frenchShortName = "Guyane française (la )"
numeric = 254
japaneseShortName = "フランス領ギアナ"

[TF]
"Country Name" = "French Southern Territories"
englishShortName = "French Southern Territories (the)"
frenchShortName = "Terres australes françaises (les)"
numeric = 260
japaneseShortName = "フランス領南方領土"

[GP]
"Country Name" = "Guadeloupe"
englishShortName = "Guadeloupe"
frenchShortName = "Guadeloupe (la)"
numeric = 312
japaneseShortName = "グアドループ島"

[HM]
"Country Name" = "Heard Island & Mcdonald Islands"
englishShortName = "Heard Island and McDonald Islands"
frenchShortName = "Heard-et-Îles MacDonald (l'Île)"
numeric = 334
japaneseShortName = "ハード島とマクドナルド諸島"

[MQ]
"Country Name" = "Martinique"
englishShortName = "Martinique"
frenchShortName = "Martinique (la)"
numeric = 474
japaneseShortName = "マルティニーク"

[NF]
"Country Name" = "Norfolk Island"
englishShortName = "Norfolk Island"
frenchShortName = "Norfolk (l'Île)"
numeric = 574
japaneseShortName = "ノーフォーク島"

[GS]
"Country Name" = "South Georgia And Sandwich Isl."
englishShortName = "South Georgia and the South Sandwich Islands"
frenchShortName = "Géorgie du Sud-et-les Îles Sandwich du Sud (la)"
numeric = 239
japaneseShortName = "サウスジョージア・サウスサンドウィッチ諸島"

[UM]
"Country Name" = "United States Outlying Islands"
englishShortName = "United States Minor Outlying Islands (the)"
frenchShortName = "Îles mineures éloignées des États-Unis (les)"
numeric = 581
japaneseShortName = "合衆国領有小離島"

5.4 - Leetcode submissions

Leetcode submission data

5.5 - License

License data

5.6 - Mullvad

Mullvad data

Update relay data:

bazel run //data/mullvad:update_relays
cat data/mullvad/relays.json  | jq -r ".wireguard.relays[] | select(.active) | .hostname"
{
  "locations": {
    "au-adl": {
      "country": "Australia",
      "city": "Adelaide",
      "latitude": -34.92123,
      "longitude": 138.599503
    },
    "nl-ams": {
      "country": "Netherlands",
      "city": "Amsterdam",
      "latitude": 52.35,
      "longitude": 4.916667
    },
    "us-qas": {
      "country": "USA",
      "city": "Ashburn, VA",
      "latitude": 39.043757,
      "longitude": -77.487442
    },
    "gr-ath": {
      "country": "Greece",
      "city": "Athens",
      "latitude": 37.98381,
      "longitude": 23.727539
    },
    "us-atl": {
      "country": "USA",
      "city": "Atlanta, GA",
      "latitude": 33.753746,
      "longitude": -84.38633
    },
    "nz-akl": {
      "country": "New Zealand",
      "city": "Auckland",
      "latitude": -36.848461,
      "longitude": 174.763336
    },
    "th-bkk": {
      "country": "Thailand",
      "city": "Bangkok",
      "latitude": 13.756331,
      "longitude": 100.501762
    },
    "es-bcn": {
      "country": "Spain",
      "city": "Barcelona",
      "latitude": 41.385063,
      "longitude": 2.173404
    },
    "rs-beg": {
      "country": "Serbia",
      "city": "Belgrade",
      "latitude": 44.787197,
      "longitude": 20.457273
    },
    "de-ber": {
      "country": "Germany",
      "city": "Berlin",
      "latitude": 52.520008,
      "longitude": 13.404954
    },
    "co-bog": {
      "country": "Colombia",
      "city": "Bogota",
      "latitude": 4.624335,
      "longitude": -74.063644
    },
    "fr-bod": {
      "country": "France",
      "city": "Bordeaux",
      "latitude": 44.837788,
      "longitude": -0.57918
    },
    "us-bos": {
      "country": "USA",
      "city": "Boston, MA",
      "latitude": 42.361145,
      "longitude": -71.057083
    },
    "sk-bts": {
      "country": "Slovakia",
      "city": "Bratislava",
      "latitude": 48.148598,
      "longitude": 17.107748
    },
    "au-bne": {
      "country": "Australia",
      "city": "Brisbane",
      "latitude": -27.471,
      "longitude": 153.0234
    },
    "be-bru": {
      "country": "Belgium",
      "city": "Brussels",
      "latitude": 50.833333,
      "longitude": 4.333333
    },
    "ro-buh": {
      "country": "Romania",
      "city": "Bucharest",
      "latitude": 44.433333,
      "longitude": 26.1
    },
    "hu-bud": {
      "country": "Hungary",
      "city": "Budapest",
      "latitude": 47.5,
      "longitude": 19.083333
    },
    "ar-bue": {
      "country": "Argentina",
      "city": "Buenos Aires",
      "latitude": -34.474561,
      "longitude": -58.664522
    },
    "ca-yyc": {
      "country": "Canada",
      "city": "Calgary",
      "latitude": 51.037007,
      "longitude": -114.058315
    },
    "us-chi": {
      "country": "USA",
      "city": "Chicago, IL",
      "latitude": 41.881832,
      "longitude": -87.623177
    },
    "dk-cph": {
      "country": "Denmark",
      "city": "Copenhagen",
      "latitude": 55.666667,
      "longitude": 12.583333
    },
    "us-dal": {
      "country": "USA",
      "city": "Dallas, TX",
      "latitude": 32.89748,
      "longitude": -97.040443
    },
    "us-den": {
      "country": "USA",
      "city": "Denver, CO",
      "latitude": 39.739236,
      "longitude": -104.990251
    },
    "us-det": {
      "country": "USA",
      "city": "Detroit, MI",
      "latitude": 42.331389,
      "longitude": -83.045833
    },
    "ie-dub": {
      "country": "Ireland",
      "city": "Dublin",
      "latitude": 53.35014,
      "longitude": -6.266155
    },
    "de-dus": {
      "country": "Germany",
      "city": "Dusseldorf",
      "latitude": 51.233334,
      "longitude": 6.783333
    },
    "br-for": {
      "country": "Brazil",
      "city": "Fortaleza",
      "latitude": -3.732714,
      "longitude": -38.526997
    },
    "de-fra": {
      "country": "Germany",
      "city": "Frankfurt",
      "latitude": 50.110924,
      "longitude": 8.682127
    },
    "gb-glw": {
      "country": "UK",
      "city": "Glasgow",
      "latitude": 55.86515,
      "longitude": -4.25763
    },
    "se-got": {
      "country": "Sweden",
      "city": "Gothenburg",
      "latitude": 57.70887,
      "longitude": 11.97456
    },
    "fi-hel": {
      "country": "Finland",
      "city": "Helsinki",
      "latitude": 60.192059,
      "longitude": 24.945831
    },
    "hk-hkg": {
      "country": "Hong Kong",
      "city": "Hong Kong",
      "latitude": 22.283333,
      "longitude": 114.15
    },
    "us-hou": {
      "country": "USA",
      "city": "Houston, TX",
      "latitude": 29.749907,
      "longitude": -95.358421
    },
    "tr-ist": {
      "country": "Turkey",
      "city": "Istanbul",
      "latitude": 41.00824,
      "longitude": 28.978359
    },
    "id-jpu": {
      "country": "Indonesia",
      "city": "Jakarta",
      "latitude": -6.17511,
      "longitude": 106.865036
    },
    "za-jnb": {
      "country": "South Africa",
      "city": "Johannesburg",
      "latitude": -26.195246,
      "longitude": 28.034088
    },
    "us-mkc": {
      "country": "USA",
      "city": "Kansas City, MO",
      "latitude": 39.099789,
      "longitude": -94.57856
    },
    "my-kul": {
      "country": "Malaysia",
      "city": "Kuala Lumpur",
      "latitude": 3.139003,
      "longitude": 101.686852
    },
    "ua-iev": {
      "country": "Ukraine",
      "city": "Kyiv",
      "latitude": 50.4501,
      "longitude": 30.5234
    },
    "ng-los": {
      "country": "Nigeria",
      "city": "Lagos",
      "latitude": 6.524379,
      "longitude": 3.379206
    },
    "pe-lim": {
      "country": "Peru",
      "city": "Lima",
      "latitude": -12.046373,
      "longitude": -77.042755
    },
    "pt-lis": {
      "country": "Portugal",
      "city": "Lisbon",
      "latitude": 38.736946,
      "longitude": -9.142685
    },
    "si-lju": {
      "country": "Slovenia",
      "city": "Ljubljana",
      "latitude": 46.0569,
      "longitude": 14.5057
    },
    "gb-lon": {
      "country": "UK",
      "city": "London",
      "latitude": 51.514125,
      "longitude": -0.093689
    },
    "us-lax": {
      "country": "USA",
      "city": "Los Angeles, CA",
      "latitude": 34.052235,
      "longitude": -118.243683
    },
    "es-mad": {
      "country": "Spain",
      "city": "Madrid",
      "latitude": 40.408566,
      "longitude": -3.69222
    },
    "se-mma": {
      "country": "Sweden",
      "city": "Malmö",
      "latitude": 55.607075,
      "longitude": 13.002716
    },
    "gb-mnc": {
      "country": "UK",
      "city": "Manchester",
      "latitude": 53.5,
      "longitude": -2.216667
    },
    "ph-mnl": {
      "country": "Philippines",
      "city": "Manila",
      "latitude": 14.599512,
      "longitude": 120.984222
    },
    "fr-mrs": {
      "country": "France",
      "city": "Marseille",
      "latitude": 43.29648,
      "longitude": 5.38107
    },
    "us-txc": {
      "country": "USA",
      "city": "McAllen, TX",
      "latitude": 26.203407,
      "longitude": -98.230011
    },
    "au-mel": {
      "country": "Australia",
      "city": "Melbourne",
      "latitude": -37.815018,
      "longitude": 144.946014
    },
    "us-mia": {
      "country": "USA",
      "city": "Miami, FL",
      "latitude": 25.761681,
      "longitude": -80.191788
    },
    "it-mil": {
      "country": "Italy",
      "city": "Milan",
      "latitude": 45.466667,
      "longitude": 9.2
    },
    "ca-mtr": {
      "country": "Canada",
      "city": "Montreal",
      "latitude": 45.5053,
      "longitude": -73.5525
    },
    "us-nyc": {
      "country": "USA",
      "city": "New York, NY",
      "latitude": 40.73061,
      "longitude": -73.935242
    },
    "cy-nic": {
      "country": "Cyprus",
      "city": "Nicosia",
      "latitude": 35.17025,
      "longitude": 33.3587
    },
    "jp-osa": {
      "country": "Japan",
      "city": "Osaka",
      "latitude": 34.672314,
      "longitude": 135.484802
    },
    "no-osl": {
      "country": "Norway",
      "city": "Oslo",
      "latitude": 59.916667,
      "longitude": 10.75
    },
    "it-pmo": {
      "country": "Italy",
      "city": "Palermo",
      "latitude": 38.115688,
      "longitude": 13.361267
    },
    "fr-par": {
      "country": "France",
      "city": "Paris",
      "latitude": 48.866667,
      "longitude": 2.333333
    },
    "au-per": {
      "country": "Australia",
      "city": "Perth",
      "latitude": -31.953512,
      "longitude": 115.857048
    },
    "us-phx": {
      "country": "USA",
      "city": "Phoenix, AZ",
      "latitude": 33.448376,
      "longitude": -112.074036
    },
    "cz-prg": {
      "country": "Czech Republic",
      "city": "Prague",
      "latitude": 50.083333,
      "longitude": 14.466667
    },
    "mx-qro": {
      "country": "Mexico",
      "city": "Queretaro",
      "latitude": 20.592774,
      "longitude": -100.390225
    },
    "us-rag": {
      "country": "USA",
      "city": "Raleigh, NC",
      "latitude": 35.787743,
      "longitude": -78.644257
    },
    "us-slc": {
      "country": "USA",
      "city": "Salt Lake City, UT",
      "latitude": 40.758701,
      "longitude": -111.876183
    },
    "us-sfo": {
      "country": "USA",
      "city": "San Francisco, CA",
      "latitude": 37.723459,
      "longitude": -122.397957
    },
    "us-sjc": {
      "country": "USA",
      "city": "San Jose, CA",
      "latitude": 37.338208,
      "longitude": -121.886329
    },
    "cl-scl": {
      "country": "Chile",
      "city": "Santiago",
      "latitude": -33.448891,
      "longitude": -70.669266
    },
    "br-sao": {
      "country": "Brazil",
      "city": "Sao Paulo",
      "latitude": -23.533773,
      "longitude": -46.62529
    },
    "us-sea": {
      "country": "USA",
      "city": "Seattle, WA",
      "latitude": 47.608013,
      "longitude": -122.335167
    },
    "us-uyk": {
      "country": "USA",
      "city": "Secaucus, NJ",
      "latitude": 40.789543,
      "longitude": -74.0565
    },
    "sg-sin": {
      "country": "Singapore",
      "city": "Singapore",
      "latitude": 1.293056,
      "longitude": 103.855833
    },
    "bg-sof": {
      "country": "Bulgaria",
      "city": "Sofia",
      "latitude": 42.683333,
      "longitude": 23.316667
    },
    "no-svg": {
      "country": "Norway",
      "city": "Stavanger",
      "latitude": 58.964432,
      "longitude": 5.72625
    },
    "se-sto": {
      "country": "Sweden",
      "city": "Stockholm",
      "latitude": 59.3289,
      "longitude": 18.0649
    },
    "au-syd": {
      "country": "Australia",
      "city": "Sydney",
      "latitude": -33.861481,
      "longitude": 151.205475
    },
    "ee-tll": {
      "country": "Estonia",
      "city": "Tallinn",
      "latitude": 59.436961,
      "longitude": 24.753575
    },
    "il-tlv": {
      "country": "Israel",
      "city": "Tel Aviv",
      "latitude": 32.0853,
      "longitude": 34.781768
    },
    "al-tia": {
      "country": "Albania",
      "city": "Tirana",
      "latitude": 41.327953,
      "longitude": 19.819025
    },
    "jp-tyo": {
      "country": "Japan",
      "city": "Tokyo",
      "latitude": 35.685,
      "longitude": 139.751389
    },
    "ca-tor": {
      "country": "Canada",
      "city": "Toronto",
      "latitude": 43.666667,
      "longitude": -79.416667
    },
    "es-vlc": {
      "country": "Spain",
      "city": "Valencia",
      "latitude": 39.466667,
      "longitude": -0.375
    },
    "ca-van": {
      "country": "Canada",
      "city": "Vancouver",
      "latitude": 49.25,
      "longitude": -123.133333
    },
    "at-vie": {
      "country": "Austria",
      "city": "Vienna",
      "latitude": 48.210033,
      "longitude": 16.363449
    },
    "pl-waw": {
      "country": "Poland",
      "city": "Warsaw",
      "latitude": 52.25,
      "longitude": 21.0
    },
    "us-was": {
      "country": "USA",
      "city": "Washington DC",
      "latitude": 38.889484,
      "longitude": -77.035278
    },
    "hr-zag": {
      "country": "Croatia",
      "city": "Zagreb",
      "latitude": 45.821,
      "longitude": 15.973
    },
    "ch-zrh": {
      "country": "Switzerland",
      "city": "Zurich",
      "latitude": 47.366667,
      "longitude": 8.55
    }
  },
  "openvpn": {
    "relays": [],
    "ports": [
      {
        "port": 1194,
        "protocol": "udp"
      },
      {
        "port": 1195,
        "protocol": "udp"
      },
      {
        "port": 1196,
        "protocol": "udp"
      },
      {
        "port": 1197,
        "protocol": "udp"
      },
      {
        "port": 1300,
        "protocol": "udp"
      },
      {
        "port": 1301,
        "protocol": "udp"
      },
      {
        "port": 1302,
        "protocol": "udp"
      },
      {
        "port": 443,
        "protocol": "tcp"
      },
      {
        "port": 80,
        "protocol": "tcp"
      }
    ]
  },
  "wireguard": {
    "relays": [
      {
        "hostname": "al-tia-wg-001",
        "location": "al-tia",
        "active": true,
        "owned": false,
        "provider": "iRegister",
        "stboot": true,
        "ipv4_addr_in": "103.124.165.2",
        "include_in_country": true,
        "weight": 100,
        "public_key": "ofyfRvMPB0PPIGGItNL+5tNdvTKXuWye5CfjPgPNvQ8=",
        "ipv6_addr_in": "2a04:27c0:0:e::f001",
        "daita": true,
        "shadowsocks_extra_addr_in": [
          "103.124.165.17",
          "103.124.165.18",
          "103.124.165.19",
          "103.124.165.20",
          "103.124.165.21",
          "103.124.165.22",
          "103.124.165.23",
          "103.124.165.24",
          "103.124.165.25",
          "103.124.165.26",
          "103.124.165.27",
          "2a04:27c0:0:e::b002",
          "2a04:27c0:0:e::b003",
          "2a04:27c0:0:e::b004",
          "2a04:27c0:0:e::b005",
          "2a04:27c0:0:e::b006",
          "2a04:27c0:0:e::b007",
          "2a04:27c0:0:e::b008",
          "2a04:27c0:0:e::b009",
          "2a04:27c0:0:e::b00a",
          "2a04:27c0:0:e::b00b",
          "2a04:27c0:0:e::b00c",
          "2a04:27c0:0:e::b00d",
          "2a04:27c0:0:e::b00e",
          "2a04:27c0:0:e::b00f",
          "2a04:27c0:0:e::b010",
          "2a04:27c0:0:e::b011",
          "2a04:27c0:0:e::b012",
          "2a04:27c0:0:e::b013",
          "2a04:27c0:0:e::b014",
          "2a04:27c0:0:e::b015",
          "2a04:27c0:0:e::b016",
          "2a04:27c0:0:e::b017",
          "2a04:27c0:0:e::b018",
          "2a04:27c0:0:e::b019",
          "2a04:27c0:0:e::b01a",
          "2a04:27c0:0:e::b01b",
          "2a04:27c0:0:e::b01c",
          "2a04:27c0:0:e::b01d",
          "2a04:27c0:0:e::b01e",
          "2a04:27c0:0:e::b01f"
        ],
        "features": {
          "daita": {},
          "lwo": {},
          "quic": {
            "addr_in": [
              "103.124.165.6",
              "103.124.165.7",
              "103.124.165.8",
              "103.124.165.9",
              "103.124.165.10",
              "103.124.165.11",
              "103.124.165.12",
              "103.124.165.13",
              "103.124.165.14",
              "103.124.165.15",
              "103.124.165.16",
              "2a04:27c0:0:e::c002",
              "2a04:27c0:0:e::c003",
              "2a04:27c0:0:e::c004",
              "2a04:27c0:0:e::c005",
              "2a04:27c0:0:e::c006",
              "2a04:27c0:0:e::c007",
              "2a04:27c0:0:e::c008",
              "2a04:27c0:0:e::c009",
              "2a04:27c0:0:e::c00a",
              "2a04:27c0:0:e::c00b",
              "2a04:27c0:0:e::c00c",
              "2a04:27c0:0:e::c00d",
              "2a04:27c0:0:e::c00e",
              "2a04:27c0:0:e::c00f",
              "2a04:27c0:0:e::c010",
              "2a04:27c0:0:e::c011",
              "2a04:27c0:0:e::c012",
              "2a04:27c0:0:e::c013",
              "2a04:27c0:0:e::c014",
              "2a04:27c0:0:e::c015",
              "2a04:27c0:0:e::c016",
              "2a04:27c0:0:e::c017",
              "2a04:27c0:0:e::c018",
              "2a04:27c0:0:e::c019",
              "2a04:27c0:0:e::c01a",
              "2a04:27c0:0:e::c01b",
              "2a04:27c0:0:e::c01c",
              "2a04:27c0:0:e::c01d",
              "2a04:27c0:0:e::c01e",
              "2a04:27c0:0:e::c01f"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "al-tia-wg-001.blockerad.eu"
          }
        }
      },
      {
        "hostname": "al-tia-wg-003",
        "location": "al-tia",
        "active": true,
        "owned": false,
        "provider": "iRegister",
        "stboot": true,
        "ipv4_addr_in": "103.124.165.130",
        "include_in_country": true,
        "weight": 100,
        "public_key": "rWiQxq5lAWD8v/bws9ITSAvThyZW8cR2x+Ins9ZvvRo=",
        "ipv6_addr_in": "2a04:27c0:0:c::f001",
        "daita": true,
        "shadowsocks_extra_addr_in": [
          "103.204.123.136"
        ],
        "features": {
          "daita": {},
          "lwo": {},
          "quic": {
            "addr_in": [
              "103.124.165.135",
              "2a04:27c0:0:c::f00a"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "al-tia-wg-003.blockerad.eu"
          }
        }
      },
      {
        "hostname": "al-tia-wg-004",
        "location": "al-tia",
        "active": true,
        "owned": false,
        "provider": "iRegister",
        "stboot": true,
        "ipv4_addr_in": "103.124.165.191",
        "include_in_country": true,
        "weight": 100,
        "public_key": "x62J1c4gfHu/bF3DSjwIjC0qOE3azRG03i/YW6bOEGY=",
        "ipv6_addr_in": "2a04:27c0:0:d::f001",
        "daita": true,
        "shadowsocks_extra_addr_in": [
          "103.124.165.197"
        ],
        "features": {
          "daita": {},
          "lwo": {},
          "quic": {
            "addr_in": [
              "103.124.165.196",
              "2a04:27c0:0:d::f00a"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "al-tia-wg-004.blockerad.eu"
          }
        }
      },
      {
        "hostname": "ar-bue-wg-001",
        "location": "ar-bue",
        "active": true,
        "owned": false,
        "provider": "DataPacket",
        "stboot": true,
        "ipv4_addr_in": "149.22.83.2",
        "include_in_country": true,
        "weight": 100,
        "public_key": "1WN0Mqa0Azw7cYYEamHPgHXE8SuylNIG2QobZKOaclA=",
        "ipv6_addr_in": "2a02:6ea0:f002:1::f001",
        "shadowsocks_extra_addr_in": [
          "149.22.83.5"
        ],
        "features": {
          "quic": {
            "addr_in": [
              "149.22.83.4"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "ar-bue-wg-001.blockerad.eu"
          }
        }
      },
      {
        "hostname": "ar-bue-wg-002",
        "location": "ar-bue",
        "active": true,
        "owned": false,
        "provider": "DataPacket",
        "stboot": true,
        "ipv4_addr_in": "149.22.83.31",
        "include_in_country": true,
        "weight": 100,
        "public_key": "gGrdozNHVCnmcX5x8OPOXfnyZ+TZWqD9GlHl1kRekyA=",
        "ipv6_addr_in": "2a02:6ea0:f002:2::f001",
        "shadowsocks_extra_addr_in": [
          "149.22.83.34"
        ],
        "features": {
          "quic": {
            "addr_in": [
              "149.22.83.33"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "ar-bue-wg-002.blockerad.eu"
          }
        }
      },
      {
        "hostname": "at-vie-wg-001",
        "location": "at-vie",
        "active": true,
        "owned": false,
        "provider": "M247",
        "stboot": true,
        "ipv4_addr_in": "146.70.116.130",
        "include_in_country": true,
        "weight": 100,
        "public_key": "GLqlOTVJCyRpJx3vgR3ykTPNJLGKNytHXu61zBWIAls=",
        "ipv6_addr_in": "2001:ac8:29:b3::f001",
        "daita": true,
        "shadowsocks_extra_addr_in": [
          "146.70.116.141",
          "146.70.116.142",
          "146.70.116.143",
          "146.70.116.144",
          "146.70.116.145",
          "146.70.116.146",
          "146.70.116.147",
          "146.70.116.148",
          "146.70.116.149",
          "146.70.116.150",
          "2001:ac8:29:b3::b002",
          "2001:ac8:29:b3::b003",
          "2001:ac8:29:b3::b004",
          "2001:ac8:29:b3::b005",
          "2001:ac8:29:b3::b006",
          "2001:ac8:29:b3::b007",
          "2001:ac8:29:b3::b008",
          "2001:ac8:29:b3::b009",
          "2001:ac8:29:b3::b00a",
          "2001:ac8:29:b3::b00b",
          "2001:ac8:29:b3::b00c",
          "2001:ac8:29:b3::b00d",
          "2001:ac8:29:b3::b00e",
          "2001:ac8:29:b3::b00f",
          "2001:ac8:29:b3::b010",
          "2001:ac8:29:b3::b011",
          "2001:ac8:29:b3::b012",
          "2001:ac8:29:b3::b013",
          "2001:ac8:29:b3::b014",
          "2001:ac8:29:b3::b015",
          "2001:ac8:29:b3::b016",
          "2001:ac8:29:b3::b017",
          "2001:ac8:29:b3::b018",
          "2001:ac8:29:b3::b019",
          "2001:ac8:29:b3::b01a",
          "2001:ac8:29:b3::b01b",
          "2001:ac8:29:b3::b01c",
          "2001:ac8:29:b3::b01d",
          "2001:ac8:29:b3::b01e",
          "2001:ac8:29:b3::b01f"
        ],
        "features": {
          "daita": {},
          "lwo": {}
        }
      },
      {
        "hostname": "at-vie-wg-002",
        "location": "at-vie",
        "active": true,
        "owned": false,
        "provider": "M247",
        "stboot": true,
        "ipv4_addr_in": "135.136.51.2",
        "include_in_country": true,
        "weight": 100,
        "public_key": "FSGkeqzoy8fWkGcGl5nrYeiQG04C511+qdH5iMramxE=",
        "ipv6_addr_in": "2001:ac8:29:b4::f001",
        "daita": true,
        "shadowsocks_extra_addr_in": [
          "135.136.51.13",
          "135.136.51.14",
          "135.136.51.15",
          "135.136.51.16",
          "135.136.51.17",
          "135.136.51.18",
          "135.136.51.19",
          "135.136.51.20",
          "135.136.51.21",
          "135.136.51.22",
          "2001:ac8:29:b4::b002",
          "2001:ac8:29:b4::b003",
          "2001:ac8:29:b4::b004",
          "2001:ac8:29:b4::b005",
          "2001:ac8:29:b4::b006",
          "2001:ac8:29:b4::b007",
          "2001:ac8:29:b4::b008",
          "2001:ac8:29:b4::b009",
          "2001:ac8:29:b4::b00a",
          "2001:ac8:29:b4::b00b",
          "2001:ac8:29:b4::b00c",
          "2001:ac8:29:b4::b00d",
          "2001:ac8:29:b4::b00e",
          "2001:ac8:29:b4::b00f",
          "2001:ac8:29:b4::b010",
          "2001:ac8:29:b4::b011",
          "2001:ac8:29:b4::b012",
          "2001:ac8:29:b4::b013",
          "2001:ac8:29:b4::b014",
          "2001:ac8:29:b4::b015",
          "2001:ac8:29:b4::b016",
          "2001:ac8:29:b4::b017",
          "2001:ac8:29:b4::b018",
          "2001:ac8:29:b4::b019",
          "2001:ac8:29:b4::b01a",
          "2001:ac8:29:b4::b01b",
          "2001:ac8:29:b4::b01c",
          "2001:ac8:29:b4::b01d",
          "2001:ac8:29:b4::b01e",
          "2001:ac8:29:b4::b01f"
        ],
        "features": {
          "daita": {},
          "lwo": {}
        }
      },
      {
        "hostname": "at-vie-wg-003",
        "location": "at-vie",
        "active": true,
        "owned": false,
        "provider": "M247",
        "stboot": true,
        "ipv4_addr_in": "135.136.51.130",
        "include_in_country": true,
        "weight": 100,
        "public_key": "HsWJFTCpoe7niGs8EOMI2/ES4Q4MuhqLIoRc9QLSpSk=",
        "ipv6_addr_in": "2001:ac8:29:b5::f001",
        "daita": true,
        "shadowsocks_extra_addr_in": [
          "135.136.51.141",
          "135.136.51.142",
          "135.136.51.143",
          "135.136.51.144",
          "135.136.51.145",
          "135.136.51.146",
          "135.136.51.147",
          "135.136.51.148",
          "135.136.51.149",
          "135.136.51.150",
          "2001:ac8:29:b5::b002",
          "2001:ac8:29:b5::b003",
          "2001:ac8:29:b5::b004",
          "2001:ac8:29:b5::b005",
          "2001:ac8:29:b5::b006",
          "2001:ac8:29:b5::b007",
          "2001:ac8:29:b5::b008",
          "2001:ac8:29:b5::b009",
          "2001:ac8:29:b5::b00a",
          "2001:ac8:29:b5::b00b",
          "2001:ac8:29:b5::b00c",
          "2001:ac8:29:b5::b00d",
          "2001:ac8:29:b5::b00e",
          "2001:ac8:29:b5::b00f",
          "2001:ac8:29:b5::b010",
          "2001:ac8:29:b5::b011",
          "2001:ac8:29:b5::b012",
          "2001:ac8:29:b5::b013",
          "2001:ac8:29:b5::b014",
          "2001:ac8:29:b5::b015",
          "2001:ac8:29:b5::b016",
          "2001:ac8:29:b5::b017",
          "2001:ac8:29:b5::b018",
          "2001:ac8:29:b5::b019",
          "2001:ac8:29:b5::b01a",
          "2001:ac8:29:b5::b01b",
          "2001:ac8:29:b5::b01c",
          "2001:ac8:29:b5::b01d",
          "2001:ac8:29:b5::b01e",
          "2001:ac8:29:b5::b01f"
        ],
        "features": {
          "daita": {},
          "lwo": {}
        }
      },
      {
        "hostname": "at-vie-wg-101",
        "location": "at-vie",
        "active": true,
        "owned": false,
        "provider": "DataPacket",
        "stboot": true,
        "ipv4_addr_in": "185.24.11.130",
        "include_in_country": true,
        "weight": 100,
        "public_key": "dj3qNfJfA4dWXsWokPcDh4oo6xaPtOTPfbr5UzHKZ0M=",
        "ipv6_addr_in": "2a02:6ea0:cb1b:1::f001",
        "shadowsocks_extra_addr_in": [
          "185.24.11.132"
        ],
        "features": {
          "lwo": {}
        }
      },
      {
        "hostname": "at-vie-wg-102",
        "location": "at-vie",
        "active": true,
        "owned": false,
        "provider": "DataPacket",
        "stboot": true,
        "ipv4_addr_in": "185.24.11.159",
        "include_in_country": true,
        "weight": 100,
        "public_key": "DANFtH+sFB19BnW1CYEwZ2pOIt7P8nLjSadjpS2rLWE=",
        "ipv6_addr_in": "2a02:6ea0:cb1b:2::f001",
        "shadowsocks_extra_addr_in": [
          "185.24.11.161"
        ],
        "features": {
          "lwo": {}
        }
      },
      {
        "hostname": "au-adl-wg-301",
        "location": "au-adl",
        "active": true,
        "owned": false,
        "provider": "hostuniversal",
        "stboot": true,
        "ipv4_addr_in": "103.214.20.50",
        "include_in_country": true,
        "weight": 100,
        "public_key": "rm2hpBiN91c7reV+cYKlw7QNkYtME/+js7IMyYBB2Aw=",
        "ipv6_addr_in": "2404:f780:0:deb::c1f"
      },
      {
        "hostname": "au-adl-wg-302",
        "location": "au-adl",
        "active": true,
        "owned": false,
        "provider": "hostuniversal",
        "stboot": true,
        "ipv4_addr_in": "103.214.20.130",
        "include_in_country": true,
        "weight": 100,
        "public_key": "e4jouH8n4e8oyi/Z7d6lJLd6975hlPZmnynJeoU+nWM=",
        "ipv6_addr_in": "2404:f780:0:dec::c2f"
      },
      {
        "hostname": "au-adl-wg-303",
        "location": "au-adl",
        "active": true,
        "owned": false,
        "provider": "hostuniversal",
        "stboot": true,
        "ipv4_addr_in": "103.214.20.162",
        "include_in_country": true,
        "weight": 100,
        "public_key": "X9vdIZG69ZDU4Wf05T8F+C+NuWeYOgojmOVeASdiIWo=",
        "ipv6_addr_in": "2404:f780:0:def::f201",
        "features": {
          "lwo": {}
        }
      },
      {
        "hostname": "au-bne-wg-301",
        "location": "au-bne",
        "active": true,
        "owned": false,
        "provider": "hostuniversal",
        "stboot": true,
        "ipv4_addr_in": "103.216.220.18",
        "include_in_country": true,
        "weight": 100,
        "public_key": "1H/gj8SVNebAIEGlvMeUVC5Rnf274dfVKbyE+v5G8HA=",
        "ipv6_addr_in": "2404:f780:4:deb::f001"
      },
      {
        "hostname": "au-bne-wg-302",
        "location": "au-bne",
        "active": true,
        "owned": false,
        "provider": "hostuniversal",
        "stboot": true,
        "ipv4_addr_in": "103.216.220.34",
        "include_in_country": true,
        "weight": 100,
        "public_key": "z+JG0QA4uNd/wRTpjCqn9rDpQsHKhf493omqQ5rqYAc=",
        "ipv6_addr_in": "2404:f780:4:dec::a02f"
      },
      {
        "hostname": "au-bne-wg-303",
        "location": "au-bne",
        "active": true,
        "owned": false,
        "provider": "hostuniversal",
        "stboot": true,
        "ipv4_addr_in": "103.216.220.66",
        "include_in_country": true,
        "weight": 100,
        "public_key": "AdUQ6vk1e1SMzlLpgwmg86A0SSj8YGrJE2UWlflGtCg=",
        "ipv6_addr_in": "2404:f780:4:def::f201",
        "features": {
          "lwo": {}
        }
      },
      {
        "hostname": "au-mel-wg-401",
        "location": "au-mel",
        "active": true,
        "owned": false,
        "provider": "hostuniversal",
        "stboot": true,
        "ipv4_addr_in": "163.47.16.146",
        "include_in_country": true,
        "weight": 100,
        "public_key": "ju0S2nDmiOrSm1H68SRTB4mtt2U8SKROprE83VCoF1Y=",
        "ipv6_addr_in": "2406:d501:f:dfa::f001",
        "shadowsocks_extra_addr_in": [
          "163.47.16.149",
          "91.190.106.11",
          "91.190.106.12",
          "91.190.106.13",
          "91.190.106.14",
          "91.190.106.15",
          "91.190.106.16",
          "91.190.106.17",
          "91.190.106.18",
          "91.190.106.19",
          "91.190.106.20",
          "2406:d501:f:dfa::b002",
          "2406:d501:f:dfa::b003",
          "2406:d501:f:dfa::b004",
          "2406:d501:f:dfa::b005",
          "2406:d501:f:dfa::b006",
          "2406:d501:f:dfa::b007",
          "2406:d501:f:dfa::b008",
          "2406:d501:f:dfa::b009",
          "2406:d501:f:dfa::b00a",
          "2406:d501:f:dfa::b00b",
          "2406:d501:f:dfa::b00c",
          "2406:d501:f:dfa::b00d",
          "2406:d501:f:dfa::b00e",
          "2406:d501:f:dfa::b00f",
          "2406:d501:f:dfa::b010",
          "2406:d501:f:dfa::b011",
          "2406:d501:f:dfa::b012",
          "2406:d501:f:dfa::b013",
          "2406:d501:f:dfa::b014",
          "2406:d501:f:dfa::b015",
          "2406:d501:f:dfa::b016",
          "2406:d501:f:dfa::b017",
          "2406:d501:f:dfa::b018",
          "2406:d501:f:dfa::b019",
          "2406:d501:f:dfa::b01a",
          "2406:d501:f:dfa::b01b",
          "2406:d501:f:dfa::b01c",
          "2406:d501:f:dfa::b01d",
          "2406:d501:f:dfa::b01e",
          "2406:d501:f:dfa::b01f"
        ],
        "features": {
          "lwo": {},
          "quic": {
            "addr_in": [
              "163.47.16.148",
              "91.190.106.3",
              "91.190.106.4",
              "91.190.106.5",
              "91.190.106.6",
              "91.190.106.7",
              "91.190.106.8",
              "91.190.106.9",
              "91.190.106.10",
              "2406:d501:f:dfa::c002",
              "2406:d501:f:dfa::c003",
              "2406:d501:f:dfa::c004",
              "2406:d501:f:dfa::c005",
              "2406:d501:f:dfa::c006",
              "2406:d501:f:dfa::c007",
              "2406:d501:f:dfa::c008",
              "2406:d501:f:dfa::c009",
              "2406:d501:f:dfa::c00a",
              "2406:d501:f:dfa::c00b",
              "2406:d501:f:dfa::c00c",
              "2406:d501:f:dfa::c00d",
              "2406:d501:f:dfa::c00e",
              "2406:d501:f:dfa::c00f",
              "2406:d501:f:dfa::c010",
              "2406:d501:f:dfa::c011",
              "2406:d501:f:dfa::c012",
              "2406:d501:f:dfa::c013",
              "2406:d501:f:dfa::c014",
              "2406:d501:f:dfa::c015",
              "2406:d501:f:dfa::c016",
              "2406:d501:f:dfa::c017",
              "2406:d501:f:dfa::c018",
              "2406:d501:f:dfa::c019",
              "2406:d501:f:dfa::c01a",
              "2406:d501:f:dfa::c01b",
              "2406:d501:f:dfa::c01c",
              "2406:d501:f:dfa::c01d",
              "2406:d501:f:dfa::c01e",
              "2406:d501:f:dfa::c01f"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "au-mel-wg-401.blockerad.eu"
          }
        }
      },
      {
        "hostname": "au-mel-wg-402",
        "location": "au-mel",
        "active": false,
        "owned": false,
        "provider": "hostuniversal",
        "stboot": true,
        "ipv4_addr_in": "163.47.16.150",
        "include_in_country": true,
        "weight": 100,
        "public_key": "j9xeIW+vE1DQAglbr00Vw1ePp6ueWklZ+Qx+KuyoBwQ=",
        "ipv6_addr_in": "2406:d501:f:dfb::f001",
        "shadowsocks_extra_addr_in": [
          "163.47.16.153",
          "91.190.106.100",
          "91.190.106.101",
          "91.190.106.102",
          "91.190.106.103",
          "91.190.106.104",
          "91.190.106.105",
          "91.190.106.106",
          "91.190.106.107",
          "91.190.106.108",
          "91.190.106.109",
          "2406:d501:f:dfb::b002",
          "2406:d501:f:dfb::b003",
          "2406:d501:f:dfb::b004",
          "2406:d501:f:dfb::b005",
          "2406:d501:f:dfb::b006",
          "2406:d501:f:dfb::b007",
          "2406:d501:f:dfb::b008",
          "2406:d501:f:dfb::b009",
          "2406:d501:f:dfb::b00a",
          "2406:d501:f:dfb::b00b",
          "2406:d501:f:dfb::b00c",
          "2406:d501:f:dfb::b00d",
          "2406:d501:f:dfb::b00e",
          "2406:d501:f:dfb::b00f",
          "2406:d501:f:dfb::b010",
          "2406:d501:f:dfb::b011",
          "2406:d501:f:dfb::b012",
          "2406:d501:f:dfb::b013",
          "2406:d501:f:dfb::b014",
          "2406:d501:f:dfb::b015",
          "2406:d501:f:dfb::b016",
          "2406:d501:f:dfb::b017",
          "2406:d501:f:dfb::b018",
          "2406:d501:f:dfb::b019",
          "2406:d501:f:dfb::b01a",
          "2406:d501:f:dfb::b01b",
          "2406:d501:f:dfb::b01c",
          "2406:d501:f:dfb::b01d",
          "2406:d501:f:dfb::b01e",
          "2406:d501:f:dfb::b01f"
        ],
        "features": {
          "lwo": {},
          "quic": {
            "addr_in": [
              "163.47.16.152",
              "91.190.106.91",
              "91.190.106.92",
              "91.190.106.93",
              "91.190.106.94",
              "91.190.106.95",
              "91.190.106.96",
              "91.190.106.97",
              "91.190.106.98",
              "91.190.106.99",
              "2406:d501:f:dfb::c002",
              "2406:d501:f:dfb::c003",
              "2406:d501:f:dfb::c004",
              "2406:d501:f:dfb::c005",
              "2406:d501:f:dfb::c006",
              "2406:d501:f:dfb::c007",
              "2406:d501:f:dfb::c008",
              "2406:d501:f:dfb::c009",
              "2406:d501:f:dfb::c00a",
              "2406:d501:f:dfb::c00b",
              "2406:d501:f:dfb::c00c",
              "2406:d501:f:dfb::c00d",
              "2406:d501:f:dfb::c00e",
              "2406:d501:f:dfb::c00f",
              "2406:d501:f:dfb::c010",
              "2406:d501:f:dfb::c011",
              "2406:d501:f:dfb::c012",
              "2406:d501:f:dfb::c013",
              "2406:d501:f:dfb::c014",
              "2406:d501:f:dfb::c015",
              "2406:d501:f:dfb::c016",
              "2406:d501:f:dfb::c017",
              "2406:d501:f:dfb::c018",
              "2406:d501:f:dfb::c019",
              "2406:d501:f:dfb::c01a",
              "2406:d501:f:dfb::c01b",
              "2406:d501:f:dfb::c01c",
              "2406:d501:f:dfb::c01d",
              "2406:d501:f:dfb::c01e",
              "2406:d501:f:dfb::c01f"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "au-mel-wg-402.blockerad.eu"
          }
        }
      },
      {
        "hostname": "au-mel-wg-403",
        "location": "au-mel",
        "active": true,
        "owned": false,
        "provider": "hostuniversal",
        "stboot": true,
        "ipv4_addr_in": "163.47.16.154",
        "include_in_country": true,
        "weight": 100,
        "public_key": "OQzxEZxEnLI85WF81VFO4tg9+fEBZ1dL+vckw2VYPxk=",
        "ipv6_addr_in": "2406:d501:f:dfc::f001",
        "shadowsocks_extra_addr_in": [
          "163.47.16.157",
          "163.47.16.158",
          "91.190.106.180",
          "91.190.106.181",
          "91.190.106.182",
          "91.190.106.183",
          "91.190.106.184",
          "91.190.106.185",
          "91.190.106.186",
          "91.190.106.187",
          "91.190.106.188",
          "91.190.106.189",
          "2406:d501:f:dfc::b002",
          "2406:d501:f:dfc::b003",
          "2406:d501:f:dfc::b004",
          "2406:d501:f:dfc::b005",
          "2406:d501:f:dfc::b006",
          "2406:d501:f:dfc::b007",
          "2406:d501:f:dfc::b008",
          "2406:d501:f:dfc::b009",
          "2406:d501:f:dfc::b00a",
          "2406:d501:f:dfc::b00b",
          "2406:d501:f:dfc::b00c",
          "2406:d501:f:dfc::b00d",
          "2406:d501:f:dfc::b00e",
          "2406:d501:f:dfc::b00f",
          "2406:d501:f:dfc::b010",
          "2406:d501:f:dfc::b011",
          "2406:d501:f:dfc::b012",
          "2406:d501:f:dfc::b013",
          "2406:d501:f:dfc::b014",
          "2406:d501:f:dfc::b015",
          "2406:d501:f:dfc::b016",
          "2406:d501:f:dfc::b017",
          "2406:d501:f:dfc::b018",
          "2406:d501:f:dfc::b019",
          "2406:d501:f:dfc::b01a",
          "2406:d501:f:dfc::b01b",
          "2406:d501:f:dfc::b01c",
          "2406:d501:f:dfc::b01d",
          "2406:d501:f:dfc::b01e",
          "2406:d501:f:dfc::b01f"
        ],
        "features": {
          "quic": {
            "addr_in": [
              "163.47.16.156",
              "91.190.106.170",
              "91.190.106.171",
              "91.190.106.172",
              "91.190.106.173",
              "91.190.106.174",
              "91.190.106.175",
              "91.190.106.176",
              "91.190.106.177",
              "91.190.106.178",
              "91.190.106.179",
              "2406:d501:f:dfc::c002",
              "2406:d501:f:dfc::c003",
              "2406:d501:f:dfc::c004",
              "2406:d501:f:dfc::c005",
              "2406:d501:f:dfc::c006",
              "2406:d501:f:dfc::c007",
              "2406:d501:f:dfc::c008",
              "2406:d501:f:dfc::c009",
              "2406:d501:f:dfc::c00a",
              "2406:d501:f:dfc::c00b",
              "2406:d501:f:dfc::c00c",
              "2406:d501:f:dfc::c00d",
              "2406:d501:f:dfc::c00e",
              "2406:d501:f:dfc::c00f",
              "2406:d501:f:dfc::c010",
              "2406:d501:f:dfc::c011",
              "2406:d501:f:dfc::c012",
              "2406:d501:f:dfc::c013",
              "2406:d501:f:dfc::c014",
              "2406:d501:f:dfc::c015",
              "2406:d501:f:dfc::c016",
              "2406:d501:f:dfc::c017",
              "2406:d501:f:dfc::c018",
              "2406:d501:f:dfc::c019",
              "2406:d501:f:dfc::c01a",
              "2406:d501:f:dfc::c01b",
              "2406:d501:f:dfc::c01c",
              "2406:d501:f:dfc::c01d",
              "2406:d501:f:dfc::c01e",
              "2406:d501:f:dfc::c01f"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "au-mel-wg-403.blockerad.eu"
          }
        }
      },
      {
        "hostname": "au-per-wg-301",
        "location": "au-per",
        "active": true,
        "owned": false,
        "provider": "hostuniversal",
        "stboot": true,
        "ipv4_addr_in": "103.108.231.50",
        "include_in_country": true,
        "weight": 100,
        "public_key": "hQXsNk/9R2We0pzP1S9J3oNErEu2CyENlwTdmDUYFhg=",
        "ipv6_addr_in": "2404:f780:8:deb::a01f"
      },
      {
        "hostname": "au-per-wg-302",
        "location": "au-per",
        "active": true,
        "owned": false,
        "provider": "hostuniversal",
        "stboot": true,
        "ipv4_addr_in": "103.108.231.66",
        "include_in_country": true,
        "weight": 100,
        "public_key": "t3Ly8bBdF2gMHzT3d529bVLDw8Jd2/FFG9GXoBEx01g=",
        "ipv6_addr_in": "2404:f780:8:dec::f001"
      },
      {
        "hostname": "au-syd-wg-001",
        "location": "au-syd",
        "active": true,
        "owned": false,
        "provider": "M247",
        "stboot": true,
        "ipv4_addr_in": "146.70.200.2",
        "include_in_country": true,
        "weight": 100,
        "public_key": "4JpfHBvthTFOhCK0f5HAbzLXAVcB97uAkuLx7E8kqW0=",
        "ipv6_addr_in": "2001:ac8:84:5::f001"
      },
      {
        "hostname": "au-syd-wg-002",
        "location": "au-syd",
        "active": true,
        "owned": false,
        "provider": "M247",
        "stboot": true,
        "ipv4_addr_in": "146.70.141.194",
        "include_in_country": true,
        "weight": 100,
        "public_key": "lUeDAOy+iAhZDuz5+6zh0Co8wZcs3ahdu2jfqQoDW3E=",
        "ipv6_addr_in": "2001:ac8:84:6::2f"
      },
      {
        "hostname": "au-syd-wg-003",
        "location": "au-syd",
        "active": true,
        "owned": false,
        "provider": "M247",
        "stboot": true,
        "ipv4_addr_in": "146.70.200.194",
        "include_in_country": true,
        "weight": 100,
        "public_key": "LXuRwa9JRTt2/UtldklKGlj/IVLORITqgET4II4DRkU=",
        "ipv6_addr_in": "2001:ac8:84:4::3f"
      },
      {
        "hostname": "au-syd-wg-101",
        "location": "au-syd",
        "active": true,
        "owned": false,
        "provider": "xtom",
        "stboot": true,
        "ipv4_addr_in": "103.136.147.3",
        "include_in_country": true,
        "weight": 100,
        "public_key": "NKP4jSvSDZg5HJ3JxpGYMxIYt7QzoxSFrU2F0m1ZxwA=",
        "ipv6_addr_in": "2a11:3:500::f001"
      },
      {
        "hostname": "au-syd-wg-102",
        "location": "au-syd",
        "active": true,
        "owned": false,
        "provider": "xtom",
        "stboot": true,
        "ipv4_addr_in": "103.136.147.65",
        "include_in_country": true,
        "weight": 100,
        "public_key": "w825smx7YI9/SrwSYGdsuwD1Qt5UsS/CyaGTjwSYljU=",
        "ipv6_addr_in": "2a11:3:500::f101"
      },
      {
        "hostname": "au-syd-wg-103",
        "location": "au-syd",
        "active": true,
        "owned": false,
        "provider": "xtom",
        "stboot": true,
        "ipv4_addr_in": "103.136.147.129",
        "include_in_country": true,
        "weight": 100,
        "public_key": "poOHsF6v91yURxDrNe/P/adyNUqsRGzhFIioyBYUPww=",
        "ipv6_addr_in": "2a11:3:500::f201",
        "features": {
          "lwo": {}
        }
      },
      {
        "hostname": "au-syd-wg-104",
        "location": "au-syd",
        "active": true,
        "owned": false,
        "provider": "xtom",
        "stboot": true,
        "ipv4_addr_in": "103.136.147.197",
        "include_in_country": true,
        "weight": 100,
        "public_key": "61Ovy3ObuHqllZK/P/5cOWZnY26SY2csmjzVK1q+fFs=",
        "ipv6_addr_in": "2a11:3:500::f301"
      },
      {
        "hostname": "au-syd-wg-301",
        "location": "au-syd",
        "active": true,
        "owned": false,
        "provider": "HostRoyale",
        "stboot": true,
        "ipv4_addr_in": "103.120.6.2",
        "include_in_country": true,
        "weight": 100,
        "public_key": "bQIQLk9zVOZLEGJsQOMu0K3rCMc85gExkS/0b1tSVBk=",
        "ipv6_addr_in": "2a06:3040:18:210::f001",
        "shadowsocks_extra_addr_in": [
          "103.120.6.13"
        ],
        "features": {
          "quic": {
            "addr_in": [
              "103.120.6.12",
              "2a06:3040:18:210::f00a"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "au-syd-wg-301.blockerad.eu"
          }
        }
      },
      {
        "hostname": "au-syd-wg-302",
        "location": "au-syd",
        "active": true,
        "owned": false,
        "provider": "HostRoyale",
        "stboot": true,
        "ipv4_addr_in": "103.120.6.127",
        "include_in_country": true,
        "weight": 100,
        "public_key": "6tTqSMUVPhaMsFFdphijwdura5RnNOzlz33Ekp1oCmc=",
        "ipv6_addr_in": "2a06:3040:18:210::f101",
        "shadowsocks_extra_addr_in": [
          "103.120.6.138"
        ],
        "features": {
          "quic": {
            "addr_in": [
              "103.120.6.137"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "au-syd-wg-302.blockerad.eu"
          }
        }
      },
      {
        "hostname": "au-syd-wg-303",
        "location": "au-syd",
        "active": true,
        "owned": false,
        "provider": "HostRoyale",
        "stboot": true,
        "ipv4_addr_in": "103.141.60.2",
        "include_in_country": true,
        "weight": 100,
        "public_key": "RK/eoKsyX4fu7iJ9F5mTf07en/WgYOMAtPGivKTntlw=",
        "ipv6_addr_in": "2a06:3040:18:210::f201",
        "shadowsocks_extra_addr_in": [
          "103.141.60.13"
        ],
        "features": {
          "quic": {
            "addr_in": [
              "103.141.60.12"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "au-syd-wg-303.blockerad.eu"
          }
        }
      },
      {
        "hostname": "au-syd-wg-304",
        "location": "au-syd",
        "active": true,
        "owned": false,
        "provider": "HostRoyale",
        "stboot": true,
        "ipv4_addr_in": "103.141.60.127",
        "include_in_country": true,
        "weight": 100,
        "public_key": "gXZZhcHfOD7FtnwTw8APUnccwMTVQYDNs4bbjHGS3CI=",
        "ipv6_addr_in": "2a06:3040:18:210::f301",
        "shadowsocks_extra_addr_in": [
          "103.141.60.138"
        ],
        "features": {
          "quic": {
            "addr_in": [
              "103.141.60.137"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "au-syd-wg-304.blockerad.eu"
          }
        }
      },
      {
        "hostname": "be-bru-wg-101",
        "location": "be-bru",
        "active": true,
        "owned": false,
        "provider": "M247",
        "stboot": true,
        "ipv4_addr_in": "91.90.123.2",
        "include_in_country": true,
        "weight": 100,
        "public_key": "GE2WP6hmwVggSvGVWLgq2L10T3WM2VspnUptK5F4B0U=",
        "ipv6_addr_in": "2001:ac8:27:88::a01f"
      },
      {
        "hostname": "be-bru-wg-102",
        "location": "be-bru",
        "active": true,
        "owned": false,
        "provider": "M247",
        "stboot": true,
        "ipv4_addr_in": "194.110.115.34",
        "include_in_country": true,
        "weight": 100,
        "public_key": "IY+FKw487MEWqMGNyyrT4PnTrJxce8oiGNHT0zifam8=",
        "ipv6_addr_in": "2001:ac8:27:89::a02f"
      },
      {
        "hostname": "be-bru-wg-103",
        "location": "be-bru",
        "active": true,
        "owned": false,
        "provider": "M247",
        "stboot": true,
        "ipv4_addr_in": "194.110.115.2",
        "include_in_country": true,
        "weight": 100,
        "public_key": "b5A1ela+BVI+AbNXz7SWekZHvdWWpt3rqUKTJj0SqCU=",
        "ipv6_addr_in": "2001:ac8:27:92::a03f"
      },
      {
        "hostname": "bg-sof-wg-001",
        "location": "bg-sof",
        "active": true,
        "owned": false,
        "provider": "M247",
        "stboot": true,
        "ipv4_addr_in": "146.70.188.130",
        "include_in_country": true,
        "weight": 100,
        "public_key": "J8KysHmHZWqtrVKKOppneDXSks/PDsB1XTlRHpwiABA=",
        "ipv6_addr_in": "2001:ac8:30:56::f001"
      },
      {
        "hostname": "bg-sof-wg-002",
        "location": "bg-sof",
        "active": true,
        "owned": false,
        "provider": "M247",
        "stboot": true,
        "ipv4_addr_in": "146.70.188.194",
        "include_in_country": true,
        "weight": 100,
        "public_key": "dg+Fw7GnKvDPBxFpnj1KPoNIu1GakuVoDJjKRni+pRU=",
        "ipv6_addr_in": "2001:ac8:30:57::f001"
      },
      {
        "hostname": "br-for-wg-001",
        "location": "br-for",
        "active": true,
        "owned": false,
        "provider": "Zenlayer",
        "stboot": true,
        "ipv4_addr_in": "98.98.12.178",
        "include_in_country": true,
        "weight": 100,
        "public_key": "CiPqGvrQidRVmKc6T8TORsAAZtQbsGzNEAKyd1iVlWY=",
        "ipv6_addr_in": "2604:980:e007:100::f001",
        "shadowsocks_extra_addr_in": [
          "155.2.219.14"
        ],
        "features": {
          "quic": {
            "addr_in": [
              "155.2.219.13",
              "2604:980:e007:100::f00a"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "br-for-wg-001.blockerad.eu"
          }
        }
      },
      {
        "hostname": "br-for-wg-002",
        "location": "br-for",
        "active": true,
        "owned": false,
        "provider": "Zenlayer",
        "stboot": true,
        "ipv4_addr_in": "98.98.12.182",
        "include_in_country": true,
        "weight": 100,
        "public_key": "qXISz0Kl4oC0sypcjD6hIxplv8zzZGIJPQZc4/EGz2k=",
        "ipv6_addr_in": "2604:980:e007:100::f101",
        "shadowsocks_extra_addr_in": [
          "155.2.219.139"
        ],
        "features": {
          "quic": {
            "addr_in": [
              "155.2.219.138",
              "2604:980:e007:100::f10a"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "br-for-wg-002.blockerad.eu"
          }
        }
      },
      {
        "hostname": "br-sao-wg-201",
        "location": "br-sao",
        "active": true,
        "owned": false,
        "provider": "DataPacket",
        "stboot": true,
        "ipv4_addr_in": "169.150.198.66",
        "include_in_country": true,
        "weight": 100,
        "public_key": "8c9M6w1BQbgMVr/Zgrj4GwSdU6q3qfQfWs17kMLC9y4=",
        "ipv6_addr_in": "2a02:6ea0:d00e:1::a01f",
        "daita": true,
        "features": {
          "daita": {}
        }
      },
      {
        "hostname": "br-sao-wg-202",
        "location": "br-sao",
        "active": true,
        "owned": false,
        "provider": "DataPacket",
        "stboot": true,
        "ipv4_addr_in": "169.150.198.79",
        "include_in_country": true,
        "weight": 100,
        "public_key": "jWURoz8SLBUlRTQnAFTA/LDZUTpvlO0ghiVWH7MgaHQ=",
        "ipv6_addr_in": "2a02:6ea0:d00e:2::a02f"
      },
      {
        "hostname": "br-sao-wg-302",
        "location": "br-sao",
        "active": true,
        "owned": false,
        "provider": "HostRoyale",
        "stboot": true,
        "ipv4_addr_in": "103.139.178.63",
        "include_in_country": true,
        "weight": 100,
        "public_key": "Xv1QvURPbgywITL6MNVhbYtfZXTm0lR98SPaf3AXeCc=",
        "ipv6_addr_in": "2a06:3040:10:610::f101",
        "shadowsocks_extra_addr_in": [
          "103.139.178.74",
          "103.139.178.75"
        ],
        "features": {
          "quic": {
            "addr_in": [
              "103.139.178.73",
              "2a06:3040:10:610::f10a"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "br-sao-wg-302.blockerad.eu"
          }
        }
      },
      {
        "hostname": "br-sao-wg-303",
        "location": "br-sao",
        "active": true,
        "owned": false,
        "provider": "HostRoyale",
        "stboot": true,
        "ipv4_addr_in": "103.139.178.123",
        "include_in_country": true,
        "weight": 100,
        "public_key": "oYrzNmnieX0iZS2nLxdM3mNcDjQZEWn5yaFCtX76qDk=",
        "ipv6_addr_in": "2a06:3040:10:610::f201",
        "shadowsocks_extra_addr_in": [
          "103.139.178.134",
          "103.139.178.135"
        ],
        "features": {
          "quic": {
            "addr_in": [
              "103.139.178.133",
              "2a06:3040:10:610::f20a"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "br-sao-wg-303.blockerad.eu"
          }
        }
      },
      {
        "hostname": "br-sao-wg-304",
        "location": "br-sao",
        "active": true,
        "owned": false,
        "provider": "HostRoyale",
        "stboot": true,
        "ipv4_addr_in": "103.139.178.183",
        "include_in_country": true,
        "weight": 100,
        "public_key": "hmO6+lN2CrWMFdpiPtSZ3oPRmcsJlpIi00P+c5p6rQQ=",
        "ipv6_addr_in": "2a06:3040:10:610::f301",
        "shadowsocks_extra_addr_in": [
          "103.139.178.194",
          "103.139.178.195"
        ],
        "features": {
          "quic": {
            "addr_in": [
              "103.139.178.193",
              "2a06:3040:10:610::f30a"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "br-sao-wg-304.blockerad.eu"
          }
        }
      },
      {
        "hostname": "ca-mtr-wg-001",
        "location": "ca-mtr",
        "active": true,
        "owned": false,
        "provider": "M247",
        "stboot": true,
        "ipv4_addr_in": "146.70.198.66",
        "include_in_country": true,
        "weight": 100,
        "public_key": "TUCaQc26/R6AGpkDUr8A8ytUs/e5+UVlIVujbuBwlzI=",
        "ipv6_addr_in": "2a0d:5600:9:c::f001",
        "features": {
          "lwo": {},
          "quic": {
            "addr_in": [
              "146.70.198.126",
              "2a0d:5600:9:c::c101"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "ca-mtr-wg-001.blockerad.eu"
          }
        }
      },
      {
        "hostname": "ca-mtr-wg-002",
        "location": "ca-mtr",
        "active": true,
        "owned": false,
        "provider": "M247",
        "stboot": true,
        "ipv4_addr_in": "146.70.198.130",
        "include_in_country": true,
        "weight": 100,
        "public_key": "7X6zOgtJfJAK8w8C3z+hekcS9Yf3qK3Bp4yx56lqxBQ=",
        "ipv6_addr_in": "2a0d:5600:9:d::f001"
      },
      {
        "hostname": "ca-mtr-wg-003",
        "location": "ca-mtr",
        "active": true,
        "owned": false,
        "provider": "M247",
        "stboot": true,
        "ipv4_addr_in": "146.70.198.194",
        "include_in_country": true,
        "weight": 100,
        "public_key": "57Zu2qPzRScZWsoC2NhXgz0FiC0HiKkbEa559sbxB3k=",
        "ipv6_addr_in": "2a0d:5600:9:e::a02f"
      },
      {
        "hostname": "ca-mtr-wg-004",
        "location": "ca-mtr",
        "active": true,
        "owned": false,
        "provider": "M247",
        "stboot": true,
        "ipv4_addr_in": "188.241.176.194",
        "include_in_country": true,
        "weight": 100,
        "public_key": "Cc5swfQ9f2tAgLduuIqC3bLbwDVoOFkkETghsE6/twA=",
        "ipv6_addr_in": "2a0d:5600:9:16::f001"
      },
      {
        "hostname": "ca-mtr-wg-201",
        "location": "ca-mtr",
        "active": true,
        "owned": false,
        "provider": "DataPacket",
        "stboot": true,
        "ipv4_addr_in": "62.93.167.130",
        "include_in_country": true,
        "weight": 100,
        "public_key": "m1DF8sQgOBo+vfdl1//sCvu2TnsHKdRzfsiszbBZQzs=",
        "ipv6_addr_in": "2a02:6ea0:a03:2::f001",
        "daita": true,
        "shadowsocks_extra_addr_in": [
          "62.93.167.132"
        ],
        "features": {
          "daita": {}
        }
      },
      {
        "hostname": "ca-mtr-wg-202",
        "location": "ca-mtr",
        "active": true,
        "owned": false,
        "provider": "DataPacket",
        "stboot": true,
        "ipv4_addr_in": "62.93.167.160",
        "include_in_country": true,
        "weight": 100,
        "public_key": "NqU0AZRAYH1p8BDUbirqITPJX47WYJsyxO73RHcEjEQ=",
        "ipv6_addr_in": "2a02:6ea0:a03::f001",
        "shadowsocks_extra_addr_in": [
          "62.93.167.162"
        ]
      },
      {
        "hostname": "ca-mtr-wg-301",
        "location": "ca-mtr",
        "active": true,
        "owned": false,
        "provider": "Tzulo",
        "stboot": true,
        "ipv4_addr_in": "23.234.120.2",
        "include_in_country": true,
        "weight": 100,
        "public_key": "iV7uZuw8vbqrW/p4YhsxkIxXaUuI4Uj2hTl8TaJZfAA=",
        "ipv6_addr_in": "2607:9000:f00:2::f001",
        "daita": true,
        "shadowsocks_extra_addr_in": [
          "23.234.120.5",
          "23.234.120.6",
          "23.234.120.7",
          "23.234.120.8",
          "23.234.120.9",
          "23.234.120.10",
          "23.234.120.11",
          "23.234.120.12",
          "23.234.120.13",
          "23.234.120.14",
          "23.234.120.15",
          "23.234.120.16",
          "23.234.120.17",
          "23.234.120.18",
          "23.234.120.19",
          "2607:9000:f00:2::b002",
          "2607:9000:f00:2::b003",
          "2607:9000:f00:2::b004",
          "2607:9000:f00:2::b005",
          "2607:9000:f00:2::b006",
          "2607:9000:f00:2::b007",
          "2607:9000:f00:2::b008",
          "2607:9000:f00:2::b009",
          "2607:9000:f00:2::b00a",
          "2607:9000:f00:2::b00b",
          "2607:9000:f00:2::b00c",
          "2607:9000:f00:2::b00d",
          "2607:9000:f00:2::b00e",
          "2607:9000:f00:2::b00f",
          "2607:9000:f00:2::b010",
          "2607:9000:f00:2::b011",
          "2607:9000:f00:2::b012",
          "2607:9000:f00:2::b013",
          "2607:9000:f00:2::b014",
          "2607:9000:f00:2::b015",
          "2607:9000:f00:2::b016",
          "2607:9000:f00:2::b017",
          "2607:9000:f00:2::b018",
          "2607:9000:f00:2::b019",
          "2607:9000:f00:2::b01a",
          "2607:9000:f00:2::b01b",
          "2607:9000:f00:2::b01c",
          "2607:9000:f00:2::b01d",
          "2607:9000:f00:2::b01e",
          "2607:9000:f00:2::b01f"
        ],
        "features": {
          "daita": {},
          "quic": {
            "addr_in": [
              "23.234.120.20",
              "23.234.120.21",
              "23.234.120.22",
              "23.234.120.23",
              "23.234.120.24",
              "23.234.120.25",
              "23.234.120.26",
              "23.234.120.27",
              "23.234.120.28",
              "23.234.120.29",
              "23.234.120.30",
              "23.234.120.31",
              "23.234.120.32",
              "23.234.120.33",
              "23.234.120.34",
              "2607:9000:f00:2::c002",
              "2607:9000:f00:2::c003",
              "2607:9000:f00:2::c004",
              "2607:9000:f00:2::c005",
              "2607:9000:f00:2::c006",
              "2607:9000:f00:2::c007",
              "2607:9000:f00:2::c008",
              "2607:9000:f00:2::c009",
              "2607:9000:f00:2::c00a",
              "2607:9000:f00:2::c00b",
              "2607:9000:f00:2::c00c",
              "2607:9000:f00:2::c00d",
              "2607:9000:f00:2::c00e",
              "2607:9000:f00:2::c00f",
              "2607:9000:f00:2::c010",
              "2607:9000:f00:2::c011",
              "2607:9000:f00:2::c012",
              "2607:9000:f00:2::c013",
              "2607:9000:f00:2::c014",
              "2607:9000:f00:2::c015",
              "2607:9000:f00:2::c016",
              "2607:9000:f00:2::c017",
              "2607:9000:f00:2::c018",
              "2607:9000:f00:2::c019",
              "2607:9000:f00:2::c01a",
              "2607:9000:f00:2::c01b",
              "2607:9000:f00:2::c01c",
              "2607:9000:f00:2::c01d",
              "2607:9000:f00:2::c01e",
              "2607:9000:f00:2::c01f"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "ca-mtr-wg-301.blockerad.eu"
          }
        }
      },
      {
        "hostname": "ca-mtr-wg-302",
        "location": "ca-mtr",
        "active": true,
        "owned": false,
        "provider": "Tzulo",
        "stboot": true,
        "ipv4_addr_in": "23.234.120.127",
        "include_in_country": true,
        "weight": 100,
        "public_key": "ihfPUEJ+SOFLzpb6ATGKX1/aAOA2MiTgm36yxmMdNUs=",
        "ipv6_addr_in": "2607:9000:f00:3::f001",
        "shadowsocks_extra_addr_in": [
          "23.234.120.130",
          "23.234.120.131",
          "23.234.120.132",
          "23.234.120.133",
          "23.234.120.134",
          "23.234.120.135",
          "23.234.120.136",
          "23.234.120.137",
          "23.234.120.138",
          "23.234.120.139",
          "23.234.120.140",
          "23.234.120.141",
          "23.234.120.142",
          "23.234.120.143",
          "23.234.120.144",
          "2607:9000:f00:3::b002",
          "2607:9000:f00:3::b003",
          "2607:9000:f00:3::b004",
          "2607:9000:f00:3::b005",
          "2607:9000:f00:3::b006",
          "2607:9000:f00:3::b007",
          "2607:9000:f00:3::b008",
          "2607:9000:f00:3::b009",
          "2607:9000:f00:3::b00a",
          "2607:9000:f00:3::b00b",
          "2607:9000:f00:3::b00c",
          "2607:9000:f00:3::b00d",
          "2607:9000:f00:3::b00e",
          "2607:9000:f00:3::b00f",
          "2607:9000:f00:3::b010",
          "2607:9000:f00:3::b011",
          "2607:9000:f00:3::b012",
          "2607:9000:f00:3::b013",
          "2607:9000:f00:3::b014",
          "2607:9000:f00:3::b015",
          "2607:9000:f00:3::b016",
          "2607:9000:f00:3::b017",
          "2607:9000:f00:3::b018",
          "2607:9000:f00:3::b019",
          "2607:9000:f00:3::b01a",
          "2607:9000:f00:3::b01b",
          "2607:9000:f00:3::b01c",
          "2607:9000:f00:3::b01d",
          "2607:9000:f00:3::b01e",
          "2607:9000:f00:3::b01f"
        ],
        "features": {
          "lwo": {},
          "quic": {
            "addr_in": [
              "23.234.120.145",
              "23.234.120.146",
              "23.234.120.147",
              "23.234.120.148",
              "23.234.120.149",
              "23.234.120.150",
              "23.234.120.151",
              "23.234.120.152",
              "23.234.120.153",
              "23.234.120.154",
              "23.234.120.155",
              "23.234.120.156",
              "23.234.120.157",
              "23.234.120.158",
              "23.234.120.159",
              "2607:9000:f00:3::c002",
              "2607:9000:f00:3::c003",
              "2607:9000:f00:3::c004",
              "2607:9000:f00:3::c005",
              "2607:9000:f00:3::c006",
              "2607:9000:f00:3::c007",
              "2607:9000:f00:3::c008",
              "2607:9000:f00:3::c009",
              "2607:9000:f00:3::c00a",
              "2607:9000:f00:3::c00b",
              "2607:9000:f00:3::c00c",
              "2607:9000:f00:3::c00d",
              "2607:9000:f00:3::c00e",
              "2607:9000:f00:3::c00f",
              "2607:9000:f00:3::c010",
              "2607:9000:f00:3::c011",
              "2607:9000:f00:3::c012",
              "2607:9000:f00:3::c013",
              "2607:9000:f00:3::c014",
              "2607:9000:f00:3::c015",
              "2607:9000:f00:3::c016",
              "2607:9000:f00:3::c017",
              "2607:9000:f00:3::c018",
              "2607:9000:f00:3::c019",
              "2607:9000:f00:3::c01a",
              "2607:9000:f00:3::c01b",
              "2607:9000:f00:3::c01c",
              "2607:9000:f00:3::c01d",
              "2607:9000:f00:3::c01e",
              "2607:9000:f00:3::c01f"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "ca-mtr-wg-302.blockerad.eu"
          }
        }
      },
      {
        "hostname": "ca-mtr-wg-303",
        "location": "ca-mtr",
        "active": true,
        "owned": false,
        "provider": "Tzulo",
        "stboot": true,
        "ipv4_addr_in": "23.234.121.2",
        "include_in_country": true,
        "weight": 100,
        "public_key": "jS8Wn97oET0rNFD9yIoJIahbVfMc6aubJq6G7+C1PBs=",
        "ipv6_addr_in": "2607:9000:f00:4::f01f",
        "shadowsocks_extra_addr_in": [
          "23.234.121.5",
          "23.234.121.6",
          "23.234.121.7",
          "23.234.121.8",
          "23.234.121.9",
          "23.234.121.10",
          "23.234.121.11",
          "23.234.121.12",
          "23.234.121.13",
          "23.234.121.14",
          "23.234.121.15",
          "23.234.121.16",
          "23.234.121.17",
          "23.234.121.18",
          "23.234.121.19",
          "2607:9000:f00:4::b002",
          "2607:9000:f00:4::b003",
          "2607:9000:f00:4::b004",
          "2607:9000:f00:4::b005",
          "2607:9000:f00:4::b006",
          "2607:9000:f00:4::b007",
          "2607:9000:f00:4::b008",
          "2607:9000:f00:4::b009",
          "2607:9000:f00:4::b00a",
          "2607:9000:f00:4::b00b",
          "2607:9000:f00:4::b00c",
          "2607:9000:f00:4::b00d",
          "2607:9000:f00:4::b00e",
          "2607:9000:f00:4::b00f",
          "2607:9000:f00:4::b010",
          "2607:9000:f00:4::b011",
          "2607:9000:f00:4::b012",
          "2607:9000:f00:4::b013",
          "2607:9000:f00:4::b014",
          "2607:9000:f00:4::b015",
          "2607:9000:f00:4::b016",
          "2607:9000:f00:4::b017",
          "2607:9000:f00:4::b018",
          "2607:9000:f00:4::b019",
          "2607:9000:f00:4::b01a",
          "2607:9000:f00:4::b01b",
          "2607:9000:f00:4::b01c",
          "2607:9000:f00:4::b01d",
          "2607:9000:f00:4::b01e",
          "2607:9000:f00:4::b01f"
        ],
        "features": {
          "lwo": {},
          "quic": {
            "addr_in": [
              "23.234.121.20",
              "23.234.121.21",
              "23.234.121.22",
              "23.234.121.23",
              "23.234.121.24",
              "23.234.121.25",
              "23.234.121.26",
              "23.234.121.27",
              "23.234.121.28",
              "23.234.121.29",
              "23.234.121.30",
              "23.234.121.31",
              "23.234.121.32",
              "23.234.121.33",
              "23.234.121.34",
              "2607:9000:f00:4::c002",
              "2607:9000:f00:4::c003",
              "2607:9000:f00:4::c004",
              "2607:9000:f00:4::c005",
              "2607:9000:f00:4::c006",
              "2607:9000:f00:4::c007",
              "2607:9000:f00:4::c008",
              "2607:9000:f00:4::c009",
              "2607:9000:f00:4::c00a",
              "2607:9000:f00:4::c00b",
              "2607:9000:f00:4::c00c",
              "2607:9000:f00:4::c00d",
              "2607:9000:f00:4::c00e",
              "2607:9000:f00:4::c00f",
              "2607:9000:f00:4::c010",
              "2607:9000:f00:4::c011",
              "2607:9000:f00:4::c012",
              "2607:9000:f00:4::c013",
              "2607:9000:f00:4::c014",
              "2607:9000:f00:4::c015",
              "2607:9000:f00:4::c016",
              "2607:9000:f00:4::c017",
              "2607:9000:f00:4::c018",
              "2607:9000:f00:4::c019",
              "2607:9000:f00:4::c01a",
              "2607:9000:f00:4::c01b",
              "2607:9000:f00:4::c01c",
              "2607:9000:f00:4::c01d",
              "2607:9000:f00:4::c01e",
              "2607:9000:f00:4::c01f"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "ca-mtr-wg-303.blockerad.eu"
          }
        }
      },
      {
        "hostname": "ca-mtr-wg-304",
        "location": "ca-mtr",
        "active": true,
        "owned": false,
        "provider": "Tzulo",
        "stboot": true,
        "ipv4_addr_in": "23.234.121.127",
        "include_in_country": true,
        "weight": 100,
        "public_key": "zY8NKWC/zDdNBBFFtH3acoZAJj2BD/AYZVOUiIRZric=",
        "ipv6_addr_in": "2607:9000:f00:5::f001",
        "shadowsocks_extra_addr_in": [
          "23.234.121.130",
          "23.234.121.131",
          "23.234.121.132",
          "23.234.121.133",
          "23.234.121.134",
          "23.234.121.135",
          "23.234.121.136",
          "23.234.121.137",
          "23.234.121.138",
          "23.234.121.139",
          "23.234.121.140",
          "23.234.121.141",
          "23.234.121.142",
          "23.234.121.143",
          "23.234.121.144",
          "2607:9000:f00:5::b002",
          "2607:9000:f00:5::b003",
          "2607:9000:f00:5::b004",
          "2607:9000:f00:5::b005",
          "2607:9000:f00:5::b006",
          "2607:9000:f00:5::b007",
          "2607:9000:f00:5::b008",
          "2607:9000:f00:5::b009",
          "2607:9000:f00:5::b00a",
          "2607:9000:f00:5::b00b",
          "2607:9000:f00:5::b00c",
          "2607:9000:f00:5::b00d",
          "2607:9000:f00:5::b00e",
          "2607:9000:f00:5::b00f",
          "2607:9000:f00:5::b010",
          "2607:9000:f00:5::b011",
          "2607:9000:f00:5::b012",
          "2607:9000:f00:5::b013",
          "2607:9000:f00:5::b014",
          "2607:9000:f00:5::b015",
          "2607:9000:f00:5::b016",
          "2607:9000:f00:5::b017",
          "2607:9000:f00:5::b018",
          "2607:9000:f00:5::b019",
          "2607:9000:f00:5::b01a",
          "2607:9000:f00:5::b01b",
          "2607:9000:f00:5::b01c",
          "2607:9000:f00:5::b01d",
          "2607:9000:f00:5::b01e",
          "2607:9000:f00:5::b01f"
        ],
        "features": {
          "lwo": {},
          "quic": {
            "addr_in": [
              "23.234.121.145",
              "23.234.121.146",
              "23.234.121.147",
              "23.234.121.148",
              "23.234.121.149",
              "23.234.121.150",
              "23.234.121.151",
              "23.234.121.152",
              "23.234.121.153",
              "23.234.121.154",
              "23.234.121.155",
              "23.234.121.156",
              "23.234.121.157",
              "23.234.121.158",
              "23.234.121.159",
              "2607:9000:f00:5::c002",
              "2607:9000:f00:5::c003",
              "2607:9000:f00:5::c004",
              "2607:9000:f00:5::c005",
              "2607:9000:f00:5::c006",
              "2607:9000:f00:5::c007",
              "2607:9000:f00:5::c008",
              "2607:9000:f00:5::c009",
              "2607:9000:f00:5::c00a",
              "2607:9000:f00:5::c00b",
              "2607:9000:f00:5::c00c",
              "2607:9000:f00:5::c00d",
              "2607:9000:f00:5::c00e",
              "2607:9000:f00:5::c00f",
              "2607:9000:f00:5::c010",
              "2607:9000:f00:5::c011",
              "2607:9000:f00:5::c012",
              "2607:9000:f00:5::c013",
              "2607:9000:f00:5::c014",
              "2607:9000:f00:5::c015",
              "2607:9000:f00:5::c016",
              "2607:9000:f00:5::c017",
              "2607:9000:f00:5::c018",
              "2607:9000:f00:5::c019",
              "2607:9000:f00:5::c01a",
              "2607:9000:f00:5::c01b",
              "2607:9000:f00:5::c01c",
              "2607:9000:f00:5::c01d",
              "2607:9000:f00:5::c01e",
              "2607:9000:f00:5::c01f"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "ca-mtr-wg-304.blockerad.eu"
          }
        }
      },
      {
        "hostname": "ca-mtr-wg-305",
        "location": "ca-mtr",
        "active": true,
        "owned": false,
        "provider": "Tzulo",
        "stboot": true,
        "ipv4_addr_in": "23.234.122.2",
        "include_in_country": true,
        "weight": 100,
        "public_key": "vHxqoUcH2dHqphHD6Kj74gf8+SldQ/S2XP1nbasTSkQ=",
        "ipv6_addr_in": "2607:9000:f00:6::f001",
        "shadowsocks_extra_addr_in": [
          "23.234.122.5",
          "23.234.122.6",
          "23.234.122.7",
          "23.234.122.8",
          "23.234.122.9",
          "23.234.122.10",
          "23.234.122.11",
          "23.234.122.12",
          "23.234.122.13",
          "23.234.122.14",
          "23.234.122.15",
          "23.234.122.16",
          "23.234.122.17",
          "23.234.122.18",
          "23.234.122.19",
          "2607:9000:f00:6::b002",
          "2607:9000:f00:6::b003",
          "2607:9000:f00:6::b004",
          "2607:9000:f00:6::b005",
          "2607:9000:f00:6::b006",
          "2607:9000:f00:6::b007",
          "2607:9000:f00:6::b008",
          "2607:9000:f00:6::b009",
          "2607:9000:f00:6::b00a",
          "2607:9000:f00:6::b00b",
          "2607:9000:f00:6::b00c",
          "2607:9000:f00:6::b00d",
          "2607:9000:f00:6::b00e",
          "2607:9000:f00:6::b00f",
          "2607:9000:f00:6::b010",
          "2607:9000:f00:6::b011",
          "2607:9000:f00:6::b012",
          "2607:9000:f00:6::b013",
          "2607:9000:f00:6::b014",
          "2607:9000:f00:6::b015",
          "2607:9000:f00:6::b016",
          "2607:9000:f00:6::b017",
          "2607:9000:f00:6::b018",
          "2607:9000:f00:6::b019",
          "2607:9000:f00:6::b01a",
          "2607:9000:f00:6::b01b",
          "2607:9000:f00:6::b01c",
          "2607:9000:f00:6::b01d",
          "2607:9000:f00:6::b01e",
          "2607:9000:f00:6::b01f"
        ],
        "features": {
          "lwo": {},
          "quic": {
            "addr_in": [
              "23.234.122.20",
              "23.234.122.21",
              "23.234.122.22",
              "23.234.122.23",
              "23.234.122.24",
              "23.234.122.25",
              "23.234.122.26",
              "23.234.122.27",
              "23.234.122.28",
              "23.234.122.29",
              "23.234.122.30",
              "23.234.122.31",
              "23.234.122.32",
              "23.234.122.33",
              "23.234.122.34",
              "2607:9000:f00:6::c002",
              "2607:9000:f00:6::c003",
              "2607:9000:f00:6::c004",
              "2607:9000:f00:6::c005",
              "2607:9000:f00:6::c006",
              "2607:9000:f00:6::c007",
              "2607:9000:f00:6::c008",
              "2607:9000:f00:6::c009",
              "2607:9000:f00:6::c00a",
              "2607:9000:f00:6::c00b",
              "2607:9000:f00:6::c00c",
              "2607:9000:f00:6::c00d",
              "2607:9000:f00:6::c00e",
              "2607:9000:f00:6::c00f",
              "2607:9000:f00:6::c010",
              "2607:9000:f00:6::c011",
              "2607:9000:f00:6::c012",
              "2607:9000:f00:6::c013",
              "2607:9000:f00:6::c014",
              "2607:9000:f00:6::c015",
              "2607:9000:f00:6::c016",
              "2607:9000:f00:6::c017",
              "2607:9000:f00:6::c018",
              "2607:9000:f00:6::c019",
              "2607:9000:f00:6::c01a",
              "2607:9000:f00:6::c01b",
              "2607:9000:f00:6::c01c",
              "2607:9000:f00:6::c01d",
              "2607:9000:f00:6::c01e",
              "2607:9000:f00:6::c01f"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "ca-mtr-wg-305.blockerad.eu"
          }
        }
      },
      {
        "hostname": "ca-mtr-wg-306",
        "location": "ca-mtr",
        "active": true,
        "owned": false,
        "provider": "Tzulo",
        "stboot": true,
        "ipv4_addr_in": "23.234.122.127",
        "include_in_country": true,
        "weight": 100,
        "public_key": "R4SOqKLtNuNSPg1L9/4mK56nahUN9uEFleuZorBXOjM=",
        "ipv6_addr_in": "2607:9000:f00:7::f001",
        "shadowsocks_extra_addr_in": [
          "23.234.122.130",
          "23.234.122.131",
          "23.234.122.132",
          "23.234.122.133",
          "23.234.122.134",
          "23.234.122.135",
          "23.234.122.136",
          "23.234.122.137",
          "23.234.122.138",
          "23.234.122.139",
          "23.234.122.140",
          "23.234.122.141",
          "23.234.122.142",
          "23.234.122.143",
          "23.234.122.144",
          "2607:9000:f00:7::b002",
          "2607:9000:f00:7::b003",
          "2607:9000:f00:7::b004",
          "2607:9000:f00:7::b005",
          "2607:9000:f00:7::b006",
          "2607:9000:f00:7::b007",
          "2607:9000:f00:7::b008",
          "2607:9000:f00:7::b009",
          "2607:9000:f00:7::b00a",
          "2607:9000:f00:7::b00b",
          "2607:9000:f00:7::b00c",
          "2607:9000:f00:7::b00d",
          "2607:9000:f00:7::b00e",
          "2607:9000:f00:7::b00f",
          "2607:9000:f00:7::b010",
          "2607:9000:f00:7::b011",
          "2607:9000:f00:7::b012",
          "2607:9000:f00:7::b013",
          "2607:9000:f00:7::b014",
          "2607:9000:f00:7::b015",
          "2607:9000:f00:7::b016",
          "2607:9000:f00:7::b017",
          "2607:9000:f00:7::b018",
          "2607:9000:f00:7::b019",
          "2607:9000:f00:7::b01a",
          "2607:9000:f00:7::b01b",
          "2607:9000:f00:7::b01c",
          "2607:9000:f00:7::b01d",
          "2607:9000:f00:7::b01e",
          "2607:9000:f00:7::b01f"
        ],
        "features": {
          "lwo": {},
          "quic": {
            "addr_in": [
              "23.234.122.130",
              "23.234.122.131",
              "23.234.122.132",
              "23.234.122.133",
              "23.234.122.134",
              "23.234.122.135",
              "23.234.122.136",
              "23.234.122.137",
              "23.234.122.138",
              "23.234.122.139",
              "23.234.122.140",
              "23.234.122.141",
              "23.234.122.142",
              "23.234.122.143",
              "23.234.122.144",
              "2607:9000:f00:7::b002",
              "2607:9000:f00:7::b003",
              "2607:9000:f00:7::b004",
              "2607:9000:f00:7::b005",
              "2607:9000:f00:7::b006",
              "2607:9000:f00:7::b007",
              "2607:9000:f00:7::b008",
              "2607:9000:f00:7::b009",
              "2607:9000:f00:7::b00a",
              "2607:9000:f00:7::b00b",
              "2607:9000:f00:7::b00c",
              "2607:9000:f00:7::b00d",
              "2607:9000:f00:7::b00e",
              "2607:9000:f00:7::b00f",
              "2607:9000:f00:7::b010",
              "2607:9000:f00:7::b011",
              "2607:9000:f00:7::b012",
              "2607:9000:f00:7::b013",
              "2607:9000:f00:7::b014",
              "2607:9000:f00:7::b015",
              "2607:9000:f00:7::b016",
              "2607:9000:f00:7::b017",
              "2607:9000:f00:7::b018",
              "2607:9000:f00:7::b019",
              "2607:9000:f00:7::b01a",
              "2607:9000:f00:7::b01b",
              "2607:9000:f00:7::b01c",
              "2607:9000:f00:7::b01d",
              "2607:9000:f00:7::b01e",
              "2607:9000:f00:7::b01f"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "ca-mtr-wg-306.blockerad.eu"
          }
        }
      },
      {
        "hostname": "ca-mtr-wg-307",
        "location": "ca-mtr",
        "active": true,
        "owned": false,
        "provider": "Tzulo",
        "stboot": true,
        "ipv4_addr_in": "23.234.123.2",
        "include_in_country": true,
        "weight": 100,
        "public_key": "MRbFe1jzuvCprXrnW2H6TpQnWx5MBwjYS+iIAhtrejc=",
        "ipv6_addr_in": "2607:9000:f00:8::f001",
        "shadowsocks_extra_addr_in": [
          "23.234.123.5",
          "23.234.123.6",
          "23.234.123.7",
          "23.234.123.8",
          "23.234.123.9",
          "23.234.123.10",
          "23.234.123.11",
          "23.234.123.12",
          "23.234.123.13",
          "23.234.123.14",
          "23.234.123.15",
          "23.234.123.16",
          "23.234.123.17",
          "23.234.123.18",
          "23.234.123.19",
          "2607:9000:f00:8::b002",
          "2607:9000:f00:8::b003",
          "2607:9000:f00:8::b004",
          "2607:9000:f00:8::b005",
          "2607:9000:f00:8::b006",
          "2607:9000:f00:8::b007",
          "2607:9000:f00:8::b008",
          "2607:9000:f00:8::b009",
          "2607:9000:f00:8::b00a",
          "2607:9000:f00:8::b00b",
          "2607:9000:f00:8::b00c",
          "2607:9000:f00:8::b00d",
          "2607:9000:f00:8::b00e",
          "2607:9000:f00:8::b00f",
          "2607:9000:f00:8::b010",
          "2607:9000:f00:8::b011",
          "2607:9000:f00:8::b012",
          "2607:9000:f00:8::b013",
          "2607:9000:f00:8::b014",
          "2607:9000:f00:8::b015",
          "2607:9000:f00:8::b016",
          "2607:9000:f00:8::b017",
          "2607:9000:f00:8::b018",
          "2607:9000:f00:8::b019",
          "2607:9000:f00:8::b01a",
          "2607:9000:f00:8::b01b",
          "2607:9000:f00:8::b01c",
          "2607:9000:f00:8::b01d",
          "2607:9000:f00:8::b01e",
          "2607:9000:f00:8::b01f"
        ],
        "features": {
          "quic": {
            "addr_in": [
              "23.234.123.5",
              "23.234.123.6",
              "23.234.123.7",
              "23.234.123.8",
              "23.234.123.9",
              "23.234.123.10",
              "23.234.123.11",
              "23.234.123.12",
              "23.234.123.13",
              "23.234.123.14",
              "23.234.123.15",
              "23.234.123.16",
              "23.234.123.17",
              "23.234.123.18",
              "23.234.123.19",
              "2607:9000:f00:8::b002",
              "2607:9000:f00:8::b003",
              "2607:9000:f00:8::b004",
              "2607:9000:f00:8::b005",
              "2607:9000:f00:8::b006",
              "2607:9000:f00:8::b007",
              "2607:9000:f00:8::b008",
              "2607:9000:f00:8::b009",
              "2607:9000:f00:8::b00a",
              "2607:9000:f00:8::b00b",
              "2607:9000:f00:8::b00c",
              "2607:9000:f00:8::b00d",
              "2607:9000:f00:8::b00e",
              "2607:9000:f00:8::b00f",
              "2607:9000:f00:8::b010",
              "2607:9000:f00:8::b011",
              "2607:9000:f00:8::b012",
              "2607:9000:f00:8::b013",
              "2607:9000:f00:8::b014",
              "2607:9000:f00:8::b015",
              "2607:9000:f00:8::b016",
              "2607:9000:f00:8::b017",
              "2607:9000:f00:8::b018",
              "2607:9000:f00:8::b019",
              "2607:9000:f00:8::b01a",
              "2607:9000:f00:8::b01b",
              "2607:9000:f00:8::b01c",
              "2607:9000:f00:8::b01d",
              "2607:9000:f00:8::b01e",
              "2607:9000:f00:8::b01f"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "ca-mtr-wg-307.blockerad.eu"
          }
        }
      },
      {
        "hostname": "ca-mtr-wg-308",
        "location": "ca-mtr",
        "active": true,
        "owned": false,
        "provider": "Tzulo",
        "stboot": true,
        "ipv4_addr_in": "23.234.123.127",
        "include_in_country": true,
        "weight": 100,
        "public_key": "lyOeQQ2eGQgEdV+uH/S7UPOPMCsRWkDSQiZhPTUT0AI=",
        "ipv6_addr_in": "2607:9000:f00:9::f001",
        "shadowsocks_extra_addr_in": [
          "23.234.123.130",
          "23.234.123.131",
          "23.234.123.132",
          "23.234.123.133",
          "23.234.123.134",
          "23.234.123.135",
          "23.234.123.136",
          "23.234.123.137",
          "23.234.123.138",
          "23.234.123.139",
          "23.234.123.140",
          "23.234.123.141",
          "23.234.123.142",
          "23.234.123.143",
          "23.234.123.144",
          "2607:9000:f00:9::b002",
          "2607:9000:f00:9::b003",
          "2607:9000:f00:9::b004",
          "2607:9000:f00:9::b005",
          "2607:9000:f00:9::b006",
          "2607:9000:f00:9::b007",
          "2607:9000:f00:9::b008",
          "2607:9000:f00:9::b009",
          "2607:9000:f00:9::b00a",
          "2607:9000:f00:9::b00b",
          "2607:9000:f00:9::b00c",
          "2607:9000:f00:9::b00d",
          "2607:9000:f00:9::b00e",
          "2607:9000:f00:9::b00f",
          "2607:9000:f00:9::b010",
          "2607:9000:f00:9::b011",
          "2607:9000:f00:9::b012",
          "2607:9000:f00:9::b013",
          "2607:9000:f00:9::b014",
          "2607:9000:f00:9::b015",
          "2607:9000:f00:9::b016",
          "2607:9000:f00:9::b017",
          "2607:9000:f00:9::b018",
          "2607:9000:f00:9::b019",
          "2607:9000:f00:9::b01a",
          "2607:9000:f00:9::b01b",
          "2607:9000:f00:9::b01c",
          "2607:9000:f00:9::b01d",
          "2607:9000:f00:9::b01e",
          "2607:9000:f00:9::b01f"
        ],
        "features": {
          "quic": {
            "addr_in": [
              "23.234.123.130",
              "23.234.123.131",
              "23.234.123.132",
              "23.234.123.133",
              "23.234.123.134",
              "23.234.123.135",
              "23.234.123.136",
              "23.234.123.137",
              "23.234.123.138",
              "23.234.123.139",
              "23.234.123.140",
              "23.234.123.141",
              "23.234.123.142",
              "23.234.123.143",
              "23.234.123.144",
              "2607:9000:f00:9::b002",
              "2607:9000:f00:9::b003",
              "2607:9000:f00:9::b004",
              "2607:9000:f00:9::b005",
              "2607:9000:f00:9::b006",
              "2607:9000:f00:9::b007",
              "2607:9000:f00:9::b008",
              "2607:9000:f00:9::b009",
              "2607:9000:f00:9::b00a",
              "2607:9000:f00:9::b00b",
              "2607:9000:f00:9::b00c",
              "2607:9000:f00:9::b00d",
              "2607:9000:f00:9::b00e",
              "2607:9000:f00:9::b00f",
              "2607:9000:f00:9::b010",
              "2607:9000:f00:9::b011",
              "2607:9000:f00:9::b012",
              "2607:9000:f00:9::b013",
              "2607:9000:f00:9::b014",
              "2607:9000:f00:9::b015",
              "2607:9000:f00:9::b016",
              "2607:9000:f00:9::b017",
              "2607:9000:f00:9::b018",
              "2607:9000:f00:9::b019",
              "2607:9000:f00:9::b01a",
              "2607:9000:f00:9::b01b",
              "2607:9000:f00:9::b01c",
              "2607:9000:f00:9::b01d",
              "2607:9000:f00:9::b01e",
              "2607:9000:f00:9::b01f"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "ca-mtr-wg-308.blockerad.eu"
          }
        }
      },
      {
        "hostname": "ca-tor-wg-001",
        "location": "ca-tor",
        "active": true,
        "owned": false,
        "provider": "DataPacket",
        "stboot": true,
        "ipv4_addr_in": "178.249.214.2",
        "include_in_country": true,
        "weight": 100,
        "public_key": "HjcUGVDXWdrRkaKNpc/8494RM5eICO6DPyrhCtTv9Ws=",
        "ipv6_addr_in": "2a02:6ea0:de08:1::f001",
        "daita": true,
        "features": {
          "daita": {}
        }
      },
      {
        "hostname": "ca-tor-wg-002",
        "location": "ca-tor",
        "active": true,
        "owned": false,
        "provider": "DataPacket",
        "stboot": true,
        "ipv4_addr_in": "178.249.214.15",
        "include_in_country": true,
        "weight": 100,
        "public_key": "iqZSgVlU9H67x/uYE5xsnzLCDXf7FL9iMfyKfl6WsV8=",
        "ipv6_addr_in": "2a02:6ea0:de08:2::a29f"
      },
      {
        "hostname": "ca-tor-wg-201",
        "location": "ca-tor",
        "active": true,
        "owned": false,
        "provider": "Tzulo",
        "stboot": true,
        "ipv4_addr_in": "23.234.84.2",
        "include_in_country": true,
        "weight": 100,
        "public_key": "94nJF3WyWKsZQOFhWWco8cjBOrSYADsMSTeivfbWQyw=",
        "ipv6_addr_in": "2607:9000:600:31::f001",
        "daita": true,
        "shadowsocks_extra_addr_in": [
          "23.234.84.13"
        ],
        "features": {
          "daita": {},
          "lwo": {},
          "quic": {
            "addr_in": [
              "23.234.84.12",
              "2607:9000:600:31::f00a"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "ca-tor-wg-201.blockerad.eu"
          }
        }
      },
      {
        "hostname": "ca-tor-wg-202",
        "location": "ca-tor",
        "active": true,
        "owned": false,
        "provider": "Tzulo",
        "stboot": true,
        "ipv4_addr_in": "23.234.84.127",
        "include_in_country": true,
        "weight": 100,
        "public_key": "vr/sAm+36c3N8jWfo14Sw6El0xJeSvu/soU/8JWSb3U=",
        "ipv6_addr_in": "2607:9000:600:32::f001",
        "daita": true,
        "shadowsocks_extra_addr_in": [
          "23.234.84.138"
        ],
        "features": {
          "daita": {},
          "lwo": {},
          "quic": {
            "addr_in": [
              "23.234.84.137"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "ca-tor-wg-202.blockerad.eu"
          }
        }
      },
      {
        "hostname": "ca-tor-wg-203",
        "location": "ca-tor",
        "active": true,
        "owned": false,
        "provider": "Tzulo",
        "stboot": true,
        "ipv4_addr_in": "23.234.85.2",
        "include_in_country": true,
        "weight": 100,
        "public_key": "kpXVJa66qgBFlwCmHx6siJT3R9afvtbjdDOTKkkbiUI=",
        "ipv6_addr_in": "2607:9000:600:33::f001",
        "shadowsocks_extra_addr_in": [
          "23.234.85.13"
        ],
        "features": {
          "lwo": {},
          "quic": {
            "addr_in": [
              "23.234.85.12"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "ca-tor-wg-203.blockerad.eu"
          }
        }
      },
      {
        "hostname": "ca-tor-wg-204",
        "location": "ca-tor",
        "active": true,
        "owned": false,
        "provider": "Tzulo",
        "stboot": true,
        "ipv4_addr_in": "23.234.85.127",
        "include_in_country": true,
        "weight": 100,
        "public_key": "APcoI2H2zdWIMdVYXslcJm4zzgePc4PESsDHgkm0UnQ=",
        "ipv6_addr_in": "2607:9000:600:34::f001",
        "shadowsocks_extra_addr_in": [
          "23.234.85.138"
        ],
        "features": {
          "quic": {
            "addr_in": [
              "23.234.85.137"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "ca-tor-wg-204.blockerad.eu"
          }
        }
      },
      {
        "hostname": "ca-tor-wg-205",
        "location": "ca-tor",
        "active": true,
        "owned": false,
        "provider": "Tzulo",
        "stboot": true,
        "ipv4_addr_in": "23.234.86.2",
        "include_in_country": true,
        "weight": 100,
        "public_key": "iePZCguBaIxO/7gqQGDDYwl6YzMZj5910nK2Q9bDP14=",
        "ipv6_addr_in": "2607:9000:600:35::f001",
        "shadowsocks_extra_addr_in": [
          "23.234.86.13"
        ],
        "features": {
          "quic": {
            "addr_in": [
              "23.234.86.12"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "ca-tor-wg-205.blockerad.eu"
          }
        }
      },
      {
        "hostname": "ca-tor-wg-206",
        "location": "ca-tor",
        "active": true,
        "owned": false,
        "provider": "Tzulo",
        "stboot": true,
        "ipv4_addr_in": "23.234.86.127",
        "include_in_country": true,
        "weight": 100,
        "public_key": "PGPyMyMPZ7Lue4pvFK7hlavToQ5FfBODmQBoiaUZ40I=",
        "ipv6_addr_in": "2607:9000:600:36::f001",
        "shadowsocks_extra_addr_in": [
          "23.234.86.138"
        ],
        "features": {
          "quic": {
            "addr_in": [
              "23.234.86.137"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "ca-tor-wg-206.blockerad.eu"
          }
        }
      },
      {
        "hostname": "ca-tor-wg-207",
        "location": "ca-tor",
        "active": true,
        "owned": false,
        "provider": "Tzulo",
        "stboot": true,
        "ipv4_addr_in": "23.234.87.2",
        "include_in_country": true,
        "weight": 100,
        "public_key": "8VmxIxjz5W44ubaBuIt5JEngh7fKCvdmdG9WBN2oqhw=",
        "ipv6_addr_in": "2607:9000:600:37::f001",
        "shadowsocks_extra_addr_in": [
          "23.234.87.13"
        ],
        "features": {
          "quic": {
            "addr_in": [
              "23.234.87.12",
              "2607:9000:600:37::f00a"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "ca-tor-wg-207.blockerad.eu"
          }
        }
      },
      {
        "hostname": "ca-van-wg-201",
        "location": "ca-van",
        "active": true,
        "owned": false,
        "provider": "techfutures",
        "stboot": true,
        "ipv4_addr_in": "104.193.135.196",
        "include_in_country": true,
        "weight": 100,
        "public_key": "hYbb2NQKB0g2RefngdHl3bfaLImUuzeVIv2i1VCVIlQ=",
        "ipv6_addr_in": "2606:9580:103:e::f001"
      },
      {
        "hostname": "ca-van-wg-202",
        "location": "ca-van",
        "active": true,
        "owned": false,
        "provider": "techfutures",
        "stboot": true,
        "ipv4_addr_in": "104.193.135.100",
        "include_in_country": true,
        "weight": 100,
        "public_key": "wGqcNxXH7A3bSptHZo7Dfmymy/Y30Ea/Zd47UkyEbzo=",
        "ipv6_addr_in": "2606:9580:103:f::f001"
      },
      {
        "hostname": "ca-van-wg-301",
        "location": "ca-van",
        "active": true,
        "owned": false,
        "provider": "DataPacket",
        "stboot": true,
        "ipv4_addr_in": "149.22.81.194",
        "include_in_country": true,
        "weight": 100,
        "public_key": "BzYINbABQiSbRLDZIlmgsLgL88offQJCEH3JkcjRGUk=",
        "ipv6_addr_in": "2a02:6ea0:5100:1::f001",
        "daita": true,
        "features": {
          "daita": {}
        }
      },
      {
        "hostname": "ca-van-wg-302",
        "location": "ca-van",
        "active": true,
        "owned": false,
        "provider": "DataPacket",
        "stboot": true,
        "ipv4_addr_in": "149.22.81.207",
        "include_in_country": true,
        "weight": 100,
        "public_key": "EOOkxbmbdHmjb8F45s33yKrIzKWH6lGIgJf2kTOxwFw=",
        "ipv6_addr_in": "2a02:6ea0:5100:2::f001"
      },
      {
        "hostname": "ca-yyc-wg-201",
        "location": "ca-yyc",
        "active": true,
        "owned": false,
        "provider": "techfutures",
        "stboot": true,
        "ipv4_addr_in": "38.240.225.36",
        "include_in_country": true,
        "weight": 100,
        "public_key": "L4RcVwk0cJJp2u8O9+86sdyUpxfYnr+ME57Ex0RY1Wo=",
        "ipv6_addr_in": "2606:9580:438:32::f001",
        "shadowsocks_extra_addr_in": [
          "2606:9580:438:32::b002",
          "2606:9580:438:32::b003",
          "2606:9580:438:32::b004",
          "2606:9580:438:32::b005",
          "2606:9580:438:32::b006",
          "2606:9580:438:32::b007",
          "2606:9580:438:32::b008",
          "2606:9580:438:32::b009",
          "2606:9580:438:32::b00a",
          "2606:9580:438:32::b00b",
          "2606:9580:438:32::b00c",
          "2606:9580:438:32::b00d",
          "2606:9580:438:32::b00e",
          "2606:9580:438:32::b00f",
          "2606:9580:438:32::b010",
          "2606:9580:438:32::b011",
          "2606:9580:438:32::b012",
          "2606:9580:438:32::b013",
          "2606:9580:438:32::b014",
          "2606:9580:438:32::b015",
          "2606:9580:438:32::b016",
          "2606:9580:438:32::b017",
          "2606:9580:438:32::b018",
          "2606:9580:438:32::b019",
          "2606:9580:438:32::b01a",
          "2606:9580:438:32::b01b",
          "2606:9580:438:32::b01c",
          "2606:9580:438:32::b01d",
          "2606:9580:438:32::b01e"
        ]
      },
      {
        "hostname": "ca-yyc-wg-202",
        "location": "ca-yyc",
        "active": true,
        "owned": false,
        "provider": "techfutures",
        "stboot": true,
        "ipv4_addr_in": "38.240.225.68",
        "include_in_country": true,
        "weight": 100,
        "public_key": "u9J/fzrSqM2aEFjTs91KEKgBsaQ/I/4XkIP1Z/zYkXA=",
        "ipv6_addr_in": "2606:9580:438:64::f001",
        "shadowsocks_extra_addr_in": [
          "2606:9580:438:64::b002",
          "2606:9580:438:64::b003",
          "2606:9580:438:64::b004",
          "2606:9580:438:64::b005",
          "2606:9580:438:64::b006",
          "2606:9580:438:64::b007",
          "2606:9580:438:64::b008",
          "2606:9580:438:64::b009",
          "2606:9580:438:64::b00a",
          "2606:9580:438:64::b00b",
          "2606:9580:438:64::b00c",
          "2606:9580:438:64::b00d",
          "2606:9580:438:64::b00e",
          "2606:9580:438:64::b00f",
          "2606:9580:438:64::b010",
          "2606:9580:438:64::b011",
          "2606:9580:438:64::b012",
          "2606:9580:438:64::b013",
          "2606:9580:438:64::b014",
          "2606:9580:438:64::b015",
          "2606:9580:438:64::b016",
          "2606:9580:438:64::b017",
          "2606:9580:438:64::b018",
          "2606:9580:438:64::b019",
          "2606:9580:438:64::b01a",
          "2606:9580:438:64::b01b",
          "2606:9580:438:64::b01c",
          "2606:9580:438:64::b01d",
          "2606:9580:438:64::b01e",
          "2606:9580:438:64::b01f"
        ],
        "features": {
          "lwo": {}
        }
      },
      {
        "hostname": "ch-zrh-wg-001",
        "location": "ch-zrh",
        "active": true,
        "owned": true,
        "provider": "31173",
        "stboot": true,
        "ipv4_addr_in": "193.32.127.66",
        "include_in_country": true,
        "weight": 1,
        "public_key": "/iivwlyqWqxQ0BVWmJRhcXIFdJeo0WbHQ/hZwuXaN3g=",
        "ipv6_addr_in": "2a03:1b20:a:f011::f001",
        "shadowsocks_extra_addr_in": [
          "2a03:1b20:a:f011::b002",
          "2a03:1b20:a:f011::b003",
          "2a03:1b20:a:f011::b004",
          "2a03:1b20:a:f011::b005",
          "2a03:1b20:a:f011::b006",
          "2a03:1b20:a:f011::b007",
          "2a03:1b20:a:f011::b008",
          "2a03:1b20:a:f011::b009",
          "2a03:1b20:a:f011::b00a",
          "2a03:1b20:a:f011::b00b",
          "2a03:1b20:a:f011::b00c",
          "2a03:1b20:a:f011::b00d",
          "2a03:1b20:a:f011::b00e",
          "2a03:1b20:a:f011::b00f",
          "2a03:1b20:a:f011::b010",
          "2a03:1b20:a:f011::b011",
          "2a03:1b20:a:f011::b012",
          "2a03:1b20:a:f011::b013",
          "2a03:1b20:a:f011::b014",
          "2a03:1b20:a:f011::b015",
          "2a03:1b20:a:f011::b016",
          "2a03:1b20:a:f011::b017",
          "2a03:1b20:a:f011::b018",
          "2a03:1b20:a:f011::b019",
          "2a03:1b20:a:f011::b01a",
          "2a03:1b20:a:f011::b01b",
          "2a03:1b20:a:f011::b01c",
          "2a03:1b20:a:f011::b01d",
          "2a03:1b20:a:f011::b01e",
          "2a03:1b20:a:f011::b01f"
        ],
        "features": {
          "lwo": {},
          "quic": {
            "addr_in": [
              "193.32.127.99",
              "2a03:1b20:a:f011::c002",
              "2a03:1b20:a:f011::c003",
              "2a03:1b20:a:f011::c004",
              "2a03:1b20:a:f011::c005",
              "2a03:1b20:a:f011::c006",
              "2a03:1b20:a:f011::c007",
              "2a03:1b20:a:f011::c008",
              "2a03:1b20:a:f011::c009",
              "2a03:1b20:a:f011::c00a",
              "2a03:1b20:a:f011::c00b",
              "2a03:1b20:a:f011::c00c",
              "2a03:1b20:a:f011::c00d",
              "2a03:1b20:a:f011::c00e",
              "2a03:1b20:a:f011::c00f",
              "2a03:1b20:a:f011::c010",
              "2a03:1b20:a:f011::c011",
              "2a03:1b20:a:f011::c012",
              "2a03:1b20:a:f011::c013",
              "2a03:1b20:a:f011::c014",
              "2a03:1b20:a:f011::c015",
              "2a03:1b20:a:f011::c016",
              "2a03:1b20:a:f011::c017",
              "2a03:1b20:a:f011::c018",
              "2a03:1b20:a:f011::c019",
              "2a03:1b20:a:f011::c01a",
              "2a03:1b20:a:f011::c01b",
              "2a03:1b20:a:f011::c01c",
              "2a03:1b20:a:f011::c01d",
              "2a03:1b20:a:f011::c01e",
              "2a03:1b20:a:f011::c01f"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "ch-zrh-wg-001.blockerad.eu"
          }
        }
      },
      {
        "hostname": "ch-zrh-wg-002",
        "location": "ch-zrh",
        "active": true,
        "owned": true,
        "provider": "31173",
        "stboot": true,
        "ipv4_addr_in": "193.32.127.67",
        "include_in_country": true,
        "weight": 1,
        "public_key": "qcvI02LwBnTb7aFrOyZSWvg4kb7zNW9/+rS6alnWyFE=",
        "ipv6_addr_in": "2a03:1b20:a:f011::f101",
        "shadowsocks_extra_addr_in": [
          "2a03:1b20:a:f011::b102",
          "2a03:1b20:a:f011::b103",
          "2a03:1b20:a:f011::b104",
          "2a03:1b20:a:f011::b105",
          "2a03:1b20:a:f011::b106",
          "2a03:1b20:a:f011::b107",
          "2a03:1b20:a:f011::b108",
          "2a03:1b20:a:f011::b109",
          "2a03:1b20:a:f011::b10a",
          "2a03:1b20:a:f011::b10b",
          "2a03:1b20:a:f011::b10c",
          "2a03:1b20:a:f011::b10d",
          "2a03:1b20:a:f011::b10e",
          "2a03:1b20:a:f011::b10f",
          "2a03:1b20:a:f011::b110",
          "2a03:1b20:a:f011::b111",
          "2a03:1b20:a:f011::b112",
          "2a03:1b20:a:f011::b113",
          "2a03:1b20:a:f011::b114",
          "2a03:1b20:a:f011::b115",
          "2a03:1b20:a:f011::b116",
          "2a03:1b20:a:f011::b117",
          "2a03:1b20:a:f011::b118",
          "2a03:1b20:a:f011::b119",
          "2a03:1b20:a:f011::b11a",
          "2a03:1b20:a:f011::b11b",
          "2a03:1b20:a:f011::b11c",
          "2a03:1b20:a:f011::b11d",
          "2a03:1b20:a:f011::b11e",
          "2a03:1b20:a:f011::b11f"
        ],
        "features": {
          "lwo": {}
        }
      },
      {
        "hostname": "ch-zrh-wg-003",
        "location": "ch-zrh",
        "active": true,
        "owned": true,
        "provider": "31173",
        "stboot": true,
        "ipv4_addr_in": "193.32.127.68",
        "include_in_country": true,
        "weight": 1,
        "public_key": "5Ms10UxGjCSzwImTrvEjcygsWY8AfMIdYyRvgFuTqH8=",
        "ipv6_addr_in": "2a03:1b20:a:f011::f201",
        "shadowsocks_extra_addr_in": [
          "2a03:1b20:a:f011::b202",
          "2a03:1b20:a:f011::b203",
          "2a03:1b20:a:f011::b204",
          "2a03:1b20:a:f011::b205",
          "2a03:1b20:a:f011::b206",
          "2a03:1b20:a:f011::b207",
          "2a03:1b20:a:f011::b208",
          "2a03:1b20:a:f011::b209",
          "2a03:1b20:a:f011::b20a",
          "2a03:1b20:a:f011::b20b",
          "2a03:1b20:a:f011::b20c",
          "2a03:1b20:a:f011::b20d",
          "2a03:1b20:a:f011::b20e",
          "2a03:1b20:a:f011::b20f",
          "2a03:1b20:a:f011::b210",
          "2a03:1b20:a:f011::b211",
          "2a03:1b20:a:f011::b212",
          "2a03:1b20:a:f011::b213",
          "2a03:1b20:a:f011::b214",
          "2a03:1b20:a:f011::b215",
          "2a03:1b20:a:f011::b216",
          "2a03:1b20:a:f011::b217",
          "2a03:1b20:a:f011::b218",
          "2a03:1b20:a:f011::b219",
          "2a03:1b20:a:f011::b21a",
          "2a03:1b20:a:f011::b21b",
          "2a03:1b20:a:f011::b21c",
          "2a03:1b20:a:f011::b21d",
          "2a03:1b20:a:f011::b21e",
          "2a03:1b20:a:f011::b21f"
        ],
        "features": {
          "lwo": {}
        }
      },
      {
        "hostname": "ch-zrh-wg-004",
        "location": "ch-zrh",
        "active": false,
        "owned": true,
        "provider": "31173",
        "stboot": true,
        "ipv4_addr_in": "193.32.127.69",
        "include_in_country": true,
        "weight": 50,
        "public_key": "C3jAgPirUZG6sNYe4VuAgDEYunENUyG34X42y+SBngQ=",
        "ipv6_addr_in": "2a03:1b20:a:f011::f301",
        "daita": true,
        "shadowsocks_extra_addr_in": [
          "2a03:1b20:a:f011::b302",
          "2a03:1b20:a:f011::b303",
          "2a03:1b20:a:f011::b304",
          "2a03:1b20:a:f011::b305",
          "2a03:1b20:a:f011::b306",
          "2a03:1b20:a:f011::b307",
          "2a03:1b20:a:f011::b308",
          "2a03:1b20:a:f011::b309",
          "2a03:1b20:a:f011::b30a",
          "2a03:1b20:a:f011::b30b",
          "2a03:1b20:a:f011::b30c",
          "2a03:1b20:a:f011::b30d",
          "2a03:1b20:a:f011::b30e",
          "2a03:1b20:a:f011::b30f",
          "2a03:1b20:a:f011::b310",
          "2a03:1b20:a:f011::b311",
          "2a03:1b20:a:f011::b312",
          "2a03:1b20:a:f011::b313",
          "2a03:1b20:a:f011::b314",
          "2a03:1b20:a:f011::b315",
          "2a03:1b20:a:f011::b316",
          "2a03:1b20:a:f011::b317",
          "2a03:1b20:a:f011::b318",
          "2a03:1b20:a:f011::b319",
          "2a03:1b20:a:f011::b31a",
          "2a03:1b20:a:f011::b31b",
          "2a03:1b20:a:f011::b31c",
          "2a03:1b20:a:f011::b31d",
          "2a03:1b20:a:f011::b31e",
          "2a03:1b20:a:f011::b31f"
        ],
        "features": {
          "daita": {},
          "lwo": {}
        }
      },
      {
        "hostname": "ch-zrh-wg-005",
        "location": "ch-zrh",
        "active": true,
        "owned": true,
        "provider": "31173",
        "stboot": true,
        "ipv4_addr_in": "193.32.127.70",
        "include_in_country": true,
        "weight": 50,
        "public_key": "dV/aHhwG0fmp0XuvSvrdWjCtdyhPDDFiE/nuv/1xnRM=",
        "ipv6_addr_in": "2a03:1b20:a:f011::f401",
        "daita": true,
        "shadowsocks_extra_addr_in": [
          "2a03:1b20:a:f011::b402",
          "2a03:1b20:a:f011::b403",
          "2a03:1b20:a:f011::b404",
          "2a03:1b20:a:f011::b405",
          "2a03:1b20:a:f011::b406",
          "2a03:1b20:a:f011::b407",
          "2a03:1b20:a:f011::b408",
          "2a03:1b20:a:f011::b409",
          "2a03:1b20:a:f011::b40a",
          "2a03:1b20:a:f011::b40b",
          "2a03:1b20:a:f011::b40c",
          "2a03:1b20:a:f011::b40d",
          "2a03:1b20:a:f011::b40e",
          "2a03:1b20:a:f011::b40f",
          "2a03:1b20:a:f011::b410",
          "2a03:1b20:a:f011::b411",
          "2a03:1b20:a:f011::b412",
          "2a03:1b20:a:f011::b413",
          "2a03:1b20:a:f011::b414",
          "2a03:1b20:a:f011::b415",
          "2a03:1b20:a:f011::b416",
          "2a03:1b20:a:f011::b417",
          "2a03:1b20:a:f011::b418",
          "2a03:1b20:a:f011::b419",
          "2a03:1b20:a:f011::b41a",
          "2a03:1b20:a:f011::b41b",
          "2a03:1b20:a:f011::b41c",
          "2a03:1b20:a:f011::b41d",
          "2a03:1b20:a:f011::b41e",
          "2a03:1b20:a:f011::b41f"
        ],
        "features": {
          "daita": {},
          "lwo": {}
        }
      },
      {
        "hostname": "ch-zrh-wg-006",
        "location": "ch-zrh",
        "active": true,
        "owned": true,
        "provider": "31173",
        "stboot": true,
        "ipv4_addr_in": "193.32.127.84",
        "include_in_country": true,
        "weight": 50,
        "public_key": "wDjbvO94t0UI1RlimpEFFv7kJ6DngthvuRX6uBN0wAA=",
        "ipv6_addr_in": "2a03:1b20:a:f011::f601",
        "daita": true,
        "shadowsocks_extra_addr_in": [
          "2a03:1b20:a:f011::b602",
          "2a03:1b20:a:f011::b603",
          "2a03:1b20:a:f011::b604",
          "2a03:1b20:a:f011::b605",
          "2a03:1b20:a:f011::b606",
          "2a03:1b20:a:f011::b607",
          "2a03:1b20:a:f011::b608",
          "2a03:1b20:a:f011::b609",
          "2a03:1b20:a:f011::b60a",
          "2a03:1b20:a:f011::b60b",
          "2a03:1b20:a:f011::b60c",
          "2a03:1b20:a:f011::b60d",
          "2a03:1b20:a:f011::b60e",
          "2a03:1b20:a:f011::b60f",
          "2a03:1b20:a:f011::b610",
          "2a03:1b20:a:f011::b611",
          "2a03:1b20:a:f011::b612",
          "2a03:1b20:a:f011::b613",
          "2a03:1b20:a:f011::b614",
          "2a03:1b20:a:f011::b615",
          "2a03:1b20:a:f011::b616",
          "2a03:1b20:a:f011::b617",
          "2a03:1b20:a:f011::b618",
          "2a03:1b20:a:f011::b619",
          "2a03:1b20:a:f011::b61a",
          "2a03:1b20:a:f011::b61b",
          "2a03:1b20:a:f011::b61c",
          "2a03:1b20:a:f011::b61d",
          "2a03:1b20:a:f011::b61e",
          "2a03:1b20:a:f011::b61f"
        ],
        "features": {
          "daita": {},
          "lwo": {}
        }
      },
      {
        "hostname": "ch-zrh-wg-201",
        "location": "ch-zrh",
        "active": true,
        "owned": false,
        "provider": "PrivateLayer",
        "stboot": true,
        "ipv4_addr_in": "179.43.189.66",
        "include_in_country": true,
        "weight": 100,
        "public_key": "66NPINP4+1AlojLP0J6O9GxdloiegNnGMV4Yit9Kzg0=",
        "ipv6_addr_in": "2a02:29b8:dc01:1832::f001",
        "shadowsocks_extra_addr_in": [
          "2a02:29b8:dc01:1831::b002",
          "2a02:29b8:dc01:1831::b003",
          "2a02:29b8:dc01:1831::b004",
          "2a02:29b8:dc01:1831::b005",
          "2a02:29b8:dc01:1831::b006",
          "2a02:29b8:dc01:1831::b007",
          "2a02:29b8:dc01:1831::b008",
          "2a02:29b8:dc01:1831::b009",
          "2a02:29b8:dc01:1831::b00a",
          "2a02:29b8:dc01:1831::b00b",
          "2a02:29b8:dc01:1831::b00c",
          "2a02:29b8:dc01:1831::b00d",
          "2a02:29b8:dc01:1831::b00e",
          "2a02:29b8:dc01:1831::b00f",
          "2a02:29b8:dc01:1831::b010",
          "2a02:29b8:dc01:1831::b011",
          "2a02:29b8:dc01:1831::b012",
          "2a02:29b8:dc01:1831::b013",
          "2a02:29b8:dc01:1831::b014",
          "2a02:29b8:dc01:1831::b015",
          "2a02:29b8:dc01:1831::b016",
          "2a02:29b8:dc01:1831::b017",
          "2a02:29b8:dc01:1831::b018",
          "2a02:29b8:dc01:1831::b019",
          "2a02:29b8:dc01:1831::b01a",
          "2a02:29b8:dc01:1831::b01b",
          "2a02:29b8:dc01:1831::b01c",
          "2a02:29b8:dc01:1831::b01d",
          "2a02:29b8:dc01:1831::b01e",
          "2a02:29b8:dc01:1831::b01f"
        ]
      },
      {
        "hostname": "ch-zrh-wg-202",
        "location": "ch-zrh",
        "active": true,
        "owned": false,
        "provider": "PrivateLayer",
        "stboot": true,
        "ipv4_addr_in": "46.19.136.226",
        "include_in_country": true,
        "weight": 100,
        "public_key": "gSLSfY2zNFRczxHndeda258z+ayMvd7DqTlKYlKWJUo=",
        "ipv6_addr_in": "2a02:29b8:dc01:1831::f101",
        "shadowsocks_extra_addr_in": [
          "2a02:29b8:dc01:1831::b102",
          "2a02:29b8:dc01:1831::b103",
          "2a02:29b8:dc01:1831::b104",
          "2a02:29b8:dc01:1831::b105",
          "2a02:29b8:dc01:1831::b106",
          "2a02:29b8:dc01:1831::b107",
          "2a02:29b8:dc01:1831::b108",
          "2a02:29b8:dc01:1831::b109",
          "2a02:29b8:dc01:1831::b10a",
          "2a02:29b8:dc01:1831::b10b",
          "2a02:29b8:dc01:1831::b10c",
          "2a02:29b8:dc01:1831::b10d",
          "2a02:29b8:dc01:1831::b10e",
          "2a02:29b8:dc01:1831::b10f",
          "2a02:29b8:dc01:1831::b110",
          "2a02:29b8:dc01:1831::b111",
          "2a02:29b8:dc01:1831::b112",
          "2a02:29b8:dc01:1831::b113",
          "2a02:29b8:dc01:1831::b114",
          "2a02:29b8:dc01:1831::b115",
          "2a02:29b8:dc01:1831::b116",
          "2a02:29b8:dc01:1831::b117",
          "2a02:29b8:dc01:1831::b118",
          "2a02:29b8:dc01:1831::b119",
          "2a02:29b8:dc01:1831::b11a",
          "2a02:29b8:dc01:1831::b11b",
          "2a02:29b8:dc01:1831::b11c",
          "2a02:29b8:dc01:1831::b11d",
          "2a02:29b8:dc01:1831::b11e",
          "2a02:29b8:dc01:1831::b11f"
        ]
      },
      {
        "hostname": "ch-zrh-wg-401",
        "location": "ch-zrh",
        "active": true,
        "owned": false,
        "provider": "DataPacket",
        "stboot": true,
        "ipv4_addr_in": "138.199.6.194",
        "include_in_country": true,
        "weight": 80,
        "public_key": "45ud3I5O6GmPXTrMJiqkiPMI/ubucDqzGaiq3CHJXk8=",
        "ipv6_addr_in": "2a02:6ea0:d406:1::a18f",
        "daita": true,
        "features": {
          "daita": {}
        }
      },
      {
        "hostname": "ch-zrh-wg-402",
        "location": "ch-zrh",
        "active": true,
        "owned": false,
        "provider": "DataPacket",
        "stboot": true,
        "ipv4_addr_in": "138.199.6.207",
        "include_in_country": true,
        "weight": 80,
        "public_key": "7VCMEE+Oljm/qKfQJSUCOYPtRSwdOnuPyqo5Vob+GRY=",
        "ipv6_addr_in": "2a02:6ea0:d406:2::a19f"
      },
      {
        "hostname": "ch-zrh-wg-403",
        "location": "ch-zrh",
        "active": false,
        "owned": false,
        "provider": "DataPacket",
        "stboot": true,
        "ipv4_addr_in": "138.199.6.220",
        "include_in_country": true,
        "weight": 80,
        "public_key": "Jmhds6oPu6/j94hjllJCIaKLDyWu6V+ZNRrVVFhWJkI=",
        "ipv6_addr_in": "2a02:6ea0:d406:3::a20f"
      },
      {
        "hostname": "ch-zrh-wg-404",
        "location": "ch-zrh",
        "active": true,
        "owned": false,
        "provider": "DataPacket",
        "stboot": true,
        "ipv4_addr_in": "138.199.6.233",
        "include_in_country": true,
        "weight": 80,
        "public_key": "zfNQqDyPmSUY8+20wxACe/wpk4Q5jpZm5iBqjXj2hk8=",
        "ipv6_addr_in": "2a02:6ea0:d406:4::a21f"
      },
      {
        "hostname": "ch-zrh-wg-502",
        "location": "ch-zrh",
        "active": true,
        "owned": false,
        "provider": "M247",
        "stboot": true,
        "ipv4_addr_in": "135.136.18.194",
        "include_in_country": true,
        "weight": 100,
        "public_key": "6rXNS6RlZ9YLZQjaEbfzAmt/6izpuMg/8LYI9jBK+i0=",
        "ipv6_addr_in": "2001:ac8:28:ab::f001",
        "daita": true,
        "shadowsocks_extra_addr_in": [
          "135.136.18.227",
          "135.136.18.228",
          "135.136.18.229",
          "135.136.18.230",
          "135.136.18.231",
          "135.136.18.232",
          "135.136.18.233",
          "135.136.18.234",
          "135.136.18.235",
          "135.136.18.236",
          "135.136.18.237",
          "135.136.18.238",
          "135.136.18.239",
          "135.136.18.240",
          "135.136.18.241",
          "135.136.18.242",
          "135.136.18.243",
          "135.136.18.244",
          "135.136.18.245",
          "135.136.18.246",
          "135.136.18.247",
          "135.136.18.248",
          "135.136.18.249",
          "135.136.18.250",
          "135.136.18.251",
          "135.136.18.252",
          "135.136.18.253",
          "2001:ac8:28:ab::b001",
          "2001:ac8:28:ab::b002",
          "2001:ac8:28:ab::b003",
          "2001:ac8:28:ab::b004",
          "2001:ac8:28:ab::b005",
          "2001:ac8:28:ab::b006",
          "2001:ac8:28:ab::b007",
          "2001:ac8:28:ab::b008",
          "2001:ac8:28:ab::b009",
          "2001:ac8:28:ab::b00a",
          "2001:ac8:28:ab::b00b",
          "2001:ac8:28:ab::b00c",
          "2001:ac8:28:ab::b00d",
          "2001:ac8:28:ab::b00e",
          "2001:ac8:28:ab::b00f",
          "2001:ac8:28:ab::b010",
          "2001:ac8:28:ab::b011",
          "2001:ac8:28:ab::b012",
          "2001:ac8:28:ab::b013",
          "2001:ac8:28:ab::b014",
          "2001:ac8:28:ab::b015",
          "2001:ac8:28:ab::b016",
          "2001:ac8:28:ab::b017",
          "2001:ac8:28:ab::b018",
          "2001:ac8:28:ab::b019",
          "2001:ac8:28:ab::b01a",
          "2001:ac8:28:ab::b01b",
          "2001:ac8:28:ab::b01c",
          "2001:ac8:28:ab::b01d",
          "2001:ac8:28:ab::b01e",
          "2001:ac8:28:ab::b01f"
        ],
        "features": {
          "daita": {},
          "lwo": {},
          "quic": {
            "addr_in": [
              "135.136.18.206",
              "135.136.18.207",
              "135.136.18.208",
              "135.136.18.209",
              "135.136.18.210",
              "135.136.18.211",
              "135.136.18.212",
              "135.136.18.213",
              "135.136.18.214",
              "135.136.18.215",
              "135.136.18.216",
              "135.136.18.217",
              "135.136.18.218",
              "135.136.18.219",
              "135.136.18.220",
              "135.136.18.221",
              "135.136.18.222",
              "135.136.18.223",
              "135.136.18.224",
              "135.136.18.225",
              "135.136.18.226",
              "2001:ac8:28:ab::c001",
              "2001:ac8:28:ab::c002",
              "2001:ac8:28:ab::c003",
              "2001:ac8:28:ab::c004",
              "2001:ac8:28:ab::c005",
              "2001:ac8:28:ab::c006",
              "2001:ac8:28:ab::c007",
              "2001:ac8:28:ab::c008",
              "2001:ac8:28:ab::c009",
              "2001:ac8:28:ab::c00a",
              "2001:ac8:28:ab::c00b",
              "2001:ac8:28:ab::c00c",
              "2001:ac8:28:ab::c00d",
              "2001:ac8:28:ab::c00e",
              "2001:ac8:28:ab::c00f",
              "2001:ac8:28:ab::c010",
              "2001:ac8:28:ab::c011",
              "2001:ac8:28:ab::c012",
              "2001:ac8:28:ab::c013",
              "2001:ac8:28:ab::c014",
              "2001:ac8:28:ab::c015",
              "2001:ac8:28:ab::c016",
              "2001:ac8:28:ab::c017",
              "2001:ac8:28:ab::c018",
              "2001:ac8:28:ab::c019",
              "2001:ac8:28:ab::c01a",
              "2001:ac8:28:ab::c01b",
              "2001:ac8:28:ab::c01c",
              "2001:ac8:28:ab::c01d",
              "2001:ac8:28:ab::c01e",
              "2001:ac8:28:ab::c01f"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "ch-zrh-wg-502.blockerad.eu"
          }
        }
      },
      {
        "hostname": "ch-zrh-wg-503",
        "location": "ch-zrh",
        "active": false,
        "owned": false,
        "provider": "M247",
        "stboot": true,
        "ipv4_addr_in": "77.243.184.2",
        "include_in_country": true,
        "weight": 200,
        "public_key": "ybC4yewkIBN+x530P5iiDdZs3mhY6xHIZOlVHMSobg0=",
        "ipv6_addr_in": "2001:ac8:28:ac::f001",
        "daita": true,
        "shadowsocks_extra_addr_in": [
          "77.243.184.16",
          "77.243.184.17",
          "77.243.184.18",
          "77.243.184.19",
          "77.243.184.20",
          "77.243.184.21",
          "77.243.184.22",
          "77.243.184.23",
          "77.243.184.24",
          "77.243.184.25",
          "77.243.184.26",
          "2001:ac8:28:ac::b001",
          "2001:ac8:28:ac::b002",
          "2001:ac8:28:ac::b003",
          "2001:ac8:28:ac::b004",
          "2001:ac8:28:ac::b005",
          "2001:ac8:28:ac::b006",
          "2001:ac8:28:ac::b007",
          "2001:ac8:28:ac::b008",
          "2001:ac8:28:ac::b009",
          "2001:ac8:28:ac::b00a",
          "2001:ac8:28:ac::b00b",
          "2001:ac8:28:ac::b00c",
          "2001:ac8:28:ac::b00d",
          "2001:ac8:28:ac::b00e",
          "2001:ac8:28:ac::b00f",
          "2001:ac8:28:ac::b010",
          "2001:ac8:28:ac::b011",
          "2001:ac8:28:ac::b012",
          "2001:ac8:28:ac::b013",
          "2001:ac8:28:ac::b014",
          "2001:ac8:28:ac::b015",
          "2001:ac8:28:ac::b016",
          "2001:ac8:28:ac::b017",
          "2001:ac8:28:ac::b018",
          "2001:ac8:28:ac::b019",
          "2001:ac8:28:ac::b01a",
          "2001:ac8:28:ac::b01b",
          "2001:ac8:28:ac::b01c",
          "2001:ac8:28:ac::b01d",
          "2001:ac8:28:ac::b01e",
          "2001:ac8:28:ac::b01f"
        ],
        "features": {
          "daita": {},
          "quic": {
            "addr_in": [
              "77.243.184.5",
              "77.243.184.6",
              "77.243.184.7",
              "77.243.184.8",
              "77.243.184.9",
              "77.243.184.10",
              "77.243.184.11",
              "77.243.184.12",
              "77.243.184.13",
              "77.243.184.14",
              "77.243.184.15",
              "2001:ac8:28:ac::c001",
              "2001:ac8:28:ac::c002",
              "2001:ac8:28:ac::c003",
              "2001:ac8:28:ac::c004",
              "2001:ac8:28:ac::c005",
              "2001:ac8:28:ac::c006",
              "2001:ac8:28:ac::c007",
              "2001:ac8:28:ac::c008",
              "2001:ac8:28:ac::c009",
              "2001:ac8:28:ac::c00a",
              "2001:ac8:28:ac::c00b",
              "2001:ac8:28:ac::c00c",
              "2001:ac8:28:ac::c00d",
              "2001:ac8:28:ac::c00e",
              "2001:ac8:28:ac::c00f",
              "2001:ac8:28:ac::c010",
              "2001:ac8:28:ac::c011",
              "2001:ac8:28:ac::c012",
              "2001:ac8:28:ac::c013",
              "2001:ac8:28:ac::c014",
              "2001:ac8:28:ac::c015",
              "2001:ac8:28:ac::c016",
              "2001:ac8:28:ac::c017",
              "2001:ac8:28:ac::c018",
              "2001:ac8:28:ac::c019",
              "2001:ac8:28:ac::c01a",
              "2001:ac8:28:ac::c01b",
              "2001:ac8:28:ac::c01c",
              "2001:ac8:28:ac::c01d",
              "2001:ac8:28:ac::c01e",
              "2001:ac8:28:ac::c01f"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "ch-zrh-wg-503.blockerad.eu"
          }
        }
      },
      {
        "hostname": "ch-zrh-wg-504",
        "location": "ch-zrh",
        "active": false,
        "owned": false,
        "provider": "M247",
        "stboot": true,
        "ipv4_addr_in": "77.243.184.130",
        "include_in_country": true,
        "weight": 200,
        "public_key": "5ioE7vTw80KVx0S/zYOZonR5ZkR+uiNJogR9Pyqtwzg=",
        "ipv6_addr_in": "2001:ac8:28:ad::f001",
        "daita": true,
        "shadowsocks_extra_addr_in": [
          "77.243.184.144",
          "77.243.184.145",
          "77.243.184.146",
          "77.243.184.147",
          "77.243.184.148",
          "77.243.184.149",
          "77.243.184.150",
          "77.243.184.151",
          "77.243.184.152",
          "77.243.184.153",
          "77.243.184.154",
          "2001:ac8:28:ad::b001",
          "2001:ac8:28:ad::b002",
          "2001:ac8:28:ad::b003",
          "2001:ac8:28:ad::b004",
          "2001:ac8:28:ad::b005",
          "2001:ac8:28:ad::b006",
          "2001:ac8:28:ad::b007",
          "2001:ac8:28:ad::b008",
          "2001:ac8:28:ad::b009",
          "2001:ac8:28:ad::b00a",
          "2001:ac8:28:ad::b00b",
          "2001:ac8:28:ad::b00c",
          "2001:ac8:28:ad::b00d",
          "2001:ac8:28:ad::b00e",
          "2001:ac8:28:ad::b00f",
          "2001:ac8:28:ad::b010",
          "2001:ac8:28:ad::b011",
          "2001:ac8:28:ad::b012",
          "2001:ac8:28:ad::b013",
          "2001:ac8:28:ad::b014",
          "2001:ac8:28:ad::b015",
          "2001:ac8:28:ad::b016",
          "2001:ac8:28:ad::b017",
          "2001:ac8:28:ad::b018",
          "2001:ac8:28:ad::b019",
          "2001:ac8:28:ad::b01a",
          "2001:ac8:28:ad::b01b",
          "2001:ac8:28:ad::b01c",
          "2001:ac8:28:ad::b01d",
          "2001:ac8:28:ad::b01e",
          "2001:ac8:28:ad::b01f"
        ],
        "features": {
          "daita": {},
          "quic": {
            "addr_in": [
              "77.243.184.133",
              "77.243.184.134",
              "77.243.184.135",
              "77.243.184.136",
              "77.243.184.137",
              "77.243.184.138",
              "77.243.184.139",
              "77.243.184.140",
              "77.243.184.141",
              "77.243.184.142",
              "77.243.184.143",
              "2001:ac8:28:ad::c001",
              "2001:ac8:28:ad::c002",
              "2001:ac8:28:ad::c003",
              "2001:ac8:28:ad::c004",
              "2001:ac8:28:ad::c005",
              "2001:ac8:28:ad::c006",
              "2001:ac8:28:ad::c007",
              "2001:ac8:28:ad::c008",
              "2001:ac8:28:ad::c009",
              "2001:ac8:28:ad::c00a",
              "2001:ac8:28:ad::c00b",
              "2001:ac8:28:ad::c00c",
              "2001:ac8:28:ad::c00d",
              "2001:ac8:28:ad::c00e",
              "2001:ac8:28:ad::c00f",
              "2001:ac8:28:ad::c010",
              "2001:ac8:28:ad::c011",
              "2001:ac8:28:ad::c012",
              "2001:ac8:28:ad::c013",
              "2001:ac8:28:ad::c014",
              "2001:ac8:28:ad::c015",
              "2001:ac8:28:ad::c016",
              "2001:ac8:28:ad::c017",
              "2001:ac8:28:ad::c018",
              "2001:ac8:28:ad::c019",
              "2001:ac8:28:ad::c01a",
              "2001:ac8:28:ad::c01b",
              "2001:ac8:28:ad::c01c",
              "2001:ac8:28:ad::c01d",
              "2001:ac8:28:ad::c01e",
              "2001:ac8:28:ad::c01f"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "ch-zrh-wg-504.blockerad.eu"
          }
        }
      },
      {
        "hostname": "cl-scl-wg-001",
        "location": "cl-scl",
        "active": true,
        "owned": false,
        "provider": "DataPacket",
        "stboot": true,
        "ipv4_addr_in": "149.88.104.2",
        "include_in_country": true,
        "weight": 100,
        "public_key": "03qeK7CSn6wcMzfqilmVt6Tf81VZIPWnSG04euSkyxM=",
        "ipv6_addr_in": "2a02:6ea0:fc02:2::f001"
      },
      {
        "hostname": "cl-scl-wg-002",
        "location": "cl-scl",
        "active": true,
        "owned": false,
        "provider": "DataPacket",
        "stboot": true,
        "ipv4_addr_in": "149.88.104.15",
        "include_in_country": true,
        "weight": 100,
        "public_key": "rn9O+cXj0WQgZAkGCoYvvWgzaB5GcOaVfke3WKsp1Ro=",
        "ipv6_addr_in": "2a02:6ea0:fc02:3::f101"
      },
      {
        "hostname": "co-bog-wg-001",
        "location": "co-bog",
        "active": true,
        "owned": false,
        "provider": "DataPacket",
        "stboot": true,
        "ipv4_addr_in": "154.47.16.34",
        "include_in_country": true,
        "weight": 100,
        "public_key": "iaMa84nCHK+v4TnQH4h2rxkqwwxemORXM12VbJDRZSU=",
        "ipv6_addr_in": "2a02:6ea0:f101:1::f001",
        "daita": true,
        "features": {
          "daita": {},
          "lwo": {}
        }
      },
      {
        "hostname": "co-bog-wg-002",
        "location": "co-bog",
        "active": true,
        "owned": false,
        "provider": "DataPacket",
        "stboot": true,
        "ipv4_addr_in": "154.47.16.47",
        "include_in_country": true,
        "weight": 100,
        "public_key": "IZDwbG9C/NrOOGVUrn+fDaPr8ZwD/yhvST7XWGk1ln8=",
        "ipv6_addr_in": "2a02:6ea0:f101:2::f001",
        "features": {
          "lwo": {}
        }
      },
      {
        "hostname": "cy-nic-wg-001",
        "location": "cy-nic",
        "active": true,
        "owned": false,
        "provider": "HostRoyale",
        "stboot": true,
        "ipv4_addr_in": "195.47.194.131",
        "include_in_country": true,
        "weight": 100,
        "public_key": "Ae9YcQjcQT+W8MU0EhKXx6KPWo6ticS1NI91e+Zy5GA=",
        "ipv6_addr_in": "2a06:3040:f:601::f001",
        "shadowsocks_extra_addr_in": [
          "195.47.194.133"
        ]
      },
      {
        "hostname": "cy-nic-wg-002",
        "location": "cy-nic",
        "active": true,
        "owned": false,
        "provider": "HostRoyale",
        "stboot": true,
        "ipv4_addr_in": "195.47.194.161",
        "include_in_country": true,
        "weight": 100,
        "public_key": "LOd1SY9YCHGiJUVT+XdYRdORu6ZMw4CqOKQBW2ElLg8=",
        "ipv6_addr_in": "2a06:3040:f:601::f101",
        "shadowsocks_extra_addr_in": [
          "195.47.194.163"
        ]
      },
      {
        "hostname": "cz-prg-wg-101",
        "location": "cz-prg",
        "active": true,
        "owned": false,
        "provider": "M247",
        "stboot": true,
        "ipv4_addr_in": "146.70.129.98",
        "include_in_country": true,
        "weight": 100,
        "public_key": "tWVga+pS/Ztrbx/L/PBlaWPGhkI3PCPBzbQlCeXWqn8=",
        "ipv6_addr_in": "2001:ac8:33:c::a01f",
        "features": {
          "lwo": {}
        }
      },
      {
        "hostname": "cz-prg-wg-102",
        "location": "cz-prg",
        "active": true,
        "owned": false,
        "provider": "M247",
        "stboot": true,
        "ipv4_addr_in": "146.70.129.130",
        "include_in_country": true,
        "weight": 100,
        "public_key": "cRCJ0vULwKRbTfzuo9W+fIt0fJGQE7DLvojIiURIpiI=",
        "ipv6_addr_in": "2001:ac8:33:d::a02f",
        "features": {
          "lwo": {},
          "quic": {
            "addr_in": [
              "146.70.129.158"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "cz-prg-wg-102.blockerad.eu"
          }
        }
      },
      {
        "hostname": "cz-prg-wg-201",
        "location": "cz-prg",
        "active": true,
        "owned": false,
        "provider": "DataPacket",
        "stboot": true,
        "ipv4_addr_in": "178.249.209.162",
        "include_in_country": true,
        "weight": 100,
        "public_key": "5FZW+fNA2iVBSY99HFl+KjGc9AFVNE+UFAedLNhu8lc=",
        "ipv6_addr_in": "2a02:6ea0:c201:1::f001"
      },
      {
        "hostname": "cz-prg-wg-202",
        "location": "cz-prg",
        "active": true,
        "owned": false,
        "provider": "DataPacket",
        "stboot": true,
        "ipv4_addr_in": "178.249.209.175",
        "include_in_country": true,
        "weight": 100,
        "public_key": "ReGrGPKDHri64D7qeXmgcLzjsTJ0B/yM7eekFz1P/34=",
        "ipv6_addr_in": "2a02:6ea0:c201:1::f101"
      },
      {
        "hostname": "de-ber-wg-001",
        "location": "de-ber",
        "active": true,
        "owned": true,
        "provider": "31173",
        "stboot": true,
        "ipv4_addr_in": "193.32.248.66",
        "include_in_country": true,
        "weight": 50,
        "public_key": "0qSP0VxoIhEhRK+fAHVvmfRdjPs2DmmpOCNLFP/7cGw=",
        "ipv6_addr_in": "2a03:1b20:b:f011::a01f",
        "shadowsocks_extra_addr_in": [
          "193.32.248.86",
          "151.241.171.20",
          "151.241.171.21",
          "151.241.171.22",
          "151.241.171.23",
          "151.241.171.24",
          "151.241.171.25",
          "151.241.171.26",
          "151.241.171.27",
          "151.241.171.28",
          "151.241.171.29",
          "2a03:1b20:b:f011::b002",
          "2a03:1b20:b:f011::b003",
          "2a03:1b20:b:f011::b004",
          "2a03:1b20:b:f011::b005",
          "2a03:1b20:b:f011::b006",
          "2a03:1b20:b:f011::b007",
          "2a03:1b20:b:f011::b008",
          "2a03:1b20:b:f011::b009",
          "2a03:1b20:b:f011::b00a",
          "2a03:1b20:b:f011::b00b",
          "2a03:1b20:b:f011::b00c",
          "2a03:1b20:b:f011::b00d",
          "2a03:1b20:b:f011::b00e",
          "2a03:1b20:b:f011::b00f",
          "2a03:1b20:b:f011::b010",
          "2a03:1b20:b:f011::b011",
          "2a03:1b20:b:f011::b012",
          "2a03:1b20:b:f011::b013",
          "2a03:1b20:b:f011::b014",
          "2a03:1b20:b:f011::b015",
          "2a03:1b20:b:f011::b016",
          "2a03:1b20:b:f011::b017",
          "2a03:1b20:b:f011::b018",
          "2a03:1b20:b:f011::b019",
          "2a03:1b20:b:f011::b01a",
          "2a03:1b20:b:f011::b01b",
          "2a03:1b20:b:f011::b01c",
          "2a03:1b20:b:f011::b01d",
          "2a03:1b20:b:f011::b01e",
          "2a03:1b20:b:f011::b01f"
        ],
        "features": {
          "lwo": {},
          "quic": {
            "addr_in": [
              "193.32.248.87",
              "151.241.171.10",
              "151.241.171.11",
              "151.241.171.12",
              "151.241.171.13",
              "151.241.171.14",
              "151.241.171.15",
              "151.241.171.16",
              "151.241.171.17",
              "151.241.171.18",
              "151.241.171.19",
              "2a03:1b20:b:f011::c002",
              "2a03:1b20:b:f011::c003",
              "2a03:1b20:b:f011::c004",
              "2a03:1b20:b:f011::c005",
              "2a03:1b20:b:f011::c006",
              "2a03:1b20:b:f011::c007",
              "2a03:1b20:b:f011::c008",
              "2a03:1b20:b:f011::c009",
              "2a03:1b20:b:f011::c00a",
              "2a03:1b20:b:f011::c00b",
              "2a03:1b20:b:f011::c00c",
              "2a03:1b20:b:f011::c00d",
              "2a03:1b20:b:f011::c00e",
              "2a03:1b20:b:f011::c00f",
              "2a03:1b20:b:f011::c010",
              "2a03:1b20:b:f011::c011",
              "2a03:1b20:b:f011::c012",
              "2a03:1b20:b:f011::c013",
              "2a03:1b20:b:f011::c014",
              "2a03:1b20:b:f011::c015",
              "2a03:1b20:b:f011::c016",
              "2a03:1b20:b:f011::c017",
              "2a03:1b20:b:f011::c018",
              "2a03:1b20:b:f011::c019",
              "2a03:1b20:b:f011::c01a",
              "2a03:1b20:b:f011::c01b",
              "2a03:1b20:b:f011::c01c",
              "2a03:1b20:b:f011::c01d",
              "2a03:1b20:b:f011::c01e",
              "2a03:1b20:b:f011::c01f"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "de-ber-wg-001.blockerad.eu"
          }
        }
      },
      {
        "hostname": "de-ber-wg-002",
        "location": "de-ber",
        "active": true,
        "owned": true,
        "provider": "31173",
        "stboot": true,
        "ipv4_addr_in": "193.32.248.67",
        "include_in_country": true,
        "weight": 50,
        "public_key": "8ov1Ws0ut3ixWDh9Chp7/WLVn9qC6/WVHtcBcuWBlgo=",
        "ipv6_addr_in": "2a03:1b20:b:f011::a02f",
        "shadowsocks_extra_addr_in": [
          "193.32.248.88",
          "151.241.171.50",
          "151.241.171.51",
          "151.241.171.52",
          "151.241.171.53",
          "151.241.171.54",
          "151.241.171.55",
          "151.241.171.56",
          "151.241.171.57",
          "151.241.171.58",
          "151.241.171.59",
          "2a03:1b20:b:f011::b102",
          "2a03:1b20:b:f011::b103",
          "2a03:1b20:b:f011::b104",
          "2a03:1b20:b:f011::b105",
          "2a03:1b20:b:f011::b106",
          "2a03:1b20:b:f011::b107",
          "2a03:1b20:b:f011::b108",
          "2a03:1b20:b:f011::b109",
          "2a03:1b20:b:f011::b10a",
          "2a03:1b20:b:f011::b10b",
          "2a03:1b20:b:f011::b10c",
          "2a03:1b20:b:f011::b10d",
          "2a03:1b20:b:f011::b10e",
          "2a03:1b20:b:f011::b10f",
          "2a03:1b20:b:f011::b110",
          "2a03:1b20:b:f011::b111",
          "2a03:1b20:b:f011::b112",
          "2a03:1b20:b:f011::b113",
          "2a03:1b20:b:f011::b114",
          "2a03:1b20:b:f011::b115",
          "2a03:1b20:b:f011::b116",
          "2a03:1b20:b:f011::b117",
          "2a03:1b20:b:f011::b118",
          "2a03:1b20:b:f011::b119",
          "2a03:1b20:b:f011::b11a",
          "2a03:1b20:b:f011::b11b",
          "2a03:1b20:b:f011::b11c",
          "2a03:1b20:b:f011::b11d",
          "2a03:1b20:b:f011::b11e",
          "2a03:1b20:b:f011::b11f"
        ],
        "features": {
          "lwo": {},
          "quic": {
            "addr_in": [
              "193.32.248.89",
              "151.241.171.40",
              "151.241.171.41",
              "151.241.171.42",
              "151.241.171.43",
              "151.241.171.44",
              "151.241.171.45",
              "151.241.171.46",
              "151.241.171.47",
              "151.241.171.48",
              "151.241.171.49",
              "2a03:1b20:b:f011::c102",
              "2a03:1b20:b:f011::c103",
              "2a03:1b20:b:f011::c104",
              "2a03:1b20:b:f011::c105",
              "2a03:1b20:b:f011::c106",
              "2a03:1b20:b:f011::c107",
              "2a03:1b20:b:f011::c108",
              "2a03:1b20:b:f011::c109",
              "2a03:1b20:b:f011::c10a",
              "2a03:1b20:b:f011::c10b",
              "2a03:1b20:b:f011::c10c",
              "2a03:1b20:b:f011::c10d",
              "2a03:1b20:b:f011::c10e",
              "2a03:1b20:b:f011::c10f",
              "2a03:1b20:b:f011::c110",
              "2a03:1b20:b:f011::c111",
              "2a03:1b20:b:f011::c112",
              "2a03:1b20:b:f011::c113",
              "2a03:1b20:b:f011::c114",
              "2a03:1b20:b:f011::c115",
              "2a03:1b20:b:f011::c116",
              "2a03:1b20:b:f011::c117",
              "2a03:1b20:b:f011::c118",
              "2a03:1b20:b:f011::c119",
              "2a03:1b20:b:f011::c11a",
              "2a03:1b20:b:f011::c11b",
              "2a03:1b20:b:f011::c11c",
              "2a03:1b20:b:f011::c11d",
              "2a03:1b20:b:f011::c11e",
              "2a03:1b20:b:f011::c11f"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "de-ber-wg-002.blockerad.eu"
          }
        }
      },
      {
        "hostname": "de-ber-wg-003",
        "location": "de-ber",
        "active": true,
        "owned": true,
        "provider": "31173",
        "stboot": true,
        "ipv4_addr_in": "193.32.248.68",
        "include_in_country": true,
        "weight": 50,
        "public_key": "USrMatdHiCL5AKdVMpHuYgWuMiK/GHPwRB3Xx00FhU0=",
        "ipv6_addr_in": "2a03:1b20:b:f011::a03f",
        "shadowsocks_extra_addr_in": [
          "193.32.248.90",
          "151.241.171.80",
          "151.241.171.81",
          "151.241.171.82",
          "151.241.171.83",
          "151.241.171.84",
          "151.241.171.85",
          "151.241.171.86",
          "151.241.171.87",
          "151.241.171.88",
          "151.241.171.89",
          "2a03:1b20:b:f011::b202",
          "2a03:1b20:b:f011::b203",
          "2a03:1b20:b:f011::b204",
          "2a03:1b20:b:f011::b205",
          "2a03:1b20:b:f011::b206",
          "2a03:1b20:b:f011::b207",
          "2a03:1b20:b:f011::b208",
          "2a03:1b20:b:f011::b209",
          "2a03:1b20:b:f011::b20a",
          "2a03:1b20:b:f011::b20b",
          "2a03:1b20:b:f011::b20c",
          "2a03:1b20:b:f011::b20d",
          "2a03:1b20:b:f011::b20e",
          "2a03:1b20:b:f011::b20f",
          "2a03:1b20:b:f011::b210",
          "2a03:1b20:b:f011::b211",
          "2a03:1b20:b:f011::b212",
          "2a03:1b20:b:f011::b213",
          "2a03:1b20:b:f011::b214",
          "2a03:1b20:b:f011::b215",
          "2a03:1b20:b:f011::b216",
          "2a03:1b20:b:f011::b217",
          "2a03:1b20:b:f011::b218",
          "2a03:1b20:b:f011::b219",
          "2a03:1b20:b:f011::b21a",
          "2a03:1b20:b:f011::b21b",
          "2a03:1b20:b:f011::b21c",
          "2a03:1b20:b:f011::b21d",
          "2a03:1b20:b:f011::b21e",
          "2a03:1b20:b:f011::b21f"
        ],
        "features": {
          "quic": {
            "addr_in": [
              "193.32.248.91",
              "151.241.171.70",
              "151.241.171.71",
              "151.241.171.72",
              "151.241.171.73",
              "151.241.171.74",
              "151.241.171.75",
              "151.241.171.76",
              "151.241.171.77",
              "151.241.171.78",
              "151.241.171.79",
              "2a03:1b20:b:f011::c202",
              "2a03:1b20:b:f011::c203",
              "2a03:1b20:b:f011::c204",
              "2a03:1b20:b:f011::c205",
              "2a03:1b20:b:f011::c206",
              "2a03:1b20:b:f011::c207",
              "2a03:1b20:b:f011::c208",
              "2a03:1b20:b:f011::c209",
              "2a03:1b20:b:f011::c20a",
              "2a03:1b20:b:f011::c20b",
              "2a03:1b20:b:f011::c20c",
              "2a03:1b20:b:f011::c20d",
              "2a03:1b20:b:f011::c20e",
              "2a03:1b20:b:f011::c20f",
              "2a03:1b20:b:f011::c210",
              "2a03:1b20:b:f011::c211",
              "2a03:1b20:b:f011::c212",
              "2a03:1b20:b:f011::c213",
              "2a03:1b20:b:f011::c214",
              "2a03:1b20:b:f011::c215",
              "2a03:1b20:b:f011::c216",
              "2a03:1b20:b:f011::c217",
              "2a03:1b20:b:f011::c218",
              "2a03:1b20:b:f011::c219",
              "2a03:1b20:b:f011::c21a",
              "2a03:1b20:b:f011::c21b",
              "2a03:1b20:b:f011::c21c",
              "2a03:1b20:b:f011::c21d",
              "2a03:1b20:b:f011::c21e",
              "2a03:1b20:b:f011::c21f"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "de-ber-wg-003.blockerad.eu"
          }
        }
      },
      {
        "hostname": "de-ber-wg-004",
        "location": "de-ber",
        "active": true,
        "owned": true,
        "provider": "31173",
        "stboot": true,
        "ipv4_addr_in": "193.32.248.69",
        "include_in_country": true,
        "weight": 50,
        "public_key": "6PchzRRxzeeHdNLyn3Nz0gmN7pUyjoZMpKmKzJRL4GM=",
        "ipv6_addr_in": "2a03:1b20:b:f011::f301",
        "shadowsocks_extra_addr_in": [
          "193.32.248.92",
          "151.241.171.110",
          "151.241.171.111",
          "151.241.171.112",
          "151.241.171.113",
          "151.241.171.114",
          "151.241.171.115",
          "151.241.171.116",
          "151.241.171.117",
          "151.241.171.118",
          "151.241.171.119",
          "2a03:1b20:b:f011::b302",
          "2a03:1b20:b:f011::b303",
          "2a03:1b20:b:f011::b304",
          "2a03:1b20:b:f011::b305",
          "2a03:1b20:b:f011::b306",
          "2a03:1b20:b:f011::b307",
          "2a03:1b20:b:f011::b308",
          "2a03:1b20:b:f011::b309",
          "2a03:1b20:b:f011::b30a",
          "2a03:1b20:b:f011::b30b",
          "2a03:1b20:b:f011::b30c",
          "2a03:1b20:b:f011::b30d",
          "2a03:1b20:b:f011::b30e",
          "2a03:1b20:b:f011::b30f",
          "2a03:1b20:b:f011::b310",
          "2a03:1b20:b:f011::b311",
          "2a03:1b20:b:f011::b312",
          "2a03:1b20:b:f011::b313",
          "2a03:1b20:b:f011::b314",
          "2a03:1b20:b:f011::b315",
          "2a03:1b20:b:f011::b316",
          "2a03:1b20:b:f011::b317",
          "2a03:1b20:b:f011::b318",
          "2a03:1b20:b:f011::b319",
          "2a03:1b20:b:f011::b31a",
          "2a03:1b20:b:f011::b31b",
          "2a03:1b20:b:f011::b31c",
          "2a03:1b20:b:f011::b31d",
          "2a03:1b20:b:f011::b31e",
          "2a03:1b20:b:f011::b31f"
        ],
        "features": {
          "quic": {
            "addr_in": [
              "193.32.248.93",
              "151.241.171.100",
              "151.241.171.101",
              "151.241.171.102",
              "151.241.171.103",
              "151.241.171.104",
              "151.241.171.105",
              "151.241.171.106",
              "151.241.171.107",
              "151.241.171.108",
              "151.241.171.109",
              "2a03:1b20:b:f011::c302",
              "2a03:1b20:b:f011::c303",
              "2a03:1b20:b:f011::c304",
              "2a03:1b20:b:f011::c305",
              "2a03:1b20:b:f011::c306",
              "2a03:1b20:b:f011::c307",
              "2a03:1b20:b:f011::c308",
              "2a03:1b20:b:f011::c309",
              "2a03:1b20:b:f011::c30a",
              "2a03:1b20:b:f011::c30b",
              "2a03:1b20:b:f011::c30c",
              "2a03:1b20:b:f011::c30d",
              "2a03:1b20:b:f011::c30e",
              "2a03:1b20:b:f011::c30f",
              "2a03:1b20:b:f011::c310",
              "2a03:1b20:b:f011::c311",
              "2a03:1b20:b:f011::c312",
              "2a03:1b20:b:f011::c313",
              "2a03:1b20:b:f011::c314",
              "2a03:1b20:b:f011::c315",
              "2a03:1b20:b:f011::c316",
              "2a03:1b20:b:f011::c317",
              "2a03:1b20:b:f011::c318",
              "2a03:1b20:b:f011::c319",
              "2a03:1b20:b:f011::c31a",
              "2a03:1b20:b:f011::c31b",
              "2a03:1b20:b:f011::c31c",
              "2a03:1b20:b:f011::c31d",
              "2a03:1b20:b:f011::c31e",
              "2a03:1b20:b:f011::c31f"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "de-ber-wg-004.blockerad.eu"
          }
        }
      },
      {
        "hostname": "de-ber-wg-005",
        "location": "de-ber",
        "active": true,
        "owned": true,
        "provider": "31173",
        "stboot": true,
        "ipv4_addr_in": "193.32.248.70",
        "include_in_country": true,
        "weight": 50,
        "public_key": "I4Y7e8LrtBC/7DLpUgRd5k+IZk+whOFVAZgbSivoiBI=",
        "ipv6_addr_in": "2a03:1b20:b:f011::f401",
        "shadowsocks_extra_addr_in": [
          "193.32.248.94",
          "151.241.171.140",
          "151.241.171.141",
          "151.241.171.142",
          "151.241.171.143",
          "151.241.171.144",
          "151.241.171.145",
          "151.241.171.146",
          "151.241.171.147",
          "151.241.171.148",
          "151.241.171.149",
          "2a03:1b20:b:f011::b402",
          "2a03:1b20:b:f011::b403",
          "2a03:1b20:b:f011::b404",
          "2a03:1b20:b:f011::b405",
          "2a03:1b20:b:f011::b406",
          "2a03:1b20:b:f011::b407",
          "2a03:1b20:b:f011::b408",
          "2a03:1b20:b:f011::b409",
          "2a03:1b20:b:f011::b40a",
          "2a03:1b20:b:f011::b40b",
          "2a03:1b20:b:f011::b40c",
          "2a03:1b20:b:f011::b40d",
          "2a03:1b20:b:f011::b40e",
          "2a03:1b20:b:f011::b40f",
          "2a03:1b20:b:f011::b410",
          "2a03:1b20:b:f011::b411",
          "2a03:1b20:b:f011::b412",
          "2a03:1b20:b:f011::b413",
          "2a03:1b20:b:f011::b414",
          "2a03:1b20:b:f011::b415",
          "2a03:1b20:b:f011::b416",
          "2a03:1b20:b:f011::b417",
          "2a03:1b20:b:f011::b418",
          "2a03:1b20:b:f011::b419",
          "2a03:1b20:b:f011::b41a",
          "2a03:1b20:b:f011::b41b",
          "2a03:1b20:b:f011::b41c",
          "2a03:1b20:b:f011::b41d",
          "2a03:1b20:b:f011::b41e",
          "2a03:1b20:b:f011::b41f"
        ],
        "features": {
          "quic": {
            "addr_in": [
              "193.32.248.95",
              "151.241.171.130",
              "151.241.171.131",
              "151.241.171.132",
              "151.241.171.133",
              "151.241.171.134",
              "151.241.171.135",
              "151.241.171.136",
              "151.241.171.137",
              "151.241.171.138",
              "151.241.171.139",
              "2a03:1b20:b:f011::c402",
              "2a03:1b20:b:f011::c403",
              "2a03:1b20:b:f011::c404",
              "2a03:1b20:b:f011::c405",
              "2a03:1b20:b:f011::c406",
              "2a03:1b20:b:f011::c407",
              "2a03:1b20:b:f011::c408",
              "2a03:1b20:b:f011::c409",
              "2a03:1b20:b:f011::c40a",
              "2a03:1b20:b:f011::c40b",
              "2a03:1b20:b:f011::c40c",
              "2a03:1b20:b:f011::c40d",
              "2a03:1b20:b:f011::c40e",
              "2a03:1b20:b:f011::c40f",
              "2a03:1b20:b:f011::c410",
              "2a03:1b20:b:f011::c411",
              "2a03:1b20:b:f011::c412",
              "2a03:1b20:b:f011::c413",
              "2a03:1b20:b:f011::c414",
              "2a03:1b20:b:f011::c415",
              "2a03:1b20:b:f011::c416",
              "2a03:1b20:b:f011::c417",
              "2a03:1b20:b:f011::c418",
              "2a03:1b20:b:f011::c419",
              "2a03:1b20:b:f011::c41a",
              "2a03:1b20:b:f011::c41b",
              "2a03:1b20:b:f011::c41c",
              "2a03:1b20:b:f011::c41d",
              "2a03:1b20:b:f011::c41e",
              "2a03:1b20:b:f011::c41f"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "de-ber-wg-005.blockerad.eu"
          }
        }
      },
      {
        "hostname": "de-ber-wg-006",
        "location": "de-ber",
        "active": true,
        "owned": true,
        "provider": "31173",
        "stboot": true,
        "ipv4_addr_in": "193.32.248.71",
        "include_in_country": true,
        "weight": 50,
        "public_key": "eprzkkkSbXCANngQDo305DIAvkKAnZaN71IpTNaOoTk=",
        "ipv6_addr_in": "2a03:1b20:b:f011::a06f",
        "shadowsocks_extra_addr_in": [
          "193.32.248.96",
          "151.241.171.170",
          "151.241.171.171",
          "151.241.171.172",
          "151.241.171.173",
          "151.241.171.174",
          "151.241.171.175",
          "151.241.171.176",
          "151.241.171.177",
          "151.241.171.178",
          "151.241.171.179",
          "2a03:1b20:b:f011::b502",
          "2a03:1b20:b:f011::b503",
          "2a03:1b20:b:f011::b504",
          "2a03:1b20:b:f011::b505",
          "2a03:1b20:b:f011::b506",
          "2a03:1b20:b:f011::b507",
          "2a03:1b20:b:f011::b508",
          "2a03:1b20:b:f011::b509",
          "2a03:1b20:b:f011::b50a",
          "2a03:1b20:b:f011::b50b",
          "2a03:1b20:b:f011::b50c",
          "2a03:1b20:b:f011::b50d",
          "2a03:1b20:b:f011::b50e",
          "2a03:1b20:b:f011::b50f",
          "2a03:1b20:b:f011::b510",
          "2a03:1b20:b:f011::b511",
          "2a03:1b20:b:f011::b512",
          "2a03:1b20:b:f011::b513",
          "2a03:1b20:b:f011::b514",
          "2a03:1b20:b:f011::b515",
          "2a03:1b20:b:f011::b516",
          "2a03:1b20:b:f011::b517",
          "2a03:1b20:b:f011::b518",
          "2a03:1b20:b:f011::b519",
          "2a03:1b20:b:f011::b51a",
          "2a03:1b20:b:f011::b51b",
          "2a03:1b20:b:f011::b51c",
          "2a03:1b20:b:f011::b51d",
          "2a03:1b20:b:f011::b51e",
          "2a03:1b20:b:f011::b51f"
        ],
        "features": {
          "quic": {
            "addr_in": [
              "193.32.248.97",
              "151.241.171.160",
              "151.241.171.161",
              "151.241.171.162",
              "151.241.171.163",
              "151.241.171.164",
              "151.241.171.165",
              "151.241.171.166",
              "151.241.171.167",
              "151.241.171.168",
              "151.241.171.169",
              "2a03:1b20:b:f011::c502",
              "2a03:1b20:b:f011::c503",
              "2a03:1b20:b:f011::c504",
              "2a03:1b20:b:f011::c505",
              "2a03:1b20:b:f011::c506",
              "2a03:1b20:b:f011::c507",
              "2a03:1b20:b:f011::c508",
              "2a03:1b20:b:f011::c509",
              "2a03:1b20:b:f011::c50a",
              "2a03:1b20:b:f011::c50b",
              "2a03:1b20:b:f011::c50c",
              "2a03:1b20:b:f011::c50d",
              "2a03:1b20:b:f011::c50e",
              "2a03:1b20:b:f011::c50f",
              "2a03:1b20:b:f011::c510",
              "2a03:1b20:b:f011::c511",
              "2a03:1b20:b:f011::c512",
              "2a03:1b20:b:f011::c513",
              "2a03:1b20:b:f011::c514",
              "2a03:1b20:b:f011::c515",
              "2a03:1b20:b:f011::c516",
              "2a03:1b20:b:f011::c517",
              "2a03:1b20:b:f011::c518",
              "2a03:1b20:b:f011::c519",
              "2a03:1b20:b:f011::c51a",
              "2a03:1b20:b:f011::c51b",
              "2a03:1b20:b:f011::c51c",
              "2a03:1b20:b:f011::c51d",
              "2a03:1b20:b:f011::c51e",
              "2a03:1b20:b:f011::c51f"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "de-ber-wg-006.blockerad.eu"
          }
        }
      },
      {
        "hostname": "de-ber-wg-007",
        "location": "de-ber",
        "active": true,
        "owned": true,
        "provider": "31173",
        "stboot": true,
        "ipv4_addr_in": "193.32.248.75",
        "include_in_country": true,
        "weight": 50,
        "public_key": "/ejdxiEsmYbeXXCN6UzvzJ0U/mLuB6baIfQRYKYHWzU=",
        "ipv6_addr_in": "2a03:1b20:b:f011::f701",
        "shadowsocks_extra_addr_in": [
          "193.32.248.98",
          "151.241.171.190",
          "151.241.171.191",
          "151.241.171.192",
          "151.241.171.193",
          "151.241.171.194",
          "151.241.171.195",
          "151.241.171.196",
          "151.241.171.197",
          "151.241.171.198",
          "151.241.171.199",
          "2a03:1b20:b:f011::b702",
          "2a03:1b20:b:f011::b703",
          "2a03:1b20:b:f011::b704",
          "2a03:1b20:b:f011::b705",
          "2a03:1b20:b:f011::b706",
          "2a03:1b20:b:f011::b707",
          "2a03:1b20:b:f011::b708",
          "2a03:1b20:b:f011::b709",
          "2a03:1b20:b:f011::b70a",
          "2a03:1b20:b:f011::b70b",
          "2a03:1b20:b:f011::b70c",
          "2a03:1b20:b:f011::b70d",
          "2a03:1b20:b:f011::b70e",
          "2a03:1b20:b:f011::b70f",
          "2a03:1b20:b:f011::b710",
          "2a03:1b20:b:f011::b711",
          "2a03:1b20:b:f011::b712",
          "2a03:1b20:b:f011::b713",
          "2a03:1b20:b:f011::b714",
          "2a03:1b20:b:f011::b715",
          "2a03:1b20:b:f011::b716",
          "2a03:1b20:b:f011::b717",
          "2a03:1b20:b:f011::b718",
          "2a03:1b20:b:f011::b719",
          "2a03:1b20:b:f011::b71a",
          "2a03:1b20:b:f011::b71b",
          "2a03:1b20:b:f011::b71c",
          "2a03:1b20:b:f011::b71d",
          "2a03:1b20:b:f011::b71e",
          "2a03:1b20:b:f011::b71f"
        ],
        "features": {
          "lwo": {},
          "quic": {
            "addr_in": [
              "193.32.248.99",
              "151.241.171.180",
              "151.241.171.181",
              "151.241.171.182",
              "151.241.171.183",
              "151.241.171.184",
              "151.241.171.185",
              "151.241.171.186",
              "151.241.171.187",
              "151.241.171.188",
              "151.241.171.189",
              "2a03:1b20:b:f011::c702",
              "2a03:1b20:b:f011::c703",
              "2a03:1b20:b:f011::c704",
              "2a03:1b20:b:f011::c705",
              "2a03:1b20:b:f011::c706",
              "2a03:1b20:b:f011::c707",
              "2a03:1b20:b:f011::c708",
              "2a03:1b20:b:f011::c709",
              "2a03:1b20:b:f011::c70a",
              "2a03:1b20:b:f011::c70b",
              "2a03:1b20:b:f011::c70c",
              "2a03:1b20:b:f011::c70d",
              "2a03:1b20:b:f011::c70e",
              "2a03:1b20:b:f011::c70f",
              "2a03:1b20:b:f011::c710",
              "2a03:1b20:b:f011::c711",
              "2a03:1b20:b:f011::c712",
              "2a03:1b20:b:f011::c713",
              "2a03:1b20:b:f011::c714",
              "2a03:1b20:b:f011::c715",
              "2a03:1b20:b:f011::c716",
              "2a03:1b20:b:f011::c717",
              "2a03:1b20:b:f011::c718",
              "2a03:1b20:b:f011::c719",
              "2a03:1b20:b:f011::c71a",
              "2a03:1b20:b:f011::c71b",
              "2a03:1b20:b:f011::c71c",
              "2a03:1b20:b:f011::c71d",
              "2a03:1b20:b:f011::c71e",
              "2a03:1b20:b:f011::c71f"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "de-ber-wg-007.blockerad.eu"
          }
        }
      },
      {
        "hostname": "de-ber-wg-008",
        "location": "de-ber",
        "active": true,
        "owned": true,
        "provider": "31173",
        "stboot": true,
        "ipv4_addr_in": "193.32.248.74",
        "include_in_country": true,
        "weight": 50,
        "public_key": "qwXs9gwhwqWgRtLjPiZ+zMphZJA3OStsn/aXcCAd5m0=",
        "ipv6_addr_in": "2a03:1b20:b:f011::f801",
        "shadowsocks_extra_addr_in": [
          "193.32.248.233",
          "151.241.171.220",
          "151.241.171.221",
          "151.241.171.222",
          "151.241.171.223",
          "151.241.171.224",
          "151.241.171.225",
          "151.241.171.226",
          "151.241.171.227",
          "151.241.171.228",
          "151.241.171.229",
          "2a03:1b20:b:f011::b802",
          "2a03:1b20:b:f011::b803",
          "2a03:1b20:b:f011::b804",
          "2a03:1b20:b:f011::b805",
          "2a03:1b20:b:f011::b806",
          "2a03:1b20:b:f011::b807",
          "2a03:1b20:b:f011::b808",
          "2a03:1b20:b:f011::b809",
          "2a03:1b20:b:f011::b80a",
          "2a03:1b20:b:f011::b80b",
          "2a03:1b20:b:f011::b80c",
          "2a03:1b20:b:f011::b80d",
          "2a03:1b20:b:f011::b80e",
          "2a03:1b20:b:f011::b80f",
          "2a03:1b20:b:f011::b810",
          "2a03:1b20:b:f011::b811",
          "2a03:1b20:b:f011::b812",
          "2a03:1b20:b:f011::b813",
          "2a03:1b20:b:f011::b814",
          "2a03:1b20:b:f011::b815",
          "2a03:1b20:b:f011::b816",
          "2a03:1b20:b:f011::b817",
          "2a03:1b20:b:f011::b818",
          "2a03:1b20:b:f011::b819",
          "2a03:1b20:b:f011::b81a",
          "2a03:1b20:b:f011::b81b",
          "2a03:1b20:b:f011::b81c",
          "2a03:1b20:b:f011::b81d",
          "2a03:1b20:b:f011::b81e",
          "2a03:1b20:b:f011::b81f"
        ],
        "features": {
          "lwo": {},
          "quic": {
            "addr_in": [
              "193.32.248.232",
              "2a03:1b20:b:f011::f80a",
              "151.241.171.210",
              "151.241.171.211",
              "151.241.171.212",
              "151.241.171.213",
              "151.241.171.214",
              "151.241.171.215",
              "151.241.171.216",
              "151.241.171.217",
              "151.241.171.218",
              "151.241.171.219",
              "2a03:1b20:b:f011::c802",
              "2a03:1b20:b:f011::c803",
              "2a03:1b20:b:f011::c804",
              "2a03:1b20:b:f011::c805",
              "2a03:1b20:b:f011::c806",
              "2a03:1b20:b:f011::c807",
              "2a03:1b20:b:f011::c808",
              "2a03:1b20:b:f011::c809",
              "2a03:1b20:b:f011::c80a",
              "2a03:1b20:b:f011::c80b",
              "2a03:1b20:b:f011::c80c",
              "2a03:1b20:b:f011::c80d",
              "2a03:1b20:b:f011::c80e",
              "2a03:1b20:b:f011::c80f",
              "2a03:1b20:b:f011::c810",
              "2a03:1b20:b:f011::c811",
              "2a03:1b20:b:f011::c812",
              "2a03:1b20:b:f011::c813",
              "2a03:1b20:b:f011::c814",
              "2a03:1b20:b:f011::c815",
              "2a03:1b20:b:f011::c816",
              "2a03:1b20:b:f011::c817",
              "2a03:1b20:b:f011::c818",
              "2a03:1b20:b:f011::c819",
              "2a03:1b20:b:f011::c81a",
              "2a03:1b20:b:f011::c81b",
              "2a03:1b20:b:f011::c81c",
              "2a03:1b20:b:f011::c81d",
              "2a03:1b20:b:f011::c81e",
              "2a03:1b20:b:f011::c81f"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "de-ber-wg-008.blockerad.eu"
          }
        }
      },
      {
        "hostname": "de-dus-wg-001",
        "location": "de-dus",
        "active": true,
        "owned": false,
        "provider": "xtom",
        "stboot": true,
        "ipv4_addr_in": "185.254.75.3",
        "include_in_country": true,
        "weight": 150,
        "public_key": "ku1NYeOAGbY65YL/JKZhrqVzDJKXQiVj9USXbfkOBA0=",
        "ipv6_addr_in": "2a03:d9c0:3000::a20f"
      },
      {
        "hostname": "de-dus-wg-002",
        "location": "de-dus",
        "active": true,
        "owned": false,
        "provider": "xtom",
        "stboot": true,
        "ipv4_addr_in": "185.254.75.4",
        "include_in_country": true,
        "weight": 150,
        "public_key": "TPAIPTgu9jIitgX1Bz5xMCZJ9pRRZTdtZEOIxArO0Hc=",
        "ipv6_addr_in": "2a03:d9c0:3000::a21f"
      },
      {
        "hostname": "de-dus-wg-003",
        "location": "de-dus",
        "active": true,
        "owned": false,
        "provider": "xtom",
        "stboot": true,
        "ipv4_addr_in": "185.254.75.5",
        "include_in_country": true,
        "weight": 150,
        "public_key": "XgSe9UwEV4JJNPPzFFOVYS6scMTL4DeNlwqBl32lDw0=",
        "ipv6_addr_in": "2a03:d9c0:3000::a22f"
      },
      {
        "hostname": "de-fra-wg-001",
        "location": "de-fra",
        "active": true,
        "owned": true,
        "provider": "31173",
        "stboot": true,
        "ipv4_addr_in": "185.213.155.73",
        "include_in_country": true,
        "weight": 25,
        "public_key": "HQHCrq4J6bSpdW1fI5hR/bvcrYa6HgGgwaa5ZY749ik=",
        "ipv6_addr_in": "2a03:1b20:6:f011::f001",
        "shadowsocks_extra_addr_in": [
          "2a03:1b20:6:f011::b002",
          "2a03:1b20:6:f011::b003",
          "2a03:1b20:6:f011::b004",
          "2a03:1b20:6:f011::b005",
          "2a03:1b20:6:f011::b006",
          "2a03:1b20:6:f011::b007",
          "2a03:1b20:6:f011::b008",
          "2a03:1b20:6:f011::b009",
          "2a03:1b20:6:f011::b00a",
          "2a03:1b20:6:f011::b00b",
          "2a03:1b20:6:f011::b00c",
          "2a03:1b20:6:f011::b00d",
          "2a03:1b20:6:f011::b00e",
          "2a03:1b20:6:f011::b00f",
          "2a03:1b20:6:f011::b010",
          "2a03:1b20:6:f011::b011",
          "2a03:1b20:6:f011::b012",
          "2a03:1b20:6:f011::b013",
          "2a03:1b20:6:f011::b014",
          "2a03:1b20:6:f011::b015",
          "2a03:1b20:6:f011::b016",
          "2a03:1b20:6:f011::b017",
          "2a03:1b20:6:f011::b018",
          "2a03:1b20:6:f011::b019",
          "2a03:1b20:6:f011::b01a",
          "2a03:1b20:6:f011::b01b",
          "2a03:1b20:6:f011::b01c",
          "2a03:1b20:6:f011::b01d",
          "2a03:1b20:6:f011::b01e",
          "2a03:1b20:6:f011::b01f"
        ],
        "features": {
          "lwo": {},
          "quic": {
            "addr_in": [
              "185.213.155.99",
              "2a03:1b20:6:f011::c002",
              "2a03:1b20:6:f011::c003",
              "2a03:1b20:6:f011::c004",
              "2a03:1b20:6:f011::c005",
              "2a03:1b20:6:f011::c006",
              "2a03:1b20:6:f011::c007",
              "2a03:1b20:6:f011::c008",
              "2a03:1b20:6:f011::c009",
              "2a03:1b20:6:f011::c00a",
              "2a03:1b20:6:f011::c00b",
              "2a03:1b20:6:f011::c00c",
              "2a03:1b20:6:f011::c00d",
              "2a03:1b20:6:f011::c00e",
              "2a03:1b20:6:f011::c00f",
              "2a03:1b20:6:f011::c010",
              "2a03:1b20:6:f011::c011",
              "2a03:1b20:6:f011::c012",
              "2a03:1b20:6:f011::c013",
              "2a03:1b20:6:f011::c014",
              "2a03:1b20:6:f011::c015",
              "2a03:1b20:6:f011::c016",
              "2a03:1b20:6:f011::c017",
              "2a03:1b20:6:f011::c018",
              "2a03:1b20:6:f011::c019",
              "2a03:1b20:6:f011::c01a",
              "2a03:1b20:6:f011::c01b",
              "2a03:1b20:6:f011::c01c",
              "2a03:1b20:6:f011::c01d",
              "2a03:1b20:6:f011::c01e",
              "2a03:1b20:6:f011::c01f"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "de-fra-wg-001.blockerad.eu"
          }
        }
      },
      {
        "hostname": "de-fra-wg-002",
        "location": "de-fra",
        "active": true,
        "owned": true,
        "provider": "31173",
        "stboot": true,
        "ipv4_addr_in": "185.213.155.74",
        "include_in_country": true,
        "weight": 25,
        "public_key": "s1c/NsfnqnwQSxao70DY4Co69AFT9e0h88IFuMD5mjs=",
        "ipv6_addr_in": "2a03:1b20:6:f011::f101",
        "shadowsocks_extra_addr_in": [
          "151.241.163.30",
          "151.241.163.31",
          "151.241.163.32",
          "151.241.163.33",
          "151.241.163.34",
          "151.241.163.35",
          "151.241.163.36",
          "151.241.163.37",
          "151.241.163.38",
          "151.241.163.39",
          "151.241.163.40",
          "151.241.163.41",
          "151.241.163.42",
          "151.241.163.43",
          "151.241.163.44",
          "151.241.163.45",
          "151.241.163.46",
          "151.241.163.47",
          "151.241.163.48",
          "151.241.163.49",
          "2a03:1b20:6:f011::b102",
          "2a03:1b20:6:f011::b103",
          "2a03:1b20:6:f011::b104",
          "2a03:1b20:6:f011::b105",
          "2a03:1b20:6:f011::b106",
          "2a03:1b20:6:f011::b107",
          "2a03:1b20:6:f011::b108",
          "2a03:1b20:6:f011::b109",
          "2a03:1b20:6:f011::b10a",
          "2a03:1b20:6:f011::b10b",
          "2a03:1b20:6:f011::b10c",
          "2a03:1b20:6:f011::b10d",
          "2a03:1b20:6:f011::b10e",
          "2a03:1b20:6:f011::b10f",
          "2a03:1b20:6:f011::b110",
          "2a03:1b20:6:f011::b111",
          "2a03:1b20:6:f011::b112",
          "2a03:1b20:6:f011::b113",
          "2a03:1b20:6:f011::b114",
          "2a03:1b20:6:f011::b115",
          "2a03:1b20:6:f011::b116",
          "2a03:1b20:6:f011::b117",
          "2a03:1b20:6:f011::b118",
          "2a03:1b20:6:f011::b119",
          "2a03:1b20:6:f011::b11a",
          "2a03:1b20:6:f011::b11b",
          "2a03:1b20:6:f011::b11c",
          "2a03:1b20:6:f011::b11d",
          "2a03:1b20:6:f011::b11e",
          "2a03:1b20:6:f011::b11f"
        ],
        "features": {
          "lwo": {},
          "quic": {
            "addr_in": [
              "151.241.163.20",
              "151.241.163.21",
              "151.241.163.22",
              "151.241.163.23",
              "151.241.163.24",
              "151.241.163.25",
              "151.241.163.26",
              "151.241.163.27",
              "151.241.163.28",
              "151.241.163.29",
              "151.241.163.50",
              "151.241.163.51",
              "151.241.163.52",
              "151.241.163.53",
              "151.241.163.54",
              "151.241.163.55",
              "151.241.163.56",
              "151.241.163.57",
              "151.241.163.58",
              "151.241.163.59",
              "2a03:1b20:6:f011::c102",
              "2a03:1b20:6:f011::c103",
              "2a03:1b20:6:f011::c104",
              "2a03:1b20:6:f011::c105",
              "2a03:1b20:6:f011::c106",
              "2a03:1b20:6:f011::c107",
              "2a03:1b20:6:f011::c108",
              "2a03:1b20:6:f011::c109",
              "2a03:1b20:6:f011::c10a",
              "2a03:1b20:6:f011::c10b",
              "2a03:1b20:6:f011::c10c",
              "2a03:1b20:6:f011::c10d",
              "2a03:1b20:6:f011::c10e",
              "2a03:1b20:6:f011::c10f",
              "2a03:1b20:6:f011::c110",
              "2a03:1b20:6:f011::c111",
              "2a03:1b20:6:f011::c112",
              "2a03:1b20:6:f011::c113",
              "2a03:1b20:6:f011::c114",
              "2a03:1b20:6:f011::c115",
              "2a03:1b20:6:f011::c116",
              "2a03:1b20:6:f011::c117",
              "2a03:1b20:6:f011::c118",
              "2a03:1b20:6:f011::c119",
              "2a03:1b20:6:f011::c11a",
              "2a03:1b20:6:f011::c11b",
              "2a03:1b20:6:f011::c11c",
              "2a03:1b20:6:f011::c11d",
              "2a03:1b20:6:f011::c11e",
              "2a03:1b20:6:f011::c11f"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "de-fra-wg-002.blockerad.eu"
          }
        }
      },
      {
        "hostname": "de-fra-wg-003",
        "location": "de-fra",
        "active": true,
        "owned": true,
        "provider": "31173",
        "stboot": true,
        "ipv4_addr_in": "185.209.196.73",
        "include_in_country": true,
        "weight": 25,
        "public_key": "vVQKs2TeTbdAvl3sH16UWLSESncXAj0oBaNuFIUkLVk=",
        "ipv6_addr_in": "2a03:1b20:6:f011::f201",
        "shadowsocks_extra_addr_in": [
          "151.241.163.100",
          "151.241.163.101",
          "151.241.163.102",
          "151.241.163.103",
          "151.241.163.104",
          "151.241.163.105",
          "151.241.163.106",
          "151.241.163.107",
          "151.241.163.108",
          "151.241.163.109",
          "151.241.163.110",
          "151.241.163.111",
          "151.241.163.112",
          "151.241.163.113",
          "151.241.163.114",
          "151.241.163.115",
          "151.241.163.116",
          "151.241.163.117",
          "151.241.163.118",
          "151.241.163.119",
          "2a03:1b20:6:f011:3:b:0:1",
          "2a03:1b20:6:f011:3:b:0:2",
          "2a03:1b20:6:f011:3:b:0:3",
          "2a03:1b20:6:f011:3:b:0:4",
          "2a03:1b20:6:f011:3:b:0:5",
          "2a03:1b20:6:f011:3:b:0:6",
          "2a03:1b20:6:f011:3:b:0:7",
          "2a03:1b20:6:f011:3:b:0:8",
          "2a03:1b20:6:f011:3:b:0:9",
          "2a03:1b20:6:f011:3:b:0:a",
          "2a03:1b20:6:f011:3:b:0:b",
          "2a03:1b20:6:f011:3:b:0:c",
          "2a03:1b20:6:f011:3:b:0:d",
          "2a03:1b20:6:f011:3:b:0:e",
          "2a03:1b20:6:f011:3:b:0:f"
        ],
        "features": {
          "lwo": {},
          "quic": {
            "addr_in": [
              "151.241.163.90",
              "151.241.163.91",
              "151.241.163.92",
              "151.241.163.93",
              "151.241.163.94",
              "151.241.163.95",
              "151.241.163.96",
              "151.241.163.97",
              "151.241.163.98",
              "151.241.163.99",
              "151.241.163.80",
              "151.241.163.81",
              "151.241.163.82",
              "151.241.163.83",
              "151.241.163.84",
              "151.241.163.85",
              "151.241.163.86",
              "151.241.163.87",
              "151.241.163.88",
              "151.241.163.89",
              "2a03:1b20:6:f011:3:c:0:1",
              "2a03:1b20:6:f011:3:c:0:2",
              "2a03:1b20:6:f011:3:c:0:3",
              "2a03:1b20:6:f011:3:c:0:4",
              "2a03:1b20:6:f011:3:c:0:5",
              "2a03:1b20:6:f011:3:c:0:6",
              "2a03:1b20:6:f011:3:c:0:7",
              "2a03:1b20:6:f011:3:c:0:8",
              "2a03:1b20:6:f011:3:c:0:9",
              "2a03:1b20:6:f011:3:c:0:a",
              "2a03:1b20:6:f011:3:c:0:b",
              "2a03:1b20:6:f011:3:c:0:c",
              "2a03:1b20:6:f011:3:c:0:d",
              "2a03:1b20:6:f011:3:c:0:e",
              "2a03:1b20:6:f011:3:c:0:f"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "de-fra-wg-003.blockerad.eu"
          }
        }
      },
      {
        "hostname": "de-fra-wg-004",
        "location": "de-fra",
        "active": true,
        "owned": true,
        "provider": "31173",
        "stboot": true,
        "ipv4_addr_in": "185.209.196.74",
        "include_in_country": true,
        "weight": 25,
        "public_key": "tzYLWgBdwrbbBCXYHRSoYIho4dHtrm+8bdONU1I8xzc=",
        "ipv6_addr_in": "2a03:1b20:6:f011::f301",
        "daita": true,
        "shadowsocks_extra_addr_in": [
          "151.241.163.160",
          "151.241.163.161",
          "151.241.163.162",
          "151.241.163.163",
          "151.241.163.164",
          "151.241.163.165",
          "151.241.163.166",
          "151.241.163.167",
          "151.241.163.168",
          "151.241.163.169",
          "151.241.163.170",
          "151.241.163.171",
          "151.241.163.172",
          "151.241.163.173",
          "151.241.163.174",
          "151.241.163.175",
          "151.241.163.176",
          "151.241.163.177",
          "151.241.163.178",
          "151.241.163.179",
          "2a03:1b20:6:f011::b302",
          "2a03:1b20:6:f011::b303",
          "2a03:1b20:6:f011::b304",
          "2a03:1b20:6:f011::b305",
          "2a03:1b20:6:f011::b306",
          "2a03:1b20:6:f011::b307",
          "2a03:1b20:6:f011::b308",
          "2a03:1b20:6:f011::b309",
          "2a03:1b20:6:f011::b30a",
          "2a03:1b20:6:f011::b30b",
          "2a03:1b20:6:f011::b30c",
          "2a03:1b20:6:f011::b30d",
          "2a03:1b20:6:f011::b30e",
          "2a03:1b20:6:f011::b30f",
          "2a03:1b20:6:f011::b310",
          "2a03:1b20:6:f011::b311",
          "2a03:1b20:6:f011::b312",
          "2a03:1b20:6:f011::b313",
          "2a03:1b20:6:f011::b314",
          "2a03:1b20:6:f011::b315",
          "2a03:1b20:6:f011::b316",
          "2a03:1b20:6:f011::b317",
          "2a03:1b20:6:f011::b318",
          "2a03:1b20:6:f011::b319",
          "2a03:1b20:6:f011::b31a",
          "2a03:1b20:6:f011::b31b",
          "2a03:1b20:6:f011::b31c",
          "2a03:1b20:6:f011::b31d",
          "2a03:1b20:6:f011::b31e",
          "2a03:1b20:6:f011::b31f"
        ],
        "features": {
          "daita": {},
          "lwo": {},
          "quic": {
            "addr_in": [
              "151.241.163.140",
              "151.241.163.141",
              "151.241.163.142",
              "151.241.163.143",
              "151.241.163.144",
              "151.241.163.145",
              "151.241.163.146",
              "151.241.163.147",
              "151.241.163.148",
              "151.241.163.149",
              "151.241.163.150",
              "151.241.163.151",
              "151.241.163.152",
              "151.241.163.153",
              "151.241.163.154",
              "151.241.163.155",
              "151.241.163.156",
              "151.241.163.157",
              "151.241.163.158",
              "151.241.163.159",
              "2a03:1b20:6:f011::c302",
              "2a03:1b20:6:f011::c303",
              "2a03:1b20:6:f011::c304",
              "2a03:1b20:6:f011::c305",
              "2a03:1b20:6:f011::c306",
              "2a03:1b20:6:f011::c307",
              "2a03:1b20:6:f011::c308",
              "2a03:1b20:6:f011::c309",
              "2a03:1b20:6:f011::c30a",
              "2a03:1b20:6:f011::c30b",
              "2a03:1b20:6:f011::c30c",
              "2a03:1b20:6:f011::c30d",
              "2a03:1b20:6:f011::c30e",
              "2a03:1b20:6:f011::c30f",
              "2a03:1b20:6:f011::c310",
              "2a03:1b20:6:f011::c311",
              "2a03:1b20:6:f011::c312",
              "2a03:1b20:6:f011::c313",
              "2a03:1b20:6:f011::c314",
              "2a03:1b20:6:f011::c315",
              "2a03:1b20:6:f011::c316",
              "2a03:1b20:6:f011::c317",
              "2a03:1b20:6:f011::c318",
              "2a03:1b20:6:f011::c319",
              "2a03:1b20:6:f011::c31a",
              "2a03:1b20:6:f011::c31b",
              "2a03:1b20:6:f011::c31c",
              "2a03:1b20:6:f011::c31d",
              "2a03:1b20:6:f011::c31e",
              "2a03:1b20:6:f011::c31f"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "de-fra-wg-004.blockerad.eu"
          }
        }
      },
      {
        "hostname": "de-fra-wg-005",
        "location": "de-fra",
        "active": true,
        "owned": true,
        "provider": "31173",
        "stboot": true,
        "ipv4_addr_in": "185.209.196.75",
        "include_in_country": true,
        "weight": 25,
        "public_key": "tpobOO6t18CzHjOg0S3RlZJMxd2tz4+BnRYS7NrjTnM=",
        "ipv6_addr_in": "2a03:1b20:6:f011::f401",
        "shadowsocks_extra_addr_in": [
          "151.241.163.220",
          "151.241.163.221",
          "151.241.163.222",
          "151.241.163.223",
          "151.241.163.224",
          "151.241.163.225",
          "151.241.163.226",
          "151.241.163.227",
          "151.241.163.228",
          "151.241.163.229",
          "151.241.163.230",
          "151.241.163.231",
          "151.241.163.232",
          "151.241.163.233",
          "151.241.163.234",
          "151.241.163.235",
          "151.241.163.236",
          "151.241.163.237",
          "151.241.163.238",
          "151.241.163.239",
          "151.241.163.240",
          "151.241.163.241",
          "151.241.163.242",
          "151.241.163.243",
          "151.241.163.244",
          "151.241.163.245",
          "151.241.163.246",
          "151.241.163.247",
          "151.241.163.248",
          "151.241.163.249",
          "2a03:1b20:6:f011::b402",
          "2a03:1b20:6:f011::b403",
          "2a03:1b20:6:f011::b404",
          "2a03:1b20:6:f011::b405",
          "2a03:1b20:6:f011::b406",
          "2a03:1b20:6:f011::b407",
          "2a03:1b20:6:f011::b408",
          "2a03:1b20:6:f011::b409",
          "2a03:1b20:6:f011::b40a",
          "2a03:1b20:6:f011::b40b",
          "2a03:1b20:6:f011::b40c",
          "2a03:1b20:6:f011::b40d",
          "2a03:1b20:6:f011::b40e",
          "2a03:1b20:6:f011::b40f",
          "2a03:1b20:6:f011::b410",
          "2a03:1b20:6:f011::b411",
          "2a03:1b20:6:f011::b412",
          "2a03:1b20:6:f011::b413",
          "2a03:1b20:6:f011::b414",
          "2a03:1b20:6:f011::b415",
          "2a03:1b20:6:f011::b416",
          "2a03:1b20:6:f011::b417",
          "2a03:1b20:6:f011::b418",
          "2a03:1b20:6:f011::b419",
          "2a03:1b20:6:f011::b41a",
          "2a03:1b20:6:f011::b41b",
          "2a03:1b20:6:f011::b41c",
          "2a03:1b20:6:f011::b41d",
          "2a03:1b20:6:f011::b41e",
          "2a03:1b20:6:f011::b41f"
        ],
        "features": {
          "lwo": {},
          "quic": {
            "addr_in": [
              "151.241.163.200",
              "151.241.163.201",
              "151.241.163.202",
              "151.241.163.203",
              "151.241.163.204",
              "151.241.163.205",
              "151.241.163.206",
              "151.241.163.207",
              "151.241.163.208",
              "151.241.163.209",
              "151.241.163.210",
              "151.241.163.210",
              "151.241.163.211",
              "151.241.163.212",
              "151.241.163.213",
              "151.241.163.214",
              "151.241.163.215",
              "151.241.163.216",
              "151.241.163.217",
              "151.241.163.218",
              "151.241.163.219",
              "2a03:1b20:6:f011::c402",
              "2a03:1b20:6:f011::c403",
              "2a03:1b20:6:f011::c404",
              "2a03:1b20:6:f011::c405",
              "2a03:1b20:6:f011::c406",
              "2a03:1b20:6:f011::c407",
              "2a03:1b20:6:f011::c408",
              "2a03:1b20:6:f011::c409",
              "2a03:1b20:6:f011::c40a",
              "2a03:1b20:6:f011::c40b",
              "2a03:1b20:6:f011::c40c",
              "2a03:1b20:6:f011::c40d",
              "2a03:1b20:6:f011::c40e",
              "2a03:1b20:6:f011::c40f",
              "2a03:1b20:6:f011::c410",
              "2a03:1b20:6:f011::c411",
              "2a03:1b20:6:f011::c412",
              "2a03:1b20:6:f011::c413",
              "2a03:1b20:6:f011::c414",
              "2a03:1b20:6:f011::c415",
              "2a03:1b20:6:f011::c416",
              "2a03:1b20:6:f011::c417",
              "2a03:1b20:6:f011::c418",
              "2a03:1b20:6:f011::c419",
              "2a03:1b20:6:f011::c41a",
              "2a03:1b20:6:f011::c41b",
              "2a03:1b20:6:f011::c41c",
              "2a03:1b20:6:f011::c41d",
              "2a03:1b20:6:f011::c41e",
              "2a03:1b20:6:f011::c41f"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "de-fra-wg-005.blockerad.eu"
          }
        }
      },
      {
        "hostname": "de-fra-wg-006",
        "location": "de-fra",
        "active": true,
        "owned": true,
        "provider": "31173",
        "stboot": true,
        "ipv4_addr_in": "185.209.196.76",
        "include_in_country": true,
        "weight": 25,
        "public_key": "nAF0wrLG2+avwQfqxnXhBGPUBCvc3QCqWKH4nK5PfEU=",
        "ipv6_addr_in": "2a03:1b20:6:f011::f501",
        "shadowsocks_extra_addr_in": [
          "2a03:1b20:6:f011::b502",
          "2a03:1b20:6:f011::b503",
          "2a03:1b20:6:f011::b504",
          "2a03:1b20:6:f011::b505",
          "2a03:1b20:6:f011::b506",
          "2a03:1b20:6:f011::b507",
          "2a03:1b20:6:f011::b508",
          "2a03:1b20:6:f011::b509",
          "2a03:1b20:6:f011::b50a",
          "2a03:1b20:6:f011::b50b",
          "2a03:1b20:6:f011::b50c",
          "2a03:1b20:6:f011::b50d",
          "2a03:1b20:6:f011::b50e",
          "2a03:1b20:6:f011::b50f",
          "2a03:1b20:6:f011::b510",
          "2a03:1b20:6:f011::b511",
          "2a03:1b20:6:f011::b512",
          "2a03:1b20:6:f011::b513",
          "2a03:1b20:6:f011::b514",
          "2a03:1b20:6:f011::b515",
          "2a03:1b20:6:f011::b516",
          "2a03:1b20:6:f011::b517",
          "2a03:1b20:6:f011::b518",
          "2a03:1b20:6:f011::b519",
          "2a03:1b20:6:f011::b51a",
          "2a03:1b20:6:f011::b51b",
          "2a03:1b20:6:f011::b51c",
          "2a03:1b20:6:f011::b51d",
          "2a03:1b20:6:f011::b51e",
          "2a03:1b20:6:f011::b51f"
        ],
        "features": {
          "lwo": {},
          "quic": {
            "addr_in": [
              "2a03:1b20:6:f011::c502",
              "2a03:1b20:6:f011::c503",
              "2a03:1b20:6:f011::c504",
              "2a03:1b20:6:f011::c505",
              "2a03:1b20:6:f011::c506",
              "2a03:1b20:6:f011::c507",
              "2a03:1b20:6:f011::c508",
              "2a03:1b20:6:f011::c509",
              "2a03:1b20:6:f011::c50a",
              "2a03:1b20:6:f011::c50b",
              "2a03:1b20:6:f011::c50c",
              "2a03:1b20:6:f011::c50d",
              "2a03:1b20:6:f011::c50e",
              "2a03:1b20:6:f011::c50f",
              "2a03:1b20:6:f011::c510",
              "2a03:1b20:6:f011::c511",
              "2a03:1b20:6:f011::c512",
              "2a03:1b20:6:f011::c513",
              "2a03:1b20:6:f011::c514",
              "2a03:1b20:6:f011::c515",
              "2a03:1b20:6:f011::c516",
              "2a03:1b20:6:f011::c517",
              "2a03:1b20:6:f011::c518",
              "2a03:1b20:6:f011::c519",
              "2a03:1b20:6:f011::c51a",
              "2a03:1b20:6:f011::c51b",
              "2a03:1b20:6:f011::c51c",
              "2a03:1b20:6:f011::c51d",
              "2a03:1b20:6:f011::c51e",
              "2a03:1b20:6:f011::c51f"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "de-fra-wg-006.blockerad.eu"
          }
        }
      },
      {
        "hostname": "de-fra-wg-007",
        "location": "de-fra",
        "active": true,
        "owned": true,
        "provider": "31173",
        "stboot": true,
        "ipv4_addr_in": "185.209.196.77",
        "include_in_country": true,
        "weight": 25,
        "public_key": "mTmrSuXmTnIC9l2Ur3/QgodGrVEhhIE3pRwOHZpiYys=",
        "ipv6_addr_in": "2a03:1b20:6:f011::f601",
        "features": {
          "lwo": {}
        }
      },
      {
        "hostname": "de-fra-wg-008",
        "location": "de-fra",
        "active": true,
        "owned": true,
        "provider": "31173",
        "stboot": true,
        "ipv4_addr_in": "185.209.196.78",
        "include_in_country": true,
        "weight": 25,
        "public_key": "+DuVLLPwGNlfZFoI24PRPdaTrO4i+WPDlYaOVcavHDo=",
        "ipv6_addr_in": "2a03:1b20:6:f011::f701",
        "shadowsocks_extra_addr_in": [
          "2a03:1b20:6:f011::b702",
          "2a03:1b20:6:f011::b703",
          "2a03:1b20:6:f011::b704",
          "2a03:1b20:6:f011::b705",
          "2a03:1b20:6:f011::b706",
          "2a03:1b20:6:f011::b707",
          "2a03:1b20:6:f011::b708",
          "2a03:1b20:6:f011::b709",
          "2a03:1b20:6:f011::b70a",
          "2a03:1b20:6:f011::b70b",
          "2a03:1b20:6:f011::b70c",
          "2a03:1b20:6:f011::b70d",
          "2a03:1b20:6:f011::b70e",
          "2a03:1b20:6:f011::b70f",
          "2a03:1b20:6:f011::b710",
          "2a03:1b20:6:f011::b711",
          "2a03:1b20:6:f011::b712",
          "2a03:1b20:6:f011::b713",
          "2a03:1b20:6:f011::b714",
          "2a03:1b20:6:f011::b715",
          "2a03:1b20:6:f011::b716",
          "2a03:1b20:6:f011::b717",
          "2a03:1b20:6:f011::b718",
          "2a03:1b20:6:f011::b719",
          "2a03:1b20:6:f011::b71a",
          "2a03:1b20:6:f011::b71b",
          "2a03:1b20:6:f011::b71c",
          "2a03:1b20:6:f011::b71d",
          "2a03:1b20:6:f011::b71e",
          "2a03:1b20:6:f011::b71f"
        ],
        "features": {
          "lwo": {}
        }
      },
      {
        "hostname": "de-fra-wg-009",
        "location": "de-fra",
        "active": true,
        "owned": true,
        "provider": "31173",
        "stboot": true,
        "ipv4_addr_in": "185.213.155.72",
        "include_in_country": true,
        "weight": 25,
        "public_key": "flq7zR8W5FxouHBuZoTRHY0A0qFEMQZF5uAgV4+sHVw=",
        "ipv6_addr_in": "2a03:1b20:6:f011::f901",
        "shadowsocks_extra_addr_in": [
          "2a03:1b20:6:f011::b902",
          "2a03:1b20:6:f011::b903",
          "2a03:1b20:6:f011::b904",
          "2a03:1b20:6:f011::b905",
          "2a03:1b20:6:f011::b906",
          "2a03:1b20:6:f011::b907",
          "2a03:1b20:6:f011::b908",
          "2a03:1b20:6:f011::b909",
          "2a03:1b20:6:f011::b90a",
          "2a03:1b20:6:f011::b90b",
          "2a03:1b20:6:f011::b90c",
          "2a03:1b20:6:f011::b90d",
          "2a03:1b20:6:f011::b90e",
          "2a03:1b20:6:f011::b90f",
          "2a03:1b20:6:f011::b910",
          "2a03:1b20:6:f011::b911",
          "2a03:1b20:6:f011::b912",
          "2a03:1b20:6:f011::b913",
          "2a03:1b20:6:f011::b914",
          "2a03:1b20:6:f011::b915",
          "2a03:1b20:6:f011::b916",
          "2a03:1b20:6:f011::b917",
          "2a03:1b20:6:f011::b918",
          "2a03:1b20:6:f011::b919",
          "2a03:1b20:6:f011::b91a",
          "2a03:1b20:6:f011::b91b",
          "2a03:1b20:6:f011::b91c",
          "2a03:1b20:6:f011::b91d",
          "2a03:1b20:6:f011::b91e",
          "2a03:1b20:6:f011::b91f"
        ],
        "features": {
          "lwo": {}
        }
      },
      {
        "hostname": "de-fra-wg-101",
        "location": "de-fra",
        "active": true,
        "owned": false,
        "provider": "M247",
        "stboot": true,
        "ipv4_addr_in": "146.70.117.2",
        "include_in_country": true,
        "weight": 100,
        "public_key": "wxbDlI3xb+Cc05XKb4usdKSzKe1byK7brmsHU2DJB14=",
        "ipv6_addr_in": "2001:ac8:20:270:1::f001",
        "daita": true,
        "shadowsocks_extra_addr_in": [
          "146.70.117.16",
          "146.70.117.17",
          "146.70.117.18",
          "146.70.117.19",
          "146.70.117.20",
          "146.70.117.21",
          "146.70.117.22",
          "146.70.117.23",
          "146.70.117.24",
          "146.70.117.25",
          "146.70.117.26",
          "2001:ac8:20:270:1::b002",
          "2001:ac8:20:270:1::b003",
          "2001:ac8:20:270:1::b004",
          "2001:ac8:20:270:1::b005",
          "2001:ac8:20:270:1::b006",
          "2001:ac8:20:270:1::b007",
          "2001:ac8:20:270:1::b008",
          "2001:ac8:20:270:1::b009",
          "2001:ac8:20:270:1::b00a",
          "2001:ac8:20:270:1::b00b",
          "2001:ac8:20:270:1::b00c",
          "2001:ac8:20:270:1::b00d",
          "2001:ac8:20:270:1::b00e",
          "2001:ac8:20:270:1::b00f",
          "2001:ac8:20:270:1::b010",
          "2001:ac8:20:270:1::b011",
          "2001:ac8:20:270:1::b012",
          "2001:ac8:20:270:1::b013",
          "2001:ac8:20:270:1::b014",
          "2001:ac8:20:270:1::b015",
          "2001:ac8:20:270:1::b016",
          "2001:ac8:20:270:1::b017",
          "2001:ac8:20:270:1::b018",
          "2001:ac8:20:270:1::b019",
          "2001:ac8:20:270:1::b01a",
          "2001:ac8:20:270:1::b01b",
          "2001:ac8:20:270:1::b01c",
          "2001:ac8:20:270:1::b01d",
          "2001:ac8:20:270:1::b01e",
          "2001:ac8:20:270:1::b01f"
        ],
        "features": {
          "daita": {},
          "quic": {
            "addr_in": [
              "146.70.117.5",
              "146.70.117.6",
              "146.70.117.7",
              "146.70.117.8",
              "146.70.117.9",
              "146.70.117.10",
              "146.70.117.11",
              "146.70.117.12",
              "146.70.117.13",
              "146.70.117.14",
              "146.70.117.15",
              "2001:ac8:20:270:1::c002",
              "2001:ac8:20:270:1::c003",
              "2001:ac8:20:270:1::c004",
              "2001:ac8:20:270:1::c005",
              "2001:ac8:20:270:1::c006",
              "2001:ac8:20:270:1::c007",
              "2001:ac8:20:270:1::c008",
              "2001:ac8:20:270:1::c009",
              "2001:ac8:20:270:1::c00a",
              "2001:ac8:20:270:1::c00b",
              "2001:ac8:20:270:1::c00c",
              "2001:ac8:20:270:1::c00d",
              "2001:ac8:20:270:1::c00e",
              "2001:ac8:20:270:1::c00f",
              "2001:ac8:20:270:1::c010",
              "2001:ac8:20:270:1::c011",
              "2001:ac8:20:270:1::c012",
              "2001:ac8:20:270:1::c013",
              "2001:ac8:20:270:1::c014",
              "2001:ac8:20:270:1::c015",
              "2001:ac8:20:270:1::c016",
              "2001:ac8:20:270:1::c017",
              "2001:ac8:20:270:1::c018",
              "2001:ac8:20:270:1::c019",
              "2001:ac8:20:270:1::c01a",
              "2001:ac8:20:270:1::c01b",
              "2001:ac8:20:270:1::c01c",
              "2001:ac8:20:270:1::c01d",
              "2001:ac8:20:270:1::c01e",
              "2001:ac8:20:270:1::c01f"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "de-fra-wg-101.blockerad.eu"
          }
        }
      },
      {
        "hostname": "de-fra-wg-102",
        "location": "de-fra",
        "active": true,
        "owned": false,
        "provider": "M247",
        "stboot": true,
        "ipv4_addr_in": "146.70.117.130",
        "include_in_country": true,
        "weight": 100,
        "public_key": "inG8qBhgEFhcs2EZsT9PezeWBI6+9p8tXeo0BojhpBQ=",
        "ipv6_addr_in": "2001:ac8:20:270:2::f001",
        "daita": true,
        "shadowsocks_extra_addr_in": [
          "146.70.117.144",
          "146.70.117.145",
          "146.70.117.146",
          "146.70.117.147",
          "146.70.117.148",
          "146.70.117.149",
          "146.70.117.150",
          "146.70.117.151",
          "146.70.117.152",
          "146.70.117.153",
          "146.70.117.154",
          "2001:ac8:20:270:2::b002",
          "2001:ac8:20:270:2::b003",
          "2001:ac8:20:270:2::b004",
          "2001:ac8:20:270:2::b005",
          "2001:ac8:20:270:2::b006",
          "2001:ac8:20:270:2::b007",
          "2001:ac8:20:270:2::b008",
          "2001:ac8:20:270:2::b009",
          "2001:ac8:20:270:2::b00a",
          "2001:ac8:20:270:2::b00b",
          "2001:ac8:20:270:2::b00c",
          "2001:ac8:20:270:2::b00d",
          "2001:ac8:20:270:2::b00e",
          "2001:ac8:20:270:2::b00f",
          "2001:ac8:20:270:2::b010",
          "2001:ac8:20:270:2::b011",
          "2001:ac8:20:270:2::b012",
          "2001:ac8:20:270:2::b013",
          "2001:ac8:20:270:2::b014",
          "2001:ac8:20:270:2::b015",
          "2001:ac8:20:270:2::b016",
          "2001:ac8:20:270:2::b017",
          "2001:ac8:20:270:2::b018",
          "2001:ac8:20:270:2::b019",
          "2001:ac8:20:270:2::b01a",
          "2001:ac8:20:270:2::b01b",
          "2001:ac8:20:270:2::b01c",
          "2001:ac8:20:270:2::b01d",
          "2001:ac8:20:270:2::b01e",
          "2001:ac8:20:270:2::b01f"
        ],
        "features": {
          "daita": {},
          "quic": {
            "addr_in": [
              "146.70.117.133",
              "146.70.117.134",
              "146.70.117.135",
              "146.70.117.136",
              "146.70.117.137",
              "146.70.117.138",
              "146.70.117.139",
              "146.70.117.140",
              "146.70.117.141",
              "146.70.117.142",
              "146.70.117.143",
              "2001:ac8:20:270:2::c002",
              "2001:ac8:20:270:2::c003",
              "2001:ac8:20:270:2::c004",
              "2001:ac8:20:270:2::c005",
              "2001:ac8:20:270:2::c006",
              "2001:ac8:20:270:2::c007",
              "2001:ac8:20:270:2::c008",
              "2001:ac8:20:270:2::c009",
              "2001:ac8:20:270:2::c00a",
              "2001:ac8:20:270:2::c00b",
              "2001:ac8:20:270:2::c00c",
              "2001:ac8:20:270:2::c00d",
              "2001:ac8:20:270:2::c00e",
              "2001:ac8:20:270:2::c00f",
              "2001:ac8:20:270:2::c010",
              "2001:ac8:20:270:2::c011",
              "2001:ac8:20:270:2::c012",
              "2001:ac8:20:270:2::c013",
              "2001:ac8:20:270:2::c014",
              "2001:ac8:20:270:2::c015",
              "2001:ac8:20:270:2::c016",
              "2001:ac8:20:270:2::c017",
              "2001:ac8:20:270:2::c018",
              "2001:ac8:20:270:2::c019",
              "2001:ac8:20:270:2::c01a",
              "2001:ac8:20:270:2::c01b",
              "2001:ac8:20:270:2::c01c",
              "2001:ac8:20:270:2::c01d",
              "2001:ac8:20:270:2::c01e",
              "2001:ac8:20:270:2::c01f"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "de-fra-wg-102.blockerad.eu"
          }
        }
      },
      {
        "hostname": "de-fra-wg-103",
        "location": "de-fra",
        "active": true,
        "owned": false,
        "provider": "M247",
        "stboot": true,
        "ipv4_addr_in": "135.136.19.2",
        "include_in_country": true,
        "weight": 100,
        "public_key": "V7g+GpphZny5CWgDdClejTQX3ImrYFRh+CVETeOWRBU=",
        "ipv6_addr_in": "2001:ac8:20:271::f001",
        "shadowsocks_extra_addr_in": [
          "135.136.19.16",
          "135.136.19.17",
          "135.136.19.18",
          "135.136.19.19",
          "135.136.19.20",
          "135.136.19.21",
          "135.136.19.22",
          "135.136.19.23",
          "135.136.19.24",
          "135.136.19.25",
          "135.136.19.26",
          "2001:ac8:20:271::b002",
          "2001:ac8:20:271::b003",
          "2001:ac8:20:271::b004",
          "2001:ac8:20:271::b005",
          "2001:ac8:20:271::b006",
          "2001:ac8:20:271::b007",
          "2001:ac8:20:271::b008",
          "2001:ac8:20:271::b009",
          "2001:ac8:20:271::b00a",
          "2001:ac8:20:271::b00b",
          "2001:ac8:20:271::b00c",
          "2001:ac8:20:271::b00d",
          "2001:ac8:20:271::b00e",
          "2001:ac8:20:271::b00f",
          "2001:ac8:20:271::b010",
          "2001:ac8:20:271::b011",
          "2001:ac8:20:271::b012",
          "2001:ac8:20:271::b013",
          "2001:ac8:20:271::b014",
          "2001:ac8:20:271::b015",
          "2001:ac8:20:271::b016",
          "2001:ac8:20:271::b017",
          "2001:ac8:20:271::b018",
          "2001:ac8:20:271::b019",
          "2001:ac8:20:271::b01a",
          "2001:ac8:20:271::b01b",
          "2001:ac8:20:271::b01c",
          "2001:ac8:20:271::b01d",
          "2001:ac8:20:271::b01e",
          "2001:ac8:20:271::b01f"
        ],
        "features": {
          "lwo": {},
          "quic": {
            "addr_in": [
              "135.136.19.5",
              "135.136.19.6",
              "135.136.19.7",
              "135.136.19.8",
              "135.136.19.9",
              "135.136.19.10",
              "135.136.19.11",
              "135.136.19.12",
              "135.136.19.13",
              "135.136.19.14",
              "135.136.19.15",
              "2001:ac8:20:271::c002",
              "2001:ac8:20:271::c003",
              "2001:ac8:20:271::c004",
              "2001:ac8:20:271::c005",
              "2001:ac8:20:271::c006",
              "2001:ac8:20:271::c007",
              "2001:ac8:20:271::c008",
              "2001:ac8:20:271::c009",
              "2001:ac8:20:271::c00a",
              "2001:ac8:20:271::c00b",
              "2001:ac8:20:271::c00c",
              "2001:ac8:20:271::c00d",
              "2001:ac8:20:271::c00e",
              "2001:ac8:20:271::c00f",
              "2001:ac8:20:271::c010",
              "2001:ac8:20:271::c011",
              "2001:ac8:20:271::c012",
              "2001:ac8:20:271::c013",
              "2001:ac8:20:271::c014",
              "2001:ac8:20:271::c015",
              "2001:ac8:20:271::c016",
              "2001:ac8:20:271::c017",
              "2001:ac8:20:271::c018",
              "2001:ac8:20:271::c019",
              "2001:ac8:20:271::c01a",
              "2001:ac8:20:271::c01b",
              "2001:ac8:20:271::c01c",
              "2001:ac8:20:271::c01d",
              "2001:ac8:20:271::c01e",
              "2001:ac8:20:271::c01f"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "de-fra-wg-103.blockerad.eu"
          }
        }
      },
      {
        "hostname": "de-fra-wg-104",
        "location": "de-fra",
        "active": true,
        "owned": false,
        "provider": "M247",
        "stboot": true,
        "ipv4_addr_in": "135.136.19.130",
        "include_in_country": true,
        "weight": 100,
        "public_key": "WPaUZB1eO0W/F4GMDk8uVgqQfS5q4P9F53/pbLmlDjs=",
        "ipv6_addr_in": "2001:ac8:20:272::f001",
        "shadowsocks_extra_addr_in": [
          "135.136.19.144",
          "135.136.19.145",
          "135.136.19.146",
          "135.136.19.147",
          "135.136.19.148",
          "135.136.19.149",
          "135.136.19.150",
          "135.136.19.151",
          "135.136.19.152",
          "135.136.19.153",
          "135.136.19.154",
          "2001:ac8:20:272::b002",
          "2001:ac8:20:272::b003",
          "2001:ac8:20:272::b004",
          "2001:ac8:20:272::b005",
          "2001:ac8:20:272::b006",
          "2001:ac8:20:272::b007",
          "2001:ac8:20:272::b008",
          "2001:ac8:20:272::b009",
          "2001:ac8:20:272::b00a",
          "2001:ac8:20:272::b00b",
          "2001:ac8:20:272::b00c",
          "2001:ac8:20:272::b00d",
          "2001:ac8:20:272::b00e",
          "2001:ac8:20:272::b00f",
          "2001:ac8:20:272::b010",
          "2001:ac8:20:272::b011",
          "2001:ac8:20:272::b012",
          "2001:ac8:20:272::b013",
          "2001:ac8:20:272::b014",
          "2001:ac8:20:272::b015",
          "2001:ac8:20:272::b016",
          "2001:ac8:20:272::b017",
          "2001:ac8:20:272::b018",
          "2001:ac8:20:272::b019",
          "2001:ac8:20:272::b01a",
          "2001:ac8:20:272::b01b",
          "2001:ac8:20:272::b01c",
          "2001:ac8:20:272::b01d",
          "2001:ac8:20:272::b01e",
          "2001:ac8:20:272::b01f"
        ],
        "features": {
          "lwo": {},
          "quic": {
            "addr_in": [
              "135.136.19.133",
              "135.136.19.134",
              "135.136.19.135",
              "135.136.19.136",
              "135.136.19.137",
              "135.136.19.138",
              "135.136.19.139",
              "135.136.19.140",
              "135.136.19.141",
              "135.136.19.142",
              "135.136.19.143",
              "2001:ac8:20:272::c002",
              "2001:ac8:20:272::c003",
              "2001:ac8:20:272::c004",
              "2001:ac8:20:272::c005",
              "2001:ac8:20:272::c006",
              "2001:ac8:20:272::c007",
              "2001:ac8:20:272::c008",
              "2001:ac8:20:272::c009",
              "2001:ac8:20:272::c00a",
              "2001:ac8:20:272::c00b",
              "2001:ac8:20:272::c00c",
              "2001:ac8:20:272::c00d",
              "2001:ac8:20:272::c00e",
              "2001:ac8:20:272::c00f",
              "2001:ac8:20:272::c010",
              "2001:ac8:20:272::c011",
              "2001:ac8:20:272::c012",
              "2001:ac8:20:272::c013",
              "2001:ac8:20:272::c014",
              "2001:ac8:20:272::c015",
              "2001:ac8:20:272::c016",
              "2001:ac8:20:272::c017",
              "2001:ac8:20:272::c018",
              "2001:ac8:20:272::c019",
              "2001:ac8:20:272::c01a",
              "2001:ac8:20:272::c01b",
              "2001:ac8:20:272::c01c",
              "2001:ac8:20:272::c01d",
              "2001:ac8:20:272::c01e",
              "2001:ac8:20:272::c01f"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "de-fra-wg-104.blockerad.eu"
          }
        }
      },
      {
        "hostname": "de-fra-wg-301",
        "location": "de-fra",
        "active": true,
        "owned": false,
        "provider": "xtom",
        "stboot": true,
        "ipv4_addr_in": "194.36.25.3",
        "include_in_country": true,
        "weight": 100,
        "public_key": "dNKRyh2MkJGZdg9jyUJtf9w5GHjX3+/fYatg+xi9TUM=",
        "ipv6_addr_in": "2a07:fe00:1::a23f",
        "features": {
          "lwo": {}
        }
      },
      {
        "hostname": "de-fra-wg-302",
        "location": "de-fra",
        "active": false,
        "owned": false,
        "provider": "xtom",
        "stboot": true,
        "ipv4_addr_in": "194.36.25.18",
        "include_in_country": true,
        "weight": 100,
        "public_key": "A3DbIgPycEJhJ1fQ4zzcajLOKTZsJMeawjdPQiWav20=",
        "ipv6_addr_in": "2a07:fe00:1::a24f",
        "features": {
          "lwo": {}
        }
      },
      {
        "hostname": "de-fra-wg-303",
        "location": "de-fra",
        "active": true,
        "owned": false,
        "provider": "xtom",
        "stboot": true,
        "ipv4_addr_in": "194.36.25.33",
        "include_in_country": true,
        "weight": 100,
        "public_key": "2P+9SjwVCEnMDnBiYfZtQLq9p2S2TFhCM0xJBoevYk4=",
        "ipv6_addr_in": "2a07:fe00:1::a25f",
        "features": {
          "lwo": {}
        }
      },
      {
        "hostname": "de-fra-wg-304",
        "location": "de-fra",
        "active": false,
        "owned": false,
        "provider": "xtom",
        "stboot": true,
        "ipv4_addr_in": "194.36.25.48",
        "include_in_country": true,
        "weight": 100,
        "public_key": "VgNcwWy8MRhfEZY+XSisDM1ykX+uXlHQScOLqqGMLkc=",
        "ipv6_addr_in": "2a07:fe00:1::a26f"
      },
      {
        "hostname": "de-fra-wg-401",
        "location": "de-fra",
        "active": true,
        "owned": false,
        "provider": "DataPacket",
        "stboot": true,
        "ipv4_addr_in": "169.150.201.2",
        "include_in_country": true,
        "weight": 100,
        "public_key": "AbM8fnQWmmX6Nv0Tz68LigPbGkamJgNjxgzPfENOdXU=",
        "ipv6_addr_in": "2a02:6ea0:c762:1::a35f",
        "features": {
          "lwo": {}
        }
      },
      {
        "hostname": "de-fra-wg-402",
        "location": "de-fra",
        "active": true,
        "owned": false,
        "provider": "DataPacket",
        "stboot": true,
        "ipv4_addr_in": "169.150.201.15",
        "include_in_country": true,
        "weight": 100,
        "public_key": "6/PBbPtoeWpJA+HZc9Iqg/PPQWD7mGVvZdwQlr1vtRk=",
        "ipv6_addr_in": "2a02:6ea0:c762:2::a36f",
        "features": {
          "lwo": {}
        }
      },
      {
        "hostname": "de-fra-wg-403",
        "location": "de-fra",
        "active": true,
        "owned": false,
        "provider": "DataPacket",
        "stboot": true,
        "ipv4_addr_in": "169.150.201.28",
        "include_in_country": true,
        "weight": 100,
        "public_key": "HWzSNMbQOQafkVp68B7aLRirhNJ6x5Wjw8/y7oUuHW0=",
        "ipv6_addr_in": "2a02:6ea0:c762:3::a37f",
        "features": {
          "lwo": {}
        }
      },
      {
        "hostname": "dk-cph-wg-001",
        "location": "dk-cph",
        "active": true,
        "owned": true,
        "provider": "31173",
        "stboot": true,
        "ipv4_addr_in": "45.129.56.67",
        "include_in_country": true,
        "weight": 100,
        "public_key": "egl+0TkpFU39F5O6r6+hIBMPQLOa8/t5CymOZV6CC3Y=",
        "ipv6_addr_in": "2a03:1b20:8:f011::f001",
        "shadowsocks_extra_addr_in": [
          "2a03:1b20:8:f011::b001",
          "2a03:1b20:8:f011::b002",
          "2a03:1b20:8:f011::b003",
          "2a03:1b20:8:f011::b004",
          "2a03:1b20:8:f011::b005",
          "2a03:1b20:8:f011::b006",
          "2a03:1b20:8:f011::b007",
          "2a03:1b20:8:f011::b008",
          "2a03:1b20:8:f011::b009",
          "2a03:1b20:8:f011::b00a",
          "2a03:1b20:8:f011::b00b",
          "2a03:1b20:8:f011::b00c",
          "2a03:1b20:8:f011::b00d",
          "2a03:1b20:8:f011::b00e",
          "2a03:1b20:8:f011::b00f",
          "2a03:1b20:8:f011::b010",
          "2a03:1b20:8:f011::b011",
          "2a03:1b20:8:f011::b012",
          "2a03:1b20:8:f011::b013",
          "2a03:1b20:8:f011::b014",
          "2a03:1b20:8:f011::b015",
          "2a03:1b20:8:f011::b016",
          "2a03:1b20:8:f011::b017",
          "2a03:1b20:8:f011::b018",
          "2a03:1b20:8:f011::b019",
          "2a03:1b20:8:f011::b01a",
          "2a03:1b20:8:f011::b01b",
          "2a03:1b20:8:f011::b01c",
          "2a03:1b20:8:f011::b01d",
          "2a03:1b20:8:f011::b01e",
          "2a03:1b20:8:f011::b01f"
        ],
        "features": {
          "lwo": {},
          "quic": {
            "addr_in": [
              "141.98.254.99",
              "2a03:1b20:8:f011::c001",
              "2a03:1b20:8:f011::c002",
              "2a03:1b20:8:f011::c003",
              "2a03:1b20:8:f011::c004",
              "2a03:1b20:8:f011::c005",
              "2a03:1b20:8:f011::c006",
              "2a03:1b20:8:f011::c007",
              "2a03:1b20:8:f011::c008",
              "2a03:1b20:8:f011::c009",
              "2a03:1b20:8:f011::c00a",
              "2a03:1b20:8:f011::c00b",
              "2a03:1b20:8:f011::c00c",
              "2a03:1b20:8:f011::c00d",
              "2a03:1b20:8:f011::c00e",
              "2a03:1b20:8:f011::c00f",
              "2a03:1b20:8:f011::c010",
              "2a03:1b20:8:f011::c011",
              "2a03:1b20:8:f011::c012",
              "2a03:1b20:8:f011::c013",
              "2a03:1b20:8:f011::c014",
              "2a03:1b20:8:f011::c015",
              "2a03:1b20:8:f011::c016",
              "2a03:1b20:8:f011::c017",
              "2a03:1b20:8:f011::c018",
              "2a03:1b20:8:f011::c019",
              "2a03:1b20:8:f011::c01a",
              "2a03:1b20:8:f011::c01b",
              "2a03:1b20:8:f011::c01c",
              "2a03:1b20:8:f011::c01d",
              "2a03:1b20:8:f011::c01e",
              "2a03:1b20:8:f011::c01f"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "dk-cph-wg-001.blockerad.eu"
          }
        }
      },
      {
        "hostname": "dk-cph-wg-002",
        "location": "dk-cph",
        "active": false,
        "owned": true,
        "provider": "31173",
        "stboot": true,
        "ipv4_addr_in": "45.129.56.68",
        "include_in_country": true,
        "weight": 100,
        "public_key": "R5LUBgM/1UjeAR4lt+L/yA30Gee6/VqVZ9eAB3ZTajs=",
        "ipv6_addr_in": "2a03:1b20:8:f011::f101",
        "shadowsocks_extra_addr_in": [
          "2a03:1b20:8:f011::b102",
          "2a03:1b20:8:f011::b103",
          "2a03:1b20:8:f011::b104",
          "2a03:1b20:8:f011::b105",
          "2a03:1b20:8:f011::b106",
          "2a03:1b20:8:f011::b107",
          "2a03:1b20:8:f011::b108",
          "2a03:1b20:8:f011::b109",
          "2a03:1b20:8:f011::b10a",
          "2a03:1b20:8:f011::b10b",
          "2a03:1b20:8:f011::b10c",
          "2a03:1b20:8:f011::b10d",
          "2a03:1b20:8:f011::b10e",
          "2a03:1b20:8:f011::b10f",
          "2a03:1b20:8:f011::b110",
          "2a03:1b20:8:f011::b111",
          "2a03:1b20:8:f011::b112",
          "2a03:1b20:8:f011::b113",
          "2a03:1b20:8:f011::b114",
          "2a03:1b20:8:f011::b115",
          "2a03:1b20:8:f011::b116",
          "2a03:1b20:8:f011::b117",
          "2a03:1b20:8:f011::b118",
          "2a03:1b20:8:f011::b119",
          "2a03:1b20:8:f011::b11a",
          "2a03:1b20:8:f011::b11b",
          "2a03:1b20:8:f011::b11c",
          "2a03:1b20:8:f011::b11d",
          "2a03:1b20:8:f011::b11e",
          "2a03:1b20:8:f011::b11f"
        ],
        "features": {
          "lwo": {}
        }
      },
      {
        "hostname": "dk-cph-wg-101",
        "location": "dk-cph",
        "active": false,
        "owned": true,
        "provider": "DataPacket",
        "stboot": true,
        "ipv4_addr_in": "149.88.109.72",
        "include_in_country": true,
        "weight": 100,
        "public_key": "CrS2Bd2IEVpPlg4DzHwfSCoqpNjrM35oiVdoUVKoxiY=",
        "ipv6_addr_in": "2a02:6ea0:470b:0:1::f001",
        "daita": true,
        "shadowsocks_extra_addr_in": [
          "158.173.46.12",
          "158.173.46.13",
          "158.173.46.14",
          "158.173.46.15",
          "158.173.46.16",
          "158.173.46.17",
          "158.173.46.18",
          "158.173.46.19",
          "158.173.46.20",
          "2a02:6ea0:470b:0:1::b002",
          "2a02:6ea0:470b:0:1::b003",
          "2a02:6ea0:470b:0:1::b004",
          "2a02:6ea0:470b:0:1::b005",
          "2a02:6ea0:470b:0:1::b006",
          "2a02:6ea0:470b:0:1::b007",
          "2a02:6ea0:470b:0:1::b008",
          "2a02:6ea0:470b:0:1::b009",
          "2a02:6ea0:470b:0:1::b00a",
          "2a02:6ea0:470b:0:1::b00b",
          "2a02:6ea0:470b:0:1::b00c",
          "2a02:6ea0:470b:0:1::b00d",
          "2a02:6ea0:470b:0:1::b00e",
          "2a02:6ea0:470b:0:1::b00f",
          "2a02:6ea0:470b:0:1::b010",
          "2a02:6ea0:470b:0:1::b011",
          "2a02:6ea0:470b:0:1::b012",
          "2a02:6ea0:470b:0:1::b013",
          "2a02:6ea0:470b:0:1::b014",
          "2a02:6ea0:470b:0:1::b015",
          "2a02:6ea0:470b:0:1::b016",
          "2a02:6ea0:470b:0:1::b017",
          "2a02:6ea0:470b:0:1::b018",
          "2a02:6ea0:470b:0:1::b019",
          "2a02:6ea0:470b:0:1::b01a",
          "2a02:6ea0:470b:0:1::b01b",
          "2a02:6ea0:470b:0:1::b01c",
          "2a02:6ea0:470b:0:1::b01d",
          "2a02:6ea0:470b:0:1::b01e",
          "2a02:6ea0:470b:0:1::b01f"
        ],
        "features": {
          "daita": {},
          "quic": {
            "addr_in": [
              "158.173.46.3",
              "158.173.46.4",
              "158.173.46.5",
              "158.173.46.6",
              "158.173.46.7",
              "158.173.46.8",
              "158.173.46.9",
              "158.173.46.10",
              "158.173.46.11",
              "2a02:6ea0:470b:0:1::c002",
              "2a02:6ea0:470b:0:1::c003",
              "2a02:6ea0:470b:0:1::c004",
              "2a02:6ea0:470b:0:1::c005",
              "2a02:6ea0:470b:0:1::c006",
              "2a02:6ea0:470b:0:1::c007",
              "2a02:6ea0:470b:0:1::c008",
              "2a02:6ea0:470b:0:1::c009",
              "2a02:6ea0:470b:0:1::c00a",
              "2a02:6ea0:470b:0:1::c00b",
              "2a02:6ea0:470b:0:1::c00c",
              "2a02:6ea0:470b:0:1::c00d",
              "2a02:6ea0:470b:0:1::c00e",
              "2a02:6ea0:470b:0:1::c00f",
              "2a02:6ea0:470b:0:1::c010",
              "2a02:6ea0:470b:0:1::c011",
              "2a02:6ea0:470b:0:1::c012",
              "2a02:6ea0:470b:0:1::c013",
              "2a02:6ea0:470b:0:1::c014",
              "2a02:6ea0:470b:0:1::c015",
              "2a02:6ea0:470b:0:1::c016",
              "2a02:6ea0:470b:0:1::c017",
              "2a02:6ea0:470b:0:1::c018",
              "2a02:6ea0:470b:0:1::c019",
              "2a02:6ea0:470b:0:1::c01a",
              "2a02:6ea0:470b:0:1::c01b",
              "2a02:6ea0:470b:0:1::c01c",
              "2a02:6ea0:470b:0:1::c01d",
              "2a02:6ea0:470b:0:1::c01e",
              "2a02:6ea0:470b:0:1::c01f"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "dk-cph-wg-101.blockerad.eu"
          }
        }
      },
      {
        "hostname": "dk-cph-wg-102",
        "location": "dk-cph",
        "active": true,
        "owned": true,
        "provider": "DataPacket",
        "stboot": true,
        "ipv4_addr_in": "149.88.109.73",
        "include_in_country": true,
        "weight": 100,
        "public_key": "oFSh/6OxGDc8LY+kCj9SNebPphDGM9UIeln0cseILxs=",
        "ipv6_addr_in": "2a02:6ea0:470b:0:2::f001",
        "shadowsocks_extra_addr_in": [
          "158.173.46.106",
          "158.173.46.107",
          "158.173.46.108",
          "158.173.46.109",
          "158.173.46.110",
          "158.173.46.111",
          "158.173.46.112",
          "158.173.46.113",
          "158.173.46.114",
          "158.173.46.115",
          "158.173.46.116",
          "158.173.46.117",
          "2a02:6ea0:470b:0:2::b002",
          "2a02:6ea0:470b:0:2::b003",
          "2a02:6ea0:470b:0:2::b004",
          "2a02:6ea0:470b:0:2::b005",
          "2a02:6ea0:470b:0:2::b006",
          "2a02:6ea0:470b:0:2::b007",
          "2a02:6ea0:470b:0:2::b008",
          "2a02:6ea0:470b:0:2::b009",
          "2a02:6ea0:470b:0:2::b00a",
          "2a02:6ea0:470b:0:2::b00b",
          "2a02:6ea0:470b:0:2::b00c",
          "2a02:6ea0:470b:0:2::b00d",
          "2a02:6ea0:470b:0:2::b00e",
          "2a02:6ea0:470b:0:2::b00f",
          "2a02:6ea0:470b:0:2::b010",
          "2a02:6ea0:470b:0:2::b011",
          "2a02:6ea0:470b:0:2::b012",
          "2a02:6ea0:470b:0:2::b013",
          "2a02:6ea0:470b:0:2::b014",
          "2a02:6ea0:470b:0:2::b015",
          "2a02:6ea0:470b:0:2::b016",
          "2a02:6ea0:470b:0:2::b017",
          "2a02:6ea0:470b:0:2::b018",
          "2a02:6ea0:470b:0:2::b019",
          "2a02:6ea0:470b:0:2::b01a",
          "2a02:6ea0:470b:0:2::b01b",
          "2a02:6ea0:470b:0:2::b01c",
          "2a02:6ea0:470b:0:2::b01d",
          "2a02:6ea0:470b:0:2::b01e",
          "2a02:6ea0:470b:0:2::b01f"
        ],
        "features": {
          "lwo": {},
          "quic": {
            "addr_in": [
              "158.173.46.94",
              "158.173.46.95",
              "158.173.46.96",
              "158.173.46.97",
              "158.173.46.98",
              "158.173.46.99",
              "158.173.46.100",
              "158.173.46.101",
              "158.173.46.102",
              "158.173.46.103",
              "158.173.46.104",
              "158.173.46.105",
              "2a02:6ea0:470b:0:2::c002",
              "2a02:6ea0:470b:0:2::c003",
              "2a02:6ea0:470b:0:2::c004",
              "2a02:6ea0:470b:0:2::c005",
              "2a02:6ea0:470b:0:2::c006",
              "2a02:6ea0:470b:0:2::c007",
              "2a02:6ea0:470b:0:2::c008",
              "2a02:6ea0:470b:0:2::c009",
              "2a02:6ea0:470b:0:2::c00a",
              "2a02:6ea0:470b:0:2::c00b",
              "2a02:6ea0:470b:0:2::c00c",
              "2a02:6ea0:470b:0:2::c00d",
              "2a02:6ea0:470b:0:2::c00e",
              "2a02:6ea0:470b:0:2::c00f",
              "2a02:6ea0:470b:0:2::c010",
              "2a02:6ea0:470b:0:2::c011",
              "2a02:6ea0:470b:0:2::c012",
              "2a02:6ea0:470b:0:2::c013",
              "2a02:6ea0:470b:0:2::c014",
              "2a02:6ea0:470b:0:2::c015",
              "2a02:6ea0:470b:0:2::c016",
              "2a02:6ea0:470b:0:2::c017",
              "2a02:6ea0:470b:0:2::c018",
              "2a02:6ea0:470b:0:2::c019",
              "2a02:6ea0:470b:0:2::c01a",
              "2a02:6ea0:470b:0:2::c01b",
              "2a02:6ea0:470b:0:2::c01c",
              "2a02:6ea0:470b:0:2::c01d",
              "2a02:6ea0:470b:0:2::c01e",
              "2a02:6ea0:470b:0:2::c01f"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "dk-cph-wg-102.blockerad.eu"
          }
        }
      },
      {
        "hostname": "dk-cph-wg-103",
        "location": "dk-cph",
        "active": false,
        "owned": true,
        "provider": "DataPacket",
        "stboot": true,
        "ipv4_addr_in": "149.88.109.74",
        "include_in_country": true,
        "weight": 100,
        "public_key": "qwH+UVu3UKbsYiHsvuXmdbvDUs/5pMV6nSCV5eNk7Q8=",
        "ipv6_addr_in": "2a02:6ea0:470b:0:3::f001",
        "daita": true,
        "shadowsocks_extra_addr_in": [
          "158.173.46.181",
          "158.173.46.182",
          "158.173.46.183",
          "158.173.46.184",
          "158.173.46.185",
          "158.173.46.186",
          "158.173.46.187",
          "158.173.46.188",
          "158.173.46.189",
          "2a02:6ea0:470b:0:3::b002",
          "2a02:6ea0:470b:0:3::b003",
          "2a02:6ea0:470b:0:3::b004",
          "2a02:6ea0:470b:0:3::b005",
          "2a02:6ea0:470b:0:3::b006",
          "2a02:6ea0:470b:0:3::b007",
          "2a02:6ea0:470b:0:3::b008",
          "2a02:6ea0:470b:0:3::b009",
          "2a02:6ea0:470b:0:3::b00a",
          "2a02:6ea0:470b:0:3::b00b",
          "2a02:6ea0:470b:0:3::b00c",
          "2a02:6ea0:470b:0:3::b00d",
          "2a02:6ea0:470b:0:3::b00e",
          "2a02:6ea0:470b:0:3::b00f",
          "2a02:6ea0:470b:0:3::b010",
          "2a02:6ea0:470b:0:3::b011",
          "2a02:6ea0:470b:0:3::b012",
          "2a02:6ea0:470b:0:3::b013",
          "2a02:6ea0:470b:0:3::b014",
          "2a02:6ea0:470b:0:3::b015",
          "2a02:6ea0:470b:0:3::b016",
          "2a02:6ea0:470b:0:3::b017",
          "2a02:6ea0:470b:0:3::b018",
          "2a02:6ea0:470b:0:3::b019",
          "2a02:6ea0:470b:0:3::b01a",
          "2a02:6ea0:470b:0:3::b01b",
          "2a02:6ea0:470b:0:3::b01c",
          "2a02:6ea0:470b:0:3::b01d",
          "2a02:6ea0:470b:0:3::b01e",
          "2a02:6ea0:470b:0:3::b01f"
        ],
        "features": {
          "daita": {},
          "lwo": {},
          "quic": {
            "addr_in": [
              "158.173.46.172",
              "158.173.46.173",
              "158.173.46.174",
              "158.173.46.175",
              "158.173.46.176",
              "158.173.46.177",
              "158.173.46.178",
              "158.173.46.179",
              "158.173.46.180",
              "2a02:6ea0:470b:0:3::c002",
              "2a02:6ea0:470b:0:3::c003",
              "2a02:6ea0:470b:0:3::c004",
              "2a02:6ea0:470b:0:3::c005",
              "2a02:6ea0:470b:0:3::c006",
              "2a02:6ea0:470b:0:3::c007",
              "2a02:6ea0:470b:0:3::c008",
              "2a02:6ea0:470b:0:3::c009",
              "2a02:6ea0:470b:0:3::c00a",
              "2a02:6ea0:470b:0:3::c00b",
              "2a02:6ea0:470b:0:3::c00c",
              "2a02:6ea0:470b:0:3::c00d",
              "2a02:6ea0:470b:0:3::c00e",
              "2a02:6ea0:470b:0:3::c00f",
              "2a02:6ea0:470b:0:3::c010",
              "2a02:6ea0:470b:0:3::c011",
              "2a02:6ea0:470b:0:3::c012",
              "2a02:6ea0:470b:0:3::c013",
              "2a02:6ea0:470b:0:3::c014",
              "2a02:6ea0:470b:0:3::c015",
              "2a02:6ea0:470b:0:3::c016",
              "2a02:6ea0:470b:0:3::c017",
              "2a02:6ea0:470b:0:3::c018",
              "2a02:6ea0:470b:0:3::c019",
              "2a02:6ea0:470b:0:3::c01a",
              "2a02:6ea0:470b:0:3::c01b",
              "2a02:6ea0:470b:0:3::c01c",
              "2a02:6ea0:470b:0:3::c01d",
              "2a02:6ea0:470b:0:3::c01e",
              "2a02:6ea0:470b:0:3::c01f"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "dk-cph-wg-103.blockerad.eu"
          }
        }
      },
      {
        "hostname": "dk-cph-wg-401",
        "location": "dk-cph",
        "active": true,
        "owned": false,
        "provider": "M247",
        "stboot": true,
        "ipv4_addr_in": "146.70.197.194",
        "include_in_country": true,
        "weight": 100,
        "public_key": "Jjml2TSqKlgzW6UzPiJszaun743QYpyl5jQk8UOQYg0=",
        "ipv6_addr_in": "2001:ac8:37:97::f001"
      },
      {
        "hostname": "dk-cph-wg-402",
        "location": "dk-cph",
        "active": true,
        "owned": false,
        "provider": "M247",
        "stboot": true,
        "ipv4_addr_in": "146.70.197.130",
        "include_in_country": true,
        "weight": 100,
        "public_key": "ML0NcFPqy+x+ZJg7y9vfh77hXAOtgueIqp1j+CJVrXM=",
        "ipv6_addr_in": "2001:ac8:37:96::f001"
      },
      {
        "hostname": "ee-tll-wg-001",
        "location": "ee-tll",
        "active": true,
        "owned": false,
        "provider": "xtom",
        "stboot": true,
        "ipv4_addr_in": "194.127.167.67",
        "include_in_country": true,
        "weight": 100,
        "public_key": "bdq37KtfoG1Tm7yQcfitdRyGeZOn/c7PwLN+LgG/6nA=",
        "ipv6_addr_in": "2a07:d880:2::a01f"
      },
      {
        "hostname": "ee-tll-wg-002",
        "location": "ee-tll",
        "active": true,
        "owned": false,
        "provider": "xtom",
        "stboot": true,
        "ipv4_addr_in": "194.127.167.87",
        "include_in_country": true,
        "weight": 100,
        "public_key": "vqGmmcERr/PAKDzy6Dxax8g4150rC93kmKYabZuAzws=",
        "ipv6_addr_in": "2a07:d880:2::a02f"
      },
      {
        "hostname": "ee-tll-wg-003",
        "location": "ee-tll",
        "active": true,
        "owned": false,
        "provider": "xtom",
        "stboot": true,
        "ipv4_addr_in": "194.127.167.107",
        "include_in_country": true,
        "weight": 100,
        "public_key": "+8dUgpD7YA4wMPnRQkO7EI7AeYd30QPMKh/hOaaGIXY=",
        "ipv6_addr_in": "2a07:d880:2::a03f"
      },
      {
        "hostname": "es-bcn-wg-001",
        "location": "es-bcn",
        "active": true,
        "owned": false,
        "provider": "HostRoyale",
        "stboot": true,
        "ipv4_addr_in": "185.188.61.195",
        "include_in_country": true,
        "weight": 100,
        "public_key": "asbfbY0oP07dBdmVNDSuO3o5rbkGnR56PkXTGXO7YFg=",
        "ipv6_addr_in": "2a06:3040:2:210::f001"
      },
      {
        "hostname": "es-bcn-wg-002",
        "location": "es-bcn",
        "active": true,
        "owned": false,
        "provider": "HostRoyale",
        "stboot": true,
        "ipv4_addr_in": "185.188.61.225",
        "include_in_country": true,
        "weight": 100,
        "public_key": "SoTWu5Cf7JSfaPVftMrTVzeyICGc7oc+ODl6GfqzUHA=",
        "ipv6_addr_in": "2a06:3040:2:210::f101",
        "features": {
          "lwo": {}
        }
      },
      {
        "hostname": "es-bcn-wg-101",
        "location": "es-bcn",
        "active": true,
        "owned": false,
        "provider": "M247",
        "stboot": true,
        "ipv4_addr_in": "185.253.99.30",
        "include_in_country": true,
        "weight": 100,
        "public_key": "TQDQ/SUW7pme5aRWFT4ugr9YAABS/uwJNZgqYKTM+iU=",
        "ipv6_addr_in": "2001:ac8:17:20::f001",
        "features": {
          "quic": {
            "addr_in": [
              "146.70.22.130",
              "2001:ac8:17:20::f00a"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "es-bcn-wg-101.blockerad.eu"
          }
        }
      },
      {
        "hostname": "es-bcn-wg-102",
        "location": "es-bcn",
        "active": true,
        "owned": false,
        "provider": "M247",
        "stboot": true,
        "ipv4_addr_in": "185.253.99.98",
        "include_in_country": true,
        "weight": 100,
        "public_key": "GqDjspXPQWM3V5nh1M9IhnxgiIwctvxuFyj73oYTRwo=",
        "ipv6_addr_in": "2001:ac8:17:20::f101",
        "features": {
          "quic": {
            "addr_in": [
              "146.70.22.194",
              "2001:ac8:17:20::f10a"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "es-bcn-wg-102.blockerad.eu"
          }
        }
      },
      {
        "hostname": "es-mad-wg-101",
        "location": "es-mad",
        "active": true,
        "owned": false,
        "provider": "DataPacket",
        "stboot": true,
        "ipv4_addr_in": "45.134.213.194",
        "include_in_country": true,
        "weight": 100,
        "public_key": "oPpPeyiQhUYqtOxwR387dmFfII8OK5LX2RPyns1rx2U=",
        "ipv6_addr_in": "2a02:6ea0:c318:1::a06f",
        "features": {
          "lwo": {}
        }
      },
      {
        "hostname": "es-mad-wg-102",
        "location": "es-mad",
        "active": true,
        "owned": false,
        "provider": "DataPacket",
        "stboot": true,
        "ipv4_addr_in": "45.134.213.207",
        "include_in_country": true,
        "weight": 100,
        "public_key": "1Wo/cQeVHX2q9k95nxN+48lgkGLsPQ+uesRb/9XdY1Y=",
        "ipv6_addr_in": "2a02:6ea0:c318:2::a07f"
      },
      {
        "hostname": "es-mad-wg-201",
        "location": "es-mad",
        "active": true,
        "owned": false,
        "provider": "M247",
        "stboot": true,
        "ipv4_addr_in": "146.70.128.194",
        "include_in_country": true,
        "weight": 100,
        "public_key": "LyO4Xs1eV8JwFr63a1FRnKboQn2Tu/oeMzHhbr7Y6GU=",
        "ipv6_addr_in": "2001:ac8:23:85::a01f"
      },
      {
        "hostname": "es-mad-wg-202",
        "location": "es-mad",
        "active": true,
        "owned": false,
        "provider": "M247",
        "stboot": true,
        "ipv4_addr_in": "146.70.128.226",
        "include_in_country": true,
        "weight": 100,
        "public_key": "iehXacO91FbBqni2IFxedEYPlW2Wvvt9GtRPPPMo9zc=",
        "ipv6_addr_in": "2001:ac8:23:86::a02f"
      },
      {
        "hostname": "es-vlc-wg-001",
        "location": "es-vlc",
        "active": true,
        "owned": false,
        "provider": "HostRoyale",
        "stboot": true,
        "ipv4_addr_in": "193.19.207.195",
        "include_in_country": true,
        "weight": 100,
        "public_key": "aEObX8ThiHcN/Y40UqY8dXaGMJsVQUWhrEphbpuQRkw=",
        "ipv6_addr_in": "2a06:3040:3:210::f001"
      },
      {
        "hostname": "es-vlc-wg-002",
        "location": "es-vlc",
        "active": true,
        "owned": false,
        "provider": "HostRoyale",
        "stboot": true,
        "ipv4_addr_in": "193.19.207.225",
        "include_in_country": true,
        "weight": 100,
        "public_key": "JEDqyG7iGjy/rYsE/9H7y0Sz8Sl+KWYYUvkPG7NnCjk=",
        "ipv6_addr_in": "2a06:3040:3:210::f101"
      },
      {
        "hostname": "fi-hel-wg-001",
        "location": "fi-hel",
        "active": true,
        "owned": true,
        "provider": "Creanova",
        "stboot": true,
        "ipv4_addr_in": "185.204.1.203",
        "include_in_country": true,
        "weight": 100,
        "public_key": "veLqpZazR9j/Ol2G8TfrO32yEhc1i543MCN8rpy1FBA=",
        "ipv6_addr_in": "2a0c:f040:0:2790::a01f",
        "features": {
          "quic": {
            "addr_in": [
              "185.77.218.49",
              "2a0c:f040:0:2790::d099"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "fi-hel-wg-001.blockerad.eu"
          }
        }
      },
      {
        "hostname": "fi-hel-wg-002",
        "location": "fi-hel",
        "active": true,
        "owned": true,
        "provider": "Creanova",
        "stboot": true,
        "ipv4_addr_in": "185.204.1.211",
        "include_in_country": true,
        "weight": 25,
        "public_key": "8BbP3GS01dGkN5ENk1Rgedxfd80friyVOABrdMgD3EY=",
        "ipv6_addr_in": "2a0c:f040:0:2790::a02f",
        "shadowsocks_extra_addr_in": [
          "2a0c:f040:0:2790::b201",
          "2a0c:f040:0:2790::b202",
          "2a0c:f040:0:2790::b203",
          "2a0c:f040:0:2790::b204",
          "2a0c:f040:0:2790::b205",
          "2a0c:f040:0:2790::b206",
          "2a0c:f040:0:2790::b207",
          "2a0c:f040:0:2790::b208",
          "2a0c:f040:0:2790::b209",
          "2a0c:f040:0:2790::b20a",
          "2a0c:f040:0:2790::b20b",
          "2a0c:f040:0:2790::b20c",
          "2a0c:f040:0:2790::b20d",
          "2a0c:f040:0:2790::b20e",
          "2a0c:f040:0:2790::b20f"
        ],
        "features": {
          "quic": {
            "addr_in": [
              "185.77.218.84",
              "2a0c:f040:0:2790::c201",
              "2a0c:f040:0:2790::c202",
              "2a0c:f040:0:2790::c203",
              "2a0c:f040:0:2790::c204",
              "2a0c:f040:0:2790::c205",
              "2a0c:f040:0:2790::c206",
              "2a0c:f040:0:2790::c207",
              "2a0c:f040:0:2790::c208",
              "2a0c:f040:0:2790::c209",
              "2a0c:f040:0:2790::c20a",
              "2a0c:f040:0:2790::c20b",
              "2a0c:f040:0:2790::c20c",
              "2a0c:f040:0:2790::c20d",
              "2a0c:f040:0:2790::c20e",
              "2a0c:f040:0:2790::c20f"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "fi-hel-wg-002.blockerad.eu"
          }
        }
      },
      {
        "hostname": "fi-hel-wg-003",
        "location": "fi-hel",
        "active": true,
        "owned": true,
        "provider": "Creanova",
        "stboot": true,
        "ipv4_addr_in": "185.204.1.219",
        "include_in_country": true,
        "weight": 25,
        "public_key": "FKodo9V6BehkNphL+neI0g4/G/cjbZyYhoptSWf3Si4=",
        "ipv6_addr_in": "2a0c:f040:0:2790::a03f",
        "shadowsocks_extra_addr_in": [
          "2a0c:f040:0:2790::b31",
          "2a0c:f040:0:2790::b32",
          "2a0c:f040:0:2790::b33",
          "2a0c:f040:0:2790::b34",
          "2a0c:f040:0:2790::b35",
          "2a0c:f040:0:2790::b36",
          "2a0c:f040:0:2790::b37",
          "2a0c:f040:0:2790::b38",
          "2a0c:f040:0:2790::b39"
        ],
        "features": {
          "quic": {
            "addr_in": [
              "185.77.218.125",
              "2a0c:f040:0:2790::c31",
              "2a0c:f040:0:2790::c32",
              "2a0c:f040:0:2790::c33",
              "2a0c:f040:0:2790::c34",
              "2a0c:f040:0:2790::c35",
              "2a0c:f040:0:2790::c36",
              "2a0c:f040:0:2790::c37",
              "2a0c:f040:0:2790::c38",
              "2a0c:f040:0:2790::c39",
              "2a0c:f040:0:2790::c398"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "fi-hel-wg-003.blockerad.eu"
          }
        }
      },
      {
        "hostname": "fi-hel-wg-101",
        "location": "fi-hel",
        "active": true,
        "owned": true,
        "provider": "Blix",
        "stboot": true,
        "ipv4_addr_in": "193.138.7.137",
        "include_in_country": true,
        "weight": 100,
        "public_key": "2S3G7Sm9DVG6+uJtlDu4N6ed5V97sTbA5dCSkUelWyk=",
        "ipv6_addr_in": "2a02:ed04:3581:1::f001",
        "features": {
          "lwo": {},
          "quic": {
            "addr_in": [
              "193.138.7.156"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "fi-hel-wg-101.blockerad.eu"
          }
        }
      },
      {
        "hostname": "fi-hel-wg-102",
        "location": "fi-hel",
        "active": true,
        "owned": true,
        "provider": "Blix",
        "stboot": true,
        "ipv4_addr_in": "193.138.7.157",
        "include_in_country": true,
        "weight": 100,
        "public_key": "xeHVhXxyyFqUEE+nsu5Tzd/t9en+++4fVFcSFngpcAU=",
        "ipv6_addr_in": "2a02:ed04:3581:2::f001"
      },
      {
        "hostname": "fi-hel-wg-103",
        "location": "fi-hel",
        "active": true,
        "owned": true,
        "provider": "Blix",
        "stboot": true,
        "ipv4_addr_in": "193.138.7.177",
        "include_in_country": true,
        "weight": 100,
        "public_key": "Mlvu14bSD6jb7ajH/CiJ/IO8W+spB8H6VmdGkFGOcUQ=",
        "ipv6_addr_in": "2a02:ed04:3581:3::f001"
      },
      {
        "hostname": "fi-hel-wg-104",
        "location": "fi-hel",
        "active": true,
        "owned": true,
        "provider": "Blix",
        "stboot": true,
        "ipv4_addr_in": "193.138.7.197",
        "include_in_country": true,
        "weight": 100,
        "public_key": "keRQGHUbYP2qgDTbYqOsI9byfNb0LOpTZ/KdC67cJiA=",
        "ipv6_addr_in": "2a02:ed04:3581:4::f001"
      },
      {
        "hostname": "fi-hel-wg-201",
        "location": "fi-hel",
        "active": true,
        "owned": true,
        "provider": "31173",
        "stboot": true,
        "ipv4_addr_in": "185.65.133.5",
        "include_in_country": true,
        "weight": 500,
        "public_key": "u+Ir9bnz8PtwXoJGQXvCxz6a+1NChEbBIox8KdWarxk=",
        "ipv6_addr_in": "2a03:1b20:d:f011:1::f001",
        "shadowsocks_extra_addr_in": [
          "185.65.133.7",
          "2a03:1b20:d:f011:1::b002",
          "2a03:1b20:d:f011:1::b003",
          "2a03:1b20:d:f011:1::b004",
          "2a03:1b20:d:f011:1::b005",
          "2a03:1b20:d:f011:1::b006",
          "2a03:1b20:d:f011:1::b007",
          "2a03:1b20:d:f011:1::b008",
          "2a03:1b20:d:f011:1::b009",
          "2a03:1b20:d:f011:1::b00a",
          "2a03:1b20:d:f011:1::b00b",
          "2a03:1b20:d:f011:1::b00c",
          "2a03:1b20:d:f011:1::b00d",
          "2a03:1b20:d:f011:1::b00e",
          "2a03:1b20:d:f011:1::b00f",
          "2a03:1b20:d:f011:1::b010",
          "2a03:1b20:d:f011:1::b011",
          "2a03:1b20:d:f011:1::b012",
          "2a03:1b20:d:f011:1::b013",
          "2a03:1b20:d:f011:1::b014",
          "2a03:1b20:d:f011:1::b015",
          "2a03:1b20:d:f011:1::b016",
          "2a03:1b20:d:f011:1::b017",
          "2a03:1b20:d:f011:1::b018",
          "2a03:1b20:d:f011:1::b019",
          "2a03:1b20:d:f011:1::b01a",
          "2a03:1b20:d:f011:1::b01b",
          "2a03:1b20:d:f011:1::b01c",
          "2a03:1b20:d:f011:1::b01d",
          "2a03:1b20:d:f011:1::b01e",
          "2a03:1b20:d:f011:1::b01f",
          "91.206.168.37",
          "91.206.168.38",
          "91.206.168.39",
          "91.206.168.40",
          "91.206.168.41",
          "91.206.168.42",
          "91.206.168.43",
          "91.206.168.44",
          "91.206.168.45",
          "91.206.168.46",
          "91.206.168.47",
          "91.206.168.48",
          "91.206.168.49",
          "91.206.168.50",
          "91.206.168.51",
          "91.206.168.52",
          "91.206.168.53",
          "91.206.168.54",
          "91.206.168.55",
          "91.206.168.56",
          "91.206.168.57",
          "91.206.168.58",
          "91.206.168.59",
          "91.206.168.60",
          "91.206.168.61",
          "91.206.168.62",
          "91.206.168.63",
          "91.206.168.64",
          "91.206.168.65",
          "91.206.168.66",
          "91.206.168.67",
          "91.206.168.68",
          "91.206.168.69",
          "91.206.168.70",
          "91.206.168.71",
          "91.206.168.72",
          "91.206.168.73",
          "91.206.168.74",
          "91.206.168.75",
          "91.206.168.76",
          "91.206.168.77",
          "91.206.168.78",
          "91.206.168.79"
        ],
        "features": {
          "lwo": {},
          "quic": {
            "addr_in": [
              "185.65.133.8",
              "2a03:1b20:d:f011:1::c002",
              "2a03:1b20:d:f011:1::c003",
              "2a03:1b20:d:f011:1::c004",
              "2a03:1b20:d:f011:1::c005",
              "2a03:1b20:d:f011:1::c006",
              "2a03:1b20:d:f011:1::c007",
              "2a03:1b20:d:f011:1::c008",
              "2a03:1b20:d:f011:1::c009",
              "2a03:1b20:d:f011:1::c00a",
              "2a03:1b20:d:f011:1::c00b",
              "2a03:1b20:d:f011:1::c00c",
              "2a03:1b20:d:f011:1::c00d",
              "2a03:1b20:d:f011:1::c00e",
              "2a03:1b20:d:f011:1::c00f",
              "2a03:1b20:d:f011:1::c010",
              "2a03:1b20:d:f011:1::c011",
              "2a03:1b20:d:f011:1::c012",
              "2a03:1b20:d:f011:1::c013",
              "2a03:1b20:d:f011:1::c014",
              "2a03:1b20:d:f011:1::c015",
              "2a03:1b20:d:f011:1::c016",
              "2a03:1b20:d:f011:1::c017",
              "2a03:1b20:d:f011:1::c018",
              "2a03:1b20:d:f011:1::c019",
              "2a03:1b20:d:f011:1::c01a",
              "2a03:1b20:d:f011:1::c01b",
              "2a03:1b20:d:f011:1::c01c",
              "2a03:1b20:d:f011:1::c01d",
              "2a03:1b20:d:f011:1::c01e",
              "2a03:1b20:d:f011:1::c01f",
              "91.206.168.11",
              "91.206.168.12",
              "91.206.168.13",
              "91.206.168.14",
              "91.206.168.15",
              "91.206.168.16",
              "91.206.168.17",
              "91.206.168.18",
              "91.206.168.19",
              "91.206.168.20",
              "91.206.168.21",
              "91.206.168.22",
              "91.206.168.23",
              "91.206.168.24",
              "91.206.168.25",
              "91.206.168.26",
              "91.206.168.27",
              "91.206.168.28",
              "91.206.168.29",
              "91.206.168.30",
              "91.206.168.31",
              "91.206.168.32",
              "91.206.168.33",
              "91.206.168.34",
              "91.206.168.35",
              "91.206.168.36"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "fi-hel-wg-201.blockerad.eu"
          }
        }
      },
      {
        "hostname": "fi-hel-wg-202",
        "location": "fi-hel",
        "active": true,
        "owned": true,
        "provider": "31173",
        "stboot": true,
        "ipv4_addr_in": "185.65.133.85",
        "include_in_country": true,
        "weight": 500,
        "public_key": "hAbVKL5Q0285gJ28nMSfztw7/FXJb+cxiKD2NMgPpTM=",
        "ipv6_addr_in": "2a03:1b20:d:f011:2::f001",
        "shadowsocks_extra_addr_in": [
          "185.65.133.87",
          "2a03:1b20:d:f011:2::b002",
          "2a03:1b20:d:f011:2::b003",
          "2a03:1b20:d:f011:2::b004",
          "2a03:1b20:d:f011:2::b005",
          "2a03:1b20:d:f011:2::b006",
          "2a03:1b20:d:f011:2::b007",
          "2a03:1b20:d:f011:2::b008",
          "2a03:1b20:d:f011:2::b009",
          "2a03:1b20:d:f011:2::b00a",
          "2a03:1b20:d:f011:2::b00b",
          "2a03:1b20:d:f011:2::b00c",
          "2a03:1b20:d:f011:2::b00d",
          "2a03:1b20:d:f011:2::b00e",
          "2a03:1b20:d:f011:2::b00f",
          "2a03:1b20:d:f011:2::b010",
          "2a03:1b20:d:f011:2::b011",
          "2a03:1b20:d:f011:2::b012",
          "2a03:1b20:d:f011:2::b013",
          "2a03:1b20:d:f011:2::b014",
          "2a03:1b20:d:f011:2::b015",
          "2a03:1b20:d:f011:2::b016",
          "2a03:1b20:d:f011:2::b017",
          "2a03:1b20:d:f011:2::b018",
          "2a03:1b20:d:f011:2::b019",
          "2a03:1b20:d:f011:2::b01a",
          "2a03:1b20:d:f011:2::b01b",
          "2a03:1b20:d:f011:2::b01c",
          "2a03:1b20:d:f011:2::b01d",
          "2a03:1b20:d:f011:2::b01e",
          "2a03:1b20:d:f011:2::b01f",
          "91.206.168.126",
          "91.206.168.127",
          "91.206.168.128",
          "91.206.168.129",
          "91.206.168.130",
          "91.206.168.131",
          "91.206.168.132",
          "91.206.168.133",
          "91.206.168.134",
          "91.206.168.135",
          "91.206.168.136",
          "91.206.168.137",
          "91.206.168.138",
          "91.206.168.139",
          "91.206.168.140",
          "91.206.168.141",
          "91.206.168.142",
          "91.206.168.143",
          "91.206.168.144",
          "91.206.168.145",
          "91.206.168.146",
          "91.206.168.147",
          "91.206.168.148",
          "91.206.168.149",
          "91.206.168.150",
          "91.206.168.151",
          "91.206.168.152",
          "91.206.168.153",
          "91.206.168.154",
          "91.206.168.155",
          "91.206.168.156",
          "91.206.168.157",
          "91.206.168.158",
          "91.206.168.159"
        ],
        "features": {
          "lwo": {},
          "quic": {
            "addr_in": [
              "185.65.133.88",
              "2a03:1b20:d:f011:2::c002",
              "2a03:1b20:d:f011:2::c003",
              "2a03:1b20:d:f011:2::c004",
              "2a03:1b20:d:f011:2::c005",
              "2a03:1b20:d:f011:2::c006",
              "2a03:1b20:d:f011:2::c007",
              "2a03:1b20:d:f011:2::c008",
              "2a03:1b20:d:f011:2::c009",
              "2a03:1b20:d:f011:2::c00a",
              "2a03:1b20:d:f011:2::c00b",
              "2a03:1b20:d:f011:2::c00c",
              "2a03:1b20:d:f011:2::c00d",
              "2a03:1b20:d:f011:2::c00e",
              "2a03:1b20:d:f011:2::c00f",
              "2a03:1b20:d:f011:2::c010",
              "2a03:1b20:d:f011:2::c011",
              "2a03:1b20:d:f011:2::c012",
              "2a03:1b20:d:f011:2::c013",
              "2a03:1b20:d:f011:2::c014",
              "2a03:1b20:d:f011:2::c015",
              "2a03:1b20:d:f011:2::c016",
              "2a03:1b20:d:f011:2::c017",
              "2a03:1b20:d:f011:2::c018",
              "2a03:1b20:d:f011:2::c019",
              "2a03:1b20:d:f011:2::c01a",
              "2a03:1b20:d:f011:2::c01b",
              "2a03:1b20:d:f011:2::c01c",
              "2a03:1b20:d:f011:2::c01d",
              "2a03:1b20:d:f011:2::c01e",
              "2a03:1b20:d:f011:2::c01f",
              "91.206.168.90",
              "91.206.168.91",
              "91.206.168.92",
              "91.206.168.93",
              "91.206.168.94",
              "91.206.168.95",
              "91.206.168.96",
              "91.206.168.97",
              "91.206.168.98",
              "91.206.168.99",
              "91.206.168.100",
              "91.206.168.101",
              "91.206.168.102",
              "91.206.168.103",
              "91.206.168.104",
              "91.206.168.105",
              "91.206.168.106",
              "91.206.168.107",
              "91.206.168.108",
              "91.206.168.109",
              "91.206.168.110",
              "91.206.168.111",
              "91.206.168.112",
              "91.206.168.113",
              "91.206.168.114",
              "91.206.168.115",
              "91.206.168.116",
              "91.206.168.117",
              "91.206.168.118",
              "91.206.168.119",
              "91.206.168.120",
              "91.206.168.121",
              "91.206.168.122",
              "91.206.168.123",
              "91.206.168.124",
              "91.206.168.125"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "fi-hel-wg-202.blockerad.eu"
          }
        }
      },
      {
        "hostname": "fi-hel-wg-203",
        "location": "fi-hel",
        "active": true,
        "owned": true,
        "provider": "31173",
        "stboot": true,
        "ipv4_addr_in": "185.65.133.165",
        "include_in_country": true,
        "weight": 500,
        "public_key": "Ck25URxG+bxlgfJVZ0A6wm7xddltSu5t1yig3CgKBDM=",
        "ipv6_addr_in": "2a03:1b20:d:f011:3::f001",
        "shadowsocks_extra_addr_in": [
          "185.65.133.167",
          "2a03:1b20:d:f011:3::b002",
          "2a03:1b20:d:f011:3::b003",
          "2a03:1b20:d:f011:3::b004",
          "2a03:1b20:d:f011:3::b005",
          "2a03:1b20:d:f011:3::b006",
          "2a03:1b20:d:f011:3::b007",
          "2a03:1b20:d:f011:3::b008",
          "2a03:1b20:d:f011:3::b009",
          "2a03:1b20:d:f011:3::b00a",
          "2a03:1b20:d:f011:3::b00b",
          "2a03:1b20:d:f011:3::b00c",
          "2a03:1b20:d:f011:3::b00d",
          "2a03:1b20:d:f011:3::b00e",
          "2a03:1b20:d:f011:3::b00f",
          "2a03:1b20:d:f011:3::b010",
          "2a03:1b20:d:f011:3::b011",
          "2a03:1b20:d:f011:3::b012",
          "2a03:1b20:d:f011:3::b013",
          "2a03:1b20:d:f011:3::b014",
          "2a03:1b20:d:f011:3::b015",
          "2a03:1b20:d:f011:3::b016",
          "2a03:1b20:d:f011:3::b017",
          "2a03:1b20:d:f011:3::b018",
          "2a03:1b20:d:f011:3::b019",
          "2a03:1b20:d:f011:3::b01a",
          "2a03:1b20:d:f011:3::b01b",
          "2a03:1b20:d:f011:3::b01c",
          "2a03:1b20:d:f011:3::b01d",
          "2a03:1b20:d:f011:3::b01e",
          "2a03:1b20:d:f011:3::b01f",
          "91.206.168.206",
          "91.206.168.207",
          "91.206.168.208",
          "91.206.168.209",
          "91.206.168.210",
          "91.206.168.211",
          "91.206.168.212",
          "91.206.168.213",
          "91.206.168.214",
          "91.206.168.215",
          "91.206.168.216",
          "91.206.168.217",
          "91.206.168.218",
          "91.206.168.219",
          "91.206.168.220",
          "91.206.168.221",
          "91.206.168.222",
          "91.206.168.223",
          "91.206.168.224",
          "91.206.168.225",
          "91.206.168.226",
          "91.206.168.227",
          "91.206.168.228",
          "91.206.168.229",
          "91.206.168.230",
          "91.206.168.231",
          "91.206.168.232",
          "91.206.168.233",
          "91.206.168.234",
          "91.206.168.235",
          "91.206.168.236",
          "91.206.168.237",
          "91.206.168.238",
          "91.206.168.239"
        ],
        "features": {
          "lwo": {},
          "quic": {
            "addr_in": [
              "185.65.133.168",
              "2a03:1b20:d:f011:3::c002",
              "2a03:1b20:d:f011:3::c003",
              "2a03:1b20:d:f011:3::c004",
              "2a03:1b20:d:f011:3::c005",
              "2a03:1b20:d:f011:3::c006",
              "2a03:1b20:d:f011:3::c007",
              "2a03:1b20:d:f011:3::c008",
              "2a03:1b20:d:f011:3::c009",
              "2a03:1b20:d:f011:3::c00a",
              "2a03:1b20:d:f011:3::c00b",
              "2a03:1b20:d:f011:3::c00c",
              "2a03:1b20:d:f011:3::c00d",
              "2a03:1b20:d:f011:3::c00e",
              "2a03:1b20:d:f011:3::c00f",
              "2a03:1b20:d:f011:3::c010",
              "2a03:1b20:d:f011:3::c011",
              "2a03:1b20:d:f011:3::c012",
              "2a03:1b20:d:f011:3::c013",
              "2a03:1b20:d:f011:3::c014",
              "2a03:1b20:d:f011:3::c015",
              "2a03:1b20:d:f011:3::c016",
              "2a03:1b20:d:f011:3::c017",
              "2a03:1b20:d:f011:3::c018",
              "2a03:1b20:d:f011:3::c019",
              "2a03:1b20:d:f011:3::c01a",
              "2a03:1b20:d:f011:3::c01b",
              "2a03:1b20:d:f011:3::c01c",
              "2a03:1b20:d:f011:3::c01d",
              "2a03:1b20:d:f011:3::c01e",
              "2a03:1b20:d:f011:3::c01f",
              "91.206.168.170",
              "91.206.168.171",
              "91.206.168.172",
              "91.206.168.173",
              "91.206.168.174",
              "91.206.168.175",
              "91.206.168.176",
              "91.206.168.177",
              "91.206.168.178",
              "91.206.168.179",
              "91.206.168.180",
              "91.206.168.181",
              "91.206.168.182",
              "91.206.168.183",
              "91.206.168.184",
              "91.206.168.185",
              "91.206.168.186",
              "91.206.168.187",
              "91.206.168.188",
              "91.206.168.189",
              "91.206.168.190",
              "91.206.168.191",
              "91.206.168.192",
              "91.206.168.193",
              "91.206.168.194",
              "91.206.168.195",
              "91.206.168.196",
              "91.206.168.197",
              "91.206.168.198",
              "91.206.168.199",
              "91.206.168.200",
              "91.206.168.201",
              "91.206.168.202",
              "91.206.168.203",
              "91.206.168.204",
              "91.206.168.205"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "fi-hel-wg-203.blockerad.eu"
          }
        }
      },
      {
        "hostname": "fr-bod-wg-001",
        "location": "fr-bod",
        "active": true,
        "owned": false,
        "provider": "HostRoyale",
        "stboot": true,
        "ipv4_addr_in": "45.134.79.67",
        "include_in_country": true,
        "weight": 100,
        "public_key": "y6dcYS7MPeApbLoWLahjku5w5cufnNkwHzj1iwDPpS0=",
        "ipv6_addr_in": "2a06:3040:4:610::f001",
        "features": {
          "lwo": {}
        }
      },
      {
        "hostname": "fr-bod-wg-002",
        "location": "fr-bod",
        "active": true,
        "owned": false,
        "provider": "HostRoyale",
        "stboot": true,
        "ipv4_addr_in": "45.134.79.97",
        "include_in_country": true,
        "weight": 100,
        "public_key": "ZBOJ2w5DqG35T1zjV/F1UgrXkDhNxObnwdm2FUwyu2o=",
        "ipv6_addr_in": "2a06:3040:4:610::f101"
      },
      {
        "hostname": "fr-mrs-wg-001",
        "location": "fr-mrs",
        "active": true,
        "owned": false,
        "provider": "DataPacket",
        "stboot": true,
        "ipv4_addr_in": "138.199.15.162",
        "include_in_country": true,
        "weight": 300,
        "public_key": "MOk2OTDEaFFN4vsCAgf+qQi6IlY99nCeDEzpXyo65wg=",
        "ipv6_addr_in": "2a02:6ea0:dc05::a15f",
        "daita": true,
        "features": {
          "daita": {}
        }
      },
      {
        "hostname": "fr-mrs-wg-002",
        "location": "fr-mrs",
        "active": true,
        "owned": false,
        "provider": "DataPacket",
        "stboot": true,
        "ipv4_addr_in": "138.199.15.146",
        "include_in_country": true,
        "weight": 300,
        "public_key": "Z0LEgZIPhNj0+/VWknU3roHlVI3qqAfoV6th9NSC0F0=",
        "ipv6_addr_in": "2a02:6ea0:dc06::a16f"
      },
      {
        "hostname": "fr-par-wg-001",
        "location": "fr-par",
        "active": true,
        "owned": true,
        "provider": "31173",
        "stboot": true,
        "ipv4_addr_in": "193.32.126.66",
        "include_in_country": true,
        "weight": 100,
        "public_key": "ov323GyDOEHLT0sNRUUPYiE3BkvFDjpmi1a4fzv49hE=",
        "ipv6_addr_in": "2a03:1b20:9:f011::a01f",
        "shadowsocks_extra_addr_in": [
          "2a03:1b20:9:f011::b002",
          "2a03:1b20:9:f011::b003",
          "2a03:1b20:9:f011::b004",
          "2a03:1b20:9:f011::b005",
          "2a03:1b20:9:f011::b006",
          "2a03:1b20:9:f011::b007",
          "2a03:1b20:9:f011::b008",
          "2a03:1b20:9:f011::b009",
          "2a03:1b20:9:f011::b00a",
          "2a03:1b20:9:f011::b00b",
          "2a03:1b20:9:f011::b00c",
          "2a03:1b20:9:f011::b00d",
          "2a03:1b20:9:f011::b00e",
          "2a03:1b20:9:f011::b00f",
          "2a03:1b20:9:f011::b010",
          "2a03:1b20:9:f011::b011",
          "2a03:1b20:9:f011::b012",
          "2a03:1b20:9:f011::b013",
          "2a03:1b20:9:f011::b014",
          "2a03:1b20:9:f011::b015",
          "2a03:1b20:9:f011::b016",
          "2a03:1b20:9:f011::b017",
          "2a03:1b20:9:f011::b018",
          "2a03:1b20:9:f011::b019",
          "2a03:1b20:9:f011::b01a",
          "2a03:1b20:9:f011::b01b",
          "2a03:1b20:9:f011::b01c",
          "2a03:1b20:9:f011::b01d",
          "2a03:1b20:9:f011::b01e",
          "2a03:1b20:9:f011::b01f"
        ]
      },
      {
        "hostname": "fr-par-wg-002",
        "location": "fr-par",
        "active": true,
        "owned": true,
        "provider": "31173",
        "stboot": true,
        "ipv4_addr_in": "193.32.126.67",
        "include_in_country": true,
        "weight": 100,
        "public_key": "R5Ve+PJD24QjNXi2Dim7szwCiOLnv+6hg+WyTudAYmE=",
        "ipv6_addr_in": "2a03:1b20:9:f011::f101"
      },
      {
        "hostname": "fr-par-wg-003",
        "location": "fr-par",
        "active": true,
        "owned": true,
        "provider": "31173",
        "stboot": true,
        "ipv4_addr_in": "193.32.126.68",
        "include_in_country": true,
        "weight": 100,
        "public_key": "w4r/o6VImF7l0/De3JpOGnpzjAFv9wcCu8Rop5eZkWc=",
        "ipv6_addr_in": "2a03:1b20:9:f011::f201"
      },
      {
        "hostname": "fr-par-wg-004",
        "location": "fr-par",
        "active": true,
        "owned": true,
        "provider": "31173",
        "stboot": true,
        "ipv4_addr_in": "193.32.126.69",
        "include_in_country": true,
        "weight": 100,
        "public_key": "E/KjR7nlFouuRXh1pwGDr7iK2TAZ6c4K0LjjmA1A2Tc=",
        "ipv6_addr_in": "2a03:1b20:9:f011::f301"
      },
      {
        "hostname": "fr-par-wg-005",
        "location": "fr-par",
        "active": false,
        "owned": true,
        "provider": "31173",
        "stboot": true,
        "ipv4_addr_in": "193.32.126.70",
        "include_in_country": true,
        "weight": 100,
        "public_key": "cmqtSjWUa4/0bENQDKxdr0vQqf4nFVDodarHm0Pc0hY=",
        "ipv6_addr_in": "2a03:1b20:9:f011::f401"
      },
      {
        "hostname": "fr-par-wg-006",
        "location": "fr-par",
        "active": true,
        "owned": true,
        "provider": "31173",
        "stboot": true,
        "ipv4_addr_in": "193.32.126.84",
        "include_in_country": true,
        "weight": 100,
        "public_key": "x0k8A2S7Dx7VNX2Yo2qRPZW/VefIogID5bVynklBugE=",
        "ipv6_addr_in": "2a03:1b20:9:f011::f501",
        "shadowsocks_extra_addr_in": [
          "2a03:1b20:9:f011::b502",
          "2a03:1b20:9:f011::b503",
          "2a03:1b20:9:f011::b504",
          "2a03:1b20:9:f011::b505",
          "2a03:1b20:9:f011::b506",
          "2a03:1b20:9:f011::b507",
          "2a03:1b20:9:f011::b508",
          "2a03:1b20:9:f011::b509",
          "2a03:1b20:9:f011::b50a",
          "2a03:1b20:9:f011::b50b",
          "2a03:1b20:9:f011::b50c",
          "2a03:1b20:9:f011::b50d",
          "2a03:1b20:9:f011::b50e",
          "2a03:1b20:9:f011::b50f",
          "2a03:1b20:9:f011::b510",
          "2a03:1b20:9:f011::b511",
          "2a03:1b20:9:f011::b512",
          "2a03:1b20:9:f011::b513",
          "2a03:1b20:9:f011::b514",
          "2a03:1b20:9:f011::b515",
          "2a03:1b20:9:f011::b516",
          "2a03:1b20:9:f011::b517",
          "2a03:1b20:9:f011::b518",
          "2a03:1b20:9:f011::b519",
          "2a03:1b20:9:f011::b51a",
          "2a03:1b20:9:f011::b51b",
          "2a03:1b20:9:f011::b51c",
          "2a03:1b20:9:f011::b51d",
          "2a03:1b20:9:f011::b51e",
          "2a03:1b20:9:f011::b51f"
        ]
      },
      {
        "hostname": "fr-par-wg-007",
        "location": "fr-par",
        "active": true,
        "owned": true,
        "provider": "31173",
        "stboot": true,
        "ipv4_addr_in": "193.32.126.83",
        "include_in_country": true,
        "weight": 100,
        "public_key": "D2o4woLw59apODi8NgvVtsbEJOAF5HRxXCp3R4mzGAs=",
        "ipv6_addr_in": "2a03:1b20:9:f011::3f",
        "shadowsocks_extra_addr_in": [
          "2a03:1b20:9:f011::b602",
          "2a03:1b20:9:f011::b603",
          "2a03:1b20:9:f011::b604",
          "2a03:1b20:9:f011::b605",
          "2a03:1b20:9:f011::b606",
          "2a03:1b20:9:f011::b607",
          "2a03:1b20:9:f011::b608",
          "2a03:1b20:9:f011::b609",
          "2a03:1b20:9:f011::b60a",
          "2a03:1b20:9:f011::b60b",
          "2a03:1b20:9:f011::b60c",
          "2a03:1b20:9:f011::b60d",
          "2a03:1b20:9:f011::b60e",
          "2a03:1b20:9:f011::b60f",
          "2a03:1b20:9:f011::b610",
          "2a03:1b20:9:f011::b611",
          "2a03:1b20:9:f011::b612",
          "2a03:1b20:9:f011::b613",
          "2a03:1b20:9:f011::b614",
          "2a03:1b20:9:f011::b615",
          "2a03:1b20:9:f011::b616",
          "2a03:1b20:9:f011::b617",
          "2a03:1b20:9:f011::b618",
          "2a03:1b20:9:f011::b619",
          "2a03:1b20:9:f011::b61a",
          "2a03:1b20:9:f011::b61b",
          "2a03:1b20:9:f011::b61c",
          "2a03:1b20:9:f011::b61d",
          "2a03:1b20:9:f011::b61e",
          "2a03:1b20:9:f011::b61f"
        ]
      },
      {
        "hostname": "fr-par-wg-101",
        "location": "fr-par",
        "active": true,
        "owned": false,
        "provider": "M247",
        "stboot": true,
        "ipv4_addr_in": "146.70.184.2",
        "include_in_country": true,
        "weight": 100,
        "public_key": "py4bg/TO5waXCoytaDpddP/qkI0tS1Wv3yAcgZ/A4wA=",
        "ipv6_addr_in": "2001:ac8:25:3a::f001",
        "daita": true,
        "shadowsocks_extra_addr_in": [
          "146.70.184.13",
          "146.70.184.14",
          "146.70.184.15",
          "146.70.184.16",
          "146.70.184.17",
          "146.70.184.18",
          "146.70.184.19",
          "146.70.184.20",
          "146.70.184.21",
          "146.70.184.22",
          "2001:ac8:25:3a::b002",
          "2001:ac8:25:3a::b003",
          "2001:ac8:25:3a::b004",
          "2001:ac8:25:3a::b005",
          "2001:ac8:25:3a::b006",
          "2001:ac8:25:3a::b007",
          "2001:ac8:25:3a::b008",
          "2001:ac8:25:3a::b009",
          "2001:ac8:25:3a::b00a",
          "2001:ac8:25:3a::b00b",
          "2001:ac8:25:3a::b00c",
          "2001:ac8:25:3a::b00d",
          "2001:ac8:25:3a::b00e",
          "2001:ac8:25:3a::b00f",
          "2001:ac8:25:3a::b010",
          "2001:ac8:25:3a::b011",
          "2001:ac8:25:3a::b012",
          "2001:ac8:25:3a::b013",
          "2001:ac8:25:3a::b014",
          "2001:ac8:25:3a::b015",
          "2001:ac8:25:3a::b016",
          "2001:ac8:25:3a::b017",
          "2001:ac8:25:3a::b018",
          "2001:ac8:25:3a::b019",
          "2001:ac8:25:3a::b01a",
          "2001:ac8:25:3a::b01b",
          "2001:ac8:25:3a::b01c",
          "2001:ac8:25:3a::b01d",
          "2001:ac8:25:3a::b01e",
          "2001:ac8:25:3a::b01f"
        ],
        "features": {
          "daita": {},
          "lwo": {},
          "quic": {
            "addr_in": [
              "146.70.184.23",
              "146.70.184.24",
              "146.70.184.25",
              "146.70.184.26",
              "146.70.184.27",
              "146.70.184.28",
              "146.70.184.29",
              "146.70.184.30",
              "146.70.184.31",
              "146.70.184.32",
              "2001:ac8:25:3a::c002",
              "2001:ac8:25:3a::c003",
              "2001:ac8:25:3a::c004",
              "2001:ac8:25:3a::c005",
              "2001:ac8:25:3a::c006",
              "2001:ac8:25:3a::c007",
              "2001:ac8:25:3a::c008",
              "2001:ac8:25:3a::c009",
              "2001:ac8:25:3a::c00a",
              "2001:ac8:25:3a::c00b",
              "2001:ac8:25:3a::c00c",
              "2001:ac8:25:3a::c00d",
              "2001:ac8:25:3a::c00e",
              "2001:ac8:25:3a::c00f",
              "2001:ac8:25:3a::c010",
              "2001:ac8:25:3a::c011",
              "2001:ac8:25:3a::c012",
              "2001:ac8:25:3a::c013",
              "2001:ac8:25:3a::c014",
              "2001:ac8:25:3a::c015",
              "2001:ac8:25:3a::c016",
              "2001:ac8:25:3a::c017",
              "2001:ac8:25:3a::c018",
              "2001:ac8:25:3a::c019",
              "2001:ac8:25:3a::c01a",
              "2001:ac8:25:3a::c01b",
              "2001:ac8:25:3a::c01c",
              "2001:ac8:25:3a::c01d",
              "2001:ac8:25:3a::c01e",
              "2001:ac8:25:3a::c01f"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "fr-par-wg-101.blockerad.eu"
          }
        }
      },
      {
        "hostname": "fr-par-wg-102",
        "location": "fr-par",
        "active": false,
        "owned": false,
        "provider": "M247",
        "stboot": true,
        "ipv4_addr_in": "146.70.184.130",
        "include_in_country": true,
        "weight": 100,
        "public_key": "gx9/WJPB3eu9nbbDA+gku9BPKhpAnJ0heaE2BZEr6Go=",
        "ipv6_addr_in": "2001:ac8:25:3b::f001",
        "daita": true,
        "shadowsocks_extra_addr_in": [
          "146.70.184.141",
          "146.70.184.142",
          "146.70.184.143",
          "146.70.184.144",
          "146.70.184.145",
          "146.70.184.146",
          "146.70.184.147",
          "146.70.184.148",
          "146.70.184.149",
          "146.70.184.150",
          "2001:ac8:25:3b::b002",
          "2001:ac8:25:3b::b003",
          "2001:ac8:25:3b::b004",
          "2001:ac8:25:3b::b005",
          "2001:ac8:25:3b::b006",
          "2001:ac8:25:3b::b007",
          "2001:ac8:25:3b::b008",
          "2001:ac8:25:3b::b009",
          "2001:ac8:25:3b::b00a",
          "2001:ac8:25:3b::b00b",
          "2001:ac8:25:3b::b00c",
          "2001:ac8:25:3b::b00d",
          "2001:ac8:25:3b::b00e",
          "2001:ac8:25:3b::b00f",
          "2001:ac8:25:3b::b010",
          "2001:ac8:25:3b::b011",
          "2001:ac8:25:3b::b012",
          "2001:ac8:25:3b::b013",
          "2001:ac8:25:3b::b014",
          "2001:ac8:25:3b::b015",
          "2001:ac8:25:3b::b016",
          "2001:ac8:25:3b::b017",
          "2001:ac8:25:3b::b018",
          "2001:ac8:25:3b::b019",
          "2001:ac8:25:3b::b01a",
          "2001:ac8:25:3b::b01b",
          "2001:ac8:25:3b::b01c",
          "2001:ac8:25:3b::b01d",
          "2001:ac8:25:3b::b01e",
          "2001:ac8:25:3b::b01f"
        ],
        "features": {
          "daita": {},
          "lwo": {},
          "quic": {
            "addr_in": [
              "146.70.184.151",
              "146.70.184.152",
              "146.70.184.153",
              "146.70.184.154",
              "146.70.184.155",
              "146.70.184.156",
              "146.70.184.157",
              "146.70.184.158",
              "146.70.184.159",
              "146.70.184.160",
              "2001:ac8:25:3b::c002",
              "2001:ac8:25:3b::c003",
              "2001:ac8:25:3b::c004",
              "2001:ac8:25:3b::c005",
              "2001:ac8:25:3b::c006",
              "2001:ac8:25:3b::c007",
              "2001:ac8:25:3b::c008",
              "2001:ac8:25:3b::c009",
              "2001:ac8:25:3b::c00a",
              "2001:ac8:25:3b::c00b",
              "2001:ac8:25:3b::c00c",
              "2001:ac8:25:3b::c00d",
              "2001:ac8:25:3b::c00e",
              "2001:ac8:25:3b::c00f",
              "2001:ac8:25:3b::c010",
              "2001:ac8:25:3b::c011",
              "2001:ac8:25:3b::c012",
              "2001:ac8:25:3b::c013",
              "2001:ac8:25:3b::c014",
              "2001:ac8:25:3b::c015",
              "2001:ac8:25:3b::c016",
              "2001:ac8:25:3b::c017",
              "2001:ac8:25:3b::c018",
              "2001:ac8:25:3b::c019",
              "2001:ac8:25:3b::c01a",
              "2001:ac8:25:3b::c01b",
              "2001:ac8:25:3b::c01c",
              "2001:ac8:25:3b::c01d",
              "2001:ac8:25:3b::c01e",
              "2001:ac8:25:3b::c01f"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "fr-par-wg-102.blockerad.eu"
          }
        }
      },
      {
        "hostname": "fr-par-wg-103",
        "location": "fr-par",
        "active": true,
        "owned": false,
        "provider": "M247",
        "stboot": true,
        "ipv4_addr_in": "185.244.213.2",
        "include_in_country": true,
        "weight": 100,
        "public_key": "BKxcFQnXCpgpGk38nDIWKgl6oeABN3GyyreMrOY7qh4=",
        "ipv6_addr_in": "2001:ac8:25:3c::f001",
        "daita": true,
        "shadowsocks_extra_addr_in": [
          "185.244.213.13",
          "185.244.213.14",
          "185.244.213.15",
          "185.244.213.16",
          "185.244.213.17",
          "185.244.213.18",
          "185.244.213.19",
          "185.244.213.20",
          "185.244.213.21",
          "185.244.213.22",
          "2001:ac8:25:3c::b002",
          "2001:ac8:25:3c::b003",
          "2001:ac8:25:3c::b004",
          "2001:ac8:25:3c::b005",
          "2001:ac8:25:3c::b006",
          "2001:ac8:25:3c::b007",
          "2001:ac8:25:3c::b008",
          "2001:ac8:25:3c::b009",
          "2001:ac8:25:3c::b00a",
          "2001:ac8:25:3c::b00b",
          "2001:ac8:25:3c::b00c",
          "2001:ac8:25:3c::b00d",
          "2001:ac8:25:3c::b00e",
          "2001:ac8:25:3c::b00f",
          "2001:ac8:25:3c::b010",
          "2001:ac8:25:3c::b011",
          "2001:ac8:25:3c::b012",
          "2001:ac8:25:3c::b013",
          "2001:ac8:25:3c::b014",
          "2001:ac8:25:3c::b015",
          "2001:ac8:25:3c::b016",
          "2001:ac8:25:3c::b017",
          "2001:ac8:25:3c::b018",
          "2001:ac8:25:3c::b019",
          "2001:ac8:25:3c::b01a",
          "2001:ac8:25:3c::b01b",
          "2001:ac8:25:3c::b01c",
          "2001:ac8:25:3c::b01d",
          "2001:ac8:25:3c::b01e",
          "2001:ac8:25:3c::b01f"
        ],
        "features": {
          "daita": {},
          "lwo": {},
          "quic": {
            "addr_in": [
              "185.244.213.23",
              "185.244.213.24",
              "185.244.213.25",
              "185.244.213.26",
              "185.244.213.27",
              "185.244.213.28",
              "185.244.213.29",
              "185.244.213.30",
              "185.244.213.31",
              "185.244.213.32",
              "2001:ac8:25:3c::c002",
              "2001:ac8:25:3c::c003",
              "2001:ac8:25:3c::c004",
              "2001:ac8:25:3c::c005",
              "2001:ac8:25:3c::c006",
              "2001:ac8:25:3c::c007",
              "2001:ac8:25:3c::c008",
              "2001:ac8:25:3c::c009",
              "2001:ac8:25:3c::c00a",
              "2001:ac8:25:3c::c00b",
              "2001:ac8:25:3c::c00c",
              "2001:ac8:25:3c::c00d",
              "2001:ac8:25:3c::c00e",
              "2001:ac8:25:3c::c00f",
              "2001:ac8:25:3c::c010",
              "2001:ac8:25:3c::c011",
              "2001:ac8:25:3c::c012",
              "2001:ac8:25:3c::c013",
              "2001:ac8:25:3c::c014",
              "2001:ac8:25:3c::c015",
              "2001:ac8:25:3c::c016",
              "2001:ac8:25:3c::c017",
              "2001:ac8:25:3c::c018",
              "2001:ac8:25:3c::c019",
              "2001:ac8:25:3c::c01a",
              "2001:ac8:25:3c::c01b",
              "2001:ac8:25:3c::c01c",
              "2001:ac8:25:3c::c01d",
              "2001:ac8:25:3c::c01e",
              "2001:ac8:25:3c::c01f"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "fr-par-wg-103.blockerad.eu"
          }
        }
      },
      {
        "hostname": "fr-par-wg-301",
        "location": "fr-par",
        "active": true,
        "owned": false,
        "provider": "DataPacket",
        "stboot": true,
        "ipv4_addr_in": "95.173.222.2",
        "include_in_country": true,
        "weight": 100,
        "public_key": "gCYpOei4ZYsWJ3mOgCdQo6bnsRgdLNJR9SWEA69U7Gw=",
        "ipv6_addr_in": "2a02:6ea0:1901:2::f001",
        "shadowsocks_extra_addr_in": [
          "95.173.222.5"
        ]
      },
      {
        "hostname": "fr-par-wg-302",
        "location": "fr-par",
        "active": true,
        "owned": false,
        "provider": "DataPacket",
        "stboot": true,
        "ipv4_addr_in": "95.173.222.31",
        "include_in_country": true,
        "weight": 100,
        "public_key": "CpbLl0WVeiW+YbJKNod5khzAI03D2hX2dhq2CCYc2Xc=",
        "ipv6_addr_in": "2a02:6ea0:1901:3::f001",
        "shadowsocks_extra_addr_in": [
          "95.173.222.33"
        ]
      },
      {
        "hostname": "gb-glw-wg-001",
        "location": "gb-glw",
        "active": true,
        "owned": false,
        "provider": "HostRoyale",
        "stboot": true,
        "ipv4_addr_in": "185.201.188.3",
        "include_in_country": false,
        "weight": 100,
        "public_key": "xCPSxGj0QVKC637D8HpRsUUCaSfgAF4ephG/CjhQ2kU=",
        "ipv6_addr_in": "2a06:3040:d:410::f001",
        "features": {
          "lwo": {}
        }
      },
      {
        "hostname": "gb-glw-wg-002",
        "location": "gb-glw",
        "active": true,
        "owned": false,
        "provider": "HostRoyale",
        "stboot": true,
        "ipv4_addr_in": "185.201.188.33",
        "include_in_country": false,
        "weight": 100,
        "public_key": "tX+LKwiFvZhGtbuJq8e62+/vhogHNqdAdjHeoOlWqws=",
        "ipv6_addr_in": "2a06:3040:d:410::f101"
      },
      {
        "hostname": "gb-lon-wg-001",
        "location": "gb-lon",
        "active": true,
        "owned": true,
        "provider": "31173",
        "stboot": true,
        "ipv4_addr_in": "141.98.252.130",
        "include_in_country": true,
        "weight": 100,
        "public_key": "IJJe0TQtuQOyemL4IZn6oHEsMKSPqOuLfD5HoAWEPTY=",
        "ipv6_addr_in": "2a03:1b20:7:f011::a01f",
        "shadowsocks_extra_addr_in": [
          "185.195.232.98",
          "2a03:1b20:7:f011::b001",
          "2a03:1b20:7:f011::b002",
          "2a03:1b20:7:f011::b003",
          "2a03:1b20:7:f011::b004",
          "2a03:1b20:7:f011::b005",
          "2a03:1b20:7:f011::b006",
          "2a03:1b20:7:f011::b007",
          "2a03:1b20:7:f011::b008",
          "2a03:1b20:7:f011::b009",
          "2a03:1b20:7:f011::b00a",
          "2a03:1b20:7:f011::b00b",
          "2a03:1b20:7:f011::b00c",
          "2a03:1b20:7:f011::b00d",
          "2a03:1b20:7:f011::b00e",
          "2a03:1b20:7:f011::b00f",
          "2a03:1b20:7:f011::b010",
          "2a03:1b20:7:f011::b011",
          "2a03:1b20:7:f011::b012",
          "2a03:1b20:7:f011::b013",
          "2a03:1b20:7:f011::b014",
          "2a03:1b20:7:f011::b015",
          "2a03:1b20:7:f011::b016",
          "2a03:1b20:7:f011::b017",
          "2a03:1b20:7:f011::b018",
          "2a03:1b20:7:f011::b019",
          "2a03:1b20:7:f011::b01a",
          "2a03:1b20:7:f011::b01b",
          "2a03:1b20:7:f011::b01c",
          "2a03:1b20:7:f011::b01d",
          "2a03:1b20:7:f011::b01e",
          "2a03:1b20:7:f011::b01f"
        ],
        "features": {
          "quic": {
            "addr_in": [
              "185.195.232.99",
              "185.195.232.95",
              "185.195.232.96",
              "185.195.232.97",
              "2a03:1b20:7:f011::c001",
              "2a03:1b20:7:f011::c002",
              "2a03:1b20:7:f011::c003",
              "2a03:1b20:7:f011::c004",
              "2a03:1b20:7:f011::c005",
              "2a03:1b20:7:f011::c006",
              "2a03:1b20:7:f011::c007",
              "2a03:1b20:7:f011::c008",
              "2a03:1b20:7:f011::c009",
              "2a03:1b20:7:f011::c00a",
              "2a03:1b20:7:f011::c00b",
              "2a03:1b20:7:f011::c00c",
              "2a03:1b20:7:f011::c00d",
              "2a03:1b20:7:f011::c00e",
              "2a03:1b20:7:f011::c00f",
              "2a03:1b20:7:f011::c010",
              "2a03:1b20:7:f011::c011",
              "2a03:1b20:7:f011::c012",
              "2a03:1b20:7:f011::c013",
              "2a03:1b20:7:f011::c014",
              "2a03:1b20:7:f011::c015",
              "2a03:1b20:7:f011::c016",
              "2a03:1b20:7:f011::c017",
              "2a03:1b20:7:f011::c018",
              "2a03:1b20:7:f011::c019",
              "2a03:1b20:7:f011::c01a",
              "2a03:1b20:7:f011::c01b",
              "2a03:1b20:7:f011::c01c",
              "2a03:1b20:7:f011::c01d",
              "2a03:1b20:7:f011::c01e",
              "2a03:1b20:7:f011::c01f"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "gb-lon-wg-001.blockerad.eu"
          }
        }
      },
      {
        "hostname": "gb-lon-wg-002",
        "location": "gb-lon",
        "active": true,
        "owned": true,
        "provider": "31173",
        "stboot": true,
        "ipv4_addr_in": "141.98.252.222",
        "include_in_country": true,
        "weight": 1,
        "public_key": "J57ba81Q8bigy9RXBXvl0DgABTrbl81nb37GuX50gnY=",
        "ipv6_addr_in": "2a03:1b20:7:f011::a02f",
        "shadowsocks_extra_addr_in": [
          "2a03:1b20:7:f011::b101",
          "2a03:1b20:7:f011::b102",
          "2a03:1b20:7:f011::b103",
          "2a03:1b20:7:f011::b104",
          "2a03:1b20:7:f011::b105",
          "2a03:1b20:7:f011::b106",
          "2a03:1b20:7:f011::b107",
          "2a03:1b20:7:f011::b108",
          "2a03:1b20:7:f011::b109",
          "2a03:1b20:7:f011::b10a",
          "2a03:1b20:7:f011::b10b",
          "2a03:1b20:7:f011::b10c",
          "2a03:1b20:7:f011::b10d",
          "2a03:1b20:7:f011::b10e",
          "2a03:1b20:7:f011::b10f",
          "2a03:1b20:7:f011::b110",
          "2a03:1b20:7:f011::b111",
          "2a03:1b20:7:f011::b112",
          "2a03:1b20:7:f011::b113",
          "2a03:1b20:7:f011::b114",
          "2a03:1b20:7:f011::b115",
          "2a03:1b20:7:f011::b116",
          "2a03:1b20:7:f011::b117",
          "2a03:1b20:7:f011::b118",
          "2a03:1b20:7:f011::b119",
          "2a03:1b20:7:f011::b11a",
          "2a03:1b20:7:f011::b11b",
          "2a03:1b20:7:f011::b11c",
          "2a03:1b20:7:f011::b11d",
          "2a03:1b20:7:f011::b11e",
          "2a03:1b20:7:f011::b11f"
        ]
      },
      {
        "hostname": "gb-lon-wg-003",
        "location": "gb-lon",
        "active": true,
        "owned": true,
        "provider": "31173",
        "stboot": true,
        "ipv4_addr_in": "185.195.232.66",
        "include_in_country": true,
        "weight": 100,
        "public_key": "VZwE8hrpNzg6SMwn9LtEqonXzSWd5dkFk62PrNWFW3Y=",
        "ipv6_addr_in": "2a03:1b20:7:f011::a11f",
        "shadowsocks_extra_addr_in": [
          "2a03:1b20:7:f011::b201",
          "2a03:1b20:7:f011::b202",
          "2a03:1b20:7:f011::b203",
          "2a03:1b20:7:f011::b204",
          "2a03:1b20:7:f011::b205",
          "2a03:1b20:7:f011::b206",
          "2a03:1b20:7:f011::b207",
          "2a03:1b20:7:f011::b208",
          "2a03:1b20:7:f011::b209",
          "2a03:1b20:7:f011::b20a",
          "2a03:1b20:7:f011::b20b",
          "2a03:1b20:7:f011::b20c",
          "2a03:1b20:7:f011::b20d",
          "2a03:1b20:7:f011::b20e",
          "2a03:1b20:7:f011::b20f",
          "2a03:1b20:7:f011::b210",
          "2a03:1b20:7:f011::b211",
          "2a03:1b20:7:f011::b212",
          "2a03:1b20:7:f011::b213",
          "2a03:1b20:7:f011::b214",
          "2a03:1b20:7:f011::b215",
          "2a03:1b20:7:f011::b216",
          "2a03:1b20:7:f011::b217",
          "2a03:1b20:7:f011::b218",
          "2a03:1b20:7:f011::b219",
          "2a03:1b20:7:f011::b21a",
          "2a03:1b20:7:f011::b21b",
          "2a03:1b20:7:f011::b21c",
          "2a03:1b20:7:f011::b21d",
          "2a03:1b20:7:f011::b21e",
          "2a03:1b20:7:f011::b21f"
        ]
      },
      {
        "hostname": "gb-lon-wg-004",
        "location": "gb-lon",
        "active": true,
        "owned": true,
        "provider": "31173",
        "stboot": true,
        "ipv4_addr_in": "185.195.232.67",
        "include_in_country": true,
        "weight": 100,
        "public_key": "PLpO9ikFX1garSFaeUpo7XVSMrILrTB8D9ZwQt6Zgwk=",
        "ipv6_addr_in": "2a03:1b20:7:f011::a12f",
        "shadowsocks_extra_addr_in": [
          "2a03:1b20:7:f011::b301",
          "2a03:1b20:7:f011::b302",
          "2a03:1b20:7:f011::b303",
          "2a03:1b20:7:f011::b304",
          "2a03:1b20:7:f011::b305",
          "2a03:1b20:7:f011::b306",
          "2a03:1b20:7:f011::b307",
          "2a03:1b20:7:f011::b308",
          "2a03:1b20:7:f011::b309",
          "2a03:1b20:7:f011::b30a",
          "2a03:1b20:7:f011::b30b",
          "2a03:1b20:7:f011::b30c",
          "2a03:1b20:7:f011::b30d",
          "2a03:1b20:7:f011::b30e",
          "2a03:1b20:7:f011::b30f",
          "2a03:1b20:7:f011::b310",
          "2a03:1b20:7:f011::b311",
          "2a03:1b20:7:f011::b312",
          "2a03:1b20:7:f011::b313",
          "2a03:1b20:7:f011::b314",
          "2a03:1b20:7:f011::b315",
          "2a03:1b20:7:f011::b316",
          "2a03:1b20:7:f011::b317",
          "2a03:1b20:7:f011::b318",
          "2a03:1b20:7:f011::b319",
          "2a03:1b20:7:f011::b31a",
          "2a03:1b20:7:f011::b31b",
          "2a03:1b20:7:f011::b31c",
          "2a03:1b20:7:f011::b31d",
          "2a03:1b20:7:f011::b31e",
          "2a03:1b20:7:f011::b31f"
        ]
      },
      {
        "hostname": "gb-lon-wg-005",
        "location": "gb-lon",
        "active": true,
        "owned": true,
        "provider": "31173",
        "stboot": true,
        "ipv4_addr_in": "185.195.232.68",
        "include_in_country": true,
        "weight": 100,
        "public_key": "bG6WulLmMK408n719B8nQJNuTRyRA3Qjm7bsm9d6v2M=",
        "ipv6_addr_in": "2a03:1b20:7:f011::a13f",
        "shadowsocks_extra_addr_in": [
          "2a03:1b20:7:f011::b401",
          "2a03:1b20:7:f011::b402",
          "2a03:1b20:7:f011::b403",
          "2a03:1b20:7:f011::b404",
          "2a03:1b20:7:f011::b405",
          "2a03:1b20:7:f011::b406",
          "2a03:1b20:7:f011::b407",
          "2a03:1b20:7:f011::b408",
          "2a03:1b20:7:f011::b409",
          "2a03:1b20:7:f011::b40a",
          "2a03:1b20:7:f011::b40b",
          "2a03:1b20:7:f011::b40c",
          "2a03:1b20:7:f011::b40d",
          "2a03:1b20:7:f011::b40e",
          "2a03:1b20:7:f011::b40f",
          "2a03:1b20:7:f011::b410",
          "2a03:1b20:7:f011::b411",
          "2a03:1b20:7:f011::b412",
          "2a03:1b20:7:f011::b413",
          "2a03:1b20:7:f011::b414",
          "2a03:1b20:7:f011::b415",
          "2a03:1b20:7:f011::b416",
          "2a03:1b20:7:f011::b417",
          "2a03:1b20:7:f011::b418",
          "2a03:1b20:7:f011::b419",
          "2a03:1b20:7:f011::b41a",
          "2a03:1b20:7:f011::b41b",
          "2a03:1b20:7:f011::b41c",
          "2a03:1b20:7:f011::b41d",
          "2a03:1b20:7:f011::b41e",
          "2a03:1b20:7:f011::b41f"
        ]
      },
      {
        "hostname": "gb-lon-wg-006",
        "location": "gb-lon",
        "active": true,
        "owned": true,
        "provider": "31173",
        "stboot": true,
        "ipv4_addr_in": "185.195.232.69",
        "include_in_country": true,
        "weight": 100,
        "public_key": "INRhM0h4T1hi9j28pcC+vRv47bp7DIsNKtagaFZFSBI=",
        "ipv6_addr_in": "2a03:1b20:7:f011::a14f",
        "shadowsocks_extra_addr_in": [
          "2a03:1b20:7:f011::b501",
          "2a03:1b20:7:f011::b502",
          "2a03:1b20:7:f011::b503",
          "2a03:1b20:7:f011::b504",
          "2a03:1b20:7:f011::b505",
          "2a03:1b20:7:f011::b506",
          "2a03:1b20:7:f011::b507",
          "2a03:1b20:7:f011::b508",
          "2a03:1b20:7:f011::b509",
          "2a03:1b20:7:f011::b50a",
          "2a03:1b20:7:f011::b50b",
          "2a03:1b20:7:f011::b50c",
          "2a03:1b20:7:f011::b50d",
          "2a03:1b20:7:f011::b50e",
          "2a03:1b20:7:f011::b50f",
          "2a03:1b20:7:f011::b510",
          "2a03:1b20:7:f011::b511",
          "2a03:1b20:7:f011::b512",
          "2a03:1b20:7:f011::b513",
          "2a03:1b20:7:f011::b514",
          "2a03:1b20:7:f011::b515",
          "2a03:1b20:7:f011::b516",
          "2a03:1b20:7:f011::b517",
          "2a03:1b20:7:f011::b518",
          "2a03:1b20:7:f011::b519",
          "2a03:1b20:7:f011::b51a",
          "2a03:1b20:7:f011::b51b",
          "2a03:1b20:7:f011::b51c",
          "2a03:1b20:7:f011::b51d",
          "2a03:1b20:7:f011::b51e",
          "2a03:1b20:7:f011::b51f"
        ]
      },
      {
        "hostname": "gb-lon-wg-007",
        "location": "gb-lon",
        "active": true,
        "owned": true,
        "provider": "31173",
        "stboot": true,
        "ipv4_addr_in": "185.195.232.70",
        "include_in_country": true,
        "weight": 100,
        "public_key": "MVqe9e9aDwfFuvEhEn4Wd/zWV3cmiCX9fZMWetz+23A=",
        "ipv6_addr_in": "2a03:1b20:7:f011::a15f",
        "shadowsocks_extra_addr_in": [
          "2a03:1b20:7:f011::b601",
          "2a03:1b20:7:f011::b602",
          "2a03:1b20:7:f011::b603",
          "2a03:1b20:7:f011::b604",
          "2a03:1b20:7:f011::b605",
          "2a03:1b20:7:f011::b606",
          "2a03:1b20:7:f011::b607",
          "2a03:1b20:7:f011::b608",
          "2a03:1b20:7:f011::b609",
          "2a03:1b20:7:f011::b60a",
          "2a03:1b20:7:f011::b60b",
          "2a03:1b20:7:f011::b60c",
          "2a03:1b20:7:f011::b60d",
          "2a03:1b20:7:f011::b60e",
          "2a03:1b20:7:f011::b60f",
          "2a03:1b20:7:f011::b610",
          "2a03:1b20:7:f011::b611",
          "2a03:1b20:7:f011::b612",
          "2a03:1b20:7:f011::b613",
          "2a03:1b20:7:f011::b614",
          "2a03:1b20:7:f011::b615",
          "2a03:1b20:7:f011::b616",
          "2a03:1b20:7:f011::b617",
          "2a03:1b20:7:f011::b618",
          "2a03:1b20:7:f011::b619",
          "2a03:1b20:7:f011::b61a",
          "2a03:1b20:7:f011::b61b",
          "2a03:1b20:7:f011::b61c",
          "2a03:1b20:7:f011::b61d",
          "2a03:1b20:7:f011::b61e",
          "2a03:1b20:7:f011::b61f"
        ]
      },
      {
        "hostname": "gb-lon-wg-008",
        "location": "gb-lon",
        "active": true,
        "owned": true,
        "provider": "31173",
        "stboot": true,
        "ipv4_addr_in": "141.98.252.138",
        "include_in_country": true,
        "weight": 1,
        "public_key": "uHkxYjfx6yzPHSdyqYqSEHsgFNFV8QCSV6aghuQK3AA=",
        "ipv6_addr_in": "2a03:1b20:7:f011::f801",
        "daita": true,
        "shadowsocks_extra_addr_in": [
          "2a03:1b20:7:f011::c801",
          "2a03:1b20:7:f011::c802",
          "2a03:1b20:7:f011::c803",
          "2a03:1b20:7:f011::c804",
          "2a03:1b20:7:f011::c805",
          "2a03:1b20:7:f011::c806",
          "2a03:1b20:7:f011::c807",
          "2a03:1b20:7:f011::c808",
          "2a03:1b20:7:f011::c809",
          "2a03:1b20:7:f011::c80a",
          "2a03:1b20:7:f011::c80b",
          "2a03:1b20:7:f011::c80c",
          "2a03:1b20:7:f011::c80d",
          "2a03:1b20:7:f011::c80e",
          "2a03:1b20:7:f011::c80f",
          "2a03:1b20:7:f011::c810",
          "2a03:1b20:7:f011::c811",
          "2a03:1b20:7:f011::c812",
          "2a03:1b20:7:f011::c813",
          "2a03:1b20:7:f011::c814",
          "2a03:1b20:7:f011::c815",
          "2a03:1b20:7:f011::c816",
          "2a03:1b20:7:f011::c817",
          "2a03:1b20:7:f011::c818",
          "2a03:1b20:7:f011::c819",
          "2a03:1b20:7:f011::c81a",
          "2a03:1b20:7:f011::c81b",
          "2a03:1b20:7:f011::c81c",
          "2a03:1b20:7:f011::c81d",
          "2a03:1b20:7:f011::c81e",
          "2a03:1b20:7:f011::c81f"
        ],
        "features": {
          "daita": {}
        }
      },
      {
        "hostname": "gb-lon-wg-201",
        "location": "gb-lon",
        "active": true,
        "owned": false,
        "provider": "xtom",
        "stboot": true,
        "ipv4_addr_in": "185.248.85.3",
        "include_in_country": true,
        "weight": 100,
        "public_key": "b71Y8V/vVwNRGkL4d1zvApDVL18u7m31dN+x+i5OJVs=",
        "ipv6_addr_in": "2a0b:89c1:3::a33f"
      },
      {
        "hostname": "gb-lon-wg-202",
        "location": "gb-lon",
        "active": true,
        "owned": false,
        "provider": "xtom",
        "stboot": true,
        "ipv4_addr_in": "185.248.85.18",
        "include_in_country": true,
        "weight": 100,
        "public_key": "+iQWuT3wb2DCy1u2eUKovhJTCB4aUdJUnpxGtONDIVE=",
        "ipv6_addr_in": "2a0b:89c1:3::a34f"
      },
      {
        "hostname": "gb-lon-wg-203",
        "location": "gb-lon",
        "active": true,
        "owned": false,
        "provider": "xtom",
        "stboot": true,
        "ipv4_addr_in": "185.248.85.33",
        "include_in_country": true,
        "weight": 100,
        "public_key": "G7XDQqevQOw1SVL7Iarn9PM+RvmI6H/CfkmahBYEG0g=",
        "ipv6_addr_in": "2a0b:89c1:3::a35f"
      },
      {
        "hostname": "gb-lon-wg-204",
        "location": "gb-lon",
        "active": true,
        "owned": false,
        "provider": "xtom",
        "stboot": true,
        "ipv4_addr_in": "185.248.85.48",
        "include_in_country": true,
        "weight": 100,
        "public_key": "tJVHqpfkV2Xgmd4YK60aoErSt6PmJKJjkggHNDfWwiU=",
        "ipv6_addr_in": "2a0b:89c1:3::a36f",
        "features": {
          "lwo": {}
        }
      },
      {
        "hostname": "gb-lon-wg-305",
        "location": "gb-lon",
        "active": true,
        "owned": false,
        "provider": "M247",
        "stboot": true,
        "ipv4_addr_in": "146.70.119.2",
        "include_in_country": true,
        "weight": 100,
        "public_key": "QCmRXGF/4sefzm5bdfXEcN/fYQGrb+F6HbOzI/FK4hU=",
        "ipv6_addr_in": "2a04:9dc0:18:70::f001",
        "shadowsocks_extra_addr_in": [
          "146.70.119.13",
          "146.70.119.14",
          "146.70.119.15",
          "146.70.119.16",
          "146.70.119.17",
          "146.70.119.18",
          "146.70.119.19",
          "146.70.119.20",
          "146.70.119.21",
          "146.70.119.22",
          "2a04:9dc0:18:70::b002",
          "2a04:9dc0:18:70::b003",
          "2a04:9dc0:18:70::b004",
          "2a04:9dc0:18:70::b005",
          "2a04:9dc0:18:70::b006",
          "2a04:9dc0:18:70::b007",
          "2a04:9dc0:18:70::b008",
          "2a04:9dc0:18:70::b009",
          "2a04:9dc0:18:70::b00a",
          "2a04:9dc0:18:70::b00b",
          "2a04:9dc0:18:70::b00c",
          "2a04:9dc0:18:70::b00d",
          "2a04:9dc0:18:70::b00e",
          "2a04:9dc0:18:70::b00f",
          "2a04:9dc0:18:70::b010",
          "2a04:9dc0:18:70::b011",
          "2a04:9dc0:18:70::b012",
          "2a04:9dc0:18:70::b013",
          "2a04:9dc0:18:70::b014",
          "2a04:9dc0:18:70::b015",
          "2a04:9dc0:18:70::b016",
          "2a04:9dc0:18:70::b017",
          "2a04:9dc0:18:70::b018",
          "2a04:9dc0:18:70::b019",
          "2a04:9dc0:18:70::b01a",
          "2a04:9dc0:18:70::b01b",
          "2a04:9dc0:18:70::b01c",
          "2a04:9dc0:18:70::b01d",
          "2a04:9dc0:18:70::b01e",
          "2a04:9dc0:18:70::b01f"
        ],
        "features": {
          "quic": {
            "addr_in": [
              "146.70.119.23",
              "146.70.119.24",
              "146.70.119.25",
              "146.70.119.26",
              "146.70.119.27",
              "146.70.119.28",
              "146.70.119.29",
              "146.70.119.30",
              "146.70.119.31",
              "146.70.119.32",
              "2a04:9dc0:18:70::c002",
              "2a04:9dc0:18:70::c003",
              "2a04:9dc0:18:70::c004",
              "2a04:9dc0:18:70::c005",
              "2a04:9dc0:18:70::c006",
              "2a04:9dc0:18:70::c007",
              "2a04:9dc0:18:70::c008",
              "2a04:9dc0:18:70::c009",
              "2a04:9dc0:18:70::c00a",
              "2a04:9dc0:18:70::c00b",
              "2a04:9dc0:18:70::c00c",
              "2a04:9dc0:18:70::c00d",
              "2a04:9dc0:18:70::c00e",
              "2a04:9dc0:18:70::c00f",
              "2a04:9dc0:18:70::c010",
              "2a04:9dc0:18:70::c011",
              "2a04:9dc0:18:70::c012",
              "2a04:9dc0:18:70::c013",
              "2a04:9dc0:18:70::c014",
              "2a04:9dc0:18:70::c015",
              "2a04:9dc0:18:70::c016",
              "2a04:9dc0:18:70::c017",
              "2a04:9dc0:18:70::c018",
              "2a04:9dc0:18:70::c019",
              "2a04:9dc0:18:70::c01a",
              "2a04:9dc0:18:70::c01b",
              "2a04:9dc0:18:70::c01c",
              "2a04:9dc0:18:70::c01d",
              "2a04:9dc0:18:70::c01e",
              "2a04:9dc0:18:70::c01f"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "gb-lon-wg-305.blockerad.eu"
          }
        }
      },
      {
        "hostname": "gb-lon-wg-306",
        "location": "gb-lon",
        "active": true,
        "owned": false,
        "provider": "M247",
        "stboot": true,
        "ipv4_addr_in": "146.70.119.130",
        "include_in_country": true,
        "weight": 100,
        "public_key": "zTM3WRyxGSqh+ZMUBXDynlyOWYkSG/J/eTFb8boDAkw=",
        "ipv6_addr_in": "2a04:9dc0:18:71::f001",
        "shadowsocks_extra_addr_in": [
          "146.70.119.151",
          "146.70.119.152",
          "146.70.119.153",
          "146.70.119.154",
          "146.70.119.155",
          "146.70.119.156",
          "146.70.119.157",
          "146.70.119.158",
          "146.70.119.159",
          "146.70.119.160",
          "146.70.119.161",
          "146.70.119.162",
          "146.70.119.163",
          "146.70.119.164",
          "146.70.119.165",
          "146.70.119.166",
          "146.70.119.167",
          "146.70.119.168",
          "146.70.119.169",
          "146.70.119.170",
          "2a04:9dc0:18:71::b002",
          "2a04:9dc0:18:71::b003",
          "2a04:9dc0:18:71::b004",
          "2a04:9dc0:18:71::b005",
          "2a04:9dc0:18:71::b006",
          "2a04:9dc0:18:71::b007",
          "2a04:9dc0:18:71::b008",
          "2a04:9dc0:18:71::b009",
          "2a04:9dc0:18:71::b00a",
          "2a04:9dc0:18:71::b00b",
          "2a04:9dc0:18:71::b00c",
          "2a04:9dc0:18:71::b00d",
          "2a04:9dc0:18:71::b00e",
          "2a04:9dc0:18:71::b00f",
          "2a04:9dc0:18:71::b010",
          "2a04:9dc0:18:71::b011",
          "2a04:9dc0:18:71::b012",
          "2a04:9dc0:18:71::b013",
          "2a04:9dc0:18:71::b014",
          "2a04:9dc0:18:71::b015",
          "2a04:9dc0:18:71::b016",
          "2a04:9dc0:18:71::b017",
          "2a04:9dc0:18:71::b018",
          "2a04:9dc0:18:71::b019",
          "2a04:9dc0:18:71::b01a",
          "2a04:9dc0:18:71::b01b",
          "2a04:9dc0:18:71::b01c",
          "2a04:9dc0:18:71::b01d",
          "2a04:9dc0:18:71::b01e",
          "2a04:9dc0:18:71::b01f"
        ],
        "features": {
          "quic": {
            "addr_in": [
              "146.70.119.171",
              "146.70.119.172",
              "146.70.119.173",
              "146.70.119.174",
              "146.70.119.175",
              "146.70.119.176",
              "146.70.119.177",
              "146.70.119.178",
              "146.70.119.179",
              "146.70.119.180",
              "146.70.119.181",
              "146.70.119.182",
              "146.70.119.183",
              "146.70.119.184",
              "146.70.119.185",
              "146.70.119.186",
              "146.70.119.187",
              "146.70.119.188",
              "146.70.119.189",
              "146.70.119.190",
              "2a04:9dc0:18:71::c002",
              "2a04:9dc0:18:71::c003",
              "2a04:9dc0:18:71::c004",
              "2a04:9dc0:18:71::c005",
              "2a04:9dc0:18:71::c006",
              "2a04:9dc0:18:71::c007",
              "2a04:9dc0:18:71::c008",
              "2a04:9dc0:18:71::c009",
              "2a04:9dc0:18:71::c00a",
              "2a04:9dc0:18:71::c00b",
              "2a04:9dc0:18:71::c00c",
              "2a04:9dc0:18:71::c00d",
              "2a04:9dc0:18:71::c00e",
              "2a04:9dc0:18:71::c00f",
              "2a04:9dc0:18:71::c010",
              "2a04:9dc0:18:71::c011",
              "2a04:9dc0:18:71::c012",
              "2a04:9dc0:18:71::c013",
              "2a04:9dc0:18:71::c014",
              "2a04:9dc0:18:71::c015",
              "2a04:9dc0:18:71::c016",
              "2a04:9dc0:18:71::c017",
              "2a04:9dc0:18:71::c018",
              "2a04:9dc0:18:71::c019",
              "2a04:9dc0:18:71::c01a",
              "2a04:9dc0:18:71::c01b",
              "2a04:9dc0:18:71::c01c",
              "2a04:9dc0:18:71::c01d",
              "2a04:9dc0:18:71::c01e",
              "2a04:9dc0:18:71::c01f"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "gb-lon-wg-306.blockerad.eu"
          }
        }
      },
      {
        "hostname": "gb-lon-wg-308",
        "location": "gb-lon",
        "active": true,
        "owned": false,
        "provider": "M247",
        "stboot": true,
        "ipv4_addr_in": "135.136.58.130",
        "include_in_country": true,
        "weight": 100,
        "public_key": "Piwplz/ROMLZqL/GEeH3//jcMYQ5oatOeWcKZOi0Nyk=",
        "ipv6_addr_in": "2a04:9dc0:18:73::f001",
        "shadowsocks_extra_addr_in": [
          "135.136.58.141",
          "135.136.58.142",
          "135.136.58.143",
          "135.136.58.144",
          "135.136.58.145",
          "135.136.58.146",
          "135.136.58.147",
          "135.136.58.148",
          "135.136.58.149",
          "135.136.58.150",
          "2a04:9dc0:18:73::b002",
          "2a04:9dc0:18:73::b003",
          "2a04:9dc0:18:73::b004",
          "2a04:9dc0:18:73::b005",
          "2a04:9dc0:18:73::b006",
          "2a04:9dc0:18:73::b007",
          "2a04:9dc0:18:73::b008",
          "2a04:9dc0:18:73::b009",
          "2a04:9dc0:18:73::b00a",
          "2a04:9dc0:18:73::b00b",
          "2a04:9dc0:18:73::b00c",
          "2a04:9dc0:18:73::b00d",
          "2a04:9dc0:18:73::b00e",
          "2a04:9dc0:18:73::b00f",
          "2a04:9dc0:18:73::b010",
          "2a04:9dc0:18:73::b011",
          "2a04:9dc0:18:73::b012",
          "2a04:9dc0:18:73::b013",
          "2a04:9dc0:18:73::b014",
          "2a04:9dc0:18:73::b015",
          "2a04:9dc0:18:73::b016",
          "2a04:9dc0:18:73::b017",
          "2a04:9dc0:18:73::b018",
          "2a04:9dc0:18:73::b019",
          "2a04:9dc0:18:73::b01a",
          "2a04:9dc0:18:73::b01b",
          "2a04:9dc0:18:73::b01c",
          "2a04:9dc0:18:73::b01d",
          "2a04:9dc0:18:73::b01e",
          "2a04:9dc0:18:73::b01f"
        ],
        "features": {
          "quic": {
            "addr_in": [
              "135.136.58.151",
              "135.136.58.152",
              "135.136.58.153",
              "135.136.58.154",
              "135.136.58.155",
              "135.136.58.156",
              "135.136.58.157",
              "135.136.58.158",
              "135.136.58.159",
              "135.136.58.160",
              "2a04:9dc0:18:73::c002",
              "2a04:9dc0:18:73::c003",
              "2a04:9dc0:18:73::c004",
              "2a04:9dc0:18:73::c005",
              "2a04:9dc0:18:73::c006",
              "2a04:9dc0:18:73::c007",
              "2a04:9dc0:18:73::c008",
              "2a04:9dc0:18:73::c009",
              "2a04:9dc0:18:73::c00a",
              "2a04:9dc0:18:73::c00b",
              "2a04:9dc0:18:73::c00c",
              "2a04:9dc0:18:73::c00d",
              "2a04:9dc0:18:73::c00e",
              "2a04:9dc0:18:73::c00f",
              "2a04:9dc0:18:73::c010",
              "2a04:9dc0:18:73::c011",
              "2a04:9dc0:18:73::c012",
              "2a04:9dc0:18:73::c013",
              "2a04:9dc0:18:73::c014",
              "2a04:9dc0:18:73::c015",
              "2a04:9dc0:18:73::c016",
              "2a04:9dc0:18:73::c017",
              "2a04:9dc0:18:73::c018",
              "2a04:9dc0:18:73::c019",
              "2a04:9dc0:18:73::c01a",
              "2a04:9dc0:18:73::c01b",
              "2a04:9dc0:18:73::c01c",
              "2a04:9dc0:18:73::c01d",
              "2a04:9dc0:18:73::c01e",
              "2a04:9dc0:18:73::c01f"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "gb-lon-wg-308.blockerad.eu"
          }
        }
      },
      {
        "hostname": "gb-mnc-wg-001",
        "location": "gb-mnc",
        "active": true,
        "owned": false,
        "provider": "M247",
        "stboot": true,
        "ipv4_addr_in": "146.70.132.2",
        "include_in_country": false,
        "weight": 200,
        "public_key": "Q2khJLbTSFxmppPGHgq2HdxMQx7CczPZCgVpYZMoNnM=",
        "ipv6_addr_in": "2001:ac8:8b:104::f001",
        "daita": true,
        "shadowsocks_extra_addr_in": [
          "146.70.132.16",
          "146.70.132.17",
          "146.70.132.18",
          "146.70.132.19",
          "146.70.132.20",
          "146.70.132.21",
          "146.70.132.22",
          "146.70.132.23",
          "146.70.132.24",
          "146.70.132.25",
          "146.70.132.26",
          "2001:ac8:8b:104::b001",
          "2001:ac8:8b:104::b002",
          "2001:ac8:8b:104::b003",
          "2001:ac8:8b:104::b004",
          "2001:ac8:8b:104::b005",
          "2001:ac8:8b:104::b006",
          "2001:ac8:8b:104::b007",
          "2001:ac8:8b:104::b008",
          "2001:ac8:8b:104::b009",
          "2001:ac8:8b:104::b00a",
          "2001:ac8:8b:104::b00b",
          "2001:ac8:8b:104::b00c",
          "2001:ac8:8b:104::b00d",
          "2001:ac8:8b:104::b00e",
          "2001:ac8:8b:104::b00f",
          "2001:ac8:8b:104::b010",
          "2001:ac8:8b:104::b011",
          "2001:ac8:8b:104::b012",
          "2001:ac8:8b:104::b013",
          "2001:ac8:8b:104::b014",
          "2001:ac8:8b:104::b015",
          "2001:ac8:8b:104::b016",
          "2001:ac8:8b:104::b017",
          "2001:ac8:8b:104::b018",
          "2001:ac8:8b:104::b019",
          "2001:ac8:8b:104::b01a",
          "2001:ac8:8b:104::b01b",
          "2001:ac8:8b:104::b01c",
          "2001:ac8:8b:104::b01d",
          "2001:ac8:8b:104::b01e",
          "2001:ac8:8b:104::b01f"
        ],
        "features": {
          "daita": {},
          "lwo": {},
          "quic": {
            "addr_in": [
              "146.70.132.5",
              "146.70.132.6",
              "146.70.132.7",
              "146.70.132.8",
              "146.70.132.9",
              "146.70.132.10",
              "146.70.132.11",
              "146.70.132.12",
              "146.70.132.13",
              "146.70.132.14",
              "146.70.132.15",
              "2001:ac8:8b:104::c001",
              "2001:ac8:8b:104::c002",
              "2001:ac8:8b:104::c003",
              "2001:ac8:8b:104::c004",
              "2001:ac8:8b:104::c005",
              "2001:ac8:8b:104::c006",
              "2001:ac8:8b:104::c007",
              "2001:ac8:8b:104::c008",
              "2001:ac8:8b:104::c009",
              "2001:ac8:8b:104::c00a",
              "2001:ac8:8b:104::c00b",
              "2001:ac8:8b:104::c00c",
              "2001:ac8:8b:104::c00d",
              "2001:ac8:8b:104::c00e",
              "2001:ac8:8b:104::c00f",
              "2001:ac8:8b:104::c010",
              "2001:ac8:8b:104::c011",
              "2001:ac8:8b:104::c012",
              "2001:ac8:8b:104::c013",
              "2001:ac8:8b:104::c014",
              "2001:ac8:8b:104::c015",
              "2001:ac8:8b:104::c016",
              "2001:ac8:8b:104::c017",
              "2001:ac8:8b:104::c018",
              "2001:ac8:8b:104::c019",
              "2001:ac8:8b:104::c01a",
              "2001:ac8:8b:104::c01b",
              "2001:ac8:8b:104::c01c",
              "2001:ac8:8b:104::c01d",
              "2001:ac8:8b:104::c01e",
              "2001:ac8:8b:104::c01f"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "gb-mnc-wg-001.blockerad.eu"
          }
        }
      },
      {
        "hostname": "gb-mnc-wg-002",
        "location": "gb-mnc",
        "active": true,
        "owned": false,
        "provider": "M247",
        "stboot": true,
        "ipv4_addr_in": "135.136.22.2",
        "include_in_country": false,
        "weight": 200,
        "public_key": "1yWXDkKtU7NQU1349DS/nvGr0XjQgsZFhRt2P+fVtTg=",
        "ipv6_addr_in": "2001:ac8:8b:105::f001",
        "daita": true,
        "shadowsocks_extra_addr_in": [
          "135.136.22.16",
          "135.136.22.17",
          "135.136.22.18",
          "135.136.22.19",
          "135.136.22.20",
          "135.136.22.21",
          "135.136.22.22",
          "135.136.22.23",
          "135.136.22.24",
          "135.136.22.25",
          "135.136.22.26",
          "2001:ac8:8b:105::b001",
          "2001:ac8:8b:105::b002",
          "2001:ac8:8b:105::b003",
          "2001:ac8:8b:105::b004",
          "2001:ac8:8b:105::b005",
          "2001:ac8:8b:105::b006",
          "2001:ac8:8b:105::b007",
          "2001:ac8:8b:105::b008",
          "2001:ac8:8b:105::b009",
          "2001:ac8:8b:105::b00a",
          "2001:ac8:8b:105::b00b",
          "2001:ac8:8b:105::b00c",
          "2001:ac8:8b:105::b00d",
          "2001:ac8:8b:105::b00e",
          "2001:ac8:8b:105::b00f",
          "2001:ac8:8b:105::b010",
          "2001:ac8:8b:105::b011",
          "2001:ac8:8b:105::b012",
          "2001:ac8:8b:105::b013",
          "2001:ac8:8b:105::b014",
          "2001:ac8:8b:105::b015",
          "2001:ac8:8b:105::b016",
          "2001:ac8:8b:105::b017",
          "2001:ac8:8b:105::b018",
          "2001:ac8:8b:105::b019",
          "2001:ac8:8b:105::b01a",
          "2001:ac8:8b:105::b01b",
          "2001:ac8:8b:105::b01c",
          "2001:ac8:8b:105::b01d",
          "2001:ac8:8b:105::b01e",
          "2001:ac8:8b:105::b01f"
        ],
        "features": {
          "daita": {},
          "lwo": {},
          "quic": {
            "addr_in": [
              "135.136.22.5",
              "135.136.22.6",
              "135.136.22.7",
              "135.136.22.8",
              "135.136.22.9",
              "135.136.22.10",
              "135.136.22.11",
              "135.136.22.12",
              "135.136.22.13",
              "135.136.22.14",
              "135.136.22.15",
              "2001:ac8:8b:105::c001",
              "2001:ac8:8b:105::c002",
              "2001:ac8:8b:105::c003",
              "2001:ac8:8b:105::c004",
              "2001:ac8:8b:105::c005",
              "2001:ac8:8b:105::c006",
              "2001:ac8:8b:105::c007",
              "2001:ac8:8b:105::c008",
              "2001:ac8:8b:105::c009",
              "2001:ac8:8b:105::c00a",
              "2001:ac8:8b:105::c00b",
              "2001:ac8:8b:105::c00c",
              "2001:ac8:8b:105::c00d",
              "2001:ac8:8b:105::c00e",
              "2001:ac8:8b:105::c00f",
              "2001:ac8:8b:105::c010",
              "2001:ac8:8b:105::c011",
              "2001:ac8:8b:105::c012",
              "2001:ac8:8b:105::c013",
              "2001:ac8:8b:105::c014",
              "2001:ac8:8b:105::c015",
              "2001:ac8:8b:105::c016",
              "2001:ac8:8b:105::c017",
              "2001:ac8:8b:105::c018",
              "2001:ac8:8b:105::c019",
              "2001:ac8:8b:105::c01a",
              "2001:ac8:8b:105::c01b",
              "2001:ac8:8b:105::c01c",
              "2001:ac8:8b:105::c01d",
              "2001:ac8:8b:105::c01e",
              "2001:ac8:8b:105::c01f"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "gb-mnc-wg-002.blockerad.eu"
          }
        }
      },
      {
        "hostname": "gb-mnc-wg-003",
        "location": "gb-mnc",
        "active": true,
        "owned": false,
        "provider": "M247",
        "stboot": true,
        "ipv4_addr_in": "135.136.22.130",
        "include_in_country": true,
        "weight": 100,
        "public_key": "3pCAP2xIdWn3O83V9tzuF0W5fmLkhFO+od0VsU3Kiy0=",
        "ipv6_addr_in": "2001:ac8:8b:106::f001",
        "daita": true,
        "shadowsocks_extra_addr_in": [
          "135.136.22.144",
          "135.136.22.145",
          "135.136.22.146",
          "135.136.22.147",
          "135.136.22.148",
          "135.136.22.149",
          "135.136.22.150",
          "135.136.22.151",
          "135.136.22.152",
          "135.136.22.153",
          "135.136.22.154",
          "2001:ac8:8b:106::b001",
          "2001:ac8:8b:106::b002",
          "2001:ac8:8b:106::b003",
          "2001:ac8:8b:106::b004",
          "2001:ac8:8b:106::b005",
          "2001:ac8:8b:106::b006",
          "2001:ac8:8b:106::b007",
          "2001:ac8:8b:106::b008",
          "2001:ac8:8b:106::b009",
          "2001:ac8:8b:106::b00a",
          "2001:ac8:8b:106::b00b",
          "2001:ac8:8b:106::b00c",
          "2001:ac8:8b:106::b00d",
          "2001:ac8:8b:106::b00e",
          "2001:ac8:8b:106::b00f",
          "2001:ac8:8b:106::b010",
          "2001:ac8:8b:106::b011",
          "2001:ac8:8b:106::b012",
          "2001:ac8:8b:106::b013",
          "2001:ac8:8b:106::b014",
          "2001:ac8:8b:106::b015",
          "2001:ac8:8b:106::b016",
          "2001:ac8:8b:106::b017",
          "2001:ac8:8b:106::b018",
          "2001:ac8:8b:106::b019",
          "2001:ac8:8b:106::b01a",
          "2001:ac8:8b:106::b01b",
          "2001:ac8:8b:106::b01c",
          "2001:ac8:8b:106::b01d",
          "2001:ac8:8b:106::b01e",
          "2001:ac8:8b:106::b01f"
        ],
        "features": {
          "daita": {},
          "lwo": {},
          "quic": {
            "addr_in": [
              "135.136.22.133",
              "135.136.22.134",
              "135.136.22.135",
              "135.136.22.136",
              "135.136.22.137",
              "135.136.22.138",
              "135.136.22.139",
              "135.136.22.140",
              "135.136.22.141",
              "135.136.22.142",
              "135.136.22.143",
              "2001:ac8:8b:106::c001",
              "2001:ac8:8b:106::c002",
              "2001:ac8:8b:106::c003",
              "2001:ac8:8b:106::c004",
              "2001:ac8:8b:106::c005",
              "2001:ac8:8b:106::c006",
              "2001:ac8:8b:106::c007",
              "2001:ac8:8b:106::c008",
              "2001:ac8:8b:106::c009",
              "2001:ac8:8b:106::c00a",
              "2001:ac8:8b:106::c00b",
              "2001:ac8:8b:106::c00c",
              "2001:ac8:8b:106::c00d",
              "2001:ac8:8b:106::c00e",
              "2001:ac8:8b:106::c00f",
              "2001:ac8:8b:106::c010",
              "2001:ac8:8b:106::c011",
              "2001:ac8:8b:106::c012",
              "2001:ac8:8b:106::c013",
              "2001:ac8:8b:106::c014",
              "2001:ac8:8b:106::c015",
              "2001:ac8:8b:106::c016",
              "2001:ac8:8b:106::c017",
              "2001:ac8:8b:106::c018",
              "2001:ac8:8b:106::c019",
              "2001:ac8:8b:106::c01a",
              "2001:ac8:8b:106::c01b",
              "2001:ac8:8b:106::c01c",
              "2001:ac8:8b:106::c01d",
              "2001:ac8:8b:106::c01e",
              "2001:ac8:8b:106::c01f"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "gb-mnc-wg-003.blockerad.eu"
          }
        }
      },
      {
        "hostname": "gb-mnc-wg-004",
        "location": "gb-mnc",
        "active": true,
        "owned": false,
        "provider": "M247",
        "stboot": true,
        "ipv4_addr_in": "135.136.21.2",
        "include_in_country": true,
        "weight": 100,
        "public_key": "BvBubnaVVynalBjiHxHxbtBLLMBC+suHZdonTpBT4zg=",
        "ipv6_addr_in": "2001:ac8:8b:107::f001",
        "daita": true,
        "shadowsocks_extra_addr_in": [
          "135.136.21.13",
          "135.136.21.14",
          "135.136.21.15",
          "135.136.21.16",
          "135.136.21.17",
          "135.136.21.18",
          "135.136.21.19",
          "135.136.21.20",
          "135.136.21.21",
          "135.136.21.22",
          "2001:ac8:8b:107::b002",
          "2001:ac8:8b:107::b003",
          "2001:ac8:8b:107::b004",
          "2001:ac8:8b:107::b005",
          "2001:ac8:8b:107::b006",
          "2001:ac8:8b:107::b007",
          "2001:ac8:8b:107::b008",
          "2001:ac8:8b:107::b009",
          "2001:ac8:8b:107::b00a",
          "2001:ac8:8b:107::b00b",
          "2001:ac8:8b:107::b00c",
          "2001:ac8:8b:107::b00d",
          "2001:ac8:8b:107::b00e",
          "2001:ac8:8b:107::b00f",
          "2001:ac8:8b:107::b010",
          "2001:ac8:8b:107::b011",
          "2001:ac8:8b:107::b012",
          "2001:ac8:8b:107::b013",
          "2001:ac8:8b:107::b014",
          "2001:ac8:8b:107::b015",
          "2001:ac8:8b:107::b016",
          "2001:ac8:8b:107::b017",
          "2001:ac8:8b:107::b018",
          "2001:ac8:8b:107::b019",
          "2001:ac8:8b:107::b01a",
          "2001:ac8:8b:107::b01b",
          "2001:ac8:8b:107::b01c",
          "2001:ac8:8b:107::b01d",
          "2001:ac8:8b:107::b01e",
          "2001:ac8:8b:107::b01f"
        ],
        "features": {
          "daita": {},
          "lwo": {},
          "quic": {
            "addr_in": [
              "135.136.21.23",
              "135.136.21.24",
              "135.136.21.25",
              "135.136.21.26",
              "135.136.21.27",
              "135.136.21.28",
              "135.136.21.29",
              "135.136.21.30",
              "135.136.21.31",
              "135.136.21.32",
              "2001:ac8:8b:107::c002",
              "2001:ac8:8b:107::c003",
              "2001:ac8:8b:107::c004",
              "2001:ac8:8b:107::c005",
              "2001:ac8:8b:107::c006",
              "2001:ac8:8b:107::c007",
              "2001:ac8:8b:107::c008",
              "2001:ac8:8b:107::c009",
              "2001:ac8:8b:107::c00a",
              "2001:ac8:8b:107::c00b",
              "2001:ac8:8b:107::c00c",
              "2001:ac8:8b:107::c00d",
              "2001:ac8:8b:107::c00e",
              "2001:ac8:8b:107::c00f",
              "2001:ac8:8b:107::c010",
              "2001:ac8:8b:107::c011",
              "2001:ac8:8b:107::c012",
              "2001:ac8:8b:107::c013",
              "2001:ac8:8b:107::c014",
              "2001:ac8:8b:107::c015",
              "2001:ac8:8b:107::c016",
              "2001:ac8:8b:107::c017",
              "2001:ac8:8b:107::c018",
              "2001:ac8:8b:107::c019",
              "2001:ac8:8b:107::c01a",
              "2001:ac8:8b:107::c01b",
              "2001:ac8:8b:107::c01c",
              "2001:ac8:8b:107::c01d",
              "2001:ac8:8b:107::c01e",
              "2001:ac8:8b:107::c01f"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "gb-mnc-wg-004.blockerad.eu"
          }
        }
      },
      {
        "hostname": "gb-mnc-wg-201",
        "location": "gb-mnc",
        "active": true,
        "owned": false,
        "provider": "Veloxserv",
        "stboot": true,
        "ipv4_addr_in": "167.160.13.3",
        "include_in_country": false,
        "weight": 400,
        "public_key": "x3APiw/mxJzdD+3WAPxTFnvOZHVotm6SGomHtMoR4Hg=",
        "ipv6_addr_in": "2a03:ee40:3304::f001",
        "shadowsocks_extra_addr_in": [
          "167.160.13.14"
        ],
        "features": {
          "lwo": {}
        }
      },
      {
        "hostname": "gb-mnc-wg-202",
        "location": "gb-mnc",
        "active": true,
        "owned": false,
        "provider": "Veloxserv",
        "stboot": true,
        "ipv4_addr_in": "167.160.13.127",
        "include_in_country": false,
        "weight": 1,
        "public_key": "OpQgffPufxbHQUbItRoezS2V+yAEBKZ10jfU82YIByI=",
        "ipv6_addr_in": "2a03:ee40:3304::f101",
        "shadowsocks_extra_addr_in": [
          "167.160.13.139"
        ]
      },
      {
        "hostname": "gr-ath-wg-101",
        "location": "gr-ath",
        "active": true,
        "owned": false,
        "provider": "DataPacket",
        "stboot": true,
        "ipv4_addr_in": "149.102.246.2",
        "include_in_country": true,
        "weight": 100,
        "public_key": "li+thkAD7s6IZDgUoiKw4YSjM/U1q203PuthMzIJIU0=",
        "ipv6_addr_in": "2a02:6ea0:f501:2::f001",
        "features": {
          "lwo": {}
        }
      },
      {
        "hostname": "gr-ath-wg-102",
        "location": "gr-ath",
        "active": true,
        "owned": false,
        "provider": "DataPacket",
        "stboot": true,
        "ipv4_addr_in": "149.102.246.15",
        "include_in_country": true,
        "weight": 100,
        "public_key": "OL0gbjlNt1s26CDQjRP9wgMZbgYff7/xyUI8ypOn01s=",
        "ipv6_addr_in": "2a02:6ea0:f501:3::f001",
        "features": {
          "lwo": {}
        }
      },
      {
        "hostname": "hk-hkg-wg-201",
        "location": "hk-hkg",
        "active": true,
        "owned": false,
        "provider": "xtom",
        "stboot": true,
        "ipv4_addr_in": "103.125.233.18",
        "include_in_country": true,
        "weight": 100,
        "public_key": "Oxh13dmwY6nNUa5rVHr7sLiFOj0fjzsaAUAUV87/nGs=",
        "ipv6_addr_in": "2403:2c81:1000::a06f",
        "shadowsocks_extra_addr_in": [
          "103.125.233.3",
          "103.125.233.4",
          "103.125.233.5",
          "103.125.233.6",
          "103.125.233.7",
          "103.125.233.8",
          "2403:2c81:1000::b002",
          "2403:2c81:1000::b003",
          "2403:2c81:1000::b004",
          "2403:2c81:1000::b005",
          "2403:2c81:1000::b006",
          "2403:2c81:1000::b007",
          "2403:2c81:1000::b008",
          "2403:2c81:1000::b009",
          "2403:2c81:1000::b00a",
          "2403:2c81:1000::b00b",
          "2403:2c81:1000::b00c",
          "2403:2c81:1000::b00d",
          "2403:2c81:1000::b00e",
          "2403:2c81:1000::b00f",
          "2403:2c81:1000::b010",
          "2403:2c81:1000::b011",
          "2403:2c81:1000::b012",
          "2403:2c81:1000::b013",
          "2403:2c81:1000::b014",
          "2403:2c81:1000::b015",
          "2403:2c81:1000::b016",
          "2403:2c81:1000::b017",
          "2403:2c81:1000::b018",
          "2403:2c81:1000::b019",
          "2403:2c81:1000::b01a",
          "2403:2c81:1000::b01b",
          "2403:2c81:1000::b01c",
          "2403:2c81:1000::b01d",
          "2403:2c81:1000::b01e",
          "2403:2c81:1000::b01f"
        ],
        "features": {
          "lwo": {}
        }
      },
      {
        "hostname": "hk-hkg-wg-202",
        "location": "hk-hkg",
        "active": false,
        "owned": false,
        "provider": "xtom",
        "stboot": true,
        "ipv4_addr_in": "103.125.233.3",
        "include_in_country": false,
        "weight": 100,
        "public_key": "zmhMPHfkgo+uQxP+l919Gw7cj5NTatg9nMU37eEUWis=",
        "ipv6_addr_in": "2403:2c81:1000::a05f"
      },
      {
        "hostname": "hk-hkg-wg-203",
        "location": "hk-hkg",
        "active": true,
        "owned": false,
        "provider": "xtom",
        "stboot": true,
        "ipv4_addr_in": "103.125.233.33",
        "include_in_country": true,
        "weight": 100,
        "public_key": "e3vqR6xVRps5ZlkL3/i6bHlrjeM/kNz+pWfSJ00UMQs=",
        "ipv6_addr_in": "2403:2c81:1000::f301",
        "shadowsocks_extra_addr_in": [
          "103.125.233.35",
          "103.125.233.36",
          "103.125.233.37",
          "2403:2c81:1000::b302",
          "2403:2c81:1000::b303",
          "2403:2c81:1000::b304",
          "2403:2c81:1000::b305",
          "2403:2c81:1000::b306",
          "2403:2c81:1000::b307",
          "2403:2c81:1000::b308",
          "2403:2c81:1000::b309",
          "2403:2c81:1000::b30a",
          "2403:2c81:1000::b30b",
          "2403:2c81:1000::b30c",
          "2403:2c81:1000::b30d",
          "2403:2c81:1000::b30e",
          "2403:2c81:1000::b30f",
          "2403:2c81:1000::b310",
          "2403:2c81:1000::b311",
          "2403:2c81:1000::b312",
          "2403:2c81:1000::b313",
          "2403:2c81:1000::b314",
          "2403:2c81:1000::b315",
          "2403:2c81:1000::b316",
          "2403:2c81:1000::b317",
          "2403:2c81:1000::b318",
          "2403:2c81:1000::b319",
          "2403:2c81:1000::b31a",
          "2403:2c81:1000::b31b",
          "2403:2c81:1000::b31c",
          "2403:2c81:1000::b31d",
          "2403:2c81:1000::b31e",
          "2403:2c81:1000::b31f"
        ]
      },
      {
        "hostname": "hk-hkg-wg-301",
        "location": "hk-hkg",
        "active": true,
        "owned": false,
        "provider": "M247",
        "stboot": true,
        "ipv4_addr_in": "146.70.224.2",
        "include_in_country": true,
        "weight": 100,
        "public_key": "qbvU06SBHXnqMnpb49rnE0yC4AOWQcWl2bEScu18dh8=",
        "ipv6_addr_in": "2001:ac8:a:f::f001",
        "features": {
          "lwo": {},
          "quic": {
            "addr_in": [
              "146.70.224.62"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "hk-hkg-wg-301.blockerad.eu"
          }
        }
      },
      {
        "hostname": "hk-hkg-wg-302",
        "location": "hk-hkg",
        "active": true,
        "owned": false,
        "provider": "M247",
        "stboot": true,
        "ipv4_addr_in": "146.70.224.66",
        "include_in_country": true,
        "weight": 100,
        "public_key": "7FADgmd9KyAVs3eFJE/ob9tV3E6m/klONEEIOfCoPTU=",
        "ipv6_addr_in": "2001:ac8:a:19::f001"
      },
      {
        "hostname": "hk-hkg-wg-303",
        "location": "hk-hkg",
        "active": true,
        "owned": false,
        "provider": "M247",
        "stboot": true,
        "ipv4_addr_in": "146.70.224.196",
        "include_in_country": true,
        "weight": 100,
        "public_key": "RtTENHB7VBUiowxtdAzopcb2Fvd+OFneN73k13oPUEo=",
        "ipv6_addr_in": "2001:ac8:a:1b::f001"
      },
      {
        "hostname": "hr-zag-wg-001",
        "location": "hr-zag",
        "active": true,
        "owned": false,
        "provider": "DataPacket",
        "stboot": true,
        "ipv4_addr_in": "154.47.29.2",
        "include_in_country": true,
        "weight": 100,
        "public_key": "PJvsgLogdAgZiVSxwTDyk9ri02mLZGuElklHShIjDGM=",
        "ipv6_addr_in": "2a02:6ea0:f401:1::a01f"
      },
      {
        "hostname": "hr-zag-wg-002",
        "location": "hr-zag",
        "active": true,
        "owned": false,
        "provider": "DataPacket",
        "stboot": true,
        "ipv4_addr_in": "154.47.29.15",
        "include_in_country": true,
        "weight": 100,
        "public_key": "V0iDOyLSj870sjGGenDvAWqJudlPKDc212cQN85snEo=",
        "ipv6_addr_in": "2a02:6ea0:f401:2::a01f"
      },
      {
        "hostname": "hu-bud-wg-101",
        "location": "hu-bud",
        "active": true,
        "owned": false,
        "provider": "M247",
        "stboot": true,
        "ipv4_addr_in": "146.70.196.194",
        "include_in_country": true,
        "weight": 100,
        "public_key": "u+h0GmQJ8UBaMTi2BP9Ls6UUszcGC51y6vTmNr/y+AU=",
        "ipv6_addr_in": "2001:ac8:26:55::f001"
      },
      {
        "hostname": "hu-bud-wg-102",
        "location": "hu-bud",
        "active": true,
        "owned": false,
        "provider": "M247",
        "stboot": true,
        "ipv4_addr_in": "146.70.196.130",
        "include_in_country": true,
        "weight": 100,
        "public_key": "iEWLm2F4xV013ZETeZcT1dyUd5O+JnyndHso8RP8txw=",
        "ipv6_addr_in": "2001:ac8:26:54::f001"
      },
      {
        "hostname": "hu-bud-wg-201",
        "location": "hu-bud",
        "active": true,
        "owned": false,
        "provider": "DataPacket",
        "stboot": true,
        "ipv4_addr_in": "79.127.182.130",
        "include_in_country": true,
        "weight": 100,
        "public_key": "RPhw+caiytSurUMQfZhEFlxGK83xcwWMNtXCkpTqJBI=",
        "ipv6_addr_in": "2a02:6ea0:5700:1::f001",
        "shadowsocks_extra_addr_in": [
          "79.127.182.132"
        ],
        "features": {
          "lwo": {}
        }
      },
      {
        "hostname": "hu-bud-wg-202",
        "location": "hu-bud",
        "active": true,
        "owned": false,
        "provider": "DataPacket",
        "stboot": true,
        "ipv4_addr_in": "79.127.182.160",
        "include_in_country": true,
        "weight": 100,
        "public_key": "xiC/w18znzSImAuzMYpP5NH+1T912cwZXo8M1V4Ruiw=",
        "ipv6_addr_in": "2a02:6ea0:5700:2::f001",
        "shadowsocks_extra_addr_in": [
          "79.127.182.162"
        ],
        "features": {
          "lwo": {}
        }
      },
      {
        "hostname": "id-jpu-wg-001",
        "location": "id-jpu",
        "active": true,
        "owned": false,
        "provider": "Zenlayer",
        "stboot": true,
        "ipv4_addr_in": "129.227.46.130",
        "include_in_country": true,
        "weight": 100,
        "public_key": "XYQvOrRqu8j521Hy/8+jGRDLZoSAssOvCectyKz350Y=",
        "ipv6_addr_in": "2602:ffe4:c0d:801d::f001"
      },
      {
        "hostname": "id-jpu-wg-002",
        "location": "id-jpu",
        "active": true,
        "owned": false,
        "provider": "Zenlayer",
        "stboot": true,
        "ipv4_addr_in": "129.227.46.162",
        "include_in_country": true,
        "weight": 100,
        "public_key": "gWsH1w7lTYbsS+WxsE6w6vtXSAJoHM6PhDX5DFMYM1k=",
        "ipv6_addr_in": "2602:ffe4:c0d:801e::f101",
        "features": {
          "lwo": {}
        }
      },
      {
        "hostname": "ie-dub-wg-101",
        "location": "ie-dub",
        "active": true,
        "owned": false,
        "provider": "M247",
        "stboot": true,
        "ipv4_addr_in": "146.70.189.2",
        "include_in_country": true,
        "weight": 100,
        "public_key": "2r0vPpM71ZXpseWXTXw3iwn2sjIHOTpw1V9sp03bLWw=",
        "ipv6_addr_in": "2001:ac8:88:107::f001",
        "daita": true,
        "shadowsocks_extra_addr_in": [
          "146.70.189.16",
          "146.70.189.17",
          "146.70.189.18",
          "146.70.189.19",
          "146.70.189.20",
          "146.70.189.21",
          "146.70.189.22",
          "146.70.189.23",
          "146.70.189.24",
          "146.70.189.25",
          "146.70.189.26",
          "2001:ac8:88:107::b002",
          "2001:ac8:88:107::b003",
          "2001:ac8:88:107::b004",
          "2001:ac8:88:107::b005",
          "2001:ac8:88:107::b006",
          "2001:ac8:88:107::b007",
          "2001:ac8:88:107::b008",
          "2001:ac8:88:107::b009",
          "2001:ac8:88:107::b00a",
          "2001:ac8:88:107::b00b",
          "2001:ac8:88:107::b00c",
          "2001:ac8:88:107::b00d",
          "2001:ac8:88:107::b00e",
          "2001:ac8:88:107::b00f",
          "2001:ac8:88:107::b010",
          "2001:ac8:88:107::b011",
          "2001:ac8:88:107::b012",
          "2001:ac8:88:107::b013",
          "2001:ac8:88:107::b014",
          "2001:ac8:88:107::b015",
          "2001:ac8:88:107::b016",
          "2001:ac8:88:107::b017",
          "2001:ac8:88:107::b018",
          "2001:ac8:88:107::b019",
          "2001:ac8:88:107::b01a",
          "2001:ac8:88:107::b01b",
          "2001:ac8:88:107::b01c",
          "2001:ac8:88:107::b01d",
          "2001:ac8:88:107::b01e",
          "2001:ac8:88:107::b01f"
        ],
        "features": {
          "daita": {},
          "quic": {
            "addr_in": [
              "146.70.189.5",
              "146.70.189.6",
              "146.70.189.7",
              "146.70.189.8",
              "146.70.189.9",
              "146.70.189.10",
              "146.70.189.11",
              "146.70.189.12",
              "146.70.189.13",
              "146.70.189.14",
              "146.70.189.15",
              "2001:ac8:88:107::c002",
              "2001:ac8:88:107::c003",
              "2001:ac8:88:107::c004",
              "2001:ac8:88:107::c005",
              "2001:ac8:88:107::c006",
              "2001:ac8:88:107::c007",
              "2001:ac8:88:107::c008",
              "2001:ac8:88:107::c009",
              "2001:ac8:88:107::c00a",
              "2001:ac8:88:107::c00b",
              "2001:ac8:88:107::c00c",
              "2001:ac8:88:107::c00d",
              "2001:ac8:88:107::c00e",
              "2001:ac8:88:107::c00f",
              "2001:ac8:88:107::c010",
              "2001:ac8:88:107::c011",
              "2001:ac8:88:107::c012",
              "2001:ac8:88:107::c013",
              "2001:ac8:88:107::c014",
              "2001:ac8:88:107::c015",
              "2001:ac8:88:107::c016",
              "2001:ac8:88:107::c017",
              "2001:ac8:88:107::c018",
              "2001:ac8:88:107::c019",
              "2001:ac8:88:107::c01a",
              "2001:ac8:88:107::c01b",
              "2001:ac8:88:107::c01c",
              "2001:ac8:88:107::c01d",
              "2001:ac8:88:107::c01e",
              "2001:ac8:88:107::c01f"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "ie-dub-wg-101.blockerad.eu"
          }
        }
      },
      {
        "hostname": "ie-dub-wg-102",
        "location": "ie-dub",
        "active": true,
        "owned": false,
        "provider": "M247",
        "stboot": true,
        "ipv4_addr_in": "146.70.189.130",
        "include_in_country": true,
        "weight": 100,
        "public_key": "2RSnfqTRb0BL/bPaKGj0OA/qopQaNG1qtzEH2Y8JyjE=",
        "ipv6_addr_in": "2001:ac8:88:108::f001",
        "shadowsocks_extra_addr_in": [
          "146.70.189.144",
          "146.70.189.145",
          "146.70.189.146",
          "146.70.189.147",
          "146.70.189.148",
          "146.70.189.149",
          "146.70.189.150",
          "146.70.189.151",
          "146.70.189.152",
          "146.70.189.153",
          "146.70.189.154",
          "2001:ac8:88:108::b002",
          "2001:ac8:88:108::b003",
          "2001:ac8:88:108::b004",
          "2001:ac8:88:108::b005",
          "2001:ac8:88:108::b006",
          "2001:ac8:88:108::b007",
          "2001:ac8:88:108::b008",
          "2001:ac8:88:108::b009",
          "2001:ac8:88:108::b00a",
          "2001:ac8:88:108::b00b",
          "2001:ac8:88:108::b00c",
          "2001:ac8:88:108::b00d",
          "2001:ac8:88:108::b00e",
          "2001:ac8:88:108::b00f",
          "2001:ac8:88:108::b010",
          "2001:ac8:88:108::b011",
          "2001:ac8:88:108::b012",
          "2001:ac8:88:108::b013",
          "2001:ac8:88:108::b014",
          "2001:ac8:88:108::b015",
          "2001:ac8:88:108::b016",
          "2001:ac8:88:108::b017",
          "2001:ac8:88:108::b018",
          "2001:ac8:88:108::b019",
          "2001:ac8:88:108::b01a",
          "2001:ac8:88:108::b01b",
          "2001:ac8:88:108::b01c",
          "2001:ac8:88:108::b01d",
          "2001:ac8:88:108::b01e",
          "2001:ac8:88:108::b01f"
        ],
        "features": {
          "lwo": {},
          "quic": {
            "addr_in": [
              "146.70.189.133",
              "146.70.189.134",
              "146.70.189.135",
              "146.70.189.136",
              "146.70.189.137",
              "146.70.189.138",
              "146.70.189.139",
              "146.70.189.140",
              "146.70.189.141",
              "146.70.189.142",
              "146.70.189.143",
              "2001:ac8:88:108::c002",
              "2001:ac8:88:108::c003",
              "2001:ac8:88:108::c004",
              "2001:ac8:88:108::c005",
              "2001:ac8:88:108::c006",
              "2001:ac8:88:108::c007",
              "2001:ac8:88:108::c008",
              "2001:ac8:88:108::c009",
              "2001:ac8:88:108::c00a",
              "2001:ac8:88:108::c00b",
              "2001:ac8:88:108::c00c",
              "2001:ac8:88:108::c00d",
              "2001:ac8:88:108::c00e",
              "2001:ac8:88:108::c00f",
              "2001:ac8:88:108::c010",
              "2001:ac8:88:108::c011",
              "2001:ac8:88:108::c012",
              "2001:ac8:88:108::c013",
              "2001:ac8:88:108::c014",
              "2001:ac8:88:108::c015",
              "2001:ac8:88:108::c016",
              "2001:ac8:88:108::c017",
              "2001:ac8:88:108::c018",
              "2001:ac8:88:108::c019",
              "2001:ac8:88:108::c01a",
              "2001:ac8:88:108::c01b",
              "2001:ac8:88:108::c01c",
              "2001:ac8:88:108::c01d",
              "2001:ac8:88:108::c01e",
              "2001:ac8:88:108::c01f"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "ie-dub-wg-102.blockerad.eu"
          }
        }
      },
      {
        "hostname": "ie-dub-wg-103",
        "location": "ie-dub",
        "active": true,
        "owned": false,
        "provider": "M247",
        "stboot": true,
        "ipv4_addr_in": "130.195.213.130",
        "include_in_country": true,
        "weight": 100,
        "public_key": "/Q7cQuVZo0IYckUncGSzRnQssR1DC5veZWaAnf/yDTI=",
        "ipv6_addr_in": "2001:ac8:88:109::f001",
        "shadowsocks_extra_addr_in": [
          "130.195.213.144",
          "130.195.213.145",
          "130.195.213.146",
          "130.195.213.147",
          "130.195.213.148",
          "130.195.213.149",
          "130.195.213.150",
          "130.195.213.151",
          "130.195.213.152",
          "130.195.213.153",
          "130.195.213.154",
          "2001:ac8:88:109::b002",
          "2001:ac8:88:109::b003",
          "2001:ac8:88:109::b004",
          "2001:ac8:88:109::b005",
          "2001:ac8:88:109::b006",
          "2001:ac8:88:109::b007",
          "2001:ac8:88:109::b008",
          "2001:ac8:88:109::b009",
          "2001:ac8:88:109::b00a",
          "2001:ac8:88:109::b00b",
          "2001:ac8:88:109::b00c",
          "2001:ac8:88:109::b00d",
          "2001:ac8:88:109::b00e",
          "2001:ac8:88:109::b00f",
          "2001:ac8:88:109::b010",
          "2001:ac8:88:109::b011",
          "2001:ac8:88:109::b012",
          "2001:ac8:88:109::b013",
          "2001:ac8:88:109::b014",
          "2001:ac8:88:109::b015",
          "2001:ac8:88:109::b016",
          "2001:ac8:88:109::b017",
          "2001:ac8:88:109::b018",
          "2001:ac8:88:109::b019",
          "2001:ac8:88:109::b01a",
          "2001:ac8:88:109::b01b",
          "2001:ac8:88:109::b01c",
          "2001:ac8:88:109::b01d",
          "2001:ac8:88:109::b01e",
          "2001:ac8:88:109::b01f"
        ],
        "features": {
          "lwo": {},
          "quic": {
            "addr_in": [
              "130.195.213.133",
              "130.195.213.134",
              "130.195.213.135",
              "130.195.213.136",
              "130.195.213.137",
              "130.195.213.138",
              "130.195.213.139",
              "130.195.213.140",
              "130.195.213.141",
              "130.195.213.142",
              "130.195.213.143",
              "2001:ac8:88:109::c002",
              "2001:ac8:88:109::c003",
              "2001:ac8:88:109::c004",
              "2001:ac8:88:109::c005",
              "2001:ac8:88:109::c006",
              "2001:ac8:88:109::c007",
              "2001:ac8:88:109::c008",
              "2001:ac8:88:109::c009",
              "2001:ac8:88:109::c00a",
              "2001:ac8:88:109::c00b",
              "2001:ac8:88:109::c00c",
              "2001:ac8:88:109::c00d",
              "2001:ac8:88:109::c00e",
              "2001:ac8:88:109::c00f",
              "2001:ac8:88:109::c010",
              "2001:ac8:88:109::c011",
              "2001:ac8:88:109::c012",
              "2001:ac8:88:109::c013",
              "2001:ac8:88:109::c014",
              "2001:ac8:88:109::c015",
              "2001:ac8:88:109::c016",
              "2001:ac8:88:109::c017",
              "2001:ac8:88:109::c018",
              "2001:ac8:88:109::c019",
              "2001:ac8:88:109::c01a",
              "2001:ac8:88:109::c01b",
              "2001:ac8:88:109::c01c",
              "2001:ac8:88:109::c01d",
              "2001:ac8:88:109::c01e",
              "2001:ac8:88:109::c01f"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "ie-dub-wg-103.blockerad.eu"
          }
        }
      },
      {
        "hostname": "il-tlv-wg-101",
        "location": "il-tlv",
        "active": true,
        "owned": false,
        "provider": "DataPacket",
        "stboot": true,
        "ipv4_addr_in": "169.150.227.197",
        "include_in_country": true,
        "weight": 100,
        "public_key": "XOedjVJaT2IrEDJbzvtZeL4hP5uPRHzFxvD1cwVwUFo=",
        "ipv6_addr_in": "2a02:6ea0:3b00:1::a01f"
      },
      {
        "hostname": "il-tlv-wg-102",
        "location": "il-tlv",
        "active": true,
        "owned": false,
        "provider": "DataPacket",
        "stboot": true,
        "ipv4_addr_in": "169.150.227.210",
        "include_in_country": true,
        "weight": 100,
        "public_key": "UNeML4rXjvOerAstTNf4gG5B+OfjVzjSQrWE6mrswD0=",
        "ipv6_addr_in": "2a02:6ea0:3b00:2::a02f"
      },
      {
        "hostname": "il-tlv-wg-103",
        "location": "il-tlv",
        "active": true,
        "owned": false,
        "provider": "DataPacket",
        "stboot": true,
        "ipv4_addr_in": "169.150.227.222",
        "include_in_country": true,
        "weight": 100,
        "public_key": "11FJ/NY3jaAw1PSYG9w7bxsMxAzlI+1p8/juh1LJPT0=",
        "ipv6_addr_in": "2a02:6ea0:3b00:3::a03f"
      },
      {
        "hostname": "it-mil-wg-001",
        "location": "it-mil",
        "active": true,
        "owned": false,
        "provider": "DataPacket",
        "stboot": true,
        "ipv4_addr_in": "178.249.211.66",
        "include_in_country": true,
        "weight": 200,
        "public_key": "Sa9fFFthvihGMO4cPExJ7ZaWSHNYoXmOqZMvJsaxOVk=",
        "ipv6_addr_in": "2a02:6ea0:d509:1::a09f",
        "features": {
          "lwo": {}
        }
      },
      {
        "hostname": "it-mil-wg-002",
        "location": "it-mil",
        "active": true,
        "owned": false,
        "provider": "DataPacket",
        "stboot": true,
        "ipv4_addr_in": "178.249.211.79",
        "include_in_country": true,
        "weight": 200,
        "public_key": "RJ7e37UEP6hfyLQM/lJ2K5wcZOJQFhm2VhFaBniH1kg=",
        "ipv6_addr_in": "2a02:6ea0:d509:2::a10f",
        "features": {
          "lwo": {}
        }
      },
      {
        "hostname": "it-mil-wg-003",
        "location": "it-mil",
        "active": true,
        "owned": false,
        "provider": "DataPacket",
        "stboot": true,
        "ipv4_addr_in": "178.249.211.92",
        "include_in_country": true,
        "weight": 200,
        "public_key": "WOyki5Gzoez07X7D3jAhG68hpoiYIWAx1yypVbkQaVY=",
        "ipv6_addr_in": "2a02:6ea0:d509:3::a11f"
      },
      {
        "hostname": "it-mil-wg-201",
        "location": "it-mil",
        "active": true,
        "owned": false,
        "provider": "M247",
        "stboot": true,
        "ipv4_addr_in": "146.70.225.2",
        "include_in_country": true,
        "weight": 100,
        "public_key": "XHwDoIVZGoVfUYbfcPiRp1LhaOCDc0A3QrS72i3ztBw=",
        "ipv6_addr_in": "2001:ac8:24:17::f001"
      },
      {
        "hostname": "it-mil-wg-202",
        "location": "it-mil",
        "active": true,
        "owned": false,
        "provider": "M247",
        "stboot": true,
        "ipv4_addr_in": "146.70.225.66",
        "include_in_country": true,
        "weight": 100,
        "public_key": "y5raL0QZx2CpOozrL+Knmjj7nnly3JKatFnxynjXpE0=",
        "ipv6_addr_in": "2001:ac8:24:18::f001"
      },
      {
        "hostname": "it-pmo-wg-001",
        "location": "it-pmo",
        "active": true,
        "owned": false,
        "provider": "DataPacket",
        "stboot": true,
        "ipv4_addr_in": "149.22.91.66",
        "include_in_country": true,
        "weight": 100,
        "public_key": "cE6s9wV8jfAa84sgXWJ5C4d769m5Ki/XA3rxPdMWhVw=",
        "ipv6_addr_in": "2a02:6ea0:4f00::f001"
      },
      {
        "hostname": "it-pmo-wg-002",
        "location": "it-pmo",
        "active": true,
        "owned": false,
        "provider": "DataPacket",
        "stboot": true,
        "ipv4_addr_in": "149.22.91.79",
        "include_in_country": true,
        "weight": 100,
        "public_key": "bGtOejMzRDKzFR1gNBAi185dkr/5RtN+QiC8EVl4kU4=",
        "ipv6_addr_in": "2a02:6ea0:4f00::f101"
      },
      {
        "hostname": "jp-osa-wg-001",
        "location": "jp-osa",
        "active": true,
        "owned": false,
        "provider": "xtom",
        "stboot": true,
        "ipv4_addr_in": "194.114.136.3",
        "include_in_country": true,
        "weight": 0,
        "public_key": "uhbuY1A7g0yNu0lRhLTi020kYeAx34ED30BA5DQRHFo=",
        "ipv6_addr_in": "2403:fbc0:7000::f001",
        "features": {
          "lwo": {},
          "quic": {
            "addr_in": [
              "194.114.136.33"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "jp-osa-wg-001.blockerad.eu"
          }
        }
      },
      {
        "hostname": "jp-osa-wg-002",
        "location": "jp-osa",
        "active": true,
        "owned": false,
        "provider": "xtom",
        "stboot": true,
        "ipv4_addr_in": "194.114.136.34",
        "include_in_country": true,
        "weight": 0,
        "public_key": "wzGXxsYOraTCPZuRxfXVTNmoWsRkMFLqMqDxI4PutBg=",
        "ipv6_addr_in": "2403:fbc0:7000::f101"
      },
      {
        "hostname": "jp-osa-wg-003",
        "location": "jp-osa",
        "active": true,
        "owned": false,
        "provider": "xtom",
        "stboot": true,
        "ipv4_addr_in": "194.114.136.65",
        "include_in_country": true,
        "weight": 0,
        "public_key": "Pt18GnBffElW0sqnd6IDRr5r0B/NDezy6NicoPI+fG8=",
        "ipv6_addr_in": "2403:fbc0:7000::f201"
      },
      {
        "hostname": "jp-osa-wg-004",
        "location": "jp-osa",
        "active": true,
        "owned": false,
        "provider": "xtom",
        "stboot": true,
        "ipv4_addr_in": "194.114.136.96",
        "include_in_country": true,
        "weight": 0,
        "public_key": "JpDAtRuR39GLFKoQNiKvpzuJ65jOOLD7h85ekZ3reVc=",
        "ipv6_addr_in": "2403:fbc0:7000::f301"
      },
      {
        "hostname": "jp-osa-wg-101",
        "location": "jp-osa",
        "active": true,
        "owned": true,
        "provider": "xtom",
        "stboot": true,
        "ipv4_addr_in": "194.127.166.2",
        "include_in_country": true,
        "weight": 100,
        "public_key": "qdFG9butVjZdtGFeQHuNftvf6ZmISf2J+v167rcPDU4=",
        "ipv6_addr_in": "2a07:d883:600:1::f001",
        "daita": true,
        "shadowsocks_extra_addr_in": [
          "194.127.166.8",
          "194.127.166.9",
          "194.127.166.10",
          "194.127.166.11",
          "194.127.166.12",
          "2a07:d883:600:1::b002",
          "2a07:d883:600:1::b003",
          "2a07:d883:600:1::b004",
          "2a07:d883:600:1::b005",
          "2a07:d883:600:1::b006",
          "2a07:d883:600:1::b007",
          "2a07:d883:600:1::b008",
          "2a07:d883:600:1::b009",
          "2a07:d883:600:1::b00a",
          "2a07:d883:600:1::b00b",
          "2a07:d883:600:1::b00c",
          "2a07:d883:600:1::b00d",
          "2a07:d883:600:1::b00e",
          "2a07:d883:600:1::b00f",
          "2a07:d883:600:1::b010",
          "2a07:d883:600:1::b011",
          "2a07:d883:600:1::b012",
          "2a07:d883:600:1::b013",
          "2a07:d883:600:1::b014",
          "2a07:d883:600:1::b015",
          "2a07:d883:600:1::b016",
          "2a07:d883:600:1::b017",
          "2a07:d883:600:1::b018",
          "2a07:d883:600:1::b019",
          "2a07:d883:600:1::b01a",
          "2a07:d883:600:1::b01b",
          "2a07:d883:600:1::b01c",
          "2a07:d883:600:1::b01d",
          "2a07:d883:600:1::b01e",
          "2a07:d883:600:1::b01f"
        ],
        "features": {
          "daita": {},
          "lwo": {},
          "quic": {
            "addr_in": [
              "194.127.166.13",
              "194.127.166.14",
              "194.127.166.15",
              "194.127.166.16",
              "194.127.166.17",
              "2a07:d883:600:1::c002",
              "2a07:d883:600:1::c003",
              "2a07:d883:600:1::c004",
              "2a07:d883:600:1::c005",
              "2a07:d883:600:1::c006",
              "2a07:d883:600:1::c007",
              "2a07:d883:600:1::c008",
              "2a07:d883:600:1::c009",
              "2a07:d883:600:1::c00a",
              "2a07:d883:600:1::c00b",
              "2a07:d883:600:1::c00c",
              "2a07:d883:600:1::c00d",
              "2a07:d883:600:1::c00e",
              "2a07:d883:600:1::c00f",
              "2a07:d883:600:1::c010",
              "2a07:d883:600:1::c011",
              "2a07:d883:600:1::c012",
              "2a07:d883:600:1::c013",
              "2a07:d883:600:1::c014",
              "2a07:d883:600:1::c015",
              "2a07:d883:600:1::c016",
              "2a07:d883:600:1::c017",
              "2a07:d883:600:1::c018",
              "2a07:d883:600:1::c019",
              "2a07:d883:600:1::c01a",
              "2a07:d883:600:1::c01b",
              "2a07:d883:600:1::c01c",
              "2a07:d883:600:1::c01d",
              "2a07:d883:600:1::c01e",
              "2a07:d883:600:1::c01f"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "jp-osa-wg-101.blockerad.eu"
          }
        }
      },
      {
        "hostname": "jp-osa-wg-102",
        "location": "jp-osa",
        "active": true,
        "owned": true,
        "provider": "xtom",
        "stboot": true,
        "ipv4_addr_in": "194.127.166.81",
        "include_in_country": true,
        "weight": 100,
        "public_key": "4Gl6OMUtsLEDIrg23j/COdpKsCi7W9tzM4zvBPXOy18=",
        "ipv6_addr_in": "2a07:d883:600:2::f001",
        "daita": true,
        "shadowsocks_extra_addr_in": [
          "194.127.166.87",
          "194.127.166.88",
          "194.127.166.89",
          "194.127.166.90",
          "194.127.166.91",
          "2a07:d883:600:2::b002",
          "2a07:d883:600:2::b003",
          "2a07:d883:600:2::b004",
          "2a07:d883:600:2::b005",
          "2a07:d883:600:2::b006",
          "2a07:d883:600:2::b007",
          "2a07:d883:600:2::b008",
          "2a07:d883:600:2::b009",
          "2a07:d883:600:2::b00a",
          "2a07:d883:600:2::b00b",
          "2a07:d883:600:2::b00c",
          "2a07:d883:600:2::b00d",
          "2a07:d883:600:2::b00e",
          "2a07:d883:600:2::b00f",
          "2a07:d883:600:2::b010",
          "2a07:d883:600:2::b011",
          "2a07:d883:600:2::b012",
          "2a07:d883:600:2::b013",
          "2a07:d883:600:2::b014",
          "2a07:d883:600:2::b015",
          "2a07:d883:600:2::b016",
          "2a07:d883:600:2::b017",
          "2a07:d883:600:2::b018",
          "2a07:d883:600:2::b019",
          "2a07:d883:600:2::b01a",
          "2a07:d883:600:2::b01b",
          "2a07:d883:600:2::b01c",
          "2a07:d883:600:2::b01d",
          "2a07:d883:600:2::b01e",
          "2a07:d883:600:2::b01f"
        ],
        "features": {
          "daita": {},
          "lwo": {},
          "quic": {
            "addr_in": [
              "194.127.166.92",
              "194.127.166.93",
              "194.127.166.94",
              "194.127.166.95",
              "194.127.166.96",
              "2a07:d883:600:2::c002",
              "2a07:d883:600:2::c003",
              "2a07:d883:600:2::c004",
              "2a07:d883:600:2::c005",
              "2a07:d883:600:2::c006",
              "2a07:d883:600:2::c007",
              "2a07:d883:600:2::c008",
              "2a07:d883:600:2::c009",
              "2a07:d883:600:2::c00a",
              "2a07:d883:600:2::c00b",
              "2a07:d883:600:2::c00c",
              "2a07:d883:600:2::c00d",
              "2a07:d883:600:2::c00e",
              "2a07:d883:600:2::c00f",
              "2a07:d883:600:2::c010",
              "2a07:d883:600:2::c011",
              "2a07:d883:600:2::c012",
              "2a07:d883:600:2::c013",
              "2a07:d883:600:2::c014",
              "2a07:d883:600:2::c015",
              "2a07:d883:600:2::c016",
              "2a07:d883:600:2::c017",
              "2a07:d883:600:2::c018",
              "2a07:d883:600:2::c019",
              "2a07:d883:600:2::c01a",
              "2a07:d883:600:2::c01b",
              "2a07:d883:600:2::c01c",
              "2a07:d883:600:2::c01d",
              "2a07:d883:600:2::c01e",
              "2a07:d883:600:2::c01f"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "jp-osa-wg-102.blockerad.eu"
          }
        }
      },
      {
        "hostname": "jp-osa-wg-103",
        "location": "jp-osa",
        "active": true,
        "owned": true,
        "provider": "xtom",
        "stboot": true,
        "ipv4_addr_in": "194.127.166.161",
        "include_in_country": true,
        "weight": 100,
        "public_key": "B4LgHDQA8GQtqer7jAEjVDiTBLTBYk6vdOY/sM8DbGI=",
        "ipv6_addr_in": "2a07:d883:600:3::f001",
        "daita": true,
        "shadowsocks_extra_addr_in": [
          "194.127.166.167",
          "194.127.166.168",
          "194.127.166.169",
          "194.127.166.170",
          "194.127.166.171",
          "2a07:d883:600:3::b002",
          "2a07:d883:600:3::b003",
          "2a07:d883:600:3::b004",
          "2a07:d883:600:3::b005",
          "2a07:d883:600:3::b006",
          "2a07:d883:600:3::b007",
          "2a07:d883:600:3::b008",
          "2a07:d883:600:3::b009",
          "2a07:d883:600:3::b00a",
          "2a07:d883:600:3::b00b",
          "2a07:d883:600:3::b00c",
          "2a07:d883:600:3::b00d",
          "2a07:d883:600:3::b00e",
          "2a07:d883:600:3::b00f",
          "2a07:d883:600:3::b010",
          "2a07:d883:600:3::b011",
          "2a07:d883:600:3::b012",
          "2a07:d883:600:3::b013",
          "2a07:d883:600:3::b014",
          "2a07:d883:600:3::b015",
          "2a07:d883:600:3::b016",
          "2a07:d883:600:3::b017",
          "2a07:d883:600:3::b018",
          "2a07:d883:600:3::b019",
          "2a07:d883:600:3::b01a",
          "2a07:d883:600:3::b01b",
          "2a07:d883:600:3::b01c",
          "2a07:d883:600:3::b01d",
          "2a07:d883:600:3::b01e",
          "2a07:d883:600:3::b01f"
        ],
        "features": {
          "daita": {},
          "lwo": {},
          "quic": {
            "addr_in": [
              "194.127.166.172",
              "194.127.166.173",
              "194.127.166.174",
              "194.127.166.175",
              "194.127.166.176",
              "2a07:d883:600:3::c002",
              "2a07:d883:600:3::c003",
              "2a07:d883:600:3::c004",
              "2a07:d883:600:3::c005",
              "2a07:d883:600:3::c006",
              "2a07:d883:600:3::c007",
              "2a07:d883:600:3::c008",
              "2a07:d883:600:3::c009",
              "2a07:d883:600:3::c00a",
              "2a07:d883:600:3::c00b",
              "2a07:d883:600:3::c00c",
              "2a07:d883:600:3::c00d",
              "2a07:d883:600:3::c00e",
              "2a07:d883:600:3::c00f",
              "2a07:d883:600:3::c010",
              "2a07:d883:600:3::c011",
              "2a07:d883:600:3::c012",
              "2a07:d883:600:3::c013",
              "2a07:d883:600:3::c014",
              "2a07:d883:600:3::c015",
              "2a07:d883:600:3::c016",
              "2a07:d883:600:3::c017",
              "2a07:d883:600:3::c018",
              "2a07:d883:600:3::c019",
              "2a07:d883:600:3::c01a",
              "2a07:d883:600:3::c01b",
              "2a07:d883:600:3::c01c",
              "2a07:d883:600:3::c01d",
              "2a07:d883:600:3::c01e",
              "2a07:d883:600:3::c01f"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "jp-osa-wg-103.blockerad.eu"
          }
        }
      },
      {
        "hostname": "jp-tyo-wg-001",
        "location": "jp-tyo",
        "active": true,
        "owned": false,
        "provider": "DataPacket",
        "stboot": true,
        "ipv4_addr_in": "138.199.21.239",
        "include_in_country": true,
        "weight": 200,
        "public_key": "AUo2zhQ0wCDy3/jmZgOe4QMncWWqrdME7BbY2UlkgyI=",
        "ipv6_addr_in": "2a02:6ea0:d31c::a15f",
        "daita": true,
        "features": {
          "daita": {}
        }
      },
      {
        "hostname": "jp-tyo-wg-002",
        "location": "jp-tyo",
        "active": true,
        "owned": false,
        "provider": "DataPacket",
        "stboot": true,
        "ipv4_addr_in": "138.199.21.226",
        "include_in_country": true,
        "weight": 200,
        "public_key": "zdlqydCbeR7sG1y5L8sS65X1oOtRKvfVbAuFgqEGhi4=",
        "ipv6_addr_in": "2a02:6ea0:d31b::a14f"
      },
      {
        "hostname": "jp-tyo-wg-201",
        "location": "jp-tyo",
        "active": true,
        "owned": false,
        "provider": "M247",
        "stboot": true,
        "ipv4_addr_in": "146.70.201.2",
        "include_in_country": true,
        "weight": 100,
        "public_key": "5YlME8hOnWqvZ7iSampvPW5bG/dJ+PYpaBFV5kfp9UA=",
        "ipv6_addr_in": "2001:ac8:40:13::f001",
        "daita": true,
        "shadowsocks_extra_addr_in": [
          "146.70.201.13",
          "146.70.201.14",
          "146.70.201.15",
          "146.70.201.16",
          "146.70.201.17",
          "146.70.201.18",
          "146.70.201.19",
          "146.70.201.20",
          "146.70.201.21",
          "146.70.201.22",
          "2001:ac8:40:13::b002",
          "2001:ac8:40:13::b003",
          "2001:ac8:40:13::b004",
          "2001:ac8:40:13::b005",
          "2001:ac8:40:13::b006",
          "2001:ac8:40:13::b007",
          "2001:ac8:40:13::b008",
          "2001:ac8:40:13::b009",
          "2001:ac8:40:13::b00a",
          "2001:ac8:40:13::b00b",
          "2001:ac8:40:13::b00c",
          "2001:ac8:40:13::b00d",
          "2001:ac8:40:13::b00e",
          "2001:ac8:40:13::b00f",
          "2001:ac8:40:13::b010",
          "2001:ac8:40:13::b011",
          "2001:ac8:40:13::b012",
          "2001:ac8:40:13::b013",
          "2001:ac8:40:13::b014",
          "2001:ac8:40:13::b015",
          "2001:ac8:40:13::b016",
          "2001:ac8:40:13::b017",
          "2001:ac8:40:13::b018",
          "2001:ac8:40:13::b019",
          "2001:ac8:40:13::b01a",
          "2001:ac8:40:13::b01b",
          "2001:ac8:40:13::b01c",
          "2001:ac8:40:13::b01d",
          "2001:ac8:40:13::b01e",
          "2001:ac8:40:13::b01f"
        ],
        "features": {
          "daita": {},
          "lwo": {},
          "quic": {
            "addr_in": [
              "146.70.201.23",
              "146.70.201.24",
              "146.70.201.25",
              "146.70.201.26",
              "146.70.201.27",
              "146.70.201.28",
              "146.70.201.29",
              "146.70.201.30",
              "146.70.201.31",
              "146.70.201.32",
              "2001:ac8:40:13::c002",
              "2001:ac8:40:13::c003",
              "2001:ac8:40:13::c004",
              "2001:ac8:40:13::c005",
              "2001:ac8:40:13::c006",
              "2001:ac8:40:13::c007",
              "2001:ac8:40:13::c008",
              "2001:ac8:40:13::c009",
              "2001:ac8:40:13::c00a",
              "2001:ac8:40:13::c00b",
              "2001:ac8:40:13::c00c",
              "2001:ac8:40:13::c00d",
              "2001:ac8:40:13::c00e",
              "2001:ac8:40:13::c00f",
              "2001:ac8:40:13::c010",
              "2001:ac8:40:13::c011",
              "2001:ac8:40:13::c012",
              "2001:ac8:40:13::c013",
              "2001:ac8:40:13::c014",
              "2001:ac8:40:13::c015",
              "2001:ac8:40:13::c016",
              "2001:ac8:40:13::c017",
              "2001:ac8:40:13::c018",
              "2001:ac8:40:13::c019",
              "2001:ac8:40:13::c01a",
              "2001:ac8:40:13::c01b",
              "2001:ac8:40:13::c01c",
              "2001:ac8:40:13::c01d",
              "2001:ac8:40:13::c01e",
              "2001:ac8:40:13::c01f"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "jp-tyo-wg-201.blockerad.eu"
          }
        }
      },
      {
        "hostname": "jp-tyo-wg-202",
        "location": "jp-tyo",
        "active": true,
        "owned": false,
        "provider": "M247",
        "stboot": true,
        "ipv4_addr_in": "146.70.201.130",
        "include_in_country": true,
        "weight": 100,
        "public_key": "3NykAEXAdeaT0qFstBkJorW3PDsBRUHHbBUc6YoIzAs=",
        "ipv6_addr_in": "2001:ac8:40:14::f001",
        "daita": true,
        "shadowsocks_extra_addr_in": [
          "146.70.201.141",
          "146.70.201.142",
          "146.70.201.143",
          "146.70.201.144",
          "146.70.201.145",
          "146.70.201.146",
          "146.70.201.147",
          "146.70.201.148",
          "146.70.201.149",
          "146.70.201.150",
          "2001:ac8:40:14::b002",
          "2001:ac8:40:14::b003",
          "2001:ac8:40:14::b004",
          "2001:ac8:40:14::b005",
          "2001:ac8:40:14::b006",
          "2001:ac8:40:14::b007",
          "2001:ac8:40:14::b008",
          "2001:ac8:40:14::b009",
          "2001:ac8:40:14::b00a",
          "2001:ac8:40:14::b00b",
          "2001:ac8:40:14::b00c",
          "2001:ac8:40:14::b00d",
          "2001:ac8:40:14::b00e",
          "2001:ac8:40:14::b00f",
          "2001:ac8:40:14::b010",
          "2001:ac8:40:14::b011",
          "2001:ac8:40:14::b012",
          "2001:ac8:40:14::b013",
          "2001:ac8:40:14::b014",
          "2001:ac8:40:14::b015",
          "2001:ac8:40:14::b016",
          "2001:ac8:40:14::b017",
          "2001:ac8:40:14::b018",
          "2001:ac8:40:14::b019",
          "2001:ac8:40:14::b01a",
          "2001:ac8:40:14::b01b",
          "2001:ac8:40:14::b01c",
          "2001:ac8:40:14::b01d",
          "2001:ac8:40:14::b01e",
          "2001:ac8:40:14::b01f"
        ],
        "features": {
          "daita": {},
          "lwo": {},
          "quic": {
            "addr_in": [
              "146.70.201.151",
              "146.70.201.152",
              "146.70.201.153",
              "146.70.201.154",
              "146.70.201.155",
              "146.70.201.156",
              "146.70.201.157",
              "146.70.201.158",
              "146.70.201.159",
              "146.70.201.160",
              "2001:ac8:40:14::c002",
              "2001:ac8:40:14::c003",
              "2001:ac8:40:14::c004",
              "2001:ac8:40:14::c005",
              "2001:ac8:40:14::c006",
              "2001:ac8:40:14::c007",
              "2001:ac8:40:14::c008",
              "2001:ac8:40:14::c009",
              "2001:ac8:40:14::c00a",
              "2001:ac8:40:14::c00b",
              "2001:ac8:40:14::c00c",
              "2001:ac8:40:14::c00d",
              "2001:ac8:40:14::c00e",
              "2001:ac8:40:14::c00f",
              "2001:ac8:40:14::c010",
              "2001:ac8:40:14::c011",
              "2001:ac8:40:14::c012",
              "2001:ac8:40:14::c013",
              "2001:ac8:40:14::c014",
              "2001:ac8:40:14::c015",
              "2001:ac8:40:14::c016",
              "2001:ac8:40:14::c017",
              "2001:ac8:40:14::c018",
              "2001:ac8:40:14::c019",
              "2001:ac8:40:14::c01a",
              "2001:ac8:40:14::c01b",
              "2001:ac8:40:14::c01c",
              "2001:ac8:40:14::c01d",
              "2001:ac8:40:14::c01e",
              "2001:ac8:40:14::c01f"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "jp-tyo-wg-202.blockerad.eu"
          }
        }
      },
      {
        "hostname": "jp-tyo-wg-203",
        "location": "jp-tyo",
        "active": true,
        "owned": false,
        "provider": "M247",
        "stboot": true,
        "ipv4_addr_in": "135.136.55.2",
        "include_in_country": true,
        "weight": 100,
        "public_key": "nkNCONMj0uw6/PV/t8R1TX7q2+DKNSDIUCnxvc0fWjs=",
        "ipv6_addr_in": "2001:ac8:40:1d::f001",
        "daita": true,
        "shadowsocks_extra_addr_in": [
          "135.136.55.13",
          "135.136.55.14",
          "135.136.55.15",
          "135.136.55.16",
          "135.136.55.17",
          "135.136.55.18",
          "135.136.55.19",
          "135.136.55.20",
          "135.136.55.21",
          "135.136.55.22",
          "2001:ac8:40:1d::b002",
          "2001:ac8:40:1d::b003",
          "2001:ac8:40:1d::b004",
          "2001:ac8:40:1d::b005",
          "2001:ac8:40:1d::b006",
          "2001:ac8:40:1d::b007",
          "2001:ac8:40:1d::b008",
          "2001:ac8:40:1d::b009",
          "2001:ac8:40:1d::b00a",
          "2001:ac8:40:1d::b00b",
          "2001:ac8:40:1d::b00c",
          "2001:ac8:40:1d::b00d",
          "2001:ac8:40:1d::b00e",
          "2001:ac8:40:1d::b00f",
          "2001:ac8:40:1d::b010",
          "2001:ac8:40:1d::b011",
          "2001:ac8:40:1d::b012",
          "2001:ac8:40:1d::b013",
          "2001:ac8:40:1d::b014",
          "2001:ac8:40:1d::b015",
          "2001:ac8:40:1d::b016",
          "2001:ac8:40:1d::b017",
          "2001:ac8:40:1d::b018",
          "2001:ac8:40:1d::b019",
          "2001:ac8:40:1d::b01a",
          "2001:ac8:40:1d::b01b",
          "2001:ac8:40:1d::b01c",
          "2001:ac8:40:1d::b01d",
          "2001:ac8:40:1d::b01e",
          "2001:ac8:40:1d::b01f"
        ],
        "features": {
          "daita": {},
          "lwo": {},
          "quic": {
            "addr_in": [
              "135.136.55.23",
              "135.136.55.24",
              "135.136.55.25",
              "135.136.55.26",
              "135.136.55.27",
              "135.136.55.28",
              "135.136.55.29",
              "135.136.55.30",
              "135.136.55.31",
              "135.136.55.32",
              "2001:ac8:40:1d::c002",
              "2001:ac8:40:1d::c003",
              "2001:ac8:40:1d::c004",
              "2001:ac8:40:1d::c005",
              "2001:ac8:40:1d::c006",
              "2001:ac8:40:1d::c007",
              "2001:ac8:40:1d::c008",
              "2001:ac8:40:1d::c009",
              "2001:ac8:40:1d::c00a",
              "2001:ac8:40:1d::c00b",
              "2001:ac8:40:1d::c00c",
              "2001:ac8:40:1d::c00d",
              "2001:ac8:40:1d::c00e",
              "2001:ac8:40:1d::c00f",
              "2001:ac8:40:1d::c010",
              "2001:ac8:40:1d::c011",
              "2001:ac8:40:1d::c012",
              "2001:ac8:40:1d::c013",
              "2001:ac8:40:1d::c014",
              "2001:ac8:40:1d::c015",
              "2001:ac8:40:1d::c016",
              "2001:ac8:40:1d::c017",
              "2001:ac8:40:1d::c018",
              "2001:ac8:40:1d::c019",
              "2001:ac8:40:1d::c01a",
              "2001:ac8:40:1d::c01b",
              "2001:ac8:40:1d::c01c",
              "2001:ac8:40:1d::c01d",
              "2001:ac8:40:1d::c01e",
              "2001:ac8:40:1d::c01f"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "jp-tyo-wg-203.blockerad.eu"
          }
        }
      },
      {
        "hostname": "mx-qro-wg-001",
        "location": "mx-qro",
        "active": true,
        "owned": false,
        "provider": "DataPacket",
        "stboot": true,
        "ipv4_addr_in": "149.88.22.129",
        "include_in_country": true,
        "weight": 100,
        "public_key": "yxyntWsANEwxeR0pOPNAcfWY7zEVICZe9G+GxortzEY=",
        "ipv6_addr_in": "2a02:6ea0:f803::f001",
        "daita": true,
        "features": {
          "daita": {},
          "lwo": {},
          "quic": {
            "addr_in": [
              "149.88.22.141"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "mx-qro-wg-001.blockerad.eu"
          }
        }
      },
      {
        "hostname": "mx-qro-wg-002",
        "location": "mx-qro",
        "active": true,
        "owned": false,
        "provider": "DataPacket",
        "stboot": true,
        "ipv4_addr_in": "149.88.22.142",
        "include_in_country": true,
        "weight": 100,
        "public_key": "kGkalo3qvm8MynKdzwW7CGBYXkqRwGhHfYVssgKOWnU=",
        "ipv6_addr_in": "2a02:6ea0:f803:1::f001",
        "features": {
          "lwo": {}
        }
      },
      {
        "hostname": "mx-qro-wg-003",
        "location": "mx-qro",
        "active": true,
        "owned": false,
        "provider": "DataPacket",
        "stboot": true,
        "ipv4_addr_in": "149.88.22.155",
        "include_in_country": true,
        "weight": 100,
        "public_key": "hRamkTwXw0usPFDorPl2vf1qP8chczEBcqeV5bA1QDA=",
        "ipv6_addr_in": "2a02:6ea0:f803:2::f001"
      },
      {
        "hostname": "mx-qro-wg-004",
        "location": "mx-qro",
        "active": true,
        "owned": false,
        "provider": "DataPacket",
        "stboot": true,
        "ipv4_addr_in": "149.88.22.168",
        "include_in_country": true,
        "weight": 100,
        "public_key": "Q3yqhnYHK/bFjrd6yqti8gSV1gzOwvnl5N5tXuUxMyk=",
        "ipv6_addr_in": "2a02:6ea0:f803:3::f001"
      },
      {
        "hostname": "my-kul-wg-001",
        "location": "my-kul",
        "active": true,
        "owned": false,
        "provider": "Zenlayer",
        "stboot": true,
        "ipv4_addr_in": "98.98.47.130",
        "include_in_country": true,
        "weight": 100,
        "public_key": "RnwTFcAl6z4UfXio9ApLqlOjBcYvD0gWG0htl6fiCl4=",
        "ipv6_addr_in": "2602:ffe4:c20:112::f001",
        "shadowsocks_extra_addr_in": [
          "98.98.47.132"
        ]
      },
      {
        "hostname": "my-kul-wg-002",
        "location": "my-kul",
        "active": true,
        "owned": false,
        "provider": "Zenlayer",
        "stboot": true,
        "ipv4_addr_in": "162.128.129.98",
        "include_in_country": true,
        "weight": 100,
        "public_key": "BVh+R5uifa9kn6fDNozd1OrnlGlV8qTr/IUIg0PDGl0=",
        "ipv6_addr_in": "2602:ffe4:c20:112::f101",
        "shadowsocks_extra_addr_in": [
          "162.128.129.100"
        ],
        "features": {
          "lwo": {}
        }
      },
      {
        "hostname": "ng-los-wg-001",
        "location": "ng-los",
        "active": true,
        "owned": false,
        "provider": "DataPacket",
        "stboot": true,
        "ipv4_addr_in": "79.127.149.130",
        "include_in_country": true,
        "weight": 100,
        "public_key": "nlpbIResE9vYypA9M/tKvfbUamsmCSawTqmq0cbVJjw=",
        "ipv6_addr_in": "2a02:6ea0:5400:1::f001",
        "shadowsocks_extra_addr_in": [
          "79.127.149.132"
        ]
      },
      {
        "hostname": "ng-los-wg-002",
        "location": "ng-los",
        "active": true,
        "owned": false,
        "provider": "DataPacket",
        "stboot": true,
        "ipv4_addr_in": "79.127.149.159",
        "include_in_country": true,
        "weight": 100,
        "public_key": "Hel+ma9otIsWedjgK6Dp51t/WmUys+Q/hUqpvN7qBXg=",
        "ipv6_addr_in": "2a02:6ea0:5400:2::f001",
        "shadowsocks_extra_addr_in": [
          "79.127.149.161"
        ]
      },
      {
        "hostname": "nl-ams-wg-001",
        "location": "nl-ams",
        "active": true,
        "owned": true,
        "provider": "31173",
        "stboot": true,
        "ipv4_addr_in": "193.32.249.66",
        "include_in_country": true,
        "weight": 50,
        "public_key": "UrQiI9ISdPPzd4ARw1NHOPKKvKvxUhjwRjaI0JpJFgM=",
        "ipv6_addr_in": "2a03:1b20:3:f011::f001",
        "daita": true,
        "shadowsocks_extra_addr_in": [
          "2a03:1b20:3:f011::b002",
          "2a03:1b20:3:f011::b003",
          "2a03:1b20:3:f011::b004",
          "2a03:1b20:3:f011::b005",
          "2a03:1b20:3:f011::b006",
          "2a03:1b20:3:f011::b007",
          "2a03:1b20:3:f011::b008",
          "2a03:1b20:3:f011::b009",
          "2a03:1b20:3:f011::b00a",
          "2a03:1b20:3:f011::b00b",
          "2a03:1b20:3:f011::b00c",
          "2a03:1b20:3:f011::b00d",
          "2a03:1b20:3:f011::b00e",
          "2a03:1b20:3:f011::b00f",
          "2a03:1b20:3:f011::b010",
          "2a03:1b20:3:f011::b011",
          "2a03:1b20:3:f011::b012",
          "2a03:1b20:3:f011::b013",
          "2a03:1b20:3:f011::b014",
          "2a03:1b20:3:f011::b015",
          "2a03:1b20:3:f011::b016",
          "2a03:1b20:3:f011::b017",
          "2a03:1b20:3:f011::b018",
          "2a03:1b20:3:f011::b019",
          "2a03:1b20:3:f011::b01a",
          "2a03:1b20:3:f011::b01b",
          "2a03:1b20:3:f011::b01c",
          "2a03:1b20:3:f011::b01d",
          "2a03:1b20:3:f011::b01e",
          "2a03:1b20:3:f011::b01f",
          "141.11.20.22",
          "141.11.20.23",
          "141.11.20.24",
          "141.11.20.25",
          "141.11.20.26",
          "141.11.20.27",
          "141.11.20.28",
          "141.11.20.29",
          "141.11.20.30",
          "141.11.20.31",
          "141.11.20.32",
          "141.11.20.33",
          "141.11.20.34",
          "141.11.20.35",
          "141.11.20.36",
          "141.11.20.37",
          "141.11.20.38",
          "141.11.20.39",
          "141.11.20.40",
          "141.11.20.41"
        ],
        "features": {
          "daita": {},
          "lwo": {}
        }
      },
      {
        "hostname": "nl-ams-wg-002",
        "location": "nl-ams",
        "active": true,
        "owned": true,
        "provider": "31173",
        "stboot": true,
        "ipv4_addr_in": "185.65.134.82",
        "include_in_country": true,
        "weight": 50,
        "public_key": "DVui+5aifNFRIVDjH3v2y+dQ+uwI+HFZOd21ajbEpBo=",
        "ipv6_addr_in": "2a03:1b20:3:f011::a02f",
        "daita": true,
        "shadowsocks_extra_addr_in": [
          "2a03:1b20:3:f011::b102",
          "2a03:1b20:3:f011::b103",
          "2a03:1b20:3:f011::b104",
          "2a03:1b20:3:f011::b105",
          "2a03:1b20:3:f011::b106",
          "2a03:1b20:3:f011::b107",
          "2a03:1b20:3:f011::b108",
          "2a03:1b20:3:f011::b109",
          "2a03:1b20:3:f011::b10a",
          "2a03:1b20:3:f011::b10b",
          "2a03:1b20:3:f011::b10c",
          "2a03:1b20:3:f011::b10d",
          "2a03:1b20:3:f011::b10e",
          "2a03:1b20:3:f011::b10f",
          "2a03:1b20:3:f011::b110",
          "2a03:1b20:3:f011::b111",
          "2a03:1b20:3:f011::b112",
          "2a03:1b20:3:f011::b113",
          "2a03:1b20:3:f011::b114",
          "2a03:1b20:3:f011::b115",
          "2a03:1b20:3:f011::b116",
          "2a03:1b20:3:f011::b117",
          "2a03:1b20:3:f011::b118",
          "2a03:1b20:3:f011::b119",
          "2a03:1b20:3:f011::b11a",
          "2a03:1b20:3:f011::b11b",
          "2a03:1b20:3:f011::b11c",
          "2a03:1b20:3:f011::b11d",
          "2a03:1b20:3:f011::b11e",
          "2a03:1b20:3:f011::b11f",
          "141.11.20.82",
          "141.11.20.83",
          "141.11.20.84",
          "141.11.20.85",
          "141.11.20.86",
          "141.11.20.87",
          "141.11.20.88",
          "141.11.20.89",
          "141.11.20.90",
          "141.11.20.91",
          "141.11.20.92",
          "141.11.20.93",
          "141.11.20.94",
          "141.11.20.95",
          "141.11.20.96",
          "141.11.20.97",
          "141.11.20.98",
          "141.11.20.99",
          "141.11.20.100",
          "141.11.20.101"
        ],
        "features": {
          "daita": {},
          "lwo": {},
          "quic": {
            "addr_in": [
              "185.65.134.218",
              "2a03:1b20:3:f011::c102",
              "2a03:1b20:3:f011::c103",
              "2a03:1b20:3:f011::c104",
              "2a03:1b20:3:f011::c105",
              "2a03:1b20:3:f011::c106",
              "2a03:1b20:3:f011::c107",
              "2a03:1b20:3:f011::c108",
              "2a03:1b20:3:f011::c109",
              "2a03:1b20:3:f011::c10a",
              "2a03:1b20:3:f011::c10b",
              "2a03:1b20:3:f011::c10c",
              "2a03:1b20:3:f011::c10d",
              "2a03:1b20:3:f011::c10e",
              "2a03:1b20:3:f011::c10f",
              "2a03:1b20:3:f011::c110",
              "2a03:1b20:3:f011::c111",
              "2a03:1b20:3:f011::c112",
              "2a03:1b20:3:f011::c113",
              "2a03:1b20:3:f011::c114",
              "2a03:1b20:3:f011::c115",
              "2a03:1b20:3:f011::c116",
              "2a03:1b20:3:f011::c117",
              "2a03:1b20:3:f011::c118",
              "2a03:1b20:3:f011::c119",
              "2a03:1b20:3:f011::c11a",
              "2a03:1b20:3:f011::c11b",
              "2a03:1b20:3:f011::c11c",
              "2a03:1b20:3:f011::c11d",
              "2a03:1b20:3:f011::c11e",
              "2a03:1b20:3:f011::c11f",
              "141.11.20.102",
              "141.11.20.103",
              "141.11.20.104",
              "141.11.20.105",
              "141.11.20.106",
              "141.11.20.107",
              "141.11.20.108",
              "141.11.20.109",
              "141.11.20.110",
              "141.11.20.111",
              "141.11.20.112",
              "141.11.20.113",
              "141.11.20.114",
              "141.11.20.115",
              "141.11.20.116",
              "141.11.20.117",
              "141.11.20.118",
              "141.11.20.119",
              "141.11.20.120",
              "141.11.20.121"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "nl-ams-wg-002.blockerad.eu"
          }
        }
      },
      {
        "hostname": "nl-ams-wg-003",
        "location": "nl-ams",
        "active": true,
        "owned": true,
        "provider": "31173",
        "stboot": true,
        "ipv4_addr_in": "185.65.134.83",
        "include_in_country": true,
        "weight": 50,
        "public_key": "if4HpJZbN7jft5E9R9wAoTcggIu6eZhgYDvqxnwrXic=",
        "ipv6_addr_in": "2a03:1b20:3:f011::f201",
        "shadowsocks_extra_addr_in": [
          "2a03:1b20:3:f011::b202",
          "2a03:1b20:3:f011::b203",
          "2a03:1b20:3:f011::b204",
          "2a03:1b20:3:f011::b205",
          "2a03:1b20:3:f011::b206",
          "2a03:1b20:3:f011::b207",
          "2a03:1b20:3:f011::b208",
          "2a03:1b20:3:f011::b209",
          "2a03:1b20:3:f011::b20a",
          "2a03:1b20:3:f011::b20b",
          "2a03:1b20:3:f011::b20c",
          "2a03:1b20:3:f011::b20d",
          "2a03:1b20:3:f011::b20e",
          "2a03:1b20:3:f011::b20f",
          "2a03:1b20:3:f011::b210",
          "2a03:1b20:3:f011::b211",
          "2a03:1b20:3:f011::b212",
          "2a03:1b20:3:f011::b213",
          "2a03:1b20:3:f011::b214",
          "2a03:1b20:3:f011::b215",
          "2a03:1b20:3:f011::b216",
          "2a03:1b20:3:f011::b217",
          "2a03:1b20:3:f011::b218",
          "2a03:1b20:3:f011::b219",
          "2a03:1b20:3:f011::b21a",
          "2a03:1b20:3:f011::b21b",
          "2a03:1b20:3:f011::b21c",
          "2a03:1b20:3:f011::b21d",
          "2a03:1b20:3:f011::b21e",
          "2a03:1b20:3:f011::b21f",
          "141.11.20.142",
          "141.11.20.143",
          "141.11.20.144",
          "141.11.20.145",
          "141.11.20.146",
          "141.11.20.147",
          "141.11.20.148",
          "141.11.20.149",
          "141.11.20.150",
          "141.11.20.151",
          "141.11.20.152",
          "141.11.20.153",
          "141.11.20.154",
          "141.11.20.155",
          "141.11.20.156",
          "141.11.20.157",
          "141.11.20.158",
          "141.11.20.159",
          "141.11.20.160",
          "141.11.20.161"
        ],
        "features": {
          "lwo": {}
        }
      },
      {
        "hostname": "nl-ams-wg-004",
        "location": "nl-ams",
        "active": true,
        "owned": true,
        "provider": "31173",
        "stboot": true,
        "ipv4_addr_in": "193.32.249.69",
        "include_in_country": true,
        "weight": 50,
        "public_key": "hnRyse6QxPPcZOoSwRsHUtK1W+APWXnIoaDTmH6JsHQ=",
        "ipv6_addr_in": "2a03:1b20:3:f011::f301",
        "shadowsocks_extra_addr_in": [
          "2a03:1b20:3:f011::b302",
          "2a03:1b20:3:f011::b303",
          "2a03:1b20:3:f011::b304",
          "2a03:1b20:3:f011::b305",
          "2a03:1b20:3:f011::b306",
          "2a03:1b20:3:f011::b307",
          "2a03:1b20:3:f011::b308",
          "2a03:1b20:3:f011::b309",
          "2a03:1b20:3:f011::b30a",
          "2a03:1b20:3:f011::b30b",
          "2a03:1b20:3:f011::b30c",
          "2a03:1b20:3:f011::b30d",
          "2a03:1b20:3:f011::b30e",
          "2a03:1b20:3:f011::b30f",
          "2a03:1b20:3:f011::b310",
          "2a03:1b20:3:f011::b311",
          "2a03:1b20:3:f011::b312",
          "2a03:1b20:3:f011::b313",
          "2a03:1b20:3:f011::b314",
          "2a03:1b20:3:f011::b315",
          "2a03:1b20:3:f011::b316",
          "2a03:1b20:3:f011::b317",
          "2a03:1b20:3:f011::b318",
          "2a03:1b20:3:f011::b319",
          "2a03:1b20:3:f011::b31a",
          "2a03:1b20:3:f011::b31b",
          "2a03:1b20:3:f011::b31c",
          "2a03:1b20:3:f011::b31d",
          "2a03:1b20:3:f011::b31e",
          "2a03:1b20:3:f011::b31f",
          "141.11.20.202",
          "141.11.20.203",
          "141.11.20.204",
          "141.11.20.205",
          "141.11.20.206",
          "141.11.20.207",
          "141.11.20.208",
          "141.11.20.209",
          "141.11.20.210",
          "141.11.20.211",
          "141.11.20.212",
          "141.11.20.213",
          "141.11.20.214",
          "141.11.20.215",
          "141.11.20.216",
          "141.11.20.217",
          "141.11.20.218",
          "141.11.20.219",
          "141.11.20.220",
          "141.11.20.221"
        ],
        "features": {
          "lwo": {}
        }
      },
      {
        "hostname": "nl-ams-wg-005",
        "location": "nl-ams",
        "active": true,
        "owned": true,
        "provider": "31173",
        "stboot": true,
        "ipv4_addr_in": "193.32.249.70",
        "include_in_country": true,
        "weight": 50,
        "public_key": "33BoONMGCm2vknq2eq72eozRsHmHQY6ZHEEZ4851TkY=",
        "ipv6_addr_in": "2a03:1b20:3:f011::f401",
        "shadowsocks_extra_addr_in": [
          "2a03:1b20:3:f011::b402",
          "2a03:1b20:3:f011::b403",
          "2a03:1b20:3:f011::b404",
          "2a03:1b20:3:f011::b405",
          "2a03:1b20:3:f011::b406",
          "2a03:1b20:3:f011::b407",
          "2a03:1b20:3:f011::b408",
          "2a03:1b20:3:f011::b409",
          "2a03:1b20:3:f011::b40a",
          "2a03:1b20:3:f011::b40b",
          "2a03:1b20:3:f011::b40c",
          "2a03:1b20:3:f011::b40d",
          "2a03:1b20:3:f011::b40e",
          "2a03:1b20:3:f011::b40f",
          "2a03:1b20:3:f011::b410",
          "2a03:1b20:3:f011::b411",
          "2a03:1b20:3:f011::b412",
          "2a03:1b20:3:f011::b413",
          "2a03:1b20:3:f011::b414",
          "2a03:1b20:3:f011::b415",
          "2a03:1b20:3:f011::b416",
          "2a03:1b20:3:f011::b417",
          "2a03:1b20:3:f011::b418",
          "2a03:1b20:3:f011::b419",
          "2a03:1b20:3:f011::b41a",
          "2a03:1b20:3:f011::b41b",
          "2a03:1b20:3:f011::b41c",
          "2a03:1b20:3:f011::b41d",
          "2a03:1b20:3:f011::b41e",
          "2a03:1b20:3:f011::b41f"
        ]
      },
      {
        "hostname": "nl-ams-wg-006",
        "location": "nl-ams",
        "active": true,
        "owned": true,
        "provider": "31173",
        "stboot": true,
        "ipv4_addr_in": "185.65.134.86",
        "include_in_country": true,
        "weight": 50,
        "public_key": "xpZ3ZDEukbqKQvdHwaqKMUhsYhcYD3uLPUh1ACsVr1s=",
        "ipv6_addr_in": "2a03:1b20:3:f011::f501",
        "shadowsocks_extra_addr_in": [
          "2a03:1b20:3:f011::b502",
          "2a03:1b20:3:f011::b503",
          "2a03:1b20:3:f011::b504",
          "2a03:1b20:3:f011::b505",
          "2a03:1b20:3:f011::b506",
          "2a03:1b20:3:f011::b507",
          "2a03:1b20:3:f011::b508",
          "2a03:1b20:3:f011::b509",
          "2a03:1b20:3:f011::b50a",
          "2a03:1b20:3:f011::b50b",
          "2a03:1b20:3:f011::b50c",
          "2a03:1b20:3:f011::b50d",
          "2a03:1b20:3:f011::b50e",
          "2a03:1b20:3:f011::b50f",
          "2a03:1b20:3:f011::b510",
          "2a03:1b20:3:f011::b511",
          "2a03:1b20:3:f011::b512",
          "2a03:1b20:3:f011::b513",
          "2a03:1b20:3:f011::b514",
          "2a03:1b20:3:f011::b515",
          "2a03:1b20:3:f011::b516",
          "2a03:1b20:3:f011::b517",
          "2a03:1b20:3:f011::b518",
          "2a03:1b20:3:f011::b519",
          "2a03:1b20:3:f011::b51a",
          "2a03:1b20:3:f011::b51b",
          "2a03:1b20:3:f011::b51c",
          "2a03:1b20:3:f011::b51d",
          "2a03:1b20:3:f011::b51e",
          "2a03:1b20:3:f011::b51f"
        ]
      },
      {
        "hostname": "nl-ams-wg-007",
        "location": "nl-ams",
        "active": true,
        "owned": true,
        "provider": "31173",
        "stboot": true,
        "ipv4_addr_in": "185.65.134.76",
        "include_in_country": true,
        "weight": 50,
        "public_key": "Os/BwxAIWehlypQ8QjrKVEK5PhY84b413+U3YWZJYXQ=",
        "ipv6_addr_in": "2a03:1b20:3:f011::f701",
        "shadowsocks_extra_addr_in": [
          "2a03:1b20:3:f011::b702",
          "2a03:1b20:3:f011::b703",
          "2a03:1b20:3:f011::b704",
          "2a03:1b20:3:f011::b705",
          "2a03:1b20:3:f011::b706",
          "2a03:1b20:3:f011::b707",
          "2a03:1b20:3:f011::b708",
          "2a03:1b20:3:f011::b709",
          "2a03:1b20:3:f011::b70a",
          "2a03:1b20:3:f011::b70b",
          "2a03:1b20:3:f011::b70c",
          "2a03:1b20:3:f011::b70d",
          "2a03:1b20:3:f011::b70e",
          "2a03:1b20:3:f011::b70f",
          "2a03:1b20:3:f011::b710",
          "2a03:1b20:3:f011::b711",
          "2a03:1b20:3:f011::b712",
          "2a03:1b20:3:f011::b713",
          "2a03:1b20:3:f011::b714",
          "2a03:1b20:3:f011::b715",
          "2a03:1b20:3:f011::b716",
          "2a03:1b20:3:f011::b717",
          "2a03:1b20:3:f011::b718",
          "2a03:1b20:3:f011::b719",
          "2a03:1b20:3:f011::b71a",
          "2a03:1b20:3:f011::b71b",
          "2a03:1b20:3:f011::b71c",
          "2a03:1b20:3:f011::b71d",
          "2a03:1b20:3:f011::b71e",
          "2a03:1b20:3:f011::b71f"
        ],
        "features": {
          "lwo": {}
        }
      },
      {
        "hostname": "nl-ams-wg-008",
        "location": "nl-ams",
        "active": true,
        "owned": true,
        "provider": "31173",
        "stboot": true,
        "ipv4_addr_in": "193.32.249.73",
        "include_in_country": true,
        "weight": 50,
        "public_key": "hf+klJbIyUoGUaFHgac9W+yriwb9uvSnafDfnmEW9Hc=",
        "ipv6_addr_in": "2a03:1b20:3:f011::f801",
        "shadowsocks_extra_addr_in": [
          "193.32.249.209",
          "2a03:1b20:3:f011::b802",
          "2a03:1b20:3:f011::b803",
          "2a03:1b20:3:f011::b804",
          "2a03:1b20:3:f011::b805",
          "2a03:1b20:3:f011::b806",
          "2a03:1b20:3:f011::b807",
          "2a03:1b20:3:f011::b808",
          "2a03:1b20:3:f011::b809",
          "2a03:1b20:3:f011::b80a",
          "2a03:1b20:3:f011::b80b",
          "2a03:1b20:3:f011::b80c",
          "2a03:1b20:3:f011::b80d",
          "2a03:1b20:3:f011::b80e",
          "2a03:1b20:3:f011::b80f",
          "2a03:1b20:3:f011::b810",
          "2a03:1b20:3:f011::b811",
          "2a03:1b20:3:f011::b812",
          "2a03:1b20:3:f011::b813",
          "2a03:1b20:3:f011::b814",
          "2a03:1b20:3:f011::b815",
          "2a03:1b20:3:f011::b816",
          "2a03:1b20:3:f011::b817",
          "2a03:1b20:3:f011::b818",
          "2a03:1b20:3:f011::b819",
          "2a03:1b20:3:f011::b81a",
          "2a03:1b20:3:f011::b81b",
          "2a03:1b20:3:f011::b81c",
          "2a03:1b20:3:f011::b81d",
          "2a03:1b20:3:f011::b81e",
          "2a03:1b20:3:f011::b81f"
        ],
        "features": {
          "lwo": {}
        }
      },
      {
        "hostname": "nl-ams-wg-101",
        "location": "nl-ams",
        "active": true,
        "owned": false,
        "provider": "xtom",
        "stboot": true,
        "ipv4_addr_in": "92.60.40.194",
        "include_in_country": true,
        "weight": 0,
        "public_key": "m9w2Fr0rcN6R1a9HYrGnUTU176rTZIq2pcsovPd9sms=",
        "ipv6_addr_in": "2a0c:59c0:18::a20f"
      },
      {
        "hostname": "nl-ams-wg-102",
        "location": "nl-ams",
        "active": true,
        "owned": false,
        "provider": "xtom",
        "stboot": true,
        "ipv4_addr_in": "92.60.40.209",
        "include_in_country": true,
        "weight": 0,
        "public_key": "uUYbYGKoA6UBh1hfkAz5tAWFv4SmteYC9kWh7/K6Ah0=",
        "ipv6_addr_in": "2a0c:59c0:18::a21f"
      },
      {
        "hostname": "nl-ams-wg-103",
        "location": "nl-ams",
        "active": true,
        "owned": false,
        "provider": "xtom",
        "stboot": true,
        "ipv4_addr_in": "92.60.40.224",
        "include_in_country": true,
        "weight": 0,
        "public_key": "CE7mlfDJ4gpwLPB/CyPfIusITnGZwDI9v4IlVueGT24=",
        "ipv6_addr_in": "2a0c:59c0:18::a22f",
        "features": {
          "lwo": {},
          "quic": {
            "addr_in": [
              "92.60.40.237"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "nl-ams-wg-103.blockerad.eu"
          }
        }
      },
      {
        "hostname": "nl-ams-wg-201",
        "location": "nl-ams",
        "active": true,
        "owned": false,
        "provider": "DataPacket",
        "stboot": true,
        "ipv4_addr_in": "169.150.196.2",
        "include_in_country": true,
        "weight": 100,
        "public_key": "vt+yTcpxWvH8qiSncd1wSPV/78vt2aE2BBU8ZbG7x1Q=",
        "ipv6_addr_in": "2a02:6ea0:c034:1::a30f",
        "daita": true,
        "features": {
          "daita": {}
        }
      },
      {
        "hostname": "nl-ams-wg-202",
        "location": "nl-ams",
        "active": true,
        "owned": false,
        "provider": "DataPacket",
        "stboot": true,
        "ipv4_addr_in": "169.150.196.15",
        "include_in_country": true,
        "weight": 100,
        "public_key": "BChJDLOwZu9Q1oH0UcrxcHP6xxHhyRbjrBUsE0e07Vk=",
        "ipv6_addr_in": "2a02:6ea0:c034:2::a31f"
      },
      {
        "hostname": "nl-ams-wg-203",
        "location": "nl-ams",
        "active": true,
        "owned": false,
        "provider": "DataPacket",
        "stboot": true,
        "ipv4_addr_in": "169.150.196.28",
        "include_in_country": true,
        "weight": 100,
        "public_key": "M5z8TKjJYpIJ3FXoXy7k58IUaoVro2tWMKSgC5WIqR8=",
        "ipv6_addr_in": "2a02:6ea0:c034:3::a32f"
      },
      {
        "hostname": "nl-ams-wg-301",
        "location": "nl-ams",
        "active": true,
        "owned": true,
        "provider": "xtom",
        "stboot": true,
        "ipv4_addr_in": "185.184.222.3",
        "include_in_country": true,
        "weight": 100,
        "public_key": "bcCnX0Rtwat5a02t80k0aVJU5Q3z48dwuePiSXQ1kEY=",
        "ipv6_addr_in": "2a07:d883:700:1::f001",
        "daita": true,
        "shadowsocks_extra_addr_in": [
          "185.184.222.14",
          "185.184.222.15",
          "185.184.222.16",
          "185.184.222.17",
          "185.184.222.18",
          "185.184.222.19",
          "185.184.222.20",
          "185.184.222.21",
          "185.184.222.22",
          "185.184.222.23",
          "185.184.222.24",
          "185.184.222.25",
          "185.184.222.26",
          "185.184.222.27",
          "185.184.222.28",
          "185.184.222.29",
          "2a07:d883:700:1::b002",
          "2a07:d883:700:1::b003",
          "2a07:d883:700:1::b004",
          "2a07:d883:700:1::b005",
          "2a07:d883:700:1::b006",
          "2a07:d883:700:1::b007",
          "2a07:d883:700:1::b008",
          "2a07:d883:700:1::b009",
          "2a07:d883:700:1::b00a",
          "2a07:d883:700:1::b00b",
          "2a07:d883:700:1::b00c",
          "2a07:d883:700:1::b00d",
          "2a07:d883:700:1::b00e",
          "2a07:d883:700:1::b00f",
          "2a07:d883:700:1::b010",
          "2a07:d883:700:1::b011",
          "2a07:d883:700:1::b012",
          "2a07:d883:700:1::b013",
          "2a07:d883:700:1::b014",
          "2a07:d883:700:1::b015",
          "2a07:d883:700:1::b016",
          "2a07:d883:700:1::b017",
          "2a07:d883:700:1::b018",
          "2a07:d883:700:1::b019",
          "2a07:d883:700:1::b01a",
          "2a07:d883:700:1::b01b",
          "2a07:d883:700:1::b01c",
          "2a07:d883:700:1::b01d",
          "2a07:d883:700:1::b01e",
          "2a07:d883:700:1::b01f"
        ],
        "features": {
          "daita": {},
          "lwo": {},
          "quic": {
            "addr_in": [
              "185.184.222.30",
              "185.184.222.31",
              "185.184.222.32",
              "185.184.222.33",
              "185.184.222.34",
              "185.184.222.35",
              "185.184.222.36",
              "185.184.222.37",
              "185.184.222.38",
              "185.184.222.39",
              "185.184.222.40",
              "185.184.222.41",
              "185.184.222.42",
              "185.184.222.43",
              "185.184.222.44",
              "2a07:d883:700:1::c002",
              "2a07:d883:700:1::c003",
              "2a07:d883:700:1::c004",
              "2a07:d883:700:1::c005",
              "2a07:d883:700:1::c006",
              "2a07:d883:700:1::c007",
              "2a07:d883:700:1::c008",
              "2a07:d883:700:1::c009",
              "2a07:d883:700:1::c00a",
              "2a07:d883:700:1::c00b",
              "2a07:d883:700:1::c00c",
              "2a07:d883:700:1::c00d",
              "2a07:d883:700:1::c00e",
              "2a07:d883:700:1::c00f",
              "2a07:d883:700:1::c010",
              "2a07:d883:700:1::c011",
              "2a07:d883:700:1::c012",
              "2a07:d883:700:1::c013",
              "2a07:d883:700:1::c014",
              "2a07:d883:700:1::c015",
              "2a07:d883:700:1::c016",
              "2a07:d883:700:1::c017",
              "2a07:d883:700:1::c018",
              "2a07:d883:700:1::c019",
              "2a07:d883:700:1::c01a",
              "2a07:d883:700:1::c01b",
              "2a07:d883:700:1::c01c",
              "2a07:d883:700:1::c01d",
              "2a07:d883:700:1::c01e",
              "2a07:d883:700:1::c01f"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "nl-ams-wg-301.blockerad.eu"
          }
        }
      },
      {
        "hostname": "nl-ams-wg-302",
        "location": "nl-ams",
        "active": true,
        "owned": true,
        "provider": "xtom",
        "stboot": true,
        "ipv4_addr_in": "185.184.222.166",
        "include_in_country": true,
        "weight": 100,
        "public_key": "P40jSYOl1qrMXtRBszMp5W7bHZMDM7zyxysqJcUGxWw=",
        "ipv6_addr_in": "2a07:d883:700:2::f001",
        "daita": true,
        "shadowsocks_extra_addr_in": [
          "185.184.222.178",
          "185.184.222.179",
          "185.184.222.180",
          "185.184.222.181",
          "185.184.222.182",
          "185.184.222.183",
          "185.184.222.184",
          "185.184.222.185",
          "185.184.222.186",
          "185.184.222.187",
          "185.184.222.188",
          "185.184.222.189",
          "185.184.222.190",
          "185.184.222.191",
          "185.184.222.192",
          "2a07:d883:700:2::b002",
          "2a07:d883:700:2::b003",
          "2a07:d883:700:2::b004",
          "2a07:d883:700:2::b005",
          "2a07:d883:700:2::b006",
          "2a07:d883:700:2::b007",
          "2a07:d883:700:2::b008",
          "2a07:d883:700:2::b009",
          "2a07:d883:700:2::b00a",
          "2a07:d883:700:2::b00b",
          "2a07:d883:700:2::b00c",
          "2a07:d883:700:2::b00d",
          "2a07:d883:700:2::b00e",
          "2a07:d883:700:2::b00f",
          "2a07:d883:700:2::b010",
          "2a07:d883:700:2::b011",
          "2a07:d883:700:2::b012",
          "2a07:d883:700:2::b013",
          "2a07:d883:700:2::b014",
          "2a07:d883:700:2::b015",
          "2a07:d883:700:2::b016",
          "2a07:d883:700:2::b017",
          "2a07:d883:700:2::b018",
          "2a07:d883:700:2::b019",
          "2a07:d883:700:2::b01a",
          "2a07:d883:700:2::b01b",
          "2a07:d883:700:2::b01c",
          "2a07:d883:700:2::b01d",
          "2a07:d883:700:2::b01e",
          "2a07:d883:700:2::b01f"
        ],
        "features": {
          "daita": {},
          "lwo": {},
          "quic": {
            "addr_in": [
              "185.184.222.193",
              "185.184.222.194",
              "185.184.222.195",
              "185.184.222.196",
              "185.184.222.197",
              "185.184.222.198",
              "185.184.222.199",
              "185.184.222.200",
              "185.184.222.201",
              "185.184.222.202",
              "185.184.222.203",
              "185.184.222.204",
              "185.184.222.205",
              "185.184.222.206",
              "185.184.222.207",
              "2a07:d883:700:2::c002",
              "2a07:d883:700:2::c003",
              "2a07:d883:700:2::c004",
              "2a07:d883:700:2::c005",
              "2a07:d883:700:2::c006",
              "2a07:d883:700:2::c007",
              "2a07:d883:700:2::c008",
              "2a07:d883:700:2::c009",
              "2a07:d883:700:2::c00a",
              "2a07:d883:700:2::c00b",
              "2a07:d883:700:2::c00c",
              "2a07:d883:700:2::c00d",
              "2a07:d883:700:2::c00e",
              "2a07:d883:700:2::c00f",
              "2a07:d883:700:2::c010",
              "2a07:d883:700:2::c011",
              "2a07:d883:700:2::c012",
              "2a07:d883:700:2::c013",
              "2a07:d883:700:2::c014",
              "2a07:d883:700:2::c015",
              "2a07:d883:700:2::c016",
              "2a07:d883:700:2::c017",
              "2a07:d883:700:2::c018",
              "2a07:d883:700:2::c019",
              "2a07:d883:700:2::c01a",
              "2a07:d883:700:2::c01b",
              "2a07:d883:700:2::c01c",
              "2a07:d883:700:2::c01d",
              "2a07:d883:700:2::c01e",
              "2a07:d883:700:2::c01f"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "nl-ams-wg-302.blockerad.eu"
          }
        }
      },
      {
        "hostname": "nl-ams-wg-303",
        "location": "nl-ams",
        "active": true,
        "owned": true,
        "provider": "xtom",
        "stboot": true,
        "ipv4_addr_in": "185.184.222.209",
        "include_in_country": true,
        "weight": 100,
        "public_key": "Ax99pLRK5ixjeBz50E2qB8aWRrj5mw0QEdS6ZThiA3o=",
        "ipv6_addr_in": "2a07:d883:700:3::f001",
        "daita": true,
        "shadowsocks_extra_addr_in": [
          "185.184.222.220",
          "185.184.222.221",
          "185.184.222.222",
          "185.184.222.223",
          "185.184.222.224",
          "185.184.222.225",
          "185.184.222.226",
          "185.184.222.227",
          "185.184.222.228",
          "185.184.222.229",
          "185.184.222.230",
          "185.184.222.231",
          "185.184.222.232",
          "185.184.222.233",
          "185.184.222.234",
          "2a07:d883:700:3::b002",
          "2a07:d883:700:3::b003",
          "2a07:d883:700:3::b004",
          "2a07:d883:700:3::b005",
          "2a07:d883:700:3::b006",
          "2a07:d883:700:3::b007",
          "2a07:d883:700:3::b008",
          "2a07:d883:700:3::b009",
          "2a07:d883:700:3::b00a",
          "2a07:d883:700:3::b00b",
          "2a07:d883:700:3::b00c",
          "2a07:d883:700:3::b00d",
          "2a07:d883:700:3::b00e",
          "2a07:d883:700:3::b00f",
          "2a07:d883:700:3::b010",
          "2a07:d883:700:3::b011",
          "2a07:d883:700:3::b012",
          "2a07:d883:700:3::b013",
          "2a07:d883:700:3::b014",
          "2a07:d883:700:3::b015",
          "2a07:d883:700:3::b016",
          "2a07:d883:700:3::b017",
          "2a07:d883:700:3::b018",
          "2a07:d883:700:3::b019",
          "2a07:d883:700:3::b01a",
          "2a07:d883:700:3::b01b",
          "2a07:d883:700:3::b01c",
          "2a07:d883:700:3::b01d",
          "2a07:d883:700:3::b01e",
          "2a07:d883:700:3::b01f"
        ],
        "features": {
          "daita": {},
          "lwo": {},
          "quic": {
            "addr_in": [
              "185.184.222.235",
              "185.184.222.236",
              "185.184.222.237",
              "185.184.222.238",
              "185.184.222.239",
              "185.184.222.240",
              "185.184.222.241",
              "185.184.222.242",
              "185.184.222.243",
              "185.184.222.244",
              "185.184.222.245",
              "185.184.222.246",
              "185.184.222.247",
              "185.184.222.248",
              "185.184.222.249",
              "185.184.222.250",
              "2a07:d883:700:3::c002",
              "2a07:d883:700:3::c003",
              "2a07:d883:700:3::c004",
              "2a07:d883:700:3::c005",
              "2a07:d883:700:3::c006",
              "2a07:d883:700:3::c007",
              "2a07:d883:700:3::c008",
              "2a07:d883:700:3::c009",
              "2a07:d883:700:3::c00a",
              "2a07:d883:700:3::c00b",
              "2a07:d883:700:3::c00c",
              "2a07:d883:700:3::c00d",
              "2a07:d883:700:3::c00e",
              "2a07:d883:700:3::c00f",
              "2a07:d883:700:3::c010",
              "2a07:d883:700:3::c011",
              "2a07:d883:700:3::c012",
              "2a07:d883:700:3::c013",
              "2a07:d883:700:3::c014",
              "2a07:d883:700:3::c015",
              "2a07:d883:700:3::c016",
              "2a07:d883:700:3::c017",
              "2a07:d883:700:3::c018",
              "2a07:d883:700:3::c019",
              "2a07:d883:700:3::c01a",
              "2a07:d883:700:3::c01b",
              "2a07:d883:700:3::c01c",
              "2a07:d883:700:3::c01d",
              "2a07:d883:700:3::c01e",
              "2a07:d883:700:3::c01f"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "nl-ams-wg-303.blockerad.eu"
          }
        }
      },
      {
        "hostname": "no-osl-wg-001",
        "location": "no-osl",
        "active": true,
        "owned": true,
        "provider": "Blix",
        "stboot": true,
        "ipv4_addr_in": "176.125.235.71",
        "include_in_country": true,
        "weight": 100,
        "public_key": "jOUZjMq2PWHDzQxu3jPXktYB7EKeFwBzGZx56cTXXQg=",
        "ipv6_addr_in": "2a02:20c8:4124::a01f",
        "daita": true,
        "shadowsocks_extra_addr_in": [
          "91.90.44.27",
          "91.90.44.28",
          "91.90.44.29",
          "91.90.44.30",
          "91.90.44.31",
          "91.90.44.32",
          "91.90.44.33",
          "91.90.44.34",
          "91.90.44.35",
          "91.90.44.36",
          "91.90.44.37",
          "91.90.44.38",
          "91.90.44.39",
          "91.90.44.40",
          "91.90.44.41",
          "91.90.44.42",
          "91.90.44.43",
          "91.90.44.44",
          "91.90.44.45",
          "91.90.44.46",
          "2a02:20c8:4124::b002",
          "2a02:20c8:4124::b003",
          "2a02:20c8:4124::b004",
          "2a02:20c8:4124::b005",
          "2a02:20c8:4124::b006",
          "2a02:20c8:4124::b007",
          "2a02:20c8:4124::b008",
          "2a02:20c8:4124::b009",
          "2a02:20c8:4124::b00a",
          "2a02:20c8:4124::b00b",
          "2a02:20c8:4124::b00c",
          "2a02:20c8:4124::b00d",
          "2a02:20c8:4124::b00e",
          "2a02:20c8:4124::b00f",
          "2a02:20c8:4124::b010",
          "2a02:20c8:4124::b011",
          "2a02:20c8:4124::b012",
          "2a02:20c8:4124::b013",
          "2a02:20c8:4124::b014",
          "2a02:20c8:4124::b015",
          "2a02:20c8:4124::b016",
          "2a02:20c8:4124::b017",
          "2a02:20c8:4124::b018",
          "2a02:20c8:4124::b019",
          "2a02:20c8:4124::b01a",
          "2a02:20c8:4124::b01b",
          "2a02:20c8:4124::b01c",
          "2a02:20c8:4124::b01d",
          "2a02:20c8:4124::b01e",
          "2a02:20c8:4124::b01f"
        ],
        "features": {
          "daita": {},
          "lwo": {},
          "quic": {
            "addr_in": [
              "91.90.44.47",
              "91.90.44.48",
              "91.90.44.49",
              "91.90.44.50",
              "91.90.44.51",
              "91.90.44.52",
              "91.90.44.53",
              "91.90.44.54",
              "91.90.44.55",
              "91.90.44.56",
              "91.90.44.57",
              "91.90.44.58",
              "91.90.44.59",
              "91.90.44.60",
              "91.90.44.61",
              "91.90.44.62",
              "2a02:20c8:4124::c002",
              "2a02:20c8:4124::c003",
              "2a02:20c8:4124::c004",
              "2a02:20c8:4124::c005",
              "2a02:20c8:4124::c006",
              "2a02:20c8:4124::c007",
              "2a02:20c8:4124::c008",
              "2a02:20c8:4124::c009",
              "2a02:20c8:4124::c00a",
              "2a02:20c8:4124::c00b",
              "2a02:20c8:4124::c00c",
              "2a02:20c8:4124::c00d",
              "2a02:20c8:4124::c00e",
              "2a02:20c8:4124::c00f",
              "2a02:20c8:4124::c010",
              "2a02:20c8:4124::c011",
              "2a02:20c8:4124::c012",
              "2a02:20c8:4124::c013",
              "2a02:20c8:4124::c014",
              "2a02:20c8:4124::c015",
              "2a02:20c8:4124::c016",
              "2a02:20c8:4124::c017",
              "2a02:20c8:4124::c018",
              "2a02:20c8:4124::c019",
              "2a02:20c8:4124::c01a",
              "2a02:20c8:4124::c01b",
              "2a02:20c8:4124::c01c",
              "2a02:20c8:4124::c01d",
              "2a02:20c8:4124::c01e",
              "2a02:20c8:4124::c01f"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "no-osl-wg-001.blockerad.eu"
          }
        }
      },
      {
        "hostname": "no-osl-wg-002",
        "location": "no-osl",
        "active": true,
        "owned": true,
        "provider": "Blix",
        "stboot": true,
        "ipv4_addr_in": "176.125.235.72",
        "include_in_country": true,
        "weight": 100,
        "public_key": "IhhpKphSFWpwja1P4HBctZ367G3Q53EgdeFGZro29Tc=",
        "ipv6_addr_in": "2a02:20c8:4124::a02f",
        "daita": true,
        "shadowsocks_extra_addr_in": [
          "176.125.235.81",
          "176.125.235.82",
          "176.125.235.83",
          "176.125.235.84",
          "176.125.235.85",
          "176.125.235.86",
          "176.125.235.87",
          "176.125.235.88",
          "176.125.235.89",
          "176.125.235.91",
          "176.125.235.92",
          "176.125.235.93",
          "176.125.235.94",
          "176.125.235.95",
          "176.125.235.96",
          "176.125.235.97",
          "176.125.235.98",
          "176.125.235.99",
          "2a02:20c8:4124::b102",
          "2a02:20c8:4124::b103",
          "2a02:20c8:4124::b104",
          "2a02:20c8:4124::b105",
          "2a02:20c8:4124::b106",
          "2a02:20c8:4124::b107",
          "2a02:20c8:4124::b108",
          "2a02:20c8:4124::b109",
          "2a02:20c8:4124::b10a",
          "2a02:20c8:4124::b10b",
          "2a02:20c8:4124::b10c",
          "2a02:20c8:4124::b10d",
          "2a02:20c8:4124::b10e",
          "2a02:20c8:4124::b10f",
          "2a02:20c8:4124::b110",
          "2a02:20c8:4124::b111",
          "2a02:20c8:4124::b112",
          "2a02:20c8:4124::b113",
          "2a02:20c8:4124::b114",
          "2a02:20c8:4124::b115",
          "2a02:20c8:4124::b116",
          "2a02:20c8:4124::b117",
          "2a02:20c8:4124::b118",
          "2a02:20c8:4124::b119",
          "2a02:20c8:4124::b11a",
          "2a02:20c8:4124::b11b",
          "2a02:20c8:4124::b11c",
          "2a02:20c8:4124::b11d",
          "2a02:20c8:4124::b11e",
          "2a02:20c8:4124::b11f"
        ],
        "features": {
          "daita": {},
          "lwo": {},
          "quic": {
            "addr_in": [
              "176.125.235.101",
              "176.125.235.102",
              "176.125.235.103",
              "176.125.235.104",
              "176.125.235.105",
              "176.125.235.106",
              "176.125.235.107",
              "176.125.235.108",
              "176.125.235.109",
              "176.125.235.110",
              "176.125.235.111",
              "176.125.235.112",
              "176.125.235.113",
              "176.125.235.114",
              "176.125.235.115",
              "176.125.235.116",
              "176.125.235.117",
              "176.125.235.118",
              "176.125.235.119",
              "176.125.235.120",
              "176.125.235.121",
              "176.125.235.122",
              "176.125.235.123",
              "176.125.235.124",
              "176.125.235.125",
              "2a02:20c8:4124::c102",
              "2a02:20c8:4124::c103",
              "2a02:20c8:4124::c104",
              "2a02:20c8:4124::c105",
              "2a02:20c8:4124::c106",
              "2a02:20c8:4124::c107",
              "2a02:20c8:4124::c108",
              "2a02:20c8:4124::c109",
              "2a02:20c8:4124::c10a",
              "2a02:20c8:4124::c10b",
              "2a02:20c8:4124::c10c",
              "2a02:20c8:4124::c10d",
              "2a02:20c8:4124::c10e",
              "2a02:20c8:4124::c10f",
              "2a02:20c8:4124::c110",
              "2a02:20c8:4124::c111",
              "2a02:20c8:4124::c112",
              "2a02:20c8:4124::c113",
              "2a02:20c8:4124::c114",
              "2a02:20c8:4124::c115",
              "2a02:20c8:4124::c116",
              "2a02:20c8:4124::c117",
              "2a02:20c8:4124::c118",
              "2a02:20c8:4124::c119",
              "2a02:20c8:4124::c11a",
              "2a02:20c8:4124::c11b",
              "2a02:20c8:4124::c11c",
              "2a02:20c8:4124::c11d",
              "2a02:20c8:4124::c11e",
              "2a02:20c8:4124::c11f"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "no-osl-wg-002.blockerad.eu"
          }
        }
      },
      {
        "hostname": "no-osl-wg-003",
        "location": "no-osl",
        "active": true,
        "owned": true,
        "provider": "Blix",
        "stboot": true,
        "ipv4_addr_in": "176.125.235.73",
        "include_in_country": true,
        "weight": 100,
        "public_key": "zOBWmQ3BEOZKsYKbj4dC2hQjxCbr3eKa6wGWyEDYbC4=",
        "ipv6_addr_in": "2a02:20c8:4124::a03f",
        "daita": true,
        "shadowsocks_extra_addr_in": [
          "178.255.149.150",
          "178.255.149.151",
          "178.255.149.152",
          "178.255.149.153",
          "178.255.149.154",
          "178.255.149.155",
          "178.255.149.156",
          "178.255.149.157",
          "178.255.149.158",
          "178.255.149.159",
          "178.255.149.160",
          "178.255.149.161",
          "178.255.149.162",
          "178.255.149.163",
          "178.255.149.164",
          "178.255.149.165",
          "178.255.149.166",
          "178.255.149.167",
          "178.255.149.168",
          "178.255.149.169",
          "2a02:20c8:4124::b202",
          "2a02:20c8:4124::b203",
          "2a02:20c8:4124::b204",
          "2a02:20c8:4124::b205",
          "2a02:20c8:4124::b206",
          "2a02:20c8:4124::b207",
          "2a02:20c8:4124::b208",
          "2a02:20c8:4124::b209",
          "2a02:20c8:4124::b20a",
          "2a02:20c8:4124::b20b",
          "2a02:20c8:4124::b20c",
          "2a02:20c8:4124::b20d",
          "2a02:20c8:4124::b20e",
          "2a02:20c8:4124::b20f",
          "2a02:20c8:4124::b210",
          "2a02:20c8:4124::b211",
          "2a02:20c8:4124::b212",
          "2a02:20c8:4124::b213",
          "2a02:20c8:4124::b214",
          "2a02:20c8:4124::b215",
          "2a02:20c8:4124::b216",
          "2a02:20c8:4124::b217",
          "2a02:20c8:4124::b218",
          "2a02:20c8:4124::b219",
          "2a02:20c8:4124::b21a",
          "2a02:20c8:4124::b21b",
          "2a02:20c8:4124::b21c",
          "2a02:20c8:4124::b21d",
          "2a02:20c8:4124::b21e",
          "2a02:20c8:4124::b21f"
        ],
        "features": {
          "daita": {},
          "lwo": {},
          "quic": {
            "addr_in": [
              "178.255.149.170",
              "178.255.149.171",
              "178.255.149.172",
              "178.255.149.173",
              "178.255.149.174",
              "178.255.149.175",
              "178.255.149.176",
              "178.255.149.177",
              "178.255.149.178",
              "178.255.149.179",
              "178.255.149.180",
              "178.255.149.181",
              "178.255.149.182",
              "178.255.149.183",
              "178.255.149.184",
              "178.255.149.185",
              "178.255.149.186",
              "178.255.149.187",
              "178.255.149.188",
              "178.255.149.189",
              "2a02:20c8:4124::c202",
              "2a02:20c8:4124::c203",
              "2a02:20c8:4124::c204",
              "2a02:20c8:4124::c205",
              "2a02:20c8:4124::c206",
              "2a02:20c8:4124::c207",
              "2a02:20c8:4124::c208",
              "2a02:20c8:4124::c209",
              "2a02:20c8:4124::c20a",
              "2a02:20c8:4124::c20b",
              "2a02:20c8:4124::c20c",
              "2a02:20c8:4124::c20d",
              "2a02:20c8:4124::c20e",
              "2a02:20c8:4124::c20f",
              "2a02:20c8:4124::c210",
              "2a02:20c8:4124::c211",
              "2a02:20c8:4124::c212",
              "2a02:20c8:4124::c213",
              "2a02:20c8:4124::c214",
              "2a02:20c8:4124::c215",
              "2a02:20c8:4124::c216",
              "2a02:20c8:4124::c217",
              "2a02:20c8:4124::c218",
              "2a02:20c8:4124::c219",
              "2a02:20c8:4124::c21a",
              "2a02:20c8:4124::c21b",
              "2a02:20c8:4124::c21c",
              "2a02:20c8:4124::c21d",
              "2a02:20c8:4124::c21e",
              "2a02:20c8:4124::c21f"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "no-osl-wg-003.blockerad.eu"
          }
        }
      },
      {
        "hostname": "no-osl-wg-101",
        "location": "no-osl",
        "active": true,
        "owned": true,
        "provider": "31173",
        "stboot": true,
        "ipv4_addr_in": "141.98.253.5",
        "include_in_country": true,
        "weight": 100,
        "public_key": "QXR6DwdWn2urvyVNt5pFulLuhkyeuTp2STwGgEQ6Ehw=",
        "ipv6_addr_in": "2a03:1b20:c:f011:1::f001",
        "shadowsocks_extra_addr_in": [
          "141.98.253.7",
          "2a03:1b20:c:f011:1::b002",
          "2a03:1b20:c:f011:1::b003",
          "2a03:1b20:c:f011:1::b004",
          "2a03:1b20:c:f011:1::b005",
          "2a03:1b20:c:f011:1::b006",
          "2a03:1b20:c:f011:1::b007",
          "2a03:1b20:c:f011:1::b008",
          "2a03:1b20:c:f011:1::b009",
          "2a03:1b20:c:f011:1::b00a",
          "2a03:1b20:c:f011:1::b00b",
          "2a03:1b20:c:f011:1::b00c",
          "2a03:1b20:c:f011:1::b00d",
          "2a03:1b20:c:f011:1::b00e",
          "2a03:1b20:c:f011:1::b00f",
          "2a03:1b20:c:f011:1::b010",
          "2a03:1b20:c:f011:1::b011",
          "2a03:1b20:c:f011:1::b012",
          "2a03:1b20:c:f011:1::b013",
          "2a03:1b20:c:f011:1::b014",
          "2a03:1b20:c:f011:1::b015",
          "2a03:1b20:c:f011:1::b016",
          "2a03:1b20:c:f011:1::b017",
          "2a03:1b20:c:f011:1::b018",
          "2a03:1b20:c:f011:1::b019",
          "2a03:1b20:c:f011:1::b01a",
          "2a03:1b20:c:f011:1::b01b",
          "2a03:1b20:c:f011:1::b01c",
          "2a03:1b20:c:f011:1::b01d",
          "2a03:1b20:c:f011:1::b01e",
          "2a03:1b20:c:f011:1::b01f"
        ],
        "features": {
          "lwo": {},
          "quic": {
            "addr_in": [
              "141.98.253.8",
              "2a03:1b20:c:f011:1::c002",
              "2a03:1b20:c:f011:1::c003",
              "2a03:1b20:c:f011:1::c004",
              "2a03:1b20:c:f011:1::c005",
              "2a03:1b20:c:f011:1::c006",
              "2a03:1b20:c:f011:1::c007",
              "2a03:1b20:c:f011:1::c008",
              "2a03:1b20:c:f011:1::c009",
              "2a03:1b20:c:f011:1::c00a",
              "2a03:1b20:c:f011:1::c00b",
              "2a03:1b20:c:f011:1::c00c",
              "2a03:1b20:c:f011:1::c00d",
              "2a03:1b20:c:f011:1::c00e",
              "2a03:1b20:c:f011:1::c00f",
              "2a03:1b20:c:f011:1::c010",
              "2a03:1b20:c:f011:1::c011",
              "2a03:1b20:c:f011:1::c012",
              "2a03:1b20:c:f011:1::c013",
              "2a03:1b20:c:f011:1::c014",
              "2a03:1b20:c:f011:1::c015",
              "2a03:1b20:c:f011:1::c016",
              "2a03:1b20:c:f011:1::c017",
              "2a03:1b20:c:f011:1::c018",
              "2a03:1b20:c:f011:1::c019",
              "2a03:1b20:c:f011:1::c01a",
              "2a03:1b20:c:f011:1::c01b",
              "2a03:1b20:c:f011:1::c01c",
              "2a03:1b20:c:f011:1::c01d",
              "2a03:1b20:c:f011:1::c01e",
              "2a03:1b20:c:f011:1::c01f"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "no-osl-wg-101.blockerad.eu"
          }
        }
      },
      {
        "hostname": "no-osl-wg-102",
        "location": "no-osl",
        "active": true,
        "owned": true,
        "provider": "31173",
        "stboot": true,
        "ipv4_addr_in": "141.98.253.85",
        "include_in_country": true,
        "weight": 100,
        "public_key": "MlS7Fep/Lx6d0j2c+ZWPWECAC+OpGVRq/NV4AWvw+C8=",
        "ipv6_addr_in": "2a03:1b20:c:f011:2::f001",
        "shadowsocks_extra_addr_in": [
          "141.98.253.87",
          "2a03:1b20:c:f011:2::b002",
          "2a03:1b20:c:f011:2::b003",
          "2a03:1b20:c:f011:2::b004",
          "2a03:1b20:c:f011:2::b005",
          "2a03:1b20:c:f011:2::b006",
          "2a03:1b20:c:f011:2::b007",
          "2a03:1b20:c:f011:2::b008",
          "2a03:1b20:c:f011:2::b009",
          "2a03:1b20:c:f011:2::b00a",
          "2a03:1b20:c:f011:2::b00b",
          "2a03:1b20:c:f011:2::b00c",
          "2a03:1b20:c:f011:2::b00d",
          "2a03:1b20:c:f011:2::b00e",
          "2a03:1b20:c:f011:2::b00f",
          "2a03:1b20:c:f011:2::b010",
          "2a03:1b20:c:f011:2::b011",
          "2a03:1b20:c:f011:2::b012",
          "2a03:1b20:c:f011:2::b013",
          "2a03:1b20:c:f011:2::b014",
          "2a03:1b20:c:f011:2::b015",
          "2a03:1b20:c:f011:2::b016",
          "2a03:1b20:c:f011:2::b017",
          "2a03:1b20:c:f011:2::b018",
          "2a03:1b20:c:f011:2::b019",
          "2a03:1b20:c:f011:2::b01a",
          "2a03:1b20:c:f011:2::b01b",
          "2a03:1b20:c:f011:2::b01c",
          "2a03:1b20:c:f011:2::b01d",
          "2a03:1b20:c:f011:2::b01e",
          "2a03:1b20:c:f011:2::b01f"
        ],
        "features": {
          "lwo": {},
          "quic": {
            "addr_in": [
              "141.98.253.88",
              "2a03:1b20:c:f011:2::c002",
              "2a03:1b20:c:f011:2::c003",
              "2a03:1b20:c:f011:2::c004",
              "2a03:1b20:c:f011:2::c005",
              "2a03:1b20:c:f011:2::c006",
              "2a03:1b20:c:f011:2::c007",
              "2a03:1b20:c:f011:2::c008",
              "2a03:1b20:c:f011:2::c009",
              "2a03:1b20:c:f011:2::c00a",
              "2a03:1b20:c:f011:2::c00b",
              "2a03:1b20:c:f011:2::c00c",
              "2a03:1b20:c:f011:2::c00d",
              "2a03:1b20:c:f011:2::c00e",
              "2a03:1b20:c:f011:2::c00f",
              "2a03:1b20:c:f011:2::c010",
              "2a03:1b20:c:f011:2::c011",
              "2a03:1b20:c:f011:2::c012",
              "2a03:1b20:c:f011:2::c013",
              "2a03:1b20:c:f011:2::c014",
              "2a03:1b20:c:f011:2::c015",
              "2a03:1b20:c:f011:2::c016",
              "2a03:1b20:c:f011:2::c017",
              "2a03:1b20:c:f011:2::c018",
              "2a03:1b20:c:f011:2::c019",
              "2a03:1b20:c:f011:2::c01a",
              "2a03:1b20:c:f011:2::c01b",
              "2a03:1b20:c:f011:2::c01c",
              "2a03:1b20:c:f011:2::c01d",
              "2a03:1b20:c:f011:2::c01e",
              "2a03:1b20:c:f011:2::c01f"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "no-osl-wg-102.blockerad.eu"
          }
        }
      },
      {
        "hostname": "no-osl-wg-103",
        "location": "no-osl",
        "active": true,
        "owned": true,
        "provider": "31173",
        "stboot": true,
        "ipv4_addr_in": "141.98.253.165",
        "include_in_country": true,
        "weight": 100,
        "public_key": "7aoQqj/A9rVeZmuT6kCRPuQ4Pf0yy2T2RlTo7P8LYGE=",
        "ipv6_addr_in": "2a03:1b20:c:f011:3::f001",
        "shadowsocks_extra_addr_in": [
          "141.98.253.167",
          "2a03:1b20:c:f011:3::b002",
          "2a03:1b20:c:f011:3::b003",
          "2a03:1b20:c:f011:3::b004",
          "2a03:1b20:c:f011:3::b005",
          "2a03:1b20:c:f011:3::b006",
          "2a03:1b20:c:f011:3::b007",
          "2a03:1b20:c:f011:3::b008",
          "2a03:1b20:c:f011:3::b009",
          "2a03:1b20:c:f011:3::b00a",
          "2a03:1b20:c:f011:3::b00b",
          "2a03:1b20:c:f011:3::b00c",
          "2a03:1b20:c:f011:3::b00d",
          "2a03:1b20:c:f011:3::b00e",
          "2a03:1b20:c:f011:3::b00f",
          "2a03:1b20:c:f011:3::b010",
          "2a03:1b20:c:f011:3::b011",
          "2a03:1b20:c:f011:3::b012",
          "2a03:1b20:c:f011:3::b013",
          "2a03:1b20:c:f011:3::b014",
          "2a03:1b20:c:f011:3::b015",
          "2a03:1b20:c:f011:3::b016",
          "2a03:1b20:c:f011:3::b017",
          "2a03:1b20:c:f011:3::b018",
          "2a03:1b20:c:f011:3::b019",
          "2a03:1b20:c:f011:3::b01a",
          "2a03:1b20:c:f011:3::b01b",
          "2a03:1b20:c:f011:3::b01c",
          "2a03:1b20:c:f011:3::b01d",
          "2a03:1b20:c:f011:3::b01e",
          "2a03:1b20:c:f011:3::b01f"
        ],
        "features": {
          "quic": {
            "addr_in": [
              "141.98.253.168",
              "2a03:1b20:c:f011:3::c002",
              "2a03:1b20:c:f011:3::c003",
              "2a03:1b20:c:f011:3::c004",
              "2a03:1b20:c:f011:3::c005",
              "2a03:1b20:c:f011:3::c006",
              "2a03:1b20:c:f011:3::c007",
              "2a03:1b20:c:f011:3::c008",
              "2a03:1b20:c:f011:3::c009",
              "2a03:1b20:c:f011:3::c00a",
              "2a03:1b20:c:f011:3::c00b",
              "2a03:1b20:c:f011:3::c00c",
              "2a03:1b20:c:f011:3::c00d",
              "2a03:1b20:c:f011:3::c00e",
              "2a03:1b20:c:f011:3::c00f",
              "2a03:1b20:c:f011:3::c010",
              "2a03:1b20:c:f011:3::c011",
              "2a03:1b20:c:f011:3::c012",
              "2a03:1b20:c:f011:3::c013",
              "2a03:1b20:c:f011:3::c014",
              "2a03:1b20:c:f011:3::c015",
              "2a03:1b20:c:f011:3::c016",
              "2a03:1b20:c:f011:3::c017",
              "2a03:1b20:c:f011:3::c018",
              "2a03:1b20:c:f011:3::c019",
              "2a03:1b20:c:f011:3::c01a",
              "2a03:1b20:c:f011:3::c01b",
              "2a03:1b20:c:f011:3::c01c",
              "2a03:1b20:c:f011:3::c01d",
              "2a03:1b20:c:f011:3::c01e",
              "2a03:1b20:c:f011:3::c01f"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "no-osl-wg-103.blockerad.eu"
          }
        }
      },
      {
        "hostname": "no-svg-wg-001",
        "location": "no-svg",
        "active": true,
        "owned": true,
        "provider": "Blix",
        "stboot": true,
        "ipv4_addr_in": "194.127.199.2",
        "include_in_country": true,
        "weight": 300,
        "public_key": "kduYoE/b1mA2Pjszx1CzE4Lktsdc2zsUU8Relul2m2U=",
        "ipv6_addr_in": "2a02:20c8:4120::a01f",
        "shadowsocks_extra_addr_in": [
          "2a02:20c8:4120::b002",
          "2a02:20c8:4120::b003",
          "2a02:20c8:4120::b004",
          "2a02:20c8:4120::b005",
          "2a02:20c8:4120::b006",
          "2a02:20c8:4120::b007",
          "2a02:20c8:4120::b008",
          "2a02:20c8:4120::b009",
          "2a02:20c8:4120::b00a",
          "2a02:20c8:4120::b00b",
          "2a02:20c8:4120::b00c",
          "2a02:20c8:4120::b00d",
          "2a02:20c8:4120::b00e",
          "2a02:20c8:4120::b00f",
          "2a02:20c8:4120::b010",
          "2a02:20c8:4120::b011",
          "2a02:20c8:4120::b012",
          "2a02:20c8:4120::b013",
          "2a02:20c8:4120::b014",
          "2a02:20c8:4120::b015",
          "2a02:20c8:4120::b016",
          "2a02:20c8:4120::b017",
          "2a02:20c8:4120::b018",
          "2a02:20c8:4120::b019",
          "2a02:20c8:4120::b01a",
          "2a02:20c8:4120::b01b",
          "2a02:20c8:4120::b01c",
          "2a02:20c8:4120::b01d",
          "2a02:20c8:4120::b01e",
          "2a02:20c8:4120::b01f"
        ]
      },
      {
        "hostname": "no-svg-wg-002",
        "location": "no-svg",
        "active": true,
        "owned": true,
        "provider": "Blix",
        "stboot": true,
        "ipv4_addr_in": "194.127.199.31",
        "include_in_country": true,
        "weight": 300,
        "public_key": "U9fbFesIIr2HotWdkfMpKyOEPk+RYtE2oYn3KoLmkj4=",
        "ipv6_addr_in": "2a02:20c8:4120::a02f",
        "shadowsocks_extra_addr_in": [
          "2a02:20c8:4120::b102",
          "2a02:20c8:4120::b103",
          "2a02:20c8:4120::b104",
          "2a02:20c8:4120::b105",
          "2a02:20c8:4120::b106",
          "2a02:20c8:4120::b107",
          "2a02:20c8:4120::b108",
          "2a02:20c8:4120::b109",
          "2a02:20c8:4120::b10a",
          "2a02:20c8:4120::b10b",
          "2a02:20c8:4120::b10c",
          "2a02:20c8:4120::b10d",
          "2a02:20c8:4120::b10e",
          "2a02:20c8:4120::b10f",
          "2a02:20c8:4120::b110",
          "2a02:20c8:4120::b111",
          "2a02:20c8:4120::b112",
          "2a02:20c8:4120::b113",
          "2a02:20c8:4120::b114",
          "2a02:20c8:4120::b115",
          "2a02:20c8:4120::b116",
          "2a02:20c8:4120::b117",
          "2a02:20c8:4120::b118",
          "2a02:20c8:4120::b119",
          "2a02:20c8:4120::b11a",
          "2a02:20c8:4120::b11b",
          "2a02:20c8:4120::b11c",
          "2a02:20c8:4120::b11d",
          "2a02:20c8:4120::b11e",
          "2a02:20c8:4120::b11f"
        ],
        "features": {
          "lwo": {}
        }
      },
      {
        "hostname": "no-svg-wg-003",
        "location": "no-svg",
        "active": true,
        "owned": true,
        "provider": "Blix",
        "stboot": true,
        "ipv4_addr_in": "194.127.199.62",
        "include_in_country": true,
        "weight": 300,
        "public_key": "btc4mh3n9jVCW6yikw3cOPct0x3B5cDK+kKnvgCV0S0=",
        "ipv6_addr_in": "2a02:20c8:4120::a03f",
        "shadowsocks_extra_addr_in": [
          "2a02:20c8:4120::b202",
          "2a02:20c8:4120::b203",
          "2a02:20c8:4120::b204",
          "2a02:20c8:4120::b205",
          "2a02:20c8:4120::b206",
          "2a02:20c8:4120::b207",
          "2a02:20c8:4120::b208",
          "2a02:20c8:4120::b209",
          "2a02:20c8:4120::b20a",
          "2a02:20c8:4120::b20b",
          "2a02:20c8:4120::b20c",
          "2a02:20c8:4120::b20d",
          "2a02:20c8:4120::b20e",
          "2a02:20c8:4120::b20f",
          "2a02:20c8:4120::b210",
          "2a02:20c8:4120::b211",
          "2a02:20c8:4120::b212",
          "2a02:20c8:4120::b213",
          "2a02:20c8:4120::b214",
          "2a02:20c8:4120::b215",
          "2a02:20c8:4120::b216",
          "2a02:20c8:4120::b217",
          "2a02:20c8:4120::b218",
          "2a02:20c8:4120::b219",
          "2a02:20c8:4120::b21a",
          "2a02:20c8:4120::b21b",
          "2a02:20c8:4120::b21c",
          "2a02:20c8:4120::b21d",
          "2a02:20c8:4120::b21e",
          "2a02:20c8:4120::b21f"
        ]
      },
      {
        "hostname": "no-svg-wg-004",
        "location": "no-svg",
        "active": true,
        "owned": true,
        "provider": "Blix",
        "stboot": true,
        "ipv4_addr_in": "194.127.199.93",
        "include_in_country": true,
        "weight": 300,
        "public_key": "Fu98PLCZw/FTcQqyTy0vzaepkfxuSLAah7wnafGVO1g=",
        "ipv6_addr_in": "2a02:20c8:4120::a04f",
        "shadowsocks_extra_addr_in": [
          "2a02:20c8:4120::b302",
          "2a02:20c8:4120::b303",
          "2a02:20c8:4120::b304",
          "2a02:20c8:4120::b305",
          "2a02:20c8:4120::b306",
          "2a02:20c8:4120::b307",
          "2a02:20c8:4120::b308",
          "2a02:20c8:4120::b309",
          "2a02:20c8:4120::b30a",
          "2a02:20c8:4120::b30b",
          "2a02:20c8:4120::b30c",
          "2a02:20c8:4120::b30d",
          "2a02:20c8:4120::b30e",
          "2a02:20c8:4120::b30f",
          "2a02:20c8:4120::b310",
          "2a02:20c8:4120::b311",
          "2a02:20c8:4120::b312",
          "2a02:20c8:4120::b313",
          "2a02:20c8:4120::b314",
          "2a02:20c8:4120::b315",
          "2a02:20c8:4120::b316",
          "2a02:20c8:4120::b317",
          "2a02:20c8:4120::b318",
          "2a02:20c8:4120::b319",
          "2a02:20c8:4120::b31a",
          "2a02:20c8:4120::b31b",
          "2a02:20c8:4120::b31c",
          "2a02:20c8:4120::b31d",
          "2a02:20c8:4120::b31e",
          "2a02:20c8:4120::b31f"
        ],
        "features": {
          "lwo": {}
        }
      },
      {
        "hostname": "nz-akl-wg-301",
        "location": "nz-akl",
        "active": true,
        "owned": false,
        "provider": "hostuniversal",
        "stboot": true,
        "ipv4_addr_in": "103.75.11.50",
        "include_in_country": true,
        "weight": 100,
        "public_key": "BOEOP01bcND1a0zvmOxRHPB/ObgjgPIzBJE5wbm7B0M=",
        "ipv6_addr_in": "2404:f780:5:deb::f001"
      },
      {
        "hostname": "nz-akl-wg-302",
        "location": "nz-akl",
        "active": true,
        "owned": false,
        "provider": "hostuniversal",
        "stboot": true,
        "ipv4_addr_in": "103.75.11.66",
        "include_in_country": true,
        "weight": 100,
        "public_key": "80WGWgFP9q3eU16MuLJISB1fzAu2LM2heschmokVSVU=",
        "ipv6_addr_in": "2404:f780:5:dec::c02f",
        "features": {
          "lwo": {}
        }
      },
      {
        "hostname": "nz-akl-wg-303",
        "location": "nz-akl",
        "active": true,
        "owned": false,
        "provider": "hostuniversal",
        "stboot": true,
        "ipv4_addr_in": "103.75.11.98",
        "include_in_country": true,
        "weight": 100,
        "public_key": "1G7/wskBBlY77PXMV3sSAv4eCm5IPjxx99Wlfs58QSI=",
        "ipv6_addr_in": "2404:f780:5:def::f201",
        "features": {
          "lwo": {}
        }
      },
      {
        "hostname": "pe-lim-wg-001",
        "location": "pe-lim",
        "active": true,
        "owned": false,
        "provider": "DataPacket",
        "stboot": true,
        "ipv4_addr_in": "95.173.223.130",
        "include_in_country": true,
        "weight": 100,
        "public_key": "S4j4wshSstg9Au6ewFWr9vsZ8giovGPpKbKehXN8Nwc=",
        "ipv6_addr_in": "2a02:6ea0:5500:1::f001",
        "shadowsocks_extra_addr_in": [
          "95.173.223.132"
        ]
      },
      {
        "hostname": "pe-lim-wg-002",
        "location": "pe-lim",
        "active": true,
        "owned": false,
        "provider": "DataPacket",
        "stboot": true,
        "ipv4_addr_in": "95.173.223.159",
        "include_in_country": true,
        "weight": 100,
        "public_key": "y7LsVrzYjeMLlTZmVUuuDkFvJp0kONC6+w+wP0gUIyo=",
        "ipv6_addr_in": "2a02:6ea0:5500:2::f001",
        "shadowsocks_extra_addr_in": [
          "95.173.223.161"
        ]
      },
      {
        "hostname": "ph-mnl-wg-001",
        "location": "ph-mnl",
        "active": true,
        "owned": false,
        "provider": "Zenlayer",
        "stboot": true,
        "ipv4_addr_in": "129.227.118.162",
        "include_in_country": true,
        "weight": 100,
        "public_key": "hORxMf/YMmN2/8VWOnTCdgGzGfEyXUEQQ5EBfoCyFDM=",
        "ipv6_addr_in": "2602:ffe4:c06:11e::f001",
        "shadowsocks_extra_addr_in": [
          "129.227.118.164"
        ]
      },
      {
        "hostname": "ph-mnl-wg-002",
        "location": "ph-mnl",
        "active": true,
        "owned": false,
        "provider": "Zenlayer",
        "stboot": true,
        "ipv4_addr_in": "156.59.127.194",
        "include_in_country": true,
        "weight": 100,
        "public_key": "TfNj4SJuIZzaXSxulpNzreDZXcX6GJJj+UYpqA2XMVE=",
        "ipv6_addr_in": "2602:ffe4:c06:11e::f101",
        "shadowsocks_extra_addr_in": [
          "156.59.127.196"
        ]
      },
      {
        "hostname": "pl-waw-wg-101",
        "location": "pl-waw",
        "active": true,
        "owned": false,
        "provider": "DataPacket",
        "stboot": true,
        "ipv4_addr_in": "45.134.212.66",
        "include_in_country": true,
        "weight": 100,
        "public_key": "fO4beJGkKZxosCZz1qunktieuPyzPnEVKVQNhzanjnA=",
        "ipv6_addr_in": "2a02:6ea0:ce08:1::f001"
      },
      {
        "hostname": "pl-waw-wg-102",
        "location": "pl-waw",
        "active": true,
        "owned": false,
        "provider": "DataPacket",
        "stboot": true,
        "ipv4_addr_in": "45.134.212.79",
        "include_in_country": true,
        "weight": 100,
        "public_key": "nJEWae9GebEY7yJONXQ1j4gbURV4QULjx388woAlbDs=",
        "ipv6_addr_in": "2a02:6ea0:ce08:2::a06f",
        "features": {
          "lwo": {}
        }
      },
      {
        "hostname": "pl-waw-wg-103",
        "location": "pl-waw",
        "active": true,
        "owned": false,
        "provider": "DataPacket",
        "stboot": true,
        "ipv4_addr_in": "45.134.212.92",
        "include_in_country": true,
        "weight": 100,
        "public_key": "07eUtSNhiJ9dQXBmUqFODj0OqhmbKQGbRikIq9f90jM=",
        "ipv6_addr_in": "2a02:6ea0:ce08:3::a07f",
        "features": {
          "lwo": {}
        }
      },
      {
        "hostname": "pl-waw-wg-201",
        "location": "pl-waw",
        "active": true,
        "owned": false,
        "provider": "M247",
        "stboot": true,
        "ipv4_addr_in": "45.128.38.226",
        "include_in_country": true,
        "weight": 100,
        "public_key": "XwFAczY5LdogFwE9soDecXWqywSCDGuRyJhr/0psI00=",
        "ipv6_addr_in": "2a0d:5600:13:67::a01f"
      },
      {
        "hostname": "pl-waw-wg-202",
        "location": "pl-waw",
        "active": true,
        "owned": false,
        "provider": "M247",
        "stboot": true,
        "ipv4_addr_in": "146.70.144.34",
        "include_in_country": true,
        "weight": 100,
        "public_key": "nyfOkamv1ryTS62lsmyU96cqI0dtqek84DhyxWgAQGY=",
        "ipv6_addr_in": "2a0d:5600:13:c47::a02f"
      },
      {
        "hostname": "pt-lis-wg-201",
        "location": "pt-lis",
        "active": true,
        "owned": false,
        "provider": "DataPacket",
        "stboot": true,
        "ipv4_addr_in": "149.88.20.206",
        "include_in_country": true,
        "weight": 100,
        "public_key": "JCAe7D/owe11Ii2rhpIKhGZvP/V1P1cVZwZAjpSRqmc=",
        "ipv6_addr_in": "2a02:6ea0:fb01:1::f001",
        "features": {
          "lwo": {}
        }
      },
      {
        "hostname": "pt-lis-wg-202",
        "location": "pt-lis",
        "active": true,
        "owned": false,
        "provider": "DataPacket",
        "stboot": true,
        "ipv4_addr_in": "149.88.20.193",
        "include_in_country": true,
        "weight": 100,
        "public_key": "5P4CQYQeSozk/3KQZh/kl7tUMFGgRB60Ttx6x2nh+F8=",
        "ipv6_addr_in": "2a02:6ea0:fb01:2::f002",
        "features": {
          "lwo": {}
        }
      },
      {
        "hostname": "pt-lis-wg-301",
        "location": "pt-lis",
        "active": true,
        "owned": false,
        "provider": "HostRoyale",
        "stboot": true,
        "ipv4_addr_in": "185.92.210.195",
        "include_in_country": true,
        "weight": 100,
        "public_key": "A2+7EIVBsq1jZlnx0AWb8xkoaTkkn8LRFwAl3Qb/xTc=",
        "ipv6_addr_in": "2a06:3040:0:1410::f001"
      },
      {
        "hostname": "pt-lis-wg-302",
        "location": "pt-lis",
        "active": true,
        "owned": false,
        "provider": "HostRoyale",
        "stboot": true,
        "ipv4_addr_in": "185.92.210.225",
        "include_in_country": true,
        "weight": 100,
        "public_key": "4V8TnXninUL+vjZqXKUIFnBPOhjFEicdVHa5ZMZhSzc=",
        "ipv6_addr_in": "2a06:3040:0:1410::f101",
        "features": {
          "lwo": {}
        }
      },
      {
        "hostname": "ro-buh-wg-001",
        "location": "ro-buh",
        "active": true,
        "owned": false,
        "provider": "M247",
        "stboot": true,
        "ipv4_addr_in": "146.70.124.130",
        "include_in_country": true,
        "weight": 100,
        "public_key": "xpKhRTf9JI269S2PujLbrJm1TwIe67HD5CLe+sP4tUU=",
        "ipv6_addr_in": "2a04:9dc0:0:133::a01f"
      },
      {
        "hostname": "ro-buh-wg-002",
        "location": "ro-buh",
        "active": true,
        "owned": false,
        "provider": "M247",
        "stboot": true,
        "ipv4_addr_in": "146.70.124.194",
        "include_in_country": true,
        "weight": 100,
        "public_key": "Ekc3+qU88FuMfkEMyLlgRqDYv+WHJvUsfOMI/C0ydE4=",
        "ipv6_addr_in": "2a04:9dc0:0:135::f001"
      },
      {
        "hostname": "rs-beg-wg-101",
        "location": "rs-beg",
        "active": true,
        "owned": false,
        "provider": "M247",
        "stboot": true,
        "ipv4_addr_in": "146.70.193.2",
        "include_in_country": true,
        "weight": 100,
        "public_key": "Orrce1127WpljZa+xKbF21zJkJ9wM1M3VJ5GJ/UsIDU=",
        "ipv6_addr_in": "2001:ac8:7d:37::a01f"
      },
      {
        "hostname": "rs-beg-wg-102",
        "location": "rs-beg",
        "active": true,
        "owned": false,
        "provider": "M247",
        "stboot": true,
        "ipv4_addr_in": "146.70.193.66",
        "include_in_country": true,
        "weight": 100,
        "public_key": "35lawt+YUx10ELTFhZhg4/xzXRmjxCl/j1O4RK5d60M=",
        "ipv6_addr_in": "2001:ac8:7d:38::a02f"
      },
      {
        "hostname": "se-got-wg-001",
        "location": "se-got",
        "active": true,
        "owned": true,
        "provider": "31173",
        "stboot": true,
        "ipv4_addr_in": "185.213.154.66",
        "include_in_country": true,
        "weight": 1,
        "public_key": "5JMPeO7gXIbR5CnUa/NPNK4L5GqUnreF0/Bozai4pl4=",
        "ipv6_addr_in": "2a03:1b20:5:f011:31::a03f",
        "shadowsocks_extra_addr_in": [
          "185.213.154.238",
          "2a03:1b20:5:f011:31::b002",
          "2a03:1b20:5:f011:31::b003",
          "2a03:1b20:5:f011:31::b004",
          "2a03:1b20:5:f011:31::b005",
          "2a03:1b20:5:f011:31::b006",
          "2a03:1b20:5:f011:31::b007",
          "2a03:1b20:5:f011:31::b008",
          "2a03:1b20:5:f011:31::b009",
          "2a03:1b20:5:f011:31::b00a",
          "2a03:1b20:5:f011:31::b00b",
          "2a03:1b20:5:f011:31::b00c",
          "2a03:1b20:5:f011:31::b00d",
          "2a03:1b20:5:f011:31::b00e",
          "2a03:1b20:5:f011:31::b00f",
          "2a03:1b20:5:f011:31::b010",
          "2a03:1b20:5:f011:31::b011",
          "2a03:1b20:5:f011:31::b012",
          "2a03:1b20:5:f011:31::b013",
          "2a03:1b20:5:f011:31::b014",
          "2a03:1b20:5:f011:31::b015",
          "2a03:1b20:5:f011:31::b016",
          "2a03:1b20:5:f011:31::b017",
          "2a03:1b20:5:f011:31::b018",
          "2a03:1b20:5:f011:31::b019",
          "2a03:1b20:5:f011:31::b01a",
          "2a03:1b20:5:f011:31::b01b",
          "2a03:1b20:5:f011:31::b01c",
          "2a03:1b20:5:f011:31::b01d",
          "2a03:1b20:5:f011:31::b01e",
          "2a03:1b20:5:f011:31::b01f"
        ],
        "features": {
          "lwo": {}
        }
      },
      {
        "hostname": "se-got-wg-002",
        "location": "se-got",
        "active": true,
        "owned": true,
        "provider": "31173",
        "stboot": true,
        "ipv4_addr_in": "185.213.154.67",
        "include_in_country": true,
        "weight": 1,
        "public_key": "AtvE5KdPeQtOcE2QyXaPt9eQoBV3GBxzimQ2FIuGQ2U=",
        "ipv6_addr_in": "2a03:1b20:5:f011::a05f",
        "shadowsocks_extra_addr_in": [
          "2a03:1b20:5:f011:31::b202",
          "2a03:1b20:5:f011:31::b203",
          "2a03:1b20:5:f011:31::b204",
          "2a03:1b20:5:f011:31::b205",
          "2a03:1b20:5:f011:31::b206",
          "2a03:1b20:5:f011:31::b207",
          "2a03:1b20:5:f011:31::b208",
          "2a03:1b20:5:f011:31::b209",
          "2a03:1b20:5:f011:31::b20a",
          "2a03:1b20:5:f011:31::b20b",
          "2a03:1b20:5:f011:31::b20c",
          "2a03:1b20:5:f011:31::b20d",
          "2a03:1b20:5:f011:31::b20e",
          "2a03:1b20:5:f011:31::b20f",
          "2a03:1b20:5:f011:31::b210",
          "2a03:1b20:5:f011:31::b211",
          "2a03:1b20:5:f011:31::b212",
          "2a03:1b20:5:f011:31::b213",
          "2a03:1b20:5:f011:31::b214",
          "2a03:1b20:5:f011:31::b215",
          "2a03:1b20:5:f011:31::b216",
          "2a03:1b20:5:f011:31::b217",
          "2a03:1b20:5:f011:31::b218",
          "2a03:1b20:5:f011:31::b219",
          "2a03:1b20:5:f011:31::b21a",
          "2a03:1b20:5:f011:31::b21b",
          "2a03:1b20:5:f011:31::b21c",
          "2a03:1b20:5:f011:31::b21d",
          "2a03:1b20:5:f011:31::b21e",
          "2a03:1b20:5:f011:31::b21f"
        ],
        "features": {
          "lwo": {}
        }
      },
      {
        "hostname": "se-got-wg-003",
        "location": "se-got",
        "active": true,
        "owned": true,
        "provider": "31173",
        "stboot": true,
        "ipv4_addr_in": "185.213.154.68",
        "include_in_country": true,
        "weight": 100,
        "public_key": "BLNHNoGO88LjV/wDBa7CUUwUzPq/fO2UwcGLy56hKy4=",
        "ipv6_addr_in": "2a03:1b20:5:f011::a09f",
        "shadowsocks_extra_addr_in": [
          "2a03:1b20:5:f011:3:b:0:1",
          "2a03:1b20:5:f011:3:b:0:2",
          "2a03:1b20:5:f011:3:b:0:3",
          "2a03:1b20:5:f011:3:b:0:4",
          "2a03:1b20:5:f011:3:b:0:5",
          "2a03:1b20:5:f011:3:b:0:6",
          "2a03:1b20:5:f011:3:b:0:7",
          "2a03:1b20:5:f011:3:b:0:8",
          "2a03:1b20:5:f011:3:b:0:9",
          "2a03:1b20:5:f011:3:b:0:a",
          "2a03:1b20:5:f011:3:b:0:b",
          "2a03:1b20:5:f011:3:b:0:e",
          "2a03:1b20:5:f011:3:b:0:d",
          "2a03:1b20:5:f011:3:b:0:e",
          "2a03:1b20:5:f011:3:b:0:f",
          "2a03:1b20:5:f011:3:b:0:10",
          "2a03:1b20:5:f011:3:b:0:11",
          "2a03:1b20:5:f011:3:b:0:12",
          "2a03:1b20:5:f011:3:b:0:13",
          "2a03:1b20:5:f011:3:b:0:14",
          "2a03:1b20:5:f011:3:b:0:15",
          "2a03:1b20:5:f011:3:b:0:16",
          "2a03:1b20:5:f011:3:b:0:17",
          "2a03:1b20:5:f011:3:b:0:18",
          "2a03:1b20:5:f011:3:b:0:19",
          "2a03:1b20:5:f011:3:b:0:1a",
          "2a03:1b20:5:f011:3:b:0:1b",
          "2a03:1b20:5:f011:3:b:0:1c",
          "2a03:1b20:5:f011:3:b:0:1d",
          "2a03:1b20:5:f011:3:b:0:1e",
          "2a03:1b20:5:f011:3:b:0:1f",
          "2a03:1b20:5:f011:3:b:0:20",
          "2a03:1b20:5:f011:3:b:0:21",
          "2a03:1b20:5:f011:3:b:0:22",
          "2a03:1b20:5:f011:3:b:0:23",
          "2a03:1b20:5:f011:3:b:0:24",
          "2a03:1b20:5:f011:3:b:0:25",
          "2a03:1b20:5:f011:3:b:0:26",
          "2a03:1b20:5:f011:3:b:0:27",
          "2a03:1b20:5:f011:3:b:0:28",
          "2a03:1b20:5:f011:3:b:0:29",
          "2a03:1b20:5:f011:3:b:0:2a",
          "2a03:1b20:5:f011:3:b:0:2b",
          "2a03:1b20:5:f011:3:b:0:2c",
          "2a03:1b20:5:f011:3:b:0:2d",
          "2a03:1b20:5:f011:3:b:0:2e",
          "2a03:1b20:5:f011:3:b:0:2f",
          "2a03:1b20:5:f011:3:b:0:30",
          "2a03:1b20:5:f011:3:b:0:31",
          "2a03:1b20:5:f011:3:b:0:32",
          "2a03:1b20:5:f011:3:b:0:33",
          "2a03:1b20:5:f011:3:b:0:34",
          "2a03:1b20:5:f011:3:b:0:35",
          "2a03:1b20:5:f011:3:b:0:36",
          "2a03:1b20:5:f011:3:b:0:37",
          "2a03:1b20:5:f011:3:b:0:38",
          "2a03:1b20:5:f011:3:b:0:39",
          "2a03:1b20:5:f011:3:b:0:3a",
          "2a03:1b20:5:f011:3:b:0:3b",
          "2a03:1b20:5:f011:3:b:0:3c",
          "2a03:1b20:5:f011:3:b:0:3d",
          "2a03:1b20:5:f011:3:b:0:3e",
          "2a03:1b20:5:f011:3:b:0:3f"
        ],
        "features": {
          "lwo": {},
          "quic": {
            "addr_in": [
              "2a03:1b20:5:f011:3:c:0:1",
              "2a03:1b20:5:f011:3:c:0:2",
              "2a03:1b20:5:f011:3:c:0:3",
              "2a03:1b20:5:f011:3:c:0:4",
              "2a03:1b20:5:f011:3:c:0:5",
              "2a03:1b20:5:f011:3:c:0:6",
              "2a03:1b20:5:f011:3:c:0:7",
              "2a03:1b20:5:f011:3:c:0:8",
              "2a03:1b20:5:f011:3:c:0:9",
              "2a03:1b20:5:f011:3:c:0:a",
              "2a03:1b20:5:f011:3:c:0:b",
              "2a03:1b20:5:f011:3:c:0:e",
              "2a03:1b20:5:f011:3:c:0:d",
              "2a03:1b20:5:f011:3:c:0:e",
              "2a03:1b20:5:f011:3:c:0:f",
              "2a03:1b20:5:f011:3:c:0:10",
              "2a03:1b20:5:f011:3:c:0:11",
              "2a03:1b20:5:f011:3:c:0:12",
              "2a03:1b20:5:f011:3:c:0:13",
              "2a03:1b20:5:f011:3:c:0:14",
              "2a03:1b20:5:f011:3:c:0:15",
              "2a03:1b20:5:f011:3:c:0:16",
              "2a03:1b20:5:f011:3:c:0:17",
              "2a03:1b20:5:f011:3:c:0:18",
              "2a03:1b20:5:f011:3:c:0:19",
              "2a03:1b20:5:f011:3:c:0:1a",
              "2a03:1b20:5:f011:3:c:0:1b",
              "2a03:1b20:5:f011:3:c:0:1c",
              "2a03:1b20:5:f011:3:c:0:1d",
              "2a03:1b20:5:f011:3:c:0:1e",
              "2a03:1b20:5:f011:3:c:0:1f",
              "2a03:1b20:5:f011:3:c:0:20",
              "2a03:1b20:5:f011:3:c:0:21",
              "2a03:1b20:5:f011:3:c:0:22",
              "2a03:1b20:5:f011:3:c:0:23",
              "2a03:1b20:5:f011:3:c:0:24",
              "2a03:1b20:5:f011:3:c:0:25",
              "2a03:1b20:5:f011:3:c:0:26",
              "2a03:1b20:5:f011:3:c:0:27",
              "2a03:1b20:5:f011:3:c:0:28",
              "2a03:1b20:5:f011:3:c:0:29",
              "2a03:1b20:5:f011:3:c:0:2a",
              "2a03:1b20:5:f011:3:c:0:2b",
              "2a03:1b20:5:f011:3:c:0:2c",
              "2a03:1b20:5:f011:3:c:0:2d",
              "2a03:1b20:5:f011:3:c:0:2e",
              "2a03:1b20:5:f011:3:c:0:2f",
              "2a03:1b20:5:f011:3:c:0:30",
              "2a03:1b20:5:f011:3:c:0:31",
              "2a03:1b20:5:f011:3:c:0:32",
              "2a03:1b20:5:f011:3:c:0:33",
              "2a03:1b20:5:f011:3:c:0:34",
              "2a03:1b20:5:f011:3:c:0:35",
              "2a03:1b20:5:f011:3:c:0:36",
              "2a03:1b20:5:f011:3:c:0:37",
              "2a03:1b20:5:f011:3:c:0:38",
              "2a03:1b20:5:f011:3:c:0:39",
              "2a03:1b20:5:f011:3:c:0:3a",
              "2a03:1b20:5:f011:3:c:0:3b",
              "2a03:1b20:5:f011:3:c:0:3c",
              "2a03:1b20:5:f011:3:c:0:3d",
              "2a03:1b20:5:f011:3:c:0:3e",
              "2a03:1b20:5:f011:3:c:0:3f"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "se-got-wg-003.blockerad.eu"
          }
        }
      },
      {
        "hostname": "se-got-wg-004",
        "location": "se-got",
        "active": true,
        "owned": true,
        "provider": "31173",
        "stboot": true,
        "ipv4_addr_in": "185.213.154.69",
        "include_in_country": true,
        "weight": 100,
        "public_key": "veGD6/aEY6sMfN3Ls7YWPmNgu3AheO7nQqsFT47YSws=",
        "ipv6_addr_in": "2a03:1b20:5:f011::a10f",
        "shadowsocks_extra_addr_in": [
          "2a03:1b20:5:f011:31::b402",
          "2a03:1b20:5:f011:31::b403",
          "2a03:1b20:5:f011:31::b404",
          "2a03:1b20:5:f011:31::b405",
          "2a03:1b20:5:f011:31::b406",
          "2a03:1b20:5:f011:31::b407",
          "2a03:1b20:5:f011:31::b408",
          "2a03:1b20:5:f011:31::b409",
          "2a03:1b20:5:f011:31::b40a",
          "2a03:1b20:5:f011:31::b40b",
          "2a03:1b20:5:f011:31::b40c",
          "2a03:1b20:5:f011:31::b40d",
          "2a03:1b20:5:f011:31::b40e",
          "2a03:1b20:5:f011:31::b40f",
          "2a03:1b20:5:f011:31::b410",
          "2a03:1b20:5:f011:31::b411",
          "2a03:1b20:5:f011:31::b412",
          "2a03:1b20:5:f011:31::b413",
          "2a03:1b20:5:f011:31::b414",
          "2a03:1b20:5:f011:31::b415",
          "2a03:1b20:5:f011:31::b416",
          "2a03:1b20:5:f011:31::b417",
          "2a03:1b20:5:f011:31::b418",
          "2a03:1b20:5:f011:31::b419",
          "2a03:1b20:5:f011:31::b41a",
          "2a03:1b20:5:f011:31::b41b",
          "2a03:1b20:5:f011:31::b41c",
          "2a03:1b20:5:f011:31::b41d",
          "2a03:1b20:5:f011:31::b41e",
          "2a03:1b20:5:f011:31::b41f"
        ],
        "features": {
          "lwo": {}
        }
      },
      {
        "hostname": "se-got-wg-005",
        "location": "se-got",
        "active": true,
        "owned": true,
        "provider": "31173",
        "stboot": true,
        "ipv4_addr_in": "185.209.199.2",
        "include_in_country": true,
        "weight": 100,
        "public_key": "x4h55uXoIIKUqKjjm6PzNiZlzLjxjuAIKzvgU9UjOGw=",
        "ipv6_addr_in": "2a03:1b20:5:f011:5::f001",
        "features": {
          "lwo": {},
          "quic": {
            "addr_in": [
              "185.209.199.6",
              "2a03:1b20:5:f011:5::f00a"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "se-got-wg-005.blockerad.eu"
          }
        }
      },
      {
        "hostname": "se-got-wg-006",
        "location": "se-got",
        "active": true,
        "owned": true,
        "provider": "31173",
        "stboot": true,
        "ipv4_addr_in": "185.209.199.7",
        "include_in_country": true,
        "weight": 100,
        "public_key": "dcSpHioI+TY37dbZcviFA/sxSUqmpECXRZIapwR8pVg=",
        "ipv6_addr_in": "2a03:1b20:5:f011:6::f001",
        "daita": true,
        "features": {
          "daita": {},
          "lwo": {},
          "quic": {
            "addr_in": [
              "185.209.199.11",
              "2a03:1b20:5:f011:6::f00a"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "se-got-wg-006.blockerad.eu"
          }
        }
      },
      {
        "hostname": "se-got-wg-007",
        "location": "se-got",
        "active": true,
        "owned": true,
        "provider": "31173",
        "stboot": true,
        "ipv4_addr_in": "185.209.199.12",
        "include_in_country": true,
        "weight": 100,
        "public_key": "ywfkKYdoVAnjsSYW145ACtrw3DV8xTzFS1hlIO7QRD4=",
        "ipv6_addr_in": "2a03:1b20:5:f011:7::f001",
        "features": {
          "lwo": {},
          "quic": {
            "addr_in": [
              "185.209.199.16",
              "2a03:1b20:5:f011:7::f00a"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "se-got-wg-007.blockerad.eu"
          }
        }
      },
      {
        "hostname": "se-got-wg-008",
        "location": "se-got",
        "active": true,
        "owned": true,
        "provider": "31173",
        "stboot": true,
        "ipv4_addr_in": "185.209.199.17",
        "include_in_country": true,
        "weight": 100,
        "public_key": "Vh3Y2LsBG1yN4kDeebOr3J6dFooGJIBTftzVqlWhiD4=",
        "ipv6_addr_in": "2a03:1b20:5:f011:8::f001",
        "features": {
          "lwo": {},
          "quic": {
            "addr_in": [
              "185.209.199.21",
              "2a03:1b20:5:f011:8::f00a"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "se-got-wg-008.blockerad.eu"
          }
        }
      },
      {
        "hostname": "se-got-wg-101",
        "location": "se-got",
        "active": true,
        "owned": true,
        "provider": "31173",
        "stboot": true,
        "ipv4_addr_in": "185.213.154.70",
        "include_in_country": true,
        "weight": 100,
        "public_key": "B8UVAeNkAW4NiGHd1lpl933Drh4y7pMqpXJpH0SrGjQ=",
        "ipv6_addr_in": "2a03:1b20:5:f011::aaaf",
        "features": {
          "lwo": {}
        }
      },
      {
        "hostname": "se-mma-wg-001",
        "location": "se-mma",
        "active": true,
        "owned": true,
        "provider": "31173",
        "stboot": true,
        "ipv4_addr_in": "193.138.218.220",
        "include_in_country": true,
        "weight": 100,
        "public_key": "Qn1QaXYTJJSmJSMw18CGdnFiVM0/Gj/15OdkxbXCSG0=",
        "ipv6_addr_in": "2a03:1b20:1:f410::fa01",
        "shadowsocks_extra_addr_in": [
          "2a03:1b20:1:f410::ba02",
          "2a03:1b20:1:f410::ba03",
          "2a03:1b20:1:f410::ba04",
          "2a03:1b20:1:f410::ba05",
          "2a03:1b20:1:f410::ba06",
          "2a03:1b20:1:f410::ba07",
          "2a03:1b20:1:f410::ba08",
          "2a03:1b20:1:f410::ba09",
          "2a03:1b20:1:f410::ba0a",
          "2a03:1b20:1:f410::ba0b",
          "2a03:1b20:1:f410::ba0c",
          "2a03:1b20:1:f410::ba0d",
          "2a03:1b20:1:f410::ba0e",
          "2a03:1b20:1:f410::ba0f",
          "2a03:1b20:1:f410::ba10",
          "2a03:1b20:1:f410::ba11",
          "2a03:1b20:1:f410::ba12",
          "2a03:1b20:1:f410::ba13",
          "2a03:1b20:1:f410::ba14",
          "2a03:1b20:1:f410::ba15",
          "2a03:1b20:1:f410::ba16",
          "2a03:1b20:1:f410::ba17",
          "2a03:1b20:1:f410::ba18",
          "2a03:1b20:1:f410::ba19",
          "2a03:1b20:1:f410::ba1a",
          "2a03:1b20:1:f410::ba1b",
          "2a03:1b20:1:f410::ba1c",
          "2a03:1b20:1:f410::ba1d",
          "2a03:1b20:1:f410::ba1e",
          "2a03:1b20:1:f410::ba1f"
        ]
      },
      {
        "hostname": "se-mma-wg-002",
        "location": "se-mma",
        "active": true,
        "owned": true,
        "provider": "31173",
        "stboot": true,
        "ipv4_addr_in": "193.138.218.80",
        "include_in_country": true,
        "weight": 100,
        "public_key": "5y66WShsFXqM5K7/4CPEGCWfk7PQyNhVBT2ILjbGm2I=",
        "ipv6_addr_in": "2a03:1b20:1:f410::a15f",
        "shadowsocks_extra_addr_in": [
          "2a03:1b20:1:f410::bb02",
          "2a03:1b20:1:f410::bb03",
          "2a03:1b20:1:f410::bb04",
          "2a03:1b20:1:f410::bb05",
          "2a03:1b20:1:f410::bb06",
          "2a03:1b20:1:f410::bb07",
          "2a03:1b20:1:f410::bb08",
          "2a03:1b20:1:f410::bb09",
          "2a03:1b20:1:f410::bb0a",
          "2a03:1b20:1:f410::bb0b",
          "2a03:1b20:1:f410::bb0c",
          "2a03:1b20:1:f410::bb0d",
          "2a03:1b20:1:f410::bb0e",
          "2a03:1b20:1:f410::bb0f",
          "2a03:1b20:1:f410::bb10",
          "2a03:1b20:1:f410::bb11",
          "2a03:1b20:1:f410::bb12",
          "2a03:1b20:1:f410::bb13",
          "2a03:1b20:1:f410::bb14",
          "2a03:1b20:1:f410::bb15",
          "2a03:1b20:1:f410::bb16",
          "2a03:1b20:1:f410::bb17",
          "2a03:1b20:1:f410::bb18",
          "2a03:1b20:1:f410::bb19",
          "2a03:1b20:1:f410::bb1a",
          "2a03:1b20:1:f410::bb1b",
          "2a03:1b20:1:f410::bb1c",
          "2a03:1b20:1:f410::bb1d",
          "2a03:1b20:1:f410::bb1e",
          "2a03:1b20:1:f410::bb1f"
        ]
      },
      {
        "hostname": "se-mma-wg-003",
        "location": "se-mma",
        "active": true,
        "owned": true,
        "provider": "31173",
        "stboot": true,
        "ipv4_addr_in": "193.138.218.83",
        "include_in_country": true,
        "weight": 100,
        "public_key": "fZFAcd8vqWOBpRqlXifsjzGf16gMTg2GuwKyZtkG6UU=",
        "ipv6_addr_in": "2a03:1b20:1:f410::a18f",
        "shadowsocks_extra_addr_in": [
          "2a03:1b20:1:f410::bc02",
          "2a03:1b20:1:f410::bc03",
          "2a03:1b20:1:f410::bc04",
          "2a03:1b20:1:f410::bc05",
          "2a03:1b20:1:f410::bc06",
          "2a03:1b20:1:f410::bc07",
          "2a03:1b20:1:f410::bc08",
          "2a03:1b20:1:f410::bc09",
          "2a03:1b20:1:f410::bc0a",
          "2a03:1b20:1:f410::bc0b",
          "2a03:1b20:1:f410::bc0c",
          "2a03:1b20:1:f410::bc0d",
          "2a03:1b20:1:f410::bc0e",
          "2a03:1b20:1:f410::bc0f",
          "2a03:1b20:1:f410::bc10",
          "2a03:1b20:1:f410::bc11",
          "2a03:1b20:1:f410::bc12",
          "2a03:1b20:1:f410::bc13",
          "2a03:1b20:1:f410::bc14",
          "2a03:1b20:1:f410::bc15",
          "2a03:1b20:1:f410::bc16",
          "2a03:1b20:1:f410::bc17",
          "2a03:1b20:1:f410::bc18",
          "2a03:1b20:1:f410::bc19",
          "2a03:1b20:1:f410::bc1a",
          "2a03:1b20:1:f410::bc1b",
          "2a03:1b20:1:f410::bc1c",
          "2a03:1b20:1:f410::bc1d",
          "2a03:1b20:1:f410::bc1e",
          "2a03:1b20:1:f410::bc1f"
        ]
      },
      {
        "hostname": "se-mma-wg-004",
        "location": "se-mma",
        "active": true,
        "owned": true,
        "provider": "31173",
        "stboot": true,
        "ipv4_addr_in": "193.138.218.130",
        "include_in_country": false,
        "weight": 100,
        "public_key": "m4jnogFbACz7LByjo++8z5+1WV0BuR1T7E1OWA+n8h0=",
        "ipv6_addr_in": "2a03:1b20:1:f410:40::a04f"
      },
      {
        "hostname": "se-mma-wg-005",
        "location": "se-mma",
        "active": true,
        "owned": true,
        "provider": "31173",
        "stboot": true,
        "ipv4_addr_in": "193.138.218.82",
        "include_in_country": true,
        "weight": 100,
        "public_key": "qnJrQEf2JiDHMnMWFFxWz8I9NREockylVgYVE95s72s=",
        "ipv6_addr_in": "2a03:1b20:1:f410::a17f",
        "shadowsocks_extra_addr_in": [
          "2a03:1b20:1:f410::be02",
          "2a03:1b20:1:f410::be03",
          "2a03:1b20:1:f410::be04",
          "2a03:1b20:1:f410::be05",
          "2a03:1b20:1:f410::be06",
          "2a03:1b20:1:f410::be07",
          "2a03:1b20:1:f410::be08",
          "2a03:1b20:1:f410::be09",
          "2a03:1b20:1:f410::be0a",
          "2a03:1b20:1:f410::be0b",
          "2a03:1b20:1:f410::be0c",
          "2a03:1b20:1:f410::be0d",
          "2a03:1b20:1:f410::be0e",
          "2a03:1b20:1:f410::be0f",
          "2a03:1b20:1:f410::be10",
          "2a03:1b20:1:f410::be11",
          "2a03:1b20:1:f410::be12",
          "2a03:1b20:1:f410::be13",
          "2a03:1b20:1:f410::be14",
          "2a03:1b20:1:f410::be15",
          "2a03:1b20:1:f410::be16",
          "2a03:1b20:1:f410::be17",
          "2a03:1b20:1:f410::be18",
          "2a03:1b20:1:f410::be19",
          "2a03:1b20:1:f410::be1a",
          "2a03:1b20:1:f410::be1b",
          "2a03:1b20:1:f410::be1c",
          "2a03:1b20:1:f410::be1d",
          "2a03:1b20:1:f410::be1e",
          "2a03:1b20:1:f410::be1f"
        ],
        "features": {
          "lwo": {}
        }
      },
      {
        "hostname": "se-mma-wg-011",
        "location": "se-mma",
        "active": true,
        "owned": true,
        "provider": "31173",
        "stboot": true,
        "ipv4_addr_in": "141.98.255.94",
        "include_in_country": true,
        "weight": 2,
        "public_key": "vclzw8ytARhkEqw4cLUJPC3REvMZqWsO+7TYD/U2UVk=",
        "ipv6_addr_in": "2a03:1b20:1:f410::f101",
        "shadowsocks_extra_addr_in": [
          "141.98.255.96"
        ],
        "features": {
          "lwo": {}
        }
      },
      {
        "hostname": "se-mma-wg-012",
        "location": "se-mma",
        "active": true,
        "owned": true,
        "provider": "31173",
        "stboot": true,
        "ipv4_addr_in": "141.98.255.97",
        "include_in_country": true,
        "weight": 2,
        "public_key": "aPcHJj3I1oISU8cwLz2Uyq4ctUOXdTpuS96aW89snUs=",
        "ipv6_addr_in": "2a03:1b20:1:f410::f201",
        "shadowsocks_extra_addr_in": [
          "141.98.255.99"
        ],
        "features": {
          "lwo": {}
        }
      },
      {
        "hostname": "se-mma-wg-101",
        "location": "se-mma",
        "active": false,
        "owned": true,
        "provider": "31173",
        "stboot": true,
        "ipv4_addr_in": "45.83.220.68",
        "include_in_country": true,
        "weight": 200,
        "public_key": "7ncbaCb+9za3jnXlR95I6dJBkwL1ABB5i4ndFUesYxE=",
        "ipv6_addr_in": "2a03:1b20:1:e011::a21f",
        "shadowsocks_extra_addr_in": [
          "2a03:1b20:1:e011::b002",
          "2a03:1b20:1:e011::b003",
          "2a03:1b20:1:e011::b004",
          "2a03:1b20:1:e011::b005",
          "2a03:1b20:1:e011::b006",
          "2a03:1b20:1:e011::b007",
          "2a03:1b20:1:e011::b008",
          "2a03:1b20:1:e011::b009",
          "2a03:1b20:1:e011::b00a",
          "2a03:1b20:1:e011::b00b",
          "2a03:1b20:1:e011::b00c",
          "2a03:1b20:1:e011::b00d",
          "2a03:1b20:1:e011::b00e",
          "2a03:1b20:1:e011::b00f",
          "2a03:1b20:1:e011::b010",
          "2a03:1b20:1:e011::b011",
          "2a03:1b20:1:e011::b012",
          "2a03:1b20:1:e011::b013",
          "2a03:1b20:1:e011::b014",
          "2a03:1b20:1:e011::b015",
          "2a03:1b20:1:e011::b016",
          "2a03:1b20:1:e011::b017",
          "2a03:1b20:1:e011::b018",
          "2a03:1b20:1:e011::b019",
          "2a03:1b20:1:e011::b01a",
          "2a03:1b20:1:e011::b01b",
          "2a03:1b20:1:e011::b01c",
          "2a03:1b20:1:e011::b01d",
          "2a03:1b20:1:e011::b01e",
          "2a03:1b20:1:e011::b01f"
        ],
        "features": {
          "lwo": {}
        }
      },
      {
        "hostname": "se-mma-wg-102",
        "location": "se-mma",
        "active": true,
        "owned": true,
        "provider": "31173",
        "stboot": true,
        "ipv4_addr_in": "45.83.220.69",
        "include_in_country": true,
        "weight": 200,
        "public_key": "cwglRdgLQ4gMG36TIYlc5OIemLNrYs4UM1KTc8mnzxk=",
        "ipv6_addr_in": "2a03:1b20:1:e011::a22f",
        "shadowsocks_extra_addr_in": [
          "2a03:1b20:1:e011::b202",
          "2a03:1b20:1:e011::b203",
          "2a03:1b20:1:e011::b204",
          "2a03:1b20:1:e011::b205",
          "2a03:1b20:1:e011::b206",
          "2a03:1b20:1:e011::b207",
          "2a03:1b20:1:e011::b208",
          "2a03:1b20:1:e011::b209",
          "2a03:1b20:1:e011::b20a",
          "2a03:1b20:1:e011::b20b",
          "2a03:1b20:1:e011::b20c",
          "2a03:1b20:1:e011::b20d",
          "2a03:1b20:1:e011::b20e",
          "2a03:1b20:1:e011::b20f",
          "2a03:1b20:1:e011::b210",
          "2a03:1b20:1:e011::b211",
          "2a03:1b20:1:e011::b212",
          "2a03:1b20:1:e011::b213",
          "2a03:1b20:1:e011::b214",
          "2a03:1b20:1:e011::b215",
          "2a03:1b20:1:e011::b216",
          "2a03:1b20:1:e011::b217",
          "2a03:1b20:1:e011::b218",
          "2a03:1b20:1:e011::b219",
          "2a03:1b20:1:e011::b21a",
          "2a03:1b20:1:e011::b21b",
          "2a03:1b20:1:e011::b21c",
          "2a03:1b20:1:e011::b21d",
          "2a03:1b20:1:e011::b21e",
          "2a03:1b20:1:e011::b21f"
        ],
        "features": {
          "lwo": {}
        }
      },
      {
        "hostname": "se-mma-wg-103",
        "location": "se-mma",
        "active": true,
        "owned": true,
        "provider": "31173",
        "stboot": true,
        "ipv4_addr_in": "45.83.220.70",
        "include_in_country": true,
        "weight": 100,
        "public_key": "XscA5gebj51nmhAr6o+aUCnMHWGjbS1Gvvd0tuLRiFE=",
        "ipv6_addr_in": "2a03:1b20:1:e011::a23f",
        "shadowsocks_extra_addr_in": [
          "2a03:1b20:1:e011::b302",
          "2a03:1b20:1:e011::b303",
          "2a03:1b20:1:e011::b304",
          "2a03:1b20:1:e011::b305",
          "2a03:1b20:1:e011::b306",
          "2a03:1b20:1:e011::b307",
          "2a03:1b20:1:e011::b308",
          "2a03:1b20:1:e011::b309",
          "2a03:1b20:1:e011::b30a",
          "2a03:1b20:1:e011::b30b",
          "2a03:1b20:1:e011::b30c",
          "2a03:1b20:1:e011::b30d",
          "2a03:1b20:1:e011::b30e",
          "2a03:1b20:1:e011::b30f",
          "2a03:1b20:1:e011::b310",
          "2a03:1b20:1:e011::b311",
          "2a03:1b20:1:e011::b312",
          "2a03:1b20:1:e011::b313",
          "2a03:1b20:1:e011::b314",
          "2a03:1b20:1:e011::b315",
          "2a03:1b20:1:e011::b316",
          "2a03:1b20:1:e011::b317",
          "2a03:1b20:1:e011::b318",
          "2a03:1b20:1:e011::b319",
          "2a03:1b20:1:e011::b31a",
          "2a03:1b20:1:e011::b31b",
          "2a03:1b20:1:e011::b31c",
          "2a03:1b20:1:e011::b31d",
          "2a03:1b20:1:e011::b31e",
          "2a03:1b20:1:e011::b31f"
        ]
      },
      {
        "hostname": "se-mma-wg-111",
        "location": "se-mma",
        "active": true,
        "owned": true,
        "provider": "31173",
        "stboot": true,
        "ipv4_addr_in": "45.129.59.19",
        "include_in_country": true,
        "weight": 2,
        "public_key": "vi0PPk0ZCDvDMCSQD0mctmPFFH7NiawLxJquyPIGwAY=",
        "ipv6_addr_in": "2a03:1b20:1:e011::f701",
        "daita": true,
        "shadowsocks_extra_addr_in": [
          "45.129.59.29",
          "2a03:1b20:1:e011::b702",
          "2a03:1b20:1:e011::b703",
          "2a03:1b20:1:e011::b704",
          "2a03:1b20:1:e011::b705",
          "2a03:1b20:1:e011::b706",
          "2a03:1b20:1:e011::b707",
          "2a03:1b20:1:e011::b708",
          "2a03:1b20:1:e011::b709",
          "2a03:1b20:1:e011::b70a",
          "2a03:1b20:1:e011::b70b",
          "2a03:1b20:1:e011::b70c",
          "2a03:1b20:1:e011::b70d",
          "2a03:1b20:1:e011::b70e",
          "2a03:1b20:1:e011::b70f",
          "2a03:1b20:1:e011::b710",
          "2a03:1b20:1:e011::b711",
          "2a03:1b20:1:e011::b712",
          "2a03:1b20:1:e011::b713",
          "2a03:1b20:1:e011::b714",
          "2a03:1b20:1:e011::b715",
          "2a03:1b20:1:e011::b716",
          "2a03:1b20:1:e011::b717",
          "2a03:1b20:1:e011::b718",
          "2a03:1b20:1:e011::b719",
          "2a03:1b20:1:e011::b71a",
          "2a03:1b20:1:e011::b71b",
          "2a03:1b20:1:e011::b71c",
          "2a03:1b20:1:e011::b71d",
          "2a03:1b20:1:e011::b71e",
          "2a03:1b20:1:e011::b71f"
        ],
        "features": {
          "daita": {},
          "lwo": {},
          "quic": {
            "addr_in": [
              "45.129.59.25",
              "2a03:1b20:1:e011::c702",
              "2a03:1b20:1:e011::c703",
              "2a03:1b20:1:e011::c704",
              "2a03:1b20:1:e011::c705",
              "2a03:1b20:1:e011::c706",
              "2a03:1b20:1:e011::c707",
              "2a03:1b20:1:e011::c708",
              "2a03:1b20:1:e011::c709",
              "2a03:1b20:1:e011::c70a",
              "2a03:1b20:1:e011::c70b",
              "2a03:1b20:1:e011::c70c",
              "2a03:1b20:1:e011::c70d",
              "2a03:1b20:1:e011::c70e",
              "2a03:1b20:1:e011::c70f",
              "2a03:1b20:1:e011::c710",
              "2a03:1b20:1:e011::c711",
              "2a03:1b20:1:e011::c712",
              "2a03:1b20:1:e011::c713",
              "2a03:1b20:1:e011::c714",
              "2a03:1b20:1:e011::c715",
              "2a03:1b20:1:e011::c716",
              "2a03:1b20:1:e011::c717",
              "2a03:1b20:1:e011::c718",
              "2a03:1b20:1:e011::c719",
              "2a03:1b20:1:e011::c71a",
              "2a03:1b20:1:e011::c71b",
              "2a03:1b20:1:e011::c71c",
              "2a03:1b20:1:e011::c71d",
              "2a03:1b20:1:e011::c71e",
              "2a03:1b20:1:e011::c71f"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "se-mma-wg-111.blockerad.eu"
          }
        }
      },
      {
        "hostname": "se-mma-wg-112",
        "location": "se-mma",
        "active": true,
        "owned": true,
        "provider": "31173",
        "stboot": true,
        "ipv4_addr_in": "45.129.59.129",
        "include_in_country": true,
        "weight": 2,
        "public_key": "bysuFAwy+jwl5IePhY06/j7ByWDsAtU5pKPo44k4qEY=",
        "ipv6_addr_in": "2a03:1b20:1:e011::f601",
        "daita": true,
        "shadowsocks_extra_addr_in": [
          "45.129.59.139",
          "2a03:1b20:1:e011::b602",
          "2a03:1b20:1:e011::b603",
          "2a03:1b20:1:e011::b604",
          "2a03:1b20:1:e011::b605",
          "2a03:1b20:1:e011::b606",
          "2a03:1b20:1:e011::b607",
          "2a03:1b20:1:e011::b608",
          "2a03:1b20:1:e011::b609",
          "2a03:1b20:1:e011::b60a",
          "2a03:1b20:1:e011::b60b",
          "2a03:1b20:1:e011::b60c",
          "2a03:1b20:1:e011::b60d",
          "2a03:1b20:1:e011::b60e",
          "2a03:1b20:1:e011::b60f",
          "2a03:1b20:1:e011::b610",
          "2a03:1b20:1:e011::b611",
          "2a03:1b20:1:e011::b612",
          "2a03:1b20:1:e011::b613",
          "2a03:1b20:1:e011::b614",
          "2a03:1b20:1:e011::b615",
          "2a03:1b20:1:e011::b616",
          "2a03:1b20:1:e011::b617",
          "2a03:1b20:1:e011::b618",
          "2a03:1b20:1:e011::b619",
          "2a03:1b20:1:e011::b61a",
          "2a03:1b20:1:e011::b61b",
          "2a03:1b20:1:e011::b61c",
          "2a03:1b20:1:e011::b61d",
          "2a03:1b20:1:e011::b61e",
          "2a03:1b20:1:e011::b61f"
        ],
        "features": {
          "daita": {},
          "lwo": {},
          "quic": {
            "addr_in": [
              "45.129.59.135",
              "2a03:1b20:1:e011::c602",
              "2a03:1b20:1:e011::c603",
              "2a03:1b20:1:e011::c604",
              "2a03:1b20:1:e011::c605",
              "2a03:1b20:1:e011::c606",
              "2a03:1b20:1:e011::c607",
              "2a03:1b20:1:e011::c608",
              "2a03:1b20:1:e011::c609",
              "2a03:1b20:1:e011::c60a",
              "2a03:1b20:1:e011::c60b",
              "2a03:1b20:1:e011::c60c",
              "2a03:1b20:1:e011::c60d",
              "2a03:1b20:1:e011::c60e",
              "2a03:1b20:1:e011::c60f",
              "2a03:1b20:1:e011::c610",
              "2a03:1b20:1:e011::c611",
              "2a03:1b20:1:e011::c612",
              "2a03:1b20:1:e011::c613",
              "2a03:1b20:1:e011::c614",
              "2a03:1b20:1:e011::c615",
              "2a03:1b20:1:e011::c616",
              "2a03:1b20:1:e011::c617",
              "2a03:1b20:1:e011::c618",
              "2a03:1b20:1:e011::c619",
              "2a03:1b20:1:e011::c61a",
              "2a03:1b20:1:e011::c61b",
              "2a03:1b20:1:e011::c61c",
              "2a03:1b20:1:e011::c61d",
              "2a03:1b20:1:e011::c61e",
              "2a03:1b20:1:e011::c61f"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "se-mma-wg-112.blockerad.eu"
          }
        }
      },
      {
        "hostname": "se-sto-wg-001",
        "location": "se-sto",
        "active": true,
        "owned": true,
        "provider": "31173",
        "stboot": true,
        "ipv4_addr_in": "185.195.233.76",
        "include_in_country": true,
        "weight": 100,
        "public_key": "MkP/Jytkg51/Y/EostONjIN6YaFRpsAYiNKMX27/CAY=",
        "ipv6_addr_in": "2a03:1b20:4:f011::999f"
      },
      {
        "hostname": "se-sto-wg-002",
        "location": "se-sto",
        "active": true,
        "owned": true,
        "provider": "31173",
        "stboot": true,
        "ipv4_addr_in": "185.65.135.67",
        "include_in_country": true,
        "weight": 100,
        "public_key": "q2ZZPfumPaRVl4DJfzNdQF/GHfe6BYAzQ2GZZHb6rmI=",
        "ipv6_addr_in": "2a03:1b20:4:f011::a02f",
        "shadowsocks_extra_addr_in": [
          "2a03:1b20:4:f011::b102",
          "2a03:1b20:4:f011::b103",
          "2a03:1b20:4:f011::b104",
          "2a03:1b20:4:f011::b105",
          "2a03:1b20:4:f011::b106",
          "2a03:1b20:4:f011::b107",
          "2a03:1b20:4:f011::b108",
          "2a03:1b20:4:f011::b109",
          "2a03:1b20:4:f011::b10a",
          "2a03:1b20:4:f011::b10b",
          "2a03:1b20:4:f011::b10c",
          "2a03:1b20:4:f011::b10d",
          "2a03:1b20:4:f011::b10e",
          "2a03:1b20:4:f011::b10f",
          "2a03:1b20:4:f011::b110",
          "2a03:1b20:4:f011::b111",
          "2a03:1b20:4:f011::b112",
          "2a03:1b20:4:f011::b113",
          "2a03:1b20:4:f011::b114",
          "2a03:1b20:4:f011::b115",
          "2a03:1b20:4:f011::b116",
          "2a03:1b20:4:f011::b117",
          "2a03:1b20:4:f011::b118",
          "2a03:1b20:4:f011::b119",
          "2a03:1b20:4:f011::b11a",
          "2a03:1b20:4:f011::b11b",
          "2a03:1b20:4:f011::b11c",
          "2a03:1b20:4:f011::b11d",
          "2a03:1b20:4:f011::b11e",
          "2a03:1b20:4:f011::b11f"
        ],
        "features": {
          "lwo": {},
          "quic": {
            "addr_in": [
              "2a03:1b20:4:f011::c102",
              "2a03:1b20:4:f011::c103",
              "2a03:1b20:4:f011::c104",
              "2a03:1b20:4:f011::c105",
              "2a03:1b20:4:f011::c106",
              "2a03:1b20:4:f011::c107",
              "2a03:1b20:4:f011::c108",
              "2a03:1b20:4:f011::c109",
              "2a03:1b20:4:f011::c10a",
              "2a03:1b20:4:f011::c10b",
              "2a03:1b20:4:f011::c10c",
              "2a03:1b20:4:f011::c10d",
              "2a03:1b20:4:f011::c10e",
              "2a03:1b20:4:f011::c10f",
              "2a03:1b20:4:f011::c110",
              "2a03:1b20:4:f011::c111",
              "2a03:1b20:4:f011::c112",
              "2a03:1b20:4:f011::c113",
              "2a03:1b20:4:f011::c114",
              "2a03:1b20:4:f011::c115",
              "2a03:1b20:4:f011::c116",
              "2a03:1b20:4:f011::c117",
              "2a03:1b20:4:f011::c118",
              "2a03:1b20:4:f011::c119",
              "2a03:1b20:4:f011::c11a",
              "2a03:1b20:4:f011::c11b",
              "2a03:1b20:4:f011::c11c",
              "2a03:1b20:4:f011::c11d",
              "2a03:1b20:4:f011::c11e",
              "2a03:1b20:4:f011::c11f"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "se-sto-wg-002.blockerad.eu"
          }
        }
      },
      {
        "hostname": "se-sto-wg-003",
        "location": "se-sto",
        "active": true,
        "owned": true,
        "provider": "31173",
        "stboot": true,
        "ipv4_addr_in": "185.65.135.68",
        "include_in_country": true,
        "weight": 100,
        "public_key": "qZbwfoY4LHhDPzUROFbG+LqOjB0+Odwjg/Nv3kGolWc=",
        "ipv6_addr_in": "2a03:1b20:4:f011::f201",
        "features": {
          "lwo": {}
        }
      },
      {
        "hostname": "se-sto-wg-007",
        "location": "se-sto",
        "active": true,
        "owned": true,
        "provider": "31173",
        "stboot": true,
        "ipv4_addr_in": "185.65.135.70",
        "include_in_country": true,
        "weight": 100,
        "public_key": "YD4k8xaiw2kcRhfLRf2UiRNcDmvvu5NV0xT4d5xOFzU=",
        "ipv6_addr_in": "2a03:1b20:4:f011::b07f",
        "shadowsocks_extra_addr_in": [
          "2a03:1b20:4:f011::b602",
          "2a03:1b20:4:f011::b603",
          "2a03:1b20:4:f011::b604",
          "2a03:1b20:4:f011::b605",
          "2a03:1b20:4:f011::b606",
          "2a03:1b20:4:f011::b607",
          "2a03:1b20:4:f011::b608",
          "2a03:1b20:4:f011::b609",
          "2a03:1b20:4:f011::b60a",
          "2a03:1b20:4:f011::b60b",
          "2a03:1b20:4:f011::b60c",
          "2a03:1b20:4:f011::b60d",
          "2a03:1b20:4:f011::b60e",
          "2a03:1b20:4:f011::b60f",
          "2a03:1b20:4:f011::b610",
          "2a03:1b20:4:f011::b611",
          "2a03:1b20:4:f011::b612",
          "2a03:1b20:4:f011::b613",
          "2a03:1b20:4:f011::b614",
          "2a03:1b20:4:f011::b615",
          "2a03:1b20:4:f011::b616",
          "2a03:1b20:4:f011::b617",
          "2a03:1b20:4:f011::b618",
          "2a03:1b20:4:f011::b619",
          "2a03:1b20:4:f011::b61a",
          "2a03:1b20:4:f011::b61b",
          "2a03:1b20:4:f011::b61c",
          "2a03:1b20:4:f011::b61d",
          "2a03:1b20:4:f011::b61e",
          "2a03:1b20:4:f011::b61f"
        ],
        "features": {
          "lwo": {}
        }
      },
      {
        "hostname": "se-sto-wg-008",
        "location": "se-sto",
        "active": true,
        "owned": true,
        "provider": "31173",
        "stboot": true,
        "ipv4_addr_in": "185.65.135.71",
        "include_in_country": true,
        "weight": 100,
        "public_key": "4nOXEaCDYBV//nsVXk7MrnHpxLV9MbGjt+IGQY//p3k=",
        "ipv6_addr_in": "2a03:1b20:4:f011::f701"
      },
      {
        "hostname": "se-sto-wg-009",
        "location": "se-sto",
        "active": true,
        "owned": true,
        "provider": "31173",
        "stboot": true,
        "ipv4_addr_in": "185.195.233.69",
        "include_in_country": false,
        "weight": 1,
        "public_key": "t1XlQD7rER0JUPrmh3R5IpxjUP9YOqodJAwfRorNxl4=",
        "ipv6_addr_in": "2a03:1b20:4:f011::a09f",
        "daita": true,
        "shadowsocks_extra_addr_in": [
          "2a03:1b20:4:f011::b802",
          "2a03:1b20:4:f011::b803",
          "2a03:1b20:4:f011::b804",
          "2a03:1b20:4:f011::b805",
          "2a03:1b20:4:f011::b806",
          "2a03:1b20:4:f011::b807",
          "2a03:1b20:4:f011::b808",
          "2a03:1b20:4:f011::b809",
          "2a03:1b20:4:f011::b80a",
          "2a03:1b20:4:f011::b80b",
          "2a03:1b20:4:f011::b80c",
          "2a03:1b20:4:f011::b80d",
          "2a03:1b20:4:f011::b80e",
          "2a03:1b20:4:f011::b80f",
          "2a03:1b20:4:f011::b810",
          "2a03:1b20:4:f011::b811",
          "2a03:1b20:4:f011::b812",
          "2a03:1b20:4:f011::b813",
          "2a03:1b20:4:f011::b814",
          "2a03:1b20:4:f011::b815",
          "2a03:1b20:4:f011::b816",
          "2a03:1b20:4:f011::b817",
          "2a03:1b20:4:f011::b818",
          "2a03:1b20:4:f011::b819",
          "2a03:1b20:4:f011::b81a",
          "2a03:1b20:4:f011::b81b",
          "2a03:1b20:4:f011::b81c",
          "2a03:1b20:4:f011::b81d",
          "2a03:1b20:4:f011::b81e",
          "2a03:1b20:4:f011::b81f"
        ],
        "features": {
          "daita": {},
          "lwo": {},
          "quic": {
            "addr_in": [
              "185.195.233.172",
              "2a03:1b20:4:f011::c802",
              "2a03:1b20:4:f011::c803",
              "2a03:1b20:4:f011::c804",
              "2a03:1b20:4:f011::c805",
              "2a03:1b20:4:f011::c806",
              "2a03:1b20:4:f011::c807",
              "2a03:1b20:4:f011::c808",
              "2a03:1b20:4:f011::c809",
              "2a03:1b20:4:f011::c80a",
              "2a03:1b20:4:f011::c80b",
              "2a03:1b20:4:f011::c80c",
              "2a03:1b20:4:f011::c80d",
              "2a03:1b20:4:f011::c80e",
              "2a03:1b20:4:f011::c80f",
              "2a03:1b20:4:f011::c810",
              "2a03:1b20:4:f011::c811",
              "2a03:1b20:4:f011::c812",
              "2a03:1b20:4:f011::c813",
              "2a03:1b20:4:f011::c814",
              "2a03:1b20:4:f011::c815",
              "2a03:1b20:4:f011::c816",
              "2a03:1b20:4:f011::c817",
              "2a03:1b20:4:f011::c818",
              "2a03:1b20:4:f011::c819",
              "2a03:1b20:4:f011::c81a",
              "2a03:1b20:4:f011::c81b",
              "2a03:1b20:4:f011::c81c",
              "2a03:1b20:4:f011::c81d",
              "2a03:1b20:4:f011::c81e",
              "2a03:1b20:4:f011::c81f"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "se-sto-wg-009.blockerad.eu"
          }
        }
      },
      {
        "hostname": "se-sto-wg-010",
        "location": "se-sto",
        "active": true,
        "owned": true,
        "provider": "31173",
        "stboot": true,
        "ipv4_addr_in": "185.195.233.70",
        "include_in_country": true,
        "weight": 1,
        "public_key": "pWhNidLbYca9j66c7iw/3kgtU+UyFRIgc75xy8riqzg=",
        "ipv6_addr_in": "2a03:1b20:4:f011::a10f",
        "shadowsocks_extra_addr_in": [
          "2a03:1b20:4:f011::b902",
          "2a03:1b20:4:f011::b903",
          "2a03:1b20:4:f011::b904",
          "2a03:1b20:4:f011::b905",
          "2a03:1b20:4:f011::b906",
          "2a03:1b20:4:f011::b907",
          "2a03:1b20:4:f011::b908",
          "2a03:1b20:4:f011::b909",
          "2a03:1b20:4:f011::b90a",
          "2a03:1b20:4:f011::b90b",
          "2a03:1b20:4:f011::b90c",
          "2a03:1b20:4:f011::b90d",
          "2a03:1b20:4:f011::b90e",
          "2a03:1b20:4:f011::b90f",
          "2a03:1b20:4:f011::b910",
          "2a03:1b20:4:f011::b911",
          "2a03:1b20:4:f011::b912",
          "2a03:1b20:4:f011::b913",
          "2a03:1b20:4:f011::b914",
          "2a03:1b20:4:f011::b915",
          "2a03:1b20:4:f011::b916",
          "2a03:1b20:4:f011::b917",
          "2a03:1b20:4:f011::b918",
          "2a03:1b20:4:f011::b919",
          "2a03:1b20:4:f011::b91a",
          "2a03:1b20:4:f011::b91b",
          "2a03:1b20:4:f011::b91c",
          "2a03:1b20:4:f011::b91d",
          "2a03:1b20:4:f011::b91e",
          "2a03:1b20:4:f011::b91f"
        ],
        "features": {
          "lwo": {}
        }
      },
      {
        "hostname": "se-sto-wg-011",
        "location": "se-sto",
        "active": true,
        "owned": true,
        "provider": "31173",
        "stboot": true,
        "ipv4_addr_in": "185.195.233.71",
        "include_in_country": true,
        "weight": 100,
        "public_key": "GqKpm8VwKJQLQEQ0PXbkRueY9hDqiMibr+EpW3n9syk=",
        "ipv6_addr_in": "2a03:1b20:4:f011::a11f",
        "shadowsocks_extra_addr_in": [
          "2a03:1b20:4:f011::ba02",
          "2a03:1b20:4:f011::ba03",
          "2a03:1b20:4:f011::ba04",
          "2a03:1b20:4:f011::ba05",
          "2a03:1b20:4:f011::ba06",
          "2a03:1b20:4:f011::ba07",
          "2a03:1b20:4:f011::ba08",
          "2a03:1b20:4:f011::ba09",
          "2a03:1b20:4:f011::ba0a",
          "2a03:1b20:4:f011::ba0b",
          "2a03:1b20:4:f011::ba0c",
          "2a03:1b20:4:f011::ba0d",
          "2a03:1b20:4:f011::ba0e",
          "2a03:1b20:4:f011::ba0f",
          "2a03:1b20:4:f011::ba10",
          "2a03:1b20:4:f011::ba11",
          "2a03:1b20:4:f011::ba12",
          "2a03:1b20:4:f011::ba13",
          "2a03:1b20:4:f011::ba14",
          "2a03:1b20:4:f011::ba15",
          "2a03:1b20:4:f011::ba16",
          "2a03:1b20:4:f011::ba17",
          "2a03:1b20:4:f011::ba18",
          "2a03:1b20:4:f011::ba19",
          "2a03:1b20:4:f011::ba1a",
          "2a03:1b20:4:f011::ba1b",
          "2a03:1b20:4:f011::ba1c",
          "2a03:1b20:4:f011::ba1d",
          "2a03:1b20:4:f011::ba1e",
          "2a03:1b20:4:f011::ba1f"
        ],
        "features": {
          "lwo": {}
        }
      },
      {
        "hostname": "se-sto-wg-012",
        "location": "se-sto",
        "active": true,
        "owned": true,
        "provider": "31173",
        "stboot": true,
        "ipv4_addr_in": "185.195.233.66",
        "include_in_country": true,
        "weight": 100,
        "public_key": "1493vtFUbIfSpQKRBki/1d0YgWIQwMV4AQAvGxjCNVM=",
        "ipv6_addr_in": "2a03:1b20:4:f011::fb01",
        "features": {
          "lwo": {}
        }
      },
      {
        "hostname": "se-sto-wg-013",
        "location": "se-sto",
        "active": true,
        "owned": true,
        "provider": "31173",
        "stboot": true,
        "ipv4_addr_in": "185.195.233.67",
        "include_in_country": true,
        "weight": 100,
        "public_key": "u3pZZjXm0NHCNqPIhKlZ7Vy6CQm5G9YpfgvaywurTho=",
        "ipv6_addr_in": "2a03:1b20:4:f011::fe01",
        "features": {
          "lwo": {}
        }
      },
      {
        "hostname": "se-sto-wg-014",
        "location": "se-sto",
        "active": true,
        "owned": true,
        "provider": "31173",
        "stboot": true,
        "ipv4_addr_in": "185.195.233.68",
        "include_in_country": true,
        "weight": 100,
        "public_key": "DYlwUsH63DLjEfKC9yq7P+FoQx99WdKvZGGhXoUZVgk=",
        "ipv6_addr_in": "2a03:1b20:4:f011::fd01"
      },
      {
        "hostname": "se-sto-wg-201",
        "location": "se-sto",
        "active": true,
        "owned": true,
        "provider": "DataPacket",
        "stboot": true,
        "ipv4_addr_in": "89.37.63.10",
        "include_in_country": true,
        "weight": 300,
        "public_key": "V5RUvv8xp3xYc9b/KoGjTL6EUEb2mTv+8egxuEvUAnc=",
        "ipv6_addr_in": "2a02:6ea0:1508:1::f001",
        "shadowsocks_extra_addr_in": [
          "89.37.63.16"
        ],
        "features": {
          "lwo": {},
          "quic": {
            "addr_in": [
              "89.37.63.15",
              "2a02:6ea0:1508:1::f009"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "se-sto-wg-201.blockerad.eu"
          }
        }
      },
      {
        "hostname": "se-sto-wg-202",
        "location": "se-sto",
        "active": true,
        "owned": true,
        "provider": "DataPacket",
        "stboot": true,
        "ipv4_addr_in": "89.37.63.66",
        "include_in_country": true,
        "weight": 300,
        "public_key": "S4fVJ6wjUxrRQsDZwWvKVLtcNBJgoSshkqy3wXWG0UM=",
        "ipv6_addr_in": "2a02:6ea0:1508:2::f001",
        "shadowsocks_extra_addr_in": [
          "89.37.63.72"
        ],
        "features": {
          "lwo": {},
          "quic": {
            "addr_in": [
              "89.37.63.71",
              "2a02:6ea0:1508:2::f009"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "se-sto-wg-202.blockerad.eu"
          }
        }
      },
      {
        "hostname": "se-sto-wg-203",
        "location": "se-sto",
        "active": true,
        "owned": true,
        "provider": "DataPacket",
        "stboot": true,
        "ipv4_addr_in": "89.37.63.129",
        "include_in_country": true,
        "weight": 300,
        "public_key": "mkBf9JhtMPHS3w0FfJOwSS5kfmUQ0RGSLXBdxUNlzTs=",
        "ipv6_addr_in": "2a02:6ea0:1508:3::f001",
        "shadowsocks_extra_addr_in": [
          "89.37.63.135"
        ],
        "features": {
          "lwo": {},
          "quic": {
            "addr_in": [
              "89.37.63.134",
              "2a02:6ea0:1508:3::f009"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "se-sto-wg-203.blockerad.eu"
          }
        }
      },
      {
        "hostname": "se-sto-wg-204",
        "location": "se-sto",
        "active": true,
        "owned": true,
        "provider": "DataPacket",
        "stboot": true,
        "ipv4_addr_in": "89.37.63.190",
        "include_in_country": true,
        "weight": 300,
        "public_key": "cPhM7ShRWQmKiJtD9Wd1vDh0GwIlaMvFb/WPrP58FH8=",
        "ipv6_addr_in": "2a02:6ea0:1508:4::f001",
        "shadowsocks_extra_addr_in": [
          "89.37.63.196"
        ],
        "features": {
          "lwo": {},
          "quic": {
            "addr_in": [
              "89.37.63.195",
              "2a02:6ea0:1508:4::c101"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "se-sto-wg-204.blockerad.eu"
          }
        }
      },
      {
        "hostname": "se-sto-wg-205",
        "location": "se-sto",
        "active": true,
        "owned": true,
        "provider": "DataPacket",
        "stboot": true,
        "ipv4_addr_in": "170.62.100.10",
        "include_in_country": true,
        "weight": 300,
        "public_key": "9V4G5BERZI4xHudcIf5wdDG77XZSY08lVEiXrAGXuEE=",
        "ipv6_addr_in": "2a02:6ea0:1508:5::f001",
        "daita": true,
        "shadowsocks_extra_addr_in": [
          "170.62.100.16"
        ],
        "features": {
          "daita": {},
          "lwo": {},
          "quic": {
            "addr_in": [
              "170.62.100.15"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "se-sto-wg-205.blockerad.eu"
          }
        }
      },
      {
        "hostname": "se-sto-wg-206",
        "location": "se-sto",
        "active": true,
        "owned": true,
        "provider": "DataPacket",
        "stboot": true,
        "ipv4_addr_in": "170.62.100.66",
        "include_in_country": true,
        "weight": 300,
        "public_key": "9KHMuwHqa1Mx2VrKX3cvqLN/ZPDjH5/z0q+IWbfrmW8=",
        "ipv6_addr_in": "2a02:6ea0:1508:6::f001",
        "daita": true,
        "shadowsocks_extra_addr_in": [
          "170.62.100.72"
        ],
        "features": {
          "daita": {},
          "lwo": {},
          "quic": {
            "addr_in": [
              "170.62.100.71"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "se-sto-wg-206.blockerad.eu"
          }
        }
      },
      {
        "hostname": "se-sto-wg-207",
        "location": "se-sto",
        "active": true,
        "owned": true,
        "provider": "DataPacket",
        "stboot": true,
        "ipv4_addr_in": "170.62.100.129",
        "include_in_country": true,
        "weight": 300,
        "public_key": "OatHF/w6fOg8w2415s8zPSXw6LtcYOm+90pqyJ5ZsVY=",
        "ipv6_addr_in": "2a02:6ea0:1508:7::f001",
        "daita": true,
        "shadowsocks_extra_addr_in": [
          "170.62.100.135"
        ],
        "features": {
          "daita": {},
          "lwo": {},
          "quic": {
            "addr_in": [
              "170.62.100.134"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "se-sto-wg-207.blockerad.eu"
          }
        }
      },
      {
        "hostname": "se-sto-wg-208",
        "location": "se-sto",
        "active": true,
        "owned": true,
        "provider": "DataPacket",
        "stboot": true,
        "ipv4_addr_in": "170.62.100.170",
        "include_in_country": true,
        "weight": 300,
        "public_key": "HozGhf1OfjFEASBzjmktB9AKkIgbC+OhSabZKwT6EHc=",
        "ipv6_addr_in": "2a02:6ea0:1508:8::f001",
        "daita": true,
        "shadowsocks_extra_addr_in": [
          "170.62.100.176"
        ],
        "features": {
          "daita": {},
          "lwo": {},
          "quic": {
            "addr_in": [
              "170.62.100.175"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "se-sto-wg-208.blockerad.eu"
          }
        }
      },
      {
        "hostname": "se-sto-wg-209",
        "location": "se-sto",
        "active": true,
        "owned": true,
        "provider": "DataPacket",
        "stboot": true,
        "ipv4_addr_in": "170.62.100.211",
        "include_in_country": true,
        "weight": 300,
        "public_key": "r3360zyxOKxUthx90sfRkLZBt1Q5alk45/H9Dkq5kFM=",
        "ipv6_addr_in": "2a02:6ea0:1508:9::f001",
        "daita": true,
        "shadowsocks_extra_addr_in": [
          "170.62.100.217"
        ],
        "features": {
          "daita": {},
          "lwo": {},
          "quic": {
            "addr_in": [
              "170.62.100.216"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "se-sto-wg-209.blockerad.eu"
          }
        }
      },
      {
        "hostname": "sg-sin-wg-001",
        "location": "sg-sin",
        "active": true,
        "owned": false,
        "provider": "DataPacket",
        "stboot": true,
        "ipv4_addr_in": "138.199.60.2",
        "include_in_country": true,
        "weight": 100,
        "public_key": "sFHv/qzG7b6ds5pow+oAR3G5Wqp9eFbBD3BmEGBuUWU=",
        "ipv6_addr_in": "2a02:6ea0:d13e:1::a09f",
        "daita": true,
        "features": {
          "daita": {}
        }
      },
      {
        "hostname": "sg-sin-wg-002",
        "location": "sg-sin",
        "active": true,
        "owned": false,
        "provider": "DataPacket",
        "stboot": true,
        "ipv4_addr_in": "138.199.60.15",
        "include_in_country": true,
        "weight": 100,
        "public_key": "WM5I4IFwQcVysM4fF4NXZtQXNrSkqVWkQxNPPygOiF0=",
        "ipv6_addr_in": "2a02:6ea0:d13e:2::a10f",
        "daita": true,
        "features": {
          "daita": {}
        }
      },
      {
        "hostname": "sg-sin-wg-003",
        "location": "sg-sin",
        "active": true,
        "owned": false,
        "provider": "DataPacket",
        "stboot": true,
        "ipv4_addr_in": "138.199.60.28",
        "include_in_country": true,
        "weight": 100,
        "public_key": "3HtGdhEXUPKQIDRW49wCUoTK2ZXfq+QfzjfYoldNchg=",
        "ipv6_addr_in": "2a02:6ea0:d13e:3::a11f",
        "features": {
          "lwo": {}
        }
      },
      {
        "hostname": "sg-sin-wg-101",
        "location": "sg-sin",
        "active": true,
        "owned": false,
        "provider": "M247",
        "stboot": true,
        "ipv4_addr_in": "146.70.199.194",
        "include_in_country": true,
        "weight": 100,
        "public_key": "KB6ZA1PAixd74c+mO0VBY4j7LaitK8B4L1APbFIQyQ0=",
        "ipv6_addr_in": "2a0d:5600:d:44::a01f"
      },
      {
        "hostname": "sg-sin-wg-102",
        "location": "sg-sin",
        "active": true,
        "owned": false,
        "provider": "M247",
        "stboot": true,
        "ipv4_addr_in": "146.70.199.130",
        "include_in_country": true,
        "weight": 100,
        "public_key": "qrhHOwk0ree+LFxW6htvGEfVFuhM2efQ/M+4p0sx/gA=",
        "ipv6_addr_in": "2a0d:5600:d:43::a02f"
      },
      {
        "hostname": "si-lju-wg-001",
        "location": "si-lju",
        "active": true,
        "owned": false,
        "provider": "HostRoyale",
        "stboot": true,
        "ipv4_addr_in": "93.115.0.3",
        "include_in_country": true,
        "weight": 100,
        "public_key": "fXWKnogYH3IORGePtkyFg3r/56ZQGkF6hjdw2svhmw8=",
        "ipv6_addr_in": "2a06:3040:7:210::f001"
      },
      {
        "hostname": "si-lju-wg-002",
        "location": "si-lju",
        "active": true,
        "owned": false,
        "provider": "HostRoyale",
        "stboot": true,
        "ipv4_addr_in": "93.115.0.33",
        "include_in_country": true,
        "weight": 100,
        "public_key": "HkPoWKRG/KV2C8afaaah9Jl5lYuvJo1loCaFadKDZVU=",
        "ipv6_addr_in": "2a06:3040:7:210::f101"
      },
      {
        "hostname": "sk-bts-wg-001",
        "location": "sk-bts",
        "active": true,
        "owned": false,
        "provider": "DataPacket",
        "stboot": true,
        "ipv4_addr_in": "138.199.34.129",
        "include_in_country": true,
        "weight": 100,
        "public_key": "QEVIaIycN8p5twXCuZeQTEj9utozakw/MU8H6+/whls=",
        "ipv6_addr_in": "2a02:6ea0:2901:1::f001"
      },
      {
        "hostname": "sk-bts-wg-002",
        "location": "sk-bts",
        "active": true,
        "owned": false,
        "provider": "DataPacket",
        "stboot": true,
        "ipv4_addr_in": "138.199.34.143",
        "include_in_country": true,
        "weight": 100,
        "public_key": "JeEuObwimNmoVtPn4kpMI1y1UM+IChGVBLtmP3CNNVQ=",
        "ipv6_addr_in": "2a02:6ea0:2901::a02f"
      },
      {
        "hostname": "th-bkk-wg-001",
        "location": "th-bkk",
        "active": true,
        "owned": false,
        "provider": "Zenlayer",
        "stboot": true,
        "ipv4_addr_in": "156.59.50.194",
        "include_in_country": true,
        "weight": 100,
        "public_key": "zX6pm3TVJe7rjQ9GrFH1IY29vw/PJL6LGh3/ALxEyx4=",
        "ipv6_addr_in": "2602:ffe4:c09:10a::f001",
        "features": {
          "lwo": {}
        }
      },
      {
        "hostname": "th-bkk-wg-002",
        "location": "th-bkk",
        "active": true,
        "owned": false,
        "provider": "Zenlayer",
        "stboot": true,
        "ipv4_addr_in": "156.59.50.226",
        "include_in_country": true,
        "weight": 100,
        "public_key": "L8CCv3NWDaMyUh4dxO44LSy07ETWCcWBeeGFyQZIlyo=",
        "ipv6_addr_in": "2602:ffe4:c09:109::f101"
      },
      {
        "hostname": "tr-ist-wg-001",
        "location": "tr-ist",
        "active": true,
        "owned": false,
        "provider": "DataPacket",
        "stboot": true,
        "ipv4_addr_in": "149.102.229.129",
        "include_in_country": true,
        "weight": 100,
        "public_key": "jPhK/ziQfJ1Z5GCPj+qR3A7YV2mIQSQtEPCRuG7TUW8=",
        "ipv6_addr_in": "2a02:6ea0:e813::f001",
        "shadowsocks_extra_addr_in": [
          "149.102.229.131"
        ]
      },
      {
        "hostname": "tr-ist-wg-002",
        "location": "tr-ist",
        "active": true,
        "owned": false,
        "provider": "DataPacket",
        "stboot": true,
        "ipv4_addr_in": "149.102.229.158",
        "include_in_country": true,
        "weight": 100,
        "public_key": "TDHn9OvFYoHh9nwlYG7OCpPRvCjfODUOksSQPzhguTg=",
        "ipv6_addr_in": "2a02:6ea0:e813:1::f001",
        "shadowsocks_extra_addr_in": [
          "149.102.229.160"
        ]
      },
      {
        "hostname": "ua-iev-wg-001",
        "location": "ua-iev",
        "active": true,
        "owned": false,
        "provider": "DataPacket",
        "stboot": true,
        "ipv4_addr_in": "149.102.240.79",
        "include_in_country": true,
        "weight": 100,
        "public_key": "PO2o3ewguPP24wLy8bbDqx1xuAnTOIVzdzVGVT0d8kU=",
        "ipv6_addr_in": "2a02:6ea0:e109:2::a01f"
      },
      {
        "hostname": "ua-iev-wg-002",
        "location": "ua-iev",
        "active": true,
        "owned": false,
        "provider": "DataPacket",
        "stboot": true,
        "ipv4_addr_in": "149.102.240.66",
        "include_in_country": true,
        "weight": 100,
        "public_key": "HUj/J8Rxx7QVGh3kJsFgPZoqtm2BQIX03vKJSIyTOSo=",
        "ipv6_addr_in": "2a02:6ea0:e109:1::a02f"
      },
      {
        "hostname": "us-atl-wg-001",
        "location": "us-atl",
        "active": true,
        "owned": false,
        "provider": "DataPacket",
        "stboot": true,
        "ipv4_addr_in": "45.134.140.130",
        "include_in_country": false,
        "weight": 100,
        "public_key": "nvyBkaEXHwyPBAm8spGB0TFzf2W5wPAl8EEuJ0t+bzs=",
        "ipv6_addr_in": "2a02:6ea0:c122:1::b79f",
        "features": {
          "lwo": {},
          "quic": {
            "addr_in": [
              "45.134.140.142"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "us-atl-wg-001.blockerad.eu"
          }
        }
      },
      {
        "hostname": "us-atl-wg-002",
        "location": "us-atl",
        "active": true,
        "owned": false,
        "provider": "DataPacket",
        "stboot": true,
        "ipv4_addr_in": "45.134.140.143",
        "include_in_country": false,
        "weight": 100,
        "public_key": "ECeGYeh8CfPJO3v56ucCDdl+PlKcj2bBszUGkT+hVWQ=",
        "ipv6_addr_in": "2a02:6ea0:c122:2::b80f"
      },
      {
        "hostname": "us-atl-wg-401",
        "location": "us-atl",
        "active": true,
        "owned": false,
        "provider": "Tzulo",
        "stboot": true,
        "ipv4_addr_in": "23.234.108.3",
        "include_in_country": true,
        "weight": 100,
        "public_key": "49LoowbQpQfc/Yw+1DZ0A/Gien3wRnxwJzvo7Gz8Zhw=",
        "ipv6_addr_in": "2607:9000:c00:31::f001",
        "shadowsocks_extra_addr_in": [
          "23.234.108.14"
        ]
      },
      {
        "hostname": "us-atl-wg-402",
        "location": "us-atl",
        "active": true,
        "owned": false,
        "provider": "Tzulo",
        "stboot": true,
        "ipv4_addr_in": "23.234.108.127",
        "include_in_country": true,
        "weight": 100,
        "public_key": "9CYtFK8cSKxzEiFYpiCuKgYnjMO5Jqri2iFiG2lDUlM=",
        "ipv6_addr_in": "2607:9000:c00:32::f001",
        "shadowsocks_extra_addr_in": [
          "23.234.108.139"
        ],
        "features": {
          "lwo": {}
        }
      },
      {
        "hostname": "us-atl-wg-403",
        "location": "us-atl",
        "active": true,
        "owned": false,
        "provider": "Tzulo",
        "stboot": true,
        "ipv4_addr_in": "23.234.109.3",
        "include_in_country": true,
        "weight": 100,
        "public_key": "a64LFZfr0htAq1mk5EvVPmQPi52oboISpVUHaYKGE1E=",
        "ipv6_addr_in": "2607:9000:c00:33::f001",
        "shadowsocks_extra_addr_in": [
          "23.234.109.14"
        ]
      },
      {
        "hostname": "us-atl-wg-404",
        "location": "us-atl",
        "active": true,
        "owned": false,
        "provider": "Tzulo",
        "stboot": true,
        "ipv4_addr_in": "23.234.109.127",
        "include_in_country": true,
        "weight": 100,
        "public_key": "kYm0GM0/fD37iCZM3+60vAxRV1w/PUW+WQkYV14QZFo=",
        "ipv6_addr_in": "2607:9000:c00:34::f001",
        "shadowsocks_extra_addr_in": [
          "23.234.109.139"
        ]
      },
      {
        "hostname": "us-atl-wg-405",
        "location": "us-atl",
        "active": true,
        "owned": false,
        "provider": "Tzulo",
        "stboot": true,
        "ipv4_addr_in": "23.234.110.3",
        "include_in_country": true,
        "weight": 100,
        "public_key": "643HR3VhN/WVydahUwuKL/e8jT8UNDHduBfDPMF/2E8=",
        "ipv6_addr_in": "2607:9000:c00:35::f001",
        "shadowsocks_extra_addr_in": [
          "23.234.110.14"
        ]
      },
      {
        "hostname": "us-atl-wg-406",
        "location": "us-atl",
        "active": true,
        "owned": false,
        "provider": "Tzulo",
        "stboot": true,
        "ipv4_addr_in": "23.234.110.127",
        "include_in_country": true,
        "weight": 100,
        "public_key": "spmw1nZv6lgKC/T1KMSuLKyAfCifmrxCdXvVPNhQFCY=",
        "ipv6_addr_in": "2607:9000:c00:36::f001",
        "shadowsocks_extra_addr_in": [
          "23.234.110.139"
        ],
        "features": {
          "lwo": {}
        }
      },
      {
        "hostname": "us-atl-wg-407",
        "location": "us-atl",
        "active": true,
        "owned": false,
        "provider": "Tzulo",
        "stboot": true,
        "ipv4_addr_in": "23.234.111.3",
        "include_in_country": true,
        "weight": 100,
        "public_key": "e2UcVruvaIHcCXYjaHe6alKbZW/Qc9lbYzYh1AckWEU=",
        "ipv6_addr_in": "2607:9000:c00:37::f001",
        "shadowsocks_extra_addr_in": [
          "23.234.111.14"
        ],
        "features": {
          "lwo": {}
        }
      },
      {
        "hostname": "us-atl-wg-408",
        "location": "us-atl",
        "active": true,
        "owned": false,
        "provider": "Tzulo",
        "stboot": true,
        "ipv4_addr_in": "23.234.111.127",
        "include_in_country": true,
        "weight": 100,
        "public_key": "x3sKDqtdNIUhOjCiZCzMSZmoMps20J0JloSQMebYK2o=",
        "ipv6_addr_in": "2607:9000:c00:38::f001",
        "shadowsocks_extra_addr_in": [
          "23.234.111.139"
        ],
        "features": {
          "lwo": {}
        }
      },
      {
        "hostname": "us-bos-wg-001",
        "location": "us-bos",
        "active": true,
        "owned": false,
        "provider": "HostRoyale",
        "stboot": true,
        "ipv4_addr_in": "43.225.189.131",
        "include_in_country": true,
        "weight": 100,
        "public_key": "CsysTnZ0HvyYRjsKMPx60JIgy777JhD0h9WpbHbV83o=",
        "ipv6_addr_in": "2a06:3040:12:610::a01f",
        "shadowsocks_extra_addr_in": [
          "2a06:3040:12:610::b002",
          "2a06:3040:12:610::b003",
          "2a06:3040:12:610::b004",
          "2a06:3040:12:610::b005",
          "2a06:3040:12:610::b006",
          "2a06:3040:12:610::b007",
          "2a06:3040:12:610::b008",
          "2a06:3040:12:610::b009",
          "2a06:3040:12:610::b00a",
          "2a06:3040:12:610::b00b",
          "2a06:3040:12:610::b00c",
          "2a06:3040:12:610::b00d",
          "2a06:3040:12:610::b00e",
          "2a06:3040:12:610::b00f",
          "2a06:3040:12:610::b010",
          "2a06:3040:12:610::b011",
          "2a06:3040:12:610::b012",
          "2a06:3040:12:610::b013",
          "2a06:3040:12:610::b014",
          "2a06:3040:12:610::b015",
          "2a06:3040:12:610::b016",
          "2a06:3040:12:610::b017",
          "2a06:3040:12:610::b018",
          "2a06:3040:12:610::b019",
          "2a06:3040:12:610::b01a",
          "2a06:3040:12:610::b01b",
          "2a06:3040:12:610::b01c",
          "2a06:3040:12:610::b01d",
          "2a06:3040:12:610::b01e",
          "2a06:3040:12:610::b01f"
        ]
      },
      {
        "hostname": "us-bos-wg-002",
        "location": "us-bos",
        "active": false,
        "owned": false,
        "provider": "HostRoyale",
        "stboot": true,
        "ipv4_addr_in": "43.225.189.162",
        "include_in_country": true,
        "weight": 100,
        "public_key": "LLkA2XSBvfUeXgLdMKP+OTQeKhtGB03kKskJEwlzAE8=",
        "ipv6_addr_in": "2a06:3040:12:610::a02f",
        "shadowsocks_extra_addr_in": [
          "2a06:3040:12:610::b102",
          "2a06:3040:12:610::b103",
          "2a06:3040:12:610::b104",
          "2a06:3040:12:610::b105",
          "2a06:3040:12:610::b106",
          "2a06:3040:12:610::b107",
          "2a06:3040:12:610::b108",
          "2a06:3040:12:610::b109",
          "2a06:3040:12:610::b10a",
          "2a06:3040:12:610::b10b",
          "2a06:3040:12:610::b10c",
          "2a06:3040:12:610::b10d",
          "2a06:3040:12:610::b10e",
          "2a06:3040:12:610::b10f",
          "2a06:3040:12:610::b110",
          "2a06:3040:12:610::b111",
          "2a06:3040:12:610::b112",
          "2a06:3040:12:610::b113",
          "2a06:3040:12:610::b114",
          "2a06:3040:12:610::b115",
          "2a06:3040:12:610::b116",
          "2a06:3040:12:610::b117",
          "2a06:3040:12:610::b118",
          "2a06:3040:12:610::b119",
          "2a06:3040:12:610::b11a",
          "2a06:3040:12:610::b11b",
          "2a06:3040:12:610::b11c",
          "2a06:3040:12:610::b11d",
          "2a06:3040:12:610::b11e",
          "2a06:3040:12:610::b11f"
        ]
      },
      {
        "hostname": "us-bos-wg-101",
        "location": "us-bos",
        "active": true,
        "owned": false,
        "provider": "DataPacket",
        "stboot": true,
        "ipv4_addr_in": "149.40.50.98",
        "include_in_country": true,
        "weight": 100,
        "public_key": "oxJ2PIqrQOmS0uiyXvnxT64E1uZnjZDWPbP/+APToAE=",
        "ipv6_addr_in": "2a02:6ea0:f901::a01f"
      },
      {
        "hostname": "us-bos-wg-102",
        "location": "us-bos",
        "active": true,
        "owned": false,
        "provider": "DataPacket",
        "stboot": true,
        "ipv4_addr_in": "149.40.50.112",
        "include_in_country": true,
        "weight": 100,
        "public_key": "wcmmadJObux2/62ES+QbIO21BkU7p2I0s6n4WNZZgW0=",
        "ipv6_addr_in": "2a02:6ea0:f901:1::a02f",
        "features": {
          "lwo": {}
        }
      },
      {
        "hostname": "us-chi-wg-201",
        "location": "us-chi",
        "active": true,
        "owned": false,
        "provider": "DataPacket",
        "stboot": true,
        "ipv4_addr_in": "87.249.134.1",
        "include_in_country": true,
        "weight": 1,
        "public_key": "+Xx2mJnoJ+JS11Z6g8mp6aUZV7p6DAN9ZTAzPaHakhM=",
        "ipv6_addr_in": "2a02:6ea0:c61f::b63f",
        "daita": true,
        "features": {
          "daita": {}
        }
      },
      {
        "hostname": "us-chi-wg-202",
        "location": "us-chi",
        "active": true,
        "owned": false,
        "provider": "DataPacket",
        "stboot": true,
        "ipv4_addr_in": "87.249.134.14",
        "include_in_country": true,
        "weight": 100,
        "public_key": "rmN4IM0I0gF7V9503/xnQMOLsu9txl8GTqci9dgUO18=",
        "ipv6_addr_in": "2a02:6ea0:c61f:1::b64f",
        "features": {
          "lwo": {}
        }
      },
      {
        "hostname": "us-chi-wg-203",
        "location": "us-chi",
        "active": true,
        "owned": false,
        "provider": "DataPacket",
        "stboot": true,
        "ipv4_addr_in": "87.249.134.27",
        "include_in_country": true,
        "weight": 100,
        "public_key": "V0ilKm3bVqt0rmJ80sP0zSVK4m6O3nADi88IQAL5kjw=",
        "ipv6_addr_in": "2a02:6ea0:c61f:2::f001",
        "features": {
          "lwo": {}
        }
      },
      {
        "hostname": "us-chi-wg-301",
        "location": "us-chi",
        "active": true,
        "owned": false,
        "provider": "Tzulo",
        "stboot": true,
        "ipv4_addr_in": "68.235.46.2",
        "include_in_country": true,
        "weight": 200,
        "public_key": "g9Dlad9R9OcM9w1yu3gq9pQWARQBc3Muj4KfeRY1p20=",
        "ipv6_addr_in": "2607:9000:0:101::f001",
        "daita": true,
        "shadowsocks_extra_addr_in": [
          "68.235.46.4"
        ],
        "features": {
          "daita": {}
        }
      },
      {
        "hostname": "us-chi-wg-302",
        "location": "us-chi",
        "active": true,
        "owned": false,
        "provider": "Tzulo",
        "stboot": true,
        "ipv4_addr_in": "68.235.46.33",
        "include_in_country": true,
        "weight": 200,
        "public_key": "rEVQ7I5Ckvg44uLaSg1l085FcQvFHfM01hMfHxyAQz0=",
        "ipv6_addr_in": "2607:9000:0:102::f001",
        "daita": true,
        "shadowsocks_extra_addr_in": [
          "68.235.46.35"
        ],
        "features": {
          "daita": {}
        }
      },
      {
        "hostname": "us-chi-wg-303",
        "location": "us-chi",
        "active": true,
        "owned": false,
        "provider": "Tzulo",
        "stboot": true,
        "ipv4_addr_in": "68.235.46.64",
        "include_in_country": true,
        "weight": 200,
        "public_key": "DfmNHT84TTS6JcJJfZJwT7tZZVgKIKRJU/2AE5sJ6A4=",
        "ipv6_addr_in": "2607:9000:0:103::f001",
        "daita": true,
        "shadowsocks_extra_addr_in": [
          "68.235.46.66"
        ],
        "features": {
          "daita": {}
        }
      },
      {
        "hostname": "us-chi-wg-304",
        "location": "us-chi",
        "active": true,
        "owned": false,
        "provider": "Tzulo",
        "stboot": true,
        "ipv4_addr_in": "68.235.46.95",
        "include_in_country": true,
        "weight": 200,
        "public_key": "Tr2rkoiqX7bERbeLMDw9CLiTaB0dp9/Fov/Ytz3C+xY=",
        "ipv6_addr_in": "2607:9000:0:104::f001",
        "daita": true,
        "shadowsocks_extra_addr_in": [
          "68.235.46.97"
        ],
        "features": {
          "daita": {}
        }
      },
      {
        "hostname": "us-chi-wg-305",
        "location": "us-chi",
        "active": true,
        "owned": false,
        "provider": "Tzulo",
        "stboot": true,
        "ipv4_addr_in": "68.235.46.126",
        "include_in_country": true,
        "weight": 200,
        "public_key": "jx/3CJiJRozty6hUTs40M/Swhfcch0z3yElmS1VKoVg=",
        "ipv6_addr_in": "2607:9000:0:105::f001",
        "shadowsocks_extra_addr_in": [
          "68.235.46.128"
        ]
      },
      {
        "hostname": "us-chi-wg-306",
        "location": "us-chi",
        "active": true,
        "owned": false,
        "provider": "Tzulo",
        "stboot": true,
        "ipv4_addr_in": "68.235.46.157",
        "include_in_country": true,
        "weight": 200,
        "public_key": "WlEbNkNAx/186YZH/UPE6YWkMyAMxRpMRP+IqWrq+TE=",
        "ipv6_addr_in": "2607:9000:0:106::f001",
        "shadowsocks_extra_addr_in": [
          "68.235.46.159"
        ]
      },
      {
        "hostname": "us-chi-wg-307",
        "location": "us-chi",
        "active": true,
        "owned": false,
        "provider": "Tzulo",
        "stboot": true,
        "ipv4_addr_in": "68.235.46.188",
        "include_in_country": true,
        "weight": 200,
        "public_key": "U9UAYlVm8nXZjWPrF/vbb1P9oqSRmHo+IfK52yDYpGo=",
        "ipv6_addr_in": "2607:9000:0:107::f001",
        "shadowsocks_extra_addr_in": [
          "68.235.46.190"
        ],
        "features": {
          "lwo": {}
        }
      },
      {
        "hostname": "us-chi-wg-308",
        "location": "us-chi",
        "active": true,
        "owned": false,
        "provider": "Tzulo",
        "stboot": true,
        "ipv4_addr_in": "68.235.46.209",
        "include_in_country": true,
        "weight": 200,
        "public_key": "gJsL4BfGcf2QOLGY1Std2Mjg6V2t2w7T2FScANlkJ2I=",
        "ipv6_addr_in": "2607:9000:0:108::f001",
        "shadowsocks_extra_addr_in": [
          "68.235.46.211"
        ],
        "features": {
          "lwo": {}
        }
      },
      {
        "hostname": "us-chi-wg-309",
        "location": "us-chi",
        "active": true,
        "owned": false,
        "provider": "Tzulo",
        "stboot": true,
        "ipv4_addr_in": "173.249.252.2",
        "include_in_country": true,
        "weight": 100,
        "public_key": "HMvcz+L7tNQc6FRMkkRDV7BUPzBH8SW74gN7yarX+hk=",
        "ipv6_addr_in": "2607:9000:100:41::f001",
        "shadowsocks_extra_addr_in": [
          "173.249.252.5",
          "173.249.252.6",
          "173.249.252.7",
          "173.249.252.8",
          "173.249.252.9",
          "173.249.252.10",
          "173.249.252.11",
          "173.249.252.12",
          "173.249.252.13",
          "173.249.252.14",
          "173.249.252.15",
          "173.249.252.16",
          "173.249.252.17",
          "173.249.252.18",
          "173.249.252.19",
          "2607:9000:100:41::b002",
          "2607:9000:100:41::b003",
          "2607:9000:100:41::b004",
          "2607:9000:100:41::b005",
          "2607:9000:100:41::b006",
          "2607:9000:100:41::b007",
          "2607:9000:100:41::b008",
          "2607:9000:100:41::b009",
          "2607:9000:100:41::b00a",
          "2607:9000:100:41::b00b",
          "2607:9000:100:41::b00c",
          "2607:9000:100:41::b00d",
          "2607:9000:100:41::b00e",
          "2607:9000:100:41::b00f",
          "2607:9000:100:41::b010",
          "2607:9000:100:41::b011",
          "2607:9000:100:41::b012",
          "2607:9000:100:41::b013",
          "2607:9000:100:41::b014",
          "2607:9000:100:41::b015",
          "2607:9000:100:41::b016",
          "2607:9000:100:41::b017",
          "2607:9000:100:41::b018",
          "2607:9000:100:41::b019",
          "2607:9000:100:41::b01a",
          "2607:9000:100:41::b01b",
          "2607:9000:100:41::b01c",
          "2607:9000:100:41::b01d",
          "2607:9000:100:41::b01e",
          "2607:9000:100:41::b01f"
        ],
        "features": {
          "quic": {
            "addr_in": [
              "173.249.252.20",
              "173.249.252.21",
              "173.249.252.22",
              "173.249.252.23",
              "173.249.252.24",
              "173.249.252.25",
              "173.249.252.26",
              "173.249.252.27",
              "173.249.252.28",
              "173.249.252.29",
              "173.249.252.30",
              "173.249.252.31",
              "173.249.252.32",
              "173.249.252.33",
              "173.249.252.34",
              "2607:9000:100:41::c002",
              "2607:9000:100:41::c003",
              "2607:9000:100:41::c004",
              "2607:9000:100:41::c005",
              "2607:9000:100:41::c006",
              "2607:9000:100:41::c007",
              "2607:9000:100:41::c008",
              "2607:9000:100:41::c009",
              "2607:9000:100:41::c00a",
              "2607:9000:100:41::c00b",
              "2607:9000:100:41::c00c",
              "2607:9000:100:41::c00d",
              "2607:9000:100:41::c00e",
              "2607:9000:100:41::c00f",
              "2607:9000:100:41::c010",
              "2607:9000:100:41::c011",
              "2607:9000:100:41::c012",
              "2607:9000:100:41::c013",
              "2607:9000:100:41::c014",
              "2607:9000:100:41::c015",
              "2607:9000:100:41::c016",
              "2607:9000:100:41::c017",
              "2607:9000:100:41::c018",
              "2607:9000:100:41::c019",
              "2607:9000:100:41::c01a",
              "2607:9000:100:41::c01b",
              "2607:9000:100:41::c01c",
              "2607:9000:100:41::c01d",
              "2607:9000:100:41::c01e",
              "2607:9000:100:41::c01f"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "us-chi-wg-309.blockerad.eu"
          }
        }
      },
      {
        "hostname": "us-chi-wg-310",
        "location": "us-chi",
        "active": true,
        "owned": false,
        "provider": "Tzulo",
        "stboot": true,
        "ipv4_addr_in": "173.249.252.127",
        "include_in_country": true,
        "weight": 100,
        "public_key": "bJLgTMbt7cx1lKyWzOwW3+Lqc0n6OOXu/iTerXZxawY=",
        "ipv6_addr_in": "2607:9000:100:42::f001",
        "shadowsocks_extra_addr_in": [
          "173.249.252.130",
          "173.249.252.131",
          "173.249.252.132",
          "173.249.252.133",
          "173.249.252.134",
          "173.249.252.135",
          "173.249.252.136",
          "173.249.252.137",
          "173.249.252.138",
          "173.249.252.139",
          "173.249.252.140",
          "173.249.252.141",
          "173.249.252.142",
          "173.249.252.143",
          "173.249.252.144",
          "2607:9000:100:42::b002",
          "2607:9000:100:42::b003",
          "2607:9000:100:42::b004",
          "2607:9000:100:42::b005",
          "2607:9000:100:42::b006",
          "2607:9000:100:42::b007",
          "2607:9000:100:42::b008",
          "2607:9000:100:42::b009",
          "2607:9000:100:42::b00a",
          "2607:9000:100:42::b00b",
          "2607:9000:100:42::b00c",
          "2607:9000:100:42::b00d",
          "2607:9000:100:42::b00e",
          "2607:9000:100:42::b00f",
          "2607:9000:100:42::b010",
          "2607:9000:100:42::b011",
          "2607:9000:100:42::b012",
          "2607:9000:100:42::b013",
          "2607:9000:100:42::b014",
          "2607:9000:100:42::b015",
          "2607:9000:100:42::b016",
          "2607:9000:100:42::b017",
          "2607:9000:100:42::b018",
          "2607:9000:100:42::b019",
          "2607:9000:100:42::b01a",
          "2607:9000:100:42::b01b",
          "2607:9000:100:42::b01c",
          "2607:9000:100:42::b01d",
          "2607:9000:100:42::b01e",
          "2607:9000:100:42::b01f"
        ],
        "features": {
          "quic": {
            "addr_in": [
              "173.249.252.145",
              "173.249.252.146",
              "173.249.252.147",
              "173.249.252.148",
              "173.249.252.149",
              "173.249.252.150",
              "173.249.252.151",
              "173.249.252.152",
              "173.249.252.153",
              "173.249.252.154",
              "173.249.252.155",
              "173.249.252.156",
              "173.249.252.157",
              "173.249.252.158",
              "173.249.252.159",
              "2607:9000:100:42::c002",
              "2607:9000:100:42::c003",
              "2607:9000:100:42::c004",
              "2607:9000:100:42::c005",
              "2607:9000:100:42::c006",
              "2607:9000:100:42::c007",
              "2607:9000:100:42::c008",
              "2607:9000:100:42::c009",
              "2607:9000:100:42::c00a",
              "2607:9000:100:42::c00b",
              "2607:9000:100:42::c00c",
              "2607:9000:100:42::c00d",
              "2607:9000:100:42::c00e",
              "2607:9000:100:42::c00f",
              "2607:9000:100:42::c010",
              "2607:9000:100:42::c011",
              "2607:9000:100:42::c012",
              "2607:9000:100:42::c013",
              "2607:9000:100:42::c014",
              "2607:9000:100:42::c015",
              "2607:9000:100:42::c016",
              "2607:9000:100:42::c017",
              "2607:9000:100:42::c018",
              "2607:9000:100:42::c019",
              "2607:9000:100:42::c01a",
              "2607:9000:100:42::c01b",
              "2607:9000:100:42::c01c",
              "2607:9000:100:42::c01d",
              "2607:9000:100:42::c01e",
              "2607:9000:100:42::c01f"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "us-chi-wg-310.blockerad.eu"
          }
        }
      },
      {
        "hostname": "us-chi-wg-311",
        "location": "us-chi",
        "active": true,
        "owned": false,
        "provider": "Tzulo",
        "stboot": true,
        "ipv4_addr_in": "173.249.253.2",
        "include_in_country": true,
        "weight": 100,
        "public_key": "9oEgVktX3TUJI5XPWnvVHszj1Q44ix6VDN0CqS0eglc=",
        "ipv6_addr_in": "2607:9000:100:43::f001",
        "shadowsocks_extra_addr_in": [
          "173.249.253.5",
          "173.249.253.6",
          "173.249.253.7",
          "173.249.253.8",
          "173.249.253.9",
          "173.249.253.10",
          "173.249.253.11",
          "173.249.253.12",
          "173.249.253.13",
          "173.249.253.14",
          "173.249.253.15",
          "173.249.253.16",
          "173.249.253.17",
          "173.249.253.18",
          "173.249.253.19",
          "2607:9000:100:43::b002",
          "2607:9000:100:43::b003",
          "2607:9000:100:43::b004",
          "2607:9000:100:43::b005",
          "2607:9000:100:43::b006",
          "2607:9000:100:43::b007",
          "2607:9000:100:43::b008",
          "2607:9000:100:43::b009",
          "2607:9000:100:43::b00a",
          "2607:9000:100:43::b00b",
          "2607:9000:100:43::b00c",
          "2607:9000:100:43::b00d",
          "2607:9000:100:43::b00e",
          "2607:9000:100:43::b00f",
          "2607:9000:100:43::b010",
          "2607:9000:100:43::b011",
          "2607:9000:100:43::b012",
          "2607:9000:100:43::b013",
          "2607:9000:100:43::b014",
          "2607:9000:100:43::b015",
          "2607:9000:100:43::b016",
          "2607:9000:100:43::b017",
          "2607:9000:100:43::b018",
          "2607:9000:100:43::b019",
          "2607:9000:100:43::b01a",
          "2607:9000:100:43::b01b",
          "2607:9000:100:43::b01c",
          "2607:9000:100:43::b01d",
          "2607:9000:100:43::b01e",
          "2607:9000:100:43::b01f"
        ],
        "features": {
          "lwo": {},
          "quic": {
            "addr_in": [
              "173.249.253.20",
              "173.249.253.21",
              "173.249.253.22",
              "173.249.253.23",
              "173.249.253.24",
              "173.249.253.25",
              "173.249.253.26",
              "173.249.253.27",
              "173.249.253.28",
              "173.249.253.29",
              "173.249.253.30",
              "173.249.253.31",
              "173.249.253.32",
              "173.249.253.33",
              "173.249.253.34",
              "2607:9000:100:43::c002",
              "2607:9000:100:43::c003",
              "2607:9000:100:43::c004",
              "2607:9000:100:43::c005",
              "2607:9000:100:43::c006",
              "2607:9000:100:43::c007",
              "2607:9000:100:43::c008",
              "2607:9000:100:43::c009",
              "2607:9000:100:43::c00a",
              "2607:9000:100:43::c00b",
              "2607:9000:100:43::c00c",
              "2607:9000:100:43::c00d",
              "2607:9000:100:43::c00e",
              "2607:9000:100:43::c00f",
              "2607:9000:100:43::c010",
              "2607:9000:100:43::c011",
              "2607:9000:100:43::c012",
              "2607:9000:100:43::c013",
              "2607:9000:100:43::c014",
              "2607:9000:100:43::c015",
              "2607:9000:100:43::c016",
              "2607:9000:100:43::c017",
              "2607:9000:100:43::c018",
              "2607:9000:100:43::c019",
              "2607:9000:100:43::c01a",
              "2607:9000:100:43::c01b",
              "2607:9000:100:43::c01c",
              "2607:9000:100:43::c01d",
              "2607:9000:100:43::c01e",
              "2607:9000:100:43::c01f"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "us-chi-wg-311.blockerad.eu"
          }
        }
      },
      {
        "hostname": "us-chi-wg-312",
        "location": "us-chi",
        "active": true,
        "owned": false,
        "provider": "Tzulo",
        "stboot": true,
        "ipv4_addr_in": "173.249.253.127",
        "include_in_country": true,
        "weight": 100,
        "public_key": "XzMA3EWGePHQ6ko5XImi4m3TphQqjq9++A8XPfre/0A=",
        "ipv6_addr_in": "2607:9000:100:44::f001",
        "shadowsocks_extra_addr_in": [
          "173.249.253.130",
          "173.249.253.131",
          "173.249.253.132",
          "173.249.253.133",
          "173.249.253.134",
          "173.249.253.135",
          "173.249.253.136",
          "173.249.253.137",
          "173.249.253.138",
          "173.249.253.139",
          "173.249.253.140",
          "173.249.253.141",
          "173.249.253.142",
          "173.249.253.143",
          "173.249.253.144",
          "2607:9000:100:44::b002",
          "2607:9000:100:44::b003",
          "2607:9000:100:44::b004",
          "2607:9000:100:44::b005",
          "2607:9000:100:44::b006",
          "2607:9000:100:44::b007",
          "2607:9000:100:44::b008",
          "2607:9000:100:44::b009",
          "2607:9000:100:44::b00a",
          "2607:9000:100:44::b00b",
          "2607:9000:100:44::b00c",
          "2607:9000:100:44::b00d",
          "2607:9000:100:44::b00e",
          "2607:9000:100:44::b00f",
          "2607:9000:100:44::b010",
          "2607:9000:100:44::b011",
          "2607:9000:100:44::b012",
          "2607:9000:100:44::b013",
          "2607:9000:100:44::b014",
          "2607:9000:100:44::b015",
          "2607:9000:100:44::b016",
          "2607:9000:100:44::b017",
          "2607:9000:100:44::b018",
          "2607:9000:100:44::b019",
          "2607:9000:100:44::b01a",
          "2607:9000:100:44::b01b",
          "2607:9000:100:44::b01c",
          "2607:9000:100:44::b01d",
          "2607:9000:100:44::b01e",
          "2607:9000:100:44::b01f"
        ],
        "features": {
          "lwo": {},
          "quic": {
            "addr_in": [
              "173.249.253.145",
              "173.249.253.146",
              "173.249.253.147",
              "173.249.253.148",
              "173.249.253.149",
              "173.249.253.150",
              "173.249.253.151",
              "173.249.253.152",
              "173.249.253.153",
              "173.249.253.154",
              "173.249.253.155",
              "173.249.253.156",
              "173.249.253.157",
              "173.249.253.158",
              "173.249.253.159",
              "2607:9000:100:44::c002",
              "2607:9000:100:44::c003",
              "2607:9000:100:44::c004",
              "2607:9000:100:44::c005",
              "2607:9000:100:44::c006",
              "2607:9000:100:44::c007",
              "2607:9000:100:44::c008",
              "2607:9000:100:44::c009",
              "2607:9000:100:44::c00a",
              "2607:9000:100:44::c00b",
              "2607:9000:100:44::c00c",
              "2607:9000:100:44::c00d",
              "2607:9000:100:44::c00e",
              "2607:9000:100:44::c00f",
              "2607:9000:100:44::c010",
              "2607:9000:100:44::c011",
              "2607:9000:100:44::c012",
              "2607:9000:100:44::c013",
              "2607:9000:100:44::c014",
              "2607:9000:100:44::c015",
              "2607:9000:100:44::c016",
              "2607:9000:100:44::c017",
              "2607:9000:100:44::c018",
              "2607:9000:100:44::c019",
              "2607:9000:100:44::c01a",
              "2607:9000:100:44::c01b",
              "2607:9000:100:44::c01c",
              "2607:9000:100:44::c01d",
              "2607:9000:100:44::c01e",
              "2607:9000:100:44::c01f"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "us-chi-wg-312.blockerad.eu"
          }
        }
      },
      {
        "hostname": "us-chi-wg-313",
        "location": "us-chi",
        "active": true,
        "owned": false,
        "provider": "Tzulo",
        "stboot": true,
        "ipv4_addr_in": "173.249.254.2",
        "include_in_country": true,
        "weight": 100,
        "public_key": "/xG21lmyVnh9eSbTP2iYWCM4SIw1QCkKyFKGBkoJlXM=",
        "ipv6_addr_in": "2607:9000:100:45::f001",
        "shadowsocks_extra_addr_in": [
          "173.249.254.5",
          "173.249.254.6",
          "173.249.254.7",
          "173.249.254.8",
          "173.249.254.9",
          "173.249.254.10",
          "173.249.254.11",
          "173.249.254.12",
          "173.249.254.13",
          "173.249.254.14",
          "173.249.254.15",
          "173.249.254.16",
          "173.249.254.17",
          "173.249.254.18",
          "173.249.254.19",
          "2607:9000:100:45::b002",
          "2607:9000:100:45::b003",
          "2607:9000:100:45::b004",
          "2607:9000:100:45::b005",
          "2607:9000:100:45::b006",
          "2607:9000:100:45::b007",
          "2607:9000:100:45::b008",
          "2607:9000:100:45::b009",
          "2607:9000:100:45::b00a",
          "2607:9000:100:45::b00b",
          "2607:9000:100:45::b00c",
          "2607:9000:100:45::b00d",
          "2607:9000:100:45::b00e",
          "2607:9000:100:45::b00f",
          "2607:9000:100:45::b010",
          "2607:9000:100:45::b011",
          "2607:9000:100:45::b012",
          "2607:9000:100:45::b013",
          "2607:9000:100:45::b014",
          "2607:9000:100:45::b015",
          "2607:9000:100:45::b016",
          "2607:9000:100:45::b017",
          "2607:9000:100:45::b018",
          "2607:9000:100:45::b019",
          "2607:9000:100:45::b01a",
          "2607:9000:100:45::b01b",
          "2607:9000:100:45::b01c",
          "2607:9000:100:45::b01d",
          "2607:9000:100:45::b01e",
          "2607:9000:100:45::b01f"
        ],
        "features": {
          "lwo": {},
          "quic": {
            "addr_in": [
              "173.249.254.20",
              "173.249.254.21",
              "173.249.254.22",
              "173.249.254.23",
              "173.249.254.24",
              "173.249.254.25",
              "173.249.254.26",
              "173.249.254.27",
              "173.249.254.28",
              "173.249.254.29",
              "173.249.254.30",
              "173.249.254.31",
              "173.249.254.32",
              "173.249.254.33",
              "173.249.254.34",
              "2607:9000:100:45::c002",
              "2607:9000:100:45::c003",
              "2607:9000:100:45::c004",
              "2607:9000:100:45::c005",
              "2607:9000:100:45::c006",
              "2607:9000:100:45::c007",
              "2607:9000:100:45::c008",
              "2607:9000:100:45::c009",
              "2607:9000:100:45::c00a",
              "2607:9000:100:45::c00b",
              "2607:9000:100:45::c00c",
              "2607:9000:100:45::c00d",
              "2607:9000:100:45::c00e",
              "2607:9000:100:45::c00f",
              "2607:9000:100:45::c010",
              "2607:9000:100:45::c011",
              "2607:9000:100:45::c012",
              "2607:9000:100:45::c013",
              "2607:9000:100:45::c014",
              "2607:9000:100:45::c015",
              "2607:9000:100:45::c016",
              "2607:9000:100:45::c017",
              "2607:9000:100:45::c018",
              "2607:9000:100:45::c019",
              "2607:9000:100:45::c01a",
              "2607:9000:100:45::c01b",
              "2607:9000:100:45::c01c",
              "2607:9000:100:45::c01d",
              "2607:9000:100:45::c01e",
              "2607:9000:100:45::c01f"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "us-chi-wg-313.blockerad.eu"
          }
        }
      },
      {
        "hostname": "us-chi-wg-314",
        "location": "us-chi",
        "active": true,
        "owned": false,
        "provider": "Tzulo",
        "stboot": true,
        "ipv4_addr_in": "173.249.254.127",
        "include_in_country": true,
        "weight": 100,
        "public_key": "2UyKDI5jY9Nlys5aiOUh8piEfF0wFBZsk7WToNQ8HTk=",
        "ipv6_addr_in": "2607:9000:100:46::f001",
        "shadowsocks_extra_addr_in": [
          "173.249.254.130",
          "173.249.254.131",
          "173.249.254.132",
          "173.249.254.133",
          "173.249.254.134",
          "173.249.254.135",
          "173.249.254.136",
          "173.249.254.137",
          "173.249.254.138",
          "173.249.254.139",
          "173.249.254.140",
          "173.249.254.141",
          "173.249.254.142",
          "173.249.254.143",
          "173.249.254.144",
          "2607:9000:100:46::b002",
          "2607:9000:100:46::b003",
          "2607:9000:100:46::b004",
          "2607:9000:100:46::b005",
          "2607:9000:100:46::b006",
          "2607:9000:100:46::b007",
          "2607:9000:100:46::b008",
          "2607:9000:100:46::b009",
          "2607:9000:100:46::b00a",
          "2607:9000:100:46::b00b",
          "2607:9000:100:46::b00c",
          "2607:9000:100:46::b00d",
          "2607:9000:100:46::b00e",
          "2607:9000:100:46::b00f",
          "2607:9000:100:46::b010",
          "2607:9000:100:46::b011",
          "2607:9000:100:46::b012",
          "2607:9000:100:46::b013",
          "2607:9000:100:46::b014",
          "2607:9000:100:46::b015",
          "2607:9000:100:46::b016",
          "2607:9000:100:46::b017",
          "2607:9000:100:46::b018",
          "2607:9000:100:46::b019",
          "2607:9000:100:46::b01a",
          "2607:9000:100:46::b01b",
          "2607:9000:100:46::b01c",
          "2607:9000:100:46::b01d",
          "2607:9000:100:46::b01e",
          "2607:9000:100:46::b01f"
        ],
        "features": {
          "lwo": {},
          "quic": {
            "addr_in": [
              "173.249.254.145",
              "173.249.254.146",
              "173.249.254.147",
              "173.249.254.148",
              "173.249.254.149",
              "173.249.254.150",
              "173.249.254.151",
              "173.249.254.152",
              "173.249.254.153",
              "173.249.254.154",
              "173.249.254.155",
              "173.249.254.156",
              "173.249.254.157",
              "173.249.254.158",
              "173.249.254.159",
              "2607:9000:100:46::c002",
              "2607:9000:100:46::c003",
              "2607:9000:100:46::c004",
              "2607:9000:100:46::c005",
              "2607:9000:100:46::c006",
              "2607:9000:100:46::c007",
              "2607:9000:100:46::c008",
              "2607:9000:100:46::c009",
              "2607:9000:100:46::c00a",
              "2607:9000:100:46::c00b",
              "2607:9000:100:46::c00c",
              "2607:9000:100:46::c00d",
              "2607:9000:100:46::c00e",
              "2607:9000:100:46::c00f",
              "2607:9000:100:46::c010",
              "2607:9000:100:46::c011",
              "2607:9000:100:46::c012",
              "2607:9000:100:46::c013",
              "2607:9000:100:46::c014",
              "2607:9000:100:46::c015",
              "2607:9000:100:46::c016",
              "2607:9000:100:46::c017",
              "2607:9000:100:46::c018",
              "2607:9000:100:46::c019",
              "2607:9000:100:46::c01a",
              "2607:9000:100:46::c01b",
              "2607:9000:100:46::c01c",
              "2607:9000:100:46::c01d",
              "2607:9000:100:46::c01e",
              "2607:9000:100:46::c01f"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "us-chi-wg-314.blockerad.eu"
          }
        }
      },
      {
        "hostname": "us-chi-wg-315",
        "location": "us-chi",
        "active": true,
        "owned": false,
        "provider": "Tzulo",
        "stboot": true,
        "ipv4_addr_in": "173.249.255.2",
        "include_in_country": true,
        "weight": 100,
        "public_key": "q8TC/ILZWlaydPdkJLkL/pWB8qrK0dWkKtZMGqEElh8=",
        "ipv6_addr_in": "2607:9000:100:47::f001",
        "daita": true,
        "shadowsocks_extra_addr_in": [
          "173.249.255.5",
          "173.249.255.6",
          "173.249.255.7",
          "173.249.255.8",
          "173.249.255.9",
          "173.249.255.10",
          "173.249.255.11",
          "173.249.255.12",
          "173.249.255.13",
          "173.249.255.14",
          "173.249.255.15",
          "173.249.255.16",
          "173.249.255.17",
          "173.249.255.18",
          "173.249.255.19",
          "2607:9000:100:47::b002",
          "2607:9000:100:47::b003",
          "2607:9000:100:47::b004",
          "2607:9000:100:47::b005",
          "2607:9000:100:47::b006",
          "2607:9000:100:47::b007",
          "2607:9000:100:47::b008",
          "2607:9000:100:47::b009",
          "2607:9000:100:47::b00a",
          "2607:9000:100:47::b00b",
          "2607:9000:100:47::b00c",
          "2607:9000:100:47::b00d",
          "2607:9000:100:47::b00e",
          "2607:9000:100:47::b00f",
          "2607:9000:100:47::b010",
          "2607:9000:100:47::b011",
          "2607:9000:100:47::b012",
          "2607:9000:100:47::b013",
          "2607:9000:100:47::b014",
          "2607:9000:100:47::b015",
          "2607:9000:100:47::b016",
          "2607:9000:100:47::b017",
          "2607:9000:100:47::b018",
          "2607:9000:100:47::b019",
          "2607:9000:100:47::b01a",
          "2607:9000:100:47::b01b",
          "2607:9000:100:47::b01c",
          "2607:9000:100:47::b01d",
          "2607:9000:100:47::b01e",
          "2607:9000:100:47::b01f"
        ],
        "features": {
          "daita": {},
          "quic": {
            "addr_in": [
              "173.249.255.20",
              "173.249.255.21",
              "173.249.255.22",
              "173.249.255.23",
              "173.249.255.24",
              "173.249.255.25",
              "173.249.255.26",
              "173.249.255.27",
              "173.249.255.28",
              "173.249.255.29",
              "173.249.255.30",
              "173.249.255.31",
              "173.249.255.32",
              "173.249.255.33",
              "173.249.255.34",
              "2607:9000:100:47::c002",
              "2607:9000:100:47::c003",
              "2607:9000:100:47::c004",
              "2607:9000:100:47::c005",
              "2607:9000:100:47::c006",
              "2607:9000:100:47::c007",
              "2607:9000:100:47::c008",
              "2607:9000:100:47::c009",
              "2607:9000:100:47::c00a",
              "2607:9000:100:47::c00b",
              "2607:9000:100:47::c00c",
              "2607:9000:100:47::c00d",
              "2607:9000:100:47::c00e",
              "2607:9000:100:47::c00f",
              "2607:9000:100:47::c010",
              "2607:9000:100:47::c011",
              "2607:9000:100:47::c012",
              "2607:9000:100:47::c013",
              "2607:9000:100:47::c014",
              "2607:9000:100:47::c015",
              "2607:9000:100:47::c016",
              "2607:9000:100:47::c017",
              "2607:9000:100:47::c018",
              "2607:9000:100:47::c019",
              "2607:9000:100:47::c01a",
              "2607:9000:100:47::c01b",
              "2607:9000:100:47::c01c",
              "2607:9000:100:47::c01d",
              "2607:9000:100:47::c01e",
              "2607:9000:100:47::c01f"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "us-chi-wg-315.blockerad.eu"
          }
        }
      },
      {
        "hostname": "us-chi-wg-316",
        "location": "us-chi",
        "active": true,
        "owned": false,
        "provider": "Tzulo",
        "stboot": true,
        "ipv4_addr_in": "173.249.255.127",
        "include_in_country": true,
        "weight": 100,
        "public_key": "5oGrphw1JoWMIeJUHytMdOKvyxx5P4l7OyP/uTYDmyg=",
        "ipv6_addr_in": "2607:9000:100:48::f001",
        "daita": true,
        "shadowsocks_extra_addr_in": [
          "173.249.255.130",
          "173.249.255.131",
          "173.249.255.132",
          "173.249.255.133",
          "173.249.255.134",
          "173.249.255.135",
          "173.249.255.136",
          "173.249.255.137",
          "173.249.255.138",
          "173.249.255.139",
          "173.249.255.140",
          "173.249.255.141",
          "173.249.255.142",
          "173.249.255.143",
          "173.249.255.144",
          "2607:9000:100:48::b002",
          "2607:9000:100:48::b003",
          "2607:9000:100:48::b004",
          "2607:9000:100:48::b005",
          "2607:9000:100:48::b006",
          "2607:9000:100:48::b007",
          "2607:9000:100:48::b008",
          "2607:9000:100:48::b009",
          "2607:9000:100:48::b00a",
          "2607:9000:100:48::b00b",
          "2607:9000:100:48::b00c",
          "2607:9000:100:48::b00d",
          "2607:9000:100:48::b00e",
          "2607:9000:100:48::b00f",
          "2607:9000:100:48::b010",
          "2607:9000:100:48::b011",
          "2607:9000:100:48::b012",
          "2607:9000:100:48::b013",
          "2607:9000:100:48::b014",
          "2607:9000:100:48::b015",
          "2607:9000:100:48::b016",
          "2607:9000:100:48::b017",
          "2607:9000:100:48::b018",
          "2607:9000:100:48::b019",
          "2607:9000:100:48::b01a",
          "2607:9000:100:48::b01b",
          "2607:9000:100:48::b01c",
          "2607:9000:100:48::b01d",
          "2607:9000:100:48::b01e",
          "2607:9000:100:48::b01f"
        ],
        "features": {
          "daita": {},
          "quic": {
            "addr_in": [
              "173.249.255.145",
              "173.249.255.146",
              "173.249.255.147",
              "173.249.255.148",
              "173.249.255.149",
              "173.249.255.150",
              "173.249.255.151",
              "173.249.255.152",
              "173.249.255.153",
              "173.249.255.154",
              "173.249.255.155",
              "173.249.255.156",
              "173.249.255.157",
              "173.249.255.158",
              "173.249.255.159",
              "2607:9000:100:48::c002",
              "2607:9000:100:48::c003",
              "2607:9000:100:48::c004",
              "2607:9000:100:48::c005",
              "2607:9000:100:48::c006",
              "2607:9000:100:48::c007",
              "2607:9000:100:48::c008",
              "2607:9000:100:48::c009",
              "2607:9000:100:48::c00a",
              "2607:9000:100:48::c00b",
              "2607:9000:100:48::c00c",
              "2607:9000:100:48::c00d",
              "2607:9000:100:48::c00e",
              "2607:9000:100:48::c00f",
              "2607:9000:100:48::c010",
              "2607:9000:100:48::c011",
              "2607:9000:100:48::c012",
              "2607:9000:100:48::c013",
              "2607:9000:100:48::c014",
              "2607:9000:100:48::c015",
              "2607:9000:100:48::c016",
              "2607:9000:100:48::c017",
              "2607:9000:100:48::c018",
              "2607:9000:100:48::c019",
              "2607:9000:100:48::c01a",
              "2607:9000:100:48::c01b",
              "2607:9000:100:48::c01c",
              "2607:9000:100:48::c01d",
              "2607:9000:100:48::c01e",
              "2607:9000:100:48::c01f"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "us-chi-wg-316.blockerad.eu"
          }
        }
      },
      {
        "hostname": "us-dal-wg-001",
        "location": "us-dal",
        "active": true,
        "owned": false,
        "provider": "M247",
        "stboot": true,
        "ipv4_addr_in": "146.70.211.66",
        "include_in_country": true,
        "weight": 100,
        "public_key": "EAzbWMQXxJGsd8j2brhYerGB3t5cPOXqdIDFspDGSng=",
        "ipv6_addr_in": "2001:ac8:9a:76::1f",
        "features": {
          "lwo": {},
          "quic": {
            "addr_in": [
              "146.70.211.126"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "us-dal-wg-001.blockerad.eu"
          }
        }
      },
      {
        "hostname": "us-dal-wg-002",
        "location": "us-dal",
        "active": true,
        "owned": false,
        "provider": "M247",
        "stboot": true,
        "ipv4_addr_in": "146.70.211.2",
        "include_in_country": true,
        "weight": 100,
        "public_key": "OYG1hxzz3kUGpVeGjx9DcCYreMO3S6tZN17iHUK+zDE=",
        "ipv6_addr_in": "2001:ac8:9a:75::2f"
      },
      {
        "hostname": "us-dal-wg-003",
        "location": "us-dal",
        "active": true,
        "owned": false,
        "provider": "M247",
        "stboot": true,
        "ipv4_addr_in": "146.70.211.130",
        "include_in_country": true,
        "weight": 100,
        "public_key": "jn/i/ekJOkkRUdMj2I4ViUKd3d/LAdTQ+ICKmBy1tkM=",
        "ipv6_addr_in": "2001:ac8:9a:78::3f"
      },
      {
        "hostname": "us-dal-wg-401",
        "location": "us-dal",
        "active": true,
        "owned": false,
        "provider": "DataPacket",
        "stboot": true,
        "ipv4_addr_in": "37.19.200.156",
        "include_in_country": true,
        "weight": 100,
        "public_key": "xZsnCxFN7pOvx6YlTbi92copdsY5xgekTCp//VUMyhE=",
        "ipv6_addr_in": "2a02:6ea0:d20c:3::b72f"
      },
      {
        "hostname": "us-dal-wg-402",
        "location": "us-dal",
        "active": true,
        "owned": false,
        "provider": "DataPacket",
        "stboot": true,
        "ipv4_addr_in": "37.19.200.143",
        "include_in_country": true,
        "weight": 100,
        "public_key": "sPQEji8BhxuM/Za0Q0/9aWYxyACtQF0qRpzaBLumEzo=",
        "ipv6_addr_in": "2a02:6ea0:d20c:2::b71f"
      },
      {
        "hostname": "us-dal-wg-403",
        "location": "us-dal",
        "active": true,
        "owned": false,
        "provider": "DataPacket",
        "stboot": true,
        "ipv4_addr_in": "37.19.200.130",
        "include_in_country": true,
        "weight": 100,
        "public_key": "4s9JIhxC/D02tosXYYcgrD+pHI+C7oTAFsXzVisKjRs=",
        "ipv6_addr_in": "2a02:6ea0:d20c:1::f001"
      },
      {
        "hostname": "us-dal-wg-601",
        "location": "us-dal",
        "active": true,
        "owned": false,
        "provider": "HostRoyale",
        "stboot": true,
        "ipv4_addr_in": "103.102.246.3",
        "include_in_country": true,
        "weight": 100,
        "public_key": "353XrBhmW0VisDN/ztYLb7WwnxQUTnL9Ys5FBPUHHVw=",
        "ipv6_addr_in": "2a01:4740:2::f001",
        "shadowsocks_extra_addr_in": [
          "103.102.246.14"
        ]
      },
      {
        "hostname": "us-dal-wg-602",
        "location": "us-dal",
        "active": false,
        "owned": false,
        "provider": "HostRoyale",
        "stboot": true,
        "ipv4_addr_in": "103.102.246.127",
        "include_in_country": true,
        "weight": 100,
        "public_key": "Vm9kQsUFIGgNeb+NBrY0KZpW51dC84cAQWMY9eMa8Ho=",
        "ipv6_addr_in": "2a01:4740:2::f101",
        "shadowsocks_extra_addr_in": [
          "103.102.246.139"
        ]
      },
      {
        "hostname": "us-dal-wg-603",
        "location": "us-dal",
        "active": true,
        "owned": false,
        "provider": "HostRoyale",
        "stboot": true,
        "ipv4_addr_in": "103.102.247.3",
        "include_in_country": true,
        "weight": 100,
        "public_key": "Y5SK28yMGjcZVByWZkMb24KdmbmY07mDnwLN6817yEE=",
        "ipv6_addr_in": "2a01:4740:2::f201",
        "shadowsocks_extra_addr_in": [
          "103.102.247.14"
        ]
      },
      {
        "hostname": "us-dal-wg-604",
        "location": "us-dal",
        "active": true,
        "owned": false,
        "provider": "HostRoyale",
        "stboot": true,
        "ipv4_addr_in": "103.102.247.127",
        "include_in_country": true,
        "weight": 100,
        "public_key": "7Wyh9lX1nIkKfIpwUywcSUVF8pOxP0c04EehfEeIWg4=",
        "ipv6_addr_in": "2a01:4740:2::f301",
        "shadowsocks_extra_addr_in": [
          "103.102.247.139"
        ]
      },
      {
        "hostname": "us-dal-wg-701",
        "location": "us-dal",
        "active": true,
        "owned": false,
        "provider": "Tzulo",
        "stboot": true,
        "ipv4_addr_in": "23.234.104.2",
        "include_in_country": true,
        "weight": 100,
        "public_key": "pl4AW+ZGaOknJlgTbACqwihOe+A3GC5aALB74RLTFF8=",
        "ipv6_addr_in": "2607:9000:b00:31::f001",
        "shadowsocks_extra_addr_in": [
          "23.234.104.5",
          "23.234.104.6",
          "23.234.104.7",
          "23.234.104.8",
          "23.234.104.9",
          "23.234.104.10",
          "23.234.104.11",
          "23.234.104.12",
          "23.234.104.13",
          "23.234.104.14",
          "23.234.104.15",
          "23.234.104.16",
          "23.234.104.17",
          "23.234.104.18",
          "23.234.104.19",
          "2607:9000:b00:31::b002",
          "2607:9000:b00:31::b003",
          "2607:9000:b00:31::b004",
          "2607:9000:b00:31::b005",
          "2607:9000:b00:31::b006",
          "2607:9000:b00:31::b007",
          "2607:9000:b00:31::b008",
          "2607:9000:b00:31::b009",
          "2607:9000:b00:31::b00a",
          "2607:9000:b00:31::b00b",
          "2607:9000:b00:31::b00c",
          "2607:9000:b00:31::b00d",
          "2607:9000:b00:31::b00e",
          "2607:9000:b00:31::b00f",
          "2607:9000:b00:31::b010",
          "2607:9000:b00:31::b011",
          "2607:9000:b00:31::b012",
          "2607:9000:b00:31::b013",
          "2607:9000:b00:31::b014",
          "2607:9000:b00:31::b015",
          "2607:9000:b00:31::b016",
          "2607:9000:b00:31::b017",
          "2607:9000:b00:31::b018",
          "2607:9000:b00:31::b019",
          "2607:9000:b00:31::b01a",
          "2607:9000:b00:31::b01b",
          "2607:9000:b00:31::b01c",
          "2607:9000:b00:31::b01d",
          "2607:9000:b00:31::b01e",
          "2607:9000:b00:31::b01f"
        ],
        "features": {
          "lwo": {},
          "quic": {
            "addr_in": [
              "23.234.104.20",
              "23.234.104.21",
              "23.234.104.22",
              "23.234.104.23",
              "23.234.104.24",
              "23.234.104.25",
              "23.234.104.26",
              "23.234.104.27",
              "23.234.104.28",
              "23.234.104.29",
              "23.234.104.30",
              "23.234.104.31",
              "23.234.104.32",
              "23.234.104.33",
              "23.234.104.34",
              "2607:9000:b00:31::c002",
              "2607:9000:b00:31::c003",
              "2607:9000:b00:31::c004",
              "2607:9000:b00:31::c005",
              "2607:9000:b00:31::c006",
              "2607:9000:b00:31::c007",
              "2607:9000:b00:31::c008",
              "2607:9000:b00:31::c009",
              "2607:9000:b00:31::c00a",
              "2607:9000:b00:31::c00b",
              "2607:9000:b00:31::c00c",
              "2607:9000:b00:31::c00d",
              "2607:9000:b00:31::c00e",
              "2607:9000:b00:31::c00f",
              "2607:9000:b00:31::c010",
              "2607:9000:b00:31::c011",
              "2607:9000:b00:31::c012",
              "2607:9000:b00:31::c013",
              "2607:9000:b00:31::c014",
              "2607:9000:b00:31::c015",
              "2607:9000:b00:31::c016",
              "2607:9000:b00:31::c017",
              "2607:9000:b00:31::c018",
              "2607:9000:b00:31::c019",
              "2607:9000:b00:31::c01a",
              "2607:9000:b00:31::c01b",
              "2607:9000:b00:31::c01c",
              "2607:9000:b00:31::c01d",
              "2607:9000:b00:31::c01e",
              "2607:9000:b00:31::c01f"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "us-dal-wg-701.blockerad.eu"
          }
        }
      },
      {
        "hostname": "us-dal-wg-702",
        "location": "us-dal",
        "active": true,
        "owned": false,
        "provider": "Tzulo",
        "stboot": true,
        "ipv4_addr_in": "23.234.104.127",
        "include_in_country": true,
        "weight": 100,
        "public_key": "UNyJnd4U9T7P+v1/NZzIBPMl83+maIY+J9NWTP0bskc=",
        "ipv6_addr_in": "2607:9000:b00:32::f001",
        "shadowsocks_extra_addr_in": [
          "23.234.104.130",
          "23.234.104.131",
          "23.234.104.132",
          "23.234.104.133",
          "23.234.104.134",
          "23.234.104.135",
          "23.234.104.136",
          "23.234.104.137",
          "23.234.104.138",
          "23.234.104.139",
          "23.234.104.140",
          "23.234.104.141",
          "23.234.104.142",
          "23.234.104.143",
          "23.234.104.144",
          "2607:9000:b00:31::b002",
          "2607:9000:b00:31::b003",
          "2607:9000:b00:31::b004",
          "2607:9000:b00:31::b005",
          "2607:9000:b00:31::b006",
          "2607:9000:b00:31::b007",
          "2607:9000:b00:31::b008",
          "2607:9000:b00:31::b009",
          "2607:9000:b00:31::b00a",
          "2607:9000:b00:31::b00b",
          "2607:9000:b00:31::b00c",
          "2607:9000:b00:31::b00d",
          "2607:9000:b00:31::b00e",
          "2607:9000:b00:31::b00f",
          "2607:9000:b00:31::b010",
          "2607:9000:b00:31::b011",
          "2607:9000:b00:31::b012",
          "2607:9000:b00:31::b013",
          "2607:9000:b00:31::b014",
          "2607:9000:b00:31::b015",
          "2607:9000:b00:31::b016",
          "2607:9000:b00:31::b017",
          "2607:9000:b00:31::b018",
          "2607:9000:b00:31::b019",
          "2607:9000:b00:31::b01a",
          "2607:9000:b00:31::b01b",
          "2607:9000:b00:31::b01c",
          "2607:9000:b00:31::b01d",
          "2607:9000:b00:31::b01e",
          "2607:9000:b00:31::b01f"
        ],
        "features": {
          "lwo": {},
          "quic": {
            "addr_in": [
              "23.234.104.145",
              "23.234.104.146",
              "23.234.104.147",
              "23.234.104.148",
              "23.234.104.149",
              "23.234.104.150",
              "23.234.104.151",
              "23.234.104.152",
              "23.234.104.153",
              "23.234.104.154",
              "23.234.104.155",
              "23.234.104.156",
              "23.234.104.157",
              "23.234.104.158",
              "23.234.104.159",
              "2607:9000:b00:31::c002",
              "2607:9000:b00:31::c003",
              "2607:9000:b00:31::c004",
              "2607:9000:b00:31::c005",
              "2607:9000:b00:31::c006",
              "2607:9000:b00:31::c007",
              "2607:9000:b00:31::c008",
              "2607:9000:b00:31::c009",
              "2607:9000:b00:31::c00a",
              "2607:9000:b00:31::c00b",
              "2607:9000:b00:31::c00c",
              "2607:9000:b00:31::c00d",
              "2607:9000:b00:31::c00e",
              "2607:9000:b00:31::c00f",
              "2607:9000:b00:31::c010",
              "2607:9000:b00:31::c011",
              "2607:9000:b00:31::c012",
              "2607:9000:b00:31::c013",
              "2607:9000:b00:31::c014",
              "2607:9000:b00:31::c015",
              "2607:9000:b00:31::c016",
              "2607:9000:b00:31::c017",
              "2607:9000:b00:31::c018",
              "2607:9000:b00:31::c019",
              "2607:9000:b00:31::c01a",
              "2607:9000:b00:31::c01b",
              "2607:9000:b00:31::c01c",
              "2607:9000:b00:31::c01d",
              "2607:9000:b00:31::c01e",
              "2607:9000:b00:31::c01f"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "us-dal-wg-702.blockerad.eu"
          }
        }
      },
      {
        "hostname": "us-dal-wg-703",
        "location": "us-dal",
        "active": true,
        "owned": false,
        "provider": "Tzulo",
        "stboot": true,
        "ipv4_addr_in": "23.234.105.2",
        "include_in_country": true,
        "weight": 100,
        "public_key": "A+PTuYy2zuYfHcKs9VZU7bgXSC0/PNndLuUD6xxgaRQ=",
        "ipv6_addr_in": "2607:9000:b00:33::f001",
        "shadowsocks_extra_addr_in": [
          "23.234.105.5",
          "23.234.105.6",
          "23.234.105.7",
          "23.234.105.8",
          "23.234.105.9",
          "23.234.105.10",
          "23.234.105.11",
          "23.234.105.12",
          "23.234.105.13",
          "23.234.105.14",
          "23.234.105.15",
          "23.234.105.16",
          "23.234.105.17",
          "23.234.105.18",
          "23.234.105.19",
          "2607:9000:b00:33::b002",
          "2607:9000:b00:33::b003",
          "2607:9000:b00:33::b004",
          "2607:9000:b00:33::b005",
          "2607:9000:b00:33::b006",
          "2607:9000:b00:33::b007",
          "2607:9000:b00:33::b008",
          "2607:9000:b00:33::b009",
          "2607:9000:b00:33::b00a",
          "2607:9000:b00:33::b00b",
          "2607:9000:b00:33::b00c",
          "2607:9000:b00:33::b00d",
          "2607:9000:b00:33::b00e",
          "2607:9000:b00:33::b00f",
          "2607:9000:b00:33::b010",
          "2607:9000:b00:33::b011",
          "2607:9000:b00:33::b012",
          "2607:9000:b00:33::b013",
          "2607:9000:b00:33::b014",
          "2607:9000:b00:33::b015",
          "2607:9000:b00:33::b016",
          "2607:9000:b00:33::b017",
          "2607:9000:b00:33::b018",
          "2607:9000:b00:33::b019",
          "2607:9000:b00:33::b01a",
          "2607:9000:b00:33::b01b",
          "2607:9000:b00:33::b01c",
          "2607:9000:b00:33::b01d",
          "2607:9000:b00:33::b01e",
          "2607:9000:b00:33::b01f"
        ],
        "features": {
          "lwo": {},
          "quic": {
            "addr_in": [
              "23.234.105.20",
              "23.234.105.21",
              "23.234.105.22",
              "23.234.105.23",
              "23.234.105.24",
              "23.234.105.25",
              "23.234.105.26",
              "23.234.105.27",
              "23.234.105.28",
              "23.234.105.29",
              "23.234.105.30",
              "23.234.105.31",
              "23.234.105.32",
              "23.234.105.33",
              "23.234.105.34",
              "2607:9000:b00:33::c002",
              "2607:9000:b00:33::c003",
              "2607:9000:b00:33::c004",
              "2607:9000:b00:33::c005",
              "2607:9000:b00:33::c006",
              "2607:9000:b00:33::c007",
              "2607:9000:b00:33::c008",
              "2607:9000:b00:33::c009",
              "2607:9000:b00:33::c00a",
              "2607:9000:b00:33::c00b",
              "2607:9000:b00:33::c00c",
              "2607:9000:b00:33::c00d",
              "2607:9000:b00:33::c00e",
              "2607:9000:b00:33::c00f",
              "2607:9000:b00:33::c010",
              "2607:9000:b00:33::c011",
              "2607:9000:b00:33::c012",
              "2607:9000:b00:33::c013",
              "2607:9000:b00:33::c014",
              "2607:9000:b00:33::c015",
              "2607:9000:b00:33::c016",
              "2607:9000:b00:33::c017",
              "2607:9000:b00:33::c018",
              "2607:9000:b00:33::c019",
              "2607:9000:b00:33::c01a",
              "2607:9000:b00:33::c01b",
              "2607:9000:b00:33::c01c",
              "2607:9000:b00:33::c01d",
              "2607:9000:b00:33::c01e",
              "2607:9000:b00:33::c01f"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "us-dal-wg-703.blockerad.eu"
          }
        }
      },
      {
        "hostname": "us-dal-wg-704",
        "location": "us-dal",
        "active": true,
        "owned": false,
        "provider": "Tzulo",
        "stboot": true,
        "ipv4_addr_in": "23.234.105.127",
        "include_in_country": true,
        "weight": 100,
        "public_key": "DlDMRNqq5oppRQaCWz8XKAccxtjCW2jSjBWGdY77BQw=",
        "ipv6_addr_in": "2607:9000:b00:34::f001",
        "shadowsocks_extra_addr_in": [
          "23.234.105.130",
          "23.234.105.131",
          "23.234.105.132",
          "23.234.105.133",
          "23.234.105.134",
          "23.234.105.135",
          "23.234.105.136",
          "23.234.105.137",
          "23.234.105.138",
          "23.234.105.139",
          "23.234.105.140",
          "23.234.105.141",
          "23.234.105.142",
          "23.234.105.143",
          "23.234.105.144",
          "2607:9000:b00:34::b002",
          "2607:9000:b00:34::b003",
          "2607:9000:b00:34::b004",
          "2607:9000:b00:34::b005",
          "2607:9000:b00:34::b006",
          "2607:9000:b00:34::b007",
          "2607:9000:b00:34::b008",
          "2607:9000:b00:34::b009",
          "2607:9000:b00:34::b00a",
          "2607:9000:b00:34::b00b",
          "2607:9000:b00:34::b00c",
          "2607:9000:b00:34::b00d",
          "2607:9000:b00:34::b00e",
          "2607:9000:b00:34::b00f",
          "2607:9000:b00:34::b010",
          "2607:9000:b00:34::b011",
          "2607:9000:b00:34::b012",
          "2607:9000:b00:34::b013",
          "2607:9000:b00:34::b014",
          "2607:9000:b00:34::b015",
          "2607:9000:b00:34::b016",
          "2607:9000:b00:34::b017",
          "2607:9000:b00:34::b018",
          "2607:9000:b00:34::b019",
          "2607:9000:b00:34::b01a",
          "2607:9000:b00:34::b01b",
          "2607:9000:b00:34::b01c",
          "2607:9000:b00:34::b01d",
          "2607:9000:b00:34::b01e",
          "2607:9000:b00:34::b01f"
        ],
        "features": {
          "lwo": {},
          "quic": {
            "addr_in": [
              "23.234.105.145",
              "23.234.105.146",
              "23.234.105.147",
              "23.234.105.148",
              "23.234.105.149",
              "23.234.105.150",
              "23.234.105.151",
              "23.234.105.152",
              "23.234.105.153",
              "23.234.105.154",
              "23.234.105.155",
              "23.234.105.156",
              "23.234.105.157",
              "23.234.105.158",
              "23.234.105.159",
              "2607:9000:b00:34::c002",
              "2607:9000:b00:34::c003",
              "2607:9000:b00:34::c004",
              "2607:9000:b00:34::c005",
              "2607:9000:b00:34::c006",
              "2607:9000:b00:34::c007",
              "2607:9000:b00:34::c008",
              "2607:9000:b00:34::c009",
              "2607:9000:b00:34::c00a",
              "2607:9000:b00:34::c00b",
              "2607:9000:b00:34::c00c",
              "2607:9000:b00:34::c00d",
              "2607:9000:b00:34::c00e",
              "2607:9000:b00:34::c00f",
              "2607:9000:b00:34::c010",
              "2607:9000:b00:34::c011",
              "2607:9000:b00:34::c012",
              "2607:9000:b00:34::c013",
              "2607:9000:b00:34::c014",
              "2607:9000:b00:34::c015",
              "2607:9000:b00:34::c016",
              "2607:9000:b00:34::c017",
              "2607:9000:b00:34::c018",
              "2607:9000:b00:34::c019",
              "2607:9000:b00:34::c01a",
              "2607:9000:b00:34::c01b",
              "2607:9000:b00:34::c01c",
              "2607:9000:b00:34::c01d",
              "2607:9000:b00:34::c01e",
              "2607:9000:b00:34::c01f"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "us-dal-wg-704.blockerad.eu"
          }
        }
      },
      {
        "hostname": "us-dal-wg-705",
        "location": "us-dal",
        "active": true,
        "owned": false,
        "provider": "Tzulo",
        "stboot": true,
        "ipv4_addr_in": "23.234.106.2",
        "include_in_country": true,
        "weight": 100,
        "public_key": "vaI2uM3xjXYxvtWMkAwRwuWMI/vlJNxsfwTAILvUNHM=",
        "ipv6_addr_in": "2607:9000:b00:35::f001",
        "shadowsocks_extra_addr_in": [
          "23.234.106.5",
          "23.234.106.6",
          "23.234.106.7",
          "23.234.106.8",
          "23.234.106.9",
          "23.234.106.10",
          "23.234.106.11",
          "23.234.106.12",
          "23.234.106.13",
          "23.234.106.14",
          "23.234.106.15",
          "23.234.106.16",
          "23.234.106.17",
          "23.234.106.18",
          "23.234.106.19",
          "2607:9000:b00:35::b002",
          "2607:9000:b00:35::b003",
          "2607:9000:b00:35::b004",
          "2607:9000:b00:35::b005",
          "2607:9000:b00:35::b006",
          "2607:9000:b00:35::b007",
          "2607:9000:b00:35::b008",
          "2607:9000:b00:35::b009",
          "2607:9000:b00:35::b00a",
          "2607:9000:b00:35::b00b",
          "2607:9000:b00:35::b00c",
          "2607:9000:b00:35::b00d",
          "2607:9000:b00:35::b00e",
          "2607:9000:b00:35::b00f",
          "2607:9000:b00:35::b010",
          "2607:9000:b00:35::b011",
          "2607:9000:b00:35::b012",
          "2607:9000:b00:35::b013",
          "2607:9000:b00:35::b014",
          "2607:9000:b00:35::b015",
          "2607:9000:b00:35::b016",
          "2607:9000:b00:35::b017",
          "2607:9000:b00:35::b018",
          "2607:9000:b00:35::b019",
          "2607:9000:b00:35::b01a",
          "2607:9000:b00:35::b01b",
          "2607:9000:b00:35::b01c",
          "2607:9000:b00:35::b01d",
          "2607:9000:b00:35::b01e",
          "2607:9000:b00:35::b01f"
        ],
        "features": {
          "quic": {
            "addr_in": [
              "23.234.106.20",
              "23.234.106.21",
              "23.234.106.22",
              "23.234.106.23",
              "23.234.106.24",
              "23.234.106.25",
              "23.234.106.26",
              "23.234.106.27",
              "23.234.106.28",
              "23.234.106.29",
              "23.234.106.30",
              "23.234.106.31",
              "23.234.106.32",
              "23.234.106.33",
              "23.234.106.34",
              "2607:9000:b00:35::c002",
              "2607:9000:b00:35::c003",
              "2607:9000:b00:35::c004",
              "2607:9000:b00:35::c005",
              "2607:9000:b00:35::c006",
              "2607:9000:b00:35::c007",
              "2607:9000:b00:35::c008",
              "2607:9000:b00:35::c009",
              "2607:9000:b00:35::c00a",
              "2607:9000:b00:35::c00b",
              "2607:9000:b00:35::c00c",
              "2607:9000:b00:35::c00d",
              "2607:9000:b00:35::c00e",
              "2607:9000:b00:35::c00f",
              "2607:9000:b00:35::c010",
              "2607:9000:b00:35::c011",
              "2607:9000:b00:35::c012",
              "2607:9000:b00:35::c013",
              "2607:9000:b00:35::c014",
              "2607:9000:b00:35::c015",
              "2607:9000:b00:35::c016",
              "2607:9000:b00:35::c017",
              "2607:9000:b00:35::c018",
              "2607:9000:b00:35::c019",
              "2607:9000:b00:35::c01a",
              "2607:9000:b00:35::c01b",
              "2607:9000:b00:35::c01c",
              "2607:9000:b00:35::c01d",
              "2607:9000:b00:35::c01e",
              "2607:9000:b00:35::c01f"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "us-dal-wg-705.blockerad.eu"
          }
        }
      },
      {
        "hostname": "us-dal-wg-706",
        "location": "us-dal",
        "active": true,
        "owned": false,
        "provider": "Tzulo",
        "stboot": true,
        "ipv4_addr_in": "23.234.106.127",
        "include_in_country": true,
        "weight": 100,
        "public_key": "vO4TIJsyvNnSH+m9iwoM1BLJokFa80YsCpMjnC8FMzc=",
        "ipv6_addr_in": "2607:9000:b00:36::f001",
        "shadowsocks_extra_addr_in": [
          "23.234.106.130",
          "23.234.106.131",
          "23.234.106.132",
          "23.234.106.133",
          "23.234.106.134",
          "23.234.106.135",
          "23.234.106.136",
          "23.234.106.137",
          "23.234.106.138",
          "23.234.106.139",
          "23.234.106.140",
          "23.234.106.141",
          "23.234.106.142",
          "23.234.106.143",
          "23.234.106.144",
          "2607:9000:b00:36::b002",
          "2607:9000:b00:36::b003",
          "2607:9000:b00:36::b004",
          "2607:9000:b00:36::b005",
          "2607:9000:b00:36::b006",
          "2607:9000:b00:36::b007",
          "2607:9000:b00:36::b008",
          "2607:9000:b00:36::b009",
          "2607:9000:b00:36::b00a",
          "2607:9000:b00:36::b00b",
          "2607:9000:b00:36::b00c",
          "2607:9000:b00:36::b00d",
          "2607:9000:b00:36::b00e",
          "2607:9000:b00:36::b00f",
          "2607:9000:b00:36::b010",
          "2607:9000:b00:36::b011",
          "2607:9000:b00:36::b012",
          "2607:9000:b00:36::b013",
          "2607:9000:b00:36::b014",
          "2607:9000:b00:36::b015",
          "2607:9000:b00:36::b016",
          "2607:9000:b00:36::b017",
          "2607:9000:b00:36::b018",
          "2607:9000:b00:36::b019",
          "2607:9000:b00:36::b01a",
          "2607:9000:b00:36::b01b",
          "2607:9000:b00:36::b01c",
          "2607:9000:b00:36::b01d",
          "2607:9000:b00:36::b01e",
          "2607:9000:b00:36::b01f"
        ],
        "features": {
          "quic": {
            "addr_in": [
              "23.234.106.145",
              "23.234.106.146",
              "23.234.106.147",
              "23.234.106.148",
              "23.234.106.149",
              "23.234.106.150",
              "23.234.106.151",
              "23.234.106.152",
              "23.234.106.153",
              "23.234.106.154",
              "23.234.106.155",
              "23.234.106.156",
              "23.234.106.157",
              "23.234.106.158",
              "23.234.106.159",
              "2607:9000:b00:36::c002",
              "2607:9000:b00:36::c003",
              "2607:9000:b00:36::c004",
              "2607:9000:b00:36::c005",
              "2607:9000:b00:36::c006",
              "2607:9000:b00:36::c007",
              "2607:9000:b00:36::c008",
              "2607:9000:b00:36::c009",
              "2607:9000:b00:36::c00a",
              "2607:9000:b00:36::c00b",
              "2607:9000:b00:36::c00c",
              "2607:9000:b00:36::c00d",
              "2607:9000:b00:36::c00e",
              "2607:9000:b00:36::c00f",
              "2607:9000:b00:36::c010",
              "2607:9000:b00:36::c011",
              "2607:9000:b00:36::c012",
              "2607:9000:b00:36::c013",
              "2607:9000:b00:36::c014",
              "2607:9000:b00:36::c015",
              "2607:9000:b00:36::c016",
              "2607:9000:b00:36::c017",
              "2607:9000:b00:36::c018",
              "2607:9000:b00:36::c019",
              "2607:9000:b00:36::c01a",
              "2607:9000:b00:36::c01b",
              "2607:9000:b00:36::c01c",
              "2607:9000:b00:36::c01d",
              "2607:9000:b00:36::c01e",
              "2607:9000:b00:36::c01f"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "us-dal-wg-706.blockerad.eu"
          }
        }
      },
      {
        "hostname": "us-dal-wg-707",
        "location": "us-dal",
        "active": true,
        "owned": false,
        "provider": "Tzulo",
        "stboot": true,
        "ipv4_addr_in": "23.234.107.2",
        "include_in_country": true,
        "weight": 100,
        "public_key": "MnFc+hUAUSIID/PykPuUPoYlMbRBbFkGK1nIlHSeJEs=",
        "ipv6_addr_in": "2607:9000:b00:37::f001",
        "shadowsocks_extra_addr_in": [
          "23.234.107.5",
          "23.234.107.6",
          "23.234.107.7",
          "23.234.107.8",
          "23.234.107.9",
          "23.234.107.10",
          "23.234.107.11",
          "23.234.107.12",
          "23.234.107.13",
          "23.234.107.14",
          "23.234.107.15",
          "23.234.107.16",
          "23.234.107.17",
          "23.234.107.18",
          "23.234.107.19",
          "2607:9000:b00:37::b002",
          "2607:9000:b00:37::b003",
          "2607:9000:b00:37::b004",
          "2607:9000:b00:37::b005",
          "2607:9000:b00:37::b006",
          "2607:9000:b00:37::b007",
          "2607:9000:b00:37::b008",
          "2607:9000:b00:37::b009",
          "2607:9000:b00:37::b00a",
          "2607:9000:b00:37::b00b",
          "2607:9000:b00:37::b00c",
          "2607:9000:b00:37::b00d",
          "2607:9000:b00:37::b00e",
          "2607:9000:b00:37::b00f",
          "2607:9000:b00:37::b010",
          "2607:9000:b00:37::b011",
          "2607:9000:b00:37::b012",
          "2607:9000:b00:37::b013",
          "2607:9000:b00:37::b014",
          "2607:9000:b00:37::b015",
          "2607:9000:b00:37::b016",
          "2607:9000:b00:37::b017",
          "2607:9000:b00:37::b018",
          "2607:9000:b00:37::b019",
          "2607:9000:b00:37::b01a",
          "2607:9000:b00:37::b01b",
          "2607:9000:b00:37::b01c",
          "2607:9000:b00:37::b01d",
          "2607:9000:b00:37::b01e",
          "2607:9000:b00:37::b01f"
        ],
        "features": {
          "quic": {
            "addr_in": [
              "23.234.107.20",
              "23.234.107.21",
              "23.234.107.22",
              "23.234.107.23",
              "23.234.107.24",
              "23.234.107.25",
              "23.234.107.26",
              "23.234.107.27",
              "23.234.107.28",
              "23.234.107.29",
              "23.234.107.30",
              "23.234.107.31",
              "23.234.107.32",
              "23.234.107.33",
              "23.234.107.34",
              "2607:9000:b00:37::c002",
              "2607:9000:b00:37::c003",
              "2607:9000:b00:37::c004",
              "2607:9000:b00:37::c005",
              "2607:9000:b00:37::c006",
              "2607:9000:b00:37::c007",
              "2607:9000:b00:37::c008",
              "2607:9000:b00:37::c009",
              "2607:9000:b00:37::c00a",
              "2607:9000:b00:37::c00b",
              "2607:9000:b00:37::c00c",
              "2607:9000:b00:37::c00d",
              "2607:9000:b00:37::c00e",
              "2607:9000:b00:37::c00f",
              "2607:9000:b00:37::c010",
              "2607:9000:b00:37::c011",
              "2607:9000:b00:37::c012",
              "2607:9000:b00:37::c013",
              "2607:9000:b00:37::c014",
              "2607:9000:b00:37::c015",
              "2607:9000:b00:37::c016",
              "2607:9000:b00:37::c017",
              "2607:9000:b00:37::c018",
              "2607:9000:b00:37::c019",
              "2607:9000:b00:37::c01a",
              "2607:9000:b00:37::c01b",
              "2607:9000:b00:37::c01c",
              "2607:9000:b00:37::c01d",
              "2607:9000:b00:37::c01e",
              "2607:9000:b00:37::c01f"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "us-dal-wg-707.blockerad.eu"
          }
        }
      },
      {
        "hostname": "us-dal-wg-708",
        "location": "us-dal",
        "active": true,
        "owned": false,
        "provider": "Tzulo",
        "stboot": true,
        "ipv4_addr_in": "23.234.107.127",
        "include_in_country": true,
        "weight": 100,
        "public_key": "I8b0Y+odQGMzuMQi+P2fbZF+FiR3rmyZsAc1SIGzNUo=",
        "ipv6_addr_in": "2607:9000:b00:38::f001",
        "shadowsocks_extra_addr_in": [
          "23.234.107.130",
          "23.234.107.131",
          "23.234.107.132",
          "23.234.107.133",
          "23.234.107.134",
          "23.234.107.135",
          "23.234.107.136",
          "23.234.107.137",
          "23.234.107.138",
          "23.234.107.139",
          "23.234.107.140",
          "23.234.107.141",
          "23.234.107.142",
          "23.234.107.143",
          "23.234.107.144",
          "2607:9000:b00:38::b002",
          "2607:9000:b00:38::b003",
          "2607:9000:b00:38::b004",
          "2607:9000:b00:38::b005",
          "2607:9000:b00:38::b006",
          "2607:9000:b00:38::b007",
          "2607:9000:b00:38::b008",
          "2607:9000:b00:38::b009",
          "2607:9000:b00:38::b00a",
          "2607:9000:b00:38::b00b",
          "2607:9000:b00:38::b00c",
          "2607:9000:b00:38::b00d",
          "2607:9000:b00:38::b00e",
          "2607:9000:b00:38::b00f",
          "2607:9000:b00:38::b010",
          "2607:9000:b00:38::b011",
          "2607:9000:b00:38::b012",
          "2607:9000:b00:38::b013",
          "2607:9000:b00:38::b014",
          "2607:9000:b00:38::b015",
          "2607:9000:b00:38::b016",
          "2607:9000:b00:38::b017",
          "2607:9000:b00:38::b018",
          "2607:9000:b00:38::b019",
          "2607:9000:b00:38::b01a",
          "2607:9000:b00:38::b01b",
          "2607:9000:b00:38::b01c",
          "2607:9000:b00:38::b01d",
          "2607:9000:b00:38::b01e",
          "2607:9000:b00:38::b01f"
        ],
        "features": {
          "quic": {
            "addr_in": [
              "23.234.107.145",
              "23.234.107.146",
              "23.234.107.147",
              "23.234.107.148",
              "23.234.107.149",
              "23.234.107.150",
              "23.234.107.151",
              "23.234.107.152",
              "23.234.107.153",
              "23.234.107.154",
              "23.234.107.155",
              "23.234.107.156",
              "23.234.107.157",
              "23.234.107.158",
              "23.234.107.159",
              "2607:9000:b00:38::c002",
              "2607:9000:b00:38::c003",
              "2607:9000:b00:38::c004",
              "2607:9000:b00:38::c005",
              "2607:9000:b00:38::c006",
              "2607:9000:b00:38::c007",
              "2607:9000:b00:38::c008",
              "2607:9000:b00:38::c009",
              "2607:9000:b00:38::c00a",
              "2607:9000:b00:38::c00b",
              "2607:9000:b00:38::c00c",
              "2607:9000:b00:38::c00d",
              "2607:9000:b00:38::c00e",
              "2607:9000:b00:38::c00f",
              "2607:9000:b00:38::c010",
              "2607:9000:b00:38::c011",
              "2607:9000:b00:38::c012",
              "2607:9000:b00:38::c013",
              "2607:9000:b00:38::c014",
              "2607:9000:b00:38::c015",
              "2607:9000:b00:38::c016",
              "2607:9000:b00:38::c017",
              "2607:9000:b00:38::c018",
              "2607:9000:b00:38::c019",
              "2607:9000:b00:38::c01a",
              "2607:9000:b00:38::c01b",
              "2607:9000:b00:38::c01c",
              "2607:9000:b00:38::c01d",
              "2607:9000:b00:38::c01e",
              "2607:9000:b00:38::c01f"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "us-dal-wg-708.blockerad.eu"
          }
        }
      },
      {
        "hostname": "us-den-wg-101",
        "location": "us-den",
        "active": true,
        "owned": false,
        "provider": "DataPacket",
        "stboot": true,
        "ipv4_addr_in": "37.19.210.1",
        "include_in_country": true,
        "weight": 100,
        "public_key": "74U+9EQrMwVOafgXuSp8eaKG0+p4zjSsDe3J7+ojhx0=",
        "ipv6_addr_in": "2a02:6ea0:d70a::b57f"
      },
      {
        "hostname": "us-den-wg-102",
        "location": "us-den",
        "active": true,
        "owned": false,
        "provider": "DataPacket",
        "stboot": true,
        "ipv4_addr_in": "37.19.210.14",
        "include_in_country": true,
        "weight": 100,
        "public_key": "T44stCRbQXFCBCcpdDbZPlNHp2eZEi91ooyk0JDC21E=",
        "ipv6_addr_in": "2a02:6ea0:d70a:1::b58f"
      },
      {
        "hostname": "us-den-wg-103",
        "location": "us-den",
        "active": true,
        "owned": false,
        "provider": "DataPacket",
        "stboot": true,
        "ipv4_addr_in": "37.19.210.27",
        "include_in_country": true,
        "weight": 100,
        "public_key": "Az+PGHQ0xFElmRBv+PKZuRnEzKPrPtUpRD3vpxb4si4=",
        "ipv6_addr_in": "2a02:6ea0:d70a:2::b59f"
      },
      {
        "hostname": "us-den-wg-201",
        "location": "us-den",
        "active": true,
        "owned": false,
        "provider": "Tzulo",
        "stboot": true,
        "ipv4_addr_in": "23.234.68.2",
        "include_in_country": true,
        "weight": 0,
        "public_key": "MsF1hhYtyCsvPt4B8f48biVcVYd692STflhcbKwTGAw=",
        "ipv6_addr_in": "2607:9000:2000:41::f001",
        "daita": true,
        "shadowsocks_extra_addr_in": [
          "23.234.68.13"
        ],
        "features": {
          "daita": {}
        }
      },
      {
        "hostname": "us-den-wg-202",
        "location": "us-den",
        "active": true,
        "owned": false,
        "provider": "Tzulo",
        "stboot": true,
        "ipv4_addr_in": "23.234.68.127",
        "include_in_country": true,
        "weight": 0,
        "public_key": "YP20qT+/cY/sbBhlXo6fWZlfVhRU+emQlZ1am+vUNnw=",
        "ipv6_addr_in": "2607:9000:2000:42::f001",
        "shadowsocks_extra_addr_in": [
          "23.234.68.138"
        ],
        "features": {
          "lwo": {}
        }
      },
      {
        "hostname": "us-den-wg-203",
        "location": "us-den",
        "active": true,
        "owned": false,
        "provider": "Tzulo",
        "stboot": true,
        "ipv4_addr_in": "23.234.69.2",
        "include_in_country": true,
        "weight": 0,
        "public_key": "D8TSWEfmRIm1qMS0RgO8uireFMMZCMi+XxhIJ2jPBEU=",
        "ipv6_addr_in": "2607:9000:2000:43::f001",
        "shadowsocks_extra_addr_in": [
          "23.234.69.13"
        ],
        "features": {
          "lwo": {}
        }
      },
      {
        "hostname": "us-den-wg-204",
        "location": "us-den",
        "active": true,
        "owned": false,
        "provider": "Tzulo",
        "stboot": true,
        "ipv4_addr_in": "23.234.69.127",
        "include_in_country": true,
        "weight": 0,
        "public_key": "DZcEpwNSf+6BoDcHknHBVPwAA0ZJjz7DgQ+llATpAzg=",
        "ipv6_addr_in": "2607:9000:2000:44::f001",
        "daita": true,
        "shadowsocks_extra_addr_in": [
          "23.234.69.138"
        ],
        "features": {
          "daita": {}
        }
      },
      {
        "hostname": "us-den-wg-205",
        "location": "us-den",
        "active": true,
        "owned": false,
        "provider": "Tzulo",
        "stboot": true,
        "ipv4_addr_in": "23.234.70.2",
        "include_in_country": true,
        "weight": 0,
        "public_key": "0LQQJLKBZD0Wf0s0nwFfyMW0MMEKoxNPZ14ZbxkogiY=",
        "ipv6_addr_in": "2607:9000:2000:45::f001",
        "shadowsocks_extra_addr_in": [
          "23.234.70.13"
        ]
      },
      {
        "hostname": "us-den-wg-206",
        "location": "us-den",
        "active": true,
        "owned": false,
        "provider": "Tzulo",
        "stboot": true,
        "ipv4_addr_in": "23.234.70.127",
        "include_in_country": true,
        "weight": 0,
        "public_key": "Y4waCBM7GE9iOT+xl9PcZ2mNKGiawEOBv8UkH84CaAo=",
        "ipv6_addr_in": "2607:9000:2000:46::f001",
        "shadowsocks_extra_addr_in": [
          "23.234.70.138"
        ]
      },
      {
        "hostname": "us-den-wg-207",
        "location": "us-den",
        "active": true,
        "owned": false,
        "provider": "Tzulo",
        "stboot": true,
        "ipv4_addr_in": "23.234.71.2",
        "include_in_country": true,
        "weight": 0,
        "public_key": "nUnmeY34CDLjW4Q3TAbJQ168jVXmkY4MVAp28rmpzEc=",
        "ipv6_addr_in": "2607:9000:2000:47::f001",
        "shadowsocks_extra_addr_in": [
          "23.234.71.13"
        ]
      },
      {
        "hostname": "us-den-wg-208",
        "location": "us-den",
        "active": true,
        "owned": false,
        "provider": "Tzulo",
        "stboot": true,
        "ipv4_addr_in": "23.234.71.127",
        "include_in_country": true,
        "weight": 0,
        "public_key": "Fo6J7nLUeSnNPenB1NiPoivVod3m4fN4OE5yjafxYXY=",
        "ipv6_addr_in": "2607:9000:2000:48::f001",
        "shadowsocks_extra_addr_in": [
          "23.234.71.138"
        ]
      },
      {
        "hostname": "us-det-wg-001",
        "location": "us-det",
        "active": true,
        "owned": false,
        "provider": "HostRoyale",
        "stboot": true,
        "ipv4_addr_in": "185.141.119.131",
        "include_in_country": true,
        "weight": 100,
        "public_key": "+USmlxhnLmlNkDnBbu+rXwjUwa383e0ilYEqPkEkNHA=",
        "ipv6_addr_in": "2a06:3040:11:610::f001",
        "features": {
          "lwo": {}
        }
      },
      {
        "hostname": "us-det-wg-002",
        "location": "us-det",
        "active": true,
        "owned": false,
        "provider": "HostRoyale",
        "stboot": true,
        "ipv4_addr_in": "185.141.119.161",
        "include_in_country": true,
        "weight": 100,
        "public_key": "cYqP1UqhOYuaj47e4jAbgL55h52L+ALjtML26OtBvFU=",
        "ipv6_addr_in": "2a06:3040:11:610::f101",
        "features": {
          "lwo": {}
        }
      },
      {
        "hostname": "us-hou-wg-001",
        "location": "us-hou",
        "active": true,
        "owned": false,
        "provider": "DataPacket",
        "stboot": true,
        "ipv4_addr_in": "37.19.221.130",
        "include_in_country": true,
        "weight": 200,
        "public_key": "NKscQ4mm24nsYWfpL85Cve+BKIExR0JaysldUtVSlzg=",
        "ipv6_addr_in": "2a02:6ea0:e001::f001"
      },
      {
        "hostname": "us-hou-wg-002",
        "location": "us-hou",
        "active": true,
        "owned": false,
        "provider": "DataPacket",
        "stboot": true,
        "ipv4_addr_in": "37.19.221.143",
        "include_in_country": true,
        "weight": 200,
        "public_key": "tzSfoiq9ZbCcE5I0Xz9kCrsWksDn0wgvaz9TiHYTmnU=",
        "ipv6_addr_in": "2a02:6ea0:e001:1::f001"
      },
      {
        "hostname": "us-hou-wg-003",
        "location": "us-hou",
        "active": true,
        "owned": false,
        "provider": "DataPacket",
        "stboot": true,
        "ipv4_addr_in": "37.19.221.156",
        "include_in_country": true,
        "weight": 200,
        "public_key": "fNSu30TCgbADxNKACx+5qWY6XGJOga4COmTZZE0k0R4=",
        "ipv6_addr_in": "2a02:6ea0:e001:2::b55f"
      },
      {
        "hostname": "us-hou-wg-004",
        "location": "us-hou",
        "active": true,
        "owned": false,
        "provider": "DataPacket",
        "stboot": true,
        "ipv4_addr_in": "37.19.221.169",
        "include_in_country": true,
        "weight": 200,
        "public_key": "NkZMYUEcHykPkAFdm3dE8l2U9P2mt58Dw6j6BWhzaCc=",
        "ipv6_addr_in": "2a02:6ea0:e001:3::b56f"
      },
      {
        "hostname": "us-lax-wg-001",
        "location": "us-lax",
        "active": true,
        "owned": false,
        "provider": "Tzulo",
        "stboot": true,
        "ipv4_addr_in": "23.234.72.2",
        "include_in_country": true,
        "weight": 100,
        "public_key": "zqsfGglzJPY657WMRxf/S4omG7+ZkSDIpDq+ggbc9yo=",
        "ipv6_addr_in": "2607:9000:300:31::f001",
        "daita": true,
        "shadowsocks_extra_addr_in": [
          "23.234.72.5",
          "23.234.72.6",
          "23.234.72.7",
          "23.234.72.8",
          "23.234.72.9",
          "23.234.72.10",
          "23.234.72.11",
          "23.234.72.12",
          "23.234.72.13",
          "23.234.72.14",
          "23.234.72.15",
          "23.234.72.16",
          "23.234.72.17",
          "23.234.72.18",
          "23.234.72.19",
          "2607:9000:300:31::b002",
          "2607:9000:300:31::b003",
          "2607:9000:300:31::b004",
          "2607:9000:300:31::b005",
          "2607:9000:300:31::b006",
          "2607:9000:300:31::b007",
          "2607:9000:300:31::b008",
          "2607:9000:300:31::b009",
          "2607:9000:300:31::b00a",
          "2607:9000:300:31::b00b",
          "2607:9000:300:31::b00c",
          "2607:9000:300:31::b00d",
          "2607:9000:300:31::b00e",
          "2607:9000:300:31::b00f",
          "2607:9000:300:31::b010",
          "2607:9000:300:31::b011",
          "2607:9000:300:31::b012",
          "2607:9000:300:31::b013",
          "2607:9000:300:31::b014",
          "2607:9000:300:31::b015",
          "2607:9000:300:31::b016",
          "2607:9000:300:31::b017",
          "2607:9000:300:31::b018",
          "2607:9000:300:31::b019",
          "2607:9000:300:31::b01a",
          "2607:9000:300:31::b01b",
          "2607:9000:300:31::b01c",
          "2607:9000:300:31::b01d",
          "2607:9000:300:31::b01e",
          "2607:9000:300:31::b01f"
        ],
        "features": {
          "daita": {},
          "quic": {
            "addr_in": [
              "23.234.72.20",
              "23.234.72.21",
              "23.234.72.22",
              "23.234.72.23",
              "23.234.72.24",
              "23.234.72.25",
              "23.234.72.26",
              "23.234.72.27",
              "23.234.72.28",
              "23.234.72.29",
              "23.234.72.30",
              "23.234.72.31",
              "23.234.72.32",
              "23.234.72.33",
              "23.234.72.34",
              "2607:9000:300:31::c002",
              "2607:9000:300:31::c003",
              "2607:9000:300:31::c004",
              "2607:9000:300:31::c005",
              "2607:9000:300:31::c006",
              "2607:9000:300:31::c007",
              "2607:9000:300:31::c008",
              "2607:9000:300:31::c009",
              "2607:9000:300:31::c00a",
              "2607:9000:300:31::c00b",
              "2607:9000:300:31::c00c",
              "2607:9000:300:31::c00d",
              "2607:9000:300:31::c00e",
              "2607:9000:300:31::c00f",
              "2607:9000:300:31::c010",
              "2607:9000:300:31::c011",
              "2607:9000:300:31::c012",
              "2607:9000:300:31::c013",
              "2607:9000:300:31::c014",
              "2607:9000:300:31::c015",
              "2607:9000:300:31::c016",
              "2607:9000:300:31::c017",
              "2607:9000:300:31::c018",
              "2607:9000:300:31::c019",
              "2607:9000:300:31::c01a",
              "2607:9000:300:31::c01b",
              "2607:9000:300:31::c01c",
              "2607:9000:300:31::c01d",
              "2607:9000:300:31::c01e",
              "2607:9000:300:31::c01f"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "us-lax-wg-001.blockerad.eu"
          }
        }
      },
      {
        "hostname": "us-lax-wg-002",
        "location": "us-lax",
        "active": true,
        "owned": false,
        "provider": "Tzulo",
        "stboot": true,
        "ipv4_addr_in": "23.234.72.127",
        "include_in_country": true,
        "weight": 100,
        "public_key": "sgcr0zSYzfspx4lD38bl3Nb9X7gtJiFLAVE2rqaDjxE=",
        "ipv6_addr_in": "2607:9000:300:32::f001",
        "daita": true,
        "shadowsocks_extra_addr_in": [
          "23.234.72.130",
          "23.234.72.131",
          "23.234.72.132",
          "23.234.72.133",
          "23.234.72.134",
          "23.234.72.135",
          "23.234.72.136",
          "23.234.72.137",
          "23.234.72.138",
          "23.234.72.139",
          "23.234.72.140",
          "23.234.72.141",
          "23.234.72.142",
          "23.234.72.143",
          "23.234.72.144",
          "2607:9000:300:32::b002",
          "2607:9000:300:32::b003",
          "2607:9000:300:32::b004",
          "2607:9000:300:32::b005",
          "2607:9000:300:32::b006",
          "2607:9000:300:32::b007",
          "2607:9000:300:32::b008",
          "2607:9000:300:32::b009",
          "2607:9000:300:32::b00a",
          "2607:9000:300:32::b00b",
          "2607:9000:300:32::b00c",
          "2607:9000:300:32::b00d",
          "2607:9000:300:32::b00e",
          "2607:9000:300:32::b00f",
          "2607:9000:300:32::b010",
          "2607:9000:300:32::b011",
          "2607:9000:300:32::b012",
          "2607:9000:300:32::b013",
          "2607:9000:300:32::b014",
          "2607:9000:300:32::b015",
          "2607:9000:300:32::b016",
          "2607:9000:300:32::b017",
          "2607:9000:300:32::b018",
          "2607:9000:300:32::b019",
          "2607:9000:300:32::b01a",
          "2607:9000:300:32::b01b",
          "2607:9000:300:32::b01c",
          "2607:9000:300:32::b01d",
          "2607:9000:300:32::b01e",
          "2607:9000:300:32::b01f"
        ],
        "features": {
          "daita": {},
          "quic": {
            "addr_in": [
              "23.234.72.145",
              "23.234.72.146",
              "23.234.72.147",
              "23.234.72.148",
              "23.234.72.149",
              "23.234.72.150",
              "23.234.72.151",
              "23.234.72.152",
              "23.234.72.153",
              "23.234.72.154",
              "23.234.72.155",
              "23.234.72.156",
              "23.234.72.157",
              "23.234.72.158",
              "23.234.72.159",
              "2607:9000:300:32::c002",
              "2607:9000:300:32::c003",
              "2607:9000:300:32::c004",
              "2607:9000:300:32::c005",
              "2607:9000:300:32::c006",
              "2607:9000:300:32::c007",
              "2607:9000:300:32::c008",
              "2607:9000:300:32::c009",
              "2607:9000:300:32::c00a",
              "2607:9000:300:32::c00b",
              "2607:9000:300:32::c00c",
              "2607:9000:300:32::c00d",
              "2607:9000:300:32::c00e",
              "2607:9000:300:32::c00f",
              "2607:9000:300:32::c010",
              "2607:9000:300:32::c011",
              "2607:9000:300:32::c012",
              "2607:9000:300:32::c013",
              "2607:9000:300:32::c014",
              "2607:9000:300:32::c015",
              "2607:9000:300:32::c016",
              "2607:9000:300:32::c017",
              "2607:9000:300:32::c018",
              "2607:9000:300:32::c019",
              "2607:9000:300:32::c01a",
              "2607:9000:300:32::c01b",
              "2607:9000:300:32::c01c",
              "2607:9000:300:32::c01d",
              "2607:9000:300:32::c01e",
              "2607:9000:300:32::c01f"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "us-lax-wg-002.blockerad.eu"
          }
        }
      },
      {
        "hostname": "us-lax-wg-003",
        "location": "us-lax",
        "active": true,
        "owned": false,
        "provider": "Tzulo",
        "stboot": true,
        "ipv4_addr_in": "23.234.73.2",
        "include_in_country": true,
        "weight": 100,
        "public_key": "kZkubkNYgzXKAWuF70RA/XGhOxorA4C3Ph3v4t+LThM=",
        "ipv6_addr_in": "2607:9000:300:33::f001",
        "shadowsocks_extra_addr_in": [
          "23.234.73.5",
          "23.234.73.6",
          "23.234.73.7",
          "23.234.73.8",
          "23.234.73.9",
          "23.234.73.10",
          "23.234.73.11",
          "23.234.73.12",
          "23.234.73.13",
          "23.234.73.14",
          "23.234.73.15",
          "23.234.73.16",
          "23.234.73.17",
          "23.234.73.18",
          "23.234.73.19",
          "2607:9000:300:33::b002",
          "2607:9000:300:33::b003",
          "2607:9000:300:33::b004",
          "2607:9000:300:33::b005",
          "2607:9000:300:33::b006",
          "2607:9000:300:33::b007",
          "2607:9000:300:33::b008",
          "2607:9000:300:33::b009",
          "2607:9000:300:33::b00a",
          "2607:9000:300:33::b00b",
          "2607:9000:300:33::b00c",
          "2607:9000:300:33::b00d",
          "2607:9000:300:33::b00e",
          "2607:9000:300:33::b00f",
          "2607:9000:300:33::b010",
          "2607:9000:300:33::b011",
          "2607:9000:300:33::b012",
          "2607:9000:300:33::b013",
          "2607:9000:300:33::b014",
          "2607:9000:300:33::b015",
          "2607:9000:300:33::b016",
          "2607:9000:300:33::b017",
          "2607:9000:300:33::b018",
          "2607:9000:300:33::b019",
          "2607:9000:300:33::b01a",
          "2607:9000:300:33::b01b",
          "2607:9000:300:33::b01c",
          "2607:9000:300:33::b01d",
          "2607:9000:300:33::b01e",
          "2607:9000:300:33::b01f"
        ],
        "features": {
          "quic": {
            "addr_in": [
              "23.234.73.20",
              "23.234.73.21",
              "23.234.73.22",
              "23.234.73.23",
              "23.234.73.24",
              "23.234.73.25",
              "23.234.73.26",
              "23.234.73.27",
              "23.234.73.28",
              "23.234.73.29",
              "23.234.73.30",
              "23.234.73.31",
              "23.234.73.32",
              "23.234.73.33",
              "23.234.73.34",
              "2607:9000:300:33::c002",
              "2607:9000:300:33::c003",
              "2607:9000:300:33::c004",
              "2607:9000:300:33::c005",
              "2607:9000:300:33::c006",
              "2607:9000:300:33::c007",
              "2607:9000:300:33::c008",
              "2607:9000:300:33::c009",
              "2607:9000:300:33::c00a",
              "2607:9000:300:33::c00b",
              "2607:9000:300:33::c00c",
              "2607:9000:300:33::c00d",
              "2607:9000:300:33::c00e",
              "2607:9000:300:33::c00f",
              "2607:9000:300:33::c010",
              "2607:9000:300:33::c011",
              "2607:9000:300:33::c012",
              "2607:9000:300:33::c013",
              "2607:9000:300:33::c014",
              "2607:9000:300:33::c015",
              "2607:9000:300:33::c016",
              "2607:9000:300:33::c017",
              "2607:9000:300:33::c018",
              "2607:9000:300:33::c019",
              "2607:9000:300:33::c01a",
              "2607:9000:300:33::c01b",
              "2607:9000:300:33::c01c",
              "2607:9000:300:33::c01d",
              "2607:9000:300:33::c01e",
              "2607:9000:300:33::c01f"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "us-lax-wg-003.blockerad.eu"
          }
        }
      },
      {
        "hostname": "us-lax-wg-004",
        "location": "us-lax",
        "active": true,
        "owned": false,
        "provider": "Tzulo",
        "stboot": true,
        "ipv4_addr_in": "23.234.73.127",
        "include_in_country": true,
        "weight": 100,
        "public_key": "5E2RphAlOuRZjhDLr5ZfRscrWJST3IkMsxEtbrJsEno=",
        "ipv6_addr_in": "2607:9000:300:34::f001",
        "shadowsocks_extra_addr_in": [
          "23.234.73.130",
          "23.234.73.131",
          "23.234.73.132",
          "23.234.73.133",
          "23.234.73.134",
          "23.234.73.135",
          "23.234.73.136",
          "23.234.73.137",
          "23.234.73.138",
          "23.234.73.139",
          "23.234.73.140",
          "23.234.73.141",
          "23.234.73.142",
          "23.234.73.143",
          "23.234.73.144",
          "2607:9000:300:34::b002",
          "2607:9000:300:34::b003",
          "2607:9000:300:34::b004",
          "2607:9000:300:34::b005",
          "2607:9000:300:34::b006",
          "2607:9000:300:34::b007",
          "2607:9000:300:34::b008",
          "2607:9000:300:34::b009",
          "2607:9000:300:34::b00a",
          "2607:9000:300:34::b00b",
          "2607:9000:300:34::b00c",
          "2607:9000:300:34::b00d",
          "2607:9000:300:34::b00e",
          "2607:9000:300:34::b00f",
          "2607:9000:300:34::b010",
          "2607:9000:300:34::b011",
          "2607:9000:300:34::b012",
          "2607:9000:300:34::b013",
          "2607:9000:300:34::b014",
          "2607:9000:300:34::b015",
          "2607:9000:300:34::b016",
          "2607:9000:300:34::b017",
          "2607:9000:300:34::b018",
          "2607:9000:300:34::b019",
          "2607:9000:300:34::b01a",
          "2607:9000:300:34::b01b",
          "2607:9000:300:34::b01c",
          "2607:9000:300:34::b01d",
          "2607:9000:300:34::b01e",
          "2607:9000:300:34::b01f"
        ],
        "features": {
          "quic": {
            "addr_in": [
              "23.234.73.145",
              "23.234.73.146",
              "23.234.73.147",
              "23.234.73.148",
              "23.234.73.149",
              "23.234.73.150",
              "23.234.73.151",
              "23.234.73.152",
              "23.234.73.153",
              "23.234.73.154",
              "23.234.73.155",
              "23.234.73.156",
              "23.234.73.157",
              "23.234.73.158",
              "23.234.73.159",
              "2607:9000:300:34::c002",
              "2607:9000:300:34::c003",
              "2607:9000:300:34::c004",
              "2607:9000:300:34::c005",
              "2607:9000:300:34::c006",
              "2607:9000:300:34::c007",
              "2607:9000:300:34::c008",
              "2607:9000:300:34::c009",
              "2607:9000:300:34::c00a",
              "2607:9000:300:34::c00b",
              "2607:9000:300:34::c00c",
              "2607:9000:300:34::c00d",
              "2607:9000:300:34::c00e",
              "2607:9000:300:34::c00f",
              "2607:9000:300:34::c010",
              "2607:9000:300:34::c011",
              "2607:9000:300:34::c012",
              "2607:9000:300:34::c013",
              "2607:9000:300:34::c014",
              "2607:9000:300:34::c015",
              "2607:9000:300:34::c016",
              "2607:9000:300:34::c017",
              "2607:9000:300:34::c018",
              "2607:9000:300:34::c019",
              "2607:9000:300:34::c01a",
              "2607:9000:300:34::c01b",
              "2607:9000:300:34::c01c",
              "2607:9000:300:34::c01d",
              "2607:9000:300:34::c01e",
              "2607:9000:300:34::c01f"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "us-lax-wg-004.blockerad.eu"
          }
        }
      },
      {
        "hostname": "us-lax-wg-005",
        "location": "us-lax",
        "active": true,
        "owned": false,
        "provider": "Tzulo",
        "stboot": true,
        "ipv4_addr_in": "23.234.74.2",
        "include_in_country": true,
        "weight": 100,
        "public_key": "U3GkeSnBuP8WmQ90Nw99Q6+lrTbgIsCD2VLpVOkRQhI=",
        "ipv6_addr_in": "2607:9000:300:35::f001",
        "shadowsocks_extra_addr_in": [
          "23.234.74.5",
          "23.234.74.6",
          "23.234.74.7",
          "23.234.74.8",
          "23.234.74.9",
          "23.234.74.10",
          "23.234.74.11",
          "23.234.74.12",
          "23.234.74.13",
          "23.234.74.14",
          "23.234.74.15",
          "23.234.74.16",
          "23.234.74.17",
          "23.234.74.18",
          "23.234.74.19",
          "2607:9000:300:35::b002",
          "2607:9000:300:35::b003",
          "2607:9000:300:35::b004",
          "2607:9000:300:35::b005",
          "2607:9000:300:35::b006",
          "2607:9000:300:35::b007",
          "2607:9000:300:35::b008",
          "2607:9000:300:35::b009",
          "2607:9000:300:35::b00a",
          "2607:9000:300:35::b00b",
          "2607:9000:300:35::b00c",
          "2607:9000:300:35::b00d",
          "2607:9000:300:35::b00e",
          "2607:9000:300:35::b00f",
          "2607:9000:300:35::b010",
          "2607:9000:300:35::b011",
          "2607:9000:300:35::b012",
          "2607:9000:300:35::b013",
          "2607:9000:300:35::b014",
          "2607:9000:300:35::b015",
          "2607:9000:300:35::b016",
          "2607:9000:300:35::b017",
          "2607:9000:300:35::b018",
          "2607:9000:300:35::b019",
          "2607:9000:300:35::b01a",
          "2607:9000:300:35::b01b",
          "2607:9000:300:35::b01c",
          "2607:9000:300:35::b01d",
          "2607:9000:300:35::b01e",
          "2607:9000:300:35::b01f"
        ],
        "features": {
          "lwo": {},
          "quic": {
            "addr_in": [
              "23.234.74.20",
              "23.234.74.21",
              "23.234.74.22",
              "23.234.74.23",
              "23.234.74.24",
              "23.234.74.25",
              "23.234.74.26",
              "23.234.74.27",
              "23.234.74.28",
              "23.234.74.29",
              "23.234.74.30",
              "23.234.74.31",
              "23.234.74.32",
              "23.234.74.33",
              "23.234.74.34",
              "2607:9000:300:35::c002",
              "2607:9000:300:35::c003",
              "2607:9000:300:35::c004",
              "2607:9000:300:35::c005",
              "2607:9000:300:35::c006",
              "2607:9000:300:35::c007",
              "2607:9000:300:35::c008",
              "2607:9000:300:35::c009",
              "2607:9000:300:35::c00a",
              "2607:9000:300:35::c00b",
              "2607:9000:300:35::c00c",
              "2607:9000:300:35::c00d",
              "2607:9000:300:35::c00e",
              "2607:9000:300:35::c00f",
              "2607:9000:300:35::c010",
              "2607:9000:300:35::c011",
              "2607:9000:300:35::c012",
              "2607:9000:300:35::c013",
              "2607:9000:300:35::c014",
              "2607:9000:300:35::c015",
              "2607:9000:300:35::c016",
              "2607:9000:300:35::c017",
              "2607:9000:300:35::c018",
              "2607:9000:300:35::c019",
              "2607:9000:300:35::c01a",
              "2607:9000:300:35::c01b",
              "2607:9000:300:35::c01c",
              "2607:9000:300:35::c01d",
              "2607:9000:300:35::c01e",
              "2607:9000:300:35::c01f"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "us-lax-wg-005.blockerad.eu"
          }
        }
      },
      {
        "hostname": "us-lax-wg-006",
        "location": "us-lax",
        "active": true,
        "owned": false,
        "provider": "Tzulo",
        "stboot": true,
        "ipv4_addr_in": "23.234.74.127",
        "include_in_country": true,
        "weight": 100,
        "public_key": "I8vdSZuJhYHhbidl21oXgiNtnHla9gjgZdm8G5UNKGU=",
        "ipv6_addr_in": "2607:9000:300:36::f001",
        "shadowsocks_extra_addr_in": [
          "23.234.74.130",
          "23.234.74.131",
          "23.234.74.132",
          "23.234.74.133",
          "23.234.74.134",
          "23.234.74.135",
          "23.234.74.136",
          "23.234.74.137",
          "23.234.74.138",
          "23.234.74.139",
          "23.234.74.140",
          "23.234.74.141",
          "23.234.74.142",
          "23.234.74.143",
          "23.234.74.144",
          "2607:9000:300:36::b002",
          "2607:9000:300:36::b003",
          "2607:9000:300:36::b004",
          "2607:9000:300:36::b005",
          "2607:9000:300:36::b006",
          "2607:9000:300:36::b007",
          "2607:9000:300:36::b008",
          "2607:9000:300:36::b009",
          "2607:9000:300:36::b00a",
          "2607:9000:300:36::b00b",
          "2607:9000:300:36::b00c",
          "2607:9000:300:36::b00d",
          "2607:9000:300:36::b00e",
          "2607:9000:300:36::b00f",
          "2607:9000:300:36::b010",
          "2607:9000:300:36::b011",
          "2607:9000:300:36::b012",
          "2607:9000:300:36::b013",
          "2607:9000:300:36::b014",
          "2607:9000:300:36::b015",
          "2607:9000:300:36::b016",
          "2607:9000:300:36::b017",
          "2607:9000:300:36::b018",
          "2607:9000:300:36::b019",
          "2607:9000:300:36::b01a",
          "2607:9000:300:36::b01b",
          "2607:9000:300:36::b01c",
          "2607:9000:300:36::b01d",
          "2607:9000:300:36::b01e",
          "2607:9000:300:36::b01f"
        ],
        "features": {
          "lwo": {},
          "quic": {
            "addr_in": [
              "23.234.74.145",
              "23.234.74.146",
              "23.234.74.147",
              "23.234.74.148",
              "23.234.74.149",
              "23.234.74.150",
              "23.234.74.151",
              "23.234.74.152",
              "23.234.74.153",
              "23.234.74.154",
              "23.234.74.155",
              "23.234.74.156",
              "23.234.74.157",
              "23.234.74.158",
              "23.234.74.159",
              "2607:9000:300:36::c002",
              "2607:9000:300:36::c003",
              "2607:9000:300:36::c004",
              "2607:9000:300:36::c005",
              "2607:9000:300:36::c006",
              "2607:9000:300:36::c007",
              "2607:9000:300:36::c008",
              "2607:9000:300:36::c009",
              "2607:9000:300:36::c00a",
              "2607:9000:300:36::c00b",
              "2607:9000:300:36::c00c",
              "2607:9000:300:36::c00d",
              "2607:9000:300:36::c00e",
              "2607:9000:300:36::c00f",
              "2607:9000:300:36::c010",
              "2607:9000:300:36::c011",
              "2607:9000:300:36::c012",
              "2607:9000:300:36::c013",
              "2607:9000:300:36::c014",
              "2607:9000:300:36::c015",
              "2607:9000:300:36::c016",
              "2607:9000:300:36::c017",
              "2607:9000:300:36::c018",
              "2607:9000:300:36::c019",
              "2607:9000:300:36::c01a",
              "2607:9000:300:36::c01b",
              "2607:9000:300:36::c01c",
              "2607:9000:300:36::c01d",
              "2607:9000:300:36::c01e",
              "2607:9000:300:36::c01f"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "us-lax-wg-006.blockerad.eu"
          }
        }
      },
      {
        "hostname": "us-lax-wg-007",
        "location": "us-lax",
        "active": true,
        "owned": false,
        "provider": "Tzulo",
        "stboot": true,
        "ipv4_addr_in": "23.234.75.2",
        "include_in_country": true,
        "weight": 100,
        "public_key": "7O2meGDMGbd6HXpRQi7ZiuF5l4JQAoV7BejdNgiLZFQ=",
        "ipv6_addr_in": "2607:9000:300:37::f001",
        "shadowsocks_extra_addr_in": [
          "23.234.75.5",
          "23.234.75.6",
          "23.234.75.7",
          "23.234.75.8",
          "23.234.75.9",
          "23.234.75.10",
          "23.234.75.11",
          "23.234.75.12",
          "23.234.75.13",
          "23.234.75.14",
          "23.234.75.15",
          "23.234.75.16",
          "23.234.75.17",
          "23.234.75.18",
          "23.234.75.19",
          "2607:9000:300:37::b002",
          "2607:9000:300:37::b003",
          "2607:9000:300:37::b004",
          "2607:9000:300:37::b005",
          "2607:9000:300:37::b006",
          "2607:9000:300:37::b007",
          "2607:9000:300:37::b008",
          "2607:9000:300:37::b009",
          "2607:9000:300:37::b00a",
          "2607:9000:300:37::b00b",
          "2607:9000:300:37::b00c",
          "2607:9000:300:37::b00d",
          "2607:9000:300:37::b00e",
          "2607:9000:300:37::b00f",
          "2607:9000:300:37::b010",
          "2607:9000:300:37::b011",
          "2607:9000:300:37::b012",
          "2607:9000:300:37::b013",
          "2607:9000:300:37::b014",
          "2607:9000:300:37::b015",
          "2607:9000:300:37::b016",
          "2607:9000:300:37::b017",
          "2607:9000:300:37::b018",
          "2607:9000:300:37::b019",
          "2607:9000:300:37::b01a",
          "2607:9000:300:37::b01b",
          "2607:9000:300:37::b01c",
          "2607:9000:300:37::b01d",
          "2607:9000:300:37::b01e",
          "2607:9000:300:37::b01f"
        ],
        "features": {
          "lwo": {},
          "quic": {
            "addr_in": [
              "23.234.75.20",
              "23.234.75.21",
              "23.234.75.22",
              "23.234.75.23",
              "23.234.75.24",
              "23.234.75.25",
              "23.234.75.26",
              "23.234.75.27",
              "23.234.75.28",
              "23.234.75.29",
              "23.234.75.30",
              "23.234.75.31",
              "23.234.75.32",
              "23.234.75.33",
              "23.234.75.34",
              "2607:9000:300:37::c002",
              "2607:9000:300:37::c003",
              "2607:9000:300:37::c004",
              "2607:9000:300:37::c005",
              "2607:9000:300:37::c006",
              "2607:9000:300:37::c007",
              "2607:9000:300:37::c008",
              "2607:9000:300:37::c009",
              "2607:9000:300:37::c00a",
              "2607:9000:300:37::c00b",
              "2607:9000:300:37::c00c",
              "2607:9000:300:37::c00d",
              "2607:9000:300:37::c00e",
              "2607:9000:300:37::c00f",
              "2607:9000:300:37::c010",
              "2607:9000:300:37::c011",
              "2607:9000:300:37::c012",
              "2607:9000:300:37::c013",
              "2607:9000:300:37::c014",
              "2607:9000:300:37::c015",
              "2607:9000:300:37::c016",
              "2607:9000:300:37::c017",
              "2607:9000:300:37::c018",
              "2607:9000:300:37::c019",
              "2607:9000:300:37::c01a",
              "2607:9000:300:37::c01b",
              "2607:9000:300:37::c01c",
              "2607:9000:300:37::c01d",
              "2607:9000:300:37::c01e",
              "2607:9000:300:37::c01f"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "us-lax-wg-007.blockerad.eu"
          }
        }
      },
      {
        "hostname": "us-lax-wg-008",
        "location": "us-lax",
        "active": true,
        "owned": false,
        "provider": "Tzulo",
        "stboot": true,
        "ipv4_addr_in": "23.234.75.127",
        "include_in_country": true,
        "weight": 100,
        "public_key": "8qtzkafLNGJkfgtuYc8bPeKN0apyyZrZ3Pq4tCkqIxc=",
        "ipv6_addr_in": "2607:9000:300:38::f001",
        "shadowsocks_extra_addr_in": [
          "23.234.75.130",
          "23.234.75.131",
          "23.234.75.132",
          "23.234.75.133",
          "23.234.75.134",
          "23.234.75.135",
          "23.234.75.136",
          "23.234.75.137",
          "23.234.75.138",
          "23.234.75.139",
          "23.234.75.140",
          "23.234.75.141",
          "23.234.75.142",
          "23.234.75.143",
          "23.234.75.144",
          "2607:9000:300:38::b002",
          "2607:9000:300:38::b003",
          "2607:9000:300:38::b004",
          "2607:9000:300:38::b005",
          "2607:9000:300:38::b006",
          "2607:9000:300:38::b007",
          "2607:9000:300:38::b008",
          "2607:9000:300:38::b009",
          "2607:9000:300:38::b00a",
          "2607:9000:300:38::b00b",
          "2607:9000:300:38::b00c",
          "2607:9000:300:38::b00d",
          "2607:9000:300:38::b00e",
          "2607:9000:300:38::b00f",
          "2607:9000:300:38::b010",
          "2607:9000:300:38::b011",
          "2607:9000:300:38::b012",
          "2607:9000:300:38::b013",
          "2607:9000:300:38::b014",
          "2607:9000:300:38::b015",
          "2607:9000:300:38::b016",
          "2607:9000:300:38::b017",
          "2607:9000:300:38::b018",
          "2607:9000:300:38::b019",
          "2607:9000:300:38::b01a",
          "2607:9000:300:38::b01b",
          "2607:9000:300:38::b01c",
          "2607:9000:300:38::b01d",
          "2607:9000:300:38::b01e",
          "2607:9000:300:38::b01f"
        ],
        "features": {
          "lwo": {},
          "quic": {
            "addr_in": [
              "23.234.75.145",
              "23.234.75.146",
              "23.234.75.147",
              "23.234.75.148",
              "23.234.75.149",
              "23.234.75.150",
              "23.234.75.151",
              "23.234.75.152",
              "23.234.75.153",
              "23.234.75.154",
              "23.234.75.155",
              "23.234.75.156",
              "23.234.75.157",
              "23.234.75.158",
              "23.234.75.159",
              "2607:9000:300:38::c002",
              "2607:9000:300:38::c003",
              "2607:9000:300:38::c004",
              "2607:9000:300:38::c005",
              "2607:9000:300:38::c006",
              "2607:9000:300:38::c007",
              "2607:9000:300:38::c008",
              "2607:9000:300:38::c009",
              "2607:9000:300:38::c00a",
              "2607:9000:300:38::c00b",
              "2607:9000:300:38::c00c",
              "2607:9000:300:38::c00d",
              "2607:9000:300:38::c00e",
              "2607:9000:300:38::c00f",
              "2607:9000:300:38::c010",
              "2607:9000:300:38::c011",
              "2607:9000:300:38::c012"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "us-lax-wg-008.blockerad.eu"
          }
        }
      },
      {
        "hostname": "us-lax-wg-201",
        "location": "us-lax",
        "active": true,
        "owned": false,
        "provider": "DataPacket",
        "stboot": true,
        "ipv4_addr_in": "169.150.203.2",
        "include_in_country": false,
        "weight": 100,
        "public_key": "xWobY7DWTL+vL1yD4NWwbQ3V4e8qz10Yz+EFdkIjq0Y=",
        "ipv6_addr_in": "2a02:6ea0:c859:1::a01f"
      },
      {
        "hostname": "us-lax-wg-202",
        "location": "us-lax",
        "active": true,
        "owned": false,
        "provider": "DataPacket",
        "stboot": true,
        "ipv4_addr_in": "169.150.203.15",
        "include_in_country": false,
        "weight": 100,
        "public_key": "SDnciTlujuy2APFTkhzfq5X+LDi+lhfU38wI2HBCxxs=",
        "ipv6_addr_in": "2a02:6ea0:c859:2::a02f"
      },
      {
        "hostname": "us-lax-wg-203",
        "location": "us-lax",
        "active": true,
        "owned": false,
        "provider": "DataPacket",
        "stboot": true,
        "ipv4_addr_in": "169.150.203.28",
        "include_in_country": true,
        "weight": 1,
        "public_key": "W6/Yamxmfx3geWTwwtBbJe/J8UdEzOfa6M+cEpNPIwg=",
        "ipv6_addr_in": "2a02:6ea0:c859:3::a03f",
        "daita": true,
        "features": {
          "daita": {},
          "lwo": {}
        }
      },
      {
        "hostname": "us-lax-wg-402",
        "location": "us-lax",
        "active": true,
        "owned": false,
        "provider": "M247",
        "stboot": true,
        "ipv4_addr_in": "146.70.173.66",
        "include_in_country": false,
        "weight": 100,
        "public_key": "EKZXvHlSDeqAjfC/m9aQR0oXfQ6Idgffa9L0DH5yaCo=",
        "ipv6_addr_in": "2a0d:5600:8:6::d2f",
        "features": {
          "lwo": {}
        }
      },
      {
        "hostname": "us-lax-wg-403",
        "location": "us-lax",
        "active": true,
        "owned": false,
        "provider": "M247",
        "stboot": true,
        "ipv4_addr_in": "146.70.173.130",
        "include_in_country": false,
        "weight": 100,
        "public_key": "mBqaWs6pti93U+1feyj6LRzzveNmeklancn3XuKoPWI=",
        "ipv6_addr_in": "2a0d:5600:8:d::d3f",
        "features": {
          "lwo": {}
        }
      },
      {
        "hostname": "us-lax-wg-404",
        "location": "us-lax",
        "active": true,
        "owned": false,
        "provider": "M247",
        "stboot": true,
        "ipv4_addr_in": "146.70.173.194",
        "include_in_country": false,
        "weight": 100,
        "public_key": "YGl+lj1tk08U9x9Z73zowUW3rk8i0nPmYkxGzNdE4VM=",
        "ipv6_addr_in": "2a0d:5600:8:2f::f001",
        "features": {
          "lwo": {}
        }
      },
      {
        "hostname": "us-lax-wg-405",
        "location": "us-lax",
        "active": true,
        "owned": false,
        "provider": "M247",
        "stboot": true,
        "ipv4_addr_in": "146.70.172.2",
        "include_in_country": false,
        "weight": 100,
        "public_key": "Pe86fNGUd+AIeaabsn7Hk4clQf1kJvxOXPykfVGjeho=",
        "ipv6_addr_in": "2a0d:5600:8:37::f001"
      },
      {
        "hostname": "us-lax-wg-406",
        "location": "us-lax",
        "active": true,
        "owned": false,
        "provider": "M247",
        "stboot": true,
        "ipv4_addr_in": "146.70.174.2",
        "include_in_country": false,
        "weight": 1,
        "public_key": "K3KF3TCWbYcHF5XHL2zaifvQGHrPWoCjFYxDaJO71GA=",
        "ipv6_addr_in": "2a0d:5600:8:3b::f001",
        "features": {
          "lwo": {},
          "quic": {
            "addr_in": [
              "146.70.174.62"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "us-lax-wg-406.blockerad.eu"
          }
        }
      },
      {
        "hostname": "us-lax-wg-407",
        "location": "us-lax",
        "active": true,
        "owned": false,
        "provider": "M247",
        "stboot": true,
        "ipv4_addr_in": "146.70.172.66",
        "include_in_country": true,
        "weight": 100,
        "public_key": "1nGkBr+oLwK5lQcVt9vF6rGM5R3ra5bmYTGJfGIh0lk=",
        "ipv6_addr_in": "2a0d:5600:8:38::f001"
      },
      {
        "hostname": "us-lax-wg-408",
        "location": "us-lax",
        "active": true,
        "owned": false,
        "provider": "M247",
        "stboot": true,
        "ipv4_addr_in": "146.70.172.130",
        "include_in_country": true,
        "weight": 100,
        "public_key": "9L5cW9VuUJUS2gH6H7ln2JeCI66fMnnjLiD5UymAtlo=",
        "ipv6_addr_in": "2a0d:5600:8:39::f001"
      },
      {
        "hostname": "us-lax-wg-409",
        "location": "us-lax",
        "active": true,
        "owned": false,
        "provider": "M247",
        "stboot": true,
        "ipv4_addr_in": "146.70.172.194",
        "include_in_country": true,
        "weight": 100,
        "public_key": "V+LTWA5DxEVITAXqHexqBzeZo95b8r+3WR8g1FsbPQ4=",
        "ipv6_addr_in": "2a0d:5600:8:3a::f001"
      },
      {
        "hostname": "us-lax-wg-601",
        "location": "us-lax",
        "active": true,
        "owned": false,
        "provider": "xtom",
        "stboot": true,
        "ipv4_addr_in": "23.162.40.3",
        "include_in_country": true,
        "weight": 100,
        "public_key": "oA6/33kBggrBOJ7z+uo5gZW6L1w2zYcCILKXXax8knY=",
        "ipv6_addr_in": "2602:fa19::f001",
        "shadowsocks_extra_addr_in": [
          "23.162.40.14"
        ]
      },
      {
        "hostname": "us-lax-wg-602",
        "location": "us-lax",
        "active": true,
        "owned": false,
        "provider": "xtom",
        "stboot": true,
        "ipv4_addr_in": "23.162.40.127",
        "include_in_country": true,
        "weight": 100,
        "public_key": "oLu1H6C8YaoWtmaPzAFboFX8r102Wb1uma9spVPqAX8=",
        "ipv6_addr_in": "2602:fa19::f101",
        "shadowsocks_extra_addr_in": [
          "23.162.40.139"
        ]
      },
      {
        "hostname": "us-lax-wg-603",
        "location": "us-lax",
        "active": true,
        "owned": false,
        "provider": "xtom",
        "stboot": true,
        "ipv4_addr_in": "23.159.216.3",
        "include_in_country": true,
        "weight": 100,
        "public_key": "qeojNB247YQbT0/ysFyZDjs9RJ6Y4bFaKCLu6PjeMxA=",
        "ipv6_addr_in": "2602:fa47::f001",
        "shadowsocks_extra_addr_in": [
          "23.159.216.14"
        ]
      },
      {
        "hostname": "us-lax-wg-604",
        "location": "us-lax",
        "active": true,
        "owned": false,
        "provider": "xtom",
        "stboot": true,
        "ipv4_addr_in": "23.159.216.127",
        "include_in_country": true,
        "weight": 100,
        "public_key": "GKl6nhOl96/1AJtVCdEZpOO6F0BS5/TMkrjdH2fb93A=",
        "ipv6_addr_in": "2602:fa47::f101",
        "shadowsocks_extra_addr_in": [
          "23.159.216.139"
        ]
      },
      {
        "hostname": "us-lax-wg-605",
        "location": "us-lax",
        "active": true,
        "owned": false,
        "provider": "xtom",
        "stboot": true,
        "ipv4_addr_in": "23.160.24.3",
        "include_in_country": true,
        "weight": 100,
        "public_key": "DbZksYqiYPGxOEF7iIaAiyN4+hZc+8HcuMMqpLW3XmA=",
        "ipv6_addr_in": "2602:fa45::f001",
        "shadowsocks_extra_addr_in": [
          "23.160.24.14"
        ]
      },
      {
        "hostname": "us-lax-wg-606",
        "location": "us-lax",
        "active": true,
        "owned": false,
        "provider": "xtom",
        "stboot": true,
        "ipv4_addr_in": "23.160.24.127",
        "include_in_country": true,
        "weight": 100,
        "public_key": "AW1YO/vYtXJioBmD8BhSGpz1DQNIQeU+jOu+3F7KBDY=",
        "ipv6_addr_in": "2602:fa45::f101",
        "shadowsocks_extra_addr_in": [
          "23.160.24.139"
        ]
      },
      {
        "hostname": "us-lax-wg-607",
        "location": "us-lax",
        "active": true,
        "owned": false,
        "provider": "xtom",
        "stboot": true,
        "ipv4_addr_in": "23.168.216.3",
        "include_in_country": true,
        "weight": 100,
        "public_key": "ItEcyDXwTXtq6bQubbO6lY0K/oh0dfk26AV+muU+Ah4=",
        "ipv6_addr_in": "2602:f99d::f001",
        "shadowsocks_extra_addr_in": [
          "23.168.216.14"
        ]
      },
      {
        "hostname": "us-lax-wg-608",
        "location": "us-lax",
        "active": true,
        "owned": false,
        "provider": "xtom",
        "stboot": true,
        "ipv4_addr_in": "23.168.216.127",
        "include_in_country": true,
        "weight": 100,
        "public_key": "ikLR1TUKk+PTWFnydqwZ9m0HaD1dPaMNI9DwZTvzYBs=",
        "ipv6_addr_in": "2602:f99d::f101",
        "shadowsocks_extra_addr_in": [
          "23.168.216.139"
        ]
      },
      {
        "hostname": "us-lax-wg-701",
        "location": "us-lax",
        "active": true,
        "owned": false,
        "provider": "HostRoyale",
        "stboot": true,
        "ipv4_addr_in": "103.251.26.3",
        "include_in_country": true,
        "weight": 100,
        "public_key": "EM/33kdl9RiNOF5jvwtp/nfchPAD/sq7MJleg1bZikU=",
        "ipv6_addr_in": "2a01:4740:3::f001",
        "shadowsocks_extra_addr_in": [
          "103.251.26.14"
        ]
      },
      {
        "hostname": "us-lax-wg-702",
        "location": "us-lax",
        "active": true,
        "owned": false,
        "provider": "HostRoyale",
        "stboot": true,
        "ipv4_addr_in": "103.251.26.127",
        "include_in_country": true,
        "weight": 100,
        "public_key": "ddv7vosBlf396nOa79nWn6qXQu2LzezGXfNUDO3hAXQ=",
        "ipv6_addr_in": "2a01:4740:3::f101",
        "shadowsocks_extra_addr_in": [
          "103.251.26.139"
        ]
      },
      {
        "hostname": "us-lax-wg-703",
        "location": "us-lax",
        "active": true,
        "owned": false,
        "provider": "HostRoyale",
        "stboot": true,
        "ipv4_addr_in": "103.251.27.3",
        "include_in_country": true,
        "weight": 100,
        "public_key": "/FWUNK2WlEQbmwYaXuTzUmtshvIYvJnKWVnuqgzlfXw=",
        "ipv6_addr_in": "2a01:4740:3::f201",
        "shadowsocks_extra_addr_in": [
          "103.251.27.14"
        ]
      },
      {
        "hostname": "us-lax-wg-704",
        "location": "us-lax",
        "active": true,
        "owned": false,
        "provider": "HostRoyale",
        "stboot": true,
        "ipv4_addr_in": "103.251.27.127",
        "include_in_country": true,
        "weight": 100,
        "public_key": "KPjr8jrGP3dVI+GbMq2LNc9eREW6EhGHndoSWHqakxE=",
        "ipv6_addr_in": "2a01:4740:3::f301",
        "shadowsocks_extra_addr_in": [
          "103.251.27.139"
        ]
      },
      {
        "hostname": "us-mia-wg-001",
        "location": "us-mia",
        "active": true,
        "owned": false,
        "provider": "DataPacket",
        "stboot": true,
        "ipv4_addr_in": "45.134.142.219",
        "include_in_country": true,
        "weight": 100,
        "public_key": "FVEKAMJqaJU2AwWn5Mg9TK9IAfJc4XDUmSzEeC/VXGs=",
        "ipv6_addr_in": "2a02:6ea0:cc1f:2::b62f",
        "features": {
          "lwo": {}
        }
      },
      {
        "hostname": "us-mia-wg-002",
        "location": "us-mia",
        "active": true,
        "owned": false,
        "provider": "DataPacket",
        "stboot": true,
        "ipv4_addr_in": "45.134.142.206",
        "include_in_country": true,
        "weight": 200,
        "public_key": "H5t7PsMDnUAHrR8D2Jt3Mh6N6w43WmCzrOHShlEU+zw=",
        "ipv6_addr_in": "2a02:6ea0:cc1f:1::b61f",
        "features": {
          "lwo": {}
        }
      },
      {
        "hostname": "us-mia-wg-003",
        "location": "us-mia",
        "active": true,
        "owned": false,
        "provider": "DataPacket",
        "stboot": true,
        "ipv4_addr_in": "45.134.142.193",
        "include_in_country": true,
        "weight": 200,
        "public_key": "N/3F0QvCuiWWzCwaJmnPZO53LZrKn6sr7rItecrQSQY=",
        "ipv6_addr_in": "2a02:6ea0:cc1f::f001",
        "features": {
          "lwo": {}
        }
      },
      {
        "hostname": "us-mia-wg-101",
        "location": "us-mia",
        "active": true,
        "owned": false,
        "provider": "M247",
        "stboot": true,
        "ipv4_addr_in": "146.70.187.2",
        "include_in_country": true,
        "weight": 100,
        "public_key": "Mn0lrr3cYuJQyIqWGSWv99MwJAS+VqlYmODpOpY3e0U=",
        "ipv6_addr_in": "2001:ac8:40:11::f001",
        "daita": true,
        "shadowsocks_extra_addr_in": [
          "146.70.187.13",
          "146.70.187.14",
          "146.70.187.15",
          "146.70.187.16",
          "146.70.187.17",
          "146.70.187.18",
          "146.70.187.19",
          "146.70.187.20",
          "146.70.187.21",
          "146.70.187.22",
          "2001:ac8:40:11::b002",
          "2001:ac8:40:11::b003",
          "2001:ac8:40:11::b004",
          "2001:ac8:40:11::b005",
          "2001:ac8:40:11::b006",
          "2001:ac8:40:11::b007",
          "2001:ac8:40:11::b008",
          "2001:ac8:40:11::b009",
          "2001:ac8:40:11::b00a",
          "2001:ac8:40:11::b00b",
          "2001:ac8:40:11::b00c",
          "2001:ac8:40:11::b00d",
          "2001:ac8:40:11::b00e",
          "2001:ac8:40:11::b00f",
          "2001:ac8:40:11::b010",
          "2001:ac8:40:11::b011",
          "2001:ac8:40:11::b012",
          "2001:ac8:40:11::b013",
          "2001:ac8:40:11::b014",
          "2001:ac8:40:11::b015",
          "2001:ac8:40:11::b016",
          "2001:ac8:40:11::b017",
          "2001:ac8:40:11::b018",
          "2001:ac8:40:11::b019",
          "2001:ac8:40:11::b01a",
          "2001:ac8:40:11::b01b",
          "2001:ac8:40:11::b01c",
          "2001:ac8:40:11::b01d",
          "2001:ac8:40:11::b01e",
          "2001:ac8:40:11::b01f"
        ],
        "features": {
          "daita": {},
          "lwo": {},
          "quic": {
            "addr_in": [
              "146.70.187.23",
              "146.70.187.24",
              "146.70.187.25",
              "146.70.187.26",
              "146.70.187.27",
              "146.70.187.28",
              "146.70.187.29",
              "146.70.187.30",
              "146.70.187.31",
              "146.70.187.32",
              "2001:ac8:40:11::c002",
              "2001:ac8:40:11::c003",
              "2001:ac8:40:11::c004",
              "2001:ac8:40:11::c005",
              "2001:ac8:40:11::c006",
              "2001:ac8:40:11::c007",
              "2001:ac8:40:11::c008",
              "2001:ac8:40:11::c009",
              "2001:ac8:40:11::c00a",
              "2001:ac8:40:11::c00b",
              "2001:ac8:40:11::c00c",
              "2001:ac8:40:11::c00d",
              "2001:ac8:40:11::c00e",
              "2001:ac8:40:11::c00f",
              "2001:ac8:40:11::c010",
              "2001:ac8:40:11::c011",
              "2001:ac8:40:11::c012",
              "2001:ac8:40:11::c013",
              "2001:ac8:40:11::c014",
              "2001:ac8:40:11::c015",
              "2001:ac8:40:11::c016",
              "2001:ac8:40:11::c017",
              "2001:ac8:40:11::c018",
              "2001:ac8:40:11::c019",
              "2001:ac8:40:11::c01a",
              "2001:ac8:40:11::c01b",
              "2001:ac8:40:11::c01c",
              "2001:ac8:40:11::c01d",
              "2001:ac8:40:11::c01e",
              "2001:ac8:40:11::c01f"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "us-mia-wg-101.blockerad.eu"
          }
        }
      },
      {
        "hostname": "us-mia-wg-102",
        "location": "us-mia",
        "active": true,
        "owned": false,
        "provider": "M247",
        "stboot": true,
        "ipv4_addr_in": "146.70.187.130",
        "include_in_country": true,
        "weight": 100,
        "public_key": "4X0whnzbu8PkdJd9znks3vXx4JyI0asFf/241XjPdks=",
        "ipv6_addr_in": "2a0d:5600:6:105::f001",
        "daita": true,
        "shadowsocks_extra_addr_in": [
          "146.70.187.141",
          "146.70.187.142",
          "146.70.187.143",
          "146.70.187.144",
          "146.70.187.145",
          "146.70.187.146",
          "146.70.187.147",
          "146.70.187.148",
          "146.70.187.149",
          "146.70.187.150",
          "2a0d:5600:6:105::b002",
          "2a0d:5600:6:105::b003",
          "2a0d:5600:6:105::b004",
          "2a0d:5600:6:105::b005",
          "2a0d:5600:6:105::b006",
          "2a0d:5600:6:105::b007",
          "2a0d:5600:6:105::b008",
          "2a0d:5600:6:105::b009",
          "2a0d:5600:6:105::b00a",
          "2a0d:5600:6:105::b00b",
          "2a0d:5600:6:105::b00c",
          "2a0d:5600:6:105::b00d",
          "2a0d:5600:6:105::b00e",
          "2a0d:5600:6:105::b00f",
          "2a0d:5600:6:105::b010",
          "2a0d:5600:6:105::b011",
          "2a0d:5600:6:105::b012",
          "2a0d:5600:6:105::b013",
          "2a0d:5600:6:105::b014",
          "2a0d:5600:6:105::b015",
          "2a0d:5600:6:105::b016",
          "2a0d:5600:6:105::b017",
          "2a0d:5600:6:105::b018",
          "2a0d:5600:6:105::b019",
          "2a0d:5600:6:105::b01a",
          "2a0d:5600:6:105::b01b",
          "2a0d:5600:6:105::b01c",
          "2a0d:5600:6:105::b01d",
          "2a0d:5600:6:105::b01e",
          "2a0d:5600:6:105::b01f"
        ],
        "features": {
          "daita": {},
          "lwo": {},
          "quic": {
            "addr_in": [
              "146.70.187.151",
              "146.70.187.152",
              "146.70.187.153",
              "146.70.187.154",
              "146.70.187.155",
              "146.70.187.156",
              "146.70.187.157",
              "146.70.187.158",
              "146.70.187.159",
              "146.70.187.160",
              "2a0d:5600:6:105::c002",
              "2a0d:5600:6:105::c003",
              "2a0d:5600:6:105::c004",
              "2a0d:5600:6:105::c005",
              "2a0d:5600:6:105::c006",
              "2a0d:5600:6:105::c007",
              "2a0d:5600:6:105::c008",
              "2a0d:5600:6:105::c009",
              "2a0d:5600:6:105::c00a",
              "2a0d:5600:6:105::c00b",
              "2a0d:5600:6:105::c00c",
              "2a0d:5600:6:105::c00d",
              "2a0d:5600:6:105::c00e",
              "2a0d:5600:6:105::c00f",
              "2a0d:5600:6:105::c010",
              "2a0d:5600:6:105::c011",
              "2a0d:5600:6:105::c012",
              "2a0d:5600:6:105::c013",
              "2a0d:5600:6:105::c014",
              "2a0d:5600:6:105::c015",
              "2a0d:5600:6:105::c016",
              "2a0d:5600:6:105::c017",
              "2a0d:5600:6:105::c018",
              "2a0d:5600:6:105::c019",
              "2a0d:5600:6:105::c01a",
              "2a0d:5600:6:105::c01b",
              "2a0d:5600:6:105::c01c",
              "2a0d:5600:6:105::c01d",
              "2a0d:5600:6:105::c01e",
              "2a0d:5600:6:105::c01f"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "us-mia-wg-102.blockerad.eu"
          }
        }
      },
      {
        "hostname": "us-mia-wg-103",
        "location": "us-mia",
        "active": true,
        "owned": false,
        "provider": "M247",
        "stboot": true,
        "ipv4_addr_in": "135.136.36.2",
        "include_in_country": true,
        "weight": 100,
        "public_key": "AvtyY8vuNyROYZQYnBCk5UTsfxb8J43Ztm9cjuHMBUg=",
        "ipv6_addr_in": "2a0d:5600:6:106::f001",
        "daita": true,
        "shadowsocks_extra_addr_in": [
          "135.136.36.13",
          "135.136.36.14",
          "135.136.36.15",
          "135.136.36.16",
          "135.136.36.17",
          "135.136.36.18",
          "135.136.36.19",
          "135.136.36.20",
          "135.136.36.21",
          "135.136.36.22",
          "2a0d:5600:6:106::b002",
          "2a0d:5600:6:106::b003",
          "2a0d:5600:6:106::b004",
          "2a0d:5600:6:106::b005",
          "2a0d:5600:6:106::b006",
          "2a0d:5600:6:106::b007",
          "2a0d:5600:6:106::b008",
          "2a0d:5600:6:106::b009",
          "2a0d:5600:6:106::b00a",
          "2a0d:5600:6:106::b00b",
          "2a0d:5600:6:106::b00c",
          "2a0d:5600:6:106::b00d",
          "2a0d:5600:6:106::b00e",
          "2a0d:5600:6:106::b00f",
          "2a0d:5600:6:106::b010",
          "2a0d:5600:6:106::b011",
          "2a0d:5600:6:106::b012",
          "2a0d:5600:6:106::b013",
          "2a0d:5600:6:106::b014",
          "2a0d:5600:6:106::b015",
          "2a0d:5600:6:106::b016",
          "2a0d:5600:6:106::b017",
          "2a0d:5600:6:106::b018",
          "2a0d:5600:6:106::b019",
          "2a0d:5600:6:106::b01a",
          "2a0d:5600:6:106::b01b",
          "2a0d:5600:6:106::b01c",
          "2a0d:5600:6:106::b01d",
          "2a0d:5600:6:106::b01e",
          "2a0d:5600:6:106::b01f"
        ],
        "features": {
          "daita": {},
          "lwo": {},
          "quic": {
            "addr_in": [
              "135.136.36.23",
              "135.136.36.24",
              "135.136.36.25",
              "135.136.36.26",
              "135.136.36.27",
              "135.136.36.28",
              "135.136.36.29",
              "135.136.36.30",
              "135.136.36.31",
              "135.136.36.32",
              "2a0d:5600:6:106::c002",
              "2a0d:5600:6:106::c003",
              "2a0d:5600:6:106::c004",
              "2a0d:5600:6:106::c005",
              "2a0d:5600:6:106::c006",
              "2a0d:5600:6:106::c007",
              "2a0d:5600:6:106::c008",
              "2a0d:5600:6:106::c009",
              "2a0d:5600:6:106::c00a",
              "2a0d:5600:6:106::c00b",
              "2a0d:5600:6:106::c00c",
              "2a0d:5600:6:106::c00d",
              "2a0d:5600:6:106::c00e",
              "2a0d:5600:6:106::c00f",
              "2a0d:5600:6:106::c010",
              "2a0d:5600:6:106::c011",
              "2a0d:5600:6:106::c012",
              "2a0d:5600:6:106::c013",
              "2a0d:5600:6:106::c014",
              "2a0d:5600:6:106::c015",
              "2a0d:5600:6:106::c016",
              "2a0d:5600:6:106::c017",
              "2a0d:5600:6:106::c018",
              "2a0d:5600:6:106::c019",
              "2a0d:5600:6:106::c01a",
              "2a0d:5600:6:106::c01b",
              "2a0d:5600:6:106::c01c",
              "2a0d:5600:6:106::c01d",
              "2a0d:5600:6:106::c01e",
              "2a0d:5600:6:106::c01f"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "us-mia-wg-103.blockerad.eu"
          }
        }
      },
      {
        "hostname": "us-mkc-wg-001",
        "location": "us-mkc",
        "active": true,
        "owned": false,
        "provider": "Tzulo",
        "stboot": true,
        "ipv4_addr_in": "23.234.116.3",
        "include_in_country": true,
        "weight": 100,
        "public_key": "0EwMQYJ2uo6xu0C3lOEfsxMdc4NpFOURVc0JPJqkhlI=",
        "ipv6_addr_in": "2607:9000:e00:2::f001",
        "daita": true,
        "shadowsocks_extra_addr_in": [
          "23.234.116.14"
        ],
        "features": {
          "daita": {}
        }
      },
      {
        "hostname": "us-mkc-wg-002",
        "location": "us-mkc",
        "active": true,
        "owned": false,
        "provider": "Tzulo",
        "stboot": true,
        "ipv4_addr_in": "23.234.116.127",
        "include_in_country": true,
        "weight": 100,
        "public_key": "XeYfktwZerrhrXzVVEd9FQUw5MaUwv2gZmkTJWK8wSU=",
        "ipv6_addr_in": "2607:9000:e00:3::f001",
        "daita": true,
        "shadowsocks_extra_addr_in": [
          "23.234.116.139"
        ],
        "features": {
          "daita": {}
        }
      },
      {
        "hostname": "us-mkc-wg-003",
        "location": "us-mkc",
        "active": true,
        "owned": false,
        "provider": "Tzulo",
        "stboot": true,
        "ipv4_addr_in": "23.234.117.3",
        "include_in_country": true,
        "weight": 100,
        "public_key": "FOPZvXEnM1XWHH+WY17JX25N4EwJz6SSmqmAxP5y7CA=",
        "ipv6_addr_in": "2607:9000:e00:4::f001",
        "shadowsocks_extra_addr_in": [
          "23.234.117.14"
        ]
      },
      {
        "hostname": "us-mkc-wg-004",
        "location": "us-mkc",
        "active": true,
        "owned": false,
        "provider": "Tzulo",
        "stboot": true,
        "ipv4_addr_in": "23.234.117.127",
        "include_in_country": true,
        "weight": 100,
        "public_key": "8ueNKHj+2nbTpnnv4MpxY98VrhtIKSMMwh0R9HF6iyE=",
        "ipv6_addr_in": "2607:9000:e00:5::f001",
        "shadowsocks_extra_addr_in": [
          "23.234.117.139"
        ]
      },
      {
        "hostname": "us-mkc-wg-005",
        "location": "us-mkc",
        "active": true,
        "owned": false,
        "provider": "Tzulo",
        "stboot": true,
        "ipv4_addr_in": "23.234.118.3",
        "include_in_country": true,
        "weight": 100,
        "public_key": "KHbQz9XJVVj5M/sK3azWfgNyybdLNOjXahnHIzYYqXY=",
        "ipv6_addr_in": "2607:9000:e00:6::f001",
        "shadowsocks_extra_addr_in": [
          "23.234.118.14"
        ]
      },
      {
        "hostname": "us-mkc-wg-006",
        "location": "us-mkc",
        "active": true,
        "owned": false,
        "provider": "Tzulo",
        "stboot": true,
        "ipv4_addr_in": "23.234.118.127",
        "include_in_country": true,
        "weight": 100,
        "public_key": "bQWDsoitERBoPnP0AXI/jCUhk4AX8cMFbhCW93wn3HM=",
        "ipv6_addr_in": "2607:9000:e00:7::f001",
        "shadowsocks_extra_addr_in": [
          "23.234.118.139"
        ]
      },
      {
        "hostname": "us-mkc-wg-007",
        "location": "us-mkc",
        "active": true,
        "owned": false,
        "provider": "Tzulo",
        "stboot": true,
        "ipv4_addr_in": "23.234.119.3",
        "include_in_country": true,
        "weight": 100,
        "public_key": "e7BOh4K+tNWSnwUMWKI7yDCiskyamqXtpLjcg00KTn8=",
        "ipv6_addr_in": "2607:9000:e00:8::f001",
        "shadowsocks_extra_addr_in": [
          "23.234.119.14"
        ]
      },
      {
        "hostname": "us-mkc-wg-008",
        "location": "us-mkc",
        "active": true,
        "owned": false,
        "provider": "Tzulo",
        "stboot": true,
        "ipv4_addr_in": "23.234.119.127",
        "include_in_country": true,
        "weight": 100,
        "public_key": "9PByPs4okeg0lWhPYkW7tuyw1XKy5+BKhgVuQbxSOk4=",
        "ipv6_addr_in": "2607:9000:e00:9::f001",
        "shadowsocks_extra_addr_in": [
          "23.234.119.139"
        ]
      },
      {
        "hostname": "us-mkc-wg-101",
        "location": "us-mkc",
        "active": true,
        "owned": false,
        "provider": "hostuniversal",
        "stboot": true,
        "ipv4_addr_in": "155.2.191.3",
        "include_in_country": true,
        "weight": 100,
        "public_key": "Nk6dTIVRHBQzIZ6CUrJH7l4dItXEz3XOSBwmI933WUo=",
        "ipv6_addr_in": "2602:fed2:7e0a::f001",
        "shadowsocks_extra_addr_in": [
          "155.2.191.14"
        ]
      },
      {
        "hostname": "us-mkc-wg-102",
        "location": "us-mkc",
        "active": true,
        "owned": false,
        "provider": "hostuniversal",
        "stboot": true,
        "ipv4_addr_in": "155.2.191.53",
        "include_in_country": true,
        "weight": 100,
        "public_key": "ie5ag1xd2x/P3fxodzB21vPbLEmqhtfqKcUs1OR0BDs=",
        "ipv6_addr_in": "2602:fed2:7e0a::f101",
        "shadowsocks_extra_addr_in": [
          "155.2.191.64"
        ]
      },
      {
        "hostname": "us-mkc-wg-103",
        "location": "us-mkc",
        "active": true,
        "owned": false,
        "provider": "hostuniversal",
        "stboot": true,
        "ipv4_addr_in": "155.2.191.103",
        "include_in_country": true,
        "weight": 100,
        "public_key": "5dpXegNTyOFwWswBaJxViEwrXSAgC+Je9KokpT1sdjU=",
        "ipv6_addr_in": "2602:fed2:7e0a::f201",
        "shadowsocks_extra_addr_in": [
          "155.2.191.114"
        ]
      },
      {
        "hostname": "us-mkc-wg-104",
        "location": "us-mkc",
        "active": true,
        "owned": false,
        "provider": "hostuniversal",
        "stboot": true,
        "ipv4_addr_in": "155.2.191.153",
        "include_in_country": true,
        "weight": 100,
        "public_key": "wugRpkJNlfAV2lE3p1UXsTfZtO8JYWEdA9ZMLFeF3G4=",
        "ipv6_addr_in": "2602:fed2:7e0a::f301",
        "shadowsocks_extra_addr_in": [
          "155.2.191.164"
        ]
      },
      {
        "hostname": "us-mkc-wg-105",
        "location": "us-mkc",
        "active": true,
        "owned": false,
        "provider": "hostuniversal",
        "stboot": true,
        "ipv4_addr_in": "155.2.191.203",
        "include_in_country": true,
        "weight": 100,
        "public_key": "9w1yXK8tpAKZ2au6JHcu+L7TytOYmmZo9q7qfCwa1U8=",
        "ipv6_addr_in": "2602:fed2:7e0a::f401",
        "shadowsocks_extra_addr_in": [
          "155.2.191.214"
        ]
      },
      {
        "hostname": "us-nyc-wg-301",
        "location": "us-nyc",
        "active": true,
        "owned": false,
        "provider": "DataPacket",
        "stboot": true,
        "ipv4_addr_in": "143.244.47.65",
        "include_in_country": true,
        "weight": 100,
        "public_key": "IzqkjVCdJYC1AShILfzebchTlKCqVCt/SMEXolaS3Uc=",
        "ipv6_addr_in": "2a02:6ea0:c43f::f001"
      },
      {
        "hostname": "us-nyc-wg-302",
        "location": "us-nyc",
        "active": true,
        "owned": false,
        "provider": "DataPacket",
        "stboot": true,
        "ipv4_addr_in": "143.244.47.78",
        "include_in_country": true,
        "weight": 100,
        "public_key": "gH/fZJwc9iLv9fazk09J/DUWT2X7/LFXijRS15e2n34=",
        "ipv6_addr_in": "2a02:6ea0:c43f:1::f001"
      },
      {
        "hostname": "us-nyc-wg-303",
        "location": "us-nyc",
        "active": true,
        "owned": false,
        "provider": "DataPacket",
        "stboot": true,
        "ipv4_addr_in": "143.244.47.91",
        "include_in_country": true,
        "weight": 1,
        "public_key": "KRO+RzrFV92Ah+qpHgAMKZH2jtjRlmJ4ayl0gletY3c=",
        "ipv6_addr_in": "2a02:6ea0:c43f:2::b52f",
        "features": {
          "lwo": {},
          "quic": {
            "addr_in": [
              "143.244.47.103"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "us-nyc-wg-303.blockerad.eu"
          }
        }
      },
      {
        "hostname": "us-nyc-wg-501",
        "location": "us-nyc",
        "active": true,
        "owned": false,
        "provider": "M247",
        "stboot": true,
        "ipv4_addr_in": "146.70.165.2",
        "include_in_country": true,
        "weight": 1,
        "public_key": "FMNXnFgDHNTrT9o49U8bb3Z8J90LZzVJPpRzKtJM9W8=",
        "ipv6_addr_in": "2a0d:5600:24:2b6::f001"
      },
      {
        "hostname": "us-nyc-wg-502",
        "location": "us-nyc",
        "active": true,
        "owned": false,
        "provider": "M247",
        "stboot": true,
        "ipv4_addr_in": "146.70.165.130",
        "include_in_country": true,
        "weight": 100,
        "public_key": "cmUR4g9aIFDa5Xnp4B6Zjyp20jwgTTMgBdhcdvDV0FM=",
        "ipv6_addr_in": "2a0d:5600:24:2b8::f001"
      },
      {
        "hostname": "us-nyc-wg-503",
        "location": "us-nyc",
        "active": false,
        "owned": false,
        "provider": "M247",
        "stboot": true,
        "ipv4_addr_in": "146.70.165.194",
        "include_in_country": true,
        "weight": 100,
        "public_key": "czE6NJ8CccA5jnJkKoZGDpMXFqSudeVTzxU5scLP/H8=",
        "ipv6_addr_in": "2a0d:5600:24:2b9::f001"
      },
      {
        "hostname": "us-nyc-wg-504",
        "location": "us-nyc",
        "active": true,
        "owned": false,
        "provider": "M247",
        "stboot": true,
        "ipv4_addr_in": "146.70.166.130",
        "include_in_country": true,
        "weight": 100,
        "public_key": "MVa5yuoYnjXJtSCeBsyvaemuaK4KFN1p78+37Nvm2m0=",
        "ipv6_addr_in": "2a0d:5600:24:2c2::f001"
      },
      {
        "hostname": "us-nyc-wg-505",
        "location": "us-nyc",
        "active": true,
        "owned": false,
        "provider": "M247",
        "stboot": true,
        "ipv4_addr_in": "146.70.166.194",
        "include_in_country": true,
        "weight": 100,
        "public_key": "jrjogHbVDuPxyloBldvtB51TmebNJo+4rW2JFrN33iM=",
        "ipv6_addr_in": "2a0d:5600:24:2c3::f001"
      },
      {
        "hostname": "us-nyc-wg-506",
        "location": "us-nyc",
        "active": true,
        "owned": false,
        "provider": "M247",
        "stboot": true,
        "ipv4_addr_in": "146.70.165.66",
        "include_in_country": true,
        "weight": 100,
        "public_key": "IjdtI6sz8ZjU5tlK3eW4HAPp+GRvHErDtqxBcr8JvTM=",
        "ipv6_addr_in": "2a0d:5600:24:2b7::f001"
      },
      {
        "hostname": "us-nyc-wg-601",
        "location": "us-nyc",
        "active": true,
        "owned": false,
        "provider": "M247",
        "stboot": true,
        "ipv4_addr_in": "146.70.185.2",
        "include_in_country": true,
        "weight": 1,
        "public_key": "OKyEPafS1lnUTWqtVeWElkTzcmkvLi9dncBHbSyFrH8=",
        "ipv6_addr_in": "2a0d:5600:24:136a::f001",
        "features": {
          "quic": {
            "addr_in": [
              "146.70.185.62"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "us-nyc-wg-601.blockerad.eu"
          }
        }
      },
      {
        "hostname": "us-nyc-wg-602",
        "location": "us-nyc",
        "active": true,
        "owned": false,
        "provider": "M247",
        "stboot": true,
        "ipv4_addr_in": "146.70.168.130",
        "include_in_country": true,
        "weight": 100,
        "public_key": "4Lg7yQlukAMp6EX+2Ap+q4O+QIV/OEZyybtFJmN9umw=",
        "ipv6_addr_in": "2a0d:5600:24:1378::f001"
      },
      {
        "hostname": "us-nyc-wg-603",
        "location": "us-nyc",
        "active": true,
        "owned": false,
        "provider": "M247",
        "stboot": true,
        "ipv4_addr_in": "146.70.168.66",
        "include_in_country": true,
        "weight": 100,
        "public_key": "s3N8Xeh6khECbgRYPk9pp5slw2uE0deOxa9rSJ6bzwE=",
        "ipv6_addr_in": "2a0d:5600:24:1377::f001"
      },
      {
        "hostname": "us-nyc-wg-604",
        "location": "us-nyc",
        "active": true,
        "owned": false,
        "provider": "M247",
        "stboot": true,
        "ipv4_addr_in": "146.70.171.66",
        "include_in_country": true,
        "weight": 100,
        "public_key": "FIcFPDjxfF24xBrv+W7Bcqb2wADSWd+HAWPKYo6xZEk=",
        "ipv6_addr_in": "2a0d:5600:24:1372::f001"
      },
      {
        "hostname": "us-nyc-wg-605",
        "location": "us-nyc",
        "active": true,
        "owned": false,
        "provider": "M247",
        "stboot": true,
        "ipv4_addr_in": "146.70.171.130",
        "include_in_country": true,
        "weight": 100,
        "public_key": "78nFhfPEjrfOxBkUf2ylM7w6upYBEcHXm93sr8CMTE4=",
        "ipv6_addr_in": "2a0d:5600:24:1374::f001"
      },
      {
        "hostname": "us-nyc-wg-606",
        "location": "us-nyc",
        "active": true,
        "owned": false,
        "provider": "M247",
        "stboot": true,
        "ipv4_addr_in": "146.70.168.194",
        "include_in_country": true,
        "weight": 100,
        "public_key": "a8+VB6Cgah7Q5mWY860VfgU/h3Zf+pMpMdHB22e1uTQ=",
        "ipv6_addr_in": "2a0d:5600:24:1379::f001"
      },
      {
        "hostname": "us-nyc-wg-701",
        "location": "us-nyc",
        "active": false,
        "owned": false,
        "provider": "xtom",
        "stboot": true,
        "ipv4_addr_in": "23.162.8.3",
        "include_in_country": true,
        "weight": 1,
        "public_key": "S3X2pCfD9X6c29fd4C6b86mEO0b01mc/WUCDN5OgyjM=",
        "ipv6_addr_in": "2602:fa1f:1::f001",
        "shadowsocks_extra_addr_in": [
          "23.162.8.9"
        ]
      },
      {
        "hostname": "us-nyc-wg-702",
        "location": "us-nyc",
        "active": true,
        "owned": false,
        "provider": "xtom",
        "stboot": true,
        "ipv4_addr_in": "23.162.8.67",
        "include_in_country": true,
        "weight": 100,
        "public_key": "O81+YN0WHF4wuWRejhPG62PGK9bv/8BQTa6Ni3fomWM=",
        "ipv6_addr_in": "2602:fa1f:1::f033",
        "shadowsocks_extra_addr_in": [
          "23.162.8.73"
        ]
      },
      {
        "hostname": "us-nyc-wg-703",
        "location": "us-nyc",
        "active": false,
        "owned": false,
        "provider": "xtom",
        "stboot": true,
        "ipv4_addr_in": "23.162.8.130",
        "include_in_country": true,
        "weight": 1,
        "public_key": "Ycm86cSu1NKGpC+vZA6htq6YE9BUFk9wweE2/RySA1g=",
        "ipv6_addr_in": "2602:fa1f:1:3::f001",
        "shadowsocks_extra_addr_in": [
          "23.162.8.136"
        ]
      },
      {
        "hostname": "us-nyc-wg-801",
        "location": "us-nyc",
        "active": true,
        "owned": false,
        "provider": "Tzulo",
        "stboot": true,
        "ipv4_addr_in": "23.234.100.3",
        "include_in_country": true,
        "weight": 100,
        "public_key": "3XVRp858LSMwQ6pA2Zo5LFGf4nIjLnuTkbXTJiNPcmo=",
        "ipv6_addr_in": "2607:9000:a000:31::f001",
        "daita": true,
        "shadowsocks_extra_addr_in": [
          "23.234.100.14"
        ],
        "features": {
          "daita": {},
          "quic": {
            "addr_in": [
              "23.234.100.13"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "us-nyc-wg-801.blockerad.eu"
          }
        }
      },
      {
        "hostname": "us-nyc-wg-802",
        "location": "us-nyc",
        "active": true,
        "owned": false,
        "provider": "Tzulo",
        "stboot": true,
        "ipv4_addr_in": "23.234.100.127",
        "include_in_country": true,
        "weight": 100,
        "public_key": "SG1mcVhXNEZDZkir3GGLA7DCltIfPr71rPW6nFzW1Rc=",
        "ipv6_addr_in": "2607:9000:a000:32::f001",
        "daita": true,
        "shadowsocks_extra_addr_in": [
          "23.234.100.139"
        ],
        "features": {
          "daita": {},
          "quic": {
            "addr_in": [
              "23.234.100.138"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "us-nyc-wg-802.blockerad.eu"
          }
        }
      },
      {
        "hostname": "us-nyc-wg-803",
        "location": "us-nyc",
        "active": true,
        "owned": false,
        "provider": "Tzulo",
        "stboot": true,
        "ipv4_addr_in": "23.234.101.3",
        "include_in_country": true,
        "weight": 100,
        "public_key": "X1ZCLofMRmOnoJiNUTokpTazaRrdtbdH8+yAFvyCMnM=",
        "ipv6_addr_in": "2607:9000:a000:33::f001",
        "daita": true,
        "shadowsocks_extra_addr_in": [
          "23.234.101.14"
        ],
        "features": {
          "daita": {},
          "quic": {
            "addr_in": [
              "23.234.101.13"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "us-nyc-wg-803.blockerad.eu"
          }
        }
      },
      {
        "hostname": "us-nyc-wg-804",
        "location": "us-nyc",
        "active": true,
        "owned": false,
        "provider": "Tzulo",
        "stboot": true,
        "ipv4_addr_in": "23.234.101.127",
        "include_in_country": true,
        "weight": 100,
        "public_key": "uNKXjnTzZE0najF3fo5HiDBkg/fCF+anDkVuBNTCfhs=",
        "ipv6_addr_in": "2607:9000:a000:34::f001",
        "daita": true,
        "shadowsocks_extra_addr_in": [
          "23.234.101.139"
        ],
        "features": {
          "daita": {},
          "quic": {
            "addr_in": [
              "23.234.101.138"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "us-nyc-wg-804.blockerad.eu"
          }
        }
      },
      {
        "hostname": "us-nyc-wg-805",
        "location": "us-nyc",
        "active": true,
        "owned": false,
        "provider": "Tzulo",
        "stboot": true,
        "ipv4_addr_in": "23.234.102.3",
        "include_in_country": true,
        "weight": 100,
        "public_key": "i97V7R9Fk5IrrbYw+k7H35i8frXOHvbES13AAoRHrWY=",
        "ipv6_addr_in": "2607:9000:a000:35::f001",
        "daita": true,
        "shadowsocks_extra_addr_in": [
          "23.234.102.14"
        ],
        "features": {
          "daita": {},
          "quic": {
            "addr_in": [
              "23.234.102.13"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "us-nyc-wg-805.blockerad.eu"
          }
        }
      },
      {
        "hostname": "us-nyc-wg-806",
        "location": "us-nyc",
        "active": true,
        "owned": false,
        "provider": "Tzulo",
        "stboot": true,
        "ipv4_addr_in": "23.234.102.127",
        "include_in_country": true,
        "weight": 100,
        "public_key": "TJxsTwqSLYLKHFJLf7Uo87GiqVXnpYFaNbiiP9qwfBE=",
        "ipv6_addr_in": "2607:9000:a000:36::f001",
        "daita": true,
        "shadowsocks_extra_addr_in": [
          "23.234.102.139"
        ],
        "features": {
          "daita": {},
          "quic": {
            "addr_in": [
              "23.234.102.138"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "us-nyc-wg-806.blockerad.eu"
          }
        }
      },
      {
        "hostname": "us-nyc-wg-807",
        "location": "us-nyc",
        "active": true,
        "owned": false,
        "provider": "Tzulo",
        "stboot": true,
        "ipv4_addr_in": "23.234.103.3",
        "include_in_country": true,
        "weight": 100,
        "public_key": "THimhBHKHZ2KeoTRURvpNIVir4nlaxx5NSYwqNuF1wk=",
        "ipv6_addr_in": "2607:9000:a000:37::f001",
        "shadowsocks_extra_addr_in": [
          "23.234.103.14"
        ],
        "features": {
          "quic": {
            "addr_in": [
              "23.234.103.13"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "us-nyc-wg-807.blockerad.eu"
          }
        }
      },
      {
        "hostname": "us-nyc-wg-808",
        "location": "us-nyc",
        "active": true,
        "owned": false,
        "provider": "Tzulo",
        "stboot": true,
        "ipv4_addr_in": "23.234.103.127",
        "include_in_country": true,
        "weight": 100,
        "public_key": "tI+Ddqg8MZ3nqXLuvA5Kzryih//XLId7IM4IEgROiFk=",
        "ipv6_addr_in": "2607:9000:a000:38::f001",
        "shadowsocks_extra_addr_in": [
          "23.234.103.139"
        ],
        "features": {
          "quic": {
            "addr_in": [
              "23.234.103.138"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "us-nyc-wg-808.blockerad.eu"
          }
        }
      },
      {
        "hostname": "us-phx-wg-201",
        "location": "us-phx",
        "active": true,
        "owned": false,
        "provider": "Tzulo",
        "stboot": true,
        "ipv4_addr_in": "23.234.88.3",
        "include_in_country": true,
        "weight": 100,
        "public_key": "8mie5kslgD63v3pZkbFmwGdj3dg5mu8Wm2Ji5kntfXA=",
        "ipv6_addr_in": "2607:9000:700:41::f001",
        "daita": true,
        "shadowsocks_extra_addr_in": [
          "23.234.88.14"
        ],
        "features": {
          "daita": {}
        }
      },
      {
        "hostname": "us-phx-wg-202",
        "location": "us-phx",
        "active": true,
        "owned": false,
        "provider": "Tzulo",
        "stboot": true,
        "ipv4_addr_in": "23.234.88.127",
        "include_in_country": true,
        "weight": 100,
        "public_key": "I8eCMCSsFlb78N8VNaFqSJKM4Z2+3iVdlG6CvJkYEiA=",
        "ipv6_addr_in": "2607:9000:700:42::f001",
        "daita": true,
        "shadowsocks_extra_addr_in": [
          "23.234.88.139"
        ],
        "features": {
          "daita": {}
        }
      },
      {
        "hostname": "us-phx-wg-203",
        "location": "us-phx",
        "active": true,
        "owned": false,
        "provider": "Tzulo",
        "stboot": true,
        "ipv4_addr_in": "23.234.89.3",
        "include_in_country": true,
        "weight": 100,
        "public_key": "nSeEIx++JuzqxNqLPOm2BVCXwPpR72Q3QLflDUK8tTA=",
        "ipv6_addr_in": "2607:9000:700:43::f001",
        "shadowsocks_extra_addr_in": [
          "23.234.89.14"
        ]
      },
      {
        "hostname": "us-phx-wg-204",
        "location": "us-phx",
        "active": true,
        "owned": false,
        "provider": "Tzulo",
        "stboot": true,
        "ipv4_addr_in": "23.234.89.127",
        "include_in_country": true,
        "weight": 100,
        "public_key": "0is4/9V/KIBWwfeuDVDlBmPa134UuV5gaFGUqI1emXY=",
        "ipv6_addr_in": "2607:9000:700:44::f001",
        "shadowsocks_extra_addr_in": [
          "23.234.89.139"
        ]
      },
      {
        "hostname": "us-phx-wg-205",
        "location": "us-phx",
        "active": true,
        "owned": false,
        "provider": "Tzulo",
        "stboot": true,
        "ipv4_addr_in": "23.234.90.3",
        "include_in_country": true,
        "weight": 100,
        "public_key": "sZMMs5XaQN+p0HXCK15zYV1jo7IJN7agm1Ftm7JDnnk=",
        "ipv6_addr_in": "2607:9000:700:45::f001",
        "shadowsocks_extra_addr_in": [
          "23.234.90.14"
        ]
      },
      {
        "hostname": "us-phx-wg-206",
        "location": "us-phx",
        "active": true,
        "owned": false,
        "provider": "Tzulo",
        "stboot": true,
        "ipv4_addr_in": "23.234.90.127",
        "include_in_country": true,
        "weight": 100,
        "public_key": "fdA7Lc9cpwb1oPy4Oa/A8sPm+RaDpW5yrdgjykde4jM=",
        "ipv6_addr_in": "2607:9000:700:46::f001",
        "shadowsocks_extra_addr_in": [
          "23.234.90.139"
        ]
      },
      {
        "hostname": "us-phx-wg-207",
        "location": "us-phx",
        "active": true,
        "owned": false,
        "provider": "Tzulo",
        "stboot": true,
        "ipv4_addr_in": "23.234.91.3",
        "include_in_country": true,
        "weight": 100,
        "public_key": "G5tIt92dwuvvln9nlsi/cI3Au47U94mOMgSdODRMIxs=",
        "ipv6_addr_in": "2607:9000:700:47::f001",
        "shadowsocks_extra_addr_in": [
          "23.234.91.14"
        ]
      },
      {
        "hostname": "us-phx-wg-208",
        "location": "us-phx",
        "active": true,
        "owned": false,
        "provider": "Tzulo",
        "stboot": true,
        "ipv4_addr_in": "23.234.91.127",
        "include_in_country": true,
        "weight": 100,
        "public_key": "4nHL/Y9efuazXJB0cx6ktdBb0L0gkITWzCFCswfCh04=",
        "ipv6_addr_in": "2607:9000:700:48::f001",
        "shadowsocks_extra_addr_in": [
          "23.234.91.139"
        ]
      },
      {
        "hostname": "us-qas-wg-101",
        "location": "us-qas",
        "active": true,
        "owned": false,
        "provider": "DataPacket",
        "stboot": true,
        "ipv4_addr_in": "185.156.46.130",
        "include_in_country": true,
        "weight": 100,
        "public_key": "JEuuPzZE8uE53OFhd3YFiZuwwANLqwmdXWMHPUbBwnk=",
        "ipv6_addr_in": "2a02:6ea0:e206:1::a01f"
      },
      {
        "hostname": "us-qas-wg-102",
        "location": "us-qas",
        "active": true,
        "owned": false,
        "provider": "DataPacket",
        "stboot": true,
        "ipv4_addr_in": "185.156.46.143",
        "include_in_country": true,
        "weight": 100,
        "public_key": "5hlEb3AjTzVIJyYWCYvJvbgA4p25Ltfp2cYnys90LQ0=",
        "ipv6_addr_in": "2a02:6ea0:e206:2::a02f"
      },
      {
        "hostname": "us-qas-wg-103",
        "location": "us-qas",
        "active": true,
        "owned": false,
        "provider": "DataPacket",
        "stboot": true,
        "ipv4_addr_in": "185.156.46.156",
        "include_in_country": true,
        "weight": 100,
        "public_key": "oD9IFZsA5sync37K/sekVXaww76MwA3IvDRpR/irZWQ=",
        "ipv6_addr_in": "2a02:6ea0:e206:3::a03f"
      },
      {
        "hostname": "us-qas-wg-201",
        "location": "us-qas",
        "active": true,
        "owned": false,
        "provider": "HostRoyale",
        "stboot": true,
        "ipv4_addr_in": "103.81.230.3",
        "include_in_country": true,
        "weight": 100,
        "public_key": "no0QE15NRHLECYe/B976IH9mLn22QecYBbcYl3LZhD0=",
        "ipv6_addr_in": "2a01:4740:1::f001",
        "shadowsocks_extra_addr_in": [
          "103.81.230.14"
        ]
      },
      {
        "hostname": "us-qas-wg-202",
        "location": "us-qas",
        "active": false,
        "owned": false,
        "provider": "HostRoyale",
        "stboot": true,
        "ipv4_addr_in": "103.81.230.127",
        "include_in_country": true,
        "weight": 100,
        "public_key": "eUTgjAPvpLba9wwMcC0HNcLwC2Q42QYCKZuFPy34+Ug=",
        "ipv6_addr_in": "2a01:4740:1::f101",
        "shadowsocks_extra_addr_in": [
          "103.81.230.139"
        ]
      },
      {
        "hostname": "us-qas-wg-203",
        "location": "us-qas",
        "active": true,
        "owned": false,
        "provider": "HostRoyale",
        "stboot": true,
        "ipv4_addr_in": "103.81.231.3",
        "include_in_country": true,
        "weight": 100,
        "public_key": "tI5F6pIZMEf0aJUTG/I2ZvYkkJDJpOxVakObTLLmBAI=",
        "ipv6_addr_in": "2a01:4740:1::f201",
        "shadowsocks_extra_addr_in": [
          "103.81.231.14"
        ],
        "features": {
          "lwo": {}
        }
      },
      {
        "hostname": "us-qas-wg-204",
        "location": "us-qas",
        "active": true,
        "owned": false,
        "provider": "HostRoyale",
        "stboot": true,
        "ipv4_addr_in": "103.81.231.127",
        "include_in_country": true,
        "weight": 100,
        "public_key": "2bvhh22EcdV3MIuIJze47gD2KmXpplYrNbCjNff2ID8=",
        "ipv6_addr_in": "2a01:4740:1::f301",
        "shadowsocks_extra_addr_in": [
          "103.81.231.139"
        ],
        "features": {
          "lwo": {}
        }
      },
      {
        "hostname": "us-qas-wg-301",
        "location": "us-qas",
        "active": true,
        "owned": false,
        "provider": "Tzulo",
        "stboot": true,
        "ipv4_addr_in": "23.234.96.2",
        "include_in_country": true,
        "weight": 100,
        "public_key": "WUF0hoTY+kiklSDjMt2Z9kuebB6L/xTm5LcdNbwnslk=",
        "ipv6_addr_in": "2607:9000:900:31::f001",
        "shadowsocks_extra_addr_in": [
          "23.234.96.5",
          "23.234.96.6",
          "23.234.96.7",
          "23.234.96.8",
          "23.234.96.9",
          "23.234.96.10",
          "23.234.96.11",
          "23.234.96.12",
          "23.234.96.13",
          "23.234.96.14",
          "23.234.96.15",
          "23.234.96.16",
          "23.234.96.17",
          "23.234.96.18",
          "23.234.96.19",
          "2607:9000:900:31::b002",
          "2607:9000:900:31::b003",
          "2607:9000:900:31::b004",
          "2607:9000:900:31::b005",
          "2607:9000:900:31::b006",
          "2607:9000:900:31::b007",
          "2607:9000:900:31::b008",
          "2607:9000:900:31::b009",
          "2607:9000:900:31::b00a",
          "2607:9000:900:31::b00b",
          "2607:9000:900:31::b00c",
          "2607:9000:900:31::b00d",
          "2607:9000:900:31::b00e",
          "2607:9000:900:31::b00f",
          "2607:9000:900:31::b010",
          "2607:9000:900:31::b011",
          "2607:9000:900:31::b012",
          "2607:9000:900:31::b013",
          "2607:9000:900:31::b014",
          "2607:9000:900:31::b015",
          "2607:9000:900:31::b016",
          "2607:9000:900:31::b017",
          "2607:9000:900:31::b018",
          "2607:9000:900:31::b019",
          "2607:9000:900:31::b01a",
          "2607:9000:900:31::b01b",
          "2607:9000:900:31::b01c",
          "2607:9000:900:31::b01d",
          "2607:9000:900:31::b01e",
          "2607:9000:900:31::b01f"
        ],
        "features": {
          "quic": {
            "addr_in": [
              "23.234.96.20",
              "23.234.96.21",
              "23.234.96.22",
              "23.234.96.23",
              "23.234.96.24",
              "23.234.96.25",
              "23.234.96.26",
              "23.234.96.27",
              "23.234.96.28",
              "23.234.96.29",
              "23.234.96.30",
              "23.234.96.31",
              "23.234.96.32",
              "23.234.96.33",
              "23.234.96.34",
              "2607:9000:900:31::c002",
              "2607:9000:900:31::c003",
              "2607:9000:900:31::c004",
              "2607:9000:900:31::c005",
              "2607:9000:900:31::c006",
              "2607:9000:900:31::c007",
              "2607:9000:900:31::c008",
              "2607:9000:900:31::c009",
              "2607:9000:900:31::c00a",
              "2607:9000:900:31::c00b",
              "2607:9000:900:31::c00c",
              "2607:9000:900:31::c00d",
              "2607:9000:900:31::c00e",
              "2607:9000:900:31::c00f",
              "2607:9000:900:31::c010",
              "2607:9000:900:31::c011",
              "2607:9000:900:31::c012",
              "2607:9000:900:31::c013",
              "2607:9000:900:31::c014",
              "2607:9000:900:31::c015",
              "2607:9000:900:31::c016",
              "2607:9000:900:31::c017",
              "2607:9000:900:31::c018",
              "2607:9000:900:31::c019",
              "2607:9000:900:31::c01a",
              "2607:9000:900:31::c01b",
              "2607:9000:900:31::c01c",
              "2607:9000:900:31::c01d",
              "2607:9000:900:31::c01e",
              "2607:9000:900:31::c01f"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "us-qas-wg-301.blockerad.eu"
          }
        }
      },
      {
        "hostname": "us-qas-wg-302",
        "location": "us-qas",
        "active": true,
        "owned": false,
        "provider": "Tzulo",
        "stboot": true,
        "ipv4_addr_in": "23.234.96.127",
        "include_in_country": true,
        "weight": 100,
        "public_key": "vwIDgSCPbEzumzi/XveunLso8yzLdOP4OdZCHFYsbkg=",
        "ipv6_addr_in": "2607:9000:900:32::f001",
        "shadowsocks_extra_addr_in": [
          "23.234.96.130",
          "23.234.96.131",
          "23.234.96.132",
          "23.234.96.133",
          "23.234.96.134",
          "23.234.96.135",
          "23.234.96.136",
          "23.234.96.137",
          "23.234.96.138",
          "23.234.96.139",
          "23.234.96.140",
          "23.234.96.141",
          "23.234.96.142",
          "23.234.96.143",
          "23.234.96.144",
          "2607:9000:900:32::b002",
          "2607:9000:900:32::b003",
          "2607:9000:900:32::b004",
          "2607:9000:900:32::b005",
          "2607:9000:900:32::b006",
          "2607:9000:900:32::b007",
          "2607:9000:900:32::b008",
          "2607:9000:900:32::b009",
          "2607:9000:900:32::b00a",
          "2607:9000:900:32::b00b",
          "2607:9000:900:32::b00c",
          "2607:9000:900:32::b00d",
          "2607:9000:900:32::b00e",
          "2607:9000:900:32::b00f",
          "2607:9000:900:32::b010",
          "2607:9000:900:32::b011",
          "2607:9000:900:32::b012",
          "2607:9000:900:32::b013",
          "2607:9000:900:32::b014",
          "2607:9000:900:32::b015",
          "2607:9000:900:32::b016",
          "2607:9000:900:32::b017",
          "2607:9000:900:32::b018",
          "2607:9000:900:32::b019",
          "2607:9000:900:32::b01a",
          "2607:9000:900:32::b01b",
          "2607:9000:900:32::b01c",
          "2607:9000:900:32::b01d",
          "2607:9000:900:32::b01e",
          "2607:9000:900:32::b01f"
        ],
        "features": {
          "quic": {
            "addr_in": [
              "23.234.96.145",
              "23.234.96.146",
              "23.234.96.147",
              "23.234.96.148",
              "23.234.96.149",
              "23.234.96.150",
              "23.234.96.151",
              "23.234.96.152",
              "23.234.96.153",
              "23.234.96.154",
              "23.234.96.155",
              "23.234.96.156",
              "23.234.96.157",
              "23.234.96.158",
              "23.234.96.159",
              "2607:9000:900:32::c002",
              "2607:9000:900:32::c003",
              "2607:9000:900:32::c004",
              "2607:9000:900:32::c005",
              "2607:9000:900:32::c006",
              "2607:9000:900:32::c007",
              "2607:9000:900:32::c008",
              "2607:9000:900:32::c009",
              "2607:9000:900:32::c00a",
              "2607:9000:900:32::c00b",
              "2607:9000:900:32::c00c",
              "2607:9000:900:32::c00d",
              "2607:9000:900:32::c00e",
              "2607:9000:900:32::c00f",
              "2607:9000:900:32::c010",
              "2607:9000:900:32::c011",
              "2607:9000:900:32::c012",
              "2607:9000:900:32::c013",
              "2607:9000:900:32::c014",
              "2607:9000:900:32::c015",
              "2607:9000:900:32::c016",
              "2607:9000:900:32::c017",
              "2607:9000:900:32::c018",
              "2607:9000:900:32::c019",
              "2607:9000:900:32::c01a",
              "2607:9000:900:32::c01b",
              "2607:9000:900:32::c01c",
              "2607:9000:900:32::c01d",
              "2607:9000:900:32::c01e",
              "2607:9000:900:32::c01f"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "us-qas-wg-302.blockerad.eu"
          }
        }
      },
      {
        "hostname": "us-qas-wg-303",
        "location": "us-qas",
        "active": true,
        "owned": false,
        "provider": "Tzulo",
        "stboot": true,
        "ipv4_addr_in": "23.234.97.2",
        "include_in_country": true,
        "weight": 100,
        "public_key": "eym7onKZRi6uTtIA7SCxON/1q6zln3o5mYeYlasMeR8=",
        "ipv6_addr_in": "2607:9000:900:33::f001",
        "shadowsocks_extra_addr_in": [
          "23.234.97.5",
          "23.234.97.6",
          "23.234.97.7",
          "23.234.97.8",
          "23.234.97.9",
          "23.234.97.10",
          "23.234.97.11",
          "23.234.97.12",
          "23.234.97.13",
          "23.234.97.14",
          "23.234.97.15",
          "23.234.97.16",
          "23.234.97.17",
          "23.234.97.18",
          "23.234.97.19",
          "2607:9000:900:33::b002",
          "2607:9000:900:33::b003",
          "2607:9000:900:33::b004",
          "2607:9000:900:33::b005",
          "2607:9000:900:33::b006",
          "2607:9000:900:33::b007",
          "2607:9000:900:33::b008",
          "2607:9000:900:33::b009",
          "2607:9000:900:33::b00a",
          "2607:9000:900:33::b00b",
          "2607:9000:900:33::b00c",
          "2607:9000:900:33::b00d",
          "2607:9000:900:33::b00e",
          "2607:9000:900:33::b00f",
          "2607:9000:900:33::b010",
          "2607:9000:900:33::b011",
          "2607:9000:900:33::b012",
          "2607:9000:900:33::b013",
          "2607:9000:900:33::b014",
          "2607:9000:900:33::b015",
          "2607:9000:900:33::b016",
          "2607:9000:900:33::b017",
          "2607:9000:900:33::b018",
          "2607:9000:900:33::b019",
          "2607:9000:900:33::b01a",
          "2607:9000:900:33::b01b",
          "2607:9000:900:33::b01c",
          "2607:9000:900:33::b01d",
          "2607:9000:900:33::b01e",
          "2607:9000:900:33::b01f"
        ],
        "features": {
          "quic": {
            "addr_in": [
              "23.234.97.20",
              "23.234.97.21",
              "23.234.97.22",
              "23.234.97.23",
              "23.234.97.24",
              "23.234.97.25",
              "23.234.97.26",
              "23.234.97.27",
              "23.234.97.28",
              "23.234.97.29",
              "23.234.97.30",
              "23.234.97.31",
              "23.234.97.32",
              "23.234.97.33",
              "23.234.97.34",
              "2607:9000:900:33::c002",
              "2607:9000:900:33::c003",
              "2607:9000:900:33::c004",
              "2607:9000:900:33::c005",
              "2607:9000:900:33::c006",
              "2607:9000:900:33::c007",
              "2607:9000:900:33::c008",
              "2607:9000:900:33::c009",
              "2607:9000:900:33::c00a",
              "2607:9000:900:33::c00b",
              "2607:9000:900:33::c00c",
              "2607:9000:900:33::c00d",
              "2607:9000:900:33::c00e",
              "2607:9000:900:33::c00f",
              "2607:9000:900:33::c010",
              "2607:9000:900:33::c011",
              "2607:9000:900:33::c012",
              "2607:9000:900:33::c013",
              "2607:9000:900:33::c014",
              "2607:9000:900:33::c015",
              "2607:9000:900:33::c016",
              "2607:9000:900:33::c017",
              "2607:9000:900:33::c018",
              "2607:9000:900:33::c019",
              "2607:9000:900:33::c01a",
              "2607:9000:900:33::c01b",
              "2607:9000:900:33::c01c",
              "2607:9000:900:33::c01d",
              "2607:9000:900:33::c01e",
              "2607:9000:900:33::c01f"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "us-qas-wg-303.blockerad.eu"
          }
        }
      },
      {
        "hostname": "us-qas-wg-304",
        "location": "us-qas",
        "active": true,
        "owned": false,
        "provider": "Tzulo",
        "stboot": true,
        "ipv4_addr_in": "23.234.97.127",
        "include_in_country": true,
        "weight": 100,
        "public_key": "D3xigYvUQnLnKBVNQ7KpaWpuIbGxHHB1mb/+nSf3QXI=",
        "ipv6_addr_in": "2607:9000:900:34::f001",
        "shadowsocks_extra_addr_in": [
          "23.234.97.130",
          "23.234.97.131",
          "23.234.97.132",
          "23.234.97.133",
          "23.234.97.134",
          "23.234.97.135",
          "23.234.97.136",
          "23.234.97.137",
          "23.234.97.138",
          "23.234.97.139",
          "23.234.97.140",
          "23.234.97.141",
          "23.234.97.142",
          "23.234.97.143",
          "23.234.97.144",
          "2607:9000:900:34::b002",
          "2607:9000:900:34::b003",
          "2607:9000:900:34::b004",
          "2607:9000:900:34::b005",
          "2607:9000:900:34::b006",
          "2607:9000:900:34::b007",
          "2607:9000:900:34::b008",
          "2607:9000:900:34::b009",
          "2607:9000:900:34::b00a",
          "2607:9000:900:34::b00b",
          "2607:9000:900:34::b00c",
          "2607:9000:900:34::b00d",
          "2607:9000:900:34::b00e",
          "2607:9000:900:34::b00f",
          "2607:9000:900:34::b010",
          "2607:9000:900:34::b011",
          "2607:9000:900:34::b012",
          "2607:9000:900:34::b013",
          "2607:9000:900:34::b014",
          "2607:9000:900:34::b015",
          "2607:9000:900:34::b016",
          "2607:9000:900:34::b017",
          "2607:9000:900:34::b018",
          "2607:9000:900:34::b019",
          "2607:9000:900:34::b01a",
          "2607:9000:900:34::b01b",
          "2607:9000:900:34::b01c",
          "2607:9000:900:34::b01d",
          "2607:9000:900:34::b01e",
          "2607:9000:900:34::b01f"
        ],
        "features": {
          "quic": {
            "addr_in": [
              "23.234.97.145",
              "23.234.97.146",
              "23.234.97.147",
              "23.234.97.148",
              "23.234.97.149",
              "23.234.97.150",
              "23.234.97.151",
              "23.234.97.152",
              "23.234.97.153",
              "23.234.97.154",
              "23.234.97.155",
              "23.234.97.156",
              "23.234.97.157",
              "23.234.97.158",
              "23.234.97.159",
              "2607:9000:900:34::c002",
              "2607:9000:900:34::c003",
              "2607:9000:900:34::c004",
              "2607:9000:900:34::c005",
              "2607:9000:900:34::c006",
              "2607:9000:900:34::c007",
              "2607:9000:900:34::c008",
              "2607:9000:900:34::c009",
              "2607:9000:900:34::c00a",
              "2607:9000:900:34::c00b",
              "2607:9000:900:34::c00c",
              "2607:9000:900:34::c00d",
              "2607:9000:900:34::c00e",
              "2607:9000:900:34::c00f",
              "2607:9000:900:34::c010",
              "2607:9000:900:34::c011",
              "2607:9000:900:34::c012",
              "2607:9000:900:34::c013",
              "2607:9000:900:34::c014",
              "2607:9000:900:34::c015",
              "2607:9000:900:34::c016",
              "2607:9000:900:34::c017",
              "2607:9000:900:34::c018",
              "2607:9000:900:34::c019",
              "2607:9000:900:34::c01a",
              "2607:9000:900:34::c01b",
              "2607:9000:900:34::c01c",
              "2607:9000:900:34::c01d",
              "2607:9000:900:34::c01e",
              "2607:9000:900:34::c01f"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "us-qas-wg-304.blockerad.eu"
          }
        }
      },
      {
        "hostname": "us-qas-wg-305",
        "location": "us-qas",
        "active": true,
        "owned": false,
        "provider": "Tzulo",
        "stboot": true,
        "ipv4_addr_in": "23.234.98.2",
        "include_in_country": true,
        "weight": 100,
        "public_key": "hOuBVCXBzSA2eDx1cuAozt1B7Cg9M9IGCS6tedZHEkE=",
        "ipv6_addr_in": "2607:9000:900:35::f001",
        "shadowsocks_extra_addr_in": [
          "23.234.98.5",
          "23.234.98.6",
          "23.234.98.7",
          "23.234.98.8",
          "23.234.98.9",
          "23.234.98.10",
          "23.234.98.11",
          "23.234.98.12",
          "23.234.98.13",
          "23.234.98.14",
          "23.234.98.15",
          "23.234.98.16",
          "23.234.98.17",
          "23.234.98.18",
          "23.234.98.19",
          "2607:9000:900:35::b002",
          "2607:9000:900:35::b003",
          "2607:9000:900:35::b004",
          "2607:9000:900:35::b005",
          "2607:9000:900:35::b006",
          "2607:9000:900:35::b007",
          "2607:9000:900:35::b008",
          "2607:9000:900:35::b009",
          "2607:9000:900:35::b00a",
          "2607:9000:900:35::b00b",
          "2607:9000:900:35::b00c",
          "2607:9000:900:35::b00d",
          "2607:9000:900:35::b00e",
          "2607:9000:900:35::b00f",
          "2607:9000:900:35::b010",
          "2607:9000:900:35::b011",
          "2607:9000:900:35::b012",
          "2607:9000:900:35::b013",
          "2607:9000:900:35::b014",
          "2607:9000:900:35::b015",
          "2607:9000:900:35::b016",
          "2607:9000:900:35::b017",
          "2607:9000:900:35::b018",
          "2607:9000:900:35::b019",
          "2607:9000:900:35::b01a",
          "2607:9000:900:35::b01b",
          "2607:9000:900:35::b01c",
          "2607:9000:900:35::b01d",
          "2607:9000:900:35::b01e",
          "2607:9000:900:35::b01f"
        ],
        "features": {
          "quic": {
            "addr_in": [
              "23.234.98.20",
              "23.234.98.21",
              "23.234.98.22",
              "23.234.98.23",
              "23.234.98.24",
              "23.234.98.25",
              "23.234.98.26",
              "23.234.98.27",
              "23.234.98.28",
              "23.234.98.29",
              "23.234.98.30",
              "23.234.98.31",
              "23.234.98.32",
              "23.234.98.33",
              "23.234.98.34",
              "2607:9000:900:35::c002",
              "2607:9000:900:35::c003",
              "2607:9000:900:35::c004",
              "2607:9000:900:35::c005",
              "2607:9000:900:35::c006",
              "2607:9000:900:35::c007",
              "2607:9000:900:35::c008",
              "2607:9000:900:35::c009",
              "2607:9000:900:35::c00a",
              "2607:9000:900:35::c00b",
              "2607:9000:900:35::c00c",
              "2607:9000:900:35::c00d",
              "2607:9000:900:35::c00e",
              "2607:9000:900:35::c00f",
              "2607:9000:900:35::c010",
              "2607:9000:900:35::c011",
              "2607:9000:900:35::c012",
              "2607:9000:900:35::c013",
              "2607:9000:900:35::c014",
              "2607:9000:900:35::c015",
              "2607:9000:900:35::c016",
              "2607:9000:900:35::c017",
              "2607:9000:900:35::c018",
              "2607:9000:900:35::c019",
              "2607:9000:900:35::c01a",
              "2607:9000:900:35::c01b",
              "2607:9000:900:35::c01c",
              "2607:9000:900:35::c01d",
              "2607:9000:900:35::c01e",
              "2607:9000:900:35::c01f"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "us-qas-wg-305.blockerad.eu"
          }
        }
      },
      {
        "hostname": "us-qas-wg-306",
        "location": "us-qas",
        "active": true,
        "owned": false,
        "provider": "Tzulo",
        "stboot": true,
        "ipv4_addr_in": "23.234.98.127",
        "include_in_country": true,
        "weight": 100,
        "public_key": "5J/CzkztJt5djDo/UiHA0jQwMOr5b7SfeY77TWmcVF0=",
        "ipv6_addr_in": "2607:9000:900:36::f001",
        "shadowsocks_extra_addr_in": [
          "23.234.98.130",
          "23.234.98.131",
          "23.234.98.132",
          "23.234.98.133",
          "23.234.98.134",
          "23.234.98.135",
          "23.234.98.136",
          "23.234.98.137",
          "23.234.98.138",
          "23.234.98.139",
          "23.234.98.140",
          "23.234.98.141",
          "23.234.98.142",
          "23.234.98.143",
          "23.234.98.144",
          "2607:9000:900:36::b002",
          "2607:9000:900:36::b003",
          "2607:9000:900:36::b004",
          "2607:9000:900:36::b005",
          "2607:9000:900:36::b006",
          "2607:9000:900:36::b007",
          "2607:9000:900:36::b008",
          "2607:9000:900:36::b009",
          "2607:9000:900:36::b00a",
          "2607:9000:900:36::b00b",
          "2607:9000:900:36::b00c",
          "2607:9000:900:36::b00d",
          "2607:9000:900:36::b00e",
          "2607:9000:900:36::b00f",
          "2607:9000:900:36::b010",
          "2607:9000:900:36::b011",
          "2607:9000:900:36::b012",
          "2607:9000:900:36::b013",
          "2607:9000:900:36::b014",
          "2607:9000:900:36::b015",
          "2607:9000:900:36::b016",
          "2607:9000:900:36::b017",
          "2607:9000:900:36::b018",
          "2607:9000:900:36::b019",
          "2607:9000:900:36::b01a",
          "2607:9000:900:36::b01b",
          "2607:9000:900:36::b01c",
          "2607:9000:900:36::b01d",
          "2607:9000:900:36::b01e",
          "2607:9000:900:36::b01f"
        ],
        "features": {
          "quic": {
            "addr_in": [
              "23.234.98.145",
              "23.234.98.146",
              "23.234.98.147",
              "23.234.98.148",
              "23.234.98.149",
              "23.234.98.150",
              "23.234.98.151",
              "23.234.98.152",
              "23.234.98.153",
              "23.234.98.154",
              "23.234.98.155",
              "23.234.98.156",
              "23.234.98.157",
              "23.234.98.158",
              "23.234.98.159",
              "2607:9000:900:36::c002",
              "2607:9000:900:36::c003",
              "2607:9000:900:36::c004",
              "2607:9000:900:36::c005",
              "2607:9000:900:36::c006",
              "2607:9000:900:36::c007",
              "2607:9000:900:36::c008",
              "2607:9000:900:36::c009",
              "2607:9000:900:36::c00a",
              "2607:9000:900:36::c00b",
              "2607:9000:900:36::c00c",
              "2607:9000:900:36::c00d",
              "2607:9000:900:36::c00e",
              "2607:9000:900:36::c00f",
              "2607:9000:900:36::c010",
              "2607:9000:900:36::c011",
              "2607:9000:900:36::c012",
              "2607:9000:900:36::c013",
              "2607:9000:900:36::c014",
              "2607:9000:900:36::c015",
              "2607:9000:900:36::c016",
              "2607:9000:900:36::c017",
              "2607:9000:900:36::c018",
              "2607:9000:900:36::c019",
              "2607:9000:900:36::c01a",
              "2607:9000:900:36::c01b",
              "2607:9000:900:36::c01c",
              "2607:9000:900:36::c01d",
              "2607:9000:900:36::c01e",
              "2607:9000:900:36::c01f"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "us-qas-wg-306.blockerad.eu"
          }
        }
      },
      {
        "hostname": "us-qas-wg-307",
        "location": "us-qas",
        "active": true,
        "owned": false,
        "provider": "Tzulo",
        "stboot": true,
        "ipv4_addr_in": "23.234.99.2",
        "include_in_country": true,
        "weight": 100,
        "public_key": "aVmjjHrEAPxxg3l/19K+WSXjH4bKBpfaKkDI+6+umkc=",
        "ipv6_addr_in": "2607:9000:900:37::f001",
        "shadowsocks_extra_addr_in": [
          "23.234.99.5",
          "23.234.99.6",
          "23.234.99.7",
          "23.234.99.8",
          "23.234.99.9",
          "23.234.99.10",
          "23.234.99.11",
          "23.234.99.12",
          "23.234.99.13",
          "23.234.99.14",
          "23.234.99.15",
          "23.234.99.16",
          "23.234.99.17",
          "23.234.99.18",
          "23.234.99.19",
          "2607:9000:900:37::b002",
          "2607:9000:900:37::b003",
          "2607:9000:900:37::b004",
          "2607:9000:900:37::b005",
          "2607:9000:900:37::b006",
          "2607:9000:900:37::b007",
          "2607:9000:900:37::b008",
          "2607:9000:900:37::b009",
          "2607:9000:900:37::b00a",
          "2607:9000:900:37::b00b",
          "2607:9000:900:37::b00c",
          "2607:9000:900:37::b00d",
          "2607:9000:900:37::b00e",
          "2607:9000:900:37::b00f",
          "2607:9000:900:37::b010",
          "2607:9000:900:37::b011",
          "2607:9000:900:37::b012",
          "2607:9000:900:37::b013",
          "2607:9000:900:37::b014",
          "2607:9000:900:37::b015",
          "2607:9000:900:37::b016",
          "2607:9000:900:37::b017",
          "2607:9000:900:37::b018",
          "2607:9000:900:37::b019",
          "2607:9000:900:37::b01a",
          "2607:9000:900:37::b01b",
          "2607:9000:900:37::b01c",
          "2607:9000:900:37::b01d",
          "2607:9000:900:37::b01e",
          "2607:9000:900:37::b01f"
        ],
        "features": {
          "lwo": {},
          "quic": {
            "addr_in": [
              "23.234.99.20",
              "23.234.99.21",
              "23.234.99.22",
              "23.234.99.23",
              "23.234.99.24",
              "23.234.99.25",
              "23.234.99.26",
              "23.234.99.27",
              "23.234.99.28",
              "23.234.99.29",
              "23.234.99.30",
              "23.234.99.31",
              "23.234.99.32",
              "23.234.99.33",
              "23.234.99.34",
              "2607:9000:900:37::c002",
              "2607:9000:900:37::c003",
              "2607:9000:900:37::c004",
              "2607:9000:900:37::c005",
              "2607:9000:900:37::c006",
              "2607:9000:900:37::c007",
              "2607:9000:900:37::c008",
              "2607:9000:900:37::c009",
              "2607:9000:900:37::c00a",
              "2607:9000:900:37::c00b",
              "2607:9000:900:37::c00c",
              "2607:9000:900:37::c00d",
              "2607:9000:900:37::c00e",
              "2607:9000:900:37::c00f",
              "2607:9000:900:37::c010",
              "2607:9000:900:37::c011",
              "2607:9000:900:37::c012",
              "2607:9000:900:37::c013",
              "2607:9000:900:37::c014",
              "2607:9000:900:37::c015",
              "2607:9000:900:37::c016",
              "2607:9000:900:37::c017",
              "2607:9000:900:37::c018",
              "2607:9000:900:37::c019",
              "2607:9000:900:37::c01a",
              "2607:9000:900:37::c01b",
              "2607:9000:900:37::c01c",
              "2607:9000:900:37::c01d",
              "2607:9000:900:37::c01e",
              "2607:9000:900:37::c01f"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "us-qas-wg-307.blockerad.eu"
          }
        }
      },
      {
        "hostname": "us-qas-wg-308",
        "location": "us-qas",
        "active": true,
        "owned": false,
        "provider": "Tzulo",
        "stboot": true,
        "ipv4_addr_in": "23.234.99.127",
        "include_in_country": true,
        "weight": 100,
        "public_key": "lXSNRlfRVmeljwu0y7m4+M2OhveCbaMRewTbssgHDyY=",
        "ipv6_addr_in": "2607:9000:900:38::f001",
        "shadowsocks_extra_addr_in": [
          "23.234.99.130",
          "23.234.99.131",
          "23.234.99.132",
          "23.234.99.133",
          "23.234.99.134",
          "23.234.99.135",
          "23.234.99.136",
          "23.234.99.137",
          "23.234.99.138",
          "23.234.99.139",
          "23.234.99.140",
          "23.234.99.141",
          "23.234.99.142",
          "23.234.99.143",
          "23.234.99.144",
          "2607:9000:900:38::b002",
          "2607:9000:900:38::b003",
          "2607:9000:900:38::b004",
          "2607:9000:900:38::b005",
          "2607:9000:900:38::b006",
          "2607:9000:900:38::b007",
          "2607:9000:900:38::b008",
          "2607:9000:900:38::b009",
          "2607:9000:900:38::b00a",
          "2607:9000:900:38::b00b",
          "2607:9000:900:38::b00c",
          "2607:9000:900:38::b00d",
          "2607:9000:900:38::b00e",
          "2607:9000:900:38::b00f",
          "2607:9000:900:38::b010",
          "2607:9000:900:38::b011",
          "2607:9000:900:38::b012",
          "2607:9000:900:38::b013",
          "2607:9000:900:38::b014",
          "2607:9000:900:38::b015",
          "2607:9000:900:38::b016",
          "2607:9000:900:38::b017",
          "2607:9000:900:38::b018",
          "2607:9000:900:38::b019",
          "2607:9000:900:38::b01a",
          "2607:9000:900:38::b01b",
          "2607:9000:900:38::b01c",
          "2607:9000:900:38::b01d",
          "2607:9000:900:38::b01e",
          "2607:9000:900:38::b01f"
        ],
        "features": {
          "lwo": {},
          "quic": {
            "addr_in": [
              "23.234.99.145",
              "23.234.99.146",
              "23.234.99.147",
              "23.234.99.148",
              "23.234.99.149",
              "23.234.99.150",
              "23.234.99.151",
              "23.234.99.152",
              "23.234.99.153",
              "23.234.99.154",
              "23.234.99.155",
              "23.234.99.156",
              "23.234.99.157",
              "23.234.99.158",
              "23.234.99.159",
              "2607:9000:900:38::c002",
              "2607:9000:900:38::c003",
              "2607:9000:900:38::c004",
              "2607:9000:900:38::c005",
              "2607:9000:900:38::c006",
              "2607:9000:900:38::c007",
              "2607:9000:900:38::c008",
              "2607:9000:900:38::c009",
              "2607:9000:900:38::c00a",
              "2607:9000:900:38::c00b",
              "2607:9000:900:38::c00c",
              "2607:9000:900:38::c00d",
              "2607:9000:900:38::c00e",
              "2607:9000:900:38::c00f",
              "2607:9000:900:38::c010",
              "2607:9000:900:38::c011",
              "2607:9000:900:38::c012",
              "2607:9000:900:38::c013",
              "2607:9000:900:38::c014",
              "2607:9000:900:38::c015",
              "2607:9000:900:38::c016",
              "2607:9000:900:38::c017",
              "2607:9000:900:38::c018",
              "2607:9000:900:38::c019",
              "2607:9000:900:38::c01a",
              "2607:9000:900:38::c01b",
              "2607:9000:900:38::c01c",
              "2607:9000:900:38::c01d",
              "2607:9000:900:38::c01e",
              "2607:9000:900:38::c01f"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "us-qas-wg-308.blockerad.eu"
          }
        }
      },
      {
        "hostname": "us-rag-wg-201",
        "location": "us-rag",
        "active": true,
        "owned": false,
        "provider": "Tzulo",
        "stboot": true,
        "ipv4_addr_in": "23.234.76.2",
        "include_in_country": true,
        "weight": 100,
        "public_key": "MuKjekVqBwpSizHLNwVRl4b8bwi6aTCBOshPiOOWrEQ=",
        "ipv6_addr_in": "2607:9000:4000:31::f001",
        "shadowsocks_extra_addr_in": [
          "23.234.76.13"
        ],
        "features": {
          "lwo": {}
        }
      },
      {
        "hostname": "us-rag-wg-202",
        "location": "us-rag",
        "active": true,
        "owned": false,
        "provider": "Tzulo",
        "stboot": true,
        "ipv4_addr_in": "23.234.76.127",
        "include_in_country": true,
        "weight": 100,
        "public_key": "T2diUJ97txooCDntCrB6Q29Qe0fm/hMdZDzdc9uOUgQ=",
        "ipv6_addr_in": "2607:9000:4000:32::f001",
        "shadowsocks_extra_addr_in": [
          "23.234.76.138"
        ],
        "features": {
          "lwo": {}
        }
      },
      {
        "hostname": "us-rag-wg-203",
        "location": "us-rag",
        "active": true,
        "owned": false,
        "provider": "Tzulo",
        "stboot": true,
        "ipv4_addr_in": "23.234.77.2",
        "include_in_country": true,
        "weight": 100,
        "public_key": "4BioSTLTYH1qL/oYGY/z5IZ049I7oSzs5IKoFZzrgn0=",
        "ipv6_addr_in": "2607:9000:4000:33::f001",
        "shadowsocks_extra_addr_in": [
          "23.234.77.13"
        ],
        "features": {
          "lwo": {}
        }
      },
      {
        "hostname": "us-rag-wg-204",
        "location": "us-rag",
        "active": true,
        "owned": false,
        "provider": "Tzulo",
        "stboot": true,
        "ipv4_addr_in": "23.234.77.127",
        "include_in_country": true,
        "weight": 100,
        "public_key": "Tk5lPM5K5qrXPWDktHH+AvcxC+UxhGSX6aILsPi33zU=",
        "ipv6_addr_in": "2607:9000:4000:34::f001",
        "daita": true,
        "shadowsocks_extra_addr_in": [
          "23.234.77.138"
        ],
        "features": {
          "daita": {}
        }
      },
      {
        "hostname": "us-rag-wg-205",
        "location": "us-rag",
        "active": true,
        "owned": false,
        "provider": "Tzulo",
        "stboot": true,
        "ipv4_addr_in": "23.234.78.2",
        "include_in_country": true,
        "weight": 100,
        "public_key": "z7vhWZ1oY+UkE7PoXF/QtofOhTNGnNfoP20al/cniyc=",
        "ipv6_addr_in": "2607:9000:4000:35::f001",
        "daita": true,
        "shadowsocks_extra_addr_in": [
          "23.234.78.13"
        ],
        "features": {
          "daita": {}
        }
      },
      {
        "hostname": "us-rag-wg-206",
        "location": "us-rag",
        "active": true,
        "owned": false,
        "provider": "Tzulo",
        "stboot": true,
        "ipv4_addr_in": "23.234.78.127",
        "include_in_country": true,
        "weight": 100,
        "public_key": "ekRrcTqihriWz4TldL2deIEbHlqwytL3pu1WV+v7zjw=",
        "ipv6_addr_in": "2607:9000:4000:36::f001",
        "shadowsocks_extra_addr_in": [
          "23.234.78.138"
        ],
        "features": {
          "lwo": {}
        }
      },
      {
        "hostname": "us-rag-wg-207",
        "location": "us-rag",
        "active": true,
        "owned": false,
        "provider": "Tzulo",
        "stboot": true,
        "ipv4_addr_in": "23.234.79.2",
        "include_in_country": true,
        "weight": 100,
        "public_key": "Y16tMAXHpCEExSZJ8AL5LfskKqPqIrZWeLFbSLE/piE=",
        "ipv6_addr_in": "2607:9000:4000:37::f001",
        "shadowsocks_extra_addr_in": [
          "23.234.79.13"
        ],
        "features": {
          "lwo": {}
        }
      },
      {
        "hostname": "us-rag-wg-208",
        "location": "us-rag",
        "active": false,
        "owned": false,
        "provider": "Tzulo",
        "stboot": true,
        "ipv4_addr_in": "23.234.79.127",
        "include_in_country": true,
        "weight": 100,
        "public_key": "lCyIXwxSGEBSpUah0kYSyuaZuDJJB0Cwia7gv4r7XTA=",
        "ipv6_addr_in": "2607:9000:4000:38::f001",
        "shadowsocks_extra_addr_in": [
          "23.234.79.138"
        ]
      },
      {
        "hostname": "us-sea-wg-001",
        "location": "us-sea",
        "active": true,
        "owned": false,
        "provider": "DataPacket",
        "stboot": true,
        "ipv4_addr_in": "138.199.43.91",
        "include_in_country": true,
        "weight": 100,
        "public_key": "bZQF7VRDRK/JUJ8L6EFzF/zRw2tsqMRk6FesGtTgsC0=",
        "ipv6_addr_in": "2a02:6ea0:d80b:3::b75f"
      },
      {
        "hostname": "us-sea-wg-002",
        "location": "us-sea",
        "active": true,
        "owned": false,
        "provider": "DataPacket",
        "stboot": true,
        "ipv4_addr_in": "138.199.43.78",
        "include_in_country": true,
        "weight": 100,
        "public_key": "Xt80FGN9eLy1vX3F29huj6oW2MnQt7ne3DMBpo525Qw=",
        "ipv6_addr_in": "2a02:6ea0:d80b:2::f001"
      },
      {
        "hostname": "us-sea-wg-003",
        "location": "us-sea",
        "active": true,
        "owned": false,
        "provider": "DataPacket",
        "stboot": true,
        "ipv4_addr_in": "138.199.43.65",
        "include_in_country": true,
        "weight": 100,
        "public_key": "4ke8ZSsroiI6Sp23OBbMAU6yQmdF3xU2N8CyzQXE/Qw=",
        "ipv6_addr_in": "2a02:6ea0:d80b:1::b73f"
      },
      {
        "hostname": "us-sea-wg-401",
        "location": "us-sea",
        "active": true,
        "owned": false,
        "provider": "Tzulo",
        "stboot": true,
        "ipv4_addr_in": "23.234.80.2",
        "include_in_country": true,
        "weight": 100,
        "public_key": "wRvkGNE3N2UklxKajU06gbBJ3Bg7KmhZsU7a5HIFBw8=",
        "ipv6_addr_in": "2607:9000:5000:31::f001",
        "shadowsocks_extra_addr_in": [
          "23.234.80.13"
        ],
        "features": {
          "lwo": {},
          "quic": {
            "addr_in": [
              "23.234.80.12"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "us-sea-wg-401.blockerad.eu"
          }
        }
      },
      {
        "hostname": "us-sea-wg-402",
        "location": "us-sea",
        "active": true,
        "owned": false,
        "provider": "Tzulo",
        "stboot": true,
        "ipv4_addr_in": "23.234.80.127",
        "include_in_country": true,
        "weight": 100,
        "public_key": "NBnpCxDrc0tdX91KUm5cEmQv7BSMOZqd7dS/d7piQl0=",
        "ipv6_addr_in": "2607:9000:5000:32::f001",
        "shadowsocks_extra_addr_in": [
          "23.234.80.138"
        ],
        "features": {
          "lwo": {},
          "quic": {
            "addr_in": [
              "23.234.80.137"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "us-sea-wg-402.blockerad.eu"
          }
        }
      },
      {
        "hostname": "us-sea-wg-403",
        "location": "us-sea",
        "active": true,
        "owned": false,
        "provider": "Tzulo",
        "stboot": true,
        "ipv4_addr_in": "23.234.81.2",
        "include_in_country": true,
        "weight": 100,
        "public_key": "cJ8317JqMtNDvxvd/8z29lWurK/3sb5nFZuOY5mw3ys=",
        "ipv6_addr_in": "2607:9000:5000:33::f001",
        "shadowsocks_extra_addr_in": [
          "23.234.81.13"
        ],
        "features": {
          "lwo": {},
          "quic": {
            "addr_in": [
              "23.234.81.12"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "us-sea-wg-403.blockerad.eu"
          }
        }
      },
      {
        "hostname": "us-sea-wg-404",
        "location": "us-sea",
        "active": true,
        "owned": false,
        "provider": "Tzulo",
        "stboot": true,
        "ipv4_addr_in": "23.234.81.127",
        "include_in_country": true,
        "weight": 100,
        "public_key": "G6+A375GVmuFCAtvwgx3SWCWhrMvdQ+cboXQ8zp2ang=",
        "ipv6_addr_in": "2607:9000:5000:34::f001",
        "shadowsocks_extra_addr_in": [
          "23.234.81.138"
        ],
        "features": {
          "lwo": {},
          "quic": {
            "addr_in": [
              "23.234.81.137"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "us-sea-wg-404.blockerad.eu"
          }
        }
      },
      {
        "hostname": "us-sea-wg-405",
        "location": "us-sea",
        "active": true,
        "owned": false,
        "provider": "Tzulo",
        "stboot": true,
        "ipv4_addr_in": "23.234.82.2",
        "include_in_country": true,
        "weight": 100,
        "public_key": "X+efE4ntYuAEHBHU32SBMq/U0lAFEKeX5/nl3CKtrVM=",
        "ipv6_addr_in": "2607:9000:5000:35::f001",
        "shadowsocks_extra_addr_in": [
          "23.234.82.13"
        ],
        "features": {
          "lwo": {},
          "quic": {
            "addr_in": [
              "23.234.82.12"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "us-sea-wg-405.blockerad.eu"
          }
        }
      },
      {
        "hostname": "us-sea-wg-406",
        "location": "us-sea",
        "active": true,
        "owned": false,
        "provider": "Tzulo",
        "stboot": true,
        "ipv4_addr_in": "23.234.82.127",
        "include_in_country": true,
        "weight": 100,
        "public_key": "kT695K8pTGd+I6Q4a4URU2AdXN2VAtHyi7kNSRjUEiw=",
        "ipv6_addr_in": "2607:9000:5000:36::f001",
        "shadowsocks_extra_addr_in": [
          "23.234.82.138"
        ],
        "features": {
          "lwo": {},
          "quic": {
            "addr_in": [
              "23.234.82.137"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "us-sea-wg-406.blockerad.eu"
          }
        }
      },
      {
        "hostname": "us-sea-wg-407",
        "location": "us-sea",
        "active": true,
        "owned": false,
        "provider": "Tzulo",
        "stboot": true,
        "ipv4_addr_in": "23.234.83.2",
        "include_in_country": true,
        "weight": 100,
        "public_key": "HrhtkMqLmKtpAHiUIw7uLHwt48mDlhyLOt4+1kpNj3Y=",
        "ipv6_addr_in": "2607:9000:5000:37::f001",
        "daita": true,
        "shadowsocks_extra_addr_in": [
          "23.234.83.13"
        ],
        "features": {
          "daita": {},
          "quic": {
            "addr_in": [
              "23.234.83.12"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "us-sea-wg-407.blockerad.eu"
          }
        }
      },
      {
        "hostname": "us-sea-wg-408",
        "location": "us-sea",
        "active": true,
        "owned": false,
        "provider": "Tzulo",
        "stboot": true,
        "ipv4_addr_in": "23.234.83.127",
        "include_in_country": true,
        "weight": 100,
        "public_key": "tfhYXF12+7tB6bEOhqZ7eMODDv08fDMnQSBTmlau9VI=",
        "ipv6_addr_in": "2607:9000:5000:38::f001",
        "daita": true,
        "shadowsocks_extra_addr_in": [
          "23.234.83.138"
        ],
        "features": {
          "daita": {},
          "quic": {
            "addr_in": [
              "23.234.83.137"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "us-sea-wg-408.blockerad.eu"
          }
        }
      },
      {
        "hostname": "us-sfo-wg-001",
        "location": "us-sfo",
        "active": true,
        "owned": false,
        "provider": "HostRoyale",
        "stboot": true,
        "ipv4_addr_in": "45.153.102.3",
        "include_in_country": true,
        "weight": 100,
        "public_key": "mf/nsPsUZZvssmD8IqZBYda/PoPyD3mZFKEf0NkyynY=",
        "ipv6_addr_in": "2a06:3040:9:610::f101",
        "shadowsocks_extra_addr_in": [
          "45.153.102.24",
          "45.153.102.25",
          "45.153.102.26",
          "45.153.102.27",
          "45.153.102.28",
          "45.153.102.29",
          "45.153.102.30",
          "45.153.102.31",
          "45.153.102.32",
          "45.153.102.33",
          "45.153.102.34",
          "45.153.102.35",
          "45.153.102.36",
          "45.153.102.37",
          "45.153.102.38",
          "45.153.102.39",
          "45.153.102.40",
          "45.153.102.41",
          "45.153.102.42",
          "45.153.102.43",
          "2a06:3040:9:610::b102",
          "2a06:3040:9:610::b103",
          "2a06:3040:9:610::b104",
          "2a06:3040:9:610::b105",
          "2a06:3040:9:610::b106",
          "2a06:3040:9:610::b107",
          "2a06:3040:9:610::b108",
          "2a06:3040:9:610::b109",
          "2a06:3040:9:610::b10a",
          "2a06:3040:9:610::b10b",
          "2a06:3040:9:610::b10c",
          "2a06:3040:9:610::b10d",
          "2a06:3040:9:610::b10e",
          "2a06:3040:9:610::b10f",
          "2a06:3040:9:610::b110",
          "2a06:3040:9:610::b111",
          "2a06:3040:9:610::b112",
          "2a06:3040:9:610::b113",
          "2a06:3040:9:610::b114",
          "2a06:3040:9:610::b115",
          "2a06:3040:9:610::b116",
          "2a06:3040:9:610::b117",
          "2a06:3040:9:610::b118",
          "2a06:3040:9:610::b119",
          "2a06:3040:9:610::b11a",
          "2a06:3040:9:610::b11b",
          "2a06:3040:9:610::b11c",
          "2a06:3040:9:610::b11d",
          "2a06:3040:9:610::b11e",
          "2a06:3040:9:610::b11f"
        ],
        "features": {
          "lwo": {},
          "quic": {
            "addr_in": [
              "45.153.102.44",
              "45.153.102.45",
              "45.153.102.46",
              "45.153.102.47",
              "45.153.102.48",
              "45.153.102.49",
              "45.153.102.50",
              "45.153.102.51",
              "45.153.102.52",
              "45.153.102.53",
              "45.153.102.54",
              "45.153.102.55",
              "45.153.102.56",
              "45.153.102.57",
              "45.153.102.58",
              "45.153.102.59",
              "45.153.102.60",
              "45.153.102.61",
              "45.153.102.62",
              "45.153.102.63",
              "2a06:3040:9:610::c102",
              "2a06:3040:9:610::c103",
              "2a06:3040:9:610::c104",
              "2a06:3040:9:610::c105",
              "2a06:3040:9:610::c106",
              "2a06:3040:9:610::c107",
              "2a06:3040:9:610::c108",
              "2a06:3040:9:610::c109",
              "2a06:3040:9:610::c10a",
              "2a06:3040:9:610::c10b",
              "2a06:3040:9:610::c10c",
              "2a06:3040:9:610::c10d",
              "2a06:3040:9:610::c10e",
              "2a06:3040:9:610::c10f",
              "2a06:3040:9:610::c110",
              "2a06:3040:9:610::c111",
              "2a06:3040:9:610::c112",
              "2a06:3040:9:610::c113",
              "2a06:3040:9:610::c114",
              "2a06:3040:9:610::c115",
              "2a06:3040:9:610::c116",
              "2a06:3040:9:610::c117",
              "2a06:3040:9:610::c118",
              "2a06:3040:9:610::c119",
              "2a06:3040:9:610::c11a",
              "2a06:3040:9:610::c11b",
              "2a06:3040:9:610::c11c",
              "2a06:3040:9:610::c11d",
              "2a06:3040:9:610::c11e",
              "2a06:3040:9:610::c11f"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "us-sfo-wg-001.blockerad.eu"
          }
        }
      },
      {
        "hostname": "us-sfo-wg-002",
        "location": "us-sfo",
        "active": true,
        "owned": false,
        "provider": "HostRoyale",
        "stboot": true,
        "ipv4_addr_in": "194.126.179.3",
        "include_in_country": true,
        "weight": 100,
        "public_key": "sXWVQ/6I6Yj9fiA3yLqpLhnoq6qAVxkwRP7KirMRb3M=",
        "ipv6_addr_in": "2a06:3040:9:610::f201",
        "shadowsocks_extra_addr_in": [
          "2a06:3040:9:610::c202",
          "2a06:3040:9:610::c203",
          "2a06:3040:9:610::c204",
          "2a06:3040:9:610::c205",
          "2a06:3040:9:610::c206",
          "2a06:3040:9:610::c207",
          "2a06:3040:9:610::c208",
          "2a06:3040:9:610::c209",
          "2a06:3040:9:610::c20a",
          "2a06:3040:9:610::c20b",
          "2a06:3040:9:610::c20c",
          "2a06:3040:9:610::c20d",
          "2a06:3040:9:610::c20e",
          "2a06:3040:9:610::c20f",
          "2a06:3040:9:610::c210",
          "2a06:3040:9:610::c211",
          "2a06:3040:9:610::c212",
          "2a06:3040:9:610::c213",
          "2a06:3040:9:610::c214",
          "2a06:3040:9:610::c215",
          "2a06:3040:9:610::c216",
          "2a06:3040:9:610::c217",
          "2a06:3040:9:610::c218",
          "2a06:3040:9:610::c219",
          "2a06:3040:9:610::c21a",
          "2a06:3040:9:610::c21b",
          "2a06:3040:9:610::c21c",
          "2a06:3040:9:610::c21d",
          "2a06:3040:9:610::c21e",
          "2a06:3040:9:610::c21f",
          "194.126.179.24",
          "194.126.179.25",
          "194.126.179.26",
          "194.126.179.27",
          "194.126.179.28",
          "194.126.179.29",
          "194.126.179.30",
          "194.126.179.31",
          "194.126.179.32",
          "194.126.179.33",
          "194.126.179.34",
          "194.126.179.35",
          "194.126.179.36",
          "194.126.179.37",
          "194.126.179.38",
          "194.126.179.39",
          "194.126.179.40",
          "194.126.179.41",
          "194.126.179.42",
          "194.126.179.43"
        ],
        "features": {
          "lwo": {},
          "quic": {
            "addr_in": [
              "2a06:3040:9:610::b202",
              "2a06:3040:9:610::b203",
              "2a06:3040:9:610::b204",
              "2a06:3040:9:610::b205",
              "2a06:3040:9:610::b206",
              "2a06:3040:9:610::b207",
              "2a06:3040:9:610::b208",
              "2a06:3040:9:610::b209",
              "2a06:3040:9:610::b20a",
              "2a06:3040:9:610::b20b",
              "2a06:3040:9:610::b20c",
              "2a06:3040:9:610::b20d",
              "2a06:3040:9:610::b20e",
              "2a06:3040:9:610::b20f",
              "2a06:3040:9:610::b210",
              "2a06:3040:9:610::b211",
              "2a06:3040:9:610::b212",
              "2a06:3040:9:610::b213",
              "2a06:3040:9:610::b214",
              "2a06:3040:9:610::b215",
              "2a06:3040:9:610::b216",
              "2a06:3040:9:610::b217",
              "2a06:3040:9:610::b218",
              "2a06:3040:9:610::b219",
              "2a06:3040:9:610::b21a",
              "2a06:3040:9:610::b21b",
              "2a06:3040:9:610::b21c",
              "2a06:3040:9:610::b21d",
              "2a06:3040:9:610::b21e",
              "2a06:3040:9:610::b21f",
              "194.126.179.44",
              "194.126.179.45",
              "194.126.179.46",
              "194.126.179.47",
              "194.126.179.48",
              "194.126.179.49",
              "194.126.179.50",
              "194.126.179.51",
              "194.126.179.52",
              "194.126.179.53",
              "194.126.179.54",
              "194.126.179.55",
              "194.126.179.56",
              "194.126.179.57",
              "194.126.179.58",
              "194.126.179.59",
              "194.126.179.60",
              "194.126.179.61",
              "194.126.179.62",
              "194.126.179.63"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "us-sfo-wg-002.blockerad.eu"
          }
        }
      },
      {
        "hostname": "us-sjc-wg-001",
        "location": "us-sjc",
        "active": true,
        "owned": true,
        "provider": "xtom",
        "stboot": true,
        "ipv4_addr_in": "23.144.160.67",
        "include_in_country": true,
        "weight": 100,
        "public_key": "FGcXuLkvErFPiTPAjtJusTtbCoFkJOK8SXHwWOeNYUM=",
        "ipv6_addr_in": "2604:e8c0:6::f001",
        "daita": true,
        "shadowsocks_extra_addr_in": [
          "23.144.160.72",
          "23.144.160.73",
          "23.144.160.74",
          "23.144.160.75",
          "23.144.160.76",
          "23.144.160.77",
          "2604:e8c0:6::b002",
          "2604:e8c0:6::b003",
          "2604:e8c0:6::b004",
          "2604:e8c0:6::b005",
          "2604:e8c0:6::b006",
          "2604:e8c0:6::b007",
          "2604:e8c0:6::b008",
          "2604:e8c0:6::b009",
          "2604:e8c0:6::b00a",
          "2604:e8c0:6::b00b",
          "2604:e8c0:6::b00c",
          "2604:e8c0:6::b00d",
          "2604:e8c0:6::b00e",
          "2604:e8c0:6::b00f",
          "2604:e8c0:6::b010",
          "2604:e8c0:6::b011",
          "2604:e8c0:6::b012",
          "2604:e8c0:6::b013",
          "2604:e8c0:6::b014",
          "2604:e8c0:6::b015",
          "2604:e8c0:6::b016",
          "2604:e8c0:6::b017",
          "2604:e8c0:6::b018",
          "2604:e8c0:6::b019",
          "2604:e8c0:6::b01a",
          "2604:e8c0:6::b01b",
          "2604:e8c0:6::b01c",
          "2604:e8c0:6::b01d",
          "2604:e8c0:6::b01e",
          "2604:e8c0:6::b01f"
        ],
        "features": {
          "daita": {},
          "lwo": {},
          "quic": {
            "addr_in": [
              "23.144.160.78",
              "23.144.160.79",
              "23.144.160.80",
              "23.144.160.81",
              "23.144.160.82",
              "23.144.160.83",
              "23.144.160.84",
              "23.144.160.85",
              "2604:e8c0:6::c002",
              "2604:e8c0:6::c003",
              "2604:e8c0:6::c004",
              "2604:e8c0:6::c005",
              "2604:e8c0:6::c006",
              "2604:e8c0:6::c007",
              "2604:e8c0:6::c008",
              "2604:e8c0:6::c009",
              "2604:e8c0:6::c00a",
              "2604:e8c0:6::c00b",
              "2604:e8c0:6::c00c",
              "2604:e8c0:6::c00d",
              "2604:e8c0:6::c00e",
              "2604:e8c0:6::c00f",
              "2604:e8c0:6::c010",
              "2604:e8c0:6::c011",
              "2604:e8c0:6::c012",
              "2604:e8c0:6::c013",
              "2604:e8c0:6::c014",
              "2604:e8c0:6::c015",
              "2604:e8c0:6::c016",
              "2604:e8c0:6::c017",
              "2604:e8c0:6::c018",
              "2604:e8c0:6::c019",
              "2604:e8c0:6::c01a",
              "2604:e8c0:6::c01b",
              "2604:e8c0:6::c01c",
              "2604:e8c0:6::c01d",
              "2604:e8c0:6::c01e",
              "2604:e8c0:6::c01f"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "us-sjc-wg-001.blockerad.eu"
          }
        }
      },
      {
        "hostname": "us-sjc-wg-002",
        "location": "us-sjc",
        "active": true,
        "owned": true,
        "provider": "xtom",
        "stboot": true,
        "ipv4_addr_in": "23.144.160.86",
        "include_in_country": true,
        "weight": 100,
        "public_key": "A/FGRjSdq2is0cFCBixLy5Htx5SYFXsVVs28Lv1wsCs=",
        "ipv6_addr_in": "2604:e8c0:6::f101",
        "daita": true,
        "shadowsocks_extra_addr_in": [
          "23.144.160.91",
          "23.144.160.92",
          "23.144.160.93",
          "23.144.160.94",
          "23.144.160.95",
          "23.144.160.96",
          "2604:e8c0:6::b102",
          "2604:e8c0:6::b103",
          "2604:e8c0:6::b104",
          "2604:e8c0:6::b105",
          "2604:e8c0:6::b106",
          "2604:e8c0:6::b107",
          "2604:e8c0:6::b108",
          "2604:e8c0:6::b109",
          "2604:e8c0:6::b10a",
          "2604:e8c0:6::b10b",
          "2604:e8c0:6::b10c",
          "2604:e8c0:6::b10d",
          "2604:e8c0:6::b10e",
          "2604:e8c0:6::b10f",
          "2604:e8c0:6::b110",
          "2604:e8c0:6::b111",
          "2604:e8c0:6::b112",
          "2604:e8c0:6::b113",
          "2604:e8c0:6::b114",
          "2604:e8c0:6::b115",
          "2604:e8c0:6::b116",
          "2604:e8c0:6::b117",
          "2604:e8c0:6::b118",
          "2604:e8c0:6::b119",
          "2604:e8c0:6::b11a",
          "2604:e8c0:6::b11b",
          "2604:e8c0:6::b11c",
          "2604:e8c0:6::b11d",
          "2604:e8c0:6::b11e",
          "2604:e8c0:6::b11f"
        ],
        "features": {
          "daita": {},
          "lwo": {},
          "quic": {
            "addr_in": [
              "23.144.160.97",
              "23.144.160.98",
              "23.144.160.99",
              "23.144.160.100",
              "23.144.160.101",
              "23.144.160.102",
              "23.144.160.103",
              "23.144.160.104",
              "23.144.160.105",
              "2604:e8c0:6::c102",
              "2604:e8c0:6::c103",
              "2604:e8c0:6::c104",
              "2604:e8c0:6::c105",
              "2604:e8c0:6::c106",
              "2604:e8c0:6::c107",
              "2604:e8c0:6::c108",
              "2604:e8c0:6::c109",
              "2604:e8c0:6::c10a",
              "2604:e8c0:6::c10b",
              "2604:e8c0:6::c10c",
              "2604:e8c0:6::c10d",
              "2604:e8c0:6::c10e",
              "2604:e8c0:6::c10f",
              "2604:e8c0:6::c110",
              "2604:e8c0:6::c111",
              "2604:e8c0:6::c112",
              "2604:e8c0:6::c113",
              "2604:e8c0:6::c114",
              "2604:e8c0:6::c115",
              "2604:e8c0:6::c116",
              "2604:e8c0:6::c117",
              "2604:e8c0:6::c118",
              "2604:e8c0:6::c119",
              "2604:e8c0:6::c11a",
              "2604:e8c0:6::c11b",
              "2604:e8c0:6::c11c",
              "2604:e8c0:6::c11d",
              "2604:e8c0:6::c11e",
              "2604:e8c0:6::c11f"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "us-sjc-wg-002.blockerad.eu"
          }
        }
      },
      {
        "hostname": "us-sjc-wg-003",
        "location": "us-sjc",
        "active": true,
        "owned": true,
        "provider": "xtom",
        "stboot": true,
        "ipv4_addr_in": "23.144.160.106",
        "include_in_country": true,
        "weight": 100,
        "public_key": "PHvr2i7PvHljrPvbMpSQikfksXJNA/tseNeplNv1Wn8=",
        "ipv6_addr_in": "2604:e8c0:6::f201",
        "daita": true,
        "shadowsocks_extra_addr_in": [
          "23.144.160.112",
          "23.144.160.113",
          "23.144.160.114",
          "23.144.160.115",
          "23.144.160.116",
          "23.144.160.117",
          "2604:e8c0:6::b202",
          "2604:e8c0:6::b203",
          "2604:e8c0:6::b204",
          "2604:e8c0:6::b205",
          "2604:e8c0:6::b206",
          "2604:e8c0:6::b207",
          "2604:e8c0:6::b208",
          "2604:e8c0:6::b209",
          "2604:e8c0:6::b20a",
          "2604:e8c0:6::b20b",
          "2604:e8c0:6::b20c",
          "2604:e8c0:6::b20d",
          "2604:e8c0:6::b20e",
          "2604:e8c0:6::b20f",
          "2604:e8c0:6::b210",
          "2604:e8c0:6::b211",
          "2604:e8c0:6::b212",
          "2604:e8c0:6::b213",
          "2604:e8c0:6::b214",
          "2604:e8c0:6::b215",
          "2604:e8c0:6::b216",
          "2604:e8c0:6::b217",
          "2604:e8c0:6::b218",
          "2604:e8c0:6::b219",
          "2604:e8c0:6::b21a",
          "2604:e8c0:6::b21b",
          "2604:e8c0:6::b21c",
          "2604:e8c0:6::b21d",
          "2604:e8c0:6::b21e",
          "2604:e8c0:6::b21f"
        ],
        "features": {
          "daita": {},
          "lwo": {},
          "quic": {
            "addr_in": [
              "23.144.160.117",
              "23.144.160.118",
              "23.144.160.119",
              "23.144.160.120",
              "23.144.160.121",
              "23.144.160.122",
              "23.144.160.123",
              "23.144.160.124",
              "23.144.160.125",
              "23.144.160.126",
              "2604:e8c0:6::c202",
              "2604:e8c0:6::c203",
              "2604:e8c0:6::c204",
              "2604:e8c0:6::c205",
              "2604:e8c0:6::c206",
              "2604:e8c0:6::c207",
              "2604:e8c0:6::c208",
              "2604:e8c0:6::c209",
              "2604:e8c0:6::c20a",
              "2604:e8c0:6::c20b",
              "2604:e8c0:6::c20c",
              "2604:e8c0:6::c20d",
              "2604:e8c0:6::c20e",
              "2604:e8c0:6::c20f",
              "2604:e8c0:6::c210",
              "2604:e8c0:6::c211",
              "2604:e8c0:6::c212",
              "2604:e8c0:6::c213",
              "2604:e8c0:6::c214",
              "2604:e8c0:6::c215",
              "2604:e8c0:6::c216",
              "2604:e8c0:6::c217",
              "2604:e8c0:6::c218",
              "2604:e8c0:6::c219",
              "2604:e8c0:6::c21a",
              "2604:e8c0:6::c21b",
              "2604:e8c0:6::c21c",
              "2604:e8c0:6::c21d",
              "2604:e8c0:6::c21e",
              "2604:e8c0:6::c21f"
            ],
            "token": "d18a23fc-7d5e-4fd2-8372-5e0e73de741a",
            "domain": "us-sjc-wg-003.blockerad.eu"
          }
        }
      },
      {
        "hostname": "us-sjc-wg-302",
        "location": "us-sjc",
        "active": true,
        "owned": false,
        "provider": "xtom",
        "stboot": true,
        "ipv4_addr_in": "142.147.89.210",
        "include_in_country": true,
        "weight": 0,
        "public_key": "8wVb4HUgmpQEa5a1Q8Ff1hTDTJVaHts487bksJVugEo=",
        "ipv6_addr_in": "2604:e8c0:7::f001"
      },
      {
        "hostname": "us-sjc-wg-303",
        "location": "us-sjc",
        "active": true,
        "owned": false,
        "provider": "xtom",
        "stboot": true,
        "ipv4_addr_in": "142.147.89.225",
        "include_in_country": true,
        "weight": 0,
        "public_key": "2ZQTRk/3jT+ccfG3G/QoJV3NFC4CFHQwGBCSokOvBnA=",
        "ipv6_addr_in": "2604:e8c0:7::b68f"
      },
      {
        "hostname": "us-sjc-wg-401",
        "location": "us-sjc",
        "active": true,
        "owned": false,
        "provider": "DataPacket",
        "stboot": true,
        "ipv4_addr_in": "79.127.217.34",
        "include_in_country": true,
        "weight": 100,
        "public_key": "2q0LGwWvnV2qbNEAgOOHh4tvol5vGeQXJZDAbazCSBY=",
        "ipv6_addr_in": "2a02:6ea0:e611::f001"
      },
      {
        "hostname": "us-sjc-wg-402",
        "location": "us-sjc",
        "active": true,
        "owned": false,
        "provider": "DataPacket",
        "stboot": true,
        "ipv4_addr_in": "79.127.217.47",
        "include_in_country": true,
        "weight": 100,
        "public_key": "+UZsgTzYTdG3LvqpL+V9ZkwEMiFcls32YlpuI0cqDQ4=",
        "ipv6_addr_in": "2a02:6ea0:e611:1::f001"
      },
      {
        "hostname": "us-sjc-wg-501",
        "location": "us-sjc",
        "active": true,
        "owned": false,
        "provider": "Tzulo",
        "stboot": true,
        "ipv4_addr_in": "23.234.92.3",
        "include_in_country": true,
        "weight": 100,
        "public_key": "wbK8/hP/ZMr972OtanZxugSqUVt/sM/G9rnTiQ5YbSw=",
        "ipv6_addr_in": "2607:9000:800:31::f001",
        "shadowsocks_extra_addr_in": [
          "23.234.92.14"
        ],
        "features": {
          "lwo": {}
        }
      },
      {
        "hostname": "us-sjc-wg-502",
        "location": "us-sjc",
        "active": true,
        "owned": false,
        "provider": "Tzulo",
        "stboot": true,
        "ipv4_addr_in": "23.234.92.127",
        "include_in_country": true,
        "weight": 100,
        "public_key": "dCHtOy+ieOOMzgpZPr557dXygpmlj9RRNCAvUQvXj3I=",
        "ipv6_addr_in": "2607:9000:800:32::f001",
        "shadowsocks_extra_addr_in": [
          "23.234.92.139"
        ],
        "features": {
          "lwo": {}
        }
      },
      {
        "hostname": "us-sjc-wg-503",
        "location": "us-sjc",
        "active": true,
        "owned": false,
        "provider": "Tzulo",
        "stboot": true,
        "ipv4_addr_in": "23.234.93.3",
        "include_in_country": true,
        "weight": 100,
        "public_key": "HqWGqZbCgLxYLGHQG7P3jHYWQgc5p6ImqaxgqA97WCY=",
        "ipv6_addr_in": "2607:9000:800:33::f001",
        "shadowsocks_extra_addr_in": [
          "23.234.93.14"
        ],
        "features": {
          "lwo": {}
        }
      },
      {
        "hostname": "us-sjc-wg-504",
        "location": "us-sjc",
        "active": true,
        "owned": false,
        "provider": "Tzulo",
        "stboot": true,
        "ipv4_addr_in": "23.234.93.127",
        "include_in_country": true,
        "weight": 100,
        "public_key": "hQ/UqXflXztKM2T39HmQRPpPjWP8I2r9FMqnqFWy53M=",
        "ipv6_addr_in": "2607:9000:800:34::f001",
        "daita": true,
        "shadowsocks_extra_addr_in": [
          "23.234.93.139"
        ],
        "features": {
          "daita": {}
        }
      },
      {
        "hostname": "us-sjc-wg-505",
        "location": "us-sjc",
        "active": true,
        "owned": false,
        "provider": "Tzulo",
        "stboot": true,
        "ipv4_addr_in": "23.234.94.3",
        "include_in_country": true,
        "weight": 100,
        "public_key": "v0CXmb+wIy1P+IbFA/1nYTB3KoDzFyW5k7n8vXoTxiY=",
        "ipv6_addr_in": "2607:9000:800:35::f001",
        "daita": true,
        "shadowsocks_extra_addr_in": [
          "23.234.94.14"
        ],
        "features": {
          "daita": {}
        }
      },
      {
        "hostname": "us-sjc-wg-506",
        "location": "us-sjc",
        "active": true,
        "owned": false,
        "provider": "Tzulo",
        "stboot": true,
        "ipv4_addr_in": "23.234.94.127",
        "include_in_country": true,
        "weight": 100,
        "public_key": "sjWKL/W2+21cyjEBjtMd4TQQlWTsLTUN4skYOF7YgnU=",
        "ipv6_addr_in": "2607:9000:800:36::f001",
        "shadowsocks_extra_addr_in": [
          "23.234.94.139"
        ]
      },
      {
        "hostname": "us-sjc-wg-507",
        "location": "us-sjc",
        "active": true,
        "owned": false,
        "provider": "Tzulo",
        "stboot": true,
        "ipv4_addr_in": "23.234.95.3",
        "include_in_country": true,
        "weight": 100,
        "public_key": "IKhrTUlWJXlcH30jNV82mlWlj6NEre3PZffJ7MoT0zc=",
        "ipv6_addr_in": "2607:9000:800:37::f001",
        "shadowsocks_extra_addr_in": [
          "23.234.95.14"
        ]
      },
      {
        "hostname": "us-sjc-wg-508",
        "location": "us-sjc",
        "active": true,
        "owned": false,
        "provider": "Tzulo",
        "stboot": true,
        "ipv4_addr_in": "23.234.95.127",
        "include_in_country": true,
        "weight": 100,
        "public_key": "rIqRJ1o3UxvuwXj9B7VDquiTZ8BtQdab4wsb4F1L7l8=",
        "ipv6_addr_in": "2607:9000:800:38::f001",
        "shadowsocks_extra_addr_in": [
          "23.234.95.139"
        ]
      },
      {
        "hostname": "us-slc-wg-301",
        "location": "us-slc",
        "active": true,
        "owned": false,
        "provider": "Tzulo",
        "stboot": true,
        "ipv4_addr_in": "23.234.112.3",
        "include_in_country": true,
        "weight": 100,
        "public_key": "tA/k8ouzYiVmgCRCF7TWibVzv5xRp3cgv9TJX66poGE=",
        "ipv6_addr_in": "2607:9000:d00:2::f001",
        "shadowsocks_extra_addr_in": [
          "23.234.112.14"
        ]
      },
      {
        "hostname": "us-slc-wg-302",
        "location": "us-slc",
        "active": true,
        "owned": false,
        "provider": "Tzulo",
        "stboot": true,
        "ipv4_addr_in": "23.234.112.127",
        "include_in_country": true,
        "weight": 100,
        "public_key": "6hF/LLVCkxlW+mH6wFob5ZiDZNu2DqfEj82w8wzVnHY=",
        "ipv6_addr_in": "2607:9000:d00:3::f001",
        "shadowsocks_extra_addr_in": [
          "23.234.112.139"
        ],
        "features": {
          "lwo": {}
        }
      },
      {
        "hostname": "us-slc-wg-303",
        "location": "us-slc",
        "active": true,
        "owned": false,
        "provider": "Tzulo",
        "stboot": true,
        "ipv4_addr_in": "23.234.113.3",
        "include_in_country": true,
        "weight": 100,
        "public_key": "Taa3TPPNUUcD3upveDHqpi9uaNHbeXzh6kX+sQUcM0s=",
        "ipv6_addr_in": "2607:9000:d00:4::f001",
        "shadowsocks_extra_addr_in": [
          "23.234.113.14"
        ],
        "features": {
          "lwo": {}
        }
      },
      {
        "hostname": "us-slc-wg-304",
        "location": "us-slc",
        "active": true,
        "owned": false,
        "provider": "Tzulo",
        "stboot": true,
        "ipv4_addr_in": "23.234.113.127",
        "include_in_country": true,
        "weight": 100,
        "public_key": "+ru/ZmhgTYWNLyn3ZWuC57PMOU64yMfuWPZ5ow0XY3A=",
        "ipv6_addr_in": "2607:9000:d00:5::f001",
        "shadowsocks_extra_addr_in": [
          "23.234.113.139"
        ],
        "features": {
          "lwo": {}
        }
      },
      {
        "hostname": "us-slc-wg-305",
        "location": "us-slc",
        "active": true,
        "owned": false,
        "provider": "Tzulo",
        "stboot": true,
        "ipv4_addr_in": "23.234.114.3",
        "include_in_country": true,
        "weight": 100,
        "public_key": "QkiwUWRNNtI+8YSK0SPCq6KeKPSohpX/8FbFZkx+uHg=",
        "ipv6_addr_in": "2607:9000:d00:6::f001",
        "shadowsocks_extra_addr_in": [
          "23.234.114.14"
        ]
      },
      {
        "hostname": "us-slc-wg-306",
        "location": "us-slc",
        "active": true,
        "owned": false,
        "provider": "Tzulo",
        "stboot": true,
        "ipv4_addr_in": "23.234.114.127",
        "include_in_country": true,
        "weight": 100,
        "public_key": "Gv4GZOT46WQsTOAH4mYlauwFRxtpCX08BI0bzot5Piw=",
        "ipv6_addr_in": "2607:9000:d00:7::f001",
        "shadowsocks_extra_addr_in": [
          "23.234.114.139"
        ]
      },
      {
        "hostname": "us-slc-wg-307",
        "location": "us-slc",
        "active": true,
        "owned": false,
        "provider": "Tzulo",
        "stboot": true,
        "ipv4_addr_in": "23.234.115.3",
        "include_in_country": true,
        "weight": 100,
        "public_key": "6pJrsejyhJLRotKdS+RCZez28/WqlOw6qEs1BbjQVSI=",
        "ipv6_addr_in": "2607:9000:d00:8::f001",
        "shadowsocks_extra_addr_in": [
          "23.234.115.14"
        ]
      },
      {
        "hostname": "us-slc-wg-308",
        "location": "us-slc",
        "active": true,
        "owned": false,
        "provider": "Tzulo",
        "stboot": true,
        "ipv4_addr_in": "23.234.115.127",
        "include_in_country": true,
        "weight": 100,
        "public_key": "f7xT56F8RP9XDXW7UCxBcjgP+SAGyH+y2OZ4fieR4X8=",
        "ipv6_addr_in": "2607:9000:d00:9::f001",
        "shadowsocks_extra_addr_in": [
          "23.234.115.139"
        ]
      },
      {
        "hostname": "us-txc-wg-001",
        "location": "us-txc",
        "active": true,
        "owned": false,
        "provider": "DataPacket",
        "stboot": true,
        "ipv4_addr_in": "79.127.222.194",
        "include_in_country": true,
        "weight": 100,
        "public_key": "+OCONjBoN5RytiPy000VOzhZsiu1tSzecmc1hl/q8hI=",
        "ipv6_addr_in": "2a02:6ea0:fe00:1::f001"
      },
      {
        "hostname": "us-txc-wg-002",
        "location": "us-txc",
        "active": true,
        "owned": false,
        "provider": "DataPacket",
        "stboot": true,
        "ipv4_addr_in": "79.127.222.207",
        "include_in_country": true,
        "weight": 100,
        "public_key": "mjv8qVNwhVKO0ePAI97CRil188uwdR/VR6ihcNY/hio=",
        "ipv6_addr_in": "2a02:6ea0:fe00:2::f001"
      },
      {
        "hostname": "us-uyk-wg-201",
        "location": "us-uyk",
        "active": true,
        "owned": false,
        "provider": "HostRoyale",
        "stboot": true,
        "ipv4_addr_in": "104.36.50.3",
        "include_in_country": true,
        "weight": 100,
        "public_key": "utm9eFUk8tH0j/dwKLJvlb6BRSfm3GZbomxr52ZDGn0=",
        "ipv6_addr_in": "2a06:3040:22:620::f001",
        "shadowsocks_extra_addr_in": [
          "104.36.50.5"
        ]
      },
      {
        "hostname": "us-uyk-wg-202",
        "location": "us-uyk",
        "active": true,
        "owned": false,
        "provider": "HostRoyale",
        "stboot": true,
        "ipv4_addr_in": "104.36.50.33",
        "include_in_country": true,
        "weight": 100,
        "public_key": "8Rh2Qc+vXTREhJb/RfCcpXS13U9xSqy4Pnw4+Wwt7iE=",
        "ipv6_addr_in": "2a06:3040:22:620::f101",
        "shadowsocks_extra_addr_in": [
          "104.36.50.35"
        ]
      },
      {
        "hostname": "us-was-wg-001",
        "location": "us-was",
        "active": true,
        "owned": false,
        "provider": "Zenlayer",
        "stboot": true,
        "ipv4_addr_in": "185.213.193.3",
        "include_in_country": true,
        "weight": 100,
        "public_key": "qD3AH8vI8MhEVc9+0+2O8zV0Gx9FfKdy7ri3Bnpzo10=",
        "ipv6_addr_in": "2604:980:1002:11::f001",
        "shadowsocks_extra_addr_in": [
          "185.213.193.14"
        ],
        "features": {
          "lwo": {}
        }
      },
      {
        "hostname": "us-was-wg-002",
        "location": "us-was",
        "active": true,
        "owned": false,
        "provider": "Zenlayer",
        "stboot": true,
        "ipv4_addr_in": "185.213.193.127",
        "include_in_country": true,
        "weight": 100,
        "public_key": "2AvJGG4MJfnJMRSR6kcha9FZMMkhJM/AtktI5DSESSI=",
        "ipv6_addr_in": "2604:980:1002:11::f101",
        "shadowsocks_extra_addr_in": [
          "185.213.193.139"
        ],
        "features": {
          "lwo": {}
        }
      },
      {
        "hostname": "za-jnb-wg-001",
        "location": "za-jnb",
        "active": true,
        "owned": false,
        "provider": "DataPacket",
        "stboot": true,
        "ipv4_addr_in": "154.47.30.130",
        "include_in_country": true,
        "weight": 100,
        "public_key": "5dOGXJ9JK/Bul0q57jsuvjNnc15gRpSO1rMbxkf4J2M=",
        "ipv6_addr_in": "2a02:6ea0:f206::f001"
      },
      {
        "hostname": "za-jnb-wg-002",
        "location": "za-jnb",
        "active": true,
        "owned": false,
        "provider": "DataPacket",
        "stboot": true,
        "ipv4_addr_in": "154.47.30.143",
        "include_in_country": true,
        "weight": 100,
        "public_key": "lTq6+yUYfYsXwBpj/u3LnYqpLhW8ZJXQQ19N/ybP2B8=",
        "ipv6_addr_in": "2a02:6ea0:f207::f001"
      }
    ],
    "port_ranges": [
      [
        53,
        53
      ],
      [
        123,
        123
      ],
      [
        4000,
        33433
      ],
      [
        33565,
        51820
      ],
      [
        52001,
        60000
      ]
    ],
    "shadowsocks_port_ranges": [
      [
        51900,
        51949
      ]
    ],
    "ipv4_gateway": "10.64.0.1",
    "ipv6_gateway": "fc00:bbbb:bbbb:bb01::1"
  },
  "bridge": {
    "relays": [
      {
        "hostname": "au-syd-br-001",
        "location": "au-syd",
        "active": true,
        "owned": false,
        "provider": "M247",
        "stboot": true,
        "ipv4_addr_in": "146.70.141.154",
        "include_in_country": true,
        "weight": 100
      },
      {
        "hostname": "ca-mtr-br-001",
        "location": "ca-mtr",
        "active": true,
        "owned": false,
        "provider": "M247",
        "stboot": true,
        "ipv4_addr_in": "217.138.213.18",
        "include_in_country": true,
        "weight": 100
      },
      {
        "hostname": "ch-zrh-br-001",
        "location": "ch-zrh",
        "active": true,
        "owned": true,
        "provider": "31173",
        "stboot": true,
        "ipv4_addr_in": "193.32.127.117",
        "include_in_country": true,
        "weight": 1
      },
      {
        "hostname": "cz-prg-br-101",
        "location": "cz-prg",
        "active": true,
        "owned": false,
        "provider": "M247",
        "stboot": true,
        "ipv4_addr_in": "217.138.199.106",
        "include_in_country": true,
        "weight": 100
      },
      {
        "hostname": "fi-hel-br-101",
        "location": "fi-hel",
        "active": true,
        "owned": true,
        "provider": "Blix",
        "stboot": true,
        "ipv4_addr_in": "193.138.7.132",
        "include_in_country": true,
        "weight": 100
      },
      {
        "hostname": "gb-lon-br-001",
        "location": "gb-lon",
        "active": true,
        "owned": true,
        "provider": "31173",
        "stboot": true,
        "ipv4_addr_in": "141.98.252.66",
        "include_in_country": true,
        "weight": 100
      },
      {
        "hostname": "hk-hkg-br-201",
        "location": "hk-hkg",
        "active": false,
        "owned": false,
        "provider": "xtom",
        "stboot": true,
        "ipv4_addr_in": "103.125.233.210",
        "include_in_country": true,
        "weight": 100
      },
      {
        "hostname": "jp-tyo-br-201",
        "location": "jp-tyo",
        "active": true,
        "owned": false,
        "provider": "M247",
        "stboot": true,
        "ipv4_addr_in": "185.242.4.34",
        "include_in_country": true,
        "weight": 100
      },
      {
        "hostname": "nl-ams-br-001",
        "location": "nl-ams",
        "active": false,
        "owned": true,
        "provider": "31173",
        "stboot": true,
        "ipv4_addr_in": "185.65.134.116",
        "include_in_country": true,
        "weight": 100
      },
      {
        "hostname": "sg-sin-br-101",
        "location": "sg-sin",
        "active": false,
        "owned": false,
        "provider": "M247",
        "stboot": true,
        "ipv4_addr_in": "146.70.192.38",
        "include_in_country": true,
        "weight": 100
      },
      {
        "hostname": "us-lax-br-401",
        "location": "us-lax",
        "active": false,
        "owned": false,
        "provider": "M247",
        "stboot": true,
        "ipv4_addr_in": "62.133.44.202",
        "include_in_country": false,
        "weight": 100
      },
      {
        "hostname": "us-nyc-br-501",
        "location": "us-nyc",
        "active": true,
        "owned": false,
        "provider": "M247",
        "stboot": true,
        "ipv4_addr_in": "212.103.48.226",
        "include_in_country": true,
        "weight": 100
      },
      {
        "hostname": "us-nyc-br-601",
        "location": "us-nyc",
        "active": true,
        "owned": false,
        "provider": "M247",
        "stboot": true,
        "ipv4_addr_in": "38.132.121.146",
        "include_in_country": true,
        "weight": 100
      }
    ],
    "shadowsocks": [
      {
        "protocol": "tcp",
        "port": 443,
        "cipher": "aes-256-gcm",
        "password": "mullvad"
      },
      {
        "protocol": "udp",
        "port": 1234,
        "cipher": "aes-256-cfb",
        "password": "mullvad"
      },
      {
        "protocol": "udp",
        "port": 1236,
        "cipher": "aes-256-gcm",
        "password": "mullvad"
      }
    ]
  }
}

5.7 - Pgp

PGP keys
-----BEGIN PGP PUBLIC KEY BLOCK-----

mQINBGm/rtIBEADFDMFRtPbif4sMCPMf7de0jiDLCm7fok4Y4jZPwRMGw7pNc6jC
N6coa+9ZarYDv1luSzPDjU+cTh3J6A5nsfBM4zjB5FZXLRnH1Fe8Kw4n9ROlXBg6
8ixm+uRzdgMKWY3+w4Fx9FE36jet5Kx0mAuKk3v+1gT6K6jBstpyVT8RTgWmfMAO
tPUEXHJ6di80hPTicORMyGFVOBjb1eXnNlc4NgML5hJTkSTR9OyYKiWA1PglMfvW
ZDKKU03uuCsia8FrJGeF3m5oP99ntQqlj7rRh2jFNeJ67b5+/z16NpzddwYufVPS
TdgZ0H93iiWDhACVf7hi/83otXVt/2ltv753bsGwuBn0ga5SZFUMalnNOaaJsXLA
0mHRIoZSl3SjM6dv+m7Y3QnMkWCXGdvg8GhQiEVUBN7h9CpXvbcfNDEQshVLDihY
T623TLPzvkWF5AxSKU6SokgOkEVUhRAYNnn8NXhgVgMSmxXRL8VU72b1sJ3YcM2J
qLP363SOCZkTPTJUQZF1sUTpvpQJuxC6bpg0r5ecKtWHFHtQIw4fOnQgTPcmFhiw
hSao1Ed2Te4pz1g+B4JsWajbIxS9CO/08LIrDTEih6bgNWZH7+XPzPgkOXdXs9Fy
qQlZznbyOBx2ombKPo8HV2VxCPnjvbwHrO0d6xMeYQBdzYqY7wEvEksQswARAQAB
tClzaW1lb253YXJyZW4gPHNpbWVvbndhcnJlbkBhbHdhbGRlbmQuY29tPokCTAQT
AQoANhYhBOD5L3UneLIiAYU7Dgn0JC/sMMPRBQJpv67SAhsBBAsJCAcEFQoJCAUW
AgMBAAIeBQIXgAAKCRAJ9CQv7DDD0V9bD/0SbKwC+XFeN54tUx0S8Fw3PVn4+UyM
CMzt8P+xHA4wa7kQYqWpdSOxYPqeWpHUmGcdIL+Re22eoLbYjKVD58dGyFKfqXvi
fWYubvdhOSIHbjSiW/hqa6ycVO4FvA51iRmFRLCj6EriFVwfMsNdxCl7/fare0vR
JiIG1VwgAbb7/CnQxsjkuGz2Shee/OhR17lLyHEl8azQhi/HUD47jCZinDw97feW
nyboZyfFJbK3EdzYCrKiuyxp2XqkCez/4DyjgDpmp1m5gOieJasHYodJ3++Q3bDE
eikNDHiRemi59kCcCNWsgJCtvRk1AyWKM0D6Rs0hHbeDtg4OJcu7MsvNEgYx7xXP
hGoYEYek52T2utWPAx9SiO/Cibo5aIEM5sRZe4iUjIEysaluBf3YLGGdD4gdUVEw
Ehn9J+Nc1F6mWnZvlYOGEeh1h0c8AQIwRAGX8YZiAf1p/ScoQ1mjJe27hxZMMVnB
osQ3iGNnMyuiL763lY6lBYmO+Ogvfx9uSAKzZuRQwSwe/A7bOiDux+7fnI1CtPRk
VYf6hNeB55aGmF8LJ/qzKApXefnhxPa2El8KDYKnM10o1yvaHtFXY5PtR9hzgNXA
pflTzw6Xy3Susz0OOkuNimLE6ubYv9gl2UKALuQEW6otVnMQNzSy/HKfKXYPfR+c
d5K8B8AB4TjJRbkCDQRpv86yARAA67SYuAteECrZ8dU2L41UOI5f7nx8j0ycAr1N
tpc+aeNkkwHH/NQnOtHXLy9Binx9Mwh5kjcQw7IgR+dYxqCXgsYHZvLWjcEPyhp8
3aTA2Ek8LlXWmPindOVu2O8DBw0Y7SAVknSEQZd7Hwg7ShbpDszhfKr37ekIvUn4
dVfRJ4Qbwm+Wl131sXzNC2nTWMaSN3HKLSPf2lX4LV65MPYHtRpcx3Sf4QrQyA++
AkOnDRjw4hbzsWqOFRcN+z5m5G7/1qhWp9coLq2bAptgIUDi7YSm6yKkv8AaMugs
RvrtVFZnBCuKEEg3LXW6mR5wJTCNxIUQxfoTIWE8ZQEK2LEMiWBtTbOzdXGOs0BM
zC3lPRUHoNUOTfIVwkrtfuh31D9J1v52S2PhMKbKtc2jlJADG0NWDu+mWwITxEep
36A6ibLRtsZVL1+MSkISjTyTwC7cRON0wEdtj2szftLJ9c/AroE/wPaNq2PFv9Wu
w8I0wBTBwDpZ3vWioXHD12+Wo9zZmKL8QHBogM4GKZhTvMyQUOzrd6bi77VsAKiw
KteVV22sBUJzEvmTduOAY+B35ThHinmx50EFIbewDaUx15hGggAZhNKQNbqSIofb
0CgucCqPHsMntYv/71JMVoQX2o3DyrS9+lq3j2YiRRQzrh56DHh2W234m1sgLzU6
RgamLGcAEQEAAYkEcgQYAQoAJhYhBOD5L3UneLIiAYU7Dgn0JC/sMMPRBQJpv86y
AhsCBQkB4TOAAkAJEAn0JC/sMMPRwXQgBBkBCgAdFiEEFuxvv2wIGF1W5BG5192I
qwwHN/IFAmm/zrIACgkQ192IqwwHN/KsmA//a926zNLxaKwWkxXW79DAvVXOpHPg
psm0ZQNCG6wB6ArJKuuF+HtpYWWahoGHVRToWJPpeHpwtoBKJ7tjWzuaByZdQINH
6u5TR3k4pDy5lWAmu97s6nlyITqPgPZDyF+mtMUoKoVe3WnNO3jF5jus0C2yf6x7
47X7JmiQYKPfwmVFWk6cr0bmlLL3pCWORocgdAllqoI8Xk537Zx38gTbb/9pPGa1
UEnq5xSQX6VKPHw2ar684QuG02QCzGnovxT2sFHgEwJtHydwnt+WwzLg3NaJXny0
zhLEH0J80958nJtkjV4KUBFOWn1Rks83j6ElUGmI5qApfy943F8dW3192tU/JK+C
Ja4vg2skwV2pfIRQp2MabU3O+sUH9b/6Yl1pjgy6pVWbwBrdHwFDoU9jXVZxMsiS
HzageHVjy0MQ24G4doHn8TEWxCjOT4rmeMvmxm9mKlzZ5K+EfqMZDosXc8NGKIVm
s6KqFJ6AcKVPK7oKEYSDFA1SoAkY19z8pUv3Utib4F7CZvhlHVDUXJ12YeALR8db
BdZAptuLaqfos8+bAy8FxavlezIr1Kdlo2u+EKV2ytQtur4PHnoFrwm7zUqpbqkK
AP/ziYyejgUyGoqLo1xOtJORWHjum8DCZkYkZbdKCJdm3GOIgSbvLcRmE4cQZpCE
JBar+mo7dkTTgGZtLw//WkZWoZdoRLscvKvFAUWdfE5RqSNP1uzsEL10wJx2Qtv4
jux+PWM3WzSsAL/EfaX0ip8XU+xhb4BjtlvdVWcAum6dB18TMQZCVpAtWZiPEHNr
SQ6BndE4t/grnLHSRGOKmZO2QHUasZiwALMiaTKpou3l31B/+dxRvYbJaqF8h47I
P/GJaWCENoO3NwhYkrWfRpctJO8nR87airqkFxdjsFyH8KJWpEzDouDgk8lmhHYe
QEwjy29DKtu+ASoIXOUDuQOn+bT7sVLh8Rlbwj9z5qrnXwZfBTTABrUhIA/ogGv5
wD4kOQ0RbjYoMwGSUAMuQZ+zhCUPRh5lKG12PhrB2mJ0X7X9diCJ0Tvqp2uSm5Wt
vH2KUyItPCB60cPa/ZAuUoD3/wdDWxTbE3XkczidRPqFb1KjCOoDiFJTOHq2FdqH
s/Zz3vMslHHBs5TwFhxrNC0/XKLTv3gOr8lU72yzPakCXdGyiLOviAcl6TgGabgU
MWLtYeOqpy8NjwcDTv1PimLzDUuhoLWfeGm9TAviDVjhAl8clIzKfWczYhTt83xE
W0FlbwXN6N388iL3+Hxwn9Q62yFAkftSm19JD6H7rrTMQIsxUHq9IdOQ1H19AyEO
87wmnJ3PGSqL1cRIic/PSE4RkZIFuDbVAJtmzvDG9E/WSafGNwbDPK7aBbMFgjS5
Ag0Eab/OsgEQAMZM+4+gJmnSM4KOKei3dyqjjYhoOltgPe0UVAbMBh5RclbZ2EIh
GqKn2HlX8OYx4IFVvuqZSPzm4MF8CoWDZbXsjgUAfk+TltR14kzyuM0wzD1HrzoH
zxYzATDH9/ciNUfJJNcW6Vfe5tNEKsjUU3UGXJ3r8Q6WsOM/YMXYH5Gw39AHPgyV
xRlY6+CTNQQIaXR2SJFJQhiOiaO6PaFIzMidrheC71n0O64q44iTEtRwIqgCbENs
3WKLFN0z3Hz5e1Os6mz6+M7Sav1XwXyM6ysAtC3Utg8j/8w4ZPH+lJO3N96GIU8H
jRjYjLedH13f7r6scRhB6Mlfp1qPK8ehYZfS+nzAmLNnsD3taw2N0pCfB5mvSRPB
EE3EDBRd8A5IMPAZTTEo9gLSlfr0ANeo23znuxYYkIZ2jWhG7TWODuGrhWHjjdDy
en5CA5ZasrpIBk5ITiNDSUrWhQwH7hfLhAaCbdt+KeKqoFfVbmZbQ7dKEbW8P1ZB
s2NKSZGqCyya2POVp+Ws7jbLoPLgUCDOyPOIz+G7o4kCnx8nBINIWKHFA4bl8U9H
jrWIW8HhX9TeH6f+ZkwVLgRfKgUvYpDPjwvgRQnyBQTeO72LM1wA7spuvKbCN0k+
cbkWxlGeoNqEYpZAlDciZN+feh7FgIgrPeuzjEkNy9rJRji8If+75ShvABEBAAGJ
AjwEGAEKACYWIQTg+S91J3iyIgGFOw4J9CQv7DDD0QUCab/OsgIbDAUJAeEzgAAK
CRAJ9CQv7DDD0a1lD/9k39CGrOXtRqTmoH1QknLGuiIeqGBPZrnN6WSh5XF3hwLV
3j97ES3VPbwd10YWAaFw7v+kMKwAaTSVaOK9Z9s5CpKwBKZo8tlAvLVHtAAFP0FJ
KK0zTIcXSdNjMLVhBo9Rj1BcovsVBLXdhMCsxt9q19V+OeVwBV3c+1KOUhl3J015
Z1qb+xh8+SZHK9AHSYQMQebyRcH4VtJgPHx3SWNiVHMI5NbPiUO1SVZXcn8P2oyu
fthY+OKeCd8y51+ubfur2O43CTGDCYWAzkWh2Xrhy3n1NHVGPAsL4+7gqblotpu2
9ULcn1Tft1AW9wRWM3syeK1TXNmPX0M/0MXtoUIpmwE6LEDTu88K7LKLu6QJt8tu
0ZmyJ2Rc2koD6/L5o2mtYRF/5feQzWGs2S9NI3CMsO7RKz4t2kJf0hftAVaUN82R
gpKAWUtsVBNnUW8tOfNEq91ql46cUTC86FXRakD0NEEw2oEBxCHuFYfVwwOQXHgt
G62NzRM4dHHBMxg6J40lFq3WJ5P2bw+sOcZLsvex4OIByZZmujJEEDnYgf+p8z/F
JEL2jiLXb61BevMVixG3y7/vYSf0OCc6xvU5DXNlG1Q+Z0xE5jKSp1L3mldF3MWR
8mQC6Rg+RHQxxABmNrofeuu2umJSaB8z+0kdgeV93/AiXnX80PY3aCkbca3MGLgz
BGm/zsoWCSsGAQQB2kcPAQEHQNe+6zNbs5HKrdZnHgeik/y7v5QYQr1cLYqfdCQ4
9GbMiQI8BBgBCgAmFiEE4PkvdSd4siIBhTsOCfQkL+www9EFAmm/zsoCGyAFCQHh
M4AACgkQCfQkL+www9FTmRAAkO36Rc9FIpWLQqMp8/KkuEtOx4UTcD1HLdHtT9dB
gdVr+OgP0dRMwT7l7rKSgX7ueWhhDdPB0gIkI2tasO7qzuFHUf8ywDxrMVWk+AJf
A+2cdrP6RANGs15clFdKfqR/r9Zn0rxDRAJKnVMirqQt1ilCHXqaavvXDOsphPgT
reoApVVv2sJbQYuL9TQnVtzfcS4cQnRPGoIqBUP98IlAhA4wK26rY9btRj5Dt6Fg
clKGu1EPCsRBWNeK/ykAfoKwJqNdnJDTUok4yEgHHZA6EcReuZlTu5RaaoQh61IC
69hSQhMO0ZXuyQKVmmSx1LAzgcPeIUaLZzUtyKqA1GEnmB32K6QmHd1nHOatZDNs
o1IIkD2EMy4JjUu3mzDKi2rPpn977jD16XrxFGGkfOhyeYayLl+vO4gVXWmWpv1F
LrYrDjbzinD1SaBYOFFl7ar+BunJcmGOQO/StJWzDHQRmFi5yiM/nxTeK5DUSJwy
baWT0G8xYedvmOwL4s0+3OT3NwA958pvluCzAQyAYcGlnEotGVBxK7sADasHtJPQ
pIVvxkUxj0SDljpk8sdJY5K4r0uWOIy9AkZbxxxu4USw7fD+gSo7wYzH06Bsdj6x
ZyvmmmEa/V0b7e3k/AghvhqTPkZT3RFs44cGmK9SHKIBBHLMt6LEEqk1LmywtuK4
9+8=
=9DMa
-----END PGP PUBLIC KEY BLOCK-----
-----BEGIN PGP SIGNATURE-----

iHUEABYKAB0WIQQzN2BQvnncpX2uEp/3LMCDXvUIegUCab/V6AAKCRD3LMCDXvUI
euylAP9F9HHcjEg2ABQaZ3pbtOxGqqgZkAxna1zo76XWsDqWGQEAq4eJamdvVnyy
+YTOnHXfG6GswSyaavue0DlxHhx2cQ8=
=LJwp
-----END PGP SIGNATURE-----
-----BEGIN PGP PUBLIC KEY BLOCK-----

mDMEaA4PTxYJKwYBBAHaRw8BAQdAqQlRlsv3N0tK9onuKxG7RIt5AGtXyI1k35cM
WZa2jA60UnNpbWVvbndhcnJlbiAoc2ltZW9ud2FycmVuLWxhcHRvcDAxLXZtLWRl
dikgPHNpbWVvbndhcnJlbi1naXQtcHpld3FAYWx3YWxkZW5kLmNvbT6ImQQTFgoA
QRYhBDM3YFC+edylfa4Sn/cswINe9Qh6BQJoDg9PAhsDBQkB4TOABQsJCAcCAiIC
BhUKCQgLAgQWAgMBAh4HAheAAAoJEPcswINe9Qh6ofgBANcxQFFPu0SsDHzwzPoo
EETvNUIy+MOKlFWHowx+o/EEAP4iEWXFg+9ujKIn52G7Vi+MR4KT9I0gOnKKYv03
teGZCrg4BGgOD08SCisGAQQBl1UBBQEBB0BojOTJPJWTlFUdWcjnPYU1dT2B0lE6
sl3EJEY+r9PzewMBCAeIfgQYFgoAJhYhBDM3YFC+edylfa4Sn/cswINe9Qh6BQJo
Dg9PAhsMBQkB4TOAAAoJEPcswINe9Qh6dzQA+wanGg8efVClaSu9TBqqTtiIltAH
gQ8/G/6Wo1xY9DvlAP0SzZXlF5o2d0tqAuQ1MdEoXb+3TL7M6R4vxkjLvfeRDA==
=mJFu
-----END PGP PUBLIC KEY BLOCK-----
-----BEGIN PGP PUBLIC KEY BLOCK-----

mQINBGZx4nABEACnQllkFhq8bMuf9cgEqtpuJ133TWogetAW21nQUL7mKaPrrSdC
S63wR5hCTiSLpoBFSNACUTYINviIDcmseq54peOivGBQvw5ywZAznPDX7DqrrOP/
Cr6YYfIdK3bVA8filgio/NgRRaUXY0aUkUceKJhF1sjRWJoJR5nkZ6ltaHwgiW2P
mGb7stRPcn0Qa3gikbv/BTCxqKg7frQLsswcsb7lVJ/1d8xODLBQnwOFCCUwnTUV
7UL/6L7QV/hl0sBLSdmFDVVHnPAlCo46BL2LfaFRcJC123Uw4xJWaL+eN7x+hFZX
meVdDIgGWUilZM3Vau0au7i8eMwi5ezczrU/bHm7q+KnCi0KivUykDmngK4FQdC2
YkZo3mYTEnFdlfp7e4KHFB+2Yc2AgziwRbxDEuPTRTcIKfr7nlqiPEAbJSqmwQlt
u5dHYeqz6ZaeOZ3S+PqVDgznhZw1PVx0qDI5gdJY/WqlwvgjOaG9s3LwMezWvLub
P2JhpgpcXpNh1R+ShwHCawjGeJxL7GS5X0qYoarAaRdJKKsPt1dBFSyuLhwfuGL0
CaXqma5WklZDyMnAqdEufFE2bVhYZZPm7E/4O+AvNIZAeMthn1QaQnwH4pQP8H0r
jODxp+Sr0X6hmx07GDlzkvTaD7DjibqMyad5tBij4AdMYX0vTyLupVIXkwARAQAB
tCJPcGVuQmFvIDxvcGVuYmFvQGxpc3RzLmxmZWRnZS5vcmc+iQJXBBMBCABBFiEE
ZtFf3YcochnI4VR40gDNcChT5tAFAmZx4nACGwEFCThkCQAFCwkIBwICIgIGFQoJ
CAsCBBYCAwECHgcCF4AACgkQ0gDNcChT5tASvw//Wx21z9DAKHuHn597UB/O9wXz
OkhHedFEq89z6+oJj7lvpnwvK5kRqnqiajerZVcbJCeq2o55qK5Q+YQFIMzJungt
zbT1d2QM99QWHq2oJD6YB1y0eUvYe+h8kLh1ljPPflLngrZJH+OtqavaIV3TS874
o6taePVyIuGRyKrQWBaYnSra7WYoeHgLqVx3KVdIwowWI48wDfBsfs5quOzJMkdg
kbxOFgb3rMtPwW72yQGN0I7xLNZQkSchgFjuX6Ue2Q8QOCkkVn1qmf1aSgavGvpW
EcGeMGvdZlzVR451/B5NKvVWFsoT3filUQzJeAN2TiNj09wr8JyIrOxf6j0vnrwD
ClrMVdtT5yDf+ZkPBya2igISPmhuKc2jezroXu7FEqzKcXsJQSV6DWhzb0RDZ00S
2pBDDs4jNGm/svwbwfz7DaBz6PnfTIZfN0ytBcGZ8OfWHksb73GvR94UIm/B8FgQ
9911xfaj/rZOd1NoL8DEw1s4KY/QRJZgKLcBh5L/AU1yZR5dUsqg88LtDCgohnug
jMVwJFsqiAF/nsfClU/pLwNCb5MP0u9rWKt+88DLc1hVUoKJn2sb6OhQeBpcZB+v
ZKcg8OM4QsY4LRWOzi5DtA6YnBYL01C0pLal6RNAnprtKaxlaoEJLlO43rJdnDSM
llN8DKC2PndsTqVofj25Ag0EZnHjqQEQAMyuoe8era7DvgkzY0lmKiILVFs9TroV
dFMaN+oGdphpn/uwrU+/gEzGemm23pkJuRpY1joS9NRyxAObIcLQulL7dcsyiRTl
m8fz6eSUlgVHrysGuArGolJRLy/BOgN0YMq5YB5N6dbzECUu7I13GmumLyxeVkTV
Pjvob91xqHJ/8JBmTmU+VQ4/SciBfvCPUHCKUA5iP5b3YLjN7zNzZ2ZmUs4AxqWS
lVrI1HZi/K1sLqCmzjIjG3Pc3JiK4Ox87JZWsv0ZGUJwgCdgthLe/fyaUuvZtfv0
Y/4e+IO7YnrekWGy3sHqSO8npdlPpwzlTlmOqHx2VpG5DlUCDy8qh4o8ya/u5YEq
Osd1Z04PsRLzB6Rl/D/lWsaztDp2Ec2U/Bv3R+bswPlIuPe3got1Q1768GQadSz6
PoxzDXBfS+Qk3do6kCsm7AUGlmH/M0SByA7kYt/mpkPrsCaF7TWUcR6p0j/VsAI7
Lk0ipYxYly8SRKARyAR811D+QFxmhLcQNTLdhxSAKKZS4n3qp3xuGQ5qfItsAFwR
+8qH19iOpLhWm/3Rgolt19G+gVUkyZEB4c0OrwAEcgHZrIgmtnELnKoAn7LJsZh6
n3heef5gmRPPF66dqXKYZTA3TrZjKJXE0C0B+3V/qaV6SNkfWhf5WGwqJ7Ot64pJ
vr53uj6PRaflABEBAAGJBHIEGAEIACYWIQRm0V/dhyhyGcjhVHjSAM1wKFPm0AUC
ZnHjqQIbAgUJOGQJAAJACRDSAM1wKFPm0MF0IAQZAQgAHRYhBOYX3NQGXCr8Cyz3
p7qLwIwPaR+UBQJmceOpAAoJELqLwIwPaR+UQx4P/0icW/kHRw/7xN24pJP2CnmL
Rga6M2H8hV4jwc2AuFuVsi/QsZKosHtFnISitl+w3crhjb/dA5ugfeQmuZpyaem0
OIk0nJLzBEdyRBTdR4b6MvraaU63KIYN6QPdHZtmFSd99MRCh6wz+S+H+K7yIDRJ
Ok4dZ2oGzQReLymsK1Ebpxl4KOlh0fT2Jz98i2enpz3AvPBJJEh6yf3/6cqb4jOa
37RVU2fuTaYVv6WwekoqkLnec0pDPuz8LUSx9yOsmXff/g+ONge8vK/EngQu5gxw
pbmF39Ki2rlFAS6yMo4SU7C+UMcx4fa4Ysa0ZByx0iy7hhRG6XhjTWEP8TZx3tGC
JCQ4/eAjpjFPQFXeOcjJcAtVb1bQCr5f+xNdMYedIaP4RbFLfhuKaMiTzrwm1Vcc
EwV4e93oPGjYwMW72XXQUgpbDiRITYYuZ3D8h2Gu3IM1ptMlCZ9cKXfkl4TKDoyx
ZtHDGMpKlXqjgYWRweeq2ZYf5y+rL9Me0/rh4JcYUInTn/XXgw/OyP9dSJjbClJ1
JCrLYBbZwofdSj0IgOA8riMzsKZBlSzS9TMfZ+QjuMSea7tYPgYNh5IwS6g8obNR
MkAZbwc0i9wSe3nohVcI7yEYilvkd4XaO/59KUrrR3piBvcotHx1QZ4M9w7BQx3r
a3e/4l2OHp7qP002DjRe0d4QAKV7971qxuAiTBkppf+KQo2Yla0xJbQUNwEHWHfM
YrUXvpPrHmID5jCR4+RoVvoxD2QGlj7mRhfv6m+J0WiE1k/4YEFxL+a4IupcLETT
n+p4bRdkVcV2a5ujrHxLU9sPtEXPGQhMjDH43FRJWNiJDIXWTBgaE2QVLpWT5ebe
qmxYBxDmexwJkiWjtBE2BO3NBxAVAw5iIvwxaSQ5pwHKQb1QeNeNVwcXOHz3t/t5
/n0pct/RD8N6hyae0fgJwjnauqsmf05nkI0xX8gdm9zaTSEFEaL3oLrRDQ+K62my
BL8DGTF9FFKV3n7lIiAhWG6OelWc4OmOnqExMb7KAZbsOzpN0Xq+S9+sFOlBhMJj
hi4pzT6ScnFglK4rQsX0dOS8oHToCXOxtzFj2WFUOnm7qtyQGKf+rpBnThvro+ep
VY3L+BDLGAMhHZsk+UAtN9a8kVGVlXrDKeFd18JMlGtxqCNVC6PGm7TEVQJ9GU2d
M19dmvNlRud4Jy4yaKp8KtJ175xPFtF4K8REiQN1XH7GIp70UWOifxSrkuYHf6ac
/2gUPx/f77XNOhECfEzR3qJi5/AgucxM4F69iaHQUVBTjiyocmQwN/eD+VrvlC4e
c4/joxuECGIF5ElE9A6d7zKkEXl18m1eZQ15tvkFyTr3TWy/b/khRTQgW33OQPpK
p3K7uQINBGZx5RgBEAC3Qits8vR4XzyHbTc9nBcquyuy8I6uYaaixEegMZRGfM62
RmgZjyGTDGF1vwmgQb0wha35b9DD33qnDb/Ea/yhUCY43nyDdvWzjIzhPTRRTn+O
5vI48PlGGzm6VHiUrO+Ds8cGbTqalzW/04ARLEHu+1U27B8+6vi9Pd+63MJl06rZ
r6F9F6lmG3XCqtXpGUv1NTI0vuOosElny546S99IqcA1TG68XozsW3mNv3R6EQb2
YEUlh3cANvWsNGDK5gH/l7Z+PsZvJW3z2bqWkD6dU5HmEE03KnNSAbs7H1Jvt6y6
kJjTo1QwTmapEf6VZ/YJigVC4YiOmdKeqr8rIWiW6dFH7YEXOjzDlWubJw+qNz1N
oN/wJtEPG0AF4QC14G3qGi0Gzw5mcZXzC+9zXJnrdNRae2PRxpSzHfSjS8vHXwNV
oE2G5zzsnfjF5MV5e4H07mBSZ0/NZiWnkN735CaFVgXSh7MSpm8q1L4H4NL0aMFr
c91HvZo7wiNMp/vDv3Tw1Mx+H9+E2djWfazfRP6SMXuEYSH1h7EAcDWWhEdIhZcC
OIoLuL/esuaK6PUxvUxDeR7M0HiyarLwUbsCSmOz2QbuMqtFmIIPNJO/ohmNC8et
9WvDAMOGkSZ3wHfyFL5yD1sLeN2FE/B1M0F/9eLttmDaOBjY7NtRCB2zzZ8FLwAR
AQABiQI8BBgBCAAmFiEEZtFf3YcochnI4VR40gDNcChT5tAFAmZx5RgCGwwFCThk
CQAACgkQ0gDNcChT5tCXIA/+PQ4WN9+pdeo7kgVjtyOz3XqQOoo+Cg01jIEmSS0r
iN/QK7iwWlxnHrhGdSjIvjM+Frx0dNGJJGaat4AVCkfo5v33SfTvn/5luS4rQiVu
TDOOIvv5d1cs8NO9kzwNBk8zMzUMad0XDiayeNGy30PUock5Qiv+oFZJ1OjiSfJ0
DNhhcEUogDvUXaeMXY9DBxAq1SDQZZSh5M+xspuPAfw3oz17Ix07DVijqTY8FStA
GANGzqtty4lfYKJuraYOnI83hQYQSO+OT01okldrUZE5WegMhrwi9prIleHjyOdF
2z6goRSH6jraYCpIXbyzLn91nYGm6Os8p0Bgvv6aFicNXKJ7XOLAh7UcCvKVrfrn
nGIywFbOAxp/lEKAZrPQ8HYjMCbOYqntw1+4BbcgART9y9OY7xNFGxRn3kdxGD/0
ue65RfY1IikPtZDNHGTYft2N3pI802VvlK4gizRSg9OJ4Tvs2x0sSxD9/P4wlwga
B6hw4NTXUre2bFUezE2gvHAnzKf6kN/59hmsQBB0QGOo9Bdt+c/17yT/TImGaf2E
XGyohhRqHw0vTn8GgnQtPQoip9cnDzU5c/MpS28A4yGxG46fIpMRIJ7bX1k/V0Az
Fd9lHWrRp+XQLjT/Y28NrFKHgOWKZZfTC+K5zax2sEezDFIMSpCmBy3rLjLl2JbY
f3S5Ag0EZnHlvgEQANi0HuC3XJiEQhlD+qciZW9fPSqsgPL0wX+x9qICBLuueWQk
5wZ+Oo476/VVy4Q6bGU/lpyDN2tiv/CQ/vejFsau90qMMsf1QlAVwNC/QFrUhDnZ
vjPjajORZuSad22efnRa8+PLTk0Iow/aqQefv0esINl6Ial7fEuBP0BG+BzU0c7+
zKHjAcqVwqtzyn0my/PqBlsXLJthwjqCiBMBLwf8BwkCsYEdOysHpsEZJUF4mQKs
Cm6QRSZylyyHnFvAk4RiVdVXZDx8HyIiKQw22H+kUYR6y6977Gi9dV2zOzwIgY43
RBBTCmiGpkbeIE6gtL1P5W8VMGwhdWVRCKK+6sB+Txlwo2iCUchuBbsVI5QoDKn4
JvzTEVMBGNH3hkIKg2atrZJ+vOaQk5ZVdmpbcPZ7rx88zFnKS2XwRrwgO82HUSNR
RLqUzf3bioNNxFGmtwcwTafT0feeFPFCs6TZWcaPtb32qYUdcoU+ZFXMNGk0k++Q
rqfbMvlVD5mn2VuCG3pzmk5oxg8OfqyaUv2Rr2DgMEm2mjtDR/SSRA9g37FMihe/
i7bRXI6JeCDQe9k9kpygvOb6lxRwScS8b5Po2YOLUd9TW+bHmaPXTnkEjfOk/Z8w
2I7nrUz44/aL7XVf2pyzKKgoTlzM52mNvYH+WKF/0g2nz2kYsZqF61VXC+RLABEB
AAGJAjMEGAEIACcWIQRm0V/dhyhyGcjhVHjSAM1wKFPm0AUCZnHlvgMbIAQFCThk
CQAAAOqDEACBwdvGyhm2vO4ZsnLmfq88OR0HCa2SsdB66XBF4e9EN0d4fNQkqQz0
6xq4Z4Pr3dIu41yrlKJhtK3wWbs4mpqGpUU4SXmlAJrh5G3QBzhoQNJwRSxBUu1H
7wYWZDfNzALQyHzfn8KUt9j9F5J7T80Uk9yT5ni27N5oTZBFoLZvf1441qdOPvkm
2XZiNS3/y57+N8J6x8Uk4ruE8/2c4Br008MXlX5ELmpbAW7yVFi6C+TvoM5QJgBs
cz6wz7bz6ZLtZmAeRZACx8teNr5sl64lKdZ74fVibPxQ2zYJLs/MCJ8H3hcjLAk7
RGfuZMKTmiacTihTTxtrQH7l6kB5oTYLkEZ5anP+Rl1m4PtHj/L7td/Af1iBBfdm
7MM3utNxRmQUC0lYw/058riksFWLQfHvgb/yICXG2TN0Q+75MHbnXknsi+8amw0z
Rb50sYi2GBa5NII+gj+2jXtakz2RlWhN0+XuTtBMHKNLpe1qh64tLrVjHGivAZwi
wIUySjVgdn9TKStReSyaDLUuYWnd3g2bKlBRjA0AIixnkEGxgajk5moaLpTHmXv4
qsIrrWjvFS0QOmuChHODqPKVR6T681HbElUkhDOBnMgRMyWxRc6WWV06IUrXZOdD
HJyC+hbV9j8H8Hwvq1RKzHeMaofejSqTJxBR8wExXC12PN7uon0DCA==
=coUG
-----END PGP PUBLIC KEY BLOCK-----

5.8 - ssh

Ssh keys

CA for SSH clients

Source: ../../infra/vault/tf/output

Update: automatically

CA for SSH servers

Source: ../../infra/vault/tf/output

Update: automatically

Source ./simeonwarren@alwaldend.com-2026-03-22-openpgp.pub

Update: manual export from the yubikey

5.9 - Ssl

SSL certificates

5.9.1 - Alwaldend.com

Alwaldend.com certificates

Source: ./root_ca.crt

Update: manually

Source: ./ica1.crt

Update: manually

Source: ../../../infra/vault/tf/output

Update: automatically

Source: ../../../infra/vault/tf/output

Update: automatically

6 - Third party

Third party tree

This tree contains vendored and externally sourced code. All tracked content follows the repository’s public-source policy and retains its upstream license and provenance requirements.

  • Bazel targets MUST use repository-internal visibility unless an owning toolchain contract requires otherwise.
  • Third-party content MUST NOT be represented or published as first-party source or artifacts.
  • Third-party content MAY be used in builds.
  • An explicit repackaging or mirroring target MAY publish an upstream artifact under its owner and license policy.

This is a state-changing operator example. An agent needs explicit publication authority and must invoke the target through bazel_agent.

bazel_agent bazel run //third_party:publish_helm.io_goharbor_helm_harbor

6.1 - ai_opencode_opencode

Opencode - The open source AI coding agent

6.2 - com_drawio_desktop_bin

Drawio desktop app

6.3 - com_github_bazelbuild_bazel_protobuf

Bazel protobuf contracts

6.4 - com_github_bazelbuild_bazelisk

Bazelisk

6.5 - com_github_georgewfraser_java_language_server

Java language server using the Java compiler API

6.6 - com_nanovms_ops

Ops CLI binary

6.7 - com_nousresearch_hermes_agent

Hermes Agent - an open-source AI agent by Nous Research

6.8 - com_truenas_scale

TrueNAS SCALE installer image

6.9 - dev_sanaei_3xui

3x-ui

6.11 - Images

Deploy of VM images
bazel run //third_party/images:deploy_proxmox
bazel run //third_party/images:deploy_yc

6.11.1 - Tf

Terraform config

6.12 - io_cert_manager_cmctl

Cert Manager cmctl

6.13 - io_controlplane_flux_operator

Flux operator

6.14 - io_docker_library_alpine

Alpine image from Dockerhub

6.15 - io_getsops_sops

Sops

6.16 - io_goharbor_harbor_cli

Harbor CLI

6.17 - io_goharbor_helm_harbor

Harbor

6.18 - io_goharbor_offline_installer

Offline installer for Harber

6.19 - io_k3s_k3s

K3s

6.20 - io_kubernetes_kubectl

Kubectl

6.21 - io_traefik_traefik

Traefik

6.22 - net_zlib_zlib

Zlib

6.23 - org_codeberg_forgejo

Forgejo

6.24 - org_codeberg_forgejo_bin

Forgejo binary

6.25 - org_codeberg_forgejo_contrib_forgejo_cli_bin

Forgejo CLI

6.26 - org_codeberg_forgejo_runner_bin

Forgejo Actions runner binary

6.27 - org_fedora_cloud

Fedora Cloud image

6.28 - org_kernel_headers

Linux kernel headers
zcat /proc/config.gz >third_party/org_kernel_headers/config.txt

6.29 - org_nmap_nmap

Nmap

6.30 - org_openssl_openssl

OpenSSL

6.31 - org_pcre_pcre2

PCRE - Perl Compatible Regular Expressions

6.32 - org_xcp_ng

XCP-ng installer image

6.33 - sh_helm_helm

Helm

6.34 - us_nasm_nasm

NASM - The Netwide Assembler

7 - Users

User tree

This tree contains user-specific code and infrastructure. Tracked source follows the repository’s public-source policy. Personal information and secrets must not be tracked or disclosed. Non-secret, non-personal operational facts remain public even when they describe generated or live state.

  • Bazel targets MUST use repository-internal visibility.
  • User artifacts MUST NOT be published.
  • User targets MUST NOT be dependencies of production build targets.

7.1 - simeonwarren

simeonwarren
bazel run //users/simeonwarren:gen_client_cert -- --host phone1 --ttl "180d" --output_dir "${PWD}/certs"
bazel run //users/simeonwarren:opencode -- "${PWD}"
bazel run //users/simeonwarren/tf:tf.apply
ln -s "${PWD}/users/simeonwarren/opencode.json" ~/.config/opencode/opencode.json
ln -s "${PWD}/users/simeonwarren/tui.json" ~/.config/opencode/tui.json

7.1.1 - Ansible

Ansible setup

7.1.2 - Host Bot

host-bot.simeonwarren.users.alwaldend.com

Host Bot runs Traefik with mTLS in front of T3 Code. The host firewall blocks direct external access to T3 Code and accepts new connections only on SSH, HTTP, and HTTPS ports.

T3 Code controls permissions per thread. Its Auto mode maps to Codex Auto-review. The managed Codex requirements allow read-only and host-bot permissions with on-request approvals, so threads cannot select Full access or disable approvals. The requirements file only allowlists the host-bot profile; it must not define the profile because T3 Code supplies a per-thread config layer with the same name, and Codex rejects profiles defined by both requirements and config. The normal and isolated provider configs define host-bot with workspace writes, public command-network access, and write access to the Bazel cache and Bazelisk directories while keeping local network binding and loopback connections available for Bazel servers. Other private network targets remain blocked. T3 Code must select that profile for the thread. Hosted web search is not restricted by this role.

The deployment installs pinned Bazelisk as ~/.local/bin/bazel, provisions the repository’s bazel_agent runner in the same directory, and pre-seeds its content-addressed mcp_cordis and repo_delivery runtimes when the canonical repository checkout is present. New Codex worktrees can then start Cordis and run delivery operations without first loading their own Bazel graph.

Two SATA SSDs, selected by their stable ATA IDs, back the sata_ssd volume group. Its striped bazel_cache logical volume is mounted persistently at /var/cache/bazel. Every Bazel workspace uses its disk_cache directory and the managed user bazelrc points its output-user root at the same filesystem. Automatic garbage collection caps the action disk cache at 700 GiB, leaving room within the 1-TiB filesystem for output bases and install state; the volume group retains about 900 GiB for later growth or another logical volume. Because the volume is striped, either SSD failing invalidates the disposable cache.

The managed user bazelrc limits each Bazel invocation to eight concurrent jobs and budgets half of the host CPUs for local actions. These scheduling limits apply to builds and tests; they do not impose a combined CPU cap across independent Bazel processes or Codex sessions.

Executable repository tools use /var/cache/bazel/tool_cache. Unlike the disposable action and output caches, this directory is private to the host-bot account. Cache entries are keyed by declared source, build configuration, platform, and dependency pins, and are installed atomically after a Bazel build on the first miss.

The arXiv MCP server is pinned to version 0.7.2 and runs locally over stdio. Its downloaded papers and search data live under /srv/misc/arxiv-mcp-server/papers on a reusable 100-GiB misc logical volume in the existing sata_ssd volume group. The volume is mounted for reconstructible non-executable application data. Data with durability or different reliability requirements belongs on a separate volume.

The managed Codex configuration allows up to 20 concurrent subagents per session. The root agent is accounted for separately.

Node.js and npm are provisioned through the development VM role’s mutable or OSTree package backend. Open Computer Use 0.3.3 is then installed without npm lifecycle scripts under the managed user’s ~/.local prefix. Its skill is then installed for the whole host under /etc/codex/skills from the matching immutable upstream revision. The deployment configures its stdio MCP server in the normal Codex config and the isolated OpenRouter and Abliteration homes. The MCP can inspect and control the logged-in desktop session, so agents must treat its actions as real user input and obtain approval before externally visible or destructive actions.

OpenRouter is available through its isolated Codex home. Its configuration reads its API key from the desktop keyring entry selected by service=openrouter and application=codex; the key is not stored in the configuration. Repository work uses the repo-owned $codex-migration skill, while the user-level Codex instructions require isolated migration testing and intentional host changes to be mirrored into this role. Existing sessions are not redirected because provider-bound encrypted reasoning history cannot safely migrate in place.

T3 Code can use OpenRouter as a separate Codex provider by setting its CODEX_HOME path to /var/home/simeonwarrenbot/.codex-openrouter. That isolated home defaults to ~deepseek/deepseek-v4-flash-latest and shares no conversation state with the ChatGPT-backed Codex provider. Start a new thread when selecting it.

Abliteration uses a separate home with CODEX_HOME="$HOME/.codex-abliteration" codex, using the endpoint and model from its Codex integration guide. It retrieves its API token at runtime with secret-tool, selecting service=abliteration and application=codex. Save the token from an interactive terminal in the same user’s desktop keyring:

secret-tool store --label='Abliteration API token for Codex' service abliteration application codex

Enter the token at the hidden prompt. The configuration contains only the lookup command. Provider response and tool-call validation require a saved token. Both providers keep their configuration and conversation state outside the main Codex home; provider profiles in the main home are removed. For T3 Code, set its CODEX_HOME path to /var/home/simeonwarrenbot/.codex-abliteration and start a new thread.

T3_MCP_BEARER_TOKEN authenticates the Codex app-server’s loopback MCP connection to T3 Code at /mcp. Codex excludes it from model-spawned commands so those subprocesses do not inherit the credential.

bazel run //users/simeonwarren/host_bot/ansible

7.1.2.1 - Ansible

Host Bot Traefik configuration

7.1.3 - Tf

Terraform config

8 - Examples

Examples of using these rules