From bb54908d1cf7a2ec060c63626e78b8ee0ac7a692 Mon Sep 17 00:00:00 2001 From: Claude Date: Sun, 20 Sep 2026 23:45:22 +0000 Subject: [PATCH 01/13] feat(spec): explore one specification, many languages Adds `spec/`, a prototype of describing a utility once as language neutral data and emitting it to every language Brazilian Utils publishes. Nothing under `src/` changes and nothing here ships in the npm package. `spec/EXPLORATION.md` is the write-up: what it proves, what it does not cover, why transpiling TypeScript and a shared native core were rejected, and the suggested order of work. What is in the prototype: - `spec/utilities/*.json` specify `isValidCpf`, `isValidPis` and `formatCpf` as pipelines over explicit charsets and check digit algorithms. A utility has named profiles, and each package declares which one it implements today, so generated code reproduces current behaviour instead of replacing it. - `spec/codegen/interpret.ts` is the reference implementation; the six emitters under `spec/codegen/targets/` turn the same specs into idiomatic TypeScript, Python, Go, Ruby, Rust and Java. - `spec/vectors/conformance.json` holds 743 seeded inputs with the answer every profile gives, and the conformance drivers check each language against it. Results, all reproducible with `bash spec/conformance/run-all.sh`: - the spec agrees with the package this repository ships on 11,928 checks, hostile inputs included; - every generated target passes its vectors; - the spec agrees with the published Python, Ruby, Go and Rust packages on 743/743 corpus inputs each, with two documented deviations in Python. Findings worth acting on, recorded in the specs and the write-up: the six packages already give four different answers for a masked CPF; `brutils` accepts a CPF written in Arabic-Indic digits because it gates on `str.isdigit()`; PIS diverges the other way, with four packages accepting `"00000000000"` and rejecting masks; and regex shorthands (`\d`, `\s`, Ruby's line anchors, Java's pre-lexing `\uXXXX`) do not survive a port, which is why the IR carries code points instead of regexes. Config: `vite.config.ts` gains a lint override for `spec/**` (console output, running other toolchains from PATH, asserting the shape of its own JSON) and keeps the generated vectors out of the formatter. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01UX1gTGeMTyoXQyr1qUoQKd --- .gitignore | 1 + CONTRIBUTING.md | 5 + spec/EXPLORATION.md | 232 ++++++++ spec/README.md | 75 +++ spec/codegen/conformance.ts | 576 ++++++++++++++++++++ spec/codegen/corpus.ts | 145 +++++ spec/codegen/emit.ts | 41 ++ spec/codegen/interpret.ts | 347 ++++++++++++ spec/codegen/ir.ts | 153 ++++++ spec/codegen/plan.ts | 179 ++++++ spec/codegen/targets/go.ts | 413 ++++++++++++++ spec/codegen/targets/java.ts | 431 +++++++++++++++ spec/codegen/targets/python.ts | 360 ++++++++++++ spec/codegen/targets/registry.ts | 20 + spec/codegen/targets/ruby.ts | 346 ++++++++++++ spec/codegen/targets/rust.ts | 374 +++++++++++++ spec/codegen/targets/typescript.ts | 364 +++++++++++++ spec/codegen/vectors.ts | 81 +++ spec/conformance/differential-javascript.ts | 132 +++++ spec/conformance/probes/go-probe.go | 40 ++ spec/conformance/probes/python-probe.py | 40 ++ spec/conformance/probes/ruby-probe.rb | 19 + spec/conformance/probes/rust-probe.rs | 111 ++++ spec/conformance/run-all.sh | 26 + spec/conformance/upstream.ts | 178 ++++++ spec/schema/charsets.json | 39 ++ spec/schema/check-digits.json | 25 + spec/schema/utility.schema.json | 237 ++++++++ spec/utilities.json | 4 + spec/utilities/format-cpf.json | 134 +++++ spec/utilities/is-valid-cpf.json | 155 ++++++ spec/utilities/is-valid-pis.json | 127 +++++ spec/vectors/conformance.json | 1 + vite.config.ts | 22 +- 34 files changed, 5432 insertions(+), 1 deletion(-) create mode 100644 spec/EXPLORATION.md create mode 100644 spec/README.md create mode 100644 spec/codegen/conformance.ts create mode 100644 spec/codegen/corpus.ts create mode 100644 spec/codegen/emit.ts create mode 100644 spec/codegen/interpret.ts create mode 100644 spec/codegen/ir.ts create mode 100644 spec/codegen/plan.ts create mode 100644 spec/codegen/targets/go.ts create mode 100644 spec/codegen/targets/java.ts create mode 100644 spec/codegen/targets/python.ts create mode 100644 spec/codegen/targets/registry.ts create mode 100644 spec/codegen/targets/ruby.ts create mode 100644 spec/codegen/targets/rust.ts create mode 100644 spec/codegen/targets/typescript.ts create mode 100644 spec/codegen/vectors.ts create mode 100644 spec/conformance/differential-javascript.ts create mode 100644 spec/conformance/probes/go-probe.go create mode 100644 spec/conformance/probes/python-probe.py create mode 100644 spec/conformance/probes/ruby-probe.rb create mode 100644 spec/conformance/probes/rust-probe.rs create mode 100755 spec/conformance/run-all.sh create mode 100644 spec/conformance/upstream.ts create mode 100644 spec/schema/charsets.json create mode 100644 spec/schema/check-digits.json create mode 100644 spec/schema/utility.schema.json create mode 100644 spec/utilities.json create mode 100644 spec/utilities/format-cpf.json create mode 100644 spec/utilities/is-valid-cpf.json create mode 100644 spec/utilities/is-valid-pis.json create mode 100644 spec/vectors/conformance.json diff --git a/.gitignore b/.gitignore index 7a784b1d1..73265048d 100644 --- a/.gitignore +++ b/.gitignore @@ -19,3 +19,4 @@ reports/* !reports/api/ reports/api/* !reports/api/brazilian-utils.api.md +spec/generated diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index cb98fd889..40b5c00db 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -84,6 +84,11 @@ but the few rules below hold everywhere: npm registry; [MAINTAINERS.md](MAINTAINERS.md) lists who can change what, and [SECURITY.md](SECURITY.md) how a release is verified. +`spec/` is not part of the published package and nothing under `src/` depends on it: it is a +prototype of describing a utility once, as language neutral data, and emitting it to the other +Brazilian Utils packages. Read [spec/EXPLORATION.md](spec/EXPLORATION.md) for what it proves and +[spec/README.md](spec/README.md) for how to run it. + The actors around the code are the consumers of the npm package, the contributors (pull requests from forks), the maintainers (review, merge, release approval) and the automation: GitHub Actions builds, tests and publishes, Dependabot and the `Update datasets` workflow open update pull requests, and diff --git a/spec/EXPLORATION.md b/spec/EXPLORATION.md new file mode 100644 index 000000000..1eecb84ba --- /dev/null +++ b/spec/EXPLORATION.md @@ -0,0 +1,232 @@ +# One implementation, every language + +An exploration of whether Brazilian Utils can be written once and shipped in JavaScript, Python, +Go, Rust, Ruby, Erlang, .NET and whatever comes next, **without changing what any published +package does today**. + +Everything claimed here is reproducible from this repository: + +```bash +bash spec/conformance/run-all.sh # 6 languages, generated and checked +node spec/conformance/upstream.ts --python ../python --ruby ../ruby --go ../go --rust ../rust +``` + +--- + +## The short answer + +Yes — but the thing to write once is **not code**. It is a specification, and code generation is +the last and most optional step of the three. + +| Layer | What it is | Who consumes it | Risk to existing packages | +| ------------ | -------------------------------------------------------------------------- | ---------------------------------------- | ------------------------------------------------------------------------- | +| L0 — Vectors | A list of inputs and the answer each named behaviour gives | Every package's test suite | None. It is a test file. | +| L1 — Spec | The behaviour itself, as data: charsets, check digit algorithms, pipelines | The generator, the reviewers, new ports | None. Nothing ships it. | +| L2 — Codegen | Idiomatic source for each language, emitted from L1 | Packages that opt in, utility by utility | None **by construction** — see [Profiles](#how-a-contract-survives-this). | + +Writing the algorithm once means writing it at L1. L2 is how a package stops re-typing it, and a +package can adopt L2 for `isValidCpf` and keep everything else handwritten. + +**Writing it in Rust and generating the rest is the wrong shape of the same idea.** Rust source is +still a language: to read it from Go you either transpile it (same problems as transpiling +TypeScript, below) or ship it as a native artifact, which costs this project the things it sells — +zero dependencies, tree shaking, Bun/Deno/browser parity, a pure gem, a pure wheel, a pure BEAM +library. A specification has no host language, so no package is anyone's downstream. + +--- + +## What was built to test the claim + +Three utilities — `isValidCpf`, `isValidPis`, `formatCpf` — were specified as data and emitted to +six languages, including Java, which has no package today. + +``` +spec/ + utilities/*.json the utilities: profiles, pipelines, names per language (416 lines) + schema/ charsets, check digit algorithms, the JSON Schema + codegen/ the reference interpreter and the six emitters (3,830 lines) + vectors/conformance.json 743 inputs x 13 expectations, generated (100 KB) + conformance/ the differential runners + generated/ output, not committed: `node spec/codegen/emit.ts` +``` + +The 416 lines of specification produce 1,647 lines of library code across the six languages, plus +the conformance drivers. A new language costs one emitter of 350–430 lines and buys every utility +already specified. + +### Results + +| Check | Result | +| ------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------- | +| Spec vs. the package **this repository ships** (`src/`) | **11,928/11,928** agree, over 1,983 corpus inputs plus `null`, `undefined`, numbers, `NaN`, arrays, objects | +| Generated TypeScript vs. vectors | 4,458/4,458 | +| Generated Python / Ruby / Go / Rust vs. vectors | 2,229/2,229 each | +| Generated Java vs. vectors | 4,458/4,458 | +| Spec vs. the **published** `brutils` (Python) | 741/743, plus 2 documented deviations | +| Spec vs. the **published** gem (Ruby) | 743/743 | +| Spec vs. the **published** Go module | 743/743 | +| Spec vs. the **published** Rust crate | 743/743 | + +The corpus is seeded and deterministic (`spec/codegen/corpus.ts`): valid numbers, masked numbers, +numbers with one digit flipped, junk, Unicode whitespace, NBSP, ZWNBSP, an emoji with a surrogate +pair, and CPFs written in full width and Arabic-Indic digits. + +--- + +## Four things the exercise turned up + +### 1. The contracts already disagree — badly + +This is the central finding. The worry was "let us not create an issue by unifying". The issue +exists now, and nobody can see it because nothing compares the packages. + +| Input | JavaScript | Python | Ruby | Rust | Erlang | Go | +| --------------------------------------- | ---------- | --------- | ------- | ------- | ------- | --------- | +| `"12345678909"` | valid | valid | valid | valid | valid | valid | +| `"123.456.789-09"` | **valid** | invalid | invalid | invalid | invalid | **valid** | +| `"123 456 789 09"` | **valid** | invalid | invalid | invalid | invalid | **valid** | +| `"abc12345678909"` | invalid | invalid | invalid | invalid | invalid | **valid** | +| `"12345678909"` (full width) | invalid | **valid** | invalid | invalid | invalid | invalid | + +Four different answers to "is this a CPF". A user who validates a masked CPF in the browser and +again in a Python backend gets two verdicts today. + +The JavaScript, Python, Ruby, Rust and Go columns were produced by running those packages +(`spec/conformance/upstream.ts`). The Erlang column was read from `brutils_cpf.erl`, whose +`is_valid/1` requires a binary of exactly 11 ASCII digits; no Erlang toolchain was available here +to execute it. + +### 2. `brutils` accepts a CPF written in Arabic-Indic digits + +`brutils/cpf.py` and `brutils/pis.py` gate on `str.isdigit()`, which is Unicode aware, so +`"١٢٣٤٥٦٧٨٩٠٩"` validates and `format_cpf` returns `"١٢٣.٤٥٦.٧٨٩-٠٩"`. Ruby's `/^\d+$/` and Rust's +`is_ascii_digit` do not. This is recorded in the specs as a `knownDeviations` entry, and it is a +bug report waiting to be filed against the Python package. + +### 3. PIS is the mirror image of CPF + +The JavaScript package rejects `"00000000000"` as a PIS and accepts `"120.56874.10-7"`. Python, Go, +Ruby and Rust do the opposite on **both** counts: they accept the repeated run and reject every +mask. 66 of 743 corpus inputs differ. Neither side is obviously right; neither side knows. + +### 4. A regex is not portable, so the spec has none + +`\s` matches 6 characters in Go and Ruby, 25 in JavaScript, and a Unicode property in Python and +the Rust `regex` crate. `\d` matches Devanagari digits in Python. Ruby's `^`/`$` are line anchors, +not string anchors. Java expands `\u000a` _before_ lexing, so a generated string literal containing +one ends on a real line break — which is exactly how the first Java emitter failed here. + +So the IR carries no regex: a charset is a list of code points +(`spec/schema/charsets.json`), and the shape of a masked number is digit group sizes plus a +separator set. Every emitter renders that as explicit comparisons. This is the concrete reason a +naive "transpile the TypeScript" approach cannot be trusted: the regexes would survive the +translation and quietly change meaning. + +--- + +## How a contract survives this + +A utility does not have _a_ behaviour. It has **profiles**, and each package declares which one it +implements today: + +```jsonc +"adopted": { + "typescript": { "profile": "masked-strict" }, + "python": { "profile": "digits-only", "knownDeviations": [ /* the Unicode digits bug */ ] }, + "go": { "profile": "digits-extracted" } +}, +"profiles": { + "masked-strict": { "description": "...", "pipeline": [ /* ... */ ] }, + "digits-only": { "description": "...", "pipeline": [ /* ... */ ] }, + "digits-extracted": { "description": "...", "pipeline": [ /* ... */ ] } +} +``` + +Three consequences: + +1. **Generating a package is a no-op release.** The Go emitter produces Go's lenient behaviour, the + Ruby emitter produces Ruby's strict one. The proof is in the table above: the generated code and + the published code agree on every corpus input. +2. **Convergence becomes a decision, not an accident.** Moving Python from `digits-only` to + `masked-strict` is a one line change whose blast radius the vectors print exactly: these inputs, + this many, changing from this answer to that one. That is a major version conversation with data + attached, per package, on each package's own schedule. +3. **A new language starts on the canonical profile.** Java here adopts `masked-strict` from day + one, because there is no installed base to protect. + +--- + +## What this does not solve + +Of the 138 utilities in `src/`, the ones that are a pipeline over digits are the large majority, +but not all of them: + +| Group | Count | Portable as data? | +| ------------------------------------------------------------------------------------ | ----- | ----------------------------------------------------------------------------------------- | +| Digit/mask pipelines (`isValid*`, `format*`, `parse*`) | ~89 | Yes — this is what the prototype covers | +| Dataset lookups (banks, municipalities, CNAE, CBO, CFOP, NCM, legal natures, states) | 25 | The logic is trivial; the value is the table. See below. | +| Random generators (`generate*`) | 13 | The construction is; the RNG and its seeding are per language. | +| Date logic (holidays, business days, date to words) | 9 | Partly. Easter and the holiday table are data; the calendar type is not. | +| HTTP (`getAddressInfoByCep`, `getCepInfoByAddress`) | 2 | The provider list, the fallback order and the error taxonomy are data. The client is not. | +| Locale formatting (`formatCurrency`) | 1 | `Intl`/CLDR has no equivalent in Go or Erlang. Handwritten, or a shared CLDR subset. | + +(24 utilities depend on a host facility — a clock, an RNG, `Intl` or the network — and 12 of those +also read a dataset, so the rows overlap slightly.) + +Trying to specify all of it in one IR is how this kind of project dies. The IR should grow one +utility family at a time, and anything that resists it stays handwritten — that is a normal +outcome, not a failure. + +**The dataset question is separate and probably worth more.** `src/_internals/constants/` (banks, +municipalities, CNAE, CBO, CFOP, NCM, legal natures) is already generated from official sources by +`scripts/`. Every other package either re-scrapes those sources or does without. Publishing those +tables as a versioned, language neutral artifact is less work than any of the above and removes +more duplication. + +--- + +## Why not the other two options + +**Transpile the TypeScript.** The semantics that would have to come along are `String()` coercion, +`NaN`, `null` vs `undefined`, UTF-16 versus scalar iteration, `Intl`, and the regex differences +above. The output would be unreviewable by the people who maintain the Go and Ruby packages, and +the generated names would not match what those packages publish. The value of these libraries is +that they read like ordinary Go and ordinary Ruby. + +**One core in Rust, bindings everywhere.** It breaks the npm package's zero dependency, +tree shakeable, Bun/Deno/browser promise; it forces a native toolchain on the gem and the wheel; +it has no answer for Erlang or for a pure .NET assembly; and every binding still needs a +handwritten shell with its own contract. Worth revisiting only for something genuinely heavy, which +none of these utilities are. + +--- + +## Suggested order of work + +1. **Publish the vectors** (no code changes anywhere). A `brazilian-utils/spec` repository holding + `charsets`, `check-digits`, the utility specs and `conformance.json`. Each package adds one test + that reads it. The payoff is immediate: every package learns, in CI, exactly how it differs from + the others. +2. **File the divergences as issues**, one per finding above, in the package that owns each. +3. **Specify the ~40 document number utilities** (CPF, CNPJ, CEP, PIS, CNH, CNS, CNO, CEI, CAEPF, + NFe key, RENAVAM, voter ID, boleto, IBAN, Pix keys, plates...). This is the bulk of the + duplicated work and the part the IR already covers. +4. **Opt into codegen where maintainers want it.** The Erlang and .NET packages, which cover the + fewest utilities, gain the most: an emitter each, and they inherit everything specified. +5. **Converge profiles deliberately**, one package major version at a time, with the vector diff in + the release notes. + +Steps 1 and 2 are worth doing even if steps 3 to 5 never happen. + +--- + +## Open questions for the team + +- Which profile should be the canonical one? The JavaScript package is the most permissive on masks + and the strictest on shape; is "accepts the mask a human would type" the contract we want + everywhere? +- Should `spec` be its own repository, or live here with the other packages reading it by tag? The + prototype lives here because that is where the most complete implementation is, not because that + is the right home. +- Who owns a profile change? Today each package owns its behaviour. A shared spec needs one place + where "CPF accepts masks" is decided. diff --git a/spec/README.md b/spec/README.md new file mode 100644 index 000000000..7455ffba0 --- /dev/null +++ b/spec/README.md @@ -0,0 +1,75 @@ +# `spec/` — the language neutral specification + +A prototype of describing a utility once, as data, and emitting it to every language Brazilian +Utils publishes. Read [EXPLORATION.md](EXPLORATION.md) first: it explains why this exists, what it +proves, what it does not, and what to do next. + +Nothing here ships in the npm package. `src/` is untouched, and the build, the bundle and the +public API are exactly what they were. + +## Layout + +| Path | What it holds | +| ---------------------------- | ---------------------------------------------------------------------------------------------- | +| `utilities/*.json` | One file per utility: its profiles, the pipeline of each, and the name every language gives it | +| `utilities.json` | The utilities the specification covers, in emission order | +| `schema/charsets.json` | Character sets as explicit code points — never a regex shorthand | +| `schema/check-digits.json` | Check digit algorithms as weights, modulus and clamp | +| `schema/utility.schema.json` | JSON Schema of a utility file | +| `codegen/interpret.ts` | The reference interpreter: the normative implementation | +| `codegen/corpus.ts` | The seeded input corpus | +| `codegen/vectors.ts` | Writes `vectors/conformance.json` from the interpreter | +| `codegen/targets/*.ts` | One emitter per language | +| `vectors/conformance.json` | The committed vectors: every input, every profile, every option set | +| `conformance/` | The runners that check the generated code, this package, and the published ones | +| `generated/` | Emitter output. Not committed; `node spec/codegen/emit.ts` rebuilds it | + +## Running it + +```bash +node spec/codegen/vectors.ts # rebuild the vectors from the interpreter +node spec/codegen/emit.ts # emit every target into spec/generated +node spec/codegen/emit.ts rust # ...or just one + +bash spec/conformance/run-all.sh # emit, then run all six conformance drivers +node spec/conformance/differential-javascript.ts # spec vs. the package this repo ships +``` + +`run-all.sh` needs `node`, `python3`, `ruby`, `go`, `rustc` and `javac` on the PATH; each driver is +standalone and needs no package manager. + +To compare the specification against the other packages, check them out as siblings and point the +upstream runner at them: + +```bash +node spec/conformance/upstream.ts --python ../python --ruby ../ruby --go ../go --rust ../rust +``` + +It prints, per package and per utility, how many of the corpus inputs agree with the profile that +package declares, and the first few that do not. `0 disagreement(s)` means the specification +describes every shipped contract exactly. + +## Adding a utility + +1. Write `utilities/.json`. Give it one profile per behaviour that exists in the wild, and an + `adopted` entry per language saying which one that package implements **today** — not the one + you wish it implemented. Add it to `utilities.json`. +2. Run `node spec/conformance/upstream.ts ...` against the other checkouts. If a package + disagrees with the profile you gave it, the profile is wrong, or you found a bug: record it + under `knownDeviations` with a reason, and open an issue there. +3. Run `node spec/codegen/vectors.ts` to refresh the vectors, then `bash +spec/conformance/run-all.sh`. +4. For a utility this repository already ships, extend `conformance/differential-javascript.ts` so + the specification is checked against the handwritten implementation over the whole corpus, + hostile inputs included. + +If a utility needs a step the IR does not have, add the step to `schema/utility.schema.json`, to +`Step` in `codegen/ir.ts`, to the interpreter, and to the six emitters — in that order. That cost +is the honest price of a new kind of behaviour, and it is why the IR should stay small. + +## Adding a language + +Write `codegen/targets/.ts` (350–430 lines, modelled on any existing one), register it in +`codegen/targets/registry.ts`, add a driver in `codegen/conformance.ts`, and add the language's +`names` and `adopted` entries to each utility file. The Java target exists precisely as the worked +example of a language with no package yet. diff --git a/spec/codegen/conformance.ts b/spec/codegen/conformance.ts new file mode 100644 index 000000000..8a45d8bc5 --- /dev/null +++ b/spec/codegen/conformance.ts @@ -0,0 +1,576 @@ +/** + * Emits the conformance driver for each target: a standalone program that runs the generated + * functions over the committed vectors and exits non zero on the first disagreement. + * + * The vectors are inlined into the driver rather than parsed at run time, so a target language + * needs no JSON library and the check is literally the same in all six. Every output is + * compared as a string: a validator's verdict as `"true"`/`"false"`, a formatter's absent value + * as `""`. + */ +import { type Plan, type PlannedFunction } from "./plan.ts"; +import { type Vectors } from "./vectors.ts"; + +const NONE = ""; + +/** + * Escapes a string into a target language literal. + * + * @param {string} value - The text to literal. + * @param {Function} unicode - Renders one non printable or non ASCII code point. + * @param {Record} [extra] - Characters the language escapes on top of `"` and `\`. + * @returns {string} The literal, quotes included. + */ +const escapeWith = ( + value: string, + unicode: (code: number) => string, + extra: Record = {}, +): string => { + let literal = '"'; + + for (const char of value) { + const code = char.codePointAt(0) ?? 0; + + if (Object.hasOwn(extra, char)) literal += extra[char]; + else if (char === '"') literal += String.raw`\"`; + else if (char === "\\") literal += String.raw`\\`; + else if (code < 0x20 || code > 0x7e) literal += unicode(code); + else literal += char; + } + + return `${literal}"`; +}; + +/** + * The control characters Java spells with their own literal: a `\uXXXX` literal is expanded + * before lexing, so `\u000a` would end the literal on a real line break. + */ +const JAVA_CONTROL: Record = { + 0x08: String.raw`\b`, + 0x09: String.raw`\t`, + 0x0a: String.raw`\n`, + 0x0c: String.raw`\f`, + 0x0d: String.raw`\r`, +}; + +const utf16 = (code: number): string => { + if (code < 0x20) return JAVA_CONTROL[code] ?? `\\${code.toString(8).padStart(3, "0")}`; + if (code <= 0xff_ff) return `\\u${code.toString(16).padStart(4, "0")}`; + + const offset = code - 0x1_00_00; + + return `\\u${(0xd8_00 + (offset >> 10)).toString(16).padStart(4, "0")}\\u${(0xdc_00 + (offset & 0x3_ff)).toString(16).padStart(4, "0")}`; +}; + +const braced = (code: number): string => `\\u{${code.toString(16)}}`; +const padded8 = (code: number): string => `\\U${code.toString(16).padStart(8, "0")}`; +const padded4 = (code: number): string => + code > 0xff_ff ? padded8(code) : `\\u${code.toString(16).padStart(4, "0")}`; + +const escapers: Record string> = { + typescript: (value) => escapeWith(value, braced), + python: (value) => escapeWith(value, padded8), + go: (value) => escapeWith(value, padded4), + ruby: (value) => escapeWith(value, braced, { "#": String.raw`\#` }), + rust: (value) => escapeWith(value, braced), + java: (value) => escapeWith(value, utf16), +}; + +type Column = { + planned: PlannedFunction; + optionSet: Record; + label: string; + expected: string[]; +}; + +/** + * One column per function and adopted option set, holding the expected output as strings. + * + * @param {Plan} plan - The emission plan of the target. + * @param {Vectors} vectors - The committed conformance vectors. + * @returns {Column[]} The columns the driver checks. + */ +const columnsFor = (plan: Plan, vectors: Vectors): Column[] => { + const columns: Column[] = []; + + for (const planned of plan.functions) { + const utility = vectors.utilities[planned.spec.id]; + const profile = utility.profiles[planned.profileName]; + + if (planned.spec.kind === "validator") { + columns.push({ + planned, + optionSet: {}, + label: `${planned.module}.${planned.name}`, + expected: (profile as boolean[]).map((value) => (value ? "true" : "false")), + }); + continue; + } + + for (const [index, optionSet] of utility.optionSets.entries()) { + const unsupported = Object.keys(optionSet).some( + (option) => !planned.options.includes(option), + ); + + if (unsupported) continue; + + columns.push({ + planned, + optionSet, + label: `${planned.module}.${planned.name}(${JSON.stringify(optionSet)})`, + expected: (profile as (string | null)[][]).map((outputs) => outputs[index] ?? NONE), + }); + } + } + + return columns; +}; + +const flags = (column: Column, trueLiteral: string, falseLiteral: string): string[] => + column.planned.options.map((option) => + (column.optionSet[option] ?? false) ? trueLiteral : falseLiteral, + ); + +const argumentList = (column: Column, trueLiteral: string, falseLiteral: string): string => { + const rest = flags(column, trueLiteral, falseLiteral); + + return rest.length > 0 ? `, ${rest.join(", ")}` : ""; +}; + +/** What every driver emitter needs: the vectors, already rendered as literals of its language. */ +type DriverContext = { + plan: Plan; + literal: (value: string) => string; + columns: Column[]; + inputs: string; + modules: string[]; + expectedList: (column: Column) => string; +}; + +/** + * Emits the typescript conformance driver. + * + * @param {DriverContext} context - The vectors and helpers, rendered for typescript. + * @returns {Record} The driver file, by path. + */ +const emitTypescriptDriver = (context: DriverContext): Record => { + const { plan, literal, columns, inputs, modules, expectedList } = context; + + return { + "conformance.ts": `// Code generated from spec/vectors by spec/codegen. DO NOT EDIT. +${modules + .map( + (module) => + `import { ${plan.functions + .filter((planned) => planned.module === module) + .map((planned) => planned.name) + .join(", ")} } from "./${module}/${module}.ts";`, + ) + .join("\n")} + +const inputs: string[] = [${inputs}]; + +const columns: { label: string; run: (value: string) => string; expected: string[] }[] = [ +${columns + .map((column) => { + const fields = column.planned.options + .map((option) => `${option}: ${String(column.optionSet[option] ?? false)}`) + .join(", "); + const options = column.planned.options.length > 0 ? `, { ${fields} }` : ""; + const call = `${column.planned.name}(value${options})`; + const run = + column.planned.spec.kind === "validator" ? `String(${call})` : `${call} ?? "${NONE}"`; + + return ` { label: ${literal(column.label)}, run: (value: string): string => ${run}, expected: [${expectedList(column)}] },`; + }) + .join("\n")} +]; + +let failures = 0; +let checked = 0; + +for (const column of columns) { + for (const [index, value] of inputs.entries()) { + const actual = column.run(value); + + checked++; + + if (actual !== column.expected[index]) { + failures++; + + if (failures <= 10) + console.error( + \`FAIL \${column.label} input=\${JSON.stringify(value)} expected=\${JSON.stringify(column.expected[index])} actual=\${JSON.stringify(actual)}\`, + ); + } + } +} + +console.log(\`typescript: \${checked - failures}/\${checked} conformance checks passed\`); +process.exit(failures === 0 ? 0 : 1); +`, + }; +}; + +/** + * Emits the python conformance driver. + * + * @param {DriverContext} context - The vectors and helpers, rendered for python. + * @returns {Record} The driver file, by path. + */ +const emitPythonDriver = (context: DriverContext): Record => { + const { literal, columns, inputs, modules, expectedList } = context; + + return { + "conformance.py": `# Code generated from spec/vectors by spec/codegen. DO NOT EDIT. +"""Runs the generated Python utilities against the committed conformance vectors.""" + +import sys +from pathlib import Path + +sys.path.insert(0, str(Path(__file__).resolve().parent)) + +${modules.map((module) => `import ${module}`).join("\n")} + +INPUTS = [${inputs}] + +COLUMNS = [ +${columns + .map((column) => { + const call = `${column.planned.module}.${column.planned.name}(value${argumentList(column, "True", "False")})`; + const run = + column.planned.spec.kind === "validator" + ? `"true" if ${call} else "false"` + : `(${call} if ${call} is not None else "${NONE}")`; + + return ` (${literal(column.label)}, lambda value: ${run}, [${expectedList(column)}]),`; + }) + .join("\n")} +] + +failures = 0 +checked = 0 + +for label, run, expected in COLUMNS: + for index, value in enumerate(INPUTS): + actual = run(value) + checked += 1 + + if actual != expected[index]: + failures += 1 + + if failures <= 10: + print( + f"FAIL {label} input={value!r} expected={expected[index]!r} actual={actual!r}", + file=sys.stderr, + ) + +print(f"python: {checked - failures}/{checked} conformance checks passed") +sys.exit(0 if failures == 0 else 1) +`, + }; +}; + +/** + * Emits the go conformance driver. + * + * @param {DriverContext} context - The vectors and helpers, rendered for go. + * @returns {Record} The driver file, by path. + */ +const emitGoDriver = (context: DriverContext): Record => { + const { literal, columns, inputs, modules, expectedList } = context; + + return { + "conformance/main.go": `// Code generated from spec/vectors by spec/codegen. DO NOT EDIT. + +package main + +import ( + "fmt" + "os" + "strconv" + +${modules.map((module) => `\t"brazilianutils/spec/${module}"`).join("\n")} +) + +type column struct { + label string + run func(string) string + expected []string +} + +func main() { + inputs := []string{${inputs}} + + columns := []column{ +${columns + .map((column) => { + const call = `${column.planned.module}.${column.planned.name}(value${argumentList(column, "true", "false")})`; + const run = column.planned.spec.kind === "validator" ? `strconv.FormatBool(${call})` : call; + + return `\t\t{label: ${literal(column.label)}, run: func(value string) string { return ${run} }, expected: []string{${expectedList(column)}}},`; + }) + .join("\n")} + } + + failures := 0 + checked := 0 + + for _, current := range columns { + for index, value := range inputs { + actual := current.run(value) + checked++ + + if actual != current.expected[index] { + failures++ + + if failures <= 10 { + fmt.Fprintf(os.Stderr, "FAIL %s input=%q expected=%q actual=%q\\n", current.label, value, current.expected[index], actual) + } + } + } + } + + fmt.Printf("go: %d/%d conformance checks passed\\n", checked-failures, checked) + + if failures > 0 { + os.Exit(1) + } +} +`, + }; +}; + +/** + * Emits the ruby conformance driver. + * + * @param {DriverContext} context - The vectors and helpers, rendered for ruby. + * @returns {Record} The driver file, by path. + */ +const emitRubyDriver = (context: DriverContext): Record => { + const { literal, columns, inputs, modules, expectedList } = context; + + return { + "conformance.rb": `# frozen_string_literal: true + +# Code generated from spec/vectors by spec/codegen. DO NOT EDIT. + +${modules + .map((module) => { + const short = (module.split("::").at(-1) ?? module).replace(/Utils$/, "").toLowerCase(); + + return `require_relative 'brazilian-utils/${short}-utils'`; + }) + .join("\n")} + +INPUTS = [${inputs}].freeze + +COLUMNS = [ +${columns + .map((column) => { + const call = `${column.planned.module}.${column.planned.name}(value${argumentList(column, "true", "false")})`; + const run = column.planned.spec.kind === "validator" ? `${call}.to_s` : `${call} || '${NONE}'`; + + return ` [${literal(column.label)}, ->(value) { ${run} }, [${expectedList(column)}]],`; + }) + .join("\n")} +].freeze + +failures = 0 +checked = 0 + +COLUMNS.each do |label, run, expected| + INPUTS.each_with_index do |value, index| + actual = run.call(value) + checked += 1 + + next if actual == expected[index] + + failures += 1 + warn "FAIL #{label} input=#{value.inspect} expected=#{expected[index].inspect} actual=#{actual.inspect}" if failures <= 10 + end +end + +puts "ruby: #{checked - failures}/#{checked} conformance checks passed" +exit(failures.zero? ? 0 : 1) +`, + }; +}; + +/** + * Emits the rust conformance driver. + * + * @param {DriverContext} context - The vectors and helpers, rendered for rust. + * @returns {Record} The driver file, by path. + */ +const emitRustDriver = (context: DriverContext): Record => { + const { literal, columns, inputs, modules, expectedList } = context; + + return { + "conformance.rs": `// Code generated from spec/vectors by spec/codegen. DO NOT EDIT. + +//! Runs the generated Rust utilities against the committed conformance vectors. + +mod spec_runtime; +${modules.map((module) => `mod ${module};`).join("\n")} + +fn main() { + let inputs: Vec<&str> = vec![${inputs}]; + + let columns: Vec<(&str, fn(&str) -> String, Vec<&str>)> = vec![ +${columns + .map((column) => { + const call = `${column.planned.module}::${column.planned.name}(value${argumentList(column, "true", "false")})`; + const formatted = column.planned.nullable + ? `${call}.unwrap_or_else(|| "${NONE}".to_string())` + : call; + const run = column.planned.spec.kind === "validator" ? `${call}.to_string()` : formatted; + + return ` (${literal(column.label)}, (|value: &str| ${run}) as fn(&str) -> String, vec![${expectedList(column)}]),`; + }) + .join("\n")} + ]; + + let mut failures = 0; + let mut checked = 0; + + for (label, run, expected) in &columns { + for (index, value) in inputs.iter().enumerate() { + let actual = run(value); + + checked += 1; + + if actual != expected[index] { + failures += 1; + + if failures <= 10 { + eprintln!( + "FAIL {} input={:?} expected={:?} actual={:?}", + label, value, expected[index], actual + ); + } + } + } + } + + println!("rust: {}/{} conformance checks passed", checked - failures, checked); + + if failures > 0 { + std::process::exit(1); + } +} +`, + }; +}; + +/** + * Emits the java conformance driver. + * + * @param {DriverContext} context - The vectors and helpers, rendered for java. + * @returns {Record} The driver file, by path. + */ +const emitJavaDriver = (context: DriverContext): Record => { + const { literal, columns, inputs, expectedList } = context; + + return { + "Conformance.java": `// Code generated from spec/vectors by spec/codegen. DO NOT EDIT. + +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; +import java.util.function.Function; + +/** Runs the generated Java utilities against the committed conformance vectors. */ +public final class Conformance { + private Conformance() {} + + private static final String[] INPUTS = {${inputs}}; + +${columns + .map( + (column, index) => + ` private static final String[] EXPECTED_${index} = {${expectedList(column)}};`, + ) + .join("\n")} + + private record Column(String label, Function run, String[] expected) {} + + public static void main(String[] args) { + List columns = new ArrayList<>(); + +${columns + .map((column, index) => { + const call = `${column.planned.module}.${column.planned.name}(value${argumentList(column, "true", "false")})`; + const run = + column.planned.spec.kind === "validator" + ? `String.valueOf(${call})` + : `${call} == null ? "${NONE}" : ${call}`; + + return ` columns.add(new Column(${literal(column.label)}, value -> ${run}, EXPECTED_${index}));`; + }) + .join("\n")} + + int failures = 0; + int checked = 0; + + for (Column column : columns) { + for (int index = 0; index < INPUTS.length; index++) { + String actual = column.run().apply(INPUTS[index]); + + checked++; + + if (!Objects.equals(actual, column.expected()[index])) { + failures++; + + if (failures <= 10) { + System.err.printf( + "FAIL %s input=%s expected=%s actual=%s%n", + column.label(), INPUTS[index], column.expected()[index], actual); + } + } + } + } + + System.out.printf("java: %d/%d conformance checks passed%n", checked - failures, checked); + + if (failures > 0) { + System.exit(1); + } + } +} +`, + }; +}; + +const drivers: Record Record> = { + typescript: emitTypescriptDriver, + python: emitPythonDriver, + go: emitGoDriver, + ruby: emitRubyDriver, + rust: emitRustDriver, + java: emitJavaDriver, +}; + +/** + * Emits the conformance driver of one target. + * + * @param {Plan} plan - The emission plan of the target. + * @param {Vectors} vectors - The committed conformance vectors. + * @returns {Record} The driver file, by path. + */ +export const emitConformance = (plan: Plan, vectors: Vectors): Record => { + const driver = drivers[plan.target]; + + if (driver === undefined) throw new Error(`no conformance driver for ${plan.target}`); + + const literal = escapers[plan.target]; + const columns = columnsFor(plan, vectors); + + return driver({ + plan, + literal, + columns, + inputs: vectors.corpus.map((input) => literal(input)).join(", "), + modules: [...new Set(plan.functions.map((planned) => planned.module))], + expectedList: (column) => column.expected.map((value) => literal(value)).join(", "), + }); +}; diff --git a/spec/codegen/corpus.ts b/spec/codegen/corpus.ts new file mode 100644 index 000000000..bde5b83eb --- /dev/null +++ b/spec/codegen/corpus.ts @@ -0,0 +1,145 @@ +/** + * Deterministic corpus of raw inputs used to build the conformance vectors. + * + * The corpus is pseudo random but seeded, so every target and every language sees exactly the + * same inputs and the vectors only change when this file does. + */ +import { computeCheckDigit } from "./interpret.ts"; + +/** + * Mulberry32: a tiny, portable PRNG, so the corpus does not depend on the host's Math.random. + * + * @param {number} seed - The seed the sequence starts from. + * @returns {Function} A generator of numbers in [0, 1). + */ +const mulberry32 = (seed: number): (() => number) => { + let state = seed; + + return () => { + // oxlint-disable-next-line unicorn/prefer-math-trunc -- `| 0` wraps to a signed 32 bit integer, which is what the algorithm specifies, and Math.trunc does not wrap + state = (state + 0x6d_2b_79_f5) | 0; + let t = Math.imul(state ^ (state >>> 15), 1 | state); + + t ^= t + Math.imul(t ^ (t >>> 7), 61 | t); + + return ((t ^ (t >>> 14)) >>> 0) / 4_294_967_296; + }; +}; + +const CURATED = [ + "", + " ", + "0", + "00000000000", + "11111111111", + "99999999999", + "12345678909", + "123.456.789-09", + "123 456 789 09", + " 12345678909 ", + "123.456.789.09", + "123/456/789/09", + "123-456-789-09", + "123..456..789--09", + ".12345678909", + "12345678909.", + "1234567890", + "123456789090", + "abc12345678909", + "12345678909abc", + "1a2345678909", + "12345678900", + " 12345678909 ", + " 123.456.789-09
", + "12345678909", + "123 456 789 09", + "123\t456\n789\r09", + "🇧🇷12345678909", + "12345678909🇧🇷", + "12345678909", + "١٢٣٤٥٦٧٨٩٠٩", + "12056874107", + "120.56874.10-7", + "120/56874/10-7", + "120(56874)10,7", + "120*56874*10-7", + "12056874108", + "1205687410", + "120.56874.10-7 ", + "120#56874#10#7", +]; + +const DIGITS = "0123456789"; +const MASKS = [".", "-", "/", " ", "(", ")", ",", "*", " ", "#", "a", ""]; + +const validCpf = (random: () => number): string => { + let base = ""; + + for (let index = 0; index < 9; index++) base += DIGITS[Math.floor(random() * 10)]; + + const first = computeCheckDigit(base, "cpf"); + const second = computeCheckDigit(`${base}${first}`, "cpf"); + + return `${base}${first}${second}`; +}; + +const validPis = (random: () => number): string => { + let base = ""; + + for (let index = 0; index < 10; index++) base += DIGITS[Math.floor(random() * 10)]; + + return `${base}${computeCheckDigit(base, "pis")}`; +}; + +const sprinkle = (value: string, random: () => number): string => { + let out = ""; + + for (const char of value) { + out += char; + if (random() < 0.18) out += MASKS[Math.floor(random() * MASKS.length)]; + } + + return out; +}; + +/** + * Builds the corpus: the curated edge cases first, then the seeded random ones. + * + * @param {number} [size] - How many inputs to produce before de-duplication. + * @returns {string[]} The corpus, in a stable order. + */ +export const buildCorpus = (size = 2000): string[] => { + const random = mulberry32(0x62_72_75_74); + const corpus = [...CURATED]; + + while (corpus.length < size) { + const roll = random(); + + if (roll < 0.3) corpus.push(validCpf(random)); + else if (roll < 0.45) corpus.push(sprinkle(validCpf(random), random)); + else if (roll < 0.6) corpus.push(validPis(random)); + else if (roll < 0.72) corpus.push(sprinkle(validPis(random), random)); + else if (roll < 0.86) { + let junk = ""; + const length = Math.floor(random() * 16); + + for (let index = 0; index < length; index++) { + junk += + random() < 0.7 + ? DIGITS[Math.floor(random() * 10)] + : MASKS[Math.floor(random() * MASKS.length)]; + } + + corpus.push(junk); + } else { + const valid = validCpf(random); + const position = Math.floor(random() * valid.length); + + corpus.push( + `${valid.slice(0, position)}${DIGITS[Math.floor(random() * 10)]}${valid.slice(position + 1)}`, + ); + } + } + + return [...new Set(corpus)]; +}; diff --git a/spec/codegen/emit.ts b/spec/codegen/emit.ts new file mode 100644 index 000000000..85aceb9b8 --- /dev/null +++ b/spec/codegen/emit.ts @@ -0,0 +1,41 @@ +/** + * Emits every language target from the specs. + * + * Usage: `node spec/codegen/emit.ts [target...]` (default: every target). + */ +import { mkdirSync, readFileSync, rmSync, writeFileSync } from "node:fs"; +import { dirname, resolve } from "node:path"; + +import { emitConformance } from "./conformance.ts"; +import { specRoot } from "./ir.ts"; +import { planFor } from "./plan.ts"; +import { emitters } from "./targets/registry.ts"; +import { type Vectors } from "./vectors.ts"; + +const vectors = JSON.parse( + readFileSync(resolve(specRoot, "vectors/conformance.json"), "utf8"), +) as Vectors; + +const requested = process.argv.slice(2); +const selected = requested.length > 0 ? requested : Object.keys(emitters); + +for (const target of selected) { + const emitter = emitters[target]; + + if (emitter === undefined) throw new Error(`unknown target: ${target}`); + + const plan = planFor(target); + const files = { ...emitter(plan), ...emitConformance(plan, vectors) }; + const outDir = resolve(specRoot, "generated", target); + + rmSync(outDir, { recursive: true, force: true }); + + for (const [path, contents] of Object.entries(files)) { + const full = resolve(outDir, path); + + mkdirSync(dirname(full), { recursive: true }); + writeFileSync(full, contents); + } + + console.log(`${target.padEnd(11)} ${Object.keys(files).length} files`); +} diff --git a/spec/codegen/interpret.ts b/spec/codegen/interpret.ts new file mode 100644 index 000000000..4cff291ae --- /dev/null +++ b/spec/codegen/interpret.ts @@ -0,0 +1,347 @@ +/** + * Reference interpreter of the utility specs. + * + * This is the normative implementation: the conformance vectors come from running it, and every + * emitted language target has to agree with it. It reads the resolved IR — code point ranges and + * weight vectors — and never a regex, because a regex shorthand does not mean the same thing in + * the six languages the specs are emitted to. + */ +import { + type CharsetRanges, + type Profile, + type Step, + type UtilitySpec, + checkDigitAlgorithm, + resolveCharset, +} from "./ir.ts"; + +/** + * Whether a code point belongs to a resolved charset. + * + * @param {number} code - The code point to test. + * @param {CharsetRanges} charset - The resolved charset. + * @returns {boolean} True when the code point is in the set. + */ +const inCharset = (code: number, charset: CharsetRanges): boolean => + charset.single.includes(code) || charset.ranges.some(([from, to]) => code >= from && code <= to); + +const DIGITS = resolveCharset("ascii-digits"); + +/** + * Strips the leading and trailing characters that belong to a charset. + * + * @param {string} value - The value to trim. + * @param {CharsetRanges} charset - The characters to strip. + * @returns {string} The trimmed value. + */ +const trimBy = (value: string, charset: CharsetRanges): string => { + let start = 0; + let end = value.length; + + while (start < end && inCharset(value.charCodeAt(start), charset)) start++; + while (end > start && inCharset(value.charCodeAt(end - 1), charset)) end--; + + return value.slice(start, end); +}; + +/** + * Whether a value is exactly the given digit groups, optionally separated. + * + * @param {string} value - The value to match. + * @param {number[]} groups - The size of each digit group. + * @param {CharsetRanges} [separators] - The characters allowed between groups, if any. + * @returns {boolean} True when the whole value matches. + */ +const matchShape = (value: string, groups: number[], separators?: CharsetRanges): boolean => { + let index = 0; + + for (const [position, size] of groups.entries()) { + if (position > 0 && separators !== undefined) { + while (index < value.length && inCharset(value.charCodeAt(index), separators)) index++; + } + + for (let digit = 0; digit < size; digit++) { + if (index >= value.length || !inCharset(value.charCodeAt(index), DIGITS)) return false; + + index++; + } + } + + return index === value.length; +}; + +/** + * Keeps only the characters that belong to a charset. + * + * @param {string} value - The value to filter. + * @param {CharsetRanges} charset - The characters to keep. + * @returns {string} The filtered value. + */ +const keepCharset = (value: string, charset: CharsetRanges): string => { + let kept = ""; + + for (let index = 0; index < value.length; index++) { + if (inCharset(value.charCodeAt(index), charset)) kept += value.charAt(index); + } + + return kept; +}; + +/** + * Whether a value is a non empty run of one repeated character. + * + * @param {string} value - The value to test. + * @returns {boolean} True for values such as "00000000000". + */ +const isRepeated = (value: string): boolean => + value !== "" && value === value.charAt(0).repeat(value.length); + +/** + * Computes one check digit of a base with the named algorithm. + * + * @param {string} base - The digits that precede the check digit. + * @param {string} algorithm - The algorithm name, as declared in `spec/schema/check-digits.json`. + * @returns {number} The check digit. + */ +export const computeCheckDigit = (base: string, algorithm: string): number => { + const spec = checkDigitAlgorithm(algorithm); + let sum = 0; + + if (spec.weights.kind === "fixed") { + const { values } = spec.weights; + + for (let index = 0; index < values.length; index++) { + sum += (base.charCodeAt(index) - 48) * values[index]; + } + } else { + let weight = base.length + 1; + + for (let index = 0; index < base.length; index++) { + sum += (base.charCodeAt(index) - 48) * weight; + weight--; + } + } + + const digit = spec.modulus - (sum % spec.modulus); + + return digit >= spec.clamp.atLeast ? spec.clamp.to : digit; +}; + +/** + * Whether every check digit of a value matches its base. + * + * @param {string} digits - The sanitized digits. + * @param {string} algorithm - The algorithm name. + * @returns {boolean} True when all the declared positions check out. + */ +const verifyCheckDigits = (digits: string, algorithm: string): boolean => { + const spec = checkDigitAlgorithm(algorithm); + + for (const position of spec.positions) { + if (digits.length <= position) return false; + + if ( + digits.charCodeAt(position) - 48 !== + computeCheckDigit(digits.slice(0, position), algorithm) + ) + return false; + } + + return true; +}; + +/** + * Lays a value over a pattern: `0` copies a character, `*` hides one, anything else separates. + * + * @param {string} value - The sanitized value. + * @param {string} pattern - The pattern to lay it over. + * @param {boolean} pad - Whether to left pad the value with zeros up to the pattern's slots. + * @returns {string} The formatted value. + */ +export const applyPattern = (value: string, pattern: string, pad: boolean): string => { + let padded = value; + + if (pad) { + let slots = 0; + + for (const char of pattern) { + if (char === "0" || char === "*") slots++; + } + + padded = value.padStart(slots, "0"); + } + + let formatted = ""; + let index = 0; + + for (const char of pattern) { + if (char === "0" || char === "*") { + if (index >= padded.length) break; + + formatted += char === "*" ? "*" : padded.charAt(index); + index++; + } else if (index < padded.length) { + formatted += char; + } + } + + return formatted; +}; + +/** Options a formatter profile can declare. */ +export type RunOptions = { pad?: boolean; obfuscate?: boolean }; + +/** The value a utility answers with, by kind: a verdict, a formatted string, or nothing. */ +type Outcome = boolean | string | null; + +let loadUtilitySync: (id: string) => UtilitySpec = () => { + throw new Error("interpreter not initialised: call setLoader first"); +}; + +/** + * Injects the spec loader the `guard-valid` step uses to reach another utility. + * + * @param {Function} loader - Loads a utility spec by id. + * @returns {void} + */ +export const setLoader = (loader: (id: string) => UtilitySpec): void => { + loadUtilitySync = loader; +}; + +/** + * The value a profile answers with when a guard rejects the input. + * + * @param {UtilitySpec} spec - The utility being run. + * @param {Profile} profile - The profile being run. + * @returns {Outcome} `false` for a validator, `""` or `null` for a formatter. + */ +const rejectionOf = (spec: UtilitySpec, profile: Profile): Outcome => { + if (spec.kind === "validator") return false; + + return (profile.absent ?? spec.input.onNullish) === "null" ? null : ""; +}; + +/** The mutable state a pipeline threads through its steps. */ +type State = { raw: string; digits: string }; + +/** + * Runs the `guard-shape` step: the value, trimmed if the profile says so, has to be exactly the + * declared digit groups. + * + * @param {Step} step - The guard-shape step. + * @param {string} raw - The raw input. + * @returns {boolean} True when the value matches. + */ +const guardShape = (step: Extract, raw: string): boolean => { + const value = step.trim === undefined ? raw : trimBy(raw, resolveCharset(step.trim)); + const separators = step.separators === undefined ? undefined : resolveCharset(step.separators); + + return matchShape(value, step.groups, separators); +}; + +/** + * Runs the `guard-charset` step: every character of the raw input has to be allowed. + * + * @param {Step} step - The guard-charset step. + * @param {string} raw - The raw input. + * @returns {boolean} True when every character is in the allowed set. + */ +const guardCharset = (step: Extract, raw: string): boolean => { + const allowed = resolveCharset(step.allow); + + for (let index = 0; index < raw.length; index++) { + if (!inCharset(raw.charCodeAt(index), allowed)) return false; + } + + return true; +}; + +/** + * Runs one pipeline step. + * + * @param {Step} step - The step to run. + * @param {State} state - The raw input and the digits sanitized so far. + * @param {RunOptions} options - The options the caller passed. + * @returns {Outcome | undefined} A value when the step answers, `undefined` to carry on. + */ +const runStep = (step: Step, state: State, options: RunOptions): Outcome | undefined => { + switch (step.op) { + case "guard-shape": { + return guardShape(step, state.raw) ? undefined : false; + } + case "guard-charset": { + return guardCharset(step, state.raw) ? undefined : false; + } + case "sanitize": { + state.digits = keepCharset(state.raw, resolveCharset(step.keep)); + + return undefined; + } + case "guard-length": { + return state.digits.length === step.equals ? undefined : false; + } + case "guard-repeated": { + return isRepeated(state.digits) ? false : undefined; + } + case "verify-check-digits": { + return verifyCheckDigits(state.digits, step.checkDigit) ? undefined : false; + } + case "guard-valid": { + // Handled by `run`, which owns the recursion into the referenced utility. + throw new Error(`${step.utility}: guard-valid must be run by the caller`); + } + case "apply-pattern": { + const obfuscated = step.variants?.["obfuscate"]; + const pattern = + (options.obfuscate ?? false) && obfuscated !== undefined ? obfuscated : step.pattern; + + return applyPattern(state.digits, pattern, options.pad ?? false); + } + default: { + throw new Error(`unsupported step: ${JSON.stringify(step)}`); + } + } +}; + +/** + * Runs a profile of a utility against a raw input. + * + * @param {UtilitySpec} spec - The utility to run. + * @param {string} profileName - Which of its profiles to run. + * @param {unknown} input - The raw input, of any type: a utility never throws on bad input. + * @param {RunOptions} [options] - The options a formatter profile declares. + * @returns {Outcome} The declared output of the utility. + */ +export const run = ( + spec: UtilitySpec, + profileName: string, + input: unknown, + options: RunOptions = {}, +): Outcome => { + const profile: Profile | undefined = spec.profiles[profileName]; + + if (profile === undefined) throw new Error(`${spec.id} has no profile ${profileName}`); + + const rejection = rejectionOf(spec, profile); + + if (spec.kind === "validator" && typeof input !== "string") return false; + if (spec.kind === "formatter" && (input === null || input === undefined)) return rejection; + + const state: State = { raw: typeof input === "string" ? input : String(input), digits: "" }; + + for (const step of profile.pipeline) { + if (step.op === "guard-valid") { + // oxlint-disable-next-line sonarjs/no-extra-arguments, sonarjs/no-use-of-empty-return-value -- `run` recurses into itself, which the analyser reads as a call to an undeclared binding + if (run(loadUtilitySync(step.utility), step.profile, state.raw) !== true) return rejection; + + continue; + } + + const outcome = runStep(step, state, options); + + if (outcome === false) return rejection; + if (outcome !== undefined) return outcome; + } + + return spec.kind === "validator" ? true : state.digits; +}; diff --git a/spec/codegen/ir.ts b/spec/codegen/ir.ts new file mode 100644 index 000000000..a7918d453 --- /dev/null +++ b/spec/codegen/ir.ts @@ -0,0 +1,153 @@ +/** + * Loader for the language neutral utility specs under `spec/utilities`. + * + * It resolves the charset and check digit references into plain data, so an emitter only ever + * sees code point ranges and weight vectors, never a regex or a language specific shorthand. + */ +import { readFileSync } from "node:fs"; +import { dirname, resolve } from "node:path"; + +const specDir = resolve(import.meta.dirname, ".."); + +export type CharsetRanges = { single: number[]; ranges: [number, number][] }; + +export type CheckDigitAlgorithm = { + description: string; + modulus: number; + weights: { kind: "descending"; from: string; to: number } | { kind: "fixed"; values: number[] }; + reduce: "modulus-minus-remainder"; + clamp: { atLeast: number; to: number }; + positions: number[]; + cumulative: boolean; + source: string; +}; + +export type Step = + | { op: "guard-shape"; target: "raw"; trim?: string; groups: number[]; separators?: string } + | { op: "guard-charset"; target: "raw"; allow: string[] } + | { op: "sanitize"; keep: string; into: string } + | { op: "guard-length"; target: string; equals: number } + | { op: "guard-repeated"; target: string } + | { op: "verify-check-digits"; target: string; checkDigit: string } + | { op: "guard-valid"; utility: string; profile: string } + | { + op: "apply-pattern"; + target: string; + engine: "pattern-v1"; + pattern: string; + variants?: Record; + }; + +export type OptionSpec = { name: string; type: string; default: boolean; read: string }; + +export type Profile = { + description: string; + /** What a formatter answers when the value has no formatting: `""` or the language's null. */ + absent?: "empty-string" | "null"; + pipeline: Step[]; + options?: OptionSpec[]; +}; + +/** A known, documented difference between a package and the profile it otherwise implements. */ +export type Deviation = { inputs: string[]; reason: string; issue?: string }; + +export type Adoption = { profile: string; options?: string[]; knownDeviations?: Deviation[] }; + +export type UtilitySpec = { + id: string; + kind: "validator" | "formatter"; + summary: string; + sources: { role: string; url: string }[]; + names: Record; + input: { name: string; type: string; onWrongType?: string; onNullish?: string }; + output: { type: string }; + adopted: Record; + profiles: Record; +}; + +/** + * Reads a JSON file of the specification. + * + * @param {string} path - The absolute path to read. + * @returns {unknown} The parsed contents, for the caller to narrow. + */ +const readJson = (path: string): unknown => JSON.parse(readFileSync(path, "utf8")); + +type CharsetFile = { + charsets: Record< + string, + { description: string; codePoints?: string[]; ranges?: [string, string][]; include?: string[] } + >; +}; + +const charsetFile = readJson(resolve(specDir, "schema/charsets.json")) as CharsetFile; + +const checkDigitFile = readJson(resolve(specDir, "schema/check-digits.json")) as { + algorithms: Record; +}; + +/** + * Expands a charset reference into sorted code point ranges. + * + * @param {string|string[]} names - One charset name, or the union of several. + * @returns {CharsetRanges} The single code points and the ranges the union covers. + */ +export const resolveCharset = (names: string | string[]): CharsetRanges => { + const wanted = Array.isArray(names) ? names : [names]; + const single = new Set(); + const ranges: [number, number][] = []; + + const visit = (name: string): void => { + const charset = charsetFile.charsets[name]; + + if (charset === undefined) throw new Error(`unknown charset: ${name}`); + + for (const codePoint of charset.codePoints ?? []) single.add(Number.parseInt(codePoint, 16)); + for (const [from, to] of charset.ranges ?? []) + ranges.push([Number.parseInt(from, 16), Number.parseInt(to, 16)]); + for (const included of charset.include ?? []) visit(included); + }; + + for (const name of wanted) visit(name); + + return { + single: [...single].sort((a, b) => a - b), + ranges: ranges.sort((a, b) => a[0] - b[0]), + }; +}; + +/** + * Looks a check digit algorithm up by name. + * + * @param {string} name - The algorithm name declared in `spec/schema/check-digits.json`. + * @returns {CheckDigitAlgorithm} The algorithm. + */ +export const checkDigitAlgorithm = (name: string): CheckDigitAlgorithm => { + const algorithm = checkDigitFile.algorithms[name]; + + if (algorithm === undefined) throw new Error(`unknown check digit algorithm: ${name}`); + + return algorithm; +}; + +/** + * Loads one utility spec. + * + * @param {string} id - The utility id, which is also its file name. + * @returns {UtilitySpec} The spec. + */ +export const loadUtility = (id: string): UtilitySpec => + readJson(resolve(specDir, `utilities/${id}.json`)) as UtilitySpec; + +/** + * Loads every utility the specification covers, in declaration order. + * + * @returns {UtilitySpec[]} The specs. + */ +export const loadAll = (): UtilitySpec[] => + (readJson(resolve(specDir, "utilities.json")) as { utilities: string[] }).utilities.map((id) => + loadUtility(id), + ); + +export const specRoot = specDir; +export const codegenRoot = dirname(resolve(import.meta.dirname, "emit.ts")); diff --git a/spec/codegen/plan.ts b/spec/codegen/plan.ts new file mode 100644 index 000000000..cab81393c --- /dev/null +++ b/spec/codegen/plan.ts @@ -0,0 +1,179 @@ +/** + * Turns the specs into the flat plan an emitter needs: which charsets and check digit + * algorithms to lay down in the prelude, and which function to emit for the target, under the + * name and with the option set that target's package already exposes. + */ +import { + type CharsetRanges, + type CheckDigitAlgorithm, + type Profile, + type Step, + type UtilitySpec, + checkDigitAlgorithm, + loadAll, + resolveCharset, +} from "./ir.ts"; + +export type PlannedFunction = { + spec: UtilitySpec; + profile: Profile; + profileName: string; + name: string; + module: string; + options: string[]; + /** Whether the function may answer "no value": a formatter whose profile is absent as null. */ + nullable: boolean; +}; + +export type Plan = { + target: string; + charsets: { name: string; symbol: string; ranges: CharsetRanges }[]; + algorithms: { name: string; symbol: string; algorithm: CheckDigitAlgorithm }[]; + functions: PlannedFunction[]; +}; + +/** + * Converts a kebab-case id to PascalCase. + * + * @param {string} value - The id to convert. + * @returns {string} The PascalCase form. + */ +const pascal = (value: string): string => + value + .split(/[-_]/) + .map((part) => part.charAt(0).toUpperCase() + part.slice(1)) + .join(""); + +/** + * Converts a kebab-case id to camelCase. + * + * @param {string} value - The id to convert. + * @returns {string} The camelCase form. + */ +const camel = (value: string): string => { + const pascalCase = pascal(value); + + return pascalCase.charAt(0).toLowerCase() + pascalCase.slice(1); +}; + +/** + * Converts a kebab-case id to snake_case. + * + * @param {string} value - The id to convert. + * @returns {string} The snake_case form. + */ +const snake = (value: string): string => value.replaceAll("-", "_"); + +export const naming = { pascal, camel, snake }; + +/** + * The charsets one step references. + * + * @param {Step} step - The step to inspect. + * @returns {string[]} The charset names, which may be empty. + */ +const charsetsOf = (step: Step): string[] => { + if (step.op === "guard-shape") + return [step.trim, step.separators].filter((name): name is string => name !== undefined); + if (step.op === "guard-charset") return step.allow; + if (step.op === "sanitize") return [step.keep]; + + return []; +}; + +/** + * Flattens a profile's pipeline into the steps an emitter renders one by one: `guard-valid` + * becomes the referenced profile's own steps, and the duplicate `sanitize` that inlining + * introduces is dropped, so the target language binds `digits` exactly once. + * + * @param {Profile} profile - The profile to flatten. + * @returns {Step[]} The steps to render, in order. + */ +export const expandPipeline = (profile: Profile): Step[] => { + const specs = loadAll(); + const expanded: Step[] = []; + + for (const step of profile.pipeline) { + if (step.op !== "guard-valid") { + expanded.push(step); + continue; + } + + const referenced = specs.find((candidate) => candidate.id === step.utility); + + if (referenced === undefined) throw new Error(`unknown referenced utility ${step.utility}`); + + expanded.push(...referenced.profiles[step.profile].pipeline); + } + + const sanitized = new Set(); + + return expanded.filter((step) => { + if (step.op !== "sanitize") return true; + + const key = `${step.keep}->${step.into}`; + const seen = sanitized.has(key); + + sanitized.add(key); + + return !seen; + }); +}; + +/** + * Builds the emission plan for one target language. + * + * @param {string} target - The target language id, as used in a spec's `adopted` map. + * @returns {Plan} Everything the emitter for that language needs. + */ +export const planFor = (target: string): Plan => { + const specs = loadAll(); + const charsetNames = new Set(["ascii-digits"]); + const algorithmNames = new Set(); + const functions: PlannedFunction[] = []; + + for (const spec of specs) { + const adoption = spec.adopted[target]; + + if (adoption === undefined) continue; + + const profile = spec.profiles[adoption.profile]; + + if (profile === undefined) + throw new Error(`${spec.id}: ${target} adopts unknown profile ${adoption.profile}`); + + const names = spec.names[target]; + + if (names === undefined) throw new Error(`${spec.id}: no name for target ${target}`); + + for (const step of expandPipeline(profile)) { + for (const charset of charsetsOf(step)) charsetNames.add(charset); + if (step.op === "verify-check-digits") algorithmNames.add(step.checkDigit); + } + + functions.push({ + spec, + profile, + profileName: adoption.profile, + name: names.function, + module: names.module, + options: adoption.options ?? (profile.options ?? []).map((option) => option.name), + nullable: (profile.absent ?? spec.input.onNullish) === "null", + }); + } + + return { + target, + charsets: [...charsetNames].sort().map((name) => ({ + name, + symbol: snake(name), + ranges: resolveCharset(name), + })), + algorithms: [...algorithmNames].sort().map((name) => ({ + name, + symbol: snake(name), + algorithm: checkDigitAlgorithm(name), + })), + functions, + }; +}; diff --git a/spec/codegen/targets/go.ts b/spec/codegen/targets/go.ts new file mode 100644 index 000000000..47727aadf --- /dev/null +++ b/spec/codegen/targets/go.ts @@ -0,0 +1,413 @@ +/** + * Go emitter: one package per module, exported names in Go's style, and a `specruntime` + * package holding the shared helpers. + */ +import { type Step, type UtilitySpec } from "../ir.ts"; +import { type Plan, type PlannedFunction, expandPipeline, naming } from "../plan.ts"; + +/** + * Renders a string as a Go interpreted string literal. + * + * @param {string} value - The text to render. + * @returns {string} The literal, quotes included. + */ +const escapeLiteral = (value: string): string => { + let literal = '"'; + + for (const char of value) { + const code = char.codePointAt(0) ?? 0; + + if (char === '"') literal += String.raw`\"`; + else if (char === "\\") literal += String.raw`\\`; + else if (code > 0xff_ff) literal += `\\U${code.toString(16).padStart(8, "0")}`; + else if (code < 0x20 || code > 0x7e) literal += `\\u${code.toString(16).padStart(4, "0")}`; + else literal += char; + } + + return `${literal}"`; +}; + +/** + * Converts an id to the exported name Go uses for it. + * + * @param {string} name - The id to convert. + * @returns {string} The Go name. + */ +const goName = (name: string): string => naming.pascal(name); + +/** + * Renders the membership test of a charset as an expression of the target language. + * + * @param {Plan} plan - The emission plan holding the resolved charsets. + * @param {string} name - The charset name. + * @returns {string} The boolean expression. + */ +const charsetTest = (plan: Plan, name: string): string => { + const found = plan.charsets.find((charset) => charset.name === name); + const { single, ranges } = found?.ranges ?? { single: [], ranges: [] }; + + return [ + ...single.map((code) => `code == 0x${code.toString(16)}`), + ...ranges.map( + ([from, to]) => `(code >= 0x${from.toString(16)} && code <= 0x${to.toString(16)})`, + ), + ].join(" ||\n\t\t"); +}; + +/** The part of the prelude that does not depend on the specs. */ +const RUNTIME_HELPERS = `// TrimBy strips the leading and trailing characters that belong to the set. +func TrimBy(value string, inSet func(rune) bool) string { + return strings.TrimFunc(value, inSet) +} + +// KeepBy keeps only the characters that belong to the set. +func KeepBy(value string, inSet func(rune) bool) string { + var kept strings.Builder + + for _, char := range value { + if inSet(char) { + kept.WriteRune(char) + } + } + + return kept.String() +} + +// MatchShape reports whether the value is exactly the digit groups, optionally separated. +func MatchShape(value string, groups []int, inSeparator func(rune) bool) bool { + runes := []rune(value) + index := 0 + + for position, size := range groups { + if position > 0 && inSeparator != nil { + for index < len(runes) && inSeparator(runes[index]) { + index++ + } + } + + for digit := 0; digit < size; digit++ { + if index >= len(runes) || !IsAsciiDigits(runes[index]) { + return false + } + + index++ + } + } + + return index == len(runes) +} + +// IsRepeated reports whether the value is a non empty run of one repeated character. +func IsRepeated(value string) bool { + if value == "" { + return false + } + + return value == strings.Repeat(value[:1], len(value)) +} + +// ApplyPattern lays the value over the pattern: '0' copies, '*' hides, anything else separates. +func ApplyPattern(value string, pattern string, pad bool) string { + padded := value + + if pad { + slots := 0 + + for _, char := range pattern { + if char == '0' || char == '*' { + slots++ + } + } + + if len(padded) < slots { + padded = strings.Repeat("0", slots-len(padded)) + padded + } + } + + var formatted strings.Builder + index := 0 + + for _, char := range pattern { + if char == '0' || char == '*' { + if index >= len(padded) { + break + } + + if char == '*' { + formatted.WriteString("*") + } else { + formatted.WriteByte(padded[index]) + } + + index++ + } else if index < len(padded) { + formatted.WriteRune(char) + } + } + + return formatted.String() +}`; + +/** + * Renders the runtime shared by every generated utility of this target. + * + * @param {Plan} plan - The emission plan. + * @returns {string} The prelude source. + */ +const prelude = (plan: Plan): string => { + const charsets = plan.charsets + .map( + ( + charset, + ) => `// Is${goName(charset.name)} reports whether the code point belongs to the ${charset.name} set. +func Is${goName(charset.name)}(code rune) bool { + return ${charsetTest(plan, charset.name)} +}`, + ) + .join("\n\n"); + + const algorithms = plan.algorithms + .map((entry) => { + const { algorithm } = entry; + const body = + algorithm.weights.kind === "fixed" + ? ` weights := []int{${algorithm.weights.values.join(", ")}} + sum := 0 + + for index, weight := range weights { + sum += int(base[index]-'0') * weight + }` + : ` sum := 0 + weight := len(base) + 1 + + for index := 0; index < len(base); index++ { + sum += int(base[index]-'0') * weight + weight-- + }`; + + return `// CheckDigit${goName(entry.name)} computes one check digit of the base. +// +// ${algorithm.description} +// +// Official source: ${algorithm.source} +func CheckDigit${goName(entry.name)}(base string) int { +${body} + + digit := ${algorithm.modulus} - (sum % ${algorithm.modulus}) + + if digit >= ${algorithm.clamp.atLeast} { + return ${algorithm.clamp.to} + } + + return digit +} + +// Verify${goName(entry.name)} reports whether every check digit matches its base. +func Verify${goName(entry.name)}(digits string) bool { + for _, position := range []int{${algorithm.positions.join(", ")}} { + if len(digits) <= position { + return false + } + + if int(digits[position]-'0') != CheckDigit${goName(entry.name)}(digits[:position]) { + return false + } + } + + return true +}`; + }) + .join("\n\n"); + + return `// Code generated from spec/utilities by spec/codegen. DO NOT EDIT. + +// Package specruntime holds the helpers shared by the generated utilities. +package specruntime + +import "strings" + +${charsets} + +${RUNTIME_HELPERS} + +${algorithms} +`; +}; + +/** + * The value the generated function returns when a guard rejects the input. + * + * @param {UtilitySpec} spec - The utility being emitted. + * @param {PlannedFunction} planned - The planned function. + * @returns {string} The literal to return. + */ +const bailValue = (spec: UtilitySpec, planned: PlannedFunction): string => { + if (spec.kind === "validator") return "false"; + + return planned.nullable ? '"", false' : '""'; +}; + +/** + * Renders one pipeline step as statements of the target language. + * + * @param {Step} step - The step to render. + * @param {UtilitySpec} spec - The utility being emitted. + * @param {PlannedFunction} planned - The planned function. + * @returns {string} The rendered statements. + */ +const renderStep = (step: Step, spec: UtilitySpec, planned: PlannedFunction): string => { + const bail = bailValue(spec, planned); + + switch (step.op) { + case "guard-shape": { + const value = + step.trim === undefined + ? "raw" + : `specruntime.TrimBy(raw, specruntime.Is${goName(step.trim)})`; + const separators = + step.separators === undefined ? "nil" : `specruntime.Is${goName(step.separators)}`; + + return ` if !specruntime.MatchShape(${value}, []int{${step.groups.join(", ")}}, ${separators}) { + return ${bail} + }`; + } + case "guard-charset": { + return ` for _, char := range raw { + if !(${step.allow.map((name) => `specruntime.Is${goName(name)}(char)`).join(" || ")}) { + return ${bail} + } + }`; + } + case "sanitize": { + return ` digits := specruntime.KeepBy(raw, specruntime.Is${goName(step.keep)})`; + } + case "guard-length": { + return ` if len(digits) != ${step.equals} { + return ${bail} + }`; + } + case "guard-repeated": { + return ` if specruntime.IsRepeated(digits) { + return ${bail} + }`; + } + case "verify-check-digits": { + return ` if !specruntime.Verify${goName(step.checkDigit)}(digits) { + return ${bail} + }`; + } + case "apply-pattern": { + const pattern = + step.variants?.["obfuscate"] !== undefined && planned.options.includes("obfuscate") + ? `map[bool]string{true: ${escapeLiteral(step.variants["obfuscate"])}, false: ${escapeLiteral(step.pattern)}}[obfuscate]` + : escapeLiteral(step.pattern); + const pad = planned.options.includes("pad") ? "pad" : "false"; + + const secondReturn = planned.nullable ? ", true" : ""; + + return ` return specruntime.ApplyPattern(digits, ${pattern}, ${pad})${secondReturn}`; + } + case "guard-valid": { + // `expandPipeline` replaces this step with the referenced profile's own steps. + throw new Error(`${spec.id}: guard-valid reached the emitter unexpanded`); + } + default: { + throw new Error(`unsupported step: ${JSON.stringify(step)}`); + } + } +}; + +/** + * The return type the generated function declares. + * + * @param {UtilitySpec} spec - The utility being emitted. + * @param {PlannedFunction} planned - The planned function. + * @returns {string} The type, spelled in the target language. + */ +const returnTypeOf = (spec: UtilitySpec, planned: PlannedFunction): string => { + if (spec.kind === "validator") return "bool"; + + return planned.nullable ? "(string, bool)" : "string"; +}; + +/** + * What closes the generated body: the success value, or nothing when a step already returned. + * + * @param {UtilitySpec} spec - The utility being emitted. + * @param {PlannedFunction} planned - The planned function. + * @returns {string} The closing lines, which may be empty. + */ +const tailOf = (spec: UtilitySpec, planned: PlannedFunction): string => { + if (spec.kind === "validator") return "\n\n return true"; + + const returnsEarly = expandPipeline(planned.profile).some((step) => step.op === "apply-pattern"); + + return returnsEarly ? "" : `\n\n return digits`; +}; + +/** + * Renders one planned function, documentation included. + * + * @param {PlannedFunction} planned - The function to render. + * @returns {string} The rendered source. + */ +const renderFunction = (planned: PlannedFunction): string => { + const { spec } = planned; + const returns = returnTypeOf(spec, planned); + const parameters = [ + `${naming.camel(spec.input.name)} string`, + ...planned.options.map((option) => `${option} bool`), + ].join(", "); + + const head = ` raw := ${naming.camel(spec.input.name)}`; + const body = expandPipeline(planned.profile) + .map((step) => renderStep(step, spec, planned)) + .join("\n"); + const tail = tailOf(spec, planned); + + return `// ${planned.name} ${spec.summary} +// +// Profile: ${planned.profileName} — ${planned.profile.description} +// +${spec.sources.map((source) => `// ${source.role === "official" ? "Official" : "Based on"}: ${source.url}`).join("\n")} +func ${planned.name}(${parameters}) ${returns} { +${head} + +${body}${tail} +}`; +}; + +/** + * Emits every file of this target. + * + * @param {Plan} plan - The emission plan. + * @returns {Record} The files, by path relative to the target directory. + */ +export const emit = (plan: Plan): Record => { + const files: Record = { + "specruntime/specruntime.go": prelude(plan), + "go.mod": "module brazilianutils/spec\n\ngo 1.24\n", + }; + const modules = new Map(); + + for (const planned of plan.functions) { + modules.set(planned.module, [...(modules.get(planned.module) ?? []), planned]); + } + + for (const [module, functions] of modules) { + const source = functions.map((planned) => renderFunction(planned)).join("\n\n"); + + files[`${module}/${module}.go`] = + `// Code generated from spec/utilities by spec/codegen. DO NOT EDIT. + +// Package ${module} holds the generated ${module} utilities. +package ${module} + +import "brazilianutils/spec/specruntime" + +${source} +`; + } + + return files; +}; diff --git a/spec/codegen/targets/java.ts b/spec/codegen/targets/java.ts new file mode 100644 index 000000000..a45332ae5 --- /dev/null +++ b/spec/codegen/targets/java.ts @@ -0,0 +1,431 @@ +/** + * Java emitter: the target with no existing package, kept here to show what onboarding a new + * language costs once the specs exist — a file of roughly 120 lines of emitter, no new + * algorithm work, and the canonical profile from day one. + */ +import { type Step, type UtilitySpec } from "../ir.ts"; +import { type Plan, type PlannedFunction, expandPipeline, naming } from "../plan.ts"; + +/** + * Renders a string as a Java literal. + * + * A `\\uXXXX` escape is expanded by the compiler before lexing, so `\\u000a` would end the + * literal on a real line break: every control character goes out as its own escape, and an + * astral code point as its UTF-16 surrogate pair. + * + * @param {string} value - The text to render. + * @returns {string} The literal, quotes included. + */ +const JAVA_CONTROL: Record = { + 0x08: "\\b", + 0x09: "\\t", + 0x0a: "\\n", + 0x0c: "\\f", + 0x0d: "\\r", +}; + +const escapeLiteral = (value: string): string => { + let literal = '"'; + + for (const char of value) { + const code = char.codePointAt(0) ?? 0; + + if (char === '"') literal += String.raw`\"`; + else if (char === "\\") literal += String.raw`\\`; + else if (code < 0x20) literal += JAVA_CONTROL[code] ?? `\\${code.toString(8).padStart(3, "0")}`; + else if (code > 0xff_ff) { + const offset = code - 0x1_00_00; + + literal += `\\u${(0xd8_00 + (offset >> 10)).toString(16).padStart(4, "0")}`; + literal += `\\u${(0xdc_00 + (offset & 0x3_ff)).toString(16).padStart(4, "0")}`; + } else if (code > 0x7e) literal += `\\u${code.toString(16).padStart(4, "0")}`; + else literal += char; + } + + return `${literal}"`; +}; + +/** + * Renders the membership test of a charset as an expression of the target language. + * + * @param {Plan} plan - The emission plan holding the resolved charsets. + * @param {string} name - The charset name. + * @returns {string} The boolean expression. + */ +const charsetTest = (plan: Plan, name: string): string => { + const found = plan.charsets.find((charset) => charset.name === name); + const { single, ranges } = found?.ranges ?? { single: [], ranges: [] }; + + return [ + ...single.map((code) => `code == 0x${code.toString(16)}`), + ...ranges.map( + ([from, to]) => `(code >= 0x${from.toString(16)} && code <= 0x${to.toString(16)})`, + ), + ].join("\n || "); +}; + +/** The part of the prelude that does not depend on the specs. */ +const RUNTIME_HELPERS = ` /** Strips the leading and trailing characters that belong to the set. */ + public static String trimBy(String value, IntPredicate inSet) { + int start = 0; + int end = value.length(); + + while (start < end && inSet.test(value.charAt(start))) { + start++; + } + while (end > start && inSet.test(value.charAt(end - 1))) { + end--; + } + + return value.substring(start, end); + } + + /** Keeps only the characters that belong to the set. */ + public static String keepBy(String value, IntPredicate inSet) { + StringBuilder kept = new StringBuilder(); + + for (int index = 0; index < value.length(); index++) { + if (inSet.test(value.charAt(index))) { + kept.append(value.charAt(index)); + } + } + + return kept.toString(); + } + + /** Whether the value is exactly the digit groups, optionally separated. */ + public static boolean matchShape(String value, int[] groups, IntPredicate inSeparator) { + int index = 0; + + for (int position = 0; position < groups.length; position++) { + if (position > 0 && inSeparator != null) { + while (index < value.length() && inSeparator.test(value.charAt(index))) { + index++; + } + } + + for (int digit = 0; digit < groups[position]; digit++) { + if (index >= value.length() || !isAsciiDigits(value.charAt(index))) { + return false; + } + + index++; + } + } + + return index == value.length(); + } + + /** Whether the value is a non empty run of one repeated character. */ + public static boolean isRepeated(String value) { + if (value.isEmpty()) { + return false; + } + + for (int index = 1; index < value.length(); index++) { + if (value.charAt(index) != value.charAt(0)) { + return false; + } + } + + return true; + } + + /** Lays the value over the pattern: '0' copies, '*' hides, anything else separates. */ + public static String applyPattern(String value, String pattern, boolean pad) { + String padded = value; + + if (pad) { + int slots = 0; + + for (int index = 0; index < pattern.length(); index++) { + char current = pattern.charAt(index); + + if (current == '0' || current == '*') { + slots++; + } + } + + while (padded.length() < slots) { + padded = "0" + padded; + } + } + + StringBuilder formatted = new StringBuilder(); + int index = 0; + + for (int position = 0; position < pattern.length(); position++) { + char current = pattern.charAt(position); + + if (current == '0' || current == '*') { + if (index >= padded.length()) { + break; + } + + formatted.append(current == '*' ? '*' : padded.charAt(index)); + index++; + } else if (index < padded.length()) { + formatted.append(current); + } + } + + return formatted.toString(); + }`; + +/** + * Renders the runtime shared by every generated utility of this target. + * + * @param {Plan} plan - The emission plan. + * @returns {string} The prelude source. + */ +const prelude = (plan: Plan): string => { + const charsets = plan.charsets + .map( + (charset) => ` /** Whether the code point belongs to the ${charset.name} set. */ + public static boolean is${naming.pascal(charset.name)}(int code) { + return ${charsetTest(plan, charset.name)}; + }`, + ) + .join("\n\n"); + + const algorithms = plan.algorithms + .map((entry) => { + const { algorithm } = entry; + const body = + algorithm.weights.kind === "fixed" + ? ` int[] weights = {${algorithm.weights.values.join(", ")}}; + int sum = 0; + + for (int index = 0; index < weights.length; index++) { + sum += (base.charAt(index) - '0') * weights[index]; + }` + : ` int sum = 0; + int weight = base.length() + 1; + + for (int index = 0; index < base.length(); index++) { + sum += (base.charAt(index) - '0') * weight; + weight--; + }`; + + return ` /** + * ${algorithm.description} + * + *

Official source: ${algorithm.source} + */ + public static int checkDigit${naming.pascal(entry.name)}(String base) { +${body} + + int digit = ${algorithm.modulus} - (sum % ${algorithm.modulus}); + + return digit >= ${algorithm.clamp.atLeast} ? ${algorithm.clamp.to} : digit; + } + + /** Whether every check digit of the value matches its base. */ + public static boolean verify${naming.pascal(entry.name)}(String digits) { + for (int position : new int[] {${algorithm.positions.join(", ")}}) { + if (digits.length() <= position) { + return false; + } + + if (digits.charAt(position) - '0' != checkDigit${naming.pascal(entry.name)}(digits.substring(0, position))) { + return false; + } + } + + return true; + }`; + }) + .join("\n\n"); + + return `// Code generated from spec/utilities by spec/codegen. DO NOT EDIT. + +import java.util.function.IntPredicate; + +/** Helpers shared by the generated utilities. */ +public final class SpecRuntime { + private SpecRuntime() {} + +${charsets} + +${RUNTIME_HELPERS} + +${algorithms} +} +`; +}; + +/** + * The value the generated function returns when a guard rejects the input. + * + * @param {UtilitySpec} spec - The utility being emitted. + * @param {PlannedFunction} planned - The planned function. + * @returns {string} The literal to return. + */ +const bailValue = (spec: UtilitySpec, planned: PlannedFunction): string => { + if (spec.kind === "validator") return "false"; + + return planned.nullable ? "null" : '""'; +}; + +/** + * Renders one pipeline step as statements of the target language. + * + * @param {Step} step - The step to render. + * @param {UtilitySpec} spec - The utility being emitted. + * @param {PlannedFunction} planned - The planned function. + * @returns {string} The rendered statements. + */ +const renderStep = (step: Step, spec: UtilitySpec, planned: PlannedFunction): string => { + const bail = bailValue(spec, planned); + + switch (step.op) { + case "guard-shape": { + const value = + step.trim === undefined + ? "raw" + : `SpecRuntime.trimBy(raw, SpecRuntime::is${naming.pascal(step.trim)})`; + const separators = + step.separators === undefined ? "null" : `SpecRuntime::is${naming.pascal(step.separators)}`; + + return ` if (!SpecRuntime.matchShape(${value}, new int[] {${step.groups.join(", ")}}, ${separators})) { + return ${bail}; + }`; + } + case "guard-charset": { + return ` for (int index = 0; index < raw.length(); index++) { + int code = raw.charAt(index); + + if (!(${step.allow.map((name) => `SpecRuntime.is${naming.pascal(name)}(code)`).join(" || ")})) { + return ${bail}; + } + }`; + } + case "sanitize": { + return ` String digits = SpecRuntime.keepBy(raw, SpecRuntime::is${naming.pascal(step.keep)});`; + } + case "guard-length": { + return ` if (digits.length() != ${step.equals}) { + return ${bail}; + }`; + } + case "guard-repeated": { + return ` if (SpecRuntime.isRepeated(digits)) { + return ${bail}; + }`; + } + case "verify-check-digits": { + return ` if (!SpecRuntime.verify${naming.pascal(step.checkDigit)}(digits)) { + return ${bail}; + }`; + } + case "apply-pattern": { + const pattern = + step.variants?.["obfuscate"] !== undefined && planned.options.includes("obfuscate") + ? `obfuscate ? ${escapeLiteral(step.variants["obfuscate"])} : ${escapeLiteral(step.pattern)}` + : escapeLiteral(step.pattern); + const pad = planned.options.includes("pad") ? "pad" : "false"; + + return ` return SpecRuntime.applyPattern(digits, ${pattern}, ${pad});`; + } + case "guard-valid": { + // `expandPipeline` replaces this step with the referenced profile's own steps. + throw new Error(`${spec.id}: guard-valid reached the emitter unexpanded`); + } + default: { + throw new Error(`unsupported step: ${JSON.stringify(step)}`); + } + } +}; + +/** + * What closes the generated body: the success value, or nothing when a step already returned. + * + * @param {UtilitySpec} spec - The utility being emitted. + * @param {PlannedFunction} planned - The planned function. + * @returns {string} The closing lines, which may be empty. + */ +const tailOf = (spec: UtilitySpec, planned: PlannedFunction): string => { + if (spec.kind === "validator") return "\n\n return true;"; + + const returnsEarly = expandPipeline(planned.profile).some((step) => step.op === "apply-pattern"); + + return returnsEarly ? "" : "\n\n return digits;"; +}; + +/** + * Renders one planned function, documentation included. + * + * @param {PlannedFunction} planned - The function to render. + * @returns {string} The rendered source. + */ +const renderFunction = (planned: PlannedFunction): string => { + const { spec } = planned; + const returns = spec.kind === "validator" ? "boolean" : "String"; + const parameters = [ + `String ${naming.camel(spec.input.name)}`, + ...planned.options.map((option) => `boolean ${option}`), + ].join(", "); + + const head = ` if (${naming.camel(spec.input.name)} == null) { + return ${bailValue(spec, planned)}; + } + + String raw = ${naming.camel(spec.input.name)};`; + + const body = expandPipeline(planned.profile) + .map((step) => renderStep(step, spec, planned)) + .join("\n"); + const tail = tailOf(spec, planned); + + const overload = + planned.options.length > 0 + ? ` + /** ${spec.summary} Uses the default options. */ + public static ${returns} ${planned.name}(String ${naming.camel(spec.input.name)}) { + return ${planned.name}(${[naming.camel(spec.input.name), ...planned.options.map(() => "false")].join(", ")}); + } +` + : ""; + + return `${overload} + /** + * ${spec.summary} + * + *

Profile: ${planned.profileName} — ${planned.profile.description} + * +${spec.sources.map((source) => ` *

${source.role === "official" ? "Official" : "Based on"}: ${source.url}`).join("\n")} + */ + public static ${returns} ${planned.name}(${parameters}) { +${head} + +${body}${tail} + }`; +}; + +/** + * Emits every file of this target. + * + * @param {Plan} plan - The emission plan. + * @returns {Record} The files, by path relative to the target directory. + */ +export const emit = (plan: Plan): Record => { + const files: Record = { "SpecRuntime.java": prelude(plan) }; + const modules = new Map(); + + for (const planned of plan.functions) { + modules.set(planned.module, [...(modules.get(planned.module) ?? []), planned]); + } + + for (const [module, functions] of modules) { + files[`${module}.java`] = `// Code generated from spec/utilities by spec/codegen. DO NOT EDIT. + +/** ${functions.map((planned) => planned.spec.summary).join(" ")} */ +public final class ${module} { + private ${module}() {} +${functions.map((planned) => renderFunction(planned)).join("\n")} +} +`; + } + + return files; +}; diff --git a/spec/codegen/targets/python.ts b/spec/codegen/targets/python.ts new file mode 100644 index 000000000..83eab569c --- /dev/null +++ b/spec/codegen/targets/python.ts @@ -0,0 +1,360 @@ +/** + * Python emitter: produces modules shaped like `brutils/`, with the names and the + * `None` returning formatter contract that package already exposes. + */ +import { type Step, type UtilitySpec } from "../ir.ts"; +import { type Plan, type PlannedFunction, expandPipeline, naming } from "../plan.ts"; + +/** + * Renders a string as a Python literal. + * + * @param {string} value - The text to render. + * @returns {string} The literal, quotes included. + */ +const escapeLiteral = (value: string): string => { + let literal = '"'; + + for (const char of value) { + const code = char.codePointAt(0) ?? 0; + + if (char === '"') literal += String.raw`\"`; + else if (char === "\\") literal += String.raw`\\`; + else if (code < 0x20 || code > 0x7e) literal += `\\U${code.toString(16).padStart(8, "0")}`; + else literal += char; + } + + return `${literal}"`; +}; + +/** + * Renders the membership test of a charset as an expression of the target language. + * + * @param {Plan} plan - The emission plan holding the resolved charsets. + * @param {string} name - The charset name. + * @returns {string} The boolean expression. + */ +const charsetTest = (plan: Plan, name: string): string => { + const found = plan.charsets.find((charset) => charset.name === name); + const { single, ranges } = found?.ranges ?? { single: [], ranges: [] }; + + return [ + ...single.map((code) => `code == 0x${code.toString(16)}`), + ...ranges.map(([from, to]) => `(0x${from.toString(16)} <= code <= 0x${to.toString(16)})`), + ].join("\n or "); +}; + +/** + * Renders the runtime shared by every generated utility of this target. + * + * @param {Plan} plan - The emission plan. + * @returns {string} The prelude source. + */ +const prelude = (plan: Plan): string => { + const charsets = plan.charsets + .map( + (charset) => `def is_${charset.symbol}(code: int) -> bool: + """Whether the code point belongs to the ${charset.name} set.""" + return ( + ${charsetTest(plan, charset.name)} + )`, + ) + .join("\n\n\n"); + + const algorithms = plan.algorithms + .map((entry) => { + const { algorithm } = entry; + const body = + algorithm.weights.kind === "fixed" + ? ` weights = [${algorithm.weights.values.join(", ")}] + total = sum(int(base[index]) * weight for index, weight in enumerate(weights))` + : ` total = sum( + int(digit) * (len(base) + 1 - index) for index, digit in enumerate(base) + )`; + + return `def check_digit_${entry.symbol}(base: str) -> int: + """${algorithm.description} + + Official source: ${algorithm.source} + """ +${body} + digit = ${algorithm.modulus} - (total % ${algorithm.modulus}) + + return ${algorithm.clamp.to} if digit >= ${algorithm.clamp.atLeast} else digit + + +def verify_${entry.symbol}(digits: str) -> bool: + """Whether every check digit of the value matches its base.""" + for position in (${algorithm.positions.join(", ")},): + if len(digits) <= position: + return False + if int(digits[position]) != check_digit_${entry.symbol}(digits[:position]): + return False + + return True`; + }) + .join("\n\n\n"); + + return `# Code generated from spec/utilities by spec/codegen. DO NOT EDIT. +"""Runtime shared by the generated utilities.""" + +from typing import Callable, List, Optional + +${charsets} + + +def trim_by(value: str, in_set: Callable[[int], bool]) -> str: + """Strips the leading and trailing characters that belong to the set.""" + start, end = 0, len(value) + + while start < end and in_set(ord(value[start])): + start += 1 + while end > start and in_set(ord(value[end - 1])): + end -= 1 + + return value[start:end] + + +def keep_by(value: str, in_set: Callable[[int], bool]) -> str: + """Keeps only the characters that belong to the set.""" + return "".join(char for char in value if in_set(ord(char))) + + +def match_shape( + value: str, groups: List[int], in_separator: Optional[Callable[[int], bool]] = None +) -> bool: + """Whether the value is exactly the digit groups, optionally separated.""" + index = 0 + + for position, size in enumerate(groups): + if position > 0 and in_separator is not None: + while index < len(value) and in_separator(ord(value[index])): + index += 1 + + for _ in range(size): + if index >= len(value) or not is_ascii_digits(ord(value[index])): + return False + index += 1 + + return index == len(value) + + +def is_repeated(value: str) -> bool: + """Whether the value is a non empty run of one repeated character.""" + return value != "" and value == value[0] * len(value) + + +def apply_pattern(value: str, pattern: str, pad: bool) -> str: + """Lays the value over the pattern: "0" copies, "*" hides, anything else separates.""" + padded = value + + if pad: + slots = sum(1 for char in pattern if char in "0*") + padded = value.rjust(slots, "0") + + formatted = "" + index = 0 + + for char in pattern: + if char in "0*": + if index >= len(padded): + break + formatted += "*" if char == "*" else padded[index] + index += 1 + elif index < len(padded): + formatted += char + + return formatted + + +${algorithms} +`; +}; + +/** + * The value the generated function returns when a guard rejects the input. + * + * @param {UtilitySpec} spec - The utility being emitted. + * @param {PlannedFunction} planned - The planned function. + * @returns {string} The literal to return. + */ +const bailValue = (spec: UtilitySpec, planned: PlannedFunction): string => { + if (spec.kind === "validator") return "False"; + + return planned.nullable ? "None" : '""'; +}; + +/** + * Renders one pipeline step as statements of the target language. + * + * @param {Step} step - The step to render. + * @param {UtilitySpec} spec - The utility being emitted. + * @param {PlannedFunction} planned - The planned function. + * @returns {string} The rendered statements. + */ +const renderStep = (step: Step, spec: UtilitySpec, planned: PlannedFunction): string => { + const bail = bailValue(spec, planned); + + switch (step.op) { + case "guard-shape": { + const value = step.trim === undefined ? "raw" : `trim_by(raw, is_${naming.snake(step.trim)})`; + const separators = + step.separators === undefined ? "" : `, is_${naming.snake(step.separators)}`; + + return ` if not match_shape(${value}, [${step.groups.join(", ")}]${separators}): + return ${bail}`; + } + case "guard-charset": { + return ` for char in raw: + if not (${step.allow.map((name) => `is_${naming.snake(name)}(ord(char))`).join(" or ")}): + return ${bail}`; + } + case "sanitize": { + return ` digits = keep_by(raw, is_${naming.snake(step.keep)})`; + } + case "guard-length": { + return ` if len(digits) != ${step.equals}: + return ${bail}`; + } + case "guard-repeated": { + return ` if is_repeated(digits): + return ${bail}`; + } + case "verify-check-digits": { + return ` if not verify_${naming.snake(step.checkDigit)}(digits): + return ${bail}`; + } + case "apply-pattern": { + const pattern = + step.variants?.["obfuscate"] !== undefined && planned.options.includes("obfuscate") + ? `${escapeLiteral(step.variants["obfuscate"])} if obfuscate else ${escapeLiteral(step.pattern)}` + : escapeLiteral(step.pattern); + const pad = planned.options.includes("pad") ? "pad" : "False"; + + return ` return apply_pattern(digits, ${pattern}, ${pad})`; + } + case "guard-valid": { + // `expandPipeline` replaces this step with the referenced profile's own steps. + throw new Error(`${spec.id}: guard-valid reached the emitter unexpanded`); + } + default: { + throw new Error(`unsupported step: ${JSON.stringify(step)}`); + } + } +}; + +/** + * The return type the generated function declares. + * + * @param {UtilitySpec} spec - The utility being emitted. + * @param {PlannedFunction} planned - The planned function. + * @returns {string} The type, spelled in the target language. + */ +const returnTypeOf = (spec: UtilitySpec, planned: PlannedFunction): string => { + if (spec.kind === "validator") return "bool"; + + return planned.nullable ? "Optional[str]" : "str"; +}; + +/** + * What closes the generated body: the success value, or nothing when a step already returned. + * + * @param {UtilitySpec} spec - The utility being emitted. + * @param {PlannedFunction} planned - The planned function. + * @returns {string} The closing lines, which may be empty. + */ +const tailOf = (spec: UtilitySpec, planned: PlannedFunction): string => { + if (spec.kind === "validator") return "\n\n return True"; + + const returnsEarly = expandPipeline(planned.profile).some((step) => step.op === "apply-pattern"); + + return returnsEarly ? "" : "\n\n return digits"; +}; + +/** + * Renders one planned function, documentation included. + * + * @param {PlannedFunction} planned - The function to render. + * @returns {string} The rendered source. + */ +const renderFunction = (planned: PlannedFunction): string => { + const { spec } = planned; + const returnType = returnTypeOf(spec, planned); + const parameters = + spec.kind === "validator" + ? `${naming.snake(spec.input.name)}: object` + : ["value: object", ...planned.options.map((option) => `${option}: bool = False`)].join(", "); + + const absent = planned.nullable ? "None" : '""'; + const head = + spec.kind === "validator" + ? ` if not isinstance(${naming.snake(spec.input.name)}, str): + return False + + raw = ${naming.snake(spec.input.name)}` + : ` if value is None: + return ${absent} + + raw = value if isinstance(value, str) else str(value)`; + + const body = expandPipeline(planned.profile) + .map((step) => renderStep(step, spec, planned)) + .join("\n"); + const tail = tailOf(spec, planned); + + return `def ${planned.name}(${parameters}) -> ${returnType}: + """${spec.summary} + + Profile: ${planned.profileName} — ${planned.profile.description} + +${spec.sources.map((source) => ` ${source.role === "official" ? "Official" : "Based on"}: ${source.url}`).join("\n")} + """ +${head} + +${body}${tail}`; +}; + +/** + * Emits every file of this target. + * + * @param {Plan} plan - The emission plan. + * @returns {Record} The files, by path relative to the target directory. + */ +export const emit = (plan: Plan): Record => { + const files: Record = { + "_spec_runtime.py": prelude(plan), + "brutils/__init__.py": "# Code generated from spec/utilities by spec/codegen. DO NOT EDIT.\n", + }; + const modules = new Map(); + + for (const planned of plan.functions) { + modules.set(planned.module, [...(modules.get(planned.module) ?? []), planned]); + } + + for (const [module, functions] of modules) { + const path = `${module.replaceAll(".", "/")}.py`; + const source = functions.map((planned) => renderFunction(planned)).join("\n\n\n"); + const symbols = [ + "trim_by", + "keep_by", + "match_shape", + "is_repeated", + "apply_pattern", + ...plan.charsets.map((charset) => `is_${charset.symbol}`), + ...plan.algorithms.map((entry) => `verify_${entry.symbol}`), + ].filter((symbol) => new RegExp(`\\b${symbol}\\b`).test(source)); + const typing = source.includes("Optional[str]") ? "from typing import Optional\n\n" : ""; + + files[path] = `# Code generated from spec/utilities by spec/codegen. DO NOT EDIT. +"""${functions.map((planned) => planned.spec.summary).join(" ")}""" + +${typing}from _spec_runtime import ( +${symbols.map((symbol) => ` ${symbol},`).join("\n")} +) + + +${source} +`; + } + + return files; +}; diff --git a/spec/codegen/targets/registry.ts b/spec/codegen/targets/registry.ts new file mode 100644 index 000000000..f1af4782a --- /dev/null +++ b/spec/codegen/targets/registry.ts @@ -0,0 +1,20 @@ +/** The language targets the specs can be emitted to, by id. */ +import { type Plan } from "../plan.ts"; +import { emit as emitGo } from "./go.ts"; +import { emit as emitJava } from "./java.ts"; +import { emit as emitPython } from "./python.ts"; +import { emit as emitRuby } from "./ruby.ts"; +import { emit as emitRust } from "./rust.ts"; +import { emit as emitTypeScript } from "./typescript.ts"; + +/** Maps a path relative to the target's output directory to the file's contents. */ +export type Emitter = (plan: Plan) => Record; + +export const emitters: Record = { + typescript: emitTypeScript, + python: emitPython, + go: emitGo, + ruby: emitRuby, + rust: emitRust, + java: emitJava, +}; diff --git a/spec/codegen/targets/ruby.ts b/spec/codegen/targets/ruby.ts new file mode 100644 index 000000000..bdcf0ac79 --- /dev/null +++ b/spec/codegen/targets/ruby.ts @@ -0,0 +1,346 @@ +/** + * Ruby emitter: module functions under `BrazilianUtils::*Utils`, keeping the `valid?` + * predicate name and the `nil` returning formatter the gem already exposes. + */ +import { type Step, type UtilitySpec } from "../ir.ts"; +import { type Plan, type PlannedFunction, expandPipeline, naming } from "../plan.ts"; + +/** + * Renders a string as a Ruby double quoted literal, where `#` also has to be escaped because + * `#{...}` would interpolate. + * + * @param {string} value - The text to render. + * @returns {string} The literal, quotes included. + */ +const escapeLiteral = (value: string): string => { + let literal = '"'; + + for (const char of value) { + const code = char.codePointAt(0) ?? 0; + + if (char === '"') literal += String.raw`\"`; + else if (char === "\\") literal += String.raw`\\`; + else if (char === "#") literal += String.raw`\#`; + else if (code < 0x20 || code > 0x7e) literal += `\\u{${code.toString(16)}}`; + else literal += char; + } + + return `${literal}"`; +}; + +/** + * Renders the membership test of a charset as an expression of the target language. + * + * @param {Plan} plan - The emission plan holding the resolved charsets. + * @param {string} name - The charset name. + * @returns {string} The boolean expression. + */ +const charsetTest = (plan: Plan, name: string): string => { + const found = plan.charsets.find((charset) => charset.name === name); + const { single, ranges } = found?.ranges ?? { single: [], ranges: [] }; + + return [ + ...single.map((code) => `code == 0x${code.toString(16)}`), + ...ranges.map( + ([from, to]) => `(code >= 0x${from.toString(16)} && code <= 0x${to.toString(16)})`, + ), + ].join(" ||\n "); +}; + +/** + * Renders the runtime shared by every generated utility of this target. + * + * @param {Plan} plan - The emission plan. + * @returns {string} The prelude source. + */ +const prelude = (plan: Plan): string => { + const charsets = plan.charsets + .map( + (charset) => ` # Whether the code point belongs to the ${charset.name} set. + def self.${charset.symbol}?(code) + ${charsetTest(plan, charset.name)} + end`, + ) + .join("\n\n"); + + const algorithms = plan.algorithms + .map((entry) => { + const { algorithm } = entry; + const body = + algorithm.weights.kind === "fixed" + ? ` weights = [${algorithm.weights.values.join(", ")}] + total = weights.each_with_index.sum { |weight, index| base[index].to_i * weight }` + : ` total = base.chars.each_with_index.sum { |digit, index| digit.to_i * (base.length + 1 - index) }`; + + return ` # ${algorithm.description} + # + # Official source: ${algorithm.source} + def self.check_digit_${entry.symbol}(base) +${body} + digit = ${algorithm.modulus} - (total % ${algorithm.modulus}) + + digit >= ${algorithm.clamp.atLeast} ? ${algorithm.clamp.to} : digit + end + + # Whether every check digit of the value matches its base. + def self.verify_${entry.symbol}(digits) + [${algorithm.positions.join(", ")}].all? do |position| + digits.length > position && + digits[position].to_i == check_digit_${entry.symbol}(digits[0...position]) + end + end`; + }) + .join("\n\n"); + + return `# frozen_string_literal: true + +# Code generated from spec/utilities by spec/codegen. DO NOT EDIT. + +module BrazilianUtils + # Helpers shared by the generated utilities. + module SpecRuntime +${charsets} + + # Strips the leading and trailing characters that belong to the set. + def self.trim_by(value, in_set) + chars = value.chars + start = 0 + last = chars.length + + start += 1 while start < last && in_set.call(chars[start].ord) + last -= 1 while last > start && in_set.call(chars[last - 1].ord) + + chars[start...last].join + end + + # Keeps only the characters that belong to the set. + def self.keep_by(value, in_set) + value.chars.select { |char| in_set.call(char.ord) }.join + end + + # Whether the value is exactly the digit groups, optionally separated. + def self.match_shape(value, groups, in_separator = nil) + chars = value.chars + index = 0 + + groups.each_with_index do |size, position| + if position.positive? && !in_separator.nil? + index += 1 while index < chars.length && in_separator.call(chars[index].ord) + end + + size.times do + return false if index >= chars.length || !ascii_digits?(chars[index].ord) + + index += 1 + end + end + + index == chars.length + end + + # Whether the value is a non empty run of one repeated character. + def self.is_repeated(value) + !value.empty? && value == value[0] * value.length + end + + # Lays the value over the pattern: "0" copies, "*" hides, anything else separates. + def self.apply_pattern(value, pattern, pad) + padded = value + + if pad + slots = pattern.chars.count { |char| ['0', '*'].include?(char) } + padded = value.rjust(slots, '0') + end + + formatted = +'' + index = 0 + + pattern.each_char do |char| + if ['0', '*'].include?(char) + break if index >= padded.length + + formatted << (char == '*' ? '*' : padded[index]) + index += 1 + elsif index < padded.length + formatted << char + end + end + + formatted + end + +${algorithms} + end +end +`; +}; + +/** + * The value the generated function returns when a guard rejects the input. + * + * @param {UtilitySpec} spec - The utility being emitted. + * @param {PlannedFunction} planned - The planned function. + * @returns {string} The literal to return. + */ +const bailValue = (spec: UtilitySpec, planned: PlannedFunction): string => { + if (spec.kind === "validator") return "false"; + + return planned.nullable ? "nil" : "''"; +}; + +/** + * Renders one pipeline step as statements of the target language. + * + * @param {Step} step - The step to render. + * @param {UtilitySpec} spec - The utility being emitted. + * @param {PlannedFunction} planned - The planned function. + * @returns {string} The rendered statements. + */ +const renderStep = (step: Step, spec: UtilitySpec, planned: PlannedFunction): string => { + const bail = bailValue(spec, planned); + const runtime = "BrazilianUtils::SpecRuntime"; + + switch (step.op) { + case "guard-shape": { + const value = + step.trim === undefined + ? "raw" + : `${runtime}.trim_by(raw, ${runtime}.method(:${naming.snake(step.trim)}?))`; + const separators = + step.separators === undefined + ? "" + : `, ${runtime}.method(:${naming.snake(step.separators)}?)`; + + return ` return ${bail} unless ${runtime}.match_shape(${value}, [${step.groups.join(", ")}]${separators})`; + } + case "guard-charset": { + return ` raw.each_char do |char| + code = char.ord + + return ${bail} unless ${step.allow.map((name) => `${runtime}.${naming.snake(name)}?(code)`).join(" || ")} + end`; + } + case "sanitize": { + return ` digits = ${runtime}.keep_by(raw, ${runtime}.method(:${naming.snake(step.keep)}?))`; + } + case "guard-length": { + return ` return ${bail} unless digits.length == ${step.equals}`; + } + case "guard-repeated": { + return ` return ${bail} if ${runtime}.is_repeated(digits)`; + } + case "verify-check-digits": { + return ` return ${bail} unless ${runtime}.verify_${naming.snake(step.checkDigit)}(digits)`; + } + case "apply-pattern": { + const pattern = + step.variants?.["obfuscate"] !== undefined && planned.options.includes("obfuscate") + ? `obfuscate ? ${escapeLiteral(step.variants["obfuscate"])} : ${escapeLiteral(step.pattern)}` + : escapeLiteral(step.pattern); + const pad = planned.options.includes("pad") ? "pad" : "false"; + + return ` ${runtime}.apply_pattern(digits, ${pattern}, ${pad})`; + } + case "guard-valid": { + // `expandPipeline` replaces this step with the referenced profile's own steps. + throw new Error(`${spec.id}: guard-valid reached the emitter unexpanded`); + } + default: { + throw new Error(`unsupported step: ${JSON.stringify(step)}`); + } + } +}; + +/** + * What closes the generated body: the success value, or nothing when a step already returned. + * + * @param {UtilitySpec} spec - The utility being emitted. + * @param {PlannedFunction} planned - The planned function. + * @returns {string} The closing lines, which may be empty. + */ +const tailOf = (spec: UtilitySpec, planned: PlannedFunction): string => { + if (spec.kind === "validator") return "\n\n true"; + + const returnsEarly = expandPipeline(planned.profile).some((step) => step.op === "apply-pattern"); + + return returnsEarly ? "" : "\n\n digits"; +}; + +/** + * Renders one planned function, documentation included. + * + * @param {PlannedFunction} planned - The function to render. + * @returns {string} The rendered source. + */ +const renderFunction = (planned: PlannedFunction): string => { + const { spec } = planned; + const parameters = [ + naming.snake(spec.input.name), + ...planned.options.map((option) => `${option} = false`), + ].join(", "); + + const absent = planned.nullable ? "nil" : "''"; + const head = + spec.kind === "validator" + ? ` return false unless ${naming.snake(spec.input.name)}.is_a?(String) + + raw = ${naming.snake(spec.input.name)}` + : ` return ${absent} if ${naming.snake(spec.input.name)}.nil? + + raw = ${naming.snake(spec.input.name)}.to_s`; + + const body = expandPipeline(planned.profile) + .map((step) => renderStep(step, spec, planned)) + .join("\n"); + const tail = tailOf(spec, planned); + + return ` # ${spec.summary} + # + # Profile: ${planned.profileName} — ${planned.profile.description} + # +${spec.sources.map((source) => ` # ${source.role === "official" ? "Official" : "Based on"}: ${source.url}`).join("\n")} + def self.${planned.name}(${parameters}) +${head} + +${body}${tail} + end`; +}; + +/** + * Emits every file of this target. + * + * @param {Plan} plan - The emission plan. + * @returns {Record} The files, by path relative to the target directory. + */ +export const emit = (plan: Plan): Record => { + const files: Record = { "brazilian-utils/spec_runtime.rb": prelude(plan) }; + const modules = new Map(); + + for (const planned of plan.functions) { + modules.set(planned.module, [...(modules.get(planned.module) ?? []), planned]); + } + + for (const [module, functions] of modules) { + const shortName = module.split("::").at(-1) ?? module; + const fileName = shortName + .replace(/Utils$/, "") + .replaceAll(/([a-z])([A-Z])/g, "$1-$2") + .toLowerCase(); + + files[`brazilian-utils/${fileName}-utils.rb`] = `# frozen_string_literal: true + +# Code generated from spec/utilities by spec/codegen. DO NOT EDIT. + +require_relative 'spec_runtime' + +module BrazilianUtils + # ${functions.map((planned) => planned.spec.summary).join(" ")} + module ${shortName} +${functions.map((planned) => renderFunction(planned)).join("\n\n")} + end +end +`; + } + + return files; +}; diff --git a/spec/codegen/targets/rust.ts b/spec/codegen/targets/rust.ts new file mode 100644 index 000000000..cfd8bf0fe --- /dev/null +++ b/spec/codegen/targets/rust.ts @@ -0,0 +1,374 @@ +/** + * Rust emitter: one module per document, `&str` in, `bool`/`Option` out, matching the + * signatures the crate already publishes. + */ +import { type Step, type UtilitySpec } from "../ir.ts"; +import { type Plan, type PlannedFunction, expandPipeline, naming } from "../plan.ts"; + +/** + * Renders a string as a Rust literal. + * + * @param {string} value - The text to render. + * @returns {string} The literal, quotes included. + */ +const escapeLiteral = (value: string): string => { + let literal = '"'; + + for (const char of value) { + const code = char.codePointAt(0) ?? 0; + + if (char === '"') literal += String.raw`\"`; + else if (char === "\\") literal += String.raw`\\`; + else if (code < 0x20 || code > 0x7e) literal += `\\u{${code.toString(16)}}`; + else literal += char; + } + + return `${literal}"`; +}; + +/** + * Renders the membership test of a charset as an expression of the target language. + * + * @param {Plan} plan - The emission plan holding the resolved charsets. + * @param {string} name - The charset name. + * @returns {string} The boolean expression. + */ +const charsetTest = (plan: Plan, name: string): string => { + const found = plan.charsets.find((charset) => charset.name === name); + const { single, ranges } = found?.ranges ?? { single: [], ranges: [] }; + + return [ + ...single.map((code) => `code == 0x${code.toString(16)}`), + ...ranges.map( + ([from, to]) => `(0x${from.toString(16)}..=0x${to.toString(16)}).contains(&code)`, + ), + ].join("\n || "); +}; + +/** + * Renders the runtime shared by every generated utility of this target. + * + * @param {Plan} plan - The emission plan. + * @returns {string} The prelude source. + */ +const prelude = (plan: Plan): string => { + const charsets = plan.charsets + .map( + (charset) => `/// Whether the code point belongs to the ${charset.name} set. +pub fn is_${charset.symbol}(code: u32) -> bool { + ${charsetTest(plan, charset.name)} +}`, + ) + .join("\n\n"); + + const algorithms = plan.algorithms + .map((entry) => { + const { algorithm } = entry; + const body = + algorithm.weights.kind === "fixed" + ? ` const WEIGHTS: [u32; ${algorithm.weights.values.length}] = [${algorithm.weights.values.join(", ")}]; + + let sum: u32 = base + .bytes() + .zip(WEIGHTS.iter()) + .map(|(byte, weight)| u32::from(byte - b'0') * weight) + .sum();` + : ` let length = base.len() as u32; + let sum: u32 = base + .bytes() + .enumerate() + .map(|(index, byte)| u32::from(byte - b'0') * (length + 1 - index as u32)) + .sum();`; + + return `/// ${algorithm.description} +/// +/// Official source: ${algorithm.source} +pub fn check_digit_${entry.symbol}(base: &str) -> u32 { +${body} + + let digit = ${algorithm.modulus} - (sum % ${algorithm.modulus}); + + if digit >= ${algorithm.clamp.atLeast} { + ${algorithm.clamp.to} + } else { + digit + } +} + +/// Whether every check digit of the value matches its base. +pub fn verify_${entry.symbol}(digits: &str) -> bool { + [${algorithm.positions.join(", ")}].iter().all(|&position: &usize| { + digits.len() > position + && u32::from(digits.as_bytes()[position] - b'0') + == check_digit_${entry.symbol}(&digits[..position]) + }) +}`; + }) + .join("\n\n"); + + return `// Code generated from spec/utilities by spec/codegen. DO NOT EDIT. + +//! Helpers shared by the generated utilities. + +${charsets} + +/// Strips the leading and trailing characters that belong to the set. +pub fn trim_by(value: &str, in_set: fn(u32) -> bool) -> &str { + value.trim_matches(|char: char| in_set(char as u32)) +} + +/// Keeps only the characters that belong to the set. +pub fn keep_by(value: &str, in_set: fn(u32) -> bool) -> String { + value.chars().filter(|char| in_set(*char as u32)).collect() +} + +/// Whether the value is exactly the digit groups, optionally separated. +pub fn match_shape(value: &str, groups: &[usize], in_separator: Option bool>) -> bool { + let chars: Vec = value.chars().collect(); + let mut index = 0; + + for (position, size) in groups.iter().enumerate() { + if position > 0 { + if let Some(separator) = in_separator { + while index < chars.len() && separator(chars[index] as u32) { + index += 1; + } + } + } + + for _ in 0..*size { + if index >= chars.len() || !is_ascii_digits(chars[index] as u32) { + return false; + } + + index += 1; + } + } + + index == chars.len() +} + +/// Whether the value is a non empty run of one repeated character. +pub fn is_repeated(value: &str) -> bool { + match value.chars().next() { + None => false, + Some(first) => value.chars().all(|char| char == first), + } +} + +/// Lays the value over the pattern: '0' copies, '*' hides, anything else separates. +pub fn apply_pattern(value: &str, pattern: &str, pad: bool) -> String { + let slots = pattern.chars().filter(|char| *char == '0' || *char == '*').count(); + let padded = if pad && value.chars().count() < slots { + format!("{}{}", "0".repeat(slots - value.chars().count()), value) + } else { + value.to_string() + }; + + let source: Vec = padded.chars().collect(); + let mut formatted = String::new(); + let mut index = 0; + + for char in pattern.chars() { + if char == '0' || char == '*' { + if index >= source.len() { + break; + } + + formatted.push(if char == '*' { '*' } else { source[index] }); + index += 1; + } else if index < source.len() { + formatted.push(char); + } + } + + formatted +} + +${algorithms} +`; +}; + +/** + * The value the generated function returns when a guard rejects the input. + * + * @param {UtilitySpec} spec - The utility being emitted. + * @param {PlannedFunction} planned - The planned function. + * @returns {string} The literal to return. + */ +const bailValue = (spec: UtilitySpec, planned: PlannedFunction): string => { + if (spec.kind === "validator") return "false"; + + return planned.nullable ? "None" : "String::new()"; +}; + +/** + * Renders one pipeline step as statements of the target language. + * + * @param {Step} step - The step to render. + * @param {UtilitySpec} spec - The utility being emitted. + * @param {PlannedFunction} planned - The planned function. + * @returns {string} The rendered statements. + */ +const renderStep = (step: Step, spec: UtilitySpec, planned: PlannedFunction): string => { + const bail = bailValue(spec, planned); + + switch (step.op) { + case "guard-shape": { + const value = + step.trim === undefined + ? "raw" + : `spec_runtime::trim_by(raw, spec_runtime::is_${naming.snake(step.trim)})`; + const separators = + step.separators === undefined + ? "None" + : `Some(spec_runtime::is_${naming.snake(step.separators)} as fn(u32) -> bool)`; + + return ` if !spec_runtime::match_shape(${value}, &[${step.groups.join(", ")}], ${separators}) { + return ${bail}; + }`; + } + case "guard-charset": { + return ` for char in raw.chars() { + let code = char as u32; + + if !(${step.allow.map((name) => `spec_runtime::is_${naming.snake(name)}(code)`).join(" || ")}) { + return ${bail}; + } + }`; + } + case "sanitize": { + return ` let digits = spec_runtime::keep_by(raw, spec_runtime::is_${naming.snake(step.keep)});`; + } + case "guard-length": { + return ` if digits.len() != ${step.equals} { + return ${bail}; + }`; + } + case "guard-repeated": { + return ` if spec_runtime::is_repeated(&digits) { + return ${bail}; + }`; + } + case "verify-check-digits": { + return ` if !spec_runtime::verify_${naming.snake(step.checkDigit)}(&digits) { + return ${bail}; + }`; + } + case "apply-pattern": { + const pattern = + step.variants?.["obfuscate"] !== undefined && planned.options.includes("obfuscate") + ? `if obfuscate { ${escapeLiteral(step.variants["obfuscate"])} } else { ${escapeLiteral(step.pattern)} }` + : escapeLiteral(step.pattern); + const pad = planned.options.includes("pad") ? "pad" : "false"; + const call = `spec_runtime::apply_pattern(&digits, ${pattern}, ${pad})`; + const wrapped = planned.nullable ? `Some(${call})` : call; + + return ` ${wrapped}`; + } + case "guard-valid": { + // `expandPipeline` replaces this step with the referenced profile's own steps. + throw new Error(`${spec.id}: guard-valid reached the emitter unexpanded`); + } + default: { + throw new Error(`unsupported step: ${JSON.stringify(step)}`); + } + } +}; + +/** + * The return type the generated function declares. + * + * @param {UtilitySpec} spec - The utility being emitted. + * @param {PlannedFunction} planned - The planned function. + * @returns {string} The type, spelled in the target language. + */ +const returnTypeOf = (spec: UtilitySpec, planned: PlannedFunction): string => { + if (spec.kind === "validator") return "bool"; + + return planned.nullable ? "Option" : "String"; +}; + +/** + * What closes the generated body: the success value, or nothing when a step already returned. + * + * @param {UtilitySpec} spec - The utility being emitted. + * @param {PlannedFunction} planned - The planned function. + * @returns {string} The closing lines, which may be empty. + */ +const tailOf = (spec: UtilitySpec, planned: PlannedFunction): string => { + if (spec.kind === "validator") return "\n\n true"; + + const returnsEarly = expandPipeline(planned.profile).some((step) => step.op === "apply-pattern"); + + return returnsEarly ? "" : "\n\n digits"; +}; + +/** + * Renders one planned function, documentation included. + * + * @param {PlannedFunction} planned - The function to render. + * @returns {string} The rendered source. + */ +const renderFunction = (planned: PlannedFunction): string => { + const { spec } = planned; + const returns = returnTypeOf(spec, planned); + const parameters = [ + `${naming.snake(spec.input.name)}: &str`, + ...planned.options.map((option) => `${option}: bool`), + ].join(", "); + + // Rust's type system already rejects the non string inputs the dynamic targets guard against. + const head = ` let raw = ${naming.snake(spec.input.name)};`; + const body = expandPipeline(planned.profile) + .map((step) => renderStep(step, spec, planned)) + .join("\n"); + const tail = tailOf(spec, planned); + + return `/// ${spec.summary} +/// +/// Profile: ${planned.profileName} — ${planned.profile.description} +/// +${spec.sources.map((source) => `/// ${source.role === "official" ? "Official" : "Based on"}: ${source.url}`).join("\n")} +pub fn ${planned.name}(${parameters}) -> ${returns} { +${head} + +${body}${tail} +}`; +}; + +/** + * Emits every file of this target. + * + * @param {Plan} plan - The emission plan. + * @returns {Record} The files, by path relative to the target directory. + */ +export const emit = (plan: Plan): Record => { + const files: Record = { "spec_runtime.rs": prelude(plan) }; + const modules = new Map(); + + for (const planned of plan.functions) { + modules.set(planned.module, [...(modules.get(planned.module) ?? []), planned]); + } + + for (const [module, functions] of modules) { + files[`${module}.rs`] = `// Code generated from spec/utilities by spec/codegen. DO NOT EDIT. + +//! ${functions.map((planned) => planned.spec.summary).join(" ")} + +use crate::spec_runtime; + +${functions.map((planned) => renderFunction(planned)).join("\n\n")} +`; + } + + files["lib.rs"] = `// Code generated from spec/utilities by spec/codegen. DO NOT EDIT. + +//! Generated Brazilian Utils, emitted from the language neutral specs. + +pub mod spec_runtime; +${[...modules.keys()].map((module) => `pub mod ${module};`).join("\n")} +`; + + return files; +}; diff --git a/spec/codegen/targets/typescript.ts b/spec/codegen/targets/typescript.ts new file mode 100644 index 000000000..561f27fdc --- /dev/null +++ b/spec/codegen/targets/typescript.ts @@ -0,0 +1,364 @@ +/** + * TypeScript emitter: produces modules shaped like the ones under `src/`, so the generated + * output can be diffed against the handwritten package it is meant to replace. + */ +import { type Step, type UtilitySpec } from "../ir.ts"; +import { type Plan, type PlannedFunction, expandPipeline, naming } from "../plan.ts"; + +/** + * Renders a string as a TypeScript literal. + * + * @param {string} value - The text to render. + * @returns {string} The literal, quotes included. + */ +const escapeLiteral = (value: string): string => { + let literal = '"'; + + for (const char of value) { + const code = char.codePointAt(0) ?? 0; + + if (char === '"') literal += String.raw`\"`; + else if (char === "\\") literal += String.raw`\\`; + else if (code < 0x20 || code > 0x7e) literal += `\\u{${code.toString(16)}}`; + else literal += char; + } + + return `${literal}"`; +}; + +/** + * Renders the membership test of a charset as an expression of the target language. + * + * @param {Plan} plan - The emission plan holding the resolved charsets. + * @param {string} name - The charset name. + * @returns {string} The boolean expression. + */ +const charsetTest = (plan: Plan, name: string): string => { + const { single, ranges } = plan.charsets.find((charset) => charset.name === name)?.ranges ?? { + single: [], + ranges: [], + }; + const tests = [ + ...single.map((code) => `code === 0x${code.toString(16)}`), + ...ranges.map( + ([from, to]) => `(code >= 0x${from.toString(16)} && code <= 0x${to.toString(16)})`, + ), + ]; + + return tests.join(" ||\n\t"); +}; + +/** + * Renders the runtime shared by every generated utility of this target. + * + * @param {Plan} plan - The emission plan. + * @returns {string} The prelude source. + */ +const prelude = (plan: Plan): string => { + const charsets = plan.charsets + .map( + ( + charset, + ) => `/** ${charset.name}: ${charset.ranges.single.length + charset.ranges.ranges.length} code point runs. */ +export const is${naming.pascal(charset.name)} = (code: number): boolean => + ${charsetTest(plan, charset.name)};`, + ) + .join("\n\n"); + + const algorithms = plan.algorithms + .map((entry) => { + const { algorithm } = entry; + const body = + algorithm.weights.kind === "fixed" + ? ` const weights = [${algorithm.weights.values.join(", ")}]; + let sum = 0; + + for (let index = 0; index < weights.length; index++) { + sum += (base.charCodeAt(index) - 48) * weights[index]; + }` + : ` let sum = 0; + let weight = base.length + 1; + + for (let index = 0; index < base.length; index++) { + sum += (base.charCodeAt(index) - 48) * weight; + weight--; + }`; + + return `/** + * ${algorithm.description} + * + * @see Official: ${algorithm.source} + */ +export const checkDigit${naming.pascal(entry.name)} = (base: string): number => { +${body} + + const digit = ${algorithm.modulus} - (sum % ${algorithm.modulus}); + + return digit >= ${algorithm.clamp.atLeast} ? ${algorithm.clamp.to} : digit; +}; + +export const verify${naming.pascal(entry.name)} = (digits: string): boolean => { + for (const position of [${algorithm.positions.join(", ")}]) { + if (digits.length <= position) return false; + if (digits.charCodeAt(position) - 48 !== checkDigit${naming.pascal(entry.name)}(digits.slice(0, position))) + return false; + } + + return true; +};`; + }) + .join("\n\n"); + + return `// Code generated from spec/utilities by spec/codegen. DO NOT EDIT. + +${charsets} + +export const trimBy = (value: string, inSet: (code: number) => boolean): string => { + let start = 0; + let end = value.length; + + while (start < end && inSet(value.charCodeAt(start))) start++; + while (end > start && inSet(value.charCodeAt(end - 1))) end--; + + return value.slice(start, end); +}; + +export const keepBy = (value: string, inSet: (code: number) => boolean): string => { + let kept = ""; + + for (let index = 0; index < value.length; index++) { + if (inSet(value.charCodeAt(index))) kept += value.charAt(index); + } + + return kept; +}; + +export const matchShape = ( + value: string, + groups: number[], + inSeparator?: (code: number) => boolean, +): boolean => { + let index = 0; + + for (const [position, size] of groups.entries()) { + if (position > 0 && inSeparator !== undefined) { + while (index < value.length && inSeparator(value.charCodeAt(index))) index++; + } + + for (let digit = 0; digit < size; digit++) { + if (index >= value.length || !isAsciiDigits(value.charCodeAt(index))) return false; + index++; + } + } + + return index === value.length; +}; + +export const isRepeated = (value: string): boolean => + value !== "" && value === value.charAt(0).repeat(value.length); + +export const applyPattern = (value: string, pattern: string, pad: boolean): string => { + let padded = value; + + if (pad) { + const slots = [...pattern].filter((char) => char === "0" || char === "*").length; + padded = value.padStart(slots, "0"); + } + + let formatted = ""; + let index = 0; + + for (const char of pattern) { + if (char === "0" || char === "*") { + if (index >= padded.length) break; + formatted += char === "*" ? "*" : padded.charAt(index); + index++; + } else if (index < padded.length) { + formatted += char; + } + } + + return formatted; +}; + +${algorithms} +`; +}; + +const reject = (spec: UtilitySpec): string => (spec.kind === "validator" ? "false" : '""'); + +/** + * Renders one pipeline step as statements of the target language. + * + * @param {Step} step - The step to render. + * @param {UtilitySpec} spec - The utility being emitted. + * @param {PlannedFunction} planned - The planned function. + * @returns {string} The rendered statements. + */ +const renderStep = (step: Step, spec: UtilitySpec, planned: PlannedFunction): string => { + const bail = planned.nullable ? "null" : reject(spec); + + switch (step.op) { + case "guard-shape": { + const value = step.trim === undefined ? "raw" : `trimBy(raw, is${naming.pascal(step.trim)})`; + const separators = + step.separators === undefined ? "" : `, is${naming.pascal(step.separators)}`; + + return ` if (!matchShape(${value}, [${step.groups.join(", ")}]${separators})) return ${bail};`; + } + case "guard-charset": { + return ` for (let index = 0; index < raw.length; index++) { + const code = raw.charCodeAt(index); + + if (!(${step.allow.map((name) => `is${naming.pascal(name)}(code)`).join(" || ")})) return ${bail}; + }`; + } + case "sanitize": { + return ` const digits = keepBy(raw, is${naming.pascal(step.keep)});`; + } + case "guard-length": { + return ` if (digits.length !== ${step.equals}) return ${bail};`; + } + case "guard-repeated": { + return ` if (isRepeated(digits)) return ${bail};`; + } + case "verify-check-digits": { + return ` if (!verify${naming.pascal(step.checkDigit)}(digits)) return ${bail};`; + } + case "apply-pattern": { + const pattern = + step.variants?.["obfuscate"] !== undefined && planned.options.includes("obfuscate") + ? `(options?.obfuscate ?? false) ? ${escapeLiteral(step.variants["obfuscate"])} : ${escapeLiteral(step.pattern)}` + : escapeLiteral(step.pattern); + const pad = planned.options.includes("pad") ? "options?.pad ?? false" : "false"; + + return ` return applyPattern(digits, ${pattern}, ${pad});`; + } + case "guard-valid": { + // `expandPipeline` replaces this step with the referenced profile's own steps. + throw new Error(`${spec.id}: guard-valid reached the emitter unexpanded`); + } + default: { + throw new Error(`unsupported step: ${JSON.stringify(step)}`); + } + } +}; + +/** + * The return type the generated function declares. + * + * @param {UtilitySpec} spec - The utility being emitted. + * @param {PlannedFunction} planned - The planned function. + * @returns {string} The type, spelled in the target language. + */ +const returnTypeOf = (spec: UtilitySpec, planned: PlannedFunction): string => { + if (spec.kind === "validator") return "boolean"; + + return planned.nullable ? "string | null" : "string"; +}; + +/** + * What closes the generated body: the success value, or nothing when a step already returned. + * + * @param {UtilitySpec} spec - The utility being emitted. + * @param {boolean} needsSanitize - Whether the pipeline never bound `digits`. + * @returns {string} The closing lines, which may be empty. + */ +const tailOf = (spec: UtilitySpec, needsSanitize: boolean): string => { + if (spec.kind === "validator") return "\n\n return true;"; + + return needsSanitize ? "\n\n return digits;" : ""; +}; + +/** + * Renders one planned function, documentation included. + * + * @param {PlannedFunction} planned - The function to render. + * @returns {string} The rendered source. + */ +const renderFunction = (planned: PlannedFunction): string => { + const { spec } = planned; + const optionsType = `${naming.pascal(spec.id)}Options`; + const hasOptions = planned.options.length > 0; + const returnType = returnTypeOf(spec, planned); + const parameter = + spec.kind === "validator" ? `${spec.input.name}: unknown` : `value: string | number`; + const optionsParameter = hasOptions ? `, options?: ${optionsType}` : ""; + + const absent = planned.nullable ? "null" : '""'; + const head = + spec.kind === "validator" + ? ` if (typeof ${spec.input.name} !== "string") return false; + + const raw = ${spec.input.name};` + : ` if (value === null || value === undefined) return ${absent}; + + const raw = String(value);`; + + // A pipeline that never sanitizes still needs `digits` in scope for the closing return. + const needsSanitize = !expandPipeline(planned.profile).some((step) => step.op === "sanitize"); + const body = expandPipeline(planned.profile) + .map((step) => renderStep(step, spec, planned)) + .join("\n"); + const tail = tailOf(spec, needsSanitize); + + const options = hasOptions + ? `/** Options of \`${planned.name}\`. */ +export type ${optionsType} = { +${planned.options.map((option) => ` /** ${option === "pad" ? "Left pads the value with zeros up to the pattern's slot count" : "Hides the digits the pattern marks with \\`*\\`"} (default: \`false\`). */\n ${option}?: boolean;`).join("\n")} +}; + +` + : ""; + + return `${options}/** + * ${spec.summary} + * + * Profile: \`${planned.profileName}\` — ${planned.profile.description} + * +${spec.sources.map((source) => ` * @see ${source.role === "official" ? "Official" : "Based on"}: ${source.url}`).join("\n")} + */ +export const ${planned.name} = (${parameter}${optionsParameter}): ${returnType} => { +${head} + +${body}${tail} +}; +`; +}; + +/** + * Emits every file of this target. + * + * @param {Plan} plan - The emission plan. + * @returns {Record} The files, by path relative to the target directory. + */ +export const emit = (plan: Plan): Record => { + const files: Record = { "_spec/runtime.ts": prelude(plan) }; + + for (const planned of plan.functions) { + const imports = new Set(); + const source = renderFunction(planned); + + for (const symbol of [ + "trimBy", + "keepBy", + "matchShape", + "isRepeated", + "applyPattern", + ...plan.charsets.map((charset) => `is${naming.pascal(charset.name)}`), + ...plan.algorithms.map((entry) => `verify${naming.pascal(entry.name)}`), + ]) { + if (new RegExp(`\\b${symbol}\\b`).test(source)) imports.add(symbol); + } + + files[`${planned.module}/${planned.module}.ts`] = + `// Code generated from spec/utilities/${planned.spec.id}.json by spec/codegen. DO NOT EDIT.\nimport {\n${[ + ...imports, + ] + .sort() + .map((symbol) => `\t${symbol},`) + .join("\n")}\n} from "../_spec/runtime.ts";\n\n${source}`; + } + + return files; +}; diff --git a/spec/codegen/vectors.ts b/spec/codegen/vectors.ts new file mode 100644 index 000000000..8fd5b1589 --- /dev/null +++ b/spec/codegen/vectors.ts @@ -0,0 +1,81 @@ +/** + * Builds the conformance vectors: the corpus, plus the output the reference interpreter + * produces for every profile of every utility. + * + * The file is stored column wise (one array per profile, indexed by corpus position) because it + * is meant to be committed and read by six languages, and it records every profile, not only the + * one a given package adopts, so a package that wants to move between profiles can see exactly + * which inputs change answer. + */ +import { writeFileSync } from "node:fs"; +import { resolve } from "node:path"; + +import { buildCorpus } from "./corpus.ts"; +import { type RunOptions, run, setLoader } from "./interpret.ts"; +import { loadAll, loadUtility, specRoot } from "./ir.ts"; + +setLoader(loadUtility); + +export type Vectors = { + corpus: string[]; + utilities: Record< + string, + { + kind: "validator" | "formatter"; + optionSets: RunOptions[]; + /** One entry per corpus input; a formatter entry holds one output per option set. */ + profiles: Record; + } + >; +}; + +const optionSetsFor = (options: string[]): RunOptions[] => { + let sets: RunOptions[] = [{}]; + + for (const option of options) sets = sets.flatMap((set) => [set, { ...set, [option]: true }]); + + return sets; +}; + +export const build = (size: number): Vectors => { + const corpus = buildCorpus(size).slice(0, size); + const utilities: Vectors["utilities"] = {}; + + for (const spec of loadAll()) { + const options = [ + ...new Set(Object.values(spec.adopted).flatMap((adoption) => adoption.options ?? [])), + ]; + const optionSets = spec.kind === "formatter" ? optionSetsFor(options) : [{}]; + const profiles: Vectors["utilities"][string]["profiles"] = {}; + + for (const profile of Object.keys(spec.profiles)) { + profiles[profile] = + spec.kind === "validator" + ? corpus.map((input) => run(spec, profile, input) as boolean) + : corpus.map((input) => + optionSets.map((set) => run(spec, profile, input, set) as string | null), + ); + } + + utilities[spec.id] = { kind: spec.kind, optionSets, profiles }; + } + + return { corpus, utilities }; +}; + +if (process.argv[1]?.endsWith("vectors.ts")) { + const size = Number(process.argv[2] ?? 750); + const vectors = build(size); + const path = resolve(specRoot, "vectors/conformance.json"); + + writeFileSync(path, `${JSON.stringify(vectors)}\n`); + + const checks = Object.values(vectors.utilities).reduce( + (total, utility) => + total + + Object.keys(utility.profiles).length * vectors.corpus.length * utility.optionSets.length, + 0, + ); + + console.log(`wrote ${path} — ${vectors.corpus.length} inputs, ${checks} expectations`); +} diff --git a/spec/conformance/differential-javascript.ts b/spec/conformance/differential-javascript.ts new file mode 100644 index 000000000..49715560d --- /dev/null +++ b/spec/conformance/differential-javascript.ts @@ -0,0 +1,132 @@ +/** + * Differential test between the reference interpreter and the implementation this repository + * actually ships, over the whole corpus. + * + * It answers the only question that matters before any code generation: does the spec describe + * the contract the published package already has, exactly, or a slightly different one? + */ +import { mkdtempSync, rmSync } from "node:fs"; +import { tmpdir } from "node:os"; +import { join, resolve } from "node:path"; + +import { build } from "esbuild"; + +import { buildCorpus } from "../codegen/corpus.ts"; +import { type RunOptions, run, setLoader } from "../codegen/interpret.ts"; +import { loadUtility } from "../codegen/ir.ts"; + +setLoader(loadUtility); + +const root = resolve(import.meta.dirname, "../.."); +const outDir = mkdtempSync(join(tmpdir(), "brutils-diff-")); +const outFile = join(outDir, "bundle.mjs"); + +await build({ + entryPoints: [join(root, "src/index.ts")], + bundle: true, + format: "esm", + platform: "neutral", + outfile: outFile, + logLevel: "error", +}); + +const shipped = (await import(outFile)) as { + isValidCpf: (value: unknown) => boolean; + isValidPis: (value: unknown) => boolean; + formatCpf: (value: unknown, options?: RunOptions) => string; +}; + +const corpus = buildCorpus(); +const isValidCpf = loadUtility("is-valid-cpf"); +const isValidPis = loadUtility("is-valid-pis"); +const formatCpf = loadUtility("format-cpf"); + +type Check = { + utility: string; + input: string; + options?: RunOptions; + spec: unknown; + shipped: unknown; +}; + +const mismatches: Check[] = []; + +/** + * Records a check, keeping it only when the two implementations disagree. + * + * @param {Check} check - What was run and what each side answered. + * @returns {void} + */ +const compare = (check: Check): void => { + if (check.spec !== check.shipped) mismatches.push(check); +}; + +const optionSets: RunOptions[] = [ + {}, + { pad: true }, + { obfuscate: true }, + { pad: true, obfuscate: true }, +]; + +for (const input of corpus) { + compare({ + utility: "isValidCpf", + input, + spec: run(isValidCpf, "masked-strict", input), + shipped: shipped.isValidCpf(input), + }); + compare({ + utility: "isValidPis", + input, + spec: run(isValidPis, "masked-charset", input), + shipped: shipped.isValidPis(input), + }); + + for (const options of optionSets) { + compare({ + utility: "formatCpf", + input, + options, + spec: run(formatCpf, "pattern-partial", input, options), + shipped: shipped.formatCpf(input, options), + }); + } +} + +// Inputs that are not strings at all: the packages promise never to throw on them. +const hostile: unknown[] = [null, undefined, 12_345_678_909, Number.NaN, 0, -1, true, [], {}, 1.5]; + +for (const input of hostile) { + compare({ + utility: "isValidCpf", + input: String(input), + spec: run(isValidCpf, "masked-strict", input), + shipped: shipped.isValidCpf(input), + }); + compare({ + utility: "isValidPis", + input: String(input), + spec: run(isValidPis, "masked-charset", input), + shipped: shipped.isValidPis(input), + }); + compare({ + utility: "formatCpf", + input: String(input), + spec: run(formatCpf, "pattern-partial", input), + shipped: shipped.formatCpf(input), + }); +} + +rmSync(outDir, { recursive: true, force: true }); + +const checks = corpus.length * (2 + optionSets.length) + hostile.length * 3; + +if (mismatches.length > 0) { + console.error(`${mismatches.length} of ${checks} checks disagree with the shipped package:`); + for (const mismatch of mismatches.slice(0, 20)) console.error("", JSON.stringify(mismatch)); + process.exit(1); +} + +console.log( + `spec == shipped JavaScript package on ${checks} checks (${corpus.length} corpus inputs)`, +); diff --git a/spec/conformance/probes/go-probe.go b/spec/conformance/probes/go-probe.go new file mode 100644 index 000000000..981c9e70e --- /dev/null +++ b/spec/conformance/probes/go-probe.go @@ -0,0 +1,40 @@ +// Runs the published Go module against the corpus on stdin, printing the results as JSON. +// +// It is built from a temporary module with a `replace` pointing at the checkout, so it needs +// no network access. +package main + +import ( + "encoding/json" + "os" + + "github.com/brazilian-utils/go/cpf" + "github.com/brazilian-utils/go/pis" +) + +func main() { + var corpus []string + + if err := json.NewDecoder(os.Stdin).Decode(&corpus); err != nil { + panic(err) + } + + results := map[string]any{} + validCpf := make([]bool, len(corpus)) + validPis := make([]bool, len(corpus)) + formatted := make([]string, len(corpus)) + + for index, value := range corpus { + validCpf[index] = cpf.IsValid(value) + validPis[index] = pis.IsValid(value) + formatted[index] = cpf.Format(value) + } + + results["is-valid-cpf"] = validCpf + results["is-valid-pis"] = validPis + results["format-cpf"] = formatted + + if err := json.NewEncoder(os.Stdout).Encode(results); err != nil { + panic(err) + } +} diff --git a/spec/conformance/probes/python-probe.py b/spec/conformance/probes/python-probe.py new file mode 100644 index 000000000..88ae51b35 --- /dev/null +++ b/spec/conformance/probes/python-probe.py @@ -0,0 +1,40 @@ +#!/usr/bin/env python3 +"""Runs the published `brutils` package against the corpus on stdin, one result line per input. + +Usage: python3 python-probe.py + +The modules are loaded by path rather than imported as a package, so the probe does not need +the package's runtime dependencies installed. +""" + +import importlib.util +import json +import sys +from pathlib import Path + + +def load(root: Path, name: str): + spec = importlib.util.spec_from_file_location(f"upstream_{name}", root / "brutils" / f"{name}.py") + module = importlib.util.module_from_spec(spec) + spec.loader.exec_module(module) + return module + + +def main() -> int: + root = Path(sys.argv[1]) + cpf = load(root, "cpf") + pis = load(root, "pis") + corpus = json.load(sys.stdin) + + results = { + "is-valid-cpf": [bool(cpf.is_valid(value)) for value in corpus], + "is-valid-pis": [bool(pis.is_valid(value)) for value in corpus], + "format-cpf": [cpf.format_cpf(value) for value in corpus], + } + + json.dump(results, sys.stdout) + return 0 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/spec/conformance/probes/ruby-probe.rb b/spec/conformance/probes/ruby-probe.rb new file mode 100644 index 000000000..cc3f75ba8 --- /dev/null +++ b/spec/conformance/probes/ruby-probe.rb @@ -0,0 +1,19 @@ +# frozen_string_literal: true + +# Runs the published gem against the corpus on stdin, printing the results as JSON. +# +# Usage: ruby ruby-probe.rb + +require 'json' + +root = ARGV[0] +require File.join(root, 'lib', 'brazilian-utils', 'cpf-utils') +require File.join(root, 'lib', 'brazilian-utils', 'pis-utils') + +corpus = JSON.parse($stdin.read) + +puts JSON.generate( + 'is-valid-cpf' => corpus.map { |value| BrazilianUtils::CPFUtils.valid?(value) }, + 'is-valid-pis' => corpus.map { |value| BrazilianUtils::PISUtils.valid?(value) }, + 'format-cpf' => corpus.map { |value| BrazilianUtils::CPFUtils.format_cpf(value) } +) diff --git a/spec/conformance/probes/rust-probe.rs b/spec/conformance/probes/rust-probe.rs new file mode 100644 index 000000000..d0f9a0dfc --- /dev/null +++ b/spec/conformance/probes/rust-probe.rs @@ -0,0 +1,111 @@ +//! Runs the published crate against the corpus on stdin, printing the results as JSON. +//! +//! Usage: linked against a built `brazilian_utils` rlib, corpus on stdin. + +use std::io::Read; + +fn escape(value: &str) -> String { + let mut out = String::from("\""); + + for char in value.chars() { + match char { + '"' => out.push_str("\\\""), + '\\' => out.push_str("\\\\"), + char if (char as u32) < 0x20 || (char as u32) > 0x7e => { + let code = char as u32; + + if code > 0xffff { + let offset = code - 0x10000; + out.push_str(&format!("\\u{:04x}", 0xd800 + (offset >> 10))); + out.push_str(&format!("\\u{:04x}", 0xdc00 + (offset & 0x3ff))); + } else { + out.push_str(&format!("\\u{:04x}", code)); + } + } + char => out.push(char), + } + } + + out.push('"'); + out +} + +/// A corpus entry is a JSON string literal; this reads them back without a JSON crate. +fn parse_corpus(raw: &str) -> Vec { + let mut values = Vec::new(); + let mut chars = raw.chars().peekable(); + + while let Some(char) = chars.next() { + if char != '"' { + continue; + } + + let mut value = String::new(); + + loop { + match chars.next() { + None | Some('"') => break, + Some('\\') => match chars.next() { + Some('u') => { + let hex: String = (0..4).filter_map(|_| chars.next()).collect(); + let code = u32::from_str_radix(&hex, 16).unwrap_or(0xfffd); + + if (0xd800..0xdc00).contains(&code) { + let mut low = String::new(); + chars.next(); + chars.next(); + for _ in 0..4 { + low.push(chars.next().unwrap_or('0')); + } + let trailing = u32::from_str_radix(&low, 16).unwrap_or(0xfffd); + let combined = 0x10000 + ((code - 0xd800) << 10) + (trailing - 0xdc00); + value.push(char::from_u32(combined).unwrap_or('\u{fffd}')); + } else { + value.push(char::from_u32(code).unwrap_or('\u{fffd}')); + } + } + Some('n') => value.push('\n'), + Some('r') => value.push('\r'), + Some('t') => value.push('\t'), + Some(other) => value.push(other), + None => break, + }, + Some(other) => value.push(other), + } + } + + values.push(value); + } + + values +} + +fn main() { + let mut raw = String::new(); + std::io::stdin().read_to_string(&mut raw).expect("corpus"); + + let corpus = parse_corpus(&raw); + + let valid_cpf: Vec = corpus + .iter() + .map(|value| brazilian_utils::cpf::is_valid(value).to_string()) + .collect(); + let valid_pis: Vec = corpus + .iter() + .map(|value| brazilian_utils::pis::is_valid(value).to_string()) + .collect(); + let formatted: Vec = corpus + .iter() + .map(|value| match brazilian_utils::cpf::format_cpf(value) { + None => "null".to_string(), + Some(text) => escape(&text), + }) + .collect(); + + println!( + "{{\"is-valid-cpf\":[{}],\"is-valid-pis\":[{}],\"format-cpf\":[{}]}}", + valid_cpf.join(","), + valid_pis.join(","), + formatted.join(",") + ); +} diff --git a/spec/conformance/run-all.sh b/spec/conformance/run-all.sh new file mode 100755 index 000000000..b3bf80d5d --- /dev/null +++ b/spec/conformance/run-all.sh @@ -0,0 +1,26 @@ +#!/usr/bin/env bash +# Regenerates every target from the specs and runs its conformance driver. +# +# Usage: bash spec/conformance/run-all.sh +set -euo pipefail + +root="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)" +generated="${root}/spec/generated" +work="$(mktemp -d)" +trap 'rm -rf "${work}"' EXIT + +node "${root}/spec/codegen/vectors.ts" >/dev/null +node "${root}/spec/codegen/emit.ts" >/dev/null + +echo "--- differential against the package this repository ships" +node "${root}/spec/conformance/differential-javascript.ts" + +echo "--- conformance of every generated target" +node "${generated}/typescript/conformance.ts" +python3 "${generated}/python/conformance.py" +ruby "${generated}/ruby/conformance.rb" +(cd "${generated}/go" && go run ./conformance) +rustc --edition 2021 -o "${work}/rust-conformance" "${generated}/rust/conformance.rs" 2>/dev/null +"${work}/rust-conformance" +javac -nowarn -d "${work}/java" "${generated}"/java/*.java +java -cp "${work}/java" Conformance diff --git a/spec/conformance/upstream.ts b/spec/conformance/upstream.ts new file mode 100644 index 000000000..89fb46464 --- /dev/null +++ b/spec/conformance/upstream.ts @@ -0,0 +1,178 @@ +/** + * Checks the specs against the libraries the organisation already publishes. + * + * For every sibling checkout it is pointed at, it runs that package's own functions over the + * corpus and compares the answers with the profile the spec says that package implements. A + * disagreement means the spec is wrong about a shipped contract, which is the only thing that + * could make a generated package a breaking change. + * + * Usage: node spec/conformance/upstream.ts --python ../python --ruby ../ruby --go ../go + */ +import { execFileSync } from "node:child_process"; +import { mkdtempSync, readFileSync, rmSync, writeFileSync } from "node:fs"; +import { tmpdir } from "node:os"; +import { join, resolve } from "node:path"; + +import { loadAll, specRoot } from "../codegen/ir.ts"; +import { type Vectors } from "../codegen/vectors.ts"; + +type ProbeResults = Record; + +const vectors = JSON.parse( + readFileSync(resolve(specRoot, "vectors/conformance.json"), "utf8"), +) as Vectors; + +const specs = loadAll(); +const corpus = JSON.stringify(vectors.corpus); +const probes = resolve(import.meta.dirname, "probes"); + +const args = process.argv.slice(2); +const checkouts = new Map(); + +for (let index = 0; index < args.length; index += 2) { + if (!args[index].startsWith("--")) throw new Error(`unexpected argument: ${args[index]}`); + + checkouts.set(args[index].slice(2), resolve(args[index + 1])); +} + +const runProbe = (language: string, checkout: string): ProbeResults => { + switch (language) { + case "python": { + return JSON.parse( + execFileSync("python3", [join(probes, "python-probe.py"), checkout], { + input: corpus, + encoding: "utf8", + maxBuffer: 64 * 1024 * 1024, + }), + ) as ProbeResults; + } + case "ruby": { + return JSON.parse( + execFileSync("ruby", [join(probes, "ruby-probe.rb"), checkout], { + input: corpus, + encoding: "utf8", + maxBuffer: 64 * 1024 * 1024, + }), + ) as ProbeResults; + } + case "go": { + const work = mkdtempSync(join(tmpdir(), "brutils-go-probe-")); + + writeFileSync( + join(work, "go.mod"), + `module brutilsprobe\n\ngo 1.23\n\nrequire github.com/brazilian-utils/go v0.0.0\n\nreplace github.com/brazilian-utils/go => ${checkout}\n`, + ); + writeFileSync(join(work, "main.go"), readFileSync(join(probes, "go-probe.go"), "utf8")); + + const output = execFileSync("go", ["run", "."], { + cwd: work, + input: corpus, + encoding: "utf8", + env: { ...process.env, GOFLAGS: "-mod=mod" }, + maxBuffer: 64 * 1024 * 1024, + }); + + rmSync(work, { recursive: true, force: true }); + + return JSON.parse(output) as ProbeResults; + } + case "rust": { + const work = mkdtempSync(join(tmpdir(), "brutils-rust-probe-")); + + execFileSync( + "rustc", + [ + "--edition", + "2021", + "-o", + join(work, "probe"), + join(probes, "rust-probe.rs"), + "--extern", + `brazilian_utils=${join(checkout, "target/debug/libbrazilian_utils.rlib")}`, + "-L", + join(checkout, "target/debug/deps"), + ], + { encoding: "utf8" }, + ); + + const output = execFileSync(join(work, "probe"), [], { + input: corpus, + encoding: "utf8", + maxBuffer: 64 * 1024 * 1024, + }); + + rmSync(work, { recursive: true, force: true }); + + return JSON.parse(output) as ProbeResults; + } + default: { + throw new Error(`no probe for ${language}`); + } + } +}; + +let disagreements = 0; + +for (const [language, checkout] of checkouts) { + console.log(`\n${language} — ${checkout}`); + + let results: ProbeResults; + + try { + results = runProbe(language, checkout); + } catch (error) { + console.log( + ` probe failed: ${error instanceof Error ? error.message.split("\n")[0] : String(error)}`, + ); + continue; + } + + for (const spec of specs) { + const adoption = spec.adopted[language]; + const observed = results[spec.id]; + + if (adoption === undefined || observed === undefined) continue; + + const utility = vectors.utilities[spec.id]; + const expectedColumn = utility.profiles[adoption.profile]; + const expected = + spec.kind === "validator" + ? (expectedColumn as boolean[]) + : (expectedColumn as (string | null)[][]).map((outputs) => outputs[0]); + + const known = new Set( + (adoption.knownDeviations ?? []).flatMap((deviation) => deviation.inputs), + ); + const mismatches: { input: string; expected: unknown; observed: unknown }[] = []; + let deviations = 0; + + for (const [index, input] of vectors.corpus.entries()) { + if (observed[index] === expected[index]) continue; + + if (known.has(input)) { + deviations++; + continue; + } + + mismatches.push({ input, expected: expected[index], observed: observed[index] }); + } + + disagreements += mismatches.length; + + const note = deviations > 0 ? ` (+${deviations} known deviation(s))` : ""; + const verdict = + mismatches.length === 0 + ? `agrees on ${vectors.corpus.length - deviations}/${vectors.corpus.length}${note}` + : `DIFFERS on ${mismatches.length}/${vectors.corpus.length}${note}`; + + console.log(` ${spec.id.padEnd(14)} profile ${adoption.profile.padEnd(17)} ${verdict}`); + + for (const mismatch of mismatches.slice(0, 5)) { + console.log( + ` input=${JSON.stringify(mismatch.input)} spec=${JSON.stringify(mismatch.expected)} package=${JSON.stringify(mismatch.observed)}`, + ); + } + } +} + +console.log(`\n${disagreements} disagreement(s) with the published packages`); diff --git a/spec/schema/charsets.json b/spec/schema/charsets.json new file mode 100644 index 000000000..518863bee --- /dev/null +++ b/spec/schema/charsets.json @@ -0,0 +1,39 @@ +{ + "$comment": "Character sets referenced by the utility specs, written out as explicit code points. Regex shorthands are deliberately avoided: `\\s` means 6 ASCII characters in Go and Ruby, the 25 code points below in JavaScript, and a Unicode property in Python and the Rust regex crate, so a spec that shipped a regex literal would not describe one behaviour. `\\d` diverges the same way (Python's `\\d` matches Devanagari digits with `re.UNICODE`).", + "charsets": { + "ascii-digits": { + "description": "The 10 ASCII digits. This is what every Brazilian document number is made of.", + "ranges": [["0030", "0039"]] + }, + "js-whitespace": { + "description": "The code points JavaScript's String.prototype.trim() strips and its regex `\\s` matches: WhiteSpace plus LineTerminator plus U+FEFF.", + "codePoints": [ + "0009", + "000A", + "000B", + "000C", + "000D", + "0020", + "00A0", + "1680", + "2028", + "2029", + "202F", + "205F", + "3000", + "FEFF" + ], + "ranges": [["2000", "200A"]] + }, + "mask-cpf": { + "description": "Separators accepted between the digit groups of a CPF.", + "codePoints": ["002E", "002D", "002F"], + "include": ["js-whitespace"] + }, + "mask-pis": { + "description": "Separators accepted anywhere in a PIS/NIS.", + "codePoints": ["002E", "002D", "002F", "0028", "0029", "002C", "002A"], + "include": ["js-whitespace"] + } + } +} diff --git a/spec/schema/check-digits.json b/spec/schema/check-digits.json new file mode 100644 index 000000000..067459331 --- /dev/null +++ b/spec/schema/check-digits.json @@ -0,0 +1,25 @@ +{ + "$comment": "Check digit algorithms referenced by the utility specs. Every Brazilian document number in the library is a weighted modulus sum, so the algorithms are described as data rather than reimplemented per utility.", + "algorithms": { + "cpf": { + "description": "Modulus 11 over the base, weights running from base length + 1 down to 2, repeated cumulatively for each check digit: the second digit is computed over the base plus the first one.", + "modulus": 11, + "weights": { "kind": "descending", "from": "length+1", "to": 2 }, + "reduce": "modulus-minus-remainder", + "clamp": { "atLeast": 10, "to": 0 }, + "positions": [9, 10], + "cumulative": true, + "source": "https://normas.receita.fazenda.gov.br/sijut2consulta/link.action?idAto=151372" + }, + "pis": { + "description": "Modulus 11 over the 10 base digits with the fixed weight vector 3 2 9 8 7 6 5 4 3 2.", + "modulus": 11, + "weights": { "kind": "fixed", "values": [3, 2, 9, 8, 7, 6, 5, 4, 3, 2] }, + "reduce": "modulus-minus-remainder", + "clamp": { "atLeast": 10, "to": 0 }, + "positions": [10], + "cumulative": false, + "source": "https://www.sirc.gov.br/wp-content/uploads/manual_sirc_recomendacoes_tecnicas_v7.pdf" + } + } +} diff --git a/spec/schema/utility.schema.json b/spec/schema/utility.schema.json new file mode 100644 index 000000000..4a192cc2f --- /dev/null +++ b/spec/schema/utility.schema.json @@ -0,0 +1,237 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://brazilian-utils.com.br/spec/schema/utility.schema.json", + "title": "Brazilian Utils utility specification", + "description": "A language neutral description of one utility: what it accepts, what it answers, and which of its behaviours each package implements today.", + "type": "object", + "required": [ + "id", + "kind", + "summary", + "sources", + "names", + "input", + "output", + "adopted", + "profiles" + ], + "additionalProperties": false, + "properties": { + "$schema": { "type": "string" }, + "id": { + "type": "string", + "pattern": "^[a-z0-9]+(-[a-z0-9]+)*$", + "description": "The utility id, in kebab-case, which is also the file name." + }, + "kind": { + "enum": ["validator", "formatter"], + "description": "Validators answer a boolean; formatters answer a string or the absent value." + }, + "summary": { "type": "string" }, + "sources": { + "type": "array", + "minItems": 1, + "items": { + "type": "object", + "required": ["role", "url"], + "additionalProperties": false, + "properties": { + "role": { + "enum": ["official", "based-on"], + "description": "`official` is a law, regulator, standard body or government dataset; `based-on` is a third party implementation or mirror the code relied on." + }, + "url": { "type": "string", "format": "uri" } + } + } + }, + "names": { + "type": "object", + "description": "What each package calls this utility. The generator never invents a name: it emits the one that package already publishes.", + "additionalProperties": { + "type": "object", + "required": ["module", "function"], + "additionalProperties": false, + "properties": { + "module": { "type": "string" }, + "function": { "type": "string" } + } + } + }, + "input": { + "type": "object", + "required": ["name", "type"], + "additionalProperties": false, + "properties": { + "name": { "type": "string" }, + "type": { "type": "string" }, + "onWrongType": { "enum": ["false"] }, + "onNullish": { "enum": ["empty-string", "null"] } + } + }, + "output": { + "type": "object", + "required": ["type"], + "additionalProperties": false, + "properties": { "type": { "enum": ["boolean", "string"] } } + }, + "adopted": { + "type": "object", + "description": "Which profile each package implements today, and where it is known to differ from it.", + "additionalProperties": { + "type": "object", + "required": ["profile"], + "additionalProperties": false, + "properties": { + "profile": { "type": "string" }, + "options": { "type": "array", "items": { "type": "string" } }, + "knownDeviations": { + "type": "array", + "items": { + "type": "object", + "required": ["inputs", "reason"], + "additionalProperties": false, + "properties": { + "inputs": { "type": "array", "items": { "type": "string" } }, + "reason": { "type": "string" }, + "issue": { "type": "string", "format": "uri" } + } + } + } + } + } + }, + "profiles": { + "type": "object", + "description": "The named behaviours of this utility. A profile is a contract: two packages on the same profile answer identically on every input.", + "minProperties": 1, + "additionalProperties": { + "type": "object", + "required": ["description", "pipeline"], + "additionalProperties": false, + "properties": { + "description": { "type": "string" }, + "absent": { + "enum": ["empty-string", "null"], + "description": "What a formatter answers when it has nothing to format." + }, + "options": { + "type": "array", + "items": { + "type": "object", + "required": ["name", "type", "default", "read"], + "additionalProperties": false, + "properties": { + "name": { "type": "string" }, + "type": { "const": "boolean" }, + "default": { "type": "boolean" }, + "read": { "enum": ["truthy", "strict"] } + } + } + }, + "pipeline": { + "type": "array", + "minItems": 1, + "items": { "$ref": "#/$defs/step" } + } + } + } + } + }, + "$defs": { + "step": { + "oneOf": [ + { + "type": "object", + "description": "The whole value, optionally trimmed, has to be the given digit groups, separated only by the given charset.", + "required": ["op", "target", "groups"], + "additionalProperties": false, + "properties": { + "op": { "const": "guard-shape" }, + "target": { "const": "raw" }, + "trim": { "type": "string" }, + "groups": { "type": "array", "items": { "type": "integer", "minimum": 1 } }, + "separators": { "type": "string" } + } + }, + { + "type": "object", + "description": "Every character of the raw input has to belong to the union of the given charsets.", + "required": ["op", "target", "allow"], + "additionalProperties": false, + "properties": { + "op": { "const": "guard-charset" }, + "target": { "const": "raw" }, + "allow": { "type": "array", "items": { "type": "string" } } + } + }, + { + "type": "object", + "required": ["op", "keep", "into"], + "additionalProperties": false, + "properties": { + "op": { "const": "sanitize" }, + "keep": { "type": "string" }, + "into": { "const": "digits" } + } + }, + { + "type": "object", + "required": ["op", "target", "equals"], + "additionalProperties": false, + "properties": { + "op": { "const": "guard-length" }, + "target": { "const": "digits" }, + "equals": { "type": "integer", "minimum": 1 } + } + }, + { + "type": "object", + "description": "Rejects a run of one repeated digit, such as \"00000000000\".", + "required": ["op", "target"], + "additionalProperties": false, + "properties": { + "op": { "const": "guard-repeated" }, + "target": { "const": "digits" } + } + }, + { + "type": "object", + "required": ["op", "target", "checkDigit"], + "additionalProperties": false, + "properties": { + "op": { "const": "verify-check-digits" }, + "target": { "const": "digits" }, + "checkDigit": { + "type": "string", + "description": "An algorithm declared in spec/schema/check-digits.json." + } + } + }, + { + "type": "object", + "description": "Requires another utility to accept the same input, under a named profile.", + "required": ["op", "utility", "profile"], + "additionalProperties": false, + "properties": { + "op": { "const": "guard-valid" }, + "utility": { "type": "string" }, + "profile": { "type": "string" } + } + }, + { + "type": "object", + "description": "Lays the digits over a pattern: `0` copies a character, `*` hides one, anything else separates.", + "required": ["op", "target", "engine", "pattern"], + "additionalProperties": false, + "properties": { + "op": { "const": "apply-pattern" }, + "target": { "const": "digits" }, + "engine": { "const": "pattern-v1" }, + "pattern": { "type": "string" }, + "variants": { "type": "object", "additionalProperties": { "type": "string" } } + } + } + ] + } + } +} diff --git a/spec/utilities.json b/spec/utilities.json new file mode 100644 index 000000000..8d68f0cc0 --- /dev/null +++ b/spec/utilities.json @@ -0,0 +1,4 @@ +{ + "$comment": "The utilities covered by the specification, in the order the emitters lay them out.", + "utilities": ["is-valid-cpf", "is-valid-pis", "format-cpf"] +} diff --git a/spec/utilities/format-cpf.json b/spec/utilities/format-cpf.json new file mode 100644 index 000000000..6086a17c2 --- /dev/null +++ b/spec/utilities/format-cpf.json @@ -0,0 +1,134 @@ +{ + "$schema": "../schema/utility.schema.json", + "id": "format-cpf", + "kind": "formatter", + "summary": "Formats a CPF value as \"000.000.000-00\".", + "sources": [ + { + "role": "official", + "url": "https://www.gov.br/receitafederal/pt-br/assuntos/meu-cpf" + } + ], + "names": { + "typescript": { + "module": "format-cpf", + "function": "formatCpf" + }, + "python": { + "module": "brutils.cpf", + "function": "format_cpf" + }, + "go": { + "module": "cpf", + "function": "Format" + }, + "ruby": { + "module": "BrazilianUtils::CPFUtils", + "function": "format_cpf" + }, + "rust": { + "module": "cpf", + "function": "format_cpf" + }, + "java": { + "module": "Cpf", + "function": "format" + } + }, + "input": { + "name": "value", + "type": "string|number", + "onNullish": "empty-string" + }, + "output": { + "type": "string" + }, + "adopted": { + "typescript": { + "profile": "pattern-partial", + "options": ["pad", "obfuscate"] + }, + "go": { + "profile": "pattern-partial", + "options": [] + }, + "java": { + "profile": "pattern-partial", + "options": ["pad", "obfuscate"] + }, + "python": { + "profile": "strict-or-null", + "knownDeviations": [ + { + "inputs": ["12345678909", "١٢٣٤٥٦٧٨٩٠٩"], + "reason": "format_cpf delegates to is_valid, so it inherits the Unicode digit deviation and returns a CPF formatted in non ASCII digits." + } + ] + }, + "ruby": { + "profile": "strict-or-null" + }, + "rust": { + "profile": "strict-or-null" + } + }, + "profiles": { + "pattern-partial": { + "description": "Sanitizes to digits and lays them over the pattern, emitting a separator only while digits are left, so a short value formats to a partial mask instead of failing.", + "absent": "empty-string", + "pipeline": [ + { + "op": "sanitize", + "keep": "ascii-digits", + "into": "digits" + }, + { + "op": "apply-pattern", + "target": "digits", + "engine": "pattern-v1", + "pattern": "000.000.000-00", + "variants": { + "obfuscate": "***.000.000-**" + } + } + ], + "options": [ + { + "name": "pad", + "type": "boolean", + "default": false, + "read": "truthy" + }, + { + "name": "obfuscate", + "type": "boolean", + "default": false, + "read": "truthy" + } + ] + }, + "strict-or-null": { + "description": "Returns the empty value unless the input is already a valid CPF. Implemented by the Python, Ruby and Rust packages, which return None/nil.", + "absent": "null", + "pipeline": [ + { + "op": "guard-valid", + "utility": "is-valid-cpf", + "profile": "digits-only" + }, + { + "op": "sanitize", + "keep": "ascii-digits", + "into": "digits" + }, + { + "op": "apply-pattern", + "target": "digits", + "engine": "pattern-v1", + "pattern": "000.000.000-00" + } + ], + "options": [] + } + } +} diff --git a/spec/utilities/is-valid-cpf.json b/spec/utilities/is-valid-cpf.json new file mode 100644 index 000000000..10a77d72a --- /dev/null +++ b/spec/utilities/is-valid-cpf.json @@ -0,0 +1,155 @@ +{ + "$schema": "../schema/utility.schema.json", + "id": "is-valid-cpf", + "kind": "validator", + "summary": "Validates a CPF (Cadastro de Pessoas Físicas) number.", + "sources": [ + { + "role": "official", + "url": "https://www.gov.br/receitafederal/pt-br/assuntos/meu-cpf" + }, + { + "role": "official", + "url": "https://normas.receita.fazenda.gov.br/sijut2consulta/link.action?idAto=151372" + } + ], + "names": { + "typescript": { + "module": "is-valid-cpf", + "function": "isValidCpf" + }, + "python": { + "module": "brutils.cpf", + "function": "is_valid" + }, + "go": { + "module": "cpf", + "function": "IsValid" + }, + "ruby": { + "module": "BrazilianUtils::CPFUtils", + "function": "valid?" + }, + "rust": { + "module": "cpf", + "function": "is_valid" + }, + "java": { + "module": "Cpf", + "function": "isValid" + } + }, + "input": { + "name": "cpf", + "type": "string", + "onWrongType": "false" + }, + "output": { + "type": "boolean" + }, + "adopted": { + "typescript": { + "profile": "masked-strict" + }, + "python": { + "profile": "digits-only", + "knownDeviations": [ + { + "inputs": ["12345678909", "١٢٣٤٥٦٧٨٩٠٩"], + "reason": "brutils/cpf.py gates on str.isdigit(), which is Unicode aware, so a CPF written in full width or Arabic-Indic digits validates. The profile is ASCII only." + } + ] + }, + "ruby": { + "profile": "digits-only" + }, + "rust": { + "profile": "digits-only" + }, + "erlang": { + "profile": "digits-only" + }, + "go": { + "profile": "digits-extracted" + }, + "java": { + "profile": "masked-strict" + } + }, + "profiles": { + "masked-strict": { + "description": "Accepts the usual mask characters and whitespace around and between the digit groups, and rejects every other shape. Implemented by the JavaScript package.", + "pipeline": [ + { + "op": "guard-shape", + "target": "raw", + "trim": "js-whitespace", + "groups": [3, 3, 3, 2], + "separators": "mask-cpf" + }, + { + "op": "sanitize", + "keep": "ascii-digits", + "into": "digits" + }, + { + "op": "guard-repeated", + "target": "digits" + }, + { + "op": "verify-check-digits", + "target": "digits", + "checkDigit": "cpf" + } + ] + }, + "digits-only": { + "description": "Accepts exactly 11 ASCII digits and nothing else. Implemented by the Python, Ruby, Rust and Erlang packages.", + "pipeline": [ + { + "op": "guard-shape", + "target": "raw", + "groups": [11] + }, + { + "op": "sanitize", + "keep": "ascii-digits", + "into": "digits" + }, + { + "op": "guard-repeated", + "target": "digits" + }, + { + "op": "verify-check-digits", + "target": "digits", + "checkDigit": "cpf" + } + ] + }, + "digits-extracted": { + "description": "Drops every non-digit character wherever it appears and validates what is left, so \"abc12345678909\" is accepted. Implemented by the Go package.", + "pipeline": [ + { + "op": "sanitize", + "keep": "ascii-digits", + "into": "digits" + }, + { + "op": "guard-length", + "target": "digits", + "equals": 11 + }, + { + "op": "guard-repeated", + "target": "digits" + }, + { + "op": "verify-check-digits", + "target": "digits", + "checkDigit": "cpf" + } + ] + } + } +} diff --git a/spec/utilities/is-valid-pis.json b/spec/utilities/is-valid-pis.json new file mode 100644 index 000000000..797f97bc1 --- /dev/null +++ b/spec/utilities/is-valid-pis.json @@ -0,0 +1,127 @@ +{ + "$schema": "../schema/utility.schema.json", + "id": "is-valid-pis", + "kind": "validator", + "summary": "Validates a PIS/PASEP/NIS number.", + "sources": [ + { + "role": "official", + "url": "https://www.gov.br/inss/pt-br/direitos-e-deveres/inscricao-e-contribuicao/inscricao" + }, + { + "role": "based-on", + "url": "https://github.com/brazilian-utils/python/blob/main/brutils/pis.py" + } + ], + "names": { + "typescript": { + "module": "is-valid-pis", + "function": "isValidPis" + }, + "python": { + "module": "brutils.pis", + "function": "is_valid" + }, + "go": { + "module": "pis", + "function": "IsValid" + }, + "ruby": { + "module": "BrazilianUtils::PISUtils", + "function": "valid?" + }, + "rust": { + "module": "pis", + "function": "is_valid" + }, + "java": { + "module": "Pis", + "function": "isValid" + } + }, + "input": { + "name": "pis", + "type": "string", + "onWrongType": "false" + }, + "output": { + "type": "boolean" + }, + "adopted": { + "typescript": { + "profile": "masked-charset" + }, + "java": { + "profile": "masked-charset" + }, + "python": { + "profile": "digits-only-lenient", + "knownDeviations": [ + { + "inputs": ["12345678909", "١٢٣٤٥٦٧٨٩٠٩"], + "reason": "brutils/pis.py gates on str.isdigit(), which is Unicode aware, so full width and Arabic-Indic digits are accepted as a PIS and int() then reads them. The profile is ASCII only." + } + ] + }, + "go": { + "profile": "digits-only-lenient" + }, + "ruby": { + "profile": "digits-only-lenient" + }, + "rust": { + "profile": "digits-only-lenient" + } + }, + "profiles": { + "masked-charset": { + "description": "Accepts mask characters and whitespace anywhere, rejects every other character, then validates the 11 digits left.", + "pipeline": [ + { + "op": "guard-charset", + "target": "raw", + "allow": ["ascii-digits", "mask-pis"] + }, + { + "op": "sanitize", + "keep": "ascii-digits", + "into": "digits" + }, + { + "op": "guard-length", + "target": "digits", + "equals": 11 + }, + { + "op": "guard-repeated", + "target": "digits" + }, + { + "op": "verify-check-digits", + "target": "digits", + "checkDigit": "pis" + } + ] + }, + "digits-only-lenient": { + "description": "Accepts exactly 11 ASCII digits, rejects every mask character, and does not reject a repeated digit run, so \"00000000000\" validates. Implemented by the Python, Go and Ruby packages.", + "pipeline": [ + { + "op": "guard-shape", + "target": "raw", + "groups": [11] + }, + { + "op": "sanitize", + "keep": "ascii-digits", + "into": "digits" + }, + { + "op": "verify-check-digits", + "target": "digits", + "checkDigit": "pis" + } + ] + } + } +} diff --git a/spec/vectors/conformance.json b/spec/vectors/conformance.json new file mode 100644 index 000000000..960998606 --- /dev/null +++ b/spec/vectors/conformance.json @@ -0,0 +1 @@ +{"corpus":[""," ","0","00000000000","11111111111","99999999999","12345678909","123.456.789-09","123 456 789 09"," 12345678909 ","123.456.789.09","123/456/789/09","123-456-789-09","123..456..789--09",".12345678909","12345678909.","1234567890","123456789090","abc12345678909","12345678909abc","1a2345678909","12345678900"," 12345678909 "," 123.456.789-09
","12345678909","123 456 789 09","123\t456\n789\r09","🇧🇷12345678909","12345678909🇧🇷","12345678909","١٢٣٤٥٦٧٨٩٠٩","12056874107","120.56874.10-7","120/56874/10-7","120(56874)10,7","120*56874*10-7","12056874108","1205687410","120.56874.10-7 ","120#56874#10#7","74275733568","69264259294","27502677658","9.5167.3","45528746248","00192591070","2423/3.79a967a0","04349316248","05828033735","*340*)6","01018054771","45960967839","72953559375","350#6#7 633717","85752788760","12201461035","65623597327","08216262647","94291497253","65546678658","02218010658","13434608915","60021596917","99266321688","036/6694a2431","29022796396","659037# ","610954584)85,","57.364183-296","72468124605","01366021578","37242507700","6.5968)418a486","64629394234","89884,197702","588519 7)4/661","06733963710","16153416609","973194*6,5520-","83438658534","48938105458","52070564410","37299492850","97116501347","267a783 45665","7*15653/41811","193a0007658a5","32605779807","81887191706","60150247125","71770889540","38306173004","63 568062866","13765631345","96840834266","875 6a6256601","17)06**05","#478089(3220","977/03000(","660(29a924818","25368103999","15050757707",")49 354 55","23609640126","7587)8147440.","95291932024","32711721370","25#8163547 95","707612.87664.","40110965809","-54)9","62501783555","3855)352323","00158379099","2(1062574","#63(67406","94622089211","85947269915","86/98247","30953452751","5554204406-9","87821425957","10359723012","38589626369","17091421971","649982-92,8,306","*737925","51723668907","0,353077501","1381-9#642420","29972448622","89/-60/84210273","1425.6372500","55427359071","63876408903","106a","53367895857","500978,20993","32498856498","36558846217","26147599291",".(1.9*24*","75660210933","93971033695","52200090253","38476272600","378447344/33","069263407*#51","59139466850","6(87953,3-8570","87373238138","95 1","641350042 5(3","40910963010","268067 8#237*8","83723418503","758131(6","20240907137","33520141268","17938","10213407217","66738397299","45-92166 57(41","05466916770","62762266910","84911262958","81826425290","89205985252","05496053471","52597393372","38652220565","17-89993365275","22279047551","15481647740","54130082795","23442185571","90 500080904","84264259522","58976801750","20648740625","57342147291","8","06787915480","74994999791","308351266,0 0","33664446341","72084287028","62610395930","39083(594068","29462 99449a8","87862097741","148965/24500 ","4549302,4182(","43955822983","49545440333","00838712551","5693995*7#12/0","79/467634503","90117760952","6","450262548(83","71733485502","59920913563","14079680171","067*37*782012","7683735755,1 ","43855708339","26273937561","66846268596","8433,56 40/307","12710973626","60805222300","36453716769","80716189538","96875115166","74336944841","31092397361","16348172139","38146986579","24144680090","35818.63-9282","(0","50373463200","7a6a61220#1053","55023a198.0,(","3857,8,49895)0","84785977515","34957107592","90534660967","2183836)15","1)8813929374(","25625090603","1-4","67817905635","45185817500","62591997515","94866406005","48986981319","48a1)896956(215","12847371605","02712781880*","50590677201","1130)86*12109","85452922541","1657*89388a2-7","06054396416","94680920548","69605029960","64060368330","79870297338","71327360357","06833761241","31953017104","21881139070","03621090/1#28 ","08845801875","66081 17 838.0","(991 59(36720","19929703942","65134983178","56127159482","13905674709","35487816369","01104612585","49147868907","8175837 988(5","1958*2603944","12857330375","39510339750-","57878124270","06770932311","29395616890","50413890.635","3","54711981085","27704704850-","46757073297","3*9#18786a8,113a","8.22,2*,(#","09624157970","20862681019","65845806283","78155325511","91246524902","85037722440","06072829910","19006621385","91822082633","284003-7)6293/","24584648158","81765431668","90125/01,2535","42430498944","28,72040882a2","4674150#3016","a58,","35738654593","49571112270","70116455780","70494#544/864/","63108583352","51832068939","99665590359","3237#5","871 20910493","6 7706696502#","74910*321292","58825236983","91665897113","22473672220","50333a031555","39376825044","16326834334","3/1854069798","86676398427","10a47#83","07203160435","7","54041828147","81939232511","033789.079#08#","7(20 613.","36081312203","14827445113","90094962103","89393206850","37845084553","775-319793 91","3359490 5 098","80531386406","57)406681,15/1","91(231287551,","415","62#067,930(891","44090285141","67489979412","11680919695","32*9#34)167801","29927535309","68816320370","32745256439","49593127933","77791117843","491(378(84506","097a 9)4741-","932.23243/178","28295821005","33212344679","77762041370","95373510416","6/4489153627","42794672014","93206839807","40428139980","27002753061","16041909891","5(939a954561)0","0438-1899814","6806703/6748","76083838506","46508664646","64204832671","03584949823","82976574340","7,2135151017","12435077094","9977(00041 98-","388993*87 958,","699367.6777/27)","91553048220","82674809787","32782781600","1302581(","301/41926580a","99064778258","824 460621 8","70140751009","79774925122","45294338971","67715677884","10*3(6158 65,90*","22115679341","02040884623","8/6956026238","88142588117","45716895786","3516340448 0a","92995777499","17710007188","35*87#17#48781","25570295610","04046*885075","73144445606","75086a8#8058/0","03670355555","-/ 02","a 434 ","59728943107","4080.3088256","#37 0","57049460387","42024527209","50224587436","33689976456","6.3.23-9(8 67877","03014108448","30173549871","53945248343","53416681118","724-49978844","45277444106","40086262556","55205/ 1(*1","54712598077","11228014a340","19984710807","87024275839","40033410231","13026104140","93439798607 ","79547137921","06586026164","30648422267","7473,2299822","78751559404","77371587199","23201372770","48 5(28827259","63098235590","44-68 1014079","4472640","18192199177","36726974559","78164817058","863758171(71","57024472704","02824308596","a252) 5","49487942440","39","01605660652","98460899292","3104897*8753","4(133807a2206","99292011308","63031473936","38076757950","05679802430","63341026362","66,5382991","30414950070","32)-#4611403*","42123780522","06236152#571","82153578817","36045129267","099(987(52343","58536818859","66540536264","45787969065","#,4236","42050173679","8569207-83(25","56(13630","03855805687","31793#036977#","92826784218","991361901*79","3*3647161)202 ","0474552)#5","654(592183 65","70389666858","62488480096","66.59-467 823)0","4#50,.0a21061,8","765801 2*2382","66122001201","26826010305","57142385151","5.35748724#4)3(","47236219541","40549687670","90141629369","70223(9 8674 7","90334100011","04518514970","9354470436 3","7 63)8680#1202.","86305661512","53111178501","35772104276","489(51911098*","19901091446","63013612798","71914656529","44617654747","96491193969","a615,,41","95805869707","29901346205","54208519975","875)53-6*81295","36988108217","5 354 19 4","4/5 3175.172 0,1","67755270160","92879818","98966060521","98114#524)235","6-2 9","77237 56004","64548712588","89499697768","64807531071","4.15*52615#960","029 0*7472598","61447588640","462 86624449","28997279157","9 2769#78 44)0*","12418027879","00576059- 4#.","83871787884","18629180668","625,765938 7(7","68675256998","62682278159","05376651371","15624641471(","55397368261","94697679827","59343010710","96988797300","68741541090","81545791201","06430204977","65078757406","95113422*195","28644466375","-63(,3698","09323157444","53234099691 ","014371442/4*9 ","29715289932","18166 728#150","2)7 6*35541370-","94622736349","30086393632","99920183642","176844)10300","72720)70-4909","0829064a1095","73165138013","21723780626","82760984438","08552756887","56267985520","62062059424","14353708309","20197616968","90970500734","31979867452","667.8133927 3","55494164179","13/73 9728530","22015806008","56825397664",")6 *6(0a146","31,43)2597604","90771312563","29389912075","381997951)31","52 62273.13)","90700384987","05621956966","7748169522","23813064123","78305022501","25623.074294","4132057/7202","71536439312","95498010125","(727,6.4.","21509606726","043397/52460","00346424712","37585164478","74.700668660*","66312087344","96883873367","61955334460","018549.08828","47772633149","01397607840","11/556669682","41826165886","2780148195 0","84674429137","94317787811","506237 79133","40584847998","44943496302","0 32,91#06 ","95196278559","92601882450","50015512407","106/38726082","901#/903678355","21117259856","25882595967","04732383491","9479969 9","95922669800","8883/06156)0*9","32850130796","77974150892","29659535186","49// ","15790872976","58260669897","91329809105","5677103 1950,","14398251227","25824296210","56314621844","94876813277","16263660120","700717*6(2167","684-0502763","15424949790","8-1#91536(69","25371491907","75532925688","34493470550","70651413020","641863190#06/","36238066631","87766231879","78507200168,","97540086980","69426575595","717 0#540339a5","40057456622","16215778052","90760673330","21056750189","64853010206","95 9)760100-00","90259943428","46625500798","98-845045580","42861538430","71521538336","637a","65411877890","2)0224658756","83660227226","41096624424","2 0199552290","43290951901","91037243784","45426209985","39704032862","64763559532","906 33(7251)53","69805193291","04785557086","49612588732","7 )9","6613898473(0","55557336505","75932776234","35734160636","68367455505","43599874434","11981522551","46538105958","45249186411","77458313465","0a0798#895659","7700.4133267",".4-#2/.*-#2*878","461,7","0638673669","7739)5204468","13419417870","30688657217","43076045033","45420468862","47713594587","98299994147","47274872842","10279.099a30)4","63735745800","96010762314","43223170146","90732490086","81106510790","36902649001","36133763930","95524229907","60486932303","48622599876","38354488462","10*237294,664","462605-225,52","82118110709","25424062431","57411529370","49640340787","6245*598(990-9-","08)840/48606","67214459051","86730859433","41922980072","573/830(43308","01504672760","63298685954","09900425375","66694/5(79109","04257613203","27662001321","45617675848","31286558395","60 78 1073417","13782269179","46201891549","72380631544","1.0664386129","51796846302","28075951700","09651265523","76","10229235 794","92605156966","79693025163","24247486918","250*5.","34663768580","03086608463","39378025846","2(718063-2428","80(96a)649936"],"utilities":{"is-valid-cpf":{"kind":"validator","optionSets":[{}],"profiles":{"masked-strict":[false,false,false,false,false,false,true,true,true,true,true,true,true,true,false,false,false,false,false,false,false,false,true,true,true,true,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true,false,true,true,false,true,true,false,false,true,false,false,false,false,true,true,true,true,true,true,false,false,false,true,false,false,false,false,false,false,false,false,false,false,true,false,false,false,true,true,false,true,false,false,false,true,false,true,true,false,false,true,false,false,false,false,false,false,true,false,false,false,false,false,true,false,false,true,false,false,false,false,false,false,true,false,false,true,false,false,true,false,false,false,false,true,false,false,true,false,false,false,true,false,true,false,true,true,true,false,false,true,false,true,false,false,true,false,false,false,false,true,false,true,false,false,false,false,false,false,false,false,false,true,false,true,true,true,true,false,true,false,true,false,false,false,true,true,false,false,false,true,false,false,false,true,false,false,false,true,false,false,true,false,false,false,false,false,false,false,false,true,false,false,true,false,true,false,true,false,false,false,true,false,true,false,true,false,false,false,true,false,false,false,true,false,true,false,false,false,false,false,true,false,false,true,false,true,false,false,false,false,false,false,true,false,false,false,true,false,false,false,false,false,false,false,true,true,false,false,false,true,false,false,false,true,false,false,false,false,false,false,false,false,false,false,false,false,false,true,false,true,false,true,false,true,false,true,false,false,false,false,false,false,false,false,true,false,true,false,true,false,true,false,false,false,false,false,false,false,false,false,true,false,false,false,true,true,false,false,false,false,true,false,false,false,false,true,false,false,false,false,false,true,true,false,true,true,false,true,true,false,false,false,false,true,true,true,false,false,true,false,true,false,false,false,false,false,true,false,true,true,false,false,false,false,false,false,true,true,false,false,false,false,false,true,true,true,false,false,false,false,false,true,false,true,false,false,false,false,true,false,false,false,false,false,false,false,false,false,false,true,false,true,false,false,true,true,true,true,false,true,false,true,true,false,true,true,true,true,true,false,true,false,false,false,false,false,false,true,false,true,false,false,false,false,true,false,false,true,false,false,true,false,false,true,false,false,true,false,false,false,true,false,false,true,false,true,false,true,false,false,true,false,false,false,false,false,false,true,true,false,false,false,true,true,false,false,true,true,false,false,true,false,false,false,false,true,true,false,true,false,false,true,true,false,false,false,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true,true,false,false,false,false,true,false,false,false,true,false,true,false,true,true,true,true,false,true,false,false,false,false,false,false,false,false,false,true,false,false,false,false,false,false,true,false,false,true,false,true,true,true,false,false,true,false,true,false,false,false,true,true,false,false,true,true,false,true,true,false,false,true,true,false,true,false,true,false,false,true,false,false,false,false,true,false,true,false,true,false,false,true,false,false,true,true,false,false,false,false,true,true,false,true,false,true,false,false,false,false,true,false,false,true,false,true,false,true,false,false,false,false,false,false,true,false,false,false,false,false,true,false,false,false,true,true,true,false,false,true,false,false,true,true,false,true,false,true,false,false,true,false,false,true,true,false,false,false,true,false,false,false,true,true,false,false,false,false,false,false,false,false,false,false,false,false,true,false,false,false,false,false,true,false,false,false,true,false,false,false,true,true,true,true,true,false,false,false,true,true,false,false,false,true,false,true,false,false,false,true,false,true,false,false,true,false,true,false,false,false,false,true,true,false,false,true,false,true,false,true,true,true,false,false],"digits-only":[false,false,false,false,false,false,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true,false,true,true,false,true,true,false,false,true,false,false,false,false,true,true,true,true,true,true,false,false,false,true,false,false,false,false,false,false,false,false,false,false,true,false,false,false,true,true,false,true,false,false,false,true,false,true,true,false,false,true,false,false,false,false,false,false,true,false,false,false,false,false,true,false,false,true,false,false,false,false,false,false,true,false,false,true,false,false,true,false,false,false,false,true,false,false,true,false,false,false,true,false,true,false,true,true,true,false,false,true,false,true,false,false,true,false,false,false,false,true,false,true,false,false,false,false,false,false,false,false,false,true,false,true,true,true,true,false,true,false,true,false,false,false,true,true,false,false,false,true,false,false,false,true,false,false,false,false,false,false,true,false,false,false,false,false,false,false,false,true,false,false,true,false,true,false,true,false,false,false,true,false,true,false,true,false,false,false,true,false,false,false,true,false,true,false,false,false,false,false,true,false,false,true,false,true,false,false,false,false,false,false,true,false,false,false,true,false,false,false,false,false,false,false,true,true,false,false,false,true,false,false,false,true,false,false,false,false,false,false,false,false,false,false,false,false,false,true,false,true,false,true,false,true,false,true,false,false,false,false,false,false,false,false,true,false,true,false,true,false,false,false,false,false,false,false,false,false,false,false,true,false,false,false,true,true,false,false,false,false,true,false,false,false,false,true,false,false,false,false,false,true,true,false,true,true,false,true,true,false,false,false,false,true,true,true,false,false,true,false,true,false,false,false,false,false,true,false,true,true,false,false,false,false,false,false,true,true,false,false,false,false,false,true,true,true,false,false,false,false,false,true,false,true,false,false,false,false,true,false,false,false,false,false,false,false,false,false,false,true,false,true,false,false,true,false,true,true,false,true,false,true,true,false,true,false,true,true,true,false,true,false,false,false,false,false,false,true,false,true,false,false,false,false,true,false,false,true,false,false,true,false,false,true,false,false,true,false,false,false,true,false,false,true,false,true,false,true,false,false,true,false,false,false,false,false,false,true,true,false,false,false,true,true,false,false,true,true,false,false,true,false,false,false,false,true,true,false,true,false,false,true,true,false,false,false,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true,false,false,false,false,true,false,false,false,true,false,true,false,true,true,true,true,false,true,false,false,false,false,false,false,false,false,false,true,false,false,false,false,false,false,true,false,false,true,false,true,true,true,false,false,true,false,true,false,false,false,true,true,false,false,true,true,false,true,true,false,false,true,true,false,true,false,true,false,false,true,false,false,false,false,true,false,true,false,true,false,false,true,false,false,true,true,false,false,false,false,true,true,false,true,false,true,false,false,false,false,true,false,false,true,false,true,false,true,false,false,false,false,false,false,true,false,false,false,false,false,true,false,false,false,true,true,true,false,false,true,false,false,true,true,false,true,false,true,false,false,true,false,false,true,true,false,false,false,true,false,false,false,true,true,false,false,false,false,false,false,false,false,false,false,false,false,true,false,false,false,false,false,true,false,false,false,true,false,false,false,true,true,true,true,true,false,false,false,true,true,false,false,false,true,false,true,false,false,false,true,false,true,false,false,true,false,true,false,false,false,false,true,true,false,false,true,false,true,false,true,true,true,false,false],"digits-extracted":[false,false,false,false,false,false,true,true,true,true,true,true,true,true,true,true,false,false,true,true,true,false,true,true,true,true,true,true,true,false,false,false,false,false,false,false,false,false,false,false,false,false,true,false,true,true,false,true,true,false,false,true,false,false,false,false,true,true,true,true,true,true,false,false,true,true,false,true,false,false,false,false,false,false,false,false,true,false,false,false,true,true,false,true,false,false,false,true,false,true,true,false,false,true,false,false,false,false,false,true,true,false,false,false,true,false,true,true,false,true,false,false,false,false,false,false,true,false,false,true,true,false,true,false,false,false,false,true,false,false,true,false,false,false,true,false,true,false,true,true,true,false,false,true,false,true,false,false,true,false,false,false,true,true,false,true,false,false,false,false,false,false,false,false,false,true,false,true,true,true,true,false,true,false,true,false,false,false,true,true,false,false,false,true,false,false,false,true,true,true,false,true,false,false,true,false,true,true,false,false,false,false,false,true,false,false,true,false,true,true,true,false,false,false,true,false,true,false,true,false,true,false,true,true,false,false,true,false,true,false,true,false,false,false,true,false,false,true,false,true,true,false,true,false,false,false,true,false,false,false,true,false,false,false,false,false,false,false,true,true,false,false,false,true,false,false,false,true,true,false,false,false,true,false,false,true,false,true,false,false,false,true,false,true,false,true,false,true,true,true,false,true,false,false,false,false,false,false,true,true,true,false,true,false,true,true,false,false,false,false,true,false,false,false,true,false,false,false,true,true,true,false,false,false,true,false,false,false,true,true,true,true,false,false,false,true,true,true,true,true,false,true,true,true,false,true,false,true,true,true,true,false,true,false,true,false,true,true,true,false,true,false,true,true,true,false,false,true,false,false,true,true,false,false,false,false,false,true,true,true,true,false,false,false,false,true,false,true,false,false,false,false,true,true,false,false,false,false,true,false,false,false,false,true,true,true,false,false,true,true,true,true,false,true,false,true,true,false,true,true,true,true,true,true,true,false,false,false,false,true,false,true,false,true,false,false,false,false,true,false,false,true,true,false,true,false,false,true,false,false,true,false,false,false,true,false,false,true,false,true,false,true,true,false,true,true,false,true,false,false,false,true,true,true,false,true,true,true,false,false,true,true,false,true,true,false,false,true,false,true,true,true,true,false,false,true,true,false,false,false,true,false,false,false,false,false,false,false,true,false,false,false,false,false,true,false,false,true,true,false,false,false,false,true,false,false,false,true,false,true,false,true,true,true,true,false,true,false,false,false,false,false,false,false,true,false,true,false,false,true,false,true,false,true,false,false,true,false,true,true,true,false,true,true,false,true,false,false,true,true,true,false,false,true,true,false,true,true,true,true,true,true,false,true,false,true,false,false,true,false,false,false,false,true,true,true,true,true,false,false,true,false,false,true,true,false,false,false,false,true,true,false,true,true,true,false,false,false,false,true,false,true,true,false,true,false,true,true,false,false,false,false,false,true,false,true,false,false,true,true,false,true,false,true,true,true,false,false,true,false,false,true,true,false,true,false,true,false,true,true,false,false,true,true,true,false,false,true,false,true,false,true,true,false,false,false,false,false,false,true,false,false,false,false,true,true,false,false,false,false,false,true,true,false,false,true,false,false,false,true,true,true,true,true,true,false,false,true,true,false,true,false,true,false,true,true,false,false,true,false,true,false,false,true,false,true,false,false,false,false,true,true,false,true,true,false,true,false,true,true,true,false,false]}},"is-valid-pis":{"kind":"validator","optionSets":[{}],"profiles":{"masked-charset":[false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true,false,false,false,false,false,false,false,false,false,true,true,true,true,true,false,false,true,false,true,true,false,false,false,true,false,false,false,false,true,false,true,false,true,false,true,false,false,true,false,false,true,false,false,true,false,false,true,true,false,true,false,false,true,true,false,true,true,true,false,true,true,false,false,true,false,false,false,false,false,false,true,false,false,false,false,false,false,false,false,true,false,true,false,false,false,false,true,false,false,true,false,false,false,false,false,true,false,false,false,true,false,true,true,false,false,false,false,false,true,false,true,true,false,false,false,true,false,false,false,false,false,false,false,true,false,false,false,true,false,false,false,true,false,true,false,true,true,false,false,true,true,true,true,false,false,false,false,false,true,false,false,false,false,false,true,true,false,false,false,false,false,true,true,true,true,false,false,false,true,false,true,true,false,false,false,false,false,false,true,false,true,false,true,true,false,false,false,false,false,false,true,false,false,false,false,false,true,true,false,false,false,false,false,true,false,false,false,false,false,true,false,true,false,false,false,false,false,false,false,false,false,true,false,true,false,true,false,true,false,true,false,false,false,false,true,false,false,true,true,true,true,false,true,true,true,false,false,true,true,true,false,false,true,false,false,false,false,false,true,true,true,false,true,false,true,false,false,false,true,false,false,false,false,false,true,true,false,false,false,true,false,false,false,false,true,false,false,false,false,true,true,true,false,false,false,false,false,false,false,false,true,true,false,true,false,true,false,false,false,false,false,false,true,false,false,false,true,false,true,false,false,false,false,false,false,false,false,false,false,true,false,true,false,true,false,false,false,false,false,true,false,false,false,true,true,true,false,false,false,false,false,false,false,false,false,false,false,false,false,true,true,true,true,false,false,true,true,false,false,true,false,false,true,false,false,true,false,false,false,true,false,false,false,false,true,true,false,false,false,false,false,false,false,false,false,true,true,false,false,false,false,true,false,true,true,false,true,false,false,false,false,false,true,true,true,false,false,false,true,false,false,false,false,true,false,false,false,false,false,false,true,false,false,true,false,false,true,false,false,false,false,false,false,false,true,false,true,false,true,false,false,false,false,false,false,false,true,false,true,false,true,false,false,true,true,false,true,false,false,false,false,false,true,false,false,false,true,false,false,true,true,false,true,true,false,true,false,false,false,true,true,false,false,true,true,false,false,false,false,false,true,false,true,false,false,false,true,false,true,false,true,false,false,false,true,true,true,false,true,true,true,true,false,true,false,false,false,false,true,false,false,false,true,true,true,true,false,false,false,true,false,false,true,false,true,false,false,false,true,true,false,false,false,false,false,false,false,false,false,false,false,false,true,true,true,true,false,true,false,true,true,false,false,false,false,false,false,true,false,false,false,false,true,false,true,false,true,false,false,false,false,false,false,true,false,false,true,false,false,true,false,true,true,true,false,false,false,true,false,false,false,false,false,false,true,false,false,false,true,false,true,false,false,false,true,true,false,false,true,false,false,false,true,true,true,false,false,false,true,false,false,false,false,true,true,false,false,false,false,false,false,false,true,true,true,true,true,false,true,false,false,false,false,false,false,true,true,false,false,true,false,false,false,false,false,false,true,false,false,false,false,true,false,true,false,false,false,true,false,false,false,true,false,false,true,false,false,true,false,true,true,false,true,false,false,true,true,true,false,false,false,false,true,false,false,false,true,false,false,true,false],"digits-only-lenient":[false,false,false,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true,false,false,false,false,false,false,false,false,false,true,false,false,false,false,false,false,false,false,true,true,false,false,false,true,false,false,false,false,true,false,true,false,true,false,true,false,false,true,false,false,true,false,false,true,false,false,false,true,false,true,false,false,false,false,false,true,false,true,false,true,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true,false,true,false,false,false,false,false,false,false,true,false,false,false,false,false,true,false,false,false,true,false,true,true,false,false,false,false,false,true,false,false,true,false,false,false,false,false,false,false,false,false,false,false,true,false,false,false,false,false,false,false,true,false,true,false,true,true,false,false,true,false,true,true,false,false,false,false,false,true,false,false,false,false,false,false,true,false,false,false,false,false,true,false,true,true,false,false,false,true,false,false,true,false,false,false,false,false,false,false,false,true,false,false,false,false,false,false,false,false,false,true,false,false,false,false,false,true,true,false,false,false,false,false,false,false,false,false,false,false,true,false,true,false,false,false,false,false,false,false,false,false,true,false,true,false,true,false,true,false,true,false,false,false,false,false,false,false,true,true,true,true,false,true,false,false,false,false,true,true,true,false,false,true,false,false,false,false,false,true,true,true,false,true,false,true,false,false,false,true,false,false,false,false,false,true,true,false,false,false,true,false,false,false,false,false,false,false,false,false,true,true,false,false,false,false,false,false,false,false,false,true,true,false,true,false,false,false,false,false,false,false,false,true,false,false,false,true,false,true,false,false,false,false,false,false,false,false,false,false,true,false,true,false,true,false,false,false,false,false,true,false,false,false,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true,true,false,true,false,false,true,true,false,false,false,false,false,true,false,false,true,false,false,false,true,false,false,false,false,true,true,false,false,false,false,false,false,false,false,false,true,true,false,false,false,false,false,false,true,true,false,true,false,false,false,false,false,false,true,true,false,false,false,true,false,false,false,false,true,false,false,false,false,false,false,true,false,false,true,false,false,true,false,false,false,false,false,false,false,true,false,false,false,false,false,false,false,false,false,false,false,true,false,true,false,true,false,false,true,false,false,true,false,false,false,false,false,true,false,false,false,true,false,false,false,true,false,false,true,false,true,false,false,false,true,true,false,false,false,true,false,false,false,false,false,true,false,false,false,false,false,false,false,true,false,true,false,false,false,true,false,true,false,true,false,false,true,false,false,false,false,false,false,false,false,false,false,true,true,true,true,false,false,false,true,false,false,false,false,true,false,false,false,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true,true,false,false,true,false,false,true,false,false,false,false,false,false,false,false,false,false,false,true,false,false,false,true,false,false,false,false,false,false,true,false,false,true,false,false,false,false,true,true,true,false,false,false,true,false,false,false,false,false,false,true,false,false,false,true,false,true,false,false,false,true,false,false,false,false,false,false,false,true,false,true,false,false,false,true,false,false,false,false,true,true,false,false,false,false,false,false,false,true,true,true,true,true,false,false,false,false,false,false,false,false,true,true,false,false,true,false,false,false,false,false,false,true,false,false,false,false,true,false,false,false,false,false,true,false,false,false,true,false,false,true,false,false,false,false,true,true,false,false,false,false,true,false,true,false,false,false,false,true,false,false,false,true,false,false,false,false]}},"format-cpf":{"kind":"formatter","optionSets":[{},{"obfuscate":true},{"pad":true},{"pad":true,"obfuscate":true}],"profiles":{"pattern-partial":[["","","000.000.000-00","***.000.000-**"],["","","000.000.000-00","***.000.000-**"],["0","*","000.000.000-00","***.000.000-**"],["000.000.000-00","***.000.000-**","000.000.000-00","***.000.000-**"],["111.111.111-11","***.111.111-**","111.111.111-11","***.111.111-**"],["999.999.999-99","***.999.999-**","999.999.999-99","***.999.999-**"],["123.456.789-09","***.456.789-**","123.456.789-09","***.456.789-**"],["123.456.789-09","***.456.789-**","123.456.789-09","***.456.789-**"],["123.456.789-09","***.456.789-**","123.456.789-09","***.456.789-**"],["123.456.789-09","***.456.789-**","123.456.789-09","***.456.789-**"],["123.456.789-09","***.456.789-**","123.456.789-09","***.456.789-**"],["123.456.789-09","***.456.789-**","123.456.789-09","***.456.789-**"],["123.456.789-09","***.456.789-**","123.456.789-09","***.456.789-**"],["123.456.789-09","***.456.789-**","123.456.789-09","***.456.789-**"],["123.456.789-09","***.456.789-**","123.456.789-09","***.456.789-**"],["123.456.789-09","***.456.789-**","123.456.789-09","***.456.789-**"],["123.456.789-0","***.456.789-*","012.345.678-90","***.345.678-**"],["123.456.789-09","***.456.789-**","123.456.789-09","***.456.789-**"],["123.456.789-09","***.456.789-**","123.456.789-09","***.456.789-**"],["123.456.789-09","***.456.789-**","123.456.789-09","***.456.789-**"],["123.456.789-09","***.456.789-**","123.456.789-09","***.456.789-**"],["123.456.789-00","***.456.789-**","123.456.789-00","***.456.789-**"],["123.456.789-09","***.456.789-**","123.456.789-09","***.456.789-**"],["123.456.789-09","***.456.789-**","123.456.789-09","***.456.789-**"],["123.456.789-09","***.456.789-**","123.456.789-09","***.456.789-**"],["123.456.789-09","***.456.789-**","123.456.789-09","***.456.789-**"],["123.456.789-09","***.456.789-**","123.456.789-09","***.456.789-**"],["123.456.789-09","***.456.789-**","123.456.789-09","***.456.789-**"],["123.456.789-09","***.456.789-**","123.456.789-09","***.456.789-**"],["","","000.000.000-00","***.000.000-**"],["","","000.000.000-00","***.000.000-**"],["120.568.741-07","***.568.741-**","120.568.741-07","***.568.741-**"],["120.568.741-07","***.568.741-**","120.568.741-07","***.568.741-**"],["120.568.741-07","***.568.741-**","120.568.741-07","***.568.741-**"],["120.568.741-07","***.568.741-**","120.568.741-07","***.568.741-**"],["120.568.741-07","***.568.741-**","120.568.741-07","***.568.741-**"],["120.568.741-08","***.568.741-**","120.568.741-08","***.568.741-**"],["120.568.741-0","***.568.741-*","012.056.874-10","***.056.874-**"],["120.568.741-07","***.568.741-**","120.568.741-07","***.568.741-**"],["120.568.741-07","***.568.741-**","120.568.741-07","***.568.741-**"],["742.757.335-68","***.757.335-**","742.757.335-68","***.757.335-**"],["692.642.592-94","***.642.592-**","692.642.592-94","***.642.592-**"],["275.026.776-58","***.026.776-**","275.026.776-58","***.026.776-**"],["951.673","***.673","000.009.516-73","***.009.516-**"],["455.287.462-48","***.287.462-**","455.287.462-48","***.287.462-**"],["001.925.910-70","***.925.910-**","001.925.910-70","***.925.910-**"],["242.337.996-70","***.337.996-**","242.337.996-70","***.337.996-**"],["043.493.162-48","***.493.162-**","043.493.162-48","***.493.162-**"],["058.280.337-35","***.280.337-**","058.280.337-35","***.280.337-**"],["340.6","***.6","000.000.034-06","***.000.034-**"],["010.180.547-71","***.180.547-**","010.180.547-71","***.180.547-**"],["459.609.678-39","***.609.678-**","459.609.678-39","***.609.678-**"],["729.535.593-75","***.535.593-**","729.535.593-75","***.535.593-**"],["350.676.337-17","***.676.337-**","350.676.337-17","***.676.337-**"],["857.527.887-60","***.527.887-**","857.527.887-60","***.527.887-**"],["122.014.610-35","***.014.610-**","122.014.610-35","***.014.610-**"],["656.235.973-27","***.235.973-**","656.235.973-27","***.235.973-**"],["082.162.626-47","***.162.626-**","082.162.626-47","***.162.626-**"],["942.914.972-53","***.914.972-**","942.914.972-53","***.914.972-**"],["655.466.786-58","***.466.786-**","655.466.786-58","***.466.786-**"],["022.180.106-58","***.180.106-**","022.180.106-58","***.180.106-**"],["134.346.089-15","***.346.089-**","134.346.089-15","***.346.089-**"],["600.215.969-17","***.215.969-**","600.215.969-17","***.215.969-**"],["992.663.216-88","***.663.216-**","992.663.216-88","***.663.216-**"],["036.669.424-31","***.669.424-**","036.669.424-31","***.669.424-**"],["290.227.963-96","***.227.963-**","290.227.963-96","***.227.963-**"],["659.037","***.037","000.006.590-37","***.006.590-**"],["610.954.584-85","***.954.584-**","610.954.584-85","***.954.584-**"],["573.641.832-96","***.641.832-**","573.641.832-96","***.641.832-**"],["724.681.246-05","***.681.246-**","724.681.246-05","***.681.246-**"],["013.660.215-78","***.660.215-**","013.660.215-78","***.660.215-**"],["372.425.077-00","***.425.077-**","372.425.077-00","***.425.077-**"],["659.684.184-86","***.684.184-**","659.684.184-86","***.684.184-**"],["646.293.942-34","***.293.942-**","646.293.942-34","***.293.942-**"],["898.841.977-02","***.841.977-**","898.841.977-02","***.841.977-**"],["588.519.746-61","***.519.746-**","588.519.746-61","***.519.746-**"],["067.339.637-10","***.339.637-**","067.339.637-10","***.339.637-**"],["161.534.166-09","***.534.166-**","161.534.166-09","***.534.166-**"],["973.194.655-20","***.194.655-**","973.194.655-20","***.194.655-**"],["834.386.585-34","***.386.585-**","834.386.585-34","***.386.585-**"],["489.381.054-58","***.381.054-**","489.381.054-58","***.381.054-**"],["520.705.644-10","***.705.644-**","520.705.644-10","***.705.644-**"],["372.994.928-50","***.994.928-**","372.994.928-50","***.994.928-**"],["971.165.013-47","***.165.013-**","971.165.013-47","***.165.013-**"],["267.783.456-65","***.783.456-**","267.783.456-65","***.783.456-**"],["715.653.418-11","***.653.418-**","715.653.418-11","***.653.418-**"],["193.000.765-85","***.000.765-**","193.000.765-85","***.000.765-**"],["326.057.798-07","***.057.798-**","326.057.798-07","***.057.798-**"],["818.871.917-06","***.871.917-**","818.871.917-06","***.871.917-**"],["601.502.471-25","***.502.471-**","601.502.471-25","***.502.471-**"],["717.708.895-40","***.708.895-**","717.708.895-40","***.708.895-**"],["383.061.730-04","***.061.730-**","383.061.730-04","***.061.730-**"],["635.680.628-66","***.680.628-**","635.680.628-66","***.680.628-**"],["137.656.313-45","***.656.313-**","137.656.313-45","***.656.313-**"],["968.408.342-66","***.408.342-**","968.408.342-66","***.408.342-**"],["875.662.566-01","***.662.566-**","875.662.566-01","***.662.566-**"],["170.605","***.605","000.001.706-05","***.001.706-**"],["478.089.322-0","***.089.322-*","047.808.932-20","***.808.932-**"],["977.030.00","***.030.00","000.977.030-00","***.977.030-**"],["660.299.248-18","***.299.248-**","660.299.248-18","***.299.248-**"],["253.681.039-99","***.681.039-**","253.681.039-99","***.681.039-**"],["150.507.577-07","***.507.577-**","150.507.577-07","***.507.577-**"],["493.545.5","***.545.5","000.049.354-55","***.049.354-**"],["236.096.401-26","***.096.401-**","236.096.401-26","***.096.401-**"],["758.781.474-40","***.781.474-**","758.781.474-40","***.781.474-**"],["952.919.320-24","***.919.320-**","952.919.320-24","***.919.320-**"],["327.117.213-70","***.117.213-**","327.117.213-70","***.117.213-**"],["258.163.547-95","***.163.547-**","258.163.547-95","***.163.547-**"],["707.612.876-64","***.612.876-**","707.612.876-64","***.612.876-**"],["401.109.658-09","***.109.658-**","401.109.658-09","***.109.658-**"],["549","***","000.000.005-49","***.000.005-**"],["625.017.835-55","***.017.835-**","625.017.835-55","***.017.835-**"],["385.535.232-3","***.535.232-*","038.553.523-23","***.553.523-**"],["001.583.790-99","***.583.790-**","001.583.790-99","***.583.790-**"],["210.625.74","***.625.74","000.210.625-74","***.210.625-**"],["636.740.6","***.740.6","000.063.674-06","***.063.674-**"],["946.220.892-11","***.220.892-**","946.220.892-11","***.220.892-**"],["859.472.699-15","***.472.699-**","859.472.699-15","***.472.699-**"],["869.824.7","***.824.7","000.086.982-47","***.086.982-**"],["309.534.527-51","***.534.527-**","309.534.527-51","***.534.527-**"],["555.420.440-69","***.420.440-**","555.420.440-69","***.420.440-**"],["878.214.259-57","***.214.259-**","878.214.259-57","***.214.259-**"],["103.597.230-12","***.597.230-**","103.597.230-12","***.597.230-**"],["385.896.263-69","***.896.263-**","385.896.263-69","***.896.263-**"],["170.914.219-71","***.914.219-**","170.914.219-71","***.914.219-**"],["649.982.928-30","***.982.928-**","649.982.928-30","***.982.928-**"],["737.925","***.925","000.007.379-25","***.007.379-**"],["517.236.689-07","***.236.689-**","517.236.689-07","***.236.689-**"],["035.307.750-1","***.307.750-*","003.530.775-01","***.530.775-**"],["138.196.424-20","***.196.424-**","138.196.424-20","***.196.424-**"],["299.724.486-22","***.724.486-**","299.724.486-22","***.724.486-**"],["896.084.210-27","***.084.210-**","896.084.210-27","***.084.210-**"],["142.563.725-00","***.563.725-**","142.563.725-00","***.563.725-**"],["554.273.590-71","***.273.590-**","554.273.590-71","***.273.590-**"],["638.764.089-03","***.764.089-**","638.764.089-03","***.764.089-**"],["106","***","000.000.001-06","***.000.001-**"],["533.678.958-57","***.678.958-**","533.678.958-57","***.678.958-**"],["500.978.209-93","***.978.209-**","500.978.209-93","***.978.209-**"],["324.988.564-98","***.988.564-**","324.988.564-98","***.988.564-**"],["365.588.462-17","***.588.462-**","365.588.462-17","***.588.462-**"],["261.475.992-91","***.475.992-**","261.475.992-91","***.475.992-**"],["192.4","***.4","000.000.019-24","***.000.019-**"],["756.602.109-33","***.602.109-**","756.602.109-33","***.602.109-**"],["939.710.336-95","***.710.336-**","939.710.336-95","***.710.336-**"],["522.000.902-53","***.000.902-**","522.000.902-53","***.000.902-**"],["384.762.726-00","***.762.726-**","384.762.726-00","***.762.726-**"],["378.447.344-33","***.447.344-**","378.447.344-33","***.447.344-**"],["069.263.407-51","***.263.407-**","069.263.407-51","***.263.407-**"],["591.394.668-50","***.394.668-**","591.394.668-50","***.394.668-**"],["687.953.385-70","***.953.385-**","687.953.385-70","***.953.385-**"],["873.732.381-38","***.732.381-**","873.732.381-38","***.732.381-**"],["951","***","000.000.009-51","***.000.009-**"],["641.350.042-53","***.350.042-**","641.350.042-53","***.350.042-**"],["409.109.630-10","***.109.630-**","409.109.630-10","***.109.630-**"],["268.067.823-78","***.067.823-**","268.067.823-78","***.067.823-**"],["837.234.185-03","***.234.185-**","837.234.185-03","***.234.185-**"],["758.131.6","***.131.6","000.075.813-16","***.075.813-**"],["202.409.071-37","***.409.071-**","202.409.071-37","***.409.071-**"],["335.201.412-68","***.201.412-**","335.201.412-68","***.201.412-**"],["179.38","***.38","000.000.179-38","***.000.179-**"],["102.134.072-17","***.134.072-**","102.134.072-17","***.134.072-**"],["667.383.972-99","***.383.972-**","667.383.972-99","***.383.972-**"],["459.216.657-41","***.216.657-**","459.216.657-41","***.216.657-**"],["054.669.167-70","***.669.167-**","054.669.167-70","***.669.167-**"],["627.622.669-10","***.622.669-**","627.622.669-10","***.622.669-**"],["849.112.629-58","***.112.629-**","849.112.629-58","***.112.629-**"],["818.264.252-90","***.264.252-**","818.264.252-90","***.264.252-**"],["892.059.852-52","***.059.852-**","892.059.852-52","***.059.852-**"],["054.960.534-71","***.960.534-**","054.960.534-71","***.960.534-**"],["525.973.933-72","***.973.933-**","525.973.933-72","***.973.933-**"],["386.522.205-65","***.522.205-**","386.522.205-65","***.522.205-**"],["178.999.336-52","***.999.336-**","178.999.336-52","***.999.336-**"],["222.790.475-51","***.790.475-**","222.790.475-51","***.790.475-**"],["154.816.477-40","***.816.477-**","154.816.477-40","***.816.477-**"],["541.300.827-95","***.300.827-**","541.300.827-95","***.300.827-**"],["234.421.855-71","***.421.855-**","234.421.855-71","***.421.855-**"],["905.000.809-04","***.000.809-**","905.000.809-04","***.000.809-**"],["842.642.595-22","***.642.595-**","842.642.595-22","***.642.595-**"],["589.768.017-50","***.768.017-**","589.768.017-50","***.768.017-**"],["206.487.406-25","***.487.406-**","206.487.406-25","***.487.406-**"],["573.421.472-91","***.421.472-**","573.421.472-91","***.421.472-**"],["8","*","000.000.000-08","***.000.000-**"],["067.879.154-80","***.879.154-**","067.879.154-80","***.879.154-**"],["749.949.997-91","***.949.997-**","749.949.997-91","***.949.997-**"],["308.351.266-00","***.351.266-**","308.351.266-00","***.351.266-**"],["336.644.463-41","***.644.463-**","336.644.463-41","***.644.463-**"],["720.842.870-28","***.842.870-**","720.842.870-28","***.842.870-**"],["626.103.959-30","***.103.959-**","626.103.959-30","***.103.959-**"],["390.835.940-68","***.835.940-**","390.835.940-68","***.835.940-**"],["294.629.944-98","***.629.944-**","294.629.944-98","***.629.944-**"],["878.620.977-41","***.620.977-**","878.620.977-41","***.620.977-**"],["148.965.245-00","***.965.245-**","148.965.245-00","***.965.245-**"],["454.930.241-82","***.930.241-**","454.930.241-82","***.930.241-**"],["439.558.229-83","***.558.229-**","439.558.229-83","***.558.229-**"],["495.454.403-33","***.454.403-**","495.454.403-33","***.454.403-**"],["008.387.125-51","***.387.125-**","008.387.125-51","***.387.125-**"],["569.399.571-20","***.399.571-**","569.399.571-20","***.399.571-**"],["794.676.345-03","***.676.345-**","794.676.345-03","***.676.345-**"],["901.177.609-52","***.177.609-**","901.177.609-52","***.177.609-**"],["6","*","000.000.000-06","***.000.000-**"],["450.262.548-83","***.262.548-**","450.262.548-83","***.262.548-**"],["717.334.855-02","***.334.855-**","717.334.855-02","***.334.855-**"],["599.209.135-63","***.209.135-**","599.209.135-63","***.209.135-**"],["140.796.801-71","***.796.801-**","140.796.801-71","***.796.801-**"],["067.377.820-12","***.377.820-**","067.377.820-12","***.377.820-**"],["768.373.575-51","***.373.575-**","768.373.575-51","***.373.575-**"],["438.557.083-39","***.557.083-**","438.557.083-39","***.557.083-**"],["262.739.375-61","***.739.375-**","262.739.375-61","***.739.375-**"],["668.462.685-96","***.462.685-**","668.462.685-96","***.462.685-**"],["843.356.403-07","***.356.403-**","843.356.403-07","***.356.403-**"],["127.109.736-26","***.109.736-**","127.109.736-26","***.109.736-**"],["608.052.223-00","***.052.223-**","608.052.223-00","***.052.223-**"],["364.537.167-69","***.537.167-**","364.537.167-69","***.537.167-**"],["807.161.895-38","***.161.895-**","807.161.895-38","***.161.895-**"],["968.751.151-66","***.751.151-**","968.751.151-66","***.751.151-**"],["743.369.448-41","***.369.448-**","743.369.448-41","***.369.448-**"],["310.923.973-61","***.923.973-**","310.923.973-61","***.923.973-**"],["163.481.721-39","***.481.721-**","163.481.721-39","***.481.721-**"],["381.469.865-79","***.469.865-**","381.469.865-79","***.469.865-**"],["241.446.800-90","***.446.800-**","241.446.800-90","***.446.800-**"],["358.186.392-82","***.186.392-**","358.186.392-82","***.186.392-**"],["0","*","000.000.000-00","***.000.000-**"],["503.734.632-00","***.734.632-**","503.734.632-00","***.734.632-**"],["766.122.010-53","***.122.010-**","766.122.010-53","***.122.010-**"],["550.231.980","***.231.980","005.502.319-80","***.502.319-**"],["385.784.989-50","***.784.989-**","385.784.989-50","***.784.989-**"],["847.859.775-15","***.859.775-**","847.859.775-15","***.859.775-**"],["349.571.075-92","***.571.075-**","349.571.075-92","***.571.075-**"],["905.346.609-67","***.346.609-**","905.346.609-67","***.346.609-**"],["218.383.615","***.383.615","002.183.836-15","***.183.836-**"],["188.139.293-74","***.139.293-**","188.139.293-74","***.139.293-**"],["256.250.906-03","***.250.906-**","256.250.906-03","***.250.906-**"],["14","**","000.000.000-14","***.000.000-**"],["678.179.056-35","***.179.056-**","678.179.056-35","***.179.056-**"],["451.858.175-00","***.858.175-**","451.858.175-00","***.858.175-**"],["625.919.975-15","***.919.975-**","625.919.975-15","***.919.975-**"],["948.664.060-05","***.664.060-**","948.664.060-05","***.664.060-**"],["489.869.813-19","***.869.813-**","489.869.813-19","***.869.813-**"],["481.896.956-21","***.896.956-**","481.896.956-21","***.896.956-**"],["128.473.716-05","***.473.716-**","128.473.716-05","***.473.716-**"],["027.127.818-80","***.127.818-**","027.127.818-80","***.127.818-**"],["505.906.772-01","***.906.772-**","505.906.772-01","***.906.772-**"],["113.086.121-09","***.086.121-**","113.086.121-09","***.086.121-**"],["854.529.225-41","***.529.225-**","854.529.225-41","***.529.225-**"],["165.789.388-27","***.789.388-**","165.789.388-27","***.789.388-**"],["060.543.964-16","***.543.964-**","060.543.964-16","***.543.964-**"],["946.809.205-48","***.809.205-**","946.809.205-48","***.809.205-**"],["696.050.299-60","***.050.299-**","696.050.299-60","***.050.299-**"],["640.603.683-30","***.603.683-**","640.603.683-30","***.603.683-**"],["798.702.973-38","***.702.973-**","798.702.973-38","***.702.973-**"],["713.273.603-57","***.273.603-**","713.273.603-57","***.273.603-**"],["068.337.612-41","***.337.612-**","068.337.612-41","***.337.612-**"],["319.530.171-04","***.530.171-**","319.530.171-04","***.530.171-**"],["218.811.390-70","***.811.390-**","218.811.390-70","***.811.390-**"],["036.210.901-28","***.210.901-**","036.210.901-28","***.210.901-**"],["088.458.018-75","***.458.018-**","088.458.018-75","***.458.018-**"],["660.811.783-80","***.811.783-**","660.811.783-80","***.811.783-**"],["991.593.672-0","***.593.672-*","099.159.367-20","***.159.367-**"],["199.297.039-42","***.297.039-**","199.297.039-42","***.297.039-**"],["651.349.831-78","***.349.831-**","651.349.831-78","***.349.831-**"],["561.271.594-82","***.271.594-**","561.271.594-82","***.271.594-**"],["139.056.747-09","***.056.747-**","139.056.747-09","***.056.747-**"],["354.878.163-69","***.878.163-**","354.878.163-69","***.878.163-**"],["011.046.125-85","***.046.125-**","011.046.125-85","***.046.125-**"],["491.478.689-07","***.478.689-**","491.478.689-07","***.478.689-**"],["817.583.798-85","***.583.798-**","817.583.798-85","***.583.798-**"],["195.826.039-44","***.826.039-**","195.826.039-44","***.826.039-**"],["128.573.303-75","***.573.303-**","128.573.303-75","***.573.303-**"],["395.103.397-50","***.103.397-**","395.103.397-50","***.103.397-**"],["578.781.242-70","***.781.242-**","578.781.242-70","***.781.242-**"],["067.709.323-11","***.709.323-**","067.709.323-11","***.709.323-**"],["293.956.168-90","***.956.168-**","293.956.168-90","***.956.168-**"],["504.138.906-35","***.138.906-**","504.138.906-35","***.138.906-**"],["3","*","000.000.000-03","***.000.000-**"],["547.119.810-85","***.119.810-**","547.119.810-85","***.119.810-**"],["277.047.048-50","***.047.048-**","277.047.048-50","***.047.048-**"],["467.570.732-97","***.570.732-**","467.570.732-97","***.570.732-**"],["391.878.681-13","***.878.681-**","391.878.681-13","***.878.681-**"],["822.2","***.2","000.000.082-22","***.000.082-**"],["096.241.579-70","***.241.579-**","096.241.579-70","***.241.579-**"],["208.626.810-19","***.626.810-**","208.626.810-19","***.626.810-**"],["658.458.062-83","***.458.062-**","658.458.062-83","***.458.062-**"],["781.553.255-11","***.553.255-**","781.553.255-11","***.553.255-**"],["912.465.249-02","***.465.249-**","912.465.249-02","***.465.249-**"],["850.377.224-40","***.377.224-**","850.377.224-40","***.377.224-**"],["060.728.299-10","***.728.299-**","060.728.299-10","***.728.299-**"],["190.066.213-85","***.066.213-**","190.066.213-85","***.066.213-**"],["918.220.826-33","***.220.826-**","918.220.826-33","***.220.826-**"],["284.003.762-93","***.003.762-**","284.003.762-93","***.003.762-**"],["245.846.481-58","***.846.481-**","245.846.481-58","***.846.481-**"],["817.654.316-68","***.654.316-**","817.654.316-68","***.654.316-**"],["901.250.125-35","***.250.125-**","901.250.125-35","***.250.125-**"],["424.304.989-44","***.304.989-**","424.304.989-44","***.304.989-**"],["287.204.088-22","***.204.088-**","287.204.088-22","***.204.088-**"],["467.415.030-16","***.415.030-**","467.415.030-16","***.415.030-**"],["58","**","000.000.000-58","***.000.000-**"],["357.386.545-93","***.386.545-**","357.386.545-93","***.386.545-**"],["495.711.122-70","***.711.122-**","495.711.122-70","***.711.122-**"],["701.164.557-80","***.164.557-**","701.164.557-80","***.164.557-**"],["704.945.448-64","***.945.448-**","704.945.448-64","***.945.448-**"],["631.085.833-52","***.085.833-**","631.085.833-52","***.085.833-**"],["518.320.689-39","***.320.689-**","518.320.689-39","***.320.689-**"],["996.655.903-59","***.655.903-**","996.655.903-59","***.655.903-**"],["323.75","***.75","000.000.323-75","***.000.323-**"],["871.209.104-93","***.209.104-**","871.209.104-93","***.209.104-**"],["677.066.965-02","***.066.965-**","677.066.965-02","***.066.965-**"],["749.103.212-92","***.103.212-**","749.103.212-92","***.103.212-**"],["588.252.369-83","***.252.369-**","588.252.369-83","***.252.369-**"],["916.658.971-13","***.658.971-**","916.658.971-13","***.658.971-**"],["224.736.722-20","***.736.722-**","224.736.722-20","***.736.722-**"],["503.330.315-55","***.330.315-**","503.330.315-55","***.330.315-**"],["393.768.250-44","***.768.250-**","393.768.250-44","***.768.250-**"],["163.268.343-34","***.268.343-**","163.268.343-34","***.268.343-**"],["318.540.697-98","***.540.697-**","318.540.697-98","***.540.697-**"],["866.763.984-27","***.763.984-**","866.763.984-27","***.763.984-**"],["104.783","***.783","000.001.047-83","***.001.047-**"],["072.031.604-35","***.031.604-**","072.031.604-35","***.031.604-**"],["7","*","000.000.000-07","***.000.000-**"],["540.418.281-47","***.418.281-**","540.418.281-47","***.418.281-**"],["819.392.325-11","***.392.325-**","819.392.325-11","***.392.325-**"],["033.789.079-08","***.789.079-**","033.789.079-08","***.789.079-**"],["720.613","***.613","000.007.206-13","***.007.206-**"],["360.813.122-03","***.813.122-**","360.813.122-03","***.813.122-**"],["148.274.451-13","***.274.451-**","148.274.451-13","***.274.451-**"],["900.949.621-03","***.949.621-**","900.949.621-03","***.949.621-**"],["893.932.068-50","***.932.068-**","893.932.068-50","***.932.068-**"],["378.450.845-53","***.450.845-**","378.450.845-53","***.450.845-**"],["775.319.793-91","***.319.793-**","775.319.793-91","***.319.793-**"],["335.949.050-98","***.949.050-**","335.949.050-98","***.949.050-**"],["805.313.864-06","***.313.864-**","805.313.864-06","***.313.864-**"],["574.066.811-51","***.066.811-**","574.066.811-51","***.066.811-**"],["912.312.875-51","***.312.875-**","912.312.875-51","***.312.875-**"],["415","***","000.000.004-15","***.000.004-**"],["620.679.308-91","***.679.308-**","620.679.308-91","***.679.308-**"],["440.902.851-41","***.902.851-**","440.902.851-41","***.902.851-**"],["674.899.794-12","***.899.794-**","674.899.794-12","***.899.794-**"],["116.809.196-95","***.809.196-**","116.809.196-95","***.809.196-**"],["329.341.678-01","***.341.678-**","329.341.678-01","***.341.678-**"],["299.275.353-09","***.275.353-**","299.275.353-09","***.275.353-**"],["688.163.203-70","***.163.203-**","688.163.203-70","***.163.203-**"],["327.452.564-39","***.452.564-**","327.452.564-39","***.452.564-**"],["495.931.279-33","***.931.279-**","495.931.279-33","***.931.279-**"],["777.911.178-43","***.911.178-**","777.911.178-43","***.911.178-**"],["491.378.845-06","***.378.845-**","491.378.845-06","***.378.845-**"],["097.947.41","***.947.41","000.097.947-41","***.097.947-**"],["932.232.431-78","***.232.431-**","932.232.431-78","***.232.431-**"],["282.958.210-05","***.958.210-**","282.958.210-05","***.958.210-**"],["332.123.446-79","***.123.446-**","332.123.446-79","***.123.446-**"],["777.620.413-70","***.620.413-**","777.620.413-70","***.620.413-**"],["953.735.104-16","***.735.104-**","953.735.104-16","***.735.104-**"],["644.891.536-27","***.891.536-**","644.891.536-27","***.891.536-**"],["427.946.720-14","***.946.720-**","427.946.720-14","***.946.720-**"],["932.068.398-07","***.068.398-**","932.068.398-07","***.068.398-**"],["404.281.399-80","***.281.399-**","404.281.399-80","***.281.399-**"],["270.027.530-61","***.027.530-**","270.027.530-61","***.027.530-**"],["160.419.098-91","***.419.098-**","160.419.098-91","***.419.098-**"],["593.995.456-10","***.995.456-**","593.995.456-10","***.995.456-**"],["043.818.998-14","***.818.998-**","043.818.998-14","***.818.998-**"],["680.670.367-48","***.670.367-**","680.670.367-48","***.670.367-**"],["760.838.385-06","***.838.385-**","760.838.385-06","***.838.385-**"],["465.086.646-46","***.086.646-**","465.086.646-46","***.086.646-**"],["642.048.326-71","***.048.326-**","642.048.326-71","***.048.326-**"],["035.849.498-23","***.849.498-**","035.849.498-23","***.849.498-**"],["829.765.743-40","***.765.743-**","829.765.743-40","***.765.743-**"],["721.351.510-17","***.351.510-**","721.351.510-17","***.351.510-**"],["124.350.770-94","***.350.770-**","124.350.770-94","***.350.770-**"],["997.700.041-98","***.700.041-**","997.700.041-98","***.700.041-**"],["388.993.879-58","***.993.879-**","388.993.879-58","***.993.879-**"],["699.367.677-72","***.367.677-**","699.367.677-72","***.367.677-**"],["915.530.482-20","***.530.482-**","915.530.482-20","***.530.482-**"],["826.748.097-87","***.748.097-**","826.748.097-87","***.748.097-**"],["327.827.816-00","***.827.816-**","327.827.816-00","***.827.816-**"],["130.258.1","***.258.1","000.013.025-81","***.013.025-**"],["301.419.265-80","***.419.265-**","301.419.265-80","***.419.265-**"],["990.647.782-58","***.647.782-**","990.647.782-58","***.647.782-**"],["824.460.621-8","***.460.621-*","082.446.062-18","***.446.062-**"],["701.407.510-09","***.407.510-**","701.407.510-09","***.407.510-**"],["797.749.251-22","***.749.251-**","797.749.251-22","***.749.251-**"],["452.943.389-71","***.943.389-**","452.943.389-71","***.943.389-**"],["677.156.778-84","***.156.778-**","677.156.778-84","***.156.778-**"],["103.615.865-90","***.615.865-**","103.615.865-90","***.615.865-**"],["221.156.793-41","***.156.793-**","221.156.793-41","***.156.793-**"],["020.408.846-23","***.408.846-**","020.408.846-23","***.408.846-**"],["869.560.262-38","***.560.262-**","869.560.262-38","***.560.262-**"],["881.425.881-17","***.425.881-**","881.425.881-17","***.425.881-**"],["457.168.957-86","***.168.957-**","457.168.957-86","***.168.957-**"],["351.634.044-80","***.634.044-**","351.634.044-80","***.634.044-**"],["929.957.774-99","***.957.774-**","929.957.774-99","***.957.774-**"],["177.100.071-88","***.100.071-**","177.100.071-88","***.100.071-**"],["358.717.487-81","***.717.487-**","358.717.487-81","***.717.487-**"],["255.702.956-10","***.702.956-**","255.702.956-10","***.702.956-**"],["040.468.850-75","***.468.850-**","040.468.850-75","***.468.850-**"],["731.444.456-06","***.444.456-**","731.444.456-06","***.444.456-**"],["750.868.805-80","***.868.805-**","750.868.805-80","***.868.805-**"],["036.703.555-55","***.703.555-**","036.703.555-55","***.703.555-**"],["02","**","000.000.000-02","***.000.000-**"],["434","***","000.000.004-34","***.000.004-**"],["597.289.431-07","***.289.431-**","597.289.431-07","***.289.431-**"],["408.030.882-56","***.030.882-**","408.030.882-56","***.030.882-**"],["370","***","000.000.003-70","***.000.003-**"],["570.494.603-87","***.494.603-**","570.494.603-87","***.494.603-**"],["420.245.272-09","***.245.272-**","420.245.272-09","***.245.272-**"],["502.245.874-36","***.245.874-**","502.245.874-36","***.245.874-**"],["336.899.764-56","***.899.764-**","336.899.764-56","***.899.764-**"],["632.398.678-77","***.398.678-**","632.398.678-77","***.398.678-**"],["030.141.084-48","***.141.084-**","030.141.084-48","***.141.084-**"],["301.735.498-71","***.735.498-**","301.735.498-71","***.735.498-**"],["539.452.483-43","***.452.483-**","539.452.483-43","***.452.483-**"],["534.166.811-18","***.166.811-**","534.166.811-18","***.166.811-**"],["724.499.788-44","***.499.788-**","724.499.788-44","***.499.788-**"],["452.774.441-06","***.774.441-**","452.774.441-06","***.774.441-**"],["400.862.625-56","***.862.625-**","400.862.625-56","***.862.625-**"],["552.051.1","***.051.1","000.055.205-11","***.055.205-**"],["547.125.980-77","***.125.980-**","547.125.980-77","***.125.980-**"],["112.280.143-40","***.280.143-**","112.280.143-40","***.280.143-**"],["199.847.108-07","***.847.108-**","199.847.108-07","***.847.108-**"],["870.242.758-39","***.242.758-**","870.242.758-39","***.242.758-**"],["400.334.102-31","***.334.102-**","400.334.102-31","***.334.102-**"],["130.261.041-40","***.261.041-**","130.261.041-40","***.261.041-**"],["934.397.986-07","***.397.986-**","934.397.986-07","***.397.986-**"],["795.471.379-21","***.471.379-**","795.471.379-21","***.471.379-**"],["065.860.261-64","***.860.261-**","065.860.261-64","***.860.261-**"],["306.484.222-67","***.484.222-**","306.484.222-67","***.484.222-**"],["747.322.998-22","***.322.998-**","747.322.998-22","***.322.998-**"],["787.515.594-04","***.515.594-**","787.515.594-04","***.515.594-**"],["773.715.871-99","***.715.871-**","773.715.871-99","***.715.871-**"],["232.013.727-70","***.013.727-**","232.013.727-70","***.013.727-**"],["485.288.272-59","***.288.272-**","485.288.272-59","***.288.272-**"],["630.982.355-90","***.982.355-**","630.982.355-90","***.982.355-**"],["446.810.140-79","***.810.140-**","446.810.140-79","***.810.140-**"],["447.264.0","***.264.0","000.044.726-40","***.044.726-**"],["181.921.991-77","***.921.991-**","181.921.991-77","***.921.991-**"],["367.269.745-59","***.269.745-**","367.269.745-59","***.269.745-**"],["781.648.170-58","***.648.170-**","781.648.170-58","***.648.170-**"],["863.758.171-71","***.758.171-**","863.758.171-71","***.758.171-**"],["570.244.727-04","***.244.727-**","570.244.727-04","***.244.727-**"],["028.243.085-96","***.243.085-**","028.243.085-96","***.243.085-**"],["252.5","***.5","000.000.025-25","***.000.025-**"],["494.879.424-40","***.879.424-**","494.879.424-40","***.879.424-**"],["39","**","000.000.000-39","***.000.000-**"],["016.056.606-52","***.056.606-**","016.056.606-52","***.056.606-**"],["984.608.992-92","***.608.992-**","984.608.992-92","***.608.992-**"],["310.489.787-53","***.489.787-**","310.489.787-53","***.489.787-**"],["413.380.722-06","***.380.722-**","413.380.722-06","***.380.722-**"],["992.920.113-08","***.920.113-**","992.920.113-08","***.920.113-**"],["630.314.739-36","***.314.739-**","630.314.739-36","***.314.739-**"],["380.767.579-50","***.767.579-**","380.767.579-50","***.767.579-**"],["056.798.024-30","***.798.024-**","056.798.024-30","***.798.024-**"],["633.410.263-62","***.410.263-**","633.410.263-62","***.410.263-**"],["665.382.991","***.382.991","006.653.829-91","***.653.829-**"],["304.149.500-70","***.149.500-**","304.149.500-70","***.149.500-**"],["324.611.403","***.611.403","003.246.114-03","***.246.114-**"],["421.237.805-22","***.237.805-**","421.237.805-22","***.237.805-**"],["062.361.525-71","***.361.525-**","062.361.525-71","***.361.525-**"],["821.535.788-17","***.535.788-**","821.535.788-17","***.535.788-**"],["360.451.292-67","***.451.292-**","360.451.292-67","***.451.292-**"],["099.987.523-43","***.987.523-**","099.987.523-43","***.987.523-**"],["585.368.188-59","***.368.188-**","585.368.188-59","***.368.188-**"],["665.405.362-64","***.405.362-**","665.405.362-64","***.405.362-**"],["457.879.690-65","***.879.690-**","457.879.690-65","***.879.690-**"],["423.6","***.6","000.000.042-36","***.000.042-**"],["420.501.736-79","***.501.736-**","420.501.736-79","***.501.736-**"],["856.920.783-25","***.920.783-**","856.920.783-25","***.920.783-**"],["561.363.0","***.363.0","000.056.136-30","***.056.136-**"],["038.558.056-87","***.558.056-**","038.558.056-87","***.558.056-**"],["317.930.369-77","***.930.369-**","317.930.369-77","***.930.369-**"],["928.267.842-18","***.267.842-**","928.267.842-18","***.267.842-**"],["991.361.901-79","***.361.901-**","991.361.901-79","***.361.901-**"],["336.471.612-02","***.471.612-**","336.471.612-02","***.471.612-**"],["047.455.25","***.455.25","000.047.455-25","***.047.455-**"],["654.592.183-65","***.592.183-**","654.592.183-65","***.592.183-**"],["703.896.668-58","***.896.668-**","703.896.668-58","***.896.668-**"],["624.884.800-96","***.884.800-**","624.884.800-96","***.884.800-**"],["665.946.782-30","***.946.782-**","665.946.782-30","***.946.782-**"],["450.021.061-8","***.021.061-*","045.002.106-18","***.002.106-**"],["765.801.223-82","***.801.223-**","765.801.223-82","***.801.223-**"],["661.220.012-01","***.220.012-**","661.220.012-01","***.220.012-**"],["268.260.103-05","***.260.103-**","268.260.103-05","***.260.103-**"],["571.423.851-51","***.423.851-**","571.423.851-51","***.423.851-**"],["535.748.724-43","***.748.724-**","535.748.724-43","***.748.724-**"],["472.362.195-41","***.362.195-**","472.362.195-41","***.362.195-**"],["405.496.876-70","***.496.876-**","405.496.876-70","***.496.876-**"],["901.416.293-69","***.416.293-**","901.416.293-69","***.416.293-**"],["702.239.867-47","***.239.867-**","702.239.867-47","***.239.867-**"],["903.341.000-11","***.341.000-**","903.341.000-11","***.341.000-**"],["045.185.149-70","***.185.149-**","045.185.149-70","***.185.149-**"],["935.447.043-63","***.447.043-**","935.447.043-63","***.447.043-**"],["763.868.012-02","***.868.012-**","763.868.012-02","***.868.012-**"],["863.056.615-12","***.056.615-**","863.056.615-12","***.056.615-**"],["531.111.785-01","***.111.785-**","531.111.785-01","***.111.785-**"],["357.721.042-76","***.721.042-**","357.721.042-76","***.721.042-**"],["489.519.110-98","***.519.110-**","489.519.110-98","***.519.110-**"],["199.010.914-46","***.010.914-**","199.010.914-46","***.010.914-**"],["630.136.127-98","***.136.127-**","630.136.127-98","***.136.127-**"],["719.146.565-29","***.146.565-**","719.146.565-29","***.146.565-**"],["446.176.547-47","***.176.547-**","446.176.547-47","***.176.547-**"],["964.911.939-69","***.911.939-**","964.911.939-69","***.911.939-**"],["615.41","***.41","000.000.615-41","***.000.615-**"],["958.058.697-07","***.058.697-**","958.058.697-07","***.058.697-**"],["299.013.462-05","***.013.462-**","299.013.462-05","***.013.462-**"],["542.085.199-75","***.085.199-**","542.085.199-75","***.085.199-**"],["875.536.812-95","***.536.812-**","875.536.812-95","***.536.812-**"],["369.881.082-17","***.881.082-**","369.881.082-17","***.881.082-**"],["535.419.4","***.419.4","000.053.541-94","***.053.541-**"],["453.175.172-01","***.175.172-**","453.175.172-01","***.175.172-**"],["677.552.701-60","***.552.701-**","677.552.701-60","***.552.701-**"],["928.798.18","***.798.18","000.928.798-18","***.928.798-**"],["989.660.605-21","***.660.605-**","989.660.605-21","***.660.605-**"],["981.145.242-35","***.145.242-**","981.145.242-35","***.145.242-**"],["629","***","000.000.006-29","***.000.006-**"],["772.375.600-4","***.375.600-*","077.237.560-04","***.237.560-**"],["645.487.125-88","***.487.125-**","645.487.125-88","***.487.125-**"],["894.996.977-68","***.996.977-**","894.996.977-68","***.996.977-**"],["648.075.310-71","***.075.310-**","648.075.310-71","***.075.310-**"],["415.526.159-60","***.526.159-**","415.526.159-60","***.526.159-**"],["029.074.725-98","***.074.725-**","029.074.725-98","***.074.725-**"],["614.475.886-40","***.475.886-**","614.475.886-40","***.475.886-**"],["462.866.244-49","***.866.244-**","462.866.244-49","***.866.244-**"],["289.972.791-57","***.972.791-**","289.972.791-57","***.972.791-**"],["927.697.844-0","***.697.844-*","092.769.784-40","***.769.784-**"],["124.180.278-79","***.180.278-**","124.180.278-79","***.180.278-**"],["005.760.594","***.760.594","000.057.605-94","***.057.605-**"],["838.717.878-84","***.717.878-**","838.717.878-84","***.717.878-**"],["186.291.806-68","***.291.806-**","186.291.806-68","***.291.806-**"],["625.765.938-77","***.765.938-**","625.765.938-77","***.765.938-**"],["686.752.569-98","***.752.569-**","686.752.569-98","***.752.569-**"],["626.822.781-59","***.822.781-**","626.822.781-59","***.822.781-**"],["053.766.513-71","***.766.513-**","053.766.513-71","***.766.513-**"],["156.246.414-71","***.246.414-**","156.246.414-71","***.246.414-**"],["553.973.682-61","***.973.682-**","553.973.682-61","***.973.682-**"],["946.976.798-27","***.976.798-**","946.976.798-27","***.976.798-**"],["593.430.107-10","***.430.107-**","593.430.107-10","***.430.107-**"],["969.887.973-00","***.887.973-**","969.887.973-00","***.887.973-**"],["687.415.410-90","***.415.410-**","687.415.410-90","***.415.410-**"],["815.457.912-01","***.457.912-**","815.457.912-01","***.457.912-**"],["064.302.049-77","***.302.049-**","064.302.049-77","***.302.049-**"],["650.787.574-06","***.787.574-**","650.787.574-06","***.787.574-**"],["951.134.221-95","***.134.221-**","951.134.221-95","***.134.221-**"],["286.444.663-75","***.444.663-**","286.444.663-75","***.444.663-**"],["633.698","***.698","000.006.336-98","***.006.336-**"],["093.231.574-44","***.231.574-**","093.231.574-44","***.231.574-**"],["532.340.996-91","***.340.996-**","532.340.996-91","***.340.996-**"],["014.371.442-49","***.371.442-**","014.371.442-49","***.371.442-**"],["297.152.899-32","***.152.899-**","297.152.899-32","***.152.899-**"],["181.667.281-50","***.667.281-**","181.667.281-50","***.667.281-**"],["276.355.413-70","***.355.413-**","276.355.413-70","***.355.413-**"],["946.227.363-49","***.227.363-**","946.227.363-49","***.227.363-**"],["300.863.936-32","***.863.936-**","300.863.936-32","***.863.936-**"],["999.201.836-42","***.201.836-**","999.201.836-42","***.201.836-**"],["176.844.103-00","***.844.103-**","176.844.103-00","***.844.103-**"],["727.207.049-09","***.207.049-**","727.207.049-09","***.207.049-**"],["082.906.410-95","***.906.410-**","082.906.410-95","***.906.410-**"],["731.651.380-13","***.651.380-**","731.651.380-13","***.651.380-**"],["217.237.806-26","***.237.806-**","217.237.806-26","***.237.806-**"],["827.609.844-38","***.609.844-**","827.609.844-38","***.609.844-**"],["085.527.568-87","***.527.568-**","085.527.568-87","***.527.568-**"],["562.679.855-20","***.679.855-**","562.679.855-20","***.679.855-**"],["620.620.594-24","***.620.594-**","620.620.594-24","***.620.594-**"],["143.537.083-09","***.537.083-**","143.537.083-09","***.537.083-**"],["201.976.169-68","***.976.169-**","201.976.169-68","***.976.169-**"],["909.705.007-34","***.705.007-**","909.705.007-34","***.705.007-**"],["319.798.674-52","***.798.674-**","319.798.674-52","***.798.674-**"],["667.813.392-73","***.813.392-**","667.813.392-73","***.813.392-**"],["554.941.641-79","***.941.641-**","554.941.641-79","***.941.641-**"],["137.397.285-30","***.397.285-**","137.397.285-30","***.397.285-**"],["220.158.060-08","***.158.060-**","220.158.060-08","***.158.060-**"],["568.253.976-64","***.253.976-**","568.253.976-64","***.253.976-**"],["660.146","***.146","000.006.601-46","***.006.601-**"],["314.325.976-04","***.325.976-**","314.325.976-04","***.325.976-**"],["907.713.125-63","***.713.125-**","907.713.125-63","***.713.125-**"],["293.899.120-75","***.899.120-**","293.899.120-75","***.899.120-**"],["381.997.951-31","***.997.951-**","381.997.951-31","***.997.951-**"],["526.227.313","***.227.313","005.262.273-13","***.262.273-**"],["907.003.849-87","***.003.849-**","907.003.849-87","***.003.849-**"],["056.219.569-66","***.219.569-**","056.219.569-66","***.219.569-**"],["774.816.952-2","***.816.952-*","077.481.695-22","***.481.695-**"],["238.130.641-23","***.130.641-**","238.130.641-23","***.130.641-**"],["783.050.225-01","***.050.225-**","783.050.225-01","***.050.225-**"],["256.230.742-94","***.230.742-**","256.230.742-94","***.230.742-**"],["413.205.772-02","***.205.772-**","413.205.772-02","***.205.772-**"],["715.364.393-12","***.364.393-**","715.364.393-12","***.364.393-**"],["954.980.101-25","***.980.101-**","954.980.101-25","***.980.101-**"],["727.64","***.64","000.000.727-64","***.000.727-**"],["215.096.067-26","***.096.067-**","215.096.067-26","***.096.067-**"],["043.397.524-60","***.397.524-**","043.397.524-60","***.397.524-**"],["003.464.247-12","***.464.247-**","003.464.247-12","***.464.247-**"],["375.851.644-78","***.851.644-**","375.851.644-78","***.851.644-**"],["747.006.686-60","***.006.686-**","747.006.686-60","***.006.686-**"],["663.120.873-44","***.120.873-**","663.120.873-44","***.120.873-**"],["968.838.733-67","***.838.733-**","968.838.733-67","***.838.733-**"],["619.553.344-60","***.553.344-**","619.553.344-60","***.553.344-**"],["018.549.088-28","***.549.088-**","018.549.088-28","***.549.088-**"],["477.726.331-49","***.726.331-**","477.726.331-49","***.726.331-**"],["013.976.078-40","***.976.078-**","013.976.078-40","***.976.078-**"],["115.566.696-82","***.566.696-**","115.566.696-82","***.566.696-**"],["418.261.658-86","***.261.658-**","418.261.658-86","***.261.658-**"],["278.014.819-50","***.014.819-**","278.014.819-50","***.014.819-**"],["846.744.291-37","***.744.291-**","846.744.291-37","***.744.291-**"],["943.177.878-11","***.177.878-**","943.177.878-11","***.177.878-**"],["506.237.791-33","***.237.791-**","506.237.791-33","***.237.791-**"],["405.848.479-98","***.848.479-**","405.848.479-98","***.848.479-**"],["449.434.963-02","***.434.963-**","449.434.963-02","***.434.963-**"],["032.910.6","***.910.6","000.003.291-06","***.003.291-**"],["951.962.785-59","***.962.785-**","951.962.785-59","***.962.785-**"],["926.018.824-50","***.018.824-**","926.018.824-50","***.018.824-**"],["500.155.124-07","***.155.124-**","500.155.124-07","***.155.124-**"],["106.387.260-82","***.387.260-**","106.387.260-82","***.387.260-**"],["901.903.678-35","***.903.678-**","901.903.678-35","***.903.678-**"],["211.172.598-56","***.172.598-**","211.172.598-56","***.172.598-**"],["258.825.959-67","***.825.959-**","258.825.959-67","***.825.959-**"],["047.323.834-91","***.323.834-**","047.323.834-91","***.323.834-**"],["947.996.99","***.996.99","000.947.996-99","***.947.996-**"],["959.226.698-00","***.226.698-**","959.226.698-00","***.226.698-**"],["888.306.156-09","***.306.156-**","888.306.156-09","***.306.156-**"],["328.501.307-96","***.501.307-**","328.501.307-96","***.501.307-**"],["779.741.508-92","***.741.508-**","779.741.508-92","***.741.508-**"],["296.595.351-86","***.595.351-**","296.595.351-86","***.595.351-**"],["49","**","000.000.000-49","***.000.000-**"],["157.908.729-76","***.908.729-**","157.908.729-76","***.908.729-**"],["582.606.698-97","***.606.698-**","582.606.698-97","***.606.698-**"],["913.298.091-05","***.298.091-**","913.298.091-05","***.298.091-**"],["567.710.319-50","***.710.319-**","567.710.319-50","***.710.319-**"],["143.982.512-27","***.982.512-**","143.982.512-27","***.982.512-**"],["258.242.962-10","***.242.962-**","258.242.962-10","***.242.962-**"],["563.146.218-44","***.146.218-**","563.146.218-44","***.146.218-**"],["948.768.132-77","***.768.132-**","948.768.132-77","***.768.132-**"],["162.636.601-20","***.636.601-**","162.636.601-20","***.636.601-**"],["700.717.621-67","***.717.621-**","700.717.621-67","***.717.621-**"],["684.050.276-3","***.050.276-*","068.405.027-63","***.405.027-**"],["154.249.497-90","***.249.497-**","154.249.497-90","***.249.497-**"],["819.153.669","***.153.669","008.191.536-69","***.191.536-**"],["253.714.919-07","***.714.919-**","253.714.919-07","***.714.919-**"],["755.329.256-88","***.329.256-**","755.329.256-88","***.329.256-**"],["344.934.705-50","***.934.705-**","344.934.705-50","***.934.705-**"],["706.514.130-20","***.514.130-**","706.514.130-20","***.514.130-**"],["641.863.190-06","***.863.190-**","641.863.190-06","***.863.190-**"],["362.380.666-31","***.380.666-**","362.380.666-31","***.380.666-**"],["877.662.318-79","***.662.318-**","877.662.318-79","***.662.318-**"],["785.072.001-68","***.072.001-**","785.072.001-68","***.072.001-**"],["975.400.869-80","***.400.869-**","975.400.869-80","***.400.869-**"],["694.265.755-95","***.265.755-**","694.265.755-95","***.265.755-**"],["717.054.033-95","***.054.033-**","717.054.033-95","***.054.033-**"],["400.574.566-22","***.574.566-**","400.574.566-22","***.574.566-**"],["162.157.780-52","***.157.780-**","162.157.780-52","***.157.780-**"],["907.606.733-30","***.606.733-**","907.606.733-30","***.606.733-**"],["210.567.501-89","***.567.501-**","210.567.501-89","***.567.501-**"],["648.530.102-06","***.530.102-**","648.530.102-06","***.530.102-**"],["959.760.100-00","***.760.100-**","959.760.100-00","***.760.100-**"],["902.599.434-28","***.599.434-**","902.599.434-28","***.599.434-**"],["466.255.007-98","***.255.007-**","466.255.007-98","***.255.007-**"],["988.450.455-80","***.450.455-**","988.450.455-80","***.450.455-**"],["428.615.384-30","***.615.384-**","428.615.384-30","***.615.384-**"],["715.215.383-36","***.215.383-**","715.215.383-36","***.215.383-**"],["637","***","000.000.006-37","***.000.006-**"],["654.118.778-90","***.118.778-**","654.118.778-90","***.118.778-**"],["202.246.587-56","***.246.587-**","202.246.587-56","***.246.587-**"],["836.602.272-26","***.602.272-**","836.602.272-26","***.602.272-**"],["410.966.244-24","***.966.244-**","410.966.244-24","***.966.244-**"],["201.995.522-90","***.995.522-**","201.995.522-90","***.995.522-**"],["432.909.519-01","***.909.519-**","432.909.519-01","***.909.519-**"],["910.372.437-84","***.372.437-**","910.372.437-84","***.372.437-**"],["454.262.099-85","***.262.099-**","454.262.099-85","***.262.099-**"],["397.040.328-62","***.040.328-**","397.040.328-62","***.040.328-**"],["647.635.595-32","***.635.595-**","647.635.595-32","***.635.595-**"],["906.337.251-53","***.337.251-**","906.337.251-53","***.337.251-**"],["698.051.932-91","***.051.932-**","698.051.932-91","***.051.932-**"],["047.855.570-86","***.855.570-**","047.855.570-86","***.855.570-**"],["496.125.887-32","***.125.887-**","496.125.887-32","***.125.887-**"],["79","**","000.000.000-79","***.000.000-**"],["661.389.847-30","***.389.847-**","661.389.847-30","***.389.847-**"],["555.573.365-05","***.573.365-**","555.573.365-05","***.573.365-**"],["759.327.762-34","***.327.762-**","759.327.762-34","***.327.762-**"],["357.341.606-36","***.341.606-**","357.341.606-36","***.341.606-**"],["683.674.555-05","***.674.555-**","683.674.555-05","***.674.555-**"],["435.998.744-34","***.998.744-**","435.998.744-34","***.998.744-**"],["119.815.225-51","***.815.225-**","119.815.225-51","***.815.225-**"],["465.381.059-58","***.381.059-**","465.381.059-58","***.381.059-**"],["452.491.864-11","***.491.864-**","452.491.864-11","***.491.864-**"],["774.583.134-65","***.583.134-**","774.583.134-65","***.583.134-**"],["007.988.956-59","***.988.956-**","007.988.956-59","***.988.956-**"],["770.041.332-67","***.041.332-**","770.041.332-67","***.041.332-**"],["422.878","***.878","000.004.228-78","***.004.228-**"],["461.7","***.7","000.000.046-17","***.000.046-**"],["063.867.366-9","***.867.366-*","006.386.736-69","***.386.736-**"],["773.952.044-68","***.952.044-**","773.952.044-68","***.952.044-**"],["134.194.178-70","***.194.178-**","134.194.178-70","***.194.178-**"],["306.886.572-17","***.886.572-**","306.886.572-17","***.886.572-**"],["430.760.450-33","***.760.450-**","430.760.450-33","***.760.450-**"],["454.204.688-62","***.204.688-**","454.204.688-62","***.204.688-**"],["477.135.945-87","***.135.945-**","477.135.945-87","***.135.945-**"],["982.999.941-47","***.999.941-**","982.999.941-47","***.999.941-**"],["472.748.728-42","***.748.728-**","472.748.728-42","***.748.728-**"],["102.790.993-04","***.790.993-**","102.790.993-04","***.790.993-**"],["637.357.458-00","***.357.458-**","637.357.458-00","***.357.458-**"],["960.107.623-14","***.107.623-**","960.107.623-14","***.107.623-**"],["432.231.701-46","***.231.701-**","432.231.701-46","***.231.701-**"],["907.324.900-86","***.324.900-**","907.324.900-86","***.324.900-**"],["811.065.107-90","***.065.107-**","811.065.107-90","***.065.107-**"],["369.026.490-01","***.026.490-**","369.026.490-01","***.026.490-**"],["361.337.639-30","***.337.639-**","361.337.639-30","***.337.639-**"],["955.242.299-07","***.242.299-**","955.242.299-07","***.242.299-**"],["604.869.323-03","***.869.323-**","604.869.323-03","***.869.323-**"],["486.225.998-76","***.225.998-**","486.225.998-76","***.225.998-**"],["383.544.884-62","***.544.884-**","383.544.884-62","***.544.884-**"],["102.372.946-64","***.372.946-**","102.372.946-64","***.372.946-**"],["462.605.225-52","***.605.225-**","462.605.225-52","***.605.225-**"],["821.181.107-09","***.181.107-**","821.181.107-09","***.181.107-**"],["254.240.624-31","***.240.624-**","254.240.624-31","***.240.624-**"],["574.115.293-70","***.115.293-**","574.115.293-70","***.115.293-**"],["496.403.407-87","***.403.407-**","496.403.407-87","***.403.407-**"],["624.559.899-09","***.559.899-**","624.559.899-09","***.559.899-**"],["088.404.860-6","***.404.860-*","008.840.486-06","***.840.486-**"],["672.144.590-51","***.144.590-**","672.144.590-51","***.144.590-**"],["867.308.594-33","***.308.594-**","867.308.594-33","***.308.594-**"],["419.229.800-72","***.229.800-**","419.229.800-72","***.229.800-**"],["573.830.433-08","***.830.433-**","573.830.433-08","***.830.433-**"],["015.046.727-60","***.046.727-**","015.046.727-60","***.046.727-**"],["632.986.859-54","***.986.859-**","632.986.859-54","***.986.859-**"],["099.004.253-75","***.004.253-**","099.004.253-75","***.004.253-**"],["666.945.791-09","***.945.791-**","666.945.791-09","***.945.791-**"],["042.576.132-03","***.576.132-**","042.576.132-03","***.576.132-**"],["276.620.013-21","***.620.013-**","276.620.013-21","***.620.013-**"],["456.176.758-48","***.176.758-**","456.176.758-48","***.176.758-**"],["312.865.583-95","***.865.583-**","312.865.583-95","***.865.583-**"],["607.810.734-17","***.810.734-**","607.810.734-17","***.810.734-**"],["137.822.691-79","***.822.691-**","137.822.691-79","***.822.691-**"],["462.018.915-49","***.018.915-**","462.018.915-49","***.018.915-**"],["723.806.315-44","***.806.315-**","723.806.315-44","***.806.315-**"],["106.643.861-29","***.643.861-**","106.643.861-29","***.643.861-**"],["517.968.463-02","***.968.463-**","517.968.463-02","***.968.463-**"],["280.759.517-00","***.759.517-**","280.759.517-00","***.759.517-**"],["096.512.655-23","***.512.655-**","096.512.655-23","***.512.655-**"],["76","**","000.000.000-76","***.000.000-**"],["102.292.357-94","***.292.357-**","102.292.357-94","***.292.357-**"],["926.051.569-66","***.051.569-**","926.051.569-66","***.051.569-**"],["796.930.251-63","***.930.251-**","796.930.251-63","***.930.251-**"],["242.474.869-18","***.474.869-**","242.474.869-18","***.474.869-**"],["250.5","***.5","000.000.025-05","***.000.025-**"],["346.637.685-80","***.637.685-**","346.637.685-80","***.637.685-**"],["030.866.084-63","***.866.084-**","030.866.084-63","***.866.084-**"],["393.780.258-46","***.780.258-**","393.780.258-46","***.780.258-**"],["271.806.324-28","***.806.324-**","271.806.324-28","***.806.324-**"],["809.664.993-6","***.664.993-*","080.966.499-36","***.966.499-**"]],"strict-or-null":[[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],["123.456.789-09","123.456.789-09","123.456.789-09","123.456.789-09"],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],["275.026.776-58","275.026.776-58","275.026.776-58","275.026.776-58"],[null,null,null,null],["455.287.462-48","455.287.462-48","455.287.462-48","455.287.462-48"],["001.925.910-70","001.925.910-70","001.925.910-70","001.925.910-70"],[null,null,null,null],["043.493.162-48","043.493.162-48","043.493.162-48","043.493.162-48"],["058.280.337-35","058.280.337-35","058.280.337-35","058.280.337-35"],[null,null,null,null],[null,null,null,null],["459.609.678-39","459.609.678-39","459.609.678-39","459.609.678-39"],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],["656.235.973-27","656.235.973-27","656.235.973-27","656.235.973-27"],["082.162.626-47","082.162.626-47","082.162.626-47","082.162.626-47"],["942.914.972-53","942.914.972-53","942.914.972-53","942.914.972-53"],["655.466.786-58","655.466.786-58","655.466.786-58","655.466.786-58"],["022.180.106-58","022.180.106-58","022.180.106-58","022.180.106-58"],["134.346.089-15","134.346.089-15","134.346.089-15","134.346.089-15"],[null,null,null,null],[null,null,null,null],[null,null,null,null],["290.227.963-96","290.227.963-96","290.227.963-96","290.227.963-96"],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],["067.339.637-10","067.339.637-10","067.339.637-10","067.339.637-10"],[null,null,null,null],[null,null,null,null],[null,null,null,null],["489.381.054-58","489.381.054-58","489.381.054-58","489.381.054-58"],["520.705.644-10","520.705.644-10","520.705.644-10","520.705.644-10"],[null,null,null,null],["971.165.013-47","971.165.013-47","971.165.013-47","971.165.013-47"],[null,null,null,null],[null,null,null,null],[null,null,null,null],["326.057.798-07","326.057.798-07","326.057.798-07","326.057.798-07"],[null,null,null,null],["601.502.471-25","601.502.471-25","601.502.471-25","601.502.471-25"],["717.708.895-40","717.708.895-40","717.708.895-40","717.708.895-40"],[null,null,null,null],[null,null,null,null],["137.656.313-45","137.656.313-45","137.656.313-45","137.656.313-45"],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],["253.681.039-99","253.681.039-99","253.681.039-99","253.681.039-99"],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],["327.117.213-70","327.117.213-70","327.117.213-70","327.117.213-70"],[null,null,null,null],[null,null,null,null],["401.109.658-09","401.109.658-09","401.109.658-09","401.109.658-09"],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],["946.220.892-11","946.220.892-11","946.220.892-11","946.220.892-11"],[null,null,null,null],[null,null,null,null],["309.534.527-51","309.534.527-51","309.534.527-51","309.534.527-51"],[null,null,null,null],[null,null,null,null],["103.597.230-12","103.597.230-12","103.597.230-12","103.597.230-12"],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],["517.236.689-07","517.236.689-07","517.236.689-07","517.236.689-07"],[null,null,null,null],[null,null,null,null],["299.724.486-22","299.724.486-22","299.724.486-22","299.724.486-22"],[null,null,null,null],[null,null,null,null],[null,null,null,null],["638.764.089-03","638.764.089-03","638.764.089-03","638.764.089-03"],[null,null,null,null],["533.678.958-57","533.678.958-57","533.678.958-57","533.678.958-57"],[null,null,null,null],["324.988.564-98","324.988.564-98","324.988.564-98","324.988.564-98"],["365.588.462-17","365.588.462-17","365.588.462-17","365.588.462-17"],["261.475.992-91","261.475.992-91","261.475.992-91","261.475.992-91"],[null,null,null,null],[null,null,null,null],["939.710.336-95","939.710.336-95","939.710.336-95","939.710.336-95"],[null,null,null,null],["384.762.726-00","384.762.726-00","384.762.726-00","384.762.726-00"],[null,null,null,null],[null,null,null,null],["591.394.668-50","591.394.668-50","591.394.668-50","591.394.668-50"],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],["409.109.630-10","409.109.630-10","409.109.630-10","409.109.630-10"],[null,null,null,null],["837.234.185-03","837.234.185-03","837.234.185-03","837.234.185-03"],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],["849.112.629-58","849.112.629-58","849.112.629-58","849.112.629-58"],[null,null,null,null],["892.059.852-52","892.059.852-52","892.059.852-52","892.059.852-52"],["054.960.534-71","054.960.534-71","054.960.534-71","054.960.534-71"],["525.973.933-72","525.973.933-72","525.973.933-72","525.973.933-72"],["386.522.205-65","386.522.205-65","386.522.205-65","386.522.205-65"],[null,null,null,null],["222.790.475-51","222.790.475-51","222.790.475-51","222.790.475-51"],[null,null,null,null],["541.300.827-95","541.300.827-95","541.300.827-95","541.300.827-95"],[null,null,null,null],[null,null,null,null],[null,null,null,null],["589.768.017-50","589.768.017-50","589.768.017-50","589.768.017-50"],["206.487.406-25","206.487.406-25","206.487.406-25","206.487.406-25"],[null,null,null,null],[null,null,null,null],[null,null,null,null],["749.949.997-91","749.949.997-91","749.949.997-91","749.949.997-91"],[null,null,null,null],[null,null,null,null],[null,null,null,null],["626.103.959-30","626.103.959-30","626.103.959-30","626.103.959-30"],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],["495.454.403-33","495.454.403-33","495.454.403-33","495.454.403-33"],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],["140.796.801-71","140.796.801-71","140.796.801-71","140.796.801-71"],[null,null,null,null],[null,null,null,null],["438.557.083-39","438.557.083-39","438.557.083-39","438.557.083-39"],[null,null,null,null],["668.462.685-96","668.462.685-96","668.462.685-96","668.462.685-96"],[null,null,null,null],["127.109.736-26","127.109.736-26","127.109.736-26","127.109.736-26"],[null,null,null,null],[null,null,null,null],[null,null,null,null],["968.751.151-66","968.751.151-66","968.751.151-66","968.751.151-66"],[null,null,null,null],["310.923.973-61","310.923.973-61","310.923.973-61","310.923.973-61"],[null,null,null,null],["381.469.865-79","381.469.865-79","381.469.865-79","381.469.865-79"],[null,null,null,null],[null,null,null,null],[null,null,null,null],["503.734.632-00","503.734.632-00","503.734.632-00","503.734.632-00"],[null,null,null,null],[null,null,null,null],[null,null,null,null],["847.859.775-15","847.859.775-15","847.859.775-15","847.859.775-15"],[null,null,null,null],["905.346.609-67","905.346.609-67","905.346.609-67","905.346.609-67"],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],["451.858.175-00","451.858.175-00","451.858.175-00","451.858.175-00"],[null,null,null,null],[null,null,null,null],["489.869.813-19","489.869.813-19","489.869.813-19","489.869.813-19"],[null,null,null,null],["128.473.716-05","128.473.716-05","128.473.716-05","128.473.716-05"],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],["946.809.205-48","946.809.205-48","946.809.205-48","946.809.205-48"],[null,null,null,null],[null,null,null,null],[null,null,null,null],["713.273.603-57","713.273.603-57","713.273.603-57","713.273.603-57"],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],["199.297.039-42","199.297.039-42","199.297.039-42","199.297.039-42"],["651.349.831-78","651.349.831-78","651.349.831-78","651.349.831-78"],[null,null,null,null],[null,null,null,null],[null,null,null,null],["011.046.125-85","011.046.125-85","011.046.125-85","011.046.125-85"],[null,null,null,null],[null,null,null,null],[null,null,null,null],["128.573.303-75","128.573.303-75","128.573.303-75","128.573.303-75"],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],["658.458.062-83","658.458.062-83","658.458.062-83","658.458.062-83"],[null,null,null,null],["912.465.249-02","912.465.249-02","912.465.249-02","912.465.249-02"],[null,null,null,null],["060.728.299-10","060.728.299-10","060.728.299-10","060.728.299-10"],[null,null,null,null],["918.220.826-33","918.220.826-33","918.220.826-33","918.220.826-33"],[null,null,null,null],["245.846.481-58","245.846.481-58","245.846.481-58","245.846.481-58"],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],["701.164.557-80","701.164.557-80","701.164.557-80","701.164.557-80"],[null,null,null,null],["631.085.833-52","631.085.833-52","631.085.833-52","631.085.833-52"],[null,null,null,null],["996.655.903-59","996.655.903-59","996.655.903-59","996.655.903-59"],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],["866.763.984-27","866.763.984-27","866.763.984-27","866.763.984-27"],[null,null,null,null],[null,null,null,null],[null,null,null,null],["540.418.281-47","540.418.281-47","540.418.281-47","540.418.281-47"],["819.392.325-11","819.392.325-11","819.392.325-11","819.392.325-11"],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],["900.949.621-03","900.949.621-03","900.949.621-03","900.949.621-03"],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],["805.313.864-06","805.313.864-06","805.313.864-06","805.313.864-06"],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],["674.899.794-12","674.899.794-12","674.899.794-12","674.899.794-12"],["116.809.196-95","116.809.196-95","116.809.196-95","116.809.196-95"],[null,null,null,null],["299.275.353-09","299.275.353-09","299.275.353-09","299.275.353-09"],["688.163.203-70","688.163.203-70","688.163.203-70","688.163.203-70"],[null,null,null,null],["495.931.279-33","495.931.279-33","495.931.279-33","495.931.279-33"],["777.911.178-43","777.911.178-43","777.911.178-43","777.911.178-43"],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],["332.123.446-79","332.123.446-79","332.123.446-79","332.123.446-79"],["777.620.413-70","777.620.413-70","777.620.413-70","777.620.413-70"],["953.735.104-16","953.735.104-16","953.735.104-16","953.735.104-16"],[null,null,null,null],[null,null,null,null],["932.068.398-07","932.068.398-07","932.068.398-07","932.068.398-07"],[null,null,null,null],["270.027.530-61","270.027.530-61","270.027.530-61","270.027.530-61"],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],["465.086.646-46","465.086.646-46","465.086.646-46","465.086.646-46"],[null,null,null,null],["035.849.498-23","035.849.498-23","035.849.498-23","035.849.498-23"],["829.765.743-40","829.765.743-40","829.765.743-40","829.765.743-40"],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],["826.748.097-87","826.748.097-87","826.748.097-87","826.748.097-87"],["327.827.816-00","327.827.816-00","327.827.816-00","327.827.816-00"],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],["797.749.251-22","797.749.251-22","797.749.251-22","797.749.251-22"],["452.943.389-71","452.943.389-71","452.943.389-71","452.943.389-71"],["677.156.778-84","677.156.778-84","677.156.778-84","677.156.778-84"],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],["457.168.957-86","457.168.957-86","457.168.957-86","457.168.957-86"],[null,null,null,null],["929.957.774-99","929.957.774-99","929.957.774-99","929.957.774-99"],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],["731.444.456-06","731.444.456-06","731.444.456-06","731.444.456-06"],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],["336.899.764-56","336.899.764-56","336.899.764-56","336.899.764-56"],[null,null,null,null],["030.141.084-48","030.141.084-48","030.141.084-48","030.141.084-48"],[null,null,null,null],[null,null,null,null],["534.166.811-18","534.166.811-18","534.166.811-18","534.166.811-18"],[null,null,null,null],["452.774.441-06","452.774.441-06","452.774.441-06","452.774.441-06"],["400.862.625-56","400.862.625-56","400.862.625-56","400.862.625-56"],[null,null,null,null],["547.125.980-77","547.125.980-77","547.125.980-77","547.125.980-77"],[null,null,null,null],["199.847.108-07","199.847.108-07","199.847.108-07","199.847.108-07"],["870.242.758-39","870.242.758-39","870.242.758-39","870.242.758-39"],[null,null,null,null],["130.261.041-40","130.261.041-40","130.261.041-40","130.261.041-40"],[null,null,null,null],["795.471.379-21","795.471.379-21","795.471.379-21","795.471.379-21"],["065.860.261-64","065.860.261-64","065.860.261-64","065.860.261-64"],["306.484.222-67","306.484.222-67","306.484.222-67","306.484.222-67"],[null,null,null,null],["787.515.594-04","787.515.594-04","787.515.594-04","787.515.594-04"],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],["181.921.991-77","181.921.991-77","181.921.991-77","181.921.991-77"],[null,null,null,null],["781.648.170-58","781.648.170-58","781.648.170-58","781.648.170-58"],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],["494.879.424-40","494.879.424-40","494.879.424-40","494.879.424-40"],[null,null,null,null],[null,null,null,null],["984.608.992-92","984.608.992-92","984.608.992-92","984.608.992-92"],[null,null,null,null],[null,null,null,null],["992.920.113-08","992.920.113-08","992.920.113-08","992.920.113-08"],[null,null,null,null],[null,null,null,null],["056.798.024-30","056.798.024-30","056.798.024-30","056.798.024-30"],[null,null,null,null],[null,null,null,null],["304.149.500-70","304.149.500-70","304.149.500-70","304.149.500-70"],[null,null,null,null],[null,null,null,null],[null,null,null,null],["821.535.788-17","821.535.788-17","821.535.788-17","821.535.788-17"],[null,null,null,null],[null,null,null,null],["585.368.188-59","585.368.188-59","585.368.188-59","585.368.188-59"],[null,null,null,null],["457.879.690-65","457.879.690-65","457.879.690-65","457.879.690-65"],[null,null,null,null],["420.501.736-79","420.501.736-79","420.501.736-79","420.501.736-79"],[null,null,null,null],[null,null,null,null],["038.558.056-87","038.558.056-87","038.558.056-87","038.558.056-87"],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],["703.896.668-58","703.896.668-58","703.896.668-58","703.896.668-58"],["624.884.800-96","624.884.800-96","624.884.800-96","624.884.800-96"],[null,null,null,null],[null,null,null,null],[null,null,null,null],["661.220.012-01","661.220.012-01","661.220.012-01","661.220.012-01"],["268.260.103-05","268.260.103-05","268.260.103-05","268.260.103-05"],[null,null,null,null],[null,null,null,null],["472.362.195-41","472.362.195-41","472.362.195-41","472.362.195-41"],["405.496.876-70","405.496.876-70","405.496.876-70","405.496.876-70"],[null,null,null,null],[null,null,null,null],["903.341.000-11","903.341.000-11","903.341.000-11","903.341.000-11"],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],["531.111.785-01","531.111.785-01","531.111.785-01","531.111.785-01"],["357.721.042-76","357.721.042-76","357.721.042-76","357.721.042-76"],[null,null,null,null],["199.010.914-46","199.010.914-46","199.010.914-46","199.010.914-46"],[null,null,null,null],[null,null,null,null],["446.176.547-47","446.176.547-47","446.176.547-47","446.176.547-47"],["964.911.939-69","964.911.939-69","964.911.939-69","964.911.939-69"],[null,null,null,null],[null,null,null,null],[null,null,null,null],["542.085.199-75","542.085.199-75","542.085.199-75","542.085.199-75"],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],["289.972.791-57","289.972.791-57","289.972.791-57","289.972.791-57"],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],["186.291.806-68","186.291.806-68","186.291.806-68","186.291.806-68"],[null,null,null,null],[null,null,null,null],[null,null,null,null],["053.766.513-71","053.766.513-71","053.766.513-71","053.766.513-71"],[null,null,null,null],["553.973.682-61","553.973.682-61","553.973.682-61","553.973.682-61"],[null,null,null,null],["593.430.107-10","593.430.107-10","593.430.107-10","593.430.107-10"],["969.887.973-00","969.887.973-00","969.887.973-00","969.887.973-00"],["687.415.410-90","687.415.410-90","687.415.410-90","687.415.410-90"],["815.457.912-01","815.457.912-01","815.457.912-01","815.457.912-01"],[null,null,null,null],["650.787.574-06","650.787.574-06","650.787.574-06","650.787.574-06"],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],["946.227.363-49","946.227.363-49","946.227.363-49","946.227.363-49"],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],["217.237.806-26","217.237.806-26","217.237.806-26","217.237.806-26"],[null,null,null,null],[null,null,null,null],["562.679.855-20","562.679.855-20","562.679.855-20","562.679.855-20"],[null,null,null,null],["143.537.083-09","143.537.083-09","143.537.083-09","143.537.083-09"],["201.976.169-68","201.976.169-68","201.976.169-68","201.976.169-68"],["909.705.007-34","909.705.007-34","909.705.007-34","909.705.007-34"],[null,null,null,null],[null,null,null,null],["554.941.641-79","554.941.641-79","554.941.641-79","554.941.641-79"],[null,null,null,null],["220.158.060-08","220.158.060-08","220.158.060-08","220.158.060-08"],[null,null,null,null],[null,null,null,null],[null,null,null,null],["907.713.125-63","907.713.125-63","907.713.125-63","907.713.125-63"],["293.899.120-75","293.899.120-75","293.899.120-75","293.899.120-75"],[null,null,null,null],[null,null,null,null],["907.003.849-87","907.003.849-87","907.003.849-87","907.003.849-87"],["056.219.569-66","056.219.569-66","056.219.569-66","056.219.569-66"],[null,null,null,null],["238.130.641-23","238.130.641-23","238.130.641-23","238.130.641-23"],["783.050.225-01","783.050.225-01","783.050.225-01","783.050.225-01"],[null,null,null,null],[null,null,null,null],["715.364.393-12","715.364.393-12","715.364.393-12","715.364.393-12"],["954.980.101-25","954.980.101-25","954.980.101-25","954.980.101-25"],[null,null,null,null],["215.096.067-26","215.096.067-26","215.096.067-26","215.096.067-26"],[null,null,null,null],["003.464.247-12","003.464.247-12","003.464.247-12","003.464.247-12"],[null,null,null,null],[null,null,null,null],["663.120.873-44","663.120.873-44","663.120.873-44","663.120.873-44"],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],["013.976.078-40","013.976.078-40","013.976.078-40","013.976.078-40"],[null,null,null,null],["418.261.658-86","418.261.658-86","418.261.658-86","418.261.658-86"],[null,null,null,null],["846.744.291-37","846.744.291-37","846.744.291-37","846.744.291-37"],[null,null,null,null],[null,null,null,null],["405.848.479-98","405.848.479-98","405.848.479-98","405.848.479-98"],[null,null,null,null],[null,null,null,null],["951.962.785-59","951.962.785-59","951.962.785-59","951.962.785-59"],["926.018.824-50","926.018.824-50","926.018.824-50","926.018.824-50"],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],["258.825.959-67","258.825.959-67","258.825.959-67","258.825.959-67"],["047.323.834-91","047.323.834-91","047.323.834-91","047.323.834-91"],[null,null,null,null],["959.226.698-00","959.226.698-00","959.226.698-00","959.226.698-00"],[null,null,null,null],["328.501.307-96","328.501.307-96","328.501.307-96","328.501.307-96"],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],["582.606.698-97","582.606.698-97","582.606.698-97","582.606.698-97"],[null,null,null,null],[null,null,null,null],["143.982.512-27","143.982.512-27","143.982.512-27","143.982.512-27"],[null,null,null,null],["563.146.218-44","563.146.218-44","563.146.218-44","563.146.218-44"],[null,null,null,null],["162.636.601-20","162.636.601-20","162.636.601-20","162.636.601-20"],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],["344.934.705-50","344.934.705-50","344.934.705-50","344.934.705-50"],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],["975.400.869-80","975.400.869-80","975.400.869-80","975.400.869-80"],[null,null,null,null],[null,null,null,null],[null,null,null,null],["162.157.780-52","162.157.780-52","162.157.780-52","162.157.780-52"],["907.606.733-30","907.606.733-30","907.606.733-30","907.606.733-30"],["210.567.501-89","210.567.501-89","210.567.501-89","210.567.501-89"],[null,null,null,null],[null,null,null,null],["902.599.434-28","902.599.434-28","902.599.434-28","902.599.434-28"],[null,null,null,null],[null,null,null,null],["428.615.384-30","428.615.384-30","428.615.384-30","428.615.384-30"],["715.215.383-36","715.215.383-36","715.215.383-36","715.215.383-36"],[null,null,null,null],["654.118.778-90","654.118.778-90","654.118.778-90","654.118.778-90"],[null,null,null,null],["836.602.272-26","836.602.272-26","836.602.272-26","836.602.272-26"],[null,null,null,null],[null,null,null,null],["432.909.519-01","432.909.519-01","432.909.519-01","432.909.519-01"],[null,null,null,null],[null,null,null,null],["397.040.328-62","397.040.328-62","397.040.328-62","397.040.328-62"],["647.635.595-32","647.635.595-32","647.635.595-32","647.635.595-32"],[null,null,null,null],[null,null,null,null],[null,null,null,null],["496.125.887-32","496.125.887-32","496.125.887-32","496.125.887-32"],[null,null,null,null],[null,null,null,null],[null,null,null,null],["759.327.762-34","759.327.762-34","759.327.762-34","759.327.762-34"],["357.341.606-36","357.341.606-36","357.341.606-36","357.341.606-36"],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],["134.194.178-70","134.194.178-70","134.194.178-70","134.194.178-70"],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],["472.748.728-42","472.748.728-42","472.748.728-42","472.748.728-42"],[null,null,null,null],[null,null,null,null],[null,null,null,null],["432.231.701-46","432.231.701-46","432.231.701-46","432.231.701-46"],[null,null,null,null],[null,null,null,null],[null,null,null,null],["361.337.639-30","361.337.639-30","361.337.639-30","361.337.639-30"],["955.242.299-07","955.242.299-07","955.242.299-07","955.242.299-07"],["604.869.323-03","604.869.323-03","604.869.323-03","604.869.323-03"],["486.225.998-76","486.225.998-76","486.225.998-76","486.225.998-76"],["383.544.884-62","383.544.884-62","383.544.884-62","383.544.884-62"],[null,null,null,null],[null,null,null,null],[null,null,null,null],["254.240.624-31","254.240.624-31","254.240.624-31","254.240.624-31"],["574.115.293-70","574.115.293-70","574.115.293-70","574.115.293-70"],[null,null,null,null],[null,null,null,null],[null,null,null,null],["672.144.590-51","672.144.590-51","672.144.590-51","672.144.590-51"],[null,null,null,null],["419.229.800-72","419.229.800-72","419.229.800-72","419.229.800-72"],[null,null,null,null],[null,null,null,null],[null,null,null,null],["099.004.253-75","099.004.253-75","099.004.253-75","099.004.253-75"],[null,null,null,null],["042.576.132-03","042.576.132-03","042.576.132-03","042.576.132-03"],[null,null,null,null],[null,null,null,null],["312.865.583-95","312.865.583-95","312.865.583-95","312.865.583-95"],[null,null,null,null],["137.822.691-79","137.822.691-79","137.822.691-79","137.822.691-79"],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],["280.759.517-00","280.759.517-00","280.759.517-00","280.759.517-00"],["096.512.655-23","096.512.655-23","096.512.655-23","096.512.655-23"],[null,null,null,null],[null,null,null,null],["926.051.569-66","926.051.569-66","926.051.569-66","926.051.569-66"],[null,null,null,null],["242.474.869-18","242.474.869-18","242.474.869-18","242.474.869-18"],[null,null,null,null],["346.637.685-80","346.637.685-80","346.637.685-80","346.637.685-80"],["030.866.084-63","030.866.084-63","030.866.084-63","030.866.084-63"],["393.780.258-46","393.780.258-46","393.780.258-46","393.780.258-46"],[null,null,null,null],[null,null,null,null]]}}}} diff --git a/vite.config.ts b/vite.config.ts index 341200a82..465c5737d 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -148,7 +148,9 @@ export default defineConfig({ // `reports` holds generated output only, the committed API Extractor baseline included: // reformatting its code block would make every `check:api` run report a changed API. // `CHANGELOG.md` is written by release-please (`* ` bullets); formatting it would fail the - // Check workflow on every release PR. + // Check workflow on every release PR. `spec/vectors` holds the generated conformance + // vectors, written on one line on purpose: pretty printing ~10k expectations would multiply + // the file size for a file nobody reads by hand. ignorePatterns: [ "dist", "coverage", @@ -157,6 +159,7 @@ export default defineConfig({ ".stryker-tmp", ".claude", "CHANGELOG.md", + "spec/vectors", ], singleQuote: false, sortImports: true, @@ -500,6 +503,23 @@ export default defineConfig({ "jsdoc/require-returns": "off", }, }, + { + env: { + node: true, + }, + files: ["spec/**/*.ts"], + rules: { + // The spec tooling is a set of command line programs: their output is the product. + "eslint/no-console": "off", + // `spec/conformance/upstream.ts` runs the other languages' own toolchains on purpose, + // from the developer's PATH, to compare this specification against the packages the + // organisation already publishes. + "sonarjs/no-os-command-from-path": "off", + // The generator reads the JSON files it writes itself, whose shape is pinned by + // `spec/schema/utility.schema.json`, so the parse results are asserted, not validated. + "typescript/no-unsafe-type-assertion": "off", + }, + }, { env: { node: true, From 983621fa72334de93b3b18fc9117a94a6212e8d4 Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 21 Sep 2026 00:18:42 +0000 Subject: [PATCH 02/13] docs(spec): measure bindings against generated source, in five languages MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Answers the follow up to the first exploration: could the logic live in one binary core — Rust, C, wasm — with every package binding to it instead of carrying generated source? `spec/BINDINGS-INVESTIGATION.md` is the write-up; `spec/bench` is the harness behind every number in it. Generated source wins. One validator, one corpus of 1000 inputs, the same profile in every arm: - generated source runs at 0.36x (Java), 0.43x (Go), 0.55x (Ruby), 0.56x (Python) and 0.66x (Node) of the idiomatic handwritten code it replaces; - UniFFI, the tool most often recommended for this, costs 9064 ns per call in Python — 3.7x slower than simply implementing the validator in Python, and 17x slower than the same shared library over hand written ctypes; - the boundary, not the work, is the cost: 104 ns per call in Go over wazero, 521 ns in Ruby, 472 ns over ctypes in Python, and 30059 ns over wasmtime-py, against a validator whose body takes about 100 ns; - batching one call over 1000 inputs makes a shared core fast everywhere (0.12x), which is the one workload where it earns its keep; - for the npm package a wasm core costs 9291 bytes against 509 for the generated `isValidCpf`, with no tree shaking and asynchronous startup. Two emitter rules make the source level result hold, and both are in this commit. Before them the Python and Ruby emitters walked strings code point by code point and were 2.6x and 4.1x slower than handwritten: - `guard-shape` plus `sanitize` collapse into one anchored regex with capture groups, with the character classes written out code point by code point so the semantics stay the spec's; - check digits are read as bytes and the verification is unrolled. Python went 6485 to 1366 ns/op and Ruby 15051 to 2020, with conformance unchanged at 2229/2229 for both and the JavaScript differential still at 11928/11928. The handwritten arms also disagree with the spec on the same corpus (Python 333, Ruby 329, Go 334 valid, against 337), each language's own `strip` being a different set of whitespace. Correctness is the reason to generate; the performance is what makes it affordable. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01UX1gTGeMTyoXQyr1qUoQKd --- .gitignore | 8 + spec/BINDINGS-INVESTIGATION.md | 276 ++++++++++ spec/README.md | 14 +- spec/bench/core/Cargo.lock | 7 + spec/bench/core/Cargo.toml | 15 + spec/bench/core/src/lib.rs | 223 ++++++++ spec/bench/corpus.json | 1 + spec/bench/harness/go/go.mod | 5 + spec/bench/harness/go/go.sum | 2 + spec/bench/harness/go/main.go | 316 +++++++++++ spec/bench/harness/java/JavaBench.java | 158 ++++++ spec/bench/harness/node-bench.ts | 144 +++++ spec/bench/harness/python_bench.py | 275 ++++++++++ spec/bench/harness/ruby_bench.rb | 187 +++++++ spec/bench/harness/uniffi_bench.py | 53 ++ spec/bench/prepare.ts | 50 ++ spec/bench/results.jsonl | 37 ++ spec/bench/run-all.sh | 29 + spec/bench/table.py | 92 ++++ spec/bench/uniffi/Cargo.lock | 711 +++++++++++++++++++++++++ spec/bench/uniffi/Cargo.toml | 23 + spec/bench/uniffi/src/bin.rs | 5 + spec/bench/uniffi/src/lib.rs | 111 ++++ spec/codegen/targets/python.ts | 137 ++++- spec/codegen/targets/ruby.ts | 157 +++++- vite.config.ts | 1 + 26 files changed, 2988 insertions(+), 49 deletions(-) create mode 100644 spec/BINDINGS-INVESTIGATION.md create mode 100644 spec/bench/core/Cargo.lock create mode 100644 spec/bench/core/Cargo.toml create mode 100644 spec/bench/core/src/lib.rs create mode 100644 spec/bench/corpus.json create mode 100644 spec/bench/harness/go/go.mod create mode 100644 spec/bench/harness/go/go.sum create mode 100644 spec/bench/harness/go/main.go create mode 100644 spec/bench/harness/java/JavaBench.java create mode 100644 spec/bench/harness/node-bench.ts create mode 100644 spec/bench/harness/python_bench.py create mode 100644 spec/bench/harness/ruby_bench.rb create mode 100644 spec/bench/harness/uniffi_bench.py create mode 100644 spec/bench/prepare.ts create mode 100644 spec/bench/results.jsonl create mode 100644 spec/bench/run-all.sh create mode 100644 spec/bench/table.py create mode 100644 spec/bench/uniffi/Cargo.lock create mode 100644 spec/bench/uniffi/Cargo.toml create mode 100644 spec/bench/uniffi/src/bin.rs create mode 100644 spec/bench/uniffi/src/lib.rs diff --git a/.gitignore b/.gitignore index 73265048d..ad8b8d57d 100644 --- a/.gitignore +++ b/.gitignore @@ -20,3 +20,11 @@ reports/* reports/api/* !reports/api/brazilian-utils.api.md spec/generated + +# The benchmark harness builds its artifacts from source; `spec/bench/run-all.sh` recreates them. +spec/bench/.build +spec/bench/.spec-masked-strict +spec/bench/**/target +spec/bench/harness/go/generated +spec/bench/harness/java/Cpf.java +spec/bench/harness/java/SpecRuntime.java diff --git a/spec/BINDINGS-INVESTIGATION.md b/spec/BINDINGS-INVESTIGATION.md new file mode 100644 index 000000000..3cfa0c147 --- /dev/null +++ b/spec/BINDINGS-INVESTIGATION.md @@ -0,0 +1,276 @@ +# One core, every language: bindings or generated source? + +The follow up question to [EXPLORATION.md](EXPLORATION.md): instead of generating **source** for +each language, could Brazilian Utils build the logic once — in Rust, in C, in WebAssembly — and +give every package a **binding** to it? Is there an off the shelf tool for that? And what does it +cost at run time? + +Everything below was measured on this branch. Reproduce with: + +```bash +bash spec/bench/run-all.sh # every arm, every language +bash spec/conformance/run-all.sh # every arm still answers identically +``` + +--- + +## The answer + +**Generated source wins, and it is not close.** The approach from the previous exploration — +a language neutral spec compiled to idiomatic source per language — beats every binding strategy +once distribution is taken into account, and after two emitter fixes it is also _faster than the +handwritten code it replaces_ in all five languages measured. + +A shared binary core is not useless, but it is a second, optional layer: worth it only for a host +that validates in bulk, never for the npm package, and never as the only implementation. + +| Strategy | Run time | Ship cost | Verdict | +| ---------------------------------------- | ---------------------------------------------------- | -------------------------------------------------------- | ----------------------- | +| **Generated native source** | 0.36×–0.66× of handwritten (i.e. faster) | none: it is just source | **default** | +| Shared core + wasm | 0.12×–15.5× depending entirely on the host's runtime | one 9 KB artifact, plus a runtime dependency per package | optional, batch only | +| Shared core + C ABI (FFI/cgo) | 0.10×–0.45× | a native build per platform × arch, per ecosystem | last resort | +| Off the shelf binding generator (UniFFI) | **3.7× slower than plain Python** | as above | rejected on the numbers | + +--- + +## How it was measured + +One function — `isValidCpf` under the `masked-strict` profile — over a fixed corpus of 1000 +inputs (`spec/bench/corpus.json`): valid CPFs bare and masked, near misses with one digit flipped, +junk, Unicode whitespace, NBSP, ZWNBSP, an emoji, and CPFs written in full width and Arabic-Indic +digits. Each arm reports the best nanoseconds per call over 7 repetitions after warmup, plus how +many inputs it called valid — an arm cannot win by doing less work. + +Every arm computes the same thing, and the source level arms are generated from the **same +profile** (`spec/bench/prepare.ts` overrides each package's adopted profile for the run), so the +comparison is not measuring one package's laxer contract against another's. + +Machine: Intel Xeon @ 2.80GHz, 4 vCPU, Linux. Node 22.22.2, Python 3.11.15, Ruby 3.3.6, Go 1.24.7, +rustc 1.94.1, OpenJDK 21.0.10, wasmtime-py 48.0.0, wasmtime gem 48.0.1, wazero 1.9.0, UniFFI 0.29. + +### Arms + +| Arm | What it is | +| --------------- | ------------------------------------------------------------------------ | +| `handwritten` | Idiomatic code a contributor would write in that language, regex and all | +| `generated` | The emitter's output for the same spec | +| `wasm` | The Rust core compiled to `wasm32-unknown-unknown`, one call per input | +| `wasm-batch` | Same core, the whole corpus in one call | +| `wasm-callonly` | The boundary alone: same pointer, same length, no marshalling | +| `ffi` / `cgo` | The same core as a `cdylib`, over ctypes / Fiddle / cgo | +| `uniffi` | The same logic behind UniFFI generated Python bindings | + +--- + +## Results + +Lower is better. `× hand` is the ratio to that language's handwritten arm, so **below 1.00 is +faster than handwritten**. + +| Language | Arm | ns/op | × hand | valid | +| -------- | ------------- | ---------: | -------: | ------: | +| Node | handwritten | 386.2 | 1.00 | 337 | +| Node | **generated** | **256.5** | **0.66** | 337 | +| Node | wasm | 224.6 | 0.58 | 337 | +| Node | wasm-batch | 240.5 | 0.62 | 337 | +| Python | handwritten | 2460.6 | 1.00 | **333** | +| Python | **generated** | **1366.0** | **0.56** | 337 | +| Python | wasm | 38039.3 | 15.46 | 337 | +| Python | wasm-callonly | 30058.9 | 12.22 | — | +| Python | wasm-batch | 306.3 | 0.12 | 337 | +| Python | ffi (ctypes) | 535.3 | 0.22 | 337 | +| Python | ffi-batch | 239.9 | 0.10 | 337 | +| Python | **uniffi** | **9064.2** | **3.68** | 337 | +| Python | uniffi-batch | 6195.8 | 2.52 | 337 | +| Ruby | handwritten | 3675.8 | 1.00 | **329** | +| Ruby | **generated** | **2020.1** | **0.55** | 337 | +| Ruby | wasm | 729.9 | 0.20 | 337 | +| Ruby | wasm-batch | 430.0 | 0.12 | 337 | +| Ruby | ffi (Fiddle) | 1662.1 | 0.45 | 337 | +| Go | handwritten | 446.2 | 1.00 | **334** | +| Go | **generated** | **193.1** | **0.43** | 337 | +| Go | wasm (wazero) | 189.1 | 0.42 | 337 | +| Go | wasm-batch | 104.5 | 0.23 | 337 | +| Go | cgo | 119.1 | 0.27 | 337 | +| Go | cgo-batch | 52.6 | 0.12 | 337 | +| Java | handwritten | 1365.3 | 1.00 | 337 | +| Java | **generated** | **493.6** | **0.36** | 337 | + +--- + +## Six findings + +### 1. Generated source is faster than handwritten, in every language measured + +0.36× in Java, 0.43× in Go, 0.56× in Python, 0.55× in Ruby, 0.66× in Node. Not because the generator is +clever, but because a human writing these by hand reaches for the regex engine (`\d{3}[\s.-]*...`) +while the emitter knows the exact character sets and can pick whichever construct is cheapest in +that language. + +This did **not** hold on the first measurement. The emitters used to walk the string code point by +code point in every language, which is right for Go and Java and terrible for Python and Ruby +(6.5 µs and 15.1 µs per call — 2.6× and 4.1× _slower_ than handwritten). Two rules fixed it, and +both are in this branch: + +- **Collapse `guard-shape` + `sanitize` into one anchored regex with capture groups.** The + character classes are written out code point by code point (`[\u0009\u000a…\u2000-\u200a…]`), so + the semantics stay exactly the spec's — `\s` would not — while the matching happens in C. The + digits come out of the capture groups, so there is no second pass over the string and no + intermediate allocation. +- **Read digits as bytes in the check digit loop** (`ord(char) - 48`, `getbyte(i) - 48`) instead of + `int(char)` / `to_i`, and unroll the verification instead of iterating positions with a closure. + +Python went 6485 → 1366 ns/op; Ruby 15051 → 2020. Conformance stayed at 2229/2229 for both. + +**This is the load bearing result for the whole idea**: the emitter is allowed to know things +about its target language, and the moment it does, generated code stops being a compromise. + +### 2. The boundary costs more than the work + +The validator itself takes ~100 ns. Look at the `callonly` arms — the same pointer and length every +time, no marshalling, no string conversion, pure boundary: + +| Host | Boundary cost per call | +| --------------------------- | ---------------------- | +| Go → wasm (wazero) | 104 ns | +| Go → C (cgo) | 98 ns | +| Ruby → wasm (wasmtime gem) | 521 ns | +| Ruby → C (Fiddle) | 1518 ns | +| Python → C (ctypes) | 472 ns | +| Python → wasm (wasmtime-py) | **30059 ns** | + +For a function whose body is 100 ns, a boundary of 500–1500 ns means the binding _is_ the cost. +That is why `ffi` in Python (535 ns) is almost exactly `ffi-callonly` (472 ns): the validation is +noise next to the call. + +The corollary is the `batch` arms: amortise one boundary crossing over 1000 inputs and everything +becomes fast (Python 240 ns/op over ctypes, 306 ns/op over wasm). A shared core is a **bulk +validation** tool, not a per call one. + +### 3. Binding quality varies by 300× between runtimes of the same technology + +Same `.wasm` file, same core, same machine: + +- wazero (pure Go): **104 ns** per call +- wasmtime gem (Rust native extension): **521 ns** +- wasmtime-py 48 (ctypes over the C API): **30 059 ns** + +wasmtime-py is not slow at running wasm; it is slow at _being called_, because every invocation +builds `Val` arrays through ctypes. Poking the linear memory through its raw pointer instead of +`Memory.write` only takes it from 38.0 µs to 32.4 µs — the cost is the call, not the copy. + +So "we ship a wasm core" is not one decision with one performance profile. It is a different +decision per package, and in Python today it means "and also batch everything". + +### 4. The off the shelf tool is slower than writing Python + +UniFFI is the tool everyone recommends for this (Mozilla ships Firefox features with it). Its +generated Python bindings cost **9064 ns per call — 3.7× slower than just implementing the +validator in Python**, and 17× slower than the same `.so` called through hand written ctypes. + +The generated call path explains it: `check_lower` validates the string, `lower` allocates a +`RustBuffer` and copies into it, a `_UniffiRustCallStatus` struct is built, the call goes through +ctypes, the status is checked, the result is lifted. Six Python level operations wrapped around +100 ns of work. Even `uniffi-batch` (a `Vec` in, a `Vec` out) lands at 6196 ns/op, +still slower than plain Python, because the sequence has to be serialised into a `RustBuffer`. + +UniFFI is built for coarse grained APIs — "sync this database", "decrypt this blob" — where a +microsecond of glue is irrelevant. Brazilian Utils is the opposite: a hundred tiny pure functions. + +### 5. The JS package would pay the most and gain the least + +| | Generated source | Wasm core | +| -------------------------------------------- | --------------------------- | ----------------------------------------------------------------------- | +| `isValidCpf` single import bundle, minified | **509 bytes** | 9291 bytes (4344 gzipped) for the core with **one** utility | +| Tree shaking | per function, as today | none: the module is one indivisible blob | +| Bundling, Deno, Bun, browsers, edge runtimes | works everywhere, no config | needs a loader, async instantiation, and a bundler that handles `.wasm` | +| `sideEffects: false` and zero dependencies | preserved | gone | + +An 18× size increase for one function, no tree shaking, and asynchronous initialisation, in +exchange for 160 ns. The npm package's selling points are exactly what a wasm core takes away. + +Cold start, for the record: instantiating the 9 KB module costs 0.025 ms in Node, 3.5 ms in +Python, 3.8 ms in Ruby — fine for a server, not free for a CLI or a lambda. + +### 6. Every handwritten port is already subtly wrong + +Look at the `valid` column. Over the same 1000 inputs, the handwritten arms disagree with the +spec: Python 333, Ruby 329, Go 334, against 337 for everything generated. + +These are not bugs I planted. I wrote each handwritten arm the way the language invites: +`cpf.strip()` in Python strips a different set from JavaScript's `trim()`; Ruby's `String#strip` +handles only ASCII whitespace plus NUL; Go's `strings.TrimSpace` is Unicode space separators, which +excludes `U+FEFF`. Three languages, three different answers, for a CPF a user pasted with an +invisible character in front of it. + +The generated arms all answer 337 because the character set came from the spec, not from the +standard library's idea of whitespace. **The reason to generate is correctness; the performance is +what makes it affordable.** + +--- + +## The tools, surveyed + +| Tool | What it does | Languages | Why it does or does not fit | +| -------------------------------------------------------------------------------- | ------------------------------------------- | ------------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| [UniFFI](https://github.com/mozilla/uniffi-rs) | Rust → bindings, from proc macros | Kotlin, Swift, Python, Ruby; C#/Go third party | **Measured: 3.6× slower than plain Python.** No JS, no Erlang. Built for coarse APIs | +| [Diplomat](https://github.com/rust-diplomat/diplomat) | Rust → FFI, one bridge, many backends | C, C++, JS/TS, Dart, Kotlin, Python | Closest fit technically (ICU4X ships JS via wasm with it), still a binary core with the costs in §5; no Go, Ruby or Erlang | +| [wit-bindgen](https://github.com/bytecodealliance/wit-bindgen) + Component Model | An IDL, guests and hosts generated | Growing; `jco` transpiles components to JS | The most future proof binary story. Still a binary, and the JS output is a wasm blob, not tree shakeable source | +| [Extism](https://extism.org) | Wasm plugin framework, host SDKs everywhere | JS, Go, Ruby, Python, C#, Java, **Erlang/Elixir**, PHP, OCaml, Zig… | Broadest host coverage by far. Adds a plugin protocol on top of the per call cost in §2–3 | +| [wasm2c](https://github.com/WebAssembly/wabt/tree/main/wasm2c) | Wasm → C, compiled natively, no runtime | any language with a C FFI | Removes the _runtime_ dependency, keeps the _binary_ one. Interesting for Erlang NIFs | +| [wasmex](https://github.com/tessi/wasmex) | Wasmtime as an Erlang/Elixir NIF | Erlang, Elixir | The only realistic wasm route for the BEAM | +| [Kaitai Struct](https://kaitai.io) | Declarative spec → parsers in 11 languages | C++, C#, Go, Java, JS, Lua, Nim, Perl, PHP, Python, Ruby | **The precedent for the approach in this repository.** Binary formats only, so not reusable directly, but it proves a spec-to-source compiler scales to a dozen targets | +| [Haxe](https://haxe.org) / [Fable](https://fable.io) | One source language → many targets | JS, Python, C#, Java, PHP, Lua, C++ / JS, TS, Python, Rust, Dart, Erlang | Both emit code that depends on their own runtime library, and neither produces something a Go or Ruby maintainer would review. Fable is worth a footnote because the .NET package is already F# | +| SWIG | C/C++ → bindings | many | Same binary tradeoffs, older ergonomics | + +**Nothing off the shelf does what this project needs**, because the need is unusual: ~100 tiny pure +functions, six ecosystems that each demand idiomatic naming, zero runtime dependencies, and a +flagship package that must stay tree shakeable. Every binding generator optimises for the opposite +shape. The closest thing to prior art is Kaitai Struct, and its model — a declarative spec plus one +compiler backend per language — is exactly what `spec/codegen` already is, at 350–430 lines per +target. + +--- + +## Recommendation + +1. **Generated source is the default.** It has no runtime dependency, no build matrix, no cold + start, no bundle penalty, it is reviewable by each package's maintainers, and it is now measured + faster than the handwritten code in Node, Python, Ruby, Go and Java (0.36×–0.66×). +2. **Keep the two emitter rules from §1 as a requirement of every new target.** A target is not + done until its output is benchmarked against idiomatic handwritten code for that language. The + harness in `spec/bench` is the acceptance test. +3. **Do not put a binary core in the npm package.** §5 is disqualifying on its own. +4. **A shared wasm core stays an option for one specific case**: a host validating in bulk — a + batch importer, an ETL job, a CEP sweep. `wasm-batch` runs at 0.12× of handwritten in Python and + Ruby. If that demand ever appears, it should be a separate, optional package + (`brazilian-utils-turbo`), never the only implementation, and it should reuse the same spec so + the two cannot drift. +5. **Revisit only if the workload changes.** Bindings win when the work per call grows past a few + microseconds. Nothing in this library is close: the heaviest validator here is ~100 ns. + +## What would change the answer + +- A utility whose work is genuinely heavy (a full NF-e XML parse, a large dataset search). Then the + boundary stops dominating. +- A host runtime fixing its call overhead — a wasmtime-py that costs 500 ns instead of 30 000 ns + would make the wasm core competitive per call in Python. +- The Component Model reaching the point where `jco` emits tree shakeable JS. Today it does not. + +## Reproducing + +```bash +cargo build --release --manifest-path spec/bench/core/Cargo.toml +cargo build --release --target wasm32-unknown-unknown --manifest-path spec/bench/core/Cargo.toml +bash spec/bench/run-all.sh > spec/bench/results.jsonl + +# the UniFFI arm, which needs its own build +cargo build --release --manifest-path spec/bench/uniffi/Cargo.toml +cd spec/bench/uniffi && ./target/release/uniffi-bindgen generate \ + --library target/release/libbrutils_uniffi.so --language python --out-dir ../.build/uniffi-python +cp target/release/libbrutils_uniffi.so ../.build/uniffi-python/ +python3 ../harness/uniffi_bench.py +``` + +Requires `node`, `python3` (with `wasmtime`), `ruby` (with the `wasmtime` gem), `go`, `cargo` with +the `wasm32-unknown-unknown` target, and `javac`. diff --git a/spec/README.md b/spec/README.md index 7455ffba0..a94bbb17b 100644 --- a/spec/README.md +++ b/spec/README.md @@ -2,7 +2,10 @@ A prototype of describing a utility once, as data, and emitting it to every language Brazilian Utils publishes. Read [EXPLORATION.md](EXPLORATION.md) first: it explains why this exists, what it -proves, what it does not, and what to do next. +proves, what it does not, and what to do next. Then +[BINDINGS-INVESTIGATION.md](BINDINGS-INVESTIGATION.md), which measures this approach against the +alternative — one binary core plus bindings — in five languages, and says why generated source +wins. Nothing here ships in the npm package. `src/` is untouched, and the build, the bundle and the public API are exactly what they were. @@ -67,6 +70,15 @@ If a utility needs a step the IR does not have, add the step to `schema/utility. `Step` in `codegen/ir.ts`, to the interpreter, and to the six emitters — in that order. That cost is the honest price of a new kind of behaviour, and it is why the IR should stay small. +## Benchmarking a target + +`bash spec/bench/run-all.sh` builds every artifact and prints one JSON line per measurement into +`spec/bench/results.jsonl`; `python3 spec/bench/table.py` folds that into the table in the +investigation. A new or changed emitter is not done until its output has been measured against +idiomatic handwritten code for that language: emitting a per code point loop into a language whose +regex engine is written in C costs 2–4×, which is how the Python and Ruby emitters were found to +be slow and then fixed. + ## Adding a language Write `codegen/targets/.ts` (350–430 lines, modelled on any existing one), register it in diff --git a/spec/bench/core/Cargo.lock b/spec/bench/core/Cargo.lock new file mode 100644 index 000000000..0c3c8d7af --- /dev/null +++ b/spec/bench/core/Cargo.lock @@ -0,0 +1,7 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "brutils_bench_core" +version = "0.0.0" diff --git a/spec/bench/core/Cargo.toml b/spec/bench/core/Cargo.toml new file mode 100644 index 000000000..0ef340660 --- /dev/null +++ b/spec/bench/core/Cargo.toml @@ -0,0 +1,15 @@ +[package] +name = "brutils_bench_core" +version = "0.0.0" +edition = "2021" +publish = false + +[lib] +crate-type = ["cdylib", "rlib"] +path = "src/lib.rs" + +[profile.release] +opt-level = 3 +lto = true +panic = "abort" +codegen-units = 1 diff --git a/spec/bench/core/src/lib.rs b/spec/bench/core/src/lib.rs new file mode 100644 index 000000000..d54293956 --- /dev/null +++ b/spec/bench/core/src/lib.rs @@ -0,0 +1,223 @@ +//! The shared core used by every non source level arm of the benchmark. +//! +//! It implements exactly one thing — `isValidCpf` under the `masked-strict` profile — with the +//! same steps the generated code uses, so the only difference between the arms is how the call +//! crosses the language boundary. +//! +//! Two entry points on purpose: +//! +//! * `cpf_is_valid` takes one string and answers one bool: the shape a binding generator +//! produces from a spec, and the shape an application actually calls. +//! * `cpf_is_valid_batch` takes a packed buffer of N strings and fills N bytes: the shape you +//! fall back to when the boundary turns out to cost more than the work itself. + +#![no_std] + +const fn is_ascii_digit(code: u32) -> bool { + code >= 0x30 && code <= 0x39 +} + +/// The code points JavaScript's `trim()` strips and its `\s` matches. +const fn is_js_whitespace(code: u32) -> bool { + matches!( + code, + 0x09 | 0x0a + | 0x0b + | 0x0c + | 0x0d + | 0x20 + | 0xa0 + | 0x1680 + | 0x2028 + | 0x2029 + | 0x202f + | 0x205f + | 0x3000 + | 0xfeff + ) || (code >= 0x2000 && code <= 0x200a) +} + +const fn is_mask_cpf(code: u32) -> bool { + code == 0x2e || code == 0x2d || code == 0x2f || is_js_whitespace(code) +} + +fn check_digit(base: &[u8]) -> u32 { + let mut sum: u32 = 0; + let mut weight = base.len() as u32 + 1; + + for byte in base { + sum += u32::from(*byte - b'0') * weight; + weight -= 1; + } + + let digit = 11 - (sum % 11); + + if digit >= 10 { + 0 + } else { + digit + } +} + +/// Validates one CPF under the `masked-strict` profile. +pub fn is_valid(value: &str) -> bool { + let trimmed = value.trim_matches(|char: char| is_js_whitespace(char as u32)); + let mut digits = [0u8; 11]; + let mut count = 0; + let groups = [3usize, 3, 3, 2]; + let mut iter = trimmed.chars().peekable(); + + for (position, size) in groups.iter().enumerate() { + if position > 0 { + while let Some(char) = iter.peek() { + if is_mask_cpf(*char as u32) { + iter.next(); + } else { + break; + } + } + } + + for _ in 0..*size { + match iter.next() { + Some(char) if is_ascii_digit(char as u32) => { + digits[count] = char as u8; + count += 1; + } + _ => return false, + } + } + } + + if iter.next().is_some() { + return false; + } + + let first = digits[0]; + + if digits.iter().all(|digit| *digit == first) { + return false; + } + + if u32::from(digits[9] - b'0') != check_digit(&digits[..9]) { + return false; + } + + u32::from(digits[10] - b'0') == check_digit(&digits[..10]) +} + +// --------------------------------------------------------------------------- +// C ABI, used by the FFI arms and by the wasm arms alike. +// --------------------------------------------------------------------------- + +/// Validates one CPF held at `ptr` for `len` bytes of UTF-8. Returns 1 or 0. +/// +/// # Safety +/// +/// `ptr` must point at `len` readable bytes. +#[no_mangle] +pub unsafe extern "C" fn cpf_is_valid(ptr: *const u8, len: usize) -> i32 { + let bytes = core::slice::from_raw_parts(ptr, len); + + match core::str::from_utf8(bytes) { + Err(_) => 0, + Ok(value) => i32::from(is_valid(value)), + } +} + +/// Validates `count` CPFs packed as [u32 length][bytes]... and writes one byte per verdict. +/// +/// # Safety +/// +/// `input` must hold the packed buffer and `output` at least `count` writable bytes. +#[no_mangle] +pub unsafe extern "C" fn cpf_is_valid_batch( + input: *const u8, + input_len: usize, + output: *mut u8, + count: usize, +) -> i32 { + let buffer = core::slice::from_raw_parts(input, input_len); + let results = core::slice::from_raw_parts_mut(output, count); + let mut offset = 0; + + for slot in results.iter_mut() { + if offset + 4 > buffer.len() { + return -1; + } + + let length = u32::from_le_bytes([ + buffer[offset], + buffer[offset + 1], + buffer[offset + 2], + buffer[offset + 3], + ]) as usize; + + offset += 4; + + if offset + length > buffer.len() { + return -1; + } + + *slot = match core::str::from_utf8(&buffer[offset..offset + length]) { + Err(_) => 0, + Ok(value) => u8::from(is_valid(value)), + }; + + offset += length; + } + + 0 +} + +// --------------------------------------------------------------------------- +// A bump arena, so a wasm host can hand strings in without a real allocator. +// --------------------------------------------------------------------------- + +const ARENA_SIZE: usize = 1 << 21; +static mut ARENA: [u8; ARENA_SIZE] = [0; ARENA_SIZE]; +static mut ARENA_USED: usize = 0; + +/// Reserves `len` bytes of the arena and returns a pointer to them. +#[no_mangle] +pub extern "C" fn arena_alloc(len: usize) -> *mut u8 { + unsafe { + let base = core::ptr::addr_of_mut!(ARENA) as *mut u8; + + if ARENA_USED + len > ARENA_SIZE { + ARENA_USED = 0; + } + + let offset = ARENA_USED; + + ARENA_USED += len; + + base.add(offset) + } +} + +/// Empties the arena. +#[no_mangle] +pub extern "C" fn arena_reset() { + unsafe { + ARENA_USED = 0; + } +} + +#[cfg(target_arch = "wasm32")] +#[panic_handler] +fn panic(_info: &core::panic::PanicInfo) -> ! { + core::arch::wasm32::unreachable() +} + +#[cfg(not(target_arch = "wasm32"))] +#[panic_handler] +fn panic(_info: &core::panic::PanicInfo) -> ! { + loop {} +} + +/// A `no_std` cdylib still has this symbol referenced by the unwinder; `panic = "abort"` means +/// it is never called. +#[cfg(not(target_arch = "wasm32"))] +#[no_mangle] +pub extern "C" fn rust_eh_personality() {} diff --git a/spec/bench/corpus.json b/spec/bench/corpus.json new file mode 100644 index 000000000..9922623b8 --- /dev/null +++ b/spec/bench/corpus.json @@ -0,0 +1 @@ +[" ","0","00000000000","11111111111","99999999999","12345678909","123.456.789-09","123 456 789 09"," 12345678909 ","123.456.789.09","123/456/789/09","123-456-789-09","123..456..789--09",".12345678909","12345678909.","1234567890","123456789090","abc12345678909","12345678909abc","1a2345678909","12345678900"," 12345678909 "," 123.456.789-09
","12345678909","123 456 789 09","123\t456\n789\r09","🇧🇷12345678909","12345678909🇧🇷","12345678909","١٢٣٤٥٦٧٨٩٠٩","12056874107","120.56874.10-7","120/56874/10-7","120(56874)10,7","120*56874*10-7","12056874108","1205687410","120.56874.10-7 ","120#56874#10#7","74275733568","69264259294","27502677658","9.5167.3","45528746248","00192591070","2423/3.79a967a0","04349316248","05828033735","*340*)6","01018054771","45960967839","72953559375","350#6#7 633717","85752788760","12201461035","65623597327","08216262647","94291497253","65546678658","02218010658","13434608915","60021596917","99266321688","036/6694a2431","29022796396","659037# ","610954584)85,","57.364183-296","72468124605","01366021578","37242507700","6.5968)418a486","64629394234","89884,197702","588519 7)4/661","06733963710","16153416609","973194*6,5520-","83438658534","48938105458","52070564410","37299492850","97116501347","267a783 45665","7*15653/41811","193a0007658a5","32605779807","81887191706","60150247125","71770889540","38306173004","63 568062866","13765631345","96840834266","875 6a6256601","17)06**05","#478089(3220","977/03000(","660(29a924818","25368103999","15050757707",")49 354 55","23609640126","7587)8147440.","95291932024","32711721370","25#8163547 95","707612.87664.","40110965809","-54)9","62501783555","3855)352323","00158379099","2(1062574","#63(67406","94622089211","85947269915","86/98247","30953452751","5554204406-9","87821425957","10359723012","38589626369","17091421971","649982-92,8,306","*737925","51723668907","0,353077501","1381-9#642420","29972448622","89/-60/84210273","1425.6372500","55427359071","63876408903","106a","53367895857","500978,20993","32498856498","36558846217","26147599291",".(1.9*24*","75660210933","93971033695","52200090253","38476272600","378447344/33","069263407*#51","59139466850","6(87953,3-8570","87373238138","95 1","641350042 5(3","40910963010","268067 8#237*8","83723418503","758131(6","20240907137","33520141268","17938","10213407217","66738397299","45-92166 57(41","05466916770","62762266910","84911262958","81826425290","89205985252","05496053471","52597393372","38652220565","17-89993365275","22279047551","15481647740","54130082795","23442185571","90 500080904","84264259522","58976801750","20648740625","57342147291","8","06787915480","74994999791","308351266,0 0","33664446341","72084287028","62610395930","39083(594068","29462 99449a8","87862097741","148965/24500 ","4549302,4182(","43955822983","49545440333","00838712551","5693995*7#12/0","79/467634503","90117760952","6","450262548(83","71733485502","59920913563","14079680171","067*37*782012","7683735755,1 ","43855708339","26273937561","66846268596","8433,56 40/307","12710973626","60805222300","36453716769","80716189538","96875115166","74336944841","31092397361","16348172139","38146986579","24144680090","35818.63-9282","(0","50373463200","7a6a61220#1053","55023a198.0,(","3857,8,49895)0","84785977515","34957107592","90534660967","2183836)15","1)8813929374(","25625090603","1-4","67817905635","45185817500","62591997515","94866406005","48986981319","48a1)896956(215","12847371605","02712781880*","50590677201","1130)86*12109","85452922541","1657*89388a2-7","06054396416","94680920548","69605029960","64060368330","79870297338","71327360357","06833761241","31953017104","21881139070","03621090/1#28 ","08845801875","66081 17 838.0","(991 59(36720","19929703942","65134983178","56127159482","13905674709","35487816369","01104612585","49147868907","8175837 988(5","1958*2603944","12857330375","39510339750-","57878124270","06770932311","29395616890","50413890.635","3","54711981085","27704704850-","46757073297","3*9#18786a8,113a","8.22,2*,(#","09624157970","20862681019","65845806283","78155325511","91246524902","85037722440","06072829910","19006621385","91822082633","284003-7)6293/","24584648158","81765431668","90125/01,2535","42430498944","28,72040882a2","4674150#3016","a58,","35738654593","49571112270","70116455780","70494#544/864/","63108583352","51832068939","99665590359","3237#5","871 20910493","6 7706696502#","74910*321292","58825236983","91665897113","22473672220","50333a031555","39376825044","16326834334","3/1854069798","86676398427","10a47#83","07203160435","7","54041828147","81939232511","033789.079#08#","7(20 613.","36081312203","14827445113","90094962103","89393206850","37845084553","775-319793 91","3359490 5 098","80531386406","57)406681,15/1","91(231287551,","415","62#067,930(891","44090285141","67489979412","11680919695","32*9#34)167801","29927535309","68816320370","32745256439","49593127933","77791117843","491(378(84506","097a 9)4741-","932.23243/178","28295821005","33212344679","77762041370","95373510416","6/4489153627","42794672014","93206839807","40428139980","27002753061","16041909891","5(939a954561)0","0438-1899814","6806703/6748","76083838506","46508664646","64204832671","03584949823","82976574340","7,2135151017","12435077094","9977(00041 98-","388993*87 958,","699367.6777/27)","91553048220","82674809787","32782781600","1302581(","301/41926580a","99064778258","824 460621 8","70140751009","79774925122","45294338971","67715677884","10*3(6158 65,90*","22115679341","02040884623","8/6956026238","88142588117","45716895786","3516340448 0a","92995777499","17710007188","35*87#17#48781","25570295610","04046*885075","73144445606","75086a8#8058/0","03670355555","-/ 02","a 434 ","59728943107","4080.3088256","#37 0","57049460387","42024527209","50224587436","33689976456","6.3.23-9(8 67877","03014108448","30173549871","53945248343","53416681118","724-49978844","45277444106","40086262556","55205/ 1(*1","54712598077","11228014a340","19984710807","87024275839","40033410231","13026104140","93439798607 ","79547137921","06586026164","30648422267","7473,2299822","78751559404","77371587199","23201372770","48 5(28827259","63098235590","44-68 1014079","4472640","18192199177","36726974559","78164817058","863758171(71","57024472704","02824308596","a252) 5","49487942440","39","01605660652","98460899292","3104897*8753","4(133807a2206","99292011308","63031473936","38076757950","05679802430","63341026362","66,5382991","30414950070","32)-#4611403*","42123780522","06236152#571","82153578817","36045129267","099(987(52343","58536818859","66540536264","45787969065","#,4236","42050173679","8569207-83(25","56(13630","03855805687","31793#036977#","92826784218","991361901*79","3*3647161)202 ","0474552)#5","654(592183 65","70389666858","62488480096","66.59-467 823)0","4#50,.0a21061,8","765801 2*2382","66122001201","26826010305","57142385151","5.35748724#4)3(","47236219541","40549687670","90141629369","70223(9 8674 7","90334100011","04518514970","9354470436 3","7 63)8680#1202.","86305661512","53111178501","35772104276","489(51911098*","19901091446","63013612798","71914656529","44617654747","96491193969","a615,,41","95805869707","29901346205","54208519975","875)53-6*81295","36988108217","5 354 19 4","4/5 3175.172 0,1","67755270160","92879818","98966060521","98114#524)235","6-2 9","77237 56004","64548712588","89499697768","64807531071","4.15*52615#960","029 0*7472598","61447588640","462 86624449","28997279157","9 2769#78 44)0*","12418027879","00576059- 4#.","83871787884","18629180668","625,765938 7(7","68675256998","62682278159","05376651371","15624641471(","55397368261","94697679827","59343010710","96988797300","68741541090","81545791201","06430204977","65078757406","95113422*195","28644466375","-63(,3698","09323157444","53234099691 ","014371442/4*9 ","29715289932","18166 728#150","2)7 6*35541370-","94622736349","30086393632","99920183642","176844)10300","72720)70-4909","0829064a1095","73165138013","21723780626","82760984438","08552756887","56267985520","62062059424","14353708309","20197616968","90970500734","31979867452","667.8133927 3","55494164179","13/73 9728530","22015806008","56825397664",")6 *6(0a146","31,43)2597604","90771312563","29389912075","381997951)31","52 62273.13)","90700384987","05621956966","7748169522","23813064123","78305022501","25623.074294","4132057/7202","71536439312","95498010125","(727,6.4.","21509606726","043397/52460","00346424712","37585164478","74.700668660*","66312087344","96883873367","61955334460","018549.08828","47772633149","01397607840","11/556669682","41826165886","2780148195 0","84674429137","94317787811","506237 79133","40584847998","44943496302","0 32,91#06 ","95196278559","92601882450","50015512407","106/38726082","901#/903678355","21117259856","25882595967","04732383491","9479969 9","95922669800","8883/06156)0*9","32850130796","77974150892","29659535186","49// ","15790872976","58260669897","91329809105","5677103 1950,","14398251227","25824296210","56314621844","94876813277","16263660120","700717*6(2167","684-0502763","15424949790","8-1#91536(69","25371491907","75532925688","34493470550","70651413020","641863190#06/","36238066631","87766231879","78507200168,","97540086980","69426575595","717 0#540339a5","40057456622","16215778052","90760673330","21056750189","64853010206","95 9)760100-00","90259943428","46625500798","98-845045580","42861538430","71521538336","637a","65411877890","2)0224658756","83660227226","41096624424","2 0199552290","43290951901","91037243784","45426209985","39704032862","64763559532","906 33(7251)53","69805193291","04785557086","49612588732","7 )9","6613898473(0","55557336505","75932776234","35734160636","68367455505","43599874434","11981522551","46538105958","45249186411","77458313465","0a0798#895659","7700.4133267",".4-#2/.*-#2*878","461,7","0638673669","7739)5204468","13419417870","30688657217","43076045033","45420468862","47713594587","98299994147","47274872842","10279.099a30)4","63735745800","96010762314","43223170146","90732490086","81106510790","36902649001","36133763930","95524229907","60486932303","48622599876","38354488462","10*237294,664","462605-225,52","82118110709","25424062431","57411529370","49640340787","6245*598(990-9-","08)840/48606","67214459051","86730859433","41922980072","573/830(43308","01504672760","63298685954","09900425375","66694/5(79109","04257613203","27662001321","45617675848","31286558395","60 78 1073417","13782269179","46201891549","72380631544","1.0664386129","51796846302","28075951700","09651265523","76","10229235 794","92605156966","79693025163","24247486918","250*5.","34663768580","03086608463","39378025846","2(718063-2428","80(96a)649936","25795545996","56a290690809","16 649792047*","27252085525","25348089079","86775460732","36445524436",".5(590a38","2062760.0786","81886636805","474*2*","61688094447","21254835059","26924300260","52258500231","065086","85105139793","63625679693","/-- 65922","708446044*6/1","60106076477","23984576480","59680077847","9322905077,0","38954348920","00492189013","04588193872","482 1,5023/#","85050381040","682#386923#44","9318066-4","44605173960","0.5217916938","26561535146","11921285672","3382 5967135(","21877806196","267,7830)51","89632966791","746/1","72894339801","24978641881","36.4(991","91797805323","2510(29/4)8688","68960443980","09615276219","5 106*3310806","86664129256","85641556232","74.98.280)49/31","0),16699-98","77075306/596","47943055403","26964670211","95523583707","22672933358","70485 88859.0#","34749116602","633595420 32","13512751547","40313076081","875279a435,55","585-0988955,4","81933902299","23988884871","15554658202","-1(a4#2 490,47","72463959622","69(448632)00-2","91885234546","47058954615","6876792285 6","644906208*05","01942202814","45006725309","399a21018#787","94525929405","3885.7)18)2789","61224521730","63448129151","065,315699*3)3","02101","401a9322/0 9","16505731180","00877131104","88867356018","958/696841 37","69408979338","18551858572","49304352*347-","22562862920","463422,89177","54098408504","68587*39874a1 ","85802617524","50388932872","10255839800","933039.58300","3634,08-032-75","27390290297","68145066107","72916978089","9)3","41388862654","04743053942","92811367903","58559689075","15444664127","82267674742","3945933-6571","0002731)69 12 ","60742830181","2,5021)0469(31","8057302-8(524","55505518250*"," 86)7#","54783617690","75828201368","55480489596","87106869244","82352299538","64938489865","30577914)342","47139881692","80159915073","06497175699","48#764700-496","7)#))(-","57450863430","0 93#1(4036087","45388613900","52714476260","71310606153","14106674564","83595381157","76893595905","68631507350","25235057708","4240716)161,4#","70972190252","18714514770","/0-7 .8)1 252","28281769581","0926646a9319","77964670522","83654466559","22072501130","40601762737586","33539777326","37284568 0","80798637765","87847789409","727938a48277","64991544661","348 557a593-33","74759107339","53382500710","91312097771","078)7,734","2/6 154219#725","90988(7 7592","67026787564","69712982700","66106200084","67258703605","05894443799","94777648338","12702179339","33444118981","95347424737","#a.32 09420.8","75599.766462","80*724171,428*","32004339225","89642567865","94771201978","72940326946","8,45","650a52136358","52087831424","03143150956","28 ","5700)01371a18","18271103172","71","38375765821","28546585221","39605624389","5","23412778830","87383271122","568287089/11","00878826679","27729132281","19880 07","10493140930","44503742254","4,#4(405)/2-39","19643630920","47663309427","15894979408","97349 100272","59056/924-1*706","04725815896","00923556680","60266-60,81-1-0","82632823032","3353277731#6","37829839908","93721059947","27252120228","08063097830","48381238765","75096379027","23096272901","62485109460","4,357*0(8336/23*","82410795080","/-4655","07081970940","37781914465","825-0/8914455","21189414639","7,31-37966680-","9,395 354)50(16","1468708736/8","286,01/119886","2a8617a","77290013125","93922212384","43641057460","68995259841","5860-18 84555(","47779837491","2 532 7988074","84719068057","44345565766","3a4206083038","211815524#78","787135944 a87#0","96397498697","96957613992","03910a6668)3)5","49097577548","96091583394","90913543292","9271.9413496*","64197773307","15255998443","31823734472","2461-3410525","36953566950","04148992881","88865190280","81896997686","73579629034","9817)9303/780)"] diff --git a/spec/bench/harness/go/go.mod b/spec/bench/harness/go/go.mod new file mode 100644 index 000000000..fdc13600f --- /dev/null +++ b/spec/bench/harness/go/go.mod @@ -0,0 +1,5 @@ +module brutilsbench + +go 1.24 + +require github.com/tetratelabs/wazero v1.9.0 diff --git a/spec/bench/harness/go/go.sum b/spec/bench/harness/go/go.sum new file mode 100644 index 000000000..b0ddcacb3 --- /dev/null +++ b/spec/bench/harness/go/go.sum @@ -0,0 +1,2 @@ +github.com/tetratelabs/wazero v1.9.0 h1:IcZ56OuxrtaEz8UYNRHBrUa9bYeX9oVY93KspZZBf/I= +github.com/tetratelabs/wazero v1.9.0/go.mod h1:TSbcXCfFP0L2FGkRPxHphadXPjo1T6W+CseNNY7EkjM= diff --git a/spec/bench/harness/go/main.go b/spec/bench/harness/go/main.go new file mode 100644 index 000000000..9735536c7 --- /dev/null +++ b/spec/bench/harness/go/main.go @@ -0,0 +1,316 @@ +// Go arms: handwritten source, generated source, the Rust core over wazero (a pure Go wasm +// runtime) and the same core over cgo. +package main + +/* +#cgo LDFLAGS: -L${SRCDIR}/../../core/target/release -lbrutils_bench_core -Wl,-rpath,${SRCDIR}/../../core/target/release +#include +int cpf_is_valid(const unsigned char *ptr, size_t len); +int cpf_is_valid_batch(const unsigned char *input, size_t input_len, unsigned char *output, size_t count); +*/ +import "C" + +import ( + "context" + "encoding/binary" + "encoding/json" + "fmt" + "math" + "os" + "path/filepath" + "regexp" + "runtime" + "strconv" + "strings" + "time" + "unsafe" + + "github.com/tetratelabs/wazero" + + generated "brutilsbench/generated/cpf" +) + +// --- arm: handwritten, the way a contributor would write it --------------------------------- + +var shape = regexp.MustCompile(`^[0-9]{3}[\s.\-/]*[0-9]{3}[\s.\-/]*[0-9]{3}[\s.\-/]*[0-9]{2}$`) +var nonDigits = regexp.MustCompile(`[^0-9]`) + +// The code points JavaScript's trim() strips; Go's strings.TrimSpace is a different set. +var jsSpace = string([]rune{0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x20, 0xa0, 0x1680, 0x2000, 0x2001, 0x2002, 0x2003, 0x2004, 0x2005, 0x2006, 0x2007, 0x2008, 0x2009, 0x200a, 0x2028, 0x2029, 0x202f, 0x205f, 0x3000, 0xfeff}) + +func checkDigit(base string) int { + sum := 0 + weight := len(base) + 1 + + for index := 0; index < len(base); index++ { + sum += int(base[index]-'0') * weight + weight-- + } + + digit := 11 - (sum % 11) + + if digit >= 10 { + return 0 + } + + return digit +} + +func handwrittenIsValid(cpf string) bool { + if !shape.MatchString(strings.Trim(cpf, jsSpace)) { + return false + } + + digits := nonDigits.ReplaceAllString(cpf, "") + + if digits == strings.Repeat(digits[:1], 11) { + return false + } + + first, _ := strconv.Atoi(digits[9:10]) + second, _ := strconv.Atoi(digits[10:11]) + + return first == checkDigit(digits[:9]) && second == checkDigit(digits[:10]) +} + +type result struct { + Lang string `json:"lang"` + Arm string `json:"arm"` + NsPerOp float64 `json:"nsPerOp"` + Valid int `json:"valid"` +} + +func measure(arm string, corpus []string, run func([]string) int) result { + reps := 7 + + if value := os.Getenv("BENCH_REPS"); value != "" { + if parsed, err := strconv.Atoi(value); err == nil { + reps = parsed + } + } + + for warm := 0; warm < 3; warm++ { + run(corpus) + } + + best := math.Inf(1) + valid := 0 + + for rep := 0; rep < reps; rep++ { + start := time.Now() + valid = run(corpus) + elapsed := float64(time.Since(start).Nanoseconds()) / float64(len(corpus)) + + if elapsed < best { + best = elapsed + } + } + + return result{Lang: "go", Arm: arm, NsPerOp: math.Round(best*10) / 10, Valid: valid} +} + +func pack(inputs []string) []byte { + packed := make([]byte, 0, 16*len(inputs)) + header := make([]byte, 4) + + for _, value := range inputs { + binary.LittleEndian.PutUint32(header, uint32(len(value))) + packed = append(packed, header...) + packed = append(packed, value...) + } + + return packed +} + +func main() { + root, _ := filepath.Abs(filepath.Join("..", "..")) + raw, err := os.ReadFile(filepath.Join(root, "corpus.json")) + + if err != nil { + panic(err) + } + + var corpus []string + + if err := json.Unmarshal(raw, &corpus); err != nil { + panic(err) + } + + results := []result{} + + results = append(results, measure("handwritten", corpus, func(inputs []string) int { + valid := 0 + + for _, value := range inputs { + if handwrittenIsValid(value) { + valid++ + } + } + + return valid + })) + + results = append(results, measure("generated", corpus, func(inputs []string) int { + valid := 0 + + for _, value := range inputs { + if generated.IsValid(value) { + valid++ + } + } + + return valid + })) + + // --- the shared core over wazero --------------------------------------------------------- + ctx := context.Background() + runtimeConfig := wazero.NewRuntimeConfigCompiler() + wasmRuntime := wazero.NewRuntimeWithConfig(ctx, runtimeConfig) + defer wasmRuntime.Close(ctx) + + wasmBytes, err := os.ReadFile(filepath.Join(root, "core/target/wasm32-unknown-unknown/release/brutils_bench_core.wasm")) + + if err != nil { + panic(err) + } + + instance, err := wasmRuntime.Instantiate(ctx, wasmBytes) + + if err != nil { + panic(err) + } + + memory := instance.Memory() + wasmIsValid := instance.ExportedFunction("cpf_is_valid") + wasmIsValidBatch := instance.ExportedFunction("cpf_is_valid_batch") + arenaAlloc := instance.ExportedFunction("arena_alloc") + + allocate := func(size uint64) uint32 { + out, err := arenaAlloc.Call(ctx, size) + + if err != nil { + panic(err) + } + + return uint32(out[0]) + } + + scratch := allocate(64) + batchInput := allocate(1 << 18) + batchOutput := allocate(uint64(len(corpus))) + + results = append(results, measure("wasm", corpus, func(inputs []string) int { + valid := 0 + + for _, value := range inputs { + memory.Write(scratch, []byte(value)) + out, err := wasmIsValid.Call(ctx, uint64(scratch), uint64(len(value))) + + if err != nil { + panic(err) + } + + if out[0] == 1 { + valid++ + } + } + + return valid + })) + + results = append(results, measure("wasm-batch", corpus, func(inputs []string) int { + packed := pack(inputs) + memory.Write(batchInput, packed) + + if _, err := wasmIsValidBatch.Call(ctx, uint64(batchInput), uint64(len(packed)), uint64(batchOutput), uint64(len(inputs))); err != nil { + panic(err) + } + + out, _ := memory.Read(batchOutput, uint32(len(inputs))) + valid := 0 + + for _, byteValue := range out { + if byteValue == 1 { + valid++ + } + } + + return valid + })) + + results = append(results, measure("wasm-callonly", corpus, func(inputs []string) int { + valid := 0 + + for range inputs { + out, _ := wasmIsValid.Call(ctx, uint64(scratch), 11) + + if out[0] == 1 { + valid++ + } + } + + return valid + })) + + // --- the shared core over cgo ------------------------------------------------------------- + results = append(results, measure("cgo", corpus, func(inputs []string) int { + valid := 0 + + for _, value := range inputs { + bytes := []byte(value) + + if len(bytes) == 0 { + continue + } + + if C.cpf_is_valid((*C.uchar)(unsafe.Pointer(&bytes[0])), C.size_t(len(bytes))) == 1 { + valid++ + } + + runtime.KeepAlive(bytes) + } + + return valid + })) + + results = append(results, measure("cgo-batch", corpus, func(inputs []string) int { + packed := pack(inputs) + output := make([]byte, len(inputs)) + + C.cpf_is_valid_batch( + (*C.uchar)(unsafe.Pointer(&packed[0])), + C.size_t(len(packed)), + (*C.uchar)(unsafe.Pointer(&output[0])), + C.size_t(len(inputs)), + ) + + valid := 0 + + for _, byteValue := range output { + if byteValue == 1 { + valid++ + } + } + + return valid + })) + + payload := []byte("12345678909") + + results = append(results, measure("cgo-callonly", corpus, func(inputs []string) int { + valid := 0 + + for range inputs { + if C.cpf_is_valid((*C.uchar)(unsafe.Pointer(&payload[0])), 11) == 1 { + valid++ + } + } + + return valid + })) + + for _, entry := range results { + line, _ := json.Marshal(entry) + fmt.Println(string(line)) + } +} diff --git a/spec/bench/harness/java/JavaBench.java b/spec/bench/harness/java/JavaBench.java new file mode 100644 index 000000000..35fb81bbd --- /dev/null +++ b/spec/bench/harness/java/JavaBench.java @@ -0,0 +1,158 @@ +// Java arms: handwritten source versus generated source. A JIT compiled language is the case +// where generated code has the least excuse to be slower, and this checks that it is not. + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public final class JavaBench { + private JavaBench() {} + + // The code points JavaScript's trim() strips. Java's String.trim() and strip() are both + // different sets, so the class is spelled out. + private static final String WS = + "\u0009\n\u000b\u000c\r           " + + "   

   "; + + private static final Pattern SHAPE = + Pattern.compile("^[0-9]{3}[" + WS + "./-]*[0-9]{3}[" + WS + "./-]*[0-9]{3}[" + WS + "./-]*[0-9]{2}$"); + + private static final Pattern NON_DIGITS = Pattern.compile("[^0-9]"); + + private static int checkDigit(String base) { + int sum = 0; + int weight = base.length() + 1; + + for (int index = 0; index < base.length(); index++) { + sum += (base.charAt(index) - '0') * weight; + weight--; + } + + int digit = 11 - (sum % 11); + + return digit >= 10 ? 0 : digit; + } + + private static String trimJs(String value) { + int start = 0; + int end = value.length(); + + while (start < end && WS.indexOf(value.charAt(start)) >= 0) { + start++; + } + while (end > start && WS.indexOf(value.charAt(end - 1)) >= 0) { + end--; + } + + return value.substring(start, end); + } + + static boolean handwrittenIsValid(String cpf) { + if (cpf == null) { + return false; + } + + if (!SHAPE.matcher(trimJs(cpf)).matches()) { + return false; + } + + String digits = NON_DIGITS.matcher(cpf).replaceAll(""); + + if (digits.chars().distinct().count() == 1) { + return false; + } + + return digits.charAt(9) - '0' == checkDigit(digits.substring(0, 9)) + && digits.charAt(10) - '0' == checkDigit(digits.substring(0, 10)); + } + + private static List readCorpus(Path path) throws IOException { + // The corpus is a flat JSON array of strings; parsed by hand to keep the harness + // dependency free. + String raw = Files.readString(path); + List corpus = new ArrayList<>(); + int index = 0; + + while (index < raw.length()) { + if (raw.charAt(index) != '"') { + index++; + continue; + } + + index++; + StringBuilder value = new StringBuilder(); + + while (index < raw.length() && raw.charAt(index) != '"') { + char current = raw.charAt(index); + + if (current == '\\') { + index++; + char escape = raw.charAt(index); + + switch (escape) { + case 'u' -> { + value.append((char) Integer.parseInt(raw.substring(index + 1, index + 5), 16)); + index += 4; + } + case 'n' -> value.append('\n'); + case 'r' -> value.append('\r'); + case 't' -> value.append('\t'); + default -> value.append(escape); + } + } else { + value.append(current); + } + + index++; + } + + index++; + corpus.add(value.toString()); + } + + return corpus; + } + + private static void measure(String arm, List corpus, java.util.function.Predicate check) { + for (int warm = 0; warm < 20; warm++) { + run(corpus, check); + } + + double best = Double.POSITIVE_INFINITY; + int valid = 0; + + for (int rep = 0; rep < 15; rep++) { + long start = System.nanoTime(); + valid = run(corpus, check); + double perOp = (System.nanoTime() - start) / (double) corpus.size(); + + best = Math.min(best, perOp); + } + + System.out.printf( + "{\"lang\":\"java\",\"arm\":\"%s\",\"nsPerOp\":%.1f,\"valid\":%d}%n", arm, best, valid); + } + + private static int run(List corpus, java.util.function.Predicate check) { + int valid = 0; + + for (String value : corpus) { + if (check.test(value)) { + valid++; + } + } + + return valid; + } + + public static void main(String[] args) throws IOException { + List corpus = readCorpus(Path.of(args[0])); + + measure("handwritten", corpus, JavaBench::handwrittenIsValid); + measure("generated", corpus, Cpf::isValid); + } +} diff --git a/spec/bench/harness/node-bench.ts b/spec/bench/harness/node-bench.ts new file mode 100644 index 000000000..9307e6193 --- /dev/null +++ b/spec/bench/harness/node-bench.ts @@ -0,0 +1,144 @@ +/** + * Node arms: handwritten source, generated source, and the shared Rust core over WebAssembly. + * + * Every arm validates the same 1000 inputs and reports the best nanoseconds per call over + * several repetitions, plus the number of valid inputs it found, so a wrong arm cannot win by + * doing less work. + */ +import { readFileSync } from "node:fs"; +import { resolve } from "node:path"; + +type Validator = (value: string) => boolean; + +type WasmExports = { + memory: WebAssembly.Memory; + cpf_is_valid: (ptr: number, len: number) => number; + cpf_is_valid_batch: (input: number, inputLen: number, output: number, count: number) => number; + arena_alloc: (len: number) => number; + arena_reset: () => void; +}; + +const benchDir = resolve(import.meta.dirname, ".."); +const corpus = JSON.parse(readFileSync(resolve(benchDir, "corpus.json"), "utf8")) as string[]; +const REPS = Number(process.env["BENCH_REPS"] ?? 7); +const SCRATCH_SIZE = 64; + +/** + * Times one arm over the whole corpus. + * + * @param {string} arm - The arm name. + * @param {Function} run - Validates every input and returns how many were valid. + * @returns {object} The measurement, ready to print. + */ +const measure = ( + arm: string, + run: (inputs: string[]) => number, +): { lang: string; arm: string; nsPerOp: number; valid: number } => { + for (let warm = 0; warm < 3; warm++) run(corpus); + + let best = Number.POSITIVE_INFINITY; + let valid = 0; + + for (let rep = 0; rep < REPS; rep++) { + const start = process.hrtime.bigint(); + + valid = run(corpus); + + const elapsed = Number(process.hrtime.bigint() - start); + + best = Math.min(best, elapsed / corpus.length); + } + + return { lang: "node", arm, nsPerOp: Number(best.toFixed(1)), valid }; +}; + +/** + * Wraps a validator into an arm that counts how many inputs it accepts. + * + * @param {Function} isValid - The validator under test. + * @returns {Function} The arm. + */ +const countWith = + (isValid: Validator) => + (inputs: string[]): number => { + let valid = 0; + + for (const input of inputs) if (isValid(input)) valid++; + + return valid; + }; + +const shipped = (await import(resolve(benchDir, ".build/shipped.mjs"))) as { + isValidCpf: Validator; +}; +const generated = (await import( + resolve(benchDir, ".spec-masked-strict/generated/typescript/is-valid-cpf/is-valid-cpf.ts") +)) as { isValidCpf: Validator }; + +const wasmBytes = readFileSync( + resolve(benchDir, "core/target/wasm32-unknown-unknown/release/brutils_bench_core.wasm"), +); +const { instance } = await WebAssembly.instantiate(wasmBytes, {}); +const wasm = instance.exports as unknown as WasmExports; +const encoder = new TextEncoder(); + +// One scratch buffer, reused: encoding into a fresh array per call would measure the allocator. +wasm.arena_reset(); + +const scratchPtr = wasm.arena_alloc(SCRATCH_SIZE); + +const runWasm = (inputs: string[]): number => { + const view = new Uint8Array(wasm.memory.buffer); + let valid = 0; + + for (const input of inputs) { + const { written } = encoder.encodeInto( + input, + view.subarray(scratchPtr, scratchPtr + SCRATCH_SIZE), + ); + + if (wasm.cpf_is_valid(scratchPtr, written) === 1) valid++; + } + + return valid; +}; + +wasm.arena_reset(); + +const batchInputPtr = wasm.arena_alloc(1 << 18); +const batchOutputPtr = wasm.arena_alloc(corpus.length); + +const runWasmBatch = (inputs: string[]): number => { + const view = new Uint8Array(wasm.memory.buffer); + const lengths = new DataView(wasm.memory.buffer); + let offset = batchInputPtr; + + for (const input of inputs) { + const { written } = encoder.encodeInto( + input, + view.subarray(offset + 4, offset + 4 + SCRATCH_SIZE), + ); + + lengths.setUint32(offset, written, true); + offset += 4 + written; + } + + wasm.cpf_is_valid_batch(batchInputPtr, offset - batchInputPtr, batchOutputPtr, inputs.length); + + let valid = 0; + + for (let index = 0; index < inputs.length; index++) { + if (view[batchOutputPtr + index] === 1) valid++; + } + + return valid; +}; + +const results = [ + measure("handwritten", countWith(shipped.isValidCpf)), + measure("generated", countWith(generated.isValidCpf)), + measure("wasm", runWasm), + measure("wasm-batch", runWasmBatch), +]; + +for (const result of results) console.log(JSON.stringify(result)); diff --git a/spec/bench/harness/python_bench.py b/spec/bench/harness/python_bench.py new file mode 100644 index 000000000..37b5e32cf --- /dev/null +++ b/spec/bench/harness/python_bench.py @@ -0,0 +1,275 @@ +"""Python arms: handwritten source, generated source, the Rust core over wasm, and over ctypes. + +Every arm validates the same 1000 inputs and reports the best nanoseconds per call over several +repetitions, plus how many it found valid, so an arm cannot win by doing less work. +""" + +import ctypes +import json +import os +import re +import struct +import sys +import time +from pathlib import Path + +BENCH = Path(__file__).resolve().parent.parent +CORPUS = json.loads((BENCH / "corpus.json").read_text()) +REPS = int(os.environ.get("BENCH_REPS", "7")) + +sys.path.insert(0, str(BENCH / ".spec-masked-strict/generated/python")) + +# --- arm: handwritten, the way a contributor would write it --------------------------------- + +SHAPE = re.compile(r"^\d{3}[\s.\-/]*\d{3}[\s.\-/]*\d{3}[\s.\-/]*\d{2}$", re.ASCII) +NON_DIGITS = re.compile(r"\D", re.ASCII) + + +def _check_digit(base): + total = sum(int(digit) * (len(base) + 1 - index) for index, digit in enumerate(base)) + digit = 11 - (total % 11) + + return 0 if digit >= 10 else digit + + +def handwritten_is_valid(cpf): + if not isinstance(cpf, str): + return False + + if not SHAPE.match(cpf.strip()): + return False + + digits = NON_DIGITS.sub("", cpf) + + if digits == digits[0] * 11: + return False + + return int(digits[9]) == _check_digit(digits[:9]) and int(digits[10]) == _check_digit(digits[:10]) + + +# --- arm: the generated source --------------------------------------------------------------- + +from brutils.cpf import is_valid as generated_is_valid # noqa: E402 + +# --- arm: what the emitter COULD generate for Python ----------------------------------------- +# +# Same spec, same semantics, but the charsets are rendered as an explicit regex character class +# instead of a per code point loop, so the work happens in CPython's C regex engine. The class is +# spelled out code point by code point: `\s` would not mean the same set. + +WS = "\t\n\x0b\x0c\r \xa0  - 

   " +WS_CHARS = "\t\n\x0b\x0c\r \xa0            

   " +SEP = f"[{WS}.\\-/]" +OPT_SHAPE = re.compile(f"^[0-9]{{3}}{SEP}*[0-9]{{3}}{SEP}*[0-9]{{3}}{SEP}*[0-9]{{2}}$") +OPT_NON_DIGITS = re.compile("[^0-9]") + + +def generated_opt_is_valid(cpf): + if not isinstance(cpf, str): + return False + + if not OPT_SHAPE.match(cpf.strip(WS_CHARS)): + return False + + digits = OPT_NON_DIGITS.sub("", cpf) + + if digits == digits[0] * 11: + return False + + return int(digits[9]) == _check_digit(digits[:9]) and int(digits[10]) == _check_digit(digits[:10]) + + +# --- arm: one anchored regex with capture groups --------------------------------------------- +# +# The trim, the shape check and the digit extraction collapse into a single match: the leading +# and trailing whitespace become `[WS]*` and the four digit runs are captured instead of being +# filtered out of the string afterwards. + +WS_CLASS = f"[{WS}]" +OPT2_SHAPE = re.compile( + f"^{WS_CLASS}*([0-9]{{3}}){SEP}*([0-9]{{3}}){SEP}*([0-9]{{3}}){SEP}*([0-9]{{2}}){WS_CLASS}*$" +) + + +def generated_opt2_is_valid(cpf): + if not isinstance(cpf, str): + return False + + match = OPT2_SHAPE.match(cpf) + + if match is None: + return False + + digits = "".join(match.groups()) + + if digits == digits[0] * 11: + return False + + return int(digits[9]) == _check_digit(digits[:9]) and int(digits[10]) == _check_digit(digits[:10]) + +# --- arms: the shared Rust core -------------------------------------------------------------- + +import wasmtime # noqa: E402 + +WASM_PATH = BENCH / "core/target/wasm32-unknown-unknown/release/brutils_bench_core.wasm" +engine = wasmtime.Engine() +module = wasmtime.Module.from_file(engine, str(WASM_PATH)) +store = wasmtime.Store(engine) +instance = wasmtime.Instance(store, module, []) +exports = instance.exports(store) +memory = exports["memory"] +wasm_is_valid = exports["cpf_is_valid"] +wasm_is_valid_batch = exports["cpf_is_valid_batch"] +arena_alloc = exports["arena_alloc"] +arena_reset = exports["arena_reset"] + +arena_reset(store) +scratch = arena_alloc(store, 64) +batch_input = arena_alloc(store, 1 << 18) +batch_output = arena_alloc(store, len(CORPUS)) + +LIB_PATH = BENCH / "core/target/release/libbrutils_bench_core.so" +lib = ctypes.CDLL(str(LIB_PATH)) +lib.cpf_is_valid.argtypes = [ctypes.c_char_p, ctypes.c_size_t] +lib.cpf_is_valid.restype = ctypes.c_int +lib.cpf_is_valid_batch.argtypes = [ctypes.c_char_p, ctypes.c_size_t, ctypes.c_char_p, ctypes.c_size_t] +lib.cpf_is_valid_batch.restype = ctypes.c_int + + +def run_wasm(inputs): + valid = 0 + + for value in inputs: + encoded = value.encode("utf-8") + memory.write(store, encoded, scratch) + + if wasm_is_valid(store, scratch, len(encoded)) == 1: + valid += 1 + + return valid + + +# The same arm, written the way a binding generator would: the linear memory is poked through +# its raw pointer instead of wasmtime-py's bounds checked `Memory.write`. +MEM_PTR = ctypes.cast(memory.data_ptr(store), ctypes.POINTER(ctypes.c_char)) + + +def run_wasm_fast(inputs): + valid = 0 + + for value in inputs: + encoded = value.encode("utf-8") + length = len(encoded) + ctypes.memmove(ctypes.byref(MEM_PTR.contents, scratch), encoded, length) + + if wasm_is_valid(store, scratch, length) == 1: + valid += 1 + + return valid + + +def run_wasm_callonly(inputs): + """Just the boundary: the same pointer and length every time, no marshalling at all.""" + valid = 0 + + for _ in inputs: + if wasm_is_valid(store, scratch, 11) == 1: + valid += 1 + + return valid + + +def run_ffi_callonly(inputs): + """Just the boundary, over ctypes.""" + payload = b"12345678909" + valid = 0 + + for _ in inputs: + if lib.cpf_is_valid(payload, 11) == 1: + valid += 1 + + return valid + + +def run_wasm_batch(inputs): + packed = bytearray() + + for value in inputs: + encoded = value.encode("utf-8") + packed += struct.pack("= 10 ? 0 : digit +end + +def handwritten_valid?(cpf) + return false unless cpf.is_a?(String) + return false unless SHAPE.match?(cpf.strip) + + digits = cpf.gsub(NON_DIGITS, '') + return false if digits == digits[0] * 11 + + digits[9].to_i == check_digit(digits[0...9]) && digits[10].to_i == check_digit(digits[0...10]) +end + + +# --- arm: what the emitter COULD generate for Ruby ------------------------------------------- +# +# Same spec, same semantics, but the charsets are rendered as an explicit regex character class +# instead of a per code point loop, so the work happens in Onigmo rather than in Ruby. The class +# is spelled out code point by code point: `\\s` is a different set, and `^`/`$` would be line +# anchors, so `\\A`/`\\z` are used. + +WS_CODEPOINTS = [0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x20, 0xa0, 0x1680, 0x2000, 0x2001, 0x2002, 0x2003, + 0x2004, 0x2005, 0x2006, 0x2007, 0x2008, 0x2009, 0x200a, 0x2028, 0x2029, 0x202f, + 0x205f, 0x3000, 0xfeff].freeze +WS_STRING = WS_CODEPOINTS.pack('U*') +SEP_CLASS = "[#{WS_CODEPOINTS.map { |code| format('\\u{%04x}', code) }.join}\\.\\-\\/]" +OPT_SHAPE = Regexp.new("\\A[0-9]{3}#{SEP_CLASS}*[0-9]{3}#{SEP_CLASS}*[0-9]{3}#{SEP_CLASS}*[0-9]{2}\\z") +OPT_NON_DIGITS = /[^0-9]/.freeze + +def generated_opt_valid?(cpf) + return false unless cpf.is_a?(String) + return false unless OPT_SHAPE.match?(cpf.gsub(/\A[#{WS_STRING}]+|[#{WS_STRING}]+\z/, '')) + + digits = cpf.gsub(OPT_NON_DIGITS, '') + return false if digits == digits[0] * 11 + + digits[9].to_i == check_digit(digits[0...9]) && digits[10].to_i == check_digit(digits[0...10]) +end + + +# --- arm: one anchored regex with capture groups --------------------------------------------- +# +# The trim, the shape check and the digit extraction collapse into a single match: the leading +# and trailing whitespace become `[WS]*`, and the four digit runs are captured instead of being +# filtered out of the string afterwards. No intermediate string is allocated. + +WS_CLASS = "[#{WS_CODEPOINTS.map { |code| format('\\u{%04x}', code) }.join}]" +OPT2_SHAPE = Regexp.new( + "\\A#{WS_CLASS}*([0-9]{3})#{SEP_CLASS}*([0-9]{3})#{SEP_CLASS}*([0-9]{3})#{SEP_CLASS}*([0-9]{2})#{WS_CLASS}*\\z" +) + +def generated_opt2_valid?(cpf) + return false unless cpf.is_a?(String) + + match = OPT2_SHAPE.match(cpf) + return false if match.nil? + + digits = "#{match[1]}#{match[2]}#{match[3]}#{match[4]}" + return false if digits == digits[0] * 11 + + digits[9].to_i == check_digit(digits[0...9]) && digits[10].to_i == check_digit(digits[0...10]) +end + +# --- the shared Rust core over wasm ---------------------------------------------------------- + +engine = Wasmtime::Engine.new +mod = Wasmtime::Module.from_file(engine, File.join(BENCH, 'core/target/wasm32-unknown-unknown/release/brutils_bench_core.wasm')) +store = Wasmtime::Store.new(engine) +instance = Wasmtime::Instance.new(store, mod) +memory = instance.export('memory').to_memory +wasm_is_valid = instance.export('cpf_is_valid').to_func +wasm_is_valid_batch = instance.export('cpf_is_valid_batch').to_func +arena_alloc = instance.export('arena_alloc').to_func +instance.export('arena_reset').to_func.call + +scratch = arena_alloc.call(64) +batch_input = arena_alloc.call(1 << 18) +batch_output = arena_alloc.call(CORPUS.length) + +# --- the same core over Fiddle (plain C ABI) -------------------------------------------------- + +LIB = Fiddle.dlopen(File.join(BENCH, 'core/target/release/libbrutils_bench_core.so')) +FFI_IS_VALID = Fiddle::Function.new(LIB['cpf_is_valid'], [Fiddle::TYPE_VOIDP, Fiddle::TYPE_SIZE_T], Fiddle::TYPE_INT) +FFI_IS_VALID_BATCH = Fiddle::Function.new( + LIB['cpf_is_valid_batch'], + [Fiddle::TYPE_VOIDP, Fiddle::TYPE_SIZE_T, Fiddle::TYPE_VOIDP, Fiddle::TYPE_SIZE_T], + Fiddle::TYPE_INT +) + +def pack(inputs) + packed = +'' + inputs.each do |value| + bytes = value.dup.force_encoding(Encoding::BINARY) + packed << [bytes.bytesize].pack('V') << bytes + end + packed +end + +ARMS = { + 'handwritten' => ->(inputs) { inputs.count { |value| handwritten_valid?(value) } }, + 'generated' => ->(inputs) { inputs.count { |value| BrazilianUtils::CPFUtils.valid?(value) } }, + 'generated-opt' => ->(inputs) { inputs.count { |value| generated_opt_valid?(value) } }, + 'generated-opt2' => ->(inputs) { inputs.count { |value| generated_opt2_valid?(value) } }, + 'wasm' => lambda { |inputs| + valid = 0 + inputs.each do |value| + bytes = value.dup.force_encoding(Encoding::BINARY) + memory.write(scratch, bytes) + valid += 1 if wasm_is_valid.call(scratch, bytes.bytesize) == 1 + end + valid + }, + 'wasm-batch' => lambda { |inputs| + packed = pack(inputs) + memory.write(batch_input, packed) + wasm_is_valid_batch.call(batch_input, packed.bytesize, batch_output, inputs.length) + memory.read(batch_output, inputs.length).bytes.count(1) + }, + 'ffi' => lambda { |inputs| + valid = 0 + inputs.each do |value| + bytes = value.dup.force_encoding(Encoding::BINARY) + valid += 1 if FFI_IS_VALID.call(bytes, bytes.bytesize) == 1 + end + valid + }, + 'ffi-batch' => lambda { |inputs| + packed = pack(inputs) + output = Fiddle::Pointer.malloc(inputs.length) + FFI_IS_VALID_BATCH.call(packed, packed.bytesize, output, inputs.length) + output.to_str(inputs.length).bytes.count(1) + }, + 'wasm-callonly' => lambda { |inputs| + valid = 0 + inputs.each { valid += 1 if wasm_is_valid.call(scratch, 11) == 1 } + valid + }, + 'ffi-callonly' => lambda { |inputs| + payload = '12345678909' + valid = 0 + inputs.each { valid += 1 if FFI_IS_VALID.call(payload, 11) == 1 } + valid + } +}.freeze + +ARMS.each do |name, run| + 2.times { run.call(CORPUS) } + + best = Float::INFINITY + valid = 0 + + REPS.times do + start = Process.clock_gettime(Process::CLOCK_MONOTONIC, :nanosecond) + valid = run.call(CORPUS) + elapsed = Process.clock_gettime(Process::CLOCK_MONOTONIC, :nanosecond) - start + best = [best, elapsed.to_f / CORPUS.length].min + end + + puts JSON.generate('lang' => 'ruby', 'arm' => name, 'nsPerOp' => best.round(1), 'valid' => valid) + $stdout.flush +end diff --git a/spec/bench/harness/uniffi_bench.py b/spec/bench/harness/uniffi_bench.py new file mode 100644 index 000000000..03397005b --- /dev/null +++ b/spec/bench/harness/uniffi_bench.py @@ -0,0 +1,53 @@ +"""The same Rust core, reached through UniFFI generated Python bindings instead of hand rolled +ctypes, so the cost of an off the shelf binding generator is measured rather than assumed. + +Build first: + cargo build --release --manifest-path spec/bench/uniffi/Cargo.toml + cd spec/bench/uniffi && ./target/release/uniffi-bindgen generate \ + --library target/release/libbrutils_uniffi.so --language python --out-dir ../.build/uniffi-python + cp spec/bench/uniffi/target/release/libbrutils_uniffi.so spec/bench/.build/uniffi-python/ +""" + +import json +import os +import sys +import time +from pathlib import Path + +BENCH = Path(__file__).resolve().parent.parent +CORPUS = json.loads((BENCH / "corpus.json").read_text()) +REPS = int(os.environ.get("BENCH_REPS", "7")) + +sys.path.insert(0, str(BENCH / ".build/uniffi-python")) + +import brutils_uniffi # noqa: E402 + + +def measure(arm, run): + for _ in range(2): + run(CORPUS) + + best = float("inf") + valid = 0 + + for _ in range(REPS): + start = time.perf_counter_ns() + valid = run(CORPUS) + best = min(best, (time.perf_counter_ns() - start) / len(CORPUS)) + + return {"lang": "python", "arm": arm, "nsPerOp": round(best, 1), "valid": valid} + + +print( + json.dumps( + measure( + "uniffi", + lambda inputs: sum(1 for value in inputs if brutils_uniffi.cpf_is_valid(value)), + ) + ) +) +print( + json.dumps( + measure("uniffi-batch", lambda inputs: sum(brutils_uniffi.cpf_is_valid_batch(inputs))) + ) +) diff --git a/spec/bench/prepare.ts b/spec/bench/prepare.ts new file mode 100644 index 000000000..6da8a4225 --- /dev/null +++ b/spec/bench/prepare.ts @@ -0,0 +1,50 @@ +import { execFileSync } from "node:child_process"; +/** + * Prepares the benchmark inputs. + * + * 1. Writes `spec/bench/corpus.json`: the inputs every arm, in every language, validates. + * 2. Emits the generated `isValidCpf` for each language under the SAME profile + * (`masked-strict`), so the source level arms do identical work. The published packages adopt + * different profiles, which is right for them and useless for a benchmark. + * + * Usage: `node spec/bench/prepare.ts` + */ +import { cpSync, mkdirSync, readFileSync, rmSync, writeFileSync } from "node:fs"; +import { resolve } from "node:path"; + +import { buildCorpus } from "../codegen/corpus.ts"; + +const benchDir = import.meta.dirname; +const specDir = resolve(benchDir, ".."); +const tempSpec = resolve(benchDir, ".spec-masked-strict"); + +// A corpus of realistic size: mostly valid CPFs, masked and bare, plus the rejects. +const corpus = buildCorpus(4000) + .filter((input) => input.length > 0 && input.length < 24) + .slice(0, 1000); + +writeFileSync(resolve(benchDir, "corpus.json"), `${JSON.stringify(corpus)}\n`); + +rmSync(tempSpec, { recursive: true, force: true }); +mkdirSync(tempSpec, { recursive: true }); + +for (const entry of ["codegen", "schema", "utilities", "vectors", "utilities.json"]) { + cpSync(resolve(specDir, entry), resolve(tempSpec, entry), { recursive: true }); +} + +const cpfPath = resolve(tempSpec, "utilities/is-valid-cpf.json"); +const cpf = JSON.parse(readFileSync(cpfPath, "utf8")) as { + adopted: Record; +}; + +for (const target of Object.keys(cpf.adopted)) cpf.adopted[target] = { profile: "masked-strict" }; + +writeFileSync(cpfPath, JSON.stringify(cpf, null, "\t")); + +// Only `is-valid-cpf` is benchmarked, so the other two utilities are dropped from the run. +writeFileSync(resolve(tempSpec, "utilities.json"), JSON.stringify({ utilities: ["is-valid-cpf"] })); + +execFileSync("node", [resolve(tempSpec, "codegen/emit.ts")], { stdio: "inherit" }); + +console.log(`corpus: ${corpus.length} inputs`); +console.log(`generated: ${resolve(tempSpec, "generated")}`); diff --git a/spec/bench/results.jsonl b/spec/bench/results.jsonl new file mode 100644 index 000000000..a5e1b86a7 --- /dev/null +++ b/spec/bench/results.jsonl @@ -0,0 +1,37 @@ +{"lang":"node","arm":"handwritten","nsPerOp":386.2,"valid":337} +{"lang":"node","arm":"generated","nsPerOp":256.5,"valid":337} +{"lang":"node","arm":"wasm","nsPerOp":224.6,"valid":337} +{"lang":"node","arm":"wasm-batch","nsPerOp":240.5,"valid":337} +{"lang": "python", "arm": "handwritten", "nsPerOp": 2460.6, "valid": 333} +{"lang": "python", "arm": "generated", "nsPerOp": 1366.0, "valid": 337} +{"lang": "python", "arm": "generated-opt", "nsPerOp": 2511.0, "valid": 337} +{"lang": "python", "arm": "generated-opt2", "nsPerOp": 2472.7, "valid": 337} +{"lang": "python", "arm": "wasm", "nsPerOp": 38039.3, "valid": 337} +{"lang": "python", "arm": "wasm-rawmem", "nsPerOp": 32422.0, "valid": 337} +{"lang": "python", "arm": "wasm-batch", "nsPerOp": 306.3, "valid": 337} +{"lang": "python", "arm": "ffi", "nsPerOp": 535.3, "valid": 337} +{"lang": "python", "arm": "ffi-batch", "nsPerOp": 239.9, "valid": 337} +{"lang": "python", "arm": "wasm-callonly", "nsPerOp": 30058.9, "valid": 0} +{"lang": "python", "arm": "ffi-callonly", "nsPerOp": 472.3, "valid": 1000} +{"lang":"ruby","arm":"handwritten","nsPerOp":3675.8,"valid":329} +{"lang":"ruby","arm":"generated","nsPerOp":2020.1,"valid":337} +{"lang":"ruby","arm":"generated-opt","nsPerOp":11607.4,"valid":337} +{"lang":"ruby","arm":"generated-opt2","nsPerOp":3975.2,"valid":337} +{"lang":"ruby","arm":"wasm","nsPerOp":729.9,"valid":337} +{"lang":"ruby","arm":"wasm-batch","nsPerOp":430.0,"valid":337} +{"lang":"ruby","arm":"ffi","nsPerOp":1662.1,"valid":337} +{"lang":"ruby","arm":"ffi-batch","nsPerOp":404.9,"valid":337} +{"lang":"ruby","arm":"wasm-callonly","nsPerOp":521.1,"valid":0} +{"lang":"ruby","arm":"ffi-callonly","nsPerOp":1518.2,"valid":1000} +{"lang":"go","arm":"handwritten","nsPerOp":446.2,"valid":334} +{"lang":"go","arm":"generated","nsPerOp":193.1,"valid":337} +{"lang":"go","arm":"wasm","nsPerOp":189.1,"valid":337} +{"lang":"go","arm":"wasm-batch","nsPerOp":104.5,"valid":337} +{"lang":"go","arm":"wasm-callonly","nsPerOp":103.8,"valid":0} +{"lang":"go","arm":"cgo","nsPerOp":119.1,"valid":337} +{"lang":"go","arm":"cgo-batch","nsPerOp":52.6,"valid":337} +{"lang":"go","arm":"cgo-callonly","nsPerOp":97.5,"valid":1000} +{"lang":"java","arm":"handwritten","nsPerOp":1365.3,"valid":337} +{"lang":"java","arm":"generated","nsPerOp":493.6,"valid":337} +{"lang": "python", "arm": "uniffi", "nsPerOp": 9064.2, "valid": 337} +{"lang": "python", "arm": "uniffi-batch", "nsPerOp": 6195.8, "valid": 337} diff --git a/spec/bench/run-all.sh b/spec/bench/run-all.sh new file mode 100644 index 000000000..d70ab4824 --- /dev/null +++ b/spec/bench/run-all.sh @@ -0,0 +1,29 @@ +#!/usr/bin/env bash +# Rebuilds every artifact and runs every benchmark arm, writing one JSON line per measurement. +# +# Usage: bash spec/bench/run-all.sh > spec/bench/results.jsonl +set -euo pipefail + +root="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)" +bench="${root}/spec/bench" + +cargo build --quiet --release --manifest-path "${bench}/core/Cargo.toml" +cargo build --quiet --release --target wasm32-unknown-unknown --manifest-path "${bench}/core/Cargo.toml" +node "${bench}/prepare.ts" >/dev/null + +mkdir -p "${bench}/.build" +npx --yes esbuild "${root}/src/index.ts" --bundle --format=esm --platform=neutral \ + --outfile="${bench}/.build/shipped.mjs" --log-level=error + +node "${bench}/harness/node-bench.ts" +python3 "${bench}/harness/python_bench.py" +ruby "${bench}/harness/ruby_bench.rb" + +cp "${bench}/.spec-masked-strict/generated/go/cpf/cpf.go" "${bench}/harness/go/generated/cpf/cpf.go" +cp "${bench}/.spec-masked-strict/generated/go/specruntime/specruntime.go" "${bench}/harness/go/generated/specruntime/specruntime.go" +sed -i 's|brazilianutils/spec/specruntime|brutilsbench/generated/specruntime|' "${bench}/harness/go/generated/cpf/cpf.go" +(cd "${bench}/harness/go" && go run .) + +cp "${bench}/.spec-masked-strict/generated/java/Cpf.java" "${bench}/.spec-masked-strict/generated/java/SpecRuntime.java" "${bench}/harness/java/" +javac -nowarn -d "${bench}/.build/java" "${bench}"/harness/java/*.java 2>/dev/null +java -cp "${bench}/.build/java" JavaBench "${bench}/corpus.json" 2>/dev/null diff --git a/spec/bench/table.py b/spec/bench/table.py new file mode 100644 index 000000000..98accbe45 --- /dev/null +++ b/spec/bench/table.py @@ -0,0 +1,92 @@ +"""Rewrites the results table in the investigation report from `results.jsonl`. + +Usage: python3 spec/bench/table.py +""" + +import collections +import json +from pathlib import Path + +BENCH = Path(__file__).resolve().parent +REPORT = BENCH.parent / "BINDINGS-INVESTIGATION.md" + +LABEL = { + "handwritten": "handwritten", + "generated": "**generated**", + "wasm": "wasm", + "wasm-batch": "wasm-batch", + "wasm-callonly": "wasm-callonly", + "ffi": "ffi (ctypes)", + "ffi-batch": "ffi-batch", + "uniffi": "**uniffi**", + "uniffi-batch": "uniffi-batch", + "cgo": "cgo", + "cgo-batch": "cgo-batch", +} + +LAYOUT = [ + ("Node", "node", ["handwritten", "generated", "wasm", "wasm-batch"]), + ( + "Python", + "python", + [ + "handwritten", + "generated", + "wasm", + "wasm-callonly", + "wasm-batch", + "ffi", + "ffi-batch", + "uniffi", + "uniffi-batch", + ], + ), + ("Ruby", "ruby", ["handwritten", "generated", "wasm", "wasm-batch", "ffi"]), + ("Go", "go", ["handwritten", "generated", "wasm", "wasm-batch", "cgo", "cgo-batch"]), + ("Java", "java", ["handwritten", "generated"]), +] + + +def main() -> None: + rows = [json.loads(line) for line in (BENCH / "results.jsonl").read_text().splitlines() if line] + by = collections.defaultdict(dict) + + for row in rows: + by[row["lang"]][row["arm"]] = row + + lines = ["| Language | Arm | ns/op | × hand | valid |", "| --- | --- | ---: | ---: | ---: |"] + + for title, lang, arms in LAYOUT: + base = by[lang]["handwritten"]["nsPerOp"] + + for arm in arms: + row = by[lang][arm] + label = LABEL[arm] + + if lang == "ruby" and arm == "ffi": + label = "ffi (Fiddle)" + if lang == "go" and arm == "wasm": + label = "wasm (wazero)" + + ratio = row["nsPerOp"] / base + emphasise = arm in ("generated", "uniffi") + ns = f"**{row['nsPerOp']:.1f}**" if emphasise else f"{row['nsPerOp']:.1f}" + rel = f"**{ratio:.2f}**" if emphasise else f"{ratio:.2f}" + valid = "—" if arm.endswith("callonly") else str(row["valid"]) + + if arm == "handwritten" and row["valid"] != 337: + valid = f"**{row['valid']}**" + + lines.append(f"| {title} | {label} | {ns} | {rel} | {valid} |") + + table = "\n".join(lines) + report = REPORT.read_text(encoding="utf-8") + start = report.index("| Language | Arm") + end = report.index("\n\n---", start) + + REPORT.write_text(report[:start] + table + report[end:], encoding="utf-8") + print(table) + + +if __name__ == "__main__": + main() diff --git a/spec/bench/uniffi/Cargo.lock b/spec/bench/uniffi/Cargo.lock new file mode 100644 index 000000000..0217ab7a5 --- /dev/null +++ b/spec/bench/uniffi/Cargo.lock @@ -0,0 +1,711 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "anstyle" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "940b3a0ca603d1eade50a4846a2afffd5ef57a9feac2c0e2ec2e14f9ead76000" + +[[package]] +name = "anyhow" +version = "1.0.104" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "330a5ed07fa54e4702c9d6c4174f74427fc0ef6e214bbd677ae50a5099946470" + +[[package]] +name = "askama" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d4744ed2eef2645831b441d8f5459689ade2ab27c854488fbab1fbe94fce1a7" +dependencies = [ + "askama_derive", + "itoa", + "percent-encoding", + "serde", + "serde_json", +] + +[[package]] +name = "askama_derive" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d661e0f57be36a5c14c48f78d09011e67e0cb618f269cca9f2fd8d15b68c46ac" +dependencies = [ + "askama_parser", + "basic-toml", + "memchr", + "proc-macro2", + "quote", + "rustc-hash", + "serde", + "serde_derive", + "syn 2.0.119", +] + +[[package]] +name = "askama_parser" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf315ce6524c857bb129ff794935cf6d42c82a6cff60526fe2a63593de4d0d4f" +dependencies = [ + "memchr", + "serde", + "serde_derive", + "winnow", +] + +[[package]] +name = "autocfg" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2032f911046de80f0a198e0901378627c33f59ea0ac00e363d481118bd70a53" + +[[package]] +name = "basic-toml" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba62675e8242a4c4e806d12f11d136e626e6c8361d6b829310732241652a178a" +dependencies = [ + "serde", +] + +[[package]] +name = "bitflags" +version = "2.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ded4057c258ba199e2d26386d3af3780957ecaee6c4ef4041c6b4b8b97c0b06" + +[[package]] +name = "brutils_uniffi" +version = "0.0.0" +dependencies = [ + "uniffi", +] + +[[package]] +name = "bytes" +version = "1.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc652a48c352aef3ea3aed32080501cf3ef6ed5da78602a020c991775b0aff04" + +[[package]] +name = "camino" +version = "1.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbbad30e4b4c14a39e3cc8aed085a12a327257c316619c93581e017bc52be591" +dependencies = [ + "serde_core", +] + +[[package]] +name = "cargo-platform" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e35af189006b9c0f00a064685c727031e3ed2d8020f7ba284d78cc2671bd36ea" +dependencies = [ + "serde", +] + +[[package]] +name = "cargo_metadata" +version = "0.19.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd5eb614ed4c27c5d706420e4320fbe3216ab31fa1c33cd8246ac36dae4479ba" +dependencies = [ + "camino", + "cargo-platform", + "semver", + "serde", + "serde_json", + "thiserror", +] + +[[package]] +name = "cfg-if" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e7648175b45a9a48536d676f68d918270699102aa8dab5496df06904c914600" + +[[package]] +name = "clap" +version = "4.6.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa8876b300ab35ba921adea3dfd70157a46249b33f95c9084ae5709785478946" +dependencies = [ + "clap_builder", + "clap_derive", +] + +[[package]] +name = "clap_builder" +version = "4.6.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0797fb7aeb1406c84efac526901f7ec3ead2124f946b494e72879d4b54704d" +dependencies = [ + "anstyle", + "clap_lex", + "strsim", +] + +[[package]] +name = "clap_derive" +version = "4.6.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9c751b79415d4e559e3d1fcf128e09e720eb673a06d26cf6f392d37d75b66e0" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn 3.0.6", +] + +[[package]] +name = "clap_lex" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c133bc6a41be0d194c306b5506d15e6feeea7b1d6604bd3f8310dfb2ca96486" + +[[package]] +name = "equivalent" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" + +[[package]] +name = "errno" +version = "0.3.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" +dependencies = [ + "libc", + "windows-sys", +] + +[[package]] +name = "fastrand" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da7c62ceae207dd37ea5b845da6a0696c799f85e97da1ab5b7910be3c1c80223" + +[[package]] +name = "fs-err" +version = "2.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88a41f105fe1d5b6b34b2055e3dc59bb79b46b48b2040b9e6c7b4b5de097aa41" +dependencies = [ + "autocfg", +] + +[[package]] +name = "getrandom" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "300e883d756b2e4ec94e02791f39b04b522276138852cfc41d9fb7e904106099" +dependencies = [ + "cfg-if", + "libc", + "r-efi", +] + +[[package]] +name = "glob" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4eba85ea1d0a966a983acd07deee566e67395d2d96b6fb39e62b5a833f1eb0b" + +[[package]] +name = "goblin" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b363a30c165f666402fe6a3024d3bec7ebc898f96a4a23bd1c99f8dbf3f4f47" +dependencies = [ + "log", + "plain", + "scroll", +] + +[[package]] +name = "hashbrown" +version = "0.17.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a" + +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + +[[package]] +name = "indexmap" +version = "2.14.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc4e190f5d26ca7051642629da2c52fc03bde85a03197c99408dcd291734c855" +dependencies = [ + "equivalent", + "hashbrown", +] + +[[package]] +name = "itoa" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" + +[[package]] +name = "libc" +version = "0.2.189" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3eaf3ede3fee6db1a4c2ee091bf8a8b4dccdc6d17f656fb07896ee72867612f2" + +[[package]] +name = "linux-raw-sys" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53" + +[[package]] +name = "log" +version = "0.4.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9f8bd3e56ce4dfc153cf470fffbfa98c7620958b312ca5c3a4b8d5181fd13c6" + +[[package]] +name = "memchr" +version = "2.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf8baf1c55e62ffcace7a9f06f4bd9cd3f0c4beb022d3b367256b91b87513d98" + +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + +[[package]] +name = "nom" +version = "7.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +dependencies = [ + "memchr", + "minimal-lexical", +] + +[[package]] +name = "once_cell" +version = "1.21.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" + +[[package]] +name = "percent-encoding" +version = "2.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" + +[[package]] +name = "plain" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4596b6d070b27117e987119b4dac604f3c58cfb0b191112e24771b2faeac1a6" + +[[package]] +name = "proc-macro2" +version = "1.0.107" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "985e7ec9bb745e6ce6535b544d84d6cd6f7ad8bd711c398938ae983b91a766d9" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.47" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fbf4db142a473a8d80c26bbf18454ed458bf8d26c8219c331daecfdbd079001" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "r-efi" +version = "6.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" + +[[package]] +name = "rustc-hash" +version = "2.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b1e7f9a428571be2dc5bc0505c13fb6bf936822b894ec87abf8a08a4e51742d" + +[[package]] +name = "rustix" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "891efababe418670775f199f0d233d84843c227a0949a883ce15b37c78d6629d" +dependencies = [ + "bitflags", + "errno", + "libc", + "linux-raw-sys", + "windows-sys", +] + +[[package]] +name = "scroll" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ab8598aa408498679922eff7fa985c25d58a90771bd6be794434c5277eab1a6" +dependencies = [ + "scroll_derive", +] + +[[package]] +name = "scroll_derive" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1783eabc414609e28a5ba76aee5ddd52199f7107a0b24c2e9746a1ecc34a683d" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "semver" +version = "1.0.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd" +dependencies = [ + "serde", + "serde_core", +] + +[[package]] +name = "serde" +version = "1.0.229" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4148590afebada386688f18773da617792bf2ef03ffc1e4cbd2b1d45b023e0ba" +dependencies = [ + "serde_core", + "serde_derive", +] + +[[package]] +name = "serde_core" +version = "1.0.229" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67dca2c9c51e58a4791a4b1ed58308b39c64224d349a935ab5039aa360942a48" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.229" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7a5d71263a5a7d47b41f6b3f06ba276f10cc18b0931f1799f710578e2309348" +dependencies = [ + "proc-macro2", + "quote", + "syn 3.0.6", +] + +[[package]] +name = "serde_json" +version = "1.0.151" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c841b55ecdae098c80dcae9cf767f6f8a0c2cdb3416bbef72181df4d0fe73f14" +dependencies = [ + "itoa", + "memchr", + "serde", + "serde_core", + "zmij", +] + +[[package]] +name = "siphasher" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d" + +[[package]] +name = "smawk" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8e2fb0f499abb4d162f2bedad68f5ef91a1682b5a03596ddb67efd37768d100" + +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + +[[package]] +name = "strsim" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" + +[[package]] +name = "syn" +version = "2.0.119" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "872831b642d1a07999a962a351ed35b955ea2cfc8f3862091e2a240a84f17297" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "3.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8593e8e72159ed2257d083c7a454a85cbf854f37a0966d8d483aff8c8a3ebcee" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "tempfile" +version = "3.27.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd" +dependencies = [ + "fastrand", + "getrandom", + "once_cell", + "rustix", + "windows-sys", +] + +[[package]] +name = "textwrap" +version = "0.16.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ecfad6c3abc80a577f2b91c1e412ee57e7a060d430b553c1b0c940974ebcd49" +dependencies = [ + "smawk", + "unicode-width", +] + +[[package]] +name = "thiserror" +version = "2.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec86235f5fcc2a73650310756d2ac5b138a5780bbbdfae3eeccec992c435ba4f" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "2.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc04cd3e1236dd4a98afca4569f2deb3f120e5422a4023be2cb683f8486292af" +dependencies = [ + "proc-macro2", + "quote", + "syn 3.0.6", +] + +[[package]] +name = "toml" +version = "0.5.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234" +dependencies = [ + "serde", +] + +[[package]] +name = "unicode-ident" +version = "1.0.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d245f478577f809a851594d02313b640fb437e0bb33866753cff937863096954" + +[[package]] +name = "unicode-width" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4ac048d71ede7ee76d585517add45da530660ef4390e49b098733c6e897f254" + +[[package]] +name = "uniffi" +version = "0.29.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3291800a6b06569f7d3e15bdb6dc235e0f0c8bd3eb07177f430057feb076415f" +dependencies = [ + "anyhow", + "camino", + "cargo_metadata", + "clap", + "uniffi_bindgen", + "uniffi_build", + "uniffi_core", + "uniffi_macros", + "uniffi_pipeline", +] + +[[package]] +name = "uniffi_bindgen" +version = "0.29.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a04b99fa7796eaaa7b87976a0dbdd1178dc1ee702ea00aca2642003aef9b669e" +dependencies = [ + "anyhow", + "askama", + "camino", + "cargo_metadata", + "fs-err", + "glob", + "goblin", + "heck", + "indexmap", + "once_cell", + "serde", + "tempfile", + "textwrap", + "toml", + "uniffi_internal_macros", + "uniffi_meta", + "uniffi_pipeline", + "uniffi_udl", +] + +[[package]] +name = "uniffi_build" +version = "0.29.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "025a05cba02ee22b6624ac3d257e59c7395319ea8fe1aae33a7cdb4e2a3016cc" +dependencies = [ + "anyhow", + "camino", + "uniffi_bindgen", +] + +[[package]] +name = "uniffi_core" +version = "0.29.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f38a9a27529ccff732f8efddb831b65b1e07f7dea3fd4cacd4a35a8c4b253b98" +dependencies = [ + "anyhow", + "bytes", + "once_cell", + "static_assertions", +] + +[[package]] +name = "uniffi_internal_macros" +version = "0.29.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09acd2ce09c777dd65ee97c251d33c8a972afc04873f1e3b21eb3492ade16933" +dependencies = [ + "anyhow", + "indexmap", + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "uniffi_macros" +version = "0.29.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5596f178c4f7aafa1a501c4e0b96236a96bc2ef92bdb453d83e609dad0040152" +dependencies = [ + "camino", + "fs-err", + "once_cell", + "proc-macro2", + "quote", + "serde", + "syn 2.0.119", + "toml", + "uniffi_meta", +] + +[[package]] +name = "uniffi_meta" +version = "0.29.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "beadc1f460eb2e209263c49c4f5b19e9a02e00a3b2b393f78ad10d766346ecff" +dependencies = [ + "anyhow", + "siphasher", + "uniffi_internal_macros", + "uniffi_pipeline", +] + +[[package]] +name = "uniffi_pipeline" +version = "0.29.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd76b3ac8a2d964ca9fce7df21c755afb4c77b054a85ad7a029ad179cc5abb8a" +dependencies = [ + "anyhow", + "heck", + "indexmap", + "tempfile", + "uniffi_internal_macros", +] + +[[package]] +name = "uniffi_udl" +version = "0.29.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4319cf905911d70d5b97ce0f46f101619a22e9a189c8c46d797a9955e9233716" +dependencies = [ + "anyhow", + "textwrap", + "uniffi_meta", + "weedle2", +] + +[[package]] +name = "weedle2" +version = "5.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "998d2c24ec099a87daf9467808859f9d82b61f1d9c9701251aea037f514eae0e" +dependencies = [ + "nom", +] + +[[package]] +name = "windows-link" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" + +[[package]] +name = "windows-sys" +version = "0.61.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" +dependencies = [ + "windows-link", +] + +[[package]] +name = "winnow" +version = "0.7.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df79d97927682d2fd8adb29682d1140b343be4ac0f08fd68b7765d9c059d3945" +dependencies = [ + "memchr", +] + +[[package]] +name = "zmij" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29666d0abbfad1e3dc4dcf6144730dd3a3ab225bbbdac83319345b1b44ccfc1b" diff --git a/spec/bench/uniffi/Cargo.toml b/spec/bench/uniffi/Cargo.toml new file mode 100644 index 000000000..d21216ce9 --- /dev/null +++ b/spec/bench/uniffi/Cargo.toml @@ -0,0 +1,23 @@ +[package] +name = "brutils_uniffi" +version = "0.0.0" +edition = "2021" +publish = false + +[lib] +crate-type = ["cdylib", "lib"] +name = "brutils_uniffi" +path = "src/lib.rs" + +[dependencies] +uniffi = { version = "0.29", features = ["cli"] } + +[build-dependencies] +uniffi = { version = "0.29", features = ["build"] } + +[[bin]] +name = "uniffi-bindgen" +path = "src/bin.rs" + +[profile.release] +opt-level = 3 diff --git a/spec/bench/uniffi/src/bin.rs b/spec/bench/uniffi/src/bin.rs new file mode 100644 index 000000000..df364f1ef --- /dev/null +++ b/spec/bench/uniffi/src/bin.rs @@ -0,0 +1,5 @@ +//! The bindings generator entry point UniFFI expects. + +fn main() { + uniffi::uniffi_bindgen_main() +} diff --git a/spec/bench/uniffi/src/lib.rs b/spec/bench/uniffi/src/lib.rs new file mode 100644 index 000000000..da54db07d --- /dev/null +++ b/spec/bench/uniffi/src/lib.rs @@ -0,0 +1,111 @@ +//! The same validator, exposed through UniFFI instead of a hand written C ABI. +//! +//! This exists to measure what an off the shelf binding generator costs per call, against the +//! hand rolled ctypes binding in the same host language. + +uniffi::setup_scaffolding!(); + +/// Validates one CPF under the `masked-strict` profile. +#[uniffi::export] +pub fn cpf_is_valid(value: String) -> bool { + brutils_bench_core_logic::is_valid(&value) +} + +/// Validates a whole batch in one call. +#[uniffi::export] +pub fn cpf_is_valid_batch(values: Vec) -> Vec { + values + .iter() + .map(|value| brutils_bench_core_logic::is_valid(value)) + .collect() +} + +/// The validator itself, copied from the benchmark core so this crate does not need `no_std`. +mod brutils_bench_core_logic { + const fn is_js_whitespace(code: u32) -> bool { + matches!( + code, + 0x09 | 0x0a + | 0x0b + | 0x0c + | 0x0d + | 0x20 + | 0xa0 + | 0x1680 + | 0x2028 + | 0x2029 + | 0x202f + | 0x205f + | 0x3000 + | 0xfeff + ) || (code >= 0x2000 && code <= 0x200a) + } + + const fn is_mask_cpf(code: u32) -> bool { + code == 0x2e || code == 0x2d || code == 0x2f || is_js_whitespace(code) + } + + fn check_digit(base: &[u8]) -> u32 { + let mut sum: u32 = 0; + let mut weight = base.len() as u32 + 1; + + for byte in base { + sum += u32::from(*byte - b'0') * weight; + weight -= 1; + } + + let digit = 11 - (sum % 11); + + if digit >= 10 { + 0 + } else { + digit + } + } + + pub fn is_valid(value: &str) -> bool { + let trimmed = value.trim_matches(|char: char| is_js_whitespace(char as u32)); + let mut digits = [0u8; 11]; + let mut count = 0; + let groups = [3usize, 3, 3, 2]; + let mut iter = trimmed.chars().peekable(); + + for (position, size) in groups.iter().enumerate() { + if position > 0 { + while let Some(char) = iter.peek() { + if is_mask_cpf(*char as u32) { + iter.next(); + } else { + break; + } + } + } + + for _ in 0..*size { + match iter.next() { + Some(char) if char.is_ascii_digit() => { + digits[count] = char as u8; + count += 1; + } + _ => return false, + } + } + } + + if iter.next().is_some() { + return false; + } + + let first = digits[0]; + + if digits.iter().all(|digit| *digit == first) { + return false; + } + + if u32::from(digits[9] - b'0') != check_digit(&digits[..9]) { + return false; + } + + u32::from(digits[10] - b'0') == check_digit(&digits[..10]) + } +} diff --git a/spec/codegen/targets/python.ts b/spec/codegen/targets/python.ts index 83eab569c..b60ec5320 100644 --- a/spec/codegen/targets/python.ts +++ b/spec/codegen/targets/python.ts @@ -2,7 +2,7 @@ * Python emitter: produces modules shaped like `brutils/`, with the names and the * `None` returning formatter contract that package already exposes. */ -import { type Step, type UtilitySpec } from "../ir.ts"; +import { type Step, type UtilitySpec, resolveCharset } from "../ir.ts"; import { type Plan, type PlannedFunction, expandPipeline, naming } from "../plan.ts"; /** @@ -65,11 +65,17 @@ const prelude = (plan: Plan): string => { const { algorithm } = entry; const body = algorithm.weights.kind === "fixed" - ? ` weights = [${algorithm.weights.values.join(", ")}] - total = sum(int(base[index]) * weight for index, weight in enumerate(weights))` - : ` total = sum( - int(digit) * (len(base) + 1 - index) for index, digit in enumerate(base) - )`; + ? ` weights = (${algorithm.weights.values.join(", ")},) + total = 0 + + for index, weight in enumerate(weights): + total += (ord(base[index]) - 48) * weight` + : ` total = 0 + weight = len(base) + 1 + + for char in base: + total += (ord(char) - 48) * weight + weight -= 1`; return `def check_digit_${entry.symbol}(base: str) -> int: """${algorithm.description} @@ -87,7 +93,7 @@ def verify_${entry.symbol}(digits: str) -> bool: for position in (${algorithm.positions.join(", ")},): if len(digits) <= position: return False - if int(digits[position]) != check_digit_${entry.symbol}(digits[:position]): + if ord(digits[position]) - 48 != check_digit_${entry.symbol}(digits[:position]): return False return True`; @@ -183,6 +189,66 @@ const bailValue = (spec: UtilitySpec, planned: PlannedFunction): string => { return planned.nullable ? "None" : '""'; }; +/** + * Renders a charset as the body of a regex character class, every code point written as a + * `\uXXXX` escape so that no character can be read as a class metacharacter or a range. + * + * @param {string|string[]} names - The charset name, or the union of several. + * @returns {string} The class body, without the brackets. + */ +/** + * Renders one code point as a regex escape. + * + * @param {number} code - The code point. + * @returns {string} The escape sequence. + */ +const escapeCodePoint = (code: number): string => { + const hex = code.toString(16); + + return code > 0xff_ff ? `\\U${hex.padStart(8, "0")}` : `\\u${hex.padStart(4, "0")}`; +}; + +const regexClass = (names: string | string[]): string => { + const { single, ranges } = resolveCharset(names); + const points = single.map((code) => escapeCodePoint(code)); + const spans = ranges.map(([from, to]) => `${escapeCodePoint(from)}-${escapeCodePoint(to)}`); + + return [...points, ...spans].join(""); +}; + +/** + * The regex a `guard-shape` step becomes, with one capture group per digit run so that the + * digits come straight out of the match instead of being filtered out of the string again. + * + * @param {Step} step - The guard-shape step. + * @returns {string} The regex source. + */ +const shapeRegex = (step: Extract): string => { + const edge = step.trim === undefined ? "" : `[${regexClass(step.trim)}]*`; + const separator = step.separators === undefined ? "" : `[${regexClass(step.separators)}]*`; + const digits = `[${regexClass("ascii-digits")}]`; + const groups = step.groups.map((size) => `(${digits}{${size}})`).join(separator); + + // `\Z` rather than `$`: Python's `$` also matches before a trailing newline. + return `\\A${edge}${groups}${edge}\\Z`; +}; + +/** + * Whether the profile is the common "match a shape, then keep the digits" shape, which + * collapses into a single regex. + * + * @param {PlannedFunction} planned - The planned function. + * @returns {boolean} True when the fast path applies. + */ +const hasShapeFastPath = (planned: PlannedFunction): boolean => { + const steps = expandPipeline(planned.profile); + + return ( + steps.some((step) => step.op === "guard-shape") && + steps.some((step) => step.op === "sanitize" && step.keep === "ascii-digits") + ); +}; + /** * Renders one pipeline step as statements of the target language. * @@ -193,23 +259,26 @@ const bailValue = (spec: UtilitySpec, planned: PlannedFunction): string => { */ const renderStep = (step: Step, spec: UtilitySpec, planned: PlannedFunction): string => { const bail = bailValue(spec, planned); + const constant = `_${naming.snake(planned.spec.id).toUpperCase()}`; switch (step.op) { case "guard-shape": { - const value = step.trim === undefined ? "raw" : `trim_by(raw, is_${naming.snake(step.trim)})`; - const separators = - step.separators === undefined ? "" : `, is_${naming.snake(step.separators)}`; + return ` match = ${constant}_SHAPE.match(raw) - return ` if not match_shape(${value}, [${step.groups.join(", ")}]${separators}): - return ${bail}`; + if match is None: + return ${bail} + + digits = "".join(match.groups())`; } case "guard-charset": { - return ` for char in raw: - if not (${step.allow.map((name) => `is_${naming.snake(name)}(ord(char))`).join(" or ")}): - return ${bail}`; + return ` if ${constant}_ALLOWED.match(raw) is None: + return ${bail}`; } case "sanitize": { - return ` digits = keep_by(raw, is_${naming.snake(step.keep)})`; + // Already bound by the shape guard's capture groups. + if (hasShapeFastPath(planned)) return ""; + + return ` digits = _NON_DIGITS.sub("", raw)`; } case "guard-length": { return ` if len(digits) != ${step.equals}: @@ -298,10 +367,27 @@ const renderFunction = (planned: PlannedFunction): string => { const body = expandPipeline(planned.profile) .map((step) => renderStep(step, spec, planned)) + .filter((rendered) => rendered !== "") .join("\n"); const tail = tailOf(spec, planned); + const constant = `_${naming.snake(spec.id).toUpperCase()}`; + const constants = expandPipeline(planned.profile) + .map((step) => { + if (step.op === "guard-shape") + return `${constant}_SHAPE = re.compile(${escapeLiteral(shapeRegex(step))})\n`; + + if (step.op === "guard-charset") { + const allowed = escapeLiteral(`\\A[${regexClass(step.allow)}]*\\Z`); - return `def ${planned.name}(${parameters}) -> ${returnType}: + return `${constant}_ALLOWED = re.compile(${allowed})\n`; + } + + return ""; + }) + .join(""); + + return `${constants} +def ${planned.name}(${parameters}) -> ${returnType}: """${spec.summary} Profile: ${planned.profileName} — ${planned.profile.description} @@ -342,17 +428,22 @@ export const emit = (plan: Plan): Record => { ...plan.charsets.map((charset) => `is_${charset.symbol}`), ...plan.algorithms.map((entry) => `verify_${entry.symbol}`), ].filter((symbol) => new RegExp(`\\b${symbol}\\b`).test(source)); - const typing = source.includes("Optional[str]") ? "from typing import Optional\n\n" : ""; + const typing = source.includes("Optional[str]") ? "from typing import Optional\n" : ""; + const regexImport = source.includes("re.compile") ? "import re\n" : ""; + const nonDigitsPattern = escapeLiteral(`[^${regexClass("ascii-digits")}]`); + const nonDigits = source.includes("_NON_DIGITS") + ? `_NON_DIGITS = re.compile(${nonDigitsPattern})\n\n` + : ""; + const importedSymbols = symbols.map((symbol) => ` ${symbol},`).join("\n"); + const runtimeImport = + symbols.length === 0 ? "" : `from _spec_runtime import (\n${importedSymbols}\n)\n`; files[path] = `# Code generated from spec/utilities by spec/codegen. DO NOT EDIT. """${functions.map((planned) => planned.spec.summary).join(" ")}""" -${typing}from _spec_runtime import ( -${symbols.map((symbol) => ` ${symbol},`).join("\n")} -) - +${regexImport}${typing}${runtimeImport} -${source} +${nonDigits}${source} `; } diff --git a/spec/codegen/targets/ruby.ts b/spec/codegen/targets/ruby.ts index bdcf0ac79..c10eeaebb 100644 --- a/spec/codegen/targets/ruby.ts +++ b/spec/codegen/targets/ruby.ts @@ -2,9 +2,76 @@ * Ruby emitter: module functions under `BrazilianUtils::*Utils`, keeping the `valid?` * predicate name and the `nil` returning formatter the gem already exposes. */ -import { type Step, type UtilitySpec } from "../ir.ts"; +import { type Step, type UtilitySpec, resolveCharset } from "../ir.ts"; import { type Plan, type PlannedFunction, expandPipeline, naming } from "../plan.ts"; +/** + * Renders a charset as the body of a regex character class, every code point written as a + * `\uXXXX` escape so that no character can be read as a class metacharacter or a range. + * + * @param {string|string[]} names - The charset name, or the union of several. + * @returns {string} The class body, without the brackets. + */ +/** + * Renders one code point as a regex escape. + * + * @param {number} code - The code point. + * @returns {string} The escape sequence. + */ +const escapeCodePoint = (code: number): string => { + const hex = code.toString(16); + + return code > 0xff_ff ? `\\u{${hex}}` : `\\u${hex.padStart(4, "0")}`; +}; + +const regexClass = (names: string | string[]): string => { + const { single, ranges } = resolveCharset(names); + const points = single.map((code) => escapeCodePoint(code)); + const spans = ranges.map(([from, to]) => `${escapeCodePoint(from)}-${escapeCodePoint(to)}`); + + return [...points, ...spans].join(""); +}; + +/** + * The regex a `guard-shape` step becomes, with one capture group per digit run. + * + * @param {Step} step - The guard-shape step. + * @returns {string} The regex source. + */ +const shapeRegex = (step: Extract): string => { + const edge = step.trim === undefined ? "" : `[${regexClass(step.trim)}]*`; + const separator = step.separators === undefined ? "" : `[${regexClass(step.separators)}]*`; + const digits = `[${regexClass("ascii-digits")}]`; + const groups = step.groups.map((size) => `(${digits}{${size}})`).join(separator); + + // `\A`/`\z` rather than `^`/`$`: in Ruby those are line anchors. + return `\\A${edge}${groups}${edge}\\z`; +}; + +/** + * Whether the profile matches a shape and then keeps the digits, which collapses into one regex. + * + * @param {PlannedFunction} planned - The planned function. + * @returns {boolean} True when the fast path applies. + */ +const hasShapeFastPath = (planned: PlannedFunction): boolean => { + const steps = expandPipeline(planned.profile); + + return ( + steps.some((step) => step.op === "guard-shape") && + steps.some((step) => step.op === "sanitize" && step.keep === "ascii-digits") + ); +}; + +/** + * The prefix of the module level constants belonging to one function. + * + * @param {PlannedFunction} planned - The planned function. + * @returns {string} The constant prefix. + */ +const constantPrefix = (planned: PlannedFunction): string => + naming.snake(planned.spec.id).toUpperCase(); + /** * Renders a string as a Ruby double quoted literal, where `#` also has to be escaped because * `#{...}` would interpolate. @@ -69,8 +136,22 @@ const prelude = (plan: Plan): string => { const body = algorithm.weights.kind === "fixed" ? ` weights = [${algorithm.weights.values.join(", ")}] - total = weights.each_with_index.sum { |weight, index| base[index].to_i * weight }` - : ` total = base.chars.each_with_index.sum { |digit, index| digit.to_i * (base.length + 1 - index) }`; + total = 0 + index = 0 + + while index < weights.length + total += (base.getbyte(index) - 48) * weights[index] + index += 1 + end` + : ` total = 0 + index = 0 + weight = base.length + 1 + + while index < base.length + total += (base.getbyte(index) - 48) * weight + weight -= 1 + index += 1 + end`; return ` # ${algorithm.description} # @@ -84,10 +165,14 @@ ${body} # Whether every check digit of the value matches its base. def self.verify_${entry.symbol}(digits) - [${algorithm.positions.join(", ")}].all? do |position| - digits.length > position && - digits[position].to_i == check_digit_${entry.symbol}(digits[0...position]) - end +${algorithm.positions + .map( + (position) => ` return false if digits.length <= ${position} + return false unless (digits.getbyte(${position}) - 48) == check_digit_${entry.symbol}(digits[0...${position}])`, + ) + .join("\n\n")} + + true end`; }) .join("\n\n"); @@ -200,28 +285,23 @@ const renderStep = (step: Step, spec: UtilitySpec, planned: PlannedFunction): st const bail = bailValue(spec, planned); const runtime = "BrazilianUtils::SpecRuntime"; + const constant = constantPrefix(planned); + switch (step.op) { case "guard-shape": { - const value = - step.trim === undefined - ? "raw" - : `${runtime}.trim_by(raw, ${runtime}.method(:${naming.snake(step.trim)}?))`; - const separators = - step.separators === undefined - ? "" - : `, ${runtime}.method(:${naming.snake(step.separators)}?)`; - - return ` return ${bail} unless ${runtime}.match_shape(${value}, [${step.groups.join(", ")}]${separators})`; + return ` match = ${constant}_SHAPE.match(raw) + return ${bail} if match.nil? + + digits = match.captures.join`; } case "guard-charset": { - return ` raw.each_char do |char| - code = char.ord - - return ${bail} unless ${step.allow.map((name) => `${runtime}.${naming.snake(name)}?(code)`).join(" || ")} - end`; + return ` return ${bail} if ${constant}_ALLOWED.match(raw).nil?`; } case "sanitize": { - return ` digits = ${runtime}.keep_by(raw, ${runtime}.method(:${naming.snake(step.keep)}?))`; + // Already bound by the shape guard's capture groups. + if (hasShapeFastPath(planned)) return ""; + + return ` digits = raw.gsub(NON_DIGITS, '')`; } case "guard-length": { return ` return ${bail} unless digits.length == ${step.equals}`; @@ -291,10 +371,27 @@ const renderFunction = (planned: PlannedFunction): string => { const body = expandPipeline(planned.profile) .map((step) => renderStep(step, spec, planned)) + .filter((rendered) => rendered !== "") .join("\n"); const tail = tailOf(spec, planned); + const constant = constantPrefix(planned); + const constants = expandPipeline(planned.profile) + .map((step) => { + if (step.op === "guard-shape") + return ` ${constant}_SHAPE = Regexp.new(${escapeLiteral(shapeRegex(step))}).freeze\n`; + + if (step.op === "guard-charset") { + const allowed = escapeLiteral(`\\A[${regexClass(step.allow)}]*\\z`); + + return ` ${constant}_ALLOWED = Regexp.new(${allowed}).freeze\n`; + } - return ` # ${spec.summary} + return ""; + }) + .join(""); + + return `${constants} + # ${spec.summary} # # Profile: ${planned.profileName} — ${planned.profile.description} # @@ -320,6 +417,8 @@ export const emit = (plan: Plan): Record => { modules.set(planned.module, [...(modules.get(planned.module) ?? []), planned]); } + const nonDigitsPattern = escapeLiteral(`[^${regexClass("ascii-digits")}]`); + for (const [module, functions] of modules) { const shortName = module.split("::").at(-1) ?? module; const fileName = shortName @@ -335,7 +434,15 @@ require_relative 'spec_runtime' module BrazilianUtils # ${functions.map((planned) => planned.spec.summary).join(" ")} - module ${shortName} + module ${shortName}${ + functions.some( + (planned) => + !hasShapeFastPath(planned) && + expandPipeline(planned.profile).some((step) => step.op === "sanitize"), + ) + ? `\n NON_DIGITS = Regexp.new(${nonDigitsPattern}).freeze\n` + : "" + } ${functions.map((planned) => renderFunction(planned)).join("\n\n")} end end diff --git a/vite.config.ts b/vite.config.ts index 465c5737d..29f30671a 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -160,6 +160,7 @@ export default defineConfig({ ".claude", "CHANGELOG.md", "spec/vectors", + "spec/bench/corpus.json", ], singleQuote: false, sortImports: true, From 956c3b10fda155e52170ddac04abb2ae3ff15944 Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 21 Sep 2026 01:36:07 +0000 Subject: [PATCH 03/13] feat(spec): compile one TypeScript source into seven native targets Adds `spec/bridge`, a compiler that takes a utility written once in a portable subset of TypeScript and emits idiomatic native code for TypeScript, Python, Go, Rust, Ruby, Java and C#. Nothing per language is written by hand: each target is an emitter plus a small runtime, both of which are utility agnostic. Covered so far: `isValidCnpj`, `formatCnpj` and `getMunicipalities`. How the hard parts are pinned: - Regular expressions are compiled at build time into explicit code point classes and a backtrack free matcher, so `\s` means the same 25 code points everywhere instead of 6 in Go and a Unicode property in Python. - Locale collation is resolved at build time too: `data/build.ts` bakes the pt-BR order the JavaScript package returns into the dataset, because no two of the seven targets ship the same collator and four ship none at all. - The boundary quirks the JavaScript package has (`String(value)` on a number, a truthy non boolean option) are a small portable std every target implements. Parity is measured, not asserted: - `conformance/verify-typescript.sh` drops the generated TypeScript into `src/` and runs the package's own vitest suites against it: 4 files, 157 tests pass, the `getMunicipalities` type level tests included. - `conformance/run-all.sh` replays 5,730 CNPJ expectations and an 11,176 line municipality dump, both recorded from the shipped package, through all seven targets. All seven match; Go, Rust, Java and C# skip the 18 cases where a `string | number` union has no static form. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01UX1gTGeMTyoXQyr1qUoQKd --- spec/bridge/.gitignore | 12 + spec/bridge/compiler/cli.ts | 61 + spec/bridge/compiler/frontend.ts | 1038 ++++++++++++++++++ spec/bridge/compiler/ir.ts | 178 +++ spec/bridge/compiler/kit.ts | 235 ++++ spec/bridge/compiler/regex.ts | 344 ++++++ spec/bridge/compiler/runtime/csharp.cs | 240 ++++ spec/bridge/compiler/runtime/go.go | 200 ++++ spec/bridge/compiler/runtime/java.java | 193 ++++ spec/bridge/compiler/runtime/python.py | 157 +++ spec/bridge/compiler/runtime/ruby.rb | 131 +++ spec/bridge/compiler/runtime/rust.rs | 172 +++ spec/bridge/compiler/runtime/typescript.ts | 183 +++ spec/bridge/compiler/targets/csharp.ts | 469 ++++++++ spec/bridge/compiler/targets/go.ts | 334 ++++++ spec/bridge/compiler/targets/java.ts | 450 ++++++++ spec/bridge/compiler/targets/python.ts | 362 ++++++ spec/bridge/compiler/targets/ruby.ts | 302 +++++ spec/bridge/compiler/targets/rust.ts | 475 ++++++++ spec/bridge/compiler/targets/typescript.ts | 387 +++++++ spec/bridge/conformance/drivers.ts | 818 ++++++++++++++ spec/bridge/conformance/municipalities.ts | 92 ++ spec/bridge/conformance/run-all.sh | 66 ++ spec/bridge/conformance/vectors.ts | 148 +++ spec/bridge/conformance/verify-typescript.sh | 48 + spec/bridge/data/build.ts | 88 ++ spec/bridge/package-lock.json | 391 +++++++ spec/bridge/package.json | 14 + spec/bridge/source/_std.ts | 80 ++ spec/bridge/source/cnpj.ts | 211 ++++ spec/bridge/source/municipalities.data.json | 1 + spec/bridge/source/municipalities.ts | 109 ++ 32 files changed, 7989 insertions(+) create mode 100644 spec/bridge/.gitignore create mode 100644 spec/bridge/compiler/cli.ts create mode 100644 spec/bridge/compiler/frontend.ts create mode 100644 spec/bridge/compiler/ir.ts create mode 100644 spec/bridge/compiler/kit.ts create mode 100644 spec/bridge/compiler/regex.ts create mode 100644 spec/bridge/compiler/runtime/csharp.cs create mode 100644 spec/bridge/compiler/runtime/go.go create mode 100644 spec/bridge/compiler/runtime/java.java create mode 100644 spec/bridge/compiler/runtime/python.py create mode 100644 spec/bridge/compiler/runtime/ruby.rb create mode 100644 spec/bridge/compiler/runtime/rust.rs create mode 100644 spec/bridge/compiler/runtime/typescript.ts create mode 100644 spec/bridge/compiler/targets/csharp.ts create mode 100644 spec/bridge/compiler/targets/go.ts create mode 100644 spec/bridge/compiler/targets/java.ts create mode 100644 spec/bridge/compiler/targets/python.ts create mode 100644 spec/bridge/compiler/targets/ruby.ts create mode 100644 spec/bridge/compiler/targets/rust.ts create mode 100644 spec/bridge/compiler/targets/typescript.ts create mode 100644 spec/bridge/conformance/drivers.ts create mode 100644 spec/bridge/conformance/municipalities.ts create mode 100644 spec/bridge/conformance/run-all.sh create mode 100644 spec/bridge/conformance/vectors.ts create mode 100644 spec/bridge/conformance/verify-typescript.sh create mode 100644 spec/bridge/data/build.ts create mode 100644 spec/bridge/package-lock.json create mode 100644 spec/bridge/package.json create mode 100644 spec/bridge/source/_std.ts create mode 100644 spec/bridge/source/cnpj.ts create mode 100644 spec/bridge/source/municipalities.data.json create mode 100644 spec/bridge/source/municipalities.ts diff --git a/spec/bridge/.gitignore b/spec/bridge/.gitignore new file mode 100644 index 000000000..322f30470 --- /dev/null +++ b/spec/bridge/.gitignore @@ -0,0 +1,12 @@ +# Everything under `out/` is generated by `compiler/cli.ts`, and every build tree the targets +# leave behind is generated by their own toolchains. +out/ +node_modules/ + +# The conformance recordings are taken from the package this repository ships, by +# `conformance/vectors.ts` and `conformance/municipalities.ts`, which `run-all.sh` runs first. +# `source/*.data.json` is committed: it is an input to the compiler, not a recording. +conformance/vectors.json +conformance/vectors.tsv +conformance/municipalities.expected.txt +conformance/municipalities.keys.txt diff --git a/spec/bridge/compiler/cli.ts b/spec/bridge/compiler/cli.ts new file mode 100644 index 000000000..f6634c263 --- /dev/null +++ b/spec/bridge/compiler/cli.ts @@ -0,0 +1,61 @@ +/** + * Compiles every module under `source/` into every target under `compiler/targets/`. + * + * Usage: `node compiler/cli.ts [target...]` + */ +import { mkdirSync, readdirSync, rmSync, writeFileSync } from "node:fs"; +import { dirname, resolve } from "node:path"; +import { compileModule } from "./frontend.ts"; +import type { Module } from "./ir.ts"; +import { emit as emitCsharp } from "./targets/csharp.ts"; +import { emit as emitGo } from "./targets/go.ts"; +import { emit as emitJava } from "./targets/java.ts"; +import { emit as emitPython } from "./targets/python.ts"; +import { emit as emitRuby } from "./targets/ruby.ts"; +import { emit as emitRust } from "./targets/rust.ts"; +import { emit as emitTypeScript } from "./targets/typescript.ts"; + +const root = resolve(import.meta.dirname, ".."); + +const targets: Record Record> = { + typescript: emitTypeScript, + python: emitPython, + go: emitGo, + rust: emitRust, + ruby: emitRuby, + java: emitJava, + csharp: emitCsharp, +}; + +const requested = process.argv.slice(2); +const selected = requested.length > 0 ? requested : Object.keys(targets); +// `_std.ts` is the portable standard library: every target implements it natively, so it is +// documentation and a reference implementation rather than a module to compile. +const sources = readdirSync(resolve(root, "source")).filter( + (name) => name.endsWith(".ts") && !name.startsWith("_"), +); +const modules = sources.map((name) => compileModule(resolve(root, "source", name))); + +for (const target of selected) { + const emit = targets[target]; + + if (emit === undefined) throw new Error(`unknown target: ${target}`); + + const outDir = resolve(root, "out", target); + + rmSync(outDir, { recursive: true, force: true }); + + let count = 0; + + for (const module of modules) { + for (const [path, contents] of Object.entries(emit(module, modules))) { + const full = resolve(outDir, path); + + mkdirSync(dirname(full), { recursive: true }); + writeFileSync(full, contents); + count++; + } + } + + console.log(`${target.padEnd(11)} ${count} files from ${modules.length} module(s)`); +} diff --git a/spec/bridge/compiler/frontend.ts b/spec/bridge/compiler/frontend.ts new file mode 100644 index 000000000..4d9a8934f --- /dev/null +++ b/spec/bridge/compiler/frontend.ts @@ -0,0 +1,1038 @@ +/** + * The frontend: ordinary TypeScript in, IR out. + * + * It accepts a subset and refuses everything else with a pointed error rather than emitting + * something that would mean a different thing in Go than it does in Ruby. The subset is + * documented in `spec/bridge/README.md` and is what the four utilities under `source/` use. + */ +import { readFileSync } from "node:fs"; +import { basename, dirname, resolve } from "node:path"; +import { parseSync } from "oxc-parser"; +import type { + BinaryOp, + CharClass, + DataDecl, + EnumDecl, + ErrorDecl, + Expr, + FuncDecl, + Module, + Param, + PatternDecl, + Stmt, + StructDecl, + Ty, +} from "./ir.ts"; +import { ClassTable, complement, parsePattern, toSteps } from "./regex.ts"; + +/* eslint-disable */ +type Node = Record; + +const fail = (node: Node, message: string): never => { + throw new Error(`${message} (at ${String(node["type"])}, offset ${String(node["start"])})`); +}; + +const STRING_METHODS: Record = { + charCodeAt: { std: "codeAt", args: 1 }, + slice: { std: "slice", args: 2 }, + toUpperCase: { std: "upper", args: 0 }, + trim: { std: "trim", args: 0 }, + padStart: { std: "padStart", args: 2 }, + repeat: { std: "repeat", args: 1 }, +}; + +/** Everything the frontend knows while walking one module. */ +type Scope = { + types: Map; + functions: Map; + structs: Map; + enums: Map; + errors: Map; + /** Module level `const` lists and strings, by name. */ + constants: Map; + /** Regex literals, by the name they were bound to. */ + regexes: Map; + classes: ClassTable; + patterns: PatternDecl[]; + /** Portable standard library members the module imported. */ + stdImports: Set; + data: Map; +}; + +/** The portable standard library, by name and return type. */ +const STD_FUNCTIONS = new Map([ + ["asString", { k: "string" }], + ["isTruthy", { k: "bool" }], + ["dataAll", { k: "list", of: { k: "list", of: { k: "string" } } }], + ["dataRows", { k: "list", of: { k: "list", of: { k: "string" } } }], +]); + +/** Members of the portable std that are types or build time only, so never lowered as calls. */ +const STD_NON_CALLS = new Set(["Dataset", "dataset"]); + +const int: Ty = { k: "int" }; +const str: Ty = { k: "string" }; +const bool: Ty = { k: "bool" }; + +/** + * Reads a TypeScript type annotation into an IR type. + * + * @param {Node} node - The annotation node. + * @param {Scope} scope - The module scope. + * @returns {Ty} The IR type. + */ +const readType = (node: Node, scope: Scope): Ty => { + switch (node["type"]) { + case "TSStringKeyword": + return str; + case "TSNumberKeyword": + return int; + case "TSBooleanKeyword": + return bool; + case "TSVoidKeyword": + return { k: "void" }; + case "TSArrayType": + return { k: "list", of: readType(node["elementType"] as Node, scope) }; + case "TSUnionType": { + const members = node["types"] as Node[]; + const kinds = new Set(members.map((member) => String(member["type"]))); + + if (kinds.has("TSStringKeyword") && kinds.has("TSNumberKeyword") && kinds.size === 2) + return { k: "scalar" }; + + const literals = members.filter((member) => member["type"] === "TSLiteralType"); + + if (literals.length === members.length) { + // A union of string literals is a closed set of strings; `1 | 2` and friends are + // integers with a documented domain. + const strings = literals.filter( + (member) => typeof (member["literal"] as Node)["value"] === "string", + ); + + if (strings.length === literals.length) return str; + + return int; + } + + return fail(node, "only unions of literal numbers or literal strings are in the subset"); + } + case "TSTypeReference": { + const name = String((node["typeName"] as Node)["name"]); + + if (name === "Promise") { + const args = node["typeArguments"] as Node | null; + + return readType(((args?.["params"] as Node[]) ?? [])[0], scope); + } + + if (scope.enums.has(name)) return { k: "enum", name }; + if (scope.structs.has(name) || scope.errors.has(name)) return { k: "named", name }; + + return fail(node, `unknown type \`${name}\``); + } + default: + return fail(node, `type ${String(node["type"])} is outside the subset`); + } +}; + +/** Reads the `@see` lines of a leading doc comment. */ +const readSources = (doc: string): { role: string; url: string }[] => + [...doc.matchAll(/@see (Official|Based on): (\S+)/g)].map((match) => ({ + role: match[1] === "Official" ? "official" : "based-on", + url: match[2], + })); + +/** Pulls the block comment that ends right before `start`, if any. */ +const docBefore = (source: string, start: number): string => { + const before = source.slice(0, start); + const open = before.lastIndexOf("/**"); + const close = before.lastIndexOf("*/"); + + if (open === -1 || close < open) return ""; + if (before.slice(close + 2).trim() !== "" && !before.slice(close + 2).trim().startsWith("export")) + return ""; + + return before + .slice(open + 3, close) + .split("\n") + .map((line) => line.replace(/^\s*\*ance?\s?/, "").replace(/^\s*\*\s?/, "")) + .join("\n") + .trim(); +}; + +/** + * Infers the IR type of an expression. + * + * @param {Expr} expr - The expression. + * @param {Map} locals - The types in scope. + * @param {Scope} scope - The module scope. + * @returns {Ty} The inferred type. + */ +const inferType = (expr: Expr, locals: Map, scope: Scope): Ty => { + switch (expr.k) { + case "str": + return str; + case "int": + return int; + case "bool": + case "not": + return bool; + case "ref": + return locals.get(expr.name) ?? scope.constants.get(expr.name)?.ty ?? str; + case "field": + case "call": + return expr.ty; + case "index": { + const target = inferType(expr.target, locals, scope); + + return target.k === "list" ? target.of : int; + } + case "bin": + if (["==", "!=", "<", "<=", ">", ">=", "&&", "||"].includes(expr.op)) return bool; + + return inferType(expr.left, locals, scope); + case "cond": + return inferType(expr.whenTrue, locals, scope); + case "listOf": + return { k: "list", of: expr.of }; + case "struct": + return { k: "named", name: expr.name }; + case "await": + return inferType(expr.value, locals, scope); + case "optionField": + return expr.ty; + default: + return str; + } +}; + +const BINARY_OPS: Record = { + "+": "+", + "-": "-", + "*": "*", + "%": "%", + "===": "==", + "!==": "!=", + "==": "==", + "!=": "!=", + "<": "<", + "<=": "<=", + ">": ">", + ">=": ">=", + "&&": "&&", + "||": "||", +}; + +/** Unwraps `a?.b` written as a ChainExpression. */ +const unchain = (node: Node): Node => { + if (node["type"] === "ChainExpression") return unchain(node["expression"] as Node); + if (node["type"] === "ParenthesizedExpression") return unchain(node["expression"] as Node); + if (node["type"] === "TSAsExpression") return unchain(node["expression"] as Node); + + return node; +}; + +type Ctx = { + locals: Map; + scope: Scope; + source: string; + /** Optionals a surrounding `if` has proved present, so a read of them unwraps. */ + narrowed: Set; +}; + +/** + * Lowers one expression. + * + * @param {Node} node - The AST node. + * @param {Ctx} ctx - The walking context. + * @returns {Expr} The IR expression. + */ +const lowerExpr = (node: Node, ctx: Ctx): Expr => { + const current = unchain(node); + + switch (current["type"]) { + case "Literal": { + const value = current["value"]; + + if (current["regex"] !== undefined && current["regex"] !== null) + return fail(current, "a regex literal has to be bound to a module level const"); + if (value === null) return { k: "none" }; + if (typeof value === "string") return { k: "str", value }; + if (typeof value === "boolean") return { k: "bool", value }; + if (typeof value === "number") { + if (!Number.isInteger(value)) return fail(current, "only integer literals are in the subset"); + + return { k: "int", value }; + } + + return fail(current, "unsupported literal"); + } + case "Identifier": { + const name = String(current["name"]); + + if (name === "undefined") return { k: "none" }; + + const local = ctx.locals.get(name); + + // Inside a branch that proved the optional present, the read is the value, not the + // optional: the targets that distinguish the two need the unwrap spelled out. + if (ctx.narrowed.has(name) && local !== undefined && local.k === "opt") + return { + k: "call", + callee: { k: "std", name: "unwrap" }, + args: [{ k: "ref", name }], + ty: local.of, + }; + + return { k: "ref", name }; + } + case "UnaryExpression": { + if (current["operator"] === "!") return { k: "not", operand: lowerExpr(current["argument"] as Node, ctx) }; + if (current["operator"] === "-") { + const inner = lowerExpr(current["argument"] as Node, ctx); + + if (inner.k === "int") return { k: "int", value: -inner.value }; + } + + return fail(current, `unary \`${String(current["operator"])}\` is outside the subset`); + } + case "BinaryExpression": + case "LogicalExpression": { + const op = BINARY_OPS[String(current["operator"])]; + + if (op === undefined) return fail(current, `operator \`${String(current["operator"])}\` is outside the subset`); + + const left = lowerExpr(current["left"] as Node, ctx); + const right = lowerExpr(current["right"] as Node, ctx); + + // The operand type travels with the node: `+` is concatenation in one target and + // addition in another, and only the frontend knows which one this is. + return { k: "bin", op, left, right, ty: inferType(left, ctx.locals, ctx.scope) }; + } + case "ConditionalExpression": + return { + k: "cond", + test: lowerExpr(current["test"] as Node, ctx), + whenTrue: lowerExpr(current["consequent"] as Node, ctx), + whenFalse: lowerExpr(current["alternate"] as Node, ctx), + }; + case "TemplateLiteral": { + const quasis = current["quasis"] as Node[]; + const expressions = current["expressions"] as Node[]; + let built: Expr = { k: "str", value: String((quasis[0]["value"] as Node)["cooked"]) }; + + for (const [index, expression] of expressions.entries()) { + built = { k: "bin", op: "+", left: built, right: lowerExpr(expression, ctx) }; + built = { + k: "bin", + op: "+", + left: built, + right: { k: "str", value: String((quasis[index + 1]["value"] as Node)["cooked"]) }, + }; + } + + return built; + } + case "ArrayExpression": { + const items = (current["elements"] as Node[]).map((element) => lowerExpr(element, ctx)); + + return { k: "listOf", items, of: items.length > 0 ? inferType(items[0], ctx.locals, ctx.scope) : str }; + } + case "AwaitExpression": + return { k: "await", value: lowerExpr(current["argument"] as Node, ctx) }; + case "MemberExpression": + return lowerMember(current, ctx); + case "CallExpression": + return lowerCall(current, ctx); + case "ObjectExpression": + return lowerObject(current, ctx); + case "ArrowFunctionExpression": + return fail(current, "inline functions are only allowed at module level in this version"); + default: + return fail(current, `expression ${String(current["type"])} is outside the subset`); + } +}; + +/** + * Lowers an object literal into a struct value. + * + * The struct is the declared record type whose field names are exactly the literal's, which is + * unambiguous for every record in the subset and keeps the source free of type assertions. + * + * @param {Node} node - The ObjectExpression. + * @param {Ctx} ctx - The walking context. + * @returns {Expr} The struct expression. + */ +const lowerObject = (node: Node, ctx: Ctx): Expr => { + const properties = (node["properties"] as Node[]).map((property) => { + if (property["type"] !== "Property" || property["computed"] === true) + return fail(property, "only plain `key: value` properties are in the subset"); + + return { name: String((property["key"] as Node)["name"]), value: property["value"] as Node }; + }); + const keys = [...properties.map((property) => property.name)].sort().join(","); + const match = [...ctx.scope.structs.values()].find( + (candidate) => + [...candidate.fields.map((field) => field.name)].sort().join(",") === keys, + ); + + if (match === undefined) return fail(node, `no declared record type has the fields \`${keys}\``); + + return { + k: "struct", + name: match.name, + fields: properties.map((property) => ({ + name: property.name, + value: lowerExpr(property.value, ctx), + })), + }; +}; + +/** Lowers `a.b`, `a[i]`, `a.length` and `options?.field`. */ +const lowerMember = (node: Node, ctx: Ctx): Expr => { + const object = node["object"] as Node; + const property = node["property"] as Node; + const computed = node["computed"] === true; + + if (computed) { + const target = lowerExpr(object, ctx); + const targetType = inferType(target, ctx.locals, ctx.scope); + + return { + k: "index", + target, + index: lowerExpr(property, ctx), + ty: targetType.k === "list" ? targetType.of : undefined, + }; + } + + const name = String(property["name"]); + const optional = node["optional"] === true; + + if (optional) { + const targetName = String(object["name"]); + const struct = ctx.scope.structs.get(nameOfOptionsParam(targetName, ctx)); + + if (struct === undefined) return fail(node, `\`${targetName}\` is not an options parameter`); + + const field = struct.fields.find((candidate) => candidate.name === name); + + if (field === undefined) return fail(node, `\`${struct.name}\` has no field \`${name}\``); + + return { + k: "optionField", + target: targetName, + field: name, + ty: field.ty, + fallback: field.ty.k === "bool" ? { k: "bool", value: false } : { k: "int", value: -1 }, + }; + } + + const target = lowerExpr(object, ctx); + const targetType = inferType(target, ctx.locals, ctx.scope); + + if (name === "length") { + if (targetType.k === "list") + return { k: "call", callee: { k: "std", name: "listLen" }, args: [target], ty: int }; + + return { k: "call", callee: { k: "std", name: "len" }, args: [target], ty: int }; + } + + if (targetType.k === "named") { + const struct = ctx.scope.structs.get(targetType.name); + const field = struct?.fields.find((candidate) => candidate.name === name); + + if (field !== undefined) return { k: "field", target, name, ty: field.ty }; + } + + return fail(node, `\`.${name}\` is outside the subset`); +}; + +/** The declared type name of an options parameter. */ +const nameOfOptionsParam = (name: string, ctx: Ctx): string => { + const ty = ctx.locals.get(name); + + return ty !== undefined && ty.k === "named" ? ty.name : name; +}; + +/** Lowers a call: a user function, a mapped string method, or a compiled pattern operation. */ +const lowerCall = (node: Node, ctx: Ctx): Expr => { + const callee = unchain(node["callee"] as Node); + const args = (node["arguments"] as Node[]) ?? []; + + if (callee["type"] === "Identifier") { + const name = String(callee["name"]); + const std = ctx.scope.stdImports.has(name) ? STD_FUNCTIONS.get(name) : undefined; + + if (std !== undefined) { + return { + k: "call", + callee: { k: "std", name }, + args: args.map((argument) => lowerExpr(argument, ctx)), + ty: std, + }; + } + + const signature = ctx.scope.functions.get(name); + + if (signature === undefined) return fail(node, `unknown function \`${name}\``); + + return { + k: "call", + callee: { k: "user", name }, + args: args.map((argument) => lowerExpr(argument, ctx)), + ty: signature.ret, + }; + } + + if (callee["type"] !== "MemberExpression") return fail(node, "unsupported call target"); + + const object = callee["object"] as Node; + const method = String((callee["property"] as Node)["name"]); + const regexName = object["type"] === "Identifier" ? String(object["name"]) : ""; + const regex = ctx.scope.regexes.get(regexName); + + if (regex !== undefined) { + if (method !== "test") return fail(node, `\`${regexName}.${method}\` is outside the subset`); + + const subject = lowerExpr(args[0], ctx); + + if (regex.anchored === true && regex.pattern !== undefined) { + return { + k: "call", + callee: { k: "std", name: "patternTest" }, + args: [{ k: "ref", name: regex.pattern }, subject], + ty: bool, + }; + } + + if (regex.charClass === undefined) return fail(node, `\`${regexName}\` needs anchors to be used with .test()`); + + return { + k: "call", + callee: { k: "std", name: "classHas" }, + args: [{ k: "ref", name: regex.charClass }, subject], + ty: bool, + }; + } + + const target = lowerExpr(object, ctx); + + if (method === "replaceAll") { + const patternName = String((args[0] as Node)["name"]); + const replacement = args[1] as Node; + + if (replacement["value"] !== "") + return fail(node, "only `replaceAll(pattern, \"\")` is in the subset"); + + const removed = ctx.scope.regexes.get(patternName); + + if (removed?.keepClass === undefined) + return fail(node, `\`${patternName}\` is not a single character class`); + + return { + k: "call", + callee: { k: "std", name: "keepClass" }, + args: [{ k: "ref", name: removed.keepClass }, target], + ty: str, + }; + } + + if (method === "push") { + const targetType = inferType(target, ctx.locals, ctx.scope); + + if (targetType.k !== "list") return fail(node, "`.push()` is only in the subset for lists"); + + return { + k: "call", + callee: { k: "std", name: "listPush" }, + args: [target, lowerExpr(args[0], ctx)], + ty: { k: "void" }, + }; + } + + const mapped = STRING_METHODS[method]; + + if (mapped === undefined) return fail(node, `\`.${method}()\` is outside the subset`); + if (args.length !== mapped.args) return fail(node, `\`.${method}()\` takes ${mapped.args} argument(s)`); + + return { + k: "call", + callee: { k: "std", name: mapped.std }, + args: [target, ...args.map((argument) => lowerExpr(argument, ctx))], + ty: mapped.std === "codeAt" ? int : str, + }; +}; + +/** + * The optionals an `if` test proves present for its `then` branch. + * + * Only `x !== undefined` and `x !== null`, alone or joined by `&&`, count: anything subtler + * would need real flow analysis, and nothing in the subset needs it. + * + * @param {Expr} test - The lowered test. + * @param {Ctx} ctx - The walking context. + * @returns {string[]} The names proved present. + */ +const provenPresent = (test: Expr, ctx: Ctx): string[] => { + if (test.k !== "bin") return []; + if (test.op === "&&") return [...provenPresent(test.left, ctx), ...provenPresent(test.right, ctx)]; + if (test.op !== "!=") return []; + + const [subject, other] = test.left.k === "none" ? [test.right, test.left] : [test.left, test.right]; + + if (other.k !== "none" || subject.k !== "ref") return []; + + return ctx.locals.get(subject.name)?.k === "opt" ? [subject.name] : []; +}; + +/** + * Lowers a statement list. + * + * @param {Node[]} nodes - The statements. + * @param {Ctx} ctx - The walking context. + * @returns {Stmt[]} The IR statements. + */ +const lowerBlock = (nodes: Node[], ctx: Ctx): Stmt[] => nodes.flatMap((node) => lowerStmt(node, ctx)); + +/** Recognises the boundary guards the handwritten package has, which only dynamic targets need. */ +const asGuard = (node: Node, ctx: Ctx): Stmt[] | undefined => { + const test = node["test"] as Node; + const consequent = node["consequent"] as Node; + const body = consequent["type"] === "BlockStatement" ? (consequent["body"] as Node[]) : [consequent]; + + if (body.length !== 1 || body[0]["type"] !== "ReturnStatement") return undefined; + + const isTypeofGuard = + test["type"] === "BinaryExpression" && + test["operator"] === "!==" && + (test["left"] as Node)["type"] === "UnaryExpression" && + ((test["left"] as Node)["operator"] as string) === "typeof"; + + const isNullishGuard = + test["type"] === "LogicalExpression" && + test["operator"] === "||" && + String(((test["left"] as Node)["right"] as Node)["raw"] ?? "") === "null"; + + if (!isTypeofGuard && !isNullishGuard) return undefined; + + const argument = (body[0]["argument"] as Node | null) ?? undefined; + const value = argument === undefined ? undefined : lowerExpr(argument, ctx); + const subject = isTypeofGuard + ? String(((test["left"] as Node)["argument"] as Node)["name"]) + : String(((test["left"] as Node)["left"] as Node)["name"]); + + return [ + { + k: "expr", + value: { + k: "call", + callee: { k: "std", name: "boundaryGuard" }, + args: [ + { k: "ref", name: subject }, + { k: "str", value: isTypeofGuard ? "string" : "nullish" }, + value ?? { k: "none" }, + ], + ty: { k: "void" }, + }, + }, + ]; +}; + +/** + * Lowers one statement. + * + * @param {Node} node - The AST node. + * @param {Ctx} ctx - The walking context. + * @returns {Stmt[]} The IR statements, usually one. + */ +const lowerStmt = (node: Node, ctx: Ctx): Stmt[] => { + switch (node["type"]) { + case "VariableDeclaration": { + const declarations = node["declarations"] as Node[]; + + return declarations.map((declaration) => { + const name = String((declaration["id"] as Node)["name"]); + const value = lowerExpr(declaration["init"] as Node, ctx); + const annotation = (declaration["id"] as Node)["typeAnnotation"] as Node | null; + const ty = + annotation === null + ? inferType(value, ctx.locals, ctx.scope) + : readType(annotation["typeAnnotation"] as Node, ctx.scope); + + ctx.locals.set(name, ty); + + // `const rows: Municipality[] = []` says what the empty literal holds; nothing else does. + if (value.k === "listOf" && value.items.length === 0 && ty.k === "list") value.of = ty.of; + + return { k: "let", name, ty, value, mutable: node["kind"] !== "const" } as Stmt; + }); + } + case "ExpressionStatement": { + const expression = node["expression"] as Node; + + if (expression["type"] === "AssignmentExpression") { + if (expression["operator"] !== "=") return fail(expression, "only `=` assignment is in the subset"); + + return [ + { + k: "assign", + name: String((expression["left"] as Node)["name"]), + value: lowerExpr(expression["right"] as Node, ctx), + }, + ]; + } + + return [{ k: "expr", value: lowerExpr(expression, ctx) }]; + } + case "IfStatement": { + const guard = asGuard(node, ctx); + + if (guard !== undefined) return guard; + + const consequent = node["consequent"] as Node; + const alternate = (node["alternate"] as Node | null) ?? undefined; + const test = lowerExpr(node["test"] as Node, ctx); + const proved = provenPresent(test, ctx); + + for (const name of proved) ctx.narrowed.add(name); + + const then = lowerBlock( + consequent["type"] === "BlockStatement" ? (consequent["body"] as Node[]) : [consequent], + ctx, + ); + + for (const name of proved) ctx.narrowed.delete(name); + + return [ + { + k: "if", + test, + then, + otherwise: + alternate === undefined + ? [] + : lowerBlock( + alternate["type"] === "BlockStatement" ? (alternate["body"] as Node[]) : [alternate], + ctx, + ), + }, + ]; + } + case "ReturnStatement": { + const argument = (node["argument"] as Node | null) ?? undefined; + + return [{ k: "return", value: argument === undefined ? undefined : lowerExpr(argument, ctx) }]; + } + case "ForStatement": { + const init = node["init"] as Node; + const test = node["test"] as Node; + const declaration = (init["declarations"] as Node[])[0]; + const name = String((declaration["id"] as Node)["name"]); + + ctx.locals.set(name, int); + + return [ + { + k: "forRange", + name, + from: lowerExpr(declaration["init"] as Node, ctx), + until: lowerExpr(test["right"] as Node, ctx), + body: lowerBlock((node["body"] as Node)["body"] as Node[], ctx), + }, + ]; + } + case "ForOfStatement": { + const left = (node["left"] as Node)["declarations"] as Node[]; + const name = String((left[0]["id"] as Node)["name"]); + const iterable = lowerExpr(node["right"] as Node, ctx); + const iterableType = inferType(iterable, ctx.locals, ctx.scope); + const ty = iterableType.k === "list" ? iterableType.of : str; + + ctx.locals.set(name, ty); + + return [ + { k: "forOf", name, ty, iterable, body: lowerBlock((node["body"] as Node)["body"] as Node[], ctx) }, + ]; + } + case "ThrowStatement": { + const argument = node["argument"] as Node; + + if (argument["type"] !== "NewExpression") + return fail(argument, "only `throw new SomeError(message)` is in the subset"); + + return [ + { + k: "throw", + error: String((argument["callee"] as Node)["name"]), + message: lowerExpr((argument["arguments"] as Node[])[0], ctx), + }, + ]; + } + case "TryStatement": { + const handler = node["handler"] as Node; + + return [ + { + k: "try", + body: lowerBlock((node["block"] as Node)["body"] as Node[], ctx), + catchName: String(((handler["param"] as Node | null) ?? { name: "error" })["name"]), + catchBody: lowerBlock((handler["body"] as Node)["body"] as Node[], ctx), + }, + ]; + } + default: + return fail(node, `statement ${String(node["type"])} is outside the subset`); + } +}; + +/** Registers a module level regex const as a pattern, a class, or both. */ +const registerRegex = (name: string, source: string, scope: Scope): void => { + const parsed = parsePattern(source); + + if (parsed.anchored) { + const patternName = `PATTERN_${name}`; + + scope.patterns.push({ name: patternName, source, steps: toSteps(parsed, scope.classes) }); + scope.regexes.set(name, { anchored: true, pattern: patternName }); + + return; + } + + if (parsed.terms.length !== 1) throw new Error(`/${source}/ must be anchored or a single class`); + + const className = scope.classes.intern(parsed.terms[0].ranges, "class"); + const keepClass = scope.classes.intern(complement(parsed.terms[0].ranges), "class"); + + scope.regexes.set(name, { anchored: false, charClass: className, keepClass }); +}; + +/** + * Compiles one portable TypeScript module into the IR. + * + * @param {string} path - The module path. + * @returns {Module} The IR module. + */ +export const compileModule = (path: string): Module => { + const source = readFileSync(path, "utf8"); + const parsed = parseSync(path, source); + + if (parsed.errors.length > 0) throw new Error(`${path}: ${parsed.errors[0].message}`); + + const scope: Scope = { + types: new Map(), + functions: new Map(), + structs: new Map(), + enums: new Map(), + errors: new Map(), + constants: new Map(), + regexes: new Map(), + classes: new ClassTable(), + patterns: [], + stdImports: new Set(), + data: new Map(), + }; + + const functions: FuncDecl[] = []; + const statements = parsed.program.body as unknown as Node[]; + + // `import { asString } from "./_std.ts"` brings in the portable standard library, whose + // members every target implements natively. + for (const statement of statements) { + if (statement["type"] !== "ImportDeclaration") continue; + + const from = String((statement["source"] as Node)["value"]); + + if (!from.endsWith("_std.ts")) throw new Error(`${path}: only "./_std.ts" can be imported`); + + for (const specifier of (statement["specifiers"] as Node[]) ?? []) { + const name = String((specifier["imported"] as Node)["name"]); + + if (!STD_FUNCTIONS.has(name) && !STD_NON_CALLS.has(name)) + throw new Error(`${path}: \`${name}\` is not in the portable std`); + + scope.stdImports.add(name); + } + } + + // First pass: types, constants and function signatures, so order does not matter. + for (const statement of statements) { + const exported = statement["type"] === "ExportNamedDeclaration"; + const declaration = exported ? (statement["declaration"] as Node) : statement; + + if (declaration["type"] === "TSTypeAliasDeclaration") { + const name = String((declaration["id"] as Node)["name"]); + const literal = declaration["typeAnnotation"] as Node; + + if (literal["type"] === "TSUnionType") { + const values = (literal["types"] as Node[]).map((member) => { + const value = (member["literal"] as Node | undefined)?.["value"]; + + if (typeof value !== "string") + return fail(member, `\`${name}\` mixes string literals with something else`); + + return value; + }); + + scope.enums.set(name, { + name, + doc: docBefore(source, declaration["start"] as number), + values, + }); + continue; + } + + const members = (literal["members"] as Node[]) ?? []; + const fields = members.map((member) => { + const annotation = (member["typeAnnotation"] as Node)["typeAnnotation"] as Node; + const union = annotation["type"] === "TSUnionType" ? (annotation["types"] as Node[]) : []; + + return { + name: String((member["key"] as Node)["name"]), + ty: readType(annotation, scope), + doc: docBefore(source, member["start"] as number), + // `version?: 1 | 2` keeps its domain so the TypeScript target can print it back. + domain: + union.length > 0 + ? union.map((entry) => Number((entry["literal"] as Node)["value"])) + : undefined, + }; + }); + + scope.structs.set(name, { + name, + doc: docBefore(source, declaration["start"] as number), + fields, + isOptions: members.every((member) => member["optional"] === true), + }); + continue; + } + + if (declaration["type"] !== "VariableDeclaration") continue; + + for (const entry of declaration["declarations"] as Node[]) { + const name = String((entry["id"] as Node)["name"]); + const init = entry["init"] as Node; + + if (init["type"] === "Literal" && init["regex"] !== undefined && init["regex"] !== null) { + registerRegex(name, String((init["regex"] as Node)["pattern"]), scope); + continue; + } + + if ( + init["type"] === "CallExpression" && + String((init["callee"] as Node)["name"]) === "dataset" + ) { + const datasetName = String(((init["arguments"] as Node[])[0] as Node)["value"]); + const table = JSON.parse( + readFileSync(resolve(dirname(path), `${datasetName}.data.json`), "utf8"), + ) as Omit; + + scope.data.set(name, { name, ...table }); + continue; + } + + if (init["type"] === "ArrowFunctionExpression") { + const params: Param[] = (init["params"] as Node[]).map((param) => { + const declared = readType( + (param["typeAnnotation"] as Node)["typeAnnotation"] as Node, + scope, + ); + const optional = param["optional"] === true; + + // A record parameter is already a reference in every target, so only the value + // types need wrapping to keep "absent" apart from "empty". + return { + name: String(param["name"]), + ty: optional && declared.k !== "named" ? { k: "opt", of: declared } : declared, + optional, + }; + }); + const returnType = init["returnType"] as Node | null; + + scope.functions.set(name, { + params, + ret: returnType === null ? { k: "void" } : readType(returnType["typeAnnotation"] as Node, scope), + isAsync: init["async"] === true, + }); + continue; + } + + if (init["type"] === "ArrayExpression") { + const items = (init["elements"] as Node[]).map((element) => ({ + k: "int" as const, + value: Number(element["value"]), + })); + + scope.constants.set(name, { ty: { k: "list", of: int }, expr: { k: "listOf", items, of: int } }); + continue; + } + + if (init["type"] === "Literal" && typeof init["value"] === "string") { + scope.constants.set(name, { ty: str, expr: { k: "str", value: String(init["value"]) } }); + continue; + } + + fail(init, `module level \`${name}\` is outside the subset`); + } + } + + // Second pass: function bodies. + for (const statement of statements) { + const exported = statement["type"] === "ExportNamedDeclaration"; + const declaration = exported ? (statement["declaration"] as Node) : statement; + + if (declaration["type"] !== "VariableDeclaration") continue; + + for (const entry of declaration["declarations"] as Node[]) { + const init = entry["init"] as Node; + + if (init["type"] !== "ArrowFunctionExpression") continue; + + const name = String((entry["id"] as Node)["name"]); + const signature = scope.functions.get(name); + + if (signature === undefined) continue; + + const locals = new Map(); + + for (const param of signature.params) locals.set(param.name, param.ty); + + const ctx: Ctx = { locals, scope, source, narrowed: new Set() }; + const body = init["body"] as Node; + const statementsOfBody = + body["type"] === "BlockStatement" + ? (body["body"] as Node[]) + : [{ type: "ReturnStatement", argument: body, start: body["start"] }]; + const doc = docBefore(source, (statement["start"] ?? declaration["start"]) as number); + + functions.push({ + name, + doc, + params: signature.params, + ret: signature.ret, + body: lowerBlock(statementsOfBody, ctx), + isAsync: signature.isAsync, + exported, + sources: readSources(doc), + }); + } + } + + // The module's own doc comment is the first block comment in the file. + const firstComment = source.indexOf("*/"); + const moduleDoc = firstComment === -1 ? "" : docBefore(source, firstComment + 2); + + return { + name: basename(path, ".ts"), + doc: moduleDoc.split("\n")[0] ?? "", + charClasses: scope.classes.all() as CharClass[], + patterns: scope.patterns, + structs: [...scope.structs.values()], + enums: [...scope.enums.values()], + errors: [...scope.errors.values()], + functions, + data: [...scope.data.values()], + constants: [...scope.constants.entries()].map(([name, entry]) => ({ name, ...entry })), + }; +}; diff --git a/spec/bridge/compiler/ir.ts b/spec/bridge/compiler/ir.ts new file mode 100644 index 000000000..2c3cce4f6 --- /dev/null +++ b/spec/bridge/compiler/ir.ts @@ -0,0 +1,178 @@ +/** + * The intermediate representation every emitter consumes. + * + * It is deliberately smaller than TypeScript: the frontend rejects anything that does not map + * cleanly onto all seven targets, so an emitter never has to guess. Numbers are 64 bit signed + * integers — none of the utilities in scope needs anything else, and float semantics differ + * enough between the targets to be worth excluding until something needs them. + */ + +export type Ty = + | { k: "string" } + | { k: "int" } + | { k: "bool" } + | { k: "void" } + | { k: "json" } + /** `string | number`: what a public entry point accepts before coercing. */ + | { k: "scalar" } + /** A string whose values are a closed set: a union of string literals in the source. */ + | { k: "enum"; name: string } + | { k: "list"; of: Ty } + | { k: "opt"; of: Ty } + | { k: "named"; name: string }; + +export type Param = { name: string; ty: Ty; optional: boolean }; + +/** A call target: a runtime helper, a function from the source, or a declared error. */ +export type Callee = + | { k: "std"; name: string } + | { k: "user"; name: string } + | { k: "error"; name: string }; + +export type Expr = + | { k: "str"; value: string } + | { k: "int"; value: number } + | { k: "bool"; value: boolean } + | { k: "none" } + | { k: "ref"; name: string } + | { k: "field"; target: Expr; name: string; ty: Ty } + | { k: "index"; target: Expr; index: Expr; ty?: Ty } + | { k: "call"; callee: Callee; args: Expr[]; ty: Ty } + | { k: "bin"; op: BinaryOp; left: Expr; right: Expr; ty?: Ty } + | { k: "not"; operand: Expr } + | { k: "cond"; test: Expr; whenTrue: Expr; whenFalse: Expr } + | { k: "listOf"; items: Expr[]; of: Ty } + | { k: "struct"; name: string; fields: { name: string; value: Expr }[] } + | { k: "lambda"; params: Param[]; body: Stmt[]; ret: Ty; isAsync: boolean } + | { k: "await"; value: Expr } + /** `options?.version ?? fallback`: reads an optional field of an optional struct. */ + | { k: "optionField"; target: string; field: string; ty: Ty; fallback: Expr }; + +export type BinaryOp = + | "+" + | "-" + | "*" + | "%" + | "==" + | "!=" + | "<" + | "<=" + | ">" + | ">=" + | "&&" + | "||"; + +export type Stmt = + | { k: "let"; name: string; ty: Ty; value: Expr; mutable: boolean } + | { k: "assign"; name: string; value: Expr } + | { k: "if"; test: Expr; then: Stmt[]; otherwise: Stmt[] } + | { k: "return"; value?: Expr } + | { k: "forOf"; name: string; ty: Ty; iterable: Expr; body: Stmt[] } + | { k: "forRange"; name: string; from: Expr; until: Expr; body: Stmt[] } + | { k: "throw"; error: string; message: Expr } + | { k: "try"; body: Stmt[]; catchName: string; catchBody: Stmt[] } + | { k: "expr"; value: Expr }; + +/** A record type: a struct in Go and Rust, a class in Java and C#, a dict-like in Python. */ +export type StructDecl = { + name: string; + doc: string; + fields: { name: string; ty: Ty; doc: string; domain?: number[] }[]; + /** Options structs are the second, optional argument of a public function. */ + isOptions: boolean; +}; + +/** A closed set of string values: `type StateCode = "AC" | "AL" | …`. */ +export type EnumDecl = { name: string; doc: string; values: string[] }; + +/** An error type. `base` is another declared error, or undefined for a root error. */ +export type ErrorDecl = { name: string; doc: string; base?: string }; + +export type FuncDecl = { + name: string; + doc: string; + params: Param[]; + ret: Ty; + body: Stmt[]; + isAsync: boolean; + exported: boolean; + /** The `@see` links of the source, carried into every target's documentation. */ + sources: { role: string; url: string }[]; +}; + +/** A dataset: rows of values materialised by every emitter as native data. */ +export type DataDecl = { + name: string; + doc: string; + /** Column names, in order. Every row has one value per column. */ + columns: string[]; + rows: string[][]; + /** Row indexes grouped by the value of the first column, for the per key lookups. */ + groups: Record; + /** The order the rows are returned in when no key is given, baked at build time. */ + fullOrder: number[]; +}; + +/** A compiled character class: sorted, non overlapping code point ranges. */ +export type CharClass = { name: string; ranges: [number, number][]; negated: boolean }; + +/** One step of a compiled pattern: repeat a character class, optionally capturing it. */ +export type PatternStep = { charClass: string; min: number; max: number; capture: boolean }; + +/** A compiled regular expression: anchored, and made only of repeated character classes. */ +export type PatternDecl = { name: string; source: string; steps: PatternStep[] }; + +export type ConstDecl = { name: string; ty: Ty; expr: Expr }; + +export type Module = { + name: string; + doc: string; + constants: ConstDecl[]; + charClasses: CharClass[]; + patterns: PatternDecl[]; + structs: StructDecl[]; + enums: EnumDecl[]; + errors: ErrorDecl[]; + functions: FuncDecl[]; + data: DataDecl[]; +}; + +/** + * The runtime surface every target implements. The frontend maps TypeScript's own string + * methods onto these, so the author writes ordinary TypeScript and the semantics stay pinned. + */ +export const STD = { + // strings + len: { params: ["string"], ret: "int" }, + codeAt: { params: ["string", "int"], ret: "int" }, + slice: { params: ["string", "int", "int"], ret: "string" }, + upper: { params: ["string"], ret: "string" }, + /** Strips the code points JavaScript's `String.prototype.trim` strips — not the host's set. */ + trim: { params: ["string"], ret: "string" }, + padStart: { params: ["string", "int", "string"], ret: "string" }, + repeat: { params: ["string", "int"], ret: "string" }, + fromInt: { params: ["int"], ret: "string" }, + // compiled patterns + patternTest: { params: ["pattern", "string"], ret: "bool" }, + patternCapture: { params: ["pattern", "string"], ret: "list" }, + keepClass: { params: ["class", "string"], ret: "string" }, + classHas: { params: ["class", "string"], ret: "bool" }, + /** Reads the value of an optional the frontend has already proved present. */ + unwrap: { params: ["opt"], ret: "any" }, + // lists + listLen: { params: ["list", "int"], ret: "int" }, + listGet: { params: ["list", "int"], ret: "any" }, + listPush: { params: ["list", "any"], ret: "void" }, + listEmpty: { params: [], ret: "list" }, + // datasets + dataRows: { params: ["data", "string"], ret: "list" }, + dataAll: { params: ["data"], ret: "list" }, + dataHasKey: { params: ["data", "string"], ret: "bool" }, + // json and http + httpGet: { params: ["string"], ret: "named:HttpResponse" }, + jsonString: { params: ["json", "string"], ret: "string" }, + jsonInt: { params: ["json", "string"], ret: "int" }, + jsonTruthy: { params: ["json", "string"], ret: "bool" }, + // concurrency + raceFirstSuccess: { params: ["list"], ret: "any" }, +} as const; diff --git a/spec/bridge/compiler/kit.ts b/spec/bridge/compiler/kit.ts new file mode 100644 index 000000000..27d20288e --- /dev/null +++ b/spec/bridge/compiler/kit.ts @@ -0,0 +1,235 @@ +/** + * Shared helpers for the emitters. + * + * The IR is small enough that each target is its own file, but three things are the same + * everywhere: naming conventions, walking the tree, and hoisting option reads into locals so + * that no emitter has to inline a null check in the middle of an expression. + */ +import type { Expr, FuncDecl, Stmt } from "./ir.ts"; + +/** + * Converts a camelCase name to snake_case. + * + * @param {string} name - The name. + * @returns {string} The converted name. + */ +export const snake = (name: string): string => + name.replaceAll(/([a-z0-9])([A-Z])/g, "$1_$2").toLowerCase(); + +/** + * Converts a name to PascalCase. + * + * @param {string} name - The name. + * @returns {string} The converted name. + */ +export const pascal = (name: string): string => `${name.charAt(0).toUpperCase()}${name.slice(1)}`; + +/** + * Converts a camelCase name to kebab-case. + * + * @param {string} name - The name. + * @returns {string} The converted name. + */ +export const kebab = (name: string): string => + name.replaceAll(/([a-z0-9])([A-Z])/g, "$1-$2").toLowerCase(); + +/** + * Converts a name to SCREAMING_SNAKE_CASE. + * + * @param {string} name - The name. + * @returns {string} The converted name. + */ +export const screaming = (name: string): string => snake(name).toUpperCase(); + +/** + * Visits every expression of a statement list. + * + * @param {Stmt[]} body - The statements. + * @param {Function} visit - Called with each expression. + * @returns {void} + */ +export const walk = (body: Stmt[], visit: (expr: Expr) => void): void => { + const expression = (node: Expr): void => { + visit(node); + + switch (node.k) { + case "field": + expression(node.target); + break; + case "index": + expression(node.target); + expression(node.index); + break; + case "call": + for (const argument of node.args) expression(argument); + break; + case "bin": + expression(node.left); + expression(node.right); + break; + case "not": + expression(node.operand); + break; + case "cond": + expression(node.test); + expression(node.whenTrue); + expression(node.whenFalse); + break; + case "listOf": + for (const item of node.items) expression(item); + break; + case "struct": + for (const field of node.fields) expression(field.value); + break; + case "await": + expression(node.value); + break; + case "lambda": + walk(node.body, visit); + break; + default: + break; + } + }; + + for (const statement of body) { + switch (statement.k) { + case "let": + case "assign": + expression(statement.value); + break; + case "if": + expression(statement.test); + walk(statement.then, visit); + walk(statement.otherwise, visit); + break; + case "return": + if (statement.value !== undefined) expression(statement.value); + break; + case "forOf": + expression(statement.iterable); + walk(statement.body, visit); + break; + case "forRange": + expression(statement.from); + expression(statement.until); + walk(statement.body, visit); + break; + case "throw": + expression(statement.message); + break; + case "try": + walk(statement.body, visit); + walk(statement.catchBody, visit); + break; + case "expr": + expression(statement.value); + break; + } + } +}; + +export type OptionRead = { target: string; field: string; local: string; expr: Expr }; + +/** + * Every option field a function reads, with the local name the emitter binds it to. + * + * Hoisting them turns `options?.version === 2` into a plain comparison against a local that the + * prologue already defaulted, which every target can write idiomatically. + * + * @param {FuncDecl} entry - The function. + * @returns {OptionRead[]} The reads, de-duplicated. + */ +export const optionReads = (entry: FuncDecl): OptionRead[] => { + const found = new Map(); + + walk(entry.body, (node) => { + if (node.k !== "optionField") return; + + const key = `${node.target}.${node.field}`; + + if (found.has(key)) return; + + found.set(key, { + target: node.target, + field: node.field, + local: `${node.target}${pascal(node.field)}`, + expr: node, + }); + }); + + return [...found.values()]; +}; + +/** + * The names a function pushes onto, which some targets must declare mutable. + * + * @param {FuncDecl} entry - The function. + * @returns {Set} The names. + */ +export const pushTargets = (entry: FuncDecl): Set => { + const found = new Set(); + + walk(entry.body, (node) => { + if (node.k !== "call" || node.callee.k !== "std" || node.callee.name !== "listPush") return; + + const target = node.args[0]; + + if (target.k === "ref") found.add(target.name); + }); + + return found; +}; + +/** + * Whether a function's body calls a given runtime helper. + * + * @param {FuncDecl[]} functions - The functions to scan. + * @param {string} name - The helper name. + * @returns {boolean} True when it is called at least once. + */ +export const usesStd = (functions: FuncDecl[], name: string): boolean => { + let used = false; + + for (const entry of functions) { + walk(entry.body, (node) => { + if (node.k === "call" && node.callee.k === "std" && node.callee.name === name) used = true; + }); + } + + return used; +}; + +/** + * The prose of a doc comment, without the JSDoc tags, for targets that do not use them. + * + * The `@see` lines survive: the provenance of an algorithm belongs in every language. + * + * @param {string} doc - The source doc comment. + * @returns {string} The prose and the `@see` lines. + */ +export const prose = (doc: string): string => { + const lines: string[] = []; + let skipping = false; + + for (const line of doc.split("\n")) { + const trimmed = line.trim(); + + if (trimmed.startsWith("@see")) { + lines.push(trimmed); + skipping = false; + continue; + } + + if (trimmed.startsWith("@")) { + skipping = true; + continue; + } + + if (skipping) continue; + + lines.push(line); + } + + return lines.join("\n").replaceAll(/\n{3,}/g, "\n\n").trim(); +}; diff --git a/spec/bridge/compiler/regex.ts b/spec/bridge/compiler/regex.ts new file mode 100644 index 000000000..a67dc1a5a --- /dev/null +++ b/spec/bridge/compiler/regex.ts @@ -0,0 +1,344 @@ +/** + * Compiles the regular expression literals the source uses into a portable form. + * + * A regex is not portable: `\s` matches 6 code points in Go and Ruby, 25 in JavaScript, and a + * Unicode property in Python and Rust. So the bridge never passes a pattern through to the + * target's regex engine. It parses the literal here and lowers it into two things every target + * can reproduce exactly: character classes as explicit code point ranges, and a sequence of + * "repeat this class between min and max times, capturing or not". + * + * The accepted subset is anchored patterns made of character classes with quantifiers. No + * alternation, no backreferences, no lookaround — the frontend rejects the literal instead of + * guessing, which is the whole point. + */ +import type { CharClass, PatternStep } from "./ir.ts"; + +type Ranges = [number, number][]; + +/** The code points JavaScript's `\s` matches and `trim()` strips. */ +const JS_WHITESPACE: Ranges = [ + [0x09, 0x0d], + [0x20, 0x20], + [0xa0, 0xa0], + [0x1680, 0x1680], + [0x2000, 0x200a], + [0x2028, 0x2029], + [0x202f, 0x202f], + [0x205f, 0x205f], + [0x3000, 0x3000], + [0xfeff, 0xfeff], +]; + +const DIGITS: Ranges = [[0x30, 0x39]]; +const MAX_CODE_POINT = 0x10_ffff; + +/** + * Sorts and merges ranges so that two classes built differently compare equal. + * + * @param {Ranges} ranges - The ranges to normalise. + * @returns {Ranges} Sorted, non overlapping ranges. + */ +export const normalise = (ranges: Ranges): Ranges => { + const sorted = [...ranges].sort((left, right) => left[0] - right[0]); + const merged: Ranges = []; + + for (const [from, to] of sorted) { + const last = merged.at(-1); + + if (last !== undefined && from <= last[1] + 1) { + last[1] = Math.max(last[1], to); + continue; + } + + merged.push([from, to]); + } + + return merged; +}; + +/** + * The complement of a set of ranges over the whole code point space. + * + * @param {Ranges} ranges - The ranges to invert. + * @returns {Ranges} Everything the input does not cover. + */ +export const complement = (ranges: Ranges): Ranges => { + const merged = normalise(ranges); + const inverted: Ranges = []; + let cursor = 0; + + for (const [from, to] of merged) { + if (from > cursor) inverted.push([cursor, from - 1]); + + cursor = to + 1; + } + + if (cursor <= MAX_CODE_POINT) inverted.push([cursor, MAX_CODE_POINT]); + + return inverted; +}; + +/** + * Whether two classes share any code point. The matcher scans greedily and never backtracks, + * which is only correct when consecutive classes cannot both match the same character. + * + * @param {Ranges} left - The first class. + * @param {Ranges} right - The second class. + * @returns {boolean} True when they overlap. + */ +export const overlaps = (left: Ranges, right: Ranges): boolean => + left.some(([from, to]) => right.some(([otherFrom, otherTo]) => from <= otherTo && otherFrom <= to)); + +type Parsed = { ranges: Ranges; min: number; max: number; capture: boolean }; + +/** Reads one escape sequence, starting after the backslash. */ +const readEscape = (source: string, index: number): { ranges: Ranges; next: number } => { + const char = source[index]; + + if (char === "d") return { ranges: DIGITS, next: index + 1 }; + if (char === "D") return { ranges: complement(DIGITS), next: index + 1 }; + if (char === "s") return { ranges: JS_WHITESPACE, next: index + 1 }; + if (char === "S") return { ranges: complement(JS_WHITESPACE), next: index + 1 }; + if (char === "n") return { ranges: [[0x0a, 0x0a]], next: index + 1 }; + if (char === "r") return { ranges: [[0x0d, 0x0d]], next: index + 1 }; + if (char === "t") return { ranges: [[0x09, 0x09]], next: index + 1 }; + + if (char === "u") { + const code = Number.parseInt(source.slice(index + 1, index + 5), 16); + + return { ranges: [[code, code]], next: index + 5 }; + } + + const code = source.codePointAt(index) ?? 0; + + return { ranges: [[code, code]], next: index + String.fromCodePoint(code).length }; +}; + +/** Reads a `[...]` character class, starting after the opening bracket. */ +const readClass = (source: string, start: number): { ranges: Ranges; next: number } => { + let index = start; + let negated = false; + const ranges: Ranges = []; + + if (source[index] === "^") { + negated = true; + index++; + } + + while (index < source.length && source[index] !== "]") { + let low: Ranges; + + if (source[index] === "\\") { + const escape = readEscape(source, index + 1); + + low = escape.ranges; + index = escape.next; + } else { + const code = source.codePointAt(index) ?? 0; + + low = [[code, code]]; + index += String.fromCodePoint(code).length; + } + + const isRange = + source[index] === "-" && source[index + 1] !== "]" && index + 1 < source.length && low.length === 1; + + if (isRange) { + index++; + + const high = + source[index] === "\\" + ? readEscape(source, index + 1) + : { + ranges: [[source.codePointAt(index) ?? 0, source.codePointAt(index) ?? 0]] as Ranges, + next: index + String.fromCodePoint(source.codePointAt(index) ?? 0).length, + }; + + ranges.push([low[0][0], high.ranges[0][1]]); + index = high.next; + continue; + } + + ranges.push(...low); + } + + return { ranges: negated ? complement(ranges) : normalise(ranges), next: index + 1 }; +}; + +/** Reads a quantifier, if there is one at `index`. */ +const readQuantifier = (source: string, index: number): { min: number; max: number; next: number } => { + if (source[index] === "*") return { min: 0, max: -1, next: index + 1 }; + if (source[index] === "+") return { min: 1, max: -1, next: index + 1 }; + if (source[index] === "?") return { min: 0, max: 1, next: index + 1 }; + + if (source[index] === "{") { + const close = source.indexOf("}", index); + const body = source.slice(index + 1, close); + const [first, second] = body.split(","); + const min = Number(first); + + if (second === undefined) return { min, max: min, next: close + 1 }; + + return { min, max: second === "" ? -1 : Number(second), next: close + 1 }; + } + + return { min: 1, max: 1, next: index }; +}; + +export type CompiledPattern = { + /** True when the literal was anchored at both ends, which is what `patternTest` needs. */ + anchored: boolean; + terms: Parsed[]; +}; + +/** + * Parses a regex literal's source into the term sequence the matcher runs. + * + * @param {string} source - The pattern source, without the slashes. + * @returns {CompiledPattern} The parsed terms. + * @throws {Error} When the pattern uses a construct outside the portable subset. + */ +export const parsePattern = (source: string): CompiledPattern => { + let index = 0; + let anchoredStart = false; + let anchoredEnd = false; + const terms: Parsed[] = []; + + if (source[index] === "^") { + anchoredStart = true; + index++; + } + + while (index < source.length) { + if (source[index] === "$" && index === source.length - 1) { + anchoredEnd = true; + index++; + continue; + } + + let capture = false; + let ranges: Ranges; + + if (source[index] === "(") { + if (source.slice(index, index + 3) === "(?:") + throw new Error(`non capturing groups are outside the portable subset: /${source}/`); + + capture = true; + index++; + + const inner = + source[index] === "[" + ? readClass(source, index + 1) + : source[index] === "\\" + ? readEscape(source, index + 1) + : { + ranges: [ + [source.codePointAt(index) ?? 0, source.codePointAt(index) ?? 0], + ] as Ranges, + next: index + 1, + }; + + ranges = inner.ranges; + index = inner.next; + + const quantifier = readQuantifier(source, index); + + index = quantifier.next; + + if (source[index] !== ")") + throw new Error(`a group must hold exactly one class: /${source}/`); + + index++; + terms.push({ ranges, min: quantifier.min, max: quantifier.max, capture }); + continue; + } + + if (source[index] === "[") { + const parsed = readClass(source, index + 1); + + ranges = parsed.ranges; + index = parsed.next; + } else if (source[index] === "\\") { + const parsed = readEscape(source, index + 1); + + ranges = parsed.ranges; + index = parsed.next; + } else if ("|.+*?()".includes(source[index])) { + throw new Error(`\`${source[index]}\` is outside the portable regex subset: /${source}/`); + } else { + const code = source.codePointAt(index) ?? 0; + + ranges = [[code, code]]; + index += String.fromCodePoint(code).length; + } + + const quantifier = readQuantifier(source, index); + + index = quantifier.next; + terms.push({ ranges, min: quantifier.min, max: quantifier.max, capture }); + } + + // A greedy, backtrack free matcher is only correct when a repeated class cannot also start + // the next term. + for (const [position, term] of terms.entries()) { + const next = terms[position + 1]; + + if (term.max !== term.min && next !== undefined && overlaps(term.ranges, next.ranges)) { + throw new Error( + `terms ${position} and ${position + 1} of /${source}/ overlap, which needs backtracking`, + ); + } + } + + return { anchored: anchoredStart && anchoredEnd, terms }; +}; + +/** Collects character classes into a module wide table, de-duplicated by their ranges. */ +export class ClassTable { + private readonly byKey = new Map(); + + /** + * Interns a class and returns the name the emitters refer to it by. + * + * @param {Ranges} ranges - The class ranges. + * @param {string} hint - A readable name to base the identifier on. + * @returns {string} The interned class name. + */ + public intern(ranges: Ranges, hint: string): string { + const merged = normalise(ranges); + const key = merged.map(([from, to]) => `${from}-${to}`).join(","); + const existing = this.byKey.get(key); + + if (existing !== undefined) return existing.name; + + const name = `${hint}${this.byKey.size}`; + + this.byKey.set(key, { name, ranges: merged, negated: false }); + + return name; + } + + /** + * Every interned class, in insertion order. + * + * @returns {CharClass[]} The classes. + */ + public all(): CharClass[] { + return [...this.byKey.values()]; + } +} + +/** + * Lowers a parsed pattern into the steps an emitter writes out. + * + * @param {CompiledPattern} pattern - The parsed pattern. + * @param {ClassTable} classes - The module's class table. + * @returns {PatternStep[]} The steps. + */ +export const toSteps = (pattern: CompiledPattern, classes: ClassTable): PatternStep[] => + pattern.terms.map((term) => ({ + charClass: classes.intern(term.ranges, "class"), + min: term.min, + max: term.max, + capture: term.capture, + })); diff --git a/spec/bridge/compiler/runtime/csharp.cs b/spec/bridge/compiler/runtime/csharp.cs new file mode 100644 index 000000000..98977dee9 --- /dev/null +++ b/spec/bridge/compiler/runtime/csharp.cs @@ -0,0 +1,240 @@ +// The portable runtime for the C# target. +// +// C# strings are UTF-16, the same as JavaScript's, so indexes and lengths already line up; +// what is here is the rest: the compiled classes and patterns, and the JavaScript specific +// trimming rules. + +using System; +using System.Text; + +namespace BrazilianUtils.Bridge +{ + ///

One step of a compiled pattern: repeat a class between Min and Max times. + public sealed class PatternStep + { + public int[][] CharClass { get; } + public long Min { get; } + public long Max { get; } + public bool Capture { get; } + + public PatternStep(int[][] charClass, long min, long max, bool capture) + { + CharClass = charClass; + Min = min; + Max = max; + Capture = capture; + } + } + + /// Helpers shared by the generated utilities. + public static class Runtime + { + /// The code points JavaScript's trim() strips; Trim() is a different set. + private static readonly int[][] JsWhitespace = + { + new[] { 0x09, 0x0d }, new[] { 0x20, 0x20 }, new[] { 0xa0, 0xa0 }, + new[] { 0x1680, 0x1680 }, new[] { 0x2000, 0x200a }, new[] { 0x2028, 0x2029 }, + new[] { 0x202f, 0x202f }, new[] { 0x205f, 0x205f }, new[] { 0x3000, 0x3000 }, + new[] { 0xfeff, 0xfeff } + }; + + /// Whether a code point belongs to a class. + public static bool InClass(int[][] charClass, int code) + { + foreach (var span in charClass) + { + if (code >= span[0] && code <= span[1]) + { + return true; + } + } + + return false; + } + + /// Reads one code unit, or -1 when the index is out of range. + public static long CodeAt(string value, long index) + { + if (index < 0 || index >= value.Length) + { + return -1; + } + + return value[(int)index]; + } + + /// Takes the code units between two indexes, clamping like JavaScript's slice. + public static string Slice(string value, long from, long to) + { + var start = Math.Max(0, from); + var end = Math.Min(value.Length, to); + + if (start >= end) + { + return string.Empty; + } + + return value.Substring((int)start, (int)(end - start)); + } + + /// Whether any character of the value belongs to the class. + public static bool ClassHas(int[][] charClass, string value) + { + foreach (var character in value) + { + if (InClass(charClass, character)) + { + return true; + } + } + + return false; + } + + /// Keeps only the characters of the value that belong to the class. + public static string KeepClass(int[][] charClass, string value) + { + var kept = new StringBuilder(); + + foreach (var character in value) + { + if (InClass(charClass, character)) + { + kept.Append(character); + } + } + + return kept.ToString(); + } + + /// Runs a compiled pattern against the whole value, without backtracking. + public static bool PatternTest(PatternStep[] steps, string value) + { + var index = 0; + + foreach (var step in steps) + { + long count = 0; + + while ((step.Max < 0 || count < step.Max) + && index < value.Length + && InClass(step.CharClass, value[index])) + { + index++; + count++; + } + + if (count < step.Min) + { + return false; + } + } + + return index == value.Length; + } + + /// Strips the code points JavaScript's trim() strips. + public static string JsTrim(string value) + { + var start = 0; + var end = value.Length; + + while (start < end && InClass(JsWhitespace, value[start])) + { + start++; + } + + while (end > start && InClass(JsWhitespace, value[end - 1])) + { + end--; + } + + return value.Substring(start, end - start); + } + + /// Left pads the value with a filler up to a length. + public static string PadStart(string value, long length, string filler) + { + var padded = new StringBuilder(); + + while (padded.Length + value.Length < length) + { + padded.Append(filler); + } + + return padded + value; + } + + /// Repeats a value. + public static string Repeat(string value, long times) + { + return times <= 0 ? string.Empty : string.Concat(Enumerable(value, times)); + } + + private static System.Collections.Generic.IEnumerable Enumerable(string value, long times) + { + for (long index = 0; index < times; index++) + { + yield return value; + } + } + + /// Reads an optional flag the way JavaScript reads truthiness. + public static bool IsTruthy(bool? value) + { + return value == true; + } + + /// Every row of a dataset, in the baked full order. + public static string[][] DataAll(Dataset table) + { + return table.All; + } + + /// The rows whose first column is the key given, empty when the key is unknown. + public static string[][] DataRows(Dataset table, string key) + { + return table.Rows(key); + } + } + + /// A dataset: the rows in the baked full order, and the rows of each key. + public sealed class Dataset + { + private static readonly string[][] Empty = new string[0][]; + + public string[][] All { get; } + + private readonly System.Collections.Generic.Dictionary byKey; + + public Dataset(string[][] rows, string[] keys, int[][] groups, int[] fullOrder) + { + All = new string[fullOrder.Length][]; + + for (var index = 0; index < fullOrder.Length; index++) + { + All[index] = rows[fullOrder[index]]; + } + + byKey = new System.Collections.Generic.Dictionary(keys.Length); + + for (var group = 0; group < keys.Length; group++) + { + var of = new string[groups[group].Length][]; + + for (var index = 0; index < groups[group].Length; index++) + { + of[index] = rows[groups[group][index]]; + } + + byKey[keys[group]] = of; + } + } + + /// The rows of one key, empty when the key is unknown. + public string[][] Rows(string key) + { + return byKey.TryGetValue(key, out var found) ? found : Empty; + } + } +} diff --git a/spec/bridge/compiler/runtime/go.go b/spec/bridge/compiler/runtime/go.go new file mode 100644 index 000000000..605dd805f --- /dev/null +++ b/spec/bridge/compiler/runtime/go.go @@ -0,0 +1,200 @@ +// Package runtime holds everything the generated Go code needs that is not plain syntax. +// +// Strings are indexed by code point, not by byte, so that the generated code means the same +// thing it does in the other targets. +package runtime + +import "strings" + +// CharClass is a set of code points, as sorted non overlapping ranges. +type CharClass [][2]rune + +// PatternStep repeats a class between Min and Max times; Max -1 means unbounded. +type PatternStep struct { + Class CharClass + Min int + Max int + Capture bool +} + +// The code points JavaScript's trim() strips. Go's strings.TrimSpace is a different set. +var jsWhitespace = CharClass{ + {0x09, 0x0d}, {0x20, 0x20}, {0xa0, 0xa0}, {0x1680, 0x1680}, {0x2000, 0x200a}, + {0x2028, 0x2029}, {0x202f, 0x202f}, {0x205f, 0x205f}, {0x3000, 0x3000}, {0xfeff, 0xfeff}, +} + +// InClass reports whether a code point belongs to a class. +func InClass(class CharClass, code rune) bool { + for _, span := range class { + if code >= span[0] && code <= span[1] { + return true + } + } + + return false +} + +// Len counts the code points of a value. +func Len(value string) int { + return len([]rune(value)) +} + +// CodeAt reads one code point, or -1 when the index is out of range. +func CodeAt(value string, index int) int { + if index < 0 { + return -1 + } + + position := 0 + + for _, char := range value { + if position == index { + return int(char) + } + + position++ + } + + return -1 +} + +// Slice takes the code points between two indexes. +func Slice(value string, from int, to int) string { + runes := []rune(value) + + if from < 0 { + from = 0 + } + + if to > len(runes) { + to = len(runes) + } + + if from >= to { + return "" + } + + return string(runes[from:to]) +} + +// ClassHas reports whether any character of the value belongs to the class. +func ClassHas(class CharClass, value string) bool { + for _, char := range value { + if InClass(class, char) { + return true + } + } + + return false +} + +// KeepClass keeps only the characters of the value that belong to the class. +func KeepClass(class CharClass, value string) string { + var kept strings.Builder + + for _, char := range value { + if InClass(class, char) { + kept.WriteRune(char) + } + } + + return kept.String() +} + +// PatternTest runs a compiled pattern against the whole value, greedily and without backtracking. +func PatternTest(steps []PatternStep, value string) bool { + runes := []rune(value) + index := 0 + + for _, step := range steps { + count := 0 + + for (step.Max < 0 || count < step.Max) && index < len(runes) && InClass(step.Class, runes[index]) { + index++ + count++ + } + + if count < step.Min { + return false + } + } + + return index == len(runes) +} + +// JsTrim strips the code points JavaScript's trim() strips. +func JsTrim(value string) string { + return strings.TrimFunc(value, func(char rune) bool { return InClass(jsWhitespace, char) }) +} + +// PadStart left pads the value with a filler up to a length, counted in code points. +func PadStart(value string, length int, filler string) string { + missing := length - Len(value) + + if missing <= 0 { + return value + } + + return strings.Repeat(filler, missing) + value +} + +// Upper uppercases a value. +func Upper(value string) string { + return strings.ToUpper(value) +} + +// Repeat repeats a value. +func Repeat(value string, times int) string { + if times <= 0 { + return "" + } + + return strings.Repeat(value, times) +} + +// DataGroup names the rows of one key of a dataset. +type DataGroup struct { + Key string + Rows []int +} + +// Dataset holds the rows of a table in the two orders the generated code asks for. +type Dataset struct { + all [][]string + byKey map[string][][]string +} + +// NewDataset materialises a dataset, resolving both orders once. +func NewDataset(rows [][]string, groups []DataGroup, fullOrder []int) *Dataset { + table := &Dataset{all: make([][]string, 0, len(fullOrder)), byKey: make(map[string][][]string, len(groups))} + + for _, index := range fullOrder { + table.all = append(table.all, rows[index]) + } + + for _, group := range groups { + of := make([][]string, 0, len(group.Rows)) + + for _, index := range group.Rows { + of = append(of, rows[index]) + } + + table.byKey[group.Key] = of + } + + return table +} + +// DataAll returns every row of a dataset, in the baked full order. +func DataAll(table *Dataset) [][]string { + return table.all +} + +// DataRows returns the rows whose first column is the key given, empty when the key is unknown. +func DataRows(table *Dataset, key string) [][]string { + if rows, ok := table.byKey[key]; ok { + return rows + } + + return [][]string{} +} diff --git a/spec/bridge/compiler/runtime/java.java b/spec/bridge/compiler/runtime/java.java new file mode 100644 index 000000000..38c3ffdad --- /dev/null +++ b/spec/bridge/compiler/runtime/java.java @@ -0,0 +1,193 @@ +// The portable runtime for the Java target. +// +// Java strings are UTF-16, the same as JavaScript's, so indexes and lengths already line up; +// what is here is the rest: the compiled classes and patterns, and the JavaScript specific +// trimming and coercion rules. + +/** Helpers shared by the generated utilities. */ +public final class Runtime { + private Runtime() {} + + /** The code points JavaScript's trim() strips. Java's String.strip() is a different set. */ + private static final int[][] JS_WHITESPACE = { + {0x09, 0x0d}, {0x20, 0x20}, {0xa0, 0xa0}, {0x1680, 0x1680}, {0x2000, 0x200a}, + {0x2028, 0x2029}, {0x202f, 0x202f}, {0x205f, 0x205f}, {0x3000, 0x3000}, {0xfeff, 0xfeff} + }; + + /** One step of a compiled pattern: repeat a class between min and max times. */ + public static final class PatternStep { + public final int[][] charClass; + public final long min; + public final long max; + public final boolean capture; + + public PatternStep(int[][] charClass, long min, long max, boolean capture) { + this.charClass = charClass; + this.min = min; + this.max = max; + this.capture = capture; + } + } + + /** Whether a code point belongs to a class. */ + public static boolean inClass(int[][] charClass, int code) { + for (int[] span : charClass) { + if (code >= span[0] && code <= span[1]) { + return true; + } + } + + return false; + } + + /** Reads one code unit, or -1 when the index is out of range. */ + public static long codeAt(String value, long index) { + if (index < 0 || index >= value.length()) { + return -1; + } + + return value.charAt((int) index); + } + + /** Takes the code units between two indexes, clamping like JavaScript's slice. */ + public static String slice(String value, long from, long to) { + long start = Math.max(0, from); + long end = Math.min(value.length(), to); + + if (start >= end) { + return ""; + } + + return value.substring((int) start, (int) end); + } + + /** Whether any character of the value belongs to the class. */ + public static boolean classHas(int[][] charClass, String value) { + for (int index = 0; index < value.length(); index++) { + if (inClass(charClass, value.charAt(index))) { + return true; + } + } + + return false; + } + + /** Keeps only the characters of the value that belong to the class. */ + public static String keepClass(int[][] charClass, String value) { + StringBuilder kept = new StringBuilder(); + + for (int index = 0; index < value.length(); index++) { + if (inClass(charClass, value.charAt(index))) { + kept.append(value.charAt(index)); + } + } + + return kept.toString(); + } + + /** Runs a compiled pattern against the whole value, greedily and without backtracking. */ + public static boolean patternTest(PatternStep[] steps, String value) { + int index = 0; + + for (PatternStep step : steps) { + long count = 0; + + while ((step.max < 0 || count < step.max) + && index < value.length() + && inClass(step.charClass, value.charAt(index))) { + index++; + count++; + } + + if (count < step.min) { + return false; + } + } + + return index == value.length(); + } + + /** Strips the code points JavaScript's trim() strips. */ + public static String jsTrim(String value) { + int start = 0; + int end = value.length(); + + while (start < end && inClass(JS_WHITESPACE, value.charAt(start))) { + start++; + } + while (end > start && inClass(JS_WHITESPACE, value.charAt(end - 1))) { + end--; + } + + return value.substring(start, end); + } + + /** Left pads the value with a filler up to a length. */ + public static String padStart(String value, long length, String filler) { + StringBuilder padded = new StringBuilder(); + + while (padded.length() + value.length() < length) { + padded.append(filler); + } + + return padded + value; + } + + /** Repeats a value. */ + public static String repeat(String value, long times) { + return times <= 0 ? "" : value.repeat((int) times); + } + + /** Reads an optional flag the way JavaScript reads truthiness. */ + public static boolean isTruthy(Boolean value) { + return value != null && value; + } + + /** A dataset: the rows in the baked full order, and the rows of each key. */ + public static final class Dataset { + private final String[][] all; + private final java.util.Map byKey; + + public Dataset(String[][] rows, String[] keys, int[][] groups, int[] fullOrder) { + this.all = new String[fullOrder.length][]; + + for (int index = 0; index < fullOrder.length; index++) { + this.all[index] = rows[fullOrder[index]]; + } + + this.byKey = new java.util.HashMap<>(keys.length * 2); + + for (int group = 0; group < keys.length; group++) { + String[][] of = new String[groups[group].length][]; + + for (int index = 0; index < groups[group].length; index++) { + of[index] = rows[groups[group][index]]; + } + + this.byKey.put(keys[group], of); + } + } + + /** Every row, in the baked full order. */ + public String[][] all() { + return this.all; + } + + /** The rows whose first column is the key given, empty when the key is unknown. */ + public String[][] rows(String key) { + String[][] found = this.byKey.get(key); + + return found == null ? new String[0][] : found; + } + } + + /** Every row of a dataset, in the baked full order. */ + public static String[][] dataAll(Dataset table) { + return table.all(); + } + + /** The rows whose first column is the key given, empty when the key is unknown. */ + public static String[][] dataRows(Dataset table, String key) { + return table.rows(key); + } +} diff --git a/spec/bridge/compiler/runtime/python.py b/spec/bridge/compiler/runtime/python.py new file mode 100644 index 000000000..153525890 --- /dev/null +++ b/spec/bridge/compiler/runtime/python.py @@ -0,0 +1,157 @@ +"""The portable runtime for the Python target. + +Everything the generated code needs that is not plain syntax lives here. The compiled character +classes and patterns are passed in as data, so this file never changes when a utility does. +""" + +from typing import Any, List, Optional, Sequence, Tuple + +CharClass = Sequence[Tuple[int, int]] + +# The code points JavaScript's `trim()` strips. Python's `str.strip()` is a different set, so +# the set is spelled out here rather than inherited from the host. +_JS_WHITESPACE = frozenset( + [0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x20, 0xA0, 0x1680, 0x2028, 0x2029, 0x202F, 0x205F, 0x3000, 0xFEFF] + + list(range(0x2000, 0x200B)) +) + + +class PatternStep: + """One step of a compiled pattern: repeat a class between `min` and `max` times.""" + + __slots__ = ("char_class", "min", "max", "capture") + + def __init__(self, char_class: CharClass, minimum: int, maximum: int, capture: bool) -> None: + self.char_class = char_class + self.min = minimum + self.max = maximum + self.capture = capture + + +def in_class(char_class: CharClass, code: int) -> bool: + """Whether a code point belongs to a class.""" + for start, end in char_class: + if start <= code <= end: + return True + + return False + + +def code_at(value: str, index: int) -> int: + """Reads one code unit, or -1 when the index is out of range.""" + if index < 0 or index >= len(value): + return -1 + + return ord(value[index]) + + +def class_has(char_class: CharClass, value: str) -> bool: + """Whether any character of the value belongs to the class.""" + for char in value: + if in_class(char_class, ord(char)): + return True + + return False + + +def keep_class(char_class: CharClass, value: str) -> str: + """Keeps only the characters of the value that belong to the class.""" + return "".join(char for char in value if in_class(char_class, ord(char))) + + +def pattern_test(steps: Sequence[PatternStep], value: str) -> bool: + """Runs a compiled pattern against the whole value, greedily and without backtracking.""" + index = 0 + + for step in steps: + count = 0 + + while ( + (step.max < 0 or count < step.max) + and index < len(value) + and in_class(step.char_class, ord(value[index])) + ): + index += 1 + count += 1 + + if count < step.min: + return False + + return index == len(value) + + +def js_trim(value: str) -> str: + """Strips the code points JavaScript's `trim()` strips.""" + start = 0 + end = len(value) + + while start < end and ord(value[start]) in _JS_WHITESPACE: + start += 1 + while end > start and ord(value[end - 1]) in _JS_WHITESPACE: + end -= 1 + + return value[start:end] + + +def pad_start(value: str, length: int, filler: str) -> str: + """Left pads the value with a filler up to a length.""" + return value.rjust(length, filler) + + +def as_string(value: Any) -> str: + """Reads a value as a string the way JavaScript's `String(value)` does.""" + if isinstance(value, str): + return value + if value is True: + return "true" + if value is False: + return "false" + if value is None: + return "null" + if isinstance(value, int): + return str(value) + if isinstance(value, float): + return str(int(value)) if value.is_integer() else str(value) + + try: + return str(value) + except Exception: # noqa: BLE001 - a value with no string form reads as empty, as in JavaScript + return "" + + +def is_truthy(value: Any) -> bool: + """Reads an optional flag the way JavaScript reads truthiness.""" + return bool(value) + + +def list_get(values: List[Any], index: int) -> Any: + """Reads one element, or None when the index is out of range.""" + if index < 0 or index >= len(values): + return None + + return values[index] + + +class Dataset: + """A dataset: the rows in the baked full order, and the rows of each key.""" + + __slots__ = ("all", "by_key") + + def __init__(self, rows, groups, full_order): + self.all = [rows[index] for index in full_order] + self.by_key = {key: [rows[index] for index in indexes] for key, indexes in groups} + + +def make_dataset(rows, groups, full_order): + """Materialises a dataset, resolving both orders once.""" + return Dataset(rows, groups, full_order) + + +def data_all(table): + """Every row of a dataset, in the baked full order.""" + return table.all + + +def data_rows(table, key): + """The rows whose first column is the key given, empty when the key is unknown.""" + return table.by_key.get(key, []) diff --git a/spec/bridge/compiler/runtime/ruby.rb b/spec/bridge/compiler/runtime/ruby.rb new file mode 100644 index 000000000..07d2ae2e2 --- /dev/null +++ b/spec/bridge/compiler/runtime/ruby.rb @@ -0,0 +1,131 @@ +# frozen_string_literal: true + +# The portable runtime for the Ruby target. +# +# Ruby indexes strings by character, which is what the generated code expects; everything else +# the code needs that is not plain syntax lives here. +module BrazilianUtilsBridge + # Helpers shared by the generated utilities. + module Runtime + # The code points JavaScript's trim() strips. Ruby's String#strip is a different set. + JS_WHITESPACE = [ + [0x09, 0x0d], [0x20, 0x20], [0xa0, 0xa0], [0x1680, 0x1680], [0x2000, 0x200a], + [0x2028, 0x2029], [0x202f, 0x202f], [0x205f, 0x205f], [0x3000, 0x3000], [0xfeff, 0xfeff] + ].freeze + + # One step of a compiled pattern: repeat a class between min and max times. + PatternStep = Struct.new(:char_class, :min, :max, :capture) + + # Whether a code point belongs to a class. + def self.in_class(char_class, code) + char_class.each do |span| + return true if code >= span[0] && code <= span[1] + end + + false + end + + # Reads one code point, or -1 when the index is out of range. + def self.code_at(value, index) + return -1 if index.negative? || index >= value.length + + value[index].ord + end + + # Whether any character of the value belongs to the class. + def self.class_has(char_class, value) + value.each_char.any? { |char| in_class(char_class, char.ord) } + end + + # Keeps only the characters of the value that belong to the class. + def self.keep_class(char_class, value) + value.each_char.select { |char| in_class(char_class, char.ord) }.join + end + + # Runs a compiled pattern against the whole value, greedily and without backtracking. + def self.pattern_test(steps, value) + chars = value.chars + index = 0 + + steps.each do |step| + count = 0 + + while (step.max.negative? || count < step.max) && index < chars.length && + in_class(step.char_class, chars[index].ord) + index += 1 + count += 1 + end + + return false if count < step.min + end + + index == chars.length + end + + # Strips the code points JavaScript's trim() strips. + def self.js_trim(value) + chars = value.chars + start = 0 + last = chars.length + + start += 1 while start < last && in_class(JS_WHITESPACE, chars[start].ord) + last -= 1 while last > start && in_class(JS_WHITESPACE, chars[last - 1].ord) + + chars[start...last].join + end + + # Left pads the value with a filler up to a length. + def self.pad_start(value, length, filler) + value.rjust(length, filler) + end + + # Reads a value as a string the way JavaScript's String(value) does. + def self.as_string(value) + return value if value.is_a?(String) + return 'true' if value == true + return 'false' if value == false + return 'null' if value.nil? + return value.to_s if value.is_a?(Integer) + + if value.is_a?(Float) + return value.to_i.to_s if value == value.to_i + + return value.to_s + end + + value.to_s + end + + # Reads an optional flag the way JavaScript reads truthiness. + def self.is_truthy(value) + !value.nil? && value != false + end + + # A dataset: the rows in the baked full order, and the rows of each key. + class Dataset + attr_reader :all, :by_key + + def initialize(rows, groups, full_order) + @all = full_order.map { |index| rows[index] } + @by_key = {} + groups.each { |key, indexes| @by_key[key] = indexes.map { |index| rows[index] } } + freeze + end + end + + # Materialises a dataset, resolving both orders once. + def self.make_dataset(rows, groups, full_order) + Dataset.new(rows, groups, full_order) + end + + # Every row of a dataset, in the baked full order. + def self.data_all(table) + table.all + end + + # The rows whose first column is the key given, empty when the key is unknown. + def self.data_rows(table, key) + table.by_key.fetch(key, []) + end + end +end diff --git a/spec/bridge/compiler/runtime/rust.rs b/spec/bridge/compiler/runtime/rust.rs new file mode 100644 index 000000000..5052ade32 --- /dev/null +++ b/spec/bridge/compiler/runtime/rust.rs @@ -0,0 +1,172 @@ +//! The portable runtime for the Rust target. +//! +//! Strings are indexed by code point, not by byte, so the generated code means the same thing +//! it does in the other targets. + +/// A set of code points, as sorted non overlapping ranges. +pub type CharClass = &'static [(u32, u32)]; + +/// Repeats a class between `min` and `max` times; `max` -1 means unbounded. +pub struct PatternStep { + pub class: CharClass, + pub min: i64, + pub max: i64, + pub capture: bool, +} + +/// The code points JavaScript's `trim()` strips. +const JS_WHITESPACE: CharClass = &[ + (0x09, 0x0d), + (0x20, 0x20), + (0xa0, 0xa0), + (0x1680, 0x1680), + (0x2000, 0x200a), + (0x2028, 0x2029), + (0x202f, 0x202f), + (0x205f, 0x205f), + (0x3000, 0x3000), + (0xfeff, 0xfeff), +]; + +/// Whether a code point belongs to a class. +pub fn in_class(class: CharClass, code: u32) -> bool { + class.iter().any(|(from, to)| code >= *from && code <= *to) +} + +/// Counts the code points of a value. +pub fn len(value: &str) -> i64 { + value.chars().count() as i64 +} + +/// Reads one code point, or -1 when the index is out of range. +pub fn code_at(value: &str, index: i64) -> i64 { + if index < 0 { + return -1; + } + + match value.chars().nth(index as usize) { + None => -1, + Some(char) => char as i64, + } +} + +/// Takes the code points between two indexes. +pub fn slice(value: &str, from: i64, to: i64) -> String { + let chars: Vec = value.chars().collect(); + let start = from.max(0) as usize; + let end = (to.max(0) as usize).min(chars.len()); + + if start >= end { + return String::new(); + } + + chars[start..end].iter().collect() +} + +/// Whether any character of the value belongs to the class. +pub fn class_has(class: CharClass, value: &str) -> bool { + value.chars().any(|char| in_class(class, char as u32)) +} + +/// Keeps only the characters of the value that belong to the class. +pub fn keep_class(class: CharClass, value: &str) -> String { + value.chars().filter(|char| in_class(class, *char as u32)).collect() +} + +/// Runs a compiled pattern against the whole value, greedily and without backtracking. +pub fn pattern_test(steps: &[PatternStep], value: &str) -> bool { + let chars: Vec = value.chars().collect(); + let mut index = 0usize; + + for step in steps { + let mut count = 0i64; + + while (step.max < 0 || count < step.max) + && index < chars.len() + && in_class(step.class, chars[index] as u32) + { + index += 1; + count += 1; + } + + if count < step.min { + return false; + } + } + + index == chars.len() +} + +/// Strips the code points JavaScript's `trim()` strips. +pub fn js_trim(value: &str) -> String { + value + .trim_matches(|char: char| in_class(JS_WHITESPACE, char as u32)) + .to_string() +} + +/// Left pads the value with a filler up to a length, counted in code points. +pub fn pad_start(value: &str, length: i64, filler: &str) -> String { + let missing = length - len(value); + + if missing <= 0 { + return value.to_string(); + } + + format!("{}{}", filler.repeat(missing as usize), value) +} + +/// Uppercases a value. +pub fn upper(value: &str) -> String { + value.to_uppercase() +} + +/// Repeats a value. +pub fn repeat(value: &str, times: i64) -> String { + if times <= 0 { + return String::new(); + } + + value.repeat(times as usize) +} + +/// One row of a dataset: the cells, in column order. +pub type Row = &'static [&'static str]; + +/// A dataset: the rows in the baked full order, and the rows of each key. +pub struct Dataset { + all: Vec, + by_key: std::collections::HashMap<&'static str, Vec>, +} + +impl Dataset { + /// Materialises a dataset, resolving both orders once. + pub fn new( + rows: &'static [Row], + groups: &'static [(&'static str, &'static [usize])], + full_order: &'static [usize], + ) -> Self { + let mut by_key = std::collections::HashMap::with_capacity(groups.len()); + + for (key, indexes) in groups { + by_key.insert(*key, indexes.iter().map(|index| rows[*index]).collect()); + } + + Self { + all: full_order.iter().map(|index| rows[*index]).collect(), + by_key, + } + } +} + +/// Every row of a dataset, in the baked full order. +pub fn data_all(table: &'static Dataset) -> Vec { + table.all.clone() +} + +/// The rows whose first column is the key given, empty when the key is unknown. +pub fn data_rows(table: &'static Dataset, key: &str) -> Vec { + match table.by_key.get(key) { + Some(rows) => rows.clone(), + None => Vec::new(), + } +} diff --git a/spec/bridge/compiler/runtime/typescript.ts b/spec/bridge/compiler/runtime/typescript.ts new file mode 100644 index 000000000..b8db764b3 --- /dev/null +++ b/spec/bridge/compiler/runtime/typescript.ts @@ -0,0 +1,183 @@ +/** + * The portable runtime for the TypeScript target. + * + * Everything the generated code needs that is not plain syntax lives here: the compiled + * character classes and patterns are passed in as data, so this file never changes when a + * utility does. + */ + +/** A character class: sorted, non overlapping code point ranges. */ +export type CharClass = readonly (readonly [number, number])[]; + +/** One step of a compiled pattern: repeat a class between `min` and `max` times. */ +export type PatternStep = { + readonly charClass: CharClass; + readonly min: number; + readonly max: number; + readonly capture: boolean; +}; + +/** + * Whether a code point belongs to a class. + * + * @param {CharClass} charClass - The class to test against. + * @param {number} code - The code point. + * @returns {boolean} True when the class covers the code point. + */ +export const inClass = (charClass: CharClass, code: number): boolean => { + for (const [from, to] of charClass) { + if (code >= from && code <= to) return true; + } + + return false; +}; + +/** + * Reads one code unit, or -1 when the index is out of range. + * + * @param {string} value - The string to read. + * @param {number} index - The index. + * @returns {number} The code unit, or -1. + */ +export const codeAt = (value: string, index: number): number => + index >= 0 && index < value.length ? value.charCodeAt(index) : -1; + +/** + * Whether any character of the value belongs to the class. + * + * @param {CharClass} charClass - The class to look for. + * @param {string} value - The string to scan. + * @returns {boolean} True when at least one character matches. + */ +export const classHas = (charClass: CharClass, value: string): boolean => { + for (let index = 0; index < value.length; index++) { + if (inClass(charClass, value.charCodeAt(index))) return true; + } + + return false; +}; + +/** + * Keeps only the characters of the value that belong to the class. + * + * @param {CharClass} charClass - The class to keep. + * @param {string} value - The string to filter. + * @returns {string} The filtered string. + */ +export const keepClass = (charClass: CharClass, value: string): string => { + let kept = ""; + + for (let index = 0; index < value.length; index++) { + if (inClass(charClass, value.charCodeAt(index))) kept += value.charAt(index); + } + + return kept; +}; + +/** + * Runs a compiled pattern against the whole value. + * + * The scan is greedy and never backtracks, which the compiler guarantees is correct by + * refusing any pattern whose consecutive classes overlap. + * + * @param {PatternStep[]} steps - The compiled steps. + * @param {string} value - The string to match. + * @returns {boolean} True when the whole value matches. + */ +export const patternTest = (steps: readonly PatternStep[], value: string): boolean => { + let index = 0; + + for (const step of steps) { + let count = 0; + + while ( + (step.max < 0 || count < step.max) && + index < value.length && + inClass(step.charClass, value.charCodeAt(index)) + ) { + index++; + count++; + } + + if (count < step.min) return false; + } + + return index === value.length; +}; + +/** + * Left pads the value with a filler up to a length. + * + * @param {string} value - The value to pad. + * @param {number} length - The target length. + * @param {string} filler - The single character filler. + * @returns {string} The padded value. + */ +export const padStart = (value: string, length: number, filler: string): string => + value.padStart(length, filler); + +/** + * Reads a value as a string the way `String(value)` does, answering `""` when the value has no + * string conversion at all. + * + * @param {string|number} value - The value to read. + * @returns {string} The string form. + */ +export const asString = (value: string | number): string => { + try { + return String(value); + } catch { + return ""; + } +}; + +/** + * Reads an optional flag the way JavaScript reads truthiness. + * + * @param {boolean} [value] - The flag. + * @returns {boolean} Whether the flag is set. + */ +export const isTruthy = (value?: boolean): boolean => Boolean(value); + +/** A dataset: string rows, the row indexes grouped by the first column, and the full order. */ +export type Dataset = { + readonly all: string[][]; + readonly byKey: ReadonlyMap; +}; + +/** + * Materialises a dataset, resolving both orders once. + * + * A `Map` rather than an object literal is what makes `dataRows(table, "toString")` answer with + * no rows instead of an inherited property. + * + * @param {string[][]} rows - The table. + * @param {Array} groups - The `[key, rowIndexes]` pairs. + * @param {number[]} fullOrder - The order the rows are returned in when no key is given. + * @returns {Dataset} The dataset. + */ +export const makeDataset = ( + rows: string[][], + groups: [string, number[]][], + fullOrder: number[], +): Dataset => ({ + all: fullOrder.map((index) => rows[index]), + byKey: new Map(groups.map(([key, indexes]) => [key, indexes.map((index) => rows[index])])), +}); + +/** + * Every row of a dataset, in the baked full order. + * + * @param {Dataset} table - The dataset. + * @returns {string[][]} The rows. + */ +export const dataAll = (table: Dataset): string[][] => table.all; + +/** + * The rows whose first column is the key given, in the baked per key order. + * + * @param {Dataset} table - The dataset. + * @param {string} key - The value of the first column. + * @returns {string[][]} The rows, empty when the key is unknown. + */ +export const dataRows = (table: Dataset, key: string): string[][] => table.byKey.get(key) ?? []; diff --git a/spec/bridge/compiler/targets/csharp.ts b/spec/bridge/compiler/targets/csharp.ts new file mode 100644 index 000000000..6cffd6362 --- /dev/null +++ b/spec/bridge/compiler/targets/csharp.ts @@ -0,0 +1,469 @@ +/** + * The C# emitter. + * + * A static class per module, nullable value types for the options, and the option reads + * hoisted into locals by the prologue. C#'s strings are UTF-16 like JavaScript's, so indexes + * need no translation. + */ +import { readFileSync } from "node:fs"; +import { resolve } from "node:path"; +import type { + CharClass, + DataDecl, + Expr, + FuncDecl, + Module, + PatternDecl, + Stmt, + StructDecl, + Ty, +} from "../ir.ts"; +import { optionReads, pascal, prose, screaming } from "../kit.ts"; + +/** The record types of the module being emitted, so a literal calls the right constructor. */ +let structs = new Map(); + +/** The declared types in scope, so a list knows whether it is an array or a growing list. */ +let localTypes = new Map(); + +/** Splits a list into fixed size chunks, so no one method carries the whole table. */ +const chunks = (items: T[], size: number): T[][] => { + const out: T[][] = []; + + for (let index = 0; index < items.length; index += size) out.push(items.slice(index, index + size)); + + return out; +}; + +const RUNTIME = resolve(import.meta.dirname, "../runtime/csharp.cs"); +const NAMESPACE = "BrazilianUtils.Bridge"; + +/** Module level names the emitter writes verbatim. */ +let verbatim = new Set(); + +/** + * C# keywords a source level identifier can collide with; `@` escapes them. + * + * @param {string} name - The identifier from the source. + * @returns {string} A form C# accepts. + */ +const safe = (name: string): string => + new Set([ + "base", + "class", + "default", + "event", + "fixed", + "lock", + "object", + "operator", + "params", + "ref", + "string", + "value", + ]).has(name) + ? `@${name}` + : name; + +const CONTROL: Record = { + 0x08: "\\b", + 0x09: "\\t", + 0x0a: "\\n", + 0x0c: "\\f", + 0x0d: "\\r", +}; + +/** Renders a string as a C# literal. */ +const lit = (value: string): string => { + let out = '"'; + + for (const char of value) { + const code = char.codePointAt(0) ?? 0; + + if (char === '"') out += String.raw`\"`; + else if (char === "\\") out += String.raw`\\`; + else if (code < 0x20) out += CONTROL[code] ?? `\\u${code.toString(16).padStart(4, "0")}`; + else if (code > 0xff_ff) { + const offset = code - 0x1_00_00; + + out += `\\u${(0xd8_00 + (offset >> 10)).toString(16).padStart(4, "0")}`; + out += `\\u${(0xdc_00 + (offset & 0x3_ff)).toString(16).padStart(4, "0")}`; + } else if (code > 0x7e) out += `\\u${code.toString(16).padStart(4, "0")}`; + else out += char; + } + + return `${out}"`; +}; + +/** Renders an IR type. */ +const type = (ty: Ty): string => { + switch (ty.k) { + case "string": + case "scalar": + case "json": + case "enum": + return "string"; + case "int": + return "long"; + case "bool": + return "bool"; + case "void": + return "void"; + case "list": + // A list of records is built by appending, which an array cannot do. + return ty.of.k === "named" + ? `System.Collections.Generic.List<${type(ty.of)}>` + : `${type(ty.of)}[]`; + case "opt": + return `${type(ty.of)}?`; + case "named": + return ty.name; + } +}; + +const OPS: Record = { + "+": "+", + "-": "-", + "*": "*", + "%": "%", + "==": "==", + "!=": "!=", + "<": "<", + "<=": "<=", + ">": ">", + ">=": ">=", + "&&": "&&", + "||": "||", +}; + +/** Renders an expression. */ +const expr = (node: Expr): string => { + switch (node.k) { + case "str": + return lit(node.value); + case "int": + return `${node.value}L`; + case "bool": + return String(node.value); + case "none": + return "null"; + case "ref": + return verbatim.has(node.name) ? screaming(node.name) : safe(node.name); + case "field": + return `${expr(node.target)}.${pascal(node.name)}`; + case "index": + return `${expr(node.target)}[(int) ${expr(node.index)}]`; + case "not": + return `!${expr(node.operand)}`; + case "bin": + return `(${expr(node.left)} ${OPS[node.op]} ${expr(node.right)})`; + case "cond": + return `(${expr(node.test)} ? ${expr(node.whenTrue)} : ${expr(node.whenFalse)})`; + case "listOf": + if (node.of.k === "named") + return `new System.Collections.Generic.List<${type(node.of)}>()`; + + return `{ ${node.items.map((item) => expr(item)).join(", ")} }`; + case "struct": { + const declared = structs.get(node.name); + const order = declared?.fields.map((field) => field.name) ?? node.fields.map((f) => f.name); + + return `new ${node.name}(${order + .map((name) => expr(node.fields.find((field) => field.name === name)?.value ?? { k: "none" })) + .join(", ")})`; + } + case "optionField": + return `${safe(node.target)}${pascal(node.field)}`; + case "call": + return call(node); + default: + throw new Error(`csharp: unsupported expression ${node.k}`); + } +}; + +/** Whether an expression is a growing list rather than an array. */ +const isGrowing = (node: Expr): boolean => { + if (node.k !== "ref") return false; + + const ty = localTypes.get(node.name); + + return ty !== undefined && ty.k === "list" && ty.of.k === "named"; +}; + +/** Renders a call. */ +const call = (node: Extract): string => { + const args = node.args.map((argument) => expr(argument)); + + if (node.callee.k === "user") return `${pascal(node.callee.name)}(${args.join(", ")})`; + + switch (node.callee.name) { + case "len": + return `(long) ${args[0]}.Length`; + case "listLen": + return isGrowing(node.args[0]) ? `(long) ${args[0]}.Count` : `(long) ${args[0]}.Length`; + case "codeAt": + return `Runtime.CodeAt(${args[0]}, ${args[1]})`; + case "slice": + return `Runtime.Slice(${args[0]}, ${args[1]}, ${args[2]})`; + case "upper": + return `${args[0]}.ToUpperInvariant()`; + case "trim": + return `Runtime.JsTrim(${args[0]})`; + case "padStart": + return `Runtime.PadStart(${args[0]}, ${args[1]}, ${args[2]})`; + case "repeat": + return `Runtime.Repeat(${args[0]}, ${args[1]})`; + case "classHas": + return `Runtime.ClassHas(${args[0]}, ${args[1]})`; + case "keepClass": + return `Runtime.KeepClass(${args[0]}, ${args[1]})`; + case "patternTest": + return `Runtime.PatternTest(${args[0]}, ${args[1]})`; + case "asString": + // C#'s types already guarantee a string at the boundary. + return args[0]; + case "isTruthy": + return args[0]; + case "listPush": + return `${args[0]}.Add(${args[1]})`; + case "unwrap": + // C# has no separate optional value to open; a reference is already nullable. + return args[0]; + case "dataAll": + return `Runtime.DataAll(${args[0]})`; + case "dataRows": + return `Runtime.DataRows(${args[0]}, ${args[1]})`; + default: + throw new Error(`csharp: unsupported runtime call ${node.callee.name}`); + } +}; + +/** Renders a statement list. */ +const block = (body: Stmt[], indent: string): string => + body + .map((statement) => stmt(statement, indent)) + .filter((line) => line !== "") + .join("\n"); + +/** Renders one statement. */ +const stmt = (node: Stmt, indent: string): string => { + switch (node.k) { + case "let": + localTypes.set(node.name, node.ty); + + return `${indent}${type(node.ty)} ${safe(node.name)} = ${expr(node.value)};`; + case "assign": + return `${indent}${safe(node.name)} = ${expr(node.value)};`; + case "if": { + const otherwise = + node.otherwise.length === 0 + ? "" + : `\n${indent}else\n${indent}{\n${block(node.otherwise, `${indent} `)}\n${indent}}`; + + return `${indent}if (${expr(node.test)})\n${indent}{\n${block(node.then, `${indent} `)}\n${indent}}${otherwise}`; + } + case "return": + return node.value === undefined ? `${indent}return;` : `${indent}return ${expr(node.value)};`; + case "forRange": + return `${indent}for (long ${safe(node.name)} = ${expr(node.from)}; ${safe(node.name)} < ${expr(node.until)}; ${safe(node.name)}++)\n${indent}{\n${block(node.body, `${indent} `)}\n${indent}}`; + case "forOf": + return `${indent}foreach (var ${safe(node.name)} in ${expr(node.iterable)})\n${indent}{\n${block(node.body, `${indent} `)}\n${indent}}`; + case "expr": { + const value = node.value; + + if (value.k === "call" && value.callee.k === "std" && value.callee.name === "boundaryGuard") { + const [subject, , fallback] = value.args; + const name = subject.k === "ref" ? safe(subject.name) : ""; + + return `${indent}if (${name} == null)\n${indent}{\n${indent} return ${expr(fallback)};\n${indent}}`; + } + + return `${indent}${expr(value)};`; + } + default: + throw new Error(`csharp: unsupported statement ${node.k}`); + } +}; + +/** Renders a character class table entry. */ +const charClass = (entry: CharClass): string => + ` private static readonly int[][] ${screaming(entry.name)} = { ${entry.ranges.map(([from, to]) => `new[] { 0x${from.toString(16)}, 0x${to.toString(16)} }`).join(", ")} };`; + +/** Renders a compiled pattern table entry. */ +const pattern = (entry: PatternDecl): string => + ` private static readonly PatternStep[] ${screaming(entry.name)} =\n {\n${entry.steps + .map( + (step) => + ` new PatternStep(${screaming(step.charClass)}, ${step.min}, ${step.max}, ${step.capture}),`, + ) + .join("\n")}\n };`; + +/** Renders an options record. */ +const struct = (entry: StructDecl): string => { + const fields = entry.fields + .map( + (field) => + `${field.doc === "" ? "" : ` /// ${field.doc}\n`} public ${type(field.ty)}${entry.isOptions ? "?" : ""} ${pascal(field.name)} { get; set; }`, + ) + .join("\n\n"); + // An options record is filled in property by property; a value record is built in one go. + const constructor = entry.isOptions + ? "" + : `\n\n public ${entry.name}(${entry.fields + .map((field) => `${type(field.ty)} ${field.name}`) + .join(", ")})\n {\n${entry.fields + .map((field) => ` ${pascal(field.name)} = ${field.name};`) + .join("\n")}\n }`; + + return ` /// ${entry.doc} + public sealed class ${entry.name} + { +${fields}${constructor} + }`; +}; + +/** Renders a dataset as the tables the runtime materialises, chunked so no method carries + * the whole thing. */ +const data = (entry: DataDecl): string => { + const name = pascal(entry.name.toLowerCase()); + const rowChunks = chunks( + entry.rows.map( + (row, index) => ` rows[${index}] = new[] { ${row.map((cell) => lit(cell)).join(", ")} };`, + ), + 200, + ); + const keys = Object.keys(entry.groups); + const groupChunks = chunks( + keys.map( + (key, index) => ` groups[${index}] = new[] { ${entry.groups[key].join(", ")} };`, + ), + 5, + ); + + return ` /// ${entry.doc} + private static readonly Dataset ${screaming(entry.name)} = new Dataset( + ${name}Rows(), new[] { ${keys.map((key) => lit(key)).join(", ")} }, ${name}Groups(), + new[] { ${entry.fullOrder.join(", ")} }); + + private static string[][] ${name}Rows() + { + var rows = new string[${entry.rows.length}][]; +${rowChunks.map((_, index) => ` ${name}Rows${index}(rows);`).join("\n")} + return rows; + } + +${rowChunks + .map( + (chunk, index) => + ` private static void ${name}Rows${index}(string[][] rows)\n {\n${chunk.join("\n")}\n }`, + ) + .join("\n\n")} + + private static int[][] ${name}Groups() + { + var groups = new int[${keys.length}][]; +${groupChunks.map((_, index) => ` ${name}Groups${index}(groups);`).join("\n")} + return groups; + } + +${groupChunks + .map( + (chunk, index) => + ` private static void ${name}Groups${index}(int[][] groups)\n {\n${chunk.join("\n")}\n }`, + ) + .join("\n\n")}`; +}; + +/** Renders one function. */ +const func = (entry: FuncDecl): string => { + localTypes = new Map(entry.params.map((param) => [param.name, param.ty])); + + const params = entry.params + .map( + (param) => + `${type(param.ty.k === "opt" ? param.ty.of : param.ty)} ${safe(param.name)}${param.optional ? " = null" : ""}`, + ) + .join(", "); + const prologue = optionReads(entry) + .map((read) => { + const local = `${safe(read.target)}${pascal(read.field)}`; + const fallback = read.expr.k === "optionField" ? expr(read.expr.fallback) : "null"; + const declared = read.expr.k === "optionField" && read.expr.ty.k === "bool" ? "bool" : "long"; + + return ` ${declared} ${local} = ${fallback};\n if (${safe(read.target)} != null && ${safe(read.target)}.${pascal(read.field)} != null)\n {\n ${local} = ${safe(read.target)}.${pascal(read.field)}.Value;\n }`; + }) + .join("\n"); + const doc = prose(entry.doc); + const comment = + doc === "" + ? "" + : ` /// \n${doc + .split("\n") + .map((line) => ` /// ${line}`.trimEnd()) + .join("\n")}\n /// \n`; + + return `${comment} public static ${type(entry.ret)} ${pascal(entry.name)}(${params}) + { +${prologue === "" ? "" : `${prologue}\n`}${block(entry.body, " ")} + }`; +}; + +/** + * Emits the C# target of one module. + * + * @param {Module} module - The compiled module. + * @returns {Record} The files, by path. + */ +export const emit = (module: Module): Record => { + structs = new Map(module.structs.map((entry) => [entry.name, entry])); + verbatim = new Set([ + ...module.charClasses.map((entry) => entry.name), + ...module.patterns.map((entry) => entry.name), + ...module.constants.map((entry) => entry.name), + ...module.data.map((entry) => entry.name), + ]); + + const className = pascal(module.name); + const constants = module.constants + .map((entry) => + entry.ty.k === "list" + ? ` private static readonly long[] ${screaming(entry.name)} = ${expr(entry.expr)};` + : ` private const string ${screaming(entry.name)} = ${expr(entry.expr)};`, + ) + .join("\n"); + + return { + "Runtime.cs": readFileSync(RUNTIME, "utf8"), + "Bridge.csproj": ` + + net8.0 + disable + BrazilianUtilsBridge + BrazilianUtils.Bridge + Exe + + +`, + [`${className}.cs`]: `// Code generated from spec/bridge/source/${module.name}.ts. DO NOT EDIT. + +namespace ${NAMESPACE} +{ +${module.structs.map((entry) => struct(entry)).join("\n\n")} + + /// ${module.doc} + public static class ${className} + { +${module.charClasses.map((entry) => charClass(entry)).join("\n")} + +${module.patterns.map((entry) => pattern(entry)).join("\n\n")} + +${constants} + +${module.data.map((entry) => data(entry)).join("\n\n")} + +${module.functions.map((entry) => func(entry)).join("\n\n")} + } +} +`, + }; +}; diff --git a/spec/bridge/compiler/targets/go.ts b/spec/bridge/compiler/targets/go.ts new file mode 100644 index 000000000..75346ec40 --- /dev/null +++ b/spec/bridge/compiler/targets/go.ts @@ -0,0 +1,334 @@ +/** + * The Go emitter. + * + * Exported names in Go's style, options as a pointer to a struct of pointers so that "unset" + * and "set to zero" stay distinguishable, and the option reads hoisted into locals by the + * prologue. + */ +import { readFileSync } from "node:fs"; +import { resolve } from "node:path"; +import type { + CharClass, + DataDecl, + Expr, + FuncDecl, + Module, + PatternDecl, + Stmt, + StructDecl, + Ty, +} from "../ir.ts"; +import { optionReads, pascal, prose, screaming } from "../kit.ts"; + +const RUNTIME = resolve(import.meta.dirname, "../runtime/go.go"); + +/** Module level names the emitter writes verbatim. */ +let verbatim = new Set(); + +/** Renders a string as a Go literal. */ +const lit = (value: string): string => { + let out = '"'; + + for (const char of value) { + const code = char.codePointAt(0) ?? 0; + + if (char === '"') out += String.raw`\"`; + else if (char === "\\") out += String.raw`\\`; + else if (code > 0xff_ff) out += `\\U${code.toString(16).padStart(8, "0")}`; + else if (code < 0x20 || code > 0x7e) out += `\\u${code.toString(16).padStart(4, "0")}`; + else out += char; + } + + return `${out}"`; +}; + +/** Renders an IR type. */ +const type = (ty: Ty): string => { + switch (ty.k) { + case "string": + case "scalar": + case "enum": + return "string"; + case "int": + return "int64"; + case "bool": + return "bool"; + case "void": + return ""; + case "json": + return "any"; + case "list": + return `[]${type(ty.of)}`; + case "opt": + return `*${type(ty.of)}`; + case "named": + return `*${ty.name}`; + } +}; + +const OPS: Record = { + "+": "+", + "-": "-", + "*": "*", + "%": "%", + "==": "==", + "!=": "!=", + "<": "<", + "<=": "<=", + ">": ">", + ">=": ">=", + "&&": "&&", + "||": "||", +}; + +/** Renders an expression. */ +const expr = (node: Expr): string => { + switch (node.k) { + case "str": + return lit(node.value); + case "int": + return String(node.value); + case "bool": + return String(node.value); + case "none": + return "nil"; + case "ref": + return verbatim.has(node.name) ? node.name : node.name; + case "field": + return `${expr(node.target)}.${pascal(node.name)}`; + case "index": + return `${expr(node.target)}[${expr(node.index)}]`; + case "not": + return `!${expr(node.operand)}`; + case "bin": + return `(${expr(node.left)} ${OPS[node.op]} ${expr(node.right)})`; + case "cond": + throw new Error("go: the ternary operator has no Go form; use an if statement"); + case "listOf": + return `[]${type(node.of)}{${node.items.map((item) => expr(item)).join(", ")}}`; + case "struct": + return `&${node.name}{${node.fields + .map((field) => `${pascal(field.name)}: ${expr(field.value)}`) + .join(", ")}}`; + case "optionField": + return `${node.target}${pascal(node.field)}`; + case "call": + return call(node); + default: + throw new Error(`go: unsupported expression ${node.k}`); + } +}; + +/** Renders a call. */ +const call = (node: Extract): string => { + const args = node.args.map((argument) => expr(argument)); + + if (node.callee.k === "user") return `${node.callee.name}(${args.join(", ")})`; + + switch (node.callee.name) { + case "len": + return `int64(runtime.Len(${args[0]}))`; + case "listLen": + return `int64(len(${args[0]}))`; + case "codeAt": + return `int64(runtime.CodeAt(${args[0]}, int(${args[1]})))`; + case "slice": + return `runtime.Slice(${args[0]}, int(${args[1]}), int(${args[2]}))`; + case "upper": + return `runtime.Upper(${args[0]})`; + case "trim": + return `runtime.JsTrim(${args[0]})`; + case "padStart": + return `runtime.PadStart(${args[0]}, int(${args[1]}), ${args[2]})`; + case "repeat": + return `runtime.Repeat(${args[0]}, int(${args[1]}))`; + case "classHas": + return `runtime.ClassHas(${args[0]}, ${args[1]})`; + case "keepClass": + return `runtime.KeepClass(${args[0]}, ${args[1]})`; + case "patternTest": + return `runtime.PatternTest(${args[0]}, ${args[1]})`; + case "asString": + // Go's type system already guarantees a string at the boundary. + return args[0]; + case "isTruthy": + return args[0]; + case "listPush": + // `append` returns a new slice, so a push is an assignment; it is only ever a statement. + return `${args[0]} = append(${args[0]}, ${args[1]})`; + case "unwrap": + return `*${args[0]}`; + case "dataAll": + return `runtime.DataAll(${args[0]})`; + case "dataRows": + return `runtime.DataRows(${args[0]}, ${args[1]})`; + default: + throw new Error(`go: unsupported runtime call ${node.callee.name}`); + } +}; + +/** Renders a statement list. */ +const block = (body: Stmt[], indent: string): string => + body + .map((statement) => stmt(statement, indent)) + .filter((line) => line !== "") + .join("\n"); + +/** Renders one statement. */ +const stmt = (node: Stmt, indent: string): string => { + switch (node.k) { + case "let": + // Integers are int64 throughout, so they are declared rather than inferred: `:=` on a + // literal would make an `int` that will not compare against the rest. + return node.ty.k === "int" + ? `${indent}var ${node.name} int64 = ${expr(node.value)}` + : `${indent}${node.name} := ${expr(node.value)}`; + case "assign": + return `${indent}${node.name} = ${expr(node.value)}`; + case "if": { + const otherwise = + node.otherwise.length === 0 ? "" : ` else {\n${block(node.otherwise, `${indent}\t`)}\n${indent}}`; + + return `${indent}if ${expr(node.test)} {\n${block(node.then, `${indent}\t`)}\n${indent}}${otherwise}`; + } + case "return": + return node.value === undefined ? `${indent}return` : `${indent}return ${expr(node.value)}`; + case "forRange": + return `${indent}for ${node.name} := int64(${expr(node.from)}); ${node.name} < ${expr(node.until)}; ${node.name}++ {\n${block(node.body, `${indent}\t`)}\n${indent}}`; + case "forOf": + return `${indent}for _, ${node.name} := range ${expr(node.iterable)} {\n${block(node.body, `${indent}\t`)}\n${indent}}`; + case "expr": { + const value = node.value; + + // Go's types make the boundary guards unnecessary, except for the nullish one on a + // value that is a string here rather than a union. + if (value.k === "call" && value.callee.k === "std" && value.callee.name === "boundaryGuard") + return ""; + + return `${indent}${expr(value)}`; + } + default: + throw new Error(`go: unsupported statement ${node.k}`); + } +}; + +/** Renders a character class table entry. */ +const charClass = (entry: CharClass): string => + `var ${entry.name} = runtime.CharClass{${entry.ranges.map(([from, to]) => `{0x${from.toString(16)}, 0x${to.toString(16)}}`).join(", ")}}`; + +/** Renders a compiled pattern table entry. */ +const pattern = (entry: PatternDecl): string => + `var ${entry.name} = []runtime.PatternStep{\n${entry.steps + .map( + (step) => + `\t{Class: ${step.charClass}, Min: ${step.min}, Max: ${step.max}, Capture: ${step.capture}},`, + ) + .join("\n")}\n}`; + +/** Renders an options record. */ +const struct = (entry: StructDecl): string => { + const fields = entry.fields + .map( + (field) => + `${field.doc === "" ? "" : `\t// ${field.doc}\n`}\t${pascal(field.name)} ${entry.isOptions ? "*" : ""}${type(field.ty)}`, + ) + .join("\n"); + + return `// ${entry.name} ${entry.doc} +type ${entry.name} struct { +${fields} +}`; +}; + +/** Renders a dataset as the table the runtime materialises. */ +const data = (entry: DataDecl): string => { + const rows = entry.rows + .map((row) => `\t{${row.map((cell) => lit(cell)).join(", ")}},`) + .join("\n"); + const groups = Object.entries(entry.groups) + .map(([key, indexes]) => `\t{Key: ${lit(key)}, Rows: []int{${indexes.join(", ")}}},`) + .join("\n"); + + return `// ${entry.name} ${entry.doc} +var ${entry.name} = runtime.NewDataset( +\t[][]string{ +${rows} +\t}, +\t[]runtime.DataGroup{ +${groups} +\t}, +\t[]int{${entry.fullOrder.join(", ")}}, +)`; +}; + +/** Renders one function. */ +const func = (entry: FuncDecl): string => { + const name = entry.exported ? pascal(entry.name) : entry.name; + const params = entry.params + .map((param) => `${param.name} ${type(param.ty)}`) + .join(", "); + const prologue = optionReads(entry) + .map((read) => { + const local = `${read.target}${pascal(read.field)}`; + const fallback = read.expr.k === "optionField" ? expr(read.expr.fallback) : "nil"; + const declared = read.expr.k === "optionField" && read.expr.ty.k === "bool" ? "bool" : "int64"; + + return `\tvar ${local} ${declared} = ${fallback}\n\tif ${read.target} != nil && ${read.target}.${pascal(read.field)} != nil {\n\t\t${local} = *${read.target}.${pascal(read.field)}\n\t}`; + }) + .join("\n"); + const doc = prose(entry.doc) + .split("\n") + .map((line) => `// ${line}`.trimEnd()) + .join("\n"); + + return `${doc === "" ? "" : `${doc.replace("// ", `// ${name} `)}\n`}func ${name}(${params}) ${type(entry.ret)} { +${prologue === "" ? "" : `${prologue}\n`}${block(entry.body, "\t")} +}`; +}; + +/** + * Emits the Go target of one module. + * + * @param {Module} module - The compiled module. + * @returns {Record} The files, by path. + */ +export const emit = (module: Module): Record => { + verbatim = new Set([ + ...module.charClasses.map((entry) => entry.name), + ...module.patterns.map((entry) => entry.name), + ...module.constants.map((entry) => entry.name), + ...module.data.map((entry) => entry.name), + ]); + + const constants = module.constants + .map((entry) => + entry.ty.k === "list" + ? `var ${screaming(entry.name)} = ${expr(entry.expr)}` + : `const ${screaming(entry.name)} = ${expr(entry.expr)}`, + ) + .join("\n"); + + return { + "runtime/runtime.go": readFileSync(RUNTIME, "utf8"), + "go.mod": "module brazilianutils/bridge\n\ngo 1.22\n", + [`${module.name}/${module.name}.go`]: `// Code generated from spec/bridge/source/${module.name}.ts. DO NOT EDIT. + +// Package ${module.name} holds the generated ${module.name} utilities. +package ${module.name} + +import "brazilianutils/bridge/runtime" + +${module.charClasses.map((entry) => charClass(entry)).join("\n")} + +${module.patterns.map((entry) => pattern(entry)).join("\n\n")} + +${constants} + +${module.structs.map((entry) => struct(entry)).join("\n\n")} + +${module.data.map((entry) => data(entry)).join("\n\n")} + +${module.functions.map((entry) => func(entry)).join("\n\n")} +`, + }; +}; diff --git a/spec/bridge/compiler/targets/java.ts b/spec/bridge/compiler/targets/java.ts new file mode 100644 index 000000000..55822b147 --- /dev/null +++ b/spec/bridge/compiler/targets/java.ts @@ -0,0 +1,450 @@ +/** + * The Java emitter. + * + * A final class of static methods per module, boxed nullable fields for the options, and the + * option reads hoisted into locals by the prologue. Java's strings are UTF-16 like + * JavaScript's, so indexes need no translation. + */ +import { readFileSync } from "node:fs"; +import { resolve } from "node:path"; +import type { + CharClass, + DataDecl, + Expr, + FuncDecl, + Module, + PatternDecl, + Stmt, + StructDecl, + Ty, +} from "../ir.ts"; +import { optionReads, pascal, prose, screaming } from "../kit.ts"; + +/** The record types of the module being emitted, so a literal calls the right constructor. */ +let structs = new Map(); + +/** The declared types in scope, so a list knows whether it is an array or a growing list. */ +let localTypes = new Map(); + +/** Splits a list into fixed size chunks, which is how the big tables stay under Java's method limit. */ +const chunks = (items: T[], size: number): T[][] => { + const out: T[][] = []; + + for (let index = 0; index < items.length; index += size) out.push(items.slice(index, index + size)); + + return out; +}; + +const RUNTIME = resolve(import.meta.dirname, "../runtime/java.java"); + +/** Module level names the emitter writes verbatim. */ +let verbatim = new Set(); + +const CONTROL: Record = { + 0x08: "\\b", + 0x09: "\\t", + 0x0a: "\\n", + 0x0c: "\\f", + 0x0d: "\\r", +}; + +/** Renders a string as a Java literal; `\uXXXX` is expanded before lexing, so controls differ. */ +const lit = (value: string): string => { + let out = '"'; + + for (const char of value) { + const code = char.codePointAt(0) ?? 0; + + if (char === '"') out += String.raw`\"`; + else if (char === "\\") out += String.raw`\\`; + else if (code < 0x20) out += CONTROL[code] ?? `\\u${code.toString(16).padStart(4, "0")}`; + else if (code > 0xff_ff) { + const offset = code - 0x1_00_00; + + out += `\\u${(0xd8_00 + (offset >> 10)).toString(16).padStart(4, "0")}`; + out += `\\u${(0xdc_00 + (offset & 0x3_ff)).toString(16).padStart(4, "0")}`; + } else if (code > 0x7e) out += `\\u${code.toString(16).padStart(4, "0")}`; + else out += char; + } + + return `${out}"`; +}; + +/** Renders an IR type. */ +const type = (ty: Ty): string => { + switch (ty.k) { + case "string": + case "scalar": + case "json": + case "enum": + return "String"; + case "int": + return "long"; + case "bool": + return "boolean"; + case "void": + return "void"; + case "list": + // A list of records is built by appending, which an array cannot do. + return ty.of.k === "named" ? `java.util.List<${type(ty.of)}>` : `${type(ty.of)}[]`; + case "opt": + return type(ty.of); + case "named": + return ty.name; + } +}; + +/** The boxed form of a type, for nullable option fields. */ +const boxed = (ty: Ty): string => (ty.k === "int" ? "Long" : ty.k === "bool" ? "Boolean" : type(ty)); + +const OPS: Record = { + "+": "+", + "-": "-", + "*": "*", + "%": "%", + "==": "==", + "!=": "!=", + "<": "<", + "<=": "<=", + ">": ">", + ">=": ">=", + "&&": "&&", + "||": "||", +}; + +/** Renders an expression. */ +const expr = (node: Expr): string => { + switch (node.k) { + case "str": + return lit(node.value); + case "int": + return `${node.value}L`; + case "bool": + return String(node.value); + case "none": + return "null"; + case "ref": + return verbatim.has(node.name) ? screaming(node.name) : node.name; + case "field": + return `${expr(node.target)}.${node.name}`; + case "index": + return isGrowing(node.target) + ? `${expr(node.target)}.get((int) ${expr(node.index)})` + : `${expr(node.target)}[(int) ${expr(node.index)}]`; + case "not": + return `!${expr(node.operand)}`; + case "bin": + if (node.op === "==" && node.ty?.k === "string") + return `${expr(node.left)}.equals(${expr(node.right)})`; + + return `(${expr(node.left)} ${OPS[node.op]} ${expr(node.right)})`; + case "cond": + return `(${expr(node.test)} ? ${expr(node.whenTrue)} : ${expr(node.whenFalse)})`; + case "listOf": + if (node.of.k === "named") + return `new java.util.ArrayList<${type(node.of)}>(java.util.List.of(${node.items + .map((item) => expr(item)) + .join(", ")}))`; + + return `{${node.items.map((item) => expr(item)).join(", ")}}`; + case "struct": { + const declared = structs.get(node.name); + const order = declared?.fields.map((field) => field.name) ?? node.fields.map((f) => f.name); + + return `new ${node.name}(${order + .map((name) => expr(node.fields.find((field) => field.name === name)?.value ?? { k: "none" })) + .join(", ")})`; + } + case "optionField": + return `${node.target}${pascal(node.field)}`; + case "call": + return call(node); + default: + throw new Error(`java: unsupported expression ${node.k}`); + } +}; + +/** Whether an expression is a growing list rather than an array. */ +const isGrowing = (node: Expr): boolean => { + if (node.k !== "ref") return false; + + const ty = localTypes.get(node.name); + + return ty !== undefined && ty.k === "list" && ty.of.k === "named"; +}; + +/** Renders a call. */ +const call = (node: Extract): string => { + const args = node.args.map((argument) => expr(argument)); + + if (node.callee.k === "user") return `${node.callee.name}(${args.join(", ")})`; + + switch (node.callee.name) { + case "len": + return `(long) ${args[0]}.length()`; + case "listLen": + return isGrowing(node.args[0]) ? `(long) ${args[0]}.size()` : `(long) ${args[0]}.length`; + case "codeAt": + return `Runtime.codeAt(${args[0]}, ${args[1]})`; + case "slice": + return `Runtime.slice(${args[0]}, ${args[1]}, ${args[2]})`; + case "upper": + return `${args[0]}.toUpperCase(java.util.Locale.ROOT)`; + case "trim": + return `Runtime.jsTrim(${args[0]})`; + case "padStart": + return `Runtime.padStart(${args[0]}, ${args[1]}, ${args[2]})`; + case "repeat": + return `Runtime.repeat(${args[0]}, ${args[1]})`; + case "classHas": + return `Runtime.classHas(${args[0]}, ${args[1]})`; + case "keepClass": + return `Runtime.keepClass(${args[0]}, ${args[1]})`; + case "patternTest": + return `Runtime.patternTest(${args[0]}, ${args[1]})`; + case "asString": + // Java's types already guarantee a string at the boundary. + return args[0]; + case "isTruthy": + return args[0]; + case "listPush": + return `${args[0]}.add(${args[1]})`; + case "unwrap": + // Java has no separate optional value to open; a reference is already nullable. + return args[0]; + case "dataAll": + return `Runtime.dataAll(${args[0]})`; + case "dataRows": + return `Runtime.dataRows(${args[0]}, ${args[1]})`; + default: + throw new Error(`java: unsupported runtime call ${node.callee.name}`); + } +}; + +/** Renders a statement list. */ +const block = (body: Stmt[], indent: string): string => + body + .map((statement) => stmt(statement, indent)) + .filter((line) => line !== "") + .join("\n"); + +/** Renders one statement. */ +const stmt = (node: Stmt, indent: string): string => { + switch (node.k) { + case "let": + localTypes.set(node.name, node.ty); + + return `${indent}${type(node.ty)} ${node.name} = ${expr(node.value)};`; + case "assign": + return `${indent}${node.name} = ${expr(node.value)};`; + case "if": { + const otherwise = + node.otherwise.length === 0 ? "" : ` else {\n${block(node.otherwise, `${indent} `)}\n${indent}}`; + + return `${indent}if (${expr(node.test)}) {\n${block(node.then, `${indent} `)}\n${indent}}${otherwise}`; + } + case "return": + return node.value === undefined ? `${indent}return;` : `${indent}return ${expr(node.value)};`; + case "forRange": + return `${indent}for (long ${node.name} = ${expr(node.from)}; ${node.name} < ${expr(node.until)}; ${node.name}++) {\n${block(node.body, `${indent} `)}\n${indent}}`; + case "forOf": + return `${indent}for (var ${node.name} : ${expr(node.iterable)}) {\n${block(node.body, `${indent} `)}\n${indent}}`; + case "expr": { + const value = node.value; + + if (value.k === "call" && value.callee.k === "std" && value.callee.name === "boundaryGuard") { + const [subject, , fallback] = value.args; + const name = subject.k === "ref" ? subject.name : ""; + + // Java has no `typeof`, but it does have null, and a null argument would throw. + return `${indent}if (${name} == null) {\n${indent} return ${expr(fallback)};\n${indent}}`; + } + + return `${indent}${expr(value)};`; + } + default: + throw new Error(`java: unsupported statement ${node.k}`); + } +}; + +/** Renders a character class table entry. */ +const charClass = (entry: CharClass): string => + ` private static final int[][] ${screaming(entry.name)} = {${entry.ranges.map(([from, to]) => `{0x${from.toString(16)}, 0x${to.toString(16)}}`).join(", ")}};`; + +/** Renders a compiled pattern table entry. */ +const pattern = (entry: PatternDecl): string => + ` private static final Runtime.PatternStep[] ${screaming(entry.name)} = {\n${entry.steps + .map( + (step) => + ` new Runtime.PatternStep(${screaming(step.charClass)}, ${step.min}, ${step.max}, ${step.capture}),`, + ) + .join("\n")}\n };`; + +/** Renders an options record. */ +const struct = (entry: StructDecl): string => { + const fields = entry.fields + .map( + (field) => + `${field.doc === "" ? "" : ` /** ${field.doc} */\n`} public ${entry.isOptions ? boxed(field.ty) : type(field.ty)} ${field.name};`, + ) + .join("\n\n"); + // An options record is filled in field by field; a value record is built in one go. + const constructor = entry.isOptions + ? "" + : `\n\n public ${entry.name}(${entry.fields + .map((field) => `${type(field.ty)} ${field.name}`) + .join(", ")}) {\n${entry.fields + .map((field) => ` this.${field.name} = ${field.name};`) + .join("\n")}\n }`; + + return `/** ${entry.doc} */ +public final class ${entry.name} { +${fields}${constructor} +}`; +}; + +/** Renders a dataset as the tables the runtime materialises, chunked to stay under Java's + * 64 KiB per method limit. */ +const data = (entry: DataDecl): string => { + const name = entry.name.toLowerCase(); + const rowChunks = chunks( + entry.rows.map( + (row, index) => ` rows[${index}] = new String[] {${row.map((cell) => lit(cell)).join(", ")}};`, + ), + 200, + ); + const orderChunks = chunks( + entry.fullOrder.map((value, index) => ` order[${index}] = ${value};`), + 500, + ); + const keys = Object.keys(entry.groups); + const groupChunks = chunks( + keys.map( + (key, index) => ` groups[${index}] = new int[] {${entry.groups[key].join(", ")}};`, + ), + 5, + ); + + return ` /** ${entry.doc} */ + private static final Runtime.Dataset ${screaming(entry.name)} = new Runtime.Dataset( + ${name}Rows(), new String[] {${keys.map((key) => lit(key)).join(", ")}}, ${name}Groups(), ${name}Order()); + + private static String[][] ${name}Rows() { + String[][] rows = new String[${entry.rows.length}][]; +${rowChunks.map((_, index) => ` ${name}Rows${index}(rows);`).join("\n")} + return rows; + } + +${rowChunks + .map( + (chunk, index) => + ` private static void ${name}Rows${index}(String[][] rows) {\n${chunk.join("\n")}\n }`, + ) + .join("\n\n")} + + private static int[][] ${name}Groups() { + int[][] groups = new int[${keys.length}][]; +${groupChunks.map((_, index) => ` ${name}Groups${index}(groups);`).join("\n")} + return groups; + } + +${groupChunks + .map( + (chunk, index) => + ` private static void ${name}Groups${index}(int[][] groups) {\n${chunk.join("\n")}\n }`, + ) + .join("\n\n")} + + private static int[] ${name}Order() { + int[] order = new int[${entry.fullOrder.length}]; +${orderChunks.map((_, index) => ` ${name}Order${index}(order);`).join("\n")} + return order; + } + +${orderChunks + .map( + (chunk, index) => + ` private static void ${name}Order${index}(int[] order) {\n${chunk.join("\n")}\n }`, + ) + .join("\n\n")}`; +}; + +/** Renders one function. */ +const func = (entry: FuncDecl): string => { + localTypes = new Map(entry.params.map((param) => [param.name, param.ty])); + + const params = entry.params + .map((param) => `${type(param.ty.k === "opt" ? param.ty.of : param.ty)} ${param.name}`) + .join(", "); + const prologue = optionReads(entry) + .map((read) => { + const local = `${read.target}${pascal(read.field)}`; + const fallback = read.expr.k === "optionField" ? expr(read.expr.fallback) : "null"; + const declared = read.expr.k === "optionField" && read.expr.ty.k === "bool" ? "boolean" : "long"; + + return ` ${declared} ${local} = ${fallback};\n if (${read.target} != null && ${read.target}.${read.field} != null) {\n ${local} = ${read.target}.${read.field};\n }`; + }) + .join("\n"); + const doc = prose(entry.doc); + const comment = + doc === "" + ? "" + : ` /**\n${doc + .split("\n") + .map((line) => ` * ${line}`.trimEnd()) + .join("\n")}\n */\n`; + + return `${comment} public static ${type(entry.ret)} ${entry.name}(${params}) { +${prologue === "" ? "" : `${prologue}\n`}${block(entry.body, " ")} + }`; +}; + +/** + * Emits the Java target of one module. + * + * @param {Module} module - The compiled module. + * @returns {Record} The files, by path. + */ +export const emit = (module: Module): Record => { + structs = new Map(module.structs.map((entry) => [entry.name, entry])); + verbatim = new Set([ + ...module.charClasses.map((entry) => entry.name), + ...module.patterns.map((entry) => entry.name), + ...module.constants.map((entry) => entry.name), + ...module.data.map((entry) => entry.name), + ]); + + const className = pascal(module.name); + const constants = module.constants + .map((entry) => + entry.ty.k === "list" + ? ` private static final long[] ${screaming(entry.name)} = ${expr(entry.expr)};` + : ` private static final String ${screaming(entry.name)} = ${expr(entry.expr)};`, + ) + .join("\n"); + + const files: Record = { + "Runtime.java": readFileSync(RUNTIME, "utf8"), + [`${className}.java`]: `// Code generated from spec/bridge/source/${module.name}.ts. DO NOT EDIT. + +/** ${module.doc} */ +public final class ${className} { + private ${className}() {} + +${module.charClasses.map((entry) => charClass(entry)).join("\n")} + +${module.patterns.map((entry) => pattern(entry)).join("\n\n")} + +${constants} + +${module.data.map((entry) => data(entry)).join("\n\n")} + +${module.functions.map((entry) => func(entry)).join("\n\n")} +} +`, + }; + + for (const entry of module.structs) files[`${entry.name}.java`] = `${struct(entry)}\n`; + + return files; +}; diff --git a/spec/bridge/compiler/targets/python.ts b/spec/bridge/compiler/targets/python.ts new file mode 100644 index 000000000..8472a4bba --- /dev/null +++ b/spec/bridge/compiler/targets/python.ts @@ -0,0 +1,362 @@ +/** + * The Python emitter. + * + * Snake case names, dataclasses for the options records, and the option fields hoisted into + * locals by the prologue so the body reads like handwritten Python. + */ +import { readFileSync } from "node:fs"; +import { resolve } from "node:path"; +import type { + CharClass, + DataDecl, + Expr, + FuncDecl, + Module, + PatternDecl, + Stmt, + StructDecl, + Ty, +} from "../ir.ts"; +import { optionReads, prose, snake } from "../kit.ts"; + +/** Module level names the emitter writes verbatim: classes, patterns and constants. */ +let verbatim = new Set(); + +const RUNTIME = resolve(import.meta.dirname, "../runtime/python.py"); + +/** Renders a string as a Python literal. */ +const lit = (value: string): string => { + let out = '"'; + + for (const char of value) { + const code = char.codePointAt(0) ?? 0; + + if (char === '"') out += String.raw`\"`; + else if (char === "\\") out += String.raw`\\`; + else if (code < 0x20 || code > 0x7e) out += `\\U${code.toString(16).padStart(8, "0")}`; + else out += char; + } + + return `${out}"`; +}; + +/** Renders an IR type as a Python annotation. */ +const type = (ty: Ty): string => { + switch (ty.k) { + case "string": + return "str"; + case "int": + return "int"; + case "bool": + return "bool"; + case "void": + return "None"; + case "json": + case "scalar": + return "Any"; + case "enum": + // A closed set of strings is still a string at run time; the compiler is the checker. + return "str"; + case "list": + return `List[${type(ty.of)}]`; + case "opt": + return `Optional[${type(ty.of)}]`; + case "named": + return ty.name; + } +}; + +const OPS: Record = { + "+": "+", + "-": "-", + "*": "*", + "%": "%", + "==": "==", + "!=": "!=", + "<": "<", + "<=": "<=", + ">": ">", + ">=": ">=", + "&&": "and", + "||": "or", +}; + +/** Renders an expression. */ +const expr = (node: Expr): string => { + switch (node.k) { + case "str": + return lit(node.value); + case "int": + return String(node.value); + case "bool": + return node.value ? "True" : "False"; + case "none": + return "None"; + case "ref": + return verbatim.has(node.name) ? node.name : snake(node.name); + case "field": + return `${expr(node.target)}.${snake(node.name)}`; + case "index": + return `${expr(node.target)}[${expr(node.index)}]`; + case "not": + return `not ${expr(node.operand)}`; + case "bin": { + // `x == None` works but reads wrong; identity is what the comparison means. + if (node.right.k === "none" && (node.op === "==" || node.op === "!=")) + return `(${expr(node.left)} is ${node.op === "!=" ? "not " : ""}None)`; + + return `(${expr(node.left)} ${OPS[node.op]} ${expr(node.right)})`; + } + case "cond": + return `(${expr(node.whenTrue)} if ${expr(node.test)} else ${expr(node.whenFalse)})`; + case "listOf": + return `[${node.items.map((item) => expr(item)).join(", ")}]`; + case "struct": + return `${node.name}(${node.fields.map((field) => `${snake(field.name)}=${expr(field.value)}`).join(", ")})`; + case "optionField": + // The prologue binds every option read to a local of this name. + return `${snake(node.target)}_${snake(node.field)}`; + case "call": + return call(node); + default: + throw new Error(`python: unsupported expression ${node.k}`); + } +}; + +/** Renders a call. */ +const call = (node: Extract): string => { + const args = node.args.map((argument) => expr(argument)); + + if (node.callee.k === "user") return `${snake(node.callee.name)}(${args.join(", ")})`; + + switch (node.callee.name) { + case "len": + case "listLen": + return `len(${args[0]})`; + case "codeAt": + return `code_at(${args[0]}, ${args[1]})`; + case "slice": + return `${args[0]}[${args[1]}:${args[2]}]`; + case "upper": + return `${args[0]}.upper()`; + case "trim": + return `js_trim(${args[0]})`; + case "padStart": + return `pad_start(${args[0]}, ${args[1]}, ${args[2]})`; + case "repeat": + return `(${args[0]} * ${args[1]})`; + case "classHas": + return `class_has(${args[0]}, ${args[1]})`; + case "keepClass": + return `keep_class(${args[0]}, ${args[1]})`; + case "patternTest": + return `pattern_test(${args[0]}, ${args[1]})`; + case "asString": + return `as_string(${args[0]})`; + case "isTruthy": + return `is_truthy(${args[0]})`; + case "listPush": + return `${args[0]}.append(${args[1]})`; + case "unwrap": + // Python has no separate optional value to open. + return args[0]; + case "dataAll": + return `data_all(${args[0]})`; + case "dataRows": + return `data_rows(${args[0]}, ${args[1]})`; + default: + throw new Error(`python: unsupported runtime call ${node.callee.name}`); + } +}; + +/** Renders a statement list. */ +const block = (body: Stmt[], indent: string): string => { + const lines = body.map((statement) => stmt(statement, indent)).filter((line) => line !== ""); + + return lines.length === 0 ? `${indent}pass` : lines.join("\n"); +}; + +/** Renders one statement. */ +const stmt = (node: Stmt, indent: string): string => { + switch (node.k) { + case "let": + case "assign": + return `${indent}${snake(node.k === "let" ? node.name : node.name)} = ${expr(node.value)}`; + case "if": { + const otherwise = + node.otherwise.length === 0 ? "" : `\n${indent}else:\n${block(node.otherwise, `${indent} `)}`; + + return `${indent}if ${expr(node.test)}:\n${block(node.then, `${indent} `)}${otherwise}`; + } + case "return": + return node.value === undefined ? `${indent}return` : `${indent}return ${expr(node.value)}`; + case "forRange": + return `${indent}for ${snake(node.name)} in range(${expr(node.from)}, ${expr(node.until)}):\n${block(node.body, `${indent} `)}`; + case "forOf": + return `${indent}for ${snake(node.name)} in ${expr(node.iterable)}:\n${block(node.body, `${indent} `)}`; + case "expr": { + const value = node.value; + + if (value.k === "call" && value.callee.k === "std" && value.callee.name === "boundaryGuard") { + const [subject, kind, fallback] = value.args; + const name = subject.k === "ref" ? snake(subject.name) : ""; + const test = + kind.k === "str" && kind.value === "string" + ? `not isinstance(${name}, str)` + : `${name} is None`; + + return `${indent}if ${test}:\n${indent} return ${expr(fallback)}`; + } + + return `${indent}${expr(value)}`; + } + default: + throw new Error(`python: unsupported statement ${node.k}`); + } +}; + +/** Renders a character class table entry. */ +const charClass = (entry: CharClass): string => + `${entry.name}: CharClass = (${entry.ranges.map(([from, to]) => `(0x${from.toString(16)}, 0x${to.toString(16)})`).join(", ")},)`; + +/** Renders a compiled pattern table entry. */ +const pattern = (entry: PatternDecl): string => + `${entry.name} = (\n${entry.steps + .map( + (step) => + ` PatternStep(${step.charClass}, ${step.min}, ${step.max}, ${step.capture ? "True" : "False"}),`, + ) + .join("\n")}\n)`; + +/** Renders a dataset as the table the runtime materialises. */ +const data = (entry: DataDecl): string => { + const rows = entry.rows + .map((row) => ` [${row.map((cell) => lit(cell)).join(", ")}],`) + .join("\n"); + const groups = Object.entries(entry.groups) + .map(([key, indexes]) => ` (${lit(key)}, [${indexes.join(", ")}]),`) + .join("\n"); + + return `# ${entry.doc} +${entry.name} = make_dataset( + [ +${rows} + ], + [ +${groups} + ], + [${entry.fullOrder.join(", ")}], +)`; +}; + +/** Renders an options record as a dataclass. */ +const struct = (entry: StructDecl): string => { + const fields = entry.fields + .map((field) => { + const declared = entry.isOptions + ? `Optional[${type(field.ty)}] = None` + : type(field.ty); + + return `${field.doc === "" ? "" : ` # ${field.doc}\n`} ${snake(field.name)}: ${declared}`; + }) + .join("\n"); + + return `@dataclass +class ${entry.name}: + """${entry.doc === "" ? entry.name : entry.doc}""" + +${fields}`; +}; + +/** Renders one function. */ +const func = (entry: FuncDecl): string => { + const params = entry.params + .map((param) => { + if (param.optional) + return `${snake(param.name)}: ${type(param.ty.k === "opt" ? param.ty : { k: "opt", of: param.ty })} = None`; + + // A public entry point takes whatever the caller hands it and guards at the boundary. + const annotation = entry.exported && param.ty.k === "string" ? "Any" : type(param.ty); + + return `${snake(param.name)}: ${annotation}`; + }) + .join(", "); + + const prologue = optionReads(entry) + .map((read) => { + const local = `${snake(read.target)}_${snake(read.field)}`; + const fallback = read.expr.k === "optionField" ? expr(read.expr.fallback) : "None"; + + return ` ${local} = ${fallback}\n if ${snake(read.target)} is not None and ${snake(read.target)}.${snake(read.field)} is not None:\n ${local} = ${snake(read.target)}.${snake(read.field)}`; + }) + .join("\n"); + + const text = prose(entry.doc); + const doc = text === "" ? "" : ` """${text.split("\n").join("\n ")}\n """\n`; + + return `def ${snake(entry.name)}(${params}) -> ${type(entry.ret)}: +${doc}${prologue === "" ? "" : `${prologue}\n`}${block(entry.body, " ")}`; +}; + +/** + * Emits the Python target of one module. + * + * @param {Module} module - The compiled module. + * @returns {Record} The files, by path. + */ +export const emit = (module: Module, modules: Module[] = [module]): Record => { + verbatim = new Set([ + ...module.charClasses.map((entry) => entry.name), + ...module.patterns.map((entry) => entry.name), + ...module.constants.map((entry) => entry.name), + ...module.data.map((entry) => entry.name), + ]); + + const constants = module.constants + .map((entry) => `${entry.name} = ${expr(entry.expr)}`) + .join("\n"); + + return { + "brutils_bridge/runtime.py": readFileSync(RUNTIME, "utf8"), + "brutils_bridge/__init__.py": `"""Generated Brazilian Utils."""\n\n${modules + .map((entry) => `from .${entry.name} import * # noqa: F401,F403`) + .join("\n")}\n`, + [`brutils_bridge/${module.name}.py`]: `# Code generated from spec/bridge/source/${module.name}.ts. DO NOT EDIT. +"""${module.doc}""" + +from dataclasses import dataclass +from typing import Any, List, Optional + +from .runtime import ( + CharClass, + PatternStep, + as_string, + class_has, + code_at, + data_all, + data_rows, + is_truthy, + js_trim, + keep_class, + make_dataset, + pad_start, + pattern_test, +) + +${module.charClasses.map((entry) => charClass(entry)).join("\n")} + +${module.patterns.map((entry) => pattern(entry)).join("\n\n")} + +${constants} + + +${module.structs.map((entry) => struct(entry)).join("\n\n\n")} + + +${module.data.map((entry) => data(entry)).join("\n\n")} + + +${module.functions.map((entry) => func(entry)).join("\n\n\n")} +`, + }; +}; diff --git a/spec/bridge/compiler/targets/ruby.ts b/spec/bridge/compiler/targets/ruby.ts new file mode 100644 index 000000000..ff453850d --- /dev/null +++ b/spec/bridge/compiler/targets/ruby.ts @@ -0,0 +1,302 @@ +/** + * The Ruby emitter. + * + * Module functions under `BrazilianUtilsBridge`, options as a keyword initialised Struct, and + * the option reads hoisted into locals by the prologue. + */ +import { readFileSync } from "node:fs"; +import { resolve } from "node:path"; +import type { + CharClass, + DataDecl, + Expr, + FuncDecl, + Module, + PatternDecl, + Stmt, + StructDecl, +} from "../ir.ts"; +import { optionReads, prose, screaming, snake } from "../kit.ts"; + +const RUNTIME = resolve(import.meta.dirname, "../runtime/ruby.rb"); +const NAMESPACE = "BrazilianUtilsBridge"; + +/** Module level names the emitter writes verbatim. */ +let verbatim = new Set(); + +/** Renders a string as a Ruby literal. */ +const lit = (value: string): string => { + let out = '"'; + + for (const char of value) { + const code = char.codePointAt(0) ?? 0; + + if (char === '"') out += String.raw`\"`; + else if (char === "\\") out += String.raw`\\`; + else if (char === "#") out += String.raw`\#`; + else if (code < 0x20 || code > 0x7e) out += `\\u{${code.toString(16)}}`; + else out += char; + } + + return `${out}"`; +}; + +const OPS: Record = { + "+": "+", + "-": "-", + "*": "*", + "%": "%", + "==": "==", + "!=": "!=", + "<": "<", + "<=": "<=", + ">": ">", + ">=": ">=", + "&&": "&&", + "||": "||", +}; + +/** Renders an expression. */ +const expr = (node: Expr): string => { + switch (node.k) { + case "str": + return lit(node.value); + case "int": + return String(node.value); + case "bool": + return String(node.value); + case "none": + return "nil"; + case "ref": + return verbatim.has(node.name) ? screaming(node.name) : snake(node.name); + case "field": + return `${expr(node.target)}.${snake(node.name)}`; + case "index": + return `${expr(node.target)}[${expr(node.index)}]`; + case "not": + return `!${expr(node.operand)}`; + case "bin": + // `x == nil` works but `nil?` is what a Ruby reader expects. + if (node.right.k === "none" && (node.op === "==" || node.op === "!=")) + return `${node.op === "!=" ? "!" : ""}${expr(node.left)}.nil?`; + + return `(${expr(node.left)} ${OPS[node.op]} ${expr(node.right)})`; + case "cond": + return `(${expr(node.test)} ? ${expr(node.whenTrue)} : ${expr(node.whenFalse)})`; + case "listOf": + return `[${node.items.map((item) => expr(item)).join(", ")}]`; + case "struct": + return `${node.name}.new(${node.fields + .map((field) => `${snake(field.name)}: ${expr(field.value)}`) + .join(", ")})`; + case "optionField": + return `${snake(node.target)}_${snake(node.field)}`; + case "call": + return call(node); + default: + throw new Error(`ruby: unsupported expression ${node.k}`); + } +}; + +/** Renders a call. */ +const call = (node: Extract): string => { + const args = node.args.map((argument) => expr(argument)); + + if (node.callee.k === "user") return `${snake(node.callee.name)}(${args.join(", ")})`; + + switch (node.callee.name) { + case "len": + case "listLen": + return `${args[0]}.length`; + case "codeAt": + return `Runtime.code_at(${args[0]}, ${args[1]})`; + case "slice": + return `${args[0]}[${args[1]}...${args[2]}]`; + case "upper": + return `${args[0]}.upcase`; + case "trim": + return `Runtime.js_trim(${args[0]})`; + case "padStart": + return `Runtime.pad_start(${args[0]}, ${args[1]}, ${args[2]})`; + case "repeat": + return `(${args[0]} * ${args[1]})`; + case "classHas": + return `Runtime.class_has(${args[0]}, ${args[1]})`; + case "keepClass": + return `Runtime.keep_class(${args[0]}, ${args[1]})`; + case "patternTest": + return `Runtime.pattern_test(${args[0]}, ${args[1]})`; + case "asString": + return `Runtime.as_string(${args[0]})`; + case "isTruthy": + return `Runtime.is_truthy(${args[0]})`; + case "listPush": + return `${args[0]}.push(${args[1]})`; + case "unwrap": + // Ruby has no separate optional value to open. + return args[0]; + case "dataAll": + return `Runtime.data_all(${args[0]})`; + case "dataRows": + return `Runtime.data_rows(${args[0]}, ${args[1]})`; + default: + throw new Error(`ruby: unsupported runtime call ${node.callee.name}`); + } +}; + +/** Renders a statement list. */ +const block = (body: Stmt[], indent: string): string => + body + .map((statement) => stmt(statement, indent)) + .filter((line) => line !== "") + .join("\n"); + +/** Renders one statement. */ +const stmt = (node: Stmt, indent: string): string => { + switch (node.k) { + case "let": + case "assign": + return `${indent}${snake(node.name)} = ${expr(node.value)}`; + case "if": { + const otherwise = + node.otherwise.length === 0 ? "" : `\n${indent}else\n${block(node.otherwise, `${indent} `)}`; + + return `${indent}if ${expr(node.test)}\n${block(node.then, `${indent} `)}${otherwise}\n${indent}end`; + } + case "return": + return node.value === undefined ? `${indent}return` : `${indent}return ${expr(node.value)}`; + case "forRange": + return `${indent}(${expr(node.from)}...${expr(node.until)}).each do |${snake(node.name)}|\n${block(node.body, `${indent} `)}\n${indent}end`; + case "forOf": + return `${indent}${expr(node.iterable)}.each do |${snake(node.name)}|\n${block(node.body, `${indent} `)}\n${indent}end`; + case "expr": { + const value = node.value; + + if (value.k === "call" && value.callee.k === "std" && value.callee.name === "boundaryGuard") { + const [subject, kind, fallback] = value.args; + const name = subject.k === "ref" ? snake(subject.name) : ""; + const test = + kind.k === "str" && kind.value === "string" + ? `!${name}.is_a?(String)` + : `${name}.nil?`; + + return `${indent}return ${expr(fallback)} if ${test}`; + } + + return `${indent}${expr(value)}`; + } + default: + throw new Error(`ruby: unsupported statement ${node.k}`); + } +}; + +/** Renders a character class table entry. */ +const charClass = (entry: CharClass): string => + ` ${screaming(entry.name)} = [${entry.ranges.map(([from, to]) => `[0x${from.toString(16)}, 0x${to.toString(16)}]`).join(", ")}].freeze`; + +/** Renders a compiled pattern table entry. */ +const pattern = (entry: PatternDecl): string => + ` ${screaming(entry.name)} = [\n${entry.steps + .map( + (step) => + ` Runtime::PatternStep.new(${screaming(step.charClass)}, ${step.min}, ${step.max}, ${step.capture}),`, + ) + .join("\n")}\n ].freeze`; + +/** Renders an options record. */ +const struct = (entry: StructDecl): string => + ` # ${entry.doc}\n ${entry.name} = Struct.new(${entry.fields + .map((field) => `:${snake(field.name)}`) + .join(", ")}, keyword_init: true)`; + +/** Renders a dataset as the table the runtime materialises. */ +const data = (entry: DataDecl): string => { + const rows = entry.rows + .map((row) => ` [${row.map((cell) => lit(cell)).join(", ")}],`) + .join("\n"); + const groups = Object.entries(entry.groups) + .map(([key, indexes]) => ` [${lit(key)}, [${indexes.join(", ")}]],`) + .join("\n"); + + return ` # ${entry.doc} + ${screaming(entry.name)} = Runtime.make_dataset( + [ +${rows} + ], + [ +${groups} + ], + [${entry.fullOrder.join(", ")}] + )`; +}; + +/** Renders one function. */ +const func = (entry: FuncDecl): string => { + const params = entry.params + .map((param) => (param.optional ? `${snake(param.name)} = nil` : snake(param.name))) + .join(", "); + const prologue = optionReads(entry) + .map((read) => { + const local = `${snake(read.target)}_${snake(read.field)}`; + const fallback = read.expr.k === "optionField" ? expr(read.expr.fallback) : "nil"; + const target = snake(read.target); + + return ` ${local} = ${fallback}\n ${local} = ${target}.${snake(read.field)} unless ${target}.nil? || ${target}.${snake(read.field)}.nil?`; + }) + .join("\n"); + const doc = prose(entry.doc) + .split("\n") + .map((line) => ` # ${line}`.trimEnd()) + .join("\n"); + + return `${doc === "" ? "" : `${doc}\n`} def self.${snake(entry.name)}(${params}) +${prologue === "" ? "" : `${prologue}\n`}${block(entry.body, " ")} + end`; +}; + +/** + * Emits the Ruby target of one module. + * + * @param {Module} module - The compiled module. + * @returns {Record} The files, by path. + */ +export const emit = (module: Module): Record => { + verbatim = new Set([ + ...module.charClasses.map((entry) => entry.name), + ...module.patterns.map((entry) => entry.name), + ...module.constants.map((entry) => entry.name), + ...module.data.map((entry) => entry.name), + ]); + + const moduleName = `${module.name.charAt(0).toUpperCase()}${module.name.slice(1)}`; + const constants = module.constants + .map((entry) => ` ${screaming(entry.name)} = ${expr(entry.expr)}.freeze`) + .join("\n"); + + return { + "lib/brazilian_utils_bridge/runtime.rb": readFileSync(RUNTIME, "utf8"), + [`lib/brazilian_utils_bridge/${module.name}.rb`]: `# frozen_string_literal: true + +# Code generated from spec/bridge/source/${module.name}.ts. DO NOT EDIT. + +require_relative 'runtime' + +module ${NAMESPACE} + # ${module.doc} + module ${moduleName} +${module.charClasses.map((entry) => charClass(entry)).join("\n")} + +${module.patterns.map((entry) => pattern(entry)).join("\n\n")} + +${constants} + +${module.structs.map((entry) => struct(entry)).join("\n\n")} + +${module.data.map((entry) => data(entry)).join("\n\n")} + +${module.functions.map((entry) => func(entry)).join("\n\n")} + end +end +`, + }; +}; diff --git a/spec/bridge/compiler/targets/rust.ts b/spec/bridge/compiler/targets/rust.ts new file mode 100644 index 000000000..c3c9a62fc --- /dev/null +++ b/spec/bridge/compiler/targets/rust.ts @@ -0,0 +1,475 @@ +/** + * The Rust emitter. + * + * `&str` in, owned `String` out, options behind an `Option<&T>`, and the option reads hoisted + * into locals by the prologue so the body has no nested matches. + */ +import { readFileSync } from "node:fs"; +import { resolve } from "node:path"; +import type { + CharClass, + DataDecl, + Expr, + FuncDecl, + Module, + Param, + PatternDecl, + Stmt, + StructDecl, + Ty, +} from "../ir.ts"; +import { optionReads, prose, pushTargets, screaming, snake } from "../kit.ts"; + +/** The record types of the module being emitted, so a struct literal owns its fields. */ +let structs = new Map(); + +/** The datasets of the module, which are functions rather than statics in Rust. */ +let datasets = new Set(); + +const RUNTIME = resolve(import.meta.dirname, "../runtime/rust.rs"); + +/** Module level names the emitter writes verbatim. */ +let verbatim = new Set(); + +/** Parameter lists of the module's own functions, so calls borrow exactly where they must. */ +let signatures = new Map(); + +/** Renders a string as a Rust literal. */ +const lit = (value: string): string => { + let out = '"'; + + for (const char of value) { + const code = char.codePointAt(0) ?? 0; + + if (char === '"') out += String.raw`\"`; + else if (char === "\\") out += String.raw`\\`; + else if (code < 0x20 || code > 0x7e) out += `\\u{${code.toString(16)}}`; + else out += char; + } + + return `${out}"`; +}; + +/** Renders an IR type. */ +const type = (ty: Ty): string => { + switch (ty.k) { + case "string": + case "scalar": + case "enum": + return "String"; + case "int": + return "i64"; + case "bool": + return "bool"; + case "void": + return "()"; + case "json": + return "String"; + case "list": + // A dataset row is borrowed from the table rather than rebuilt for every reader. + if (ty.of.k === "list" && ty.of.of.k === "string") return "Vec"; + + return `Vec<${type(ty.of)}>`; + case "opt": + return `Option<${type(ty.of)}>`; + case "named": + return ty.name; + } +}; + +const OPS: Record = { + "+": "+", + "-": "-", + "*": "*", + "%": "%", + "==": "==", + "!=": "!=", + "<": "<", + "<=": "<=", + ">": ">", + ">=": ">=", + "&&": "&&", + "||": "||", +}; + +/** Renders an expression, borrowing where the runtime takes a `&str`. */ +const asStr = (node: Expr): string => { + const rendered = expr(node); + + if (node.k === "str") return rendered; + + return `&${rendered}`; +}; + +/** Renders an expression. */ +const expr = (node: Expr): string => { + switch (node.k) { + case "str": + return lit(node.value); + case "int": + return String(node.value); + case "bool": + return String(node.value); + case "none": + return "None"; + case "ref": + if (datasets.has(node.name)) return `${snake(node.name)}_table()`; + + return verbatim.has(node.name) ? screaming(node.name) : snake(node.name); + case "field": + return `${expr(node.target)}.${snake(node.name)}`; + case "index": + return `${expr(node.target)}[${expr(node.index)} as usize]`; + case "not": + return `!${expr(node.operand)}`; + case "bin": { + if (node.right.k === "none" && (node.op === "==" || node.op === "!=")) + return `${expr(node.left)}.${node.op === "!=" ? "is_some" : "is_none"}()`; + + if (node.op === "+" && node.ty?.k === "string") + return `format!("{}{}", ${expr(node.left)}, ${expr(node.right)})`; + + return `(${expr(node.left)} ${OPS[node.op]} ${expr(node.right)})`; + } + case "cond": + return `(if ${expr(node.test)} { ${expr(node.whenTrue)} } else { ${expr(node.whenFalse)} })`; + case "listOf": + // A list that only ever holds literals is a fixed size array; anything else is a Vec. + if (node.of.k === "int") return `[${node.items.map((item) => expr(item)).join(", ")}]`; + + return `vec![${node.items.map((item) => expr(item)).join(", ")}]`; + case "struct": { + const declared = structs.get(node.name); + + return `${node.name} { ${node.fields + .map((field) => { + const ty = declared?.fields.find((candidate) => candidate.name === field.name)?.ty; + + return `${snake(field.name)}: ${owned(field.value, ty)}`; + }) + .join(", ")} }`; + } + case "optionField": + return `${snake(node.target)}_${snake(node.field)}`; + case "call": + return call(node); + default: + throw new Error(`rust: unsupported expression ${node.k}`); + } +}; + +/** Renders a call. */ +const call = (node: Extract): string => { + const args = node.args; + + if (node.callee.k === "user") { + const params = signatures.get(node.callee.name) ?? []; + const rendered = args.map((argument, index) => { + const ty = params[index]?.ty; + + if (ty === undefined) return expr(argument); + if (ty.k === "list" && ty.of.k === "string") return expr(argument); + if (ty.k === "string" || ty.k === "scalar" || ty.k === "enum" || ty.k === "list") + return asStr(argument); + + return expr(argument); + }); + + return `${snake(node.callee.name)}(${rendered.join(", ")})`; + } + + switch (node.callee.name) { + case "listPush": + return `${expr(args[0])}.push(${expr(args[1])})`; + case "unwrap": + return `${expr(args[0])}.unwrap()`; + case "dataAll": + return `runtime::data_all(${expr(args[0])})`; + case "dataRows": + return `runtime::data_rows(${expr(args[0])}, ${asStr(args[1])})`; + case "len": + return `runtime::len(${asStr(args[0])})`; + case "listLen": + return `(${expr(args[0])}.len() as i64)`; + case "codeAt": + return `runtime::code_at(${asStr(args[0])}, ${expr(args[1])})`; + case "slice": + return `runtime::slice(${asStr(args[0])}, ${expr(args[1])}, ${expr(args[2])})`; + case "upper": + return `runtime::upper(${asStr(args[0])})`; + case "trim": + return `runtime::js_trim(${asStr(args[0])})`; + case "padStart": + return `runtime::pad_start(${asStr(args[0])}, ${expr(args[1])}, ${asStr(args[2])})`; + case "repeat": + return `runtime::repeat(${asStr(args[0])}, ${expr(args[1])})`; + case "classHas": + return `runtime::class_has(${expr(args[0])}, ${asStr(args[1])})`; + case "keepClass": + return `runtime::keep_class(${expr(args[0])}, ${asStr(args[1])})`; + case "patternTest": + return `runtime::pattern_test(${expr(args[0])}, ${asStr(args[1])})`; + case "asString": + return `${expr(args[0])}.to_string()`; + case "isTruthy": + return expr(args[0]); + default: + throw new Error(`rust: unsupported runtime call ${node.callee.name}`); + } +}; + +/** Names that are borrowed `&str` in the current function: its string parameters and consts. */ +let borrowed = new Set(); + +/** Locals the body pushes onto, which Rust needs declared `mut`. */ +let mutated = new Set(); + +/** Local variable types of the function being rendered, so assignments can own their value. */ +let localTypes = new Map(); + +/** + * Renders an expression as an owned `String` when the target type asks for one. + * + * @param {Expr} node - The expression. + * @param {Ty} [ty] - The type the value is being stored in. + * @returns {string} The rendered expression. + */ +const owned = (node: Expr, ty?: Ty): string => { + const rendered = expr(node); + + if (ty !== undefined && ty.k !== "string" && ty.k !== "scalar" && ty.k !== "enum") return rendered; + if (node.k === "str") return `${rendered}.to_string()`; + if (node.k === "index" && (node.ty?.k === "string" || node.ty?.k === "enum")) + return `${rendered}.to_string()`; + if (node.k === "ref" && borrowed.has(node.name)) return `${rendered}.to_string()`; + + return rendered; +}; + +/** Renders a statement list. */ +const block = (body: Stmt[], indent: string): string => + body + .map((statement) => stmt(statement, indent)) + .filter((line) => line !== "") + .join("\n"); + +/** Renders one statement. */ +const stmt = (node: Stmt, indent: string): string => { + switch (node.k) { + case "let": + return `${indent}let ${node.mutable || mutated.has(node.name) ? "mut " : ""}${snake(node.name)}: ${type(node.ty)} = ${owned(node.value, node.ty)};`; + case "assign": + return `${indent}${snake(node.name)} = ${owned(node.value, localTypes.get(node.name))};`; + case "if": { + const otherwise = + node.otherwise.length === 0 ? "" : ` else {\n${block(node.otherwise, `${indent}\t`)}\n${indent}}`; + + return `${indent}if ${expr(node.test)} {\n${block(node.then, `${indent}\t`)}\n${indent}}${otherwise}`; + } + case "return": + return node.value === undefined ? `${indent}return;` : `${indent}return ${expr(node.value)};`; + case "forRange": + return `${indent}for ${snake(node.name)} in ${expr(node.from)}..${expr(node.until)} {\n${block(node.body, `${indent}\t`)}\n${indent}}`; + case "forOf": + // The loop consumes the list: nothing in the subset reads one after iterating it. + return `${indent}for ${snake(node.name)} in ${expr(node.iterable)} {\n${block(node.body, `${indent}\t`)}\n${indent}}`; + case "expr": { + const value = node.value; + + // Rust's types make the boundary guards unnecessary. + if (value.k === "call" && value.callee.k === "std" && value.callee.name === "boundaryGuard") + return ""; + + return `${indent}${expr(value)};`; + } + default: + throw new Error(`rust: unsupported statement ${node.k}`); + } +}; + +/** Renders a character class table entry. */ +const charClass = (entry: CharClass): string => + `const ${screaming(entry.name)}: runtime::CharClass = &[${entry.ranges.map(([from, to]) => `(0x${from.toString(16)}, 0x${to.toString(16)})`).join(", ")}];`; + +/** Renders a compiled pattern table entry. */ +const pattern = (entry: PatternDecl): string => + `const ${screaming(entry.name)}: &[runtime::PatternStep] = &[\n${entry.steps + .map( + (step) => + `\truntime::PatternStep { class: ${screaming(step.charClass)}, min: ${step.min}, max: ${step.max}, capture: ${step.capture} },`, + ) + .join("\n")}\n];`; + +/** Renders an options record. */ +const struct = (entry: StructDecl): string => { + const fields = entry.fields + .map((field) => { + const declared = entry.isOptions ? `Option<${type(field.ty)}>` : type(field.ty); + + return `${field.doc === "" ? "" : `\t/// ${field.doc}\n`}\tpub ${snake(field.name)}: ${declared},`; + }) + .join("\n"); + + return `/// ${entry.doc} +#[derive(Debug, Default, Clone, PartialEq, Eq)] +pub struct ${entry.name} { +${fields} +}`; +}; + +/** Renders one function. */ +const func = (entry: FuncDecl): string => { + borrowed = new Set([ + ...entry.params + .filter((param) => param.ty.k === "string" || param.ty.k === "scalar") + .map((param) => param.name), + ...[...verbatim], + ]); + localTypes = new Map(); + mutated = pushTargets(entry); + + const collect = (body: Stmt[]): void => { + for (const statement of body) { + if (statement.k === "let") localTypes.set(statement.name, statement.ty); + if (statement.k === "if") { + collect(statement.then); + collect(statement.otherwise); + } + if (statement.k === "forOf" || statement.k === "forRange") collect(statement.body); + if (statement.k === "try") { + collect(statement.body); + collect(statement.catchBody); + } + } + }; + + collect(entry.body); + + const params = entry.params + .map((param) => { + if (param.optional) { + const of = param.ty.k === "opt" ? param.ty.of : param.ty; + + return `${snake(param.name)}: Option<&${of.k === "named" ? type(of) : "str"}>`; + } + + if (param.ty.k === "string" || param.ty.k === "scalar" || param.ty.k === "enum") + return `${snake(param.name)}: &str`; + if (param.ty.k === "list") + return param.ty.of.k === "string" + ? `${snake(param.name)}: runtime::Row` + : `${snake(param.name)}: &[${type(param.ty.of)}]`; + + return `${snake(param.name)}: ${type(param.ty)}`; + }) + .join(", "); + + const prologue = optionReads(entry) + .map((read) => { + const local = `${snake(read.target)}_${snake(read.field)}`; + const fallback = read.expr.k === "optionField" ? expr(read.expr.fallback) : "None"; + + return `\tlet ${local} = match ${snake(read.target)} {\n\t\tNone => ${fallback},\n\t\tSome(value) => value.${snake(read.field)}.unwrap_or(${fallback}),\n\t};`; + }) + .join("\n"); + + const doc = prose(entry.doc) + .split("\n") + .map((line) => `/// ${line}`.trimEnd()) + .join("\n"); + + return `${doc === "" ? "" : `${doc}\n`}pub fn ${snake(entry.name)}(${params}) -> ${type(entry.ret)} { +${prologue === "" ? "" : `${prologue}\n`}${block(entry.body, "\t")} +}`; +}; + +/** Renders a dataset as the statics the runtime materialises, behind a `OnceLock`. */ +const data = (entry: DataDecl): string => { + const upper = screaming(entry.name); + const rows = entry.rows + .map((row) => `\t&[${row.map((cell) => lit(cell)).join(", ")}],`) + .join("\n"); + const groups = Object.entries(entry.groups) + .map(([key, indexes]) => `\t(${lit(key)}, &[${indexes.join(", ")}]),`) + .join("\n"); + + return `static ${upper}_ROWS: &[runtime::Row] = &[ +${rows} +]; + +static ${upper}_GROUPS: &[(&str, &[usize])] = &[ +${groups} +]; + +static ${upper}_ORDER: &[usize] = &[${entry.fullOrder.join(", ")}]; + +/// ${entry.doc} +fn ${snake(entry.name)}_table() -> &'static runtime::Dataset { +\tstatic TABLE: std::sync::OnceLock = std::sync::OnceLock::new(); + +\tTABLE.get_or_init(|| runtime::Dataset::new(${upper}_ROWS, ${upper}_GROUPS, ${upper}_ORDER)) +}`; +}; + +/** + * Emits the Rust target of one module. + * + * @param {Module} module - The compiled module. + * @returns {Record} The files, by path. + */ +export const emit = (module: Module, modules: Module[] = [module]): Record => { + signatures = new Map(module.functions.map((entry) => [entry.name, entry.params])); + structs = new Map(module.structs.map((entry) => [entry.name, entry])); + datasets = new Set(module.data.map((entry) => entry.name)); + verbatim = new Set([ + ...module.charClasses.map((entry) => entry.name), + ...module.patterns.map((entry) => entry.name), + ...module.constants.map((entry) => entry.name), + ]); + + const constants = module.constants + .map((entry) => + entry.ty.k === "list" + ? `const ${screaming(entry.name)}: [i64; ${(entry.expr as Extract).items.length}] = ${expr(entry.expr)};` + : `const ${screaming(entry.name)}: &str = ${expr(entry.expr)};`, + ) + .join("\n"); + + return { + "src/runtime.rs": readFileSync(RUNTIME, "utf8"), + "src/lib.rs": `// Code generated from spec/bridge/source. DO NOT EDIT. + +//! Generated Brazilian Utils. + +pub mod runtime; +${modules.map((entry) => `pub mod ${entry.name};`).join("\n")} +`, + "Cargo.toml": `[package] +name = "brazilian_utils_bridge" +version = "0.0.0" +edition = "2021" +publish = false + +[lib] +path = "src/lib.rs" +`, + [`src/${module.name}.rs`]: `// Code generated from spec/bridge/source/${module.name}.ts. DO NOT EDIT. + +//! ${module.doc} + +use crate::runtime; + +${module.charClasses.map((entry) => charClass(entry)).join("\n")} + +${module.patterns.map((entry) => pattern(entry)).join("\n\n")} + +${constants} + +${module.structs.map((entry) => struct(entry)).join("\n\n")} + +${module.data.map((entry) => data(entry)).join("\n\n")} + +${module.functions.map((entry) => func(entry)).join("\n\n")} +`, + }; +}; diff --git a/spec/bridge/compiler/targets/typescript.ts b/spec/bridge/compiler/targets/typescript.ts new file mode 100644 index 000000000..3df688615 --- /dev/null +++ b/spec/bridge/compiler/targets/typescript.ts @@ -0,0 +1,387 @@ +/** + * The TypeScript emitter. + * + * Its output has to drop into `src/` and pass the package's own test suite, so it follows the + * repository's conventions: arrow functions, tabs, JSDoc with the `@see` lines carried over + * from the source, and the literal option types the type level tests assert on. + */ +import { readFileSync } from "node:fs"; +import { resolve } from "node:path"; +import type { + CharClass, + DataDecl, + EnumDecl, + Expr, + FuncDecl, + Module, + PatternDecl, + Stmt, + StructDecl, + Ty, +} from "../ir.ts"; + +/** The record types of the module being emitted, for the field level casts. */ +let structs = new Map(); + +const RUNTIME = resolve(import.meta.dirname, "../runtime/typescript.ts"); + +/** + * Renders a string as a TypeScript literal. + * + * @param {string} value - The text. + * @returns {string} The literal. + */ +const lit = (value: string): string => { + let out = '"'; + + for (const char of value) { + const code = char.codePointAt(0) ?? 0; + + if (char === '"') out += String.raw`\"`; + else if (char === "\\") out += String.raw`\\`; + else if (code < 0x20 || code > 0x7e) out += `\\u{${code.toString(16)}}`; + else out += char; + } + + return `${out}"`; +}; + +/** + * Renders an IR type. + * + * @param {Ty} ty - The type. + * @returns {string} The TypeScript type. + */ +const type = (ty: Ty): string => { + switch (ty.k) { + case "string": + return "string"; + case "int": + return "number"; + case "bool": + return "boolean"; + case "void": + return "void"; + case "json": + return "unknown"; + case "scalar": + return "string | number"; + case "enum": + return ty.name; + case "list": + return `${type(ty.of)}[]`; + case "opt": + return `${type(ty.of)} | undefined`; + case "named": + return ty.name; + } +}; + +/** + * Renders an expression. + * + * @param {Expr} expr - The expression. + * @returns {string} The TypeScript expression. + */ +const expr = (expr_: Expr): string => { + switch (expr_.k) { + case "str": + return lit(expr_.value); + case "int": + return String(expr_.value); + case "bool": + return String(expr_.value); + case "none": + return "undefined"; + case "ref": + return expr_.name; + case "field": + return `${expr(expr_.target)}.${expr_.name}`; + case "index": + return `${expr(expr_.target)}[${expr(expr_.index)}]`; + case "not": + return `!${expr(expr_.operand)}`; + case "bin": + return `(${expr(expr_.left)} ${expr_.op === "==" ? "===" : expr_.op === "!=" ? "!==" : expr_.op} ${expr(expr_.right)})`; + case "cond": + return `(${expr(expr_.test)} ? ${expr(expr_.whenTrue)} : ${expr(expr_.whenFalse)})`; + case "listOf": + return `[${expr_.items.map((item) => expr(item)).join(", ")}]`; + case "struct": { + const declared = structs.get(expr_.name); + + return `{ ${expr_.fields + .map((field) => { + const ty = declared?.fields.find((candidate) => candidate.name === field.name)?.ty; + // A dataset holds plain strings; the closed set is the declaration's promise, and + // `data/build.ts` is what keeps it true. + const cast = ty?.k === "enum" && field.value.k !== "str" ? ` as ${ty.name}` : ""; + + return `${field.name}: ${expr(field.value)}${cast}`; + }) + .join(", ")} }`; + } + case "await": + return `await ${expr(expr_.value)}`; + case "optionField": + return `${expr_.target}?.${expr_.field}`; + case "call": + return call(expr_); + default: + throw new Error(`typescript: unsupported expression ${expr_.k}`); + } +}; + +/** Renders a call, mapping the runtime helpers onto TypeScript's own string methods. */ +const call = (node: Extract): string => { + const args = node.args.map((argument) => expr(argument)); + + if (node.callee.k === "user") return `${node.callee.name}(${args.join(", ")})`; + + switch (node.callee.name) { + case "len": + return `${args[0]}.length`; + case "listLen": + return `${args[0]}.length`; + case "codeAt": + return `codeAt(${args[0]}, ${args[1]})`; + case "slice": + return `${args[0]}.slice(${args[1]}, ${args[2]})`; + case "upper": + return `${args[0]}.toUpperCase()`; + case "trim": + return `${args[0]}.trim()`; + case "padStart": + return `padStart(${args[0]}, ${args[1]}, ${args[2]})`; + case "repeat": + return `${args[0]}.repeat(${args[1]})`; + case "classHas": + return `classHas(${args[0]}, ${args[1]})`; + case "keepClass": + return `keepClass(${args[0]}, ${args[1]})`; + case "patternTest": + return `patternTest(${args[0]}, ${args[1]})`; + case "asString": + return `asString(${args[0]})`; + case "isTruthy": + return `isTruthy(${args[0]})`; + case "listPush": + return `${args[0]}.push(${args[1]})`; + case "unwrap": + // TypeScript's own narrowing has already done this. + return args[0]; + case "dataAll": + return `dataAll(${args[0]})`; + case "dataRows": + return `dataRows(${args[0]}, ${args[1]})`; + default: + throw new Error(`typescript: unsupported runtime call ${node.callee.name}`); + } +}; + +/** + * Renders a statement list. + * + * @param {Stmt[]} body - The statements. + * @param {string} indent - The current indentation. + * @returns {string} The rendered block. + */ +const block = (body: Stmt[], indent: string): string => + body + .map((statement) => stmt(statement, indent)) + .filter((rendered) => rendered !== "") + .join("\n"); + +/** Renders one statement. */ +const stmt = (node: Stmt, indent: string): string => { + switch (node.k) { + case "let": { + // An empty literal says nothing about what it holds, so the declaration has to. + const annotation = + node.value.k === "listOf" && node.value.items.length === 0 ? `: ${type(node.ty)}` : ""; + + return `${indent}${node.mutable ? "let" : "const"} ${node.name}${annotation} = ${expr(node.value)};`; + } + case "assign": + return `${indent}${node.name} = ${expr(node.value)};`; + case "if": { + const otherwise = + node.otherwise.length === 0 + ? "" + : ` else {\n${block(node.otherwise, `${indent}\t`)}\n${indent}}`; + + return `${indent}if (${expr(node.test)}) {\n${block(node.then, `${indent}\t`)}\n${indent}}${otherwise}`; + } + case "return": + return node.value === undefined ? `${indent}return;` : `${indent}return ${expr(node.value)};`; + case "forRange": + return `${indent}for (let ${node.name} = ${expr(node.from)}; ${node.name} < ${expr(node.until)}; ${node.name}++) {\n${block(node.body, `${indent}\t`)}\n${indent}}`; + case "forOf": + return `${indent}for (const ${node.name} of ${expr(node.iterable)}) {\n${block(node.body, `${indent}\t`)}\n${indent}}`; + case "expr": { + const value = node.value; + + if (value.k === "call" && value.callee.k === "std" && value.callee.name === "boundaryGuard") { + const [subject, kind, fallback] = value.args; + const name = subject.k === "ref" ? subject.name : ""; + const test = + kind.k === "str" && kind.value === "string" + ? `typeof ${name} !== "string"` + : `${name} === null || ${name} === undefined`; + + return `${indent}if (${test}) {\n${indent}\treturn ${expr(fallback)};\n${indent}}`; + } + + return `${indent}${expr(value)};`; + } + default: + throw new Error(`typescript: unsupported statement ${node.k}`); + } +}; + +/** Renders a character class table entry. */ +const charClass = (entry: CharClass): string => + `const ${entry.name}: CharClass = [${entry.ranges.map(([from, to]) => `[0x${from.toString(16)}, 0x${to.toString(16)}]`).join(", ")}];`; + +/** Renders a compiled pattern table entry. */ +const pattern = (entry: PatternDecl): string => + `const ${entry.name}: readonly PatternStep[] = [\n${entry.steps + .map( + (step) => + `\t{ charClass: ${step.charClass}, min: ${step.min}, max: ${step.max}, capture: ${step.capture} },`, + ) + .join("\n")}\n];`; + +/** Renders a closed set of strings. */ +const enumeration = (entry: EnumDecl): string => + `${entry.doc === "" ? "" : `/**\n${entry.doc + .split("\n") + .map((line) => ` * ${line}`.trimEnd()) + .join("\n")}\n */\n`}export type ${entry.name} =\n${entry.values + .map((value) => `\t| ${lit(value)}`) + .join("\n")};`; + +/** Renders a dataset as the table the runtime materialises. */ +const data = (entry: DataDecl): string => { + const rows = entry.rows.map((row) => `\t\t[${row.map((cell) => lit(cell)).join(", ")}],`).join("\n"); + const groups = Object.entries(entry.groups) + .map(([key, indexes]) => `\t\t[${lit(key)}, [${indexes.join(", ")}]],`) + .join("\n"); + + return `/** ${entry.doc} */ +const ${entry.name} = makeDataset( +\t[ +${rows} +\t], +\t[ +${groups} +\t], +\t[${entry.fullOrder.join(", ")}], +);`; +}; + +/** Renders an options or record type. */ +const struct = (entry: StructDecl): string => { + const fields = entry.fields + .map((field) => { + const domain = field.domain === undefined ? type(field.ty) : field.domain.join(" | "); + + return `${field.doc === "" ? "" : `\t/** ${field.doc} */\n`}\t${field.name}${entry.isOptions ? "?" : ""}: ${domain};`; + }) + .join("\n"); + + return `${entry.doc === "" ? "" : `/** ${entry.doc} */\n`}export type ${entry.name} = {\n${fields}\n};`; +}; + +/** Renders one function, documentation included. */ +const func = (entry: FuncDecl): string => { + const params = entry.params + .map((param) => { + // `stateCode?: StateCode` already says "or undefined"; spelling it twice is noise. + const declared = param.optional && param.ty.k === "opt" ? param.ty.of : param.ty; + + return `${param.name}${param.optional ? "?" : ""}: ${type(declared)}`; + }) + .join(", "); + const doc = entry.doc === "" ? "" : `/**\n${entry.doc.split("\n").map((line) => ` * ${line}`.trimEnd()).join("\n")}\n */\n`; + const signature = `(${params}): ${entry.isAsync ? `Promise<${type(entry.ret)}>` : type(entry.ret)}`; + + return `${doc}${entry.exported ? "export " : ""}const ${entry.name} = ${entry.isAsync ? "async " : ""}${signature} => {\n${block(entry.body, "\t")}\n};`; +}; + +/** + * Emits the TypeScript target of one module. + * + * @param {Module} module - The compiled module. + * @returns {Record} The files, by path. + */ +export const emit = (module: Module): Record => { + structs = new Map(module.structs.map((entry) => [entry.name, entry])); + + const used = new Set(); + const rendered = module.functions.map((entry) => func(entry)).join("\n\n"); + + for (const helper of [ + "codeAt", + "classHas", + "keepClass", + "patternTest", + "padStart", + "asString", + "isTruthy", + "dataAll", + "dataRows", + ]) { + if (new RegExp(`\\b${helper}\\(`).test(rendered)) used.add(helper); + } + + if (module.charClasses.length > 0) used.add("type CharClass"); + if (module.patterns.length > 0) used.add("type PatternStep"); + if (module.data.length > 0) used.add("makeDataset"); + + const imports = [...used].sort(); + const constants = module.constants + .map((entry) => `const ${entry.name} = ${expr(entry.expr)};`) + .join("\n"); + + // One file per exported function, in the layout `src/` uses, re-exporting the module. The + // package's own tests import these paths, so the generated code drops straight in. + const shims: Record = {}; + + for (const entry of module.functions) { + if (!entry.exported) continue; + + const kebab = entry.name.replaceAll(/([a-z0-9])([A-Z])/g, "$1-$2").toLowerCase(); + const types = [ + ...module.structs.map((candidate) => candidate.name), + ...module.enums.map((candidate) => candidate.name), + ]; + const exports = [entry.name, ...types.map((name) => `type ${name}`)].join(", "); + + shims[`${kebab}/${kebab}.ts`] = + `// Code generated from spec/bridge/source/${module.name}.ts. DO NOT EDIT.\nexport { ${exports} } from "../_bridge/${module.name}";\n`; + } + + return { + ...shims, + "_bridge/_runtime.ts": readFileSync(RUNTIME, "utf8"), + [`_bridge/${module.name}.ts`]: `// Code generated from spec/bridge/source/${module.name}.ts. DO NOT EDIT. +${module.doc === "" ? "" : `\n/** ${module.doc} */\n`} +import { ${imports.join(", ")} } from "./_runtime.ts"; + +${module.charClasses.map((entry) => charClass(entry)).join("\n")} + +${module.patterns.map((entry) => pattern(entry)).join("\n\n")} + +${constants} + +${module.enums.map((entry) => enumeration(entry)).join("\n\n")} + +${module.structs.map((entry) => struct(entry)).join("\n\n")} + +${module.data.map((entry) => data(entry)).join("\n\n")} + +${rendered} +`, + }; +}; diff --git a/spec/bridge/conformance/drivers.ts b/spec/bridge/conformance/drivers.ts new file mode 100644 index 000000000..1654a5ac9 --- /dev/null +++ b/spec/bridge/conformance/drivers.ts @@ -0,0 +1,818 @@ +/** + * Turns the recorded vectors into a table every target can read, and writes the small driver + * each language uses to replay it. + * + * A tab separated file rather than JSON: every target can split a line without a parser, and + * the escaping rules are the same everywhere, which keeps the drivers honest and tiny. + * + * Usage: `node spec/bridge/conformance/drivers.ts` + */ +import { mkdirSync, readFileSync, writeFileSync } from "node:fs"; +import { dirname, resolve } from "node:path"; +import type { Case } from "./vectors.ts"; + +const bridge = resolve(import.meta.dirname, ".."); +const vectors = JSON.parse(readFileSync(resolve(bridge, "conformance/vectors.json"), "utf8")) as { + cases: Case[]; +}; + +/** Escapes the three characters the table format reserves. */ +const cell = (value: string): string => + value.replaceAll("\\", "\\\\").replaceAll("\t", "\\t").replaceAll("\n", "\\n"); + +const columns = ["fn", "input", "kind", "version", "pad", "obfuscate", "expected"]; +const lines = [columns.join("\t")]; + +for (const entry of vectors.cases) { + const options = entry.options as { version?: number; pad?: boolean; obfuscate?: boolean }; + + lines.push( + [ + entry.fn, + cell(String(entry.input)), + typeof entry.input === "number" ? "number" : "string", + options.version === undefined ? "" : String(options.version), + options.pad === true ? "1" : "", + options.obfuscate === true ? "1" : "", + cell(entry.expected), + ].join("\t"), + ); +} + +const tablePath = resolve(bridge, "conformance/vectors.tsv"); + +writeFileSync(tablePath, `${lines.join("\n")}\n`); + +const files: Record = { + "out/typescript/conformance.ts": `// Code generated by spec/bridge/conformance/drivers.ts. DO NOT EDIT. +import { readFileSync } from "node:fs"; +import { resolve } from "node:path"; +import { formatCnpj, isValidCnpj } from "./_bridge/cnpj.ts"; +import { type StateCode, getMunicipalities } from "./_bridge/municipalities.ts"; + +const table = readFileSync(resolve(import.meta.dirname, "../../conformance/vectors.tsv"), "utf8"); +const unescape = (value: string): string => + value.replaceAll("\\\\t", "\\t").replaceAll("\\\\n", "\\n").replaceAll("\\\\\\\\", "\\\\"); + +let passed = 0; +let failed = 0; + +for (const line of table.split("\\n").slice(1)) { + if (line === "") continue; + + const [fn, rawInput, kind, version, pad, obfuscate, rawExpected] = line.split("\\t"); + const input = unescape(rawInput); + const expected = unescape(rawExpected); + const options: Record = {}; + + if (version !== "") options["version"] = Number(version); + if (pad === "1") options["pad"] = true; + if (obfuscate === "1") options["obfuscate"] = true; + + const value = kind === "number" ? Number(input) : input; + const actual = + fn === "isValidCnpj" + ? String(isValidCnpj(value as string, options)) + : formatCnpj(value as string, options); + + if (actual === expected) passed++; + else { + failed++; + + if (failed <= 5) + console.error(\`FAIL \${fn}(\${JSON.stringify(input)}) expected \${JSON.stringify(expected)} got \${JSON.stringify(actual)}\`); + } +} + +console.log(\`typescript: \${passed}/\${passed + failed} conformance checks passed\`); + +const dump: string[] = []; + +for (const key of readFileSync(resolve(import.meta.dirname, "../../conformance/municipalities.keys.txt"), "utf8").trimEnd().split("\\n")) { + const found = key === "*" ? getMunicipalities() : getMunicipalities(key as StateCode); + + dump.push(\`\${key}\\t\${found.length}\`); + + for (const municipality of found) + dump.push(\`\${municipality.code}|\${municipality.name}|\${municipality.stateCode}\`); +} + +const expectedDump = readFileSync(resolve(import.meta.dirname, "../../conformance/municipalities.expected.txt"), "utf8").trimEnd().split("\\n"); +let dumpFailed = 0; + +for (let index = 0; index < Math.max(dump.length, expectedDump.length); index++) { + if (dump[index] === expectedDump[index]) continue; + + dumpFailed++; + + if (dumpFailed <= 5) + console.error(\`FAIL municipalities line \${index + 1}: expected \${JSON.stringify(expectedDump[index])} got \${JSON.stringify(dump[index])}\`); +} + +console.log(\`typescript: \${expectedDump.length - dumpFailed}/\${expectedDump.length} municipality lines matched\`); +process.exit(failed === 0 && dumpFailed === 0 ? 0 : 1); +`, + + "out/python/conformance.py": `# Code generated by spec/bridge/conformance/drivers.ts. DO NOT EDIT. +"""Replays the vectors recorded from the JavaScript package against the generated Python.""" + +import sys +from pathlib import Path + +HERE = Path(__file__).resolve().parent +sys.path.insert(0, str(HERE)) + +from brutils_bridge.cnpj import ( # noqa: E402 + FormatCnpjOptions, + IsValidCnpjOptions, + format_cnpj, + is_valid_cnpj, +) +from brutils_bridge.municipalities import get_municipalities # noqa: E402 + + +def unescape(value): + return value.replace("\\\\t", "\\t").replace("\\\\n", "\\n").replace("\\\\\\\\", "\\\\") + + +passed = 0 +failed = 0 + +with (HERE.parent.parent / "conformance/vectors.tsv").open(encoding="utf-8") as handle: + next(handle) + + for line in handle: + if line.strip("\\n") == "": + continue + + fn, raw_input, kind, version, pad, obfuscate, raw_expected = line.rstrip("\\n").split("\\t") + value = unescape(raw_input) + expected = unescape(raw_expected) + number = float(value) if kind == "number" else None + + if kind == "number": + value = int(number) if number.is_integer() else number + + if fn == "isValidCnpj": + options = IsValidCnpjOptions(version=int(version) if version else None) + actual = str(is_valid_cnpj(value, options)).lower() + else: + options = FormatCnpjOptions( + version=int(version) if version else None, + pad=True if pad == "1" else None, + obfuscate=True if obfuscate == "1" else None, + ) + actual = format_cnpj(value, options) + + if actual == expected: + passed += 1 + else: + failed += 1 + + if failed <= 5: + print(f"FAIL {fn}({value!r}) expected {expected!r} got {actual!r}", file=sys.stderr) + +print(f"python: {passed}/{passed + failed} conformance checks passed") + +CONFORMANCE = HERE.parent.parent / "conformance" +dump = [] + +for key in (CONFORMANCE / "municipalities.keys.txt").read_text(encoding="utf-8").rstrip("\\n").split("\\n"): + found = get_municipalities(None) if key == "*" else get_municipalities(key) + dump.append(f"{key}\\t{len(found)}") + + for municipality in found: + dump.append(f"{municipality.code}|{municipality.name}|{municipality.state_code}") + +expected_dump = ( + (CONFORMANCE / "municipalities.expected.txt").read_text(encoding="utf-8").rstrip("\\n").split("\\n") +) +dump_failed = 0 + +for index in range(max(len(dump), len(expected_dump))): + got = dump[index] if index < len(dump) else None + want = expected_dump[index] if index < len(expected_dump) else None + + if got == want: + continue + + dump_failed += 1 + + if dump_failed <= 5: + print(f"FAIL municipalities line {index + 1}: expected {want!r} got {got!r}", file=sys.stderr) + +print(f"python: {len(expected_dump) - dump_failed}/{len(expected_dump)} municipality lines matched") +sys.exit(0 if failed == 0 and dump_failed == 0 else 1) +`, + + "out/go/conformance/main.go": `// Code generated by spec/bridge/conformance/drivers.ts. DO NOT EDIT. + +package main + +import ( + "bufio" + "fmt" + "os" + "strconv" + "strings" + + "brazilianutils/bridge/cnpj" + "brazilianutils/bridge/municipalities" +) + +func unescape(value string) string { + value = strings.ReplaceAll(value, "\\\\t", "\\t") + value = strings.ReplaceAll(value, "\\\\n", "\\n") + + return strings.ReplaceAll(value, "\\\\\\\\", "\\\\") +} + +func intPtr(value int64) *int64 { return &value } +func boolPtr(value bool) *bool { return &value } + +func main() { + file, err := os.Open("../../conformance/vectors.tsv") + + if err != nil { + panic(err) + } + + defer file.Close() + + scanner := bufio.NewScanner(file) + scanner.Buffer(make([]byte, 1024*1024), 1024*1024) + scanner.Scan() + + passed := 0 + failed := 0 + skipped := 0 + + for scanner.Scan() { + line := scanner.Text() + + if line == "" { + continue + } + + parts := strings.Split(line, "\\t") + fn, input, kind, version, pad, obfuscate, expected := parts[0], unescape(parts[1]), parts[2], parts[3], parts[4], parts[5], unescape(parts[6]) + + // A number input to a validator cannot be written in Go: the parameter is a string, so + // the JavaScript quirk "a number is never a valid CNPJ" has no Go equivalent. + if kind == "number" && fn == "isValidCnpj" { + skipped++ + + continue + } + + var actual string + + if fn == "isValidCnpj" { + options := &cnpj.IsValidCnpjOptions{} + + if version != "" { + parsed, _ := strconv.ParseInt(version, 10, 64) + options.Version = intPtr(parsed) + } + + actual = strconv.FormatBool(cnpj.IsValidCnpj(input, options)) + } else { + options := &cnpj.FormatCnpjOptions{} + + if version != "" { + parsed, _ := strconv.ParseInt(version, 10, 64) + options.Version = intPtr(parsed) + } + + if pad == "1" { + options.Pad = boolPtr(true) + } + + if obfuscate == "1" { + options.Obfuscate = boolPtr(true) + } + + actual = cnpj.FormatCnpj(input, options) + } + + if actual == expected { + passed++ + } else { + failed++ + + if failed <= 5 { + fmt.Fprintf(os.Stderr, "FAIL %s(%q) expected %q got %q\\n", fn, input, expected, actual) + } + } + } + + fmt.Printf("go: %d/%d conformance checks passed (%d not expressible)\\n", passed, passed+failed, skipped) + + keys, err := os.ReadFile("../../conformance/municipalities.keys.txt") + + if err != nil { + panic(err) + } + + dump := []string{} + + for _, key := range strings.Split(strings.TrimRight(string(keys), "\\n"), "\\n") { + var found []*municipalities.Municipality + + if key == "*" { + found = municipalities.GetMunicipalities(nil) + } else { + asked := key + found = municipalities.GetMunicipalities(&asked) + } + + dump = append(dump, fmt.Sprintf("%s\\t%d", key, len(found))) + + for _, municipality := range found { + dump = append(dump, fmt.Sprintf("%s|%s|%s", municipality.Code, municipality.Name, municipality.StateCode)) + } + } + + raw, err := os.ReadFile("../../conformance/municipalities.expected.txt") + + if err != nil { + panic(err) + } + + expectedDump := strings.Split(strings.TrimRight(string(raw), "\\n"), "\\n") + dumpFailed := 0 + longest := len(dump) + + if len(expectedDump) > longest { + longest = len(expectedDump) + } + + for index := 0; index < longest; index++ { + got := "" + want := "" + + if index < len(dump) { + got = dump[index] + } + + if index < len(expectedDump) { + want = expectedDump[index] + } + + if got == want { + continue + } + + dumpFailed++ + + if dumpFailed <= 5 { + fmt.Fprintf(os.Stderr, "FAIL municipalities line %d: expected %q got %q\\n", index+1, want, got) + } + } + + fmt.Printf("go: %d/%d municipality lines matched\\n", len(expectedDump)-dumpFailed, len(expectedDump)) + + if failed > 0 || dumpFailed > 0 { + os.Exit(1) + } +} +`, + + "out/rust/src/bin/conformance.rs": `// Code generated by spec/bridge/conformance/drivers.ts. DO NOT EDIT. + +use brazilian_utils_bridge::cnpj; +use brazilian_utils_bridge::municipalities; + +fn unescape(value: &str) -> String { + value.replace("\\\\t", "\\t").replace("\\\\n", "\\n").replace("\\\\\\\\", "\\\\") +} + +fn main() { + let table = std::fs::read_to_string("../../conformance/vectors.tsv").expect("vectors"); + let mut passed = 0; + let mut failed = 0; + let mut skipped = 0; + + for line in table.lines().skip(1) { + if line.is_empty() { + continue; + } + + let parts: Vec<&str> = line.split('\\t').collect(); + let (fn_name, input, kind) = (parts[0], unescape(parts[1]), parts[2]); + let (version, pad, obfuscate, expected) = (parts[3], parts[4], parts[5], unescape(parts[6])); + + // A number input to a validator cannot be written in Rust: the parameter is a \`&str\`. + if kind == "number" && fn_name == "isValidCnpj" { + skipped += 1; + + continue; + } + + let actual = if fn_name == "isValidCnpj" { + let options = cnpj::IsValidCnpjOptions { + version: if version.is_empty() { None } else { Some(version.parse().unwrap()) }, + }; + + cnpj::is_valid_cnpj(&input, Some(&options)).to_string() + } else { + let options = cnpj::FormatCnpjOptions { + version: if version.is_empty() { None } else { Some(version.parse().unwrap()) }, + pad: if pad == "1" { Some(true) } else { None }, + obfuscate: if obfuscate == "1" { Some(true) } else { None }, + }; + + cnpj::format_cnpj(&input, Some(&options)) + }; + + if actual == expected { + passed += 1; + } else { + failed += 1; + + if failed <= 5 { + eprintln!("FAIL {}({:?}) expected {:?} got {:?}", fn_name, input, expected, actual); + } + } + } + + println!("rust: {}/{} conformance checks passed ({} not expressible)", passed, passed + failed, skipped); + + let keys = std::fs::read_to_string("../../conformance/municipalities.keys.txt").expect("keys"); + let mut dump: Vec = Vec::new(); + + for key in keys.trim_end_matches('\\n').split('\\n') { + let found = if key == "*" { + municipalities::get_municipalities(None) + } else { + municipalities::get_municipalities(Some(key)) + }; + + dump.push(format!("{}\\t{}", key, found.len())); + + for municipality in &found { + dump.push(format!("{}|{}|{}", municipality.code, municipality.name, municipality.state_code)); + } + } + + let raw = std::fs::read_to_string("../../conformance/municipalities.expected.txt").expect("dump"); + let expected_dump: Vec<&str> = raw.trim_end_matches('\\n').split('\\n').collect(); + let mut dump_failed = 0; + + for index in 0..std::cmp::max(dump.len(), expected_dump.len()) { + let got = dump.get(index).map(String::as_str).unwrap_or(""); + let want = *expected_dump.get(index).unwrap_or(&""); + + if got == want { + continue; + } + + dump_failed += 1; + + if dump_failed <= 5 { + eprintln!("FAIL municipalities line {}: expected {:?} got {:?}", index + 1, want, got); + } + } + + println!("rust: {}/{} municipality lines matched", expected_dump.len() - dump_failed, expected_dump.len()); + + if failed > 0 || dump_failed > 0 { + std::process::exit(1); + } +} +`, + "out/ruby/conformance.rb": `# frozen_string_literal: true + +# Code generated by spec/bridge/conformance/drivers.ts. DO NOT EDIT. + +require_relative 'lib/brazilian_utils_bridge/cnpj' +require_relative 'lib/brazilian_utils_bridge/municipalities' + +def unescape(value) + value.gsub('\\\\t', "\\t").gsub('\\\\n', "\\n").gsub('\\\\\\\\', '\\\\') +end + +passed = 0 +failed = 0 + +lines = File.readlines(File.expand_path('../../conformance/vectors.tsv', __dir__), encoding: 'UTF-8') + +lines.drop(1).each do |line| + next if line.strip.empty? + + fn, raw_input, kind, version, pad, obfuscate, raw_expected = line.chomp("\\n").split("\\t", -1) + value = unescape(raw_input) + expected = unescape(raw_expected) + value = value.to_i if kind == 'number' + + actual = + if fn == 'isValidCnpj' + options = BrazilianUtilsBridge::Cnpj::IsValidCnpjOptions.new( + version: version.empty? ? nil : version.to_i + ) + BrazilianUtilsBridge::Cnpj.is_valid_cnpj(value, options).to_s + else + options = BrazilianUtilsBridge::Cnpj::FormatCnpjOptions.new( + version: version.empty? ? nil : version.to_i, + pad: pad == '1' ? true : nil, + obfuscate: obfuscate == '1' ? true : nil + ) + BrazilianUtilsBridge::Cnpj.format_cnpj(value, options) + end + + if actual == expected + passed += 1 + else + failed += 1 + warn "FAIL #{fn}(#{value.inspect}) expected #{expected.inspect} got #{actual.inspect}" if failed <= 5 + end +end + +puts "ruby: #{passed}/#{passed + failed} conformance checks passed" + +conformance = File.expand_path('../../conformance', __dir__) +keys = File.read(File.join(conformance, 'municipalities.keys.txt'), encoding: 'UTF-8') +dump = [] + +keys.chomp("\n").split("\n", -1).each do |key| + found = + if key == '*' + BrazilianUtilsBridge::Municipalities.get_municipalities(nil) + else + BrazilianUtilsBridge::Municipalities.get_municipalities(key) + end + + dump.push("#{key}\t#{found.length}") + found.each { |m| dump.push("#{m.code}|#{m.name}|#{m.state_code}") } +end + +expected_dump = File.read(File.join(conformance, 'municipalities.expected.txt'), encoding: 'UTF-8') + .chomp("\n").split("\n", -1) +dump_failed = 0 + +[dump.length, expected_dump.length].max.times do |index| + next if dump[index] == expected_dump[index] + + dump_failed += 1 + warn "FAIL municipalities line #{index + 1}: expected #{expected_dump[index].inspect} got #{dump[index].inspect}" if dump_failed <= 5 +end + +puts "ruby: #{expected_dump.length - dump_failed}/#{expected_dump.length} municipality lines matched" +exit(failed.zero? && dump_failed.zero? ? 0 : 1) +`, + + "out/java/Conformance.java": `// Code generated by spec/bridge/conformance/drivers.ts. DO NOT EDIT. + +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.List; + +/** Replays the vectors recorded from the JavaScript package against the generated Java. */ +public final class Conformance { + private Conformance() {} + + private static String unescape(String value) { + return value.replace("\\\\t", "\\t").replace("\\\\n", "\\n").replace("\\\\\\\\", "\\\\"); + } + + public static void main(String[] args) throws Exception { + List lines = Files.readAllLines(Path.of(args[0])); + int passed = 0; + int failed = 0; + int skipped = 0; + + for (String line : lines.subList(1, lines.size())) { + if (line.isEmpty()) { + continue; + } + + String[] parts = line.split("\\t", -1); + String fn = parts[0]; + String input = unescape(parts[1]); + String kind = parts[2]; + String version = parts[3]; + String expected = unescape(parts[6]); + + // A number input to a validator cannot be written in Java: the parameter is a String. + if (kind.equals("number") && fn.equals("isValidCnpj")) { + skipped++; + + continue; + } + + String actual; + + if (fn.equals("isValidCnpj")) { + IsValidCnpjOptions options = new IsValidCnpjOptions(); + + if (!version.isEmpty()) { + options.version = Long.parseLong(version); + } + + actual = String.valueOf(Cnpj.isValidCnpj(input, options)); + } else { + FormatCnpjOptions options = new FormatCnpjOptions(); + + if (!version.isEmpty()) { + options.version = Long.parseLong(version); + } + + options.pad = parts[4].equals("1") ? Boolean.TRUE : null; + options.obfuscate = parts[5].equals("1") ? Boolean.TRUE : null; + actual = Cnpj.formatCnpj(input, options); + } + + if (actual.equals(expected)) { + passed++; + } else { + failed++; + + if (failed <= 5) { + System.err.printf("FAIL %s(%s) expected %s got %s%n", fn, input, expected, actual); + } + } + } + + System.out.printf("java: %d/%d conformance checks passed (%d not expressible)%n", passed, passed + failed, skipped); + + Path conformance = Path.of(args[0]).getParent(); + java.util.List dump = new java.util.ArrayList<>(); + + for (String key : Files.readString(conformance.resolve("municipalities.keys.txt")).stripTrailing().split("\\n", -1)) { + java.util.List found = + key.equals("*") ? Municipalities.getMunicipalities(null) : Municipalities.getMunicipalities(key); + + dump.add(key + "\\t" + found.size()); + + for (Municipality municipality : found) { + dump.add(municipality.code + "|" + municipality.name + "|" + municipality.stateCode); + } + } + + String[] expectedDump = + Files.readString(conformance.resolve("municipalities.expected.txt")).stripTrailing().split("\\n", -1); + int dumpFailed = 0; + + for (int index = 0; index < Math.max(dump.size(), expectedDump.length); index++) { + String got = index < dump.size() ? dump.get(index) : ""; + String want = index < expectedDump.length ? expectedDump[index] : ""; + + if (got.equals(want)) { + continue; + } + + dumpFailed++; + + if (dumpFailed <= 5) { + System.err.printf("FAIL municipalities line %d: expected %s got %s%n", index + 1, want, got); + } + } + + System.out.printf("java: %d/%d municipality lines matched%n", expectedDump.length - dumpFailed, expectedDump.length); + + if (failed > 0 || dumpFailed > 0) { + System.exit(1); + } + } +} +`, + + "out/csharp/Conformance.cs": `// Code generated by spec/bridge/conformance/drivers.ts. DO NOT EDIT. + +using System; +using System.IO; +using BrazilianUtils.Bridge; + +/// Replays the vectors recorded from the JavaScript package against the generated C#. +public static class Conformance +{ + private static string Unescape(string value) + { + return value.Replace("\\\\t", "\\t").Replace("\\\\n", "\\n").Replace("\\\\\\\\", "\\\\"); + } + + public static int Main(string[] args) + { + var lines = File.ReadAllLines(args[0]); + var passed = 0; + var failed = 0; + var skipped = 0; + + for (var row = 1; row < lines.Length; row++) + { + if (lines[row].Length == 0) + { + continue; + } + + var parts = lines[row].Split('\\t'); + var fn = parts[0]; + var input = Unescape(parts[1]); + var kind = parts[2]; + var version = parts[3]; + var expected = Unescape(parts[6]); + + // A number input to a validator cannot be written in C#: the parameter is a string. + if (kind == "number" && fn == "isValidCnpj") + { + skipped++; + + continue; + } + + string actual; + + if (fn == "isValidCnpj") + { + var options = new IsValidCnpjOptions(); + + if (version.Length > 0) + { + options.Version = long.Parse(version); + } + + actual = Cnpj.IsValidCnpj(input, options) ? "true" : "false"; + } + else + { + var options = new FormatCnpjOptions(); + + if (version.Length > 0) + { + options.Version = long.Parse(version); + } + + options.Pad = parts[4] == "1" ? true : (bool?)null; + options.Obfuscate = parts[5] == "1" ? true : (bool?)null; + actual = Cnpj.FormatCnpj(input, options); + } + + if (actual == expected) + { + passed++; + } + else + { + failed++; + + if (failed <= 5) + { + Console.Error.WriteLine($"FAIL {fn}({input}) expected {expected} got {actual}"); + } + } + } + + Console.WriteLine($"csharp: {passed}/{passed + failed} conformance checks passed ({skipped} not expressible)"); + + var conformance = Path.GetDirectoryName(Path.GetFullPath(args[0])); + var dump = new System.Collections.Generic.List(); + + foreach (var key in File.ReadAllText(Path.Combine(conformance, "municipalities.keys.txt")).TrimEnd('\\n').Split('\\n')) + { + var found = key == "*" ? Municipalities.GetMunicipalities() : Municipalities.GetMunicipalities(key); + + dump.Add(key + "\\t" + found.Count); + + foreach (var municipality in found) + { + dump.Add(municipality.Code + "|" + municipality.Name + "|" + municipality.StateCode); + } + } + + var expectedDump = File.ReadAllText(Path.Combine(conformance, "municipalities.expected.txt")).TrimEnd('\\n').Split('\\n'); + var dumpFailed = 0; + + for (var index = 0; index < Math.Max(dump.Count, expectedDump.Length); index++) + { + var got = index < dump.Count ? dump[index] : ""; + var want = index < expectedDump.Length ? expectedDump[index] : ""; + + if (got == want) + { + continue; + } + + dumpFailed++; + + if (dumpFailed <= 5) + { + Console.Error.WriteLine($"FAIL municipalities line {index + 1}: expected {want} got {got}"); + } + } + + Console.WriteLine($"csharp: {expectedDump.Length - dumpFailed}/{expectedDump.Length} municipality lines matched"); + + return failed == 0 && dumpFailed == 0 ? 0 : 1; + } +} +`, +}; + +for (const [path, contents] of Object.entries(files)) { + const full = resolve(bridge, path); + + mkdirSync(dirname(full), { recursive: true }); + writeFileSync(full, contents); +} + +console.log(`wrote ${tablePath} (${lines.length - 1} rows) and ${Object.keys(files).length} drivers`); diff --git a/spec/bridge/conformance/municipalities.ts b/spec/bridge/conformance/municipalities.ts new file mode 100644 index 000000000..019561f1a --- /dev/null +++ b/spec/bridge/conformance/municipalities.ts @@ -0,0 +1,92 @@ +/** + * Records the municipality dump the generated code has to reproduce, from the package this + * repository ships. + * + * A dump rather than a sample: every municipality of every key is written out, so a single + * name out of place in one of the seven targets fails the check. + * + * Usage: `node spec/bridge/conformance/municipalities.ts` + */ +import { mkdtempSync, rmSync, writeFileSync } from "node:fs"; +import { tmpdir } from "node:os"; +import { join, resolve } from "node:path"; +import { build } from "esbuild"; + +const bridge = resolve(import.meta.dirname, ".."); +const root = resolve(bridge, "../.."); + +/** + * The keys to dump. `*` stands for "no state code at all", which is the only way to ask for the + * combined list; every other value, an unknown state and an inherited `Object` property name + * included, has its own answer. + */ +export const KEYS = [ + "*", + "AC", + "AL", + "AP", + "AM", + "BA", + "CE", + "DF", + "ES", + "GO", + "MA", + "MT", + "MS", + "MG", + "PA", + "PB", + "PR", + "PE", + "PI", + "RJ", + "RN", + "RS", + "RO", + "RR", + "SC", + "SP", + "SE", + "TO", + "ZZ", + "sp", + "", + "toString", + "constructor", + "hasOwnProperty", +]; + +const outDir = mkdtempSync(join(tmpdir(), "brutils-dump-")); +const bundlePath = join(outDir, "shipped.mjs"); + +await build({ + entryPoints: [resolve(root, "src/index.ts")], + bundle: true, + format: "esm", + platform: "neutral", + outfile: bundlePath, + logLevel: "error", +}); + +const shipped = (await import(bundlePath)) as { + getMunicipalities: (stateCode?: string) => { code: string; name: string; stateCode: string }[]; +}; + +rmSync(outDir, { recursive: true, force: true }); + +const lines: string[] = []; + +for (const key of KEYS) { + const found = key === "*" ? shipped.getMunicipalities() : shipped.getMunicipalities(key); + + lines.push(`${key}\t${found.length}`); + + for (const municipality of found) + lines.push(`${municipality.code}|${municipality.name}|${municipality.stateCode}`); +} + +writeFileSync(resolve(bridge, "conformance/municipalities.expected.txt"), `${lines.join("\n")}\n`); +writeFileSync(resolve(bridge, "conformance/municipalities.keys.txt"), `${KEYS.join("\n")}\n`); + +console.log(`${KEYS.length} keys, ${lines.length - KEYS.length} rows recorded from the shipped package`); diff --git a/spec/bridge/conformance/run-all.sh b/spec/bridge/conformance/run-all.sh new file mode 100644 index 000000000..12c6642a9 --- /dev/null +++ b/spec/bridge/conformance/run-all.sh @@ -0,0 +1,66 @@ +#!/usr/bin/env bash +# Regenerates every target and replays the recorded vectors through all seven of them. +# +# The vectors and the municipality dump are recordings of the JavaScript package this +# repository ships, so a green run means the generated code answers exactly what the +# handwritten code answers, in every language. +# +# Usage: `bash spec/bridge/conformance/run-all.sh` +set -uo pipefail + +bridge="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" +out="${bridge}/out" +status=0 + +step() { + echo + echo "── $1" +} + +run() { + local label="$1" + shift + + if ! "$@"; then + echo "${label}: FAILED" + status=1 + fi +} + +step "recording the expectations from the package this repository ships" +node "${bridge}/conformance/vectors.ts" +node "${bridge}/conformance/municipalities.ts" + +step "compiling source/ into every target" +node "${bridge}/compiler/cli.ts" +node "${bridge}/conformance/drivers.ts" + +step "typescript" +run typescript bash -c "cd '${out}/typescript' && node conformance.ts" + +step "python" +run python bash -c "cd '${out}/python' && python3 conformance.py" + +step "ruby" +run ruby bash -c "cd '${out}/ruby' && ruby conformance.rb" + +step "go" +run go bash -c "cd '${out}/go' && go run ./conformance" + +step "rust" +run rust bash -c "cd '${out}/rust' && cargo run --quiet --release --bin conformance 2>/dev/null" + +step "java" +run java bash -c "cd '${out}/java' && javac -nowarn -d classes *.java >/dev/null 2>&1 && java -cp classes Conformance ../../conformance/vectors.tsv" + +step "csharp" +run csharp bash -c "cd '${out}/csharp' && DOTNET_CLI_TELEMETRY_OPTOUT=1 dotnet run --verbosity quiet -- ../../conformance/vectors.tsv" + +echo +if [ "${status}" -eq 0 ]; then + echo "all seven targets match the JavaScript package" +else + echo "at least one target diverged" +fi + +exit "${status}" diff --git a/spec/bridge/conformance/vectors.ts b/spec/bridge/conformance/vectors.ts new file mode 100644 index 000000000..4324c2d21 --- /dev/null +++ b/spec/bridge/conformance/vectors.ts @@ -0,0 +1,148 @@ +/** + * Builds the conformance vectors from the package this repository ships. + * + * The corpus is not invented: every string literal the relevant test files use is pulled out of + * them, so the cross language check runs the same inputs the JavaScript suite runs, plus + * generated and fuzzed values on top. The expectations come from calling the handwritten + * implementation, which makes the vectors a recording of the real contract. + * + * Usage: `node spec/bridge/conformance/vectors.ts` + */ +import { mkdtempSync, readFileSync, readdirSync, rmSync, writeFileSync } from "node:fs"; +import { tmpdir } from "node:os"; +import { join, resolve } from "node:path"; +import { build } from "esbuild"; + +const bridge = resolve(import.meta.dirname, ".."); +const root = resolve(bridge, "../.."); + +type Options = Record; +export type Case = { fn: string; input: string | number; options: Options; expected: string }; +export type Vectors = { cases: Case[] }; + +/** Pulls every string literal out of a test file, which is where the interesting inputs live. */ +const literalsOf = (path: string): string[] => { + const source = readFileSync(path, "utf8"); + const found = new Set(); + + for (const match of source.matchAll(/"((?:[^"\\\n]|\\.){0,40})"/g)) { + try { + found.add(JSON.parse(`"${match[1]}"`) as string); + } catch { + // A literal that is not valid JSON on its own is not an input worth replaying. + } + } + + return [...found]; +}; + +/** A deterministic pseudo random generator, so the corpus only changes when this file does. */ +const mulberry32 = (seed: number): (() => number) => { + let state = seed; + + return () => { + state = Math.imul(state + 0x6d_2b_79_f5, 1); + let t = Math.imul(state ^ (state >>> 15), 1 | state); + + t ^= t + Math.imul(t ^ (t >>> 7), 61 | t); + + return ((t ^ (t >>> 14)) >>> 0) / 4_294_967_296; + }; +}; + +const MASKS = [".", "-", "/", " ", " ", "", "!", "a"]; + +/** + * Builds the corpus: the test literals, generated CNPJs, masked variants and junk. + * + * @param {Function} generateCnpj - The package's own generator. + * @returns {(string | number)[]} The corpus. + */ +const buildCorpus = (generateCnpj: (version?: 1 | 2) => string): (string | number)[] => { + const random = mulberry32(0x62_72_31); + const corpus = new Set(); + + for (const name of readdirSync(resolve(root, "src/is-valid-cnpj"))) { + if (name.endsWith(".test.ts")) + for (const literal of literalsOf(resolve(root, "src/is-valid-cnpj", name))) corpus.add(literal); + } + + for (const name of readdirSync(resolve(root, "src/format-cnpj"))) { + if (name.endsWith(".test.ts")) + for (const literal of literalsOf(resolve(root, "src/format-cnpj", name))) corpus.add(literal); + } + + for (let index = 0; index < 120; index++) { + const version = index % 2 === 0 ? 1 : 2; + const cnpj = generateCnpj(version as 1 | 2); + + corpus.add(cnpj); + corpus.add(cnpj.toLowerCase()); + + const separators = [0, 1, 2, 3].map(() => MASKS[Math.floor(random() * MASKS.length)]); + + corpus.add( + `${cnpj.slice(0, 2)}${separators[0]}${cnpj.slice(2, 5)}${separators[1]}${cnpj.slice(5, 8)}${separators[2]}${cnpj.slice(8, 12)}${separators[3]}${cnpj.slice(12)}`, + ); + + const position = Math.floor(random() * cnpj.length); + + corpus.add(`${cnpj.slice(0, position)}${Math.floor(random() * 10)}${cnpj.slice(position + 1)}`); + } + + for (const number of [0, 4, 46, 468, 12_345_678, 12_345_678_000_195]) corpus.add(number); + + return [...corpus]; +}; + +const outDir = mkdtempSync(join(tmpdir(), "brutils-bridge-")); +const bundlePath = join(outDir, "shipped.mjs"); + +await build({ + entryPoints: [resolve(root, "src/index.ts")], + bundle: true, + format: "esm", + platform: "neutral", + outfile: bundlePath, + logLevel: "error", +}); + +const shipped = (await import(bundlePath)) as { + isValidCnpj: (value: unknown, options?: Options) => boolean; + formatCnpj: (value: unknown, options?: Options) => string; + generateCnpj: (version?: 1 | 2) => string; +}; + +const corpus = buildCorpus(shipped.generateCnpj); +const validatorOptions: Options[] = [{}, { version: 1 }, { version: 2 }]; +const formatterOptions: Options[] = [ + {}, + { version: 2 }, + { pad: true }, + { obfuscate: true }, + { version: 2, pad: true }, + { version: 2, obfuscate: true }, + { pad: true, obfuscate: true }, +]; + +const cases: Case[] = []; + +for (const input of corpus) { + for (const options of validatorOptions) { + cases.push({ + fn: "isValidCnpj", + input, + options, + expected: String(shipped.isValidCnpj(input, options)), + }); + } + + for (const options of formatterOptions) { + cases.push({ fn: "formatCnpj", input, options, expected: shipped.formatCnpj(input, options) }); + } +} + +rmSync(outDir, { recursive: true, force: true }); +writeFileSync(resolve(bridge, "conformance/vectors.json"), `${JSON.stringify({ cases })}\n`); + +console.log(`${corpus.length} inputs, ${cases.length} expectations recorded from the shipped package`); diff --git a/spec/bridge/conformance/verify-typescript.sh b/spec/bridge/conformance/verify-typescript.sh new file mode 100644 index 000000000..68f174b71 --- /dev/null +++ b/spec/bridge/conformance/verify-typescript.sh @@ -0,0 +1,48 @@ +#!/usr/bin/env bash +# Drops the generated TypeScript into `src/` and runs the package's own test suite against it. +# +# This is the parity gate: the generated code has to pass the tests the handwritten code passes, +# unmodified. The tree is restored afterwards, whatever the outcome. +# +# Usage: bash spec/bridge/conformance/verify-typescript.sh [vitest path...] +set -euo pipefail + +root="$(cd "$(dirname "${BASH_SOURCE[0]}")/../../.." && pwd)" +bridge="${root}/spec/bridge" +out="${bridge}/out/typescript" + +targets=("$@") + +if [ ${#targets[@]} -eq 0 ]; then + targets=(src/is-valid-cnpj src/format-cnpj src/get-municipalities src/get-address-info-by-cep) +fi + +restore() { + rm -rf "${root}/src/_bridge" + git -C "${root}" checkout -- src >/dev/null 2>&1 +} + +trap restore EXIT + +node "${bridge}/compiler/cli.ts" typescript >/dev/null + +mkdir -p "${root}/src/_bridge" +cp -r "${out}/_bridge/." "${root}/src/_bridge/" + +for shim in "${out}"/*/; do + name="$(basename "${shim}")" + + [ "${name}" = "_bridge" ] && continue + + mkdir -p "${root}/src/${name}" + cp "${shim}${name}.ts" "${root}/src/${name}/${name}.ts" + echo "replaced src/${name}/${name}.ts with the generated version" +done + +existing=() + +for target in "${targets[@]}"; do + [ -d "${root}/${target}" ] && existing+=("${target}") +done + +cd "${root}" && npx vp test run "${existing[@]}" diff --git a/spec/bridge/data/build.ts b/spec/bridge/data/build.ts new file mode 100644 index 000000000..5a66f5d28 --- /dev/null +++ b/spec/bridge/data/build.ts @@ -0,0 +1,88 @@ +/** + * Builds the datasets the portable source reads. + * + * A dataset is a table plus the two orders the utilities need: the per key order and the full + * order. Both are resolved here, once, against the JavaScript package's own data and its own + * `localeCompare(…, "pt-BR")`, and then baked into the JSON the emitters materialise natively. + * + * Collation is the reason this step exists. `"Á".localeCompare("B", "pt-BR")` is a locale + * database lookup, and no two of the seven targets ship the same one: Go has no collator in the + * standard library, Rust has none either, Ruby compares bytes, and Java, C# and Python each + * resolve their own ICU or libc table. Sorting at run time would therefore produce seven + * different orders. Sorting here produces one, and every target replays it. + * + * Usage: `node spec/bridge/data/build.ts` + */ +import { mkdtempSync, rmSync, writeFileSync } from "node:fs"; +import { tmpdir } from "node:os"; +import { join, resolve } from "node:path"; +import { build } from "esbuild"; + +const bridge = resolve(import.meta.dirname, ".."); +const root = resolve(bridge, "../.."); + +const outDir = mkdtempSync(join(tmpdir(), "brutils-data-")); +const bundlePath = join(outDir, "shipped.mjs"); + +await build({ + entryPoints: [resolve(root, "src/index.ts")], + bundle: true, + format: "esm", + platform: "neutral", + outfile: bundlePath, + logLevel: "error", +}); + +const shipped = (await import(bundlePath)) as { + getStates: () => { code: string }[]; + getMunicipalities: (stateCode?: string) => { code: string; name: string; stateCode: string }[]; +}; + +rmSync(outDir, { recursive: true, force: true }); + +const columns = ["stateCode", "name", "code"]; +const rows: string[][] = []; +const groups: Record = {}; + +// The per state order is the order the package itself returns, which is already the pt-BR one. +for (const state of shipped.getStates()) { + groups[state.code] = []; + + for (const municipality of shipped.getMunicipalities(state.code)) { + groups[state.code].push(rows.length); + rows.push([municipality.stateCode, municipality.name, municipality.code]); + } +} + +// The full order is the one `getMunicipalities()` returns: every state's rows merged and sorted +// by name with the pt-BR collator. Matching it by (name, code) rather than by position keeps +// this honest even if the package ever changes how it merges the states. +const byKey = new Map(); + +for (const [index, row] of rows.entries()) byKey.set(`${row[1]}\u0000${row[2]}`, index); + +const fullOrder = shipped.getMunicipalities().map((municipality) => { + const index = byKey.get(`${municipality.name}\u0000${municipality.code}`); + + if (index === undefined) + throw new Error(`the full list holds ${municipality.name} but no state does`); + + return index; +}); + +if (fullOrder.length !== rows.length) + throw new Error(`the full list has ${fullOrder.length} rows but the states have ${rows.length}`); + +const dataset = { + doc: "Brazilian municipalities published by the IBGE, by state, in the pt-BR collation order the JavaScript package returns.", + columns, + rows, + groups, + fullOrder, +}; + +writeFileSync(resolve(bridge, "source/municipalities.data.json"), `${JSON.stringify(dataset)}\n`); + +console.log( + `municipalities: ${rows.length} rows, ${Object.keys(groups).length} groups, full order baked`, +); diff --git a/spec/bridge/package-lock.json b/spec/bridge/package-lock.json new file mode 100644 index 000000000..fd7495aa3 --- /dev/null +++ b/spec/bridge/package-lock.json @@ -0,0 +1,391 @@ +{ + "name": "@brazilian-utils/bridge", + "version": "0.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "@brazilian-utils/bridge", + "version": "0.0.0", + "devDependencies": { + "oxc-parser": "^0.98.0" + } + }, + "node_modules/@emnapi/core": { + "version": "1.11.3", + "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.11.3.tgz", + "integrity": "sha512-zLpS5asjEb7lq8jYLq37N6XKaE41DIexlY1rF/z4/tIl3wo13Sqm28fRyfIsKZD+NZ8mM5RoKkpW/rBcuoSZSg==", + "dev": true, + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "@emnapi/wasi-threads": "1.2.3", + "tslib": "^2.4.0" + } + }, + "node_modules/@emnapi/runtime": { + "version": "1.11.3", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.11.3.tgz", + "integrity": "sha512-Xz4Tpyki7XyrpbUK1jR1AhdAdaXyhhY4lZ3neLodmhpuWfy2PAQN5B46sAiU4liOXGLkHypn/qU+jvfWSCYYLA==", + "dev": true, + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@emnapi/wasi-threads": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.2.3.tgz", + "integrity": "sha512-ELEBe8PsLvvJ6QMr0zLt8ffvOHW/dc1m3CEzNMg7aJUv3bMaoDtw2TXyDAwkYBuroxxuHEwhRTLJSe5sya547g==", + "dev": true, + "license": "MIT", + "optional": true, + "peer": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@napi-rs/wasm-runtime": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.2.4.tgz", + "integrity": "sha512-AJxoUD2/15ESHbvpcyjU274nsAPLuOtPHCk0vKJM5pj//Fg/B1FXNWjPnXTT9PymCYYiHo4zPj0ZomXBKhoy7g==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@tybys/wasm-util": "^0.10.3" + }, + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=23.5.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Brooooooklyn" + }, + "peerDependencies": { + "@emnapi/core": "^1.7.1 || ^2.0.0-alpha.4", + "@emnapi/runtime": "^1.7.1 || ^2.0.0-alpha.4" + } + }, + "node_modules/@oxc-parser/binding-android-arm64": { + "version": "0.98.0", + "resolved": "https://registry.npmjs.org/@oxc-parser/binding-android-arm64/-/binding-android-arm64-0.98.0.tgz", + "integrity": "sha512-/4S2BATZLxH94smwxLSvQsnzYjtyh/0mekgMnK/efCaU+92VNYir4+HOs/dvspYsWUooxPvj+AkwRUsLk9IuSg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxc-parser/binding-darwin-arm64": { + "version": "0.98.0", + "resolved": "https://registry.npmjs.org/@oxc-parser/binding-darwin-arm64/-/binding-darwin-arm64-0.98.0.tgz", + "integrity": "sha512-joNn+2n+TrDJ79GlwR32LK1gctKIxvSJm93teROFiYEde0Dhq9IZpnxiX9ctw4R2zwmSTf1yistTXIR84UGGDQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxc-parser/binding-darwin-x64": { + "version": "0.98.0", + "resolved": "https://registry.npmjs.org/@oxc-parser/binding-darwin-x64/-/binding-darwin-x64-0.98.0.tgz", + "integrity": "sha512-FUVDRGkMpx41bJI+seN57vmkwOp2uSATrU7e3mEjyP6lWTCvJWmD20/fxaXRY/Kh0xHvy1KBn4jPyKoK1ya/cg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxc-parser/binding-freebsd-x64": { + "version": "0.98.0", + "resolved": "https://registry.npmjs.org/@oxc-parser/binding-freebsd-x64/-/binding-freebsd-x64-0.98.0.tgz", + "integrity": "sha512-2ysH/IYALz2mDCnqu0xmJ/s0u2f+LZtDOaTkLhwTSQrLOqK4Pr3n4n564Jd1pxNabr07pAMUvBjQNzvWrKfmOg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxc-parser/binding-linux-arm-gnueabihf": { + "version": "0.98.0", + "resolved": "https://registry.npmjs.org/@oxc-parser/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-0.98.0.tgz", + "integrity": "sha512-7wwkjeCGzGP9gzmJcHyUDT67MP5szMvjlJs3VvWzGaPiQPaMnWzRpuLkycPlslT5/ch8j+rZm2vByPIKz6cIuw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxc-parser/binding-linux-arm-musleabihf": { + "version": "0.98.0", + "resolved": "https://registry.npmjs.org/@oxc-parser/binding-linux-arm-musleabihf/-/binding-linux-arm-musleabihf-0.98.0.tgz", + "integrity": "sha512-p93J3cNgVCiCcshXiaq+A+bws8AH0h5LmoEKtt1rJHkZH3uY3dEuuh/3T7arMd+mStVsBM8h+PQ2V/0MyI0rUw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxc-parser/binding-linux-arm64-gnu": { + "version": "0.98.0", + "resolved": "https://registry.npmjs.org/@oxc-parser/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-0.98.0.tgz", + "integrity": "sha512-wiIHSaNbAj7F8Ac5BERGJq2dSy+abNrZILY7s8PNK2VdwWXhfBSeRV+wUt3tC9zdsrvmRaLAUiM9IaRHEwKWsw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxc-parser/binding-linux-arm64-musl": { + "version": "0.98.0", + "resolved": "https://registry.npmjs.org/@oxc-parser/binding-linux-arm64-musl/-/binding-linux-arm64-musl-0.98.0.tgz", + "integrity": "sha512-Z/PBmbYZ+uBxqiKr3FGvg45rUr52FZQed26gJZZWFLt7a7l3AbfAL9bxUG5a+HiDC9+sDZrezJbjSRmTlPPg7Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxc-parser/binding-linux-riscv64-gnu": { + "version": "0.98.0", + "resolved": "https://registry.npmjs.org/@oxc-parser/binding-linux-riscv64-gnu/-/binding-linux-riscv64-gnu-0.98.0.tgz", + "integrity": "sha512-H4i91pTgQlCWmbVTye2YH0mgSw3YYf5vyJtCzk18IHtSRaYJ6QokyIkXAMStQv5iMBg6CibEKTv3/1vlemW5/g==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxc-parser/binding-linux-s390x-gnu": { + "version": "0.98.0", + "resolved": "https://registry.npmjs.org/@oxc-parser/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-0.98.0.tgz", + "integrity": "sha512-yNS5u0/K4Zyi7f43mvqMogXe9GedllLWGEwW6btp/sQce7GnGbMV6oDRiDs0C6UlnJMbctEU6qM4LsNkEobCSg==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxc-parser/binding-linux-x64-gnu": { + "version": "0.98.0", + "resolved": "https://registry.npmjs.org/@oxc-parser/binding-linux-x64-gnu/-/binding-linux-x64-gnu-0.98.0.tgz", + "integrity": "sha512-gmljgOLJvPljYk4pDxglK9Zg/dYrdnwIINYnNyMmEMl9/5Xn7MoJIR9QN52Vh+Fyq09ftDH89R3R2ef57MRKKw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxc-parser/binding-linux-x64-musl": { + "version": "0.98.0", + "resolved": "https://registry.npmjs.org/@oxc-parser/binding-linux-x64-musl/-/binding-linux-x64-musl-0.98.0.tgz", + "integrity": "sha512-zcD9b22Mb1/JsU3nCMGboiFZPFLtqNzViaQoPlN6ceDNejt4SsRDlChmLs/u6PluYn1V1SrvAThx1Skq2esD/A==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxc-parser/binding-wasm32-wasi": { + "version": "0.98.0", + "resolved": "https://registry.npmjs.org/@oxc-parser/binding-wasm32-wasi/-/binding-wasm32-wasi-0.98.0.tgz", + "integrity": "sha512-vp2OlfPGYMudNlDLL5+UJPPRn/RUI2VMFhKBnpC+nuAOz69IOf70ajwDATw+9jc8vVftuDzn06u+XTWJZGkGvQ==", + "cpu": [ + "wasm32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@napi-rs/wasm-runtime": "^1.0.7" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@oxc-parser/binding-win32-arm64-msvc": { + "version": "0.98.0", + "resolved": "https://registry.npmjs.org/@oxc-parser/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-0.98.0.tgz", + "integrity": "sha512-2SJI5E46/lBknEsTtxzFvlyUWAWBs6hSYbj46uIBfNpnLbF/lqo3ekuk1w5evEJjZdgYk7ayDSaRE1bm+7XUaw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxc-parser/binding-win32-x64-msvc": { + "version": "0.98.0", + "resolved": "https://registry.npmjs.org/@oxc-parser/binding-win32-x64-msvc/-/binding-win32-x64-msvc-0.98.0.tgz", + "integrity": "sha512-o5PfFt85u0nx2VLiKr2e+8j7kN4WaQR5sUTMZv2X0SOXfsLmmvr7DldQTeV/uWWLi0kFw0qpekKLBheHK1V2tA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxc-project/types": { + "version": "0.98.0", + "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.98.0.tgz", + "integrity": "sha512-Vzmd6FsqVuz5HQVcRC/hrx7Ujo3WEVeQP7C2UNP5uy1hUY4SQvMB+93jxkI1KRHz9a/6cni3glPOtvteN+zpsw==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/Boshen" + } + }, + "node_modules/@tybys/wasm-util": { + "version": "0.10.4", + "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.4.tgz", + "integrity": "sha512-W3c4gRigFS0T/Ma4qIYF3GDAc5AQdHb1yL5znJT1Zv1YaD9Kitx656wBjvr19qbiosmZT8lWDM5BEMynUqX65A==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/oxc-parser": { + "version": "0.98.0", + "resolved": "https://registry.npmjs.org/oxc-parser/-/oxc-parser-0.98.0.tgz", + "integrity": "sha512-gt99VUKRlZ6ZB3VBgqMJD858E8V5UpBQWX7cVI9XaYzuS8e3nN63uRlwPfkFoE4JN+MGxJ/WSRhBUhxUv23A/Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@oxc-project/types": "^0.98.0" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "funding": { + "url": "https://github.com/sponsors/Boshen" + }, + "optionalDependencies": { + "@oxc-parser/binding-android-arm64": "0.98.0", + "@oxc-parser/binding-darwin-arm64": "0.98.0", + "@oxc-parser/binding-darwin-x64": "0.98.0", + "@oxc-parser/binding-freebsd-x64": "0.98.0", + "@oxc-parser/binding-linux-arm-gnueabihf": "0.98.0", + "@oxc-parser/binding-linux-arm-musleabihf": "0.98.0", + "@oxc-parser/binding-linux-arm64-gnu": "0.98.0", + "@oxc-parser/binding-linux-arm64-musl": "0.98.0", + "@oxc-parser/binding-linux-riscv64-gnu": "0.98.0", + "@oxc-parser/binding-linux-s390x-gnu": "0.98.0", + "@oxc-parser/binding-linux-x64-gnu": "0.98.0", + "@oxc-parser/binding-linux-x64-musl": "0.98.0", + "@oxc-parser/binding-wasm32-wasi": "0.98.0", + "@oxc-parser/binding-win32-arm64-msvc": "0.98.0", + "@oxc-parser/binding-win32-x64-msvc": "0.98.0" + } + }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "dev": true, + "license": "0BSD", + "optional": true + } + } +} diff --git a/spec/bridge/package.json b/spec/bridge/package.json new file mode 100644 index 000000000..d6a03de3a --- /dev/null +++ b/spec/bridge/package.json @@ -0,0 +1,14 @@ +{ + "name": "@brazilian-utils/bridge", + "private": true, + "version": "0.0.0", + "type": "module", + "description": "Build time tool: compiles the portable TypeScript source under source/ into idiomatic native code for every language Brazilian Utils publishes. Not part of the npm package.", + "scripts": { + "build": "node compiler/cli.ts", + "conformance": "bash conformance/run-all.sh" + }, + "devDependencies": { + "oxc-parser": "^0.98.0" + } +} diff --git a/spec/bridge/source/_std.ts b/spec/bridge/source/_std.ts new file mode 100644 index 000000000..6f2f429aa --- /dev/null +++ b/spec/bridge/source/_std.ts @@ -0,0 +1,80 @@ +/** + * The portable standard library. + * + * These are the few operations whose behaviour the bridge pins itself instead of inheriting + * from the host: every target implements them identically. The implementations here are the + * reference, and are what runs when the source is executed directly as TypeScript. + */ +import { readFileSync } from "node:fs"; + +/** + * Reads a value as a string the way `String(value)` does, answering `""` when the value has no + * string conversion at all. + * + * @param {string|number} value - The value to read. + * @returns {string} The string form. + */ +export const asString = (value: string | number): string => { + try { + return String(value); + } catch { + return ""; + } +}; + +/** + * Reads an optional flag the way JavaScript reads truthiness, so a caller passing `1` where a + * boolean was declared gets the same answer everywhere. + * + * @param {boolean} [value] - The flag. + * @returns {boolean} Whether the flag is set. + */ +export const isTruthy = (value?: boolean): boolean => Boolean(value); + +/** + * A dataset: a table of string rows, the row indexes grouped by the value of the first column, + * and the order the rows are returned in when no key is given. + * + * Both orders are resolved at build time by `data/build.ts`, never at run time, because + * locale aware comparison is the one thing the seven targets cannot agree on. + */ +export type Dataset = { + rows: readonly (readonly string[])[]; + groups: Readonly>; + fullOrder: readonly number[]; +}; + +/** + * Binds a dataset built by `data/build.ts`. Only valid at module level, as a `const`. + * + * @param {string} name - The dataset name, which is the JSON file's basename. + * @returns {Dataset} The dataset. + */ +export const dataset = (name: string): Dataset => + // The compiler replaces every call with the table itself; this body only runs when the + // portable source is executed directly, which the conformance harness never does. + JSON.parse( + readFileSync(new URL(`./${name}.data.json`, import.meta.url), "utf8"), + ) as Dataset; + +/** + * Every row of a dataset, in the baked full order. + * + * @param {Dataset} table - The dataset. + * @returns {string[][]} The rows. + */ +export const dataAll = (table: Dataset): string[][] => + table.fullOrder.map((index) => [...table.rows[index]]); + +/** + * The rows of a dataset whose first column is the key given, in the baked per key order. An + * unknown key, an inherited `Object` property name included, has no rows. + * + * @param {Dataset} table - The dataset. + * @param {string} key - The value of the first column. + * @returns {string[][]} The rows, empty when the key is unknown. + */ +export const dataRows = (table: Dataset, key: string): string[][] => + (Object.hasOwn(table.groups, key) ? table.groups[key] : []).map((index) => [ + ...table.rows[index], + ]); diff --git a/spec/bridge/source/cnpj.ts b/spec/bridge/source/cnpj.ts new file mode 100644 index 000000000..ed28b0a4d --- /dev/null +++ b/spec/bridge/source/cnpj.ts @@ -0,0 +1,211 @@ +/** + * CNPJ, written once. + * + * This is ordinary TypeScript inside the portable subset the bridge accepts: annotated + * parameters and returns, regex literals it compiles rather than passes through, and the same + * boundary guards the handwritten package has. `spec/bridge/README.md` documents the subset; + * the compiler rejects anything outside it instead of guessing. + * + * @see Official: https://www.gov.br/receitafederal/pt-br/assuntos/orientacao-tributaria/cadastros/cnpj + * @see Official: https://www.gov.br/receitafederal/pt-br/centrais-de-conteudo/publicacoes/documentos-tecnicos/cnpj/manual-dv-cnpj.pdf + * @see Official: https://www.gov.br/receitafederal/pt-br/acesso-a-informacao/acoes-e-programas/programas-e-atividades/cnpj-alfanumerico + */ +import { asString, isTruthy } from "./_std.ts"; + +/** Options of `isValidCnpj`. */ +export type IsValidCnpjOptions = { + /** Which CNPJ format to accept: `1` numeric only, `2` alphanumeric (default: `1`). */ + version?: 1 | 2; +}; + +/** Options of `formatCnpj`. */ +export type FormatCnpjOptions = { + /** Whether to left pad the value with zeros up to the number of slots in the pattern (default: `false`). */ + pad?: boolean; + /** Which CNPJ format to read: `1` numeric only, `2` alphanumeric (default: `1`). */ + version?: 1 | 2; + /** Whether to hide the first 2 digits and the 2 check digits with `*` (default: `false`). */ + obfuscate?: boolean; +}; + +const FIRST_DIGIT_WEIGHTS = [5, 4, 3, 2, 9, 8, 7, 6, 5, 4, 3, 2]; +const SECOND_DIGIT_WEIGHTS = [6, 5, 4, 3, 2, 9, 8, 7, 6, 5, 4, 3, 2]; + +const PATTERN = "00.000.000/0000-00"; +const OBFUSCATED_PATTERN = "**.000.000/0000-**"; + +const ALPHANUMERIC_FORMAT = + /^[0-9A-Z]{2}[\s.\-/]*[0-9A-Z]{3}[\s.\-/]*[0-9A-Z]{3}[\s.\-/]*[0-9A-Z]{4}[\s.\-/]*[0-9]{2}$/; +const NUMERIC_FORMAT = /^\d{2}[\s.\-/]*\d{3}[\s.\-/]*\d{3}[\s.\-/]*\d{4}[\s.\-/]*\d{2}$/; +const LETTER = /[A-Z]/; +const NON_ALPHANUMERIC = /[^A-Za-z0-9]/g; +const NON_DIGIT = /\D/g; + +/** Computes one CNPJ check digit from the base and its weight vector. */ +const checkDigit = (base: string, weights: number[]): number => { + let sum = 0; + + for (let index = 0; index < weights.length; index++) { + sum = sum + (base.charCodeAt(index) - 48) * weights[index]; + } + + const remainder = sum % 11; + + if (remainder < 2) { + return 0; + } + + return 11 - remainder; +}; + +/** Whether both check digits of a sanitized 14 character CNPJ match its base. */ +const hasValidChecksum = (cnpj: string): boolean => { + if (cnpj.charCodeAt(12) - 48 !== checkDigit(cnpj, FIRST_DIGIT_WEIGHTS)) { + return false; + } + + return cnpj.charCodeAt(13) - 48 === checkDigit(cnpj, SECOND_DIGIT_WEIGHTS); +}; + +/** Whether every character of the value is the same one. */ +const isRepeated = (value: string): boolean => { + if (value.length === 0) { + return false; + } + + for (let index = 1; index < value.length; index++) { + if (value.charCodeAt(index) !== value.charCodeAt(0)) { + return false; + } + } + + return true; +}; + +/** Lays a value over a pattern: `0` copies a character, `*` hides one, anything else separates. */ +const layout = (value: string, pattern: string, pad: boolean): string => { + let slots = 0; + + for (let index = 0; index < pattern.length; index++) { + if (pattern.charCodeAt(index) === 48 || pattern.charCodeAt(index) === 42) { + slots = slots + 1; + } + } + + let padded = value; + + if (pad) { + padded = value.padStart(slots, "0"); + } + + let formatted = ""; + let cursor = 0; + + for (let index = 0; index < pattern.length; index++) { + const slot = pattern.charCodeAt(index); + + if (slot === 48 || slot === 42) { + if (cursor >= padded.length) { + return formatted; + } + + if (slot === 42) { + formatted = formatted + "*"; + } else { + formatted = formatted + padded.slice(cursor, cursor + 1); + } + + cursor = cursor + 1; + } else if (cursor < padded.length) { + formatted = formatted + pattern.slice(index, index + 1); + } + } + + return formatted; +}; + +/** + * Validates if a CNPJ (Cadastro Nacional da Pessoa Jurídica) is valid. + * + * Supports both numeric (version 1) and alphanumeric (version 2) CNPJ formats, and accepts the + * usual mask characters (`.`, `-`, `/`) and whitespace around and between groups. + * + * @param {string} cnpj - The CNPJ value to be validated. + * @param {IsValidCnpjOptions} [options] - Optional options. + * @returns {boolean} True if the CNPJ is valid, false otherwise. + * + * @example + * ```typescript + * isValidCnpj("12.345.678/0001-95"); // true + * isValidCnpj("q0slfmbd7vx439", { version: 2 }); // true + * isValidCnpj("00000000000000"); // false (reserved number) + * ``` + */ +export const isValidCnpj = (cnpj: string, options?: IsValidCnpjOptions): boolean => { + if (typeof cnpj !== "string") { + return false; + } + + const trimmed = cnpj.trim(); + + if (options?.version === 2) { + const cleaned = cnpj.replaceAll(NON_ALPHANUMERIC, "").toUpperCase(); + + if (LETTER.test(cleaned)) { + if (!ALPHANUMERIC_FORMAT.test(trimmed.toUpperCase())) { + return false; + } + + return hasValidChecksum(cleaned); + } + } + + const numeric = cnpj.replaceAll(NON_DIGIT, ""); + + if (!NUMERIC_FORMAT.test(trimmed)) { + return false; + } + + if (isRepeated(numeric)) { + return false; + } + + return hasValidChecksum(numeric); +}; + +/** + * Formats a given CNPJ (Cadastro Nacional da Pessoa Jurídica) value. + * + * @param {string} value - The CNPJ value to be formatted. + * @param {FormatCnpjOptions} [options] - Optional configuration for formatting the CNPJ. + * @returns {string} The formatted CNPJ string in the pattern "00.000.000/0000-00". + * + * @example + * ```typescript + * formatCnpj("12345678000195"); // "12.345.678/0001-95" + * formatCnpj("12345678", { pad: true }); // "00.000.012/3456-78" + * formatCnpj("q0SLFMBD7VX439", { version: 2 }); // "Q0.SLF.MBD/7VX4-39" + * formatCnpj("12345678000195", { obfuscate: true }); // "**.345.678/0001-**" + * ``` + */ +export const formatCnpj = (value: string | number, options?: FormatCnpjOptions): string => { + if (value === null || value === undefined) { + return ""; + } + + const text = asString(value); + + let cleaned = text.replaceAll(NON_DIGIT, ""); + + if (options?.version === 2) { + cleaned = text.replaceAll(NON_ALPHANUMERIC, "").toUpperCase(); + } + + let pattern = PATTERN; + + if (isTruthy(options?.obfuscate)) { + pattern = OBFUSCATED_PATTERN; + } + + return layout(cleaned, pattern, isTruthy(options?.pad)); +}; diff --git a/spec/bridge/source/municipalities.data.json b/spec/bridge/source/municipalities.data.json new file mode 100644 index 000000000..5e3a44875 --- /dev/null +++ b/spec/bridge/source/municipalities.data.json @@ -0,0 +1 @@ +{"doc":"Brazilian municipalities published by the IBGE, by state, in the pt-BR collation order the JavaScript package returns.","columns":["stateCode","name","code"],"rows":[["AC","Acrelândia","1200013"],["AC","Assis Brasil","1200054"],["AC","Brasiléia","1200104"],["AC","Bujari","1200138"],["AC","Capixaba","1200179"],["AC","Cruzeiro do Sul","1200203"],["AC","Epitaciolândia","1200252"],["AC","Feijó","1200302"],["AC","Jordão","1200328"],["AC","Mâncio Lima","1200336"],["AC","Manoel Urbano","1200344"],["AC","Marechal Thaumaturgo","1200351"],["AC","Plácido de Castro","1200385"],["AC","Porto Acre","1200807"],["AC","Porto Walter","1200393"],["AC","Rio Branco","1200401"],["AC","Rodrigues Alves","1200427"],["AC","Santa Rosa do Purus","1200435"],["AC","Sena Madureira","1200500"],["AC","Senador Guiomard","1200450"],["AC","Tarauacá","1200609"],["AC","Xapuri","1200708"],["AL","Água Branca","2700102"],["AL","Anadia","2700201"],["AL","Arapiraca","2700300"],["AL","Atalaia","2700409"],["AL","Barra de Santo Antônio","2700508"],["AL","Barra de São Miguel","2700607"],["AL","Batalha","2700706"],["AL","Belém","2700805"],["AL","Belo Monte","2700904"],["AL","Boca da Mata","2701001"],["AL","Branquinha","2701100"],["AL","Cacimbinhas","2701209"],["AL","Cajueiro","2701308"],["AL","Campestre","2701357"],["AL","Campo Alegre","2701407"],["AL","Campo Grande","2701506"],["AL","Canapi","2701605"],["AL","Capela","2701704"],["AL","Carneiros","2701803"],["AL","Chã Preta","2701902"],["AL","Coité do Nóia","2702009"],["AL","Colônia Leopoldina","2702108"],["AL","Coqueiro Seco","2702207"],["AL","Coruripe","2702306"],["AL","Craíbas","2702355"],["AL","Delmiro Gouveia","2702405"],["AL","Dois Riachos","2702504"],["AL","Estrela de Alagoas","2702553"],["AL","Feira Grande","2702603"],["AL","Feliz Deserto","2702702"],["AL","Flexeiras","2702801"],["AL","Girau do Ponciano","2702900"],["AL","Ibateguara","2703007"],["AL","Igaci","2703106"],["AL","Igreja Nova","2703205"],["AL","Inhapi","2703304"],["AL","Jacaré dos Homens","2703403"],["AL","Jacuípe","2703502"],["AL","Japaratinga","2703601"],["AL","Jaramataia","2703700"],["AL","Jequiá da Praia","2703759"],["AL","Joaquim Gomes","2703809"],["AL","Jundiá","2703908"],["AL","Junqueiro","2704005"],["AL","Lagoa da Canoa","2704104"],["AL","Limoeiro de Anadia","2704203"],["AL","Maceió","2704302"],["AL","Major Isidoro","2704401"],["AL","Mar Vermelho","2704906"],["AL","Maragogi","2704500"],["AL","Maravilha","2704609"],["AL","Marechal Deodoro","2704708"],["AL","Maribondo","2704807"],["AL","Mata Grande","2705002"],["AL","Matriz de Camaragibe","2705101"],["AL","Messias","2705200"],["AL","Minador do Negrão","2705309"],["AL","Monteirópolis","2705408"],["AL","Murici","2705507"],["AL","Novo Lino","2705606"],["AL","Olho d'Água das Flores","2705705"],["AL","Olho d'Água do Casado","2705804"],["AL","Olho d'Água Grande","2705903"],["AL","Olivença","2706000"],["AL","Ouro Branco","2706109"],["AL","Palestina","2706208"],["AL","Palmeira dos Índios","2706307"],["AL","Pão de Açúcar","2706406"],["AL","Pariconha","2706422"],["AL","Paripueira","2706448"],["AL","Passo de Camaragibe","2706505"],["AL","Paulo Jacinto","2706604"],["AL","Penedo","2706703"],["AL","Piaçabuçu","2706802"],["AL","Pilar","2706901"],["AL","Pindoba","2707008"],["AL","Piranhas","2707107"],["AL","Poço das Trincheiras","2707206"],["AL","Porto Calvo","2707305"],["AL","Porto de Pedras","2707404"],["AL","Porto Real do Colégio","2707503"],["AL","Quebrangulo","2707602"],["AL","Rio Largo","2707701"],["AL","Roteiro","2707800"],["AL","Santa Luzia do Norte","2707909"],["AL","Santana do Ipanema","2708006"],["AL","Santana do Mundaú","2708105"],["AL","São Brás","2708204"],["AL","São José da Laje","2708303"],["AL","São José da Tapera","2708402"],["AL","São Luís do Quitunde","2708501"],["AL","São Miguel dos Campos","2708600"],["AL","São Miguel dos Milagres","2708709"],["AL","São Sebastião","2708808"],["AL","Satuba","2708907"],["AL","Senador Rui Palmeira","2708956"],["AL","Tanque d'Arca","2709004"],["AL","Taquarana","2709103"],["AL","Teotônio Vilela","2709152"],["AL","Traipu","2709202"],["AL","União dos Palmares","2709301"],["AL","Viçosa","2709400"],["AP","Amapá","1600105"],["AP","Calçoene","1600204"],["AP","Cutias","1600212"],["AP","Ferreira Gomes","1600238"],["AP","Itaubal","1600253"],["AP","Laranjal do Jari","1600279"],["AP","Macapá","1600303"],["AP","Mazagão","1600402"],["AP","Oiapoque","1600501"],["AP","Pedra Branca do Amapari","1600154"],["AP","Porto Grande","1600535"],["AP","Pracuúba","1600550"],["AP","Santana","1600600"],["AP","Serra do Navio","1600055"],["AP","Tartarugalzinho","1600709"],["AP","Vitória do Jari","1600808"],["AM","Alvarães","1300029"],["AM","Amaturá","1300060"],["AM","Anamã","1300086"],["AM","Anori","1300102"],["AM","Apuí","1300144"],["AM","Atalaia do Norte","1300201"],["AM","Autazes","1300300"],["AM","Barcelos","1300409"],["AM","Barreirinha","1300508"],["AM","Benjamin Constant","1300607"],["AM","Beruri","1300631"],["AM","Boa Vista do Ramos","1300680"],["AM","Boca do Acre","1300706"],["AM","Borba","1300805"],["AM","Caapiranga","1300839"],["AM","Canutama","1300904"],["AM","Carauari","1301001"],["AM","Careiro","1301100"],["AM","Careiro da Várzea","1301159"],["AM","Coari","1301209"],["AM","Codajás","1301308"],["AM","Eirunepé","1301407"],["AM","Envira","1301506"],["AM","Fonte Boa","1301605"],["AM","Guajará","1301654"],["AM","Humaitá","1301704"],["AM","Ipixuna","1301803"],["AM","Iranduba","1301852"],["AM","Itacoatiara","1301902"],["AM","Itamarati","1301951"],["AM","Itapiranga","1302009"],["AM","Japurá","1302108"],["AM","Juruá","1302207"],["AM","Jutaí","1302306"],["AM","Lábrea","1302405"],["AM","Manacapuru","1302504"],["AM","Manaquiri","1302553"],["AM","Manaus","1302603"],["AM","Manicoré","1302702"],["AM","Maraã","1302801"],["AM","Maués","1302900"],["AM","Nhamundá","1303007"],["AM","Nova Olinda do Norte","1303106"],["AM","Novo Airão","1303205"],["AM","Novo Aripuanã","1303304"],["AM","Parintins","1303403"],["AM","Pauini","1303502"],["AM","Presidente Figueiredo","1303536"],["AM","Rio Preto da Eva","1303569"],["AM","Santa Isabel do Rio Negro","1303601"],["AM","Santo Antônio do Içá","1303700"],["AM","São Gabriel da Cachoeira","1303809"],["AM","São Paulo de Olivença","1303908"],["AM","São Sebastião do Uatumã","1303957"],["AM","Silves","1304005"],["AM","Tabatinga","1304062"],["AM","Tapauá","1304104"],["AM","Tefé","1304203"],["AM","Tonantins","1304237"],["AM","Uarini","1304260"],["AM","Urucará","1304302"],["AM","Urucurituba","1304401"],["BA","Abaíra","2900108"],["BA","Abaré","2900207"],["BA","Acajutiba","2900306"],["BA","Adustina","2900355"],["BA","Água Fria","2900405"],["BA","Aiquara","2900603"],["BA","Alagoinhas","2900702"],["BA","Alcobaça","2900801"],["BA","Almadina","2900900"],["BA","Amargosa","2901007"],["BA","Amélia Rodrigues","2901106"],["BA","América Dourada","2901155"],["BA","Anagé","2901205"],["BA","Andaraí","2901304"],["BA","Andorinha","2901353"],["BA","Angical","2901403"],["BA","Anguera","2901502"],["BA","Antas","2901601"],["BA","Antônio Cardoso","2901700"],["BA","Antônio Gonçalves","2901809"],["BA","Aporá","2901908"],["BA","Apuarema","2901957"],["BA","Araçás","2902054"],["BA","Aracatu","2902005"],["BA","Araci","2902104"],["BA","Aramari","2902203"],["BA","Arataca","2902252"],["BA","Aratuípe","2902302"],["BA","Aurelino Leal","2902401"],["BA","Baianópolis","2902500"],["BA","Baixa Grande","2902609"],["BA","Banzaê","2902658"],["BA","Barra","2902708"],["BA","Barra da Estiva","2902807"],["BA","Barra do Choça","2902906"],["BA","Barra do Mendes","2903003"],["BA","Barra do Rocha","2903102"],["BA","Barreiras","2903201"],["BA","Barro Alto","2903235"],["BA","Barro Preto","2903300"],["BA","Barrocas","2903276"],["BA","Belmonte","2903409"],["BA","Belo Campo","2903508"],["BA","Biritinga","2903607"],["BA","Boa Nova","2903706"],["BA","Boa Vista do Tupim","2903805"],["BA","Bom Jesus da Lapa","2903904"],["BA","Bom Jesus da Serra","2903953"],["BA","Boninal","2904001"],["BA","Bonito","2904050"],["BA","Boquira","2904100"],["BA","Botuporã","2904209"],["BA","Brejões","2904308"],["BA","Brejolândia","2904407"],["BA","Brotas de Macaúbas","2904506"],["BA","Brumado","2904605"],["BA","Buerarema","2904704"],["BA","Buritirama","2904753"],["BA","Caatiba","2904803"],["BA","Cabaceiras do Paraguaçu","2904852"],["BA","Cachoeira","2904902"],["BA","Caculé","2905008"],["BA","Caém","2905107"],["BA","Caetanos","2905156"],["BA","Caetité","2905206"],["BA","Cafarnaum","2905305"],["BA","Cairu","2905404"],["BA","Caldeirão Grande","2905503"],["BA","Camacan","2905602"],["BA","Camaçari","2905701"],["BA","Camamu","2905800"],["BA","Campo Alegre de Lourdes","2905909"],["BA","Campo Formoso","2906006"],["BA","Canápolis","2906105"],["BA","Canarana","2906204"],["BA","Canavieiras","2906303"],["BA","Candeal","2906402"],["BA","Candeias","2906501"],["BA","Candiba","2906600"],["BA","Cândido Sales","2906709"],["BA","Cansanção","2906808"],["BA","Canudos","2906824"],["BA","Capela do Alto Alegre","2906857"],["BA","Capim Grosso","2906873"],["BA","Caraíbas","2906899"],["BA","Caravelas","2906907"],["BA","Cardeal da Silva","2907004"],["BA","Carinhanha","2907103"],["BA","Casa Nova","2907202"],["BA","Castro Alves","2907301"],["BA","Catolândia","2907400"],["BA","Catu","2907509"],["BA","Caturama","2907558"],["BA","Central","2907608"],["BA","Chorrochó","2907707"],["BA","Cícero Dantas","2907806"],["BA","Cipó","2907905"],["BA","Coaraci","2908002"],["BA","Cocos","2908101"],["BA","Conceição da Feira","2908200"],["BA","Conceição do Almeida","2908309"],["BA","Conceição do Coité","2908408"],["BA","Conceição do Jacuípe","2908507"],["BA","Conde","2908606"],["BA","Condeúba","2908705"],["BA","Contendas do Sincorá","2908804"],["BA","Coração de Maria","2908903"],["BA","Cordeiros","2909000"],["BA","Coribe","2909109"],["BA","Coronel João Sá","2909208"],["BA","Correntina","2909307"],["BA","Cotegipe","2909406"],["BA","Cravolândia","2909505"],["BA","Crisópolis","2909604"],["BA","Cristópolis","2909703"],["BA","Cruz das Almas","2909802"],["BA","Curaçá","2909901"],["BA","Dário Meira","2910008"],["BA","Dias d'Ávila","2910057"],["BA","Dom Basílio","2910107"],["BA","Dom Macedo Costa","2910206"],["BA","Elísio Medrado","2910305"],["BA","Encruzilhada","2910404"],["BA","Entre Rios","2910503"],["BA","Érico Cardoso","2900504"],["BA","Esplanada","2910602"],["BA","Euclides da Cunha","2910701"],["BA","Eunápolis","2910727"],["BA","Fátima","2910750"],["BA","Feira da Mata","2910776"],["BA","Feira de Santana","2910800"],["BA","Filadélfia","2910859"],["BA","Firmino Alves","2910909"],["BA","Floresta Azul","2911006"],["BA","Formosa do Rio Preto","2911105"],["BA","Gandu","2911204"],["BA","Gavião","2911253"],["BA","Gentio do Ouro","2911303"],["BA","Glória","2911402"],["BA","Gongogi","2911501"],["BA","Governador Mangabeira","2911600"],["BA","Guajeru","2911659"],["BA","Guanambi","2911709"],["BA","Guaratinga","2911808"],["BA","Heliópolis","2911857"],["BA","Iaçu","2911907"],["BA","Ibiassucê","2912004"],["BA","Ibicaraí","2912103"],["BA","Ibicoara","2912202"],["BA","Ibicuí","2912301"],["BA","Ibipeba","2912400"],["BA","Ibipitanga","2912509"],["BA","Ibiquera","2912608"],["BA","Ibirapitanga","2912707"],["BA","Ibirapuã","2912806"],["BA","Ibirataia","2912905"],["BA","Ibitiara","2913002"],["BA","Ibititá","2913101"],["BA","Ibotirama","2913200"],["BA","Ichu","2913309"],["BA","Igaporã","2913408"],["BA","Igrapiúna","2913457"],["BA","Iguaí","2913507"],["BA","Ilhéus","2913606"],["BA","Inhambupe","2913705"],["BA","Ipecaetá","2913804"],["BA","Ipiaú","2913903"],["BA","Ipirá","2914000"],["BA","Ipupiara","2914109"],["BA","Irajuba","2914208"],["BA","Iramaia","2914307"],["BA","Iraquara","2914406"],["BA","Irará","2914505"],["BA","Irecê","2914604"],["BA","Itabela","2914653"],["BA","Itaberaba","2914703"],["BA","Itabuna","2914802"],["BA","Itacaré","2914901"],["BA","Itaeté","2915007"],["BA","Itagi","2915106"],["BA","Itagibá","2915205"],["BA","Itagimirim","2915304"],["BA","Itaguaçu da Bahia","2915353"],["BA","Itaju do Colônia","2915403"],["BA","Itajuípe","2915502"],["BA","Itamaraju","2915601"],["BA","Itamari","2915700"],["BA","Itambé","2915809"],["BA","Itanagra","2915908"],["BA","Itanhém","2916005"],["BA","Itaparica","2916104"],["BA","Itapé","2916203"],["BA","Itapebi","2916302"],["BA","Itapetinga","2916401"],["BA","Itapicuru","2916500"],["BA","Itapitanga","2916609"],["BA","Itaquara","2916708"],["BA","Itarantim","2916807"],["BA","Itatim","2916856"],["BA","Itiruçu","2916906"],["BA","Itiúba","2917003"],["BA","Itororó","2917102"],["BA","Ituaçu","2917201"],["BA","Ituberá","2917300"],["BA","Iuiu","2917334"],["BA","Jaborandi","2917359"],["BA","Jacaraci","2917409"],["BA","Jacobina","2917508"],["BA","Jaguaquara","2917607"],["BA","Jaguarari","2917706"],["BA","Jaguaripe","2917805"],["BA","Jandaíra","2917904"],["BA","Jequié","2918001"],["BA","Jeremoabo","2918100"],["BA","Jiquiriçá","2918209"],["BA","Jitaúna","2918308"],["BA","João Dourado","2918357"],["BA","Juazeiro","2918407"],["BA","Jucuruçu","2918456"],["BA","Jussara","2918506"],["BA","Jussari","2918555"],["BA","Jussiape","2918605"],["BA","Lafaiete Coutinho","2918704"],["BA","Lagoa Real","2918753"],["BA","Laje","2918803"],["BA","Lajedão","2918902"],["BA","Lajedinho","2919009"],["BA","Lajedo do Tabocal","2919058"],["BA","Lamarão","2919108"],["BA","Lapão","2919157"],["BA","Lauro de Freitas","2919207"],["BA","Lençóis","2919306"],["BA","Licínio de Almeida","2919405"],["BA","Livramento de Nossa Senhora","2919504"],["BA","Luís Eduardo Magalhães","2919553"],["BA","Macajuba","2919603"],["BA","Macarani","2919702"],["BA","Macaúbas","2919801"],["BA","Macururé","2919900"],["BA","Madre de Deus","2919926"],["BA","Maetinga","2919959"],["BA","Maiquinique","2920007"],["BA","Mairi","2920106"],["BA","Malhada","2920205"],["BA","Malhada de Pedras","2920304"],["BA","Manoel Vitorino","2920403"],["BA","Mansidão","2920452"],["BA","Maracás","2920502"],["BA","Maragogipe","2920601"],["BA","Maraú","2920700"],["BA","Marcionílio Souza","2920809"],["BA","Mascote","2920908"],["BA","Mata de São João","2921005"],["BA","Matina","2921054"],["BA","Medeiros Neto","2921104"],["BA","Miguel Calmon","2921203"],["BA","Milagres","2921302"],["BA","Mirangaba","2921401"],["BA","Mirante","2921450"],["BA","Monte Santo","2921500"],["BA","Morpará","2921609"],["BA","Morro do Chapéu","2921708"],["BA","Mortugaba","2921807"],["BA","Mucugê","2921906"],["BA","Mucuri","2922003"],["BA","Mulungu do Morro","2922052"],["BA","Mundo Novo","2922102"],["BA","Muniz Ferreira","2922201"],["BA","Muquém do São Francisco","2922250"],["BA","Muritiba","2922300"],["BA","Mutuípe","2922409"],["BA","Nazaré","2922508"],["BA","Nilo Peçanha","2922607"],["BA","Nordestina","2922656"],["BA","Nova Canaã","2922706"],["BA","Nova Fátima","2922730"],["BA","Nova Ibiá","2922755"],["BA","Nova Itarana","2922805"],["BA","Nova Redenção","2922854"],["BA","Nova Soure","2922904"],["BA","Nova Viçosa","2923001"],["BA","Novo Horizonte","2923035"],["BA","Novo Triunfo","2923050"],["BA","Olindina","2923100"],["BA","Oliveira dos Brejinhos","2923209"],["BA","Ouriçangas","2923308"],["BA","Ourolândia","2923357"],["BA","Palmas de Monte Alto","2923407"],["BA","Palmeiras","2923506"],["BA","Paramirim","2923605"],["BA","Paratinga","2923704"],["BA","Paripiranga","2923803"],["BA","Pau Brasil","2923902"],["BA","Paulo Afonso","2924009"],["BA","Pé de Serra","2924058"],["BA","Pedrão","2924108"],["BA","Pedro Alexandre","2924207"],["BA","Piatã","2924306"],["BA","Pilão Arcado","2924405"],["BA","Pindaí","2924504"],["BA","Pindobaçu","2924603"],["BA","Pintadas","2924652"],["BA","Piraí do Norte","2924678"],["BA","Piripá","2924702"],["BA","Piritiba","2924801"],["BA","Planaltino","2924900"],["BA","Planalto","2925006"],["BA","Poções","2925105"],["BA","Pojuca","2925204"],["BA","Ponto Novo","2925253"],["BA","Porto Seguro","2925303"],["BA","Potiraguá","2925402"],["BA","Prado","2925501"],["BA","Presidente Dutra","2925600"],["BA","Presidente Jânio Quadros","2925709"],["BA","Presidente Tancredo Neves","2925758"],["BA","Queimadas","2925808"],["BA","Quijingue","2925907"],["BA","Quixabeira","2925931"],["BA","Rafael Jambeiro","2925956"],["BA","Remanso","2926004"],["BA","Retirolândia","2926103"],["BA","Riachão das Neves","2926202"],["BA","Riachão do Jacuípe","2926301"],["BA","Riacho de Santana","2926400"],["BA","Ribeira do Amparo","2926509"],["BA","Ribeira do Pombal","2926608"],["BA","Ribeirão do Largo","2926657"],["BA","Rio de Contas","2926707"],["BA","Rio do Antônio","2926806"],["BA","Rio do Pires","2926905"],["BA","Rio Real","2927002"],["BA","Rodelas","2927101"],["BA","Ruy Barbosa","2927200"],["BA","Salinas da Margarida","2927309"],["BA","Salvador","2927408"],["BA","Santa Bárbara","2927507"],["BA","Santa Brígida","2927606"],["BA","Santa Cruz Cabrália","2927705"],["BA","Santa Cruz da Vitória","2927804"],["BA","Santa Inês","2927903"],["BA","Santa Luzia","2928059"],["BA","Santa Maria da Vitória","2928109"],["BA","Santa Rita de Cássia","2928406"],["BA","Santa Terezinha","2928505"],["BA","Santaluz","2928000"],["BA","Santana","2928208"],["BA","Santanópolis","2928307"],["BA","Santo Amaro","2928604"],["BA","Santo Antônio de Jesus","2928703"],["BA","Santo Estêvão","2928802"],["BA","São Desidério","2928901"],["BA","São Domingos","2928950"],["BA","São Felipe","2929107"],["BA","São Félix","2929008"],["BA","São Félix do Coribe","2929057"],["BA","São Francisco do Conde","2929206"],["BA","São Gabriel","2929255"],["BA","São Gonçalo dos Campos","2929305"],["BA","São José da Vitória","2929354"],["BA","São José do Jacuípe","2929370"],["BA","São Miguel das Matas","2929404"],["BA","São Sebastião do Passé","2929503"],["BA","Sapeaçu","2929602"],["BA","Sátiro Dias","2929701"],["BA","Saubara","2929750"],["BA","Saúde","2929800"],["BA","Seabra","2929909"],["BA","Sebastião Laranjeiras","2930006"],["BA","Senhor do Bonfim","2930105"],["BA","Sento Sé","2930204"],["BA","Serra do Ramalho","2930154"],["BA","Serra Dourada","2930303"],["BA","Serra Preta","2930402"],["BA","Serrinha","2930501"],["BA","Serrolândia","2930600"],["BA","Simões Filho","2930709"],["BA","Sítio do Mato","2930758"],["BA","Sítio do Quinto","2930766"],["BA","Sobradinho","2930774"],["BA","Souto Soares","2930808"],["BA","Tabocas do Brejo Velho","2930907"],["BA","Tanhaçu","2931004"],["BA","Tanque Novo","2931053"],["BA","Tanquinho","2931103"],["BA","Taperoá","2931202"],["BA","Tapiramutá","2931301"],["BA","Teixeira de Freitas","2931350"],["BA","Teodoro Sampaio","2931400"],["BA","Teofilândia","2931509"],["BA","Teolândia","2931608"],["BA","Terra Nova","2931707"],["BA","Tremedal","2931806"],["BA","Tucano","2931905"],["BA","Uauá","2932002"],["BA","Ubaíra","2932101"],["BA","Ubaitaba","2932200"],["BA","Ubatã","2932309"],["BA","Uibaí","2932408"],["BA","Umburanas","2932457"],["BA","Una","2932507"],["BA","Urandi","2932606"],["BA","Uruçuca","2932705"],["BA","Utinga","2932804"],["BA","Valença","2932903"],["BA","Valente","2933000"],["BA","Várzea da Roça","2933059"],["BA","Várzea do Poço","2933109"],["BA","Várzea Nova","2933158"],["BA","Varzedo","2933174"],["BA","Vera Cruz","2933208"],["BA","Vereda","2933257"],["BA","Vitória da Conquista","2933307"],["BA","Wagner","2933406"],["BA","Wanderley","2933455"],["BA","Wenceslau Guimarães","2933505"],["BA","Xique-Xique","2933604"],["CE","Abaiara","2300101"],["CE","Acarape","2300150"],["CE","Acaraú","2300200"],["CE","Acopiara","2300309"],["CE","Aiuaba","2300408"],["CE","Alcântaras","2300507"],["CE","Altaneira","2300606"],["CE","Alto Santo","2300705"],["CE","Amontada","2300754"],["CE","Antonina do Norte","2300804"],["CE","Apuiarés","2300903"],["CE","Aquiraz","2301000"],["CE","Aracati","2301109"],["CE","Aracoiaba","2301208"],["CE","Ararendá","2301257"],["CE","Araripe","2301307"],["CE","Aratuba","2301406"],["CE","Arneiroz","2301505"],["CE","Assaré","2301604"],["CE","Aurora","2301703"],["CE","Baixio","2301802"],["CE","Banabuiú","2301851"],["CE","Barbalha","2301901"],["CE","Barreira","2301950"],["CE","Barro","2302008"],["CE","Barroquinha","2302057"],["CE","Baturité","2302107"],["CE","Beberibe","2302206"],["CE","Bela Cruz","2302305"],["CE","Boa Viagem","2302404"],["CE","Brejo Santo","2302503"],["CE","Camocim","2302602"],["CE","Campos Sales","2302701"],["CE","Canindé","2302800"],["CE","Capistrano","2302909"],["CE","Caridade","2303006"],["CE","Cariré","2303105"],["CE","Caririaçu","2303204"],["CE","Cariús","2303303"],["CE","Carnaubal","2303402"],["CE","Cascavel","2303501"],["CE","Catarina","2303600"],["CE","Catunda","2303659"],["CE","Caucaia","2303709"],["CE","Cedro","2303808"],["CE","Chaval","2303907"],["CE","Choró","2303931"],["CE","Chorozinho","2303956"],["CE","Coreaú","2304004"],["CE","Crateús","2304103"],["CE","Crato","2304202"],["CE","Croatá","2304236"],["CE","Cruz","2304251"],["CE","Deputado Irapuan Pinheiro","2304269"],["CE","Ereré","2304277"],["CE","Eusébio","2304285"],["CE","Farias Brito","2304301"],["CE","Forquilha","2304350"],["CE","Fortaleza","2304400"],["CE","Fortim","2304459"],["CE","Frecheirinha","2304509"],["CE","General Sampaio","2304608"],["CE","Graça","2304657"],["CE","Granja","2304707"],["CE","Granjeiro","2304806"],["CE","Groaíras","2304905"],["CE","Guaiúba","2304954"],["CE","Guaraciaba do Norte","2305001"],["CE","Guaramiranga","2305100"],["CE","Hidrolândia","2305209"],["CE","Horizonte","2305233"],["CE","Ibaretama","2305266"],["CE","Ibiapina","2305308"],["CE","Ibicuitinga","2305332"],["CE","Icapuí","2305357"],["CE","Icó","2305407"],["CE","Iguatu","2305506"],["CE","Independência","2305605"],["CE","Ipaporanga","2305654"],["CE","Ipaumirim","2305704"],["CE","Ipu","2305803"],["CE","Ipueiras","2305902"],["CE","Iracema","2306009"],["CE","Irauçuba","2306108"],["CE","Itaiçaba","2306207"],["CE","Itaitinga","2306256"],["CE","Itapajé","2306306"],["CE","Itapipoca","2306405"],["CE","Itapiúna","2306504"],["CE","Itarema","2306553"],["CE","Itatira","2306603"],["CE","Jaguaretama","2306702"],["CE","Jaguaribara","2306801"],["CE","Jaguaribe","2306900"],["CE","Jaguaruana","2307007"],["CE","Jardim","2307106"],["CE","Jati","2307205"],["CE","Jijoca de Jericoacoara","2307254"],["CE","Juazeiro do Norte","2307304"],["CE","Jucás","2307403"],["CE","Lavras da Mangabeira","2307502"],["CE","Limoeiro do Norte","2307601"],["CE","Madalena","2307635"],["CE","Maracanaú","2307650"],["CE","Maranguape","2307700"],["CE","Marco","2307809"],["CE","Martinópole","2307908"],["CE","Massapê","2308005"],["CE","Mauriti","2308104"],["CE","Meruoca","2308203"],["CE","Milagres","2308302"],["CE","Milhã","2308351"],["CE","Miraíma","2308377"],["CE","Missão Velha","2308401"],["CE","Mombaça","2308500"],["CE","Monsenhor Tabosa","2308609"],["CE","Morada Nova","2308708"],["CE","Moraújo","2308807"],["CE","Morrinhos","2308906"],["CE","Mucambo","2309003"],["CE","Mulungu","2309102"],["CE","Nova Olinda","2309201"],["CE","Nova Russas","2309300"],["CE","Novo Oriente","2309409"],["CE","Ocara","2309458"],["CE","Orós","2309508"],["CE","Pacajus","2309607"],["CE","Pacatuba","2309706"],["CE","Pacoti","2309805"],["CE","Pacujá","2309904"],["CE","Palhano","2310001"],["CE","Palmácia","2310100"],["CE","Paracuru","2310209"],["CE","Paraipaba","2310258"],["CE","Parambu","2310308"],["CE","Paramoti","2310407"],["CE","Pedra Branca","2310506"],["CE","Penaforte","2310605"],["CE","Pentecoste","2310704"],["CE","Pereiro","2310803"],["CE","Pindoretama","2310852"],["CE","Piquet Carneiro","2310902"],["CE","Pires Ferreira","2310951"],["CE","Poranga","2311009"],["CE","Porteiras","2311108"],["CE","Potengi","2311207"],["CE","Potiretama","2311231"],["CE","Quiterianópolis","2311264"],["CE","Quixadá","2311306"],["CE","Quixelô","2311355"],["CE","Quixeramobim","2311405"],["CE","Quixeré","2311504"],["CE","Redenção","2311603"],["CE","Reriutaba","2311702"],["CE","Russas","2311801"],["CE","Saboeiro","2311900"],["CE","Salitre","2311959"],["CE","Santa Quitéria","2312205"],["CE","Santana do Acaraú","2312007"],["CE","Santana do Cariri","2312106"],["CE","São Benedito","2312304"],["CE","São Gonçalo do Amarante","2312403"],["CE","São João do Jaguaribe","2312502"],["CE","São Luís do Curu","2312601"],["CE","Senador Pompeu","2312700"],["CE","Senador Sá","2312809"],["CE","Sobral","2312908"],["CE","Solonópole","2313005"],["CE","Tabuleiro do Norte","2313104"],["CE","Tamboril","2313203"],["CE","Tarrafas","2313252"],["CE","Tauá","2313302"],["CE","Tejuçuoca","2313351"],["CE","Tianguá","2313401"],["CE","Trairi","2313500"],["CE","Tururu","2313559"],["CE","Ubajara","2313609"],["CE","Umari","2313708"],["CE","Umirim","2313757"],["CE","Uruburetama","2313807"],["CE","Uruoca","2313906"],["CE","Varjota","2313955"],["CE","Várzea Alegre","2314003"],["CE","Viçosa do Ceará","2314102"],["DF","Brasília","5300108"],["ES","Afonso Cláudio","3200102"],["ES","Água Doce do Norte","3200169"],["ES","Águia Branca","3200136"],["ES","Alegre","3200201"],["ES","Alfredo Chaves","3200300"],["ES","Alto Rio Novo","3200359"],["ES","Anchieta","3200409"],["ES","Apiacá","3200508"],["ES","Aracruz","3200607"],["ES","Atílio Vivácqua","3200706"],["ES","Baixo Guandu","3200805"],["ES","Barra de São Francisco","3200904"],["ES","Boa Esperança","3201001"],["ES","Bom Jesus do Norte","3201100"],["ES","Brejetuba","3201159"],["ES","Cachoeiro de Itapemirim","3201209"],["ES","Cariacica","3201308"],["ES","Castelo","3201407"],["ES","Colatina","3201506"],["ES","Conceição da Barra","3201605"],["ES","Conceição do Castelo","3201704"],["ES","Divino de São Lourenço","3201803"],["ES","Domingos Martins","3201902"],["ES","Dores do Rio Preto","3202009"],["ES","Ecoporanga","3202108"],["ES","Fundão","3202207"],["ES","Governador Lindenberg","3202256"],["ES","Guaçuí","3202306"],["ES","Guarapari","3202405"],["ES","Ibatiba","3202454"],["ES","Ibiraçu","3202504"],["ES","Ibitirama","3202553"],["ES","Iconha","3202603"],["ES","Irupi","3202652"],["ES","Itaguaçu","3202702"],["ES","Itapemirim","3202801"],["ES","Itarana","3202900"],["ES","Iúna","3203007"],["ES","Jaguaré","3203056"],["ES","Jerônimo Monteiro","3203106"],["ES","João Neiva","3203130"],["ES","Laranja da Terra","3203163"],["ES","Linhares","3203205"],["ES","Mantenópolis","3203304"],["ES","Marataízes","3203320"],["ES","Marechal Floriano","3203346"],["ES","Marilândia","3203353"],["ES","Mimoso do Sul","3203403"],["ES","Montanha","3203502"],["ES","Mucurici","3203601"],["ES","Muniz Freire","3203700"],["ES","Muqui","3203809"],["ES","Nova Venécia","3203908"],["ES","Pancas","3204005"],["ES","Pedro Canário","3204054"],["ES","Pinheiros","3204104"],["ES","Piúma","3204203"],["ES","Ponto Belo","3204252"],["ES","Presidente Kennedy","3204302"],["ES","Rio Bananal","3204351"],["ES","Rio Novo do Sul","3204401"],["ES","Santa Leopoldina","3204500"],["ES","Santa Maria de Jetibá","3204559"],["ES","Santa Teresa","3204609"],["ES","São Domingos do Norte","3204658"],["ES","São Gabriel da Palha","3204708"],["ES","São José do Calçado","3204807"],["ES","São Mateus","3204906"],["ES","São Roque do Canaã","3204955"],["ES","Serra","3205002"],["ES","Sooretama","3205010"],["ES","Vargem Alta","3205036"],["ES","Venda Nova do Imigrante","3205069"],["ES","Viana","3205101"],["ES","Vila Pavão","3205150"],["ES","Vila Valério","3205176"],["ES","Vila Velha","3205200"],["ES","Vitória","3205309"],["GO","Abadia de Goiás","5200050"],["GO","Abadiânia","5200100"],["GO","Acreúna","5200134"],["GO","Adelândia","5200159"],["GO","Água Fria de Goiás","5200175"],["GO","Água Limpa","5200209"],["GO","Águas Lindas de Goiás","5200258"],["GO","Alexânia","5200308"],["GO","Aloândia","5200506"],["GO","Alto Horizonte","5200555"],["GO","Alto Paraíso de Goiás","5200605"],["GO","Alvorada do Norte","5200803"],["GO","Amaralina","5200829"],["GO","Americano do Brasil","5200852"],["GO","Amorinópolis","5200902"],["GO","Anápolis","5201108"],["GO","Anhanguera","5201207"],["GO","Anicuns","5201306"],["GO","Aparecida de Goiânia","5201405"],["GO","Aparecida do Rio Doce","5201454"],["GO","Aporé","5201504"],["GO","Araçu","5201603"],["GO","Aragarças","5201702"],["GO","Aragoiânia","5201801"],["GO","Araguapaz","5202155"],["GO","Arenópolis","5202353"],["GO","Aruanã","5202502"],["GO","Aurilândia","5202601"],["GO","Avelinópolis","5202809"],["GO","Baliza","5203104"],["GO","Barro Alto","5203203"],["GO","Bela Vista de Goiás","5203302"],["GO","Bom Jardim de Goiás","5203401"],["GO","Bom Jesus de Goiás","5203500"],["GO","Bonfinópolis","5203559"],["GO","Bonópolis","5203575"],["GO","Brazabrantes","5203609"],["GO","Britânia","5203807"],["GO","Buriti Alegre","5203906"],["GO","Buriti de Goiás","5203939"],["GO","Buritinópolis","5203962"],["GO","Cabeceiras","5204003"],["GO","Cachoeira Alta","5204102"],["GO","Cachoeira de Goiás","5204201"],["GO","Cachoeira Dourada","5204250"],["GO","Caçu","5204300"],["GO","Caiapônia","5204409"],["GO","Caldas Novas","5204508"],["GO","Caldazinha","5204557"],["GO","Campestre de Goiás","5204607"],["GO","Campinaçu","5204656"],["GO","Campinorte","5204706"],["GO","Campo Alegre de Goiás","5204805"],["GO","Campo Limpo de Goiás","5204854"],["GO","Campos Belos","5204904"],["GO","Campos Verdes","5204953"],["GO","Carmo do Rio Verde","5205000"],["GO","Castelândia","5205059"],["GO","Catalão","5205109"],["GO","Caturaí","5205208"],["GO","Cavalcante","5205307"],["GO","Ceres","5205406"],["GO","Cezarina","5205455"],["GO","Chapadão do Céu","5205471"],["GO","Cidade Ocidental","5205497"],["GO","Cocalzinho de Goiás","5205513"],["GO","Colinas do Sul","5205521"],["GO","Córrego do Ouro","5205703"],["GO","Corumbá de Goiás","5205802"],["GO","Corumbaíba","5205901"],["GO","Cristalina","5206206"],["GO","Cristianópolis","5206305"],["GO","Crixás","5206404"],["GO","Cromínia","5206503"],["GO","Cumari","5206602"],["GO","Damianópolis","5206701"],["GO","Damolândia","5206800"],["GO","Davinópolis","5206909"],["GO","Diorama","5207105"],["GO","Divinópolis de Goiás","5208301"],["GO","Doverlândia","5207253"],["GO","Edealina","5207352"],["GO","Edéia","5207402"],["GO","Estrela do Norte","5207501"],["GO","Faina","5207535"],["GO","Fazenda Nova","5207600"],["GO","Firminópolis","5207808"],["GO","Flores de Goiás","5207907"],["GO","Formosa","5208004"],["GO","Formoso","5208103"],["GO","Gameleira de Goiás","5208152"],["GO","Goianápolis","5208400"],["GO","Goiandira","5208509"],["GO","Goianésia","5208608"],["GO","Goiânia","5208707"],["GO","Goianira","5208806"],["GO","Goiás","5208905"],["GO","Goiatuba","5209101"],["GO","Gouvelândia","5209150"],["GO","Guapó","5209200"],["GO","Guaraíta","5209291"],["GO","Guarani de Goiás","5209408"],["GO","Guarinos","5209457"],["GO","Heitoraí","5209606"],["GO","Hidrolândia","5209705"],["GO","Hidrolina","5209804"],["GO","Iaciara","5209903"],["GO","Inaciolândia","5209937"],["GO","Indiara","5209952"],["GO","Inhumas","5210000"],["GO","Ipameri","5210109"],["GO","Ipiranga de Goiás","5210158"],["GO","Iporá","5210208"],["GO","Israelândia","5210307"],["GO","Itaberaí","5210406"],["GO","Itaguari","5210562"],["GO","Itaguaru","5210604"],["GO","Itajá","5210802"],["GO","Itapaci","5210901"],["GO","Itapirapuã","5211008"],["GO","Itapuranga","5211206"],["GO","Itarumã","5211305"],["GO","Itauçu","5211404"],["GO","Itumbiara","5211503"],["GO","Ivolândia","5211602"],["GO","Jandaia","5211701"],["GO","Jaraguá","5211800"],["GO","Jataí","5211909"],["GO","Jaupaci","5212006"],["GO","Jesúpolis","5212055"],["GO","Joviânia","5212105"],["GO","Jussara","5212204"],["GO","Lagoa Santa","5212253"],["GO","Leopoldo de Bulhões","5212303"],["GO","Luziânia","5212501"],["GO","Mairipotaba","5212600"],["GO","Mambaí","5212709"],["GO","Mara Rosa","5212808"],["GO","Marzagão","5212907"],["GO","Matrinchã","5212956"],["GO","Maurilândia","5213004"],["GO","Mimoso de Goiás","5213053"],["GO","Minaçu","5213087"],["GO","Mineiros","5213103"],["GO","Moiporá","5213400"],["GO","Monte Alegre de Goiás","5213509"],["GO","Montes Claros de Goiás","5213707"],["GO","Montividiu","5213756"],["GO","Montividiu do Norte","5213772"],["GO","Morrinhos","5213806"],["GO","Morro Agudo de Goiás","5213855"],["GO","Mossâmedes","5213905"],["GO","Mozarlândia","5214002"],["GO","Mundo Novo","5214051"],["GO","Mutunópolis","5214101"],["GO","Nazário","5214408"],["GO","Nerópolis","5214507"],["GO","Niquelândia","5214606"],["GO","Nova América","5214705"],["GO","Nova Aurora","5214804"],["GO","Nova Crixás","5214838"],["GO","Nova Glória","5214861"],["GO","Nova Iguaçu de Goiás","5214879"],["GO","Nova Roma","5214903"],["GO","Nova Veneza","5215009"],["GO","Novo Brasil","5215207"],["GO","Novo Gama","5215231"],["GO","Novo Planalto","5215256"],["GO","Orizona","5215306"],["GO","Ouro Verde de Goiás","5215405"],["GO","Ouvidor","5215504"],["GO","Padre Bernardo","5215603"],["GO","Palestina de Goiás","5215652"],["GO","Palmeiras de Goiás","5215702"],["GO","Palmelo","5215801"],["GO","Palminópolis","5215900"],["GO","Panamá","5216007"],["GO","Paranaiguara","5216304"],["GO","Paraúna","5216403"],["GO","Perolândia","5216452"],["GO","Petrolina de Goiás","5216809"],["GO","Pilar de Goiás","5216908"],["GO","Piracanjuba","5217104"],["GO","Piranhas","5217203"],["GO","Pirenópolis","5217302"],["GO","Pires do Rio","5217401"],["GO","Planaltina","5217609"],["GO","Pontalina","5217708"],["GO","Porangatu","5218003"],["GO","Porteirão","5218052"],["GO","Portelândia","5218102"],["GO","Posse","5218300"],["GO","Professor Jamil","5218391"],["GO","Quirinópolis","5218508"],["GO","Rialma","5218607"],["GO","Rianápolis","5218706"],["GO","Rio Quente","5218789"],["GO","Rio Verde","5218805"],["GO","Rubiataba","5218904"],["GO","Sanclerlândia","5219001"],["GO","Santa Bárbara de Goiás","5219100"],["GO","Santa Cruz de Goiás","5219209"],["GO","Santa Fé de Goiás","5219258"],["GO","Santa Helena de Goiás","5219308"],["GO","Santa Isabel","5219357"],["GO","Santa Rita do Araguaia","5219407"],["GO","Santa Rita do Novo Destino","5219456"],["GO","Santa Rosa de Goiás","5219506"],["GO","Santa Tereza de Goiás","5219605"],["GO","Santa Terezinha de Goiás","5219704"],["GO","Santo Antônio da Barra","5219712"],["GO","Santo Antônio de Goiás","5219738"],["GO","Santo Antônio do Descoberto","5219753"],["GO","São Domingos","5219803"],["GO","São Francisco de Goiás","5219902"],["GO","São João d'Aliança","5220009"],["GO","São João da Paraúna","5220058"],["GO","São Luís de Montes Belos","5220108"],["GO","São Luiz do Norte","5220157"],["GO","São Miguel do Araguaia","5220207"],["GO","São Miguel do Passa Quatro","5220264"],["GO","São Patrício","5220280"],["GO","São Simão","5220405"],["GO","Senador Canedo","5220454"],["GO","Serranópolis","5220504"],["GO","Silvânia","5220603"],["GO","Simolândia","5220686"],["GO","Sítio d'Abadia","5220702"],["GO","Taquaral de Goiás","5221007"],["GO","Teresina de Goiás","5221080"],["GO","Terezópolis de Goiás","5221197"],["GO","Três Ranchos","5221304"],["GO","Trindade","5221403"],["GO","Trombas","5221452"],["GO","Turvânia","5221502"],["GO","Turvelândia","5221551"],["GO","Uirapuru","5221577"],["GO","Uruaçu","5221601"],["GO","Uruana","5221700"],["GO","Urutaí","5221809"],["GO","Valparaíso de Goiás","5221858"],["GO","Varjão","5221908"],["GO","Vianópolis","5222005"],["GO","Vicentinópolis","5222054"],["GO","Vila Boa","5222203"],["GO","Vila Propício","5222302"],["MA","Açailândia","2100055"],["MA","Afonso Cunha","2100105"],["MA","Água Doce do Maranhão","2100154"],["MA","Alcântara","2100204"],["MA","Aldeias Altas","2100303"],["MA","Altamira do Maranhão","2100402"],["MA","Alto Alegre do Maranhão","2100436"],["MA","Alto Alegre do Pindaré","2100477"],["MA","Alto Parnaíba","2100501"],["MA","Amapá do Maranhão","2100550"],["MA","Amarante do Maranhão","2100600"],["MA","Anajatuba","2100709"],["MA","Anapurus","2100808"],["MA","Apicum-Açu","2100832"],["MA","Araguanã","2100873"],["MA","Araioses","2100907"],["MA","Arame","2100956"],["MA","Arari","2101004"],["MA","Axixá","2101103"],["MA","Bacabal","2101202"],["MA","Bacabeira","2101251"],["MA","Bacuri","2101301"],["MA","Bacurituba","2101350"],["MA","Balsas","2101400"],["MA","Barão de Grajaú","2101509"],["MA","Barra do Corda","2101608"],["MA","Barreirinhas","2101707"],["MA","Bela Vista do Maranhão","2101772"],["MA","Belágua","2101731"],["MA","Benedito Leite","2101806"],["MA","Bequimão","2101905"],["MA","Bernardo do Mearim","2101939"],["MA","Boa Vista do Gurupi","2101970"],["MA","Bom Jardim","2102002"],["MA","Bom Jesus das Selvas","2102036"],["MA","Bom Lugar","2102077"],["MA","Brejo","2102101"],["MA","Brejo de Areia","2102150"],["MA","Buriti","2102200"],["MA","Buriti Bravo","2102309"],["MA","Buriticupu","2102325"],["MA","Buritirana","2102358"],["MA","Cachoeira Grande","2102374"],["MA","Cajapió","2102408"],["MA","Cajari","2102507"],["MA","Campestre do Maranhão","2102556"],["MA","Cândido Mendes","2102606"],["MA","Cantanhede","2102705"],["MA","Capinzal do Norte","2102754"],["MA","Carolina","2102804"],["MA","Carutapera","2102903"],["MA","Caxias","2103000"],["MA","Cedral","2103109"],["MA","Central do Maranhão","2103125"],["MA","Centro do Guilherme","2103158"],["MA","Centro Novo do Maranhão","2103174"],["MA","Chapadinha","2103208"],["MA","Cidelândia","2103257"],["MA","Codó","2103307"],["MA","Coelho Neto","2103406"],["MA","Colinas","2103505"],["MA","Conceição do Lago-Açu","2103554"],["MA","Coroatá","2103604"],["MA","Cururupu","2103703"],["MA","Davinópolis","2103752"],["MA","Dom Pedro","2103802"],["MA","Duque Bacelar","2103901"],["MA","Esperantinópolis","2104008"],["MA","Estreito","2104057"],["MA","Feira Nova do Maranhão","2104073"],["MA","Fernando Falcão","2104081"],["MA","Formosa da Serra Negra","2104099"],["MA","Fortaleza dos Nogueiras","2104107"],["MA","Fortuna","2104206"],["MA","Godofredo Viana","2104305"],["MA","Gonçalves Dias","2104404"],["MA","Governador Archer","2104503"],["MA","Governador Edison Lobão","2104552"],["MA","Governador Eugênio Barros","2104602"],["MA","Governador Luiz Rocha","2104628"],["MA","Governador Newton Bello","2104651"],["MA","Governador Nunes Freire","2104677"],["MA","Graça Aranha","2104701"],["MA","Grajaú","2104800"],["MA","Guimarães","2104909"],["MA","Humberto de Campos","2105005"],["MA","Icatu","2105104"],["MA","Igarapé do Meio","2105153"],["MA","Igarapé Grande","2105203"],["MA","Imperatriz","2105302"],["MA","Itaipava do Grajaú","2105351"],["MA","Itapecuru Mirim","2105401"],["MA","Itinga do Maranhão","2105427"],["MA","Jatobá","2105450"],["MA","Jenipapo dos Vieiras","2105476"],["MA","João Lisboa","2105500"],["MA","Joselândia","2105609"],["MA","Junco do Maranhão","2105658"],["MA","Lago da Pedra","2105708"],["MA","Lago do Junco","2105807"],["MA","Lago dos Rodrigues","2105948"],["MA","Lago Verde","2105906"],["MA","Lagoa do Mato","2105922"],["MA","Lagoa Grande do Maranhão","2105963"],["MA","Lajeado Novo","2105989"],["MA","Lima Campos","2106003"],["MA","Loreto","2106102"],["MA","Luís Domingues","2106201"],["MA","Magalhães de Almeida","2106300"],["MA","Maracaçumé","2106326"],["MA","Marajá do Sena","2106359"],["MA","Maranhãozinho","2106375"],["MA","Mata Roma","2106409"],["MA","Matinha","2106508"],["MA","Matões","2106607"],["MA","Matões do Norte","2106631"],["MA","Milagres do Maranhão","2106672"],["MA","Mirador","2106706"],["MA","Miranda do Norte","2106755"],["MA","Mirinzal","2106805"],["MA","Monção","2106904"],["MA","Montes Altos","2107001"],["MA","Morros","2107100"],["MA","Nina Rodrigues","2107209"],["MA","Nova Colinas","2107258"],["MA","Nova Iorque","2107308"],["MA","Nova Olinda do Maranhão","2107357"],["MA","Olho d'Água das Cunhãs","2107407"],["MA","Olinda Nova do Maranhão","2107456"],["MA","Paço do Lumiar","2107506"],["MA","Palmeirândia","2107605"],["MA","Paraibano","2107704"],["MA","Parnarama","2107803"],["MA","Passagem Franca","2107902"],["MA","Pastos Bons","2108009"],["MA","Paulino Neves","2108058"],["MA","Paulo Ramos","2108108"],["MA","Pedreiras","2108207"],["MA","Pedro do Rosário","2108256"],["MA","Penalva","2108306"],["MA","Peri Mirim","2108405"],["MA","Peritoró","2108454"],["MA","Pindaré-Mirim","2108504"],["MA","Pinheiro","2108603"],["MA","Pio XII","2108702"],["MA","Pirapemas","2108801"],["MA","Poção de Pedras","2108900"],["MA","Porto Franco","2109007"],["MA","Porto Rico do Maranhão","2109056"],["MA","Presidente Dutra","2109106"],["MA","Presidente Juscelino","2109205"],["MA","Presidente Médici","2109239"],["MA","Presidente Sarney","2109270"],["MA","Presidente Vargas","2109304"],["MA","Primeira Cruz","2109403"],["MA","Raposa","2109452"],["MA","Riachão","2109502"],["MA","Ribamar Fiquene","2109551"],["MA","Rosário","2109601"],["MA","Sambaíba","2109700"],["MA","Santa Filomena do Maranhão","2109759"],["MA","Santa Helena","2109809"],["MA","Santa Inês","2109908"],["MA","Santa Luzia","2110005"],["MA","Santa Luzia do Paruá","2110039"],["MA","Santa Quitéria do Maranhão","2110104"],["MA","Santa Rita","2110203"],["MA","Santana do Maranhão","2110237"],["MA","Santo Amaro do Maranhão","2110278"],["MA","Santo Antônio dos Lopes","2110302"],["MA","São Benedito do Rio Preto","2110401"],["MA","São Bento","2110500"],["MA","São Bernardo","2110609"],["MA","São Domingos do Azeitão","2110658"],["MA","São Domingos do Maranhão","2110708"],["MA","São Félix de Balsas","2110807"],["MA","São Francisco do Brejão","2110856"],["MA","São Francisco do Maranhão","2110906"],["MA","São João Batista","2111003"],["MA","São João do Carú","2111029"],["MA","São João do Paraíso","2111052"],["MA","São João do Soter","2111078"],["MA","São João dos Patos","2111102"],["MA","São José de Ribamar","2111201"],["MA","São José dos Basílios","2111250"],["MA","São Luís","2111300"],["MA","São Luís Gonzaga do Maranhão","2111409"],["MA","São Mateus do Maranhão","2111508"],["MA","São Pedro da Água Branca","2111532"],["MA","São Pedro dos Crentes","2111573"],["MA","São Raimundo das Mangabeiras","2111607"],["MA","São Raimundo do Doca Bezerra","2111631"],["MA","São Roberto","2111672"],["MA","São Vicente Ferrer","2111706"],["MA","Satubinha","2111722"],["MA","Senador Alexandre Costa","2111748"],["MA","Senador La Rocque","2111763"],["MA","Serrano do Maranhão","2111789"],["MA","Sítio Novo","2111805"],["MA","Sucupira do Norte","2111904"],["MA","Sucupira do Riachão","2111953"],["MA","Tasso Fragoso","2112001"],["MA","Timbiras","2112100"],["MA","Timon","2112209"],["MA","Trizidela do Vale","2112233"],["MA","Tufilândia","2112274"],["MA","Tuntum","2112308"],["MA","Turiaçu","2112407"],["MA","Turilândia","2112456"],["MA","Tutóia","2112506"],["MA","Urbano Santos","2112605"],["MA","Vargem Grande","2112704"],["MA","Viana","2112803"],["MA","Vila Nova dos Martírios","2112852"],["MA","Vitória do Mearim","2112902"],["MA","Vitorino Freire","2113009"],["MA","Zé Doca","2114007"],["MT","Acorizal","5100102"],["MT","Água Boa","5100201"],["MT","Alta Floresta","5100250"],["MT","Alto Araguaia","5100300"],["MT","Alto Boa Vista","5100359"],["MT","Alto Garças","5100409"],["MT","Alto Paraguai","5100508"],["MT","Alto Taquari","5100607"],["MT","Apiacás","5100805"],["MT","Araguaiana","5101001"],["MT","Araguainha","5101209"],["MT","Araputanga","5101258"],["MT","Arenápolis","5101308"],["MT","Aripuanã","5101407"],["MT","Barão de Melgaço","5101605"],["MT","Barra do Bugres","5101704"],["MT","Barra do Garças","5101803"],["MT","Boa Esperança do Norte","5101837"],["MT","Bom Jesus do Araguaia","5101852"],["MT","Brasnorte","5101902"],["MT","Cáceres","5102504"],["MT","Campinápolis","5102603"],["MT","Campo Novo do Parecis","5102637"],["MT","Campo Verde","5102678"],["MT","Campos de Júlio","5102686"],["MT","Canabrava do Norte","5102694"],["MT","Canarana","5102702"],["MT","Carlinda","5102793"],["MT","Castanheira","5102850"],["MT","Chapada dos Guimarães","5103007"],["MT","Cláudia","5103056"],["MT","Cocalinho","5103106"],["MT","Colíder","5103205"],["MT","Colniza","5103254"],["MT","Comodoro","5103304"],["MT","Confresa","5103353"],["MT","Conquista D'Oeste","5103361"],["MT","Cotriguaçu","5103379"],["MT","Cuiabá","5103403"],["MT","Curvelândia","5103437"],["MT","Denise","5103452"],["MT","Diamantino","5103502"],["MT","Dom Aquino","5103601"],["MT","Feliz Natal","5103700"],["MT","Figueirópolis D'Oeste","5103809"],["MT","Gaúcha do Norte","5103858"],["MT","General Carneiro","5103908"],["MT","Glória D'Oeste","5103957"],["MT","Guarantã do Norte","5104104"],["MT","Guiratinga","5104203"],["MT","Indiavaí","5104500"],["MT","Ipiranga do Norte","5104526"],["MT","Itanhangá","5104542"],["MT","Itaúba","5104559"],["MT","Itiquira","5104609"],["MT","Jaciara","5104807"],["MT","Jangada","5104906"],["MT","Jauru","5105002"],["MT","Juara","5105101"],["MT","Juína","5105150"],["MT","Juruena","5105176"],["MT","Juscimeira","5105200"],["MT","Lambari D'Oeste","5105234"],["MT","Lucas do Rio Verde","5105259"],["MT","Luciara","5105309"],["MT","Marcelândia","5105580"],["MT","Matupá","5105606"],["MT","Mirassol d'Oeste","5105622"],["MT","Nobres","5105903"],["MT","Nortelândia","5106000"],["MT","Nossa Senhora do Livramento","5106109"],["MT","Nova Bandeirantes","5106158"],["MT","Nova Brasilândia","5106208"],["MT","Nova Canaã do Norte","5106216"],["MT","Nova Guarita","5108808"],["MT","Nova Lacerda","5106182"],["MT","Nova Marilândia","5108857"],["MT","Nova Maringá","5108907"],["MT","Nova Monte Verde","5108956"],["MT","Nova Mutum","5106224"],["MT","Nova Nazaré","5106174"],["MT","Nova Olímpia","5106232"],["MT","Nova Santa Helena","5106190"],["MT","Nova Ubiratã","5106240"],["MT","Nova Xavantina","5106257"],["MT","Novo Horizonte do Norte","5106273"],["MT","Novo Mundo","5106265"],["MT","Novo Santo Antônio","5106315"],["MT","Novo São Joaquim","5106281"],["MT","Paranaíta","5106299"],["MT","Paranatinga","5106307"],["MT","Pedra Preta","5106372"],["MT","Peixoto de Azevedo","5106422"],["MT","Planalto da Serra","5106455"],["MT","Poconé","5106505"],["MT","Pontal do Araguaia","5106653"],["MT","Ponte Branca","5106703"],["MT","Pontes e Lacerda","5106752"],["MT","Porto Alegre do Norte","5106778"],["MT","Porto dos Gaúchos","5106802"],["MT","Porto Esperidião","5106828"],["MT","Porto Estrela","5106851"],["MT","Poxoréu","5107008"],["MT","Primavera do Leste","5107040"],["MT","Querência","5107065"],["MT","Reserva do Cabaçal","5107156"],["MT","Ribeirão Cascalheira","5107180"],["MT","Ribeirãozinho","5107198"],["MT","Rio Branco","5107206"],["MT","Rondolândia","5107578"],["MT","Rondonópolis","5107602"],["MT","Rosário Oeste","5107701"],["MT","Salto do Céu","5107750"],["MT","Santa Carmem","5107248"],["MT","Santa Cruz do Xingu","5107743"],["MT","Santa Rita do Trivelato","5107768"],["MT","Santa Terezinha","5107776"],["MT","Santo Afonso","5107263"],["MT","Santo Antônio de Leverger","5107800"],["MT","Santo Antônio do Leste","5107792"],["MT","São Félix do Araguaia","5107859"],["MT","São José do Povo","5107297"],["MT","São José do Rio Claro","5107305"],["MT","São José do Xingu","5107354"],["MT","São José dos Quatro Marcos","5107107"],["MT","São Pedro da Cipa","5107404"],["MT","Sapezal","5107875"],["MT","Serra Nova Dourada","5107883"],["MT","Sinop","5107909"],["MT","Sorriso","5107925"],["MT","Tabaporã","5107941"],["MT","Tangará da Serra","5107958"],["MT","Tapurah","5108006"],["MT","Terra Nova do Norte","5108055"],["MT","Tesouro","5108105"],["MT","Torixoréu","5108204"],["MT","União do Sul","5108303"],["MT","Vale de São Domingos","5108352"],["MT","Várzea Grande","5108402"],["MT","Vera","5108501"],["MT","Vila Bela da Santíssima Trindade","5105507"],["MT","Vila Rica","5108600"],["MS","Água Clara","5000203"],["MS","Alcinópolis","5000252"],["MS","Amambai","5000609"],["MS","Anastácio","5000708"],["MS","Anaurilândia","5000807"],["MS","Angélica","5000856"],["MS","Antônio João","5000906"],["MS","Aparecida do Taboado","5001003"],["MS","Aquidauana","5001102"],["MS","Aral Moreira","5001243"],["MS","Bandeirantes","5001508"],["MS","Bataguassu","5001904"],["MS","Batayporã","5002001"],["MS","Bela Vista","5002100"],["MS","Bodoquena","5002159"],["MS","Bonito","5002209"],["MS","Brasilândia","5002308"],["MS","Caarapó","5002407"],["MS","Camapuã","5002605"],["MS","Campo Grande","5002704"],["MS","Caracol","5002803"],["MS","Cassilândia","5002902"],["MS","Chapadão do Sul","5002951"],["MS","Corguinho","5003108"],["MS","Coronel Sapucaia","5003157"],["MS","Corumbá","5003207"],["MS","Costa Rica","5003256"],["MS","Coxim","5003306"],["MS","Deodápolis","5003454"],["MS","Dois Irmãos do Buriti","5003488"],["MS","Douradina","5003504"],["MS","Dourados","5003702"],["MS","Eldorado","5003751"],["MS","Fátima do Sul","5003801"],["MS","Figueirão","5003900"],["MS","Glória de Dourados","5004007"],["MS","Guia Lopes da Laguna","5004106"],["MS","Iguatemi","5004304"],["MS","Inocência","5004403"],["MS","Itaporã","5004502"],["MS","Itaquiraí","5004601"],["MS","Ivinhema","5004700"],["MS","Japorã","5004809"],["MS","Jaraguari","5004908"],["MS","Jardim","5005004"],["MS","Jateí","5005103"],["MS","Juti","5005152"],["MS","Ladário","5005202"],["MS","Laguna Carapã","5005251"],["MS","Maracaju","5005400"],["MS","Miranda","5005608"],["MS","Mundo Novo","5005681"],["MS","Naviraí","5005707"],["MS","Nioaque","5005806"],["MS","Nova Alvorada do Sul","5006002"],["MS","Nova Andradina","5006200"],["MS","Novo Horizonte do Sul","5006259"],["MS","Paraíso das Águas","5006275"],["MS","Paranaíba","5006309"],["MS","Paranhos","5006358"],["MS","Pedro Gomes","5006408"],["MS","Ponta Porã","5006606"],["MS","Porto Murtinho","5006903"],["MS","Ribas do Rio Pardo","5007109"],["MS","Rio Brilhante","5007208"],["MS","Rio Negro","5007307"],["MS","Rio Verde de Mato Grosso","5007406"],["MS","Rochedo","5007505"],["MS","Santa Rita do Pardo","5007554"],["MS","São Gabriel do Oeste","5007695"],["MS","Selvíria","5007802"],["MS","Sete Quedas","5007703"],["MS","Sidrolândia","5007901"],["MS","Sonora","5007935"],["MS","Tacuru","5007950"],["MS","Taquarussu","5007976"],["MS","Terenos","5008008"],["MS","Três Lagoas","5008305"],["MS","Vicentina","5008404"],["MG","Abadia dos Dourados","3100104"],["MG","Abaeté","3100203"],["MG","Abre Campo","3100302"],["MG","Acaiaca","3100401"],["MG","Açucena","3100500"],["MG","Água Boa","3100609"],["MG","Água Comprida","3100708"],["MG","Aguanil","3100807"],["MG","Águas Formosas","3100906"],["MG","Águas Vermelhas","3101003"],["MG","Aimorés","3101102"],["MG","Aiuruoca","3101201"],["MG","Alagoa","3101300"],["MG","Albertina","3101409"],["MG","Além Paraíba","3101508"],["MG","Alfenas","3101607"],["MG","Alfredo Vasconcelos","3101631"],["MG","Almenara","3101706"],["MG","Alpercata","3101805"],["MG","Alpinópolis","3101904"],["MG","Alterosa","3102001"],["MG","Alto Caparaó","3102050"],["MG","Alto Jequitibá","3153509"],["MG","Alto Rio Doce","3102100"],["MG","Alvarenga","3102209"],["MG","Alvinópolis","3102308"],["MG","Alvorada de Minas","3102407"],["MG","Amparo do Serra","3102506"],["MG","Andradas","3102605"],["MG","Andrelândia","3102803"],["MG","Angelândia","3102852"],["MG","Antônio Carlos","3102902"],["MG","Antônio Dias","3103009"],["MG","Antônio Prado de Minas","3103108"],["MG","Araçaí","3103207"],["MG","Aracitaba","3103306"],["MG","Araçuaí","3103405"],["MG","Araguari","3103504"],["MG","Arantina","3103603"],["MG","Araponga","3103702"],["MG","Araporã","3103751"],["MG","Arapuá","3103801"],["MG","Araújos","3103900"],["MG","Araxá","3104007"],["MG","Arceburgo","3104106"],["MG","Arcos","3104205"],["MG","Areado","3104304"],["MG","Argirita","3104403"],["MG","Aricanduva","3104452"],["MG","Arinos","3104502"],["MG","Astolfo Dutra","3104601"],["MG","Ataléia","3104700"],["MG","Augusto de Lima","3104809"],["MG","Baependi","3104908"],["MG","Baldim","3105004"],["MG","Bambuí","3105103"],["MG","Bandeira","3105202"],["MG","Bandeira do Sul","3105301"],["MG","Barão de Cocais","3105400"],["MG","Barão do Monte Alto","3105509"],["MG","Barbacena","3105608"],["MG","Barra Longa","3105707"],["MG","Barroso","3105905"],["MG","Bela Vista de Minas","3106002"],["MG","Belmiro Braga","3106101"],["MG","Belo Horizonte","3106200"],["MG","Belo Oriente","3106309"],["MG","Belo Vale","3106408"],["MG","Berilo","3106507"],["MG","Berizal","3106655"],["MG","Bertópolis","3106606"],["MG","Betim","3106705"],["MG","Bias Fortes","3106804"],["MG","Bicas","3106903"],["MG","Biquinhas","3107000"],["MG","Boa Esperança","3107109"],["MG","Bocaina de Minas","3107208"],["MG","Bocaiúva","3107307"],["MG","Bom Despacho","3107406"],["MG","Bom Jardim de Minas","3107505"],["MG","Bom Jesus da Penha","3107604"],["MG","Bom Jesus do Amparo","3107703"],["MG","Bom Jesus do Galho","3107802"],["MG","Bom Repouso","3107901"],["MG","Bom Sucesso","3108008"],["MG","Bonfim","3108107"],["MG","Bonfinópolis de Minas","3108206"],["MG","Bonito de Minas","3108255"],["MG","Borda da Mata","3108305"],["MG","Botelhos","3108404"],["MG","Botumirim","3108503"],["MG","Brás Pires","3108701"],["MG","Brasilândia de Minas","3108552"],["MG","Brasília de Minas","3108602"],["MG","Braúnas","3108800"],["MG","Brazópolis","3108909"],["MG","Brumadinho","3109006"],["MG","Bueno Brandão","3109105"],["MG","Buenópolis","3109204"],["MG","Bugre","3109253"],["MG","Buritis","3109303"],["MG","Buritizeiro","3109402"],["MG","Cabeceira Grande","3109451"],["MG","Cabo Verde","3109501"],["MG","Cachoeira da Prata","3109600"],["MG","Cachoeira de Minas","3109709"],["MG","Cachoeira de Pajeú","3102704"],["MG","Cachoeira Dourada","3109808"],["MG","Caetanópolis","3109907"],["MG","Caeté","3110004"],["MG","Caiana","3110103"],["MG","Cajuri","3110202"],["MG","Caldas","3110301"],["MG","Camacho","3110400"],["MG","Camanducaia","3110509"],["MG","Cambuí","3110608"],["MG","Cambuquira","3110707"],["MG","Campanário","3110806"],["MG","Campanha","3110905"],["MG","Campestre","3111002"],["MG","Campina Verde","3111101"],["MG","Campo Azul","3111150"],["MG","Campo Belo","3111200"],["MG","Campo do Meio","3111309"],["MG","Campo Florido","3111408"],["MG","Campos Altos","3111507"],["MG","Campos Gerais","3111606"],["MG","Cana Verde","3111903"],["MG","Canaã","3111705"],["MG","Canápolis","3111804"],["MG","Candeias","3112000"],["MG","Cantagalo","3112059"],["MG","Caparaó","3112109"],["MG","Capela Nova","3112208"],["MG","Capelinha","3112307"],["MG","Capetinga","3112406"],["MG","Capim Branco","3112505"],["MG","Capinópolis","3112604"],["MG","Capitão Andrade","3112653"],["MG","Capitão Enéas","3112703"],["MG","Capitólio","3112802"],["MG","Caputira","3112901"],["MG","Caraí","3113008"],["MG","Caranaíba","3113107"],["MG","Carandaí","3113206"],["MG","Carangola","3113305"],["MG","Caratinga","3113404"],["MG","Carbonita","3113503"],["MG","Careaçu","3113602"],["MG","Carlos Chagas","3113701"],["MG","Carmésia","3113800"],["MG","Carmo da Cachoeira","3113909"],["MG","Carmo da Mata","3114006"],["MG","Carmo de Minas","3114105"],["MG","Carmo do Cajuru","3114204"],["MG","Carmo do Paranaíba","3114303"],["MG","Carmo do Rio Claro","3114402"],["MG","Carmópolis de Minas","3114501"],["MG","Carneirinho","3114550"],["MG","Carrancas","3114600"],["MG","Carvalhópolis","3114709"],["MG","Carvalhos","3114808"],["MG","Casa Grande","3114907"],["MG","Cascalho Rico","3115003"],["MG","Cássia","3115102"],["MG","Cataguases","3115300"],["MG","Catas Altas","3115359"],["MG","Catas Altas da Noruega","3115409"],["MG","Catuji","3115458"],["MG","Catuti","3115474"],["MG","Caxambu","3115508"],["MG","Cedro do Abaeté","3115607"],["MG","Central de Minas","3115706"],["MG","Centralina","3115805"],["MG","Chácara","3115904"],["MG","Chalé","3116001"],["MG","Chapada do Norte","3116100"],["MG","Chapada Gaúcha","3116159"],["MG","Chiador","3116209"],["MG","Cipotânea","3116308"],["MG","Claraval","3116407"],["MG","Claro dos Poções","3116506"],["MG","Cláudio","3116605"],["MG","Coimbra","3116704"],["MG","Coluna","3116803"],["MG","Comendador Gomes","3116902"],["MG","Comercinho","3117009"],["MG","Conceição da Aparecida","3117108"],["MG","Conceição da Barra de Minas","3115201"],["MG","Conceição das Alagoas","3117306"],["MG","Conceição das Pedras","3117207"],["MG","Conceição de Ipanema","3117405"],["MG","Conceição do Mato Dentro","3117504"],["MG","Conceição do Pará","3117603"],["MG","Conceição do Rio Verde","3117702"],["MG","Conceição dos Ouros","3117801"],["MG","Cônego Marinho","3117836"],["MG","Confins","3117876"],["MG","Congonhal","3117900"],["MG","Congonhas","3118007"],["MG","Congonhas do Norte","3118106"],["MG","Conquista","3118205"],["MG","Conselheiro Lafaiete","3118304"],["MG","Conselheiro Pena","3118403"],["MG","Consolação","3118502"],["MG","Contagem","3118601"],["MG","Coqueiral","3118700"],["MG","Coração de Jesus","3118809"],["MG","Cordisburgo","3118908"],["MG","Cordislândia","3119005"],["MG","Corinto","3119104"],["MG","Coroaci","3119203"],["MG","Coromandel","3119302"],["MG","Coronel Fabriciano","3119401"],["MG","Coronel Murta","3119500"],["MG","Coronel Pacheco","3119609"],["MG","Coronel Xavier Chaves","3119708"],["MG","Córrego Danta","3119807"],["MG","Córrego do Bom Jesus","3119906"],["MG","Córrego Fundo","3119955"],["MG","Córrego Novo","3120003"],["MG","Couto de Magalhães de Minas","3120102"],["MG","Crisólita","3120151"],["MG","Cristais","3120201"],["MG","Cristália","3120300"],["MG","Cristiano Otoni","3120409"],["MG","Cristina","3120508"],["MG","Crucilândia","3120607"],["MG","Cruzeiro da Fortaleza","3120706"],["MG","Cruzília","3120805"],["MG","Cuparaque","3120839"],["MG","Curral de Dentro","3120870"],["MG","Curvelo","3120904"],["MG","Datas","3121001"],["MG","Delfim Moreira","3121100"],["MG","Delfinópolis","3121209"],["MG","Delta","3121258"],["MG","Descoberto","3121308"],["MG","Desterro de Entre Rios","3121407"],["MG","Desterro do Melo","3121506"],["MG","Diamantina","3121605"],["MG","Diogo de Vasconcelos","3121704"],["MG","Dionísio","3121803"],["MG","Divinésia","3121902"],["MG","Divino","3122009"],["MG","Divino das Laranjeiras","3122108"],["MG","Divinolândia de Minas","3122207"],["MG","Divinópolis","3122306"],["MG","Divisa Alegre","3122355"],["MG","Divisa Nova","3122405"],["MG","Divisópolis","3122454"],["MG","Dom Bosco","3122470"],["MG","Dom Cavati","3122504"],["MG","Dom Joaquim","3122603"],["MG","Dom Silvério","3122702"],["MG","Dom Viçoso","3122801"],["MG","Dona Euzébia","3122900"],["MG","Dores de Campos","3123007"],["MG","Dores de Guanhães","3123106"],["MG","Dores do Indaiá","3123205"],["MG","Dores do Turvo","3123304"],["MG","Doresópolis","3123403"],["MG","Douradoquara","3123502"],["MG","Durandé","3123528"],["MG","Elói Mendes","3123601"],["MG","Engenheiro Caldas","3123700"],["MG","Engenheiro Navarro","3123809"],["MG","Entre Folhas","3123858"],["MG","Entre Rios de Minas","3123908"],["MG","Ervália","3124005"],["MG","Esmeraldas","3124104"],["MG","Espera Feliz","3124203"],["MG","Espinosa","3124302"],["MG","Espírito Santo do Dourado","3124401"],["MG","Estiva","3124500"],["MG","Estrela Dalva","3124609"],["MG","Estrela do Indaiá","3124708"],["MG","Estrela do Sul","3124807"],["MG","Eugenópolis","3124906"],["MG","Ewbank da Câmara","3125002"],["MG","Extrema","3125101"],["MG","Fama","3125200"],["MG","Faria Lemos","3125309"],["MG","Felício dos Santos","3125408"],["MG","Felisburgo","3125606"],["MG","Felixlândia","3125705"],["MG","Fernandes Tourinho","3125804"],["MG","Ferros","3125903"],["MG","Fervedouro","3125952"],["MG","Florestal","3126000"],["MG","Formiga","3126109"],["MG","Formoso","3126208"],["MG","Fortaleza de Minas","3126307"],["MG","Fortuna de Minas","3126406"],["MG","Francisco Badaró","3126505"],["MG","Francisco Dumont","3126604"],["MG","Francisco Sá","3126703"],["MG","Franciscópolis","3126752"],["MG","Frei Gaspar","3126802"],["MG","Frei Inocêncio","3126901"],["MG","Frei Lagonegro","3126950"],["MG","Fronteira","3127008"],["MG","Fronteira dos Vales","3127057"],["MG","Fruta de Leite","3127073"],["MG","Frutal","3127107"],["MG","Funilândia","3127206"],["MG","Galiléia","3127305"],["MG","Gameleiras","3127339"],["MG","Glaucilândia","3127354"],["MG","Goiabeira","3127370"],["MG","Goianá","3127388"],["MG","Gonçalves","3127404"],["MG","Gonzaga","3127503"],["MG","Gouveia","3127602"],["MG","Governador Valadares","3127701"],["MG","Grão Mogol","3127800"],["MG","Grupiara","3127909"],["MG","Guanhães","3128006"],["MG","Guapé","3128105"],["MG","Guaraciaba","3128204"],["MG","Guaraciama","3128253"],["MG","Guaranésia","3128303"],["MG","Guarani","3128402"],["MG","Guarará","3128501"],["MG","Guarda-Mor","3128600"],["MG","Guaxupé","3128709"],["MG","Guidoval","3128808"],["MG","Guimarânia","3128907"],["MG","Guiricema","3129004"],["MG","Gurinhatã","3129103"],["MG","Heliodora","3129202"],["MG","Iapu","3129301"],["MG","Ibertioga","3129400"],["MG","Ibiá","3129509"],["MG","Ibiaí","3129608"],["MG","Ibiracatu","3129657"],["MG","Ibiraci","3129707"],["MG","Ibirité","3129806"],["MG","Ibitiúra de Minas","3129905"],["MG","Ibituruna","3130002"],["MG","Icaraí de Minas","3130051"],["MG","Igarapé","3130101"],["MG","Igaratinga","3130200"],["MG","Iguatama","3130309"],["MG","Ijaci","3130408"],["MG","Ilicínea","3130507"],["MG","Imbé de Minas","3130556"],["MG","Inconfidentes","3130606"],["MG","Indaiabira","3130655"],["MG","Indianópolis","3130705"],["MG","Ingaí","3130804"],["MG","Inhapim","3130903"],["MG","Inhaúma","3131000"],["MG","Inimutaba","3131109"],["MG","Ipaba","3131158"],["MG","Ipanema","3131208"],["MG","Ipatinga","3131307"],["MG","Ipiaçu","3131406"],["MG","Ipuiúna","3131505"],["MG","Iraí de Minas","3131604"],["MG","Itabira","3131703"],["MG","Itabirinha","3131802"],["MG","Itabirito","3131901"],["MG","Itacambira","3132008"],["MG","Itacarambi","3132107"],["MG","Itaguara","3132206"],["MG","Itaipé","3132305"],["MG","Itajubá","3132404"],["MG","Itamarandiba","3132503"],["MG","Itamarati de Minas","3132602"],["MG","Itambacuri","3132701"],["MG","Itambé do Mato Dentro","3132800"],["MG","Itamogi","3132909"],["MG","Itamonte","3133006"],["MG","Itanhandu","3133105"],["MG","Itanhomi","3133204"],["MG","Itaobim","3133303"],["MG","Itapagipe","3133402"],["MG","Itapecerica","3133501"],["MG","Itapeva","3133600"],["MG","Itatiaiuçu","3133709"],["MG","Itaú de Minas","3133758"],["MG","Itaúna","3133808"],["MG","Itaverava","3133907"],["MG","Itinga","3134004"],["MG","Itueta","3134103"],["MG","Ituiutaba","3134202"],["MG","Itumirim","3134301"],["MG","Iturama","3134400"],["MG","Itutinga","3134509"],["MG","Jaboticatubas","3134608"],["MG","Jacinto","3134707"],["MG","Jacuí","3134806"],["MG","Jacutinga","3134905"],["MG","Jaguaraçu","3135001"],["MG","Jaíba","3135050"],["MG","Jampruca","3135076"],["MG","Janaúba","3135100"],["MG","Januária","3135209"],["MG","Japaraíba","3135308"],["MG","Japonvar","3135357"],["MG","Jeceaba","3135407"],["MG","Jenipapo de Minas","3135456"],["MG","Jequeri","3135506"],["MG","Jequitaí","3135605"],["MG","Jequitibá","3135704"],["MG","Jequitinhonha","3135803"],["MG","Jesuânia","3135902"],["MG","Joaíma","3136009"],["MG","Joanésia","3136108"],["MG","João Monlevade","3136207"],["MG","João Pinheiro","3136306"],["MG","Joaquim Felício","3136405"],["MG","Jordânia","3136504"],["MG","José Gonçalves de Minas","3136520"],["MG","José Raydan","3136553"],["MG","Josenópolis","3136579"],["MG","Juatuba","3136652"],["MG","Juiz de Fora","3136702"],["MG","Juramento","3136801"],["MG","Juruaia","3136900"],["MG","Juvenília","3136959"],["MG","Ladainha","3137007"],["MG","Lagamar","3137106"],["MG","Lagoa da Prata","3137205"],["MG","Lagoa dos Patos","3137304"],["MG","Lagoa Dourada","3137403"],["MG","Lagoa Formosa","3137502"],["MG","Lagoa Grande","3137536"],["MG","Lagoa Santa","3137601"],["MG","Lajinha","3137700"],["MG","Lambari","3137809"],["MG","Lamim","3137908"],["MG","Laranjal","3138005"],["MG","Lassance","3138104"],["MG","Lavras","3138203"],["MG","Leandro Ferreira","3138302"],["MG","Leme do Prado","3138351"],["MG","Leopoldina","3138401"],["MG","Liberdade","3138500"],["MG","Lima Duarte","3138609"],["MG","Limeira do Oeste","3138625"],["MG","Lontra","3138658"],["MG","Luisburgo","3138674"],["MG","Luislândia","3138682"],["MG","Luminárias","3138708"],["MG","Luz","3138807"],["MG","Machacalis","3138906"],["MG","Machado","3139003"],["MG","Madre de Deus de Minas","3139102"],["MG","Malacacheta","3139201"],["MG","Mamonas","3139250"],["MG","Manga","3139300"],["MG","Manhuaçu","3139409"],["MG","Manhumirim","3139508"],["MG","Mantena","3139607"],["MG","Mar de Espanha","3139805"],["MG","Maravilhas","3139706"],["MG","Maria da Fé","3139904"],["MG","Mariana","3140001"],["MG","Marilac","3140100"],["MG","Mário Campos","3140159"],["MG","Maripá de Minas","3140209"],["MG","Marliéria","3140308"],["MG","Marmelópolis","3140407"],["MG","Martinho Campos","3140506"],["MG","Martins Soares","3140530"],["MG","Mata Verde","3140555"],["MG","Materlândia","3140605"],["MG","Mateus Leme","3140704"],["MG","Mathias Lobato","3171501"],["MG","Matias Barbosa","3140803"],["MG","Matias Cardoso","3140852"],["MG","Matipó","3140902"],["MG","Mato Verde","3141009"],["MG","Matozinhos","3141108"],["MG","Matutina","3141207"],["MG","Medeiros","3141306"],["MG","Medina","3141405"],["MG","Mendes Pimentel","3141504"],["MG","Mercês","3141603"],["MG","Mesquita","3141702"],["MG","Minas Novas","3141801"],["MG","Minduri","3141900"],["MG","Mirabela","3142007"],["MG","Miradouro","3142106"],["MG","Miraí","3142205"],["MG","Miravânia","3142254"],["MG","Moeda","3142304"],["MG","Moema","3142403"],["MG","Monjolos","3142502"],["MG","Monsenhor Paulo","3142601"],["MG","Montalvânia","3142700"],["MG","Monte Alegre de Minas","3142809"],["MG","Monte Azul","3142908"],["MG","Monte Belo","3143005"],["MG","Monte Carmelo","3143104"],["MG","Monte Formoso","3143153"],["MG","Monte Santo de Minas","3143203"],["MG","Monte Sião","3143401"],["MG","Montes Claros","3143302"],["MG","Montezuma","3143450"],["MG","Morada Nova de Minas","3143500"],["MG","Morro da Garça","3143609"],["MG","Morro do Pilar","3143708"],["MG","Munhoz","3143807"],["MG","Muriaé","3143906"],["MG","Mutum","3144003"],["MG","Muzambinho","3144102"],["MG","Nacip Raydan","3144201"],["MG","Nanuque","3144300"],["MG","Naque","3144359"],["MG","Natalândia","3144375"],["MG","Natércia","3144409"],["MG","Nazareno","3144508"],["MG","Nepomuceno","3144607"],["MG","Ninheira","3144656"],["MG","Nova Belém","3144672"],["MG","Nova Era","3144706"],["MG","Nova Lima","3144805"],["MG","Nova Módica","3144904"],["MG","Nova Ponte","3145000"],["MG","Nova Porteirinha","3145059"],["MG","Nova Resende","3145109"],["MG","Nova Serrana","3145208"],["MG","Nova União","3136603"],["MG","Novo Cruzeiro","3145307"],["MG","Novo Oriente de Minas","3145356"],["MG","Novorizonte","3145372"],["MG","Olaria","3145406"],["MG","Olhos-d'Água","3145455"],["MG","Olímpio Noronha","3145505"],["MG","Oliveira","3145604"],["MG","Oliveira Fortes","3145703"],["MG","Onça de Pitangui","3145802"],["MG","Oratórios","3145851"],["MG","Orizânia","3145877"],["MG","Ouro Branco","3145901"],["MG","Ouro Fino","3146008"],["MG","Ouro Preto","3146107"],["MG","Ouro Verde de Minas","3146206"],["MG","Padre Carvalho","3146255"],["MG","Padre Paraíso","3146305"],["MG","Pai Pedro","3146552"],["MG","Paineiras","3146404"],["MG","Pains","3146503"],["MG","Paiva","3146602"],["MG","Palma","3146701"],["MG","Palmópolis","3146750"],["MG","Papagaios","3146909"],["MG","Pará de Minas","3147105"],["MG","Paracatu","3147006"],["MG","Paraguaçu","3147204"],["MG","Paraisópolis","3147303"],["MG","Paraopeba","3147402"],["MG","Passa Quatro","3147600"],["MG","Passa Tempo","3147709"],["MG","Passa Vinte","3147808"],["MG","Passabém","3147501"],["MG","Passos","3147907"],["MG","Patis","3147956"],["MG","Patos de Minas","3148004"],["MG","Patrocínio","3148103"],["MG","Patrocínio do Muriaé","3148202"],["MG","Paula Cândido","3148301"],["MG","Paulistas","3148400"],["MG","Pavão","3148509"],["MG","Peçanha","3148608"],["MG","Pedra Azul","3148707"],["MG","Pedra Bonita","3148756"],["MG","Pedra do Anta","3148806"],["MG","Pedra do Indaiá","3148905"],["MG","Pedra Dourada","3149002"],["MG","Pedralva","3149101"],["MG","Pedras de Maria da Cruz","3149150"],["MG","Pedrinópolis","3149200"],["MG","Pedro Leopoldo","3149309"],["MG","Pedro Teixeira","3149408"],["MG","Pequeri","3149507"],["MG","Pequi","3149606"],["MG","Perdigão","3149705"],["MG","Perdizes","3149804"],["MG","Perdões","3149903"],["MG","Periquito","3149952"],["MG","Pescador","3150000"],["MG","Piau","3150109"],["MG","Piedade de Caratinga","3150158"],["MG","Piedade de Ponte Nova","3150208"],["MG","Piedade do Rio Grande","3150307"],["MG","Piedade dos Gerais","3150406"],["MG","Pimenta","3150505"],["MG","Pingo-d'Água","3150539"],["MG","Pintópolis","3150570"],["MG","Piracema","3150604"],["MG","Pirajuba","3150703"],["MG","Piranga","3150802"],["MG","Piranguçu","3150901"],["MG","Piranguinho","3151008"],["MG","Pirapetinga","3151107"],["MG","Pirapora","3151206"],["MG","Piraúba","3151305"],["MG","Pitangui","3151404"],["MG","Piumhi","3151503"],["MG","Planura","3151602"],["MG","Poço Fundo","3151701"],["MG","Poços de Caldas","3151800"],["MG","Pocrane","3151909"],["MG","Pompéu","3152006"],["MG","Ponte Nova","3152105"],["MG","Ponto Chique","3152131"],["MG","Ponto dos Volantes","3152170"],["MG","Porteirinha","3152204"],["MG","Porto Firme","3152303"],["MG","Poté","3152402"],["MG","Pouso Alegre","3152501"],["MG","Pouso Alto","3152600"],["MG","Prados","3152709"],["MG","Prata","3152808"],["MG","Pratápolis","3152907"],["MG","Pratinha","3153004"],["MG","Presidente Bernardes","3153103"],["MG","Presidente Juscelino","3153202"],["MG","Presidente Kubitschek","3153301"],["MG","Presidente Olegário","3153400"],["MG","Prudente de Morais","3153608"],["MG","Quartel Geral","3153707"],["MG","Queluzito","3153806"],["MG","Raposos","3153905"],["MG","Raul Soares","3154002"],["MG","Recreio","3154101"],["MG","Reduto","3154150"],["MG","Resende Costa","3154200"],["MG","Resplendor","3154309"],["MG","Ressaquinha","3154408"],["MG","Riachinho","3154457"],["MG","Riacho dos Machados","3154507"],["MG","Ribeirão das Neves","3154606"],["MG","Ribeirão Vermelho","3154705"],["MG","Rio Acima","3154804"],["MG","Rio Casca","3154903"],["MG","Rio do Prado","3155108"],["MG","Rio Doce","3155009"],["MG","Rio Espera","3155207"],["MG","Rio Manso","3155306"],["MG","Rio Novo","3155405"],["MG","Rio Paranaíba","3155504"],["MG","Rio Pardo de Minas","3155603"],["MG","Rio Piracicaba","3155702"],["MG","Rio Pomba","3155801"],["MG","Rio Preto","3155900"],["MG","Rio Vermelho","3156007"],["MG","Ritápolis","3156106"],["MG","Rochedo de Minas","3156205"],["MG","Rodeiro","3156304"],["MG","Romaria","3156403"],["MG","Rosário da Limeira","3156452"],["MG","Rubelita","3156502"],["MG","Rubim","3156601"],["MG","Sabará","3156700"],["MG","Sabinópolis","3156809"],["MG","Sacramento","3156908"],["MG","Salinas","3157005"],["MG","Salto da Divisa","3157104"],["MG","Santa Bárbara","3157203"],["MG","Santa Bárbara do Leste","3157252"],["MG","Santa Bárbara do Monte Verde","3157278"],["MG","Santa Bárbara do Tugúrio","3157302"],["MG","Santa Cruz de Minas","3157336"],["MG","Santa Cruz de Salinas","3157377"],["MG","Santa Cruz do Escalvado","3157401"],["MG","Santa Efigênia de Minas","3157500"],["MG","Santa Fé de Minas","3157609"],["MG","Santa Helena de Minas","3157658"],["MG","Santa Juliana","3157708"],["MG","Santa Luzia","3157807"],["MG","Santa Margarida","3157906"],["MG","Santa Maria de Itabira","3158003"],["MG","Santa Maria do Salto","3158102"],["MG","Santa Maria do Suaçuí","3158201"],["MG","Santa Rita de Caldas","3159209"],["MG","Santa Rita de Ibitipoca","3159407"],["MG","Santa Rita de Jacutinga","3159308"],["MG","Santa Rita de Minas","3159357"],["MG","Santa Rita do Itueto","3159506"],["MG","Santa Rita do Sapucaí","3159605"],["MG","Santa Rosa da Serra","3159704"],["MG","Santa Vitória","3159803"],["MG","Santana da Vargem","3158300"],["MG","Santana de Cataguases","3158409"],["MG","Santana de Pirapama","3158508"],["MG","Santana do Deserto","3158607"],["MG","Santana do Garambéu","3158706"],["MG","Santana do Jacaré","3158805"],["MG","Santana do Manhuaçu","3158904"],["MG","Santana do Paraíso","3158953"],["MG","Santana do Riacho","3159001"],["MG","Santana dos Montes","3159100"],["MG","Santo Antônio do Amparo","3159902"],["MG","Santo Antônio do Aventureiro","3160009"],["MG","Santo Antônio do Grama","3160108"],["MG","Santo Antônio do Itambé","3160207"],["MG","Santo Antônio do Jacinto","3160306"],["MG","Santo Antônio do Monte","3160405"],["MG","Santo Antônio do Retiro","3160454"],["MG","Santo Antônio do Rio Abaixo","3160504"],["MG","Santo Hipólito","3160603"],["MG","Santos Dumont","3160702"],["MG","São Bento Abade","3160801"],["MG","São Brás do Suaçuí","3160900"],["MG","São Domingos das Dores","3160959"],["MG","São Domingos do Prata","3161007"],["MG","São Félix de Minas","3161056"],["MG","São Francisco","3161106"],["MG","São Francisco de Paula","3161205"],["MG","São Francisco de Sales","3161304"],["MG","São Francisco do Glória","3161403"],["MG","São Geraldo","3161502"],["MG","São Geraldo da Piedade","3161601"],["MG","São Geraldo do Baixio","3161650"],["MG","São Gonçalo do Abaeté","3161700"],["MG","São Gonçalo do Pará","3161809"],["MG","São Gonçalo do Rio Abaixo","3161908"],["MG","São Gonçalo do Rio Preto","3125507"],["MG","São Gonçalo do Sapucaí","3162005"],["MG","São Gotardo","3162104"],["MG","São João Batista do Glória","3162203"],["MG","São João da Lagoa","3162252"],["MG","São João da Mata","3162302"],["MG","São João da Ponte","3162401"],["MG","São João das Missões","3162450"],["MG","São João del Rei","3162500"],["MG","São João do Manhuaçu","3162559"],["MG","São João do Manteninha","3162575"],["MG","São João do Oriente","3162609"],["MG","São João do Pacuí","3162658"],["MG","São João do Paraíso","3162708"],["MG","São João Evangelista","3162807"],["MG","São João Nepomuceno","3162906"],["MG","São Joaquim de Bicas","3162922"],["MG","São José da Barra","3162948"],["MG","São José da Lapa","3162955"],["MG","São José da Safira","3163003"],["MG","São José da Varginha","3163102"],["MG","São José do Alegre","3163201"],["MG","São José do Divino","3163300"],["MG","São José do Goiabal","3163409"],["MG","São José do Jacuri","3163508"],["MG","São José do Mantimento","3163607"],["MG","São Lourenço","3163706"],["MG","São Miguel do Anta","3163805"],["MG","São Pedro da União","3163904"],["MG","São Pedro do Suaçuí","3164100"],["MG","São Pedro dos Ferros","3164001"],["MG","São Romão","3164209"],["MG","São Roque de Minas","3164308"],["MG","São Sebastião da Bela Vista","3164407"],["MG","São Sebastião da Vargem Alegre","3164431"],["MG","São Sebastião do Anta","3164472"],["MG","São Sebastião do Maranhão","3164506"],["MG","São Sebastião do Oeste","3164605"],["MG","São Sebastião do Paraíso","3164704"],["MG","São Sebastião do Rio Preto","3164803"],["MG","São Sebastião do Rio Verde","3164902"],["MG","São Tiago","3165008"],["MG","São Tomás de Aquino","3165107"],["MG","São Tomé das Letras","3165206"],["MG","São Vicente de Minas","3165305"],["MG","Sapucaí-Mirim","3165404"],["MG","Sardoá","3165503"],["MG","Sarzedo","3165537"],["MG","Sem-Peixe","3165560"],["MG","Senador Amaral","3165578"],["MG","Senador Cortes","3165602"],["MG","Senador Firmino","3165701"],["MG","Senador José Bento","3165800"],["MG","Senador Modestino Gonçalves","3165909"],["MG","Senhora de Oliveira","3166006"],["MG","Senhora do Porto","3166105"],["MG","Senhora dos Remédios","3166204"],["MG","Sericita","3166303"],["MG","Seritinga","3166402"],["MG","Serra Azul de Minas","3166501"],["MG","Serra da Saudade","3166600"],["MG","Serra do Salitre","3166808"],["MG","Serra dos Aimorés","3166709"],["MG","Serrania","3166907"],["MG","Serranópolis de Minas","3166956"],["MG","Serranos","3167004"],["MG","Serro","3167103"],["MG","Sete Lagoas","3167202"],["MG","Setubinha","3165552"],["MG","Silveirânia","3167301"],["MG","Silvianópolis","3167400"],["MG","Simão Pereira","3167509"],["MG","Simonésia","3167608"],["MG","Sobrália","3167707"],["MG","Soledade de Minas","3167806"],["MG","Tabuleiro","3167905"],["MG","Taiobeiras","3168002"],["MG","Taparuba","3168051"],["MG","Tapira","3168101"],["MG","Tapiraí","3168200"],["MG","Taquaraçu de Minas","3168309"],["MG","Tarumirim","3168408"],["MG","Teixeiras","3168507"],["MG","Teófilo Otoni","3168606"],["MG","Timóteo","3168705"],["MG","Tiradentes","3168804"],["MG","Tiros","3168903"],["MG","Tocantins","3169000"],["MG","Tocos do Moji","3169059"],["MG","Toledo","3169109"],["MG","Tombos","3169208"],["MG","Três Corações","3169307"],["MG","Três Marias","3169356"],["MG","Três Pontas","3169406"],["MG","Tumiritinga","3169505"],["MG","Tupaciguara","3169604"],["MG","Turmalina","3169703"],["MG","Turvolândia","3169802"],["MG","Ubá","3169901"],["MG","Ubaí","3170008"],["MG","Ubaporanga","3170057"],["MG","Uberaba","3170107"],["MG","Uberlândia","3170206"],["MG","Umburatiba","3170305"],["MG","Unaí","3170404"],["MG","União de Minas","3170438"],["MG","Uruana de Minas","3170479"],["MG","Urucânia","3170503"],["MG","Urucuia","3170529"],["MG","Vargem Alegre","3170578"],["MG","Vargem Bonita","3170602"],["MG","Vargem Grande do Rio Pardo","3170651"],["MG","Varginha","3170701"],["MG","Varjão de Minas","3170750"],["MG","Várzea da Palma","3170800"],["MG","Varzelândia","3170909"],["MG","Vazante","3171006"],["MG","Verdelândia","3171030"],["MG","Veredinha","3171071"],["MG","Veríssimo","3171105"],["MG","Vermelho Novo","3171154"],["MG","Vespasiano","3171204"],["MG","Viçosa","3171303"],["MG","Vieiras","3171402"],["MG","Virgem da Lapa","3171600"],["MG","Virgínia","3171709"],["MG","Virginópolis","3171808"],["MG","Virgolândia","3171907"],["MG","Visconde do Rio Branco","3172004"],["MG","Volta Grande","3172103"],["MG","Wenceslau Braz","3172202"],["PA","Abaetetuba","1500107"],["PA","Abel Figueiredo","1500131"],["PA","Acará","1500206"],["PA","Afuá","1500305"],["PA","Água Azul do Norte","1500347"],["PA","Alenquer","1500404"],["PA","Almeirim","1500503"],["PA","Altamira","1500602"],["PA","Anajás","1500701"],["PA","Ananindeua","1500800"],["PA","Anapu","1500859"],["PA","Augusto Corrêa","1500909"],["PA","Aurora do Pará","1500958"],["PA","Aveiro","1501006"],["PA","Bagre","1501105"],["PA","Baião","1501204"],["PA","Bannach","1501253"],["PA","Barcarena","1501303"],["PA","Belém","1501402"],["PA","Belterra","1501451"],["PA","Benevides","1501501"],["PA","Bom Jesus do Tocantins","1501576"],["PA","Bonito","1501600"],["PA","Bragança","1501709"],["PA","Brasil Novo","1501725"],["PA","Brejo Grande do Araguaia","1501758"],["PA","Breu Branco","1501782"],["PA","Breves","1501808"],["PA","Bujaru","1501907"],["PA","Cachoeira do Arari","1502004"],["PA","Cachoeira do Piriá","1501956"],["PA","Cametá","1502103"],["PA","Canaã dos Carajás","1502152"],["PA","Capanema","1502202"],["PA","Capitão Poço","1502301"],["PA","Castanhal","1502400"],["PA","Chaves","1502509"],["PA","Colares","1502608"],["PA","Conceição do Araguaia","1502707"],["PA","Concórdia do Pará","1502756"],["PA","Cumaru do Norte","1502764"],["PA","Curionópolis","1502772"],["PA","Curralinho","1502806"],["PA","Curuá","1502855"],["PA","Curuçá","1502905"],["PA","Dom Eliseu","1502939"],["PA","Eldorado do Carajás","1502954"],["PA","Faro","1503002"],["PA","Floresta do Araguaia","1503044"],["PA","Garrafão do Norte","1503077"],["PA","Goianésia do Pará","1503093"],["PA","Gurupá","1503101"],["PA","Igarapé-Açu","1503200"],["PA","Igarapé-Miri","1503309"],["PA","Inhangapi","1503408"],["PA","Ipixuna do Pará","1503457"],["PA","Irituia","1503507"],["PA","Itaituba","1503606"],["PA","Itupiranga","1503705"],["PA","Jacareacanga","1503754"],["PA","Jacundá","1503804"],["PA","Juruti","1503903"],["PA","Limoeiro do Ajuru","1504000"],["PA","Mãe do Rio","1504059"],["PA","Magalhães Barata","1504109"],["PA","Marabá","1504208"],["PA","Maracanã","1504307"],["PA","Marapanim","1504406"],["PA","Marituba","1504422"],["PA","Medicilândia","1504455"],["PA","Melgaço","1504505"],["PA","Mocajuba","1504604"],["PA","Moju","1504703"],["PA","Mojuí dos Campos","1504752"],["PA","Monte Alegre","1504802"],["PA","Muaná","1504901"],["PA","Nova Esperança do Piriá","1504950"],["PA","Nova Ipixuna","1504976"],["PA","Nova Timboteua","1505007"],["PA","Novo Progresso","1505031"],["PA","Novo Repartimento","1505064"],["PA","Óbidos","1505106"],["PA","Oeiras do Pará","1505205"],["PA","Oriximiná","1505304"],["PA","Ourém","1505403"],["PA","Ourilândia do Norte","1505437"],["PA","Pacajá","1505486"],["PA","Palestina do Pará","1505494"],["PA","Paragominas","1505502"],["PA","Parauapebas","1505536"],["PA","Pau D'Arco","1505551"],["PA","Peixe-Boi","1505601"],["PA","Piçarra","1505635"],["PA","Placas","1505650"],["PA","Ponta de Pedras","1505700"],["PA","Portel","1505809"],["PA","Porto de Moz","1505908"],["PA","Prainha","1506005"],["PA","Primavera","1506104"],["PA","Quatipuru","1506112"],["PA","Redenção","1506138"],["PA","Rio Maria","1506161"],["PA","Rondon do Pará","1506187"],["PA","Rurópolis","1506195"],["PA","Salinópolis","1506203"],["PA","Salvaterra","1506302"],["PA","Santa Bárbara do Pará","1506351"],["PA","Santa Cruz do Arari","1506401"],["PA","Santa Izabel do Pará","1506500"],["PA","Santa Luzia do Pará","1506559"],["PA","Santa Maria das Barreiras","1506583"],["PA","Santa Maria do Pará","1506609"],["PA","Santana do Araguaia","1506708"],["PA","Santarém","1506807"],["PA","Santarém Novo","1506906"],["PA","Santo Antônio do Tauá","1507003"],["PA","São Caetano de Odivelas","1507102"],["PA","São Domingos do Araguaia","1507151"],["PA","São Domingos do Capim","1507201"],["PA","São Félix do Xingu","1507300"],["PA","São Francisco do Pará","1507409"],["PA","São Geraldo do Araguaia","1507458"],["PA","São João da Ponta","1507466"],["PA","São João de Pirabas","1507474"],["PA","São João do Araguaia","1507508"],["PA","São Miguel do Guamá","1507607"],["PA","São Sebastião da Boa Vista","1507706"],["PA","Sapucaia","1507755"],["PA","Senador José Porfírio","1507805"],["PA","Soure","1507904"],["PA","Tailândia","1507953"],["PA","Terra Alta","1507961"],["PA","Terra Santa","1507979"],["PA","Tomé-Açu","1508001"],["PA","Tracuateua","1508035"],["PA","Trairão","1508050"],["PA","Tucumã","1508084"],["PA","Tucuruí","1508100"],["PA","Ulianópolis","1508126"],["PA","Uruará","1508159"],["PA","Vigia","1508209"],["PA","Viseu","1508308"],["PA","Vitória do Xingu","1508357"],["PA","Xinguara","1508407"],["PB","Água Branca","2500106"],["PB","Aguiar","2500205"],["PB","Alagoa Grande","2500304"],["PB","Alagoa Nova","2500403"],["PB","Alagoinha","2500502"],["PB","Alcantil","2500536"],["PB","Algodão de Jandaíra","2500577"],["PB","Alhandra","2500601"],["PB","Amparo","2500734"],["PB","Aparecida","2500775"],["PB","Araçagi","2500809"],["PB","Arara","2500908"],["PB","Araruna","2501005"],["PB","Areia","2501104"],["PB","Areia de Baraúnas","2501153"],["PB","Areial","2501203"],["PB","Aroeiras","2501302"],["PB","Assunção","2501351"],["PB","Baía da Traição","2501401"],["PB","Bananeiras","2501500"],["PB","Baraúna","2501534"],["PB","Barra de Santa Rosa","2501609"],["PB","Barra de Santana","2501575"],["PB","Barra de São Miguel","2501708"],["PB","Bayeux","2501807"],["PB","Belém","2501906"],["PB","Belém do Brejo do Cruz","2502003"],["PB","Bernardino Batista","2502052"],["PB","Boa Ventura","2502102"],["PB","Boa Vista","2502151"],["PB","Bom Jesus","2502201"],["PB","Bom Sucesso","2502300"],["PB","Bonito de Santa Fé","2502409"],["PB","Boqueirão","2502508"],["PB","Borborema","2502706"],["PB","Brejo do Cruz","2502805"],["PB","Brejo dos Santos","2502904"],["PB","Caaporã","2503001"],["PB","Cabaceiras","2503100"],["PB","Cabedelo","2503209"],["PB","Cachoeira dos Índios","2503308"],["PB","Cacimba de Areia","2503407"],["PB","Cacimba de Dentro","2503506"],["PB","Cacimbas","2503555"],["PB","Caiçara","2503605"],["PB","Cajazeiras","2503704"],["PB","Cajazeirinhas","2503753"],["PB","Caldas Brandão","2503803"],["PB","Camalaú","2503902"],["PB","Campina Grande","2504009"],["PB","Capim","2504033"],["PB","Caraúbas","2504074"],["PB","Carrapateira","2504108"],["PB","Casserengue","2504157"],["PB","Catingueira","2504207"],["PB","Catolé do Rocha","2504306"],["PB","Caturité","2504355"],["PB","Conceição","2504405"],["PB","Condado","2504504"],["PB","Conde","2504603"],["PB","Congo","2504702"],["PB","Coremas","2504801"],["PB","Coxixola","2504850"],["PB","Cruz do Espírito Santo","2504900"],["PB","Cubati","2505006"],["PB","Cuité","2505105"],["PB","Cuité de Mamanguape","2505238"],["PB","Cuitegi","2505204"],["PB","Curral de Cima","2505279"],["PB","Curral Velho","2505303"],["PB","Damião","2505352"],["PB","Desterro","2505402"],["PB","Diamante","2505600"],["PB","Dona Inês","2505709"],["PB","Duas Estradas","2505808"],["PB","Emas","2505907"],["PB","Esperança","2506004"],["PB","Fagundes","2506103"],["PB","Frei Martinho","2506202"],["PB","Gado Bravo","2506251"],["PB","Guarabira","2506301"],["PB","Gurinhém","2506400"],["PB","Gurjão","2506509"],["PB","Ibiara","2506608"],["PB","Igaracy","2502607"],["PB","Imaculada","2506707"],["PB","Ingá","2506806"],["PB","Itabaiana","2506905"],["PB","Itaporanga","2507002"],["PB","Itapororoca","2507101"],["PB","Itatuba","2507200"],["PB","Jacaraú","2507309"],["PB","Jericó","2507408"],["PB","João Pessoa","2507507"],["PB","Joca Claudino","2513653"],["PB","Juarez Távora","2507606"],["PB","Juazeirinho","2507705"],["PB","Junco do Seridó","2507804"],["PB","Juripiranga","2507903"],["PB","Juru","2508000"],["PB","Lagoa","2508109"],["PB","Lagoa de Dentro","2508208"],["PB","Lagoa Seca","2508307"],["PB","Lastro","2508406"],["PB","Livramento","2508505"],["PB","Logradouro","2508554"],["PB","Lucena","2508604"],["PB","Mãe d'Água","2508703"],["PB","Malta","2508802"],["PB","Mamanguape","2508901"],["PB","Manaíra","2509008"],["PB","Marcação","2509057"],["PB","Mari","2509107"],["PB","Marizópolis","2509156"],["PB","Massaranduba","2509206"],["PB","Mataraca","2509305"],["PB","Matinhas","2509339"],["PB","Mato Grosso","2509370"],["PB","Maturéia","2509396"],["PB","Mogeiro","2509404"],["PB","Montadas","2509503"],["PB","Monte Horebe","2509602"],["PB","Monteiro","2509701"],["PB","Mulungu","2509800"],["PB","Natuba","2509909"],["PB","Nazarezinho","2510006"],["PB","Nova Floresta","2510105"],["PB","Nova Olinda","2510204"],["PB","Nova Palmeira","2510303"],["PB","Olho d'Água","2510402"],["PB","Olivedos","2510501"],["PB","Ouro Velho","2510600"],["PB","Parari","2510659"],["PB","Passagem","2510709"],["PB","Patos","2510808"],["PB","Paulista","2510907"],["PB","Pedra Branca","2511004"],["PB","Pedra Lavrada","2511103"],["PB","Pedras de Fogo","2511202"],["PB","Pedro Régis","2512721"],["PB","Piancó","2511301"],["PB","Picuí","2511400"],["PB","Pilar","2511509"],["PB","Pilões","2511608"],["PB","Pilõezinhos","2511707"],["PB","Pirpirituba","2511806"],["PB","Pitimbu","2511905"],["PB","Pocinhos","2512002"],["PB","Poço Dantas","2512036"],["PB","Poço de José de Moura","2512077"],["PB","Pombal","2512101"],["PB","Prata","2512200"],["PB","Princesa Isabel","2512309"],["PB","Puxinanã","2512408"],["PB","Queimadas","2512507"],["PB","Quixaba","2512606"],["PB","Remígio","2512705"],["PB","Riachão","2512747"],["PB","Riachão do Bacamarte","2512754"],["PB","Riachão do Poço","2512762"],["PB","Riacho de Santo Antônio","2512788"],["PB","Riacho dos Cavalos","2512804"],["PB","Rio Tinto","2512903"],["PB","Salgadinho","2513000"],["PB","Salgado de São Félix","2513109"],["PB","Santa Cecília","2513158"],["PB","Santa Cruz","2513208"],["PB","Santa Helena","2513307"],["PB","Santa Inês","2513356"],["PB","Santa Luzia","2513406"],["PB","Santa Rita","2513703"],["PB","Santa Teresinha","2513802"],["PB","Santana de Mangueira","2513505"],["PB","Santana dos Garrotes","2513604"],["PB","Santo André","2513851"],["PB","São Bentinho","2513927"],["PB","São Bento","2513901"],["PB","São Domingos","2513968"],["PB","São Domingos do Cariri","2513943"],["PB","São Francisco","2513984"],["PB","São João do Cariri","2514008"],["PB","São João do Rio do Peixe","2500700"],["PB","São João do Tigre","2514107"],["PB","São José da Lagoa Tapada","2514206"],["PB","São José de Caiana","2514305"],["PB","São José de Espinharas","2514404"],["PB","São José de Piranhas","2514503"],["PB","São José de Princesa","2514552"],["PB","São José do Bonfim","2514602"],["PB","São José do Brejo do Cruz","2514651"],["PB","São José do Sabugi","2514701"],["PB","São José dos Cordeiros","2514800"],["PB","São José dos Ramos","2514453"],["PB","São Mamede","2514909"],["PB","São Miguel de Taipu","2515005"],["PB","São Sebastião de Lagoa de Roça","2515104"],["PB","São Sebastião do Umbuzeiro","2515203"],["PB","São Vicente do Seridó","2515401"],["PB","Sapé","2515302"],["PB","Serra Branca","2515500"],["PB","Serra da Raiz","2515609"],["PB","Serra Grande","2515708"],["PB","Serra Redonda","2515807"],["PB","Serraria","2515906"],["PB","Sertãozinho","2515930"],["PB","Sobrado","2515971"],["PB","Solânea","2516003"],["PB","Soledade","2516102"],["PB","Sossêgo","2516151"],["PB","Sousa","2516201"],["PB","Sumé","2516300"],["PB","Tacima","2516409"],["PB","Taperoá","2516508"],["PB","Tavares","2516607"],["PB","Teixeira","2516706"],["PB","Tenório","2516755"],["PB","Triunfo","2516805"],["PB","Uiraúna","2516904"],["PB","Umbuzeiro","2517001"],["PB","Várzea","2517100"],["PB","Vieirópolis","2517209"],["PB","Vista Serrana","2505501"],["PB","Zabelê","2517407"],["PR","Abatiá","4100103"],["PR","Adrianópolis","4100202"],["PR","Agudos do Sul","4100301"],["PR","Almirante Tamandaré","4100400"],["PR","Altamira do Paraná","4100459"],["PR","Alto Paraíso","4128625"],["PR","Alto Paraná","4100608"],["PR","Alto Piquiri","4100707"],["PR","Altônia","4100509"],["PR","Alvorada do Sul","4100806"],["PR","Amaporã","4100905"],["PR","Ampére","4101002"],["PR","Anahy","4101051"],["PR","Andirá","4101101"],["PR","Ângulo","4101150"],["PR","Antonina","4101200"],["PR","Antônio Olinto","4101309"],["PR","Apucarana","4101408"],["PR","Arapongas","4101507"],["PR","Arapoti","4101606"],["PR","Arapuã","4101655"],["PR","Araruna","4101705"],["PR","Araucária","4101804"],["PR","Ariranha do Ivaí","4101853"],["PR","Assaí","4101903"],["PR","Assis Chateaubriand","4102000"],["PR","Astorga","4102109"],["PR","Atalaia","4102208"],["PR","Balsa Nova","4102307"],["PR","Bandeirantes","4102406"],["PR","Barbosa Ferraz","4102505"],["PR","Barra do Jacaré","4102703"],["PR","Barracão","4102604"],["PR","Bela Vista da Caroba","4102752"],["PR","Bela Vista do Paraíso","4102802"],["PR","Bituruna","4102901"],["PR","Boa Esperança","4103008"],["PR","Boa Esperança do Iguaçu","4103024"],["PR","Boa Ventura de São Roque","4103040"],["PR","Boa Vista da Aparecida","4103057"],["PR","Bocaiúva do Sul","4103107"],["PR","Bom Jesus do Sul","4103156"],["PR","Bom Sucesso","4103206"],["PR","Bom Sucesso do Sul","4103222"],["PR","Borrazópolis","4103305"],["PR","Braganey","4103354"],["PR","Brasilândia do Sul","4103370"],["PR","Cafeara","4103404"],["PR","Cafelândia","4103453"],["PR","Cafezal do Sul","4103479"],["PR","Califórnia","4103503"],["PR","Cambará","4103602"],["PR","Cambé","4103701"],["PR","Cambira","4103800"],["PR","Campina da Lagoa","4103909"],["PR","Campina do Simão","4103958"],["PR","Campina Grande do Sul","4104006"],["PR","Campo Bonito","4104055"],["PR","Campo do Tenente","4104105"],["PR","Campo Largo","4104204"],["PR","Campo Magro","4104253"],["PR","Campo Mourão","4104303"],["PR","Cândido de Abreu","4104402"],["PR","Candói","4104428"],["PR","Cantagalo","4104451"],["PR","Capanema","4104501"],["PR","Capitão Leônidas Marques","4104600"],["PR","Carambeí","4104659"],["PR","Carlópolis","4104709"],["PR","Cascavel","4104808"],["PR","Castro","4104907"],["PR","Catanduvas","4105003"],["PR","Centenário do Sul","4105102"],["PR","Cerro Azul","4105201"],["PR","Céu Azul","4105300"],["PR","Chopinzinho","4105409"],["PR","Cianorte","4105508"],["PR","Cidade Gaúcha","4105607"],["PR","Clevelândia","4105706"],["PR","Colombo","4105805"],["PR","Colorado","4105904"],["PR","Congonhinhas","4106001"],["PR","Conselheiro Mairinck","4106100"],["PR","Contenda","4106209"],["PR","Corbélia","4106308"],["PR","Cornélio Procópio","4106407"],["PR","Coronel Domingos Soares","4106456"],["PR","Coronel Vivida","4106506"],["PR","Corumbataí do Sul","4106555"],["PR","Cruz Machado","4106803"],["PR","Cruzeiro do Iguaçu","4106571"],["PR","Cruzeiro do Oeste","4106605"],["PR","Cruzeiro do Sul","4106704"],["PR","Cruzmaltina","4106852"],["PR","Curitiba","4106902"],["PR","Curiúva","4107009"],["PR","Diamante D'Oeste","4107157"],["PR","Diamante do Norte","4107108"],["PR","Diamante do Sul","4107124"],["PR","Dois Vizinhos","4107207"],["PR","Douradina","4107256"],["PR","Doutor Camargo","4107306"],["PR","Doutor Ulysses","4128633"],["PR","Enéas Marques","4107405"],["PR","Engenheiro Beltrão","4107504"],["PR","Entre Rios do Oeste","4107538"],["PR","Esperança Nova","4107520"],["PR","Espigão Alto do Iguaçu","4107546"],["PR","Farol","4107553"],["PR","Faxinal","4107603"],["PR","Fazenda Rio Grande","4107652"],["PR","Fênix","4107702"],["PR","Fernandes Pinheiro","4107736"],["PR","Figueira","4107751"],["PR","Flor da Serra do Sul","4107850"],["PR","Floraí","4107801"],["PR","Floresta","4107900"],["PR","Florestópolis","4108007"],["PR","Flórida","4108106"],["PR","Formosa do Oeste","4108205"],["PR","Foz do Iguaçu","4108304"],["PR","Foz do Jordão","4108452"],["PR","Francisco Alves","4108320"],["PR","Francisco Beltrão","4108403"],["PR","General Carneiro","4108502"],["PR","Godoy Moreira","4108551"],["PR","Goioerê","4108601"],["PR","Goioxim","4108650"],["PR","Grandes Rios","4108700"],["PR","Guaíra","4108809"],["PR","Guairaçá","4108908"],["PR","Guamiranga","4108957"],["PR","Guapirama","4109005"],["PR","Guaporema","4109104"],["PR","Guaraci","4109203"],["PR","Guaraniaçu","4109302"],["PR","Guarapuava","4109401"],["PR","Guaraqueçaba","4109500"],["PR","Guaratuba","4109609"],["PR","Honório Serpa","4109658"],["PR","Ibaiti","4109708"],["PR","Ibema","4109757"],["PR","Ibiporã","4109807"],["PR","Icaraíma","4109906"],["PR","Iguaraçu","4110003"],["PR","Iguatu","4110052"],["PR","Imbaú","4110078"],["PR","Imbituva","4110102"],["PR","Inácio Martins","4110201"],["PR","Inajá","4110300"],["PR","Indianópolis","4110409"],["PR","Ipiranga","4110508"],["PR","Iporã","4110607"],["PR","Iracema do Oeste","4110656"],["PR","Irati","4110706"],["PR","Iretama","4110805"],["PR","Itaguajé","4110904"],["PR","Itaipulândia","4110953"],["PR","Itambaracá","4111001"],["PR","Itambé","4111100"],["PR","Itapejara d'Oeste","4111209"],["PR","Itaperuçu","4111258"],["PR","Itaúna do Sul","4111308"],["PR","Ivaí","4111407"],["PR","Ivaiporã","4111506"],["PR","Ivaté","4111555"],["PR","Ivatuba","4111605"],["PR","Jaboti","4111704"],["PR","Jacarezinho","4111803"],["PR","Jaguapitã","4111902"],["PR","Jaguariaíva","4112009"],["PR","Jandaia do Sul","4112108"],["PR","Janiópolis","4112207"],["PR","Japira","4112306"],["PR","Japurá","4112405"],["PR","Jardim Alegre","4112504"],["PR","Jardim Olinda","4112603"],["PR","Jataizinho","4112702"],["PR","Jesuítas","4112751"],["PR","Joaquim Távora","4112801"],["PR","Jundiaí do Sul","4112900"],["PR","Juranda","4112959"],["PR","Jussara","4113007"],["PR","Kaloré","4113106"],["PR","Lapa","4113205"],["PR","Laranjal","4113254"],["PR","Laranjeiras do Sul","4113304"],["PR","Leópolis","4113403"],["PR","Lidianópolis","4113429"],["PR","Lindoeste","4113452"],["PR","Loanda","4113502"],["PR","Lobato","4113601"],["PR","Londrina","4113700"],["PR","Luiziana","4113734"],["PR","Lunardelli","4113759"],["PR","Lupionópolis","4113809"],["PR","Mallet","4113908"],["PR","Mamborê","4114005"],["PR","Mandaguaçu","4114104"],["PR","Mandaguari","4114203"],["PR","Mandirituba","4114302"],["PR","Manfrinópolis","4114351"],["PR","Mangueirinha","4114401"],["PR","Manoel Ribas","4114500"],["PR","Marechal Cândido Rondon","4114609"],["PR","Maria Helena","4114708"],["PR","Marialva","4114807"],["PR","Marilândia do Sul","4114906"],["PR","Marilena","4115002"],["PR","Mariluz","4115101"],["PR","Maringá","4115200"],["PR","Mariópolis","4115309"],["PR","Maripá","4115358"],["PR","Marmeleiro","4115408"],["PR","Marquinho","4115457"],["PR","Marumbi","4115507"],["PR","Matelândia","4115606"],["PR","Matinhos","4115705"],["PR","Mato Rico","4115739"],["PR","Mauá da Serra","4115754"],["PR","Medianeira","4115804"],["PR","Mercedes","4115853"],["PR","Mirador","4115903"],["PR","Miraselva","4116000"],["PR","Missal","4116059"],["PR","Moreira Sales","4116109"],["PR","Morretes","4116208"],["PR","Munhoz de Melo","4116307"],["PR","Nossa Senhora das Graças","4116406"],["PR","Nova Aliança do Ivaí","4116505"],["PR","Nova América da Colina","4116604"],["PR","Nova Aurora","4116703"],["PR","Nova Cantu","4116802"],["PR","Nova Esperança","4116901"],["PR","Nova Esperança do Sudoeste","4116950"],["PR","Nova Fátima","4117008"],["PR","Nova Laranjeiras","4117057"],["PR","Nova Londrina","4117107"],["PR","Nova Olímpia","4117206"],["PR","Nova Prata do Iguaçu","4117255"],["PR","Nova Santa Bárbara","4117214"],["PR","Nova Santa Rosa","4117222"],["PR","Nova Tebas","4117271"],["PR","Novo Itacolomi","4117297"],["PR","Ortigueira","4117305"],["PR","Ourizona","4117404"],["PR","Ouro Verde do Oeste","4117453"],["PR","Paiçandu","4117503"],["PR","Palmas","4117602"],["PR","Palmeira","4117701"],["PR","Palmital","4117800"],["PR","Palotina","4117909"],["PR","Paraíso do Norte","4118006"],["PR","Paranacity","4118105"],["PR","Paranaguá","4118204"],["PR","Paranapoema","4118303"],["PR","Paranavaí","4118402"],["PR","Pato Bragado","4118451"],["PR","Pato Branco","4118501"],["PR","Paula Freitas","4118600"],["PR","Paulo Frontin","4118709"],["PR","Peabiru","4118808"],["PR","Perobal","4118857"],["PR","Pérola","4118907"],["PR","Pérola d'Oeste","4119004"],["PR","Piên","4119103"],["PR","Pinhais","4119152"],["PR","Pinhal de São Bento","4119251"],["PR","Pinhalão","4119202"],["PR","Pinhão","4119301"],["PR","Piraí do Sul","4119400"],["PR","Piraquara","4119509"],["PR","Pitanga","4119608"],["PR","Pitangueiras","4119657"],["PR","Planaltina do Paraná","4119707"],["PR","Planalto","4119806"],["PR","Ponta Grossa","4119905"],["PR","Pontal do Paraná","4119954"],["PR","Porecatu","4120002"],["PR","Porto Amazonas","4120101"],["PR","Porto Barreiro","4120150"],["PR","Porto Rico","4120200"],["PR","Porto Vitória","4120309"],["PR","Prado Ferreira","4120333"],["PR","Pranchita","4120358"],["PR","Presidente Castelo Branco","4120408"],["PR","Primeiro de Maio","4120507"],["PR","Prudentópolis","4120606"],["PR","Quarto Centenário","4120655"],["PR","Quatiguá","4120705"],["PR","Quatro Barras","4120804"],["PR","Quatro Pontes","4120853"],["PR","Quedas do Iguaçu","4120903"],["PR","Querência do Norte","4121000"],["PR","Quinta do Sol","4121109"],["PR","Quitandinha","4121208"],["PR","Ramilândia","4121257"],["PR","Rancho Alegre","4121307"],["PR","Rancho Alegre D'Oeste","4121356"],["PR","Realeza","4121406"],["PR","Rebouças","4121505"],["PR","Renascença","4121604"],["PR","Reserva","4121703"],["PR","Reserva do Iguaçu","4121752"],["PR","Ribeirão Claro","4121802"],["PR","Ribeirão do Pinhal","4121901"],["PR","Rio Azul","4122008"],["PR","Rio Bom","4122107"],["PR","Rio Bonito do Iguaçu","4122156"],["PR","Rio Branco do Ivaí","4122172"],["PR","Rio Branco do Sul","4122206"],["PR","Rio Negro","4122305"],["PR","Rolândia","4122404"],["PR","Roncador","4122503"],["PR","Rondon","4122602"],["PR","Rosário do Ivaí","4122651"],["PR","Sabáudia","4122701"],["PR","Salgado Filho","4122800"],["PR","Salto do Itararé","4122909"],["PR","Salto do Lontra","4123006"],["PR","Santa Amélia","4123105"],["PR","Santa Cecília do Pavão","4123204"],["PR","Santa Cruz de Monte Castelo","4123303"],["PR","Santa Fé","4123402"],["PR","Santa Helena","4123501"],["PR","Santa Inês","4123600"],["PR","Santa Isabel do Ivaí","4123709"],["PR","Santa Izabel do Oeste","4123808"],["PR","Santa Lúcia","4123824"],["PR","Santa Maria do Oeste","4123857"],["PR","Santa Mariana","4123907"],["PR","Santa Mônica","4123956"],["PR","Santa Tereza do Oeste","4124020"],["PR","Santa Terezinha de Itaipu","4124053"],["PR","Santana do Itararé","4124004"],["PR","Santo Antônio da Platina","4124103"],["PR","Santo Antônio do Caiuá","4124202"],["PR","Santo Antônio do Paraíso","4124301"],["PR","Santo Antônio do Sudoeste","4124400"],["PR","Santo Inácio","4124509"],["PR","São Carlos do Ivaí","4124608"],["PR","São Jerônimo da Serra","4124707"],["PR","São João","4124806"],["PR","São João do Caiuá","4124905"],["PR","São João do Ivaí","4125001"],["PR","São João do Triunfo","4125100"],["PR","São Jorge d'Oeste","4125209"],["PR","São Jorge do Ivaí","4125308"],["PR","São Jorge do Patrocínio","4125357"],["PR","São José da Boa Vista","4125407"],["PR","São José das Palmeiras","4125456"],["PR","São José dos Pinhais","4125506"],["PR","São Manoel do Paraná","4125555"],["PR","São Mateus do Sul","4125605"],["PR","São Miguel do Iguaçu","4125704"],["PR","São Pedro do Iguaçu","4125753"],["PR","São Pedro do Ivaí","4125803"],["PR","São Pedro do Paraná","4125902"],["PR","São Sebastião da Amoreira","4126009"],["PR","São Tomé","4126108"],["PR","Sapopema","4126207"],["PR","Sarandi","4126256"],["PR","Saudade do Iguaçu","4126272"],["PR","Sengés","4126306"],["PR","Serranópolis do Iguaçu","4126355"],["PR","Sertaneja","4126405"],["PR","Sertanópolis","4126504"],["PR","Siqueira Campos","4126603"],["PR","Sulina","4126652"],["PR","Tamarana","4126678"],["PR","Tamboara","4126702"],["PR","Tapejara","4126801"],["PR","Tapira","4126900"],["PR","Teixeira Soares","4127007"],["PR","Telêmaco Borba","4127106"],["PR","Terra Boa","4127205"],["PR","Terra Rica","4127304"],["PR","Terra Roxa","4127403"],["PR","Tibagi","4127502"],["PR","Tijucas do Sul","4127601"],["PR","Toledo","4127700"],["PR","Tomazina","4127809"],["PR","Três Barras do Paraná","4127858"],["PR","Tunas do Paraná","4127882"],["PR","Tuneiras do Oeste","4127908"],["PR","Tupãssi","4127957"],["PR","Turvo","4127965"],["PR","Ubiratã","4128005"],["PR","Umuarama","4128104"],["PR","União da Vitória","4128203"],["PR","Uniflor","4128302"],["PR","Uraí","4128401"],["PR","Ventania","4128534"],["PR","Vera Cruz do Oeste","4128559"],["PR","Verê","4128609"],["PR","Virmond","4128658"],["PR","Vitorino","4128708"],["PR","Wenceslau Braz","4128500"],["PR","Xambrê","4128807"],["PE","Abreu e Lima","2600054"],["PE","Afogados da Ingazeira","2600104"],["PE","Afrânio","2600203"],["PE","Agrestina","2600302"],["PE","Água Preta","2600401"],["PE","Águas Belas","2600500"],["PE","Alagoinha","2600609"],["PE","Aliança","2600708"],["PE","Altinho","2600807"],["PE","Amaraji","2600906"],["PE","Angelim","2601003"],["PE","Araçoiaba","2601052"],["PE","Araripina","2601102"],["PE","Arcoverde","2601201"],["PE","Barra de Guabiraba","2601300"],["PE","Barreiros","2601409"],["PE","Belém de Maria","2601508"],["PE","Belém do São Francisco","2601607"],["PE","Belo Jardim","2601706"],["PE","Betânia","2601805"],["PE","Bezerros","2601904"],["PE","Bodocó","2602001"],["PE","Bom Conselho","2602100"],["PE","Bom Jardim","2602209"],["PE","Bonito","2602308"],["PE","Brejão","2602407"],["PE","Brejinho","2602506"],["PE","Brejo da Madre de Deus","2602605"],["PE","Buenos Aires","2602704"],["PE","Buíque","2602803"],["PE","Cabo de Santo Agostinho","2602902"],["PE","Cabrobó","2603009"],["PE","Cachoeirinha","2603108"],["PE","Caetés","2603207"],["PE","Calçado","2603306"],["PE","Calumbi","2603405"],["PE","Camaragibe","2603454"],["PE","Camocim de São Félix","2603504"],["PE","Camutanga","2603603"],["PE","Canhotinho","2603702"],["PE","Capoeiras","2603801"],["PE","Carnaíba","2603900"],["PE","Carnaubeira da Penha","2603926"],["PE","Carpina","2604007"],["PE","Caruaru","2604106"],["PE","Casinhas","2604155"],["PE","Catende","2604205"],["PE","Cedro","2604304"],["PE","Chã de Alegria","2604403"],["PE","Chã Grande","2604502"],["PE","Condado","2604601"],["PE","Correntes","2604700"],["PE","Cortês","2604809"],["PE","Cumaru","2604908"],["PE","Cupira","2605004"],["PE","Custódia","2605103"],["PE","Dormentes","2605152"],["PE","Escada","2605202"],["PE","Exu","2605301"],["PE","Feira Nova","2605400"],["PE","Fernando de Noronha","2605459"],["PE","Ferreiros","2605509"],["PE","Flores","2605608"],["PE","Floresta","2605707"],["PE","Frei Miguelinho","2605806"],["PE","Gameleira","2605905"],["PE","Garanhuns","2606002"],["PE","Glória do Goitá","2606101"],["PE","Goiana","2606200"],["PE","Granito","2606309"],["PE","Gravatá","2606408"],["PE","Iati","2606507"],["PE","Ibimirim","2606606"],["PE","Ibirajuba","2606705"],["PE","Igarassu","2606804"],["PE","Iguaracy","2606903"],["PE","Ilha de Itamaracá","2607604"],["PE","Inajá","2607000"],["PE","Ingazeira","2607109"],["PE","Ipojuca","2607208"],["PE","Ipubi","2607307"],["PE","Itacuruba","2607406"],["PE","Itaíba","2607505"],["PE","Itambé","2607653"],["PE","Itapetim","2607703"],["PE","Itapissuma","2607752"],["PE","Itaquitinga","2607802"],["PE","Jaboatão dos Guararapes","2607901"],["PE","Jaqueira","2607950"],["PE","Jataúba","2608008"],["PE","Jatobá","2608057"],["PE","João Alfredo","2608107"],["PE","Joaquim Nabuco","2608206"],["PE","Jucati","2608255"],["PE","Jupi","2608305"],["PE","Jurema","2608404"],["PE","Lagoa de Itaenga","2608503"],["PE","Lagoa do Carro","2608453"],["PE","Lagoa do Ouro","2608602"],["PE","Lagoa dos Gatos","2608701"],["PE","Lagoa Grande","2608750"],["PE","Lajedo","2608800"],["PE","Limoeiro","2608909"],["PE","Macaparana","2609006"],["PE","Machados","2609105"],["PE","Manari","2609154"],["PE","Maraial","2609204"],["PE","Mirandiba","2609303"],["PE","Moreilândia","2614303"],["PE","Moreno","2609402"],["PE","Nazaré da Mata","2609501"],["PE","Olinda","2609600"],["PE","Orobó","2609709"],["PE","Orocó","2609808"],["PE","Ouricuri","2609907"],["PE","Palmares","2610004"],["PE","Palmeirina","2610103"],["PE","Panelas","2610202"],["PE","Paranatama","2610301"],["PE","Parnamirim","2610400"],["PE","Passira","2610509"],["PE","Paudalho","2610608"],["PE","Paulista","2610707"],["PE","Pedra","2610806"],["PE","Pesqueira","2610905"],["PE","Petrolândia","2611002"],["PE","Petrolina","2611101"],["PE","Poção","2611200"],["PE","Pombos","2611309"],["PE","Primavera","2611408"],["PE","Quipapá","2611507"],["PE","Quixaba","2611533"],["PE","Recife","2611606"],["PE","Riacho das Almas","2611705"],["PE","Ribeirão","2611804"],["PE","Rio Formoso","2611903"],["PE","Sairé","2612000"],["PE","Salgadinho","2612109"],["PE","Salgueiro","2612208"],["PE","Saloá","2612307"],["PE","Sanharó","2612406"],["PE","Santa Cruz","2612455"],["PE","Santa Cruz da Baixa Verde","2612471"],["PE","Santa Cruz do Capibaribe","2612505"],["PE","Santa Filomena","2612554"],["PE","Santa Maria da Boa Vista","2612604"],["PE","Santa Maria do Cambucá","2612703"],["PE","Santa Terezinha","2612802"],["PE","São Benedito do Sul","2612901"],["PE","São Bento do Una","2613008"],["PE","São Caitano","2613107"],["PE","São João","2613206"],["PE","São Joaquim do Monte","2613305"],["PE","São José da Coroa Grande","2613404"],["PE","São José do Belmonte","2613503"],["PE","São José do Egito","2613602"],["PE","São Lourenço da Mata","2613701"],["PE","São Vicente Férrer","2613800"],["PE","Serra Talhada","2613909"],["PE","Serrita","2614006"],["PE","Sertânia","2614105"],["PE","Sirinhaém","2614204"],["PE","Solidão","2614402"],["PE","Surubim","2614501"],["PE","Tabira","2614600"],["PE","Tacaimbó","2614709"],["PE","Tacaratu","2614808"],["PE","Tamandaré","2614857"],["PE","Taquaritinga do Norte","2615003"],["PE","Terezinha","2615102"],["PE","Terra Nova","2615201"],["PE","Timbaúba","2615300"],["PE","Toritama","2615409"],["PE","Tracunhaém","2615508"],["PE","Trindade","2615607"],["PE","Triunfo","2615706"],["PE","Tupanatinga","2615805"],["PE","Tuparetama","2615904"],["PE","Venturosa","2616001"],["PE","Verdejante","2616100"],["PE","Vertente do Lério","2616183"],["PE","Vertentes","2616209"],["PE","Vicência","2616308"],["PE","Vitória de Santo Antão","2616407"],["PE","Xexéu","2616506"],["PI","Acauã","2200053"],["PI","Agricolândia","2200103"],["PI","Água Branca","2200202"],["PI","Alagoinha do Piauí","2200251"],["PI","Alegrete do Piauí","2200277"],["PI","Alto Longá","2200301"],["PI","Altos","2200400"],["PI","Alvorada do Gurguéia","2200459"],["PI","Amarante","2200509"],["PI","Angical do Piauí","2200608"],["PI","Anísio de Abreu","2200707"],["PI","Antônio Almeida","2200806"],["PI","Aroazes","2200905"],["PI","Aroeiras do Itaim","2200954"],["PI","Arraial","2201002"],["PI","Assunção do Piauí","2201051"],["PI","Avelino Lopes","2201101"],["PI","Baixa Grande do Ribeiro","2201150"],["PI","Barra D'Alcântara","2201176"],["PI","Barras","2201200"],["PI","Barreiras do Piauí","2201309"],["PI","Barro Duro","2201408"],["PI","Batalha","2201507"],["PI","Bela Vista do Piauí","2201556"],["PI","Belém do Piauí","2201572"],["PI","Beneditinos","2201606"],["PI","Bertolínia","2201705"],["PI","Betânia do Piauí","2201739"],["PI","Boa Hora","2201770"],["PI","Bocaina","2201804"],["PI","Bom Jesus","2201903"],["PI","Bom Princípio do Piauí","2201919"],["PI","Bonfim do Piauí","2201929"],["PI","Boqueirão do Piauí","2201945"],["PI","Brasileira","2201960"],["PI","Brejo do Piauí","2201988"],["PI","Buriti dos Lopes","2202000"],["PI","Buriti dos Montes","2202026"],["PI","Cabeceiras do Piauí","2202059"],["PI","Cajazeiras do Piauí","2202075"],["PI","Cajueiro da Praia","2202083"],["PI","Caldeirão Grande do Piauí","2202091"],["PI","Campinas do Piauí","2202109"],["PI","Campo Alegre do Fidalgo","2202117"],["PI","Campo Grande do Piauí","2202133"],["PI","Campo Largo do Piauí","2202174"],["PI","Campo Maior","2202208"],["PI","Canavieira","2202251"],["PI","Canto do Buriti","2202307"],["PI","Capitão de Campos","2202406"],["PI","Capitão Gervásio Oliveira","2202455"],["PI","Caracol","2202505"],["PI","Caraúbas do Piauí","2202539"],["PI","Caridade do Piauí","2202554"],["PI","Castelo do Piauí","2202604"],["PI","Caxingó","2202653"],["PI","Cocal","2202703"],["PI","Cocal de Telha","2202711"],["PI","Cocal dos Alves","2202729"],["PI","Coivaras","2202737"],["PI","Colônia do Gurguéia","2202752"],["PI","Colônia do Piauí","2202778"],["PI","Conceição do Canindé","2202802"],["PI","Coronel José Dias","2202851"],["PI","Corrente","2202901"],["PI","Cristalândia do Piauí","2203008"],["PI","Cristino Castro","2203107"],["PI","Curimatá","2203206"],["PI","Currais","2203230"],["PI","Curral Novo do Piauí","2203271"],["PI","Curralinhos","2203255"],["PI","Demerval Lobão","2203305"],["PI","Dirceu Arcoverde","2203354"],["PI","Dom Expedito Lopes","2203404"],["PI","Dom Inocêncio","2203453"],["PI","Domingos Mourão","2203420"],["PI","Elesbão Veloso","2203503"],["PI","Eliseu Martins","2203602"],["PI","Esperantina","2203701"],["PI","Fartura do Piauí","2203750"],["PI","Flores do Piauí","2203800"],["PI","Floresta do Piauí","2203859"],["PI","Floriano","2203909"],["PI","Francinópolis","2204006"],["PI","Francisco Ayres","2204105"],["PI","Francisco Macedo","2204154"],["PI","Francisco Santos","2204204"],["PI","Fronteiras","2204303"],["PI","Geminiano","2204352"],["PI","Gilbués","2204402"],["PI","Guadalupe","2204501"],["PI","Guaribas","2204550"],["PI","Hugo Napoleão","2204600"],["PI","Ilha Grande","2204659"],["PI","Inhuma","2204709"],["PI","Ipiranga do Piauí","2204808"],["PI","Isaías Coelho","2204907"],["PI","Itainópolis","2205003"],["PI","Itaueira","2205102"],["PI","Jacobina do Piauí","2205151"],["PI","Jaicós","2205201"],["PI","Jardim do Mulato","2205250"],["PI","Jatobá do Piauí","2205276"],["PI","Jerumenha","2205300"],["PI","João Costa","2205359"],["PI","Joaquim Pires","2205409"],["PI","Joca Marques","2205458"],["PI","José de Freitas","2205508"],["PI","Juazeiro do Piauí","2205516"],["PI","Júlio Borges","2205524"],["PI","Jurema","2205532"],["PI","Lagoa Alegre","2205557"],["PI","Lagoa de São Francisco","2205573"],["PI","Lagoa do Barro do Piauí","2205565"],["PI","Lagoa do Piauí","2205581"],["PI","Lagoa do Sítio","2205599"],["PI","Lagoinha do Piauí","2205540"],["PI","Landri Sales","2205607"],["PI","Luís Correia","2205706"],["PI","Luzilândia","2205805"],["PI","Madeiro","2205854"],["PI","Manoel Emídio","2205904"],["PI","Marcolândia","2205953"],["PI","Marcos Parente","2206001"],["PI","Massapê do Piauí","2206050"],["PI","Matias Olímpio","2206100"],["PI","Miguel Alves","2206209"],["PI","Miguel Leão","2206308"],["PI","Milton Brandão","2206357"],["PI","Monsenhor Gil","2206407"],["PI","Monsenhor Hipólito","2206506"],["PI","Monte Alegre do Piauí","2206605"],["PI","Morro Cabeça no Tempo","2206654"],["PI","Morro do Chapéu do Piauí","2206670"],["PI","Murici dos Portelas","2206696"],["PI","Nazaré do Piauí","2206704"],["PI","Nazária","2206720"],["PI","Nossa Senhora de Nazaré","2206753"],["PI","Nossa Senhora dos Remédios","2206803"],["PI","Nova Santa Rita","2207959"],["PI","Novo Oriente do Piauí","2206902"],["PI","Novo Santo Antônio","2206951"],["PI","Oeiras","2207009"],["PI","Olho D'Água do Piauí","2207108"],["PI","Padre Marcos","2207207"],["PI","Paes Landim","2207306"],["PI","Pajeú do Piauí","2207355"],["PI","Palmeira do Piauí","2207405"],["PI","Palmeirais","2207504"],["PI","Paquetá","2207553"],["PI","Parnaguá","2207603"],["PI","Parnaíba","2207702"],["PI","Passagem Franca do Piauí","2207751"],["PI","Patos do Piauí","2207777"],["PI","Pau D'Arco do Piauí","2207793"],["PI","Paulistana","2207801"],["PI","Pavussu","2207850"],["PI","Pedro II","2207900"],["PI","Pedro Laurentino","2207934"],["PI","Picos","2208007"],["PI","Pimenteiras","2208106"],["PI","Pio IX","2208205"],["PI","Piracuruca","2208304"],["PI","Piripiri","2208403"],["PI","Porto","2208502"],["PI","Porto Alegre do Piauí","2208551"],["PI","Prata do Piauí","2208601"],["PI","Queimada Nova","2208650"],["PI","Redenção do Gurguéia","2208700"],["PI","Regeneração","2208809"],["PI","Riacho Frio","2208858"],["PI","Ribeira do Piauí","2208874"],["PI","Ribeiro Gonçalves","2208908"],["PI","Rio Grande do Piauí","2209005"],["PI","Santa Cruz do Piauí","2209104"],["PI","Santa Cruz dos Milagres","2209153"],["PI","Santa Filomena","2209203"],["PI","Santa Luz","2209302"],["PI","Santa Rosa do Piauí","2209377"],["PI","Santana do Piauí","2209351"],["PI","Santo Antônio de Lisboa","2209401"],["PI","Santo Antônio dos Milagres","2209450"],["PI","Santo Inácio do Piauí","2209500"],["PI","São Braz do Piauí","2209559"],["PI","São Félix do Piauí","2209609"],["PI","São Francisco de Assis do Piauí","2209658"],["PI","São Francisco do Piauí","2209708"],["PI","São Gonçalo do Gurguéia","2209757"],["PI","São Gonçalo do Piauí","2209807"],["PI","São João da Canabrava","2209856"],["PI","São João da Fronteira","2209872"],["PI","São João da Serra","2209906"],["PI","São João da Varjota","2209955"],["PI","São João do Arraial","2209971"],["PI","São João do Piauí","2210003"],["PI","São José do Divino","2210052"],["PI","São José do Peixe","2210102"],["PI","São José do Piauí","2210201"],["PI","São Julião","2210300"],["PI","São Lourenço do Piauí","2210359"],["PI","São Luis do Piauí","2210375"],["PI","São Miguel da Baixa Grande","2210383"],["PI","São Miguel do Fidalgo","2210391"],["PI","São Miguel do Tapuio","2210409"],["PI","São Pedro do Piauí","2210508"],["PI","São Raimundo Nonato","2210607"],["PI","Sebastião Barros","2210623"],["PI","Sebastião Leal","2210631"],["PI","Sigefredo Pacheco","2210656"],["PI","Simões","2210706"],["PI","Simplício Mendes","2210805"],["PI","Socorro do Piauí","2210904"],["PI","Sussuapara","2210938"],["PI","Tamboril do Piauí","2210953"],["PI","Tanque do Piauí","2210979"],["PI","Teresina","2211001"],["PI","União","2211100"],["PI","Uruçuí","2211209"],["PI","Valença do Piauí","2211308"],["PI","Várzea Branca","2211357"],["PI","Várzea Grande","2211407"],["PI","Vera Mendes","2211506"],["PI","Vila Nova do Piauí","2211605"],["PI","Wall Ferraz","2211704"],["RJ","Angra dos Reis","3300100"],["RJ","Aperibé","3300159"],["RJ","Araruama","3300209"],["RJ","Areal","3300225"],["RJ","Armação dos Búzios","3300233"],["RJ","Arraial do Cabo","3300258"],["RJ","Barra do Piraí","3300308"],["RJ","Barra Mansa","3300407"],["RJ","Belford Roxo","3300456"],["RJ","Bom Jardim","3300506"],["RJ","Bom Jesus do Itabapoana","3300605"],["RJ","Cabo Frio","3300704"],["RJ","Cachoeiras de Macacu","3300803"],["RJ","Cambuci","3300902"],["RJ","Campos dos Goytacazes","3301009"],["RJ","Cantagalo","3301108"],["RJ","Carapebus","3300936"],["RJ","Cardoso Moreira","3301157"],["RJ","Carmo","3301207"],["RJ","Casimiro de Abreu","3301306"],["RJ","Comendador Levy Gasparian","3300951"],["RJ","Conceição de Macabu","3301405"],["RJ","Cordeiro","3301504"],["RJ","Duas Barras","3301603"],["RJ","Duque de Caxias","3301702"],["RJ","Engenheiro Paulo de Frontin","3301801"],["RJ","Guapimirim","3301850"],["RJ","Iguaba Grande","3301876"],["RJ","Itaboraí","3301900"],["RJ","Itaguaí","3302007"],["RJ","Italva","3302056"],["RJ","Itaocara","3302106"],["RJ","Itaperuna","3302205"],["RJ","Itatiaia","3302254"],["RJ","Japeri","3302270"],["RJ","Laje do Muriaé","3302304"],["RJ","Macaé","3302403"],["RJ","Macuco","3302452"],["RJ","Magé","3302502"],["RJ","Mangaratiba","3302601"],["RJ","Maricá","3302700"],["RJ","Mendes","3302809"],["RJ","Mesquita","3302858"],["RJ","Miguel Pereira","3302908"],["RJ","Miracema","3303005"],["RJ","Natividade","3303104"],["RJ","Nilópolis","3303203"],["RJ","Niterói","3303302"],["RJ","Nova Friburgo","3303401"],["RJ","Nova Iguaçu","3303500"],["RJ","Paracambi","3303609"],["RJ","Paraíba do Sul","3303708"],["RJ","Paraty","3303807"],["RJ","Paty do Alferes","3303856"],["RJ","Petrópolis","3303906"],["RJ","Pinheiral","3303955"],["RJ","Piraí","3304003"],["RJ","Porciúncula","3304102"],["RJ","Porto Real","3304110"],["RJ","Quatis","3304128"],["RJ","Queimados","3304144"],["RJ","Quissamã","3304151"],["RJ","Resende","3304201"],["RJ","Rio Bonito","3304300"],["RJ","Rio Claro","3304409"],["RJ","Rio das Flores","3304508"],["RJ","Rio das Ostras","3304524"],["RJ","Rio de Janeiro","3304557"],["RJ","Santa Maria Madalena","3304607"],["RJ","Santo Antônio de Pádua","3304706"],["RJ","São Fidélis","3304805"],["RJ","São Francisco de Itabapoana","3304755"],["RJ","São Gonçalo","3304904"],["RJ","São João da Barra","3305000"],["RJ","São João de Meriti","3305109"],["RJ","São José de Ubá","3305133"],["RJ","São José do Vale do Rio Preto","3305158"],["RJ","São Pedro da Aldeia","3305208"],["RJ","São Sebastião do Alto","3305307"],["RJ","Sapucaia","3305406"],["RJ","Saquarema","3305505"],["RJ","Seropédica","3305554"],["RJ","Silva Jardim","3305604"],["RJ","Sumidouro","3305703"],["RJ","Tanguá","3305752"],["RJ","Teresópolis","3305802"],["RJ","Trajano de Moraes","3305901"],["RJ","Três Rios","3306008"],["RJ","Valença","3306107"],["RJ","Varre-Sai","3306156"],["RJ","Vassouras","3306206"],["RJ","Volta Redonda","3306305"],["RN","Acari","2400109"],["RN","Afonso Bezerra","2400307"],["RN","Água Nova","2400406"],["RN","Alexandria","2400505"],["RN","Almino Afonso","2400604"],["RN","Alto do Rodrigues","2400703"],["RN","Angicos","2400802"],["RN","Antônio Martins","2400901"],["RN","Apodi","2401008"],["RN","Areia Branca","2401107"],["RN","Arez","2401206"],["RN","Assú","2400208"],["RN","Baía Formosa","2401404"],["RN","Baraúna","2401453"],["RN","Barcelona","2401503"],["RN","Bento Fernandes","2401602"],["RN","Bodó","2401651"],["RN","Bom Jesus","2401701"],["RN","Brejinho","2401800"],["RN","Caiçara do Norte","2401859"],["RN","Caiçara do Rio do Vento","2401909"],["RN","Caicó","2402006"],["RN","Campo Grande","2401305"],["RN","Campo Redondo","2402105"],["RN","Canguaretama","2402204"],["RN","Caraúbas","2402303"],["RN","Carnaúba dos Dantas","2402402"],["RN","Carnaubais","2402501"],["RN","Ceará-Mirim","2402600"],["RN","Cerro Corá","2402709"],["RN","Coronel Ezequiel","2402808"],["RN","Coronel João Pessoa","2402907"],["RN","Cruzeta","2403004"],["RN","Currais Novos","2403103"],["RN","Doutor Severiano","2403202"],["RN","Encanto","2403301"],["RN","Equador","2403400"],["RN","Espírito Santo","2403509"],["RN","Extremoz","2403608"],["RN","Felipe Guerra","2403707"],["RN","Fernando Pedroza","2403756"],["RN","Florânia","2403806"],["RN","Francisco Dantas","2403905"],["RN","Frutuoso Gomes","2404002"],["RN","Galinhos","2404101"],["RN","Goianinha","2404200"],["RN","Governador Dix-Sept Rosado","2404309"],["RN","Grossos","2404408"],["RN","Guamaré","2404507"],["RN","Ielmo Marinho","2404606"],["RN","Ipanguaçu","2404705"],["RN","Ipueira","2404804"],["RN","Itajá","2404853"],["RN","Itaú","2404903"],["RN","Jaçanã","2405009"],["RN","Jandaíra","2405108"],["RN","Janduís","2405207"],["RN","Januário Cicco","2405306"],["RN","Japi","2405405"],["RN","Jardim de Angicos","2405504"],["RN","Jardim de Piranhas","2405603"],["RN","Jardim do Seridó","2405702"],["RN","João Câmara","2405801"],["RN","João Dias","2405900"],["RN","José da Penha","2406007"],["RN","Jucurutu","2406106"],["RN","Jundiá","2406155"],["RN","Lagoa d'Anta","2406205"],["RN","Lagoa de Pedras","2406304"],["RN","Lagoa de Velhos","2406403"],["RN","Lagoa Nova","2406502"],["RN","Lagoa Salgada","2406601"],["RN","Lajes","2406700"],["RN","Lajes Pintadas","2406809"],["RN","Lucrécia","2406908"],["RN","Luís Gomes","2407005"],["RN","Macaíba","2407104"],["RN","Macau","2407203"],["RN","Major Sales","2407252"],["RN","Marcelino Vieira","2407302"],["RN","Martins","2407401"],["RN","Maxaranguape","2407500"],["RN","Messias Targino","2407609"],["RN","Montanhas","2407708"],["RN","Monte Alegre","2407807"],["RN","Monte das Gameleiras","2407906"],["RN","Mossoró","2408003"],["RN","Natal","2408102"],["RN","Nísia Floresta","2408201"],["RN","Nova Cruz","2408300"],["RN","Olho d'Água do Borges","2408409"],["RN","Ouro Branco","2408508"],["RN","Paraná","2408607"],["RN","Paraú","2408706"],["RN","Parazinho","2408805"],["RN","Parelhas","2408904"],["RN","Parnamirim","2403251"],["RN","Passa e Fica","2409100"],["RN","Passagem","2409209"],["RN","Patu","2409308"],["RN","Pau dos Ferros","2409407"],["RN","Pedra Grande","2409506"],["RN","Pedra Preta","2409605"],["RN","Pedro Avelino","2409704"],["RN","Pedro Velho","2409803"],["RN","Pendências","2409902"],["RN","Pilões","2410009"],["RN","Poço Branco","2410108"],["RN","Portalegre","2410207"],["RN","Porto do Mangue","2410256"],["RN","Pureza","2410405"],["RN","Rafael Fernandes","2410504"],["RN","Rafael Godeiro","2410603"],["RN","Riacho da Cruz","2410702"],["RN","Riacho de Santana","2410801"],["RN","Riachuelo","2410900"],["RN","Rio do Fogo","2408953"],["RN","Rodolfo Fernandes","2411007"],["RN","Ruy Barbosa","2411106"],["RN","Santa Cruz","2411205"],["RN","Santa Maria","2409332"],["RN","Santana do Matos","2411403"],["RN","Santana do Seridó","2411429"],["RN","Santo Antônio","2411502"],["RN","São Bento do Norte","2411601"],["RN","São Bento do Trairí","2411700"],["RN","São Fernando","2411809"],["RN","São Francisco do Oeste","2411908"],["RN","São Gonçalo do Amarante","2412005"],["RN","São João do Sabugi","2412104"],["RN","São José de Mipibu","2412203"],["RN","São José do Campestre","2412302"],["RN","São José do Seridó","2412401"],["RN","São Miguel","2412500"],["RN","São Miguel do Gostoso","2412559"],["RN","São Paulo do Potengi","2412609"],["RN","São Pedro","2412708"],["RN","São Rafael","2412807"],["RN","São Tomé","2412906"],["RN","São Vicente","2413003"],["RN","Senador Elói de Souza","2413102"],["RN","Senador Georgino Avelino","2413201"],["RN","Serra Caiada","2410306"],["RN","Serra de São Bento","2413300"],["RN","Serra do Mel","2413359"],["RN","Serra Negra do Norte","2413409"],["RN","Serrinha","2413508"],["RN","Serrinha dos Pintos","2413557"],["RN","Severiano Melo","2413607"],["RN","Sítio Novo","2413706"],["RN","Taboleiro Grande","2413805"],["RN","Taipu","2413904"],["RN","Tangará","2414001"],["RN","Tenente Ananias","2414100"],["RN","Tenente Laurentino Cruz","2414159"],["RN","Tibau","2411056"],["RN","Tibau do Sul","2414209"],["RN","Timbaúba dos Batistas","2414308"],["RN","Touros","2414407"],["RN","Triunfo Potiguar","2414456"],["RN","Umarizal","2414506"],["RN","Upanema","2414605"],["RN","Várzea","2414704"],["RN","Venha-Ver","2414753"],["RN","Vera Cruz","2414803"],["RN","Viçosa","2414902"],["RN","Vila Flor","2415008"],["RS","Aceguá","4300034"],["RS","Água Santa","4300059"],["RS","Agudo","4300109"],["RS","Ajuricaba","4300208"],["RS","Alecrim","4300307"],["RS","Alegrete","4300406"],["RS","Alegria","4300455"],["RS","Almirante Tamandaré do Sul","4300471"],["RS","Alpestre","4300505"],["RS","Alto Alegre","4300554"],["RS","Alto Feliz","4300570"],["RS","Alvorada","4300604"],["RS","Amaral Ferrador","4300638"],["RS","Ametista do Sul","4300646"],["RS","André da Rocha","4300661"],["RS","Anta Gorda","4300703"],["RS","Antônio Prado","4300802"],["RS","Arambaré","4300851"],["RS","Araricá","4300877"],["RS","Aratiba","4300901"],["RS","Arroio do Meio","4301008"],["RS","Arroio do Padre","4301073"],["RS","Arroio do Sal","4301057"],["RS","Arroio do Tigre","4301206"],["RS","Arroio dos Ratos","4301107"],["RS","Arroio Grande","4301305"],["RS","Arvorezinha","4301404"],["RS","Augusto Pestana","4301503"],["RS","Áurea","4301552"],["RS","Bagé","4301602"],["RS","Balneário Pinhal","4301636"],["RS","Barão","4301651"],["RS","Barão de Cotegipe","4301701"],["RS","Barão do Triunfo","4301750"],["RS","Barra do Guarita","4301859"],["RS","Barra do Quaraí","4301875"],["RS","Barra do Ribeiro","4301909"],["RS","Barra do Rio Azul","4301925"],["RS","Barra Funda","4301958"],["RS","Barracão","4301800"],["RS","Barros Cassal","4302006"],["RS","Benjamin Constant do Sul","4302055"],["RS","Bento Gonçalves","4302105"],["RS","Boa Vista das Missões","4302154"],["RS","Boa Vista do Buricá","4302204"],["RS","Boa Vista do Cadeado","4302220"],["RS","Boa Vista do Incra","4302238"],["RS","Boa Vista do Sul","4302253"],["RS","Bom Jesus","4302303"],["RS","Bom Princípio","4302352"],["RS","Bom Progresso","4302378"],["RS","Bom Retiro do Sul","4302402"],["RS","Boqueirão do Leão","4302451"],["RS","Bossoroca","4302501"],["RS","Bozano","4302584"],["RS","Braga","4302600"],["RS","Brochier","4302659"],["RS","Butiá","4302709"],["RS","Caçapava do Sul","4302808"],["RS","Cacequi","4302907"],["RS","Cachoeira do Sul","4303004"],["RS","Cachoeirinha","4303103"],["RS","Cacique Doble","4303202"],["RS","Caibaté","4303301"],["RS","Caiçara","4303400"],["RS","Camaquã","4303509"],["RS","Camargo","4303558"],["RS","Cambará do Sul","4303608"],["RS","Campestre da Serra","4303673"],["RS","Campina das Missões","4303707"],["RS","Campinas do Sul","4303806"],["RS","Campo Bom","4303905"],["RS","Campo Novo","4304002"],["RS","Campos Borges","4304101"],["RS","Candelária","4304200"],["RS","Cândido Godói","4304309"],["RS","Candiota","4304358"],["RS","Canela","4304408"],["RS","Canguçu","4304507"],["RS","Canoas","4304606"],["RS","Canudos do Vale","4304614"],["RS","Capão Bonito do Sul","4304622"],["RS","Capão da Canoa","4304630"],["RS","Capão do Cipó","4304655"],["RS","Capão do Leão","4304663"],["RS","Capela de Santana","4304689"],["RS","Capitão","4304697"],["RS","Capivari do Sul","4304671"],["RS","Caraá","4304713"],["RS","Carazinho","4304705"],["RS","Carlos Barbosa","4304804"],["RS","Carlos Gomes","4304853"],["RS","Casca","4304903"],["RS","Caseiros","4304952"],["RS","Catuípe","4305009"],["RS","Caxias do Sul","4305108"],["RS","Centenário","4305116"],["RS","Cerrito","4305124"],["RS","Cerro Branco","4305132"],["RS","Cerro Grande","4305157"],["RS","Cerro Grande do Sul","4305173"],["RS","Cerro Largo","4305207"],["RS","Chapada","4305306"],["RS","Charqueadas","4305355"],["RS","Charrua","4305371"],["RS","Chiapetta","4305405"],["RS","Chuí","4305439"],["RS","Chuvisca","4305447"],["RS","Cidreira","4305454"],["RS","Ciríaco","4305504"],["RS","Colinas","4305587"],["RS","Colorado","4305603"],["RS","Condor","4305702"],["RS","Constantina","4305801"],["RS","Coqueiro Baixo","4305835"],["RS","Coqueiros do Sul","4305850"],["RS","Coronel Barros","4305871"],["RS","Coronel Bicaco","4305900"],["RS","Coronel Pilar","4305934"],["RS","Cotiporã","4305959"],["RS","Coxilha","4305975"],["RS","Crissiumal","4306007"],["RS","Cristal","4306056"],["RS","Cristal do Sul","4306072"],["RS","Cruz Alta","4306106"],["RS","Cruzaltense","4306130"],["RS","Cruzeiro do Sul","4306205"],["RS","David Canabarro","4306304"],["RS","Derrubadas","4306320"],["RS","Dezesseis de Novembro","4306353"],["RS","Dilermando de Aguiar","4306379"],["RS","Dois Irmãos","4306403"],["RS","Dois Irmãos das Missões","4306429"],["RS","Dois Lajeados","4306452"],["RS","Dom Feliciano","4306502"],["RS","Dom Pedrito","4306601"],["RS","Dom Pedro de Alcântara","4306551"],["RS","Dona Francisca","4306700"],["RS","Doutor Maurício Cardoso","4306734"],["RS","Doutor Ricardo","4306759"],["RS","Eldorado do Sul","4306767"],["RS","Encantado","4306809"],["RS","Encruzilhada do Sul","4306908"],["RS","Engenho Velho","4306924"],["RS","Entre Rios do Sul","4306957"],["RS","Entre-Ijuís","4306932"],["RS","Erebango","4306973"],["RS","Erechim","4307005"],["RS","Ernestina","4307054"],["RS","Erval Grande","4307203"],["RS","Erval Seco","4307302"],["RS","Esmeralda","4307401"],["RS","Esperança do Sul","4307450"],["RS","Espumoso","4307500"],["RS","Estação","4307559"],["RS","Estância Velha","4307609"],["RS","Esteio","4307708"],["RS","Estrela","4307807"],["RS","Estrela Velha","4307815"],["RS","Eugênio de Castro","4307831"],["RS","Fagundes Varela","4307864"],["RS","Farroupilha","4307906"],["RS","Faxinal do Soturno","4308003"],["RS","Faxinalzinho","4308052"],["RS","Fazenda Vilanova","4308078"],["RS","Feliz","4308102"],["RS","Flores da Cunha","4308201"],["RS","Floriano Peixoto","4308250"],["RS","Fontoura Xavier","4308300"],["RS","Formigueiro","4308409"],["RS","Forquetinha","4308433"],["RS","Fortaleza dos Valos","4308458"],["RS","Frederico Westphalen","4308508"],["RS","Garibaldi","4308607"],["RS","Garruchos","4308656"],["RS","Gaurama","4308706"],["RS","General Câmara","4308805"],["RS","Gentil","4308854"],["RS","Getúlio Vargas","4308904"],["RS","Giruá","4309001"],["RS","Glorinha","4309050"],["RS","Gramado","4309100"],["RS","Gramado dos Loureiros","4309126"],["RS","Gramado Xavier","4309159"],["RS","Gravataí","4309209"],["RS","Guabiju","4309258"],["RS","Guaíba","4309308"],["RS","Guaporé","4309407"],["RS","Guarani das Missões","4309506"],["RS","Harmonia","4309555"],["RS","Herval","4307104"],["RS","Herveiras","4309571"],["RS","Horizontina","4309605"],["RS","Hulha Negra","4309654"],["RS","Humaitá","4309704"],["RS","Ibarama","4309753"],["RS","Ibiaçá","4309803"],["RS","Ibiraiaras","4309902"],["RS","Ibirapuitã","4309951"],["RS","Ibirubá","4310009"],["RS","Igrejinha","4310108"],["RS","Ijuí","4310207"],["RS","Ilópolis","4310306"],["RS","Imbé","4310330"],["RS","Imigrante","4310363"],["RS","Independência","4310405"],["RS","Inhacorá","4310413"],["RS","Ipê","4310439"],["RS","Ipiranga do Sul","4310462"],["RS","Iraí","4310504"],["RS","Itaara","4310538"],["RS","Itacurubi","4310553"],["RS","Itapuca","4310579"],["RS","Itaqui","4310603"],["RS","Itati","4310652"],["RS","Itatiba do Sul","4310702"],["RS","Ivorá","4310751"],["RS","Ivoti","4310801"],["RS","Jaboticaba","4310850"],["RS","Jacuizinho","4310876"],["RS","Jacutinga","4310900"],["RS","Jaguarão","4311007"],["RS","Jaguari","4311106"],["RS","Jaquirana","4311122"],["RS","Jari","4311130"],["RS","Jóia","4311155"],["RS","Júlio de Castilhos","4311205"],["RS","Lagoa Bonita do Sul","4311239"],["RS","Lagoa dos Três Cantos","4311270"],["RS","Lagoa Vermelha","4311304"],["RS","Lagoão","4311254"],["RS","Lajeado","4311403"],["RS","Lajeado do Bugre","4311429"],["RS","Lavras do Sul","4311502"],["RS","Liberato Salzano","4311601"],["RS","Lindolfo Collor","4311627"],["RS","Linha Nova","4311643"],["RS","Maçambará","4311718"],["RS","Machadinho","4311700"],["RS","Mampituba","4311734"],["RS","Manoel Viana","4311759"],["RS","Maquiné","4311775"],["RS","Maratá","4311791"],["RS","Marau","4311809"],["RS","Marcelino Ramos","4311908"],["RS","Mariana Pimentel","4311981"],["RS","Mariano Moro","4312005"],["RS","Marques de Souza","4312054"],["RS","Mata","4312104"],["RS","Mato Castelhano","4312138"],["RS","Mato Leitão","4312153"],["RS","Mato Queimado","4312179"],["RS","Maximiliano de Almeida","4312203"],["RS","Minas do Leão","4312252"],["RS","Miraguaí","4312302"],["RS","Montauri","4312351"],["RS","Monte Alegre dos Campos","4312377"],["RS","Monte Belo do Sul","4312385"],["RS","Montenegro","4312401"],["RS","Mormaço","4312427"],["RS","Morrinhos do Sul","4312443"],["RS","Morro Redondo","4312450"],["RS","Morro Reuter","4312476"],["RS","Mostardas","4312500"],["RS","Muçum","4312609"],["RS","Muitos Capões","4312617"],["RS","Muliterno","4312625"],["RS","Não-Me-Toque","4312658"],["RS","Nicolau Vergueiro","4312674"],["RS","Nonoai","4312708"],["RS","Nova Alvorada","4312757"],["RS","Nova Araçá","4312807"],["RS","Nova Bassano","4312906"],["RS","Nova Boa Vista","4312955"],["RS","Nova Bréscia","4313003"],["RS","Nova Candelária","4313011"],["RS","Nova Esperança do Sul","4313037"],["RS","Nova Hartz","4313060"],["RS","Nova Pádua","4313086"],["RS","Nova Palma","4313102"],["RS","Nova Petrópolis","4313201"],["RS","Nova Prata","4313300"],["RS","Nova Ramada","4313334"],["RS","Nova Roma do Sul","4313359"],["RS","Nova Santa Rita","4313375"],["RS","Novo Barreiro","4313490"],["RS","Novo Cabrais","4313391"],["RS","Novo Hamburgo","4313409"],["RS","Novo Machado","4313425"],["RS","Novo Tiradentes","4313441"],["RS","Novo Xingu","4313466"],["RS","Osório","4313508"],["RS","Paim Filho","4313607"],["RS","Palmares do Sul","4313656"],["RS","Palmeira das Missões","4313706"],["RS","Palmitinho","4313805"],["RS","Panambi","4313904"],["RS","Pantano Grande","4313953"],["RS","Paraí","4314001"],["RS","Paraíso do Sul","4314027"],["RS","Pareci Novo","4314035"],["RS","Parobé","4314050"],["RS","Passa Sete","4314068"],["RS","Passo do Sobrado","4314076"],["RS","Passo Fundo","4314100"],["RS","Paulo Bento","4314134"],["RS","Paverama","4314159"],["RS","Pedras Altas","4314175"],["RS","Pedro Osório","4314209"],["RS","Pejuçara","4314308"],["RS","Pelotas","4314407"],["RS","Picada Café","4314423"],["RS","Pinhal","4314456"],["RS","Pinhal da Serra","4314464"],["RS","Pinhal Grande","4314472"],["RS","Pinheirinho do Vale","4314498"],["RS","Pinheiro Machado","4314506"],["RS","Pinto Bandeira","4314548"],["RS","Pirapó","4314555"],["RS","Piratini","4314605"],["RS","Planalto","4314704"],["RS","Poço das Antas","4314753"],["RS","Pontão","4314779"],["RS","Ponte Preta","4314787"],["RS","Portão","4314803"],["RS","Porto Alegre","4314902"],["RS","Porto Lucena","4315008"],["RS","Porto Mauá","4315057"],["RS","Porto Vera Cruz","4315073"],["RS","Porto Xavier","4315107"],["RS","Pouso Novo","4315131"],["RS","Presidente Lucena","4315149"],["RS","Progresso","4315156"],["RS","Protásio Alves","4315172"],["RS","Putinga","4315206"],["RS","Quaraí","4315305"],["RS","Quatro Irmãos","4315313"],["RS","Quevedos","4315321"],["RS","Quinze de Novembro","4315354"],["RS","Redentora","4315404"],["RS","Relvado","4315453"],["RS","Restinga Sêca","4315503"],["RS","Rio dos Índios","4315552"],["RS","Rio Grande","4315602"],["RS","Rio Pardo","4315701"],["RS","Riozinho","4315750"],["RS","Roca Sales","4315800"],["RS","Rodeio Bonito","4315909"],["RS","Rolador","4315958"],["RS","Rolante","4316006"],["RS","Ronda Alta","4316105"],["RS","Rondinha","4316204"],["RS","Roque Gonzales","4316303"],["RS","Rosário do Sul","4316402"],["RS","Sagrada Família","4316428"],["RS","Saldanha Marinho","4316436"],["RS","Salto do Jacuí","4316451"],["RS","Salvador das Missões","4316477"],["RS","Salvador do Sul","4316501"],["RS","Sananduva","4316600"],["RS","Sant'Ana do Livramento","4317103"],["RS","Santa Bárbara do Sul","4316709"],["RS","Santa Cecília do Sul","4316733"],["RS","Santa Clara do Sul","4316758"],["RS","Santa Cruz do Sul","4316808"],["RS","Santa Margarida do Sul","4316972"],["RS","Santa Maria","4316907"],["RS","Santa Maria do Herval","4316956"],["RS","Santa Rosa","4317202"],["RS","Santa Tereza","4317251"],["RS","Santa Vitória do Palmar","4317301"],["RS","Santana da Boa Vista","4317004"],["RS","Santiago","4317400"],["RS","Santo Ângelo","4317509"],["RS","Santo Antônio da Patrulha","4317608"],["RS","Santo Antônio das Missões","4317707"],["RS","Santo Antônio do Palma","4317558"],["RS","Santo Antônio do Planalto","4317756"],["RS","Santo Augusto","4317806"],["RS","Santo Cristo","4317905"],["RS","Santo Expedito do Sul","4317954"],["RS","São Borja","4318002"],["RS","São Domingos do Sul","4318051"],["RS","São Francisco de Assis","4318101"],["RS","São Francisco de Paula","4318200"],["RS","São Gabriel","4318309"],["RS","São Jerônimo","4318408"],["RS","São João da Urtiga","4318424"],["RS","São João do Polêsine","4318432"],["RS","São Jorge","4318440"],["RS","São José das Missões","4318457"],["RS","São José do Herval","4318465"],["RS","São José do Hortêncio","4318481"],["RS","São José do Inhacorá","4318499"],["RS","São José do Norte","4318507"],["RS","São José do Ouro","4318606"],["RS","São José do Sul","4318614"],["RS","São José dos Ausentes","4318622"],["RS","São Leopoldo","4318705"],["RS","São Lourenço do Sul","4318804"],["RS","São Luiz Gonzaga","4318903"],["RS","São Marcos","4319000"],["RS","São Martinho","4319109"],["RS","São Martinho da Serra","4319125"],["RS","São Miguel das Missões","4319158"],["RS","São Nicolau","4319208"],["RS","São Paulo das Missões","4319307"],["RS","São Pedro da Serra","4319356"],["RS","São Pedro das Missões","4319364"],["RS","São Pedro do Butiá","4319372"],["RS","São Pedro do Sul","4319406"],["RS","São Sebastião do Caí","4319505"],["RS","São Sepé","4319604"],["RS","São Valentim","4319703"],["RS","São Valentim do Sul","4319711"],["RS","São Valério do Sul","4319737"],["RS","São Vendelino","4319752"],["RS","São Vicente do Sul","4319802"],["RS","Sapiranga","4319901"],["RS","Sapucaia do Sul","4320008"],["RS","Sarandi","4320107"],["RS","Seberi","4320206"],["RS","Sede Nova","4320230"],["RS","Segredo","4320263"],["RS","Selbach","4320305"],["RS","Senador Salgado Filho","4320321"],["RS","Sentinela do Sul","4320354"],["RS","Serafina Corrêa","4320404"],["RS","Sério","4320453"],["RS","Sertão","4320503"],["RS","Sertão Santana","4320552"],["RS","Sete de Setembro","4320578"],["RS","Severiano de Almeida","4320602"],["RS","Silveira Martins","4320651"],["RS","Sinimbu","4320677"],["RS","Sobradinho","4320701"],["RS","Soledade","4320800"],["RS","Tabaí","4320859"],["RS","Tapejara","4320909"],["RS","Tapera","4321006"],["RS","Tapes","4321105"],["RS","Taquara","4321204"],["RS","Taquari","4321303"],["RS","Taquaruçu do Sul","4321329"],["RS","Tavares","4321352"],["RS","Tenente Portela","4321402"],["RS","Terra de Areia","4321436"],["RS","Teutônia","4321451"],["RS","Tio Hugo","4321469"],["RS","Tiradentes do Sul","4321477"],["RS","Toropi","4321493"],["RS","Torres","4321501"],["RS","Tramandaí","4321600"],["RS","Travesseiro","4321626"],["RS","Três Arroios","4321634"],["RS","Três Cachoeiras","4321667"],["RS","Três Coroas","4321709"],["RS","Três de Maio","4321808"],["RS","Três Forquilhas","4321832"],["RS","Três Palmeiras","4321857"],["RS","Três Passos","4321907"],["RS","Trindade do Sul","4321956"],["RS","Triunfo","4322004"],["RS","Tucunduva","4322103"],["RS","Tunas","4322152"],["RS","Tupanci do Sul","4322186"],["RS","Tupanciretã","4322202"],["RS","Tupandi","4322251"],["RS","Tuparendi","4322301"],["RS","Turuçu","4322327"],["RS","Ubiretama","4322343"],["RS","União da Serra","4322350"],["RS","Unistalda","4322376"],["RS","Uruguaiana","4322400"],["RS","Vacaria","4322509"],["RS","Vale do Sol","4322533"],["RS","Vale Real","4322541"],["RS","Vale Verde","4322525"],["RS","Vanini","4322558"],["RS","Venâncio Aires","4322608"],["RS","Vera Cruz","4322707"],["RS","Veranópolis","4322806"],["RS","Vespasiano Corrêa","4322855"],["RS","Viadutos","4322905"],["RS","Viamão","4323002"],["RS","Vicente Dutra","4323101"],["RS","Victor Graeff","4323200"],["RS","Vila Flores","4323309"],["RS","Vila Lângaro","4323358"],["RS","Vila Maria","4323408"],["RS","Vila Nova do Sul","4323457"],["RS","Vista Alegre","4323507"],["RS","Vista Alegre do Prata","4323606"],["RS","Vista Gaúcha","4323705"],["RS","Vitória das Missões","4323754"],["RS","Westfália","4323770"],["RS","Xangri-lá","4323804"],["RO","Alta Floresta D'Oeste","1100015"],["RO","Alto Alegre dos Parecis","1100379"],["RO","Alto Paraíso","1100403"],["RO","Alvorada D'Oeste","1100346"],["RO","Ariquemes","1100023"],["RO","Buritis","1100452"],["RO","Cabixi","1100031"],["RO","Cacaulândia","1100601"],["RO","Cacoal","1100049"],["RO","Campo Novo de Rondônia","1100700"],["RO","Candeias do Jamari","1100809"],["RO","Castanheiras","1100908"],["RO","Cerejeiras","1100056"],["RO","Chupinguaia","1100924"],["RO","Colorado do Oeste","1100064"],["RO","Corumbiara","1100072"],["RO","Costa Marques","1100080"],["RO","Cujubim","1100940"],["RO","Espigão D'Oeste","1100098"],["RO","Governador Jorge Teixeira","1101005"],["RO","Guajará-Mirim","1100106"],["RO","Itapuã do Oeste","1101104"],["RO","Jaru","1100114"],["RO","Ji-Paraná","1100122"],["RO","Machadinho D'Oeste","1100130"],["RO","Ministro Andreazza","1101203"],["RO","Mirante da Serra","1101302"],["RO","Monte Negro","1101401"],["RO","Nova Brasilândia D'Oeste","1100148"],["RO","Nova Mamoré","1100338"],["RO","Nova União","1101435"],["RO","Novo Horizonte do Oeste","1100502"],["RO","Ouro Preto do Oeste","1100155"],["RO","Parecis","1101450"],["RO","Pimenta Bueno","1100189"],["RO","Pimenteiras do Oeste","1101468"],["RO","Porto Velho","1100205"],["RO","Presidente Médici","1100254"],["RO","Primavera de Rondônia","1101476"],["RO","Rio Crespo","1100262"],["RO","Rolim de Moura","1100288"],["RO","Santa Luzia D'Oeste","1100296"],["RO","São Felipe D'Oeste","1101484"],["RO","São Francisco do Guaporé","1101492"],["RO","São Miguel do Guaporé","1100320"],["RO","Seringueiras","1101500"],["RO","Teixeirópolis","1101559"],["RO","Theobroma","1101609"],["RO","Urupá","1101708"],["RO","Vale do Anari","1101757"],["RO","Vale do Paraíso","1101807"],["RO","Vilhena","1100304"],["RR","Alto Alegre","1400050"],["RR","Amajari","1400027"],["RR","Boa Vista","1400100"],["RR","Bonfim","1400159"],["RR","Cantá","1400175"],["RR","Caracaraí","1400209"],["RR","Caroebe","1400233"],["RR","Iracema","1400282"],["RR","Mucajaí","1400308"],["RR","Normandia","1400407"],["RR","Pacaraima","1400456"],["RR","Rorainópolis","1400472"],["RR","São João da Baliza","1400506"],["RR","São Luiz do Anauá","1400605"],["RR","Uiramutã","1400704"],["SC","Abdon Batista","4200051"],["SC","Abelardo Luz","4200101"],["SC","Agrolândia","4200200"],["SC","Agronômica","4200309"],["SC","Água Doce","4200408"],["SC","Águas de Chapecó","4200507"],["SC","Águas Frias","4200556"],["SC","Águas Mornas","4200606"],["SC","Alfredo Wagner","4200705"],["SC","Alto Bela Vista","4200754"],["SC","Anchieta","4200804"],["SC","Angelina","4200903"],["SC","Anita Garibaldi","4201000"],["SC","Anitápolis","4201109"],["SC","Antônio Carlos","4201208"],["SC","Apiúna","4201257"],["SC","Arabutã","4201273"],["SC","Araquari","4201307"],["SC","Araranguá","4201406"],["SC","Armazém","4201505"],["SC","Arroio Trinta","4201604"],["SC","Arvoredo","4201653"],["SC","Ascurra","4201703"],["SC","Atalanta","4201802"],["SC","Aurora","4201901"],["SC","Balneário Arroio do Silva","4201950"],["SC","Balneário Barra do Sul","4202057"],["SC","Balneário Camboriú","4202008"],["SC","Balneário Gaivota","4202073"],["SC","Balneário Piçarras","4212809"],["SC","Balneário Rincão","4220000"],["SC","Bandeirante","4202081"],["SC","Barra Bonita","4202099"],["SC","Barra Velha","4202107"],["SC","Bela Vista do Toldo","4202131"],["SC","Belmonte","4202156"],["SC","Benedito Novo","4202206"],["SC","Biguaçu","4202305"],["SC","Blumenau","4202404"],["SC","Bocaina do Sul","4202438"],["SC","Bom Jardim da Serra","4202503"],["SC","Bom Jesus","4202537"],["SC","Bom Jesus do Oeste","4202578"],["SC","Bom Retiro","4202602"],["SC","Bombinhas","4202453"],["SC","Botuverá","4202701"],["SC","Braço do Norte","4202800"],["SC","Braço do Trombudo","4202859"],["SC","Brunópolis","4202875"],["SC","Brusque","4202909"],["SC","Caçador","4203006"],["SC","Caibi","4203105"],["SC","Calmon","4203154"],["SC","Camboriú","4203204"],["SC","Campo Alegre","4203303"],["SC","Campo Belo do Sul","4203402"],["SC","Campo Erê","4203501"],["SC","Campos Novos","4203600"],["SC","Canelinha","4203709"],["SC","Canoinhas","4203808"],["SC","Capão Alto","4203253"],["SC","Capinzal","4203907"],["SC","Capivari de Baixo","4203956"],["SC","Catanduvas","4204004"],["SC","Caxambu do Sul","4204103"],["SC","Celso Ramos","4204152"],["SC","Cerro Negro","4204178"],["SC","Chapadão do Lageado","4204194"],["SC","Chapecó","4204202"],["SC","Cocal do Sul","4204251"],["SC","Concórdia","4204301"],["SC","Cordilheira Alta","4204350"],["SC","Coronel Freitas","4204400"],["SC","Coronel Martins","4204459"],["SC","Correia Pinto","4204558"],["SC","Corupá","4204509"],["SC","Criciúma","4204608"],["SC","Cunha Porã","4204707"],["SC","Cunhataí","4204756"],["SC","Curitibanos","4204806"],["SC","Descanso","4204905"],["SC","Dionísio Cerqueira","4205001"],["SC","Dona Emma","4205100"],["SC","Doutor Pedrinho","4205159"],["SC","Entre Rios","4205175"],["SC","Ermo","4205191"],["SC","Erval Velho","4205209"],["SC","Faxinal dos Guedes","4205308"],["SC","Flor do Sertão","4205357"],["SC","Florianópolis","4205407"],["SC","Formosa do Sul","4205431"],["SC","Forquilhinha","4205456"],["SC","Fraiburgo","4205506"],["SC","Frei Rogério","4205555"],["SC","Galvão","4205605"],["SC","Garopaba","4205704"],["SC","Garuva","4205803"],["SC","Gaspar","4205902"],["SC","Governador Celso Ramos","4206009"],["SC","Grão-Pará","4206108"],["SC","Gravatal","4206207"],["SC","Guabiruba","4206306"],["SC","Guaraciaba","4206405"],["SC","Guaramirim","4206504"],["SC","Guarujá do Sul","4206603"],["SC","Guatambú","4206652"],["SC","Herval d'Oeste","4206702"],["SC","Ibiam","4206751"],["SC","Ibicaré","4206801"],["SC","Ibirama","4206900"],["SC","Içara","4207007"],["SC","Ilhota","4207106"],["SC","Imaruí","4207205"],["SC","Imbituba","4207304"],["SC","Imbuia","4207403"],["SC","Indaial","4207502"],["SC","Iomerê","4207577"],["SC","Ipira","4207601"],["SC","Iporã do Oeste","4207650"],["SC","Ipuaçu","4207684"],["SC","Ipumirim","4207700"],["SC","Iraceminha","4207759"],["SC","Irani","4207809"],["SC","Irati","4207858"],["SC","Irineópolis","4207908"],["SC","Itá","4208005"],["SC","Itaiópolis","4208104"],["SC","Itajaí","4208203"],["SC","Itapema","4208302"],["SC","Itapiranga","4208401"],["SC","Itapoá","4208450"],["SC","Ituporanga","4208500"],["SC","Jaborá","4208609"],["SC","Jacinto Machado","4208708"],["SC","Jaguaruna","4208807"],["SC","Jaraguá do Sul","4208906"],["SC","Jardinópolis","4208955"],["SC","Joaçaba","4209003"],["SC","Joinville","4209102"],["SC","José Boiteux","4209151"],["SC","Jupiá","4209177"],["SC","Lacerdópolis","4209201"],["SC","Lages","4209300"],["SC","Laguna","4209409"],["SC","Lajeado Grande","4209458"],["SC","Laurentino","4209508"],["SC","Lauro Müller","4209607"],["SC","Lebon Régis","4209706"],["SC","Leoberto Leal","4209805"],["SC","Lindóia do Sul","4209854"],["SC","Lontras","4209904"],["SC","Luiz Alves","4210001"],["SC","Luzerna","4210035"],["SC","Macieira","4210050"],["SC","Mafra","4210100"],["SC","Major Gercino","4210209"],["SC","Major Vieira","4210308"],["SC","Maracajá","4210407"],["SC","Maravilha","4210506"],["SC","Marema","4210555"],["SC","Massaranduba","4210605"],["SC","Matos Costa","4210704"],["SC","Meleiro","4210803"],["SC","Mirim Doce","4210852"],["SC","Modelo","4210902"],["SC","Mondaí","4211009"],["SC","Monte Carlo","4211058"],["SC","Monte Castelo","4211108"],["SC","Morro da Fumaça","4211207"],["SC","Morro Grande","4211256"],["SC","Navegantes","4211306"],["SC","Nova Erechim","4211405"],["SC","Nova Itaberaba","4211454"],["SC","Nova Trento","4211504"],["SC","Nova Veneza","4211603"],["SC","Novo Horizonte","4211652"],["SC","Orleans","4211702"],["SC","Otacílio Costa","4211751"],["SC","Ouro","4211801"],["SC","Ouro Verde","4211850"],["SC","Paial","4211876"],["SC","Painel","4211892"],["SC","Palhoça","4211900"],["SC","Palma Sola","4212007"],["SC","Palmeira","4212056"],["SC","Palmitos","4212106"],["SC","Papanduva","4212205"],["SC","Paraíso","4212239"],["SC","Passo de Torres","4212254"],["SC","Passos Maia","4212270"],["SC","Paulo Lopes","4212304"],["SC","Pedras Grandes","4212403"],["SC","Penha","4212502"],["SC","Peritiba","4212601"],["SC","Pescaria Brava","4212650"],["SC","Petrolândia","4212700"],["SC","Pinhalzinho","4212908"],["SC","Pinheiro Preto","4213005"],["SC","Piratuba","4213104"],["SC","Planalto Alegre","4213153"],["SC","Pomerode","4213203"],["SC","Ponte Alta","4213302"],["SC","Ponte Alta do Norte","4213351"],["SC","Ponte Serrada","4213401"],["SC","Porto Belo","4213500"],["SC","Porto União","4213609"],["SC","Pouso Redondo","4213708"],["SC","Praia Grande","4213807"],["SC","Presidente Castello Branco","4213906"],["SC","Presidente Getúlio","4214003"],["SC","Presidente Nereu","4214102"],["SC","Princesa","4214151"],["SC","Quilombo","4214201"],["SC","Rancho Queimado","4214300"],["SC","Rio das Antas","4214409"],["SC","Rio do Campo","4214508"],["SC","Rio do Oeste","4214607"],["SC","Rio do Sul","4214805"],["SC","Rio dos Cedros","4214706"],["SC","Rio Fortuna","4214904"],["SC","Rio Negrinho","4215000"],["SC","Rio Rufino","4215059"],["SC","Riqueza","4215075"],["SC","Rodeio","4215109"],["SC","Romelândia","4215208"],["SC","Salete","4215307"],["SC","Saltinho","4215356"],["SC","Salto Veloso","4215406"],["SC","Sangão","4215455"],["SC","Santa Cecília","4215505"],["SC","Santa Helena","4215554"],["SC","Santa Rosa de Lima","4215604"],["SC","Santa Rosa do Sul","4215653"],["SC","Santa Terezinha","4215679"],["SC","Santa Terezinha do Progresso","4215687"],["SC","Santiago do Sul","4215695"],["SC","Santo Amaro da Imperatriz","4215703"],["SC","São Bento do Sul","4215802"],["SC","São Bernardino","4215752"],["SC","São Bonifácio","4215901"],["SC","São Carlos","4216008"],["SC","São Cristóvão do Sul","4216057"],["SC","São Domingos","4216107"],["SC","São Francisco do Sul","4216206"],["SC","São João Batista","4216305"],["SC","São João do Itaperiú","4216354"],["SC","São João do Oeste","4216255"],["SC","São João do Sul","4216404"],["SC","São Joaquim","4216503"],["SC","São José","4216602"],["SC","São José do Cedro","4216701"],["SC","São José do Cerrito","4216800"],["SC","São Lourenço do Oeste","4216909"],["SC","São Ludgero","4217006"],["SC","São Martinho","4217105"],["SC","São Miguel da Boa Vista","4217154"],["SC","São Miguel do Oeste","4217204"],["SC","São Pedro de Alcântara","4217253"],["SC","Saudades","4217303"],["SC","Schroeder","4217402"],["SC","Seara","4217501"],["SC","Serra Alta","4217550"],["SC","Siderópolis","4217600"],["SC","Sombrio","4217709"],["SC","Sul Brasil","4217758"],["SC","Taió","4217808"],["SC","Tangará","4217907"],["SC","Tigrinhos","4217956"],["SC","Tijucas","4218004"],["SC","Timbé do Sul","4218103"],["SC","Timbó","4218202"],["SC","Timbó Grande","4218251"],["SC","Três Barras","4218301"],["SC","Treviso","4218350"],["SC","Treze de Maio","4218400"],["SC","Treze Tílias","4218509"],["SC","Trombudo Central","4218608"],["SC","Tubarão","4218707"],["SC","Tunápolis","4218756"],["SC","Turvo","4218806"],["SC","União do Oeste","4218855"],["SC","Urubici","4218905"],["SC","Urupema","4218954"],["SC","Urussanga","4219002"],["SC","Vargeão","4219101"],["SC","Vargem","4219150"],["SC","Vargem Bonita","4219176"],["SC","Vidal Ramos","4219200"],["SC","Videira","4219309"],["SC","Vitor Meireles","4219358"],["SC","Witmarsum","4219408"],["SC","Xanxerê","4219507"],["SC","Xavantina","4219606"],["SC","Xaxim","4219705"],["SC","Zortéa","4219853"],["SP","Adamantina","3500105"],["SP","Adolfo","3500204"],["SP","Aguaí","3500303"],["SP","Águas da Prata","3500402"],["SP","Águas de Lindóia","3500501"],["SP","Águas de Santa Bárbara","3500550"],["SP","Águas de São Pedro","3500600"],["SP","Agudos","3500709"],["SP","Alambari","3500758"],["SP","Alfredo Marcondes","3500808"],["SP","Altair","3500907"],["SP","Altinópolis","3501004"],["SP","Alto Alegre","3501103"],["SP","Alumínio","3501152"],["SP","Álvares Florence","3501202"],["SP","Álvares Machado","3501301"],["SP","Álvaro de Carvalho","3501400"],["SP","Alvinlândia","3501509"],["SP","Americana","3501608"],["SP","Américo Brasiliense","3501707"],["SP","Américo de Campos","3501806"],["SP","Amparo","3501905"],["SP","Analândia","3502002"],["SP","Andradina","3502101"],["SP","Angatuba","3502200"],["SP","Anhembi","3502309"],["SP","Anhumas","3502408"],["SP","Aparecida","3502507"],["SP","Aparecida d'Oeste","3502606"],["SP","Apiaí","3502705"],["SP","Araçariguama","3502754"],["SP","Araçatuba","3502804"],["SP","Araçoiaba da Serra","3502903"],["SP","Aramina","3503000"],["SP","Arandu","3503109"],["SP","Arapeí","3503158"],["SP","Araraquara","3503208"],["SP","Araras","3503307"],["SP","Arco-Íris","3503356"],["SP","Arealva","3503406"],["SP","Areias","3503505"],["SP","Areiópolis","3503604"],["SP","Ariranha","3503703"],["SP","Artur Nogueira","3503802"],["SP","Arujá","3503901"],["SP","Aspásia","3503950"],["SP","Assis","3504008"],["SP","Atibaia","3504107"],["SP","Auriflama","3504206"],["SP","Avaí","3504305"],["SP","Avanhandava","3504404"],["SP","Avaré","3504503"],["SP","Bady Bassitt","3504602"],["SP","Balbinos","3504701"],["SP","Bálsamo","3504800"],["SP","Bananal","3504909"],["SP","Barão de Antonina","3505005"],["SP","Barbosa","3505104"],["SP","Bariri","3505203"],["SP","Barra Bonita","3505302"],["SP","Barra do Chapéu","3505351"],["SP","Barra do Turvo","3505401"],["SP","Barretos","3505500"],["SP","Barrinha","3505609"],["SP","Barueri","3505708"],["SP","Bastos","3505807"],["SP","Batatais","3505906"],["SP","Bauru","3506003"],["SP","Bebedouro","3506102"],["SP","Bento de Abreu","3506201"],["SP","Bernardino de Campos","3506300"],["SP","Bertioga","3506359"],["SP","Bilac","3506409"],["SP","Birigui","3506508"],["SP","Biritiba Mirim","3506607"],["SP","Boa Esperança do Sul","3506706"],["SP","Bocaina","3506805"],["SP","Bofete","3506904"],["SP","Boituva","3507001"],["SP","Bom Jesus dos Perdões","3507100"],["SP","Bom Sucesso de Itararé","3507159"],["SP","Borá","3507209"],["SP","Boracéia","3507308"],["SP","Borborema","3507407"],["SP","Borebi","3507456"],["SP","Botucatu","3507506"],["SP","Bragança Paulista","3507605"],["SP","Braúna","3507704"],["SP","Brejo Alegre","3507753"],["SP","Brodowski","3507803"],["SP","Brotas","3507902"],["SP","Buri","3508009"],["SP","Buritama","3508108"],["SP","Buritizal","3508207"],["SP","Cabrália Paulista","3508306"],["SP","Cabreúva","3508405"],["SP","Caçapava","3508504"],["SP","Cachoeira Paulista","3508603"],["SP","Caconde","3508702"],["SP","Cafelândia","3508801"],["SP","Caiabu","3508900"],["SP","Caieiras","3509007"],["SP","Caiuá","3509106"],["SP","Cajamar","3509205"],["SP","Cajati","3509254"],["SP","Cajobi","3509304"],["SP","Cajuru","3509403"],["SP","Campina do Monte Alegre","3509452"],["SP","Campinas","3509502"],["SP","Campo Limpo Paulista","3509601"],["SP","Campos do Jordão","3509700"],["SP","Campos Novos Paulista","3509809"],["SP","Cananéia","3509908"],["SP","Canas","3509957"],["SP","Cândido Mota","3510005"],["SP","Cândido Rodrigues","3510104"],["SP","Canitar","3510153"],["SP","Capão Bonito","3510203"],["SP","Capela do Alto","3510302"],["SP","Capivari","3510401"],["SP","Caraguatatuba","3510500"],["SP","Carapicuíba","3510609"],["SP","Cardoso","3510708"],["SP","Casa Branca","3510807"],["SP","Cássia dos Coqueiros","3510906"],["SP","Castilho","3511003"],["SP","Catanduva","3511102"],["SP","Catiguá","3511201"],["SP","Cedral","3511300"],["SP","Cerqueira César","3511409"],["SP","Cerquilho","3511508"],["SP","Cesário Lange","3511607"],["SP","Charqueada","3511706"],["SP","Chavantes","3557204"],["SP","Clementina","3511904"],["SP","Colina","3512001"],["SP","Colômbia","3512100"],["SP","Conchal","3512209"],["SP","Conchas","3512308"],["SP","Cordeirópolis","3512407"],["SP","Coroados","3512506"],["SP","Coronel Macedo","3512605"],["SP","Corumbataí","3512704"],["SP","Cosmópolis","3512803"],["SP","Cosmorama","3512902"],["SP","Cotia","3513009"],["SP","Cravinhos","3513108"],["SP","Cristais Paulista","3513207"],["SP","Cruzália","3513306"],["SP","Cruzeiro","3513405"],["SP","Cubatão","3513504"],["SP","Cunha","3513603"],["SP","Descalvado","3513702"],["SP","Diadema","3513801"],["SP","Dirce Reis","3513850"],["SP","Divinolândia","3513900"],["SP","Dobrada","3514007"],["SP","Dois Córregos","3514106"],["SP","Dolcinópolis","3514205"],["SP","Dourado","3514304"],["SP","Dracena","3514403"],["SP","Duartina","3514502"],["SP","Dumont","3514601"],["SP","Echaporã","3514700"],["SP","Eldorado","3514809"],["SP","Elias Fausto","3514908"],["SP","Elisiário","3514924"],["SP","Embaúba","3514957"],["SP","Embu das Artes","3515004"],["SP","Embu-Guaçu","3515103"],["SP","Emilianópolis","3515129"],["SP","Engenheiro Coelho","3515152"],["SP","Espírito Santo do Pinhal","3515186"],["SP","Espírito Santo do Turvo","3515194"],["SP","Estiva Gerbi","3557303"],["SP","Estrela d'Oeste","3515202"],["SP","Estrela do Norte","3515301"],["SP","Euclides da Cunha Paulista","3515350"],["SP","Fartura","3515400"],["SP","Fernando Prestes","3515608"],["SP","Fernandópolis","3515509"],["SP","Fernão","3515657"],["SP","Ferraz de Vasconcelos","3515707"],["SP","Flora Rica","3515806"],["SP","Floreal","3515905"],["SP","Flórida Paulista","3516002"],["SP","Florínea","3516101"],["SP","Franca","3516200"],["SP","Francisco Morato","3516309"],["SP","Franco da Rocha","3516408"],["SP","Gabriel Monteiro","3516507"],["SP","Gália","3516606"],["SP","Garça","3516705"],["SP","Gastão Vidigal","3516804"],["SP","Gavião Peixoto","3516853"],["SP","General Salgado","3516903"],["SP","Getulina","3517000"],["SP","Glicério","3517109"],["SP","Guaiçara","3517208"],["SP","Guaimbê","3517307"],["SP","Guaíra","3517406"],["SP","Guapiaçu","3517505"],["SP","Guapiara","3517604"],["SP","Guará","3517703"],["SP","Guaraçaí","3517802"],["SP","Guaraci","3517901"],["SP","Guarani d'Oeste","3518008"],["SP","Guarantã","3518107"],["SP","Guararapes","3518206"],["SP","Guararema","3518305"],["SP","Guaratinguetá","3518404"],["SP","Guareí","3518503"],["SP","Guariba","3518602"],["SP","Guarujá","3518701"],["SP","Guarulhos","3518800"],["SP","Guatapará","3518859"],["SP","Guzolândia","3518909"],["SP","Herculândia","3519006"],["SP","Holambra","3519055"],["SP","Hortolândia","3519071"],["SP","Iacanga","3519105"],["SP","Iacri","3519204"],["SP","Iaras","3519253"],["SP","Ibaté","3519303"],["SP","Ibirá","3519402"],["SP","Ibirarema","3519501"],["SP","Ibitinga","3519600"],["SP","Ibiúna","3519709"],["SP","Icém","3519808"],["SP","Iepê","3519907"],["SP","Igaraçu do Tietê","3520004"],["SP","Igarapava","3520103"],["SP","Igaratá","3520202"],["SP","Iguape","3520301"],["SP","Ilha Comprida","3520426"],["SP","Ilha Solteira","3520442"],["SP","Ilhabela","3520400"],["SP","Indaiatuba","3520509"],["SP","Indiana","3520608"],["SP","Indiaporã","3520707"],["SP","Inúbia Paulista","3520806"],["SP","Ipaussu","3520905"],["SP","Iperó","3521002"],["SP","Ipeúna","3521101"],["SP","Ipiguá","3521150"],["SP","Iporanga","3521200"],["SP","Ipuã","3521309"],["SP","Iracemápolis","3521408"],["SP","Irapuã","3521507"],["SP","Irapuru","3521606"],["SP","Itaberá","3521705"],["SP","Itaí","3521804"],["SP","Itajobi","3521903"],["SP","Itaju","3522000"],["SP","Itanhaém","3522109"],["SP","Itaoca","3522158"],["SP","Itapecerica da Serra","3522208"],["SP","Itapetininga","3522307"],["SP","Itapeva","3522406"],["SP","Itapevi","3522505"],["SP","Itapira","3522604"],["SP","Itapirapuã Paulista","3522653"],["SP","Itápolis","3522703"],["SP","Itaporanga","3522802"],["SP","Itapuí","3522901"],["SP","Itapura","3523008"],["SP","Itaquaquecetuba","3523107"],["SP","Itararé","3523206"],["SP","Itariri","3523305"],["SP","Itatiba","3523404"],["SP","Itatinga","3523503"],["SP","Itirapina","3523602"],["SP","Itirapuã","3523701"],["SP","Itobi","3523800"],["SP","Itu","3523909"],["SP","Itupeva","3524006"],["SP","Ituverava","3524105"],["SP","Jaborandi","3524204"],["SP","Jaboticabal","3524303"],["SP","Jacareí","3524402"],["SP","Jaci","3524501"],["SP","Jacupiranga","3524600"],["SP","Jaguariúna","3524709"],["SP","Jales","3524808"],["SP","Jambeiro","3524907"],["SP","Jandira","3525003"],["SP","Jardinópolis","3525102"],["SP","Jarinu","3525201"],["SP","Jaú","3525300"],["SP","Jeriquara","3525409"],["SP","Joanópolis","3525508"],["SP","João Ramalho","3525607"],["SP","José Bonifácio","3525706"],["SP","Júlio Mesquita","3525805"],["SP","Jumirim","3525854"],["SP","Jundiaí","3525904"],["SP","Junqueirópolis","3526001"],["SP","Juquiá","3526100"],["SP","Juquitiba","3526209"],["SP","Lagoinha","3526308"],["SP","Laranjal Paulista","3526407"],["SP","Lavínia","3526506"],["SP","Lavrinhas","3526605"],["SP","Leme","3526704"],["SP","Lençóis Paulista","3526803"],["SP","Limeira","3526902"],["SP","Lindóia","3527009"],["SP","Lins","3527108"],["SP","Lorena","3527207"],["SP","Lourdes","3527256"],["SP","Louveira","3527306"],["SP","Lucélia","3527405"],["SP","Lucianópolis","3527504"],["SP","Luís Antônio","3527603"],["SP","Luiziânia","3527702"],["SP","Lupércio","3527801"],["SP","Lutécia","3527900"],["SP","Macatuba","3528007"],["SP","Macaubal","3528106"],["SP","Macedônia","3528205"],["SP","Magda","3528304"],["SP","Mairinque","3528403"],["SP","Mairiporã","3528502"],["SP","Manduri","3528601"],["SP","Marabá Paulista","3528700"],["SP","Maracaí","3528809"],["SP","Marapoama","3528858"],["SP","Mariápolis","3528908"],["SP","Marília","3529005"],["SP","Marinópolis","3529104"],["SP","Martinópolis","3529203"],["SP","Matão","3529302"],["SP","Mauá","3529401"],["SP","Mendonça","3529500"],["SP","Meridiano","3529609"],["SP","Mesópolis","3529658"],["SP","Miguelópolis","3529708"],["SP","Mineiros do Tietê","3529807"],["SP","Mira Estrela","3530003"],["SP","Miracatu","3529906"],["SP","Mirandópolis","3530102"],["SP","Mirante do Paranapanema","3530201"],["SP","Mirassol","3530300"],["SP","Mirassolândia","3530409"],["SP","Mococa","3530508"],["SP","Mogi das Cruzes","3530607"],["SP","Mogi Guaçu","3530706"],["SP","Mogi Mirim","3530805"],["SP","Mombuca","3530904"],["SP","Monções","3531001"],["SP","Mongaguá","3531100"],["SP","Monte Alegre do Sul","3531209"],["SP","Monte Alto","3531308"],["SP","Monte Aprazível","3531407"],["SP","Monte Azul Paulista","3531506"],["SP","Monte Castelo","3531605"],["SP","Monte Mor","3531803"],["SP","Monteiro Lobato","3531704"],["SP","Morro Agudo","3531902"],["SP","Morungaba","3532009"],["SP","Motuca","3532058"],["SP","Murutinga do Sul","3532108"],["SP","Nantes","3532157"],["SP","Narandiba","3532207"],["SP","Natividade da Serra","3532306"],["SP","Nazaré Paulista","3532405"],["SP","Neves Paulista","3532504"],["SP","Nhandeara","3532603"],["SP","Nipoã","3532702"],["SP","Nova Aliança","3532801"],["SP","Nova Campina","3532827"],["SP","Nova Canaã Paulista","3532843"],["SP","Nova Castilho","3532868"],["SP","Nova Europa","3532900"],["SP","Nova Granada","3533007"],["SP","Nova Guataporanga","3533106"],["SP","Nova Independência","3533205"],["SP","Nova Luzitânia","3533304"],["SP","Nova Odessa","3533403"],["SP","Novais","3533254"],["SP","Novo Horizonte","3533502"],["SP","Nuporanga","3533601"],["SP","Ocauçu","3533700"],["SP","Óleo","3533809"],["SP","Olímpia","3533908"],["SP","Onda Verde","3534005"],["SP","Oriente","3534104"],["SP","Orindiúva","3534203"],["SP","Orlândia","3534302"],["SP","Osasco","3534401"],["SP","Oscar Bressane","3534500"],["SP","Osvaldo Cruz","3534609"],["SP","Ourinhos","3534708"],["SP","Ouro Verde","3534807"],["SP","Ouroeste","3534757"],["SP","Pacaembu","3534906"],["SP","Palestina","3535002"],["SP","Palmares Paulista","3535101"],["SP","Palmeira d'Oeste","3535200"],["SP","Palmital","3535309"],["SP","Panorama","3535408"],["SP","Paraguaçu Paulista","3535507"],["SP","Paraibuna","3535606"],["SP","Paraíso","3535705"],["SP","Paranapanema","3535804"],["SP","Paranapuã","3535903"],["SP","Parapuã","3536000"],["SP","Pardinho","3536109"],["SP","Pariquera-Açu","3536208"],["SP","Parisi","3536257"],["SP","Patrocínio Paulista","3536307"],["SP","Paulicéia","3536406"],["SP","Paulínia","3536505"],["SP","Paulistânia","3536570"],["SP","Paulo de Faria","3536604"],["SP","Pederneiras","3536703"],["SP","Pedra Bela","3536802"],["SP","Pedranópolis","3536901"],["SP","Pedregulho","3537008"],["SP","Pedreira","3537107"],["SP","Pedrinhas Paulista","3537156"],["SP","Pedro de Toledo","3537206"],["SP","Penápolis","3537305"],["SP","Pereira Barreto","3537404"],["SP","Pereiras","3537503"],["SP","Peruíbe","3537602"],["SP","Piacatu","3537701"],["SP","Piedade","3537800"],["SP","Pilar do Sul","3537909"],["SP","Pindamonhangaba","3538006"],["SP","Pindorama","3538105"],["SP","Pinhalzinho","3538204"],["SP","Piquerobi","3538303"],["SP","Piquete","3538501"],["SP","Piracaia","3538600"],["SP","Piracicaba","3538709"],["SP","Piraju","3538808"],["SP","Pirajuí","3538907"],["SP","Pirangi","3539004"],["SP","Pirapora do Bom Jesus","3539103"],["SP","Pirapozinho","3539202"],["SP","Pirassununga","3539301"],["SP","Piratininga","3539400"],["SP","Pitangueiras","3539509"],["SP","Planalto","3539608"],["SP","Platina","3539707"],["SP","Poá","3539806"],["SP","Poloni","3539905"],["SP","Pompéia","3540002"],["SP","Pongaí","3540101"],["SP","Pontal","3540200"],["SP","Pontalinda","3540259"],["SP","Pontes Gestal","3540309"],["SP","Populina","3540408"],["SP","Porangaba","3540507"],["SP","Porto Feliz","3540606"],["SP","Porto Ferreira","3540705"],["SP","Potim","3540754"],["SP","Potirendaba","3540804"],["SP","Pracinha","3540853"],["SP","Pradópolis","3540903"],["SP","Praia Grande","3541000"],["SP","Pratânia","3541059"],["SP","Presidente Alves","3541109"],["SP","Presidente Bernardes","3541208"],["SP","Presidente Epitácio","3541307"],["SP","Presidente Prudente","3541406"],["SP","Presidente Venceslau","3541505"],["SP","Promissão","3541604"],["SP","Quadra","3541653"],["SP","Quatá","3541703"],["SP","Queiroz","3541802"],["SP","Queluz","3541901"],["SP","Quintana","3542008"],["SP","Rafard","3542107"],["SP","Rancharia","3542206"],["SP","Redenção da Serra","3542305"],["SP","Regente Feijó","3542404"],["SP","Reginópolis","3542503"],["SP","Registro","3542602"],["SP","Restinga","3542701"],["SP","Ribeira","3542800"],["SP","Ribeirão Bonito","3542909"],["SP","Ribeirão Branco","3543006"],["SP","Ribeirão Corrente","3543105"],["SP","Ribeirão do Sul","3543204"],["SP","Ribeirão dos Índios","3543238"],["SP","Ribeirão Grande","3543253"],["SP","Ribeirão Pires","3543303"],["SP","Ribeirão Preto","3543402"],["SP","Rifaina","3543600"],["SP","Rincão","3543709"],["SP","Rinópolis","3543808"],["SP","Rio Claro","3543907"],["SP","Rio das Pedras","3544004"],["SP","Rio Grande da Serra","3544103"],["SP","Riolândia","3544202"],["SP","Riversul","3543501"],["SP","Rosana","3544251"],["SP","Roseira","3544301"],["SP","Rubiácea","3544400"],["SP","Rubinéia","3544509"],["SP","Sabino","3544608"],["SP","Sagres","3544707"],["SP","Sales","3544806"],["SP","Sales Oliveira","3544905"],["SP","Salesópolis","3545001"],["SP","Salmourão","3545100"],["SP","Saltinho","3545159"],["SP","Salto","3545209"],["SP","Salto de Pirapora","3545308"],["SP","Salto Grande","3545407"],["SP","Sandovalina","3545506"],["SP","Santa Adélia","3545605"],["SP","Santa Albertina","3545704"],["SP","Santa Bárbara d'Oeste","3545803"],["SP","Santa Branca","3546009"],["SP","Santa Clara d'Oeste","3546108"],["SP","Santa Cruz da Conceição","3546207"],["SP","Santa Cruz da Esperança","3546256"],["SP","Santa Cruz das Palmeiras","3546306"],["SP","Santa Cruz do Rio Pardo","3546405"],["SP","Santa Ernestina","3546504"],["SP","Santa Fé do Sul","3546603"],["SP","Santa Gertrudes","3546702"],["SP","Santa Isabel","3546801"],["SP","Santa Lúcia","3546900"],["SP","Santa Maria da Serra","3547007"],["SP","Santa Mercedes","3547106"],["SP","Santa Rita d'Oeste","3547403"],["SP","Santa Rita do Passa Quatro","3547502"],["SP","Santa Rosa de Viterbo","3547601"],["SP","Santa Salete","3547650"],["SP","Santana da Ponte Pensa","3547205"],["SP","Santana de Parnaíba","3547304"],["SP","Santo Anastácio","3547700"],["SP","Santo André","3547809"],["SP","Santo Antônio da Alegria","3547908"],["SP","Santo Antônio de Posse","3548005"],["SP","Santo Antônio do Aracanguá","3548054"],["SP","Santo Antônio do Jardim","3548104"],["SP","Santo Antônio do Pinhal","3548203"],["SP","Santo Expedito","3548302"],["SP","Santópolis do Aguapeí","3548401"],["SP","Santos","3548500"],["SP","São Bento do Sapucaí","3548609"],["SP","São Bernardo do Campo","3548708"],["SP","São Caetano do Sul","3548807"],["SP","São Carlos","3548906"],["SP","São Francisco","3549003"],["SP","São João da Boa Vista","3549102"],["SP","São João das Duas Pontes","3549201"],["SP","São João de Iracema","3549250"],["SP","São João do Pau d'Alho","3549300"],["SP","São Joaquim da Barra","3549409"],["SP","São José da Bela Vista","3549508"],["SP","São José do Barreiro","3549607"],["SP","São José do Rio Pardo","3549706"],["SP","São José do Rio Preto","3549805"],["SP","São José dos Campos","3549904"],["SP","São Lourenço da Serra","3549953"],["SP","São Luiz do Paraitinga","3550001"],["SP","São Manuel","3550100"],["SP","São Miguel Arcanjo","3550209"],["SP","São Paulo","3550308"],["SP","São Pedro","3550407"],["SP","São Pedro do Turvo","3550506"],["SP","São Roque","3550605"],["SP","São Sebastião","3550704"],["SP","São Sebastião da Grama","3550803"],["SP","São Simão","3550902"],["SP","São Vicente","3551009"],["SP","Sarapuí","3551108"],["SP","Sarutaiá","3551207"],["SP","Sebastianópolis do Sul","3551306"],["SP","Serra Azul","3551405"],["SP","Serra Negra","3551603"],["SP","Serrana","3551504"],["SP","Sertãozinho","3551702"],["SP","Sete Barras","3551801"],["SP","Severínia","3551900"],["SP","Silveiras","3552007"],["SP","Socorro","3552106"],["SP","Sorocaba","3552205"],["SP","Sud Mennucci","3552304"],["SP","Sumaré","3552403"],["SP","Suzanápolis","3552551"],["SP","Suzano","3552502"],["SP","Tabapuã","3552601"],["SP","Tabatinga","3552700"],["SP","Taboão da Serra","3552809"],["SP","Taciba","3552908"],["SP","Taguaí","3553005"],["SP","Taiaçu","3553104"],["SP","Taiúva","3553203"],["SP","Tambaú","3553302"],["SP","Tanabi","3553401"],["SP","Tapiraí","3553500"],["SP","Tapiratiba","3553609"],["SP","Taquaral","3553658"],["SP","Taquaritinga","3553708"],["SP","Taquarituba","3553807"],["SP","Taquarivaí","3553856"],["SP","Tarabai","3553906"],["SP","Tarumã","3553955"],["SP","Tatuí","3554003"],["SP","Taubaté","3554102"],["SP","Tejupá","3554201"],["SP","Teodoro Sampaio","3554300"],["SP","Terra Roxa","3554409"],["SP","Tietê","3554508"],["SP","Timburi","3554607"],["SP","Torre de Pedra","3554656"],["SP","Torrinha","3554706"],["SP","Trabiju","3554755"],["SP","Tremembé","3554805"],["SP","Três Fronteiras","3554904"],["SP","Tuiuti","3554953"],["SP","Tupã","3555000"],["SP","Tupi Paulista","3555109"],["SP","Turiúba","3555208"],["SP","Turmalina","3555307"],["SP","Ubarana","3555356"],["SP","Ubatuba","3555406"],["SP","Ubirajara","3555505"],["SP","Uchoa","3555604"],["SP","União Paulista","3555703"],["SP","Urânia","3555802"],["SP","Uru","3555901"],["SP","Urupês","3556008"],["SP","Valentim Gentil","3556107"],["SP","Valinhos","3556206"],["SP","Valparaíso","3556305"],["SP","Vargem","3556354"],["SP","Vargem Grande do Sul","3556404"],["SP","Vargem Grande Paulista","3556453"],["SP","Várzea Paulista","3556503"],["SP","Vera Cruz","3556602"],["SP","Vinhedo","3556701"],["SP","Viradouro","3556800"],["SP","Vista Alegre do Alto","3556909"],["SP","Vitória Brasil","3556958"],["SP","Votorantim","3557006"],["SP","Votuporanga","3557105"],["SP","Zacarias","3557154"],["SE","Amparo do São Francisco","2800100"],["SE","Aquidabã","2800209"],["SE","Aracaju","2800308"],["SE","Arauá","2800407"],["SE","Areia Branca","2800506"],["SE","Barra dos Coqueiros","2800605"],["SE","Boquim","2800670"],["SE","Brejo Grande","2800704"],["SE","Campo do Brito","2801009"],["SE","Canhoba","2801108"],["SE","Canindé de São Francisco","2801207"],["SE","Capela","2801306"],["SE","Carira","2801405"],["SE","Carmópolis","2801504"],["SE","Cedro de São João","2801603"],["SE","Cristinápolis","2801702"],["SE","Cumbe","2801900"],["SE","Divina Pastora","2802007"],["SE","Estância","2802106"],["SE","Feira Nova","2802205"],["SE","Frei Paulo","2802304"],["SE","Gararu","2802403"],["SE","General Maynard","2802502"],["SE","Graccho Cardoso","2802601"],["SE","Ilha das Flores","2802700"],["SE","Indiaroba","2802809"],["SE","Itabaiana","2802908"],["SE","Itabaianinha","2803005"],["SE","Itabi","2803104"],["SE","Itaporanga d'Ajuda","2803203"],["SE","Japaratuba","2803302"],["SE","Japoatã","2803401"],["SE","Lagarto","2803500"],["SE","Laranjeiras","2803609"],["SE","Macambira","2803708"],["SE","Malhada dos Bois","2803807"],["SE","Malhador","2803906"],["SE","Maruim","2804003"],["SE","Moita Bonita","2804102"],["SE","Monte Alegre de Sergipe","2804201"],["SE","Muribeca","2804300"],["SE","Neópolis","2804409"],["SE","Nossa Senhora Aparecida","2804458"],["SE","Nossa Senhora da Glória","2804508"],["SE","Nossa Senhora das Dores","2804607"],["SE","Nossa Senhora de Lourdes","2804706"],["SE","Nossa Senhora do Socorro","2804805"],["SE","Pacatuba","2804904"],["SE","Pedra Mole","2805000"],["SE","Pedrinhas","2805109"],["SE","Pinhão","2805208"],["SE","Pirambu","2805307"],["SE","Poço Redondo","2805406"],["SE","Poço Verde","2805505"],["SE","Porto da Folha","2805604"],["SE","Propriá","2805703"],["SE","Riachão do Dantas","2805802"],["SE","Riachuelo","2805901"],["SE","Ribeirópolis","2806008"],["SE","Rosário do Catete","2806107"],["SE","Salgado","2806206"],["SE","Santa Luzia do Itanhy","2806305"],["SE","Santa Rosa de Lima","2806503"],["SE","Santana do São Francisco","2806404"],["SE","Santo Amaro das Brotas","2806602"],["SE","São Cristóvão","2806701"],["SE","São Domingos","2806800"],["SE","São Francisco","2806909"],["SE","São Miguel do Aleixo","2807006"],["SE","Simão Dias","2807105"],["SE","Siriri","2807204"],["SE","Telha","2807303"],["SE","Tobias Barreto","2807402"],["SE","Tomar do Geru","2807501"],["SE","Umbaúba","2807600"],["TO","Abreulândia","1700251"],["TO","Aguiarnópolis","1700301"],["TO","Aliança do Tocantins","1700350"],["TO","Almas","1700400"],["TO","Alvorada","1700707"],["TO","Ananás","1701002"],["TO","Angico","1701051"],["TO","Aparecida do Rio Negro","1701101"],["TO","Aragominas","1701309"],["TO","Araguacema","1701903"],["TO","Araguaçu","1702000"],["TO","Araguaína","1702109"],["TO","Araguanã","1702158"],["TO","Araguatins","1702208"],["TO","Arapoema","1702307"],["TO","Arraias","1702406"],["TO","Augustinópolis","1702554"],["TO","Aurora do Tocantins","1702703"],["TO","Axixá do Tocantins","1702901"],["TO","Babaçulândia","1703008"],["TO","Bandeirantes do Tocantins","1703057"],["TO","Barra do Ouro","1703073"],["TO","Barrolândia","1703107"],["TO","Bernardo Sayão","1703206"],["TO","Bom Jesus do Tocantins","1703305"],["TO","Brasilândia do Tocantins","1703602"],["TO","Brejinho de Nazaré","1703701"],["TO","Buriti do Tocantins","1703800"],["TO","Cachoeirinha","1703826"],["TO","Campos Lindos","1703842"],["TO","Cariri do Tocantins","1703867"],["TO","Carmolândia","1703883"],["TO","Carrasco Bonito","1703891"],["TO","Caseara","1703909"],["TO","Centenário","1704105"],["TO","Chapada da Natividade","1705102"],["TO","Chapada de Areia","1704600"],["TO","Colinas do Tocantins","1705508"],["TO","Colméia","1716703"],["TO","Combinado","1705557"],["TO","Conceição do Tocantins","1705607"],["TO","Couto Magalhães","1706001"],["TO","Cristalândia","1706100"],["TO","Crixás do Tocantins","1706258"],["TO","Darcinópolis","1706506"],["TO","Dianópolis","1707009"],["TO","Divinópolis do Tocantins","1707108"],["TO","Dois Irmãos do Tocantins","1707207"],["TO","Dueré","1707306"],["TO","Esperantina","1707405"],["TO","Fátima","1707553"],["TO","Figueirópolis","1707652"],["TO","Filadélfia","1707702"],["TO","Formoso do Araguaia","1708205"],["TO","Goianorte","1708304"],["TO","Goiatins","1709005"],["TO","Guaraí","1709302"],["TO","Gurupi","1709500"],["TO","Ipueiras","1709807"],["TO","Itacajá","1710508"],["TO","Itaguatins","1710706"],["TO","Itapiratins","1710904"],["TO","Itaporã do Tocantins","1711100"],["TO","Jaú do Tocantins","1711506"],["TO","Juarina","1711803"],["TO","Lagoa da Confusão","1711902"],["TO","Lagoa do Tocantins","1711951"],["TO","Lajeado","1712009"],["TO","Lavandeira","1712157"],["TO","Lizarda","1712405"],["TO","Luzinópolis","1712454"],["TO","Marianópolis do Tocantins","1712504"],["TO","Mateiros","1712702"],["TO","Maurilândia do Tocantins","1712801"],["TO","Miracema do Tocantins","1713205"],["TO","Miranorte","1713304"],["TO","Monte do Carmo","1713601"],["TO","Monte Santo do Tocantins","1713700"],["TO","Muricilândia","1713957"],["TO","Natividade","1714203"],["TO","Nazaré","1714302"],["TO","Nova Olinda","1714880"],["TO","Nova Rosalândia","1715002"],["TO","Novo Acordo","1715101"],["TO","Novo Alegre","1715150"],["TO","Novo Jardim","1715259"],["TO","Oliveira de Fátima","1715507"],["TO","Palmas","1721000"],["TO","Palmeirante","1715705"],["TO","Palmeiras do Tocantins","1713809"],["TO","Palmeirópolis","1715754"],["TO","Paraíso do Tocantins","1716109"],["TO","Paranã","1716208"],["TO","Pau D'Arco","1716307"],["TO","Pedro Afonso","1716505"],["TO","Peixe","1716604"],["TO","Pequizeiro","1716653"],["TO","Pindorama do Tocantins","1717008"],["TO","Piraquê","1717206"],["TO","Pium","1717503"],["TO","Ponte Alta do Bom Jesus","1717800"],["TO","Ponte Alta do Tocantins","1717909"],["TO","Porto Alegre do Tocantins","1718006"],["TO","Porto Nacional","1718204"],["TO","Praia Norte","1718303"],["TO","Presidente Kennedy","1718402"],["TO","Pugmil","1718451"],["TO","Recursolândia","1718501"],["TO","Riachinho","1718550"],["TO","Rio da Conceição","1718659"],["TO","Rio dos Bois","1718709"],["TO","Rio Sono","1718758"],["TO","Sampaio","1718808"],["TO","Sandolândia","1718840"],["TO","Santa Fé do Araguaia","1718865"],["TO","Santa Maria do Tocantins","1718881"],["TO","Santa Rita do Tocantins","1718899"],["TO","Santa Rosa do Tocantins","1718907"],["TO","Santa Tereza do Tocantins","1719004"],["TO","Santa Terezinha do Tocantins","1720002"],["TO","São Bento do Tocantins","1720101"],["TO","São Félix do Tocantins","1720150"],["TO","São Miguel do Tocantins","1720200"],["TO","São Salvador do Tocantins","1720259"],["TO","São Sebastião do Tocantins","1720309"],["TO","São Valério","1720499"],["TO","Silvanópolis","1720655"],["TO","Sítio Novo do Tocantins","1720804"],["TO","Sucupira","1720853"],["TO","Tabocão","1708254"],["TO","Taguatinga","1720903"],["TO","Taipas do Tocantins","1720937"],["TO","Talismã","1720978"],["TO","Tocantínia","1721109"],["TO","Tocantinópolis","1721208"],["TO","Tupirama","1721257"],["TO","Tupiratins","1721307"],["TO","Wanderlândia","1722081"],["TO","Xambioá","1722107"]],"groups":{"AC":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21],"AL":[22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123],"AP":[124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139],"AM":[140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201],"BA":[202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,270,271,272,273,274,275,276,277,278,279,280,281,282,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,350,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,371,372,373,374,375,376,377,378,379,380,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,400,401,402,403,404,405,406,407,408,409,410,411,412,413,414,415,416,417,418,419,420,421,422,423,424,425,426,427,428,429,430,431,432,433,434,435,436,437,438,439,440,441,442,443,444,445,446,447,448,449,450,451,452,453,454,455,456,457,458,459,460,461,462,463,464,465,466,467,468,469,470,471,472,473,474,475,476,477,478,479,480,481,482,483,484,485,486,487,488,489,490,491,492,493,494,495,496,497,498,499,500,501,502,503,504,505,506,507,508,509,510,511,512,513,514,515,516,517,518,519,520,521,522,523,524,525,526,527,528,529,530,531,532,533,534,535,536,537,538,539,540,541,542,543,544,545,546,547,548,549,550,551,552,553,554,555,556,557,558,559,560,561,562,563,564,565,566,567,568,569,570,571,572,573,574,575,576,577,578,579,580,581,582,583,584,585,586,587,588,589,590,591,592,593,594,595,596,597,598,599,600,601,602,603,604,605,606,607,608,609,610,611,612,613,614,615,616,617,618],"CE":[619,620,621,622,623,624,625,626,627,628,629,630,631,632,633,634,635,636,637,638,639,640,641,642,643,644,645,646,647,648,649,650,651,652,653,654,655,656,657,658,659,660,661,662,663,664,665,666,667,668,669,670,671,672,673,674,675,676,677,678,679,680,681,682,683,684,685,686,687,688,689,690,691,692,693,694,695,696,697,698,699,700,701,702,703,704,705,706,707,708,709,710,711,712,713,714,715,716,717,718,719,720,721,722,723,724,725,726,727,728,729,730,731,732,733,734,735,736,737,738,739,740,741,742,743,744,745,746,747,748,749,750,751,752,753,754,755,756,757,758,759,760,761,762,763,764,765,766,767,768,769,770,771,772,773,774,775,776,777,778,779,780,781,782,783,784,785,786,787,788,789,790,791,792,793,794,795,796,797,798,799,800,801,802],"DF":[803],"ES":[804,805,806,807,808,809,810,811,812,813,814,815,816,817,818,819,820,821,822,823,824,825,826,827,828,829,830,831,832,833,834,835,836,837,838,839,840,841,842,843,844,845,846,847,848,849,850,851,852,853,854,855,856,857,858,859,860,861,862,863,864,865,866,867,868,869,870,871,872,873,874,875,876,877,878,879,880,881],"GO":[882,883,884,885,886,887,888,889,890,891,892,893,894,895,896,897,898,899,900,901,902,903,904,905,906,907,908,909,910,911,912,913,914,915,916,917,918,919,920,921,922,923,924,925,926,927,928,929,930,931,932,933,934,935,936,937,938,939,940,941,942,943,944,945,946,947,948,949,950,951,952,953,954,955,956,957,958,959,960,961,962,963,964,965,966,967,968,969,970,971,972,973,974,975,976,977,978,979,980,981,982,983,984,985,986,987,988,989,990,991,992,993,994,995,996,997,998,999,1000,1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1011,1012,1013,1014,1015,1016,1017,1018,1019,1020,1021,1022,1023,1024,1025,1026,1027,1028,1029,1030,1031,1032,1033,1034,1035,1036,1037,1038,1039,1040,1041,1042,1043,1044,1045,1046,1047,1048,1049,1050,1051,1052,1053,1054,1055,1056,1057,1058,1059,1060,1061,1062,1063,1064,1065,1066,1067,1068,1069,1070,1071,1072,1073,1074,1075,1076,1077,1078,1079,1080,1081,1082,1083,1084,1085,1086,1087,1088,1089,1090,1091,1092,1093,1094,1095,1096,1097,1098,1099,1100,1101,1102,1103,1104,1105,1106,1107,1108,1109,1110,1111,1112,1113,1114,1115,1116,1117,1118,1119,1120,1121,1122,1123,1124,1125,1126,1127],"MA":[1128,1129,1130,1131,1132,1133,1134,1135,1136,1137,1138,1139,1140,1141,1142,1143,1144,1145,1146,1147,1148,1149,1150,1151,1152,1153,1154,1155,1156,1157,1158,1159,1160,1161,1162,1163,1164,1165,1166,1167,1168,1169,1170,1171,1172,1173,1174,1175,1176,1177,1178,1179,1180,1181,1182,1183,1184,1185,1186,1187,1188,1189,1190,1191,1192,1193,1194,1195,1196,1197,1198,1199,1200,1201,1202,1203,1204,1205,1206,1207,1208,1209,1210,1211,1212,1213,1214,1215,1216,1217,1218,1219,1220,1221,1222,1223,1224,1225,1226,1227,1228,1229,1230,1231,1232,1233,1234,1235,1236,1237,1238,1239,1240,1241,1242,1243,1244,1245,1246,1247,1248,1249,1250,1251,1252,1253,1254,1255,1256,1257,1258,1259,1260,1261,1262,1263,1264,1265,1266,1267,1268,1269,1270,1271,1272,1273,1274,1275,1276,1277,1278,1279,1280,1281,1282,1283,1284,1285,1286,1287,1288,1289,1290,1291,1292,1293,1294,1295,1296,1297,1298,1299,1300,1301,1302,1303,1304,1305,1306,1307,1308,1309,1310,1311,1312,1313,1314,1315,1316,1317,1318,1319,1320,1321,1322,1323,1324,1325,1326,1327,1328,1329,1330,1331,1332,1333,1334,1335,1336,1337,1338,1339,1340,1341,1342,1343,1344],"MT":[1345,1346,1347,1348,1349,1350,1351,1352,1353,1354,1355,1356,1357,1358,1359,1360,1361,1362,1363,1364,1365,1366,1367,1368,1369,1370,1371,1372,1373,1374,1375,1376,1377,1378,1379,1380,1381,1382,1383,1384,1385,1386,1387,1388,1389,1390,1391,1392,1393,1394,1395,1396,1397,1398,1399,1400,1401,1402,1403,1404,1405,1406,1407,1408,1409,1410,1411,1412,1413,1414,1415,1416,1417,1418,1419,1420,1421,1422,1423,1424,1425,1426,1427,1428,1429,1430,1431,1432,1433,1434,1435,1436,1437,1438,1439,1440,1441,1442,1443,1444,1445,1446,1447,1448,1449,1450,1451,1452,1453,1454,1455,1456,1457,1458,1459,1460,1461,1462,1463,1464,1465,1466,1467,1468,1469,1470,1471,1472,1473,1474,1475,1476,1477,1478,1479,1480,1481,1482,1483,1484,1485,1486],"MS":[1487,1488,1489,1490,1491,1492,1493,1494,1495,1496,1497,1498,1499,1500,1501,1502,1503,1504,1505,1506,1507,1508,1509,1510,1511,1512,1513,1514,1515,1516,1517,1518,1519,1520,1521,1522,1523,1524,1525,1526,1527,1528,1529,1530,1531,1532,1533,1534,1535,1536,1537,1538,1539,1540,1541,1542,1543,1544,1545,1546,1547,1548,1549,1550,1551,1552,1553,1554,1555,1556,1557,1558,1559,1560,1561,1562,1563,1564,1565],"MG":[1566,1567,1568,1569,1570,1571,1572,1573,1574,1575,1576,1577,1578,1579,1580,1581,1582,1583,1584,1585,1586,1587,1588,1589,1590,1591,1592,1593,1594,1595,1596,1597,1598,1599,1600,1601,1602,1603,1604,1605,1606,1607,1608,1609,1610,1611,1612,1613,1614,1615,1616,1617,1618,1619,1620,1621,1622,1623,1624,1625,1626,1627,1628,1629,1630,1631,1632,1633,1634,1635,1636,1637,1638,1639,1640,1641,1642,1643,1644,1645,1646,1647,1648,1649,1650,1651,1652,1653,1654,1655,1656,1657,1658,1659,1660,1661,1662,1663,1664,1665,1666,1667,1668,1669,1670,1671,1672,1673,1674,1675,1676,1677,1678,1679,1680,1681,1682,1683,1684,1685,1686,1687,1688,1689,1690,1691,1692,1693,1694,1695,1696,1697,1698,1699,1700,1701,1702,1703,1704,1705,1706,1707,1708,1709,1710,1711,1712,1713,1714,1715,1716,1717,1718,1719,1720,1721,1722,1723,1724,1725,1726,1727,1728,1729,1730,1731,1732,1733,1734,1735,1736,1737,1738,1739,1740,1741,1742,1743,1744,1745,1746,1747,1748,1749,1750,1751,1752,1753,1754,1755,1756,1757,1758,1759,1760,1761,1762,1763,1764,1765,1766,1767,1768,1769,1770,1771,1772,1773,1774,1775,1776,1777,1778,1779,1780,1781,1782,1783,1784,1785,1786,1787,1788,1789,1790,1791,1792,1793,1794,1795,1796,1797,1798,1799,1800,1801,1802,1803,1804,1805,1806,1807,1808,1809,1810,1811,1812,1813,1814,1815,1816,1817,1818,1819,1820,1821,1822,1823,1824,1825,1826,1827,1828,1829,1830,1831,1832,1833,1834,1835,1836,1837,1838,1839,1840,1841,1842,1843,1844,1845,1846,1847,1848,1849,1850,1851,1852,1853,1854,1855,1856,1857,1858,1859,1860,1861,1862,1863,1864,1865,1866,1867,1868,1869,1870,1871,1872,1873,1874,1875,1876,1877,1878,1879,1880,1881,1882,1883,1884,1885,1886,1887,1888,1889,1890,1891,1892,1893,1894,1895,1896,1897,1898,1899,1900,1901,1902,1903,1904,1905,1906,1907,1908,1909,1910,1911,1912,1913,1914,1915,1916,1917,1918,1919,1920,1921,1922,1923,1924,1925,1926,1927,1928,1929,1930,1931,1932,1933,1934,1935,1936,1937,1938,1939,1940,1941,1942,1943,1944,1945,1946,1947,1948,1949,1950,1951,1952,1953,1954,1955,1956,1957,1958,1959,1960,1961,1962,1963,1964,1965,1966,1967,1968,1969,1970,1971,1972,1973,1974,1975,1976,1977,1978,1979,1980,1981,1982,1983,1984,1985,1986,1987,1988,1989,1990,1991,1992,1993,1994,1995,1996,1997,1998,1999,2000,2001,2002,2003,2004,2005,2006,2007,2008,2009,2010,2011,2012,2013,2014,2015,2016,2017,2018,2019,2020,2021,2022,2023,2024,2025,2026,2027,2028,2029,2030,2031,2032,2033,2034,2035,2036,2037,2038,2039,2040,2041,2042,2043,2044,2045,2046,2047,2048,2049,2050,2051,2052,2053,2054,2055,2056,2057,2058,2059,2060,2061,2062,2063,2064,2065,2066,2067,2068,2069,2070,2071,2072,2073,2074,2075,2076,2077,2078,2079,2080,2081,2082,2083,2084,2085,2086,2087,2088,2089,2090,2091,2092,2093,2094,2095,2096,2097,2098,2099,2100,2101,2102,2103,2104,2105,2106,2107,2108,2109,2110,2111,2112,2113,2114,2115,2116,2117,2118,2119,2120,2121,2122,2123,2124,2125,2126,2127,2128,2129,2130,2131,2132,2133,2134,2135,2136,2137,2138,2139,2140,2141,2142,2143,2144,2145,2146,2147,2148,2149,2150,2151,2152,2153,2154,2155,2156,2157,2158,2159,2160,2161,2162,2163,2164,2165,2166,2167,2168,2169,2170,2171,2172,2173,2174,2175,2176,2177,2178,2179,2180,2181,2182,2183,2184,2185,2186,2187,2188,2189,2190,2191,2192,2193,2194,2195,2196,2197,2198,2199,2200,2201,2202,2203,2204,2205,2206,2207,2208,2209,2210,2211,2212,2213,2214,2215,2216,2217,2218,2219,2220,2221,2222,2223,2224,2225,2226,2227,2228,2229,2230,2231,2232,2233,2234,2235,2236,2237,2238,2239,2240,2241,2242,2243,2244,2245,2246,2247,2248,2249,2250,2251,2252,2253,2254,2255,2256,2257,2258,2259,2260,2261,2262,2263,2264,2265,2266,2267,2268,2269,2270,2271,2272,2273,2274,2275,2276,2277,2278,2279,2280,2281,2282,2283,2284,2285,2286,2287,2288,2289,2290,2291,2292,2293,2294,2295,2296,2297,2298,2299,2300,2301,2302,2303,2304,2305,2306,2307,2308,2309,2310,2311,2312,2313,2314,2315,2316,2317,2318,2319,2320,2321,2322,2323,2324,2325,2326,2327,2328,2329,2330,2331,2332,2333,2334,2335,2336,2337,2338,2339,2340,2341,2342,2343,2344,2345,2346,2347,2348,2349,2350,2351,2352,2353,2354,2355,2356,2357,2358,2359,2360,2361,2362,2363,2364,2365,2366,2367,2368,2369,2370,2371,2372,2373,2374,2375,2376,2377,2378,2379,2380,2381,2382,2383,2384,2385,2386,2387,2388,2389,2390,2391,2392,2393,2394,2395,2396,2397,2398,2399,2400,2401,2402,2403,2404,2405,2406,2407,2408,2409,2410,2411,2412,2413,2414,2415,2416,2417,2418],"PA":[2419,2420,2421,2422,2423,2424,2425,2426,2427,2428,2429,2430,2431,2432,2433,2434,2435,2436,2437,2438,2439,2440,2441,2442,2443,2444,2445,2446,2447,2448,2449,2450,2451,2452,2453,2454,2455,2456,2457,2458,2459,2460,2461,2462,2463,2464,2465,2466,2467,2468,2469,2470,2471,2472,2473,2474,2475,2476,2477,2478,2479,2480,2481,2482,2483,2484,2485,2486,2487,2488,2489,2490,2491,2492,2493,2494,2495,2496,2497,2498,2499,2500,2501,2502,2503,2504,2505,2506,2507,2508,2509,2510,2511,2512,2513,2514,2515,2516,2517,2518,2519,2520,2521,2522,2523,2524,2525,2526,2527,2528,2529,2530,2531,2532,2533,2534,2535,2536,2537,2538,2539,2540,2541,2542,2543,2544,2545,2546,2547,2548,2549,2550,2551,2552,2553,2554,2555,2556,2557,2558,2559,2560,2561,2562],"PB":[2563,2564,2565,2566,2567,2568,2569,2570,2571,2572,2573,2574,2575,2576,2577,2578,2579,2580,2581,2582,2583,2584,2585,2586,2587,2588,2589,2590,2591,2592,2593,2594,2595,2596,2597,2598,2599,2600,2601,2602,2603,2604,2605,2606,2607,2608,2609,2610,2611,2612,2613,2614,2615,2616,2617,2618,2619,2620,2621,2622,2623,2624,2625,2626,2627,2628,2629,2630,2631,2632,2633,2634,2635,2636,2637,2638,2639,2640,2641,2642,2643,2644,2645,2646,2647,2648,2649,2650,2651,2652,2653,2654,2655,2656,2657,2658,2659,2660,2661,2662,2663,2664,2665,2666,2667,2668,2669,2670,2671,2672,2673,2674,2675,2676,2677,2678,2679,2680,2681,2682,2683,2684,2685,2686,2687,2688,2689,2690,2691,2692,2693,2694,2695,2696,2697,2698,2699,2700,2701,2702,2703,2704,2705,2706,2707,2708,2709,2710,2711,2712,2713,2714,2715,2716,2717,2718,2719,2720,2721,2722,2723,2724,2725,2726,2727,2728,2729,2730,2731,2732,2733,2734,2735,2736,2737,2738,2739,2740,2741,2742,2743,2744,2745,2746,2747,2748,2749,2750,2751,2752,2753,2754,2755,2756,2757,2758,2759,2760,2761,2762,2763,2764,2765,2766,2767,2768,2769,2770,2771,2772,2773,2774,2775,2776,2777,2778,2779,2780,2781,2782,2783,2784,2785],"PR":[2786,2787,2788,2789,2790,2791,2792,2793,2794,2795,2796,2797,2798,2799,2800,2801,2802,2803,2804,2805,2806,2807,2808,2809,2810,2811,2812,2813,2814,2815,2816,2817,2818,2819,2820,2821,2822,2823,2824,2825,2826,2827,2828,2829,2830,2831,2832,2833,2834,2835,2836,2837,2838,2839,2840,2841,2842,2843,2844,2845,2846,2847,2848,2849,2850,2851,2852,2853,2854,2855,2856,2857,2858,2859,2860,2861,2862,2863,2864,2865,2866,2867,2868,2869,2870,2871,2872,2873,2874,2875,2876,2877,2878,2879,2880,2881,2882,2883,2884,2885,2886,2887,2888,2889,2890,2891,2892,2893,2894,2895,2896,2897,2898,2899,2900,2901,2902,2903,2904,2905,2906,2907,2908,2909,2910,2911,2912,2913,2914,2915,2916,2917,2918,2919,2920,2921,2922,2923,2924,2925,2926,2927,2928,2929,2930,2931,2932,2933,2934,2935,2936,2937,2938,2939,2940,2941,2942,2943,2944,2945,2946,2947,2948,2949,2950,2951,2952,2953,2954,2955,2956,2957,2958,2959,2960,2961,2962,2963,2964,2965,2966,2967,2968,2969,2970,2971,2972,2973,2974,2975,2976,2977,2978,2979,2980,2981,2982,2983,2984,2985,2986,2987,2988,2989,2990,2991,2992,2993,2994,2995,2996,2997,2998,2999,3000,3001,3002,3003,3004,3005,3006,3007,3008,3009,3010,3011,3012,3013,3014,3015,3016,3017,3018,3019,3020,3021,3022,3023,3024,3025,3026,3027,3028,3029,3030,3031,3032,3033,3034,3035,3036,3037,3038,3039,3040,3041,3042,3043,3044,3045,3046,3047,3048,3049,3050,3051,3052,3053,3054,3055,3056,3057,3058,3059,3060,3061,3062,3063,3064,3065,3066,3067,3068,3069,3070,3071,3072,3073,3074,3075,3076,3077,3078,3079,3080,3081,3082,3083,3084,3085,3086,3087,3088,3089,3090,3091,3092,3093,3094,3095,3096,3097,3098,3099,3100,3101,3102,3103,3104,3105,3106,3107,3108,3109,3110,3111,3112,3113,3114,3115,3116,3117,3118,3119,3120,3121,3122,3123,3124,3125,3126,3127,3128,3129,3130,3131,3132,3133,3134,3135,3136,3137,3138,3139,3140,3141,3142,3143,3144,3145,3146,3147,3148,3149,3150,3151,3152,3153,3154,3155,3156,3157,3158,3159,3160,3161,3162,3163,3164,3165,3166,3167,3168,3169,3170,3171,3172,3173,3174,3175,3176,3177,3178,3179,3180,3181,3182,3183,3184],"PE":[3185,3186,3187,3188,3189,3190,3191,3192,3193,3194,3195,3196,3197,3198,3199,3200,3201,3202,3203,3204,3205,3206,3207,3208,3209,3210,3211,3212,3213,3214,3215,3216,3217,3218,3219,3220,3221,3222,3223,3224,3225,3226,3227,3228,3229,3230,3231,3232,3233,3234,3235,3236,3237,3238,3239,3240,3241,3242,3243,3244,3245,3246,3247,3248,3249,3250,3251,3252,3253,3254,3255,3256,3257,3258,3259,3260,3261,3262,3263,3264,3265,3266,3267,3268,3269,3270,3271,3272,3273,3274,3275,3276,3277,3278,3279,3280,3281,3282,3283,3284,3285,3286,3287,3288,3289,3290,3291,3292,3293,3294,3295,3296,3297,3298,3299,3300,3301,3302,3303,3304,3305,3306,3307,3308,3309,3310,3311,3312,3313,3314,3315,3316,3317,3318,3319,3320,3321,3322,3323,3324,3325,3326,3327,3328,3329,3330,3331,3332,3333,3334,3335,3336,3337,3338,3339,3340,3341,3342,3343,3344,3345,3346,3347,3348,3349,3350,3351,3352,3353,3354,3355,3356,3357,3358,3359,3360,3361,3362,3363,3364,3365,3366,3367,3368,3369],"PI":[3370,3371,3372,3373,3374,3375,3376,3377,3378,3379,3380,3381,3382,3383,3384,3385,3386,3387,3388,3389,3390,3391,3392,3393,3394,3395,3396,3397,3398,3399,3400,3401,3402,3403,3404,3405,3406,3407,3408,3409,3410,3411,3412,3413,3414,3415,3416,3417,3418,3419,3420,3421,3422,3423,3424,3425,3426,3427,3428,3429,3430,3431,3432,3433,3434,3435,3436,3437,3438,3439,3440,3441,3442,3443,3444,3445,3446,3447,3448,3449,3450,3451,3452,3453,3454,3455,3456,3457,3458,3459,3460,3461,3462,3463,3464,3465,3466,3467,3468,3469,3470,3471,3472,3473,3474,3475,3476,3477,3478,3479,3480,3481,3482,3483,3484,3485,3486,3487,3488,3489,3490,3491,3492,3493,3494,3495,3496,3497,3498,3499,3500,3501,3502,3503,3504,3505,3506,3507,3508,3509,3510,3511,3512,3513,3514,3515,3516,3517,3518,3519,3520,3521,3522,3523,3524,3525,3526,3527,3528,3529,3530,3531,3532,3533,3534,3535,3536,3537,3538,3539,3540,3541,3542,3543,3544,3545,3546,3547,3548,3549,3550,3551,3552,3553,3554,3555,3556,3557,3558,3559,3560,3561,3562,3563,3564,3565,3566,3567,3568,3569,3570,3571,3572,3573,3574,3575,3576,3577,3578,3579,3580,3581,3582,3583,3584,3585,3586,3587,3588,3589,3590,3591,3592,3593],"RJ":[3594,3595,3596,3597,3598,3599,3600,3601,3602,3603,3604,3605,3606,3607,3608,3609,3610,3611,3612,3613,3614,3615,3616,3617,3618,3619,3620,3621,3622,3623,3624,3625,3626,3627,3628,3629,3630,3631,3632,3633,3634,3635,3636,3637,3638,3639,3640,3641,3642,3643,3644,3645,3646,3647,3648,3649,3650,3651,3652,3653,3654,3655,3656,3657,3658,3659,3660,3661,3662,3663,3664,3665,3666,3667,3668,3669,3670,3671,3672,3673,3674,3675,3676,3677,3678,3679,3680,3681,3682,3683,3684,3685],"RN":[3686,3687,3688,3689,3690,3691,3692,3693,3694,3695,3696,3697,3698,3699,3700,3701,3702,3703,3704,3705,3706,3707,3708,3709,3710,3711,3712,3713,3714,3715,3716,3717,3718,3719,3720,3721,3722,3723,3724,3725,3726,3727,3728,3729,3730,3731,3732,3733,3734,3735,3736,3737,3738,3739,3740,3741,3742,3743,3744,3745,3746,3747,3748,3749,3750,3751,3752,3753,3754,3755,3756,3757,3758,3759,3760,3761,3762,3763,3764,3765,3766,3767,3768,3769,3770,3771,3772,3773,3774,3775,3776,3777,3778,3779,3780,3781,3782,3783,3784,3785,3786,3787,3788,3789,3790,3791,3792,3793,3794,3795,3796,3797,3798,3799,3800,3801,3802,3803,3804,3805,3806,3807,3808,3809,3810,3811,3812,3813,3814,3815,3816,3817,3818,3819,3820,3821,3822,3823,3824,3825,3826,3827,3828,3829,3830,3831,3832,3833,3834,3835,3836,3837,3838,3839,3840,3841,3842,3843,3844,3845,3846,3847,3848,3849,3850,3851,3852],"RS":[3853,3854,3855,3856,3857,3858,3859,3860,3861,3862,3863,3864,3865,3866,3867,3868,3869,3870,3871,3872,3873,3874,3875,3876,3877,3878,3879,3880,3881,3882,3883,3884,3885,3886,3887,3888,3889,3890,3891,3892,3893,3894,3895,3896,3897,3898,3899,3900,3901,3902,3903,3904,3905,3906,3907,3908,3909,3910,3911,3912,3913,3914,3915,3916,3917,3918,3919,3920,3921,3922,3923,3924,3925,3926,3927,3928,3929,3930,3931,3932,3933,3934,3935,3936,3937,3938,3939,3940,3941,3942,3943,3944,3945,3946,3947,3948,3949,3950,3951,3952,3953,3954,3955,3956,3957,3958,3959,3960,3961,3962,3963,3964,3965,3966,3967,3968,3969,3970,3971,3972,3973,3974,3975,3976,3977,3978,3979,3980,3981,3982,3983,3984,3985,3986,3987,3988,3989,3990,3991,3992,3993,3994,3995,3996,3997,3998,3999,4000,4001,4002,4003,4004,4005,4006,4007,4008,4009,4010,4011,4012,4013,4014,4015,4016,4017,4018,4019,4020,4021,4022,4023,4024,4025,4026,4027,4028,4029,4030,4031,4032,4033,4034,4035,4036,4037,4038,4039,4040,4041,4042,4043,4044,4045,4046,4047,4048,4049,4050,4051,4052,4053,4054,4055,4056,4057,4058,4059,4060,4061,4062,4063,4064,4065,4066,4067,4068,4069,4070,4071,4072,4073,4074,4075,4076,4077,4078,4079,4080,4081,4082,4083,4084,4085,4086,4087,4088,4089,4090,4091,4092,4093,4094,4095,4096,4097,4098,4099,4100,4101,4102,4103,4104,4105,4106,4107,4108,4109,4110,4111,4112,4113,4114,4115,4116,4117,4118,4119,4120,4121,4122,4123,4124,4125,4126,4127,4128,4129,4130,4131,4132,4133,4134,4135,4136,4137,4138,4139,4140,4141,4142,4143,4144,4145,4146,4147,4148,4149,4150,4151,4152,4153,4154,4155,4156,4157,4158,4159,4160,4161,4162,4163,4164,4165,4166,4167,4168,4169,4170,4171,4172,4173,4174,4175,4176,4177,4178,4179,4180,4181,4182,4183,4184,4185,4186,4187,4188,4189,4190,4191,4192,4193,4194,4195,4196,4197,4198,4199,4200,4201,4202,4203,4204,4205,4206,4207,4208,4209,4210,4211,4212,4213,4214,4215,4216,4217,4218,4219,4220,4221,4222,4223,4224,4225,4226,4227,4228,4229,4230,4231,4232,4233,4234,4235,4236,4237,4238,4239,4240,4241,4242,4243,4244,4245,4246,4247,4248,4249,4250,4251,4252,4253,4254,4255,4256,4257,4258,4259,4260,4261,4262,4263,4264,4265,4266,4267,4268,4269,4270,4271,4272,4273,4274,4275,4276,4277,4278,4279,4280,4281,4282,4283,4284,4285,4286,4287,4288,4289,4290,4291,4292,4293,4294,4295,4296,4297,4298,4299,4300,4301,4302,4303,4304,4305,4306,4307,4308,4309,4310,4311,4312,4313,4314,4315,4316,4317,4318,4319,4320,4321,4322,4323,4324,4325,4326,4327,4328,4329,4330,4331,4332,4333,4334,4335,4336,4337,4338,4339,4340,4341,4342,4343,4344,4345,4346,4347,4348,4349],"RO":[4350,4351,4352,4353,4354,4355,4356,4357,4358,4359,4360,4361,4362,4363,4364,4365,4366,4367,4368,4369,4370,4371,4372,4373,4374,4375,4376,4377,4378,4379,4380,4381,4382,4383,4384,4385,4386,4387,4388,4389,4390,4391,4392,4393,4394,4395,4396,4397,4398,4399,4400,4401],"RR":[4402,4403,4404,4405,4406,4407,4408,4409,4410,4411,4412,4413,4414,4415,4416],"SC":[4417,4418,4419,4420,4421,4422,4423,4424,4425,4426,4427,4428,4429,4430,4431,4432,4433,4434,4435,4436,4437,4438,4439,4440,4441,4442,4443,4444,4445,4446,4447,4448,4449,4450,4451,4452,4453,4454,4455,4456,4457,4458,4459,4460,4461,4462,4463,4464,4465,4466,4467,4468,4469,4470,4471,4472,4473,4474,4475,4476,4477,4478,4479,4480,4481,4482,4483,4484,4485,4486,4487,4488,4489,4490,4491,4492,4493,4494,4495,4496,4497,4498,4499,4500,4501,4502,4503,4504,4505,4506,4507,4508,4509,4510,4511,4512,4513,4514,4515,4516,4517,4518,4519,4520,4521,4522,4523,4524,4525,4526,4527,4528,4529,4530,4531,4532,4533,4534,4535,4536,4537,4538,4539,4540,4541,4542,4543,4544,4545,4546,4547,4548,4549,4550,4551,4552,4553,4554,4555,4556,4557,4558,4559,4560,4561,4562,4563,4564,4565,4566,4567,4568,4569,4570,4571,4572,4573,4574,4575,4576,4577,4578,4579,4580,4581,4582,4583,4584,4585,4586,4587,4588,4589,4590,4591,4592,4593,4594,4595,4596,4597,4598,4599,4600,4601,4602,4603,4604,4605,4606,4607,4608,4609,4610,4611,4612,4613,4614,4615,4616,4617,4618,4619,4620,4621,4622,4623,4624,4625,4626,4627,4628,4629,4630,4631,4632,4633,4634,4635,4636,4637,4638,4639,4640,4641,4642,4643,4644,4645,4646,4647,4648,4649,4650,4651,4652,4653,4654,4655,4656,4657,4658,4659,4660,4661,4662,4663,4664,4665,4666,4667,4668,4669,4670,4671,4672,4673,4674,4675,4676,4677,4678,4679,4680,4681,4682,4683,4684,4685,4686,4687,4688,4689,4690,4691,4692,4693,4694,4695,4696,4697,4698,4699,4700,4701,4702,4703,4704,4705,4706,4707,4708,4709,4710,4711],"SP":[4712,4713,4714,4715,4716,4717,4718,4719,4720,4721,4722,4723,4724,4725,4726,4727,4728,4729,4730,4731,4732,4733,4734,4735,4736,4737,4738,4739,4740,4741,4742,4743,4744,4745,4746,4747,4748,4749,4750,4751,4752,4753,4754,4755,4756,4757,4758,4759,4760,4761,4762,4763,4764,4765,4766,4767,4768,4769,4770,4771,4772,4773,4774,4775,4776,4777,4778,4779,4780,4781,4782,4783,4784,4785,4786,4787,4788,4789,4790,4791,4792,4793,4794,4795,4796,4797,4798,4799,4800,4801,4802,4803,4804,4805,4806,4807,4808,4809,4810,4811,4812,4813,4814,4815,4816,4817,4818,4819,4820,4821,4822,4823,4824,4825,4826,4827,4828,4829,4830,4831,4832,4833,4834,4835,4836,4837,4838,4839,4840,4841,4842,4843,4844,4845,4846,4847,4848,4849,4850,4851,4852,4853,4854,4855,4856,4857,4858,4859,4860,4861,4862,4863,4864,4865,4866,4867,4868,4869,4870,4871,4872,4873,4874,4875,4876,4877,4878,4879,4880,4881,4882,4883,4884,4885,4886,4887,4888,4889,4890,4891,4892,4893,4894,4895,4896,4897,4898,4899,4900,4901,4902,4903,4904,4905,4906,4907,4908,4909,4910,4911,4912,4913,4914,4915,4916,4917,4918,4919,4920,4921,4922,4923,4924,4925,4926,4927,4928,4929,4930,4931,4932,4933,4934,4935,4936,4937,4938,4939,4940,4941,4942,4943,4944,4945,4946,4947,4948,4949,4950,4951,4952,4953,4954,4955,4956,4957,4958,4959,4960,4961,4962,4963,4964,4965,4966,4967,4968,4969,4970,4971,4972,4973,4974,4975,4976,4977,4978,4979,4980,4981,4982,4983,4984,4985,4986,4987,4988,4989,4990,4991,4992,4993,4994,4995,4996,4997,4998,4999,5000,5001,5002,5003,5004,5005,5006,5007,5008,5009,5010,5011,5012,5013,5014,5015,5016,5017,5018,5019,5020,5021,5022,5023,5024,5025,5026,5027,5028,5029,5030,5031,5032,5033,5034,5035,5036,5037,5038,5039,5040,5041,5042,5043,5044,5045,5046,5047,5048,5049,5050,5051,5052,5053,5054,5055,5056,5057,5058,5059,5060,5061,5062,5063,5064,5065,5066,5067,5068,5069,5070,5071,5072,5073,5074,5075,5076,5077,5078,5079,5080,5081,5082,5083,5084,5085,5086,5087,5088,5089,5090,5091,5092,5093,5094,5095,5096,5097,5098,5099,5100,5101,5102,5103,5104,5105,5106,5107,5108,5109,5110,5111,5112,5113,5114,5115,5116,5117,5118,5119,5120,5121,5122,5123,5124,5125,5126,5127,5128,5129,5130,5131,5132,5133,5134,5135,5136,5137,5138,5139,5140,5141,5142,5143,5144,5145,5146,5147,5148,5149,5150,5151,5152,5153,5154,5155,5156,5157,5158,5159,5160,5161,5162,5163,5164,5165,5166,5167,5168,5169,5170,5171,5172,5173,5174,5175,5176,5177,5178,5179,5180,5181,5182,5183,5184,5185,5186,5187,5188,5189,5190,5191,5192,5193,5194,5195,5196,5197,5198,5199,5200,5201,5202,5203,5204,5205,5206,5207,5208,5209,5210,5211,5212,5213,5214,5215,5216,5217,5218,5219,5220,5221,5222,5223,5224,5225,5226,5227,5228,5229,5230,5231,5232,5233,5234,5235,5236,5237,5238,5239,5240,5241,5242,5243,5244,5245,5246,5247,5248,5249,5250,5251,5252,5253,5254,5255,5256,5257,5258,5259,5260,5261,5262,5263,5264,5265,5266,5267,5268,5269,5270,5271,5272,5273,5274,5275,5276,5277,5278,5279,5280,5281,5282,5283,5284,5285,5286,5287,5288,5289,5290,5291,5292,5293,5294,5295,5296,5297,5298,5299,5300,5301,5302,5303,5304,5305,5306,5307,5308,5309,5310,5311,5312,5313,5314,5315,5316,5317,5318,5319,5320,5321,5322,5323,5324,5325,5326,5327,5328,5329,5330,5331,5332,5333,5334,5335,5336,5337,5338,5339,5340,5341,5342,5343,5344,5345,5346,5347,5348,5349,5350,5351,5352,5353,5354,5355,5356],"SE":[5357,5358,5359,5360,5361,5362,5363,5364,5365,5366,5367,5368,5369,5370,5371,5372,5373,5374,5375,5376,5377,5378,5379,5380,5381,5382,5383,5384,5385,5386,5387,5388,5389,5390,5391,5392,5393,5394,5395,5396,5397,5398,5399,5400,5401,5402,5403,5404,5405,5406,5407,5408,5409,5410,5411,5412,5413,5414,5415,5416,5417,5418,5419,5420,5421,5422,5423,5424,5425,5426,5427,5428,5429,5430,5431],"TO":[5432,5433,5434,5435,5436,5437,5438,5439,5440,5441,5442,5443,5444,5445,5446,5447,5448,5449,5450,5451,5452,5453,5454,5455,5456,5457,5458,5459,5460,5461,5462,5463,5464,5465,5466,5467,5468,5469,5470,5471,5472,5473,5474,5475,5476,5477,5478,5479,5480,5481,5482,5483,5484,5485,5486,5487,5488,5489,5490,5491,5492,5493,5494,5495,5496,5497,5498,5499,5500,5501,5502,5503,5504,5505,5506,5507,5508,5509,5510,5511,5512,5513,5514,5515,5516,5517,5518,5519,5520,5521,5522,5523,5524,5525,5526,5527,5528,5529,5530,5531,5532,5533,5534,5535,5536,5537,5538,5539,5540,5541,5542,5543,5544,5545,5546,5547,5548,5549,5550,5551,5552,5553,5554,5555,5556,5557,5558,5559,5560,5561,5562,5563,5564,5565,5566,5567,5568,5569,5570]},"fullOrder":[882,1566,883,1567,2419,619,202,203,2786,4417,2420,4418,1568,3185,5432,1569,1128,204,2421,620,621,3686,3370,3853,622,1345,0,884,1570,4712,885,4713,2787,205,3186,3687,804,1129,3187,2422,3188,3371,4419,4420,2423,1346,1571,22,2563,3372,1487,1572,4421,1130,805,206,886,887,3688,3189,3854,4714,1573,3190,4715,4422,4716,4717,4718,1574,4423,888,4424,1575,3855,4719,2788,806,2564,5433,1576,207,623,1577,3856,1578,2565,2566,2567,3191,3373,208,4720,1579,1131,624,2568,1488,209,1132,3857,807,3858,3374,3859,1580,2424,3689,889,1581,808,4721,1582,4425,2569,2570,3192,5434,210,5435,2425,1583,3690,2789,3860,890,1584,3861,1585,1347,4350,4722,2426,1133,2790,625,1586,3193,4723,3862,4402,4724,1134,1135,4351,1348,4426,1349,1587,3691,3863,1350,891,1588,3375,1351,2791,4352,892,2792,1136,2793,1589,809,626,1352,2794,3376,4725,140,1590,4726,4727,4728,4729,1591,3864,5436,4353,1592,3377,893,2795,4403,1489,124,1137,2796,3194,3865,894,3378,1138,211,141,212,213,4730,895,4731,4732,3866,627,896,2571,4733,5357,1593,2797,23,214,2798,2427,1139,4734,142,5437,2428,897,2429,1140,1490,1491,810,4427,215,2799,216,1594,4735,3867,1595,4736,1596,1492,3195,4428,217,3379,5438,3692,3594,218,2800,898,4737,4738,899,3380,4429,4430,143,3868,219,2801,628,3381,220,1597,4431,1598,221,1493,3693,2802,3869,1599,2572,4739,4740,900,901,5439,1494,3595,811,1353,4741,1141,4432,3694,222,902,223,2803,144,629,5358,1495,630,4433,2573,1600,5359,4742,224,631,225,4743,226,1601,632,3196,4744,812,903,1602,904,905,5440,5441,5442,1354,5443,1355,1142,5444,906,1603,5445,1143,1496,227,3870,1144,4745,4746,1604,4747,24,5446,1605,2804,1606,2805,1607,2806,1356,4434,2574,4435,4748,4749,633,1145,3871,634,3197,3596,2575,2807,228,3872,635,229,5360,2808,1608,1609,1610,4750,1611,3198,1612,3597,4751,2576,3695,5361,2577,2578,4752,4753,1357,907,3696,1613,1614,1615,1358,4354,4754,2809,3598,4436,636,3382,2579,3383,3384,3599,5447,3873,3874,3875,3876,3877,3878,4437,4755,908,4756,4438,3879,4439,4757,2810,637,4758,1,2811,3697,2580,3385,1616,2812,25,2813,145,4440,1617,4759,813,5448,2430,1618,3880,3881,230,4760,909,638,4441,2431,5449,146,4761,4762,4763,2432,3386,910,1146,5450,5451,1147,1148,1149,1150,4764,1619,3882,2433,2581,3698,231,2434,232,3387,639,814,4765,1620,911,4442,4443,4444,4445,4446,3883,4447,2814,4766,1151,1621,640,4767,2582,1622,1623,4448,1497,2815,5452,2435,233,3884,4768,1624,3885,1152,1359,1625,3886,2583,3699,1626,641,4769,2816,2436,3700,147,4770,234,4449,4771,3388,235,3199,2584,2585,26,815,27,2586,1360,4772,236,1153,1361,3887,2817,237,5453,3600,3888,3889,3890,238,4773,5362,3891,1627,3601,4450,2818,3892,3389,642,239,3390,148,1154,3200,4774,4775,643,240,912,3391,241,242,5454,644,3893,1628,4776,4777,1498,28,3392,4778,1499,645,4779,2587,4780,646,647,1500,2819,913,1629,1155,2820,3393,4451,1156,29,2437,2588,3201,2589,3394,3202,3602,1630,243,4452,244,1631,3203,30,1632,1633,2438,3395,1157,4453,2439,149,3894,4781,3701,3895,1158,1634,1635,2590,4782,1159,5455,4783,3396,1636,150,3204,3397,1637,3205,1638,1639,4454,4784,1640,4785,4786,245,2821,4455,816,1641,2822,2823,1362,4787,3398,246,2591,2824,648,2592,4404,2825,3896,3897,3898,1160,3899,151,3900,247,31,152,3399,4788,1642,4456,1643,2826,3702,3206,1501,4789,4790,3207,1644,1161,3208,3603,4457,914,1645,2593,3400,3703,3901,4458,248,1646,249,1162,915,1647,1363,1648,3604,817,4459,2827,2440,5456,4791,1163,3902,3401,3903,1649,4460,3904,1650,2594,2828,4792,2829,4461,1651,4405,3402,916,1652,250,251,1502,2441,3209,1653,2595,917,2596,3905,3403,5363,252,4793,4794,153,2597,4795,1654,4796,2830,3906,1655,4797,1656,253,4462,3907,4463,4464,3908,2442,4798,2831,32,1657,2443,1503,1658,2832,5457,2,3404,803,1659,1364,4799,1660,918,1661,3210,818,3211,3704,5458,1164,4800,3212,1165,2598,3405,2599,5364,2444,649,254,255,2445,2446,919,3909,4801,4802,256,1662,257,4465,4466,1663,1664,3213,258,1665,3214,3,2447,4803,4804,1166,920,1167,921,5459,3406,3407,1168,922,259,1169,1666,4355,4805,1667,3910,154,2600,1504,260,2601,261,1668,923,3408,2602,4356,3215,3605,1669,4806,4807,3216,4467,4808,3911,4357,3912,1365,262,924,1670,925,1671,1672,2448,2449,3913,2603,926,1673,1170,4809,3606,3217,3914,5460,819,2604,2605,2606,33,3915,4358,4810,927,263,264,1674,265,1675,3218,266,267,2833,2834,4811,2835,4812,1676,928,3916,4468,2607,3917,3705,3706,3707,4813,268,4814,4815,1171,1172,4816,2608,3409,2609,4817,34,3410,1677,4818,3219,125,1678,2610,929,930,269,3411,2836,4469,3220,270,271,1679,2611,272,1680,1505,3918,3221,3919,2837,3920,2838,2839,4470,3607,1681,1682,2450,650,3222,1683,1684,35,1685,3921,931,1173,2840,3922,4819,2841,2612,2842,1686,932,1366,4820,3412,3923,933,36,4471,934,273,3413,1687,1688,4472,3924,2843,5365,1689,2844,4473,1690,274,37,1506,3708,3414,2845,3415,935,4821,2846,3416,2847,3925,4359,1367,3709,1368,1691,936,3926,1369,4822,3608,1692,5461,4474,4823,651,937,3223,1693,1694,2451,1370,4824,38,275,1695,276,1371,4825,3417,277,278,279,1696,4360,3927,280,2848,3928,1174,4826,4827,281,3929,2849,3930,4475,3710,3931,5366,3224,652,5367,4828,3932,4476,282,4406,1697,2850,3609,1175,3418,283,3933,155,2452,2851,4477,4829,3934,3935,3936,3937,1698,39,5368,3938,4830,284,1699,1700,1701,2613,1702,285,1703,4478,1176,653,3939,1704,3419,1705,3420,2852,2453,1706,4831,4479,3940,4,3225,1707,3941,4407,1507,3421,4832,1708,286,2853,1709,1710,1711,3610,4833,1712,156,2614,3711,3422,287,3942,1713,288,4834,3611,1714,157,158,820,654,3423,289,5369,655,5462,656,657,1372,2854,3943,1715,3944,1716,3612,1717,1718,1719,1720,1721,1722,938,5463,5370,1723,3226,3712,3713,658,3227,1724,40,4408,1177,3228,1725,2615,5464,3229,1178,1726,1727,4835,1728,290,3945,1729,659,2855,5465,3946,3613,3230,2616,1730,4836,1508,2454,1373,4361,939,821,3424,4837,2856,291,1731,940,4838,2857,4480,660,1732,1733,3231,4839,2617,292,2618,293,3947,1734,661,941,294,2619,1735,662,942,1736,4481,1179,3948,3425,3714,1180,4840,663,3232,5371,1737,4482,3949,5466,2858,295,1738,1181,1739,1182,1183,4362,943,4841,4842,3950,2859,3951,3715,3952,3953,3954,4483,4843,2860,944,3233,3234,41,1740,1741,3955,5467,5468,1742,1374,1743,945,4484,1509,1184,4485,4844,3956,3957,664,4845,2455,1744,3958,2861,665,666,296,3959,4363,3960,2862,297,2863,946,1185,3961,298,1745,3962,1746,1747,1375,1748,4846,2864,299,159,3426,3427,4486,3428,1376,947,300,160,1186,1187,1749,42,3429,2456,822,1377,4847,1188,3963,948,5469,5470,1378,4848,2865,3430,3431,43,2866,3964,4364,1750,5471,1751,3614,1752,1379,2620,1753,823,1754,301,1755,1756,1757,3615,302,2457,3432,824,303,304,1189,1758,1759,1760,5472,1761,4849,4850,4487,2458,2621,3235,305,2622,306,3965,1762,1763,1380,2623,1764,1765,1766,2867,1767,1381,1768,2868,1769,1770,3966,1771,2869,307,1772,3967,44,3968,1773,308,2870,3616,4851,309,4488,1774,1775,667,2624,1510,310,1776,2871,1777,4852,1190,1778,3969,3970,2872,3716,1779,4489,3717,311,3433,4853,4490,1780,1781,3971,1511,2873,1782,1783,1784,949,1785,1786,4491,3434,3236,312,3237,1512,950,951,4854,2874,4365,4492,45,4855,4856,4366,1513,313,4857,3972,1382,1787,5473,3973,1514,2625,46,668,669,4858,314,4493,1788,315,3974,1789,4859,3975,3976,5474,3435,1790,952,1791,953,1792,5372,3436,316,954,5475,670,955,1793,671,3977,317,2626,2875,4860,3978,4861,1794,2876,2877,5,2878,3979,3718,1795,2879,4862,2627,1383,2628,2629,2630,4367,956,3238,2459,5373,4863,4494,4495,1796,3239,318,3437,2460,2880,4496,2881,3438,3719,2631,1797,3439,2632,2461,3440,2462,2463,1191,1384,1798,3240,126,957,2633,958,5476,319,1799,3980,959,1192,1800,1801,47,1802,3441,1385,1515,672,3981,4864,4497,1803,2634,1804,1805,3982,4865,2635,2882,2883,2884,1806,1386,5477,320,3983,1807,1808,4498,960,4866,3442,5374,1809,1810,1811,825,4867,1812,1813,961,5478,1814,1815,1816,4868,4869,3984,3985,1516,5479,3986,48,2885,4870,1387,321,1817,1818,2464,3443,3987,3444,1819,322,3988,1193,3989,1820,1821,826,3445,4499,1822,3990,2636,1823,1824,1825,827,1826,1827,3241,1517,2886,4871,1828,1518,2887,3991,4500,3992,3720,2888,962,4872,4873,3617,2637,5480,4874,1194,3618,1829,4875,828,963,964,161,1519,4876,2465,3993,3446,4877,3447,4878,323,1830,2638,4879,4880,4881,4882,3994,3721,324,3995,2889,2890,1831,4883,1832,3619,3996,1833,325,4501,1834,2891,3997,3998,162,6,3722,3999,4000,673,326,4502,4001,4002,4003,4503,1835,3242,4004,1836,1837,2639,4005,2892,3448,5481,1195,2893,4368,1838,3723,1839,4884,4885,327,4006,4007,5375,4008,4009,1840,4886,1196,4010,4887,1841,49,1842,965,4888,1843,4011,328,4889,4012,1844,329,674,1845,1846,3724,3243,2640,4013,966,1847,1848,675,2466,2894,4014,4890,3449,330,5482,1520,2895,4015,4504,4016,967,2896,4017,7,331,332,50,3244,5376,1197,1849,3725,1850,1851,4018,51,1388,2897,2898,1852,3245,1198,3726,4891,4892,4893,4894,127,3246,1853,1854,2899,1521,5483,1389,333,5484,334,968,52,2900,4505,4895,2901,3727,4896,3247,4019,969,3450,2902,3248,335,2467,3451,1855,2903,3452,4020,4506,2904,4897,4898,163,4021,1856,4022,970,1199,2905,336,4507,971,1857,5485,4023,676,4508,677,1858,1200,4024,678,1201,1859,2906,2907,4509,4899,3453,2908,3454,1860,2909,3728,1861,3455,4900,1862,3456,1863,4901,679,4025,1864,1865,1866,2641,3249,5377,4510,1867,1868,3457,1869,1870,3729,829,1871,4902,2642,4903,1872,3730,4511,3250,972,1873,337,3251,5378,4904,4026,4512,2468,4027,4513,4514,4905,1390,4028,338,4906,3458,4029,1391,2910,5379,4907,680,4030,339,4908,4031,3459,53,4032,1874,4909,340,1392,1522,3252,4033,1202,2911,1875,3253,1876,973,974,975,2469,976,3731,977,5486,978,5487,979,2912,2913,1877,1203,341,1878,1879,980,1204,4515,3732,1205,1206,4369,830,1207,342,1208,1209,1880,681,1210,5380,1211,4034,4035,4036,2914,3254,682,683,1881,4516,3255,4037,4517,684,3733,1882,4038,4518,831,3460,4039,4910,4911,2915,4912,2916,685,164,4370,343,3734,2917,344,1883,1884,4913,4914,3620,2918,981,4040,2919,4915,2643,4916,2920,4917,1885,4519,686,1886,5488,982,687,4520,1887,1888,4918,4041,983,2921,4919,1393,832,2922,2923,1889,4920,4921,345,4922,2924,1890,4923,4924,3461,984,4925,4521,4926,4522,4927,1891,1523,1892,1212,1893,1394,1894,1895,2644,2645,2470,5489,4928,4042,985,1896,346,4929,4043,4523,4044,688,986,987,4930,2925,689,4045,4931,3462,4046,165,4047,1213,4932,988,4933,347,1897,4934,3256,2926,4048,690,4935,54,833,2927,1898,1899,4049,1900,4524,691,2646,348,349,4525,350,351,692,3257,352,353,2928,354,4936,1901,1902,834,4050,3258,4526,355,356,4051,4937,357,1903,4052,358,4938,835,359,1904,1905,4939,360,693,4527,1906,2929,1214,4940,361,694,836,3735,4941,55,362,4942,2647,4943,1907,1215,1216,2471,2472,3259,4944,1908,363,56,4053,3621,364,4945,2930,3260,1909,1524,695,2931,1910,4054,4946,5381,3261,3463,4947,4948,365,4528,1911,4055,2648,4529,2932,4056,1912,4530,2933,4531,4057,1217,2934,989,2935,3262,1913,1914,4532,4949,696,4058,4950,1915,2936,4951,990,5382,1395,2649,1916,3263,4059,366,2473,57,1917,1918,3464,991,1919,1525,4952,4533,1920,992,1921,3736,697,1922,698,4953,4060,367,4954,4955,1923,368,4956,4534,369,2937,993,1396,3465,4061,166,2474,3264,994,2938,4535,4957,699,4958,4536,3265,3737,700,5490,1924,4537,370,701,4409,2939,4959,4538,4062,1925,371,372,167,4539,4960,4961,373,374,2940,4540,702,375,2941,4541,2475,837,3466,995,4542,4063,2650,5383,5384,376,4962,377,996,5385,1926,1927,1928,3622,378,5491,1929,1930,379,168,3266,4064,380,381,382,383,838,384,3623,2942,1931,997,998,5492,4963,3267,703,3467,4543,1218,1932,2943,704,2476,999,3738,4544,4964,4965,385,1933,386,3624,387,1934,169,1935,388,1936,2944,389,2945,3268,1937,1938,1939,390,4966,1940,1397,391,1941,1942,4967,3625,1000,1943,705,392,393,394,1944,4968,1219,2946,4545,839,2947,3626,3269,395,4969,1945,4970,4971,396,706,4972,170,4546,1001,4973,5493,3270,397,707,4547,4974,1526,5494,2651,4975,5386,2652,4371,4065,4976,4977,1002,4978,398,4066,1527,3271,840,399,4979,708,4980,1003,4067,3627,1946,4981,4068,400,4982,709,2653,3739,1947,1398,128,1004,3468,1948,2948,1949,1950,1220,1399,4983,4984,401,402,4985,403,4986,404,405,1951,1952,1005,1953,4987,2477,4548,1954,1955,4988,406,841,2949,2950,2951,2952,1528,1006,4069,4070,3272,4549,407,4989,2953,4071,4990,1956,3740,408,2654,58,2478,4991,2954,4992,1400,1957,4550,409,3469,1958,59,4072,2479,4993,1959,4073,2955,410,1960,4074,411,842,710,4075,2956,711,712,412,4994,713,4551,1961,3470,4995,4996,1962,1963,1007,2957,413,3741,4997,3742,1401,2958,1964,3743,1965,60,5387,3628,3744,2959,5388,1966,1529,171,2960,3273,4076,1008,4552,1530,61,714,1531,2961,3745,3746,3471,3747,2962,4553,4998,4077,4999,4372,1009,2963,3274,1532,715,1221,3275,3472,5000,5495,1010,1402,1967,1968,1222,1969,62,414,1970,1971,1972,415,2655,5001,843,3473,1973,2964,1011,4373,716,416,417,4554,1974,1975,5002,3276,3748,3474,3749,418,1223,1976,844,2656,1977,5003,1978,63,3277,3475,2965,2657,3476,4078,4555,1979,8,4556,5004,3750,3477,1980,1981,1224,1982,1012,1403,2658,5496,1983,2659,419,717,3478,718,3278,420,3751,1404,1984,3479,4079,5005,5006,1225,2660,64,3752,5007,2966,65,5008,3279,4557,5009,5010,1985,2967,3280,3480,2661,2662,172,1986,1405,2480,1406,421,1013,2968,422,423,173,1533,1987,2969,174,4558,1988,1534,424,1989,5389,4559,1226,1227,1228,1229,2663,3481,4080,3753,66,5497,1990,2664,3281,3754,3482,3755,3483,3282,1230,3283,3484,3485,5498,3284,1991,4081,1992,1993,1994,3285,1231,3756,425,3757,1014,1995,2665,4082,4083,5011,3486,4560,1535,426,3629,4084,5499,4085,4561,1232,427,428,3286,429,3758,3759,1996,430,1997,1407,1998,3487,2970,431,845,1999,2971,129,5012,5390,2972,2000,2666,4562,432,4563,5500,5013,2001,719,4086,5014,2002,4564,5015,2003,433,5016,4565,2004,1015,2973,4087,2005,434,2974,1233,2006,5017,2007,3287,67,2481,720,2975,5018,4566,4088,4089,846,5019,2667,435,5501,2976,2977,2668,2978,2008,4567,5020,1234,5021,5022,1408,5023,2669,5024,1409,3760,5025,3488,1235,436,3761,2009,2010,4568,2979,5026,2011,2980,5027,2981,5028,2012,4569,1016,3489,5502,3630,3762,437,4090,5391,130,3288,438,5029,3763,5030,439,5031,68,2013,4091,4374,2014,3289,4570,3631,440,721,3490,441,2015,2670,2482,442,4571,2483,1236,5032,3632,443,444,5033,5034,1017,4572,69,3764,4573,2016,445,446,5392,5393,2982,2671,2672,1018,2983,2017,4092,175,2673,176,3290,177,9,2984,2985,2986,5035,2987,2018,3633,2988,2019,2020,178,3491,2989,10,4093,447,448,2021,847,4094,2022,70,1019,179,2484,5036,1237,5037,4574,1536,2485,722,449,71,450,3291,1238,723,1239,2486,5038,4095,848,4096,451,72,4575,2023,2674,1410,4097,3765,452,724,3492,3493,2990,73,849,11,4576,2675,2024,2991,2992,2025,4098,4099,5503,5039,74,3634,2026,850,2993,2994,5040,2995,2996,5041,2027,2997,2998,2028,2487,2676,2029,2999,2030,4100,3000,2031,725,5042,3766,2032,5394,3001,1020,453,726,3494,2677,4577,4101,454,75,1240,2033,5043,2678,5504,3002,2034,2035,2036,2037,2038,3495,455,1241,2679,3003,2039,4102,2680,4103,4104,3004,2040,1242,1243,4578,2041,1021,76,1411,2681,2042,5044,3005,180,1022,5505,727,3767,4105,131,2043,456,3006,2488,2044,4579,2489,3635,2045,5045,3007,2046,5046,728,5047,2047,3636,77,3768,3496,457,3497,3637,5048,458,729,1244,730,3498,1023,851,1024,78,4106,2048,2049,1025,5049,4375,5050,2050,5051,3638,5506,1245,3008,2051,4107,2052,731,1537,1246,3292,5052,459,5507,460,4376,5053,3009,5054,1412,5055,2053,4580,1247,3010,732,2490,5056,4581,2054,2055,2682,5057,5058,5059,1026,5395,2491,2492,733,5060,1248,5061,4582,5062,2056,3499,3500,2057,734,2683,2058,852,3769,4108,2493,3770,1027,2059,5396,3501,5063,4109,5064,5065,2060,5066,2061,4110,4583,2062,4584,5067,3771,5508,2063,2684,5068,4377,461,2064,5509,2065,2685,5069,79,4111,1249,2066,1028,2067,1029,1030,735,2068,736,3293,3011,3294,4112,462,3012,737,1031,4113,5070,1032,3502,4585,2069,463,3503,2070,4586,4114,4115,1250,464,5071,1033,3772,4116,5072,1034,2494,4410,738,465,4117,466,853,4118,4119,739,2686,467,468,1035,1538,2071,3013,469,854,470,855,2072,5397,80,3504,5510,471,5073,472,2073,1036,2074,2075,5074,2076,4120,2077,5075,3773,2078,2079,3639,5511,5076,2687,4587,1539,473,5512,3295,3505,5077,2080,2688,3506,1037,5398,2081,1038,5078,181,5079,4121,474,3640,1251,2082,1540,5080,1039,3774,3641,1413,4122,475,4411,1414,5399,5400,5401,3014,5402,3507,1415,5403,3508,5081,3015,4123,1541,1040,3016,1542,4124,1041,3017,1416,4125,2083,4126,1417,4378,4127,5082,476,1418,5083,4128,3018,5084,1252,1042,3775,2084,4588,3019,2495,3020,4129,5085,477,3021,2689,3642,1043,5086,1419,5087,4130,478,3643,1044,5088,1253,2496,4589,479,1420,3022,2085,3023,5089,4379,1421,1422,2086,1423,1424,1425,5090,1426,3024,740,2690,5513,1254,182,4131,4132,2691,4133,2087,2088,4134,3025,4135,480,2089,1045,4136,5514,741,3026,1427,3509,4137,3027,2090,481,3028,2497,4590,1428,2091,4380,856,1046,4591,482,1429,5091,5515,183,5516,184,4138,1047,4139,2092,1048,4140,483,4592,5092,1430,4381,1543,3029,5517,81,4141,1431,742,2093,3510,1049,2498,2499,1432,3511,1433,4142,484,4143,2094,5093,2500,743,5094,3512,2501,132,2095,5095,2692,1255,82,3776,83,3513,84,2096,5096,2097,3296,1256,485,2693,2098,5518,486,2099,85,2100,5097,2101,5098,5099,2502,2102,1050,5100,4593,3297,3298,744,3030,5101,5102,4144,5103,4594,2503,487,3299,2504,5104,3031,4595,86,2103,3777,2104,2105,4382,2694,4596,5105,1051,2106,3032,5106,488,1052,5107,2505,745,4412,746,5404,1257,747,748,1053,2107,3514,2108,3515,2109,4597,3033,4145,2110,4598,2111,2112,3516,87,5108,1054,2506,749,4599,2113,4600,750,3300,4146,5109,3034,5519,489,3035,4601,5110,4147,3517,88,3518,1258,5520,490,1055,5521,3301,5522,1056,1057,3036,5111,4148,4602,2114,3037,1058,4149,857,3302,5112,4150,89,2115,4603,3519,2116,3644,2117,751,2507,2118,5113,4151,3645,1259,5114,752,4604,5115,1544,3038,4152,5523,2119,753,491,754,3778,5524,3039,3040,1545,1059,1434,5116,3041,5117,3303,1435,3042,1546,2120,5118,2695,492,3646,3779,2508,1060,3780,5119,4153,4383,3781,90,185,493,91,5120,5121,3520,3521,3304,3782,1260,4154,3783,2121,4155,2122,2123,2124,2696,3784,1261,3522,3305,92,4605,4156,4157,2125,4606,1262,2126,3043,3044,2697,2127,3523,2128,2129,5122,3785,3647,494,2509,5525,3524,3786,3306,186,2130,3045,5123,5124,1263,2698,3307,3525,5125,2131,495,4158,5126,3046,93,4607,1264,2132,4159,3526,496,3047,2133,5127,3308,2134,5128,2135,755,2699,133,2136,2137,2138,3787,2700,5405,1436,3788,2139,5129,497,4160,2701,2140,4608,5130,5131,1265,5406,5132,2141,5526,498,3789,858,5133,1266,1547,3527,3528,2142,4161,2702,2143,3790,5527,2510,1437,4162,4163,756,1267,5134,3791,94,4609,757,2144,2145,5528,2146,2147,2148,5135,5136,758,1268,2149,4610,1269,3048,3049,3050,1061,5137,2150,4611,3309,3310,4612,3311,1062,3648,95,5138,2703,499,2151,4164,2511,3529,2704,5139,2152,2153,2154,2155,3051,500,96,2705,1063,5140,2706,3792,2707,2156,4384,3530,4385,501,5141,1270,97,502,5142,5529,759,2157,3052,4165,4166,3053,4167,3054,4613,5143,3055,5407,3649,4168,1271,4169,4614,859,503,4170,2158,3531,1272,5144,760,5145,5146,1064,2159,5147,3532,3650,504,3056,5148,2160,5149,5408,2161,5150,2162,2163,98,1065,1273,2164,4171,2165,5151,5152,3057,5530,5153,4172,5154,4615,2166,1066,1067,761,505,3533,506,2708,3058,3059,5155,2167,2709,5531,860,2168,2512,12,1068,3060,507,508,3061,4173,5156,4616,1438,2169,5157,5158,3312,1274,2710,3793,2711,4174,99,2712,2170,5409,5410,509,1439,2171,2172,510,5159,2713,3313,4617,5160,2173,5161,2513,3062,1548,5162,1440,3063,1069,5163,4175,4618,5532,4619,5533,1441,2174,4176,4620,1442,5164,861,2175,2176,511,5165,762,5166,1070,3651,3064,3794,4177,1071,763,2177,2514,1072,3534,13,4178,1443,3535,5534,3065,3066,4621,100,5411,2515,101,3795,1444,1445,1446,5167,5168,2178,1275,134,4179,4180,1549,5535,3652,102,3067,1276,512,4622,4386,4181,3068,14,4182,1073,2179,764,5169,513,5170,765,2180,2181,4183,4623,1447,5171,135,514,3069,5172,2182,4624,5173,5536,2516,3070,2183,2714,3536,5174,2184,2185,5175,2186,5176,4625,3071,515,1277,5177,187,4626,516,1278,2187,862,5537,2188,4184,1279,4387,4627,2189,5178,1280,517,1281,5179,2517,3314,4388,1448,1282,3072,4628,2715,1074,4185,5180,5412,4186,2190,3073,5538,3796,4187,2716,5181,4188,2191,3074,5182,3075,2518,3653,3076,4189,3077,103,3078,3537,518,2717,3654,5183,5184,2192,1449,3079,4190,519,4629,3080,5185,4191,3315,1075,3655,3081,766,2718,3316,520,767,768,769,770,3797,3798,521,5186,3082,5187,3083,3084,4630,1283,2193,2194,3085,3086,3317,2195,5539,771,2519,5188,3538,4192,2196,3539,5189,5190,5191,4193,522,2719,3087,772,3656,2197,3088,1450,3089,2198,2199,5192,4194,523,1284,2720,524,2721,5413,525,2722,2200,5540,3799,3318,526,3800,2723,2724,2201,3540,3801,5414,1076,1077,1285,1550,5193,527,3541,528,3319,5194,5195,1451,3090,5196,2202,529,3091,5197,5198,5199,5200,5201,2203,1452,3542,5415,5202,5203,5204,2204,3092,863,3093,3657,3094,15,1453,3095,3096,1551,2205,3658,5205,4389,5541,4631,3659,3660,5206,530,3661,531,4632,3802,4633,532,2206,4634,2207,5542,4635,4195,2208,3320,4636,4196,5207,3543,104,2209,2520,4637,1552,3097,2210,864,2211,4197,2212,2213,2214,2215,188,1078,533,4638,5543,2725,1079,1553,2216,5208,4198,4639,2217,5209,4199,1554,2218,4640,4200,2219,534,3803,16,4201,3098,4202,4390,2220,4641,3099,4203,4204,1454,3100,2521,1455,4205,4413,5210,1286,2221,5416,3101,4206,1456,5211,105,2222,5212,1080,2223,5213,2522,773,535,3804,2224,3102,5214,2225,774,2226,4207,5215,3321,4208,5216,5217,5218,4642,2726,3322,5417,2727,3103,3323,2227,536,2523,775,5219,3324,4643,5220,5221,2228,5222,1457,3104,4209,3105,5223,4644,537,4210,4211,2524,1287,5544,4212,1081,5545,5224,4645,3325,4213,5225,5226,3106,538,2229,5227,1082,2230,2231,2525,4214,2232,5228,539,1458,2728,4646,3107,4215,5229,4216,2729,3326,3805,540,3327,5230,5231,541,5232,1083,2233,3108,2234,2526,3328,2235,3544,5233,4217,1459,3545,2236,5234,3109,1084,2237,5546,5235,3329,3546,1288,5236,1289,2730,3110,4647,1085,2238,542,1290,2731,3111,1086,5237,3112,189,3113,2527,2239,865,3114,5238,3547,543,1291,2240,2732,4391,5418,106,2528,1292,2241,4218,3806,4219,3330,5239,544,2529,2242,866,3331,4220,3115,2530,2243,2244,5547,3662,3116,5240,3117,776,1293,1294,2733,5241,2245,545,2246,2247,2248,1087,2249,1088,1555,5242,2250,5548,1460,4221,2251,1089,4648,5419,5243,3548,17,4649,5549,5244,867,2734,4222,1090,3118,5550,546,1461,3332,4650,1091,3119,4651,5551,2252,4223,547,136,548,4224,5245,2253,2254,2735,5246,2255,777,2531,778,2256,2257,107,3120,2258,2259,1295,3807,108,2260,3549,2261,5420,3808,2736,2262,549,2532,2533,4225,4652,1462,550,4653,5421,1296,5247,2737,5248,4226,3809,5249,1092,4227,3121,4228,1093,551,1463,3550,3663,5250,2263,5251,2264,3122,1094,2265,190,2266,2267,5252,1464,2268,4229,3123,5253,4230,2269,2270,3124,2534,1297,3551,4231,4232,552,5254,4233,2271,3125,3552,5255,5256,2272,779,1298,3333,2738,1299,2739,2273,3810,5257,4654,5552,3811,3334,4655,1300,5258,4656,4234,109,2274,3553,2535,5259,3335,4657,5260,3126,5422,4658,553,554,1095,2740,4659,5423,2275,2536,1301,2537,2741,1302,868,2276,4235,555,4392,556,1303,2277,1465,557,3554,5553,2538,3812,3664,2278,2742,5261,5424,4236,3555,1096,3665,2279,4237,2280,1304,558,2281,4393,1305,3813,2539,3556,4660,559,4238,191,869,1556,2282,2283,2540,2284,3666,2285,780,3814,3557,2286,3558,2287,2288,2289,560,2290,4239,3127,3128,3336,1306,4661,2291,1097,4414,3667,5262,3559,3560,2292,2293,1098,2541,2294,3561,4240,3562,5263,2295,5264,3668,2542,2296,2543,3563,3129,2743,1307,4662,3130,781,2297,2298,4663,2299,2300,1308,2301,5265,3564,4241,2744,3815,1309,4664,2745,3131,1310,2302,2303,4665,5266,2304,3337,4242,3132,3133,3134,4666,2305,5267,3135,3338,2746,110,2306,2307,111,2308,561,4243,3136,2747,2748,3816,2749,2750,1311,3669,2309,5268,3339,2751,2752,870,3817,4667,4668,2310,3565,3340,2311,4244,4245,4246,562,2312,2313,4247,4248,3566,3567,1466,1467,5269,5270,2753,3818,4249,3670,1468,4250,1312,5271,2754,3137,1469,2755,3568,4251,2314,3341,5272,4669,3569,4252,4670,1313,1099,782,3570,112,1314,4415,1100,5273,4253,2756,3138,5274,4254,4255,4671,4256,871,1315,3139,3819,5275,3571,4672,563,4257,2757,5425,2315,1101,3572,3820,2544,4394,3140,4673,1102,3573,5554,113,114,4258,1103,5276,4259,192,3821,3822,5277,1316,3671,1470,4260,2316,4261,4674,4262,3141,3142,3143,3574,2317,4263,5278,1317,2318,3823,1318,1319,3575,1320,2319,5279,2320,872,5555,115,5280,3144,2321,2545,5281,2322,2758,3672,2323,4264,2324,2325,2326,564,2327,2328,5556,193,2759,4265,1104,5282,2329,2330,3145,3824,2331,4266,4267,5557,4268,4269,3825,5283,2332,2760,4270,1321,3342,2761,565,1471,4271,3146,2333,2546,3673,4272,3674,3147,4273,5284,2334,5285,2335,566,116,1322,567,3148,4675,568,4676,569,4677,5286,3576,570,3577,4274,4275,4276,4277,1557,2336,18,1323,2337,1105,2338,3826,2339,3827,19,2340,2547,1324,2341,783,117,784,4278,3149,571,2342,2343,2344,4279,572,4280,2345,4395,4281,2346,3675,873,4678,5287,2347,2762,3828,2763,2348,3829,3830,137,573,2349,2350,574,2764,5288,3831,1472,575,2765,3343,5289,2351,1325,1106,2352,3150,2353,2766,576,3832,3833,3344,2354,577,3151,3345,3152,4282,4283,2767,5290,5291,4284,2355,1558,2356,4285,3834,5292,4679,1559,3578,3676,1107,5558,4286,2357,5293,194,2358,5426,2359,3579,578,1108,2360,3580,4287,1473,3153,3346,5427,1109,579,580,1326,3835,5559,581,4288,2768,785,2361,5294,3581,2769,2770,4289,2362,3347,786,4680,1560,874,5295,1474,2771,2548,2772,582,5560,1327,1328,5296,4681,3154,5297,2773,3677,3348,3582,5298,5299,4290,1475,5300,195,5301,3349,5302,5561,583,3836,2363,787,3350,3351,5303,2774,1561,5304,5562,5305,2549,4682,2364,5563,3837,5306,5564,3352,3155,5307,3156,788,3583,5308,3838,4683,1476,3678,584,118,3584,585,586,2365,196,3157,4291,4292,587,2775,4293,2366,3158,2367,5309,588,5310,1477,4294,2368,5311,1110,119,4295,5312,3353,5313,5314,4296,1562,5315,20,789,138,5316,2369,1329,5317,790,5318,2776,4297,197,2777,589,3159,2370,4396,791,5319,3160,5428,3839,3840,4298,2778,590,5320,591,2371,592,120,1563,3585,1111,3679,3354,1112,2550,3161,4299,593,3355,1478,3162,3163,5321,2551,1479,4300,4397,792,3164,3841,3842,5322,4684,4685,3165,3356,3843,4686,1330,4687,4688,5323,1331,2372,4301,2373,4302,2374,5429,5565,5566,2375,2376,2377,3166,5430,3167,2378,2552,198,3357,1480,4303,5324,4304,5325,3844,5326,2553,3358,121,2554,793,3680,4305,4306,594,5327,4307,4689,3168,4308,2379,4309,4310,4311,5328,1564,2380,4312,4313,2381,1113,3681,4690,4691,4692,1114,3359,4314,2779,3360,4315,3845,1332,1115,4693,4694,595,2555,4316,2556,1333,5329,2382,4695,4317,3169,3170,1334,5330,2383,3361,4318,4319,4320,4321,3362,3171,5331,5567,5568,1335,1336,5332,2384,5333,4322,794,1116,1117,3172,4696,2385,1337,199,596,2386,2387,597,598,795,2388,5334,599,5335,2389,2390,5336,3173,4323,5337,600,4416,1118,2780,2557,796,3846,5431,601,2391,2781,797,3174,602,2392,3586,4324,3175,2393,4697,1481,122,5338,3176,4325,3847,3177,603,5339,1338,5340,1119,1120,2394,2558,4698,798,2395,200,604,3587,2396,201,4326,799,4398,4699,5341,4700,1121,605,4327,1482,4399,4400,4328,4329,4330,606,3682,3588,607,5342,5343,5344,1122,4331,4701,4702,5345,2397,875,2398,4703,1339,2399,5346,5347,2400,1123,2401,800,3683,2782,3848,801,3589,2402,608,609,1483,3590,610,5348,611,2403,3684,2404,4332,876,3849,3178,3363,1484,612,3850,4333,5349,3179,3591,4334,3364,2405,3180,613,2406,2407,2408,3365,3366,2409,4335,4336,4337,877,1340,1124,3367,4338,1565,1125,123,2410,3851,802,4339,4704,4705,2411,2783,2559,1485,1126,3852,4340,4341,4342,3592,4343,1341,878,1127,1486,879,880,4401,5350,5351,2412,2413,2414,2415,3181,2416,2560,4344,5352,4345,4346,2784,4706,881,5353,614,4347,3368,139,1342,2561,3182,1343,2417,3685,5354,5355,615,3593,5569,616,2418,3183,617,4348,4707,5570,3184,4349,4708,21,4709,4710,3369,2562,618,2785,5356,1344,4711]} diff --git a/spec/bridge/source/municipalities.ts b/spec/bridge/source/municipalities.ts new file mode 100644 index 000000000..7bd82268b --- /dev/null +++ b/spec/bridge/source/municipalities.ts @@ -0,0 +1,109 @@ +/** + * Brazilian municipalities, written once. + */ +import { type Dataset, dataAll, dataRows, dataset } from "./_std.ts"; + +/** + * The two letter code of a Brazilian state. Checked against the dataset by `data/build.ts`, so + * the union and the table can never drift apart. + */ +export type StateCode = + | "AC" + | "AL" + | "AP" + | "AM" + | "BA" + | "CE" + | "DF" + | "ES" + | "GO" + | "MA" + | "MT" + | "MS" + | "MG" + | "PA" + | "PB" + | "PR" + | "PE" + | "PI" + | "RJ" + | "RN" + | "RS" + | "RO" + | "RR" + | "SC" + | "SP" + | "SE" + | "TO"; + +/** One Brazilian municipality, as the IBGE publishes it. */ +export type Municipality = { + /** The 7-digit IBGE municipality code. */ + code: string; + /** The municipality name. */ + name: string; + /** The two-letter code of the state the municipality belongs to. */ + stateCode: StateCode; +}; + +/** + * The municipalities table: `[stateCode, name, code]` per row, grouped by state, with the + * combined pt-BR order baked in at build time. + */ +const MUNICIPALITIES: Dataset = dataset("municipalities"); + +/** + * Reads one dataset row as a municipality. + * + * @param {string[]} row - The `[stateCode, name, code]` row. + * @returns {Municipality} The municipality. + */ +const rowToMunicipality = (row: string[]): Municipality => ({ + code: row[2], + name: row[1], + stateCode: row[0], +}); + +/** + * Returns Brazilian municipalities published by the IBGE, optionally filtered by state. + * + * If `stateCode` is provided, only municipalities of that state are returned. If it is + * omitted, every municipality of every state is returned, sorted with `localeCompare` in the + * "pt-BR" locale so accented names land where a Brazilian reader expects them. Every per-state + * list is sorted the same way. + * + * Only an omitted (or `undefined`) `stateCode` asks for the full list: any other value that is + * not a known state code, `null` and `""` included, returns `[]`. + * + * The state code is matched exactly, case included: `getMunicipalities("sp")` returns `[]` where + * `getMunicipalities("SP")` returns the 645 São Paulo municipalities. + * + * @param {StateCode} [stateCode] - The two letter code of the Brazilian state to filter by. + * @returns {Municipality[]} A fresh array of fresh `Municipality` objects. Empty when + * `stateCode` is not a known state. + * + * @example + * ```typescript + * getMunicipalities("SP")[0]; // { code: "3500105", name: "Adamantina", stateCode: "SP" } + * getMunicipalities().length; // every municipality of every state + * getMunicipalities("ZZ"); // [] + * getMunicipalities("sp"); // [] (the state code is case-sensitive here) + * getMunicipalities(null); // [] (only an omitted state code asks for the full list) + * ``` + * + * @see Official: https://servicodados.ibge.gov.br/api/docs/localidades + */ +export const getMunicipalities = (stateCode?: StateCode): Municipality[] => { + const municipalities: Municipality[] = []; + let rows = dataAll(MUNICIPALITIES); + + if (stateCode !== undefined) { + rows = dataRows(MUNICIPALITIES, stateCode); + } + + for (const row of rows) { + municipalities.push(rowToMunicipality(row)); + } + + return municipalities; +}; From a17cc4734c63e6c49c45677bb0420089b96c2e93 Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 21 Sep 2026 02:34:10 +0000 Subject: [PATCH 04/13] feat(spec): bridge the async, HTTP and error-handling utility too MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds `getAddressInfoByCep` to `spec/bridge`, which completes the POC: the four utilities it now covers use, between them, every hard thing a Brazilian Utils function does — regular expressions, a 5,571 row dataset with a pt-BR collation order, HTTP with retries, JSON, an error hierarchy, and three providers raced against each other. The source stays straight-line, synchronous TypeScript. Three things are now the emitter's job rather than the author's: - `async` is inferred. The compiler works out which functions wait on the network and colours the call graph per target: TypeScript and C# get async/await and a Promise/Task return, while Go, Rust, Ruby, Java and Python stay blocking. - Raising is translated. `throw new GetAddressInfoByCepNotFoundError(…)` becomes a real exception class in five targets, `(T, error)` threaded through every call site in Go, and `Result` in Rust. The declared error hierarchy survives in all seven. - Concurrency is one primitive. `startAll` becomes promises, Tasks, goroutines with a channel, threads with an mpsc channel, virtual threads, or threads with a queue, depending on the target. Parity, all recorded from the package this repository ships: - The package's own vitest suites pass against the generated TypeScript: 4 files, 157 tests, the type level assertions and the CEP error class hierarchy included. - `conformance/run-all.sh` replays the CNPJ vectors, an 11,176 line municipality dump and 110 CEP scenarios through all seven targets. The CEP scenarios are served over real HTTP by the same table that recorded them, so Go, Rust, Java, C#, Ruby and Python exercise their own HTTP clients, JSON readers and schedulers rather than a stub. - All seven match. The only skips are inputs with no form in a statically typed language — a `string | number` union, and a `providers: null` that Python and Ruby cannot tell from an absent one. Both are listed in the README. `spec/bridge/README.md` documents the accepted subset, the three things that would otherwise differ between hosts, and every known gap. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01UX1gTGeMTyoXQyr1qUoQKd --- spec/bridge/.gitignore | 1 + spec/bridge/README.md | 189 +++++++++ spec/bridge/compiler/cli.ts | 3 +- spec/bridge/compiler/frontend.ts | 395 +++++++++++++++--- spec/bridge/compiler/ir.ts | 46 ++- spec/bridge/compiler/kit.ts | 73 ++-- spec/bridge/compiler/regex.ts | 32 +- spec/bridge/compiler/runtime/csharp.cs | 312 +++++++++++++- spec/bridge/compiler/runtime/go.go | 267 +++++++++++- spec/bridge/compiler/runtime/java.java | 454 ++++++++++++++++++++- spec/bridge/compiler/runtime/python.py | 165 ++++++++ spec/bridge/compiler/runtime/ruby.rb | 156 +++++++ spec/bridge/compiler/runtime/rust.rs | 233 +++++++++++ spec/bridge/compiler/runtime/typescript.ts | 275 +++++++++++++ spec/bridge/compiler/targets/csharp.ts | 306 ++++++++++---- spec/bridge/compiler/targets/go.ts | 308 ++++++++++---- spec/bridge/compiler/targets/java.ts | 313 +++++++++----- spec/bridge/compiler/targets/python.ts | 235 ++++++++--- spec/bridge/compiler/targets/ruby.ts | 191 ++++++--- spec/bridge/compiler/targets/rust.ts | 320 +++++++++++---- spec/bridge/compiler/targets/typescript.ts | 337 ++++++++++----- spec/bridge/conformance/cep.ts | 337 +++++++++++++++ spec/bridge/conformance/drivers.ts | 398 +++++++++++++++++- spec/bridge/conformance/municipalities.ts | 5 +- spec/bridge/conformance/run-all.sh | 21 +- spec/bridge/conformance/vectors.ts | 10 +- spec/bridge/data/build.ts | 1 + spec/bridge/package.json | 4 +- spec/bridge/source/_std.ts | 177 +++++++- spec/bridge/source/cep.ts | 318 +++++++++++++++ spec/bridge/source/cnpj.ts | 12 +- spec/bridge/source/municipalities.ts | 3 +- vite.config.ts | 52 ++- 33 files changed, 5227 insertions(+), 722 deletions(-) create mode 100644 spec/bridge/README.md create mode 100644 spec/bridge/conformance/cep.ts create mode 100644 spec/bridge/source/cep.ts diff --git a/spec/bridge/.gitignore b/spec/bridge/.gitignore index 322f30470..b1bcb15a2 100644 --- a/spec/bridge/.gitignore +++ b/spec/bridge/.gitignore @@ -10,3 +10,4 @@ conformance/vectors.json conformance/vectors.tsv conformance/municipalities.expected.txt conformance/municipalities.keys.txt +conformance/cep.expected.tsv diff --git a/spec/bridge/README.md b/spec/bridge/README.md new file mode 100644 index 000000000..40e6e1f63 --- /dev/null +++ b/spec/bridge/README.md @@ -0,0 +1,189 @@ +# The bridge: write a utility once, ship it in seven languages + +`spec/bridge` is a compiler. You write a utility once, in ordinary TypeScript, under +[`source/`](source). It emits idiomatic native code for **TypeScript, Python, Go, Rust, Ruby, +Java and C#** — no bindings, no embedded VM, no FFI, and nothing hand-written per language. + +Three utilities are ported so far, chosen because between them they use everything hard: + +| utility | what makes it hard | +| --------------------------- | ------------------------------------------------------------------- | +| `isValidCnpj`, `formatCnpj` | regular expressions, JavaScript's own coercion quirks | +| `getMunicipalities` | 5,571 rows of data and a `pt-BR` collation order | +| `getAddressInfoByCep` | HTTP, JSON, retries, an error hierarchy, and racing three providers | + +``` +source/cnpj.ts ──┐ +source/municipalities.ts ─┼──> compiler/frontend.ts ──> IR ──┬──> out/typescript +source/cep.ts ──┘ (oxc parser) ├──> out/python + ├──> out/go + ├──> out/rust + ├──> out/ruby + ├──> out/java + └──> out/csharp +``` + +## Is it actually the same? + +Parity is measured against the package this repository ships, not asserted. + +```bash +# The generated TypeScript drops into src/ and runs the package's own vitest suites. +bash spec/bridge/conformance/verify-typescript.sh + +# Every target replays the expectations recorded from the shipped package. +bash spec/bridge/conformance/run-all.sh +``` + +| target | CNPJ vectors | municipality dump | CEP scenarios | +| ---------- | ---------------------- | ----------------- | ----------------- | +| typescript | 5,740 / 5,740 | 11,176 / 11,176 | 110 / 110 | +| python | 5,740 / 5,740 | 11,176 / 11,176 | 109 / 109 (1 n/e) | +| ruby | 5,740 / 5,740 | 11,176 / 11,176 | 109 / 109 (1 n/e) | +| go | 5,722 / 5,722 (18 n/e) | 11,176 / 11,176 | 103 / 103 (7 n/e) | +| rust | 5,722 / 5,722 (18 n/e) | 11,176 / 11,176 | 103 / 103 (7 n/e) | +| java | 5,722 / 5,722 (18 n/e) | 11,176 / 11,176 | 103 / 103 (7 n/e) | +| csharp | 5,722 / 5,722 (18 n/e) | 11,176 / 11,176 | 103 / 103 (7 n/e) | + +"n/e" is **not expressible**: a case whose input has no form in that language, listed under +[Known gaps](#known-gaps). Nothing is skipped for being inconvenient. + +The CNPJ corpus is every string literal in the package's own CNPJ test files, plus 120 freshly +generated CNPJs and masked and mutated variants of each, so its total moves by a few dozen every +time the expectations are re-recorded. The municipality dump and the CEP scenarios are fixed. + +And the package's own suites, run against the generated TypeScript: + +``` +Test Files 4 passed (4) + Tests 157 passed | 3 skipped | 3 todo (164) +``` + +That includes the type level assertions — `expectTypeOf(getMunicipalities).parameter(0)` has to +be `StateCode | undefined`, `getAddressInfoByCep` has to resolve to `AddressInfo`, and the four +CEP error classes have to extend one another. + +## The three things that would otherwise differ + +Most of a utility ports without thought. Three things do not, and each is resolved at build +time rather than left to the host: + +**Regular expressions.** `\s` is 25 code points in JavaScript, 6 in Go and Ruby, and a Unicode +property in Python and Rust; `^` and `$` are line anchors in Ruby; Java and C# expand `\uXXXX` +before the regex engine ever sees it. So a pattern is compiled, at build time, into explicit +code point ranges and a backtrack-free matcher that every runtime implements the same way +([`compiler/regex.ts`](compiler/regex.ts)). The compiler refuses any pattern whose consecutive +classes overlap, which is what makes the greedy, backtrack-free scan provably correct. + +**Collation.** `getMunicipalities()` returns names sorted with `localeCompare(…, "pt-BR")`. Go +and Rust ship no collator at all; Ruby compares bytes; Python, Java and C# each resolve their +own. Sorting at run time would produce seven different orders, so +[`data/build.ts`](data/build.ts) resolves the order once, against the JavaScript package's own +comparator, and bakes it into the dataset. Every target replays it. + +**JavaScript's boundary quirks.** `formatCnpj(12_345_678)` coerces, `{ obfuscate: 1 }` is +truthy, `getAddressInfoByCep("01310-100")` strips the mask. These are the package's contract, +not accidents, so they live in a small portable standard library +([`source/_std.ts`](source/_std.ts)) that each target implements natively: `asString`, +`isTruthy`, `isNumber`, `isList`. + +## What the author never writes + +The source is straight-line, synchronous TypeScript. Three things are the emitter's job: + +- **`async`.** `source/cep.ts` calls `httpGet(…)` and returns an `AddressInfo`. The compiler + works out which functions wait on the network, and colours the call graph per target: + TypeScript and C# get `async`/`await` and a `Promise`/`Task` return, while Go, Rust, Ruby, + Java and Python stay blocking. +- **Raising.** The source writes `throw new GetAddressInfoByCepNotFoundError(…)`. Java, C#, + Python, Ruby and TypeScript get a real exception class. Go gets `(T, error)` with the error + threaded through every call site; Rust gets `Result`. The declared error + hierarchy survives in all seven. +- **Concurrency.** `startAll(fetchProvider, chosen, digits)` is the only concurrency primitive + of the subset. It becomes promises in TypeScript, `Task`s in C#, goroutines and a channel in + Go, threads and an `mpsc` channel in Rust, virtual threads in Java, and threads with a queue + in Python and Ruby. + +## The subset + +The frontend accepts a subset and refuses everything else with a pointed error rather than +emitting something that means one thing in Go and another in Ruby. + +**Accepted:** `const`/`let`, `if`/`else`, `for (let i = …)`, `for…of`, `return`, `throw`, +arrow functions at module level, `+ - * % === !== < <= > >= && || !`, compound assignment, +template literals, the ternary operator (outside Go), object literals for declared record +types, array literals, `.push()`, `.length`, and the string methods `charCodeAt`, `slice`, +`toUpperCase`, `trim`, `padStart`, `repeat`, `replaceAll(/…/g, "")`. + +**Declarations:** `type X = { … }` (a record, or an options record when every field is +optional), `type X = "a" | "b"` (a closed set of strings), `class X extends Y {}` (an error +type, body must be empty), module level `const` for strings, integers, lists and regular +expressions, and `dataset("name")` for a table built by `data/build.ts`. + +**Refused:** classes with bodies, inheritance other than for errors, inline closures, `switch`, +`while`, floating point, `null` as a value, mutation of anything but a local, and any regular +expression with alternation, lookaround or overlapping consecutive classes. + +## Known gaps + +These are the honest edges, all of them measured rather than assumed. + +- **`string | number` has no static form.** `isValidCnpj(12_345_678_000_195)` is `false` in + JavaScript, because the value is not a string. Go, Rust, Java and C# declare the parameter as + a string, so the question cannot be asked: 18 of the CNPJ vectors and 2 of the CEP cases are + not expressible there. Python and Ruby, being dynamically typed, answer all of them. +- **`null` and `undefined` are one value in most hosts.** `getAddressInfoByCep(cep, { providers: +null })` rejects, where an omitted `providers` uses the default. Only TypeScript can tell the + two apart; Python's `None` and Ruby's `nil` are both, so that case is not expressible there + either. +- **`toUpperCase` is not the same function everywhere.** The generated code calls each host's + own uppercasing, which agrees with JavaScript's for ASCII and for the Latin-1 range the CNPJ + alphabet uses, but not for every code point (Turkish dotless i, for instance). No utility in + scope depends on the difference; one that did would need `upper` pinned in the portable std + the way `trim` already is. +- **Retry policy is the host's.** `httpGet(url, retries, delayMs)` retries a _transient_ + transport failure, and what counts as transient is each client's own set of error codes. The + generated TypeScript reproduces the shipped package's list exactly; the other six use their + own client's equivalent. +- **The generated TypeScript is not (yet) what the package ships.** It passes the package's + tests, but adopting it would mean moving the handwritten `src/` implementations to + `spec/bridge/source/` and generating the rest. That is a decision, not a technical blocker. + +## Layout + +``` +source/ the utilities, written once, and the portable std + _std.ts the operations each target implements natively + *.data.json datasets, built by data/build.ts +compiler/ + frontend.ts TypeScript (via the oxc parser) -> IR + ir.ts the intermediate representation + regex.ts regular expressions -> code point classes + a matcher + targets/*.ts one emitter per language + runtime/* one small runtime per language, utility agnostic +data/build.ts builds the datasets, resolving collation once +conformance/ + vectors.ts records the CNPJ expectations from the shipped package + municipalities.ts records the municipality dump + cep.ts the CEP scenarios: recorder and mock server in one file + drivers.ts writes the replay driver for each language + run-all.sh regenerates everything and replays it through all seven + verify-typescript.sh runs the package's own vitest suites on the output +out/ generated; not committed +``` + +## Running it + +```bash +cd spec/bridge +npm install # oxc-parser, for the frontend +node data/build.ts # rebuild the datasets +node compiler/cli.ts # every target +node compiler/cli.ts rust # one target +bash conformance/run-all.sh # the whole parity check +``` + +The conformance run needs the toolchains of the languages it checks (node, python3, ruby, go, +cargo, javac, dotnet) and uses a local HTTP server on port 18080, which +`BRUTILS_BRIDGE_PORT` overrides. The runtimes read `BRUTILS_BRIDGE_HTTP_ORIGIN` to point their +requests at it; unset, they call the real services. diff --git a/spec/bridge/compiler/cli.ts b/spec/bridge/compiler/cli.ts index f6634c263..6cf66cb62 100644 --- a/spec/bridge/compiler/cli.ts +++ b/spec/bridge/compiler/cli.ts @@ -5,8 +5,9 @@ */ import { mkdirSync, readdirSync, rmSync, writeFileSync } from "node:fs"; import { dirname, resolve } from "node:path"; + import { compileModule } from "./frontend.ts"; -import type { Module } from "./ir.ts"; +import { type Module } from "./ir.ts"; import { emit as emitCsharp } from "./targets/csharp.ts"; import { emit as emitGo } from "./targets/go.ts"; import { emit as emitJava } from "./targets/java.ts"; diff --git a/spec/bridge/compiler/frontend.ts b/spec/bridge/compiler/frontend.ts index 4d9a8934f..8a2b8c151 100644 --- a/spec/bridge/compiler/frontend.ts +++ b/spec/bridge/compiler/frontend.ts @@ -7,22 +7,25 @@ */ import { readFileSync } from "node:fs"; import { basename, dirname, resolve } from "node:path"; + import { parseSync } from "oxc-parser"; -import type { - BinaryOp, - CharClass, - DataDecl, - EnumDecl, - ErrorDecl, - Expr, - FuncDecl, - Module, - Param, - PatternDecl, - Stmt, - StructDecl, - Ty, + +import { + type BinaryOp, + type CharClass, + type DataDecl, + type EnumDecl, + type ErrorDecl, + type Expr, + type FuncDecl, + type Module, + type Param, + type PatternDecl, + type Stmt, + type StructDecl, + type Ty, } from "./ir.ts"; +import { walk } from "./kit.ts"; import { ClassTable, complement, parsePattern, toSteps } from "./regex.ts"; /* eslint-disable */ @@ -51,7 +54,10 @@ type Scope = { /** Module level `const` lists and strings, by name. */ constants: Map; /** Regex literals, by the name they were bound to. */ - regexes: Map; + regexes: Map< + string, + { anchored: boolean; pattern?: string; charClass?: string; keepClass?: string } + >; classes: ClassTable; patterns: PatternDecl[]; /** Portable standard library members the module imported. */ @@ -65,10 +71,48 @@ const STD_FUNCTIONS = new Map([ ["isTruthy", { k: "bool" }], ["dataAll", { k: "list", of: { k: "list", of: { k: "string" } } }], ["dataRows", { k: "list", of: { k: "list", of: { k: "string" } } }], + ["isNumber", { k: "bool" }], + ["isList", { k: "bool" }], + ["listHas", { k: "bool" }], + ["httpGet", { k: "named", name: "HttpResponse" }], + ["jsonString", { k: "string" }], + ["jsonInt", { k: "int" }], + ["jsonTruthy", { k: "bool" }], + ["jsonIsTrue", { k: "bool" }], + ["anyFailedWith", { k: "bool" }], ]); /** Members of the portable std that are types or build time only, so never lowered as calls. */ -const STD_NON_CALLS = new Set(["Dataset", "dataset"]); +const STD_NON_CALLS = new Set([ + "Dataset", + "dataset", + "HttpResponse", + "Attempts", + "Outcome", + // Typed where they are lowered, because their types come from the function they are given. + "startAll", + "firstSuccess", +]); + +/** The std calls that wait on the network, which is what makes a function `async` in some targets. */ +const STD_BLOCKING = new Set(["httpGet", "firstSuccess"]); + +/** The record the runtime declares for `httpGet`, so `response.status` reads like any field. */ +const HTTP_RESPONSE: StructDecl = { + name: "HttpResponse", + doc: "What a provider answered: the HTTP status, whether it counts as a success, and the body.", + isOptions: false, + external: true, + fields: [ + { + name: "status", + ty: { k: "int" }, + doc: "The HTTP status, or 0 when the request never reached the server.", + }, + { name: "ok", ty: { k: "bool" }, doc: "Whether the status is in the 2xx range." }, + { name: "body", ty: { k: "json" }, doc: "The decoded JSON body." }, + ], +}; const int: Ty = { k: "int" }; const str: Ty = { k: "string" }; @@ -116,6 +160,8 @@ const readType = (node: Node, scope: Scope): Ty => { return fail(node, "only unions of literal numbers or literal strings are in the subset"); } + case "TSUnknownKeyword": + return { k: "json" }; case "TSTypeReference": { const name = String((node["typeName"] as Node)["name"]); @@ -142,6 +188,14 @@ const readSources = (doc: string): { role: string; url: string }[] => url: match[2], })); +/** A doc comment on one line, for the places a target can only write one. */ +const oneLine = (doc: string): string => + doc + .split("\n") + .join(" ") + .replaceAll(/\s{2,}/g, " ") + .trim(); + /** Pulls the block comment that ends right before `start`, if any. */ const docBefore = (source: string, start: number): string => { const before = source.slice(0, start); @@ -149,7 +203,13 @@ const docBefore = (source: string, start: number): string => { const close = before.lastIndexOf("*/"); if (open === -1 || close < open) return ""; - if (before.slice(close + 2).trim() !== "" && !before.slice(close + 2).trim().startsWith("export")) + if ( + before.slice(close + 2).trim() !== "" && + !before + .slice(close + 2) + .trim() + .startsWith("export") + ) return ""; return before @@ -201,6 +261,8 @@ const inferType = (expr: Expr, locals: Map, scope: Scope): Ty => { return inferType(expr.value, locals, scope); case "optionField": return expr.ty; + case "none": + return { k: "opt", of: str }; default: return str; } @@ -260,7 +322,8 @@ const lowerExpr = (node: Node, ctx: Ctx): Expr => { if (typeof value === "string") return { k: "str", value }; if (typeof value === "boolean") return { k: "bool", value }; if (typeof value === "number") { - if (!Number.isInteger(value)) return fail(current, "only integer literals are in the subset"); + if (!Number.isInteger(value)) + return fail(current, "only integer literals are in the subset"); return { k: "int", value }; } @@ -287,7 +350,8 @@ const lowerExpr = (node: Node, ctx: Ctx): Expr => { return { k: "ref", name }; } case "UnaryExpression": { - if (current["operator"] === "!") return { k: "not", operand: lowerExpr(current["argument"] as Node, ctx) }; + if (current["operator"] === "!") + return { k: "not", operand: lowerExpr(current["argument"] as Node, ctx) }; if (current["operator"] === "-") { const inner = lowerExpr(current["argument"] as Node, ctx); @@ -300,7 +364,8 @@ const lowerExpr = (node: Node, ctx: Ctx): Expr => { case "LogicalExpression": { const op = BINARY_OPS[String(current["operator"])]; - if (op === undefined) return fail(current, `operator \`${String(current["operator"])}\` is outside the subset`); + if (op === undefined) + return fail(current, `operator \`${String(current["operator"])}\` is outside the subset`); const left = lowerExpr(current["left"] as Node, ctx); const right = lowerExpr(current["right"] as Node, ctx); @@ -321,13 +386,16 @@ const lowerExpr = (node: Node, ctx: Ctx): Expr => { const expressions = current["expressions"] as Node[]; let built: Expr = { k: "str", value: String((quasis[0]["value"] as Node)["cooked"]) }; + // The type travels with the node: a template literal is always concatenation, never + // the addition the same operator means elsewhere. for (const [index, expression] of expressions.entries()) { - built = { k: "bin", op: "+", left: built, right: lowerExpr(expression, ctx) }; + built = { k: "bin", op: "+", left: built, right: lowerExpr(expression, ctx), ty: str }; built = { k: "bin", op: "+", left: built, right: { k: "str", value: String((quasis[index + 1]["value"] as Node)["cooked"]) }, + ty: str, }; } @@ -336,7 +404,11 @@ const lowerExpr = (node: Node, ctx: Ctx): Expr => { case "ArrayExpression": { const items = (current["elements"] as Node[]).map((element) => lowerExpr(element, ctx)); - return { k: "listOf", items, of: items.length > 0 ? inferType(items[0], ctx.locals, ctx.scope) : str }; + return { + k: "listOf", + items, + of: items.length > 0 ? inferType(items[0], ctx.locals, ctx.scope) : str, + }; } case "AwaitExpression": return { k: "await", value: lowerExpr(current["argument"] as Node, ctx) }; @@ -372,8 +444,7 @@ const lowerObject = (node: Node, ctx: Ctx): Expr => { }); const keys = [...properties.map((property) => property.name)].sort().join(","); const match = [...ctx.scope.structs.values()].find( - (candidate) => - [...candidate.fields.map((field) => field.name)].sort().join(",") === keys, + (candidate) => [...candidate.fields.map((field) => field.name)].sort().join(",") === keys, ); if (match === undefined) return fail(node, `no declared record type has the fields \`${keys}\``); @@ -419,13 +490,24 @@ const lowerMember = (node: Node, ctx: Ctx): Expr => { if (field === undefined) return fail(node, `\`${struct.name}\` has no field \`${name}\``); - return { + const read: Expr = { k: "optionField", target: targetName, field: name, ty: field.ty, - fallback: field.ty.k === "bool" ? { k: "bool", value: false } : { k: "int", value: -1 }, + fallback: + field.ty.k === "bool" + ? { k: "bool", value: false } + : field.ty.k === "int" + ? { k: "int", value: -1 } + : { k: "none" }, }; + + // Inside a branch that proved the option present, the read is the value. + if (ctx.narrowed.has(`${targetName}.${name}`)) + return { k: "call", callee: { k: "std", name: "unwrap" }, args: [read], ty: field.ty }; + + return read; } const target = lowerExpr(object, ctx); @@ -462,6 +544,52 @@ const lowerCall = (node: Node, ctx: Ctx): Expr => { if (callee["type"] === "Identifier") { const name = String(callee["name"]); + + // `startAll` and `firstSuccess` carry the type of whatever the started function returns, + // so they are typed here rather than from the table. + if (name === "startAll" && ctx.scope.stdImports.has(name)) { + const started = String((args[0] as Node)["name"]); + const signature = ctx.scope.functions.get(started); + + if (signature === undefined) + return fail(node, `\`startAll\` needs a function, not \`${started}\``); + + return { + k: "call", + callee: { k: "std", name }, + args: [ + { k: "ref", name: started }, + ...args.slice(1).map((argument) => lowerExpr(argument, ctx)), + ], + ty: { k: "tasks", of: signature.ret }, + }; + } + + if (name === "firstSuccess" && ctx.scope.stdImports.has(name)) { + const attempts = lowerExpr(args[0], ctx); + const ty = inferType(attempts, ctx.locals, ctx.scope); + + return { + k: "call", + callee: { k: "std", name }, + args: [attempts], + ty: { k: "opt", of: ty.k === "tasks" ? ty.of : str }, + }; + } + + if (name === "anyFailedWith" && ctx.scope.stdImports.has(name)) { + const kind = String((args[1] as Node)["name"]); + + if (!ctx.scope.errors.has(kind)) return fail(node, `\`${kind}\` is not a declared error`); + + return { + k: "call", + callee: { k: "std", name }, + args: [lowerExpr(args[0], ctx), { k: "str", value: kind }], + ty: bool, + }; + } + const std = ctx.scope.stdImports.has(name) ? STD_FUNCTIONS.get(name) : undefined; if (std !== undefined) { @@ -506,7 +634,8 @@ const lowerCall = (node: Node, ctx: Ctx): Expr => { }; } - if (regex.charClass === undefined) return fail(node, `\`${regexName}\` needs anchors to be used with .test()`); + if (regex.charClass === undefined) + return fail(node, `\`${regexName}\` needs anchors to be used with .test()`); return { k: "call", @@ -523,7 +652,7 @@ const lowerCall = (node: Node, ctx: Ctx): Expr => { const replacement = args[1] as Node; if (replacement["value"] !== "") - return fail(node, "only `replaceAll(pattern, \"\")` is in the subset"); + return fail(node, 'only `replaceAll(pattern, "")` is in the subset'); const removed = ctx.scope.regexes.get(patternName); @@ -554,7 +683,8 @@ const lowerCall = (node: Node, ctx: Ctx): Expr => { const mapped = STRING_METHODS[method]; if (mapped === undefined) return fail(node, `\`.${method}()\` is outside the subset`); - if (args.length !== mapped.args) return fail(node, `\`.${method}()\` takes ${mapped.args} argument(s)`); + if (args.length !== mapped.args) + return fail(node, `\`.${method}()\` takes ${mapped.args} argument(s)`); return { k: "call", @@ -564,6 +694,27 @@ const lowerCall = (node: Node, ctx: Ctx): Expr => { }; }; +/** + * Every statement of a body, nested ones included. + * + * @param {Stmt[]} body - The statements. + * @returns {Stmt[]} The flattened list. + */ +const allStatements = (body: Stmt[]): Stmt[] => + body.flatMap((statement) => { + switch (statement.k) { + case "if": + return [statement, ...allStatements(statement.then), ...allStatements(statement.otherwise)]; + case "forOf": + case "forRange": + return [statement, ...allStatements(statement.body)]; + case "try": + return [statement, ...allStatements(statement.body), ...allStatements(statement.catchBody)]; + default: + return [statement]; + } + }); + /** * The optionals an `if` test proves present for its `then` branch. * @@ -576,12 +727,17 @@ const lowerCall = (node: Node, ctx: Ctx): Expr => { */ const provenPresent = (test: Expr, ctx: Ctx): string[] => { if (test.k !== "bin") return []; - if (test.op === "&&") return [...provenPresent(test.left, ctx), ...provenPresent(test.right, ctx)]; + if (test.op === "&&") + return [...provenPresent(test.left, ctx), ...provenPresent(test.right, ctx)]; if (test.op !== "!=") return []; - const [subject, other] = test.left.k === "none" ? [test.right, test.left] : [test.left, test.right]; + const [subject, other] = + test.left.k === "none" ? [test.right, test.left] : [test.left, test.right]; - if (other.k !== "none" || subject.k !== "ref") return []; + if (other.k !== "none") return []; + // An option field is optional by declaration, so proving it present narrows it too. + if (subject.k === "optionField") return [`${subject.target}.${subject.field}`]; + if (subject.k !== "ref") return []; return ctx.locals.get(subject.name)?.k === "opt" ? [subject.name] : []; }; @@ -593,13 +749,15 @@ const provenPresent = (test: Expr, ctx: Ctx): string[] => { * @param {Ctx} ctx - The walking context. * @returns {Stmt[]} The IR statements. */ -const lowerBlock = (nodes: Node[], ctx: Ctx): Stmt[] => nodes.flatMap((node) => lowerStmt(node, ctx)); +const lowerBlock = (nodes: Node[], ctx: Ctx): Stmt[] => + nodes.flatMap((node) => lowerStmt(node, ctx)); /** Recognises the boundary guards the handwritten package has, which only dynamic targets need. */ const asGuard = (node: Node, ctx: Ctx): Stmt[] | undefined => { const test = node["test"] as Node; const consequent = node["consequent"] as Node; - const body = consequent["type"] === "BlockStatement" ? (consequent["body"] as Node[]) : [consequent]; + const body = + consequent["type"] === "BlockStatement" ? (consequent["body"] as Node[]) : [consequent]; if (body.length !== 1 || body[0]["type"] !== "ReturnStatement") return undefined; @@ -672,7 +830,33 @@ const lowerStmt = (node: Node, ctx: Ctx): Stmt[] => { const expression = node["expression"] as Node; if (expression["type"] === "AssignmentExpression") { - if (expression["operator"] !== "=") return fail(expression, "only `=` assignment is in the subset"); + const operator = String(expression["operator"]); + + // `sum += x` is `sum = sum + x`; every target writes the second form. + if (operator.length === 2 && operator.endsWith("=")) { + const op = BINARY_OPS[operator.slice(0, 1)]; + + if (op === undefined) + return fail(expression, `\`${operator}\` assignment is outside the subset`); + + const left = lowerExpr(expression["left"] as Node, ctx); + + return [ + { + k: "assign", + name: String((expression["left"] as Node)["name"]), + value: { + k: "bin", + op, + left, + right: lowerExpr(expression["right"] as Node, ctx), + ty: inferType(left, ctx.locals, ctx.scope), + }, + }, + ]; + } + + if (operator !== "=") return fail(expression, "only `=` assignment is in the subset"); return [ { @@ -713,7 +897,9 @@ const lowerStmt = (node: Node, ctx: Ctx): Stmt[] => { alternate === undefined ? [] : lowerBlock( - alternate["type"] === "BlockStatement" ? (alternate["body"] as Node[]) : [alternate], + alternate["type"] === "BlockStatement" + ? (alternate["body"] as Node[]) + : [alternate], ctx, ), }, @@ -722,7 +908,9 @@ const lowerStmt = (node: Node, ctx: Ctx): Stmt[] => { case "ReturnStatement": { const argument = (node["argument"] as Node | null) ?? undefined; - return [{ k: "return", value: argument === undefined ? undefined : lowerExpr(argument, ctx) }]; + return [ + { k: "return", value: argument === undefined ? undefined : lowerExpr(argument, ctx) }, + ]; } case "ForStatement": { const init = node["init"] as Node; @@ -752,7 +940,13 @@ const lowerStmt = (node: Node, ctx: Ctx): Stmt[] => { ctx.locals.set(name, ty); return [ - { k: "forOf", name, ty, iterable, body: lowerBlock((node["body"] as Node)["body"] as Node[], ctx) }, + { + k: "forOf", + name, + ty, + iterable, + body: lowerBlock((node["body"] as Node)["body"] as Node[], ctx), + }, ]; } case "ThrowStatement": { @@ -836,6 +1030,8 @@ export const compileModule = (path: string): Module => { const functions: FuncDecl[] = []; const statements = parsed.program.body as unknown as Node[]; + scope.structs.set(HTTP_RESPONSE.name, HTTP_RESPONSE); + // `import { asString } from "./_std.ts"` brings in the portable standard library, whose // members every target implements natively. for (const statement of statements) { @@ -860,6 +1056,29 @@ export const compileModule = (path: string): Module => { const exported = statement["type"] === "ExportNamedDeclaration"; const declaration = exported ? (statement["declaration"] as Node) : statement; + if (declaration["type"] === "ClassDeclaration") { + const name = String((declaration["id"] as Node)["name"]); + const parent = (declaration["superClass"] as Node | null) ?? undefined; + const base = parent === undefined ? undefined : String(parent["name"]); + + if ((declaration["body"] as Node | undefined) !== undefined) { + const members = ((declaration["body"] as Node)["body"] as Node[]) ?? []; + + if (members.length > 0) + fail(declaration, `\`${name}\` has a body; an error type in the subset is only a name`); + } + + scope.errors.set(name, { + name, + doc: oneLine(docBefore(source, (statement["start"] ?? declaration["start"]) as number)), + base: base === "Error" ? undefined : base, + exported, + // Filled in below, once every error of the module is known. + kinds: [], + }); + continue; + } + if (declaration["type"] === "TSTypeAliasDeclaration") { const name = String((declaration["id"] as Node)["name"]); const literal = declaration["typeAnnotation"] as Node; @@ -876,7 +1095,7 @@ export const compileModule = (path: string): Module => { scope.enums.set(name, { name, - doc: docBefore(source, declaration["start"] as number), + doc: oneLine(docBefore(source, declaration["start"] as number)), values, }); continue; @@ -890,7 +1109,7 @@ export const compileModule = (path: string): Module => { return { name: String((member["key"] as Node)["name"]), ty: readType(annotation, scope), - doc: docBefore(source, member["start"] as number), + doc: oneLine(docBefore(source, member["start"] as number)), // `version?: 1 | 2` keeps its domain so the TypeScript target can print it back. domain: union.length > 0 @@ -901,7 +1120,7 @@ export const compileModule = (path: string): Module => { scope.structs.set(name, { name, - doc: docBefore(source, declaration["start"] as number), + doc: oneLine(docBefore(source, declaration["start"] as number)), fields, isOptions: members.every((member) => member["optional"] === true), }); @@ -952,19 +1171,33 @@ export const compileModule = (path: string): Module => { scope.functions.set(name, { params, - ret: returnType === null ? { k: "void" } : readType(returnType["typeAnnotation"] as Node, scope), + ret: + returnType === null + ? { k: "void" } + : readType(returnType["typeAnnotation"] as Node, scope), isAsync: init["async"] === true, }); continue; } if (init["type"] === "ArrayExpression") { - const items = (init["elements"] as Node[]).map((element) => ({ - k: "int" as const, - value: Number(element["value"]), - })); + const elements = init["elements"] as Node[]; + const annotation = (entry["id"] as Node)["typeAnnotation"] as Node | null; + const declared = + annotation === null ? undefined : readType(annotation["typeAnnotation"] as Node, scope); + const of: Ty = + declared !== undefined && declared.k === "list" + ? declared.of + : typeof elements[0]?.["value"] === "string" + ? str + : int; + const items = elements.map((element) => + of.k === "int" + ? ({ k: "int", value: Number(element["value"]) } as Expr) + : ({ k: "str", value: String(element["value"]) } as Expr), + ); - scope.constants.set(name, { ty: { k: "list", of: int }, expr: { k: "listOf", items, of: int } }); + scope.constants.set(name, { ty: { k: "list", of }, expr: { k: "listOf", items, of } }); continue; } @@ -973,6 +1206,14 @@ export const compileModule = (path: string): Module => { continue; } + if (init["type"] === "Literal" && typeof init["value"] === "number") { + if (!Number.isInteger(init["value"])) + fail(init, `module level \`${name}\` is not an integer`); + + scope.constants.set(name, { ty: int, expr: { k: "int", value: Number(init["value"]) } }); + continue; + } + fail(init, `module level \`${name}\` is outside the subset`); } } @@ -1014,11 +1255,71 @@ export const compileModule = (path: string): Module => { body: lowerBlock(statementsOfBody, ctx), isAsync: signature.isAsync, exported, + blocking: false, + throws: false, sources: readSources(doc), }); } } + // Two properties travel up the call graph: a function that waits on the network makes its + // callers wait too, and a function that raises makes its callers able to raise. The targets + // that colour their functions (`async` in TypeScript, `Result` in Rust) need both. + const byName = new Map(functions.map((entry) => [entry.name, entry])); + + for (const entry of functions) { + walk(entry.body, (node) => { + if (node.k !== "call") return; + if (node.callee.k === "std" && STD_BLOCKING.has(node.callee.name)) entry.blocking = true; + }); + + for (const statement of allStatements(entry.body)) { + if (statement.k === "throw") entry.throws = true; + } + } + + for (let pass = 0; pass < functions.length + 1; pass++) { + let changed = false; + + for (const entry of functions) { + walk(entry.body, (node) => { + if (node.k !== "call") return; + + // `startAll` takes the function itself, so its properties are the caller's too. + const called = + node.callee.k === "user" + ? byName.get(node.callee.name) + : node.callee.k === "std" && node.callee.name === "startAll" && node.args[0].k === "ref" + ? byName.get(node.args[0].name) + : undefined; + + if (called === undefined) return; + if (called.blocking && !entry.blocking) { + entry.blocking = true; + changed = true; + } + + if (called.throws && !entry.throws) { + entry.throws = true; + changed = true; + } + }); + } + + if (!changed) break; + } + + for (const entry of scope.errors.values()) { + const kinds: string[] = []; + + for (let current: ErrorDecl | undefined = entry; current !== undefined;) { + kinds.push(current.name); + current = current.base === undefined ? undefined : scope.errors.get(current.base); + } + + entry.kinds = kinds; + } + // The module's own doc comment is the first block comment in the file. const firstComment = source.indexOf("*/"); const moduleDoc = firstComment === -1 ? "" : docBefore(source, firstComment + 2); diff --git a/spec/bridge/compiler/ir.ts b/spec/bridge/compiler/ir.ts index 2c3cce4f6..544cce6f1 100644 --- a/spec/bridge/compiler/ir.ts +++ b/spec/bridge/compiler/ir.ts @@ -17,6 +17,8 @@ export type Ty = | { k: "scalar" } /** A string whose values are a closed set: a union of string literals in the source. */ | { k: "enum"; name: string } + /** The running attempts of a race, as `startAll` hands them over. */ + | { k: "tasks"; of: Ty } | { k: "list"; of: Ty } | { k: "opt"; of: Ty } | { k: "named"; name: string }; @@ -43,24 +45,11 @@ export type Expr = | { k: "cond"; test: Expr; whenTrue: Expr; whenFalse: Expr } | { k: "listOf"; items: Expr[]; of: Ty } | { k: "struct"; name: string; fields: { name: string; value: Expr }[] } - | { k: "lambda"; params: Param[]; body: Stmt[]; ret: Ty; isAsync: boolean } | { k: "await"; value: Expr } /** `options?.version ?? fallback`: reads an optional field of an optional struct. */ | { k: "optionField"; target: string; field: string; ty: Ty; fallback: Expr }; -export type BinaryOp = - | "+" - | "-" - | "*" - | "%" - | "==" - | "!=" - | "<" - | "<=" - | ">" - | ">=" - | "&&" - | "||"; +export type BinaryOp = "+" | "-" | "*" | "%" | "==" | "!=" | "<" | "<=" | ">" | ">=" | "&&" | "||"; export type Stmt = | { k: "let"; name: string; ty: Ty; value: Expr; mutable: boolean } @@ -80,13 +69,22 @@ export type StructDecl = { fields: { name: string; ty: Ty; doc: string; domain?: number[] }[]; /** Options structs are the second, optional argument of a public function. */ isOptions: boolean; + /** Records the runtime already declares, which no emitter writes out again. */ + external?: boolean; }; /** A closed set of string values: `type StateCode = "AC" | "AL" | …`. */ export type EnumDecl = { name: string; doc: string; values: string[] }; /** An error type. `base` is another declared error, or undefined for a root error. */ -export type ErrorDecl = { name: string; doc: string; base?: string }; +export type ErrorDecl = { + name: string; + doc: string; + base?: string; + exported: boolean; + /** The name and every name it inherits from, which is what a failure is matched on. */ + kinds: string[]; +}; export type FuncDecl = { name: string; @@ -96,6 +94,10 @@ export type FuncDecl = { body: Stmt[]; isAsync: boolean; exported: boolean; + /** Whether the body waits on the network, directly or through another function. */ + blocking: boolean; + /** Whether the body can raise, directly or through another function. */ + throws: boolean; /** The `@see` links of the source, carried into every target's documentation. */ sources: { role: string; url: string }[]; }; @@ -168,11 +170,19 @@ export const STD = { dataRows: { params: ["data", "string"], ret: "list" }, dataAll: { params: ["data"], ret: "list" }, dataHasKey: { params: ["data", "string"], ret: "bool" }, + /** Whether a list holds a value. */ + listHas: { params: ["list", "string"], ret: "bool" }, + // boundary questions only a dynamically typed host can answer with anything but a constant + isNumber: { params: ["scalar"], ret: "bool" }, + isList: { params: ["any"], ret: "bool" }, // json and http - httpGet: { params: ["string"], ret: "named:HttpResponse" }, + httpGet: { params: ["string", "int", "int"], ret: "named:HttpResponse" }, jsonString: { params: ["json", "string"], ret: "string" }, jsonInt: { params: ["json", "string"], ret: "int" }, jsonTruthy: { params: ["json", "string"], ret: "bool" }, - // concurrency - raceFirstSuccess: { params: ["list"], ret: "any" }, + jsonIsTrue: { params: ["json", "string"], ret: "bool" }, + // concurrency: the only primitive of the subset + startAll: { params: ["function", "list", "string"], ret: "tasks" }, + firstSuccess: { params: ["tasks"], ret: "opt" }, + anyFailedWith: { params: ["tasks", "error"], ret: "bool" }, } as const; diff --git a/spec/bridge/compiler/kit.ts b/spec/bridge/compiler/kit.ts index 27d20288e..0cad284a4 100644 --- a/spec/bridge/compiler/kit.ts +++ b/spec/bridge/compiler/kit.ts @@ -5,7 +5,7 @@ * everywhere: naming conventions, walking the tree, and hoisting option reads into locals so * that no emitter has to inline a null check in the middle of an expression. */ -import type { Expr, FuncDecl, Stmt } from "./ir.ts"; +import { type Expr, type FuncDecl, type Stmt } from "./ir.ts"; /** * Converts a camelCase name to snake_case. @@ -53,78 +53,93 @@ export const walk = (body: Stmt[], visit: (expr: Expr) => void): void => { visit(node); switch (node.k) { - case "field": + case "field": { expression(node.target); break; - case "index": + } + case "index": { expression(node.target); expression(node.index); break; - case "call": + } + case "call": { for (const argument of node.args) expression(argument); break; - case "bin": + } + case "bin": { expression(node.left); expression(node.right); break; - case "not": + } + case "not": { expression(node.operand); break; - case "cond": + } + case "cond": { expression(node.test); expression(node.whenTrue); expression(node.whenFalse); break; - case "listOf": + } + case "listOf": { for (const item of node.items) expression(item); break; - case "struct": + } + case "struct": { for (const field of node.fields) expression(field.value); break; - case "await": + } + case "await": { expression(node.value); break; - case "lambda": - walk(node.body, visit); - break; - default: + } + default: { break; + } } }; for (const statement of body) { switch (statement.k) { case "let": - case "assign": + case "assign": { expression(statement.value); break; - case "if": + } + case "if": { expression(statement.test); walk(statement.then, visit); walk(statement.otherwise, visit); break; - case "return": + } + case "return": { if (statement.value !== undefined) expression(statement.value); break; - case "forOf": + } + case "forOf": { expression(statement.iterable); walk(statement.body, visit); break; - case "forRange": + } + case "forRange": { expression(statement.from); expression(statement.until); walk(statement.body, visit); break; - case "throw": + } + case "throw": { expression(statement.message); break; - case "try": + } + case "try": { walk(statement.body, visit); walk(statement.catchBody, visit); break; - case "expr": + } + case "expr": { expression(statement.value); break; + } } } }; @@ -190,12 +205,11 @@ export const pushTargets = (entry: FuncDecl): Set => { */ export const usesStd = (functions: FuncDecl[], name: string): boolean => { let used = false; + const look = (node: Expr): void => { + if (node.k === "call" && node.callee.k === "std" && node.callee.name === name) used = true; + }; - for (const entry of functions) { - walk(entry.body, (node) => { - if (node.k === "call" && node.callee.k === "std" && node.callee.name === name) used = true; - }); - } + for (const entry of functions) walk(entry.body, look); return used; }; @@ -231,5 +245,8 @@ export const prose = (doc: string): string => { lines.push(line); } - return lines.join("\n").replaceAll(/\n{3,}/g, "\n\n").trim(); + return lines + .join("\n") + .replaceAll(/\n{3,}/g, "\n\n") + .trim(); }; diff --git a/spec/bridge/compiler/regex.ts b/spec/bridge/compiler/regex.ts index a67dc1a5a..6d91b1dda 100644 --- a/spec/bridge/compiler/regex.ts +++ b/spec/bridge/compiler/regex.ts @@ -11,7 +11,7 @@ * alternation, no backreferences, no lookaround — the frontend rejects the literal instead of * guessing, which is the whole point. */ -import type { CharClass, PatternStep } from "./ir.ts"; +import { type CharClass, type PatternStep } from "./ir.ts"; type Ranges = [number, number][]; @@ -20,17 +20,17 @@ const JS_WHITESPACE: Ranges = [ [0x09, 0x0d], [0x20, 0x20], [0xa0, 0xa0], - [0x1680, 0x1680], - [0x2000, 0x200a], - [0x2028, 0x2029], - [0x202f, 0x202f], - [0x205f, 0x205f], - [0x3000, 0x3000], - [0xfeff, 0xfeff], + [0x16_80, 0x16_80], + [0x20_00, 0x20_0a], + [0x20_28, 0x20_29], + [0x20_2f, 0x20_2f], + [0x20_5f, 0x20_5f], + [0x30_00, 0x30_00], + [0xfe_ff, 0xfe_ff], ]; const DIGITS: Ranges = [[0x30, 0x39]]; -const MAX_CODE_POINT = 0x10_ffff; +const MAX_CODE_POINT = 0x10_ff_ff; /** * Sorts and merges ranges so that two classes built differently compare equal. @@ -87,7 +87,9 @@ export const complement = (ranges: Ranges): Ranges => { * @returns {boolean} True when they overlap. */ export const overlaps = (left: Ranges, right: Ranges): boolean => - left.some(([from, to]) => right.some(([otherFrom, otherTo]) => from <= otherTo && otherFrom <= to)); + left.some(([from, to]) => + right.some(([otherFrom, otherTo]) => from <= otherTo && otherFrom <= to), + ); type Parsed = { ranges: Ranges; min: number; max: number; capture: boolean }; @@ -141,7 +143,10 @@ const readClass = (source: string, start: number): { ranges: Ranges; next: numbe } const isRange = - source[index] === "-" && source[index + 1] !== "]" && index + 1 < source.length && low.length === 1; + source[index] === "-" && + source[index + 1] !== "]" && + index + 1 < source.length && + low.length === 1; if (isRange) { index++; @@ -166,7 +171,10 @@ const readClass = (source: string, start: number): { ranges: Ranges; next: numbe }; /** Reads a quantifier, if there is one at `index`. */ -const readQuantifier = (source: string, index: number): { min: number; max: number; next: number } => { +const readQuantifier = ( + source: string, + index: number, +): { min: number; max: number; next: number } => { if (source[index] === "*") return { min: 0, max: -1, next: index + 1 }; if (source[index] === "+") return { min: 1, max: -1, next: index + 1 }; if (source[index] === "?") return { min: 0, max: 1, next: index + 1 }; diff --git a/spec/bridge/compiler/runtime/csharp.cs b/spec/bridge/compiler/runtime/csharp.cs index 98977dee9..14fac3ad7 100644 --- a/spec/bridge/compiler/runtime/csharp.cs +++ b/spec/bridge/compiler/runtime/csharp.cs @@ -186,13 +186,15 @@ public static bool IsTruthy(bool? value) } /// Every row of a dataset, in the baked full order. - public static string[][] DataAll(Dataset table) + public static System.Collections.Generic.List> DataAll(Dataset table) { return table.All; } /// The rows whose first column is the key given, empty when the key is unknown. - public static string[][] DataRows(Dataset table, string key) + public static System.Collections.Generic.List> DataRows( + Dataset table, + string key) { return table.Rows(key); } @@ -201,30 +203,37 @@ public static string[][] DataRows(Dataset table, string key) /// A dataset: the rows in the baked full order, and the rows of each key. public sealed class Dataset { - private static readonly string[][] Empty = new string[0][]; + private static readonly Rows Empty = new Rows(); - public string[][] All { get; } + public Rows All { get; } - private readonly System.Collections.Generic.Dictionary byKey; + private readonly System.Collections.Generic.Dictionary byKey; public Dataset(string[][] rows, string[] keys, int[][] groups, int[] fullOrder) { - All = new string[fullOrder.Length][]; + var shared = new System.Collections.Generic.List>(rows.Length); - for (var index = 0; index < fullOrder.Length; index++) + foreach (var row in rows) { - All[index] = rows[fullOrder[index]]; + shared.Add(new System.Collections.Generic.List(row)); } - byKey = new System.Collections.Generic.Dictionary(keys.Length); + All = new Rows(); + + foreach (var index in fullOrder) + { + All.Add(shared[index]); + } + + byKey = new System.Collections.Generic.Dictionary(keys.Length); for (var group = 0; group < keys.Length; group++) { - var of = new string[groups[group].Length][]; + var of = new Rows(); - for (var index = 0; index < groups[group].Length; index++) + foreach (var index in groups[group]) { - of[index] = rows[groups[group][index]]; + of.Add(shared[index]); } byKey[keys[group]] = of; @@ -232,9 +241,286 @@ public Dataset(string[][] rows, string[] keys, int[][] groups, int[] fullOrder) } /// The rows of one key, empty when the key is unknown. - public string[][] Rows(string key) + public Rows Rows(string key) { return byKey.TryGetValue(key, out var found) ? found : Empty; } } + + /// A table of rows, which is what the generated code reads a dataset as. + public sealed class Rows : System.Collections.Generic.List> + { + } + + /// What a provider answered: the status, whether it is a success, and the body. + public sealed class HttpResponse + { + public long Status { get; } + public bool Ok { get; } + public System.Text.Json.Nodes.JsonNode Body { get; } + + public HttpResponse(long status, bool ok, System.Text.Json.Nodes.JsonNode body) + { + Status = status; + Ok = ok; + Body = body; + } + } + + /// What one attempt of a race ended with. + internal sealed class Outcome + { + public bool Ok { get; init; } + public T Value { get; init; } + public System.Collections.Generic.List Kinds { get; init; } + } + + /// The running attempts of a race, and what each one ended with. + public sealed class Attempts + { + internal System.Collections.Generic.List>> Settled { get; } = + new System.Collections.Generic.List>>(); + + internal System.Collections.Generic.List> Outcomes { get; } = + new System.Collections.Generic.List>(); + } + + /// The helpers the generated code needs for HTTP, JSON and racing. + public static class Net + { + private static readonly System.Net.Http.HttpClient Client = new System.Net.Http.HttpClient + { + Timeout = System.TimeSpan.FromSeconds(15), + }; + + /// + /// The origin every request is sent to instead of its own, when one is set. This is the + /// conformance hook: the cross language replay points all seven targets at one local + /// server, the same way the JavaScript suite points fetch at a mock. + /// + private static string Target(string url) + { + var origin = System.Environment.GetEnvironmentVariable("BRUTILS_BRIDGE_HTTP_ORIGIN"); + + if (string.IsNullOrEmpty(origin)) + { + return url; + } + + return origin + "/" + System.Text.RegularExpressions.Regex.Replace(url, "^https?://", string.Empty); + } + + /// Performs an HTTP GET, retrying a transient transport failure with a backoff. + public static async System.Threading.Tasks.Task HttpGet( + string url, + long retries, + long retryDelayMs) + { + var target = Target(url); + + for (long attempt = 0; ; attempt++) + { + try + { + var answer = await Client.GetAsync(target).ConfigureAwait(false); + var status = (long)answer.StatusCode; + var text = await answer.Content.ReadAsStringAsync().ConfigureAwait(false); + System.Text.Json.Nodes.JsonNode body = null; + + try + { + body = System.Text.Json.Nodes.JsonNode.Parse(text); + } + catch (System.Text.Json.JsonException) + { + body = null; + } + + return new HttpResponse(status, status >= 200 && status < 300, body); + } + catch (System.Exception) + { + if (attempt >= retries) + { + return new HttpResponse(0, false, null); + } + + await System.Threading.Tasks.Task.Delay((int)(retryDelayMs * (attempt + 1))).ConfigureAwait(false); + } + } + } + + /// Whether a list holds a value. + public static bool ListHas(System.Collections.Generic.List items, string value) + { + return items.Contains(value); + } + + /// Reads one field of a JSON body, treating anything that is not an object as empty. + private static System.Text.Json.Nodes.JsonNode Field(System.Text.Json.Nodes.JsonNode body, string key) + { + if (body is not System.Text.Json.Nodes.JsonObject found) + { + return null; + } + + return found.TryGetPropertyValue(key, out var value) ? value : null; + } + + /// Reads a string field of a JSON body, answering "" when it is missing. + public static string JsonString(System.Text.Json.Nodes.JsonNode body, string key) + { + var found = Field(body, key); + + if (found is System.Text.Json.Nodes.JsonValue value + && value.TryGetValue(out var text)) + { + return text; + } + + return string.Empty; + } + + /// Reads an integer field of a JSON body, answering -1 when it is missing. + public static long JsonInt(System.Text.Json.Nodes.JsonNode body, string key) + { + var found = Field(body, key); + + if (found is System.Text.Json.Nodes.JsonValue value && value.TryGetValue(out var number)) + { + return (long)number; + } + + return -1; + } + + /// Whether a field of a JSON body is truthy, the way JavaScript reads truthiness. + public static bool JsonTruthy(System.Text.Json.Nodes.JsonNode body, string key) + { + var found = Field(body, key); + + if (found is null) + { + return false; + } + + if (found is System.Text.Json.Nodes.JsonValue value) + { + if (value.TryGetValue(out var flag)) + { + return flag; + } + + if (value.TryGetValue(out var number)) + { + return number != 0; + } + + if (value.TryGetValue(out var text)) + { + return text.Length > 0; + } + } + + return true; + } + + /// Whether a field of a JSON body is exactly true. + public static bool JsonIsTrue(System.Text.Json.Nodes.JsonNode body, string key) + { + return Field(body, key) is System.Text.Json.Nodes.JsonValue value + && value.TryGetValue(out var flag) + && flag; + } + + /// The error name and every name it inherits from. + private static System.Collections.Generic.List KindsOf(System.Exception error) + { + var kinds = new System.Collections.Generic.List(); + + for (var current = error.GetType(); current != null; current = current.BaseType) + { + kinds.Add(current.Name); + } + + return kinds; + } + + /// + /// Starts one attempt per item, all at once. This is the only concurrency primitive of + /// the portable subset. + /// + public static Attempts StartAll( + System.Func> run, + System.Collections.Generic.List items, + string argument) + { + var attempts = new Attempts(); + + foreach (var item in items) + { + attempts.Settled.Add(Run(run, item, argument)); + } + + return attempts; + } + + private static async System.Threading.Tasks.Task> Run( + System.Func> run, + string item, + string argument) + { + try + { + return new Outcome + { + Ok = true, + Value = await run(item, argument).ConfigureAwait(false), + Kinds = new System.Collections.Generic.List(), + }; + } + catch (System.Exception error) + { + return new Outcome { Ok = false, Kinds = KindsOf(error) }; + } + } + + /// The value of the first attempt that succeeds, or the default once all failed. + public static async System.Threading.Tasks.Task FirstSuccess(Attempts attempts) + { + var waiting = new System.Collections.Generic.List>>(attempts.Settled); + + while (waiting.Count > 0) + { + var settled = await System.Threading.Tasks.Task.WhenAny(waiting).ConfigureAwait(false); + + waiting.Remove(settled); + + var outcome = await settled.ConfigureAwait(false); + + attempts.Outcomes.Add(outcome); + + if (outcome.Ok) + { + return outcome.Value; + } + } + + return default; + } + + /// Whether any attempt failed with a given error kind. + public static bool AnyFailedWith(Attempts attempts, string kind) + { + foreach (var outcome in attempts.Outcomes) + { + if (!outcome.Ok && outcome.Kinds.Contains(kind)) + { + return true; + } + } + + return false; + } + } } diff --git a/spec/bridge/compiler/runtime/go.go b/spec/bridge/compiler/runtime/go.go index 605dd805f..7a1c29b10 100644 --- a/spec/bridge/compiler/runtime/go.go +++ b/spec/bridge/compiler/runtime/go.go @@ -4,7 +4,16 @@ // thing it does in the other targets. package runtime -import "strings" +import ( + "encoding/json" + "errors" + "io" + "net/http" + "os" + "regexp" + "strings" + "time" +) // CharClass is a set of code points, as sorted non overlapping ranges. type CharClass [][2]rune @@ -198,3 +207,259 @@ func DataRows(table *Dataset, key string) [][]string { return [][]string{} } + +// HttpResponse is what a provider answered: the status, whether it counts as a success, and +// the decoded body. +type HttpResponse struct { + Status int64 + Ok bool + Body any +} + +// httpTarget is the origin every request is sent to instead of its own, when one is set. +// +// This is the conformance hook: the cross language replay points all seven targets at one +// local server, the same way the JavaScript suite points fetch at a mock. +func httpTarget(url string) string { + base := os.Getenv("BRUTILS_BRIDGE_HTTP_ORIGIN") + + if base == "" { + return url + } + + return base + "/" + originPrefix.ReplaceAllString(url, "") +} + +var originPrefix = regexp.MustCompile(`^https?://`) + +var httpClient = &http.Client{Timeout: 15 * time.Second} + +// HttpGet performs an HTTP GET, retrying a transient transport failure with a linear backoff. +func HttpGet(url string, retries int64, retryDelayMs int64) *HttpResponse { + target := httpTarget(url) + + for attempt := int64(0); ; attempt++ { + answer, err := httpClient.Get(target) + + if err != nil { + if attempt >= retries { + return &HttpResponse{Status: 0, Ok: false, Body: nil} + } + + time.Sleep(time.Duration(retryDelayMs*(attempt+1)) * time.Millisecond) + + continue + } + + raw, readErr := io.ReadAll(answer.Body) + answer.Body.Close() + + var body any + + if readErr == nil { + if json.Unmarshal(raw, &body) != nil { + body = nil + } + } + + status := int64(answer.StatusCode) + + return &HttpResponse{Status: status, Ok: status >= 200 && status < 300, Body: body} + } +} + +// ListHas reports whether a list holds a value. +func ListHas(items []string, value string) bool { + for _, item := range items { + if item == value { + return true + } + } + + return false +} + +// jsonField reads one field of a JSON body, treating anything that is not an object as empty. +func jsonField(body any, key string) any { + object, ok := body.(map[string]any) + + if !ok { + return nil + } + + return object[key] +} + +// JsonString reads a string field of a JSON body, answering "" when it is missing. +func JsonString(body any, key string) string { + found, ok := jsonField(body, key).(string) + + if !ok { + return "" + } + + return found +} + +// JsonInt reads an integer field of a JSON body, answering -1 when it is missing. +func JsonInt(body any, key string) int64 { + found, ok := jsonField(body, key).(float64) + + if !ok { + return -1 + } + + return int64(found) +} + +// JsonTruthy reports whether a field of a JSON body is truthy, the way JavaScript reads it. +func JsonTruthy(body any, key string) bool { + switch found := jsonField(body, key).(type) { + case nil: + return false + case bool: + return found + case float64: + return found != 0 + case string: + return found != "" + default: + return true + } +} + +// JsonIsTrue reports whether a field of a JSON body is exactly true. +func JsonIsTrue(body any, key string) bool { + found, ok := jsonField(body, key).(bool) + + return ok && found +} + +// Error is a failure raised by the generated code. Go has no exception hierarchy, so the kinds +// the source declared travel with the value. +type Error struct { + Kinds []string + Message string +} + +// Error returns the message. +func (e *Error) Error() string { + return e.Message +} + +// Kind returns the most specific kind of the failure. +func (e *Error) Kind() string { + if len(e.Kinds) == 0 { + return "" + } + + return e.Kinds[0] +} + +// NewError builds a failure of the given kinds. +func NewError(kinds []string, message string) error { + return &Error{Kinds: kinds, Message: message} +} + +// IsKind reports whether an error is of a kind, its bases included. +func IsKind(err error, kind string) bool { + var found *Error + + if !errors.As(err, &found) { + return false + } + + for _, candidate := range found.Kinds { + if candidate == kind { + return true + } + } + + return false +} + +// Outcome is what one attempt of a race ended with. +type Outcome struct { + Ok bool + Value any + Kinds []string +} + +// Attempts holds the running attempts of a race and what each one ended with. +type Attempts struct { + settled chan Outcome + total int + Outcomes []Outcome +} + +// StartAll starts one attempt per item, all at once. +// +// This is the only concurrency primitive of the portable subset: the author never writes a +// goroutine, and the emitter never has to decide where one belongs. +func StartAll(run func(string, string) (any, error), items []string, argument string) *Attempts { + attempts := &Attempts{settled: make(chan Outcome, len(items)), total: len(items)} + + for _, item := range items { + go func(item string) { + value, err := run(item, argument) + + if err != nil { + kinds := []string{} + + var raised *Error + + if errors.As(err, &raised) { + kinds = raised.Kinds + } + + attempts.settled <- Outcome{Ok: false, Kinds: kinds} + + return + } + + attempts.settled <- Outcome{Ok: true, Value: value} + }(item) + } + + return attempts +} + +// FirstSuccessOf returns the value of the first attempt that succeeds, or the zero value once +// every attempt has failed. +func FirstSuccessOf[T any](attempts *Attempts) T { + var zero T + + for len(attempts.Outcomes) < attempts.total { + outcome := <-attempts.settled + attempts.Outcomes = append(attempts.Outcomes, outcome) + + if outcome.Ok { + found, ok := outcome.Value.(T) + + if ok { + return found + } + + return zero + } + } + + return zero +} + +// AnyFailedWith reports whether any attempt failed with a given error kind. +func AnyFailedWith(attempts *Attempts, kind string) bool { + for _, outcome := range attempts.Outcomes { + if outcome.Ok { + continue + } + + for _, candidate := range outcome.Kinds { + if candidate == kind { + return true + } + } + } + + return false +} diff --git a/spec/bridge/compiler/runtime/java.java b/spec/bridge/compiler/runtime/java.java index 38c3ffdad..e483e96d6 100644 --- a/spec/bridge/compiler/runtime/java.java +++ b/spec/bridge/compiler/runtime/java.java @@ -145,23 +145,29 @@ public static boolean isTruthy(Boolean value) { /** A dataset: the rows in the baked full order, and the rows of each key. */ public static final class Dataset { - private final String[][] all; - private final java.util.Map byKey; + private final java.util.List> all; + private final java.util.Map>> byKey; public Dataset(String[][] rows, String[] keys, int[][] groups, int[] fullOrder) { - this.all = new String[fullOrder.length][]; + java.util.List> shared = new java.util.ArrayList<>(rows.length); - for (int index = 0; index < fullOrder.length; index++) { - this.all[index] = rows[fullOrder[index]]; + for (String[] row : rows) { + shared.add(java.util.List.of(row)); + } + + this.all = new java.util.ArrayList<>(fullOrder.length); + + for (int index : fullOrder) { + this.all.add(shared.get(index)); } this.byKey = new java.util.HashMap<>(keys.length * 2); for (int group = 0; group < keys.length; group++) { - String[][] of = new String[groups[group].length][]; + java.util.List> of = new java.util.ArrayList<>(groups[group].length); - for (int index = 0; index < groups[group].length; index++) { - of[index] = rows[groups[group][index]]; + for (int index : groups[group]) { + of.add(shared.get(index)); } this.byKey.put(keys[group], of); @@ -169,25 +175,443 @@ public Dataset(String[][] rows, String[] keys, int[][] groups, int[] fullOrder) } /** Every row, in the baked full order. */ - public String[][] all() { + public java.util.List> all() { return this.all; } /** The rows whose first column is the key given, empty when the key is unknown. */ - public String[][] rows(String key) { - String[][] found = this.byKey.get(key); - - return found == null ? new String[0][] : found; + public java.util.List> rows(String key) { + return this.byKey.getOrDefault(key, java.util.List.of()); } } /** Every row of a dataset, in the baked full order. */ - public static String[][] dataAll(Dataset table) { + public static java.util.List> dataAll(Dataset table) { return table.all(); } /** The rows whose first column is the key given, empty when the key is unknown. */ - public static String[][] dataRows(Dataset table, String key) { + public static java.util.List> dataRows(Dataset table, String key) { return table.rows(key); } + + /** What a provider answered: the HTTP status, whether it counts as a success, and the body. */ + public static final class HttpResponse { + public final long status; + public final boolean ok; + public final Object body; + + public HttpResponse(long status, boolean ok, Object body) { + this.status = status; + this.ok = ok; + this.body = body; + } + } + + private static final java.net.http.HttpClient HTTP = java.net.http.HttpClient.newBuilder() + .connectTimeout(java.time.Duration.ofSeconds(15)) + .build(); + + /** + * The origin every request is sent to instead of its own, when one is set. + * + * This is the conformance hook: the cross language replay points all seven targets at one + * local server, the same way the JavaScript suite points fetch at a mock. + */ + private static String httpTarget(String url) { + String base = System.getenv("BRUTILS_BRIDGE_HTTP_ORIGIN"); + + if (base == null || base.isEmpty()) { + return url; + } + + return base + "/" + url.replaceFirst("^https?://", ""); + } + + /** Performs an HTTP GET, retrying a transient transport failure with a linear backoff. */ + public static HttpResponse httpGet(String url, long retries, long retryDelayMs) { + String target = httpTarget(url); + + for (long attempt = 0; ; attempt++) { + try { + java.net.http.HttpRequest request = java.net.http.HttpRequest.newBuilder() + .uri(java.net.URI.create(target)) + .timeout(java.time.Duration.ofSeconds(15)) + .GET() + .build(); + java.net.http.HttpResponse answer = + HTTP.send(request, java.net.http.HttpResponse.BodyHandlers.ofString()); + long status = answer.statusCode(); + Object body; + + try { + body = Json.parse(answer.body()); + } catch (RuntimeException error) { + body = null; + } + + return new HttpResponse(status, status >= 200 && status < 300, body); + } catch (Exception error) { + if (attempt >= retries) { + return new HttpResponse(0, false, null); + } + + try { + Thread.sleep(retryDelayMs * (attempt + 1)); + } catch (InterruptedException interrupted) { + Thread.currentThread().interrupt(); + + return new HttpResponse(0, false, null); + } + } + } + } + + /** Whether a list holds a value. */ + public static boolean listHas(java.util.List items, String value) { + for (String item : items) { + if (item.equals(value)) { + return true; + } + } + + return false; + } + + /** Reads one field of a JSON body, treating anything that is not an object as empty. */ + private static Object jsonField(Object body, String key) { + if (!(body instanceof java.util.Map)) { + return null; + } + + return ((java.util.Map) body).get(key); + } + + /** Reads a string field of a JSON body, answering "" when it is missing. */ + public static String jsonString(Object body, String key) { + Object found = jsonField(body, key); + + return found instanceof String ? (String) found : ""; + } + + /** Reads an integer field of a JSON body, answering -1 when it is missing. */ + public static long jsonInt(Object body, String key) { + Object found = jsonField(body, key); + + return found instanceof Double ? (long) (double) (Double) found : -1L; + } + + /** Whether a field of a JSON body is truthy, the way JavaScript reads truthiness. */ + public static boolean jsonTruthy(Object body, String key) { + Object found = jsonField(body, key); + + if (found == null) { + return false; + } + + if (found instanceof Boolean) { + return (Boolean) found; + } + + if (found instanceof Double) { + return (Double) found != 0.0; + } + + if (found instanceof String) { + return !((String) found).isEmpty(); + } + + return true; + } + + /** Whether a field of a JSON body is exactly true. */ + public static boolean jsonIsTrue(Object body, String key) { + return Boolean.TRUE.equals(jsonField(body, key)); + } + + /** A JSON reader, so the target needs nothing outside the JDK. */ + static final class Json { + private final String text; + private int at; + + private Json(String text) { + this.text = text; + } + + static Object parse(String text) { + Json reader = new Json(text); + + reader.space(); + + Object value = reader.value(); + + reader.space(); + + if (reader.at != text.length()) { + throw new IllegalArgumentException("trailing JSON"); + } + + return value; + } + + private void space() { + while (at < text.length() && Character.isWhitespace(text.charAt(at))) { + at++; + } + } + + private Object value() { + if (at >= text.length()) { + throw new IllegalArgumentException("empty JSON"); + } + + char head = text.charAt(at); + + if (head == '{') { + return object(); + } + + if (head == '[') { + return array(); + } + + if (head == '"') { + return string(); + } + + if (text.startsWith("true", at)) { + at += 4; + + return Boolean.TRUE; + } + + if (text.startsWith("false", at)) { + at += 5; + + return Boolean.FALSE; + } + + if (text.startsWith("null", at)) { + at += 4; + + return null; + } + + return number(); + } + + private java.util.Map object() { + java.util.Map found = new java.util.LinkedHashMap<>(); + + at++; + space(); + + if (at < text.length() && text.charAt(at) == '}') { + at++; + + return found; + } + + while (true) { + space(); + + String key = string(); + + space(); + at++; // ':' + space(); + found.put(key, value()); + space(); + + if (at < text.length() && text.charAt(at) == ',') { + at++; + + continue; + } + + at++; // '}' + + return found; + } + } + + private java.util.List array() { + java.util.List found = new java.util.ArrayList<>(); + + at++; + space(); + + if (at < text.length() && text.charAt(at) == ']') { + at++; + + return found; + } + + while (true) { + space(); + found.add(value()); + space(); + + if (at < text.length() && text.charAt(at) == ',') { + at++; + + continue; + } + + at++; // ']' + + return found; + } + } + + private String string() { + StringBuilder out = new StringBuilder(); + + at++; + + while (at < text.length()) { + char here = text.charAt(at++); + + if (here == '"') { + return out.toString(); + } + + if (here != '\\') { + out.append(here); + + continue; + } + + char escaped = text.charAt(at++); + + switch (escaped) { + case 'n': out.append('\n'); break; + case 't': out.append('\t'); break; + case 'r': out.append('\r'); break; + case 'b': out.append('\b'); break; + case 'f': out.append('\f'); break; + case 'u': + out.append((char) Integer.parseInt(text.substring(at, at + 4), 16)); + at += 4; + break; + default: out.append(escaped); + } + } + + throw new IllegalArgumentException("unterminated string"); + } + + private Double number() { + int start = at; + + while (at < text.length() && "+-.eE0123456789".indexOf(text.charAt(at)) >= 0) { + at++; + } + + return Double.valueOf(text.substring(start, at)); + } + } + + /** What one attempt of a race ended with. */ + private static final class Outcome { + final boolean ok; + final Object value; + final java.util.List kinds; + + Outcome(boolean ok, Object value, java.util.List kinds) { + this.ok = ok; + this.value = value; + this.kinds = kinds; + } + } + + /** One attempt of a race: the function the source named, applied to one item. */ + public interface Task { + Object run(String item, String argument); + } + + /** The running attempts of a race, and what each one ended with. */ + public static final class Attempts { + private final java.util.concurrent.BlockingQueue settled; + private final int total; + private final java.util.List outcomes = new java.util.ArrayList<>(); + + Attempts(int total) { + this.settled = new java.util.concurrent.ArrayBlockingQueue<>(Math.max(total, 1)); + this.total = total; + } + } + + /** The error name and every name it inherits from, which is what a failure is matched on. */ + private static java.util.List kindsOf(Throwable error) { + java.util.List kinds = new java.util.ArrayList<>(); + + for (Class current = error.getClass(); current != null; current = current.getSuperclass()) { + kinds.add(current.getSimpleName()); + } + + return kinds; + } + + /** + * Starts one attempt per item, all at once. + * + * This is the only concurrency primitive of the portable subset. Java has virtual threads, + * so the work goes on one each and the caller simply waits. + */ + public static Attempts startAll(Task run, java.util.List items, String argument) { + Attempts attempts = new Attempts(items.size()); + + for (String item : items) { + Thread.ofVirtual().start(() -> { + try { + attempts.settled.put(new Outcome(true, run.run(item, argument), java.util.List.of())); + } catch (InterruptedException interrupted) { + Thread.currentThread().interrupt(); + } catch (Throwable error) { + try { + attempts.settled.put(new Outcome(false, null, kindsOf(error))); + } catch (InterruptedException interrupted) { + Thread.currentThread().interrupt(); + } + } + }); + } + + return attempts; + } + + /** The value of the first attempt that succeeds, or null once every attempt has failed. */ + public static Object firstSuccess(Attempts attempts) { + while (attempts.outcomes.size() < attempts.total) { + Outcome outcome; + + try { + outcome = attempts.settled.take(); + } catch (InterruptedException interrupted) { + Thread.currentThread().interrupt(); + + return null; + } + + attempts.outcomes.add(outcome); + + if (outcome.ok) { + return outcome.value; + } + } + + return null; + } + + /** Whether any attempt failed with a given error kind. */ + public static boolean anyFailedWith(Attempts attempts, String kind) { + for (Outcome outcome : attempts.outcomes) { + if (!outcome.ok && outcome.kinds.contains(kind)) { + return true; + } + } + + return false; + } } diff --git a/spec/bridge/compiler/runtime/python.py b/spec/bridge/compiler/runtime/python.py index 153525890..ed312c95a 100644 --- a/spec/bridge/compiler/runtime/python.py +++ b/spec/bridge/compiler/runtime/python.py @@ -4,6 +4,14 @@ classes and patterns are passed in as data, so this file never changes when a utility does. """ +import json +import os +import queue +import re +import threading +import time +import urllib.error +import urllib.request from typing import Any, List, Optional, Sequence, Tuple CharClass = Sequence[Tuple[int, int]] @@ -155,3 +163,160 @@ def data_all(table): def data_rows(table, key): """The rows whose first column is the key given, empty when the key is unknown.""" return table.by_key.get(key, []) + + +class HttpResponse: + """What a provider answered: the HTTP status, whether it counts as a success, and the body.""" + + __slots__ = ("status", "ok", "body") + + def __init__(self, status, ok, body): + self.status = status + self.ok = ok + self.body = body + + +def _http_target(url): + """The origin every request is sent to instead of its own, when one is set. + + This is the conformance hook: the cross language replay points all seven targets at one + local server, the same way the JavaScript suite points `fetch` at a mock. + """ + base = os.environ.get("BRUTILS_BRIDGE_HTTP_ORIGIN", "") + + if base == "": + return url + + return base + "/" + re.sub(r"^https?://", "", url) + + +def http_get(url, retries, retry_delay_ms): + """Performs an HTTP GET, retrying a transient transport failure with a linear backoff.""" + target = _http_target(url) + attempt = 0 + + while True: + try: + with urllib.request.urlopen(target, timeout=15) as response: + raw = response.read() + status = response.status + except urllib.error.HTTPError as error: + raw = error.read() + status = error.code + except Exception: + if attempt >= retries: + return HttpResponse(0, False, None) + + time.sleep(retry_delay_ms * (attempt + 1) / 1000) + attempt += 1 + continue + + try: + body = json.loads(raw.decode("utf-8")) + except Exception: + body = None + + return HttpResponse(status, 200 <= status < 300, body) + + +def is_number(value): + """Whether the caller handed a number where a string or a number was declared.""" + return isinstance(value, (int, float)) and not isinstance(value, bool) + + +def is_list(value): + """Whether a value is a list.""" + return isinstance(value, (list, tuple)) + + +def list_has(items, value): + """Whether a list holds a value.""" + return value in items + + +def _json_field(body, key): + """Reads one field of a JSON body, treating anything that is not an object as empty.""" + if not isinstance(body, dict): + return None + + return body.get(key) + + +def json_string(body, key): + """Reads a string field of a JSON body, answering "" when it is missing or not a string.""" + found = _json_field(body, key) + + return found if isinstance(found, str) else "" + + +def json_int(body, key): + """Reads an integer field of a JSON body, answering -1 when it is missing or not a number.""" + found = _json_field(body, key) + + if isinstance(found, bool) or not isinstance(found, (int, float)): + return -1 + + return int(found) + + +def json_truthy(body, key): + """Whether a field of a JSON body is truthy, the way JavaScript reads truthiness.""" + return bool(_json_field(body, key)) + + +def json_is_true(body, key): + """Whether a field of a JSON body is exactly True.""" + return _json_field(body, key) is True + + +class Attempts: + """The running attempts of a race, and what each one ended with.""" + + __slots__ = ("settled", "total", "outcomes") + + def __init__(self, total): + self.settled = queue.Queue() + self.total = total + self.outcomes = [] + + +def _kinds_of(error): + """The error name and every name it inherits from, which is what a failure is matched on.""" + return [kind.__name__ for kind in type(error).__mro__ if kind is not object] + + +def start_all(run, items, argument): + """Starts one attempt per item, all at once. + + This is the only concurrency primitive of the portable subset. Python has no promise to + colour a function with, so the work goes on threads and the caller simply waits. + """ + attempts = Attempts(len(items)) + + for item in items: + def work(item=item): + try: + attempts.settled.put((True, run(item, argument), [])) + except Exception as error: # noqa: BLE001 + attempts.settled.put((False, None, _kinds_of(error))) + + threading.Thread(target=work, daemon=True).start() + + return attempts + + +def first_success(attempts): + """The value of the first attempt that succeeds, or None once every attempt has failed.""" + while len(attempts.outcomes) < attempts.total: + outcome = attempts.settled.get() + attempts.outcomes.append(outcome) + + if outcome[0]: + return outcome[1] + + return None + + +def any_failed_with(attempts, kind): + """Whether any attempt failed with a given error kind.""" + return any(not ok and kind in kinds for ok, _value, kinds in attempts.outcomes) diff --git a/spec/bridge/compiler/runtime/ruby.rb b/spec/bridge/compiler/runtime/ruby.rb index 07d2ae2e2..8e17a8f32 100644 --- a/spec/bridge/compiler/runtime/ruby.rb +++ b/spec/bridge/compiler/runtime/ruby.rb @@ -1,5 +1,9 @@ # frozen_string_literal: true +require 'json' +require 'net/http' +require 'uri' + # The portable runtime for the Ruby target. # # Ruby indexes strings by character, which is what the generated code expects; everything else @@ -127,5 +131,157 @@ def self.data_all(table) def self.data_rows(table, key) table.by_key.fetch(key, []) end + + # What a provider answered: the HTTP status, whether it counts as a success, and the body. + HttpResponse = Struct.new(:status, :ok, :body) + + # The origin every request is sent to instead of its own, when one is set. + # + # This is the conformance hook: the cross language replay points all seven targets at one + # local server, the same way the JavaScript suite points fetch at a mock. + def self.http_target(url) + base = ENV.fetch('BRUTILS_BRIDGE_HTTP_ORIGIN', '') + + return url if base.empty? + + "#{base}/#{url.sub(%r{\Ahttps?://}, '')}" + end + + # Performs an HTTP GET, retrying a transient transport failure with a linear backoff. + def self.http_get(url, retries, retry_delay_ms) + target = URI.parse(http_target(url)) + attempt = 0 + + loop do + begin + answer = Net::HTTP.get_response(target) + rescue StandardError + return HttpResponse.new(0, false, nil) if attempt >= retries + + sleep(retry_delay_ms * (attempt + 1) / 1000.0) + attempt += 1 + next + end + + status = answer.code.to_i + body = begin + JSON.parse(answer.body) + rescue StandardError + nil + end + + return HttpResponse.new(status, status >= 200 && status < 300, body) + end + end + + # Whether the caller handed a number where a string or a number was declared. + def self.is_number(value) + value.is_a?(Numeric) + end + + # Whether a value is a list. + def self.is_list(value) + value.is_a?(Array) + end + + # Whether a list holds a value. + def self.list_has(items, value) + items.include?(value) + end + + # Reads one field of a JSON body, treating anything that is not an object as empty. + def self.json_field(body, key) + return nil unless body.is_a?(Hash) + + body[key] + end + + # Reads a string field of a JSON body, answering '' when it is missing or not a string. + def self.json_string(body, key) + found = json_field(body, key) + + found.is_a?(String) ? found : '' + end + + # Reads an integer field of a JSON body, answering -1 when it is missing or not a number. + def self.json_int(body, key) + found = json_field(body, key) + + found.is_a?(Numeric) && !found.is_a?(TrueClass) ? found.to_i : -1 + end + + # Whether a field of a JSON body is truthy, the way JavaScript reads truthiness. + def self.json_truthy(body, key) + found = json_field(body, key) + + !(found.nil? || found == false || found == 0 || found == '') + end + + # Whether a field of a JSON body is exactly true. + def self.json_is_true(body, key) + json_field(body, key) == true + end + + # The running attempts of a race, and what each one ended with. + class Attempts + attr_reader :settled, :total + attr_accessor :outcomes + + def initialize(total) + @settled = Queue.new + @total = total + @outcomes = [] + end + end + + # The error name and every name it inherits from, which is what a failure is matched on. + def self.kinds_of(error) + kinds = [] + current = error.class + + while current + kinds.push(current.name.to_s.split('::').last) + current = current.superclass + end + + kinds + end + + # Starts one attempt per item, all at once. + # + # This is the only concurrency primitive of the portable subset. Ruby has no promise to + # colour a function with, so the work goes on threads and the caller simply waits. + def self.start_all(run, items, argument) + attempts = Attempts.new(items.length) + + items.each do |item| + Thread.new do + begin + attempts.settled.push([true, run.call(item, argument), []]) + rescue StandardError => e + attempts.settled.push([false, nil, kinds_of(e)]) + end + end + end + + attempts + end + + # The value of the first attempt that succeeds, or nil once every attempt has failed. + def self.first_success(attempts) + while attempts.outcomes.length < attempts.total + outcome = attempts.settled.pop + attempts.outcomes.push(outcome) + + return outcome[1] if outcome[0] + end + + nil + end + + # Whether any attempt failed with a given error kind. + def self.any_failed_with(attempts, kind) + attempts.outcomes.any? { |ok, _value, kinds| !ok && kinds.include?(kind) } + end end end diff --git a/spec/bridge/compiler/runtime/rust.rs b/spec/bridge/compiler/runtime/rust.rs index 5052ade32..78852747d 100644 --- a/spec/bridge/compiler/runtime/rust.rs +++ b/spec/bridge/compiler/runtime/rust.rs @@ -170,3 +170,236 @@ pub fn data_rows(table: &'static Dataset, key: &str) -> Vec { None => Vec::new(), } } + +/// What a provider answered: the HTTP status, whether it counts as a success, and the body. +pub struct HttpResponse { + pub status: i64, + pub ok: bool, + pub body: serde_json::Value, +} + +/// The origin every request is sent to instead of its own, when one is set. +/// +/// This is the conformance hook: the cross language replay points all seven targets at one +/// local server, the same way the JavaScript suite points fetch at a mock. +fn http_target(url: &str) -> String { + let base = std::env::var("BRUTILS_BRIDGE_HTTP_ORIGIN").unwrap_or_default(); + + if base.is_empty() { + return url.to_string(); + } + + let without_scheme = url + .strip_prefix("https://") + .or_else(|| url.strip_prefix("http://")) + .unwrap_or(url); + + format!("{}/{}", base, without_scheme) +} + +/// Performs an HTTP GET, retrying a transient transport failure with a linear backoff. +pub fn http_get(url: &str, retries: i64, retry_delay_ms: i64) -> HttpResponse { + let target = http_target(url); + let agent: ureq::Agent = ureq::Agent::config_builder() + .http_status_as_error(false) + .timeout_global(Some(std::time::Duration::from_secs(15))) + .build() + .into(); + let mut attempt: i64 = 0; + + loop { + match agent.get(&target).call() { + Ok(mut answer) => { + let status = i64::from(answer.status().as_u16()); + let body = answer + .body_mut() + .read_to_string() + .ok() + .and_then(|text| serde_json::from_str(&text).ok()) + .unwrap_or(serde_json::Value::Null); + + return HttpResponse { + status, + ok: (200..300).contains(&status), + body, + }; + } + Err(_) => { + if attempt >= retries { + return HttpResponse { + status: 0, + ok: false, + body: serde_json::Value::Null, + }; + } + + std::thread::sleep(std::time::Duration::from_millis( + (retry_delay_ms * (attempt + 1)) as u64, + )); + attempt += 1; + } + } + } +} + +/// Whether a list holds a value. +pub fn list_has(items: &[&str], value: &str) -> bool { + items.iter().any(|item| *item == value) +} + +/// Reads one field of a JSON body, treating anything that is not an object as empty. +fn json_field<'a>(body: &'a serde_json::Value, key: &str) -> Option<&'a serde_json::Value> { + body.as_object().and_then(|object| object.get(key)) +} + +/// Reads a string field of a JSON body, answering "" when it is missing or not a string. +pub fn json_string(body: &serde_json::Value, key: &str) -> String { + match json_field(body, key).and_then(serde_json::Value::as_str) { + Some(found) => found.to_string(), + None => String::new(), + } +} + +/// Reads an integer field of a JSON body, answering -1 when it is missing or not a number. +pub fn json_int(body: &serde_json::Value, key: &str) -> i64 { + match json_field(body, key).and_then(serde_json::Value::as_f64) { + Some(found) => found as i64, + None => -1, + } +} + +/// Whether a field of a JSON body is truthy, the way JavaScript reads truthiness. +pub fn json_truthy(body: &serde_json::Value, key: &str) -> bool { + match json_field(body, key) { + None | Some(serde_json::Value::Null) => false, + Some(serde_json::Value::Bool(found)) => *found, + Some(serde_json::Value::Number(found)) => found.as_f64().unwrap_or(0.0) != 0.0, + Some(serde_json::Value::String(found)) => !found.is_empty(), + Some(_) => true, + } +} + +/// Whether a field of a JSON body is exactly true. +pub fn json_is_true(body: &serde_json::Value, key: &str) -> bool { + json_field(body, key) == Some(&serde_json::Value::Bool(true)) +} + +/// A failure raised by the generated code. Rust has no exception hierarchy, so the kinds the +/// source declared travel with the value. +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct Error { + pub kinds: Vec<&'static str>, + pub message: String, +} + +impl Error { + /// Builds a failure of the given kinds. + pub fn new(kinds: &[&'static str], message: &str) -> Self { + Self { + kinds: kinds.to_vec(), + message: message.to_string(), + } + } + + /// The most specific kind of the failure. + pub fn kind(&self) -> &str { + self.kinds.first().copied().unwrap_or("") + } + + /// Whether the failure is of a kind, its bases included. + pub fn is_kind(&self, kind: &str) -> bool { + self.kinds.iter().any(|candidate| *candidate == kind) + } +} + +impl std::fmt::Display for Error { + fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(formatter, "{}", self.message) + } +} + +impl std::error::Error for Error {} + +/// What one attempt of a race ended with. +pub struct Outcome { + pub ok: bool, + pub value: Option, + pub kinds: Vec<&'static str>, +} + +/// The running attempts of a race, and what each one ended with. +pub struct Attempts { + settled: std::sync::mpsc::Receiver>, + total: usize, + pub outcomes: Vec>, +} + +/// Starts one attempt per item, all at once. +/// +/// This is the only concurrency primitive of the portable subset. Rust has no runtime to await +/// on by default, so the work goes on threads and the caller simply waits. +pub fn start_all( + run: fn(&str, &str) -> Result, + items: &[String], + argument: &str, +) -> Attempts { + let (sender, settled) = std::sync::mpsc::channel(); + + for item in items { + let sender = sender.clone(); + let item = item.clone(); + let argument = argument.to_string(); + + std::thread::spawn(move || { + let outcome = match run(&item, &argument) { + Ok(value) => Outcome { + ok: true, + value: Some(value), + kinds: Vec::new(), + }, + Err(error) => Outcome { + ok: false, + value: None, + kinds: error.kinds, + }, + }; + + let _ = sender.send(outcome); + }); + } + + Attempts { + settled, + total: items.len(), + outcomes: Vec::new(), + } +} + +/// The value of the first attempt that succeeds, or nothing once every attempt has failed. +pub fn first_success(attempts: &mut Attempts) -> Option { + while attempts.outcomes.len() < attempts.total { + let Ok(mut outcome) = attempts.settled.recv() else { + return None; + }; + + if outcome.ok { + let value = outcome.value.take(); + + attempts.outcomes.push(outcome); + + return value; + } + + attempts.outcomes.push(outcome); + } + + None +} + +/// Whether any attempt failed with a given error kind. +pub fn any_failed_with(attempts: &Attempts, kind: &str) -> bool { + attempts + .outcomes + .iter() + .any(|outcome| !outcome.ok && outcome.kinds.iter().any(|candidate| *candidate == kind)) +} diff --git a/spec/bridge/compiler/runtime/typescript.ts b/spec/bridge/compiler/runtime/typescript.ts index b8db764b3..8d27ee1e2 100644 --- a/spec/bridge/compiler/runtime/typescript.ts +++ b/spec/bridge/compiler/runtime/typescript.ts @@ -181,3 +181,278 @@ export const dataAll = (table: Dataset): string[][] => table.all; * @returns {string[][]} The rows, empty when the key is unknown. */ export const dataRows = (table: Dataset, key: string): string[][] => table.byKey.get(key) ?? []; + +/** What a provider answered: the HTTP status, whether it counts as a success, and the body. */ +export type HttpResponse = { + readonly status: number; + readonly ok: boolean; + readonly body: unknown; +}; + +/** + * The transport failures worth retrying. `fetch` reports them on the error or on its cause, + * and a failure that is not one of these is an answer, not a hiccup. + */ +const RETRYABLE_ERROR_CODES = new Set([ + "UND_ERR_SOCKET", + "UND_ERR_CONNECT_TIMEOUT", + "UND_ERR_HEADERS_TIMEOUT", + "UND_ERR_BODY_TIMEOUT", + "ECONNRESET", + "ECONNREFUSED", + "EHOSTUNREACH", + "ENETUNREACH", + "ETIMEDOUT", +]); + +/** The `code` of an error, or of its cause. */ +const errorCode = (error: unknown): string | undefined => { + if (error === null || typeof error !== "object") return undefined; + + const code = "code" in error ? error.code : undefined; + + if (typeof code === "string") return code; + + const cause = "cause" in error ? error.cause : undefined; + + if (cause === null || cause === undefined || typeof cause !== "object") return undefined; + + const causeCode = "code" in cause ? cause.code : undefined; + + return typeof causeCode === "string" ? causeCode : undefined; +}; + +/** Whether a `fetch` rejection is a transient transport failure. */ +const isRetryable = (error: unknown): boolean => { + const code = errorCode(error); + + if (code !== undefined && RETRYABLE_ERROR_CODES.has(code)) return true; + if (!(error instanceof Error)) return false; + + return error.message.toLowerCase().includes("fetch failed"); +}; + +/** + * The origin every request is sent to instead of its own, when one is set. + * + * This is the conformance hook: the cross language replay points all seven targets at one local + * server, the same way the JavaScript suite points `fetch` at a mock. + */ +const origin = (url: string): string => { + const base = globalThis.process?.env?.["BRUTILS_BRIDGE_HTTP_ORIGIN"]; + + if (base === undefined || base === "") return url; + + return `${base}/${url.replace(/^https?:\/\//, "")}`; +}; + +/** + * Performs an HTTP GET, retrying a transient transport failure with a linear backoff. + * + * @param {string} url - The URL to read. + * @param {number} retries - How many retries follow the first attempt. + * @param {number} retryDelayMs - The base delay, multiplied by the attempt number. + * @returns {Promise} The response; `status` is 0 when nothing reached the server. + */ +export const httpGet = async ( + url: string, + retries: number, + retryDelayMs: number, +): Promise => { + const target = origin(url); + + for (let attempt = 0; ; attempt++) { + try { + const response = await fetch(target); + let body: unknown; + + try { + body = await response.json(); + } catch { + body = undefined; + } + + return { status: response.status, ok: response.ok, body }; + } catch (error) { + if (attempt >= retries || !isRetryable(error)) + return { status: 0, ok: false, body: undefined }; + } + + const delay = retryDelayMs * (attempt + 1); + + await new Promise((resolve) => { + setTimeout(resolve, delay); + }); + } +}; + +/** + * Whether the caller handed a number where a `string | number` was declared. + * + * @param {unknown} value - The value. + * @returns {boolean} True when it is a number. + */ +export const isNumber = (value: unknown): boolean => typeof value === "number"; + +/** + * Whether a value is a list. + * + * @param {unknown} value - The value. + * @returns {boolean} True when it is a list. + */ +export const isList = (value: unknown): value is unknown[] => Array.isArray(value); + +/** + * Whether a list holds a value. + * + * @param {string[]} list - The list. + * @param {string} value - The value to look for. + * @returns {boolean} True when the list holds it. + */ +export const listHas = (list: readonly string[], value: string): boolean => list.includes(value); + +/** Reads one field of a JSON body, treating anything that is not an object as empty. */ +const jsonField = (body: unknown, key: string): unknown => { + if (body === null || typeof body !== "object" || Array.isArray(body)) return undefined; + + return Object.hasOwn(body, key) ? (body as Record)[key] : undefined; +}; + +/** + * Reads a string field of a JSON body, answering `""` when it is missing or not a string. + * + * @param {unknown} body - The body. + * @param {string} key - The field name. + * @returns {string} The value, or `""`. + */ +export const jsonString = (body: unknown, key: string): string => { + const found = jsonField(body, key); + + return typeof found === "string" ? found : ""; +}; + +/** + * Reads an integer field of a JSON body, answering `-1` when it is missing or not a number. + * + * @param {unknown} body - The body. + * @param {string} key - The field name. + * @returns {number} The value, or `-1`. + */ +export const jsonInt = (body: unknown, key: string): number => { + const found = jsonField(body, key); + + return typeof found === "number" ? Math.trunc(found) : -1; +}; + +/** + * Whether a field of a JSON body is truthy, the way JavaScript reads truthiness. + * + * @param {unknown} body - The body. + * @param {string} key - The field name. + * @returns {boolean} True when the field is set and truthy. + */ +export const jsonTruthy = (body: unknown, key: string): boolean => Boolean(jsonField(body, key)); + +/** + * Whether a field of a JSON body is exactly `true`. + * + * @param {unknown} body - The body. + * @param {string} key - The field name. + * @returns {boolean} True when the field is the boolean `true`. + */ +export const jsonIsTrue = (body: unknown, key: string): boolean => jsonField(body, key) === true; + +/** What one attempt of a race ended with. */ +type Outcome = { ok: boolean; value?: T; kinds: string[] }; + +/** The running attempts of a race, and what each one ended with. */ +export type Attempts = { settled: Promise>[]; outcomes: Outcome[] }; + +/** The error name and every name it inherits from, which is what a failure is matched on. */ +const kindsOf = (error: unknown): string[] => { + const kinds: string[] = []; + + for ( + let current: unknown = error; + current instanceof Error; + current = Object.getPrototypeOf(current) as unknown + ) { + const name = (current.constructor as { name?: string } | undefined)?.name; + + if (name !== undefined && name !== "" && !kinds.includes(name)) kinds.push(name); + } + + return kinds; +}; + +/** + * Starts one attempt per item, all at once. + * + * @param {Function} run - The function to run per item. + * @param {string[]} items - The items. + * @param {string} argument - A second argument handed to every call. + * @returns {Attempts} The running attempts. + */ +export const startAll = ( + run: (item: never, argument: string) => T | Promise, + items: readonly string[], + argument: string, +): Attempts => { + const attempts: Attempts = { settled: [], outcomes: [] }; + + for (const item of items) { + attempts.settled.push( + Promise.resolve() + .then(async (): Promise> => ({ + ok: true, + value: await run(item as never, argument), + kinds: [], + })) + .catch((error: unknown): Outcome => ({ ok: false, kinds: kindsOf(error) })) + .then((outcome) => { + attempts.outcomes.push(outcome); + + return outcome; + }), + ); + } + + return attempts; +}; + +/** + * The value of the first attempt that succeeds, or nothing once every attempt has failed. + * + * @param {Attempts} attempts - The running attempts. + * @returns {Promise} The value, or `undefined`. + */ +export const firstSuccess = async (attempts: Attempts): Promise => { + const waiting = new Map( + attempts.settled.map((settled, index) => [ + index, + settled.then((outcome) => ({ index, outcome })), + ]), + ); + + while (waiting.size > 0) { + // The attempts are already running; this only picks whichever lands first. + // eslint-disable-next-line no-await-in-loop + const { index, outcome } = await Promise.race(waiting.values()); + + waiting.delete(index); + + if (outcome.ok) return outcome.value; + } + + return undefined; +}; + +/** + * Whether any attempt failed with a given error kind. + * + * @param {Attempts} attempts - The attempts. + * @param {string} kind - The error name to look for. + * @returns {boolean} True when at least one attempt failed with it. + */ +export const anyFailedWith = (attempts: Attempts, kind: string): boolean => + attempts.outcomes.some((outcome) => !outcome.ok && outcome.kinds.includes(kind)); diff --git a/spec/bridge/compiler/targets/csharp.ts b/spec/bridge/compiler/targets/csharp.ts index 6cffd6362..3a2b1a5e5 100644 --- a/spec/bridge/compiler/targets/csharp.ts +++ b/spec/bridge/compiler/targets/csharp.ts @@ -7,16 +7,18 @@ */ import { readFileSync } from "node:fs"; import { resolve } from "node:path"; -import type { - CharClass, - DataDecl, - Expr, - FuncDecl, - Module, - PatternDecl, - Stmt, - StructDecl, - Ty, + +import { + type CharClass, + type DataDecl, + type ErrorDecl, + type Expr, + type FuncDecl, + type Module, + type PatternDecl, + type Stmt, + type StructDecl, + type Ty, } from "../ir.ts"; import { optionReads, pascal, prose, screaming } from "../kit.ts"; @@ -26,11 +28,15 @@ let structs = new Map(); /** The declared types in scope, so a list knows whether it is an array or a growing list. */ let localTypes = new Map(); +/** The functions that wait on the network, and are therefore `async` here. */ +let blocking = new Set(); + /** Splits a list into fixed size chunks, so no one method carries the whole table. */ const chunks = (items: T[], size: number): T[][] => { const out: T[][] = []; - for (let index = 0; index < items.length; index += size) out.push(items.slice(index, index + size)); + for (let index = 0; index < items.length; index += size) + out.push(items.slice(index, index + size)); return out; }; @@ -101,23 +107,34 @@ const type = (ty: Ty): string => { case "string": case "scalar": case "json": - case "enum": + case "enum": { return "string"; - case "int": + } + case "int": { return "long"; - case "bool": + } + case "bool": { return "bool"; - case "void": + } + case "void": { return "void"; - case "list": - // A list of records is built by appending, which an array cannot do. - return ty.of.k === "named" - ? `System.Collections.Generic.List<${type(ty.of)}>` - : `${type(ty.of)}[]`; - case "opt": - return `${type(ty.of)}?`; - case "named": + } + case "list": { + // Only the integer lists stay arrays: they are the hot path. Everything else is a + // List, which is what appending needs and what a C# caller expects. + return ty.of.k === "int" ? "long[]" : `System.Collections.Generic.List<${type(ty.of)}>`; + } + case "opt": { + // A reference is already "or nothing"; only the value types need the annotation. + return ty.of.k === "int" || ty.of.k === "bool" ? `${type(ty.of)}?` : type(ty.of); + } + case "named": { + // The runtime declares its own records beside the generated ones, in the same namespace. return ty.name; + } + case "tasks": { + return `Attempts<${type(ty.of)}>`; + } } }; @@ -139,45 +156,64 @@ const OPS: Record = { /** Renders an expression. */ const expr = (node: Expr): string => { switch (node.k) { - case "str": + case "str": { return lit(node.value); - case "int": + } + case "int": { return `${node.value}L`; - case "bool": + } + case "bool": { return String(node.value); - case "none": + } + case "none": { return "null"; - case "ref": + } + case "ref": { return verbatim.has(node.name) ? screaming(node.name) : safe(node.name); - case "field": + } + case "field": { return `${expr(node.target)}.${pascal(node.name)}`; - case "index": + } + case "index": { return `${expr(node.target)}[(int) ${expr(node.index)}]`; - case "not": + } + case "not": { return `!${expr(node.operand)}`; - case "bin": + } + case "bin": { return `(${expr(node.left)} ${OPS[node.op]} ${expr(node.right)})`; - case "cond": + } + case "cond": { return `(${expr(node.test)} ? ${expr(node.whenTrue)} : ${expr(node.whenFalse)})`; - case "listOf": - if (node.of.k === "named") - return `new System.Collections.Generic.List<${type(node.of)}>()`; - - return `{ ${node.items.map((item) => expr(item)).join(", ")} }`; + } + case "listOf": { + if (node.of.k !== "int") + return `new System.Collections.Generic.List<${type(node.of)}> { ${node.items + .map((item) => expr(item)) + .join(", ")} }`; + + // A collection initializer without `new T[]` is only valid in a declaration. + return `new long[] { ${node.items.map((item) => expr(item)).join(", ")} }`; + } case "struct": { const declared = structs.get(node.name); const order = declared?.fields.map((field) => field.name) ?? node.fields.map((f) => f.name); return `new ${node.name}(${order - .map((name) => expr(node.fields.find((field) => field.name === name)?.value ?? { k: "none" })) + .map((name) => + expr(node.fields.find((field) => field.name === name)?.value ?? { k: "none" }), + ) .join(", ")})`; } - case "optionField": + case "optionField": { return `${safe(node.target)}${pascal(node.field)}`; - case "call": + } + case "await": { + return `await ${expr(node.value)}`; + } + case "call": { return call(node); - default: - throw new Error(`csharp: unsupported expression ${node.k}`); + } } }; @@ -187,54 +223,107 @@ const isGrowing = (node: Expr): boolean => { const ty = localTypes.get(node.name); - return ty !== undefined && ty.k === "list" && ty.of.k === "named"; + return ty?.k === "list" && ty.of.k !== "int"; }; /** Renders a call. */ const call = (node: Extract): string => { const args = node.args.map((argument) => expr(argument)); - if (node.callee.k === "user") return `${pascal(node.callee.name)}(${args.join(", ")})`; + if (node.callee.k === "user") + return `${blocking.has(node.callee.name) ? "await " : ""}${pascal(node.callee.name)}(${args.join(", ")})`; switch (node.callee.name) { - case "len": + case "len": { return `(long) ${args[0]}.Length`; - case "listLen": + } + case "listLen": { return isGrowing(node.args[0]) ? `(long) ${args[0]}.Count` : `(long) ${args[0]}.Length`; - case "codeAt": + } + case "isNumber": { + // C#'s parameter is a string, so the question cannot arise. + return "false"; + } + case "isList": { + return "true"; + } + case "listHas": { + return `Net.ListHas(${args[0]}, ${args[1]})`; + } + case "httpGet": { + return `await Net.HttpGet(${args.join(", ")})`; + } + case "jsonString": { + return `Net.JsonString(${args[0]}, ${args[1]})`; + } + case "jsonInt": { + return `Net.JsonInt(${args[0]}, ${args[1]})`; + } + case "jsonTruthy": { + return `Net.JsonTruthy(${args[0]}, ${args[1]})`; + } + case "jsonIsTrue": { + return `Net.JsonIsTrue(${args[0]}, ${args[1]})`; + } + case "startAll": { + return `Net.StartAll(${pascal(node.args[0].k === "ref" ? node.args[0].name : "")}, ${args[1]}, ${args[2]})`; + } + case "firstSuccess": { + return `await Net.FirstSuccess(${args[0]})`; + } + case "anyFailedWith": { + return `Net.AnyFailedWith(${args[0]}, ${args[1]})`; + } + case "codeAt": { return `Runtime.CodeAt(${args[0]}, ${args[1]})`; - case "slice": + } + case "slice": { return `Runtime.Slice(${args[0]}, ${args[1]}, ${args[2]})`; - case "upper": + } + case "upper": { return `${args[0]}.ToUpperInvariant()`; - case "trim": + } + case "trim": { return `Runtime.JsTrim(${args[0]})`; - case "padStart": + } + case "padStart": { return `Runtime.PadStart(${args[0]}, ${args[1]}, ${args[2]})`; - case "repeat": + } + case "repeat": { return `Runtime.Repeat(${args[0]}, ${args[1]})`; - case "classHas": + } + case "classHas": { return `Runtime.ClassHas(${args[0]}, ${args[1]})`; - case "keepClass": + } + case "keepClass": { return `Runtime.KeepClass(${args[0]}, ${args[1]})`; - case "patternTest": + } + case "patternTest": { return `Runtime.PatternTest(${args[0]}, ${args[1]})`; - case "asString": + } + case "asString": { // C#'s types already guarantee a string at the boundary. return args[0]; - case "isTruthy": + } + case "isTruthy": { return args[0]; - case "listPush": + } + case "listPush": { return `${args[0]}.Add(${args[1]})`; - case "unwrap": + } + case "unwrap": { // C# has no separate optional value to open; a reference is already nullable. return args[0]; - case "dataAll": + } + case "dataAll": { return `Runtime.DataAll(${args[0]})`; - case "dataRows": + } + case "dataRows": { return `Runtime.DataRows(${args[0]}, ${args[1]})`; - default: + } + default: { throw new Error(`csharp: unsupported runtime call ${node.callee.name}`); + } } }; @@ -248,12 +337,14 @@ const block = (body: Stmt[], indent: string): string => /** Renders one statement. */ const stmt = (node: Stmt, indent: string): string => { switch (node.k) { - case "let": + case "let": { localTypes.set(node.name, node.ty); return `${indent}${type(node.ty)} ${safe(node.name)} = ${expr(node.value)};`; - case "assign": + } + case "assign": { return `${indent}${safe(node.name)} = ${expr(node.value)};`; + } case "if": { const otherwise = node.otherwise.length === 0 @@ -262,12 +353,23 @@ const stmt = (node: Stmt, indent: string): string => { return `${indent}if (${expr(node.test)})\n${indent}{\n${block(node.then, `${indent} `)}\n${indent}}${otherwise}`; } - case "return": + case "return": { return node.value === undefined ? `${indent}return;` : `${indent}return ${expr(node.value)};`; - case "forRange": + } + case "throw": { + return `${indent}throw new ${node.error}(${expr(node.message)});`; + } + case "try": { + return `${indent}try\n${indent}{\n${block(node.body, `${indent} `)}\n${indent}}\n${indent}catch (System.Exception ${node.catchName})\n${indent}{\n${block(node.catchBody, `${indent} `)}\n${indent}}`; + } + case "forRange": { return `${indent}for (long ${safe(node.name)} = ${expr(node.from)}; ${safe(node.name)} < ${expr(node.until)}; ${safe(node.name)}++)\n${indent}{\n${block(node.body, `${indent} `)}\n${indent}}`; - case "forOf": + } + case "forOf": { + localTypes.set(node.name, node.ty); + return `${indent}foreach (var ${safe(node.name)} in ${expr(node.iterable)})\n${indent}{\n${block(node.body, `${indent} `)}\n${indent}}`; + } case "expr": { const value = node.value; @@ -280,8 +382,6 @@ const stmt = (node: Stmt, indent: string): string => { return `${indent}${expr(value)};`; } - default: - throw new Error(`csharp: unsupported statement ${node.k}`); } }; @@ -303,7 +403,7 @@ const struct = (entry: StructDecl): string => { const fields = entry.fields .map( (field) => - `${field.doc === "" ? "" : ` /// ${field.doc}\n`} public ${type(field.ty)}${entry.isOptions ? "?" : ""} ${pascal(field.name)} { get; set; }`, + `${field.doc === "" ? "" : ` /// ${field.doc}\n`} public ${type(field.ty)}${entry.isOptions && (field.ty.k === "int" || field.ty.k === "bool") ? "?" : ""} ${pascal(field.name)} { get; set; }`, ) .join("\n\n"); // An options record is filled in property by property; a value record is built in one go. @@ -322,13 +422,24 @@ ${fields}${constructor} }`; }; +/** Renders an error type. C# has real inheritance, so the hierarchy is the declaration. */ +const error = (entry: ErrorDecl): string => + ` /// ${entry.doc === "" ? entry.name : entry.doc} + public class ${entry.name} : ${entry.base ?? "System.Exception"} + { + public ${entry.name}(string message) : base(message) + { + } + }`; + /** Renders a dataset as the tables the runtime materialises, chunked so no method carries * the whole thing. */ const data = (entry: DataDecl): string => { const name = pascal(entry.name.toLowerCase()); const rowChunks = chunks( entry.rows.map( - (row, index) => ` rows[${index}] = new[] { ${row.map((cell) => lit(cell)).join(", ")} };`, + (row, index) => + ` rows[${index}] = new[] { ${row.map((cell) => lit(cell)).join(", ")} };`, ), 200, ); @@ -353,11 +464,11 @@ ${rowChunks.map((_, index) => ` ${name}Rows${index}(rows);`).join("\n } ${rowChunks - .map( - (chunk, index) => - ` private static void ${name}Rows${index}(string[][] rows)\n {\n${chunk.join("\n")}\n }`, - ) - .join("\n\n")} + .map( + (chunk, index) => + ` private static void ${name}Rows${index}(string[][] rows)\n {\n${chunk.join("\n")}\n }`, + ) + .join("\n\n")} private static int[][] ${name}Groups() { @@ -367,11 +478,11 @@ ${groupChunks.map((_, index) => ` ${name}Groups${index}(groups);`).jo } ${groupChunks - .map( - (chunk, index) => - ` private static void ${name}Groups${index}(int[][] groups)\n {\n${chunk.join("\n")}\n }`, - ) - .join("\n\n")}`; + .map( + (chunk, index) => + ` private static void ${name}Groups${index}(int[][] groups)\n {\n${chunk.join("\n")}\n }`, + ) + .join("\n\n")}`; }; /** Renders one function. */ @@ -387,10 +498,14 @@ const func = (entry: FuncDecl): string => { const prologue = optionReads(entry) .map((read) => { const local = `${safe(read.target)}${pascal(read.field)}`; + const ty = read.expr.k === "optionField" ? read.expr.ty : ({ k: "int" } as Ty); const fallback = read.expr.k === "optionField" ? expr(read.expr.fallback) : "null"; - const declared = read.expr.k === "optionField" && read.expr.ty.k === "bool" ? "bool" : "long"; + const primitive = ty.k === "bool" || ty.k === "int"; + const declared = ty.k === "bool" ? "bool" : ty.k === "int" ? "long" : type(ty); + + localTypes.set(local, ty); - return ` ${declared} ${local} = ${fallback};\n if (${safe(read.target)} != null && ${safe(read.target)}.${pascal(read.field)} != null)\n {\n ${local} = ${safe(read.target)}.${pascal(read.field)}.Value;\n }`; + return ` ${declared} ${local} = ${fallback};\n if (${safe(read.target)} != null && ${safe(read.target)}.${pascal(read.field)} != null)\n {\n ${local} = ${safe(read.target)}.${pascal(read.field)}${primitive ? ".Value" : ""};\n }`; }) .join("\n"); const doc = prose(entry.doc); @@ -402,7 +517,13 @@ const func = (entry: FuncDecl): string => { .map((line) => ` /// ${line}`.trimEnd()) .join("\n")}\n /// \n`; - return `${comment} public static ${type(entry.ret)} ${pascal(entry.name)}(${params}) + // A function that waits on the network is a Task here even though the source is written + // straight-line: colouring the call graph is the emitter's job, not the author's. + const returns = entry.blocking + ? `async System.Threading.Tasks.Task<${type(entry.ret)}>` + : type(entry.ret); + + return `${comment} public static ${returns} ${pascal(entry.name)}(${params}) { ${prologue === "" ? "" : `${prologue}\n`}${block(entry.body, " ")} }`; @@ -416,6 +537,7 @@ ${prologue === "" ? "" : `${prologue}\n`}${block(entry.body, " ")} */ export const emit = (module: Module): Record => { structs = new Map(module.structs.map((entry) => [entry.name, entry])); + blocking = new Set(module.functions.filter((entry) => entry.blocking).map((entry) => entry.name)); verbatim = new Set([ ...module.charClasses.map((entry) => entry.name), ...module.patterns.map((entry) => entry.name), @@ -427,8 +549,8 @@ export const emit = (module: Module): Record => { const constants = module.constants .map((entry) => entry.ty.k === "list" - ? ` private static readonly long[] ${screaming(entry.name)} = ${expr(entry.expr)};` - : ` private const string ${screaming(entry.name)} = ${expr(entry.expr)};`, + ? ` private static readonly ${type(entry.ty)} ${screaming(entry.name)} = ${expr(entry.expr)};` + : ` private const ${type(entry.ty)} ${screaming(entry.name)} = ${expr(entry.expr)};`, ) .join("\n"); @@ -441,6 +563,9 @@ export const emit = (module: Module): Record => { BrazilianUtilsBridge BrazilianUtils.Bridge Exe + + CS0162 `, @@ -448,7 +573,12 @@ export const emit = (module: Module): Record => { namespace ${NAMESPACE} { -${module.structs.map((entry) => struct(entry)).join("\n\n")} +${module.errors.map((entry) => error(entry)).join("\n\n")} + +${module.structs + .filter((entry) => entry.external !== true) + .map((entry) => struct(entry)) + .join("\n\n")} /// ${module.doc} public static class ${className} diff --git a/spec/bridge/compiler/targets/go.ts b/spec/bridge/compiler/targets/go.ts index 75346ec40..9535b3381 100644 --- a/spec/bridge/compiler/targets/go.ts +++ b/spec/bridge/compiler/targets/go.ts @@ -7,23 +7,28 @@ */ import { readFileSync } from "node:fs"; import { resolve } from "node:path"; -import type { - CharClass, - DataDecl, - Expr, - FuncDecl, - Module, - PatternDecl, - Stmt, - StructDecl, - Ty, + +import { + type CharClass, + type DataDecl, + type ErrorDecl, + type Expr, + type FuncDecl, + type Module, + type PatternDecl, + type Stmt, + type StructDecl, + type Ty, } from "../ir.ts"; import { optionReads, pascal, prose, screaming } from "../kit.ts"; const RUNTIME = resolve(import.meta.dirname, "../runtime/go.go"); -/** Module level names the emitter writes verbatim. */ -let verbatim = new Set(); +/** The functions that return an error alongside their value. */ +let throwing = new Set(); + +/** The function being rendered, so a return knows whether to carry a nil error. */ +let current: FuncDecl | undefined; /** Renders a string as a Go literal. */ const lit = (value: string): string => { @@ -47,22 +52,34 @@ const type = (ty: Ty): string => { switch (ty.k) { case "string": case "scalar": - case "enum": + case "enum": { return "string"; - case "int": + } + case "int": { return "int64"; - case "bool": + } + case "bool": { return "bool"; - case "void": + } + case "void": { return ""; - case "json": + } + case "json": { return "any"; - case "list": + } + case "list": { return `[]${type(ty.of)}`; - case "opt": - return `*${type(ty.of)}`; - case "named": + } + case "opt": { + // A pointer is already "or nothing"; a record is already a pointer. + return ty.of.k === "named" ? type(ty.of) : `*${type(ty.of)}`; + } + case "named": { return `*${ty.name}`; + } + case "tasks": { + return "*runtime.Attempts"; + } } }; @@ -84,38 +101,75 @@ const OPS: Record = { /** Renders an expression. */ const expr = (node: Expr): string => { switch (node.k) { - case "str": + case "str": { return lit(node.value); - case "int": + } + case "int": { return String(node.value); - case "bool": + } + case "bool": { return String(node.value); - case "none": + } + case "none": { return "nil"; - case "ref": - return verbatim.has(node.name) ? node.name : node.name; - case "field": + } + case "ref": { + // Go's exported names are already the source's, constants included. + return node.name; + } + case "field": { return `${expr(node.target)}.${pascal(node.name)}`; - case "index": + } + case "index": { return `${expr(node.target)}[${expr(node.index)}]`; - case "not": + } + case "not": { return `!${expr(node.operand)}`; - case "bin": + } + case "bin": { return `(${expr(node.left)} ${OPS[node.op]} ${expr(node.right)})`; - case "cond": + } + case "cond": { throw new Error("go: the ternary operator has no Go form; use an if statement"); - case "listOf": + } + case "listOf": { return `[]${type(node.of)}{${node.items.map((item) => expr(item)).join(", ")}}`; - case "struct": + } + case "struct": { return `&${node.name}{${node.fields .map((field) => `${pascal(field.name)}: ${expr(field.value)}`) .join(", ")}}`; - case "optionField": + } + case "optionField": { return `${node.target}${pascal(node.field)}`; - case "call": + } + case "await": { + // The blocking targets have nothing to wait on: the call has already returned. + return expr(node.value); + } + case "call": { return call(node); - default: - throw new Error(`go: unsupported expression ${node.k}`); + } + } +}; + +/** The zero value of a type, which is what a raising function returns alongside its error. */ +const zero = (ty: Ty): string => { + switch (ty.k) { + case "int": { + return "0"; + } + case "bool": { + return "false"; + } + case "string": + case "scalar": + case "enum": { + return `""`; + } + default: { + return "nil"; + } } }; @@ -125,45 +179,102 @@ const call = (node: Extract): string => { if (node.callee.k === "user") return `${node.callee.name}(${args.join(", ")})`; + if (node.callee.name === "startAll") { + const started = node.args[0].k === "ref" ? node.args[0].name : ""; + + return `runtime.StartAll(func(item string, argument string) (any, error) { return ${started}(item, argument) }, ${args[1]}, ${args[2]})`; + } + + if (node.callee.name === "firstSuccess") + return `runtime.FirstSuccessOf[${type(node.ty.k === "opt" ? node.ty.of : node.ty)}](${args[0]})`; + switch (node.callee.name) { - case "len": + case "len": { return `int64(runtime.Len(${args[0]}))`; - case "listLen": + } + case "listLen": { return `int64(len(${args[0]}))`; - case "codeAt": + } + case "codeAt": { return `int64(runtime.CodeAt(${args[0]}, int(${args[1]})))`; - case "slice": + } + case "slice": { return `runtime.Slice(${args[0]}, int(${args[1]}), int(${args[2]}))`; - case "upper": + } + case "upper": { return `runtime.Upper(${args[0]})`; - case "trim": + } + case "trim": { return `runtime.JsTrim(${args[0]})`; - case "padStart": + } + case "padStart": { return `runtime.PadStart(${args[0]}, int(${args[1]}), ${args[2]})`; - case "repeat": + } + case "repeat": { return `runtime.Repeat(${args[0]}, int(${args[1]}))`; - case "classHas": + } + case "classHas": { return `runtime.ClassHas(${args[0]}, ${args[1]})`; - case "keepClass": + } + case "keepClass": { return `runtime.KeepClass(${args[0]}, ${args[1]})`; - case "patternTest": + } + case "patternTest": { return `runtime.PatternTest(${args[0]}, ${args[1]})`; - case "asString": + } + case "asString": { // Go's type system already guarantees a string at the boundary. return args[0]; - case "isTruthy": + } + case "isTruthy": { return args[0]; - case "listPush": + } + case "listPush": { // `append` returns a new slice, so a push is an assignment; it is only ever a statement. return `${args[0]} = append(${args[0]}, ${args[1]})`; - case "unwrap": - return `*${args[0]}`; - case "dataAll": + } + case "unwrap": { + // A record is already a pointer, and the prologue has already opened every option + // read; only an optional parameter is still behind one. + return node.ty.k === "named" || node.args[0].k === "optionField" ? args[0] : `*${args[0]}`; + } + case "dataAll": { return `runtime.DataAll(${args[0]})`; - case "dataRows": + } + case "dataRows": { return `runtime.DataRows(${args[0]}, ${args[1]})`; - default: + } + case "isNumber": { + // Go's parameter is a string, so the question cannot arise. + return "false"; + } + case "isList": { + return "true"; + } + case "listHas": { + return `runtime.ListHas(${args[0]}, ${args[1]})`; + } + case "httpGet": { + return `runtime.HttpGet(${args.join(", ")})`; + } + case "jsonString": { + return `runtime.JsonString(${args[0]}, ${args[1]})`; + } + case "jsonInt": { + return `runtime.JsonInt(${args[0]}, ${args[1]})`; + } + case "jsonTruthy": { + return `runtime.JsonTruthy(${args[0]}, ${args[1]})`; + } + case "jsonIsTrue": { + return `runtime.JsonIsTrue(${args[0]}, ${args[1]})`; + } + case "anyFailedWith": { + return `runtime.AnyFailedWith(${args[0]}, ${args[1]})`; + } + default: { throw new Error(`go: unsupported runtime call ${node.callee.name}`); + } } }; @@ -177,26 +288,52 @@ const block = (body: Stmt[], indent: string): string => /** Renders one statement. */ const stmt = (node: Stmt, indent: string): string => { switch (node.k) { - case "let": + case "let": { // Integers are int64 throughout, so they are declared rather than inferred: `:=` on a // literal would make an `int` that will not compare against the rest. return node.ty.k === "int" ? `${indent}var ${node.name} int64 = ${expr(node.value)}` : `${indent}${node.name} := ${expr(node.value)}`; - case "assign": + } + case "assign": { return `${indent}${node.name} = ${expr(node.value)}`; + } case "if": { const otherwise = - node.otherwise.length === 0 ? "" : ` else {\n${block(node.otherwise, `${indent}\t`)}\n${indent}}`; + node.otherwise.length === 0 + ? "" + : ` else {\n${block(node.otherwise, `${indent}\t`)}\n${indent}}`; return `${indent}if ${expr(node.test)} {\n${block(node.then, `${indent}\t`)}\n${indent}}${otherwise}`; } - case "return": - return node.value === undefined ? `${indent}return` : `${indent}return ${expr(node.value)}`; - case "forRange": + case "return": { + if (current?.throws !== true) + return node.value === undefined ? `${indent}return` : `${indent}return ${expr(node.value)}`; + + // A call to another raising function already carries both values. + if ( + node.value?.k === "call" && + node.value.callee.k === "user" && + throwing.has(node.value.callee.name) + ) + return `${indent}return ${expr(node.value)}`; + + return node.value === undefined + ? `${indent}return nil` + : `${indent}return ${expr(node.value)}, nil`; + } + case "try": { + throw new Error("go: try/catch has no Go form; a raising call answers an error instead"); + } + case "throw": { + return `${indent}return ${current === undefined ? "nil" : zero(current.ret)}, runtime.NewError(${node.error}Kinds, ${expr(node.message)})`; + } + case "forRange": { return `${indent}for ${node.name} := int64(${expr(node.from)}); ${node.name} < ${expr(node.until)}; ${node.name}++ {\n${block(node.body, `${indent}\t`)}\n${indent}}`; - case "forOf": + } + case "forOf": { return `${indent}for _, ${node.name} := range ${expr(node.iterable)} {\n${block(node.body, `${indent}\t`)}\n${indent}}`; + } case "expr": { const value = node.value; @@ -207,8 +344,6 @@ const stmt = (node: Stmt, indent: string): string => { return `${indent}${expr(value)}`; } - default: - throw new Error(`go: unsupported statement ${node.k}`); } }; @@ -225,6 +360,16 @@ const pattern = (entry: PatternDecl): string => ) .join("\n")}\n}`; +/** Renders an error type: its kinds, and the predicate a caller matches on. */ +const error = (entry: ErrorDecl): string => + `// ${entry.name}Kinds names ${entry.name}${entry.doc === "" ? "" : `: ${entry.doc}`} +var ${entry.name}Kinds = []string{${entry.kinds.map((kind) => lit(kind)).join(", ")}} + +// Is${entry.name} reports whether err is a ${entry.name}. +func Is${entry.name}(err error) bool { + return runtime.IsKind(err, ${lit(entry.name)}) +}`; + /** Renders an options record. */ const struct = (entry: StructDecl): string => { const fields = entry.fields @@ -263,17 +408,17 @@ ${groups} /** Renders one function. */ const func = (entry: FuncDecl): string => { + current = entry; + const name = entry.exported ? pascal(entry.name) : entry.name; - const params = entry.params - .map((param) => `${param.name} ${type(param.ty)}`) - .join(", "); + const params = entry.params.map((param) => `${param.name} ${type(param.ty)}`).join(", "); const prologue = optionReads(entry) .map((read) => { const local = `${read.target}${pascal(read.field)}`; + const ty = read.expr.k === "optionField" ? read.expr.ty : ({ k: "int" } as Ty); const fallback = read.expr.k === "optionField" ? expr(read.expr.fallback) : "nil"; - const declared = read.expr.k === "optionField" && read.expr.ty.k === "bool" ? "bool" : "int64"; - return `\tvar ${local} ${declared} = ${fallback}\n\tif ${read.target} != nil && ${read.target}.${pascal(read.field)} != nil {\n\t\t${local} = *${read.target}.${pascal(read.field)}\n\t}`; + return `\tvar ${local} ${type(ty)} = ${fallback}\n\tif ${read.target} != nil && ${read.target}.${pascal(read.field)} != nil {\n\t\t${local} = *${read.target}.${pascal(read.field)}\n\t}`; }) .join("\n"); const doc = prose(entry.doc) @@ -281,7 +426,11 @@ const func = (entry: FuncDecl): string => { .map((line) => `// ${line}`.trimEnd()) .join("\n"); - return `${doc === "" ? "" : `${doc.replace("// ", `// ${name} `)}\n`}func ${name}(${params}) ${type(entry.ret)} { + // Go has no exceptions, so a function that can raise says so in its signature and the + // emitter threads the error through; the source never mentions it. + const returns = entry.throws ? `(${type(entry.ret)}, error)` : type(entry.ret); + + return `${doc === "" ? "" : `${doc.replace("// ", `// ${name} `)}\n`}func ${name}(${params}) ${returns} { ${prologue === "" ? "" : `${prologue}\n`}${block(entry.body, "\t")} }`; }; @@ -293,13 +442,7 @@ ${prologue === "" ? "" : `${prologue}\n`}${block(entry.body, "\t")} * @returns {Record} The files, by path. */ export const emit = (module: Module): Record => { - verbatim = new Set([ - ...module.charClasses.map((entry) => entry.name), - ...module.patterns.map((entry) => entry.name), - ...module.constants.map((entry) => entry.name), - ...module.data.map((entry) => entry.name), - ]); - + throwing = new Set(module.functions.filter((entry) => entry.throws).map((entry) => entry.name)); const constants = module.constants .map((entry) => entry.ty.k === "list" @@ -324,7 +467,12 @@ ${module.patterns.map((entry) => pattern(entry)).join("\n\n")} ${constants} -${module.structs.map((entry) => struct(entry)).join("\n\n")} +${module.errors.map((entry) => error(entry)).join("\n\n")} + +${module.structs + .filter((entry) => entry.external !== true) + .map((entry) => struct(entry)) + .join("\n\n")} ${module.data.map((entry) => data(entry)).join("\n\n")} diff --git a/spec/bridge/compiler/targets/java.ts b/spec/bridge/compiler/targets/java.ts index 55822b147..d18b71378 100644 --- a/spec/bridge/compiler/targets/java.ts +++ b/spec/bridge/compiler/targets/java.ts @@ -7,22 +7,30 @@ */ import { readFileSync } from "node:fs"; import { resolve } from "node:path"; -import type { - CharClass, - DataDecl, - Expr, - FuncDecl, - Module, - PatternDecl, - Stmt, - StructDecl, - Ty, + +import { + type CharClass, + type DataDecl, + type ErrorDecl, + type Expr, + type FuncDecl, + type Module, + type PatternDecl, + type Stmt, + type StructDecl, + type Ty, } from "../ir.ts"; import { optionReads, pascal, prose, screaming } from "../kit.ts"; /** The record types of the module being emitted, so a literal calls the right constructor. */ let structs = new Map(); +/** The records the runtime declares, which are reached through its class. */ +let external = new Set(); + +/** The class the functions are being emitted into, for the method references. */ +let className = ""; + /** The declared types in scope, so a list knows whether it is an array or a growing list. */ let localTypes = new Map(); @@ -30,7 +38,8 @@ let localTypes = new Map(); const chunks = (items: T[], size: number): T[][] => { const out: T[][] = []; - for (let index = 0; index < items.length; index += size) out.push(items.slice(index, index + size)); + for (let index = 0; index < items.length; index += size) + out.push(items.slice(index, index + size)); return out; }; @@ -76,26 +85,39 @@ const type = (ty: Ty): string => { case "string": case "scalar": case "json": - case "enum": + case "enum": { return "String"; - case "int": + } + case "int": { return "long"; - case "bool": + } + case "bool": { return "boolean"; - case "void": + } + case "void": { return "void"; - case "list": - // A list of records is built by appending, which an array cannot do. - return ty.of.k === "named" ? `java.util.List<${type(ty.of)}>` : `${type(ty.of)}[]`; - case "opt": + } + case "list": { + // Only the integer lists stay arrays: they are the hot path, and boxing every element + // of a checksum would cost more than the shape is worth. Everything else is a List, + // which is what appending needs and what a Java caller expects. + return ty.of.k === "int" ? "long[]" : `java.util.List<${type(ty.of)}>`; + } + case "opt": { return type(ty.of); - case "named": - return ty.name; + } + case "named": { + return external.has(ty.name) ? `Runtime.${ty.name}` : ty.name; + } + case "tasks": { + return "Runtime.Attempts"; + } } }; /** The boxed form of a type, for nullable option fields. */ -const boxed = (ty: Ty): string => (ty.k === "int" ? "Long" : ty.k === "bool" ? "Boolean" : type(ty)); +const boxed = (ty: Ty): string => + ty.k === "int" ? "Long" : ty.k === "bool" ? "Boolean" : type(ty); const OPS: Record = { "+": "+", @@ -115,52 +137,73 @@ const OPS: Record = { /** Renders an expression. */ const expr = (node: Expr): string => { switch (node.k) { - case "str": + case "str": { return lit(node.value); - case "int": + } + case "int": { return `${node.value}L`; - case "bool": + } + case "bool": { return String(node.value); - case "none": + } + case "none": { return "null"; - case "ref": + } + case "ref": { return verbatim.has(node.name) ? screaming(node.name) : node.name; - case "field": + } + case "field": { return `${expr(node.target)}.${node.name}`; - case "index": + } + case "index": { return isGrowing(node.target) ? `${expr(node.target)}.get((int) ${expr(node.index)})` : `${expr(node.target)}[(int) ${expr(node.index)}]`; - case "not": + } + case "not": { return `!${expr(node.operand)}`; - case "bin": - if (node.op === "==" && node.ty?.k === "string") - return `${expr(node.left)}.equals(${expr(node.right)})`; + } + case "bin": { + // `==` on Java strings compares references, which is never what the source meant. + const isText = node.ty?.k === "string" || node.ty?.k === "enum" || node.ty?.k === "scalar"; + + if (isText && (node.op === "==" || node.op === "!=")) + return `${node.op === "!=" ? "!" : ""}${expr(node.left)}.equals(${expr(node.right)})`; return `(${expr(node.left)} ${OPS[node.op]} ${expr(node.right)})`; - case "cond": + } + case "cond": { return `(${expr(node.test)} ? ${expr(node.whenTrue)} : ${expr(node.whenFalse)})`; - case "listOf": - if (node.of.k === "named") + } + case "listOf": { + if (node.of.k !== "int") return `new java.util.ArrayList<${type(node.of)}>(java.util.List.of(${node.items .map((item) => expr(item)) .join(", ")}))`; - return `{${node.items.map((item) => expr(item)).join(", ")}}`; + // An array initializer without `new T[]` is only valid in a declaration. + return `new long[] {${node.items.map((item) => expr(item)).join(", ")}}`; + } case "struct": { const declared = structs.get(node.name); const order = declared?.fields.map((field) => field.name) ?? node.fields.map((f) => f.name); return `new ${node.name}(${order - .map((name) => expr(node.fields.find((field) => field.name === name)?.value ?? { k: "none" })) + .map((name) => + expr(node.fields.find((field) => field.name === name)?.value ?? { k: "none" }), + ) .join(", ")})`; } - case "optionField": + case "optionField": { return `${node.target}${pascal(node.field)}`; - case "call": + } + case "await": { + // The blocking targets have nothing to wait on: the call has already returned. + return expr(node.value); + } + case "call": { return call(node); - default: - throw new Error(`java: unsupported expression ${node.k}`); + } } }; @@ -170,7 +213,7 @@ const isGrowing = (node: Expr): boolean => { const ty = localTypes.get(node.name); - return ty !== undefined && ty.k === "list" && ty.of.k === "named"; + return ty?.k === "list" && ty.of.k !== "int"; }; /** Renders a call. */ @@ -180,44 +223,96 @@ const call = (node: Extract): string => { if (node.callee.k === "user") return `${node.callee.name}(${args.join(", ")})`; switch (node.callee.name) { - case "len": + case "len": { return `(long) ${args[0]}.length()`; - case "listLen": + } + case "listLen": { return isGrowing(node.args[0]) ? `(long) ${args[0]}.size()` : `(long) ${args[0]}.length`; - case "codeAt": + } + case "codeAt": { return `Runtime.codeAt(${args[0]}, ${args[1]})`; - case "slice": + } + case "slice": { return `Runtime.slice(${args[0]}, ${args[1]}, ${args[2]})`; - case "upper": + } + case "upper": { return `${args[0]}.toUpperCase(java.util.Locale.ROOT)`; - case "trim": + } + case "trim": { return `Runtime.jsTrim(${args[0]})`; - case "padStart": + } + case "padStart": { return `Runtime.padStart(${args[0]}, ${args[1]}, ${args[2]})`; - case "repeat": + } + case "repeat": { return `Runtime.repeat(${args[0]}, ${args[1]})`; - case "classHas": + } + case "classHas": { return `Runtime.classHas(${args[0]}, ${args[1]})`; - case "keepClass": + } + case "keepClass": { return `Runtime.keepClass(${args[0]}, ${args[1]})`; - case "patternTest": + } + case "patternTest": { return `Runtime.patternTest(${args[0]}, ${args[1]})`; - case "asString": + } + case "asString": { // Java's types already guarantee a string at the boundary. return args[0]; - case "isTruthy": + } + case "isTruthy": { return args[0]; - case "listPush": + } + case "listPush": { return `${args[0]}.add(${args[1]})`; - case "unwrap": + } + case "unwrap": { // Java has no separate optional value to open; a reference is already nullable. return args[0]; - case "dataAll": + } + case "dataAll": { return `Runtime.dataAll(${args[0]})`; - case "dataRows": + } + case "dataRows": { return `Runtime.dataRows(${args[0]}, ${args[1]})`; - default: + } + case "isNumber": { + // Java's parameter is a String, so the question cannot arise. + return "false"; + } + case "isList": { + return "true"; + } + case "listHas": { + return `Runtime.listHas(${args[0]}, ${args[1]})`; + } + case "httpGet": { + return `Runtime.httpGet(${args.join(", ")})`; + } + case "jsonString": { + return `Runtime.jsonString(${args[0]}, ${args[1]})`; + } + case "jsonInt": { + return `Runtime.jsonInt(${args[0]}, ${args[1]})`; + } + case "jsonTruthy": { + return `Runtime.jsonTruthy(${args[0]}, ${args[1]})`; + } + case "jsonIsTrue": { + return `Runtime.jsonIsTrue(${args[0]}, ${args[1]})`; + } + case "startAll": { + return `Runtime.startAll(${className}::${node.args[0].k === "ref" ? node.args[0].name : ""}, ${args[1]}, ${args[2]})`; + } + case "firstSuccess": { + return `(${type(node.ty.k === "opt" ? node.ty.of : node.ty)}) Runtime.firstSuccess(${args[0]})`; + } + case "anyFailedWith": { + return `Runtime.anyFailedWith(${args[0]}, ${args[1]})`; + } + default: { throw new Error(`java: unsupported runtime call ${node.callee.name}`); + } } }; @@ -231,24 +326,39 @@ const block = (body: Stmt[], indent: string): string => /** Renders one statement. */ const stmt = (node: Stmt, indent: string): string => { switch (node.k) { - case "let": + case "let": { localTypes.set(node.name, node.ty); return `${indent}${type(node.ty)} ${node.name} = ${expr(node.value)};`; - case "assign": + } + case "assign": { return `${indent}${node.name} = ${expr(node.value)};`; + } case "if": { const otherwise = - node.otherwise.length === 0 ? "" : ` else {\n${block(node.otherwise, `${indent} `)}\n${indent}}`; + node.otherwise.length === 0 + ? "" + : ` else {\n${block(node.otherwise, `${indent} `)}\n${indent}}`; return `${indent}if (${expr(node.test)}) {\n${block(node.then, `${indent} `)}\n${indent}}${otherwise}`; } - case "return": + case "return": { return node.value === undefined ? `${indent}return;` : `${indent}return ${expr(node.value)};`; - case "forRange": + } + case "throw": { + return `${indent}throw new ${node.error}(${expr(node.message)});`; + } + case "try": { + return `${indent}try {\n${block(node.body, `${indent} `)}\n${indent}} catch (RuntimeException ${node.catchName}) {\n${block(node.catchBody, `${indent} `)}\n${indent}}`; + } + case "forRange": { return `${indent}for (long ${node.name} = ${expr(node.from)}; ${node.name} < ${expr(node.until)}; ${node.name}++) {\n${block(node.body, `${indent} `)}\n${indent}}`; - case "forOf": + } + case "forOf": { + localTypes.set(node.name, node.ty); + return `${indent}for (var ${node.name} : ${expr(node.iterable)}) {\n${block(node.body, `${indent} `)}\n${indent}}`; + } case "expr": { const value = node.value; @@ -262,8 +372,6 @@ const stmt = (node: Stmt, indent: string): string => { return `${indent}${expr(value)};`; } - default: - throw new Error(`java: unsupported statement ${node.k}`); } }; @@ -303,13 +411,23 @@ ${fields}${constructor} }`; }; +/** Renders an error type. Java has real inheritance, so the hierarchy is the declaration. */ +const error = (entry: ErrorDecl): string => + `/** ${entry.doc === "" ? entry.name : entry.doc} */ +public class ${entry.name} extends ${entry.base ?? "RuntimeException"} { + public ${entry.name}(String message) { + super(message); + } +}`; + /** Renders a dataset as the tables the runtime materialises, chunked to stay under Java's * 64 KiB per method limit. */ const data = (entry: DataDecl): string => { const name = entry.name.toLowerCase(); const rowChunks = chunks( entry.rows.map( - (row, index) => ` rows[${index}] = new String[] {${row.map((cell) => lit(cell)).join(", ")}};`, + (row, index) => + ` rows[${index}] = new String[] {${row.map((cell) => lit(cell)).join(", ")}};`, ), 200, ); @@ -336,11 +454,11 @@ ${rowChunks.map((_, index) => ` ${name}Rows${index}(rows);`).join("\n")} } ${rowChunks - .map( - (chunk, index) => - ` private static void ${name}Rows${index}(String[][] rows) {\n${chunk.join("\n")}\n }`, - ) - .join("\n\n")} + .map( + (chunk, index) => + ` private static void ${name}Rows${index}(String[][] rows) {\n${chunk.join("\n")}\n }`, + ) + .join("\n\n")} private static int[][] ${name}Groups() { int[][] groups = new int[${keys.length}][]; @@ -349,11 +467,11 @@ ${groupChunks.map((_, index) => ` ${name}Groups${index}(groups);`).join(" } ${groupChunks - .map( - (chunk, index) => - ` private static void ${name}Groups${index}(int[][] groups) {\n${chunk.join("\n")}\n }`, - ) - .join("\n\n")} + .map( + (chunk, index) => + ` private static void ${name}Groups${index}(int[][] groups) {\n${chunk.join("\n")}\n }`, + ) + .join("\n\n")} private static int[] ${name}Order() { int[] order = new int[${entry.fullOrder.length}]; @@ -362,11 +480,11 @@ ${orderChunks.map((_, index) => ` ${name}Order${index}(order);`).join("\n } ${orderChunks - .map( - (chunk, index) => - ` private static void ${name}Order${index}(int[] order) {\n${chunk.join("\n")}\n }`, - ) - .join("\n\n")}`; + .map( + (chunk, index) => + ` private static void ${name}Order${index}(int[] order) {\n${chunk.join("\n")}\n }`, + ) + .join("\n\n")}`; }; /** Renders one function. */ @@ -379,8 +497,11 @@ const func = (entry: FuncDecl): string => { const prologue = optionReads(entry) .map((read) => { const local = `${read.target}${pascal(read.field)}`; + const ty = read.expr.k === "optionField" ? read.expr.ty : ({ k: "int" } as Ty); const fallback = read.expr.k === "optionField" ? expr(read.expr.fallback) : "null"; - const declared = read.expr.k === "optionField" && read.expr.ty.k === "bool" ? "boolean" : "long"; + const declared = ty.k === "bool" ? "boolean" : ty.k === "int" ? "long" : type(ty); + + localTypes.set(local, ty); return ` ${declared} ${local} = ${fallback};\n if (${read.target} != null && ${read.target}.${read.field} != null) {\n ${local} = ${read.target}.${read.field};\n }`; }) @@ -407,6 +528,10 @@ ${prologue === "" ? "" : `${prologue}\n`}${block(entry.body, " ")} */ export const emit = (module: Module): Record => { structs = new Map(module.structs.map((entry) => [entry.name, entry])); + external = new Set( + module.structs.filter((entry) => entry.external === true).map((entry) => entry.name), + ); + className = pascal(module.name); verbatim = new Set([ ...module.charClasses.map((entry) => entry.name), ...module.patterns.map((entry) => entry.name), @@ -414,12 +539,10 @@ export const emit = (module: Module): Record => { ...module.data.map((entry) => entry.name), ]); - const className = pascal(module.name); const constants = module.constants - .map((entry) => - entry.ty.k === "list" - ? ` private static final long[] ${screaming(entry.name)} = ${expr(entry.expr)};` - : ` private static final String ${screaming(entry.name)} = ${expr(entry.expr)};`, + .map( + (entry) => + ` private static final ${type(entry.ty)} ${screaming(entry.name)} = ${expr(entry.expr)};`, ) .join("\n"); @@ -444,7 +567,13 @@ ${module.functions.map((entry) => func(entry)).join("\n\n")} `, }; - for (const entry of module.structs) files[`${entry.name}.java`] = `${struct(entry)}\n`; + for (const entry of module.structs) { + if (entry.external === true) continue; + + files[`${entry.name}.java`] = `${struct(entry)}\n`; + } + + for (const entry of module.errors) files[`${entry.name}.java`] = `${error(entry)}\n`; return files; }; diff --git a/spec/bridge/compiler/targets/python.ts b/spec/bridge/compiler/targets/python.ts index 8472a4bba..e4c891816 100644 --- a/spec/bridge/compiler/targets/python.ts +++ b/spec/bridge/compiler/targets/python.ts @@ -6,16 +6,18 @@ */ import { readFileSync } from "node:fs"; import { resolve } from "node:path"; -import type { - CharClass, - DataDecl, - Expr, - FuncDecl, - Module, - PatternDecl, - Stmt, - StructDecl, - Ty, + +import { + type CharClass, + type DataDecl, + type ErrorDecl, + type Expr, + type FuncDecl, + type Module, + type PatternDecl, + type Stmt, + type StructDecl, + type Ty, } from "../ir.ts"; import { optionReads, prose, snake } from "../kit.ts"; @@ -43,26 +45,38 @@ const lit = (value: string): string => { /** Renders an IR type as a Python annotation. */ const type = (ty: Ty): string => { switch (ty.k) { - case "string": + case "string": { return "str"; - case "int": + } + case "int": { return "int"; - case "bool": + } + case "bool": { return "bool"; - case "void": + } + case "void": { return "None"; + } case "json": - case "scalar": + case "scalar": { return "Any"; - case "enum": + } + case "enum": { // A closed set of strings is still a string at run time; the compiler is the checker. return "str"; - case "list": + } + case "tasks": { + return "Any"; + } + case "list": { return `List[${type(ty.of)}]`; - case "opt": + } + case "opt": { return `Optional[${type(ty.of)}]`; - case "named": + } + case "named": { return ty.name; + } } }; @@ -84,22 +98,30 @@ const OPS: Record = { /** Renders an expression. */ const expr = (node: Expr): string => { switch (node.k) { - case "str": + case "str": { return lit(node.value); - case "int": + } + case "int": { return String(node.value); - case "bool": + } + case "bool": { return node.value ? "True" : "False"; - case "none": + } + case "none": { return "None"; - case "ref": + } + case "ref": { return verbatim.has(node.name) ? node.name : snake(node.name); - case "field": + } + case "field": { return `${expr(node.target)}.${snake(node.name)}`; - case "index": + } + case "index": { return `${expr(node.target)}[${expr(node.index)}]`; - case "not": + } + case "not": { return `not ${expr(node.operand)}`; + } case "bin": { // `x == None` works but reads wrong; identity is what the comparison means. if (node.right.k === "none" && (node.op === "==" || node.op === "!=")) @@ -107,19 +129,26 @@ const expr = (node: Expr): string => { return `(${expr(node.left)} ${OPS[node.op]} ${expr(node.right)})`; } - case "cond": + case "cond": { return `(${expr(node.whenTrue)} if ${expr(node.test)} else ${expr(node.whenFalse)})`; - case "listOf": + } + case "listOf": { return `[${node.items.map((item) => expr(item)).join(", ")}]`; - case "struct": + } + case "struct": { return `${node.name}(${node.fields.map((field) => `${snake(field.name)}=${expr(field.value)}`).join(", ")})`; - case "optionField": + } + case "optionField": { // The prologue binds every option read to a local of this name. return `${snake(node.target)}_${snake(node.field)}`; - case "call": + } + case "await": { + // The blocking targets have nothing to wait on: the call has already returned. + return expr(node.value); + } + case "call": { return call(node); - default: - throw new Error(`python: unsupported expression ${node.k}`); + } } }; @@ -131,41 +160,91 @@ const call = (node: Extract): string => { switch (node.callee.name) { case "len": - case "listLen": + case "listLen": { return `len(${args[0]})`; - case "codeAt": + } + case "codeAt": { return `code_at(${args[0]}, ${args[1]})`; - case "slice": + } + case "slice": { return `${args[0]}[${args[1]}:${args[2]}]`; - case "upper": + } + case "upper": { return `${args[0]}.upper()`; - case "trim": + } + case "trim": { return `js_trim(${args[0]})`; - case "padStart": + } + case "padStart": { return `pad_start(${args[0]}, ${args[1]}, ${args[2]})`; - case "repeat": + } + case "repeat": { return `(${args[0]} * ${args[1]})`; - case "classHas": + } + case "classHas": { return `class_has(${args[0]}, ${args[1]})`; - case "keepClass": + } + case "keepClass": { return `keep_class(${args[0]}, ${args[1]})`; - case "patternTest": + } + case "patternTest": { return `pattern_test(${args[0]}, ${args[1]})`; - case "asString": + } + case "asString": { return `as_string(${args[0]})`; - case "isTruthy": + } + case "isTruthy": { return `is_truthy(${args[0]})`; - case "listPush": + } + case "listPush": { return `${args[0]}.append(${args[1]})`; - case "unwrap": + } + case "unwrap": { // Python has no separate optional value to open. return args[0]; - case "dataAll": + } + case "dataAll": { return `data_all(${args[0]})`; - case "dataRows": + } + case "dataRows": { return `data_rows(${args[0]}, ${args[1]})`; - default: + } + case "isNumber": { + return `is_number(${args[0]})`; + } + case "isList": { + return `is_list(${args[0]})`; + } + case "listHas": { + return `list_has(${args[0]}, ${args[1]})`; + } + case "httpGet": { + return `http_get(${args.join(", ")})`; + } + case "jsonString": { + return `json_string(${args[0]}, ${args[1]})`; + } + case "jsonInt": { + return `json_int(${args[0]}, ${args[1]})`; + } + case "jsonTruthy": { + return `json_truthy(${args[0]}, ${args[1]})`; + } + case "jsonIsTrue": { + return `json_is_true(${args[0]}, ${args[1]})`; + } + case "startAll": { + return `start_all(${args.join(", ")})`; + } + case "firstSuccess": { + return `first_success(${args[0]})`; + } + case "anyFailedWith": { + return `any_failed_with(${args[0]}, ${args[1]})`; + } + default: { throw new Error(`python: unsupported runtime call ${node.callee.name}`); + } } }; @@ -180,20 +259,32 @@ const block = (body: Stmt[], indent: string): string => { const stmt = (node: Stmt, indent: string): string => { switch (node.k) { case "let": - case "assign": - return `${indent}${snake(node.k === "let" ? node.name : node.name)} = ${expr(node.value)}`; + case "assign": { + return `${indent}${snake(node.name)} = ${expr(node.value)}`; + } case "if": { const otherwise = - node.otherwise.length === 0 ? "" : `\n${indent}else:\n${block(node.otherwise, `${indent} `)}`; + node.otherwise.length === 0 + ? "" + : `\n${indent}else:\n${block(node.otherwise, `${indent} `)}`; return `${indent}if ${expr(node.test)}:\n${block(node.then, `${indent} `)}${otherwise}`; } - case "return": + case "return": { return node.value === undefined ? `${indent}return` : `${indent}return ${expr(node.value)}`; - case "forRange": + } + case "throw": { + return `${indent}raise ${node.error}(${expr(node.message)})`; + } + case "try": { + return `${indent}try:\n${block(node.body, `${indent} `)}\n${indent}except Exception as ${snake(node.catchName)}:\n${block(node.catchBody, `${indent} `)}`; + } + case "forRange": { return `${indent}for ${snake(node.name)} in range(${expr(node.from)}, ${expr(node.until)}):\n${block(node.body, `${indent} `)}`; - case "forOf": + } + case "forOf": { return `${indent}for ${snake(node.name)} in ${expr(node.iterable)}:\n${block(node.body, `${indent} `)}`; + } case "expr": { const value = node.value; @@ -210,8 +301,6 @@ const stmt = (node: Stmt, indent: string): string => { return `${indent}${expr(value)}`; } - default: - throw new Error(`python: unsupported statement ${node.k}`); } }; @@ -249,13 +338,16 @@ ${groups} )`; }; +/** Renders an error type. */ +const error = (entry: ErrorDecl): string => + `class ${entry.name}(${entry.base ?? "Exception"}): + """${entry.doc === "" ? entry.name : entry.doc.split("\n").join(" ")}"""`; + /** Renders an options record as a dataclass. */ const struct = (entry: StructDecl): string => { const fields = entry.fields .map((field) => { - const declared = entry.isOptions - ? `Optional[${type(field.ty)}] = None` - : type(field.ty); + const declared = entry.isOptions ? `Optional[${type(field.ty)}] = None` : type(field.ty); return `${field.doc === "" ? "" : ` # ${field.doc}\n`} ${snake(field.name)}: ${declared}`; }) @@ -330,17 +422,28 @@ from typing import Any, List, Optional from .runtime import ( CharClass, PatternStep, + any_failed_with, as_string, class_has, code_at, data_all, data_rows, + first_success, + http_get, + is_list, + is_number, is_truthy, js_trim, + json_int, + json_is_true, + json_string, + json_truthy, keep_class, + list_has, make_dataset, pad_start, pattern_test, + start_all, ) ${module.charClasses.map((entry) => charClass(entry)).join("\n")} @@ -350,7 +453,13 @@ ${module.patterns.map((entry) => pattern(entry)).join("\n\n")} ${constants} -${module.structs.map((entry) => struct(entry)).join("\n\n\n")} +${module.errors.map((entry) => error(entry)).join("\n\n\n")} + + +${module.structs + .filter((entry) => entry.external !== true) + .map((entry) => struct(entry)) + .join("\n\n\n")} ${module.data.map((entry) => data(entry)).join("\n\n")} diff --git a/spec/bridge/compiler/targets/ruby.ts b/spec/bridge/compiler/targets/ruby.ts index ff453850d..4d952e33e 100644 --- a/spec/bridge/compiler/targets/ruby.ts +++ b/spec/bridge/compiler/targets/ruby.ts @@ -6,15 +6,17 @@ */ import { readFileSync } from "node:fs"; import { resolve } from "node:path"; -import type { - CharClass, - DataDecl, - Expr, - FuncDecl, - Module, - PatternDecl, - Stmt, - StructDecl, + +import { + type CharClass, + type DataDecl, + type ErrorDecl, + type Expr, + type FuncDecl, + type Module, + type PatternDecl, + type Stmt, + type StructDecl, } from "../ir.ts"; import { optionReads, prose, screaming, snake } from "../kit.ts"; @@ -59,42 +61,58 @@ const OPS: Record = { /** Renders an expression. */ const expr = (node: Expr): string => { switch (node.k) { - case "str": + case "str": { return lit(node.value); - case "int": + } + case "int": { return String(node.value); - case "bool": + } + case "bool": { return String(node.value); - case "none": + } + case "none": { return "nil"; - case "ref": + } + case "ref": { return verbatim.has(node.name) ? screaming(node.name) : snake(node.name); - case "field": + } + case "field": { return `${expr(node.target)}.${snake(node.name)}`; - case "index": + } + case "index": { return `${expr(node.target)}[${expr(node.index)}]`; - case "not": + } + case "not": { return `!${expr(node.operand)}`; - case "bin": + } + case "bin": { // `x == nil` works but `nil?` is what a Ruby reader expects. if (node.right.k === "none" && (node.op === "==" || node.op === "!=")) return `${node.op === "!=" ? "!" : ""}${expr(node.left)}.nil?`; return `(${expr(node.left)} ${OPS[node.op]} ${expr(node.right)})`; - case "cond": + } + case "cond": { return `(${expr(node.test)} ? ${expr(node.whenTrue)} : ${expr(node.whenFalse)})`; - case "listOf": + } + case "listOf": { return `[${node.items.map((item) => expr(item)).join(", ")}]`; - case "struct": + } + case "struct": { return `${node.name}.new(${node.fields .map((field) => `${snake(field.name)}: ${expr(field.value)}`) .join(", ")})`; - case "optionField": + } + case "optionField": { return `${snake(node.target)}_${snake(node.field)}`; - case "call": + } + case "await": { + // The blocking targets have nothing to wait on: the call has already returned. + return expr(node.value); + } + case "call": { return call(node); - default: - throw new Error(`ruby: unsupported expression ${node.k}`); + } } }; @@ -106,41 +124,91 @@ const call = (node: Extract): string => { switch (node.callee.name) { case "len": - case "listLen": + case "listLen": { return `${args[0]}.length`; - case "codeAt": + } + case "codeAt": { return `Runtime.code_at(${args[0]}, ${args[1]})`; - case "slice": + } + case "slice": { return `${args[0]}[${args[1]}...${args[2]}]`; - case "upper": + } + case "upper": { return `${args[0]}.upcase`; - case "trim": + } + case "trim": { return `Runtime.js_trim(${args[0]})`; - case "padStart": + } + case "padStart": { return `Runtime.pad_start(${args[0]}, ${args[1]}, ${args[2]})`; - case "repeat": + } + case "repeat": { return `(${args[0]} * ${args[1]})`; - case "classHas": + } + case "classHas": { return `Runtime.class_has(${args[0]}, ${args[1]})`; - case "keepClass": + } + case "keepClass": { return `Runtime.keep_class(${args[0]}, ${args[1]})`; - case "patternTest": + } + case "patternTest": { return `Runtime.pattern_test(${args[0]}, ${args[1]})`; - case "asString": + } + case "asString": { return `Runtime.as_string(${args[0]})`; - case "isTruthy": + } + case "isTruthy": { return `Runtime.is_truthy(${args[0]})`; - case "listPush": + } + case "listPush": { return `${args[0]}.push(${args[1]})`; - case "unwrap": + } + case "unwrap": { // Ruby has no separate optional value to open. return args[0]; - case "dataAll": + } + case "dataAll": { return `Runtime.data_all(${args[0]})`; - case "dataRows": + } + case "dataRows": { return `Runtime.data_rows(${args[0]}, ${args[1]})`; - default: + } + case "isNumber": { + return `Runtime.is_number(${args[0]})`; + } + case "isList": { + return `Runtime.is_list(${args[0]})`; + } + case "listHas": { + return `Runtime.list_has(${args[0]}, ${args[1]})`; + } + case "httpGet": { + return `Runtime.http_get(${args.join(", ")})`; + } + case "jsonString": { + return `Runtime.json_string(${args[0]}, ${args[1]})`; + } + case "jsonInt": { + return `Runtime.json_int(${args[0]}, ${args[1]})`; + } + case "jsonTruthy": { + return `Runtime.json_truthy(${args[0]}, ${args[1]})`; + } + case "jsonIsTrue": { + return `Runtime.json_is_true(${args[0]}, ${args[1]})`; + } + case "startAll": { + return `Runtime.start_all(method(:${args[0]}), ${args[1]}, ${args[2]})`; + } + case "firstSuccess": { + return `Runtime.first_success(${args[0]})`; + } + case "anyFailedWith": { + return `Runtime.any_failed_with(${args[0]}, ${args[1]})`; + } + default: { throw new Error(`ruby: unsupported runtime call ${node.callee.name}`); + } } }; @@ -155,20 +223,32 @@ const block = (body: Stmt[], indent: string): string => const stmt = (node: Stmt, indent: string): string => { switch (node.k) { case "let": - case "assign": + case "assign": { return `${indent}${snake(node.name)} = ${expr(node.value)}`; + } case "if": { const otherwise = - node.otherwise.length === 0 ? "" : `\n${indent}else\n${block(node.otherwise, `${indent} `)}`; + node.otherwise.length === 0 + ? "" + : `\n${indent}else\n${block(node.otherwise, `${indent} `)}`; return `${indent}if ${expr(node.test)}\n${block(node.then, `${indent} `)}${otherwise}\n${indent}end`; } - case "return": + case "return": { return node.value === undefined ? `${indent}return` : `${indent}return ${expr(node.value)}`; - case "forRange": + } + case "throw": { + return `${indent}raise ${node.error}, ${expr(node.message)}`; + } + case "try": { + return `${indent}begin\n${block(node.body, `${indent} `)}\n${indent}rescue StandardError => ${snake(node.catchName)}\n${block(node.catchBody, `${indent} `)}\n${indent}end`; + } + case "forRange": { return `${indent}(${expr(node.from)}...${expr(node.until)}).each do |${snake(node.name)}|\n${block(node.body, `${indent} `)}\n${indent}end`; - case "forOf": + } + case "forOf": { return `${indent}${expr(node.iterable)}.each do |${snake(node.name)}|\n${block(node.body, `${indent} `)}\n${indent}end`; + } case "expr": { const value = node.value; @@ -176,17 +256,13 @@ const stmt = (node: Stmt, indent: string): string => { const [subject, kind, fallback] = value.args; const name = subject.k === "ref" ? snake(subject.name) : ""; const test = - kind.k === "str" && kind.value === "string" - ? `!${name}.is_a?(String)` - : `${name}.nil?`; + kind.k === "str" && kind.value === "string" ? `!${name}.is_a?(String)` : `${name}.nil?`; return `${indent}return ${expr(fallback)} if ${test}`; } return `${indent}${expr(value)}`; } - default: - throw new Error(`ruby: unsupported statement ${node.k}`); } }; @@ -209,6 +285,10 @@ const struct = (entry: StructDecl): string => .map((field) => `:${snake(field.name)}`) .join(", ")}, keyword_init: true)`; +/** Renders an error type. */ +const error = (entry: ErrorDecl): string => + ` # ${entry.doc === "" ? entry.name : entry.doc}\n class ${entry.name} < ${entry.base ?? "StandardError"}; end`; + /** Renders a dataset as the table the runtime materialises. */ const data = (entry: DataDecl): string => { const rows = entry.rows @@ -290,7 +370,12 @@ ${module.patterns.map((entry) => pattern(entry)).join("\n\n")} ${constants} -${module.structs.map((entry) => struct(entry)).join("\n\n")} +${module.errors.map((entry) => error(entry)).join("\n\n")} + +${module.structs + .filter((entry) => entry.external !== true) + .map((entry) => struct(entry)) + .join("\n\n")} ${module.data.map((entry) => data(entry)).join("\n\n")} diff --git a/spec/bridge/compiler/targets/rust.ts b/spec/bridge/compiler/targets/rust.ts index c3c9a62fc..2b9aaa4ce 100644 --- a/spec/bridge/compiler/targets/rust.ts +++ b/spec/bridge/compiler/targets/rust.ts @@ -6,17 +6,19 @@ */ import { readFileSync } from "node:fs"; import { resolve } from "node:path"; -import type { - CharClass, - DataDecl, - Expr, - FuncDecl, - Module, - Param, - PatternDecl, - Stmt, - StructDecl, - Ty, + +import { + type CharClass, + type DataDecl, + type ErrorDecl, + type Expr, + type FuncDecl, + type Module, + type Param, + type PatternDecl, + type Stmt, + type StructDecl, + type Ty, } from "../ir.ts"; import { optionReads, prose, pushTargets, screaming, snake } from "../kit.ts"; @@ -26,6 +28,15 @@ let structs = new Map(); /** The datasets of the module, which are functions rather than statics in Rust. */ let datasets = new Set(); +/** The functions that answer a `Result`. */ +let throwing = new Set(); + +/** The records the runtime declares, which are reached through its module. */ +let external = new Set(); + +/** The function being rendered, so a return knows whether to wrap its value. */ +let current: FuncDecl | undefined; + const RUNTIME = resolve(import.meta.dirname, "../runtime/rust.rs"); /** Module level names the emitter writes verbatim. */ @@ -55,25 +66,36 @@ const type = (ty: Ty): string => { switch (ty.k) { case "string": case "scalar": - case "enum": + case "enum": { return "String"; - case "int": + } + case "int": { return "i64"; - case "bool": + } + case "bool": { return "bool"; - case "void": + } + case "void": { return "()"; - case "json": - return "String"; - case "list": + } + case "json": { + return "serde_json::Value"; + } + case "list": { // A dataset row is borrowed from the table rather than rebuilt for every reader. if (ty.of.k === "list" && ty.of.of.k === "string") return "Vec"; return `Vec<${type(ty.of)}>`; - case "opt": + } + case "opt": { return `Option<${type(ty.of)}>`; - case "named": - return ty.name; + } + case "tasks": { + return `runtime::Attempts<${type(ty.of)}>`; + } + case "named": { + return external.has(ty.name) ? `runtime::${ty.name}` : ty.name; + } } }; @@ -104,24 +126,32 @@ const asStr = (node: Expr): string => { /** Renders an expression. */ const expr = (node: Expr): string => { switch (node.k) { - case "str": + case "str": { return lit(node.value); - case "int": + } + case "int": { return String(node.value); - case "bool": + } + case "bool": { return String(node.value); - case "none": + } + case "none": { return "None"; - case "ref": + } + case "ref": { if (datasets.has(node.name)) return `${snake(node.name)}_table()`; return verbatim.has(node.name) ? screaming(node.name) : snake(node.name); - case "field": + } + case "field": { return `${expr(node.target)}.${snake(node.name)}`; - case "index": + } + case "index": { return `${expr(node.target)}[${expr(node.index)} as usize]`; - case "not": + } + case "not": { return `!${expr(node.operand)}`; + } case "bin": { if (node.right.k === "none" && (node.op === "==" || node.op === "!=")) return `${expr(node.left)}.${node.op === "!=" ? "is_some" : "is_none"}()`; @@ -131,13 +161,15 @@ const expr = (node: Expr): string => { return `(${expr(node.left)} ${OPS[node.op]} ${expr(node.right)})`; } - case "cond": + case "cond": { return `(if ${expr(node.test)} { ${expr(node.whenTrue)} } else { ${expr(node.whenFalse)} })`; - case "listOf": + } + case "listOf": { // A list that only ever holds literals is a fixed size array; anything else is a Vec. if (node.of.k === "int") return `[${node.items.map((item) => expr(item)).join(", ")}]`; return `vec![${node.items.map((item) => expr(item)).join(", ")}]`; + } case "struct": { const declared = structs.get(node.name); @@ -149,12 +181,16 @@ const expr = (node: Expr): string => { }) .join(", ")} }`; } - case "optionField": + case "optionField": { return `${snake(node.target)}_${snake(node.field)}`; - case "call": + } + case "await": { + // The blocking targets have nothing to wait on: the call has already returned. + return expr(node.value); + } + case "call": { return call(node); - default: - throw new Error(`rust: unsupported expression ${node.k}`); + } } }; @@ -179,42 +215,98 @@ const call = (node: Extract): string => { } switch (node.callee.name) { - case "listPush": - return `${expr(args[0])}.push(${expr(args[1])})`; - case "unwrap": - return `${expr(args[0])}.unwrap()`; - case "dataAll": + case "listPush": { + const target = args[0].k === "ref" ? localTypes.get(args[0].name) : undefined; + + return `${expr(args[0])}.push(${owned(args[1], target?.k === "list" ? target.of : undefined)})`; + } + case "isNumber": { + // Rust's parameter is a `&str`, so the question cannot arise. + return "false"; + } + case "isList": { + return "true"; + } + case "listHas": { + return `runtime::list_has(${expr(args[0])}, ${asStr(args[1])})`; + } + case "httpGet": { + return `runtime::http_get(${asStr(args[0])}, ${expr(args[1])}, ${expr(args[2])})`; + } + case "jsonString": { + return `runtime::json_string(&${expr(args[0])}, ${asStr(args[1])})`; + } + case "jsonInt": { + return `runtime::json_int(&${expr(args[0])}, ${asStr(args[1])})`; + } + case "jsonTruthy": { + return `runtime::json_truthy(&${expr(args[0])}, ${asStr(args[1])})`; + } + case "jsonIsTrue": { + return `runtime::json_is_true(&${expr(args[0])}, ${asStr(args[1])})`; + } + case "startAll": { + return `runtime::start_all(${snake(args[0].k === "ref" ? args[0].name : "")}, &${expr(args[1])}, ${asStr(args[2])})`; + } + case "firstSuccess": { + return `runtime::first_success(&mut ${expr(args[0])})`; + } + case "anyFailedWith": { + return `runtime::any_failed_with(&${expr(args[0])}, ${asStr(args[1])})`; + } + case "unwrap": { + return node.ty.k === "int" || node.ty.k === "bool" + ? `${expr(args[0])}.unwrap()` + : `${expr(args[0])}.clone().unwrap()`; + } + case "dataAll": { return `runtime::data_all(${expr(args[0])})`; - case "dataRows": + } + case "dataRows": { return `runtime::data_rows(${expr(args[0])}, ${asStr(args[1])})`; - case "len": + } + case "len": { return `runtime::len(${asStr(args[0])})`; - case "listLen": + } + case "listLen": { return `(${expr(args[0])}.len() as i64)`; - case "codeAt": + } + case "codeAt": { return `runtime::code_at(${asStr(args[0])}, ${expr(args[1])})`; - case "slice": + } + case "slice": { return `runtime::slice(${asStr(args[0])}, ${expr(args[1])}, ${expr(args[2])})`; - case "upper": + } + case "upper": { return `runtime::upper(${asStr(args[0])})`; - case "trim": + } + case "trim": { return `runtime::js_trim(${asStr(args[0])})`; - case "padStart": + } + case "padStart": { return `runtime::pad_start(${asStr(args[0])}, ${expr(args[1])}, ${asStr(args[2])})`; - case "repeat": + } + case "repeat": { return `runtime::repeat(${asStr(args[0])}, ${expr(args[1])})`; - case "classHas": + } + case "classHas": { return `runtime::class_has(${expr(args[0])}, ${asStr(args[1])})`; - case "keepClass": + } + case "keepClass": { return `runtime::keep_class(${expr(args[0])}, ${asStr(args[1])})`; - case "patternTest": + } + case "patternTest": { return `runtime::pattern_test(${expr(args[0])}, ${asStr(args[1])})`; - case "asString": + } + case "asString": { return `${expr(args[0])}.to_string()`; - case "isTruthy": + } + case "isTruthy": { return expr(args[0]); - default: + } + default: { throw new Error(`rust: unsupported runtime call ${node.callee.name}`); + } } }; @@ -237,7 +329,14 @@ let localTypes = new Map(); const owned = (node: Expr, ty?: Ty): string => { const rendered = expr(node); - if (ty !== undefined && ty.k !== "string" && ty.k !== "scalar" && ty.k !== "enum") return rendered; + // A list constant is a slice of borrowed strings; owning it is spelled out. + if (ty?.k === "list" && (ty.of.k === "string" || ty.of.k === "enum")) + return node.k === "ref" && verbatim.has(node.name) + ? `${rendered}.iter().map(|value| value.to_string()).collect()` + : rendered; + + if (ty !== undefined && ty.k !== "string" && ty.k !== "scalar" && ty.k !== "enum") + return rendered; if (node.k === "str") return `${rendered}.to_string()`; if (node.k === "index" && (node.ty?.k === "string" || node.ty?.k === "enum")) return `${rendered}.to_string()`; @@ -256,23 +355,51 @@ const block = (body: Stmt[], indent: string): string => /** Renders one statement. */ const stmt = (node: Stmt, indent: string): string => { switch (node.k) { - case "let": - return `${indent}let ${node.mutable || mutated.has(node.name) ? "mut " : ""}${snake(node.name)}: ${type(node.ty)} = ${owned(node.value, node.ty)};`; - case "assign": + case "let": { + return `${indent}let ${node.mutable || mutated.has(node.name) || node.ty.k === "tasks" ? "mut " : ""}${snake(node.name)}: ${type(node.ty)} = ${owned(node.value, node.ty)};`; + } + case "assign": { return `${indent}${snake(node.name)} = ${owned(node.value, localTypes.get(node.name))};`; + } case "if": { const otherwise = - node.otherwise.length === 0 ? "" : ` else {\n${block(node.otherwise, `${indent}\t`)}\n${indent}}`; + node.otherwise.length === 0 + ? "" + : ` else {\n${block(node.otherwise, `${indent}\t`)}\n${indent}}`; return `${indent}if ${expr(node.test)} {\n${block(node.then, `${indent}\t`)}\n${indent}}${otherwise}`; } - case "return": - return node.value === undefined ? `${indent}return;` : `${indent}return ${expr(node.value)};`; - case "forRange": + case "return": { + if (current?.throws !== true) + return node.value === undefined + ? `${indent}return;` + : `${indent}return ${expr(node.value)};`; + + // A call to another raising function already answers a `Result`. + if ( + node.value?.k === "call" && + node.value.callee.k === "user" && + throwing.has(node.value.callee.name) + ) + return `${indent}return ${expr(node.value)};`; + + return node.value === undefined + ? `${indent}return Ok(());` + : `${indent}return Ok(${owned(node.value, current.ret)});`; + } + case "try": { + throw new Error("rust: try/catch has no Rust form; a raising call answers a Result instead"); + } + case "throw": { + return `${indent}return Err(runtime::Error::new(${screaming(`${node.error}Kinds`)}, ${expr(node.message)}));`; + } + case "forRange": { return `${indent}for ${snake(node.name)} in ${expr(node.from)}..${expr(node.until)} {\n${block(node.body, `${indent}\t`)}\n${indent}}`; - case "forOf": + } + case "forOf": { // The loop consumes the list: nothing in the subset reads one after iterating it. return `${indent}for ${snake(node.name)} in ${expr(node.iterable)} {\n${block(node.body, `${indent}\t`)}\n${indent}}`; + } case "expr": { const value = node.value; @@ -282,8 +409,6 @@ const stmt = (node: Stmt, indent: string): string => { return `${indent}${expr(value)};`; } - default: - throw new Error(`rust: unsupported statement ${node.k}`); } }; @@ -300,6 +425,16 @@ const pattern = (entry: PatternDecl): string => ) .join("\n")}\n];`; +/** Renders an error type: its kinds, and the predicate a caller matches on. */ +const error = (entry: ErrorDecl): string => + `/// ${entry.doc === "" ? entry.name : entry.doc} +pub const ${screaming(`${entry.name}Kinds`)}: &[&str] = &[${entry.kinds.map((kind) => lit(kind)).join(", ")}]; + +/// Whether a failure is a ${entry.name}. +pub fn ${snake(`is${entry.name}`)}(error: &runtime::Error) -> bool { + error.is_kind(${lit(entry.name)}) +}`; + /** Renders an options record. */ const struct = (entry: StructDecl): string => { const fields = entry.fields @@ -319,11 +454,12 @@ ${fields} /** Renders one function. */ const func = (entry: FuncDecl): string => { + current = entry; borrowed = new Set([ ...entry.params .filter((param) => param.ty.k === "string" || param.ty.k === "scalar") .map((param) => param.name), - ...[...verbatim], + ...verbatim, ]); localTypes = new Map(); mutated = pushTargets(entry); @@ -335,6 +471,12 @@ const func = (entry: FuncDecl): string => { collect(statement.then); collect(statement.otherwise); } + if (statement.k === "forOf") { + localTypes.set(statement.name, statement.ty); + + if (statement.ty.k === "string" || statement.ty.k === "enum") borrowed.add(statement.name); + } + if (statement.k === "forOf" || statement.k === "forRange") collect(statement.body); if (statement.k === "try") { collect(statement.body); @@ -367,9 +509,12 @@ const func = (entry: FuncDecl): string => { const prologue = optionReads(entry) .map((read) => { const local = `${snake(read.target)}_${snake(read.field)}`; - const fallback = read.expr.k === "optionField" ? expr(read.expr.fallback) : "None"; + const fallback = read.expr.k === "optionField" ? read.expr.fallback : { k: "none" as const }; + const held = `value.${snake(read.field)}`; + const taken = + fallback.k === "none" ? `${held}.clone()` : `${held}.unwrap_or(${expr(fallback)})`; - return `\tlet ${local} = match ${snake(read.target)} {\n\t\tNone => ${fallback},\n\t\tSome(value) => value.${snake(read.field)}.unwrap_or(${fallback}),\n\t};`; + return `\tlet ${local} = match ${snake(read.target)} {\n\t\tNone => ${fallback.k === "none" ? "None" : expr(fallback)},\n\t\tSome(value) => ${taken},\n\t};`; }) .join("\n"); @@ -378,7 +523,11 @@ const func = (entry: FuncDecl): string => { .map((line) => `/// ${line}`.trimEnd()) .join("\n"); - return `${doc === "" ? "" : `${doc}\n`}pub fn ${snake(entry.name)}(${params}) -> ${type(entry.ret)} { + // Rust has no exceptions, so a function that can raise answers a `Result` and the emitter + // threads it through; the source never mentions it. + const returns = entry.throws ? `Result<${type(entry.ret)}, runtime::Error>` : type(entry.ret); + + return `${doc === "" ? "" : `${doc}\n`}pub fn ${snake(entry.name)}(${params}) -> ${returns} { ${prologue === "" ? "" : `${prologue}\n`}${block(entry.body, "\t")} }`; }; @@ -420,6 +569,10 @@ fn ${snake(entry.name)}_table() -> &'static runtime::Dataset { export const emit = (module: Module, modules: Module[] = [module]): Record => { signatures = new Map(module.functions.map((entry) => [entry.name, entry.params])); structs = new Map(module.structs.map((entry) => [entry.name, entry])); + throwing = new Set(module.functions.filter((entry) => entry.throws).map((entry) => entry.name)); + external = new Set( + module.structs.filter((entry) => entry.external === true).map((entry) => entry.name), + ); datasets = new Set(module.data.map((entry) => entry.name)); verbatim = new Set([ ...module.charClasses.map((entry) => entry.name), @@ -428,11 +581,17 @@ export const emit = (module: Module, modules: Module[] = [module]): Record - entry.ty.k === "list" - ? `const ${screaming(entry.name)}: [i64; ${(entry.expr as Extract).items.length}] = ${expr(entry.expr)};` - : `const ${screaming(entry.name)}: &str = ${expr(entry.expr)};`, - ) + .map((entry) => { + const items = (entry.expr as Extract).items; + + if (entry.ty.k === "list" && entry.ty.of.k === "int") + return `const ${screaming(entry.name)}: [i64; ${items.length}] = ${expr(entry.expr)};`; + if (entry.ty.k === "list") + return `const ${screaming(entry.name)}: &[&str] = &[${items.map((item) => expr(item)).join(", ")}];`; + if (entry.ty.k === "int") return `const ${screaming(entry.name)}: i64 = ${expr(entry.expr)};`; + + return `const ${screaming(entry.name)}: &str = ${expr(entry.expr)};`; + }) .join("\n"); return { @@ -450,6 +609,10 @@ version = "0.0.0" edition = "2021" publish = false +[dependencies] +serde_json = "1" +ureq = "3" + [lib] path = "src/lib.rs" `, @@ -465,7 +628,12 @@ ${module.patterns.map((entry) => pattern(entry)).join("\n\n")} ${constants} -${module.structs.map((entry) => struct(entry)).join("\n\n")} +${module.errors.map((entry) => error(entry)).join("\n\n")} + +${module.structs + .filter((entry) => entry.external !== true) + .map((entry) => struct(entry)) + .join("\n\n")} ${module.data.map((entry) => data(entry)).join("\n\n")} diff --git a/spec/bridge/compiler/targets/typescript.ts b/spec/bridge/compiler/targets/typescript.ts index 3df688615..76965e0b2 100644 --- a/spec/bridge/compiler/targets/typescript.ts +++ b/spec/bridge/compiler/targets/typescript.ts @@ -7,22 +7,28 @@ */ import { readFileSync } from "node:fs"; import { resolve } from "node:path"; -import type { - CharClass, - DataDecl, - EnumDecl, - Expr, - FuncDecl, - Module, - PatternDecl, - Stmt, - StructDecl, - Ty, + +import { + type CharClass, + type DataDecl, + type EnumDecl, + type ErrorDecl, + type Expr, + type FuncDecl, + type Module, + type PatternDecl, + type Stmt, + type StructDecl, + type Ty, } from "../ir.ts"; +import { optionReads, pascal } from "../kit.ts"; /** The record types of the module being emitted, for the field level casts. */ let structs = new Map(); +/** The functions that wait on the network, and are therefore `async` here. */ +let blocking = new Set(); + const RUNTIME = resolve(import.meta.dirname, "../runtime/typescript.ts"); /** @@ -54,26 +60,39 @@ const lit = (value: string): string => { */ const type = (ty: Ty): string => { switch (ty.k) { - case "string": + case "string": { return "string"; - case "int": + } + case "int": { return "number"; - case "bool": + } + case "bool": { return "boolean"; - case "void": + } + case "void": { return "void"; - case "json": + } + case "json": { return "unknown"; - case "scalar": + } + case "scalar": { return "string | number"; - case "enum": + } + case "enum": { return ty.name; - case "list": + } + case "tasks": { + return `Attempts<${type(ty.of)}>`; + } + case "list": { return `${type(ty.of)}[]`; - case "opt": + } + case "opt": { return `${type(ty.of)} | undefined`; - case "named": + } + case "named": { return ty.name; + } } }; @@ -83,34 +102,45 @@ const type = (ty: Ty): string => { * @param {Expr} expr - The expression. * @returns {string} The TypeScript expression. */ -const expr = (expr_: Expr): string => { - switch (expr_.k) { - case "str": - return lit(expr_.value); - case "int": - return String(expr_.value); - case "bool": - return String(expr_.value); - case "none": +const expr = (node: Expr): string => { + switch (node.k) { + case "str": { + return lit(node.value); + } + case "int": { + return String(node.value); + } + case "bool": { + return String(node.value); + } + case "none": { return "undefined"; - case "ref": - return expr_.name; - case "field": - return `${expr(expr_.target)}.${expr_.name}`; - case "index": - return `${expr(expr_.target)}[${expr(expr_.index)}]`; - case "not": - return `!${expr(expr_.operand)}`; - case "bin": - return `(${expr(expr_.left)} ${expr_.op === "==" ? "===" : expr_.op === "!=" ? "!==" : expr_.op} ${expr(expr_.right)})`; - case "cond": - return `(${expr(expr_.test)} ? ${expr(expr_.whenTrue)} : ${expr(expr_.whenFalse)})`; - case "listOf": - return `[${expr_.items.map((item) => expr(item)).join(", ")}]`; + } + case "ref": { + return node.name; + } + case "field": { + return `${expr(node.target)}.${node.name}`; + } + case "index": { + return `${expr(node.target)}[${expr(node.index)}]`; + } + case "not": { + return `!${expr(node.operand)}`; + } + case "bin": { + return `(${expr(node.left)} ${node.op === "==" ? "===" : node.op === "!=" ? "!==" : node.op} ${expr(node.right)})`; + } + case "cond": { + return `(${expr(node.test)} ? ${expr(node.whenTrue)} : ${expr(node.whenFalse)})`; + } + case "listOf": { + return `[${node.items.map((item) => expr(item)).join(", ")}]`; + } case "struct": { - const declared = structs.get(expr_.name); + const declared = structs.get(node.name); - return `{ ${expr_.fields + return `{ ${node.fields .map((field) => { const ty = declared?.fields.find((candidate) => candidate.name === field.name)?.ty; // A dataset holds plain strings; the closed set is the declaration's promise, and @@ -121,14 +151,16 @@ const expr = (expr_: Expr): string => { }) .join(", ")} }`; } - case "await": - return `await ${expr(expr_.value)}`; - case "optionField": - return `${expr_.target}?.${expr_.field}`; - case "call": - return call(expr_); - default: - throw new Error(`typescript: unsupported expression ${expr_.k}`); + case "await": { + return `await ${expr(node.value)}`; + } + case "optionField": { + // The prologue binds every option read to a local of this name. + return `${node.target}${pascal(node.field)}`; + } + case "call": { + return call(node); + } } }; @@ -136,46 +168,98 @@ const expr = (expr_: Expr): string => { const call = (node: Extract): string => { const args = node.args.map((argument) => expr(argument)); - if (node.callee.k === "user") return `${node.callee.name}(${args.join(", ")})`; + if (node.callee.k === "user") + return `${blocking.has(node.callee.name) ? "await " : ""}${node.callee.name}(${args.join(", ")})`; switch (node.callee.name) { - case "len": + case "len": { return `${args[0]}.length`; - case "listLen": + } + case "listLen": { return `${args[0]}.length`; - case "codeAt": + } + case "codeAt": { return `codeAt(${args[0]}, ${args[1]})`; - case "slice": + } + case "slice": { return `${args[0]}.slice(${args[1]}, ${args[2]})`; - case "upper": + } + case "upper": { return `${args[0]}.toUpperCase()`; - case "trim": + } + case "trim": { return `${args[0]}.trim()`; - case "padStart": + } + case "padStart": { return `padStart(${args[0]}, ${args[1]}, ${args[2]})`; - case "repeat": + } + case "repeat": { return `${args[0]}.repeat(${args[1]})`; - case "classHas": + } + case "classHas": { return `classHas(${args[0]}, ${args[1]})`; - case "keepClass": + } + case "keepClass": { return `keepClass(${args[0]}, ${args[1]})`; - case "patternTest": + } + case "patternTest": { return `patternTest(${args[0]}, ${args[1]})`; - case "asString": + } + case "asString": { return `asString(${args[0]})`; - case "isTruthy": + } + case "isTruthy": { return `isTruthy(${args[0]})`; - case "listPush": + } + case "listPush": { return `${args[0]}.push(${args[1]})`; - case "unwrap": + } + case "unwrap": { // TypeScript's own narrowing has already done this. return args[0]; - case "dataAll": + } + case "dataAll": { return `dataAll(${args[0]})`; - case "dataRows": + } + case "dataRows": { return `dataRows(${args[0]}, ${args[1]})`; - default: + } + case "isNumber": { + return `isNumber(${args[0]})`; + } + case "isList": { + return `isList(${args[0]})`; + } + case "listHas": { + return `listHas(${args[0]}, ${args[1]})`; + } + case "httpGet": { + return `await httpGet(${args.join(", ")})`; + } + case "jsonString": { + return `jsonString(${args[0]}, ${args[1]})`; + } + case "jsonInt": { + return `jsonInt(${args[0]}, ${args[1]})`; + } + case "jsonTruthy": { + return `jsonTruthy(${args[0]}, ${args[1]})`; + } + case "jsonIsTrue": { + return `jsonIsTrue(${args[0]}, ${args[1]})`; + } + case "startAll": { + return `startAll(${args.join(", ")})`; + } + case "firstSuccess": { + return `await firstSuccess(${args[0]})`; + } + case "anyFailedWith": { + return `anyFailedWith(${args[0]}, ${args[1]})`; + } + default: { throw new Error(`typescript: unsupported runtime call ${node.callee.name}`); + } } }; @@ -202,8 +286,9 @@ const stmt = (node: Stmt, indent: string): string => { return `${indent}${node.mutable ? "let" : "const"} ${node.name}${annotation} = ${expr(node.value)};`; } - case "assign": + case "assign": { return `${indent}${node.name} = ${expr(node.value)};`; + } case "if": { const otherwise = node.otherwise.length === 0 @@ -212,12 +297,21 @@ const stmt = (node: Stmt, indent: string): string => { return `${indent}if (${expr(node.test)}) {\n${block(node.then, `${indent}\t`)}\n${indent}}${otherwise}`; } - case "return": + case "return": { return node.value === undefined ? `${indent}return;` : `${indent}return ${expr(node.value)};`; - case "forRange": + } + case "throw": { + return `${indent}throw new ${node.error}(${expr(node.message)});`; + } + case "try": { + return `${indent}try {\n${block(node.body, `${indent}\t`)}\n${indent}} catch (${node.catchName}) {\n${block(node.catchBody, `${indent}\t`)}\n${indent}}`; + } + case "forRange": { return `${indent}for (let ${node.name} = ${expr(node.from)}; ${node.name} < ${expr(node.until)}; ${node.name}++) {\n${block(node.body, `${indent}\t`)}\n${indent}}`; - case "forOf": + } + case "forOf": { return `${indent}for (const ${node.name} of ${expr(node.iterable)}) {\n${block(node.body, `${indent}\t`)}\n${indent}}`; + } case "expr": { const value = node.value; @@ -234,8 +328,6 @@ const stmt = (node: Stmt, indent: string): string => { return `${indent}${expr(value)};`; } - default: - throw new Error(`typescript: unsupported statement ${node.k}`); } }; @@ -252,18 +344,31 @@ const pattern = (entry: PatternDecl): string => ) .join("\n")}\n];`; +/** Renders an error type, with the `name` its own tests assert on. */ +const error = (entry: ErrorDecl): string => + `${entry.doc === "" ? "" : `/** ${entry.doc.split("\n").join(" ")} */\n`}${entry.exported ? "export " : ""}class ${entry.name} extends ${entry.base ?? "Error"} { +\tpublic constructor(message: string) { +\t\tsuper(message); +\t\tthis.name = ${lit(entry.name)}; +\t} +}`; + /** Renders a closed set of strings. */ const enumeration = (entry: EnumDecl): string => - `${entry.doc === "" ? "" : `/**\n${entry.doc - .split("\n") - .map((line) => ` * ${line}`.trimEnd()) - .join("\n")}\n */\n`}export type ${entry.name} =\n${entry.values - .map((value) => `\t| ${lit(value)}`) - .join("\n")};`; + `${ + entry.doc === "" + ? "" + : `/**\n${entry.doc + .split("\n") + .map((line) => ` * ${line}`.trimEnd()) + .join("\n")}\n */\n` + }export type ${entry.name} =\n${entry.values.map((value) => `\t| ${lit(value)}`).join("\n")};`; /** Renders a dataset as the table the runtime materialises. */ const data = (entry: DataDecl): string => { - const rows = entry.rows.map((row) => `\t\t[${row.map((cell) => lit(cell)).join(", ")}],`).join("\n"); + const rows = entry.rows + .map((row) => `\t\t[${row.map((cell) => lit(cell)).join(", ")}],`) + .join("\n"); const groups = Object.entries(entry.groups) .map(([key, indexes]) => `\t\t[${lit(key)}, [${indexes.join(", ")}]],`) .join("\n"); @@ -303,10 +408,27 @@ const func = (entry: FuncDecl): string => { return `${param.name}${param.optional ? "?" : ""}: ${type(declared)}`; }) .join(", "); - const doc = entry.doc === "" ? "" : `/**\n${entry.doc.split("\n").map((line) => ` * ${line}`.trimEnd()).join("\n")}\n */\n`; - const signature = `(${params}): ${entry.isAsync ? `Promise<${type(entry.ret)}>` : type(entry.ret)}`; + const prologue = optionReads(entry) + .map((read) => { + const fallback = read.expr.k === "optionField" ? read.expr.fallback : { k: "none" as const }; + const otherwise = fallback.k === "none" ? "" : ` ?? ${expr(fallback)}`; - return `${doc}${entry.exported ? "export " : ""}const ${entry.name} = ${entry.isAsync ? "async " : ""}${signature} => {\n${block(entry.body, "\t")}\n};`; + return `\tconst ${read.local} = ${read.target}?.${read.field}${otherwise};`; + }) + .join("\n"); + const doc = + entry.doc === "" + ? "" + : `/**\n${entry.doc + .split("\n") + .map((line) => ` * ${line}`.trimEnd()) + .join("\n")}\n */\n`; + // A function that waits on the network is `async` here even though the source is written + // straight-line: colouring the call graph is the emitter's job, not the author's. + const isAsync = entry.isAsync || entry.blocking; + const signature = `(${params}): ${isAsync ? `Promise<${type(entry.ret)}>` : type(entry.ret)}`; + + return `${doc}${entry.exported ? "export " : ""}const ${entry.name} = ${isAsync ? "async " : ""}${signature} => {\n${prologue === "" ? "" : `${prologue}\n`}${block(entry.body, "\t")}\n};`; }; /** @@ -317,6 +439,7 @@ const func = (entry: FuncDecl): string => { */ export const emit = (module: Module): Record => { structs = new Map(module.structs.map((entry) => [entry.name, entry])); + blocking = new Set(module.functions.filter((entry) => entry.blocking).map((entry) => entry.name)); const used = new Set(); const rendered = module.functions.map((entry) => func(entry)).join("\n\n"); @@ -331,6 +454,17 @@ export const emit = (module: Module): Record => { "isTruthy", "dataAll", "dataRows", + "isNumber", + "isList", + "listHas", + "httpGet", + "jsonString", + "jsonInt", + "jsonTruthy", + "jsonIsTrue", + "startAll", + "firstSuccess", + "anyFailedWith", ]) { if (new RegExp(`\\b${helper}\\(`).test(rendered)) used.add(helper); } @@ -338,10 +472,15 @@ export const emit = (module: Module): Record => { if (module.charClasses.length > 0) used.add("type CharClass"); if (module.patterns.length > 0) used.add("type PatternStep"); if (module.data.length > 0) used.add("makeDataset"); + if (used.has("startAll")) used.add("type Attempts"); const imports = [...used].sort(); const constants = module.constants - .map((entry) => `const ${entry.name} = ${expr(entry.expr)};`) + .map((entry) => + entry.ty.k === "list" && entry.ty.of.k === "enum" + ? `const ${entry.name}: ${type(entry.ty)} = ${expr(entry.expr)};` + : `const ${entry.name} = ${expr(entry.expr)};`, + ) .join("\n"); // One file per exported function, in the layout `src/` uses, re-exporting the module. The @@ -353,10 +492,13 @@ export const emit = (module: Module): Record => { const kebab = entry.name.replaceAll(/([a-z0-9])([A-Z])/g, "$1-$2").toLowerCase(); const types = [ - ...module.structs.map((candidate) => candidate.name), - ...module.enums.map((candidate) => candidate.name), - ]; - const exports = [entry.name, ...types.map((name) => `type ${name}`)].join(", "); + ...module.structs.filter((candidate) => candidate.external !== true), + ...module.enums, + ].map((candidate) => `type ${candidate.name}`); + const errors = module.errors + .filter((candidate) => candidate.exported) + .map((candidate) => candidate.name); + const exports = [entry.name, ...errors, ...types].join(", "); shims[`${kebab}/${kebab}.ts`] = `// Code generated from spec/bridge/source/${module.name}.ts. DO NOT EDIT.\nexport { ${exports} } from "../_bridge/${module.name}";\n`; @@ -377,7 +519,12 @@ ${constants} ${module.enums.map((entry) => enumeration(entry)).join("\n\n")} -${module.structs.map((entry) => struct(entry)).join("\n\n")} +${module.errors.map((entry) => error(entry)).join("\n\n")} + +${module.structs + .filter((entry) => entry.external !== true) + .map((entry) => struct(entry)) + .join("\n\n")} ${module.data.map((entry) => data(entry)).join("\n\n")} diff --git a/spec/bridge/conformance/cep.ts b/spec/bridge/conformance/cep.ts new file mode 100644 index 000000000..c43519480 --- /dev/null +++ b/spec/bridge/conformance/cep.ts @@ -0,0 +1,337 @@ +/** + * The CEP scenarios, the expectations recorded from the package this repository ships, and the + * mock server the other six targets are pointed at. + * + * One table drives both sides: `node conformance/cep.ts record` replays the scenarios against + * the shipped package with `fetch` mocked, exactly as the JavaScript suite does, and + * `node conformance/cep.ts serve ` answers the same scenarios over real HTTP so the + * generated Go, Rust, Ruby, Java, C# and Python run against something a real client can talk to. + * + * A scenario is keyed by the CEP, so no target needs to be told which one it is in: the CEP in + * the URL is the whole protocol. + */ +import { mkdtempSync, rmSync, writeFileSync } from "node:fs"; +import { createServer } from "node:http"; +import { tmpdir } from "node:os"; +import { join, resolve } from "node:path"; + +import { build } from "esbuild"; + +const bridge = resolve(import.meta.dirname, ".."); +const root = resolve(bridge, "../.."); + +/** What one provider answers in one scenario. `fail` is a transport failure, not an answer. */ +type Answer = { status: number; body: unknown } | { fail: true }; + +type Scenario = { viacep: Answer; widenet: Answer; brasilapi: Answer }; + +const address = (cep: string): Record => ({ + bairro: "Bela Vista", + cep, + localidade: "São Paulo", + logradouro: "Avenida Paulista", + uf: "SP", +}); + +const widenetAddress = (cep: string): Record => ({ + address: "Avenida Paulista", + city: "São Paulo", + code: cep, + district: "Bela Vista", + ok: true, + state: "SP", + status: 200, +}); + +const brasilApiAddress = (cep: string): Record => ({ + cep, + city: "São Paulo", + neighborhood: "Bela Vista", + state: "SP", + street: "Avenida Paulista", +}); + +const NOT_FOUND_BODY = { errors: [{ message: "CEP não encontrado" }] }; + +/** + * The scenarios, by CEP. Every provider that succeeds in a scenario answers the same address, + * so which one wins the race cannot change the expected result. + */ +export const SCENARIOS: Record = { + // Every provider answers. + "01310100": { + viacep: { status: 200, body: address("01310-100") }, + widenet: { status: 200, body: widenetAddress("01310-100") }, + brasilapi: { status: 200, body: brasilApiAddress("01310100") }, + }, + // Every provider reports a miss, each in its own way. + "00000000": { + viacep: { status: 200, body: { erro: true } }, + widenet: { status: 200, body: { ok: false, status: 404 } }, + brasilapi: { status: 200, body: NOT_FOUND_BODY }, + }, + // Every provider answers an HTTP error. + "00000001": { + viacep: { status: 500, body: {} }, + widenet: { status: 503, body: {} }, + brasilapi: { status: 500, body: {} }, + }, + // Nothing reaches any server. + "00000002": { viacep: { fail: true }, widenet: { fail: true }, brasilapi: { fail: true } }, + // Only BrasilAPI answers, and it is the one the caller gets. + "00000003": { + viacep: { fail: true }, + widenet: { status: 503, body: {} }, + brasilapi: { status: 200, body: brasilApiAddress("00000003") }, + }, + // BrasilAPI reports the miss with a status, the others are simply down: not found wins. + "00000004": { + viacep: { status: 500, body: {} }, + widenet: { status: 503, body: {} }, + brasilapi: { status: 404, body: NOT_FOUND_BODY }, + }, + // A body that is not an object at all. + "00000005": { + viacep: { status: 200, body: "oops" }, + widenet: { status: 200, body: 42 }, + brasilapi: { status: 200, body: null }, + }, + // The optional fields are missing. + "00000006": { + viacep: { status: 200, body: { cep: "00000006" } }, + widenet: { status: 200, body: { code: "00000006", ok: true, status: 200 } }, + brasilapi: { status: 200, body: { cep: "00000006" } }, + }, + // ViaCEP answers fields that are not strings. + "00000007": { + viacep: { status: 200, body: { ...address("00000007"), localidade: null, uf: 12 } }, + widenet: { status: 503, body: {} }, + brasilapi: { status: 500, body: {} }, + }, + // The CEP comes back masked and has to be stripped. + "00000008": { + viacep: { status: 200, body: address("00000-008") }, + widenet: { status: 200, body: widenetAddress("00000-008") }, + brasilapi: { status: 200, body: brasilApiAddress("00000-008") }, + }, + // An empty CEP in the body is a miss, whatever else the body holds. + "00000009": { + viacep: { status: 200, body: { ...address(""), cep: "" } }, + widenet: { status: 200, body: { ...widenetAddress(""), code: "" } }, + brasilapi: { status: 200, body: { ...brasilApiAddress(""), cep: "" } }, + }, + // Widenet's own flags disagree with its body. + "00000010": { + viacep: { status: 500, body: {} }, + widenet: { status: 200, body: { code: "00000010", ok: false, status: 200 } }, + brasilapi: { status: 500, body: {} }, + }, + "00000011": { + viacep: { status: 500, body: {} }, + widenet: { status: 200, body: { code: "00000011", ok: true, status: 404 } }, + brasilapi: { status: 500, body: {} }, + }, + // A miss reported alongside a CEP is still a miss. + "00000012": { + viacep: { status: 200, body: { cep: "00000-012", erro: true } }, + widenet: { status: 503, body: {} }, + brasilapi: { status: 200, body: { ...brasilApiAddress("00000012"), ...NOT_FOUND_BODY } }, + }, + // One provider misses and the other is down: the miss is what the caller hears about. + "00000013": { + viacep: { status: 200, body: { erro: true } }, + widenet: { fail: true }, + brasilapi: { fail: true }, + }, +}; + +/** The provider sets a case can ask for. `-` is "the caller named none". */ +type Providers = string; + +type Case = { cep: string; kind: "string" | "number"; providers: Providers }; + +const EVERY_PROVIDER = [ + "-", + "viacep", + "widenet", + "brasilapi", + "viacep|brasilapi", + "viacep|widenet|brasilapi", +]; + +const cases: Case[] = []; + +for (const cep of Object.keys(SCENARIOS)) { + for (const providers of EVERY_PROVIDER) cases.push({ cep, kind: "string", providers }); +} + +// The inputs that never reach a provider. +for (const cep of ["12345", "123456789", "", "1310100", "abc", "0131010a"]) + cases.push({ cep, kind: "string", providers: "-" }); + +// A mask is stripped, and a number is padded; both land on the first scenario. +cases.push( + { cep: "01310-100", kind: "string", providers: "-" }, + { cep: "01.310-100", kind: "string", providers: "-" }, + { cep: "1310100", kind: "number", providers: "-" }, + { cep: "1310100", kind: "number", providers: "brasilapi" }, +); + +// Provider lists that name nothing usable. +for (const providers of ["[]", "invalid", "constructor|toString", "VIACEP"]) + cases.push({ cep: "01310100", kind: "string", providers }); + +// An unknown name among known ones is dropped rather than fatal. +cases.push({ cep: "01310100", kind: "string", providers: "viacep|invalid|brasilapi" }); + +/** The values a `providers` option can take that are not a list at all. */ +export const NOT_A_LIST: Record = { + "!null": null, + "!string": "viacep", + "!number": 5, + "!object": {}, + "!bool": true, +}; + +for (const providers of Object.keys(NOT_A_LIST)) + cases.push({ cep: "01310100", kind: "string", providers }); + +/** Reads a `providers` cell back into the value the call takes. */ +const optionsOf = (providers: Providers): Record | undefined => { + if (providers === "-") return undefined; + if (providers === "[]") return { providers: [] }; + if (providers.startsWith("!")) return { providers: NOT_A_LIST[providers] }; + + return { providers: providers.split("|") }; +}; + +/** The answer a provider gives for a CEP, or a 404 when the scenario does not know it. */ +export const answerFor = (provider: keyof Scenario, cep: string): Answer => { + const scenario = SCENARIOS[cep]; + + if (scenario === undefined) return { status: 404, body: NOT_FOUND_BODY }; + + return scenario[provider]; +}; + +/** Which provider a mock server path belongs to. */ +export const providerOf = (path: string): keyof Scenario | undefined => { + if (path.includes("viacep.com.br")) return "viacep"; + if (path.includes("widenet.com.br")) return "widenet"; + if (path.includes("brasilapi.com.br")) return "brasilapi"; + + return undefined; +}; + +/** The CEP a mock server path asks about. */ +export const cepOf = (path: string): string => { + const digits = path.replaceAll(/\D/g, ""); + + return digits.slice(-8); +}; + +const serve = (port: number): void => { + const server = createServer((request, response) => { + const path = request.url ?? ""; + const provider = providerOf(path); + const answer = + provider === undefined ? { status: 404, body: {} } : answerFor(provider, cepOf(path)); + + if ("fail" in answer) { + request.socket.destroy(); + + return; + } + + response.writeHead(answer.status, { "content-type": "application/json; charset=utf-8" }); + response.end(JSON.stringify(answer.body)); + }); + + server.listen(port, "127.0.0.1", () => { + console.log(`cep mock server on http://127.0.0.1:${port}`); + }); +}; + +const record = async (): Promise => { + const outDir = mkdtempSync(join(tmpdir(), "brutils-cep-")); + const bundlePath = join(outDir, "shipped.mjs"); + + await build({ + entryPoints: [resolve(root, "src/index.ts")], + bundle: true, + format: "esm", + platform: "neutral", + outfile: bundlePath, + logLevel: "error", + }); + + const shipped = (await import(bundlePath)) as { + getAddressInfoByCep: ( + cep: string | number, + options?: Record, + ) => Promise>; + }; + + rmSync(outDir, { recursive: true, force: true }); + + const realFetch = globalThis.fetch; + + globalThis.fetch = ((input: unknown): Promise => { + const url = String(input); + const provider = providerOf(url); + const answer = + provider === undefined ? { status: 404, body: {} } : answerFor(provider, cepOf(url)); + + if ("fail" in answer) { + // The shipped `fetchWithRetry` retries on a transient transport failure, so the mock + // reports one the same way the mock server does by closing the socket. + const error = new Error("fetch failed"); + + (error as { cause?: unknown }).cause = { code: "ECONNRESET" }; + + return Promise.reject(error); + } + + return Promise.resolve({ + ok: answer.status >= 200 && answer.status < 300, + status: answer.status, + json: () => Promise.resolve(answer.body), + }); + }) as typeof fetch; + + const lines = ["cep\tkind\tproviders\toutcome\tdetail"]; + + for (const entry of cases) { + const input = entry.kind === "number" ? Number(entry.cep) : entry.cep; + let outcome = "ok"; + let detail = ""; + + try { + const found = await shipped.getAddressInfoByCep(input, optionsOf(entry.providers)); + + detail = [ + found["cep"], + found["state"], + found["city"], + found["neighborhood"], + found["street"], + ].join("|"); + } catch (error) { + outcome = "error"; + detail = `${(error as Error).name}|${(error as Error).message}`; + } + + lines.push([entry.cep, entry.kind, entry.providers, outcome, detail].join("\t")); + } + + globalThis.fetch = realFetch; + + writeFileSync(resolve(bridge, "conformance/cep.expected.tsv"), `${lines.join("\n")}\n`); + + console.log(`${cases.length} CEP cases recorded from the shipped package`); +}; + +const [command, argument] = process.argv.slice(2); + +if (command === "serve") serve(Number(argument)); +else await record(); diff --git a/spec/bridge/conformance/drivers.ts b/spec/bridge/conformance/drivers.ts index 1654a5ac9..020ee1f63 100644 --- a/spec/bridge/conformance/drivers.ts +++ b/spec/bridge/conformance/drivers.ts @@ -9,7 +9,8 @@ */ import { mkdirSync, readFileSync, writeFileSync } from "node:fs"; import { dirname, resolve } from "node:path"; -import type { Case } from "./vectors.ts"; + +import { type Case } from "./vectors.ts"; const bridge = resolve(import.meta.dirname, ".."); const vectors = JSON.parse(readFileSync(resolve(bridge, "conformance/vectors.json"), "utf8")) as { @@ -18,7 +19,10 @@ const vectors = JSON.parse(readFileSync(resolve(bridge, "conformance/vectors.jso /** Escapes the three characters the table format reserves. */ const cell = (value: string): string => - value.replaceAll("\\", "\\\\").replaceAll("\t", "\\t").replaceAll("\n", "\\n"); + value + .replaceAll("\\", String.raw`\\`) + .replaceAll("\t", String.raw`\t`) + .replaceAll("\n", String.raw`\n`); const columns = ["fn", "input", "kind", "version", "pad", "obfuscate", "expected"]; const lines = [columns.join("\t")]; @@ -49,6 +53,7 @@ import { readFileSync } from "node:fs"; import { resolve } from "node:path"; import { formatCnpj, isValidCnpj } from "./_bridge/cnpj.ts"; import { type StateCode, getMunicipalities } from "./_bridge/municipalities.ts"; +import { type CepProvider, getAddressInfoByCep } from "./_bridge/cep.ts"; const table = readFileSync(resolve(import.meta.dirname, "../../conformance/vectors.tsv"), "utf8"); const unescape = (value: string): string => @@ -110,7 +115,52 @@ for (let index = 0; index < Math.max(dump.length, expectedDump.length); index++) } console.log(\`typescript: \${expectedDump.length - dumpFailed}/\${expectedDump.length} municipality lines matched\`); -process.exit(failed === 0 && dumpFailed === 0 ? 0 : 1); + +const NOT_A_LIST: Record = { + "!null": null, + "!string": "viacep", + "!number": 5, + "!object": {}, + "!bool": true, +}; + +const cepTable = readFileSync(resolve(import.meta.dirname, "../../conformance/cep.expected.tsv"), "utf8") + .trimEnd() + .split("\\n") + .slice(1); +let cepPassed = 0; +let cepFailed = 0; + +for (const line of cepTable) { + const [rawCep, kind, providers, outcome, detail] = line.split("\\t"); + const value = kind === "number" ? Number(rawCep) : rawCep; + let options: { providers?: CepProvider[] } | undefined; + + if (providers === "[]") options = { providers: [] }; + else if (providers.startsWith("!")) options = { providers: NOT_A_LIST[providers] as CepProvider[] }; + else if (providers !== "-") options = { providers: providers.split("|") as CepProvider[] }; + + let actual: string; + + try { + const found = await getAddressInfoByCep(value, options); + + actual = \`ok\\t\${found.cep}|\${found.state}|\${found.city}|\${found.neighborhood}|\${found.street}\`; + } catch (error) { + actual = \`error\\t\${(error as Error).name}|\${(error as Error).message}\`; + } + + if (actual === \`\${outcome}\\t\${detail}\`) cepPassed++; + else { + cepFailed++; + + if (cepFailed <= 5) + console.error(\`FAIL cep(\${rawCep}, \${providers}) expected \${outcome}/\${detail} got \${actual.replace("\\t", "/")}\`); + } +} + +console.log(\`typescript: \${cepPassed}/\${cepPassed + cepFailed} CEP cases matched\`); +process.exit(failed === 0 && dumpFailed === 0 && cepFailed === 0 ? 0 : 1); `, "out/python/conformance.py": `# Code generated by spec/bridge/conformance/drivers.ts. DO NOT EDIT. @@ -129,6 +179,10 @@ from brutils_bridge.cnpj import ( # noqa: E402 is_valid_cnpj, ) from brutils_bridge.municipalities import get_municipalities # noqa: E402 +from brutils_bridge.cep import ( # noqa: E402 + GetAddressInfoByCepOptions, + get_address_info_by_cep, +) def unescape(value): @@ -202,7 +256,46 @@ for index in range(max(len(dump), len(expected_dump))): print(f"FAIL municipalities line {index + 1}: expected {want!r} got {got!r}", file=sys.stderr) print(f"python: {len(expected_dump) - dump_failed}/{len(expected_dump)} municipality lines matched") -sys.exit(0 if failed == 0 and dump_failed == 0 else 1) + +NOT_A_LIST = {"!null": None, "!string": "viacep", "!number": 5, "!object": {}, "!bool": True} +cep_passed = 0 +cep_failed = 0 +cep_skipped = 0 + +for line in (CONFORMANCE / "cep.expected.tsv").read_text(encoding="utf-8").rstrip("\\n").split("\\n")[1:]: + raw_cep, kind, providers, outcome, detail = line.split("\\t") + + # Python's None is both "absent" and "null", so a null providers option cannot be written. + if providers == "!null": + cep_skipped += 1 + continue + + value = int(raw_cep) if kind == "number" else raw_cep + options = None + + if providers == "[]": + options = GetAddressInfoByCepOptions(providers=[]) + elif providers.startswith("!"): + options = GetAddressInfoByCepOptions(providers=NOT_A_LIST[providers]) + elif providers != "-": + options = GetAddressInfoByCepOptions(providers=providers.split("|")) + + try: + found = get_address_info_by_cep(value, options) + actual = "ok\\t" + "|".join([found.cep, found.state, found.city, found.neighborhood, found.street]) + except Exception as error: # noqa: BLE001 + actual = f"error\\t{type(error).__name__}|{error}" + + if actual == f"{outcome}\\t{detail}": + cep_passed += 1 + else: + cep_failed += 1 + + if cep_failed <= 5: + print(f"FAIL cep({raw_cep}, {providers}) expected {outcome}/{detail} got {actual}", file=sys.stderr) + +print(f"python: {cep_passed}/{cep_passed + cep_failed} CEP cases matched ({cep_skipped} not expressible)") +sys.exit(0 if failed == 0 and dump_failed == 0 and cep_failed == 0 else 1) `, "out/go/conformance/main.go": `// Code generated by spec/bridge/conformance/drivers.ts. DO NOT EDIT. @@ -211,13 +304,16 @@ package main import ( "bufio" + "errors" "fmt" "os" "strconv" "strings" + "brazilianutils/bridge/cep" "brazilianutils/bridge/cnpj" "brazilianutils/bridge/municipalities" + "brazilianutils/bridge/runtime" ) func unescape(value string) string { @@ -372,7 +468,70 @@ func main() { fmt.Printf("go: %d/%d municipality lines matched\\n", len(expectedDump)-dumpFailed, len(expectedDump)) - if failed > 0 || dumpFailed > 0 { + cepRaw, err := os.ReadFile("../../conformance/cep.expected.tsv") + + if err != nil { + panic(err) + } + + cepPassed := 0 + cepFailed := 0 + cepSkipped := 0 + + for _, line := range strings.Split(strings.TrimRight(string(cepRaw), "\\n"), "\\n")[1:] { + parts := strings.Split(line, "\\t") + rawCep, kind, providers, outcome, detail := parts[0], parts[1], parts[2], parts[3], parts[4] + + // A number input and a providers option that is not a list have no Go form. + if kind == "number" || strings.HasPrefix(providers, "!") { + cepSkipped++ + + continue + } + + var options *cep.GetAddressInfoByCepOptions + + if providers != "-" { + named := []string{} + + if providers != "[]" { + named = strings.Split(providers, "|") + } + + options = &cep.GetAddressInfoByCepOptions{Providers: &named} + } + + found, err := cep.GetAddressInfoByCep(rawCep, options) + actual := "" + + if err == nil { + actual = fmt.Sprintf("ok\\t%s|%s|%s|%s|%s", found.Cep, found.State, found.City, found.Neighborhood, found.Street) + } else { + kindName := "" + + var raised *runtime.Error + + if errors.As(err, &raised) { + kindName = raised.Kind() + } + + actual = fmt.Sprintf("error\\t%s|%s", kindName, err.Error()) + } + + if actual == outcome+"\\t"+detail { + cepPassed++ + } else { + cepFailed++ + + if cepFailed <= 5 { + fmt.Fprintf(os.Stderr, "FAIL cep(%s, %s) expected %s/%s got %s\\n", rawCep, providers, outcome, detail, actual) + } + } + } + + fmt.Printf("go: %d/%d CEP cases matched (%d not expressible)\\n", cepPassed, cepPassed+cepFailed, cepSkipped) + + if failed > 0 || dumpFailed > 0 || cepFailed > 0 { os.Exit(1) } } @@ -381,6 +540,7 @@ func main() { "out/rust/src/bin/conformance.rs": `// Code generated by spec/bridge/conformance/drivers.ts. DO NOT EDIT. use brazilian_utils_bridge::cnpj; +use brazilian_utils_bridge::cep; use brazilian_utils_bridge::municipalities; fn unescape(value: &str) -> String { @@ -476,7 +636,56 @@ fn main() { println!("rust: {}/{} municipality lines matched", expected_dump.len() - dump_failed, expected_dump.len()); - if failed > 0 || dump_failed > 0 { + let cep_raw = std::fs::read_to_string("../../conformance/cep.expected.tsv").expect("cep"); + let mut cep_passed = 0; + let mut cep_failed = 0; + let mut cep_skipped = 0; + + for line in cep_raw.trim_end_matches('\\n').split('\\n').skip(1) { + let parts: Vec<&str> = line.split('\\t').collect(); + let (raw_cep, kind, providers, outcome, detail) = (parts[0], parts[1], parts[2], parts[3], parts[4]); + + // A number input and a providers option that is not a list have no Rust form. + if kind == "number" || providers.starts_with('!') { + cep_skipped += 1; + + continue; + } + + let options = if providers == "-" { + None + } else { + let named: Vec = if providers == "[]" { + Vec::new() + } else { + providers.split('|').map(str::to_string).collect() + }; + + Some(cep::GetAddressInfoByCepOptions { providers: Some(named) }) + }; + + let actual = match cep::get_address_info_by_cep(raw_cep, options.as_ref()) { + Ok(found) => format!( + "ok\\t{}|{}|{}|{}|{}", + found.cep, found.state, found.city, found.neighborhood, found.street + ), + Err(error) => format!("error\\t{}|{}", error.kind(), error.message), + }; + + if actual == format!("{}\\t{}", outcome, detail) { + cep_passed += 1; + } else { + cep_failed += 1; + + if cep_failed <= 5 { + eprintln!("FAIL cep({}, {}) expected {}/{} got {}", raw_cep, providers, outcome, detail, actual); + } + } + } + + println!("rust: {}/{} CEP cases matched ({} not expressible)", cep_passed, cep_passed + cep_failed, cep_skipped); + + if failed > 0 || dump_failed > 0 || cep_failed > 0 { std::process::exit(1); } } @@ -487,6 +696,7 @@ fn main() { require_relative 'lib/brazilian_utils_bridge/cnpj' require_relative 'lib/brazilian_utils_bridge/municipalities' +require_relative 'lib/brazilian_utils_bridge/cep' def unescape(value) value.gsub('\\\\t', "\\t").gsub('\\\\n', "\\n").gsub('\\\\\\\\', '\\\\') @@ -558,7 +768,53 @@ dump_failed = 0 end puts "ruby: #{expected_dump.length - dump_failed}/#{expected_dump.length} municipality lines matched" -exit(failed.zero? && dump_failed.zero? ? 0 : 1) + +NOT_A_LIST = { '!string' => 'viacep', '!number' => 5, '!object' => {}, '!bool' => true }.freeze +cep_passed = 0 +cep_failed = 0 +cep_skipped = 0 +Cep = BrazilianUtilsBridge::Cep + +File.read(File.join(conformance, 'cep.expected.tsv'), encoding: 'UTF-8') + .chomp("\n").split("\n", -1).drop(1).each do |line| + raw_cep, kind, providers, outcome, detail = line.split("\t", -1) + + # Ruby's nil is both "absent" and "null", so a null providers option cannot be written. + if providers == '!null' + cep_skipped += 1 + next + end + + value = kind == 'number' ? raw_cep.to_i : raw_cep + options = + if providers == '-' + nil + elsif providers == '[]' + Cep::GetAddressInfoByCepOptions.new(providers: []) + elsif providers.start_with?('!') + Cep::GetAddressInfoByCepOptions.new(providers: NOT_A_LIST[providers]) + else + Cep::GetAddressInfoByCepOptions.new(providers: providers.split('|')) + end + + actual = + begin + found = Cep.get_address_info_by_cep(value, options) + "ok\t#{[found.cep, found.state, found.city, found.neighborhood, found.street].join('|')}" + rescue StandardError => e + "error\t#{e.class.name.split('::').last}|#{e.message}" + end + + if actual == "#{outcome}\t#{detail}" + cep_passed += 1 + else + cep_failed += 1 + warn "FAIL cep(#{raw_cep}, #{providers}) expected #{outcome}/#{detail} got #{actual}" if cep_failed <= 5 + end +end + +puts "ruby: #{cep_passed}/#{cep_passed + cep_failed} CEP cases matched (#{cep_skipped} not expressible)" +exit(failed.zero? && dump_failed.zero? && cep_failed.zero? ? 0 : 1) `, "out/java/Conformance.java": `// Code generated by spec/bridge/conformance/drivers.ts. DO NOT EDIT. @@ -670,7 +926,60 @@ public final class Conformance { System.out.printf("java: %d/%d municipality lines matched%n", expectedDump.length - dumpFailed, expectedDump.length); - if (failed > 0 || dumpFailed > 0) { + int cepPassed = 0; + int cepFailed = 0; + int cepSkipped = 0; + + for (String row : Files.readString(conformance.resolve("cep.expected.tsv")).stripTrailing().split("\\n", -1)) { + if (row.startsWith("cep\\t")) { + continue; + } + + String[] cells = row.split("\\t", -1); + String rawCep = cells[0]; + String providers = cells[2]; + + // A number input and a providers option that is not a list have no Java form. + if (cells[1].equals("number") || providers.startsWith("!")) { + cepSkipped++; + + continue; + } + + GetAddressInfoByCepOptions cepOptions = null; + + if (!providers.equals("-")) { + cepOptions = new GetAddressInfoByCepOptions(); + cepOptions.providers = providers.equals("[]") + ? java.util.List.of() + : java.util.List.of(providers.split("\\\\|", -1)); + } + + String actual; + + try { + AddressInfo found = Cep.getAddressInfoByCep(rawCep, cepOptions); + + actual = "ok\\t" + found.cep + "|" + found.state + "|" + found.city + "|" + + found.neighborhood + "|" + found.street; + } catch (RuntimeException error) { + actual = "error\\t" + error.getClass().getSimpleName() + "|" + error.getMessage(); + } + + if (actual.equals(cells[3] + "\\t" + cells[4])) { + cepPassed++; + } else { + cepFailed++; + + if (cepFailed <= 5) { + System.err.printf("FAIL cep(%s, %s) expected %s/%s got %s%n", rawCep, providers, cells[3], cells[4], actual); + } + } + } + + System.out.printf("java: %d/%d CEP cases matched (%d not expressible)%n", cepPassed, cepPassed + cepFailed, cepSkipped); + + if (failed > 0 || dumpFailed > 0 || cepFailed > 0) { System.exit(1); } } @@ -691,7 +1000,7 @@ public static class Conformance return value.Replace("\\\\t", "\\t").Replace("\\\\n", "\\n").Replace("\\\\\\\\", "\\\\"); } - public static int Main(string[] args) + public static async System.Threading.Tasks.Task Main(string[] args) { var lines = File.ReadAllLines(args[0]); var passed = 0; @@ -802,7 +1111,72 @@ public static class Conformance Console.WriteLine($"csharp: {expectedDump.Length - dumpFailed}/{expectedDump.Length} municipality lines matched"); - return failed == 0 && dumpFailed == 0 ? 0 : 1; + var cepPassed = 0; + var cepFailed = 0; + var cepSkipped = 0; + + foreach (var row in File.ReadAllText(Path.Combine(conformance, "cep.expected.tsv")).TrimEnd('\\n').Split('\\n')) + { + if (row.StartsWith("cep\\t")) + { + continue; + } + + var cells = row.Split('\\t'); + var rawCep = cells[0]; + var providers = cells[2]; + + // A number input and a providers option that is not a list have no C# form. + if (cells[1] == "number" || providers.StartsWith("!")) + { + cepSkipped++; + + continue; + } + + GetAddressInfoByCepOptions cepOptions = null; + + if (providers != "-") + { + cepOptions = new GetAddressInfoByCepOptions + { + Providers = providers == "[]" + ? new System.Collections.Generic.List() + : new System.Collections.Generic.List(providers.Split('|')), + }; + } + + string actual; + + try + { + var found = await Cep.GetAddressInfoByCep(rawCep, cepOptions); + + actual = $"ok\\t{found.Cep}|{found.State}|{found.City}|{found.Neighborhood}|{found.Street}"; + } + catch (Exception error) + { + actual = $"error\\t{error.GetType().Name}|{error.Message}"; + } + + if (actual == cells[3] + "\\t" + cells[4]) + { + cepPassed++; + } + else + { + cepFailed++; + + if (cepFailed <= 5) + { + Console.Error.WriteLine($"FAIL cep({rawCep}, {providers}) expected {cells[3]}/{cells[4]} got {actual}"); + } + } + } + + Console.WriteLine($"csharp: {cepPassed}/{cepPassed + cepFailed} CEP cases matched ({cepSkipped} not expressible)"); + + return failed == 0 && dumpFailed == 0 && cepFailed == 0 ? 0 : 1; } } `, @@ -815,4 +1189,6 @@ for (const [path, contents] of Object.entries(files)) { writeFileSync(full, contents); } -console.log(`wrote ${tablePath} (${lines.length - 1} rows) and ${Object.keys(files).length} drivers`); +console.log( + `wrote ${tablePath} (${lines.length - 1} rows) and ${Object.keys(files).length} drivers`, +); diff --git a/spec/bridge/conformance/municipalities.ts b/spec/bridge/conformance/municipalities.ts index 019561f1a..9913f6a90 100644 --- a/spec/bridge/conformance/municipalities.ts +++ b/spec/bridge/conformance/municipalities.ts @@ -10,6 +10,7 @@ import { mkdtempSync, rmSync, writeFileSync } from "node:fs"; import { tmpdir } from "node:os"; import { join, resolve } from "node:path"; + import { build } from "esbuild"; const bridge = resolve(import.meta.dirname, ".."); @@ -89,4 +90,6 @@ for (const key of KEYS) { writeFileSync(resolve(bridge, "conformance/municipalities.expected.txt"), `${lines.join("\n")}\n`); writeFileSync(resolve(bridge, "conformance/municipalities.keys.txt"), `${KEYS.join("\n")}\n`); -console.log(`${KEYS.length} keys, ${lines.length - KEYS.length} rows recorded from the shipped package`); +console.log( + `${KEYS.length} keys, ${lines.length - KEYS.length} rows recorded from the shipped package`, +); diff --git a/spec/bridge/conformance/run-all.sh b/spec/bridge/conformance/run-all.sh index 12c6642a9..c882a4ed2 100644 --- a/spec/bridge/conformance/run-all.sh +++ b/spec/bridge/conformance/run-all.sh @@ -1,15 +1,21 @@ #!/usr/bin/env bash -# Regenerates every target and replays the recorded vectors through all seven of them. +# Regenerates every target and replays the recorded expectations through all seven of them. # -# The vectors and the municipality dump are recordings of the JavaScript package this -# repository ships, so a green run means the generated code answers exactly what the -# handwritten code answers, in every language. +# Three recordings, all taken from the JavaScript package this repository ships: the CNPJ +# vectors, the municipality dump, and the CEP scenarios. A green run means the generated code +# answers exactly what the handwritten code answers, in every language. +# +# The CEP replay needs somewhere to send its requests, so the same scenario table is served +# over HTTP on a local port and every target is pointed at it through the runtime's +# BRUTILS_BRIDGE_HTTP_ORIGIN hook. # # Usage: `bash spec/bridge/conformance/run-all.sh` set -uo pipefail bridge="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" out="${bridge}/out" +port="${BRUTILS_BRIDGE_PORT:-18080}" +export BRUTILS_BRIDGE_HTTP_ORIGIN="http://127.0.0.1:${port}" status=0 step() { @@ -30,11 +36,18 @@ run() { step "recording the expectations from the package this repository ships" node "${bridge}/conformance/vectors.ts" node "${bridge}/conformance/municipalities.ts" +node "${bridge}/conformance/cep.ts" step "compiling source/ into every target" node "${bridge}/compiler/cli.ts" node "${bridge}/conformance/drivers.ts" +step "serving the CEP scenarios on ${BRUTILS_BRIDGE_HTTP_ORIGIN}" +node "${bridge}/conformance/cep.ts" serve "${port}" & +server=$! +trap 'kill "${server}" 2>/dev/null' EXIT +sleep 1 + step "typescript" run typescript bash -c "cd '${out}/typescript' && node conformance.ts" diff --git a/spec/bridge/conformance/vectors.ts b/spec/bridge/conformance/vectors.ts index 4324c2d21..472118201 100644 --- a/spec/bridge/conformance/vectors.ts +++ b/spec/bridge/conformance/vectors.ts @@ -11,6 +11,7 @@ import { mkdtempSync, readFileSync, readdirSync, rmSync, writeFileSync } from "node:fs"; import { tmpdir } from "node:os"; import { join, resolve } from "node:path"; + import { build } from "esbuild"; const bridge = resolve(import.meta.dirname, ".."); @@ -64,7 +65,8 @@ const buildCorpus = (generateCnpj: (version?: 1 | 2) => string): (string | numbe for (const name of readdirSync(resolve(root, "src/is-valid-cnpj"))) { if (name.endsWith(".test.ts")) - for (const literal of literalsOf(resolve(root, "src/is-valid-cnpj", name))) corpus.add(literal); + for (const literal of literalsOf(resolve(root, "src/is-valid-cnpj", name))) + corpus.add(literal); } for (const name of readdirSync(resolve(root, "src/format-cnpj"))) { @@ -74,7 +76,7 @@ const buildCorpus = (generateCnpj: (version?: 1 | 2) => string): (string | numbe for (let index = 0; index < 120; index++) { const version = index % 2 === 0 ? 1 : 2; - const cnpj = generateCnpj(version as 1 | 2); + const cnpj = generateCnpj(version); corpus.add(cnpj); corpus.add(cnpj.toLowerCase()); @@ -145,4 +147,6 @@ for (const input of corpus) { rmSync(outDir, { recursive: true, force: true }); writeFileSync(resolve(bridge, "conformance/vectors.json"), `${JSON.stringify({ cases })}\n`); -console.log(`${corpus.length} inputs, ${cases.length} expectations recorded from the shipped package`); +console.log( + `${corpus.length} inputs, ${cases.length} expectations recorded from the shipped package`, +); diff --git a/spec/bridge/data/build.ts b/spec/bridge/data/build.ts index 5a66f5d28..608e235a3 100644 --- a/spec/bridge/data/build.ts +++ b/spec/bridge/data/build.ts @@ -16,6 +16,7 @@ import { mkdtempSync, rmSync, writeFileSync } from "node:fs"; import { tmpdir } from "node:os"; import { join, resolve } from "node:path"; + import { build } from "esbuild"; const bridge = resolve(import.meta.dirname, ".."); diff --git a/spec/bridge/package.json b/spec/bridge/package.json index d6a03de3a..402e07821 100644 --- a/spec/bridge/package.json +++ b/spec/bridge/package.json @@ -1,9 +1,9 @@ { "name": "@brazilian-utils/bridge", - "private": true, "version": "0.0.0", - "type": "module", + "private": true, "description": "Build time tool: compiles the portable TypeScript source under source/ into idiomatic native code for every language Brazilian Utils publishes. Not part of the npm package.", + "type": "module", "scripts": { "build": "node compiler/cli.ts", "conformance": "bash conformance/run-all.sh" diff --git a/spec/bridge/source/_std.ts b/spec/bridge/source/_std.ts index 6f2f429aa..ca6ca1394 100644 --- a/spec/bridge/source/_std.ts +++ b/spec/bridge/source/_std.ts @@ -39,9 +39,9 @@ export const isTruthy = (value?: boolean): boolean => Boolean(value); * locale aware comparison is the one thing the seven targets cannot agree on. */ export type Dataset = { - rows: readonly (readonly string[])[]; - groups: Readonly>; - fullOrder: readonly number[]; + rows: string[][]; + groups: Record; + fullOrder: number[]; }; /** @@ -53,18 +53,19 @@ export type Dataset = { export const dataset = (name: string): Dataset => // The compiler replaces every call with the table itself; this body only runs when the // portable source is executed directly, which the conformance harness never does. - JSON.parse( - readFileSync(new URL(`./${name}.data.json`, import.meta.url), "utf8"), - ) as Dataset; + JSON.parse(readFileSync(new URL(`${name}.data.json`, import.meta.url), "utf8")) as Dataset; /** * Every row of a dataset, in the baked full order. * + * The rows are the table's own: nothing reads them twice and nothing writes to them, which is + * what lets every target hand out the same ones instead of copying 5,571 of them per call. + * * @param {Dataset} table - The dataset. * @returns {string[][]} The rows. */ export const dataAll = (table: Dataset): string[][] => - table.fullOrder.map((index) => [...table.rows[index]]); + table.fullOrder.map((index) => table.rows[index]); /** * The rows of a dataset whose first column is the key given, in the baked per key order. An @@ -74,7 +75,161 @@ export const dataAll = (table: Dataset): string[][] => * @param {string} key - The value of the first column. * @returns {string[][]} The rows, empty when the key is unknown. */ -export const dataRows = (table: Dataset, key: string): string[][] => - (Object.hasOwn(table.groups, key) ? table.groups[key] : []).map((index) => [ - ...table.rows[index], - ]); +export const dataRows = (table: Dataset, key: string): string[][] => { + const group = Object.hasOwn(table.groups, key) ? table.groups[key] : []; + + return group.map((index) => table.rows[index]); +}; + +/** What a provider answered: the HTTP status, whether it counts as a success, and the body. */ +export type HttpResponse = { + /** The HTTP status, or `0` when the request never reached the server. */ + status: number; + /** Whether the status is in the 2xx range. */ + ok: boolean; + /** The decoded JSON body, read through the `json*` helpers. */ + body: unknown; +}; + +/** + * Performs an HTTP GET, retrying a transient transport failure with a linear backoff. + * + * A request that never reached the server answers `status: 0`, so a transport failure and an + * HTTP error are told apart the same way in every target. What "transient" means is the host's + * own question, and each runtime answers it with its own client's error codes. + * + * The signature is synchronous on purpose: the author writes straight-line code, and the + * emitters that need a coloured call graph, TypeScript and C#, add `async` and `await` + * themselves. + * + * @param {string} url - The URL to read. + * @param {number} retries - How many retries follow the first attempt. + * @param {number} retryDelayMs - The base delay, multiplied by the attempt number. + * @returns {HttpResponse} The response. + */ +export declare const httpGet: (url: string, retries: number, retryDelayMs: number) => HttpResponse; + +/** + * Whether the caller handed a number where a `string | number` was declared. + * + * Only the dynamically typed targets can answer anything but `false`: elsewhere the parameter + * is a string and the question cannot arise. + * + * @param {string|number} value - The value. + * @returns {boolean} True when it is a number. + */ +export const isNumber = (value: string | number): boolean => typeof value === "number"; + +/** + * Whether a value is a list. Like `isNumber`, only the dynamically typed targets can answer + * anything but `true`. + * + * @param {unknown} value - The value. + * @returns {boolean} True when it is a list. + */ +export const isList = (value: unknown): boolean => Array.isArray(value); + +/** + * Whether a list holds a value. + * + * @param {string[]} list - The list. + * @param {string} value - The value to look for. + * @returns {boolean} True when the list holds it. + */ +export const listHas = (list: readonly string[], value: string): boolean => list.includes(value); + +/** Reads one field of a JSON body, treating anything that is not an object as empty. */ +const jsonField = (body: unknown, key: string): unknown => { + if (body === null || typeof body !== "object" || Array.isArray(body)) return undefined; + + return Object.hasOwn(body, key) ? (body as Record)[key] : undefined; +}; + +/** + * Reads a string field of a JSON body, answering `""` when it is missing or not a string. + * + * @param {unknown} body - The body. + * @param {string} key - The field name. + * @returns {string} The value, or `""`. + */ +export const jsonString = (body: unknown, key: string): string => { + const found = jsonField(body, key); + + return typeof found === "string" ? found : ""; +}; + +/** + * Reads an integer field of a JSON body, answering `-1` when it is missing or not a number. + * + * @param {unknown} body - The body. + * @param {string} key - The field name. + * @returns {number} The value, or `-1`. + */ +export const jsonInt = (body: unknown, key: string): number => { + const found = jsonField(body, key); + + return typeof found === "number" ? Math.trunc(found) : -1; +}; + +/** + * Whether a field of a JSON body is truthy, the way JavaScript reads truthiness. + * + * @param {unknown} body - The body. + * @param {string} key - The field name. + * @returns {boolean} True when the field is set and truthy. + */ +export const jsonTruthy = (body: unknown, key: string): boolean => Boolean(jsonField(body, key)); + +/** + * Whether a field of a JSON body is exactly `true`, which is not the same question as truthy: + * Widenet reports its own success with a boolean and a `1` there would not be one. + * + * @param {unknown} body - The body. + * @param {string} key - The field name. + * @returns {boolean} True when the field is the boolean `true`. + */ +export const jsonIsTrue = (body: unknown, key: string): boolean => jsonField(body, key) === true; + +/** The running attempts of a race. What is inside is the runtime's business, not the source's. */ +export type Attempts = { readonly attempts: unique symbol; readonly of: T }; + +/** + * Starts one attempt per item, all at once. + * + * This is the only concurrency primitive of the portable subset: the author never writes a + * thread, a goroutine or a promise. Every target starts the work the way its own runtime does + * — goroutines in Go, virtual threads in Java, tasks in C#, promises in TypeScript. + * + * @param {Function} run - The function to run per item. + * @param {string[]} items - The items. + * @param {string} argument - A second argument handed to every call. + * @returns {Attempts} The running attempts. + */ +export declare const startAll: ( + run: (item: never, argument: string) => T, + items: readonly string[], + argument: string, +) => Attempts; + +/** + * The value of the first attempt that succeeds, or nothing once every attempt has failed. + * + * @param {Attempts} attempts - The running attempts. + * @returns {unknown} The value, or `undefined`. + */ +export declare const firstSuccess: (attempts: Attempts) => T | undefined; + +/** + * Whether any attempt failed with a given error kind, the kinds it inherits from included. + * + * Only meaningful once `firstSuccess` has answered nothing, which is exactly when every attempt + * has settled. + * + * @param {Attempts} attempts - The attempts. + * @param {Function} kind - The error class to look for. + * @returns {boolean} True when at least one attempt failed with it. + */ +export declare const anyFailedWith: ( + attempts: Attempts, + kind: new (message: string) => Error, +) => boolean; diff --git a/spec/bridge/source/cep.ts b/spec/bridge/source/cep.ts new file mode 100644 index 000000000..2543a11e4 --- /dev/null +++ b/spec/bridge/source/cep.ts @@ -0,0 +1,318 @@ +/** + * Address lookup by CEP, written once. + */ +import { + type HttpResponse, + anyFailedWith, + asString, + firstSuccess, + httpGet, + isList, + isNumber, + jsonIsTrue, + jsonInt, + jsonString, + jsonTruthy, + listHas, + startAll, +} from "./_std.ts"; + +/** Base class of every error `getAddressInfoByCep` rejects with. */ +export class GetAddressInfoByCepError extends Error {} + +/** Thrown by `getAddressInfoByCep` when the value given is not a valid CEP. */ +export class GetAddressInfoByCepValidationError extends GetAddressInfoByCepError {} + +/** Thrown by `getAddressInfoByCep` when no CEP service knows the CEP. */ +export class GetAddressInfoByCepNotFoundError extends GetAddressInfoByCepError {} + +/** Thrown by `getAddressInfoByCep` when every CEP service failed to answer. */ +export class GetAddressInfoByCepServiceError extends GetAddressInfoByCepError {} + +/** + * Raised inside a provider that did not answer. Only whether a failure was a not found is + * looked at when the provider failures are aggregated, so this one never leaves the module. + */ +class CepProviderFailure extends Error {} + +/** The address `getAddressInfoByCep` returns for a CEP. */ +export type AddressInfo = { + /** The 8 digit CEP, no mask. */ + cep: string; + /** Two letter state code, e.g. "SP". */ + state: string; + /** City name. */ + city: string; + /** Neighborhood name, empty when the CEP covers a whole city. */ + neighborhood: string; + /** Street name, empty when the CEP covers a whole city. */ + street: string; +}; + +/** The CEP services `getAddressInfoByCep` can query. */ +export type CepProvider = "viacep" | "widenet" | "brasilapi"; + +/** Options of `getAddressInfoByCep`. */ +export type GetAddressInfoByCepOptions = { + /** + * Which CEP services to race, in the order given (default: `["viacep", "brasilapi"]`; the + * deprecated `"widenet"` provider is excluded from the default list, but can still be + * requested explicitly). + */ + providers?: CepProvider[]; +}; + +const CEP_FORMAT = /^\d{8}$/; +const NON_DIGIT = /\D/g; + +/** The providers raced when the caller names none. */ +const DEFAULT_PROVIDERS: CepProvider[] = ["viacep", "brasilapi"]; + +/** Every provider that can be named, including the deprecated one. */ +const KNOWN_PROVIDERS: CepProvider[] = ["viacep", "widenet", "brasilapi"]; + +/** + * The status BrasilAPI answers an unknown CEP with, alongside an `errors` body. ViaCEP and + * Widenet report a miss inside a 200 body instead, so BrasilAPI is the only provider whose + * not-found signal is an HTTP status. + * + * @see Based on: https://brasilapi.com.br/docs#tag/CEP + */ +const BRASIL_API_NOT_FOUND_STATUS = 404; + +/** How many times a request is retried, and the base delay between attempts. */ +const HTTP_RETRIES = 2; +const HTTP_RETRY_DELAY_MS = 250; + +/** + * Reads the address ViaCEP answers with. + * + * @param {string} cep - The 8 digit CEP. + * @returns {AddressInfo} The address. + * + * @see Based on: https://viacep.com.br/ + */ +const fetchViaCep = (cep: string): AddressInfo => { + const response: HttpResponse = httpGet( + `https://viacep.com.br/ws/${cep}/json/`, + HTTP_RETRIES, + HTTP_RETRY_DELAY_MS, + ); + + if (!response.ok) { + throw new CepProviderFailure("ViaCEP request failed"); + } + + const found = jsonString(response.body, "cep"); + + if (jsonTruthy(response.body, "erro") || found === "") { + throw new GetAddressInfoByCepNotFoundError("CEP não encontrado"); + } + + return { + cep: found.replaceAll(NON_DIGIT, ""), + state: jsonString(response.body, "uf"), + city: jsonString(response.body, "localidade"), + neighborhood: jsonString(response.body, "bairro"), + street: jsonString(response.body, "logradouro"), + }; +}; + +/** + * Reads the address Widenet answers with. + * + * @param {string} cep - The 8 digit CEP. + * @returns {AddressInfo} The address. + */ +const fetchWidenet = (cep: string): AddressInfo => { + const response: HttpResponse = httpGet( + `https://apps.widenet.com.br/busca-cep/api/cep/${cep}.json`, + HTTP_RETRIES, + HTTP_RETRY_DELAY_MS, + ); + + if (!response.ok) { + throw new CepProviderFailure("Widenet request failed"); + } + + const found = jsonString(response.body, "code"); + + if ( + jsonInt(response.body, "status") !== 200 || + !jsonIsTrue(response.body, "ok") || + found === "" + ) { + throw new GetAddressInfoByCepNotFoundError("CEP não encontrado"); + } + + return { + cep: found.replaceAll(NON_DIGIT, ""), + state: jsonString(response.body, "state"), + city: jsonString(response.body, "city"), + neighborhood: jsonString(response.body, "district"), + street: jsonString(response.body, "address"), + }; +}; + +/** + * Reads the address BrasilAPI answers with. + * + * @param {string} cep - The 8 digit CEP. + * @returns {AddressInfo} The address. + * + * @see Based on: https://brasilapi.com.br/docs#tag/CEP + */ +const fetchBrasilApi = (cep: string): AddressInfo => { + const response: HttpResponse = httpGet( + `https://brasilapi.com.br/api/cep/v1/${cep}`, + HTTP_RETRIES, + HTTP_RETRY_DELAY_MS, + ); + + if (response.status === BRASIL_API_NOT_FOUND_STATUS) { + throw new GetAddressInfoByCepNotFoundError("CEP não encontrado"); + } + + if (!response.ok) { + throw new CepProviderFailure("BrasilAPI request failed"); + } + + const found = jsonString(response.body, "cep"); + + if (jsonTruthy(response.body, "errors") || found === "") { + throw new GetAddressInfoByCepNotFoundError("CEP não encontrado"); + } + + return { + cep: found.replaceAll(NON_DIGIT, ""), + state: jsonString(response.body, "state"), + city: jsonString(response.body, "city"), + neighborhood: jsonString(response.body, "neighborhood"), + street: jsonString(response.body, "street"), + }; +}; + +/** + * Asks one named provider for a CEP. + * + * @param {CepProvider} provider - The provider name. + * @param {string} cep - The 8 digit CEP. + * @returns {AddressInfo} The address. + */ +const fetchProvider = (provider: CepProvider, cep: string): AddressInfo => { + if (provider === "viacep") { + return fetchViaCep(cep); + } + + if (provider === "widenet") { + return fetchWidenet(cep); + } + + return fetchBrasilApi(cep); +}; + +/** + * The providers of a list that are known, in the order they were given. + * + * @param {CepProvider[]} given - The names the caller asked for. + * @returns {CepProvider[]} The known ones. + */ +const knownProviders = (given: CepProvider[]): CepProvider[] => { + const kept: CepProvider[] = []; + + for (const provider of given) { + if (listHas(KNOWN_PROVIDERS, provider)) { + kept.push(provider); + } + } + + return kept; +}; + +/** + * Fetches address information for a given CEP using multiple providers simultaneously. + * Returns the result from the first provider that responds successfully. + * + * The providers are started together and raced, not tried one after the other, so a provider + * that is retrying delays nothing for the others: its retries only push back the moment its own + * failure lands, and therefore the moment an all-failed rejection can surface. + * + * @param {string|number} cep - The CEP (Brazilian postal code) to search for. Can be a string or number. + * @param {GetAddressInfoByCepOptions} options - Optional configuration for the function. + * @param {CepProvider[]} options.providers - List of providers to use. Defaults to `["viacep", "brasilapi"]` + * if not specified (the deprecated `"widenet"` provider is excluded from the default list, but can still + * be requested explicitly). + * @returns {Promise} A promise that resolves to the address information. + * @throws {GetAddressInfoByCepValidationError} If the CEP format is invalid, or if + * `options.providers` is given and names no known provider: an empty array, an array of unknown + * names, and a value that is not an array at all (`null` included) all reject this way rather + * than with a raw `TypeError`. + * @throws {GetAddressInfoByCepNotFoundError} If the CEP is not found in any of the services. + * @throws {GetAddressInfoByCepServiceError} If all services are unavailable. + * + * @example + * ```typescript + * // Using the default providers (["viacep", "brasilapi"]) + * const address = await getAddressInfoByCep("01310100"); + * + * // Using specific providers + * const address = await getAddressInfoByCep("01310-100", { + * providers: ["viacep", "brasilapi"] + * }); + * + * // Using number input + * const address = await getAddressInfoByCep(1310100); + * ``` + * + * @see Official: https://www.correios.com.br/enviar/precisa-de-ajuda/tudo-sobre-cep + * @see Based on: https://viacep.com.br/ + * ViaCEP, one of the two default providers. A third-party service, not a Correios one. + * @see Based on: https://brasilapi.com.br/docs#tag/CEP + * BrasilAPI, the other default provider. A third-party service, not a Correios one. + */ +export const getAddressInfoByCep = ( + cep: string | number, + options?: GetAddressInfoByCepOptions, +): AddressInfo => { + let digits = asString(cep).replaceAll(NON_DIGIT, ""); + + if (isNumber(cep)) { + // `padStart` is a no-op when `digits` is already 8 characters or longer. + digits = digits.padStart(8, "0"); + } + + if (!CEP_FORMAT.test(digits)) { + throw new GetAddressInfoByCepValidationError("CEP inválido"); + } + + let chosen: CepProvider[] = DEFAULT_PROVIDERS; + + if (options?.providers !== undefined) { + // A value that is not a list at all reports the same thing as a list of unknown names, + // rather than the raw `TypeError` a filter over it would raise. + if (!isList(options?.providers)) { + throw new GetAddressInfoByCepValidationError("Nenhum provedor válido especificado"); + } + + chosen = knownProviders(options?.providers); + + if (chosen.length === 0) { + throw new GetAddressInfoByCepValidationError("Nenhum provedor válido especificado"); + } + } + + const attempts = startAll(fetchProvider, chosen, digits); + const found = firstSuccess(attempts); + + if (found !== undefined) { + return found; + } + + if (anyFailedWith(attempts, GetAddressInfoByCepNotFoundError)) { + throw new GetAddressInfoByCepNotFoundError("CEP não encontrado em nenhum serviço"); + } + + throw new GetAddressInfoByCepServiceError( + "Todos os serviços estão fora de serviço ou indisponíveis", + ); +}; diff --git a/spec/bridge/source/cnpj.ts b/spec/bridge/source/cnpj.ts index ed28b0a4d..37d2ff40f 100644 --- a/spec/bridge/source/cnpj.ts +++ b/spec/bridge/source/cnpj.ts @@ -46,7 +46,7 @@ const checkDigit = (base: string, weights: number[]): number => { let sum = 0; for (let index = 0; index < weights.length; index++) { - sum = sum + (base.charCodeAt(index) - 48) * weights[index]; + sum += (base.charCodeAt(index) - 48) * weights[index]; } const remainder = sum % 11; @@ -88,7 +88,7 @@ const layout = (value: string, pattern: string, pad: boolean): string => { for (let index = 0; index < pattern.length; index++) { if (pattern.charCodeAt(index) === 48 || pattern.charCodeAt(index) === 42) { - slots = slots + 1; + slots += 1; } } @@ -110,14 +110,14 @@ const layout = (value: string, pattern: string, pad: boolean): string => { } if (slot === 42) { - formatted = formatted + "*"; + formatted += "*"; } else { - formatted = formatted + padded.slice(cursor, cursor + 1); + formatted += padded.slice(cursor, cursor + 1); } - cursor = cursor + 1; + cursor += 1; } else if (cursor < padded.length) { - formatted = formatted + pattern.slice(index, index + 1); + formatted += pattern.slice(index, index + 1); } } diff --git a/spec/bridge/source/municipalities.ts b/spec/bridge/source/municipalities.ts index 7bd82268b..c36eac5d9 100644 --- a/spec/bridge/source/municipalities.ts +++ b/spec/bridge/source/municipalities.ts @@ -61,7 +61,8 @@ const MUNICIPALITIES: Dataset = dataset("municipalities"); const rowToMunicipality = (row: string[]): Municipality => ({ code: row[2], name: row[1], - stateCode: row[0], + // The dataset holds plain strings; `data/build.ts` is what keeps the closed set true. + stateCode: row[0] as StateCode, }); /** diff --git a/vite.config.ts b/vite.config.ts index 29f30671a..301860015 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -150,7 +150,8 @@ export default defineConfig({ // `CHANGELOG.md` is written by release-please (`* ` bullets); formatting it would fail the // Check workflow on every release PR. `spec/vectors` holds the generated conformance // vectors, written on one line on purpose: pretty printing ~10k expectations would multiply - // the file size for a file nobody reads by hand. + // the file size for a file nobody reads by hand, and `spec/bridge/source/*.data.json` and + // `spec/bridge/out` are the same: a generated table and the generated targets. ignorePatterns: [ "dist", "coverage", @@ -161,6 +162,8 @@ export default defineConfig({ "CHANGELOG.md", "spec/vectors", "spec/bench/corpus.json", + "**/spec/bridge/out/**", + "spec/bridge/source/municipalities.data.json", ], singleQuote: false, sortImports: true, @@ -521,6 +524,53 @@ export default defineConfig({ "typescript/no-unsafe-type-assertion": "off", }, }, + { + env: { + node: true, + }, + files: ["spec/bridge/**/*.ts"], + rules: { + // `spec/bridge` is a compiler. Its emitters are one big switch over the IR per + // language, and their product is source code, so a few of the rules that keep + // library code readable work against it here. + // + // Every emitter is a table of one-line renderers (`const lit`, `const type`, + // `const expr`): a `@param`/`@returns` block on each would be three times the + // code and say nothing the signature does not. + "jsdoc/require-param": "off", + "jsdoc/require-returns": "off", + // Generated code is built out of template literals that hold template literals: + // a function body inside a class body inside a file. + "sonarjs/no-nested-template-literals": "off", + // The renderers are mutually recursive by nature (`expr` calls `call` calls + // `expr`), and each one is a wide, flat switch rather than deep logic. + "eslint/no-use-before-define": "off", + "eslint/complexity": "off", + "sonarjs/cognitive-complexity": "off", + "sonarjs/no-nested-conditional": "off", + // A switch over the IR ends in a defensive `default` so an unhandled node fails + // loudly; the rule reads that as a switch that could have listed every case. + "typescript/switch-exhaustiveness-check": "off", + "typescript/consistent-return": "off", + "sonarjs/no-inconsistent-returns": "off", + // The conformance drivers replay recorded cases one at a time on purpose: the + // point is to compare answers, not to be fast. + "eslint/no-await-in-loop": "off", + "promise/prefer-await-to-then": "off", + // `source/_std.ts` is the portable standard library: its members are named after + // what they shadow in each host, `isNumber` and `repeat` included. + "sonarjs/no-built-in-override": "off", + "unicorn/prefer-native-coercion-functions": "off", + // The emitters read the whole IR, so they import every kind of node. + "import/max-dependencies": "off", + // `compiler/frontend.ts` walks the parser's AST, which is untyped by design: + // oxc hands back plain objects, and the frontend is what gives them a shape. + "unicorn/no-abusive-eslint-disable": "off", + // `isTruthy` exists for the case where the flag is missing, so a default value + // would hide the very thing it is there to answer. + "sonarjs/bool-param-default": "off", + }, + }, { env: { node: true, From 3780bd6888d447913e1a15d00f80922ddd9b0617 Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 21 Sep 2026 03:03:26 +0000 Subject: [PATCH 05/13] fix(spec): measure the bindings a package ships, not the ones a script uses MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The bindings investigation concluded that generated source beat every binding. That conclusion came from the wrong measurements: it compared generated source against `ctypes`, Fiddle and a wasm runtime, and never against the mechanism each ecosystem actually ships native code with. Those differ by three orders of magnitude, so the conclusion was wrong for four of the seven ecosystems. Measured properly, per call, against a validator body of 47 ns: | ecosystem | best | mechanism | boundary | | --------- | ----------- | ----------------------------- | -------- | | C# | 76 ns | P/Invoke, SuppressGCTransition| ~1 ns | | Python | 65 ns | CPython extension module | 27 ns | | Ruby | 109 ns | C extension | 65 ns | | Java | 127 ns | Panama FFM, trivial downcall | 62 ns | | Go | 119 ns | cgo | 58 ns | Against each language's own generated source that is 21× for Python, 18× for Ruby, 3.9× for Java, and 4.3× against handwritten for C#, which had no arm at all before. The old numbers stand for what they measured: ctypes is 433 ns of boundary, Fiddle 1,479 ns, wasmtime-py 30 µs. Three details decide which half a binding lands in, and the harness shows each: a `static final` MethodHandle and a global arena in Java (84 ns otherwise), a real extension module rather than an FFI shim in Python and Ruby, and `[SuppressGCTransition]` in C# — the one runtime where the naive version is already fine. What does not change is JavaScript: the package is tree shakeable and a binary core is not, so npm keeps generated source whatever the others do. Go keeps it too, because cgo costs cross compilation, static binaries and CGO_ENABLED=0 for a 74 ns gain. So the answer is a hybrid, and `spec/bridge` now emits both halves from the one source: the Rust target also produces `#[no_mangle] extern "C"` wrappers, a C header, and a crate that builds as `cdylib` and `staticlib`. The CNPJ vectors replay through that ABI from C as an eighth conformance arm — 5,782 of 5,782, the same 18 skips as the other statically typed targets — which is the same surface a CPython extension, a Ruby C extension, a NuGet package over P/Invoke and a JAR over Panama would each call. Shapes the ABI refuses rather than guesses at, and says so in its own output: a function that raises needs an out parameter, one that waits on the network needs a callback, one that answers a list needs an iterator. `getMunicipalities` and `getAddressInfoByCep` stay generated-source only for now. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01UX1gTGeMTyoXQyr1qUoQKd --- .gitignore | 2 + spec/BINDINGS-INVESTIGATION.md | 310 +++++++++++++------ spec/bench/harness/csharp/CsharpBench.csproj | 12 + spec/bench/harness/csharp/Program.cs | 246 +++++++++++++++ spec/bench/harness/java/JavaNativeBench.java | 205 ++++++++++++ spec/bench/harness/python_native.py | 80 +++++ spec/bench/harness/ruby_native.rb | 65 ++++ spec/bench/native/c_bench.c | 150 +++++++++ spec/bench/native/python_cext.c | 80 +++++ spec/bench/native/ruby_cext.c | 47 +++ spec/bench/results.jsonl | 15 + spec/bench/run-native.sh | 69 +++++ spec/bench/table.py | 29 +- spec/bridge/README.md | 38 +++ spec/bridge/compiler/targets/cabi.ts | 251 +++++++++++++++ spec/bridge/compiler/targets/rust.ts | 19 +- spec/bridge/conformance/drivers.ts | 143 +++++++++ spec/bridge/conformance/run-all.sh | 9 +- 18 files changed, 1668 insertions(+), 102 deletions(-) create mode 100644 spec/bench/harness/csharp/CsharpBench.csproj create mode 100644 spec/bench/harness/csharp/Program.cs create mode 100644 spec/bench/harness/java/JavaNativeBench.java create mode 100644 spec/bench/harness/python_native.py create mode 100644 spec/bench/harness/ruby_native.rb create mode 100644 spec/bench/native/c_bench.c create mode 100644 spec/bench/native/python_cext.c create mode 100644 spec/bench/native/ruby_cext.c create mode 100644 spec/bench/run-native.sh create mode 100644 spec/bridge/compiler/targets/cabi.ts diff --git a/.gitignore b/.gitignore index ad8b8d57d..c6411c74d 100644 --- a/.gitignore +++ b/.gitignore @@ -28,3 +28,5 @@ spec/bench/**/target spec/bench/harness/go/generated spec/bench/harness/java/Cpf.java spec/bench/harness/java/SpecRuntime.java +spec/bench/harness/csharp/bin +spec/bench/harness/csharp/obj diff --git a/spec/BINDINGS-INVESTIGATION.md b/spec/BINDINGS-INVESTIGATION.md index 3cfa0c147..238822b1a 100644 --- a/spec/BINDINGS-INVESTIGATION.md +++ b/spec/BINDINGS-INVESTIGATION.md @@ -5,10 +5,23 @@ each language, could Brazilian Utils build the logic once — in Rust, in C, in give every package a **binding** to it? Is there an off the shelf tool for that? And what does it cost at run time? +What is being shared either way is the **utility's implementation**, not the published package. +Every ecosystem keeps writing its own DX by hand: its naming, its option objects, its types, its +docs. That matters for the answer, because a hand-written binding is then no more hand-written +code than the wrapper it sits behind. + +> **Revised.** The first version of this document concluded that generated source beat every +> binding. It had only measured the bindings a script reaches for — `ctypes`, Fiddle, a wasm +> runtime — and not the ones a package ships. A CPython extension is 16× cheaper than `ctypes` +> and P/Invoke costs about a nanosecond, which changes the answer for four of the seven +> ecosystems. [§2](#2-the-boundary-costs-more-than-the-work--but-only-over-the-wrong-boundary) +> has the corrected numbers and what they turn on. + Everything below was measured on this branch. Reproduce with: ```bash bash spec/bench/run-all.sh # every arm, every language +bash spec/bench/run-native.sh # the bindings each ecosystem actually ships bash spec/conformance/run-all.sh # every arm still answers identically ``` @@ -16,22 +29,46 @@ bash spec/conformance/run-all.sh # every arm still answers identically ## The answer -**Generated source wins, and it is not close.** The approach from the previous exploration — -a language neutral spec compiled to idiomatic source per language — beats every binding strategy -once distribution is taken into account, and after two emitter fixes it is also _faster than the -handwritten code it replaces_ in all five languages measured. - -A shared binary core is not useless, but it is a second, optional layer: worth it only for a host -that validates in bulk, never for the npm package, and never as the only implementation. - -| Strategy | Run time | Ship cost | Verdict | -| ---------------------------------------- | ---------------------------------------------------- | -------------------------------------------------------- | ----------------------- | -| **Generated native source** | 0.36×–0.66× of handwritten (i.e. faster) | none: it is just source | **default** | -| Shared core + wasm | 0.12×–15.5× depending entirely on the host's runtime | one 9 KB artifact, plus a runtime dependency per package | optional, batch only | -| Shared core + C ABI (FFI/cgo) | 0.10×–0.45× | a native build per platform × arch, per ecosystem | last resort | -| Off the shelf binding generator (UniFFI) | **3.7× slower than plain Python** | as above | rejected on the numbers | - ---- +**It depends on the ecosystem, and the deciding factor is not speed.** + +The first pass of this document concluded that generated source beat every binding. That +conclusion was drawn from the wrong measurements: it compared generated source against the +bindings a _script_ reaches for — `ctypes`, Fiddle, a wasm runtime — and never against the +bindings a _package_ ships. Those are not the same thing, and they are not close: a CPython +extension module costs 27 ns per call where `ctypes` costs 433 ns, and P/Invoke with the GC +transition suppressed costs about 1 ns. + +Measured properly, with the core called the way each ecosystem actually calls native code: + +| Ecosystem | Best per call | Against its own generated source | Boundary cost | +| ---------- | --------------------------- | -------------------------------- | ------------- | +| **C#** | **76 ns** P/Invoke | 4.3× faster than handwritten | **~1 ns** | +| **Python** | **65 ns** CPython extension | **21× faster** | 27 ns | +| **Ruby** | **109 ns** C extension | **18× faster** | 65 ns | +| **Java** | **127 ns** Panama FFM | 3.9× faster | 62 ns | +| **Go** | 119 ns cgo | 1.6× faster | 58 ns | +| **Node** | 257 ns generated source | binding not available | — | +| **Rust** | 47 ns | it _is_ the core | 0 | + +So a C ABI really is close to free in C#, cheap in Python, and about 60 ns everywhere else — +against a validator body of 47 ns. That is the correction. + +What it does **not** change is the recommendation for the npm package, and that turns out to +decide the shape of the whole thing: + +- **JavaScript cannot take a binary core**, because the package is tree shakeable and a wasm + module is not. One utility as generated source is 509 bytes and disappears when unused; the + wasm core is 9,291 bytes, indivisible, and asynchronous to start. This is not a preference, + it is a requirement, so JavaScript gets generated source whatever the other ecosystems do. +- **Go pays for cgo in something other than nanoseconds.** It loses cross compilation, static + binaries and `CGO_ENABLED=0` builds, for a 74 ns gain. Not worth it. +- **Everywhere else the binding is the better answer**, and the ship cost — a native artifact + per platform × arch — is a cost those ecosystems already pay routinely. + +Which points at a hybrid rather than a winner, and a smaller tool than either option alone: +write the utility once, emit **TypeScript** for npm and **Rust** for the shared core, and let +Python, Ruby, C#, Java and Erlang bind to the compiled core with a hand-written binding. Go +takes generated source. The full recommendation is [at the end](#recommendation). ## How it was measured @@ -50,15 +87,19 @@ rustc 1.94.1, OpenJDK 21.0.10, wasmtime-py 48.0.0, wasmtime gem 48.0.1, wazero 1 ### Arms -| Arm | What it is | -| --------------- | ------------------------------------------------------------------------ | -| `handwritten` | Idiomatic code a contributor would write in that language, regex and all | -| `generated` | The emitter's output for the same spec | -| `wasm` | The Rust core compiled to `wasm32-unknown-unknown`, one call per input | -| `wasm-batch` | Same core, the whole corpus in one call | -| `wasm-callonly` | The boundary alone: same pointer, same length, no marshalling | -| `ffi` / `cgo` | The same core as a `cdylib`, over ctypes / Fiddle / cgo | -| `uniffi` | The same logic behind UniFFI generated Python bindings | +| Arm | What it is | +| --------------- | ------------------------------------------------------------------------- | +| `handwritten` | Idiomatic code a contributor would write in that language, regex and all | +| `generated` | The emitter's output for the same spec | +| `wasm` | The Rust core compiled to `wasm32-unknown-unknown`, one call per input | +| `wasm-batch` | Same core, the whole corpus in one call | +| `wasm-callonly` | The boundary alone: same pointer, same length, no marshalling | +| `ffi` / `cgo` | The same core as a `cdylib`, over ctypes / Fiddle / cgo | +| `uniffi` | The same logic behind UniFFI generated Python bindings | +| `cext` | The same core as a CPython extension module / a Ruby C extension | +| `ffm` | The same core over Java's Foreign Function & Memory API, trivial downcall | +| `ffi` (C#) | The same core over P/Invoke with `[SuppressGCTransition]` | +| `core-direct` | The same core called from C: the floor, the work with no boundary at all | --- @@ -67,38 +108,45 @@ rustc 1.94.1, OpenJDK 21.0.10, wasmtime-py 48.0.0, wasmtime gem 48.0.1, wazero 1 Lower is better. `× hand` is the ratio to that language's handwritten arm, so **below 1.00 is faster than handwritten**. -| Language | Arm | ns/op | × hand | valid | -| -------- | ------------- | ---------: | -------: | ------: | -| Node | handwritten | 386.2 | 1.00 | 337 | -| Node | **generated** | **256.5** | **0.66** | 337 | -| Node | wasm | 224.6 | 0.58 | 337 | -| Node | wasm-batch | 240.5 | 0.62 | 337 | -| Python | handwritten | 2460.6 | 1.00 | **333** | -| Python | **generated** | **1366.0** | **0.56** | 337 | -| Python | wasm | 38039.3 | 15.46 | 337 | -| Python | wasm-callonly | 30058.9 | 12.22 | — | -| Python | wasm-batch | 306.3 | 0.12 | 337 | -| Python | ffi (ctypes) | 535.3 | 0.22 | 337 | -| Python | ffi-batch | 239.9 | 0.10 | 337 | -| Python | **uniffi** | **9064.2** | **3.68** | 337 | -| Python | uniffi-batch | 6195.8 | 2.52 | 337 | -| Ruby | handwritten | 3675.8 | 1.00 | **329** | -| Ruby | **generated** | **2020.1** | **0.55** | 337 | -| Ruby | wasm | 729.9 | 0.20 | 337 | -| Ruby | wasm-batch | 430.0 | 0.12 | 337 | -| Ruby | ffi (Fiddle) | 1662.1 | 0.45 | 337 | -| Go | handwritten | 446.2 | 1.00 | **334** | -| Go | **generated** | **193.1** | **0.43** | 337 | -| Go | wasm (wazero) | 189.1 | 0.42 | 337 | -| Go | wasm-batch | 104.5 | 0.23 | 337 | -| Go | cgo | 119.1 | 0.27 | 337 | -| Go | cgo-batch | 52.6 | 0.12 | 337 | -| Java | handwritten | 1365.3 | 1.00 | 337 | -| Java | **generated** | **493.6** | **0.36** | 337 | +| Language | Arm | ns/op | × hand | valid | +| -------- | ------------------ | ---------: | -------: | ------: | +| C | **core-direct** | **47.0** | — | 337 | +| Node | handwritten | 386.2 | 1.00 | 337 | +| Node | **generated** | **256.5** | **0.66** | 337 | +| Node | wasm | 224.6 | 0.58 | 337 | +| Node | wasm-batch | 240.5 | 0.62 | 337 | +| Python | handwritten | 2460.6 | 1.00 | **333** | +| Python | **generated** | **1366.0** | **0.56** | 337 | +| Python | wasm | 38039.3 | 15.46 | 337 | +| Python | wasm-callonly | 30058.9 | 12.22 | — | +| Python | wasm-batch | 306.3 | 0.12 | 337 | +| Python | ffi (ctypes) | 535.3 | 0.22 | 337 | +| Python | ffi-batch | 239.9 | 0.10 | 337 | +| Python | **uniffi** | **9064.2** | **3.68** | 337 | +| Python | uniffi-batch | 6195.8 | 2.52 | 337 | +| Python | **cext** | **65.4** | **0.03** | 337 | +| Python | cext-batch | 235.9 | 0.10 | 337 | +| Ruby | handwritten | 3675.8 | 1.00 | **329** | +| Ruby | **generated** | **2020.1** | **0.55** | 337 | +| Ruby | wasm | 729.9 | 0.20 | 337 | +| Ruby | wasm-batch | 430.0 | 0.12 | 337 | +| Ruby | ffi (Fiddle) | 1662.1 | 0.45 | 337 | +| Ruby | **cext** | **109.3** | **0.03** | 337 | +| Go | handwritten | 446.2 | 1.00 | **334** | +| Go | **generated** | **193.1** | **0.43** | 337 | +| Go | wasm (wazero) | 189.1 | 0.42 | 337 | +| Go | wasm-batch | 104.5 | 0.23 | 337 | +| Go | cgo | 119.1 | 0.27 | 337 | +| Go | cgo-batch | 52.6 | 0.12 | 337 | +| Java | handwritten | 1365.3 | 1.00 | 337 | +| Java | **generated** | **493.6** | **0.36** | 337 | +| Java | **ffm (Panama)** | **127.3** | **0.09** | 337 | +| C# | handwritten | 330.2 | 1.00 | 337 | +| C# | **ffi (P/Invoke)** | **76.4** | **0.23** | 337 | --- -## Six findings +## Seven findings ### 1. Generated source is faster than handwritten, in every language measured @@ -125,27 +173,45 @@ Python went 6485 → 1366 ns/op; Ruby 15051 → 2020. Conformance stayed at 2229 **This is the load bearing result for the whole idea**: the emitter is allowed to know things about its target language, and the moment it does, generated code stops being a compromise. -### 2. The boundary costs more than the work - -The validator itself takes ~100 ns. Look at the `callonly` arms — the same pointer and length every -time, no marshalling, no string conversion, pure boundary: - -| Host | Boundary cost per call | -| --------------------------- | ---------------------- | -| Go → wasm (wazero) | 104 ns | -| Go → C (cgo) | 98 ns | -| Ruby → wasm (wasmtime gem) | 521 ns | -| Ruby → C (Fiddle) | 1518 ns | -| Python → C (ctypes) | 472 ns | -| Python → wasm (wasmtime-py) | **30059 ns** | - -For a function whose body is 100 ns, a boundary of 500–1500 ns means the binding _is_ the cost. -That is why `ffi` in Python (535 ns) is almost exactly `ffi-callonly` (472 ns): the validation is -noise next to the call. - -The corollary is the `batch` arms: amortise one boundary crossing over 1000 inputs and everything -becomes fast (Python 240 ns/op over ctypes, 306 ns/op over wasm). A shared core is a **bulk -validation** tool, not a per call one. +### 2. The boundary costs more than the work — but only over the wrong boundary + +The validator body is 47 ns, measured by calling the same shared library from C +(`core-direct`). Against that, here is every boundary measured, isolated: the same pointer and +length every call, no marshalling, minus the 40 ns the same fixed input costs in C. + +| Host | Mechanism | Boundary cost per call | +| ------------- | ---------------------------------- | ---------------------- | +| C# → C | P/Invoke, `[SuppressGCTransition]` | **~1 ns** | +| Python → C | CPython extension module | **27 ns** | +| Go → C | cgo | 58 ns | +| Java → C | Panama FFM, trivial downcall | 62 ns | +| Ruby → C | C extension | 65 ns | +| Go → wasm | wazero | 64 ns | +| Python → C | ctypes | 433 ns | +| Ruby → wasm | wasmtime gem | 482 ns | +| Ruby → C | Fiddle | 1,479 ns | +| Python → wasm | wasmtime-py 48 | **30,019 ns** | + +The top half and the bottom half are the same idea over different plumbing, and they differ by +three orders of magnitude. The first pass of this document measured only the bottom half and +drew a general conclusion from it; that was wrong. + +Three details decide which half a binding lands in, and all three are easy to get wrong: + +- **C#** needs `[SuppressGCTransition]`. Without it the call still costs only 42 ns rather than + 41, because .NET's transition is already cheap — this is the one runtime where the naive + version is fine. +- **Java** needs the `MethodHandle` to be `static final` and the off-heap buffer to come from + `Arena.global()`. With a shared arena and an instance handle the same call costs 84 ns more, + because the JIT cannot fold the downcall stub and pays a liveness check per call. + `Linker.Option.isTrivial()` itself is worth about 1 ns here. +- **Python and Ruby** need a real extension module. `ctypes` is 16× more expensive than a + CPython extension; Fiddle is 23× more expensive than a Ruby C extension. + +The corollary about batching still holds, and is now less interesting: amortising one crossing +over 1000 inputs helps the expensive boundaries and _hurts_ the cheap ones. Python's C +extension is 65 ns per call and 236 ns per call in batch, because packing the buffer in Python +costs more than the calls it saves. ### 3. Binding quality varies by 300× between runtimes of the same technology @@ -177,7 +243,7 @@ still slower than plain Python, because the sequence has to be serialised into a UniFFI is built for coarse grained APIs — "sync this database", "decrypt this blob" — where a microsecond of glue is irrelevant. Brazilian Utils is the opposite: a hundred tiny pure functions. -### 5. The JS package would pay the most and gain the least +### 5. The JS package would pay the most and gain the least, which settles it | | Generated source | Wasm core | | -------------------------------------------- | --------------------------- | ----------------------------------------------------------------------- | @@ -192,7 +258,27 @@ exchange for 160 ns. The npm package's selling points are exactly what a wasm co Cold start, for the record: instantiating the 9 KB module costs 0.025 ms in Node, 3.5 ms in Python, 3.8 ms in Ruby — fine for a server, not free for a CLI or a lambda. -### 6. Every handwritten port is already subtly wrong +### 6. A binding is cheap; a binary is not + +Every number above is per call. The cost that decides the question is per release. + +Generated source ships as source: it is reviewed in the package's own repository, `git diff` +shows what changed, a stack trace points at a line, and there is no build matrix at all. A +shared core ships as an artifact per platform × arch per ecosystem, and needs a release +pipeline that produces them, a fallback for platforms nobody built, and an ABI that the +package and the artifact both agree on. + +Two ecosystems make that trade badly: + +- **JavaScript**, because of §5: no tree shaking, 18× the bytes, asynchronous startup. +- **Go**, because cgo costs cross compilation, static binaries and `CGO_ENABLED=0` builds — the + things a Go library is expected to keep — and buys 74 ns against the generated code. + +Four make it well, because they already ship native extensions as a matter of course: Python, +Ruby, C# and Java. There the speedup is 3.9× to 21×, and the pipeline is one their maintainers +have built before. + +### 7. Every handwritten port is already subtly wrong Look at the `valid` column. Over the same 1000 inputs, the handwritten arms disagree with the spec: Python 333, Ruby 329, Go 334, against 337 for everything generated. @@ -234,20 +320,48 @@ target. ## Recommendation -1. **Generated source is the default.** It has no runtime dependency, no build matrix, no cold - start, no bundle penalty, it is reviewable by each package's maintainers, and it is now measured - faster than the handwritten code in Node, Python, Ruby, Go and Java (0.36×–0.66×). -2. **Keep the two emitter rules from §1 as a requirement of every new target.** A target is not - done until its output is benchmarked against idiomatic handwritten code for that language. The - harness in `spec/bench` is the acceptance test. -3. **Do not put a binary core in the npm package.** §5 is disqualifying on its own. -4. **A shared wasm core stays an option for one specific case**: a host validating in bulk — a - batch importer, an ETL job, a CEP sweep. `wasm-batch` runs at 0.12× of handwritten in Python and - Ruby. If that demand ever appears, it should be a separate, optional package - (`brazilian-utils-turbo`), never the only implementation, and it should reuse the same spec so - the two cannot drift. -5. **Revisit only if the workload changes.** Bindings win when the work per call grows past a few - microseconds. Nothing in this library is close: the heaviest validator here is ~100 ns. +The unit being shared is the **utility's implementation**, not the published package: every +ecosystem writes its own DX by hand — its naming, its option objects, its types, its docs — +over whichever core it gets. That is what makes a hand-written binding acceptable, and it is +why the answer can differ per ecosystem without the library becoming incoherent. + +1. **Write the utility once**, in the portable TypeScript subset + ([`spec/bridge`](bridge/README.md)). One implementation, one review, one set of conformance + vectors. +2. **Emit TypeScript for npm.** Not negotiable: the package is tree shakeable and a binary core + is not. 509 bytes per utility that disappear when unused, against 9,291 indivisible bytes. +3. **Emit Rust for the shared core**, compiled to a C ABI. This is the piece that does not + exist yet: the Rust emitter produces a library crate, and a `cdylib` with + `#[no_mangle] extern "C"` wrappers is a small addition to it. +4. **Bind to that core from Python, Ruby, C#, Java and Erlang.** 21×, 18×, 4.3×, 3.9× and + unmeasured respectively, over a boundary of 1–65 ns. Each binding is hand-written, small, + and lives with the DX layer it serves — the same place those packages already keep their + hand-written code. +5. **Give Go generated source.** cgo's cost is not its 58 ns. It is cross compilation, static + binaries and `CGO_ENABLED=0`, all of which a Go library is expected to keep, traded for + 74 ns against the generated code. The wrong trade. +6. **Keep the other emitters.** They are written and they pass conformance, so they stay as the + escape hatch for any ecosystem that would rather not ship a native artifact — and as the + reference the bindings are checked against. + +The two halves stay honest about each other the same way they do now: every target, generated +or bound, replays the same vectors recorded from the package this repository ships. + +### What the binding route costs to ship + +Worth pricing before agreeing to it, because this is where generated source is free and a +native core is not. + +| Ecosystem | Artifact | Notes | +| --------- | ------------------------------------------- | ------------------------------------------------------------------ | +| Python | wheels per platform × arch, `abi3` | cibuildwheel; ~10 wheels; an sdist fallback needs a compiler | +| Ruby | native gem per platform, or source gem | rake-compiler-dock; a source gem compiling on install is normal | +| C# | NuGet with `runtimes/{rid}/native/` | well-trodden; `SuppressGCTransition` needs .NET 5+ | +| Java | JAR with the library per os-arch, extracted | **needs JDK 22+** for FFM without `--enable-preview`; JNI below it | +| Erlang | a NIF, built on install | unmeasured here; the same C boundary | + +None of that is exotic — every one of those ecosystems ships native extensions routinely — but +it is a release pipeline per package, and it is the reason step 6 exists. ## What would change the answer @@ -255,6 +369,8 @@ target. boundary stops dominating. - A host runtime fixing its call overhead — a wasmtime-py that costs 500 ns instead of 30 000 ns would make the wasm core competitive per call in Python. +- Go removing the cost of cgo, or the library deciding it does not care about `CGO_ENABLED=0`. + The nanoseconds already favour the binding there; nothing else does. - The Component Model reaching the point where `jco` emits tree shakeable JS. Today it does not. ## Reproducing @@ -272,5 +388,13 @@ cp target/release/libbrutils_uniffi.so ../.build/uniffi-python/ python3 ../harness/uniffi_bench.py ``` -Requires `node`, `python3` (with `wasmtime`), `ruby` (with the `wasmtime` gem), `go`, `cargo` with -the `wasm32-unknown-unknown` target, and `javac`. +The native binding arms are a separate script, because they need each ecosystem's build +toolchain rather than its wasm runtime: + +```bash +bash spec/bench/run-native.sh >> spec/bench/results.jsonl +``` + +Requires `node`, `python3` (with `wasmtime` and its development headers), `ruby` (with the +`wasmtime` gem and its development headers), `go`, `cargo` with the `wasm32-unknown-unknown` +target, `javac` (21+), `dotnet` (8+) and a C compiler. diff --git a/spec/bench/harness/csharp/CsharpBench.csproj b/spec/bench/harness/csharp/CsharpBench.csproj new file mode 100644 index 000000000..1f4f727ea --- /dev/null +++ b/spec/bench/harness/csharp/CsharpBench.csproj @@ -0,0 +1,12 @@ + + + net8.0 + disable + Exe + CsharpBench + + true + true + true + + diff --git a/spec/bench/harness/csharp/Program.cs b/spec/bench/harness/csharp/Program.cs new file mode 100644 index 000000000..000835dc8 --- /dev/null +++ b/spec/bench/harness/csharp/Program.cs @@ -0,0 +1,246 @@ +// C# arms: handwritten source against the shared core over P/Invoke. +// +// .NET has the cheapest boundary of the managed runtimes measured here. `[SuppressGCTransition]` +// tells the runtime the callee is short and never blocks, so the call skips the transition to +// preemptive GC mode and becomes little more than an indirect jump. The string still has to +// reach the core as UTF-8 bytes, which is a `stackalloc` and an encode — measured as part of +// the `ffi` arm, because a real binding pays it too. + +using System; +using System.Diagnostics; +using System.IO; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Text; +using System.Text.Json; +using System.Text.RegularExpressions; + +internal static class Program +{ + // The code points JavaScript's trim() strips. .NET's Trim() is a different set, and C# + // expands a unicode escape before lexing, so the set is built from numbers, not escapes. + private static readonly string Whitespace = new string(new[] + { + (char)0x09, (char)0x0a, (char)0x0b, (char)0x0c, (char)0x0d, (char)0x20, (char)0xa0, + (char)0x1680, (char)0x2000, (char)0x2001, (char)0x2002, (char)0x2003, (char)0x2004, + (char)0x2005, (char)0x2006, (char)0x2007, (char)0x2008, (char)0x2009, (char)0x200a, + (char)0x2028, (char)0x2029, (char)0x202f, (char)0x205f, (char)0x3000, (char)0xfeff, + }); + + private static readonly Regex Shape = new Regex( + "^[0-9]{3}[" + Whitespace + "./-]*[0-9]{3}[" + Whitespace + "./-]*[0-9]{3}[" + + Whitespace + "./-]*[0-9]{2}$", + RegexOptions.Compiled); + + private static readonly Regex NonDigits = new Regex("[^0-9]", RegexOptions.Compiled); + + private static int CheckDigit(string basis) + { + var sum = 0; + var weight = basis.Length + 1; + + for (var index = 0; index < basis.Length; index++) + { + sum += (basis[index] - '0') * weight; + weight--; + } + + var digit = 11 - (sum % 11); + + return digit >= 10 ? 0 : digit; + } + + private static string TrimJs(string value) + { + var start = 0; + var end = value.Length; + + while (start < end && Whitespace.IndexOf(value[start]) >= 0) + { + start++; + } + + while (end > start && Whitespace.IndexOf(value[end - 1]) >= 0) + { + end--; + } + + return value.Substring(start, end - start); + } + + private static bool HandwrittenIsValid(string cpf) + { + if (cpf == null) + { + return false; + } + + if (!Shape.IsMatch(TrimJs(cpf))) + { + return false; + } + + var digits = NonDigits.Replace(cpf, string.Empty); + var first = digits[0]; + var repeated = true; + + for (var index = 1; index < digits.Length; index++) + { + if (digits[index] != first) + { + repeated = false; + + break; + } + } + + if (repeated) + { + return false; + } + + return digits[9] - '0' == CheckDigit(digits.Substring(0, 9)) + && digits[10] - '0' == CheckDigit(digits.Substring(0, 10)); + } + + // --- the shared core ------------------------------------------------------------------- + + private const string Core = "brutils_bench_core"; + + [DllImport(Core, EntryPoint = "cpf_is_valid")] + [SuppressGCTransition] + private static extern unsafe int CpfIsValidFast(byte* ptr, nuint len); + + [DllImport(Core, EntryPoint = "cpf_is_valid")] + private static extern unsafe int CpfIsValidPlain(byte* ptr, nuint len); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static unsafe bool FfiIsValid(string value) + { + Span buffer = stackalloc byte[128]; + var written = Encoding.UTF8.GetBytes(value.AsSpan(), buffer); + + fixed (byte* ptr = buffer) + { + return CpfIsValidFast(ptr, (nuint)written) == 1; + } + } + + private static int RunHandwritten(string[] corpus) + { + var valid = 0; + + foreach (var value in corpus) + { + if (HandwrittenIsValid(value)) + { + valid++; + } + } + + return valid; + } + + private static int RunFfi(string[] corpus) + { + var valid = 0; + + foreach (var value in corpus) + { + if (FfiIsValid(value)) + { + valid++; + } + } + + return valid; + } + + /// Just the boundary: the same bytes every time, no marshalling at all. + private static unsafe int RunFfiCallOnly(string[] corpus) + { + Span buffer = stackalloc byte[16]; + var written = Encoding.UTF8.GetBytes("12345678909".AsSpan(), buffer); + var valid = 0; + + fixed (byte* ptr = buffer) + { + for (var index = 0; index < corpus.Length; index++) + { + if (CpfIsValidFast(ptr, (nuint)written) == 1) + { + valid++; + } + } + } + + return valid; + } + + /// The same boundary with the GC transition, to show what suppressing it is worth. + private static unsafe int RunFfiPlainCallOnly(string[] corpus) + { + Span buffer = stackalloc byte[16]; + var written = Encoding.UTF8.GetBytes("12345678909".AsSpan(), buffer); + var valid = 0; + + fixed (byte* ptr = buffer) + { + for (var index = 0; index < corpus.Length; index++) + { + if (CpfIsValidPlain(ptr, (nuint)written) == 1) + { + valid++; + } + } + } + + return valid; + } + + private static void Measure(string arm, string[] corpus, Func run) + { + for (var warm = 0; warm < 50; warm++) + { + run(corpus); + } + + var best = double.PositiveInfinity; + var valid = 0; + + for (var rep = 0; rep < 15; rep++) + { + var started = Stopwatch.GetTimestamp(); + + valid = run(corpus); + + var elapsed = (Stopwatch.GetTimestamp() - started) * (1e9 / Stopwatch.Frequency); + var perOp = elapsed / corpus.Length; + + if (perOp < best) + { + best = perOp; + } + } + + Console.WriteLine( + $"{{\"lang\":\"csharp\",\"arm\":\"{arm}\",\"nsPerOp\":{best.ToString("F1", System.Globalization.CultureInfo.InvariantCulture)},\"valid\":{valid}}}"); + } + + public static int Main(string[] args) + { + NativeLibrary.SetDllImportResolver( + typeof(Program).Assembly, + (name, assembly, path) => + name == Core ? NativeLibrary.Load(args[1]) : IntPtr.Zero); + + var corpus = JsonSerializer.Deserialize(File.ReadAllText(args[0])); + + Measure("handwritten", corpus, RunHandwritten); + Measure("ffi", corpus, RunFfi); + Measure("ffi-callonly", corpus, RunFfiCallOnly); + Measure("ffi-plain-callonly", corpus, RunFfiPlainCallOnly); + + return 0; + } +} diff --git a/spec/bench/harness/java/JavaNativeBench.java b/spec/bench/harness/java/JavaNativeBench.java new file mode 100644 index 000000000..46f126515 --- /dev/null +++ b/spec/bench/harness/java/JavaNativeBench.java @@ -0,0 +1,205 @@ +// The Java arm the first pass missed: the shared core over the Foreign Function & Memory API. +// +// Panama is the cheapest boundary the JVM has, but only if it is written the way a real binding +// writes it. Two things matter and both are easy to get wrong: +// +// * the `MethodHandle` has to be `static final`, or the JIT cannot fold the downcall stub into +// the caller and every call goes through a generic invoker; +// * `Linker.Option.isTrivial()` (renamed `critical` in JDK 22) tells the runtime the callee +// returns quickly and never calls back, which lets it skip the thread state transition. +// +// What Panama cannot skip on JDK 21 is marshalling: a trivial downcall may not touch the heap, +// so the string is encoded and copied off-heap before the call. That copy is measured as part +// of the `ffm` arm, because a real binding cannot avoid it either. + +import java.io.IOException; +import java.lang.foreign.Arena; +import java.lang.foreign.FunctionDescriptor; +import java.lang.foreign.Linker; +import java.lang.foreign.MemorySegment; +import java.lang.foreign.SymbolLookup; +import java.lang.foreign.ValueLayout; +import java.lang.invoke.MethodHandle; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.List; + +public final class JavaNativeBench { + private JavaNativeBench() {} + + // A global arena: its segments need no liveness check, which a shared one would pay per call. + private static final Arena ARENA = Arena.global(); + private static final MemorySegment SCRATCH = ARENA.allocate(256); + private static final FunctionDescriptor DESCRIPTOR = + FunctionDescriptor.of(ValueLayout.JAVA_INT, ValueLayout.ADDRESS, ValueLayout.JAVA_LONG); + private static final SymbolLookup LOOKUP = + SymbolLookup.libraryLookup(Path.of(System.getProperty("core.library")), ARENA); + private static final MemorySegment SYMBOL = LOOKUP.find("cpf_is_valid").orElseThrow(); + + /** The trivial downcall option, absent on a JDK that does not have it yet. */ + private static final Linker.Option TRIVIAL = trivialOption(); + + private static final MethodHandle CPF_IS_VALID = TRIVIAL == null + ? Linker.nativeLinker().downcallHandle(SYMBOL, DESCRIPTOR) + : Linker.nativeLinker().downcallHandle(SYMBOL, DESCRIPTOR, TRIVIAL); + + private static final MethodHandle CPF_IS_VALID_PLAIN = + Linker.nativeLinker().downcallHandle(SYMBOL, DESCRIPTOR); + + private static Linker.Option trivialOption() { + for (var method : Linker.Option.class.getMethods()) { + if (method.getName().equals("isTrivial") && method.getParameterCount() == 0) { + try { + return (Linker.Option) method.invoke(null); + } catch (ReflectiveOperationException ignored) { + return null; + } + } + } + + return null; + } + + private static boolean ffmIsValid(String value) throws Throwable { + byte[] encoded = value.getBytes(StandardCharsets.UTF_8); + + MemorySegment.copy(encoded, 0, SCRATCH, ValueLayout.JAVA_BYTE, 0, encoded.length); + + return (int) CPF_IS_VALID.invokeExact(SCRATCH, (long) encoded.length) == 1; + } + + private static int runFfm(List corpus) throws Throwable { + int valid = 0; + + for (String value : corpus) { + if (ffmIsValid(value)) { + valid++; + } + } + + return valid; + } + + /** Just the boundary: the same pointer and length every time, no marshalling at all. */ + private static int runFfmCallOnly(List corpus) throws Throwable { + writePayload(); + + int valid = 0; + + for (int index = 0; index < corpus.size(); index++) { + if ((int) CPF_IS_VALID.invokeExact(SCRATCH, 11L) == 1) { + valid++; + } + } + + return valid; + } + + /** The same boundary without the trivial option, to show what the option is worth. */ + private static int runFfmPlainCallOnly(List corpus) throws Throwable { + writePayload(); + + int valid = 0; + + for (int index = 0; index < corpus.size(); index++) { + if ((int) CPF_IS_VALID_PLAIN.invokeExact(SCRATCH, 11L) == 1) { + valid++; + } + } + + return valid; + } + + private static void writePayload() { + byte[] payload = "12345678909".getBytes(StandardCharsets.UTF_8); + + MemorySegment.copy(payload, 0, SCRATCH, ValueLayout.JAVA_BYTE, 0, payload.length); + } + + private static List readCorpus(Path path) throws IOException { + String raw = Files.readString(path); + List corpus = new ArrayList<>(); + int index = 0; + + while (index < raw.length()) { + if (raw.charAt(index) != '"') { + index++; + continue; + } + + index++; + + StringBuilder value = new StringBuilder(); + + while (index < raw.length() && raw.charAt(index) != '"') { + char current = raw.charAt(index); + + if (current == '\\') { + index++; + + char escape = raw.charAt(index); + + switch (escape) { + case 'u' -> { + value.append((char) Integer.parseInt(raw.substring(index + 1, index + 5), 16)); + index += 4; + } + case 'n' -> value.append('\n'); + case 'r' -> value.append('\r'); + case 't' -> value.append('\t'); + default -> value.append(escape); + } + } else { + value.append(current); + } + + index++; + } + + index++; + corpus.add(value.toString()); + } + + return corpus; + } + + private interface Run { + int over(List corpus) throws Throwable; + } + + private static void measure(String arm, List corpus, Run run) throws Throwable { + for (int warm = 0; warm < 50; warm++) { + run.over(corpus); + } + + double best = Double.POSITIVE_INFINITY; + int valid = 0; + + for (int rep = 0; rep < 15; rep++) { + long start = System.nanoTime(); + + valid = run.over(corpus); + + double perOp = (System.nanoTime() - start) / (double) corpus.size(); + + best = Math.min(best, perOp); + } + + System.out.printf( + "{\"lang\":\"java\",\"arm\":\"%s\",\"nsPerOp\":%.1f,\"valid\":%d}%n", arm, best, valid); + } + + public static void main(String[] args) throws Throwable { + List corpus = readCorpus(Path.of(args[0])); + + if (TRIVIAL == null) { + System.err.println("note: no trivial downcall option on this JDK"); + } + + measure("ffm", corpus, JavaNativeBench::runFfm); + measure("ffm-callonly", corpus, JavaNativeBench::runFfmCallOnly); + measure("ffm-plain-callonly", corpus, JavaNativeBench::runFfmPlainCallOnly); + } +} diff --git a/spec/bench/harness/python_native.py b/spec/bench/harness/python_native.py new file mode 100644 index 000000000..749034ce3 --- /dev/null +++ b/spec/bench/harness/python_native.py @@ -0,0 +1,80 @@ +"""The Python arm the first pass missed: the shared core as a CPython extension. + +`ctypes` is the binding a script reaches for; a C extension is the binding a package ships. +Both are measured here against the same corpus and the same core, so the difference is the +mechanism and nothing else. +""" + +import json +import os +import struct +import sys +import time +from pathlib import Path + +BENCH = Path(__file__).resolve().parent.parent +CORPUS = json.loads((BENCH / "corpus.json").read_text()) +REPS = int(os.environ.get("BENCH_REPS", "7")) + +sys.path.insert(0, str(BENCH / ".build/native/python")) + +import cpf_native # noqa: E402 + +def run_cext(inputs): + valid = 0 + is_valid = cpf_native.is_valid + + for value in inputs: + if is_valid(value): + valid += 1 + + return valid + + +def run_cext_callonly(inputs): + """Just the boundary: the same string every time, so nothing but the call is measured.""" + payload = "12345678909" + valid = 0 + is_valid = cpf_native.is_valid + + for _ in inputs: + if is_valid(payload): + valid += 1 + + return valid + + +def run_cext_batch(inputs): + packed = bytearray() + + for value in inputs: + encoded = value.encode("utf-8") + packed += struct.pack(" +#include +#include +#include + +extern int cpf_is_valid(const unsigned char *ptr, size_t len); + +typedef struct { + const unsigned char *ptr; + size_t len; +} Input; + +static long now_ns(void) { + struct timespec spec; + + clock_gettime(CLOCK_MONOTONIC, &spec); + + return spec.tv_sec * 1000000000L + spec.tv_nsec; +} + +static int run(const Input *corpus, size_t count) { + int valid = 0; + + for (size_t index = 0; index < count; index++) { + valid += cpf_is_valid(corpus[index].ptr, corpus[index].len); + } + + return valid; +} + +/* + * The same loop over one cached, always valid input. Every language's "callonly" arm does + * exactly this, so subtracting this number from theirs leaves the boundary and nothing else. + */ +static int run_fixed(size_t count) { + static const unsigned char payload[] = "12345678909"; + int valid = 0; + + for (size_t index = 0; index < count; index++) { + valid += cpf_is_valid(payload, 11); + } + + return valid; +} + +int main(int argc, char **argv) { + const char *path = argc > 1 ? argv[1] : "corpus.bin"; + FILE *handle = fopen(path, "rb"); + unsigned char *raw = NULL; + long size = 0; + size_t count = 0; + size_t offset = 0; + Input *corpus = NULL; + const char *reps_env = getenv("BENCH_REPS"); + int reps = reps_env == NULL ? 7 : atoi(reps_env); + double best = 1e18; + int valid = 0; + + if (handle == NULL) { + fprintf(stderr, "cannot open %s\n", path); + + return 1; + } + + fseek(handle, 0, SEEK_END); + size = ftell(handle); + fseek(handle, 0, SEEK_SET); + raw = malloc((size_t)size); + + if (fread(raw, 1, (size_t)size, handle) != (size_t)size) { + fprintf(stderr, "short read\n"); + + return 1; + } + + fclose(handle); + + while (offset + 4 <= (size_t)size) { + unsigned int length = (unsigned int)raw[offset] | ((unsigned int)raw[offset + 1] << 8) + | ((unsigned int)raw[offset + 2] << 16) + | ((unsigned int)raw[offset + 3] << 24); + + offset += 4 + length; + count++; + } + + corpus = malloc(count * sizeof(Input)); + offset = 0; + count = 0; + + while (offset + 4 <= (size_t)size) { + unsigned int length = (unsigned int)raw[offset] | ((unsigned int)raw[offset + 1] << 8) + | ((unsigned int)raw[offset + 2] << 16) + | ((unsigned int)raw[offset + 3] << 24); + + offset += 4; + corpus[count].ptr = raw + offset; + corpus[count].len = length; + offset += length; + count++; + } + + for (int warm = 0; warm < 3; warm++) { + run(corpus, count); + } + + for (int rep = 0; rep < reps; rep++) { + long started = now_ns(); + + valid = run(corpus, count); + + double per_op = (double)(now_ns() - started) / (double)count; + + if (per_op < best) { + best = per_op; + } + } + + printf("{\"lang\":\"c\",\"arm\":\"core-direct\",\"nsPerOp\":%.1f,\"valid\":%d}\n", best, valid); + + for (int warm = 0; warm < 3; warm++) { + run_fixed(count); + } + + best = 1e18; + + for (int rep = 0; rep < reps; rep++) { + long started = now_ns(); + + valid = run_fixed(count); + + double per_op = (double)(now_ns() - started) / (double)count; + + if (per_op < best) { + best = per_op; + } + } + + printf("{\"lang\":\"c\",\"arm\":\"core-direct-callonly\",\"nsPerOp\":%.1f,\"valid\":%d}\n", + best, valid); + + return 0; +} diff --git a/spec/bench/native/python_cext.c b/spec/bench/native/python_cext.c new file mode 100644 index 000000000..7dbfcf007 --- /dev/null +++ b/spec/bench/native/python_cext.c @@ -0,0 +1,80 @@ +/* + * A CPython extension module over the shared core. + * + * This is the cheapest boundary CPython has: `PyUnicode_AsUTF8AndSize` hands back the string's + * own UTF-8 buffer (cached on the object, and the object itself for an ASCII string), so the + * call marshals nothing — it passes a pointer and a length straight through to the core. + * + * It is also hand-written glue, which is the point: the DX layer of each package is written by + * hand anyway, so a binding written the way that ecosystem writes bindings is fair game. + */ +#define PY_SSIZE_T_CLEAN +#include +#include + +extern int cpf_is_valid(const unsigned char *ptr, size_t len); +extern int cpf_is_valid_batch(const unsigned char *input, size_t input_len, unsigned char *output, + size_t count); + +static PyObject *cpf_native_is_valid(PyObject *self, PyObject *value) { + Py_ssize_t length = 0; + const char *utf8 = NULL; + + (void)self; + + if (!PyUnicode_Check(value)) { + Py_RETURN_FALSE; + } + + utf8 = PyUnicode_AsUTF8AndSize(value, &length); + + if (utf8 == NULL) { + PyErr_Clear(); + Py_RETURN_FALSE; + } + + if (cpf_is_valid((const unsigned char *)utf8, (size_t)length)) { + Py_RETURN_TRUE; + } + + Py_RETURN_FALSE; +} + +static PyObject *cpf_native_is_valid_batch(PyObject *self, PyObject *packed) { + Py_ssize_t count = 0; + PyObject *output = NULL; + + (void)self; + + if (!PyTuple_Check(packed) || PyTuple_GET_SIZE(packed) != 2) { + PyErr_SetString(PyExc_TypeError, "expected (bytes, count)"); + + return NULL; + } + + count = PyLong_AsSsize_t(PyTuple_GET_ITEM(packed, 1)); + output = PyBytes_FromStringAndSize(NULL, count); + + if (output == NULL) { + return NULL; + } + + cpf_is_valid_batch((const unsigned char *)PyBytes_AS_STRING(PyTuple_GET_ITEM(packed, 0)), + (size_t)PyBytes_GET_SIZE(PyTuple_GET_ITEM(packed, 0)), + (unsigned char *)PyBytes_AS_STRING(output), (size_t)count); + + return output; +} + +static PyMethodDef CpfNativeMethods[] = { + {"is_valid", cpf_native_is_valid, METH_O, "Validate one CPF."}, + {"is_valid_batch", cpf_native_is_valid_batch, METH_O, "Validate a packed batch of CPFs."}, + {NULL, NULL, 0, NULL}, +}; + +static struct PyModuleDef cpf_native_module = { + PyModuleDef_HEAD_INIT, "cpf_native", "The shared CPF core, as a CPython extension.", -1, + CpfNativeMethods, +}; + +PyMODINIT_FUNC PyInit_cpf_native(void) { return PyModule_Create(&cpf_native_module); } diff --git a/spec/bench/native/ruby_cext.c b/spec/bench/native/ruby_cext.c new file mode 100644 index 000000000..85ef156da --- /dev/null +++ b/spec/bench/native/ruby_cext.c @@ -0,0 +1,47 @@ +/* + * A Ruby C extension over the shared core. + * + * `RSTRING_PTR` and `RSTRING_LEN` read the string object's own buffer, so nothing is copied: + * the call passes a pointer and a length straight through to the core. This is the boundary + * a gem ships when it cares, as opposed to `fiddle` or the `ffi` gem, which are what a script + * reaches for. + */ +#include +#include + +extern int cpf_is_valid(const unsigned char *ptr, size_t len); +extern int cpf_is_valid_batch(const unsigned char *input, size_t input_len, unsigned char *output, + size_t count); + +static VALUE cpf_native_is_valid(VALUE self, VALUE value) { + (void)self; + + if (!RB_TYPE_P(value, T_STRING)) { + return Qfalse; + } + + return cpf_is_valid((const unsigned char *)RSTRING_PTR(value), (size_t)RSTRING_LEN(value)) + ? Qtrue + : Qfalse; +} + +static VALUE cpf_native_is_valid_batch(VALUE self, VALUE packed, VALUE count) { + VALUE output = Qnil; + long total = 0; + + (void)self; + total = NUM2LONG(count); + output = rb_str_new(NULL, total); + + cpf_is_valid_batch((const unsigned char *)RSTRING_PTR(packed), (size_t)RSTRING_LEN(packed), + (unsigned char *)RSTRING_PTR(output), (size_t)total); + + return output; +} + +void Init_cpf_native(void) { + VALUE module = rb_define_module("CpfNative"); + + rb_define_module_function(module, "is_valid", cpf_native_is_valid, 1); + rb_define_module_function(module, "is_valid_batch", cpf_native_is_valid_batch, 2); +} diff --git a/spec/bench/results.jsonl b/spec/bench/results.jsonl index a5e1b86a7..caaecb504 100644 --- a/spec/bench/results.jsonl +++ b/spec/bench/results.jsonl @@ -35,3 +35,18 @@ {"lang":"java","arm":"generated","nsPerOp":493.6,"valid":337} {"lang": "python", "arm": "uniffi", "nsPerOp": 9064.2, "valid": 337} {"lang": "python", "arm": "uniffi-batch", "nsPerOp": 6195.8, "valid": 337} +{"lang":"c","arm":"core-direct","nsPerOp":47.0,"valid":337} +{"lang":"c","arm":"core-direct-callonly","nsPerOp":39.5,"valid":1000} +{"lang": "python", "arm": "cext", "nsPerOp": 65.4, "valid": 337} +{"lang": "python", "arm": "cext-callonly", "nsPerOp": 66.5, "valid": 1000} +{"lang": "python", "arm": "cext-batch", "nsPerOp": 235.9, "valid": 337} +{"lang":"ruby","arm":"cext","nsPerOp":109.3,"valid":337} +{"lang":"ruby","arm":"cext-callonly","nsPerOp":104.6,"valid":1000} +{"lang":"ruby","arm":"cext-batch","nsPerOp":465.7,"valid":337} +{"lang":"java","arm":"ffm","nsPerOp":127.3,"valid":337} +{"lang":"java","arm":"ffm-callonly","nsPerOp":101.9,"valid":1000} +{"lang":"java","arm":"ffm-plain-callonly","nsPerOp":102.7,"valid":1000} +{"lang":"csharp","arm":"handwritten","nsPerOp":330.2,"valid":337} +{"lang":"csharp","arm":"ffi","nsPerOp":76.4,"valid":337} +{"lang":"csharp","arm":"ffi-callonly","nsPerOp":40.6,"valid":1000} +{"lang":"csharp","arm":"ffi-plain-callonly","nsPerOp":41.2,"valid":1000} diff --git a/spec/bench/run-native.sh b/spec/bench/run-native.sh new file mode 100644 index 000000000..d9b09f207 --- /dev/null +++ b/spec/bench/run-native.sh @@ -0,0 +1,69 @@ +#!/usr/bin/env bash +# The native binding arms: the shared core over the boundary each ecosystem actually ships. +# +# The first pass measured the bindings a script reaches for — ctypes, fiddle, a wasm runtime — +# and concluded the boundary costs more than the work. That is true of those mechanisms and +# false of the ones a package ships, so each ecosystem's own is measured here: +# +# c the floor, the same shared library called from C +# python a CPython extension module, not ctypes +# ruby a C extension, not fiddle or the ffi gem +# java the Foreign Function & Memory API with a trivial downcall +# csharp P/Invoke with the GC transition suppressed +# +# Each language also runs a "callonly" arm over one cached input, and C runs the same, so +# subtracting the two leaves the boundary and nothing else. +# +# Usage: bash spec/bench/run-native.sh >> spec/bench/results.jsonl +set -euo pipefail + +bench="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +core_dir="${bench}/core/target/release" + +cargo build --quiet --release --manifest-path "${bench}/core/Cargo.toml" + +mkdir -p "${bench}/.build/native/python" "${bench}/.build/native/ruby" + +python3 - "${bench}" <<'PY' +import json +import pathlib +import struct +import sys + +bench = pathlib.Path(sys.argv[1]) +corpus = json.loads((bench / "corpus.json").read_text()) +packed = bytearray() + +for value in corpus: + encoded = value.encode("utf-8") + packed += struct.pack("/dev/null +java --enable-preview -Dcore.library="${core_dir}/libbrutils_bench_core.so" \ + -cp "${bench}/.build/java" JavaNativeBench "${bench}/corpus.json" 2>/dev/null + +cd "${bench}/harness/csharp" +DOTNET_CLI_TELEMETRY_OPTOUT=1 dotnet run -c Release --verbosity quiet -- \ + "${bench}/corpus.json" "${core_dir}/libbrutils_bench_core.so" diff --git a/spec/bench/table.py b/spec/bench/table.py index 98accbe45..b0ac2083a 100644 --- a/spec/bench/table.py +++ b/spec/bench/table.py @@ -22,9 +22,14 @@ "uniffi-batch": "uniffi-batch", "cgo": "cgo", "cgo-batch": "cgo-batch", + "cext": "**cext**", + "cext-batch": "cext-batch", + "ffm": "**ffm (Panama)**", + "core-direct": "**core-direct**", } LAYOUT = [ + ("C", "c", ["core-direct"]), ("Node", "node", ["handwritten", "generated", "wasm", "wasm-batch"]), ( "Python", @@ -39,11 +44,14 @@ "ffi-batch", "uniffi", "uniffi-batch", + "cext", + "cext-batch", ], ), - ("Ruby", "ruby", ["handwritten", "generated", "wasm", "wasm-batch", "ffi"]), + ("Ruby", "ruby", ["handwritten", "generated", "wasm", "wasm-batch", "ffi", "cext"]), ("Go", "go", ["handwritten", "generated", "wasm", "wasm-batch", "cgo", "cgo-batch"]), - ("Java", "java", ["handwritten", "generated"]), + ("Java", "java", ["handwritten", "generated", "ffm"]), + ("C#", "csharp", ["handwritten", "ffi"]), ] @@ -57,7 +65,8 @@ def main() -> None: lines = ["| Language | Arm | ns/op | × hand | valid |", "| --- | --- | ---: | ---: | ---: |"] for title, lang, arms in LAYOUT: - base = by[lang]["handwritten"]["nsPerOp"] + # C is the floor: the same core with no boundary, so there is nothing to compare it to. + base = by[lang]["handwritten"]["nsPerOp"] if "handwritten" in by[lang] else None for arm in arms: row = by[lang][arm] @@ -67,11 +76,19 @@ def main() -> None: label = "ffi (Fiddle)" if lang == "go" and arm == "wasm": label = "wasm (wazero)" + if lang == "csharp" and arm == "ffi": + label = "**ffi (P/Invoke)**" - ratio = row["nsPerOp"] / base - emphasise = arm in ("generated", "uniffi") + ratio = None if base is None else row["nsPerOp"] / base + emphasise = arm in ("generated", "uniffi", "cext", "ffm", "core-direct") or ( + lang == "csharp" and arm == "ffi" + ) ns = f"**{row['nsPerOp']:.1f}**" if emphasise else f"{row['nsPerOp']:.1f}" - rel = f"**{ratio:.2f}**" if emphasise else f"{ratio:.2f}" + + if ratio is None: + rel = "—" + else: + rel = f"**{ratio:.2f}**" if emphasise else f"{ratio:.2f}" valid = "—" if arm.endswith("callonly") else str(row["valid"]) if arm == "handwritten" and row["valid"] != 337: diff --git a/spec/bridge/README.md b/spec/bridge/README.md index 40e6e1f63..458b1555e 100644 --- a/spec/bridge/README.md +++ b/spec/bridge/README.md @@ -104,6 +104,44 @@ The source is straight-line, synchronous TypeScript. Three things are the emitte Go, threads and an `mpsc` channel in Rust, virtual threads in Java, and threads with a queue in Python and Ruby. +## The eighth target: a C ABI, for the ecosystems that would rather bind + +Generated source is not the only way to get one implementation into seven languages. The other +is one compiled core with a hand-written binding per ecosystem, and +[`spec/BINDINGS-INVESTIGATION.md`](../BINDINGS-INVESTIGATION.md) measures what that boundary +actually costs when it is written the way a package writes it rather than the way a script +does: **~1 ns in C#, 27 ns in Python, ~60 ns in Go, Java and Ruby**, against a validator body +of 47 ns. In Python and Ruby that is 21× and 18× faster than the generated source. + +So the Rust target emits both surfaces from the same source: + +``` +out/rust/src/cnpj.rs the library a Rust caller uses +out/rust/src/cabi_cnpj.rs #[no_mangle] extern "C" wrappers over the same functions +out/rust/include/cnpj.h the header a binding author reads +``` + +```c +int32_t cnpj_is_valid_cnpj(const uint8_t *cnpj, size_t len, int64_t version); +intptr_t cnpj_format_cnpj(const uint8_t *value, size_t len, int64_t version, + int32_t obfuscate, int32_t pad, uint8_t *out, size_t out_len); +``` + +Pointers, lengths and integers, nothing owned and nothing allocated across the boundary. An +option that was not given is its "unset" sentinel — the same one the emitters already compare +against. A function that answers text writes into the caller's buffer and returns the length. + +`conformance/run-all.sh` replays the CNPJ vectors through that ABI from C as an eighth arm +(5,732 / 5,732), which checks every hand-written binding's target at once: a CPython extension, +a Ruby C extension, a NuGet package over P/Invoke and a JAR over Panama all call exactly these +symbols. + +What the ABI does **not** cover yet is listed in the generated file itself: a function that +raises needs an out parameter for the error, one that waits on the network needs a callback or +a poll, and one that answers a list needs an iterator. `getMunicipalities` and +`getAddressInfoByCep` are refused rather than guessed at, so today they are generated-source +only. + ## The subset The frontend accepts a subset and refuses everything else with a pointed error rather than diff --git a/spec/bridge/compiler/targets/cabi.ts b/spec/bridge/compiler/targets/cabi.ts new file mode 100644 index 000000000..d02c29e2c --- /dev/null +++ b/spec/bridge/compiler/targets/cabi.ts @@ -0,0 +1,251 @@ +/** + * The C ABI surface, emitted alongside the Rust target. + * + * This is the piece the binding route needs: one shared core, compiled once per platform, that + * Python, Ruby, C#, Java and Erlang call with a hand-written binding of their own. The + * benchmark in `spec/bench` measures that boundary at 1 ns in C#, 27 ns in Python and about + * 60 ns elsewhere, against a validator body of 47 ns, so the surface is deliberately as narrow + * as a C caller can ask for: pointers, lengths and integers, nothing owned, nothing allocated. + * + * The shapes it covers, which is what the CNPJ utilities need: + * + * bool f(string, options?) -> int32 f(const uint8_t *, size_t, ) + * string f(string, options?) -> intptr f(const uint8_t *, size_t, , uint8_t *, size_t) + * + * An option field becomes one scalar parameter carrying the same "unset" sentinel the emitters + * already use: -1 for a number, 0 for a flag. A string result is written into a caller owned + * buffer and its length returned, so the caller frees nothing and the two sides share no + * allocator. Anything else — a list, a record, a function that raises — is refused rather than + * guessed at; those need a richer surface than this POC has. + */ +import { type Expr, type FuncDecl, type Module, type Ty } from "../ir.ts"; +import { optionReads, snake } from "../kit.ts"; + +/** One parameter of the C entry point. */ +type Slot = { name: string; c: string; rust: string }; + +/** Whether a type can cross a C boundary as a scalar. */ +const isScalar = (ty: Ty): boolean => + ty.k === "int" || ty.k === "bool" || ty.k === "string" || ty.k === "scalar" || ty.k === "enum"; + +/** The C type of a scalar option field. */ +const scalarC = (ty: Ty): string => (ty.k === "bool" ? "int32_t" : "int64_t"); + +/** The Rust type of a scalar option field. */ +const scalarRust = (ty: Ty): string => (ty.k === "bool" ? "i32" : "i64"); + +/** + * The entry point name a C caller sees: `cnpj_is_valid_cnpj`, module prefixed so two utilities + * can live in one library without colliding. + */ +const symbol = (module: Module, entry: FuncDecl): string => + `${snake(module.name)}_${snake(entry.name)}`; + +/** + * Whether a function can be exposed, and why not when it cannot. + * + * @param {FuncDecl} entry - The function. + * @returns {string} The reason it cannot, or an empty string when it can. + */ +const refuse = (entry: FuncDecl): string => { + if (entry.throws) return "it can raise, which needs an out parameter for the error"; + if (entry.blocking) return "it waits on the network, which needs a callback or a poll"; + if (entry.ret.k !== "bool" && entry.ret.k !== "string") return `it answers a ${entry.ret.k}`; + + for (const param of entry.params) { + if (param.ty.k === "named") continue; + if (!isScalar(param.ty)) return `its \`${param.name}\` parameter is a ${param.ty.k}`; + } + + return ""; +}; + +/** The C and Rust parameter lists of one entry point, before the string result slots. */ +const slots = (entry: FuncDecl): Slot[] => { + const found: Slot[] = []; + + for (const param of entry.params) { + if (param.ty.k === "named") continue; + + if (param.ty.k === "int" || param.ty.k === "bool") { + found.push({ name: snake(param.name), c: scalarC(param.ty), rust: scalarRust(param.ty) }); + + continue; + } + + found.push( + { name: `${snake(param.name)}_ptr`, c: "const uint8_t *", rust: "*const u8" }, + { name: `${snake(param.name)}_len`, c: "size_t", rust: "usize" }, + ); + } + + // Every option field becomes one scalar, carrying the sentinel the body already compares to. + for (const read of optionReads(entry)) { + const ty = read.expr.k === "optionField" ? read.expr.ty : ({ k: "int" } as Ty); + + found.push({ name: snake(read.local), c: scalarC(ty), rust: scalarRust(ty) }); + } + + return found; +}; + +/** How the body rebuilds the options record from the flattened scalars. */ +const rebuild = (entry: FuncDecl, module: string): string => { + const reads = optionReads(entry); + + if (reads.length === 0) return ""; + + const record = entry.params.find((param) => param.ty.k === "named"); + + if (record?.ty.k !== "named") return ""; + + const fields = reads + .map((read) => { + const ty = read.expr.k === "optionField" ? read.expr.ty : ({ k: "int" } as Ty); + const fallback = read.expr.k === "optionField" ? read.expr.fallback : ({ k: "none" } as Expr); + const unset = + ty.k === "bool" + ? `${snake(read.local)} == 0` + : `${snake(read.local)} == ${(fallback as Extract).value ?? -1}`; + const value = ty.k === "bool" ? `${snake(read.local)} != 0` : snake(read.local); + + return `\t\t${snake(read.field)}: if ${unset} { None } else { Some(${value}) },`; + }) + .join("\n"); + + return `\tlet options = ${snake(module)}::${record.ty.name} {\n${fields}\n\t\t..Default::default()\n\t};\n`; +}; + +/** The call into the generated function, with the arguments it expects. */ +const invoke = (module: Module, entry: FuncDecl): string => { + const args = entry.params.map((param) => { + if (param.ty.k === "named") return "Some(&options)"; + if (param.ty.k === "int" || param.ty.k === "bool") return snake(param.name); + + return `${snake(param.name)}_value`; + }); + + return `${snake(module.name)}::${snake(entry.name)}(${args.join(", ")})`; +}; + +/** Reads every string parameter out of its pointer and length, refusing invalid UTF-8. */ +const decode = (entry: FuncDecl, onBad: string): string => + entry.params + .filter((param) => param.ty.k !== "named" && param.ty.k !== "int" && param.ty.k !== "bool") + .map( + (param) => + `\tlet ${snake(param.name)}_value = match std::str::from_utf8(unsafe {\n\t\tstd::slice::from_raw_parts(${snake(param.name)}_ptr, ${snake(param.name)}_len)\n\t}) {\n\t\tOk(value) => value,\n\t\tErr(_) => return ${onBad},\n\t};\n`, + ) + .join(""); + +/** Renders one entry point. */ +const entryPoint = (module: Module, entry: FuncDecl): string => { + const name = symbol(module, entry); + const parameters = slots(entry); + const returnsText = entry.ret.k === "string"; + const rustParams = parameters.map((slot) => `${slot.name}: ${slot.rust}`); + + if (returnsText) rustParams.push("out: *mut u8", "out_len: usize"); + + const signature = `#[no_mangle]\npub unsafe extern "C" fn ${name}(${rustParams.join(", ")}) -> ${returnsText ? "isize" : "i32"} {`; + const body = returnsText + ? `${decode(entry, "-1")}${rebuild(entry, module.name)}\tlet answer = ${invoke(module, entry)}; + let bytes = answer.as_bytes(); + + if out.is_null() || out_len < bytes.len() { + // The caller sizes its own buffer: answering the length lets it try again. + return bytes.len() as isize; + } + + unsafe { std::ptr::copy_nonoverlapping(bytes.as_ptr(), out, bytes.len()) }; + + bytes.len() as isize +}` + : `${decode(entry, "0")}${rebuild(entry, module.name)}\ti32::from(${invoke(module, entry)}) +}`; + + return `/// ${entry.doc.split("\n")[0]}\n${signature}\n${body}`; +}; + +/** Renders the C header a binding author reads. */ +const header = (module: Module, exposed: FuncDecl[]): string => { + const declarations = exposed + .map((entry) => { + const parameters = slots(entry).map((slot) => `${slot.c} ${slot.name}`); + + if (entry.ret.k === "string") parameters.push("uint8_t *out", "size_t out_len"); + + return `/* ${entry.doc.split("\n")[0]} */\n${entry.ret.k === "string" ? "intptr_t" : "int32_t"} ${symbol(module, entry)}(${parameters.join(", ")});`; + }) + .join("\n\n"); + + return `/* Code generated from spec/bridge/source/${module.name}.ts. DO NOT EDIT. + * + * The C surface of the shared core. A binding hands in pointers, lengths and integers; it owns + * every buffer, and the core allocates nothing on its behalf. + * + * An option that was not given is passed as its "unset" sentinel: -1 for a number, 0 for a flag. + * A function that answers text writes into \`out\` and returns the byte length; when the buffer + * is too small nothing is written and the length needed is returned, so the caller can size it + * and call again. + */ +#ifndef BRAZILIAN_UTILS_${module.name.toUpperCase()}_H +#define BRAZILIAN_UTILS_${module.name.toUpperCase()}_H + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +${declarations} + +#ifdef __cplusplus +} +#endif + +#endif +`; +}; + +/** + * Emits the C ABI of one module: a Rust source file and the header that describes it. + * + * @param {Module} module - The compiled module. + * @returns {Record} The files, by path, empty when nothing can be exposed. + */ +export const emit = (module: Module): Record => { + const exposed: FuncDecl[] = []; + const skipped: string[] = []; + + for (const entry of module.functions) { + if (!entry.exported) continue; + + const reason = refuse(entry); + + if (reason === "") exposed.push(entry); + else skipped.push(`// ${entry.name}: ${reason}`); + } + + if (exposed.length === 0) return {}; + + const notes = + skipped.length === 0 + ? "" + : `//\n// Not exposed, because the shapes below need more than pointers and integers:\n${skipped.join("\n")}\n`; + + return { + [`src/cabi_${module.name}.rs`]: `// Code generated from spec/bridge/source/${module.name}.ts. DO NOT EDIT. +// +// The C ABI of this module: what a hand-written binding in Python, Ruby, C#, Java or Erlang +// calls. Everything is a pointer, a length or an integer, and nothing crosses that either side +// has to free. +${notes} +use crate::${snake(module.name)}; + +${exposed.map((entry) => entryPoint(module, entry)).join("\n\n")} +`, + [`include/${module.name}.h`]: header(module, exposed), + }; +}; diff --git a/spec/bridge/compiler/targets/rust.ts b/spec/bridge/compiler/targets/rust.ts index 2b9aaa4ce..86cf5fa8a 100644 --- a/spec/bridge/compiler/targets/rust.ts +++ b/spec/bridge/compiler/targets/rust.ts @@ -21,6 +21,7 @@ import { type Ty, } from "../ir.ts"; import { optionReads, prose, pushTargets, screaming, snake } from "../kit.ts"; +import { emit as emitCabi } from "./cabi.ts"; /** The record types of the module being emitted, so a struct literal owns its fields. */ let structs = new Map(); @@ -566,7 +567,7 @@ fn ${snake(entry.name)}_table() -> &'static runtime::Dataset { * @param {Module} module - The compiled module. * @returns {Record} The files, by path. */ -export const emit = (module: Module, modules: Module[] = [module]): Record => { +export const emit = (module: Module, allModules: Module[] = [module]): Record => { signatures = new Map(module.functions.map((entry) => [entry.name, entry.params])); structs = new Map(module.structs.map((entry) => [entry.name, entry])); throwing = new Set(module.functions.filter((entry) => entry.throws).map((entry) => entry.name)); @@ -594,14 +595,26 @@ export const emit = (module: Module, modules: Module[] = [module]): Record entry.name))]; + return { + ...cabi, "src/runtime.rs": readFileSync(RUNTIME, "utf8"), "src/lib.rs": `// Code generated from spec/bridge/source. DO NOT EDIT. //! Generated Brazilian Utils. pub mod runtime; -${modules.map((entry) => `pub mod ${entry.name};`).join("\n")} +${modules.map((name) => `pub mod ${name};`).join("\n")} + +// The C ABI, for the ecosystems that bind to this crate instead of generating their own source. +${allModules + .filter((entry) => Object.keys(emitCabi(entry)).length > 0) + .map((entry) => `pub mod cabi_${entry.name};`) + .join("\n")} `, "Cargo.toml": `[package] name = "brazilian_utils_bridge" @@ -615,6 +628,8 @@ ureq = "3" [lib] path = "src/lib.rs" +# lib for a Rust caller, cdylib and staticlib for every binding that is not Rust. +crate-type = ["lib", "cdylib", "staticlib"] `, [`src/${module.name}.rs`]: `// Code generated from spec/bridge/source/${module.name}.ts. DO NOT EDIT. diff --git a/spec/bridge/conformance/drivers.ts b/spec/bridge/conformance/drivers.ts index 020ee1f63..9e7769be6 100644 --- a/spec/bridge/conformance/drivers.ts +++ b/spec/bridge/conformance/drivers.ts @@ -984,6 +984,149 @@ public final class Conformance { } } } +`, + + "out/rust/conformance_cabi.c": `/* Code generated by spec/bridge/conformance/drivers.ts. DO NOT EDIT. + * + * The eighth target is not a language: it is the C ABI the Rust crate exposes, replayed from C. + * + * Every hand-written binding — a CPython extension, a Ruby C extension, a NuGet package over + * P/Invoke, a JAR over Panama — calls exactly these symbols with exactly these arguments, so + * checking them from C checks all of them at once. What it cannot check is each binding's own + * marshalling, which is why the bindings themselves stay each package's own code to test. + */ +#include +#include +#include + +#include "include/cnpj.h" + +static void unescape(char *value) { + char *read = value; + char *write = value; + + while (*read != '\\0') { + if (*read != '\\\\') { + *write++ = *read++; + + continue; + } + + read++; + + switch (*read) { + case 't': *write++ = '\\t'; break; + case 'n': *write++ = '\\n'; break; + default: *write++ = *read; + } + + read++; + } + + *write = '\\0'; +} + +int main(int argc, char **argv) { + const char *path = argc > 1 ? argv[1] : "../../conformance/vectors.tsv"; + FILE *handle = fopen(path, "r"); + char *line = NULL; + size_t capacity = 0; + int passed = 0; + int failed = 0; + int skipped = 0; + int first = 1; + + if (handle == NULL) { + fprintf(stderr, "cannot open %s\\n", path); + + return 1; + } + + while (getline(&line, &capacity, handle) != -1) { + char *cells[7]; + char *cursor = line; + char answer[256]; + char actual[256]; + int index = 0; + long written = 0; + size_t length = strlen(line); + + if (length > 0 && line[length - 1] == '\\n') { + line[length - 1] = '\\0'; + } + + if (first) { + first = 0; + + continue; + } + + if (line[0] == '\\0') { + continue; + } + + for (index = 0; index < 7; index++) { + char *tab = strchr(cursor, '\\t'); + + cells[index] = cursor; + + if (tab == NULL) { + break; + } + + *tab = '\\0'; + cursor = tab + 1; + } + + unescape(cells[1]); + unescape(cells[6]); + + /* A number input to a validator has no C form: the parameter is a pointer and a length, + * so the JavaScript quirk "a number is never a valid CNPJ" cannot be asked. The formatter + * coerces, so its number cases are replayed as the decimal string, the same as in Go. */ + if (strcmp(cells[2], "number") == 0 && strcmp(cells[0], "isValidCnpj") == 0) { + skipped++; + + continue; + } + + long version = cells[3][0] == '\\0' ? -1 : atol(cells[3]); + + if (strcmp(cells[0], "isValidCnpj") == 0) { + int valid = cnpj_is_valid_cnpj((const unsigned char *)cells[1], strlen(cells[1]), version); + + snprintf(actual, sizeof(actual), "%s", valid ? "true" : "false"); + } else { + written = (long)cnpj_format_cnpj((const unsigned char *)cells[1], strlen(cells[1]), version, + cells[5][0] == '1' ? 1 : 0, cells[4][0] == '1' ? 1 : 0, + (unsigned char *)answer, sizeof(answer) - 1); + + if (written < 0) { + written = 0; + } + + answer[written] = '\\0'; + snprintf(actual, sizeof(actual), "%s", answer); + } + + if (strcmp(actual, cells[6]) == 0) { + passed++; + } else { + failed++; + + if (failed <= 5) { + fprintf(stderr, "FAIL %s(%s) expected %s got %s\\n", cells[0], cells[1], cells[6], actual); + } + } + } + + free(line); + fclose(handle); + printf("cabi: %d/%d conformance checks passed (%d not expressible)\\n", passed, passed + failed, + skipped); + + return failed == 0 ? 0 : 1; +} `, "out/csharp/Conformance.cs": `// Code generated by spec/bridge/conformance/drivers.ts. DO NOT EDIT. diff --git a/spec/bridge/conformance/run-all.sh b/spec/bridge/conformance/run-all.sh index c882a4ed2..7d3d0d178 100644 --- a/spec/bridge/conformance/run-all.sh +++ b/spec/bridge/conformance/run-all.sh @@ -9,6 +9,10 @@ # over HTTP on a local port and every target is pointed at it through the runtime's # BRUTILS_BRIDGE_HTTP_ORIGIN hook. # +# The eighth arm is not a language: it is the C ABI the Rust crate exposes, which is what a +# hand-written binding in Python, Ruby, C#, Java or Erlang would call instead of generated +# source. `spec/BINDINGS-INVESTIGATION.md` has the numbers that make that a real option. +# # Usage: `bash spec/bridge/conformance/run-all.sh` set -uo pipefail @@ -66,12 +70,15 @@ run rust bash -c "cd '${out}/rust' && cargo run --quiet --release --bin conforma step "java" run java bash -c "cd '${out}/java' && javac -nowarn -d classes *.java >/dev/null 2>&1 && java -cp classes Conformance ../../conformance/vectors.tsv" +step "c abi (the shared core every hand-written binding calls)" +run cabi bash -c "cd '${out}/rust' && cargo build --quiet --release 2>/dev/null && gcc -O2 -D_GNU_SOURCE -I. conformance_cabi.c -o conformance_cabi -Ltarget/release -lbrazilian_utils_bridge -Wl,-rpath,'${out}/rust/target/release' && ./conformance_cabi ../../conformance/vectors.tsv" + step "csharp" run csharp bash -c "cd '${out}/csharp' && DOTNET_CLI_TELEMETRY_OPTOUT=1 dotnet run --verbosity quiet -- ../../conformance/vectors.tsv" echo if [ "${status}" -eq 0 ]; then - echo "all seven targets match the JavaScript package" + echo "all seven targets, and the C ABI, match the JavaScript package" else echo "at least one target diverged" fi From 2f35ff2b4d1d72c3300154d067b9a28f2c70f4da Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 21 Sep 2026 03:18:48 +0000 Subject: [PATCH 06/13] refactor(spec): retire the first prototype and its benchmark harness The JSON-per-utility prototype under `spec/codegen` stopped scaling at the third utility and `spec/bridge` replaced it, so the prototype, the schema and the utility files it read, and the conformance runners built on it are removed. `spec/bench` goes with it: the harness existed to answer whether a binary core beats generated source, it answered, and the answer is written down in `spec/BINDINGS-INVESTIGATION.md`. Both are one `git checkout` away in this branch's history, which the report now says. What is left under `spec/` is the engine and the research that shaped it. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01UX1gTGeMTyoXQyr1qUoQKd --- .gitignore | 11 - spec/BINDINGS-INVESTIGATION.md | 60 +- spec/EXPLORATION.md | 232 ------ spec/README.md | 90 +-- spec/bench/core/Cargo.lock | 7 - spec/bench/core/Cargo.toml | 15 - spec/bench/core/src/lib.rs | 223 ------ spec/bench/corpus.json | 1 - spec/bench/harness/csharp/CsharpBench.csproj | 12 - spec/bench/harness/csharp/Program.cs | 246 ------- spec/bench/harness/go/go.mod | 5 - spec/bench/harness/go/go.sum | 2 - spec/bench/harness/go/main.go | 316 --------- spec/bench/harness/java/JavaBench.java | 158 ----- spec/bench/harness/java/JavaNativeBench.java | 205 ------ spec/bench/harness/node-bench.ts | 144 ---- spec/bench/harness/python_bench.py | 275 ------- spec/bench/harness/python_native.py | 80 --- spec/bench/harness/ruby_bench.rb | 187 ----- spec/bench/harness/ruby_native.rb | 65 -- spec/bench/harness/uniffi_bench.py | 53 -- spec/bench/native/c_bench.c | 150 ---- spec/bench/native/python_cext.c | 80 --- spec/bench/native/ruby_cext.c | 47 -- spec/bench/prepare.ts | 50 -- spec/bench/results.jsonl | 52 -- spec/bench/run-all.sh | 29 - spec/bench/run-native.sh | 69 -- spec/bench/table.py | 109 --- spec/bench/uniffi/Cargo.lock | 711 ------------------- spec/bench/uniffi/Cargo.toml | 23 - spec/bench/uniffi/src/bin.rs | 5 - spec/bench/uniffi/src/lib.rs | 111 --- spec/codegen/conformance.ts | 576 --------------- spec/codegen/corpus.ts | 145 ---- spec/codegen/emit.ts | 41 -- spec/codegen/interpret.ts | 347 --------- spec/codegen/ir.ts | 153 ---- spec/codegen/plan.ts | 179 ----- spec/codegen/targets/go.ts | 413 ----------- spec/codegen/targets/java.ts | 431 ----------- spec/codegen/targets/python.ts | 451 ------------ spec/codegen/targets/registry.ts | 20 - spec/codegen/targets/ruby.ts | 453 ------------ spec/codegen/targets/rust.ts | 374 ---------- spec/codegen/targets/typescript.ts | 364 ---------- spec/codegen/vectors.ts | 81 --- spec/conformance/differential-javascript.ts | 132 ---- spec/conformance/probes/go-probe.go | 40 -- spec/conformance/probes/python-probe.py | 40 -- spec/conformance/probes/ruby-probe.rb | 19 - spec/conformance/probes/rust-probe.rs | 111 --- spec/conformance/run-all.sh | 26 - spec/conformance/upstream.ts | 178 ----- spec/schema/charsets.json | 39 - spec/schema/check-digits.json | 25 - spec/schema/utility.schema.json | 237 ------- spec/utilities.json | 4 - spec/utilities/format-cpf.json | 134 ---- spec/utilities/is-valid-cpf.json | 155 ---- spec/utilities/is-valid-pis.json | 127 ---- spec/vectors/conformance.json | 1 - vite.config.ts | 21 +- 63 files changed, 53 insertions(+), 9087 deletions(-) delete mode 100644 spec/EXPLORATION.md delete mode 100644 spec/bench/core/Cargo.lock delete mode 100644 spec/bench/core/Cargo.toml delete mode 100644 spec/bench/core/src/lib.rs delete mode 100644 spec/bench/corpus.json delete mode 100644 spec/bench/harness/csharp/CsharpBench.csproj delete mode 100644 spec/bench/harness/csharp/Program.cs delete mode 100644 spec/bench/harness/go/go.mod delete mode 100644 spec/bench/harness/go/go.sum delete mode 100644 spec/bench/harness/go/main.go delete mode 100644 spec/bench/harness/java/JavaBench.java delete mode 100644 spec/bench/harness/java/JavaNativeBench.java delete mode 100644 spec/bench/harness/node-bench.ts delete mode 100644 spec/bench/harness/python_bench.py delete mode 100644 spec/bench/harness/python_native.py delete mode 100644 spec/bench/harness/ruby_bench.rb delete mode 100644 spec/bench/harness/ruby_native.rb delete mode 100644 spec/bench/harness/uniffi_bench.py delete mode 100644 spec/bench/native/c_bench.c delete mode 100644 spec/bench/native/python_cext.c delete mode 100644 spec/bench/native/ruby_cext.c delete mode 100644 spec/bench/prepare.ts delete mode 100644 spec/bench/results.jsonl delete mode 100644 spec/bench/run-all.sh delete mode 100644 spec/bench/run-native.sh delete mode 100644 spec/bench/table.py delete mode 100644 spec/bench/uniffi/Cargo.lock delete mode 100644 spec/bench/uniffi/Cargo.toml delete mode 100644 spec/bench/uniffi/src/bin.rs delete mode 100644 spec/bench/uniffi/src/lib.rs delete mode 100644 spec/codegen/conformance.ts delete mode 100644 spec/codegen/corpus.ts delete mode 100644 spec/codegen/emit.ts delete mode 100644 spec/codegen/interpret.ts delete mode 100644 spec/codegen/ir.ts delete mode 100644 spec/codegen/plan.ts delete mode 100644 spec/codegen/targets/go.ts delete mode 100644 spec/codegen/targets/java.ts delete mode 100644 spec/codegen/targets/python.ts delete mode 100644 spec/codegen/targets/registry.ts delete mode 100644 spec/codegen/targets/ruby.ts delete mode 100644 spec/codegen/targets/rust.ts delete mode 100644 spec/codegen/targets/typescript.ts delete mode 100644 spec/codegen/vectors.ts delete mode 100644 spec/conformance/differential-javascript.ts delete mode 100644 spec/conformance/probes/go-probe.go delete mode 100644 spec/conformance/probes/python-probe.py delete mode 100644 spec/conformance/probes/ruby-probe.rb delete mode 100644 spec/conformance/probes/rust-probe.rs delete mode 100755 spec/conformance/run-all.sh delete mode 100644 spec/conformance/upstream.ts delete mode 100644 spec/schema/charsets.json delete mode 100644 spec/schema/check-digits.json delete mode 100644 spec/schema/utility.schema.json delete mode 100644 spec/utilities.json delete mode 100644 spec/utilities/format-cpf.json delete mode 100644 spec/utilities/is-valid-cpf.json delete mode 100644 spec/utilities/is-valid-pis.json delete mode 100644 spec/vectors/conformance.json diff --git a/.gitignore b/.gitignore index c6411c74d..7a784b1d1 100644 --- a/.gitignore +++ b/.gitignore @@ -19,14 +19,3 @@ reports/* !reports/api/ reports/api/* !reports/api/brazilian-utils.api.md -spec/generated - -# The benchmark harness builds its artifacts from source; `spec/bench/run-all.sh` recreates them. -spec/bench/.build -spec/bench/.spec-masked-strict -spec/bench/**/target -spec/bench/harness/go/generated -spec/bench/harness/java/Cpf.java -spec/bench/harness/java/SpecRuntime.java -spec/bench/harness/csharp/bin -spec/bench/harness/csharp/obj diff --git a/spec/BINDINGS-INVESTIGATION.md b/spec/BINDINGS-INVESTIGATION.md index 238822b1a..1c4890a4d 100644 --- a/spec/BINDINGS-INVESTIGATION.md +++ b/spec/BINDINGS-INVESTIGATION.md @@ -1,9 +1,8 @@ # One core, every language: bindings or generated source? -The follow up question to [EXPLORATION.md](EXPLORATION.md): instead of generating **source** for -each language, could Brazilian Utils build the logic once — in Rust, in C, in WebAssembly — and -give every package a **binding** to it? Is there an off the shelf tool for that? And what does it -cost at run time? +Instead of generating **source** for each language, could Brazilian Utils build the logic once +— in Rust, in C, in WebAssembly — and give every package a **binding** to it? Is there an off +the shelf tool for that? And what does it cost at run time? What is being shared either way is the **utility's implementation**, not the published package. Every ecosystem keeps writing its own DX by hand: its naming, its option objects, its types, its @@ -17,13 +16,8 @@ code than the wrapper it sits behind. > ecosystems. [§2](#2-the-boundary-costs-more-than-the-work--but-only-over-the-wrong-boundary) > has the corrected numbers and what they turn on. -Everything below was measured on this branch. Reproduce with: - -```bash -bash spec/bench/run-all.sh # every arm, every language -bash spec/bench/run-native.sh # the bindings each ecosystem actually ships -bash spec/conformance/run-all.sh # every arm still answers identically -``` +Everything below was measured on this branch; [Reproducing](#reproducing) says how to get the +harness back and re-run it. --- @@ -72,15 +66,15 @@ takes generated source. The full recommendation is [at the end](#recommendation) ## How it was measured -One function — `isValidCpf` under the `masked-strict` profile — over a fixed corpus of 1000 -inputs (`spec/bench/corpus.json`): valid CPFs bare and masked, near misses with one digit flipped, +One function — `isValidCpf` under a single shared profile — over a fixed corpus of 1000 +inputs: valid CPFs bare and masked, near misses with one digit flipped, junk, Unicode whitespace, NBSP, ZWNBSP, an emoji, and CPFs written in full width and Arabic-Indic digits. Each arm reports the best nanoseconds per call over 7 repetitions after warmup, plus how many inputs it called valid — an arm cannot win by doing less work. Every arm computes the same thing, and the source level arms are generated from the **same -profile** (`spec/bench/prepare.ts` overrides each package's adopted profile for the run), so the -comparison is not measuring one package's laxer contract against another's. +profile** — the harness overrides each package's adopted profile for the run — so the comparison +is not measuring one package's laxer contract against another's. Machine: Intel Xeon @ 2.80GHz, 4 vCPU, Linux. Node 22.22.2, Python 3.11.15, Ruby 3.3.6, Go 1.24.7, rustc 1.94.1, OpenJDK 21.0.10, wasmtime-py 48.0.0, wasmtime gem 48.0.1, wazero 1.9.0, UniFFI 0.29. @@ -173,6 +167,12 @@ Python went 6485 → 1366 ns/op; Ruby 15051 → 2020. Conformance stayed at 2229 **This is the load bearing result for the whole idea**: the emitter is allowed to know things about its target language, and the moment it does, generated code stops being a compromise. +The `generated` arms came from the first prototype, `spec/codegen`, which described a utility as +JSON and emitted six languages from it. That prototype is retired — writing a utility as data +stopped scaling at the third one — and [`spec/bridge`](bridge/README.md) replaced it, so the +numbers above are a recording rather than something the current tree re-runs. What carried over +is the rule they established, and every emitter in `spec/bridge` is written to it. + ### 2. The boundary costs more than the work — but only over the wrong boundary The validator body is 47 ns, measured by calling the same shared library from C @@ -313,8 +313,8 @@ what makes it affordable.** functions, six ecosystems that each demand idiomatic naming, zero runtime dependencies, and a flagship package that must stay tree shakeable. Every binding generator optimises for the opposite shape. The closest thing to prior art is Kaitai Struct, and its model — a declarative spec plus one -compiler backend per language — is exactly what `spec/codegen` already is, at 350–430 lines per -target. +compiler backend per language — is exactly what [`spec/bridge`](bridge/README.md) is, at +390–660 lines per target. --- @@ -375,26 +375,22 @@ it is a release pipeline per package, and it is the reason step 6 exists. ## Reproducing -```bash -cargo build --release --manifest-path spec/bench/core/Cargo.toml -cargo build --release --target wasm32-unknown-unknown --manifest-path spec/bench/core/Cargo.toml -bash spec/bench/run-all.sh > spec/bench/results.jsonl - -# the UniFFI arm, which needs its own build -cargo build --release --manifest-path spec/bench/uniffi/Cargo.toml -cd spec/bench/uniffi && ./target/release/uniffi-bindgen generate \ - --library target/release/libbrutils_uniffi.so --language python --out-dir ../.build/uniffi-python -cp target/release/libbrutils_uniffi.so ../.build/uniffi-python/ -python3 ../harness/uniffi_bench.py -``` - -The native binding arms are a separate script, because they need each ecosystem's build -toolchain rather than its wasm runtime: +The harness that produced every number above — the Rust core, the wasm and `cdylib` builds, the +handwritten and generated arms in six languages, the CPython and Ruby C extensions, the Panama +and P/Invoke arms, the UniFFI crate and the recorded `results.jsonl` — lived at `spec/bench/`. +It was removed once it had answered the question, so that what stays in the tree is the engine +rather than the experiment. It is one command away: ```bash +git checkout 3780bd6 -- spec/bench # the last commit that carries the harness +bash spec/bench/run-all.sh > spec/bench/results.jsonl bash spec/bench/run-native.sh >> spec/bench/results.jsonl +python3 spec/bench/table.py # folds the lines into the tables above ``` +`run-all.sh` also needs `spec/codegen`, the first prototype, which the same commit carries; the +two were retired together, and the paragraph below §1 says what that means for that finding. + Requires `node`, `python3` (with `wasmtime` and its development headers), `ruby` (with the `wasmtime` gem and its development headers), `go`, `cargo` with the `wasm32-unknown-unknown` target, `javac` (21+), `dotnet` (8+) and a C compiler. diff --git a/spec/EXPLORATION.md b/spec/EXPLORATION.md deleted file mode 100644 index 1eecb84ba..000000000 --- a/spec/EXPLORATION.md +++ /dev/null @@ -1,232 +0,0 @@ -# One implementation, every language - -An exploration of whether Brazilian Utils can be written once and shipped in JavaScript, Python, -Go, Rust, Ruby, Erlang, .NET and whatever comes next, **without changing what any published -package does today**. - -Everything claimed here is reproducible from this repository: - -```bash -bash spec/conformance/run-all.sh # 6 languages, generated and checked -node spec/conformance/upstream.ts --python ../python --ruby ../ruby --go ../go --rust ../rust -``` - ---- - -## The short answer - -Yes — but the thing to write once is **not code**. It is a specification, and code generation is -the last and most optional step of the three. - -| Layer | What it is | Who consumes it | Risk to existing packages | -| ------------ | -------------------------------------------------------------------------- | ---------------------------------------- | ------------------------------------------------------------------------- | -| L0 — Vectors | A list of inputs and the answer each named behaviour gives | Every package's test suite | None. It is a test file. | -| L1 — Spec | The behaviour itself, as data: charsets, check digit algorithms, pipelines | The generator, the reviewers, new ports | None. Nothing ships it. | -| L2 — Codegen | Idiomatic source for each language, emitted from L1 | Packages that opt in, utility by utility | None **by construction** — see [Profiles](#how-a-contract-survives-this). | - -Writing the algorithm once means writing it at L1. L2 is how a package stops re-typing it, and a -package can adopt L2 for `isValidCpf` and keep everything else handwritten. - -**Writing it in Rust and generating the rest is the wrong shape of the same idea.** Rust source is -still a language: to read it from Go you either transpile it (same problems as transpiling -TypeScript, below) or ship it as a native artifact, which costs this project the things it sells — -zero dependencies, tree shaking, Bun/Deno/browser parity, a pure gem, a pure wheel, a pure BEAM -library. A specification has no host language, so no package is anyone's downstream. - ---- - -## What was built to test the claim - -Three utilities — `isValidCpf`, `isValidPis`, `formatCpf` — were specified as data and emitted to -six languages, including Java, which has no package today. - -``` -spec/ - utilities/*.json the utilities: profiles, pipelines, names per language (416 lines) - schema/ charsets, check digit algorithms, the JSON Schema - codegen/ the reference interpreter and the six emitters (3,830 lines) - vectors/conformance.json 743 inputs x 13 expectations, generated (100 KB) - conformance/ the differential runners - generated/ output, not committed: `node spec/codegen/emit.ts` -``` - -The 416 lines of specification produce 1,647 lines of library code across the six languages, plus -the conformance drivers. A new language costs one emitter of 350–430 lines and buys every utility -already specified. - -### Results - -| Check | Result | -| ------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------- | -| Spec vs. the package **this repository ships** (`src/`) | **11,928/11,928** agree, over 1,983 corpus inputs plus `null`, `undefined`, numbers, `NaN`, arrays, objects | -| Generated TypeScript vs. vectors | 4,458/4,458 | -| Generated Python / Ruby / Go / Rust vs. vectors | 2,229/2,229 each | -| Generated Java vs. vectors | 4,458/4,458 | -| Spec vs. the **published** `brutils` (Python) | 741/743, plus 2 documented deviations | -| Spec vs. the **published** gem (Ruby) | 743/743 | -| Spec vs. the **published** Go module | 743/743 | -| Spec vs. the **published** Rust crate | 743/743 | - -The corpus is seeded and deterministic (`spec/codegen/corpus.ts`): valid numbers, masked numbers, -numbers with one digit flipped, junk, Unicode whitespace, NBSP, ZWNBSP, an emoji with a surrogate -pair, and CPFs written in full width and Arabic-Indic digits. - ---- - -## Four things the exercise turned up - -### 1. The contracts already disagree — badly - -This is the central finding. The worry was "let us not create an issue by unifying". The issue -exists now, and nobody can see it because nothing compares the packages. - -| Input | JavaScript | Python | Ruby | Rust | Erlang | Go | -| --------------------------------------- | ---------- | --------- | ------- | ------- | ------- | --------- | -| `"12345678909"` | valid | valid | valid | valid | valid | valid | -| `"123.456.789-09"` | **valid** | invalid | invalid | invalid | invalid | **valid** | -| `"123 456 789 09"` | **valid** | invalid | invalid | invalid | invalid | **valid** | -| `"abc12345678909"` | invalid | invalid | invalid | invalid | invalid | **valid** | -| `"12345678909"` (full width) | invalid | **valid** | invalid | invalid | invalid | invalid | - -Four different answers to "is this a CPF". A user who validates a masked CPF in the browser and -again in a Python backend gets two verdicts today. - -The JavaScript, Python, Ruby, Rust and Go columns were produced by running those packages -(`spec/conformance/upstream.ts`). The Erlang column was read from `brutils_cpf.erl`, whose -`is_valid/1` requires a binary of exactly 11 ASCII digits; no Erlang toolchain was available here -to execute it. - -### 2. `brutils` accepts a CPF written in Arabic-Indic digits - -`brutils/cpf.py` and `brutils/pis.py` gate on `str.isdigit()`, which is Unicode aware, so -`"١٢٣٤٥٦٧٨٩٠٩"` validates and `format_cpf` returns `"١٢٣.٤٥٦.٧٨٩-٠٩"`. Ruby's `/^\d+$/` and Rust's -`is_ascii_digit` do not. This is recorded in the specs as a `knownDeviations` entry, and it is a -bug report waiting to be filed against the Python package. - -### 3. PIS is the mirror image of CPF - -The JavaScript package rejects `"00000000000"` as a PIS and accepts `"120.56874.10-7"`. Python, Go, -Ruby and Rust do the opposite on **both** counts: they accept the repeated run and reject every -mask. 66 of 743 corpus inputs differ. Neither side is obviously right; neither side knows. - -### 4. A regex is not portable, so the spec has none - -`\s` matches 6 characters in Go and Ruby, 25 in JavaScript, and a Unicode property in Python and -the Rust `regex` crate. `\d` matches Devanagari digits in Python. Ruby's `^`/`$` are line anchors, -not string anchors. Java expands `\u000a` _before_ lexing, so a generated string literal containing -one ends on a real line break — which is exactly how the first Java emitter failed here. - -So the IR carries no regex: a charset is a list of code points -(`spec/schema/charsets.json`), and the shape of a masked number is digit group sizes plus a -separator set. Every emitter renders that as explicit comparisons. This is the concrete reason a -naive "transpile the TypeScript" approach cannot be trusted: the regexes would survive the -translation and quietly change meaning. - ---- - -## How a contract survives this - -A utility does not have _a_ behaviour. It has **profiles**, and each package declares which one it -implements today: - -```jsonc -"adopted": { - "typescript": { "profile": "masked-strict" }, - "python": { "profile": "digits-only", "knownDeviations": [ /* the Unicode digits bug */ ] }, - "go": { "profile": "digits-extracted" } -}, -"profiles": { - "masked-strict": { "description": "...", "pipeline": [ /* ... */ ] }, - "digits-only": { "description": "...", "pipeline": [ /* ... */ ] }, - "digits-extracted": { "description": "...", "pipeline": [ /* ... */ ] } -} -``` - -Three consequences: - -1. **Generating a package is a no-op release.** The Go emitter produces Go's lenient behaviour, the - Ruby emitter produces Ruby's strict one. The proof is in the table above: the generated code and - the published code agree on every corpus input. -2. **Convergence becomes a decision, not an accident.** Moving Python from `digits-only` to - `masked-strict` is a one line change whose blast radius the vectors print exactly: these inputs, - this many, changing from this answer to that one. That is a major version conversation with data - attached, per package, on each package's own schedule. -3. **A new language starts on the canonical profile.** Java here adopts `masked-strict` from day - one, because there is no installed base to protect. - ---- - -## What this does not solve - -Of the 138 utilities in `src/`, the ones that are a pipeline over digits are the large majority, -but not all of them: - -| Group | Count | Portable as data? | -| ------------------------------------------------------------------------------------ | ----- | ----------------------------------------------------------------------------------------- | -| Digit/mask pipelines (`isValid*`, `format*`, `parse*`) | ~89 | Yes — this is what the prototype covers | -| Dataset lookups (banks, municipalities, CNAE, CBO, CFOP, NCM, legal natures, states) | 25 | The logic is trivial; the value is the table. See below. | -| Random generators (`generate*`) | 13 | The construction is; the RNG and its seeding are per language. | -| Date logic (holidays, business days, date to words) | 9 | Partly. Easter and the holiday table are data; the calendar type is not. | -| HTTP (`getAddressInfoByCep`, `getCepInfoByAddress`) | 2 | The provider list, the fallback order and the error taxonomy are data. The client is not. | -| Locale formatting (`formatCurrency`) | 1 | `Intl`/CLDR has no equivalent in Go or Erlang. Handwritten, or a shared CLDR subset. | - -(24 utilities depend on a host facility — a clock, an RNG, `Intl` or the network — and 12 of those -also read a dataset, so the rows overlap slightly.) - -Trying to specify all of it in one IR is how this kind of project dies. The IR should grow one -utility family at a time, and anything that resists it stays handwritten — that is a normal -outcome, not a failure. - -**The dataset question is separate and probably worth more.** `src/_internals/constants/` (banks, -municipalities, CNAE, CBO, CFOP, NCM, legal natures) is already generated from official sources by -`scripts/`. Every other package either re-scrapes those sources or does without. Publishing those -tables as a versioned, language neutral artifact is less work than any of the above and removes -more duplication. - ---- - -## Why not the other two options - -**Transpile the TypeScript.** The semantics that would have to come along are `String()` coercion, -`NaN`, `null` vs `undefined`, UTF-16 versus scalar iteration, `Intl`, and the regex differences -above. The output would be unreviewable by the people who maintain the Go and Ruby packages, and -the generated names would not match what those packages publish. The value of these libraries is -that they read like ordinary Go and ordinary Ruby. - -**One core in Rust, bindings everywhere.** It breaks the npm package's zero dependency, -tree shakeable, Bun/Deno/browser promise; it forces a native toolchain on the gem and the wheel; -it has no answer for Erlang or for a pure .NET assembly; and every binding still needs a -handwritten shell with its own contract. Worth revisiting only for something genuinely heavy, which -none of these utilities are. - ---- - -## Suggested order of work - -1. **Publish the vectors** (no code changes anywhere). A `brazilian-utils/spec` repository holding - `charsets`, `check-digits`, the utility specs and `conformance.json`. Each package adds one test - that reads it. The payoff is immediate: every package learns, in CI, exactly how it differs from - the others. -2. **File the divergences as issues**, one per finding above, in the package that owns each. -3. **Specify the ~40 document number utilities** (CPF, CNPJ, CEP, PIS, CNH, CNS, CNO, CEI, CAEPF, - NFe key, RENAVAM, voter ID, boleto, IBAN, Pix keys, plates...). This is the bulk of the - duplicated work and the part the IR already covers. -4. **Opt into codegen where maintainers want it.** The Erlang and .NET packages, which cover the - fewest utilities, gain the most: an emitter each, and they inherit everything specified. -5. **Converge profiles deliberately**, one package major version at a time, with the vector diff in - the release notes. - -Steps 1 and 2 are worth doing even if steps 3 to 5 never happen. - ---- - -## Open questions for the team - -- Which profile should be the canonical one? The JavaScript package is the most permissive on masks - and the strictest on shape; is "accepts the mask a human would type" the contract we want - everywhere? -- Should `spec` be its own repository, or live here with the other packages reading it by tag? The - prototype lives here because that is where the most complete implementation is, not because that - is the right home. -- Who owns a profile change? Today each package owns its behaviour. A shared spec needs one place - where "CPF accepts masks" is decided. diff --git a/spec/README.md b/spec/README.md index a94bbb17b..38f5588f1 100644 --- a/spec/README.md +++ b/spec/README.md @@ -1,87 +1,29 @@ -# `spec/` — the language neutral specification +# `spec/` — write a utility once, ship it in every language -A prototype of describing a utility once, as data, and emitting it to every language Brazilian -Utils publishes. Read [EXPLORATION.md](EXPLORATION.md) first: it explains why this exists, what it -proves, what it does not, and what to do next. Then -[BINDINGS-INVESTIGATION.md](BINDINGS-INVESTIGATION.md), which measures this approach against the -alternative — one binary core plus bindings — in five languages, and says why generated source -wins. +Brazilian Utils publishes the same utilities in JavaScript, Python, Go, Rust and Ruby, and each +one is written by hand, in each language, again. This directory is the attempt to write each +utility **once** and have every language's implementation come out of that. Nothing here ships in the npm package. `src/` is untouched, and the build, the bundle and the public API are exactly what they were. ## Layout -| Path | What it holds | -| ---------------------------- | ---------------------------------------------------------------------------------------------- | -| `utilities/*.json` | One file per utility: its profiles, the pipeline of each, and the name every language gives it | -| `utilities.json` | The utilities the specification covers, in emission order | -| `schema/charsets.json` | Character sets as explicit code points — never a regex shorthand | -| `schema/check-digits.json` | Check digit algorithms as weights, modulus and clamp | -| `schema/utility.schema.json` | JSON Schema of a utility file | -| `codegen/interpret.ts` | The reference interpreter: the normative implementation | -| `codegen/corpus.ts` | The seeded input corpus | -| `codegen/vectors.ts` | Writes `vectors/conformance.json` from the interpreter | -| `codegen/targets/*.ts` | One emitter per language | -| `vectors/conformance.json` | The committed vectors: every input, every profile, every option set | -| `conformance/` | The runners that check the generated code, this package, and the published ones | -| `generated/` | Emitter output. Not committed; `node spec/codegen/emit.ts` rebuilds it | +| Path | What it holds | +| --------------------------- | ------------------------------------------------------------------------------- | +| `bridge/` | The engine: a portable TypeScript subset in, native code for seven targets out | +| `BINDINGS-INVESTIGATION.md` | The other route — one binary core plus bindings — measured, and where each wins | + +Start with [`bridge/README.md`](bridge/README.md): it is the manual for the engine, the subset it +accepts and what it refuses. [`BINDINGS-INVESTIGATION.md`](BINDINGS-INVESTIGATION.md) is the +research that decided the shape of it, including the benchmark numbers that say a binding is +cheap in C#, Python, Ruby and Java, and that JavaScript cannot take one at all. ## Running it ```bash -node spec/codegen/vectors.ts # rebuild the vectors from the interpreter -node spec/codegen/emit.ts # emit every target into spec/generated -node spec/codegen/emit.ts rust # ...or just one +node spec/bridge/compiler/cli.ts # compile source/ into every target +node spec/bridge/compiler/cli.ts rust # ...or just one -bash spec/conformance/run-all.sh # emit, then run all six conformance drivers -node spec/conformance/differential-javascript.ts # spec vs. the package this repo ships +bash spec/bridge/conformance/run-all.sh # every target replays what the npm package answers ``` - -`run-all.sh` needs `node`, `python3`, `ruby`, `go`, `rustc` and `javac` on the PATH; each driver is -standalone and needs no package manager. - -To compare the specification against the other packages, check them out as siblings and point the -upstream runner at them: - -```bash -node spec/conformance/upstream.ts --python ../python --ruby ../ruby --go ../go --rust ../rust -``` - -It prints, per package and per utility, how many of the corpus inputs agree with the profile that -package declares, and the first few that do not. `0 disagreement(s)` means the specification -describes every shipped contract exactly. - -## Adding a utility - -1. Write `utilities/.json`. Give it one profile per behaviour that exists in the wild, and an - `adopted` entry per language saying which one that package implements **today** — not the one - you wish it implemented. Add it to `utilities.json`. -2. Run `node spec/conformance/upstream.ts ...` against the other checkouts. If a package - disagrees with the profile you gave it, the profile is wrong, or you found a bug: record it - under `knownDeviations` with a reason, and open an issue there. -3. Run `node spec/codegen/vectors.ts` to refresh the vectors, then `bash -spec/conformance/run-all.sh`. -4. For a utility this repository already ships, extend `conformance/differential-javascript.ts` so - the specification is checked against the handwritten implementation over the whole corpus, - hostile inputs included. - -If a utility needs a step the IR does not have, add the step to `schema/utility.schema.json`, to -`Step` in `codegen/ir.ts`, to the interpreter, and to the six emitters — in that order. That cost -is the honest price of a new kind of behaviour, and it is why the IR should stay small. - -## Benchmarking a target - -`bash spec/bench/run-all.sh` builds every artifact and prints one JSON line per measurement into -`spec/bench/results.jsonl`; `python3 spec/bench/table.py` folds that into the table in the -investigation. A new or changed emitter is not done until its output has been measured against -idiomatic handwritten code for that language: emitting a per code point loop into a language whose -regex engine is written in C costs 2–4×, which is how the Python and Ruby emitters were found to -be slow and then fixed. - -## Adding a language - -Write `codegen/targets/.ts` (350–430 lines, modelled on any existing one), register it in -`codegen/targets/registry.ts`, add a driver in `codegen/conformance.ts`, and add the language's -`names` and `adopted` entries to each utility file. The Java target exists precisely as the worked -example of a language with no package yet. diff --git a/spec/bench/core/Cargo.lock b/spec/bench/core/Cargo.lock deleted file mode 100644 index 0c3c8d7af..000000000 --- a/spec/bench/core/Cargo.lock +++ /dev/null @@ -1,7 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 4 - -[[package]] -name = "brutils_bench_core" -version = "0.0.0" diff --git a/spec/bench/core/Cargo.toml b/spec/bench/core/Cargo.toml deleted file mode 100644 index 0ef340660..000000000 --- a/spec/bench/core/Cargo.toml +++ /dev/null @@ -1,15 +0,0 @@ -[package] -name = "brutils_bench_core" -version = "0.0.0" -edition = "2021" -publish = false - -[lib] -crate-type = ["cdylib", "rlib"] -path = "src/lib.rs" - -[profile.release] -opt-level = 3 -lto = true -panic = "abort" -codegen-units = 1 diff --git a/spec/bench/core/src/lib.rs b/spec/bench/core/src/lib.rs deleted file mode 100644 index d54293956..000000000 --- a/spec/bench/core/src/lib.rs +++ /dev/null @@ -1,223 +0,0 @@ -//! The shared core used by every non source level arm of the benchmark. -//! -//! It implements exactly one thing — `isValidCpf` under the `masked-strict` profile — with the -//! same steps the generated code uses, so the only difference between the arms is how the call -//! crosses the language boundary. -//! -//! Two entry points on purpose: -//! -//! * `cpf_is_valid` takes one string and answers one bool: the shape a binding generator -//! produces from a spec, and the shape an application actually calls. -//! * `cpf_is_valid_batch` takes a packed buffer of N strings and fills N bytes: the shape you -//! fall back to when the boundary turns out to cost more than the work itself. - -#![no_std] - -const fn is_ascii_digit(code: u32) -> bool { - code >= 0x30 && code <= 0x39 -} - -/// The code points JavaScript's `trim()` strips and its `\s` matches. -const fn is_js_whitespace(code: u32) -> bool { - matches!( - code, - 0x09 | 0x0a - | 0x0b - | 0x0c - | 0x0d - | 0x20 - | 0xa0 - | 0x1680 - | 0x2028 - | 0x2029 - | 0x202f - | 0x205f - | 0x3000 - | 0xfeff - ) || (code >= 0x2000 && code <= 0x200a) -} - -const fn is_mask_cpf(code: u32) -> bool { - code == 0x2e || code == 0x2d || code == 0x2f || is_js_whitespace(code) -} - -fn check_digit(base: &[u8]) -> u32 { - let mut sum: u32 = 0; - let mut weight = base.len() as u32 + 1; - - for byte in base { - sum += u32::from(*byte - b'0') * weight; - weight -= 1; - } - - let digit = 11 - (sum % 11); - - if digit >= 10 { - 0 - } else { - digit - } -} - -/// Validates one CPF under the `masked-strict` profile. -pub fn is_valid(value: &str) -> bool { - let trimmed = value.trim_matches(|char: char| is_js_whitespace(char as u32)); - let mut digits = [0u8; 11]; - let mut count = 0; - let groups = [3usize, 3, 3, 2]; - let mut iter = trimmed.chars().peekable(); - - for (position, size) in groups.iter().enumerate() { - if position > 0 { - while let Some(char) = iter.peek() { - if is_mask_cpf(*char as u32) { - iter.next(); - } else { - break; - } - } - } - - for _ in 0..*size { - match iter.next() { - Some(char) if is_ascii_digit(char as u32) => { - digits[count] = char as u8; - count += 1; - } - _ => return false, - } - } - } - - if iter.next().is_some() { - return false; - } - - let first = digits[0]; - - if digits.iter().all(|digit| *digit == first) { - return false; - } - - if u32::from(digits[9] - b'0') != check_digit(&digits[..9]) { - return false; - } - - u32::from(digits[10] - b'0') == check_digit(&digits[..10]) -} - -// --------------------------------------------------------------------------- -// C ABI, used by the FFI arms and by the wasm arms alike. -// --------------------------------------------------------------------------- - -/// Validates one CPF held at `ptr` for `len` bytes of UTF-8. Returns 1 or 0. -/// -/// # Safety -/// -/// `ptr` must point at `len` readable bytes. -#[no_mangle] -pub unsafe extern "C" fn cpf_is_valid(ptr: *const u8, len: usize) -> i32 { - let bytes = core::slice::from_raw_parts(ptr, len); - - match core::str::from_utf8(bytes) { - Err(_) => 0, - Ok(value) => i32::from(is_valid(value)), - } -} - -/// Validates `count` CPFs packed as [u32 length][bytes]... and writes one byte per verdict. -/// -/// # Safety -/// -/// `input` must hold the packed buffer and `output` at least `count` writable bytes. -#[no_mangle] -pub unsafe extern "C" fn cpf_is_valid_batch( - input: *const u8, - input_len: usize, - output: *mut u8, - count: usize, -) -> i32 { - let buffer = core::slice::from_raw_parts(input, input_len); - let results = core::slice::from_raw_parts_mut(output, count); - let mut offset = 0; - - for slot in results.iter_mut() { - if offset + 4 > buffer.len() { - return -1; - } - - let length = u32::from_le_bytes([ - buffer[offset], - buffer[offset + 1], - buffer[offset + 2], - buffer[offset + 3], - ]) as usize; - - offset += 4; - - if offset + length > buffer.len() { - return -1; - } - - *slot = match core::str::from_utf8(&buffer[offset..offset + length]) { - Err(_) => 0, - Ok(value) => u8::from(is_valid(value)), - }; - - offset += length; - } - - 0 -} - -// --------------------------------------------------------------------------- -// A bump arena, so a wasm host can hand strings in without a real allocator. -// --------------------------------------------------------------------------- - -const ARENA_SIZE: usize = 1 << 21; -static mut ARENA: [u8; ARENA_SIZE] = [0; ARENA_SIZE]; -static mut ARENA_USED: usize = 0; - -/// Reserves `len` bytes of the arena and returns a pointer to them. -#[no_mangle] -pub extern "C" fn arena_alloc(len: usize) -> *mut u8 { - unsafe { - let base = core::ptr::addr_of_mut!(ARENA) as *mut u8; - - if ARENA_USED + len > ARENA_SIZE { - ARENA_USED = 0; - } - - let offset = ARENA_USED; - - ARENA_USED += len; - - base.add(offset) - } -} - -/// Empties the arena. -#[no_mangle] -pub extern "C" fn arena_reset() { - unsafe { - ARENA_USED = 0; - } -} - -#[cfg(target_arch = "wasm32")] -#[panic_handler] -fn panic(_info: &core::panic::PanicInfo) -> ! { - core::arch::wasm32::unreachable() -} - -#[cfg(not(target_arch = "wasm32"))] -#[panic_handler] -fn panic(_info: &core::panic::PanicInfo) -> ! { - loop {} -} - -/// A `no_std` cdylib still has this symbol referenced by the unwinder; `panic = "abort"` means -/// it is never called. -#[cfg(not(target_arch = "wasm32"))] -#[no_mangle] -pub extern "C" fn rust_eh_personality() {} diff --git a/spec/bench/corpus.json b/spec/bench/corpus.json deleted file mode 100644 index 9922623b8..000000000 --- a/spec/bench/corpus.json +++ /dev/null @@ -1 +0,0 @@ -[" ","0","00000000000","11111111111","99999999999","12345678909","123.456.789-09","123 456 789 09"," 12345678909 ","123.456.789.09","123/456/789/09","123-456-789-09","123..456..789--09",".12345678909","12345678909.","1234567890","123456789090","abc12345678909","12345678909abc","1a2345678909","12345678900"," 12345678909 "," 123.456.789-09
","12345678909","123 456 789 09","123\t456\n789\r09","🇧🇷12345678909","12345678909🇧🇷","12345678909","١٢٣٤٥٦٧٨٩٠٩","12056874107","120.56874.10-7","120/56874/10-7","120(56874)10,7","120*56874*10-7","12056874108","1205687410","120.56874.10-7 ","120#56874#10#7","74275733568","69264259294","27502677658","9.5167.3","45528746248","00192591070","2423/3.79a967a0","04349316248","05828033735","*340*)6","01018054771","45960967839","72953559375","350#6#7 633717","85752788760","12201461035","65623597327","08216262647","94291497253","65546678658","02218010658","13434608915","60021596917","99266321688","036/6694a2431","29022796396","659037# ","610954584)85,","57.364183-296","72468124605","01366021578","37242507700","6.5968)418a486","64629394234","89884,197702","588519 7)4/661","06733963710","16153416609","973194*6,5520-","83438658534","48938105458","52070564410","37299492850","97116501347","267a783 45665","7*15653/41811","193a0007658a5","32605779807","81887191706","60150247125","71770889540","38306173004","63 568062866","13765631345","96840834266","875 6a6256601","17)06**05","#478089(3220","977/03000(","660(29a924818","25368103999","15050757707",")49 354 55","23609640126","7587)8147440.","95291932024","32711721370","25#8163547 95","707612.87664.","40110965809","-54)9","62501783555","3855)352323","00158379099","2(1062574","#63(67406","94622089211","85947269915","86/98247","30953452751","5554204406-9","87821425957","10359723012","38589626369","17091421971","649982-92,8,306","*737925","51723668907","0,353077501","1381-9#642420","29972448622","89/-60/84210273","1425.6372500","55427359071","63876408903","106a","53367895857","500978,20993","32498856498","36558846217","26147599291",".(1.9*24*","75660210933","93971033695","52200090253","38476272600","378447344/33","069263407*#51","59139466850","6(87953,3-8570","87373238138","95 1","641350042 5(3","40910963010","268067 8#237*8","83723418503","758131(6","20240907137","33520141268","17938","10213407217","66738397299","45-92166 57(41","05466916770","62762266910","84911262958","81826425290","89205985252","05496053471","52597393372","38652220565","17-89993365275","22279047551","15481647740","54130082795","23442185571","90 500080904","84264259522","58976801750","20648740625","57342147291","8","06787915480","74994999791","308351266,0 0","33664446341","72084287028","62610395930","39083(594068","29462 99449a8","87862097741","148965/24500 ","4549302,4182(","43955822983","49545440333","00838712551","5693995*7#12/0","79/467634503","90117760952","6","450262548(83","71733485502","59920913563","14079680171","067*37*782012","7683735755,1 ","43855708339","26273937561","66846268596","8433,56 40/307","12710973626","60805222300","36453716769","80716189538","96875115166","74336944841","31092397361","16348172139","38146986579","24144680090","35818.63-9282","(0","50373463200","7a6a61220#1053","55023a198.0,(","3857,8,49895)0","84785977515","34957107592","90534660967","2183836)15","1)8813929374(","25625090603","1-4","67817905635","45185817500","62591997515","94866406005","48986981319","48a1)896956(215","12847371605","02712781880*","50590677201","1130)86*12109","85452922541","1657*89388a2-7","06054396416","94680920548","69605029960","64060368330","79870297338","71327360357","06833761241","31953017104","21881139070","03621090/1#28 ","08845801875","66081 17 838.0","(991 59(36720","19929703942","65134983178","56127159482","13905674709","35487816369","01104612585","49147868907","8175837 988(5","1958*2603944","12857330375","39510339750-","57878124270","06770932311","29395616890","50413890.635","3","54711981085","27704704850-","46757073297","3*9#18786a8,113a","8.22,2*,(#","09624157970","20862681019","65845806283","78155325511","91246524902","85037722440","06072829910","19006621385","91822082633","284003-7)6293/","24584648158","81765431668","90125/01,2535","42430498944","28,72040882a2","4674150#3016","a58,","35738654593","49571112270","70116455780","70494#544/864/","63108583352","51832068939","99665590359","3237#5","871 20910493","6 7706696502#","74910*321292","58825236983","91665897113","22473672220","50333a031555","39376825044","16326834334","3/1854069798","86676398427","10a47#83","07203160435","7","54041828147","81939232511","033789.079#08#","7(20 613.","36081312203","14827445113","90094962103","89393206850","37845084553","775-319793 91","3359490 5 098","80531386406","57)406681,15/1","91(231287551,","415","62#067,930(891","44090285141","67489979412","11680919695","32*9#34)167801","29927535309","68816320370","32745256439","49593127933","77791117843","491(378(84506","097a 9)4741-","932.23243/178","28295821005","33212344679","77762041370","95373510416","6/4489153627","42794672014","93206839807","40428139980","27002753061","16041909891","5(939a954561)0","0438-1899814","6806703/6748","76083838506","46508664646","64204832671","03584949823","82976574340","7,2135151017","12435077094","9977(00041 98-","388993*87 958,","699367.6777/27)","91553048220","82674809787","32782781600","1302581(","301/41926580a","99064778258","824 460621 8","70140751009","79774925122","45294338971","67715677884","10*3(6158 65,90*","22115679341","02040884623","8/6956026238","88142588117","45716895786","3516340448 0a","92995777499","17710007188","35*87#17#48781","25570295610","04046*885075","73144445606","75086a8#8058/0","03670355555","-/ 02","a 434 ","59728943107","4080.3088256","#37 0","57049460387","42024527209","50224587436","33689976456","6.3.23-9(8 67877","03014108448","30173549871","53945248343","53416681118","724-49978844","45277444106","40086262556","55205/ 1(*1","54712598077","11228014a340","19984710807","87024275839","40033410231","13026104140","93439798607 ","79547137921","06586026164","30648422267","7473,2299822","78751559404","77371587199","23201372770","48 5(28827259","63098235590","44-68 1014079","4472640","18192199177","36726974559","78164817058","863758171(71","57024472704","02824308596","a252) 5","49487942440","39","01605660652","98460899292","3104897*8753","4(133807a2206","99292011308","63031473936","38076757950","05679802430","63341026362","66,5382991","30414950070","32)-#4611403*","42123780522","06236152#571","82153578817","36045129267","099(987(52343","58536818859","66540536264","45787969065","#,4236","42050173679","8569207-83(25","56(13630","03855805687","31793#036977#","92826784218","991361901*79","3*3647161)202 ","0474552)#5","654(592183 65","70389666858","62488480096","66.59-467 823)0","4#50,.0a21061,8","765801 2*2382","66122001201","26826010305","57142385151","5.35748724#4)3(","47236219541","40549687670","90141629369","70223(9 8674 7","90334100011","04518514970","9354470436 3","7 63)8680#1202.","86305661512","53111178501","35772104276","489(51911098*","19901091446","63013612798","71914656529","44617654747","96491193969","a615,,41","95805869707","29901346205","54208519975","875)53-6*81295","36988108217","5 354 19 4","4/5 3175.172 0,1","67755270160","92879818","98966060521","98114#524)235","6-2 9","77237 56004","64548712588","89499697768","64807531071","4.15*52615#960","029 0*7472598","61447588640","462 86624449","28997279157","9 2769#78 44)0*","12418027879","00576059- 4#.","83871787884","18629180668","625,765938 7(7","68675256998","62682278159","05376651371","15624641471(","55397368261","94697679827","59343010710","96988797300","68741541090","81545791201","06430204977","65078757406","95113422*195","28644466375","-63(,3698","09323157444","53234099691 ","014371442/4*9 ","29715289932","18166 728#150","2)7 6*35541370-","94622736349","30086393632","99920183642","176844)10300","72720)70-4909","0829064a1095","73165138013","21723780626","82760984438","08552756887","56267985520","62062059424","14353708309","20197616968","90970500734","31979867452","667.8133927 3","55494164179","13/73 9728530","22015806008","56825397664",")6 *6(0a146","31,43)2597604","90771312563","29389912075","381997951)31","52 62273.13)","90700384987","05621956966","7748169522","23813064123","78305022501","25623.074294","4132057/7202","71536439312","95498010125","(727,6.4.","21509606726","043397/52460","00346424712","37585164478","74.700668660*","66312087344","96883873367","61955334460","018549.08828","47772633149","01397607840","11/556669682","41826165886","2780148195 0","84674429137","94317787811","506237 79133","40584847998","44943496302","0 32,91#06 ","95196278559","92601882450","50015512407","106/38726082","901#/903678355","21117259856","25882595967","04732383491","9479969 9","95922669800","8883/06156)0*9","32850130796","77974150892","29659535186","49// ","15790872976","58260669897","91329809105","5677103 1950,","14398251227","25824296210","56314621844","94876813277","16263660120","700717*6(2167","684-0502763","15424949790","8-1#91536(69","25371491907","75532925688","34493470550","70651413020","641863190#06/","36238066631","87766231879","78507200168,","97540086980","69426575595","717 0#540339a5","40057456622","16215778052","90760673330","21056750189","64853010206","95 9)760100-00","90259943428","46625500798","98-845045580","42861538430","71521538336","637a","65411877890","2)0224658756","83660227226","41096624424","2 0199552290","43290951901","91037243784","45426209985","39704032862","64763559532","906 33(7251)53","69805193291","04785557086","49612588732","7 )9","6613898473(0","55557336505","75932776234","35734160636","68367455505","43599874434","11981522551","46538105958","45249186411","77458313465","0a0798#895659","7700.4133267",".4-#2/.*-#2*878","461,7","0638673669","7739)5204468","13419417870","30688657217","43076045033","45420468862","47713594587","98299994147","47274872842","10279.099a30)4","63735745800","96010762314","43223170146","90732490086","81106510790","36902649001","36133763930","95524229907","60486932303","48622599876","38354488462","10*237294,664","462605-225,52","82118110709","25424062431","57411529370","49640340787","6245*598(990-9-","08)840/48606","67214459051","86730859433","41922980072","573/830(43308","01504672760","63298685954","09900425375","66694/5(79109","04257613203","27662001321","45617675848","31286558395","60 78 1073417","13782269179","46201891549","72380631544","1.0664386129","51796846302","28075951700","09651265523","76","10229235 794","92605156966","79693025163","24247486918","250*5.","34663768580","03086608463","39378025846","2(718063-2428","80(96a)649936","25795545996","56a290690809","16 649792047*","27252085525","25348089079","86775460732","36445524436",".5(590a38","2062760.0786","81886636805","474*2*","61688094447","21254835059","26924300260","52258500231","065086","85105139793","63625679693","/-- 65922","708446044*6/1","60106076477","23984576480","59680077847","9322905077,0","38954348920","00492189013","04588193872","482 1,5023/#","85050381040","682#386923#44","9318066-4","44605173960","0.5217916938","26561535146","11921285672","3382 5967135(","21877806196","267,7830)51","89632966791","746/1","72894339801","24978641881","36.4(991","91797805323","2510(29/4)8688","68960443980","09615276219","5 106*3310806","86664129256","85641556232","74.98.280)49/31","0),16699-98","77075306/596","47943055403","26964670211","95523583707","22672933358","70485 88859.0#","34749116602","633595420 32","13512751547","40313076081","875279a435,55","585-0988955,4","81933902299","23988884871","15554658202","-1(a4#2 490,47","72463959622","69(448632)00-2","91885234546","47058954615","6876792285 6","644906208*05","01942202814","45006725309","399a21018#787","94525929405","3885.7)18)2789","61224521730","63448129151","065,315699*3)3","02101","401a9322/0 9","16505731180","00877131104","88867356018","958/696841 37","69408979338","18551858572","49304352*347-","22562862920","463422,89177","54098408504","68587*39874a1 ","85802617524","50388932872","10255839800","933039.58300","3634,08-032-75","27390290297","68145066107","72916978089","9)3","41388862654","04743053942","92811367903","58559689075","15444664127","82267674742","3945933-6571","0002731)69 12 ","60742830181","2,5021)0469(31","8057302-8(524","55505518250*"," 86)7#","54783617690","75828201368","55480489596","87106869244","82352299538","64938489865","30577914)342","47139881692","80159915073","06497175699","48#764700-496","7)#))(-","57450863430","0 93#1(4036087","45388613900","52714476260","71310606153","14106674564","83595381157","76893595905","68631507350","25235057708","4240716)161,4#","70972190252","18714514770","/0-7 .8)1 252","28281769581","0926646a9319","77964670522","83654466559","22072501130","40601762737586","33539777326","37284568 0","80798637765","87847789409","727938a48277","64991544661","348 557a593-33","74759107339","53382500710","91312097771","078)7,734","2/6 154219#725","90988(7 7592","67026787564","69712982700","66106200084","67258703605","05894443799","94777648338","12702179339","33444118981","95347424737","#a.32 09420.8","75599.766462","80*724171,428*","32004339225","89642567865","94771201978","72940326946","8,45","650a52136358","52087831424","03143150956","28 ","5700)01371a18","18271103172","71","38375765821","28546585221","39605624389","5","23412778830","87383271122","568287089/11","00878826679","27729132281","19880 07","10493140930","44503742254","4,#4(405)/2-39","19643630920","47663309427","15894979408","97349 100272","59056/924-1*706","04725815896","00923556680","60266-60,81-1-0","82632823032","3353277731#6","37829839908","93721059947","27252120228","08063097830","48381238765","75096379027","23096272901","62485109460","4,357*0(8336/23*","82410795080","/-4655","07081970940","37781914465","825-0/8914455","21189414639","7,31-37966680-","9,395 354)50(16","1468708736/8","286,01/119886","2a8617a","77290013125","93922212384","43641057460","68995259841","5860-18 84555(","47779837491","2 532 7988074","84719068057","44345565766","3a4206083038","211815524#78","787135944 a87#0","96397498697","96957613992","03910a6668)3)5","49097577548","96091583394","90913543292","9271.9413496*","64197773307","15255998443","31823734472","2461-3410525","36953566950","04148992881","88865190280","81896997686","73579629034","9817)9303/780)"] diff --git a/spec/bench/harness/csharp/CsharpBench.csproj b/spec/bench/harness/csharp/CsharpBench.csproj deleted file mode 100644 index 1f4f727ea..000000000 --- a/spec/bench/harness/csharp/CsharpBench.csproj +++ /dev/null @@ -1,12 +0,0 @@ - - - net8.0 - disable - Exe - CsharpBench - - true - true - true - - diff --git a/spec/bench/harness/csharp/Program.cs b/spec/bench/harness/csharp/Program.cs deleted file mode 100644 index 000835dc8..000000000 --- a/spec/bench/harness/csharp/Program.cs +++ /dev/null @@ -1,246 +0,0 @@ -// C# arms: handwritten source against the shared core over P/Invoke. -// -// .NET has the cheapest boundary of the managed runtimes measured here. `[SuppressGCTransition]` -// tells the runtime the callee is short and never blocks, so the call skips the transition to -// preemptive GC mode and becomes little more than an indirect jump. The string still has to -// reach the core as UTF-8 bytes, which is a `stackalloc` and an encode — measured as part of -// the `ffi` arm, because a real binding pays it too. - -using System; -using System.Diagnostics; -using System.IO; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; -using System.Text; -using System.Text.Json; -using System.Text.RegularExpressions; - -internal static class Program -{ - // The code points JavaScript's trim() strips. .NET's Trim() is a different set, and C# - // expands a unicode escape before lexing, so the set is built from numbers, not escapes. - private static readonly string Whitespace = new string(new[] - { - (char)0x09, (char)0x0a, (char)0x0b, (char)0x0c, (char)0x0d, (char)0x20, (char)0xa0, - (char)0x1680, (char)0x2000, (char)0x2001, (char)0x2002, (char)0x2003, (char)0x2004, - (char)0x2005, (char)0x2006, (char)0x2007, (char)0x2008, (char)0x2009, (char)0x200a, - (char)0x2028, (char)0x2029, (char)0x202f, (char)0x205f, (char)0x3000, (char)0xfeff, - }); - - private static readonly Regex Shape = new Regex( - "^[0-9]{3}[" + Whitespace + "./-]*[0-9]{3}[" + Whitespace + "./-]*[0-9]{3}[" - + Whitespace + "./-]*[0-9]{2}$", - RegexOptions.Compiled); - - private static readonly Regex NonDigits = new Regex("[^0-9]", RegexOptions.Compiled); - - private static int CheckDigit(string basis) - { - var sum = 0; - var weight = basis.Length + 1; - - for (var index = 0; index < basis.Length; index++) - { - sum += (basis[index] - '0') * weight; - weight--; - } - - var digit = 11 - (sum % 11); - - return digit >= 10 ? 0 : digit; - } - - private static string TrimJs(string value) - { - var start = 0; - var end = value.Length; - - while (start < end && Whitespace.IndexOf(value[start]) >= 0) - { - start++; - } - - while (end > start && Whitespace.IndexOf(value[end - 1]) >= 0) - { - end--; - } - - return value.Substring(start, end - start); - } - - private static bool HandwrittenIsValid(string cpf) - { - if (cpf == null) - { - return false; - } - - if (!Shape.IsMatch(TrimJs(cpf))) - { - return false; - } - - var digits = NonDigits.Replace(cpf, string.Empty); - var first = digits[0]; - var repeated = true; - - for (var index = 1; index < digits.Length; index++) - { - if (digits[index] != first) - { - repeated = false; - - break; - } - } - - if (repeated) - { - return false; - } - - return digits[9] - '0' == CheckDigit(digits.Substring(0, 9)) - && digits[10] - '0' == CheckDigit(digits.Substring(0, 10)); - } - - // --- the shared core ------------------------------------------------------------------- - - private const string Core = "brutils_bench_core"; - - [DllImport(Core, EntryPoint = "cpf_is_valid")] - [SuppressGCTransition] - private static extern unsafe int CpfIsValidFast(byte* ptr, nuint len); - - [DllImport(Core, EntryPoint = "cpf_is_valid")] - private static extern unsafe int CpfIsValidPlain(byte* ptr, nuint len); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static unsafe bool FfiIsValid(string value) - { - Span buffer = stackalloc byte[128]; - var written = Encoding.UTF8.GetBytes(value.AsSpan(), buffer); - - fixed (byte* ptr = buffer) - { - return CpfIsValidFast(ptr, (nuint)written) == 1; - } - } - - private static int RunHandwritten(string[] corpus) - { - var valid = 0; - - foreach (var value in corpus) - { - if (HandwrittenIsValid(value)) - { - valid++; - } - } - - return valid; - } - - private static int RunFfi(string[] corpus) - { - var valid = 0; - - foreach (var value in corpus) - { - if (FfiIsValid(value)) - { - valid++; - } - } - - return valid; - } - - /// Just the boundary: the same bytes every time, no marshalling at all. - private static unsafe int RunFfiCallOnly(string[] corpus) - { - Span buffer = stackalloc byte[16]; - var written = Encoding.UTF8.GetBytes("12345678909".AsSpan(), buffer); - var valid = 0; - - fixed (byte* ptr = buffer) - { - for (var index = 0; index < corpus.Length; index++) - { - if (CpfIsValidFast(ptr, (nuint)written) == 1) - { - valid++; - } - } - } - - return valid; - } - - /// The same boundary with the GC transition, to show what suppressing it is worth. - private static unsafe int RunFfiPlainCallOnly(string[] corpus) - { - Span buffer = stackalloc byte[16]; - var written = Encoding.UTF8.GetBytes("12345678909".AsSpan(), buffer); - var valid = 0; - - fixed (byte* ptr = buffer) - { - for (var index = 0; index < corpus.Length; index++) - { - if (CpfIsValidPlain(ptr, (nuint)written) == 1) - { - valid++; - } - } - } - - return valid; - } - - private static void Measure(string arm, string[] corpus, Func run) - { - for (var warm = 0; warm < 50; warm++) - { - run(corpus); - } - - var best = double.PositiveInfinity; - var valid = 0; - - for (var rep = 0; rep < 15; rep++) - { - var started = Stopwatch.GetTimestamp(); - - valid = run(corpus); - - var elapsed = (Stopwatch.GetTimestamp() - started) * (1e9 / Stopwatch.Frequency); - var perOp = elapsed / corpus.Length; - - if (perOp < best) - { - best = perOp; - } - } - - Console.WriteLine( - $"{{\"lang\":\"csharp\",\"arm\":\"{arm}\",\"nsPerOp\":{best.ToString("F1", System.Globalization.CultureInfo.InvariantCulture)},\"valid\":{valid}}}"); - } - - public static int Main(string[] args) - { - NativeLibrary.SetDllImportResolver( - typeof(Program).Assembly, - (name, assembly, path) => - name == Core ? NativeLibrary.Load(args[1]) : IntPtr.Zero); - - var corpus = JsonSerializer.Deserialize(File.ReadAllText(args[0])); - - Measure("handwritten", corpus, RunHandwritten); - Measure("ffi", corpus, RunFfi); - Measure("ffi-callonly", corpus, RunFfiCallOnly); - Measure("ffi-plain-callonly", corpus, RunFfiPlainCallOnly); - - return 0; - } -} diff --git a/spec/bench/harness/go/go.mod b/spec/bench/harness/go/go.mod deleted file mode 100644 index fdc13600f..000000000 --- a/spec/bench/harness/go/go.mod +++ /dev/null @@ -1,5 +0,0 @@ -module brutilsbench - -go 1.24 - -require github.com/tetratelabs/wazero v1.9.0 diff --git a/spec/bench/harness/go/go.sum b/spec/bench/harness/go/go.sum deleted file mode 100644 index b0ddcacb3..000000000 --- a/spec/bench/harness/go/go.sum +++ /dev/null @@ -1,2 +0,0 @@ -github.com/tetratelabs/wazero v1.9.0 h1:IcZ56OuxrtaEz8UYNRHBrUa9bYeX9oVY93KspZZBf/I= -github.com/tetratelabs/wazero v1.9.0/go.mod h1:TSbcXCfFP0L2FGkRPxHphadXPjo1T6W+CseNNY7EkjM= diff --git a/spec/bench/harness/go/main.go b/spec/bench/harness/go/main.go deleted file mode 100644 index 9735536c7..000000000 --- a/spec/bench/harness/go/main.go +++ /dev/null @@ -1,316 +0,0 @@ -// Go arms: handwritten source, generated source, the Rust core over wazero (a pure Go wasm -// runtime) and the same core over cgo. -package main - -/* -#cgo LDFLAGS: -L${SRCDIR}/../../core/target/release -lbrutils_bench_core -Wl,-rpath,${SRCDIR}/../../core/target/release -#include -int cpf_is_valid(const unsigned char *ptr, size_t len); -int cpf_is_valid_batch(const unsigned char *input, size_t input_len, unsigned char *output, size_t count); -*/ -import "C" - -import ( - "context" - "encoding/binary" - "encoding/json" - "fmt" - "math" - "os" - "path/filepath" - "regexp" - "runtime" - "strconv" - "strings" - "time" - "unsafe" - - "github.com/tetratelabs/wazero" - - generated "brutilsbench/generated/cpf" -) - -// --- arm: handwritten, the way a contributor would write it --------------------------------- - -var shape = regexp.MustCompile(`^[0-9]{3}[\s.\-/]*[0-9]{3}[\s.\-/]*[0-9]{3}[\s.\-/]*[0-9]{2}$`) -var nonDigits = regexp.MustCompile(`[^0-9]`) - -// The code points JavaScript's trim() strips; Go's strings.TrimSpace is a different set. -var jsSpace = string([]rune{0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x20, 0xa0, 0x1680, 0x2000, 0x2001, 0x2002, 0x2003, 0x2004, 0x2005, 0x2006, 0x2007, 0x2008, 0x2009, 0x200a, 0x2028, 0x2029, 0x202f, 0x205f, 0x3000, 0xfeff}) - -func checkDigit(base string) int { - sum := 0 - weight := len(base) + 1 - - for index := 0; index < len(base); index++ { - sum += int(base[index]-'0') * weight - weight-- - } - - digit := 11 - (sum % 11) - - if digit >= 10 { - return 0 - } - - return digit -} - -func handwrittenIsValid(cpf string) bool { - if !shape.MatchString(strings.Trim(cpf, jsSpace)) { - return false - } - - digits := nonDigits.ReplaceAllString(cpf, "") - - if digits == strings.Repeat(digits[:1], 11) { - return false - } - - first, _ := strconv.Atoi(digits[9:10]) - second, _ := strconv.Atoi(digits[10:11]) - - return first == checkDigit(digits[:9]) && second == checkDigit(digits[:10]) -} - -type result struct { - Lang string `json:"lang"` - Arm string `json:"arm"` - NsPerOp float64 `json:"nsPerOp"` - Valid int `json:"valid"` -} - -func measure(arm string, corpus []string, run func([]string) int) result { - reps := 7 - - if value := os.Getenv("BENCH_REPS"); value != "" { - if parsed, err := strconv.Atoi(value); err == nil { - reps = parsed - } - } - - for warm := 0; warm < 3; warm++ { - run(corpus) - } - - best := math.Inf(1) - valid := 0 - - for rep := 0; rep < reps; rep++ { - start := time.Now() - valid = run(corpus) - elapsed := float64(time.Since(start).Nanoseconds()) / float64(len(corpus)) - - if elapsed < best { - best = elapsed - } - } - - return result{Lang: "go", Arm: arm, NsPerOp: math.Round(best*10) / 10, Valid: valid} -} - -func pack(inputs []string) []byte { - packed := make([]byte, 0, 16*len(inputs)) - header := make([]byte, 4) - - for _, value := range inputs { - binary.LittleEndian.PutUint32(header, uint32(len(value))) - packed = append(packed, header...) - packed = append(packed, value...) - } - - return packed -} - -func main() { - root, _ := filepath.Abs(filepath.Join("..", "..")) - raw, err := os.ReadFile(filepath.Join(root, "corpus.json")) - - if err != nil { - panic(err) - } - - var corpus []string - - if err := json.Unmarshal(raw, &corpus); err != nil { - panic(err) - } - - results := []result{} - - results = append(results, measure("handwritten", corpus, func(inputs []string) int { - valid := 0 - - for _, value := range inputs { - if handwrittenIsValid(value) { - valid++ - } - } - - return valid - })) - - results = append(results, measure("generated", corpus, func(inputs []string) int { - valid := 0 - - for _, value := range inputs { - if generated.IsValid(value) { - valid++ - } - } - - return valid - })) - - // --- the shared core over wazero --------------------------------------------------------- - ctx := context.Background() - runtimeConfig := wazero.NewRuntimeConfigCompiler() - wasmRuntime := wazero.NewRuntimeWithConfig(ctx, runtimeConfig) - defer wasmRuntime.Close(ctx) - - wasmBytes, err := os.ReadFile(filepath.Join(root, "core/target/wasm32-unknown-unknown/release/brutils_bench_core.wasm")) - - if err != nil { - panic(err) - } - - instance, err := wasmRuntime.Instantiate(ctx, wasmBytes) - - if err != nil { - panic(err) - } - - memory := instance.Memory() - wasmIsValid := instance.ExportedFunction("cpf_is_valid") - wasmIsValidBatch := instance.ExportedFunction("cpf_is_valid_batch") - arenaAlloc := instance.ExportedFunction("arena_alloc") - - allocate := func(size uint64) uint32 { - out, err := arenaAlloc.Call(ctx, size) - - if err != nil { - panic(err) - } - - return uint32(out[0]) - } - - scratch := allocate(64) - batchInput := allocate(1 << 18) - batchOutput := allocate(uint64(len(corpus))) - - results = append(results, measure("wasm", corpus, func(inputs []string) int { - valid := 0 - - for _, value := range inputs { - memory.Write(scratch, []byte(value)) - out, err := wasmIsValid.Call(ctx, uint64(scratch), uint64(len(value))) - - if err != nil { - panic(err) - } - - if out[0] == 1 { - valid++ - } - } - - return valid - })) - - results = append(results, measure("wasm-batch", corpus, func(inputs []string) int { - packed := pack(inputs) - memory.Write(batchInput, packed) - - if _, err := wasmIsValidBatch.Call(ctx, uint64(batchInput), uint64(len(packed)), uint64(batchOutput), uint64(len(inputs))); err != nil { - panic(err) - } - - out, _ := memory.Read(batchOutput, uint32(len(inputs))) - valid := 0 - - for _, byteValue := range out { - if byteValue == 1 { - valid++ - } - } - - return valid - })) - - results = append(results, measure("wasm-callonly", corpus, func(inputs []string) int { - valid := 0 - - for range inputs { - out, _ := wasmIsValid.Call(ctx, uint64(scratch), 11) - - if out[0] == 1 { - valid++ - } - } - - return valid - })) - - // --- the shared core over cgo ------------------------------------------------------------- - results = append(results, measure("cgo", corpus, func(inputs []string) int { - valid := 0 - - for _, value := range inputs { - bytes := []byte(value) - - if len(bytes) == 0 { - continue - } - - if C.cpf_is_valid((*C.uchar)(unsafe.Pointer(&bytes[0])), C.size_t(len(bytes))) == 1 { - valid++ - } - - runtime.KeepAlive(bytes) - } - - return valid - })) - - results = append(results, measure("cgo-batch", corpus, func(inputs []string) int { - packed := pack(inputs) - output := make([]byte, len(inputs)) - - C.cpf_is_valid_batch( - (*C.uchar)(unsafe.Pointer(&packed[0])), - C.size_t(len(packed)), - (*C.uchar)(unsafe.Pointer(&output[0])), - C.size_t(len(inputs)), - ) - - valid := 0 - - for _, byteValue := range output { - if byteValue == 1 { - valid++ - } - } - - return valid - })) - - payload := []byte("12345678909") - - results = append(results, measure("cgo-callonly", corpus, func(inputs []string) int { - valid := 0 - - for range inputs { - if C.cpf_is_valid((*C.uchar)(unsafe.Pointer(&payload[0])), 11) == 1 { - valid++ - } - } - - return valid - })) - - for _, entry := range results { - line, _ := json.Marshal(entry) - fmt.Println(string(line)) - } -} diff --git a/spec/bench/harness/java/JavaBench.java b/spec/bench/harness/java/JavaBench.java deleted file mode 100644 index 35fb81bbd..000000000 --- a/spec/bench/harness/java/JavaBench.java +++ /dev/null @@ -1,158 +0,0 @@ -// Java arms: handwritten source versus generated source. A JIT compiled language is the case -// where generated code has the least excuse to be slower, and this checks that it is not. - -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.ArrayList; -import java.util.List; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -public final class JavaBench { - private JavaBench() {} - - // The code points JavaScript's trim() strips. Java's String.trim() and strip() are both - // different sets, so the class is spelled out. - private static final String WS = - "\u0009\n\u000b\u000c\r           " - + "   

   "; - - private static final Pattern SHAPE = - Pattern.compile("^[0-9]{3}[" + WS + "./-]*[0-9]{3}[" + WS + "./-]*[0-9]{3}[" + WS + "./-]*[0-9]{2}$"); - - private static final Pattern NON_DIGITS = Pattern.compile("[^0-9]"); - - private static int checkDigit(String base) { - int sum = 0; - int weight = base.length() + 1; - - for (int index = 0; index < base.length(); index++) { - sum += (base.charAt(index) - '0') * weight; - weight--; - } - - int digit = 11 - (sum % 11); - - return digit >= 10 ? 0 : digit; - } - - private static String trimJs(String value) { - int start = 0; - int end = value.length(); - - while (start < end && WS.indexOf(value.charAt(start)) >= 0) { - start++; - } - while (end > start && WS.indexOf(value.charAt(end - 1)) >= 0) { - end--; - } - - return value.substring(start, end); - } - - static boolean handwrittenIsValid(String cpf) { - if (cpf == null) { - return false; - } - - if (!SHAPE.matcher(trimJs(cpf)).matches()) { - return false; - } - - String digits = NON_DIGITS.matcher(cpf).replaceAll(""); - - if (digits.chars().distinct().count() == 1) { - return false; - } - - return digits.charAt(9) - '0' == checkDigit(digits.substring(0, 9)) - && digits.charAt(10) - '0' == checkDigit(digits.substring(0, 10)); - } - - private static List readCorpus(Path path) throws IOException { - // The corpus is a flat JSON array of strings; parsed by hand to keep the harness - // dependency free. - String raw = Files.readString(path); - List corpus = new ArrayList<>(); - int index = 0; - - while (index < raw.length()) { - if (raw.charAt(index) != '"') { - index++; - continue; - } - - index++; - StringBuilder value = new StringBuilder(); - - while (index < raw.length() && raw.charAt(index) != '"') { - char current = raw.charAt(index); - - if (current == '\\') { - index++; - char escape = raw.charAt(index); - - switch (escape) { - case 'u' -> { - value.append((char) Integer.parseInt(raw.substring(index + 1, index + 5), 16)); - index += 4; - } - case 'n' -> value.append('\n'); - case 'r' -> value.append('\r'); - case 't' -> value.append('\t'); - default -> value.append(escape); - } - } else { - value.append(current); - } - - index++; - } - - index++; - corpus.add(value.toString()); - } - - return corpus; - } - - private static void measure(String arm, List corpus, java.util.function.Predicate check) { - for (int warm = 0; warm < 20; warm++) { - run(corpus, check); - } - - double best = Double.POSITIVE_INFINITY; - int valid = 0; - - for (int rep = 0; rep < 15; rep++) { - long start = System.nanoTime(); - valid = run(corpus, check); - double perOp = (System.nanoTime() - start) / (double) corpus.size(); - - best = Math.min(best, perOp); - } - - System.out.printf( - "{\"lang\":\"java\",\"arm\":\"%s\",\"nsPerOp\":%.1f,\"valid\":%d}%n", arm, best, valid); - } - - private static int run(List corpus, java.util.function.Predicate check) { - int valid = 0; - - for (String value : corpus) { - if (check.test(value)) { - valid++; - } - } - - return valid; - } - - public static void main(String[] args) throws IOException { - List corpus = readCorpus(Path.of(args[0])); - - measure("handwritten", corpus, JavaBench::handwrittenIsValid); - measure("generated", corpus, Cpf::isValid); - } -} diff --git a/spec/bench/harness/java/JavaNativeBench.java b/spec/bench/harness/java/JavaNativeBench.java deleted file mode 100644 index 46f126515..000000000 --- a/spec/bench/harness/java/JavaNativeBench.java +++ /dev/null @@ -1,205 +0,0 @@ -// The Java arm the first pass missed: the shared core over the Foreign Function & Memory API. -// -// Panama is the cheapest boundary the JVM has, but only if it is written the way a real binding -// writes it. Two things matter and both are easy to get wrong: -// -// * the `MethodHandle` has to be `static final`, or the JIT cannot fold the downcall stub into -// the caller and every call goes through a generic invoker; -// * `Linker.Option.isTrivial()` (renamed `critical` in JDK 22) tells the runtime the callee -// returns quickly and never calls back, which lets it skip the thread state transition. -// -// What Panama cannot skip on JDK 21 is marshalling: a trivial downcall may not touch the heap, -// so the string is encoded and copied off-heap before the call. That copy is measured as part -// of the `ffm` arm, because a real binding cannot avoid it either. - -import java.io.IOException; -import java.lang.foreign.Arena; -import java.lang.foreign.FunctionDescriptor; -import java.lang.foreign.Linker; -import java.lang.foreign.MemorySegment; -import java.lang.foreign.SymbolLookup; -import java.lang.foreign.ValueLayout; -import java.lang.invoke.MethodHandle; -import java.nio.charset.StandardCharsets; -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.ArrayList; -import java.util.List; - -public final class JavaNativeBench { - private JavaNativeBench() {} - - // A global arena: its segments need no liveness check, which a shared one would pay per call. - private static final Arena ARENA = Arena.global(); - private static final MemorySegment SCRATCH = ARENA.allocate(256); - private static final FunctionDescriptor DESCRIPTOR = - FunctionDescriptor.of(ValueLayout.JAVA_INT, ValueLayout.ADDRESS, ValueLayout.JAVA_LONG); - private static final SymbolLookup LOOKUP = - SymbolLookup.libraryLookup(Path.of(System.getProperty("core.library")), ARENA); - private static final MemorySegment SYMBOL = LOOKUP.find("cpf_is_valid").orElseThrow(); - - /** The trivial downcall option, absent on a JDK that does not have it yet. */ - private static final Linker.Option TRIVIAL = trivialOption(); - - private static final MethodHandle CPF_IS_VALID = TRIVIAL == null - ? Linker.nativeLinker().downcallHandle(SYMBOL, DESCRIPTOR) - : Linker.nativeLinker().downcallHandle(SYMBOL, DESCRIPTOR, TRIVIAL); - - private static final MethodHandle CPF_IS_VALID_PLAIN = - Linker.nativeLinker().downcallHandle(SYMBOL, DESCRIPTOR); - - private static Linker.Option trivialOption() { - for (var method : Linker.Option.class.getMethods()) { - if (method.getName().equals("isTrivial") && method.getParameterCount() == 0) { - try { - return (Linker.Option) method.invoke(null); - } catch (ReflectiveOperationException ignored) { - return null; - } - } - } - - return null; - } - - private static boolean ffmIsValid(String value) throws Throwable { - byte[] encoded = value.getBytes(StandardCharsets.UTF_8); - - MemorySegment.copy(encoded, 0, SCRATCH, ValueLayout.JAVA_BYTE, 0, encoded.length); - - return (int) CPF_IS_VALID.invokeExact(SCRATCH, (long) encoded.length) == 1; - } - - private static int runFfm(List corpus) throws Throwable { - int valid = 0; - - for (String value : corpus) { - if (ffmIsValid(value)) { - valid++; - } - } - - return valid; - } - - /** Just the boundary: the same pointer and length every time, no marshalling at all. */ - private static int runFfmCallOnly(List corpus) throws Throwable { - writePayload(); - - int valid = 0; - - for (int index = 0; index < corpus.size(); index++) { - if ((int) CPF_IS_VALID.invokeExact(SCRATCH, 11L) == 1) { - valid++; - } - } - - return valid; - } - - /** The same boundary without the trivial option, to show what the option is worth. */ - private static int runFfmPlainCallOnly(List corpus) throws Throwable { - writePayload(); - - int valid = 0; - - for (int index = 0; index < corpus.size(); index++) { - if ((int) CPF_IS_VALID_PLAIN.invokeExact(SCRATCH, 11L) == 1) { - valid++; - } - } - - return valid; - } - - private static void writePayload() { - byte[] payload = "12345678909".getBytes(StandardCharsets.UTF_8); - - MemorySegment.copy(payload, 0, SCRATCH, ValueLayout.JAVA_BYTE, 0, payload.length); - } - - private static List readCorpus(Path path) throws IOException { - String raw = Files.readString(path); - List corpus = new ArrayList<>(); - int index = 0; - - while (index < raw.length()) { - if (raw.charAt(index) != '"') { - index++; - continue; - } - - index++; - - StringBuilder value = new StringBuilder(); - - while (index < raw.length() && raw.charAt(index) != '"') { - char current = raw.charAt(index); - - if (current == '\\') { - index++; - - char escape = raw.charAt(index); - - switch (escape) { - case 'u' -> { - value.append((char) Integer.parseInt(raw.substring(index + 1, index + 5), 16)); - index += 4; - } - case 'n' -> value.append('\n'); - case 'r' -> value.append('\r'); - case 't' -> value.append('\t'); - default -> value.append(escape); - } - } else { - value.append(current); - } - - index++; - } - - index++; - corpus.add(value.toString()); - } - - return corpus; - } - - private interface Run { - int over(List corpus) throws Throwable; - } - - private static void measure(String arm, List corpus, Run run) throws Throwable { - for (int warm = 0; warm < 50; warm++) { - run.over(corpus); - } - - double best = Double.POSITIVE_INFINITY; - int valid = 0; - - for (int rep = 0; rep < 15; rep++) { - long start = System.nanoTime(); - - valid = run.over(corpus); - - double perOp = (System.nanoTime() - start) / (double) corpus.size(); - - best = Math.min(best, perOp); - } - - System.out.printf( - "{\"lang\":\"java\",\"arm\":\"%s\",\"nsPerOp\":%.1f,\"valid\":%d}%n", arm, best, valid); - } - - public static void main(String[] args) throws Throwable { - List corpus = readCorpus(Path.of(args[0])); - - if (TRIVIAL == null) { - System.err.println("note: no trivial downcall option on this JDK"); - } - - measure("ffm", corpus, JavaNativeBench::runFfm); - measure("ffm-callonly", corpus, JavaNativeBench::runFfmCallOnly); - measure("ffm-plain-callonly", corpus, JavaNativeBench::runFfmPlainCallOnly); - } -} diff --git a/spec/bench/harness/node-bench.ts b/spec/bench/harness/node-bench.ts deleted file mode 100644 index 9307e6193..000000000 --- a/spec/bench/harness/node-bench.ts +++ /dev/null @@ -1,144 +0,0 @@ -/** - * Node arms: handwritten source, generated source, and the shared Rust core over WebAssembly. - * - * Every arm validates the same 1000 inputs and reports the best nanoseconds per call over - * several repetitions, plus the number of valid inputs it found, so a wrong arm cannot win by - * doing less work. - */ -import { readFileSync } from "node:fs"; -import { resolve } from "node:path"; - -type Validator = (value: string) => boolean; - -type WasmExports = { - memory: WebAssembly.Memory; - cpf_is_valid: (ptr: number, len: number) => number; - cpf_is_valid_batch: (input: number, inputLen: number, output: number, count: number) => number; - arena_alloc: (len: number) => number; - arena_reset: () => void; -}; - -const benchDir = resolve(import.meta.dirname, ".."); -const corpus = JSON.parse(readFileSync(resolve(benchDir, "corpus.json"), "utf8")) as string[]; -const REPS = Number(process.env["BENCH_REPS"] ?? 7); -const SCRATCH_SIZE = 64; - -/** - * Times one arm over the whole corpus. - * - * @param {string} arm - The arm name. - * @param {Function} run - Validates every input and returns how many were valid. - * @returns {object} The measurement, ready to print. - */ -const measure = ( - arm: string, - run: (inputs: string[]) => number, -): { lang: string; arm: string; nsPerOp: number; valid: number } => { - for (let warm = 0; warm < 3; warm++) run(corpus); - - let best = Number.POSITIVE_INFINITY; - let valid = 0; - - for (let rep = 0; rep < REPS; rep++) { - const start = process.hrtime.bigint(); - - valid = run(corpus); - - const elapsed = Number(process.hrtime.bigint() - start); - - best = Math.min(best, elapsed / corpus.length); - } - - return { lang: "node", arm, nsPerOp: Number(best.toFixed(1)), valid }; -}; - -/** - * Wraps a validator into an arm that counts how many inputs it accepts. - * - * @param {Function} isValid - The validator under test. - * @returns {Function} The arm. - */ -const countWith = - (isValid: Validator) => - (inputs: string[]): number => { - let valid = 0; - - for (const input of inputs) if (isValid(input)) valid++; - - return valid; - }; - -const shipped = (await import(resolve(benchDir, ".build/shipped.mjs"))) as { - isValidCpf: Validator; -}; -const generated = (await import( - resolve(benchDir, ".spec-masked-strict/generated/typescript/is-valid-cpf/is-valid-cpf.ts") -)) as { isValidCpf: Validator }; - -const wasmBytes = readFileSync( - resolve(benchDir, "core/target/wasm32-unknown-unknown/release/brutils_bench_core.wasm"), -); -const { instance } = await WebAssembly.instantiate(wasmBytes, {}); -const wasm = instance.exports as unknown as WasmExports; -const encoder = new TextEncoder(); - -// One scratch buffer, reused: encoding into a fresh array per call would measure the allocator. -wasm.arena_reset(); - -const scratchPtr = wasm.arena_alloc(SCRATCH_SIZE); - -const runWasm = (inputs: string[]): number => { - const view = new Uint8Array(wasm.memory.buffer); - let valid = 0; - - for (const input of inputs) { - const { written } = encoder.encodeInto( - input, - view.subarray(scratchPtr, scratchPtr + SCRATCH_SIZE), - ); - - if (wasm.cpf_is_valid(scratchPtr, written) === 1) valid++; - } - - return valid; -}; - -wasm.arena_reset(); - -const batchInputPtr = wasm.arena_alloc(1 << 18); -const batchOutputPtr = wasm.arena_alloc(corpus.length); - -const runWasmBatch = (inputs: string[]): number => { - const view = new Uint8Array(wasm.memory.buffer); - const lengths = new DataView(wasm.memory.buffer); - let offset = batchInputPtr; - - for (const input of inputs) { - const { written } = encoder.encodeInto( - input, - view.subarray(offset + 4, offset + 4 + SCRATCH_SIZE), - ); - - lengths.setUint32(offset, written, true); - offset += 4 + written; - } - - wasm.cpf_is_valid_batch(batchInputPtr, offset - batchInputPtr, batchOutputPtr, inputs.length); - - let valid = 0; - - for (let index = 0; index < inputs.length; index++) { - if (view[batchOutputPtr + index] === 1) valid++; - } - - return valid; -}; - -const results = [ - measure("handwritten", countWith(shipped.isValidCpf)), - measure("generated", countWith(generated.isValidCpf)), - measure("wasm", runWasm), - measure("wasm-batch", runWasmBatch), -]; - -for (const result of results) console.log(JSON.stringify(result)); diff --git a/spec/bench/harness/python_bench.py b/spec/bench/harness/python_bench.py deleted file mode 100644 index 37b5e32cf..000000000 --- a/spec/bench/harness/python_bench.py +++ /dev/null @@ -1,275 +0,0 @@ -"""Python arms: handwritten source, generated source, the Rust core over wasm, and over ctypes. - -Every arm validates the same 1000 inputs and reports the best nanoseconds per call over several -repetitions, plus how many it found valid, so an arm cannot win by doing less work. -""" - -import ctypes -import json -import os -import re -import struct -import sys -import time -from pathlib import Path - -BENCH = Path(__file__).resolve().parent.parent -CORPUS = json.loads((BENCH / "corpus.json").read_text()) -REPS = int(os.environ.get("BENCH_REPS", "7")) - -sys.path.insert(0, str(BENCH / ".spec-masked-strict/generated/python")) - -# --- arm: handwritten, the way a contributor would write it --------------------------------- - -SHAPE = re.compile(r"^\d{3}[\s.\-/]*\d{3}[\s.\-/]*\d{3}[\s.\-/]*\d{2}$", re.ASCII) -NON_DIGITS = re.compile(r"\D", re.ASCII) - - -def _check_digit(base): - total = sum(int(digit) * (len(base) + 1 - index) for index, digit in enumerate(base)) - digit = 11 - (total % 11) - - return 0 if digit >= 10 else digit - - -def handwritten_is_valid(cpf): - if not isinstance(cpf, str): - return False - - if not SHAPE.match(cpf.strip()): - return False - - digits = NON_DIGITS.sub("", cpf) - - if digits == digits[0] * 11: - return False - - return int(digits[9]) == _check_digit(digits[:9]) and int(digits[10]) == _check_digit(digits[:10]) - - -# --- arm: the generated source --------------------------------------------------------------- - -from brutils.cpf import is_valid as generated_is_valid # noqa: E402 - -# --- arm: what the emitter COULD generate for Python ----------------------------------------- -# -# Same spec, same semantics, but the charsets are rendered as an explicit regex character class -# instead of a per code point loop, so the work happens in CPython's C regex engine. The class is -# spelled out code point by code point: `\s` would not mean the same set. - -WS = "\t\n\x0b\x0c\r \xa0  - 

   " -WS_CHARS = "\t\n\x0b\x0c\r \xa0            

   " -SEP = f"[{WS}.\\-/]" -OPT_SHAPE = re.compile(f"^[0-9]{{3}}{SEP}*[0-9]{{3}}{SEP}*[0-9]{{3}}{SEP}*[0-9]{{2}}$") -OPT_NON_DIGITS = re.compile("[^0-9]") - - -def generated_opt_is_valid(cpf): - if not isinstance(cpf, str): - return False - - if not OPT_SHAPE.match(cpf.strip(WS_CHARS)): - return False - - digits = OPT_NON_DIGITS.sub("", cpf) - - if digits == digits[0] * 11: - return False - - return int(digits[9]) == _check_digit(digits[:9]) and int(digits[10]) == _check_digit(digits[:10]) - - -# --- arm: one anchored regex with capture groups --------------------------------------------- -# -# The trim, the shape check and the digit extraction collapse into a single match: the leading -# and trailing whitespace become `[WS]*` and the four digit runs are captured instead of being -# filtered out of the string afterwards. - -WS_CLASS = f"[{WS}]" -OPT2_SHAPE = re.compile( - f"^{WS_CLASS}*([0-9]{{3}}){SEP}*([0-9]{{3}}){SEP}*([0-9]{{3}}){SEP}*([0-9]{{2}}){WS_CLASS}*$" -) - - -def generated_opt2_is_valid(cpf): - if not isinstance(cpf, str): - return False - - match = OPT2_SHAPE.match(cpf) - - if match is None: - return False - - digits = "".join(match.groups()) - - if digits == digits[0] * 11: - return False - - return int(digits[9]) == _check_digit(digits[:9]) and int(digits[10]) == _check_digit(digits[:10]) - -# --- arms: the shared Rust core -------------------------------------------------------------- - -import wasmtime # noqa: E402 - -WASM_PATH = BENCH / "core/target/wasm32-unknown-unknown/release/brutils_bench_core.wasm" -engine = wasmtime.Engine() -module = wasmtime.Module.from_file(engine, str(WASM_PATH)) -store = wasmtime.Store(engine) -instance = wasmtime.Instance(store, module, []) -exports = instance.exports(store) -memory = exports["memory"] -wasm_is_valid = exports["cpf_is_valid"] -wasm_is_valid_batch = exports["cpf_is_valid_batch"] -arena_alloc = exports["arena_alloc"] -arena_reset = exports["arena_reset"] - -arena_reset(store) -scratch = arena_alloc(store, 64) -batch_input = arena_alloc(store, 1 << 18) -batch_output = arena_alloc(store, len(CORPUS)) - -LIB_PATH = BENCH / "core/target/release/libbrutils_bench_core.so" -lib = ctypes.CDLL(str(LIB_PATH)) -lib.cpf_is_valid.argtypes = [ctypes.c_char_p, ctypes.c_size_t] -lib.cpf_is_valid.restype = ctypes.c_int -lib.cpf_is_valid_batch.argtypes = [ctypes.c_char_p, ctypes.c_size_t, ctypes.c_char_p, ctypes.c_size_t] -lib.cpf_is_valid_batch.restype = ctypes.c_int - - -def run_wasm(inputs): - valid = 0 - - for value in inputs: - encoded = value.encode("utf-8") - memory.write(store, encoded, scratch) - - if wasm_is_valid(store, scratch, len(encoded)) == 1: - valid += 1 - - return valid - - -# The same arm, written the way a binding generator would: the linear memory is poked through -# its raw pointer instead of wasmtime-py's bounds checked `Memory.write`. -MEM_PTR = ctypes.cast(memory.data_ptr(store), ctypes.POINTER(ctypes.c_char)) - - -def run_wasm_fast(inputs): - valid = 0 - - for value in inputs: - encoded = value.encode("utf-8") - length = len(encoded) - ctypes.memmove(ctypes.byref(MEM_PTR.contents, scratch), encoded, length) - - if wasm_is_valid(store, scratch, length) == 1: - valid += 1 - - return valid - - -def run_wasm_callonly(inputs): - """Just the boundary: the same pointer and length every time, no marshalling at all.""" - valid = 0 - - for _ in inputs: - if wasm_is_valid(store, scratch, 11) == 1: - valid += 1 - - return valid - - -def run_ffi_callonly(inputs): - """Just the boundary, over ctypes.""" - payload = b"12345678909" - valid = 0 - - for _ in inputs: - if lib.cpf_is_valid(payload, 11) == 1: - valid += 1 - - return valid - - -def run_wasm_batch(inputs): - packed = bytearray() - - for value in inputs: - encoded = value.encode("utf-8") - packed += struct.pack("= 10 ? 0 : digit -end - -def handwritten_valid?(cpf) - return false unless cpf.is_a?(String) - return false unless SHAPE.match?(cpf.strip) - - digits = cpf.gsub(NON_DIGITS, '') - return false if digits == digits[0] * 11 - - digits[9].to_i == check_digit(digits[0...9]) && digits[10].to_i == check_digit(digits[0...10]) -end - - -# --- arm: what the emitter COULD generate for Ruby ------------------------------------------- -# -# Same spec, same semantics, but the charsets are rendered as an explicit regex character class -# instead of a per code point loop, so the work happens in Onigmo rather than in Ruby. The class -# is spelled out code point by code point: `\\s` is a different set, and `^`/`$` would be line -# anchors, so `\\A`/`\\z` are used. - -WS_CODEPOINTS = [0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x20, 0xa0, 0x1680, 0x2000, 0x2001, 0x2002, 0x2003, - 0x2004, 0x2005, 0x2006, 0x2007, 0x2008, 0x2009, 0x200a, 0x2028, 0x2029, 0x202f, - 0x205f, 0x3000, 0xfeff].freeze -WS_STRING = WS_CODEPOINTS.pack('U*') -SEP_CLASS = "[#{WS_CODEPOINTS.map { |code| format('\\u{%04x}', code) }.join}\\.\\-\\/]" -OPT_SHAPE = Regexp.new("\\A[0-9]{3}#{SEP_CLASS}*[0-9]{3}#{SEP_CLASS}*[0-9]{3}#{SEP_CLASS}*[0-9]{2}\\z") -OPT_NON_DIGITS = /[^0-9]/.freeze - -def generated_opt_valid?(cpf) - return false unless cpf.is_a?(String) - return false unless OPT_SHAPE.match?(cpf.gsub(/\A[#{WS_STRING}]+|[#{WS_STRING}]+\z/, '')) - - digits = cpf.gsub(OPT_NON_DIGITS, '') - return false if digits == digits[0] * 11 - - digits[9].to_i == check_digit(digits[0...9]) && digits[10].to_i == check_digit(digits[0...10]) -end - - -# --- arm: one anchored regex with capture groups --------------------------------------------- -# -# The trim, the shape check and the digit extraction collapse into a single match: the leading -# and trailing whitespace become `[WS]*`, and the four digit runs are captured instead of being -# filtered out of the string afterwards. No intermediate string is allocated. - -WS_CLASS = "[#{WS_CODEPOINTS.map { |code| format('\\u{%04x}', code) }.join}]" -OPT2_SHAPE = Regexp.new( - "\\A#{WS_CLASS}*([0-9]{3})#{SEP_CLASS}*([0-9]{3})#{SEP_CLASS}*([0-9]{3})#{SEP_CLASS}*([0-9]{2})#{WS_CLASS}*\\z" -) - -def generated_opt2_valid?(cpf) - return false unless cpf.is_a?(String) - - match = OPT2_SHAPE.match(cpf) - return false if match.nil? - - digits = "#{match[1]}#{match[2]}#{match[3]}#{match[4]}" - return false if digits == digits[0] * 11 - - digits[9].to_i == check_digit(digits[0...9]) && digits[10].to_i == check_digit(digits[0...10]) -end - -# --- the shared Rust core over wasm ---------------------------------------------------------- - -engine = Wasmtime::Engine.new -mod = Wasmtime::Module.from_file(engine, File.join(BENCH, 'core/target/wasm32-unknown-unknown/release/brutils_bench_core.wasm')) -store = Wasmtime::Store.new(engine) -instance = Wasmtime::Instance.new(store, mod) -memory = instance.export('memory').to_memory -wasm_is_valid = instance.export('cpf_is_valid').to_func -wasm_is_valid_batch = instance.export('cpf_is_valid_batch').to_func -arena_alloc = instance.export('arena_alloc').to_func -instance.export('arena_reset').to_func.call - -scratch = arena_alloc.call(64) -batch_input = arena_alloc.call(1 << 18) -batch_output = arena_alloc.call(CORPUS.length) - -# --- the same core over Fiddle (plain C ABI) -------------------------------------------------- - -LIB = Fiddle.dlopen(File.join(BENCH, 'core/target/release/libbrutils_bench_core.so')) -FFI_IS_VALID = Fiddle::Function.new(LIB['cpf_is_valid'], [Fiddle::TYPE_VOIDP, Fiddle::TYPE_SIZE_T], Fiddle::TYPE_INT) -FFI_IS_VALID_BATCH = Fiddle::Function.new( - LIB['cpf_is_valid_batch'], - [Fiddle::TYPE_VOIDP, Fiddle::TYPE_SIZE_T, Fiddle::TYPE_VOIDP, Fiddle::TYPE_SIZE_T], - Fiddle::TYPE_INT -) - -def pack(inputs) - packed = +'' - inputs.each do |value| - bytes = value.dup.force_encoding(Encoding::BINARY) - packed << [bytes.bytesize].pack('V') << bytes - end - packed -end - -ARMS = { - 'handwritten' => ->(inputs) { inputs.count { |value| handwritten_valid?(value) } }, - 'generated' => ->(inputs) { inputs.count { |value| BrazilianUtils::CPFUtils.valid?(value) } }, - 'generated-opt' => ->(inputs) { inputs.count { |value| generated_opt_valid?(value) } }, - 'generated-opt2' => ->(inputs) { inputs.count { |value| generated_opt2_valid?(value) } }, - 'wasm' => lambda { |inputs| - valid = 0 - inputs.each do |value| - bytes = value.dup.force_encoding(Encoding::BINARY) - memory.write(scratch, bytes) - valid += 1 if wasm_is_valid.call(scratch, bytes.bytesize) == 1 - end - valid - }, - 'wasm-batch' => lambda { |inputs| - packed = pack(inputs) - memory.write(batch_input, packed) - wasm_is_valid_batch.call(batch_input, packed.bytesize, batch_output, inputs.length) - memory.read(batch_output, inputs.length).bytes.count(1) - }, - 'ffi' => lambda { |inputs| - valid = 0 - inputs.each do |value| - bytes = value.dup.force_encoding(Encoding::BINARY) - valid += 1 if FFI_IS_VALID.call(bytes, bytes.bytesize) == 1 - end - valid - }, - 'ffi-batch' => lambda { |inputs| - packed = pack(inputs) - output = Fiddle::Pointer.malloc(inputs.length) - FFI_IS_VALID_BATCH.call(packed, packed.bytesize, output, inputs.length) - output.to_str(inputs.length).bytes.count(1) - }, - 'wasm-callonly' => lambda { |inputs| - valid = 0 - inputs.each { valid += 1 if wasm_is_valid.call(scratch, 11) == 1 } - valid - }, - 'ffi-callonly' => lambda { |inputs| - payload = '12345678909' - valid = 0 - inputs.each { valid += 1 if FFI_IS_VALID.call(payload, 11) == 1 } - valid - } -}.freeze - -ARMS.each do |name, run| - 2.times { run.call(CORPUS) } - - best = Float::INFINITY - valid = 0 - - REPS.times do - start = Process.clock_gettime(Process::CLOCK_MONOTONIC, :nanosecond) - valid = run.call(CORPUS) - elapsed = Process.clock_gettime(Process::CLOCK_MONOTONIC, :nanosecond) - start - best = [best, elapsed.to_f / CORPUS.length].min - end - - puts JSON.generate('lang' => 'ruby', 'arm' => name, 'nsPerOp' => best.round(1), 'valid' => valid) - $stdout.flush -end diff --git a/spec/bench/harness/ruby_native.rb b/spec/bench/harness/ruby_native.rb deleted file mode 100644 index 03b541c94..000000000 --- a/spec/bench/harness/ruby_native.rb +++ /dev/null @@ -1,65 +0,0 @@ -# frozen_string_literal: true - -# The Ruby arm the first pass missed: the shared core as a C extension. -# -# `fiddle` and the `ffi` gem are what a script reaches for; a C extension is what a gem ships -# when it cares. Both are measured against the same corpus and the same core. - -require 'json' -require 'benchmark' - -BENCH = File.expand_path('..', __dir__) -CORPUS = JSON.parse(File.read(File.join(BENCH, 'corpus.json'))) -REPS = Integer(ENV.fetch('BENCH_REPS', '7')) - -$LOAD_PATH.unshift(File.join(BENCH, '.build/native/ruby')) -require 'cpf_native' - -def run_cext(inputs) - valid = 0 - inputs.each { |value| valid += 1 if CpfNative.is_valid(value) } - valid -end - -def run_cext_callonly(inputs) - payload = '12345678909' - valid = 0 - inputs.each { valid += 1 if CpfNative.is_valid(payload) } - valid -end - -def run_cext_batch(inputs) - packed = +'' - inputs.each do |value| - encoded = value.dup.force_encoding(Encoding::BINARY) - packed << [encoded.bytesize].pack('V') << encoded - end - - results = CpfNative.is_valid_batch(packed, inputs.length) - results.bytes.count(1) -end - -def measure(arm, &block) - 2.times { block.call(CORPUS) } - - best = Float::INFINITY - valid = 0 - - REPS.times do - started = Process.clock_gettime(Process::CLOCK_MONOTONIC, :nanosecond) - valid = block.call(CORPUS) - elapsed = Process.clock_gettime(Process::CLOCK_MONOTONIC, :nanosecond) - started - best = [best, elapsed.to_f / CORPUS.length].min - end - - { lang: 'ruby', arm: arm, nsPerOp: best.round(1), valid: valid } -end - -[ - ['cext', method(:run_cext)], - ['cext-callonly', method(:run_cext_callonly)], - ['cext-batch', method(:run_cext_batch)] -].each do |arm, runner| - puts JSON.generate(measure(arm) { |inputs| runner.call(inputs) }) - $stdout.flush -end diff --git a/spec/bench/harness/uniffi_bench.py b/spec/bench/harness/uniffi_bench.py deleted file mode 100644 index 03397005b..000000000 --- a/spec/bench/harness/uniffi_bench.py +++ /dev/null @@ -1,53 +0,0 @@ -"""The same Rust core, reached through UniFFI generated Python bindings instead of hand rolled -ctypes, so the cost of an off the shelf binding generator is measured rather than assumed. - -Build first: - cargo build --release --manifest-path spec/bench/uniffi/Cargo.toml - cd spec/bench/uniffi && ./target/release/uniffi-bindgen generate \ - --library target/release/libbrutils_uniffi.so --language python --out-dir ../.build/uniffi-python - cp spec/bench/uniffi/target/release/libbrutils_uniffi.so spec/bench/.build/uniffi-python/ -""" - -import json -import os -import sys -import time -from pathlib import Path - -BENCH = Path(__file__).resolve().parent.parent -CORPUS = json.loads((BENCH / "corpus.json").read_text()) -REPS = int(os.environ.get("BENCH_REPS", "7")) - -sys.path.insert(0, str(BENCH / ".build/uniffi-python")) - -import brutils_uniffi # noqa: E402 - - -def measure(arm, run): - for _ in range(2): - run(CORPUS) - - best = float("inf") - valid = 0 - - for _ in range(REPS): - start = time.perf_counter_ns() - valid = run(CORPUS) - best = min(best, (time.perf_counter_ns() - start) / len(CORPUS)) - - return {"lang": "python", "arm": arm, "nsPerOp": round(best, 1), "valid": valid} - - -print( - json.dumps( - measure( - "uniffi", - lambda inputs: sum(1 for value in inputs if brutils_uniffi.cpf_is_valid(value)), - ) - ) -) -print( - json.dumps( - measure("uniffi-batch", lambda inputs: sum(brutils_uniffi.cpf_is_valid_batch(inputs))) - ) -) diff --git a/spec/bench/native/c_bench.c b/spec/bench/native/c_bench.c deleted file mode 100644 index cd40c65dd..000000000 --- a/spec/bench/native/c_bench.c +++ /dev/null @@ -1,150 +0,0 @@ -/* - * The floor: the shared core called from C, over the same shared library every binding uses. - * - * A call through the PLT costs a couple of nanoseconds, so this is as close to "just the work" - * as the benchmark gets. Every other arm pays this plus whatever its own boundary costs, which - * is what lets the table say how much of a binding's total is crossing rather than validating. - */ -#include -#include -#include -#include - -extern int cpf_is_valid(const unsigned char *ptr, size_t len); - -typedef struct { - const unsigned char *ptr; - size_t len; -} Input; - -static long now_ns(void) { - struct timespec spec; - - clock_gettime(CLOCK_MONOTONIC, &spec); - - return spec.tv_sec * 1000000000L + spec.tv_nsec; -} - -static int run(const Input *corpus, size_t count) { - int valid = 0; - - for (size_t index = 0; index < count; index++) { - valid += cpf_is_valid(corpus[index].ptr, corpus[index].len); - } - - return valid; -} - -/* - * The same loop over one cached, always valid input. Every language's "callonly" arm does - * exactly this, so subtracting this number from theirs leaves the boundary and nothing else. - */ -static int run_fixed(size_t count) { - static const unsigned char payload[] = "12345678909"; - int valid = 0; - - for (size_t index = 0; index < count; index++) { - valid += cpf_is_valid(payload, 11); - } - - return valid; -} - -int main(int argc, char **argv) { - const char *path = argc > 1 ? argv[1] : "corpus.bin"; - FILE *handle = fopen(path, "rb"); - unsigned char *raw = NULL; - long size = 0; - size_t count = 0; - size_t offset = 0; - Input *corpus = NULL; - const char *reps_env = getenv("BENCH_REPS"); - int reps = reps_env == NULL ? 7 : atoi(reps_env); - double best = 1e18; - int valid = 0; - - if (handle == NULL) { - fprintf(stderr, "cannot open %s\n", path); - - return 1; - } - - fseek(handle, 0, SEEK_END); - size = ftell(handle); - fseek(handle, 0, SEEK_SET); - raw = malloc((size_t)size); - - if (fread(raw, 1, (size_t)size, handle) != (size_t)size) { - fprintf(stderr, "short read\n"); - - return 1; - } - - fclose(handle); - - while (offset + 4 <= (size_t)size) { - unsigned int length = (unsigned int)raw[offset] | ((unsigned int)raw[offset + 1] << 8) - | ((unsigned int)raw[offset + 2] << 16) - | ((unsigned int)raw[offset + 3] << 24); - - offset += 4 + length; - count++; - } - - corpus = malloc(count * sizeof(Input)); - offset = 0; - count = 0; - - while (offset + 4 <= (size_t)size) { - unsigned int length = (unsigned int)raw[offset] | ((unsigned int)raw[offset + 1] << 8) - | ((unsigned int)raw[offset + 2] << 16) - | ((unsigned int)raw[offset + 3] << 24); - - offset += 4; - corpus[count].ptr = raw + offset; - corpus[count].len = length; - offset += length; - count++; - } - - for (int warm = 0; warm < 3; warm++) { - run(corpus, count); - } - - for (int rep = 0; rep < reps; rep++) { - long started = now_ns(); - - valid = run(corpus, count); - - double per_op = (double)(now_ns() - started) / (double)count; - - if (per_op < best) { - best = per_op; - } - } - - printf("{\"lang\":\"c\",\"arm\":\"core-direct\",\"nsPerOp\":%.1f,\"valid\":%d}\n", best, valid); - - for (int warm = 0; warm < 3; warm++) { - run_fixed(count); - } - - best = 1e18; - - for (int rep = 0; rep < reps; rep++) { - long started = now_ns(); - - valid = run_fixed(count); - - double per_op = (double)(now_ns() - started) / (double)count; - - if (per_op < best) { - best = per_op; - } - } - - printf("{\"lang\":\"c\",\"arm\":\"core-direct-callonly\",\"nsPerOp\":%.1f,\"valid\":%d}\n", - best, valid); - - return 0; -} diff --git a/spec/bench/native/python_cext.c b/spec/bench/native/python_cext.c deleted file mode 100644 index 7dbfcf007..000000000 --- a/spec/bench/native/python_cext.c +++ /dev/null @@ -1,80 +0,0 @@ -/* - * A CPython extension module over the shared core. - * - * This is the cheapest boundary CPython has: `PyUnicode_AsUTF8AndSize` hands back the string's - * own UTF-8 buffer (cached on the object, and the object itself for an ASCII string), so the - * call marshals nothing — it passes a pointer and a length straight through to the core. - * - * It is also hand-written glue, which is the point: the DX layer of each package is written by - * hand anyway, so a binding written the way that ecosystem writes bindings is fair game. - */ -#define PY_SSIZE_T_CLEAN -#include -#include - -extern int cpf_is_valid(const unsigned char *ptr, size_t len); -extern int cpf_is_valid_batch(const unsigned char *input, size_t input_len, unsigned char *output, - size_t count); - -static PyObject *cpf_native_is_valid(PyObject *self, PyObject *value) { - Py_ssize_t length = 0; - const char *utf8 = NULL; - - (void)self; - - if (!PyUnicode_Check(value)) { - Py_RETURN_FALSE; - } - - utf8 = PyUnicode_AsUTF8AndSize(value, &length); - - if (utf8 == NULL) { - PyErr_Clear(); - Py_RETURN_FALSE; - } - - if (cpf_is_valid((const unsigned char *)utf8, (size_t)length)) { - Py_RETURN_TRUE; - } - - Py_RETURN_FALSE; -} - -static PyObject *cpf_native_is_valid_batch(PyObject *self, PyObject *packed) { - Py_ssize_t count = 0; - PyObject *output = NULL; - - (void)self; - - if (!PyTuple_Check(packed) || PyTuple_GET_SIZE(packed) != 2) { - PyErr_SetString(PyExc_TypeError, "expected (bytes, count)"); - - return NULL; - } - - count = PyLong_AsSsize_t(PyTuple_GET_ITEM(packed, 1)); - output = PyBytes_FromStringAndSize(NULL, count); - - if (output == NULL) { - return NULL; - } - - cpf_is_valid_batch((const unsigned char *)PyBytes_AS_STRING(PyTuple_GET_ITEM(packed, 0)), - (size_t)PyBytes_GET_SIZE(PyTuple_GET_ITEM(packed, 0)), - (unsigned char *)PyBytes_AS_STRING(output), (size_t)count); - - return output; -} - -static PyMethodDef CpfNativeMethods[] = { - {"is_valid", cpf_native_is_valid, METH_O, "Validate one CPF."}, - {"is_valid_batch", cpf_native_is_valid_batch, METH_O, "Validate a packed batch of CPFs."}, - {NULL, NULL, 0, NULL}, -}; - -static struct PyModuleDef cpf_native_module = { - PyModuleDef_HEAD_INIT, "cpf_native", "The shared CPF core, as a CPython extension.", -1, - CpfNativeMethods, -}; - -PyMODINIT_FUNC PyInit_cpf_native(void) { return PyModule_Create(&cpf_native_module); } diff --git a/spec/bench/native/ruby_cext.c b/spec/bench/native/ruby_cext.c deleted file mode 100644 index 85ef156da..000000000 --- a/spec/bench/native/ruby_cext.c +++ /dev/null @@ -1,47 +0,0 @@ -/* - * A Ruby C extension over the shared core. - * - * `RSTRING_PTR` and `RSTRING_LEN` read the string object's own buffer, so nothing is copied: - * the call passes a pointer and a length straight through to the core. This is the boundary - * a gem ships when it cares, as opposed to `fiddle` or the `ffi` gem, which are what a script - * reaches for. - */ -#include -#include - -extern int cpf_is_valid(const unsigned char *ptr, size_t len); -extern int cpf_is_valid_batch(const unsigned char *input, size_t input_len, unsigned char *output, - size_t count); - -static VALUE cpf_native_is_valid(VALUE self, VALUE value) { - (void)self; - - if (!RB_TYPE_P(value, T_STRING)) { - return Qfalse; - } - - return cpf_is_valid((const unsigned char *)RSTRING_PTR(value), (size_t)RSTRING_LEN(value)) - ? Qtrue - : Qfalse; -} - -static VALUE cpf_native_is_valid_batch(VALUE self, VALUE packed, VALUE count) { - VALUE output = Qnil; - long total = 0; - - (void)self; - total = NUM2LONG(count); - output = rb_str_new(NULL, total); - - cpf_is_valid_batch((const unsigned char *)RSTRING_PTR(packed), (size_t)RSTRING_LEN(packed), - (unsigned char *)RSTRING_PTR(output), (size_t)total); - - return output; -} - -void Init_cpf_native(void) { - VALUE module = rb_define_module("CpfNative"); - - rb_define_module_function(module, "is_valid", cpf_native_is_valid, 1); - rb_define_module_function(module, "is_valid_batch", cpf_native_is_valid_batch, 2); -} diff --git a/spec/bench/prepare.ts b/spec/bench/prepare.ts deleted file mode 100644 index 6da8a4225..000000000 --- a/spec/bench/prepare.ts +++ /dev/null @@ -1,50 +0,0 @@ -import { execFileSync } from "node:child_process"; -/** - * Prepares the benchmark inputs. - * - * 1. Writes `spec/bench/corpus.json`: the inputs every arm, in every language, validates. - * 2. Emits the generated `isValidCpf` for each language under the SAME profile - * (`masked-strict`), so the source level arms do identical work. The published packages adopt - * different profiles, which is right for them and useless for a benchmark. - * - * Usage: `node spec/bench/prepare.ts` - */ -import { cpSync, mkdirSync, readFileSync, rmSync, writeFileSync } from "node:fs"; -import { resolve } from "node:path"; - -import { buildCorpus } from "../codegen/corpus.ts"; - -const benchDir = import.meta.dirname; -const specDir = resolve(benchDir, ".."); -const tempSpec = resolve(benchDir, ".spec-masked-strict"); - -// A corpus of realistic size: mostly valid CPFs, masked and bare, plus the rejects. -const corpus = buildCorpus(4000) - .filter((input) => input.length > 0 && input.length < 24) - .slice(0, 1000); - -writeFileSync(resolve(benchDir, "corpus.json"), `${JSON.stringify(corpus)}\n`); - -rmSync(tempSpec, { recursive: true, force: true }); -mkdirSync(tempSpec, { recursive: true }); - -for (const entry of ["codegen", "schema", "utilities", "vectors", "utilities.json"]) { - cpSync(resolve(specDir, entry), resolve(tempSpec, entry), { recursive: true }); -} - -const cpfPath = resolve(tempSpec, "utilities/is-valid-cpf.json"); -const cpf = JSON.parse(readFileSync(cpfPath, "utf8")) as { - adopted: Record; -}; - -for (const target of Object.keys(cpf.adopted)) cpf.adopted[target] = { profile: "masked-strict" }; - -writeFileSync(cpfPath, JSON.stringify(cpf, null, "\t")); - -// Only `is-valid-cpf` is benchmarked, so the other two utilities are dropped from the run. -writeFileSync(resolve(tempSpec, "utilities.json"), JSON.stringify({ utilities: ["is-valid-cpf"] })); - -execFileSync("node", [resolve(tempSpec, "codegen/emit.ts")], { stdio: "inherit" }); - -console.log(`corpus: ${corpus.length} inputs`); -console.log(`generated: ${resolve(tempSpec, "generated")}`); diff --git a/spec/bench/results.jsonl b/spec/bench/results.jsonl deleted file mode 100644 index caaecb504..000000000 --- a/spec/bench/results.jsonl +++ /dev/null @@ -1,52 +0,0 @@ -{"lang":"node","arm":"handwritten","nsPerOp":386.2,"valid":337} -{"lang":"node","arm":"generated","nsPerOp":256.5,"valid":337} -{"lang":"node","arm":"wasm","nsPerOp":224.6,"valid":337} -{"lang":"node","arm":"wasm-batch","nsPerOp":240.5,"valid":337} -{"lang": "python", "arm": "handwritten", "nsPerOp": 2460.6, "valid": 333} -{"lang": "python", "arm": "generated", "nsPerOp": 1366.0, "valid": 337} -{"lang": "python", "arm": "generated-opt", "nsPerOp": 2511.0, "valid": 337} -{"lang": "python", "arm": "generated-opt2", "nsPerOp": 2472.7, "valid": 337} -{"lang": "python", "arm": "wasm", "nsPerOp": 38039.3, "valid": 337} -{"lang": "python", "arm": "wasm-rawmem", "nsPerOp": 32422.0, "valid": 337} -{"lang": "python", "arm": "wasm-batch", "nsPerOp": 306.3, "valid": 337} -{"lang": "python", "arm": "ffi", "nsPerOp": 535.3, "valid": 337} -{"lang": "python", "arm": "ffi-batch", "nsPerOp": 239.9, "valid": 337} -{"lang": "python", "arm": "wasm-callonly", "nsPerOp": 30058.9, "valid": 0} -{"lang": "python", "arm": "ffi-callonly", "nsPerOp": 472.3, "valid": 1000} -{"lang":"ruby","arm":"handwritten","nsPerOp":3675.8,"valid":329} -{"lang":"ruby","arm":"generated","nsPerOp":2020.1,"valid":337} -{"lang":"ruby","arm":"generated-opt","nsPerOp":11607.4,"valid":337} -{"lang":"ruby","arm":"generated-opt2","nsPerOp":3975.2,"valid":337} -{"lang":"ruby","arm":"wasm","nsPerOp":729.9,"valid":337} -{"lang":"ruby","arm":"wasm-batch","nsPerOp":430.0,"valid":337} -{"lang":"ruby","arm":"ffi","nsPerOp":1662.1,"valid":337} -{"lang":"ruby","arm":"ffi-batch","nsPerOp":404.9,"valid":337} -{"lang":"ruby","arm":"wasm-callonly","nsPerOp":521.1,"valid":0} -{"lang":"ruby","arm":"ffi-callonly","nsPerOp":1518.2,"valid":1000} -{"lang":"go","arm":"handwritten","nsPerOp":446.2,"valid":334} -{"lang":"go","arm":"generated","nsPerOp":193.1,"valid":337} -{"lang":"go","arm":"wasm","nsPerOp":189.1,"valid":337} -{"lang":"go","arm":"wasm-batch","nsPerOp":104.5,"valid":337} -{"lang":"go","arm":"wasm-callonly","nsPerOp":103.8,"valid":0} -{"lang":"go","arm":"cgo","nsPerOp":119.1,"valid":337} -{"lang":"go","arm":"cgo-batch","nsPerOp":52.6,"valid":337} -{"lang":"go","arm":"cgo-callonly","nsPerOp":97.5,"valid":1000} -{"lang":"java","arm":"handwritten","nsPerOp":1365.3,"valid":337} -{"lang":"java","arm":"generated","nsPerOp":493.6,"valid":337} -{"lang": "python", "arm": "uniffi", "nsPerOp": 9064.2, "valid": 337} -{"lang": "python", "arm": "uniffi-batch", "nsPerOp": 6195.8, "valid": 337} -{"lang":"c","arm":"core-direct","nsPerOp":47.0,"valid":337} -{"lang":"c","arm":"core-direct-callonly","nsPerOp":39.5,"valid":1000} -{"lang": "python", "arm": "cext", "nsPerOp": 65.4, "valid": 337} -{"lang": "python", "arm": "cext-callonly", "nsPerOp": 66.5, "valid": 1000} -{"lang": "python", "arm": "cext-batch", "nsPerOp": 235.9, "valid": 337} -{"lang":"ruby","arm":"cext","nsPerOp":109.3,"valid":337} -{"lang":"ruby","arm":"cext-callonly","nsPerOp":104.6,"valid":1000} -{"lang":"ruby","arm":"cext-batch","nsPerOp":465.7,"valid":337} -{"lang":"java","arm":"ffm","nsPerOp":127.3,"valid":337} -{"lang":"java","arm":"ffm-callonly","nsPerOp":101.9,"valid":1000} -{"lang":"java","arm":"ffm-plain-callonly","nsPerOp":102.7,"valid":1000} -{"lang":"csharp","arm":"handwritten","nsPerOp":330.2,"valid":337} -{"lang":"csharp","arm":"ffi","nsPerOp":76.4,"valid":337} -{"lang":"csharp","arm":"ffi-callonly","nsPerOp":40.6,"valid":1000} -{"lang":"csharp","arm":"ffi-plain-callonly","nsPerOp":41.2,"valid":1000} diff --git a/spec/bench/run-all.sh b/spec/bench/run-all.sh deleted file mode 100644 index d70ab4824..000000000 --- a/spec/bench/run-all.sh +++ /dev/null @@ -1,29 +0,0 @@ -#!/usr/bin/env bash -# Rebuilds every artifact and runs every benchmark arm, writing one JSON line per measurement. -# -# Usage: bash spec/bench/run-all.sh > spec/bench/results.jsonl -set -euo pipefail - -root="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)" -bench="${root}/spec/bench" - -cargo build --quiet --release --manifest-path "${bench}/core/Cargo.toml" -cargo build --quiet --release --target wasm32-unknown-unknown --manifest-path "${bench}/core/Cargo.toml" -node "${bench}/prepare.ts" >/dev/null - -mkdir -p "${bench}/.build" -npx --yes esbuild "${root}/src/index.ts" --bundle --format=esm --platform=neutral \ - --outfile="${bench}/.build/shipped.mjs" --log-level=error - -node "${bench}/harness/node-bench.ts" -python3 "${bench}/harness/python_bench.py" -ruby "${bench}/harness/ruby_bench.rb" - -cp "${bench}/.spec-masked-strict/generated/go/cpf/cpf.go" "${bench}/harness/go/generated/cpf/cpf.go" -cp "${bench}/.spec-masked-strict/generated/go/specruntime/specruntime.go" "${bench}/harness/go/generated/specruntime/specruntime.go" -sed -i 's|brazilianutils/spec/specruntime|brutilsbench/generated/specruntime|' "${bench}/harness/go/generated/cpf/cpf.go" -(cd "${bench}/harness/go" && go run .) - -cp "${bench}/.spec-masked-strict/generated/java/Cpf.java" "${bench}/.spec-masked-strict/generated/java/SpecRuntime.java" "${bench}/harness/java/" -javac -nowarn -d "${bench}/.build/java" "${bench}"/harness/java/*.java 2>/dev/null -java -cp "${bench}/.build/java" JavaBench "${bench}/corpus.json" 2>/dev/null diff --git a/spec/bench/run-native.sh b/spec/bench/run-native.sh deleted file mode 100644 index d9b09f207..000000000 --- a/spec/bench/run-native.sh +++ /dev/null @@ -1,69 +0,0 @@ -#!/usr/bin/env bash -# The native binding arms: the shared core over the boundary each ecosystem actually ships. -# -# The first pass measured the bindings a script reaches for — ctypes, fiddle, a wasm runtime — -# and concluded the boundary costs more than the work. That is true of those mechanisms and -# false of the ones a package ships, so each ecosystem's own is measured here: -# -# c the floor, the same shared library called from C -# python a CPython extension module, not ctypes -# ruby a C extension, not fiddle or the ffi gem -# java the Foreign Function & Memory API with a trivial downcall -# csharp P/Invoke with the GC transition suppressed -# -# Each language also runs a "callonly" arm over one cached input, and C runs the same, so -# subtracting the two leaves the boundary and nothing else. -# -# Usage: bash spec/bench/run-native.sh >> spec/bench/results.jsonl -set -euo pipefail - -bench="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -core_dir="${bench}/core/target/release" - -cargo build --quiet --release --manifest-path "${bench}/core/Cargo.toml" - -mkdir -p "${bench}/.build/native/python" "${bench}/.build/native/ruby" - -python3 - "${bench}" <<'PY' -import json -import pathlib -import struct -import sys - -bench = pathlib.Path(sys.argv[1]) -corpus = json.loads((bench / "corpus.json").read_text()) -packed = bytearray() - -for value in corpus: - encoded = value.encode("utf-8") - packed += struct.pack("/dev/null -java --enable-preview -Dcore.library="${core_dir}/libbrutils_bench_core.so" \ - -cp "${bench}/.build/java" JavaNativeBench "${bench}/corpus.json" 2>/dev/null - -cd "${bench}/harness/csharp" -DOTNET_CLI_TELEMETRY_OPTOUT=1 dotnet run -c Release --verbosity quiet -- \ - "${bench}/corpus.json" "${core_dir}/libbrutils_bench_core.so" diff --git a/spec/bench/table.py b/spec/bench/table.py deleted file mode 100644 index b0ac2083a..000000000 --- a/spec/bench/table.py +++ /dev/null @@ -1,109 +0,0 @@ -"""Rewrites the results table in the investigation report from `results.jsonl`. - -Usage: python3 spec/bench/table.py -""" - -import collections -import json -from pathlib import Path - -BENCH = Path(__file__).resolve().parent -REPORT = BENCH.parent / "BINDINGS-INVESTIGATION.md" - -LABEL = { - "handwritten": "handwritten", - "generated": "**generated**", - "wasm": "wasm", - "wasm-batch": "wasm-batch", - "wasm-callonly": "wasm-callonly", - "ffi": "ffi (ctypes)", - "ffi-batch": "ffi-batch", - "uniffi": "**uniffi**", - "uniffi-batch": "uniffi-batch", - "cgo": "cgo", - "cgo-batch": "cgo-batch", - "cext": "**cext**", - "cext-batch": "cext-batch", - "ffm": "**ffm (Panama)**", - "core-direct": "**core-direct**", -} - -LAYOUT = [ - ("C", "c", ["core-direct"]), - ("Node", "node", ["handwritten", "generated", "wasm", "wasm-batch"]), - ( - "Python", - "python", - [ - "handwritten", - "generated", - "wasm", - "wasm-callonly", - "wasm-batch", - "ffi", - "ffi-batch", - "uniffi", - "uniffi-batch", - "cext", - "cext-batch", - ], - ), - ("Ruby", "ruby", ["handwritten", "generated", "wasm", "wasm-batch", "ffi", "cext"]), - ("Go", "go", ["handwritten", "generated", "wasm", "wasm-batch", "cgo", "cgo-batch"]), - ("Java", "java", ["handwritten", "generated", "ffm"]), - ("C#", "csharp", ["handwritten", "ffi"]), -] - - -def main() -> None: - rows = [json.loads(line) for line in (BENCH / "results.jsonl").read_text().splitlines() if line] - by = collections.defaultdict(dict) - - for row in rows: - by[row["lang"]][row["arm"]] = row - - lines = ["| Language | Arm | ns/op | × hand | valid |", "| --- | --- | ---: | ---: | ---: |"] - - for title, lang, arms in LAYOUT: - # C is the floor: the same core with no boundary, so there is nothing to compare it to. - base = by[lang]["handwritten"]["nsPerOp"] if "handwritten" in by[lang] else None - - for arm in arms: - row = by[lang][arm] - label = LABEL[arm] - - if lang == "ruby" and arm == "ffi": - label = "ffi (Fiddle)" - if lang == "go" and arm == "wasm": - label = "wasm (wazero)" - if lang == "csharp" and arm == "ffi": - label = "**ffi (P/Invoke)**" - - ratio = None if base is None else row["nsPerOp"] / base - emphasise = arm in ("generated", "uniffi", "cext", "ffm", "core-direct") or ( - lang == "csharp" and arm == "ffi" - ) - ns = f"**{row['nsPerOp']:.1f}**" if emphasise else f"{row['nsPerOp']:.1f}" - - if ratio is None: - rel = "—" - else: - rel = f"**{ratio:.2f}**" if emphasise else f"{ratio:.2f}" - valid = "—" if arm.endswith("callonly") else str(row["valid"]) - - if arm == "handwritten" and row["valid"] != 337: - valid = f"**{row['valid']}**" - - lines.append(f"| {title} | {label} | {ns} | {rel} | {valid} |") - - table = "\n".join(lines) - report = REPORT.read_text(encoding="utf-8") - start = report.index("| Language | Arm") - end = report.index("\n\n---", start) - - REPORT.write_text(report[:start] + table + report[end:], encoding="utf-8") - print(table) - - -if __name__ == "__main__": - main() diff --git a/spec/bench/uniffi/Cargo.lock b/spec/bench/uniffi/Cargo.lock deleted file mode 100644 index 0217ab7a5..000000000 --- a/spec/bench/uniffi/Cargo.lock +++ /dev/null @@ -1,711 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 4 - -[[package]] -name = "anstyle" -version = "1.0.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "940b3a0ca603d1eade50a4846a2afffd5ef57a9feac2c0e2ec2e14f9ead76000" - -[[package]] -name = "anyhow" -version = "1.0.104" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "330a5ed07fa54e4702c9d6c4174f74427fc0ef6e214bbd677ae50a5099946470" - -[[package]] -name = "askama" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d4744ed2eef2645831b441d8f5459689ade2ab27c854488fbab1fbe94fce1a7" -dependencies = [ - "askama_derive", - "itoa", - "percent-encoding", - "serde", - "serde_json", -] - -[[package]] -name = "askama_derive" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d661e0f57be36a5c14c48f78d09011e67e0cb618f269cca9f2fd8d15b68c46ac" -dependencies = [ - "askama_parser", - "basic-toml", - "memchr", - "proc-macro2", - "quote", - "rustc-hash", - "serde", - "serde_derive", - "syn 2.0.119", -] - -[[package]] -name = "askama_parser" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf315ce6524c857bb129ff794935cf6d42c82a6cff60526fe2a63593de4d0d4f" -dependencies = [ - "memchr", - "serde", - "serde_derive", - "winnow", -] - -[[package]] -name = "autocfg" -version = "1.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2032f911046de80f0a198e0901378627c33f59ea0ac00e363d481118bd70a53" - -[[package]] -name = "basic-toml" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba62675e8242a4c4e806d12f11d136e626e6c8361d6b829310732241652a178a" -dependencies = [ - "serde", -] - -[[package]] -name = "bitflags" -version = "2.13.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ded4057c258ba199e2d26386d3af3780957ecaee6c4ef4041c6b4b8b97c0b06" - -[[package]] -name = "brutils_uniffi" -version = "0.0.0" -dependencies = [ - "uniffi", -] - -[[package]] -name = "bytes" -version = "1.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc652a48c352aef3ea3aed32080501cf3ef6ed5da78602a020c991775b0aff04" - -[[package]] -name = "camino" -version = "1.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbbad30e4b4c14a39e3cc8aed085a12a327257c316619c93581e017bc52be591" -dependencies = [ - "serde_core", -] - -[[package]] -name = "cargo-platform" -version = "0.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e35af189006b9c0f00a064685c727031e3ed2d8020f7ba284d78cc2671bd36ea" -dependencies = [ - "serde", -] - -[[package]] -name = "cargo_metadata" -version = "0.19.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd5eb614ed4c27c5d706420e4320fbe3216ab31fa1c33cd8246ac36dae4479ba" -dependencies = [ - "camino", - "cargo-platform", - "semver", - "serde", - "serde_json", - "thiserror", -] - -[[package]] -name = "cfg-if" -version = "1.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e7648175b45a9a48536d676f68d918270699102aa8dab5496df06904c914600" - -[[package]] -name = "clap" -version = "4.6.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa8876b300ab35ba921adea3dfd70157a46249b33f95c9084ae5709785478946" -dependencies = [ - "clap_builder", - "clap_derive", -] - -[[package]] -name = "clap_builder" -version = "4.6.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec0797fb7aeb1406c84efac526901f7ec3ead2124f946b494e72879d4b54704d" -dependencies = [ - "anstyle", - "clap_lex", - "strsim", -] - -[[package]] -name = "clap_derive" -version = "4.6.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9c751b79415d4e559e3d1fcf128e09e720eb673a06d26cf6f392d37d75b66e0" -dependencies = [ - "heck", - "proc-macro2", - "quote", - "syn 3.0.6", -] - -[[package]] -name = "clap_lex" -version = "1.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c133bc6a41be0d194c306b5506d15e6feeea7b1d6604bd3f8310dfb2ca96486" - -[[package]] -name = "equivalent" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" - -[[package]] -name = "errno" -version = "0.3.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" -dependencies = [ - "libc", - "windows-sys", -] - -[[package]] -name = "fastrand" -version = "2.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da7c62ceae207dd37ea5b845da6a0696c799f85e97da1ab5b7910be3c1c80223" - -[[package]] -name = "fs-err" -version = "2.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88a41f105fe1d5b6b34b2055e3dc59bb79b46b48b2040b9e6c7b4b5de097aa41" -dependencies = [ - "autocfg", -] - -[[package]] -name = "getrandom" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "300e883d756b2e4ec94e02791f39b04b522276138852cfc41d9fb7e904106099" -dependencies = [ - "cfg-if", - "libc", - "r-efi", -] - -[[package]] -name = "glob" -version = "0.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4eba85ea1d0a966a983acd07deee566e67395d2d96b6fb39e62b5a833f1eb0b" - -[[package]] -name = "goblin" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b363a30c165f666402fe6a3024d3bec7ebc898f96a4a23bd1c99f8dbf3f4f47" -dependencies = [ - "log", - "plain", - "scroll", -] - -[[package]] -name = "hashbrown" -version = "0.17.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a" - -[[package]] -name = "heck" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" - -[[package]] -name = "indexmap" -version = "2.14.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc4e190f5d26ca7051642629da2c52fc03bde85a03197c99408dcd291734c855" -dependencies = [ - "equivalent", - "hashbrown", -] - -[[package]] -name = "itoa" -version = "1.0.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" - -[[package]] -name = "libc" -version = "0.2.189" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3eaf3ede3fee6db1a4c2ee091bf8a8b4dccdc6d17f656fb07896ee72867612f2" - -[[package]] -name = "linux-raw-sys" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53" - -[[package]] -name = "log" -version = "0.4.34" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9f8bd3e56ce4dfc153cf470fffbfa98c7620958b312ca5c3a4b8d5181fd13c6" - -[[package]] -name = "memchr" -version = "2.8.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf8baf1c55e62ffcace7a9f06f4bd9cd3f0c4beb022d3b367256b91b87513d98" - -[[package]] -name = "minimal-lexical" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" - -[[package]] -name = "nom" -version = "7.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" -dependencies = [ - "memchr", - "minimal-lexical", -] - -[[package]] -name = "once_cell" -version = "1.21.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" - -[[package]] -name = "percent-encoding" -version = "2.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" - -[[package]] -name = "plain" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4596b6d070b27117e987119b4dac604f3c58cfb0b191112e24771b2faeac1a6" - -[[package]] -name = "proc-macro2" -version = "1.0.107" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "985e7ec9bb745e6ce6535b544d84d6cd6f7ad8bd711c398938ae983b91a766d9" -dependencies = [ - "unicode-ident", -] - -[[package]] -name = "quote" -version = "1.0.47" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fbf4db142a473a8d80c26bbf18454ed458bf8d26c8219c331daecfdbd079001" -dependencies = [ - "proc-macro2", -] - -[[package]] -name = "r-efi" -version = "6.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" - -[[package]] -name = "rustc-hash" -version = "2.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b1e7f9a428571be2dc5bc0505c13fb6bf936822b894ec87abf8a08a4e51742d" - -[[package]] -name = "rustix" -version = "1.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "891efababe418670775f199f0d233d84843c227a0949a883ce15b37c78d6629d" -dependencies = [ - "bitflags", - "errno", - "libc", - "linux-raw-sys", - "windows-sys", -] - -[[package]] -name = "scroll" -version = "0.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ab8598aa408498679922eff7fa985c25d58a90771bd6be794434c5277eab1a6" -dependencies = [ - "scroll_derive", -] - -[[package]] -name = "scroll_derive" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1783eabc414609e28a5ba76aee5ddd52199f7107a0b24c2e9746a1ecc34a683d" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.119", -] - -[[package]] -name = "semver" -version = "1.0.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd" -dependencies = [ - "serde", - "serde_core", -] - -[[package]] -name = "serde" -version = "1.0.229" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4148590afebada386688f18773da617792bf2ef03ffc1e4cbd2b1d45b023e0ba" -dependencies = [ - "serde_core", - "serde_derive", -] - -[[package]] -name = "serde_core" -version = "1.0.229" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67dca2c9c51e58a4791a4b1ed58308b39c64224d349a935ab5039aa360942a48" -dependencies = [ - "serde_derive", -] - -[[package]] -name = "serde_derive" -version = "1.0.229" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7a5d71263a5a7d47b41f6b3f06ba276f10cc18b0931f1799f710578e2309348" -dependencies = [ - "proc-macro2", - "quote", - "syn 3.0.6", -] - -[[package]] -name = "serde_json" -version = "1.0.151" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c841b55ecdae098c80dcae9cf767f6f8a0c2cdb3416bbef72181df4d0fe73f14" -dependencies = [ - "itoa", - "memchr", - "serde", - "serde_core", - "zmij", -] - -[[package]] -name = "siphasher" -version = "0.3.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d" - -[[package]] -name = "smawk" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8e2fb0f499abb4d162f2bedad68f5ef91a1682b5a03596ddb67efd37768d100" - -[[package]] -name = "static_assertions" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" - -[[package]] -name = "strsim" -version = "0.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" - -[[package]] -name = "syn" -version = "2.0.119" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "872831b642d1a07999a962a351ed35b955ea2cfc8f3862091e2a240a84f17297" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "syn" -version = "3.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8593e8e72159ed2257d083c7a454a85cbf854f37a0966d8d483aff8c8a3ebcee" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "tempfile" -version = "3.27.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd" -dependencies = [ - "fastrand", - "getrandom", - "once_cell", - "rustix", - "windows-sys", -] - -[[package]] -name = "textwrap" -version = "0.16.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ecfad6c3abc80a577f2b91c1e412ee57e7a060d430b553c1b0c940974ebcd49" -dependencies = [ - "smawk", - "unicode-width", -] - -[[package]] -name = "thiserror" -version = "2.0.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec86235f5fcc2a73650310756d2ac5b138a5780bbbdfae3eeccec992c435ba4f" -dependencies = [ - "thiserror-impl", -] - -[[package]] -name = "thiserror-impl" -version = "2.0.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc04cd3e1236dd4a98afca4569f2deb3f120e5422a4023be2cb683f8486292af" -dependencies = [ - "proc-macro2", - "quote", - "syn 3.0.6", -] - -[[package]] -name = "toml" -version = "0.5.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234" -dependencies = [ - "serde", -] - -[[package]] -name = "unicode-ident" -version = "1.0.26" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d245f478577f809a851594d02313b640fb437e0bb33866753cff937863096954" - -[[package]] -name = "unicode-width" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4ac048d71ede7ee76d585517add45da530660ef4390e49b098733c6e897f254" - -[[package]] -name = "uniffi" -version = "0.29.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3291800a6b06569f7d3e15bdb6dc235e0f0c8bd3eb07177f430057feb076415f" -dependencies = [ - "anyhow", - "camino", - "cargo_metadata", - "clap", - "uniffi_bindgen", - "uniffi_build", - "uniffi_core", - "uniffi_macros", - "uniffi_pipeline", -] - -[[package]] -name = "uniffi_bindgen" -version = "0.29.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a04b99fa7796eaaa7b87976a0dbdd1178dc1ee702ea00aca2642003aef9b669e" -dependencies = [ - "anyhow", - "askama", - "camino", - "cargo_metadata", - "fs-err", - "glob", - "goblin", - "heck", - "indexmap", - "once_cell", - "serde", - "tempfile", - "textwrap", - "toml", - "uniffi_internal_macros", - "uniffi_meta", - "uniffi_pipeline", - "uniffi_udl", -] - -[[package]] -name = "uniffi_build" -version = "0.29.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "025a05cba02ee22b6624ac3d257e59c7395319ea8fe1aae33a7cdb4e2a3016cc" -dependencies = [ - "anyhow", - "camino", - "uniffi_bindgen", -] - -[[package]] -name = "uniffi_core" -version = "0.29.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f38a9a27529ccff732f8efddb831b65b1e07f7dea3fd4cacd4a35a8c4b253b98" -dependencies = [ - "anyhow", - "bytes", - "once_cell", - "static_assertions", -] - -[[package]] -name = "uniffi_internal_macros" -version = "0.29.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09acd2ce09c777dd65ee97c251d33c8a972afc04873f1e3b21eb3492ade16933" -dependencies = [ - "anyhow", - "indexmap", - "proc-macro2", - "quote", - "syn 2.0.119", -] - -[[package]] -name = "uniffi_macros" -version = "0.29.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5596f178c4f7aafa1a501c4e0b96236a96bc2ef92bdb453d83e609dad0040152" -dependencies = [ - "camino", - "fs-err", - "once_cell", - "proc-macro2", - "quote", - "serde", - "syn 2.0.119", - "toml", - "uniffi_meta", -] - -[[package]] -name = "uniffi_meta" -version = "0.29.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "beadc1f460eb2e209263c49c4f5b19e9a02e00a3b2b393f78ad10d766346ecff" -dependencies = [ - "anyhow", - "siphasher", - "uniffi_internal_macros", - "uniffi_pipeline", -] - -[[package]] -name = "uniffi_pipeline" -version = "0.29.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd76b3ac8a2d964ca9fce7df21c755afb4c77b054a85ad7a029ad179cc5abb8a" -dependencies = [ - "anyhow", - "heck", - "indexmap", - "tempfile", - "uniffi_internal_macros", -] - -[[package]] -name = "uniffi_udl" -version = "0.29.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4319cf905911d70d5b97ce0f46f101619a22e9a189c8c46d797a9955e9233716" -dependencies = [ - "anyhow", - "textwrap", - "uniffi_meta", - "weedle2", -] - -[[package]] -name = "weedle2" -version = "5.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "998d2c24ec099a87daf9467808859f9d82b61f1d9c9701251aea037f514eae0e" -dependencies = [ - "nom", -] - -[[package]] -name = "windows-link" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" - -[[package]] -name = "windows-sys" -version = "0.61.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" -dependencies = [ - "windows-link", -] - -[[package]] -name = "winnow" -version = "0.7.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df79d97927682d2fd8adb29682d1140b343be4ac0f08fd68b7765d9c059d3945" -dependencies = [ - "memchr", -] - -[[package]] -name = "zmij" -version = "1.0.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29666d0abbfad1e3dc4dcf6144730dd3a3ab225bbbdac83319345b1b44ccfc1b" diff --git a/spec/bench/uniffi/Cargo.toml b/spec/bench/uniffi/Cargo.toml deleted file mode 100644 index d21216ce9..000000000 --- a/spec/bench/uniffi/Cargo.toml +++ /dev/null @@ -1,23 +0,0 @@ -[package] -name = "brutils_uniffi" -version = "0.0.0" -edition = "2021" -publish = false - -[lib] -crate-type = ["cdylib", "lib"] -name = "brutils_uniffi" -path = "src/lib.rs" - -[dependencies] -uniffi = { version = "0.29", features = ["cli"] } - -[build-dependencies] -uniffi = { version = "0.29", features = ["build"] } - -[[bin]] -name = "uniffi-bindgen" -path = "src/bin.rs" - -[profile.release] -opt-level = 3 diff --git a/spec/bench/uniffi/src/bin.rs b/spec/bench/uniffi/src/bin.rs deleted file mode 100644 index df364f1ef..000000000 --- a/spec/bench/uniffi/src/bin.rs +++ /dev/null @@ -1,5 +0,0 @@ -//! The bindings generator entry point UniFFI expects. - -fn main() { - uniffi::uniffi_bindgen_main() -} diff --git a/spec/bench/uniffi/src/lib.rs b/spec/bench/uniffi/src/lib.rs deleted file mode 100644 index da54db07d..000000000 --- a/spec/bench/uniffi/src/lib.rs +++ /dev/null @@ -1,111 +0,0 @@ -//! The same validator, exposed through UniFFI instead of a hand written C ABI. -//! -//! This exists to measure what an off the shelf binding generator costs per call, against the -//! hand rolled ctypes binding in the same host language. - -uniffi::setup_scaffolding!(); - -/// Validates one CPF under the `masked-strict` profile. -#[uniffi::export] -pub fn cpf_is_valid(value: String) -> bool { - brutils_bench_core_logic::is_valid(&value) -} - -/// Validates a whole batch in one call. -#[uniffi::export] -pub fn cpf_is_valid_batch(values: Vec) -> Vec { - values - .iter() - .map(|value| brutils_bench_core_logic::is_valid(value)) - .collect() -} - -/// The validator itself, copied from the benchmark core so this crate does not need `no_std`. -mod brutils_bench_core_logic { - const fn is_js_whitespace(code: u32) -> bool { - matches!( - code, - 0x09 | 0x0a - | 0x0b - | 0x0c - | 0x0d - | 0x20 - | 0xa0 - | 0x1680 - | 0x2028 - | 0x2029 - | 0x202f - | 0x205f - | 0x3000 - | 0xfeff - ) || (code >= 0x2000 && code <= 0x200a) - } - - const fn is_mask_cpf(code: u32) -> bool { - code == 0x2e || code == 0x2d || code == 0x2f || is_js_whitespace(code) - } - - fn check_digit(base: &[u8]) -> u32 { - let mut sum: u32 = 0; - let mut weight = base.len() as u32 + 1; - - for byte in base { - sum += u32::from(*byte - b'0') * weight; - weight -= 1; - } - - let digit = 11 - (sum % 11); - - if digit >= 10 { - 0 - } else { - digit - } - } - - pub fn is_valid(value: &str) -> bool { - let trimmed = value.trim_matches(|char: char| is_js_whitespace(char as u32)); - let mut digits = [0u8; 11]; - let mut count = 0; - let groups = [3usize, 3, 3, 2]; - let mut iter = trimmed.chars().peekable(); - - for (position, size) in groups.iter().enumerate() { - if position > 0 { - while let Some(char) = iter.peek() { - if is_mask_cpf(*char as u32) { - iter.next(); - } else { - break; - } - } - } - - for _ in 0..*size { - match iter.next() { - Some(char) if char.is_ascii_digit() => { - digits[count] = char as u8; - count += 1; - } - _ => return false, - } - } - } - - if iter.next().is_some() { - return false; - } - - let first = digits[0]; - - if digits.iter().all(|digit| *digit == first) { - return false; - } - - if u32::from(digits[9] - b'0') != check_digit(&digits[..9]) { - return false; - } - - u32::from(digits[10] - b'0') == check_digit(&digits[..10]) - } -} diff --git a/spec/codegen/conformance.ts b/spec/codegen/conformance.ts deleted file mode 100644 index 8a45d8bc5..000000000 --- a/spec/codegen/conformance.ts +++ /dev/null @@ -1,576 +0,0 @@ -/** - * Emits the conformance driver for each target: a standalone program that runs the generated - * functions over the committed vectors and exits non zero on the first disagreement. - * - * The vectors are inlined into the driver rather than parsed at run time, so a target language - * needs no JSON library and the check is literally the same in all six. Every output is - * compared as a string: a validator's verdict as `"true"`/`"false"`, a formatter's absent value - * as `""`. - */ -import { type Plan, type PlannedFunction } from "./plan.ts"; -import { type Vectors } from "./vectors.ts"; - -const NONE = ""; - -/** - * Escapes a string into a target language literal. - * - * @param {string} value - The text to literal. - * @param {Function} unicode - Renders one non printable or non ASCII code point. - * @param {Record} [extra] - Characters the language escapes on top of `"` and `\`. - * @returns {string} The literal, quotes included. - */ -const escapeWith = ( - value: string, - unicode: (code: number) => string, - extra: Record = {}, -): string => { - let literal = '"'; - - for (const char of value) { - const code = char.codePointAt(0) ?? 0; - - if (Object.hasOwn(extra, char)) literal += extra[char]; - else if (char === '"') literal += String.raw`\"`; - else if (char === "\\") literal += String.raw`\\`; - else if (code < 0x20 || code > 0x7e) literal += unicode(code); - else literal += char; - } - - return `${literal}"`; -}; - -/** - * The control characters Java spells with their own literal: a `\uXXXX` literal is expanded - * before lexing, so `\u000a` would end the literal on a real line break. - */ -const JAVA_CONTROL: Record = { - 0x08: String.raw`\b`, - 0x09: String.raw`\t`, - 0x0a: String.raw`\n`, - 0x0c: String.raw`\f`, - 0x0d: String.raw`\r`, -}; - -const utf16 = (code: number): string => { - if (code < 0x20) return JAVA_CONTROL[code] ?? `\\${code.toString(8).padStart(3, "0")}`; - if (code <= 0xff_ff) return `\\u${code.toString(16).padStart(4, "0")}`; - - const offset = code - 0x1_00_00; - - return `\\u${(0xd8_00 + (offset >> 10)).toString(16).padStart(4, "0")}\\u${(0xdc_00 + (offset & 0x3_ff)).toString(16).padStart(4, "0")}`; -}; - -const braced = (code: number): string => `\\u{${code.toString(16)}}`; -const padded8 = (code: number): string => `\\U${code.toString(16).padStart(8, "0")}`; -const padded4 = (code: number): string => - code > 0xff_ff ? padded8(code) : `\\u${code.toString(16).padStart(4, "0")}`; - -const escapers: Record string> = { - typescript: (value) => escapeWith(value, braced), - python: (value) => escapeWith(value, padded8), - go: (value) => escapeWith(value, padded4), - ruby: (value) => escapeWith(value, braced, { "#": String.raw`\#` }), - rust: (value) => escapeWith(value, braced), - java: (value) => escapeWith(value, utf16), -}; - -type Column = { - planned: PlannedFunction; - optionSet: Record; - label: string; - expected: string[]; -}; - -/** - * One column per function and adopted option set, holding the expected output as strings. - * - * @param {Plan} plan - The emission plan of the target. - * @param {Vectors} vectors - The committed conformance vectors. - * @returns {Column[]} The columns the driver checks. - */ -const columnsFor = (plan: Plan, vectors: Vectors): Column[] => { - const columns: Column[] = []; - - for (const planned of plan.functions) { - const utility = vectors.utilities[planned.spec.id]; - const profile = utility.profiles[planned.profileName]; - - if (planned.spec.kind === "validator") { - columns.push({ - planned, - optionSet: {}, - label: `${planned.module}.${planned.name}`, - expected: (profile as boolean[]).map((value) => (value ? "true" : "false")), - }); - continue; - } - - for (const [index, optionSet] of utility.optionSets.entries()) { - const unsupported = Object.keys(optionSet).some( - (option) => !planned.options.includes(option), - ); - - if (unsupported) continue; - - columns.push({ - planned, - optionSet, - label: `${planned.module}.${planned.name}(${JSON.stringify(optionSet)})`, - expected: (profile as (string | null)[][]).map((outputs) => outputs[index] ?? NONE), - }); - } - } - - return columns; -}; - -const flags = (column: Column, trueLiteral: string, falseLiteral: string): string[] => - column.planned.options.map((option) => - (column.optionSet[option] ?? false) ? trueLiteral : falseLiteral, - ); - -const argumentList = (column: Column, trueLiteral: string, falseLiteral: string): string => { - const rest = flags(column, trueLiteral, falseLiteral); - - return rest.length > 0 ? `, ${rest.join(", ")}` : ""; -}; - -/** What every driver emitter needs: the vectors, already rendered as literals of its language. */ -type DriverContext = { - plan: Plan; - literal: (value: string) => string; - columns: Column[]; - inputs: string; - modules: string[]; - expectedList: (column: Column) => string; -}; - -/** - * Emits the typescript conformance driver. - * - * @param {DriverContext} context - The vectors and helpers, rendered for typescript. - * @returns {Record} The driver file, by path. - */ -const emitTypescriptDriver = (context: DriverContext): Record => { - const { plan, literal, columns, inputs, modules, expectedList } = context; - - return { - "conformance.ts": `// Code generated from spec/vectors by spec/codegen. DO NOT EDIT. -${modules - .map( - (module) => - `import { ${plan.functions - .filter((planned) => planned.module === module) - .map((planned) => planned.name) - .join(", ")} } from "./${module}/${module}.ts";`, - ) - .join("\n")} - -const inputs: string[] = [${inputs}]; - -const columns: { label: string; run: (value: string) => string; expected: string[] }[] = [ -${columns - .map((column) => { - const fields = column.planned.options - .map((option) => `${option}: ${String(column.optionSet[option] ?? false)}`) - .join(", "); - const options = column.planned.options.length > 0 ? `, { ${fields} }` : ""; - const call = `${column.planned.name}(value${options})`; - const run = - column.planned.spec.kind === "validator" ? `String(${call})` : `${call} ?? "${NONE}"`; - - return ` { label: ${literal(column.label)}, run: (value: string): string => ${run}, expected: [${expectedList(column)}] },`; - }) - .join("\n")} -]; - -let failures = 0; -let checked = 0; - -for (const column of columns) { - for (const [index, value] of inputs.entries()) { - const actual = column.run(value); - - checked++; - - if (actual !== column.expected[index]) { - failures++; - - if (failures <= 10) - console.error( - \`FAIL \${column.label} input=\${JSON.stringify(value)} expected=\${JSON.stringify(column.expected[index])} actual=\${JSON.stringify(actual)}\`, - ); - } - } -} - -console.log(\`typescript: \${checked - failures}/\${checked} conformance checks passed\`); -process.exit(failures === 0 ? 0 : 1); -`, - }; -}; - -/** - * Emits the python conformance driver. - * - * @param {DriverContext} context - The vectors and helpers, rendered for python. - * @returns {Record} The driver file, by path. - */ -const emitPythonDriver = (context: DriverContext): Record => { - const { literal, columns, inputs, modules, expectedList } = context; - - return { - "conformance.py": `# Code generated from spec/vectors by spec/codegen. DO NOT EDIT. -"""Runs the generated Python utilities against the committed conformance vectors.""" - -import sys -from pathlib import Path - -sys.path.insert(0, str(Path(__file__).resolve().parent)) - -${modules.map((module) => `import ${module}`).join("\n")} - -INPUTS = [${inputs}] - -COLUMNS = [ -${columns - .map((column) => { - const call = `${column.planned.module}.${column.planned.name}(value${argumentList(column, "True", "False")})`; - const run = - column.planned.spec.kind === "validator" - ? `"true" if ${call} else "false"` - : `(${call} if ${call} is not None else "${NONE}")`; - - return ` (${literal(column.label)}, lambda value: ${run}, [${expectedList(column)}]),`; - }) - .join("\n")} -] - -failures = 0 -checked = 0 - -for label, run, expected in COLUMNS: - for index, value in enumerate(INPUTS): - actual = run(value) - checked += 1 - - if actual != expected[index]: - failures += 1 - - if failures <= 10: - print( - f"FAIL {label} input={value!r} expected={expected[index]!r} actual={actual!r}", - file=sys.stderr, - ) - -print(f"python: {checked - failures}/{checked} conformance checks passed") -sys.exit(0 if failures == 0 else 1) -`, - }; -}; - -/** - * Emits the go conformance driver. - * - * @param {DriverContext} context - The vectors and helpers, rendered for go. - * @returns {Record} The driver file, by path. - */ -const emitGoDriver = (context: DriverContext): Record => { - const { literal, columns, inputs, modules, expectedList } = context; - - return { - "conformance/main.go": `// Code generated from spec/vectors by spec/codegen. DO NOT EDIT. - -package main - -import ( - "fmt" - "os" - "strconv" - -${modules.map((module) => `\t"brazilianutils/spec/${module}"`).join("\n")} -) - -type column struct { - label string - run func(string) string - expected []string -} - -func main() { - inputs := []string{${inputs}} - - columns := []column{ -${columns - .map((column) => { - const call = `${column.planned.module}.${column.planned.name}(value${argumentList(column, "true", "false")})`; - const run = column.planned.spec.kind === "validator" ? `strconv.FormatBool(${call})` : call; - - return `\t\t{label: ${literal(column.label)}, run: func(value string) string { return ${run} }, expected: []string{${expectedList(column)}}},`; - }) - .join("\n")} - } - - failures := 0 - checked := 0 - - for _, current := range columns { - for index, value := range inputs { - actual := current.run(value) - checked++ - - if actual != current.expected[index] { - failures++ - - if failures <= 10 { - fmt.Fprintf(os.Stderr, "FAIL %s input=%q expected=%q actual=%q\\n", current.label, value, current.expected[index], actual) - } - } - } - } - - fmt.Printf("go: %d/%d conformance checks passed\\n", checked-failures, checked) - - if failures > 0 { - os.Exit(1) - } -} -`, - }; -}; - -/** - * Emits the ruby conformance driver. - * - * @param {DriverContext} context - The vectors and helpers, rendered for ruby. - * @returns {Record} The driver file, by path. - */ -const emitRubyDriver = (context: DriverContext): Record => { - const { literal, columns, inputs, modules, expectedList } = context; - - return { - "conformance.rb": `# frozen_string_literal: true - -# Code generated from spec/vectors by spec/codegen. DO NOT EDIT. - -${modules - .map((module) => { - const short = (module.split("::").at(-1) ?? module).replace(/Utils$/, "").toLowerCase(); - - return `require_relative 'brazilian-utils/${short}-utils'`; - }) - .join("\n")} - -INPUTS = [${inputs}].freeze - -COLUMNS = [ -${columns - .map((column) => { - const call = `${column.planned.module}.${column.planned.name}(value${argumentList(column, "true", "false")})`; - const run = column.planned.spec.kind === "validator" ? `${call}.to_s` : `${call} || '${NONE}'`; - - return ` [${literal(column.label)}, ->(value) { ${run} }, [${expectedList(column)}]],`; - }) - .join("\n")} -].freeze - -failures = 0 -checked = 0 - -COLUMNS.each do |label, run, expected| - INPUTS.each_with_index do |value, index| - actual = run.call(value) - checked += 1 - - next if actual == expected[index] - - failures += 1 - warn "FAIL #{label} input=#{value.inspect} expected=#{expected[index].inspect} actual=#{actual.inspect}" if failures <= 10 - end -end - -puts "ruby: #{checked - failures}/#{checked} conformance checks passed" -exit(failures.zero? ? 0 : 1) -`, - }; -}; - -/** - * Emits the rust conformance driver. - * - * @param {DriverContext} context - The vectors and helpers, rendered for rust. - * @returns {Record} The driver file, by path. - */ -const emitRustDriver = (context: DriverContext): Record => { - const { literal, columns, inputs, modules, expectedList } = context; - - return { - "conformance.rs": `// Code generated from spec/vectors by spec/codegen. DO NOT EDIT. - -//! Runs the generated Rust utilities against the committed conformance vectors. - -mod spec_runtime; -${modules.map((module) => `mod ${module};`).join("\n")} - -fn main() { - let inputs: Vec<&str> = vec![${inputs}]; - - let columns: Vec<(&str, fn(&str) -> String, Vec<&str>)> = vec![ -${columns - .map((column) => { - const call = `${column.planned.module}::${column.planned.name}(value${argumentList(column, "true", "false")})`; - const formatted = column.planned.nullable - ? `${call}.unwrap_or_else(|| "${NONE}".to_string())` - : call; - const run = column.planned.spec.kind === "validator" ? `${call}.to_string()` : formatted; - - return ` (${literal(column.label)}, (|value: &str| ${run}) as fn(&str) -> String, vec![${expectedList(column)}]),`; - }) - .join("\n")} - ]; - - let mut failures = 0; - let mut checked = 0; - - for (label, run, expected) in &columns { - for (index, value) in inputs.iter().enumerate() { - let actual = run(value); - - checked += 1; - - if actual != expected[index] { - failures += 1; - - if failures <= 10 { - eprintln!( - "FAIL {} input={:?} expected={:?} actual={:?}", - label, value, expected[index], actual - ); - } - } - } - } - - println!("rust: {}/{} conformance checks passed", checked - failures, checked); - - if failures > 0 { - std::process::exit(1); - } -} -`, - }; -}; - -/** - * Emits the java conformance driver. - * - * @param {DriverContext} context - The vectors and helpers, rendered for java. - * @returns {Record} The driver file, by path. - */ -const emitJavaDriver = (context: DriverContext): Record => { - const { literal, columns, inputs, expectedList } = context; - - return { - "Conformance.java": `// Code generated from spec/vectors by spec/codegen. DO NOT EDIT. - -import java.util.ArrayList; -import java.util.List; -import java.util.Objects; -import java.util.function.Function; - -/** Runs the generated Java utilities against the committed conformance vectors. */ -public final class Conformance { - private Conformance() {} - - private static final String[] INPUTS = {${inputs}}; - -${columns - .map( - (column, index) => - ` private static final String[] EXPECTED_${index} = {${expectedList(column)}};`, - ) - .join("\n")} - - private record Column(String label, Function run, String[] expected) {} - - public static void main(String[] args) { - List columns = new ArrayList<>(); - -${columns - .map((column, index) => { - const call = `${column.planned.module}.${column.planned.name}(value${argumentList(column, "true", "false")})`; - const run = - column.planned.spec.kind === "validator" - ? `String.valueOf(${call})` - : `${call} == null ? "${NONE}" : ${call}`; - - return ` columns.add(new Column(${literal(column.label)}, value -> ${run}, EXPECTED_${index}));`; - }) - .join("\n")} - - int failures = 0; - int checked = 0; - - for (Column column : columns) { - for (int index = 0; index < INPUTS.length; index++) { - String actual = column.run().apply(INPUTS[index]); - - checked++; - - if (!Objects.equals(actual, column.expected()[index])) { - failures++; - - if (failures <= 10) { - System.err.printf( - "FAIL %s input=%s expected=%s actual=%s%n", - column.label(), INPUTS[index], column.expected()[index], actual); - } - } - } - } - - System.out.printf("java: %d/%d conformance checks passed%n", checked - failures, checked); - - if (failures > 0) { - System.exit(1); - } - } -} -`, - }; -}; - -const drivers: Record Record> = { - typescript: emitTypescriptDriver, - python: emitPythonDriver, - go: emitGoDriver, - ruby: emitRubyDriver, - rust: emitRustDriver, - java: emitJavaDriver, -}; - -/** - * Emits the conformance driver of one target. - * - * @param {Plan} plan - The emission plan of the target. - * @param {Vectors} vectors - The committed conformance vectors. - * @returns {Record} The driver file, by path. - */ -export const emitConformance = (plan: Plan, vectors: Vectors): Record => { - const driver = drivers[plan.target]; - - if (driver === undefined) throw new Error(`no conformance driver for ${plan.target}`); - - const literal = escapers[plan.target]; - const columns = columnsFor(plan, vectors); - - return driver({ - plan, - literal, - columns, - inputs: vectors.corpus.map((input) => literal(input)).join(", "), - modules: [...new Set(plan.functions.map((planned) => planned.module))], - expectedList: (column) => column.expected.map((value) => literal(value)).join(", "), - }); -}; diff --git a/spec/codegen/corpus.ts b/spec/codegen/corpus.ts deleted file mode 100644 index bde5b83eb..000000000 --- a/spec/codegen/corpus.ts +++ /dev/null @@ -1,145 +0,0 @@ -/** - * Deterministic corpus of raw inputs used to build the conformance vectors. - * - * The corpus is pseudo random but seeded, so every target and every language sees exactly the - * same inputs and the vectors only change when this file does. - */ -import { computeCheckDigit } from "./interpret.ts"; - -/** - * Mulberry32: a tiny, portable PRNG, so the corpus does not depend on the host's Math.random. - * - * @param {number} seed - The seed the sequence starts from. - * @returns {Function} A generator of numbers in [0, 1). - */ -const mulberry32 = (seed: number): (() => number) => { - let state = seed; - - return () => { - // oxlint-disable-next-line unicorn/prefer-math-trunc -- `| 0` wraps to a signed 32 bit integer, which is what the algorithm specifies, and Math.trunc does not wrap - state = (state + 0x6d_2b_79_f5) | 0; - let t = Math.imul(state ^ (state >>> 15), 1 | state); - - t ^= t + Math.imul(t ^ (t >>> 7), 61 | t); - - return ((t ^ (t >>> 14)) >>> 0) / 4_294_967_296; - }; -}; - -const CURATED = [ - "", - " ", - "0", - "00000000000", - "11111111111", - "99999999999", - "12345678909", - "123.456.789-09", - "123 456 789 09", - " 12345678909 ", - "123.456.789.09", - "123/456/789/09", - "123-456-789-09", - "123..456..789--09", - ".12345678909", - "12345678909.", - "1234567890", - "123456789090", - "abc12345678909", - "12345678909abc", - "1a2345678909", - "12345678900", - " 12345678909 ", - " 123.456.789-09
", - "12345678909", - "123 456 789 09", - "123\t456\n789\r09", - "🇧🇷12345678909", - "12345678909🇧🇷", - "12345678909", - "١٢٣٤٥٦٧٨٩٠٩", - "12056874107", - "120.56874.10-7", - "120/56874/10-7", - "120(56874)10,7", - "120*56874*10-7", - "12056874108", - "1205687410", - "120.56874.10-7 ", - "120#56874#10#7", -]; - -const DIGITS = "0123456789"; -const MASKS = [".", "-", "/", " ", "(", ")", ",", "*", " ", "#", "a", ""]; - -const validCpf = (random: () => number): string => { - let base = ""; - - for (let index = 0; index < 9; index++) base += DIGITS[Math.floor(random() * 10)]; - - const first = computeCheckDigit(base, "cpf"); - const second = computeCheckDigit(`${base}${first}`, "cpf"); - - return `${base}${first}${second}`; -}; - -const validPis = (random: () => number): string => { - let base = ""; - - for (let index = 0; index < 10; index++) base += DIGITS[Math.floor(random() * 10)]; - - return `${base}${computeCheckDigit(base, "pis")}`; -}; - -const sprinkle = (value: string, random: () => number): string => { - let out = ""; - - for (const char of value) { - out += char; - if (random() < 0.18) out += MASKS[Math.floor(random() * MASKS.length)]; - } - - return out; -}; - -/** - * Builds the corpus: the curated edge cases first, then the seeded random ones. - * - * @param {number} [size] - How many inputs to produce before de-duplication. - * @returns {string[]} The corpus, in a stable order. - */ -export const buildCorpus = (size = 2000): string[] => { - const random = mulberry32(0x62_72_75_74); - const corpus = [...CURATED]; - - while (corpus.length < size) { - const roll = random(); - - if (roll < 0.3) corpus.push(validCpf(random)); - else if (roll < 0.45) corpus.push(sprinkle(validCpf(random), random)); - else if (roll < 0.6) corpus.push(validPis(random)); - else if (roll < 0.72) corpus.push(sprinkle(validPis(random), random)); - else if (roll < 0.86) { - let junk = ""; - const length = Math.floor(random() * 16); - - for (let index = 0; index < length; index++) { - junk += - random() < 0.7 - ? DIGITS[Math.floor(random() * 10)] - : MASKS[Math.floor(random() * MASKS.length)]; - } - - corpus.push(junk); - } else { - const valid = validCpf(random); - const position = Math.floor(random() * valid.length); - - corpus.push( - `${valid.slice(0, position)}${DIGITS[Math.floor(random() * 10)]}${valid.slice(position + 1)}`, - ); - } - } - - return [...new Set(corpus)]; -}; diff --git a/spec/codegen/emit.ts b/spec/codegen/emit.ts deleted file mode 100644 index 85aceb9b8..000000000 --- a/spec/codegen/emit.ts +++ /dev/null @@ -1,41 +0,0 @@ -/** - * Emits every language target from the specs. - * - * Usage: `node spec/codegen/emit.ts [target...]` (default: every target). - */ -import { mkdirSync, readFileSync, rmSync, writeFileSync } from "node:fs"; -import { dirname, resolve } from "node:path"; - -import { emitConformance } from "./conformance.ts"; -import { specRoot } from "./ir.ts"; -import { planFor } from "./plan.ts"; -import { emitters } from "./targets/registry.ts"; -import { type Vectors } from "./vectors.ts"; - -const vectors = JSON.parse( - readFileSync(resolve(specRoot, "vectors/conformance.json"), "utf8"), -) as Vectors; - -const requested = process.argv.slice(2); -const selected = requested.length > 0 ? requested : Object.keys(emitters); - -for (const target of selected) { - const emitter = emitters[target]; - - if (emitter === undefined) throw new Error(`unknown target: ${target}`); - - const plan = planFor(target); - const files = { ...emitter(plan), ...emitConformance(plan, vectors) }; - const outDir = resolve(specRoot, "generated", target); - - rmSync(outDir, { recursive: true, force: true }); - - for (const [path, contents] of Object.entries(files)) { - const full = resolve(outDir, path); - - mkdirSync(dirname(full), { recursive: true }); - writeFileSync(full, contents); - } - - console.log(`${target.padEnd(11)} ${Object.keys(files).length} files`); -} diff --git a/spec/codegen/interpret.ts b/spec/codegen/interpret.ts deleted file mode 100644 index 4cff291ae..000000000 --- a/spec/codegen/interpret.ts +++ /dev/null @@ -1,347 +0,0 @@ -/** - * Reference interpreter of the utility specs. - * - * This is the normative implementation: the conformance vectors come from running it, and every - * emitted language target has to agree with it. It reads the resolved IR — code point ranges and - * weight vectors — and never a regex, because a regex shorthand does not mean the same thing in - * the six languages the specs are emitted to. - */ -import { - type CharsetRanges, - type Profile, - type Step, - type UtilitySpec, - checkDigitAlgorithm, - resolveCharset, -} from "./ir.ts"; - -/** - * Whether a code point belongs to a resolved charset. - * - * @param {number} code - The code point to test. - * @param {CharsetRanges} charset - The resolved charset. - * @returns {boolean} True when the code point is in the set. - */ -const inCharset = (code: number, charset: CharsetRanges): boolean => - charset.single.includes(code) || charset.ranges.some(([from, to]) => code >= from && code <= to); - -const DIGITS = resolveCharset("ascii-digits"); - -/** - * Strips the leading and trailing characters that belong to a charset. - * - * @param {string} value - The value to trim. - * @param {CharsetRanges} charset - The characters to strip. - * @returns {string} The trimmed value. - */ -const trimBy = (value: string, charset: CharsetRanges): string => { - let start = 0; - let end = value.length; - - while (start < end && inCharset(value.charCodeAt(start), charset)) start++; - while (end > start && inCharset(value.charCodeAt(end - 1), charset)) end--; - - return value.slice(start, end); -}; - -/** - * Whether a value is exactly the given digit groups, optionally separated. - * - * @param {string} value - The value to match. - * @param {number[]} groups - The size of each digit group. - * @param {CharsetRanges} [separators] - The characters allowed between groups, if any. - * @returns {boolean} True when the whole value matches. - */ -const matchShape = (value: string, groups: number[], separators?: CharsetRanges): boolean => { - let index = 0; - - for (const [position, size] of groups.entries()) { - if (position > 0 && separators !== undefined) { - while (index < value.length && inCharset(value.charCodeAt(index), separators)) index++; - } - - for (let digit = 0; digit < size; digit++) { - if (index >= value.length || !inCharset(value.charCodeAt(index), DIGITS)) return false; - - index++; - } - } - - return index === value.length; -}; - -/** - * Keeps only the characters that belong to a charset. - * - * @param {string} value - The value to filter. - * @param {CharsetRanges} charset - The characters to keep. - * @returns {string} The filtered value. - */ -const keepCharset = (value: string, charset: CharsetRanges): string => { - let kept = ""; - - for (let index = 0; index < value.length; index++) { - if (inCharset(value.charCodeAt(index), charset)) kept += value.charAt(index); - } - - return kept; -}; - -/** - * Whether a value is a non empty run of one repeated character. - * - * @param {string} value - The value to test. - * @returns {boolean} True for values such as "00000000000". - */ -const isRepeated = (value: string): boolean => - value !== "" && value === value.charAt(0).repeat(value.length); - -/** - * Computes one check digit of a base with the named algorithm. - * - * @param {string} base - The digits that precede the check digit. - * @param {string} algorithm - The algorithm name, as declared in `spec/schema/check-digits.json`. - * @returns {number} The check digit. - */ -export const computeCheckDigit = (base: string, algorithm: string): number => { - const spec = checkDigitAlgorithm(algorithm); - let sum = 0; - - if (spec.weights.kind === "fixed") { - const { values } = spec.weights; - - for (let index = 0; index < values.length; index++) { - sum += (base.charCodeAt(index) - 48) * values[index]; - } - } else { - let weight = base.length + 1; - - for (let index = 0; index < base.length; index++) { - sum += (base.charCodeAt(index) - 48) * weight; - weight--; - } - } - - const digit = spec.modulus - (sum % spec.modulus); - - return digit >= spec.clamp.atLeast ? spec.clamp.to : digit; -}; - -/** - * Whether every check digit of a value matches its base. - * - * @param {string} digits - The sanitized digits. - * @param {string} algorithm - The algorithm name. - * @returns {boolean} True when all the declared positions check out. - */ -const verifyCheckDigits = (digits: string, algorithm: string): boolean => { - const spec = checkDigitAlgorithm(algorithm); - - for (const position of spec.positions) { - if (digits.length <= position) return false; - - if ( - digits.charCodeAt(position) - 48 !== - computeCheckDigit(digits.slice(0, position), algorithm) - ) - return false; - } - - return true; -}; - -/** - * Lays a value over a pattern: `0` copies a character, `*` hides one, anything else separates. - * - * @param {string} value - The sanitized value. - * @param {string} pattern - The pattern to lay it over. - * @param {boolean} pad - Whether to left pad the value with zeros up to the pattern's slots. - * @returns {string} The formatted value. - */ -export const applyPattern = (value: string, pattern: string, pad: boolean): string => { - let padded = value; - - if (pad) { - let slots = 0; - - for (const char of pattern) { - if (char === "0" || char === "*") slots++; - } - - padded = value.padStart(slots, "0"); - } - - let formatted = ""; - let index = 0; - - for (const char of pattern) { - if (char === "0" || char === "*") { - if (index >= padded.length) break; - - formatted += char === "*" ? "*" : padded.charAt(index); - index++; - } else if (index < padded.length) { - formatted += char; - } - } - - return formatted; -}; - -/** Options a formatter profile can declare. */ -export type RunOptions = { pad?: boolean; obfuscate?: boolean }; - -/** The value a utility answers with, by kind: a verdict, a formatted string, or nothing. */ -type Outcome = boolean | string | null; - -let loadUtilitySync: (id: string) => UtilitySpec = () => { - throw new Error("interpreter not initialised: call setLoader first"); -}; - -/** - * Injects the spec loader the `guard-valid` step uses to reach another utility. - * - * @param {Function} loader - Loads a utility spec by id. - * @returns {void} - */ -export const setLoader = (loader: (id: string) => UtilitySpec): void => { - loadUtilitySync = loader; -}; - -/** - * The value a profile answers with when a guard rejects the input. - * - * @param {UtilitySpec} spec - The utility being run. - * @param {Profile} profile - The profile being run. - * @returns {Outcome} `false` for a validator, `""` or `null` for a formatter. - */ -const rejectionOf = (spec: UtilitySpec, profile: Profile): Outcome => { - if (spec.kind === "validator") return false; - - return (profile.absent ?? spec.input.onNullish) === "null" ? null : ""; -}; - -/** The mutable state a pipeline threads through its steps. */ -type State = { raw: string; digits: string }; - -/** - * Runs the `guard-shape` step: the value, trimmed if the profile says so, has to be exactly the - * declared digit groups. - * - * @param {Step} step - The guard-shape step. - * @param {string} raw - The raw input. - * @returns {boolean} True when the value matches. - */ -const guardShape = (step: Extract, raw: string): boolean => { - const value = step.trim === undefined ? raw : trimBy(raw, resolveCharset(step.trim)); - const separators = step.separators === undefined ? undefined : resolveCharset(step.separators); - - return matchShape(value, step.groups, separators); -}; - -/** - * Runs the `guard-charset` step: every character of the raw input has to be allowed. - * - * @param {Step} step - The guard-charset step. - * @param {string} raw - The raw input. - * @returns {boolean} True when every character is in the allowed set. - */ -const guardCharset = (step: Extract, raw: string): boolean => { - const allowed = resolveCharset(step.allow); - - for (let index = 0; index < raw.length; index++) { - if (!inCharset(raw.charCodeAt(index), allowed)) return false; - } - - return true; -}; - -/** - * Runs one pipeline step. - * - * @param {Step} step - The step to run. - * @param {State} state - The raw input and the digits sanitized so far. - * @param {RunOptions} options - The options the caller passed. - * @returns {Outcome | undefined} A value when the step answers, `undefined` to carry on. - */ -const runStep = (step: Step, state: State, options: RunOptions): Outcome | undefined => { - switch (step.op) { - case "guard-shape": { - return guardShape(step, state.raw) ? undefined : false; - } - case "guard-charset": { - return guardCharset(step, state.raw) ? undefined : false; - } - case "sanitize": { - state.digits = keepCharset(state.raw, resolveCharset(step.keep)); - - return undefined; - } - case "guard-length": { - return state.digits.length === step.equals ? undefined : false; - } - case "guard-repeated": { - return isRepeated(state.digits) ? false : undefined; - } - case "verify-check-digits": { - return verifyCheckDigits(state.digits, step.checkDigit) ? undefined : false; - } - case "guard-valid": { - // Handled by `run`, which owns the recursion into the referenced utility. - throw new Error(`${step.utility}: guard-valid must be run by the caller`); - } - case "apply-pattern": { - const obfuscated = step.variants?.["obfuscate"]; - const pattern = - (options.obfuscate ?? false) && obfuscated !== undefined ? obfuscated : step.pattern; - - return applyPattern(state.digits, pattern, options.pad ?? false); - } - default: { - throw new Error(`unsupported step: ${JSON.stringify(step)}`); - } - } -}; - -/** - * Runs a profile of a utility against a raw input. - * - * @param {UtilitySpec} spec - The utility to run. - * @param {string} profileName - Which of its profiles to run. - * @param {unknown} input - The raw input, of any type: a utility never throws on bad input. - * @param {RunOptions} [options] - The options a formatter profile declares. - * @returns {Outcome} The declared output of the utility. - */ -export const run = ( - spec: UtilitySpec, - profileName: string, - input: unknown, - options: RunOptions = {}, -): Outcome => { - const profile: Profile | undefined = spec.profiles[profileName]; - - if (profile === undefined) throw new Error(`${spec.id} has no profile ${profileName}`); - - const rejection = rejectionOf(spec, profile); - - if (spec.kind === "validator" && typeof input !== "string") return false; - if (spec.kind === "formatter" && (input === null || input === undefined)) return rejection; - - const state: State = { raw: typeof input === "string" ? input : String(input), digits: "" }; - - for (const step of profile.pipeline) { - if (step.op === "guard-valid") { - // oxlint-disable-next-line sonarjs/no-extra-arguments, sonarjs/no-use-of-empty-return-value -- `run` recurses into itself, which the analyser reads as a call to an undeclared binding - if (run(loadUtilitySync(step.utility), step.profile, state.raw) !== true) return rejection; - - continue; - } - - const outcome = runStep(step, state, options); - - if (outcome === false) return rejection; - if (outcome !== undefined) return outcome; - } - - return spec.kind === "validator" ? true : state.digits; -}; diff --git a/spec/codegen/ir.ts b/spec/codegen/ir.ts deleted file mode 100644 index a7918d453..000000000 --- a/spec/codegen/ir.ts +++ /dev/null @@ -1,153 +0,0 @@ -/** - * Loader for the language neutral utility specs under `spec/utilities`. - * - * It resolves the charset and check digit references into plain data, so an emitter only ever - * sees code point ranges and weight vectors, never a regex or a language specific shorthand. - */ -import { readFileSync } from "node:fs"; -import { dirname, resolve } from "node:path"; - -const specDir = resolve(import.meta.dirname, ".."); - -export type CharsetRanges = { single: number[]; ranges: [number, number][] }; - -export type CheckDigitAlgorithm = { - description: string; - modulus: number; - weights: { kind: "descending"; from: string; to: number } | { kind: "fixed"; values: number[] }; - reduce: "modulus-minus-remainder"; - clamp: { atLeast: number; to: number }; - positions: number[]; - cumulative: boolean; - source: string; -}; - -export type Step = - | { op: "guard-shape"; target: "raw"; trim?: string; groups: number[]; separators?: string } - | { op: "guard-charset"; target: "raw"; allow: string[] } - | { op: "sanitize"; keep: string; into: string } - | { op: "guard-length"; target: string; equals: number } - | { op: "guard-repeated"; target: string } - | { op: "verify-check-digits"; target: string; checkDigit: string } - | { op: "guard-valid"; utility: string; profile: string } - | { - op: "apply-pattern"; - target: string; - engine: "pattern-v1"; - pattern: string; - variants?: Record; - }; - -export type OptionSpec = { name: string; type: string; default: boolean; read: string }; - -export type Profile = { - description: string; - /** What a formatter answers when the value has no formatting: `""` or the language's null. */ - absent?: "empty-string" | "null"; - pipeline: Step[]; - options?: OptionSpec[]; -}; - -/** A known, documented difference between a package and the profile it otherwise implements. */ -export type Deviation = { inputs: string[]; reason: string; issue?: string }; - -export type Adoption = { profile: string; options?: string[]; knownDeviations?: Deviation[] }; - -export type UtilitySpec = { - id: string; - kind: "validator" | "formatter"; - summary: string; - sources: { role: string; url: string }[]; - names: Record; - input: { name: string; type: string; onWrongType?: string; onNullish?: string }; - output: { type: string }; - adopted: Record; - profiles: Record; -}; - -/** - * Reads a JSON file of the specification. - * - * @param {string} path - The absolute path to read. - * @returns {unknown} The parsed contents, for the caller to narrow. - */ -const readJson = (path: string): unknown => JSON.parse(readFileSync(path, "utf8")); - -type CharsetFile = { - charsets: Record< - string, - { description: string; codePoints?: string[]; ranges?: [string, string][]; include?: string[] } - >; -}; - -const charsetFile = readJson(resolve(specDir, "schema/charsets.json")) as CharsetFile; - -const checkDigitFile = readJson(resolve(specDir, "schema/check-digits.json")) as { - algorithms: Record; -}; - -/** - * Expands a charset reference into sorted code point ranges. - * - * @param {string|string[]} names - One charset name, or the union of several. - * @returns {CharsetRanges} The single code points and the ranges the union covers. - */ -export const resolveCharset = (names: string | string[]): CharsetRanges => { - const wanted = Array.isArray(names) ? names : [names]; - const single = new Set(); - const ranges: [number, number][] = []; - - const visit = (name: string): void => { - const charset = charsetFile.charsets[name]; - - if (charset === undefined) throw new Error(`unknown charset: ${name}`); - - for (const codePoint of charset.codePoints ?? []) single.add(Number.parseInt(codePoint, 16)); - for (const [from, to] of charset.ranges ?? []) - ranges.push([Number.parseInt(from, 16), Number.parseInt(to, 16)]); - for (const included of charset.include ?? []) visit(included); - }; - - for (const name of wanted) visit(name); - - return { - single: [...single].sort((a, b) => a - b), - ranges: ranges.sort((a, b) => a[0] - b[0]), - }; -}; - -/** - * Looks a check digit algorithm up by name. - * - * @param {string} name - The algorithm name declared in `spec/schema/check-digits.json`. - * @returns {CheckDigitAlgorithm} The algorithm. - */ -export const checkDigitAlgorithm = (name: string): CheckDigitAlgorithm => { - const algorithm = checkDigitFile.algorithms[name]; - - if (algorithm === undefined) throw new Error(`unknown check digit algorithm: ${name}`); - - return algorithm; -}; - -/** - * Loads one utility spec. - * - * @param {string} id - The utility id, which is also its file name. - * @returns {UtilitySpec} The spec. - */ -export const loadUtility = (id: string): UtilitySpec => - readJson(resolve(specDir, `utilities/${id}.json`)) as UtilitySpec; - -/** - * Loads every utility the specification covers, in declaration order. - * - * @returns {UtilitySpec[]} The specs. - */ -export const loadAll = (): UtilitySpec[] => - (readJson(resolve(specDir, "utilities.json")) as { utilities: string[] }).utilities.map((id) => - loadUtility(id), - ); - -export const specRoot = specDir; -export const codegenRoot = dirname(resolve(import.meta.dirname, "emit.ts")); diff --git a/spec/codegen/plan.ts b/spec/codegen/plan.ts deleted file mode 100644 index cab81393c..000000000 --- a/spec/codegen/plan.ts +++ /dev/null @@ -1,179 +0,0 @@ -/** - * Turns the specs into the flat plan an emitter needs: which charsets and check digit - * algorithms to lay down in the prelude, and which function to emit for the target, under the - * name and with the option set that target's package already exposes. - */ -import { - type CharsetRanges, - type CheckDigitAlgorithm, - type Profile, - type Step, - type UtilitySpec, - checkDigitAlgorithm, - loadAll, - resolveCharset, -} from "./ir.ts"; - -export type PlannedFunction = { - spec: UtilitySpec; - profile: Profile; - profileName: string; - name: string; - module: string; - options: string[]; - /** Whether the function may answer "no value": a formatter whose profile is absent as null. */ - nullable: boolean; -}; - -export type Plan = { - target: string; - charsets: { name: string; symbol: string; ranges: CharsetRanges }[]; - algorithms: { name: string; symbol: string; algorithm: CheckDigitAlgorithm }[]; - functions: PlannedFunction[]; -}; - -/** - * Converts a kebab-case id to PascalCase. - * - * @param {string} value - The id to convert. - * @returns {string} The PascalCase form. - */ -const pascal = (value: string): string => - value - .split(/[-_]/) - .map((part) => part.charAt(0).toUpperCase() + part.slice(1)) - .join(""); - -/** - * Converts a kebab-case id to camelCase. - * - * @param {string} value - The id to convert. - * @returns {string} The camelCase form. - */ -const camel = (value: string): string => { - const pascalCase = pascal(value); - - return pascalCase.charAt(0).toLowerCase() + pascalCase.slice(1); -}; - -/** - * Converts a kebab-case id to snake_case. - * - * @param {string} value - The id to convert. - * @returns {string} The snake_case form. - */ -const snake = (value: string): string => value.replaceAll("-", "_"); - -export const naming = { pascal, camel, snake }; - -/** - * The charsets one step references. - * - * @param {Step} step - The step to inspect. - * @returns {string[]} The charset names, which may be empty. - */ -const charsetsOf = (step: Step): string[] => { - if (step.op === "guard-shape") - return [step.trim, step.separators].filter((name): name is string => name !== undefined); - if (step.op === "guard-charset") return step.allow; - if (step.op === "sanitize") return [step.keep]; - - return []; -}; - -/** - * Flattens a profile's pipeline into the steps an emitter renders one by one: `guard-valid` - * becomes the referenced profile's own steps, and the duplicate `sanitize` that inlining - * introduces is dropped, so the target language binds `digits` exactly once. - * - * @param {Profile} profile - The profile to flatten. - * @returns {Step[]} The steps to render, in order. - */ -export const expandPipeline = (profile: Profile): Step[] => { - const specs = loadAll(); - const expanded: Step[] = []; - - for (const step of profile.pipeline) { - if (step.op !== "guard-valid") { - expanded.push(step); - continue; - } - - const referenced = specs.find((candidate) => candidate.id === step.utility); - - if (referenced === undefined) throw new Error(`unknown referenced utility ${step.utility}`); - - expanded.push(...referenced.profiles[step.profile].pipeline); - } - - const sanitized = new Set(); - - return expanded.filter((step) => { - if (step.op !== "sanitize") return true; - - const key = `${step.keep}->${step.into}`; - const seen = sanitized.has(key); - - sanitized.add(key); - - return !seen; - }); -}; - -/** - * Builds the emission plan for one target language. - * - * @param {string} target - The target language id, as used in a spec's `adopted` map. - * @returns {Plan} Everything the emitter for that language needs. - */ -export const planFor = (target: string): Plan => { - const specs = loadAll(); - const charsetNames = new Set(["ascii-digits"]); - const algorithmNames = new Set(); - const functions: PlannedFunction[] = []; - - for (const spec of specs) { - const adoption = spec.adopted[target]; - - if (adoption === undefined) continue; - - const profile = spec.profiles[adoption.profile]; - - if (profile === undefined) - throw new Error(`${spec.id}: ${target} adopts unknown profile ${adoption.profile}`); - - const names = spec.names[target]; - - if (names === undefined) throw new Error(`${spec.id}: no name for target ${target}`); - - for (const step of expandPipeline(profile)) { - for (const charset of charsetsOf(step)) charsetNames.add(charset); - if (step.op === "verify-check-digits") algorithmNames.add(step.checkDigit); - } - - functions.push({ - spec, - profile, - profileName: adoption.profile, - name: names.function, - module: names.module, - options: adoption.options ?? (profile.options ?? []).map((option) => option.name), - nullable: (profile.absent ?? spec.input.onNullish) === "null", - }); - } - - return { - target, - charsets: [...charsetNames].sort().map((name) => ({ - name, - symbol: snake(name), - ranges: resolveCharset(name), - })), - algorithms: [...algorithmNames].sort().map((name) => ({ - name, - symbol: snake(name), - algorithm: checkDigitAlgorithm(name), - })), - functions, - }; -}; diff --git a/spec/codegen/targets/go.ts b/spec/codegen/targets/go.ts deleted file mode 100644 index 47727aadf..000000000 --- a/spec/codegen/targets/go.ts +++ /dev/null @@ -1,413 +0,0 @@ -/** - * Go emitter: one package per module, exported names in Go's style, and a `specruntime` - * package holding the shared helpers. - */ -import { type Step, type UtilitySpec } from "../ir.ts"; -import { type Plan, type PlannedFunction, expandPipeline, naming } from "../plan.ts"; - -/** - * Renders a string as a Go interpreted string literal. - * - * @param {string} value - The text to render. - * @returns {string} The literal, quotes included. - */ -const escapeLiteral = (value: string): string => { - let literal = '"'; - - for (const char of value) { - const code = char.codePointAt(0) ?? 0; - - if (char === '"') literal += String.raw`\"`; - else if (char === "\\") literal += String.raw`\\`; - else if (code > 0xff_ff) literal += `\\U${code.toString(16).padStart(8, "0")}`; - else if (code < 0x20 || code > 0x7e) literal += `\\u${code.toString(16).padStart(4, "0")}`; - else literal += char; - } - - return `${literal}"`; -}; - -/** - * Converts an id to the exported name Go uses for it. - * - * @param {string} name - The id to convert. - * @returns {string} The Go name. - */ -const goName = (name: string): string => naming.pascal(name); - -/** - * Renders the membership test of a charset as an expression of the target language. - * - * @param {Plan} plan - The emission plan holding the resolved charsets. - * @param {string} name - The charset name. - * @returns {string} The boolean expression. - */ -const charsetTest = (plan: Plan, name: string): string => { - const found = plan.charsets.find((charset) => charset.name === name); - const { single, ranges } = found?.ranges ?? { single: [], ranges: [] }; - - return [ - ...single.map((code) => `code == 0x${code.toString(16)}`), - ...ranges.map( - ([from, to]) => `(code >= 0x${from.toString(16)} && code <= 0x${to.toString(16)})`, - ), - ].join(" ||\n\t\t"); -}; - -/** The part of the prelude that does not depend on the specs. */ -const RUNTIME_HELPERS = `// TrimBy strips the leading and trailing characters that belong to the set. -func TrimBy(value string, inSet func(rune) bool) string { - return strings.TrimFunc(value, inSet) -} - -// KeepBy keeps only the characters that belong to the set. -func KeepBy(value string, inSet func(rune) bool) string { - var kept strings.Builder - - for _, char := range value { - if inSet(char) { - kept.WriteRune(char) - } - } - - return kept.String() -} - -// MatchShape reports whether the value is exactly the digit groups, optionally separated. -func MatchShape(value string, groups []int, inSeparator func(rune) bool) bool { - runes := []rune(value) - index := 0 - - for position, size := range groups { - if position > 0 && inSeparator != nil { - for index < len(runes) && inSeparator(runes[index]) { - index++ - } - } - - for digit := 0; digit < size; digit++ { - if index >= len(runes) || !IsAsciiDigits(runes[index]) { - return false - } - - index++ - } - } - - return index == len(runes) -} - -// IsRepeated reports whether the value is a non empty run of one repeated character. -func IsRepeated(value string) bool { - if value == "" { - return false - } - - return value == strings.Repeat(value[:1], len(value)) -} - -// ApplyPattern lays the value over the pattern: '0' copies, '*' hides, anything else separates. -func ApplyPattern(value string, pattern string, pad bool) string { - padded := value - - if pad { - slots := 0 - - for _, char := range pattern { - if char == '0' || char == '*' { - slots++ - } - } - - if len(padded) < slots { - padded = strings.Repeat("0", slots-len(padded)) + padded - } - } - - var formatted strings.Builder - index := 0 - - for _, char := range pattern { - if char == '0' || char == '*' { - if index >= len(padded) { - break - } - - if char == '*' { - formatted.WriteString("*") - } else { - formatted.WriteByte(padded[index]) - } - - index++ - } else if index < len(padded) { - formatted.WriteRune(char) - } - } - - return formatted.String() -}`; - -/** - * Renders the runtime shared by every generated utility of this target. - * - * @param {Plan} plan - The emission plan. - * @returns {string} The prelude source. - */ -const prelude = (plan: Plan): string => { - const charsets = plan.charsets - .map( - ( - charset, - ) => `// Is${goName(charset.name)} reports whether the code point belongs to the ${charset.name} set. -func Is${goName(charset.name)}(code rune) bool { - return ${charsetTest(plan, charset.name)} -}`, - ) - .join("\n\n"); - - const algorithms = plan.algorithms - .map((entry) => { - const { algorithm } = entry; - const body = - algorithm.weights.kind === "fixed" - ? ` weights := []int{${algorithm.weights.values.join(", ")}} - sum := 0 - - for index, weight := range weights { - sum += int(base[index]-'0') * weight - }` - : ` sum := 0 - weight := len(base) + 1 - - for index := 0; index < len(base); index++ { - sum += int(base[index]-'0') * weight - weight-- - }`; - - return `// CheckDigit${goName(entry.name)} computes one check digit of the base. -// -// ${algorithm.description} -// -// Official source: ${algorithm.source} -func CheckDigit${goName(entry.name)}(base string) int { -${body} - - digit := ${algorithm.modulus} - (sum % ${algorithm.modulus}) - - if digit >= ${algorithm.clamp.atLeast} { - return ${algorithm.clamp.to} - } - - return digit -} - -// Verify${goName(entry.name)} reports whether every check digit matches its base. -func Verify${goName(entry.name)}(digits string) bool { - for _, position := range []int{${algorithm.positions.join(", ")}} { - if len(digits) <= position { - return false - } - - if int(digits[position]-'0') != CheckDigit${goName(entry.name)}(digits[:position]) { - return false - } - } - - return true -}`; - }) - .join("\n\n"); - - return `// Code generated from spec/utilities by spec/codegen. DO NOT EDIT. - -// Package specruntime holds the helpers shared by the generated utilities. -package specruntime - -import "strings" - -${charsets} - -${RUNTIME_HELPERS} - -${algorithms} -`; -}; - -/** - * The value the generated function returns when a guard rejects the input. - * - * @param {UtilitySpec} spec - The utility being emitted. - * @param {PlannedFunction} planned - The planned function. - * @returns {string} The literal to return. - */ -const bailValue = (spec: UtilitySpec, planned: PlannedFunction): string => { - if (spec.kind === "validator") return "false"; - - return planned.nullable ? '"", false' : '""'; -}; - -/** - * Renders one pipeline step as statements of the target language. - * - * @param {Step} step - The step to render. - * @param {UtilitySpec} spec - The utility being emitted. - * @param {PlannedFunction} planned - The planned function. - * @returns {string} The rendered statements. - */ -const renderStep = (step: Step, spec: UtilitySpec, planned: PlannedFunction): string => { - const bail = bailValue(spec, planned); - - switch (step.op) { - case "guard-shape": { - const value = - step.trim === undefined - ? "raw" - : `specruntime.TrimBy(raw, specruntime.Is${goName(step.trim)})`; - const separators = - step.separators === undefined ? "nil" : `specruntime.Is${goName(step.separators)}`; - - return ` if !specruntime.MatchShape(${value}, []int{${step.groups.join(", ")}}, ${separators}) { - return ${bail} - }`; - } - case "guard-charset": { - return ` for _, char := range raw { - if !(${step.allow.map((name) => `specruntime.Is${goName(name)}(char)`).join(" || ")}) { - return ${bail} - } - }`; - } - case "sanitize": { - return ` digits := specruntime.KeepBy(raw, specruntime.Is${goName(step.keep)})`; - } - case "guard-length": { - return ` if len(digits) != ${step.equals} { - return ${bail} - }`; - } - case "guard-repeated": { - return ` if specruntime.IsRepeated(digits) { - return ${bail} - }`; - } - case "verify-check-digits": { - return ` if !specruntime.Verify${goName(step.checkDigit)}(digits) { - return ${bail} - }`; - } - case "apply-pattern": { - const pattern = - step.variants?.["obfuscate"] !== undefined && planned.options.includes("obfuscate") - ? `map[bool]string{true: ${escapeLiteral(step.variants["obfuscate"])}, false: ${escapeLiteral(step.pattern)}}[obfuscate]` - : escapeLiteral(step.pattern); - const pad = planned.options.includes("pad") ? "pad" : "false"; - - const secondReturn = planned.nullable ? ", true" : ""; - - return ` return specruntime.ApplyPattern(digits, ${pattern}, ${pad})${secondReturn}`; - } - case "guard-valid": { - // `expandPipeline` replaces this step with the referenced profile's own steps. - throw new Error(`${spec.id}: guard-valid reached the emitter unexpanded`); - } - default: { - throw new Error(`unsupported step: ${JSON.stringify(step)}`); - } - } -}; - -/** - * The return type the generated function declares. - * - * @param {UtilitySpec} spec - The utility being emitted. - * @param {PlannedFunction} planned - The planned function. - * @returns {string} The type, spelled in the target language. - */ -const returnTypeOf = (spec: UtilitySpec, planned: PlannedFunction): string => { - if (spec.kind === "validator") return "bool"; - - return planned.nullable ? "(string, bool)" : "string"; -}; - -/** - * What closes the generated body: the success value, or nothing when a step already returned. - * - * @param {UtilitySpec} spec - The utility being emitted. - * @param {PlannedFunction} planned - The planned function. - * @returns {string} The closing lines, which may be empty. - */ -const tailOf = (spec: UtilitySpec, planned: PlannedFunction): string => { - if (spec.kind === "validator") return "\n\n return true"; - - const returnsEarly = expandPipeline(planned.profile).some((step) => step.op === "apply-pattern"); - - return returnsEarly ? "" : `\n\n return digits`; -}; - -/** - * Renders one planned function, documentation included. - * - * @param {PlannedFunction} planned - The function to render. - * @returns {string} The rendered source. - */ -const renderFunction = (planned: PlannedFunction): string => { - const { spec } = planned; - const returns = returnTypeOf(spec, planned); - const parameters = [ - `${naming.camel(spec.input.name)} string`, - ...planned.options.map((option) => `${option} bool`), - ].join(", "); - - const head = ` raw := ${naming.camel(spec.input.name)}`; - const body = expandPipeline(planned.profile) - .map((step) => renderStep(step, spec, planned)) - .join("\n"); - const tail = tailOf(spec, planned); - - return `// ${planned.name} ${spec.summary} -// -// Profile: ${planned.profileName} — ${planned.profile.description} -// -${spec.sources.map((source) => `// ${source.role === "official" ? "Official" : "Based on"}: ${source.url}`).join("\n")} -func ${planned.name}(${parameters}) ${returns} { -${head} - -${body}${tail} -}`; -}; - -/** - * Emits every file of this target. - * - * @param {Plan} plan - The emission plan. - * @returns {Record} The files, by path relative to the target directory. - */ -export const emit = (plan: Plan): Record => { - const files: Record = { - "specruntime/specruntime.go": prelude(plan), - "go.mod": "module brazilianutils/spec\n\ngo 1.24\n", - }; - const modules = new Map(); - - for (const planned of plan.functions) { - modules.set(planned.module, [...(modules.get(planned.module) ?? []), planned]); - } - - for (const [module, functions] of modules) { - const source = functions.map((planned) => renderFunction(planned)).join("\n\n"); - - files[`${module}/${module}.go`] = - `// Code generated from spec/utilities by spec/codegen. DO NOT EDIT. - -// Package ${module} holds the generated ${module} utilities. -package ${module} - -import "brazilianutils/spec/specruntime" - -${source} -`; - } - - return files; -}; diff --git a/spec/codegen/targets/java.ts b/spec/codegen/targets/java.ts deleted file mode 100644 index a45332ae5..000000000 --- a/spec/codegen/targets/java.ts +++ /dev/null @@ -1,431 +0,0 @@ -/** - * Java emitter: the target with no existing package, kept here to show what onboarding a new - * language costs once the specs exist — a file of roughly 120 lines of emitter, no new - * algorithm work, and the canonical profile from day one. - */ -import { type Step, type UtilitySpec } from "../ir.ts"; -import { type Plan, type PlannedFunction, expandPipeline, naming } from "../plan.ts"; - -/** - * Renders a string as a Java literal. - * - * A `\\uXXXX` escape is expanded by the compiler before lexing, so `\\u000a` would end the - * literal on a real line break: every control character goes out as its own escape, and an - * astral code point as its UTF-16 surrogate pair. - * - * @param {string} value - The text to render. - * @returns {string} The literal, quotes included. - */ -const JAVA_CONTROL: Record = { - 0x08: "\\b", - 0x09: "\\t", - 0x0a: "\\n", - 0x0c: "\\f", - 0x0d: "\\r", -}; - -const escapeLiteral = (value: string): string => { - let literal = '"'; - - for (const char of value) { - const code = char.codePointAt(0) ?? 0; - - if (char === '"') literal += String.raw`\"`; - else if (char === "\\") literal += String.raw`\\`; - else if (code < 0x20) literal += JAVA_CONTROL[code] ?? `\\${code.toString(8).padStart(3, "0")}`; - else if (code > 0xff_ff) { - const offset = code - 0x1_00_00; - - literal += `\\u${(0xd8_00 + (offset >> 10)).toString(16).padStart(4, "0")}`; - literal += `\\u${(0xdc_00 + (offset & 0x3_ff)).toString(16).padStart(4, "0")}`; - } else if (code > 0x7e) literal += `\\u${code.toString(16).padStart(4, "0")}`; - else literal += char; - } - - return `${literal}"`; -}; - -/** - * Renders the membership test of a charset as an expression of the target language. - * - * @param {Plan} plan - The emission plan holding the resolved charsets. - * @param {string} name - The charset name. - * @returns {string} The boolean expression. - */ -const charsetTest = (plan: Plan, name: string): string => { - const found = plan.charsets.find((charset) => charset.name === name); - const { single, ranges } = found?.ranges ?? { single: [], ranges: [] }; - - return [ - ...single.map((code) => `code == 0x${code.toString(16)}`), - ...ranges.map( - ([from, to]) => `(code >= 0x${from.toString(16)} && code <= 0x${to.toString(16)})`, - ), - ].join("\n || "); -}; - -/** The part of the prelude that does not depend on the specs. */ -const RUNTIME_HELPERS = ` /** Strips the leading and trailing characters that belong to the set. */ - public static String trimBy(String value, IntPredicate inSet) { - int start = 0; - int end = value.length(); - - while (start < end && inSet.test(value.charAt(start))) { - start++; - } - while (end > start && inSet.test(value.charAt(end - 1))) { - end--; - } - - return value.substring(start, end); - } - - /** Keeps only the characters that belong to the set. */ - public static String keepBy(String value, IntPredicate inSet) { - StringBuilder kept = new StringBuilder(); - - for (int index = 0; index < value.length(); index++) { - if (inSet.test(value.charAt(index))) { - kept.append(value.charAt(index)); - } - } - - return kept.toString(); - } - - /** Whether the value is exactly the digit groups, optionally separated. */ - public static boolean matchShape(String value, int[] groups, IntPredicate inSeparator) { - int index = 0; - - for (int position = 0; position < groups.length; position++) { - if (position > 0 && inSeparator != null) { - while (index < value.length() && inSeparator.test(value.charAt(index))) { - index++; - } - } - - for (int digit = 0; digit < groups[position]; digit++) { - if (index >= value.length() || !isAsciiDigits(value.charAt(index))) { - return false; - } - - index++; - } - } - - return index == value.length(); - } - - /** Whether the value is a non empty run of one repeated character. */ - public static boolean isRepeated(String value) { - if (value.isEmpty()) { - return false; - } - - for (int index = 1; index < value.length(); index++) { - if (value.charAt(index) != value.charAt(0)) { - return false; - } - } - - return true; - } - - /** Lays the value over the pattern: '0' copies, '*' hides, anything else separates. */ - public static String applyPattern(String value, String pattern, boolean pad) { - String padded = value; - - if (pad) { - int slots = 0; - - for (int index = 0; index < pattern.length(); index++) { - char current = pattern.charAt(index); - - if (current == '0' || current == '*') { - slots++; - } - } - - while (padded.length() < slots) { - padded = "0" + padded; - } - } - - StringBuilder formatted = new StringBuilder(); - int index = 0; - - for (int position = 0; position < pattern.length(); position++) { - char current = pattern.charAt(position); - - if (current == '0' || current == '*') { - if (index >= padded.length()) { - break; - } - - formatted.append(current == '*' ? '*' : padded.charAt(index)); - index++; - } else if (index < padded.length()) { - formatted.append(current); - } - } - - return formatted.toString(); - }`; - -/** - * Renders the runtime shared by every generated utility of this target. - * - * @param {Plan} plan - The emission plan. - * @returns {string} The prelude source. - */ -const prelude = (plan: Plan): string => { - const charsets = plan.charsets - .map( - (charset) => ` /** Whether the code point belongs to the ${charset.name} set. */ - public static boolean is${naming.pascal(charset.name)}(int code) { - return ${charsetTest(plan, charset.name)}; - }`, - ) - .join("\n\n"); - - const algorithms = plan.algorithms - .map((entry) => { - const { algorithm } = entry; - const body = - algorithm.weights.kind === "fixed" - ? ` int[] weights = {${algorithm.weights.values.join(", ")}}; - int sum = 0; - - for (int index = 0; index < weights.length; index++) { - sum += (base.charAt(index) - '0') * weights[index]; - }` - : ` int sum = 0; - int weight = base.length() + 1; - - for (int index = 0; index < base.length(); index++) { - sum += (base.charAt(index) - '0') * weight; - weight--; - }`; - - return ` /** - * ${algorithm.description} - * - *

Official source: ${algorithm.source} - */ - public static int checkDigit${naming.pascal(entry.name)}(String base) { -${body} - - int digit = ${algorithm.modulus} - (sum % ${algorithm.modulus}); - - return digit >= ${algorithm.clamp.atLeast} ? ${algorithm.clamp.to} : digit; - } - - /** Whether every check digit of the value matches its base. */ - public static boolean verify${naming.pascal(entry.name)}(String digits) { - for (int position : new int[] {${algorithm.positions.join(", ")}}) { - if (digits.length() <= position) { - return false; - } - - if (digits.charAt(position) - '0' != checkDigit${naming.pascal(entry.name)}(digits.substring(0, position))) { - return false; - } - } - - return true; - }`; - }) - .join("\n\n"); - - return `// Code generated from spec/utilities by spec/codegen. DO NOT EDIT. - -import java.util.function.IntPredicate; - -/** Helpers shared by the generated utilities. */ -public final class SpecRuntime { - private SpecRuntime() {} - -${charsets} - -${RUNTIME_HELPERS} - -${algorithms} -} -`; -}; - -/** - * The value the generated function returns when a guard rejects the input. - * - * @param {UtilitySpec} spec - The utility being emitted. - * @param {PlannedFunction} planned - The planned function. - * @returns {string} The literal to return. - */ -const bailValue = (spec: UtilitySpec, planned: PlannedFunction): string => { - if (spec.kind === "validator") return "false"; - - return planned.nullable ? "null" : '""'; -}; - -/** - * Renders one pipeline step as statements of the target language. - * - * @param {Step} step - The step to render. - * @param {UtilitySpec} spec - The utility being emitted. - * @param {PlannedFunction} planned - The planned function. - * @returns {string} The rendered statements. - */ -const renderStep = (step: Step, spec: UtilitySpec, planned: PlannedFunction): string => { - const bail = bailValue(spec, planned); - - switch (step.op) { - case "guard-shape": { - const value = - step.trim === undefined - ? "raw" - : `SpecRuntime.trimBy(raw, SpecRuntime::is${naming.pascal(step.trim)})`; - const separators = - step.separators === undefined ? "null" : `SpecRuntime::is${naming.pascal(step.separators)}`; - - return ` if (!SpecRuntime.matchShape(${value}, new int[] {${step.groups.join(", ")}}, ${separators})) { - return ${bail}; - }`; - } - case "guard-charset": { - return ` for (int index = 0; index < raw.length(); index++) { - int code = raw.charAt(index); - - if (!(${step.allow.map((name) => `SpecRuntime.is${naming.pascal(name)}(code)`).join(" || ")})) { - return ${bail}; - } - }`; - } - case "sanitize": { - return ` String digits = SpecRuntime.keepBy(raw, SpecRuntime::is${naming.pascal(step.keep)});`; - } - case "guard-length": { - return ` if (digits.length() != ${step.equals}) { - return ${bail}; - }`; - } - case "guard-repeated": { - return ` if (SpecRuntime.isRepeated(digits)) { - return ${bail}; - }`; - } - case "verify-check-digits": { - return ` if (!SpecRuntime.verify${naming.pascal(step.checkDigit)}(digits)) { - return ${bail}; - }`; - } - case "apply-pattern": { - const pattern = - step.variants?.["obfuscate"] !== undefined && planned.options.includes("obfuscate") - ? `obfuscate ? ${escapeLiteral(step.variants["obfuscate"])} : ${escapeLiteral(step.pattern)}` - : escapeLiteral(step.pattern); - const pad = planned.options.includes("pad") ? "pad" : "false"; - - return ` return SpecRuntime.applyPattern(digits, ${pattern}, ${pad});`; - } - case "guard-valid": { - // `expandPipeline` replaces this step with the referenced profile's own steps. - throw new Error(`${spec.id}: guard-valid reached the emitter unexpanded`); - } - default: { - throw new Error(`unsupported step: ${JSON.stringify(step)}`); - } - } -}; - -/** - * What closes the generated body: the success value, or nothing when a step already returned. - * - * @param {UtilitySpec} spec - The utility being emitted. - * @param {PlannedFunction} planned - The planned function. - * @returns {string} The closing lines, which may be empty. - */ -const tailOf = (spec: UtilitySpec, planned: PlannedFunction): string => { - if (spec.kind === "validator") return "\n\n return true;"; - - const returnsEarly = expandPipeline(planned.profile).some((step) => step.op === "apply-pattern"); - - return returnsEarly ? "" : "\n\n return digits;"; -}; - -/** - * Renders one planned function, documentation included. - * - * @param {PlannedFunction} planned - The function to render. - * @returns {string} The rendered source. - */ -const renderFunction = (planned: PlannedFunction): string => { - const { spec } = planned; - const returns = spec.kind === "validator" ? "boolean" : "String"; - const parameters = [ - `String ${naming.camel(spec.input.name)}`, - ...planned.options.map((option) => `boolean ${option}`), - ].join(", "); - - const head = ` if (${naming.camel(spec.input.name)} == null) { - return ${bailValue(spec, planned)}; - } - - String raw = ${naming.camel(spec.input.name)};`; - - const body = expandPipeline(planned.profile) - .map((step) => renderStep(step, spec, planned)) - .join("\n"); - const tail = tailOf(spec, planned); - - const overload = - planned.options.length > 0 - ? ` - /** ${spec.summary} Uses the default options. */ - public static ${returns} ${planned.name}(String ${naming.camel(spec.input.name)}) { - return ${planned.name}(${[naming.camel(spec.input.name), ...planned.options.map(() => "false")].join(", ")}); - } -` - : ""; - - return `${overload} - /** - * ${spec.summary} - * - *

Profile: ${planned.profileName} — ${planned.profile.description} - * -${spec.sources.map((source) => ` *

${source.role === "official" ? "Official" : "Based on"}: ${source.url}`).join("\n")} - */ - public static ${returns} ${planned.name}(${parameters}) { -${head} - -${body}${tail} - }`; -}; - -/** - * Emits every file of this target. - * - * @param {Plan} plan - The emission plan. - * @returns {Record} The files, by path relative to the target directory. - */ -export const emit = (plan: Plan): Record => { - const files: Record = { "SpecRuntime.java": prelude(plan) }; - const modules = new Map(); - - for (const planned of plan.functions) { - modules.set(planned.module, [...(modules.get(planned.module) ?? []), planned]); - } - - for (const [module, functions] of modules) { - files[`${module}.java`] = `// Code generated from spec/utilities by spec/codegen. DO NOT EDIT. - -/** ${functions.map((planned) => planned.spec.summary).join(" ")} */ -public final class ${module} { - private ${module}() {} -${functions.map((planned) => renderFunction(planned)).join("\n")} -} -`; - } - - return files; -}; diff --git a/spec/codegen/targets/python.ts b/spec/codegen/targets/python.ts deleted file mode 100644 index b60ec5320..000000000 --- a/spec/codegen/targets/python.ts +++ /dev/null @@ -1,451 +0,0 @@ -/** - * Python emitter: produces modules shaped like `brutils/`, with the names and the - * `None` returning formatter contract that package already exposes. - */ -import { type Step, type UtilitySpec, resolveCharset } from "../ir.ts"; -import { type Plan, type PlannedFunction, expandPipeline, naming } from "../plan.ts"; - -/** - * Renders a string as a Python literal. - * - * @param {string} value - The text to render. - * @returns {string} The literal, quotes included. - */ -const escapeLiteral = (value: string): string => { - let literal = '"'; - - for (const char of value) { - const code = char.codePointAt(0) ?? 0; - - if (char === '"') literal += String.raw`\"`; - else if (char === "\\") literal += String.raw`\\`; - else if (code < 0x20 || code > 0x7e) literal += `\\U${code.toString(16).padStart(8, "0")}`; - else literal += char; - } - - return `${literal}"`; -}; - -/** - * Renders the membership test of a charset as an expression of the target language. - * - * @param {Plan} plan - The emission plan holding the resolved charsets. - * @param {string} name - The charset name. - * @returns {string} The boolean expression. - */ -const charsetTest = (plan: Plan, name: string): string => { - const found = plan.charsets.find((charset) => charset.name === name); - const { single, ranges } = found?.ranges ?? { single: [], ranges: [] }; - - return [ - ...single.map((code) => `code == 0x${code.toString(16)}`), - ...ranges.map(([from, to]) => `(0x${from.toString(16)} <= code <= 0x${to.toString(16)})`), - ].join("\n or "); -}; - -/** - * Renders the runtime shared by every generated utility of this target. - * - * @param {Plan} plan - The emission plan. - * @returns {string} The prelude source. - */ -const prelude = (plan: Plan): string => { - const charsets = plan.charsets - .map( - (charset) => `def is_${charset.symbol}(code: int) -> bool: - """Whether the code point belongs to the ${charset.name} set.""" - return ( - ${charsetTest(plan, charset.name)} - )`, - ) - .join("\n\n\n"); - - const algorithms = plan.algorithms - .map((entry) => { - const { algorithm } = entry; - const body = - algorithm.weights.kind === "fixed" - ? ` weights = (${algorithm.weights.values.join(", ")},) - total = 0 - - for index, weight in enumerate(weights): - total += (ord(base[index]) - 48) * weight` - : ` total = 0 - weight = len(base) + 1 - - for char in base: - total += (ord(char) - 48) * weight - weight -= 1`; - - return `def check_digit_${entry.symbol}(base: str) -> int: - """${algorithm.description} - - Official source: ${algorithm.source} - """ -${body} - digit = ${algorithm.modulus} - (total % ${algorithm.modulus}) - - return ${algorithm.clamp.to} if digit >= ${algorithm.clamp.atLeast} else digit - - -def verify_${entry.symbol}(digits: str) -> bool: - """Whether every check digit of the value matches its base.""" - for position in (${algorithm.positions.join(", ")},): - if len(digits) <= position: - return False - if ord(digits[position]) - 48 != check_digit_${entry.symbol}(digits[:position]): - return False - - return True`; - }) - .join("\n\n\n"); - - return `# Code generated from spec/utilities by spec/codegen. DO NOT EDIT. -"""Runtime shared by the generated utilities.""" - -from typing import Callable, List, Optional - -${charsets} - - -def trim_by(value: str, in_set: Callable[[int], bool]) -> str: - """Strips the leading and trailing characters that belong to the set.""" - start, end = 0, len(value) - - while start < end and in_set(ord(value[start])): - start += 1 - while end > start and in_set(ord(value[end - 1])): - end -= 1 - - return value[start:end] - - -def keep_by(value: str, in_set: Callable[[int], bool]) -> str: - """Keeps only the characters that belong to the set.""" - return "".join(char for char in value if in_set(ord(char))) - - -def match_shape( - value: str, groups: List[int], in_separator: Optional[Callable[[int], bool]] = None -) -> bool: - """Whether the value is exactly the digit groups, optionally separated.""" - index = 0 - - for position, size in enumerate(groups): - if position > 0 and in_separator is not None: - while index < len(value) and in_separator(ord(value[index])): - index += 1 - - for _ in range(size): - if index >= len(value) or not is_ascii_digits(ord(value[index])): - return False - index += 1 - - return index == len(value) - - -def is_repeated(value: str) -> bool: - """Whether the value is a non empty run of one repeated character.""" - return value != "" and value == value[0] * len(value) - - -def apply_pattern(value: str, pattern: str, pad: bool) -> str: - """Lays the value over the pattern: "0" copies, "*" hides, anything else separates.""" - padded = value - - if pad: - slots = sum(1 for char in pattern if char in "0*") - padded = value.rjust(slots, "0") - - formatted = "" - index = 0 - - for char in pattern: - if char in "0*": - if index >= len(padded): - break - formatted += "*" if char == "*" else padded[index] - index += 1 - elif index < len(padded): - formatted += char - - return formatted - - -${algorithms} -`; -}; - -/** - * The value the generated function returns when a guard rejects the input. - * - * @param {UtilitySpec} spec - The utility being emitted. - * @param {PlannedFunction} planned - The planned function. - * @returns {string} The literal to return. - */ -const bailValue = (spec: UtilitySpec, planned: PlannedFunction): string => { - if (spec.kind === "validator") return "False"; - - return planned.nullable ? "None" : '""'; -}; - -/** - * Renders a charset as the body of a regex character class, every code point written as a - * `\uXXXX` escape so that no character can be read as a class metacharacter or a range. - * - * @param {string|string[]} names - The charset name, or the union of several. - * @returns {string} The class body, without the brackets. - */ -/** - * Renders one code point as a regex escape. - * - * @param {number} code - The code point. - * @returns {string} The escape sequence. - */ -const escapeCodePoint = (code: number): string => { - const hex = code.toString(16); - - return code > 0xff_ff ? `\\U${hex.padStart(8, "0")}` : `\\u${hex.padStart(4, "0")}`; -}; - -const regexClass = (names: string | string[]): string => { - const { single, ranges } = resolveCharset(names); - const points = single.map((code) => escapeCodePoint(code)); - const spans = ranges.map(([from, to]) => `${escapeCodePoint(from)}-${escapeCodePoint(to)}`); - - return [...points, ...spans].join(""); -}; - -/** - * The regex a `guard-shape` step becomes, with one capture group per digit run so that the - * digits come straight out of the match instead of being filtered out of the string again. - * - * @param {Step} step - The guard-shape step. - * @returns {string} The regex source. - */ -const shapeRegex = (step: Extract): string => { - const edge = step.trim === undefined ? "" : `[${regexClass(step.trim)}]*`; - const separator = step.separators === undefined ? "" : `[${regexClass(step.separators)}]*`; - const digits = `[${regexClass("ascii-digits")}]`; - const groups = step.groups.map((size) => `(${digits}{${size}})`).join(separator); - - // `\Z` rather than `$`: Python's `$` also matches before a trailing newline. - return `\\A${edge}${groups}${edge}\\Z`; -}; - -/** - * Whether the profile is the common "match a shape, then keep the digits" shape, which - * collapses into a single regex. - * - * @param {PlannedFunction} planned - The planned function. - * @returns {boolean} True when the fast path applies. - */ -const hasShapeFastPath = (planned: PlannedFunction): boolean => { - const steps = expandPipeline(planned.profile); - - return ( - steps.some((step) => step.op === "guard-shape") && - steps.some((step) => step.op === "sanitize" && step.keep === "ascii-digits") - ); -}; - -/** - * Renders one pipeline step as statements of the target language. - * - * @param {Step} step - The step to render. - * @param {UtilitySpec} spec - The utility being emitted. - * @param {PlannedFunction} planned - The planned function. - * @returns {string} The rendered statements. - */ -const renderStep = (step: Step, spec: UtilitySpec, planned: PlannedFunction): string => { - const bail = bailValue(spec, planned); - const constant = `_${naming.snake(planned.spec.id).toUpperCase()}`; - - switch (step.op) { - case "guard-shape": { - return ` match = ${constant}_SHAPE.match(raw) - - if match is None: - return ${bail} - - digits = "".join(match.groups())`; - } - case "guard-charset": { - return ` if ${constant}_ALLOWED.match(raw) is None: - return ${bail}`; - } - case "sanitize": { - // Already bound by the shape guard's capture groups. - if (hasShapeFastPath(planned)) return ""; - - return ` digits = _NON_DIGITS.sub("", raw)`; - } - case "guard-length": { - return ` if len(digits) != ${step.equals}: - return ${bail}`; - } - case "guard-repeated": { - return ` if is_repeated(digits): - return ${bail}`; - } - case "verify-check-digits": { - return ` if not verify_${naming.snake(step.checkDigit)}(digits): - return ${bail}`; - } - case "apply-pattern": { - const pattern = - step.variants?.["obfuscate"] !== undefined && planned.options.includes("obfuscate") - ? `${escapeLiteral(step.variants["obfuscate"])} if obfuscate else ${escapeLiteral(step.pattern)}` - : escapeLiteral(step.pattern); - const pad = planned.options.includes("pad") ? "pad" : "False"; - - return ` return apply_pattern(digits, ${pattern}, ${pad})`; - } - case "guard-valid": { - // `expandPipeline` replaces this step with the referenced profile's own steps. - throw new Error(`${spec.id}: guard-valid reached the emitter unexpanded`); - } - default: { - throw new Error(`unsupported step: ${JSON.stringify(step)}`); - } - } -}; - -/** - * The return type the generated function declares. - * - * @param {UtilitySpec} spec - The utility being emitted. - * @param {PlannedFunction} planned - The planned function. - * @returns {string} The type, spelled in the target language. - */ -const returnTypeOf = (spec: UtilitySpec, planned: PlannedFunction): string => { - if (spec.kind === "validator") return "bool"; - - return planned.nullable ? "Optional[str]" : "str"; -}; - -/** - * What closes the generated body: the success value, or nothing when a step already returned. - * - * @param {UtilitySpec} spec - The utility being emitted. - * @param {PlannedFunction} planned - The planned function. - * @returns {string} The closing lines, which may be empty. - */ -const tailOf = (spec: UtilitySpec, planned: PlannedFunction): string => { - if (spec.kind === "validator") return "\n\n return True"; - - const returnsEarly = expandPipeline(planned.profile).some((step) => step.op === "apply-pattern"); - - return returnsEarly ? "" : "\n\n return digits"; -}; - -/** - * Renders one planned function, documentation included. - * - * @param {PlannedFunction} planned - The function to render. - * @returns {string} The rendered source. - */ -const renderFunction = (planned: PlannedFunction): string => { - const { spec } = planned; - const returnType = returnTypeOf(spec, planned); - const parameters = - spec.kind === "validator" - ? `${naming.snake(spec.input.name)}: object` - : ["value: object", ...planned.options.map((option) => `${option}: bool = False`)].join(", "); - - const absent = planned.nullable ? "None" : '""'; - const head = - spec.kind === "validator" - ? ` if not isinstance(${naming.snake(spec.input.name)}, str): - return False - - raw = ${naming.snake(spec.input.name)}` - : ` if value is None: - return ${absent} - - raw = value if isinstance(value, str) else str(value)`; - - const body = expandPipeline(planned.profile) - .map((step) => renderStep(step, spec, planned)) - .filter((rendered) => rendered !== "") - .join("\n"); - const tail = tailOf(spec, planned); - const constant = `_${naming.snake(spec.id).toUpperCase()}`; - const constants = expandPipeline(planned.profile) - .map((step) => { - if (step.op === "guard-shape") - return `${constant}_SHAPE = re.compile(${escapeLiteral(shapeRegex(step))})\n`; - - if (step.op === "guard-charset") { - const allowed = escapeLiteral(`\\A[${regexClass(step.allow)}]*\\Z`); - - return `${constant}_ALLOWED = re.compile(${allowed})\n`; - } - - return ""; - }) - .join(""); - - return `${constants} -def ${planned.name}(${parameters}) -> ${returnType}: - """${spec.summary} - - Profile: ${planned.profileName} — ${planned.profile.description} - -${spec.sources.map((source) => ` ${source.role === "official" ? "Official" : "Based on"}: ${source.url}`).join("\n")} - """ -${head} - -${body}${tail}`; -}; - -/** - * Emits every file of this target. - * - * @param {Plan} plan - The emission plan. - * @returns {Record} The files, by path relative to the target directory. - */ -export const emit = (plan: Plan): Record => { - const files: Record = { - "_spec_runtime.py": prelude(plan), - "brutils/__init__.py": "# Code generated from spec/utilities by spec/codegen. DO NOT EDIT.\n", - }; - const modules = new Map(); - - for (const planned of plan.functions) { - modules.set(planned.module, [...(modules.get(planned.module) ?? []), planned]); - } - - for (const [module, functions] of modules) { - const path = `${module.replaceAll(".", "/")}.py`; - const source = functions.map((planned) => renderFunction(planned)).join("\n\n\n"); - const symbols = [ - "trim_by", - "keep_by", - "match_shape", - "is_repeated", - "apply_pattern", - ...plan.charsets.map((charset) => `is_${charset.symbol}`), - ...plan.algorithms.map((entry) => `verify_${entry.symbol}`), - ].filter((symbol) => new RegExp(`\\b${symbol}\\b`).test(source)); - const typing = source.includes("Optional[str]") ? "from typing import Optional\n" : ""; - const regexImport = source.includes("re.compile") ? "import re\n" : ""; - const nonDigitsPattern = escapeLiteral(`[^${regexClass("ascii-digits")}]`); - const nonDigits = source.includes("_NON_DIGITS") - ? `_NON_DIGITS = re.compile(${nonDigitsPattern})\n\n` - : ""; - const importedSymbols = symbols.map((symbol) => ` ${symbol},`).join("\n"); - const runtimeImport = - symbols.length === 0 ? "" : `from _spec_runtime import (\n${importedSymbols}\n)\n`; - - files[path] = `# Code generated from spec/utilities by spec/codegen. DO NOT EDIT. -"""${functions.map((planned) => planned.spec.summary).join(" ")}""" - -${regexImport}${typing}${runtimeImport} - -${nonDigits}${source} -`; - } - - return files; -}; diff --git a/spec/codegen/targets/registry.ts b/spec/codegen/targets/registry.ts deleted file mode 100644 index f1af4782a..000000000 --- a/spec/codegen/targets/registry.ts +++ /dev/null @@ -1,20 +0,0 @@ -/** The language targets the specs can be emitted to, by id. */ -import { type Plan } from "../plan.ts"; -import { emit as emitGo } from "./go.ts"; -import { emit as emitJava } from "./java.ts"; -import { emit as emitPython } from "./python.ts"; -import { emit as emitRuby } from "./ruby.ts"; -import { emit as emitRust } from "./rust.ts"; -import { emit as emitTypeScript } from "./typescript.ts"; - -/** Maps a path relative to the target's output directory to the file's contents. */ -export type Emitter = (plan: Plan) => Record; - -export const emitters: Record = { - typescript: emitTypeScript, - python: emitPython, - go: emitGo, - ruby: emitRuby, - rust: emitRust, - java: emitJava, -}; diff --git a/spec/codegen/targets/ruby.ts b/spec/codegen/targets/ruby.ts deleted file mode 100644 index c10eeaebb..000000000 --- a/spec/codegen/targets/ruby.ts +++ /dev/null @@ -1,453 +0,0 @@ -/** - * Ruby emitter: module functions under `BrazilianUtils::*Utils`, keeping the `valid?` - * predicate name and the `nil` returning formatter the gem already exposes. - */ -import { type Step, type UtilitySpec, resolveCharset } from "../ir.ts"; -import { type Plan, type PlannedFunction, expandPipeline, naming } from "../plan.ts"; - -/** - * Renders a charset as the body of a regex character class, every code point written as a - * `\uXXXX` escape so that no character can be read as a class metacharacter or a range. - * - * @param {string|string[]} names - The charset name, or the union of several. - * @returns {string} The class body, without the brackets. - */ -/** - * Renders one code point as a regex escape. - * - * @param {number} code - The code point. - * @returns {string} The escape sequence. - */ -const escapeCodePoint = (code: number): string => { - const hex = code.toString(16); - - return code > 0xff_ff ? `\\u{${hex}}` : `\\u${hex.padStart(4, "0")}`; -}; - -const regexClass = (names: string | string[]): string => { - const { single, ranges } = resolveCharset(names); - const points = single.map((code) => escapeCodePoint(code)); - const spans = ranges.map(([from, to]) => `${escapeCodePoint(from)}-${escapeCodePoint(to)}`); - - return [...points, ...spans].join(""); -}; - -/** - * The regex a `guard-shape` step becomes, with one capture group per digit run. - * - * @param {Step} step - The guard-shape step. - * @returns {string} The regex source. - */ -const shapeRegex = (step: Extract): string => { - const edge = step.trim === undefined ? "" : `[${regexClass(step.trim)}]*`; - const separator = step.separators === undefined ? "" : `[${regexClass(step.separators)}]*`; - const digits = `[${regexClass("ascii-digits")}]`; - const groups = step.groups.map((size) => `(${digits}{${size}})`).join(separator); - - // `\A`/`\z` rather than `^`/`$`: in Ruby those are line anchors. - return `\\A${edge}${groups}${edge}\\z`; -}; - -/** - * Whether the profile matches a shape and then keeps the digits, which collapses into one regex. - * - * @param {PlannedFunction} planned - The planned function. - * @returns {boolean} True when the fast path applies. - */ -const hasShapeFastPath = (planned: PlannedFunction): boolean => { - const steps = expandPipeline(planned.profile); - - return ( - steps.some((step) => step.op === "guard-shape") && - steps.some((step) => step.op === "sanitize" && step.keep === "ascii-digits") - ); -}; - -/** - * The prefix of the module level constants belonging to one function. - * - * @param {PlannedFunction} planned - The planned function. - * @returns {string} The constant prefix. - */ -const constantPrefix = (planned: PlannedFunction): string => - naming.snake(planned.spec.id).toUpperCase(); - -/** - * Renders a string as a Ruby double quoted literal, where `#` also has to be escaped because - * `#{...}` would interpolate. - * - * @param {string} value - The text to render. - * @returns {string} The literal, quotes included. - */ -const escapeLiteral = (value: string): string => { - let literal = '"'; - - for (const char of value) { - const code = char.codePointAt(0) ?? 0; - - if (char === '"') literal += String.raw`\"`; - else if (char === "\\") literal += String.raw`\\`; - else if (char === "#") literal += String.raw`\#`; - else if (code < 0x20 || code > 0x7e) literal += `\\u{${code.toString(16)}}`; - else literal += char; - } - - return `${literal}"`; -}; - -/** - * Renders the membership test of a charset as an expression of the target language. - * - * @param {Plan} plan - The emission plan holding the resolved charsets. - * @param {string} name - The charset name. - * @returns {string} The boolean expression. - */ -const charsetTest = (plan: Plan, name: string): string => { - const found = plan.charsets.find((charset) => charset.name === name); - const { single, ranges } = found?.ranges ?? { single: [], ranges: [] }; - - return [ - ...single.map((code) => `code == 0x${code.toString(16)}`), - ...ranges.map( - ([from, to]) => `(code >= 0x${from.toString(16)} && code <= 0x${to.toString(16)})`, - ), - ].join(" ||\n "); -}; - -/** - * Renders the runtime shared by every generated utility of this target. - * - * @param {Plan} plan - The emission plan. - * @returns {string} The prelude source. - */ -const prelude = (plan: Plan): string => { - const charsets = plan.charsets - .map( - (charset) => ` # Whether the code point belongs to the ${charset.name} set. - def self.${charset.symbol}?(code) - ${charsetTest(plan, charset.name)} - end`, - ) - .join("\n\n"); - - const algorithms = plan.algorithms - .map((entry) => { - const { algorithm } = entry; - const body = - algorithm.weights.kind === "fixed" - ? ` weights = [${algorithm.weights.values.join(", ")}] - total = 0 - index = 0 - - while index < weights.length - total += (base.getbyte(index) - 48) * weights[index] - index += 1 - end` - : ` total = 0 - index = 0 - weight = base.length + 1 - - while index < base.length - total += (base.getbyte(index) - 48) * weight - weight -= 1 - index += 1 - end`; - - return ` # ${algorithm.description} - # - # Official source: ${algorithm.source} - def self.check_digit_${entry.symbol}(base) -${body} - digit = ${algorithm.modulus} - (total % ${algorithm.modulus}) - - digit >= ${algorithm.clamp.atLeast} ? ${algorithm.clamp.to} : digit - end - - # Whether every check digit of the value matches its base. - def self.verify_${entry.symbol}(digits) -${algorithm.positions - .map( - (position) => ` return false if digits.length <= ${position} - return false unless (digits.getbyte(${position}) - 48) == check_digit_${entry.symbol}(digits[0...${position}])`, - ) - .join("\n\n")} - - true - end`; - }) - .join("\n\n"); - - return `# frozen_string_literal: true - -# Code generated from spec/utilities by spec/codegen. DO NOT EDIT. - -module BrazilianUtils - # Helpers shared by the generated utilities. - module SpecRuntime -${charsets} - - # Strips the leading and trailing characters that belong to the set. - def self.trim_by(value, in_set) - chars = value.chars - start = 0 - last = chars.length - - start += 1 while start < last && in_set.call(chars[start].ord) - last -= 1 while last > start && in_set.call(chars[last - 1].ord) - - chars[start...last].join - end - - # Keeps only the characters that belong to the set. - def self.keep_by(value, in_set) - value.chars.select { |char| in_set.call(char.ord) }.join - end - - # Whether the value is exactly the digit groups, optionally separated. - def self.match_shape(value, groups, in_separator = nil) - chars = value.chars - index = 0 - - groups.each_with_index do |size, position| - if position.positive? && !in_separator.nil? - index += 1 while index < chars.length && in_separator.call(chars[index].ord) - end - - size.times do - return false if index >= chars.length || !ascii_digits?(chars[index].ord) - - index += 1 - end - end - - index == chars.length - end - - # Whether the value is a non empty run of one repeated character. - def self.is_repeated(value) - !value.empty? && value == value[0] * value.length - end - - # Lays the value over the pattern: "0" copies, "*" hides, anything else separates. - def self.apply_pattern(value, pattern, pad) - padded = value - - if pad - slots = pattern.chars.count { |char| ['0', '*'].include?(char) } - padded = value.rjust(slots, '0') - end - - formatted = +'' - index = 0 - - pattern.each_char do |char| - if ['0', '*'].include?(char) - break if index >= padded.length - - formatted << (char == '*' ? '*' : padded[index]) - index += 1 - elsif index < padded.length - formatted << char - end - end - - formatted - end - -${algorithms} - end -end -`; -}; - -/** - * The value the generated function returns when a guard rejects the input. - * - * @param {UtilitySpec} spec - The utility being emitted. - * @param {PlannedFunction} planned - The planned function. - * @returns {string} The literal to return. - */ -const bailValue = (spec: UtilitySpec, planned: PlannedFunction): string => { - if (spec.kind === "validator") return "false"; - - return planned.nullable ? "nil" : "''"; -}; - -/** - * Renders one pipeline step as statements of the target language. - * - * @param {Step} step - The step to render. - * @param {UtilitySpec} spec - The utility being emitted. - * @param {PlannedFunction} planned - The planned function. - * @returns {string} The rendered statements. - */ -const renderStep = (step: Step, spec: UtilitySpec, planned: PlannedFunction): string => { - const bail = bailValue(spec, planned); - const runtime = "BrazilianUtils::SpecRuntime"; - - const constant = constantPrefix(planned); - - switch (step.op) { - case "guard-shape": { - return ` match = ${constant}_SHAPE.match(raw) - return ${bail} if match.nil? - - digits = match.captures.join`; - } - case "guard-charset": { - return ` return ${bail} if ${constant}_ALLOWED.match(raw).nil?`; - } - case "sanitize": { - // Already bound by the shape guard's capture groups. - if (hasShapeFastPath(planned)) return ""; - - return ` digits = raw.gsub(NON_DIGITS, '')`; - } - case "guard-length": { - return ` return ${bail} unless digits.length == ${step.equals}`; - } - case "guard-repeated": { - return ` return ${bail} if ${runtime}.is_repeated(digits)`; - } - case "verify-check-digits": { - return ` return ${bail} unless ${runtime}.verify_${naming.snake(step.checkDigit)}(digits)`; - } - case "apply-pattern": { - const pattern = - step.variants?.["obfuscate"] !== undefined && planned.options.includes("obfuscate") - ? `obfuscate ? ${escapeLiteral(step.variants["obfuscate"])} : ${escapeLiteral(step.pattern)}` - : escapeLiteral(step.pattern); - const pad = planned.options.includes("pad") ? "pad" : "false"; - - return ` ${runtime}.apply_pattern(digits, ${pattern}, ${pad})`; - } - case "guard-valid": { - // `expandPipeline` replaces this step with the referenced profile's own steps. - throw new Error(`${spec.id}: guard-valid reached the emitter unexpanded`); - } - default: { - throw new Error(`unsupported step: ${JSON.stringify(step)}`); - } - } -}; - -/** - * What closes the generated body: the success value, or nothing when a step already returned. - * - * @param {UtilitySpec} spec - The utility being emitted. - * @param {PlannedFunction} planned - The planned function. - * @returns {string} The closing lines, which may be empty. - */ -const tailOf = (spec: UtilitySpec, planned: PlannedFunction): string => { - if (spec.kind === "validator") return "\n\n true"; - - const returnsEarly = expandPipeline(planned.profile).some((step) => step.op === "apply-pattern"); - - return returnsEarly ? "" : "\n\n digits"; -}; - -/** - * Renders one planned function, documentation included. - * - * @param {PlannedFunction} planned - The function to render. - * @returns {string} The rendered source. - */ -const renderFunction = (planned: PlannedFunction): string => { - const { spec } = planned; - const parameters = [ - naming.snake(spec.input.name), - ...planned.options.map((option) => `${option} = false`), - ].join(", "); - - const absent = planned.nullable ? "nil" : "''"; - const head = - spec.kind === "validator" - ? ` return false unless ${naming.snake(spec.input.name)}.is_a?(String) - - raw = ${naming.snake(spec.input.name)}` - : ` return ${absent} if ${naming.snake(spec.input.name)}.nil? - - raw = ${naming.snake(spec.input.name)}.to_s`; - - const body = expandPipeline(planned.profile) - .map((step) => renderStep(step, spec, planned)) - .filter((rendered) => rendered !== "") - .join("\n"); - const tail = tailOf(spec, planned); - const constant = constantPrefix(planned); - const constants = expandPipeline(planned.profile) - .map((step) => { - if (step.op === "guard-shape") - return ` ${constant}_SHAPE = Regexp.new(${escapeLiteral(shapeRegex(step))}).freeze\n`; - - if (step.op === "guard-charset") { - const allowed = escapeLiteral(`\\A[${regexClass(step.allow)}]*\\z`); - - return ` ${constant}_ALLOWED = Regexp.new(${allowed}).freeze\n`; - } - - return ""; - }) - .join(""); - - return `${constants} - # ${spec.summary} - # - # Profile: ${planned.profileName} — ${planned.profile.description} - # -${spec.sources.map((source) => ` # ${source.role === "official" ? "Official" : "Based on"}: ${source.url}`).join("\n")} - def self.${planned.name}(${parameters}) -${head} - -${body}${tail} - end`; -}; - -/** - * Emits every file of this target. - * - * @param {Plan} plan - The emission plan. - * @returns {Record} The files, by path relative to the target directory. - */ -export const emit = (plan: Plan): Record => { - const files: Record = { "brazilian-utils/spec_runtime.rb": prelude(plan) }; - const modules = new Map(); - - for (const planned of plan.functions) { - modules.set(planned.module, [...(modules.get(planned.module) ?? []), planned]); - } - - const nonDigitsPattern = escapeLiteral(`[^${regexClass("ascii-digits")}]`); - - for (const [module, functions] of modules) { - const shortName = module.split("::").at(-1) ?? module; - const fileName = shortName - .replace(/Utils$/, "") - .replaceAll(/([a-z])([A-Z])/g, "$1-$2") - .toLowerCase(); - - files[`brazilian-utils/${fileName}-utils.rb`] = `# frozen_string_literal: true - -# Code generated from spec/utilities by spec/codegen. DO NOT EDIT. - -require_relative 'spec_runtime' - -module BrazilianUtils - # ${functions.map((planned) => planned.spec.summary).join(" ")} - module ${shortName}${ - functions.some( - (planned) => - !hasShapeFastPath(planned) && - expandPipeline(planned.profile).some((step) => step.op === "sanitize"), - ) - ? `\n NON_DIGITS = Regexp.new(${nonDigitsPattern}).freeze\n` - : "" - } -${functions.map((planned) => renderFunction(planned)).join("\n\n")} - end -end -`; - } - - return files; -}; diff --git a/spec/codegen/targets/rust.ts b/spec/codegen/targets/rust.ts deleted file mode 100644 index cfd8bf0fe..000000000 --- a/spec/codegen/targets/rust.ts +++ /dev/null @@ -1,374 +0,0 @@ -/** - * Rust emitter: one module per document, `&str` in, `bool`/`Option` out, matching the - * signatures the crate already publishes. - */ -import { type Step, type UtilitySpec } from "../ir.ts"; -import { type Plan, type PlannedFunction, expandPipeline, naming } from "../plan.ts"; - -/** - * Renders a string as a Rust literal. - * - * @param {string} value - The text to render. - * @returns {string} The literal, quotes included. - */ -const escapeLiteral = (value: string): string => { - let literal = '"'; - - for (const char of value) { - const code = char.codePointAt(0) ?? 0; - - if (char === '"') literal += String.raw`\"`; - else if (char === "\\") literal += String.raw`\\`; - else if (code < 0x20 || code > 0x7e) literal += `\\u{${code.toString(16)}}`; - else literal += char; - } - - return `${literal}"`; -}; - -/** - * Renders the membership test of a charset as an expression of the target language. - * - * @param {Plan} plan - The emission plan holding the resolved charsets. - * @param {string} name - The charset name. - * @returns {string} The boolean expression. - */ -const charsetTest = (plan: Plan, name: string): string => { - const found = plan.charsets.find((charset) => charset.name === name); - const { single, ranges } = found?.ranges ?? { single: [], ranges: [] }; - - return [ - ...single.map((code) => `code == 0x${code.toString(16)}`), - ...ranges.map( - ([from, to]) => `(0x${from.toString(16)}..=0x${to.toString(16)}).contains(&code)`, - ), - ].join("\n || "); -}; - -/** - * Renders the runtime shared by every generated utility of this target. - * - * @param {Plan} plan - The emission plan. - * @returns {string} The prelude source. - */ -const prelude = (plan: Plan): string => { - const charsets = plan.charsets - .map( - (charset) => `/// Whether the code point belongs to the ${charset.name} set. -pub fn is_${charset.symbol}(code: u32) -> bool { - ${charsetTest(plan, charset.name)} -}`, - ) - .join("\n\n"); - - const algorithms = plan.algorithms - .map((entry) => { - const { algorithm } = entry; - const body = - algorithm.weights.kind === "fixed" - ? ` const WEIGHTS: [u32; ${algorithm.weights.values.length}] = [${algorithm.weights.values.join(", ")}]; - - let sum: u32 = base - .bytes() - .zip(WEIGHTS.iter()) - .map(|(byte, weight)| u32::from(byte - b'0') * weight) - .sum();` - : ` let length = base.len() as u32; - let sum: u32 = base - .bytes() - .enumerate() - .map(|(index, byte)| u32::from(byte - b'0') * (length + 1 - index as u32)) - .sum();`; - - return `/// ${algorithm.description} -/// -/// Official source: ${algorithm.source} -pub fn check_digit_${entry.symbol}(base: &str) -> u32 { -${body} - - let digit = ${algorithm.modulus} - (sum % ${algorithm.modulus}); - - if digit >= ${algorithm.clamp.atLeast} { - ${algorithm.clamp.to} - } else { - digit - } -} - -/// Whether every check digit of the value matches its base. -pub fn verify_${entry.symbol}(digits: &str) -> bool { - [${algorithm.positions.join(", ")}].iter().all(|&position: &usize| { - digits.len() > position - && u32::from(digits.as_bytes()[position] - b'0') - == check_digit_${entry.symbol}(&digits[..position]) - }) -}`; - }) - .join("\n\n"); - - return `// Code generated from spec/utilities by spec/codegen. DO NOT EDIT. - -//! Helpers shared by the generated utilities. - -${charsets} - -/// Strips the leading and trailing characters that belong to the set. -pub fn trim_by(value: &str, in_set: fn(u32) -> bool) -> &str { - value.trim_matches(|char: char| in_set(char as u32)) -} - -/// Keeps only the characters that belong to the set. -pub fn keep_by(value: &str, in_set: fn(u32) -> bool) -> String { - value.chars().filter(|char| in_set(*char as u32)).collect() -} - -/// Whether the value is exactly the digit groups, optionally separated. -pub fn match_shape(value: &str, groups: &[usize], in_separator: Option bool>) -> bool { - let chars: Vec = value.chars().collect(); - let mut index = 0; - - for (position, size) in groups.iter().enumerate() { - if position > 0 { - if let Some(separator) = in_separator { - while index < chars.len() && separator(chars[index] as u32) { - index += 1; - } - } - } - - for _ in 0..*size { - if index >= chars.len() || !is_ascii_digits(chars[index] as u32) { - return false; - } - - index += 1; - } - } - - index == chars.len() -} - -/// Whether the value is a non empty run of one repeated character. -pub fn is_repeated(value: &str) -> bool { - match value.chars().next() { - None => false, - Some(first) => value.chars().all(|char| char == first), - } -} - -/// Lays the value over the pattern: '0' copies, '*' hides, anything else separates. -pub fn apply_pattern(value: &str, pattern: &str, pad: bool) -> String { - let slots = pattern.chars().filter(|char| *char == '0' || *char == '*').count(); - let padded = if pad && value.chars().count() < slots { - format!("{}{}", "0".repeat(slots - value.chars().count()), value) - } else { - value.to_string() - }; - - let source: Vec = padded.chars().collect(); - let mut formatted = String::new(); - let mut index = 0; - - for char in pattern.chars() { - if char == '0' || char == '*' { - if index >= source.len() { - break; - } - - formatted.push(if char == '*' { '*' } else { source[index] }); - index += 1; - } else if index < source.len() { - formatted.push(char); - } - } - - formatted -} - -${algorithms} -`; -}; - -/** - * The value the generated function returns when a guard rejects the input. - * - * @param {UtilitySpec} spec - The utility being emitted. - * @param {PlannedFunction} planned - The planned function. - * @returns {string} The literal to return. - */ -const bailValue = (spec: UtilitySpec, planned: PlannedFunction): string => { - if (spec.kind === "validator") return "false"; - - return planned.nullable ? "None" : "String::new()"; -}; - -/** - * Renders one pipeline step as statements of the target language. - * - * @param {Step} step - The step to render. - * @param {UtilitySpec} spec - The utility being emitted. - * @param {PlannedFunction} planned - The planned function. - * @returns {string} The rendered statements. - */ -const renderStep = (step: Step, spec: UtilitySpec, planned: PlannedFunction): string => { - const bail = bailValue(spec, planned); - - switch (step.op) { - case "guard-shape": { - const value = - step.trim === undefined - ? "raw" - : `spec_runtime::trim_by(raw, spec_runtime::is_${naming.snake(step.trim)})`; - const separators = - step.separators === undefined - ? "None" - : `Some(spec_runtime::is_${naming.snake(step.separators)} as fn(u32) -> bool)`; - - return ` if !spec_runtime::match_shape(${value}, &[${step.groups.join(", ")}], ${separators}) { - return ${bail}; - }`; - } - case "guard-charset": { - return ` for char in raw.chars() { - let code = char as u32; - - if !(${step.allow.map((name) => `spec_runtime::is_${naming.snake(name)}(code)`).join(" || ")}) { - return ${bail}; - } - }`; - } - case "sanitize": { - return ` let digits = spec_runtime::keep_by(raw, spec_runtime::is_${naming.snake(step.keep)});`; - } - case "guard-length": { - return ` if digits.len() != ${step.equals} { - return ${bail}; - }`; - } - case "guard-repeated": { - return ` if spec_runtime::is_repeated(&digits) { - return ${bail}; - }`; - } - case "verify-check-digits": { - return ` if !spec_runtime::verify_${naming.snake(step.checkDigit)}(&digits) { - return ${bail}; - }`; - } - case "apply-pattern": { - const pattern = - step.variants?.["obfuscate"] !== undefined && planned.options.includes("obfuscate") - ? `if obfuscate { ${escapeLiteral(step.variants["obfuscate"])} } else { ${escapeLiteral(step.pattern)} }` - : escapeLiteral(step.pattern); - const pad = planned.options.includes("pad") ? "pad" : "false"; - const call = `spec_runtime::apply_pattern(&digits, ${pattern}, ${pad})`; - const wrapped = planned.nullable ? `Some(${call})` : call; - - return ` ${wrapped}`; - } - case "guard-valid": { - // `expandPipeline` replaces this step with the referenced profile's own steps. - throw new Error(`${spec.id}: guard-valid reached the emitter unexpanded`); - } - default: { - throw new Error(`unsupported step: ${JSON.stringify(step)}`); - } - } -}; - -/** - * The return type the generated function declares. - * - * @param {UtilitySpec} spec - The utility being emitted. - * @param {PlannedFunction} planned - The planned function. - * @returns {string} The type, spelled in the target language. - */ -const returnTypeOf = (spec: UtilitySpec, planned: PlannedFunction): string => { - if (spec.kind === "validator") return "bool"; - - return planned.nullable ? "Option" : "String"; -}; - -/** - * What closes the generated body: the success value, or nothing when a step already returned. - * - * @param {UtilitySpec} spec - The utility being emitted. - * @param {PlannedFunction} planned - The planned function. - * @returns {string} The closing lines, which may be empty. - */ -const tailOf = (spec: UtilitySpec, planned: PlannedFunction): string => { - if (spec.kind === "validator") return "\n\n true"; - - const returnsEarly = expandPipeline(planned.profile).some((step) => step.op === "apply-pattern"); - - return returnsEarly ? "" : "\n\n digits"; -}; - -/** - * Renders one planned function, documentation included. - * - * @param {PlannedFunction} planned - The function to render. - * @returns {string} The rendered source. - */ -const renderFunction = (planned: PlannedFunction): string => { - const { spec } = planned; - const returns = returnTypeOf(spec, planned); - const parameters = [ - `${naming.snake(spec.input.name)}: &str`, - ...planned.options.map((option) => `${option}: bool`), - ].join(", "); - - // Rust's type system already rejects the non string inputs the dynamic targets guard against. - const head = ` let raw = ${naming.snake(spec.input.name)};`; - const body = expandPipeline(planned.profile) - .map((step) => renderStep(step, spec, planned)) - .join("\n"); - const tail = tailOf(spec, planned); - - return `/// ${spec.summary} -/// -/// Profile: ${planned.profileName} — ${planned.profile.description} -/// -${spec.sources.map((source) => `/// ${source.role === "official" ? "Official" : "Based on"}: ${source.url}`).join("\n")} -pub fn ${planned.name}(${parameters}) -> ${returns} { -${head} - -${body}${tail} -}`; -}; - -/** - * Emits every file of this target. - * - * @param {Plan} plan - The emission plan. - * @returns {Record} The files, by path relative to the target directory. - */ -export const emit = (plan: Plan): Record => { - const files: Record = { "spec_runtime.rs": prelude(plan) }; - const modules = new Map(); - - for (const planned of plan.functions) { - modules.set(planned.module, [...(modules.get(planned.module) ?? []), planned]); - } - - for (const [module, functions] of modules) { - files[`${module}.rs`] = `// Code generated from spec/utilities by spec/codegen. DO NOT EDIT. - -//! ${functions.map((planned) => planned.spec.summary).join(" ")} - -use crate::spec_runtime; - -${functions.map((planned) => renderFunction(planned)).join("\n\n")} -`; - } - - files["lib.rs"] = `// Code generated from spec/utilities by spec/codegen. DO NOT EDIT. - -//! Generated Brazilian Utils, emitted from the language neutral specs. - -pub mod spec_runtime; -${[...modules.keys()].map((module) => `pub mod ${module};`).join("\n")} -`; - - return files; -}; diff --git a/spec/codegen/targets/typescript.ts b/spec/codegen/targets/typescript.ts deleted file mode 100644 index 561f27fdc..000000000 --- a/spec/codegen/targets/typescript.ts +++ /dev/null @@ -1,364 +0,0 @@ -/** - * TypeScript emitter: produces modules shaped like the ones under `src/`, so the generated - * output can be diffed against the handwritten package it is meant to replace. - */ -import { type Step, type UtilitySpec } from "../ir.ts"; -import { type Plan, type PlannedFunction, expandPipeline, naming } from "../plan.ts"; - -/** - * Renders a string as a TypeScript literal. - * - * @param {string} value - The text to render. - * @returns {string} The literal, quotes included. - */ -const escapeLiteral = (value: string): string => { - let literal = '"'; - - for (const char of value) { - const code = char.codePointAt(0) ?? 0; - - if (char === '"') literal += String.raw`\"`; - else if (char === "\\") literal += String.raw`\\`; - else if (code < 0x20 || code > 0x7e) literal += `\\u{${code.toString(16)}}`; - else literal += char; - } - - return `${literal}"`; -}; - -/** - * Renders the membership test of a charset as an expression of the target language. - * - * @param {Plan} plan - The emission plan holding the resolved charsets. - * @param {string} name - The charset name. - * @returns {string} The boolean expression. - */ -const charsetTest = (plan: Plan, name: string): string => { - const { single, ranges } = plan.charsets.find((charset) => charset.name === name)?.ranges ?? { - single: [], - ranges: [], - }; - const tests = [ - ...single.map((code) => `code === 0x${code.toString(16)}`), - ...ranges.map( - ([from, to]) => `(code >= 0x${from.toString(16)} && code <= 0x${to.toString(16)})`, - ), - ]; - - return tests.join(" ||\n\t"); -}; - -/** - * Renders the runtime shared by every generated utility of this target. - * - * @param {Plan} plan - The emission plan. - * @returns {string} The prelude source. - */ -const prelude = (plan: Plan): string => { - const charsets = plan.charsets - .map( - ( - charset, - ) => `/** ${charset.name}: ${charset.ranges.single.length + charset.ranges.ranges.length} code point runs. */ -export const is${naming.pascal(charset.name)} = (code: number): boolean => - ${charsetTest(plan, charset.name)};`, - ) - .join("\n\n"); - - const algorithms = plan.algorithms - .map((entry) => { - const { algorithm } = entry; - const body = - algorithm.weights.kind === "fixed" - ? ` const weights = [${algorithm.weights.values.join(", ")}]; - let sum = 0; - - for (let index = 0; index < weights.length; index++) { - sum += (base.charCodeAt(index) - 48) * weights[index]; - }` - : ` let sum = 0; - let weight = base.length + 1; - - for (let index = 0; index < base.length; index++) { - sum += (base.charCodeAt(index) - 48) * weight; - weight--; - }`; - - return `/** - * ${algorithm.description} - * - * @see Official: ${algorithm.source} - */ -export const checkDigit${naming.pascal(entry.name)} = (base: string): number => { -${body} - - const digit = ${algorithm.modulus} - (sum % ${algorithm.modulus}); - - return digit >= ${algorithm.clamp.atLeast} ? ${algorithm.clamp.to} : digit; -}; - -export const verify${naming.pascal(entry.name)} = (digits: string): boolean => { - for (const position of [${algorithm.positions.join(", ")}]) { - if (digits.length <= position) return false; - if (digits.charCodeAt(position) - 48 !== checkDigit${naming.pascal(entry.name)}(digits.slice(0, position))) - return false; - } - - return true; -};`; - }) - .join("\n\n"); - - return `// Code generated from spec/utilities by spec/codegen. DO NOT EDIT. - -${charsets} - -export const trimBy = (value: string, inSet: (code: number) => boolean): string => { - let start = 0; - let end = value.length; - - while (start < end && inSet(value.charCodeAt(start))) start++; - while (end > start && inSet(value.charCodeAt(end - 1))) end--; - - return value.slice(start, end); -}; - -export const keepBy = (value: string, inSet: (code: number) => boolean): string => { - let kept = ""; - - for (let index = 0; index < value.length; index++) { - if (inSet(value.charCodeAt(index))) kept += value.charAt(index); - } - - return kept; -}; - -export const matchShape = ( - value: string, - groups: number[], - inSeparator?: (code: number) => boolean, -): boolean => { - let index = 0; - - for (const [position, size] of groups.entries()) { - if (position > 0 && inSeparator !== undefined) { - while (index < value.length && inSeparator(value.charCodeAt(index))) index++; - } - - for (let digit = 0; digit < size; digit++) { - if (index >= value.length || !isAsciiDigits(value.charCodeAt(index))) return false; - index++; - } - } - - return index === value.length; -}; - -export const isRepeated = (value: string): boolean => - value !== "" && value === value.charAt(0).repeat(value.length); - -export const applyPattern = (value: string, pattern: string, pad: boolean): string => { - let padded = value; - - if (pad) { - const slots = [...pattern].filter((char) => char === "0" || char === "*").length; - padded = value.padStart(slots, "0"); - } - - let formatted = ""; - let index = 0; - - for (const char of pattern) { - if (char === "0" || char === "*") { - if (index >= padded.length) break; - formatted += char === "*" ? "*" : padded.charAt(index); - index++; - } else if (index < padded.length) { - formatted += char; - } - } - - return formatted; -}; - -${algorithms} -`; -}; - -const reject = (spec: UtilitySpec): string => (spec.kind === "validator" ? "false" : '""'); - -/** - * Renders one pipeline step as statements of the target language. - * - * @param {Step} step - The step to render. - * @param {UtilitySpec} spec - The utility being emitted. - * @param {PlannedFunction} planned - The planned function. - * @returns {string} The rendered statements. - */ -const renderStep = (step: Step, spec: UtilitySpec, planned: PlannedFunction): string => { - const bail = planned.nullable ? "null" : reject(spec); - - switch (step.op) { - case "guard-shape": { - const value = step.trim === undefined ? "raw" : `trimBy(raw, is${naming.pascal(step.trim)})`; - const separators = - step.separators === undefined ? "" : `, is${naming.pascal(step.separators)}`; - - return ` if (!matchShape(${value}, [${step.groups.join(", ")}]${separators})) return ${bail};`; - } - case "guard-charset": { - return ` for (let index = 0; index < raw.length; index++) { - const code = raw.charCodeAt(index); - - if (!(${step.allow.map((name) => `is${naming.pascal(name)}(code)`).join(" || ")})) return ${bail}; - }`; - } - case "sanitize": { - return ` const digits = keepBy(raw, is${naming.pascal(step.keep)});`; - } - case "guard-length": { - return ` if (digits.length !== ${step.equals}) return ${bail};`; - } - case "guard-repeated": { - return ` if (isRepeated(digits)) return ${bail};`; - } - case "verify-check-digits": { - return ` if (!verify${naming.pascal(step.checkDigit)}(digits)) return ${bail};`; - } - case "apply-pattern": { - const pattern = - step.variants?.["obfuscate"] !== undefined && planned.options.includes("obfuscate") - ? `(options?.obfuscate ?? false) ? ${escapeLiteral(step.variants["obfuscate"])} : ${escapeLiteral(step.pattern)}` - : escapeLiteral(step.pattern); - const pad = planned.options.includes("pad") ? "options?.pad ?? false" : "false"; - - return ` return applyPattern(digits, ${pattern}, ${pad});`; - } - case "guard-valid": { - // `expandPipeline` replaces this step with the referenced profile's own steps. - throw new Error(`${spec.id}: guard-valid reached the emitter unexpanded`); - } - default: { - throw new Error(`unsupported step: ${JSON.stringify(step)}`); - } - } -}; - -/** - * The return type the generated function declares. - * - * @param {UtilitySpec} spec - The utility being emitted. - * @param {PlannedFunction} planned - The planned function. - * @returns {string} The type, spelled in the target language. - */ -const returnTypeOf = (spec: UtilitySpec, planned: PlannedFunction): string => { - if (spec.kind === "validator") return "boolean"; - - return planned.nullable ? "string | null" : "string"; -}; - -/** - * What closes the generated body: the success value, or nothing when a step already returned. - * - * @param {UtilitySpec} spec - The utility being emitted. - * @param {boolean} needsSanitize - Whether the pipeline never bound `digits`. - * @returns {string} The closing lines, which may be empty. - */ -const tailOf = (spec: UtilitySpec, needsSanitize: boolean): string => { - if (spec.kind === "validator") return "\n\n return true;"; - - return needsSanitize ? "\n\n return digits;" : ""; -}; - -/** - * Renders one planned function, documentation included. - * - * @param {PlannedFunction} planned - The function to render. - * @returns {string} The rendered source. - */ -const renderFunction = (planned: PlannedFunction): string => { - const { spec } = planned; - const optionsType = `${naming.pascal(spec.id)}Options`; - const hasOptions = planned.options.length > 0; - const returnType = returnTypeOf(spec, planned); - const parameter = - spec.kind === "validator" ? `${spec.input.name}: unknown` : `value: string | number`; - const optionsParameter = hasOptions ? `, options?: ${optionsType}` : ""; - - const absent = planned.nullable ? "null" : '""'; - const head = - spec.kind === "validator" - ? ` if (typeof ${spec.input.name} !== "string") return false; - - const raw = ${spec.input.name};` - : ` if (value === null || value === undefined) return ${absent}; - - const raw = String(value);`; - - // A pipeline that never sanitizes still needs `digits` in scope for the closing return. - const needsSanitize = !expandPipeline(planned.profile).some((step) => step.op === "sanitize"); - const body = expandPipeline(planned.profile) - .map((step) => renderStep(step, spec, planned)) - .join("\n"); - const tail = tailOf(spec, needsSanitize); - - const options = hasOptions - ? `/** Options of \`${planned.name}\`. */ -export type ${optionsType} = { -${planned.options.map((option) => ` /** ${option === "pad" ? "Left pads the value with zeros up to the pattern's slot count" : "Hides the digits the pattern marks with \\`*\\`"} (default: \`false\`). */\n ${option}?: boolean;`).join("\n")} -}; - -` - : ""; - - return `${options}/** - * ${spec.summary} - * - * Profile: \`${planned.profileName}\` — ${planned.profile.description} - * -${spec.sources.map((source) => ` * @see ${source.role === "official" ? "Official" : "Based on"}: ${source.url}`).join("\n")} - */ -export const ${planned.name} = (${parameter}${optionsParameter}): ${returnType} => { -${head} - -${body}${tail} -}; -`; -}; - -/** - * Emits every file of this target. - * - * @param {Plan} plan - The emission plan. - * @returns {Record} The files, by path relative to the target directory. - */ -export const emit = (plan: Plan): Record => { - const files: Record = { "_spec/runtime.ts": prelude(plan) }; - - for (const planned of plan.functions) { - const imports = new Set(); - const source = renderFunction(planned); - - for (const symbol of [ - "trimBy", - "keepBy", - "matchShape", - "isRepeated", - "applyPattern", - ...plan.charsets.map((charset) => `is${naming.pascal(charset.name)}`), - ...plan.algorithms.map((entry) => `verify${naming.pascal(entry.name)}`), - ]) { - if (new RegExp(`\\b${symbol}\\b`).test(source)) imports.add(symbol); - } - - files[`${planned.module}/${planned.module}.ts`] = - `// Code generated from spec/utilities/${planned.spec.id}.json by spec/codegen. DO NOT EDIT.\nimport {\n${[ - ...imports, - ] - .sort() - .map((symbol) => `\t${symbol},`) - .join("\n")}\n} from "../_spec/runtime.ts";\n\n${source}`; - } - - return files; -}; diff --git a/spec/codegen/vectors.ts b/spec/codegen/vectors.ts deleted file mode 100644 index 8fd5b1589..000000000 --- a/spec/codegen/vectors.ts +++ /dev/null @@ -1,81 +0,0 @@ -/** - * Builds the conformance vectors: the corpus, plus the output the reference interpreter - * produces for every profile of every utility. - * - * The file is stored column wise (one array per profile, indexed by corpus position) because it - * is meant to be committed and read by six languages, and it records every profile, not only the - * one a given package adopts, so a package that wants to move between profiles can see exactly - * which inputs change answer. - */ -import { writeFileSync } from "node:fs"; -import { resolve } from "node:path"; - -import { buildCorpus } from "./corpus.ts"; -import { type RunOptions, run, setLoader } from "./interpret.ts"; -import { loadAll, loadUtility, specRoot } from "./ir.ts"; - -setLoader(loadUtility); - -export type Vectors = { - corpus: string[]; - utilities: Record< - string, - { - kind: "validator" | "formatter"; - optionSets: RunOptions[]; - /** One entry per corpus input; a formatter entry holds one output per option set. */ - profiles: Record; - } - >; -}; - -const optionSetsFor = (options: string[]): RunOptions[] => { - let sets: RunOptions[] = [{}]; - - for (const option of options) sets = sets.flatMap((set) => [set, { ...set, [option]: true }]); - - return sets; -}; - -export const build = (size: number): Vectors => { - const corpus = buildCorpus(size).slice(0, size); - const utilities: Vectors["utilities"] = {}; - - for (const spec of loadAll()) { - const options = [ - ...new Set(Object.values(spec.adopted).flatMap((adoption) => adoption.options ?? [])), - ]; - const optionSets = spec.kind === "formatter" ? optionSetsFor(options) : [{}]; - const profiles: Vectors["utilities"][string]["profiles"] = {}; - - for (const profile of Object.keys(spec.profiles)) { - profiles[profile] = - spec.kind === "validator" - ? corpus.map((input) => run(spec, profile, input) as boolean) - : corpus.map((input) => - optionSets.map((set) => run(spec, profile, input, set) as string | null), - ); - } - - utilities[spec.id] = { kind: spec.kind, optionSets, profiles }; - } - - return { corpus, utilities }; -}; - -if (process.argv[1]?.endsWith("vectors.ts")) { - const size = Number(process.argv[2] ?? 750); - const vectors = build(size); - const path = resolve(specRoot, "vectors/conformance.json"); - - writeFileSync(path, `${JSON.stringify(vectors)}\n`); - - const checks = Object.values(vectors.utilities).reduce( - (total, utility) => - total + - Object.keys(utility.profiles).length * vectors.corpus.length * utility.optionSets.length, - 0, - ); - - console.log(`wrote ${path} — ${vectors.corpus.length} inputs, ${checks} expectations`); -} diff --git a/spec/conformance/differential-javascript.ts b/spec/conformance/differential-javascript.ts deleted file mode 100644 index 49715560d..000000000 --- a/spec/conformance/differential-javascript.ts +++ /dev/null @@ -1,132 +0,0 @@ -/** - * Differential test between the reference interpreter and the implementation this repository - * actually ships, over the whole corpus. - * - * It answers the only question that matters before any code generation: does the spec describe - * the contract the published package already has, exactly, or a slightly different one? - */ -import { mkdtempSync, rmSync } from "node:fs"; -import { tmpdir } from "node:os"; -import { join, resolve } from "node:path"; - -import { build } from "esbuild"; - -import { buildCorpus } from "../codegen/corpus.ts"; -import { type RunOptions, run, setLoader } from "../codegen/interpret.ts"; -import { loadUtility } from "../codegen/ir.ts"; - -setLoader(loadUtility); - -const root = resolve(import.meta.dirname, "../.."); -const outDir = mkdtempSync(join(tmpdir(), "brutils-diff-")); -const outFile = join(outDir, "bundle.mjs"); - -await build({ - entryPoints: [join(root, "src/index.ts")], - bundle: true, - format: "esm", - platform: "neutral", - outfile: outFile, - logLevel: "error", -}); - -const shipped = (await import(outFile)) as { - isValidCpf: (value: unknown) => boolean; - isValidPis: (value: unknown) => boolean; - formatCpf: (value: unknown, options?: RunOptions) => string; -}; - -const corpus = buildCorpus(); -const isValidCpf = loadUtility("is-valid-cpf"); -const isValidPis = loadUtility("is-valid-pis"); -const formatCpf = loadUtility("format-cpf"); - -type Check = { - utility: string; - input: string; - options?: RunOptions; - spec: unknown; - shipped: unknown; -}; - -const mismatches: Check[] = []; - -/** - * Records a check, keeping it only when the two implementations disagree. - * - * @param {Check} check - What was run and what each side answered. - * @returns {void} - */ -const compare = (check: Check): void => { - if (check.spec !== check.shipped) mismatches.push(check); -}; - -const optionSets: RunOptions[] = [ - {}, - { pad: true }, - { obfuscate: true }, - { pad: true, obfuscate: true }, -]; - -for (const input of corpus) { - compare({ - utility: "isValidCpf", - input, - spec: run(isValidCpf, "masked-strict", input), - shipped: shipped.isValidCpf(input), - }); - compare({ - utility: "isValidPis", - input, - spec: run(isValidPis, "masked-charset", input), - shipped: shipped.isValidPis(input), - }); - - for (const options of optionSets) { - compare({ - utility: "formatCpf", - input, - options, - spec: run(formatCpf, "pattern-partial", input, options), - shipped: shipped.formatCpf(input, options), - }); - } -} - -// Inputs that are not strings at all: the packages promise never to throw on them. -const hostile: unknown[] = [null, undefined, 12_345_678_909, Number.NaN, 0, -1, true, [], {}, 1.5]; - -for (const input of hostile) { - compare({ - utility: "isValidCpf", - input: String(input), - spec: run(isValidCpf, "masked-strict", input), - shipped: shipped.isValidCpf(input), - }); - compare({ - utility: "isValidPis", - input: String(input), - spec: run(isValidPis, "masked-charset", input), - shipped: shipped.isValidPis(input), - }); - compare({ - utility: "formatCpf", - input: String(input), - spec: run(formatCpf, "pattern-partial", input), - shipped: shipped.formatCpf(input), - }); -} - -rmSync(outDir, { recursive: true, force: true }); - -const checks = corpus.length * (2 + optionSets.length) + hostile.length * 3; - -if (mismatches.length > 0) { - console.error(`${mismatches.length} of ${checks} checks disagree with the shipped package:`); - for (const mismatch of mismatches.slice(0, 20)) console.error("", JSON.stringify(mismatch)); - process.exit(1); -} - -console.log( - `spec == shipped JavaScript package on ${checks} checks (${corpus.length} corpus inputs)`, -); diff --git a/spec/conformance/probes/go-probe.go b/spec/conformance/probes/go-probe.go deleted file mode 100644 index 981c9e70e..000000000 --- a/spec/conformance/probes/go-probe.go +++ /dev/null @@ -1,40 +0,0 @@ -// Runs the published Go module against the corpus on stdin, printing the results as JSON. -// -// It is built from a temporary module with a `replace` pointing at the checkout, so it needs -// no network access. -package main - -import ( - "encoding/json" - "os" - - "github.com/brazilian-utils/go/cpf" - "github.com/brazilian-utils/go/pis" -) - -func main() { - var corpus []string - - if err := json.NewDecoder(os.Stdin).Decode(&corpus); err != nil { - panic(err) - } - - results := map[string]any{} - validCpf := make([]bool, len(corpus)) - validPis := make([]bool, len(corpus)) - formatted := make([]string, len(corpus)) - - for index, value := range corpus { - validCpf[index] = cpf.IsValid(value) - validPis[index] = pis.IsValid(value) - formatted[index] = cpf.Format(value) - } - - results["is-valid-cpf"] = validCpf - results["is-valid-pis"] = validPis - results["format-cpf"] = formatted - - if err := json.NewEncoder(os.Stdout).Encode(results); err != nil { - panic(err) - } -} diff --git a/spec/conformance/probes/python-probe.py b/spec/conformance/probes/python-probe.py deleted file mode 100644 index 88ae51b35..000000000 --- a/spec/conformance/probes/python-probe.py +++ /dev/null @@ -1,40 +0,0 @@ -#!/usr/bin/env python3 -"""Runs the published `brutils` package against the corpus on stdin, one result line per input. - -Usage: python3 python-probe.py - -The modules are loaded by path rather than imported as a package, so the probe does not need -the package's runtime dependencies installed. -""" - -import importlib.util -import json -import sys -from pathlib import Path - - -def load(root: Path, name: str): - spec = importlib.util.spec_from_file_location(f"upstream_{name}", root / "brutils" / f"{name}.py") - module = importlib.util.module_from_spec(spec) - spec.loader.exec_module(module) - return module - - -def main() -> int: - root = Path(sys.argv[1]) - cpf = load(root, "cpf") - pis = load(root, "pis") - corpus = json.load(sys.stdin) - - results = { - "is-valid-cpf": [bool(cpf.is_valid(value)) for value in corpus], - "is-valid-pis": [bool(pis.is_valid(value)) for value in corpus], - "format-cpf": [cpf.format_cpf(value) for value in corpus], - } - - json.dump(results, sys.stdout) - return 0 - - -if __name__ == "__main__": - sys.exit(main()) diff --git a/spec/conformance/probes/ruby-probe.rb b/spec/conformance/probes/ruby-probe.rb deleted file mode 100644 index cc3f75ba8..000000000 --- a/spec/conformance/probes/ruby-probe.rb +++ /dev/null @@ -1,19 +0,0 @@ -# frozen_string_literal: true - -# Runs the published gem against the corpus on stdin, printing the results as JSON. -# -# Usage: ruby ruby-probe.rb - -require 'json' - -root = ARGV[0] -require File.join(root, 'lib', 'brazilian-utils', 'cpf-utils') -require File.join(root, 'lib', 'brazilian-utils', 'pis-utils') - -corpus = JSON.parse($stdin.read) - -puts JSON.generate( - 'is-valid-cpf' => corpus.map { |value| BrazilianUtils::CPFUtils.valid?(value) }, - 'is-valid-pis' => corpus.map { |value| BrazilianUtils::PISUtils.valid?(value) }, - 'format-cpf' => corpus.map { |value| BrazilianUtils::CPFUtils.format_cpf(value) } -) diff --git a/spec/conformance/probes/rust-probe.rs b/spec/conformance/probes/rust-probe.rs deleted file mode 100644 index d0f9a0dfc..000000000 --- a/spec/conformance/probes/rust-probe.rs +++ /dev/null @@ -1,111 +0,0 @@ -//! Runs the published crate against the corpus on stdin, printing the results as JSON. -//! -//! Usage: linked against a built `brazilian_utils` rlib, corpus on stdin. - -use std::io::Read; - -fn escape(value: &str) -> String { - let mut out = String::from("\""); - - for char in value.chars() { - match char { - '"' => out.push_str("\\\""), - '\\' => out.push_str("\\\\"), - char if (char as u32) < 0x20 || (char as u32) > 0x7e => { - let code = char as u32; - - if code > 0xffff { - let offset = code - 0x10000; - out.push_str(&format!("\\u{:04x}", 0xd800 + (offset >> 10))); - out.push_str(&format!("\\u{:04x}", 0xdc00 + (offset & 0x3ff))); - } else { - out.push_str(&format!("\\u{:04x}", code)); - } - } - char => out.push(char), - } - } - - out.push('"'); - out -} - -/// A corpus entry is a JSON string literal; this reads them back without a JSON crate. -fn parse_corpus(raw: &str) -> Vec { - let mut values = Vec::new(); - let mut chars = raw.chars().peekable(); - - while let Some(char) = chars.next() { - if char != '"' { - continue; - } - - let mut value = String::new(); - - loop { - match chars.next() { - None | Some('"') => break, - Some('\\') => match chars.next() { - Some('u') => { - let hex: String = (0..4).filter_map(|_| chars.next()).collect(); - let code = u32::from_str_radix(&hex, 16).unwrap_or(0xfffd); - - if (0xd800..0xdc00).contains(&code) { - let mut low = String::new(); - chars.next(); - chars.next(); - for _ in 0..4 { - low.push(chars.next().unwrap_or('0')); - } - let trailing = u32::from_str_radix(&low, 16).unwrap_or(0xfffd); - let combined = 0x10000 + ((code - 0xd800) << 10) + (trailing - 0xdc00); - value.push(char::from_u32(combined).unwrap_or('\u{fffd}')); - } else { - value.push(char::from_u32(code).unwrap_or('\u{fffd}')); - } - } - Some('n') => value.push('\n'), - Some('r') => value.push('\r'), - Some('t') => value.push('\t'), - Some(other) => value.push(other), - None => break, - }, - Some(other) => value.push(other), - } - } - - values.push(value); - } - - values -} - -fn main() { - let mut raw = String::new(); - std::io::stdin().read_to_string(&mut raw).expect("corpus"); - - let corpus = parse_corpus(&raw); - - let valid_cpf: Vec = corpus - .iter() - .map(|value| brazilian_utils::cpf::is_valid(value).to_string()) - .collect(); - let valid_pis: Vec = corpus - .iter() - .map(|value| brazilian_utils::pis::is_valid(value).to_string()) - .collect(); - let formatted: Vec = corpus - .iter() - .map(|value| match brazilian_utils::cpf::format_cpf(value) { - None => "null".to_string(), - Some(text) => escape(&text), - }) - .collect(); - - println!( - "{{\"is-valid-cpf\":[{}],\"is-valid-pis\":[{}],\"format-cpf\":[{}]}}", - valid_cpf.join(","), - valid_pis.join(","), - formatted.join(",") - ); -} diff --git a/spec/conformance/run-all.sh b/spec/conformance/run-all.sh deleted file mode 100755 index b3bf80d5d..000000000 --- a/spec/conformance/run-all.sh +++ /dev/null @@ -1,26 +0,0 @@ -#!/usr/bin/env bash -# Regenerates every target from the specs and runs its conformance driver. -# -# Usage: bash spec/conformance/run-all.sh -set -euo pipefail - -root="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)" -generated="${root}/spec/generated" -work="$(mktemp -d)" -trap 'rm -rf "${work}"' EXIT - -node "${root}/spec/codegen/vectors.ts" >/dev/null -node "${root}/spec/codegen/emit.ts" >/dev/null - -echo "--- differential against the package this repository ships" -node "${root}/spec/conformance/differential-javascript.ts" - -echo "--- conformance of every generated target" -node "${generated}/typescript/conformance.ts" -python3 "${generated}/python/conformance.py" -ruby "${generated}/ruby/conformance.rb" -(cd "${generated}/go" && go run ./conformance) -rustc --edition 2021 -o "${work}/rust-conformance" "${generated}/rust/conformance.rs" 2>/dev/null -"${work}/rust-conformance" -javac -nowarn -d "${work}/java" "${generated}"/java/*.java -java -cp "${work}/java" Conformance diff --git a/spec/conformance/upstream.ts b/spec/conformance/upstream.ts deleted file mode 100644 index 89fb46464..000000000 --- a/spec/conformance/upstream.ts +++ /dev/null @@ -1,178 +0,0 @@ -/** - * Checks the specs against the libraries the organisation already publishes. - * - * For every sibling checkout it is pointed at, it runs that package's own functions over the - * corpus and compares the answers with the profile the spec says that package implements. A - * disagreement means the spec is wrong about a shipped contract, which is the only thing that - * could make a generated package a breaking change. - * - * Usage: node spec/conformance/upstream.ts --python ../python --ruby ../ruby --go ../go - */ -import { execFileSync } from "node:child_process"; -import { mkdtempSync, readFileSync, rmSync, writeFileSync } from "node:fs"; -import { tmpdir } from "node:os"; -import { join, resolve } from "node:path"; - -import { loadAll, specRoot } from "../codegen/ir.ts"; -import { type Vectors } from "../codegen/vectors.ts"; - -type ProbeResults = Record; - -const vectors = JSON.parse( - readFileSync(resolve(specRoot, "vectors/conformance.json"), "utf8"), -) as Vectors; - -const specs = loadAll(); -const corpus = JSON.stringify(vectors.corpus); -const probes = resolve(import.meta.dirname, "probes"); - -const args = process.argv.slice(2); -const checkouts = new Map(); - -for (let index = 0; index < args.length; index += 2) { - if (!args[index].startsWith("--")) throw new Error(`unexpected argument: ${args[index]}`); - - checkouts.set(args[index].slice(2), resolve(args[index + 1])); -} - -const runProbe = (language: string, checkout: string): ProbeResults => { - switch (language) { - case "python": { - return JSON.parse( - execFileSync("python3", [join(probes, "python-probe.py"), checkout], { - input: corpus, - encoding: "utf8", - maxBuffer: 64 * 1024 * 1024, - }), - ) as ProbeResults; - } - case "ruby": { - return JSON.parse( - execFileSync("ruby", [join(probes, "ruby-probe.rb"), checkout], { - input: corpus, - encoding: "utf8", - maxBuffer: 64 * 1024 * 1024, - }), - ) as ProbeResults; - } - case "go": { - const work = mkdtempSync(join(tmpdir(), "brutils-go-probe-")); - - writeFileSync( - join(work, "go.mod"), - `module brutilsprobe\n\ngo 1.23\n\nrequire github.com/brazilian-utils/go v0.0.0\n\nreplace github.com/brazilian-utils/go => ${checkout}\n`, - ); - writeFileSync(join(work, "main.go"), readFileSync(join(probes, "go-probe.go"), "utf8")); - - const output = execFileSync("go", ["run", "."], { - cwd: work, - input: corpus, - encoding: "utf8", - env: { ...process.env, GOFLAGS: "-mod=mod" }, - maxBuffer: 64 * 1024 * 1024, - }); - - rmSync(work, { recursive: true, force: true }); - - return JSON.parse(output) as ProbeResults; - } - case "rust": { - const work = mkdtempSync(join(tmpdir(), "brutils-rust-probe-")); - - execFileSync( - "rustc", - [ - "--edition", - "2021", - "-o", - join(work, "probe"), - join(probes, "rust-probe.rs"), - "--extern", - `brazilian_utils=${join(checkout, "target/debug/libbrazilian_utils.rlib")}`, - "-L", - join(checkout, "target/debug/deps"), - ], - { encoding: "utf8" }, - ); - - const output = execFileSync(join(work, "probe"), [], { - input: corpus, - encoding: "utf8", - maxBuffer: 64 * 1024 * 1024, - }); - - rmSync(work, { recursive: true, force: true }); - - return JSON.parse(output) as ProbeResults; - } - default: { - throw new Error(`no probe for ${language}`); - } - } -}; - -let disagreements = 0; - -for (const [language, checkout] of checkouts) { - console.log(`\n${language} — ${checkout}`); - - let results: ProbeResults; - - try { - results = runProbe(language, checkout); - } catch (error) { - console.log( - ` probe failed: ${error instanceof Error ? error.message.split("\n")[0] : String(error)}`, - ); - continue; - } - - for (const spec of specs) { - const adoption = spec.adopted[language]; - const observed = results[spec.id]; - - if (adoption === undefined || observed === undefined) continue; - - const utility = vectors.utilities[spec.id]; - const expectedColumn = utility.profiles[adoption.profile]; - const expected = - spec.kind === "validator" - ? (expectedColumn as boolean[]) - : (expectedColumn as (string | null)[][]).map((outputs) => outputs[0]); - - const known = new Set( - (adoption.knownDeviations ?? []).flatMap((deviation) => deviation.inputs), - ); - const mismatches: { input: string; expected: unknown; observed: unknown }[] = []; - let deviations = 0; - - for (const [index, input] of vectors.corpus.entries()) { - if (observed[index] === expected[index]) continue; - - if (known.has(input)) { - deviations++; - continue; - } - - mismatches.push({ input, expected: expected[index], observed: observed[index] }); - } - - disagreements += mismatches.length; - - const note = deviations > 0 ? ` (+${deviations} known deviation(s))` : ""; - const verdict = - mismatches.length === 0 - ? `agrees on ${vectors.corpus.length - deviations}/${vectors.corpus.length}${note}` - : `DIFFERS on ${mismatches.length}/${vectors.corpus.length}${note}`; - - console.log(` ${spec.id.padEnd(14)} profile ${adoption.profile.padEnd(17)} ${verdict}`); - - for (const mismatch of mismatches.slice(0, 5)) { - console.log( - ` input=${JSON.stringify(mismatch.input)} spec=${JSON.stringify(mismatch.expected)} package=${JSON.stringify(mismatch.observed)}`, - ); - } - } -} - -console.log(`\n${disagreements} disagreement(s) with the published packages`); diff --git a/spec/schema/charsets.json b/spec/schema/charsets.json deleted file mode 100644 index 518863bee..000000000 --- a/spec/schema/charsets.json +++ /dev/null @@ -1,39 +0,0 @@ -{ - "$comment": "Character sets referenced by the utility specs, written out as explicit code points. Regex shorthands are deliberately avoided: `\\s` means 6 ASCII characters in Go and Ruby, the 25 code points below in JavaScript, and a Unicode property in Python and the Rust regex crate, so a spec that shipped a regex literal would not describe one behaviour. `\\d` diverges the same way (Python's `\\d` matches Devanagari digits with `re.UNICODE`).", - "charsets": { - "ascii-digits": { - "description": "The 10 ASCII digits. This is what every Brazilian document number is made of.", - "ranges": [["0030", "0039"]] - }, - "js-whitespace": { - "description": "The code points JavaScript's String.prototype.trim() strips and its regex `\\s` matches: WhiteSpace plus LineTerminator plus U+FEFF.", - "codePoints": [ - "0009", - "000A", - "000B", - "000C", - "000D", - "0020", - "00A0", - "1680", - "2028", - "2029", - "202F", - "205F", - "3000", - "FEFF" - ], - "ranges": [["2000", "200A"]] - }, - "mask-cpf": { - "description": "Separators accepted between the digit groups of a CPF.", - "codePoints": ["002E", "002D", "002F"], - "include": ["js-whitespace"] - }, - "mask-pis": { - "description": "Separators accepted anywhere in a PIS/NIS.", - "codePoints": ["002E", "002D", "002F", "0028", "0029", "002C", "002A"], - "include": ["js-whitespace"] - } - } -} diff --git a/spec/schema/check-digits.json b/spec/schema/check-digits.json deleted file mode 100644 index 067459331..000000000 --- a/spec/schema/check-digits.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "$comment": "Check digit algorithms referenced by the utility specs. Every Brazilian document number in the library is a weighted modulus sum, so the algorithms are described as data rather than reimplemented per utility.", - "algorithms": { - "cpf": { - "description": "Modulus 11 over the base, weights running from base length + 1 down to 2, repeated cumulatively for each check digit: the second digit is computed over the base plus the first one.", - "modulus": 11, - "weights": { "kind": "descending", "from": "length+1", "to": 2 }, - "reduce": "modulus-minus-remainder", - "clamp": { "atLeast": 10, "to": 0 }, - "positions": [9, 10], - "cumulative": true, - "source": "https://normas.receita.fazenda.gov.br/sijut2consulta/link.action?idAto=151372" - }, - "pis": { - "description": "Modulus 11 over the 10 base digits with the fixed weight vector 3 2 9 8 7 6 5 4 3 2.", - "modulus": 11, - "weights": { "kind": "fixed", "values": [3, 2, 9, 8, 7, 6, 5, 4, 3, 2] }, - "reduce": "modulus-minus-remainder", - "clamp": { "atLeast": 10, "to": 0 }, - "positions": [10], - "cumulative": false, - "source": "https://www.sirc.gov.br/wp-content/uploads/manual_sirc_recomendacoes_tecnicas_v7.pdf" - } - } -} diff --git a/spec/schema/utility.schema.json b/spec/schema/utility.schema.json deleted file mode 100644 index 4a192cc2f..000000000 --- a/spec/schema/utility.schema.json +++ /dev/null @@ -1,237 +0,0 @@ -{ - "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://brazilian-utils.com.br/spec/schema/utility.schema.json", - "title": "Brazilian Utils utility specification", - "description": "A language neutral description of one utility: what it accepts, what it answers, and which of its behaviours each package implements today.", - "type": "object", - "required": [ - "id", - "kind", - "summary", - "sources", - "names", - "input", - "output", - "adopted", - "profiles" - ], - "additionalProperties": false, - "properties": { - "$schema": { "type": "string" }, - "id": { - "type": "string", - "pattern": "^[a-z0-9]+(-[a-z0-9]+)*$", - "description": "The utility id, in kebab-case, which is also the file name." - }, - "kind": { - "enum": ["validator", "formatter"], - "description": "Validators answer a boolean; formatters answer a string or the absent value." - }, - "summary": { "type": "string" }, - "sources": { - "type": "array", - "minItems": 1, - "items": { - "type": "object", - "required": ["role", "url"], - "additionalProperties": false, - "properties": { - "role": { - "enum": ["official", "based-on"], - "description": "`official` is a law, regulator, standard body or government dataset; `based-on` is a third party implementation or mirror the code relied on." - }, - "url": { "type": "string", "format": "uri" } - } - } - }, - "names": { - "type": "object", - "description": "What each package calls this utility. The generator never invents a name: it emits the one that package already publishes.", - "additionalProperties": { - "type": "object", - "required": ["module", "function"], - "additionalProperties": false, - "properties": { - "module": { "type": "string" }, - "function": { "type": "string" } - } - } - }, - "input": { - "type": "object", - "required": ["name", "type"], - "additionalProperties": false, - "properties": { - "name": { "type": "string" }, - "type": { "type": "string" }, - "onWrongType": { "enum": ["false"] }, - "onNullish": { "enum": ["empty-string", "null"] } - } - }, - "output": { - "type": "object", - "required": ["type"], - "additionalProperties": false, - "properties": { "type": { "enum": ["boolean", "string"] } } - }, - "adopted": { - "type": "object", - "description": "Which profile each package implements today, and where it is known to differ from it.", - "additionalProperties": { - "type": "object", - "required": ["profile"], - "additionalProperties": false, - "properties": { - "profile": { "type": "string" }, - "options": { "type": "array", "items": { "type": "string" } }, - "knownDeviations": { - "type": "array", - "items": { - "type": "object", - "required": ["inputs", "reason"], - "additionalProperties": false, - "properties": { - "inputs": { "type": "array", "items": { "type": "string" } }, - "reason": { "type": "string" }, - "issue": { "type": "string", "format": "uri" } - } - } - } - } - } - }, - "profiles": { - "type": "object", - "description": "The named behaviours of this utility. A profile is a contract: two packages on the same profile answer identically on every input.", - "minProperties": 1, - "additionalProperties": { - "type": "object", - "required": ["description", "pipeline"], - "additionalProperties": false, - "properties": { - "description": { "type": "string" }, - "absent": { - "enum": ["empty-string", "null"], - "description": "What a formatter answers when it has nothing to format." - }, - "options": { - "type": "array", - "items": { - "type": "object", - "required": ["name", "type", "default", "read"], - "additionalProperties": false, - "properties": { - "name": { "type": "string" }, - "type": { "const": "boolean" }, - "default": { "type": "boolean" }, - "read": { "enum": ["truthy", "strict"] } - } - } - }, - "pipeline": { - "type": "array", - "minItems": 1, - "items": { "$ref": "#/$defs/step" } - } - } - } - } - }, - "$defs": { - "step": { - "oneOf": [ - { - "type": "object", - "description": "The whole value, optionally trimmed, has to be the given digit groups, separated only by the given charset.", - "required": ["op", "target", "groups"], - "additionalProperties": false, - "properties": { - "op": { "const": "guard-shape" }, - "target": { "const": "raw" }, - "trim": { "type": "string" }, - "groups": { "type": "array", "items": { "type": "integer", "minimum": 1 } }, - "separators": { "type": "string" } - } - }, - { - "type": "object", - "description": "Every character of the raw input has to belong to the union of the given charsets.", - "required": ["op", "target", "allow"], - "additionalProperties": false, - "properties": { - "op": { "const": "guard-charset" }, - "target": { "const": "raw" }, - "allow": { "type": "array", "items": { "type": "string" } } - } - }, - { - "type": "object", - "required": ["op", "keep", "into"], - "additionalProperties": false, - "properties": { - "op": { "const": "sanitize" }, - "keep": { "type": "string" }, - "into": { "const": "digits" } - } - }, - { - "type": "object", - "required": ["op", "target", "equals"], - "additionalProperties": false, - "properties": { - "op": { "const": "guard-length" }, - "target": { "const": "digits" }, - "equals": { "type": "integer", "minimum": 1 } - } - }, - { - "type": "object", - "description": "Rejects a run of one repeated digit, such as \"00000000000\".", - "required": ["op", "target"], - "additionalProperties": false, - "properties": { - "op": { "const": "guard-repeated" }, - "target": { "const": "digits" } - } - }, - { - "type": "object", - "required": ["op", "target", "checkDigit"], - "additionalProperties": false, - "properties": { - "op": { "const": "verify-check-digits" }, - "target": { "const": "digits" }, - "checkDigit": { - "type": "string", - "description": "An algorithm declared in spec/schema/check-digits.json." - } - } - }, - { - "type": "object", - "description": "Requires another utility to accept the same input, under a named profile.", - "required": ["op", "utility", "profile"], - "additionalProperties": false, - "properties": { - "op": { "const": "guard-valid" }, - "utility": { "type": "string" }, - "profile": { "type": "string" } - } - }, - { - "type": "object", - "description": "Lays the digits over a pattern: `0` copies a character, `*` hides one, anything else separates.", - "required": ["op", "target", "engine", "pattern"], - "additionalProperties": false, - "properties": { - "op": { "const": "apply-pattern" }, - "target": { "const": "digits" }, - "engine": { "const": "pattern-v1" }, - "pattern": { "type": "string" }, - "variants": { "type": "object", "additionalProperties": { "type": "string" } } - } - } - ] - } - } -} diff --git a/spec/utilities.json b/spec/utilities.json deleted file mode 100644 index 8d68f0cc0..000000000 --- a/spec/utilities.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "$comment": "The utilities covered by the specification, in the order the emitters lay them out.", - "utilities": ["is-valid-cpf", "is-valid-pis", "format-cpf"] -} diff --git a/spec/utilities/format-cpf.json b/spec/utilities/format-cpf.json deleted file mode 100644 index 6086a17c2..000000000 --- a/spec/utilities/format-cpf.json +++ /dev/null @@ -1,134 +0,0 @@ -{ - "$schema": "../schema/utility.schema.json", - "id": "format-cpf", - "kind": "formatter", - "summary": "Formats a CPF value as \"000.000.000-00\".", - "sources": [ - { - "role": "official", - "url": "https://www.gov.br/receitafederal/pt-br/assuntos/meu-cpf" - } - ], - "names": { - "typescript": { - "module": "format-cpf", - "function": "formatCpf" - }, - "python": { - "module": "brutils.cpf", - "function": "format_cpf" - }, - "go": { - "module": "cpf", - "function": "Format" - }, - "ruby": { - "module": "BrazilianUtils::CPFUtils", - "function": "format_cpf" - }, - "rust": { - "module": "cpf", - "function": "format_cpf" - }, - "java": { - "module": "Cpf", - "function": "format" - } - }, - "input": { - "name": "value", - "type": "string|number", - "onNullish": "empty-string" - }, - "output": { - "type": "string" - }, - "adopted": { - "typescript": { - "profile": "pattern-partial", - "options": ["pad", "obfuscate"] - }, - "go": { - "profile": "pattern-partial", - "options": [] - }, - "java": { - "profile": "pattern-partial", - "options": ["pad", "obfuscate"] - }, - "python": { - "profile": "strict-or-null", - "knownDeviations": [ - { - "inputs": ["12345678909", "١٢٣٤٥٦٧٨٩٠٩"], - "reason": "format_cpf delegates to is_valid, so it inherits the Unicode digit deviation and returns a CPF formatted in non ASCII digits." - } - ] - }, - "ruby": { - "profile": "strict-or-null" - }, - "rust": { - "profile": "strict-or-null" - } - }, - "profiles": { - "pattern-partial": { - "description": "Sanitizes to digits and lays them over the pattern, emitting a separator only while digits are left, so a short value formats to a partial mask instead of failing.", - "absent": "empty-string", - "pipeline": [ - { - "op": "sanitize", - "keep": "ascii-digits", - "into": "digits" - }, - { - "op": "apply-pattern", - "target": "digits", - "engine": "pattern-v1", - "pattern": "000.000.000-00", - "variants": { - "obfuscate": "***.000.000-**" - } - } - ], - "options": [ - { - "name": "pad", - "type": "boolean", - "default": false, - "read": "truthy" - }, - { - "name": "obfuscate", - "type": "boolean", - "default": false, - "read": "truthy" - } - ] - }, - "strict-or-null": { - "description": "Returns the empty value unless the input is already a valid CPF. Implemented by the Python, Ruby and Rust packages, which return None/nil.", - "absent": "null", - "pipeline": [ - { - "op": "guard-valid", - "utility": "is-valid-cpf", - "profile": "digits-only" - }, - { - "op": "sanitize", - "keep": "ascii-digits", - "into": "digits" - }, - { - "op": "apply-pattern", - "target": "digits", - "engine": "pattern-v1", - "pattern": "000.000.000-00" - } - ], - "options": [] - } - } -} diff --git a/spec/utilities/is-valid-cpf.json b/spec/utilities/is-valid-cpf.json deleted file mode 100644 index 10a77d72a..000000000 --- a/spec/utilities/is-valid-cpf.json +++ /dev/null @@ -1,155 +0,0 @@ -{ - "$schema": "../schema/utility.schema.json", - "id": "is-valid-cpf", - "kind": "validator", - "summary": "Validates a CPF (Cadastro de Pessoas Físicas) number.", - "sources": [ - { - "role": "official", - "url": "https://www.gov.br/receitafederal/pt-br/assuntos/meu-cpf" - }, - { - "role": "official", - "url": "https://normas.receita.fazenda.gov.br/sijut2consulta/link.action?idAto=151372" - } - ], - "names": { - "typescript": { - "module": "is-valid-cpf", - "function": "isValidCpf" - }, - "python": { - "module": "brutils.cpf", - "function": "is_valid" - }, - "go": { - "module": "cpf", - "function": "IsValid" - }, - "ruby": { - "module": "BrazilianUtils::CPFUtils", - "function": "valid?" - }, - "rust": { - "module": "cpf", - "function": "is_valid" - }, - "java": { - "module": "Cpf", - "function": "isValid" - } - }, - "input": { - "name": "cpf", - "type": "string", - "onWrongType": "false" - }, - "output": { - "type": "boolean" - }, - "adopted": { - "typescript": { - "profile": "masked-strict" - }, - "python": { - "profile": "digits-only", - "knownDeviations": [ - { - "inputs": ["12345678909", "١٢٣٤٥٦٧٨٩٠٩"], - "reason": "brutils/cpf.py gates on str.isdigit(), which is Unicode aware, so a CPF written in full width or Arabic-Indic digits validates. The profile is ASCII only." - } - ] - }, - "ruby": { - "profile": "digits-only" - }, - "rust": { - "profile": "digits-only" - }, - "erlang": { - "profile": "digits-only" - }, - "go": { - "profile": "digits-extracted" - }, - "java": { - "profile": "masked-strict" - } - }, - "profiles": { - "masked-strict": { - "description": "Accepts the usual mask characters and whitespace around and between the digit groups, and rejects every other shape. Implemented by the JavaScript package.", - "pipeline": [ - { - "op": "guard-shape", - "target": "raw", - "trim": "js-whitespace", - "groups": [3, 3, 3, 2], - "separators": "mask-cpf" - }, - { - "op": "sanitize", - "keep": "ascii-digits", - "into": "digits" - }, - { - "op": "guard-repeated", - "target": "digits" - }, - { - "op": "verify-check-digits", - "target": "digits", - "checkDigit": "cpf" - } - ] - }, - "digits-only": { - "description": "Accepts exactly 11 ASCII digits and nothing else. Implemented by the Python, Ruby, Rust and Erlang packages.", - "pipeline": [ - { - "op": "guard-shape", - "target": "raw", - "groups": [11] - }, - { - "op": "sanitize", - "keep": "ascii-digits", - "into": "digits" - }, - { - "op": "guard-repeated", - "target": "digits" - }, - { - "op": "verify-check-digits", - "target": "digits", - "checkDigit": "cpf" - } - ] - }, - "digits-extracted": { - "description": "Drops every non-digit character wherever it appears and validates what is left, so \"abc12345678909\" is accepted. Implemented by the Go package.", - "pipeline": [ - { - "op": "sanitize", - "keep": "ascii-digits", - "into": "digits" - }, - { - "op": "guard-length", - "target": "digits", - "equals": 11 - }, - { - "op": "guard-repeated", - "target": "digits" - }, - { - "op": "verify-check-digits", - "target": "digits", - "checkDigit": "cpf" - } - ] - } - } -} diff --git a/spec/utilities/is-valid-pis.json b/spec/utilities/is-valid-pis.json deleted file mode 100644 index 797f97bc1..000000000 --- a/spec/utilities/is-valid-pis.json +++ /dev/null @@ -1,127 +0,0 @@ -{ - "$schema": "../schema/utility.schema.json", - "id": "is-valid-pis", - "kind": "validator", - "summary": "Validates a PIS/PASEP/NIS number.", - "sources": [ - { - "role": "official", - "url": "https://www.gov.br/inss/pt-br/direitos-e-deveres/inscricao-e-contribuicao/inscricao" - }, - { - "role": "based-on", - "url": "https://github.com/brazilian-utils/python/blob/main/brutils/pis.py" - } - ], - "names": { - "typescript": { - "module": "is-valid-pis", - "function": "isValidPis" - }, - "python": { - "module": "brutils.pis", - "function": "is_valid" - }, - "go": { - "module": "pis", - "function": "IsValid" - }, - "ruby": { - "module": "BrazilianUtils::PISUtils", - "function": "valid?" - }, - "rust": { - "module": "pis", - "function": "is_valid" - }, - "java": { - "module": "Pis", - "function": "isValid" - } - }, - "input": { - "name": "pis", - "type": "string", - "onWrongType": "false" - }, - "output": { - "type": "boolean" - }, - "adopted": { - "typescript": { - "profile": "masked-charset" - }, - "java": { - "profile": "masked-charset" - }, - "python": { - "profile": "digits-only-lenient", - "knownDeviations": [ - { - "inputs": ["12345678909", "١٢٣٤٥٦٧٨٩٠٩"], - "reason": "brutils/pis.py gates on str.isdigit(), which is Unicode aware, so full width and Arabic-Indic digits are accepted as a PIS and int() then reads them. The profile is ASCII only." - } - ] - }, - "go": { - "profile": "digits-only-lenient" - }, - "ruby": { - "profile": "digits-only-lenient" - }, - "rust": { - "profile": "digits-only-lenient" - } - }, - "profiles": { - "masked-charset": { - "description": "Accepts mask characters and whitespace anywhere, rejects every other character, then validates the 11 digits left.", - "pipeline": [ - { - "op": "guard-charset", - "target": "raw", - "allow": ["ascii-digits", "mask-pis"] - }, - { - "op": "sanitize", - "keep": "ascii-digits", - "into": "digits" - }, - { - "op": "guard-length", - "target": "digits", - "equals": 11 - }, - { - "op": "guard-repeated", - "target": "digits" - }, - { - "op": "verify-check-digits", - "target": "digits", - "checkDigit": "pis" - } - ] - }, - "digits-only-lenient": { - "description": "Accepts exactly 11 ASCII digits, rejects every mask character, and does not reject a repeated digit run, so \"00000000000\" validates. Implemented by the Python, Go and Ruby packages.", - "pipeline": [ - { - "op": "guard-shape", - "target": "raw", - "groups": [11] - }, - { - "op": "sanitize", - "keep": "ascii-digits", - "into": "digits" - }, - { - "op": "verify-check-digits", - "target": "digits", - "checkDigit": "pis" - } - ] - } - } -} diff --git a/spec/vectors/conformance.json b/spec/vectors/conformance.json deleted file mode 100644 index 960998606..000000000 --- a/spec/vectors/conformance.json +++ /dev/null @@ -1 +0,0 @@ -{"corpus":[""," ","0","00000000000","11111111111","99999999999","12345678909","123.456.789-09","123 456 789 09"," 12345678909 ","123.456.789.09","123/456/789/09","123-456-789-09","123..456..789--09",".12345678909","12345678909.","1234567890","123456789090","abc12345678909","12345678909abc","1a2345678909","12345678900"," 12345678909 "," 123.456.789-09
","12345678909","123 456 789 09","123\t456\n789\r09","🇧🇷12345678909","12345678909🇧🇷","12345678909","١٢٣٤٥٦٧٨٩٠٩","12056874107","120.56874.10-7","120/56874/10-7","120(56874)10,7","120*56874*10-7","12056874108","1205687410","120.56874.10-7 ","120#56874#10#7","74275733568","69264259294","27502677658","9.5167.3","45528746248","00192591070","2423/3.79a967a0","04349316248","05828033735","*340*)6","01018054771","45960967839","72953559375","350#6#7 633717","85752788760","12201461035","65623597327","08216262647","94291497253","65546678658","02218010658","13434608915","60021596917","99266321688","036/6694a2431","29022796396","659037# ","610954584)85,","57.364183-296","72468124605","01366021578","37242507700","6.5968)418a486","64629394234","89884,197702","588519 7)4/661","06733963710","16153416609","973194*6,5520-","83438658534","48938105458","52070564410","37299492850","97116501347","267a783 45665","7*15653/41811","193a0007658a5","32605779807","81887191706","60150247125","71770889540","38306173004","63 568062866","13765631345","96840834266","875 6a6256601","17)06**05","#478089(3220","977/03000(","660(29a924818","25368103999","15050757707",")49 354 55","23609640126","7587)8147440.","95291932024","32711721370","25#8163547 95","707612.87664.","40110965809","-54)9","62501783555","3855)352323","00158379099","2(1062574","#63(67406","94622089211","85947269915","86/98247","30953452751","5554204406-9","87821425957","10359723012","38589626369","17091421971","649982-92,8,306","*737925","51723668907","0,353077501","1381-9#642420","29972448622","89/-60/84210273","1425.6372500","55427359071","63876408903","106a","53367895857","500978,20993","32498856498","36558846217","26147599291",".(1.9*24*","75660210933","93971033695","52200090253","38476272600","378447344/33","069263407*#51","59139466850","6(87953,3-8570","87373238138","95 1","641350042 5(3","40910963010","268067 8#237*8","83723418503","758131(6","20240907137","33520141268","17938","10213407217","66738397299","45-92166 57(41","05466916770","62762266910","84911262958","81826425290","89205985252","05496053471","52597393372","38652220565","17-89993365275","22279047551","15481647740","54130082795","23442185571","90 500080904","84264259522","58976801750","20648740625","57342147291","8","06787915480","74994999791","308351266,0 0","33664446341","72084287028","62610395930","39083(594068","29462 99449a8","87862097741","148965/24500 ","4549302,4182(","43955822983","49545440333","00838712551","5693995*7#12/0","79/467634503","90117760952","6","450262548(83","71733485502","59920913563","14079680171","067*37*782012","7683735755,1 ","43855708339","26273937561","66846268596","8433,56 40/307","12710973626","60805222300","36453716769","80716189538","96875115166","74336944841","31092397361","16348172139","38146986579","24144680090","35818.63-9282","(0","50373463200","7a6a61220#1053","55023a198.0,(","3857,8,49895)0","84785977515","34957107592","90534660967","2183836)15","1)8813929374(","25625090603","1-4","67817905635","45185817500","62591997515","94866406005","48986981319","48a1)896956(215","12847371605","02712781880*","50590677201","1130)86*12109","85452922541","1657*89388a2-7","06054396416","94680920548","69605029960","64060368330","79870297338","71327360357","06833761241","31953017104","21881139070","03621090/1#28 ","08845801875","66081 17 838.0","(991 59(36720","19929703942","65134983178","56127159482","13905674709","35487816369","01104612585","49147868907","8175837 988(5","1958*2603944","12857330375","39510339750-","57878124270","06770932311","29395616890","50413890.635","3","54711981085","27704704850-","46757073297","3*9#18786a8,113a","8.22,2*,(#","09624157970","20862681019","65845806283","78155325511","91246524902","85037722440","06072829910","19006621385","91822082633","284003-7)6293/","24584648158","81765431668","90125/01,2535","42430498944","28,72040882a2","4674150#3016","a58,","35738654593","49571112270","70116455780","70494#544/864/","63108583352","51832068939","99665590359","3237#5","871 20910493","6 7706696502#","74910*321292","58825236983","91665897113","22473672220","50333a031555","39376825044","16326834334","3/1854069798","86676398427","10a47#83","07203160435","7","54041828147","81939232511","033789.079#08#","7(20 613.","36081312203","14827445113","90094962103","89393206850","37845084553","775-319793 91","3359490 5 098","80531386406","57)406681,15/1","91(231287551,","415","62#067,930(891","44090285141","67489979412","11680919695","32*9#34)167801","29927535309","68816320370","32745256439","49593127933","77791117843","491(378(84506","097a 9)4741-","932.23243/178","28295821005","33212344679","77762041370","95373510416","6/4489153627","42794672014","93206839807","40428139980","27002753061","16041909891","5(939a954561)0","0438-1899814","6806703/6748","76083838506","46508664646","64204832671","03584949823","82976574340","7,2135151017","12435077094","9977(00041 98-","388993*87 958,","699367.6777/27)","91553048220","82674809787","32782781600","1302581(","301/41926580a","99064778258","824 460621 8","70140751009","79774925122","45294338971","67715677884","10*3(6158 65,90*","22115679341","02040884623","8/6956026238","88142588117","45716895786","3516340448 0a","92995777499","17710007188","35*87#17#48781","25570295610","04046*885075","73144445606","75086a8#8058/0","03670355555","-/ 02","a 434 ","59728943107","4080.3088256","#37 0","57049460387","42024527209","50224587436","33689976456","6.3.23-9(8 67877","03014108448","30173549871","53945248343","53416681118","724-49978844","45277444106","40086262556","55205/ 1(*1","54712598077","11228014a340","19984710807","87024275839","40033410231","13026104140","93439798607 ","79547137921","06586026164","30648422267","7473,2299822","78751559404","77371587199","23201372770","48 5(28827259","63098235590","44-68 1014079","4472640","18192199177","36726974559","78164817058","863758171(71","57024472704","02824308596","a252) 5","49487942440","39","01605660652","98460899292","3104897*8753","4(133807a2206","99292011308","63031473936","38076757950","05679802430","63341026362","66,5382991","30414950070","32)-#4611403*","42123780522","06236152#571","82153578817","36045129267","099(987(52343","58536818859","66540536264","45787969065","#,4236","42050173679","8569207-83(25","56(13630","03855805687","31793#036977#","92826784218","991361901*79","3*3647161)202 ","0474552)#5","654(592183 65","70389666858","62488480096","66.59-467 823)0","4#50,.0a21061,8","765801 2*2382","66122001201","26826010305","57142385151","5.35748724#4)3(","47236219541","40549687670","90141629369","70223(9 8674 7","90334100011","04518514970","9354470436 3","7 63)8680#1202.","86305661512","53111178501","35772104276","489(51911098*","19901091446","63013612798","71914656529","44617654747","96491193969","a615,,41","95805869707","29901346205","54208519975","875)53-6*81295","36988108217","5 354 19 4","4/5 3175.172 0,1","67755270160","92879818","98966060521","98114#524)235","6-2 9","77237 56004","64548712588","89499697768","64807531071","4.15*52615#960","029 0*7472598","61447588640","462 86624449","28997279157","9 2769#78 44)0*","12418027879","00576059- 4#.","83871787884","18629180668","625,765938 7(7","68675256998","62682278159","05376651371","15624641471(","55397368261","94697679827","59343010710","96988797300","68741541090","81545791201","06430204977","65078757406","95113422*195","28644466375","-63(,3698","09323157444","53234099691 ","014371442/4*9 ","29715289932","18166 728#150","2)7 6*35541370-","94622736349","30086393632","99920183642","176844)10300","72720)70-4909","0829064a1095","73165138013","21723780626","82760984438","08552756887","56267985520","62062059424","14353708309","20197616968","90970500734","31979867452","667.8133927 3","55494164179","13/73 9728530","22015806008","56825397664",")6 *6(0a146","31,43)2597604","90771312563","29389912075","381997951)31","52 62273.13)","90700384987","05621956966","7748169522","23813064123","78305022501","25623.074294","4132057/7202","71536439312","95498010125","(727,6.4.","21509606726","043397/52460","00346424712","37585164478","74.700668660*","66312087344","96883873367","61955334460","018549.08828","47772633149","01397607840","11/556669682","41826165886","2780148195 0","84674429137","94317787811","506237 79133","40584847998","44943496302","0 32,91#06 ","95196278559","92601882450","50015512407","106/38726082","901#/903678355","21117259856","25882595967","04732383491","9479969 9","95922669800","8883/06156)0*9","32850130796","77974150892","29659535186","49// ","15790872976","58260669897","91329809105","5677103 1950,","14398251227","25824296210","56314621844","94876813277","16263660120","700717*6(2167","684-0502763","15424949790","8-1#91536(69","25371491907","75532925688","34493470550","70651413020","641863190#06/","36238066631","87766231879","78507200168,","97540086980","69426575595","717 0#540339a5","40057456622","16215778052","90760673330","21056750189","64853010206","95 9)760100-00","90259943428","46625500798","98-845045580","42861538430","71521538336","637a","65411877890","2)0224658756","83660227226","41096624424","2 0199552290","43290951901","91037243784","45426209985","39704032862","64763559532","906 33(7251)53","69805193291","04785557086","49612588732","7 )9","6613898473(0","55557336505","75932776234","35734160636","68367455505","43599874434","11981522551","46538105958","45249186411","77458313465","0a0798#895659","7700.4133267",".4-#2/.*-#2*878","461,7","0638673669","7739)5204468","13419417870","30688657217","43076045033","45420468862","47713594587","98299994147","47274872842","10279.099a30)4","63735745800","96010762314","43223170146","90732490086","81106510790","36902649001","36133763930","95524229907","60486932303","48622599876","38354488462","10*237294,664","462605-225,52","82118110709","25424062431","57411529370","49640340787","6245*598(990-9-","08)840/48606","67214459051","86730859433","41922980072","573/830(43308","01504672760","63298685954","09900425375","66694/5(79109","04257613203","27662001321","45617675848","31286558395","60 78 1073417","13782269179","46201891549","72380631544","1.0664386129","51796846302","28075951700","09651265523","76","10229235 794","92605156966","79693025163","24247486918","250*5.","34663768580","03086608463","39378025846","2(718063-2428","80(96a)649936"],"utilities":{"is-valid-cpf":{"kind":"validator","optionSets":[{}],"profiles":{"masked-strict":[false,false,false,false,false,false,true,true,true,true,true,true,true,true,false,false,false,false,false,false,false,false,true,true,true,true,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true,false,true,true,false,true,true,false,false,true,false,false,false,false,true,true,true,true,true,true,false,false,false,true,false,false,false,false,false,false,false,false,false,false,true,false,false,false,true,true,false,true,false,false,false,true,false,true,true,false,false,true,false,false,false,false,false,false,true,false,false,false,false,false,true,false,false,true,false,false,false,false,false,false,true,false,false,true,false,false,true,false,false,false,false,true,false,false,true,false,false,false,true,false,true,false,true,true,true,false,false,true,false,true,false,false,true,false,false,false,false,true,false,true,false,false,false,false,false,false,false,false,false,true,false,true,true,true,true,false,true,false,true,false,false,false,true,true,false,false,false,true,false,false,false,true,false,false,false,true,false,false,true,false,false,false,false,false,false,false,false,true,false,false,true,false,true,false,true,false,false,false,true,false,true,false,true,false,false,false,true,false,false,false,true,false,true,false,false,false,false,false,true,false,false,true,false,true,false,false,false,false,false,false,true,false,false,false,true,false,false,false,false,false,false,false,true,true,false,false,false,true,false,false,false,true,false,false,false,false,false,false,false,false,false,false,false,false,false,true,false,true,false,true,false,true,false,true,false,false,false,false,false,false,false,false,true,false,true,false,true,false,true,false,false,false,false,false,false,false,false,false,true,false,false,false,true,true,false,false,false,false,true,false,false,false,false,true,false,false,false,false,false,true,true,false,true,true,false,true,true,false,false,false,false,true,true,true,false,false,true,false,true,false,false,false,false,false,true,false,true,true,false,false,false,false,false,false,true,true,false,false,false,false,false,true,true,true,false,false,false,false,false,true,false,true,false,false,false,false,true,false,false,false,false,false,false,false,false,false,false,true,false,true,false,false,true,true,true,true,false,true,false,true,true,false,true,true,true,true,true,false,true,false,false,false,false,false,false,true,false,true,false,false,false,false,true,false,false,true,false,false,true,false,false,true,false,false,true,false,false,false,true,false,false,true,false,true,false,true,false,false,true,false,false,false,false,false,false,true,true,false,false,false,true,true,false,false,true,true,false,false,true,false,false,false,false,true,true,false,true,false,false,true,true,false,false,false,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true,true,false,false,false,false,true,false,false,false,true,false,true,false,true,true,true,true,false,true,false,false,false,false,false,false,false,false,false,true,false,false,false,false,false,false,true,false,false,true,false,true,true,true,false,false,true,false,true,false,false,false,true,true,false,false,true,true,false,true,true,false,false,true,true,false,true,false,true,false,false,true,false,false,false,false,true,false,true,false,true,false,false,true,false,false,true,true,false,false,false,false,true,true,false,true,false,true,false,false,false,false,true,false,false,true,false,true,false,true,false,false,false,false,false,false,true,false,false,false,false,false,true,false,false,false,true,true,true,false,false,true,false,false,true,true,false,true,false,true,false,false,true,false,false,true,true,false,false,false,true,false,false,false,true,true,false,false,false,false,false,false,false,false,false,false,false,false,true,false,false,false,false,false,true,false,false,false,true,false,false,false,true,true,true,true,true,false,false,false,true,true,false,false,false,true,false,true,false,false,false,true,false,true,false,false,true,false,true,false,false,false,false,true,true,false,false,true,false,true,false,true,true,true,false,false],"digits-only":[false,false,false,false,false,false,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true,false,true,true,false,true,true,false,false,true,false,false,false,false,true,true,true,true,true,true,false,false,false,true,false,false,false,false,false,false,false,false,false,false,true,false,false,false,true,true,false,true,false,false,false,true,false,true,true,false,false,true,false,false,false,false,false,false,true,false,false,false,false,false,true,false,false,true,false,false,false,false,false,false,true,false,false,true,false,false,true,false,false,false,false,true,false,false,true,false,false,false,true,false,true,false,true,true,true,false,false,true,false,true,false,false,true,false,false,false,false,true,false,true,false,false,false,false,false,false,false,false,false,true,false,true,true,true,true,false,true,false,true,false,false,false,true,true,false,false,false,true,false,false,false,true,false,false,false,false,false,false,true,false,false,false,false,false,false,false,false,true,false,false,true,false,true,false,true,false,false,false,true,false,true,false,true,false,false,false,true,false,false,false,true,false,true,false,false,false,false,false,true,false,false,true,false,true,false,false,false,false,false,false,true,false,false,false,true,false,false,false,false,false,false,false,true,true,false,false,false,true,false,false,false,true,false,false,false,false,false,false,false,false,false,false,false,false,false,true,false,true,false,true,false,true,false,true,false,false,false,false,false,false,false,false,true,false,true,false,true,false,false,false,false,false,false,false,false,false,false,false,true,false,false,false,true,true,false,false,false,false,true,false,false,false,false,true,false,false,false,false,false,true,true,false,true,true,false,true,true,false,false,false,false,true,true,true,false,false,true,false,true,false,false,false,false,false,true,false,true,true,false,false,false,false,false,false,true,true,false,false,false,false,false,true,true,true,false,false,false,false,false,true,false,true,false,false,false,false,true,false,false,false,false,false,false,false,false,false,false,true,false,true,false,false,true,false,true,true,false,true,false,true,true,false,true,false,true,true,true,false,true,false,false,false,false,false,false,true,false,true,false,false,false,false,true,false,false,true,false,false,true,false,false,true,false,false,true,false,false,false,true,false,false,true,false,true,false,true,false,false,true,false,false,false,false,false,false,true,true,false,false,false,true,true,false,false,true,true,false,false,true,false,false,false,false,true,true,false,true,false,false,true,true,false,false,false,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true,false,false,false,false,true,false,false,false,true,false,true,false,true,true,true,true,false,true,false,false,false,false,false,false,false,false,false,true,false,false,false,false,false,false,true,false,false,true,false,true,true,true,false,false,true,false,true,false,false,false,true,true,false,false,true,true,false,true,true,false,false,true,true,false,true,false,true,false,false,true,false,false,false,false,true,false,true,false,true,false,false,true,false,false,true,true,false,false,false,false,true,true,false,true,false,true,false,false,false,false,true,false,false,true,false,true,false,true,false,false,false,false,false,false,true,false,false,false,false,false,true,false,false,false,true,true,true,false,false,true,false,false,true,true,false,true,false,true,false,false,true,false,false,true,true,false,false,false,true,false,false,false,true,true,false,false,false,false,false,false,false,false,false,false,false,false,true,false,false,false,false,false,true,false,false,false,true,false,false,false,true,true,true,true,true,false,false,false,true,true,false,false,false,true,false,true,false,false,false,true,false,true,false,false,true,false,true,false,false,false,false,true,true,false,false,true,false,true,false,true,true,true,false,false],"digits-extracted":[false,false,false,false,false,false,true,true,true,true,true,true,true,true,true,true,false,false,true,true,true,false,true,true,true,true,true,true,true,false,false,false,false,false,false,false,false,false,false,false,false,false,true,false,true,true,false,true,true,false,false,true,false,false,false,false,true,true,true,true,true,true,false,false,true,true,false,true,false,false,false,false,false,false,false,false,true,false,false,false,true,true,false,true,false,false,false,true,false,true,true,false,false,true,false,false,false,false,false,true,true,false,false,false,true,false,true,true,false,true,false,false,false,false,false,false,true,false,false,true,true,false,true,false,false,false,false,true,false,false,true,false,false,false,true,false,true,false,true,true,true,false,false,true,false,true,false,false,true,false,false,false,true,true,false,true,false,false,false,false,false,false,false,false,false,true,false,true,true,true,true,false,true,false,true,false,false,false,true,true,false,false,false,true,false,false,false,true,true,true,false,true,false,false,true,false,true,true,false,false,false,false,false,true,false,false,true,false,true,true,true,false,false,false,true,false,true,false,true,false,true,false,true,true,false,false,true,false,true,false,true,false,false,false,true,false,false,true,false,true,true,false,true,false,false,false,true,false,false,false,true,false,false,false,false,false,false,false,true,true,false,false,false,true,false,false,false,true,true,false,false,false,true,false,false,true,false,true,false,false,false,true,false,true,false,true,false,true,true,true,false,true,false,false,false,false,false,false,true,true,true,false,true,false,true,true,false,false,false,false,true,false,false,false,true,false,false,false,true,true,true,false,false,false,true,false,false,false,true,true,true,true,false,false,false,true,true,true,true,true,false,true,true,true,false,true,false,true,true,true,true,false,true,false,true,false,true,true,true,false,true,false,true,true,true,false,false,true,false,false,true,true,false,false,false,false,false,true,true,true,true,false,false,false,false,true,false,true,false,false,false,false,true,true,false,false,false,false,true,false,false,false,false,true,true,true,false,false,true,true,true,true,false,true,false,true,true,false,true,true,true,true,true,true,true,false,false,false,false,true,false,true,false,true,false,false,false,false,true,false,false,true,true,false,true,false,false,true,false,false,true,false,false,false,true,false,false,true,false,true,false,true,true,false,true,true,false,true,false,false,false,true,true,true,false,true,true,true,false,false,true,true,false,true,true,false,false,true,false,true,true,true,true,false,false,true,true,false,false,false,true,false,false,false,false,false,false,false,true,false,false,false,false,false,true,false,false,true,true,false,false,false,false,true,false,false,false,true,false,true,false,true,true,true,true,false,true,false,false,false,false,false,false,false,true,false,true,false,false,true,false,true,false,true,false,false,true,false,true,true,true,false,true,true,false,true,false,false,true,true,true,false,false,true,true,false,true,true,true,true,true,true,false,true,false,true,false,false,true,false,false,false,false,true,true,true,true,true,false,false,true,false,false,true,true,false,false,false,false,true,true,false,true,true,true,false,false,false,false,true,false,true,true,false,true,false,true,true,false,false,false,false,false,true,false,true,false,false,true,true,false,true,false,true,true,true,false,false,true,false,false,true,true,false,true,false,true,false,true,true,false,false,true,true,true,false,false,true,false,true,false,true,true,false,false,false,false,false,false,true,false,false,false,false,true,true,false,false,false,false,false,true,true,false,false,true,false,false,false,true,true,true,true,true,true,false,false,true,true,false,true,false,true,false,true,true,false,false,true,false,true,false,false,true,false,true,false,false,false,false,true,true,false,true,true,false,true,false,true,true,true,false,false]}},"is-valid-pis":{"kind":"validator","optionSets":[{}],"profiles":{"masked-charset":[false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true,false,false,false,false,false,false,false,false,false,true,true,true,true,true,false,false,true,false,true,true,false,false,false,true,false,false,false,false,true,false,true,false,true,false,true,false,false,true,false,false,true,false,false,true,false,false,true,true,false,true,false,false,true,true,false,true,true,true,false,true,true,false,false,true,false,false,false,false,false,false,true,false,false,false,false,false,false,false,false,true,false,true,false,false,false,false,true,false,false,true,false,false,false,false,false,true,false,false,false,true,false,true,true,false,false,false,false,false,true,false,true,true,false,false,false,true,false,false,false,false,false,false,false,true,false,false,false,true,false,false,false,true,false,true,false,true,true,false,false,true,true,true,true,false,false,false,false,false,true,false,false,false,false,false,true,true,false,false,false,false,false,true,true,true,true,false,false,false,true,false,true,true,false,false,false,false,false,false,true,false,true,false,true,true,false,false,false,false,false,false,true,false,false,false,false,false,true,true,false,false,false,false,false,true,false,false,false,false,false,true,false,true,false,false,false,false,false,false,false,false,false,true,false,true,false,true,false,true,false,true,false,false,false,false,true,false,false,true,true,true,true,false,true,true,true,false,false,true,true,true,false,false,true,false,false,false,false,false,true,true,true,false,true,false,true,false,false,false,true,false,false,false,false,false,true,true,false,false,false,true,false,false,false,false,true,false,false,false,false,true,true,true,false,false,false,false,false,false,false,false,true,true,false,true,false,true,false,false,false,false,false,false,true,false,false,false,true,false,true,false,false,false,false,false,false,false,false,false,false,true,false,true,false,true,false,false,false,false,false,true,false,false,false,true,true,true,false,false,false,false,false,false,false,false,false,false,false,false,false,true,true,true,true,false,false,true,true,false,false,true,false,false,true,false,false,true,false,false,false,true,false,false,false,false,true,true,false,false,false,false,false,false,false,false,false,true,true,false,false,false,false,true,false,true,true,false,true,false,false,false,false,false,true,true,true,false,false,false,true,false,false,false,false,true,false,false,false,false,false,false,true,false,false,true,false,false,true,false,false,false,false,false,false,false,true,false,true,false,true,false,false,false,false,false,false,false,true,false,true,false,true,false,false,true,true,false,true,false,false,false,false,false,true,false,false,false,true,false,false,true,true,false,true,true,false,true,false,false,false,true,true,false,false,true,true,false,false,false,false,false,true,false,true,false,false,false,true,false,true,false,true,false,false,false,true,true,true,false,true,true,true,true,false,true,false,false,false,false,true,false,false,false,true,true,true,true,false,false,false,true,false,false,true,false,true,false,false,false,true,true,false,false,false,false,false,false,false,false,false,false,false,false,true,true,true,true,false,true,false,true,true,false,false,false,false,false,false,true,false,false,false,false,true,false,true,false,true,false,false,false,false,false,false,true,false,false,true,false,false,true,false,true,true,true,false,false,false,true,false,false,false,false,false,false,true,false,false,false,true,false,true,false,false,false,true,true,false,false,true,false,false,false,true,true,true,false,false,false,true,false,false,false,false,true,true,false,false,false,false,false,false,false,true,true,true,true,true,false,true,false,false,false,false,false,false,true,true,false,false,true,false,false,false,false,false,false,true,false,false,false,false,true,false,true,false,false,false,true,false,false,false,true,false,false,true,false,false,true,false,true,true,false,true,false,false,true,true,true,false,false,false,false,true,false,false,false,true,false,false,true,false],"digits-only-lenient":[false,false,false,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true,false,false,false,false,false,false,false,false,false,true,false,false,false,false,false,false,false,false,true,true,false,false,false,true,false,false,false,false,true,false,true,false,true,false,true,false,false,true,false,false,true,false,false,true,false,false,false,true,false,true,false,false,false,false,false,true,false,true,false,true,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true,false,true,false,false,false,false,false,false,false,true,false,false,false,false,false,true,false,false,false,true,false,true,true,false,false,false,false,false,true,false,false,true,false,false,false,false,false,false,false,false,false,false,false,true,false,false,false,false,false,false,false,true,false,true,false,true,true,false,false,true,false,true,true,false,false,false,false,false,true,false,false,false,false,false,false,true,false,false,false,false,false,true,false,true,true,false,false,false,true,false,false,true,false,false,false,false,false,false,false,false,true,false,false,false,false,false,false,false,false,false,true,false,false,false,false,false,true,true,false,false,false,false,false,false,false,false,false,false,false,true,false,true,false,false,false,false,false,false,false,false,false,true,false,true,false,true,false,true,false,true,false,false,false,false,false,false,false,true,true,true,true,false,true,false,false,false,false,true,true,true,false,false,true,false,false,false,false,false,true,true,true,false,true,false,true,false,false,false,true,false,false,false,false,false,true,true,false,false,false,true,false,false,false,false,false,false,false,false,false,true,true,false,false,false,false,false,false,false,false,false,true,true,false,true,false,false,false,false,false,false,false,false,true,false,false,false,true,false,true,false,false,false,false,false,false,false,false,false,false,true,false,true,false,true,false,false,false,false,false,true,false,false,false,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true,true,false,true,false,false,true,true,false,false,false,false,false,true,false,false,true,false,false,false,true,false,false,false,false,true,true,false,false,false,false,false,false,false,false,false,true,true,false,false,false,false,false,false,true,true,false,true,false,false,false,false,false,false,true,true,false,false,false,true,false,false,false,false,true,false,false,false,false,false,false,true,false,false,true,false,false,true,false,false,false,false,false,false,false,true,false,false,false,false,false,false,false,false,false,false,false,true,false,true,false,true,false,false,true,false,false,true,false,false,false,false,false,true,false,false,false,true,false,false,false,true,false,false,true,false,true,false,false,false,true,true,false,false,false,true,false,false,false,false,false,true,false,false,false,false,false,false,false,true,false,true,false,false,false,true,false,true,false,true,false,false,true,false,false,false,false,false,false,false,false,false,false,true,true,true,true,false,false,false,true,false,false,false,false,true,false,false,false,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true,true,false,false,true,false,false,true,false,false,false,false,false,false,false,false,false,false,false,true,false,false,false,true,false,false,false,false,false,false,true,false,false,true,false,false,false,false,true,true,true,false,false,false,true,false,false,false,false,false,false,true,false,false,false,true,false,true,false,false,false,true,false,false,false,false,false,false,false,true,false,true,false,false,false,true,false,false,false,false,true,true,false,false,false,false,false,false,false,true,true,true,true,true,false,false,false,false,false,false,false,false,true,true,false,false,true,false,false,false,false,false,false,true,false,false,false,false,true,false,false,false,false,false,true,false,false,false,true,false,false,true,false,false,false,false,true,true,false,false,false,false,true,false,true,false,false,false,false,true,false,false,false,true,false,false,false,false]}},"format-cpf":{"kind":"formatter","optionSets":[{},{"obfuscate":true},{"pad":true},{"pad":true,"obfuscate":true}],"profiles":{"pattern-partial":[["","","000.000.000-00","***.000.000-**"],["","","000.000.000-00","***.000.000-**"],["0","*","000.000.000-00","***.000.000-**"],["000.000.000-00","***.000.000-**","000.000.000-00","***.000.000-**"],["111.111.111-11","***.111.111-**","111.111.111-11","***.111.111-**"],["999.999.999-99","***.999.999-**","999.999.999-99","***.999.999-**"],["123.456.789-09","***.456.789-**","123.456.789-09","***.456.789-**"],["123.456.789-09","***.456.789-**","123.456.789-09","***.456.789-**"],["123.456.789-09","***.456.789-**","123.456.789-09","***.456.789-**"],["123.456.789-09","***.456.789-**","123.456.789-09","***.456.789-**"],["123.456.789-09","***.456.789-**","123.456.789-09","***.456.789-**"],["123.456.789-09","***.456.789-**","123.456.789-09","***.456.789-**"],["123.456.789-09","***.456.789-**","123.456.789-09","***.456.789-**"],["123.456.789-09","***.456.789-**","123.456.789-09","***.456.789-**"],["123.456.789-09","***.456.789-**","123.456.789-09","***.456.789-**"],["123.456.789-09","***.456.789-**","123.456.789-09","***.456.789-**"],["123.456.789-0","***.456.789-*","012.345.678-90","***.345.678-**"],["123.456.789-09","***.456.789-**","123.456.789-09","***.456.789-**"],["123.456.789-09","***.456.789-**","123.456.789-09","***.456.789-**"],["123.456.789-09","***.456.789-**","123.456.789-09","***.456.789-**"],["123.456.789-09","***.456.789-**","123.456.789-09","***.456.789-**"],["123.456.789-00","***.456.789-**","123.456.789-00","***.456.789-**"],["123.456.789-09","***.456.789-**","123.456.789-09","***.456.789-**"],["123.456.789-09","***.456.789-**","123.456.789-09","***.456.789-**"],["123.456.789-09","***.456.789-**","123.456.789-09","***.456.789-**"],["123.456.789-09","***.456.789-**","123.456.789-09","***.456.789-**"],["123.456.789-09","***.456.789-**","123.456.789-09","***.456.789-**"],["123.456.789-09","***.456.789-**","123.456.789-09","***.456.789-**"],["123.456.789-09","***.456.789-**","123.456.789-09","***.456.789-**"],["","","000.000.000-00","***.000.000-**"],["","","000.000.000-00","***.000.000-**"],["120.568.741-07","***.568.741-**","120.568.741-07","***.568.741-**"],["120.568.741-07","***.568.741-**","120.568.741-07","***.568.741-**"],["120.568.741-07","***.568.741-**","120.568.741-07","***.568.741-**"],["120.568.741-07","***.568.741-**","120.568.741-07","***.568.741-**"],["120.568.741-07","***.568.741-**","120.568.741-07","***.568.741-**"],["120.568.741-08","***.568.741-**","120.568.741-08","***.568.741-**"],["120.568.741-0","***.568.741-*","012.056.874-10","***.056.874-**"],["120.568.741-07","***.568.741-**","120.568.741-07","***.568.741-**"],["120.568.741-07","***.568.741-**","120.568.741-07","***.568.741-**"],["742.757.335-68","***.757.335-**","742.757.335-68","***.757.335-**"],["692.642.592-94","***.642.592-**","692.642.592-94","***.642.592-**"],["275.026.776-58","***.026.776-**","275.026.776-58","***.026.776-**"],["951.673","***.673","000.009.516-73","***.009.516-**"],["455.287.462-48","***.287.462-**","455.287.462-48","***.287.462-**"],["001.925.910-70","***.925.910-**","001.925.910-70","***.925.910-**"],["242.337.996-70","***.337.996-**","242.337.996-70","***.337.996-**"],["043.493.162-48","***.493.162-**","043.493.162-48","***.493.162-**"],["058.280.337-35","***.280.337-**","058.280.337-35","***.280.337-**"],["340.6","***.6","000.000.034-06","***.000.034-**"],["010.180.547-71","***.180.547-**","010.180.547-71","***.180.547-**"],["459.609.678-39","***.609.678-**","459.609.678-39","***.609.678-**"],["729.535.593-75","***.535.593-**","729.535.593-75","***.535.593-**"],["350.676.337-17","***.676.337-**","350.676.337-17","***.676.337-**"],["857.527.887-60","***.527.887-**","857.527.887-60","***.527.887-**"],["122.014.610-35","***.014.610-**","122.014.610-35","***.014.610-**"],["656.235.973-27","***.235.973-**","656.235.973-27","***.235.973-**"],["082.162.626-47","***.162.626-**","082.162.626-47","***.162.626-**"],["942.914.972-53","***.914.972-**","942.914.972-53","***.914.972-**"],["655.466.786-58","***.466.786-**","655.466.786-58","***.466.786-**"],["022.180.106-58","***.180.106-**","022.180.106-58","***.180.106-**"],["134.346.089-15","***.346.089-**","134.346.089-15","***.346.089-**"],["600.215.969-17","***.215.969-**","600.215.969-17","***.215.969-**"],["992.663.216-88","***.663.216-**","992.663.216-88","***.663.216-**"],["036.669.424-31","***.669.424-**","036.669.424-31","***.669.424-**"],["290.227.963-96","***.227.963-**","290.227.963-96","***.227.963-**"],["659.037","***.037","000.006.590-37","***.006.590-**"],["610.954.584-85","***.954.584-**","610.954.584-85","***.954.584-**"],["573.641.832-96","***.641.832-**","573.641.832-96","***.641.832-**"],["724.681.246-05","***.681.246-**","724.681.246-05","***.681.246-**"],["013.660.215-78","***.660.215-**","013.660.215-78","***.660.215-**"],["372.425.077-00","***.425.077-**","372.425.077-00","***.425.077-**"],["659.684.184-86","***.684.184-**","659.684.184-86","***.684.184-**"],["646.293.942-34","***.293.942-**","646.293.942-34","***.293.942-**"],["898.841.977-02","***.841.977-**","898.841.977-02","***.841.977-**"],["588.519.746-61","***.519.746-**","588.519.746-61","***.519.746-**"],["067.339.637-10","***.339.637-**","067.339.637-10","***.339.637-**"],["161.534.166-09","***.534.166-**","161.534.166-09","***.534.166-**"],["973.194.655-20","***.194.655-**","973.194.655-20","***.194.655-**"],["834.386.585-34","***.386.585-**","834.386.585-34","***.386.585-**"],["489.381.054-58","***.381.054-**","489.381.054-58","***.381.054-**"],["520.705.644-10","***.705.644-**","520.705.644-10","***.705.644-**"],["372.994.928-50","***.994.928-**","372.994.928-50","***.994.928-**"],["971.165.013-47","***.165.013-**","971.165.013-47","***.165.013-**"],["267.783.456-65","***.783.456-**","267.783.456-65","***.783.456-**"],["715.653.418-11","***.653.418-**","715.653.418-11","***.653.418-**"],["193.000.765-85","***.000.765-**","193.000.765-85","***.000.765-**"],["326.057.798-07","***.057.798-**","326.057.798-07","***.057.798-**"],["818.871.917-06","***.871.917-**","818.871.917-06","***.871.917-**"],["601.502.471-25","***.502.471-**","601.502.471-25","***.502.471-**"],["717.708.895-40","***.708.895-**","717.708.895-40","***.708.895-**"],["383.061.730-04","***.061.730-**","383.061.730-04","***.061.730-**"],["635.680.628-66","***.680.628-**","635.680.628-66","***.680.628-**"],["137.656.313-45","***.656.313-**","137.656.313-45","***.656.313-**"],["968.408.342-66","***.408.342-**","968.408.342-66","***.408.342-**"],["875.662.566-01","***.662.566-**","875.662.566-01","***.662.566-**"],["170.605","***.605","000.001.706-05","***.001.706-**"],["478.089.322-0","***.089.322-*","047.808.932-20","***.808.932-**"],["977.030.00","***.030.00","000.977.030-00","***.977.030-**"],["660.299.248-18","***.299.248-**","660.299.248-18","***.299.248-**"],["253.681.039-99","***.681.039-**","253.681.039-99","***.681.039-**"],["150.507.577-07","***.507.577-**","150.507.577-07","***.507.577-**"],["493.545.5","***.545.5","000.049.354-55","***.049.354-**"],["236.096.401-26","***.096.401-**","236.096.401-26","***.096.401-**"],["758.781.474-40","***.781.474-**","758.781.474-40","***.781.474-**"],["952.919.320-24","***.919.320-**","952.919.320-24","***.919.320-**"],["327.117.213-70","***.117.213-**","327.117.213-70","***.117.213-**"],["258.163.547-95","***.163.547-**","258.163.547-95","***.163.547-**"],["707.612.876-64","***.612.876-**","707.612.876-64","***.612.876-**"],["401.109.658-09","***.109.658-**","401.109.658-09","***.109.658-**"],["549","***","000.000.005-49","***.000.005-**"],["625.017.835-55","***.017.835-**","625.017.835-55","***.017.835-**"],["385.535.232-3","***.535.232-*","038.553.523-23","***.553.523-**"],["001.583.790-99","***.583.790-**","001.583.790-99","***.583.790-**"],["210.625.74","***.625.74","000.210.625-74","***.210.625-**"],["636.740.6","***.740.6","000.063.674-06","***.063.674-**"],["946.220.892-11","***.220.892-**","946.220.892-11","***.220.892-**"],["859.472.699-15","***.472.699-**","859.472.699-15","***.472.699-**"],["869.824.7","***.824.7","000.086.982-47","***.086.982-**"],["309.534.527-51","***.534.527-**","309.534.527-51","***.534.527-**"],["555.420.440-69","***.420.440-**","555.420.440-69","***.420.440-**"],["878.214.259-57","***.214.259-**","878.214.259-57","***.214.259-**"],["103.597.230-12","***.597.230-**","103.597.230-12","***.597.230-**"],["385.896.263-69","***.896.263-**","385.896.263-69","***.896.263-**"],["170.914.219-71","***.914.219-**","170.914.219-71","***.914.219-**"],["649.982.928-30","***.982.928-**","649.982.928-30","***.982.928-**"],["737.925","***.925","000.007.379-25","***.007.379-**"],["517.236.689-07","***.236.689-**","517.236.689-07","***.236.689-**"],["035.307.750-1","***.307.750-*","003.530.775-01","***.530.775-**"],["138.196.424-20","***.196.424-**","138.196.424-20","***.196.424-**"],["299.724.486-22","***.724.486-**","299.724.486-22","***.724.486-**"],["896.084.210-27","***.084.210-**","896.084.210-27","***.084.210-**"],["142.563.725-00","***.563.725-**","142.563.725-00","***.563.725-**"],["554.273.590-71","***.273.590-**","554.273.590-71","***.273.590-**"],["638.764.089-03","***.764.089-**","638.764.089-03","***.764.089-**"],["106","***","000.000.001-06","***.000.001-**"],["533.678.958-57","***.678.958-**","533.678.958-57","***.678.958-**"],["500.978.209-93","***.978.209-**","500.978.209-93","***.978.209-**"],["324.988.564-98","***.988.564-**","324.988.564-98","***.988.564-**"],["365.588.462-17","***.588.462-**","365.588.462-17","***.588.462-**"],["261.475.992-91","***.475.992-**","261.475.992-91","***.475.992-**"],["192.4","***.4","000.000.019-24","***.000.019-**"],["756.602.109-33","***.602.109-**","756.602.109-33","***.602.109-**"],["939.710.336-95","***.710.336-**","939.710.336-95","***.710.336-**"],["522.000.902-53","***.000.902-**","522.000.902-53","***.000.902-**"],["384.762.726-00","***.762.726-**","384.762.726-00","***.762.726-**"],["378.447.344-33","***.447.344-**","378.447.344-33","***.447.344-**"],["069.263.407-51","***.263.407-**","069.263.407-51","***.263.407-**"],["591.394.668-50","***.394.668-**","591.394.668-50","***.394.668-**"],["687.953.385-70","***.953.385-**","687.953.385-70","***.953.385-**"],["873.732.381-38","***.732.381-**","873.732.381-38","***.732.381-**"],["951","***","000.000.009-51","***.000.009-**"],["641.350.042-53","***.350.042-**","641.350.042-53","***.350.042-**"],["409.109.630-10","***.109.630-**","409.109.630-10","***.109.630-**"],["268.067.823-78","***.067.823-**","268.067.823-78","***.067.823-**"],["837.234.185-03","***.234.185-**","837.234.185-03","***.234.185-**"],["758.131.6","***.131.6","000.075.813-16","***.075.813-**"],["202.409.071-37","***.409.071-**","202.409.071-37","***.409.071-**"],["335.201.412-68","***.201.412-**","335.201.412-68","***.201.412-**"],["179.38","***.38","000.000.179-38","***.000.179-**"],["102.134.072-17","***.134.072-**","102.134.072-17","***.134.072-**"],["667.383.972-99","***.383.972-**","667.383.972-99","***.383.972-**"],["459.216.657-41","***.216.657-**","459.216.657-41","***.216.657-**"],["054.669.167-70","***.669.167-**","054.669.167-70","***.669.167-**"],["627.622.669-10","***.622.669-**","627.622.669-10","***.622.669-**"],["849.112.629-58","***.112.629-**","849.112.629-58","***.112.629-**"],["818.264.252-90","***.264.252-**","818.264.252-90","***.264.252-**"],["892.059.852-52","***.059.852-**","892.059.852-52","***.059.852-**"],["054.960.534-71","***.960.534-**","054.960.534-71","***.960.534-**"],["525.973.933-72","***.973.933-**","525.973.933-72","***.973.933-**"],["386.522.205-65","***.522.205-**","386.522.205-65","***.522.205-**"],["178.999.336-52","***.999.336-**","178.999.336-52","***.999.336-**"],["222.790.475-51","***.790.475-**","222.790.475-51","***.790.475-**"],["154.816.477-40","***.816.477-**","154.816.477-40","***.816.477-**"],["541.300.827-95","***.300.827-**","541.300.827-95","***.300.827-**"],["234.421.855-71","***.421.855-**","234.421.855-71","***.421.855-**"],["905.000.809-04","***.000.809-**","905.000.809-04","***.000.809-**"],["842.642.595-22","***.642.595-**","842.642.595-22","***.642.595-**"],["589.768.017-50","***.768.017-**","589.768.017-50","***.768.017-**"],["206.487.406-25","***.487.406-**","206.487.406-25","***.487.406-**"],["573.421.472-91","***.421.472-**","573.421.472-91","***.421.472-**"],["8","*","000.000.000-08","***.000.000-**"],["067.879.154-80","***.879.154-**","067.879.154-80","***.879.154-**"],["749.949.997-91","***.949.997-**","749.949.997-91","***.949.997-**"],["308.351.266-00","***.351.266-**","308.351.266-00","***.351.266-**"],["336.644.463-41","***.644.463-**","336.644.463-41","***.644.463-**"],["720.842.870-28","***.842.870-**","720.842.870-28","***.842.870-**"],["626.103.959-30","***.103.959-**","626.103.959-30","***.103.959-**"],["390.835.940-68","***.835.940-**","390.835.940-68","***.835.940-**"],["294.629.944-98","***.629.944-**","294.629.944-98","***.629.944-**"],["878.620.977-41","***.620.977-**","878.620.977-41","***.620.977-**"],["148.965.245-00","***.965.245-**","148.965.245-00","***.965.245-**"],["454.930.241-82","***.930.241-**","454.930.241-82","***.930.241-**"],["439.558.229-83","***.558.229-**","439.558.229-83","***.558.229-**"],["495.454.403-33","***.454.403-**","495.454.403-33","***.454.403-**"],["008.387.125-51","***.387.125-**","008.387.125-51","***.387.125-**"],["569.399.571-20","***.399.571-**","569.399.571-20","***.399.571-**"],["794.676.345-03","***.676.345-**","794.676.345-03","***.676.345-**"],["901.177.609-52","***.177.609-**","901.177.609-52","***.177.609-**"],["6","*","000.000.000-06","***.000.000-**"],["450.262.548-83","***.262.548-**","450.262.548-83","***.262.548-**"],["717.334.855-02","***.334.855-**","717.334.855-02","***.334.855-**"],["599.209.135-63","***.209.135-**","599.209.135-63","***.209.135-**"],["140.796.801-71","***.796.801-**","140.796.801-71","***.796.801-**"],["067.377.820-12","***.377.820-**","067.377.820-12","***.377.820-**"],["768.373.575-51","***.373.575-**","768.373.575-51","***.373.575-**"],["438.557.083-39","***.557.083-**","438.557.083-39","***.557.083-**"],["262.739.375-61","***.739.375-**","262.739.375-61","***.739.375-**"],["668.462.685-96","***.462.685-**","668.462.685-96","***.462.685-**"],["843.356.403-07","***.356.403-**","843.356.403-07","***.356.403-**"],["127.109.736-26","***.109.736-**","127.109.736-26","***.109.736-**"],["608.052.223-00","***.052.223-**","608.052.223-00","***.052.223-**"],["364.537.167-69","***.537.167-**","364.537.167-69","***.537.167-**"],["807.161.895-38","***.161.895-**","807.161.895-38","***.161.895-**"],["968.751.151-66","***.751.151-**","968.751.151-66","***.751.151-**"],["743.369.448-41","***.369.448-**","743.369.448-41","***.369.448-**"],["310.923.973-61","***.923.973-**","310.923.973-61","***.923.973-**"],["163.481.721-39","***.481.721-**","163.481.721-39","***.481.721-**"],["381.469.865-79","***.469.865-**","381.469.865-79","***.469.865-**"],["241.446.800-90","***.446.800-**","241.446.800-90","***.446.800-**"],["358.186.392-82","***.186.392-**","358.186.392-82","***.186.392-**"],["0","*","000.000.000-00","***.000.000-**"],["503.734.632-00","***.734.632-**","503.734.632-00","***.734.632-**"],["766.122.010-53","***.122.010-**","766.122.010-53","***.122.010-**"],["550.231.980","***.231.980","005.502.319-80","***.502.319-**"],["385.784.989-50","***.784.989-**","385.784.989-50","***.784.989-**"],["847.859.775-15","***.859.775-**","847.859.775-15","***.859.775-**"],["349.571.075-92","***.571.075-**","349.571.075-92","***.571.075-**"],["905.346.609-67","***.346.609-**","905.346.609-67","***.346.609-**"],["218.383.615","***.383.615","002.183.836-15","***.183.836-**"],["188.139.293-74","***.139.293-**","188.139.293-74","***.139.293-**"],["256.250.906-03","***.250.906-**","256.250.906-03","***.250.906-**"],["14","**","000.000.000-14","***.000.000-**"],["678.179.056-35","***.179.056-**","678.179.056-35","***.179.056-**"],["451.858.175-00","***.858.175-**","451.858.175-00","***.858.175-**"],["625.919.975-15","***.919.975-**","625.919.975-15","***.919.975-**"],["948.664.060-05","***.664.060-**","948.664.060-05","***.664.060-**"],["489.869.813-19","***.869.813-**","489.869.813-19","***.869.813-**"],["481.896.956-21","***.896.956-**","481.896.956-21","***.896.956-**"],["128.473.716-05","***.473.716-**","128.473.716-05","***.473.716-**"],["027.127.818-80","***.127.818-**","027.127.818-80","***.127.818-**"],["505.906.772-01","***.906.772-**","505.906.772-01","***.906.772-**"],["113.086.121-09","***.086.121-**","113.086.121-09","***.086.121-**"],["854.529.225-41","***.529.225-**","854.529.225-41","***.529.225-**"],["165.789.388-27","***.789.388-**","165.789.388-27","***.789.388-**"],["060.543.964-16","***.543.964-**","060.543.964-16","***.543.964-**"],["946.809.205-48","***.809.205-**","946.809.205-48","***.809.205-**"],["696.050.299-60","***.050.299-**","696.050.299-60","***.050.299-**"],["640.603.683-30","***.603.683-**","640.603.683-30","***.603.683-**"],["798.702.973-38","***.702.973-**","798.702.973-38","***.702.973-**"],["713.273.603-57","***.273.603-**","713.273.603-57","***.273.603-**"],["068.337.612-41","***.337.612-**","068.337.612-41","***.337.612-**"],["319.530.171-04","***.530.171-**","319.530.171-04","***.530.171-**"],["218.811.390-70","***.811.390-**","218.811.390-70","***.811.390-**"],["036.210.901-28","***.210.901-**","036.210.901-28","***.210.901-**"],["088.458.018-75","***.458.018-**","088.458.018-75","***.458.018-**"],["660.811.783-80","***.811.783-**","660.811.783-80","***.811.783-**"],["991.593.672-0","***.593.672-*","099.159.367-20","***.159.367-**"],["199.297.039-42","***.297.039-**","199.297.039-42","***.297.039-**"],["651.349.831-78","***.349.831-**","651.349.831-78","***.349.831-**"],["561.271.594-82","***.271.594-**","561.271.594-82","***.271.594-**"],["139.056.747-09","***.056.747-**","139.056.747-09","***.056.747-**"],["354.878.163-69","***.878.163-**","354.878.163-69","***.878.163-**"],["011.046.125-85","***.046.125-**","011.046.125-85","***.046.125-**"],["491.478.689-07","***.478.689-**","491.478.689-07","***.478.689-**"],["817.583.798-85","***.583.798-**","817.583.798-85","***.583.798-**"],["195.826.039-44","***.826.039-**","195.826.039-44","***.826.039-**"],["128.573.303-75","***.573.303-**","128.573.303-75","***.573.303-**"],["395.103.397-50","***.103.397-**","395.103.397-50","***.103.397-**"],["578.781.242-70","***.781.242-**","578.781.242-70","***.781.242-**"],["067.709.323-11","***.709.323-**","067.709.323-11","***.709.323-**"],["293.956.168-90","***.956.168-**","293.956.168-90","***.956.168-**"],["504.138.906-35","***.138.906-**","504.138.906-35","***.138.906-**"],["3","*","000.000.000-03","***.000.000-**"],["547.119.810-85","***.119.810-**","547.119.810-85","***.119.810-**"],["277.047.048-50","***.047.048-**","277.047.048-50","***.047.048-**"],["467.570.732-97","***.570.732-**","467.570.732-97","***.570.732-**"],["391.878.681-13","***.878.681-**","391.878.681-13","***.878.681-**"],["822.2","***.2","000.000.082-22","***.000.082-**"],["096.241.579-70","***.241.579-**","096.241.579-70","***.241.579-**"],["208.626.810-19","***.626.810-**","208.626.810-19","***.626.810-**"],["658.458.062-83","***.458.062-**","658.458.062-83","***.458.062-**"],["781.553.255-11","***.553.255-**","781.553.255-11","***.553.255-**"],["912.465.249-02","***.465.249-**","912.465.249-02","***.465.249-**"],["850.377.224-40","***.377.224-**","850.377.224-40","***.377.224-**"],["060.728.299-10","***.728.299-**","060.728.299-10","***.728.299-**"],["190.066.213-85","***.066.213-**","190.066.213-85","***.066.213-**"],["918.220.826-33","***.220.826-**","918.220.826-33","***.220.826-**"],["284.003.762-93","***.003.762-**","284.003.762-93","***.003.762-**"],["245.846.481-58","***.846.481-**","245.846.481-58","***.846.481-**"],["817.654.316-68","***.654.316-**","817.654.316-68","***.654.316-**"],["901.250.125-35","***.250.125-**","901.250.125-35","***.250.125-**"],["424.304.989-44","***.304.989-**","424.304.989-44","***.304.989-**"],["287.204.088-22","***.204.088-**","287.204.088-22","***.204.088-**"],["467.415.030-16","***.415.030-**","467.415.030-16","***.415.030-**"],["58","**","000.000.000-58","***.000.000-**"],["357.386.545-93","***.386.545-**","357.386.545-93","***.386.545-**"],["495.711.122-70","***.711.122-**","495.711.122-70","***.711.122-**"],["701.164.557-80","***.164.557-**","701.164.557-80","***.164.557-**"],["704.945.448-64","***.945.448-**","704.945.448-64","***.945.448-**"],["631.085.833-52","***.085.833-**","631.085.833-52","***.085.833-**"],["518.320.689-39","***.320.689-**","518.320.689-39","***.320.689-**"],["996.655.903-59","***.655.903-**","996.655.903-59","***.655.903-**"],["323.75","***.75","000.000.323-75","***.000.323-**"],["871.209.104-93","***.209.104-**","871.209.104-93","***.209.104-**"],["677.066.965-02","***.066.965-**","677.066.965-02","***.066.965-**"],["749.103.212-92","***.103.212-**","749.103.212-92","***.103.212-**"],["588.252.369-83","***.252.369-**","588.252.369-83","***.252.369-**"],["916.658.971-13","***.658.971-**","916.658.971-13","***.658.971-**"],["224.736.722-20","***.736.722-**","224.736.722-20","***.736.722-**"],["503.330.315-55","***.330.315-**","503.330.315-55","***.330.315-**"],["393.768.250-44","***.768.250-**","393.768.250-44","***.768.250-**"],["163.268.343-34","***.268.343-**","163.268.343-34","***.268.343-**"],["318.540.697-98","***.540.697-**","318.540.697-98","***.540.697-**"],["866.763.984-27","***.763.984-**","866.763.984-27","***.763.984-**"],["104.783","***.783","000.001.047-83","***.001.047-**"],["072.031.604-35","***.031.604-**","072.031.604-35","***.031.604-**"],["7","*","000.000.000-07","***.000.000-**"],["540.418.281-47","***.418.281-**","540.418.281-47","***.418.281-**"],["819.392.325-11","***.392.325-**","819.392.325-11","***.392.325-**"],["033.789.079-08","***.789.079-**","033.789.079-08","***.789.079-**"],["720.613","***.613","000.007.206-13","***.007.206-**"],["360.813.122-03","***.813.122-**","360.813.122-03","***.813.122-**"],["148.274.451-13","***.274.451-**","148.274.451-13","***.274.451-**"],["900.949.621-03","***.949.621-**","900.949.621-03","***.949.621-**"],["893.932.068-50","***.932.068-**","893.932.068-50","***.932.068-**"],["378.450.845-53","***.450.845-**","378.450.845-53","***.450.845-**"],["775.319.793-91","***.319.793-**","775.319.793-91","***.319.793-**"],["335.949.050-98","***.949.050-**","335.949.050-98","***.949.050-**"],["805.313.864-06","***.313.864-**","805.313.864-06","***.313.864-**"],["574.066.811-51","***.066.811-**","574.066.811-51","***.066.811-**"],["912.312.875-51","***.312.875-**","912.312.875-51","***.312.875-**"],["415","***","000.000.004-15","***.000.004-**"],["620.679.308-91","***.679.308-**","620.679.308-91","***.679.308-**"],["440.902.851-41","***.902.851-**","440.902.851-41","***.902.851-**"],["674.899.794-12","***.899.794-**","674.899.794-12","***.899.794-**"],["116.809.196-95","***.809.196-**","116.809.196-95","***.809.196-**"],["329.341.678-01","***.341.678-**","329.341.678-01","***.341.678-**"],["299.275.353-09","***.275.353-**","299.275.353-09","***.275.353-**"],["688.163.203-70","***.163.203-**","688.163.203-70","***.163.203-**"],["327.452.564-39","***.452.564-**","327.452.564-39","***.452.564-**"],["495.931.279-33","***.931.279-**","495.931.279-33","***.931.279-**"],["777.911.178-43","***.911.178-**","777.911.178-43","***.911.178-**"],["491.378.845-06","***.378.845-**","491.378.845-06","***.378.845-**"],["097.947.41","***.947.41","000.097.947-41","***.097.947-**"],["932.232.431-78","***.232.431-**","932.232.431-78","***.232.431-**"],["282.958.210-05","***.958.210-**","282.958.210-05","***.958.210-**"],["332.123.446-79","***.123.446-**","332.123.446-79","***.123.446-**"],["777.620.413-70","***.620.413-**","777.620.413-70","***.620.413-**"],["953.735.104-16","***.735.104-**","953.735.104-16","***.735.104-**"],["644.891.536-27","***.891.536-**","644.891.536-27","***.891.536-**"],["427.946.720-14","***.946.720-**","427.946.720-14","***.946.720-**"],["932.068.398-07","***.068.398-**","932.068.398-07","***.068.398-**"],["404.281.399-80","***.281.399-**","404.281.399-80","***.281.399-**"],["270.027.530-61","***.027.530-**","270.027.530-61","***.027.530-**"],["160.419.098-91","***.419.098-**","160.419.098-91","***.419.098-**"],["593.995.456-10","***.995.456-**","593.995.456-10","***.995.456-**"],["043.818.998-14","***.818.998-**","043.818.998-14","***.818.998-**"],["680.670.367-48","***.670.367-**","680.670.367-48","***.670.367-**"],["760.838.385-06","***.838.385-**","760.838.385-06","***.838.385-**"],["465.086.646-46","***.086.646-**","465.086.646-46","***.086.646-**"],["642.048.326-71","***.048.326-**","642.048.326-71","***.048.326-**"],["035.849.498-23","***.849.498-**","035.849.498-23","***.849.498-**"],["829.765.743-40","***.765.743-**","829.765.743-40","***.765.743-**"],["721.351.510-17","***.351.510-**","721.351.510-17","***.351.510-**"],["124.350.770-94","***.350.770-**","124.350.770-94","***.350.770-**"],["997.700.041-98","***.700.041-**","997.700.041-98","***.700.041-**"],["388.993.879-58","***.993.879-**","388.993.879-58","***.993.879-**"],["699.367.677-72","***.367.677-**","699.367.677-72","***.367.677-**"],["915.530.482-20","***.530.482-**","915.530.482-20","***.530.482-**"],["826.748.097-87","***.748.097-**","826.748.097-87","***.748.097-**"],["327.827.816-00","***.827.816-**","327.827.816-00","***.827.816-**"],["130.258.1","***.258.1","000.013.025-81","***.013.025-**"],["301.419.265-80","***.419.265-**","301.419.265-80","***.419.265-**"],["990.647.782-58","***.647.782-**","990.647.782-58","***.647.782-**"],["824.460.621-8","***.460.621-*","082.446.062-18","***.446.062-**"],["701.407.510-09","***.407.510-**","701.407.510-09","***.407.510-**"],["797.749.251-22","***.749.251-**","797.749.251-22","***.749.251-**"],["452.943.389-71","***.943.389-**","452.943.389-71","***.943.389-**"],["677.156.778-84","***.156.778-**","677.156.778-84","***.156.778-**"],["103.615.865-90","***.615.865-**","103.615.865-90","***.615.865-**"],["221.156.793-41","***.156.793-**","221.156.793-41","***.156.793-**"],["020.408.846-23","***.408.846-**","020.408.846-23","***.408.846-**"],["869.560.262-38","***.560.262-**","869.560.262-38","***.560.262-**"],["881.425.881-17","***.425.881-**","881.425.881-17","***.425.881-**"],["457.168.957-86","***.168.957-**","457.168.957-86","***.168.957-**"],["351.634.044-80","***.634.044-**","351.634.044-80","***.634.044-**"],["929.957.774-99","***.957.774-**","929.957.774-99","***.957.774-**"],["177.100.071-88","***.100.071-**","177.100.071-88","***.100.071-**"],["358.717.487-81","***.717.487-**","358.717.487-81","***.717.487-**"],["255.702.956-10","***.702.956-**","255.702.956-10","***.702.956-**"],["040.468.850-75","***.468.850-**","040.468.850-75","***.468.850-**"],["731.444.456-06","***.444.456-**","731.444.456-06","***.444.456-**"],["750.868.805-80","***.868.805-**","750.868.805-80","***.868.805-**"],["036.703.555-55","***.703.555-**","036.703.555-55","***.703.555-**"],["02","**","000.000.000-02","***.000.000-**"],["434","***","000.000.004-34","***.000.004-**"],["597.289.431-07","***.289.431-**","597.289.431-07","***.289.431-**"],["408.030.882-56","***.030.882-**","408.030.882-56","***.030.882-**"],["370","***","000.000.003-70","***.000.003-**"],["570.494.603-87","***.494.603-**","570.494.603-87","***.494.603-**"],["420.245.272-09","***.245.272-**","420.245.272-09","***.245.272-**"],["502.245.874-36","***.245.874-**","502.245.874-36","***.245.874-**"],["336.899.764-56","***.899.764-**","336.899.764-56","***.899.764-**"],["632.398.678-77","***.398.678-**","632.398.678-77","***.398.678-**"],["030.141.084-48","***.141.084-**","030.141.084-48","***.141.084-**"],["301.735.498-71","***.735.498-**","301.735.498-71","***.735.498-**"],["539.452.483-43","***.452.483-**","539.452.483-43","***.452.483-**"],["534.166.811-18","***.166.811-**","534.166.811-18","***.166.811-**"],["724.499.788-44","***.499.788-**","724.499.788-44","***.499.788-**"],["452.774.441-06","***.774.441-**","452.774.441-06","***.774.441-**"],["400.862.625-56","***.862.625-**","400.862.625-56","***.862.625-**"],["552.051.1","***.051.1","000.055.205-11","***.055.205-**"],["547.125.980-77","***.125.980-**","547.125.980-77","***.125.980-**"],["112.280.143-40","***.280.143-**","112.280.143-40","***.280.143-**"],["199.847.108-07","***.847.108-**","199.847.108-07","***.847.108-**"],["870.242.758-39","***.242.758-**","870.242.758-39","***.242.758-**"],["400.334.102-31","***.334.102-**","400.334.102-31","***.334.102-**"],["130.261.041-40","***.261.041-**","130.261.041-40","***.261.041-**"],["934.397.986-07","***.397.986-**","934.397.986-07","***.397.986-**"],["795.471.379-21","***.471.379-**","795.471.379-21","***.471.379-**"],["065.860.261-64","***.860.261-**","065.860.261-64","***.860.261-**"],["306.484.222-67","***.484.222-**","306.484.222-67","***.484.222-**"],["747.322.998-22","***.322.998-**","747.322.998-22","***.322.998-**"],["787.515.594-04","***.515.594-**","787.515.594-04","***.515.594-**"],["773.715.871-99","***.715.871-**","773.715.871-99","***.715.871-**"],["232.013.727-70","***.013.727-**","232.013.727-70","***.013.727-**"],["485.288.272-59","***.288.272-**","485.288.272-59","***.288.272-**"],["630.982.355-90","***.982.355-**","630.982.355-90","***.982.355-**"],["446.810.140-79","***.810.140-**","446.810.140-79","***.810.140-**"],["447.264.0","***.264.0","000.044.726-40","***.044.726-**"],["181.921.991-77","***.921.991-**","181.921.991-77","***.921.991-**"],["367.269.745-59","***.269.745-**","367.269.745-59","***.269.745-**"],["781.648.170-58","***.648.170-**","781.648.170-58","***.648.170-**"],["863.758.171-71","***.758.171-**","863.758.171-71","***.758.171-**"],["570.244.727-04","***.244.727-**","570.244.727-04","***.244.727-**"],["028.243.085-96","***.243.085-**","028.243.085-96","***.243.085-**"],["252.5","***.5","000.000.025-25","***.000.025-**"],["494.879.424-40","***.879.424-**","494.879.424-40","***.879.424-**"],["39","**","000.000.000-39","***.000.000-**"],["016.056.606-52","***.056.606-**","016.056.606-52","***.056.606-**"],["984.608.992-92","***.608.992-**","984.608.992-92","***.608.992-**"],["310.489.787-53","***.489.787-**","310.489.787-53","***.489.787-**"],["413.380.722-06","***.380.722-**","413.380.722-06","***.380.722-**"],["992.920.113-08","***.920.113-**","992.920.113-08","***.920.113-**"],["630.314.739-36","***.314.739-**","630.314.739-36","***.314.739-**"],["380.767.579-50","***.767.579-**","380.767.579-50","***.767.579-**"],["056.798.024-30","***.798.024-**","056.798.024-30","***.798.024-**"],["633.410.263-62","***.410.263-**","633.410.263-62","***.410.263-**"],["665.382.991","***.382.991","006.653.829-91","***.653.829-**"],["304.149.500-70","***.149.500-**","304.149.500-70","***.149.500-**"],["324.611.403","***.611.403","003.246.114-03","***.246.114-**"],["421.237.805-22","***.237.805-**","421.237.805-22","***.237.805-**"],["062.361.525-71","***.361.525-**","062.361.525-71","***.361.525-**"],["821.535.788-17","***.535.788-**","821.535.788-17","***.535.788-**"],["360.451.292-67","***.451.292-**","360.451.292-67","***.451.292-**"],["099.987.523-43","***.987.523-**","099.987.523-43","***.987.523-**"],["585.368.188-59","***.368.188-**","585.368.188-59","***.368.188-**"],["665.405.362-64","***.405.362-**","665.405.362-64","***.405.362-**"],["457.879.690-65","***.879.690-**","457.879.690-65","***.879.690-**"],["423.6","***.6","000.000.042-36","***.000.042-**"],["420.501.736-79","***.501.736-**","420.501.736-79","***.501.736-**"],["856.920.783-25","***.920.783-**","856.920.783-25","***.920.783-**"],["561.363.0","***.363.0","000.056.136-30","***.056.136-**"],["038.558.056-87","***.558.056-**","038.558.056-87","***.558.056-**"],["317.930.369-77","***.930.369-**","317.930.369-77","***.930.369-**"],["928.267.842-18","***.267.842-**","928.267.842-18","***.267.842-**"],["991.361.901-79","***.361.901-**","991.361.901-79","***.361.901-**"],["336.471.612-02","***.471.612-**","336.471.612-02","***.471.612-**"],["047.455.25","***.455.25","000.047.455-25","***.047.455-**"],["654.592.183-65","***.592.183-**","654.592.183-65","***.592.183-**"],["703.896.668-58","***.896.668-**","703.896.668-58","***.896.668-**"],["624.884.800-96","***.884.800-**","624.884.800-96","***.884.800-**"],["665.946.782-30","***.946.782-**","665.946.782-30","***.946.782-**"],["450.021.061-8","***.021.061-*","045.002.106-18","***.002.106-**"],["765.801.223-82","***.801.223-**","765.801.223-82","***.801.223-**"],["661.220.012-01","***.220.012-**","661.220.012-01","***.220.012-**"],["268.260.103-05","***.260.103-**","268.260.103-05","***.260.103-**"],["571.423.851-51","***.423.851-**","571.423.851-51","***.423.851-**"],["535.748.724-43","***.748.724-**","535.748.724-43","***.748.724-**"],["472.362.195-41","***.362.195-**","472.362.195-41","***.362.195-**"],["405.496.876-70","***.496.876-**","405.496.876-70","***.496.876-**"],["901.416.293-69","***.416.293-**","901.416.293-69","***.416.293-**"],["702.239.867-47","***.239.867-**","702.239.867-47","***.239.867-**"],["903.341.000-11","***.341.000-**","903.341.000-11","***.341.000-**"],["045.185.149-70","***.185.149-**","045.185.149-70","***.185.149-**"],["935.447.043-63","***.447.043-**","935.447.043-63","***.447.043-**"],["763.868.012-02","***.868.012-**","763.868.012-02","***.868.012-**"],["863.056.615-12","***.056.615-**","863.056.615-12","***.056.615-**"],["531.111.785-01","***.111.785-**","531.111.785-01","***.111.785-**"],["357.721.042-76","***.721.042-**","357.721.042-76","***.721.042-**"],["489.519.110-98","***.519.110-**","489.519.110-98","***.519.110-**"],["199.010.914-46","***.010.914-**","199.010.914-46","***.010.914-**"],["630.136.127-98","***.136.127-**","630.136.127-98","***.136.127-**"],["719.146.565-29","***.146.565-**","719.146.565-29","***.146.565-**"],["446.176.547-47","***.176.547-**","446.176.547-47","***.176.547-**"],["964.911.939-69","***.911.939-**","964.911.939-69","***.911.939-**"],["615.41","***.41","000.000.615-41","***.000.615-**"],["958.058.697-07","***.058.697-**","958.058.697-07","***.058.697-**"],["299.013.462-05","***.013.462-**","299.013.462-05","***.013.462-**"],["542.085.199-75","***.085.199-**","542.085.199-75","***.085.199-**"],["875.536.812-95","***.536.812-**","875.536.812-95","***.536.812-**"],["369.881.082-17","***.881.082-**","369.881.082-17","***.881.082-**"],["535.419.4","***.419.4","000.053.541-94","***.053.541-**"],["453.175.172-01","***.175.172-**","453.175.172-01","***.175.172-**"],["677.552.701-60","***.552.701-**","677.552.701-60","***.552.701-**"],["928.798.18","***.798.18","000.928.798-18","***.928.798-**"],["989.660.605-21","***.660.605-**","989.660.605-21","***.660.605-**"],["981.145.242-35","***.145.242-**","981.145.242-35","***.145.242-**"],["629","***","000.000.006-29","***.000.006-**"],["772.375.600-4","***.375.600-*","077.237.560-04","***.237.560-**"],["645.487.125-88","***.487.125-**","645.487.125-88","***.487.125-**"],["894.996.977-68","***.996.977-**","894.996.977-68","***.996.977-**"],["648.075.310-71","***.075.310-**","648.075.310-71","***.075.310-**"],["415.526.159-60","***.526.159-**","415.526.159-60","***.526.159-**"],["029.074.725-98","***.074.725-**","029.074.725-98","***.074.725-**"],["614.475.886-40","***.475.886-**","614.475.886-40","***.475.886-**"],["462.866.244-49","***.866.244-**","462.866.244-49","***.866.244-**"],["289.972.791-57","***.972.791-**","289.972.791-57","***.972.791-**"],["927.697.844-0","***.697.844-*","092.769.784-40","***.769.784-**"],["124.180.278-79","***.180.278-**","124.180.278-79","***.180.278-**"],["005.760.594","***.760.594","000.057.605-94","***.057.605-**"],["838.717.878-84","***.717.878-**","838.717.878-84","***.717.878-**"],["186.291.806-68","***.291.806-**","186.291.806-68","***.291.806-**"],["625.765.938-77","***.765.938-**","625.765.938-77","***.765.938-**"],["686.752.569-98","***.752.569-**","686.752.569-98","***.752.569-**"],["626.822.781-59","***.822.781-**","626.822.781-59","***.822.781-**"],["053.766.513-71","***.766.513-**","053.766.513-71","***.766.513-**"],["156.246.414-71","***.246.414-**","156.246.414-71","***.246.414-**"],["553.973.682-61","***.973.682-**","553.973.682-61","***.973.682-**"],["946.976.798-27","***.976.798-**","946.976.798-27","***.976.798-**"],["593.430.107-10","***.430.107-**","593.430.107-10","***.430.107-**"],["969.887.973-00","***.887.973-**","969.887.973-00","***.887.973-**"],["687.415.410-90","***.415.410-**","687.415.410-90","***.415.410-**"],["815.457.912-01","***.457.912-**","815.457.912-01","***.457.912-**"],["064.302.049-77","***.302.049-**","064.302.049-77","***.302.049-**"],["650.787.574-06","***.787.574-**","650.787.574-06","***.787.574-**"],["951.134.221-95","***.134.221-**","951.134.221-95","***.134.221-**"],["286.444.663-75","***.444.663-**","286.444.663-75","***.444.663-**"],["633.698","***.698","000.006.336-98","***.006.336-**"],["093.231.574-44","***.231.574-**","093.231.574-44","***.231.574-**"],["532.340.996-91","***.340.996-**","532.340.996-91","***.340.996-**"],["014.371.442-49","***.371.442-**","014.371.442-49","***.371.442-**"],["297.152.899-32","***.152.899-**","297.152.899-32","***.152.899-**"],["181.667.281-50","***.667.281-**","181.667.281-50","***.667.281-**"],["276.355.413-70","***.355.413-**","276.355.413-70","***.355.413-**"],["946.227.363-49","***.227.363-**","946.227.363-49","***.227.363-**"],["300.863.936-32","***.863.936-**","300.863.936-32","***.863.936-**"],["999.201.836-42","***.201.836-**","999.201.836-42","***.201.836-**"],["176.844.103-00","***.844.103-**","176.844.103-00","***.844.103-**"],["727.207.049-09","***.207.049-**","727.207.049-09","***.207.049-**"],["082.906.410-95","***.906.410-**","082.906.410-95","***.906.410-**"],["731.651.380-13","***.651.380-**","731.651.380-13","***.651.380-**"],["217.237.806-26","***.237.806-**","217.237.806-26","***.237.806-**"],["827.609.844-38","***.609.844-**","827.609.844-38","***.609.844-**"],["085.527.568-87","***.527.568-**","085.527.568-87","***.527.568-**"],["562.679.855-20","***.679.855-**","562.679.855-20","***.679.855-**"],["620.620.594-24","***.620.594-**","620.620.594-24","***.620.594-**"],["143.537.083-09","***.537.083-**","143.537.083-09","***.537.083-**"],["201.976.169-68","***.976.169-**","201.976.169-68","***.976.169-**"],["909.705.007-34","***.705.007-**","909.705.007-34","***.705.007-**"],["319.798.674-52","***.798.674-**","319.798.674-52","***.798.674-**"],["667.813.392-73","***.813.392-**","667.813.392-73","***.813.392-**"],["554.941.641-79","***.941.641-**","554.941.641-79","***.941.641-**"],["137.397.285-30","***.397.285-**","137.397.285-30","***.397.285-**"],["220.158.060-08","***.158.060-**","220.158.060-08","***.158.060-**"],["568.253.976-64","***.253.976-**","568.253.976-64","***.253.976-**"],["660.146","***.146","000.006.601-46","***.006.601-**"],["314.325.976-04","***.325.976-**","314.325.976-04","***.325.976-**"],["907.713.125-63","***.713.125-**","907.713.125-63","***.713.125-**"],["293.899.120-75","***.899.120-**","293.899.120-75","***.899.120-**"],["381.997.951-31","***.997.951-**","381.997.951-31","***.997.951-**"],["526.227.313","***.227.313","005.262.273-13","***.262.273-**"],["907.003.849-87","***.003.849-**","907.003.849-87","***.003.849-**"],["056.219.569-66","***.219.569-**","056.219.569-66","***.219.569-**"],["774.816.952-2","***.816.952-*","077.481.695-22","***.481.695-**"],["238.130.641-23","***.130.641-**","238.130.641-23","***.130.641-**"],["783.050.225-01","***.050.225-**","783.050.225-01","***.050.225-**"],["256.230.742-94","***.230.742-**","256.230.742-94","***.230.742-**"],["413.205.772-02","***.205.772-**","413.205.772-02","***.205.772-**"],["715.364.393-12","***.364.393-**","715.364.393-12","***.364.393-**"],["954.980.101-25","***.980.101-**","954.980.101-25","***.980.101-**"],["727.64","***.64","000.000.727-64","***.000.727-**"],["215.096.067-26","***.096.067-**","215.096.067-26","***.096.067-**"],["043.397.524-60","***.397.524-**","043.397.524-60","***.397.524-**"],["003.464.247-12","***.464.247-**","003.464.247-12","***.464.247-**"],["375.851.644-78","***.851.644-**","375.851.644-78","***.851.644-**"],["747.006.686-60","***.006.686-**","747.006.686-60","***.006.686-**"],["663.120.873-44","***.120.873-**","663.120.873-44","***.120.873-**"],["968.838.733-67","***.838.733-**","968.838.733-67","***.838.733-**"],["619.553.344-60","***.553.344-**","619.553.344-60","***.553.344-**"],["018.549.088-28","***.549.088-**","018.549.088-28","***.549.088-**"],["477.726.331-49","***.726.331-**","477.726.331-49","***.726.331-**"],["013.976.078-40","***.976.078-**","013.976.078-40","***.976.078-**"],["115.566.696-82","***.566.696-**","115.566.696-82","***.566.696-**"],["418.261.658-86","***.261.658-**","418.261.658-86","***.261.658-**"],["278.014.819-50","***.014.819-**","278.014.819-50","***.014.819-**"],["846.744.291-37","***.744.291-**","846.744.291-37","***.744.291-**"],["943.177.878-11","***.177.878-**","943.177.878-11","***.177.878-**"],["506.237.791-33","***.237.791-**","506.237.791-33","***.237.791-**"],["405.848.479-98","***.848.479-**","405.848.479-98","***.848.479-**"],["449.434.963-02","***.434.963-**","449.434.963-02","***.434.963-**"],["032.910.6","***.910.6","000.003.291-06","***.003.291-**"],["951.962.785-59","***.962.785-**","951.962.785-59","***.962.785-**"],["926.018.824-50","***.018.824-**","926.018.824-50","***.018.824-**"],["500.155.124-07","***.155.124-**","500.155.124-07","***.155.124-**"],["106.387.260-82","***.387.260-**","106.387.260-82","***.387.260-**"],["901.903.678-35","***.903.678-**","901.903.678-35","***.903.678-**"],["211.172.598-56","***.172.598-**","211.172.598-56","***.172.598-**"],["258.825.959-67","***.825.959-**","258.825.959-67","***.825.959-**"],["047.323.834-91","***.323.834-**","047.323.834-91","***.323.834-**"],["947.996.99","***.996.99","000.947.996-99","***.947.996-**"],["959.226.698-00","***.226.698-**","959.226.698-00","***.226.698-**"],["888.306.156-09","***.306.156-**","888.306.156-09","***.306.156-**"],["328.501.307-96","***.501.307-**","328.501.307-96","***.501.307-**"],["779.741.508-92","***.741.508-**","779.741.508-92","***.741.508-**"],["296.595.351-86","***.595.351-**","296.595.351-86","***.595.351-**"],["49","**","000.000.000-49","***.000.000-**"],["157.908.729-76","***.908.729-**","157.908.729-76","***.908.729-**"],["582.606.698-97","***.606.698-**","582.606.698-97","***.606.698-**"],["913.298.091-05","***.298.091-**","913.298.091-05","***.298.091-**"],["567.710.319-50","***.710.319-**","567.710.319-50","***.710.319-**"],["143.982.512-27","***.982.512-**","143.982.512-27","***.982.512-**"],["258.242.962-10","***.242.962-**","258.242.962-10","***.242.962-**"],["563.146.218-44","***.146.218-**","563.146.218-44","***.146.218-**"],["948.768.132-77","***.768.132-**","948.768.132-77","***.768.132-**"],["162.636.601-20","***.636.601-**","162.636.601-20","***.636.601-**"],["700.717.621-67","***.717.621-**","700.717.621-67","***.717.621-**"],["684.050.276-3","***.050.276-*","068.405.027-63","***.405.027-**"],["154.249.497-90","***.249.497-**","154.249.497-90","***.249.497-**"],["819.153.669","***.153.669","008.191.536-69","***.191.536-**"],["253.714.919-07","***.714.919-**","253.714.919-07","***.714.919-**"],["755.329.256-88","***.329.256-**","755.329.256-88","***.329.256-**"],["344.934.705-50","***.934.705-**","344.934.705-50","***.934.705-**"],["706.514.130-20","***.514.130-**","706.514.130-20","***.514.130-**"],["641.863.190-06","***.863.190-**","641.863.190-06","***.863.190-**"],["362.380.666-31","***.380.666-**","362.380.666-31","***.380.666-**"],["877.662.318-79","***.662.318-**","877.662.318-79","***.662.318-**"],["785.072.001-68","***.072.001-**","785.072.001-68","***.072.001-**"],["975.400.869-80","***.400.869-**","975.400.869-80","***.400.869-**"],["694.265.755-95","***.265.755-**","694.265.755-95","***.265.755-**"],["717.054.033-95","***.054.033-**","717.054.033-95","***.054.033-**"],["400.574.566-22","***.574.566-**","400.574.566-22","***.574.566-**"],["162.157.780-52","***.157.780-**","162.157.780-52","***.157.780-**"],["907.606.733-30","***.606.733-**","907.606.733-30","***.606.733-**"],["210.567.501-89","***.567.501-**","210.567.501-89","***.567.501-**"],["648.530.102-06","***.530.102-**","648.530.102-06","***.530.102-**"],["959.760.100-00","***.760.100-**","959.760.100-00","***.760.100-**"],["902.599.434-28","***.599.434-**","902.599.434-28","***.599.434-**"],["466.255.007-98","***.255.007-**","466.255.007-98","***.255.007-**"],["988.450.455-80","***.450.455-**","988.450.455-80","***.450.455-**"],["428.615.384-30","***.615.384-**","428.615.384-30","***.615.384-**"],["715.215.383-36","***.215.383-**","715.215.383-36","***.215.383-**"],["637","***","000.000.006-37","***.000.006-**"],["654.118.778-90","***.118.778-**","654.118.778-90","***.118.778-**"],["202.246.587-56","***.246.587-**","202.246.587-56","***.246.587-**"],["836.602.272-26","***.602.272-**","836.602.272-26","***.602.272-**"],["410.966.244-24","***.966.244-**","410.966.244-24","***.966.244-**"],["201.995.522-90","***.995.522-**","201.995.522-90","***.995.522-**"],["432.909.519-01","***.909.519-**","432.909.519-01","***.909.519-**"],["910.372.437-84","***.372.437-**","910.372.437-84","***.372.437-**"],["454.262.099-85","***.262.099-**","454.262.099-85","***.262.099-**"],["397.040.328-62","***.040.328-**","397.040.328-62","***.040.328-**"],["647.635.595-32","***.635.595-**","647.635.595-32","***.635.595-**"],["906.337.251-53","***.337.251-**","906.337.251-53","***.337.251-**"],["698.051.932-91","***.051.932-**","698.051.932-91","***.051.932-**"],["047.855.570-86","***.855.570-**","047.855.570-86","***.855.570-**"],["496.125.887-32","***.125.887-**","496.125.887-32","***.125.887-**"],["79","**","000.000.000-79","***.000.000-**"],["661.389.847-30","***.389.847-**","661.389.847-30","***.389.847-**"],["555.573.365-05","***.573.365-**","555.573.365-05","***.573.365-**"],["759.327.762-34","***.327.762-**","759.327.762-34","***.327.762-**"],["357.341.606-36","***.341.606-**","357.341.606-36","***.341.606-**"],["683.674.555-05","***.674.555-**","683.674.555-05","***.674.555-**"],["435.998.744-34","***.998.744-**","435.998.744-34","***.998.744-**"],["119.815.225-51","***.815.225-**","119.815.225-51","***.815.225-**"],["465.381.059-58","***.381.059-**","465.381.059-58","***.381.059-**"],["452.491.864-11","***.491.864-**","452.491.864-11","***.491.864-**"],["774.583.134-65","***.583.134-**","774.583.134-65","***.583.134-**"],["007.988.956-59","***.988.956-**","007.988.956-59","***.988.956-**"],["770.041.332-67","***.041.332-**","770.041.332-67","***.041.332-**"],["422.878","***.878","000.004.228-78","***.004.228-**"],["461.7","***.7","000.000.046-17","***.000.046-**"],["063.867.366-9","***.867.366-*","006.386.736-69","***.386.736-**"],["773.952.044-68","***.952.044-**","773.952.044-68","***.952.044-**"],["134.194.178-70","***.194.178-**","134.194.178-70","***.194.178-**"],["306.886.572-17","***.886.572-**","306.886.572-17","***.886.572-**"],["430.760.450-33","***.760.450-**","430.760.450-33","***.760.450-**"],["454.204.688-62","***.204.688-**","454.204.688-62","***.204.688-**"],["477.135.945-87","***.135.945-**","477.135.945-87","***.135.945-**"],["982.999.941-47","***.999.941-**","982.999.941-47","***.999.941-**"],["472.748.728-42","***.748.728-**","472.748.728-42","***.748.728-**"],["102.790.993-04","***.790.993-**","102.790.993-04","***.790.993-**"],["637.357.458-00","***.357.458-**","637.357.458-00","***.357.458-**"],["960.107.623-14","***.107.623-**","960.107.623-14","***.107.623-**"],["432.231.701-46","***.231.701-**","432.231.701-46","***.231.701-**"],["907.324.900-86","***.324.900-**","907.324.900-86","***.324.900-**"],["811.065.107-90","***.065.107-**","811.065.107-90","***.065.107-**"],["369.026.490-01","***.026.490-**","369.026.490-01","***.026.490-**"],["361.337.639-30","***.337.639-**","361.337.639-30","***.337.639-**"],["955.242.299-07","***.242.299-**","955.242.299-07","***.242.299-**"],["604.869.323-03","***.869.323-**","604.869.323-03","***.869.323-**"],["486.225.998-76","***.225.998-**","486.225.998-76","***.225.998-**"],["383.544.884-62","***.544.884-**","383.544.884-62","***.544.884-**"],["102.372.946-64","***.372.946-**","102.372.946-64","***.372.946-**"],["462.605.225-52","***.605.225-**","462.605.225-52","***.605.225-**"],["821.181.107-09","***.181.107-**","821.181.107-09","***.181.107-**"],["254.240.624-31","***.240.624-**","254.240.624-31","***.240.624-**"],["574.115.293-70","***.115.293-**","574.115.293-70","***.115.293-**"],["496.403.407-87","***.403.407-**","496.403.407-87","***.403.407-**"],["624.559.899-09","***.559.899-**","624.559.899-09","***.559.899-**"],["088.404.860-6","***.404.860-*","008.840.486-06","***.840.486-**"],["672.144.590-51","***.144.590-**","672.144.590-51","***.144.590-**"],["867.308.594-33","***.308.594-**","867.308.594-33","***.308.594-**"],["419.229.800-72","***.229.800-**","419.229.800-72","***.229.800-**"],["573.830.433-08","***.830.433-**","573.830.433-08","***.830.433-**"],["015.046.727-60","***.046.727-**","015.046.727-60","***.046.727-**"],["632.986.859-54","***.986.859-**","632.986.859-54","***.986.859-**"],["099.004.253-75","***.004.253-**","099.004.253-75","***.004.253-**"],["666.945.791-09","***.945.791-**","666.945.791-09","***.945.791-**"],["042.576.132-03","***.576.132-**","042.576.132-03","***.576.132-**"],["276.620.013-21","***.620.013-**","276.620.013-21","***.620.013-**"],["456.176.758-48","***.176.758-**","456.176.758-48","***.176.758-**"],["312.865.583-95","***.865.583-**","312.865.583-95","***.865.583-**"],["607.810.734-17","***.810.734-**","607.810.734-17","***.810.734-**"],["137.822.691-79","***.822.691-**","137.822.691-79","***.822.691-**"],["462.018.915-49","***.018.915-**","462.018.915-49","***.018.915-**"],["723.806.315-44","***.806.315-**","723.806.315-44","***.806.315-**"],["106.643.861-29","***.643.861-**","106.643.861-29","***.643.861-**"],["517.968.463-02","***.968.463-**","517.968.463-02","***.968.463-**"],["280.759.517-00","***.759.517-**","280.759.517-00","***.759.517-**"],["096.512.655-23","***.512.655-**","096.512.655-23","***.512.655-**"],["76","**","000.000.000-76","***.000.000-**"],["102.292.357-94","***.292.357-**","102.292.357-94","***.292.357-**"],["926.051.569-66","***.051.569-**","926.051.569-66","***.051.569-**"],["796.930.251-63","***.930.251-**","796.930.251-63","***.930.251-**"],["242.474.869-18","***.474.869-**","242.474.869-18","***.474.869-**"],["250.5","***.5","000.000.025-05","***.000.025-**"],["346.637.685-80","***.637.685-**","346.637.685-80","***.637.685-**"],["030.866.084-63","***.866.084-**","030.866.084-63","***.866.084-**"],["393.780.258-46","***.780.258-**","393.780.258-46","***.780.258-**"],["271.806.324-28","***.806.324-**","271.806.324-28","***.806.324-**"],["809.664.993-6","***.664.993-*","080.966.499-36","***.966.499-**"]],"strict-or-null":[[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],["123.456.789-09","123.456.789-09","123.456.789-09","123.456.789-09"],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],["275.026.776-58","275.026.776-58","275.026.776-58","275.026.776-58"],[null,null,null,null],["455.287.462-48","455.287.462-48","455.287.462-48","455.287.462-48"],["001.925.910-70","001.925.910-70","001.925.910-70","001.925.910-70"],[null,null,null,null],["043.493.162-48","043.493.162-48","043.493.162-48","043.493.162-48"],["058.280.337-35","058.280.337-35","058.280.337-35","058.280.337-35"],[null,null,null,null],[null,null,null,null],["459.609.678-39","459.609.678-39","459.609.678-39","459.609.678-39"],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],["656.235.973-27","656.235.973-27","656.235.973-27","656.235.973-27"],["082.162.626-47","082.162.626-47","082.162.626-47","082.162.626-47"],["942.914.972-53","942.914.972-53","942.914.972-53","942.914.972-53"],["655.466.786-58","655.466.786-58","655.466.786-58","655.466.786-58"],["022.180.106-58","022.180.106-58","022.180.106-58","022.180.106-58"],["134.346.089-15","134.346.089-15","134.346.089-15","134.346.089-15"],[null,null,null,null],[null,null,null,null],[null,null,null,null],["290.227.963-96","290.227.963-96","290.227.963-96","290.227.963-96"],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],["067.339.637-10","067.339.637-10","067.339.637-10","067.339.637-10"],[null,null,null,null],[null,null,null,null],[null,null,null,null],["489.381.054-58","489.381.054-58","489.381.054-58","489.381.054-58"],["520.705.644-10","520.705.644-10","520.705.644-10","520.705.644-10"],[null,null,null,null],["971.165.013-47","971.165.013-47","971.165.013-47","971.165.013-47"],[null,null,null,null],[null,null,null,null],[null,null,null,null],["326.057.798-07","326.057.798-07","326.057.798-07","326.057.798-07"],[null,null,null,null],["601.502.471-25","601.502.471-25","601.502.471-25","601.502.471-25"],["717.708.895-40","717.708.895-40","717.708.895-40","717.708.895-40"],[null,null,null,null],[null,null,null,null],["137.656.313-45","137.656.313-45","137.656.313-45","137.656.313-45"],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],["253.681.039-99","253.681.039-99","253.681.039-99","253.681.039-99"],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],["327.117.213-70","327.117.213-70","327.117.213-70","327.117.213-70"],[null,null,null,null],[null,null,null,null],["401.109.658-09","401.109.658-09","401.109.658-09","401.109.658-09"],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],["946.220.892-11","946.220.892-11","946.220.892-11","946.220.892-11"],[null,null,null,null],[null,null,null,null],["309.534.527-51","309.534.527-51","309.534.527-51","309.534.527-51"],[null,null,null,null],[null,null,null,null],["103.597.230-12","103.597.230-12","103.597.230-12","103.597.230-12"],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],["517.236.689-07","517.236.689-07","517.236.689-07","517.236.689-07"],[null,null,null,null],[null,null,null,null],["299.724.486-22","299.724.486-22","299.724.486-22","299.724.486-22"],[null,null,null,null],[null,null,null,null],[null,null,null,null],["638.764.089-03","638.764.089-03","638.764.089-03","638.764.089-03"],[null,null,null,null],["533.678.958-57","533.678.958-57","533.678.958-57","533.678.958-57"],[null,null,null,null],["324.988.564-98","324.988.564-98","324.988.564-98","324.988.564-98"],["365.588.462-17","365.588.462-17","365.588.462-17","365.588.462-17"],["261.475.992-91","261.475.992-91","261.475.992-91","261.475.992-91"],[null,null,null,null],[null,null,null,null],["939.710.336-95","939.710.336-95","939.710.336-95","939.710.336-95"],[null,null,null,null],["384.762.726-00","384.762.726-00","384.762.726-00","384.762.726-00"],[null,null,null,null],[null,null,null,null],["591.394.668-50","591.394.668-50","591.394.668-50","591.394.668-50"],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],["409.109.630-10","409.109.630-10","409.109.630-10","409.109.630-10"],[null,null,null,null],["837.234.185-03","837.234.185-03","837.234.185-03","837.234.185-03"],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],["849.112.629-58","849.112.629-58","849.112.629-58","849.112.629-58"],[null,null,null,null],["892.059.852-52","892.059.852-52","892.059.852-52","892.059.852-52"],["054.960.534-71","054.960.534-71","054.960.534-71","054.960.534-71"],["525.973.933-72","525.973.933-72","525.973.933-72","525.973.933-72"],["386.522.205-65","386.522.205-65","386.522.205-65","386.522.205-65"],[null,null,null,null],["222.790.475-51","222.790.475-51","222.790.475-51","222.790.475-51"],[null,null,null,null],["541.300.827-95","541.300.827-95","541.300.827-95","541.300.827-95"],[null,null,null,null],[null,null,null,null],[null,null,null,null],["589.768.017-50","589.768.017-50","589.768.017-50","589.768.017-50"],["206.487.406-25","206.487.406-25","206.487.406-25","206.487.406-25"],[null,null,null,null],[null,null,null,null],[null,null,null,null],["749.949.997-91","749.949.997-91","749.949.997-91","749.949.997-91"],[null,null,null,null],[null,null,null,null],[null,null,null,null],["626.103.959-30","626.103.959-30","626.103.959-30","626.103.959-30"],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],["495.454.403-33","495.454.403-33","495.454.403-33","495.454.403-33"],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],["140.796.801-71","140.796.801-71","140.796.801-71","140.796.801-71"],[null,null,null,null],[null,null,null,null],["438.557.083-39","438.557.083-39","438.557.083-39","438.557.083-39"],[null,null,null,null],["668.462.685-96","668.462.685-96","668.462.685-96","668.462.685-96"],[null,null,null,null],["127.109.736-26","127.109.736-26","127.109.736-26","127.109.736-26"],[null,null,null,null],[null,null,null,null],[null,null,null,null],["968.751.151-66","968.751.151-66","968.751.151-66","968.751.151-66"],[null,null,null,null],["310.923.973-61","310.923.973-61","310.923.973-61","310.923.973-61"],[null,null,null,null],["381.469.865-79","381.469.865-79","381.469.865-79","381.469.865-79"],[null,null,null,null],[null,null,null,null],[null,null,null,null],["503.734.632-00","503.734.632-00","503.734.632-00","503.734.632-00"],[null,null,null,null],[null,null,null,null],[null,null,null,null],["847.859.775-15","847.859.775-15","847.859.775-15","847.859.775-15"],[null,null,null,null],["905.346.609-67","905.346.609-67","905.346.609-67","905.346.609-67"],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],["451.858.175-00","451.858.175-00","451.858.175-00","451.858.175-00"],[null,null,null,null],[null,null,null,null],["489.869.813-19","489.869.813-19","489.869.813-19","489.869.813-19"],[null,null,null,null],["128.473.716-05","128.473.716-05","128.473.716-05","128.473.716-05"],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],["946.809.205-48","946.809.205-48","946.809.205-48","946.809.205-48"],[null,null,null,null],[null,null,null,null],[null,null,null,null],["713.273.603-57","713.273.603-57","713.273.603-57","713.273.603-57"],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],["199.297.039-42","199.297.039-42","199.297.039-42","199.297.039-42"],["651.349.831-78","651.349.831-78","651.349.831-78","651.349.831-78"],[null,null,null,null],[null,null,null,null],[null,null,null,null],["011.046.125-85","011.046.125-85","011.046.125-85","011.046.125-85"],[null,null,null,null],[null,null,null,null],[null,null,null,null],["128.573.303-75","128.573.303-75","128.573.303-75","128.573.303-75"],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],["658.458.062-83","658.458.062-83","658.458.062-83","658.458.062-83"],[null,null,null,null],["912.465.249-02","912.465.249-02","912.465.249-02","912.465.249-02"],[null,null,null,null],["060.728.299-10","060.728.299-10","060.728.299-10","060.728.299-10"],[null,null,null,null],["918.220.826-33","918.220.826-33","918.220.826-33","918.220.826-33"],[null,null,null,null],["245.846.481-58","245.846.481-58","245.846.481-58","245.846.481-58"],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],["701.164.557-80","701.164.557-80","701.164.557-80","701.164.557-80"],[null,null,null,null],["631.085.833-52","631.085.833-52","631.085.833-52","631.085.833-52"],[null,null,null,null],["996.655.903-59","996.655.903-59","996.655.903-59","996.655.903-59"],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],["866.763.984-27","866.763.984-27","866.763.984-27","866.763.984-27"],[null,null,null,null],[null,null,null,null],[null,null,null,null],["540.418.281-47","540.418.281-47","540.418.281-47","540.418.281-47"],["819.392.325-11","819.392.325-11","819.392.325-11","819.392.325-11"],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],["900.949.621-03","900.949.621-03","900.949.621-03","900.949.621-03"],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],["805.313.864-06","805.313.864-06","805.313.864-06","805.313.864-06"],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],["674.899.794-12","674.899.794-12","674.899.794-12","674.899.794-12"],["116.809.196-95","116.809.196-95","116.809.196-95","116.809.196-95"],[null,null,null,null],["299.275.353-09","299.275.353-09","299.275.353-09","299.275.353-09"],["688.163.203-70","688.163.203-70","688.163.203-70","688.163.203-70"],[null,null,null,null],["495.931.279-33","495.931.279-33","495.931.279-33","495.931.279-33"],["777.911.178-43","777.911.178-43","777.911.178-43","777.911.178-43"],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],["332.123.446-79","332.123.446-79","332.123.446-79","332.123.446-79"],["777.620.413-70","777.620.413-70","777.620.413-70","777.620.413-70"],["953.735.104-16","953.735.104-16","953.735.104-16","953.735.104-16"],[null,null,null,null],[null,null,null,null],["932.068.398-07","932.068.398-07","932.068.398-07","932.068.398-07"],[null,null,null,null],["270.027.530-61","270.027.530-61","270.027.530-61","270.027.530-61"],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],["465.086.646-46","465.086.646-46","465.086.646-46","465.086.646-46"],[null,null,null,null],["035.849.498-23","035.849.498-23","035.849.498-23","035.849.498-23"],["829.765.743-40","829.765.743-40","829.765.743-40","829.765.743-40"],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],["826.748.097-87","826.748.097-87","826.748.097-87","826.748.097-87"],["327.827.816-00","327.827.816-00","327.827.816-00","327.827.816-00"],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],["797.749.251-22","797.749.251-22","797.749.251-22","797.749.251-22"],["452.943.389-71","452.943.389-71","452.943.389-71","452.943.389-71"],["677.156.778-84","677.156.778-84","677.156.778-84","677.156.778-84"],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],["457.168.957-86","457.168.957-86","457.168.957-86","457.168.957-86"],[null,null,null,null],["929.957.774-99","929.957.774-99","929.957.774-99","929.957.774-99"],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],["731.444.456-06","731.444.456-06","731.444.456-06","731.444.456-06"],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],["336.899.764-56","336.899.764-56","336.899.764-56","336.899.764-56"],[null,null,null,null],["030.141.084-48","030.141.084-48","030.141.084-48","030.141.084-48"],[null,null,null,null],[null,null,null,null],["534.166.811-18","534.166.811-18","534.166.811-18","534.166.811-18"],[null,null,null,null],["452.774.441-06","452.774.441-06","452.774.441-06","452.774.441-06"],["400.862.625-56","400.862.625-56","400.862.625-56","400.862.625-56"],[null,null,null,null],["547.125.980-77","547.125.980-77","547.125.980-77","547.125.980-77"],[null,null,null,null],["199.847.108-07","199.847.108-07","199.847.108-07","199.847.108-07"],["870.242.758-39","870.242.758-39","870.242.758-39","870.242.758-39"],[null,null,null,null],["130.261.041-40","130.261.041-40","130.261.041-40","130.261.041-40"],[null,null,null,null],["795.471.379-21","795.471.379-21","795.471.379-21","795.471.379-21"],["065.860.261-64","065.860.261-64","065.860.261-64","065.860.261-64"],["306.484.222-67","306.484.222-67","306.484.222-67","306.484.222-67"],[null,null,null,null],["787.515.594-04","787.515.594-04","787.515.594-04","787.515.594-04"],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],["181.921.991-77","181.921.991-77","181.921.991-77","181.921.991-77"],[null,null,null,null],["781.648.170-58","781.648.170-58","781.648.170-58","781.648.170-58"],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],["494.879.424-40","494.879.424-40","494.879.424-40","494.879.424-40"],[null,null,null,null],[null,null,null,null],["984.608.992-92","984.608.992-92","984.608.992-92","984.608.992-92"],[null,null,null,null],[null,null,null,null],["992.920.113-08","992.920.113-08","992.920.113-08","992.920.113-08"],[null,null,null,null],[null,null,null,null],["056.798.024-30","056.798.024-30","056.798.024-30","056.798.024-30"],[null,null,null,null],[null,null,null,null],["304.149.500-70","304.149.500-70","304.149.500-70","304.149.500-70"],[null,null,null,null],[null,null,null,null],[null,null,null,null],["821.535.788-17","821.535.788-17","821.535.788-17","821.535.788-17"],[null,null,null,null],[null,null,null,null],["585.368.188-59","585.368.188-59","585.368.188-59","585.368.188-59"],[null,null,null,null],["457.879.690-65","457.879.690-65","457.879.690-65","457.879.690-65"],[null,null,null,null],["420.501.736-79","420.501.736-79","420.501.736-79","420.501.736-79"],[null,null,null,null],[null,null,null,null],["038.558.056-87","038.558.056-87","038.558.056-87","038.558.056-87"],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],["703.896.668-58","703.896.668-58","703.896.668-58","703.896.668-58"],["624.884.800-96","624.884.800-96","624.884.800-96","624.884.800-96"],[null,null,null,null],[null,null,null,null],[null,null,null,null],["661.220.012-01","661.220.012-01","661.220.012-01","661.220.012-01"],["268.260.103-05","268.260.103-05","268.260.103-05","268.260.103-05"],[null,null,null,null],[null,null,null,null],["472.362.195-41","472.362.195-41","472.362.195-41","472.362.195-41"],["405.496.876-70","405.496.876-70","405.496.876-70","405.496.876-70"],[null,null,null,null],[null,null,null,null],["903.341.000-11","903.341.000-11","903.341.000-11","903.341.000-11"],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],["531.111.785-01","531.111.785-01","531.111.785-01","531.111.785-01"],["357.721.042-76","357.721.042-76","357.721.042-76","357.721.042-76"],[null,null,null,null],["199.010.914-46","199.010.914-46","199.010.914-46","199.010.914-46"],[null,null,null,null],[null,null,null,null],["446.176.547-47","446.176.547-47","446.176.547-47","446.176.547-47"],["964.911.939-69","964.911.939-69","964.911.939-69","964.911.939-69"],[null,null,null,null],[null,null,null,null],[null,null,null,null],["542.085.199-75","542.085.199-75","542.085.199-75","542.085.199-75"],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],["289.972.791-57","289.972.791-57","289.972.791-57","289.972.791-57"],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],["186.291.806-68","186.291.806-68","186.291.806-68","186.291.806-68"],[null,null,null,null],[null,null,null,null],[null,null,null,null],["053.766.513-71","053.766.513-71","053.766.513-71","053.766.513-71"],[null,null,null,null],["553.973.682-61","553.973.682-61","553.973.682-61","553.973.682-61"],[null,null,null,null],["593.430.107-10","593.430.107-10","593.430.107-10","593.430.107-10"],["969.887.973-00","969.887.973-00","969.887.973-00","969.887.973-00"],["687.415.410-90","687.415.410-90","687.415.410-90","687.415.410-90"],["815.457.912-01","815.457.912-01","815.457.912-01","815.457.912-01"],[null,null,null,null],["650.787.574-06","650.787.574-06","650.787.574-06","650.787.574-06"],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],["946.227.363-49","946.227.363-49","946.227.363-49","946.227.363-49"],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],["217.237.806-26","217.237.806-26","217.237.806-26","217.237.806-26"],[null,null,null,null],[null,null,null,null],["562.679.855-20","562.679.855-20","562.679.855-20","562.679.855-20"],[null,null,null,null],["143.537.083-09","143.537.083-09","143.537.083-09","143.537.083-09"],["201.976.169-68","201.976.169-68","201.976.169-68","201.976.169-68"],["909.705.007-34","909.705.007-34","909.705.007-34","909.705.007-34"],[null,null,null,null],[null,null,null,null],["554.941.641-79","554.941.641-79","554.941.641-79","554.941.641-79"],[null,null,null,null],["220.158.060-08","220.158.060-08","220.158.060-08","220.158.060-08"],[null,null,null,null],[null,null,null,null],[null,null,null,null],["907.713.125-63","907.713.125-63","907.713.125-63","907.713.125-63"],["293.899.120-75","293.899.120-75","293.899.120-75","293.899.120-75"],[null,null,null,null],[null,null,null,null],["907.003.849-87","907.003.849-87","907.003.849-87","907.003.849-87"],["056.219.569-66","056.219.569-66","056.219.569-66","056.219.569-66"],[null,null,null,null],["238.130.641-23","238.130.641-23","238.130.641-23","238.130.641-23"],["783.050.225-01","783.050.225-01","783.050.225-01","783.050.225-01"],[null,null,null,null],[null,null,null,null],["715.364.393-12","715.364.393-12","715.364.393-12","715.364.393-12"],["954.980.101-25","954.980.101-25","954.980.101-25","954.980.101-25"],[null,null,null,null],["215.096.067-26","215.096.067-26","215.096.067-26","215.096.067-26"],[null,null,null,null],["003.464.247-12","003.464.247-12","003.464.247-12","003.464.247-12"],[null,null,null,null],[null,null,null,null],["663.120.873-44","663.120.873-44","663.120.873-44","663.120.873-44"],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],["013.976.078-40","013.976.078-40","013.976.078-40","013.976.078-40"],[null,null,null,null],["418.261.658-86","418.261.658-86","418.261.658-86","418.261.658-86"],[null,null,null,null],["846.744.291-37","846.744.291-37","846.744.291-37","846.744.291-37"],[null,null,null,null],[null,null,null,null],["405.848.479-98","405.848.479-98","405.848.479-98","405.848.479-98"],[null,null,null,null],[null,null,null,null],["951.962.785-59","951.962.785-59","951.962.785-59","951.962.785-59"],["926.018.824-50","926.018.824-50","926.018.824-50","926.018.824-50"],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],["258.825.959-67","258.825.959-67","258.825.959-67","258.825.959-67"],["047.323.834-91","047.323.834-91","047.323.834-91","047.323.834-91"],[null,null,null,null],["959.226.698-00","959.226.698-00","959.226.698-00","959.226.698-00"],[null,null,null,null],["328.501.307-96","328.501.307-96","328.501.307-96","328.501.307-96"],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],["582.606.698-97","582.606.698-97","582.606.698-97","582.606.698-97"],[null,null,null,null],[null,null,null,null],["143.982.512-27","143.982.512-27","143.982.512-27","143.982.512-27"],[null,null,null,null],["563.146.218-44","563.146.218-44","563.146.218-44","563.146.218-44"],[null,null,null,null],["162.636.601-20","162.636.601-20","162.636.601-20","162.636.601-20"],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],["344.934.705-50","344.934.705-50","344.934.705-50","344.934.705-50"],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],["975.400.869-80","975.400.869-80","975.400.869-80","975.400.869-80"],[null,null,null,null],[null,null,null,null],[null,null,null,null],["162.157.780-52","162.157.780-52","162.157.780-52","162.157.780-52"],["907.606.733-30","907.606.733-30","907.606.733-30","907.606.733-30"],["210.567.501-89","210.567.501-89","210.567.501-89","210.567.501-89"],[null,null,null,null],[null,null,null,null],["902.599.434-28","902.599.434-28","902.599.434-28","902.599.434-28"],[null,null,null,null],[null,null,null,null],["428.615.384-30","428.615.384-30","428.615.384-30","428.615.384-30"],["715.215.383-36","715.215.383-36","715.215.383-36","715.215.383-36"],[null,null,null,null],["654.118.778-90","654.118.778-90","654.118.778-90","654.118.778-90"],[null,null,null,null],["836.602.272-26","836.602.272-26","836.602.272-26","836.602.272-26"],[null,null,null,null],[null,null,null,null],["432.909.519-01","432.909.519-01","432.909.519-01","432.909.519-01"],[null,null,null,null],[null,null,null,null],["397.040.328-62","397.040.328-62","397.040.328-62","397.040.328-62"],["647.635.595-32","647.635.595-32","647.635.595-32","647.635.595-32"],[null,null,null,null],[null,null,null,null],[null,null,null,null],["496.125.887-32","496.125.887-32","496.125.887-32","496.125.887-32"],[null,null,null,null],[null,null,null,null],[null,null,null,null],["759.327.762-34","759.327.762-34","759.327.762-34","759.327.762-34"],["357.341.606-36","357.341.606-36","357.341.606-36","357.341.606-36"],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],["134.194.178-70","134.194.178-70","134.194.178-70","134.194.178-70"],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],["472.748.728-42","472.748.728-42","472.748.728-42","472.748.728-42"],[null,null,null,null],[null,null,null,null],[null,null,null,null],["432.231.701-46","432.231.701-46","432.231.701-46","432.231.701-46"],[null,null,null,null],[null,null,null,null],[null,null,null,null],["361.337.639-30","361.337.639-30","361.337.639-30","361.337.639-30"],["955.242.299-07","955.242.299-07","955.242.299-07","955.242.299-07"],["604.869.323-03","604.869.323-03","604.869.323-03","604.869.323-03"],["486.225.998-76","486.225.998-76","486.225.998-76","486.225.998-76"],["383.544.884-62","383.544.884-62","383.544.884-62","383.544.884-62"],[null,null,null,null],[null,null,null,null],[null,null,null,null],["254.240.624-31","254.240.624-31","254.240.624-31","254.240.624-31"],["574.115.293-70","574.115.293-70","574.115.293-70","574.115.293-70"],[null,null,null,null],[null,null,null,null],[null,null,null,null],["672.144.590-51","672.144.590-51","672.144.590-51","672.144.590-51"],[null,null,null,null],["419.229.800-72","419.229.800-72","419.229.800-72","419.229.800-72"],[null,null,null,null],[null,null,null,null],[null,null,null,null],["099.004.253-75","099.004.253-75","099.004.253-75","099.004.253-75"],[null,null,null,null],["042.576.132-03","042.576.132-03","042.576.132-03","042.576.132-03"],[null,null,null,null],[null,null,null,null],["312.865.583-95","312.865.583-95","312.865.583-95","312.865.583-95"],[null,null,null,null],["137.822.691-79","137.822.691-79","137.822.691-79","137.822.691-79"],[null,null,null,null],[null,null,null,null],[null,null,null,null],[null,null,null,null],["280.759.517-00","280.759.517-00","280.759.517-00","280.759.517-00"],["096.512.655-23","096.512.655-23","096.512.655-23","096.512.655-23"],[null,null,null,null],[null,null,null,null],["926.051.569-66","926.051.569-66","926.051.569-66","926.051.569-66"],[null,null,null,null],["242.474.869-18","242.474.869-18","242.474.869-18","242.474.869-18"],[null,null,null,null],["346.637.685-80","346.637.685-80","346.637.685-80","346.637.685-80"],["030.866.084-63","030.866.084-63","030.866.084-63","030.866.084-63"],["393.780.258-46","393.780.258-46","393.780.258-46","393.780.258-46"],[null,null,null,null],[null,null,null,null]]}}}} diff --git a/vite.config.ts b/vite.config.ts index 301860015..1822d8c93 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -148,10 +148,10 @@ export default defineConfig({ // `reports` holds generated output only, the committed API Extractor baseline included: // reformatting its code block would make every `check:api` run report a changed API. // `CHANGELOG.md` is written by release-please (`* ` bullets); formatting it would fail the - // Check workflow on every release PR. `spec/vectors` holds the generated conformance - // vectors, written on one line on purpose: pretty printing ~10k expectations would multiply - // the file size for a file nobody reads by hand, and `spec/bridge/source/*.data.json` and - // `spec/bridge/out` are the same: a generated table and the generated targets. + // Check workflow on every release PR. `spec/bridge/out` holds the compiler's output, and + // `spec/bridge/source/*.data.json` the tables it bakes at build time: both are generated, + // and the tables are written on one line on purpose, since pretty printing thousands of + // rows would multiply the size of a file nobody reads by hand. ignorePatterns: [ "dist", "coverage", @@ -160,10 +160,8 @@ export default defineConfig({ ".stryker-tmp", ".claude", "CHANGELOG.md", - "spec/vectors", - "spec/bench/corpus.json", "**/spec/bridge/out/**", - "spec/bridge/source/municipalities.data.json", + "spec/bridge/source/*.data.json", ], singleQuote: false, sortImports: true, @@ -515,12 +513,11 @@ export default defineConfig({ rules: { // The spec tooling is a set of command line programs: their output is the product. "eslint/no-console": "off", - // `spec/conformance/upstream.ts` runs the other languages' own toolchains on purpose, - // from the developer's PATH, to compare this specification against the packages the - // organisation already publishes. + // The conformance runners drive each target's own toolchain on purpose, from the + // developer's PATH, to check the generated code the way its users would build it. "sonarjs/no-os-command-from-path": "off", - // The generator reads the JSON files it writes itself, whose shape is pinned by - // `spec/schema/utility.schema.json`, so the parse results are asserted, not validated. + // The tooling reads back the JSON it writes itself, so the parse results are + // asserted against the shape it just wrote rather than validated. "typescript/no-unsafe-type-assertion": "off", }, }, From 4de5b1692ae41b30950ed57bb893d66d985de75c Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 21 Sep 2026 03:59:51 +0000 Subject: [PATCH 07/13] feat(spec): a compiler that turns one TypeScript utility into seven languages `spec/bridge` reads a utility written once, in a documented subset of TypeScript, and emits idiomatic native code for TypeScript, Python, Go, Rust, Ruby, Java and C#, plus a C ABI over the Rust crate for the ecosystems that would rather bind to a shared core than carry generated source. Three things would otherwise differ between the targets, and each is resolved at build time rather than left to the host: regular expressions are compiled into explicit code point classes and a backtrack-free matcher, collation is resolved once against the JavaScript package's own comparator and baked into the dataset, and JavaScript's boundary coercions live in a small portable standard library every target implements natively. Three more are the emitter's job rather than the author's: async colouring, raising, and the one concurrency primitive the subset has. A utility is one file exporting one function, the way `src/` is one directory per utility. What two of them share goes under `source/_internals/`, and `compiler/link.ts` inlines those helpers into whichever utility imports them and prunes whatever it does not reach, so every target still emits one self-contained unit. That is what keeps the JavaScript output tree shakeable and the C symbol table flat. Parity is measured rather than asserted, and nothing about it is hand-written per utility: a utility says which arguments to replay, the expectation comes from calling the package this repository ships, and the program that replays it in each language is generated from the compiled signature. A row also records which targets can be handed the call at all, so a number where a signature says `string` is reported as not expressible rather than quietly dropped. The engine lands on its own. Each utility is a change of its own on top of it. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01UX1gTGeMTyoXQyr1qUoQKd --- CONTRIBUTING.md | 8 +- spec/bridge/.gitignore | 10 +- spec/bridge/README.md | 278 ++- spec/bridge/compiler/frontend.ts | 14 +- spec/bridge/compiler/kit.ts | 23 +- spec/bridge/compiler/link.ts | 405 ++++ spec/bridge/compiler/targets/cabi.ts | 71 +- spec/bridge/compiler/targets/csharp.ts | 5 +- spec/bridge/compiler/targets/go.ts | 8 +- spec/bridge/compiler/targets/python.ts | 4 +- spec/bridge/compiler/targets/ruby.ts | 6 +- spec/bridge/compiler/targets/rust.ts | 6 +- spec/bridge/conformance/cases.ts | 271 +++ spec/bridge/conformance/cep.ts | 337 --- spec/bridge/conformance/drivers.ts | 2249 ++++++++++-------- spec/bridge/conformance/municipalities.ts | 95 - spec/bridge/conformance/record.ts | 173 ++ spec/bridge/conformance/run-all.sh | 38 +- spec/bridge/conformance/serve.ts | 24 + spec/bridge/conformance/shipped.ts | 40 + spec/bridge/conformance/vectors.ts | 152 -- spec/bridge/conformance/verify-typescript.sh | 35 +- spec/bridge/data/_builder.ts | 20 + spec/bridge/data/build.ts | 101 +- spec/bridge/source/cep.ts | 318 --- spec/bridge/source/cnpj.ts | 211 -- spec/bridge/source/municipalities.data.json | 1 - spec/bridge/source/municipalities.ts | 110 - vite.config.ts | 3 + 29 files changed, 2544 insertions(+), 2472 deletions(-) create mode 100644 spec/bridge/compiler/link.ts create mode 100644 spec/bridge/conformance/cases.ts delete mode 100644 spec/bridge/conformance/cep.ts delete mode 100644 spec/bridge/conformance/municipalities.ts create mode 100644 spec/bridge/conformance/record.ts create mode 100644 spec/bridge/conformance/serve.ts create mode 100644 spec/bridge/conformance/shipped.ts delete mode 100644 spec/bridge/conformance/vectors.ts create mode 100644 spec/bridge/data/_builder.ts delete mode 100644 spec/bridge/source/cep.ts delete mode 100644 spec/bridge/source/cnpj.ts delete mode 100644 spec/bridge/source/municipalities.data.json delete mode 100644 spec/bridge/source/municipalities.ts diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 40b5c00db..710c5ac1e 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -84,10 +84,10 @@ but the few rules below hold everywhere: npm registry; [MAINTAINERS.md](MAINTAINERS.md) lists who can change what, and [SECURITY.md](SECURITY.md) how a release is verified. -`spec/` is not part of the published package and nothing under `src/` depends on it: it is a -prototype of describing a utility once, as language neutral data, and emitting it to the other -Brazilian Utils packages. Read [spec/EXPLORATION.md](spec/EXPLORATION.md) for what it proves and -[spec/README.md](spec/README.md) for how to run it. +`spec/` is not part of the published package and nothing under `src/` depends on it: it is an +attempt at writing a utility once and emitting it to every language Brazilian Utils publishes. +Read [spec/README.md](spec/README.md) for what is there and +[spec/bridge/README.md](spec/bridge/README.md) for how to add a utility to it. The actors around the code are the consumers of the npm package, the contributors (pull requests from forks), the maintainers (review, merge, release approval) and the automation: GitHub Actions diff --git a/spec/bridge/.gitignore b/spec/bridge/.gitignore index b1bcb15a2..0ae05c1a6 100644 --- a/spec/bridge/.gitignore +++ b/spec/bridge/.gitignore @@ -3,11 +3,7 @@ out/ node_modules/ -# The conformance recordings are taken from the package this repository ships, by -# `conformance/vectors.ts` and `conformance/municipalities.ts`, which `run-all.sh` runs first. +# The conformance tables are recorded from the package this repository ships, by +# `conformance/record.ts`, which `run-all.sh` runs first. # `source/*.data.json` is committed: it is an input to the compiler, not a recording. -conformance/vectors.json -conformance/vectors.tsv -conformance/municipalities.expected.txt -conformance/municipalities.keys.txt -conformance/cep.expected.tsv +conformance/recorded/ diff --git a/spec/bridge/README.md b/spec/bridge/README.md index 458b1555e..40a70c39b 100644 --- a/spec/bridge/README.md +++ b/spec/bridge/README.md @@ -2,66 +2,45 @@ `spec/bridge` is a compiler. You write a utility once, in ordinary TypeScript, under [`source/`](source). It emits idiomatic native code for **TypeScript, Python, Go, Rust, Ruby, -Java and C#** — no bindings, no embedded VM, no FFI, and nothing hand-written per language. - -Three utilities are ported so far, chosen because between them they use everything hard: - -| utility | what makes it hard | -| --------------------------- | ------------------------------------------------------------------- | -| `isValidCnpj`, `formatCnpj` | regular expressions, JavaScript's own coercion quirks | -| `getMunicipalities` | 5,571 rows of data and a `pt-BR` collation order | -| `getAddressInfoByCep` | HTTP, JSON, retries, an error hierarchy, and racing three providers | +Java and C#**, and a C ABI on top of the Rust crate — no bindings, no embedded VM, no FFI, and +nothing hand-written per language. ``` -source/cnpj.ts ──┐ -source/municipalities.ts ─┼──> compiler/frontend.ts ──> IR ──┬──> out/typescript -source/cep.ts ──┘ (oxc parser) ├──> out/python - ├──> out/go - ├──> out/rust - ├──> out/ruby - ├──> out/java - └──> out/csharp +source/is-valid-cnpj.ts ─┐ +source/format-cnpj.ts ─┼─> compiler/frontend.ts ─> IR ─┬─> out/typescript +source/… ─┘ (oxc parser) ├─> out/python + ├─> out/go + ├─> out/rust (+ the C ABI) + ├─> out/ruby + ├─> out/java + └─> out/csharp ``` -## Is it actually the same? - -Parity is measured against the package this repository ships, not asserted. - -```bash -# The generated TypeScript drops into src/ and runs the package's own vitest suites. -bash spec/bridge/conformance/verify-typescript.sh +What is shared is the **utility's implementation**, not the published package. Every ecosystem +keeps writing its own DX by hand — its naming, its option objects, its types, its docs — over +whichever core it gets. That is why each source file holds exactly one utility and each target +emits exactly one self-contained unit: the JavaScript output has to stay tree shakeable, and a +C symbol table has to stay flat. -# Every target replays the expectations recorded from the shipped package. -bash spec/bridge/conformance/run-all.sh -``` +## One utility, one file -| target | CNPJ vectors | municipality dump | CEP scenarios | -| ---------- | ---------------------- | ----------------- | ----------------- | -| typescript | 5,740 / 5,740 | 11,176 / 11,176 | 110 / 110 | -| python | 5,740 / 5,740 | 11,176 / 11,176 | 109 / 109 (1 n/e) | -| ruby | 5,740 / 5,740 | 11,176 / 11,176 | 109 / 109 (1 n/e) | -| go | 5,722 / 5,722 (18 n/e) | 11,176 / 11,176 | 103 / 103 (7 n/e) | -| rust | 5,722 / 5,722 (18 n/e) | 11,176 / 11,176 | 103 / 103 (7 n/e) | -| java | 5,722 / 5,722 (18 n/e) | 11,176 / 11,176 | 103 / 103 (7 n/e) | -| csharp | 5,722 / 5,722 (18 n/e) | 11,176 / 11,176 | 103 / 103 (7 n/e) | +`src/` in this repository is one directory per utility, with everything two of them share +under `_internals/`. `source/` is laid out the same way, and +[`compiler/link.ts`](compiler/link.ts) is what makes that work across seven languages at once: -"n/e" is **not expressible**: a case whose input has no form in that language, listed under -[Known gaps](#known-gaps). Nothing is skipped for being inconvenient. +- **`inline`** splices the helpers a module imports into the module, so the compiler sees one + file and every target emits one unit that references nothing else. +- **`prune`** then drops whatever that splicing brought in and the module does not reach. A + utility importing one helper out of a file of ten emits one helper. -The CNPJ corpus is every string literal in the package's own CNPJ test files, plus 120 freshly -generated CNPJs and masked and mutated variants of each, so its total moves by a few dozen every -time the expectations are re-recorded. The municipality dump and the CEP scenarios are fixed. +So `source/is-valid-cnpj.ts` and `source/format-cnpj.ts` both import from +`source/_internals/cnpj.ts`, the check digit rules are written once, and neither generated +module carries a line of the other's. -And the package's own suites, run against the generated TypeScript: - -``` -Test Files 4 passed (4) - Tests 157 passed | 3 skipped | 3 todo (164) -``` - -That includes the type level assertions — `expectTypeOf(getMunicipalities).parameter(0)` has to -be `StateCode | undefined`, `getAddressInfoByCep` has to resolve to `AddressInfo`, and the four -CEP error classes have to extend one another. +The alternative — a shared module per target, imported across — would mean seven module +systems, seven visibility models, and a Go package named after a directory Rust spells +differently. Inlining costs a few duplicated helper bodies across utilities and buys all of +that back. ## The three things that would otherwise differ @@ -75,11 +54,11 @@ code point ranges and a backtrack-free matcher that every runtime implements the ([`compiler/regex.ts`](compiler/regex.ts)). The compiler refuses any pattern whose consecutive classes overlap, which is what makes the greedy, backtrack-free scan provably correct. -**Collation.** `getMunicipalities()` returns names sorted with `localeCompare(…, "pt-BR")`. Go -and Rust ship no collator at all; Ruby compares bytes; Python, Java and C# each resolve their -own. Sorting at run time would produce seven different orders, so -[`data/build.ts`](data/build.ts) resolves the order once, against the JavaScript package's own -comparator, and bakes it into the dataset. Every target replays it. +**Collation.** A utility that returns names in `localeCompare(…, "pt-BR")` order cannot sort +at run time: Go and Rust ship no collator at all, Ruby compares bytes, and Python, Java and C# +each resolve their own. [`data/build.ts`](data/build.ts) resolves the order once, against the +JavaScript package's own comparator, and bakes it into the dataset the emitters materialise. +Every target replays it. **JavaScript's boundary quirks.** `formatCnpj(12_345_678)` coerces, `{ obfuscate: 1 }` is truthy, `getAddressInfoByCep("01310-100")` strips the mask. These are the package's contract, @@ -91,18 +70,18 @@ not accidents, so they live in a small portable standard library The source is straight-line, synchronous TypeScript. Three things are the emitter's job: -- **`async`.** `source/cep.ts` calls `httpGet(…)` and returns an `AddressInfo`. The compiler - works out which functions wait on the network, and colours the call graph per target: +- **`async`.** A utility that calls `httpGet(…)` returns its record, plainly. The compiler + works out which functions wait on the network and colours the call graph per target: TypeScript and C# get `async`/`await` and a `Promise`/`Task` return, while Go, Rust, Ruby, Java and Python stay blocking. -- **Raising.** The source writes `throw new GetAddressInfoByCepNotFoundError(…)`. Java, C#, - Python, Ruby and TypeScript get a real exception class. Go gets `(T, error)` with the error - threaded through every call site; Rust gets `Result`. The declared error - hierarchy survives in all seven. -- **Concurrency.** `startAll(fetchProvider, chosen, digits)` is the only concurrency primitive - of the subset. It becomes promises in TypeScript, `Task`s in C#, goroutines and a channel in - Go, threads and an `mpsc` channel in Rust, virtual threads in Java, and threads with a queue - in Python and Ruby. +- **Raising.** The source writes `throw new SomeError(…)`. Java, C#, Python, Ruby and + TypeScript get a real exception class. Go gets `(T, error)` with the error threaded through + every call site; Rust gets `Result`. The declared error hierarchy + survives in all seven. +- **Concurrency.** `startAll(fn, values, argument)` is the only concurrency primitive of the + subset. It becomes promises in TypeScript, `Task`s in C#, goroutines and a channel in Go, + threads and an `mpsc` channel in Rust, virtual threads in Java, and threads with a queue in + Python and Ruby. ## The eighth target: a C ABI, for the ecosystems that would rather bind @@ -116,31 +95,81 @@ of 47 ns. In Python and Ruby that is 21× and 18× faster than the generated sou So the Rust target emits both surfaces from the same source: ``` -out/rust/src/cnpj.rs the library a Rust caller uses -out/rust/src/cabi_cnpj.rs #[no_mangle] extern "C" wrappers over the same functions -out/rust/include/cnpj.h the header a binding author reads +out/rust/src/is_valid_cnpj.rs the library a Rust caller uses +out/rust/src/cabi_is_valid_cnpj.rs #[no_mangle] extern "C" wrappers over the same functions +out/rust/include/is_valid_cnpj.h the header a binding author reads ``` ```c -int32_t cnpj_is_valid_cnpj(const uint8_t *cnpj, size_t len, int64_t version); -intptr_t cnpj_format_cnpj(const uint8_t *value, size_t len, int64_t version, - int32_t obfuscate, int32_t pad, uint8_t *out, size_t out_len); +int32_t is_valid_cnpj(const uint8_t *cnpj, size_t len, int64_t version); +intptr_t format_cnpj(const uint8_t *value, size_t len, int64_t version, + int32_t obfuscate, int32_t pad, uint8_t *out, size_t out_len); ``` Pointers, lengths and integers, nothing owned and nothing allocated across the boundary. An option that was not given is its "unset" sentinel — the same one the emitters already compare against. A function that answers text writes into the caller's buffer and returns the length. -`conformance/run-all.sh` replays the CNPJ vectors through that ABI from C as an eighth arm -(5,732 / 5,732), which checks every hand-written binding's target at once: a CPython extension, -a Ruby C extension, a NuGet package over P/Invoke and a JAR over Panama all call exactly these -symbols. +`conformance/run-all.sh` replays the same tables through that ABI from C, as an eighth arm, +which checks every hand-written binding's target at once: a CPython extension, a Ruby C +extension, a NuGet package over P/Invoke and a JAR over Panama all call exactly these symbols. + +What the ABI does **not** cover is listed in the generated file itself: a function that raises +needs an out parameter for the error, one that waits on the network needs a callback or a +poll, and one that answers a list needs an iterator. Those are refused rather than guessed at, +so they are generated-source only. + +## Is it actually the same? -What the ABI does **not** cover yet is listed in the generated file itself: a function that -raises needs an out parameter for the error, one that waits on the network needs a callback or -a poll, and one that answers a list needs an iterator. `getMunicipalities` and -`getAddressInfoByCep` are refused rather than guessed at, so today they are generated-source -only. +Parity is measured against the package this repository ships, not asserted. Nothing is written +by hand per utility except the utility: the expectations are recorded by calling the shipped +package, and the program that replays them in each language is generated from the compiled +signature. + +```bash +# The generated TypeScript drops into src/ and runs the package's own vitest suites. +bash spec/bridge/conformance/verify-typescript.sh + +# Every target replays the expectations recorded from the shipped package. +bash spec/bridge/conformance/run-all.sh +``` + +A run prints one line per utility per target: + +``` +go: isValidCnpj 1707/1707 matched (18 not expressible) +``` + +"not expressible" is a case whose input has no form in that language — a number where the +signature says `string`, `null` where it says a list of names. The row says which targets can +be handed it, so nothing is skipped for being inconvenient, and the count is visible. + +## Ported so far + +Nothing yet: this is the engine on its own, and each utility is a change of its own on top of +it. `conformance/run-all.sh` says so rather than passing vacuously. + +## Adding a utility + +Two files, and nothing else changes: + +1. **`source/.ts`** — the utility, in the subset below, exporting exactly one function. + Anything it shares with another utility goes in `source/_internals/`. +2. **`conformance/cases/.ts`** — the arguments to replay. Only the arguments: the + expectation comes from calling the shipped package, the table's columns come from the + compiled signature, and each target's replay program is generated. + +A utility that needs a baked table adds **`data/.ts`**, which builds it from the shipped +package. A utility that reaches the network adds a `serve` to its recorder, and `run-all.sh` +starts it for the run. + +```ts +// conformance/cases/is-valid-cnpj.ts +export const recorder: Recorder = { + module: "is-valid-cnpj", + inputs: (shipped) => [["12.345.678/0001-95"], ["q0slfmbd7vx439", { version: 2 }]], +}; +``` ## The subset @@ -156,7 +185,10 @@ types, array literals, `.push()`, `.length`, and the string methods `charCodeAt` **Declarations:** `type X = { … }` (a record, or an options record when every field is optional), `type X = "a" | "b"` (a closed set of strings), `class X extends Y {}` (an error type, body must be empty), module level `const` for strings, integers, lists and regular -expressions, and `dataset("name")` for a table built by `data/build.ts`. +expressions, and `dataset("name")` for a table built by `data/`. + +**Imports:** `./_std.ts` for the portable standard library, and `./_internals/*.ts` for +helpers, which are inlined and pruned rather than emitted as a module. **Refused:** classes with bodies, inheritance other than for errors, inline closures, `switch`, `while`, floating point, `null` as a value, mutation of anything but a local, and any regular @@ -166,19 +198,32 @@ expression with alternation, lookaround or overlapping consecutive classes. These are the honest edges, all of them measured rather than assumed. +### What the subset cannot express yet + +A survey of the 140 utilities this package ships says four capabilities are missing, and each +is a decision rather than a detail: + +| missing | utilities it blocks | why it is not a detail | +| ------------------- | -------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------- | +| dates | 11, including `isBusinessDay`, `getHolidays`, `addBusinessDays`, `getBoletoInfo` | a date type and an arithmetic per target, plus a calendar whose rules move | +| randomness | 15 `generate*` utilities | untestable by replay: a recorded expectation needs a seeded generator every target agrees on | +| floats and `Intl` | ~8, including `formatCurrency`, `clampPrecision`, `convertCurrencyToWords` | rounding and currency formatting differ per target; the IR is integers only for exactly this reason | +| Unicode `normalize` | `removeAccents` and `sanitizeToAscii` | NFD tables ship with the host and are not the same everywhere; this one wants a baked table | + +Everything else in the survey is reachable with what is here. + +### Where the targets cannot be handed the same call + - **`string | number` has no static form.** `isValidCnpj(12_345_678_000_195)` is `false` in - JavaScript, because the value is not a string. Go, Rust, Java and C# declare the parameter as - a string, so the question cannot be asked: 18 of the CNPJ vectors and 2 of the CEP cases are - not expressible there. Python and Ruby, being dynamically typed, answer all of them. -- **`null` and `undefined` are one value in most hosts.** `getAddressInfoByCep(cep, { providers: -null })` rejects, where an omitted `providers` uses the default. Only TypeScript can tell the - two apart; Python's `None` and Ruby's `nil` are both, so that case is not expressible there - either. + JavaScript, because the value is not a string. Go, Rust, Java and C# declare the parameter + as a string, so the question cannot be asked there. Python, Ruby and TypeScript answer it. +- **`null` and `undefined` are one value in most hosts.** An option given as `null` is not the + same as an omitted one. Only TypeScript can tell them apart; Python's `None` and Ruby's + `nil` are both. - **`toUpperCase` is not the same function everywhere.** The generated code calls each host's - own uppercasing, which agrees with JavaScript's for ASCII and for the Latin-1 range the CNPJ - alphabet uses, but not for every code point (Turkish dotless i, for instance). No utility in - scope depends on the difference; one that did would need `upper` pinned in the portable std - the way `trim` already is. + own uppercasing, which agrees with JavaScript's for ASCII and for the Latin-1 range, but not + for every code point (Turkish dotless i, for instance). No utility in scope depends on the + difference; one that did would need `upper` pinned in the portable std the way `trim` is. - **Retry policy is the host's.** `httpGet(url, retries, delayMs)` retries a _transient_ transport failure, and what counts as transient is each client's own set of error codes. The generated TypeScript reproduces the shipped package's list exactly; the other six use their @@ -190,24 +235,33 @@ null })` rejects, where an omitted `providers` uses the default. Only TypeScript ## Layout ``` -source/ the utilities, written once, and the portable std - _std.ts the operations each target implements natively - *.data.json datasets, built by data/build.ts +source/ + _std.ts the operations each target implements natively + _internals/*.ts helpers, inlined into whichever utility imports them + .ts one utility, one exported function + *.data.json datasets, built by data/ compiler/ - frontend.ts TypeScript (via the oxc parser) -> IR - ir.ts the intermediate representation - regex.ts regular expressions -> code point classes + a matcher - targets/*.ts one emitter per language - runtime/* one small runtime per language, utility agnostic -data/build.ts builds the datasets, resolving collation once + frontend.ts TypeScript (via the oxc parser) -> IR + ir.ts the intermediate representation + link.ts inlines the imported helpers, prunes what is unreachable + regex.ts regular expressions -> code point classes + a matcher + kit.ts naming and traversal, shared by the emitters + cli.ts compiles every module into every target + targets/*.ts one emitter per language, plus cabi.ts for the C ABI + runtime/* one small runtime per language, utility agnostic +data/ + build.ts runs every dataset builder + .ts one dataset, with its order resolved once conformance/ - vectors.ts records the CNPJ expectations from the shipped package - municipalities.ts records the municipality dump - cep.ts the CEP scenarios: recorder and mock server in one file - drivers.ts writes the replay driver for each language - run-all.sh regenerates everything and replays it through all seven - verify-typescript.sh runs the package's own vitest suites on the output -out/ generated; not committed + cases.ts the case format: columns, rendering, which target can be handed what + cases/.ts the arguments to replay, per utility + record.ts calls the shipped package and writes the tables + drivers.ts writes each target's replay program from the compiled signature + serve.ts serves what the generated code talks to, for a run + run-all.sh records, compiles, and replays through all seven plus the C ABI + verify-typescript.sh runs the package's own vitest suites on the output + recorded/ generated; not committed +out/ generated; not committed ``` ## Running it @@ -222,6 +276,6 @@ bash conformance/run-all.sh # the whole parity check ``` The conformance run needs the toolchains of the languages it checks (node, python3, ruby, go, -cargo, javac, dotnet) and uses a local HTTP server on port 18080, which -`BRUTILS_BRIDGE_PORT` overrides. The runtimes read `BRUTILS_BRIDGE_HTTP_ORIGIN` to point their -requests at it; unset, they call the real services. +cargo, javac, dotnet) and uses a local HTTP server on port 18080, which `BRUTILS_BRIDGE_PORT` +overrides. The runtimes read `BRUTILS_BRIDGE_HTTP_ORIGIN` to point their requests at it; +unset, they call the real services. diff --git a/spec/bridge/compiler/frontend.ts b/spec/bridge/compiler/frontend.ts index 8a2b8c151..84b759612 100644 --- a/spec/bridge/compiler/frontend.ts +++ b/spec/bridge/compiler/frontend.ts @@ -26,6 +26,7 @@ import { type Ty, } from "./ir.ts"; import { walk } from "./kit.ts"; +import { inline, prune } from "./link.ts"; import { ClassTable, complement, parsePattern, toSteps } from "./regex.ts"; /* eslint-disable */ @@ -1008,7 +1009,7 @@ const registerRegex = (name: string, source: string, scope: Scope): void => { * @returns {Module} The IR module. */ export const compileModule = (path: string): Module => { - const source = readFileSync(path, "utf8"); + const source = inline(path); const parsed = parseSync(path, source); if (parsed.errors.length > 0) throw new Error(`${path}: ${parsed.errors[0].message}`); @@ -1039,7 +1040,12 @@ export const compileModule = (path: string): Module => { const from = String((statement["source"] as Node)["value"]); - if (!from.endsWith("_std.ts")) throw new Error(`${path}: only "./_std.ts" can be imported`); + // The shared helpers are already spliced into `source` by `inline`, so their names are + // ordinary declarations of this module by the time the passes below run. + if (from.includes("_internals/")) continue; + + if (!from.endsWith("_std.ts")) + throw new Error(`${path}: only "./_std.ts" and "./_internals/*.ts" can be imported`); for (const specifier of (statement["specifiers"] as Node[]) ?? []) { const name = String((specifier["imported"] as Node)["name"]); @@ -1324,7 +1330,7 @@ export const compileModule = (path: string): Module => { const firstComment = source.indexOf("*/"); const moduleDoc = firstComment === -1 ? "" : docBefore(source, firstComment + 2); - return { + return prune({ name: basename(path, ".ts"), doc: moduleDoc.split("\n")[0] ?? "", charClasses: scope.classes.all() as CharClass[], @@ -1335,5 +1341,5 @@ export const compileModule = (path: string): Module => { functions, data: [...scope.data.values()], constants: [...scope.constants.entries()].map(([name, entry]) => ({ name, ...entry })), - }; + }); }; diff --git a/spec/bridge/compiler/kit.ts b/spec/bridge/compiler/kit.ts index 0cad284a4..e63aaede8 100644 --- a/spec/bridge/compiler/kit.ts +++ b/spec/bridge/compiler/kit.ts @@ -8,21 +8,31 @@ import { type Expr, type FuncDecl, type Stmt } from "./ir.ts"; /** - * Converts a camelCase name to snake_case. + * Converts a camelCase or kebab-case name to snake_case. + * + * Module names are kebab-case, the way the directories under `src/` are, and every other name + * the frontend collects is camelCase, so both spellings arrive here. * * @param {string} name - The name. * @returns {string} The converted name. */ export const snake = (name: string): string => - name.replaceAll(/([a-z0-9])([A-Z])/g, "$1_$2").toLowerCase(); + name + .replaceAll(/([a-z0-9])([A-Z])/g, "$1_$2") + .replaceAll("-", "_") + .toLowerCase(); /** - * Converts a name to PascalCase. + * Converts a camelCase or kebab-case name to PascalCase. * * @param {string} name - The name. * @returns {string} The converted name. */ -export const pascal = (name: string): string => `${name.charAt(0).toUpperCase()}${name.slice(1)}`; +export const pascal = (name: string): string => + name + .split(/[-_]/) + .map((part) => `${part.charAt(0).toUpperCase()}${part.slice(1)}`) + .join(""); /** * Converts a camelCase name to kebab-case. @@ -31,7 +41,10 @@ export const pascal = (name: string): string => `${name.charAt(0).toUpperCase()} * @returns {string} The converted name. */ export const kebab = (name: string): string => - name.replaceAll(/([a-z0-9])([A-Z])/g, "$1-$2").toLowerCase(); + name + .replaceAll(/([a-z0-9])([A-Z])/g, "$1-$2") + .replaceAll("_", "-") + .toLowerCase(); /** * Converts a name to SCREAMING_SNAKE_CASE. diff --git a/spec/bridge/compiler/link.ts b/spec/bridge/compiler/link.ts new file mode 100644 index 000000000..8735567ff --- /dev/null +++ b/spec/bridge/compiler/link.ts @@ -0,0 +1,405 @@ +/** + * The two passes that let a utility be one file without repeating itself. + * + * `src/` in this repository is one directory per utility, with everything two of them share + * under `_internals/`. The source under `source/` is laid out the same way, and these two + * passes are what make that work across seven languages at once: + * + * - `inline` splices the helpers a module imports into the module, so the compiler still sees + * exactly one file and every target still emits exactly one self-contained unit. Nothing + * cross-references anything, which is what keeps the JavaScript output tree shakeable and + * the C ABI a flat list of symbols. + * - `prune` then drops whatever that splicing brought in and the module does not reach. A + * utility importing one helper out of a file of ten emits one helper. + * + * The alternative — emitting a shared module per target and importing across it — would mean + * seven different module systems, seven visibility models, and a Go package named after a + * directory that Rust would spell differently. Inlining costs a few duplicated helper bodies + * across utilities and buys all of that back. + */ +import { readFileSync } from "node:fs"; +import { dirname, resolve } from "node:path"; + +import { + type CharClass, + type ConstDecl, + type DataDecl, + type EnumDecl, + type ErrorDecl, + type Expr, + type FuncDecl, + type Module, + type PatternDecl, + type Stmt, + type StructDecl, + type Ty, +} from "./ir.ts"; +import { walk } from "./kit.ts"; + +/** `import { a, b } from "./_internals/name.ts"`, which is the only import that is resolved. */ +const INTERNAL_IMPORT = + /^import\s+(?:type\s+)?\{[^}]*\}\s+from\s+"([^"]*_internals\/[^"]+)";?[ \t]*$/gm; + +/** + * Reads a module and appends every helper file it imports, with the imports resolved. + * + * The helpers go after the module rather than before it, for two reasons: the frontend + * collects signatures in a first pass, so order does not matter to it, and the module's own + * doc comment has to stay the first block comment in the text. + * + * `export` is stripped from the helpers on the way in. A helper is shared source, not a public + * name, so once it is part of a module it is one of that module's private declarations, and + * every target emits it unexported. + * + * @param {string} path - The module path. + * @returns {string} The module's source with its helpers appended. + */ +export const inline = (path: string): string => { + const seen = new Set(); + const parts: string[] = []; + + const read = (file: string, top: boolean): void => { + if (seen.has(file)) return; + + seen.add(file); + + const text = readFileSync(file, "utf8"); + const imports = [...text.matchAll(INTERNAL_IMPORT)].map((match) => match[1]); + + parts.push( + top + ? text + : `\n// Inlined from ${file.slice(file.lastIndexOf("/source/") + 1)}.\n${text.replaceAll( + /^export /gm, + "", + )}`, + ); + + for (const from of imports) read(resolve(dirname(file), from), false); + }; + + read(path, true); + + return parts.join("\n"); +}; + +/** Every table a name can be found in, so that one lookup resolves a reference. */ +type Tables = { + functions: Map; + constants: Map; + patterns: Map; + charClasses: Map; + structs: Map; + enums: Map; + errors: Map; + data: Map; +}; + +/** The names reached so far, one set per table. */ +type Kept = Record>; + +/** + * Drops every private declaration the module's exported surface cannot reach. + * + * Reachability starts at the exported functions and the exported errors — a caller catches + * those by name, so they stay whether or not this module raises them — and follows calls, + * references, thrown errors, and the types of parameters, returns, locals and struct fields. + * + * @param {Module} module - The compiled module. + * @returns {Module} The same module with the unreachable declarations removed. + */ +export const prune = (module: Module): Module => { + const tables: Tables = { + functions: new Map(module.functions.map((entry) => [entry.name, entry])), + constants: new Map(module.constants.map((entry) => [entry.name, entry])), + patterns: new Map(module.patterns.map((entry) => [entry.name, entry])), + charClasses: new Map(module.charClasses.map((entry) => [entry.name, entry])), + structs: new Map(module.structs.map((entry) => [entry.name, entry])), + enums: new Map(module.enums.map((entry) => [entry.name, entry])), + errors: new Map(module.errors.map((entry) => [entry.name, entry])), + data: new Map(module.data.map((entry) => [entry.name, entry])), + }; + + const kept: Kept = { + functions: new Set(), + constants: new Set(), + patterns: new Set(), + charClasses: new Set(), + structs: new Set(), + enums: new Set(), + errors: new Set(), + data: new Set(), + }; + + const keepType = (ty: Ty): void => { + switch (ty.k) { + case "named": { + keepStruct(ty.name); + break; + } + case "enum": { + if (tables.enums.has(ty.name)) kept.enums.add(ty.name); + break; + } + case "list": + case "opt": + case "tasks": { + keepType(ty.of); + break; + } + default: { + break; + } + } + }; + + const keepStruct = (name: string): void => { + if (kept.structs.has(name)) return; + + const entry = tables.structs.get(name); + + if (entry === undefined) return; + + kept.structs.add(name); + + for (const field of entry.fields) keepType(field.ty); + }; + + const keepError = (name: string): void => { + if (kept.errors.has(name)) return; + + const entry = tables.errors.get(name); + + if (entry === undefined) return; + + kept.errors.add(name); + + if (entry.base !== undefined) keepError(entry.base); + }; + + const keepPattern = (name: string): void => { + if (kept.patterns.has(name)) return; + + const entry = tables.patterns.get(name); + + if (entry === undefined) return; + + kept.patterns.add(name); + + for (const step of entry.steps) kept.charClasses.add(step.charClass); + }; + + /** A bare name is whatever table holds it: they never collide inside one module. */ + const keepName = (name: string): void => { + if (tables.functions.has(name)) keepFunction(name); + if (tables.constants.has(name)) kept.constants.add(name); + if (tables.patterns.has(name)) keepPattern(name); + if (tables.charClasses.has(name)) kept.charClasses.add(name); + if (tables.data.has(name)) kept.data.add(name); + if (tables.errors.has(name)) keepError(name); + }; + + const keepExpr = (node: Expr): void => { + switch (node.k) { + case "ref": { + keepName(node.name); + break; + } + case "field": { + keepType(node.ty); + keepExpr(node.target); + break; + } + case "index": { + if (node.ty !== undefined) keepType(node.ty); + + keepExpr(node.target); + keepExpr(node.index); + break; + } + case "call": { + keepType(node.ty); + + if (node.callee.k === "user") keepFunction(node.callee.name); + if (node.callee.k === "error") keepError(node.callee.name); + + // `anyFailedWith(attempts, SomeError)` carries the error as its name, because what + // the targets compare is the kind rather than a class object. + if (node.callee.k === "std" && node.callee.name === "anyFailedWith") { + const kind = node.args[1]; + + if (kind?.k === "str") keepError(kind.value); + } + + for (const argument of node.args) keepExpr(argument); + + break; + } + case "bin": { + if (node.ty !== undefined) keepType(node.ty); + + keepExpr(node.left); + keepExpr(node.right); + break; + } + case "not": { + keepExpr(node.operand); + break; + } + case "cond": { + keepExpr(node.test); + keepExpr(node.whenTrue); + keepExpr(node.whenFalse); + break; + } + case "listOf": { + keepType(node.of); + + for (const item of node.items) keepExpr(item); + + break; + } + case "struct": { + keepStruct(node.name); + + for (const field of node.fields) keepExpr(field.value); + + break; + } + case "await": { + keepExpr(node.value); + break; + } + case "optionField": { + keepType(node.ty); + keepExpr(node.fallback); + break; + } + default: { + break; + } + } + }; + + const keepBody = (body: Stmt[]): void => { + for (const statement of body) { + switch (statement.k) { + case "let": { + keepType(statement.ty); + keepExpr(statement.value); + break; + } + case "assign": { + keepExpr(statement.value); + break; + } + case "if": { + keepExpr(statement.test); + keepBody(statement.then); + keepBody(statement.otherwise); + break; + } + case "return": { + if (statement.value !== undefined) keepExpr(statement.value); + + break; + } + case "forOf": { + keepType(statement.ty); + keepExpr(statement.iterable); + keepBody(statement.body); + break; + } + case "forRange": { + keepExpr(statement.from); + keepExpr(statement.until); + keepBody(statement.body); + break; + } + case "throw": { + keepError(statement.error); + keepExpr(statement.message); + break; + } + case "try": { + keepBody(statement.body); + keepBody(statement.catchBody); + break; + } + case "expr": { + keepExpr(statement.value); + break; + } + } + } + }; + + function keepFunction(name: string): void { + if (kept.functions.has(name)) return; + + const entry = tables.functions.get(name); + + if (entry === undefined) return; + + kept.functions.add(name); + + for (const param of entry.params) keepType(param.ty); + + keepType(entry.ret); + keepBody(entry.body); + } + + for (const entry of module.functions) if (entry.exported) keepFunction(entry.name); + + for (const entry of module.errors) if (entry.exported) keepError(entry.name); + + // A record the runtime already declares is not this module's to drop: an emitter recognises + // it by name and skips it, and the frontend needs it in the table to type a field read. + for (const entry of module.structs) if (entry.external === true) kept.structs.add(entry.name); + + return renumber({ + ...module, + charClasses: module.charClasses.filter((entry) => kept.charClasses.has(entry.name)), + constants: module.constants.filter((entry) => kept.constants.has(entry.name)), + data: module.data.filter((entry) => kept.data.has(entry.name)), + enums: module.enums.filter((entry) => kept.enums.has(entry.name)), + errors: module.errors.filter((entry) => kept.errors.has(entry.name)), + functions: module.functions.filter((entry) => kept.functions.has(entry.name)), + patterns: module.patterns.filter((entry) => kept.patterns.has(entry.name)), + structs: module.structs.filter((entry) => kept.structs.has(entry.name)), + }); +}; + +/** + * Closes the gaps pruning leaves in the character class names. + * + * The classes are interned as `class0`, `class1`, … in the order the regexes are read, so + * dropping one leaves a hole in a name a reader of the generated code would otherwise take for + * a missing declaration. + * + * @param {Module} module - The pruned module. + * @returns {Module} The same module with its character classes numbered from zero. + */ +const renumber = (module: Module): Module => { + const renamed = new Map(); + + for (const [index, entry] of module.charClasses.entries()) { + const name = `class${index}`; + + if (name !== entry.name) renamed.set(entry.name, name); + + entry.name = name; + } + + if (renamed.size === 0) return module; + + for (const entry of module.patterns) + for (const step of entry.steps) step.charClass = renamed.get(step.charClass) ?? step.charClass; + + for (const entry of module.functions) + walk(entry.body, (node) => { + if (node.k === "ref") node.name = renamed.get(node.name) ?? node.name; + }); + + return module; +}; diff --git a/spec/bridge/compiler/targets/cabi.ts b/spec/bridge/compiler/targets/cabi.ts index d02c29e2c..f47d1ce4d 100644 --- a/spec/bridge/compiler/targets/cabi.ts +++ b/spec/bridge/compiler/targets/cabi.ts @@ -19,7 +19,7 @@ * guessed at; those need a richer surface than this POC has. */ import { type Expr, type FuncDecl, type Module, type Ty } from "../ir.ts"; -import { optionReads, snake } from "../kit.ts"; +import { optionReads, screaming, snake } from "../kit.ts"; /** One parameter of the C entry point. */ type Slot = { name: string; c: string; rust: string }; @@ -35,11 +35,13 @@ const scalarC = (ty: Ty): string => (ty.k === "bool" ? "int32_t" : "int64_t"); const scalarRust = (ty: Ty): string => (ty.k === "bool" ? "i32" : "i64"); /** - * The entry point name a C caller sees: `cnpj_is_valid_cnpj`, module prefixed so two utilities - * can live in one library without colliding. + * The entry point name a C caller sees: `is_valid_cnpj`, or `_` for the rare + * module that exposes more than one, so two utilities never collide in one library. */ const symbol = (module: Module, entry: FuncDecl): string => - `${snake(module.name)}_${snake(entry.name)}`; + snake(module.name) === snake(entry.name) + ? snake(entry.name) + : `${snake(module.name)}_${snake(entry.name)}`; /** * Whether a function can be exposed, and why not when it cannot. @@ -189,8 +191,8 @@ const header = (module: Module, exposed: FuncDecl[]): string => { * is too small nothing is written and the length needed is returned, so the caller can size it * and call again. */ -#ifndef BRAZILIAN_UTILS_${module.name.toUpperCase()}_H -#define BRAZILIAN_UTILS_${module.name.toUpperCase()}_H +#ifndef BRAZILIAN_UTILS_${screaming(module.name)}_H +#define BRAZILIAN_UTILS_${screaming(module.name)}_H #include #include @@ -209,6 +211,59 @@ ${declarations} `; }; +/** One argument of a C entry point, as a caller has to build it. */ +export type AbiArg = + | { k: "text"; param: string } + | { k: "scalar"; param: string; ty: Ty } + | { k: "option"; field: string; ty: Ty; unset: string }; + +/** What a caller needs to know to reach one entry point: its symbol, arguments and answer. */ +export type Abi = { symbol: string; args: AbiArg[]; returns: "bool" | "string" }; + +/** + * Describes the C entry point of one function, for a caller that has to build the call. + * + * @param {Module} module - The compiled module. + * @param {FuncDecl} entry - The exported function. + * @returns {Abi | undefined} The description, or undefined when the shape cannot cross a C + * boundary at all. + */ +export const abiOf = (module: Module, entry: FuncDecl): Abi | undefined => { + if (refuse(entry) !== "") return undefined; + + const args: AbiArg[] = []; + + for (const param of entry.params) { + if (param.ty.k === "named") continue; + + args.push( + param.ty.k === "int" || param.ty.k === "bool" + ? { k: "scalar", param: param.name, ty: param.ty } + : { k: "text", param: param.name }, + ); + } + + for (const read of optionReads(entry)) { + const ty = read.expr.k === "optionField" ? read.expr.ty : ({ k: "int" } as Ty); + const fallback = read.expr.k === "optionField" ? read.expr.fallback : ({ k: "none" } as Expr); + + args.push({ + k: "option", + field: read.field, + ty, + // The sentinel the body already compares to: a flag is off at zero, and a number is + // unset at whatever the source falls back to. + unset: ty.k === "bool" ? "0" : String((fallback as Extract).value ?? -1), + }); + } + + return { + symbol: symbol(module, entry), + args, + returns: entry.ret.k === "bool" ? "bool" : "string", + }; +}; + /** * Emits the C ABI of one module: a Rust source file and the header that describes it. * @@ -236,7 +291,7 @@ export const emit = (module: Module): Record => { : `//\n// Not exposed, because the shapes below need more than pointers and integers:\n${skipped.join("\n")}\n`; return { - [`src/cabi_${module.name}.rs`]: `// Code generated from spec/bridge/source/${module.name}.ts. DO NOT EDIT. + [`src/cabi_${snake(module.name)}.rs`]: `// Code generated from spec/bridge/source/${module.name}.ts. DO NOT EDIT. // // The C ABI of this module: what a hand-written binding in Python, Ruby, C#, Java or Erlang // calls. Everything is a pointer, a length or an integer, and nothing crosses that either side @@ -246,6 +301,6 @@ use crate::${snake(module.name)}; ${exposed.map((entry) => entryPoint(module, entry)).join("\n\n")} `, - [`include/${module.name}.h`]: header(module, exposed), + [`include/${snake(module.name)}.h`]: header(module, exposed), }; }; diff --git a/spec/bridge/compiler/targets/csharp.ts b/spec/bridge/compiler/targets/csharp.ts index 3a2b1a5e5..3fb6a8720 100644 --- a/spec/bridge/compiler/targets/csharp.ts +++ b/spec/bridge/compiler/targets/csharp.ts @@ -545,7 +545,10 @@ export const emit = (module: Module): Record => { ...module.data.map((entry) => entry.name), ]); - const className = pascal(module.name); + // C# refuses a member whose name matches its enclosing type, and a one-function module is + // exactly that case, so the class the function lives in carries a suffix. It is scaffolding + // either way: the published package wraps these in its own hand-written surface. + const className = `${pascal(module.name)}Utility`; const constants = module.constants .map((entry) => entry.ty.k === "list" diff --git a/spec/bridge/compiler/targets/go.ts b/spec/bridge/compiler/targets/go.ts index 9535b3381..2668245e9 100644 --- a/spec/bridge/compiler/targets/go.ts +++ b/spec/bridge/compiler/targets/go.ts @@ -20,7 +20,7 @@ import { type StructDecl, type Ty, } from "../ir.ts"; -import { optionReads, pascal, prose, screaming } from "../kit.ts"; +import { optionReads, pascal, prose, screaming, snake } from "../kit.ts"; const RUNTIME = resolve(import.meta.dirname, "../runtime/go.go"); @@ -454,10 +454,10 @@ export const emit = (module: Module): Record => { return { "runtime/runtime.go": readFileSync(RUNTIME, "utf8"), "go.mod": "module brazilianutils/bridge\n\ngo 1.22\n", - [`${module.name}/${module.name}.go`]: `// Code generated from spec/bridge/source/${module.name}.ts. DO NOT EDIT. + [`${snake(module.name)}/${snake(module.name)}.go`]: `// Code generated from spec/bridge/source/${module.name}.ts. DO NOT EDIT. -// Package ${module.name} holds the generated ${module.name} utilities. -package ${module.name} +// Package ${snake(module.name)} holds the generated ${module.name} utility. +package ${snake(module.name)} import "brazilianutils/bridge/runtime" diff --git a/spec/bridge/compiler/targets/python.ts b/spec/bridge/compiler/targets/python.ts index e4c891816..c9da7f804 100644 --- a/spec/bridge/compiler/targets/python.ts +++ b/spec/bridge/compiler/targets/python.ts @@ -411,9 +411,9 @@ export const emit = (module: Module, modules: Module[] = [module]): Record `from .${entry.name} import * # noqa: F401,F403`) + .map((entry) => `from .${snake(entry.name)} import * # noqa: F401,F403`) .join("\n")}\n`, - [`brutils_bridge/${module.name}.py`]: `# Code generated from spec/bridge/source/${module.name}.ts. DO NOT EDIT. + [`brutils_bridge/${snake(module.name)}.py`]: `# Code generated from spec/bridge/source/${module.name}.ts. DO NOT EDIT. """${module.doc}""" from dataclasses import dataclass diff --git a/spec/bridge/compiler/targets/ruby.ts b/spec/bridge/compiler/targets/ruby.ts index 4d952e33e..0b2842a6c 100644 --- a/spec/bridge/compiler/targets/ruby.ts +++ b/spec/bridge/compiler/targets/ruby.ts @@ -18,7 +18,7 @@ import { type Stmt, type StructDecl, } from "../ir.ts"; -import { optionReads, prose, screaming, snake } from "../kit.ts"; +import { optionReads, pascal, prose, screaming, snake } from "../kit.ts"; const RUNTIME = resolve(import.meta.dirname, "../runtime/ruby.rb"); const NAMESPACE = "BrazilianUtilsBridge"; @@ -348,14 +348,14 @@ export const emit = (module: Module): Record => { ...module.data.map((entry) => entry.name), ]); - const moduleName = `${module.name.charAt(0).toUpperCase()}${module.name.slice(1)}`; + const moduleName = pascal(module.name); const constants = module.constants .map((entry) => ` ${screaming(entry.name)} = ${expr(entry.expr)}.freeze`) .join("\n"); return { "lib/brazilian_utils_bridge/runtime.rb": readFileSync(RUNTIME, "utf8"), - [`lib/brazilian_utils_bridge/${module.name}.rb`]: `# frozen_string_literal: true + [`lib/brazilian_utils_bridge/${snake(module.name)}.rb`]: `# frozen_string_literal: true # Code generated from spec/bridge/source/${module.name}.ts. DO NOT EDIT. diff --git a/spec/bridge/compiler/targets/rust.ts b/spec/bridge/compiler/targets/rust.ts index 86cf5fa8a..8c559741a 100644 --- a/spec/bridge/compiler/targets/rust.ts +++ b/spec/bridge/compiler/targets/rust.ts @@ -598,7 +598,7 @@ export const emit = (module: Module, allModules: Module[] = [module]): Record entry.name))]; + const modules = [...new Set(allModules.map((entry) => snake(entry.name)))]; return { ...cabi, @@ -613,7 +613,7 @@ ${modules.map((name) => `pub mod ${name};`).join("\n")} // The C ABI, for the ecosystems that bind to this crate instead of generating their own source. ${allModules .filter((entry) => Object.keys(emitCabi(entry)).length > 0) - .map((entry) => `pub mod cabi_${entry.name};`) + .map((entry) => `pub mod cabi_${snake(entry.name)};`) .join("\n")} `, "Cargo.toml": `[package] @@ -631,7 +631,7 @@ path = "src/lib.rs" # lib for a Rust caller, cdylib and staticlib for every binding that is not Rust. crate-type = ["lib", "cdylib", "staticlib"] `, - [`src/${module.name}.rs`]: `// Code generated from spec/bridge/source/${module.name}.ts. DO NOT EDIT. + [`src/${snake(module.name)}.rs`]: `// Code generated from spec/bridge/source/${module.name}.ts. DO NOT EDIT. //! ${module.doc} diff --git a/spec/bridge/conformance/cases.ts b/spec/bridge/conformance/cases.ts new file mode 100644 index 000000000..a759a687d --- /dev/null +++ b/spec/bridge/conformance/cases.ts @@ -0,0 +1,271 @@ +/** + * The conformance protocol: what a case is, how it is written down, and how an answer is + * spelled so that eight languages can agree on it. + * + * A utility contributes one file under `conformance/cases/`, and that file only says which + * arguments to replay. Everything else is derived: the expectation comes from calling the + * package this repository ships, the columns come from the compiled signature, and the driver + * that replays them in each language is generated. Adding a utility therefore touches its own + * two files and nothing else. + * + * A case table is TSV rather than JSON because every target has to read it, and splitting a + * line on a tab needs no parser in any of them. Three characters are escaped — backslash, tab + * and newline — and each driver unescapes the same three. + */ +import { readdirSync } from "node:fs"; +import { resolve } from "node:path"; + +import { type FuncDecl, type Module, type StructDecl, type Ty } from "../compiler/ir.ts"; + +/** + * The package this repository ships, as a recorder sees it. + * + * Untyped on purpose: a recorder names a function and hands it arguments a JavaScript + * caller could write, which is the whole point of the boundary cases. + */ +export type Shipped = Record unknown>; + +/** What a recorder under `conformance/cases/` exports. */ +export type Recorder = { + /** The module under `source/`, without the extension. */ + module: string; + /** + * The argument lists to replay, as they would be written in JavaScript. A trailing options + * object is one argument; omit it to record the call without options. + * + * @param shipped - The package this repository ships, bundled. + * @returns The argument lists. + */ + inputs: (shipped: Shipped) => unknown[][]; + /** + * How to call the shipped function, for a utility that needs something around the call — + * a stubbed `fetch`, a fixed clock. The default is to apply it to the arguments. + */ + call?: (shipped: Shipped, fn: string, args: unknown[]) => Promise; + /** + * Serves whatever the generated code talks to while the other targets replay, for a utility + * that reaches the network. The returned function stops it. + * + * @param port - The port to listen on. + * @returns A function that stops the server. + */ + serve?: (port: number) => Promise<() => void>; +}; + +/** One recorded call: what went in, and what the shipped package answered or raised. */ +export type Recorded = { + args: unknown[]; + value?: unknown; + failure?: { kind: string; message: string }; +}; + +/** Every target a case can be replayed in. `cabi` is the C ABI rather than a language. */ +export const TARGETS = [ + "typescript", + "python", + "ruby", + "go", + "rust", + "java", + "csharp", + "cabi", +] as const; + +/** + * The targets that can still be handed a value their declared types do not allow. + * + * The other five lower `string | number` to `string` and a closed list of names to a list of + * strings, so a call a JavaScript caller can make — a number where a string is declared, `null` + * where a list is — has no form in them at all. TypeScript keeps the union and keeps the guard, + * so it stays on this side of the line even though it is compiled. + */ +export const DYNAMIC = ["typescript", "python", "ruby"]; + +/** + * The targets that tell "given as null" apart from "not given at all". + * + * An optional field in Python and Ruby is one value, so a caller there cannot say that it + * passed `null`; TypeScript has both `null` and `undefined` and keeps the difference. + */ +export const NULLABLE = ["typescript"]; + +/** One column of a case table. */ +export type Column = + | { k: "targets" } + /** A positional argument, as text. */ + | { k: "arg"; name: string; ty: Ty; index: number } + /** `string` or `number`: which side of a `string | number` an argument was given as. */ + | { k: "kind"; name: string; index: number } + /** `1` when an optional positional argument was given at all. */ + | { k: "set"; name: string; index: number } + /** + * One field of the options record, empty when it was not given. + * + * A value the field's declared type does not allow — what an untyped JavaScript caller can + * still pass — is written as `!null`, `!string`, `!number`, `!object` or `!boolean`, and + * every driver that can express it turns the token back into a value of that shape. + */ + | { k: "option"; name: string; ty: Ty; field: string } + | { k: "expect" }; + +/** Escapes the three characters the table format reserves. */ +export const cell = (value: string): string => + value + .replaceAll("\\", String.raw`\\`) + .replaceAll("\t", String.raw`\t`) + .replaceAll("\n", String.raw`\n`); + +/** The options record of a function, when it takes one. */ +export const optionsOf = (module: Module, entry: FuncDecl): StructDecl | undefined => { + const named = entry.params.map((param) => param.ty).find((ty) => ty.k === "named"); + + if (named === undefined) return; + + return module.structs.find((struct) => struct.name === named.name); +}; + +/** + * The columns of one function's case table, in order. + * + * @param {Module} module - The compiled module. + * @param {FuncDecl} entry - The exported function. + * @returns {Column[]} The columns. + */ +export const columnsOf = (module: Module, entry: FuncDecl): Column[] => { + const columns: Column[] = [{ k: "targets" }]; + + for (const [index, param] of entry.params.entries()) { + if (param.ty.k === "named") continue; + + if (param.optional) columns.push({ k: "set", name: param.name, index }); + + columns.push({ k: "arg", name: param.name, ty: param.ty, index }); + + // Any target can be handed text. Only the three that still check at run time can be + // handed a number where the signature says otherwise, so the column exists for both + // `string` and `string | number`, and the row says who can replay it. + if (param.ty.k === "scalar" || param.ty.k === "string") + columns.push({ k: "kind", name: param.name, index }); + } + + for (const field of optionsOf(module, entry)?.fields ?? []) + columns.push({ k: "option", name: field.name, ty: field.ty, field: field.name }); + + columns.push({ k: "expect" }); + + return columns; +}; + +/** The header line of a case table, which is documentation: the drivers read by position. */ +export const headerOf = (columns: Column[]): string => + columns + .map((column) => { + switch (column.k) { + case "targets": { + return "targets"; + } + case "expect": { + return "expect"; + } + case "kind": { + return `${column.name}#kind`; + } + case "set": { + return `${column.name}#set`; + } + default: { + return column.name; + } + } + }) + .join("\t"); + +/** + * Renders a value the way every target has to render it. + * + * Text, so that one comparison covers a boolean, a record and a list of five thousand rows. + * A record is its fields in declared order joined by `|`, a list is its length followed by one + * rendered item per line, and an absent optional is `~`. + * + * @param {unknown} value - The value the shipped package answered. + * @param {Ty} ty - The declared type of that value. + * @param {Module} module - The compiled module, for the records the type names. + * @returns {string} The rendered value. + */ +export const render = (value: unknown, ty: Ty, module: Module): string => { + switch (ty.k) { + case "bool": { + return value === true ? "true" : "false"; + } + case "int": { + return String(value); + } + case "opt": { + return value === undefined || value === null ? "~" : render(value, ty.of, module); + } + case "list": { + const items = value as unknown[]; + + return [String(items.length), ...items.map((item) => render(item, ty.of, module))].join("\n"); + } + case "named": { + const struct = module.structs.find((entry) => entry.name === ty.name); + const record = value as Record; + + return (struct?.fields ?? []) + .map((field) => render(record[field.name], field.ty, module)) + .join("|"); + } + default: { + return String(value); + } + } +}; + +/** How a failure is written down: the class the shipped package raised, and its message. */ +export const renderFailure = (kind: string, message: string): string => `!${kind}|${message}`; + +/** + * Reads every recorder under `conformance/cases/`. + * + * @returns {Promise} The recorders, in name order. Empty when there are none, + * which is what the engine on its own looks like. + */ +export const loadRecorders = async (): Promise => { + const directory = resolve(import.meta.dirname, "cases"); + let names: string[] = []; + + try { + // A `_` prefix is a helper the recorders share, not a recorder. + names = readdirSync(directory).filter((name) => name.endsWith(".ts") && !name.startsWith("_")); + } catch { + return []; + } + + const found: Recorder[] = []; + + for (const name of names.sort()) { + const loaded = (await import(resolve(directory, name))) as { recorder: Recorder }; + + found.push(loaded.recorder); + } + + return found; +}; + +/** + * The one exported function of a module, which is what a utility is. + * + * @param {Module} module - The compiled module. + * @returns {FuncDecl} Its exported function. + */ +export const entryOf = (module: Module): FuncDecl => { + const exported = module.functions.filter((entry) => entry.exported); + + if (exported.length !== 1) + throw new Error( + `${module.name}: a utility exports one function, this one exports ${exported.length}`, + ); + + return exported[0]; +}; diff --git a/spec/bridge/conformance/cep.ts b/spec/bridge/conformance/cep.ts deleted file mode 100644 index c43519480..000000000 --- a/spec/bridge/conformance/cep.ts +++ /dev/null @@ -1,337 +0,0 @@ -/** - * The CEP scenarios, the expectations recorded from the package this repository ships, and the - * mock server the other six targets are pointed at. - * - * One table drives both sides: `node conformance/cep.ts record` replays the scenarios against - * the shipped package with `fetch` mocked, exactly as the JavaScript suite does, and - * `node conformance/cep.ts serve ` answers the same scenarios over real HTTP so the - * generated Go, Rust, Ruby, Java, C# and Python run against something a real client can talk to. - * - * A scenario is keyed by the CEP, so no target needs to be told which one it is in: the CEP in - * the URL is the whole protocol. - */ -import { mkdtempSync, rmSync, writeFileSync } from "node:fs"; -import { createServer } from "node:http"; -import { tmpdir } from "node:os"; -import { join, resolve } from "node:path"; - -import { build } from "esbuild"; - -const bridge = resolve(import.meta.dirname, ".."); -const root = resolve(bridge, "../.."); - -/** What one provider answers in one scenario. `fail` is a transport failure, not an answer. */ -type Answer = { status: number; body: unknown } | { fail: true }; - -type Scenario = { viacep: Answer; widenet: Answer; brasilapi: Answer }; - -const address = (cep: string): Record => ({ - bairro: "Bela Vista", - cep, - localidade: "São Paulo", - logradouro: "Avenida Paulista", - uf: "SP", -}); - -const widenetAddress = (cep: string): Record => ({ - address: "Avenida Paulista", - city: "São Paulo", - code: cep, - district: "Bela Vista", - ok: true, - state: "SP", - status: 200, -}); - -const brasilApiAddress = (cep: string): Record => ({ - cep, - city: "São Paulo", - neighborhood: "Bela Vista", - state: "SP", - street: "Avenida Paulista", -}); - -const NOT_FOUND_BODY = { errors: [{ message: "CEP não encontrado" }] }; - -/** - * The scenarios, by CEP. Every provider that succeeds in a scenario answers the same address, - * so which one wins the race cannot change the expected result. - */ -export const SCENARIOS: Record = { - // Every provider answers. - "01310100": { - viacep: { status: 200, body: address("01310-100") }, - widenet: { status: 200, body: widenetAddress("01310-100") }, - brasilapi: { status: 200, body: brasilApiAddress("01310100") }, - }, - // Every provider reports a miss, each in its own way. - "00000000": { - viacep: { status: 200, body: { erro: true } }, - widenet: { status: 200, body: { ok: false, status: 404 } }, - brasilapi: { status: 200, body: NOT_FOUND_BODY }, - }, - // Every provider answers an HTTP error. - "00000001": { - viacep: { status: 500, body: {} }, - widenet: { status: 503, body: {} }, - brasilapi: { status: 500, body: {} }, - }, - // Nothing reaches any server. - "00000002": { viacep: { fail: true }, widenet: { fail: true }, brasilapi: { fail: true } }, - // Only BrasilAPI answers, and it is the one the caller gets. - "00000003": { - viacep: { fail: true }, - widenet: { status: 503, body: {} }, - brasilapi: { status: 200, body: brasilApiAddress("00000003") }, - }, - // BrasilAPI reports the miss with a status, the others are simply down: not found wins. - "00000004": { - viacep: { status: 500, body: {} }, - widenet: { status: 503, body: {} }, - brasilapi: { status: 404, body: NOT_FOUND_BODY }, - }, - // A body that is not an object at all. - "00000005": { - viacep: { status: 200, body: "oops" }, - widenet: { status: 200, body: 42 }, - brasilapi: { status: 200, body: null }, - }, - // The optional fields are missing. - "00000006": { - viacep: { status: 200, body: { cep: "00000006" } }, - widenet: { status: 200, body: { code: "00000006", ok: true, status: 200 } }, - brasilapi: { status: 200, body: { cep: "00000006" } }, - }, - // ViaCEP answers fields that are not strings. - "00000007": { - viacep: { status: 200, body: { ...address("00000007"), localidade: null, uf: 12 } }, - widenet: { status: 503, body: {} }, - brasilapi: { status: 500, body: {} }, - }, - // The CEP comes back masked and has to be stripped. - "00000008": { - viacep: { status: 200, body: address("00000-008") }, - widenet: { status: 200, body: widenetAddress("00000-008") }, - brasilapi: { status: 200, body: brasilApiAddress("00000-008") }, - }, - // An empty CEP in the body is a miss, whatever else the body holds. - "00000009": { - viacep: { status: 200, body: { ...address(""), cep: "" } }, - widenet: { status: 200, body: { ...widenetAddress(""), code: "" } }, - brasilapi: { status: 200, body: { ...brasilApiAddress(""), cep: "" } }, - }, - // Widenet's own flags disagree with its body. - "00000010": { - viacep: { status: 500, body: {} }, - widenet: { status: 200, body: { code: "00000010", ok: false, status: 200 } }, - brasilapi: { status: 500, body: {} }, - }, - "00000011": { - viacep: { status: 500, body: {} }, - widenet: { status: 200, body: { code: "00000011", ok: true, status: 404 } }, - brasilapi: { status: 500, body: {} }, - }, - // A miss reported alongside a CEP is still a miss. - "00000012": { - viacep: { status: 200, body: { cep: "00000-012", erro: true } }, - widenet: { status: 503, body: {} }, - brasilapi: { status: 200, body: { ...brasilApiAddress("00000012"), ...NOT_FOUND_BODY } }, - }, - // One provider misses and the other is down: the miss is what the caller hears about. - "00000013": { - viacep: { status: 200, body: { erro: true } }, - widenet: { fail: true }, - brasilapi: { fail: true }, - }, -}; - -/** The provider sets a case can ask for. `-` is "the caller named none". */ -type Providers = string; - -type Case = { cep: string; kind: "string" | "number"; providers: Providers }; - -const EVERY_PROVIDER = [ - "-", - "viacep", - "widenet", - "brasilapi", - "viacep|brasilapi", - "viacep|widenet|brasilapi", -]; - -const cases: Case[] = []; - -for (const cep of Object.keys(SCENARIOS)) { - for (const providers of EVERY_PROVIDER) cases.push({ cep, kind: "string", providers }); -} - -// The inputs that never reach a provider. -for (const cep of ["12345", "123456789", "", "1310100", "abc", "0131010a"]) - cases.push({ cep, kind: "string", providers: "-" }); - -// A mask is stripped, and a number is padded; both land on the first scenario. -cases.push( - { cep: "01310-100", kind: "string", providers: "-" }, - { cep: "01.310-100", kind: "string", providers: "-" }, - { cep: "1310100", kind: "number", providers: "-" }, - { cep: "1310100", kind: "number", providers: "brasilapi" }, -); - -// Provider lists that name nothing usable. -for (const providers of ["[]", "invalid", "constructor|toString", "VIACEP"]) - cases.push({ cep: "01310100", kind: "string", providers }); - -// An unknown name among known ones is dropped rather than fatal. -cases.push({ cep: "01310100", kind: "string", providers: "viacep|invalid|brasilapi" }); - -/** The values a `providers` option can take that are not a list at all. */ -export const NOT_A_LIST: Record = { - "!null": null, - "!string": "viacep", - "!number": 5, - "!object": {}, - "!bool": true, -}; - -for (const providers of Object.keys(NOT_A_LIST)) - cases.push({ cep: "01310100", kind: "string", providers }); - -/** Reads a `providers` cell back into the value the call takes. */ -const optionsOf = (providers: Providers): Record | undefined => { - if (providers === "-") return undefined; - if (providers === "[]") return { providers: [] }; - if (providers.startsWith("!")) return { providers: NOT_A_LIST[providers] }; - - return { providers: providers.split("|") }; -}; - -/** The answer a provider gives for a CEP, or a 404 when the scenario does not know it. */ -export const answerFor = (provider: keyof Scenario, cep: string): Answer => { - const scenario = SCENARIOS[cep]; - - if (scenario === undefined) return { status: 404, body: NOT_FOUND_BODY }; - - return scenario[provider]; -}; - -/** Which provider a mock server path belongs to. */ -export const providerOf = (path: string): keyof Scenario | undefined => { - if (path.includes("viacep.com.br")) return "viacep"; - if (path.includes("widenet.com.br")) return "widenet"; - if (path.includes("brasilapi.com.br")) return "brasilapi"; - - return undefined; -}; - -/** The CEP a mock server path asks about. */ -export const cepOf = (path: string): string => { - const digits = path.replaceAll(/\D/g, ""); - - return digits.slice(-8); -}; - -const serve = (port: number): void => { - const server = createServer((request, response) => { - const path = request.url ?? ""; - const provider = providerOf(path); - const answer = - provider === undefined ? { status: 404, body: {} } : answerFor(provider, cepOf(path)); - - if ("fail" in answer) { - request.socket.destroy(); - - return; - } - - response.writeHead(answer.status, { "content-type": "application/json; charset=utf-8" }); - response.end(JSON.stringify(answer.body)); - }); - - server.listen(port, "127.0.0.1", () => { - console.log(`cep mock server on http://127.0.0.1:${port}`); - }); -}; - -const record = async (): Promise => { - const outDir = mkdtempSync(join(tmpdir(), "brutils-cep-")); - const bundlePath = join(outDir, "shipped.mjs"); - - await build({ - entryPoints: [resolve(root, "src/index.ts")], - bundle: true, - format: "esm", - platform: "neutral", - outfile: bundlePath, - logLevel: "error", - }); - - const shipped = (await import(bundlePath)) as { - getAddressInfoByCep: ( - cep: string | number, - options?: Record, - ) => Promise>; - }; - - rmSync(outDir, { recursive: true, force: true }); - - const realFetch = globalThis.fetch; - - globalThis.fetch = ((input: unknown): Promise => { - const url = String(input); - const provider = providerOf(url); - const answer = - provider === undefined ? { status: 404, body: {} } : answerFor(provider, cepOf(url)); - - if ("fail" in answer) { - // The shipped `fetchWithRetry` retries on a transient transport failure, so the mock - // reports one the same way the mock server does by closing the socket. - const error = new Error("fetch failed"); - - (error as { cause?: unknown }).cause = { code: "ECONNRESET" }; - - return Promise.reject(error); - } - - return Promise.resolve({ - ok: answer.status >= 200 && answer.status < 300, - status: answer.status, - json: () => Promise.resolve(answer.body), - }); - }) as typeof fetch; - - const lines = ["cep\tkind\tproviders\toutcome\tdetail"]; - - for (const entry of cases) { - const input = entry.kind === "number" ? Number(entry.cep) : entry.cep; - let outcome = "ok"; - let detail = ""; - - try { - const found = await shipped.getAddressInfoByCep(input, optionsOf(entry.providers)); - - detail = [ - found["cep"], - found["state"], - found["city"], - found["neighborhood"], - found["street"], - ].join("|"); - } catch (error) { - outcome = "error"; - detail = `${(error as Error).name}|${(error as Error).message}`; - } - - lines.push([entry.cep, entry.kind, entry.providers, outcome, detail].join("\t")); - } - - globalThis.fetch = realFetch; - - writeFileSync(resolve(bridge, "conformance/cep.expected.tsv"), `${lines.join("\n")}\n`); - - console.log(`${cases.length} CEP cases recorded from the shipped package`); -}; - -const [command, argument] = process.argv.slice(2); - -if (command === "serve") serve(Number(argument)); -else await record(); diff --git a/spec/bridge/conformance/drivers.ts b/spec/bridge/conformance/drivers.ts index 9e7769be6..3ae6eaf12 100644 --- a/spec/bridge/conformance/drivers.ts +++ b/spec/bridge/conformance/drivers.ts @@ -1,1330 +1,1593 @@ /** - * Turns the recorded vectors into a table every target can read, and writes the small driver - * each language uses to replay it. + * Writes the small program each target runs to replay the recorded tables. * - * A tab separated file rather than JSON: every target can split a line without a parser, and - * the escaping rules are the same everywhere, which keeps the drivers honest and tiny. + * Every driver is generated from the compiled signature, so adding a utility adds rows to a + * table and nothing to this file. A driver reads its table, rebuilds each call from the + * columns, renders the answer the way `cases.ts` defines, and compares. Eight of them, one + * per target plus the C ABI, all doing the same thing in their own idiom. + * + * The rendering is the contract: a boolean is `true`/`false`, a record is its fields joined by + * `|`, a list is its length and then one rendered item per line, and a raised error is + * `!Class|message`. One string comparison then covers every shape a utility can answer. * * Usage: `node spec/bridge/conformance/drivers.ts` */ -import { mkdirSync, readFileSync, writeFileSync } from "node:fs"; +import { mkdirSync, writeFileSync } from "node:fs"; import { dirname, resolve } from "node:path"; -import { type Case } from "./vectors.ts"; +import { compileModule } from "../compiler/frontend.ts"; +import { type FuncDecl, type Module, type Ty } from "../compiler/ir.ts"; +import { pascal, snake } from "../compiler/kit.ts"; +import { type Abi, abiOf } from "../compiler/targets/cabi.ts"; +import { columnsOf, entryOf, loadRecorders, optionsOf } from "./cases.ts"; const bridge = resolve(import.meta.dirname, ".."); -const vectors = JSON.parse(readFileSync(resolve(bridge, "conformance/vectors.json"), "utf8")) as { - cases: Case[]; + +/** One positional argument, and the columns that carry it. */ +type ArgPlan = { name: string; ty: Ty; at: number; kind: number; set: number }; + +/** One field of the options record, and the column that carries it. */ +type OptPlan = { name: string; ty: Ty; at: number }; + +/** Everything a driver needs to know about one utility. */ +type Plan = { + module: Module; + entry: FuncDecl; + args: ArgPlan[]; + opts: OptPlan[]; + options: string; + expect: number; + abi: Abi | undefined; }; -/** Escapes the three characters the table format reserves. */ -const cell = (value: string): string => - value - .replaceAll("\\", String.raw`\\`) - .replaceAll("\t", String.raw`\t`) - .replaceAll("\n", String.raw`\n`); - -const columns = ["fn", "input", "kind", "version", "pad", "obfuscate", "expected"]; -const lines = [columns.join("\t")]; - -for (const entry of vectors.cases) { - const options = entry.options as { version?: number; pad?: boolean; obfuscate?: boolean }; - - lines.push( - [ - entry.fn, - cell(String(entry.input)), - typeof entry.input === "number" ? "number" : "string", - options.version === undefined ? "" : String(options.version), - options.pad === true ? "1" : "", - options.obfuscate === true ? "1" : "", - cell(entry.expected), - ].join("\t"), - ); -} +/** Where a driver finds a table, relative to the directory it runs in. */ +const tableOf = (plan: Plan): string => `../../conformance/recorded/${plan.module.name}.tsv`; -const tablePath = resolve(bridge, "conformance/vectors.tsv"); +/** Reads the columns back into the shape a driver is written against. */ +const planOf = (module: Module): Plan => { + const entry = entryOf(module); + const columns = columnsOf(module, entry); + const args: ArgPlan[] = []; + const opts: OptPlan[] = []; -writeFileSync(tablePath, `${lines.join("\n")}\n`); + for (const [at, column] of columns.entries()) { + if (column.k === "arg") args.push({ name: column.name, ty: column.ty, at, kind: -1, set: -1 }); + if (column.k === "kind") (args.at(-1) as ArgPlan).kind = at; + if (column.k === "option") opts.push({ name: column.name, ty: column.ty, at }); + } -const files: Record = { - "out/typescript/conformance.ts": `// Code generated by spec/bridge/conformance/drivers.ts. DO NOT EDIT. -import { readFileSync } from "node:fs"; -import { resolve } from "node:path"; -import { formatCnpj, isValidCnpj } from "./_bridge/cnpj.ts"; -import { type StateCode, getMunicipalities } from "./_bridge/municipalities.ts"; -import { type CepProvider, getAddressInfoByCep } from "./_bridge/cep.ts"; + // The `#set` column comes before the argument it belongs to, so it is matched by name. + for (const [at, column] of columns.entries()) + if (column.k === "set") for (const arg of args) if (arg.name === column.name) arg.set = at; + + return { + module, + entry, + args, + opts, + options: optionsOf(module, entry)?.name ?? "", + expect: columns.length - 1, + abi: abiOf(module, entry), + }; +}; -const table = readFileSync(resolve(import.meta.dirname, "../../conformance/vectors.tsv"), "utf8"); -const unescape = (value: string): string => - value.replaceAll("\\\\t", "\\t").replaceAll("\\\\n", "\\n").replaceAll("\\\\\\\\", "\\\\"); +/** + * The five values a list-typed option can be given that are not a list at all. + * + * Only the three targets that still check at run time are ever handed one, and each spells + * them in its own syntax, so the table is per target rather than shared. + */ +const NOT_A_LIST: Record = { + typescript: ["null", '"viacep"', "5", "{}", "true"], + python: ["None", '"viacep"', "5", "{}", "True"], + ruby: ["nil", "'viacep'", "5", "{}", "true"], +}; -let passed = 0; -let failed = 0; +/** That table as a literal the target can read by token. */ +const notAList = (target: string, open: string, close: string, arrow: string): string => + `${open}${["!null", "!string", "!number", "!object", "!boolean"] + .map((token, index) => `"${token}"${arrow} ${NOT_A_LIST[target][index]}`) + .join(", ")}${close}`; -for (const line of table.split("\\n").slice(1)) { - if (line === "") continue; +/** The Go package, the Rust module and the Python module of a utility. */ +const unit = (plan: Plan): string => snake(plan.module.name); - const [fn, rawInput, kind, version, pad, obfuscate, rawExpected] = line.split("\\t"); - const input = unescape(rawInput); - const expected = unescape(rawExpected); - const options: Record = {}; +/** The Ruby module a utility's names live under. */ +const namespaceOf = (plan: Plan): string => `BrazilianUtilsBridge::${pascal(plan.module.name)}`; - if (version !== "") options["version"] = Number(version); - if (pad === "1") options["pad"] = true; - if (obfuscate === "1") options["obfuscate"] = true; +/** The Go spelling of a type, which is a pointer for every record. */ +const goType = (plan: Plan, ty: Ty): string => { + if (ty.k === "named") return `*${unit(plan)}.${ty.name}`; + if (ty.k === "int") return "int64"; + if (ty.k === "bool") return "bool"; - const value = kind === "number" ? Number(input) : input; - const actual = - fn === "isValidCnpj" - ? String(isValidCnpj(value as string, options)) - : formatCnpj(value as string, options); + return "string"; +}; - if (actual === expected) passed++; - else { - failed++; +/** The Rust spelling of a type, always owned: the driver never borrows an answer. */ +const rustType = (plan: Plan, ty: Ty): string => { + if (ty.k === "named") return `${unit(plan)}::${ty.name}`; + if (ty.k === "int") return "i64"; + if (ty.k === "bool") return "bool"; - if (failed <= 5) - console.error(\`FAIL \${fn}(\${JSON.stringify(input)}) expected \${JSON.stringify(expected)} got \${JSON.stringify(actual)}\`); - } -} + return "String"; +}; -console.log(\`typescript: \${passed}/\${passed + failed} conformance checks passed\`); +/** The Java spelling of a type. */ +const javaType = (ty: Ty): string => { + if (ty.k === "named") return ty.name; + if (ty.k === "int") return "long"; + if (ty.k === "bool") return "boolean"; -const dump: string[] = []; + return "String"; +}; -for (const key of readFileSync(resolve(import.meta.dirname, "../../conformance/municipalities.keys.txt"), "utf8").trimEnd().split("\\n")) { - const found = key === "*" ? getMunicipalities() : getMunicipalities(key as StateCode); +/** The C# spelling of a type. */ +const csharpType = (ty: Ty): string => { + if (ty.k === "named") return ty.name; + if (ty.k === "int") return "long"; + if (ty.k === "bool") return "bool"; - dump.push(\`\${key}\\t\${found.length}\`); + return "string"; +}; - for (const municipality of found) - dump.push(\`\${municipality.code}|\${municipality.name}|\${municipality.stateCode}\`); -} +/** The name of the helper that renders one record, unique across modules. */ +const helperName = (plan: Plan, name: string): string => `render${pascal(plan.module.name)}${name}`; -const expectedDump = readFileSync(resolve(import.meta.dirname, "../../conformance/municipalities.expected.txt"), "utf8").trimEnd().split("\\n"); -let dumpFailed = 0; +/** The name of the helper that renders a list of one element type. */ +const listHelperName = (plan: Plan, of: Ty): string => + `renderList${pascal(plan.module.name)}${of.k === "named" ? of.name : pascal(of.k)}`; -for (let index = 0; index < Math.max(dump.length, expectedDump.length); index++) { - if (dump[index] === expectedDump[index]) continue; +/* ------------------------------------------------------------------ TypeScript */ - dumpFailed++; +const typescript = (plans: Plan[]): string => { + const helpers = new Map(); - if (dumpFailed <= 5) - console.error(\`FAIL municipalities line \${index + 1}: expected \${JSON.stringify(expectedDump[index])} got \${JSON.stringify(dump[index])}\`); -} + const render = (plan: Plan, ty: Ty, value: string): string => { + if (ty.k === "bool" || ty.k === "int") return `String(${value})`; + if (ty.k === "opt") return `(${value} === undefined ? "~" : ${render(plan, ty.of, value)})`; -console.log(\`typescript: \${expectedDump.length - dumpFailed}/\${expectedDump.length} municipality lines matched\`); + if (ty.k === "named") { + const struct = plan.module.structs.find((entry) => entry.name === ty.name); + const name = helperName(plan, ty.name); -const NOT_A_LIST: Record = { - "!null": null, - "!string": "viacep", - "!number": 5, - "!object": {}, - "!bool": true, -}; + helpers.set( + name, + `const ${name} = (value: ${ty.name}): string =>\n\t[${(struct?.fields ?? []).map((field) => render(plan, field.ty, `value.${field.name}`)).join(", ")}].join("|");`, + ); -const cepTable = readFileSync(resolve(import.meta.dirname, "../../conformance/cep.expected.tsv"), "utf8") - .trimEnd() - .split("\\n") - .slice(1); -let cepPassed = 0; -let cepFailed = 0; + return `${name}(${value})`; + } -for (const line of cepTable) { - const [rawCep, kind, providers, outcome, detail] = line.split("\\t"); - const value = kind === "number" ? Number(rawCep) : rawCep; - let options: { providers?: CepProvider[] } | undefined; + if (ty.k === "list") { + const name = listHelperName(plan, ty.of); - if (providers === "[]") options = { providers: [] }; - else if (providers.startsWith("!")) options = { providers: NOT_A_LIST[providers] as CepProvider[] }; - else if (providers !== "-") options = { providers: providers.split("|") as CepProvider[] }; + helpers.set( + name, + `const ${name} = (items: readonly unknown[]): string =>\n\t[String(items.length), ...items.map((item) => ${render(plan, ty.of, `(item as ${ty.of.k === "named" ? ty.of.name : "string"})`)})].join("\\n");`, + ); - let actual: string; + return `${name}(${value})`; + } - try { - const found = await getAddressInfoByCep(value, options); + return value; + }; + + const checks = plans.map((plan) => { + const argNames = plan.args.map((_, index) => `argument${index}`); + const reads = plan.args + .map((arg, index) => { + const text = `unescape(parts[${arg.at}])`; + const declared = + arg.ty.k === "scalar" ? "string | number" : arg.ty.k === "enum" ? arg.ty.name : "string"; + const value = `(${ + arg.kind === -1 ? text : `parts[${arg.kind}] === "number" ? Number(${text}) : ${text}` + }) as ${declared}`; + + return arg.set === -1 + ? `\t\tconst ${argNames[index]} = ${value};` + : `\t\tconst ${argNames[index]} = parts[${arg.set}] === "1" ? ${value} : undefined;`; + }) + .join("\n"); + const options = plan.opts + .map((option) => { + const cell = `parts[${option.at}]`; + const value = + option.ty.k === "bool" + ? `${cell} === "1"` + : option.ty.k === "list" + ? `${cell} in NOT_A_LIST ? NOT_A_LIST[${cell}] : ${cell} === "[]" ? [] : ${cell}.split("|")` + : `Number(${cell})`; + + return `\t\tif (${cell} !== "") {\n\t\t\t(options as Record)["${option.name}"] = ${value};\n\t\t\tgiven = true;\n\t\t}`; + }) + .join("\n\n"); + const call = `${plan.entry.name}(${[ + ...argNames, + ...(plan.options === "" ? [] : ["given ? options : undefined"]), + ].join(", ")})`; + + return `/** Replays what \`${plan.entry.name}\` answers. */ +const check${pascal(plan.entry.name)} = async (): Promise => { + const table = readFileSync(resolve(import.meta.dirname, "${tableOf(plan)}"), "utf8"); + const tally: Tally = { passed: 0, failed: 0, skipped: 0 }; + + for (const line of table.split("\\n").slice(1)) { + if (line === "") continue; + + const parts = line.split("\\t"); + + if (!runs(parts[0])) { + tally.skipped++; - actual = \`ok\\t\${found.cep}|\${found.state}|\${found.city}|\${found.neighborhood}|\${found.street}\`; - } catch (error) { - actual = \`error\\t\${(error as Error).name}|\${(error as Error).message}\`; - } + continue; + } - if (actual === \`\${outcome}\\t\${detail}\`) cepPassed++; - else { - cepFailed++; +${reads} +${plan.options === "" ? "" : `\t\tconst options: ${plan.options} = {};\n\t\tlet given = false;\n\n${options}\n`} + let actual: string; - if (cepFailed <= 5) - console.error(\`FAIL cep(\${rawCep}, \${providers}) expected \${outcome}/\${detail} got \${actual.replace("\\t", "/")}\`); + try { + actual = ${render(plan, plan.entry.ret, `${plan.entry.blocking ? "await " : ""}${call}`)}; + } catch (error) { + actual = \`!\${(error as Error).constructor.name}|\${(error as Error).message}\`; + } + + report("${plan.entry.name}", parts, actual, unescape(parts[${plan.expect}]), tally); } -} -console.log(\`typescript: \${cepPassed}/\${cepPassed + cepFailed} CEP cases matched\`); -process.exit(failed === 0 && dumpFailed === 0 && cepFailed === 0 ? 0 : 1); -`, + return tally; +};`; + }); - "out/python/conformance.py": `# Code generated by spec/bridge/conformance/drivers.ts. DO NOT EDIT. -"""Replays the vectors recorded from the JavaScript package against the generated Python.""" + return `// Code generated by spec/bridge/conformance/drivers.ts. DO NOT EDIT. +import { readFileSync } from "node:fs"; +import { resolve } from "node:path"; -import sys -from pathlib import Path +${plans + .map((plan) => { + const types = [ + ...plan.module.structs.filter((entry) => entry.external !== true).map((entry) => entry.name), + ...plan.module.enums.map((entry) => entry.name), + ]; -HERE = Path(__file__).resolve().parent -sys.path.insert(0, str(HERE)) + return `import { ${[plan.entry.name, ...types.map((name) => `type ${name}`)].join(", ")} } from "./_bridge/${plan.module.name}.ts";`; + }) + .join("\n")} -from brutils_bridge.cnpj import ( # noqa: E402 - FormatCnpjOptions, - IsValidCnpjOptions, - format_cnpj, - is_valid_cnpj, -) -from brutils_bridge.municipalities import get_municipalities # noqa: E402 -from brutils_bridge.cep import ( # noqa: E402 - GetAddressInfoByCepOptions, - get_address_info_by_cep, -) +type Tally = { passed: number; failed: number; skipped: number }; +const TARGET = "typescript"; -def unescape(value): - return value.replace("\\\\t", "\\t").replace("\\\\n", "\\n").replace("\\\\\\\\", "\\\\") +const unescape = (value: string): string => + value.replaceAll("\\\\t", "\\t").replaceAll("\\\\n", "\\n").replaceAll("\\\\\\\\", "\\\\"); +/** Whether this target can express the call a row describes. */ +const runs = (targets: string): boolean => targets === "*" || targets.split("|").includes(TARGET); -passed = 0 -failed = 0 +/** The values a declared type does not allow, which only a run time check can still catch. */ +const NOT_A_LIST: Record = ${notAList("typescript", "{ ", " }", ":")}; -with (HERE.parent.parent / "conformance/vectors.tsv").open(encoding="utf-8") as handle: - next(handle) +const report = (fn: string, parts: string[], actual: string, expected: string, tally: Tally): void => { + if (actual === expected) { + tally.passed++; - for line in handle: - if line.strip("\\n") == "": - continue + return; + } - fn, raw_input, kind, version, pad, obfuscate, raw_expected = line.rstrip("\\n").split("\\t") - value = unescape(raw_input) - expected = unescape(raw_expected) - number = float(value) if kind == "number" else None + tally.failed++; - if kind == "number": - value = int(number) if number.is_integer() else number + if (tally.failed <= 3) + console.error(\`FAIL \${fn}(\${parts.slice(1, -1).join(", ")}) expected \${JSON.stringify(expected.slice(0, 120))} got \${JSON.stringify(actual.slice(0, 120))}\`); +}; - if fn == "isValidCnpj": - options = IsValidCnpjOptions(version=int(version) if version else None) - actual = str(is_valid_cnpj(value, options)).lower() - else: - options = FormatCnpjOptions( - version=int(version) if version else None, - pad=True if pad == "1" else None, - obfuscate=True if obfuscate == "1" else None, - ) - actual = format_cnpj(value, options) +${[...helpers.values()].join("\n\n")} - if actual == expected: - passed += 1 - else: - failed += 1 +${checks.join("\n\n")} - if failed <= 5: - print(f"FAIL {fn}({value!r}) expected {expected!r} got {actual!r}", file=sys.stderr) +let failed = 0; -print(f"python: {passed}/{passed + failed} conformance checks passed") +const announce = (name: string, tally: Tally): void => { + failed += tally.failed; -CONFORMANCE = HERE.parent.parent / "conformance" -dump = [] + console.log( + \`\${TARGET}: \${name} \${tally.passed}/\${tally.passed + tally.failed} matched\${tally.skipped === 0 ? "" : \` (\${tally.skipped} not expressible)\`}\`, + ); +}; -for key in (CONFORMANCE / "municipalities.keys.txt").read_text(encoding="utf-8").rstrip("\\n").split("\\n"): - found = get_municipalities(None) if key == "*" else get_municipalities(key) - dump.append(f"{key}\\t{len(found)}") +${plans.map((plan) => `announce("${plan.entry.name}", await check${pascal(plan.entry.name)}());`).join("\n")} - for municipality in found: - dump.append(f"{municipality.code}|{municipality.name}|{municipality.state_code}") +if (failed > 0) process.exit(1); +`; +}; -expected_dump = ( - (CONFORMANCE / "municipalities.expected.txt").read_text(encoding="utf-8").rstrip("\\n").split("\\n") -) -dump_failed = 0 +/* ---------------------------------------------------------------------- Python */ -for index in range(max(len(dump), len(expected_dump))): - got = dump[index] if index < len(dump) else None - want = expected_dump[index] if index < len(expected_dump) else None +const python = (plans: Plan[]): string => { + const helpers = new Map(); - if got == want: - continue + const render = (plan: Plan, ty: Ty, value: string): string => { + if (ty.k === "bool") return `("true" if ${value} else "false")`; + if (ty.k === "int") return `str(${value})`; + if (ty.k === "opt") return `("~" if ${value} is None else ${render(plan, ty.of, value)})`; - dump_failed += 1 + if (ty.k === "named") { + const name = helperName(plan, ty.name); + const struct = plan.module.structs.find((entry) => entry.name === ty.name); - if dump_failed <= 5: - print(f"FAIL municipalities line {index + 1}: expected {want!r} got {got!r}", file=sys.stderr) + helpers.set( + name, + `def ${name}(value):\n return "|".join([${(struct?.fields ?? []).map((field) => render(plan, field.ty, `value.${snake(field.name)}`)).join(", ")}])`, + ); -print(f"python: {len(expected_dump) - dump_failed}/{len(expected_dump)} municipality lines matched") + return `${name}(${value})`; + } -NOT_A_LIST = {"!null": None, "!string": "viacep", "!number": 5, "!object": {}, "!bool": True} -cep_passed = 0 -cep_failed = 0 -cep_skipped = 0 + if (ty.k === "list") { + const name = listHelperName(plan, ty.of); -for line in (CONFORMANCE / "cep.expected.tsv").read_text(encoding="utf-8").rstrip("\\n").split("\\n")[1:]: - raw_cep, kind, providers, outcome, detail = line.split("\\t") + helpers.set( + name, + `def ${name}(items):\n return "\\n".join([str(len(items))] + [${render(plan, ty.of, "item")} for item in items])`, + ); - # Python's None is both "absent" and "null", so a null providers option cannot be written. - if providers == "!null": - cep_skipped += 1 - continue + return `${name}(${value})`; + } - value = int(raw_cep) if kind == "number" else raw_cep - options = None + return value; + }; + + const checks = plans.map((plan) => { + const argNames = plan.args.map((_, index) => `argument${index}`); + const reads = plan.args + .map((arg, index) => { + const text = `unescape(parts[${arg.at}])`; + const value = + arg.kind === -1 ? text : `(int(${text}) if parts[${arg.kind}] == "number" else ${text})`; + + return arg.set === -1 + ? ` ${argNames[index]} = ${value}` + : ` ${argNames[index]} = ${value} if parts[${arg.set}] == "1" else None`; + }) + .join("\n"); + const options = plan.opts + .map((option) => { + const cell = `parts[${option.at}]`; + const value = + option.ty.k === "bool" + ? `${cell} == "1"` + : option.ty.k === "list" + ? `NOT_A_LIST[${cell}] if ${cell} in NOT_A_LIST else ([] if ${cell} == "[]" else ${cell}.split("|"))` + : `int(${cell})`; + + return ` if ${cell} != "":\n options.${snake(option.name)} = ${value}\n given = True`; + }) + .join("\n"); + const call = `bridge.${snake(plan.entry.name)}(${[...argNames, ...(plan.options === "" ? [] : ["options if given else None"])].join(", ")})`; + + return `def check_${snake(plan.entry.name)}(): + """Replays what \`${plan.entry.name}\` answers.""" + tally = [0, 0, 0] + + with open("${tableOf(plan)}", encoding="utf-8") as handle: + rows = handle.read().split("\\n")[1:] + + for line in rows: + if line == "": + continue - if providers == "[]": - options = GetAddressInfoByCepOptions(providers=[]) - elif providers.startswith("!"): - options = GetAddressInfoByCepOptions(providers=NOT_A_LIST[providers]) - elif providers != "-": - options = GetAddressInfoByCepOptions(providers=providers.split("|")) + parts = line.split("\\t") - try: - found = get_address_info_by_cep(value, options) - actual = "ok\\t" + "|".join([found.cep, found.state, found.city, found.neighborhood, found.street]) - except Exception as error: # noqa: BLE001 - actual = f"error\\t{type(error).__name__}|{error}" + if not runs(parts[0]): + tally[2] += 1 - if actual == f"{outcome}\\t{detail}": - cep_passed += 1 - else: - cep_failed += 1 + continue - if cep_failed <= 5: - print(f"FAIL cep({raw_cep}, {providers}) expected {outcome}/{detail} got {actual}", file=sys.stderr) +${reads} +${plan.options === "" ? "" : ` options = bridge.${plan.options}()\n given = False\n\n${options}\n`} + try: + actual = ${render(plan, plan.entry.ret, call)} + except Exception as error: # noqa: BLE001 + actual = "!" + type(error).__name__ + "|" + str(error) -print(f"python: {cep_passed}/{cep_passed + cep_failed} CEP cases matched ({cep_skipped} not expressible)") -sys.exit(0 if failed == 0 and dump_failed == 0 and cep_failed == 0 else 1) -`, + report("${plan.entry.name}", actual, unescape(parts[${plan.expect}]), tally) - "out/go/conformance/main.go": `// Code generated by spec/bridge/conformance/drivers.ts. DO NOT EDIT. + return tally`; + }); -package main + return `# Code generated by spec/bridge/conformance/drivers.ts. DO NOT EDIT. +"""Replays the recorded tables against the generated Python.""" -import ( - "bufio" - "errors" - "fmt" - "os" - "strconv" - "strings" - - "brazilianutils/bridge/cep" - "brazilianutils/bridge/cnpj" - "brazilianutils/bridge/municipalities" - "brazilianutils/bridge/runtime" -) +import sys -func unescape(value string) string { - value = strings.ReplaceAll(value, "\\\\t", "\\t") - value = strings.ReplaceAll(value, "\\\\n", "\\n") +import brutils_bridge as bridge - return strings.ReplaceAll(value, "\\\\\\\\", "\\\\") -} +TARGET = "python" -func intPtr(value int64) *int64 { return &value } -func boolPtr(value bool) *bool { return &value } +NOT_A_LIST = ${notAList("python", "{", "}", ":")} -func main() { - file, err := os.Open("../../conformance/vectors.tsv") - if err != nil { - panic(err) - } +def unescape(value): + """Reads back the three characters the table format escapes.""" + return value.replace("\\\\t", "\\t").replace("\\\\n", "\\n").replace("\\\\\\\\", "\\\\") - defer file.Close() - scanner := bufio.NewScanner(file) - scanner.Buffer(make([]byte, 1024*1024), 1024*1024) - scanner.Scan() +def runs(targets): + """Whether this target can express the call a row describes.""" + return targets == "*" or TARGET in targets.split("|") - passed := 0 - failed := 0 - skipped := 0 - for scanner.Scan() { - line := scanner.Text() +def report(fn, actual, expected, tally): + """Counts one comparison, and shows the first few that disagree.""" + if actual == expected: + tally[0] += 1 - if line == "" { - continue - } + return - parts := strings.Split(line, "\\t") - fn, input, kind, version, pad, obfuscate, expected := parts[0], unescape(parts[1]), parts[2], parts[3], parts[4], parts[5], unescape(parts[6]) + tally[1] += 1 - // A number input to a validator cannot be written in Go: the parameter is a string, so - // the JavaScript quirk "a number is never a valid CNPJ" has no Go equivalent. - if kind == "number" && fn == "isValidCnpj" { - skipped++ + if tally[1] <= 3: + print(f"FAIL {fn} expected {expected[:120]!r} got {actual[:120]!r}", file=sys.stderr) - continue - } - var actual string +${[...helpers.values()].join("\n\n\n")} - if fn == "isValidCnpj" { - options := &cnpj.IsValidCnpjOptions{} - if version != "" { - parsed, _ := strconv.ParseInt(version, 10, 64) - options.Version = intPtr(parsed) - } +${checks.join("\n\n\n")} - actual = strconv.FormatBool(cnpj.IsValidCnpj(input, options)) - } else { - options := &cnpj.FormatCnpjOptions{} - if version != "" { - parsed, _ := strconv.ParseInt(version, 10, 64) - options.Version = intPtr(parsed) - } +FAILED = 0 - if pad == "1" { - options.Pad = boolPtr(true) - } +${plans + .map( + (plan) => `TALLY = check_${snake(plan.entry.name)}() +FAILED += TALLY[1] +print( + f"{TARGET}: ${plan.entry.name} {TALLY[0]}/{TALLY[0] + TALLY[1]} matched" + + ("" if TALLY[2] == 0 else f" ({TALLY[2]} not expressible)") +)`, + ) + .join("\n\n")} - if obfuscate == "1" { - options.Obfuscate = boolPtr(true) - } +if FAILED > 0: + sys.exit(1) +`; +}; + +/* ------------------------------------------------------------------------ Ruby */ + +const ruby = (plans: Plan[]): string => { + const helpers = new Map(); + + const render = (plan: Plan, ty: Ty, value: string): string => { + if (ty.k === "bool") return `(${value} ? 'true' : 'false')`; + if (ty.k === "int") return `${value}.to_s`; + if (ty.k === "opt") return `(${value}.nil? ? '~' : ${render(plan, ty.of, value)})`; - actual = cnpj.FormatCnpj(input, options) + if (ty.k === "named") { + const name = snake(helperName(plan, ty.name)); + const struct = plan.module.structs.find((entry) => entry.name === ty.name); + + helpers.set( + name, + `def ${name}(value)\n [${(struct?.fields ?? []).map((field) => render(plan, field.ty, `value.${snake(field.name)}`)).join(", ")}].join('|')\nend`, + ); + + return `${name}(${value})`; } - if actual == expected { - passed++ - } else { - failed++ + if (ty.k === "list") { + const name = snake(listHelperName(plan, ty.of)); - if failed <= 5 { - fmt.Fprintf(os.Stderr, "FAIL %s(%q) expected %q got %q\\n", fn, input, expected, actual) - } + helpers.set( + name, + `def ${name}(items)\n ([items.length.to_s] + items.map { |item| ${render(plan, ty.of, "item")} }).join("\\n")\nend`, + ); + + return `${name}(${value})`; } - } - fmt.Printf("go: %d/%d conformance checks passed (%d not expressible)\\n", passed, passed+failed, skipped) + return value; + }; + + const checks = plans.map((plan) => { + const argNames = plan.args.map((_, index) => `argument#{""}${index}`.replace('#{""}', "")); + const reads = plan.args + .map((arg, index) => { + const text = `unescape(parts[${arg.at}])`; + const value = + arg.kind === -1 ? text : `(parts[${arg.kind}] == 'number' ? ${text}.to_i : ${text})`; + + return arg.set === -1 + ? ` ${argNames[index]} = ${value}` + : ` ${argNames[index]} = parts[${arg.set}] == '1' ? ${value} : nil`; + }) + .join("\n"); + const options = plan.opts + .map((option) => { + const cell = `parts[${option.at}]`; + const value = + option.ty.k === "bool" + ? `${cell} == '1'` + : option.ty.k === "list" + ? `NOT_A_LIST.key?(${cell}) ? NOT_A_LIST[${cell}] : (${cell} == '[]' ? [] : ${cell}.split('|'))` + : `${cell}.to_i`; + + return ` unless ${cell}.empty?\n options.${snake(option.name)} = ${value}\n given = true\n end`; + }) + .join("\n\n"); + const call = `${namespaceOf(plan)}.${snake(plan.entry.name)}(${[...argNames, ...(plan.options === "" ? [] : ["given ? options : nil"])].join(", ")})`; + + return `# Replays what \`${plan.entry.name}\` answers. +def check_${snake(plan.entry.name)} + tally = [0, 0, 0] + + File.read('${tableOf(plan)}', encoding: 'UTF-8').split("\\n").drop(1).each do |line| + next if line.empty? + + parts = line.split("\\t", -1) + + unless runs(parts[0]) + tally[2] += 1 + + next + end - keys, err := os.ReadFile("../../conformance/municipalities.keys.txt") +${reads} +${plan.options === "" ? "" : ` options = ${namespaceOf(plan)}::${plan.options}.new\n given = false\n\n${options}\n`} + begin + actual = ${render(plan, plan.entry.ret, call)} + rescue StandardError => e + actual = "!#{e.class.name.split('::').last}|#{e.message}" + end - if err != nil { - panic(err) - } + report('${plan.entry.name}', actual, unescape(parts[${plan.expect}]), tally) + end - dump := []string{} + tally +end`; + }); - for _, key := range strings.Split(strings.TrimRight(string(keys), "\\n"), "\\n") { - var found []*municipalities.Municipality + return `# frozen_string_literal: true - if key == "*" { - found = municipalities.GetMunicipalities(nil) - } else { - asked := key - found = municipalities.GetMunicipalities(&asked) - } +# Code generated by spec/bridge/conformance/drivers.ts. DO NOT EDIT. - dump = append(dump, fmt.Sprintf("%s\\t%d", key, len(found))) +${plans.map((plan) => `require_relative 'lib/brazilian_utils_bridge/${snake(plan.module.name)}'`).join("\n")} - for _, municipality := range found { - dump = append(dump, fmt.Sprintf("%s|%s|%s", municipality.Code, municipality.Name, municipality.StateCode)) - } - } +TARGET = 'ruby' - raw, err := os.ReadFile("../../conformance/municipalities.expected.txt") +NOT_A_LIST = ${notAList("ruby", "{ ", " }", " =>")}.freeze - if err != nil { - panic(err) - } +# Reads back the three characters the table format escapes. +def unescape(value) + value.gsub('\\\\t', "\\t").gsub('\\\\n', "\\n").gsub('\\\\\\\\', '\\\\') +end - expectedDump := strings.Split(strings.TrimRight(string(raw), "\\n"), "\\n") - dumpFailed := 0 - longest := len(dump) +# Whether this target can express the call a row describes. +def runs(targets) + targets == '*' || targets.split('|').include?(TARGET) +end - if len(expectedDump) > longest { - longest = len(expectedDump) - } +# Counts one comparison, and shows the first few that disagree. +def report(fn, actual, expected, tally) + if actual == expected + tally[0] += 1 - for index := 0; index < longest; index++ { - got := "" - want := "" + return + end - if index < len(dump) { - got = dump[index] - } + tally[1] += 1 - if index < len(expectedDump) { - want = expectedDump[index] - } + warn("FAIL #{fn} expected #{expected[0, 120].inspect} got #{actual[0, 120].inspect}") if tally[1] <= 3 +end - if got == want { - continue - } +${[...helpers.values()].join("\n\n")} - dumpFailed++ +${checks.join("\n\n")} - if dumpFailed <= 5 { - fmt.Fprintf(os.Stderr, "FAIL municipalities line %d: expected %q got %q\\n", index+1, want, got) - } - } +failed = 0 - fmt.Printf("go: %d/%d municipality lines matched\\n", len(expectedDump)-dumpFailed, len(expectedDump)) +${plans + .map( + (plan) => `tally = check_${snake(plan.entry.name)} +failed += tally[1] +puts("#{TARGET}: ${plan.entry.name} #{tally[0]}/#{tally[0] + tally[1]} matched" + + (tally[2].zero? ? '' : " (#{tally[2]} not expressible)"))`, + ) + .join("\n\n")} + +exit(1) if failed.positive? +`; +}; - cepRaw, err := os.ReadFile("../../conformance/cep.expected.tsv") +/* -------------------------------------------------------------------------- Go */ - if err != nil { - panic(err) - } +const go = (plans: Plan[]): string => { + const helpers = new Map(); + const raises = plans.some((plan) => plan.entry.throws); - cepPassed := 0 - cepFailed := 0 - cepSkipped := 0 + const render = (plan: Plan, ty: Ty, value: string): string => { + if (ty.k === "bool") return `strconv.FormatBool(${value})`; + if (ty.k === "int") return `strconv.FormatInt(${value}, 10)`; - for _, line := range strings.Split(strings.TrimRight(string(cepRaw), "\\n"), "\\n")[1:] { - parts := strings.Split(line, "\\t") - rawCep, kind, providers, outcome, detail := parts[0], parts[1], parts[2], parts[3], parts[4] + if (ty.k === "named") { + const name = helperName(plan, ty.name); + const struct = plan.module.structs.find((entry) => entry.name === ty.name); - // A number input and a providers option that is not a list have no Go form. - if kind == "number" || strings.HasPrefix(providers, "!") { - cepSkipped++ + helpers.set( + name, + `func ${name}(value ${goType(plan, ty)}) string {\n\treturn ${(struct?.fields ?? []).map((field) => render(plan, field.ty, `value.${pascal(field.name)}`)).join(' + "|" + ')}\n}`, + ); - continue + return `${name}(${value})`; } - var options *cep.GetAddressInfoByCepOptions + if (ty.k === "list") { + const name = listHelperName(plan, ty.of); - if providers != "-" { - named := []string{} + helpers.set( + name, + `func ${name}(items []${goType(plan, ty.of)}) string {\n\tout := strconv.Itoa(len(items))\n\n\tfor _, item := range items {\n\t\tout += "\\n" + ${render(plan, ty.of, "item")}\n\t}\n\n\treturn out\n}`, + ); - if providers != "[]" { - named = strings.Split(providers, "|") - } - - options = &cep.GetAddressInfoByCepOptions{Providers: &named} + return `${name}(${value})`; } - found, err := cep.GetAddressInfoByCep(rawCep, options) + return value; + }; + + const checks = plans.map((plan) => { + const argNames = plan.args.map((_, index) => `argument${index}`); + const reads = plan.args + .map((arg, index) => { + const text = `unescape(parts[${arg.at}])`; + + return arg.set === -1 + ? `\t\t${argNames[index]} := ${text}` + : `\t\tvar ${argNames[index]} *string\n\n\t\tif parts[${arg.set}] == "1" {\n\t\t\tgiven := ${text}\n\t\t\t${argNames[index]} = &given\n\t\t}`; + }) + .join("\n\n"); + const options = plan.opts + .map((option) => { + const cell = `parts[${option.at}]`; + const value = + option.ty.k === "bool" + ? `${cell} == "1"` + : option.ty.k === "list" + ? `${cell} == "[]" ? nil : strings.Split(${cell}, "|")` + : `mustParse(${cell})`; + const assign = + option.ty.k === "list" + ? `\t\t\tnamed := []string{}\n\n\t\t\tif ${cell} != "[]" {\n\t\t\t\tnamed = strings.Split(${cell}, "|")\n\t\t\t}\n\n\t\t\toptions.${pascal(option.name)} = &named` + : `\t\t\tvalue := ${value}\n\t\t\toptions.${pascal(option.name)} = &value`; + + return `\t\tif ${cell} != "" {\n${assign}\n\t\t\tgiven = true\n\t\t}`; + }) + .join("\n\n"); + const call = `${unit(plan)}.${pascal(plan.entry.name)}(${[...argNames, ...(plan.options === "" ? [] : ["chosen"])].join(", ")})`; + const body = plan.entry.throws + ? `\t\tfound, err := ${call} actual := "" if err == nil { - actual = fmt.Sprintf("ok\\t%s|%s|%s|%s|%s", found.Cep, found.State, found.City, found.Neighborhood, found.Street) + actual = ${render(plan, plan.entry.ret, "found")} } else { - kindName := "" + kind := "" var raised *runtime.Error if errors.As(err, &raised) { - kindName = raised.Kind() + kind = raised.Kind() } - actual = fmt.Sprintf("error\\t%s|%s", kindName, err.Error()) - } + actual = "!" + kind + "|" + err.Error() + }` + : `\t\tactual := ${render(plan, plan.entry.ret, call)}`; - if actual == outcome+"\\t"+detail { - cepPassed++ - } else { - cepFailed++ + return `// check${pascal(plan.entry.name)} replays what ${plan.entry.name} answers. +func check${pascal(plan.entry.name)}() tally { + raw, err := os.ReadFile("${tableOf(plan)}") - if cepFailed <= 5 { - fmt.Fprintf(os.Stderr, "FAIL cep(%s, %s) expected %s/%s got %s\\n", rawCep, providers, outcome, detail, actual) - } - } + if err != nil { + panic(err) } - fmt.Printf("go: %d/%d CEP cases matched (%d not expressible)\\n", cepPassed, cepPassed+cepFailed, cepSkipped) + counts := tally{} - if failed > 0 || dumpFailed > 0 || cepFailed > 0 { - os.Exit(1) - } -} -`, + for _, line := range strings.Split(strings.TrimRight(string(raw), "\\n"), "\\n")[1:] { + if line == "" { + continue + } - "out/rust/src/bin/conformance.rs": `// Code generated by spec/bridge/conformance/drivers.ts. DO NOT EDIT. + parts := strings.Split(line, "\\t") -use brazilian_utils_bridge::cnpj; -use brazilian_utils_bridge::cep; -use brazilian_utils_bridge::municipalities; + if !runs(parts[0]) { + counts.skipped++ -fn unescape(value: &str) -> String { - value.replace("\\\\t", "\\t").replace("\\\\n", "\\n").replace("\\\\\\\\", "\\\\") + continue + } + +${reads} +${ + plan.options === "" + ? "" + : `\t\toptions := &${unit(plan)}.${plan.options}{}\n\t\tgiven := false\n\n${options}\n\n\t\tvar chosen *${unit(plan)}.${plan.options}\n\n\t\tif given {\n\t\t\tchosen = options\n\t\t}\n` } +${body} -fn main() { - let table = std::fs::read_to_string("../../conformance/vectors.tsv").expect("vectors"); - let mut passed = 0; - let mut failed = 0; - let mut skipped = 0; + report("${plan.entry.name}", actual, unescape(parts[${plan.expect}]), &counts) + } - for line in table.lines().skip(1) { - if line.is_empty() { - continue; - } + return counts +}`; + }); - let parts: Vec<&str> = line.split('\\t').collect(); - let (fn_name, input, kind) = (parts[0], unescape(parts[1]), parts[2]); - let (version, pad, obfuscate, expected) = (parts[3], parts[4], parts[5], unescape(parts[6])); + return `// Code generated by spec/bridge/conformance/drivers.ts. DO NOT EDIT. - // A number input to a validator cannot be written in Rust: the parameter is a \`&str\`. - if kind == "number" && fn_name == "isValidCnpj" { - skipped += 1; +// Command conformance replays the recorded tables against the generated Go. +package main - continue; - } +import ( +${[ + ...(raises ? ['\t"errors"'] : []), + '\t"fmt"', + '\t"os"', + '\t"strconv"', + '\t"strings"', + "", + ...plans.map((plan) => `\t"brazilianutils/bridge/${unit(plan)}"`), + ...(raises ? ['\t"brazilianutils/bridge/runtime"'] : []), +].join("\n")} +) - let actual = if fn_name == "isValidCnpj" { - let options = cnpj::IsValidCnpjOptions { - version: if version.is_empty() { None } else { Some(version.parse().unwrap()) }, - }; - - cnpj::is_valid_cnpj(&input, Some(&options)).to_string() - } else { - let options = cnpj::FormatCnpjOptions { - version: if version.is_empty() { None } else { Some(version.parse().unwrap()) }, - pad: if pad == "1" { Some(true) } else { None }, - obfuscate: if obfuscate == "1" { Some(true) } else { None }, - }; - - cnpj::format_cnpj(&input, Some(&options)) - }; - - if actual == expected { - passed += 1; - } else { - failed += 1; - - if failed <= 5 { - eprintln!("FAIL {}({:?}) expected {:?} got {:?}", fn_name, input, expected, actual); - } - } - } +const target = "go" - println!("rust: {}/{} conformance checks passed ({} not expressible)", passed, passed + failed, skipped); +type tally struct{ passed, failed, skipped int } - let keys = std::fs::read_to_string("../../conformance/municipalities.keys.txt").expect("keys"); - let mut dump: Vec = Vec::new(); +// unescape reads back the three characters the table format escapes. +func unescape(value string) string { + value = strings.ReplaceAll(value, "\\\\t", "\\t") + value = strings.ReplaceAll(value, "\\\\n", "\\n") - for key in keys.trim_end_matches('\\n').split('\\n') { - let found = if key == "*" { - municipalities::get_municipalities(None) - } else { - municipalities::get_municipalities(Some(key)) - }; + return strings.ReplaceAll(value, "\\\\\\\\", "\\\\") +} - dump.push(format!("{}\\t{}", key, found.len())); +// runs reports whether this target can express the call a row describes. +func runs(targets string) bool { + if targets == "*" { + return true + } - for municipality in &found { - dump.push(format!("{}|{}|{}", municipality.code, municipality.name, municipality.state_code)); - } - } + for _, name := range strings.Split(targets, "|") { + if name == target { + return true + } + } - let raw = std::fs::read_to_string("../../conformance/municipalities.expected.txt").expect("dump"); - let expected_dump: Vec<&str> = raw.trim_end_matches('\\n').split('\\n').collect(); - let mut dump_failed = 0; + return false +} - for index in 0..std::cmp::max(dump.len(), expected_dump.len()) { - let got = dump.get(index).map(String::as_str).unwrap_or(""); - let want = *expected_dump.get(index).unwrap_or(&""); +// mustParse reads a number the recorder wrote, which is never malformed. +func mustParse(value string) int64 { + parsed, err := strconv.ParseInt(value, 10, 64) - if got == want { - continue; - } + if err != nil { + panic(err) + } - dump_failed += 1; + return parsed +} - if dump_failed <= 5 { - eprintln!("FAIL municipalities line {}: expected {:?} got {:?}", index + 1, want, got); - } - } +// report counts one comparison, and shows the first few that disagree. +func report(fn string, actual string, expected string, counts *tally) { + if actual == expected { + counts.passed++ - println!("rust: {}/{} municipality lines matched", expected_dump.len() - dump_failed, expected_dump.len()); + return + } - let cep_raw = std::fs::read_to_string("../../conformance/cep.expected.tsv").expect("cep"); - let mut cep_passed = 0; - let mut cep_failed = 0; - let mut cep_skipped = 0; + counts.failed++ - for line in cep_raw.trim_end_matches('\\n').split('\\n').skip(1) { - let parts: Vec<&str> = line.split('\\t').collect(); - let (raw_cep, kind, providers, outcome, detail) = (parts[0], parts[1], parts[2], parts[3], parts[4]); + if counts.failed <= 3 { + fmt.Fprintf(os.Stderr, "FAIL %s expected %q got %q\\n", fn, cut(expected), cut(actual)) + } +} - // A number input and a providers option that is not a list have no Rust form. - if kind == "number" || providers.starts_with('!') { - cep_skipped += 1; +// cut keeps a failure message readable when the answer is a five thousand row list. +func cut(value string) string { + if len(value) <= 120 { + return value + } - continue; - } + return value[:120] +} - let options = if providers == "-" { - None - } else { - let named: Vec = if providers == "[]" { - Vec::new() - } else { - providers.split('|').map(str::to_string).collect() - }; - - Some(cep::GetAddressInfoByCepOptions { providers: Some(named) }) - }; - - let actual = match cep::get_address_info_by_cep(raw_cep, options.as_ref()) { - Ok(found) => format!( - "ok\\t{}|{}|{}|{}|{}", - found.cep, found.state, found.city, found.neighborhood, found.street - ), - Err(error) => format!("error\\t{}|{}", error.kind(), error.message), - }; - - if actual == format!("{}\\t{}", outcome, detail) { - cep_passed += 1; - } else { - cep_failed += 1; - - if cep_failed <= 5 { - eprintln!("FAIL cep({}, {}) expected {}/{} got {}", raw_cep, providers, outcome, detail, actual); - } - } - } +${[...helpers.values()].join("\n\n")} - println!("rust: {}/{} CEP cases matched ({} not expressible)", cep_passed, cep_passed + cep_failed, cep_skipped); +${checks.join("\n\n")} - if failed > 0 || dump_failed > 0 || cep_failed > 0 { - std::process::exit(1); - } +func main() { + failed := 0 + +${plans + .map( + (plan) => `\tcounts${pascal(plan.entry.name)} := check${pascal(plan.entry.name)}() + failed += counts${pascal(plan.entry.name)}.failed + + fmt.Printf("%s: ${plan.entry.name} %d/%d matched%s\\n", target, counts${pascal(plan.entry.name)}.passed, counts${pascal(plan.entry.name)}.passed+counts${pascal(plan.entry.name)}.failed, note(counts${pascal(plan.entry.name)}.skipped))`, + ) + .join("\n\n")} + + if failed > 0 { + os.Exit(1) + } } -`, - "out/ruby/conformance.rb": `# frozen_string_literal: true -# Code generated by spec/bridge/conformance/drivers.ts. DO NOT EDIT. +// note names how many rows this target could not be handed. +func note(skipped int) string { + if skipped == 0 { + return "" + } -require_relative 'lib/brazilian_utils_bridge/cnpj' -require_relative 'lib/brazilian_utils_bridge/municipalities' -require_relative 'lib/brazilian_utils_bridge/cep' + return fmt.Sprintf(" (%d not expressible)", skipped) +} +`; +}; -def unescape(value) - value.gsub('\\\\t', "\\t").gsub('\\\\n', "\\n").gsub('\\\\\\\\', '\\\\') -end +/* ------------------------------------------------------------------------ Rust */ -passed = 0 -failed = 0 +const rust = (plans: Plan[]): string => { + const helpers = new Map(); -lines = File.readlines(File.expand_path('../../conformance/vectors.tsv', __dir__), encoding: 'UTF-8') - -lines.drop(1).each do |line| - next if line.strip.empty? - - fn, raw_input, kind, version, pad, obfuscate, raw_expected = line.chomp("\\n").split("\\t", -1) - value = unescape(raw_input) - expected = unescape(raw_expected) - value = value.to_i if kind == 'number' - - actual = - if fn == 'isValidCnpj' - options = BrazilianUtilsBridge::Cnpj::IsValidCnpjOptions.new( - version: version.empty? ? nil : version.to_i - ) - BrazilianUtilsBridge::Cnpj.is_valid_cnpj(value, options).to_s - else - options = BrazilianUtilsBridge::Cnpj::FormatCnpjOptions.new( - version: version.empty? ? nil : version.to_i, - pad: pad == '1' ? true : nil, - obfuscate: obfuscate == '1' ? true : nil - ) - BrazilianUtilsBridge::Cnpj.format_cnpj(value, options) - end + const render = (plan: Plan, ty: Ty, value: string): string => { + if (ty.k === "bool" || ty.k === "int") return `${value}.to_string()`; - if actual == expected - passed += 1 - else - failed += 1 - warn "FAIL #{fn}(#{value.inspect}) expected #{expected.inspect} got #{actual.inspect}" if failed <= 5 - end -end + if (ty.k === "named") { + const name = snake(helperName(plan, ty.name)); + const struct = plan.module.structs.find((entry) => entry.name === ty.name); + const fields = struct?.fields ?? []; -puts "ruby: #{passed}/#{passed + failed} conformance checks passed" + helpers.set( + name, + `fn ${name}(value: &${rustType(plan, ty)}) -> String {\n format!("${fields.map(() => "{}").join("|")}", ${fields.map((field) => render(plan, field.ty, `value.${snake(field.name)}`)).join(", ")})\n}`, + ); -conformance = File.expand_path('../../conformance', __dir__) -keys = File.read(File.join(conformance, 'municipalities.keys.txt'), encoding: 'UTF-8') -dump = [] + return `${name}(&${value})`; + } -keys.chomp("\n").split("\n", -1).each do |key| - found = - if key == '*' - BrazilianUtilsBridge::Municipalities.get_municipalities(nil) - else - BrazilianUtilsBridge::Municipalities.get_municipalities(key) - end + if (ty.k === "list") { + const name = snake(listHelperName(plan, ty.of)); - dump.push("#{key}\t#{found.length}") - found.each { |m| dump.push("#{m.code}|#{m.name}|#{m.state_code}") } -end + helpers.set( + name, + `fn ${name}(items: &[${rustType(plan, ty.of)}]) -> String {\n let mut out = items.len().to_string();\n\n for item in items {\n out.push('\\n');\n out.push_str(&${render(plan, ty.of, "item.clone()")});\n }\n\n out\n}`, + ); -expected_dump = File.read(File.join(conformance, 'municipalities.expected.txt'), encoding: 'UTF-8') - .chomp("\n").split("\n", -1) -dump_failed = 0 + return `${name}(&${value})`; + } -[dump.length, expected_dump.length].max.times do |index| - next if dump[index] == expected_dump[index] + return `${value}.to_string()`; + }; + + const checks = plans.map((plan) => { + const argNames = plan.args.map((_, index) => `argument${index}`); + const reads = plan.args + .map((arg, index) => { + const text = `unescape(parts[${arg.at}])`; + + return arg.set === -1 + ? ` let ${argNames[index]} = ${text};` + : ` let ${argNames[index]} = if parts[${arg.set}] == "1" { Some(${text}) } else { None };`; + }) + .join("\n"); + const passed = plan.args.map((arg, index) => + arg.set === -1 ? `${argNames[index]}.as_str()` : `${argNames[index]}.as_deref()`, + ); + const options = plan.opts + .map((option) => { + const cell = `parts[${option.at}]`; + const value = + option.ty.k === "bool" + ? `${cell} == "1"` + : option.ty.k === "list" + ? `if ${cell} == "[]" { Vec::new() } else { ${cell}.split('|').map(str::to_string).collect() }` + : `${cell}.parse().expect("a number")`; + + return ` if !${cell}.is_empty() {\n options.${snake(option.name)} = Some(${value});\n given = true;\n }`; + }) + .join("\n\n"); + const call = `${unit(plan)}::${snake(plan.entry.name)}(${[...passed, ...(plan.options === "" ? [] : ["if given { Some(&options) } else { None }"])].join(", ")})`; + const body = plan.entry.throws + ? ` let actual = match ${call} {\n Ok(found) => ${render(plan, plan.entry.ret, "found")},\n Err(error) => format!("!{}|{}", error.kind(), error.message),\n };` + : ` let actual = ${render(plan, plan.entry.ret, call)};`; + + return `/// Replays what \`${plan.entry.name}\` answers. +fn check_${snake(plan.entry.name)}() -> Tally { + let table = std::fs::read_to_string("${tableOf(plan)}").expect("the recorded table"); + let mut counts = Tally::default(); - dump_failed += 1 - warn "FAIL municipalities line #{index + 1}: expected #{expected_dump[index].inspect} got #{dump[index].inspect}" if dump_failed <= 5 -end + for line in table.lines().skip(1) { + if line.is_empty() { + continue; + } -puts "ruby: #{expected_dump.length - dump_failed}/#{expected_dump.length} municipality lines matched" + let parts: Vec<&str> = line.split('\\t').collect(); -NOT_A_LIST = { '!string' => 'viacep', '!number' => 5, '!object' => {}, '!bool' => true }.freeze -cep_passed = 0 -cep_failed = 0 -cep_skipped = 0 -Cep = BrazilianUtilsBridge::Cep + if !runs(parts[0]) { + counts.skipped += 1; -File.read(File.join(conformance, 'cep.expected.tsv'), encoding: 'UTF-8') - .chomp("\n").split("\n", -1).drop(1).each do |line| - raw_cep, kind, providers, outcome, detail = line.split("\t", -1) + continue; + } - # Ruby's nil is both "absent" and "null", so a null providers option cannot be written. - if providers == '!null' - cep_skipped += 1 - next - end +${reads} +${plan.options === "" ? "" : ` let mut options = ${unit(plan)}::${plan.options}::default();\n let mut given = false;\n\n${options}\n`} +${body} - value = kind == 'number' ? raw_cep.to_i : raw_cep - options = - if providers == '-' - nil - elsif providers == '[]' - Cep::GetAddressInfoByCepOptions.new(providers: []) - elsif providers.start_with?('!') - Cep::GetAddressInfoByCepOptions.new(providers: NOT_A_LIST[providers]) - else - Cep::GetAddressInfoByCepOptions.new(providers: providers.split('|')) - end + report("${plan.entry.name}", &actual, &unescape(parts[${plan.expect}]), &mut counts); + } - actual = - begin - found = Cep.get_address_info_by_cep(value, options) - "ok\t#{[found.cep, found.state, found.city, found.neighborhood, found.street].join('|')}" - rescue StandardError => e - "error\t#{e.class.name.split('::').last}|#{e.message}" - end + counts +}`; + }); - if actual == "#{outcome}\t#{detail}" - cep_passed += 1 - else - cep_failed += 1 - warn "FAIL cep(#{raw_cep}, #{providers}) expected #{outcome}/#{detail} got #{actual}" if cep_failed <= 5 - end -end + return `// Code generated by spec/bridge/conformance/drivers.ts. DO NOT EDIT. +// +// Replays the recorded tables against the generated Rust. -puts "ruby: #{cep_passed}/#{cep_passed + cep_failed} CEP cases matched (#{cep_skipped} not expressible)" -exit(failed.zero? && dump_failed.zero? && cep_failed.zero? ? 0 : 1) -`, +${plans.map((plan) => `use brazilian_utils_bridge::${unit(plan)};`).join("\n")} - "out/java/Conformance.java": `// Code generated by spec/bridge/conformance/drivers.ts. DO NOT EDIT. +const TARGET: &str = "rust"; -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.List; +#[derive(Default)] +struct Tally { + passed: usize, + failed: usize, + skipped: usize, +} -/** Replays the vectors recorded from the JavaScript package against the generated Java. */ -public final class Conformance { - private Conformance() {} +/// Reads back the three characters the table format escapes. +fn unescape(value: &str) -> String { + value + .replace("\\\\t", "\\t") + .replace("\\\\n", "\\n") + .replace("\\\\\\\\", "\\\\") +} - private static String unescape(String value) { - return value.replace("\\\\t", "\\t").replace("\\\\n", "\\n").replace("\\\\\\\\", "\\\\"); - } +/// Whether this target can express the call a row describes. +fn runs(targets: &str) -> bool { + targets == "*" || targets.split('|').any(|name| name == TARGET) +} - public static void main(String[] args) throws Exception { - List lines = Files.readAllLines(Path.of(args[0])); - int passed = 0; - int failed = 0; - int skipped = 0; +/// Counts one comparison, and shows the first few that disagree. +fn report(name: &str, actual: &str, expected: &str, counts: &mut Tally) { + if actual == expected { + counts.passed += 1; - for (String line : lines.subList(1, lines.size())) { - if (line.isEmpty()) { - continue; - } + return; + } - String[] parts = line.split("\\t", -1); - String fn = parts[0]; - String input = unescape(parts[1]); - String kind = parts[2]; - String version = parts[3]; - String expected = unescape(parts[6]); + counts.failed += 1; - // A number input to a validator cannot be written in Java: the parameter is a String. - if (kind.equals("number") && fn.equals("isValidCnpj")) { - skipped++; + if counts.failed <= 3 { + eprintln!( + "FAIL {} expected {:?} got {:?}", + name, + &expected[..expected.len().min(120)], + &actual[..actual.len().min(120)] + ); + } +} - continue; - } +${[...helpers.values()].join("\n\n")} - String actual; +${checks.join("\n\n")} - if (fn.equals("isValidCnpj")) { - IsValidCnpjOptions options = new IsValidCnpjOptions(); +fn main() { + let mut failed = 0; - if (!version.isEmpty()) { - options.version = Long.parseLong(version); - } +${plans + .map( + (plan) => ` let counts = check_${snake(plan.entry.name)}(); + failed += counts.failed; + println!( + "{}: ${plan.entry.name} {}/{} matched{}", + TARGET, + counts.passed, + counts.passed + counts.failed, + if counts.skipped == 0 { String::new() } else { format!(" ({} not expressible)", counts.skipped) } + );`, + ) + .join("\n\n")} + + if failed > 0 { + std::process::exit(1); + } +} +`; +}; - actual = String.valueOf(Cnpj.isValidCnpj(input, options)); - } else { - FormatCnpjOptions options = new FormatCnpjOptions(); +/* ------------------------------------------------------------------------ Java */ - if (!version.isEmpty()) { - options.version = Long.parseLong(version); - } +const java = (plans: Plan[]): string => { + const helpers = new Map(); - options.pad = parts[4].equals("1") ? Boolean.TRUE : null; - options.obfuscate = parts[5].equals("1") ? Boolean.TRUE : null; - actual = Cnpj.formatCnpj(input, options); - } + const render = (plan: Plan, ty: Ty, value: string): string => { + if (ty.k === "bool" || ty.k === "int") return `String.valueOf(${value})`; - if (actual.equals(expected)) { - passed++; - } else { - failed++; + if (ty.k === "named") { + const name = helperName(plan, ty.name); + const struct = plan.module.structs.find((entry) => entry.name === ty.name); - if (failed <= 5) { - System.err.printf("FAIL %s(%s) expected %s got %s%n", fn, input, expected, actual); - } - } - } + helpers.set( + name, + ` private static String ${name}(${ty.name} value) {\n return ${(struct?.fields ?? []).map((field) => render(plan, field.ty, `value.${field.name}`)).join(' + "|" + ')};\n }`, + ); - System.out.printf("java: %d/%d conformance checks passed (%d not expressible)%n", passed, passed + failed, skipped); + return `${name}(${value})`; + } - Path conformance = Path.of(args[0]).getParent(); - java.util.List dump = new java.util.ArrayList<>(); + if (ty.k === "list") { + const name = listHelperName(plan, ty.of); - for (String key : Files.readString(conformance.resolve("municipalities.keys.txt")).stripTrailing().split("\\n", -1)) { - java.util.List found = - key.equals("*") ? Municipalities.getMunicipalities(null) : Municipalities.getMunicipalities(key); + helpers.set( + name, + ` private static String ${name}(java.util.List<${javaType(ty.of)}> items) {\n StringBuilder out = new StringBuilder(String.valueOf(items.size()));\n\n for (${javaType(ty.of)} item : items) {\n out.append("\\n").append(${render(plan, ty.of, "item")});\n }\n\n return out.toString();\n }`, + ); - dump.add(key + "\\t" + found.size()); + return `${name}(${value})`; + } - for (Municipality municipality : found) { - dump.add(municipality.code + "|" + municipality.name + "|" + municipality.stateCode); + return value; + }; + + const checks = plans.map((plan) => { + const argNames = plan.args.map((_, index) => `argument${index}`); + const reads = plan.args + .map((arg, index) => { + const text = `unescape(cells[${arg.at}])`; + + return arg.set === -1 + ? ` String ${argNames[index]} = ${text};` + : ` String ${argNames[index]} = cells[${arg.set}].equals("1") ? ${text} : null;`; + }) + .join("\n"); + const options = plan.opts + .map((option) => { + const cell = `cells[${option.at}]`; + const value = + option.ty.k === "bool" + ? `${cell}.equals("1")` + : option.ty.k === "list" + ? `${cell}.equals("[]") ? java.util.List.of() : java.util.List.of(${cell}.split("\\\\|", -1))` + : `Long.parseLong(${cell})`; + + return ` if (!${cell}.isEmpty()) {\n options.${option.name} = ${value};\n given = true;\n }`; + }) + .join("\n\n"); + const call = `${pascal(plan.module.name)}.${plan.entry.name}(${[...argNames, ...(plan.options === "" ? [] : ["given ? options : null"])].join(", ")})`; + const body = plan.entry.throws + ? ` String actual;\n\n try {\n actual = ${render(plan, plan.entry.ret, call)};\n } catch (RuntimeException error) {\n actual = "!" + error.getClass().getSimpleName() + "|" + error.getMessage();\n }` + : ` String actual = ${render(plan, plan.entry.ret, call)};`; + + return ` /** Replays what {@code ${plan.entry.name}} answers. */ + private static Tally check${pascal(plan.entry.name)}() throws java.io.IOException { + Tally counts = new Tally(); + + for (String line : Files.readString(Path.of("${tableOf(plan)}")).stripTrailing().split("\\n", -1)) { + if (line.isEmpty() || line.startsWith("targets\\t")) { + continue; } - } - String[] expectedDump = - Files.readString(conformance.resolve("municipalities.expected.txt")).stripTrailing().split("\\n", -1); - int dumpFailed = 0; + String[] cells = line.split("\\t", -1); - for (int index = 0; index < Math.max(dump.size(), expectedDump.length); index++) { - String got = index < dump.size() ? dump.get(index) : ""; - String want = index < expectedDump.length ? expectedDump[index] : ""; + if (!runs(cells[0])) { + counts.skipped++; - if (got.equals(want)) { continue; } - dumpFailed++; +${reads} +${plan.options === "" ? "" : ` ${plan.options} options = new ${plan.options}();\n boolean given = false;\n\n${options}\n`} +${body} - if (dumpFailed <= 5) { - System.err.printf("FAIL municipalities line %d: expected %s got %s%n", index + 1, want, got); - } + report("${plan.entry.name}", actual, unescape(cells[${plan.expect}]), counts); } - System.out.printf("java: %d/%d municipality lines matched%n", expectedDump.length - dumpFailed, expectedDump.length); + return counts; + }`; + }); - int cepPassed = 0; - int cepFailed = 0; - int cepSkipped = 0; + return `// Code generated by spec/bridge/conformance/drivers.ts. DO NOT EDIT. - for (String row : Files.readString(conformance.resolve("cep.expected.tsv")).stripTrailing().split("\\n", -1)) { - if (row.startsWith("cep\\t")) { - continue; - } +import java.nio.file.Files; +import java.nio.file.Path; - String[] cells = row.split("\\t", -1); - String rawCep = cells[0]; - String providers = cells[2]; +/** Replays the recorded tables against the generated Java. */ +public final class Conformance { + private static final String TARGET = "java"; - // A number input and a providers option that is not a list have no Java form. - if (cells[1].equals("number") || providers.startsWith("!")) { - cepSkipped++; + private Conformance() {} - continue; - } + /** One utility's score. */ + private static final class Tally { + private int passed; + private int failed; + private int skipped; + } - GetAddressInfoByCepOptions cepOptions = null; + /** Reads back the three characters the table format escapes. */ + private static String unescape(String value) { + return value.replace("\\\\t", "\\t").replace("\\\\n", "\\n").replace("\\\\\\\\", "\\\\"); + } - if (!providers.equals("-")) { - cepOptions = new GetAddressInfoByCepOptions(); - cepOptions.providers = providers.equals("[]") - ? java.util.List.of() - : java.util.List.of(providers.split("\\\\|", -1)); + /** Whether this target can express the call a row describes. */ + private static boolean runs(String targets) { + if (targets.equals("*")) { + return true; + } + + for (String name : targets.split("\\\\|", -1)) { + if (name.equals(TARGET)) { + return true; } + } - String actual; + return false; + } - try { - AddressInfo found = Cep.getAddressInfoByCep(rawCep, cepOptions); + /** Keeps a failure message readable when the answer is a five thousand row list. */ + private static String cut(String value) { + return value.length() <= 120 ? value : value.substring(0, 120); + } - actual = "ok\\t" + found.cep + "|" + found.state + "|" + found.city + "|" - + found.neighborhood + "|" + found.street; - } catch (RuntimeException error) { - actual = "error\\t" + error.getClass().getSimpleName() + "|" + error.getMessage(); - } + /** Counts one comparison, and shows the first few that disagree. */ + private static void report(String fn, String actual, String expected, Tally counts) { + if (actual.equals(expected)) { + counts.passed++; - if (actual.equals(cells[3] + "\\t" + cells[4])) { - cepPassed++; - } else { - cepFailed++; + return; + } - if (cepFailed <= 5) { - System.err.printf("FAIL cep(%s, %s) expected %s/%s got %s%n", rawCep, providers, cells[3], cells[4], actual); - } - } + counts.failed++; + + if (counts.failed <= 3) { + System.err.printf("FAIL %s expected %s got %s%n", fn, cut(expected), cut(actual)); } + } + +${[...helpers.values()].join("\n\n")} - System.out.printf("java: %d/%d CEP cases matched (%d not expressible)%n", cepPassed, cepPassed + cepFailed, cepSkipped); +${checks.join("\n\n")} - if (failed > 0 || dumpFailed > 0 || cepFailed > 0) { + public static void main(String[] args) throws java.io.IOException { + int failed = 0; + Tally counts; + +${plans + .map( + (plan) => ` counts = check${pascal(plan.entry.name)}(); + failed += counts.failed; + System.out.printf( + "%s: ${plan.entry.name} %d/%d matched%s%n", + TARGET, + counts.passed, + counts.passed + counts.failed, + counts.skipped == 0 ? "" : String.format(" (%d not expressible)", counts.skipped));`, + ) + .join("\n\n")} + + if (failed > 0) { System.exit(1); } } } -`, +`; +}; - "out/rust/conformance_cabi.c": `/* Code generated by spec/bridge/conformance/drivers.ts. DO NOT EDIT. - * - * The eighth target is not a language: it is the C ABI the Rust crate exposes, replayed from C. - * - * Every hand-written binding — a CPython extension, a Ruby C extension, a NuGet package over - * P/Invoke, a JAR over Panama — calls exactly these symbols with exactly these arguments, so - * checking them from C checks all of them at once. What it cannot check is each binding's own - * marshalling, which is why the bindings themselves stay each package's own code to test. - */ -#include -#include -#include +/* -------------------------------------------------------------------------- C# */ -#include "include/cnpj.h" +const csharp = (plans: Plan[]): string => { + const helpers = new Map(); -static void unescape(char *value) { - char *read = value; - char *write = value; + const render = (plan: Plan, ty: Ty, value: string): string => { + if (ty.k === "bool") return `(${value} ? "true" : "false")`; + if (ty.k === "int") return `${value}.ToString()`; - while (*read != '\\0') { - if (*read != '\\\\') { - *write++ = *read++; + if (ty.k === "named") { + const name = helperName(plan, ty.name); + const struct = plan.module.structs.find((entry) => entry.name === ty.name); - continue; + helpers.set( + name, + ` private static string ${name}(${ty.name} value)\n {\n return ${(struct?.fields ?? []).map((field) => render(plan, field.ty, `value.${pascal(field.name)}`)).join(' + "|" + ')};\n }`, + ); + + return `${name}(${value})`; } - read++; + if (ty.k === "list") { + const name = listHelperName(plan, ty.of); - switch (*read) { - case 't': *write++ = '\\t'; break; - case 'n': *write++ = '\\n'; break; - default: *write++ = *read; + helpers.set( + name, + ` private static string ${name}(System.Collections.Generic.List<${csharpType(ty.of)}> items)\n {\n var out_ = new System.Text.StringBuilder(items.Count.ToString());\n\n foreach (var item in items)\n {\n out_.Append("\\n").Append(${render(plan, ty.of, "item")});\n }\n\n return out_.ToString();\n }`, + ); + + return `${name}(${value})`; } - read++; - } + return value; + }; + + const checks = plans.map((plan) => { + const argNames = plan.args.map((_, index) => `argument${index}`); + const reads = plan.args + .map((arg, index) => { + const text = `Unescape(cells[${arg.at}])`; + + return arg.set === -1 + ? ` var ${argNames[index]} = ${text};` + : ` var ${argNames[index]} = cells[${arg.set}] == "1" ? ${text} : null;`; + }) + .join("\n"); + const options = plan.opts + .map((option) => { + const cell = `cells[${option.at}]`; + const value = + option.ty.k === "bool" + ? `${cell} == "1"` + : option.ty.k === "list" + ? `${cell} == "[]" ? new System.Collections.Generic.List() : new System.Collections.Generic.List(${cell}.Split('|'))` + : `long.Parse(${cell})`; + + return ` if (${cell}.Length > 0)\n {\n options.${pascal(option.name)} = ${value};\n given = true;\n }`; + }) + .join("\n\n"); + const call = `${plan.entry.blocking ? "await " : ""}${pascal(plan.module.name)}Utility.${pascal(plan.entry.name)}(${[...argNames, ...(plan.options === "" ? [] : ["given ? options : null"])].join(", ")})`; + const body = plan.entry.throws + ? ` string actual;\n\n try\n {\n actual = ${render(plan, plan.entry.ret, call)};\n }\n catch (Exception error)\n {\n actual = "!" + error.GetType().Name + "|" + error.Message;\n }` + : ` var actual = ${render(plan, plan.entry.ret, call)};`; + + // Only a utility that waits on something has anything to await; the rest would warn. + return ` ///

Replays what ${plan.entry.name} answers. + private static ${plan.entry.blocking ? "async " : ""}System.Threading.Tasks.Task Check${pascal(plan.entry.name)}() + { + var counts = new Tally(); - *write = '\\0'; -} + foreach (var line in File.ReadAllText("${tableOf(plan)}").TrimEnd('\\n').Split('\\n')) + { + if (line.Length == 0 || line.StartsWith("targets\\t")) + { + continue; + } -int main(int argc, char **argv) { - const char *path = argc > 1 ? argv[1] : "../../conformance/vectors.tsv"; - FILE *handle = fopen(path, "r"); - char *line = NULL; - size_t capacity = 0; - int passed = 0; - int failed = 0; - int skipped = 0; - int first = 1; + var cells = line.Split('\\t'); - if (handle == NULL) { - fprintf(stderr, "cannot open %s\\n", path); + if (!Runs(cells[0])) + { + counts.Skipped++; - return 1; - } + continue; + } - while (getline(&line, &capacity, handle) != -1) { - char *cells[7]; - char *cursor = line; - char answer[256]; - char actual[256]; - int index = 0; - long written = 0; - size_t length = strlen(line); - - if (length > 0 && line[length - 1] == '\\n') { - line[length - 1] = '\\0'; - } +${reads} +${plan.options === "" ? "" : ` var options = new ${plan.options}();\n var given = false;\n\n${options}\n`} +${body} - if (first) { - first = 0; + Report("${plan.entry.name}", actual, Unescape(cells[${plan.expect}]), counts); + } - continue; - } + return ${plan.entry.blocking ? "counts" : "System.Threading.Tasks.Task.FromResult(counts)"}; + }`; + }); - if (line[0] == '\\0') { - continue; - } + return `// Code generated by spec/bridge/conformance/drivers.ts. DO NOT EDIT. - for (index = 0; index < 7; index++) { - char *tab = strchr(cursor, '\\t'); +using System; +using System.IO; +using BrazilianUtils.Bridge; - cells[index] = cursor; +/// Replays the recorded tables against the generated C#. +public static class Conformance +{ + private const string Target = "csharp"; - if (tab == NULL) { - break; - } + /// One utility's score. + private sealed class Tally + { + public int Passed { get; set; } - *tab = '\\0'; - cursor = tab + 1; - } + public int Failed { get; set; } + + public int Skipped { get; set; } + } - unescape(cells[1]); - unescape(cells[6]); + /// Reads back the three characters the table format escapes. + private static string Unescape(string value) + { + return value.Replace("\\\\t", "\\t").Replace("\\\\n", "\\n").Replace("\\\\\\\\", "\\\\"); + } - /* A number input to a validator has no C form: the parameter is a pointer and a length, - * so the JavaScript quirk "a number is never a valid CNPJ" cannot be asked. The formatter - * coerces, so its number cases are replayed as the decimal string, the same as in Go. */ - if (strcmp(cells[2], "number") == 0 && strcmp(cells[0], "isValidCnpj") == 0) { - skipped++; + /// Whether this target can express the call a row describes. + private static bool Runs(string targets) + { + return targets == "*" || Array.IndexOf(targets.Split('|'), Target) >= 0; + } - continue; - } + /// Keeps a failure message readable when the answer is a five thousand row list. + private static string Cut(string value) + { + return value.Length <= 120 ? value : value.Substring(0, 120); + } - long version = cells[3][0] == '\\0' ? -1 : atol(cells[3]); + /// Counts one comparison, and shows the first few that disagree. + private static void Report(string fn, string actual, string expected, Tally counts) + { + if (actual == expected) + { + counts.Passed++; - if (strcmp(cells[0], "isValidCnpj") == 0) { - int valid = cnpj_is_valid_cnpj((const unsigned char *)cells[1], strlen(cells[1]), version); + return; + } - snprintf(actual, sizeof(actual), "%s", valid ? "true" : "false"); - } else { - written = (long)cnpj_format_cnpj((const unsigned char *)cells[1], strlen(cells[1]), version, - cells[5][0] == '1' ? 1 : 0, cells[4][0] == '1' ? 1 : 0, - (unsigned char *)answer, sizeof(answer) - 1); + counts.Failed++; - if (written < 0) { - written = 0; - } + if (counts.Failed <= 3) + { + Console.Error.WriteLine($"FAIL {fn} expected {Cut(expected)} got {Cut(actual)}"); + } + } - answer[written] = '\\0'; - snprintf(actual, sizeof(actual), "%s", answer); - } +${[...helpers.values()].join("\n\n")} - if (strcmp(actual, cells[6]) == 0) { - passed++; - } else { - failed++; +${checks.join("\n\n")} - if (failed <= 5) { - fprintf(stderr, "FAIL %s(%s) expected %s got %s\\n", cells[0], cells[1], cells[6], actual); + public static async System.Threading.Tasks.Task Main(string[] args) + { + var failed = 0; + Tally counts; + +${plans + .map( + (plan) => ` counts = await Check${pascal(plan.entry.name)}(); + failed += counts.Failed; + Console.WriteLine( + $"{Target}: ${plan.entry.name} {counts.Passed}/{counts.Passed + counts.Failed} matched" + + (counts.Skipped == 0 ? "" : $" ({counts.Skipped} not expressible)"));`, + ) + .join("\n\n")} + + return failed == 0 ? 0 : 1; + } +} +`; +}; + +/* --------------------------------------------------------------------- C ABI */ + +const cabi = (plans: Plan[]): string => { + const exposed = plans.filter((plan) => plan.abi !== undefined); + + const checks = exposed.map((plan) => { + const abi = plan.abi as Abi; + const args = abi.args.map((argument) => { + if (argument.k === "option") { + const column = plan.opts.find((option) => option.name === argument.field) as OptPlan; + const cell = `fields[${column.at}]`; + const given = argument.ty.k === "bool" ? `strcmp(${cell}, "1") == 0` : `atoll(${cell})`; + + return `${cell}[0] == '\\0' ? ${argument.unset} : (${given})`; } - } - } - free(line); - fclose(handle); - printf("cabi: %d/%d conformance checks passed (%d not expressible)\\n", passed, passed + failed, - skipped); + const column = plan.args.find((arg) => arg.name === argument.param) as ArgPlan; - return failed == 0 ? 0 : 1; -} -`, + return argument.k === "text" + ? `(const uint8_t *)fields[${column.at}], strlen(fields[${column.at}])` + : `atoll(fields[${column.at}])`; + }); + const body = + abi.returns === "bool" + ? ` const char *actual = ${abi.symbol}(${args.join(", ")}) ? "true" : "false";` + : ` uint8_t answer[512]; + intptr_t length = ${abi.symbol}(${args.join(", ")}, answer, sizeof answer - 1); - "out/csharp/Conformance.cs": `// Code generated by spec/bridge/conformance/drivers.ts. DO NOT EDIT. + if (length < 0 || (size_t)length >= sizeof answer) { + length = 0; + } -using System; -using System.IO; -using BrazilianUtils.Bridge; + answer[length] = '\\0'; -/// Replays the vectors recorded from the JavaScript package against the generated C#. -public static class Conformance -{ - private static string Unescape(string value) - { - return value.Replace("\\\\t", "\\t").Replace("\\\\n", "\\n").Replace("\\\\\\\\", "\\\\"); + const char *actual = (const char *)answer;`; + + return `/* Replays what ${plan.entry.name} answers, over the C ABI. */ +static struct tally check_${snake(plan.entry.name)}(void) { + struct tally counts = {0, 0, 0}; + FILE *table = fopen("${tableOf(plan)}", "r"); + + if (table == NULL) { + perror("${tableOf(plan)}"); + exit(1); } - public static async System.Threading.Tasks.Task Main(string[] args) - { - var lines = File.ReadAllLines(args[0]); - var passed = 0; - var failed = 0; - var skipped = 0; + char *line = malloc(MAX_LINE); + char *fields[64]; - for (var row = 1; row < lines.Length; row++) - { - if (lines[row].Length == 0) - { - continue; - } + /* The header. */ + if (fgets(line, MAX_LINE, table) == NULL) { + exit(1); + } - var parts = lines[row].Split('\\t'); - var fn = parts[0]; - var input = Unescape(parts[1]); - var kind = parts[2]; - var version = parts[3]; - var expected = Unescape(parts[6]); + while (fgets(line, MAX_LINE, table) != NULL) { + line[strcspn(line, "\\n")] = '\\0'; - // A number input to a validator cannot be written in C#: the parameter is a string. - if (kind == "number" && fn == "isValidCnpj") - { - skipped++; + if (line[0] == '\\0') { + continue; + } - continue; - } + split(line, fields, 64); - string actual; + if (!runs(fields[0])) { + counts.skipped++; - if (fn == "isValidCnpj") - { - var options = new IsValidCnpjOptions(); + continue; + } - if (version.Length > 0) - { - options.Version = long.Parse(version); - } +${plan.args.map((arg) => ` unescape(fields[${arg.at}]);`).join("\n")} + unescape(fields[${plan.expect}]); - actual = Cnpj.IsValidCnpj(input, options) ? "true" : "false"; - } - else - { - var options = new FormatCnpjOptions(); +${body} - if (version.Length > 0) - { - options.Version = long.Parse(version); - } + report("${plan.entry.name}", actual, fields[${plan.expect}], &counts); + } - options.Pad = parts[4] == "1" ? true : (bool?)null; - options.Obfuscate = parts[5] == "1" ? true : (bool?)null; - actual = Cnpj.FormatCnpj(input, options); - } + free(line); + fclose(table); - if (actual == expected) - { - passed++; - } - else - { - failed++; + return counts; +}`; + }); - if (failed <= 5) - { - Console.Error.WriteLine($"FAIL {fn}({input}) expected {expected} got {actual}"); - } - } - } + return `/* Code generated by spec/bridge/conformance/drivers.ts. DO NOT EDIT. + * + * Replays the recorded tables over the C ABI the Rust crate exposes: the same surface a + * hand-written binding in Python, Ruby, C#, Java or Erlang would call. Only the utilities the + * ABI can carry appear here; the rest need a richer surface than pointers and integers. + */ +#include +#include +#include +#include - Console.WriteLine($"csharp: {passed}/{passed + failed} conformance checks passed ({skipped} not expressible)"); +${exposed.map((plan) => `#include "include/${snake(plan.module.name)}.h"`).join("\n")} - var conformance = Path.GetDirectoryName(Path.GetFullPath(args[0])); - var dump = new System.Collections.Generic.List(); +#define MAX_LINE (1 << 20) - foreach (var key in File.ReadAllText(Path.Combine(conformance, "municipalities.keys.txt")).TrimEnd('\\n').Split('\\n')) - { - var found = key == "*" ? Municipalities.GetMunicipalities() : Municipalities.GetMunicipalities(key); +static const char *TARGET = "cabi"; - dump.Add(key + "\\t" + found.Count); +struct tally { + int passed; + int failed; + int skipped; +}; - foreach (var municipality in found) - { - dump.Add(municipality.Code + "|" + municipality.Name + "|" + municipality.StateCode); - } +/* Reads back the three characters the table format escapes, in place. */ +static void unescape(char *value) { + char *write = value; + + for (const char *read = value; *read != '\\0'; read++) { + if (*read != '\\\\' || read[1] == '\\0') { + *write++ = *read; + + continue; } - var expectedDump = File.ReadAllText(Path.Combine(conformance, "municipalities.expected.txt")).TrimEnd('\\n').Split('\\n'); - var dumpFailed = 0; + read++; + *write++ = *read == 't' ? '\\t' : *read == 'n' ? '\\n' : *read; + } - for (var index = 0; index < Math.Max(dump.Count, expectedDump.Length); index++) - { - var got = index < dump.Count ? dump[index] : ""; - var want = index < expectedDump.Length ? expectedDump[index] : ""; + *write = '\\0'; +} - if (got == want) - { - continue; - } +/* Splits a line on tabs, in place. */ +static int split(char *line, char **fields, int max) { + int count = 0; - dumpFailed++; + fields[count++] = line; - if (dumpFailed <= 5) - { - Console.Error.WriteLine($"FAIL municipalities line {index + 1}: expected {want} got {got}"); - } + for (char *cursor = line; *cursor != '\\0'; cursor++) { + if (*cursor == '\\t' && count < max) { + *cursor = '\\0'; + fields[count++] = cursor + 1; } + } - Console.WriteLine($"csharp: {expectedDump.Length - dumpFailed}/{expectedDump.Length} municipality lines matched"); + return count; +} - var cepPassed = 0; - var cepFailed = 0; - var cepSkipped = 0; +/* Whether this target can express the call a row describes. */ +static int runs(const char *targets) { + if (strcmp(targets, "*") == 0) { + return 1; + } - foreach (var row in File.ReadAllText(Path.Combine(conformance, "cep.expected.tsv")).TrimEnd('\\n').Split('\\n')) - { - if (row.StartsWith("cep\\t")) - { - continue; - } + const char *cursor = targets; + size_t width = strlen(TARGET); - var cells = row.Split('\\t'); - var rawCep = cells[0]; - var providers = cells[2]; + while (cursor != NULL) { + if (strncmp(cursor, TARGET, width) == 0 && (cursor[width] == '\\0' || cursor[width] == '|')) { + return 1; + } - // A number input and a providers option that is not a list have no C# form. - if (cells[1] == "number" || providers.StartsWith("!")) - { - cepSkipped++; + cursor = strchr(cursor, '|'); - continue; - } + if (cursor != NULL) { + cursor++; + } + } - GetAddressInfoByCepOptions cepOptions = null; + return 0; +} - if (providers != "-") - { - cepOptions = new GetAddressInfoByCepOptions - { - Providers = providers == "[]" - ? new System.Collections.Generic.List() - : new System.Collections.Generic.List(providers.Split('|')), - }; - } +/* Counts one comparison, and shows the first few that disagree. */ +static void report(const char *fn, const char *actual, const char *expected, struct tally *counts) { + if (strcmp(actual, expected) == 0) { + counts->passed++; - string actual; + return; + } - try - { - var found = await Cep.GetAddressInfoByCep(rawCep, cepOptions); + counts->failed++; - actual = $"ok\\t{found.Cep}|{found.State}|{found.City}|{found.Neighborhood}|{found.Street}"; - } - catch (Exception error) - { - actual = $"error\\t{error.GetType().Name}|{error.Message}"; - } + if (counts->failed <= 3) { + fprintf(stderr, "FAIL %s expected %.120s got %.120s\\n", fn, expected, actual); + } +} - if (actual == cells[3] + "\\t" + cells[4]) - { - cepPassed++; - } - else - { - cepFailed++; +${checks.join("\n\n")} - if (cepFailed <= 5) - { - Console.Error.WriteLine($"FAIL cep({rawCep}, {providers}) expected {cells[3]}/{cells[4]} got {actual}"); - } - } - } +int main(void) { + int failed = 0; + struct tally counts; - Console.WriteLine($"csharp: {cepPassed}/{cepPassed + cepFailed} CEP cases matched ({cepSkipped} not expressible)"); +${exposed + .map( + (plan) => ` counts = check_${snake(plan.entry.name)}(); + failed += counts.failed; + printf("%s: ${plan.entry.name} %d/%d matched", TARGET, counts.passed, counts.passed + counts.failed); - return failed == 0 && dumpFailed == 0 && cepFailed == 0 ? 0 : 1; + if (counts.skipped > 0) { + printf(" (%d not expressible)", counts.skipped); } + + printf("\\n");`, + ) + .join("\n\n")} + + return failed == 0 ? 0 : 1; } -`, +`; }; +const recorders = await loadRecorders(); +const modules = recorders.map((recorder) => + compileModule(resolve(bridge, "source", `${recorder.module}.ts`)), +); +const plans = modules.map((module) => planOf(module)); + +const files: Record = + plans.length === 0 + ? {} + : { + "out/typescript/conformance.ts": typescript(plans), + "out/python/conformance.py": python(plans), + "out/ruby/conformance.rb": ruby(plans), + "out/go/conformance/main.go": go(plans), + "out/rust/src/bin/conformance.rs": rust(plans), + "out/rust/conformance_cabi.c": cabi(plans), + "out/java/Conformance.java": java(plans), + "out/csharp/Conformance.cs": csharp(plans), + }; + for (const [path, contents] of Object.entries(files)) { const full = resolve(bridge, path); @@ -1332,6 +1595,4 @@ for (const [path, contents] of Object.entries(files)) { writeFileSync(full, contents); } -console.log( - `wrote ${tablePath} (${lines.length - 1} rows) and ${Object.keys(files).length} drivers`, -); +console.log(`${Object.keys(files).length} drivers for ${plans.length} utilities`); diff --git a/spec/bridge/conformance/municipalities.ts b/spec/bridge/conformance/municipalities.ts deleted file mode 100644 index 9913f6a90..000000000 --- a/spec/bridge/conformance/municipalities.ts +++ /dev/null @@ -1,95 +0,0 @@ -/** - * Records the municipality dump the generated code has to reproduce, from the package this - * repository ships. - * - * A dump rather than a sample: every municipality of every key is written out, so a single - * name out of place in one of the seven targets fails the check. - * - * Usage: `node spec/bridge/conformance/municipalities.ts` - */ -import { mkdtempSync, rmSync, writeFileSync } from "node:fs"; -import { tmpdir } from "node:os"; -import { join, resolve } from "node:path"; - -import { build } from "esbuild"; - -const bridge = resolve(import.meta.dirname, ".."); -const root = resolve(bridge, "../.."); - -/** - * The keys to dump. `*` stands for "no state code at all", which is the only way to ask for the - * combined list; every other value, an unknown state and an inherited `Object` property name - * included, has its own answer. - */ -export const KEYS = [ - "*", - "AC", - "AL", - "AP", - "AM", - "BA", - "CE", - "DF", - "ES", - "GO", - "MA", - "MT", - "MS", - "MG", - "PA", - "PB", - "PR", - "PE", - "PI", - "RJ", - "RN", - "RS", - "RO", - "RR", - "SC", - "SP", - "SE", - "TO", - "ZZ", - "sp", - "", - "toString", - "constructor", - "hasOwnProperty", -]; - -const outDir = mkdtempSync(join(tmpdir(), "brutils-dump-")); -const bundlePath = join(outDir, "shipped.mjs"); - -await build({ - entryPoints: [resolve(root, "src/index.ts")], - bundle: true, - format: "esm", - platform: "neutral", - outfile: bundlePath, - logLevel: "error", -}); - -const shipped = (await import(bundlePath)) as { - getMunicipalities: (stateCode?: string) => { code: string; name: string; stateCode: string }[]; -}; - -rmSync(outDir, { recursive: true, force: true }); - -const lines: string[] = []; - -for (const key of KEYS) { - const found = key === "*" ? shipped.getMunicipalities() : shipped.getMunicipalities(key); - - lines.push(`${key}\t${found.length}`); - - for (const municipality of found) - lines.push(`${municipality.code}|${municipality.name}|${municipality.stateCode}`); -} - -writeFileSync(resolve(bridge, "conformance/municipalities.expected.txt"), `${lines.join("\n")}\n`); -writeFileSync(resolve(bridge, "conformance/municipalities.keys.txt"), `${KEYS.join("\n")}\n`); - -console.log( - `${KEYS.length} keys, ${lines.length - KEYS.length} rows recorded from the shipped package`, -); diff --git a/spec/bridge/conformance/record.ts b/spec/bridge/conformance/record.ts new file mode 100644 index 000000000..9621a99a0 --- /dev/null +++ b/spec/bridge/conformance/record.ts @@ -0,0 +1,173 @@ +/** + * Records what the shipped package answers, as the table every target replays. + * + * One file per utility under `conformance/cases/` says which arguments to try. This turns each + * of those into a row: the arguments in the columns the compiled signature asks for, and the + * answer — or the failure — rendered the one way `cases.ts` defines. + * + * It also decides, per row, which targets can express the call at all. A number where the + * signature says `string | number`, or `null` where it says a list of names, is a call a + * JavaScript caller can make and a Go caller cannot, and a row that says so is more useful + * than a row quietly left out. + * + * Usage: `node spec/bridge/conformance/record.ts` + */ +import { mkdirSync, writeFileSync } from "node:fs"; +import { resolve } from "node:path"; + +import { compileModule } from "../compiler/frontend.ts"; +import { type FuncDecl } from "../compiler/ir.ts"; +import { + type Column, + DYNAMIC, + type Shipped, + NULLABLE, + TARGETS, + cell, + columnsOf, + entryOf, + headerOf, + loadRecorders, + render, + renderFailure, +} from "./cases.ts"; +import { loadShipped } from "./shipped.ts"; + +const bridge = resolve(import.meta.dirname, ".."); + +/** Writes an argument into the column that carries it. */ +const encode = (column: Column, args: unknown[], options: Record): string => { + if (column.k === "targets" || column.k === "expect") return ""; + + if (column.k === "set") return args[column.index] === undefined ? "" : "1"; + + if (column.k === "kind") return typeof args[column.index] === "number" ? "number" : "string"; + + if (column.k === "arg") { + const value = args[column.index] as string | number | undefined | null; + + return value === undefined || value === null ? "" : String(value); + } + + if (!(column.field in options)) return ""; + + const value = options[column.field] as string | number | boolean | unknown[] | null; + + if (column.ty.k === "bool") return value === true ? "1" : "0"; + + if (column.ty.k === "list") { + if (value === null) return "!null"; + if (!Array.isArray(value)) return `!${typeof value}`; + + return value.length === 0 ? "[]" : value.join("|"); + } + + return String(value); +}; + +/** + * Which targets can be handed this call, given what their declared types allow. + * + * Three answers. A number where the signature says `string` needs a host that still checks at + * run time. `null` where it says a list needs one that also tells `null` apart from "not + * given", which the optional of a Python or Ruby signature does not. Everything else is `*`. + */ +const expressibleIn = (columns: Column[], row: string[]): string => { + let allowed: readonly string[] = TARGETS; + + const narrow = (to: readonly string[]): void => { + allowed = allowed.filter((target) => to.includes(target)); + }; + + for (const [index, column] of columns.entries()) { + if (column.k === "kind" && row[index] === "number") narrow(DYNAMIC); + + if (column.k === "option" && row[index].startsWith("!")) + narrow(row[index] === "!null" ? NULLABLE : DYNAMIC); + } + + return allowed.length === TARGETS.length ? "*" : allowed.join("|"); +}; + +/** Splits an argument list into the positional arguments and the options record. */ +const split = ( + args: unknown[], + entry: FuncDecl, +): { positional: unknown[]; options: Record } => { + const found: unknown[] = []; + let options: Record = {}; + + for (const [index, param] of entry.params.entries()) { + if (param.ty.k === "named") { + options = (args[index] ?? {}) as Record; + continue; + } + + found[index] = args[index]; + } + + return { positional: found, options }; +}; + +const shipped = await loadShipped(); +const recorders = await loadRecorders(); + +if (recorders.length === 0) console.log("no utilities under conformance/cases: nothing to record"); + +mkdirSync(resolve(bridge, "conformance/recorded"), { recursive: true }); + +for (const recorder of recorders) { + const module = compileModule(resolve(bridge, "source", `${recorder.module}.ts`)); + const entry = entryOf(module); + const columns = columnsOf(module, entry); + const call = + recorder.call ?? + (async (target: Shipped, fn: string, args: unknown[]): Promise => { + const answered = target[fn](...args); + + return await answered; + }); + + const lines = [headerOf(columns)]; + let raising = 0; + let partial = 0; + + for (const args of recorder.inputs(shipped)) { + const { positional, options } = split(args, entry); + let expect = ""; + + try { + const answered = await call(shipped, entry.name, args); + + expect = render(answered, entry.ret, module); + } catch (error) { + const raised = error as Error; + + expect = renderFailure(raised.constructor.name, raised.message); + raising++; + } + + const row = columns.map((column) => + column.k === "targets" || column.k === "expect" ? "" : encode(column, positional, options), + ); + const targets = expressibleIn(columns, row); + + if (targets !== "*") partial++; + + for (const [index, column] of columns.entries()) { + if (column.k === "targets") row[index] = targets; + if (column.k === "expect") row[index] = expect; + } + + lines.push(row.map((value) => cell(value)).join("\t")); + } + + writeFileSync( + resolve(bridge, "conformance/recorded", `${recorder.module}.tsv`), + `${lines.join("\n")}\n`, + ); + + console.log( + `${recorder.module.padEnd(26)} ${lines.length - 1} cases, ${raising} raising, ${partial} not expressible everywhere`, + ); +} diff --git a/spec/bridge/conformance/run-all.sh b/spec/bridge/conformance/run-all.sh index 7d3d0d178..29ad7cc2d 100644 --- a/spec/bridge/conformance/run-all.sh +++ b/spec/bridge/conformance/run-all.sh @@ -1,13 +1,15 @@ #!/usr/bin/env bash -# Regenerates every target and replays the recorded expectations through all seven of them. +# Records what the npm package answers, compiles every target, and replays the recording +# through all of them. # -# Three recordings, all taken from the JavaScript package this repository ships: the CNPJ -# vectors, the municipality dump, and the CEP scenarios. A green run means the generated code -# answers exactly what the handwritten code answers, in every language. +# Nothing here knows which utilities exist. `conformance/record.ts` reads the recorders under +# `conformance/cases/`, `compiler/cli.ts` compiles whatever is under `source/`, and +# `conformance/drivers.ts` writes each target's replay program from the compiled signatures. +# Adding a utility therefore changes this script not at all. # -# The CEP replay needs somewhere to send its requests, so the same scenario table is served -# over HTTP on a local port and every target is pointed at it through the runtime's -# BRUTILS_BRIDGE_HTTP_ORIGIN hook. +# A utility that reaches the network is served locally for the run, over the runtime's +# `BRUTILS_BRIDGE_HTTP_ORIGIN` hook, so every target talks to the same answers the recording +# was taken from. # # The eighth arm is not a language: it is the C ABI the Rust crate exposes, which is what a # hand-written binding in Python, Ruby, C#, Java or Erlang would call instead of generated @@ -37,17 +39,21 @@ run() { fi } -step "recording the expectations from the package this repository ships" -node "${bridge}/conformance/vectors.ts" -node "${bridge}/conformance/municipalities.ts" -node "${bridge}/conformance/cep.ts" +step "recording what the package this repository ships answers" +node "${bridge}/conformance/record.ts" step "compiling source/ into every target" node "${bridge}/compiler/cli.ts" node "${bridge}/conformance/drivers.ts" -step "serving the CEP scenarios on ${BRUTILS_BRIDGE_HTTP_ORIGIN}" -node "${bridge}/conformance/cep.ts" serve "${port}" & +if [ ! -f "${out}/typescript/conformance.ts" ]; then + echo + echo "no utilities under source/: the engine has nothing to replay" + exit 0 +fi + +step "serving what the generated code talks to, on ${BRUTILS_BRIDGE_HTTP_ORIGIN}" +node "${bridge}/conformance/serve.ts" "${port}" & server=$! trap 'kill "${server}" 2>/dev/null' EXIT sleep 1 @@ -68,13 +74,13 @@ step "rust" run rust bash -c "cd '${out}/rust' && cargo run --quiet --release --bin conformance 2>/dev/null" step "java" -run java bash -c "cd '${out}/java' && javac -nowarn -d classes *.java >/dev/null 2>&1 && java -cp classes Conformance ../../conformance/vectors.tsv" +run java bash -c "cd '${out}/java' && javac -nowarn -d classes *.java >/dev/null 2>&1 && java -cp classes Conformance" step "c abi (the shared core every hand-written binding calls)" -run cabi bash -c "cd '${out}/rust' && cargo build --quiet --release 2>/dev/null && gcc -O2 -D_GNU_SOURCE -I. conformance_cabi.c -o conformance_cabi -Ltarget/release -lbrazilian_utils_bridge -Wl,-rpath,'${out}/rust/target/release' && ./conformance_cabi ../../conformance/vectors.tsv" +run cabi bash -c "cd '${out}/rust' && cargo build --quiet --release 2>/dev/null && gcc -O2 -D_GNU_SOURCE -I. conformance_cabi.c -o conformance_cabi -Ltarget/release -lbrazilian_utils_bridge -Wl,-rpath,'${out}/rust/target/release' && ./conformance_cabi" step "csharp" -run csharp bash -c "cd '${out}/csharp' && DOTNET_CLI_TELEMETRY_OPTOUT=1 dotnet run --verbosity quiet -- ../../conformance/vectors.tsv" +run csharp bash -c "cd '${out}/csharp' && DOTNET_CLI_TELEMETRY_OPTOUT=1 dotnet run --verbosity quiet" echo if [ "${status}" -eq 0 ]; then diff --git a/spec/bridge/conformance/serve.ts b/spec/bridge/conformance/serve.ts new file mode 100644 index 000000000..4f3bbb02e --- /dev/null +++ b/spec/bridge/conformance/serve.ts @@ -0,0 +1,24 @@ +/** + * Serves whatever the generated code talks to while the drivers run. + * + * A utility that reaches the network declares a `serve` in its recorder, and this starts every + * one of them on the port the runtime's `BRUTILS_BRIDGE_HTTP_ORIGIN` hook points at. A tree + * with no such utility serves nothing and exits, which is what `run-all.sh` expects. + * + * Usage: `node spec/bridge/conformance/serve.ts ` + */ +import { loadRecorders } from "./cases.ts"; + +const port = Number(process.argv[2] ?? 18_080); +const loaded = await loadRecorders(); +const recorders = loaded.filter((recorder) => recorder.serve !== undefined); + +if (recorders.length === 0) { + console.log("no utility reaches the network: nothing to serve"); +} else { + for (const recorder of recorders) { + await recorder.serve?.(port); + + console.log(`${recorder.module} answering on http://127.0.0.1:${port}`); + } +} diff --git a/spec/bridge/conformance/shipped.ts b/spec/bridge/conformance/shipped.ts new file mode 100644 index 000000000..b80ca794d --- /dev/null +++ b/spec/bridge/conformance/shipped.ts @@ -0,0 +1,40 @@ +/** + * The package this repository ships, loaded as one module. + * + * Every expectation in the conformance tables is what this answered. Bundling `src/index.ts` + * rather than importing the files one by one keeps the recording honest: it is the same entry + * point a consumer of the npm package imports, with the same internals behind it. + */ +import { mkdtempSync, rmSync } from "node:fs"; +import { tmpdir } from "node:os"; +import { join, resolve } from "node:path"; + +import { build } from "esbuild"; + +import { type Shipped } from "./cases.ts"; + +/** + * Bundles and imports the shipped package. + * + * @returns {Promise} Its exports. + */ +export const loadShipped = async (): Promise => { + const root = resolve(import.meta.dirname, "../../.."); + const outDir = mkdtempSync(join(tmpdir(), "brutils-bridge-")); + const bundlePath = join(outDir, "shipped.mjs"); + + await build({ + entryPoints: [resolve(root, "src/index.ts")], + bundle: true, + format: "esm", + platform: "neutral", + outfile: bundlePath, + logLevel: "error", + }); + + const shipped = (await import(bundlePath)) as Shipped; + + rmSync(outDir, { recursive: true, force: true }); + + return shipped; +}; diff --git a/spec/bridge/conformance/vectors.ts b/spec/bridge/conformance/vectors.ts deleted file mode 100644 index 472118201..000000000 --- a/spec/bridge/conformance/vectors.ts +++ /dev/null @@ -1,152 +0,0 @@ -/** - * Builds the conformance vectors from the package this repository ships. - * - * The corpus is not invented: every string literal the relevant test files use is pulled out of - * them, so the cross language check runs the same inputs the JavaScript suite runs, plus - * generated and fuzzed values on top. The expectations come from calling the handwritten - * implementation, which makes the vectors a recording of the real contract. - * - * Usage: `node spec/bridge/conformance/vectors.ts` - */ -import { mkdtempSync, readFileSync, readdirSync, rmSync, writeFileSync } from "node:fs"; -import { tmpdir } from "node:os"; -import { join, resolve } from "node:path"; - -import { build } from "esbuild"; - -const bridge = resolve(import.meta.dirname, ".."); -const root = resolve(bridge, "../.."); - -type Options = Record; -export type Case = { fn: string; input: string | number; options: Options; expected: string }; -export type Vectors = { cases: Case[] }; - -/** Pulls every string literal out of a test file, which is where the interesting inputs live. */ -const literalsOf = (path: string): string[] => { - const source = readFileSync(path, "utf8"); - const found = new Set(); - - for (const match of source.matchAll(/"((?:[^"\\\n]|\\.){0,40})"/g)) { - try { - found.add(JSON.parse(`"${match[1]}"`) as string); - } catch { - // A literal that is not valid JSON on its own is not an input worth replaying. - } - } - - return [...found]; -}; - -/** A deterministic pseudo random generator, so the corpus only changes when this file does. */ -const mulberry32 = (seed: number): (() => number) => { - let state = seed; - - return () => { - state = Math.imul(state + 0x6d_2b_79_f5, 1); - let t = Math.imul(state ^ (state >>> 15), 1 | state); - - t ^= t + Math.imul(t ^ (t >>> 7), 61 | t); - - return ((t ^ (t >>> 14)) >>> 0) / 4_294_967_296; - }; -}; - -const MASKS = [".", "-", "/", " ", " ", "", "!", "a"]; - -/** - * Builds the corpus: the test literals, generated CNPJs, masked variants and junk. - * - * @param {Function} generateCnpj - The package's own generator. - * @returns {(string | number)[]} The corpus. - */ -const buildCorpus = (generateCnpj: (version?: 1 | 2) => string): (string | number)[] => { - const random = mulberry32(0x62_72_31); - const corpus = new Set(); - - for (const name of readdirSync(resolve(root, "src/is-valid-cnpj"))) { - if (name.endsWith(".test.ts")) - for (const literal of literalsOf(resolve(root, "src/is-valid-cnpj", name))) - corpus.add(literal); - } - - for (const name of readdirSync(resolve(root, "src/format-cnpj"))) { - if (name.endsWith(".test.ts")) - for (const literal of literalsOf(resolve(root, "src/format-cnpj", name))) corpus.add(literal); - } - - for (let index = 0; index < 120; index++) { - const version = index % 2 === 0 ? 1 : 2; - const cnpj = generateCnpj(version); - - corpus.add(cnpj); - corpus.add(cnpj.toLowerCase()); - - const separators = [0, 1, 2, 3].map(() => MASKS[Math.floor(random() * MASKS.length)]); - - corpus.add( - `${cnpj.slice(0, 2)}${separators[0]}${cnpj.slice(2, 5)}${separators[1]}${cnpj.slice(5, 8)}${separators[2]}${cnpj.slice(8, 12)}${separators[3]}${cnpj.slice(12)}`, - ); - - const position = Math.floor(random() * cnpj.length); - - corpus.add(`${cnpj.slice(0, position)}${Math.floor(random() * 10)}${cnpj.slice(position + 1)}`); - } - - for (const number of [0, 4, 46, 468, 12_345_678, 12_345_678_000_195]) corpus.add(number); - - return [...corpus]; -}; - -const outDir = mkdtempSync(join(tmpdir(), "brutils-bridge-")); -const bundlePath = join(outDir, "shipped.mjs"); - -await build({ - entryPoints: [resolve(root, "src/index.ts")], - bundle: true, - format: "esm", - platform: "neutral", - outfile: bundlePath, - logLevel: "error", -}); - -const shipped = (await import(bundlePath)) as { - isValidCnpj: (value: unknown, options?: Options) => boolean; - formatCnpj: (value: unknown, options?: Options) => string; - generateCnpj: (version?: 1 | 2) => string; -}; - -const corpus = buildCorpus(shipped.generateCnpj); -const validatorOptions: Options[] = [{}, { version: 1 }, { version: 2 }]; -const formatterOptions: Options[] = [ - {}, - { version: 2 }, - { pad: true }, - { obfuscate: true }, - { version: 2, pad: true }, - { version: 2, obfuscate: true }, - { pad: true, obfuscate: true }, -]; - -const cases: Case[] = []; - -for (const input of corpus) { - for (const options of validatorOptions) { - cases.push({ - fn: "isValidCnpj", - input, - options, - expected: String(shipped.isValidCnpj(input, options)), - }); - } - - for (const options of formatterOptions) { - cases.push({ fn: "formatCnpj", input, options, expected: shipped.formatCnpj(input, options) }); - } -} - -rmSync(outDir, { recursive: true, force: true }); -writeFileSync(resolve(bridge, "conformance/vectors.json"), `${JSON.stringify({ cases })}\n`); - -console.log( - `${corpus.length} inputs, ${cases.length} expectations recorded from the shipped package`, -); diff --git a/spec/bridge/conformance/verify-typescript.sh b/spec/bridge/conformance/verify-typescript.sh index 68f174b71..a5d396550 100644 --- a/spec/bridge/conformance/verify-typescript.sh +++ b/spec/bridge/conformance/verify-typescript.sh @@ -1,8 +1,10 @@ #!/usr/bin/env bash # Drops the generated TypeScript into `src/` and runs the package's own test suite against it. # -# This is the parity gate: the generated code has to pass the tests the handwritten code passes, -# unmodified. The tree is restored afterwards, whatever the outcome. +# This is the parity gate: the generated code has to pass the tests the handwritten code +# passes, unmodified. Every utility under `source/` replaces its namesake under `src/`, and the +# suites that cover them are the ones that run. The tree is restored afterwards, whatever the +# outcome. # # Usage: bash spec/bridge/conformance/verify-typescript.sh [vitest path...] set -euo pipefail @@ -11,12 +13,6 @@ root="$(cd "$(dirname "${BASH_SOURCE[0]}")/../../.." && pwd)" bridge="${root}/spec/bridge" out="${bridge}/out/typescript" -targets=("$@") - -if [ ${#targets[@]} -eq 0 ]; then - targets=(src/is-valid-cnpj src/format-cnpj src/get-municipalities src/get-address-info-by-cep) -fi - restore() { rm -rf "${root}/src/_bridge" git -C "${root}" checkout -- src >/dev/null 2>&1 @@ -26,9 +22,16 @@ trap restore EXIT node "${bridge}/compiler/cli.ts" typescript >/dev/null +if [ ! -d "${out}/_bridge" ]; then + echo "no utilities under source/: nothing to verify" + exit 0 +fi + mkdir -p "${root}/src/_bridge" cp -r "${out}/_bridge/." "${root}/src/_bridge/" +replaced=() + for shim in "${out}"/*/; do name="$(basename "${shim}")" @@ -36,13 +39,19 @@ for shim in "${out}"/*/; do mkdir -p "${root}/src/${name}" cp "${shim}${name}.ts" "${root}/src/${name}/${name}.ts" + replaced+=("src/${name}") echo "replaced src/${name}/${name}.ts with the generated version" done -existing=() +targets=("$@") -for target in "${targets[@]}"; do - [ -d "${root}/${target}" ] && existing+=("${target}") -done +if [ ${#targets[@]} -eq 0 ]; then + targets=("${replaced[@]}") +fi + +if [ ${#targets[@]} -eq 0 ]; then + echo "no utilities under source/: nothing to verify" + exit 0 +fi -cd "${root}" && npx vp test run "${existing[@]}" +cd "${root}" && npx vp test run "${targets[@]}" diff --git a/spec/bridge/data/_builder.ts b/spec/bridge/data/_builder.ts new file mode 100644 index 000000000..75f0e0470 --- /dev/null +++ b/spec/bridge/data/_builder.ts @@ -0,0 +1,20 @@ +/** + * What a dataset builder under `data/` exports. + * + * Its own file, rather than `build.ts`, so that a builder can name the type without importing + * the runner that imports it. + */ +import { type DataDecl } from "../compiler/ir.ts"; +import { type Shipped } from "../conformance/cases.ts"; + +export type Builder = { + /** The module under `source/`, whose `.data.json` this writes. */ + module: string; + /** + * Builds the table. + * + * @param shipped - The package this repository ships, bundled. + * @returns The dataset, less its name. + */ + build: (shipped: Shipped) => Omit; +}; diff --git a/spec/bridge/data/build.ts b/spec/bridge/data/build.ts index 608e235a3..b69de6622 100644 --- a/spec/bridge/data/build.ts +++ b/spec/bridge/data/build.ts @@ -1,89 +1,46 @@ /** * Builds the datasets the portable source reads. * - * A dataset is a table plus the two orders the utilities need: the per key order and the full + * A dataset is a table plus the orders the utility needs: the per key order and the full * order. Both are resolved here, once, against the JavaScript package's own data and its own - * `localeCompare(…, "pt-BR")`, and then baked into the JSON the emitters materialise natively. + * comparator, and then baked into the JSON every emitter materialises natively. * * Collation is the reason this step exists. `"Á".localeCompare("B", "pt-BR")` is a locale - * database lookup, and no two of the seven targets ship the same one: Go has no collator in the - * standard library, Rust has none either, Ruby compares bytes, and Java, C# and Python each - * resolve their own ICU or libc table. Sorting at run time would therefore produce seven + * database lookup, and no two of the seven targets ship the same one: Go has no collator in + * the standard library, Rust has none either, Ruby compares bytes, and Java, C# and Python + * each resolve their own ICU or libc table. Sorting at run time would therefore produce seven * different orders. Sorting here produces one, and every target replays it. * + * One file per dataset under `data/`, named after the utility that reads it, the same way + * `conformance/cases/` is. This runs all of them. + * * Usage: `node spec/bridge/data/build.ts` */ -import { mkdtempSync, rmSync, writeFileSync } from "node:fs"; -import { tmpdir } from "node:os"; -import { join, resolve } from "node:path"; - -import { build } from "esbuild"; - -const bridge = resolve(import.meta.dirname, ".."); -const root = resolve(bridge, "../.."); - -const outDir = mkdtempSync(join(tmpdir(), "brutils-data-")); -const bundlePath = join(outDir, "shipped.mjs"); +import { readdirSync, writeFileSync } from "node:fs"; +import { resolve } from "node:path"; -await build({ - entryPoints: [resolve(root, "src/index.ts")], - bundle: true, - format: "esm", - platform: "neutral", - outfile: bundlePath, - logLevel: "error", -}); +import { loadShipped } from "../conformance/shipped.ts"; +import { type Builder } from "./_builder.ts"; -const shipped = (await import(bundlePath)) as { - getStates: () => { code: string }[]; - getMunicipalities: (stateCode?: string) => { code: string; name: string; stateCode: string }[]; -}; +const here = import.meta.dirname; +const shipped = await loadShipped(); +// A `_` prefix is shared scaffolding, not a dataset. +const names = readdirSync(here).filter( + (name) => name.endsWith(".ts") && name !== "build.ts" && !name.startsWith("_"), +); -rmSync(outDir, { recursive: true, force: true }); +if (names.length === 0) console.log("no datasets under data/: nothing to build"); -const columns = ["stateCode", "name", "code"]; -const rows: string[][] = []; -const groups: Record = {}; +for (const name of names.sort()) { + const loaded = (await import(resolve(here, name))) as { builder: Builder }; + const dataset = loaded.builder.build(shipped); -// The per state order is the order the package itself returns, which is already the pt-BR one. -for (const state of shipped.getStates()) { - groups[state.code] = []; + writeFileSync( + resolve(here, "..", "source", `${loaded.builder.module}.data.json`), + `${JSON.stringify(dataset)}\n`, + ); - for (const municipality of shipped.getMunicipalities(state.code)) { - groups[state.code].push(rows.length); - rows.push([municipality.stateCode, municipality.name, municipality.code]); - } + console.log( + `${loaded.builder.module.padEnd(26)} ${dataset.rows.length} rows, ${Object.keys(dataset.groups).length} groups, full order baked`, + ); } - -// The full order is the one `getMunicipalities()` returns: every state's rows merged and sorted -// by name with the pt-BR collator. Matching it by (name, code) rather than by position keeps -// this honest even if the package ever changes how it merges the states. -const byKey = new Map(); - -for (const [index, row] of rows.entries()) byKey.set(`${row[1]}\u0000${row[2]}`, index); - -const fullOrder = shipped.getMunicipalities().map((municipality) => { - const index = byKey.get(`${municipality.name}\u0000${municipality.code}`); - - if (index === undefined) - throw new Error(`the full list holds ${municipality.name} but no state does`); - - return index; -}); - -if (fullOrder.length !== rows.length) - throw new Error(`the full list has ${fullOrder.length} rows but the states have ${rows.length}`); - -const dataset = { - doc: "Brazilian municipalities published by the IBGE, by state, in the pt-BR collation order the JavaScript package returns.", - columns, - rows, - groups, - fullOrder, -}; - -writeFileSync(resolve(bridge, "source/municipalities.data.json"), `${JSON.stringify(dataset)}\n`); - -console.log( - `municipalities: ${rows.length} rows, ${Object.keys(groups).length} groups, full order baked`, -); diff --git a/spec/bridge/source/cep.ts b/spec/bridge/source/cep.ts deleted file mode 100644 index 2543a11e4..000000000 --- a/spec/bridge/source/cep.ts +++ /dev/null @@ -1,318 +0,0 @@ -/** - * Address lookup by CEP, written once. - */ -import { - type HttpResponse, - anyFailedWith, - asString, - firstSuccess, - httpGet, - isList, - isNumber, - jsonIsTrue, - jsonInt, - jsonString, - jsonTruthy, - listHas, - startAll, -} from "./_std.ts"; - -/** Base class of every error `getAddressInfoByCep` rejects with. */ -export class GetAddressInfoByCepError extends Error {} - -/** Thrown by `getAddressInfoByCep` when the value given is not a valid CEP. */ -export class GetAddressInfoByCepValidationError extends GetAddressInfoByCepError {} - -/** Thrown by `getAddressInfoByCep` when no CEP service knows the CEP. */ -export class GetAddressInfoByCepNotFoundError extends GetAddressInfoByCepError {} - -/** Thrown by `getAddressInfoByCep` when every CEP service failed to answer. */ -export class GetAddressInfoByCepServiceError extends GetAddressInfoByCepError {} - -/** - * Raised inside a provider that did not answer. Only whether a failure was a not found is - * looked at when the provider failures are aggregated, so this one never leaves the module. - */ -class CepProviderFailure extends Error {} - -/** The address `getAddressInfoByCep` returns for a CEP. */ -export type AddressInfo = { - /** The 8 digit CEP, no mask. */ - cep: string; - /** Two letter state code, e.g. "SP". */ - state: string; - /** City name. */ - city: string; - /** Neighborhood name, empty when the CEP covers a whole city. */ - neighborhood: string; - /** Street name, empty when the CEP covers a whole city. */ - street: string; -}; - -/** The CEP services `getAddressInfoByCep` can query. */ -export type CepProvider = "viacep" | "widenet" | "brasilapi"; - -/** Options of `getAddressInfoByCep`. */ -export type GetAddressInfoByCepOptions = { - /** - * Which CEP services to race, in the order given (default: `["viacep", "brasilapi"]`; the - * deprecated `"widenet"` provider is excluded from the default list, but can still be - * requested explicitly). - */ - providers?: CepProvider[]; -}; - -const CEP_FORMAT = /^\d{8}$/; -const NON_DIGIT = /\D/g; - -/** The providers raced when the caller names none. */ -const DEFAULT_PROVIDERS: CepProvider[] = ["viacep", "brasilapi"]; - -/** Every provider that can be named, including the deprecated one. */ -const KNOWN_PROVIDERS: CepProvider[] = ["viacep", "widenet", "brasilapi"]; - -/** - * The status BrasilAPI answers an unknown CEP with, alongside an `errors` body. ViaCEP and - * Widenet report a miss inside a 200 body instead, so BrasilAPI is the only provider whose - * not-found signal is an HTTP status. - * - * @see Based on: https://brasilapi.com.br/docs#tag/CEP - */ -const BRASIL_API_NOT_FOUND_STATUS = 404; - -/** How many times a request is retried, and the base delay between attempts. */ -const HTTP_RETRIES = 2; -const HTTP_RETRY_DELAY_MS = 250; - -/** - * Reads the address ViaCEP answers with. - * - * @param {string} cep - The 8 digit CEP. - * @returns {AddressInfo} The address. - * - * @see Based on: https://viacep.com.br/ - */ -const fetchViaCep = (cep: string): AddressInfo => { - const response: HttpResponse = httpGet( - `https://viacep.com.br/ws/${cep}/json/`, - HTTP_RETRIES, - HTTP_RETRY_DELAY_MS, - ); - - if (!response.ok) { - throw new CepProviderFailure("ViaCEP request failed"); - } - - const found = jsonString(response.body, "cep"); - - if (jsonTruthy(response.body, "erro") || found === "") { - throw new GetAddressInfoByCepNotFoundError("CEP não encontrado"); - } - - return { - cep: found.replaceAll(NON_DIGIT, ""), - state: jsonString(response.body, "uf"), - city: jsonString(response.body, "localidade"), - neighborhood: jsonString(response.body, "bairro"), - street: jsonString(response.body, "logradouro"), - }; -}; - -/** - * Reads the address Widenet answers with. - * - * @param {string} cep - The 8 digit CEP. - * @returns {AddressInfo} The address. - */ -const fetchWidenet = (cep: string): AddressInfo => { - const response: HttpResponse = httpGet( - `https://apps.widenet.com.br/busca-cep/api/cep/${cep}.json`, - HTTP_RETRIES, - HTTP_RETRY_DELAY_MS, - ); - - if (!response.ok) { - throw new CepProviderFailure("Widenet request failed"); - } - - const found = jsonString(response.body, "code"); - - if ( - jsonInt(response.body, "status") !== 200 || - !jsonIsTrue(response.body, "ok") || - found === "" - ) { - throw new GetAddressInfoByCepNotFoundError("CEP não encontrado"); - } - - return { - cep: found.replaceAll(NON_DIGIT, ""), - state: jsonString(response.body, "state"), - city: jsonString(response.body, "city"), - neighborhood: jsonString(response.body, "district"), - street: jsonString(response.body, "address"), - }; -}; - -/** - * Reads the address BrasilAPI answers with. - * - * @param {string} cep - The 8 digit CEP. - * @returns {AddressInfo} The address. - * - * @see Based on: https://brasilapi.com.br/docs#tag/CEP - */ -const fetchBrasilApi = (cep: string): AddressInfo => { - const response: HttpResponse = httpGet( - `https://brasilapi.com.br/api/cep/v1/${cep}`, - HTTP_RETRIES, - HTTP_RETRY_DELAY_MS, - ); - - if (response.status === BRASIL_API_NOT_FOUND_STATUS) { - throw new GetAddressInfoByCepNotFoundError("CEP não encontrado"); - } - - if (!response.ok) { - throw new CepProviderFailure("BrasilAPI request failed"); - } - - const found = jsonString(response.body, "cep"); - - if (jsonTruthy(response.body, "errors") || found === "") { - throw new GetAddressInfoByCepNotFoundError("CEP não encontrado"); - } - - return { - cep: found.replaceAll(NON_DIGIT, ""), - state: jsonString(response.body, "state"), - city: jsonString(response.body, "city"), - neighborhood: jsonString(response.body, "neighborhood"), - street: jsonString(response.body, "street"), - }; -}; - -/** - * Asks one named provider for a CEP. - * - * @param {CepProvider} provider - The provider name. - * @param {string} cep - The 8 digit CEP. - * @returns {AddressInfo} The address. - */ -const fetchProvider = (provider: CepProvider, cep: string): AddressInfo => { - if (provider === "viacep") { - return fetchViaCep(cep); - } - - if (provider === "widenet") { - return fetchWidenet(cep); - } - - return fetchBrasilApi(cep); -}; - -/** - * The providers of a list that are known, in the order they were given. - * - * @param {CepProvider[]} given - The names the caller asked for. - * @returns {CepProvider[]} The known ones. - */ -const knownProviders = (given: CepProvider[]): CepProvider[] => { - const kept: CepProvider[] = []; - - for (const provider of given) { - if (listHas(KNOWN_PROVIDERS, provider)) { - kept.push(provider); - } - } - - return kept; -}; - -/** - * Fetches address information for a given CEP using multiple providers simultaneously. - * Returns the result from the first provider that responds successfully. - * - * The providers are started together and raced, not tried one after the other, so a provider - * that is retrying delays nothing for the others: its retries only push back the moment its own - * failure lands, and therefore the moment an all-failed rejection can surface. - * - * @param {string|number} cep - The CEP (Brazilian postal code) to search for. Can be a string or number. - * @param {GetAddressInfoByCepOptions} options - Optional configuration for the function. - * @param {CepProvider[]} options.providers - List of providers to use. Defaults to `["viacep", "brasilapi"]` - * if not specified (the deprecated `"widenet"` provider is excluded from the default list, but can still - * be requested explicitly). - * @returns {Promise} A promise that resolves to the address information. - * @throws {GetAddressInfoByCepValidationError} If the CEP format is invalid, or if - * `options.providers` is given and names no known provider: an empty array, an array of unknown - * names, and a value that is not an array at all (`null` included) all reject this way rather - * than with a raw `TypeError`. - * @throws {GetAddressInfoByCepNotFoundError} If the CEP is not found in any of the services. - * @throws {GetAddressInfoByCepServiceError} If all services are unavailable. - * - * @example - * ```typescript - * // Using the default providers (["viacep", "brasilapi"]) - * const address = await getAddressInfoByCep("01310100"); - * - * // Using specific providers - * const address = await getAddressInfoByCep("01310-100", { - * providers: ["viacep", "brasilapi"] - * }); - * - * // Using number input - * const address = await getAddressInfoByCep(1310100); - * ``` - * - * @see Official: https://www.correios.com.br/enviar/precisa-de-ajuda/tudo-sobre-cep - * @see Based on: https://viacep.com.br/ - * ViaCEP, one of the two default providers. A third-party service, not a Correios one. - * @see Based on: https://brasilapi.com.br/docs#tag/CEP - * BrasilAPI, the other default provider. A third-party service, not a Correios one. - */ -export const getAddressInfoByCep = ( - cep: string | number, - options?: GetAddressInfoByCepOptions, -): AddressInfo => { - let digits = asString(cep).replaceAll(NON_DIGIT, ""); - - if (isNumber(cep)) { - // `padStart` is a no-op when `digits` is already 8 characters or longer. - digits = digits.padStart(8, "0"); - } - - if (!CEP_FORMAT.test(digits)) { - throw new GetAddressInfoByCepValidationError("CEP inválido"); - } - - let chosen: CepProvider[] = DEFAULT_PROVIDERS; - - if (options?.providers !== undefined) { - // A value that is not a list at all reports the same thing as a list of unknown names, - // rather than the raw `TypeError` a filter over it would raise. - if (!isList(options?.providers)) { - throw new GetAddressInfoByCepValidationError("Nenhum provedor válido especificado"); - } - - chosen = knownProviders(options?.providers); - - if (chosen.length === 0) { - throw new GetAddressInfoByCepValidationError("Nenhum provedor válido especificado"); - } - } - - const attempts = startAll(fetchProvider, chosen, digits); - const found = firstSuccess(attempts); - - if (found !== undefined) { - return found; - } - - if (anyFailedWith(attempts, GetAddressInfoByCepNotFoundError)) { - throw new GetAddressInfoByCepNotFoundError("CEP não encontrado em nenhum serviço"); - } - - throw new GetAddressInfoByCepServiceError( - "Todos os serviços estão fora de serviço ou indisponíveis", - ); -}; diff --git a/spec/bridge/source/cnpj.ts b/spec/bridge/source/cnpj.ts deleted file mode 100644 index 37d2ff40f..000000000 --- a/spec/bridge/source/cnpj.ts +++ /dev/null @@ -1,211 +0,0 @@ -/** - * CNPJ, written once. - * - * This is ordinary TypeScript inside the portable subset the bridge accepts: annotated - * parameters and returns, regex literals it compiles rather than passes through, and the same - * boundary guards the handwritten package has. `spec/bridge/README.md` documents the subset; - * the compiler rejects anything outside it instead of guessing. - * - * @see Official: https://www.gov.br/receitafederal/pt-br/assuntos/orientacao-tributaria/cadastros/cnpj - * @see Official: https://www.gov.br/receitafederal/pt-br/centrais-de-conteudo/publicacoes/documentos-tecnicos/cnpj/manual-dv-cnpj.pdf - * @see Official: https://www.gov.br/receitafederal/pt-br/acesso-a-informacao/acoes-e-programas/programas-e-atividades/cnpj-alfanumerico - */ -import { asString, isTruthy } from "./_std.ts"; - -/** Options of `isValidCnpj`. */ -export type IsValidCnpjOptions = { - /** Which CNPJ format to accept: `1` numeric only, `2` alphanumeric (default: `1`). */ - version?: 1 | 2; -}; - -/** Options of `formatCnpj`. */ -export type FormatCnpjOptions = { - /** Whether to left pad the value with zeros up to the number of slots in the pattern (default: `false`). */ - pad?: boolean; - /** Which CNPJ format to read: `1` numeric only, `2` alphanumeric (default: `1`). */ - version?: 1 | 2; - /** Whether to hide the first 2 digits and the 2 check digits with `*` (default: `false`). */ - obfuscate?: boolean; -}; - -const FIRST_DIGIT_WEIGHTS = [5, 4, 3, 2, 9, 8, 7, 6, 5, 4, 3, 2]; -const SECOND_DIGIT_WEIGHTS = [6, 5, 4, 3, 2, 9, 8, 7, 6, 5, 4, 3, 2]; - -const PATTERN = "00.000.000/0000-00"; -const OBFUSCATED_PATTERN = "**.000.000/0000-**"; - -const ALPHANUMERIC_FORMAT = - /^[0-9A-Z]{2}[\s.\-/]*[0-9A-Z]{3}[\s.\-/]*[0-9A-Z]{3}[\s.\-/]*[0-9A-Z]{4}[\s.\-/]*[0-9]{2}$/; -const NUMERIC_FORMAT = /^\d{2}[\s.\-/]*\d{3}[\s.\-/]*\d{3}[\s.\-/]*\d{4}[\s.\-/]*\d{2}$/; -const LETTER = /[A-Z]/; -const NON_ALPHANUMERIC = /[^A-Za-z0-9]/g; -const NON_DIGIT = /\D/g; - -/** Computes one CNPJ check digit from the base and its weight vector. */ -const checkDigit = (base: string, weights: number[]): number => { - let sum = 0; - - for (let index = 0; index < weights.length; index++) { - sum += (base.charCodeAt(index) - 48) * weights[index]; - } - - const remainder = sum % 11; - - if (remainder < 2) { - return 0; - } - - return 11 - remainder; -}; - -/** Whether both check digits of a sanitized 14 character CNPJ match its base. */ -const hasValidChecksum = (cnpj: string): boolean => { - if (cnpj.charCodeAt(12) - 48 !== checkDigit(cnpj, FIRST_DIGIT_WEIGHTS)) { - return false; - } - - return cnpj.charCodeAt(13) - 48 === checkDigit(cnpj, SECOND_DIGIT_WEIGHTS); -}; - -/** Whether every character of the value is the same one. */ -const isRepeated = (value: string): boolean => { - if (value.length === 0) { - return false; - } - - for (let index = 1; index < value.length; index++) { - if (value.charCodeAt(index) !== value.charCodeAt(0)) { - return false; - } - } - - return true; -}; - -/** Lays a value over a pattern: `0` copies a character, `*` hides one, anything else separates. */ -const layout = (value: string, pattern: string, pad: boolean): string => { - let slots = 0; - - for (let index = 0; index < pattern.length; index++) { - if (pattern.charCodeAt(index) === 48 || pattern.charCodeAt(index) === 42) { - slots += 1; - } - } - - let padded = value; - - if (pad) { - padded = value.padStart(slots, "0"); - } - - let formatted = ""; - let cursor = 0; - - for (let index = 0; index < pattern.length; index++) { - const slot = pattern.charCodeAt(index); - - if (slot === 48 || slot === 42) { - if (cursor >= padded.length) { - return formatted; - } - - if (slot === 42) { - formatted += "*"; - } else { - formatted += padded.slice(cursor, cursor + 1); - } - - cursor += 1; - } else if (cursor < padded.length) { - formatted += pattern.slice(index, index + 1); - } - } - - return formatted; -}; - -/** - * Validates if a CNPJ (Cadastro Nacional da Pessoa Jurídica) is valid. - * - * Supports both numeric (version 1) and alphanumeric (version 2) CNPJ formats, and accepts the - * usual mask characters (`.`, `-`, `/`) and whitespace around and between groups. - * - * @param {string} cnpj - The CNPJ value to be validated. - * @param {IsValidCnpjOptions} [options] - Optional options. - * @returns {boolean} True if the CNPJ is valid, false otherwise. - * - * @example - * ```typescript - * isValidCnpj("12.345.678/0001-95"); // true - * isValidCnpj("q0slfmbd7vx439", { version: 2 }); // true - * isValidCnpj("00000000000000"); // false (reserved number) - * ``` - */ -export const isValidCnpj = (cnpj: string, options?: IsValidCnpjOptions): boolean => { - if (typeof cnpj !== "string") { - return false; - } - - const trimmed = cnpj.trim(); - - if (options?.version === 2) { - const cleaned = cnpj.replaceAll(NON_ALPHANUMERIC, "").toUpperCase(); - - if (LETTER.test(cleaned)) { - if (!ALPHANUMERIC_FORMAT.test(trimmed.toUpperCase())) { - return false; - } - - return hasValidChecksum(cleaned); - } - } - - const numeric = cnpj.replaceAll(NON_DIGIT, ""); - - if (!NUMERIC_FORMAT.test(trimmed)) { - return false; - } - - if (isRepeated(numeric)) { - return false; - } - - return hasValidChecksum(numeric); -}; - -/** - * Formats a given CNPJ (Cadastro Nacional da Pessoa Jurídica) value. - * - * @param {string} value - The CNPJ value to be formatted. - * @param {FormatCnpjOptions} [options] - Optional configuration for formatting the CNPJ. - * @returns {string} The formatted CNPJ string in the pattern "00.000.000/0000-00". - * - * @example - * ```typescript - * formatCnpj("12345678000195"); // "12.345.678/0001-95" - * formatCnpj("12345678", { pad: true }); // "00.000.012/3456-78" - * formatCnpj("q0SLFMBD7VX439", { version: 2 }); // "Q0.SLF.MBD/7VX4-39" - * formatCnpj("12345678000195", { obfuscate: true }); // "**.345.678/0001-**" - * ``` - */ -export const formatCnpj = (value: string | number, options?: FormatCnpjOptions): string => { - if (value === null || value === undefined) { - return ""; - } - - const text = asString(value); - - let cleaned = text.replaceAll(NON_DIGIT, ""); - - if (options?.version === 2) { - cleaned = text.replaceAll(NON_ALPHANUMERIC, "").toUpperCase(); - } - - let pattern = PATTERN; - - if (isTruthy(options?.obfuscate)) { - pattern = OBFUSCATED_PATTERN; - } - - return layout(cleaned, pattern, isTruthy(options?.pad)); -}; diff --git a/spec/bridge/source/municipalities.data.json b/spec/bridge/source/municipalities.data.json deleted file mode 100644 index 5e3a44875..000000000 --- a/spec/bridge/source/municipalities.data.json +++ /dev/null @@ -1 +0,0 @@ -{"doc":"Brazilian municipalities published by the IBGE, by state, in the pt-BR collation order the JavaScript package returns.","columns":["stateCode","name","code"],"rows":[["AC","Acrelândia","1200013"],["AC","Assis Brasil","1200054"],["AC","Brasiléia","1200104"],["AC","Bujari","1200138"],["AC","Capixaba","1200179"],["AC","Cruzeiro do Sul","1200203"],["AC","Epitaciolândia","1200252"],["AC","Feijó","1200302"],["AC","Jordão","1200328"],["AC","Mâncio Lima","1200336"],["AC","Manoel Urbano","1200344"],["AC","Marechal Thaumaturgo","1200351"],["AC","Plácido de Castro","1200385"],["AC","Porto Acre","1200807"],["AC","Porto Walter","1200393"],["AC","Rio Branco","1200401"],["AC","Rodrigues Alves","1200427"],["AC","Santa Rosa do Purus","1200435"],["AC","Sena Madureira","1200500"],["AC","Senador Guiomard","1200450"],["AC","Tarauacá","1200609"],["AC","Xapuri","1200708"],["AL","Água Branca","2700102"],["AL","Anadia","2700201"],["AL","Arapiraca","2700300"],["AL","Atalaia","2700409"],["AL","Barra de Santo Antônio","2700508"],["AL","Barra de São Miguel","2700607"],["AL","Batalha","2700706"],["AL","Belém","2700805"],["AL","Belo Monte","2700904"],["AL","Boca da Mata","2701001"],["AL","Branquinha","2701100"],["AL","Cacimbinhas","2701209"],["AL","Cajueiro","2701308"],["AL","Campestre","2701357"],["AL","Campo Alegre","2701407"],["AL","Campo Grande","2701506"],["AL","Canapi","2701605"],["AL","Capela","2701704"],["AL","Carneiros","2701803"],["AL","Chã Preta","2701902"],["AL","Coité do Nóia","2702009"],["AL","Colônia Leopoldina","2702108"],["AL","Coqueiro Seco","2702207"],["AL","Coruripe","2702306"],["AL","Craíbas","2702355"],["AL","Delmiro Gouveia","2702405"],["AL","Dois Riachos","2702504"],["AL","Estrela de Alagoas","2702553"],["AL","Feira Grande","2702603"],["AL","Feliz Deserto","2702702"],["AL","Flexeiras","2702801"],["AL","Girau do Ponciano","2702900"],["AL","Ibateguara","2703007"],["AL","Igaci","2703106"],["AL","Igreja Nova","2703205"],["AL","Inhapi","2703304"],["AL","Jacaré dos Homens","2703403"],["AL","Jacuípe","2703502"],["AL","Japaratinga","2703601"],["AL","Jaramataia","2703700"],["AL","Jequiá da Praia","2703759"],["AL","Joaquim Gomes","2703809"],["AL","Jundiá","2703908"],["AL","Junqueiro","2704005"],["AL","Lagoa da Canoa","2704104"],["AL","Limoeiro de Anadia","2704203"],["AL","Maceió","2704302"],["AL","Major Isidoro","2704401"],["AL","Mar Vermelho","2704906"],["AL","Maragogi","2704500"],["AL","Maravilha","2704609"],["AL","Marechal Deodoro","2704708"],["AL","Maribondo","2704807"],["AL","Mata Grande","2705002"],["AL","Matriz de Camaragibe","2705101"],["AL","Messias","2705200"],["AL","Minador do Negrão","2705309"],["AL","Monteirópolis","2705408"],["AL","Murici","2705507"],["AL","Novo Lino","2705606"],["AL","Olho d'Água das Flores","2705705"],["AL","Olho d'Água do Casado","2705804"],["AL","Olho d'Água Grande","2705903"],["AL","Olivença","2706000"],["AL","Ouro Branco","2706109"],["AL","Palestina","2706208"],["AL","Palmeira dos Índios","2706307"],["AL","Pão de Açúcar","2706406"],["AL","Pariconha","2706422"],["AL","Paripueira","2706448"],["AL","Passo de Camaragibe","2706505"],["AL","Paulo Jacinto","2706604"],["AL","Penedo","2706703"],["AL","Piaçabuçu","2706802"],["AL","Pilar","2706901"],["AL","Pindoba","2707008"],["AL","Piranhas","2707107"],["AL","Poço das Trincheiras","2707206"],["AL","Porto Calvo","2707305"],["AL","Porto de Pedras","2707404"],["AL","Porto Real do Colégio","2707503"],["AL","Quebrangulo","2707602"],["AL","Rio Largo","2707701"],["AL","Roteiro","2707800"],["AL","Santa Luzia do Norte","2707909"],["AL","Santana do Ipanema","2708006"],["AL","Santana do Mundaú","2708105"],["AL","São Brás","2708204"],["AL","São José da Laje","2708303"],["AL","São José da Tapera","2708402"],["AL","São Luís do Quitunde","2708501"],["AL","São Miguel dos Campos","2708600"],["AL","São Miguel dos Milagres","2708709"],["AL","São Sebastião","2708808"],["AL","Satuba","2708907"],["AL","Senador Rui Palmeira","2708956"],["AL","Tanque d'Arca","2709004"],["AL","Taquarana","2709103"],["AL","Teotônio Vilela","2709152"],["AL","Traipu","2709202"],["AL","União dos Palmares","2709301"],["AL","Viçosa","2709400"],["AP","Amapá","1600105"],["AP","Calçoene","1600204"],["AP","Cutias","1600212"],["AP","Ferreira Gomes","1600238"],["AP","Itaubal","1600253"],["AP","Laranjal do Jari","1600279"],["AP","Macapá","1600303"],["AP","Mazagão","1600402"],["AP","Oiapoque","1600501"],["AP","Pedra Branca do Amapari","1600154"],["AP","Porto Grande","1600535"],["AP","Pracuúba","1600550"],["AP","Santana","1600600"],["AP","Serra do Navio","1600055"],["AP","Tartarugalzinho","1600709"],["AP","Vitória do Jari","1600808"],["AM","Alvarães","1300029"],["AM","Amaturá","1300060"],["AM","Anamã","1300086"],["AM","Anori","1300102"],["AM","Apuí","1300144"],["AM","Atalaia do Norte","1300201"],["AM","Autazes","1300300"],["AM","Barcelos","1300409"],["AM","Barreirinha","1300508"],["AM","Benjamin Constant","1300607"],["AM","Beruri","1300631"],["AM","Boa Vista do Ramos","1300680"],["AM","Boca do Acre","1300706"],["AM","Borba","1300805"],["AM","Caapiranga","1300839"],["AM","Canutama","1300904"],["AM","Carauari","1301001"],["AM","Careiro","1301100"],["AM","Careiro da Várzea","1301159"],["AM","Coari","1301209"],["AM","Codajás","1301308"],["AM","Eirunepé","1301407"],["AM","Envira","1301506"],["AM","Fonte Boa","1301605"],["AM","Guajará","1301654"],["AM","Humaitá","1301704"],["AM","Ipixuna","1301803"],["AM","Iranduba","1301852"],["AM","Itacoatiara","1301902"],["AM","Itamarati","1301951"],["AM","Itapiranga","1302009"],["AM","Japurá","1302108"],["AM","Juruá","1302207"],["AM","Jutaí","1302306"],["AM","Lábrea","1302405"],["AM","Manacapuru","1302504"],["AM","Manaquiri","1302553"],["AM","Manaus","1302603"],["AM","Manicoré","1302702"],["AM","Maraã","1302801"],["AM","Maués","1302900"],["AM","Nhamundá","1303007"],["AM","Nova Olinda do Norte","1303106"],["AM","Novo Airão","1303205"],["AM","Novo Aripuanã","1303304"],["AM","Parintins","1303403"],["AM","Pauini","1303502"],["AM","Presidente Figueiredo","1303536"],["AM","Rio Preto da Eva","1303569"],["AM","Santa Isabel do Rio Negro","1303601"],["AM","Santo Antônio do Içá","1303700"],["AM","São Gabriel da Cachoeira","1303809"],["AM","São Paulo de Olivença","1303908"],["AM","São Sebastião do Uatumã","1303957"],["AM","Silves","1304005"],["AM","Tabatinga","1304062"],["AM","Tapauá","1304104"],["AM","Tefé","1304203"],["AM","Tonantins","1304237"],["AM","Uarini","1304260"],["AM","Urucará","1304302"],["AM","Urucurituba","1304401"],["BA","Abaíra","2900108"],["BA","Abaré","2900207"],["BA","Acajutiba","2900306"],["BA","Adustina","2900355"],["BA","Água Fria","2900405"],["BA","Aiquara","2900603"],["BA","Alagoinhas","2900702"],["BA","Alcobaça","2900801"],["BA","Almadina","2900900"],["BA","Amargosa","2901007"],["BA","Amélia Rodrigues","2901106"],["BA","América Dourada","2901155"],["BA","Anagé","2901205"],["BA","Andaraí","2901304"],["BA","Andorinha","2901353"],["BA","Angical","2901403"],["BA","Anguera","2901502"],["BA","Antas","2901601"],["BA","Antônio Cardoso","2901700"],["BA","Antônio Gonçalves","2901809"],["BA","Aporá","2901908"],["BA","Apuarema","2901957"],["BA","Araçás","2902054"],["BA","Aracatu","2902005"],["BA","Araci","2902104"],["BA","Aramari","2902203"],["BA","Arataca","2902252"],["BA","Aratuípe","2902302"],["BA","Aurelino Leal","2902401"],["BA","Baianópolis","2902500"],["BA","Baixa Grande","2902609"],["BA","Banzaê","2902658"],["BA","Barra","2902708"],["BA","Barra da Estiva","2902807"],["BA","Barra do Choça","2902906"],["BA","Barra do Mendes","2903003"],["BA","Barra do Rocha","2903102"],["BA","Barreiras","2903201"],["BA","Barro Alto","2903235"],["BA","Barro Preto","2903300"],["BA","Barrocas","2903276"],["BA","Belmonte","2903409"],["BA","Belo Campo","2903508"],["BA","Biritinga","2903607"],["BA","Boa Nova","2903706"],["BA","Boa Vista do Tupim","2903805"],["BA","Bom Jesus da Lapa","2903904"],["BA","Bom Jesus da Serra","2903953"],["BA","Boninal","2904001"],["BA","Bonito","2904050"],["BA","Boquira","2904100"],["BA","Botuporã","2904209"],["BA","Brejões","2904308"],["BA","Brejolândia","2904407"],["BA","Brotas de Macaúbas","2904506"],["BA","Brumado","2904605"],["BA","Buerarema","2904704"],["BA","Buritirama","2904753"],["BA","Caatiba","2904803"],["BA","Cabaceiras do Paraguaçu","2904852"],["BA","Cachoeira","2904902"],["BA","Caculé","2905008"],["BA","Caém","2905107"],["BA","Caetanos","2905156"],["BA","Caetité","2905206"],["BA","Cafarnaum","2905305"],["BA","Cairu","2905404"],["BA","Caldeirão Grande","2905503"],["BA","Camacan","2905602"],["BA","Camaçari","2905701"],["BA","Camamu","2905800"],["BA","Campo Alegre de Lourdes","2905909"],["BA","Campo Formoso","2906006"],["BA","Canápolis","2906105"],["BA","Canarana","2906204"],["BA","Canavieiras","2906303"],["BA","Candeal","2906402"],["BA","Candeias","2906501"],["BA","Candiba","2906600"],["BA","Cândido Sales","2906709"],["BA","Cansanção","2906808"],["BA","Canudos","2906824"],["BA","Capela do Alto Alegre","2906857"],["BA","Capim Grosso","2906873"],["BA","Caraíbas","2906899"],["BA","Caravelas","2906907"],["BA","Cardeal da Silva","2907004"],["BA","Carinhanha","2907103"],["BA","Casa Nova","2907202"],["BA","Castro Alves","2907301"],["BA","Catolândia","2907400"],["BA","Catu","2907509"],["BA","Caturama","2907558"],["BA","Central","2907608"],["BA","Chorrochó","2907707"],["BA","Cícero Dantas","2907806"],["BA","Cipó","2907905"],["BA","Coaraci","2908002"],["BA","Cocos","2908101"],["BA","Conceição da Feira","2908200"],["BA","Conceição do Almeida","2908309"],["BA","Conceição do Coité","2908408"],["BA","Conceição do Jacuípe","2908507"],["BA","Conde","2908606"],["BA","Condeúba","2908705"],["BA","Contendas do Sincorá","2908804"],["BA","Coração de Maria","2908903"],["BA","Cordeiros","2909000"],["BA","Coribe","2909109"],["BA","Coronel João Sá","2909208"],["BA","Correntina","2909307"],["BA","Cotegipe","2909406"],["BA","Cravolândia","2909505"],["BA","Crisópolis","2909604"],["BA","Cristópolis","2909703"],["BA","Cruz das Almas","2909802"],["BA","Curaçá","2909901"],["BA","Dário Meira","2910008"],["BA","Dias d'Ávila","2910057"],["BA","Dom Basílio","2910107"],["BA","Dom Macedo Costa","2910206"],["BA","Elísio Medrado","2910305"],["BA","Encruzilhada","2910404"],["BA","Entre Rios","2910503"],["BA","Érico Cardoso","2900504"],["BA","Esplanada","2910602"],["BA","Euclides da Cunha","2910701"],["BA","Eunápolis","2910727"],["BA","Fátima","2910750"],["BA","Feira da Mata","2910776"],["BA","Feira de Santana","2910800"],["BA","Filadélfia","2910859"],["BA","Firmino Alves","2910909"],["BA","Floresta Azul","2911006"],["BA","Formosa do Rio Preto","2911105"],["BA","Gandu","2911204"],["BA","Gavião","2911253"],["BA","Gentio do Ouro","2911303"],["BA","Glória","2911402"],["BA","Gongogi","2911501"],["BA","Governador Mangabeira","2911600"],["BA","Guajeru","2911659"],["BA","Guanambi","2911709"],["BA","Guaratinga","2911808"],["BA","Heliópolis","2911857"],["BA","Iaçu","2911907"],["BA","Ibiassucê","2912004"],["BA","Ibicaraí","2912103"],["BA","Ibicoara","2912202"],["BA","Ibicuí","2912301"],["BA","Ibipeba","2912400"],["BA","Ibipitanga","2912509"],["BA","Ibiquera","2912608"],["BA","Ibirapitanga","2912707"],["BA","Ibirapuã","2912806"],["BA","Ibirataia","2912905"],["BA","Ibitiara","2913002"],["BA","Ibititá","2913101"],["BA","Ibotirama","2913200"],["BA","Ichu","2913309"],["BA","Igaporã","2913408"],["BA","Igrapiúna","2913457"],["BA","Iguaí","2913507"],["BA","Ilhéus","2913606"],["BA","Inhambupe","2913705"],["BA","Ipecaetá","2913804"],["BA","Ipiaú","2913903"],["BA","Ipirá","2914000"],["BA","Ipupiara","2914109"],["BA","Irajuba","2914208"],["BA","Iramaia","2914307"],["BA","Iraquara","2914406"],["BA","Irará","2914505"],["BA","Irecê","2914604"],["BA","Itabela","2914653"],["BA","Itaberaba","2914703"],["BA","Itabuna","2914802"],["BA","Itacaré","2914901"],["BA","Itaeté","2915007"],["BA","Itagi","2915106"],["BA","Itagibá","2915205"],["BA","Itagimirim","2915304"],["BA","Itaguaçu da Bahia","2915353"],["BA","Itaju do Colônia","2915403"],["BA","Itajuípe","2915502"],["BA","Itamaraju","2915601"],["BA","Itamari","2915700"],["BA","Itambé","2915809"],["BA","Itanagra","2915908"],["BA","Itanhém","2916005"],["BA","Itaparica","2916104"],["BA","Itapé","2916203"],["BA","Itapebi","2916302"],["BA","Itapetinga","2916401"],["BA","Itapicuru","2916500"],["BA","Itapitanga","2916609"],["BA","Itaquara","2916708"],["BA","Itarantim","2916807"],["BA","Itatim","2916856"],["BA","Itiruçu","2916906"],["BA","Itiúba","2917003"],["BA","Itororó","2917102"],["BA","Ituaçu","2917201"],["BA","Ituberá","2917300"],["BA","Iuiu","2917334"],["BA","Jaborandi","2917359"],["BA","Jacaraci","2917409"],["BA","Jacobina","2917508"],["BA","Jaguaquara","2917607"],["BA","Jaguarari","2917706"],["BA","Jaguaripe","2917805"],["BA","Jandaíra","2917904"],["BA","Jequié","2918001"],["BA","Jeremoabo","2918100"],["BA","Jiquiriçá","2918209"],["BA","Jitaúna","2918308"],["BA","João Dourado","2918357"],["BA","Juazeiro","2918407"],["BA","Jucuruçu","2918456"],["BA","Jussara","2918506"],["BA","Jussari","2918555"],["BA","Jussiape","2918605"],["BA","Lafaiete Coutinho","2918704"],["BA","Lagoa Real","2918753"],["BA","Laje","2918803"],["BA","Lajedão","2918902"],["BA","Lajedinho","2919009"],["BA","Lajedo do Tabocal","2919058"],["BA","Lamarão","2919108"],["BA","Lapão","2919157"],["BA","Lauro de Freitas","2919207"],["BA","Lençóis","2919306"],["BA","Licínio de Almeida","2919405"],["BA","Livramento de Nossa Senhora","2919504"],["BA","Luís Eduardo Magalhães","2919553"],["BA","Macajuba","2919603"],["BA","Macarani","2919702"],["BA","Macaúbas","2919801"],["BA","Macururé","2919900"],["BA","Madre de Deus","2919926"],["BA","Maetinga","2919959"],["BA","Maiquinique","2920007"],["BA","Mairi","2920106"],["BA","Malhada","2920205"],["BA","Malhada de Pedras","2920304"],["BA","Manoel Vitorino","2920403"],["BA","Mansidão","2920452"],["BA","Maracás","2920502"],["BA","Maragogipe","2920601"],["BA","Maraú","2920700"],["BA","Marcionílio Souza","2920809"],["BA","Mascote","2920908"],["BA","Mata de São João","2921005"],["BA","Matina","2921054"],["BA","Medeiros Neto","2921104"],["BA","Miguel Calmon","2921203"],["BA","Milagres","2921302"],["BA","Mirangaba","2921401"],["BA","Mirante","2921450"],["BA","Monte Santo","2921500"],["BA","Morpará","2921609"],["BA","Morro do Chapéu","2921708"],["BA","Mortugaba","2921807"],["BA","Mucugê","2921906"],["BA","Mucuri","2922003"],["BA","Mulungu do Morro","2922052"],["BA","Mundo Novo","2922102"],["BA","Muniz Ferreira","2922201"],["BA","Muquém do São Francisco","2922250"],["BA","Muritiba","2922300"],["BA","Mutuípe","2922409"],["BA","Nazaré","2922508"],["BA","Nilo Peçanha","2922607"],["BA","Nordestina","2922656"],["BA","Nova Canaã","2922706"],["BA","Nova Fátima","2922730"],["BA","Nova Ibiá","2922755"],["BA","Nova Itarana","2922805"],["BA","Nova Redenção","2922854"],["BA","Nova Soure","2922904"],["BA","Nova Viçosa","2923001"],["BA","Novo Horizonte","2923035"],["BA","Novo Triunfo","2923050"],["BA","Olindina","2923100"],["BA","Oliveira dos Brejinhos","2923209"],["BA","Ouriçangas","2923308"],["BA","Ourolândia","2923357"],["BA","Palmas de Monte Alto","2923407"],["BA","Palmeiras","2923506"],["BA","Paramirim","2923605"],["BA","Paratinga","2923704"],["BA","Paripiranga","2923803"],["BA","Pau Brasil","2923902"],["BA","Paulo Afonso","2924009"],["BA","Pé de Serra","2924058"],["BA","Pedrão","2924108"],["BA","Pedro Alexandre","2924207"],["BA","Piatã","2924306"],["BA","Pilão Arcado","2924405"],["BA","Pindaí","2924504"],["BA","Pindobaçu","2924603"],["BA","Pintadas","2924652"],["BA","Piraí do Norte","2924678"],["BA","Piripá","2924702"],["BA","Piritiba","2924801"],["BA","Planaltino","2924900"],["BA","Planalto","2925006"],["BA","Poções","2925105"],["BA","Pojuca","2925204"],["BA","Ponto Novo","2925253"],["BA","Porto Seguro","2925303"],["BA","Potiraguá","2925402"],["BA","Prado","2925501"],["BA","Presidente Dutra","2925600"],["BA","Presidente Jânio Quadros","2925709"],["BA","Presidente Tancredo Neves","2925758"],["BA","Queimadas","2925808"],["BA","Quijingue","2925907"],["BA","Quixabeira","2925931"],["BA","Rafael Jambeiro","2925956"],["BA","Remanso","2926004"],["BA","Retirolândia","2926103"],["BA","Riachão das Neves","2926202"],["BA","Riachão do Jacuípe","2926301"],["BA","Riacho de Santana","2926400"],["BA","Ribeira do Amparo","2926509"],["BA","Ribeira do Pombal","2926608"],["BA","Ribeirão do Largo","2926657"],["BA","Rio de Contas","2926707"],["BA","Rio do Antônio","2926806"],["BA","Rio do Pires","2926905"],["BA","Rio Real","2927002"],["BA","Rodelas","2927101"],["BA","Ruy Barbosa","2927200"],["BA","Salinas da Margarida","2927309"],["BA","Salvador","2927408"],["BA","Santa Bárbara","2927507"],["BA","Santa Brígida","2927606"],["BA","Santa Cruz Cabrália","2927705"],["BA","Santa Cruz da Vitória","2927804"],["BA","Santa Inês","2927903"],["BA","Santa Luzia","2928059"],["BA","Santa Maria da Vitória","2928109"],["BA","Santa Rita de Cássia","2928406"],["BA","Santa Terezinha","2928505"],["BA","Santaluz","2928000"],["BA","Santana","2928208"],["BA","Santanópolis","2928307"],["BA","Santo Amaro","2928604"],["BA","Santo Antônio de Jesus","2928703"],["BA","Santo Estêvão","2928802"],["BA","São Desidério","2928901"],["BA","São Domingos","2928950"],["BA","São Felipe","2929107"],["BA","São Félix","2929008"],["BA","São Félix do Coribe","2929057"],["BA","São Francisco do Conde","2929206"],["BA","São Gabriel","2929255"],["BA","São Gonçalo dos Campos","2929305"],["BA","São José da Vitória","2929354"],["BA","São José do Jacuípe","2929370"],["BA","São Miguel das Matas","2929404"],["BA","São Sebastião do Passé","2929503"],["BA","Sapeaçu","2929602"],["BA","Sátiro Dias","2929701"],["BA","Saubara","2929750"],["BA","Saúde","2929800"],["BA","Seabra","2929909"],["BA","Sebastião Laranjeiras","2930006"],["BA","Senhor do Bonfim","2930105"],["BA","Sento Sé","2930204"],["BA","Serra do Ramalho","2930154"],["BA","Serra Dourada","2930303"],["BA","Serra Preta","2930402"],["BA","Serrinha","2930501"],["BA","Serrolândia","2930600"],["BA","Simões Filho","2930709"],["BA","Sítio do Mato","2930758"],["BA","Sítio do Quinto","2930766"],["BA","Sobradinho","2930774"],["BA","Souto Soares","2930808"],["BA","Tabocas do Brejo Velho","2930907"],["BA","Tanhaçu","2931004"],["BA","Tanque Novo","2931053"],["BA","Tanquinho","2931103"],["BA","Taperoá","2931202"],["BA","Tapiramutá","2931301"],["BA","Teixeira de Freitas","2931350"],["BA","Teodoro Sampaio","2931400"],["BA","Teofilândia","2931509"],["BA","Teolândia","2931608"],["BA","Terra Nova","2931707"],["BA","Tremedal","2931806"],["BA","Tucano","2931905"],["BA","Uauá","2932002"],["BA","Ubaíra","2932101"],["BA","Ubaitaba","2932200"],["BA","Ubatã","2932309"],["BA","Uibaí","2932408"],["BA","Umburanas","2932457"],["BA","Una","2932507"],["BA","Urandi","2932606"],["BA","Uruçuca","2932705"],["BA","Utinga","2932804"],["BA","Valença","2932903"],["BA","Valente","2933000"],["BA","Várzea da Roça","2933059"],["BA","Várzea do Poço","2933109"],["BA","Várzea Nova","2933158"],["BA","Varzedo","2933174"],["BA","Vera Cruz","2933208"],["BA","Vereda","2933257"],["BA","Vitória da Conquista","2933307"],["BA","Wagner","2933406"],["BA","Wanderley","2933455"],["BA","Wenceslau Guimarães","2933505"],["BA","Xique-Xique","2933604"],["CE","Abaiara","2300101"],["CE","Acarape","2300150"],["CE","Acaraú","2300200"],["CE","Acopiara","2300309"],["CE","Aiuaba","2300408"],["CE","Alcântaras","2300507"],["CE","Altaneira","2300606"],["CE","Alto Santo","2300705"],["CE","Amontada","2300754"],["CE","Antonina do Norte","2300804"],["CE","Apuiarés","2300903"],["CE","Aquiraz","2301000"],["CE","Aracati","2301109"],["CE","Aracoiaba","2301208"],["CE","Ararendá","2301257"],["CE","Araripe","2301307"],["CE","Aratuba","2301406"],["CE","Arneiroz","2301505"],["CE","Assaré","2301604"],["CE","Aurora","2301703"],["CE","Baixio","2301802"],["CE","Banabuiú","2301851"],["CE","Barbalha","2301901"],["CE","Barreira","2301950"],["CE","Barro","2302008"],["CE","Barroquinha","2302057"],["CE","Baturité","2302107"],["CE","Beberibe","2302206"],["CE","Bela Cruz","2302305"],["CE","Boa Viagem","2302404"],["CE","Brejo Santo","2302503"],["CE","Camocim","2302602"],["CE","Campos Sales","2302701"],["CE","Canindé","2302800"],["CE","Capistrano","2302909"],["CE","Caridade","2303006"],["CE","Cariré","2303105"],["CE","Caririaçu","2303204"],["CE","Cariús","2303303"],["CE","Carnaubal","2303402"],["CE","Cascavel","2303501"],["CE","Catarina","2303600"],["CE","Catunda","2303659"],["CE","Caucaia","2303709"],["CE","Cedro","2303808"],["CE","Chaval","2303907"],["CE","Choró","2303931"],["CE","Chorozinho","2303956"],["CE","Coreaú","2304004"],["CE","Crateús","2304103"],["CE","Crato","2304202"],["CE","Croatá","2304236"],["CE","Cruz","2304251"],["CE","Deputado Irapuan Pinheiro","2304269"],["CE","Ereré","2304277"],["CE","Eusébio","2304285"],["CE","Farias Brito","2304301"],["CE","Forquilha","2304350"],["CE","Fortaleza","2304400"],["CE","Fortim","2304459"],["CE","Frecheirinha","2304509"],["CE","General Sampaio","2304608"],["CE","Graça","2304657"],["CE","Granja","2304707"],["CE","Granjeiro","2304806"],["CE","Groaíras","2304905"],["CE","Guaiúba","2304954"],["CE","Guaraciaba do Norte","2305001"],["CE","Guaramiranga","2305100"],["CE","Hidrolândia","2305209"],["CE","Horizonte","2305233"],["CE","Ibaretama","2305266"],["CE","Ibiapina","2305308"],["CE","Ibicuitinga","2305332"],["CE","Icapuí","2305357"],["CE","Icó","2305407"],["CE","Iguatu","2305506"],["CE","Independência","2305605"],["CE","Ipaporanga","2305654"],["CE","Ipaumirim","2305704"],["CE","Ipu","2305803"],["CE","Ipueiras","2305902"],["CE","Iracema","2306009"],["CE","Irauçuba","2306108"],["CE","Itaiçaba","2306207"],["CE","Itaitinga","2306256"],["CE","Itapajé","2306306"],["CE","Itapipoca","2306405"],["CE","Itapiúna","2306504"],["CE","Itarema","2306553"],["CE","Itatira","2306603"],["CE","Jaguaretama","2306702"],["CE","Jaguaribara","2306801"],["CE","Jaguaribe","2306900"],["CE","Jaguaruana","2307007"],["CE","Jardim","2307106"],["CE","Jati","2307205"],["CE","Jijoca de Jericoacoara","2307254"],["CE","Juazeiro do Norte","2307304"],["CE","Jucás","2307403"],["CE","Lavras da Mangabeira","2307502"],["CE","Limoeiro do Norte","2307601"],["CE","Madalena","2307635"],["CE","Maracanaú","2307650"],["CE","Maranguape","2307700"],["CE","Marco","2307809"],["CE","Martinópole","2307908"],["CE","Massapê","2308005"],["CE","Mauriti","2308104"],["CE","Meruoca","2308203"],["CE","Milagres","2308302"],["CE","Milhã","2308351"],["CE","Miraíma","2308377"],["CE","Missão Velha","2308401"],["CE","Mombaça","2308500"],["CE","Monsenhor Tabosa","2308609"],["CE","Morada Nova","2308708"],["CE","Moraújo","2308807"],["CE","Morrinhos","2308906"],["CE","Mucambo","2309003"],["CE","Mulungu","2309102"],["CE","Nova Olinda","2309201"],["CE","Nova Russas","2309300"],["CE","Novo Oriente","2309409"],["CE","Ocara","2309458"],["CE","Orós","2309508"],["CE","Pacajus","2309607"],["CE","Pacatuba","2309706"],["CE","Pacoti","2309805"],["CE","Pacujá","2309904"],["CE","Palhano","2310001"],["CE","Palmácia","2310100"],["CE","Paracuru","2310209"],["CE","Paraipaba","2310258"],["CE","Parambu","2310308"],["CE","Paramoti","2310407"],["CE","Pedra Branca","2310506"],["CE","Penaforte","2310605"],["CE","Pentecoste","2310704"],["CE","Pereiro","2310803"],["CE","Pindoretama","2310852"],["CE","Piquet Carneiro","2310902"],["CE","Pires Ferreira","2310951"],["CE","Poranga","2311009"],["CE","Porteiras","2311108"],["CE","Potengi","2311207"],["CE","Potiretama","2311231"],["CE","Quiterianópolis","2311264"],["CE","Quixadá","2311306"],["CE","Quixelô","2311355"],["CE","Quixeramobim","2311405"],["CE","Quixeré","2311504"],["CE","Redenção","2311603"],["CE","Reriutaba","2311702"],["CE","Russas","2311801"],["CE","Saboeiro","2311900"],["CE","Salitre","2311959"],["CE","Santa Quitéria","2312205"],["CE","Santana do Acaraú","2312007"],["CE","Santana do Cariri","2312106"],["CE","São Benedito","2312304"],["CE","São Gonçalo do Amarante","2312403"],["CE","São João do Jaguaribe","2312502"],["CE","São Luís do Curu","2312601"],["CE","Senador Pompeu","2312700"],["CE","Senador Sá","2312809"],["CE","Sobral","2312908"],["CE","Solonópole","2313005"],["CE","Tabuleiro do Norte","2313104"],["CE","Tamboril","2313203"],["CE","Tarrafas","2313252"],["CE","Tauá","2313302"],["CE","Tejuçuoca","2313351"],["CE","Tianguá","2313401"],["CE","Trairi","2313500"],["CE","Tururu","2313559"],["CE","Ubajara","2313609"],["CE","Umari","2313708"],["CE","Umirim","2313757"],["CE","Uruburetama","2313807"],["CE","Uruoca","2313906"],["CE","Varjota","2313955"],["CE","Várzea Alegre","2314003"],["CE","Viçosa do Ceará","2314102"],["DF","Brasília","5300108"],["ES","Afonso Cláudio","3200102"],["ES","Água Doce do Norte","3200169"],["ES","Águia Branca","3200136"],["ES","Alegre","3200201"],["ES","Alfredo Chaves","3200300"],["ES","Alto Rio Novo","3200359"],["ES","Anchieta","3200409"],["ES","Apiacá","3200508"],["ES","Aracruz","3200607"],["ES","Atílio Vivácqua","3200706"],["ES","Baixo Guandu","3200805"],["ES","Barra de São Francisco","3200904"],["ES","Boa Esperança","3201001"],["ES","Bom Jesus do Norte","3201100"],["ES","Brejetuba","3201159"],["ES","Cachoeiro de Itapemirim","3201209"],["ES","Cariacica","3201308"],["ES","Castelo","3201407"],["ES","Colatina","3201506"],["ES","Conceição da Barra","3201605"],["ES","Conceição do Castelo","3201704"],["ES","Divino de São Lourenço","3201803"],["ES","Domingos Martins","3201902"],["ES","Dores do Rio Preto","3202009"],["ES","Ecoporanga","3202108"],["ES","Fundão","3202207"],["ES","Governador Lindenberg","3202256"],["ES","Guaçuí","3202306"],["ES","Guarapari","3202405"],["ES","Ibatiba","3202454"],["ES","Ibiraçu","3202504"],["ES","Ibitirama","3202553"],["ES","Iconha","3202603"],["ES","Irupi","3202652"],["ES","Itaguaçu","3202702"],["ES","Itapemirim","3202801"],["ES","Itarana","3202900"],["ES","Iúna","3203007"],["ES","Jaguaré","3203056"],["ES","Jerônimo Monteiro","3203106"],["ES","João Neiva","3203130"],["ES","Laranja da Terra","3203163"],["ES","Linhares","3203205"],["ES","Mantenópolis","3203304"],["ES","Marataízes","3203320"],["ES","Marechal Floriano","3203346"],["ES","Marilândia","3203353"],["ES","Mimoso do Sul","3203403"],["ES","Montanha","3203502"],["ES","Mucurici","3203601"],["ES","Muniz Freire","3203700"],["ES","Muqui","3203809"],["ES","Nova Venécia","3203908"],["ES","Pancas","3204005"],["ES","Pedro Canário","3204054"],["ES","Pinheiros","3204104"],["ES","Piúma","3204203"],["ES","Ponto Belo","3204252"],["ES","Presidente Kennedy","3204302"],["ES","Rio Bananal","3204351"],["ES","Rio Novo do Sul","3204401"],["ES","Santa Leopoldina","3204500"],["ES","Santa Maria de Jetibá","3204559"],["ES","Santa Teresa","3204609"],["ES","São Domingos do Norte","3204658"],["ES","São Gabriel da Palha","3204708"],["ES","São José do Calçado","3204807"],["ES","São Mateus","3204906"],["ES","São Roque do Canaã","3204955"],["ES","Serra","3205002"],["ES","Sooretama","3205010"],["ES","Vargem Alta","3205036"],["ES","Venda Nova do Imigrante","3205069"],["ES","Viana","3205101"],["ES","Vila Pavão","3205150"],["ES","Vila Valério","3205176"],["ES","Vila Velha","3205200"],["ES","Vitória","3205309"],["GO","Abadia de Goiás","5200050"],["GO","Abadiânia","5200100"],["GO","Acreúna","5200134"],["GO","Adelândia","5200159"],["GO","Água Fria de Goiás","5200175"],["GO","Água Limpa","5200209"],["GO","Águas Lindas de Goiás","5200258"],["GO","Alexânia","5200308"],["GO","Aloândia","5200506"],["GO","Alto Horizonte","5200555"],["GO","Alto Paraíso de Goiás","5200605"],["GO","Alvorada do Norte","5200803"],["GO","Amaralina","5200829"],["GO","Americano do Brasil","5200852"],["GO","Amorinópolis","5200902"],["GO","Anápolis","5201108"],["GO","Anhanguera","5201207"],["GO","Anicuns","5201306"],["GO","Aparecida de Goiânia","5201405"],["GO","Aparecida do Rio Doce","5201454"],["GO","Aporé","5201504"],["GO","Araçu","5201603"],["GO","Aragarças","5201702"],["GO","Aragoiânia","5201801"],["GO","Araguapaz","5202155"],["GO","Arenópolis","5202353"],["GO","Aruanã","5202502"],["GO","Aurilândia","5202601"],["GO","Avelinópolis","5202809"],["GO","Baliza","5203104"],["GO","Barro Alto","5203203"],["GO","Bela Vista de Goiás","5203302"],["GO","Bom Jardim de Goiás","5203401"],["GO","Bom Jesus de Goiás","5203500"],["GO","Bonfinópolis","5203559"],["GO","Bonópolis","5203575"],["GO","Brazabrantes","5203609"],["GO","Britânia","5203807"],["GO","Buriti Alegre","5203906"],["GO","Buriti de Goiás","5203939"],["GO","Buritinópolis","5203962"],["GO","Cabeceiras","5204003"],["GO","Cachoeira Alta","5204102"],["GO","Cachoeira de Goiás","5204201"],["GO","Cachoeira Dourada","5204250"],["GO","Caçu","5204300"],["GO","Caiapônia","5204409"],["GO","Caldas Novas","5204508"],["GO","Caldazinha","5204557"],["GO","Campestre de Goiás","5204607"],["GO","Campinaçu","5204656"],["GO","Campinorte","5204706"],["GO","Campo Alegre de Goiás","5204805"],["GO","Campo Limpo de Goiás","5204854"],["GO","Campos Belos","5204904"],["GO","Campos Verdes","5204953"],["GO","Carmo do Rio Verde","5205000"],["GO","Castelândia","5205059"],["GO","Catalão","5205109"],["GO","Caturaí","5205208"],["GO","Cavalcante","5205307"],["GO","Ceres","5205406"],["GO","Cezarina","5205455"],["GO","Chapadão do Céu","5205471"],["GO","Cidade Ocidental","5205497"],["GO","Cocalzinho de Goiás","5205513"],["GO","Colinas do Sul","5205521"],["GO","Córrego do Ouro","5205703"],["GO","Corumbá de Goiás","5205802"],["GO","Corumbaíba","5205901"],["GO","Cristalina","5206206"],["GO","Cristianópolis","5206305"],["GO","Crixás","5206404"],["GO","Cromínia","5206503"],["GO","Cumari","5206602"],["GO","Damianópolis","5206701"],["GO","Damolândia","5206800"],["GO","Davinópolis","5206909"],["GO","Diorama","5207105"],["GO","Divinópolis de Goiás","5208301"],["GO","Doverlândia","5207253"],["GO","Edealina","5207352"],["GO","Edéia","5207402"],["GO","Estrela do Norte","5207501"],["GO","Faina","5207535"],["GO","Fazenda Nova","5207600"],["GO","Firminópolis","5207808"],["GO","Flores de Goiás","5207907"],["GO","Formosa","5208004"],["GO","Formoso","5208103"],["GO","Gameleira de Goiás","5208152"],["GO","Goianápolis","5208400"],["GO","Goiandira","5208509"],["GO","Goianésia","5208608"],["GO","Goiânia","5208707"],["GO","Goianira","5208806"],["GO","Goiás","5208905"],["GO","Goiatuba","5209101"],["GO","Gouvelândia","5209150"],["GO","Guapó","5209200"],["GO","Guaraíta","5209291"],["GO","Guarani de Goiás","5209408"],["GO","Guarinos","5209457"],["GO","Heitoraí","5209606"],["GO","Hidrolândia","5209705"],["GO","Hidrolina","5209804"],["GO","Iaciara","5209903"],["GO","Inaciolândia","5209937"],["GO","Indiara","5209952"],["GO","Inhumas","5210000"],["GO","Ipameri","5210109"],["GO","Ipiranga de Goiás","5210158"],["GO","Iporá","5210208"],["GO","Israelândia","5210307"],["GO","Itaberaí","5210406"],["GO","Itaguari","5210562"],["GO","Itaguaru","5210604"],["GO","Itajá","5210802"],["GO","Itapaci","5210901"],["GO","Itapirapuã","5211008"],["GO","Itapuranga","5211206"],["GO","Itarumã","5211305"],["GO","Itauçu","5211404"],["GO","Itumbiara","5211503"],["GO","Ivolândia","5211602"],["GO","Jandaia","5211701"],["GO","Jaraguá","5211800"],["GO","Jataí","5211909"],["GO","Jaupaci","5212006"],["GO","Jesúpolis","5212055"],["GO","Joviânia","5212105"],["GO","Jussara","5212204"],["GO","Lagoa Santa","5212253"],["GO","Leopoldo de Bulhões","5212303"],["GO","Luziânia","5212501"],["GO","Mairipotaba","5212600"],["GO","Mambaí","5212709"],["GO","Mara Rosa","5212808"],["GO","Marzagão","5212907"],["GO","Matrinchã","5212956"],["GO","Maurilândia","5213004"],["GO","Mimoso de Goiás","5213053"],["GO","Minaçu","5213087"],["GO","Mineiros","5213103"],["GO","Moiporá","5213400"],["GO","Monte Alegre de Goiás","5213509"],["GO","Montes Claros de Goiás","5213707"],["GO","Montividiu","5213756"],["GO","Montividiu do Norte","5213772"],["GO","Morrinhos","5213806"],["GO","Morro Agudo de Goiás","5213855"],["GO","Mossâmedes","5213905"],["GO","Mozarlândia","5214002"],["GO","Mundo Novo","5214051"],["GO","Mutunópolis","5214101"],["GO","Nazário","5214408"],["GO","Nerópolis","5214507"],["GO","Niquelândia","5214606"],["GO","Nova América","5214705"],["GO","Nova Aurora","5214804"],["GO","Nova Crixás","5214838"],["GO","Nova Glória","5214861"],["GO","Nova Iguaçu de Goiás","5214879"],["GO","Nova Roma","5214903"],["GO","Nova Veneza","5215009"],["GO","Novo Brasil","5215207"],["GO","Novo Gama","5215231"],["GO","Novo Planalto","5215256"],["GO","Orizona","5215306"],["GO","Ouro Verde de Goiás","5215405"],["GO","Ouvidor","5215504"],["GO","Padre Bernardo","5215603"],["GO","Palestina de Goiás","5215652"],["GO","Palmeiras de Goiás","5215702"],["GO","Palmelo","5215801"],["GO","Palminópolis","5215900"],["GO","Panamá","5216007"],["GO","Paranaiguara","5216304"],["GO","Paraúna","5216403"],["GO","Perolândia","5216452"],["GO","Petrolina de Goiás","5216809"],["GO","Pilar de Goiás","5216908"],["GO","Piracanjuba","5217104"],["GO","Piranhas","5217203"],["GO","Pirenópolis","5217302"],["GO","Pires do Rio","5217401"],["GO","Planaltina","5217609"],["GO","Pontalina","5217708"],["GO","Porangatu","5218003"],["GO","Porteirão","5218052"],["GO","Portelândia","5218102"],["GO","Posse","5218300"],["GO","Professor Jamil","5218391"],["GO","Quirinópolis","5218508"],["GO","Rialma","5218607"],["GO","Rianápolis","5218706"],["GO","Rio Quente","5218789"],["GO","Rio Verde","5218805"],["GO","Rubiataba","5218904"],["GO","Sanclerlândia","5219001"],["GO","Santa Bárbara de Goiás","5219100"],["GO","Santa Cruz de Goiás","5219209"],["GO","Santa Fé de Goiás","5219258"],["GO","Santa Helena de Goiás","5219308"],["GO","Santa Isabel","5219357"],["GO","Santa Rita do Araguaia","5219407"],["GO","Santa Rita do Novo Destino","5219456"],["GO","Santa Rosa de Goiás","5219506"],["GO","Santa Tereza de Goiás","5219605"],["GO","Santa Terezinha de Goiás","5219704"],["GO","Santo Antônio da Barra","5219712"],["GO","Santo Antônio de Goiás","5219738"],["GO","Santo Antônio do Descoberto","5219753"],["GO","São Domingos","5219803"],["GO","São Francisco de Goiás","5219902"],["GO","São João d'Aliança","5220009"],["GO","São João da Paraúna","5220058"],["GO","São Luís de Montes Belos","5220108"],["GO","São Luiz do Norte","5220157"],["GO","São Miguel do Araguaia","5220207"],["GO","São Miguel do Passa Quatro","5220264"],["GO","São Patrício","5220280"],["GO","São Simão","5220405"],["GO","Senador Canedo","5220454"],["GO","Serranópolis","5220504"],["GO","Silvânia","5220603"],["GO","Simolândia","5220686"],["GO","Sítio d'Abadia","5220702"],["GO","Taquaral de Goiás","5221007"],["GO","Teresina de Goiás","5221080"],["GO","Terezópolis de Goiás","5221197"],["GO","Três Ranchos","5221304"],["GO","Trindade","5221403"],["GO","Trombas","5221452"],["GO","Turvânia","5221502"],["GO","Turvelândia","5221551"],["GO","Uirapuru","5221577"],["GO","Uruaçu","5221601"],["GO","Uruana","5221700"],["GO","Urutaí","5221809"],["GO","Valparaíso de Goiás","5221858"],["GO","Varjão","5221908"],["GO","Vianópolis","5222005"],["GO","Vicentinópolis","5222054"],["GO","Vila Boa","5222203"],["GO","Vila Propício","5222302"],["MA","Açailândia","2100055"],["MA","Afonso Cunha","2100105"],["MA","Água Doce do Maranhão","2100154"],["MA","Alcântara","2100204"],["MA","Aldeias Altas","2100303"],["MA","Altamira do Maranhão","2100402"],["MA","Alto Alegre do Maranhão","2100436"],["MA","Alto Alegre do Pindaré","2100477"],["MA","Alto Parnaíba","2100501"],["MA","Amapá do Maranhão","2100550"],["MA","Amarante do Maranhão","2100600"],["MA","Anajatuba","2100709"],["MA","Anapurus","2100808"],["MA","Apicum-Açu","2100832"],["MA","Araguanã","2100873"],["MA","Araioses","2100907"],["MA","Arame","2100956"],["MA","Arari","2101004"],["MA","Axixá","2101103"],["MA","Bacabal","2101202"],["MA","Bacabeira","2101251"],["MA","Bacuri","2101301"],["MA","Bacurituba","2101350"],["MA","Balsas","2101400"],["MA","Barão de Grajaú","2101509"],["MA","Barra do Corda","2101608"],["MA","Barreirinhas","2101707"],["MA","Bela Vista do Maranhão","2101772"],["MA","Belágua","2101731"],["MA","Benedito Leite","2101806"],["MA","Bequimão","2101905"],["MA","Bernardo do Mearim","2101939"],["MA","Boa Vista do Gurupi","2101970"],["MA","Bom Jardim","2102002"],["MA","Bom Jesus das Selvas","2102036"],["MA","Bom Lugar","2102077"],["MA","Brejo","2102101"],["MA","Brejo de Areia","2102150"],["MA","Buriti","2102200"],["MA","Buriti Bravo","2102309"],["MA","Buriticupu","2102325"],["MA","Buritirana","2102358"],["MA","Cachoeira Grande","2102374"],["MA","Cajapió","2102408"],["MA","Cajari","2102507"],["MA","Campestre do Maranhão","2102556"],["MA","Cândido Mendes","2102606"],["MA","Cantanhede","2102705"],["MA","Capinzal do Norte","2102754"],["MA","Carolina","2102804"],["MA","Carutapera","2102903"],["MA","Caxias","2103000"],["MA","Cedral","2103109"],["MA","Central do Maranhão","2103125"],["MA","Centro do Guilherme","2103158"],["MA","Centro Novo do Maranhão","2103174"],["MA","Chapadinha","2103208"],["MA","Cidelândia","2103257"],["MA","Codó","2103307"],["MA","Coelho Neto","2103406"],["MA","Colinas","2103505"],["MA","Conceição do Lago-Açu","2103554"],["MA","Coroatá","2103604"],["MA","Cururupu","2103703"],["MA","Davinópolis","2103752"],["MA","Dom Pedro","2103802"],["MA","Duque Bacelar","2103901"],["MA","Esperantinópolis","2104008"],["MA","Estreito","2104057"],["MA","Feira Nova do Maranhão","2104073"],["MA","Fernando Falcão","2104081"],["MA","Formosa da Serra Negra","2104099"],["MA","Fortaleza dos Nogueiras","2104107"],["MA","Fortuna","2104206"],["MA","Godofredo Viana","2104305"],["MA","Gonçalves Dias","2104404"],["MA","Governador Archer","2104503"],["MA","Governador Edison Lobão","2104552"],["MA","Governador Eugênio Barros","2104602"],["MA","Governador Luiz Rocha","2104628"],["MA","Governador Newton Bello","2104651"],["MA","Governador Nunes Freire","2104677"],["MA","Graça Aranha","2104701"],["MA","Grajaú","2104800"],["MA","Guimarães","2104909"],["MA","Humberto de Campos","2105005"],["MA","Icatu","2105104"],["MA","Igarapé do Meio","2105153"],["MA","Igarapé Grande","2105203"],["MA","Imperatriz","2105302"],["MA","Itaipava do Grajaú","2105351"],["MA","Itapecuru Mirim","2105401"],["MA","Itinga do Maranhão","2105427"],["MA","Jatobá","2105450"],["MA","Jenipapo dos Vieiras","2105476"],["MA","João Lisboa","2105500"],["MA","Joselândia","2105609"],["MA","Junco do Maranhão","2105658"],["MA","Lago da Pedra","2105708"],["MA","Lago do Junco","2105807"],["MA","Lago dos Rodrigues","2105948"],["MA","Lago Verde","2105906"],["MA","Lagoa do Mato","2105922"],["MA","Lagoa Grande do Maranhão","2105963"],["MA","Lajeado Novo","2105989"],["MA","Lima Campos","2106003"],["MA","Loreto","2106102"],["MA","Luís Domingues","2106201"],["MA","Magalhães de Almeida","2106300"],["MA","Maracaçumé","2106326"],["MA","Marajá do Sena","2106359"],["MA","Maranhãozinho","2106375"],["MA","Mata Roma","2106409"],["MA","Matinha","2106508"],["MA","Matões","2106607"],["MA","Matões do Norte","2106631"],["MA","Milagres do Maranhão","2106672"],["MA","Mirador","2106706"],["MA","Miranda do Norte","2106755"],["MA","Mirinzal","2106805"],["MA","Monção","2106904"],["MA","Montes Altos","2107001"],["MA","Morros","2107100"],["MA","Nina Rodrigues","2107209"],["MA","Nova Colinas","2107258"],["MA","Nova Iorque","2107308"],["MA","Nova Olinda do Maranhão","2107357"],["MA","Olho d'Água das Cunhãs","2107407"],["MA","Olinda Nova do Maranhão","2107456"],["MA","Paço do Lumiar","2107506"],["MA","Palmeirândia","2107605"],["MA","Paraibano","2107704"],["MA","Parnarama","2107803"],["MA","Passagem Franca","2107902"],["MA","Pastos Bons","2108009"],["MA","Paulino Neves","2108058"],["MA","Paulo Ramos","2108108"],["MA","Pedreiras","2108207"],["MA","Pedro do Rosário","2108256"],["MA","Penalva","2108306"],["MA","Peri Mirim","2108405"],["MA","Peritoró","2108454"],["MA","Pindaré-Mirim","2108504"],["MA","Pinheiro","2108603"],["MA","Pio XII","2108702"],["MA","Pirapemas","2108801"],["MA","Poção de Pedras","2108900"],["MA","Porto Franco","2109007"],["MA","Porto Rico do Maranhão","2109056"],["MA","Presidente Dutra","2109106"],["MA","Presidente Juscelino","2109205"],["MA","Presidente Médici","2109239"],["MA","Presidente Sarney","2109270"],["MA","Presidente Vargas","2109304"],["MA","Primeira Cruz","2109403"],["MA","Raposa","2109452"],["MA","Riachão","2109502"],["MA","Ribamar Fiquene","2109551"],["MA","Rosário","2109601"],["MA","Sambaíba","2109700"],["MA","Santa Filomena do Maranhão","2109759"],["MA","Santa Helena","2109809"],["MA","Santa Inês","2109908"],["MA","Santa Luzia","2110005"],["MA","Santa Luzia do Paruá","2110039"],["MA","Santa Quitéria do Maranhão","2110104"],["MA","Santa Rita","2110203"],["MA","Santana do Maranhão","2110237"],["MA","Santo Amaro do Maranhão","2110278"],["MA","Santo Antônio dos Lopes","2110302"],["MA","São Benedito do Rio Preto","2110401"],["MA","São Bento","2110500"],["MA","São Bernardo","2110609"],["MA","São Domingos do Azeitão","2110658"],["MA","São Domingos do Maranhão","2110708"],["MA","São Félix de Balsas","2110807"],["MA","São Francisco do Brejão","2110856"],["MA","São Francisco do Maranhão","2110906"],["MA","São João Batista","2111003"],["MA","São João do Carú","2111029"],["MA","São João do Paraíso","2111052"],["MA","São João do Soter","2111078"],["MA","São João dos Patos","2111102"],["MA","São José de Ribamar","2111201"],["MA","São José dos Basílios","2111250"],["MA","São Luís","2111300"],["MA","São Luís Gonzaga do Maranhão","2111409"],["MA","São Mateus do Maranhão","2111508"],["MA","São Pedro da Água Branca","2111532"],["MA","São Pedro dos Crentes","2111573"],["MA","São Raimundo das Mangabeiras","2111607"],["MA","São Raimundo do Doca Bezerra","2111631"],["MA","São Roberto","2111672"],["MA","São Vicente Ferrer","2111706"],["MA","Satubinha","2111722"],["MA","Senador Alexandre Costa","2111748"],["MA","Senador La Rocque","2111763"],["MA","Serrano do Maranhão","2111789"],["MA","Sítio Novo","2111805"],["MA","Sucupira do Norte","2111904"],["MA","Sucupira do Riachão","2111953"],["MA","Tasso Fragoso","2112001"],["MA","Timbiras","2112100"],["MA","Timon","2112209"],["MA","Trizidela do Vale","2112233"],["MA","Tufilândia","2112274"],["MA","Tuntum","2112308"],["MA","Turiaçu","2112407"],["MA","Turilândia","2112456"],["MA","Tutóia","2112506"],["MA","Urbano Santos","2112605"],["MA","Vargem Grande","2112704"],["MA","Viana","2112803"],["MA","Vila Nova dos Martírios","2112852"],["MA","Vitória do Mearim","2112902"],["MA","Vitorino Freire","2113009"],["MA","Zé Doca","2114007"],["MT","Acorizal","5100102"],["MT","Água Boa","5100201"],["MT","Alta Floresta","5100250"],["MT","Alto Araguaia","5100300"],["MT","Alto Boa Vista","5100359"],["MT","Alto Garças","5100409"],["MT","Alto Paraguai","5100508"],["MT","Alto Taquari","5100607"],["MT","Apiacás","5100805"],["MT","Araguaiana","5101001"],["MT","Araguainha","5101209"],["MT","Araputanga","5101258"],["MT","Arenápolis","5101308"],["MT","Aripuanã","5101407"],["MT","Barão de Melgaço","5101605"],["MT","Barra do Bugres","5101704"],["MT","Barra do Garças","5101803"],["MT","Boa Esperança do Norte","5101837"],["MT","Bom Jesus do Araguaia","5101852"],["MT","Brasnorte","5101902"],["MT","Cáceres","5102504"],["MT","Campinápolis","5102603"],["MT","Campo Novo do Parecis","5102637"],["MT","Campo Verde","5102678"],["MT","Campos de Júlio","5102686"],["MT","Canabrava do Norte","5102694"],["MT","Canarana","5102702"],["MT","Carlinda","5102793"],["MT","Castanheira","5102850"],["MT","Chapada dos Guimarães","5103007"],["MT","Cláudia","5103056"],["MT","Cocalinho","5103106"],["MT","Colíder","5103205"],["MT","Colniza","5103254"],["MT","Comodoro","5103304"],["MT","Confresa","5103353"],["MT","Conquista D'Oeste","5103361"],["MT","Cotriguaçu","5103379"],["MT","Cuiabá","5103403"],["MT","Curvelândia","5103437"],["MT","Denise","5103452"],["MT","Diamantino","5103502"],["MT","Dom Aquino","5103601"],["MT","Feliz Natal","5103700"],["MT","Figueirópolis D'Oeste","5103809"],["MT","Gaúcha do Norte","5103858"],["MT","General Carneiro","5103908"],["MT","Glória D'Oeste","5103957"],["MT","Guarantã do Norte","5104104"],["MT","Guiratinga","5104203"],["MT","Indiavaí","5104500"],["MT","Ipiranga do Norte","5104526"],["MT","Itanhangá","5104542"],["MT","Itaúba","5104559"],["MT","Itiquira","5104609"],["MT","Jaciara","5104807"],["MT","Jangada","5104906"],["MT","Jauru","5105002"],["MT","Juara","5105101"],["MT","Juína","5105150"],["MT","Juruena","5105176"],["MT","Juscimeira","5105200"],["MT","Lambari D'Oeste","5105234"],["MT","Lucas do Rio Verde","5105259"],["MT","Luciara","5105309"],["MT","Marcelândia","5105580"],["MT","Matupá","5105606"],["MT","Mirassol d'Oeste","5105622"],["MT","Nobres","5105903"],["MT","Nortelândia","5106000"],["MT","Nossa Senhora do Livramento","5106109"],["MT","Nova Bandeirantes","5106158"],["MT","Nova Brasilândia","5106208"],["MT","Nova Canaã do Norte","5106216"],["MT","Nova Guarita","5108808"],["MT","Nova Lacerda","5106182"],["MT","Nova Marilândia","5108857"],["MT","Nova Maringá","5108907"],["MT","Nova Monte Verde","5108956"],["MT","Nova Mutum","5106224"],["MT","Nova Nazaré","5106174"],["MT","Nova Olímpia","5106232"],["MT","Nova Santa Helena","5106190"],["MT","Nova Ubiratã","5106240"],["MT","Nova Xavantina","5106257"],["MT","Novo Horizonte do Norte","5106273"],["MT","Novo Mundo","5106265"],["MT","Novo Santo Antônio","5106315"],["MT","Novo São Joaquim","5106281"],["MT","Paranaíta","5106299"],["MT","Paranatinga","5106307"],["MT","Pedra Preta","5106372"],["MT","Peixoto de Azevedo","5106422"],["MT","Planalto da Serra","5106455"],["MT","Poconé","5106505"],["MT","Pontal do Araguaia","5106653"],["MT","Ponte Branca","5106703"],["MT","Pontes e Lacerda","5106752"],["MT","Porto Alegre do Norte","5106778"],["MT","Porto dos Gaúchos","5106802"],["MT","Porto Esperidião","5106828"],["MT","Porto Estrela","5106851"],["MT","Poxoréu","5107008"],["MT","Primavera do Leste","5107040"],["MT","Querência","5107065"],["MT","Reserva do Cabaçal","5107156"],["MT","Ribeirão Cascalheira","5107180"],["MT","Ribeirãozinho","5107198"],["MT","Rio Branco","5107206"],["MT","Rondolândia","5107578"],["MT","Rondonópolis","5107602"],["MT","Rosário Oeste","5107701"],["MT","Salto do Céu","5107750"],["MT","Santa Carmem","5107248"],["MT","Santa Cruz do Xingu","5107743"],["MT","Santa Rita do Trivelato","5107768"],["MT","Santa Terezinha","5107776"],["MT","Santo Afonso","5107263"],["MT","Santo Antônio de Leverger","5107800"],["MT","Santo Antônio do Leste","5107792"],["MT","São Félix do Araguaia","5107859"],["MT","São José do Povo","5107297"],["MT","São José do Rio Claro","5107305"],["MT","São José do Xingu","5107354"],["MT","São José dos Quatro Marcos","5107107"],["MT","São Pedro da Cipa","5107404"],["MT","Sapezal","5107875"],["MT","Serra Nova Dourada","5107883"],["MT","Sinop","5107909"],["MT","Sorriso","5107925"],["MT","Tabaporã","5107941"],["MT","Tangará da Serra","5107958"],["MT","Tapurah","5108006"],["MT","Terra Nova do Norte","5108055"],["MT","Tesouro","5108105"],["MT","Torixoréu","5108204"],["MT","União do Sul","5108303"],["MT","Vale de São Domingos","5108352"],["MT","Várzea Grande","5108402"],["MT","Vera","5108501"],["MT","Vila Bela da Santíssima Trindade","5105507"],["MT","Vila Rica","5108600"],["MS","Água Clara","5000203"],["MS","Alcinópolis","5000252"],["MS","Amambai","5000609"],["MS","Anastácio","5000708"],["MS","Anaurilândia","5000807"],["MS","Angélica","5000856"],["MS","Antônio João","5000906"],["MS","Aparecida do Taboado","5001003"],["MS","Aquidauana","5001102"],["MS","Aral Moreira","5001243"],["MS","Bandeirantes","5001508"],["MS","Bataguassu","5001904"],["MS","Batayporã","5002001"],["MS","Bela Vista","5002100"],["MS","Bodoquena","5002159"],["MS","Bonito","5002209"],["MS","Brasilândia","5002308"],["MS","Caarapó","5002407"],["MS","Camapuã","5002605"],["MS","Campo Grande","5002704"],["MS","Caracol","5002803"],["MS","Cassilândia","5002902"],["MS","Chapadão do Sul","5002951"],["MS","Corguinho","5003108"],["MS","Coronel Sapucaia","5003157"],["MS","Corumbá","5003207"],["MS","Costa Rica","5003256"],["MS","Coxim","5003306"],["MS","Deodápolis","5003454"],["MS","Dois Irmãos do Buriti","5003488"],["MS","Douradina","5003504"],["MS","Dourados","5003702"],["MS","Eldorado","5003751"],["MS","Fátima do Sul","5003801"],["MS","Figueirão","5003900"],["MS","Glória de Dourados","5004007"],["MS","Guia Lopes da Laguna","5004106"],["MS","Iguatemi","5004304"],["MS","Inocência","5004403"],["MS","Itaporã","5004502"],["MS","Itaquiraí","5004601"],["MS","Ivinhema","5004700"],["MS","Japorã","5004809"],["MS","Jaraguari","5004908"],["MS","Jardim","5005004"],["MS","Jateí","5005103"],["MS","Juti","5005152"],["MS","Ladário","5005202"],["MS","Laguna Carapã","5005251"],["MS","Maracaju","5005400"],["MS","Miranda","5005608"],["MS","Mundo Novo","5005681"],["MS","Naviraí","5005707"],["MS","Nioaque","5005806"],["MS","Nova Alvorada do Sul","5006002"],["MS","Nova Andradina","5006200"],["MS","Novo Horizonte do Sul","5006259"],["MS","Paraíso das Águas","5006275"],["MS","Paranaíba","5006309"],["MS","Paranhos","5006358"],["MS","Pedro Gomes","5006408"],["MS","Ponta Porã","5006606"],["MS","Porto Murtinho","5006903"],["MS","Ribas do Rio Pardo","5007109"],["MS","Rio Brilhante","5007208"],["MS","Rio Negro","5007307"],["MS","Rio Verde de Mato Grosso","5007406"],["MS","Rochedo","5007505"],["MS","Santa Rita do Pardo","5007554"],["MS","São Gabriel do Oeste","5007695"],["MS","Selvíria","5007802"],["MS","Sete Quedas","5007703"],["MS","Sidrolândia","5007901"],["MS","Sonora","5007935"],["MS","Tacuru","5007950"],["MS","Taquarussu","5007976"],["MS","Terenos","5008008"],["MS","Três Lagoas","5008305"],["MS","Vicentina","5008404"],["MG","Abadia dos Dourados","3100104"],["MG","Abaeté","3100203"],["MG","Abre Campo","3100302"],["MG","Acaiaca","3100401"],["MG","Açucena","3100500"],["MG","Água Boa","3100609"],["MG","Água Comprida","3100708"],["MG","Aguanil","3100807"],["MG","Águas Formosas","3100906"],["MG","Águas Vermelhas","3101003"],["MG","Aimorés","3101102"],["MG","Aiuruoca","3101201"],["MG","Alagoa","3101300"],["MG","Albertina","3101409"],["MG","Além Paraíba","3101508"],["MG","Alfenas","3101607"],["MG","Alfredo Vasconcelos","3101631"],["MG","Almenara","3101706"],["MG","Alpercata","3101805"],["MG","Alpinópolis","3101904"],["MG","Alterosa","3102001"],["MG","Alto Caparaó","3102050"],["MG","Alto Jequitibá","3153509"],["MG","Alto Rio Doce","3102100"],["MG","Alvarenga","3102209"],["MG","Alvinópolis","3102308"],["MG","Alvorada de Minas","3102407"],["MG","Amparo do Serra","3102506"],["MG","Andradas","3102605"],["MG","Andrelândia","3102803"],["MG","Angelândia","3102852"],["MG","Antônio Carlos","3102902"],["MG","Antônio Dias","3103009"],["MG","Antônio Prado de Minas","3103108"],["MG","Araçaí","3103207"],["MG","Aracitaba","3103306"],["MG","Araçuaí","3103405"],["MG","Araguari","3103504"],["MG","Arantina","3103603"],["MG","Araponga","3103702"],["MG","Araporã","3103751"],["MG","Arapuá","3103801"],["MG","Araújos","3103900"],["MG","Araxá","3104007"],["MG","Arceburgo","3104106"],["MG","Arcos","3104205"],["MG","Areado","3104304"],["MG","Argirita","3104403"],["MG","Aricanduva","3104452"],["MG","Arinos","3104502"],["MG","Astolfo Dutra","3104601"],["MG","Ataléia","3104700"],["MG","Augusto de Lima","3104809"],["MG","Baependi","3104908"],["MG","Baldim","3105004"],["MG","Bambuí","3105103"],["MG","Bandeira","3105202"],["MG","Bandeira do Sul","3105301"],["MG","Barão de Cocais","3105400"],["MG","Barão do Monte Alto","3105509"],["MG","Barbacena","3105608"],["MG","Barra Longa","3105707"],["MG","Barroso","3105905"],["MG","Bela Vista de Minas","3106002"],["MG","Belmiro Braga","3106101"],["MG","Belo Horizonte","3106200"],["MG","Belo Oriente","3106309"],["MG","Belo Vale","3106408"],["MG","Berilo","3106507"],["MG","Berizal","3106655"],["MG","Bertópolis","3106606"],["MG","Betim","3106705"],["MG","Bias Fortes","3106804"],["MG","Bicas","3106903"],["MG","Biquinhas","3107000"],["MG","Boa Esperança","3107109"],["MG","Bocaina de Minas","3107208"],["MG","Bocaiúva","3107307"],["MG","Bom Despacho","3107406"],["MG","Bom Jardim de Minas","3107505"],["MG","Bom Jesus da Penha","3107604"],["MG","Bom Jesus do Amparo","3107703"],["MG","Bom Jesus do Galho","3107802"],["MG","Bom Repouso","3107901"],["MG","Bom Sucesso","3108008"],["MG","Bonfim","3108107"],["MG","Bonfinópolis de Minas","3108206"],["MG","Bonito de Minas","3108255"],["MG","Borda da Mata","3108305"],["MG","Botelhos","3108404"],["MG","Botumirim","3108503"],["MG","Brás Pires","3108701"],["MG","Brasilândia de Minas","3108552"],["MG","Brasília de Minas","3108602"],["MG","Braúnas","3108800"],["MG","Brazópolis","3108909"],["MG","Brumadinho","3109006"],["MG","Bueno Brandão","3109105"],["MG","Buenópolis","3109204"],["MG","Bugre","3109253"],["MG","Buritis","3109303"],["MG","Buritizeiro","3109402"],["MG","Cabeceira Grande","3109451"],["MG","Cabo Verde","3109501"],["MG","Cachoeira da Prata","3109600"],["MG","Cachoeira de Minas","3109709"],["MG","Cachoeira de Pajeú","3102704"],["MG","Cachoeira Dourada","3109808"],["MG","Caetanópolis","3109907"],["MG","Caeté","3110004"],["MG","Caiana","3110103"],["MG","Cajuri","3110202"],["MG","Caldas","3110301"],["MG","Camacho","3110400"],["MG","Camanducaia","3110509"],["MG","Cambuí","3110608"],["MG","Cambuquira","3110707"],["MG","Campanário","3110806"],["MG","Campanha","3110905"],["MG","Campestre","3111002"],["MG","Campina Verde","3111101"],["MG","Campo Azul","3111150"],["MG","Campo Belo","3111200"],["MG","Campo do Meio","3111309"],["MG","Campo Florido","3111408"],["MG","Campos Altos","3111507"],["MG","Campos Gerais","3111606"],["MG","Cana Verde","3111903"],["MG","Canaã","3111705"],["MG","Canápolis","3111804"],["MG","Candeias","3112000"],["MG","Cantagalo","3112059"],["MG","Caparaó","3112109"],["MG","Capela Nova","3112208"],["MG","Capelinha","3112307"],["MG","Capetinga","3112406"],["MG","Capim Branco","3112505"],["MG","Capinópolis","3112604"],["MG","Capitão Andrade","3112653"],["MG","Capitão Enéas","3112703"],["MG","Capitólio","3112802"],["MG","Caputira","3112901"],["MG","Caraí","3113008"],["MG","Caranaíba","3113107"],["MG","Carandaí","3113206"],["MG","Carangola","3113305"],["MG","Caratinga","3113404"],["MG","Carbonita","3113503"],["MG","Careaçu","3113602"],["MG","Carlos Chagas","3113701"],["MG","Carmésia","3113800"],["MG","Carmo da Cachoeira","3113909"],["MG","Carmo da Mata","3114006"],["MG","Carmo de Minas","3114105"],["MG","Carmo do Cajuru","3114204"],["MG","Carmo do Paranaíba","3114303"],["MG","Carmo do Rio Claro","3114402"],["MG","Carmópolis de Minas","3114501"],["MG","Carneirinho","3114550"],["MG","Carrancas","3114600"],["MG","Carvalhópolis","3114709"],["MG","Carvalhos","3114808"],["MG","Casa Grande","3114907"],["MG","Cascalho Rico","3115003"],["MG","Cássia","3115102"],["MG","Cataguases","3115300"],["MG","Catas Altas","3115359"],["MG","Catas Altas da Noruega","3115409"],["MG","Catuji","3115458"],["MG","Catuti","3115474"],["MG","Caxambu","3115508"],["MG","Cedro do Abaeté","3115607"],["MG","Central de Minas","3115706"],["MG","Centralina","3115805"],["MG","Chácara","3115904"],["MG","Chalé","3116001"],["MG","Chapada do Norte","3116100"],["MG","Chapada Gaúcha","3116159"],["MG","Chiador","3116209"],["MG","Cipotânea","3116308"],["MG","Claraval","3116407"],["MG","Claro dos Poções","3116506"],["MG","Cláudio","3116605"],["MG","Coimbra","3116704"],["MG","Coluna","3116803"],["MG","Comendador Gomes","3116902"],["MG","Comercinho","3117009"],["MG","Conceição da Aparecida","3117108"],["MG","Conceição da Barra de Minas","3115201"],["MG","Conceição das Alagoas","3117306"],["MG","Conceição das Pedras","3117207"],["MG","Conceição de Ipanema","3117405"],["MG","Conceição do Mato Dentro","3117504"],["MG","Conceição do Pará","3117603"],["MG","Conceição do Rio Verde","3117702"],["MG","Conceição dos Ouros","3117801"],["MG","Cônego Marinho","3117836"],["MG","Confins","3117876"],["MG","Congonhal","3117900"],["MG","Congonhas","3118007"],["MG","Congonhas do Norte","3118106"],["MG","Conquista","3118205"],["MG","Conselheiro Lafaiete","3118304"],["MG","Conselheiro Pena","3118403"],["MG","Consolação","3118502"],["MG","Contagem","3118601"],["MG","Coqueiral","3118700"],["MG","Coração de Jesus","3118809"],["MG","Cordisburgo","3118908"],["MG","Cordislândia","3119005"],["MG","Corinto","3119104"],["MG","Coroaci","3119203"],["MG","Coromandel","3119302"],["MG","Coronel Fabriciano","3119401"],["MG","Coronel Murta","3119500"],["MG","Coronel Pacheco","3119609"],["MG","Coronel Xavier Chaves","3119708"],["MG","Córrego Danta","3119807"],["MG","Córrego do Bom Jesus","3119906"],["MG","Córrego Fundo","3119955"],["MG","Córrego Novo","3120003"],["MG","Couto de Magalhães de Minas","3120102"],["MG","Crisólita","3120151"],["MG","Cristais","3120201"],["MG","Cristália","3120300"],["MG","Cristiano Otoni","3120409"],["MG","Cristina","3120508"],["MG","Crucilândia","3120607"],["MG","Cruzeiro da Fortaleza","3120706"],["MG","Cruzília","3120805"],["MG","Cuparaque","3120839"],["MG","Curral de Dentro","3120870"],["MG","Curvelo","3120904"],["MG","Datas","3121001"],["MG","Delfim Moreira","3121100"],["MG","Delfinópolis","3121209"],["MG","Delta","3121258"],["MG","Descoberto","3121308"],["MG","Desterro de Entre Rios","3121407"],["MG","Desterro do Melo","3121506"],["MG","Diamantina","3121605"],["MG","Diogo de Vasconcelos","3121704"],["MG","Dionísio","3121803"],["MG","Divinésia","3121902"],["MG","Divino","3122009"],["MG","Divino das Laranjeiras","3122108"],["MG","Divinolândia de Minas","3122207"],["MG","Divinópolis","3122306"],["MG","Divisa Alegre","3122355"],["MG","Divisa Nova","3122405"],["MG","Divisópolis","3122454"],["MG","Dom Bosco","3122470"],["MG","Dom Cavati","3122504"],["MG","Dom Joaquim","3122603"],["MG","Dom Silvério","3122702"],["MG","Dom Viçoso","3122801"],["MG","Dona Euzébia","3122900"],["MG","Dores de Campos","3123007"],["MG","Dores de Guanhães","3123106"],["MG","Dores do Indaiá","3123205"],["MG","Dores do Turvo","3123304"],["MG","Doresópolis","3123403"],["MG","Douradoquara","3123502"],["MG","Durandé","3123528"],["MG","Elói Mendes","3123601"],["MG","Engenheiro Caldas","3123700"],["MG","Engenheiro Navarro","3123809"],["MG","Entre Folhas","3123858"],["MG","Entre Rios de Minas","3123908"],["MG","Ervália","3124005"],["MG","Esmeraldas","3124104"],["MG","Espera Feliz","3124203"],["MG","Espinosa","3124302"],["MG","Espírito Santo do Dourado","3124401"],["MG","Estiva","3124500"],["MG","Estrela Dalva","3124609"],["MG","Estrela do Indaiá","3124708"],["MG","Estrela do Sul","3124807"],["MG","Eugenópolis","3124906"],["MG","Ewbank da Câmara","3125002"],["MG","Extrema","3125101"],["MG","Fama","3125200"],["MG","Faria Lemos","3125309"],["MG","Felício dos Santos","3125408"],["MG","Felisburgo","3125606"],["MG","Felixlândia","3125705"],["MG","Fernandes Tourinho","3125804"],["MG","Ferros","3125903"],["MG","Fervedouro","3125952"],["MG","Florestal","3126000"],["MG","Formiga","3126109"],["MG","Formoso","3126208"],["MG","Fortaleza de Minas","3126307"],["MG","Fortuna de Minas","3126406"],["MG","Francisco Badaró","3126505"],["MG","Francisco Dumont","3126604"],["MG","Francisco Sá","3126703"],["MG","Franciscópolis","3126752"],["MG","Frei Gaspar","3126802"],["MG","Frei Inocêncio","3126901"],["MG","Frei Lagonegro","3126950"],["MG","Fronteira","3127008"],["MG","Fronteira dos Vales","3127057"],["MG","Fruta de Leite","3127073"],["MG","Frutal","3127107"],["MG","Funilândia","3127206"],["MG","Galiléia","3127305"],["MG","Gameleiras","3127339"],["MG","Glaucilândia","3127354"],["MG","Goiabeira","3127370"],["MG","Goianá","3127388"],["MG","Gonçalves","3127404"],["MG","Gonzaga","3127503"],["MG","Gouveia","3127602"],["MG","Governador Valadares","3127701"],["MG","Grão Mogol","3127800"],["MG","Grupiara","3127909"],["MG","Guanhães","3128006"],["MG","Guapé","3128105"],["MG","Guaraciaba","3128204"],["MG","Guaraciama","3128253"],["MG","Guaranésia","3128303"],["MG","Guarani","3128402"],["MG","Guarará","3128501"],["MG","Guarda-Mor","3128600"],["MG","Guaxupé","3128709"],["MG","Guidoval","3128808"],["MG","Guimarânia","3128907"],["MG","Guiricema","3129004"],["MG","Gurinhatã","3129103"],["MG","Heliodora","3129202"],["MG","Iapu","3129301"],["MG","Ibertioga","3129400"],["MG","Ibiá","3129509"],["MG","Ibiaí","3129608"],["MG","Ibiracatu","3129657"],["MG","Ibiraci","3129707"],["MG","Ibirité","3129806"],["MG","Ibitiúra de Minas","3129905"],["MG","Ibituruna","3130002"],["MG","Icaraí de Minas","3130051"],["MG","Igarapé","3130101"],["MG","Igaratinga","3130200"],["MG","Iguatama","3130309"],["MG","Ijaci","3130408"],["MG","Ilicínea","3130507"],["MG","Imbé de Minas","3130556"],["MG","Inconfidentes","3130606"],["MG","Indaiabira","3130655"],["MG","Indianópolis","3130705"],["MG","Ingaí","3130804"],["MG","Inhapim","3130903"],["MG","Inhaúma","3131000"],["MG","Inimutaba","3131109"],["MG","Ipaba","3131158"],["MG","Ipanema","3131208"],["MG","Ipatinga","3131307"],["MG","Ipiaçu","3131406"],["MG","Ipuiúna","3131505"],["MG","Iraí de Minas","3131604"],["MG","Itabira","3131703"],["MG","Itabirinha","3131802"],["MG","Itabirito","3131901"],["MG","Itacambira","3132008"],["MG","Itacarambi","3132107"],["MG","Itaguara","3132206"],["MG","Itaipé","3132305"],["MG","Itajubá","3132404"],["MG","Itamarandiba","3132503"],["MG","Itamarati de Minas","3132602"],["MG","Itambacuri","3132701"],["MG","Itambé do Mato Dentro","3132800"],["MG","Itamogi","3132909"],["MG","Itamonte","3133006"],["MG","Itanhandu","3133105"],["MG","Itanhomi","3133204"],["MG","Itaobim","3133303"],["MG","Itapagipe","3133402"],["MG","Itapecerica","3133501"],["MG","Itapeva","3133600"],["MG","Itatiaiuçu","3133709"],["MG","Itaú de Minas","3133758"],["MG","Itaúna","3133808"],["MG","Itaverava","3133907"],["MG","Itinga","3134004"],["MG","Itueta","3134103"],["MG","Ituiutaba","3134202"],["MG","Itumirim","3134301"],["MG","Iturama","3134400"],["MG","Itutinga","3134509"],["MG","Jaboticatubas","3134608"],["MG","Jacinto","3134707"],["MG","Jacuí","3134806"],["MG","Jacutinga","3134905"],["MG","Jaguaraçu","3135001"],["MG","Jaíba","3135050"],["MG","Jampruca","3135076"],["MG","Janaúba","3135100"],["MG","Januária","3135209"],["MG","Japaraíba","3135308"],["MG","Japonvar","3135357"],["MG","Jeceaba","3135407"],["MG","Jenipapo de Minas","3135456"],["MG","Jequeri","3135506"],["MG","Jequitaí","3135605"],["MG","Jequitibá","3135704"],["MG","Jequitinhonha","3135803"],["MG","Jesuânia","3135902"],["MG","Joaíma","3136009"],["MG","Joanésia","3136108"],["MG","João Monlevade","3136207"],["MG","João Pinheiro","3136306"],["MG","Joaquim Felício","3136405"],["MG","Jordânia","3136504"],["MG","José Gonçalves de Minas","3136520"],["MG","José Raydan","3136553"],["MG","Josenópolis","3136579"],["MG","Juatuba","3136652"],["MG","Juiz de Fora","3136702"],["MG","Juramento","3136801"],["MG","Juruaia","3136900"],["MG","Juvenília","3136959"],["MG","Ladainha","3137007"],["MG","Lagamar","3137106"],["MG","Lagoa da Prata","3137205"],["MG","Lagoa dos Patos","3137304"],["MG","Lagoa Dourada","3137403"],["MG","Lagoa Formosa","3137502"],["MG","Lagoa Grande","3137536"],["MG","Lagoa Santa","3137601"],["MG","Lajinha","3137700"],["MG","Lambari","3137809"],["MG","Lamim","3137908"],["MG","Laranjal","3138005"],["MG","Lassance","3138104"],["MG","Lavras","3138203"],["MG","Leandro Ferreira","3138302"],["MG","Leme do Prado","3138351"],["MG","Leopoldina","3138401"],["MG","Liberdade","3138500"],["MG","Lima Duarte","3138609"],["MG","Limeira do Oeste","3138625"],["MG","Lontra","3138658"],["MG","Luisburgo","3138674"],["MG","Luislândia","3138682"],["MG","Luminárias","3138708"],["MG","Luz","3138807"],["MG","Machacalis","3138906"],["MG","Machado","3139003"],["MG","Madre de Deus de Minas","3139102"],["MG","Malacacheta","3139201"],["MG","Mamonas","3139250"],["MG","Manga","3139300"],["MG","Manhuaçu","3139409"],["MG","Manhumirim","3139508"],["MG","Mantena","3139607"],["MG","Mar de Espanha","3139805"],["MG","Maravilhas","3139706"],["MG","Maria da Fé","3139904"],["MG","Mariana","3140001"],["MG","Marilac","3140100"],["MG","Mário Campos","3140159"],["MG","Maripá de Minas","3140209"],["MG","Marliéria","3140308"],["MG","Marmelópolis","3140407"],["MG","Martinho Campos","3140506"],["MG","Martins Soares","3140530"],["MG","Mata Verde","3140555"],["MG","Materlândia","3140605"],["MG","Mateus Leme","3140704"],["MG","Mathias Lobato","3171501"],["MG","Matias Barbosa","3140803"],["MG","Matias Cardoso","3140852"],["MG","Matipó","3140902"],["MG","Mato Verde","3141009"],["MG","Matozinhos","3141108"],["MG","Matutina","3141207"],["MG","Medeiros","3141306"],["MG","Medina","3141405"],["MG","Mendes Pimentel","3141504"],["MG","Mercês","3141603"],["MG","Mesquita","3141702"],["MG","Minas Novas","3141801"],["MG","Minduri","3141900"],["MG","Mirabela","3142007"],["MG","Miradouro","3142106"],["MG","Miraí","3142205"],["MG","Miravânia","3142254"],["MG","Moeda","3142304"],["MG","Moema","3142403"],["MG","Monjolos","3142502"],["MG","Monsenhor Paulo","3142601"],["MG","Montalvânia","3142700"],["MG","Monte Alegre de Minas","3142809"],["MG","Monte Azul","3142908"],["MG","Monte Belo","3143005"],["MG","Monte Carmelo","3143104"],["MG","Monte Formoso","3143153"],["MG","Monte Santo de Minas","3143203"],["MG","Monte Sião","3143401"],["MG","Montes Claros","3143302"],["MG","Montezuma","3143450"],["MG","Morada Nova de Minas","3143500"],["MG","Morro da Garça","3143609"],["MG","Morro do Pilar","3143708"],["MG","Munhoz","3143807"],["MG","Muriaé","3143906"],["MG","Mutum","3144003"],["MG","Muzambinho","3144102"],["MG","Nacip Raydan","3144201"],["MG","Nanuque","3144300"],["MG","Naque","3144359"],["MG","Natalândia","3144375"],["MG","Natércia","3144409"],["MG","Nazareno","3144508"],["MG","Nepomuceno","3144607"],["MG","Ninheira","3144656"],["MG","Nova Belém","3144672"],["MG","Nova Era","3144706"],["MG","Nova Lima","3144805"],["MG","Nova Módica","3144904"],["MG","Nova Ponte","3145000"],["MG","Nova Porteirinha","3145059"],["MG","Nova Resende","3145109"],["MG","Nova Serrana","3145208"],["MG","Nova União","3136603"],["MG","Novo Cruzeiro","3145307"],["MG","Novo Oriente de Minas","3145356"],["MG","Novorizonte","3145372"],["MG","Olaria","3145406"],["MG","Olhos-d'Água","3145455"],["MG","Olímpio Noronha","3145505"],["MG","Oliveira","3145604"],["MG","Oliveira Fortes","3145703"],["MG","Onça de Pitangui","3145802"],["MG","Oratórios","3145851"],["MG","Orizânia","3145877"],["MG","Ouro Branco","3145901"],["MG","Ouro Fino","3146008"],["MG","Ouro Preto","3146107"],["MG","Ouro Verde de Minas","3146206"],["MG","Padre Carvalho","3146255"],["MG","Padre Paraíso","3146305"],["MG","Pai Pedro","3146552"],["MG","Paineiras","3146404"],["MG","Pains","3146503"],["MG","Paiva","3146602"],["MG","Palma","3146701"],["MG","Palmópolis","3146750"],["MG","Papagaios","3146909"],["MG","Pará de Minas","3147105"],["MG","Paracatu","3147006"],["MG","Paraguaçu","3147204"],["MG","Paraisópolis","3147303"],["MG","Paraopeba","3147402"],["MG","Passa Quatro","3147600"],["MG","Passa Tempo","3147709"],["MG","Passa Vinte","3147808"],["MG","Passabém","3147501"],["MG","Passos","3147907"],["MG","Patis","3147956"],["MG","Patos de Minas","3148004"],["MG","Patrocínio","3148103"],["MG","Patrocínio do Muriaé","3148202"],["MG","Paula Cândido","3148301"],["MG","Paulistas","3148400"],["MG","Pavão","3148509"],["MG","Peçanha","3148608"],["MG","Pedra Azul","3148707"],["MG","Pedra Bonita","3148756"],["MG","Pedra do Anta","3148806"],["MG","Pedra do Indaiá","3148905"],["MG","Pedra Dourada","3149002"],["MG","Pedralva","3149101"],["MG","Pedras de Maria da Cruz","3149150"],["MG","Pedrinópolis","3149200"],["MG","Pedro Leopoldo","3149309"],["MG","Pedro Teixeira","3149408"],["MG","Pequeri","3149507"],["MG","Pequi","3149606"],["MG","Perdigão","3149705"],["MG","Perdizes","3149804"],["MG","Perdões","3149903"],["MG","Periquito","3149952"],["MG","Pescador","3150000"],["MG","Piau","3150109"],["MG","Piedade de Caratinga","3150158"],["MG","Piedade de Ponte Nova","3150208"],["MG","Piedade do Rio Grande","3150307"],["MG","Piedade dos Gerais","3150406"],["MG","Pimenta","3150505"],["MG","Pingo-d'Água","3150539"],["MG","Pintópolis","3150570"],["MG","Piracema","3150604"],["MG","Pirajuba","3150703"],["MG","Piranga","3150802"],["MG","Piranguçu","3150901"],["MG","Piranguinho","3151008"],["MG","Pirapetinga","3151107"],["MG","Pirapora","3151206"],["MG","Piraúba","3151305"],["MG","Pitangui","3151404"],["MG","Piumhi","3151503"],["MG","Planura","3151602"],["MG","Poço Fundo","3151701"],["MG","Poços de Caldas","3151800"],["MG","Pocrane","3151909"],["MG","Pompéu","3152006"],["MG","Ponte Nova","3152105"],["MG","Ponto Chique","3152131"],["MG","Ponto dos Volantes","3152170"],["MG","Porteirinha","3152204"],["MG","Porto Firme","3152303"],["MG","Poté","3152402"],["MG","Pouso Alegre","3152501"],["MG","Pouso Alto","3152600"],["MG","Prados","3152709"],["MG","Prata","3152808"],["MG","Pratápolis","3152907"],["MG","Pratinha","3153004"],["MG","Presidente Bernardes","3153103"],["MG","Presidente Juscelino","3153202"],["MG","Presidente Kubitschek","3153301"],["MG","Presidente Olegário","3153400"],["MG","Prudente de Morais","3153608"],["MG","Quartel Geral","3153707"],["MG","Queluzito","3153806"],["MG","Raposos","3153905"],["MG","Raul Soares","3154002"],["MG","Recreio","3154101"],["MG","Reduto","3154150"],["MG","Resende Costa","3154200"],["MG","Resplendor","3154309"],["MG","Ressaquinha","3154408"],["MG","Riachinho","3154457"],["MG","Riacho dos Machados","3154507"],["MG","Ribeirão das Neves","3154606"],["MG","Ribeirão Vermelho","3154705"],["MG","Rio Acima","3154804"],["MG","Rio Casca","3154903"],["MG","Rio do Prado","3155108"],["MG","Rio Doce","3155009"],["MG","Rio Espera","3155207"],["MG","Rio Manso","3155306"],["MG","Rio Novo","3155405"],["MG","Rio Paranaíba","3155504"],["MG","Rio Pardo de Minas","3155603"],["MG","Rio Piracicaba","3155702"],["MG","Rio Pomba","3155801"],["MG","Rio Preto","3155900"],["MG","Rio Vermelho","3156007"],["MG","Ritápolis","3156106"],["MG","Rochedo de Minas","3156205"],["MG","Rodeiro","3156304"],["MG","Romaria","3156403"],["MG","Rosário da Limeira","3156452"],["MG","Rubelita","3156502"],["MG","Rubim","3156601"],["MG","Sabará","3156700"],["MG","Sabinópolis","3156809"],["MG","Sacramento","3156908"],["MG","Salinas","3157005"],["MG","Salto da Divisa","3157104"],["MG","Santa Bárbara","3157203"],["MG","Santa Bárbara do Leste","3157252"],["MG","Santa Bárbara do Monte Verde","3157278"],["MG","Santa Bárbara do Tugúrio","3157302"],["MG","Santa Cruz de Minas","3157336"],["MG","Santa Cruz de Salinas","3157377"],["MG","Santa Cruz do Escalvado","3157401"],["MG","Santa Efigênia de Minas","3157500"],["MG","Santa Fé de Minas","3157609"],["MG","Santa Helena de Minas","3157658"],["MG","Santa Juliana","3157708"],["MG","Santa Luzia","3157807"],["MG","Santa Margarida","3157906"],["MG","Santa Maria de Itabira","3158003"],["MG","Santa Maria do Salto","3158102"],["MG","Santa Maria do Suaçuí","3158201"],["MG","Santa Rita de Caldas","3159209"],["MG","Santa Rita de Ibitipoca","3159407"],["MG","Santa Rita de Jacutinga","3159308"],["MG","Santa Rita de Minas","3159357"],["MG","Santa Rita do Itueto","3159506"],["MG","Santa Rita do Sapucaí","3159605"],["MG","Santa Rosa da Serra","3159704"],["MG","Santa Vitória","3159803"],["MG","Santana da Vargem","3158300"],["MG","Santana de Cataguases","3158409"],["MG","Santana de Pirapama","3158508"],["MG","Santana do Deserto","3158607"],["MG","Santana do Garambéu","3158706"],["MG","Santana do Jacaré","3158805"],["MG","Santana do Manhuaçu","3158904"],["MG","Santana do Paraíso","3158953"],["MG","Santana do Riacho","3159001"],["MG","Santana dos Montes","3159100"],["MG","Santo Antônio do Amparo","3159902"],["MG","Santo Antônio do Aventureiro","3160009"],["MG","Santo Antônio do Grama","3160108"],["MG","Santo Antônio do Itambé","3160207"],["MG","Santo Antônio do Jacinto","3160306"],["MG","Santo Antônio do Monte","3160405"],["MG","Santo Antônio do Retiro","3160454"],["MG","Santo Antônio do Rio Abaixo","3160504"],["MG","Santo Hipólito","3160603"],["MG","Santos Dumont","3160702"],["MG","São Bento Abade","3160801"],["MG","São Brás do Suaçuí","3160900"],["MG","São Domingos das Dores","3160959"],["MG","São Domingos do Prata","3161007"],["MG","São Félix de Minas","3161056"],["MG","São Francisco","3161106"],["MG","São Francisco de Paula","3161205"],["MG","São Francisco de Sales","3161304"],["MG","São Francisco do Glória","3161403"],["MG","São Geraldo","3161502"],["MG","São Geraldo da Piedade","3161601"],["MG","São Geraldo do Baixio","3161650"],["MG","São Gonçalo do Abaeté","3161700"],["MG","São Gonçalo do Pará","3161809"],["MG","São Gonçalo do Rio Abaixo","3161908"],["MG","São Gonçalo do Rio Preto","3125507"],["MG","São Gonçalo do Sapucaí","3162005"],["MG","São Gotardo","3162104"],["MG","São João Batista do Glória","3162203"],["MG","São João da Lagoa","3162252"],["MG","São João da Mata","3162302"],["MG","São João da Ponte","3162401"],["MG","São João das Missões","3162450"],["MG","São João del Rei","3162500"],["MG","São João do Manhuaçu","3162559"],["MG","São João do Manteninha","3162575"],["MG","São João do Oriente","3162609"],["MG","São João do Pacuí","3162658"],["MG","São João do Paraíso","3162708"],["MG","São João Evangelista","3162807"],["MG","São João Nepomuceno","3162906"],["MG","São Joaquim de Bicas","3162922"],["MG","São José da Barra","3162948"],["MG","São José da Lapa","3162955"],["MG","São José da Safira","3163003"],["MG","São José da Varginha","3163102"],["MG","São José do Alegre","3163201"],["MG","São José do Divino","3163300"],["MG","São José do Goiabal","3163409"],["MG","São José do Jacuri","3163508"],["MG","São José do Mantimento","3163607"],["MG","São Lourenço","3163706"],["MG","São Miguel do Anta","3163805"],["MG","São Pedro da União","3163904"],["MG","São Pedro do Suaçuí","3164100"],["MG","São Pedro dos Ferros","3164001"],["MG","São Romão","3164209"],["MG","São Roque de Minas","3164308"],["MG","São Sebastião da Bela Vista","3164407"],["MG","São Sebastião da Vargem Alegre","3164431"],["MG","São Sebastião do Anta","3164472"],["MG","São Sebastião do Maranhão","3164506"],["MG","São Sebastião do Oeste","3164605"],["MG","São Sebastião do Paraíso","3164704"],["MG","São Sebastião do Rio Preto","3164803"],["MG","São Sebastião do Rio Verde","3164902"],["MG","São Tiago","3165008"],["MG","São Tomás de Aquino","3165107"],["MG","São Tomé das Letras","3165206"],["MG","São Vicente de Minas","3165305"],["MG","Sapucaí-Mirim","3165404"],["MG","Sardoá","3165503"],["MG","Sarzedo","3165537"],["MG","Sem-Peixe","3165560"],["MG","Senador Amaral","3165578"],["MG","Senador Cortes","3165602"],["MG","Senador Firmino","3165701"],["MG","Senador José Bento","3165800"],["MG","Senador Modestino Gonçalves","3165909"],["MG","Senhora de Oliveira","3166006"],["MG","Senhora do Porto","3166105"],["MG","Senhora dos Remédios","3166204"],["MG","Sericita","3166303"],["MG","Seritinga","3166402"],["MG","Serra Azul de Minas","3166501"],["MG","Serra da Saudade","3166600"],["MG","Serra do Salitre","3166808"],["MG","Serra dos Aimorés","3166709"],["MG","Serrania","3166907"],["MG","Serranópolis de Minas","3166956"],["MG","Serranos","3167004"],["MG","Serro","3167103"],["MG","Sete Lagoas","3167202"],["MG","Setubinha","3165552"],["MG","Silveirânia","3167301"],["MG","Silvianópolis","3167400"],["MG","Simão Pereira","3167509"],["MG","Simonésia","3167608"],["MG","Sobrália","3167707"],["MG","Soledade de Minas","3167806"],["MG","Tabuleiro","3167905"],["MG","Taiobeiras","3168002"],["MG","Taparuba","3168051"],["MG","Tapira","3168101"],["MG","Tapiraí","3168200"],["MG","Taquaraçu de Minas","3168309"],["MG","Tarumirim","3168408"],["MG","Teixeiras","3168507"],["MG","Teófilo Otoni","3168606"],["MG","Timóteo","3168705"],["MG","Tiradentes","3168804"],["MG","Tiros","3168903"],["MG","Tocantins","3169000"],["MG","Tocos do Moji","3169059"],["MG","Toledo","3169109"],["MG","Tombos","3169208"],["MG","Três Corações","3169307"],["MG","Três Marias","3169356"],["MG","Três Pontas","3169406"],["MG","Tumiritinga","3169505"],["MG","Tupaciguara","3169604"],["MG","Turmalina","3169703"],["MG","Turvolândia","3169802"],["MG","Ubá","3169901"],["MG","Ubaí","3170008"],["MG","Ubaporanga","3170057"],["MG","Uberaba","3170107"],["MG","Uberlândia","3170206"],["MG","Umburatiba","3170305"],["MG","Unaí","3170404"],["MG","União de Minas","3170438"],["MG","Uruana de Minas","3170479"],["MG","Urucânia","3170503"],["MG","Urucuia","3170529"],["MG","Vargem Alegre","3170578"],["MG","Vargem Bonita","3170602"],["MG","Vargem Grande do Rio Pardo","3170651"],["MG","Varginha","3170701"],["MG","Varjão de Minas","3170750"],["MG","Várzea da Palma","3170800"],["MG","Varzelândia","3170909"],["MG","Vazante","3171006"],["MG","Verdelândia","3171030"],["MG","Veredinha","3171071"],["MG","Veríssimo","3171105"],["MG","Vermelho Novo","3171154"],["MG","Vespasiano","3171204"],["MG","Viçosa","3171303"],["MG","Vieiras","3171402"],["MG","Virgem da Lapa","3171600"],["MG","Virgínia","3171709"],["MG","Virginópolis","3171808"],["MG","Virgolândia","3171907"],["MG","Visconde do Rio Branco","3172004"],["MG","Volta Grande","3172103"],["MG","Wenceslau Braz","3172202"],["PA","Abaetetuba","1500107"],["PA","Abel Figueiredo","1500131"],["PA","Acará","1500206"],["PA","Afuá","1500305"],["PA","Água Azul do Norte","1500347"],["PA","Alenquer","1500404"],["PA","Almeirim","1500503"],["PA","Altamira","1500602"],["PA","Anajás","1500701"],["PA","Ananindeua","1500800"],["PA","Anapu","1500859"],["PA","Augusto Corrêa","1500909"],["PA","Aurora do Pará","1500958"],["PA","Aveiro","1501006"],["PA","Bagre","1501105"],["PA","Baião","1501204"],["PA","Bannach","1501253"],["PA","Barcarena","1501303"],["PA","Belém","1501402"],["PA","Belterra","1501451"],["PA","Benevides","1501501"],["PA","Bom Jesus do Tocantins","1501576"],["PA","Bonito","1501600"],["PA","Bragança","1501709"],["PA","Brasil Novo","1501725"],["PA","Brejo Grande do Araguaia","1501758"],["PA","Breu Branco","1501782"],["PA","Breves","1501808"],["PA","Bujaru","1501907"],["PA","Cachoeira do Arari","1502004"],["PA","Cachoeira do Piriá","1501956"],["PA","Cametá","1502103"],["PA","Canaã dos Carajás","1502152"],["PA","Capanema","1502202"],["PA","Capitão Poço","1502301"],["PA","Castanhal","1502400"],["PA","Chaves","1502509"],["PA","Colares","1502608"],["PA","Conceição do Araguaia","1502707"],["PA","Concórdia do Pará","1502756"],["PA","Cumaru do Norte","1502764"],["PA","Curionópolis","1502772"],["PA","Curralinho","1502806"],["PA","Curuá","1502855"],["PA","Curuçá","1502905"],["PA","Dom Eliseu","1502939"],["PA","Eldorado do Carajás","1502954"],["PA","Faro","1503002"],["PA","Floresta do Araguaia","1503044"],["PA","Garrafão do Norte","1503077"],["PA","Goianésia do Pará","1503093"],["PA","Gurupá","1503101"],["PA","Igarapé-Açu","1503200"],["PA","Igarapé-Miri","1503309"],["PA","Inhangapi","1503408"],["PA","Ipixuna do Pará","1503457"],["PA","Irituia","1503507"],["PA","Itaituba","1503606"],["PA","Itupiranga","1503705"],["PA","Jacareacanga","1503754"],["PA","Jacundá","1503804"],["PA","Juruti","1503903"],["PA","Limoeiro do Ajuru","1504000"],["PA","Mãe do Rio","1504059"],["PA","Magalhães Barata","1504109"],["PA","Marabá","1504208"],["PA","Maracanã","1504307"],["PA","Marapanim","1504406"],["PA","Marituba","1504422"],["PA","Medicilândia","1504455"],["PA","Melgaço","1504505"],["PA","Mocajuba","1504604"],["PA","Moju","1504703"],["PA","Mojuí dos Campos","1504752"],["PA","Monte Alegre","1504802"],["PA","Muaná","1504901"],["PA","Nova Esperança do Piriá","1504950"],["PA","Nova Ipixuna","1504976"],["PA","Nova Timboteua","1505007"],["PA","Novo Progresso","1505031"],["PA","Novo Repartimento","1505064"],["PA","Óbidos","1505106"],["PA","Oeiras do Pará","1505205"],["PA","Oriximiná","1505304"],["PA","Ourém","1505403"],["PA","Ourilândia do Norte","1505437"],["PA","Pacajá","1505486"],["PA","Palestina do Pará","1505494"],["PA","Paragominas","1505502"],["PA","Parauapebas","1505536"],["PA","Pau D'Arco","1505551"],["PA","Peixe-Boi","1505601"],["PA","Piçarra","1505635"],["PA","Placas","1505650"],["PA","Ponta de Pedras","1505700"],["PA","Portel","1505809"],["PA","Porto de Moz","1505908"],["PA","Prainha","1506005"],["PA","Primavera","1506104"],["PA","Quatipuru","1506112"],["PA","Redenção","1506138"],["PA","Rio Maria","1506161"],["PA","Rondon do Pará","1506187"],["PA","Rurópolis","1506195"],["PA","Salinópolis","1506203"],["PA","Salvaterra","1506302"],["PA","Santa Bárbara do Pará","1506351"],["PA","Santa Cruz do Arari","1506401"],["PA","Santa Izabel do Pará","1506500"],["PA","Santa Luzia do Pará","1506559"],["PA","Santa Maria das Barreiras","1506583"],["PA","Santa Maria do Pará","1506609"],["PA","Santana do Araguaia","1506708"],["PA","Santarém","1506807"],["PA","Santarém Novo","1506906"],["PA","Santo Antônio do Tauá","1507003"],["PA","São Caetano de Odivelas","1507102"],["PA","São Domingos do Araguaia","1507151"],["PA","São Domingos do Capim","1507201"],["PA","São Félix do Xingu","1507300"],["PA","São Francisco do Pará","1507409"],["PA","São Geraldo do Araguaia","1507458"],["PA","São João da Ponta","1507466"],["PA","São João de Pirabas","1507474"],["PA","São João do Araguaia","1507508"],["PA","São Miguel do Guamá","1507607"],["PA","São Sebastião da Boa Vista","1507706"],["PA","Sapucaia","1507755"],["PA","Senador José Porfírio","1507805"],["PA","Soure","1507904"],["PA","Tailândia","1507953"],["PA","Terra Alta","1507961"],["PA","Terra Santa","1507979"],["PA","Tomé-Açu","1508001"],["PA","Tracuateua","1508035"],["PA","Trairão","1508050"],["PA","Tucumã","1508084"],["PA","Tucuruí","1508100"],["PA","Ulianópolis","1508126"],["PA","Uruará","1508159"],["PA","Vigia","1508209"],["PA","Viseu","1508308"],["PA","Vitória do Xingu","1508357"],["PA","Xinguara","1508407"],["PB","Água Branca","2500106"],["PB","Aguiar","2500205"],["PB","Alagoa Grande","2500304"],["PB","Alagoa Nova","2500403"],["PB","Alagoinha","2500502"],["PB","Alcantil","2500536"],["PB","Algodão de Jandaíra","2500577"],["PB","Alhandra","2500601"],["PB","Amparo","2500734"],["PB","Aparecida","2500775"],["PB","Araçagi","2500809"],["PB","Arara","2500908"],["PB","Araruna","2501005"],["PB","Areia","2501104"],["PB","Areia de Baraúnas","2501153"],["PB","Areial","2501203"],["PB","Aroeiras","2501302"],["PB","Assunção","2501351"],["PB","Baía da Traição","2501401"],["PB","Bananeiras","2501500"],["PB","Baraúna","2501534"],["PB","Barra de Santa Rosa","2501609"],["PB","Barra de Santana","2501575"],["PB","Barra de São Miguel","2501708"],["PB","Bayeux","2501807"],["PB","Belém","2501906"],["PB","Belém do Brejo do Cruz","2502003"],["PB","Bernardino Batista","2502052"],["PB","Boa Ventura","2502102"],["PB","Boa Vista","2502151"],["PB","Bom Jesus","2502201"],["PB","Bom Sucesso","2502300"],["PB","Bonito de Santa Fé","2502409"],["PB","Boqueirão","2502508"],["PB","Borborema","2502706"],["PB","Brejo do Cruz","2502805"],["PB","Brejo dos Santos","2502904"],["PB","Caaporã","2503001"],["PB","Cabaceiras","2503100"],["PB","Cabedelo","2503209"],["PB","Cachoeira dos Índios","2503308"],["PB","Cacimba de Areia","2503407"],["PB","Cacimba de Dentro","2503506"],["PB","Cacimbas","2503555"],["PB","Caiçara","2503605"],["PB","Cajazeiras","2503704"],["PB","Cajazeirinhas","2503753"],["PB","Caldas Brandão","2503803"],["PB","Camalaú","2503902"],["PB","Campina Grande","2504009"],["PB","Capim","2504033"],["PB","Caraúbas","2504074"],["PB","Carrapateira","2504108"],["PB","Casserengue","2504157"],["PB","Catingueira","2504207"],["PB","Catolé do Rocha","2504306"],["PB","Caturité","2504355"],["PB","Conceição","2504405"],["PB","Condado","2504504"],["PB","Conde","2504603"],["PB","Congo","2504702"],["PB","Coremas","2504801"],["PB","Coxixola","2504850"],["PB","Cruz do Espírito Santo","2504900"],["PB","Cubati","2505006"],["PB","Cuité","2505105"],["PB","Cuité de Mamanguape","2505238"],["PB","Cuitegi","2505204"],["PB","Curral de Cima","2505279"],["PB","Curral Velho","2505303"],["PB","Damião","2505352"],["PB","Desterro","2505402"],["PB","Diamante","2505600"],["PB","Dona Inês","2505709"],["PB","Duas Estradas","2505808"],["PB","Emas","2505907"],["PB","Esperança","2506004"],["PB","Fagundes","2506103"],["PB","Frei Martinho","2506202"],["PB","Gado Bravo","2506251"],["PB","Guarabira","2506301"],["PB","Gurinhém","2506400"],["PB","Gurjão","2506509"],["PB","Ibiara","2506608"],["PB","Igaracy","2502607"],["PB","Imaculada","2506707"],["PB","Ingá","2506806"],["PB","Itabaiana","2506905"],["PB","Itaporanga","2507002"],["PB","Itapororoca","2507101"],["PB","Itatuba","2507200"],["PB","Jacaraú","2507309"],["PB","Jericó","2507408"],["PB","João Pessoa","2507507"],["PB","Joca Claudino","2513653"],["PB","Juarez Távora","2507606"],["PB","Juazeirinho","2507705"],["PB","Junco do Seridó","2507804"],["PB","Juripiranga","2507903"],["PB","Juru","2508000"],["PB","Lagoa","2508109"],["PB","Lagoa de Dentro","2508208"],["PB","Lagoa Seca","2508307"],["PB","Lastro","2508406"],["PB","Livramento","2508505"],["PB","Logradouro","2508554"],["PB","Lucena","2508604"],["PB","Mãe d'Água","2508703"],["PB","Malta","2508802"],["PB","Mamanguape","2508901"],["PB","Manaíra","2509008"],["PB","Marcação","2509057"],["PB","Mari","2509107"],["PB","Marizópolis","2509156"],["PB","Massaranduba","2509206"],["PB","Mataraca","2509305"],["PB","Matinhas","2509339"],["PB","Mato Grosso","2509370"],["PB","Maturéia","2509396"],["PB","Mogeiro","2509404"],["PB","Montadas","2509503"],["PB","Monte Horebe","2509602"],["PB","Monteiro","2509701"],["PB","Mulungu","2509800"],["PB","Natuba","2509909"],["PB","Nazarezinho","2510006"],["PB","Nova Floresta","2510105"],["PB","Nova Olinda","2510204"],["PB","Nova Palmeira","2510303"],["PB","Olho d'Água","2510402"],["PB","Olivedos","2510501"],["PB","Ouro Velho","2510600"],["PB","Parari","2510659"],["PB","Passagem","2510709"],["PB","Patos","2510808"],["PB","Paulista","2510907"],["PB","Pedra Branca","2511004"],["PB","Pedra Lavrada","2511103"],["PB","Pedras de Fogo","2511202"],["PB","Pedro Régis","2512721"],["PB","Piancó","2511301"],["PB","Picuí","2511400"],["PB","Pilar","2511509"],["PB","Pilões","2511608"],["PB","Pilõezinhos","2511707"],["PB","Pirpirituba","2511806"],["PB","Pitimbu","2511905"],["PB","Pocinhos","2512002"],["PB","Poço Dantas","2512036"],["PB","Poço de José de Moura","2512077"],["PB","Pombal","2512101"],["PB","Prata","2512200"],["PB","Princesa Isabel","2512309"],["PB","Puxinanã","2512408"],["PB","Queimadas","2512507"],["PB","Quixaba","2512606"],["PB","Remígio","2512705"],["PB","Riachão","2512747"],["PB","Riachão do Bacamarte","2512754"],["PB","Riachão do Poço","2512762"],["PB","Riacho de Santo Antônio","2512788"],["PB","Riacho dos Cavalos","2512804"],["PB","Rio Tinto","2512903"],["PB","Salgadinho","2513000"],["PB","Salgado de São Félix","2513109"],["PB","Santa Cecília","2513158"],["PB","Santa Cruz","2513208"],["PB","Santa Helena","2513307"],["PB","Santa Inês","2513356"],["PB","Santa Luzia","2513406"],["PB","Santa Rita","2513703"],["PB","Santa Teresinha","2513802"],["PB","Santana de Mangueira","2513505"],["PB","Santana dos Garrotes","2513604"],["PB","Santo André","2513851"],["PB","São Bentinho","2513927"],["PB","São Bento","2513901"],["PB","São Domingos","2513968"],["PB","São Domingos do Cariri","2513943"],["PB","São Francisco","2513984"],["PB","São João do Cariri","2514008"],["PB","São João do Rio do Peixe","2500700"],["PB","São João do Tigre","2514107"],["PB","São José da Lagoa Tapada","2514206"],["PB","São José de Caiana","2514305"],["PB","São José de Espinharas","2514404"],["PB","São José de Piranhas","2514503"],["PB","São José de Princesa","2514552"],["PB","São José do Bonfim","2514602"],["PB","São José do Brejo do Cruz","2514651"],["PB","São José do Sabugi","2514701"],["PB","São José dos Cordeiros","2514800"],["PB","São José dos Ramos","2514453"],["PB","São Mamede","2514909"],["PB","São Miguel de Taipu","2515005"],["PB","São Sebastião de Lagoa de Roça","2515104"],["PB","São Sebastião do Umbuzeiro","2515203"],["PB","São Vicente do Seridó","2515401"],["PB","Sapé","2515302"],["PB","Serra Branca","2515500"],["PB","Serra da Raiz","2515609"],["PB","Serra Grande","2515708"],["PB","Serra Redonda","2515807"],["PB","Serraria","2515906"],["PB","Sertãozinho","2515930"],["PB","Sobrado","2515971"],["PB","Solânea","2516003"],["PB","Soledade","2516102"],["PB","Sossêgo","2516151"],["PB","Sousa","2516201"],["PB","Sumé","2516300"],["PB","Tacima","2516409"],["PB","Taperoá","2516508"],["PB","Tavares","2516607"],["PB","Teixeira","2516706"],["PB","Tenório","2516755"],["PB","Triunfo","2516805"],["PB","Uiraúna","2516904"],["PB","Umbuzeiro","2517001"],["PB","Várzea","2517100"],["PB","Vieirópolis","2517209"],["PB","Vista Serrana","2505501"],["PB","Zabelê","2517407"],["PR","Abatiá","4100103"],["PR","Adrianópolis","4100202"],["PR","Agudos do Sul","4100301"],["PR","Almirante Tamandaré","4100400"],["PR","Altamira do Paraná","4100459"],["PR","Alto Paraíso","4128625"],["PR","Alto Paraná","4100608"],["PR","Alto Piquiri","4100707"],["PR","Altônia","4100509"],["PR","Alvorada do Sul","4100806"],["PR","Amaporã","4100905"],["PR","Ampére","4101002"],["PR","Anahy","4101051"],["PR","Andirá","4101101"],["PR","Ângulo","4101150"],["PR","Antonina","4101200"],["PR","Antônio Olinto","4101309"],["PR","Apucarana","4101408"],["PR","Arapongas","4101507"],["PR","Arapoti","4101606"],["PR","Arapuã","4101655"],["PR","Araruna","4101705"],["PR","Araucária","4101804"],["PR","Ariranha do Ivaí","4101853"],["PR","Assaí","4101903"],["PR","Assis Chateaubriand","4102000"],["PR","Astorga","4102109"],["PR","Atalaia","4102208"],["PR","Balsa Nova","4102307"],["PR","Bandeirantes","4102406"],["PR","Barbosa Ferraz","4102505"],["PR","Barra do Jacaré","4102703"],["PR","Barracão","4102604"],["PR","Bela Vista da Caroba","4102752"],["PR","Bela Vista do Paraíso","4102802"],["PR","Bituruna","4102901"],["PR","Boa Esperança","4103008"],["PR","Boa Esperança do Iguaçu","4103024"],["PR","Boa Ventura de São Roque","4103040"],["PR","Boa Vista da Aparecida","4103057"],["PR","Bocaiúva do Sul","4103107"],["PR","Bom Jesus do Sul","4103156"],["PR","Bom Sucesso","4103206"],["PR","Bom Sucesso do Sul","4103222"],["PR","Borrazópolis","4103305"],["PR","Braganey","4103354"],["PR","Brasilândia do Sul","4103370"],["PR","Cafeara","4103404"],["PR","Cafelândia","4103453"],["PR","Cafezal do Sul","4103479"],["PR","Califórnia","4103503"],["PR","Cambará","4103602"],["PR","Cambé","4103701"],["PR","Cambira","4103800"],["PR","Campina da Lagoa","4103909"],["PR","Campina do Simão","4103958"],["PR","Campina Grande do Sul","4104006"],["PR","Campo Bonito","4104055"],["PR","Campo do Tenente","4104105"],["PR","Campo Largo","4104204"],["PR","Campo Magro","4104253"],["PR","Campo Mourão","4104303"],["PR","Cândido de Abreu","4104402"],["PR","Candói","4104428"],["PR","Cantagalo","4104451"],["PR","Capanema","4104501"],["PR","Capitão Leônidas Marques","4104600"],["PR","Carambeí","4104659"],["PR","Carlópolis","4104709"],["PR","Cascavel","4104808"],["PR","Castro","4104907"],["PR","Catanduvas","4105003"],["PR","Centenário do Sul","4105102"],["PR","Cerro Azul","4105201"],["PR","Céu Azul","4105300"],["PR","Chopinzinho","4105409"],["PR","Cianorte","4105508"],["PR","Cidade Gaúcha","4105607"],["PR","Clevelândia","4105706"],["PR","Colombo","4105805"],["PR","Colorado","4105904"],["PR","Congonhinhas","4106001"],["PR","Conselheiro Mairinck","4106100"],["PR","Contenda","4106209"],["PR","Corbélia","4106308"],["PR","Cornélio Procópio","4106407"],["PR","Coronel Domingos Soares","4106456"],["PR","Coronel Vivida","4106506"],["PR","Corumbataí do Sul","4106555"],["PR","Cruz Machado","4106803"],["PR","Cruzeiro do Iguaçu","4106571"],["PR","Cruzeiro do Oeste","4106605"],["PR","Cruzeiro do Sul","4106704"],["PR","Cruzmaltina","4106852"],["PR","Curitiba","4106902"],["PR","Curiúva","4107009"],["PR","Diamante D'Oeste","4107157"],["PR","Diamante do Norte","4107108"],["PR","Diamante do Sul","4107124"],["PR","Dois Vizinhos","4107207"],["PR","Douradina","4107256"],["PR","Doutor Camargo","4107306"],["PR","Doutor Ulysses","4128633"],["PR","Enéas Marques","4107405"],["PR","Engenheiro Beltrão","4107504"],["PR","Entre Rios do Oeste","4107538"],["PR","Esperança Nova","4107520"],["PR","Espigão Alto do Iguaçu","4107546"],["PR","Farol","4107553"],["PR","Faxinal","4107603"],["PR","Fazenda Rio Grande","4107652"],["PR","Fênix","4107702"],["PR","Fernandes Pinheiro","4107736"],["PR","Figueira","4107751"],["PR","Flor da Serra do Sul","4107850"],["PR","Floraí","4107801"],["PR","Floresta","4107900"],["PR","Florestópolis","4108007"],["PR","Flórida","4108106"],["PR","Formosa do Oeste","4108205"],["PR","Foz do Iguaçu","4108304"],["PR","Foz do Jordão","4108452"],["PR","Francisco Alves","4108320"],["PR","Francisco Beltrão","4108403"],["PR","General Carneiro","4108502"],["PR","Godoy Moreira","4108551"],["PR","Goioerê","4108601"],["PR","Goioxim","4108650"],["PR","Grandes Rios","4108700"],["PR","Guaíra","4108809"],["PR","Guairaçá","4108908"],["PR","Guamiranga","4108957"],["PR","Guapirama","4109005"],["PR","Guaporema","4109104"],["PR","Guaraci","4109203"],["PR","Guaraniaçu","4109302"],["PR","Guarapuava","4109401"],["PR","Guaraqueçaba","4109500"],["PR","Guaratuba","4109609"],["PR","Honório Serpa","4109658"],["PR","Ibaiti","4109708"],["PR","Ibema","4109757"],["PR","Ibiporã","4109807"],["PR","Icaraíma","4109906"],["PR","Iguaraçu","4110003"],["PR","Iguatu","4110052"],["PR","Imbaú","4110078"],["PR","Imbituva","4110102"],["PR","Inácio Martins","4110201"],["PR","Inajá","4110300"],["PR","Indianópolis","4110409"],["PR","Ipiranga","4110508"],["PR","Iporã","4110607"],["PR","Iracema do Oeste","4110656"],["PR","Irati","4110706"],["PR","Iretama","4110805"],["PR","Itaguajé","4110904"],["PR","Itaipulândia","4110953"],["PR","Itambaracá","4111001"],["PR","Itambé","4111100"],["PR","Itapejara d'Oeste","4111209"],["PR","Itaperuçu","4111258"],["PR","Itaúna do Sul","4111308"],["PR","Ivaí","4111407"],["PR","Ivaiporã","4111506"],["PR","Ivaté","4111555"],["PR","Ivatuba","4111605"],["PR","Jaboti","4111704"],["PR","Jacarezinho","4111803"],["PR","Jaguapitã","4111902"],["PR","Jaguariaíva","4112009"],["PR","Jandaia do Sul","4112108"],["PR","Janiópolis","4112207"],["PR","Japira","4112306"],["PR","Japurá","4112405"],["PR","Jardim Alegre","4112504"],["PR","Jardim Olinda","4112603"],["PR","Jataizinho","4112702"],["PR","Jesuítas","4112751"],["PR","Joaquim Távora","4112801"],["PR","Jundiaí do Sul","4112900"],["PR","Juranda","4112959"],["PR","Jussara","4113007"],["PR","Kaloré","4113106"],["PR","Lapa","4113205"],["PR","Laranjal","4113254"],["PR","Laranjeiras do Sul","4113304"],["PR","Leópolis","4113403"],["PR","Lidianópolis","4113429"],["PR","Lindoeste","4113452"],["PR","Loanda","4113502"],["PR","Lobato","4113601"],["PR","Londrina","4113700"],["PR","Luiziana","4113734"],["PR","Lunardelli","4113759"],["PR","Lupionópolis","4113809"],["PR","Mallet","4113908"],["PR","Mamborê","4114005"],["PR","Mandaguaçu","4114104"],["PR","Mandaguari","4114203"],["PR","Mandirituba","4114302"],["PR","Manfrinópolis","4114351"],["PR","Mangueirinha","4114401"],["PR","Manoel Ribas","4114500"],["PR","Marechal Cândido Rondon","4114609"],["PR","Maria Helena","4114708"],["PR","Marialva","4114807"],["PR","Marilândia do Sul","4114906"],["PR","Marilena","4115002"],["PR","Mariluz","4115101"],["PR","Maringá","4115200"],["PR","Mariópolis","4115309"],["PR","Maripá","4115358"],["PR","Marmeleiro","4115408"],["PR","Marquinho","4115457"],["PR","Marumbi","4115507"],["PR","Matelândia","4115606"],["PR","Matinhos","4115705"],["PR","Mato Rico","4115739"],["PR","Mauá da Serra","4115754"],["PR","Medianeira","4115804"],["PR","Mercedes","4115853"],["PR","Mirador","4115903"],["PR","Miraselva","4116000"],["PR","Missal","4116059"],["PR","Moreira Sales","4116109"],["PR","Morretes","4116208"],["PR","Munhoz de Melo","4116307"],["PR","Nossa Senhora das Graças","4116406"],["PR","Nova Aliança do Ivaí","4116505"],["PR","Nova América da Colina","4116604"],["PR","Nova Aurora","4116703"],["PR","Nova Cantu","4116802"],["PR","Nova Esperança","4116901"],["PR","Nova Esperança do Sudoeste","4116950"],["PR","Nova Fátima","4117008"],["PR","Nova Laranjeiras","4117057"],["PR","Nova Londrina","4117107"],["PR","Nova Olímpia","4117206"],["PR","Nova Prata do Iguaçu","4117255"],["PR","Nova Santa Bárbara","4117214"],["PR","Nova Santa Rosa","4117222"],["PR","Nova Tebas","4117271"],["PR","Novo Itacolomi","4117297"],["PR","Ortigueira","4117305"],["PR","Ourizona","4117404"],["PR","Ouro Verde do Oeste","4117453"],["PR","Paiçandu","4117503"],["PR","Palmas","4117602"],["PR","Palmeira","4117701"],["PR","Palmital","4117800"],["PR","Palotina","4117909"],["PR","Paraíso do Norte","4118006"],["PR","Paranacity","4118105"],["PR","Paranaguá","4118204"],["PR","Paranapoema","4118303"],["PR","Paranavaí","4118402"],["PR","Pato Bragado","4118451"],["PR","Pato Branco","4118501"],["PR","Paula Freitas","4118600"],["PR","Paulo Frontin","4118709"],["PR","Peabiru","4118808"],["PR","Perobal","4118857"],["PR","Pérola","4118907"],["PR","Pérola d'Oeste","4119004"],["PR","Piên","4119103"],["PR","Pinhais","4119152"],["PR","Pinhal de São Bento","4119251"],["PR","Pinhalão","4119202"],["PR","Pinhão","4119301"],["PR","Piraí do Sul","4119400"],["PR","Piraquara","4119509"],["PR","Pitanga","4119608"],["PR","Pitangueiras","4119657"],["PR","Planaltina do Paraná","4119707"],["PR","Planalto","4119806"],["PR","Ponta Grossa","4119905"],["PR","Pontal do Paraná","4119954"],["PR","Porecatu","4120002"],["PR","Porto Amazonas","4120101"],["PR","Porto Barreiro","4120150"],["PR","Porto Rico","4120200"],["PR","Porto Vitória","4120309"],["PR","Prado Ferreira","4120333"],["PR","Pranchita","4120358"],["PR","Presidente Castelo Branco","4120408"],["PR","Primeiro de Maio","4120507"],["PR","Prudentópolis","4120606"],["PR","Quarto Centenário","4120655"],["PR","Quatiguá","4120705"],["PR","Quatro Barras","4120804"],["PR","Quatro Pontes","4120853"],["PR","Quedas do Iguaçu","4120903"],["PR","Querência do Norte","4121000"],["PR","Quinta do Sol","4121109"],["PR","Quitandinha","4121208"],["PR","Ramilândia","4121257"],["PR","Rancho Alegre","4121307"],["PR","Rancho Alegre D'Oeste","4121356"],["PR","Realeza","4121406"],["PR","Rebouças","4121505"],["PR","Renascença","4121604"],["PR","Reserva","4121703"],["PR","Reserva do Iguaçu","4121752"],["PR","Ribeirão Claro","4121802"],["PR","Ribeirão do Pinhal","4121901"],["PR","Rio Azul","4122008"],["PR","Rio Bom","4122107"],["PR","Rio Bonito do Iguaçu","4122156"],["PR","Rio Branco do Ivaí","4122172"],["PR","Rio Branco do Sul","4122206"],["PR","Rio Negro","4122305"],["PR","Rolândia","4122404"],["PR","Roncador","4122503"],["PR","Rondon","4122602"],["PR","Rosário do Ivaí","4122651"],["PR","Sabáudia","4122701"],["PR","Salgado Filho","4122800"],["PR","Salto do Itararé","4122909"],["PR","Salto do Lontra","4123006"],["PR","Santa Amélia","4123105"],["PR","Santa Cecília do Pavão","4123204"],["PR","Santa Cruz de Monte Castelo","4123303"],["PR","Santa Fé","4123402"],["PR","Santa Helena","4123501"],["PR","Santa Inês","4123600"],["PR","Santa Isabel do Ivaí","4123709"],["PR","Santa Izabel do Oeste","4123808"],["PR","Santa Lúcia","4123824"],["PR","Santa Maria do Oeste","4123857"],["PR","Santa Mariana","4123907"],["PR","Santa Mônica","4123956"],["PR","Santa Tereza do Oeste","4124020"],["PR","Santa Terezinha de Itaipu","4124053"],["PR","Santana do Itararé","4124004"],["PR","Santo Antônio da Platina","4124103"],["PR","Santo Antônio do Caiuá","4124202"],["PR","Santo Antônio do Paraíso","4124301"],["PR","Santo Antônio do Sudoeste","4124400"],["PR","Santo Inácio","4124509"],["PR","São Carlos do Ivaí","4124608"],["PR","São Jerônimo da Serra","4124707"],["PR","São João","4124806"],["PR","São João do Caiuá","4124905"],["PR","São João do Ivaí","4125001"],["PR","São João do Triunfo","4125100"],["PR","São Jorge d'Oeste","4125209"],["PR","São Jorge do Ivaí","4125308"],["PR","São Jorge do Patrocínio","4125357"],["PR","São José da Boa Vista","4125407"],["PR","São José das Palmeiras","4125456"],["PR","São José dos Pinhais","4125506"],["PR","São Manoel do Paraná","4125555"],["PR","São Mateus do Sul","4125605"],["PR","São Miguel do Iguaçu","4125704"],["PR","São Pedro do Iguaçu","4125753"],["PR","São Pedro do Ivaí","4125803"],["PR","São Pedro do Paraná","4125902"],["PR","São Sebastião da Amoreira","4126009"],["PR","São Tomé","4126108"],["PR","Sapopema","4126207"],["PR","Sarandi","4126256"],["PR","Saudade do Iguaçu","4126272"],["PR","Sengés","4126306"],["PR","Serranópolis do Iguaçu","4126355"],["PR","Sertaneja","4126405"],["PR","Sertanópolis","4126504"],["PR","Siqueira Campos","4126603"],["PR","Sulina","4126652"],["PR","Tamarana","4126678"],["PR","Tamboara","4126702"],["PR","Tapejara","4126801"],["PR","Tapira","4126900"],["PR","Teixeira Soares","4127007"],["PR","Telêmaco Borba","4127106"],["PR","Terra Boa","4127205"],["PR","Terra Rica","4127304"],["PR","Terra Roxa","4127403"],["PR","Tibagi","4127502"],["PR","Tijucas do Sul","4127601"],["PR","Toledo","4127700"],["PR","Tomazina","4127809"],["PR","Três Barras do Paraná","4127858"],["PR","Tunas do Paraná","4127882"],["PR","Tuneiras do Oeste","4127908"],["PR","Tupãssi","4127957"],["PR","Turvo","4127965"],["PR","Ubiratã","4128005"],["PR","Umuarama","4128104"],["PR","União da Vitória","4128203"],["PR","Uniflor","4128302"],["PR","Uraí","4128401"],["PR","Ventania","4128534"],["PR","Vera Cruz do Oeste","4128559"],["PR","Verê","4128609"],["PR","Virmond","4128658"],["PR","Vitorino","4128708"],["PR","Wenceslau Braz","4128500"],["PR","Xambrê","4128807"],["PE","Abreu e Lima","2600054"],["PE","Afogados da Ingazeira","2600104"],["PE","Afrânio","2600203"],["PE","Agrestina","2600302"],["PE","Água Preta","2600401"],["PE","Águas Belas","2600500"],["PE","Alagoinha","2600609"],["PE","Aliança","2600708"],["PE","Altinho","2600807"],["PE","Amaraji","2600906"],["PE","Angelim","2601003"],["PE","Araçoiaba","2601052"],["PE","Araripina","2601102"],["PE","Arcoverde","2601201"],["PE","Barra de Guabiraba","2601300"],["PE","Barreiros","2601409"],["PE","Belém de Maria","2601508"],["PE","Belém do São Francisco","2601607"],["PE","Belo Jardim","2601706"],["PE","Betânia","2601805"],["PE","Bezerros","2601904"],["PE","Bodocó","2602001"],["PE","Bom Conselho","2602100"],["PE","Bom Jardim","2602209"],["PE","Bonito","2602308"],["PE","Brejão","2602407"],["PE","Brejinho","2602506"],["PE","Brejo da Madre de Deus","2602605"],["PE","Buenos Aires","2602704"],["PE","Buíque","2602803"],["PE","Cabo de Santo Agostinho","2602902"],["PE","Cabrobó","2603009"],["PE","Cachoeirinha","2603108"],["PE","Caetés","2603207"],["PE","Calçado","2603306"],["PE","Calumbi","2603405"],["PE","Camaragibe","2603454"],["PE","Camocim de São Félix","2603504"],["PE","Camutanga","2603603"],["PE","Canhotinho","2603702"],["PE","Capoeiras","2603801"],["PE","Carnaíba","2603900"],["PE","Carnaubeira da Penha","2603926"],["PE","Carpina","2604007"],["PE","Caruaru","2604106"],["PE","Casinhas","2604155"],["PE","Catende","2604205"],["PE","Cedro","2604304"],["PE","Chã de Alegria","2604403"],["PE","Chã Grande","2604502"],["PE","Condado","2604601"],["PE","Correntes","2604700"],["PE","Cortês","2604809"],["PE","Cumaru","2604908"],["PE","Cupira","2605004"],["PE","Custódia","2605103"],["PE","Dormentes","2605152"],["PE","Escada","2605202"],["PE","Exu","2605301"],["PE","Feira Nova","2605400"],["PE","Fernando de Noronha","2605459"],["PE","Ferreiros","2605509"],["PE","Flores","2605608"],["PE","Floresta","2605707"],["PE","Frei Miguelinho","2605806"],["PE","Gameleira","2605905"],["PE","Garanhuns","2606002"],["PE","Glória do Goitá","2606101"],["PE","Goiana","2606200"],["PE","Granito","2606309"],["PE","Gravatá","2606408"],["PE","Iati","2606507"],["PE","Ibimirim","2606606"],["PE","Ibirajuba","2606705"],["PE","Igarassu","2606804"],["PE","Iguaracy","2606903"],["PE","Ilha de Itamaracá","2607604"],["PE","Inajá","2607000"],["PE","Ingazeira","2607109"],["PE","Ipojuca","2607208"],["PE","Ipubi","2607307"],["PE","Itacuruba","2607406"],["PE","Itaíba","2607505"],["PE","Itambé","2607653"],["PE","Itapetim","2607703"],["PE","Itapissuma","2607752"],["PE","Itaquitinga","2607802"],["PE","Jaboatão dos Guararapes","2607901"],["PE","Jaqueira","2607950"],["PE","Jataúba","2608008"],["PE","Jatobá","2608057"],["PE","João Alfredo","2608107"],["PE","Joaquim Nabuco","2608206"],["PE","Jucati","2608255"],["PE","Jupi","2608305"],["PE","Jurema","2608404"],["PE","Lagoa de Itaenga","2608503"],["PE","Lagoa do Carro","2608453"],["PE","Lagoa do Ouro","2608602"],["PE","Lagoa dos Gatos","2608701"],["PE","Lagoa Grande","2608750"],["PE","Lajedo","2608800"],["PE","Limoeiro","2608909"],["PE","Macaparana","2609006"],["PE","Machados","2609105"],["PE","Manari","2609154"],["PE","Maraial","2609204"],["PE","Mirandiba","2609303"],["PE","Moreilândia","2614303"],["PE","Moreno","2609402"],["PE","Nazaré da Mata","2609501"],["PE","Olinda","2609600"],["PE","Orobó","2609709"],["PE","Orocó","2609808"],["PE","Ouricuri","2609907"],["PE","Palmares","2610004"],["PE","Palmeirina","2610103"],["PE","Panelas","2610202"],["PE","Paranatama","2610301"],["PE","Parnamirim","2610400"],["PE","Passira","2610509"],["PE","Paudalho","2610608"],["PE","Paulista","2610707"],["PE","Pedra","2610806"],["PE","Pesqueira","2610905"],["PE","Petrolândia","2611002"],["PE","Petrolina","2611101"],["PE","Poção","2611200"],["PE","Pombos","2611309"],["PE","Primavera","2611408"],["PE","Quipapá","2611507"],["PE","Quixaba","2611533"],["PE","Recife","2611606"],["PE","Riacho das Almas","2611705"],["PE","Ribeirão","2611804"],["PE","Rio Formoso","2611903"],["PE","Sairé","2612000"],["PE","Salgadinho","2612109"],["PE","Salgueiro","2612208"],["PE","Saloá","2612307"],["PE","Sanharó","2612406"],["PE","Santa Cruz","2612455"],["PE","Santa Cruz da Baixa Verde","2612471"],["PE","Santa Cruz do Capibaribe","2612505"],["PE","Santa Filomena","2612554"],["PE","Santa Maria da Boa Vista","2612604"],["PE","Santa Maria do Cambucá","2612703"],["PE","Santa Terezinha","2612802"],["PE","São Benedito do Sul","2612901"],["PE","São Bento do Una","2613008"],["PE","São Caitano","2613107"],["PE","São João","2613206"],["PE","São Joaquim do Monte","2613305"],["PE","São José da Coroa Grande","2613404"],["PE","São José do Belmonte","2613503"],["PE","São José do Egito","2613602"],["PE","São Lourenço da Mata","2613701"],["PE","São Vicente Férrer","2613800"],["PE","Serra Talhada","2613909"],["PE","Serrita","2614006"],["PE","Sertânia","2614105"],["PE","Sirinhaém","2614204"],["PE","Solidão","2614402"],["PE","Surubim","2614501"],["PE","Tabira","2614600"],["PE","Tacaimbó","2614709"],["PE","Tacaratu","2614808"],["PE","Tamandaré","2614857"],["PE","Taquaritinga do Norte","2615003"],["PE","Terezinha","2615102"],["PE","Terra Nova","2615201"],["PE","Timbaúba","2615300"],["PE","Toritama","2615409"],["PE","Tracunhaém","2615508"],["PE","Trindade","2615607"],["PE","Triunfo","2615706"],["PE","Tupanatinga","2615805"],["PE","Tuparetama","2615904"],["PE","Venturosa","2616001"],["PE","Verdejante","2616100"],["PE","Vertente do Lério","2616183"],["PE","Vertentes","2616209"],["PE","Vicência","2616308"],["PE","Vitória de Santo Antão","2616407"],["PE","Xexéu","2616506"],["PI","Acauã","2200053"],["PI","Agricolândia","2200103"],["PI","Água Branca","2200202"],["PI","Alagoinha do Piauí","2200251"],["PI","Alegrete do Piauí","2200277"],["PI","Alto Longá","2200301"],["PI","Altos","2200400"],["PI","Alvorada do Gurguéia","2200459"],["PI","Amarante","2200509"],["PI","Angical do Piauí","2200608"],["PI","Anísio de Abreu","2200707"],["PI","Antônio Almeida","2200806"],["PI","Aroazes","2200905"],["PI","Aroeiras do Itaim","2200954"],["PI","Arraial","2201002"],["PI","Assunção do Piauí","2201051"],["PI","Avelino Lopes","2201101"],["PI","Baixa Grande do Ribeiro","2201150"],["PI","Barra D'Alcântara","2201176"],["PI","Barras","2201200"],["PI","Barreiras do Piauí","2201309"],["PI","Barro Duro","2201408"],["PI","Batalha","2201507"],["PI","Bela Vista do Piauí","2201556"],["PI","Belém do Piauí","2201572"],["PI","Beneditinos","2201606"],["PI","Bertolínia","2201705"],["PI","Betânia do Piauí","2201739"],["PI","Boa Hora","2201770"],["PI","Bocaina","2201804"],["PI","Bom Jesus","2201903"],["PI","Bom Princípio do Piauí","2201919"],["PI","Bonfim do Piauí","2201929"],["PI","Boqueirão do Piauí","2201945"],["PI","Brasileira","2201960"],["PI","Brejo do Piauí","2201988"],["PI","Buriti dos Lopes","2202000"],["PI","Buriti dos Montes","2202026"],["PI","Cabeceiras do Piauí","2202059"],["PI","Cajazeiras do Piauí","2202075"],["PI","Cajueiro da Praia","2202083"],["PI","Caldeirão Grande do Piauí","2202091"],["PI","Campinas do Piauí","2202109"],["PI","Campo Alegre do Fidalgo","2202117"],["PI","Campo Grande do Piauí","2202133"],["PI","Campo Largo do Piauí","2202174"],["PI","Campo Maior","2202208"],["PI","Canavieira","2202251"],["PI","Canto do Buriti","2202307"],["PI","Capitão de Campos","2202406"],["PI","Capitão Gervásio Oliveira","2202455"],["PI","Caracol","2202505"],["PI","Caraúbas do Piauí","2202539"],["PI","Caridade do Piauí","2202554"],["PI","Castelo do Piauí","2202604"],["PI","Caxingó","2202653"],["PI","Cocal","2202703"],["PI","Cocal de Telha","2202711"],["PI","Cocal dos Alves","2202729"],["PI","Coivaras","2202737"],["PI","Colônia do Gurguéia","2202752"],["PI","Colônia do Piauí","2202778"],["PI","Conceição do Canindé","2202802"],["PI","Coronel José Dias","2202851"],["PI","Corrente","2202901"],["PI","Cristalândia do Piauí","2203008"],["PI","Cristino Castro","2203107"],["PI","Curimatá","2203206"],["PI","Currais","2203230"],["PI","Curral Novo do Piauí","2203271"],["PI","Curralinhos","2203255"],["PI","Demerval Lobão","2203305"],["PI","Dirceu Arcoverde","2203354"],["PI","Dom Expedito Lopes","2203404"],["PI","Dom Inocêncio","2203453"],["PI","Domingos Mourão","2203420"],["PI","Elesbão Veloso","2203503"],["PI","Eliseu Martins","2203602"],["PI","Esperantina","2203701"],["PI","Fartura do Piauí","2203750"],["PI","Flores do Piauí","2203800"],["PI","Floresta do Piauí","2203859"],["PI","Floriano","2203909"],["PI","Francinópolis","2204006"],["PI","Francisco Ayres","2204105"],["PI","Francisco Macedo","2204154"],["PI","Francisco Santos","2204204"],["PI","Fronteiras","2204303"],["PI","Geminiano","2204352"],["PI","Gilbués","2204402"],["PI","Guadalupe","2204501"],["PI","Guaribas","2204550"],["PI","Hugo Napoleão","2204600"],["PI","Ilha Grande","2204659"],["PI","Inhuma","2204709"],["PI","Ipiranga do Piauí","2204808"],["PI","Isaías Coelho","2204907"],["PI","Itainópolis","2205003"],["PI","Itaueira","2205102"],["PI","Jacobina do Piauí","2205151"],["PI","Jaicós","2205201"],["PI","Jardim do Mulato","2205250"],["PI","Jatobá do Piauí","2205276"],["PI","Jerumenha","2205300"],["PI","João Costa","2205359"],["PI","Joaquim Pires","2205409"],["PI","Joca Marques","2205458"],["PI","José de Freitas","2205508"],["PI","Juazeiro do Piauí","2205516"],["PI","Júlio Borges","2205524"],["PI","Jurema","2205532"],["PI","Lagoa Alegre","2205557"],["PI","Lagoa de São Francisco","2205573"],["PI","Lagoa do Barro do Piauí","2205565"],["PI","Lagoa do Piauí","2205581"],["PI","Lagoa do Sítio","2205599"],["PI","Lagoinha do Piauí","2205540"],["PI","Landri Sales","2205607"],["PI","Luís Correia","2205706"],["PI","Luzilândia","2205805"],["PI","Madeiro","2205854"],["PI","Manoel Emídio","2205904"],["PI","Marcolândia","2205953"],["PI","Marcos Parente","2206001"],["PI","Massapê do Piauí","2206050"],["PI","Matias Olímpio","2206100"],["PI","Miguel Alves","2206209"],["PI","Miguel Leão","2206308"],["PI","Milton Brandão","2206357"],["PI","Monsenhor Gil","2206407"],["PI","Monsenhor Hipólito","2206506"],["PI","Monte Alegre do Piauí","2206605"],["PI","Morro Cabeça no Tempo","2206654"],["PI","Morro do Chapéu do Piauí","2206670"],["PI","Murici dos Portelas","2206696"],["PI","Nazaré do Piauí","2206704"],["PI","Nazária","2206720"],["PI","Nossa Senhora de Nazaré","2206753"],["PI","Nossa Senhora dos Remédios","2206803"],["PI","Nova Santa Rita","2207959"],["PI","Novo Oriente do Piauí","2206902"],["PI","Novo Santo Antônio","2206951"],["PI","Oeiras","2207009"],["PI","Olho D'Água do Piauí","2207108"],["PI","Padre Marcos","2207207"],["PI","Paes Landim","2207306"],["PI","Pajeú do Piauí","2207355"],["PI","Palmeira do Piauí","2207405"],["PI","Palmeirais","2207504"],["PI","Paquetá","2207553"],["PI","Parnaguá","2207603"],["PI","Parnaíba","2207702"],["PI","Passagem Franca do Piauí","2207751"],["PI","Patos do Piauí","2207777"],["PI","Pau D'Arco do Piauí","2207793"],["PI","Paulistana","2207801"],["PI","Pavussu","2207850"],["PI","Pedro II","2207900"],["PI","Pedro Laurentino","2207934"],["PI","Picos","2208007"],["PI","Pimenteiras","2208106"],["PI","Pio IX","2208205"],["PI","Piracuruca","2208304"],["PI","Piripiri","2208403"],["PI","Porto","2208502"],["PI","Porto Alegre do Piauí","2208551"],["PI","Prata do Piauí","2208601"],["PI","Queimada Nova","2208650"],["PI","Redenção do Gurguéia","2208700"],["PI","Regeneração","2208809"],["PI","Riacho Frio","2208858"],["PI","Ribeira do Piauí","2208874"],["PI","Ribeiro Gonçalves","2208908"],["PI","Rio Grande do Piauí","2209005"],["PI","Santa Cruz do Piauí","2209104"],["PI","Santa Cruz dos Milagres","2209153"],["PI","Santa Filomena","2209203"],["PI","Santa Luz","2209302"],["PI","Santa Rosa do Piauí","2209377"],["PI","Santana do Piauí","2209351"],["PI","Santo Antônio de Lisboa","2209401"],["PI","Santo Antônio dos Milagres","2209450"],["PI","Santo Inácio do Piauí","2209500"],["PI","São Braz do Piauí","2209559"],["PI","São Félix do Piauí","2209609"],["PI","São Francisco de Assis do Piauí","2209658"],["PI","São Francisco do Piauí","2209708"],["PI","São Gonçalo do Gurguéia","2209757"],["PI","São Gonçalo do Piauí","2209807"],["PI","São João da Canabrava","2209856"],["PI","São João da Fronteira","2209872"],["PI","São João da Serra","2209906"],["PI","São João da Varjota","2209955"],["PI","São João do Arraial","2209971"],["PI","São João do Piauí","2210003"],["PI","São José do Divino","2210052"],["PI","São José do Peixe","2210102"],["PI","São José do Piauí","2210201"],["PI","São Julião","2210300"],["PI","São Lourenço do Piauí","2210359"],["PI","São Luis do Piauí","2210375"],["PI","São Miguel da Baixa Grande","2210383"],["PI","São Miguel do Fidalgo","2210391"],["PI","São Miguel do Tapuio","2210409"],["PI","São Pedro do Piauí","2210508"],["PI","São Raimundo Nonato","2210607"],["PI","Sebastião Barros","2210623"],["PI","Sebastião Leal","2210631"],["PI","Sigefredo Pacheco","2210656"],["PI","Simões","2210706"],["PI","Simplício Mendes","2210805"],["PI","Socorro do Piauí","2210904"],["PI","Sussuapara","2210938"],["PI","Tamboril do Piauí","2210953"],["PI","Tanque do Piauí","2210979"],["PI","Teresina","2211001"],["PI","União","2211100"],["PI","Uruçuí","2211209"],["PI","Valença do Piauí","2211308"],["PI","Várzea Branca","2211357"],["PI","Várzea Grande","2211407"],["PI","Vera Mendes","2211506"],["PI","Vila Nova do Piauí","2211605"],["PI","Wall Ferraz","2211704"],["RJ","Angra dos Reis","3300100"],["RJ","Aperibé","3300159"],["RJ","Araruama","3300209"],["RJ","Areal","3300225"],["RJ","Armação dos Búzios","3300233"],["RJ","Arraial do Cabo","3300258"],["RJ","Barra do Piraí","3300308"],["RJ","Barra Mansa","3300407"],["RJ","Belford Roxo","3300456"],["RJ","Bom Jardim","3300506"],["RJ","Bom Jesus do Itabapoana","3300605"],["RJ","Cabo Frio","3300704"],["RJ","Cachoeiras de Macacu","3300803"],["RJ","Cambuci","3300902"],["RJ","Campos dos Goytacazes","3301009"],["RJ","Cantagalo","3301108"],["RJ","Carapebus","3300936"],["RJ","Cardoso Moreira","3301157"],["RJ","Carmo","3301207"],["RJ","Casimiro de Abreu","3301306"],["RJ","Comendador Levy Gasparian","3300951"],["RJ","Conceição de Macabu","3301405"],["RJ","Cordeiro","3301504"],["RJ","Duas Barras","3301603"],["RJ","Duque de Caxias","3301702"],["RJ","Engenheiro Paulo de Frontin","3301801"],["RJ","Guapimirim","3301850"],["RJ","Iguaba Grande","3301876"],["RJ","Itaboraí","3301900"],["RJ","Itaguaí","3302007"],["RJ","Italva","3302056"],["RJ","Itaocara","3302106"],["RJ","Itaperuna","3302205"],["RJ","Itatiaia","3302254"],["RJ","Japeri","3302270"],["RJ","Laje do Muriaé","3302304"],["RJ","Macaé","3302403"],["RJ","Macuco","3302452"],["RJ","Magé","3302502"],["RJ","Mangaratiba","3302601"],["RJ","Maricá","3302700"],["RJ","Mendes","3302809"],["RJ","Mesquita","3302858"],["RJ","Miguel Pereira","3302908"],["RJ","Miracema","3303005"],["RJ","Natividade","3303104"],["RJ","Nilópolis","3303203"],["RJ","Niterói","3303302"],["RJ","Nova Friburgo","3303401"],["RJ","Nova Iguaçu","3303500"],["RJ","Paracambi","3303609"],["RJ","Paraíba do Sul","3303708"],["RJ","Paraty","3303807"],["RJ","Paty do Alferes","3303856"],["RJ","Petrópolis","3303906"],["RJ","Pinheiral","3303955"],["RJ","Piraí","3304003"],["RJ","Porciúncula","3304102"],["RJ","Porto Real","3304110"],["RJ","Quatis","3304128"],["RJ","Queimados","3304144"],["RJ","Quissamã","3304151"],["RJ","Resende","3304201"],["RJ","Rio Bonito","3304300"],["RJ","Rio Claro","3304409"],["RJ","Rio das Flores","3304508"],["RJ","Rio das Ostras","3304524"],["RJ","Rio de Janeiro","3304557"],["RJ","Santa Maria Madalena","3304607"],["RJ","Santo Antônio de Pádua","3304706"],["RJ","São Fidélis","3304805"],["RJ","São Francisco de Itabapoana","3304755"],["RJ","São Gonçalo","3304904"],["RJ","São João da Barra","3305000"],["RJ","São João de Meriti","3305109"],["RJ","São José de Ubá","3305133"],["RJ","São José do Vale do Rio Preto","3305158"],["RJ","São Pedro da Aldeia","3305208"],["RJ","São Sebastião do Alto","3305307"],["RJ","Sapucaia","3305406"],["RJ","Saquarema","3305505"],["RJ","Seropédica","3305554"],["RJ","Silva Jardim","3305604"],["RJ","Sumidouro","3305703"],["RJ","Tanguá","3305752"],["RJ","Teresópolis","3305802"],["RJ","Trajano de Moraes","3305901"],["RJ","Três Rios","3306008"],["RJ","Valença","3306107"],["RJ","Varre-Sai","3306156"],["RJ","Vassouras","3306206"],["RJ","Volta Redonda","3306305"],["RN","Acari","2400109"],["RN","Afonso Bezerra","2400307"],["RN","Água Nova","2400406"],["RN","Alexandria","2400505"],["RN","Almino Afonso","2400604"],["RN","Alto do Rodrigues","2400703"],["RN","Angicos","2400802"],["RN","Antônio Martins","2400901"],["RN","Apodi","2401008"],["RN","Areia Branca","2401107"],["RN","Arez","2401206"],["RN","Assú","2400208"],["RN","Baía Formosa","2401404"],["RN","Baraúna","2401453"],["RN","Barcelona","2401503"],["RN","Bento Fernandes","2401602"],["RN","Bodó","2401651"],["RN","Bom Jesus","2401701"],["RN","Brejinho","2401800"],["RN","Caiçara do Norte","2401859"],["RN","Caiçara do Rio do Vento","2401909"],["RN","Caicó","2402006"],["RN","Campo Grande","2401305"],["RN","Campo Redondo","2402105"],["RN","Canguaretama","2402204"],["RN","Caraúbas","2402303"],["RN","Carnaúba dos Dantas","2402402"],["RN","Carnaubais","2402501"],["RN","Ceará-Mirim","2402600"],["RN","Cerro Corá","2402709"],["RN","Coronel Ezequiel","2402808"],["RN","Coronel João Pessoa","2402907"],["RN","Cruzeta","2403004"],["RN","Currais Novos","2403103"],["RN","Doutor Severiano","2403202"],["RN","Encanto","2403301"],["RN","Equador","2403400"],["RN","Espírito Santo","2403509"],["RN","Extremoz","2403608"],["RN","Felipe Guerra","2403707"],["RN","Fernando Pedroza","2403756"],["RN","Florânia","2403806"],["RN","Francisco Dantas","2403905"],["RN","Frutuoso Gomes","2404002"],["RN","Galinhos","2404101"],["RN","Goianinha","2404200"],["RN","Governador Dix-Sept Rosado","2404309"],["RN","Grossos","2404408"],["RN","Guamaré","2404507"],["RN","Ielmo Marinho","2404606"],["RN","Ipanguaçu","2404705"],["RN","Ipueira","2404804"],["RN","Itajá","2404853"],["RN","Itaú","2404903"],["RN","Jaçanã","2405009"],["RN","Jandaíra","2405108"],["RN","Janduís","2405207"],["RN","Januário Cicco","2405306"],["RN","Japi","2405405"],["RN","Jardim de Angicos","2405504"],["RN","Jardim de Piranhas","2405603"],["RN","Jardim do Seridó","2405702"],["RN","João Câmara","2405801"],["RN","João Dias","2405900"],["RN","José da Penha","2406007"],["RN","Jucurutu","2406106"],["RN","Jundiá","2406155"],["RN","Lagoa d'Anta","2406205"],["RN","Lagoa de Pedras","2406304"],["RN","Lagoa de Velhos","2406403"],["RN","Lagoa Nova","2406502"],["RN","Lagoa Salgada","2406601"],["RN","Lajes","2406700"],["RN","Lajes Pintadas","2406809"],["RN","Lucrécia","2406908"],["RN","Luís Gomes","2407005"],["RN","Macaíba","2407104"],["RN","Macau","2407203"],["RN","Major Sales","2407252"],["RN","Marcelino Vieira","2407302"],["RN","Martins","2407401"],["RN","Maxaranguape","2407500"],["RN","Messias Targino","2407609"],["RN","Montanhas","2407708"],["RN","Monte Alegre","2407807"],["RN","Monte das Gameleiras","2407906"],["RN","Mossoró","2408003"],["RN","Natal","2408102"],["RN","Nísia Floresta","2408201"],["RN","Nova Cruz","2408300"],["RN","Olho d'Água do Borges","2408409"],["RN","Ouro Branco","2408508"],["RN","Paraná","2408607"],["RN","Paraú","2408706"],["RN","Parazinho","2408805"],["RN","Parelhas","2408904"],["RN","Parnamirim","2403251"],["RN","Passa e Fica","2409100"],["RN","Passagem","2409209"],["RN","Patu","2409308"],["RN","Pau dos Ferros","2409407"],["RN","Pedra Grande","2409506"],["RN","Pedra Preta","2409605"],["RN","Pedro Avelino","2409704"],["RN","Pedro Velho","2409803"],["RN","Pendências","2409902"],["RN","Pilões","2410009"],["RN","Poço Branco","2410108"],["RN","Portalegre","2410207"],["RN","Porto do Mangue","2410256"],["RN","Pureza","2410405"],["RN","Rafael Fernandes","2410504"],["RN","Rafael Godeiro","2410603"],["RN","Riacho da Cruz","2410702"],["RN","Riacho de Santana","2410801"],["RN","Riachuelo","2410900"],["RN","Rio do Fogo","2408953"],["RN","Rodolfo Fernandes","2411007"],["RN","Ruy Barbosa","2411106"],["RN","Santa Cruz","2411205"],["RN","Santa Maria","2409332"],["RN","Santana do Matos","2411403"],["RN","Santana do Seridó","2411429"],["RN","Santo Antônio","2411502"],["RN","São Bento do Norte","2411601"],["RN","São Bento do Trairí","2411700"],["RN","São Fernando","2411809"],["RN","São Francisco do Oeste","2411908"],["RN","São Gonçalo do Amarante","2412005"],["RN","São João do Sabugi","2412104"],["RN","São José de Mipibu","2412203"],["RN","São José do Campestre","2412302"],["RN","São José do Seridó","2412401"],["RN","São Miguel","2412500"],["RN","São Miguel do Gostoso","2412559"],["RN","São Paulo do Potengi","2412609"],["RN","São Pedro","2412708"],["RN","São Rafael","2412807"],["RN","São Tomé","2412906"],["RN","São Vicente","2413003"],["RN","Senador Elói de Souza","2413102"],["RN","Senador Georgino Avelino","2413201"],["RN","Serra Caiada","2410306"],["RN","Serra de São Bento","2413300"],["RN","Serra do Mel","2413359"],["RN","Serra Negra do Norte","2413409"],["RN","Serrinha","2413508"],["RN","Serrinha dos Pintos","2413557"],["RN","Severiano Melo","2413607"],["RN","Sítio Novo","2413706"],["RN","Taboleiro Grande","2413805"],["RN","Taipu","2413904"],["RN","Tangará","2414001"],["RN","Tenente Ananias","2414100"],["RN","Tenente Laurentino Cruz","2414159"],["RN","Tibau","2411056"],["RN","Tibau do Sul","2414209"],["RN","Timbaúba dos Batistas","2414308"],["RN","Touros","2414407"],["RN","Triunfo Potiguar","2414456"],["RN","Umarizal","2414506"],["RN","Upanema","2414605"],["RN","Várzea","2414704"],["RN","Venha-Ver","2414753"],["RN","Vera Cruz","2414803"],["RN","Viçosa","2414902"],["RN","Vila Flor","2415008"],["RS","Aceguá","4300034"],["RS","Água Santa","4300059"],["RS","Agudo","4300109"],["RS","Ajuricaba","4300208"],["RS","Alecrim","4300307"],["RS","Alegrete","4300406"],["RS","Alegria","4300455"],["RS","Almirante Tamandaré do Sul","4300471"],["RS","Alpestre","4300505"],["RS","Alto Alegre","4300554"],["RS","Alto Feliz","4300570"],["RS","Alvorada","4300604"],["RS","Amaral Ferrador","4300638"],["RS","Ametista do Sul","4300646"],["RS","André da Rocha","4300661"],["RS","Anta Gorda","4300703"],["RS","Antônio Prado","4300802"],["RS","Arambaré","4300851"],["RS","Araricá","4300877"],["RS","Aratiba","4300901"],["RS","Arroio do Meio","4301008"],["RS","Arroio do Padre","4301073"],["RS","Arroio do Sal","4301057"],["RS","Arroio do Tigre","4301206"],["RS","Arroio dos Ratos","4301107"],["RS","Arroio Grande","4301305"],["RS","Arvorezinha","4301404"],["RS","Augusto Pestana","4301503"],["RS","Áurea","4301552"],["RS","Bagé","4301602"],["RS","Balneário Pinhal","4301636"],["RS","Barão","4301651"],["RS","Barão de Cotegipe","4301701"],["RS","Barão do Triunfo","4301750"],["RS","Barra do Guarita","4301859"],["RS","Barra do Quaraí","4301875"],["RS","Barra do Ribeiro","4301909"],["RS","Barra do Rio Azul","4301925"],["RS","Barra Funda","4301958"],["RS","Barracão","4301800"],["RS","Barros Cassal","4302006"],["RS","Benjamin Constant do Sul","4302055"],["RS","Bento Gonçalves","4302105"],["RS","Boa Vista das Missões","4302154"],["RS","Boa Vista do Buricá","4302204"],["RS","Boa Vista do Cadeado","4302220"],["RS","Boa Vista do Incra","4302238"],["RS","Boa Vista do Sul","4302253"],["RS","Bom Jesus","4302303"],["RS","Bom Princípio","4302352"],["RS","Bom Progresso","4302378"],["RS","Bom Retiro do Sul","4302402"],["RS","Boqueirão do Leão","4302451"],["RS","Bossoroca","4302501"],["RS","Bozano","4302584"],["RS","Braga","4302600"],["RS","Brochier","4302659"],["RS","Butiá","4302709"],["RS","Caçapava do Sul","4302808"],["RS","Cacequi","4302907"],["RS","Cachoeira do Sul","4303004"],["RS","Cachoeirinha","4303103"],["RS","Cacique Doble","4303202"],["RS","Caibaté","4303301"],["RS","Caiçara","4303400"],["RS","Camaquã","4303509"],["RS","Camargo","4303558"],["RS","Cambará do Sul","4303608"],["RS","Campestre da Serra","4303673"],["RS","Campina das Missões","4303707"],["RS","Campinas do Sul","4303806"],["RS","Campo Bom","4303905"],["RS","Campo Novo","4304002"],["RS","Campos Borges","4304101"],["RS","Candelária","4304200"],["RS","Cândido Godói","4304309"],["RS","Candiota","4304358"],["RS","Canela","4304408"],["RS","Canguçu","4304507"],["RS","Canoas","4304606"],["RS","Canudos do Vale","4304614"],["RS","Capão Bonito do Sul","4304622"],["RS","Capão da Canoa","4304630"],["RS","Capão do Cipó","4304655"],["RS","Capão do Leão","4304663"],["RS","Capela de Santana","4304689"],["RS","Capitão","4304697"],["RS","Capivari do Sul","4304671"],["RS","Caraá","4304713"],["RS","Carazinho","4304705"],["RS","Carlos Barbosa","4304804"],["RS","Carlos Gomes","4304853"],["RS","Casca","4304903"],["RS","Caseiros","4304952"],["RS","Catuípe","4305009"],["RS","Caxias do Sul","4305108"],["RS","Centenário","4305116"],["RS","Cerrito","4305124"],["RS","Cerro Branco","4305132"],["RS","Cerro Grande","4305157"],["RS","Cerro Grande do Sul","4305173"],["RS","Cerro Largo","4305207"],["RS","Chapada","4305306"],["RS","Charqueadas","4305355"],["RS","Charrua","4305371"],["RS","Chiapetta","4305405"],["RS","Chuí","4305439"],["RS","Chuvisca","4305447"],["RS","Cidreira","4305454"],["RS","Ciríaco","4305504"],["RS","Colinas","4305587"],["RS","Colorado","4305603"],["RS","Condor","4305702"],["RS","Constantina","4305801"],["RS","Coqueiro Baixo","4305835"],["RS","Coqueiros do Sul","4305850"],["RS","Coronel Barros","4305871"],["RS","Coronel Bicaco","4305900"],["RS","Coronel Pilar","4305934"],["RS","Cotiporã","4305959"],["RS","Coxilha","4305975"],["RS","Crissiumal","4306007"],["RS","Cristal","4306056"],["RS","Cristal do Sul","4306072"],["RS","Cruz Alta","4306106"],["RS","Cruzaltense","4306130"],["RS","Cruzeiro do Sul","4306205"],["RS","David Canabarro","4306304"],["RS","Derrubadas","4306320"],["RS","Dezesseis de Novembro","4306353"],["RS","Dilermando de Aguiar","4306379"],["RS","Dois Irmãos","4306403"],["RS","Dois Irmãos das Missões","4306429"],["RS","Dois Lajeados","4306452"],["RS","Dom Feliciano","4306502"],["RS","Dom Pedrito","4306601"],["RS","Dom Pedro de Alcântara","4306551"],["RS","Dona Francisca","4306700"],["RS","Doutor Maurício Cardoso","4306734"],["RS","Doutor Ricardo","4306759"],["RS","Eldorado do Sul","4306767"],["RS","Encantado","4306809"],["RS","Encruzilhada do Sul","4306908"],["RS","Engenho Velho","4306924"],["RS","Entre Rios do Sul","4306957"],["RS","Entre-Ijuís","4306932"],["RS","Erebango","4306973"],["RS","Erechim","4307005"],["RS","Ernestina","4307054"],["RS","Erval Grande","4307203"],["RS","Erval Seco","4307302"],["RS","Esmeralda","4307401"],["RS","Esperança do Sul","4307450"],["RS","Espumoso","4307500"],["RS","Estação","4307559"],["RS","Estância Velha","4307609"],["RS","Esteio","4307708"],["RS","Estrela","4307807"],["RS","Estrela Velha","4307815"],["RS","Eugênio de Castro","4307831"],["RS","Fagundes Varela","4307864"],["RS","Farroupilha","4307906"],["RS","Faxinal do Soturno","4308003"],["RS","Faxinalzinho","4308052"],["RS","Fazenda Vilanova","4308078"],["RS","Feliz","4308102"],["RS","Flores da Cunha","4308201"],["RS","Floriano Peixoto","4308250"],["RS","Fontoura Xavier","4308300"],["RS","Formigueiro","4308409"],["RS","Forquetinha","4308433"],["RS","Fortaleza dos Valos","4308458"],["RS","Frederico Westphalen","4308508"],["RS","Garibaldi","4308607"],["RS","Garruchos","4308656"],["RS","Gaurama","4308706"],["RS","General Câmara","4308805"],["RS","Gentil","4308854"],["RS","Getúlio Vargas","4308904"],["RS","Giruá","4309001"],["RS","Glorinha","4309050"],["RS","Gramado","4309100"],["RS","Gramado dos Loureiros","4309126"],["RS","Gramado Xavier","4309159"],["RS","Gravataí","4309209"],["RS","Guabiju","4309258"],["RS","Guaíba","4309308"],["RS","Guaporé","4309407"],["RS","Guarani das Missões","4309506"],["RS","Harmonia","4309555"],["RS","Herval","4307104"],["RS","Herveiras","4309571"],["RS","Horizontina","4309605"],["RS","Hulha Negra","4309654"],["RS","Humaitá","4309704"],["RS","Ibarama","4309753"],["RS","Ibiaçá","4309803"],["RS","Ibiraiaras","4309902"],["RS","Ibirapuitã","4309951"],["RS","Ibirubá","4310009"],["RS","Igrejinha","4310108"],["RS","Ijuí","4310207"],["RS","Ilópolis","4310306"],["RS","Imbé","4310330"],["RS","Imigrante","4310363"],["RS","Independência","4310405"],["RS","Inhacorá","4310413"],["RS","Ipê","4310439"],["RS","Ipiranga do Sul","4310462"],["RS","Iraí","4310504"],["RS","Itaara","4310538"],["RS","Itacurubi","4310553"],["RS","Itapuca","4310579"],["RS","Itaqui","4310603"],["RS","Itati","4310652"],["RS","Itatiba do Sul","4310702"],["RS","Ivorá","4310751"],["RS","Ivoti","4310801"],["RS","Jaboticaba","4310850"],["RS","Jacuizinho","4310876"],["RS","Jacutinga","4310900"],["RS","Jaguarão","4311007"],["RS","Jaguari","4311106"],["RS","Jaquirana","4311122"],["RS","Jari","4311130"],["RS","Jóia","4311155"],["RS","Júlio de Castilhos","4311205"],["RS","Lagoa Bonita do Sul","4311239"],["RS","Lagoa dos Três Cantos","4311270"],["RS","Lagoa Vermelha","4311304"],["RS","Lagoão","4311254"],["RS","Lajeado","4311403"],["RS","Lajeado do Bugre","4311429"],["RS","Lavras do Sul","4311502"],["RS","Liberato Salzano","4311601"],["RS","Lindolfo Collor","4311627"],["RS","Linha Nova","4311643"],["RS","Maçambará","4311718"],["RS","Machadinho","4311700"],["RS","Mampituba","4311734"],["RS","Manoel Viana","4311759"],["RS","Maquiné","4311775"],["RS","Maratá","4311791"],["RS","Marau","4311809"],["RS","Marcelino Ramos","4311908"],["RS","Mariana Pimentel","4311981"],["RS","Mariano Moro","4312005"],["RS","Marques de Souza","4312054"],["RS","Mata","4312104"],["RS","Mato Castelhano","4312138"],["RS","Mato Leitão","4312153"],["RS","Mato Queimado","4312179"],["RS","Maximiliano de Almeida","4312203"],["RS","Minas do Leão","4312252"],["RS","Miraguaí","4312302"],["RS","Montauri","4312351"],["RS","Monte Alegre dos Campos","4312377"],["RS","Monte Belo do Sul","4312385"],["RS","Montenegro","4312401"],["RS","Mormaço","4312427"],["RS","Morrinhos do Sul","4312443"],["RS","Morro Redondo","4312450"],["RS","Morro Reuter","4312476"],["RS","Mostardas","4312500"],["RS","Muçum","4312609"],["RS","Muitos Capões","4312617"],["RS","Muliterno","4312625"],["RS","Não-Me-Toque","4312658"],["RS","Nicolau Vergueiro","4312674"],["RS","Nonoai","4312708"],["RS","Nova Alvorada","4312757"],["RS","Nova Araçá","4312807"],["RS","Nova Bassano","4312906"],["RS","Nova Boa Vista","4312955"],["RS","Nova Bréscia","4313003"],["RS","Nova Candelária","4313011"],["RS","Nova Esperança do Sul","4313037"],["RS","Nova Hartz","4313060"],["RS","Nova Pádua","4313086"],["RS","Nova Palma","4313102"],["RS","Nova Petrópolis","4313201"],["RS","Nova Prata","4313300"],["RS","Nova Ramada","4313334"],["RS","Nova Roma do Sul","4313359"],["RS","Nova Santa Rita","4313375"],["RS","Novo Barreiro","4313490"],["RS","Novo Cabrais","4313391"],["RS","Novo Hamburgo","4313409"],["RS","Novo Machado","4313425"],["RS","Novo Tiradentes","4313441"],["RS","Novo Xingu","4313466"],["RS","Osório","4313508"],["RS","Paim Filho","4313607"],["RS","Palmares do Sul","4313656"],["RS","Palmeira das Missões","4313706"],["RS","Palmitinho","4313805"],["RS","Panambi","4313904"],["RS","Pantano Grande","4313953"],["RS","Paraí","4314001"],["RS","Paraíso do Sul","4314027"],["RS","Pareci Novo","4314035"],["RS","Parobé","4314050"],["RS","Passa Sete","4314068"],["RS","Passo do Sobrado","4314076"],["RS","Passo Fundo","4314100"],["RS","Paulo Bento","4314134"],["RS","Paverama","4314159"],["RS","Pedras Altas","4314175"],["RS","Pedro Osório","4314209"],["RS","Pejuçara","4314308"],["RS","Pelotas","4314407"],["RS","Picada Café","4314423"],["RS","Pinhal","4314456"],["RS","Pinhal da Serra","4314464"],["RS","Pinhal Grande","4314472"],["RS","Pinheirinho do Vale","4314498"],["RS","Pinheiro Machado","4314506"],["RS","Pinto Bandeira","4314548"],["RS","Pirapó","4314555"],["RS","Piratini","4314605"],["RS","Planalto","4314704"],["RS","Poço das Antas","4314753"],["RS","Pontão","4314779"],["RS","Ponte Preta","4314787"],["RS","Portão","4314803"],["RS","Porto Alegre","4314902"],["RS","Porto Lucena","4315008"],["RS","Porto Mauá","4315057"],["RS","Porto Vera Cruz","4315073"],["RS","Porto Xavier","4315107"],["RS","Pouso Novo","4315131"],["RS","Presidente Lucena","4315149"],["RS","Progresso","4315156"],["RS","Protásio Alves","4315172"],["RS","Putinga","4315206"],["RS","Quaraí","4315305"],["RS","Quatro Irmãos","4315313"],["RS","Quevedos","4315321"],["RS","Quinze de Novembro","4315354"],["RS","Redentora","4315404"],["RS","Relvado","4315453"],["RS","Restinga Sêca","4315503"],["RS","Rio dos Índios","4315552"],["RS","Rio Grande","4315602"],["RS","Rio Pardo","4315701"],["RS","Riozinho","4315750"],["RS","Roca Sales","4315800"],["RS","Rodeio Bonito","4315909"],["RS","Rolador","4315958"],["RS","Rolante","4316006"],["RS","Ronda Alta","4316105"],["RS","Rondinha","4316204"],["RS","Roque Gonzales","4316303"],["RS","Rosário do Sul","4316402"],["RS","Sagrada Família","4316428"],["RS","Saldanha Marinho","4316436"],["RS","Salto do Jacuí","4316451"],["RS","Salvador das Missões","4316477"],["RS","Salvador do Sul","4316501"],["RS","Sananduva","4316600"],["RS","Sant'Ana do Livramento","4317103"],["RS","Santa Bárbara do Sul","4316709"],["RS","Santa Cecília do Sul","4316733"],["RS","Santa Clara do Sul","4316758"],["RS","Santa Cruz do Sul","4316808"],["RS","Santa Margarida do Sul","4316972"],["RS","Santa Maria","4316907"],["RS","Santa Maria do Herval","4316956"],["RS","Santa Rosa","4317202"],["RS","Santa Tereza","4317251"],["RS","Santa Vitória do Palmar","4317301"],["RS","Santana da Boa Vista","4317004"],["RS","Santiago","4317400"],["RS","Santo Ângelo","4317509"],["RS","Santo Antônio da Patrulha","4317608"],["RS","Santo Antônio das Missões","4317707"],["RS","Santo Antônio do Palma","4317558"],["RS","Santo Antônio do Planalto","4317756"],["RS","Santo Augusto","4317806"],["RS","Santo Cristo","4317905"],["RS","Santo Expedito do Sul","4317954"],["RS","São Borja","4318002"],["RS","São Domingos do Sul","4318051"],["RS","São Francisco de Assis","4318101"],["RS","São Francisco de Paula","4318200"],["RS","São Gabriel","4318309"],["RS","São Jerônimo","4318408"],["RS","São João da Urtiga","4318424"],["RS","São João do Polêsine","4318432"],["RS","São Jorge","4318440"],["RS","São José das Missões","4318457"],["RS","São José do Herval","4318465"],["RS","São José do Hortêncio","4318481"],["RS","São José do Inhacorá","4318499"],["RS","São José do Norte","4318507"],["RS","São José do Ouro","4318606"],["RS","São José do Sul","4318614"],["RS","São José dos Ausentes","4318622"],["RS","São Leopoldo","4318705"],["RS","São Lourenço do Sul","4318804"],["RS","São Luiz Gonzaga","4318903"],["RS","São Marcos","4319000"],["RS","São Martinho","4319109"],["RS","São Martinho da Serra","4319125"],["RS","São Miguel das Missões","4319158"],["RS","São Nicolau","4319208"],["RS","São Paulo das Missões","4319307"],["RS","São Pedro da Serra","4319356"],["RS","São Pedro das Missões","4319364"],["RS","São Pedro do Butiá","4319372"],["RS","São Pedro do Sul","4319406"],["RS","São Sebastião do Caí","4319505"],["RS","São Sepé","4319604"],["RS","São Valentim","4319703"],["RS","São Valentim do Sul","4319711"],["RS","São Valério do Sul","4319737"],["RS","São Vendelino","4319752"],["RS","São Vicente do Sul","4319802"],["RS","Sapiranga","4319901"],["RS","Sapucaia do Sul","4320008"],["RS","Sarandi","4320107"],["RS","Seberi","4320206"],["RS","Sede Nova","4320230"],["RS","Segredo","4320263"],["RS","Selbach","4320305"],["RS","Senador Salgado Filho","4320321"],["RS","Sentinela do Sul","4320354"],["RS","Serafina Corrêa","4320404"],["RS","Sério","4320453"],["RS","Sertão","4320503"],["RS","Sertão Santana","4320552"],["RS","Sete de Setembro","4320578"],["RS","Severiano de Almeida","4320602"],["RS","Silveira Martins","4320651"],["RS","Sinimbu","4320677"],["RS","Sobradinho","4320701"],["RS","Soledade","4320800"],["RS","Tabaí","4320859"],["RS","Tapejara","4320909"],["RS","Tapera","4321006"],["RS","Tapes","4321105"],["RS","Taquara","4321204"],["RS","Taquari","4321303"],["RS","Taquaruçu do Sul","4321329"],["RS","Tavares","4321352"],["RS","Tenente Portela","4321402"],["RS","Terra de Areia","4321436"],["RS","Teutônia","4321451"],["RS","Tio Hugo","4321469"],["RS","Tiradentes do Sul","4321477"],["RS","Toropi","4321493"],["RS","Torres","4321501"],["RS","Tramandaí","4321600"],["RS","Travesseiro","4321626"],["RS","Três Arroios","4321634"],["RS","Três Cachoeiras","4321667"],["RS","Três Coroas","4321709"],["RS","Três de Maio","4321808"],["RS","Três Forquilhas","4321832"],["RS","Três Palmeiras","4321857"],["RS","Três Passos","4321907"],["RS","Trindade do Sul","4321956"],["RS","Triunfo","4322004"],["RS","Tucunduva","4322103"],["RS","Tunas","4322152"],["RS","Tupanci do Sul","4322186"],["RS","Tupanciretã","4322202"],["RS","Tupandi","4322251"],["RS","Tuparendi","4322301"],["RS","Turuçu","4322327"],["RS","Ubiretama","4322343"],["RS","União da Serra","4322350"],["RS","Unistalda","4322376"],["RS","Uruguaiana","4322400"],["RS","Vacaria","4322509"],["RS","Vale do Sol","4322533"],["RS","Vale Real","4322541"],["RS","Vale Verde","4322525"],["RS","Vanini","4322558"],["RS","Venâncio Aires","4322608"],["RS","Vera Cruz","4322707"],["RS","Veranópolis","4322806"],["RS","Vespasiano Corrêa","4322855"],["RS","Viadutos","4322905"],["RS","Viamão","4323002"],["RS","Vicente Dutra","4323101"],["RS","Victor Graeff","4323200"],["RS","Vila Flores","4323309"],["RS","Vila Lângaro","4323358"],["RS","Vila Maria","4323408"],["RS","Vila Nova do Sul","4323457"],["RS","Vista Alegre","4323507"],["RS","Vista Alegre do Prata","4323606"],["RS","Vista Gaúcha","4323705"],["RS","Vitória das Missões","4323754"],["RS","Westfália","4323770"],["RS","Xangri-lá","4323804"],["RO","Alta Floresta D'Oeste","1100015"],["RO","Alto Alegre dos Parecis","1100379"],["RO","Alto Paraíso","1100403"],["RO","Alvorada D'Oeste","1100346"],["RO","Ariquemes","1100023"],["RO","Buritis","1100452"],["RO","Cabixi","1100031"],["RO","Cacaulândia","1100601"],["RO","Cacoal","1100049"],["RO","Campo Novo de Rondônia","1100700"],["RO","Candeias do Jamari","1100809"],["RO","Castanheiras","1100908"],["RO","Cerejeiras","1100056"],["RO","Chupinguaia","1100924"],["RO","Colorado do Oeste","1100064"],["RO","Corumbiara","1100072"],["RO","Costa Marques","1100080"],["RO","Cujubim","1100940"],["RO","Espigão D'Oeste","1100098"],["RO","Governador Jorge Teixeira","1101005"],["RO","Guajará-Mirim","1100106"],["RO","Itapuã do Oeste","1101104"],["RO","Jaru","1100114"],["RO","Ji-Paraná","1100122"],["RO","Machadinho D'Oeste","1100130"],["RO","Ministro Andreazza","1101203"],["RO","Mirante da Serra","1101302"],["RO","Monte Negro","1101401"],["RO","Nova Brasilândia D'Oeste","1100148"],["RO","Nova Mamoré","1100338"],["RO","Nova União","1101435"],["RO","Novo Horizonte do Oeste","1100502"],["RO","Ouro Preto do Oeste","1100155"],["RO","Parecis","1101450"],["RO","Pimenta Bueno","1100189"],["RO","Pimenteiras do Oeste","1101468"],["RO","Porto Velho","1100205"],["RO","Presidente Médici","1100254"],["RO","Primavera de Rondônia","1101476"],["RO","Rio Crespo","1100262"],["RO","Rolim de Moura","1100288"],["RO","Santa Luzia D'Oeste","1100296"],["RO","São Felipe D'Oeste","1101484"],["RO","São Francisco do Guaporé","1101492"],["RO","São Miguel do Guaporé","1100320"],["RO","Seringueiras","1101500"],["RO","Teixeirópolis","1101559"],["RO","Theobroma","1101609"],["RO","Urupá","1101708"],["RO","Vale do Anari","1101757"],["RO","Vale do Paraíso","1101807"],["RO","Vilhena","1100304"],["RR","Alto Alegre","1400050"],["RR","Amajari","1400027"],["RR","Boa Vista","1400100"],["RR","Bonfim","1400159"],["RR","Cantá","1400175"],["RR","Caracaraí","1400209"],["RR","Caroebe","1400233"],["RR","Iracema","1400282"],["RR","Mucajaí","1400308"],["RR","Normandia","1400407"],["RR","Pacaraima","1400456"],["RR","Rorainópolis","1400472"],["RR","São João da Baliza","1400506"],["RR","São Luiz do Anauá","1400605"],["RR","Uiramutã","1400704"],["SC","Abdon Batista","4200051"],["SC","Abelardo Luz","4200101"],["SC","Agrolândia","4200200"],["SC","Agronômica","4200309"],["SC","Água Doce","4200408"],["SC","Águas de Chapecó","4200507"],["SC","Águas Frias","4200556"],["SC","Águas Mornas","4200606"],["SC","Alfredo Wagner","4200705"],["SC","Alto Bela Vista","4200754"],["SC","Anchieta","4200804"],["SC","Angelina","4200903"],["SC","Anita Garibaldi","4201000"],["SC","Anitápolis","4201109"],["SC","Antônio Carlos","4201208"],["SC","Apiúna","4201257"],["SC","Arabutã","4201273"],["SC","Araquari","4201307"],["SC","Araranguá","4201406"],["SC","Armazém","4201505"],["SC","Arroio Trinta","4201604"],["SC","Arvoredo","4201653"],["SC","Ascurra","4201703"],["SC","Atalanta","4201802"],["SC","Aurora","4201901"],["SC","Balneário Arroio do Silva","4201950"],["SC","Balneário Barra do Sul","4202057"],["SC","Balneário Camboriú","4202008"],["SC","Balneário Gaivota","4202073"],["SC","Balneário Piçarras","4212809"],["SC","Balneário Rincão","4220000"],["SC","Bandeirante","4202081"],["SC","Barra Bonita","4202099"],["SC","Barra Velha","4202107"],["SC","Bela Vista do Toldo","4202131"],["SC","Belmonte","4202156"],["SC","Benedito Novo","4202206"],["SC","Biguaçu","4202305"],["SC","Blumenau","4202404"],["SC","Bocaina do Sul","4202438"],["SC","Bom Jardim da Serra","4202503"],["SC","Bom Jesus","4202537"],["SC","Bom Jesus do Oeste","4202578"],["SC","Bom Retiro","4202602"],["SC","Bombinhas","4202453"],["SC","Botuverá","4202701"],["SC","Braço do Norte","4202800"],["SC","Braço do Trombudo","4202859"],["SC","Brunópolis","4202875"],["SC","Brusque","4202909"],["SC","Caçador","4203006"],["SC","Caibi","4203105"],["SC","Calmon","4203154"],["SC","Camboriú","4203204"],["SC","Campo Alegre","4203303"],["SC","Campo Belo do Sul","4203402"],["SC","Campo Erê","4203501"],["SC","Campos Novos","4203600"],["SC","Canelinha","4203709"],["SC","Canoinhas","4203808"],["SC","Capão Alto","4203253"],["SC","Capinzal","4203907"],["SC","Capivari de Baixo","4203956"],["SC","Catanduvas","4204004"],["SC","Caxambu do Sul","4204103"],["SC","Celso Ramos","4204152"],["SC","Cerro Negro","4204178"],["SC","Chapadão do Lageado","4204194"],["SC","Chapecó","4204202"],["SC","Cocal do Sul","4204251"],["SC","Concórdia","4204301"],["SC","Cordilheira Alta","4204350"],["SC","Coronel Freitas","4204400"],["SC","Coronel Martins","4204459"],["SC","Correia Pinto","4204558"],["SC","Corupá","4204509"],["SC","Criciúma","4204608"],["SC","Cunha Porã","4204707"],["SC","Cunhataí","4204756"],["SC","Curitibanos","4204806"],["SC","Descanso","4204905"],["SC","Dionísio Cerqueira","4205001"],["SC","Dona Emma","4205100"],["SC","Doutor Pedrinho","4205159"],["SC","Entre Rios","4205175"],["SC","Ermo","4205191"],["SC","Erval Velho","4205209"],["SC","Faxinal dos Guedes","4205308"],["SC","Flor do Sertão","4205357"],["SC","Florianópolis","4205407"],["SC","Formosa do Sul","4205431"],["SC","Forquilhinha","4205456"],["SC","Fraiburgo","4205506"],["SC","Frei Rogério","4205555"],["SC","Galvão","4205605"],["SC","Garopaba","4205704"],["SC","Garuva","4205803"],["SC","Gaspar","4205902"],["SC","Governador Celso Ramos","4206009"],["SC","Grão-Pará","4206108"],["SC","Gravatal","4206207"],["SC","Guabiruba","4206306"],["SC","Guaraciaba","4206405"],["SC","Guaramirim","4206504"],["SC","Guarujá do Sul","4206603"],["SC","Guatambú","4206652"],["SC","Herval d'Oeste","4206702"],["SC","Ibiam","4206751"],["SC","Ibicaré","4206801"],["SC","Ibirama","4206900"],["SC","Içara","4207007"],["SC","Ilhota","4207106"],["SC","Imaruí","4207205"],["SC","Imbituba","4207304"],["SC","Imbuia","4207403"],["SC","Indaial","4207502"],["SC","Iomerê","4207577"],["SC","Ipira","4207601"],["SC","Iporã do Oeste","4207650"],["SC","Ipuaçu","4207684"],["SC","Ipumirim","4207700"],["SC","Iraceminha","4207759"],["SC","Irani","4207809"],["SC","Irati","4207858"],["SC","Irineópolis","4207908"],["SC","Itá","4208005"],["SC","Itaiópolis","4208104"],["SC","Itajaí","4208203"],["SC","Itapema","4208302"],["SC","Itapiranga","4208401"],["SC","Itapoá","4208450"],["SC","Ituporanga","4208500"],["SC","Jaborá","4208609"],["SC","Jacinto Machado","4208708"],["SC","Jaguaruna","4208807"],["SC","Jaraguá do Sul","4208906"],["SC","Jardinópolis","4208955"],["SC","Joaçaba","4209003"],["SC","Joinville","4209102"],["SC","José Boiteux","4209151"],["SC","Jupiá","4209177"],["SC","Lacerdópolis","4209201"],["SC","Lages","4209300"],["SC","Laguna","4209409"],["SC","Lajeado Grande","4209458"],["SC","Laurentino","4209508"],["SC","Lauro Müller","4209607"],["SC","Lebon Régis","4209706"],["SC","Leoberto Leal","4209805"],["SC","Lindóia do Sul","4209854"],["SC","Lontras","4209904"],["SC","Luiz Alves","4210001"],["SC","Luzerna","4210035"],["SC","Macieira","4210050"],["SC","Mafra","4210100"],["SC","Major Gercino","4210209"],["SC","Major Vieira","4210308"],["SC","Maracajá","4210407"],["SC","Maravilha","4210506"],["SC","Marema","4210555"],["SC","Massaranduba","4210605"],["SC","Matos Costa","4210704"],["SC","Meleiro","4210803"],["SC","Mirim Doce","4210852"],["SC","Modelo","4210902"],["SC","Mondaí","4211009"],["SC","Monte Carlo","4211058"],["SC","Monte Castelo","4211108"],["SC","Morro da Fumaça","4211207"],["SC","Morro Grande","4211256"],["SC","Navegantes","4211306"],["SC","Nova Erechim","4211405"],["SC","Nova Itaberaba","4211454"],["SC","Nova Trento","4211504"],["SC","Nova Veneza","4211603"],["SC","Novo Horizonte","4211652"],["SC","Orleans","4211702"],["SC","Otacílio Costa","4211751"],["SC","Ouro","4211801"],["SC","Ouro Verde","4211850"],["SC","Paial","4211876"],["SC","Painel","4211892"],["SC","Palhoça","4211900"],["SC","Palma Sola","4212007"],["SC","Palmeira","4212056"],["SC","Palmitos","4212106"],["SC","Papanduva","4212205"],["SC","Paraíso","4212239"],["SC","Passo de Torres","4212254"],["SC","Passos Maia","4212270"],["SC","Paulo Lopes","4212304"],["SC","Pedras Grandes","4212403"],["SC","Penha","4212502"],["SC","Peritiba","4212601"],["SC","Pescaria Brava","4212650"],["SC","Petrolândia","4212700"],["SC","Pinhalzinho","4212908"],["SC","Pinheiro Preto","4213005"],["SC","Piratuba","4213104"],["SC","Planalto Alegre","4213153"],["SC","Pomerode","4213203"],["SC","Ponte Alta","4213302"],["SC","Ponte Alta do Norte","4213351"],["SC","Ponte Serrada","4213401"],["SC","Porto Belo","4213500"],["SC","Porto União","4213609"],["SC","Pouso Redondo","4213708"],["SC","Praia Grande","4213807"],["SC","Presidente Castello Branco","4213906"],["SC","Presidente Getúlio","4214003"],["SC","Presidente Nereu","4214102"],["SC","Princesa","4214151"],["SC","Quilombo","4214201"],["SC","Rancho Queimado","4214300"],["SC","Rio das Antas","4214409"],["SC","Rio do Campo","4214508"],["SC","Rio do Oeste","4214607"],["SC","Rio do Sul","4214805"],["SC","Rio dos Cedros","4214706"],["SC","Rio Fortuna","4214904"],["SC","Rio Negrinho","4215000"],["SC","Rio Rufino","4215059"],["SC","Riqueza","4215075"],["SC","Rodeio","4215109"],["SC","Romelândia","4215208"],["SC","Salete","4215307"],["SC","Saltinho","4215356"],["SC","Salto Veloso","4215406"],["SC","Sangão","4215455"],["SC","Santa Cecília","4215505"],["SC","Santa Helena","4215554"],["SC","Santa Rosa de Lima","4215604"],["SC","Santa Rosa do Sul","4215653"],["SC","Santa Terezinha","4215679"],["SC","Santa Terezinha do Progresso","4215687"],["SC","Santiago do Sul","4215695"],["SC","Santo Amaro da Imperatriz","4215703"],["SC","São Bento do Sul","4215802"],["SC","São Bernardino","4215752"],["SC","São Bonifácio","4215901"],["SC","São Carlos","4216008"],["SC","São Cristóvão do Sul","4216057"],["SC","São Domingos","4216107"],["SC","São Francisco do Sul","4216206"],["SC","São João Batista","4216305"],["SC","São João do Itaperiú","4216354"],["SC","São João do Oeste","4216255"],["SC","São João do Sul","4216404"],["SC","São Joaquim","4216503"],["SC","São José","4216602"],["SC","São José do Cedro","4216701"],["SC","São José do Cerrito","4216800"],["SC","São Lourenço do Oeste","4216909"],["SC","São Ludgero","4217006"],["SC","São Martinho","4217105"],["SC","São Miguel da Boa Vista","4217154"],["SC","São Miguel do Oeste","4217204"],["SC","São Pedro de Alcântara","4217253"],["SC","Saudades","4217303"],["SC","Schroeder","4217402"],["SC","Seara","4217501"],["SC","Serra Alta","4217550"],["SC","Siderópolis","4217600"],["SC","Sombrio","4217709"],["SC","Sul Brasil","4217758"],["SC","Taió","4217808"],["SC","Tangará","4217907"],["SC","Tigrinhos","4217956"],["SC","Tijucas","4218004"],["SC","Timbé do Sul","4218103"],["SC","Timbó","4218202"],["SC","Timbó Grande","4218251"],["SC","Três Barras","4218301"],["SC","Treviso","4218350"],["SC","Treze de Maio","4218400"],["SC","Treze Tílias","4218509"],["SC","Trombudo Central","4218608"],["SC","Tubarão","4218707"],["SC","Tunápolis","4218756"],["SC","Turvo","4218806"],["SC","União do Oeste","4218855"],["SC","Urubici","4218905"],["SC","Urupema","4218954"],["SC","Urussanga","4219002"],["SC","Vargeão","4219101"],["SC","Vargem","4219150"],["SC","Vargem Bonita","4219176"],["SC","Vidal Ramos","4219200"],["SC","Videira","4219309"],["SC","Vitor Meireles","4219358"],["SC","Witmarsum","4219408"],["SC","Xanxerê","4219507"],["SC","Xavantina","4219606"],["SC","Xaxim","4219705"],["SC","Zortéa","4219853"],["SP","Adamantina","3500105"],["SP","Adolfo","3500204"],["SP","Aguaí","3500303"],["SP","Águas da Prata","3500402"],["SP","Águas de Lindóia","3500501"],["SP","Águas de Santa Bárbara","3500550"],["SP","Águas de São Pedro","3500600"],["SP","Agudos","3500709"],["SP","Alambari","3500758"],["SP","Alfredo Marcondes","3500808"],["SP","Altair","3500907"],["SP","Altinópolis","3501004"],["SP","Alto Alegre","3501103"],["SP","Alumínio","3501152"],["SP","Álvares Florence","3501202"],["SP","Álvares Machado","3501301"],["SP","Álvaro de Carvalho","3501400"],["SP","Alvinlândia","3501509"],["SP","Americana","3501608"],["SP","Américo Brasiliense","3501707"],["SP","Américo de Campos","3501806"],["SP","Amparo","3501905"],["SP","Analândia","3502002"],["SP","Andradina","3502101"],["SP","Angatuba","3502200"],["SP","Anhembi","3502309"],["SP","Anhumas","3502408"],["SP","Aparecida","3502507"],["SP","Aparecida d'Oeste","3502606"],["SP","Apiaí","3502705"],["SP","Araçariguama","3502754"],["SP","Araçatuba","3502804"],["SP","Araçoiaba da Serra","3502903"],["SP","Aramina","3503000"],["SP","Arandu","3503109"],["SP","Arapeí","3503158"],["SP","Araraquara","3503208"],["SP","Araras","3503307"],["SP","Arco-Íris","3503356"],["SP","Arealva","3503406"],["SP","Areias","3503505"],["SP","Areiópolis","3503604"],["SP","Ariranha","3503703"],["SP","Artur Nogueira","3503802"],["SP","Arujá","3503901"],["SP","Aspásia","3503950"],["SP","Assis","3504008"],["SP","Atibaia","3504107"],["SP","Auriflama","3504206"],["SP","Avaí","3504305"],["SP","Avanhandava","3504404"],["SP","Avaré","3504503"],["SP","Bady Bassitt","3504602"],["SP","Balbinos","3504701"],["SP","Bálsamo","3504800"],["SP","Bananal","3504909"],["SP","Barão de Antonina","3505005"],["SP","Barbosa","3505104"],["SP","Bariri","3505203"],["SP","Barra Bonita","3505302"],["SP","Barra do Chapéu","3505351"],["SP","Barra do Turvo","3505401"],["SP","Barretos","3505500"],["SP","Barrinha","3505609"],["SP","Barueri","3505708"],["SP","Bastos","3505807"],["SP","Batatais","3505906"],["SP","Bauru","3506003"],["SP","Bebedouro","3506102"],["SP","Bento de Abreu","3506201"],["SP","Bernardino de Campos","3506300"],["SP","Bertioga","3506359"],["SP","Bilac","3506409"],["SP","Birigui","3506508"],["SP","Biritiba Mirim","3506607"],["SP","Boa Esperança do Sul","3506706"],["SP","Bocaina","3506805"],["SP","Bofete","3506904"],["SP","Boituva","3507001"],["SP","Bom Jesus dos Perdões","3507100"],["SP","Bom Sucesso de Itararé","3507159"],["SP","Borá","3507209"],["SP","Boracéia","3507308"],["SP","Borborema","3507407"],["SP","Borebi","3507456"],["SP","Botucatu","3507506"],["SP","Bragança Paulista","3507605"],["SP","Braúna","3507704"],["SP","Brejo Alegre","3507753"],["SP","Brodowski","3507803"],["SP","Brotas","3507902"],["SP","Buri","3508009"],["SP","Buritama","3508108"],["SP","Buritizal","3508207"],["SP","Cabrália Paulista","3508306"],["SP","Cabreúva","3508405"],["SP","Caçapava","3508504"],["SP","Cachoeira Paulista","3508603"],["SP","Caconde","3508702"],["SP","Cafelândia","3508801"],["SP","Caiabu","3508900"],["SP","Caieiras","3509007"],["SP","Caiuá","3509106"],["SP","Cajamar","3509205"],["SP","Cajati","3509254"],["SP","Cajobi","3509304"],["SP","Cajuru","3509403"],["SP","Campina do Monte Alegre","3509452"],["SP","Campinas","3509502"],["SP","Campo Limpo Paulista","3509601"],["SP","Campos do Jordão","3509700"],["SP","Campos Novos Paulista","3509809"],["SP","Cananéia","3509908"],["SP","Canas","3509957"],["SP","Cândido Mota","3510005"],["SP","Cândido Rodrigues","3510104"],["SP","Canitar","3510153"],["SP","Capão Bonito","3510203"],["SP","Capela do Alto","3510302"],["SP","Capivari","3510401"],["SP","Caraguatatuba","3510500"],["SP","Carapicuíba","3510609"],["SP","Cardoso","3510708"],["SP","Casa Branca","3510807"],["SP","Cássia dos Coqueiros","3510906"],["SP","Castilho","3511003"],["SP","Catanduva","3511102"],["SP","Catiguá","3511201"],["SP","Cedral","3511300"],["SP","Cerqueira César","3511409"],["SP","Cerquilho","3511508"],["SP","Cesário Lange","3511607"],["SP","Charqueada","3511706"],["SP","Chavantes","3557204"],["SP","Clementina","3511904"],["SP","Colina","3512001"],["SP","Colômbia","3512100"],["SP","Conchal","3512209"],["SP","Conchas","3512308"],["SP","Cordeirópolis","3512407"],["SP","Coroados","3512506"],["SP","Coronel Macedo","3512605"],["SP","Corumbataí","3512704"],["SP","Cosmópolis","3512803"],["SP","Cosmorama","3512902"],["SP","Cotia","3513009"],["SP","Cravinhos","3513108"],["SP","Cristais Paulista","3513207"],["SP","Cruzália","3513306"],["SP","Cruzeiro","3513405"],["SP","Cubatão","3513504"],["SP","Cunha","3513603"],["SP","Descalvado","3513702"],["SP","Diadema","3513801"],["SP","Dirce Reis","3513850"],["SP","Divinolândia","3513900"],["SP","Dobrada","3514007"],["SP","Dois Córregos","3514106"],["SP","Dolcinópolis","3514205"],["SP","Dourado","3514304"],["SP","Dracena","3514403"],["SP","Duartina","3514502"],["SP","Dumont","3514601"],["SP","Echaporã","3514700"],["SP","Eldorado","3514809"],["SP","Elias Fausto","3514908"],["SP","Elisiário","3514924"],["SP","Embaúba","3514957"],["SP","Embu das Artes","3515004"],["SP","Embu-Guaçu","3515103"],["SP","Emilianópolis","3515129"],["SP","Engenheiro Coelho","3515152"],["SP","Espírito Santo do Pinhal","3515186"],["SP","Espírito Santo do Turvo","3515194"],["SP","Estiva Gerbi","3557303"],["SP","Estrela d'Oeste","3515202"],["SP","Estrela do Norte","3515301"],["SP","Euclides da Cunha Paulista","3515350"],["SP","Fartura","3515400"],["SP","Fernando Prestes","3515608"],["SP","Fernandópolis","3515509"],["SP","Fernão","3515657"],["SP","Ferraz de Vasconcelos","3515707"],["SP","Flora Rica","3515806"],["SP","Floreal","3515905"],["SP","Flórida Paulista","3516002"],["SP","Florínea","3516101"],["SP","Franca","3516200"],["SP","Francisco Morato","3516309"],["SP","Franco da Rocha","3516408"],["SP","Gabriel Monteiro","3516507"],["SP","Gália","3516606"],["SP","Garça","3516705"],["SP","Gastão Vidigal","3516804"],["SP","Gavião Peixoto","3516853"],["SP","General Salgado","3516903"],["SP","Getulina","3517000"],["SP","Glicério","3517109"],["SP","Guaiçara","3517208"],["SP","Guaimbê","3517307"],["SP","Guaíra","3517406"],["SP","Guapiaçu","3517505"],["SP","Guapiara","3517604"],["SP","Guará","3517703"],["SP","Guaraçaí","3517802"],["SP","Guaraci","3517901"],["SP","Guarani d'Oeste","3518008"],["SP","Guarantã","3518107"],["SP","Guararapes","3518206"],["SP","Guararema","3518305"],["SP","Guaratinguetá","3518404"],["SP","Guareí","3518503"],["SP","Guariba","3518602"],["SP","Guarujá","3518701"],["SP","Guarulhos","3518800"],["SP","Guatapará","3518859"],["SP","Guzolândia","3518909"],["SP","Herculândia","3519006"],["SP","Holambra","3519055"],["SP","Hortolândia","3519071"],["SP","Iacanga","3519105"],["SP","Iacri","3519204"],["SP","Iaras","3519253"],["SP","Ibaté","3519303"],["SP","Ibirá","3519402"],["SP","Ibirarema","3519501"],["SP","Ibitinga","3519600"],["SP","Ibiúna","3519709"],["SP","Icém","3519808"],["SP","Iepê","3519907"],["SP","Igaraçu do Tietê","3520004"],["SP","Igarapava","3520103"],["SP","Igaratá","3520202"],["SP","Iguape","3520301"],["SP","Ilha Comprida","3520426"],["SP","Ilha Solteira","3520442"],["SP","Ilhabela","3520400"],["SP","Indaiatuba","3520509"],["SP","Indiana","3520608"],["SP","Indiaporã","3520707"],["SP","Inúbia Paulista","3520806"],["SP","Ipaussu","3520905"],["SP","Iperó","3521002"],["SP","Ipeúna","3521101"],["SP","Ipiguá","3521150"],["SP","Iporanga","3521200"],["SP","Ipuã","3521309"],["SP","Iracemápolis","3521408"],["SP","Irapuã","3521507"],["SP","Irapuru","3521606"],["SP","Itaberá","3521705"],["SP","Itaí","3521804"],["SP","Itajobi","3521903"],["SP","Itaju","3522000"],["SP","Itanhaém","3522109"],["SP","Itaoca","3522158"],["SP","Itapecerica da Serra","3522208"],["SP","Itapetininga","3522307"],["SP","Itapeva","3522406"],["SP","Itapevi","3522505"],["SP","Itapira","3522604"],["SP","Itapirapuã Paulista","3522653"],["SP","Itápolis","3522703"],["SP","Itaporanga","3522802"],["SP","Itapuí","3522901"],["SP","Itapura","3523008"],["SP","Itaquaquecetuba","3523107"],["SP","Itararé","3523206"],["SP","Itariri","3523305"],["SP","Itatiba","3523404"],["SP","Itatinga","3523503"],["SP","Itirapina","3523602"],["SP","Itirapuã","3523701"],["SP","Itobi","3523800"],["SP","Itu","3523909"],["SP","Itupeva","3524006"],["SP","Ituverava","3524105"],["SP","Jaborandi","3524204"],["SP","Jaboticabal","3524303"],["SP","Jacareí","3524402"],["SP","Jaci","3524501"],["SP","Jacupiranga","3524600"],["SP","Jaguariúna","3524709"],["SP","Jales","3524808"],["SP","Jambeiro","3524907"],["SP","Jandira","3525003"],["SP","Jardinópolis","3525102"],["SP","Jarinu","3525201"],["SP","Jaú","3525300"],["SP","Jeriquara","3525409"],["SP","Joanópolis","3525508"],["SP","João Ramalho","3525607"],["SP","José Bonifácio","3525706"],["SP","Júlio Mesquita","3525805"],["SP","Jumirim","3525854"],["SP","Jundiaí","3525904"],["SP","Junqueirópolis","3526001"],["SP","Juquiá","3526100"],["SP","Juquitiba","3526209"],["SP","Lagoinha","3526308"],["SP","Laranjal Paulista","3526407"],["SP","Lavínia","3526506"],["SP","Lavrinhas","3526605"],["SP","Leme","3526704"],["SP","Lençóis Paulista","3526803"],["SP","Limeira","3526902"],["SP","Lindóia","3527009"],["SP","Lins","3527108"],["SP","Lorena","3527207"],["SP","Lourdes","3527256"],["SP","Louveira","3527306"],["SP","Lucélia","3527405"],["SP","Lucianópolis","3527504"],["SP","Luís Antônio","3527603"],["SP","Luiziânia","3527702"],["SP","Lupércio","3527801"],["SP","Lutécia","3527900"],["SP","Macatuba","3528007"],["SP","Macaubal","3528106"],["SP","Macedônia","3528205"],["SP","Magda","3528304"],["SP","Mairinque","3528403"],["SP","Mairiporã","3528502"],["SP","Manduri","3528601"],["SP","Marabá Paulista","3528700"],["SP","Maracaí","3528809"],["SP","Marapoama","3528858"],["SP","Mariápolis","3528908"],["SP","Marília","3529005"],["SP","Marinópolis","3529104"],["SP","Martinópolis","3529203"],["SP","Matão","3529302"],["SP","Mauá","3529401"],["SP","Mendonça","3529500"],["SP","Meridiano","3529609"],["SP","Mesópolis","3529658"],["SP","Miguelópolis","3529708"],["SP","Mineiros do Tietê","3529807"],["SP","Mira Estrela","3530003"],["SP","Miracatu","3529906"],["SP","Mirandópolis","3530102"],["SP","Mirante do Paranapanema","3530201"],["SP","Mirassol","3530300"],["SP","Mirassolândia","3530409"],["SP","Mococa","3530508"],["SP","Mogi das Cruzes","3530607"],["SP","Mogi Guaçu","3530706"],["SP","Mogi Mirim","3530805"],["SP","Mombuca","3530904"],["SP","Monções","3531001"],["SP","Mongaguá","3531100"],["SP","Monte Alegre do Sul","3531209"],["SP","Monte Alto","3531308"],["SP","Monte Aprazível","3531407"],["SP","Monte Azul Paulista","3531506"],["SP","Monte Castelo","3531605"],["SP","Monte Mor","3531803"],["SP","Monteiro Lobato","3531704"],["SP","Morro Agudo","3531902"],["SP","Morungaba","3532009"],["SP","Motuca","3532058"],["SP","Murutinga do Sul","3532108"],["SP","Nantes","3532157"],["SP","Narandiba","3532207"],["SP","Natividade da Serra","3532306"],["SP","Nazaré Paulista","3532405"],["SP","Neves Paulista","3532504"],["SP","Nhandeara","3532603"],["SP","Nipoã","3532702"],["SP","Nova Aliança","3532801"],["SP","Nova Campina","3532827"],["SP","Nova Canaã Paulista","3532843"],["SP","Nova Castilho","3532868"],["SP","Nova Europa","3532900"],["SP","Nova Granada","3533007"],["SP","Nova Guataporanga","3533106"],["SP","Nova Independência","3533205"],["SP","Nova Luzitânia","3533304"],["SP","Nova Odessa","3533403"],["SP","Novais","3533254"],["SP","Novo Horizonte","3533502"],["SP","Nuporanga","3533601"],["SP","Ocauçu","3533700"],["SP","Óleo","3533809"],["SP","Olímpia","3533908"],["SP","Onda Verde","3534005"],["SP","Oriente","3534104"],["SP","Orindiúva","3534203"],["SP","Orlândia","3534302"],["SP","Osasco","3534401"],["SP","Oscar Bressane","3534500"],["SP","Osvaldo Cruz","3534609"],["SP","Ourinhos","3534708"],["SP","Ouro Verde","3534807"],["SP","Ouroeste","3534757"],["SP","Pacaembu","3534906"],["SP","Palestina","3535002"],["SP","Palmares Paulista","3535101"],["SP","Palmeira d'Oeste","3535200"],["SP","Palmital","3535309"],["SP","Panorama","3535408"],["SP","Paraguaçu Paulista","3535507"],["SP","Paraibuna","3535606"],["SP","Paraíso","3535705"],["SP","Paranapanema","3535804"],["SP","Paranapuã","3535903"],["SP","Parapuã","3536000"],["SP","Pardinho","3536109"],["SP","Pariquera-Açu","3536208"],["SP","Parisi","3536257"],["SP","Patrocínio Paulista","3536307"],["SP","Paulicéia","3536406"],["SP","Paulínia","3536505"],["SP","Paulistânia","3536570"],["SP","Paulo de Faria","3536604"],["SP","Pederneiras","3536703"],["SP","Pedra Bela","3536802"],["SP","Pedranópolis","3536901"],["SP","Pedregulho","3537008"],["SP","Pedreira","3537107"],["SP","Pedrinhas Paulista","3537156"],["SP","Pedro de Toledo","3537206"],["SP","Penápolis","3537305"],["SP","Pereira Barreto","3537404"],["SP","Pereiras","3537503"],["SP","Peruíbe","3537602"],["SP","Piacatu","3537701"],["SP","Piedade","3537800"],["SP","Pilar do Sul","3537909"],["SP","Pindamonhangaba","3538006"],["SP","Pindorama","3538105"],["SP","Pinhalzinho","3538204"],["SP","Piquerobi","3538303"],["SP","Piquete","3538501"],["SP","Piracaia","3538600"],["SP","Piracicaba","3538709"],["SP","Piraju","3538808"],["SP","Pirajuí","3538907"],["SP","Pirangi","3539004"],["SP","Pirapora do Bom Jesus","3539103"],["SP","Pirapozinho","3539202"],["SP","Pirassununga","3539301"],["SP","Piratininga","3539400"],["SP","Pitangueiras","3539509"],["SP","Planalto","3539608"],["SP","Platina","3539707"],["SP","Poá","3539806"],["SP","Poloni","3539905"],["SP","Pompéia","3540002"],["SP","Pongaí","3540101"],["SP","Pontal","3540200"],["SP","Pontalinda","3540259"],["SP","Pontes Gestal","3540309"],["SP","Populina","3540408"],["SP","Porangaba","3540507"],["SP","Porto Feliz","3540606"],["SP","Porto Ferreira","3540705"],["SP","Potim","3540754"],["SP","Potirendaba","3540804"],["SP","Pracinha","3540853"],["SP","Pradópolis","3540903"],["SP","Praia Grande","3541000"],["SP","Pratânia","3541059"],["SP","Presidente Alves","3541109"],["SP","Presidente Bernardes","3541208"],["SP","Presidente Epitácio","3541307"],["SP","Presidente Prudente","3541406"],["SP","Presidente Venceslau","3541505"],["SP","Promissão","3541604"],["SP","Quadra","3541653"],["SP","Quatá","3541703"],["SP","Queiroz","3541802"],["SP","Queluz","3541901"],["SP","Quintana","3542008"],["SP","Rafard","3542107"],["SP","Rancharia","3542206"],["SP","Redenção da Serra","3542305"],["SP","Regente Feijó","3542404"],["SP","Reginópolis","3542503"],["SP","Registro","3542602"],["SP","Restinga","3542701"],["SP","Ribeira","3542800"],["SP","Ribeirão Bonito","3542909"],["SP","Ribeirão Branco","3543006"],["SP","Ribeirão Corrente","3543105"],["SP","Ribeirão do Sul","3543204"],["SP","Ribeirão dos Índios","3543238"],["SP","Ribeirão Grande","3543253"],["SP","Ribeirão Pires","3543303"],["SP","Ribeirão Preto","3543402"],["SP","Rifaina","3543600"],["SP","Rincão","3543709"],["SP","Rinópolis","3543808"],["SP","Rio Claro","3543907"],["SP","Rio das Pedras","3544004"],["SP","Rio Grande da Serra","3544103"],["SP","Riolândia","3544202"],["SP","Riversul","3543501"],["SP","Rosana","3544251"],["SP","Roseira","3544301"],["SP","Rubiácea","3544400"],["SP","Rubinéia","3544509"],["SP","Sabino","3544608"],["SP","Sagres","3544707"],["SP","Sales","3544806"],["SP","Sales Oliveira","3544905"],["SP","Salesópolis","3545001"],["SP","Salmourão","3545100"],["SP","Saltinho","3545159"],["SP","Salto","3545209"],["SP","Salto de Pirapora","3545308"],["SP","Salto Grande","3545407"],["SP","Sandovalina","3545506"],["SP","Santa Adélia","3545605"],["SP","Santa Albertina","3545704"],["SP","Santa Bárbara d'Oeste","3545803"],["SP","Santa Branca","3546009"],["SP","Santa Clara d'Oeste","3546108"],["SP","Santa Cruz da Conceição","3546207"],["SP","Santa Cruz da Esperança","3546256"],["SP","Santa Cruz das Palmeiras","3546306"],["SP","Santa Cruz do Rio Pardo","3546405"],["SP","Santa Ernestina","3546504"],["SP","Santa Fé do Sul","3546603"],["SP","Santa Gertrudes","3546702"],["SP","Santa Isabel","3546801"],["SP","Santa Lúcia","3546900"],["SP","Santa Maria da Serra","3547007"],["SP","Santa Mercedes","3547106"],["SP","Santa Rita d'Oeste","3547403"],["SP","Santa Rita do Passa Quatro","3547502"],["SP","Santa Rosa de Viterbo","3547601"],["SP","Santa Salete","3547650"],["SP","Santana da Ponte Pensa","3547205"],["SP","Santana de Parnaíba","3547304"],["SP","Santo Anastácio","3547700"],["SP","Santo André","3547809"],["SP","Santo Antônio da Alegria","3547908"],["SP","Santo Antônio de Posse","3548005"],["SP","Santo Antônio do Aracanguá","3548054"],["SP","Santo Antônio do Jardim","3548104"],["SP","Santo Antônio do Pinhal","3548203"],["SP","Santo Expedito","3548302"],["SP","Santópolis do Aguapeí","3548401"],["SP","Santos","3548500"],["SP","São Bento do Sapucaí","3548609"],["SP","São Bernardo do Campo","3548708"],["SP","São Caetano do Sul","3548807"],["SP","São Carlos","3548906"],["SP","São Francisco","3549003"],["SP","São João da Boa Vista","3549102"],["SP","São João das Duas Pontes","3549201"],["SP","São João de Iracema","3549250"],["SP","São João do Pau d'Alho","3549300"],["SP","São Joaquim da Barra","3549409"],["SP","São José da Bela Vista","3549508"],["SP","São José do Barreiro","3549607"],["SP","São José do Rio Pardo","3549706"],["SP","São José do Rio Preto","3549805"],["SP","São José dos Campos","3549904"],["SP","São Lourenço da Serra","3549953"],["SP","São Luiz do Paraitinga","3550001"],["SP","São Manuel","3550100"],["SP","São Miguel Arcanjo","3550209"],["SP","São Paulo","3550308"],["SP","São Pedro","3550407"],["SP","São Pedro do Turvo","3550506"],["SP","São Roque","3550605"],["SP","São Sebastião","3550704"],["SP","São Sebastião da Grama","3550803"],["SP","São Simão","3550902"],["SP","São Vicente","3551009"],["SP","Sarapuí","3551108"],["SP","Sarutaiá","3551207"],["SP","Sebastianópolis do Sul","3551306"],["SP","Serra Azul","3551405"],["SP","Serra Negra","3551603"],["SP","Serrana","3551504"],["SP","Sertãozinho","3551702"],["SP","Sete Barras","3551801"],["SP","Severínia","3551900"],["SP","Silveiras","3552007"],["SP","Socorro","3552106"],["SP","Sorocaba","3552205"],["SP","Sud Mennucci","3552304"],["SP","Sumaré","3552403"],["SP","Suzanápolis","3552551"],["SP","Suzano","3552502"],["SP","Tabapuã","3552601"],["SP","Tabatinga","3552700"],["SP","Taboão da Serra","3552809"],["SP","Taciba","3552908"],["SP","Taguaí","3553005"],["SP","Taiaçu","3553104"],["SP","Taiúva","3553203"],["SP","Tambaú","3553302"],["SP","Tanabi","3553401"],["SP","Tapiraí","3553500"],["SP","Tapiratiba","3553609"],["SP","Taquaral","3553658"],["SP","Taquaritinga","3553708"],["SP","Taquarituba","3553807"],["SP","Taquarivaí","3553856"],["SP","Tarabai","3553906"],["SP","Tarumã","3553955"],["SP","Tatuí","3554003"],["SP","Taubaté","3554102"],["SP","Tejupá","3554201"],["SP","Teodoro Sampaio","3554300"],["SP","Terra Roxa","3554409"],["SP","Tietê","3554508"],["SP","Timburi","3554607"],["SP","Torre de Pedra","3554656"],["SP","Torrinha","3554706"],["SP","Trabiju","3554755"],["SP","Tremembé","3554805"],["SP","Três Fronteiras","3554904"],["SP","Tuiuti","3554953"],["SP","Tupã","3555000"],["SP","Tupi Paulista","3555109"],["SP","Turiúba","3555208"],["SP","Turmalina","3555307"],["SP","Ubarana","3555356"],["SP","Ubatuba","3555406"],["SP","Ubirajara","3555505"],["SP","Uchoa","3555604"],["SP","União Paulista","3555703"],["SP","Urânia","3555802"],["SP","Uru","3555901"],["SP","Urupês","3556008"],["SP","Valentim Gentil","3556107"],["SP","Valinhos","3556206"],["SP","Valparaíso","3556305"],["SP","Vargem","3556354"],["SP","Vargem Grande do Sul","3556404"],["SP","Vargem Grande Paulista","3556453"],["SP","Várzea Paulista","3556503"],["SP","Vera Cruz","3556602"],["SP","Vinhedo","3556701"],["SP","Viradouro","3556800"],["SP","Vista Alegre do Alto","3556909"],["SP","Vitória Brasil","3556958"],["SP","Votorantim","3557006"],["SP","Votuporanga","3557105"],["SP","Zacarias","3557154"],["SE","Amparo do São Francisco","2800100"],["SE","Aquidabã","2800209"],["SE","Aracaju","2800308"],["SE","Arauá","2800407"],["SE","Areia Branca","2800506"],["SE","Barra dos Coqueiros","2800605"],["SE","Boquim","2800670"],["SE","Brejo Grande","2800704"],["SE","Campo do Brito","2801009"],["SE","Canhoba","2801108"],["SE","Canindé de São Francisco","2801207"],["SE","Capela","2801306"],["SE","Carira","2801405"],["SE","Carmópolis","2801504"],["SE","Cedro de São João","2801603"],["SE","Cristinápolis","2801702"],["SE","Cumbe","2801900"],["SE","Divina Pastora","2802007"],["SE","Estância","2802106"],["SE","Feira Nova","2802205"],["SE","Frei Paulo","2802304"],["SE","Gararu","2802403"],["SE","General Maynard","2802502"],["SE","Graccho Cardoso","2802601"],["SE","Ilha das Flores","2802700"],["SE","Indiaroba","2802809"],["SE","Itabaiana","2802908"],["SE","Itabaianinha","2803005"],["SE","Itabi","2803104"],["SE","Itaporanga d'Ajuda","2803203"],["SE","Japaratuba","2803302"],["SE","Japoatã","2803401"],["SE","Lagarto","2803500"],["SE","Laranjeiras","2803609"],["SE","Macambira","2803708"],["SE","Malhada dos Bois","2803807"],["SE","Malhador","2803906"],["SE","Maruim","2804003"],["SE","Moita Bonita","2804102"],["SE","Monte Alegre de Sergipe","2804201"],["SE","Muribeca","2804300"],["SE","Neópolis","2804409"],["SE","Nossa Senhora Aparecida","2804458"],["SE","Nossa Senhora da Glória","2804508"],["SE","Nossa Senhora das Dores","2804607"],["SE","Nossa Senhora de Lourdes","2804706"],["SE","Nossa Senhora do Socorro","2804805"],["SE","Pacatuba","2804904"],["SE","Pedra Mole","2805000"],["SE","Pedrinhas","2805109"],["SE","Pinhão","2805208"],["SE","Pirambu","2805307"],["SE","Poço Redondo","2805406"],["SE","Poço Verde","2805505"],["SE","Porto da Folha","2805604"],["SE","Propriá","2805703"],["SE","Riachão do Dantas","2805802"],["SE","Riachuelo","2805901"],["SE","Ribeirópolis","2806008"],["SE","Rosário do Catete","2806107"],["SE","Salgado","2806206"],["SE","Santa Luzia do Itanhy","2806305"],["SE","Santa Rosa de Lima","2806503"],["SE","Santana do São Francisco","2806404"],["SE","Santo Amaro das Brotas","2806602"],["SE","São Cristóvão","2806701"],["SE","São Domingos","2806800"],["SE","São Francisco","2806909"],["SE","São Miguel do Aleixo","2807006"],["SE","Simão Dias","2807105"],["SE","Siriri","2807204"],["SE","Telha","2807303"],["SE","Tobias Barreto","2807402"],["SE","Tomar do Geru","2807501"],["SE","Umbaúba","2807600"],["TO","Abreulândia","1700251"],["TO","Aguiarnópolis","1700301"],["TO","Aliança do Tocantins","1700350"],["TO","Almas","1700400"],["TO","Alvorada","1700707"],["TO","Ananás","1701002"],["TO","Angico","1701051"],["TO","Aparecida do Rio Negro","1701101"],["TO","Aragominas","1701309"],["TO","Araguacema","1701903"],["TO","Araguaçu","1702000"],["TO","Araguaína","1702109"],["TO","Araguanã","1702158"],["TO","Araguatins","1702208"],["TO","Arapoema","1702307"],["TO","Arraias","1702406"],["TO","Augustinópolis","1702554"],["TO","Aurora do Tocantins","1702703"],["TO","Axixá do Tocantins","1702901"],["TO","Babaçulândia","1703008"],["TO","Bandeirantes do Tocantins","1703057"],["TO","Barra do Ouro","1703073"],["TO","Barrolândia","1703107"],["TO","Bernardo Sayão","1703206"],["TO","Bom Jesus do Tocantins","1703305"],["TO","Brasilândia do Tocantins","1703602"],["TO","Brejinho de Nazaré","1703701"],["TO","Buriti do Tocantins","1703800"],["TO","Cachoeirinha","1703826"],["TO","Campos Lindos","1703842"],["TO","Cariri do Tocantins","1703867"],["TO","Carmolândia","1703883"],["TO","Carrasco Bonito","1703891"],["TO","Caseara","1703909"],["TO","Centenário","1704105"],["TO","Chapada da Natividade","1705102"],["TO","Chapada de Areia","1704600"],["TO","Colinas do Tocantins","1705508"],["TO","Colméia","1716703"],["TO","Combinado","1705557"],["TO","Conceição do Tocantins","1705607"],["TO","Couto Magalhães","1706001"],["TO","Cristalândia","1706100"],["TO","Crixás do Tocantins","1706258"],["TO","Darcinópolis","1706506"],["TO","Dianópolis","1707009"],["TO","Divinópolis do Tocantins","1707108"],["TO","Dois Irmãos do Tocantins","1707207"],["TO","Dueré","1707306"],["TO","Esperantina","1707405"],["TO","Fátima","1707553"],["TO","Figueirópolis","1707652"],["TO","Filadélfia","1707702"],["TO","Formoso do Araguaia","1708205"],["TO","Goianorte","1708304"],["TO","Goiatins","1709005"],["TO","Guaraí","1709302"],["TO","Gurupi","1709500"],["TO","Ipueiras","1709807"],["TO","Itacajá","1710508"],["TO","Itaguatins","1710706"],["TO","Itapiratins","1710904"],["TO","Itaporã do Tocantins","1711100"],["TO","Jaú do Tocantins","1711506"],["TO","Juarina","1711803"],["TO","Lagoa da Confusão","1711902"],["TO","Lagoa do Tocantins","1711951"],["TO","Lajeado","1712009"],["TO","Lavandeira","1712157"],["TO","Lizarda","1712405"],["TO","Luzinópolis","1712454"],["TO","Marianópolis do Tocantins","1712504"],["TO","Mateiros","1712702"],["TO","Maurilândia do Tocantins","1712801"],["TO","Miracema do Tocantins","1713205"],["TO","Miranorte","1713304"],["TO","Monte do Carmo","1713601"],["TO","Monte Santo do Tocantins","1713700"],["TO","Muricilândia","1713957"],["TO","Natividade","1714203"],["TO","Nazaré","1714302"],["TO","Nova Olinda","1714880"],["TO","Nova Rosalândia","1715002"],["TO","Novo Acordo","1715101"],["TO","Novo Alegre","1715150"],["TO","Novo Jardim","1715259"],["TO","Oliveira de Fátima","1715507"],["TO","Palmas","1721000"],["TO","Palmeirante","1715705"],["TO","Palmeiras do Tocantins","1713809"],["TO","Palmeirópolis","1715754"],["TO","Paraíso do Tocantins","1716109"],["TO","Paranã","1716208"],["TO","Pau D'Arco","1716307"],["TO","Pedro Afonso","1716505"],["TO","Peixe","1716604"],["TO","Pequizeiro","1716653"],["TO","Pindorama do Tocantins","1717008"],["TO","Piraquê","1717206"],["TO","Pium","1717503"],["TO","Ponte Alta do Bom Jesus","1717800"],["TO","Ponte Alta do Tocantins","1717909"],["TO","Porto Alegre do Tocantins","1718006"],["TO","Porto Nacional","1718204"],["TO","Praia Norte","1718303"],["TO","Presidente Kennedy","1718402"],["TO","Pugmil","1718451"],["TO","Recursolândia","1718501"],["TO","Riachinho","1718550"],["TO","Rio da Conceição","1718659"],["TO","Rio dos Bois","1718709"],["TO","Rio Sono","1718758"],["TO","Sampaio","1718808"],["TO","Sandolândia","1718840"],["TO","Santa Fé do Araguaia","1718865"],["TO","Santa Maria do Tocantins","1718881"],["TO","Santa Rita do Tocantins","1718899"],["TO","Santa Rosa do Tocantins","1718907"],["TO","Santa Tereza do Tocantins","1719004"],["TO","Santa Terezinha do Tocantins","1720002"],["TO","São Bento do Tocantins","1720101"],["TO","São Félix do Tocantins","1720150"],["TO","São Miguel do Tocantins","1720200"],["TO","São Salvador do Tocantins","1720259"],["TO","São Sebastião do Tocantins","1720309"],["TO","São Valério","1720499"],["TO","Silvanópolis","1720655"],["TO","Sítio Novo do Tocantins","1720804"],["TO","Sucupira","1720853"],["TO","Tabocão","1708254"],["TO","Taguatinga","1720903"],["TO","Taipas do Tocantins","1720937"],["TO","Talismã","1720978"],["TO","Tocantínia","1721109"],["TO","Tocantinópolis","1721208"],["TO","Tupirama","1721257"],["TO","Tupiratins","1721307"],["TO","Wanderlândia","1722081"],["TO","Xambioá","1722107"]],"groups":{"AC":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21],"AL":[22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123],"AP":[124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139],"AM":[140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201],"BA":[202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,270,271,272,273,274,275,276,277,278,279,280,281,282,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,350,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,371,372,373,374,375,376,377,378,379,380,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,400,401,402,403,404,405,406,407,408,409,410,411,412,413,414,415,416,417,418,419,420,421,422,423,424,425,426,427,428,429,430,431,432,433,434,435,436,437,438,439,440,441,442,443,444,445,446,447,448,449,450,451,452,453,454,455,456,457,458,459,460,461,462,463,464,465,466,467,468,469,470,471,472,473,474,475,476,477,478,479,480,481,482,483,484,485,486,487,488,489,490,491,492,493,494,495,496,497,498,499,500,501,502,503,504,505,506,507,508,509,510,511,512,513,514,515,516,517,518,519,520,521,522,523,524,525,526,527,528,529,530,531,532,533,534,535,536,537,538,539,540,541,542,543,544,545,546,547,548,549,550,551,552,553,554,555,556,557,558,559,560,561,562,563,564,565,566,567,568,569,570,571,572,573,574,575,576,577,578,579,580,581,582,583,584,585,586,587,588,589,590,591,592,593,594,595,596,597,598,599,600,601,602,603,604,605,606,607,608,609,610,611,612,613,614,615,616,617,618],"CE":[619,620,621,622,623,624,625,626,627,628,629,630,631,632,633,634,635,636,637,638,639,640,641,642,643,644,645,646,647,648,649,650,651,652,653,654,655,656,657,658,659,660,661,662,663,664,665,666,667,668,669,670,671,672,673,674,675,676,677,678,679,680,681,682,683,684,685,686,687,688,689,690,691,692,693,694,695,696,697,698,699,700,701,702,703,704,705,706,707,708,709,710,711,712,713,714,715,716,717,718,719,720,721,722,723,724,725,726,727,728,729,730,731,732,733,734,735,736,737,738,739,740,741,742,743,744,745,746,747,748,749,750,751,752,753,754,755,756,757,758,759,760,761,762,763,764,765,766,767,768,769,770,771,772,773,774,775,776,777,778,779,780,781,782,783,784,785,786,787,788,789,790,791,792,793,794,795,796,797,798,799,800,801,802],"DF":[803],"ES":[804,805,806,807,808,809,810,811,812,813,814,815,816,817,818,819,820,821,822,823,824,825,826,827,828,829,830,831,832,833,834,835,836,837,838,839,840,841,842,843,844,845,846,847,848,849,850,851,852,853,854,855,856,857,858,859,860,861,862,863,864,865,866,867,868,869,870,871,872,873,874,875,876,877,878,879,880,881],"GO":[882,883,884,885,886,887,888,889,890,891,892,893,894,895,896,897,898,899,900,901,902,903,904,905,906,907,908,909,910,911,912,913,914,915,916,917,918,919,920,921,922,923,924,925,926,927,928,929,930,931,932,933,934,935,936,937,938,939,940,941,942,943,944,945,946,947,948,949,950,951,952,953,954,955,956,957,958,959,960,961,962,963,964,965,966,967,968,969,970,971,972,973,974,975,976,977,978,979,980,981,982,983,984,985,986,987,988,989,990,991,992,993,994,995,996,997,998,999,1000,1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1011,1012,1013,1014,1015,1016,1017,1018,1019,1020,1021,1022,1023,1024,1025,1026,1027,1028,1029,1030,1031,1032,1033,1034,1035,1036,1037,1038,1039,1040,1041,1042,1043,1044,1045,1046,1047,1048,1049,1050,1051,1052,1053,1054,1055,1056,1057,1058,1059,1060,1061,1062,1063,1064,1065,1066,1067,1068,1069,1070,1071,1072,1073,1074,1075,1076,1077,1078,1079,1080,1081,1082,1083,1084,1085,1086,1087,1088,1089,1090,1091,1092,1093,1094,1095,1096,1097,1098,1099,1100,1101,1102,1103,1104,1105,1106,1107,1108,1109,1110,1111,1112,1113,1114,1115,1116,1117,1118,1119,1120,1121,1122,1123,1124,1125,1126,1127],"MA":[1128,1129,1130,1131,1132,1133,1134,1135,1136,1137,1138,1139,1140,1141,1142,1143,1144,1145,1146,1147,1148,1149,1150,1151,1152,1153,1154,1155,1156,1157,1158,1159,1160,1161,1162,1163,1164,1165,1166,1167,1168,1169,1170,1171,1172,1173,1174,1175,1176,1177,1178,1179,1180,1181,1182,1183,1184,1185,1186,1187,1188,1189,1190,1191,1192,1193,1194,1195,1196,1197,1198,1199,1200,1201,1202,1203,1204,1205,1206,1207,1208,1209,1210,1211,1212,1213,1214,1215,1216,1217,1218,1219,1220,1221,1222,1223,1224,1225,1226,1227,1228,1229,1230,1231,1232,1233,1234,1235,1236,1237,1238,1239,1240,1241,1242,1243,1244,1245,1246,1247,1248,1249,1250,1251,1252,1253,1254,1255,1256,1257,1258,1259,1260,1261,1262,1263,1264,1265,1266,1267,1268,1269,1270,1271,1272,1273,1274,1275,1276,1277,1278,1279,1280,1281,1282,1283,1284,1285,1286,1287,1288,1289,1290,1291,1292,1293,1294,1295,1296,1297,1298,1299,1300,1301,1302,1303,1304,1305,1306,1307,1308,1309,1310,1311,1312,1313,1314,1315,1316,1317,1318,1319,1320,1321,1322,1323,1324,1325,1326,1327,1328,1329,1330,1331,1332,1333,1334,1335,1336,1337,1338,1339,1340,1341,1342,1343,1344],"MT":[1345,1346,1347,1348,1349,1350,1351,1352,1353,1354,1355,1356,1357,1358,1359,1360,1361,1362,1363,1364,1365,1366,1367,1368,1369,1370,1371,1372,1373,1374,1375,1376,1377,1378,1379,1380,1381,1382,1383,1384,1385,1386,1387,1388,1389,1390,1391,1392,1393,1394,1395,1396,1397,1398,1399,1400,1401,1402,1403,1404,1405,1406,1407,1408,1409,1410,1411,1412,1413,1414,1415,1416,1417,1418,1419,1420,1421,1422,1423,1424,1425,1426,1427,1428,1429,1430,1431,1432,1433,1434,1435,1436,1437,1438,1439,1440,1441,1442,1443,1444,1445,1446,1447,1448,1449,1450,1451,1452,1453,1454,1455,1456,1457,1458,1459,1460,1461,1462,1463,1464,1465,1466,1467,1468,1469,1470,1471,1472,1473,1474,1475,1476,1477,1478,1479,1480,1481,1482,1483,1484,1485,1486],"MS":[1487,1488,1489,1490,1491,1492,1493,1494,1495,1496,1497,1498,1499,1500,1501,1502,1503,1504,1505,1506,1507,1508,1509,1510,1511,1512,1513,1514,1515,1516,1517,1518,1519,1520,1521,1522,1523,1524,1525,1526,1527,1528,1529,1530,1531,1532,1533,1534,1535,1536,1537,1538,1539,1540,1541,1542,1543,1544,1545,1546,1547,1548,1549,1550,1551,1552,1553,1554,1555,1556,1557,1558,1559,1560,1561,1562,1563,1564,1565],"MG":[1566,1567,1568,1569,1570,1571,1572,1573,1574,1575,1576,1577,1578,1579,1580,1581,1582,1583,1584,1585,1586,1587,1588,1589,1590,1591,1592,1593,1594,1595,1596,1597,1598,1599,1600,1601,1602,1603,1604,1605,1606,1607,1608,1609,1610,1611,1612,1613,1614,1615,1616,1617,1618,1619,1620,1621,1622,1623,1624,1625,1626,1627,1628,1629,1630,1631,1632,1633,1634,1635,1636,1637,1638,1639,1640,1641,1642,1643,1644,1645,1646,1647,1648,1649,1650,1651,1652,1653,1654,1655,1656,1657,1658,1659,1660,1661,1662,1663,1664,1665,1666,1667,1668,1669,1670,1671,1672,1673,1674,1675,1676,1677,1678,1679,1680,1681,1682,1683,1684,1685,1686,1687,1688,1689,1690,1691,1692,1693,1694,1695,1696,1697,1698,1699,1700,1701,1702,1703,1704,1705,1706,1707,1708,1709,1710,1711,1712,1713,1714,1715,1716,1717,1718,1719,1720,1721,1722,1723,1724,1725,1726,1727,1728,1729,1730,1731,1732,1733,1734,1735,1736,1737,1738,1739,1740,1741,1742,1743,1744,1745,1746,1747,1748,1749,1750,1751,1752,1753,1754,1755,1756,1757,1758,1759,1760,1761,1762,1763,1764,1765,1766,1767,1768,1769,1770,1771,1772,1773,1774,1775,1776,1777,1778,1779,1780,1781,1782,1783,1784,1785,1786,1787,1788,1789,1790,1791,1792,1793,1794,1795,1796,1797,1798,1799,1800,1801,1802,1803,1804,1805,1806,1807,1808,1809,1810,1811,1812,1813,1814,1815,1816,1817,1818,1819,1820,1821,1822,1823,1824,1825,1826,1827,1828,1829,1830,1831,1832,1833,1834,1835,1836,1837,1838,1839,1840,1841,1842,1843,1844,1845,1846,1847,1848,1849,1850,1851,1852,1853,1854,1855,1856,1857,1858,1859,1860,1861,1862,1863,1864,1865,1866,1867,1868,1869,1870,1871,1872,1873,1874,1875,1876,1877,1878,1879,1880,1881,1882,1883,1884,1885,1886,1887,1888,1889,1890,1891,1892,1893,1894,1895,1896,1897,1898,1899,1900,1901,1902,1903,1904,1905,1906,1907,1908,1909,1910,1911,1912,1913,1914,1915,1916,1917,1918,1919,1920,1921,1922,1923,1924,1925,1926,1927,1928,1929,1930,1931,1932,1933,1934,1935,1936,1937,1938,1939,1940,1941,1942,1943,1944,1945,1946,1947,1948,1949,1950,1951,1952,1953,1954,1955,1956,1957,1958,1959,1960,1961,1962,1963,1964,1965,1966,1967,1968,1969,1970,1971,1972,1973,1974,1975,1976,1977,1978,1979,1980,1981,1982,1983,1984,1985,1986,1987,1988,1989,1990,1991,1992,1993,1994,1995,1996,1997,1998,1999,2000,2001,2002,2003,2004,2005,2006,2007,2008,2009,2010,2011,2012,2013,2014,2015,2016,2017,2018,2019,2020,2021,2022,2023,2024,2025,2026,2027,2028,2029,2030,2031,2032,2033,2034,2035,2036,2037,2038,2039,2040,2041,2042,2043,2044,2045,2046,2047,2048,2049,2050,2051,2052,2053,2054,2055,2056,2057,2058,2059,2060,2061,2062,2063,2064,2065,2066,2067,2068,2069,2070,2071,2072,2073,2074,2075,2076,2077,2078,2079,2080,2081,2082,2083,2084,2085,2086,2087,2088,2089,2090,2091,2092,2093,2094,2095,2096,2097,2098,2099,2100,2101,2102,2103,2104,2105,2106,2107,2108,2109,2110,2111,2112,2113,2114,2115,2116,2117,2118,2119,2120,2121,2122,2123,2124,2125,2126,2127,2128,2129,2130,2131,2132,2133,2134,2135,2136,2137,2138,2139,2140,2141,2142,2143,2144,2145,2146,2147,2148,2149,2150,2151,2152,2153,2154,2155,2156,2157,2158,2159,2160,2161,2162,2163,2164,2165,2166,2167,2168,2169,2170,2171,2172,2173,2174,2175,2176,2177,2178,2179,2180,2181,2182,2183,2184,2185,2186,2187,2188,2189,2190,2191,2192,2193,2194,2195,2196,2197,2198,2199,2200,2201,2202,2203,2204,2205,2206,2207,2208,2209,2210,2211,2212,2213,2214,2215,2216,2217,2218,2219,2220,2221,2222,2223,2224,2225,2226,2227,2228,2229,2230,2231,2232,2233,2234,2235,2236,2237,2238,2239,2240,2241,2242,2243,2244,2245,2246,2247,2248,2249,2250,2251,2252,2253,2254,2255,2256,2257,2258,2259,2260,2261,2262,2263,2264,2265,2266,2267,2268,2269,2270,2271,2272,2273,2274,2275,2276,2277,2278,2279,2280,2281,2282,2283,2284,2285,2286,2287,2288,2289,2290,2291,2292,2293,2294,2295,2296,2297,2298,2299,2300,2301,2302,2303,2304,2305,2306,2307,2308,2309,2310,2311,2312,2313,2314,2315,2316,2317,2318,2319,2320,2321,2322,2323,2324,2325,2326,2327,2328,2329,2330,2331,2332,2333,2334,2335,2336,2337,2338,2339,2340,2341,2342,2343,2344,2345,2346,2347,2348,2349,2350,2351,2352,2353,2354,2355,2356,2357,2358,2359,2360,2361,2362,2363,2364,2365,2366,2367,2368,2369,2370,2371,2372,2373,2374,2375,2376,2377,2378,2379,2380,2381,2382,2383,2384,2385,2386,2387,2388,2389,2390,2391,2392,2393,2394,2395,2396,2397,2398,2399,2400,2401,2402,2403,2404,2405,2406,2407,2408,2409,2410,2411,2412,2413,2414,2415,2416,2417,2418],"PA":[2419,2420,2421,2422,2423,2424,2425,2426,2427,2428,2429,2430,2431,2432,2433,2434,2435,2436,2437,2438,2439,2440,2441,2442,2443,2444,2445,2446,2447,2448,2449,2450,2451,2452,2453,2454,2455,2456,2457,2458,2459,2460,2461,2462,2463,2464,2465,2466,2467,2468,2469,2470,2471,2472,2473,2474,2475,2476,2477,2478,2479,2480,2481,2482,2483,2484,2485,2486,2487,2488,2489,2490,2491,2492,2493,2494,2495,2496,2497,2498,2499,2500,2501,2502,2503,2504,2505,2506,2507,2508,2509,2510,2511,2512,2513,2514,2515,2516,2517,2518,2519,2520,2521,2522,2523,2524,2525,2526,2527,2528,2529,2530,2531,2532,2533,2534,2535,2536,2537,2538,2539,2540,2541,2542,2543,2544,2545,2546,2547,2548,2549,2550,2551,2552,2553,2554,2555,2556,2557,2558,2559,2560,2561,2562],"PB":[2563,2564,2565,2566,2567,2568,2569,2570,2571,2572,2573,2574,2575,2576,2577,2578,2579,2580,2581,2582,2583,2584,2585,2586,2587,2588,2589,2590,2591,2592,2593,2594,2595,2596,2597,2598,2599,2600,2601,2602,2603,2604,2605,2606,2607,2608,2609,2610,2611,2612,2613,2614,2615,2616,2617,2618,2619,2620,2621,2622,2623,2624,2625,2626,2627,2628,2629,2630,2631,2632,2633,2634,2635,2636,2637,2638,2639,2640,2641,2642,2643,2644,2645,2646,2647,2648,2649,2650,2651,2652,2653,2654,2655,2656,2657,2658,2659,2660,2661,2662,2663,2664,2665,2666,2667,2668,2669,2670,2671,2672,2673,2674,2675,2676,2677,2678,2679,2680,2681,2682,2683,2684,2685,2686,2687,2688,2689,2690,2691,2692,2693,2694,2695,2696,2697,2698,2699,2700,2701,2702,2703,2704,2705,2706,2707,2708,2709,2710,2711,2712,2713,2714,2715,2716,2717,2718,2719,2720,2721,2722,2723,2724,2725,2726,2727,2728,2729,2730,2731,2732,2733,2734,2735,2736,2737,2738,2739,2740,2741,2742,2743,2744,2745,2746,2747,2748,2749,2750,2751,2752,2753,2754,2755,2756,2757,2758,2759,2760,2761,2762,2763,2764,2765,2766,2767,2768,2769,2770,2771,2772,2773,2774,2775,2776,2777,2778,2779,2780,2781,2782,2783,2784,2785],"PR":[2786,2787,2788,2789,2790,2791,2792,2793,2794,2795,2796,2797,2798,2799,2800,2801,2802,2803,2804,2805,2806,2807,2808,2809,2810,2811,2812,2813,2814,2815,2816,2817,2818,2819,2820,2821,2822,2823,2824,2825,2826,2827,2828,2829,2830,2831,2832,2833,2834,2835,2836,2837,2838,2839,2840,2841,2842,2843,2844,2845,2846,2847,2848,2849,2850,2851,2852,2853,2854,2855,2856,2857,2858,2859,2860,2861,2862,2863,2864,2865,2866,2867,2868,2869,2870,2871,2872,2873,2874,2875,2876,2877,2878,2879,2880,2881,2882,2883,2884,2885,2886,2887,2888,2889,2890,2891,2892,2893,2894,2895,2896,2897,2898,2899,2900,2901,2902,2903,2904,2905,2906,2907,2908,2909,2910,2911,2912,2913,2914,2915,2916,2917,2918,2919,2920,2921,2922,2923,2924,2925,2926,2927,2928,2929,2930,2931,2932,2933,2934,2935,2936,2937,2938,2939,2940,2941,2942,2943,2944,2945,2946,2947,2948,2949,2950,2951,2952,2953,2954,2955,2956,2957,2958,2959,2960,2961,2962,2963,2964,2965,2966,2967,2968,2969,2970,2971,2972,2973,2974,2975,2976,2977,2978,2979,2980,2981,2982,2983,2984,2985,2986,2987,2988,2989,2990,2991,2992,2993,2994,2995,2996,2997,2998,2999,3000,3001,3002,3003,3004,3005,3006,3007,3008,3009,3010,3011,3012,3013,3014,3015,3016,3017,3018,3019,3020,3021,3022,3023,3024,3025,3026,3027,3028,3029,3030,3031,3032,3033,3034,3035,3036,3037,3038,3039,3040,3041,3042,3043,3044,3045,3046,3047,3048,3049,3050,3051,3052,3053,3054,3055,3056,3057,3058,3059,3060,3061,3062,3063,3064,3065,3066,3067,3068,3069,3070,3071,3072,3073,3074,3075,3076,3077,3078,3079,3080,3081,3082,3083,3084,3085,3086,3087,3088,3089,3090,3091,3092,3093,3094,3095,3096,3097,3098,3099,3100,3101,3102,3103,3104,3105,3106,3107,3108,3109,3110,3111,3112,3113,3114,3115,3116,3117,3118,3119,3120,3121,3122,3123,3124,3125,3126,3127,3128,3129,3130,3131,3132,3133,3134,3135,3136,3137,3138,3139,3140,3141,3142,3143,3144,3145,3146,3147,3148,3149,3150,3151,3152,3153,3154,3155,3156,3157,3158,3159,3160,3161,3162,3163,3164,3165,3166,3167,3168,3169,3170,3171,3172,3173,3174,3175,3176,3177,3178,3179,3180,3181,3182,3183,3184],"PE":[3185,3186,3187,3188,3189,3190,3191,3192,3193,3194,3195,3196,3197,3198,3199,3200,3201,3202,3203,3204,3205,3206,3207,3208,3209,3210,3211,3212,3213,3214,3215,3216,3217,3218,3219,3220,3221,3222,3223,3224,3225,3226,3227,3228,3229,3230,3231,3232,3233,3234,3235,3236,3237,3238,3239,3240,3241,3242,3243,3244,3245,3246,3247,3248,3249,3250,3251,3252,3253,3254,3255,3256,3257,3258,3259,3260,3261,3262,3263,3264,3265,3266,3267,3268,3269,3270,3271,3272,3273,3274,3275,3276,3277,3278,3279,3280,3281,3282,3283,3284,3285,3286,3287,3288,3289,3290,3291,3292,3293,3294,3295,3296,3297,3298,3299,3300,3301,3302,3303,3304,3305,3306,3307,3308,3309,3310,3311,3312,3313,3314,3315,3316,3317,3318,3319,3320,3321,3322,3323,3324,3325,3326,3327,3328,3329,3330,3331,3332,3333,3334,3335,3336,3337,3338,3339,3340,3341,3342,3343,3344,3345,3346,3347,3348,3349,3350,3351,3352,3353,3354,3355,3356,3357,3358,3359,3360,3361,3362,3363,3364,3365,3366,3367,3368,3369],"PI":[3370,3371,3372,3373,3374,3375,3376,3377,3378,3379,3380,3381,3382,3383,3384,3385,3386,3387,3388,3389,3390,3391,3392,3393,3394,3395,3396,3397,3398,3399,3400,3401,3402,3403,3404,3405,3406,3407,3408,3409,3410,3411,3412,3413,3414,3415,3416,3417,3418,3419,3420,3421,3422,3423,3424,3425,3426,3427,3428,3429,3430,3431,3432,3433,3434,3435,3436,3437,3438,3439,3440,3441,3442,3443,3444,3445,3446,3447,3448,3449,3450,3451,3452,3453,3454,3455,3456,3457,3458,3459,3460,3461,3462,3463,3464,3465,3466,3467,3468,3469,3470,3471,3472,3473,3474,3475,3476,3477,3478,3479,3480,3481,3482,3483,3484,3485,3486,3487,3488,3489,3490,3491,3492,3493,3494,3495,3496,3497,3498,3499,3500,3501,3502,3503,3504,3505,3506,3507,3508,3509,3510,3511,3512,3513,3514,3515,3516,3517,3518,3519,3520,3521,3522,3523,3524,3525,3526,3527,3528,3529,3530,3531,3532,3533,3534,3535,3536,3537,3538,3539,3540,3541,3542,3543,3544,3545,3546,3547,3548,3549,3550,3551,3552,3553,3554,3555,3556,3557,3558,3559,3560,3561,3562,3563,3564,3565,3566,3567,3568,3569,3570,3571,3572,3573,3574,3575,3576,3577,3578,3579,3580,3581,3582,3583,3584,3585,3586,3587,3588,3589,3590,3591,3592,3593],"RJ":[3594,3595,3596,3597,3598,3599,3600,3601,3602,3603,3604,3605,3606,3607,3608,3609,3610,3611,3612,3613,3614,3615,3616,3617,3618,3619,3620,3621,3622,3623,3624,3625,3626,3627,3628,3629,3630,3631,3632,3633,3634,3635,3636,3637,3638,3639,3640,3641,3642,3643,3644,3645,3646,3647,3648,3649,3650,3651,3652,3653,3654,3655,3656,3657,3658,3659,3660,3661,3662,3663,3664,3665,3666,3667,3668,3669,3670,3671,3672,3673,3674,3675,3676,3677,3678,3679,3680,3681,3682,3683,3684,3685],"RN":[3686,3687,3688,3689,3690,3691,3692,3693,3694,3695,3696,3697,3698,3699,3700,3701,3702,3703,3704,3705,3706,3707,3708,3709,3710,3711,3712,3713,3714,3715,3716,3717,3718,3719,3720,3721,3722,3723,3724,3725,3726,3727,3728,3729,3730,3731,3732,3733,3734,3735,3736,3737,3738,3739,3740,3741,3742,3743,3744,3745,3746,3747,3748,3749,3750,3751,3752,3753,3754,3755,3756,3757,3758,3759,3760,3761,3762,3763,3764,3765,3766,3767,3768,3769,3770,3771,3772,3773,3774,3775,3776,3777,3778,3779,3780,3781,3782,3783,3784,3785,3786,3787,3788,3789,3790,3791,3792,3793,3794,3795,3796,3797,3798,3799,3800,3801,3802,3803,3804,3805,3806,3807,3808,3809,3810,3811,3812,3813,3814,3815,3816,3817,3818,3819,3820,3821,3822,3823,3824,3825,3826,3827,3828,3829,3830,3831,3832,3833,3834,3835,3836,3837,3838,3839,3840,3841,3842,3843,3844,3845,3846,3847,3848,3849,3850,3851,3852],"RS":[3853,3854,3855,3856,3857,3858,3859,3860,3861,3862,3863,3864,3865,3866,3867,3868,3869,3870,3871,3872,3873,3874,3875,3876,3877,3878,3879,3880,3881,3882,3883,3884,3885,3886,3887,3888,3889,3890,3891,3892,3893,3894,3895,3896,3897,3898,3899,3900,3901,3902,3903,3904,3905,3906,3907,3908,3909,3910,3911,3912,3913,3914,3915,3916,3917,3918,3919,3920,3921,3922,3923,3924,3925,3926,3927,3928,3929,3930,3931,3932,3933,3934,3935,3936,3937,3938,3939,3940,3941,3942,3943,3944,3945,3946,3947,3948,3949,3950,3951,3952,3953,3954,3955,3956,3957,3958,3959,3960,3961,3962,3963,3964,3965,3966,3967,3968,3969,3970,3971,3972,3973,3974,3975,3976,3977,3978,3979,3980,3981,3982,3983,3984,3985,3986,3987,3988,3989,3990,3991,3992,3993,3994,3995,3996,3997,3998,3999,4000,4001,4002,4003,4004,4005,4006,4007,4008,4009,4010,4011,4012,4013,4014,4015,4016,4017,4018,4019,4020,4021,4022,4023,4024,4025,4026,4027,4028,4029,4030,4031,4032,4033,4034,4035,4036,4037,4038,4039,4040,4041,4042,4043,4044,4045,4046,4047,4048,4049,4050,4051,4052,4053,4054,4055,4056,4057,4058,4059,4060,4061,4062,4063,4064,4065,4066,4067,4068,4069,4070,4071,4072,4073,4074,4075,4076,4077,4078,4079,4080,4081,4082,4083,4084,4085,4086,4087,4088,4089,4090,4091,4092,4093,4094,4095,4096,4097,4098,4099,4100,4101,4102,4103,4104,4105,4106,4107,4108,4109,4110,4111,4112,4113,4114,4115,4116,4117,4118,4119,4120,4121,4122,4123,4124,4125,4126,4127,4128,4129,4130,4131,4132,4133,4134,4135,4136,4137,4138,4139,4140,4141,4142,4143,4144,4145,4146,4147,4148,4149,4150,4151,4152,4153,4154,4155,4156,4157,4158,4159,4160,4161,4162,4163,4164,4165,4166,4167,4168,4169,4170,4171,4172,4173,4174,4175,4176,4177,4178,4179,4180,4181,4182,4183,4184,4185,4186,4187,4188,4189,4190,4191,4192,4193,4194,4195,4196,4197,4198,4199,4200,4201,4202,4203,4204,4205,4206,4207,4208,4209,4210,4211,4212,4213,4214,4215,4216,4217,4218,4219,4220,4221,4222,4223,4224,4225,4226,4227,4228,4229,4230,4231,4232,4233,4234,4235,4236,4237,4238,4239,4240,4241,4242,4243,4244,4245,4246,4247,4248,4249,4250,4251,4252,4253,4254,4255,4256,4257,4258,4259,4260,4261,4262,4263,4264,4265,4266,4267,4268,4269,4270,4271,4272,4273,4274,4275,4276,4277,4278,4279,4280,4281,4282,4283,4284,4285,4286,4287,4288,4289,4290,4291,4292,4293,4294,4295,4296,4297,4298,4299,4300,4301,4302,4303,4304,4305,4306,4307,4308,4309,4310,4311,4312,4313,4314,4315,4316,4317,4318,4319,4320,4321,4322,4323,4324,4325,4326,4327,4328,4329,4330,4331,4332,4333,4334,4335,4336,4337,4338,4339,4340,4341,4342,4343,4344,4345,4346,4347,4348,4349],"RO":[4350,4351,4352,4353,4354,4355,4356,4357,4358,4359,4360,4361,4362,4363,4364,4365,4366,4367,4368,4369,4370,4371,4372,4373,4374,4375,4376,4377,4378,4379,4380,4381,4382,4383,4384,4385,4386,4387,4388,4389,4390,4391,4392,4393,4394,4395,4396,4397,4398,4399,4400,4401],"RR":[4402,4403,4404,4405,4406,4407,4408,4409,4410,4411,4412,4413,4414,4415,4416],"SC":[4417,4418,4419,4420,4421,4422,4423,4424,4425,4426,4427,4428,4429,4430,4431,4432,4433,4434,4435,4436,4437,4438,4439,4440,4441,4442,4443,4444,4445,4446,4447,4448,4449,4450,4451,4452,4453,4454,4455,4456,4457,4458,4459,4460,4461,4462,4463,4464,4465,4466,4467,4468,4469,4470,4471,4472,4473,4474,4475,4476,4477,4478,4479,4480,4481,4482,4483,4484,4485,4486,4487,4488,4489,4490,4491,4492,4493,4494,4495,4496,4497,4498,4499,4500,4501,4502,4503,4504,4505,4506,4507,4508,4509,4510,4511,4512,4513,4514,4515,4516,4517,4518,4519,4520,4521,4522,4523,4524,4525,4526,4527,4528,4529,4530,4531,4532,4533,4534,4535,4536,4537,4538,4539,4540,4541,4542,4543,4544,4545,4546,4547,4548,4549,4550,4551,4552,4553,4554,4555,4556,4557,4558,4559,4560,4561,4562,4563,4564,4565,4566,4567,4568,4569,4570,4571,4572,4573,4574,4575,4576,4577,4578,4579,4580,4581,4582,4583,4584,4585,4586,4587,4588,4589,4590,4591,4592,4593,4594,4595,4596,4597,4598,4599,4600,4601,4602,4603,4604,4605,4606,4607,4608,4609,4610,4611,4612,4613,4614,4615,4616,4617,4618,4619,4620,4621,4622,4623,4624,4625,4626,4627,4628,4629,4630,4631,4632,4633,4634,4635,4636,4637,4638,4639,4640,4641,4642,4643,4644,4645,4646,4647,4648,4649,4650,4651,4652,4653,4654,4655,4656,4657,4658,4659,4660,4661,4662,4663,4664,4665,4666,4667,4668,4669,4670,4671,4672,4673,4674,4675,4676,4677,4678,4679,4680,4681,4682,4683,4684,4685,4686,4687,4688,4689,4690,4691,4692,4693,4694,4695,4696,4697,4698,4699,4700,4701,4702,4703,4704,4705,4706,4707,4708,4709,4710,4711],"SP":[4712,4713,4714,4715,4716,4717,4718,4719,4720,4721,4722,4723,4724,4725,4726,4727,4728,4729,4730,4731,4732,4733,4734,4735,4736,4737,4738,4739,4740,4741,4742,4743,4744,4745,4746,4747,4748,4749,4750,4751,4752,4753,4754,4755,4756,4757,4758,4759,4760,4761,4762,4763,4764,4765,4766,4767,4768,4769,4770,4771,4772,4773,4774,4775,4776,4777,4778,4779,4780,4781,4782,4783,4784,4785,4786,4787,4788,4789,4790,4791,4792,4793,4794,4795,4796,4797,4798,4799,4800,4801,4802,4803,4804,4805,4806,4807,4808,4809,4810,4811,4812,4813,4814,4815,4816,4817,4818,4819,4820,4821,4822,4823,4824,4825,4826,4827,4828,4829,4830,4831,4832,4833,4834,4835,4836,4837,4838,4839,4840,4841,4842,4843,4844,4845,4846,4847,4848,4849,4850,4851,4852,4853,4854,4855,4856,4857,4858,4859,4860,4861,4862,4863,4864,4865,4866,4867,4868,4869,4870,4871,4872,4873,4874,4875,4876,4877,4878,4879,4880,4881,4882,4883,4884,4885,4886,4887,4888,4889,4890,4891,4892,4893,4894,4895,4896,4897,4898,4899,4900,4901,4902,4903,4904,4905,4906,4907,4908,4909,4910,4911,4912,4913,4914,4915,4916,4917,4918,4919,4920,4921,4922,4923,4924,4925,4926,4927,4928,4929,4930,4931,4932,4933,4934,4935,4936,4937,4938,4939,4940,4941,4942,4943,4944,4945,4946,4947,4948,4949,4950,4951,4952,4953,4954,4955,4956,4957,4958,4959,4960,4961,4962,4963,4964,4965,4966,4967,4968,4969,4970,4971,4972,4973,4974,4975,4976,4977,4978,4979,4980,4981,4982,4983,4984,4985,4986,4987,4988,4989,4990,4991,4992,4993,4994,4995,4996,4997,4998,4999,5000,5001,5002,5003,5004,5005,5006,5007,5008,5009,5010,5011,5012,5013,5014,5015,5016,5017,5018,5019,5020,5021,5022,5023,5024,5025,5026,5027,5028,5029,5030,5031,5032,5033,5034,5035,5036,5037,5038,5039,5040,5041,5042,5043,5044,5045,5046,5047,5048,5049,5050,5051,5052,5053,5054,5055,5056,5057,5058,5059,5060,5061,5062,5063,5064,5065,5066,5067,5068,5069,5070,5071,5072,5073,5074,5075,5076,5077,5078,5079,5080,5081,5082,5083,5084,5085,5086,5087,5088,5089,5090,5091,5092,5093,5094,5095,5096,5097,5098,5099,5100,5101,5102,5103,5104,5105,5106,5107,5108,5109,5110,5111,5112,5113,5114,5115,5116,5117,5118,5119,5120,5121,5122,5123,5124,5125,5126,5127,5128,5129,5130,5131,5132,5133,5134,5135,5136,5137,5138,5139,5140,5141,5142,5143,5144,5145,5146,5147,5148,5149,5150,5151,5152,5153,5154,5155,5156,5157,5158,5159,5160,5161,5162,5163,5164,5165,5166,5167,5168,5169,5170,5171,5172,5173,5174,5175,5176,5177,5178,5179,5180,5181,5182,5183,5184,5185,5186,5187,5188,5189,5190,5191,5192,5193,5194,5195,5196,5197,5198,5199,5200,5201,5202,5203,5204,5205,5206,5207,5208,5209,5210,5211,5212,5213,5214,5215,5216,5217,5218,5219,5220,5221,5222,5223,5224,5225,5226,5227,5228,5229,5230,5231,5232,5233,5234,5235,5236,5237,5238,5239,5240,5241,5242,5243,5244,5245,5246,5247,5248,5249,5250,5251,5252,5253,5254,5255,5256,5257,5258,5259,5260,5261,5262,5263,5264,5265,5266,5267,5268,5269,5270,5271,5272,5273,5274,5275,5276,5277,5278,5279,5280,5281,5282,5283,5284,5285,5286,5287,5288,5289,5290,5291,5292,5293,5294,5295,5296,5297,5298,5299,5300,5301,5302,5303,5304,5305,5306,5307,5308,5309,5310,5311,5312,5313,5314,5315,5316,5317,5318,5319,5320,5321,5322,5323,5324,5325,5326,5327,5328,5329,5330,5331,5332,5333,5334,5335,5336,5337,5338,5339,5340,5341,5342,5343,5344,5345,5346,5347,5348,5349,5350,5351,5352,5353,5354,5355,5356],"SE":[5357,5358,5359,5360,5361,5362,5363,5364,5365,5366,5367,5368,5369,5370,5371,5372,5373,5374,5375,5376,5377,5378,5379,5380,5381,5382,5383,5384,5385,5386,5387,5388,5389,5390,5391,5392,5393,5394,5395,5396,5397,5398,5399,5400,5401,5402,5403,5404,5405,5406,5407,5408,5409,5410,5411,5412,5413,5414,5415,5416,5417,5418,5419,5420,5421,5422,5423,5424,5425,5426,5427,5428,5429,5430,5431],"TO":[5432,5433,5434,5435,5436,5437,5438,5439,5440,5441,5442,5443,5444,5445,5446,5447,5448,5449,5450,5451,5452,5453,5454,5455,5456,5457,5458,5459,5460,5461,5462,5463,5464,5465,5466,5467,5468,5469,5470,5471,5472,5473,5474,5475,5476,5477,5478,5479,5480,5481,5482,5483,5484,5485,5486,5487,5488,5489,5490,5491,5492,5493,5494,5495,5496,5497,5498,5499,5500,5501,5502,5503,5504,5505,5506,5507,5508,5509,5510,5511,5512,5513,5514,5515,5516,5517,5518,5519,5520,5521,5522,5523,5524,5525,5526,5527,5528,5529,5530,5531,5532,5533,5534,5535,5536,5537,5538,5539,5540,5541,5542,5543,5544,5545,5546,5547,5548,5549,5550,5551,5552,5553,5554,5555,5556,5557,5558,5559,5560,5561,5562,5563,5564,5565,5566,5567,5568,5569,5570]},"fullOrder":[882,1566,883,1567,2419,619,202,203,2786,4417,2420,4418,1568,3185,5432,1569,1128,204,2421,620,621,3686,3370,3853,622,1345,0,884,1570,4712,885,4713,2787,205,3186,3687,804,1129,3187,2422,3188,3371,4419,4420,2423,1346,1571,22,2563,3372,1487,1572,4421,1130,805,206,886,887,3688,3189,3854,4714,1573,3190,4715,4422,4716,4717,4718,1574,4423,888,4424,1575,3855,4719,2788,806,2564,5433,1576,207,623,1577,3856,1578,2565,2566,2567,3191,3373,208,4720,1579,1131,624,2568,1488,209,1132,3857,807,3858,3374,3859,1580,2424,3689,889,1581,808,4721,1582,4425,2569,2570,3192,5434,210,5435,2425,1583,3690,2789,3860,890,1584,3861,1585,1347,4350,4722,2426,1133,2790,625,1586,3193,4723,3862,4402,4724,1134,1135,4351,1348,4426,1349,1587,3691,3863,1350,891,1588,3375,1351,2791,4352,892,2792,1136,2793,1589,809,626,1352,2794,3376,4725,140,1590,4726,4727,4728,4729,1591,3864,5436,4353,1592,3377,893,2795,4403,1489,124,1137,2796,3194,3865,894,3378,1138,211,141,212,213,4730,895,4731,4732,3866,627,896,2571,4733,5357,1593,2797,23,214,2798,2427,1139,4734,142,5437,2428,897,2429,1140,1490,1491,810,4427,215,2799,216,1594,4735,3867,1595,4736,1596,1492,3195,4428,217,3379,5438,3692,3594,218,2800,898,4737,4738,899,3380,4429,4430,143,3868,219,2801,628,3381,220,1597,4431,1598,221,1493,3693,2802,3869,1599,2572,4739,4740,900,901,5439,1494,3595,811,1353,4741,1141,4432,3694,222,902,223,2803,144,629,5358,1495,630,4433,2573,1600,5359,4742,224,631,225,4743,226,1601,632,3196,4744,812,903,1602,904,905,5440,5441,5442,1354,5443,1355,1142,5444,906,1603,5445,1143,1496,227,3870,1144,4745,4746,1604,4747,24,5446,1605,2804,1606,2805,1607,2806,1356,4434,2574,4435,4748,4749,633,1145,3871,634,3197,3596,2575,2807,228,3872,635,229,5360,2808,1608,1609,1610,4750,1611,3198,1612,3597,4751,2576,3695,5361,2577,2578,4752,4753,1357,907,3696,1613,1614,1615,1358,4354,4754,2809,3598,4436,636,3382,2579,3383,3384,3599,5447,3873,3874,3875,3876,3877,3878,4437,4755,908,4756,4438,3879,4439,4757,2810,637,4758,1,2811,3697,2580,3385,1616,2812,25,2813,145,4440,1617,4759,813,5448,2430,1618,3880,3881,230,4760,909,638,4441,2431,5449,146,4761,4762,4763,2432,3386,910,1146,5450,5451,1147,1148,1149,1150,4764,1619,3882,2433,2581,3698,231,2434,232,3387,639,814,4765,1620,911,4442,4443,4444,4445,4446,3883,4447,2814,4766,1151,1621,640,4767,2582,1622,1623,4448,1497,2815,5452,2435,233,3884,4768,1624,3885,1152,1359,1625,3886,2583,3699,1626,641,4769,2816,2436,3700,147,4770,234,4449,4771,3388,235,3199,2584,2585,26,815,27,2586,1360,4772,236,1153,1361,3887,2817,237,5453,3600,3888,3889,3890,238,4773,5362,3891,1627,3601,4450,2818,3892,3389,642,239,3390,148,1154,3200,4774,4775,643,240,912,3391,241,242,5454,644,3893,1628,4776,4777,1498,28,3392,4778,1499,645,4779,2587,4780,646,647,1500,2819,913,1629,1155,2820,3393,4451,1156,29,2437,2588,3201,2589,3394,3202,3602,1630,243,4452,244,1631,3203,30,1632,1633,2438,3395,1157,4453,2439,149,3894,4781,3701,3895,1158,1634,1635,2590,4782,1159,5455,4783,3396,1636,150,3204,3397,1637,3205,1638,1639,4454,4784,1640,4785,4786,245,2821,4455,816,1641,2822,2823,1362,4787,3398,246,2591,2824,648,2592,4404,2825,3896,3897,3898,1160,3899,151,3900,247,31,152,3399,4788,1642,4456,1643,2826,3702,3206,1501,4789,4790,3207,1644,1161,3208,3603,4457,914,1645,2593,3400,3703,3901,4458,248,1646,249,1162,915,1647,1363,1648,3604,817,4459,2827,2440,5456,4791,1163,3902,3401,3903,1649,4460,3904,1650,2594,2828,4792,2829,4461,1651,4405,3402,916,1652,250,251,1502,2441,3209,1653,2595,917,2596,3905,3403,5363,252,4793,4794,153,2597,4795,1654,4796,2830,3906,1655,4797,1656,253,4462,3907,4463,4464,3908,2442,4798,2831,32,1657,2443,1503,1658,2832,5457,2,3404,803,1659,1364,4799,1660,918,1661,3210,818,3211,3704,5458,1164,4800,3212,1165,2598,3405,2599,5364,2444,649,254,255,2445,2446,919,3909,4801,4802,256,1662,257,4465,4466,1663,1664,3213,258,1665,3214,3,2447,4803,4804,1166,920,1167,921,5459,3406,3407,1168,922,259,1169,1666,4355,4805,1667,3910,154,2600,1504,260,2601,261,1668,923,3408,2602,4356,3215,3605,1669,4806,4807,3216,4467,4808,3911,4357,3912,1365,262,924,1670,925,1671,1672,2448,2449,3913,2603,926,1673,1170,4809,3606,3217,3914,5460,819,2604,2605,2606,33,3915,4358,4810,927,263,264,1674,265,1675,3218,266,267,2833,2834,4811,2835,4812,1676,928,3916,4468,2607,3917,3705,3706,3707,4813,268,4814,4815,1171,1172,4816,2608,3409,2609,4817,34,3410,1677,4818,3219,125,1678,2610,929,930,269,3411,2836,4469,3220,270,271,1679,2611,272,1680,1505,3918,3221,3919,2837,3920,2838,2839,4470,3607,1681,1682,2450,650,3222,1683,1684,35,1685,3921,931,1173,2840,3922,4819,2841,2612,2842,1686,932,1366,4820,3412,3923,933,36,4471,934,273,3413,1687,1688,4472,3924,2843,5365,1689,2844,4473,1690,274,37,1506,3708,3414,2845,3415,935,4821,2846,3416,2847,3925,4359,1367,3709,1368,1691,936,3926,1369,4822,3608,1692,5461,4474,4823,651,937,3223,1693,1694,2451,1370,4824,38,275,1695,276,1371,4825,3417,277,278,279,1696,4360,3927,280,2848,3928,1174,4826,4827,281,3929,2849,3930,4475,3710,3931,5366,3224,652,5367,4828,3932,4476,282,4406,1697,2850,3609,1175,3418,283,3933,155,2452,2851,4477,4829,3934,3935,3936,3937,1698,39,5368,3938,4830,284,1699,1700,1701,2613,1702,285,1703,4478,1176,653,3939,1704,3419,1705,3420,2852,2453,1706,4831,4479,3940,4,3225,1707,3941,4407,1507,3421,4832,1708,286,2853,1709,1710,1711,3610,4833,1712,156,2614,3711,3422,287,3942,1713,288,4834,3611,1714,157,158,820,654,3423,289,5369,655,5462,656,657,1372,2854,3943,1715,3944,1716,3612,1717,1718,1719,1720,1721,1722,938,5463,5370,1723,3226,3712,3713,658,3227,1724,40,4408,1177,3228,1725,2615,5464,3229,1178,1726,1727,4835,1728,290,3945,1729,659,2855,5465,3946,3613,3230,2616,1730,4836,1508,2454,1373,4361,939,821,3424,4837,2856,291,1731,940,4838,2857,4480,660,1732,1733,3231,4839,2617,292,2618,293,3947,1734,661,941,294,2619,1735,662,942,1736,4481,1179,3948,3425,3714,1180,4840,663,3232,5371,1737,4482,3949,5466,2858,295,1738,1181,1739,1182,1183,4362,943,4841,4842,3950,2859,3951,3715,3952,3953,3954,4483,4843,2860,944,3233,3234,41,1740,1741,3955,5467,5468,1742,1374,1743,945,4484,1509,1184,4485,4844,3956,3957,664,4845,2455,1744,3958,2861,665,666,296,3959,4363,3960,2862,297,2863,946,1185,3961,298,1745,3962,1746,1747,1375,1748,4846,2864,299,159,3426,3427,4486,3428,1376,947,300,160,1186,1187,1749,42,3429,2456,822,1377,4847,1188,3963,948,5469,5470,1378,4848,2865,3430,3431,43,2866,3964,4364,1750,5471,1751,3614,1752,1379,2620,1753,823,1754,301,1755,1756,1757,3615,302,2457,3432,824,303,304,1189,1758,1759,1760,5472,1761,4849,4850,4487,2458,2621,3235,305,2622,306,3965,1762,1763,1380,2623,1764,1765,1766,2867,1767,1381,1768,2868,1769,1770,3966,1771,2869,307,1772,3967,44,3968,1773,308,2870,3616,4851,309,4488,1774,1775,667,2624,1510,310,1776,2871,1777,4852,1190,1778,3969,3970,2872,3716,1779,4489,3717,311,3433,4853,4490,1780,1781,3971,1511,2873,1782,1783,1784,949,1785,1786,4491,3434,3236,312,3237,1512,950,951,4854,2874,4365,4492,45,4855,4856,4366,1513,313,4857,3972,1382,1787,5473,3973,1514,2625,46,668,669,4858,314,4493,1788,315,3974,1789,4859,3975,3976,5474,3435,1790,952,1791,953,1792,5372,3436,316,954,5475,670,955,1793,671,3977,317,2626,2875,4860,3978,4861,1794,2876,2877,5,2878,3979,3718,1795,2879,4862,2627,1383,2628,2629,2630,4367,956,3238,2459,5373,4863,4494,4495,1796,3239,318,3437,2460,2880,4496,2881,3438,3719,2631,1797,3439,2632,2461,3440,2462,2463,1191,1384,1798,3240,126,957,2633,958,5476,319,1799,3980,959,1192,1800,1801,47,1802,3441,1385,1515,672,3981,4864,4497,1803,2634,1804,1805,3982,4865,2635,2882,2883,2884,1806,1386,5477,320,3983,1807,1808,4498,960,4866,3442,5374,1809,1810,1811,825,4867,1812,1813,961,5478,1814,1815,1816,4868,4869,3984,3985,1516,5479,3986,48,2885,4870,1387,321,1817,1818,2464,3443,3987,3444,1819,322,3988,1193,3989,1820,1821,826,3445,4499,1822,3990,2636,1823,1824,1825,827,1826,1827,3241,1517,2886,4871,1828,1518,2887,3991,4500,3992,3720,2888,962,4872,4873,3617,2637,5480,4874,1194,3618,1829,4875,828,963,964,161,1519,4876,2465,3993,3446,4877,3447,4878,323,1830,2638,4879,4880,4881,4882,3994,3721,324,3995,2889,2890,1831,4883,1832,3619,3996,1833,325,4501,1834,2891,3997,3998,162,6,3722,3999,4000,673,326,4502,4001,4002,4003,4503,1835,3242,4004,1836,1837,2639,4005,2892,3448,5481,1195,2893,4368,1838,3723,1839,4884,4885,327,4006,4007,5375,4008,4009,1840,4886,1196,4010,4887,1841,49,1842,965,4888,1843,4011,328,4889,4012,1844,329,674,1845,1846,3724,3243,2640,4013,966,1847,1848,675,2466,2894,4014,4890,3449,330,5482,1520,2895,4015,4504,4016,967,2896,4017,7,331,332,50,3244,5376,1197,1849,3725,1850,1851,4018,51,1388,2897,2898,1852,3245,1198,3726,4891,4892,4893,4894,127,3246,1853,1854,2899,1521,5483,1389,333,5484,334,968,52,2900,4505,4895,2901,3727,4896,3247,4019,969,3450,2902,3248,335,2467,3451,1855,2903,3452,4020,4506,2904,4897,4898,163,4021,1856,4022,970,1199,2905,336,4507,971,1857,5485,4023,676,4508,677,1858,1200,4024,678,1201,1859,2906,2907,4509,4899,3453,2908,3454,1860,2909,3728,1861,3455,4900,1862,3456,1863,4901,679,4025,1864,1865,1866,2641,3249,5377,4510,1867,1868,3457,1869,1870,3729,829,1871,4902,2642,4903,1872,3730,4511,3250,972,1873,337,3251,5378,4904,4026,4512,2468,4027,4513,4514,4905,1390,4028,338,4906,3458,4029,1391,2910,5379,4907,680,4030,339,4908,4031,3459,53,4032,1874,4909,340,1392,1522,3252,4033,1202,2911,1875,3253,1876,973,974,975,2469,976,3731,977,5486,978,5487,979,2912,2913,1877,1203,341,1878,1879,980,1204,4515,3732,1205,1206,4369,830,1207,342,1208,1209,1880,681,1210,5380,1211,4034,4035,4036,2914,3254,682,683,1881,4516,3255,4037,4517,684,3733,1882,4038,4518,831,3460,4039,4910,4911,2915,4912,2916,685,164,4370,343,3734,2917,344,1883,1884,4913,4914,3620,2918,981,4040,2919,4915,2643,4916,2920,4917,1885,4519,686,1886,5488,982,687,4520,1887,1888,4918,4041,983,2921,4919,1393,832,2922,2923,1889,4920,4921,345,4922,2924,1890,4923,4924,3461,984,4925,4521,4926,4522,4927,1891,1523,1892,1212,1893,1394,1894,1895,2644,2645,2470,5489,4928,4042,985,1896,346,4929,4043,4523,4044,688,986,987,4930,2925,689,4045,4931,3462,4046,165,4047,1213,4932,988,4933,347,1897,4934,3256,2926,4048,690,4935,54,833,2927,1898,1899,4049,1900,4524,691,2646,348,349,4525,350,351,692,3257,352,353,2928,354,4936,1901,1902,834,4050,3258,4526,355,356,4051,4937,357,1903,4052,358,4938,835,359,1904,1905,4939,360,693,4527,1906,2929,1214,4940,361,694,836,3735,4941,55,362,4942,2647,4943,1907,1215,1216,2471,2472,3259,4944,1908,363,56,4053,3621,364,4945,2930,3260,1909,1524,695,2931,1910,4054,4946,5381,3261,3463,4947,4948,365,4528,1911,4055,2648,4529,2932,4056,1912,4530,2933,4531,4057,1217,2934,989,2935,3262,1913,1914,4532,4949,696,4058,4950,1915,2936,4951,990,5382,1395,2649,1916,3263,4059,366,2473,57,1917,1918,3464,991,1919,1525,4952,4533,1920,992,1921,3736,697,1922,698,4953,4060,367,4954,4955,1923,368,4956,4534,369,2937,993,1396,3465,4061,166,2474,3264,994,2938,4535,4957,699,4958,4536,3265,3737,700,5490,1924,4537,370,701,4409,2939,4959,4538,4062,1925,371,372,167,4539,4960,4961,373,374,2940,4540,702,375,2941,4541,2475,837,3466,995,4542,4063,2650,5383,5384,376,4962,377,996,5385,1926,1927,1928,3622,378,5491,1929,1930,379,168,3266,4064,380,381,382,383,838,384,3623,2942,1931,997,998,5492,4963,3267,703,3467,4543,1218,1932,2943,704,2476,999,3738,4544,4964,4965,385,1933,386,3624,387,1934,169,1935,388,1936,2944,389,2945,3268,1937,1938,1939,390,4966,1940,1397,391,1941,1942,4967,3625,1000,1943,705,392,393,394,1944,4968,1219,2946,4545,839,2947,3626,3269,395,4969,1945,4970,4971,396,706,4972,170,4546,1001,4973,5493,3270,397,707,4547,4974,1526,5494,2651,4975,5386,2652,4371,4065,4976,4977,1002,4978,398,4066,1527,3271,840,399,4979,708,4980,1003,4067,3627,1946,4981,4068,400,4982,709,2653,3739,1947,1398,128,1004,3468,1948,2948,1949,1950,1220,1399,4983,4984,401,402,4985,403,4986,404,405,1951,1952,1005,1953,4987,2477,4548,1954,1955,4988,406,841,2949,2950,2951,2952,1528,1006,4069,4070,3272,4549,407,4989,2953,4071,4990,1956,3740,408,2654,58,2478,4991,2954,4992,1400,1957,4550,409,3469,1958,59,4072,2479,4993,1959,4073,2955,410,1960,4074,411,842,710,4075,2956,711,712,412,4994,713,4551,1961,3470,4995,4996,1962,1963,1007,2957,413,3741,4997,3742,1401,2958,1964,3743,1965,60,5387,3628,3744,2959,5388,1966,1529,171,2960,3273,4076,1008,4552,1530,61,714,1531,2961,3745,3746,3471,3747,2962,4553,4998,4077,4999,4372,1009,2963,3274,1532,715,1221,3275,3472,5000,5495,1010,1402,1967,1968,1222,1969,62,414,1970,1971,1972,415,2655,5001,843,3473,1973,2964,1011,4373,716,416,417,4554,1974,1975,5002,3276,3748,3474,3749,418,1223,1976,844,2656,1977,5003,1978,63,3277,3475,2965,2657,3476,4078,4555,1979,8,4556,5004,3750,3477,1980,1981,1224,1982,1012,1403,2658,5496,1983,2659,419,717,3478,718,3278,420,3751,1404,1984,3479,4079,5005,5006,1225,2660,64,3752,5007,2966,65,5008,3279,4557,5009,5010,1985,2967,3280,3480,2661,2662,172,1986,1405,2480,1406,421,1013,2968,422,423,173,1533,1987,2969,174,4558,1988,1534,424,1989,5389,4559,1226,1227,1228,1229,2663,3481,4080,3753,66,5497,1990,2664,3281,3754,3482,3755,3483,3282,1230,3283,3484,3485,5498,3284,1991,4081,1992,1993,1994,3285,1231,3756,425,3757,1014,1995,2665,4082,4083,5011,3486,4560,1535,426,3629,4084,5499,4085,4561,1232,427,428,3286,429,3758,3759,1996,430,1997,1407,1998,3487,2970,431,845,1999,2971,129,5012,5390,2972,2000,2666,4562,432,4563,5500,5013,2001,719,4086,5014,2002,4564,5015,2003,433,5016,4565,2004,1015,2973,4087,2005,434,2974,1233,2006,5017,2007,3287,67,2481,720,2975,5018,4566,4088,4089,846,5019,2667,435,5501,2976,2977,2668,2978,2008,4567,5020,1234,5021,5022,1408,5023,2669,5024,1409,3760,5025,3488,1235,436,3761,2009,2010,4568,2979,5026,2011,2980,5027,2981,5028,2012,4569,1016,3489,5502,3630,3762,437,4090,5391,130,3288,438,5029,3763,5030,439,5031,68,2013,4091,4374,2014,3289,4570,3631,440,721,3490,441,2015,2670,2482,442,4571,2483,1236,5032,3632,443,444,5033,5034,1017,4572,69,3764,4573,2016,445,446,5392,5393,2982,2671,2672,1018,2983,2017,4092,175,2673,176,3290,177,9,2984,2985,2986,5035,2987,2018,3633,2988,2019,2020,178,3491,2989,10,4093,447,448,2021,847,4094,2022,70,1019,179,2484,5036,1237,5037,4574,1536,2485,722,449,71,450,3291,1238,723,1239,2486,5038,4095,848,4096,451,72,4575,2023,2674,1410,4097,3765,452,724,3492,3493,2990,73,849,11,4576,2675,2024,2991,2992,2025,4098,4099,5503,5039,74,3634,2026,850,2993,2994,5040,2995,2996,5041,2027,2997,2998,2028,2487,2676,2029,2999,2030,4100,3000,2031,725,5042,3766,2032,5394,3001,1020,453,726,3494,2677,4577,4101,454,75,1240,2033,5043,2678,5504,3002,2034,2035,2036,2037,2038,3495,455,1241,2679,3003,2039,4102,2680,4103,4104,3004,2040,1242,1243,4578,2041,1021,76,1411,2681,2042,5044,3005,180,1022,5505,727,3767,4105,131,2043,456,3006,2488,2044,4579,2489,3635,2045,5045,3007,2046,5046,728,5047,2047,3636,77,3768,3496,457,3497,3637,5048,458,729,1244,730,3498,1023,851,1024,78,4106,2048,2049,1025,5049,4375,5050,2050,5051,3638,5506,1245,3008,2051,4107,2052,731,1537,1246,3292,5052,459,5507,460,4376,5053,3009,5054,1412,5055,2053,4580,1247,3010,732,2490,5056,4581,2054,2055,2682,5057,5058,5059,1026,5395,2491,2492,733,5060,1248,5061,4582,5062,2056,3499,3500,2057,734,2683,2058,852,3769,4108,2493,3770,1027,2059,5396,3501,5063,4109,5064,5065,2060,5066,2061,4110,4583,2062,4584,5067,3771,5508,2063,2684,5068,4377,461,2064,5509,2065,2685,5069,79,4111,1249,2066,1028,2067,1029,1030,735,2068,736,3293,3011,3294,4112,462,3012,737,1031,4113,5070,1032,3502,4585,2069,463,3503,2070,4586,4114,4115,1250,464,5071,1033,3772,4116,5072,1034,2494,4410,738,465,4117,466,853,4118,4119,739,2686,467,468,1035,1538,2071,3013,469,854,470,855,2072,5397,80,3504,5510,471,5073,472,2073,1036,2074,2075,5074,2076,4120,2077,5075,3773,2078,2079,3639,5511,5076,2687,4587,1539,473,5512,3295,3505,5077,2080,2688,3506,1037,5398,2081,1038,5078,181,5079,4121,474,3640,1251,2082,1540,5080,1039,3774,3641,1413,4122,475,4411,1414,5399,5400,5401,3014,5402,3507,1415,5403,3508,5081,3015,4123,1541,1040,3016,1542,4124,1041,3017,1416,4125,2083,4126,1417,4378,4127,5082,476,1418,5083,4128,3018,5084,1252,1042,3775,2084,4588,3019,2495,3020,4129,5085,477,3021,2689,3642,1043,5086,1419,5087,4130,478,3643,1044,5088,1253,2496,4589,479,1420,3022,2085,3023,5089,4379,1421,1422,2086,1423,1424,1425,5090,1426,3024,740,2690,5513,1254,182,4131,4132,2691,4133,2087,2088,4134,3025,4135,480,2089,1045,4136,5514,741,3026,1427,3509,4137,3027,2090,481,3028,2497,4590,1428,2091,4380,856,1046,4591,482,1429,5091,5515,183,5516,184,4138,1047,4139,2092,1048,4140,483,4592,5092,1430,4381,1543,3029,5517,81,4141,1431,742,2093,3510,1049,2498,2499,1432,3511,1433,4142,484,4143,2094,5093,2500,743,5094,3512,2501,132,2095,5095,2692,1255,82,3776,83,3513,84,2096,5096,2097,3296,1256,485,2693,2098,5518,486,2099,85,2100,5097,2101,5098,5099,2502,2102,1050,5100,4593,3297,3298,744,3030,5101,5102,4144,5103,4594,2503,487,3299,2504,5104,3031,4595,86,2103,3777,2104,2105,4382,2694,4596,5105,1051,2106,3032,5106,488,1052,5107,2505,745,4412,746,5404,1257,747,748,1053,2107,3514,2108,3515,2109,4597,3033,4145,2110,4598,2111,2112,3516,87,5108,1054,2506,749,4599,2113,4600,750,3300,4146,5109,3034,5519,489,3035,4601,5110,4147,3517,88,3518,1258,5520,490,1055,5521,3301,5522,1056,1057,3036,5111,4148,4602,2114,3037,1058,4149,857,3302,5112,4150,89,2115,4603,3519,2116,3644,2117,751,2507,2118,5113,4151,3645,1259,5114,752,4604,5115,1544,3038,4152,5523,2119,753,491,754,3778,5524,3039,3040,1545,1059,1434,5116,3041,5117,3303,1435,3042,1546,2120,5118,2695,492,3646,3779,2508,1060,3780,5119,4153,4383,3781,90,185,493,91,5120,5121,3520,3521,3304,3782,1260,4154,3783,2121,4155,2122,2123,2124,2696,3784,1261,3522,3305,92,4605,4156,4157,2125,4606,1262,2126,3043,3044,2697,2127,3523,2128,2129,5122,3785,3647,494,2509,5525,3524,3786,3306,186,2130,3045,5123,5124,1263,2698,3307,3525,5125,2131,495,4158,5126,3046,93,4607,1264,2132,4159,3526,496,3047,2133,5127,3308,2134,5128,2135,755,2699,133,2136,2137,2138,3787,2700,5405,1436,3788,2139,5129,497,4160,2701,2140,4608,5130,5131,1265,5406,5132,2141,5526,498,3789,858,5133,1266,1547,3527,3528,2142,4161,2702,2143,3790,5527,2510,1437,4162,4163,756,1267,5134,3791,94,4609,757,2144,2145,5528,2146,2147,2148,5135,5136,758,1268,2149,4610,1269,3048,3049,3050,1061,5137,2150,4611,3309,3310,4612,3311,1062,3648,95,5138,2703,499,2151,4164,2511,3529,2704,5139,2152,2153,2154,2155,3051,500,96,2705,1063,5140,2706,3792,2707,2156,4384,3530,4385,501,5141,1270,97,502,5142,5529,759,2157,3052,4165,4166,3053,4167,3054,4613,5143,3055,5407,3649,4168,1271,4169,4614,859,503,4170,2158,3531,1272,5144,760,5145,5146,1064,2159,5147,3532,3650,504,3056,5148,2160,5149,5408,2161,5150,2162,2163,98,1065,1273,2164,4171,2165,5151,5152,3057,5530,5153,4172,5154,4615,2166,1066,1067,761,505,3533,506,2708,3058,3059,5155,2167,2709,5531,860,2168,2512,12,1068,3060,507,508,3061,4173,5156,4616,1438,2169,5157,5158,3312,1274,2710,3793,2711,4174,99,2712,2170,5409,5410,509,1439,2171,2172,510,5159,2713,3313,4617,5160,2173,5161,2513,3062,1548,5162,1440,3063,1069,5163,4175,4618,5532,4619,5533,1441,2174,4176,4620,1442,5164,861,2175,2176,511,5165,762,5166,1070,3651,3064,3794,4177,1071,763,2177,2514,1072,3534,13,4178,1443,3535,5534,3065,3066,4621,100,5411,2515,101,3795,1444,1445,1446,5167,5168,2178,1275,134,4179,4180,1549,5535,3652,102,3067,1276,512,4622,4386,4181,3068,14,4182,1073,2179,764,5169,513,5170,765,2180,2181,4183,4623,1447,5171,135,514,3069,5172,2182,4624,5173,5536,2516,3070,2183,2714,3536,5174,2184,2185,5175,2186,5176,4625,3071,515,1277,5177,187,4626,516,1278,2187,862,5537,2188,4184,1279,4387,4627,2189,5178,1280,517,1281,5179,2517,3314,4388,1448,1282,3072,4628,2715,1074,4185,5180,5412,4186,2190,3073,5538,3796,4187,2716,5181,4188,2191,3074,5182,3075,2518,3653,3076,4189,3077,103,3078,3537,518,2717,3654,5183,5184,2192,1449,3079,4190,519,4629,3080,5185,4191,3315,1075,3655,3081,766,2718,3316,520,767,768,769,770,3797,3798,521,5186,3082,5187,3083,3084,4630,1283,2193,2194,3085,3086,3317,2195,5539,771,2519,5188,3538,4192,2196,3539,5189,5190,5191,4193,522,2719,3087,772,3656,2197,3088,1450,3089,2198,2199,5192,4194,523,1284,2720,524,2721,5413,525,2722,2200,5540,3799,3318,526,3800,2723,2724,2201,3540,3801,5414,1076,1077,1285,1550,5193,527,3541,528,3319,5194,5195,1451,3090,5196,2202,529,3091,5197,5198,5199,5200,5201,2203,1452,3542,5415,5202,5203,5204,2204,3092,863,3093,3657,3094,15,1453,3095,3096,1551,2205,3658,5205,4389,5541,4631,3659,3660,5206,530,3661,531,4632,3802,4633,532,2206,4634,2207,5542,4635,4195,2208,3320,4636,4196,5207,3543,104,2209,2520,4637,1552,3097,2210,864,2211,4197,2212,2213,2214,2215,188,1078,533,4638,5543,2725,1079,1553,2216,5208,4198,4639,2217,5209,4199,1554,2218,4640,4200,2219,534,3803,16,4201,3098,4202,4390,2220,4641,3099,4203,4204,1454,3100,2521,1455,4205,4413,5210,1286,2221,5416,3101,4206,1456,5211,105,2222,5212,1080,2223,5213,2522,773,535,3804,2224,3102,5214,2225,774,2226,4207,5215,3321,4208,5216,5217,5218,4642,2726,3322,5417,2727,3103,3323,2227,536,2523,775,5219,3324,4643,5220,5221,2228,5222,1457,3104,4209,3105,5223,4644,537,4210,4211,2524,1287,5544,4212,1081,5545,5224,4645,3325,4213,5225,5226,3106,538,2229,5227,1082,2230,2231,2525,4214,2232,5228,539,1458,2728,4646,3107,4215,5229,4216,2729,3326,3805,540,3327,5230,5231,541,5232,1083,2233,3108,2234,2526,3328,2235,3544,5233,4217,1459,3545,2236,5234,3109,1084,2237,5546,5235,3329,3546,1288,5236,1289,2730,3110,4647,1085,2238,542,1290,2731,3111,1086,5237,3112,189,3113,2527,2239,865,3114,5238,3547,543,1291,2240,2732,4391,5418,106,2528,1292,2241,4218,3806,4219,3330,5239,544,2529,2242,866,3331,4220,3115,2530,2243,2244,5547,3662,3116,5240,3117,776,1293,1294,2733,5241,2245,545,2246,2247,2248,1087,2249,1088,1555,5242,2250,5548,1460,4221,2251,1089,4648,5419,5243,3548,17,4649,5549,5244,867,2734,4222,1090,3118,5550,546,1461,3332,4650,1091,3119,4651,5551,2252,4223,547,136,548,4224,5245,2253,2254,2735,5246,2255,777,2531,778,2256,2257,107,3120,2258,2259,1295,3807,108,2260,3549,2261,5420,3808,2736,2262,549,2532,2533,4225,4652,1462,550,4653,5421,1296,5247,2737,5248,4226,3809,5249,1092,4227,3121,4228,1093,551,1463,3550,3663,5250,2263,5251,2264,3122,1094,2265,190,2266,2267,5252,1464,2268,4229,3123,5253,4230,2269,2270,3124,2534,1297,3551,4231,4232,552,5254,4233,2271,3125,3552,5255,5256,2272,779,1298,3333,2738,1299,2739,2273,3810,5257,4654,5552,3811,3334,4655,1300,5258,4656,4234,109,2274,3553,2535,5259,3335,4657,5260,3126,5422,4658,553,554,1095,2740,4659,5423,2275,2536,1301,2537,2741,1302,868,2276,4235,555,4392,556,1303,2277,1465,557,3554,5553,2538,3812,3664,2278,2742,5261,5424,4236,3555,1096,3665,2279,4237,2280,1304,558,2281,4393,1305,3813,2539,3556,4660,559,4238,191,869,1556,2282,2283,2540,2284,3666,2285,780,3814,3557,2286,3558,2287,2288,2289,560,2290,4239,3127,3128,3336,1306,4661,2291,1097,4414,3667,5262,3559,3560,2292,2293,1098,2541,2294,3561,4240,3562,5263,2295,5264,3668,2542,2296,2543,3563,3129,2743,1307,4662,3130,781,2297,2298,4663,2299,2300,1308,2301,5265,3564,4241,2744,3815,1309,4664,2745,3131,1310,2302,2303,4665,5266,2304,3337,4242,3132,3133,3134,4666,2305,5267,3135,3338,2746,110,2306,2307,111,2308,561,4243,3136,2747,2748,3816,2749,2750,1311,3669,2309,5268,3339,2751,2752,870,3817,4667,4668,2310,3565,3340,2311,4244,4245,4246,562,2312,2313,4247,4248,3566,3567,1466,1467,5269,5270,2753,3818,4249,3670,1468,4250,1312,5271,2754,3137,1469,2755,3568,4251,2314,3341,5272,4669,3569,4252,4670,1313,1099,782,3570,112,1314,4415,1100,5273,4253,2756,3138,5274,4254,4255,4671,4256,871,1315,3139,3819,5275,3571,4672,563,4257,2757,5425,2315,1101,3572,3820,2544,4394,3140,4673,1102,3573,5554,113,114,4258,1103,5276,4259,192,3821,3822,5277,1316,3671,1470,4260,2316,4261,4674,4262,3141,3142,3143,3574,2317,4263,5278,1317,2318,3823,1318,1319,3575,1320,2319,5279,2320,872,5555,115,5280,3144,2321,2545,5281,2322,2758,3672,2323,4264,2324,2325,2326,564,2327,2328,5556,193,2759,4265,1104,5282,2329,2330,3145,3824,2331,4266,4267,5557,4268,4269,3825,5283,2332,2760,4270,1321,3342,2761,565,1471,4271,3146,2333,2546,3673,4272,3674,3147,4273,5284,2334,5285,2335,566,116,1322,567,3148,4675,568,4676,569,4677,5286,3576,570,3577,4274,4275,4276,4277,1557,2336,18,1323,2337,1105,2338,3826,2339,3827,19,2340,2547,1324,2341,783,117,784,4278,3149,571,2342,2343,2344,4279,572,4280,2345,4395,4281,2346,3675,873,4678,5287,2347,2762,3828,2763,2348,3829,3830,137,573,2349,2350,574,2764,5288,3831,1472,575,2765,3343,5289,2351,1325,1106,2352,3150,2353,2766,576,3832,3833,3344,2354,577,3151,3345,3152,4282,4283,2767,5290,5291,4284,2355,1558,2356,4285,3834,5292,4679,1559,3578,3676,1107,5558,4286,2357,5293,194,2358,5426,2359,3579,578,1108,2360,3580,4287,1473,3153,3346,5427,1109,579,580,1326,3835,5559,581,4288,2768,785,2361,5294,3581,2769,2770,4289,2362,3347,786,4680,1560,874,5295,1474,2771,2548,2772,582,5560,1327,1328,5296,4681,3154,5297,2773,3677,3348,3582,5298,5299,4290,1475,5300,195,5301,3349,5302,5561,583,3836,2363,787,3350,3351,5303,2774,1561,5304,5562,5305,2549,4682,2364,5563,3837,5306,5564,3352,3155,5307,3156,788,3583,5308,3838,4683,1476,3678,584,118,3584,585,586,2365,196,3157,4291,4292,587,2775,4293,2366,3158,2367,5309,588,5310,1477,4294,2368,5311,1110,119,4295,5312,3353,5313,5314,4296,1562,5315,20,789,138,5316,2369,1329,5317,790,5318,2776,4297,197,2777,589,3159,2370,4396,791,5319,3160,5428,3839,3840,4298,2778,590,5320,591,2371,592,120,1563,3585,1111,3679,3354,1112,2550,3161,4299,593,3355,1478,3162,3163,5321,2551,1479,4300,4397,792,3164,3841,3842,5322,4684,4685,3165,3356,3843,4686,1330,4687,4688,5323,1331,2372,4301,2373,4302,2374,5429,5565,5566,2375,2376,2377,3166,5430,3167,2378,2552,198,3357,1480,4303,5324,4304,5325,3844,5326,2553,3358,121,2554,793,3680,4305,4306,594,5327,4307,4689,3168,4308,2379,4309,4310,4311,5328,1564,2380,4312,4313,2381,1113,3681,4690,4691,4692,1114,3359,4314,2779,3360,4315,3845,1332,1115,4693,4694,595,2555,4316,2556,1333,5329,2382,4695,4317,3169,3170,1334,5330,2383,3361,4318,4319,4320,4321,3362,3171,5331,5567,5568,1335,1336,5332,2384,5333,4322,794,1116,1117,3172,4696,2385,1337,199,596,2386,2387,597,598,795,2388,5334,599,5335,2389,2390,5336,3173,4323,5337,600,4416,1118,2780,2557,796,3846,5431,601,2391,2781,797,3174,602,2392,3586,4324,3175,2393,4697,1481,122,5338,3176,4325,3847,3177,603,5339,1338,5340,1119,1120,2394,2558,4698,798,2395,200,604,3587,2396,201,4326,799,4398,4699,5341,4700,1121,605,4327,1482,4399,4400,4328,4329,4330,606,3682,3588,607,5342,5343,5344,1122,4331,4701,4702,5345,2397,875,2398,4703,1339,2399,5346,5347,2400,1123,2401,800,3683,2782,3848,801,3589,2402,608,609,1483,3590,610,5348,611,2403,3684,2404,4332,876,3849,3178,3363,1484,612,3850,4333,5349,3179,3591,4334,3364,2405,3180,613,2406,2407,2408,3365,3366,2409,4335,4336,4337,877,1340,1124,3367,4338,1565,1125,123,2410,3851,802,4339,4704,4705,2411,2783,2559,1485,1126,3852,4340,4341,4342,3592,4343,1341,878,1127,1486,879,880,4401,5350,5351,2412,2413,2414,2415,3181,2416,2560,4344,5352,4345,4346,2784,4706,881,5353,614,4347,3368,139,1342,2561,3182,1343,2417,3685,5354,5355,615,3593,5569,616,2418,3183,617,4348,4707,5570,3184,4349,4708,21,4709,4710,3369,2562,618,2785,5356,1344,4711]} diff --git a/spec/bridge/source/municipalities.ts b/spec/bridge/source/municipalities.ts deleted file mode 100644 index c36eac5d9..000000000 --- a/spec/bridge/source/municipalities.ts +++ /dev/null @@ -1,110 +0,0 @@ -/** - * Brazilian municipalities, written once. - */ -import { type Dataset, dataAll, dataRows, dataset } from "./_std.ts"; - -/** - * The two letter code of a Brazilian state. Checked against the dataset by `data/build.ts`, so - * the union and the table can never drift apart. - */ -export type StateCode = - | "AC" - | "AL" - | "AP" - | "AM" - | "BA" - | "CE" - | "DF" - | "ES" - | "GO" - | "MA" - | "MT" - | "MS" - | "MG" - | "PA" - | "PB" - | "PR" - | "PE" - | "PI" - | "RJ" - | "RN" - | "RS" - | "RO" - | "RR" - | "SC" - | "SP" - | "SE" - | "TO"; - -/** One Brazilian municipality, as the IBGE publishes it. */ -export type Municipality = { - /** The 7-digit IBGE municipality code. */ - code: string; - /** The municipality name. */ - name: string; - /** The two-letter code of the state the municipality belongs to. */ - stateCode: StateCode; -}; - -/** - * The municipalities table: `[stateCode, name, code]` per row, grouped by state, with the - * combined pt-BR order baked in at build time. - */ -const MUNICIPALITIES: Dataset = dataset("municipalities"); - -/** - * Reads one dataset row as a municipality. - * - * @param {string[]} row - The `[stateCode, name, code]` row. - * @returns {Municipality} The municipality. - */ -const rowToMunicipality = (row: string[]): Municipality => ({ - code: row[2], - name: row[1], - // The dataset holds plain strings; `data/build.ts` is what keeps the closed set true. - stateCode: row[0] as StateCode, -}); - -/** - * Returns Brazilian municipalities published by the IBGE, optionally filtered by state. - * - * If `stateCode` is provided, only municipalities of that state are returned. If it is - * omitted, every municipality of every state is returned, sorted with `localeCompare` in the - * "pt-BR" locale so accented names land where a Brazilian reader expects them. Every per-state - * list is sorted the same way. - * - * Only an omitted (or `undefined`) `stateCode` asks for the full list: any other value that is - * not a known state code, `null` and `""` included, returns `[]`. - * - * The state code is matched exactly, case included: `getMunicipalities("sp")` returns `[]` where - * `getMunicipalities("SP")` returns the 645 São Paulo municipalities. - * - * @param {StateCode} [stateCode] - The two letter code of the Brazilian state to filter by. - * @returns {Municipality[]} A fresh array of fresh `Municipality` objects. Empty when - * `stateCode` is not a known state. - * - * @example - * ```typescript - * getMunicipalities("SP")[0]; // { code: "3500105", name: "Adamantina", stateCode: "SP" } - * getMunicipalities().length; // every municipality of every state - * getMunicipalities("ZZ"); // [] - * getMunicipalities("sp"); // [] (the state code is case-sensitive here) - * getMunicipalities(null); // [] (only an omitted state code asks for the full list) - * ``` - * - * @see Official: https://servicodados.ibge.gov.br/api/docs/localidades - */ -export const getMunicipalities = (stateCode?: StateCode): Municipality[] => { - const municipalities: Municipality[] = []; - let rows = dataAll(MUNICIPALITIES); - - if (stateCode !== undefined) { - rows = dataRows(MUNICIPALITIES, stateCode); - } - - for (const row of rows) { - municipalities.push(rowToMunicipality(row)); - } - - return municipalities; -}; diff --git a/vite.config.ts b/vite.config.ts index 1822d8c93..157d718a4 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -527,6 +527,9 @@ export default defineConfig({ }, files: ["spec/bridge/**/*.ts"], rules: { + // An emitter is one template per target, and splitting a template in half to + // satisfy a line count would hide the shape of the code it writes. + "eslint/max-lines-per-function": "off", // `spec/bridge` is a compiler. Its emitters are one big switch over the IR per // language, and their product is source code, so a few of the rules that keep // library code readable work against it here. From f701ac065b28c27f8c42c3fa681989c2154b61da Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 21 Sep 2026 04:00:11 +0000 Subject: [PATCH 08/13] feat(spec): port isValidCnpj to the bridge MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The first utility through the compiler, and the one that exercises the parts a validator needs: two compiled regular expressions, a check digit pass over both CNPJ versions, and the `typeof` guard that makes a number invalid in JavaScript. The CNPJ rules that `formatCnpj` will also need — the two shapes a CNPJ can be written in, the weight vectors, the check digits — go under `source/_internals/`, written once. The compiler inlines them into this utility and prunes the rest, so the emitted module carries what it uses and nothing else. The corpus is every string literal in the package's own CNPJ test files, plus generated CNPJs, masked variants, one-digit mutations and the numbers a JavaScript caller can pass where a string is declared, under all three option sets. The generator is seeded, so the table is the same on every run. typescript 1725/1725 python 1725/1725 ruby 1725/1725 go 1707/1707 rust 1707/1707 java 1707/1707 csharp 1707/1707 cabi 1707/1707 The eighteen the compiled targets do not run are the numeric inputs: they declare the parameter as a string, so `isValidCnpj(12345678000195)` is a question that cannot be asked there. The row records that rather than dropping it. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01UX1gTGeMTyoXQyr1qUoQKd --- spec/bridge/README.md | 5 +- spec/bridge/conformance/cases/_cnpj-corpus.ts | 92 +++++++++++++++++++ .../bridge/conformance/cases/is-valid-cnpj.ts | 20 ++++ spec/bridge/source/_internals/cnpj.ts | 88 ++++++++++++++++++ spec/bridge/source/is-valid-cnpj.ts | 75 +++++++++++++++ 5 files changed, 278 insertions(+), 2 deletions(-) create mode 100644 spec/bridge/conformance/cases/_cnpj-corpus.ts create mode 100644 spec/bridge/conformance/cases/is-valid-cnpj.ts create mode 100644 spec/bridge/source/_internals/cnpj.ts create mode 100644 spec/bridge/source/is-valid-cnpj.ts diff --git a/spec/bridge/README.md b/spec/bridge/README.md index 40a70c39b..cad288ba9 100644 --- a/spec/bridge/README.md +++ b/spec/bridge/README.md @@ -146,8 +146,9 @@ be handed it, so nothing is skipped for being inconvenient, and the count is vis ## Ported so far -Nothing yet: this is the engine on its own, and each utility is a change of its own on top of -it. `conformance/run-all.sh` says so rather than passing vacuously. +| utility | what makes it worth porting | +| ------------- | ----------------------------------------------------------------- | +| `isValidCnpj` | regular expressions, check digits, JavaScript's own type coercion | ## Adding a utility diff --git a/spec/bridge/conformance/cases/_cnpj-corpus.ts b/spec/bridge/conformance/cases/_cnpj-corpus.ts new file mode 100644 index 000000000..ac23e44dd --- /dev/null +++ b/spec/bridge/conformance/cases/_cnpj-corpus.ts @@ -0,0 +1,92 @@ +/** + * The CNPJ corpus both CNPJ recorders replay. + * + * It is not invented: every string literal the package's own CNPJ test files use is pulled out + * of them, so the cross language check runs the same inputs the JavaScript suite runs. On top + * of that go freshly generated CNPJs, masked variants of them, one-digit mutations, and the + * numbers a JavaScript caller can pass where a string is declared. + */ +import { readFileSync, readdirSync } from "node:fs"; +import { resolve } from "node:path"; + +const root = resolve(import.meta.dirname, "../../../.."); + +/** Pulls every string literal out of a test file, which is where the interesting inputs live. */ +const literalsOf = (path: string): string[] => { + const source = readFileSync(path, "utf8"); + const found = new Set(); + + for (const match of source.matchAll(/"((?:[^"\\\n]|\\.){0,40})"/g)) { + try { + found.add(JSON.parse(`"${match[1]}"`) as string); + } catch { + // A literal that is not valid JSON on its own is not an input worth replaying. + } + } + + return [...found]; +}; + +/** A deterministic pseudo random generator, so the corpus only changes when this file does. */ +const mulberry32 = (seed: number): (() => number) => { + let state = seed; + + return () => { + state = Math.imul(state + 0x6d_2b_79_f5, 1); + let t = Math.imul(state ^ (state >>> 15), 1 | state); + + t ^= t + Math.imul(t ^ (t >>> 7), 61 | t); + + return ((t ^ (t >>> 14)) >>> 0) / 4_294_967_296; + }; +}; + +const MASKS = [".", "-", "/", " ", " ", "", "!", "a"]; + +/** + * Builds the corpus. + * + * @param {Function} generateCnpj - The package's own generator. + * @returns {(string | number)[]} The corpus. + */ +export const cnpjCorpus = (generateCnpj: (version?: 1 | 2) => string): (string | number)[] => { + const random = mulberry32(0x62_72_31); + const corpus = new Set(); + // `generateCnpj` draws from `Math.random`, and a corpus that changes between runs makes a + // diverging target look like a flake. Seeding it makes the table the same every time. + const realRandom = Math.random; + + Math.random = random; + + for (const utility of ["is-valid-cnpj", "format-cnpj"]) { + for (const name of readdirSync(resolve(root, "src", utility))) { + if (!name.endsWith(".test.ts")) continue; + + for (const literal of literalsOf(resolve(root, "src", utility, name))) corpus.add(literal); + } + } + + for (let index = 0; index < 120; index++) { + const version = index % 2 === 0 ? 1 : 2; + const cnpj = generateCnpj(version); + + corpus.add(cnpj); + corpus.add(cnpj.toLowerCase()); + + const separators = [0, 1, 2, 3].map(() => MASKS[Math.floor(random() * MASKS.length)]); + + corpus.add( + `${cnpj.slice(0, 2)}${separators[0]}${cnpj.slice(2, 5)}${separators[1]}${cnpj.slice(5, 8)}${separators[2]}${cnpj.slice(8, 12)}${separators[3]}${cnpj.slice(12)}`, + ); + + const position = Math.floor(random() * cnpj.length); + + corpus.add(`${cnpj.slice(0, position)}${Math.floor(random() * 10)}${cnpj.slice(position + 1)}`); + } + + Math.random = realRandom; + + for (const number of [0, 4, 46, 468, 12_345_678, 12_345_678_000_195]) corpus.add(number); + + return [...corpus]; +}; diff --git a/spec/bridge/conformance/cases/is-valid-cnpj.ts b/spec/bridge/conformance/cases/is-valid-cnpj.ts new file mode 100644 index 000000000..c20febc6d --- /dev/null +++ b/spec/bridge/conformance/cases/is-valid-cnpj.ts @@ -0,0 +1,20 @@ +/** + * What `isValidCnpj` is replayed with: the whole CNPJ corpus, under every option set. + */ +import { type Recorder } from "../cases.ts"; +import { cnpjCorpus } from "./_cnpj-corpus.ts"; + +const OPTIONS = [undefined, { version: 1 }, { version: 2 }]; + +export const recorder: Recorder = { + module: "is-valid-cnpj", + inputs: (shipped) => { + const corpus = cnpjCorpus(shipped["generateCnpj"] as (version?: 1 | 2) => string); + const found: unknown[][] = []; + + for (const input of corpus) + for (const options of OPTIONS) found.push(options === undefined ? [input] : [input, options]); + + return found; + }, +}; diff --git a/spec/bridge/source/_internals/cnpj.ts b/spec/bridge/source/_internals/cnpj.ts new file mode 100644 index 000000000..2b3d7535a --- /dev/null +++ b/spec/bridge/source/_internals/cnpj.ts @@ -0,0 +1,88 @@ +/** + * What the CNPJ utilities share: the shapes a CNPJ can be written in, and its check digits. + * + * Every name here is spliced into the utility that imports it and emitted as one of its own + * private declarations, so this file is where a CNPJ rule is written once — not a module any + * target ends up depending on. + * + * @see Official: https://www.gov.br/receitafederal/pt-br/centrais-de-conteudo/publicacoes/documentos-tecnicos/cnpj/manual-dv-cnpj.pdf + */ + +/** The weights of the first check digit, most significant first. */ +export const FIRST_DIGIT_WEIGHTS = [5, 4, 3, 2, 9, 8, 7, 6, 5, 4, 3, 2]; + +/** The weights of the second check digit, most significant first. */ +export const SECOND_DIGIT_WEIGHTS = [6, 5, 4, 3, 2, 9, 8, 7, 6, 5, 4, 3, 2]; + +/** A version 2 CNPJ: letters allowed everywhere but the two check digits. */ +export const ALPHANUMERIC_FORMAT = + /^[0-9A-Z]{2}[\s.\-/]*[0-9A-Z]{3}[\s.\-/]*[0-9A-Z]{3}[\s.\-/]*[0-9A-Z]{4}[\s.\-/]*[0-9]{2}$/; + +/** A version 1 CNPJ: digits only, with the usual mask characters between the groups. */ +export const NUMERIC_FORMAT = /^\d{2}[\s.\-/]*\d{3}[\s.\-/]*\d{3}[\s.\-/]*\d{4}[\s.\-/]*\d{2}$/; + +/** Whether a value holds a letter, which is what tells the two versions apart. */ +export const LETTER = /[A-Z]/; + +/** Everything a version 2 CNPJ is not made of. */ +export const NON_ALPHANUMERIC = /[^A-Za-z0-9]/g; + +/** Everything a version 1 CNPJ is not made of. */ +export const NON_DIGIT = /\D/g; + +/** + * Computes one CNPJ check digit from the base and its weight vector. + * + * @param {string} base - The sanitized CNPJ, of which only the base is read. + * @param {number[]} weights - The weight vector of the digit being computed. + * @returns {number} The check digit. + */ +export const checkDigit = (base: string, weights: number[]): number => { + let sum = 0; + + for (let index = 0; index < weights.length; index++) { + sum += (base.charCodeAt(index) - 48) * weights[index]; + } + + const remainder = sum % 11; + + if (remainder < 2) { + return 0; + } + + return 11 - remainder; +}; + +/** + * Whether both check digits of a sanitized 14 character CNPJ match its base. + * + * @param {string} cnpj - The sanitized CNPJ. + * @returns {boolean} True when both check digits match. + */ +export const hasValidChecksum = (cnpj: string): boolean => { + if (cnpj.charCodeAt(12) - 48 !== checkDigit(cnpj, FIRST_DIGIT_WEIGHTS)) { + return false; + } + + return cnpj.charCodeAt(13) - 48 === checkDigit(cnpj, SECOND_DIGIT_WEIGHTS); +}; + +/** + * Whether every character of the value is the same one. + * + * @param {string} value - The value. + * @returns {boolean} True when the value repeats one character. + */ +export const isRepeated = (value: string): boolean => { + if (value.length === 0) { + return false; + } + + for (let index = 1; index < value.length; index++) { + if (value.charCodeAt(index) !== value.charCodeAt(0)) { + return false; + } + } + + return true; +}; diff --git a/spec/bridge/source/is-valid-cnpj.ts b/spec/bridge/source/is-valid-cnpj.ts new file mode 100644 index 000000000..9861fff17 --- /dev/null +++ b/spec/bridge/source/is-valid-cnpj.ts @@ -0,0 +1,75 @@ +/** + * `isValidCnpj`, written once. + * + * This is ordinary TypeScript inside the portable subset the bridge accepts: annotated + * parameters and returns, regex literals it compiles rather than passes through, and the same + * boundary guards the handwritten package has. `spec/bridge/README.md` documents the subset; + * the compiler rejects anything outside it instead of guessing. + * + * @see Official: https://www.gov.br/receitafederal/pt-br/assuntos/orientacao-tributaria/cadastros/cnpj + * @see Official: https://www.gov.br/receitafederal/pt-br/acesso-a-informacao/acoes-e-programas/programas-e-atividades/cnpj-alfanumerico + */ +import { + ALPHANUMERIC_FORMAT, + LETTER, + NON_ALPHANUMERIC, + NON_DIGIT, + NUMERIC_FORMAT, + hasValidChecksum, + isRepeated, +} from "./_internals/cnpj.ts"; + +/** Options of `isValidCnpj`. */ +export type IsValidCnpjOptions = { + /** Which CNPJ format to accept: `1` numeric only, `2` alphanumeric (default: `1`). */ + version?: 1 | 2; +}; + +/** + * Validates if a CNPJ (Cadastro Nacional da Pessoa Jurídica) is valid. + * + * Supports both numeric (version 1) and alphanumeric (version 2) CNPJ formats, and accepts the + * usual mask characters (`.`, `-`, `/`) and whitespace around and between groups. + * + * @param {string} cnpj - The CNPJ value to be validated. + * @param {IsValidCnpjOptions} [options] - Optional options. + * @returns {boolean} True if the CNPJ is valid, false otherwise. + * + * @example + * ```typescript + * isValidCnpj("12.345.678/0001-95"); // true + * isValidCnpj("q0slfmbd7vx439", { version: 2 }); // true + * isValidCnpj("00000000000000"); // false (reserved number) + * ``` + */ +export const isValidCnpj = (cnpj: string, options?: IsValidCnpjOptions): boolean => { + if (typeof cnpj !== "string") { + return false; + } + + const trimmed = cnpj.trim(); + + if (options?.version === 2) { + const cleaned = cnpj.replaceAll(NON_ALPHANUMERIC, "").toUpperCase(); + + if (LETTER.test(cleaned)) { + if (!ALPHANUMERIC_FORMAT.test(trimmed.toUpperCase())) { + return false; + } + + return hasValidChecksum(cleaned); + } + } + + const numeric = cnpj.replaceAll(NON_DIGIT, ""); + + if (!NUMERIC_FORMAT.test(trimmed)) { + return false; + } + + if (isRepeated(numeric)) { + return false; + } + + return hasValidChecksum(numeric); +}; From dbff7d8508a46335742d36cb9238c37a5a92976e Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 21 Sep 2026 04:00:23 +0000 Subject: [PATCH 09/13] feat(spec): port formatCnpj to the bridge MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The second utility, and the one that shows what sharing costs. It reads the same two character classes `isValidCnpj` reads, out of the same `source/_internals/cnpj.ts`, and adds a mask helper of its own under `source/_internals/mask.ts` — written once, for every `format*` utility that comes after it. What each target ends up with is still one self-contained module: the generated `format-cnpj` carries the mask helper and the two classes it uses, and not a line of the check digit code, because the compiler prunes what the utility cannot reach. That is the property the npm package needs, and it is why the helpers are inlined rather than emitted as a shared module per target. Three options that interact — `pad`, `version`, `obfuscate` — over the same corpus, so all seven combinations are replayed against every input. typescript 4025/4025 python 4025/4025 ruby 4025/4025 go 3983/3983 rust 3983/3983 java 3983/3983 csharp 3983/3983 cabi 3983/3983 Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01UX1gTGeMTyoXQyr1qUoQKd --- spec/bridge/README.md | 1 + spec/bridge/conformance/cases/format-cnpj.ts | 28 +++++++++ spec/bridge/source/_internals/mask.ts | 56 +++++++++++++++++ spec/bridge/source/format-cnpj.ts | 63 ++++++++++++++++++++ 4 files changed, 148 insertions(+) create mode 100644 spec/bridge/conformance/cases/format-cnpj.ts create mode 100644 spec/bridge/source/_internals/mask.ts create mode 100644 spec/bridge/source/format-cnpj.ts diff --git a/spec/bridge/README.md b/spec/bridge/README.md index cad288ba9..964fc225a 100644 --- a/spec/bridge/README.md +++ b/spec/bridge/README.md @@ -149,6 +149,7 @@ be handed it, so nothing is skipped for being inconvenient, and the count is vis | utility | what makes it worth porting | | ------------- | ----------------------------------------------------------------- | | `isValidCnpj` | regular expressions, check digits, JavaScript's own type coercion | +| `formatCnpj` | a shared mask helper, and three options that interact | ## Adding a utility diff --git a/spec/bridge/conformance/cases/format-cnpj.ts b/spec/bridge/conformance/cases/format-cnpj.ts new file mode 100644 index 000000000..6363e1411 --- /dev/null +++ b/spec/bridge/conformance/cases/format-cnpj.ts @@ -0,0 +1,28 @@ +/** + * What `formatCnpj` is replayed with: the whole CNPJ corpus, under every option combination. + */ +import { type Recorder } from "../cases.ts"; +import { cnpjCorpus } from "./_cnpj-corpus.ts"; + +const OPTIONS = [ + undefined, + { version: 2 }, + { pad: true }, + { obfuscate: true }, + { pad: true, version: 2 }, + { obfuscate: true, version: 2 }, + { obfuscate: true, pad: true }, +]; + +export const recorder: Recorder = { + module: "format-cnpj", + inputs: (shipped) => { + const corpus = cnpjCorpus(shipped["generateCnpj"] as (version?: 1 | 2) => string); + const found: unknown[][] = []; + + for (const input of corpus) + for (const options of OPTIONS) found.push(options === undefined ? [input] : [input, options]); + + return found; + }, +}; diff --git a/spec/bridge/source/_internals/mask.ts b/spec/bridge/source/_internals/mask.ts new file mode 100644 index 000000000..092e94f15 --- /dev/null +++ b/spec/bridge/source/_internals/mask.ts @@ -0,0 +1,56 @@ +/** + * Laying a value over a mask, which is what every `format*` utility does. + * + * The mask is a string: `0` is a slot the value fills, `*` is a slot the value fills and the + * mask hides, and anything else is a separator, written only while there is still value left + * to write. + */ + +/** + * Lays a value over a pattern. + * + * @param {string} value - The sanitized value. + * @param {string} pattern - The mask. + * @param {boolean} pad - Whether to left pad the value with zeros up to the number of slots. + * @returns {string} The masked value, cut short where the value runs out. + */ +export const layout = (value: string, pattern: string, pad: boolean): string => { + let slots = 0; + + for (let index = 0; index < pattern.length; index++) { + if (pattern.charCodeAt(index) === 48 || pattern.charCodeAt(index) === 42) { + slots += 1; + } + } + + let padded = value; + + if (pad) { + padded = value.padStart(slots, "0"); + } + + let formatted = ""; + let cursor = 0; + + for (let index = 0; index < pattern.length; index++) { + const slot = pattern.charCodeAt(index); + + if (slot === 48 || slot === 42) { + if (cursor >= padded.length) { + return formatted; + } + + if (slot === 42) { + formatted += "*"; + } else { + formatted += padded.slice(cursor, cursor + 1); + } + + cursor += 1; + } else if (cursor < padded.length) { + formatted += pattern.slice(index, index + 1); + } + } + + return formatted; +}; diff --git a/spec/bridge/source/format-cnpj.ts b/spec/bridge/source/format-cnpj.ts new file mode 100644 index 000000000..104ee34a2 --- /dev/null +++ b/spec/bridge/source/format-cnpj.ts @@ -0,0 +1,63 @@ +/** + * `formatCnpj`, written once. + * + * The boundary guards are the handwritten package's, not a tidier version of them: a nullish + * value answers the empty string, and a value the mask outruns is cut short rather than + * padded, because that is what the JavaScript this repository ships already does. + * + * @see Official: https://www.gov.br/receitafederal/pt-br/assuntos/orientacao-tributaria/cadastros/cnpj + * @see Official: https://www.gov.br/receitafederal/pt-br/acesso-a-informacao/acoes-e-programas/programas-e-atividades/cnpj-alfanumerico + */ +import { NON_ALPHANUMERIC, NON_DIGIT } from "./_internals/cnpj.ts"; +import { layout } from "./_internals/mask.ts"; +import { asString, isTruthy } from "./_std.ts"; + +/** Options of `formatCnpj`. */ +export type FormatCnpjOptions = { + /** Whether to left pad the value with zeros up to the number of slots in the pattern (default: `false`). */ + pad?: boolean; + /** Which CNPJ format to read: `1` numeric only, `2` alphanumeric (default: `1`). */ + version?: 1 | 2; + /** Whether to hide the first 2 digits and the 2 check digits with `*` (default: `false`). */ + obfuscate?: boolean; +}; + +const PATTERN = "00.000.000/0000-00"; +const OBFUSCATED_PATTERN = "**.000.000/0000-**"; + +/** + * Formats a given CNPJ (Cadastro Nacional da Pessoa Jurídica) value. + * + * @param {string} value - The CNPJ value to be formatted. + * @param {FormatCnpjOptions} [options] - Optional configuration for formatting the CNPJ. + * @returns {string} The formatted CNPJ string in the pattern "00.000.000/0000-00". + * + * @example + * ```typescript + * formatCnpj("12345678000195"); // "12.345.678/0001-95" + * formatCnpj("12345678", { pad: true }); // "00.000.012/3456-78" + * formatCnpj("q0SLFMBD7VX439", { version: 2 }); // "Q0.SLF.MBD/7VX4-39" + * formatCnpj("12345678000195", { obfuscate: true }); // "**.345.678/0001-**" + * ``` + */ +export const formatCnpj = (value: string | number, options?: FormatCnpjOptions): string => { + if (value === null || value === undefined) { + return ""; + } + + const text = asString(value); + + let cleaned = text.replaceAll(NON_DIGIT, ""); + + if (options?.version === 2) { + cleaned = text.replaceAll(NON_ALPHANUMERIC, "").toUpperCase(); + } + + let pattern = PATTERN; + + if (isTruthy(options?.obfuscate)) { + pattern = OBFUSCATED_PATTERN; + } + + return layout(cleaned, pattern, isTruthy(options?.pad)); +}; From 3cd23851ec0cc07f4b4dc721c5d73f2e8c1dd2a6 Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 21 Sep 2026 04:00:40 +0000 Subject: [PATCH 10/13] feat(spec): port getAddressInfoByCep to the bridge MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The utility that decides whether the engine is real. It reaches the network, parses JSON, retries a transient failure, races three providers and raises one of four errors depending on how they fail — and none of that is written per target. The source is straight-line and synchronous. The compiler works out that the call graph waits on the network and colours it: TypeScript and C# come out `async`, with a `Promise` and a `Task`; Go, Rust, Ruby, Java and Python stay blocking. `throw` becomes a real exception class in five targets, `(T, error)` in Go and `Result` in Rust, with the declared hierarchy intact in all seven. `startAll` becomes promises, `Task`s, goroutines and a channel, threads and an `mpsc`, virtual threads, and threads with a queue. The recorder carries both sides of the same scenario table: recording stubs `fetch` the way the JavaScript suite does, and replaying serves the same answers over real HTTP, so each target runs through its own client. Fourteen scenarios cover a provider that answers, one that misses, one that is down, a body that is not an object, fields that are not strings, a masked CEP, and the flags that disagree with the body. typescript 110/110 python 109/109 ruby 109/109 go 103/103 rust 103/103 java 103/103 csharp 103/103 Python and Ruby cannot be handed `{ providers: null }`, because `None` and `nil` are also what an omitted option looks like; the five compiled targets cannot be handed a numeric CEP or a `providers` that is not a list at all. The C ABI does not carry this one: a function that raises and waits needs more than pointers and integers, and it is refused rather than guessed at. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01UX1gTGeMTyoXQyr1qUoQKd --- spec/bridge/README.md | 9 +- .../cases/get-address-info-by-cep.ts | 266 +++++++++++++++ spec/bridge/source/get-address-info-by-cep.ts | 318 ++++++++++++++++++ 3 files changed, 589 insertions(+), 4 deletions(-) create mode 100644 spec/bridge/conformance/cases/get-address-info-by-cep.ts create mode 100644 spec/bridge/source/get-address-info-by-cep.ts diff --git a/spec/bridge/README.md b/spec/bridge/README.md index 964fc225a..877649391 100644 --- a/spec/bridge/README.md +++ b/spec/bridge/README.md @@ -146,10 +146,11 @@ be handed it, so nothing is skipped for being inconvenient, and the count is vis ## Ported so far -| utility | what makes it worth porting | -| ------------- | ----------------------------------------------------------------- | -| `isValidCnpj` | regular expressions, check digits, JavaScript's own type coercion | -| `formatCnpj` | a shared mask helper, and three options that interact | +| utility | what makes it worth porting | +| --------------------- | ----------------------------------------------------------------- | +| `isValidCnpj` | regular expressions, check digits, JavaScript's own type coercion | +| `formatCnpj` | a shared mask helper, and three options that interact | +| `getAddressInfoByCep` | HTTP, JSON, retries, an error hierarchy, three providers raced | ## Adding a utility diff --git a/spec/bridge/conformance/cases/get-address-info-by-cep.ts b/spec/bridge/conformance/cases/get-address-info-by-cep.ts new file mode 100644 index 000000000..d9da982c7 --- /dev/null +++ b/spec/bridge/conformance/cases/get-address-info-by-cep.ts @@ -0,0 +1,266 @@ +/** + * What `getAddressInfoByCep` is replayed with, and the mock the other targets talk to. + * + * One table drives both sides. Recording stubs `fetch`, exactly as the JavaScript suite does; + * replaying serves the same scenarios over real HTTP, so the generated Go, Rust, Ruby, Java, + * C# and Python each run through their own client against something a real client can talk to. + * + * A scenario is keyed by the CEP, so no target needs to be told which one it is in: the CEP in + * the URL is the whole protocol. + */ +import { createServer } from "node:http"; + +import { type Recorder } from "../cases.ts"; + +/** What one provider answers in one scenario. `fail` is a transport failure, not an answer. */ +type Answer = { status: number; body: unknown } | { fail: true }; + +type Scenario = { viacep: Answer; widenet: Answer; brasilapi: Answer }; + +const address = (cep: string): Record => ({ + bairro: "Bela Vista", + cep, + localidade: "São Paulo", + logradouro: "Avenida Paulista", + uf: "SP", +}); + +const widenetAddress = (cep: string): Record => ({ + address: "Avenida Paulista", + city: "São Paulo", + code: cep, + district: "Bela Vista", + ok: true, + state: "SP", + status: 200, +}); + +const brasilApiAddress = (cep: string): Record => ({ + cep, + city: "São Paulo", + neighborhood: "Bela Vista", + state: "SP", + street: "Avenida Paulista", +}); + +const NOT_FOUND_BODY = { errors: [{ message: "CEP não encontrado" }] }; + +/** + * The scenarios, by CEP. Every provider that succeeds in a scenario answers the same address, + * so which one wins the race cannot change the expected result. + */ +const SCENARIOS: Record = { + // Every provider answers. + "01310100": { + viacep: { status: 200, body: address("01310-100") }, + widenet: { status: 200, body: widenetAddress("01310-100") }, + brasilapi: { status: 200, body: brasilApiAddress("01310100") }, + }, + // Every provider reports a miss, each in its own way. + "00000000": { + viacep: { status: 200, body: { erro: true } }, + widenet: { status: 200, body: { ok: false, status: 404 } }, + brasilapi: { status: 200, body: NOT_FOUND_BODY }, + }, + // Every provider answers an HTTP error. + "00000001": { + viacep: { status: 500, body: {} }, + widenet: { status: 503, body: {} }, + brasilapi: { status: 500, body: {} }, + }, + // Nothing reaches any server. + "00000002": { viacep: { fail: true }, widenet: { fail: true }, brasilapi: { fail: true } }, + // Only BrasilAPI answers, and it is the one the caller gets. + "00000003": { + viacep: { fail: true }, + widenet: { status: 503, body: {} }, + brasilapi: { status: 200, body: brasilApiAddress("00000003") }, + }, + // BrasilAPI reports the miss with a status, the others are simply down: not found wins. + "00000004": { + viacep: { status: 500, body: {} }, + widenet: { status: 503, body: {} }, + brasilapi: { status: 404, body: NOT_FOUND_BODY }, + }, + // A body that is not an object at all. + "00000005": { + viacep: { status: 200, body: "oops" }, + widenet: { status: 200, body: 42 }, + brasilapi: { status: 200, body: null }, + }, + // The optional fields are missing. + "00000006": { + viacep: { status: 200, body: { cep: "00000006" } }, + widenet: { status: 200, body: { code: "00000006", ok: true, status: 200 } }, + brasilapi: { status: 200, body: { cep: "00000006" } }, + }, + // ViaCEP answers fields that are not strings. + "00000007": { + viacep: { status: 200, body: { ...address("00000007"), localidade: null, uf: 12 } }, + widenet: { status: 503, body: {} }, + brasilapi: { status: 500, body: {} }, + }, + // The CEP comes back masked and has to be stripped. + "00000008": { + viacep: { status: 200, body: address("00000-008") }, + widenet: { status: 200, body: widenetAddress("00000-008") }, + brasilapi: { status: 200, body: brasilApiAddress("00000-008") }, + }, + // An empty CEP in the body is a miss, whatever else the body holds. + "00000009": { + viacep: { status: 200, body: { ...address(""), cep: "" } }, + widenet: { status: 200, body: { ...widenetAddress(""), code: "" } }, + brasilapi: { status: 200, body: { ...brasilApiAddress(""), cep: "" } }, + }, + // Widenet's own flags disagree with its body. + "00000010": { + viacep: { status: 500, body: {} }, + widenet: { status: 200, body: { code: "00000010", ok: false, status: 200 } }, + brasilapi: { status: 500, body: {} }, + }, + "00000011": { + viacep: { status: 500, body: {} }, + widenet: { status: 200, body: { code: "00000011", ok: true, status: 404 } }, + brasilapi: { status: 500, body: {} }, + }, + // A miss reported alongside a CEP is still a miss. + "00000012": { + viacep: { status: 200, body: { cep: "00000-012", erro: true } }, + widenet: { status: 503, body: {} }, + brasilapi: { status: 200, body: { ...brasilApiAddress("00000012"), ...NOT_FOUND_BODY } }, + }, + // One provider misses and the other is down: the miss is what the caller hears about. + "00000013": { + viacep: { status: 200, body: { erro: true } }, + widenet: { fail: true }, + brasilapi: { fail: true }, + }, +}; + +/** The provider lists worth trying against every scenario. */ +const EVERY_PROVIDER: (string[] | undefined)[] = [ + undefined, + ["viacep"], + ["widenet"], + ["brasilapi"], + ["viacep", "brasilapi"], + ["viacep", "widenet", "brasilapi"], +]; + +/** The answer a provider gives for a CEP, or a 404 when the scenario does not know it. */ +const answerFor = (provider: keyof Scenario, cep: string): Answer => { + const scenario = SCENARIOS[cep]; + + if (scenario === undefined) return { status: 404, body: NOT_FOUND_BODY }; + + return scenario[provider]; +}; + +/** Which provider a URL belongs to. */ +const providerOf = (path: string): keyof Scenario | undefined => { + if (path.includes("viacep.com.br")) return "viacep"; + if (path.includes("widenet.com.br")) return "widenet"; + if (path.includes("brasilapi.com.br")) return "brasilapi"; + + return undefined; +}; + +/** The CEP a URL asks about. */ +const cepOf = (path: string): string => path.replaceAll(/\D/g, "").slice(-8); + +/** The answer for a URL, whichever side is asking. */ +const answerForUrl = (url: string): Answer => { + const provider = providerOf(url); + + return provider === undefined ? { status: 404, body: {} } : answerFor(provider, cepOf(url)); +}; + +export const recorder: Recorder = { + module: "get-address-info-by-cep", + + inputs: () => { + const found: unknown[][] = []; + + for (const cep of Object.keys(SCENARIOS)) + for (const providers of EVERY_PROVIDER) + found.push(providers === undefined ? [cep] : [cep, { providers }]); + + // The inputs that never reach a provider. + for (const cep of ["12345", "123456789", "", "1310100", "abc", "0131010a"]) found.push([cep]); + + // A mask is stripped, and a number is padded; both land on the first scenario. + found.push( + ["01310-100"], + ["01.310-100"], + [1_310_100], + [1_310_100, { providers: ["brasilapi"] }], + ); + + // Provider lists that name nothing usable. + for (const providers of [[], ["invalid"], ["constructor", "toString"], ["VIACEP"]]) + found.push(["01310100", { providers }]); + + // An unknown name among known ones is dropped rather than fatal. + found.push(["01310100", { providers: ["viacep", "invalid", "brasilapi"] }]); + + // What an untyped JavaScript caller can still pass where a list of names is declared. + for (const providers of [null, "viacep", 5, {}, true]) found.push(["01310100", { providers }]); + + return found; + }, + + call: async (shipped, fn, args) => { + const realFetch = globalThis.fetch; + + globalThis.fetch = ((input: unknown): Promise => { + const answer = answerForUrl(String(input)); + + if ("fail" in answer) { + // The shipped `fetchWithRetry` retries a transient transport failure, so the stub + // reports one the same way the mock server does, by closing the socket. + const error = new Error("fetch failed"); + + (error as { cause?: unknown }).cause = { code: "ECONNRESET" }; + + return Promise.reject(error); + } + + return Promise.resolve({ + ok: answer.status >= 200 && answer.status < 300, + status: answer.status, + json: () => Promise.resolve(answer.body), + }); + }) as typeof fetch; + + try { + const answered = shipped[fn](...args); + + return await answered; + } finally { + globalThis.fetch = realFetch; + } + }, + + serve: async (port) => { + const server = createServer((request, response) => { + const answer = answerForUrl(request.url ?? ""); + + if ("fail" in answer) { + request.socket.destroy(); + + return; + } + + response.writeHead(answer.status, { "content-type": "application/json; charset=utf-8" }); + response.end(JSON.stringify(answer.body)); + }); + + await new Promise((resolve) => { + server.listen(port, "127.0.0.1", resolve); + }); + + return () => { + server.close(); + }; + }, +}; diff --git a/spec/bridge/source/get-address-info-by-cep.ts b/spec/bridge/source/get-address-info-by-cep.ts new file mode 100644 index 000000000..2543a11e4 --- /dev/null +++ b/spec/bridge/source/get-address-info-by-cep.ts @@ -0,0 +1,318 @@ +/** + * Address lookup by CEP, written once. + */ +import { + type HttpResponse, + anyFailedWith, + asString, + firstSuccess, + httpGet, + isList, + isNumber, + jsonIsTrue, + jsonInt, + jsonString, + jsonTruthy, + listHas, + startAll, +} from "./_std.ts"; + +/** Base class of every error `getAddressInfoByCep` rejects with. */ +export class GetAddressInfoByCepError extends Error {} + +/** Thrown by `getAddressInfoByCep` when the value given is not a valid CEP. */ +export class GetAddressInfoByCepValidationError extends GetAddressInfoByCepError {} + +/** Thrown by `getAddressInfoByCep` when no CEP service knows the CEP. */ +export class GetAddressInfoByCepNotFoundError extends GetAddressInfoByCepError {} + +/** Thrown by `getAddressInfoByCep` when every CEP service failed to answer. */ +export class GetAddressInfoByCepServiceError extends GetAddressInfoByCepError {} + +/** + * Raised inside a provider that did not answer. Only whether a failure was a not found is + * looked at when the provider failures are aggregated, so this one never leaves the module. + */ +class CepProviderFailure extends Error {} + +/** The address `getAddressInfoByCep` returns for a CEP. */ +export type AddressInfo = { + /** The 8 digit CEP, no mask. */ + cep: string; + /** Two letter state code, e.g. "SP". */ + state: string; + /** City name. */ + city: string; + /** Neighborhood name, empty when the CEP covers a whole city. */ + neighborhood: string; + /** Street name, empty when the CEP covers a whole city. */ + street: string; +}; + +/** The CEP services `getAddressInfoByCep` can query. */ +export type CepProvider = "viacep" | "widenet" | "brasilapi"; + +/** Options of `getAddressInfoByCep`. */ +export type GetAddressInfoByCepOptions = { + /** + * Which CEP services to race, in the order given (default: `["viacep", "brasilapi"]`; the + * deprecated `"widenet"` provider is excluded from the default list, but can still be + * requested explicitly). + */ + providers?: CepProvider[]; +}; + +const CEP_FORMAT = /^\d{8}$/; +const NON_DIGIT = /\D/g; + +/** The providers raced when the caller names none. */ +const DEFAULT_PROVIDERS: CepProvider[] = ["viacep", "brasilapi"]; + +/** Every provider that can be named, including the deprecated one. */ +const KNOWN_PROVIDERS: CepProvider[] = ["viacep", "widenet", "brasilapi"]; + +/** + * The status BrasilAPI answers an unknown CEP with, alongside an `errors` body. ViaCEP and + * Widenet report a miss inside a 200 body instead, so BrasilAPI is the only provider whose + * not-found signal is an HTTP status. + * + * @see Based on: https://brasilapi.com.br/docs#tag/CEP + */ +const BRASIL_API_NOT_FOUND_STATUS = 404; + +/** How many times a request is retried, and the base delay between attempts. */ +const HTTP_RETRIES = 2; +const HTTP_RETRY_DELAY_MS = 250; + +/** + * Reads the address ViaCEP answers with. + * + * @param {string} cep - The 8 digit CEP. + * @returns {AddressInfo} The address. + * + * @see Based on: https://viacep.com.br/ + */ +const fetchViaCep = (cep: string): AddressInfo => { + const response: HttpResponse = httpGet( + `https://viacep.com.br/ws/${cep}/json/`, + HTTP_RETRIES, + HTTP_RETRY_DELAY_MS, + ); + + if (!response.ok) { + throw new CepProviderFailure("ViaCEP request failed"); + } + + const found = jsonString(response.body, "cep"); + + if (jsonTruthy(response.body, "erro") || found === "") { + throw new GetAddressInfoByCepNotFoundError("CEP não encontrado"); + } + + return { + cep: found.replaceAll(NON_DIGIT, ""), + state: jsonString(response.body, "uf"), + city: jsonString(response.body, "localidade"), + neighborhood: jsonString(response.body, "bairro"), + street: jsonString(response.body, "logradouro"), + }; +}; + +/** + * Reads the address Widenet answers with. + * + * @param {string} cep - The 8 digit CEP. + * @returns {AddressInfo} The address. + */ +const fetchWidenet = (cep: string): AddressInfo => { + const response: HttpResponse = httpGet( + `https://apps.widenet.com.br/busca-cep/api/cep/${cep}.json`, + HTTP_RETRIES, + HTTP_RETRY_DELAY_MS, + ); + + if (!response.ok) { + throw new CepProviderFailure("Widenet request failed"); + } + + const found = jsonString(response.body, "code"); + + if ( + jsonInt(response.body, "status") !== 200 || + !jsonIsTrue(response.body, "ok") || + found === "" + ) { + throw new GetAddressInfoByCepNotFoundError("CEP não encontrado"); + } + + return { + cep: found.replaceAll(NON_DIGIT, ""), + state: jsonString(response.body, "state"), + city: jsonString(response.body, "city"), + neighborhood: jsonString(response.body, "district"), + street: jsonString(response.body, "address"), + }; +}; + +/** + * Reads the address BrasilAPI answers with. + * + * @param {string} cep - The 8 digit CEP. + * @returns {AddressInfo} The address. + * + * @see Based on: https://brasilapi.com.br/docs#tag/CEP + */ +const fetchBrasilApi = (cep: string): AddressInfo => { + const response: HttpResponse = httpGet( + `https://brasilapi.com.br/api/cep/v1/${cep}`, + HTTP_RETRIES, + HTTP_RETRY_DELAY_MS, + ); + + if (response.status === BRASIL_API_NOT_FOUND_STATUS) { + throw new GetAddressInfoByCepNotFoundError("CEP não encontrado"); + } + + if (!response.ok) { + throw new CepProviderFailure("BrasilAPI request failed"); + } + + const found = jsonString(response.body, "cep"); + + if (jsonTruthy(response.body, "errors") || found === "") { + throw new GetAddressInfoByCepNotFoundError("CEP não encontrado"); + } + + return { + cep: found.replaceAll(NON_DIGIT, ""), + state: jsonString(response.body, "state"), + city: jsonString(response.body, "city"), + neighborhood: jsonString(response.body, "neighborhood"), + street: jsonString(response.body, "street"), + }; +}; + +/** + * Asks one named provider for a CEP. + * + * @param {CepProvider} provider - The provider name. + * @param {string} cep - The 8 digit CEP. + * @returns {AddressInfo} The address. + */ +const fetchProvider = (provider: CepProvider, cep: string): AddressInfo => { + if (provider === "viacep") { + return fetchViaCep(cep); + } + + if (provider === "widenet") { + return fetchWidenet(cep); + } + + return fetchBrasilApi(cep); +}; + +/** + * The providers of a list that are known, in the order they were given. + * + * @param {CepProvider[]} given - The names the caller asked for. + * @returns {CepProvider[]} The known ones. + */ +const knownProviders = (given: CepProvider[]): CepProvider[] => { + const kept: CepProvider[] = []; + + for (const provider of given) { + if (listHas(KNOWN_PROVIDERS, provider)) { + kept.push(provider); + } + } + + return kept; +}; + +/** + * Fetches address information for a given CEP using multiple providers simultaneously. + * Returns the result from the first provider that responds successfully. + * + * The providers are started together and raced, not tried one after the other, so a provider + * that is retrying delays nothing for the others: its retries only push back the moment its own + * failure lands, and therefore the moment an all-failed rejection can surface. + * + * @param {string|number} cep - The CEP (Brazilian postal code) to search for. Can be a string or number. + * @param {GetAddressInfoByCepOptions} options - Optional configuration for the function. + * @param {CepProvider[]} options.providers - List of providers to use. Defaults to `["viacep", "brasilapi"]` + * if not specified (the deprecated `"widenet"` provider is excluded from the default list, but can still + * be requested explicitly). + * @returns {Promise} A promise that resolves to the address information. + * @throws {GetAddressInfoByCepValidationError} If the CEP format is invalid, or if + * `options.providers` is given and names no known provider: an empty array, an array of unknown + * names, and a value that is not an array at all (`null` included) all reject this way rather + * than with a raw `TypeError`. + * @throws {GetAddressInfoByCepNotFoundError} If the CEP is not found in any of the services. + * @throws {GetAddressInfoByCepServiceError} If all services are unavailable. + * + * @example + * ```typescript + * // Using the default providers (["viacep", "brasilapi"]) + * const address = await getAddressInfoByCep("01310100"); + * + * // Using specific providers + * const address = await getAddressInfoByCep("01310-100", { + * providers: ["viacep", "brasilapi"] + * }); + * + * // Using number input + * const address = await getAddressInfoByCep(1310100); + * ``` + * + * @see Official: https://www.correios.com.br/enviar/precisa-de-ajuda/tudo-sobre-cep + * @see Based on: https://viacep.com.br/ + * ViaCEP, one of the two default providers. A third-party service, not a Correios one. + * @see Based on: https://brasilapi.com.br/docs#tag/CEP + * BrasilAPI, the other default provider. A third-party service, not a Correios one. + */ +export const getAddressInfoByCep = ( + cep: string | number, + options?: GetAddressInfoByCepOptions, +): AddressInfo => { + let digits = asString(cep).replaceAll(NON_DIGIT, ""); + + if (isNumber(cep)) { + // `padStart` is a no-op when `digits` is already 8 characters or longer. + digits = digits.padStart(8, "0"); + } + + if (!CEP_FORMAT.test(digits)) { + throw new GetAddressInfoByCepValidationError("CEP inválido"); + } + + let chosen: CepProvider[] = DEFAULT_PROVIDERS; + + if (options?.providers !== undefined) { + // A value that is not a list at all reports the same thing as a list of unknown names, + // rather than the raw `TypeError` a filter over it would raise. + if (!isList(options?.providers)) { + throw new GetAddressInfoByCepValidationError("Nenhum provedor válido especificado"); + } + + chosen = knownProviders(options?.providers); + + if (chosen.length === 0) { + throw new GetAddressInfoByCepValidationError("Nenhum provedor válido especificado"); + } + } + + const attempts = startAll(fetchProvider, chosen, digits); + const found = firstSuccess(attempts); + + if (found !== undefined) { + return found; + } + + if (anyFailedWith(attempts, GetAddressInfoByCepNotFoundError)) { + throw new GetAddressInfoByCepNotFoundError("CEP não encontrado em nenhum serviço"); + } + + throw new GetAddressInfoByCepServiceError( + "Todos os serviços estão fora de serviço ou indisponíveis", + ); +}; From 9660681c05132ab9798730185cbfe938230bf891 Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 21 Sep 2026 04:01:03 +0000 Subject: [PATCH 11/13] feat(spec): port getMunicipalities to the bridge MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The last of the four, and the one that is about data rather than logic: 5,571 municipalities per state, in the order `localeCompare(…, "pt-BR")` puts them. That order is the whole difficulty. Go and Rust ship no collator, Ruby compares bytes, and Python, Java and C# each resolve their own ICU or libc table, so sorting at run time would produce seven different answers. `data/get-municipalities.ts` resolves both orders once — the per state one and the combined one — against the JavaScript package's own comparator, and bakes them into the table every emitter materialises natively. Nothing sorts at run time. Every municipality of every key is replayed, not a sample, so one name out of place in one target fails the check. The keys include an unknown state, a lower case one, the empty string and three inherited `Object` property names, because each of those has an answer of its own. typescript 34/34 python 34/34 ruby 34/34 go 34/34 rust 34/34 java 34/34 csharp 34/34 The C ABI does not carry this one: a function that answers a list needs an iterator rather than a buffer, and it is refused rather than guessed at. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01UX1gTGeMTyoXQyr1qUoQKd --- spec/bridge/README.md | 1 + .../conformance/cases/get-municipalities.ts | 54 +++++++++ spec/bridge/data/get-municipalities.ts | 64 ++++++++++ .../source/get-municipalities.data.json | 1 + spec/bridge/source/get-municipalities.ts | 110 ++++++++++++++++++ 5 files changed, 230 insertions(+) create mode 100644 spec/bridge/conformance/cases/get-municipalities.ts create mode 100644 spec/bridge/data/get-municipalities.ts create mode 100644 spec/bridge/source/get-municipalities.data.json create mode 100644 spec/bridge/source/get-municipalities.ts diff --git a/spec/bridge/README.md b/spec/bridge/README.md index 877649391..c9263bb70 100644 --- a/spec/bridge/README.md +++ b/spec/bridge/README.md @@ -151,6 +151,7 @@ be handed it, so nothing is skipped for being inconvenient, and the count is vis | `isValidCnpj` | regular expressions, check digits, JavaScript's own type coercion | | `formatCnpj` | a shared mask helper, and three options that interact | | `getAddressInfoByCep` | HTTP, JSON, retries, an error hierarchy, three providers raced | +| `getMunicipalities` | 5,571 baked rows, and a pt-BR order no two targets agree on | ## Adding a utility diff --git a/spec/bridge/conformance/cases/get-municipalities.ts b/spec/bridge/conformance/cases/get-municipalities.ts new file mode 100644 index 000000000..74c878385 --- /dev/null +++ b/spec/bridge/conformance/cases/get-municipalities.ts @@ -0,0 +1,54 @@ +/** + * What `getMunicipalities` is replayed with: every state, and the keys that are not one. + * + * The whole list comes back per key rather than a sample, so one municipality out of order in + * one of the seven targets fails the check. That is the point of this utility being here: the + * order is pt-BR collation, and no two targets ship the same collator. + */ +import { type Recorder } from "../cases.ts"; + +/** + * The keys to ask for. Omitting the state code is the only way to ask for the combined list; + * every other value, an unknown state and an inherited `Object` property name included, has an + * answer of its own. + */ +const KEYS = [ + "AC", + "AL", + "AP", + "AM", + "BA", + "CE", + "DF", + "ES", + "GO", + "MA", + "MT", + "MS", + "MG", + "PA", + "PB", + "PR", + "PE", + "PI", + "RJ", + "RN", + "RS", + "RO", + "RR", + "SC", + "SP", + "SE", + "TO", + "ZZ", + "sp", + "", + "toString", + "constructor", + "hasOwnProperty", +]; + +export const recorder: Recorder = { + module: "get-municipalities", + inputs: () => [[], ...KEYS.map((key) => [key])], +}; diff --git a/spec/bridge/data/get-municipalities.ts b/spec/bridge/data/get-municipalities.ts new file mode 100644 index 000000000..eec489d7c --- /dev/null +++ b/spec/bridge/data/get-municipalities.ts @@ -0,0 +1,64 @@ +/** + * The municipalities table, with the pt-BR order the JavaScript package returns baked in. + * + * Two orders are resolved here: the per state one, which is the order the package already + * returns for a state, and the combined one, which is every state's rows merged and sorted by + * name with the pt-BR collator. Neither is recomputed at run time, because no two targets + * would agree on it. + */ +import { type DataDecl } from "../compiler/ir.ts"; +import { type Builder } from "./_builder.ts"; + +type Municipality = { code: string; name: string; stateCode: string }; + +export const builder: Builder = { + module: "get-municipalities", + + build: (shipped): Omit => { + const getStates = shipped["getStates"] as () => { code: string }[]; + const getMunicipalities = shipped["getMunicipalities"] as ( + stateCode?: string, + ) => Municipality[]; + + const rows: string[][] = []; + const groups: Record = {}; + + // The per state order is the order the package itself returns, already the pt-BR one. + for (const state of getStates()) { + groups[state.code] = []; + + for (const municipality of getMunicipalities(state.code)) { + groups[state.code].push(rows.length); + rows.push([municipality.stateCode, municipality.name, municipality.code]); + } + } + + // Matching the combined list by (name, code) rather than by position keeps this honest + // even if the package ever changes how it merges the states. + const byKey = new Map(); + + for (const [index, row] of rows.entries()) byKey.set(`${row[1]}\u0000${row[2]}`, index); + + const fullOrder = getMunicipalities().map((municipality) => { + const index = byKey.get(`${municipality.name}\u0000${municipality.code}`); + + if (index === undefined) + throw new Error(`the full list holds ${municipality.name} but no state does`); + + return index; + }); + + if (fullOrder.length !== rows.length) + throw new Error( + `the full list has ${fullOrder.length} rows but the states have ${rows.length}`, + ); + + return { + doc: "Brazilian municipalities published by the IBGE, by state, in the pt-BR collation order the JavaScript package returns.", + columns: ["stateCode", "name", "code"], + rows, + groups, + fullOrder, + }; + }, +}; diff --git a/spec/bridge/source/get-municipalities.data.json b/spec/bridge/source/get-municipalities.data.json new file mode 100644 index 000000000..5e3a44875 --- /dev/null +++ b/spec/bridge/source/get-municipalities.data.json @@ -0,0 +1 @@ +{"doc":"Brazilian municipalities published by the IBGE, by state, in the pt-BR collation order the JavaScript package returns.","columns":["stateCode","name","code"],"rows":[["AC","Acrelândia","1200013"],["AC","Assis Brasil","1200054"],["AC","Brasiléia","1200104"],["AC","Bujari","1200138"],["AC","Capixaba","1200179"],["AC","Cruzeiro do Sul","1200203"],["AC","Epitaciolândia","1200252"],["AC","Feijó","1200302"],["AC","Jordão","1200328"],["AC","Mâncio Lima","1200336"],["AC","Manoel Urbano","1200344"],["AC","Marechal Thaumaturgo","1200351"],["AC","Plácido de Castro","1200385"],["AC","Porto Acre","1200807"],["AC","Porto Walter","1200393"],["AC","Rio Branco","1200401"],["AC","Rodrigues Alves","1200427"],["AC","Santa Rosa do Purus","1200435"],["AC","Sena Madureira","1200500"],["AC","Senador Guiomard","1200450"],["AC","Tarauacá","1200609"],["AC","Xapuri","1200708"],["AL","Água Branca","2700102"],["AL","Anadia","2700201"],["AL","Arapiraca","2700300"],["AL","Atalaia","2700409"],["AL","Barra de Santo Antônio","2700508"],["AL","Barra de São Miguel","2700607"],["AL","Batalha","2700706"],["AL","Belém","2700805"],["AL","Belo Monte","2700904"],["AL","Boca da Mata","2701001"],["AL","Branquinha","2701100"],["AL","Cacimbinhas","2701209"],["AL","Cajueiro","2701308"],["AL","Campestre","2701357"],["AL","Campo Alegre","2701407"],["AL","Campo Grande","2701506"],["AL","Canapi","2701605"],["AL","Capela","2701704"],["AL","Carneiros","2701803"],["AL","Chã Preta","2701902"],["AL","Coité do Nóia","2702009"],["AL","Colônia Leopoldina","2702108"],["AL","Coqueiro Seco","2702207"],["AL","Coruripe","2702306"],["AL","Craíbas","2702355"],["AL","Delmiro Gouveia","2702405"],["AL","Dois Riachos","2702504"],["AL","Estrela de Alagoas","2702553"],["AL","Feira Grande","2702603"],["AL","Feliz Deserto","2702702"],["AL","Flexeiras","2702801"],["AL","Girau do Ponciano","2702900"],["AL","Ibateguara","2703007"],["AL","Igaci","2703106"],["AL","Igreja Nova","2703205"],["AL","Inhapi","2703304"],["AL","Jacaré dos Homens","2703403"],["AL","Jacuípe","2703502"],["AL","Japaratinga","2703601"],["AL","Jaramataia","2703700"],["AL","Jequiá da Praia","2703759"],["AL","Joaquim Gomes","2703809"],["AL","Jundiá","2703908"],["AL","Junqueiro","2704005"],["AL","Lagoa da Canoa","2704104"],["AL","Limoeiro de Anadia","2704203"],["AL","Maceió","2704302"],["AL","Major Isidoro","2704401"],["AL","Mar Vermelho","2704906"],["AL","Maragogi","2704500"],["AL","Maravilha","2704609"],["AL","Marechal Deodoro","2704708"],["AL","Maribondo","2704807"],["AL","Mata Grande","2705002"],["AL","Matriz de Camaragibe","2705101"],["AL","Messias","2705200"],["AL","Minador do Negrão","2705309"],["AL","Monteirópolis","2705408"],["AL","Murici","2705507"],["AL","Novo Lino","2705606"],["AL","Olho d'Água das Flores","2705705"],["AL","Olho d'Água do Casado","2705804"],["AL","Olho d'Água Grande","2705903"],["AL","Olivença","2706000"],["AL","Ouro Branco","2706109"],["AL","Palestina","2706208"],["AL","Palmeira dos Índios","2706307"],["AL","Pão de Açúcar","2706406"],["AL","Pariconha","2706422"],["AL","Paripueira","2706448"],["AL","Passo de Camaragibe","2706505"],["AL","Paulo Jacinto","2706604"],["AL","Penedo","2706703"],["AL","Piaçabuçu","2706802"],["AL","Pilar","2706901"],["AL","Pindoba","2707008"],["AL","Piranhas","2707107"],["AL","Poço das Trincheiras","2707206"],["AL","Porto Calvo","2707305"],["AL","Porto de Pedras","2707404"],["AL","Porto Real do Colégio","2707503"],["AL","Quebrangulo","2707602"],["AL","Rio Largo","2707701"],["AL","Roteiro","2707800"],["AL","Santa Luzia do Norte","2707909"],["AL","Santana do Ipanema","2708006"],["AL","Santana do Mundaú","2708105"],["AL","São Brás","2708204"],["AL","São José da Laje","2708303"],["AL","São José da Tapera","2708402"],["AL","São Luís do Quitunde","2708501"],["AL","São Miguel dos Campos","2708600"],["AL","São Miguel dos Milagres","2708709"],["AL","São Sebastião","2708808"],["AL","Satuba","2708907"],["AL","Senador Rui Palmeira","2708956"],["AL","Tanque d'Arca","2709004"],["AL","Taquarana","2709103"],["AL","Teotônio Vilela","2709152"],["AL","Traipu","2709202"],["AL","União dos Palmares","2709301"],["AL","Viçosa","2709400"],["AP","Amapá","1600105"],["AP","Calçoene","1600204"],["AP","Cutias","1600212"],["AP","Ferreira Gomes","1600238"],["AP","Itaubal","1600253"],["AP","Laranjal do Jari","1600279"],["AP","Macapá","1600303"],["AP","Mazagão","1600402"],["AP","Oiapoque","1600501"],["AP","Pedra Branca do Amapari","1600154"],["AP","Porto Grande","1600535"],["AP","Pracuúba","1600550"],["AP","Santana","1600600"],["AP","Serra do Navio","1600055"],["AP","Tartarugalzinho","1600709"],["AP","Vitória do Jari","1600808"],["AM","Alvarães","1300029"],["AM","Amaturá","1300060"],["AM","Anamã","1300086"],["AM","Anori","1300102"],["AM","Apuí","1300144"],["AM","Atalaia do Norte","1300201"],["AM","Autazes","1300300"],["AM","Barcelos","1300409"],["AM","Barreirinha","1300508"],["AM","Benjamin Constant","1300607"],["AM","Beruri","1300631"],["AM","Boa Vista do Ramos","1300680"],["AM","Boca do Acre","1300706"],["AM","Borba","1300805"],["AM","Caapiranga","1300839"],["AM","Canutama","1300904"],["AM","Carauari","1301001"],["AM","Careiro","1301100"],["AM","Careiro da Várzea","1301159"],["AM","Coari","1301209"],["AM","Codajás","1301308"],["AM","Eirunepé","1301407"],["AM","Envira","1301506"],["AM","Fonte Boa","1301605"],["AM","Guajará","1301654"],["AM","Humaitá","1301704"],["AM","Ipixuna","1301803"],["AM","Iranduba","1301852"],["AM","Itacoatiara","1301902"],["AM","Itamarati","1301951"],["AM","Itapiranga","1302009"],["AM","Japurá","1302108"],["AM","Juruá","1302207"],["AM","Jutaí","1302306"],["AM","Lábrea","1302405"],["AM","Manacapuru","1302504"],["AM","Manaquiri","1302553"],["AM","Manaus","1302603"],["AM","Manicoré","1302702"],["AM","Maraã","1302801"],["AM","Maués","1302900"],["AM","Nhamundá","1303007"],["AM","Nova Olinda do Norte","1303106"],["AM","Novo Airão","1303205"],["AM","Novo Aripuanã","1303304"],["AM","Parintins","1303403"],["AM","Pauini","1303502"],["AM","Presidente Figueiredo","1303536"],["AM","Rio Preto da Eva","1303569"],["AM","Santa Isabel do Rio Negro","1303601"],["AM","Santo Antônio do Içá","1303700"],["AM","São Gabriel da Cachoeira","1303809"],["AM","São Paulo de Olivença","1303908"],["AM","São Sebastião do Uatumã","1303957"],["AM","Silves","1304005"],["AM","Tabatinga","1304062"],["AM","Tapauá","1304104"],["AM","Tefé","1304203"],["AM","Tonantins","1304237"],["AM","Uarini","1304260"],["AM","Urucará","1304302"],["AM","Urucurituba","1304401"],["BA","Abaíra","2900108"],["BA","Abaré","2900207"],["BA","Acajutiba","2900306"],["BA","Adustina","2900355"],["BA","Água Fria","2900405"],["BA","Aiquara","2900603"],["BA","Alagoinhas","2900702"],["BA","Alcobaça","2900801"],["BA","Almadina","2900900"],["BA","Amargosa","2901007"],["BA","Amélia Rodrigues","2901106"],["BA","América Dourada","2901155"],["BA","Anagé","2901205"],["BA","Andaraí","2901304"],["BA","Andorinha","2901353"],["BA","Angical","2901403"],["BA","Anguera","2901502"],["BA","Antas","2901601"],["BA","Antônio Cardoso","2901700"],["BA","Antônio Gonçalves","2901809"],["BA","Aporá","2901908"],["BA","Apuarema","2901957"],["BA","Araçás","2902054"],["BA","Aracatu","2902005"],["BA","Araci","2902104"],["BA","Aramari","2902203"],["BA","Arataca","2902252"],["BA","Aratuípe","2902302"],["BA","Aurelino Leal","2902401"],["BA","Baianópolis","2902500"],["BA","Baixa Grande","2902609"],["BA","Banzaê","2902658"],["BA","Barra","2902708"],["BA","Barra da Estiva","2902807"],["BA","Barra do Choça","2902906"],["BA","Barra do Mendes","2903003"],["BA","Barra do Rocha","2903102"],["BA","Barreiras","2903201"],["BA","Barro Alto","2903235"],["BA","Barro Preto","2903300"],["BA","Barrocas","2903276"],["BA","Belmonte","2903409"],["BA","Belo Campo","2903508"],["BA","Biritinga","2903607"],["BA","Boa Nova","2903706"],["BA","Boa Vista do Tupim","2903805"],["BA","Bom Jesus da Lapa","2903904"],["BA","Bom Jesus da Serra","2903953"],["BA","Boninal","2904001"],["BA","Bonito","2904050"],["BA","Boquira","2904100"],["BA","Botuporã","2904209"],["BA","Brejões","2904308"],["BA","Brejolândia","2904407"],["BA","Brotas de Macaúbas","2904506"],["BA","Brumado","2904605"],["BA","Buerarema","2904704"],["BA","Buritirama","2904753"],["BA","Caatiba","2904803"],["BA","Cabaceiras do Paraguaçu","2904852"],["BA","Cachoeira","2904902"],["BA","Caculé","2905008"],["BA","Caém","2905107"],["BA","Caetanos","2905156"],["BA","Caetité","2905206"],["BA","Cafarnaum","2905305"],["BA","Cairu","2905404"],["BA","Caldeirão Grande","2905503"],["BA","Camacan","2905602"],["BA","Camaçari","2905701"],["BA","Camamu","2905800"],["BA","Campo Alegre de Lourdes","2905909"],["BA","Campo Formoso","2906006"],["BA","Canápolis","2906105"],["BA","Canarana","2906204"],["BA","Canavieiras","2906303"],["BA","Candeal","2906402"],["BA","Candeias","2906501"],["BA","Candiba","2906600"],["BA","Cândido Sales","2906709"],["BA","Cansanção","2906808"],["BA","Canudos","2906824"],["BA","Capela do Alto Alegre","2906857"],["BA","Capim Grosso","2906873"],["BA","Caraíbas","2906899"],["BA","Caravelas","2906907"],["BA","Cardeal da Silva","2907004"],["BA","Carinhanha","2907103"],["BA","Casa Nova","2907202"],["BA","Castro Alves","2907301"],["BA","Catolândia","2907400"],["BA","Catu","2907509"],["BA","Caturama","2907558"],["BA","Central","2907608"],["BA","Chorrochó","2907707"],["BA","Cícero Dantas","2907806"],["BA","Cipó","2907905"],["BA","Coaraci","2908002"],["BA","Cocos","2908101"],["BA","Conceição da Feira","2908200"],["BA","Conceição do Almeida","2908309"],["BA","Conceição do Coité","2908408"],["BA","Conceição do Jacuípe","2908507"],["BA","Conde","2908606"],["BA","Condeúba","2908705"],["BA","Contendas do Sincorá","2908804"],["BA","Coração de Maria","2908903"],["BA","Cordeiros","2909000"],["BA","Coribe","2909109"],["BA","Coronel João Sá","2909208"],["BA","Correntina","2909307"],["BA","Cotegipe","2909406"],["BA","Cravolândia","2909505"],["BA","Crisópolis","2909604"],["BA","Cristópolis","2909703"],["BA","Cruz das Almas","2909802"],["BA","Curaçá","2909901"],["BA","Dário Meira","2910008"],["BA","Dias d'Ávila","2910057"],["BA","Dom Basílio","2910107"],["BA","Dom Macedo Costa","2910206"],["BA","Elísio Medrado","2910305"],["BA","Encruzilhada","2910404"],["BA","Entre Rios","2910503"],["BA","Érico Cardoso","2900504"],["BA","Esplanada","2910602"],["BA","Euclides da Cunha","2910701"],["BA","Eunápolis","2910727"],["BA","Fátima","2910750"],["BA","Feira da Mata","2910776"],["BA","Feira de Santana","2910800"],["BA","Filadélfia","2910859"],["BA","Firmino Alves","2910909"],["BA","Floresta Azul","2911006"],["BA","Formosa do Rio Preto","2911105"],["BA","Gandu","2911204"],["BA","Gavião","2911253"],["BA","Gentio do Ouro","2911303"],["BA","Glória","2911402"],["BA","Gongogi","2911501"],["BA","Governador Mangabeira","2911600"],["BA","Guajeru","2911659"],["BA","Guanambi","2911709"],["BA","Guaratinga","2911808"],["BA","Heliópolis","2911857"],["BA","Iaçu","2911907"],["BA","Ibiassucê","2912004"],["BA","Ibicaraí","2912103"],["BA","Ibicoara","2912202"],["BA","Ibicuí","2912301"],["BA","Ibipeba","2912400"],["BA","Ibipitanga","2912509"],["BA","Ibiquera","2912608"],["BA","Ibirapitanga","2912707"],["BA","Ibirapuã","2912806"],["BA","Ibirataia","2912905"],["BA","Ibitiara","2913002"],["BA","Ibititá","2913101"],["BA","Ibotirama","2913200"],["BA","Ichu","2913309"],["BA","Igaporã","2913408"],["BA","Igrapiúna","2913457"],["BA","Iguaí","2913507"],["BA","Ilhéus","2913606"],["BA","Inhambupe","2913705"],["BA","Ipecaetá","2913804"],["BA","Ipiaú","2913903"],["BA","Ipirá","2914000"],["BA","Ipupiara","2914109"],["BA","Irajuba","2914208"],["BA","Iramaia","2914307"],["BA","Iraquara","2914406"],["BA","Irará","2914505"],["BA","Irecê","2914604"],["BA","Itabela","2914653"],["BA","Itaberaba","2914703"],["BA","Itabuna","2914802"],["BA","Itacaré","2914901"],["BA","Itaeté","2915007"],["BA","Itagi","2915106"],["BA","Itagibá","2915205"],["BA","Itagimirim","2915304"],["BA","Itaguaçu da Bahia","2915353"],["BA","Itaju do Colônia","2915403"],["BA","Itajuípe","2915502"],["BA","Itamaraju","2915601"],["BA","Itamari","2915700"],["BA","Itambé","2915809"],["BA","Itanagra","2915908"],["BA","Itanhém","2916005"],["BA","Itaparica","2916104"],["BA","Itapé","2916203"],["BA","Itapebi","2916302"],["BA","Itapetinga","2916401"],["BA","Itapicuru","2916500"],["BA","Itapitanga","2916609"],["BA","Itaquara","2916708"],["BA","Itarantim","2916807"],["BA","Itatim","2916856"],["BA","Itiruçu","2916906"],["BA","Itiúba","2917003"],["BA","Itororó","2917102"],["BA","Ituaçu","2917201"],["BA","Ituberá","2917300"],["BA","Iuiu","2917334"],["BA","Jaborandi","2917359"],["BA","Jacaraci","2917409"],["BA","Jacobina","2917508"],["BA","Jaguaquara","2917607"],["BA","Jaguarari","2917706"],["BA","Jaguaripe","2917805"],["BA","Jandaíra","2917904"],["BA","Jequié","2918001"],["BA","Jeremoabo","2918100"],["BA","Jiquiriçá","2918209"],["BA","Jitaúna","2918308"],["BA","João Dourado","2918357"],["BA","Juazeiro","2918407"],["BA","Jucuruçu","2918456"],["BA","Jussara","2918506"],["BA","Jussari","2918555"],["BA","Jussiape","2918605"],["BA","Lafaiete Coutinho","2918704"],["BA","Lagoa Real","2918753"],["BA","Laje","2918803"],["BA","Lajedão","2918902"],["BA","Lajedinho","2919009"],["BA","Lajedo do Tabocal","2919058"],["BA","Lamarão","2919108"],["BA","Lapão","2919157"],["BA","Lauro de Freitas","2919207"],["BA","Lençóis","2919306"],["BA","Licínio de Almeida","2919405"],["BA","Livramento de Nossa Senhora","2919504"],["BA","Luís Eduardo Magalhães","2919553"],["BA","Macajuba","2919603"],["BA","Macarani","2919702"],["BA","Macaúbas","2919801"],["BA","Macururé","2919900"],["BA","Madre de Deus","2919926"],["BA","Maetinga","2919959"],["BA","Maiquinique","2920007"],["BA","Mairi","2920106"],["BA","Malhada","2920205"],["BA","Malhada de Pedras","2920304"],["BA","Manoel Vitorino","2920403"],["BA","Mansidão","2920452"],["BA","Maracás","2920502"],["BA","Maragogipe","2920601"],["BA","Maraú","2920700"],["BA","Marcionílio Souza","2920809"],["BA","Mascote","2920908"],["BA","Mata de São João","2921005"],["BA","Matina","2921054"],["BA","Medeiros Neto","2921104"],["BA","Miguel Calmon","2921203"],["BA","Milagres","2921302"],["BA","Mirangaba","2921401"],["BA","Mirante","2921450"],["BA","Monte Santo","2921500"],["BA","Morpará","2921609"],["BA","Morro do Chapéu","2921708"],["BA","Mortugaba","2921807"],["BA","Mucugê","2921906"],["BA","Mucuri","2922003"],["BA","Mulungu do Morro","2922052"],["BA","Mundo Novo","2922102"],["BA","Muniz Ferreira","2922201"],["BA","Muquém do São Francisco","2922250"],["BA","Muritiba","2922300"],["BA","Mutuípe","2922409"],["BA","Nazaré","2922508"],["BA","Nilo Peçanha","2922607"],["BA","Nordestina","2922656"],["BA","Nova Canaã","2922706"],["BA","Nova Fátima","2922730"],["BA","Nova Ibiá","2922755"],["BA","Nova Itarana","2922805"],["BA","Nova Redenção","2922854"],["BA","Nova Soure","2922904"],["BA","Nova Viçosa","2923001"],["BA","Novo Horizonte","2923035"],["BA","Novo Triunfo","2923050"],["BA","Olindina","2923100"],["BA","Oliveira dos Brejinhos","2923209"],["BA","Ouriçangas","2923308"],["BA","Ourolândia","2923357"],["BA","Palmas de Monte Alto","2923407"],["BA","Palmeiras","2923506"],["BA","Paramirim","2923605"],["BA","Paratinga","2923704"],["BA","Paripiranga","2923803"],["BA","Pau Brasil","2923902"],["BA","Paulo Afonso","2924009"],["BA","Pé de Serra","2924058"],["BA","Pedrão","2924108"],["BA","Pedro Alexandre","2924207"],["BA","Piatã","2924306"],["BA","Pilão Arcado","2924405"],["BA","Pindaí","2924504"],["BA","Pindobaçu","2924603"],["BA","Pintadas","2924652"],["BA","Piraí do Norte","2924678"],["BA","Piripá","2924702"],["BA","Piritiba","2924801"],["BA","Planaltino","2924900"],["BA","Planalto","2925006"],["BA","Poções","2925105"],["BA","Pojuca","2925204"],["BA","Ponto Novo","2925253"],["BA","Porto Seguro","2925303"],["BA","Potiraguá","2925402"],["BA","Prado","2925501"],["BA","Presidente Dutra","2925600"],["BA","Presidente Jânio Quadros","2925709"],["BA","Presidente Tancredo Neves","2925758"],["BA","Queimadas","2925808"],["BA","Quijingue","2925907"],["BA","Quixabeira","2925931"],["BA","Rafael Jambeiro","2925956"],["BA","Remanso","2926004"],["BA","Retirolândia","2926103"],["BA","Riachão das Neves","2926202"],["BA","Riachão do Jacuípe","2926301"],["BA","Riacho de Santana","2926400"],["BA","Ribeira do Amparo","2926509"],["BA","Ribeira do Pombal","2926608"],["BA","Ribeirão do Largo","2926657"],["BA","Rio de Contas","2926707"],["BA","Rio do Antônio","2926806"],["BA","Rio do Pires","2926905"],["BA","Rio Real","2927002"],["BA","Rodelas","2927101"],["BA","Ruy Barbosa","2927200"],["BA","Salinas da Margarida","2927309"],["BA","Salvador","2927408"],["BA","Santa Bárbara","2927507"],["BA","Santa Brígida","2927606"],["BA","Santa Cruz Cabrália","2927705"],["BA","Santa Cruz da Vitória","2927804"],["BA","Santa Inês","2927903"],["BA","Santa Luzia","2928059"],["BA","Santa Maria da Vitória","2928109"],["BA","Santa Rita de Cássia","2928406"],["BA","Santa Terezinha","2928505"],["BA","Santaluz","2928000"],["BA","Santana","2928208"],["BA","Santanópolis","2928307"],["BA","Santo Amaro","2928604"],["BA","Santo Antônio de Jesus","2928703"],["BA","Santo Estêvão","2928802"],["BA","São Desidério","2928901"],["BA","São Domingos","2928950"],["BA","São Felipe","2929107"],["BA","São Félix","2929008"],["BA","São Félix do Coribe","2929057"],["BA","São Francisco do Conde","2929206"],["BA","São Gabriel","2929255"],["BA","São Gonçalo dos Campos","2929305"],["BA","São José da Vitória","2929354"],["BA","São José do Jacuípe","2929370"],["BA","São Miguel das Matas","2929404"],["BA","São Sebastião do Passé","2929503"],["BA","Sapeaçu","2929602"],["BA","Sátiro Dias","2929701"],["BA","Saubara","2929750"],["BA","Saúde","2929800"],["BA","Seabra","2929909"],["BA","Sebastião Laranjeiras","2930006"],["BA","Senhor do Bonfim","2930105"],["BA","Sento Sé","2930204"],["BA","Serra do Ramalho","2930154"],["BA","Serra Dourada","2930303"],["BA","Serra Preta","2930402"],["BA","Serrinha","2930501"],["BA","Serrolândia","2930600"],["BA","Simões Filho","2930709"],["BA","Sítio do Mato","2930758"],["BA","Sítio do Quinto","2930766"],["BA","Sobradinho","2930774"],["BA","Souto Soares","2930808"],["BA","Tabocas do Brejo Velho","2930907"],["BA","Tanhaçu","2931004"],["BA","Tanque Novo","2931053"],["BA","Tanquinho","2931103"],["BA","Taperoá","2931202"],["BA","Tapiramutá","2931301"],["BA","Teixeira de Freitas","2931350"],["BA","Teodoro Sampaio","2931400"],["BA","Teofilândia","2931509"],["BA","Teolândia","2931608"],["BA","Terra Nova","2931707"],["BA","Tremedal","2931806"],["BA","Tucano","2931905"],["BA","Uauá","2932002"],["BA","Ubaíra","2932101"],["BA","Ubaitaba","2932200"],["BA","Ubatã","2932309"],["BA","Uibaí","2932408"],["BA","Umburanas","2932457"],["BA","Una","2932507"],["BA","Urandi","2932606"],["BA","Uruçuca","2932705"],["BA","Utinga","2932804"],["BA","Valença","2932903"],["BA","Valente","2933000"],["BA","Várzea da Roça","2933059"],["BA","Várzea do Poço","2933109"],["BA","Várzea Nova","2933158"],["BA","Varzedo","2933174"],["BA","Vera Cruz","2933208"],["BA","Vereda","2933257"],["BA","Vitória da Conquista","2933307"],["BA","Wagner","2933406"],["BA","Wanderley","2933455"],["BA","Wenceslau Guimarães","2933505"],["BA","Xique-Xique","2933604"],["CE","Abaiara","2300101"],["CE","Acarape","2300150"],["CE","Acaraú","2300200"],["CE","Acopiara","2300309"],["CE","Aiuaba","2300408"],["CE","Alcântaras","2300507"],["CE","Altaneira","2300606"],["CE","Alto Santo","2300705"],["CE","Amontada","2300754"],["CE","Antonina do Norte","2300804"],["CE","Apuiarés","2300903"],["CE","Aquiraz","2301000"],["CE","Aracati","2301109"],["CE","Aracoiaba","2301208"],["CE","Ararendá","2301257"],["CE","Araripe","2301307"],["CE","Aratuba","2301406"],["CE","Arneiroz","2301505"],["CE","Assaré","2301604"],["CE","Aurora","2301703"],["CE","Baixio","2301802"],["CE","Banabuiú","2301851"],["CE","Barbalha","2301901"],["CE","Barreira","2301950"],["CE","Barro","2302008"],["CE","Barroquinha","2302057"],["CE","Baturité","2302107"],["CE","Beberibe","2302206"],["CE","Bela Cruz","2302305"],["CE","Boa Viagem","2302404"],["CE","Brejo Santo","2302503"],["CE","Camocim","2302602"],["CE","Campos Sales","2302701"],["CE","Canindé","2302800"],["CE","Capistrano","2302909"],["CE","Caridade","2303006"],["CE","Cariré","2303105"],["CE","Caririaçu","2303204"],["CE","Cariús","2303303"],["CE","Carnaubal","2303402"],["CE","Cascavel","2303501"],["CE","Catarina","2303600"],["CE","Catunda","2303659"],["CE","Caucaia","2303709"],["CE","Cedro","2303808"],["CE","Chaval","2303907"],["CE","Choró","2303931"],["CE","Chorozinho","2303956"],["CE","Coreaú","2304004"],["CE","Crateús","2304103"],["CE","Crato","2304202"],["CE","Croatá","2304236"],["CE","Cruz","2304251"],["CE","Deputado Irapuan Pinheiro","2304269"],["CE","Ereré","2304277"],["CE","Eusébio","2304285"],["CE","Farias Brito","2304301"],["CE","Forquilha","2304350"],["CE","Fortaleza","2304400"],["CE","Fortim","2304459"],["CE","Frecheirinha","2304509"],["CE","General Sampaio","2304608"],["CE","Graça","2304657"],["CE","Granja","2304707"],["CE","Granjeiro","2304806"],["CE","Groaíras","2304905"],["CE","Guaiúba","2304954"],["CE","Guaraciaba do Norte","2305001"],["CE","Guaramiranga","2305100"],["CE","Hidrolândia","2305209"],["CE","Horizonte","2305233"],["CE","Ibaretama","2305266"],["CE","Ibiapina","2305308"],["CE","Ibicuitinga","2305332"],["CE","Icapuí","2305357"],["CE","Icó","2305407"],["CE","Iguatu","2305506"],["CE","Independência","2305605"],["CE","Ipaporanga","2305654"],["CE","Ipaumirim","2305704"],["CE","Ipu","2305803"],["CE","Ipueiras","2305902"],["CE","Iracema","2306009"],["CE","Irauçuba","2306108"],["CE","Itaiçaba","2306207"],["CE","Itaitinga","2306256"],["CE","Itapajé","2306306"],["CE","Itapipoca","2306405"],["CE","Itapiúna","2306504"],["CE","Itarema","2306553"],["CE","Itatira","2306603"],["CE","Jaguaretama","2306702"],["CE","Jaguaribara","2306801"],["CE","Jaguaribe","2306900"],["CE","Jaguaruana","2307007"],["CE","Jardim","2307106"],["CE","Jati","2307205"],["CE","Jijoca de Jericoacoara","2307254"],["CE","Juazeiro do Norte","2307304"],["CE","Jucás","2307403"],["CE","Lavras da Mangabeira","2307502"],["CE","Limoeiro do Norte","2307601"],["CE","Madalena","2307635"],["CE","Maracanaú","2307650"],["CE","Maranguape","2307700"],["CE","Marco","2307809"],["CE","Martinópole","2307908"],["CE","Massapê","2308005"],["CE","Mauriti","2308104"],["CE","Meruoca","2308203"],["CE","Milagres","2308302"],["CE","Milhã","2308351"],["CE","Miraíma","2308377"],["CE","Missão Velha","2308401"],["CE","Mombaça","2308500"],["CE","Monsenhor Tabosa","2308609"],["CE","Morada Nova","2308708"],["CE","Moraújo","2308807"],["CE","Morrinhos","2308906"],["CE","Mucambo","2309003"],["CE","Mulungu","2309102"],["CE","Nova Olinda","2309201"],["CE","Nova Russas","2309300"],["CE","Novo Oriente","2309409"],["CE","Ocara","2309458"],["CE","Orós","2309508"],["CE","Pacajus","2309607"],["CE","Pacatuba","2309706"],["CE","Pacoti","2309805"],["CE","Pacujá","2309904"],["CE","Palhano","2310001"],["CE","Palmácia","2310100"],["CE","Paracuru","2310209"],["CE","Paraipaba","2310258"],["CE","Parambu","2310308"],["CE","Paramoti","2310407"],["CE","Pedra Branca","2310506"],["CE","Penaforte","2310605"],["CE","Pentecoste","2310704"],["CE","Pereiro","2310803"],["CE","Pindoretama","2310852"],["CE","Piquet Carneiro","2310902"],["CE","Pires Ferreira","2310951"],["CE","Poranga","2311009"],["CE","Porteiras","2311108"],["CE","Potengi","2311207"],["CE","Potiretama","2311231"],["CE","Quiterianópolis","2311264"],["CE","Quixadá","2311306"],["CE","Quixelô","2311355"],["CE","Quixeramobim","2311405"],["CE","Quixeré","2311504"],["CE","Redenção","2311603"],["CE","Reriutaba","2311702"],["CE","Russas","2311801"],["CE","Saboeiro","2311900"],["CE","Salitre","2311959"],["CE","Santa Quitéria","2312205"],["CE","Santana do Acaraú","2312007"],["CE","Santana do Cariri","2312106"],["CE","São Benedito","2312304"],["CE","São Gonçalo do Amarante","2312403"],["CE","São João do Jaguaribe","2312502"],["CE","São Luís do Curu","2312601"],["CE","Senador Pompeu","2312700"],["CE","Senador Sá","2312809"],["CE","Sobral","2312908"],["CE","Solonópole","2313005"],["CE","Tabuleiro do Norte","2313104"],["CE","Tamboril","2313203"],["CE","Tarrafas","2313252"],["CE","Tauá","2313302"],["CE","Tejuçuoca","2313351"],["CE","Tianguá","2313401"],["CE","Trairi","2313500"],["CE","Tururu","2313559"],["CE","Ubajara","2313609"],["CE","Umari","2313708"],["CE","Umirim","2313757"],["CE","Uruburetama","2313807"],["CE","Uruoca","2313906"],["CE","Varjota","2313955"],["CE","Várzea Alegre","2314003"],["CE","Viçosa do Ceará","2314102"],["DF","Brasília","5300108"],["ES","Afonso Cláudio","3200102"],["ES","Água Doce do Norte","3200169"],["ES","Águia Branca","3200136"],["ES","Alegre","3200201"],["ES","Alfredo Chaves","3200300"],["ES","Alto Rio Novo","3200359"],["ES","Anchieta","3200409"],["ES","Apiacá","3200508"],["ES","Aracruz","3200607"],["ES","Atílio Vivácqua","3200706"],["ES","Baixo Guandu","3200805"],["ES","Barra de São Francisco","3200904"],["ES","Boa Esperança","3201001"],["ES","Bom Jesus do Norte","3201100"],["ES","Brejetuba","3201159"],["ES","Cachoeiro de Itapemirim","3201209"],["ES","Cariacica","3201308"],["ES","Castelo","3201407"],["ES","Colatina","3201506"],["ES","Conceição da Barra","3201605"],["ES","Conceição do Castelo","3201704"],["ES","Divino de São Lourenço","3201803"],["ES","Domingos Martins","3201902"],["ES","Dores do Rio Preto","3202009"],["ES","Ecoporanga","3202108"],["ES","Fundão","3202207"],["ES","Governador Lindenberg","3202256"],["ES","Guaçuí","3202306"],["ES","Guarapari","3202405"],["ES","Ibatiba","3202454"],["ES","Ibiraçu","3202504"],["ES","Ibitirama","3202553"],["ES","Iconha","3202603"],["ES","Irupi","3202652"],["ES","Itaguaçu","3202702"],["ES","Itapemirim","3202801"],["ES","Itarana","3202900"],["ES","Iúna","3203007"],["ES","Jaguaré","3203056"],["ES","Jerônimo Monteiro","3203106"],["ES","João Neiva","3203130"],["ES","Laranja da Terra","3203163"],["ES","Linhares","3203205"],["ES","Mantenópolis","3203304"],["ES","Marataízes","3203320"],["ES","Marechal Floriano","3203346"],["ES","Marilândia","3203353"],["ES","Mimoso do Sul","3203403"],["ES","Montanha","3203502"],["ES","Mucurici","3203601"],["ES","Muniz Freire","3203700"],["ES","Muqui","3203809"],["ES","Nova Venécia","3203908"],["ES","Pancas","3204005"],["ES","Pedro Canário","3204054"],["ES","Pinheiros","3204104"],["ES","Piúma","3204203"],["ES","Ponto Belo","3204252"],["ES","Presidente Kennedy","3204302"],["ES","Rio Bananal","3204351"],["ES","Rio Novo do Sul","3204401"],["ES","Santa Leopoldina","3204500"],["ES","Santa Maria de Jetibá","3204559"],["ES","Santa Teresa","3204609"],["ES","São Domingos do Norte","3204658"],["ES","São Gabriel da Palha","3204708"],["ES","São José do Calçado","3204807"],["ES","São Mateus","3204906"],["ES","São Roque do Canaã","3204955"],["ES","Serra","3205002"],["ES","Sooretama","3205010"],["ES","Vargem Alta","3205036"],["ES","Venda Nova do Imigrante","3205069"],["ES","Viana","3205101"],["ES","Vila Pavão","3205150"],["ES","Vila Valério","3205176"],["ES","Vila Velha","3205200"],["ES","Vitória","3205309"],["GO","Abadia de Goiás","5200050"],["GO","Abadiânia","5200100"],["GO","Acreúna","5200134"],["GO","Adelândia","5200159"],["GO","Água Fria de Goiás","5200175"],["GO","Água Limpa","5200209"],["GO","Águas Lindas de Goiás","5200258"],["GO","Alexânia","5200308"],["GO","Aloândia","5200506"],["GO","Alto Horizonte","5200555"],["GO","Alto Paraíso de Goiás","5200605"],["GO","Alvorada do Norte","5200803"],["GO","Amaralina","5200829"],["GO","Americano do Brasil","5200852"],["GO","Amorinópolis","5200902"],["GO","Anápolis","5201108"],["GO","Anhanguera","5201207"],["GO","Anicuns","5201306"],["GO","Aparecida de Goiânia","5201405"],["GO","Aparecida do Rio Doce","5201454"],["GO","Aporé","5201504"],["GO","Araçu","5201603"],["GO","Aragarças","5201702"],["GO","Aragoiânia","5201801"],["GO","Araguapaz","5202155"],["GO","Arenópolis","5202353"],["GO","Aruanã","5202502"],["GO","Aurilândia","5202601"],["GO","Avelinópolis","5202809"],["GO","Baliza","5203104"],["GO","Barro Alto","5203203"],["GO","Bela Vista de Goiás","5203302"],["GO","Bom Jardim de Goiás","5203401"],["GO","Bom Jesus de Goiás","5203500"],["GO","Bonfinópolis","5203559"],["GO","Bonópolis","5203575"],["GO","Brazabrantes","5203609"],["GO","Britânia","5203807"],["GO","Buriti Alegre","5203906"],["GO","Buriti de Goiás","5203939"],["GO","Buritinópolis","5203962"],["GO","Cabeceiras","5204003"],["GO","Cachoeira Alta","5204102"],["GO","Cachoeira de Goiás","5204201"],["GO","Cachoeira Dourada","5204250"],["GO","Caçu","5204300"],["GO","Caiapônia","5204409"],["GO","Caldas Novas","5204508"],["GO","Caldazinha","5204557"],["GO","Campestre de Goiás","5204607"],["GO","Campinaçu","5204656"],["GO","Campinorte","5204706"],["GO","Campo Alegre de Goiás","5204805"],["GO","Campo Limpo de Goiás","5204854"],["GO","Campos Belos","5204904"],["GO","Campos Verdes","5204953"],["GO","Carmo do Rio Verde","5205000"],["GO","Castelândia","5205059"],["GO","Catalão","5205109"],["GO","Caturaí","5205208"],["GO","Cavalcante","5205307"],["GO","Ceres","5205406"],["GO","Cezarina","5205455"],["GO","Chapadão do Céu","5205471"],["GO","Cidade Ocidental","5205497"],["GO","Cocalzinho de Goiás","5205513"],["GO","Colinas do Sul","5205521"],["GO","Córrego do Ouro","5205703"],["GO","Corumbá de Goiás","5205802"],["GO","Corumbaíba","5205901"],["GO","Cristalina","5206206"],["GO","Cristianópolis","5206305"],["GO","Crixás","5206404"],["GO","Cromínia","5206503"],["GO","Cumari","5206602"],["GO","Damianópolis","5206701"],["GO","Damolândia","5206800"],["GO","Davinópolis","5206909"],["GO","Diorama","5207105"],["GO","Divinópolis de Goiás","5208301"],["GO","Doverlândia","5207253"],["GO","Edealina","5207352"],["GO","Edéia","5207402"],["GO","Estrela do Norte","5207501"],["GO","Faina","5207535"],["GO","Fazenda Nova","5207600"],["GO","Firminópolis","5207808"],["GO","Flores de Goiás","5207907"],["GO","Formosa","5208004"],["GO","Formoso","5208103"],["GO","Gameleira de Goiás","5208152"],["GO","Goianápolis","5208400"],["GO","Goiandira","5208509"],["GO","Goianésia","5208608"],["GO","Goiânia","5208707"],["GO","Goianira","5208806"],["GO","Goiás","5208905"],["GO","Goiatuba","5209101"],["GO","Gouvelândia","5209150"],["GO","Guapó","5209200"],["GO","Guaraíta","5209291"],["GO","Guarani de Goiás","5209408"],["GO","Guarinos","5209457"],["GO","Heitoraí","5209606"],["GO","Hidrolândia","5209705"],["GO","Hidrolina","5209804"],["GO","Iaciara","5209903"],["GO","Inaciolândia","5209937"],["GO","Indiara","5209952"],["GO","Inhumas","5210000"],["GO","Ipameri","5210109"],["GO","Ipiranga de Goiás","5210158"],["GO","Iporá","5210208"],["GO","Israelândia","5210307"],["GO","Itaberaí","5210406"],["GO","Itaguari","5210562"],["GO","Itaguaru","5210604"],["GO","Itajá","5210802"],["GO","Itapaci","5210901"],["GO","Itapirapuã","5211008"],["GO","Itapuranga","5211206"],["GO","Itarumã","5211305"],["GO","Itauçu","5211404"],["GO","Itumbiara","5211503"],["GO","Ivolândia","5211602"],["GO","Jandaia","5211701"],["GO","Jaraguá","5211800"],["GO","Jataí","5211909"],["GO","Jaupaci","5212006"],["GO","Jesúpolis","5212055"],["GO","Joviânia","5212105"],["GO","Jussara","5212204"],["GO","Lagoa Santa","5212253"],["GO","Leopoldo de Bulhões","5212303"],["GO","Luziânia","5212501"],["GO","Mairipotaba","5212600"],["GO","Mambaí","5212709"],["GO","Mara Rosa","5212808"],["GO","Marzagão","5212907"],["GO","Matrinchã","5212956"],["GO","Maurilândia","5213004"],["GO","Mimoso de Goiás","5213053"],["GO","Minaçu","5213087"],["GO","Mineiros","5213103"],["GO","Moiporá","5213400"],["GO","Monte Alegre de Goiás","5213509"],["GO","Montes Claros de Goiás","5213707"],["GO","Montividiu","5213756"],["GO","Montividiu do Norte","5213772"],["GO","Morrinhos","5213806"],["GO","Morro Agudo de Goiás","5213855"],["GO","Mossâmedes","5213905"],["GO","Mozarlândia","5214002"],["GO","Mundo Novo","5214051"],["GO","Mutunópolis","5214101"],["GO","Nazário","5214408"],["GO","Nerópolis","5214507"],["GO","Niquelândia","5214606"],["GO","Nova América","5214705"],["GO","Nova Aurora","5214804"],["GO","Nova Crixás","5214838"],["GO","Nova Glória","5214861"],["GO","Nova Iguaçu de Goiás","5214879"],["GO","Nova Roma","5214903"],["GO","Nova Veneza","5215009"],["GO","Novo Brasil","5215207"],["GO","Novo Gama","5215231"],["GO","Novo Planalto","5215256"],["GO","Orizona","5215306"],["GO","Ouro Verde de Goiás","5215405"],["GO","Ouvidor","5215504"],["GO","Padre Bernardo","5215603"],["GO","Palestina de Goiás","5215652"],["GO","Palmeiras de Goiás","5215702"],["GO","Palmelo","5215801"],["GO","Palminópolis","5215900"],["GO","Panamá","5216007"],["GO","Paranaiguara","5216304"],["GO","Paraúna","5216403"],["GO","Perolândia","5216452"],["GO","Petrolina de Goiás","5216809"],["GO","Pilar de Goiás","5216908"],["GO","Piracanjuba","5217104"],["GO","Piranhas","5217203"],["GO","Pirenópolis","5217302"],["GO","Pires do Rio","5217401"],["GO","Planaltina","5217609"],["GO","Pontalina","5217708"],["GO","Porangatu","5218003"],["GO","Porteirão","5218052"],["GO","Portelândia","5218102"],["GO","Posse","5218300"],["GO","Professor Jamil","5218391"],["GO","Quirinópolis","5218508"],["GO","Rialma","5218607"],["GO","Rianápolis","5218706"],["GO","Rio Quente","5218789"],["GO","Rio Verde","5218805"],["GO","Rubiataba","5218904"],["GO","Sanclerlândia","5219001"],["GO","Santa Bárbara de Goiás","5219100"],["GO","Santa Cruz de Goiás","5219209"],["GO","Santa Fé de Goiás","5219258"],["GO","Santa Helena de Goiás","5219308"],["GO","Santa Isabel","5219357"],["GO","Santa Rita do Araguaia","5219407"],["GO","Santa Rita do Novo Destino","5219456"],["GO","Santa Rosa de Goiás","5219506"],["GO","Santa Tereza de Goiás","5219605"],["GO","Santa Terezinha de Goiás","5219704"],["GO","Santo Antônio da Barra","5219712"],["GO","Santo Antônio de Goiás","5219738"],["GO","Santo Antônio do Descoberto","5219753"],["GO","São Domingos","5219803"],["GO","São Francisco de Goiás","5219902"],["GO","São João d'Aliança","5220009"],["GO","São João da Paraúna","5220058"],["GO","São Luís de Montes Belos","5220108"],["GO","São Luiz do Norte","5220157"],["GO","São Miguel do Araguaia","5220207"],["GO","São Miguel do Passa Quatro","5220264"],["GO","São Patrício","5220280"],["GO","São Simão","5220405"],["GO","Senador Canedo","5220454"],["GO","Serranópolis","5220504"],["GO","Silvânia","5220603"],["GO","Simolândia","5220686"],["GO","Sítio d'Abadia","5220702"],["GO","Taquaral de Goiás","5221007"],["GO","Teresina de Goiás","5221080"],["GO","Terezópolis de Goiás","5221197"],["GO","Três Ranchos","5221304"],["GO","Trindade","5221403"],["GO","Trombas","5221452"],["GO","Turvânia","5221502"],["GO","Turvelândia","5221551"],["GO","Uirapuru","5221577"],["GO","Uruaçu","5221601"],["GO","Uruana","5221700"],["GO","Urutaí","5221809"],["GO","Valparaíso de Goiás","5221858"],["GO","Varjão","5221908"],["GO","Vianópolis","5222005"],["GO","Vicentinópolis","5222054"],["GO","Vila Boa","5222203"],["GO","Vila Propício","5222302"],["MA","Açailândia","2100055"],["MA","Afonso Cunha","2100105"],["MA","Água Doce do Maranhão","2100154"],["MA","Alcântara","2100204"],["MA","Aldeias Altas","2100303"],["MA","Altamira do Maranhão","2100402"],["MA","Alto Alegre do Maranhão","2100436"],["MA","Alto Alegre do Pindaré","2100477"],["MA","Alto Parnaíba","2100501"],["MA","Amapá do Maranhão","2100550"],["MA","Amarante do Maranhão","2100600"],["MA","Anajatuba","2100709"],["MA","Anapurus","2100808"],["MA","Apicum-Açu","2100832"],["MA","Araguanã","2100873"],["MA","Araioses","2100907"],["MA","Arame","2100956"],["MA","Arari","2101004"],["MA","Axixá","2101103"],["MA","Bacabal","2101202"],["MA","Bacabeira","2101251"],["MA","Bacuri","2101301"],["MA","Bacurituba","2101350"],["MA","Balsas","2101400"],["MA","Barão de Grajaú","2101509"],["MA","Barra do Corda","2101608"],["MA","Barreirinhas","2101707"],["MA","Bela Vista do Maranhão","2101772"],["MA","Belágua","2101731"],["MA","Benedito Leite","2101806"],["MA","Bequimão","2101905"],["MA","Bernardo do Mearim","2101939"],["MA","Boa Vista do Gurupi","2101970"],["MA","Bom Jardim","2102002"],["MA","Bom Jesus das Selvas","2102036"],["MA","Bom Lugar","2102077"],["MA","Brejo","2102101"],["MA","Brejo de Areia","2102150"],["MA","Buriti","2102200"],["MA","Buriti Bravo","2102309"],["MA","Buriticupu","2102325"],["MA","Buritirana","2102358"],["MA","Cachoeira Grande","2102374"],["MA","Cajapió","2102408"],["MA","Cajari","2102507"],["MA","Campestre do Maranhão","2102556"],["MA","Cândido Mendes","2102606"],["MA","Cantanhede","2102705"],["MA","Capinzal do Norte","2102754"],["MA","Carolina","2102804"],["MA","Carutapera","2102903"],["MA","Caxias","2103000"],["MA","Cedral","2103109"],["MA","Central do Maranhão","2103125"],["MA","Centro do Guilherme","2103158"],["MA","Centro Novo do Maranhão","2103174"],["MA","Chapadinha","2103208"],["MA","Cidelândia","2103257"],["MA","Codó","2103307"],["MA","Coelho Neto","2103406"],["MA","Colinas","2103505"],["MA","Conceição do Lago-Açu","2103554"],["MA","Coroatá","2103604"],["MA","Cururupu","2103703"],["MA","Davinópolis","2103752"],["MA","Dom Pedro","2103802"],["MA","Duque Bacelar","2103901"],["MA","Esperantinópolis","2104008"],["MA","Estreito","2104057"],["MA","Feira Nova do Maranhão","2104073"],["MA","Fernando Falcão","2104081"],["MA","Formosa da Serra Negra","2104099"],["MA","Fortaleza dos Nogueiras","2104107"],["MA","Fortuna","2104206"],["MA","Godofredo Viana","2104305"],["MA","Gonçalves Dias","2104404"],["MA","Governador Archer","2104503"],["MA","Governador Edison Lobão","2104552"],["MA","Governador Eugênio Barros","2104602"],["MA","Governador Luiz Rocha","2104628"],["MA","Governador Newton Bello","2104651"],["MA","Governador Nunes Freire","2104677"],["MA","Graça Aranha","2104701"],["MA","Grajaú","2104800"],["MA","Guimarães","2104909"],["MA","Humberto de Campos","2105005"],["MA","Icatu","2105104"],["MA","Igarapé do Meio","2105153"],["MA","Igarapé Grande","2105203"],["MA","Imperatriz","2105302"],["MA","Itaipava do Grajaú","2105351"],["MA","Itapecuru Mirim","2105401"],["MA","Itinga do Maranhão","2105427"],["MA","Jatobá","2105450"],["MA","Jenipapo dos Vieiras","2105476"],["MA","João Lisboa","2105500"],["MA","Joselândia","2105609"],["MA","Junco do Maranhão","2105658"],["MA","Lago da Pedra","2105708"],["MA","Lago do Junco","2105807"],["MA","Lago dos Rodrigues","2105948"],["MA","Lago Verde","2105906"],["MA","Lagoa do Mato","2105922"],["MA","Lagoa Grande do Maranhão","2105963"],["MA","Lajeado Novo","2105989"],["MA","Lima Campos","2106003"],["MA","Loreto","2106102"],["MA","Luís Domingues","2106201"],["MA","Magalhães de Almeida","2106300"],["MA","Maracaçumé","2106326"],["MA","Marajá do Sena","2106359"],["MA","Maranhãozinho","2106375"],["MA","Mata Roma","2106409"],["MA","Matinha","2106508"],["MA","Matões","2106607"],["MA","Matões do Norte","2106631"],["MA","Milagres do Maranhão","2106672"],["MA","Mirador","2106706"],["MA","Miranda do Norte","2106755"],["MA","Mirinzal","2106805"],["MA","Monção","2106904"],["MA","Montes Altos","2107001"],["MA","Morros","2107100"],["MA","Nina Rodrigues","2107209"],["MA","Nova Colinas","2107258"],["MA","Nova Iorque","2107308"],["MA","Nova Olinda do Maranhão","2107357"],["MA","Olho d'Água das Cunhãs","2107407"],["MA","Olinda Nova do Maranhão","2107456"],["MA","Paço do Lumiar","2107506"],["MA","Palmeirândia","2107605"],["MA","Paraibano","2107704"],["MA","Parnarama","2107803"],["MA","Passagem Franca","2107902"],["MA","Pastos Bons","2108009"],["MA","Paulino Neves","2108058"],["MA","Paulo Ramos","2108108"],["MA","Pedreiras","2108207"],["MA","Pedro do Rosário","2108256"],["MA","Penalva","2108306"],["MA","Peri Mirim","2108405"],["MA","Peritoró","2108454"],["MA","Pindaré-Mirim","2108504"],["MA","Pinheiro","2108603"],["MA","Pio XII","2108702"],["MA","Pirapemas","2108801"],["MA","Poção de Pedras","2108900"],["MA","Porto Franco","2109007"],["MA","Porto Rico do Maranhão","2109056"],["MA","Presidente Dutra","2109106"],["MA","Presidente Juscelino","2109205"],["MA","Presidente Médici","2109239"],["MA","Presidente Sarney","2109270"],["MA","Presidente Vargas","2109304"],["MA","Primeira Cruz","2109403"],["MA","Raposa","2109452"],["MA","Riachão","2109502"],["MA","Ribamar Fiquene","2109551"],["MA","Rosário","2109601"],["MA","Sambaíba","2109700"],["MA","Santa Filomena do Maranhão","2109759"],["MA","Santa Helena","2109809"],["MA","Santa Inês","2109908"],["MA","Santa Luzia","2110005"],["MA","Santa Luzia do Paruá","2110039"],["MA","Santa Quitéria do Maranhão","2110104"],["MA","Santa Rita","2110203"],["MA","Santana do Maranhão","2110237"],["MA","Santo Amaro do Maranhão","2110278"],["MA","Santo Antônio dos Lopes","2110302"],["MA","São Benedito do Rio Preto","2110401"],["MA","São Bento","2110500"],["MA","São Bernardo","2110609"],["MA","São Domingos do Azeitão","2110658"],["MA","São Domingos do Maranhão","2110708"],["MA","São Félix de Balsas","2110807"],["MA","São Francisco do Brejão","2110856"],["MA","São Francisco do Maranhão","2110906"],["MA","São João Batista","2111003"],["MA","São João do Carú","2111029"],["MA","São João do Paraíso","2111052"],["MA","São João do Soter","2111078"],["MA","São João dos Patos","2111102"],["MA","São José de Ribamar","2111201"],["MA","São José dos Basílios","2111250"],["MA","São Luís","2111300"],["MA","São Luís Gonzaga do Maranhão","2111409"],["MA","São Mateus do Maranhão","2111508"],["MA","São Pedro da Água Branca","2111532"],["MA","São Pedro dos Crentes","2111573"],["MA","São Raimundo das Mangabeiras","2111607"],["MA","São Raimundo do Doca Bezerra","2111631"],["MA","São Roberto","2111672"],["MA","São Vicente Ferrer","2111706"],["MA","Satubinha","2111722"],["MA","Senador Alexandre Costa","2111748"],["MA","Senador La Rocque","2111763"],["MA","Serrano do Maranhão","2111789"],["MA","Sítio Novo","2111805"],["MA","Sucupira do Norte","2111904"],["MA","Sucupira do Riachão","2111953"],["MA","Tasso Fragoso","2112001"],["MA","Timbiras","2112100"],["MA","Timon","2112209"],["MA","Trizidela do Vale","2112233"],["MA","Tufilândia","2112274"],["MA","Tuntum","2112308"],["MA","Turiaçu","2112407"],["MA","Turilândia","2112456"],["MA","Tutóia","2112506"],["MA","Urbano Santos","2112605"],["MA","Vargem Grande","2112704"],["MA","Viana","2112803"],["MA","Vila Nova dos Martírios","2112852"],["MA","Vitória do Mearim","2112902"],["MA","Vitorino Freire","2113009"],["MA","Zé Doca","2114007"],["MT","Acorizal","5100102"],["MT","Água Boa","5100201"],["MT","Alta Floresta","5100250"],["MT","Alto Araguaia","5100300"],["MT","Alto Boa Vista","5100359"],["MT","Alto Garças","5100409"],["MT","Alto Paraguai","5100508"],["MT","Alto Taquari","5100607"],["MT","Apiacás","5100805"],["MT","Araguaiana","5101001"],["MT","Araguainha","5101209"],["MT","Araputanga","5101258"],["MT","Arenápolis","5101308"],["MT","Aripuanã","5101407"],["MT","Barão de Melgaço","5101605"],["MT","Barra do Bugres","5101704"],["MT","Barra do Garças","5101803"],["MT","Boa Esperança do Norte","5101837"],["MT","Bom Jesus do Araguaia","5101852"],["MT","Brasnorte","5101902"],["MT","Cáceres","5102504"],["MT","Campinápolis","5102603"],["MT","Campo Novo do Parecis","5102637"],["MT","Campo Verde","5102678"],["MT","Campos de Júlio","5102686"],["MT","Canabrava do Norte","5102694"],["MT","Canarana","5102702"],["MT","Carlinda","5102793"],["MT","Castanheira","5102850"],["MT","Chapada dos Guimarães","5103007"],["MT","Cláudia","5103056"],["MT","Cocalinho","5103106"],["MT","Colíder","5103205"],["MT","Colniza","5103254"],["MT","Comodoro","5103304"],["MT","Confresa","5103353"],["MT","Conquista D'Oeste","5103361"],["MT","Cotriguaçu","5103379"],["MT","Cuiabá","5103403"],["MT","Curvelândia","5103437"],["MT","Denise","5103452"],["MT","Diamantino","5103502"],["MT","Dom Aquino","5103601"],["MT","Feliz Natal","5103700"],["MT","Figueirópolis D'Oeste","5103809"],["MT","Gaúcha do Norte","5103858"],["MT","General Carneiro","5103908"],["MT","Glória D'Oeste","5103957"],["MT","Guarantã do Norte","5104104"],["MT","Guiratinga","5104203"],["MT","Indiavaí","5104500"],["MT","Ipiranga do Norte","5104526"],["MT","Itanhangá","5104542"],["MT","Itaúba","5104559"],["MT","Itiquira","5104609"],["MT","Jaciara","5104807"],["MT","Jangada","5104906"],["MT","Jauru","5105002"],["MT","Juara","5105101"],["MT","Juína","5105150"],["MT","Juruena","5105176"],["MT","Juscimeira","5105200"],["MT","Lambari D'Oeste","5105234"],["MT","Lucas do Rio Verde","5105259"],["MT","Luciara","5105309"],["MT","Marcelândia","5105580"],["MT","Matupá","5105606"],["MT","Mirassol d'Oeste","5105622"],["MT","Nobres","5105903"],["MT","Nortelândia","5106000"],["MT","Nossa Senhora do Livramento","5106109"],["MT","Nova Bandeirantes","5106158"],["MT","Nova Brasilândia","5106208"],["MT","Nova Canaã do Norte","5106216"],["MT","Nova Guarita","5108808"],["MT","Nova Lacerda","5106182"],["MT","Nova Marilândia","5108857"],["MT","Nova Maringá","5108907"],["MT","Nova Monte Verde","5108956"],["MT","Nova Mutum","5106224"],["MT","Nova Nazaré","5106174"],["MT","Nova Olímpia","5106232"],["MT","Nova Santa Helena","5106190"],["MT","Nova Ubiratã","5106240"],["MT","Nova Xavantina","5106257"],["MT","Novo Horizonte do Norte","5106273"],["MT","Novo Mundo","5106265"],["MT","Novo Santo Antônio","5106315"],["MT","Novo São Joaquim","5106281"],["MT","Paranaíta","5106299"],["MT","Paranatinga","5106307"],["MT","Pedra Preta","5106372"],["MT","Peixoto de Azevedo","5106422"],["MT","Planalto da Serra","5106455"],["MT","Poconé","5106505"],["MT","Pontal do Araguaia","5106653"],["MT","Ponte Branca","5106703"],["MT","Pontes e Lacerda","5106752"],["MT","Porto Alegre do Norte","5106778"],["MT","Porto dos Gaúchos","5106802"],["MT","Porto Esperidião","5106828"],["MT","Porto Estrela","5106851"],["MT","Poxoréu","5107008"],["MT","Primavera do Leste","5107040"],["MT","Querência","5107065"],["MT","Reserva do Cabaçal","5107156"],["MT","Ribeirão Cascalheira","5107180"],["MT","Ribeirãozinho","5107198"],["MT","Rio Branco","5107206"],["MT","Rondolândia","5107578"],["MT","Rondonópolis","5107602"],["MT","Rosário Oeste","5107701"],["MT","Salto do Céu","5107750"],["MT","Santa Carmem","5107248"],["MT","Santa Cruz do Xingu","5107743"],["MT","Santa Rita do Trivelato","5107768"],["MT","Santa Terezinha","5107776"],["MT","Santo Afonso","5107263"],["MT","Santo Antônio de Leverger","5107800"],["MT","Santo Antônio do Leste","5107792"],["MT","São Félix do Araguaia","5107859"],["MT","São José do Povo","5107297"],["MT","São José do Rio Claro","5107305"],["MT","São José do Xingu","5107354"],["MT","São José dos Quatro Marcos","5107107"],["MT","São Pedro da Cipa","5107404"],["MT","Sapezal","5107875"],["MT","Serra Nova Dourada","5107883"],["MT","Sinop","5107909"],["MT","Sorriso","5107925"],["MT","Tabaporã","5107941"],["MT","Tangará da Serra","5107958"],["MT","Tapurah","5108006"],["MT","Terra Nova do Norte","5108055"],["MT","Tesouro","5108105"],["MT","Torixoréu","5108204"],["MT","União do Sul","5108303"],["MT","Vale de São Domingos","5108352"],["MT","Várzea Grande","5108402"],["MT","Vera","5108501"],["MT","Vila Bela da Santíssima Trindade","5105507"],["MT","Vila Rica","5108600"],["MS","Água Clara","5000203"],["MS","Alcinópolis","5000252"],["MS","Amambai","5000609"],["MS","Anastácio","5000708"],["MS","Anaurilândia","5000807"],["MS","Angélica","5000856"],["MS","Antônio João","5000906"],["MS","Aparecida do Taboado","5001003"],["MS","Aquidauana","5001102"],["MS","Aral Moreira","5001243"],["MS","Bandeirantes","5001508"],["MS","Bataguassu","5001904"],["MS","Batayporã","5002001"],["MS","Bela Vista","5002100"],["MS","Bodoquena","5002159"],["MS","Bonito","5002209"],["MS","Brasilândia","5002308"],["MS","Caarapó","5002407"],["MS","Camapuã","5002605"],["MS","Campo Grande","5002704"],["MS","Caracol","5002803"],["MS","Cassilândia","5002902"],["MS","Chapadão do Sul","5002951"],["MS","Corguinho","5003108"],["MS","Coronel Sapucaia","5003157"],["MS","Corumbá","5003207"],["MS","Costa Rica","5003256"],["MS","Coxim","5003306"],["MS","Deodápolis","5003454"],["MS","Dois Irmãos do Buriti","5003488"],["MS","Douradina","5003504"],["MS","Dourados","5003702"],["MS","Eldorado","5003751"],["MS","Fátima do Sul","5003801"],["MS","Figueirão","5003900"],["MS","Glória de Dourados","5004007"],["MS","Guia Lopes da Laguna","5004106"],["MS","Iguatemi","5004304"],["MS","Inocência","5004403"],["MS","Itaporã","5004502"],["MS","Itaquiraí","5004601"],["MS","Ivinhema","5004700"],["MS","Japorã","5004809"],["MS","Jaraguari","5004908"],["MS","Jardim","5005004"],["MS","Jateí","5005103"],["MS","Juti","5005152"],["MS","Ladário","5005202"],["MS","Laguna Carapã","5005251"],["MS","Maracaju","5005400"],["MS","Miranda","5005608"],["MS","Mundo Novo","5005681"],["MS","Naviraí","5005707"],["MS","Nioaque","5005806"],["MS","Nova Alvorada do Sul","5006002"],["MS","Nova Andradina","5006200"],["MS","Novo Horizonte do Sul","5006259"],["MS","Paraíso das Águas","5006275"],["MS","Paranaíba","5006309"],["MS","Paranhos","5006358"],["MS","Pedro Gomes","5006408"],["MS","Ponta Porã","5006606"],["MS","Porto Murtinho","5006903"],["MS","Ribas do Rio Pardo","5007109"],["MS","Rio Brilhante","5007208"],["MS","Rio Negro","5007307"],["MS","Rio Verde de Mato Grosso","5007406"],["MS","Rochedo","5007505"],["MS","Santa Rita do Pardo","5007554"],["MS","São Gabriel do Oeste","5007695"],["MS","Selvíria","5007802"],["MS","Sete Quedas","5007703"],["MS","Sidrolândia","5007901"],["MS","Sonora","5007935"],["MS","Tacuru","5007950"],["MS","Taquarussu","5007976"],["MS","Terenos","5008008"],["MS","Três Lagoas","5008305"],["MS","Vicentina","5008404"],["MG","Abadia dos Dourados","3100104"],["MG","Abaeté","3100203"],["MG","Abre Campo","3100302"],["MG","Acaiaca","3100401"],["MG","Açucena","3100500"],["MG","Água Boa","3100609"],["MG","Água Comprida","3100708"],["MG","Aguanil","3100807"],["MG","Águas Formosas","3100906"],["MG","Águas Vermelhas","3101003"],["MG","Aimorés","3101102"],["MG","Aiuruoca","3101201"],["MG","Alagoa","3101300"],["MG","Albertina","3101409"],["MG","Além Paraíba","3101508"],["MG","Alfenas","3101607"],["MG","Alfredo Vasconcelos","3101631"],["MG","Almenara","3101706"],["MG","Alpercata","3101805"],["MG","Alpinópolis","3101904"],["MG","Alterosa","3102001"],["MG","Alto Caparaó","3102050"],["MG","Alto Jequitibá","3153509"],["MG","Alto Rio Doce","3102100"],["MG","Alvarenga","3102209"],["MG","Alvinópolis","3102308"],["MG","Alvorada de Minas","3102407"],["MG","Amparo do Serra","3102506"],["MG","Andradas","3102605"],["MG","Andrelândia","3102803"],["MG","Angelândia","3102852"],["MG","Antônio Carlos","3102902"],["MG","Antônio Dias","3103009"],["MG","Antônio Prado de Minas","3103108"],["MG","Araçaí","3103207"],["MG","Aracitaba","3103306"],["MG","Araçuaí","3103405"],["MG","Araguari","3103504"],["MG","Arantina","3103603"],["MG","Araponga","3103702"],["MG","Araporã","3103751"],["MG","Arapuá","3103801"],["MG","Araújos","3103900"],["MG","Araxá","3104007"],["MG","Arceburgo","3104106"],["MG","Arcos","3104205"],["MG","Areado","3104304"],["MG","Argirita","3104403"],["MG","Aricanduva","3104452"],["MG","Arinos","3104502"],["MG","Astolfo Dutra","3104601"],["MG","Ataléia","3104700"],["MG","Augusto de Lima","3104809"],["MG","Baependi","3104908"],["MG","Baldim","3105004"],["MG","Bambuí","3105103"],["MG","Bandeira","3105202"],["MG","Bandeira do Sul","3105301"],["MG","Barão de Cocais","3105400"],["MG","Barão do Monte Alto","3105509"],["MG","Barbacena","3105608"],["MG","Barra Longa","3105707"],["MG","Barroso","3105905"],["MG","Bela Vista de Minas","3106002"],["MG","Belmiro Braga","3106101"],["MG","Belo Horizonte","3106200"],["MG","Belo Oriente","3106309"],["MG","Belo Vale","3106408"],["MG","Berilo","3106507"],["MG","Berizal","3106655"],["MG","Bertópolis","3106606"],["MG","Betim","3106705"],["MG","Bias Fortes","3106804"],["MG","Bicas","3106903"],["MG","Biquinhas","3107000"],["MG","Boa Esperança","3107109"],["MG","Bocaina de Minas","3107208"],["MG","Bocaiúva","3107307"],["MG","Bom Despacho","3107406"],["MG","Bom Jardim de Minas","3107505"],["MG","Bom Jesus da Penha","3107604"],["MG","Bom Jesus do Amparo","3107703"],["MG","Bom Jesus do Galho","3107802"],["MG","Bom Repouso","3107901"],["MG","Bom Sucesso","3108008"],["MG","Bonfim","3108107"],["MG","Bonfinópolis de Minas","3108206"],["MG","Bonito de Minas","3108255"],["MG","Borda da Mata","3108305"],["MG","Botelhos","3108404"],["MG","Botumirim","3108503"],["MG","Brás Pires","3108701"],["MG","Brasilândia de Minas","3108552"],["MG","Brasília de Minas","3108602"],["MG","Braúnas","3108800"],["MG","Brazópolis","3108909"],["MG","Brumadinho","3109006"],["MG","Bueno Brandão","3109105"],["MG","Buenópolis","3109204"],["MG","Bugre","3109253"],["MG","Buritis","3109303"],["MG","Buritizeiro","3109402"],["MG","Cabeceira Grande","3109451"],["MG","Cabo Verde","3109501"],["MG","Cachoeira da Prata","3109600"],["MG","Cachoeira de Minas","3109709"],["MG","Cachoeira de Pajeú","3102704"],["MG","Cachoeira Dourada","3109808"],["MG","Caetanópolis","3109907"],["MG","Caeté","3110004"],["MG","Caiana","3110103"],["MG","Cajuri","3110202"],["MG","Caldas","3110301"],["MG","Camacho","3110400"],["MG","Camanducaia","3110509"],["MG","Cambuí","3110608"],["MG","Cambuquira","3110707"],["MG","Campanário","3110806"],["MG","Campanha","3110905"],["MG","Campestre","3111002"],["MG","Campina Verde","3111101"],["MG","Campo Azul","3111150"],["MG","Campo Belo","3111200"],["MG","Campo do Meio","3111309"],["MG","Campo Florido","3111408"],["MG","Campos Altos","3111507"],["MG","Campos Gerais","3111606"],["MG","Cana Verde","3111903"],["MG","Canaã","3111705"],["MG","Canápolis","3111804"],["MG","Candeias","3112000"],["MG","Cantagalo","3112059"],["MG","Caparaó","3112109"],["MG","Capela Nova","3112208"],["MG","Capelinha","3112307"],["MG","Capetinga","3112406"],["MG","Capim Branco","3112505"],["MG","Capinópolis","3112604"],["MG","Capitão Andrade","3112653"],["MG","Capitão Enéas","3112703"],["MG","Capitólio","3112802"],["MG","Caputira","3112901"],["MG","Caraí","3113008"],["MG","Caranaíba","3113107"],["MG","Carandaí","3113206"],["MG","Carangola","3113305"],["MG","Caratinga","3113404"],["MG","Carbonita","3113503"],["MG","Careaçu","3113602"],["MG","Carlos Chagas","3113701"],["MG","Carmésia","3113800"],["MG","Carmo da Cachoeira","3113909"],["MG","Carmo da Mata","3114006"],["MG","Carmo de Minas","3114105"],["MG","Carmo do Cajuru","3114204"],["MG","Carmo do Paranaíba","3114303"],["MG","Carmo do Rio Claro","3114402"],["MG","Carmópolis de Minas","3114501"],["MG","Carneirinho","3114550"],["MG","Carrancas","3114600"],["MG","Carvalhópolis","3114709"],["MG","Carvalhos","3114808"],["MG","Casa Grande","3114907"],["MG","Cascalho Rico","3115003"],["MG","Cássia","3115102"],["MG","Cataguases","3115300"],["MG","Catas Altas","3115359"],["MG","Catas Altas da Noruega","3115409"],["MG","Catuji","3115458"],["MG","Catuti","3115474"],["MG","Caxambu","3115508"],["MG","Cedro do Abaeté","3115607"],["MG","Central de Minas","3115706"],["MG","Centralina","3115805"],["MG","Chácara","3115904"],["MG","Chalé","3116001"],["MG","Chapada do Norte","3116100"],["MG","Chapada Gaúcha","3116159"],["MG","Chiador","3116209"],["MG","Cipotânea","3116308"],["MG","Claraval","3116407"],["MG","Claro dos Poções","3116506"],["MG","Cláudio","3116605"],["MG","Coimbra","3116704"],["MG","Coluna","3116803"],["MG","Comendador Gomes","3116902"],["MG","Comercinho","3117009"],["MG","Conceição da Aparecida","3117108"],["MG","Conceição da Barra de Minas","3115201"],["MG","Conceição das Alagoas","3117306"],["MG","Conceição das Pedras","3117207"],["MG","Conceição de Ipanema","3117405"],["MG","Conceição do Mato Dentro","3117504"],["MG","Conceição do Pará","3117603"],["MG","Conceição do Rio Verde","3117702"],["MG","Conceição dos Ouros","3117801"],["MG","Cônego Marinho","3117836"],["MG","Confins","3117876"],["MG","Congonhal","3117900"],["MG","Congonhas","3118007"],["MG","Congonhas do Norte","3118106"],["MG","Conquista","3118205"],["MG","Conselheiro Lafaiete","3118304"],["MG","Conselheiro Pena","3118403"],["MG","Consolação","3118502"],["MG","Contagem","3118601"],["MG","Coqueiral","3118700"],["MG","Coração de Jesus","3118809"],["MG","Cordisburgo","3118908"],["MG","Cordislândia","3119005"],["MG","Corinto","3119104"],["MG","Coroaci","3119203"],["MG","Coromandel","3119302"],["MG","Coronel Fabriciano","3119401"],["MG","Coronel Murta","3119500"],["MG","Coronel Pacheco","3119609"],["MG","Coronel Xavier Chaves","3119708"],["MG","Córrego Danta","3119807"],["MG","Córrego do Bom Jesus","3119906"],["MG","Córrego Fundo","3119955"],["MG","Córrego Novo","3120003"],["MG","Couto de Magalhães de Minas","3120102"],["MG","Crisólita","3120151"],["MG","Cristais","3120201"],["MG","Cristália","3120300"],["MG","Cristiano Otoni","3120409"],["MG","Cristina","3120508"],["MG","Crucilândia","3120607"],["MG","Cruzeiro da Fortaleza","3120706"],["MG","Cruzília","3120805"],["MG","Cuparaque","3120839"],["MG","Curral de Dentro","3120870"],["MG","Curvelo","3120904"],["MG","Datas","3121001"],["MG","Delfim Moreira","3121100"],["MG","Delfinópolis","3121209"],["MG","Delta","3121258"],["MG","Descoberto","3121308"],["MG","Desterro de Entre Rios","3121407"],["MG","Desterro do Melo","3121506"],["MG","Diamantina","3121605"],["MG","Diogo de Vasconcelos","3121704"],["MG","Dionísio","3121803"],["MG","Divinésia","3121902"],["MG","Divino","3122009"],["MG","Divino das Laranjeiras","3122108"],["MG","Divinolândia de Minas","3122207"],["MG","Divinópolis","3122306"],["MG","Divisa Alegre","3122355"],["MG","Divisa Nova","3122405"],["MG","Divisópolis","3122454"],["MG","Dom Bosco","3122470"],["MG","Dom Cavati","3122504"],["MG","Dom Joaquim","3122603"],["MG","Dom Silvério","3122702"],["MG","Dom Viçoso","3122801"],["MG","Dona Euzébia","3122900"],["MG","Dores de Campos","3123007"],["MG","Dores de Guanhães","3123106"],["MG","Dores do Indaiá","3123205"],["MG","Dores do Turvo","3123304"],["MG","Doresópolis","3123403"],["MG","Douradoquara","3123502"],["MG","Durandé","3123528"],["MG","Elói Mendes","3123601"],["MG","Engenheiro Caldas","3123700"],["MG","Engenheiro Navarro","3123809"],["MG","Entre Folhas","3123858"],["MG","Entre Rios de Minas","3123908"],["MG","Ervália","3124005"],["MG","Esmeraldas","3124104"],["MG","Espera Feliz","3124203"],["MG","Espinosa","3124302"],["MG","Espírito Santo do Dourado","3124401"],["MG","Estiva","3124500"],["MG","Estrela Dalva","3124609"],["MG","Estrela do Indaiá","3124708"],["MG","Estrela do Sul","3124807"],["MG","Eugenópolis","3124906"],["MG","Ewbank da Câmara","3125002"],["MG","Extrema","3125101"],["MG","Fama","3125200"],["MG","Faria Lemos","3125309"],["MG","Felício dos Santos","3125408"],["MG","Felisburgo","3125606"],["MG","Felixlândia","3125705"],["MG","Fernandes Tourinho","3125804"],["MG","Ferros","3125903"],["MG","Fervedouro","3125952"],["MG","Florestal","3126000"],["MG","Formiga","3126109"],["MG","Formoso","3126208"],["MG","Fortaleza de Minas","3126307"],["MG","Fortuna de Minas","3126406"],["MG","Francisco Badaró","3126505"],["MG","Francisco Dumont","3126604"],["MG","Francisco Sá","3126703"],["MG","Franciscópolis","3126752"],["MG","Frei Gaspar","3126802"],["MG","Frei Inocêncio","3126901"],["MG","Frei Lagonegro","3126950"],["MG","Fronteira","3127008"],["MG","Fronteira dos Vales","3127057"],["MG","Fruta de Leite","3127073"],["MG","Frutal","3127107"],["MG","Funilândia","3127206"],["MG","Galiléia","3127305"],["MG","Gameleiras","3127339"],["MG","Glaucilândia","3127354"],["MG","Goiabeira","3127370"],["MG","Goianá","3127388"],["MG","Gonçalves","3127404"],["MG","Gonzaga","3127503"],["MG","Gouveia","3127602"],["MG","Governador Valadares","3127701"],["MG","Grão Mogol","3127800"],["MG","Grupiara","3127909"],["MG","Guanhães","3128006"],["MG","Guapé","3128105"],["MG","Guaraciaba","3128204"],["MG","Guaraciama","3128253"],["MG","Guaranésia","3128303"],["MG","Guarani","3128402"],["MG","Guarará","3128501"],["MG","Guarda-Mor","3128600"],["MG","Guaxupé","3128709"],["MG","Guidoval","3128808"],["MG","Guimarânia","3128907"],["MG","Guiricema","3129004"],["MG","Gurinhatã","3129103"],["MG","Heliodora","3129202"],["MG","Iapu","3129301"],["MG","Ibertioga","3129400"],["MG","Ibiá","3129509"],["MG","Ibiaí","3129608"],["MG","Ibiracatu","3129657"],["MG","Ibiraci","3129707"],["MG","Ibirité","3129806"],["MG","Ibitiúra de Minas","3129905"],["MG","Ibituruna","3130002"],["MG","Icaraí de Minas","3130051"],["MG","Igarapé","3130101"],["MG","Igaratinga","3130200"],["MG","Iguatama","3130309"],["MG","Ijaci","3130408"],["MG","Ilicínea","3130507"],["MG","Imbé de Minas","3130556"],["MG","Inconfidentes","3130606"],["MG","Indaiabira","3130655"],["MG","Indianópolis","3130705"],["MG","Ingaí","3130804"],["MG","Inhapim","3130903"],["MG","Inhaúma","3131000"],["MG","Inimutaba","3131109"],["MG","Ipaba","3131158"],["MG","Ipanema","3131208"],["MG","Ipatinga","3131307"],["MG","Ipiaçu","3131406"],["MG","Ipuiúna","3131505"],["MG","Iraí de Minas","3131604"],["MG","Itabira","3131703"],["MG","Itabirinha","3131802"],["MG","Itabirito","3131901"],["MG","Itacambira","3132008"],["MG","Itacarambi","3132107"],["MG","Itaguara","3132206"],["MG","Itaipé","3132305"],["MG","Itajubá","3132404"],["MG","Itamarandiba","3132503"],["MG","Itamarati de Minas","3132602"],["MG","Itambacuri","3132701"],["MG","Itambé do Mato Dentro","3132800"],["MG","Itamogi","3132909"],["MG","Itamonte","3133006"],["MG","Itanhandu","3133105"],["MG","Itanhomi","3133204"],["MG","Itaobim","3133303"],["MG","Itapagipe","3133402"],["MG","Itapecerica","3133501"],["MG","Itapeva","3133600"],["MG","Itatiaiuçu","3133709"],["MG","Itaú de Minas","3133758"],["MG","Itaúna","3133808"],["MG","Itaverava","3133907"],["MG","Itinga","3134004"],["MG","Itueta","3134103"],["MG","Ituiutaba","3134202"],["MG","Itumirim","3134301"],["MG","Iturama","3134400"],["MG","Itutinga","3134509"],["MG","Jaboticatubas","3134608"],["MG","Jacinto","3134707"],["MG","Jacuí","3134806"],["MG","Jacutinga","3134905"],["MG","Jaguaraçu","3135001"],["MG","Jaíba","3135050"],["MG","Jampruca","3135076"],["MG","Janaúba","3135100"],["MG","Januária","3135209"],["MG","Japaraíba","3135308"],["MG","Japonvar","3135357"],["MG","Jeceaba","3135407"],["MG","Jenipapo de Minas","3135456"],["MG","Jequeri","3135506"],["MG","Jequitaí","3135605"],["MG","Jequitibá","3135704"],["MG","Jequitinhonha","3135803"],["MG","Jesuânia","3135902"],["MG","Joaíma","3136009"],["MG","Joanésia","3136108"],["MG","João Monlevade","3136207"],["MG","João Pinheiro","3136306"],["MG","Joaquim Felício","3136405"],["MG","Jordânia","3136504"],["MG","José Gonçalves de Minas","3136520"],["MG","José Raydan","3136553"],["MG","Josenópolis","3136579"],["MG","Juatuba","3136652"],["MG","Juiz de Fora","3136702"],["MG","Juramento","3136801"],["MG","Juruaia","3136900"],["MG","Juvenília","3136959"],["MG","Ladainha","3137007"],["MG","Lagamar","3137106"],["MG","Lagoa da Prata","3137205"],["MG","Lagoa dos Patos","3137304"],["MG","Lagoa Dourada","3137403"],["MG","Lagoa Formosa","3137502"],["MG","Lagoa Grande","3137536"],["MG","Lagoa Santa","3137601"],["MG","Lajinha","3137700"],["MG","Lambari","3137809"],["MG","Lamim","3137908"],["MG","Laranjal","3138005"],["MG","Lassance","3138104"],["MG","Lavras","3138203"],["MG","Leandro Ferreira","3138302"],["MG","Leme do Prado","3138351"],["MG","Leopoldina","3138401"],["MG","Liberdade","3138500"],["MG","Lima Duarte","3138609"],["MG","Limeira do Oeste","3138625"],["MG","Lontra","3138658"],["MG","Luisburgo","3138674"],["MG","Luislândia","3138682"],["MG","Luminárias","3138708"],["MG","Luz","3138807"],["MG","Machacalis","3138906"],["MG","Machado","3139003"],["MG","Madre de Deus de Minas","3139102"],["MG","Malacacheta","3139201"],["MG","Mamonas","3139250"],["MG","Manga","3139300"],["MG","Manhuaçu","3139409"],["MG","Manhumirim","3139508"],["MG","Mantena","3139607"],["MG","Mar de Espanha","3139805"],["MG","Maravilhas","3139706"],["MG","Maria da Fé","3139904"],["MG","Mariana","3140001"],["MG","Marilac","3140100"],["MG","Mário Campos","3140159"],["MG","Maripá de Minas","3140209"],["MG","Marliéria","3140308"],["MG","Marmelópolis","3140407"],["MG","Martinho Campos","3140506"],["MG","Martins Soares","3140530"],["MG","Mata Verde","3140555"],["MG","Materlândia","3140605"],["MG","Mateus Leme","3140704"],["MG","Mathias Lobato","3171501"],["MG","Matias Barbosa","3140803"],["MG","Matias Cardoso","3140852"],["MG","Matipó","3140902"],["MG","Mato Verde","3141009"],["MG","Matozinhos","3141108"],["MG","Matutina","3141207"],["MG","Medeiros","3141306"],["MG","Medina","3141405"],["MG","Mendes Pimentel","3141504"],["MG","Mercês","3141603"],["MG","Mesquita","3141702"],["MG","Minas Novas","3141801"],["MG","Minduri","3141900"],["MG","Mirabela","3142007"],["MG","Miradouro","3142106"],["MG","Miraí","3142205"],["MG","Miravânia","3142254"],["MG","Moeda","3142304"],["MG","Moema","3142403"],["MG","Monjolos","3142502"],["MG","Monsenhor Paulo","3142601"],["MG","Montalvânia","3142700"],["MG","Monte Alegre de Minas","3142809"],["MG","Monte Azul","3142908"],["MG","Monte Belo","3143005"],["MG","Monte Carmelo","3143104"],["MG","Monte Formoso","3143153"],["MG","Monte Santo de Minas","3143203"],["MG","Monte Sião","3143401"],["MG","Montes Claros","3143302"],["MG","Montezuma","3143450"],["MG","Morada Nova de Minas","3143500"],["MG","Morro da Garça","3143609"],["MG","Morro do Pilar","3143708"],["MG","Munhoz","3143807"],["MG","Muriaé","3143906"],["MG","Mutum","3144003"],["MG","Muzambinho","3144102"],["MG","Nacip Raydan","3144201"],["MG","Nanuque","3144300"],["MG","Naque","3144359"],["MG","Natalândia","3144375"],["MG","Natércia","3144409"],["MG","Nazareno","3144508"],["MG","Nepomuceno","3144607"],["MG","Ninheira","3144656"],["MG","Nova Belém","3144672"],["MG","Nova Era","3144706"],["MG","Nova Lima","3144805"],["MG","Nova Módica","3144904"],["MG","Nova Ponte","3145000"],["MG","Nova Porteirinha","3145059"],["MG","Nova Resende","3145109"],["MG","Nova Serrana","3145208"],["MG","Nova União","3136603"],["MG","Novo Cruzeiro","3145307"],["MG","Novo Oriente de Minas","3145356"],["MG","Novorizonte","3145372"],["MG","Olaria","3145406"],["MG","Olhos-d'Água","3145455"],["MG","Olímpio Noronha","3145505"],["MG","Oliveira","3145604"],["MG","Oliveira Fortes","3145703"],["MG","Onça de Pitangui","3145802"],["MG","Oratórios","3145851"],["MG","Orizânia","3145877"],["MG","Ouro Branco","3145901"],["MG","Ouro Fino","3146008"],["MG","Ouro Preto","3146107"],["MG","Ouro Verde de Minas","3146206"],["MG","Padre Carvalho","3146255"],["MG","Padre Paraíso","3146305"],["MG","Pai Pedro","3146552"],["MG","Paineiras","3146404"],["MG","Pains","3146503"],["MG","Paiva","3146602"],["MG","Palma","3146701"],["MG","Palmópolis","3146750"],["MG","Papagaios","3146909"],["MG","Pará de Minas","3147105"],["MG","Paracatu","3147006"],["MG","Paraguaçu","3147204"],["MG","Paraisópolis","3147303"],["MG","Paraopeba","3147402"],["MG","Passa Quatro","3147600"],["MG","Passa Tempo","3147709"],["MG","Passa Vinte","3147808"],["MG","Passabém","3147501"],["MG","Passos","3147907"],["MG","Patis","3147956"],["MG","Patos de Minas","3148004"],["MG","Patrocínio","3148103"],["MG","Patrocínio do Muriaé","3148202"],["MG","Paula Cândido","3148301"],["MG","Paulistas","3148400"],["MG","Pavão","3148509"],["MG","Peçanha","3148608"],["MG","Pedra Azul","3148707"],["MG","Pedra Bonita","3148756"],["MG","Pedra do Anta","3148806"],["MG","Pedra do Indaiá","3148905"],["MG","Pedra Dourada","3149002"],["MG","Pedralva","3149101"],["MG","Pedras de Maria da Cruz","3149150"],["MG","Pedrinópolis","3149200"],["MG","Pedro Leopoldo","3149309"],["MG","Pedro Teixeira","3149408"],["MG","Pequeri","3149507"],["MG","Pequi","3149606"],["MG","Perdigão","3149705"],["MG","Perdizes","3149804"],["MG","Perdões","3149903"],["MG","Periquito","3149952"],["MG","Pescador","3150000"],["MG","Piau","3150109"],["MG","Piedade de Caratinga","3150158"],["MG","Piedade de Ponte Nova","3150208"],["MG","Piedade do Rio Grande","3150307"],["MG","Piedade dos Gerais","3150406"],["MG","Pimenta","3150505"],["MG","Pingo-d'Água","3150539"],["MG","Pintópolis","3150570"],["MG","Piracema","3150604"],["MG","Pirajuba","3150703"],["MG","Piranga","3150802"],["MG","Piranguçu","3150901"],["MG","Piranguinho","3151008"],["MG","Pirapetinga","3151107"],["MG","Pirapora","3151206"],["MG","Piraúba","3151305"],["MG","Pitangui","3151404"],["MG","Piumhi","3151503"],["MG","Planura","3151602"],["MG","Poço Fundo","3151701"],["MG","Poços de Caldas","3151800"],["MG","Pocrane","3151909"],["MG","Pompéu","3152006"],["MG","Ponte Nova","3152105"],["MG","Ponto Chique","3152131"],["MG","Ponto dos Volantes","3152170"],["MG","Porteirinha","3152204"],["MG","Porto Firme","3152303"],["MG","Poté","3152402"],["MG","Pouso Alegre","3152501"],["MG","Pouso Alto","3152600"],["MG","Prados","3152709"],["MG","Prata","3152808"],["MG","Pratápolis","3152907"],["MG","Pratinha","3153004"],["MG","Presidente Bernardes","3153103"],["MG","Presidente Juscelino","3153202"],["MG","Presidente Kubitschek","3153301"],["MG","Presidente Olegário","3153400"],["MG","Prudente de Morais","3153608"],["MG","Quartel Geral","3153707"],["MG","Queluzito","3153806"],["MG","Raposos","3153905"],["MG","Raul Soares","3154002"],["MG","Recreio","3154101"],["MG","Reduto","3154150"],["MG","Resende Costa","3154200"],["MG","Resplendor","3154309"],["MG","Ressaquinha","3154408"],["MG","Riachinho","3154457"],["MG","Riacho dos Machados","3154507"],["MG","Ribeirão das Neves","3154606"],["MG","Ribeirão Vermelho","3154705"],["MG","Rio Acima","3154804"],["MG","Rio Casca","3154903"],["MG","Rio do Prado","3155108"],["MG","Rio Doce","3155009"],["MG","Rio Espera","3155207"],["MG","Rio Manso","3155306"],["MG","Rio Novo","3155405"],["MG","Rio Paranaíba","3155504"],["MG","Rio Pardo de Minas","3155603"],["MG","Rio Piracicaba","3155702"],["MG","Rio Pomba","3155801"],["MG","Rio Preto","3155900"],["MG","Rio Vermelho","3156007"],["MG","Ritápolis","3156106"],["MG","Rochedo de Minas","3156205"],["MG","Rodeiro","3156304"],["MG","Romaria","3156403"],["MG","Rosário da Limeira","3156452"],["MG","Rubelita","3156502"],["MG","Rubim","3156601"],["MG","Sabará","3156700"],["MG","Sabinópolis","3156809"],["MG","Sacramento","3156908"],["MG","Salinas","3157005"],["MG","Salto da Divisa","3157104"],["MG","Santa Bárbara","3157203"],["MG","Santa Bárbara do Leste","3157252"],["MG","Santa Bárbara do Monte Verde","3157278"],["MG","Santa Bárbara do Tugúrio","3157302"],["MG","Santa Cruz de Minas","3157336"],["MG","Santa Cruz de Salinas","3157377"],["MG","Santa Cruz do Escalvado","3157401"],["MG","Santa Efigênia de Minas","3157500"],["MG","Santa Fé de Minas","3157609"],["MG","Santa Helena de Minas","3157658"],["MG","Santa Juliana","3157708"],["MG","Santa Luzia","3157807"],["MG","Santa Margarida","3157906"],["MG","Santa Maria de Itabira","3158003"],["MG","Santa Maria do Salto","3158102"],["MG","Santa Maria do Suaçuí","3158201"],["MG","Santa Rita de Caldas","3159209"],["MG","Santa Rita de Ibitipoca","3159407"],["MG","Santa Rita de Jacutinga","3159308"],["MG","Santa Rita de Minas","3159357"],["MG","Santa Rita do Itueto","3159506"],["MG","Santa Rita do Sapucaí","3159605"],["MG","Santa Rosa da Serra","3159704"],["MG","Santa Vitória","3159803"],["MG","Santana da Vargem","3158300"],["MG","Santana de Cataguases","3158409"],["MG","Santana de Pirapama","3158508"],["MG","Santana do Deserto","3158607"],["MG","Santana do Garambéu","3158706"],["MG","Santana do Jacaré","3158805"],["MG","Santana do Manhuaçu","3158904"],["MG","Santana do Paraíso","3158953"],["MG","Santana do Riacho","3159001"],["MG","Santana dos Montes","3159100"],["MG","Santo Antônio do Amparo","3159902"],["MG","Santo Antônio do Aventureiro","3160009"],["MG","Santo Antônio do Grama","3160108"],["MG","Santo Antônio do Itambé","3160207"],["MG","Santo Antônio do Jacinto","3160306"],["MG","Santo Antônio do Monte","3160405"],["MG","Santo Antônio do Retiro","3160454"],["MG","Santo Antônio do Rio Abaixo","3160504"],["MG","Santo Hipólito","3160603"],["MG","Santos Dumont","3160702"],["MG","São Bento Abade","3160801"],["MG","São Brás do Suaçuí","3160900"],["MG","São Domingos das Dores","3160959"],["MG","São Domingos do Prata","3161007"],["MG","São Félix de Minas","3161056"],["MG","São Francisco","3161106"],["MG","São Francisco de Paula","3161205"],["MG","São Francisco de Sales","3161304"],["MG","São Francisco do Glória","3161403"],["MG","São Geraldo","3161502"],["MG","São Geraldo da Piedade","3161601"],["MG","São Geraldo do Baixio","3161650"],["MG","São Gonçalo do Abaeté","3161700"],["MG","São Gonçalo do Pará","3161809"],["MG","São Gonçalo do Rio Abaixo","3161908"],["MG","São Gonçalo do Rio Preto","3125507"],["MG","São Gonçalo do Sapucaí","3162005"],["MG","São Gotardo","3162104"],["MG","São João Batista do Glória","3162203"],["MG","São João da Lagoa","3162252"],["MG","São João da Mata","3162302"],["MG","São João da Ponte","3162401"],["MG","São João das Missões","3162450"],["MG","São João del Rei","3162500"],["MG","São João do Manhuaçu","3162559"],["MG","São João do Manteninha","3162575"],["MG","São João do Oriente","3162609"],["MG","São João do Pacuí","3162658"],["MG","São João do Paraíso","3162708"],["MG","São João Evangelista","3162807"],["MG","São João Nepomuceno","3162906"],["MG","São Joaquim de Bicas","3162922"],["MG","São José da Barra","3162948"],["MG","São José da Lapa","3162955"],["MG","São José da Safira","3163003"],["MG","São José da Varginha","3163102"],["MG","São José do Alegre","3163201"],["MG","São José do Divino","3163300"],["MG","São José do Goiabal","3163409"],["MG","São José do Jacuri","3163508"],["MG","São José do Mantimento","3163607"],["MG","São Lourenço","3163706"],["MG","São Miguel do Anta","3163805"],["MG","São Pedro da União","3163904"],["MG","São Pedro do Suaçuí","3164100"],["MG","São Pedro dos Ferros","3164001"],["MG","São Romão","3164209"],["MG","São Roque de Minas","3164308"],["MG","São Sebastião da Bela Vista","3164407"],["MG","São Sebastião da Vargem Alegre","3164431"],["MG","São Sebastião do Anta","3164472"],["MG","São Sebastião do Maranhão","3164506"],["MG","São Sebastião do Oeste","3164605"],["MG","São Sebastião do Paraíso","3164704"],["MG","São Sebastião do Rio Preto","3164803"],["MG","São Sebastião do Rio Verde","3164902"],["MG","São Tiago","3165008"],["MG","São Tomás de Aquino","3165107"],["MG","São Tomé das Letras","3165206"],["MG","São Vicente de Minas","3165305"],["MG","Sapucaí-Mirim","3165404"],["MG","Sardoá","3165503"],["MG","Sarzedo","3165537"],["MG","Sem-Peixe","3165560"],["MG","Senador Amaral","3165578"],["MG","Senador Cortes","3165602"],["MG","Senador Firmino","3165701"],["MG","Senador José Bento","3165800"],["MG","Senador Modestino Gonçalves","3165909"],["MG","Senhora de Oliveira","3166006"],["MG","Senhora do Porto","3166105"],["MG","Senhora dos Remédios","3166204"],["MG","Sericita","3166303"],["MG","Seritinga","3166402"],["MG","Serra Azul de Minas","3166501"],["MG","Serra da Saudade","3166600"],["MG","Serra do Salitre","3166808"],["MG","Serra dos Aimorés","3166709"],["MG","Serrania","3166907"],["MG","Serranópolis de Minas","3166956"],["MG","Serranos","3167004"],["MG","Serro","3167103"],["MG","Sete Lagoas","3167202"],["MG","Setubinha","3165552"],["MG","Silveirânia","3167301"],["MG","Silvianópolis","3167400"],["MG","Simão Pereira","3167509"],["MG","Simonésia","3167608"],["MG","Sobrália","3167707"],["MG","Soledade de Minas","3167806"],["MG","Tabuleiro","3167905"],["MG","Taiobeiras","3168002"],["MG","Taparuba","3168051"],["MG","Tapira","3168101"],["MG","Tapiraí","3168200"],["MG","Taquaraçu de Minas","3168309"],["MG","Tarumirim","3168408"],["MG","Teixeiras","3168507"],["MG","Teófilo Otoni","3168606"],["MG","Timóteo","3168705"],["MG","Tiradentes","3168804"],["MG","Tiros","3168903"],["MG","Tocantins","3169000"],["MG","Tocos do Moji","3169059"],["MG","Toledo","3169109"],["MG","Tombos","3169208"],["MG","Três Corações","3169307"],["MG","Três Marias","3169356"],["MG","Três Pontas","3169406"],["MG","Tumiritinga","3169505"],["MG","Tupaciguara","3169604"],["MG","Turmalina","3169703"],["MG","Turvolândia","3169802"],["MG","Ubá","3169901"],["MG","Ubaí","3170008"],["MG","Ubaporanga","3170057"],["MG","Uberaba","3170107"],["MG","Uberlândia","3170206"],["MG","Umburatiba","3170305"],["MG","Unaí","3170404"],["MG","União de Minas","3170438"],["MG","Uruana de Minas","3170479"],["MG","Urucânia","3170503"],["MG","Urucuia","3170529"],["MG","Vargem Alegre","3170578"],["MG","Vargem Bonita","3170602"],["MG","Vargem Grande do Rio Pardo","3170651"],["MG","Varginha","3170701"],["MG","Varjão de Minas","3170750"],["MG","Várzea da Palma","3170800"],["MG","Varzelândia","3170909"],["MG","Vazante","3171006"],["MG","Verdelândia","3171030"],["MG","Veredinha","3171071"],["MG","Veríssimo","3171105"],["MG","Vermelho Novo","3171154"],["MG","Vespasiano","3171204"],["MG","Viçosa","3171303"],["MG","Vieiras","3171402"],["MG","Virgem da Lapa","3171600"],["MG","Virgínia","3171709"],["MG","Virginópolis","3171808"],["MG","Virgolândia","3171907"],["MG","Visconde do Rio Branco","3172004"],["MG","Volta Grande","3172103"],["MG","Wenceslau Braz","3172202"],["PA","Abaetetuba","1500107"],["PA","Abel Figueiredo","1500131"],["PA","Acará","1500206"],["PA","Afuá","1500305"],["PA","Água Azul do Norte","1500347"],["PA","Alenquer","1500404"],["PA","Almeirim","1500503"],["PA","Altamira","1500602"],["PA","Anajás","1500701"],["PA","Ananindeua","1500800"],["PA","Anapu","1500859"],["PA","Augusto Corrêa","1500909"],["PA","Aurora do Pará","1500958"],["PA","Aveiro","1501006"],["PA","Bagre","1501105"],["PA","Baião","1501204"],["PA","Bannach","1501253"],["PA","Barcarena","1501303"],["PA","Belém","1501402"],["PA","Belterra","1501451"],["PA","Benevides","1501501"],["PA","Bom Jesus do Tocantins","1501576"],["PA","Bonito","1501600"],["PA","Bragança","1501709"],["PA","Brasil Novo","1501725"],["PA","Brejo Grande do Araguaia","1501758"],["PA","Breu Branco","1501782"],["PA","Breves","1501808"],["PA","Bujaru","1501907"],["PA","Cachoeira do Arari","1502004"],["PA","Cachoeira do Piriá","1501956"],["PA","Cametá","1502103"],["PA","Canaã dos Carajás","1502152"],["PA","Capanema","1502202"],["PA","Capitão Poço","1502301"],["PA","Castanhal","1502400"],["PA","Chaves","1502509"],["PA","Colares","1502608"],["PA","Conceição do Araguaia","1502707"],["PA","Concórdia do Pará","1502756"],["PA","Cumaru do Norte","1502764"],["PA","Curionópolis","1502772"],["PA","Curralinho","1502806"],["PA","Curuá","1502855"],["PA","Curuçá","1502905"],["PA","Dom Eliseu","1502939"],["PA","Eldorado do Carajás","1502954"],["PA","Faro","1503002"],["PA","Floresta do Araguaia","1503044"],["PA","Garrafão do Norte","1503077"],["PA","Goianésia do Pará","1503093"],["PA","Gurupá","1503101"],["PA","Igarapé-Açu","1503200"],["PA","Igarapé-Miri","1503309"],["PA","Inhangapi","1503408"],["PA","Ipixuna do Pará","1503457"],["PA","Irituia","1503507"],["PA","Itaituba","1503606"],["PA","Itupiranga","1503705"],["PA","Jacareacanga","1503754"],["PA","Jacundá","1503804"],["PA","Juruti","1503903"],["PA","Limoeiro do Ajuru","1504000"],["PA","Mãe do Rio","1504059"],["PA","Magalhães Barata","1504109"],["PA","Marabá","1504208"],["PA","Maracanã","1504307"],["PA","Marapanim","1504406"],["PA","Marituba","1504422"],["PA","Medicilândia","1504455"],["PA","Melgaço","1504505"],["PA","Mocajuba","1504604"],["PA","Moju","1504703"],["PA","Mojuí dos Campos","1504752"],["PA","Monte Alegre","1504802"],["PA","Muaná","1504901"],["PA","Nova Esperança do Piriá","1504950"],["PA","Nova Ipixuna","1504976"],["PA","Nova Timboteua","1505007"],["PA","Novo Progresso","1505031"],["PA","Novo Repartimento","1505064"],["PA","Óbidos","1505106"],["PA","Oeiras do Pará","1505205"],["PA","Oriximiná","1505304"],["PA","Ourém","1505403"],["PA","Ourilândia do Norte","1505437"],["PA","Pacajá","1505486"],["PA","Palestina do Pará","1505494"],["PA","Paragominas","1505502"],["PA","Parauapebas","1505536"],["PA","Pau D'Arco","1505551"],["PA","Peixe-Boi","1505601"],["PA","Piçarra","1505635"],["PA","Placas","1505650"],["PA","Ponta de Pedras","1505700"],["PA","Portel","1505809"],["PA","Porto de Moz","1505908"],["PA","Prainha","1506005"],["PA","Primavera","1506104"],["PA","Quatipuru","1506112"],["PA","Redenção","1506138"],["PA","Rio Maria","1506161"],["PA","Rondon do Pará","1506187"],["PA","Rurópolis","1506195"],["PA","Salinópolis","1506203"],["PA","Salvaterra","1506302"],["PA","Santa Bárbara do Pará","1506351"],["PA","Santa Cruz do Arari","1506401"],["PA","Santa Izabel do Pará","1506500"],["PA","Santa Luzia do Pará","1506559"],["PA","Santa Maria das Barreiras","1506583"],["PA","Santa Maria do Pará","1506609"],["PA","Santana do Araguaia","1506708"],["PA","Santarém","1506807"],["PA","Santarém Novo","1506906"],["PA","Santo Antônio do Tauá","1507003"],["PA","São Caetano de Odivelas","1507102"],["PA","São Domingos do Araguaia","1507151"],["PA","São Domingos do Capim","1507201"],["PA","São Félix do Xingu","1507300"],["PA","São Francisco do Pará","1507409"],["PA","São Geraldo do Araguaia","1507458"],["PA","São João da Ponta","1507466"],["PA","São João de Pirabas","1507474"],["PA","São João do Araguaia","1507508"],["PA","São Miguel do Guamá","1507607"],["PA","São Sebastião da Boa Vista","1507706"],["PA","Sapucaia","1507755"],["PA","Senador José Porfírio","1507805"],["PA","Soure","1507904"],["PA","Tailândia","1507953"],["PA","Terra Alta","1507961"],["PA","Terra Santa","1507979"],["PA","Tomé-Açu","1508001"],["PA","Tracuateua","1508035"],["PA","Trairão","1508050"],["PA","Tucumã","1508084"],["PA","Tucuruí","1508100"],["PA","Ulianópolis","1508126"],["PA","Uruará","1508159"],["PA","Vigia","1508209"],["PA","Viseu","1508308"],["PA","Vitória do Xingu","1508357"],["PA","Xinguara","1508407"],["PB","Água Branca","2500106"],["PB","Aguiar","2500205"],["PB","Alagoa Grande","2500304"],["PB","Alagoa Nova","2500403"],["PB","Alagoinha","2500502"],["PB","Alcantil","2500536"],["PB","Algodão de Jandaíra","2500577"],["PB","Alhandra","2500601"],["PB","Amparo","2500734"],["PB","Aparecida","2500775"],["PB","Araçagi","2500809"],["PB","Arara","2500908"],["PB","Araruna","2501005"],["PB","Areia","2501104"],["PB","Areia de Baraúnas","2501153"],["PB","Areial","2501203"],["PB","Aroeiras","2501302"],["PB","Assunção","2501351"],["PB","Baía da Traição","2501401"],["PB","Bananeiras","2501500"],["PB","Baraúna","2501534"],["PB","Barra de Santa Rosa","2501609"],["PB","Barra de Santana","2501575"],["PB","Barra de São Miguel","2501708"],["PB","Bayeux","2501807"],["PB","Belém","2501906"],["PB","Belém do Brejo do Cruz","2502003"],["PB","Bernardino Batista","2502052"],["PB","Boa Ventura","2502102"],["PB","Boa Vista","2502151"],["PB","Bom Jesus","2502201"],["PB","Bom Sucesso","2502300"],["PB","Bonito de Santa Fé","2502409"],["PB","Boqueirão","2502508"],["PB","Borborema","2502706"],["PB","Brejo do Cruz","2502805"],["PB","Brejo dos Santos","2502904"],["PB","Caaporã","2503001"],["PB","Cabaceiras","2503100"],["PB","Cabedelo","2503209"],["PB","Cachoeira dos Índios","2503308"],["PB","Cacimba de Areia","2503407"],["PB","Cacimba de Dentro","2503506"],["PB","Cacimbas","2503555"],["PB","Caiçara","2503605"],["PB","Cajazeiras","2503704"],["PB","Cajazeirinhas","2503753"],["PB","Caldas Brandão","2503803"],["PB","Camalaú","2503902"],["PB","Campina Grande","2504009"],["PB","Capim","2504033"],["PB","Caraúbas","2504074"],["PB","Carrapateira","2504108"],["PB","Casserengue","2504157"],["PB","Catingueira","2504207"],["PB","Catolé do Rocha","2504306"],["PB","Caturité","2504355"],["PB","Conceição","2504405"],["PB","Condado","2504504"],["PB","Conde","2504603"],["PB","Congo","2504702"],["PB","Coremas","2504801"],["PB","Coxixola","2504850"],["PB","Cruz do Espírito Santo","2504900"],["PB","Cubati","2505006"],["PB","Cuité","2505105"],["PB","Cuité de Mamanguape","2505238"],["PB","Cuitegi","2505204"],["PB","Curral de Cima","2505279"],["PB","Curral Velho","2505303"],["PB","Damião","2505352"],["PB","Desterro","2505402"],["PB","Diamante","2505600"],["PB","Dona Inês","2505709"],["PB","Duas Estradas","2505808"],["PB","Emas","2505907"],["PB","Esperança","2506004"],["PB","Fagundes","2506103"],["PB","Frei Martinho","2506202"],["PB","Gado Bravo","2506251"],["PB","Guarabira","2506301"],["PB","Gurinhém","2506400"],["PB","Gurjão","2506509"],["PB","Ibiara","2506608"],["PB","Igaracy","2502607"],["PB","Imaculada","2506707"],["PB","Ingá","2506806"],["PB","Itabaiana","2506905"],["PB","Itaporanga","2507002"],["PB","Itapororoca","2507101"],["PB","Itatuba","2507200"],["PB","Jacaraú","2507309"],["PB","Jericó","2507408"],["PB","João Pessoa","2507507"],["PB","Joca Claudino","2513653"],["PB","Juarez Távora","2507606"],["PB","Juazeirinho","2507705"],["PB","Junco do Seridó","2507804"],["PB","Juripiranga","2507903"],["PB","Juru","2508000"],["PB","Lagoa","2508109"],["PB","Lagoa de Dentro","2508208"],["PB","Lagoa Seca","2508307"],["PB","Lastro","2508406"],["PB","Livramento","2508505"],["PB","Logradouro","2508554"],["PB","Lucena","2508604"],["PB","Mãe d'Água","2508703"],["PB","Malta","2508802"],["PB","Mamanguape","2508901"],["PB","Manaíra","2509008"],["PB","Marcação","2509057"],["PB","Mari","2509107"],["PB","Marizópolis","2509156"],["PB","Massaranduba","2509206"],["PB","Mataraca","2509305"],["PB","Matinhas","2509339"],["PB","Mato Grosso","2509370"],["PB","Maturéia","2509396"],["PB","Mogeiro","2509404"],["PB","Montadas","2509503"],["PB","Monte Horebe","2509602"],["PB","Monteiro","2509701"],["PB","Mulungu","2509800"],["PB","Natuba","2509909"],["PB","Nazarezinho","2510006"],["PB","Nova Floresta","2510105"],["PB","Nova Olinda","2510204"],["PB","Nova Palmeira","2510303"],["PB","Olho d'Água","2510402"],["PB","Olivedos","2510501"],["PB","Ouro Velho","2510600"],["PB","Parari","2510659"],["PB","Passagem","2510709"],["PB","Patos","2510808"],["PB","Paulista","2510907"],["PB","Pedra Branca","2511004"],["PB","Pedra Lavrada","2511103"],["PB","Pedras de Fogo","2511202"],["PB","Pedro Régis","2512721"],["PB","Piancó","2511301"],["PB","Picuí","2511400"],["PB","Pilar","2511509"],["PB","Pilões","2511608"],["PB","Pilõezinhos","2511707"],["PB","Pirpirituba","2511806"],["PB","Pitimbu","2511905"],["PB","Pocinhos","2512002"],["PB","Poço Dantas","2512036"],["PB","Poço de José de Moura","2512077"],["PB","Pombal","2512101"],["PB","Prata","2512200"],["PB","Princesa Isabel","2512309"],["PB","Puxinanã","2512408"],["PB","Queimadas","2512507"],["PB","Quixaba","2512606"],["PB","Remígio","2512705"],["PB","Riachão","2512747"],["PB","Riachão do Bacamarte","2512754"],["PB","Riachão do Poço","2512762"],["PB","Riacho de Santo Antônio","2512788"],["PB","Riacho dos Cavalos","2512804"],["PB","Rio Tinto","2512903"],["PB","Salgadinho","2513000"],["PB","Salgado de São Félix","2513109"],["PB","Santa Cecília","2513158"],["PB","Santa Cruz","2513208"],["PB","Santa Helena","2513307"],["PB","Santa Inês","2513356"],["PB","Santa Luzia","2513406"],["PB","Santa Rita","2513703"],["PB","Santa Teresinha","2513802"],["PB","Santana de Mangueira","2513505"],["PB","Santana dos Garrotes","2513604"],["PB","Santo André","2513851"],["PB","São Bentinho","2513927"],["PB","São Bento","2513901"],["PB","São Domingos","2513968"],["PB","São Domingos do Cariri","2513943"],["PB","São Francisco","2513984"],["PB","São João do Cariri","2514008"],["PB","São João do Rio do Peixe","2500700"],["PB","São João do Tigre","2514107"],["PB","São José da Lagoa Tapada","2514206"],["PB","São José de Caiana","2514305"],["PB","São José de Espinharas","2514404"],["PB","São José de Piranhas","2514503"],["PB","São José de Princesa","2514552"],["PB","São José do Bonfim","2514602"],["PB","São José do Brejo do Cruz","2514651"],["PB","São José do Sabugi","2514701"],["PB","São José dos Cordeiros","2514800"],["PB","São José dos Ramos","2514453"],["PB","São Mamede","2514909"],["PB","São Miguel de Taipu","2515005"],["PB","São Sebastião de Lagoa de Roça","2515104"],["PB","São Sebastião do Umbuzeiro","2515203"],["PB","São Vicente do Seridó","2515401"],["PB","Sapé","2515302"],["PB","Serra Branca","2515500"],["PB","Serra da Raiz","2515609"],["PB","Serra Grande","2515708"],["PB","Serra Redonda","2515807"],["PB","Serraria","2515906"],["PB","Sertãozinho","2515930"],["PB","Sobrado","2515971"],["PB","Solânea","2516003"],["PB","Soledade","2516102"],["PB","Sossêgo","2516151"],["PB","Sousa","2516201"],["PB","Sumé","2516300"],["PB","Tacima","2516409"],["PB","Taperoá","2516508"],["PB","Tavares","2516607"],["PB","Teixeira","2516706"],["PB","Tenório","2516755"],["PB","Triunfo","2516805"],["PB","Uiraúna","2516904"],["PB","Umbuzeiro","2517001"],["PB","Várzea","2517100"],["PB","Vieirópolis","2517209"],["PB","Vista Serrana","2505501"],["PB","Zabelê","2517407"],["PR","Abatiá","4100103"],["PR","Adrianópolis","4100202"],["PR","Agudos do Sul","4100301"],["PR","Almirante Tamandaré","4100400"],["PR","Altamira do Paraná","4100459"],["PR","Alto Paraíso","4128625"],["PR","Alto Paraná","4100608"],["PR","Alto Piquiri","4100707"],["PR","Altônia","4100509"],["PR","Alvorada do Sul","4100806"],["PR","Amaporã","4100905"],["PR","Ampére","4101002"],["PR","Anahy","4101051"],["PR","Andirá","4101101"],["PR","Ângulo","4101150"],["PR","Antonina","4101200"],["PR","Antônio Olinto","4101309"],["PR","Apucarana","4101408"],["PR","Arapongas","4101507"],["PR","Arapoti","4101606"],["PR","Arapuã","4101655"],["PR","Araruna","4101705"],["PR","Araucária","4101804"],["PR","Ariranha do Ivaí","4101853"],["PR","Assaí","4101903"],["PR","Assis Chateaubriand","4102000"],["PR","Astorga","4102109"],["PR","Atalaia","4102208"],["PR","Balsa Nova","4102307"],["PR","Bandeirantes","4102406"],["PR","Barbosa Ferraz","4102505"],["PR","Barra do Jacaré","4102703"],["PR","Barracão","4102604"],["PR","Bela Vista da Caroba","4102752"],["PR","Bela Vista do Paraíso","4102802"],["PR","Bituruna","4102901"],["PR","Boa Esperança","4103008"],["PR","Boa Esperança do Iguaçu","4103024"],["PR","Boa Ventura de São Roque","4103040"],["PR","Boa Vista da Aparecida","4103057"],["PR","Bocaiúva do Sul","4103107"],["PR","Bom Jesus do Sul","4103156"],["PR","Bom Sucesso","4103206"],["PR","Bom Sucesso do Sul","4103222"],["PR","Borrazópolis","4103305"],["PR","Braganey","4103354"],["PR","Brasilândia do Sul","4103370"],["PR","Cafeara","4103404"],["PR","Cafelândia","4103453"],["PR","Cafezal do Sul","4103479"],["PR","Califórnia","4103503"],["PR","Cambará","4103602"],["PR","Cambé","4103701"],["PR","Cambira","4103800"],["PR","Campina da Lagoa","4103909"],["PR","Campina do Simão","4103958"],["PR","Campina Grande do Sul","4104006"],["PR","Campo Bonito","4104055"],["PR","Campo do Tenente","4104105"],["PR","Campo Largo","4104204"],["PR","Campo Magro","4104253"],["PR","Campo Mourão","4104303"],["PR","Cândido de Abreu","4104402"],["PR","Candói","4104428"],["PR","Cantagalo","4104451"],["PR","Capanema","4104501"],["PR","Capitão Leônidas Marques","4104600"],["PR","Carambeí","4104659"],["PR","Carlópolis","4104709"],["PR","Cascavel","4104808"],["PR","Castro","4104907"],["PR","Catanduvas","4105003"],["PR","Centenário do Sul","4105102"],["PR","Cerro Azul","4105201"],["PR","Céu Azul","4105300"],["PR","Chopinzinho","4105409"],["PR","Cianorte","4105508"],["PR","Cidade Gaúcha","4105607"],["PR","Clevelândia","4105706"],["PR","Colombo","4105805"],["PR","Colorado","4105904"],["PR","Congonhinhas","4106001"],["PR","Conselheiro Mairinck","4106100"],["PR","Contenda","4106209"],["PR","Corbélia","4106308"],["PR","Cornélio Procópio","4106407"],["PR","Coronel Domingos Soares","4106456"],["PR","Coronel Vivida","4106506"],["PR","Corumbataí do Sul","4106555"],["PR","Cruz Machado","4106803"],["PR","Cruzeiro do Iguaçu","4106571"],["PR","Cruzeiro do Oeste","4106605"],["PR","Cruzeiro do Sul","4106704"],["PR","Cruzmaltina","4106852"],["PR","Curitiba","4106902"],["PR","Curiúva","4107009"],["PR","Diamante D'Oeste","4107157"],["PR","Diamante do Norte","4107108"],["PR","Diamante do Sul","4107124"],["PR","Dois Vizinhos","4107207"],["PR","Douradina","4107256"],["PR","Doutor Camargo","4107306"],["PR","Doutor Ulysses","4128633"],["PR","Enéas Marques","4107405"],["PR","Engenheiro Beltrão","4107504"],["PR","Entre Rios do Oeste","4107538"],["PR","Esperança Nova","4107520"],["PR","Espigão Alto do Iguaçu","4107546"],["PR","Farol","4107553"],["PR","Faxinal","4107603"],["PR","Fazenda Rio Grande","4107652"],["PR","Fênix","4107702"],["PR","Fernandes Pinheiro","4107736"],["PR","Figueira","4107751"],["PR","Flor da Serra do Sul","4107850"],["PR","Floraí","4107801"],["PR","Floresta","4107900"],["PR","Florestópolis","4108007"],["PR","Flórida","4108106"],["PR","Formosa do Oeste","4108205"],["PR","Foz do Iguaçu","4108304"],["PR","Foz do Jordão","4108452"],["PR","Francisco Alves","4108320"],["PR","Francisco Beltrão","4108403"],["PR","General Carneiro","4108502"],["PR","Godoy Moreira","4108551"],["PR","Goioerê","4108601"],["PR","Goioxim","4108650"],["PR","Grandes Rios","4108700"],["PR","Guaíra","4108809"],["PR","Guairaçá","4108908"],["PR","Guamiranga","4108957"],["PR","Guapirama","4109005"],["PR","Guaporema","4109104"],["PR","Guaraci","4109203"],["PR","Guaraniaçu","4109302"],["PR","Guarapuava","4109401"],["PR","Guaraqueçaba","4109500"],["PR","Guaratuba","4109609"],["PR","Honório Serpa","4109658"],["PR","Ibaiti","4109708"],["PR","Ibema","4109757"],["PR","Ibiporã","4109807"],["PR","Icaraíma","4109906"],["PR","Iguaraçu","4110003"],["PR","Iguatu","4110052"],["PR","Imbaú","4110078"],["PR","Imbituva","4110102"],["PR","Inácio Martins","4110201"],["PR","Inajá","4110300"],["PR","Indianópolis","4110409"],["PR","Ipiranga","4110508"],["PR","Iporã","4110607"],["PR","Iracema do Oeste","4110656"],["PR","Irati","4110706"],["PR","Iretama","4110805"],["PR","Itaguajé","4110904"],["PR","Itaipulândia","4110953"],["PR","Itambaracá","4111001"],["PR","Itambé","4111100"],["PR","Itapejara d'Oeste","4111209"],["PR","Itaperuçu","4111258"],["PR","Itaúna do Sul","4111308"],["PR","Ivaí","4111407"],["PR","Ivaiporã","4111506"],["PR","Ivaté","4111555"],["PR","Ivatuba","4111605"],["PR","Jaboti","4111704"],["PR","Jacarezinho","4111803"],["PR","Jaguapitã","4111902"],["PR","Jaguariaíva","4112009"],["PR","Jandaia do Sul","4112108"],["PR","Janiópolis","4112207"],["PR","Japira","4112306"],["PR","Japurá","4112405"],["PR","Jardim Alegre","4112504"],["PR","Jardim Olinda","4112603"],["PR","Jataizinho","4112702"],["PR","Jesuítas","4112751"],["PR","Joaquim Távora","4112801"],["PR","Jundiaí do Sul","4112900"],["PR","Juranda","4112959"],["PR","Jussara","4113007"],["PR","Kaloré","4113106"],["PR","Lapa","4113205"],["PR","Laranjal","4113254"],["PR","Laranjeiras do Sul","4113304"],["PR","Leópolis","4113403"],["PR","Lidianópolis","4113429"],["PR","Lindoeste","4113452"],["PR","Loanda","4113502"],["PR","Lobato","4113601"],["PR","Londrina","4113700"],["PR","Luiziana","4113734"],["PR","Lunardelli","4113759"],["PR","Lupionópolis","4113809"],["PR","Mallet","4113908"],["PR","Mamborê","4114005"],["PR","Mandaguaçu","4114104"],["PR","Mandaguari","4114203"],["PR","Mandirituba","4114302"],["PR","Manfrinópolis","4114351"],["PR","Mangueirinha","4114401"],["PR","Manoel Ribas","4114500"],["PR","Marechal Cândido Rondon","4114609"],["PR","Maria Helena","4114708"],["PR","Marialva","4114807"],["PR","Marilândia do Sul","4114906"],["PR","Marilena","4115002"],["PR","Mariluz","4115101"],["PR","Maringá","4115200"],["PR","Mariópolis","4115309"],["PR","Maripá","4115358"],["PR","Marmeleiro","4115408"],["PR","Marquinho","4115457"],["PR","Marumbi","4115507"],["PR","Matelândia","4115606"],["PR","Matinhos","4115705"],["PR","Mato Rico","4115739"],["PR","Mauá da Serra","4115754"],["PR","Medianeira","4115804"],["PR","Mercedes","4115853"],["PR","Mirador","4115903"],["PR","Miraselva","4116000"],["PR","Missal","4116059"],["PR","Moreira Sales","4116109"],["PR","Morretes","4116208"],["PR","Munhoz de Melo","4116307"],["PR","Nossa Senhora das Graças","4116406"],["PR","Nova Aliança do Ivaí","4116505"],["PR","Nova América da Colina","4116604"],["PR","Nova Aurora","4116703"],["PR","Nova Cantu","4116802"],["PR","Nova Esperança","4116901"],["PR","Nova Esperança do Sudoeste","4116950"],["PR","Nova Fátima","4117008"],["PR","Nova Laranjeiras","4117057"],["PR","Nova Londrina","4117107"],["PR","Nova Olímpia","4117206"],["PR","Nova Prata do Iguaçu","4117255"],["PR","Nova Santa Bárbara","4117214"],["PR","Nova Santa Rosa","4117222"],["PR","Nova Tebas","4117271"],["PR","Novo Itacolomi","4117297"],["PR","Ortigueira","4117305"],["PR","Ourizona","4117404"],["PR","Ouro Verde do Oeste","4117453"],["PR","Paiçandu","4117503"],["PR","Palmas","4117602"],["PR","Palmeira","4117701"],["PR","Palmital","4117800"],["PR","Palotina","4117909"],["PR","Paraíso do Norte","4118006"],["PR","Paranacity","4118105"],["PR","Paranaguá","4118204"],["PR","Paranapoema","4118303"],["PR","Paranavaí","4118402"],["PR","Pato Bragado","4118451"],["PR","Pato Branco","4118501"],["PR","Paula Freitas","4118600"],["PR","Paulo Frontin","4118709"],["PR","Peabiru","4118808"],["PR","Perobal","4118857"],["PR","Pérola","4118907"],["PR","Pérola d'Oeste","4119004"],["PR","Piên","4119103"],["PR","Pinhais","4119152"],["PR","Pinhal de São Bento","4119251"],["PR","Pinhalão","4119202"],["PR","Pinhão","4119301"],["PR","Piraí do Sul","4119400"],["PR","Piraquara","4119509"],["PR","Pitanga","4119608"],["PR","Pitangueiras","4119657"],["PR","Planaltina do Paraná","4119707"],["PR","Planalto","4119806"],["PR","Ponta Grossa","4119905"],["PR","Pontal do Paraná","4119954"],["PR","Porecatu","4120002"],["PR","Porto Amazonas","4120101"],["PR","Porto Barreiro","4120150"],["PR","Porto Rico","4120200"],["PR","Porto Vitória","4120309"],["PR","Prado Ferreira","4120333"],["PR","Pranchita","4120358"],["PR","Presidente Castelo Branco","4120408"],["PR","Primeiro de Maio","4120507"],["PR","Prudentópolis","4120606"],["PR","Quarto Centenário","4120655"],["PR","Quatiguá","4120705"],["PR","Quatro Barras","4120804"],["PR","Quatro Pontes","4120853"],["PR","Quedas do Iguaçu","4120903"],["PR","Querência do Norte","4121000"],["PR","Quinta do Sol","4121109"],["PR","Quitandinha","4121208"],["PR","Ramilândia","4121257"],["PR","Rancho Alegre","4121307"],["PR","Rancho Alegre D'Oeste","4121356"],["PR","Realeza","4121406"],["PR","Rebouças","4121505"],["PR","Renascença","4121604"],["PR","Reserva","4121703"],["PR","Reserva do Iguaçu","4121752"],["PR","Ribeirão Claro","4121802"],["PR","Ribeirão do Pinhal","4121901"],["PR","Rio Azul","4122008"],["PR","Rio Bom","4122107"],["PR","Rio Bonito do Iguaçu","4122156"],["PR","Rio Branco do Ivaí","4122172"],["PR","Rio Branco do Sul","4122206"],["PR","Rio Negro","4122305"],["PR","Rolândia","4122404"],["PR","Roncador","4122503"],["PR","Rondon","4122602"],["PR","Rosário do Ivaí","4122651"],["PR","Sabáudia","4122701"],["PR","Salgado Filho","4122800"],["PR","Salto do Itararé","4122909"],["PR","Salto do Lontra","4123006"],["PR","Santa Amélia","4123105"],["PR","Santa Cecília do Pavão","4123204"],["PR","Santa Cruz de Monte Castelo","4123303"],["PR","Santa Fé","4123402"],["PR","Santa Helena","4123501"],["PR","Santa Inês","4123600"],["PR","Santa Isabel do Ivaí","4123709"],["PR","Santa Izabel do Oeste","4123808"],["PR","Santa Lúcia","4123824"],["PR","Santa Maria do Oeste","4123857"],["PR","Santa Mariana","4123907"],["PR","Santa Mônica","4123956"],["PR","Santa Tereza do Oeste","4124020"],["PR","Santa Terezinha de Itaipu","4124053"],["PR","Santana do Itararé","4124004"],["PR","Santo Antônio da Platina","4124103"],["PR","Santo Antônio do Caiuá","4124202"],["PR","Santo Antônio do Paraíso","4124301"],["PR","Santo Antônio do Sudoeste","4124400"],["PR","Santo Inácio","4124509"],["PR","São Carlos do Ivaí","4124608"],["PR","São Jerônimo da Serra","4124707"],["PR","São João","4124806"],["PR","São João do Caiuá","4124905"],["PR","São João do Ivaí","4125001"],["PR","São João do Triunfo","4125100"],["PR","São Jorge d'Oeste","4125209"],["PR","São Jorge do Ivaí","4125308"],["PR","São Jorge do Patrocínio","4125357"],["PR","São José da Boa Vista","4125407"],["PR","São José das Palmeiras","4125456"],["PR","São José dos Pinhais","4125506"],["PR","São Manoel do Paraná","4125555"],["PR","São Mateus do Sul","4125605"],["PR","São Miguel do Iguaçu","4125704"],["PR","São Pedro do Iguaçu","4125753"],["PR","São Pedro do Ivaí","4125803"],["PR","São Pedro do Paraná","4125902"],["PR","São Sebastião da Amoreira","4126009"],["PR","São Tomé","4126108"],["PR","Sapopema","4126207"],["PR","Sarandi","4126256"],["PR","Saudade do Iguaçu","4126272"],["PR","Sengés","4126306"],["PR","Serranópolis do Iguaçu","4126355"],["PR","Sertaneja","4126405"],["PR","Sertanópolis","4126504"],["PR","Siqueira Campos","4126603"],["PR","Sulina","4126652"],["PR","Tamarana","4126678"],["PR","Tamboara","4126702"],["PR","Tapejara","4126801"],["PR","Tapira","4126900"],["PR","Teixeira Soares","4127007"],["PR","Telêmaco Borba","4127106"],["PR","Terra Boa","4127205"],["PR","Terra Rica","4127304"],["PR","Terra Roxa","4127403"],["PR","Tibagi","4127502"],["PR","Tijucas do Sul","4127601"],["PR","Toledo","4127700"],["PR","Tomazina","4127809"],["PR","Três Barras do Paraná","4127858"],["PR","Tunas do Paraná","4127882"],["PR","Tuneiras do Oeste","4127908"],["PR","Tupãssi","4127957"],["PR","Turvo","4127965"],["PR","Ubiratã","4128005"],["PR","Umuarama","4128104"],["PR","União da Vitória","4128203"],["PR","Uniflor","4128302"],["PR","Uraí","4128401"],["PR","Ventania","4128534"],["PR","Vera Cruz do Oeste","4128559"],["PR","Verê","4128609"],["PR","Virmond","4128658"],["PR","Vitorino","4128708"],["PR","Wenceslau Braz","4128500"],["PR","Xambrê","4128807"],["PE","Abreu e Lima","2600054"],["PE","Afogados da Ingazeira","2600104"],["PE","Afrânio","2600203"],["PE","Agrestina","2600302"],["PE","Água Preta","2600401"],["PE","Águas Belas","2600500"],["PE","Alagoinha","2600609"],["PE","Aliança","2600708"],["PE","Altinho","2600807"],["PE","Amaraji","2600906"],["PE","Angelim","2601003"],["PE","Araçoiaba","2601052"],["PE","Araripina","2601102"],["PE","Arcoverde","2601201"],["PE","Barra de Guabiraba","2601300"],["PE","Barreiros","2601409"],["PE","Belém de Maria","2601508"],["PE","Belém do São Francisco","2601607"],["PE","Belo Jardim","2601706"],["PE","Betânia","2601805"],["PE","Bezerros","2601904"],["PE","Bodocó","2602001"],["PE","Bom Conselho","2602100"],["PE","Bom Jardim","2602209"],["PE","Bonito","2602308"],["PE","Brejão","2602407"],["PE","Brejinho","2602506"],["PE","Brejo da Madre de Deus","2602605"],["PE","Buenos Aires","2602704"],["PE","Buíque","2602803"],["PE","Cabo de Santo Agostinho","2602902"],["PE","Cabrobó","2603009"],["PE","Cachoeirinha","2603108"],["PE","Caetés","2603207"],["PE","Calçado","2603306"],["PE","Calumbi","2603405"],["PE","Camaragibe","2603454"],["PE","Camocim de São Félix","2603504"],["PE","Camutanga","2603603"],["PE","Canhotinho","2603702"],["PE","Capoeiras","2603801"],["PE","Carnaíba","2603900"],["PE","Carnaubeira da Penha","2603926"],["PE","Carpina","2604007"],["PE","Caruaru","2604106"],["PE","Casinhas","2604155"],["PE","Catende","2604205"],["PE","Cedro","2604304"],["PE","Chã de Alegria","2604403"],["PE","Chã Grande","2604502"],["PE","Condado","2604601"],["PE","Correntes","2604700"],["PE","Cortês","2604809"],["PE","Cumaru","2604908"],["PE","Cupira","2605004"],["PE","Custódia","2605103"],["PE","Dormentes","2605152"],["PE","Escada","2605202"],["PE","Exu","2605301"],["PE","Feira Nova","2605400"],["PE","Fernando de Noronha","2605459"],["PE","Ferreiros","2605509"],["PE","Flores","2605608"],["PE","Floresta","2605707"],["PE","Frei Miguelinho","2605806"],["PE","Gameleira","2605905"],["PE","Garanhuns","2606002"],["PE","Glória do Goitá","2606101"],["PE","Goiana","2606200"],["PE","Granito","2606309"],["PE","Gravatá","2606408"],["PE","Iati","2606507"],["PE","Ibimirim","2606606"],["PE","Ibirajuba","2606705"],["PE","Igarassu","2606804"],["PE","Iguaracy","2606903"],["PE","Ilha de Itamaracá","2607604"],["PE","Inajá","2607000"],["PE","Ingazeira","2607109"],["PE","Ipojuca","2607208"],["PE","Ipubi","2607307"],["PE","Itacuruba","2607406"],["PE","Itaíba","2607505"],["PE","Itambé","2607653"],["PE","Itapetim","2607703"],["PE","Itapissuma","2607752"],["PE","Itaquitinga","2607802"],["PE","Jaboatão dos Guararapes","2607901"],["PE","Jaqueira","2607950"],["PE","Jataúba","2608008"],["PE","Jatobá","2608057"],["PE","João Alfredo","2608107"],["PE","Joaquim Nabuco","2608206"],["PE","Jucati","2608255"],["PE","Jupi","2608305"],["PE","Jurema","2608404"],["PE","Lagoa de Itaenga","2608503"],["PE","Lagoa do Carro","2608453"],["PE","Lagoa do Ouro","2608602"],["PE","Lagoa dos Gatos","2608701"],["PE","Lagoa Grande","2608750"],["PE","Lajedo","2608800"],["PE","Limoeiro","2608909"],["PE","Macaparana","2609006"],["PE","Machados","2609105"],["PE","Manari","2609154"],["PE","Maraial","2609204"],["PE","Mirandiba","2609303"],["PE","Moreilândia","2614303"],["PE","Moreno","2609402"],["PE","Nazaré da Mata","2609501"],["PE","Olinda","2609600"],["PE","Orobó","2609709"],["PE","Orocó","2609808"],["PE","Ouricuri","2609907"],["PE","Palmares","2610004"],["PE","Palmeirina","2610103"],["PE","Panelas","2610202"],["PE","Paranatama","2610301"],["PE","Parnamirim","2610400"],["PE","Passira","2610509"],["PE","Paudalho","2610608"],["PE","Paulista","2610707"],["PE","Pedra","2610806"],["PE","Pesqueira","2610905"],["PE","Petrolândia","2611002"],["PE","Petrolina","2611101"],["PE","Poção","2611200"],["PE","Pombos","2611309"],["PE","Primavera","2611408"],["PE","Quipapá","2611507"],["PE","Quixaba","2611533"],["PE","Recife","2611606"],["PE","Riacho das Almas","2611705"],["PE","Ribeirão","2611804"],["PE","Rio Formoso","2611903"],["PE","Sairé","2612000"],["PE","Salgadinho","2612109"],["PE","Salgueiro","2612208"],["PE","Saloá","2612307"],["PE","Sanharó","2612406"],["PE","Santa Cruz","2612455"],["PE","Santa Cruz da Baixa Verde","2612471"],["PE","Santa Cruz do Capibaribe","2612505"],["PE","Santa Filomena","2612554"],["PE","Santa Maria da Boa Vista","2612604"],["PE","Santa Maria do Cambucá","2612703"],["PE","Santa Terezinha","2612802"],["PE","São Benedito do Sul","2612901"],["PE","São Bento do Una","2613008"],["PE","São Caitano","2613107"],["PE","São João","2613206"],["PE","São Joaquim do Monte","2613305"],["PE","São José da Coroa Grande","2613404"],["PE","São José do Belmonte","2613503"],["PE","São José do Egito","2613602"],["PE","São Lourenço da Mata","2613701"],["PE","São Vicente Férrer","2613800"],["PE","Serra Talhada","2613909"],["PE","Serrita","2614006"],["PE","Sertânia","2614105"],["PE","Sirinhaém","2614204"],["PE","Solidão","2614402"],["PE","Surubim","2614501"],["PE","Tabira","2614600"],["PE","Tacaimbó","2614709"],["PE","Tacaratu","2614808"],["PE","Tamandaré","2614857"],["PE","Taquaritinga do Norte","2615003"],["PE","Terezinha","2615102"],["PE","Terra Nova","2615201"],["PE","Timbaúba","2615300"],["PE","Toritama","2615409"],["PE","Tracunhaém","2615508"],["PE","Trindade","2615607"],["PE","Triunfo","2615706"],["PE","Tupanatinga","2615805"],["PE","Tuparetama","2615904"],["PE","Venturosa","2616001"],["PE","Verdejante","2616100"],["PE","Vertente do Lério","2616183"],["PE","Vertentes","2616209"],["PE","Vicência","2616308"],["PE","Vitória de Santo Antão","2616407"],["PE","Xexéu","2616506"],["PI","Acauã","2200053"],["PI","Agricolândia","2200103"],["PI","Água Branca","2200202"],["PI","Alagoinha do Piauí","2200251"],["PI","Alegrete do Piauí","2200277"],["PI","Alto Longá","2200301"],["PI","Altos","2200400"],["PI","Alvorada do Gurguéia","2200459"],["PI","Amarante","2200509"],["PI","Angical do Piauí","2200608"],["PI","Anísio de Abreu","2200707"],["PI","Antônio Almeida","2200806"],["PI","Aroazes","2200905"],["PI","Aroeiras do Itaim","2200954"],["PI","Arraial","2201002"],["PI","Assunção do Piauí","2201051"],["PI","Avelino Lopes","2201101"],["PI","Baixa Grande do Ribeiro","2201150"],["PI","Barra D'Alcântara","2201176"],["PI","Barras","2201200"],["PI","Barreiras do Piauí","2201309"],["PI","Barro Duro","2201408"],["PI","Batalha","2201507"],["PI","Bela Vista do Piauí","2201556"],["PI","Belém do Piauí","2201572"],["PI","Beneditinos","2201606"],["PI","Bertolínia","2201705"],["PI","Betânia do Piauí","2201739"],["PI","Boa Hora","2201770"],["PI","Bocaina","2201804"],["PI","Bom Jesus","2201903"],["PI","Bom Princípio do Piauí","2201919"],["PI","Bonfim do Piauí","2201929"],["PI","Boqueirão do Piauí","2201945"],["PI","Brasileira","2201960"],["PI","Brejo do Piauí","2201988"],["PI","Buriti dos Lopes","2202000"],["PI","Buriti dos Montes","2202026"],["PI","Cabeceiras do Piauí","2202059"],["PI","Cajazeiras do Piauí","2202075"],["PI","Cajueiro da Praia","2202083"],["PI","Caldeirão Grande do Piauí","2202091"],["PI","Campinas do Piauí","2202109"],["PI","Campo Alegre do Fidalgo","2202117"],["PI","Campo Grande do Piauí","2202133"],["PI","Campo Largo do Piauí","2202174"],["PI","Campo Maior","2202208"],["PI","Canavieira","2202251"],["PI","Canto do Buriti","2202307"],["PI","Capitão de Campos","2202406"],["PI","Capitão Gervásio Oliveira","2202455"],["PI","Caracol","2202505"],["PI","Caraúbas do Piauí","2202539"],["PI","Caridade do Piauí","2202554"],["PI","Castelo do Piauí","2202604"],["PI","Caxingó","2202653"],["PI","Cocal","2202703"],["PI","Cocal de Telha","2202711"],["PI","Cocal dos Alves","2202729"],["PI","Coivaras","2202737"],["PI","Colônia do Gurguéia","2202752"],["PI","Colônia do Piauí","2202778"],["PI","Conceição do Canindé","2202802"],["PI","Coronel José Dias","2202851"],["PI","Corrente","2202901"],["PI","Cristalândia do Piauí","2203008"],["PI","Cristino Castro","2203107"],["PI","Curimatá","2203206"],["PI","Currais","2203230"],["PI","Curral Novo do Piauí","2203271"],["PI","Curralinhos","2203255"],["PI","Demerval Lobão","2203305"],["PI","Dirceu Arcoverde","2203354"],["PI","Dom Expedito Lopes","2203404"],["PI","Dom Inocêncio","2203453"],["PI","Domingos Mourão","2203420"],["PI","Elesbão Veloso","2203503"],["PI","Eliseu Martins","2203602"],["PI","Esperantina","2203701"],["PI","Fartura do Piauí","2203750"],["PI","Flores do Piauí","2203800"],["PI","Floresta do Piauí","2203859"],["PI","Floriano","2203909"],["PI","Francinópolis","2204006"],["PI","Francisco Ayres","2204105"],["PI","Francisco Macedo","2204154"],["PI","Francisco Santos","2204204"],["PI","Fronteiras","2204303"],["PI","Geminiano","2204352"],["PI","Gilbués","2204402"],["PI","Guadalupe","2204501"],["PI","Guaribas","2204550"],["PI","Hugo Napoleão","2204600"],["PI","Ilha Grande","2204659"],["PI","Inhuma","2204709"],["PI","Ipiranga do Piauí","2204808"],["PI","Isaías Coelho","2204907"],["PI","Itainópolis","2205003"],["PI","Itaueira","2205102"],["PI","Jacobina do Piauí","2205151"],["PI","Jaicós","2205201"],["PI","Jardim do Mulato","2205250"],["PI","Jatobá do Piauí","2205276"],["PI","Jerumenha","2205300"],["PI","João Costa","2205359"],["PI","Joaquim Pires","2205409"],["PI","Joca Marques","2205458"],["PI","José de Freitas","2205508"],["PI","Juazeiro do Piauí","2205516"],["PI","Júlio Borges","2205524"],["PI","Jurema","2205532"],["PI","Lagoa Alegre","2205557"],["PI","Lagoa de São Francisco","2205573"],["PI","Lagoa do Barro do Piauí","2205565"],["PI","Lagoa do Piauí","2205581"],["PI","Lagoa do Sítio","2205599"],["PI","Lagoinha do Piauí","2205540"],["PI","Landri Sales","2205607"],["PI","Luís Correia","2205706"],["PI","Luzilândia","2205805"],["PI","Madeiro","2205854"],["PI","Manoel Emídio","2205904"],["PI","Marcolândia","2205953"],["PI","Marcos Parente","2206001"],["PI","Massapê do Piauí","2206050"],["PI","Matias Olímpio","2206100"],["PI","Miguel Alves","2206209"],["PI","Miguel Leão","2206308"],["PI","Milton Brandão","2206357"],["PI","Monsenhor Gil","2206407"],["PI","Monsenhor Hipólito","2206506"],["PI","Monte Alegre do Piauí","2206605"],["PI","Morro Cabeça no Tempo","2206654"],["PI","Morro do Chapéu do Piauí","2206670"],["PI","Murici dos Portelas","2206696"],["PI","Nazaré do Piauí","2206704"],["PI","Nazária","2206720"],["PI","Nossa Senhora de Nazaré","2206753"],["PI","Nossa Senhora dos Remédios","2206803"],["PI","Nova Santa Rita","2207959"],["PI","Novo Oriente do Piauí","2206902"],["PI","Novo Santo Antônio","2206951"],["PI","Oeiras","2207009"],["PI","Olho D'Água do Piauí","2207108"],["PI","Padre Marcos","2207207"],["PI","Paes Landim","2207306"],["PI","Pajeú do Piauí","2207355"],["PI","Palmeira do Piauí","2207405"],["PI","Palmeirais","2207504"],["PI","Paquetá","2207553"],["PI","Parnaguá","2207603"],["PI","Parnaíba","2207702"],["PI","Passagem Franca do Piauí","2207751"],["PI","Patos do Piauí","2207777"],["PI","Pau D'Arco do Piauí","2207793"],["PI","Paulistana","2207801"],["PI","Pavussu","2207850"],["PI","Pedro II","2207900"],["PI","Pedro Laurentino","2207934"],["PI","Picos","2208007"],["PI","Pimenteiras","2208106"],["PI","Pio IX","2208205"],["PI","Piracuruca","2208304"],["PI","Piripiri","2208403"],["PI","Porto","2208502"],["PI","Porto Alegre do Piauí","2208551"],["PI","Prata do Piauí","2208601"],["PI","Queimada Nova","2208650"],["PI","Redenção do Gurguéia","2208700"],["PI","Regeneração","2208809"],["PI","Riacho Frio","2208858"],["PI","Ribeira do Piauí","2208874"],["PI","Ribeiro Gonçalves","2208908"],["PI","Rio Grande do Piauí","2209005"],["PI","Santa Cruz do Piauí","2209104"],["PI","Santa Cruz dos Milagres","2209153"],["PI","Santa Filomena","2209203"],["PI","Santa Luz","2209302"],["PI","Santa Rosa do Piauí","2209377"],["PI","Santana do Piauí","2209351"],["PI","Santo Antônio de Lisboa","2209401"],["PI","Santo Antônio dos Milagres","2209450"],["PI","Santo Inácio do Piauí","2209500"],["PI","São Braz do Piauí","2209559"],["PI","São Félix do Piauí","2209609"],["PI","São Francisco de Assis do Piauí","2209658"],["PI","São Francisco do Piauí","2209708"],["PI","São Gonçalo do Gurguéia","2209757"],["PI","São Gonçalo do Piauí","2209807"],["PI","São João da Canabrava","2209856"],["PI","São João da Fronteira","2209872"],["PI","São João da Serra","2209906"],["PI","São João da Varjota","2209955"],["PI","São João do Arraial","2209971"],["PI","São João do Piauí","2210003"],["PI","São José do Divino","2210052"],["PI","São José do Peixe","2210102"],["PI","São José do Piauí","2210201"],["PI","São Julião","2210300"],["PI","São Lourenço do Piauí","2210359"],["PI","São Luis do Piauí","2210375"],["PI","São Miguel da Baixa Grande","2210383"],["PI","São Miguel do Fidalgo","2210391"],["PI","São Miguel do Tapuio","2210409"],["PI","São Pedro do Piauí","2210508"],["PI","São Raimundo Nonato","2210607"],["PI","Sebastião Barros","2210623"],["PI","Sebastião Leal","2210631"],["PI","Sigefredo Pacheco","2210656"],["PI","Simões","2210706"],["PI","Simplício Mendes","2210805"],["PI","Socorro do Piauí","2210904"],["PI","Sussuapara","2210938"],["PI","Tamboril do Piauí","2210953"],["PI","Tanque do Piauí","2210979"],["PI","Teresina","2211001"],["PI","União","2211100"],["PI","Uruçuí","2211209"],["PI","Valença do Piauí","2211308"],["PI","Várzea Branca","2211357"],["PI","Várzea Grande","2211407"],["PI","Vera Mendes","2211506"],["PI","Vila Nova do Piauí","2211605"],["PI","Wall Ferraz","2211704"],["RJ","Angra dos Reis","3300100"],["RJ","Aperibé","3300159"],["RJ","Araruama","3300209"],["RJ","Areal","3300225"],["RJ","Armação dos Búzios","3300233"],["RJ","Arraial do Cabo","3300258"],["RJ","Barra do Piraí","3300308"],["RJ","Barra Mansa","3300407"],["RJ","Belford Roxo","3300456"],["RJ","Bom Jardim","3300506"],["RJ","Bom Jesus do Itabapoana","3300605"],["RJ","Cabo Frio","3300704"],["RJ","Cachoeiras de Macacu","3300803"],["RJ","Cambuci","3300902"],["RJ","Campos dos Goytacazes","3301009"],["RJ","Cantagalo","3301108"],["RJ","Carapebus","3300936"],["RJ","Cardoso Moreira","3301157"],["RJ","Carmo","3301207"],["RJ","Casimiro de Abreu","3301306"],["RJ","Comendador Levy Gasparian","3300951"],["RJ","Conceição de Macabu","3301405"],["RJ","Cordeiro","3301504"],["RJ","Duas Barras","3301603"],["RJ","Duque de Caxias","3301702"],["RJ","Engenheiro Paulo de Frontin","3301801"],["RJ","Guapimirim","3301850"],["RJ","Iguaba Grande","3301876"],["RJ","Itaboraí","3301900"],["RJ","Itaguaí","3302007"],["RJ","Italva","3302056"],["RJ","Itaocara","3302106"],["RJ","Itaperuna","3302205"],["RJ","Itatiaia","3302254"],["RJ","Japeri","3302270"],["RJ","Laje do Muriaé","3302304"],["RJ","Macaé","3302403"],["RJ","Macuco","3302452"],["RJ","Magé","3302502"],["RJ","Mangaratiba","3302601"],["RJ","Maricá","3302700"],["RJ","Mendes","3302809"],["RJ","Mesquita","3302858"],["RJ","Miguel Pereira","3302908"],["RJ","Miracema","3303005"],["RJ","Natividade","3303104"],["RJ","Nilópolis","3303203"],["RJ","Niterói","3303302"],["RJ","Nova Friburgo","3303401"],["RJ","Nova Iguaçu","3303500"],["RJ","Paracambi","3303609"],["RJ","Paraíba do Sul","3303708"],["RJ","Paraty","3303807"],["RJ","Paty do Alferes","3303856"],["RJ","Petrópolis","3303906"],["RJ","Pinheiral","3303955"],["RJ","Piraí","3304003"],["RJ","Porciúncula","3304102"],["RJ","Porto Real","3304110"],["RJ","Quatis","3304128"],["RJ","Queimados","3304144"],["RJ","Quissamã","3304151"],["RJ","Resende","3304201"],["RJ","Rio Bonito","3304300"],["RJ","Rio Claro","3304409"],["RJ","Rio das Flores","3304508"],["RJ","Rio das Ostras","3304524"],["RJ","Rio de Janeiro","3304557"],["RJ","Santa Maria Madalena","3304607"],["RJ","Santo Antônio de Pádua","3304706"],["RJ","São Fidélis","3304805"],["RJ","São Francisco de Itabapoana","3304755"],["RJ","São Gonçalo","3304904"],["RJ","São João da Barra","3305000"],["RJ","São João de Meriti","3305109"],["RJ","São José de Ubá","3305133"],["RJ","São José do Vale do Rio Preto","3305158"],["RJ","São Pedro da Aldeia","3305208"],["RJ","São Sebastião do Alto","3305307"],["RJ","Sapucaia","3305406"],["RJ","Saquarema","3305505"],["RJ","Seropédica","3305554"],["RJ","Silva Jardim","3305604"],["RJ","Sumidouro","3305703"],["RJ","Tanguá","3305752"],["RJ","Teresópolis","3305802"],["RJ","Trajano de Moraes","3305901"],["RJ","Três Rios","3306008"],["RJ","Valença","3306107"],["RJ","Varre-Sai","3306156"],["RJ","Vassouras","3306206"],["RJ","Volta Redonda","3306305"],["RN","Acari","2400109"],["RN","Afonso Bezerra","2400307"],["RN","Água Nova","2400406"],["RN","Alexandria","2400505"],["RN","Almino Afonso","2400604"],["RN","Alto do Rodrigues","2400703"],["RN","Angicos","2400802"],["RN","Antônio Martins","2400901"],["RN","Apodi","2401008"],["RN","Areia Branca","2401107"],["RN","Arez","2401206"],["RN","Assú","2400208"],["RN","Baía Formosa","2401404"],["RN","Baraúna","2401453"],["RN","Barcelona","2401503"],["RN","Bento Fernandes","2401602"],["RN","Bodó","2401651"],["RN","Bom Jesus","2401701"],["RN","Brejinho","2401800"],["RN","Caiçara do Norte","2401859"],["RN","Caiçara do Rio do Vento","2401909"],["RN","Caicó","2402006"],["RN","Campo Grande","2401305"],["RN","Campo Redondo","2402105"],["RN","Canguaretama","2402204"],["RN","Caraúbas","2402303"],["RN","Carnaúba dos Dantas","2402402"],["RN","Carnaubais","2402501"],["RN","Ceará-Mirim","2402600"],["RN","Cerro Corá","2402709"],["RN","Coronel Ezequiel","2402808"],["RN","Coronel João Pessoa","2402907"],["RN","Cruzeta","2403004"],["RN","Currais Novos","2403103"],["RN","Doutor Severiano","2403202"],["RN","Encanto","2403301"],["RN","Equador","2403400"],["RN","Espírito Santo","2403509"],["RN","Extremoz","2403608"],["RN","Felipe Guerra","2403707"],["RN","Fernando Pedroza","2403756"],["RN","Florânia","2403806"],["RN","Francisco Dantas","2403905"],["RN","Frutuoso Gomes","2404002"],["RN","Galinhos","2404101"],["RN","Goianinha","2404200"],["RN","Governador Dix-Sept Rosado","2404309"],["RN","Grossos","2404408"],["RN","Guamaré","2404507"],["RN","Ielmo Marinho","2404606"],["RN","Ipanguaçu","2404705"],["RN","Ipueira","2404804"],["RN","Itajá","2404853"],["RN","Itaú","2404903"],["RN","Jaçanã","2405009"],["RN","Jandaíra","2405108"],["RN","Janduís","2405207"],["RN","Januário Cicco","2405306"],["RN","Japi","2405405"],["RN","Jardim de Angicos","2405504"],["RN","Jardim de Piranhas","2405603"],["RN","Jardim do Seridó","2405702"],["RN","João Câmara","2405801"],["RN","João Dias","2405900"],["RN","José da Penha","2406007"],["RN","Jucurutu","2406106"],["RN","Jundiá","2406155"],["RN","Lagoa d'Anta","2406205"],["RN","Lagoa de Pedras","2406304"],["RN","Lagoa de Velhos","2406403"],["RN","Lagoa Nova","2406502"],["RN","Lagoa Salgada","2406601"],["RN","Lajes","2406700"],["RN","Lajes Pintadas","2406809"],["RN","Lucrécia","2406908"],["RN","Luís Gomes","2407005"],["RN","Macaíba","2407104"],["RN","Macau","2407203"],["RN","Major Sales","2407252"],["RN","Marcelino Vieira","2407302"],["RN","Martins","2407401"],["RN","Maxaranguape","2407500"],["RN","Messias Targino","2407609"],["RN","Montanhas","2407708"],["RN","Monte Alegre","2407807"],["RN","Monte das Gameleiras","2407906"],["RN","Mossoró","2408003"],["RN","Natal","2408102"],["RN","Nísia Floresta","2408201"],["RN","Nova Cruz","2408300"],["RN","Olho d'Água do Borges","2408409"],["RN","Ouro Branco","2408508"],["RN","Paraná","2408607"],["RN","Paraú","2408706"],["RN","Parazinho","2408805"],["RN","Parelhas","2408904"],["RN","Parnamirim","2403251"],["RN","Passa e Fica","2409100"],["RN","Passagem","2409209"],["RN","Patu","2409308"],["RN","Pau dos Ferros","2409407"],["RN","Pedra Grande","2409506"],["RN","Pedra Preta","2409605"],["RN","Pedro Avelino","2409704"],["RN","Pedro Velho","2409803"],["RN","Pendências","2409902"],["RN","Pilões","2410009"],["RN","Poço Branco","2410108"],["RN","Portalegre","2410207"],["RN","Porto do Mangue","2410256"],["RN","Pureza","2410405"],["RN","Rafael Fernandes","2410504"],["RN","Rafael Godeiro","2410603"],["RN","Riacho da Cruz","2410702"],["RN","Riacho de Santana","2410801"],["RN","Riachuelo","2410900"],["RN","Rio do Fogo","2408953"],["RN","Rodolfo Fernandes","2411007"],["RN","Ruy Barbosa","2411106"],["RN","Santa Cruz","2411205"],["RN","Santa Maria","2409332"],["RN","Santana do Matos","2411403"],["RN","Santana do Seridó","2411429"],["RN","Santo Antônio","2411502"],["RN","São Bento do Norte","2411601"],["RN","São Bento do Trairí","2411700"],["RN","São Fernando","2411809"],["RN","São Francisco do Oeste","2411908"],["RN","São Gonçalo do Amarante","2412005"],["RN","São João do Sabugi","2412104"],["RN","São José de Mipibu","2412203"],["RN","São José do Campestre","2412302"],["RN","São José do Seridó","2412401"],["RN","São Miguel","2412500"],["RN","São Miguel do Gostoso","2412559"],["RN","São Paulo do Potengi","2412609"],["RN","São Pedro","2412708"],["RN","São Rafael","2412807"],["RN","São Tomé","2412906"],["RN","São Vicente","2413003"],["RN","Senador Elói de Souza","2413102"],["RN","Senador Georgino Avelino","2413201"],["RN","Serra Caiada","2410306"],["RN","Serra de São Bento","2413300"],["RN","Serra do Mel","2413359"],["RN","Serra Negra do Norte","2413409"],["RN","Serrinha","2413508"],["RN","Serrinha dos Pintos","2413557"],["RN","Severiano Melo","2413607"],["RN","Sítio Novo","2413706"],["RN","Taboleiro Grande","2413805"],["RN","Taipu","2413904"],["RN","Tangará","2414001"],["RN","Tenente Ananias","2414100"],["RN","Tenente Laurentino Cruz","2414159"],["RN","Tibau","2411056"],["RN","Tibau do Sul","2414209"],["RN","Timbaúba dos Batistas","2414308"],["RN","Touros","2414407"],["RN","Triunfo Potiguar","2414456"],["RN","Umarizal","2414506"],["RN","Upanema","2414605"],["RN","Várzea","2414704"],["RN","Venha-Ver","2414753"],["RN","Vera Cruz","2414803"],["RN","Viçosa","2414902"],["RN","Vila Flor","2415008"],["RS","Aceguá","4300034"],["RS","Água Santa","4300059"],["RS","Agudo","4300109"],["RS","Ajuricaba","4300208"],["RS","Alecrim","4300307"],["RS","Alegrete","4300406"],["RS","Alegria","4300455"],["RS","Almirante Tamandaré do Sul","4300471"],["RS","Alpestre","4300505"],["RS","Alto Alegre","4300554"],["RS","Alto Feliz","4300570"],["RS","Alvorada","4300604"],["RS","Amaral Ferrador","4300638"],["RS","Ametista do Sul","4300646"],["RS","André da Rocha","4300661"],["RS","Anta Gorda","4300703"],["RS","Antônio Prado","4300802"],["RS","Arambaré","4300851"],["RS","Araricá","4300877"],["RS","Aratiba","4300901"],["RS","Arroio do Meio","4301008"],["RS","Arroio do Padre","4301073"],["RS","Arroio do Sal","4301057"],["RS","Arroio do Tigre","4301206"],["RS","Arroio dos Ratos","4301107"],["RS","Arroio Grande","4301305"],["RS","Arvorezinha","4301404"],["RS","Augusto Pestana","4301503"],["RS","Áurea","4301552"],["RS","Bagé","4301602"],["RS","Balneário Pinhal","4301636"],["RS","Barão","4301651"],["RS","Barão de Cotegipe","4301701"],["RS","Barão do Triunfo","4301750"],["RS","Barra do Guarita","4301859"],["RS","Barra do Quaraí","4301875"],["RS","Barra do Ribeiro","4301909"],["RS","Barra do Rio Azul","4301925"],["RS","Barra Funda","4301958"],["RS","Barracão","4301800"],["RS","Barros Cassal","4302006"],["RS","Benjamin Constant do Sul","4302055"],["RS","Bento Gonçalves","4302105"],["RS","Boa Vista das Missões","4302154"],["RS","Boa Vista do Buricá","4302204"],["RS","Boa Vista do Cadeado","4302220"],["RS","Boa Vista do Incra","4302238"],["RS","Boa Vista do Sul","4302253"],["RS","Bom Jesus","4302303"],["RS","Bom Princípio","4302352"],["RS","Bom Progresso","4302378"],["RS","Bom Retiro do Sul","4302402"],["RS","Boqueirão do Leão","4302451"],["RS","Bossoroca","4302501"],["RS","Bozano","4302584"],["RS","Braga","4302600"],["RS","Brochier","4302659"],["RS","Butiá","4302709"],["RS","Caçapava do Sul","4302808"],["RS","Cacequi","4302907"],["RS","Cachoeira do Sul","4303004"],["RS","Cachoeirinha","4303103"],["RS","Cacique Doble","4303202"],["RS","Caibaté","4303301"],["RS","Caiçara","4303400"],["RS","Camaquã","4303509"],["RS","Camargo","4303558"],["RS","Cambará do Sul","4303608"],["RS","Campestre da Serra","4303673"],["RS","Campina das Missões","4303707"],["RS","Campinas do Sul","4303806"],["RS","Campo Bom","4303905"],["RS","Campo Novo","4304002"],["RS","Campos Borges","4304101"],["RS","Candelária","4304200"],["RS","Cândido Godói","4304309"],["RS","Candiota","4304358"],["RS","Canela","4304408"],["RS","Canguçu","4304507"],["RS","Canoas","4304606"],["RS","Canudos do Vale","4304614"],["RS","Capão Bonito do Sul","4304622"],["RS","Capão da Canoa","4304630"],["RS","Capão do Cipó","4304655"],["RS","Capão do Leão","4304663"],["RS","Capela de Santana","4304689"],["RS","Capitão","4304697"],["RS","Capivari do Sul","4304671"],["RS","Caraá","4304713"],["RS","Carazinho","4304705"],["RS","Carlos Barbosa","4304804"],["RS","Carlos Gomes","4304853"],["RS","Casca","4304903"],["RS","Caseiros","4304952"],["RS","Catuípe","4305009"],["RS","Caxias do Sul","4305108"],["RS","Centenário","4305116"],["RS","Cerrito","4305124"],["RS","Cerro Branco","4305132"],["RS","Cerro Grande","4305157"],["RS","Cerro Grande do Sul","4305173"],["RS","Cerro Largo","4305207"],["RS","Chapada","4305306"],["RS","Charqueadas","4305355"],["RS","Charrua","4305371"],["RS","Chiapetta","4305405"],["RS","Chuí","4305439"],["RS","Chuvisca","4305447"],["RS","Cidreira","4305454"],["RS","Ciríaco","4305504"],["RS","Colinas","4305587"],["RS","Colorado","4305603"],["RS","Condor","4305702"],["RS","Constantina","4305801"],["RS","Coqueiro Baixo","4305835"],["RS","Coqueiros do Sul","4305850"],["RS","Coronel Barros","4305871"],["RS","Coronel Bicaco","4305900"],["RS","Coronel Pilar","4305934"],["RS","Cotiporã","4305959"],["RS","Coxilha","4305975"],["RS","Crissiumal","4306007"],["RS","Cristal","4306056"],["RS","Cristal do Sul","4306072"],["RS","Cruz Alta","4306106"],["RS","Cruzaltense","4306130"],["RS","Cruzeiro do Sul","4306205"],["RS","David Canabarro","4306304"],["RS","Derrubadas","4306320"],["RS","Dezesseis de Novembro","4306353"],["RS","Dilermando de Aguiar","4306379"],["RS","Dois Irmãos","4306403"],["RS","Dois Irmãos das Missões","4306429"],["RS","Dois Lajeados","4306452"],["RS","Dom Feliciano","4306502"],["RS","Dom Pedrito","4306601"],["RS","Dom Pedro de Alcântara","4306551"],["RS","Dona Francisca","4306700"],["RS","Doutor Maurício Cardoso","4306734"],["RS","Doutor Ricardo","4306759"],["RS","Eldorado do Sul","4306767"],["RS","Encantado","4306809"],["RS","Encruzilhada do Sul","4306908"],["RS","Engenho Velho","4306924"],["RS","Entre Rios do Sul","4306957"],["RS","Entre-Ijuís","4306932"],["RS","Erebango","4306973"],["RS","Erechim","4307005"],["RS","Ernestina","4307054"],["RS","Erval Grande","4307203"],["RS","Erval Seco","4307302"],["RS","Esmeralda","4307401"],["RS","Esperança do Sul","4307450"],["RS","Espumoso","4307500"],["RS","Estação","4307559"],["RS","Estância Velha","4307609"],["RS","Esteio","4307708"],["RS","Estrela","4307807"],["RS","Estrela Velha","4307815"],["RS","Eugênio de Castro","4307831"],["RS","Fagundes Varela","4307864"],["RS","Farroupilha","4307906"],["RS","Faxinal do Soturno","4308003"],["RS","Faxinalzinho","4308052"],["RS","Fazenda Vilanova","4308078"],["RS","Feliz","4308102"],["RS","Flores da Cunha","4308201"],["RS","Floriano Peixoto","4308250"],["RS","Fontoura Xavier","4308300"],["RS","Formigueiro","4308409"],["RS","Forquetinha","4308433"],["RS","Fortaleza dos Valos","4308458"],["RS","Frederico Westphalen","4308508"],["RS","Garibaldi","4308607"],["RS","Garruchos","4308656"],["RS","Gaurama","4308706"],["RS","General Câmara","4308805"],["RS","Gentil","4308854"],["RS","Getúlio Vargas","4308904"],["RS","Giruá","4309001"],["RS","Glorinha","4309050"],["RS","Gramado","4309100"],["RS","Gramado dos Loureiros","4309126"],["RS","Gramado Xavier","4309159"],["RS","Gravataí","4309209"],["RS","Guabiju","4309258"],["RS","Guaíba","4309308"],["RS","Guaporé","4309407"],["RS","Guarani das Missões","4309506"],["RS","Harmonia","4309555"],["RS","Herval","4307104"],["RS","Herveiras","4309571"],["RS","Horizontina","4309605"],["RS","Hulha Negra","4309654"],["RS","Humaitá","4309704"],["RS","Ibarama","4309753"],["RS","Ibiaçá","4309803"],["RS","Ibiraiaras","4309902"],["RS","Ibirapuitã","4309951"],["RS","Ibirubá","4310009"],["RS","Igrejinha","4310108"],["RS","Ijuí","4310207"],["RS","Ilópolis","4310306"],["RS","Imbé","4310330"],["RS","Imigrante","4310363"],["RS","Independência","4310405"],["RS","Inhacorá","4310413"],["RS","Ipê","4310439"],["RS","Ipiranga do Sul","4310462"],["RS","Iraí","4310504"],["RS","Itaara","4310538"],["RS","Itacurubi","4310553"],["RS","Itapuca","4310579"],["RS","Itaqui","4310603"],["RS","Itati","4310652"],["RS","Itatiba do Sul","4310702"],["RS","Ivorá","4310751"],["RS","Ivoti","4310801"],["RS","Jaboticaba","4310850"],["RS","Jacuizinho","4310876"],["RS","Jacutinga","4310900"],["RS","Jaguarão","4311007"],["RS","Jaguari","4311106"],["RS","Jaquirana","4311122"],["RS","Jari","4311130"],["RS","Jóia","4311155"],["RS","Júlio de Castilhos","4311205"],["RS","Lagoa Bonita do Sul","4311239"],["RS","Lagoa dos Três Cantos","4311270"],["RS","Lagoa Vermelha","4311304"],["RS","Lagoão","4311254"],["RS","Lajeado","4311403"],["RS","Lajeado do Bugre","4311429"],["RS","Lavras do Sul","4311502"],["RS","Liberato Salzano","4311601"],["RS","Lindolfo Collor","4311627"],["RS","Linha Nova","4311643"],["RS","Maçambará","4311718"],["RS","Machadinho","4311700"],["RS","Mampituba","4311734"],["RS","Manoel Viana","4311759"],["RS","Maquiné","4311775"],["RS","Maratá","4311791"],["RS","Marau","4311809"],["RS","Marcelino Ramos","4311908"],["RS","Mariana Pimentel","4311981"],["RS","Mariano Moro","4312005"],["RS","Marques de Souza","4312054"],["RS","Mata","4312104"],["RS","Mato Castelhano","4312138"],["RS","Mato Leitão","4312153"],["RS","Mato Queimado","4312179"],["RS","Maximiliano de Almeida","4312203"],["RS","Minas do Leão","4312252"],["RS","Miraguaí","4312302"],["RS","Montauri","4312351"],["RS","Monte Alegre dos Campos","4312377"],["RS","Monte Belo do Sul","4312385"],["RS","Montenegro","4312401"],["RS","Mormaço","4312427"],["RS","Morrinhos do Sul","4312443"],["RS","Morro Redondo","4312450"],["RS","Morro Reuter","4312476"],["RS","Mostardas","4312500"],["RS","Muçum","4312609"],["RS","Muitos Capões","4312617"],["RS","Muliterno","4312625"],["RS","Não-Me-Toque","4312658"],["RS","Nicolau Vergueiro","4312674"],["RS","Nonoai","4312708"],["RS","Nova Alvorada","4312757"],["RS","Nova Araçá","4312807"],["RS","Nova Bassano","4312906"],["RS","Nova Boa Vista","4312955"],["RS","Nova Bréscia","4313003"],["RS","Nova Candelária","4313011"],["RS","Nova Esperança do Sul","4313037"],["RS","Nova Hartz","4313060"],["RS","Nova Pádua","4313086"],["RS","Nova Palma","4313102"],["RS","Nova Petrópolis","4313201"],["RS","Nova Prata","4313300"],["RS","Nova Ramada","4313334"],["RS","Nova Roma do Sul","4313359"],["RS","Nova Santa Rita","4313375"],["RS","Novo Barreiro","4313490"],["RS","Novo Cabrais","4313391"],["RS","Novo Hamburgo","4313409"],["RS","Novo Machado","4313425"],["RS","Novo Tiradentes","4313441"],["RS","Novo Xingu","4313466"],["RS","Osório","4313508"],["RS","Paim Filho","4313607"],["RS","Palmares do Sul","4313656"],["RS","Palmeira das Missões","4313706"],["RS","Palmitinho","4313805"],["RS","Panambi","4313904"],["RS","Pantano Grande","4313953"],["RS","Paraí","4314001"],["RS","Paraíso do Sul","4314027"],["RS","Pareci Novo","4314035"],["RS","Parobé","4314050"],["RS","Passa Sete","4314068"],["RS","Passo do Sobrado","4314076"],["RS","Passo Fundo","4314100"],["RS","Paulo Bento","4314134"],["RS","Paverama","4314159"],["RS","Pedras Altas","4314175"],["RS","Pedro Osório","4314209"],["RS","Pejuçara","4314308"],["RS","Pelotas","4314407"],["RS","Picada Café","4314423"],["RS","Pinhal","4314456"],["RS","Pinhal da Serra","4314464"],["RS","Pinhal Grande","4314472"],["RS","Pinheirinho do Vale","4314498"],["RS","Pinheiro Machado","4314506"],["RS","Pinto Bandeira","4314548"],["RS","Pirapó","4314555"],["RS","Piratini","4314605"],["RS","Planalto","4314704"],["RS","Poço das Antas","4314753"],["RS","Pontão","4314779"],["RS","Ponte Preta","4314787"],["RS","Portão","4314803"],["RS","Porto Alegre","4314902"],["RS","Porto Lucena","4315008"],["RS","Porto Mauá","4315057"],["RS","Porto Vera Cruz","4315073"],["RS","Porto Xavier","4315107"],["RS","Pouso Novo","4315131"],["RS","Presidente Lucena","4315149"],["RS","Progresso","4315156"],["RS","Protásio Alves","4315172"],["RS","Putinga","4315206"],["RS","Quaraí","4315305"],["RS","Quatro Irmãos","4315313"],["RS","Quevedos","4315321"],["RS","Quinze de Novembro","4315354"],["RS","Redentora","4315404"],["RS","Relvado","4315453"],["RS","Restinga Sêca","4315503"],["RS","Rio dos Índios","4315552"],["RS","Rio Grande","4315602"],["RS","Rio Pardo","4315701"],["RS","Riozinho","4315750"],["RS","Roca Sales","4315800"],["RS","Rodeio Bonito","4315909"],["RS","Rolador","4315958"],["RS","Rolante","4316006"],["RS","Ronda Alta","4316105"],["RS","Rondinha","4316204"],["RS","Roque Gonzales","4316303"],["RS","Rosário do Sul","4316402"],["RS","Sagrada Família","4316428"],["RS","Saldanha Marinho","4316436"],["RS","Salto do Jacuí","4316451"],["RS","Salvador das Missões","4316477"],["RS","Salvador do Sul","4316501"],["RS","Sananduva","4316600"],["RS","Sant'Ana do Livramento","4317103"],["RS","Santa Bárbara do Sul","4316709"],["RS","Santa Cecília do Sul","4316733"],["RS","Santa Clara do Sul","4316758"],["RS","Santa Cruz do Sul","4316808"],["RS","Santa Margarida do Sul","4316972"],["RS","Santa Maria","4316907"],["RS","Santa Maria do Herval","4316956"],["RS","Santa Rosa","4317202"],["RS","Santa Tereza","4317251"],["RS","Santa Vitória do Palmar","4317301"],["RS","Santana da Boa Vista","4317004"],["RS","Santiago","4317400"],["RS","Santo Ângelo","4317509"],["RS","Santo Antônio da Patrulha","4317608"],["RS","Santo Antônio das Missões","4317707"],["RS","Santo Antônio do Palma","4317558"],["RS","Santo Antônio do Planalto","4317756"],["RS","Santo Augusto","4317806"],["RS","Santo Cristo","4317905"],["RS","Santo Expedito do Sul","4317954"],["RS","São Borja","4318002"],["RS","São Domingos do Sul","4318051"],["RS","São Francisco de Assis","4318101"],["RS","São Francisco de Paula","4318200"],["RS","São Gabriel","4318309"],["RS","São Jerônimo","4318408"],["RS","São João da Urtiga","4318424"],["RS","São João do Polêsine","4318432"],["RS","São Jorge","4318440"],["RS","São José das Missões","4318457"],["RS","São José do Herval","4318465"],["RS","São José do Hortêncio","4318481"],["RS","São José do Inhacorá","4318499"],["RS","São José do Norte","4318507"],["RS","São José do Ouro","4318606"],["RS","São José do Sul","4318614"],["RS","São José dos Ausentes","4318622"],["RS","São Leopoldo","4318705"],["RS","São Lourenço do Sul","4318804"],["RS","São Luiz Gonzaga","4318903"],["RS","São Marcos","4319000"],["RS","São Martinho","4319109"],["RS","São Martinho da Serra","4319125"],["RS","São Miguel das Missões","4319158"],["RS","São Nicolau","4319208"],["RS","São Paulo das Missões","4319307"],["RS","São Pedro da Serra","4319356"],["RS","São Pedro das Missões","4319364"],["RS","São Pedro do Butiá","4319372"],["RS","São Pedro do Sul","4319406"],["RS","São Sebastião do Caí","4319505"],["RS","São Sepé","4319604"],["RS","São Valentim","4319703"],["RS","São Valentim do Sul","4319711"],["RS","São Valério do Sul","4319737"],["RS","São Vendelino","4319752"],["RS","São Vicente do Sul","4319802"],["RS","Sapiranga","4319901"],["RS","Sapucaia do Sul","4320008"],["RS","Sarandi","4320107"],["RS","Seberi","4320206"],["RS","Sede Nova","4320230"],["RS","Segredo","4320263"],["RS","Selbach","4320305"],["RS","Senador Salgado Filho","4320321"],["RS","Sentinela do Sul","4320354"],["RS","Serafina Corrêa","4320404"],["RS","Sério","4320453"],["RS","Sertão","4320503"],["RS","Sertão Santana","4320552"],["RS","Sete de Setembro","4320578"],["RS","Severiano de Almeida","4320602"],["RS","Silveira Martins","4320651"],["RS","Sinimbu","4320677"],["RS","Sobradinho","4320701"],["RS","Soledade","4320800"],["RS","Tabaí","4320859"],["RS","Tapejara","4320909"],["RS","Tapera","4321006"],["RS","Tapes","4321105"],["RS","Taquara","4321204"],["RS","Taquari","4321303"],["RS","Taquaruçu do Sul","4321329"],["RS","Tavares","4321352"],["RS","Tenente Portela","4321402"],["RS","Terra de Areia","4321436"],["RS","Teutônia","4321451"],["RS","Tio Hugo","4321469"],["RS","Tiradentes do Sul","4321477"],["RS","Toropi","4321493"],["RS","Torres","4321501"],["RS","Tramandaí","4321600"],["RS","Travesseiro","4321626"],["RS","Três Arroios","4321634"],["RS","Três Cachoeiras","4321667"],["RS","Três Coroas","4321709"],["RS","Três de Maio","4321808"],["RS","Três Forquilhas","4321832"],["RS","Três Palmeiras","4321857"],["RS","Três Passos","4321907"],["RS","Trindade do Sul","4321956"],["RS","Triunfo","4322004"],["RS","Tucunduva","4322103"],["RS","Tunas","4322152"],["RS","Tupanci do Sul","4322186"],["RS","Tupanciretã","4322202"],["RS","Tupandi","4322251"],["RS","Tuparendi","4322301"],["RS","Turuçu","4322327"],["RS","Ubiretama","4322343"],["RS","União da Serra","4322350"],["RS","Unistalda","4322376"],["RS","Uruguaiana","4322400"],["RS","Vacaria","4322509"],["RS","Vale do Sol","4322533"],["RS","Vale Real","4322541"],["RS","Vale Verde","4322525"],["RS","Vanini","4322558"],["RS","Venâncio Aires","4322608"],["RS","Vera Cruz","4322707"],["RS","Veranópolis","4322806"],["RS","Vespasiano Corrêa","4322855"],["RS","Viadutos","4322905"],["RS","Viamão","4323002"],["RS","Vicente Dutra","4323101"],["RS","Victor Graeff","4323200"],["RS","Vila Flores","4323309"],["RS","Vila Lângaro","4323358"],["RS","Vila Maria","4323408"],["RS","Vila Nova do Sul","4323457"],["RS","Vista Alegre","4323507"],["RS","Vista Alegre do Prata","4323606"],["RS","Vista Gaúcha","4323705"],["RS","Vitória das Missões","4323754"],["RS","Westfália","4323770"],["RS","Xangri-lá","4323804"],["RO","Alta Floresta D'Oeste","1100015"],["RO","Alto Alegre dos Parecis","1100379"],["RO","Alto Paraíso","1100403"],["RO","Alvorada D'Oeste","1100346"],["RO","Ariquemes","1100023"],["RO","Buritis","1100452"],["RO","Cabixi","1100031"],["RO","Cacaulândia","1100601"],["RO","Cacoal","1100049"],["RO","Campo Novo de Rondônia","1100700"],["RO","Candeias do Jamari","1100809"],["RO","Castanheiras","1100908"],["RO","Cerejeiras","1100056"],["RO","Chupinguaia","1100924"],["RO","Colorado do Oeste","1100064"],["RO","Corumbiara","1100072"],["RO","Costa Marques","1100080"],["RO","Cujubim","1100940"],["RO","Espigão D'Oeste","1100098"],["RO","Governador Jorge Teixeira","1101005"],["RO","Guajará-Mirim","1100106"],["RO","Itapuã do Oeste","1101104"],["RO","Jaru","1100114"],["RO","Ji-Paraná","1100122"],["RO","Machadinho D'Oeste","1100130"],["RO","Ministro Andreazza","1101203"],["RO","Mirante da Serra","1101302"],["RO","Monte Negro","1101401"],["RO","Nova Brasilândia D'Oeste","1100148"],["RO","Nova Mamoré","1100338"],["RO","Nova União","1101435"],["RO","Novo Horizonte do Oeste","1100502"],["RO","Ouro Preto do Oeste","1100155"],["RO","Parecis","1101450"],["RO","Pimenta Bueno","1100189"],["RO","Pimenteiras do Oeste","1101468"],["RO","Porto Velho","1100205"],["RO","Presidente Médici","1100254"],["RO","Primavera de Rondônia","1101476"],["RO","Rio Crespo","1100262"],["RO","Rolim de Moura","1100288"],["RO","Santa Luzia D'Oeste","1100296"],["RO","São Felipe D'Oeste","1101484"],["RO","São Francisco do Guaporé","1101492"],["RO","São Miguel do Guaporé","1100320"],["RO","Seringueiras","1101500"],["RO","Teixeirópolis","1101559"],["RO","Theobroma","1101609"],["RO","Urupá","1101708"],["RO","Vale do Anari","1101757"],["RO","Vale do Paraíso","1101807"],["RO","Vilhena","1100304"],["RR","Alto Alegre","1400050"],["RR","Amajari","1400027"],["RR","Boa Vista","1400100"],["RR","Bonfim","1400159"],["RR","Cantá","1400175"],["RR","Caracaraí","1400209"],["RR","Caroebe","1400233"],["RR","Iracema","1400282"],["RR","Mucajaí","1400308"],["RR","Normandia","1400407"],["RR","Pacaraima","1400456"],["RR","Rorainópolis","1400472"],["RR","São João da Baliza","1400506"],["RR","São Luiz do Anauá","1400605"],["RR","Uiramutã","1400704"],["SC","Abdon Batista","4200051"],["SC","Abelardo Luz","4200101"],["SC","Agrolândia","4200200"],["SC","Agronômica","4200309"],["SC","Água Doce","4200408"],["SC","Águas de Chapecó","4200507"],["SC","Águas Frias","4200556"],["SC","Águas Mornas","4200606"],["SC","Alfredo Wagner","4200705"],["SC","Alto Bela Vista","4200754"],["SC","Anchieta","4200804"],["SC","Angelina","4200903"],["SC","Anita Garibaldi","4201000"],["SC","Anitápolis","4201109"],["SC","Antônio Carlos","4201208"],["SC","Apiúna","4201257"],["SC","Arabutã","4201273"],["SC","Araquari","4201307"],["SC","Araranguá","4201406"],["SC","Armazém","4201505"],["SC","Arroio Trinta","4201604"],["SC","Arvoredo","4201653"],["SC","Ascurra","4201703"],["SC","Atalanta","4201802"],["SC","Aurora","4201901"],["SC","Balneário Arroio do Silva","4201950"],["SC","Balneário Barra do Sul","4202057"],["SC","Balneário Camboriú","4202008"],["SC","Balneário Gaivota","4202073"],["SC","Balneário Piçarras","4212809"],["SC","Balneário Rincão","4220000"],["SC","Bandeirante","4202081"],["SC","Barra Bonita","4202099"],["SC","Barra Velha","4202107"],["SC","Bela Vista do Toldo","4202131"],["SC","Belmonte","4202156"],["SC","Benedito Novo","4202206"],["SC","Biguaçu","4202305"],["SC","Blumenau","4202404"],["SC","Bocaina do Sul","4202438"],["SC","Bom Jardim da Serra","4202503"],["SC","Bom Jesus","4202537"],["SC","Bom Jesus do Oeste","4202578"],["SC","Bom Retiro","4202602"],["SC","Bombinhas","4202453"],["SC","Botuverá","4202701"],["SC","Braço do Norte","4202800"],["SC","Braço do Trombudo","4202859"],["SC","Brunópolis","4202875"],["SC","Brusque","4202909"],["SC","Caçador","4203006"],["SC","Caibi","4203105"],["SC","Calmon","4203154"],["SC","Camboriú","4203204"],["SC","Campo Alegre","4203303"],["SC","Campo Belo do Sul","4203402"],["SC","Campo Erê","4203501"],["SC","Campos Novos","4203600"],["SC","Canelinha","4203709"],["SC","Canoinhas","4203808"],["SC","Capão Alto","4203253"],["SC","Capinzal","4203907"],["SC","Capivari de Baixo","4203956"],["SC","Catanduvas","4204004"],["SC","Caxambu do Sul","4204103"],["SC","Celso Ramos","4204152"],["SC","Cerro Negro","4204178"],["SC","Chapadão do Lageado","4204194"],["SC","Chapecó","4204202"],["SC","Cocal do Sul","4204251"],["SC","Concórdia","4204301"],["SC","Cordilheira Alta","4204350"],["SC","Coronel Freitas","4204400"],["SC","Coronel Martins","4204459"],["SC","Correia Pinto","4204558"],["SC","Corupá","4204509"],["SC","Criciúma","4204608"],["SC","Cunha Porã","4204707"],["SC","Cunhataí","4204756"],["SC","Curitibanos","4204806"],["SC","Descanso","4204905"],["SC","Dionísio Cerqueira","4205001"],["SC","Dona Emma","4205100"],["SC","Doutor Pedrinho","4205159"],["SC","Entre Rios","4205175"],["SC","Ermo","4205191"],["SC","Erval Velho","4205209"],["SC","Faxinal dos Guedes","4205308"],["SC","Flor do Sertão","4205357"],["SC","Florianópolis","4205407"],["SC","Formosa do Sul","4205431"],["SC","Forquilhinha","4205456"],["SC","Fraiburgo","4205506"],["SC","Frei Rogério","4205555"],["SC","Galvão","4205605"],["SC","Garopaba","4205704"],["SC","Garuva","4205803"],["SC","Gaspar","4205902"],["SC","Governador Celso Ramos","4206009"],["SC","Grão-Pará","4206108"],["SC","Gravatal","4206207"],["SC","Guabiruba","4206306"],["SC","Guaraciaba","4206405"],["SC","Guaramirim","4206504"],["SC","Guarujá do Sul","4206603"],["SC","Guatambú","4206652"],["SC","Herval d'Oeste","4206702"],["SC","Ibiam","4206751"],["SC","Ibicaré","4206801"],["SC","Ibirama","4206900"],["SC","Içara","4207007"],["SC","Ilhota","4207106"],["SC","Imaruí","4207205"],["SC","Imbituba","4207304"],["SC","Imbuia","4207403"],["SC","Indaial","4207502"],["SC","Iomerê","4207577"],["SC","Ipira","4207601"],["SC","Iporã do Oeste","4207650"],["SC","Ipuaçu","4207684"],["SC","Ipumirim","4207700"],["SC","Iraceminha","4207759"],["SC","Irani","4207809"],["SC","Irati","4207858"],["SC","Irineópolis","4207908"],["SC","Itá","4208005"],["SC","Itaiópolis","4208104"],["SC","Itajaí","4208203"],["SC","Itapema","4208302"],["SC","Itapiranga","4208401"],["SC","Itapoá","4208450"],["SC","Ituporanga","4208500"],["SC","Jaborá","4208609"],["SC","Jacinto Machado","4208708"],["SC","Jaguaruna","4208807"],["SC","Jaraguá do Sul","4208906"],["SC","Jardinópolis","4208955"],["SC","Joaçaba","4209003"],["SC","Joinville","4209102"],["SC","José Boiteux","4209151"],["SC","Jupiá","4209177"],["SC","Lacerdópolis","4209201"],["SC","Lages","4209300"],["SC","Laguna","4209409"],["SC","Lajeado Grande","4209458"],["SC","Laurentino","4209508"],["SC","Lauro Müller","4209607"],["SC","Lebon Régis","4209706"],["SC","Leoberto Leal","4209805"],["SC","Lindóia do Sul","4209854"],["SC","Lontras","4209904"],["SC","Luiz Alves","4210001"],["SC","Luzerna","4210035"],["SC","Macieira","4210050"],["SC","Mafra","4210100"],["SC","Major Gercino","4210209"],["SC","Major Vieira","4210308"],["SC","Maracajá","4210407"],["SC","Maravilha","4210506"],["SC","Marema","4210555"],["SC","Massaranduba","4210605"],["SC","Matos Costa","4210704"],["SC","Meleiro","4210803"],["SC","Mirim Doce","4210852"],["SC","Modelo","4210902"],["SC","Mondaí","4211009"],["SC","Monte Carlo","4211058"],["SC","Monte Castelo","4211108"],["SC","Morro da Fumaça","4211207"],["SC","Morro Grande","4211256"],["SC","Navegantes","4211306"],["SC","Nova Erechim","4211405"],["SC","Nova Itaberaba","4211454"],["SC","Nova Trento","4211504"],["SC","Nova Veneza","4211603"],["SC","Novo Horizonte","4211652"],["SC","Orleans","4211702"],["SC","Otacílio Costa","4211751"],["SC","Ouro","4211801"],["SC","Ouro Verde","4211850"],["SC","Paial","4211876"],["SC","Painel","4211892"],["SC","Palhoça","4211900"],["SC","Palma Sola","4212007"],["SC","Palmeira","4212056"],["SC","Palmitos","4212106"],["SC","Papanduva","4212205"],["SC","Paraíso","4212239"],["SC","Passo de Torres","4212254"],["SC","Passos Maia","4212270"],["SC","Paulo Lopes","4212304"],["SC","Pedras Grandes","4212403"],["SC","Penha","4212502"],["SC","Peritiba","4212601"],["SC","Pescaria Brava","4212650"],["SC","Petrolândia","4212700"],["SC","Pinhalzinho","4212908"],["SC","Pinheiro Preto","4213005"],["SC","Piratuba","4213104"],["SC","Planalto Alegre","4213153"],["SC","Pomerode","4213203"],["SC","Ponte Alta","4213302"],["SC","Ponte Alta do Norte","4213351"],["SC","Ponte Serrada","4213401"],["SC","Porto Belo","4213500"],["SC","Porto União","4213609"],["SC","Pouso Redondo","4213708"],["SC","Praia Grande","4213807"],["SC","Presidente Castello Branco","4213906"],["SC","Presidente Getúlio","4214003"],["SC","Presidente Nereu","4214102"],["SC","Princesa","4214151"],["SC","Quilombo","4214201"],["SC","Rancho Queimado","4214300"],["SC","Rio das Antas","4214409"],["SC","Rio do Campo","4214508"],["SC","Rio do Oeste","4214607"],["SC","Rio do Sul","4214805"],["SC","Rio dos Cedros","4214706"],["SC","Rio Fortuna","4214904"],["SC","Rio Negrinho","4215000"],["SC","Rio Rufino","4215059"],["SC","Riqueza","4215075"],["SC","Rodeio","4215109"],["SC","Romelândia","4215208"],["SC","Salete","4215307"],["SC","Saltinho","4215356"],["SC","Salto Veloso","4215406"],["SC","Sangão","4215455"],["SC","Santa Cecília","4215505"],["SC","Santa Helena","4215554"],["SC","Santa Rosa de Lima","4215604"],["SC","Santa Rosa do Sul","4215653"],["SC","Santa Terezinha","4215679"],["SC","Santa Terezinha do Progresso","4215687"],["SC","Santiago do Sul","4215695"],["SC","Santo Amaro da Imperatriz","4215703"],["SC","São Bento do Sul","4215802"],["SC","São Bernardino","4215752"],["SC","São Bonifácio","4215901"],["SC","São Carlos","4216008"],["SC","São Cristóvão do Sul","4216057"],["SC","São Domingos","4216107"],["SC","São Francisco do Sul","4216206"],["SC","São João Batista","4216305"],["SC","São João do Itaperiú","4216354"],["SC","São João do Oeste","4216255"],["SC","São João do Sul","4216404"],["SC","São Joaquim","4216503"],["SC","São José","4216602"],["SC","São José do Cedro","4216701"],["SC","São José do Cerrito","4216800"],["SC","São Lourenço do Oeste","4216909"],["SC","São Ludgero","4217006"],["SC","São Martinho","4217105"],["SC","São Miguel da Boa Vista","4217154"],["SC","São Miguel do Oeste","4217204"],["SC","São Pedro de Alcântara","4217253"],["SC","Saudades","4217303"],["SC","Schroeder","4217402"],["SC","Seara","4217501"],["SC","Serra Alta","4217550"],["SC","Siderópolis","4217600"],["SC","Sombrio","4217709"],["SC","Sul Brasil","4217758"],["SC","Taió","4217808"],["SC","Tangará","4217907"],["SC","Tigrinhos","4217956"],["SC","Tijucas","4218004"],["SC","Timbé do Sul","4218103"],["SC","Timbó","4218202"],["SC","Timbó Grande","4218251"],["SC","Três Barras","4218301"],["SC","Treviso","4218350"],["SC","Treze de Maio","4218400"],["SC","Treze Tílias","4218509"],["SC","Trombudo Central","4218608"],["SC","Tubarão","4218707"],["SC","Tunápolis","4218756"],["SC","Turvo","4218806"],["SC","União do Oeste","4218855"],["SC","Urubici","4218905"],["SC","Urupema","4218954"],["SC","Urussanga","4219002"],["SC","Vargeão","4219101"],["SC","Vargem","4219150"],["SC","Vargem Bonita","4219176"],["SC","Vidal Ramos","4219200"],["SC","Videira","4219309"],["SC","Vitor Meireles","4219358"],["SC","Witmarsum","4219408"],["SC","Xanxerê","4219507"],["SC","Xavantina","4219606"],["SC","Xaxim","4219705"],["SC","Zortéa","4219853"],["SP","Adamantina","3500105"],["SP","Adolfo","3500204"],["SP","Aguaí","3500303"],["SP","Águas da Prata","3500402"],["SP","Águas de Lindóia","3500501"],["SP","Águas de Santa Bárbara","3500550"],["SP","Águas de São Pedro","3500600"],["SP","Agudos","3500709"],["SP","Alambari","3500758"],["SP","Alfredo Marcondes","3500808"],["SP","Altair","3500907"],["SP","Altinópolis","3501004"],["SP","Alto Alegre","3501103"],["SP","Alumínio","3501152"],["SP","Álvares Florence","3501202"],["SP","Álvares Machado","3501301"],["SP","Álvaro de Carvalho","3501400"],["SP","Alvinlândia","3501509"],["SP","Americana","3501608"],["SP","Américo Brasiliense","3501707"],["SP","Américo de Campos","3501806"],["SP","Amparo","3501905"],["SP","Analândia","3502002"],["SP","Andradina","3502101"],["SP","Angatuba","3502200"],["SP","Anhembi","3502309"],["SP","Anhumas","3502408"],["SP","Aparecida","3502507"],["SP","Aparecida d'Oeste","3502606"],["SP","Apiaí","3502705"],["SP","Araçariguama","3502754"],["SP","Araçatuba","3502804"],["SP","Araçoiaba da Serra","3502903"],["SP","Aramina","3503000"],["SP","Arandu","3503109"],["SP","Arapeí","3503158"],["SP","Araraquara","3503208"],["SP","Araras","3503307"],["SP","Arco-Íris","3503356"],["SP","Arealva","3503406"],["SP","Areias","3503505"],["SP","Areiópolis","3503604"],["SP","Ariranha","3503703"],["SP","Artur Nogueira","3503802"],["SP","Arujá","3503901"],["SP","Aspásia","3503950"],["SP","Assis","3504008"],["SP","Atibaia","3504107"],["SP","Auriflama","3504206"],["SP","Avaí","3504305"],["SP","Avanhandava","3504404"],["SP","Avaré","3504503"],["SP","Bady Bassitt","3504602"],["SP","Balbinos","3504701"],["SP","Bálsamo","3504800"],["SP","Bananal","3504909"],["SP","Barão de Antonina","3505005"],["SP","Barbosa","3505104"],["SP","Bariri","3505203"],["SP","Barra Bonita","3505302"],["SP","Barra do Chapéu","3505351"],["SP","Barra do Turvo","3505401"],["SP","Barretos","3505500"],["SP","Barrinha","3505609"],["SP","Barueri","3505708"],["SP","Bastos","3505807"],["SP","Batatais","3505906"],["SP","Bauru","3506003"],["SP","Bebedouro","3506102"],["SP","Bento de Abreu","3506201"],["SP","Bernardino de Campos","3506300"],["SP","Bertioga","3506359"],["SP","Bilac","3506409"],["SP","Birigui","3506508"],["SP","Biritiba Mirim","3506607"],["SP","Boa Esperança do Sul","3506706"],["SP","Bocaina","3506805"],["SP","Bofete","3506904"],["SP","Boituva","3507001"],["SP","Bom Jesus dos Perdões","3507100"],["SP","Bom Sucesso de Itararé","3507159"],["SP","Borá","3507209"],["SP","Boracéia","3507308"],["SP","Borborema","3507407"],["SP","Borebi","3507456"],["SP","Botucatu","3507506"],["SP","Bragança Paulista","3507605"],["SP","Braúna","3507704"],["SP","Brejo Alegre","3507753"],["SP","Brodowski","3507803"],["SP","Brotas","3507902"],["SP","Buri","3508009"],["SP","Buritama","3508108"],["SP","Buritizal","3508207"],["SP","Cabrália Paulista","3508306"],["SP","Cabreúva","3508405"],["SP","Caçapava","3508504"],["SP","Cachoeira Paulista","3508603"],["SP","Caconde","3508702"],["SP","Cafelândia","3508801"],["SP","Caiabu","3508900"],["SP","Caieiras","3509007"],["SP","Caiuá","3509106"],["SP","Cajamar","3509205"],["SP","Cajati","3509254"],["SP","Cajobi","3509304"],["SP","Cajuru","3509403"],["SP","Campina do Monte Alegre","3509452"],["SP","Campinas","3509502"],["SP","Campo Limpo Paulista","3509601"],["SP","Campos do Jordão","3509700"],["SP","Campos Novos Paulista","3509809"],["SP","Cananéia","3509908"],["SP","Canas","3509957"],["SP","Cândido Mota","3510005"],["SP","Cândido Rodrigues","3510104"],["SP","Canitar","3510153"],["SP","Capão Bonito","3510203"],["SP","Capela do Alto","3510302"],["SP","Capivari","3510401"],["SP","Caraguatatuba","3510500"],["SP","Carapicuíba","3510609"],["SP","Cardoso","3510708"],["SP","Casa Branca","3510807"],["SP","Cássia dos Coqueiros","3510906"],["SP","Castilho","3511003"],["SP","Catanduva","3511102"],["SP","Catiguá","3511201"],["SP","Cedral","3511300"],["SP","Cerqueira César","3511409"],["SP","Cerquilho","3511508"],["SP","Cesário Lange","3511607"],["SP","Charqueada","3511706"],["SP","Chavantes","3557204"],["SP","Clementina","3511904"],["SP","Colina","3512001"],["SP","Colômbia","3512100"],["SP","Conchal","3512209"],["SP","Conchas","3512308"],["SP","Cordeirópolis","3512407"],["SP","Coroados","3512506"],["SP","Coronel Macedo","3512605"],["SP","Corumbataí","3512704"],["SP","Cosmópolis","3512803"],["SP","Cosmorama","3512902"],["SP","Cotia","3513009"],["SP","Cravinhos","3513108"],["SP","Cristais Paulista","3513207"],["SP","Cruzália","3513306"],["SP","Cruzeiro","3513405"],["SP","Cubatão","3513504"],["SP","Cunha","3513603"],["SP","Descalvado","3513702"],["SP","Diadema","3513801"],["SP","Dirce Reis","3513850"],["SP","Divinolândia","3513900"],["SP","Dobrada","3514007"],["SP","Dois Córregos","3514106"],["SP","Dolcinópolis","3514205"],["SP","Dourado","3514304"],["SP","Dracena","3514403"],["SP","Duartina","3514502"],["SP","Dumont","3514601"],["SP","Echaporã","3514700"],["SP","Eldorado","3514809"],["SP","Elias Fausto","3514908"],["SP","Elisiário","3514924"],["SP","Embaúba","3514957"],["SP","Embu das Artes","3515004"],["SP","Embu-Guaçu","3515103"],["SP","Emilianópolis","3515129"],["SP","Engenheiro Coelho","3515152"],["SP","Espírito Santo do Pinhal","3515186"],["SP","Espírito Santo do Turvo","3515194"],["SP","Estiva Gerbi","3557303"],["SP","Estrela d'Oeste","3515202"],["SP","Estrela do Norte","3515301"],["SP","Euclides da Cunha Paulista","3515350"],["SP","Fartura","3515400"],["SP","Fernando Prestes","3515608"],["SP","Fernandópolis","3515509"],["SP","Fernão","3515657"],["SP","Ferraz de Vasconcelos","3515707"],["SP","Flora Rica","3515806"],["SP","Floreal","3515905"],["SP","Flórida Paulista","3516002"],["SP","Florínea","3516101"],["SP","Franca","3516200"],["SP","Francisco Morato","3516309"],["SP","Franco da Rocha","3516408"],["SP","Gabriel Monteiro","3516507"],["SP","Gália","3516606"],["SP","Garça","3516705"],["SP","Gastão Vidigal","3516804"],["SP","Gavião Peixoto","3516853"],["SP","General Salgado","3516903"],["SP","Getulina","3517000"],["SP","Glicério","3517109"],["SP","Guaiçara","3517208"],["SP","Guaimbê","3517307"],["SP","Guaíra","3517406"],["SP","Guapiaçu","3517505"],["SP","Guapiara","3517604"],["SP","Guará","3517703"],["SP","Guaraçaí","3517802"],["SP","Guaraci","3517901"],["SP","Guarani d'Oeste","3518008"],["SP","Guarantã","3518107"],["SP","Guararapes","3518206"],["SP","Guararema","3518305"],["SP","Guaratinguetá","3518404"],["SP","Guareí","3518503"],["SP","Guariba","3518602"],["SP","Guarujá","3518701"],["SP","Guarulhos","3518800"],["SP","Guatapará","3518859"],["SP","Guzolândia","3518909"],["SP","Herculândia","3519006"],["SP","Holambra","3519055"],["SP","Hortolândia","3519071"],["SP","Iacanga","3519105"],["SP","Iacri","3519204"],["SP","Iaras","3519253"],["SP","Ibaté","3519303"],["SP","Ibirá","3519402"],["SP","Ibirarema","3519501"],["SP","Ibitinga","3519600"],["SP","Ibiúna","3519709"],["SP","Icém","3519808"],["SP","Iepê","3519907"],["SP","Igaraçu do Tietê","3520004"],["SP","Igarapava","3520103"],["SP","Igaratá","3520202"],["SP","Iguape","3520301"],["SP","Ilha Comprida","3520426"],["SP","Ilha Solteira","3520442"],["SP","Ilhabela","3520400"],["SP","Indaiatuba","3520509"],["SP","Indiana","3520608"],["SP","Indiaporã","3520707"],["SP","Inúbia Paulista","3520806"],["SP","Ipaussu","3520905"],["SP","Iperó","3521002"],["SP","Ipeúna","3521101"],["SP","Ipiguá","3521150"],["SP","Iporanga","3521200"],["SP","Ipuã","3521309"],["SP","Iracemápolis","3521408"],["SP","Irapuã","3521507"],["SP","Irapuru","3521606"],["SP","Itaberá","3521705"],["SP","Itaí","3521804"],["SP","Itajobi","3521903"],["SP","Itaju","3522000"],["SP","Itanhaém","3522109"],["SP","Itaoca","3522158"],["SP","Itapecerica da Serra","3522208"],["SP","Itapetininga","3522307"],["SP","Itapeva","3522406"],["SP","Itapevi","3522505"],["SP","Itapira","3522604"],["SP","Itapirapuã Paulista","3522653"],["SP","Itápolis","3522703"],["SP","Itaporanga","3522802"],["SP","Itapuí","3522901"],["SP","Itapura","3523008"],["SP","Itaquaquecetuba","3523107"],["SP","Itararé","3523206"],["SP","Itariri","3523305"],["SP","Itatiba","3523404"],["SP","Itatinga","3523503"],["SP","Itirapina","3523602"],["SP","Itirapuã","3523701"],["SP","Itobi","3523800"],["SP","Itu","3523909"],["SP","Itupeva","3524006"],["SP","Ituverava","3524105"],["SP","Jaborandi","3524204"],["SP","Jaboticabal","3524303"],["SP","Jacareí","3524402"],["SP","Jaci","3524501"],["SP","Jacupiranga","3524600"],["SP","Jaguariúna","3524709"],["SP","Jales","3524808"],["SP","Jambeiro","3524907"],["SP","Jandira","3525003"],["SP","Jardinópolis","3525102"],["SP","Jarinu","3525201"],["SP","Jaú","3525300"],["SP","Jeriquara","3525409"],["SP","Joanópolis","3525508"],["SP","João Ramalho","3525607"],["SP","José Bonifácio","3525706"],["SP","Júlio Mesquita","3525805"],["SP","Jumirim","3525854"],["SP","Jundiaí","3525904"],["SP","Junqueirópolis","3526001"],["SP","Juquiá","3526100"],["SP","Juquitiba","3526209"],["SP","Lagoinha","3526308"],["SP","Laranjal Paulista","3526407"],["SP","Lavínia","3526506"],["SP","Lavrinhas","3526605"],["SP","Leme","3526704"],["SP","Lençóis Paulista","3526803"],["SP","Limeira","3526902"],["SP","Lindóia","3527009"],["SP","Lins","3527108"],["SP","Lorena","3527207"],["SP","Lourdes","3527256"],["SP","Louveira","3527306"],["SP","Lucélia","3527405"],["SP","Lucianópolis","3527504"],["SP","Luís Antônio","3527603"],["SP","Luiziânia","3527702"],["SP","Lupércio","3527801"],["SP","Lutécia","3527900"],["SP","Macatuba","3528007"],["SP","Macaubal","3528106"],["SP","Macedônia","3528205"],["SP","Magda","3528304"],["SP","Mairinque","3528403"],["SP","Mairiporã","3528502"],["SP","Manduri","3528601"],["SP","Marabá Paulista","3528700"],["SP","Maracaí","3528809"],["SP","Marapoama","3528858"],["SP","Mariápolis","3528908"],["SP","Marília","3529005"],["SP","Marinópolis","3529104"],["SP","Martinópolis","3529203"],["SP","Matão","3529302"],["SP","Mauá","3529401"],["SP","Mendonça","3529500"],["SP","Meridiano","3529609"],["SP","Mesópolis","3529658"],["SP","Miguelópolis","3529708"],["SP","Mineiros do Tietê","3529807"],["SP","Mira Estrela","3530003"],["SP","Miracatu","3529906"],["SP","Mirandópolis","3530102"],["SP","Mirante do Paranapanema","3530201"],["SP","Mirassol","3530300"],["SP","Mirassolândia","3530409"],["SP","Mococa","3530508"],["SP","Mogi das Cruzes","3530607"],["SP","Mogi Guaçu","3530706"],["SP","Mogi Mirim","3530805"],["SP","Mombuca","3530904"],["SP","Monções","3531001"],["SP","Mongaguá","3531100"],["SP","Monte Alegre do Sul","3531209"],["SP","Monte Alto","3531308"],["SP","Monte Aprazível","3531407"],["SP","Monte Azul Paulista","3531506"],["SP","Monte Castelo","3531605"],["SP","Monte Mor","3531803"],["SP","Monteiro Lobato","3531704"],["SP","Morro Agudo","3531902"],["SP","Morungaba","3532009"],["SP","Motuca","3532058"],["SP","Murutinga do Sul","3532108"],["SP","Nantes","3532157"],["SP","Narandiba","3532207"],["SP","Natividade da Serra","3532306"],["SP","Nazaré Paulista","3532405"],["SP","Neves Paulista","3532504"],["SP","Nhandeara","3532603"],["SP","Nipoã","3532702"],["SP","Nova Aliança","3532801"],["SP","Nova Campina","3532827"],["SP","Nova Canaã Paulista","3532843"],["SP","Nova Castilho","3532868"],["SP","Nova Europa","3532900"],["SP","Nova Granada","3533007"],["SP","Nova Guataporanga","3533106"],["SP","Nova Independência","3533205"],["SP","Nova Luzitânia","3533304"],["SP","Nova Odessa","3533403"],["SP","Novais","3533254"],["SP","Novo Horizonte","3533502"],["SP","Nuporanga","3533601"],["SP","Ocauçu","3533700"],["SP","Óleo","3533809"],["SP","Olímpia","3533908"],["SP","Onda Verde","3534005"],["SP","Oriente","3534104"],["SP","Orindiúva","3534203"],["SP","Orlândia","3534302"],["SP","Osasco","3534401"],["SP","Oscar Bressane","3534500"],["SP","Osvaldo Cruz","3534609"],["SP","Ourinhos","3534708"],["SP","Ouro Verde","3534807"],["SP","Ouroeste","3534757"],["SP","Pacaembu","3534906"],["SP","Palestina","3535002"],["SP","Palmares Paulista","3535101"],["SP","Palmeira d'Oeste","3535200"],["SP","Palmital","3535309"],["SP","Panorama","3535408"],["SP","Paraguaçu Paulista","3535507"],["SP","Paraibuna","3535606"],["SP","Paraíso","3535705"],["SP","Paranapanema","3535804"],["SP","Paranapuã","3535903"],["SP","Parapuã","3536000"],["SP","Pardinho","3536109"],["SP","Pariquera-Açu","3536208"],["SP","Parisi","3536257"],["SP","Patrocínio Paulista","3536307"],["SP","Paulicéia","3536406"],["SP","Paulínia","3536505"],["SP","Paulistânia","3536570"],["SP","Paulo de Faria","3536604"],["SP","Pederneiras","3536703"],["SP","Pedra Bela","3536802"],["SP","Pedranópolis","3536901"],["SP","Pedregulho","3537008"],["SP","Pedreira","3537107"],["SP","Pedrinhas Paulista","3537156"],["SP","Pedro de Toledo","3537206"],["SP","Penápolis","3537305"],["SP","Pereira Barreto","3537404"],["SP","Pereiras","3537503"],["SP","Peruíbe","3537602"],["SP","Piacatu","3537701"],["SP","Piedade","3537800"],["SP","Pilar do Sul","3537909"],["SP","Pindamonhangaba","3538006"],["SP","Pindorama","3538105"],["SP","Pinhalzinho","3538204"],["SP","Piquerobi","3538303"],["SP","Piquete","3538501"],["SP","Piracaia","3538600"],["SP","Piracicaba","3538709"],["SP","Piraju","3538808"],["SP","Pirajuí","3538907"],["SP","Pirangi","3539004"],["SP","Pirapora do Bom Jesus","3539103"],["SP","Pirapozinho","3539202"],["SP","Pirassununga","3539301"],["SP","Piratininga","3539400"],["SP","Pitangueiras","3539509"],["SP","Planalto","3539608"],["SP","Platina","3539707"],["SP","Poá","3539806"],["SP","Poloni","3539905"],["SP","Pompéia","3540002"],["SP","Pongaí","3540101"],["SP","Pontal","3540200"],["SP","Pontalinda","3540259"],["SP","Pontes Gestal","3540309"],["SP","Populina","3540408"],["SP","Porangaba","3540507"],["SP","Porto Feliz","3540606"],["SP","Porto Ferreira","3540705"],["SP","Potim","3540754"],["SP","Potirendaba","3540804"],["SP","Pracinha","3540853"],["SP","Pradópolis","3540903"],["SP","Praia Grande","3541000"],["SP","Pratânia","3541059"],["SP","Presidente Alves","3541109"],["SP","Presidente Bernardes","3541208"],["SP","Presidente Epitácio","3541307"],["SP","Presidente Prudente","3541406"],["SP","Presidente Venceslau","3541505"],["SP","Promissão","3541604"],["SP","Quadra","3541653"],["SP","Quatá","3541703"],["SP","Queiroz","3541802"],["SP","Queluz","3541901"],["SP","Quintana","3542008"],["SP","Rafard","3542107"],["SP","Rancharia","3542206"],["SP","Redenção da Serra","3542305"],["SP","Regente Feijó","3542404"],["SP","Reginópolis","3542503"],["SP","Registro","3542602"],["SP","Restinga","3542701"],["SP","Ribeira","3542800"],["SP","Ribeirão Bonito","3542909"],["SP","Ribeirão Branco","3543006"],["SP","Ribeirão Corrente","3543105"],["SP","Ribeirão do Sul","3543204"],["SP","Ribeirão dos Índios","3543238"],["SP","Ribeirão Grande","3543253"],["SP","Ribeirão Pires","3543303"],["SP","Ribeirão Preto","3543402"],["SP","Rifaina","3543600"],["SP","Rincão","3543709"],["SP","Rinópolis","3543808"],["SP","Rio Claro","3543907"],["SP","Rio das Pedras","3544004"],["SP","Rio Grande da Serra","3544103"],["SP","Riolândia","3544202"],["SP","Riversul","3543501"],["SP","Rosana","3544251"],["SP","Roseira","3544301"],["SP","Rubiácea","3544400"],["SP","Rubinéia","3544509"],["SP","Sabino","3544608"],["SP","Sagres","3544707"],["SP","Sales","3544806"],["SP","Sales Oliveira","3544905"],["SP","Salesópolis","3545001"],["SP","Salmourão","3545100"],["SP","Saltinho","3545159"],["SP","Salto","3545209"],["SP","Salto de Pirapora","3545308"],["SP","Salto Grande","3545407"],["SP","Sandovalina","3545506"],["SP","Santa Adélia","3545605"],["SP","Santa Albertina","3545704"],["SP","Santa Bárbara d'Oeste","3545803"],["SP","Santa Branca","3546009"],["SP","Santa Clara d'Oeste","3546108"],["SP","Santa Cruz da Conceição","3546207"],["SP","Santa Cruz da Esperança","3546256"],["SP","Santa Cruz das Palmeiras","3546306"],["SP","Santa Cruz do Rio Pardo","3546405"],["SP","Santa Ernestina","3546504"],["SP","Santa Fé do Sul","3546603"],["SP","Santa Gertrudes","3546702"],["SP","Santa Isabel","3546801"],["SP","Santa Lúcia","3546900"],["SP","Santa Maria da Serra","3547007"],["SP","Santa Mercedes","3547106"],["SP","Santa Rita d'Oeste","3547403"],["SP","Santa Rita do Passa Quatro","3547502"],["SP","Santa Rosa de Viterbo","3547601"],["SP","Santa Salete","3547650"],["SP","Santana da Ponte Pensa","3547205"],["SP","Santana de Parnaíba","3547304"],["SP","Santo Anastácio","3547700"],["SP","Santo André","3547809"],["SP","Santo Antônio da Alegria","3547908"],["SP","Santo Antônio de Posse","3548005"],["SP","Santo Antônio do Aracanguá","3548054"],["SP","Santo Antônio do Jardim","3548104"],["SP","Santo Antônio do Pinhal","3548203"],["SP","Santo Expedito","3548302"],["SP","Santópolis do Aguapeí","3548401"],["SP","Santos","3548500"],["SP","São Bento do Sapucaí","3548609"],["SP","São Bernardo do Campo","3548708"],["SP","São Caetano do Sul","3548807"],["SP","São Carlos","3548906"],["SP","São Francisco","3549003"],["SP","São João da Boa Vista","3549102"],["SP","São João das Duas Pontes","3549201"],["SP","São João de Iracema","3549250"],["SP","São João do Pau d'Alho","3549300"],["SP","São Joaquim da Barra","3549409"],["SP","São José da Bela Vista","3549508"],["SP","São José do Barreiro","3549607"],["SP","São José do Rio Pardo","3549706"],["SP","São José do Rio Preto","3549805"],["SP","São José dos Campos","3549904"],["SP","São Lourenço da Serra","3549953"],["SP","São Luiz do Paraitinga","3550001"],["SP","São Manuel","3550100"],["SP","São Miguel Arcanjo","3550209"],["SP","São Paulo","3550308"],["SP","São Pedro","3550407"],["SP","São Pedro do Turvo","3550506"],["SP","São Roque","3550605"],["SP","São Sebastião","3550704"],["SP","São Sebastião da Grama","3550803"],["SP","São Simão","3550902"],["SP","São Vicente","3551009"],["SP","Sarapuí","3551108"],["SP","Sarutaiá","3551207"],["SP","Sebastianópolis do Sul","3551306"],["SP","Serra Azul","3551405"],["SP","Serra Negra","3551603"],["SP","Serrana","3551504"],["SP","Sertãozinho","3551702"],["SP","Sete Barras","3551801"],["SP","Severínia","3551900"],["SP","Silveiras","3552007"],["SP","Socorro","3552106"],["SP","Sorocaba","3552205"],["SP","Sud Mennucci","3552304"],["SP","Sumaré","3552403"],["SP","Suzanápolis","3552551"],["SP","Suzano","3552502"],["SP","Tabapuã","3552601"],["SP","Tabatinga","3552700"],["SP","Taboão da Serra","3552809"],["SP","Taciba","3552908"],["SP","Taguaí","3553005"],["SP","Taiaçu","3553104"],["SP","Taiúva","3553203"],["SP","Tambaú","3553302"],["SP","Tanabi","3553401"],["SP","Tapiraí","3553500"],["SP","Tapiratiba","3553609"],["SP","Taquaral","3553658"],["SP","Taquaritinga","3553708"],["SP","Taquarituba","3553807"],["SP","Taquarivaí","3553856"],["SP","Tarabai","3553906"],["SP","Tarumã","3553955"],["SP","Tatuí","3554003"],["SP","Taubaté","3554102"],["SP","Tejupá","3554201"],["SP","Teodoro Sampaio","3554300"],["SP","Terra Roxa","3554409"],["SP","Tietê","3554508"],["SP","Timburi","3554607"],["SP","Torre de Pedra","3554656"],["SP","Torrinha","3554706"],["SP","Trabiju","3554755"],["SP","Tremembé","3554805"],["SP","Três Fronteiras","3554904"],["SP","Tuiuti","3554953"],["SP","Tupã","3555000"],["SP","Tupi Paulista","3555109"],["SP","Turiúba","3555208"],["SP","Turmalina","3555307"],["SP","Ubarana","3555356"],["SP","Ubatuba","3555406"],["SP","Ubirajara","3555505"],["SP","Uchoa","3555604"],["SP","União Paulista","3555703"],["SP","Urânia","3555802"],["SP","Uru","3555901"],["SP","Urupês","3556008"],["SP","Valentim Gentil","3556107"],["SP","Valinhos","3556206"],["SP","Valparaíso","3556305"],["SP","Vargem","3556354"],["SP","Vargem Grande do Sul","3556404"],["SP","Vargem Grande Paulista","3556453"],["SP","Várzea Paulista","3556503"],["SP","Vera Cruz","3556602"],["SP","Vinhedo","3556701"],["SP","Viradouro","3556800"],["SP","Vista Alegre do Alto","3556909"],["SP","Vitória Brasil","3556958"],["SP","Votorantim","3557006"],["SP","Votuporanga","3557105"],["SP","Zacarias","3557154"],["SE","Amparo do São Francisco","2800100"],["SE","Aquidabã","2800209"],["SE","Aracaju","2800308"],["SE","Arauá","2800407"],["SE","Areia Branca","2800506"],["SE","Barra dos Coqueiros","2800605"],["SE","Boquim","2800670"],["SE","Brejo Grande","2800704"],["SE","Campo do Brito","2801009"],["SE","Canhoba","2801108"],["SE","Canindé de São Francisco","2801207"],["SE","Capela","2801306"],["SE","Carira","2801405"],["SE","Carmópolis","2801504"],["SE","Cedro de São João","2801603"],["SE","Cristinápolis","2801702"],["SE","Cumbe","2801900"],["SE","Divina Pastora","2802007"],["SE","Estância","2802106"],["SE","Feira Nova","2802205"],["SE","Frei Paulo","2802304"],["SE","Gararu","2802403"],["SE","General Maynard","2802502"],["SE","Graccho Cardoso","2802601"],["SE","Ilha das Flores","2802700"],["SE","Indiaroba","2802809"],["SE","Itabaiana","2802908"],["SE","Itabaianinha","2803005"],["SE","Itabi","2803104"],["SE","Itaporanga d'Ajuda","2803203"],["SE","Japaratuba","2803302"],["SE","Japoatã","2803401"],["SE","Lagarto","2803500"],["SE","Laranjeiras","2803609"],["SE","Macambira","2803708"],["SE","Malhada dos Bois","2803807"],["SE","Malhador","2803906"],["SE","Maruim","2804003"],["SE","Moita Bonita","2804102"],["SE","Monte Alegre de Sergipe","2804201"],["SE","Muribeca","2804300"],["SE","Neópolis","2804409"],["SE","Nossa Senhora Aparecida","2804458"],["SE","Nossa Senhora da Glória","2804508"],["SE","Nossa Senhora das Dores","2804607"],["SE","Nossa Senhora de Lourdes","2804706"],["SE","Nossa Senhora do Socorro","2804805"],["SE","Pacatuba","2804904"],["SE","Pedra Mole","2805000"],["SE","Pedrinhas","2805109"],["SE","Pinhão","2805208"],["SE","Pirambu","2805307"],["SE","Poço Redondo","2805406"],["SE","Poço Verde","2805505"],["SE","Porto da Folha","2805604"],["SE","Propriá","2805703"],["SE","Riachão do Dantas","2805802"],["SE","Riachuelo","2805901"],["SE","Ribeirópolis","2806008"],["SE","Rosário do Catete","2806107"],["SE","Salgado","2806206"],["SE","Santa Luzia do Itanhy","2806305"],["SE","Santa Rosa de Lima","2806503"],["SE","Santana do São Francisco","2806404"],["SE","Santo Amaro das Brotas","2806602"],["SE","São Cristóvão","2806701"],["SE","São Domingos","2806800"],["SE","São Francisco","2806909"],["SE","São Miguel do Aleixo","2807006"],["SE","Simão Dias","2807105"],["SE","Siriri","2807204"],["SE","Telha","2807303"],["SE","Tobias Barreto","2807402"],["SE","Tomar do Geru","2807501"],["SE","Umbaúba","2807600"],["TO","Abreulândia","1700251"],["TO","Aguiarnópolis","1700301"],["TO","Aliança do Tocantins","1700350"],["TO","Almas","1700400"],["TO","Alvorada","1700707"],["TO","Ananás","1701002"],["TO","Angico","1701051"],["TO","Aparecida do Rio Negro","1701101"],["TO","Aragominas","1701309"],["TO","Araguacema","1701903"],["TO","Araguaçu","1702000"],["TO","Araguaína","1702109"],["TO","Araguanã","1702158"],["TO","Araguatins","1702208"],["TO","Arapoema","1702307"],["TO","Arraias","1702406"],["TO","Augustinópolis","1702554"],["TO","Aurora do Tocantins","1702703"],["TO","Axixá do Tocantins","1702901"],["TO","Babaçulândia","1703008"],["TO","Bandeirantes do Tocantins","1703057"],["TO","Barra do Ouro","1703073"],["TO","Barrolândia","1703107"],["TO","Bernardo Sayão","1703206"],["TO","Bom Jesus do Tocantins","1703305"],["TO","Brasilândia do Tocantins","1703602"],["TO","Brejinho de Nazaré","1703701"],["TO","Buriti do Tocantins","1703800"],["TO","Cachoeirinha","1703826"],["TO","Campos Lindos","1703842"],["TO","Cariri do Tocantins","1703867"],["TO","Carmolândia","1703883"],["TO","Carrasco Bonito","1703891"],["TO","Caseara","1703909"],["TO","Centenário","1704105"],["TO","Chapada da Natividade","1705102"],["TO","Chapada de Areia","1704600"],["TO","Colinas do Tocantins","1705508"],["TO","Colméia","1716703"],["TO","Combinado","1705557"],["TO","Conceição do Tocantins","1705607"],["TO","Couto Magalhães","1706001"],["TO","Cristalândia","1706100"],["TO","Crixás do Tocantins","1706258"],["TO","Darcinópolis","1706506"],["TO","Dianópolis","1707009"],["TO","Divinópolis do Tocantins","1707108"],["TO","Dois Irmãos do Tocantins","1707207"],["TO","Dueré","1707306"],["TO","Esperantina","1707405"],["TO","Fátima","1707553"],["TO","Figueirópolis","1707652"],["TO","Filadélfia","1707702"],["TO","Formoso do Araguaia","1708205"],["TO","Goianorte","1708304"],["TO","Goiatins","1709005"],["TO","Guaraí","1709302"],["TO","Gurupi","1709500"],["TO","Ipueiras","1709807"],["TO","Itacajá","1710508"],["TO","Itaguatins","1710706"],["TO","Itapiratins","1710904"],["TO","Itaporã do Tocantins","1711100"],["TO","Jaú do Tocantins","1711506"],["TO","Juarina","1711803"],["TO","Lagoa da Confusão","1711902"],["TO","Lagoa do Tocantins","1711951"],["TO","Lajeado","1712009"],["TO","Lavandeira","1712157"],["TO","Lizarda","1712405"],["TO","Luzinópolis","1712454"],["TO","Marianópolis do Tocantins","1712504"],["TO","Mateiros","1712702"],["TO","Maurilândia do Tocantins","1712801"],["TO","Miracema do Tocantins","1713205"],["TO","Miranorte","1713304"],["TO","Monte do Carmo","1713601"],["TO","Monte Santo do Tocantins","1713700"],["TO","Muricilândia","1713957"],["TO","Natividade","1714203"],["TO","Nazaré","1714302"],["TO","Nova Olinda","1714880"],["TO","Nova Rosalândia","1715002"],["TO","Novo Acordo","1715101"],["TO","Novo Alegre","1715150"],["TO","Novo Jardim","1715259"],["TO","Oliveira de Fátima","1715507"],["TO","Palmas","1721000"],["TO","Palmeirante","1715705"],["TO","Palmeiras do Tocantins","1713809"],["TO","Palmeirópolis","1715754"],["TO","Paraíso do Tocantins","1716109"],["TO","Paranã","1716208"],["TO","Pau D'Arco","1716307"],["TO","Pedro Afonso","1716505"],["TO","Peixe","1716604"],["TO","Pequizeiro","1716653"],["TO","Pindorama do Tocantins","1717008"],["TO","Piraquê","1717206"],["TO","Pium","1717503"],["TO","Ponte Alta do Bom Jesus","1717800"],["TO","Ponte Alta do Tocantins","1717909"],["TO","Porto Alegre do Tocantins","1718006"],["TO","Porto Nacional","1718204"],["TO","Praia Norte","1718303"],["TO","Presidente Kennedy","1718402"],["TO","Pugmil","1718451"],["TO","Recursolândia","1718501"],["TO","Riachinho","1718550"],["TO","Rio da Conceição","1718659"],["TO","Rio dos Bois","1718709"],["TO","Rio Sono","1718758"],["TO","Sampaio","1718808"],["TO","Sandolândia","1718840"],["TO","Santa Fé do Araguaia","1718865"],["TO","Santa Maria do Tocantins","1718881"],["TO","Santa Rita do Tocantins","1718899"],["TO","Santa Rosa do Tocantins","1718907"],["TO","Santa Tereza do Tocantins","1719004"],["TO","Santa Terezinha do Tocantins","1720002"],["TO","São Bento do Tocantins","1720101"],["TO","São Félix do Tocantins","1720150"],["TO","São Miguel do Tocantins","1720200"],["TO","São Salvador do Tocantins","1720259"],["TO","São Sebastião do Tocantins","1720309"],["TO","São Valério","1720499"],["TO","Silvanópolis","1720655"],["TO","Sítio Novo do Tocantins","1720804"],["TO","Sucupira","1720853"],["TO","Tabocão","1708254"],["TO","Taguatinga","1720903"],["TO","Taipas do Tocantins","1720937"],["TO","Talismã","1720978"],["TO","Tocantínia","1721109"],["TO","Tocantinópolis","1721208"],["TO","Tupirama","1721257"],["TO","Tupiratins","1721307"],["TO","Wanderlândia","1722081"],["TO","Xambioá","1722107"]],"groups":{"AC":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21],"AL":[22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123],"AP":[124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139],"AM":[140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201],"BA":[202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,270,271,272,273,274,275,276,277,278,279,280,281,282,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,350,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,371,372,373,374,375,376,377,378,379,380,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,400,401,402,403,404,405,406,407,408,409,410,411,412,413,414,415,416,417,418,419,420,421,422,423,424,425,426,427,428,429,430,431,432,433,434,435,436,437,438,439,440,441,442,443,444,445,446,447,448,449,450,451,452,453,454,455,456,457,458,459,460,461,462,463,464,465,466,467,468,469,470,471,472,473,474,475,476,477,478,479,480,481,482,483,484,485,486,487,488,489,490,491,492,493,494,495,496,497,498,499,500,501,502,503,504,505,506,507,508,509,510,511,512,513,514,515,516,517,518,519,520,521,522,523,524,525,526,527,528,529,530,531,532,533,534,535,536,537,538,539,540,541,542,543,544,545,546,547,548,549,550,551,552,553,554,555,556,557,558,559,560,561,562,563,564,565,566,567,568,569,570,571,572,573,574,575,576,577,578,579,580,581,582,583,584,585,586,587,588,589,590,591,592,593,594,595,596,597,598,599,600,601,602,603,604,605,606,607,608,609,610,611,612,613,614,615,616,617,618],"CE":[619,620,621,622,623,624,625,626,627,628,629,630,631,632,633,634,635,636,637,638,639,640,641,642,643,644,645,646,647,648,649,650,651,652,653,654,655,656,657,658,659,660,661,662,663,664,665,666,667,668,669,670,671,672,673,674,675,676,677,678,679,680,681,682,683,684,685,686,687,688,689,690,691,692,693,694,695,696,697,698,699,700,701,702,703,704,705,706,707,708,709,710,711,712,713,714,715,716,717,718,719,720,721,722,723,724,725,726,727,728,729,730,731,732,733,734,735,736,737,738,739,740,741,742,743,744,745,746,747,748,749,750,751,752,753,754,755,756,757,758,759,760,761,762,763,764,765,766,767,768,769,770,771,772,773,774,775,776,777,778,779,780,781,782,783,784,785,786,787,788,789,790,791,792,793,794,795,796,797,798,799,800,801,802],"DF":[803],"ES":[804,805,806,807,808,809,810,811,812,813,814,815,816,817,818,819,820,821,822,823,824,825,826,827,828,829,830,831,832,833,834,835,836,837,838,839,840,841,842,843,844,845,846,847,848,849,850,851,852,853,854,855,856,857,858,859,860,861,862,863,864,865,866,867,868,869,870,871,872,873,874,875,876,877,878,879,880,881],"GO":[882,883,884,885,886,887,888,889,890,891,892,893,894,895,896,897,898,899,900,901,902,903,904,905,906,907,908,909,910,911,912,913,914,915,916,917,918,919,920,921,922,923,924,925,926,927,928,929,930,931,932,933,934,935,936,937,938,939,940,941,942,943,944,945,946,947,948,949,950,951,952,953,954,955,956,957,958,959,960,961,962,963,964,965,966,967,968,969,970,971,972,973,974,975,976,977,978,979,980,981,982,983,984,985,986,987,988,989,990,991,992,993,994,995,996,997,998,999,1000,1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1011,1012,1013,1014,1015,1016,1017,1018,1019,1020,1021,1022,1023,1024,1025,1026,1027,1028,1029,1030,1031,1032,1033,1034,1035,1036,1037,1038,1039,1040,1041,1042,1043,1044,1045,1046,1047,1048,1049,1050,1051,1052,1053,1054,1055,1056,1057,1058,1059,1060,1061,1062,1063,1064,1065,1066,1067,1068,1069,1070,1071,1072,1073,1074,1075,1076,1077,1078,1079,1080,1081,1082,1083,1084,1085,1086,1087,1088,1089,1090,1091,1092,1093,1094,1095,1096,1097,1098,1099,1100,1101,1102,1103,1104,1105,1106,1107,1108,1109,1110,1111,1112,1113,1114,1115,1116,1117,1118,1119,1120,1121,1122,1123,1124,1125,1126,1127],"MA":[1128,1129,1130,1131,1132,1133,1134,1135,1136,1137,1138,1139,1140,1141,1142,1143,1144,1145,1146,1147,1148,1149,1150,1151,1152,1153,1154,1155,1156,1157,1158,1159,1160,1161,1162,1163,1164,1165,1166,1167,1168,1169,1170,1171,1172,1173,1174,1175,1176,1177,1178,1179,1180,1181,1182,1183,1184,1185,1186,1187,1188,1189,1190,1191,1192,1193,1194,1195,1196,1197,1198,1199,1200,1201,1202,1203,1204,1205,1206,1207,1208,1209,1210,1211,1212,1213,1214,1215,1216,1217,1218,1219,1220,1221,1222,1223,1224,1225,1226,1227,1228,1229,1230,1231,1232,1233,1234,1235,1236,1237,1238,1239,1240,1241,1242,1243,1244,1245,1246,1247,1248,1249,1250,1251,1252,1253,1254,1255,1256,1257,1258,1259,1260,1261,1262,1263,1264,1265,1266,1267,1268,1269,1270,1271,1272,1273,1274,1275,1276,1277,1278,1279,1280,1281,1282,1283,1284,1285,1286,1287,1288,1289,1290,1291,1292,1293,1294,1295,1296,1297,1298,1299,1300,1301,1302,1303,1304,1305,1306,1307,1308,1309,1310,1311,1312,1313,1314,1315,1316,1317,1318,1319,1320,1321,1322,1323,1324,1325,1326,1327,1328,1329,1330,1331,1332,1333,1334,1335,1336,1337,1338,1339,1340,1341,1342,1343,1344],"MT":[1345,1346,1347,1348,1349,1350,1351,1352,1353,1354,1355,1356,1357,1358,1359,1360,1361,1362,1363,1364,1365,1366,1367,1368,1369,1370,1371,1372,1373,1374,1375,1376,1377,1378,1379,1380,1381,1382,1383,1384,1385,1386,1387,1388,1389,1390,1391,1392,1393,1394,1395,1396,1397,1398,1399,1400,1401,1402,1403,1404,1405,1406,1407,1408,1409,1410,1411,1412,1413,1414,1415,1416,1417,1418,1419,1420,1421,1422,1423,1424,1425,1426,1427,1428,1429,1430,1431,1432,1433,1434,1435,1436,1437,1438,1439,1440,1441,1442,1443,1444,1445,1446,1447,1448,1449,1450,1451,1452,1453,1454,1455,1456,1457,1458,1459,1460,1461,1462,1463,1464,1465,1466,1467,1468,1469,1470,1471,1472,1473,1474,1475,1476,1477,1478,1479,1480,1481,1482,1483,1484,1485,1486],"MS":[1487,1488,1489,1490,1491,1492,1493,1494,1495,1496,1497,1498,1499,1500,1501,1502,1503,1504,1505,1506,1507,1508,1509,1510,1511,1512,1513,1514,1515,1516,1517,1518,1519,1520,1521,1522,1523,1524,1525,1526,1527,1528,1529,1530,1531,1532,1533,1534,1535,1536,1537,1538,1539,1540,1541,1542,1543,1544,1545,1546,1547,1548,1549,1550,1551,1552,1553,1554,1555,1556,1557,1558,1559,1560,1561,1562,1563,1564,1565],"MG":[1566,1567,1568,1569,1570,1571,1572,1573,1574,1575,1576,1577,1578,1579,1580,1581,1582,1583,1584,1585,1586,1587,1588,1589,1590,1591,1592,1593,1594,1595,1596,1597,1598,1599,1600,1601,1602,1603,1604,1605,1606,1607,1608,1609,1610,1611,1612,1613,1614,1615,1616,1617,1618,1619,1620,1621,1622,1623,1624,1625,1626,1627,1628,1629,1630,1631,1632,1633,1634,1635,1636,1637,1638,1639,1640,1641,1642,1643,1644,1645,1646,1647,1648,1649,1650,1651,1652,1653,1654,1655,1656,1657,1658,1659,1660,1661,1662,1663,1664,1665,1666,1667,1668,1669,1670,1671,1672,1673,1674,1675,1676,1677,1678,1679,1680,1681,1682,1683,1684,1685,1686,1687,1688,1689,1690,1691,1692,1693,1694,1695,1696,1697,1698,1699,1700,1701,1702,1703,1704,1705,1706,1707,1708,1709,1710,1711,1712,1713,1714,1715,1716,1717,1718,1719,1720,1721,1722,1723,1724,1725,1726,1727,1728,1729,1730,1731,1732,1733,1734,1735,1736,1737,1738,1739,1740,1741,1742,1743,1744,1745,1746,1747,1748,1749,1750,1751,1752,1753,1754,1755,1756,1757,1758,1759,1760,1761,1762,1763,1764,1765,1766,1767,1768,1769,1770,1771,1772,1773,1774,1775,1776,1777,1778,1779,1780,1781,1782,1783,1784,1785,1786,1787,1788,1789,1790,1791,1792,1793,1794,1795,1796,1797,1798,1799,1800,1801,1802,1803,1804,1805,1806,1807,1808,1809,1810,1811,1812,1813,1814,1815,1816,1817,1818,1819,1820,1821,1822,1823,1824,1825,1826,1827,1828,1829,1830,1831,1832,1833,1834,1835,1836,1837,1838,1839,1840,1841,1842,1843,1844,1845,1846,1847,1848,1849,1850,1851,1852,1853,1854,1855,1856,1857,1858,1859,1860,1861,1862,1863,1864,1865,1866,1867,1868,1869,1870,1871,1872,1873,1874,1875,1876,1877,1878,1879,1880,1881,1882,1883,1884,1885,1886,1887,1888,1889,1890,1891,1892,1893,1894,1895,1896,1897,1898,1899,1900,1901,1902,1903,1904,1905,1906,1907,1908,1909,1910,1911,1912,1913,1914,1915,1916,1917,1918,1919,1920,1921,1922,1923,1924,1925,1926,1927,1928,1929,1930,1931,1932,1933,1934,1935,1936,1937,1938,1939,1940,1941,1942,1943,1944,1945,1946,1947,1948,1949,1950,1951,1952,1953,1954,1955,1956,1957,1958,1959,1960,1961,1962,1963,1964,1965,1966,1967,1968,1969,1970,1971,1972,1973,1974,1975,1976,1977,1978,1979,1980,1981,1982,1983,1984,1985,1986,1987,1988,1989,1990,1991,1992,1993,1994,1995,1996,1997,1998,1999,2000,2001,2002,2003,2004,2005,2006,2007,2008,2009,2010,2011,2012,2013,2014,2015,2016,2017,2018,2019,2020,2021,2022,2023,2024,2025,2026,2027,2028,2029,2030,2031,2032,2033,2034,2035,2036,2037,2038,2039,2040,2041,2042,2043,2044,2045,2046,2047,2048,2049,2050,2051,2052,2053,2054,2055,2056,2057,2058,2059,2060,2061,2062,2063,2064,2065,2066,2067,2068,2069,2070,2071,2072,2073,2074,2075,2076,2077,2078,2079,2080,2081,2082,2083,2084,2085,2086,2087,2088,2089,2090,2091,2092,2093,2094,2095,2096,2097,2098,2099,2100,2101,2102,2103,2104,2105,2106,2107,2108,2109,2110,2111,2112,2113,2114,2115,2116,2117,2118,2119,2120,2121,2122,2123,2124,2125,2126,2127,2128,2129,2130,2131,2132,2133,2134,2135,2136,2137,2138,2139,2140,2141,2142,2143,2144,2145,2146,2147,2148,2149,2150,2151,2152,2153,2154,2155,2156,2157,2158,2159,2160,2161,2162,2163,2164,2165,2166,2167,2168,2169,2170,2171,2172,2173,2174,2175,2176,2177,2178,2179,2180,2181,2182,2183,2184,2185,2186,2187,2188,2189,2190,2191,2192,2193,2194,2195,2196,2197,2198,2199,2200,2201,2202,2203,2204,2205,2206,2207,2208,2209,2210,2211,2212,2213,2214,2215,2216,2217,2218,2219,2220,2221,2222,2223,2224,2225,2226,2227,2228,2229,2230,2231,2232,2233,2234,2235,2236,2237,2238,2239,2240,2241,2242,2243,2244,2245,2246,2247,2248,2249,2250,2251,2252,2253,2254,2255,2256,2257,2258,2259,2260,2261,2262,2263,2264,2265,2266,2267,2268,2269,2270,2271,2272,2273,2274,2275,2276,2277,2278,2279,2280,2281,2282,2283,2284,2285,2286,2287,2288,2289,2290,2291,2292,2293,2294,2295,2296,2297,2298,2299,2300,2301,2302,2303,2304,2305,2306,2307,2308,2309,2310,2311,2312,2313,2314,2315,2316,2317,2318,2319,2320,2321,2322,2323,2324,2325,2326,2327,2328,2329,2330,2331,2332,2333,2334,2335,2336,2337,2338,2339,2340,2341,2342,2343,2344,2345,2346,2347,2348,2349,2350,2351,2352,2353,2354,2355,2356,2357,2358,2359,2360,2361,2362,2363,2364,2365,2366,2367,2368,2369,2370,2371,2372,2373,2374,2375,2376,2377,2378,2379,2380,2381,2382,2383,2384,2385,2386,2387,2388,2389,2390,2391,2392,2393,2394,2395,2396,2397,2398,2399,2400,2401,2402,2403,2404,2405,2406,2407,2408,2409,2410,2411,2412,2413,2414,2415,2416,2417,2418],"PA":[2419,2420,2421,2422,2423,2424,2425,2426,2427,2428,2429,2430,2431,2432,2433,2434,2435,2436,2437,2438,2439,2440,2441,2442,2443,2444,2445,2446,2447,2448,2449,2450,2451,2452,2453,2454,2455,2456,2457,2458,2459,2460,2461,2462,2463,2464,2465,2466,2467,2468,2469,2470,2471,2472,2473,2474,2475,2476,2477,2478,2479,2480,2481,2482,2483,2484,2485,2486,2487,2488,2489,2490,2491,2492,2493,2494,2495,2496,2497,2498,2499,2500,2501,2502,2503,2504,2505,2506,2507,2508,2509,2510,2511,2512,2513,2514,2515,2516,2517,2518,2519,2520,2521,2522,2523,2524,2525,2526,2527,2528,2529,2530,2531,2532,2533,2534,2535,2536,2537,2538,2539,2540,2541,2542,2543,2544,2545,2546,2547,2548,2549,2550,2551,2552,2553,2554,2555,2556,2557,2558,2559,2560,2561,2562],"PB":[2563,2564,2565,2566,2567,2568,2569,2570,2571,2572,2573,2574,2575,2576,2577,2578,2579,2580,2581,2582,2583,2584,2585,2586,2587,2588,2589,2590,2591,2592,2593,2594,2595,2596,2597,2598,2599,2600,2601,2602,2603,2604,2605,2606,2607,2608,2609,2610,2611,2612,2613,2614,2615,2616,2617,2618,2619,2620,2621,2622,2623,2624,2625,2626,2627,2628,2629,2630,2631,2632,2633,2634,2635,2636,2637,2638,2639,2640,2641,2642,2643,2644,2645,2646,2647,2648,2649,2650,2651,2652,2653,2654,2655,2656,2657,2658,2659,2660,2661,2662,2663,2664,2665,2666,2667,2668,2669,2670,2671,2672,2673,2674,2675,2676,2677,2678,2679,2680,2681,2682,2683,2684,2685,2686,2687,2688,2689,2690,2691,2692,2693,2694,2695,2696,2697,2698,2699,2700,2701,2702,2703,2704,2705,2706,2707,2708,2709,2710,2711,2712,2713,2714,2715,2716,2717,2718,2719,2720,2721,2722,2723,2724,2725,2726,2727,2728,2729,2730,2731,2732,2733,2734,2735,2736,2737,2738,2739,2740,2741,2742,2743,2744,2745,2746,2747,2748,2749,2750,2751,2752,2753,2754,2755,2756,2757,2758,2759,2760,2761,2762,2763,2764,2765,2766,2767,2768,2769,2770,2771,2772,2773,2774,2775,2776,2777,2778,2779,2780,2781,2782,2783,2784,2785],"PR":[2786,2787,2788,2789,2790,2791,2792,2793,2794,2795,2796,2797,2798,2799,2800,2801,2802,2803,2804,2805,2806,2807,2808,2809,2810,2811,2812,2813,2814,2815,2816,2817,2818,2819,2820,2821,2822,2823,2824,2825,2826,2827,2828,2829,2830,2831,2832,2833,2834,2835,2836,2837,2838,2839,2840,2841,2842,2843,2844,2845,2846,2847,2848,2849,2850,2851,2852,2853,2854,2855,2856,2857,2858,2859,2860,2861,2862,2863,2864,2865,2866,2867,2868,2869,2870,2871,2872,2873,2874,2875,2876,2877,2878,2879,2880,2881,2882,2883,2884,2885,2886,2887,2888,2889,2890,2891,2892,2893,2894,2895,2896,2897,2898,2899,2900,2901,2902,2903,2904,2905,2906,2907,2908,2909,2910,2911,2912,2913,2914,2915,2916,2917,2918,2919,2920,2921,2922,2923,2924,2925,2926,2927,2928,2929,2930,2931,2932,2933,2934,2935,2936,2937,2938,2939,2940,2941,2942,2943,2944,2945,2946,2947,2948,2949,2950,2951,2952,2953,2954,2955,2956,2957,2958,2959,2960,2961,2962,2963,2964,2965,2966,2967,2968,2969,2970,2971,2972,2973,2974,2975,2976,2977,2978,2979,2980,2981,2982,2983,2984,2985,2986,2987,2988,2989,2990,2991,2992,2993,2994,2995,2996,2997,2998,2999,3000,3001,3002,3003,3004,3005,3006,3007,3008,3009,3010,3011,3012,3013,3014,3015,3016,3017,3018,3019,3020,3021,3022,3023,3024,3025,3026,3027,3028,3029,3030,3031,3032,3033,3034,3035,3036,3037,3038,3039,3040,3041,3042,3043,3044,3045,3046,3047,3048,3049,3050,3051,3052,3053,3054,3055,3056,3057,3058,3059,3060,3061,3062,3063,3064,3065,3066,3067,3068,3069,3070,3071,3072,3073,3074,3075,3076,3077,3078,3079,3080,3081,3082,3083,3084,3085,3086,3087,3088,3089,3090,3091,3092,3093,3094,3095,3096,3097,3098,3099,3100,3101,3102,3103,3104,3105,3106,3107,3108,3109,3110,3111,3112,3113,3114,3115,3116,3117,3118,3119,3120,3121,3122,3123,3124,3125,3126,3127,3128,3129,3130,3131,3132,3133,3134,3135,3136,3137,3138,3139,3140,3141,3142,3143,3144,3145,3146,3147,3148,3149,3150,3151,3152,3153,3154,3155,3156,3157,3158,3159,3160,3161,3162,3163,3164,3165,3166,3167,3168,3169,3170,3171,3172,3173,3174,3175,3176,3177,3178,3179,3180,3181,3182,3183,3184],"PE":[3185,3186,3187,3188,3189,3190,3191,3192,3193,3194,3195,3196,3197,3198,3199,3200,3201,3202,3203,3204,3205,3206,3207,3208,3209,3210,3211,3212,3213,3214,3215,3216,3217,3218,3219,3220,3221,3222,3223,3224,3225,3226,3227,3228,3229,3230,3231,3232,3233,3234,3235,3236,3237,3238,3239,3240,3241,3242,3243,3244,3245,3246,3247,3248,3249,3250,3251,3252,3253,3254,3255,3256,3257,3258,3259,3260,3261,3262,3263,3264,3265,3266,3267,3268,3269,3270,3271,3272,3273,3274,3275,3276,3277,3278,3279,3280,3281,3282,3283,3284,3285,3286,3287,3288,3289,3290,3291,3292,3293,3294,3295,3296,3297,3298,3299,3300,3301,3302,3303,3304,3305,3306,3307,3308,3309,3310,3311,3312,3313,3314,3315,3316,3317,3318,3319,3320,3321,3322,3323,3324,3325,3326,3327,3328,3329,3330,3331,3332,3333,3334,3335,3336,3337,3338,3339,3340,3341,3342,3343,3344,3345,3346,3347,3348,3349,3350,3351,3352,3353,3354,3355,3356,3357,3358,3359,3360,3361,3362,3363,3364,3365,3366,3367,3368,3369],"PI":[3370,3371,3372,3373,3374,3375,3376,3377,3378,3379,3380,3381,3382,3383,3384,3385,3386,3387,3388,3389,3390,3391,3392,3393,3394,3395,3396,3397,3398,3399,3400,3401,3402,3403,3404,3405,3406,3407,3408,3409,3410,3411,3412,3413,3414,3415,3416,3417,3418,3419,3420,3421,3422,3423,3424,3425,3426,3427,3428,3429,3430,3431,3432,3433,3434,3435,3436,3437,3438,3439,3440,3441,3442,3443,3444,3445,3446,3447,3448,3449,3450,3451,3452,3453,3454,3455,3456,3457,3458,3459,3460,3461,3462,3463,3464,3465,3466,3467,3468,3469,3470,3471,3472,3473,3474,3475,3476,3477,3478,3479,3480,3481,3482,3483,3484,3485,3486,3487,3488,3489,3490,3491,3492,3493,3494,3495,3496,3497,3498,3499,3500,3501,3502,3503,3504,3505,3506,3507,3508,3509,3510,3511,3512,3513,3514,3515,3516,3517,3518,3519,3520,3521,3522,3523,3524,3525,3526,3527,3528,3529,3530,3531,3532,3533,3534,3535,3536,3537,3538,3539,3540,3541,3542,3543,3544,3545,3546,3547,3548,3549,3550,3551,3552,3553,3554,3555,3556,3557,3558,3559,3560,3561,3562,3563,3564,3565,3566,3567,3568,3569,3570,3571,3572,3573,3574,3575,3576,3577,3578,3579,3580,3581,3582,3583,3584,3585,3586,3587,3588,3589,3590,3591,3592,3593],"RJ":[3594,3595,3596,3597,3598,3599,3600,3601,3602,3603,3604,3605,3606,3607,3608,3609,3610,3611,3612,3613,3614,3615,3616,3617,3618,3619,3620,3621,3622,3623,3624,3625,3626,3627,3628,3629,3630,3631,3632,3633,3634,3635,3636,3637,3638,3639,3640,3641,3642,3643,3644,3645,3646,3647,3648,3649,3650,3651,3652,3653,3654,3655,3656,3657,3658,3659,3660,3661,3662,3663,3664,3665,3666,3667,3668,3669,3670,3671,3672,3673,3674,3675,3676,3677,3678,3679,3680,3681,3682,3683,3684,3685],"RN":[3686,3687,3688,3689,3690,3691,3692,3693,3694,3695,3696,3697,3698,3699,3700,3701,3702,3703,3704,3705,3706,3707,3708,3709,3710,3711,3712,3713,3714,3715,3716,3717,3718,3719,3720,3721,3722,3723,3724,3725,3726,3727,3728,3729,3730,3731,3732,3733,3734,3735,3736,3737,3738,3739,3740,3741,3742,3743,3744,3745,3746,3747,3748,3749,3750,3751,3752,3753,3754,3755,3756,3757,3758,3759,3760,3761,3762,3763,3764,3765,3766,3767,3768,3769,3770,3771,3772,3773,3774,3775,3776,3777,3778,3779,3780,3781,3782,3783,3784,3785,3786,3787,3788,3789,3790,3791,3792,3793,3794,3795,3796,3797,3798,3799,3800,3801,3802,3803,3804,3805,3806,3807,3808,3809,3810,3811,3812,3813,3814,3815,3816,3817,3818,3819,3820,3821,3822,3823,3824,3825,3826,3827,3828,3829,3830,3831,3832,3833,3834,3835,3836,3837,3838,3839,3840,3841,3842,3843,3844,3845,3846,3847,3848,3849,3850,3851,3852],"RS":[3853,3854,3855,3856,3857,3858,3859,3860,3861,3862,3863,3864,3865,3866,3867,3868,3869,3870,3871,3872,3873,3874,3875,3876,3877,3878,3879,3880,3881,3882,3883,3884,3885,3886,3887,3888,3889,3890,3891,3892,3893,3894,3895,3896,3897,3898,3899,3900,3901,3902,3903,3904,3905,3906,3907,3908,3909,3910,3911,3912,3913,3914,3915,3916,3917,3918,3919,3920,3921,3922,3923,3924,3925,3926,3927,3928,3929,3930,3931,3932,3933,3934,3935,3936,3937,3938,3939,3940,3941,3942,3943,3944,3945,3946,3947,3948,3949,3950,3951,3952,3953,3954,3955,3956,3957,3958,3959,3960,3961,3962,3963,3964,3965,3966,3967,3968,3969,3970,3971,3972,3973,3974,3975,3976,3977,3978,3979,3980,3981,3982,3983,3984,3985,3986,3987,3988,3989,3990,3991,3992,3993,3994,3995,3996,3997,3998,3999,4000,4001,4002,4003,4004,4005,4006,4007,4008,4009,4010,4011,4012,4013,4014,4015,4016,4017,4018,4019,4020,4021,4022,4023,4024,4025,4026,4027,4028,4029,4030,4031,4032,4033,4034,4035,4036,4037,4038,4039,4040,4041,4042,4043,4044,4045,4046,4047,4048,4049,4050,4051,4052,4053,4054,4055,4056,4057,4058,4059,4060,4061,4062,4063,4064,4065,4066,4067,4068,4069,4070,4071,4072,4073,4074,4075,4076,4077,4078,4079,4080,4081,4082,4083,4084,4085,4086,4087,4088,4089,4090,4091,4092,4093,4094,4095,4096,4097,4098,4099,4100,4101,4102,4103,4104,4105,4106,4107,4108,4109,4110,4111,4112,4113,4114,4115,4116,4117,4118,4119,4120,4121,4122,4123,4124,4125,4126,4127,4128,4129,4130,4131,4132,4133,4134,4135,4136,4137,4138,4139,4140,4141,4142,4143,4144,4145,4146,4147,4148,4149,4150,4151,4152,4153,4154,4155,4156,4157,4158,4159,4160,4161,4162,4163,4164,4165,4166,4167,4168,4169,4170,4171,4172,4173,4174,4175,4176,4177,4178,4179,4180,4181,4182,4183,4184,4185,4186,4187,4188,4189,4190,4191,4192,4193,4194,4195,4196,4197,4198,4199,4200,4201,4202,4203,4204,4205,4206,4207,4208,4209,4210,4211,4212,4213,4214,4215,4216,4217,4218,4219,4220,4221,4222,4223,4224,4225,4226,4227,4228,4229,4230,4231,4232,4233,4234,4235,4236,4237,4238,4239,4240,4241,4242,4243,4244,4245,4246,4247,4248,4249,4250,4251,4252,4253,4254,4255,4256,4257,4258,4259,4260,4261,4262,4263,4264,4265,4266,4267,4268,4269,4270,4271,4272,4273,4274,4275,4276,4277,4278,4279,4280,4281,4282,4283,4284,4285,4286,4287,4288,4289,4290,4291,4292,4293,4294,4295,4296,4297,4298,4299,4300,4301,4302,4303,4304,4305,4306,4307,4308,4309,4310,4311,4312,4313,4314,4315,4316,4317,4318,4319,4320,4321,4322,4323,4324,4325,4326,4327,4328,4329,4330,4331,4332,4333,4334,4335,4336,4337,4338,4339,4340,4341,4342,4343,4344,4345,4346,4347,4348,4349],"RO":[4350,4351,4352,4353,4354,4355,4356,4357,4358,4359,4360,4361,4362,4363,4364,4365,4366,4367,4368,4369,4370,4371,4372,4373,4374,4375,4376,4377,4378,4379,4380,4381,4382,4383,4384,4385,4386,4387,4388,4389,4390,4391,4392,4393,4394,4395,4396,4397,4398,4399,4400,4401],"RR":[4402,4403,4404,4405,4406,4407,4408,4409,4410,4411,4412,4413,4414,4415,4416],"SC":[4417,4418,4419,4420,4421,4422,4423,4424,4425,4426,4427,4428,4429,4430,4431,4432,4433,4434,4435,4436,4437,4438,4439,4440,4441,4442,4443,4444,4445,4446,4447,4448,4449,4450,4451,4452,4453,4454,4455,4456,4457,4458,4459,4460,4461,4462,4463,4464,4465,4466,4467,4468,4469,4470,4471,4472,4473,4474,4475,4476,4477,4478,4479,4480,4481,4482,4483,4484,4485,4486,4487,4488,4489,4490,4491,4492,4493,4494,4495,4496,4497,4498,4499,4500,4501,4502,4503,4504,4505,4506,4507,4508,4509,4510,4511,4512,4513,4514,4515,4516,4517,4518,4519,4520,4521,4522,4523,4524,4525,4526,4527,4528,4529,4530,4531,4532,4533,4534,4535,4536,4537,4538,4539,4540,4541,4542,4543,4544,4545,4546,4547,4548,4549,4550,4551,4552,4553,4554,4555,4556,4557,4558,4559,4560,4561,4562,4563,4564,4565,4566,4567,4568,4569,4570,4571,4572,4573,4574,4575,4576,4577,4578,4579,4580,4581,4582,4583,4584,4585,4586,4587,4588,4589,4590,4591,4592,4593,4594,4595,4596,4597,4598,4599,4600,4601,4602,4603,4604,4605,4606,4607,4608,4609,4610,4611,4612,4613,4614,4615,4616,4617,4618,4619,4620,4621,4622,4623,4624,4625,4626,4627,4628,4629,4630,4631,4632,4633,4634,4635,4636,4637,4638,4639,4640,4641,4642,4643,4644,4645,4646,4647,4648,4649,4650,4651,4652,4653,4654,4655,4656,4657,4658,4659,4660,4661,4662,4663,4664,4665,4666,4667,4668,4669,4670,4671,4672,4673,4674,4675,4676,4677,4678,4679,4680,4681,4682,4683,4684,4685,4686,4687,4688,4689,4690,4691,4692,4693,4694,4695,4696,4697,4698,4699,4700,4701,4702,4703,4704,4705,4706,4707,4708,4709,4710,4711],"SP":[4712,4713,4714,4715,4716,4717,4718,4719,4720,4721,4722,4723,4724,4725,4726,4727,4728,4729,4730,4731,4732,4733,4734,4735,4736,4737,4738,4739,4740,4741,4742,4743,4744,4745,4746,4747,4748,4749,4750,4751,4752,4753,4754,4755,4756,4757,4758,4759,4760,4761,4762,4763,4764,4765,4766,4767,4768,4769,4770,4771,4772,4773,4774,4775,4776,4777,4778,4779,4780,4781,4782,4783,4784,4785,4786,4787,4788,4789,4790,4791,4792,4793,4794,4795,4796,4797,4798,4799,4800,4801,4802,4803,4804,4805,4806,4807,4808,4809,4810,4811,4812,4813,4814,4815,4816,4817,4818,4819,4820,4821,4822,4823,4824,4825,4826,4827,4828,4829,4830,4831,4832,4833,4834,4835,4836,4837,4838,4839,4840,4841,4842,4843,4844,4845,4846,4847,4848,4849,4850,4851,4852,4853,4854,4855,4856,4857,4858,4859,4860,4861,4862,4863,4864,4865,4866,4867,4868,4869,4870,4871,4872,4873,4874,4875,4876,4877,4878,4879,4880,4881,4882,4883,4884,4885,4886,4887,4888,4889,4890,4891,4892,4893,4894,4895,4896,4897,4898,4899,4900,4901,4902,4903,4904,4905,4906,4907,4908,4909,4910,4911,4912,4913,4914,4915,4916,4917,4918,4919,4920,4921,4922,4923,4924,4925,4926,4927,4928,4929,4930,4931,4932,4933,4934,4935,4936,4937,4938,4939,4940,4941,4942,4943,4944,4945,4946,4947,4948,4949,4950,4951,4952,4953,4954,4955,4956,4957,4958,4959,4960,4961,4962,4963,4964,4965,4966,4967,4968,4969,4970,4971,4972,4973,4974,4975,4976,4977,4978,4979,4980,4981,4982,4983,4984,4985,4986,4987,4988,4989,4990,4991,4992,4993,4994,4995,4996,4997,4998,4999,5000,5001,5002,5003,5004,5005,5006,5007,5008,5009,5010,5011,5012,5013,5014,5015,5016,5017,5018,5019,5020,5021,5022,5023,5024,5025,5026,5027,5028,5029,5030,5031,5032,5033,5034,5035,5036,5037,5038,5039,5040,5041,5042,5043,5044,5045,5046,5047,5048,5049,5050,5051,5052,5053,5054,5055,5056,5057,5058,5059,5060,5061,5062,5063,5064,5065,5066,5067,5068,5069,5070,5071,5072,5073,5074,5075,5076,5077,5078,5079,5080,5081,5082,5083,5084,5085,5086,5087,5088,5089,5090,5091,5092,5093,5094,5095,5096,5097,5098,5099,5100,5101,5102,5103,5104,5105,5106,5107,5108,5109,5110,5111,5112,5113,5114,5115,5116,5117,5118,5119,5120,5121,5122,5123,5124,5125,5126,5127,5128,5129,5130,5131,5132,5133,5134,5135,5136,5137,5138,5139,5140,5141,5142,5143,5144,5145,5146,5147,5148,5149,5150,5151,5152,5153,5154,5155,5156,5157,5158,5159,5160,5161,5162,5163,5164,5165,5166,5167,5168,5169,5170,5171,5172,5173,5174,5175,5176,5177,5178,5179,5180,5181,5182,5183,5184,5185,5186,5187,5188,5189,5190,5191,5192,5193,5194,5195,5196,5197,5198,5199,5200,5201,5202,5203,5204,5205,5206,5207,5208,5209,5210,5211,5212,5213,5214,5215,5216,5217,5218,5219,5220,5221,5222,5223,5224,5225,5226,5227,5228,5229,5230,5231,5232,5233,5234,5235,5236,5237,5238,5239,5240,5241,5242,5243,5244,5245,5246,5247,5248,5249,5250,5251,5252,5253,5254,5255,5256,5257,5258,5259,5260,5261,5262,5263,5264,5265,5266,5267,5268,5269,5270,5271,5272,5273,5274,5275,5276,5277,5278,5279,5280,5281,5282,5283,5284,5285,5286,5287,5288,5289,5290,5291,5292,5293,5294,5295,5296,5297,5298,5299,5300,5301,5302,5303,5304,5305,5306,5307,5308,5309,5310,5311,5312,5313,5314,5315,5316,5317,5318,5319,5320,5321,5322,5323,5324,5325,5326,5327,5328,5329,5330,5331,5332,5333,5334,5335,5336,5337,5338,5339,5340,5341,5342,5343,5344,5345,5346,5347,5348,5349,5350,5351,5352,5353,5354,5355,5356],"SE":[5357,5358,5359,5360,5361,5362,5363,5364,5365,5366,5367,5368,5369,5370,5371,5372,5373,5374,5375,5376,5377,5378,5379,5380,5381,5382,5383,5384,5385,5386,5387,5388,5389,5390,5391,5392,5393,5394,5395,5396,5397,5398,5399,5400,5401,5402,5403,5404,5405,5406,5407,5408,5409,5410,5411,5412,5413,5414,5415,5416,5417,5418,5419,5420,5421,5422,5423,5424,5425,5426,5427,5428,5429,5430,5431],"TO":[5432,5433,5434,5435,5436,5437,5438,5439,5440,5441,5442,5443,5444,5445,5446,5447,5448,5449,5450,5451,5452,5453,5454,5455,5456,5457,5458,5459,5460,5461,5462,5463,5464,5465,5466,5467,5468,5469,5470,5471,5472,5473,5474,5475,5476,5477,5478,5479,5480,5481,5482,5483,5484,5485,5486,5487,5488,5489,5490,5491,5492,5493,5494,5495,5496,5497,5498,5499,5500,5501,5502,5503,5504,5505,5506,5507,5508,5509,5510,5511,5512,5513,5514,5515,5516,5517,5518,5519,5520,5521,5522,5523,5524,5525,5526,5527,5528,5529,5530,5531,5532,5533,5534,5535,5536,5537,5538,5539,5540,5541,5542,5543,5544,5545,5546,5547,5548,5549,5550,5551,5552,5553,5554,5555,5556,5557,5558,5559,5560,5561,5562,5563,5564,5565,5566,5567,5568,5569,5570]},"fullOrder":[882,1566,883,1567,2419,619,202,203,2786,4417,2420,4418,1568,3185,5432,1569,1128,204,2421,620,621,3686,3370,3853,622,1345,0,884,1570,4712,885,4713,2787,205,3186,3687,804,1129,3187,2422,3188,3371,4419,4420,2423,1346,1571,22,2563,3372,1487,1572,4421,1130,805,206,886,887,3688,3189,3854,4714,1573,3190,4715,4422,4716,4717,4718,1574,4423,888,4424,1575,3855,4719,2788,806,2564,5433,1576,207,623,1577,3856,1578,2565,2566,2567,3191,3373,208,4720,1579,1131,624,2568,1488,209,1132,3857,807,3858,3374,3859,1580,2424,3689,889,1581,808,4721,1582,4425,2569,2570,3192,5434,210,5435,2425,1583,3690,2789,3860,890,1584,3861,1585,1347,4350,4722,2426,1133,2790,625,1586,3193,4723,3862,4402,4724,1134,1135,4351,1348,4426,1349,1587,3691,3863,1350,891,1588,3375,1351,2791,4352,892,2792,1136,2793,1589,809,626,1352,2794,3376,4725,140,1590,4726,4727,4728,4729,1591,3864,5436,4353,1592,3377,893,2795,4403,1489,124,1137,2796,3194,3865,894,3378,1138,211,141,212,213,4730,895,4731,4732,3866,627,896,2571,4733,5357,1593,2797,23,214,2798,2427,1139,4734,142,5437,2428,897,2429,1140,1490,1491,810,4427,215,2799,216,1594,4735,3867,1595,4736,1596,1492,3195,4428,217,3379,5438,3692,3594,218,2800,898,4737,4738,899,3380,4429,4430,143,3868,219,2801,628,3381,220,1597,4431,1598,221,1493,3693,2802,3869,1599,2572,4739,4740,900,901,5439,1494,3595,811,1353,4741,1141,4432,3694,222,902,223,2803,144,629,5358,1495,630,4433,2573,1600,5359,4742,224,631,225,4743,226,1601,632,3196,4744,812,903,1602,904,905,5440,5441,5442,1354,5443,1355,1142,5444,906,1603,5445,1143,1496,227,3870,1144,4745,4746,1604,4747,24,5446,1605,2804,1606,2805,1607,2806,1356,4434,2574,4435,4748,4749,633,1145,3871,634,3197,3596,2575,2807,228,3872,635,229,5360,2808,1608,1609,1610,4750,1611,3198,1612,3597,4751,2576,3695,5361,2577,2578,4752,4753,1357,907,3696,1613,1614,1615,1358,4354,4754,2809,3598,4436,636,3382,2579,3383,3384,3599,5447,3873,3874,3875,3876,3877,3878,4437,4755,908,4756,4438,3879,4439,4757,2810,637,4758,1,2811,3697,2580,3385,1616,2812,25,2813,145,4440,1617,4759,813,5448,2430,1618,3880,3881,230,4760,909,638,4441,2431,5449,146,4761,4762,4763,2432,3386,910,1146,5450,5451,1147,1148,1149,1150,4764,1619,3882,2433,2581,3698,231,2434,232,3387,639,814,4765,1620,911,4442,4443,4444,4445,4446,3883,4447,2814,4766,1151,1621,640,4767,2582,1622,1623,4448,1497,2815,5452,2435,233,3884,4768,1624,3885,1152,1359,1625,3886,2583,3699,1626,641,4769,2816,2436,3700,147,4770,234,4449,4771,3388,235,3199,2584,2585,26,815,27,2586,1360,4772,236,1153,1361,3887,2817,237,5453,3600,3888,3889,3890,238,4773,5362,3891,1627,3601,4450,2818,3892,3389,642,239,3390,148,1154,3200,4774,4775,643,240,912,3391,241,242,5454,644,3893,1628,4776,4777,1498,28,3392,4778,1499,645,4779,2587,4780,646,647,1500,2819,913,1629,1155,2820,3393,4451,1156,29,2437,2588,3201,2589,3394,3202,3602,1630,243,4452,244,1631,3203,30,1632,1633,2438,3395,1157,4453,2439,149,3894,4781,3701,3895,1158,1634,1635,2590,4782,1159,5455,4783,3396,1636,150,3204,3397,1637,3205,1638,1639,4454,4784,1640,4785,4786,245,2821,4455,816,1641,2822,2823,1362,4787,3398,246,2591,2824,648,2592,4404,2825,3896,3897,3898,1160,3899,151,3900,247,31,152,3399,4788,1642,4456,1643,2826,3702,3206,1501,4789,4790,3207,1644,1161,3208,3603,4457,914,1645,2593,3400,3703,3901,4458,248,1646,249,1162,915,1647,1363,1648,3604,817,4459,2827,2440,5456,4791,1163,3902,3401,3903,1649,4460,3904,1650,2594,2828,4792,2829,4461,1651,4405,3402,916,1652,250,251,1502,2441,3209,1653,2595,917,2596,3905,3403,5363,252,4793,4794,153,2597,4795,1654,4796,2830,3906,1655,4797,1656,253,4462,3907,4463,4464,3908,2442,4798,2831,32,1657,2443,1503,1658,2832,5457,2,3404,803,1659,1364,4799,1660,918,1661,3210,818,3211,3704,5458,1164,4800,3212,1165,2598,3405,2599,5364,2444,649,254,255,2445,2446,919,3909,4801,4802,256,1662,257,4465,4466,1663,1664,3213,258,1665,3214,3,2447,4803,4804,1166,920,1167,921,5459,3406,3407,1168,922,259,1169,1666,4355,4805,1667,3910,154,2600,1504,260,2601,261,1668,923,3408,2602,4356,3215,3605,1669,4806,4807,3216,4467,4808,3911,4357,3912,1365,262,924,1670,925,1671,1672,2448,2449,3913,2603,926,1673,1170,4809,3606,3217,3914,5460,819,2604,2605,2606,33,3915,4358,4810,927,263,264,1674,265,1675,3218,266,267,2833,2834,4811,2835,4812,1676,928,3916,4468,2607,3917,3705,3706,3707,4813,268,4814,4815,1171,1172,4816,2608,3409,2609,4817,34,3410,1677,4818,3219,125,1678,2610,929,930,269,3411,2836,4469,3220,270,271,1679,2611,272,1680,1505,3918,3221,3919,2837,3920,2838,2839,4470,3607,1681,1682,2450,650,3222,1683,1684,35,1685,3921,931,1173,2840,3922,4819,2841,2612,2842,1686,932,1366,4820,3412,3923,933,36,4471,934,273,3413,1687,1688,4472,3924,2843,5365,1689,2844,4473,1690,274,37,1506,3708,3414,2845,3415,935,4821,2846,3416,2847,3925,4359,1367,3709,1368,1691,936,3926,1369,4822,3608,1692,5461,4474,4823,651,937,3223,1693,1694,2451,1370,4824,38,275,1695,276,1371,4825,3417,277,278,279,1696,4360,3927,280,2848,3928,1174,4826,4827,281,3929,2849,3930,4475,3710,3931,5366,3224,652,5367,4828,3932,4476,282,4406,1697,2850,3609,1175,3418,283,3933,155,2452,2851,4477,4829,3934,3935,3936,3937,1698,39,5368,3938,4830,284,1699,1700,1701,2613,1702,285,1703,4478,1176,653,3939,1704,3419,1705,3420,2852,2453,1706,4831,4479,3940,4,3225,1707,3941,4407,1507,3421,4832,1708,286,2853,1709,1710,1711,3610,4833,1712,156,2614,3711,3422,287,3942,1713,288,4834,3611,1714,157,158,820,654,3423,289,5369,655,5462,656,657,1372,2854,3943,1715,3944,1716,3612,1717,1718,1719,1720,1721,1722,938,5463,5370,1723,3226,3712,3713,658,3227,1724,40,4408,1177,3228,1725,2615,5464,3229,1178,1726,1727,4835,1728,290,3945,1729,659,2855,5465,3946,3613,3230,2616,1730,4836,1508,2454,1373,4361,939,821,3424,4837,2856,291,1731,940,4838,2857,4480,660,1732,1733,3231,4839,2617,292,2618,293,3947,1734,661,941,294,2619,1735,662,942,1736,4481,1179,3948,3425,3714,1180,4840,663,3232,5371,1737,4482,3949,5466,2858,295,1738,1181,1739,1182,1183,4362,943,4841,4842,3950,2859,3951,3715,3952,3953,3954,4483,4843,2860,944,3233,3234,41,1740,1741,3955,5467,5468,1742,1374,1743,945,4484,1509,1184,4485,4844,3956,3957,664,4845,2455,1744,3958,2861,665,666,296,3959,4363,3960,2862,297,2863,946,1185,3961,298,1745,3962,1746,1747,1375,1748,4846,2864,299,159,3426,3427,4486,3428,1376,947,300,160,1186,1187,1749,42,3429,2456,822,1377,4847,1188,3963,948,5469,5470,1378,4848,2865,3430,3431,43,2866,3964,4364,1750,5471,1751,3614,1752,1379,2620,1753,823,1754,301,1755,1756,1757,3615,302,2457,3432,824,303,304,1189,1758,1759,1760,5472,1761,4849,4850,4487,2458,2621,3235,305,2622,306,3965,1762,1763,1380,2623,1764,1765,1766,2867,1767,1381,1768,2868,1769,1770,3966,1771,2869,307,1772,3967,44,3968,1773,308,2870,3616,4851,309,4488,1774,1775,667,2624,1510,310,1776,2871,1777,4852,1190,1778,3969,3970,2872,3716,1779,4489,3717,311,3433,4853,4490,1780,1781,3971,1511,2873,1782,1783,1784,949,1785,1786,4491,3434,3236,312,3237,1512,950,951,4854,2874,4365,4492,45,4855,4856,4366,1513,313,4857,3972,1382,1787,5473,3973,1514,2625,46,668,669,4858,314,4493,1788,315,3974,1789,4859,3975,3976,5474,3435,1790,952,1791,953,1792,5372,3436,316,954,5475,670,955,1793,671,3977,317,2626,2875,4860,3978,4861,1794,2876,2877,5,2878,3979,3718,1795,2879,4862,2627,1383,2628,2629,2630,4367,956,3238,2459,5373,4863,4494,4495,1796,3239,318,3437,2460,2880,4496,2881,3438,3719,2631,1797,3439,2632,2461,3440,2462,2463,1191,1384,1798,3240,126,957,2633,958,5476,319,1799,3980,959,1192,1800,1801,47,1802,3441,1385,1515,672,3981,4864,4497,1803,2634,1804,1805,3982,4865,2635,2882,2883,2884,1806,1386,5477,320,3983,1807,1808,4498,960,4866,3442,5374,1809,1810,1811,825,4867,1812,1813,961,5478,1814,1815,1816,4868,4869,3984,3985,1516,5479,3986,48,2885,4870,1387,321,1817,1818,2464,3443,3987,3444,1819,322,3988,1193,3989,1820,1821,826,3445,4499,1822,3990,2636,1823,1824,1825,827,1826,1827,3241,1517,2886,4871,1828,1518,2887,3991,4500,3992,3720,2888,962,4872,4873,3617,2637,5480,4874,1194,3618,1829,4875,828,963,964,161,1519,4876,2465,3993,3446,4877,3447,4878,323,1830,2638,4879,4880,4881,4882,3994,3721,324,3995,2889,2890,1831,4883,1832,3619,3996,1833,325,4501,1834,2891,3997,3998,162,6,3722,3999,4000,673,326,4502,4001,4002,4003,4503,1835,3242,4004,1836,1837,2639,4005,2892,3448,5481,1195,2893,4368,1838,3723,1839,4884,4885,327,4006,4007,5375,4008,4009,1840,4886,1196,4010,4887,1841,49,1842,965,4888,1843,4011,328,4889,4012,1844,329,674,1845,1846,3724,3243,2640,4013,966,1847,1848,675,2466,2894,4014,4890,3449,330,5482,1520,2895,4015,4504,4016,967,2896,4017,7,331,332,50,3244,5376,1197,1849,3725,1850,1851,4018,51,1388,2897,2898,1852,3245,1198,3726,4891,4892,4893,4894,127,3246,1853,1854,2899,1521,5483,1389,333,5484,334,968,52,2900,4505,4895,2901,3727,4896,3247,4019,969,3450,2902,3248,335,2467,3451,1855,2903,3452,4020,4506,2904,4897,4898,163,4021,1856,4022,970,1199,2905,336,4507,971,1857,5485,4023,676,4508,677,1858,1200,4024,678,1201,1859,2906,2907,4509,4899,3453,2908,3454,1860,2909,3728,1861,3455,4900,1862,3456,1863,4901,679,4025,1864,1865,1866,2641,3249,5377,4510,1867,1868,3457,1869,1870,3729,829,1871,4902,2642,4903,1872,3730,4511,3250,972,1873,337,3251,5378,4904,4026,4512,2468,4027,4513,4514,4905,1390,4028,338,4906,3458,4029,1391,2910,5379,4907,680,4030,339,4908,4031,3459,53,4032,1874,4909,340,1392,1522,3252,4033,1202,2911,1875,3253,1876,973,974,975,2469,976,3731,977,5486,978,5487,979,2912,2913,1877,1203,341,1878,1879,980,1204,4515,3732,1205,1206,4369,830,1207,342,1208,1209,1880,681,1210,5380,1211,4034,4035,4036,2914,3254,682,683,1881,4516,3255,4037,4517,684,3733,1882,4038,4518,831,3460,4039,4910,4911,2915,4912,2916,685,164,4370,343,3734,2917,344,1883,1884,4913,4914,3620,2918,981,4040,2919,4915,2643,4916,2920,4917,1885,4519,686,1886,5488,982,687,4520,1887,1888,4918,4041,983,2921,4919,1393,832,2922,2923,1889,4920,4921,345,4922,2924,1890,4923,4924,3461,984,4925,4521,4926,4522,4927,1891,1523,1892,1212,1893,1394,1894,1895,2644,2645,2470,5489,4928,4042,985,1896,346,4929,4043,4523,4044,688,986,987,4930,2925,689,4045,4931,3462,4046,165,4047,1213,4932,988,4933,347,1897,4934,3256,2926,4048,690,4935,54,833,2927,1898,1899,4049,1900,4524,691,2646,348,349,4525,350,351,692,3257,352,353,2928,354,4936,1901,1902,834,4050,3258,4526,355,356,4051,4937,357,1903,4052,358,4938,835,359,1904,1905,4939,360,693,4527,1906,2929,1214,4940,361,694,836,3735,4941,55,362,4942,2647,4943,1907,1215,1216,2471,2472,3259,4944,1908,363,56,4053,3621,364,4945,2930,3260,1909,1524,695,2931,1910,4054,4946,5381,3261,3463,4947,4948,365,4528,1911,4055,2648,4529,2932,4056,1912,4530,2933,4531,4057,1217,2934,989,2935,3262,1913,1914,4532,4949,696,4058,4950,1915,2936,4951,990,5382,1395,2649,1916,3263,4059,366,2473,57,1917,1918,3464,991,1919,1525,4952,4533,1920,992,1921,3736,697,1922,698,4953,4060,367,4954,4955,1923,368,4956,4534,369,2937,993,1396,3465,4061,166,2474,3264,994,2938,4535,4957,699,4958,4536,3265,3737,700,5490,1924,4537,370,701,4409,2939,4959,4538,4062,1925,371,372,167,4539,4960,4961,373,374,2940,4540,702,375,2941,4541,2475,837,3466,995,4542,4063,2650,5383,5384,376,4962,377,996,5385,1926,1927,1928,3622,378,5491,1929,1930,379,168,3266,4064,380,381,382,383,838,384,3623,2942,1931,997,998,5492,4963,3267,703,3467,4543,1218,1932,2943,704,2476,999,3738,4544,4964,4965,385,1933,386,3624,387,1934,169,1935,388,1936,2944,389,2945,3268,1937,1938,1939,390,4966,1940,1397,391,1941,1942,4967,3625,1000,1943,705,392,393,394,1944,4968,1219,2946,4545,839,2947,3626,3269,395,4969,1945,4970,4971,396,706,4972,170,4546,1001,4973,5493,3270,397,707,4547,4974,1526,5494,2651,4975,5386,2652,4371,4065,4976,4977,1002,4978,398,4066,1527,3271,840,399,4979,708,4980,1003,4067,3627,1946,4981,4068,400,4982,709,2653,3739,1947,1398,128,1004,3468,1948,2948,1949,1950,1220,1399,4983,4984,401,402,4985,403,4986,404,405,1951,1952,1005,1953,4987,2477,4548,1954,1955,4988,406,841,2949,2950,2951,2952,1528,1006,4069,4070,3272,4549,407,4989,2953,4071,4990,1956,3740,408,2654,58,2478,4991,2954,4992,1400,1957,4550,409,3469,1958,59,4072,2479,4993,1959,4073,2955,410,1960,4074,411,842,710,4075,2956,711,712,412,4994,713,4551,1961,3470,4995,4996,1962,1963,1007,2957,413,3741,4997,3742,1401,2958,1964,3743,1965,60,5387,3628,3744,2959,5388,1966,1529,171,2960,3273,4076,1008,4552,1530,61,714,1531,2961,3745,3746,3471,3747,2962,4553,4998,4077,4999,4372,1009,2963,3274,1532,715,1221,3275,3472,5000,5495,1010,1402,1967,1968,1222,1969,62,414,1970,1971,1972,415,2655,5001,843,3473,1973,2964,1011,4373,716,416,417,4554,1974,1975,5002,3276,3748,3474,3749,418,1223,1976,844,2656,1977,5003,1978,63,3277,3475,2965,2657,3476,4078,4555,1979,8,4556,5004,3750,3477,1980,1981,1224,1982,1012,1403,2658,5496,1983,2659,419,717,3478,718,3278,420,3751,1404,1984,3479,4079,5005,5006,1225,2660,64,3752,5007,2966,65,5008,3279,4557,5009,5010,1985,2967,3280,3480,2661,2662,172,1986,1405,2480,1406,421,1013,2968,422,423,173,1533,1987,2969,174,4558,1988,1534,424,1989,5389,4559,1226,1227,1228,1229,2663,3481,4080,3753,66,5497,1990,2664,3281,3754,3482,3755,3483,3282,1230,3283,3484,3485,5498,3284,1991,4081,1992,1993,1994,3285,1231,3756,425,3757,1014,1995,2665,4082,4083,5011,3486,4560,1535,426,3629,4084,5499,4085,4561,1232,427,428,3286,429,3758,3759,1996,430,1997,1407,1998,3487,2970,431,845,1999,2971,129,5012,5390,2972,2000,2666,4562,432,4563,5500,5013,2001,719,4086,5014,2002,4564,5015,2003,433,5016,4565,2004,1015,2973,4087,2005,434,2974,1233,2006,5017,2007,3287,67,2481,720,2975,5018,4566,4088,4089,846,5019,2667,435,5501,2976,2977,2668,2978,2008,4567,5020,1234,5021,5022,1408,5023,2669,5024,1409,3760,5025,3488,1235,436,3761,2009,2010,4568,2979,5026,2011,2980,5027,2981,5028,2012,4569,1016,3489,5502,3630,3762,437,4090,5391,130,3288,438,5029,3763,5030,439,5031,68,2013,4091,4374,2014,3289,4570,3631,440,721,3490,441,2015,2670,2482,442,4571,2483,1236,5032,3632,443,444,5033,5034,1017,4572,69,3764,4573,2016,445,446,5392,5393,2982,2671,2672,1018,2983,2017,4092,175,2673,176,3290,177,9,2984,2985,2986,5035,2987,2018,3633,2988,2019,2020,178,3491,2989,10,4093,447,448,2021,847,4094,2022,70,1019,179,2484,5036,1237,5037,4574,1536,2485,722,449,71,450,3291,1238,723,1239,2486,5038,4095,848,4096,451,72,4575,2023,2674,1410,4097,3765,452,724,3492,3493,2990,73,849,11,4576,2675,2024,2991,2992,2025,4098,4099,5503,5039,74,3634,2026,850,2993,2994,5040,2995,2996,5041,2027,2997,2998,2028,2487,2676,2029,2999,2030,4100,3000,2031,725,5042,3766,2032,5394,3001,1020,453,726,3494,2677,4577,4101,454,75,1240,2033,5043,2678,5504,3002,2034,2035,2036,2037,2038,3495,455,1241,2679,3003,2039,4102,2680,4103,4104,3004,2040,1242,1243,4578,2041,1021,76,1411,2681,2042,5044,3005,180,1022,5505,727,3767,4105,131,2043,456,3006,2488,2044,4579,2489,3635,2045,5045,3007,2046,5046,728,5047,2047,3636,77,3768,3496,457,3497,3637,5048,458,729,1244,730,3498,1023,851,1024,78,4106,2048,2049,1025,5049,4375,5050,2050,5051,3638,5506,1245,3008,2051,4107,2052,731,1537,1246,3292,5052,459,5507,460,4376,5053,3009,5054,1412,5055,2053,4580,1247,3010,732,2490,5056,4581,2054,2055,2682,5057,5058,5059,1026,5395,2491,2492,733,5060,1248,5061,4582,5062,2056,3499,3500,2057,734,2683,2058,852,3769,4108,2493,3770,1027,2059,5396,3501,5063,4109,5064,5065,2060,5066,2061,4110,4583,2062,4584,5067,3771,5508,2063,2684,5068,4377,461,2064,5509,2065,2685,5069,79,4111,1249,2066,1028,2067,1029,1030,735,2068,736,3293,3011,3294,4112,462,3012,737,1031,4113,5070,1032,3502,4585,2069,463,3503,2070,4586,4114,4115,1250,464,5071,1033,3772,4116,5072,1034,2494,4410,738,465,4117,466,853,4118,4119,739,2686,467,468,1035,1538,2071,3013,469,854,470,855,2072,5397,80,3504,5510,471,5073,472,2073,1036,2074,2075,5074,2076,4120,2077,5075,3773,2078,2079,3639,5511,5076,2687,4587,1539,473,5512,3295,3505,5077,2080,2688,3506,1037,5398,2081,1038,5078,181,5079,4121,474,3640,1251,2082,1540,5080,1039,3774,3641,1413,4122,475,4411,1414,5399,5400,5401,3014,5402,3507,1415,5403,3508,5081,3015,4123,1541,1040,3016,1542,4124,1041,3017,1416,4125,2083,4126,1417,4378,4127,5082,476,1418,5083,4128,3018,5084,1252,1042,3775,2084,4588,3019,2495,3020,4129,5085,477,3021,2689,3642,1043,5086,1419,5087,4130,478,3643,1044,5088,1253,2496,4589,479,1420,3022,2085,3023,5089,4379,1421,1422,2086,1423,1424,1425,5090,1426,3024,740,2690,5513,1254,182,4131,4132,2691,4133,2087,2088,4134,3025,4135,480,2089,1045,4136,5514,741,3026,1427,3509,4137,3027,2090,481,3028,2497,4590,1428,2091,4380,856,1046,4591,482,1429,5091,5515,183,5516,184,4138,1047,4139,2092,1048,4140,483,4592,5092,1430,4381,1543,3029,5517,81,4141,1431,742,2093,3510,1049,2498,2499,1432,3511,1433,4142,484,4143,2094,5093,2500,743,5094,3512,2501,132,2095,5095,2692,1255,82,3776,83,3513,84,2096,5096,2097,3296,1256,485,2693,2098,5518,486,2099,85,2100,5097,2101,5098,5099,2502,2102,1050,5100,4593,3297,3298,744,3030,5101,5102,4144,5103,4594,2503,487,3299,2504,5104,3031,4595,86,2103,3777,2104,2105,4382,2694,4596,5105,1051,2106,3032,5106,488,1052,5107,2505,745,4412,746,5404,1257,747,748,1053,2107,3514,2108,3515,2109,4597,3033,4145,2110,4598,2111,2112,3516,87,5108,1054,2506,749,4599,2113,4600,750,3300,4146,5109,3034,5519,489,3035,4601,5110,4147,3517,88,3518,1258,5520,490,1055,5521,3301,5522,1056,1057,3036,5111,4148,4602,2114,3037,1058,4149,857,3302,5112,4150,89,2115,4603,3519,2116,3644,2117,751,2507,2118,5113,4151,3645,1259,5114,752,4604,5115,1544,3038,4152,5523,2119,753,491,754,3778,5524,3039,3040,1545,1059,1434,5116,3041,5117,3303,1435,3042,1546,2120,5118,2695,492,3646,3779,2508,1060,3780,5119,4153,4383,3781,90,185,493,91,5120,5121,3520,3521,3304,3782,1260,4154,3783,2121,4155,2122,2123,2124,2696,3784,1261,3522,3305,92,4605,4156,4157,2125,4606,1262,2126,3043,3044,2697,2127,3523,2128,2129,5122,3785,3647,494,2509,5525,3524,3786,3306,186,2130,3045,5123,5124,1263,2698,3307,3525,5125,2131,495,4158,5126,3046,93,4607,1264,2132,4159,3526,496,3047,2133,5127,3308,2134,5128,2135,755,2699,133,2136,2137,2138,3787,2700,5405,1436,3788,2139,5129,497,4160,2701,2140,4608,5130,5131,1265,5406,5132,2141,5526,498,3789,858,5133,1266,1547,3527,3528,2142,4161,2702,2143,3790,5527,2510,1437,4162,4163,756,1267,5134,3791,94,4609,757,2144,2145,5528,2146,2147,2148,5135,5136,758,1268,2149,4610,1269,3048,3049,3050,1061,5137,2150,4611,3309,3310,4612,3311,1062,3648,95,5138,2703,499,2151,4164,2511,3529,2704,5139,2152,2153,2154,2155,3051,500,96,2705,1063,5140,2706,3792,2707,2156,4384,3530,4385,501,5141,1270,97,502,5142,5529,759,2157,3052,4165,4166,3053,4167,3054,4613,5143,3055,5407,3649,4168,1271,4169,4614,859,503,4170,2158,3531,1272,5144,760,5145,5146,1064,2159,5147,3532,3650,504,3056,5148,2160,5149,5408,2161,5150,2162,2163,98,1065,1273,2164,4171,2165,5151,5152,3057,5530,5153,4172,5154,4615,2166,1066,1067,761,505,3533,506,2708,3058,3059,5155,2167,2709,5531,860,2168,2512,12,1068,3060,507,508,3061,4173,5156,4616,1438,2169,5157,5158,3312,1274,2710,3793,2711,4174,99,2712,2170,5409,5410,509,1439,2171,2172,510,5159,2713,3313,4617,5160,2173,5161,2513,3062,1548,5162,1440,3063,1069,5163,4175,4618,5532,4619,5533,1441,2174,4176,4620,1442,5164,861,2175,2176,511,5165,762,5166,1070,3651,3064,3794,4177,1071,763,2177,2514,1072,3534,13,4178,1443,3535,5534,3065,3066,4621,100,5411,2515,101,3795,1444,1445,1446,5167,5168,2178,1275,134,4179,4180,1549,5535,3652,102,3067,1276,512,4622,4386,4181,3068,14,4182,1073,2179,764,5169,513,5170,765,2180,2181,4183,4623,1447,5171,135,514,3069,5172,2182,4624,5173,5536,2516,3070,2183,2714,3536,5174,2184,2185,5175,2186,5176,4625,3071,515,1277,5177,187,4626,516,1278,2187,862,5537,2188,4184,1279,4387,4627,2189,5178,1280,517,1281,5179,2517,3314,4388,1448,1282,3072,4628,2715,1074,4185,5180,5412,4186,2190,3073,5538,3796,4187,2716,5181,4188,2191,3074,5182,3075,2518,3653,3076,4189,3077,103,3078,3537,518,2717,3654,5183,5184,2192,1449,3079,4190,519,4629,3080,5185,4191,3315,1075,3655,3081,766,2718,3316,520,767,768,769,770,3797,3798,521,5186,3082,5187,3083,3084,4630,1283,2193,2194,3085,3086,3317,2195,5539,771,2519,5188,3538,4192,2196,3539,5189,5190,5191,4193,522,2719,3087,772,3656,2197,3088,1450,3089,2198,2199,5192,4194,523,1284,2720,524,2721,5413,525,2722,2200,5540,3799,3318,526,3800,2723,2724,2201,3540,3801,5414,1076,1077,1285,1550,5193,527,3541,528,3319,5194,5195,1451,3090,5196,2202,529,3091,5197,5198,5199,5200,5201,2203,1452,3542,5415,5202,5203,5204,2204,3092,863,3093,3657,3094,15,1453,3095,3096,1551,2205,3658,5205,4389,5541,4631,3659,3660,5206,530,3661,531,4632,3802,4633,532,2206,4634,2207,5542,4635,4195,2208,3320,4636,4196,5207,3543,104,2209,2520,4637,1552,3097,2210,864,2211,4197,2212,2213,2214,2215,188,1078,533,4638,5543,2725,1079,1553,2216,5208,4198,4639,2217,5209,4199,1554,2218,4640,4200,2219,534,3803,16,4201,3098,4202,4390,2220,4641,3099,4203,4204,1454,3100,2521,1455,4205,4413,5210,1286,2221,5416,3101,4206,1456,5211,105,2222,5212,1080,2223,5213,2522,773,535,3804,2224,3102,5214,2225,774,2226,4207,5215,3321,4208,5216,5217,5218,4642,2726,3322,5417,2727,3103,3323,2227,536,2523,775,5219,3324,4643,5220,5221,2228,5222,1457,3104,4209,3105,5223,4644,537,4210,4211,2524,1287,5544,4212,1081,5545,5224,4645,3325,4213,5225,5226,3106,538,2229,5227,1082,2230,2231,2525,4214,2232,5228,539,1458,2728,4646,3107,4215,5229,4216,2729,3326,3805,540,3327,5230,5231,541,5232,1083,2233,3108,2234,2526,3328,2235,3544,5233,4217,1459,3545,2236,5234,3109,1084,2237,5546,5235,3329,3546,1288,5236,1289,2730,3110,4647,1085,2238,542,1290,2731,3111,1086,5237,3112,189,3113,2527,2239,865,3114,5238,3547,543,1291,2240,2732,4391,5418,106,2528,1292,2241,4218,3806,4219,3330,5239,544,2529,2242,866,3331,4220,3115,2530,2243,2244,5547,3662,3116,5240,3117,776,1293,1294,2733,5241,2245,545,2246,2247,2248,1087,2249,1088,1555,5242,2250,5548,1460,4221,2251,1089,4648,5419,5243,3548,17,4649,5549,5244,867,2734,4222,1090,3118,5550,546,1461,3332,4650,1091,3119,4651,5551,2252,4223,547,136,548,4224,5245,2253,2254,2735,5246,2255,777,2531,778,2256,2257,107,3120,2258,2259,1295,3807,108,2260,3549,2261,5420,3808,2736,2262,549,2532,2533,4225,4652,1462,550,4653,5421,1296,5247,2737,5248,4226,3809,5249,1092,4227,3121,4228,1093,551,1463,3550,3663,5250,2263,5251,2264,3122,1094,2265,190,2266,2267,5252,1464,2268,4229,3123,5253,4230,2269,2270,3124,2534,1297,3551,4231,4232,552,5254,4233,2271,3125,3552,5255,5256,2272,779,1298,3333,2738,1299,2739,2273,3810,5257,4654,5552,3811,3334,4655,1300,5258,4656,4234,109,2274,3553,2535,5259,3335,4657,5260,3126,5422,4658,553,554,1095,2740,4659,5423,2275,2536,1301,2537,2741,1302,868,2276,4235,555,4392,556,1303,2277,1465,557,3554,5553,2538,3812,3664,2278,2742,5261,5424,4236,3555,1096,3665,2279,4237,2280,1304,558,2281,4393,1305,3813,2539,3556,4660,559,4238,191,869,1556,2282,2283,2540,2284,3666,2285,780,3814,3557,2286,3558,2287,2288,2289,560,2290,4239,3127,3128,3336,1306,4661,2291,1097,4414,3667,5262,3559,3560,2292,2293,1098,2541,2294,3561,4240,3562,5263,2295,5264,3668,2542,2296,2543,3563,3129,2743,1307,4662,3130,781,2297,2298,4663,2299,2300,1308,2301,5265,3564,4241,2744,3815,1309,4664,2745,3131,1310,2302,2303,4665,5266,2304,3337,4242,3132,3133,3134,4666,2305,5267,3135,3338,2746,110,2306,2307,111,2308,561,4243,3136,2747,2748,3816,2749,2750,1311,3669,2309,5268,3339,2751,2752,870,3817,4667,4668,2310,3565,3340,2311,4244,4245,4246,562,2312,2313,4247,4248,3566,3567,1466,1467,5269,5270,2753,3818,4249,3670,1468,4250,1312,5271,2754,3137,1469,2755,3568,4251,2314,3341,5272,4669,3569,4252,4670,1313,1099,782,3570,112,1314,4415,1100,5273,4253,2756,3138,5274,4254,4255,4671,4256,871,1315,3139,3819,5275,3571,4672,563,4257,2757,5425,2315,1101,3572,3820,2544,4394,3140,4673,1102,3573,5554,113,114,4258,1103,5276,4259,192,3821,3822,5277,1316,3671,1470,4260,2316,4261,4674,4262,3141,3142,3143,3574,2317,4263,5278,1317,2318,3823,1318,1319,3575,1320,2319,5279,2320,872,5555,115,5280,3144,2321,2545,5281,2322,2758,3672,2323,4264,2324,2325,2326,564,2327,2328,5556,193,2759,4265,1104,5282,2329,2330,3145,3824,2331,4266,4267,5557,4268,4269,3825,5283,2332,2760,4270,1321,3342,2761,565,1471,4271,3146,2333,2546,3673,4272,3674,3147,4273,5284,2334,5285,2335,566,116,1322,567,3148,4675,568,4676,569,4677,5286,3576,570,3577,4274,4275,4276,4277,1557,2336,18,1323,2337,1105,2338,3826,2339,3827,19,2340,2547,1324,2341,783,117,784,4278,3149,571,2342,2343,2344,4279,572,4280,2345,4395,4281,2346,3675,873,4678,5287,2347,2762,3828,2763,2348,3829,3830,137,573,2349,2350,574,2764,5288,3831,1472,575,2765,3343,5289,2351,1325,1106,2352,3150,2353,2766,576,3832,3833,3344,2354,577,3151,3345,3152,4282,4283,2767,5290,5291,4284,2355,1558,2356,4285,3834,5292,4679,1559,3578,3676,1107,5558,4286,2357,5293,194,2358,5426,2359,3579,578,1108,2360,3580,4287,1473,3153,3346,5427,1109,579,580,1326,3835,5559,581,4288,2768,785,2361,5294,3581,2769,2770,4289,2362,3347,786,4680,1560,874,5295,1474,2771,2548,2772,582,5560,1327,1328,5296,4681,3154,5297,2773,3677,3348,3582,5298,5299,4290,1475,5300,195,5301,3349,5302,5561,583,3836,2363,787,3350,3351,5303,2774,1561,5304,5562,5305,2549,4682,2364,5563,3837,5306,5564,3352,3155,5307,3156,788,3583,5308,3838,4683,1476,3678,584,118,3584,585,586,2365,196,3157,4291,4292,587,2775,4293,2366,3158,2367,5309,588,5310,1477,4294,2368,5311,1110,119,4295,5312,3353,5313,5314,4296,1562,5315,20,789,138,5316,2369,1329,5317,790,5318,2776,4297,197,2777,589,3159,2370,4396,791,5319,3160,5428,3839,3840,4298,2778,590,5320,591,2371,592,120,1563,3585,1111,3679,3354,1112,2550,3161,4299,593,3355,1478,3162,3163,5321,2551,1479,4300,4397,792,3164,3841,3842,5322,4684,4685,3165,3356,3843,4686,1330,4687,4688,5323,1331,2372,4301,2373,4302,2374,5429,5565,5566,2375,2376,2377,3166,5430,3167,2378,2552,198,3357,1480,4303,5324,4304,5325,3844,5326,2553,3358,121,2554,793,3680,4305,4306,594,5327,4307,4689,3168,4308,2379,4309,4310,4311,5328,1564,2380,4312,4313,2381,1113,3681,4690,4691,4692,1114,3359,4314,2779,3360,4315,3845,1332,1115,4693,4694,595,2555,4316,2556,1333,5329,2382,4695,4317,3169,3170,1334,5330,2383,3361,4318,4319,4320,4321,3362,3171,5331,5567,5568,1335,1336,5332,2384,5333,4322,794,1116,1117,3172,4696,2385,1337,199,596,2386,2387,597,598,795,2388,5334,599,5335,2389,2390,5336,3173,4323,5337,600,4416,1118,2780,2557,796,3846,5431,601,2391,2781,797,3174,602,2392,3586,4324,3175,2393,4697,1481,122,5338,3176,4325,3847,3177,603,5339,1338,5340,1119,1120,2394,2558,4698,798,2395,200,604,3587,2396,201,4326,799,4398,4699,5341,4700,1121,605,4327,1482,4399,4400,4328,4329,4330,606,3682,3588,607,5342,5343,5344,1122,4331,4701,4702,5345,2397,875,2398,4703,1339,2399,5346,5347,2400,1123,2401,800,3683,2782,3848,801,3589,2402,608,609,1483,3590,610,5348,611,2403,3684,2404,4332,876,3849,3178,3363,1484,612,3850,4333,5349,3179,3591,4334,3364,2405,3180,613,2406,2407,2408,3365,3366,2409,4335,4336,4337,877,1340,1124,3367,4338,1565,1125,123,2410,3851,802,4339,4704,4705,2411,2783,2559,1485,1126,3852,4340,4341,4342,3592,4343,1341,878,1127,1486,879,880,4401,5350,5351,2412,2413,2414,2415,3181,2416,2560,4344,5352,4345,4346,2784,4706,881,5353,614,4347,3368,139,1342,2561,3182,1343,2417,3685,5354,5355,615,3593,5569,616,2418,3183,617,4348,4707,5570,3184,4349,4708,21,4709,4710,3369,2562,618,2785,5356,1344,4711]} diff --git a/spec/bridge/source/get-municipalities.ts b/spec/bridge/source/get-municipalities.ts new file mode 100644 index 000000000..945bbe704 --- /dev/null +++ b/spec/bridge/source/get-municipalities.ts @@ -0,0 +1,110 @@ +/** + * Brazilian municipalities, written once. + */ +import { type Dataset, dataAll, dataRows, dataset } from "./_std.ts"; + +/** + * The two letter code of a Brazilian state. Checked against the dataset by `data/build.ts`, so + * the union and the table can never drift apart. + */ +export type StateCode = + | "AC" + | "AL" + | "AP" + | "AM" + | "BA" + | "CE" + | "DF" + | "ES" + | "GO" + | "MA" + | "MT" + | "MS" + | "MG" + | "PA" + | "PB" + | "PR" + | "PE" + | "PI" + | "RJ" + | "RN" + | "RS" + | "RO" + | "RR" + | "SC" + | "SP" + | "SE" + | "TO"; + +/** One Brazilian municipality, as the IBGE publishes it. */ +export type Municipality = { + /** The 7-digit IBGE municipality code. */ + code: string; + /** The municipality name. */ + name: string; + /** The two-letter code of the state the municipality belongs to. */ + stateCode: StateCode; +}; + +/** + * The municipalities table: `[stateCode, name, code]` per row, grouped by state, with the + * combined pt-BR order baked in at build time. + */ +const MUNICIPALITIES: Dataset = dataset("get-municipalities"); + +/** + * Reads one dataset row as a municipality. + * + * @param {string[]} row - The `[stateCode, name, code]` row. + * @returns {Municipality} The municipality. + */ +const rowToMunicipality = (row: string[]): Municipality => ({ + code: row[2], + name: row[1], + // The dataset holds plain strings; `data/build.ts` is what keeps the closed set true. + stateCode: row[0] as StateCode, +}); + +/** + * Returns Brazilian municipalities published by the IBGE, optionally filtered by state. + * + * If `stateCode` is provided, only municipalities of that state are returned. If it is + * omitted, every municipality of every state is returned, sorted with `localeCompare` in the + * "pt-BR" locale so accented names land where a Brazilian reader expects them. Every per-state + * list is sorted the same way. + * + * Only an omitted (or `undefined`) `stateCode` asks for the full list: any other value that is + * not a known state code, `null` and `""` included, returns `[]`. + * + * The state code is matched exactly, case included: `getMunicipalities("sp")` returns `[]` where + * `getMunicipalities("SP")` returns the 645 São Paulo municipalities. + * + * @param {StateCode} [stateCode] - The two letter code of the Brazilian state to filter by. + * @returns {Municipality[]} A fresh array of fresh `Municipality` objects. Empty when + * `stateCode` is not a known state. + * + * @example + * ```typescript + * getMunicipalities("SP")[0]; // { code: "3500105", name: "Adamantina", stateCode: "SP" } + * getMunicipalities().length; // every municipality of every state + * getMunicipalities("ZZ"); // [] + * getMunicipalities("sp"); // [] (the state code is case-sensitive here) + * getMunicipalities(null); // [] (only an omitted state code asks for the full list) + * ``` + * + * @see Official: https://servicodados.ibge.gov.br/api/docs/localidades + */ +export const getMunicipalities = (stateCode?: StateCode): Municipality[] => { + const municipalities: Municipality[] = []; + let rows = dataAll(MUNICIPALITIES); + + if (stateCode !== undefined) { + rows = dataRows(MUNICIPALITIES, stateCode); + } + + for (const row of rows) { + municipalities.push(rowToMunicipality(row)); + } + + return municipalities; +}; From d6965d82c71430114113dd0aa3c479c8d15f3362 Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 21 Sep 2026 11:49:36 +0000 Subject: [PATCH 12/13] build(spec): commit the compiler's output so the generated code can be read MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `spec/bridge/out` was ignored, which meant the central claim — that the compiler emits code a Go or Rust maintainer would accept — could only be checked by running it. The output is now committed: 64 files, seven targets and the C ABI, every one of them headed `DO NOT EDIT` and rewritten by `node compiler/cli.ts`. What the targets' own toolchains build from it stays ignored, since those are binaries and caches that `conformance/run-all.sh` recreates: `target/`, `classes/`, `obj/`, `bin/`, `__pycache__/`, the Rust lockfile and the compiled C driver. The generated tree is excluded from the linter for the same reason it was already excluded from the formatter: linting emitted code is linting the emitters at one remove, and the emitters are linted directly. `README.md` gains a short index of which files are worth opening, because seven copies of the baked municipality table are 85% of the bytes and none of the interest. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01UX1gTGeMTyoXQyr1qUoQKd --- spec/bridge/.gitignore | 18 +- spec/bridge/README.md | 26 + spec/bridge/conformance/verify-typescript.sh | 4 + spec/bridge/out/csharp/Bridge.csproj | 12 + spec/bridge/out/csharp/Conformance.cs | 280 + spec/bridge/out/csharp/FormatCnpjUtility.cs | 121 + .../out/csharp/GetAddressInfoByCepUtility.cs | 248 + .../out/csharp/GetMunicipalitiesUtility.cs | 5860 ++++++++ spec/bridge/out/csharp/IsValidCnpjUtility.cs | 145 + spec/bridge/out/csharp/Runtime.cs | 526 + spec/bridge/out/go/conformance/main.go | 346 + spec/bridge/out/go/format_cnpj/format_cnpj.go | 89 + .../get_address_info_by_cep.go | 193 + .../get_municipalities/get_municipalities.go | 5662 ++++++++ spec/bridge/out/go/go.mod | 3 + .../out/go/is_valid_cnpj/is_valid_cnpj.go | 112 + spec/bridge/out/go/runtime/runtime.go | 465 + spec/bridge/out/java/AddressInfo.java | 25 + spec/bridge/out/java/CepProviderFailure.java | 6 + spec/bridge/out/java/Conformance.java | 266 + spec/bridge/out/java/FormatCnpj.java | 84 + spec/bridge/out/java/FormatCnpjOptions.java | 11 + spec/bridge/out/java/GetAddressInfoByCep.java | 145 + .../out/java/GetAddressInfoByCepError.java | 6 + .../GetAddressInfoByCepNotFoundError.java | 6 + .../out/java/GetAddressInfoByCepOptions.java | 5 + .../java/GetAddressInfoByCepServiceError.java | 6 + .../GetAddressInfoByCepValidationError.java | 6 + spec/bridge/out/java/GetMunicipalities.java | 11419 ++++++++++++++++ spec/bridge/out/java/IsValidCnpj.java | 115 + spec/bridge/out/java/IsValidCnpjOptions.java | 5 + spec/bridge/out/java/Municipality.java | 17 + spec/bridge/out/java/Runtime.java | 617 + .../out/python/brutils_bridge/__init__.py | 6 + .../out/python/brutils_bridge/format_cnpj.py | 110 + .../brutils_bridge/get_address_info_by_cep.py | 191 + .../brutils_bridge/get_municipalities.py | 5692 ++++++++ .../python/brutils_bridge/is_valid_cnpj.py | 136 + .../out/python/brutils_bridge/runtime.py | 322 + spec/bridge/out/python/conformance.py | 223 + spec/bridge/out/ruby/conformance.rb | 218 + .../lib/brazilian_utils_bridge/format_cnpj.rb | 81 + .../get_address_info_by_cep.rb | 156 + .../get_municipalities.rb | 5659 ++++++++ .../brazilian_utils_bridge/is_valid_cnpj.rb | 112 + .../lib/brazilian_utils_bridge/runtime.rb | 287 + spec/bridge/out/rust/Cargo.toml | 14 + spec/bridge/out/rust/conformance_cabi.c | 226 + spec/bridge/out/rust/include/format_cnpj.h | 28 + spec/bridge/out/rust/include/is_valid_cnpj.h | 28 + spec/bridge/out/rust/src/bin/conformance.rs | 263 + spec/bridge/out/rust/src/cabi_format_cnpj.rs | 35 + .../bridge/out/rust/src/cabi_is_valid_cnpj.rs | 23 + spec/bridge/out/rust/src/format_cnpj.rs | 89 + .../out/rust/src/get_address_info_by_cep.rs | 194 + .../bridge/out/rust/src/get_municipalities.rs | 5668 ++++++++ spec/bridge/out/rust/src/is_valid_cnpj.rs | 112 + spec/bridge/out/rust/src/lib.rs | 13 + spec/bridge/out/rust/src/runtime.rs | 405 + .../bridge/out/typescript/_bridge/_runtime.ts | 458 + .../out/typescript/_bridge/format-cnpj.ts | 105 + .../_bridge/get-address-info-by-cep.ts | 252 + .../typescript/_bridge/get-municipalities.ts | 5713 ++++++++ .../out/typescript/_bridge/is-valid-cnpj.ts | 142 + spec/bridge/out/typescript/conformance.ts | 219 + .../out/typescript/format-cnpj/format-cnpj.ts | 2 + .../get-address-info-by-cep.ts | 2 + .../get-municipalities/get-municipalities.ts | 2 + .../typescript/is-valid-cnpj/is-valid-cnpj.ts | 2 + vite.config.ts | 13 +- 70 files changed, 54046 insertions(+), 4 deletions(-) create mode 100644 spec/bridge/out/csharp/Bridge.csproj create mode 100644 spec/bridge/out/csharp/Conformance.cs create mode 100644 spec/bridge/out/csharp/FormatCnpjUtility.cs create mode 100644 spec/bridge/out/csharp/GetAddressInfoByCepUtility.cs create mode 100644 spec/bridge/out/csharp/GetMunicipalitiesUtility.cs create mode 100644 spec/bridge/out/csharp/IsValidCnpjUtility.cs create mode 100644 spec/bridge/out/csharp/Runtime.cs create mode 100644 spec/bridge/out/go/conformance/main.go create mode 100644 spec/bridge/out/go/format_cnpj/format_cnpj.go create mode 100644 spec/bridge/out/go/get_address_info_by_cep/get_address_info_by_cep.go create mode 100644 spec/bridge/out/go/get_municipalities/get_municipalities.go create mode 100644 spec/bridge/out/go/go.mod create mode 100644 spec/bridge/out/go/is_valid_cnpj/is_valid_cnpj.go create mode 100644 spec/bridge/out/go/runtime/runtime.go create mode 100644 spec/bridge/out/java/AddressInfo.java create mode 100644 spec/bridge/out/java/CepProviderFailure.java create mode 100644 spec/bridge/out/java/Conformance.java create mode 100644 spec/bridge/out/java/FormatCnpj.java create mode 100644 spec/bridge/out/java/FormatCnpjOptions.java create mode 100644 spec/bridge/out/java/GetAddressInfoByCep.java create mode 100644 spec/bridge/out/java/GetAddressInfoByCepError.java create mode 100644 spec/bridge/out/java/GetAddressInfoByCepNotFoundError.java create mode 100644 spec/bridge/out/java/GetAddressInfoByCepOptions.java create mode 100644 spec/bridge/out/java/GetAddressInfoByCepServiceError.java create mode 100644 spec/bridge/out/java/GetAddressInfoByCepValidationError.java create mode 100644 spec/bridge/out/java/GetMunicipalities.java create mode 100644 spec/bridge/out/java/IsValidCnpj.java create mode 100644 spec/bridge/out/java/IsValidCnpjOptions.java create mode 100644 spec/bridge/out/java/Municipality.java create mode 100644 spec/bridge/out/java/Runtime.java create mode 100644 spec/bridge/out/python/brutils_bridge/__init__.py create mode 100644 spec/bridge/out/python/brutils_bridge/format_cnpj.py create mode 100644 spec/bridge/out/python/brutils_bridge/get_address_info_by_cep.py create mode 100644 spec/bridge/out/python/brutils_bridge/get_municipalities.py create mode 100644 spec/bridge/out/python/brutils_bridge/is_valid_cnpj.py create mode 100644 spec/bridge/out/python/brutils_bridge/runtime.py create mode 100644 spec/bridge/out/python/conformance.py create mode 100644 spec/bridge/out/ruby/conformance.rb create mode 100644 spec/bridge/out/ruby/lib/brazilian_utils_bridge/format_cnpj.rb create mode 100644 spec/bridge/out/ruby/lib/brazilian_utils_bridge/get_address_info_by_cep.rb create mode 100644 spec/bridge/out/ruby/lib/brazilian_utils_bridge/get_municipalities.rb create mode 100644 spec/bridge/out/ruby/lib/brazilian_utils_bridge/is_valid_cnpj.rb create mode 100644 spec/bridge/out/ruby/lib/brazilian_utils_bridge/runtime.rb create mode 100644 spec/bridge/out/rust/Cargo.toml create mode 100644 spec/bridge/out/rust/conformance_cabi.c create mode 100644 spec/bridge/out/rust/include/format_cnpj.h create mode 100644 spec/bridge/out/rust/include/is_valid_cnpj.h create mode 100644 spec/bridge/out/rust/src/bin/conformance.rs create mode 100644 spec/bridge/out/rust/src/cabi_format_cnpj.rs create mode 100644 spec/bridge/out/rust/src/cabi_is_valid_cnpj.rs create mode 100644 spec/bridge/out/rust/src/format_cnpj.rs create mode 100644 spec/bridge/out/rust/src/get_address_info_by_cep.rs create mode 100644 spec/bridge/out/rust/src/get_municipalities.rs create mode 100644 spec/bridge/out/rust/src/is_valid_cnpj.rs create mode 100644 spec/bridge/out/rust/src/lib.rs create mode 100644 spec/bridge/out/rust/src/runtime.rs create mode 100644 spec/bridge/out/typescript/_bridge/_runtime.ts create mode 100644 spec/bridge/out/typescript/_bridge/format-cnpj.ts create mode 100644 spec/bridge/out/typescript/_bridge/get-address-info-by-cep.ts create mode 100644 spec/bridge/out/typescript/_bridge/get-municipalities.ts create mode 100644 spec/bridge/out/typescript/_bridge/is-valid-cnpj.ts create mode 100644 spec/bridge/out/typescript/conformance.ts create mode 100644 spec/bridge/out/typescript/format-cnpj/format-cnpj.ts create mode 100644 spec/bridge/out/typescript/get-address-info-by-cep/get-address-info-by-cep.ts create mode 100644 spec/bridge/out/typescript/get-municipalities/get-municipalities.ts create mode 100644 spec/bridge/out/typescript/is-valid-cnpj/is-valid-cnpj.ts diff --git a/spec/bridge/.gitignore b/spec/bridge/.gitignore index 0ae05c1a6..0bbb9e4ec 100644 --- a/spec/bridge/.gitignore +++ b/spec/bridge/.gitignore @@ -1,6 +1,18 @@ -# Everything under `out/` is generated by `compiler/cli.ts`, and every build tree the targets -# leave behind is generated by their own toolchains. -out/ +# The compiler's output is committed, so the code it writes can be read in review rather than +# taken on trust. `node compiler/cli.ts` and `node conformance/drivers.ts` rewrite it, and +# every file says DO NOT EDIT. +# +# What the targets' own toolchains then build from it is not committed: those are binaries and +# caches, and `conformance/run-all.sh` recreates them. The paths are spelled out per target +# rather than globbed, because `out/rust/src/bin/` is generated source, not a build directory. +out/rust/target/ +out/rust/Cargo.lock +out/rust/conformance_cabi +out/java/classes/ +out/csharp/bin/ +out/csharp/obj/ +out/python/**/__pycache__/ + node_modules/ # The conformance tables are recorded from the package this repository ships, by diff --git a/spec/bridge/README.md b/spec/bridge/README.md index c9263bb70..8244d5e01 100644 --- a/spec/bridge/README.md +++ b/spec/bridge/README.md @@ -153,6 +153,32 @@ be handed it, so nothing is skipped for being inconvenient, and the count is vis | `getAddressInfoByCep` | HTTP, JSON, retries, an error hierarchy, three providers raced | | `getMunicipalities` | 5,571 baked rows, and a pt-BR order no two targets agree on | +## Reading the output + +`out/` is committed. Everything in it is written by `node compiler/cli.ts` and says +`DO NOT EDIT` at the top — it is there to be read, because "the compiler emits idiomatic code" +is a claim worth checking rather than believing. What the targets' own toolchains then build +from it (`target/`, `classes/`, `obj/`, `bin/`) is not committed. + +Where to look, shortest first: + +| file | what it shows | +| ------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------- | +| `out/typescript/_bridge/format-cnpj.ts` | 105 lines: the utility, the mask helper it shares, the two character classes it uses — and not one line of `isValidCnpj`, because pruning dropped it | +| `out/typescript/_bridge/is-valid-cnpj.ts` | the other half of that pair: check digits and two compiled patterns, and no mask helper | +| `out/rust/include/*.h` | the C ABI a hand-written binding reads, with the "unset" sentinels spelled out | +| `out/go/get_address_info_by_cep/` | `(T, error)` threaded through every call site, and goroutines with a channel for the provider race | +| `out/rust/src/get_address_info_by_cep.rs` | the same utility as `Result`, with an `mpsc` channel | +| `out/csharp/GetAddressInfoByCepUtility.cs` | the same utility again, `async` all the way down, from source that never says `async` | +| `out/*/…get_municipalities…` | the baked table: ~5,600 lines each, of which the last twenty are the logic | + +Those seven municipality modules are **85% of the committed output**. That is the honest shape +of a utility whose difficulty is a dataset, and it is why the table above says where to skip to. + +Two commands rewrite `out/`, and between them they cover it: `node compiler/cli.ts` clears each +target and re-emits the utilities, and `node conformance/drivers.ts` adds the replay programs. +`bash conformance/run-all.sh` runs both, so a clean checkout and a fresh run agree file for file. + ## Adding a utility Two files, and nothing else changes: diff --git a/spec/bridge/conformance/verify-typescript.sh b/spec/bridge/conformance/verify-typescript.sh index a5d396550..7780a23f8 100644 --- a/spec/bridge/conformance/verify-typescript.sh +++ b/spec/bridge/conformance/verify-typescript.sh @@ -16,6 +16,10 @@ out="${bridge}/out/typescript" restore() { rm -rf "${root}/src/_bridge" git -C "${root}" checkout -- src >/dev/null 2>&1 + # `compiler/cli.ts` clears each target before re-emitting, which drops the replay programs + # that are committed alongside the utilities. Put them back, so running this gate leaves + # `out/` exactly as the repository has it. + node "${bridge}/conformance/drivers.ts" >/dev/null } trap restore EXIT diff --git a/spec/bridge/out/csharp/Bridge.csproj b/spec/bridge/out/csharp/Bridge.csproj new file mode 100644 index 000000000..b98e9edd1 --- /dev/null +++ b/spec/bridge/out/csharp/Bridge.csproj @@ -0,0 +1,12 @@ + + + net8.0 + disable + BrazilianUtilsBridge + BrazilianUtils.Bridge + Exe + + CS0162 + + diff --git a/spec/bridge/out/csharp/Conformance.cs b/spec/bridge/out/csharp/Conformance.cs new file mode 100644 index 000000000..6f35c8a16 --- /dev/null +++ b/spec/bridge/out/csharp/Conformance.cs @@ -0,0 +1,280 @@ +// Code generated by spec/bridge/conformance/drivers.ts. DO NOT EDIT. + +using System; +using System.IO; +using BrazilianUtils.Bridge; + +/// Replays the recorded tables against the generated C#. +public static class Conformance +{ + private const string Target = "csharp"; + + /// One utility's score. + private sealed class Tally + { + public int Passed { get; set; } + + public int Failed { get; set; } + + public int Skipped { get; set; } + } + + /// Reads back the three characters the table format escapes. + private static string Unescape(string value) + { + return value.Replace("\\t", "\t").Replace("\\n", "\n").Replace("\\\\", "\\"); + } + + /// Whether this target can express the call a row describes. + private static bool Runs(string targets) + { + return targets == "*" || Array.IndexOf(targets.Split('|'), Target) >= 0; + } + + /// Keeps a failure message readable when the answer is a five thousand row list. + private static string Cut(string value) + { + return value.Length <= 120 ? value : value.Substring(0, 120); + } + + /// Counts one comparison, and shows the first few that disagree. + private static void Report(string fn, string actual, string expected, Tally counts) + { + if (actual == expected) + { + counts.Passed++; + + return; + } + + counts.Failed++; + + if (counts.Failed <= 3) + { + Console.Error.WriteLine($"FAIL {fn} expected {Cut(expected)} got {Cut(actual)}"); + } + } + + private static string renderGetAddressInfoByCepAddressInfo(AddressInfo value) + { + return value.Cep + "|" + value.State + "|" + value.City + "|" + value.Neighborhood + "|" + value.Street; + } + + private static string renderGetMunicipalitiesMunicipality(Municipality value) + { + return value.Code + "|" + value.Name + "|" + value.StateCode; + } + + private static string renderListGetMunicipalitiesMunicipality(System.Collections.Generic.List items) + { + var out_ = new System.Text.StringBuilder(items.Count.ToString()); + + foreach (var item in items) + { + out_.Append("\n").Append(renderGetMunicipalitiesMunicipality(item)); + } + + return out_.ToString(); + } + + /// Replays what formatCnpj answers. + private static System.Threading.Tasks.Task CheckFormatCnpj() + { + var counts = new Tally(); + + foreach (var line in File.ReadAllText("../../conformance/recorded/format-cnpj.tsv").TrimEnd('\n').Split('\n')) + { + if (line.Length == 0 || line.StartsWith("targets\t")) + { + continue; + } + + var cells = line.Split('\t'); + + if (!Runs(cells[0])) + { + counts.Skipped++; + + continue; + } + + var argument0 = Unescape(cells[1]); + var options = new FormatCnpjOptions(); + var given = false; + + if (cells[3].Length > 0) + { + options.Pad = cells[3] == "1"; + given = true; + } + + if (cells[4].Length > 0) + { + options.Version = long.Parse(cells[4]); + given = true; + } + + if (cells[5].Length > 0) + { + options.Obfuscate = cells[5] == "1"; + given = true; + } + + var actual = FormatCnpjUtility.FormatCnpj(argument0, given ? options : null); + + Report("formatCnpj", actual, Unescape(cells[6]), counts); + } + + return System.Threading.Tasks.Task.FromResult(counts); + } + + /// Replays what getAddressInfoByCep answers. + private static async System.Threading.Tasks.Task CheckGetAddressInfoByCep() + { + var counts = new Tally(); + + foreach (var line in File.ReadAllText("../../conformance/recorded/get-address-info-by-cep.tsv").TrimEnd('\n').Split('\n')) + { + if (line.Length == 0 || line.StartsWith("targets\t")) + { + continue; + } + + var cells = line.Split('\t'); + + if (!Runs(cells[0])) + { + counts.Skipped++; + + continue; + } + + var argument0 = Unescape(cells[1]); + var options = new GetAddressInfoByCepOptions(); + var given = false; + + if (cells[3].Length > 0) + { + options.Providers = cells[3] == "[]" ? new System.Collections.Generic.List() : new System.Collections.Generic.List(cells[3].Split('|')); + given = true; + } + + string actual; + + try + { + actual = renderGetAddressInfoByCepAddressInfo(await GetAddressInfoByCepUtility.GetAddressInfoByCep(argument0, given ? options : null)); + } + catch (Exception error) + { + actual = "!" + error.GetType().Name + "|" + error.Message; + } + + Report("getAddressInfoByCep", actual, Unescape(cells[4]), counts); + } + + return counts; + } + + /// Replays what getMunicipalities answers. + private static System.Threading.Tasks.Task CheckGetMunicipalities() + { + var counts = new Tally(); + + foreach (var line in File.ReadAllText("../../conformance/recorded/get-municipalities.tsv").TrimEnd('\n').Split('\n')) + { + if (line.Length == 0 || line.StartsWith("targets\t")) + { + continue; + } + + var cells = line.Split('\t'); + + if (!Runs(cells[0])) + { + counts.Skipped++; + + continue; + } + + var argument0 = cells[1] == "1" ? Unescape(cells[2]) : null; + + var actual = renderListGetMunicipalitiesMunicipality(GetMunicipalitiesUtility.GetMunicipalities(argument0)); + + Report("getMunicipalities", actual, Unescape(cells[3]), counts); + } + + return System.Threading.Tasks.Task.FromResult(counts); + } + + /// Replays what isValidCnpj answers. + private static System.Threading.Tasks.Task CheckIsValidCnpj() + { + var counts = new Tally(); + + foreach (var line in File.ReadAllText("../../conformance/recorded/is-valid-cnpj.tsv").TrimEnd('\n').Split('\n')) + { + if (line.Length == 0 || line.StartsWith("targets\t")) + { + continue; + } + + var cells = line.Split('\t'); + + if (!Runs(cells[0])) + { + counts.Skipped++; + + continue; + } + + var argument0 = Unescape(cells[1]); + var options = new IsValidCnpjOptions(); + var given = false; + + if (cells[3].Length > 0) + { + options.Version = long.Parse(cells[3]); + given = true; + } + + var actual = (IsValidCnpjUtility.IsValidCnpj(argument0, given ? options : null) ? "true" : "false"); + + Report("isValidCnpj", actual, Unescape(cells[4]), counts); + } + + return System.Threading.Tasks.Task.FromResult(counts); + } + + public static async System.Threading.Tasks.Task Main(string[] args) + { + var failed = 0; + Tally counts; + + counts = await CheckFormatCnpj(); + failed += counts.Failed; + Console.WriteLine( + $"{Target}: formatCnpj {counts.Passed}/{counts.Passed + counts.Failed} matched" + + (counts.Skipped == 0 ? "" : $" ({counts.Skipped} not expressible)")); + + counts = await CheckGetAddressInfoByCep(); + failed += counts.Failed; + Console.WriteLine( + $"{Target}: getAddressInfoByCep {counts.Passed}/{counts.Passed + counts.Failed} matched" + + (counts.Skipped == 0 ? "" : $" ({counts.Skipped} not expressible)")); + + counts = await CheckGetMunicipalities(); + failed += counts.Failed; + Console.WriteLine( + $"{Target}: getMunicipalities {counts.Passed}/{counts.Passed + counts.Failed} matched" + + (counts.Skipped == 0 ? "" : $" ({counts.Skipped} not expressible)")); + + counts = await CheckIsValidCnpj(); + failed += counts.Failed; + Console.WriteLine( + $"{Target}: isValidCnpj {counts.Passed}/{counts.Passed + counts.Failed} matched" + + (counts.Skipped == 0 ? "" : $" ({counts.Skipped} not expressible)")); + + return failed == 0 ? 0 : 1; + } +} diff --git a/spec/bridge/out/csharp/FormatCnpjUtility.cs b/spec/bridge/out/csharp/FormatCnpjUtility.cs new file mode 100644 index 000000000..a05b95c50 --- /dev/null +++ b/spec/bridge/out/csharp/FormatCnpjUtility.cs @@ -0,0 +1,121 @@ +// Code generated from spec/bridge/source/format-cnpj.ts. DO NOT EDIT. + +namespace BrazilianUtils.Bridge +{ + + + /// Options of `formatCnpj`. + public sealed class FormatCnpjOptions + { + /// Whether to left pad the value with zeros up to the number of slots in the pattern (default: `false`). + public bool? Pad { get; set; } + + /// Which CNPJ format to read: `1` numeric only, `2` alphanumeric (default: `1`). + public long? Version { get; set; } + + /// Whether to hide the first 2 digits and the 2 check digits with `*` (default: `false`). + public bool? Obfuscate { get; set; } + } + + /// `formatCnpj`, written once. + public static class FormatCnpjUtility + { + private static readonly int[][] CLASS0 = { new[] { 0x30, 0x39 } }; + private static readonly int[][] CLASS1 = { new[] { 0x30, 0x39 }, new[] { 0x41, 0x5a }, new[] { 0x61, 0x7a } }; + + + + private const string PATTERN = "00.000.000/0000-00"; + private const string OBFUSCATED_PATTERN = "**.000.000/0000-**"; + + + + /// + /// Formats a given CNPJ (Cadastro Nacional da Pessoa Jurídica) value. + /// + public static string FormatCnpj(string @value, FormatCnpjOptions options = null) + { + long optionsVersion = -1L; + if (options != null && options.Version != null) + { + optionsVersion = options.Version.Value; + } + bool optionsObfuscate = false; + if (options != null && options.Obfuscate != null) + { + optionsObfuscate = options.Obfuscate.Value; + } + bool optionsPad = false; + if (options != null && options.Pad != null) + { + optionsPad = options.Pad.Value; + } + if (@value == null) + { + return ""; + } + string text = @value; + string cleaned = Runtime.KeepClass(CLASS0, text); + if ((optionsVersion == 2L)) + { + cleaned = Runtime.KeepClass(CLASS1, text).ToUpperInvariant(); + } + string pattern = PATTERN; + if (optionsObfuscate) + { + pattern = OBFUSCATED_PATTERN; + } + return Layout(cleaned, pattern, optionsPad); + } + + /// + /// Lays a value over a pattern. + /// + public static string Layout(string @value, string pattern, bool pad) + { + long slots = 0L; + for (long index = 0L; index < (long) pattern.Length; index++) + { + if (((Runtime.CodeAt(pattern, index) == 48L) || (Runtime.CodeAt(pattern, index) == 42L))) + { + slots = (slots + 1L); + } + } + string padded = @value; + if (pad) + { + padded = Runtime.PadStart(@value, slots, "0"); + } + string formatted = ""; + long cursor = 0L; + for (long index = 0L; index < (long) pattern.Length; index++) + { + long slot = Runtime.CodeAt(pattern, index); + if (((slot == 48L) || (slot == 42L))) + { + if ((cursor >= (long) padded.Length)) + { + return formatted; + } + if ((slot == 42L)) + { + formatted = (formatted + "*"); + } + else + { + formatted = (formatted + Runtime.Slice(padded, cursor, (cursor + 1L))); + } + cursor = (cursor + 1L); + } + else + { + if ((cursor < (long) padded.Length)) + { + formatted = (formatted + Runtime.Slice(pattern, index, (index + 1L))); + } + } + } + return formatted; + } + } +} diff --git a/spec/bridge/out/csharp/GetAddressInfoByCepUtility.cs b/spec/bridge/out/csharp/GetAddressInfoByCepUtility.cs new file mode 100644 index 000000000..6e3d2ef80 --- /dev/null +++ b/spec/bridge/out/csharp/GetAddressInfoByCepUtility.cs @@ -0,0 +1,248 @@ +// Code generated from spec/bridge/source/get-address-info-by-cep.ts. DO NOT EDIT. + +namespace BrazilianUtils.Bridge +{ + /// Base class of every error `getAddressInfoByCep` rejects with. + public class GetAddressInfoByCepError : System.Exception + { + public GetAddressInfoByCepError(string message) : base(message) + { + } + } + + /// Thrown by `getAddressInfoByCep` when the value given is not a valid CEP. + public class GetAddressInfoByCepValidationError : GetAddressInfoByCepError + { + public GetAddressInfoByCepValidationError(string message) : base(message) + { + } + } + + /// Thrown by `getAddressInfoByCep` when no CEP service knows the CEP. + public class GetAddressInfoByCepNotFoundError : GetAddressInfoByCepError + { + public GetAddressInfoByCepNotFoundError(string message) : base(message) + { + } + } + + /// Thrown by `getAddressInfoByCep` when every CEP service failed to answer. + public class GetAddressInfoByCepServiceError : GetAddressInfoByCepError + { + public GetAddressInfoByCepServiceError(string message) : base(message) + { + } + } + + /// Raised inside a provider that did not answer. Only whether a failure was a not found is looked at when the provider failures are aggregated, so this one never leaves the module. + public class CepProviderFailure : System.Exception + { + public CepProviderFailure(string message) : base(message) + { + } + } + + /// The address `getAddressInfoByCep` returns for a CEP. + public sealed class AddressInfo + { + /// The 8 digit CEP, no mask. + public string Cep { get; set; } + + /// Two letter state code, e.g. "SP". + public string State { get; set; } + + /// City name. + public string City { get; set; } + + /// Neighborhood name, empty when the CEP covers a whole city. + public string Neighborhood { get; set; } + + /// Street name, empty when the CEP covers a whole city. + public string Street { get; set; } + + public AddressInfo(string cep, string state, string city, string neighborhood, string street) + { + Cep = cep; + State = state; + City = city; + Neighborhood = neighborhood; + Street = street; + } + } + + /// Options of `getAddressInfoByCep`. + public sealed class GetAddressInfoByCepOptions + { + /// Which CEP services to race, in the order given (default: `["viacep", "brasilapi"]`; the deprecated `"widenet"` provider is excluded from the default list, but can still be requested explicitly). + public System.Collections.Generic.List Providers { get; set; } + } + + /// Address lookup by CEP, written once. + public static class GetAddressInfoByCepUtility + { + private static readonly int[][] CLASS0 = { new[] { 0x30, 0x39 } }; + + private static readonly PatternStep[] PATTERN_CEP_FORMAT = + { + new PatternStep(CLASS0, 8, 8, false), + }; + + private static readonly System.Collections.Generic.List DEFAULT_PROVIDERS = new System.Collections.Generic.List { "viacep", "brasilapi" }; + private static readonly System.Collections.Generic.List KNOWN_PROVIDERS = new System.Collections.Generic.List { "viacep", "widenet", "brasilapi" }; + private const long BRASIL_API_NOT_FOUND_STATUS = 404L; + private const long HTTP_RETRIES = 2L; + private const long HTTP_RETRY_DELAY_MS = 250L; + + + + /// + /// Reads the address ViaCEP answers with. + /// + /// @see Based on: https://viacep.com.br/ + /// + public static async System.Threading.Tasks.Task FetchViaCep(string cep) + { + HttpResponse response = await Net.HttpGet((("https://viacep.com.br/ws/" + cep) + "/json/"), HTTP_RETRIES, HTTP_RETRY_DELAY_MS); + if (!response.Ok) + { + throw new CepProviderFailure("ViaCEP request failed"); + } + string found = Net.JsonString(response.Body, "cep"); + if ((Net.JsonTruthy(response.Body, "erro") || (found == ""))) + { + throw new GetAddressInfoByCepNotFoundError("CEP n\u00e3o encontrado"); + } + return new AddressInfo(Runtime.KeepClass(CLASS0, found), Net.JsonString(response.Body, "uf"), Net.JsonString(response.Body, "localidade"), Net.JsonString(response.Body, "bairro"), Net.JsonString(response.Body, "logradouro")); + } + + /// + /// Reads the address Widenet answers with. + /// + public static async System.Threading.Tasks.Task FetchWidenet(string cep) + { + HttpResponse response = await Net.HttpGet((("https://apps.widenet.com.br/busca-cep/api/cep/" + cep) + ".json"), HTTP_RETRIES, HTTP_RETRY_DELAY_MS); + if (!response.Ok) + { + throw new CepProviderFailure("Widenet request failed"); + } + string found = Net.JsonString(response.Body, "code"); + if ((((Net.JsonInt(response.Body, "status") != 200L) || !Net.JsonIsTrue(response.Body, "ok")) || (found == ""))) + { + throw new GetAddressInfoByCepNotFoundError("CEP n\u00e3o encontrado"); + } + return new AddressInfo(Runtime.KeepClass(CLASS0, found), Net.JsonString(response.Body, "state"), Net.JsonString(response.Body, "city"), Net.JsonString(response.Body, "district"), Net.JsonString(response.Body, "address")); + } + + /// + /// Reads the address BrasilAPI answers with. + /// + /// @see Based on: https://brasilapi.com.br/docs#tag/CEP + /// + public static async System.Threading.Tasks.Task FetchBrasilApi(string cep) + { + HttpResponse response = await Net.HttpGet((("https://brasilapi.com.br/api/cep/v1/" + cep) + ""), HTTP_RETRIES, HTTP_RETRY_DELAY_MS); + if ((response.Status == BRASIL_API_NOT_FOUND_STATUS)) + { + throw new GetAddressInfoByCepNotFoundError("CEP n\u00e3o encontrado"); + } + if (!response.Ok) + { + throw new CepProviderFailure("BrasilAPI request failed"); + } + string found = Net.JsonString(response.Body, "cep"); + if ((Net.JsonTruthy(response.Body, "errors") || (found == ""))) + { + throw new GetAddressInfoByCepNotFoundError("CEP n\u00e3o encontrado"); + } + return new AddressInfo(Runtime.KeepClass(CLASS0, found), Net.JsonString(response.Body, "state"), Net.JsonString(response.Body, "city"), Net.JsonString(response.Body, "neighborhood"), Net.JsonString(response.Body, "street")); + } + + /// + /// Asks one named provider for a CEP. + /// + public static async System.Threading.Tasks.Task FetchProvider(string provider, string cep) + { + if ((provider == "viacep")) + { + return await FetchViaCep(cep); + } + if ((provider == "widenet")) + { + return await FetchWidenet(cep); + } + return await FetchBrasilApi(cep); + } + + /// + /// The providers of a list that are known, in the order they were given. + /// + public static System.Collections.Generic.List KnownProviders(System.Collections.Generic.List given) + { + System.Collections.Generic.List kept = new System.Collections.Generic.List { }; + foreach (var provider in given) + { + if (Net.ListHas(KNOWN_PROVIDERS, provider)) + { + kept.Add(provider); + } + } + return kept; + } + + /// + /// Fetches address information for a given CEP using multiple providers simultaneously. + /// Returns the result from the first provider that responds successfully. + /// + /// The providers are started together and raced, not tried one after the other, so a provider + /// that is retrying delays nothing for the others: its retries only push back the moment its own + /// failure lands, and therefore the moment an all-failed rejection can surface. + /// + /// @see Official: https://www.correios.com.br/enviar/precisa-de-ajuda/tudo-sobre-cep + /// @see Based on: https://viacep.com.br/ + /// ViaCEP, one of the two default providers. A third-party service, not a Correios one. + /// @see Based on: https://brasilapi.com.br/docs#tag/CEP + /// BrasilAPI, the other default provider. A third-party service, not a Correios one. + /// + public static async System.Threading.Tasks.Task GetAddressInfoByCep(string cep, GetAddressInfoByCepOptions options = null) + { + System.Collections.Generic.List optionsProviders = null; + if (options != null && options.Providers != null) + { + optionsProviders = options.Providers; + } + string digits = Runtime.KeepClass(CLASS0, cep); + if (false) + { + digits = Runtime.PadStart(digits, 8L, "0"); + } + if (!Runtime.PatternTest(PATTERN_CEP_FORMAT, digits)) + { + throw new GetAddressInfoByCepValidationError("CEP inv\u00e1lido"); + } + System.Collections.Generic.List chosen = DEFAULT_PROVIDERS; + if ((optionsProviders != null)) + { + if (!true) + { + throw new GetAddressInfoByCepValidationError("Nenhum provedor v\u00e1lido especificado"); + } + chosen = KnownProviders(optionsProviders); + if (((long) chosen.Count == 0L)) + { + throw new GetAddressInfoByCepValidationError("Nenhum provedor v\u00e1lido especificado"); + } + } + Attempts attempts = Net.StartAll(FetchProvider, chosen, digits); + AddressInfo found = await Net.FirstSuccess(attempts); + if ((found != null)) + { + return found; + } + if (Net.AnyFailedWith(attempts, "GetAddressInfoByCepNotFoundError")) + { + throw new GetAddressInfoByCepNotFoundError("CEP n\u00e3o encontrado em nenhum servi\u00e7o"); + } + throw new GetAddressInfoByCepServiceError("Todos os servi\u00e7os est\u00e3o fora de servi\u00e7o ou indispon\u00edveis"); + } + } +} diff --git a/spec/bridge/out/csharp/GetMunicipalitiesUtility.cs b/spec/bridge/out/csharp/GetMunicipalitiesUtility.cs new file mode 100644 index 000000000..f094fac6a --- /dev/null +++ b/spec/bridge/out/csharp/GetMunicipalitiesUtility.cs @@ -0,0 +1,5860 @@ +// Code generated from spec/bridge/source/get-municipalities.ts. DO NOT EDIT. + +namespace BrazilianUtils.Bridge +{ + + + /// One Brazilian municipality, as the IBGE publishes it. + public sealed class Municipality + { + /// The 7-digit IBGE municipality code. + public string Code { get; set; } + + /// The municipality name. + public string Name { get; set; } + + /// The two-letter code of the state the municipality belongs to. + public string StateCode { get; set; } + + public Municipality(string code, string name, string stateCode) + { + Code = code; + Name = name; + StateCode = stateCode; + } + } + + /// Brazilian municipalities, written once. + public static class GetMunicipalitiesUtility + { + + + + + + + /// Brazilian municipalities published by the IBGE, by state, in the pt-BR collation order the JavaScript package returns. + private static readonly Dataset MUNICIPALITIES = new Dataset( + MunicipalitiesRows(), new[] { "AC", "AL", "AP", "AM", "BA", "CE", "DF", "ES", "GO", "MA", "MT", "MS", "MG", "PA", "PB", "PR", "PE", "PI", "RJ", "RN", "RS", "RO", "RR", "SC", "SP", "SE", "TO" }, MunicipalitiesGroups(), + new[] { 882, 1566, 883, 1567, 2419, 619, 202, 203, 2786, 4417, 2420, 4418, 1568, 3185, 5432, 1569, 1128, 204, 2421, 620, 621, 3686, 3370, 3853, 622, 1345, 0, 884, 1570, 4712, 885, 4713, 2787, 205, 3186, 3687, 804, 1129, 3187, 2422, 3188, 3371, 4419, 4420, 2423, 1346, 1571, 22, 2563, 3372, 1487, 1572, 4421, 1130, 805, 206, 886, 887, 3688, 3189, 3854, 4714, 1573, 3190, 4715, 4422, 4716, 4717, 4718, 1574, 4423, 888, 4424, 1575, 3855, 4719, 2788, 806, 2564, 5433, 1576, 207, 623, 1577, 3856, 1578, 2565, 2566, 2567, 3191, 3373, 208, 4720, 1579, 1131, 624, 2568, 1488, 209, 1132, 3857, 807, 3858, 3374, 3859, 1580, 2424, 3689, 889, 1581, 808, 4721, 1582, 4425, 2569, 2570, 3192, 5434, 210, 5435, 2425, 1583, 3690, 2789, 3860, 890, 1584, 3861, 1585, 1347, 4350, 4722, 2426, 1133, 2790, 625, 1586, 3193, 4723, 3862, 4402, 4724, 1134, 1135, 4351, 1348, 4426, 1349, 1587, 3691, 3863, 1350, 891, 1588, 3375, 1351, 2791, 4352, 892, 2792, 1136, 2793, 1589, 809, 626, 1352, 2794, 3376, 4725, 140, 1590, 4726, 4727, 4728, 4729, 1591, 3864, 5436, 4353, 1592, 3377, 893, 2795, 4403, 1489, 124, 1137, 2796, 3194, 3865, 894, 3378, 1138, 211, 141, 212, 213, 4730, 895, 4731, 4732, 3866, 627, 896, 2571, 4733, 5357, 1593, 2797, 23, 214, 2798, 2427, 1139, 4734, 142, 5437, 2428, 897, 2429, 1140, 1490, 1491, 810, 4427, 215, 2799, 216, 1594, 4735, 3867, 1595, 4736, 1596, 1492, 3195, 4428, 217, 3379, 5438, 3692, 3594, 218, 2800, 898, 4737, 4738, 899, 3380, 4429, 4430, 143, 3868, 219, 2801, 628, 3381, 220, 1597, 4431, 1598, 221, 1493, 3693, 2802, 3869, 1599, 2572, 4739, 4740, 900, 901, 5439, 1494, 3595, 811, 1353, 4741, 1141, 4432, 3694, 222, 902, 223, 2803, 144, 629, 5358, 1495, 630, 4433, 2573, 1600, 5359, 4742, 224, 631, 225, 4743, 226, 1601, 632, 3196, 4744, 812, 903, 1602, 904, 905, 5440, 5441, 5442, 1354, 5443, 1355, 1142, 5444, 906, 1603, 5445, 1143, 1496, 227, 3870, 1144, 4745, 4746, 1604, 4747, 24, 5446, 1605, 2804, 1606, 2805, 1607, 2806, 1356, 4434, 2574, 4435, 4748, 4749, 633, 1145, 3871, 634, 3197, 3596, 2575, 2807, 228, 3872, 635, 229, 5360, 2808, 1608, 1609, 1610, 4750, 1611, 3198, 1612, 3597, 4751, 2576, 3695, 5361, 2577, 2578, 4752, 4753, 1357, 907, 3696, 1613, 1614, 1615, 1358, 4354, 4754, 2809, 3598, 4436, 636, 3382, 2579, 3383, 3384, 3599, 5447, 3873, 3874, 3875, 3876, 3877, 3878, 4437, 4755, 908, 4756, 4438, 3879, 4439, 4757, 2810, 637, 4758, 1, 2811, 3697, 2580, 3385, 1616, 2812, 25, 2813, 145, 4440, 1617, 4759, 813, 5448, 2430, 1618, 3880, 3881, 230, 4760, 909, 638, 4441, 2431, 5449, 146, 4761, 4762, 4763, 2432, 3386, 910, 1146, 5450, 5451, 1147, 1148, 1149, 1150, 4764, 1619, 3882, 2433, 2581, 3698, 231, 2434, 232, 3387, 639, 814, 4765, 1620, 911, 4442, 4443, 4444, 4445, 4446, 3883, 4447, 2814, 4766, 1151, 1621, 640, 4767, 2582, 1622, 1623, 4448, 1497, 2815, 5452, 2435, 233, 3884, 4768, 1624, 3885, 1152, 1359, 1625, 3886, 2583, 3699, 1626, 641, 4769, 2816, 2436, 3700, 147, 4770, 234, 4449, 4771, 3388, 235, 3199, 2584, 2585, 26, 815, 27, 2586, 1360, 4772, 236, 1153, 1361, 3887, 2817, 237, 5453, 3600, 3888, 3889, 3890, 238, 4773, 5362, 3891, 1627, 3601, 4450, 2818, 3892, 3389, 642, 239, 3390, 148, 1154, 3200, 4774, 4775, 643, 240, 912, 3391, 241, 242, 5454, 644, 3893, 1628, 4776, 4777, 1498, 28, 3392, 4778, 1499, 645, 4779, 2587, 4780, 646, 647, 1500, 2819, 913, 1629, 1155, 2820, 3393, 4451, 1156, 29, 2437, 2588, 3201, 2589, 3394, 3202, 3602, 1630, 243, 4452, 244, 1631, 3203, 30, 1632, 1633, 2438, 3395, 1157, 4453, 2439, 149, 3894, 4781, 3701, 3895, 1158, 1634, 1635, 2590, 4782, 1159, 5455, 4783, 3396, 1636, 150, 3204, 3397, 1637, 3205, 1638, 1639, 4454, 4784, 1640, 4785, 4786, 245, 2821, 4455, 816, 1641, 2822, 2823, 1362, 4787, 3398, 246, 2591, 2824, 648, 2592, 4404, 2825, 3896, 3897, 3898, 1160, 3899, 151, 3900, 247, 31, 152, 3399, 4788, 1642, 4456, 1643, 2826, 3702, 3206, 1501, 4789, 4790, 3207, 1644, 1161, 3208, 3603, 4457, 914, 1645, 2593, 3400, 3703, 3901, 4458, 248, 1646, 249, 1162, 915, 1647, 1363, 1648, 3604, 817, 4459, 2827, 2440, 5456, 4791, 1163, 3902, 3401, 3903, 1649, 4460, 3904, 1650, 2594, 2828, 4792, 2829, 4461, 1651, 4405, 3402, 916, 1652, 250, 251, 1502, 2441, 3209, 1653, 2595, 917, 2596, 3905, 3403, 5363, 252, 4793, 4794, 153, 2597, 4795, 1654, 4796, 2830, 3906, 1655, 4797, 1656, 253, 4462, 3907, 4463, 4464, 3908, 2442, 4798, 2831, 32, 1657, 2443, 1503, 1658, 2832, 5457, 2, 3404, 803, 1659, 1364, 4799, 1660, 918, 1661, 3210, 818, 3211, 3704, 5458, 1164, 4800, 3212, 1165, 2598, 3405, 2599, 5364, 2444, 649, 254, 255, 2445, 2446, 919, 3909, 4801, 4802, 256, 1662, 257, 4465, 4466, 1663, 1664, 3213, 258, 1665, 3214, 3, 2447, 4803, 4804, 1166, 920, 1167, 921, 5459, 3406, 3407, 1168, 922, 259, 1169, 1666, 4355, 4805, 1667, 3910, 154, 2600, 1504, 260, 2601, 261, 1668, 923, 3408, 2602, 4356, 3215, 3605, 1669, 4806, 4807, 3216, 4467, 4808, 3911, 4357, 3912, 1365, 262, 924, 1670, 925, 1671, 1672, 2448, 2449, 3913, 2603, 926, 1673, 1170, 4809, 3606, 3217, 3914, 5460, 819, 2604, 2605, 2606, 33, 3915, 4358, 4810, 927, 263, 264, 1674, 265, 1675, 3218, 266, 267, 2833, 2834, 4811, 2835, 4812, 1676, 928, 3916, 4468, 2607, 3917, 3705, 3706, 3707, 4813, 268, 4814, 4815, 1171, 1172, 4816, 2608, 3409, 2609, 4817, 34, 3410, 1677, 4818, 3219, 125, 1678, 2610, 929, 930, 269, 3411, 2836, 4469, 3220, 270, 271, 1679, 2611, 272, 1680, 1505, 3918, 3221, 3919, 2837, 3920, 2838, 2839, 4470, 3607, 1681, 1682, 2450, 650, 3222, 1683, 1684, 35, 1685, 3921, 931, 1173, 2840, 3922, 4819, 2841, 2612, 2842, 1686, 932, 1366, 4820, 3412, 3923, 933, 36, 4471, 934, 273, 3413, 1687, 1688, 4472, 3924, 2843, 5365, 1689, 2844, 4473, 1690, 274, 37, 1506, 3708, 3414, 2845, 3415, 935, 4821, 2846, 3416, 2847, 3925, 4359, 1367, 3709, 1368, 1691, 936, 3926, 1369, 4822, 3608, 1692, 5461, 4474, 4823, 651, 937, 3223, 1693, 1694, 2451, 1370, 4824, 38, 275, 1695, 276, 1371, 4825, 3417, 277, 278, 279, 1696, 4360, 3927, 280, 2848, 3928, 1174, 4826, 4827, 281, 3929, 2849, 3930, 4475, 3710, 3931, 5366, 3224, 652, 5367, 4828, 3932, 4476, 282, 4406, 1697, 2850, 3609, 1175, 3418, 283, 3933, 155, 2452, 2851, 4477, 4829, 3934, 3935, 3936, 3937, 1698, 39, 5368, 3938, 4830, 284, 1699, 1700, 1701, 2613, 1702, 285, 1703, 4478, 1176, 653, 3939, 1704, 3419, 1705, 3420, 2852, 2453, 1706, 4831, 4479, 3940, 4, 3225, 1707, 3941, 4407, 1507, 3421, 4832, 1708, 286, 2853, 1709, 1710, 1711, 3610, 4833, 1712, 156, 2614, 3711, 3422, 287, 3942, 1713, 288, 4834, 3611, 1714, 157, 158, 820, 654, 3423, 289, 5369, 655, 5462, 656, 657, 1372, 2854, 3943, 1715, 3944, 1716, 3612, 1717, 1718, 1719, 1720, 1721, 1722, 938, 5463, 5370, 1723, 3226, 3712, 3713, 658, 3227, 1724, 40, 4408, 1177, 3228, 1725, 2615, 5464, 3229, 1178, 1726, 1727, 4835, 1728, 290, 3945, 1729, 659, 2855, 5465, 3946, 3613, 3230, 2616, 1730, 4836, 1508, 2454, 1373, 4361, 939, 821, 3424, 4837, 2856, 291, 1731, 940, 4838, 2857, 4480, 660, 1732, 1733, 3231, 4839, 2617, 292, 2618, 293, 3947, 1734, 661, 941, 294, 2619, 1735, 662, 942, 1736, 4481, 1179, 3948, 3425, 3714, 1180, 4840, 663, 3232, 5371, 1737, 4482, 3949, 5466, 2858, 295, 1738, 1181, 1739, 1182, 1183, 4362, 943, 4841, 4842, 3950, 2859, 3951, 3715, 3952, 3953, 3954, 4483, 4843, 2860, 944, 3233, 3234, 41, 1740, 1741, 3955, 5467, 5468, 1742, 1374, 1743, 945, 4484, 1509, 1184, 4485, 4844, 3956, 3957, 664, 4845, 2455, 1744, 3958, 2861, 665, 666, 296, 3959, 4363, 3960, 2862, 297, 2863, 946, 1185, 3961, 298, 1745, 3962, 1746, 1747, 1375, 1748, 4846, 2864, 299, 159, 3426, 3427, 4486, 3428, 1376, 947, 300, 160, 1186, 1187, 1749, 42, 3429, 2456, 822, 1377, 4847, 1188, 3963, 948, 5469, 5470, 1378, 4848, 2865, 3430, 3431, 43, 2866, 3964, 4364, 1750, 5471, 1751, 3614, 1752, 1379, 2620, 1753, 823, 1754, 301, 1755, 1756, 1757, 3615, 302, 2457, 3432, 824, 303, 304, 1189, 1758, 1759, 1760, 5472, 1761, 4849, 4850, 4487, 2458, 2621, 3235, 305, 2622, 306, 3965, 1762, 1763, 1380, 2623, 1764, 1765, 1766, 2867, 1767, 1381, 1768, 2868, 1769, 1770, 3966, 1771, 2869, 307, 1772, 3967, 44, 3968, 1773, 308, 2870, 3616, 4851, 309, 4488, 1774, 1775, 667, 2624, 1510, 310, 1776, 2871, 1777, 4852, 1190, 1778, 3969, 3970, 2872, 3716, 1779, 4489, 3717, 311, 3433, 4853, 4490, 1780, 1781, 3971, 1511, 2873, 1782, 1783, 1784, 949, 1785, 1786, 4491, 3434, 3236, 312, 3237, 1512, 950, 951, 4854, 2874, 4365, 4492, 45, 4855, 4856, 4366, 1513, 313, 4857, 3972, 1382, 1787, 5473, 3973, 1514, 2625, 46, 668, 669, 4858, 314, 4493, 1788, 315, 3974, 1789, 4859, 3975, 3976, 5474, 3435, 1790, 952, 1791, 953, 1792, 5372, 3436, 316, 954, 5475, 670, 955, 1793, 671, 3977, 317, 2626, 2875, 4860, 3978, 4861, 1794, 2876, 2877, 5, 2878, 3979, 3718, 1795, 2879, 4862, 2627, 1383, 2628, 2629, 2630, 4367, 956, 3238, 2459, 5373, 4863, 4494, 4495, 1796, 3239, 318, 3437, 2460, 2880, 4496, 2881, 3438, 3719, 2631, 1797, 3439, 2632, 2461, 3440, 2462, 2463, 1191, 1384, 1798, 3240, 126, 957, 2633, 958, 5476, 319, 1799, 3980, 959, 1192, 1800, 1801, 47, 1802, 3441, 1385, 1515, 672, 3981, 4864, 4497, 1803, 2634, 1804, 1805, 3982, 4865, 2635, 2882, 2883, 2884, 1806, 1386, 5477, 320, 3983, 1807, 1808, 4498, 960, 4866, 3442, 5374, 1809, 1810, 1811, 825, 4867, 1812, 1813, 961, 5478, 1814, 1815, 1816, 4868, 4869, 3984, 3985, 1516, 5479, 3986, 48, 2885, 4870, 1387, 321, 1817, 1818, 2464, 3443, 3987, 3444, 1819, 322, 3988, 1193, 3989, 1820, 1821, 826, 3445, 4499, 1822, 3990, 2636, 1823, 1824, 1825, 827, 1826, 1827, 3241, 1517, 2886, 4871, 1828, 1518, 2887, 3991, 4500, 3992, 3720, 2888, 962, 4872, 4873, 3617, 2637, 5480, 4874, 1194, 3618, 1829, 4875, 828, 963, 964, 161, 1519, 4876, 2465, 3993, 3446, 4877, 3447, 4878, 323, 1830, 2638, 4879, 4880, 4881, 4882, 3994, 3721, 324, 3995, 2889, 2890, 1831, 4883, 1832, 3619, 3996, 1833, 325, 4501, 1834, 2891, 3997, 3998, 162, 6, 3722, 3999, 4000, 673, 326, 4502, 4001, 4002, 4003, 4503, 1835, 3242, 4004, 1836, 1837, 2639, 4005, 2892, 3448, 5481, 1195, 2893, 4368, 1838, 3723, 1839, 4884, 4885, 327, 4006, 4007, 5375, 4008, 4009, 1840, 4886, 1196, 4010, 4887, 1841, 49, 1842, 965, 4888, 1843, 4011, 328, 4889, 4012, 1844, 329, 674, 1845, 1846, 3724, 3243, 2640, 4013, 966, 1847, 1848, 675, 2466, 2894, 4014, 4890, 3449, 330, 5482, 1520, 2895, 4015, 4504, 4016, 967, 2896, 4017, 7, 331, 332, 50, 3244, 5376, 1197, 1849, 3725, 1850, 1851, 4018, 51, 1388, 2897, 2898, 1852, 3245, 1198, 3726, 4891, 4892, 4893, 4894, 127, 3246, 1853, 1854, 2899, 1521, 5483, 1389, 333, 5484, 334, 968, 52, 2900, 4505, 4895, 2901, 3727, 4896, 3247, 4019, 969, 3450, 2902, 3248, 335, 2467, 3451, 1855, 2903, 3452, 4020, 4506, 2904, 4897, 4898, 163, 4021, 1856, 4022, 970, 1199, 2905, 336, 4507, 971, 1857, 5485, 4023, 676, 4508, 677, 1858, 1200, 4024, 678, 1201, 1859, 2906, 2907, 4509, 4899, 3453, 2908, 3454, 1860, 2909, 3728, 1861, 3455, 4900, 1862, 3456, 1863, 4901, 679, 4025, 1864, 1865, 1866, 2641, 3249, 5377, 4510, 1867, 1868, 3457, 1869, 1870, 3729, 829, 1871, 4902, 2642, 4903, 1872, 3730, 4511, 3250, 972, 1873, 337, 3251, 5378, 4904, 4026, 4512, 2468, 4027, 4513, 4514, 4905, 1390, 4028, 338, 4906, 3458, 4029, 1391, 2910, 5379, 4907, 680, 4030, 339, 4908, 4031, 3459, 53, 4032, 1874, 4909, 340, 1392, 1522, 3252, 4033, 1202, 2911, 1875, 3253, 1876, 973, 974, 975, 2469, 976, 3731, 977, 5486, 978, 5487, 979, 2912, 2913, 1877, 1203, 341, 1878, 1879, 980, 1204, 4515, 3732, 1205, 1206, 4369, 830, 1207, 342, 1208, 1209, 1880, 681, 1210, 5380, 1211, 4034, 4035, 4036, 2914, 3254, 682, 683, 1881, 4516, 3255, 4037, 4517, 684, 3733, 1882, 4038, 4518, 831, 3460, 4039, 4910, 4911, 2915, 4912, 2916, 685, 164, 4370, 343, 3734, 2917, 344, 1883, 1884, 4913, 4914, 3620, 2918, 981, 4040, 2919, 4915, 2643, 4916, 2920, 4917, 1885, 4519, 686, 1886, 5488, 982, 687, 4520, 1887, 1888, 4918, 4041, 983, 2921, 4919, 1393, 832, 2922, 2923, 1889, 4920, 4921, 345, 4922, 2924, 1890, 4923, 4924, 3461, 984, 4925, 4521, 4926, 4522, 4927, 1891, 1523, 1892, 1212, 1893, 1394, 1894, 1895, 2644, 2645, 2470, 5489, 4928, 4042, 985, 1896, 346, 4929, 4043, 4523, 4044, 688, 986, 987, 4930, 2925, 689, 4045, 4931, 3462, 4046, 165, 4047, 1213, 4932, 988, 4933, 347, 1897, 4934, 3256, 2926, 4048, 690, 4935, 54, 833, 2927, 1898, 1899, 4049, 1900, 4524, 691, 2646, 348, 349, 4525, 350, 351, 692, 3257, 352, 353, 2928, 354, 4936, 1901, 1902, 834, 4050, 3258, 4526, 355, 356, 4051, 4937, 357, 1903, 4052, 358, 4938, 835, 359, 1904, 1905, 4939, 360, 693, 4527, 1906, 2929, 1214, 4940, 361, 694, 836, 3735, 4941, 55, 362, 4942, 2647, 4943, 1907, 1215, 1216, 2471, 2472, 3259, 4944, 1908, 363, 56, 4053, 3621, 364, 4945, 2930, 3260, 1909, 1524, 695, 2931, 1910, 4054, 4946, 5381, 3261, 3463, 4947, 4948, 365, 4528, 1911, 4055, 2648, 4529, 2932, 4056, 1912, 4530, 2933, 4531, 4057, 1217, 2934, 989, 2935, 3262, 1913, 1914, 4532, 4949, 696, 4058, 4950, 1915, 2936, 4951, 990, 5382, 1395, 2649, 1916, 3263, 4059, 366, 2473, 57, 1917, 1918, 3464, 991, 1919, 1525, 4952, 4533, 1920, 992, 1921, 3736, 697, 1922, 698, 4953, 4060, 367, 4954, 4955, 1923, 368, 4956, 4534, 369, 2937, 993, 1396, 3465, 4061, 166, 2474, 3264, 994, 2938, 4535, 4957, 699, 4958, 4536, 3265, 3737, 700, 5490, 1924, 4537, 370, 701, 4409, 2939, 4959, 4538, 4062, 1925, 371, 372, 167, 4539, 4960, 4961, 373, 374, 2940, 4540, 702, 375, 2941, 4541, 2475, 837, 3466, 995, 4542, 4063, 2650, 5383, 5384, 376, 4962, 377, 996, 5385, 1926, 1927, 1928, 3622, 378, 5491, 1929, 1930, 379, 168, 3266, 4064, 380, 381, 382, 383, 838, 384, 3623, 2942, 1931, 997, 998, 5492, 4963, 3267, 703, 3467, 4543, 1218, 1932, 2943, 704, 2476, 999, 3738, 4544, 4964, 4965, 385, 1933, 386, 3624, 387, 1934, 169, 1935, 388, 1936, 2944, 389, 2945, 3268, 1937, 1938, 1939, 390, 4966, 1940, 1397, 391, 1941, 1942, 4967, 3625, 1000, 1943, 705, 392, 393, 394, 1944, 4968, 1219, 2946, 4545, 839, 2947, 3626, 3269, 395, 4969, 1945, 4970, 4971, 396, 706, 4972, 170, 4546, 1001, 4973, 5493, 3270, 397, 707, 4547, 4974, 1526, 5494, 2651, 4975, 5386, 2652, 4371, 4065, 4976, 4977, 1002, 4978, 398, 4066, 1527, 3271, 840, 399, 4979, 708, 4980, 1003, 4067, 3627, 1946, 4981, 4068, 400, 4982, 709, 2653, 3739, 1947, 1398, 128, 1004, 3468, 1948, 2948, 1949, 1950, 1220, 1399, 4983, 4984, 401, 402, 4985, 403, 4986, 404, 405, 1951, 1952, 1005, 1953, 4987, 2477, 4548, 1954, 1955, 4988, 406, 841, 2949, 2950, 2951, 2952, 1528, 1006, 4069, 4070, 3272, 4549, 407, 4989, 2953, 4071, 4990, 1956, 3740, 408, 2654, 58, 2478, 4991, 2954, 4992, 1400, 1957, 4550, 409, 3469, 1958, 59, 4072, 2479, 4993, 1959, 4073, 2955, 410, 1960, 4074, 411, 842, 710, 4075, 2956, 711, 712, 412, 4994, 713, 4551, 1961, 3470, 4995, 4996, 1962, 1963, 1007, 2957, 413, 3741, 4997, 3742, 1401, 2958, 1964, 3743, 1965, 60, 5387, 3628, 3744, 2959, 5388, 1966, 1529, 171, 2960, 3273, 4076, 1008, 4552, 1530, 61, 714, 1531, 2961, 3745, 3746, 3471, 3747, 2962, 4553, 4998, 4077, 4999, 4372, 1009, 2963, 3274, 1532, 715, 1221, 3275, 3472, 5000, 5495, 1010, 1402, 1967, 1968, 1222, 1969, 62, 414, 1970, 1971, 1972, 415, 2655, 5001, 843, 3473, 1973, 2964, 1011, 4373, 716, 416, 417, 4554, 1974, 1975, 5002, 3276, 3748, 3474, 3749, 418, 1223, 1976, 844, 2656, 1977, 5003, 1978, 63, 3277, 3475, 2965, 2657, 3476, 4078, 4555, 1979, 8, 4556, 5004, 3750, 3477, 1980, 1981, 1224, 1982, 1012, 1403, 2658, 5496, 1983, 2659, 419, 717, 3478, 718, 3278, 420, 3751, 1404, 1984, 3479, 4079, 5005, 5006, 1225, 2660, 64, 3752, 5007, 2966, 65, 5008, 3279, 4557, 5009, 5010, 1985, 2967, 3280, 3480, 2661, 2662, 172, 1986, 1405, 2480, 1406, 421, 1013, 2968, 422, 423, 173, 1533, 1987, 2969, 174, 4558, 1988, 1534, 424, 1989, 5389, 4559, 1226, 1227, 1228, 1229, 2663, 3481, 4080, 3753, 66, 5497, 1990, 2664, 3281, 3754, 3482, 3755, 3483, 3282, 1230, 3283, 3484, 3485, 5498, 3284, 1991, 4081, 1992, 1993, 1994, 3285, 1231, 3756, 425, 3757, 1014, 1995, 2665, 4082, 4083, 5011, 3486, 4560, 1535, 426, 3629, 4084, 5499, 4085, 4561, 1232, 427, 428, 3286, 429, 3758, 3759, 1996, 430, 1997, 1407, 1998, 3487, 2970, 431, 845, 1999, 2971, 129, 5012, 5390, 2972, 2000, 2666, 4562, 432, 4563, 5500, 5013, 2001, 719, 4086, 5014, 2002, 4564, 5015, 2003, 433, 5016, 4565, 2004, 1015, 2973, 4087, 2005, 434, 2974, 1233, 2006, 5017, 2007, 3287, 67, 2481, 720, 2975, 5018, 4566, 4088, 4089, 846, 5019, 2667, 435, 5501, 2976, 2977, 2668, 2978, 2008, 4567, 5020, 1234, 5021, 5022, 1408, 5023, 2669, 5024, 1409, 3760, 5025, 3488, 1235, 436, 3761, 2009, 2010, 4568, 2979, 5026, 2011, 2980, 5027, 2981, 5028, 2012, 4569, 1016, 3489, 5502, 3630, 3762, 437, 4090, 5391, 130, 3288, 438, 5029, 3763, 5030, 439, 5031, 68, 2013, 4091, 4374, 2014, 3289, 4570, 3631, 440, 721, 3490, 441, 2015, 2670, 2482, 442, 4571, 2483, 1236, 5032, 3632, 443, 444, 5033, 5034, 1017, 4572, 69, 3764, 4573, 2016, 445, 446, 5392, 5393, 2982, 2671, 2672, 1018, 2983, 2017, 4092, 175, 2673, 176, 3290, 177, 9, 2984, 2985, 2986, 5035, 2987, 2018, 3633, 2988, 2019, 2020, 178, 3491, 2989, 10, 4093, 447, 448, 2021, 847, 4094, 2022, 70, 1019, 179, 2484, 5036, 1237, 5037, 4574, 1536, 2485, 722, 449, 71, 450, 3291, 1238, 723, 1239, 2486, 5038, 4095, 848, 4096, 451, 72, 4575, 2023, 2674, 1410, 4097, 3765, 452, 724, 3492, 3493, 2990, 73, 849, 11, 4576, 2675, 2024, 2991, 2992, 2025, 4098, 4099, 5503, 5039, 74, 3634, 2026, 850, 2993, 2994, 5040, 2995, 2996, 5041, 2027, 2997, 2998, 2028, 2487, 2676, 2029, 2999, 2030, 4100, 3000, 2031, 725, 5042, 3766, 2032, 5394, 3001, 1020, 453, 726, 3494, 2677, 4577, 4101, 454, 75, 1240, 2033, 5043, 2678, 5504, 3002, 2034, 2035, 2036, 2037, 2038, 3495, 455, 1241, 2679, 3003, 2039, 4102, 2680, 4103, 4104, 3004, 2040, 1242, 1243, 4578, 2041, 1021, 76, 1411, 2681, 2042, 5044, 3005, 180, 1022, 5505, 727, 3767, 4105, 131, 2043, 456, 3006, 2488, 2044, 4579, 2489, 3635, 2045, 5045, 3007, 2046, 5046, 728, 5047, 2047, 3636, 77, 3768, 3496, 457, 3497, 3637, 5048, 458, 729, 1244, 730, 3498, 1023, 851, 1024, 78, 4106, 2048, 2049, 1025, 5049, 4375, 5050, 2050, 5051, 3638, 5506, 1245, 3008, 2051, 4107, 2052, 731, 1537, 1246, 3292, 5052, 459, 5507, 460, 4376, 5053, 3009, 5054, 1412, 5055, 2053, 4580, 1247, 3010, 732, 2490, 5056, 4581, 2054, 2055, 2682, 5057, 5058, 5059, 1026, 5395, 2491, 2492, 733, 5060, 1248, 5061, 4582, 5062, 2056, 3499, 3500, 2057, 734, 2683, 2058, 852, 3769, 4108, 2493, 3770, 1027, 2059, 5396, 3501, 5063, 4109, 5064, 5065, 2060, 5066, 2061, 4110, 4583, 2062, 4584, 5067, 3771, 5508, 2063, 2684, 5068, 4377, 461, 2064, 5509, 2065, 2685, 5069, 79, 4111, 1249, 2066, 1028, 2067, 1029, 1030, 735, 2068, 736, 3293, 3011, 3294, 4112, 462, 3012, 737, 1031, 4113, 5070, 1032, 3502, 4585, 2069, 463, 3503, 2070, 4586, 4114, 4115, 1250, 464, 5071, 1033, 3772, 4116, 5072, 1034, 2494, 4410, 738, 465, 4117, 466, 853, 4118, 4119, 739, 2686, 467, 468, 1035, 1538, 2071, 3013, 469, 854, 470, 855, 2072, 5397, 80, 3504, 5510, 471, 5073, 472, 2073, 1036, 2074, 2075, 5074, 2076, 4120, 2077, 5075, 3773, 2078, 2079, 3639, 5511, 5076, 2687, 4587, 1539, 473, 5512, 3295, 3505, 5077, 2080, 2688, 3506, 1037, 5398, 2081, 1038, 5078, 181, 5079, 4121, 474, 3640, 1251, 2082, 1540, 5080, 1039, 3774, 3641, 1413, 4122, 475, 4411, 1414, 5399, 5400, 5401, 3014, 5402, 3507, 1415, 5403, 3508, 5081, 3015, 4123, 1541, 1040, 3016, 1542, 4124, 1041, 3017, 1416, 4125, 2083, 4126, 1417, 4378, 4127, 5082, 476, 1418, 5083, 4128, 3018, 5084, 1252, 1042, 3775, 2084, 4588, 3019, 2495, 3020, 4129, 5085, 477, 3021, 2689, 3642, 1043, 5086, 1419, 5087, 4130, 478, 3643, 1044, 5088, 1253, 2496, 4589, 479, 1420, 3022, 2085, 3023, 5089, 4379, 1421, 1422, 2086, 1423, 1424, 1425, 5090, 1426, 3024, 740, 2690, 5513, 1254, 182, 4131, 4132, 2691, 4133, 2087, 2088, 4134, 3025, 4135, 480, 2089, 1045, 4136, 5514, 741, 3026, 1427, 3509, 4137, 3027, 2090, 481, 3028, 2497, 4590, 1428, 2091, 4380, 856, 1046, 4591, 482, 1429, 5091, 5515, 183, 5516, 184, 4138, 1047, 4139, 2092, 1048, 4140, 483, 4592, 5092, 1430, 4381, 1543, 3029, 5517, 81, 4141, 1431, 742, 2093, 3510, 1049, 2498, 2499, 1432, 3511, 1433, 4142, 484, 4143, 2094, 5093, 2500, 743, 5094, 3512, 2501, 132, 2095, 5095, 2692, 1255, 82, 3776, 83, 3513, 84, 2096, 5096, 2097, 3296, 1256, 485, 2693, 2098, 5518, 486, 2099, 85, 2100, 5097, 2101, 5098, 5099, 2502, 2102, 1050, 5100, 4593, 3297, 3298, 744, 3030, 5101, 5102, 4144, 5103, 4594, 2503, 487, 3299, 2504, 5104, 3031, 4595, 86, 2103, 3777, 2104, 2105, 4382, 2694, 4596, 5105, 1051, 2106, 3032, 5106, 488, 1052, 5107, 2505, 745, 4412, 746, 5404, 1257, 747, 748, 1053, 2107, 3514, 2108, 3515, 2109, 4597, 3033, 4145, 2110, 4598, 2111, 2112, 3516, 87, 5108, 1054, 2506, 749, 4599, 2113, 4600, 750, 3300, 4146, 5109, 3034, 5519, 489, 3035, 4601, 5110, 4147, 3517, 88, 3518, 1258, 5520, 490, 1055, 5521, 3301, 5522, 1056, 1057, 3036, 5111, 4148, 4602, 2114, 3037, 1058, 4149, 857, 3302, 5112, 4150, 89, 2115, 4603, 3519, 2116, 3644, 2117, 751, 2507, 2118, 5113, 4151, 3645, 1259, 5114, 752, 4604, 5115, 1544, 3038, 4152, 5523, 2119, 753, 491, 754, 3778, 5524, 3039, 3040, 1545, 1059, 1434, 5116, 3041, 5117, 3303, 1435, 3042, 1546, 2120, 5118, 2695, 492, 3646, 3779, 2508, 1060, 3780, 5119, 4153, 4383, 3781, 90, 185, 493, 91, 5120, 5121, 3520, 3521, 3304, 3782, 1260, 4154, 3783, 2121, 4155, 2122, 2123, 2124, 2696, 3784, 1261, 3522, 3305, 92, 4605, 4156, 4157, 2125, 4606, 1262, 2126, 3043, 3044, 2697, 2127, 3523, 2128, 2129, 5122, 3785, 3647, 494, 2509, 5525, 3524, 3786, 3306, 186, 2130, 3045, 5123, 5124, 1263, 2698, 3307, 3525, 5125, 2131, 495, 4158, 5126, 3046, 93, 4607, 1264, 2132, 4159, 3526, 496, 3047, 2133, 5127, 3308, 2134, 5128, 2135, 755, 2699, 133, 2136, 2137, 2138, 3787, 2700, 5405, 1436, 3788, 2139, 5129, 497, 4160, 2701, 2140, 4608, 5130, 5131, 1265, 5406, 5132, 2141, 5526, 498, 3789, 858, 5133, 1266, 1547, 3527, 3528, 2142, 4161, 2702, 2143, 3790, 5527, 2510, 1437, 4162, 4163, 756, 1267, 5134, 3791, 94, 4609, 757, 2144, 2145, 5528, 2146, 2147, 2148, 5135, 5136, 758, 1268, 2149, 4610, 1269, 3048, 3049, 3050, 1061, 5137, 2150, 4611, 3309, 3310, 4612, 3311, 1062, 3648, 95, 5138, 2703, 499, 2151, 4164, 2511, 3529, 2704, 5139, 2152, 2153, 2154, 2155, 3051, 500, 96, 2705, 1063, 5140, 2706, 3792, 2707, 2156, 4384, 3530, 4385, 501, 5141, 1270, 97, 502, 5142, 5529, 759, 2157, 3052, 4165, 4166, 3053, 4167, 3054, 4613, 5143, 3055, 5407, 3649, 4168, 1271, 4169, 4614, 859, 503, 4170, 2158, 3531, 1272, 5144, 760, 5145, 5146, 1064, 2159, 5147, 3532, 3650, 504, 3056, 5148, 2160, 5149, 5408, 2161, 5150, 2162, 2163, 98, 1065, 1273, 2164, 4171, 2165, 5151, 5152, 3057, 5530, 5153, 4172, 5154, 4615, 2166, 1066, 1067, 761, 505, 3533, 506, 2708, 3058, 3059, 5155, 2167, 2709, 5531, 860, 2168, 2512, 12, 1068, 3060, 507, 508, 3061, 4173, 5156, 4616, 1438, 2169, 5157, 5158, 3312, 1274, 2710, 3793, 2711, 4174, 99, 2712, 2170, 5409, 5410, 509, 1439, 2171, 2172, 510, 5159, 2713, 3313, 4617, 5160, 2173, 5161, 2513, 3062, 1548, 5162, 1440, 3063, 1069, 5163, 4175, 4618, 5532, 4619, 5533, 1441, 2174, 4176, 4620, 1442, 5164, 861, 2175, 2176, 511, 5165, 762, 5166, 1070, 3651, 3064, 3794, 4177, 1071, 763, 2177, 2514, 1072, 3534, 13, 4178, 1443, 3535, 5534, 3065, 3066, 4621, 100, 5411, 2515, 101, 3795, 1444, 1445, 1446, 5167, 5168, 2178, 1275, 134, 4179, 4180, 1549, 5535, 3652, 102, 3067, 1276, 512, 4622, 4386, 4181, 3068, 14, 4182, 1073, 2179, 764, 5169, 513, 5170, 765, 2180, 2181, 4183, 4623, 1447, 5171, 135, 514, 3069, 5172, 2182, 4624, 5173, 5536, 2516, 3070, 2183, 2714, 3536, 5174, 2184, 2185, 5175, 2186, 5176, 4625, 3071, 515, 1277, 5177, 187, 4626, 516, 1278, 2187, 862, 5537, 2188, 4184, 1279, 4387, 4627, 2189, 5178, 1280, 517, 1281, 5179, 2517, 3314, 4388, 1448, 1282, 3072, 4628, 2715, 1074, 4185, 5180, 5412, 4186, 2190, 3073, 5538, 3796, 4187, 2716, 5181, 4188, 2191, 3074, 5182, 3075, 2518, 3653, 3076, 4189, 3077, 103, 3078, 3537, 518, 2717, 3654, 5183, 5184, 2192, 1449, 3079, 4190, 519, 4629, 3080, 5185, 4191, 3315, 1075, 3655, 3081, 766, 2718, 3316, 520, 767, 768, 769, 770, 3797, 3798, 521, 5186, 3082, 5187, 3083, 3084, 4630, 1283, 2193, 2194, 3085, 3086, 3317, 2195, 5539, 771, 2519, 5188, 3538, 4192, 2196, 3539, 5189, 5190, 5191, 4193, 522, 2719, 3087, 772, 3656, 2197, 3088, 1450, 3089, 2198, 2199, 5192, 4194, 523, 1284, 2720, 524, 2721, 5413, 525, 2722, 2200, 5540, 3799, 3318, 526, 3800, 2723, 2724, 2201, 3540, 3801, 5414, 1076, 1077, 1285, 1550, 5193, 527, 3541, 528, 3319, 5194, 5195, 1451, 3090, 5196, 2202, 529, 3091, 5197, 5198, 5199, 5200, 5201, 2203, 1452, 3542, 5415, 5202, 5203, 5204, 2204, 3092, 863, 3093, 3657, 3094, 15, 1453, 3095, 3096, 1551, 2205, 3658, 5205, 4389, 5541, 4631, 3659, 3660, 5206, 530, 3661, 531, 4632, 3802, 4633, 532, 2206, 4634, 2207, 5542, 4635, 4195, 2208, 3320, 4636, 4196, 5207, 3543, 104, 2209, 2520, 4637, 1552, 3097, 2210, 864, 2211, 4197, 2212, 2213, 2214, 2215, 188, 1078, 533, 4638, 5543, 2725, 1079, 1553, 2216, 5208, 4198, 4639, 2217, 5209, 4199, 1554, 2218, 4640, 4200, 2219, 534, 3803, 16, 4201, 3098, 4202, 4390, 2220, 4641, 3099, 4203, 4204, 1454, 3100, 2521, 1455, 4205, 4413, 5210, 1286, 2221, 5416, 3101, 4206, 1456, 5211, 105, 2222, 5212, 1080, 2223, 5213, 2522, 773, 535, 3804, 2224, 3102, 5214, 2225, 774, 2226, 4207, 5215, 3321, 4208, 5216, 5217, 5218, 4642, 2726, 3322, 5417, 2727, 3103, 3323, 2227, 536, 2523, 775, 5219, 3324, 4643, 5220, 5221, 2228, 5222, 1457, 3104, 4209, 3105, 5223, 4644, 537, 4210, 4211, 2524, 1287, 5544, 4212, 1081, 5545, 5224, 4645, 3325, 4213, 5225, 5226, 3106, 538, 2229, 5227, 1082, 2230, 2231, 2525, 4214, 2232, 5228, 539, 1458, 2728, 4646, 3107, 4215, 5229, 4216, 2729, 3326, 3805, 540, 3327, 5230, 5231, 541, 5232, 1083, 2233, 3108, 2234, 2526, 3328, 2235, 3544, 5233, 4217, 1459, 3545, 2236, 5234, 3109, 1084, 2237, 5546, 5235, 3329, 3546, 1288, 5236, 1289, 2730, 3110, 4647, 1085, 2238, 542, 1290, 2731, 3111, 1086, 5237, 3112, 189, 3113, 2527, 2239, 865, 3114, 5238, 3547, 543, 1291, 2240, 2732, 4391, 5418, 106, 2528, 1292, 2241, 4218, 3806, 4219, 3330, 5239, 544, 2529, 2242, 866, 3331, 4220, 3115, 2530, 2243, 2244, 5547, 3662, 3116, 5240, 3117, 776, 1293, 1294, 2733, 5241, 2245, 545, 2246, 2247, 2248, 1087, 2249, 1088, 1555, 5242, 2250, 5548, 1460, 4221, 2251, 1089, 4648, 5419, 5243, 3548, 17, 4649, 5549, 5244, 867, 2734, 4222, 1090, 3118, 5550, 546, 1461, 3332, 4650, 1091, 3119, 4651, 5551, 2252, 4223, 547, 136, 548, 4224, 5245, 2253, 2254, 2735, 5246, 2255, 777, 2531, 778, 2256, 2257, 107, 3120, 2258, 2259, 1295, 3807, 108, 2260, 3549, 2261, 5420, 3808, 2736, 2262, 549, 2532, 2533, 4225, 4652, 1462, 550, 4653, 5421, 1296, 5247, 2737, 5248, 4226, 3809, 5249, 1092, 4227, 3121, 4228, 1093, 551, 1463, 3550, 3663, 5250, 2263, 5251, 2264, 3122, 1094, 2265, 190, 2266, 2267, 5252, 1464, 2268, 4229, 3123, 5253, 4230, 2269, 2270, 3124, 2534, 1297, 3551, 4231, 4232, 552, 5254, 4233, 2271, 3125, 3552, 5255, 5256, 2272, 779, 1298, 3333, 2738, 1299, 2739, 2273, 3810, 5257, 4654, 5552, 3811, 3334, 4655, 1300, 5258, 4656, 4234, 109, 2274, 3553, 2535, 5259, 3335, 4657, 5260, 3126, 5422, 4658, 553, 554, 1095, 2740, 4659, 5423, 2275, 2536, 1301, 2537, 2741, 1302, 868, 2276, 4235, 555, 4392, 556, 1303, 2277, 1465, 557, 3554, 5553, 2538, 3812, 3664, 2278, 2742, 5261, 5424, 4236, 3555, 1096, 3665, 2279, 4237, 2280, 1304, 558, 2281, 4393, 1305, 3813, 2539, 3556, 4660, 559, 4238, 191, 869, 1556, 2282, 2283, 2540, 2284, 3666, 2285, 780, 3814, 3557, 2286, 3558, 2287, 2288, 2289, 560, 2290, 4239, 3127, 3128, 3336, 1306, 4661, 2291, 1097, 4414, 3667, 5262, 3559, 3560, 2292, 2293, 1098, 2541, 2294, 3561, 4240, 3562, 5263, 2295, 5264, 3668, 2542, 2296, 2543, 3563, 3129, 2743, 1307, 4662, 3130, 781, 2297, 2298, 4663, 2299, 2300, 1308, 2301, 5265, 3564, 4241, 2744, 3815, 1309, 4664, 2745, 3131, 1310, 2302, 2303, 4665, 5266, 2304, 3337, 4242, 3132, 3133, 3134, 4666, 2305, 5267, 3135, 3338, 2746, 110, 2306, 2307, 111, 2308, 561, 4243, 3136, 2747, 2748, 3816, 2749, 2750, 1311, 3669, 2309, 5268, 3339, 2751, 2752, 870, 3817, 4667, 4668, 2310, 3565, 3340, 2311, 4244, 4245, 4246, 562, 2312, 2313, 4247, 4248, 3566, 3567, 1466, 1467, 5269, 5270, 2753, 3818, 4249, 3670, 1468, 4250, 1312, 5271, 2754, 3137, 1469, 2755, 3568, 4251, 2314, 3341, 5272, 4669, 3569, 4252, 4670, 1313, 1099, 782, 3570, 112, 1314, 4415, 1100, 5273, 4253, 2756, 3138, 5274, 4254, 4255, 4671, 4256, 871, 1315, 3139, 3819, 5275, 3571, 4672, 563, 4257, 2757, 5425, 2315, 1101, 3572, 3820, 2544, 4394, 3140, 4673, 1102, 3573, 5554, 113, 114, 4258, 1103, 5276, 4259, 192, 3821, 3822, 5277, 1316, 3671, 1470, 4260, 2316, 4261, 4674, 4262, 3141, 3142, 3143, 3574, 2317, 4263, 5278, 1317, 2318, 3823, 1318, 1319, 3575, 1320, 2319, 5279, 2320, 872, 5555, 115, 5280, 3144, 2321, 2545, 5281, 2322, 2758, 3672, 2323, 4264, 2324, 2325, 2326, 564, 2327, 2328, 5556, 193, 2759, 4265, 1104, 5282, 2329, 2330, 3145, 3824, 2331, 4266, 4267, 5557, 4268, 4269, 3825, 5283, 2332, 2760, 4270, 1321, 3342, 2761, 565, 1471, 4271, 3146, 2333, 2546, 3673, 4272, 3674, 3147, 4273, 5284, 2334, 5285, 2335, 566, 116, 1322, 567, 3148, 4675, 568, 4676, 569, 4677, 5286, 3576, 570, 3577, 4274, 4275, 4276, 4277, 1557, 2336, 18, 1323, 2337, 1105, 2338, 3826, 2339, 3827, 19, 2340, 2547, 1324, 2341, 783, 117, 784, 4278, 3149, 571, 2342, 2343, 2344, 4279, 572, 4280, 2345, 4395, 4281, 2346, 3675, 873, 4678, 5287, 2347, 2762, 3828, 2763, 2348, 3829, 3830, 137, 573, 2349, 2350, 574, 2764, 5288, 3831, 1472, 575, 2765, 3343, 5289, 2351, 1325, 1106, 2352, 3150, 2353, 2766, 576, 3832, 3833, 3344, 2354, 577, 3151, 3345, 3152, 4282, 4283, 2767, 5290, 5291, 4284, 2355, 1558, 2356, 4285, 3834, 5292, 4679, 1559, 3578, 3676, 1107, 5558, 4286, 2357, 5293, 194, 2358, 5426, 2359, 3579, 578, 1108, 2360, 3580, 4287, 1473, 3153, 3346, 5427, 1109, 579, 580, 1326, 3835, 5559, 581, 4288, 2768, 785, 2361, 5294, 3581, 2769, 2770, 4289, 2362, 3347, 786, 4680, 1560, 874, 5295, 1474, 2771, 2548, 2772, 582, 5560, 1327, 1328, 5296, 4681, 3154, 5297, 2773, 3677, 3348, 3582, 5298, 5299, 4290, 1475, 5300, 195, 5301, 3349, 5302, 5561, 583, 3836, 2363, 787, 3350, 3351, 5303, 2774, 1561, 5304, 5562, 5305, 2549, 4682, 2364, 5563, 3837, 5306, 5564, 3352, 3155, 5307, 3156, 788, 3583, 5308, 3838, 4683, 1476, 3678, 584, 118, 3584, 585, 586, 2365, 196, 3157, 4291, 4292, 587, 2775, 4293, 2366, 3158, 2367, 5309, 588, 5310, 1477, 4294, 2368, 5311, 1110, 119, 4295, 5312, 3353, 5313, 5314, 4296, 1562, 5315, 20, 789, 138, 5316, 2369, 1329, 5317, 790, 5318, 2776, 4297, 197, 2777, 589, 3159, 2370, 4396, 791, 5319, 3160, 5428, 3839, 3840, 4298, 2778, 590, 5320, 591, 2371, 592, 120, 1563, 3585, 1111, 3679, 3354, 1112, 2550, 3161, 4299, 593, 3355, 1478, 3162, 3163, 5321, 2551, 1479, 4300, 4397, 792, 3164, 3841, 3842, 5322, 4684, 4685, 3165, 3356, 3843, 4686, 1330, 4687, 4688, 5323, 1331, 2372, 4301, 2373, 4302, 2374, 5429, 5565, 5566, 2375, 2376, 2377, 3166, 5430, 3167, 2378, 2552, 198, 3357, 1480, 4303, 5324, 4304, 5325, 3844, 5326, 2553, 3358, 121, 2554, 793, 3680, 4305, 4306, 594, 5327, 4307, 4689, 3168, 4308, 2379, 4309, 4310, 4311, 5328, 1564, 2380, 4312, 4313, 2381, 1113, 3681, 4690, 4691, 4692, 1114, 3359, 4314, 2779, 3360, 4315, 3845, 1332, 1115, 4693, 4694, 595, 2555, 4316, 2556, 1333, 5329, 2382, 4695, 4317, 3169, 3170, 1334, 5330, 2383, 3361, 4318, 4319, 4320, 4321, 3362, 3171, 5331, 5567, 5568, 1335, 1336, 5332, 2384, 5333, 4322, 794, 1116, 1117, 3172, 4696, 2385, 1337, 199, 596, 2386, 2387, 597, 598, 795, 2388, 5334, 599, 5335, 2389, 2390, 5336, 3173, 4323, 5337, 600, 4416, 1118, 2780, 2557, 796, 3846, 5431, 601, 2391, 2781, 797, 3174, 602, 2392, 3586, 4324, 3175, 2393, 4697, 1481, 122, 5338, 3176, 4325, 3847, 3177, 603, 5339, 1338, 5340, 1119, 1120, 2394, 2558, 4698, 798, 2395, 200, 604, 3587, 2396, 201, 4326, 799, 4398, 4699, 5341, 4700, 1121, 605, 4327, 1482, 4399, 4400, 4328, 4329, 4330, 606, 3682, 3588, 607, 5342, 5343, 5344, 1122, 4331, 4701, 4702, 5345, 2397, 875, 2398, 4703, 1339, 2399, 5346, 5347, 2400, 1123, 2401, 800, 3683, 2782, 3848, 801, 3589, 2402, 608, 609, 1483, 3590, 610, 5348, 611, 2403, 3684, 2404, 4332, 876, 3849, 3178, 3363, 1484, 612, 3850, 4333, 5349, 3179, 3591, 4334, 3364, 2405, 3180, 613, 2406, 2407, 2408, 3365, 3366, 2409, 4335, 4336, 4337, 877, 1340, 1124, 3367, 4338, 1565, 1125, 123, 2410, 3851, 802, 4339, 4704, 4705, 2411, 2783, 2559, 1485, 1126, 3852, 4340, 4341, 4342, 3592, 4343, 1341, 878, 1127, 1486, 879, 880, 4401, 5350, 5351, 2412, 2413, 2414, 2415, 3181, 2416, 2560, 4344, 5352, 4345, 4346, 2784, 4706, 881, 5353, 614, 4347, 3368, 139, 1342, 2561, 3182, 1343, 2417, 3685, 5354, 5355, 615, 3593, 5569, 616, 2418, 3183, 617, 4348, 4707, 5570, 3184, 4349, 4708, 21, 4709, 4710, 3369, 2562, 618, 2785, 5356, 1344, 4711 }); + + private static string[][] MunicipalitiesRows() + { + var rows = new string[5571][]; + MunicipalitiesRows0(rows); + MunicipalitiesRows1(rows); + MunicipalitiesRows2(rows); + MunicipalitiesRows3(rows); + MunicipalitiesRows4(rows); + MunicipalitiesRows5(rows); + MunicipalitiesRows6(rows); + MunicipalitiesRows7(rows); + MunicipalitiesRows8(rows); + MunicipalitiesRows9(rows); + MunicipalitiesRows10(rows); + MunicipalitiesRows11(rows); + MunicipalitiesRows12(rows); + MunicipalitiesRows13(rows); + MunicipalitiesRows14(rows); + MunicipalitiesRows15(rows); + MunicipalitiesRows16(rows); + MunicipalitiesRows17(rows); + MunicipalitiesRows18(rows); + MunicipalitiesRows19(rows); + MunicipalitiesRows20(rows); + MunicipalitiesRows21(rows); + MunicipalitiesRows22(rows); + MunicipalitiesRows23(rows); + MunicipalitiesRows24(rows); + MunicipalitiesRows25(rows); + MunicipalitiesRows26(rows); + MunicipalitiesRows27(rows); + return rows; + } + + private static void MunicipalitiesRows0(string[][] rows) + { + rows[0] = new[] { "AC", "Acrel\u00e2ndia", "1200013" }; + rows[1] = new[] { "AC", "Assis Brasil", "1200054" }; + rows[2] = new[] { "AC", "Brasil\u00e9ia", "1200104" }; + rows[3] = new[] { "AC", "Bujari", "1200138" }; + rows[4] = new[] { "AC", "Capixaba", "1200179" }; + rows[5] = new[] { "AC", "Cruzeiro do Sul", "1200203" }; + rows[6] = new[] { "AC", "Epitaciol\u00e2ndia", "1200252" }; + rows[7] = new[] { "AC", "Feij\u00f3", "1200302" }; + rows[8] = new[] { "AC", "Jord\u00e3o", "1200328" }; + rows[9] = new[] { "AC", "M\u00e2ncio Lima", "1200336" }; + rows[10] = new[] { "AC", "Manoel Urbano", "1200344" }; + rows[11] = new[] { "AC", "Marechal Thaumaturgo", "1200351" }; + rows[12] = new[] { "AC", "Pl\u00e1cido de Castro", "1200385" }; + rows[13] = new[] { "AC", "Porto Acre", "1200807" }; + rows[14] = new[] { "AC", "Porto Walter", "1200393" }; + rows[15] = new[] { "AC", "Rio Branco", "1200401" }; + rows[16] = new[] { "AC", "Rodrigues Alves", "1200427" }; + rows[17] = new[] { "AC", "Santa Rosa do Purus", "1200435" }; + rows[18] = new[] { "AC", "Sena Madureira", "1200500" }; + rows[19] = new[] { "AC", "Senador Guiomard", "1200450" }; + rows[20] = new[] { "AC", "Tarauac\u00e1", "1200609" }; + rows[21] = new[] { "AC", "Xapuri", "1200708" }; + rows[22] = new[] { "AL", "\u00c1gua Branca", "2700102" }; + rows[23] = new[] { "AL", "Anadia", "2700201" }; + rows[24] = new[] { "AL", "Arapiraca", "2700300" }; + rows[25] = new[] { "AL", "Atalaia", "2700409" }; + rows[26] = new[] { "AL", "Barra de Santo Ant\u00f4nio", "2700508" }; + rows[27] = new[] { "AL", "Barra de S\u00e3o Miguel", "2700607" }; + rows[28] = new[] { "AL", "Batalha", "2700706" }; + rows[29] = new[] { "AL", "Bel\u00e9m", "2700805" }; + rows[30] = new[] { "AL", "Belo Monte", "2700904" }; + rows[31] = new[] { "AL", "Boca da Mata", "2701001" }; + rows[32] = new[] { "AL", "Branquinha", "2701100" }; + rows[33] = new[] { "AL", "Cacimbinhas", "2701209" }; + rows[34] = new[] { "AL", "Cajueiro", "2701308" }; + rows[35] = new[] { "AL", "Campestre", "2701357" }; + rows[36] = new[] { "AL", "Campo Alegre", "2701407" }; + rows[37] = new[] { "AL", "Campo Grande", "2701506" }; + rows[38] = new[] { "AL", "Canapi", "2701605" }; + rows[39] = new[] { "AL", "Capela", "2701704" }; + rows[40] = new[] { "AL", "Carneiros", "2701803" }; + rows[41] = new[] { "AL", "Ch\u00e3 Preta", "2701902" }; + rows[42] = new[] { "AL", "Coit\u00e9 do N\u00f3ia", "2702009" }; + rows[43] = new[] { "AL", "Col\u00f4nia Leopoldina", "2702108" }; + rows[44] = new[] { "AL", "Coqueiro Seco", "2702207" }; + rows[45] = new[] { "AL", "Coruripe", "2702306" }; + rows[46] = new[] { "AL", "Cra\u00edbas", "2702355" }; + rows[47] = new[] { "AL", "Delmiro Gouveia", "2702405" }; + rows[48] = new[] { "AL", "Dois Riachos", "2702504" }; + rows[49] = new[] { "AL", "Estrela de Alagoas", "2702553" }; + rows[50] = new[] { "AL", "Feira Grande", "2702603" }; + rows[51] = new[] { "AL", "Feliz Deserto", "2702702" }; + rows[52] = new[] { "AL", "Flexeiras", "2702801" }; + rows[53] = new[] { "AL", "Girau do Ponciano", "2702900" }; + rows[54] = new[] { "AL", "Ibateguara", "2703007" }; + rows[55] = new[] { "AL", "Igaci", "2703106" }; + rows[56] = new[] { "AL", "Igreja Nova", "2703205" }; + rows[57] = new[] { "AL", "Inhapi", "2703304" }; + rows[58] = new[] { "AL", "Jacar\u00e9 dos Homens", "2703403" }; + rows[59] = new[] { "AL", "Jacu\u00edpe", "2703502" }; + rows[60] = new[] { "AL", "Japaratinga", "2703601" }; + rows[61] = new[] { "AL", "Jaramataia", "2703700" }; + rows[62] = new[] { "AL", "Jequi\u00e1 da Praia", "2703759" }; + rows[63] = new[] { "AL", "Joaquim Gomes", "2703809" }; + rows[64] = new[] { "AL", "Jundi\u00e1", "2703908" }; + rows[65] = new[] { "AL", "Junqueiro", "2704005" }; + rows[66] = new[] { "AL", "Lagoa da Canoa", "2704104" }; + rows[67] = new[] { "AL", "Limoeiro de Anadia", "2704203" }; + rows[68] = new[] { "AL", "Macei\u00f3", "2704302" }; + rows[69] = new[] { "AL", "Major Isidoro", "2704401" }; + rows[70] = new[] { "AL", "Mar Vermelho", "2704906" }; + rows[71] = new[] { "AL", "Maragogi", "2704500" }; + rows[72] = new[] { "AL", "Maravilha", "2704609" }; + rows[73] = new[] { "AL", "Marechal Deodoro", "2704708" }; + rows[74] = new[] { "AL", "Maribondo", "2704807" }; + rows[75] = new[] { "AL", "Mata Grande", "2705002" }; + rows[76] = new[] { "AL", "Matriz de Camaragibe", "2705101" }; + rows[77] = new[] { "AL", "Messias", "2705200" }; + rows[78] = new[] { "AL", "Minador do Negr\u00e3o", "2705309" }; + rows[79] = new[] { "AL", "Monteir\u00f3polis", "2705408" }; + rows[80] = new[] { "AL", "Murici", "2705507" }; + rows[81] = new[] { "AL", "Novo Lino", "2705606" }; + rows[82] = new[] { "AL", "Olho d'\u00c1gua das Flores", "2705705" }; + rows[83] = new[] { "AL", "Olho d'\u00c1gua do Casado", "2705804" }; + rows[84] = new[] { "AL", "Olho d'\u00c1gua Grande", "2705903" }; + rows[85] = new[] { "AL", "Oliven\u00e7a", "2706000" }; + rows[86] = new[] { "AL", "Ouro Branco", "2706109" }; + rows[87] = new[] { "AL", "Palestina", "2706208" }; + rows[88] = new[] { "AL", "Palmeira dos \u00cdndios", "2706307" }; + rows[89] = new[] { "AL", "P\u00e3o de A\u00e7\u00facar", "2706406" }; + rows[90] = new[] { "AL", "Pariconha", "2706422" }; + rows[91] = new[] { "AL", "Paripueira", "2706448" }; + rows[92] = new[] { "AL", "Passo de Camaragibe", "2706505" }; + rows[93] = new[] { "AL", "Paulo Jacinto", "2706604" }; + rows[94] = new[] { "AL", "Penedo", "2706703" }; + rows[95] = new[] { "AL", "Pia\u00e7abu\u00e7u", "2706802" }; + rows[96] = new[] { "AL", "Pilar", "2706901" }; + rows[97] = new[] { "AL", "Pindoba", "2707008" }; + rows[98] = new[] { "AL", "Piranhas", "2707107" }; + rows[99] = new[] { "AL", "Po\u00e7o das Trincheiras", "2707206" }; + rows[100] = new[] { "AL", "Porto Calvo", "2707305" }; + rows[101] = new[] { "AL", "Porto de Pedras", "2707404" }; + rows[102] = new[] { "AL", "Porto Real do Col\u00e9gio", "2707503" }; + rows[103] = new[] { "AL", "Quebrangulo", "2707602" }; + rows[104] = new[] { "AL", "Rio Largo", "2707701" }; + rows[105] = new[] { "AL", "Roteiro", "2707800" }; + rows[106] = new[] { "AL", "Santa Luzia do Norte", "2707909" }; + rows[107] = new[] { "AL", "Santana do Ipanema", "2708006" }; + rows[108] = new[] { "AL", "Santana do Munda\u00fa", "2708105" }; + rows[109] = new[] { "AL", "S\u00e3o Br\u00e1s", "2708204" }; + rows[110] = new[] { "AL", "S\u00e3o Jos\u00e9 da Laje", "2708303" }; + rows[111] = new[] { "AL", "S\u00e3o Jos\u00e9 da Tapera", "2708402" }; + rows[112] = new[] { "AL", "S\u00e3o Lu\u00eds do Quitunde", "2708501" }; + rows[113] = new[] { "AL", "S\u00e3o Miguel dos Campos", "2708600" }; + rows[114] = new[] { "AL", "S\u00e3o Miguel dos Milagres", "2708709" }; + rows[115] = new[] { "AL", "S\u00e3o Sebasti\u00e3o", "2708808" }; + rows[116] = new[] { "AL", "Satuba", "2708907" }; + rows[117] = new[] { "AL", "Senador Rui Palmeira", "2708956" }; + rows[118] = new[] { "AL", "Tanque d'Arca", "2709004" }; + rows[119] = new[] { "AL", "Taquarana", "2709103" }; + rows[120] = new[] { "AL", "Teot\u00f4nio Vilela", "2709152" }; + rows[121] = new[] { "AL", "Traipu", "2709202" }; + rows[122] = new[] { "AL", "Uni\u00e3o dos Palmares", "2709301" }; + rows[123] = new[] { "AL", "Vi\u00e7osa", "2709400" }; + rows[124] = new[] { "AP", "Amap\u00e1", "1600105" }; + rows[125] = new[] { "AP", "Cal\u00e7oene", "1600204" }; + rows[126] = new[] { "AP", "Cutias", "1600212" }; + rows[127] = new[] { "AP", "Ferreira Gomes", "1600238" }; + rows[128] = new[] { "AP", "Itaubal", "1600253" }; + rows[129] = new[] { "AP", "Laranjal do Jari", "1600279" }; + rows[130] = new[] { "AP", "Macap\u00e1", "1600303" }; + rows[131] = new[] { "AP", "Mazag\u00e3o", "1600402" }; + rows[132] = new[] { "AP", "Oiapoque", "1600501" }; + rows[133] = new[] { "AP", "Pedra Branca do Amapari", "1600154" }; + rows[134] = new[] { "AP", "Porto Grande", "1600535" }; + rows[135] = new[] { "AP", "Pracu\u00faba", "1600550" }; + rows[136] = new[] { "AP", "Santana", "1600600" }; + rows[137] = new[] { "AP", "Serra do Navio", "1600055" }; + rows[138] = new[] { "AP", "Tartarugalzinho", "1600709" }; + rows[139] = new[] { "AP", "Vit\u00f3ria do Jari", "1600808" }; + rows[140] = new[] { "AM", "Alvar\u00e3es", "1300029" }; + rows[141] = new[] { "AM", "Amatur\u00e1", "1300060" }; + rows[142] = new[] { "AM", "Anam\u00e3", "1300086" }; + rows[143] = new[] { "AM", "Anori", "1300102" }; + rows[144] = new[] { "AM", "Apu\u00ed", "1300144" }; + rows[145] = new[] { "AM", "Atalaia do Norte", "1300201" }; + rows[146] = new[] { "AM", "Autazes", "1300300" }; + rows[147] = new[] { "AM", "Barcelos", "1300409" }; + rows[148] = new[] { "AM", "Barreirinha", "1300508" }; + rows[149] = new[] { "AM", "Benjamin Constant", "1300607" }; + rows[150] = new[] { "AM", "Beruri", "1300631" }; + rows[151] = new[] { "AM", "Boa Vista do Ramos", "1300680" }; + rows[152] = new[] { "AM", "Boca do Acre", "1300706" }; + rows[153] = new[] { "AM", "Borba", "1300805" }; + rows[154] = new[] { "AM", "Caapiranga", "1300839" }; + rows[155] = new[] { "AM", "Canutama", "1300904" }; + rows[156] = new[] { "AM", "Carauari", "1301001" }; + rows[157] = new[] { "AM", "Careiro", "1301100" }; + rows[158] = new[] { "AM", "Careiro da V\u00e1rzea", "1301159" }; + rows[159] = new[] { "AM", "Coari", "1301209" }; + rows[160] = new[] { "AM", "Codaj\u00e1s", "1301308" }; + rows[161] = new[] { "AM", "Eirunep\u00e9", "1301407" }; + rows[162] = new[] { "AM", "Envira", "1301506" }; + rows[163] = new[] { "AM", "Fonte Boa", "1301605" }; + rows[164] = new[] { "AM", "Guajar\u00e1", "1301654" }; + rows[165] = new[] { "AM", "Humait\u00e1", "1301704" }; + rows[166] = new[] { "AM", "Ipixuna", "1301803" }; + rows[167] = new[] { "AM", "Iranduba", "1301852" }; + rows[168] = new[] { "AM", "Itacoatiara", "1301902" }; + rows[169] = new[] { "AM", "Itamarati", "1301951" }; + rows[170] = new[] { "AM", "Itapiranga", "1302009" }; + rows[171] = new[] { "AM", "Japur\u00e1", "1302108" }; + rows[172] = new[] { "AM", "Juru\u00e1", "1302207" }; + rows[173] = new[] { "AM", "Juta\u00ed", "1302306" }; + rows[174] = new[] { "AM", "L\u00e1brea", "1302405" }; + rows[175] = new[] { "AM", "Manacapuru", "1302504" }; + rows[176] = new[] { "AM", "Manaquiri", "1302553" }; + rows[177] = new[] { "AM", "Manaus", "1302603" }; + rows[178] = new[] { "AM", "Manicor\u00e9", "1302702" }; + rows[179] = new[] { "AM", "Mara\u00e3", "1302801" }; + rows[180] = new[] { "AM", "Mau\u00e9s", "1302900" }; + rows[181] = new[] { "AM", "Nhamund\u00e1", "1303007" }; + rows[182] = new[] { "AM", "Nova Olinda do Norte", "1303106" }; + rows[183] = new[] { "AM", "Novo Air\u00e3o", "1303205" }; + rows[184] = new[] { "AM", "Novo Aripuan\u00e3", "1303304" }; + rows[185] = new[] { "AM", "Parintins", "1303403" }; + rows[186] = new[] { "AM", "Pauini", "1303502" }; + rows[187] = new[] { "AM", "Presidente Figueiredo", "1303536" }; + rows[188] = new[] { "AM", "Rio Preto da Eva", "1303569" }; + rows[189] = new[] { "AM", "Santa Isabel do Rio Negro", "1303601" }; + rows[190] = new[] { "AM", "Santo Ant\u00f4nio do I\u00e7\u00e1", "1303700" }; + rows[191] = new[] { "AM", "S\u00e3o Gabriel da Cachoeira", "1303809" }; + rows[192] = new[] { "AM", "S\u00e3o Paulo de Oliven\u00e7a", "1303908" }; + rows[193] = new[] { "AM", "S\u00e3o Sebasti\u00e3o do Uatum\u00e3", "1303957" }; + rows[194] = new[] { "AM", "Silves", "1304005" }; + rows[195] = new[] { "AM", "Tabatinga", "1304062" }; + rows[196] = new[] { "AM", "Tapau\u00e1", "1304104" }; + rows[197] = new[] { "AM", "Tef\u00e9", "1304203" }; + rows[198] = new[] { "AM", "Tonantins", "1304237" }; + rows[199] = new[] { "AM", "Uarini", "1304260" }; + } + + private static void MunicipalitiesRows1(string[][] rows) + { + rows[200] = new[] { "AM", "Urucar\u00e1", "1304302" }; + rows[201] = new[] { "AM", "Urucurituba", "1304401" }; + rows[202] = new[] { "BA", "Aba\u00edra", "2900108" }; + rows[203] = new[] { "BA", "Abar\u00e9", "2900207" }; + rows[204] = new[] { "BA", "Acajutiba", "2900306" }; + rows[205] = new[] { "BA", "Adustina", "2900355" }; + rows[206] = new[] { "BA", "\u00c1gua Fria", "2900405" }; + rows[207] = new[] { "BA", "Aiquara", "2900603" }; + rows[208] = new[] { "BA", "Alagoinhas", "2900702" }; + rows[209] = new[] { "BA", "Alcoba\u00e7a", "2900801" }; + rows[210] = new[] { "BA", "Almadina", "2900900" }; + rows[211] = new[] { "BA", "Amargosa", "2901007" }; + rows[212] = new[] { "BA", "Am\u00e9lia Rodrigues", "2901106" }; + rows[213] = new[] { "BA", "Am\u00e9rica Dourada", "2901155" }; + rows[214] = new[] { "BA", "Anag\u00e9", "2901205" }; + rows[215] = new[] { "BA", "Andara\u00ed", "2901304" }; + rows[216] = new[] { "BA", "Andorinha", "2901353" }; + rows[217] = new[] { "BA", "Angical", "2901403" }; + rows[218] = new[] { "BA", "Anguera", "2901502" }; + rows[219] = new[] { "BA", "Antas", "2901601" }; + rows[220] = new[] { "BA", "Ant\u00f4nio Cardoso", "2901700" }; + rows[221] = new[] { "BA", "Ant\u00f4nio Gon\u00e7alves", "2901809" }; + rows[222] = new[] { "BA", "Apor\u00e1", "2901908" }; + rows[223] = new[] { "BA", "Apuarema", "2901957" }; + rows[224] = new[] { "BA", "Ara\u00e7\u00e1s", "2902054" }; + rows[225] = new[] { "BA", "Aracatu", "2902005" }; + rows[226] = new[] { "BA", "Araci", "2902104" }; + rows[227] = new[] { "BA", "Aramari", "2902203" }; + rows[228] = new[] { "BA", "Arataca", "2902252" }; + rows[229] = new[] { "BA", "Aratu\u00edpe", "2902302" }; + rows[230] = new[] { "BA", "Aurelino Leal", "2902401" }; + rows[231] = new[] { "BA", "Baian\u00f3polis", "2902500" }; + rows[232] = new[] { "BA", "Baixa Grande", "2902609" }; + rows[233] = new[] { "BA", "Banza\u00ea", "2902658" }; + rows[234] = new[] { "BA", "Barra", "2902708" }; + rows[235] = new[] { "BA", "Barra da Estiva", "2902807" }; + rows[236] = new[] { "BA", "Barra do Cho\u00e7a", "2902906" }; + rows[237] = new[] { "BA", "Barra do Mendes", "2903003" }; + rows[238] = new[] { "BA", "Barra do Rocha", "2903102" }; + rows[239] = new[] { "BA", "Barreiras", "2903201" }; + rows[240] = new[] { "BA", "Barro Alto", "2903235" }; + rows[241] = new[] { "BA", "Barro Preto", "2903300" }; + rows[242] = new[] { "BA", "Barrocas", "2903276" }; + rows[243] = new[] { "BA", "Belmonte", "2903409" }; + rows[244] = new[] { "BA", "Belo Campo", "2903508" }; + rows[245] = new[] { "BA", "Biritinga", "2903607" }; + rows[246] = new[] { "BA", "Boa Nova", "2903706" }; + rows[247] = new[] { "BA", "Boa Vista do Tupim", "2903805" }; + rows[248] = new[] { "BA", "Bom Jesus da Lapa", "2903904" }; + rows[249] = new[] { "BA", "Bom Jesus da Serra", "2903953" }; + rows[250] = new[] { "BA", "Boninal", "2904001" }; + rows[251] = new[] { "BA", "Bonito", "2904050" }; + rows[252] = new[] { "BA", "Boquira", "2904100" }; + rows[253] = new[] { "BA", "Botupor\u00e3", "2904209" }; + rows[254] = new[] { "BA", "Brej\u00f5es", "2904308" }; + rows[255] = new[] { "BA", "Brejol\u00e2ndia", "2904407" }; + rows[256] = new[] { "BA", "Brotas de Maca\u00fabas", "2904506" }; + rows[257] = new[] { "BA", "Brumado", "2904605" }; + rows[258] = new[] { "BA", "Buerarema", "2904704" }; + rows[259] = new[] { "BA", "Buritirama", "2904753" }; + rows[260] = new[] { "BA", "Caatiba", "2904803" }; + rows[261] = new[] { "BA", "Cabaceiras do Paragua\u00e7u", "2904852" }; + rows[262] = new[] { "BA", "Cachoeira", "2904902" }; + rows[263] = new[] { "BA", "Cacul\u00e9", "2905008" }; + rows[264] = new[] { "BA", "Ca\u00e9m", "2905107" }; + rows[265] = new[] { "BA", "Caetanos", "2905156" }; + rows[266] = new[] { "BA", "Caetit\u00e9", "2905206" }; + rows[267] = new[] { "BA", "Cafarnaum", "2905305" }; + rows[268] = new[] { "BA", "Cairu", "2905404" }; + rows[269] = new[] { "BA", "Caldeir\u00e3o Grande", "2905503" }; + rows[270] = new[] { "BA", "Camacan", "2905602" }; + rows[271] = new[] { "BA", "Cama\u00e7ari", "2905701" }; + rows[272] = new[] { "BA", "Camamu", "2905800" }; + rows[273] = new[] { "BA", "Campo Alegre de Lourdes", "2905909" }; + rows[274] = new[] { "BA", "Campo Formoso", "2906006" }; + rows[275] = new[] { "BA", "Can\u00e1polis", "2906105" }; + rows[276] = new[] { "BA", "Canarana", "2906204" }; + rows[277] = new[] { "BA", "Canavieiras", "2906303" }; + rows[278] = new[] { "BA", "Candeal", "2906402" }; + rows[279] = new[] { "BA", "Candeias", "2906501" }; + rows[280] = new[] { "BA", "Candiba", "2906600" }; + rows[281] = new[] { "BA", "C\u00e2ndido Sales", "2906709" }; + rows[282] = new[] { "BA", "Cansan\u00e7\u00e3o", "2906808" }; + rows[283] = new[] { "BA", "Canudos", "2906824" }; + rows[284] = new[] { "BA", "Capela do Alto Alegre", "2906857" }; + rows[285] = new[] { "BA", "Capim Grosso", "2906873" }; + rows[286] = new[] { "BA", "Cara\u00edbas", "2906899" }; + rows[287] = new[] { "BA", "Caravelas", "2906907" }; + rows[288] = new[] { "BA", "Cardeal da Silva", "2907004" }; + rows[289] = new[] { "BA", "Carinhanha", "2907103" }; + rows[290] = new[] { "BA", "Casa Nova", "2907202" }; + rows[291] = new[] { "BA", "Castro Alves", "2907301" }; + rows[292] = new[] { "BA", "Catol\u00e2ndia", "2907400" }; + rows[293] = new[] { "BA", "Catu", "2907509" }; + rows[294] = new[] { "BA", "Caturama", "2907558" }; + rows[295] = new[] { "BA", "Central", "2907608" }; + rows[296] = new[] { "BA", "Chorroch\u00f3", "2907707" }; + rows[297] = new[] { "BA", "C\u00edcero Dantas", "2907806" }; + rows[298] = new[] { "BA", "Cip\u00f3", "2907905" }; + rows[299] = new[] { "BA", "Coaraci", "2908002" }; + rows[300] = new[] { "BA", "Cocos", "2908101" }; + rows[301] = new[] { "BA", "Concei\u00e7\u00e3o da Feira", "2908200" }; + rows[302] = new[] { "BA", "Concei\u00e7\u00e3o do Almeida", "2908309" }; + rows[303] = new[] { "BA", "Concei\u00e7\u00e3o do Coit\u00e9", "2908408" }; + rows[304] = new[] { "BA", "Concei\u00e7\u00e3o do Jacu\u00edpe", "2908507" }; + rows[305] = new[] { "BA", "Conde", "2908606" }; + rows[306] = new[] { "BA", "Conde\u00faba", "2908705" }; + rows[307] = new[] { "BA", "Contendas do Sincor\u00e1", "2908804" }; + rows[308] = new[] { "BA", "Cora\u00e7\u00e3o de Maria", "2908903" }; + rows[309] = new[] { "BA", "Cordeiros", "2909000" }; + rows[310] = new[] { "BA", "Coribe", "2909109" }; + rows[311] = new[] { "BA", "Coronel Jo\u00e3o S\u00e1", "2909208" }; + rows[312] = new[] { "BA", "Correntina", "2909307" }; + rows[313] = new[] { "BA", "Cotegipe", "2909406" }; + rows[314] = new[] { "BA", "Cravol\u00e2ndia", "2909505" }; + rows[315] = new[] { "BA", "Cris\u00f3polis", "2909604" }; + rows[316] = new[] { "BA", "Crist\u00f3polis", "2909703" }; + rows[317] = new[] { "BA", "Cruz das Almas", "2909802" }; + rows[318] = new[] { "BA", "Cura\u00e7\u00e1", "2909901" }; + rows[319] = new[] { "BA", "D\u00e1rio Meira", "2910008" }; + rows[320] = new[] { "BA", "Dias d'\u00c1vila", "2910057" }; + rows[321] = new[] { "BA", "Dom Bas\u00edlio", "2910107" }; + rows[322] = new[] { "BA", "Dom Macedo Costa", "2910206" }; + rows[323] = new[] { "BA", "El\u00edsio Medrado", "2910305" }; + rows[324] = new[] { "BA", "Encruzilhada", "2910404" }; + rows[325] = new[] { "BA", "Entre Rios", "2910503" }; + rows[326] = new[] { "BA", "\u00c9rico Cardoso", "2900504" }; + rows[327] = new[] { "BA", "Esplanada", "2910602" }; + rows[328] = new[] { "BA", "Euclides da Cunha", "2910701" }; + rows[329] = new[] { "BA", "Eun\u00e1polis", "2910727" }; + rows[330] = new[] { "BA", "F\u00e1tima", "2910750" }; + rows[331] = new[] { "BA", "Feira da Mata", "2910776" }; + rows[332] = new[] { "BA", "Feira de Santana", "2910800" }; + rows[333] = new[] { "BA", "Filad\u00e9lfia", "2910859" }; + rows[334] = new[] { "BA", "Firmino Alves", "2910909" }; + rows[335] = new[] { "BA", "Floresta Azul", "2911006" }; + rows[336] = new[] { "BA", "Formosa do Rio Preto", "2911105" }; + rows[337] = new[] { "BA", "Gandu", "2911204" }; + rows[338] = new[] { "BA", "Gavi\u00e3o", "2911253" }; + rows[339] = new[] { "BA", "Gentio do Ouro", "2911303" }; + rows[340] = new[] { "BA", "Gl\u00f3ria", "2911402" }; + rows[341] = new[] { "BA", "Gongogi", "2911501" }; + rows[342] = new[] { "BA", "Governador Mangabeira", "2911600" }; + rows[343] = new[] { "BA", "Guajeru", "2911659" }; + rows[344] = new[] { "BA", "Guanambi", "2911709" }; + rows[345] = new[] { "BA", "Guaratinga", "2911808" }; + rows[346] = new[] { "BA", "Heli\u00f3polis", "2911857" }; + rows[347] = new[] { "BA", "Ia\u00e7u", "2911907" }; + rows[348] = new[] { "BA", "Ibiassuc\u00ea", "2912004" }; + rows[349] = new[] { "BA", "Ibicara\u00ed", "2912103" }; + rows[350] = new[] { "BA", "Ibicoara", "2912202" }; + rows[351] = new[] { "BA", "Ibicu\u00ed", "2912301" }; + rows[352] = new[] { "BA", "Ibipeba", "2912400" }; + rows[353] = new[] { "BA", "Ibipitanga", "2912509" }; + rows[354] = new[] { "BA", "Ibiquera", "2912608" }; + rows[355] = new[] { "BA", "Ibirapitanga", "2912707" }; + rows[356] = new[] { "BA", "Ibirapu\u00e3", "2912806" }; + rows[357] = new[] { "BA", "Ibirataia", "2912905" }; + rows[358] = new[] { "BA", "Ibitiara", "2913002" }; + rows[359] = new[] { "BA", "Ibitit\u00e1", "2913101" }; + rows[360] = new[] { "BA", "Ibotirama", "2913200" }; + rows[361] = new[] { "BA", "Ichu", "2913309" }; + rows[362] = new[] { "BA", "Igapor\u00e3", "2913408" }; + rows[363] = new[] { "BA", "Igrapi\u00fana", "2913457" }; + rows[364] = new[] { "BA", "Igua\u00ed", "2913507" }; + rows[365] = new[] { "BA", "Ilh\u00e9us", "2913606" }; + rows[366] = new[] { "BA", "Inhambupe", "2913705" }; + rows[367] = new[] { "BA", "Ipecaet\u00e1", "2913804" }; + rows[368] = new[] { "BA", "Ipia\u00fa", "2913903" }; + rows[369] = new[] { "BA", "Ipir\u00e1", "2914000" }; + rows[370] = new[] { "BA", "Ipupiara", "2914109" }; + rows[371] = new[] { "BA", "Irajuba", "2914208" }; + rows[372] = new[] { "BA", "Iramaia", "2914307" }; + rows[373] = new[] { "BA", "Iraquara", "2914406" }; + rows[374] = new[] { "BA", "Irar\u00e1", "2914505" }; + rows[375] = new[] { "BA", "Irec\u00ea", "2914604" }; + rows[376] = new[] { "BA", "Itabela", "2914653" }; + rows[377] = new[] { "BA", "Itaberaba", "2914703" }; + rows[378] = new[] { "BA", "Itabuna", "2914802" }; + rows[379] = new[] { "BA", "Itacar\u00e9", "2914901" }; + rows[380] = new[] { "BA", "Itaet\u00e9", "2915007" }; + rows[381] = new[] { "BA", "Itagi", "2915106" }; + rows[382] = new[] { "BA", "Itagib\u00e1", "2915205" }; + rows[383] = new[] { "BA", "Itagimirim", "2915304" }; + rows[384] = new[] { "BA", "Itagua\u00e7u da Bahia", "2915353" }; + rows[385] = new[] { "BA", "Itaju do Col\u00f4nia", "2915403" }; + rows[386] = new[] { "BA", "Itaju\u00edpe", "2915502" }; + rows[387] = new[] { "BA", "Itamaraju", "2915601" }; + rows[388] = new[] { "BA", "Itamari", "2915700" }; + rows[389] = new[] { "BA", "Itamb\u00e9", "2915809" }; + rows[390] = new[] { "BA", "Itanagra", "2915908" }; + rows[391] = new[] { "BA", "Itanh\u00e9m", "2916005" }; + rows[392] = new[] { "BA", "Itaparica", "2916104" }; + rows[393] = new[] { "BA", "Itap\u00e9", "2916203" }; + rows[394] = new[] { "BA", "Itapebi", "2916302" }; + rows[395] = new[] { "BA", "Itapetinga", "2916401" }; + rows[396] = new[] { "BA", "Itapicuru", "2916500" }; + rows[397] = new[] { "BA", "Itapitanga", "2916609" }; + rows[398] = new[] { "BA", "Itaquara", "2916708" }; + rows[399] = new[] { "BA", "Itarantim", "2916807" }; + } + + private static void MunicipalitiesRows2(string[][] rows) + { + rows[400] = new[] { "BA", "Itatim", "2916856" }; + rows[401] = new[] { "BA", "Itiru\u00e7u", "2916906" }; + rows[402] = new[] { "BA", "Iti\u00faba", "2917003" }; + rows[403] = new[] { "BA", "Itoror\u00f3", "2917102" }; + rows[404] = new[] { "BA", "Itua\u00e7u", "2917201" }; + rows[405] = new[] { "BA", "Ituber\u00e1", "2917300" }; + rows[406] = new[] { "BA", "Iuiu", "2917334" }; + rows[407] = new[] { "BA", "Jaborandi", "2917359" }; + rows[408] = new[] { "BA", "Jacaraci", "2917409" }; + rows[409] = new[] { "BA", "Jacobina", "2917508" }; + rows[410] = new[] { "BA", "Jaguaquara", "2917607" }; + rows[411] = new[] { "BA", "Jaguarari", "2917706" }; + rows[412] = new[] { "BA", "Jaguaripe", "2917805" }; + rows[413] = new[] { "BA", "Janda\u00edra", "2917904" }; + rows[414] = new[] { "BA", "Jequi\u00e9", "2918001" }; + rows[415] = new[] { "BA", "Jeremoabo", "2918100" }; + rows[416] = new[] { "BA", "Jiquiri\u00e7\u00e1", "2918209" }; + rows[417] = new[] { "BA", "Jita\u00fana", "2918308" }; + rows[418] = new[] { "BA", "Jo\u00e3o Dourado", "2918357" }; + rows[419] = new[] { "BA", "Juazeiro", "2918407" }; + rows[420] = new[] { "BA", "Jucuru\u00e7u", "2918456" }; + rows[421] = new[] { "BA", "Jussara", "2918506" }; + rows[422] = new[] { "BA", "Jussari", "2918555" }; + rows[423] = new[] { "BA", "Jussiape", "2918605" }; + rows[424] = new[] { "BA", "Lafaiete Coutinho", "2918704" }; + rows[425] = new[] { "BA", "Lagoa Real", "2918753" }; + rows[426] = new[] { "BA", "Laje", "2918803" }; + rows[427] = new[] { "BA", "Lajed\u00e3o", "2918902" }; + rows[428] = new[] { "BA", "Lajedinho", "2919009" }; + rows[429] = new[] { "BA", "Lajedo do Tabocal", "2919058" }; + rows[430] = new[] { "BA", "Lamar\u00e3o", "2919108" }; + rows[431] = new[] { "BA", "Lap\u00e3o", "2919157" }; + rows[432] = new[] { "BA", "Lauro de Freitas", "2919207" }; + rows[433] = new[] { "BA", "Len\u00e7\u00f3is", "2919306" }; + rows[434] = new[] { "BA", "Lic\u00ednio de Almeida", "2919405" }; + rows[435] = new[] { "BA", "Livramento de Nossa Senhora", "2919504" }; + rows[436] = new[] { "BA", "Lu\u00eds Eduardo Magalh\u00e3es", "2919553" }; + rows[437] = new[] { "BA", "Macajuba", "2919603" }; + rows[438] = new[] { "BA", "Macarani", "2919702" }; + rows[439] = new[] { "BA", "Maca\u00fabas", "2919801" }; + rows[440] = new[] { "BA", "Macurur\u00e9", "2919900" }; + rows[441] = new[] { "BA", "Madre de Deus", "2919926" }; + rows[442] = new[] { "BA", "Maetinga", "2919959" }; + rows[443] = new[] { "BA", "Maiquinique", "2920007" }; + rows[444] = new[] { "BA", "Mairi", "2920106" }; + rows[445] = new[] { "BA", "Malhada", "2920205" }; + rows[446] = new[] { "BA", "Malhada de Pedras", "2920304" }; + rows[447] = new[] { "BA", "Manoel Vitorino", "2920403" }; + rows[448] = new[] { "BA", "Mansid\u00e3o", "2920452" }; + rows[449] = new[] { "BA", "Marac\u00e1s", "2920502" }; + rows[450] = new[] { "BA", "Maragogipe", "2920601" }; + rows[451] = new[] { "BA", "Mara\u00fa", "2920700" }; + rows[452] = new[] { "BA", "Marcion\u00edlio Souza", "2920809" }; + rows[453] = new[] { "BA", "Mascote", "2920908" }; + rows[454] = new[] { "BA", "Mata de S\u00e3o Jo\u00e3o", "2921005" }; + rows[455] = new[] { "BA", "Matina", "2921054" }; + rows[456] = new[] { "BA", "Medeiros Neto", "2921104" }; + rows[457] = new[] { "BA", "Miguel Calmon", "2921203" }; + rows[458] = new[] { "BA", "Milagres", "2921302" }; + rows[459] = new[] { "BA", "Mirangaba", "2921401" }; + rows[460] = new[] { "BA", "Mirante", "2921450" }; + rows[461] = new[] { "BA", "Monte Santo", "2921500" }; + rows[462] = new[] { "BA", "Morpar\u00e1", "2921609" }; + rows[463] = new[] { "BA", "Morro do Chap\u00e9u", "2921708" }; + rows[464] = new[] { "BA", "Mortugaba", "2921807" }; + rows[465] = new[] { "BA", "Mucug\u00ea", "2921906" }; + rows[466] = new[] { "BA", "Mucuri", "2922003" }; + rows[467] = new[] { "BA", "Mulungu do Morro", "2922052" }; + rows[468] = new[] { "BA", "Mundo Novo", "2922102" }; + rows[469] = new[] { "BA", "Muniz Ferreira", "2922201" }; + rows[470] = new[] { "BA", "Muqu\u00e9m do S\u00e3o Francisco", "2922250" }; + rows[471] = new[] { "BA", "Muritiba", "2922300" }; + rows[472] = new[] { "BA", "Mutu\u00edpe", "2922409" }; + rows[473] = new[] { "BA", "Nazar\u00e9", "2922508" }; + rows[474] = new[] { "BA", "Nilo Pe\u00e7anha", "2922607" }; + rows[475] = new[] { "BA", "Nordestina", "2922656" }; + rows[476] = new[] { "BA", "Nova Cana\u00e3", "2922706" }; + rows[477] = new[] { "BA", "Nova F\u00e1tima", "2922730" }; + rows[478] = new[] { "BA", "Nova Ibi\u00e1", "2922755" }; + rows[479] = new[] { "BA", "Nova Itarana", "2922805" }; + rows[480] = new[] { "BA", "Nova Reden\u00e7\u00e3o", "2922854" }; + rows[481] = new[] { "BA", "Nova Soure", "2922904" }; + rows[482] = new[] { "BA", "Nova Vi\u00e7osa", "2923001" }; + rows[483] = new[] { "BA", "Novo Horizonte", "2923035" }; + rows[484] = new[] { "BA", "Novo Triunfo", "2923050" }; + rows[485] = new[] { "BA", "Olindina", "2923100" }; + rows[486] = new[] { "BA", "Oliveira dos Brejinhos", "2923209" }; + rows[487] = new[] { "BA", "Ouri\u00e7angas", "2923308" }; + rows[488] = new[] { "BA", "Ourol\u00e2ndia", "2923357" }; + rows[489] = new[] { "BA", "Palmas de Monte Alto", "2923407" }; + rows[490] = new[] { "BA", "Palmeiras", "2923506" }; + rows[491] = new[] { "BA", "Paramirim", "2923605" }; + rows[492] = new[] { "BA", "Paratinga", "2923704" }; + rows[493] = new[] { "BA", "Paripiranga", "2923803" }; + rows[494] = new[] { "BA", "Pau Brasil", "2923902" }; + rows[495] = new[] { "BA", "Paulo Afonso", "2924009" }; + rows[496] = new[] { "BA", "P\u00e9 de Serra", "2924058" }; + rows[497] = new[] { "BA", "Pedr\u00e3o", "2924108" }; + rows[498] = new[] { "BA", "Pedro Alexandre", "2924207" }; + rows[499] = new[] { "BA", "Piat\u00e3", "2924306" }; + rows[500] = new[] { "BA", "Pil\u00e3o Arcado", "2924405" }; + rows[501] = new[] { "BA", "Pinda\u00ed", "2924504" }; + rows[502] = new[] { "BA", "Pindoba\u00e7u", "2924603" }; + rows[503] = new[] { "BA", "Pintadas", "2924652" }; + rows[504] = new[] { "BA", "Pira\u00ed do Norte", "2924678" }; + rows[505] = new[] { "BA", "Pirip\u00e1", "2924702" }; + rows[506] = new[] { "BA", "Piritiba", "2924801" }; + rows[507] = new[] { "BA", "Planaltino", "2924900" }; + rows[508] = new[] { "BA", "Planalto", "2925006" }; + rows[509] = new[] { "BA", "Po\u00e7\u00f5es", "2925105" }; + rows[510] = new[] { "BA", "Pojuca", "2925204" }; + rows[511] = new[] { "BA", "Ponto Novo", "2925253" }; + rows[512] = new[] { "BA", "Porto Seguro", "2925303" }; + rows[513] = new[] { "BA", "Potiragu\u00e1", "2925402" }; + rows[514] = new[] { "BA", "Prado", "2925501" }; + rows[515] = new[] { "BA", "Presidente Dutra", "2925600" }; + rows[516] = new[] { "BA", "Presidente J\u00e2nio Quadros", "2925709" }; + rows[517] = new[] { "BA", "Presidente Tancredo Neves", "2925758" }; + rows[518] = new[] { "BA", "Queimadas", "2925808" }; + rows[519] = new[] { "BA", "Quijingue", "2925907" }; + rows[520] = new[] { "BA", "Quixabeira", "2925931" }; + rows[521] = new[] { "BA", "Rafael Jambeiro", "2925956" }; + rows[522] = new[] { "BA", "Remanso", "2926004" }; + rows[523] = new[] { "BA", "Retirol\u00e2ndia", "2926103" }; + rows[524] = new[] { "BA", "Riach\u00e3o das Neves", "2926202" }; + rows[525] = new[] { "BA", "Riach\u00e3o do Jacu\u00edpe", "2926301" }; + rows[526] = new[] { "BA", "Riacho de Santana", "2926400" }; + rows[527] = new[] { "BA", "Ribeira do Amparo", "2926509" }; + rows[528] = new[] { "BA", "Ribeira do Pombal", "2926608" }; + rows[529] = new[] { "BA", "Ribeir\u00e3o do Largo", "2926657" }; + rows[530] = new[] { "BA", "Rio de Contas", "2926707" }; + rows[531] = new[] { "BA", "Rio do Ant\u00f4nio", "2926806" }; + rows[532] = new[] { "BA", "Rio do Pires", "2926905" }; + rows[533] = new[] { "BA", "Rio Real", "2927002" }; + rows[534] = new[] { "BA", "Rodelas", "2927101" }; + rows[535] = new[] { "BA", "Ruy Barbosa", "2927200" }; + rows[536] = new[] { "BA", "Salinas da Margarida", "2927309" }; + rows[537] = new[] { "BA", "Salvador", "2927408" }; + rows[538] = new[] { "BA", "Santa B\u00e1rbara", "2927507" }; + rows[539] = new[] { "BA", "Santa Br\u00edgida", "2927606" }; + rows[540] = new[] { "BA", "Santa Cruz Cabr\u00e1lia", "2927705" }; + rows[541] = new[] { "BA", "Santa Cruz da Vit\u00f3ria", "2927804" }; + rows[542] = new[] { "BA", "Santa In\u00eas", "2927903" }; + rows[543] = new[] { "BA", "Santa Luzia", "2928059" }; + rows[544] = new[] { "BA", "Santa Maria da Vit\u00f3ria", "2928109" }; + rows[545] = new[] { "BA", "Santa Rita de C\u00e1ssia", "2928406" }; + rows[546] = new[] { "BA", "Santa Terezinha", "2928505" }; + rows[547] = new[] { "BA", "Santaluz", "2928000" }; + rows[548] = new[] { "BA", "Santana", "2928208" }; + rows[549] = new[] { "BA", "Santan\u00f3polis", "2928307" }; + rows[550] = new[] { "BA", "Santo Amaro", "2928604" }; + rows[551] = new[] { "BA", "Santo Ant\u00f4nio de Jesus", "2928703" }; + rows[552] = new[] { "BA", "Santo Est\u00eav\u00e3o", "2928802" }; + rows[553] = new[] { "BA", "S\u00e3o Desid\u00e9rio", "2928901" }; + rows[554] = new[] { "BA", "S\u00e3o Domingos", "2928950" }; + rows[555] = new[] { "BA", "S\u00e3o Felipe", "2929107" }; + rows[556] = new[] { "BA", "S\u00e3o F\u00e9lix", "2929008" }; + rows[557] = new[] { "BA", "S\u00e3o F\u00e9lix do Coribe", "2929057" }; + rows[558] = new[] { "BA", "S\u00e3o Francisco do Conde", "2929206" }; + rows[559] = new[] { "BA", "S\u00e3o Gabriel", "2929255" }; + rows[560] = new[] { "BA", "S\u00e3o Gon\u00e7alo dos Campos", "2929305" }; + rows[561] = new[] { "BA", "S\u00e3o Jos\u00e9 da Vit\u00f3ria", "2929354" }; + rows[562] = new[] { "BA", "S\u00e3o Jos\u00e9 do Jacu\u00edpe", "2929370" }; + rows[563] = new[] { "BA", "S\u00e3o Miguel das Matas", "2929404" }; + rows[564] = new[] { "BA", "S\u00e3o Sebasti\u00e3o do Pass\u00e9", "2929503" }; + rows[565] = new[] { "BA", "Sapea\u00e7u", "2929602" }; + rows[566] = new[] { "BA", "S\u00e1tiro Dias", "2929701" }; + rows[567] = new[] { "BA", "Saubara", "2929750" }; + rows[568] = new[] { "BA", "Sa\u00fade", "2929800" }; + rows[569] = new[] { "BA", "Seabra", "2929909" }; + rows[570] = new[] { "BA", "Sebasti\u00e3o Laranjeiras", "2930006" }; + rows[571] = new[] { "BA", "Senhor do Bonfim", "2930105" }; + rows[572] = new[] { "BA", "Sento S\u00e9", "2930204" }; + rows[573] = new[] { "BA", "Serra do Ramalho", "2930154" }; + rows[574] = new[] { "BA", "Serra Dourada", "2930303" }; + rows[575] = new[] { "BA", "Serra Preta", "2930402" }; + rows[576] = new[] { "BA", "Serrinha", "2930501" }; + rows[577] = new[] { "BA", "Serrol\u00e2ndia", "2930600" }; + rows[578] = new[] { "BA", "Sim\u00f5es Filho", "2930709" }; + rows[579] = new[] { "BA", "S\u00edtio do Mato", "2930758" }; + rows[580] = new[] { "BA", "S\u00edtio do Quinto", "2930766" }; + rows[581] = new[] { "BA", "Sobradinho", "2930774" }; + rows[582] = new[] { "BA", "Souto Soares", "2930808" }; + rows[583] = new[] { "BA", "Tabocas do Brejo Velho", "2930907" }; + rows[584] = new[] { "BA", "Tanha\u00e7u", "2931004" }; + rows[585] = new[] { "BA", "Tanque Novo", "2931053" }; + rows[586] = new[] { "BA", "Tanquinho", "2931103" }; + rows[587] = new[] { "BA", "Tapero\u00e1", "2931202" }; + rows[588] = new[] { "BA", "Tapiramut\u00e1", "2931301" }; + rows[589] = new[] { "BA", "Teixeira de Freitas", "2931350" }; + rows[590] = new[] { "BA", "Teodoro Sampaio", "2931400" }; + rows[591] = new[] { "BA", "Teofil\u00e2ndia", "2931509" }; + rows[592] = new[] { "BA", "Teol\u00e2ndia", "2931608" }; + rows[593] = new[] { "BA", "Terra Nova", "2931707" }; + rows[594] = new[] { "BA", "Tremedal", "2931806" }; + rows[595] = new[] { "BA", "Tucano", "2931905" }; + rows[596] = new[] { "BA", "Uau\u00e1", "2932002" }; + rows[597] = new[] { "BA", "Uba\u00edra", "2932101" }; + rows[598] = new[] { "BA", "Ubaitaba", "2932200" }; + rows[599] = new[] { "BA", "Ubat\u00e3", "2932309" }; + } + + private static void MunicipalitiesRows3(string[][] rows) + { + rows[600] = new[] { "BA", "Uiba\u00ed", "2932408" }; + rows[601] = new[] { "BA", "Umburanas", "2932457" }; + rows[602] = new[] { "BA", "Una", "2932507" }; + rows[603] = new[] { "BA", "Urandi", "2932606" }; + rows[604] = new[] { "BA", "Uru\u00e7uca", "2932705" }; + rows[605] = new[] { "BA", "Utinga", "2932804" }; + rows[606] = new[] { "BA", "Valen\u00e7a", "2932903" }; + rows[607] = new[] { "BA", "Valente", "2933000" }; + rows[608] = new[] { "BA", "V\u00e1rzea da Ro\u00e7a", "2933059" }; + rows[609] = new[] { "BA", "V\u00e1rzea do Po\u00e7o", "2933109" }; + rows[610] = new[] { "BA", "V\u00e1rzea Nova", "2933158" }; + rows[611] = new[] { "BA", "Varzedo", "2933174" }; + rows[612] = new[] { "BA", "Vera Cruz", "2933208" }; + rows[613] = new[] { "BA", "Vereda", "2933257" }; + rows[614] = new[] { "BA", "Vit\u00f3ria da Conquista", "2933307" }; + rows[615] = new[] { "BA", "Wagner", "2933406" }; + rows[616] = new[] { "BA", "Wanderley", "2933455" }; + rows[617] = new[] { "BA", "Wenceslau Guimar\u00e3es", "2933505" }; + rows[618] = new[] { "BA", "Xique-Xique", "2933604" }; + rows[619] = new[] { "CE", "Abaiara", "2300101" }; + rows[620] = new[] { "CE", "Acarape", "2300150" }; + rows[621] = new[] { "CE", "Acara\u00fa", "2300200" }; + rows[622] = new[] { "CE", "Acopiara", "2300309" }; + rows[623] = new[] { "CE", "Aiuaba", "2300408" }; + rows[624] = new[] { "CE", "Alc\u00e2ntaras", "2300507" }; + rows[625] = new[] { "CE", "Altaneira", "2300606" }; + rows[626] = new[] { "CE", "Alto Santo", "2300705" }; + rows[627] = new[] { "CE", "Amontada", "2300754" }; + rows[628] = new[] { "CE", "Antonina do Norte", "2300804" }; + rows[629] = new[] { "CE", "Apuiar\u00e9s", "2300903" }; + rows[630] = new[] { "CE", "Aquiraz", "2301000" }; + rows[631] = new[] { "CE", "Aracati", "2301109" }; + rows[632] = new[] { "CE", "Aracoiaba", "2301208" }; + rows[633] = new[] { "CE", "Ararend\u00e1", "2301257" }; + rows[634] = new[] { "CE", "Araripe", "2301307" }; + rows[635] = new[] { "CE", "Aratuba", "2301406" }; + rows[636] = new[] { "CE", "Arneiroz", "2301505" }; + rows[637] = new[] { "CE", "Assar\u00e9", "2301604" }; + rows[638] = new[] { "CE", "Aurora", "2301703" }; + rows[639] = new[] { "CE", "Baixio", "2301802" }; + rows[640] = new[] { "CE", "Banabui\u00fa", "2301851" }; + rows[641] = new[] { "CE", "Barbalha", "2301901" }; + rows[642] = new[] { "CE", "Barreira", "2301950" }; + rows[643] = new[] { "CE", "Barro", "2302008" }; + rows[644] = new[] { "CE", "Barroquinha", "2302057" }; + rows[645] = new[] { "CE", "Baturit\u00e9", "2302107" }; + rows[646] = new[] { "CE", "Beberibe", "2302206" }; + rows[647] = new[] { "CE", "Bela Cruz", "2302305" }; + rows[648] = new[] { "CE", "Boa Viagem", "2302404" }; + rows[649] = new[] { "CE", "Brejo Santo", "2302503" }; + rows[650] = new[] { "CE", "Camocim", "2302602" }; + rows[651] = new[] { "CE", "Campos Sales", "2302701" }; + rows[652] = new[] { "CE", "Canind\u00e9", "2302800" }; + rows[653] = new[] { "CE", "Capistrano", "2302909" }; + rows[654] = new[] { "CE", "Caridade", "2303006" }; + rows[655] = new[] { "CE", "Carir\u00e9", "2303105" }; + rows[656] = new[] { "CE", "Cariria\u00e7u", "2303204" }; + rows[657] = new[] { "CE", "Cari\u00fas", "2303303" }; + rows[658] = new[] { "CE", "Carnaubal", "2303402" }; + rows[659] = new[] { "CE", "Cascavel", "2303501" }; + rows[660] = new[] { "CE", "Catarina", "2303600" }; + rows[661] = new[] { "CE", "Catunda", "2303659" }; + rows[662] = new[] { "CE", "Caucaia", "2303709" }; + rows[663] = new[] { "CE", "Cedro", "2303808" }; + rows[664] = new[] { "CE", "Chaval", "2303907" }; + rows[665] = new[] { "CE", "Chor\u00f3", "2303931" }; + rows[666] = new[] { "CE", "Chorozinho", "2303956" }; + rows[667] = new[] { "CE", "Corea\u00fa", "2304004" }; + rows[668] = new[] { "CE", "Crate\u00fas", "2304103" }; + rows[669] = new[] { "CE", "Crato", "2304202" }; + rows[670] = new[] { "CE", "Croat\u00e1", "2304236" }; + rows[671] = new[] { "CE", "Cruz", "2304251" }; + rows[672] = new[] { "CE", "Deputado Irapuan Pinheiro", "2304269" }; + rows[673] = new[] { "CE", "Erer\u00e9", "2304277" }; + rows[674] = new[] { "CE", "Eus\u00e9bio", "2304285" }; + rows[675] = new[] { "CE", "Farias Brito", "2304301" }; + rows[676] = new[] { "CE", "Forquilha", "2304350" }; + rows[677] = new[] { "CE", "Fortaleza", "2304400" }; + rows[678] = new[] { "CE", "Fortim", "2304459" }; + rows[679] = new[] { "CE", "Frecheirinha", "2304509" }; + rows[680] = new[] { "CE", "General Sampaio", "2304608" }; + rows[681] = new[] { "CE", "Gra\u00e7a", "2304657" }; + rows[682] = new[] { "CE", "Granja", "2304707" }; + rows[683] = new[] { "CE", "Granjeiro", "2304806" }; + rows[684] = new[] { "CE", "Groa\u00edras", "2304905" }; + rows[685] = new[] { "CE", "Guai\u00faba", "2304954" }; + rows[686] = new[] { "CE", "Guaraciaba do Norte", "2305001" }; + rows[687] = new[] { "CE", "Guaramiranga", "2305100" }; + rows[688] = new[] { "CE", "Hidrol\u00e2ndia", "2305209" }; + rows[689] = new[] { "CE", "Horizonte", "2305233" }; + rows[690] = new[] { "CE", "Ibaretama", "2305266" }; + rows[691] = new[] { "CE", "Ibiapina", "2305308" }; + rows[692] = new[] { "CE", "Ibicuitinga", "2305332" }; + rows[693] = new[] { "CE", "Icapu\u00ed", "2305357" }; + rows[694] = new[] { "CE", "Ic\u00f3", "2305407" }; + rows[695] = new[] { "CE", "Iguatu", "2305506" }; + rows[696] = new[] { "CE", "Independ\u00eancia", "2305605" }; + rows[697] = new[] { "CE", "Ipaporanga", "2305654" }; + rows[698] = new[] { "CE", "Ipaumirim", "2305704" }; + rows[699] = new[] { "CE", "Ipu", "2305803" }; + rows[700] = new[] { "CE", "Ipueiras", "2305902" }; + rows[701] = new[] { "CE", "Iracema", "2306009" }; + rows[702] = new[] { "CE", "Irau\u00e7uba", "2306108" }; + rows[703] = new[] { "CE", "Itai\u00e7aba", "2306207" }; + rows[704] = new[] { "CE", "Itaitinga", "2306256" }; + rows[705] = new[] { "CE", "Itapaj\u00e9", "2306306" }; + rows[706] = new[] { "CE", "Itapipoca", "2306405" }; + rows[707] = new[] { "CE", "Itapi\u00fana", "2306504" }; + rows[708] = new[] { "CE", "Itarema", "2306553" }; + rows[709] = new[] { "CE", "Itatira", "2306603" }; + rows[710] = new[] { "CE", "Jaguaretama", "2306702" }; + rows[711] = new[] { "CE", "Jaguaribara", "2306801" }; + rows[712] = new[] { "CE", "Jaguaribe", "2306900" }; + rows[713] = new[] { "CE", "Jaguaruana", "2307007" }; + rows[714] = new[] { "CE", "Jardim", "2307106" }; + rows[715] = new[] { "CE", "Jati", "2307205" }; + rows[716] = new[] { "CE", "Jijoca de Jericoacoara", "2307254" }; + rows[717] = new[] { "CE", "Juazeiro do Norte", "2307304" }; + rows[718] = new[] { "CE", "Juc\u00e1s", "2307403" }; + rows[719] = new[] { "CE", "Lavras da Mangabeira", "2307502" }; + rows[720] = new[] { "CE", "Limoeiro do Norte", "2307601" }; + rows[721] = new[] { "CE", "Madalena", "2307635" }; + rows[722] = new[] { "CE", "Maracana\u00fa", "2307650" }; + rows[723] = new[] { "CE", "Maranguape", "2307700" }; + rows[724] = new[] { "CE", "Marco", "2307809" }; + rows[725] = new[] { "CE", "Martin\u00f3pole", "2307908" }; + rows[726] = new[] { "CE", "Massap\u00ea", "2308005" }; + rows[727] = new[] { "CE", "Mauriti", "2308104" }; + rows[728] = new[] { "CE", "Meruoca", "2308203" }; + rows[729] = new[] { "CE", "Milagres", "2308302" }; + rows[730] = new[] { "CE", "Milh\u00e3", "2308351" }; + rows[731] = new[] { "CE", "Mira\u00edma", "2308377" }; + rows[732] = new[] { "CE", "Miss\u00e3o Velha", "2308401" }; + rows[733] = new[] { "CE", "Momba\u00e7a", "2308500" }; + rows[734] = new[] { "CE", "Monsenhor Tabosa", "2308609" }; + rows[735] = new[] { "CE", "Morada Nova", "2308708" }; + rows[736] = new[] { "CE", "Mora\u00fajo", "2308807" }; + rows[737] = new[] { "CE", "Morrinhos", "2308906" }; + rows[738] = new[] { "CE", "Mucambo", "2309003" }; + rows[739] = new[] { "CE", "Mulungu", "2309102" }; + rows[740] = new[] { "CE", "Nova Olinda", "2309201" }; + rows[741] = new[] { "CE", "Nova Russas", "2309300" }; + rows[742] = new[] { "CE", "Novo Oriente", "2309409" }; + rows[743] = new[] { "CE", "Ocara", "2309458" }; + rows[744] = new[] { "CE", "Or\u00f3s", "2309508" }; + rows[745] = new[] { "CE", "Pacajus", "2309607" }; + rows[746] = new[] { "CE", "Pacatuba", "2309706" }; + rows[747] = new[] { "CE", "Pacoti", "2309805" }; + rows[748] = new[] { "CE", "Pacuj\u00e1", "2309904" }; + rows[749] = new[] { "CE", "Palhano", "2310001" }; + rows[750] = new[] { "CE", "Palm\u00e1cia", "2310100" }; + rows[751] = new[] { "CE", "Paracuru", "2310209" }; + rows[752] = new[] { "CE", "Paraipaba", "2310258" }; + rows[753] = new[] { "CE", "Parambu", "2310308" }; + rows[754] = new[] { "CE", "Paramoti", "2310407" }; + rows[755] = new[] { "CE", "Pedra Branca", "2310506" }; + rows[756] = new[] { "CE", "Penaforte", "2310605" }; + rows[757] = new[] { "CE", "Pentecoste", "2310704" }; + rows[758] = new[] { "CE", "Pereiro", "2310803" }; + rows[759] = new[] { "CE", "Pindoretama", "2310852" }; + rows[760] = new[] { "CE", "Piquet Carneiro", "2310902" }; + rows[761] = new[] { "CE", "Pires Ferreira", "2310951" }; + rows[762] = new[] { "CE", "Poranga", "2311009" }; + rows[763] = new[] { "CE", "Porteiras", "2311108" }; + rows[764] = new[] { "CE", "Potengi", "2311207" }; + rows[765] = new[] { "CE", "Potiretama", "2311231" }; + rows[766] = new[] { "CE", "Quiterian\u00f3polis", "2311264" }; + rows[767] = new[] { "CE", "Quixad\u00e1", "2311306" }; + rows[768] = new[] { "CE", "Quixel\u00f4", "2311355" }; + rows[769] = new[] { "CE", "Quixeramobim", "2311405" }; + rows[770] = new[] { "CE", "Quixer\u00e9", "2311504" }; + rows[771] = new[] { "CE", "Reden\u00e7\u00e3o", "2311603" }; + rows[772] = new[] { "CE", "Reriutaba", "2311702" }; + rows[773] = new[] { "CE", "Russas", "2311801" }; + rows[774] = new[] { "CE", "Saboeiro", "2311900" }; + rows[775] = new[] { "CE", "Salitre", "2311959" }; + rows[776] = new[] { "CE", "Santa Quit\u00e9ria", "2312205" }; + rows[777] = new[] { "CE", "Santana do Acara\u00fa", "2312007" }; + rows[778] = new[] { "CE", "Santana do Cariri", "2312106" }; + rows[779] = new[] { "CE", "S\u00e3o Benedito", "2312304" }; + rows[780] = new[] { "CE", "S\u00e3o Gon\u00e7alo do Amarante", "2312403" }; + rows[781] = new[] { "CE", "S\u00e3o Jo\u00e3o do Jaguaribe", "2312502" }; + rows[782] = new[] { "CE", "S\u00e3o Lu\u00eds do Curu", "2312601" }; + rows[783] = new[] { "CE", "Senador Pompeu", "2312700" }; + rows[784] = new[] { "CE", "Senador S\u00e1", "2312809" }; + rows[785] = new[] { "CE", "Sobral", "2312908" }; + rows[786] = new[] { "CE", "Solon\u00f3pole", "2313005" }; + rows[787] = new[] { "CE", "Tabuleiro do Norte", "2313104" }; + rows[788] = new[] { "CE", "Tamboril", "2313203" }; + rows[789] = new[] { "CE", "Tarrafas", "2313252" }; + rows[790] = new[] { "CE", "Tau\u00e1", "2313302" }; + rows[791] = new[] { "CE", "Teju\u00e7uoca", "2313351" }; + rows[792] = new[] { "CE", "Tiangu\u00e1", "2313401" }; + rows[793] = new[] { "CE", "Trairi", "2313500" }; + rows[794] = new[] { "CE", "Tururu", "2313559" }; + rows[795] = new[] { "CE", "Ubajara", "2313609" }; + rows[796] = new[] { "CE", "Umari", "2313708" }; + rows[797] = new[] { "CE", "Umirim", "2313757" }; + rows[798] = new[] { "CE", "Uruburetama", "2313807" }; + rows[799] = new[] { "CE", "Uruoca", "2313906" }; + } + + private static void MunicipalitiesRows4(string[][] rows) + { + rows[800] = new[] { "CE", "Varjota", "2313955" }; + rows[801] = new[] { "CE", "V\u00e1rzea Alegre", "2314003" }; + rows[802] = new[] { "CE", "Vi\u00e7osa do Cear\u00e1", "2314102" }; + rows[803] = new[] { "DF", "Bras\u00edlia", "5300108" }; + rows[804] = new[] { "ES", "Afonso Cl\u00e1udio", "3200102" }; + rows[805] = new[] { "ES", "\u00c1gua Doce do Norte", "3200169" }; + rows[806] = new[] { "ES", "\u00c1guia Branca", "3200136" }; + rows[807] = new[] { "ES", "Alegre", "3200201" }; + rows[808] = new[] { "ES", "Alfredo Chaves", "3200300" }; + rows[809] = new[] { "ES", "Alto Rio Novo", "3200359" }; + rows[810] = new[] { "ES", "Anchieta", "3200409" }; + rows[811] = new[] { "ES", "Apiac\u00e1", "3200508" }; + rows[812] = new[] { "ES", "Aracruz", "3200607" }; + rows[813] = new[] { "ES", "At\u00edlio Viv\u00e1cqua", "3200706" }; + rows[814] = new[] { "ES", "Baixo Guandu", "3200805" }; + rows[815] = new[] { "ES", "Barra de S\u00e3o Francisco", "3200904" }; + rows[816] = new[] { "ES", "Boa Esperan\u00e7a", "3201001" }; + rows[817] = new[] { "ES", "Bom Jesus do Norte", "3201100" }; + rows[818] = new[] { "ES", "Brejetuba", "3201159" }; + rows[819] = new[] { "ES", "Cachoeiro de Itapemirim", "3201209" }; + rows[820] = new[] { "ES", "Cariacica", "3201308" }; + rows[821] = new[] { "ES", "Castelo", "3201407" }; + rows[822] = new[] { "ES", "Colatina", "3201506" }; + rows[823] = new[] { "ES", "Concei\u00e7\u00e3o da Barra", "3201605" }; + rows[824] = new[] { "ES", "Concei\u00e7\u00e3o do Castelo", "3201704" }; + rows[825] = new[] { "ES", "Divino de S\u00e3o Louren\u00e7o", "3201803" }; + rows[826] = new[] { "ES", "Domingos Martins", "3201902" }; + rows[827] = new[] { "ES", "Dores do Rio Preto", "3202009" }; + rows[828] = new[] { "ES", "Ecoporanga", "3202108" }; + rows[829] = new[] { "ES", "Fund\u00e3o", "3202207" }; + rows[830] = new[] { "ES", "Governador Lindenberg", "3202256" }; + rows[831] = new[] { "ES", "Gua\u00e7u\u00ed", "3202306" }; + rows[832] = new[] { "ES", "Guarapari", "3202405" }; + rows[833] = new[] { "ES", "Ibatiba", "3202454" }; + rows[834] = new[] { "ES", "Ibira\u00e7u", "3202504" }; + rows[835] = new[] { "ES", "Ibitirama", "3202553" }; + rows[836] = new[] { "ES", "Iconha", "3202603" }; + rows[837] = new[] { "ES", "Irupi", "3202652" }; + rows[838] = new[] { "ES", "Itagua\u00e7u", "3202702" }; + rows[839] = new[] { "ES", "Itapemirim", "3202801" }; + rows[840] = new[] { "ES", "Itarana", "3202900" }; + rows[841] = new[] { "ES", "I\u00fana", "3203007" }; + rows[842] = new[] { "ES", "Jaguar\u00e9", "3203056" }; + rows[843] = new[] { "ES", "Jer\u00f4nimo Monteiro", "3203106" }; + rows[844] = new[] { "ES", "Jo\u00e3o Neiva", "3203130" }; + rows[845] = new[] { "ES", "Laranja da Terra", "3203163" }; + rows[846] = new[] { "ES", "Linhares", "3203205" }; + rows[847] = new[] { "ES", "Manten\u00f3polis", "3203304" }; + rows[848] = new[] { "ES", "Marata\u00edzes", "3203320" }; + rows[849] = new[] { "ES", "Marechal Floriano", "3203346" }; + rows[850] = new[] { "ES", "Maril\u00e2ndia", "3203353" }; + rows[851] = new[] { "ES", "Mimoso do Sul", "3203403" }; + rows[852] = new[] { "ES", "Montanha", "3203502" }; + rows[853] = new[] { "ES", "Mucurici", "3203601" }; + rows[854] = new[] { "ES", "Muniz Freire", "3203700" }; + rows[855] = new[] { "ES", "Muqui", "3203809" }; + rows[856] = new[] { "ES", "Nova Ven\u00e9cia", "3203908" }; + rows[857] = new[] { "ES", "Pancas", "3204005" }; + rows[858] = new[] { "ES", "Pedro Can\u00e1rio", "3204054" }; + rows[859] = new[] { "ES", "Pinheiros", "3204104" }; + rows[860] = new[] { "ES", "Pi\u00fama", "3204203" }; + rows[861] = new[] { "ES", "Ponto Belo", "3204252" }; + rows[862] = new[] { "ES", "Presidente Kennedy", "3204302" }; + rows[863] = new[] { "ES", "Rio Bananal", "3204351" }; + rows[864] = new[] { "ES", "Rio Novo do Sul", "3204401" }; + rows[865] = new[] { "ES", "Santa Leopoldina", "3204500" }; + rows[866] = new[] { "ES", "Santa Maria de Jetib\u00e1", "3204559" }; + rows[867] = new[] { "ES", "Santa Teresa", "3204609" }; + rows[868] = new[] { "ES", "S\u00e3o Domingos do Norte", "3204658" }; + rows[869] = new[] { "ES", "S\u00e3o Gabriel da Palha", "3204708" }; + rows[870] = new[] { "ES", "S\u00e3o Jos\u00e9 do Cal\u00e7ado", "3204807" }; + rows[871] = new[] { "ES", "S\u00e3o Mateus", "3204906" }; + rows[872] = new[] { "ES", "S\u00e3o Roque do Cana\u00e3", "3204955" }; + rows[873] = new[] { "ES", "Serra", "3205002" }; + rows[874] = new[] { "ES", "Sooretama", "3205010" }; + rows[875] = new[] { "ES", "Vargem Alta", "3205036" }; + rows[876] = new[] { "ES", "Venda Nova do Imigrante", "3205069" }; + rows[877] = new[] { "ES", "Viana", "3205101" }; + rows[878] = new[] { "ES", "Vila Pav\u00e3o", "3205150" }; + rows[879] = new[] { "ES", "Vila Val\u00e9rio", "3205176" }; + rows[880] = new[] { "ES", "Vila Velha", "3205200" }; + rows[881] = new[] { "ES", "Vit\u00f3ria", "3205309" }; + rows[882] = new[] { "GO", "Abadia de Goi\u00e1s", "5200050" }; + rows[883] = new[] { "GO", "Abadi\u00e2nia", "5200100" }; + rows[884] = new[] { "GO", "Acre\u00fana", "5200134" }; + rows[885] = new[] { "GO", "Adel\u00e2ndia", "5200159" }; + rows[886] = new[] { "GO", "\u00c1gua Fria de Goi\u00e1s", "5200175" }; + rows[887] = new[] { "GO", "\u00c1gua Limpa", "5200209" }; + rows[888] = new[] { "GO", "\u00c1guas Lindas de Goi\u00e1s", "5200258" }; + rows[889] = new[] { "GO", "Alex\u00e2nia", "5200308" }; + rows[890] = new[] { "GO", "Alo\u00e2ndia", "5200506" }; + rows[891] = new[] { "GO", "Alto Horizonte", "5200555" }; + rows[892] = new[] { "GO", "Alto Para\u00edso de Goi\u00e1s", "5200605" }; + rows[893] = new[] { "GO", "Alvorada do Norte", "5200803" }; + rows[894] = new[] { "GO", "Amaralina", "5200829" }; + rows[895] = new[] { "GO", "Americano do Brasil", "5200852" }; + rows[896] = new[] { "GO", "Amorin\u00f3polis", "5200902" }; + rows[897] = new[] { "GO", "An\u00e1polis", "5201108" }; + rows[898] = new[] { "GO", "Anhanguera", "5201207" }; + rows[899] = new[] { "GO", "Anicuns", "5201306" }; + rows[900] = new[] { "GO", "Aparecida de Goi\u00e2nia", "5201405" }; + rows[901] = new[] { "GO", "Aparecida do Rio Doce", "5201454" }; + rows[902] = new[] { "GO", "Apor\u00e9", "5201504" }; + rows[903] = new[] { "GO", "Ara\u00e7u", "5201603" }; + rows[904] = new[] { "GO", "Aragar\u00e7as", "5201702" }; + rows[905] = new[] { "GO", "Aragoi\u00e2nia", "5201801" }; + rows[906] = new[] { "GO", "Araguapaz", "5202155" }; + rows[907] = new[] { "GO", "Aren\u00f3polis", "5202353" }; + rows[908] = new[] { "GO", "Aruan\u00e3", "5202502" }; + rows[909] = new[] { "GO", "Auril\u00e2ndia", "5202601" }; + rows[910] = new[] { "GO", "Avelin\u00f3polis", "5202809" }; + rows[911] = new[] { "GO", "Baliza", "5203104" }; + rows[912] = new[] { "GO", "Barro Alto", "5203203" }; + rows[913] = new[] { "GO", "Bela Vista de Goi\u00e1s", "5203302" }; + rows[914] = new[] { "GO", "Bom Jardim de Goi\u00e1s", "5203401" }; + rows[915] = new[] { "GO", "Bom Jesus de Goi\u00e1s", "5203500" }; + rows[916] = new[] { "GO", "Bonfin\u00f3polis", "5203559" }; + rows[917] = new[] { "GO", "Bon\u00f3polis", "5203575" }; + rows[918] = new[] { "GO", "Brazabrantes", "5203609" }; + rows[919] = new[] { "GO", "Brit\u00e2nia", "5203807" }; + rows[920] = new[] { "GO", "Buriti Alegre", "5203906" }; + rows[921] = new[] { "GO", "Buriti de Goi\u00e1s", "5203939" }; + rows[922] = new[] { "GO", "Buritin\u00f3polis", "5203962" }; + rows[923] = new[] { "GO", "Cabeceiras", "5204003" }; + rows[924] = new[] { "GO", "Cachoeira Alta", "5204102" }; + rows[925] = new[] { "GO", "Cachoeira de Goi\u00e1s", "5204201" }; + rows[926] = new[] { "GO", "Cachoeira Dourada", "5204250" }; + rows[927] = new[] { "GO", "Ca\u00e7u", "5204300" }; + rows[928] = new[] { "GO", "Caiap\u00f4nia", "5204409" }; + rows[929] = new[] { "GO", "Caldas Novas", "5204508" }; + rows[930] = new[] { "GO", "Caldazinha", "5204557" }; + rows[931] = new[] { "GO", "Campestre de Goi\u00e1s", "5204607" }; + rows[932] = new[] { "GO", "Campina\u00e7u", "5204656" }; + rows[933] = new[] { "GO", "Campinorte", "5204706" }; + rows[934] = new[] { "GO", "Campo Alegre de Goi\u00e1s", "5204805" }; + rows[935] = new[] { "GO", "Campo Limpo de Goi\u00e1s", "5204854" }; + rows[936] = new[] { "GO", "Campos Belos", "5204904" }; + rows[937] = new[] { "GO", "Campos Verdes", "5204953" }; + rows[938] = new[] { "GO", "Carmo do Rio Verde", "5205000" }; + rows[939] = new[] { "GO", "Castel\u00e2ndia", "5205059" }; + rows[940] = new[] { "GO", "Catal\u00e3o", "5205109" }; + rows[941] = new[] { "GO", "Catura\u00ed", "5205208" }; + rows[942] = new[] { "GO", "Cavalcante", "5205307" }; + rows[943] = new[] { "GO", "Ceres", "5205406" }; + rows[944] = new[] { "GO", "Cezarina", "5205455" }; + rows[945] = new[] { "GO", "Chapad\u00e3o do C\u00e9u", "5205471" }; + rows[946] = new[] { "GO", "Cidade Ocidental", "5205497" }; + rows[947] = new[] { "GO", "Cocalzinho de Goi\u00e1s", "5205513" }; + rows[948] = new[] { "GO", "Colinas do Sul", "5205521" }; + rows[949] = new[] { "GO", "C\u00f3rrego do Ouro", "5205703" }; + rows[950] = new[] { "GO", "Corumb\u00e1 de Goi\u00e1s", "5205802" }; + rows[951] = new[] { "GO", "Corumba\u00edba", "5205901" }; + rows[952] = new[] { "GO", "Cristalina", "5206206" }; + rows[953] = new[] { "GO", "Cristian\u00f3polis", "5206305" }; + rows[954] = new[] { "GO", "Crix\u00e1s", "5206404" }; + rows[955] = new[] { "GO", "Crom\u00ednia", "5206503" }; + rows[956] = new[] { "GO", "Cumari", "5206602" }; + rows[957] = new[] { "GO", "Damian\u00f3polis", "5206701" }; + rows[958] = new[] { "GO", "Damol\u00e2ndia", "5206800" }; + rows[959] = new[] { "GO", "Davin\u00f3polis", "5206909" }; + rows[960] = new[] { "GO", "Diorama", "5207105" }; + rows[961] = new[] { "GO", "Divin\u00f3polis de Goi\u00e1s", "5208301" }; + rows[962] = new[] { "GO", "Doverl\u00e2ndia", "5207253" }; + rows[963] = new[] { "GO", "Edealina", "5207352" }; + rows[964] = new[] { "GO", "Ed\u00e9ia", "5207402" }; + rows[965] = new[] { "GO", "Estrela do Norte", "5207501" }; + rows[966] = new[] { "GO", "Faina", "5207535" }; + rows[967] = new[] { "GO", "Fazenda Nova", "5207600" }; + rows[968] = new[] { "GO", "Firmin\u00f3polis", "5207808" }; + rows[969] = new[] { "GO", "Flores de Goi\u00e1s", "5207907" }; + rows[970] = new[] { "GO", "Formosa", "5208004" }; + rows[971] = new[] { "GO", "Formoso", "5208103" }; + rows[972] = new[] { "GO", "Gameleira de Goi\u00e1s", "5208152" }; + rows[973] = new[] { "GO", "Goian\u00e1polis", "5208400" }; + rows[974] = new[] { "GO", "Goiandira", "5208509" }; + rows[975] = new[] { "GO", "Goian\u00e9sia", "5208608" }; + rows[976] = new[] { "GO", "Goi\u00e2nia", "5208707" }; + rows[977] = new[] { "GO", "Goianira", "5208806" }; + rows[978] = new[] { "GO", "Goi\u00e1s", "5208905" }; + rows[979] = new[] { "GO", "Goiatuba", "5209101" }; + rows[980] = new[] { "GO", "Gouvel\u00e2ndia", "5209150" }; + rows[981] = new[] { "GO", "Guap\u00f3", "5209200" }; + rows[982] = new[] { "GO", "Guara\u00edta", "5209291" }; + rows[983] = new[] { "GO", "Guarani de Goi\u00e1s", "5209408" }; + rows[984] = new[] { "GO", "Guarinos", "5209457" }; + rows[985] = new[] { "GO", "Heitora\u00ed", "5209606" }; + rows[986] = new[] { "GO", "Hidrol\u00e2ndia", "5209705" }; + rows[987] = new[] { "GO", "Hidrolina", "5209804" }; + rows[988] = new[] { "GO", "Iaciara", "5209903" }; + rows[989] = new[] { "GO", "Inaciol\u00e2ndia", "5209937" }; + rows[990] = new[] { "GO", "Indiara", "5209952" }; + rows[991] = new[] { "GO", "Inhumas", "5210000" }; + rows[992] = new[] { "GO", "Ipameri", "5210109" }; + rows[993] = new[] { "GO", "Ipiranga de Goi\u00e1s", "5210158" }; + rows[994] = new[] { "GO", "Ipor\u00e1", "5210208" }; + rows[995] = new[] { "GO", "Israel\u00e2ndia", "5210307" }; + rows[996] = new[] { "GO", "Itabera\u00ed", "5210406" }; + rows[997] = new[] { "GO", "Itaguari", "5210562" }; + rows[998] = new[] { "GO", "Itaguaru", "5210604" }; + rows[999] = new[] { "GO", "Itaj\u00e1", "5210802" }; + } + + private static void MunicipalitiesRows5(string[][] rows) + { + rows[1000] = new[] { "GO", "Itapaci", "5210901" }; + rows[1001] = new[] { "GO", "Itapirapu\u00e3", "5211008" }; + rows[1002] = new[] { "GO", "Itapuranga", "5211206" }; + rows[1003] = new[] { "GO", "Itarum\u00e3", "5211305" }; + rows[1004] = new[] { "GO", "Itau\u00e7u", "5211404" }; + rows[1005] = new[] { "GO", "Itumbiara", "5211503" }; + rows[1006] = new[] { "GO", "Ivol\u00e2ndia", "5211602" }; + rows[1007] = new[] { "GO", "Jandaia", "5211701" }; + rows[1008] = new[] { "GO", "Jaragu\u00e1", "5211800" }; + rows[1009] = new[] { "GO", "Jata\u00ed", "5211909" }; + rows[1010] = new[] { "GO", "Jaupaci", "5212006" }; + rows[1011] = new[] { "GO", "Jes\u00fapolis", "5212055" }; + rows[1012] = new[] { "GO", "Jovi\u00e2nia", "5212105" }; + rows[1013] = new[] { "GO", "Jussara", "5212204" }; + rows[1014] = new[] { "GO", "Lagoa Santa", "5212253" }; + rows[1015] = new[] { "GO", "Leopoldo de Bulh\u00f5es", "5212303" }; + rows[1016] = new[] { "GO", "Luzi\u00e2nia", "5212501" }; + rows[1017] = new[] { "GO", "Mairipotaba", "5212600" }; + rows[1018] = new[] { "GO", "Mamba\u00ed", "5212709" }; + rows[1019] = new[] { "GO", "Mara Rosa", "5212808" }; + rows[1020] = new[] { "GO", "Marzag\u00e3o", "5212907" }; + rows[1021] = new[] { "GO", "Matrinch\u00e3", "5212956" }; + rows[1022] = new[] { "GO", "Mauril\u00e2ndia", "5213004" }; + rows[1023] = new[] { "GO", "Mimoso de Goi\u00e1s", "5213053" }; + rows[1024] = new[] { "GO", "Mina\u00e7u", "5213087" }; + rows[1025] = new[] { "GO", "Mineiros", "5213103" }; + rows[1026] = new[] { "GO", "Moipor\u00e1", "5213400" }; + rows[1027] = new[] { "GO", "Monte Alegre de Goi\u00e1s", "5213509" }; + rows[1028] = new[] { "GO", "Montes Claros de Goi\u00e1s", "5213707" }; + rows[1029] = new[] { "GO", "Montividiu", "5213756" }; + rows[1030] = new[] { "GO", "Montividiu do Norte", "5213772" }; + rows[1031] = new[] { "GO", "Morrinhos", "5213806" }; + rows[1032] = new[] { "GO", "Morro Agudo de Goi\u00e1s", "5213855" }; + rows[1033] = new[] { "GO", "Moss\u00e2medes", "5213905" }; + rows[1034] = new[] { "GO", "Mozarl\u00e2ndia", "5214002" }; + rows[1035] = new[] { "GO", "Mundo Novo", "5214051" }; + rows[1036] = new[] { "GO", "Mutun\u00f3polis", "5214101" }; + rows[1037] = new[] { "GO", "Naz\u00e1rio", "5214408" }; + rows[1038] = new[] { "GO", "Ner\u00f3polis", "5214507" }; + rows[1039] = new[] { "GO", "Niquel\u00e2ndia", "5214606" }; + rows[1040] = new[] { "GO", "Nova Am\u00e9rica", "5214705" }; + rows[1041] = new[] { "GO", "Nova Aurora", "5214804" }; + rows[1042] = new[] { "GO", "Nova Crix\u00e1s", "5214838" }; + rows[1043] = new[] { "GO", "Nova Gl\u00f3ria", "5214861" }; + rows[1044] = new[] { "GO", "Nova Igua\u00e7u de Goi\u00e1s", "5214879" }; + rows[1045] = new[] { "GO", "Nova Roma", "5214903" }; + rows[1046] = new[] { "GO", "Nova Veneza", "5215009" }; + rows[1047] = new[] { "GO", "Novo Brasil", "5215207" }; + rows[1048] = new[] { "GO", "Novo Gama", "5215231" }; + rows[1049] = new[] { "GO", "Novo Planalto", "5215256" }; + rows[1050] = new[] { "GO", "Orizona", "5215306" }; + rows[1051] = new[] { "GO", "Ouro Verde de Goi\u00e1s", "5215405" }; + rows[1052] = new[] { "GO", "Ouvidor", "5215504" }; + rows[1053] = new[] { "GO", "Padre Bernardo", "5215603" }; + rows[1054] = new[] { "GO", "Palestina de Goi\u00e1s", "5215652" }; + rows[1055] = new[] { "GO", "Palmeiras de Goi\u00e1s", "5215702" }; + rows[1056] = new[] { "GO", "Palmelo", "5215801" }; + rows[1057] = new[] { "GO", "Palmin\u00f3polis", "5215900" }; + rows[1058] = new[] { "GO", "Panam\u00e1", "5216007" }; + rows[1059] = new[] { "GO", "Paranaiguara", "5216304" }; + rows[1060] = new[] { "GO", "Para\u00fana", "5216403" }; + rows[1061] = new[] { "GO", "Perol\u00e2ndia", "5216452" }; + rows[1062] = new[] { "GO", "Petrolina de Goi\u00e1s", "5216809" }; + rows[1063] = new[] { "GO", "Pilar de Goi\u00e1s", "5216908" }; + rows[1064] = new[] { "GO", "Piracanjuba", "5217104" }; + rows[1065] = new[] { "GO", "Piranhas", "5217203" }; + rows[1066] = new[] { "GO", "Piren\u00f3polis", "5217302" }; + rows[1067] = new[] { "GO", "Pires do Rio", "5217401" }; + rows[1068] = new[] { "GO", "Planaltina", "5217609" }; + rows[1069] = new[] { "GO", "Pontalina", "5217708" }; + rows[1070] = new[] { "GO", "Porangatu", "5218003" }; + rows[1071] = new[] { "GO", "Porteir\u00e3o", "5218052" }; + rows[1072] = new[] { "GO", "Portel\u00e2ndia", "5218102" }; + rows[1073] = new[] { "GO", "Posse", "5218300" }; + rows[1074] = new[] { "GO", "Professor Jamil", "5218391" }; + rows[1075] = new[] { "GO", "Quirin\u00f3polis", "5218508" }; + rows[1076] = new[] { "GO", "Rialma", "5218607" }; + rows[1077] = new[] { "GO", "Rian\u00e1polis", "5218706" }; + rows[1078] = new[] { "GO", "Rio Quente", "5218789" }; + rows[1079] = new[] { "GO", "Rio Verde", "5218805" }; + rows[1080] = new[] { "GO", "Rubiataba", "5218904" }; + rows[1081] = new[] { "GO", "Sanclerl\u00e2ndia", "5219001" }; + rows[1082] = new[] { "GO", "Santa B\u00e1rbara de Goi\u00e1s", "5219100" }; + rows[1083] = new[] { "GO", "Santa Cruz de Goi\u00e1s", "5219209" }; + rows[1084] = new[] { "GO", "Santa F\u00e9 de Goi\u00e1s", "5219258" }; + rows[1085] = new[] { "GO", "Santa Helena de Goi\u00e1s", "5219308" }; + rows[1086] = new[] { "GO", "Santa Isabel", "5219357" }; + rows[1087] = new[] { "GO", "Santa Rita do Araguaia", "5219407" }; + rows[1088] = new[] { "GO", "Santa Rita do Novo Destino", "5219456" }; + rows[1089] = new[] { "GO", "Santa Rosa de Goi\u00e1s", "5219506" }; + rows[1090] = new[] { "GO", "Santa Tereza de Goi\u00e1s", "5219605" }; + rows[1091] = new[] { "GO", "Santa Terezinha de Goi\u00e1s", "5219704" }; + rows[1092] = new[] { "GO", "Santo Ant\u00f4nio da Barra", "5219712" }; + rows[1093] = new[] { "GO", "Santo Ant\u00f4nio de Goi\u00e1s", "5219738" }; + rows[1094] = new[] { "GO", "Santo Ant\u00f4nio do Descoberto", "5219753" }; + rows[1095] = new[] { "GO", "S\u00e3o Domingos", "5219803" }; + rows[1096] = new[] { "GO", "S\u00e3o Francisco de Goi\u00e1s", "5219902" }; + rows[1097] = new[] { "GO", "S\u00e3o Jo\u00e3o d'Alian\u00e7a", "5220009" }; + rows[1098] = new[] { "GO", "S\u00e3o Jo\u00e3o da Para\u00fana", "5220058" }; + rows[1099] = new[] { "GO", "S\u00e3o Lu\u00eds de Montes Belos", "5220108" }; + rows[1100] = new[] { "GO", "S\u00e3o Luiz do Norte", "5220157" }; + rows[1101] = new[] { "GO", "S\u00e3o Miguel do Araguaia", "5220207" }; + rows[1102] = new[] { "GO", "S\u00e3o Miguel do Passa Quatro", "5220264" }; + rows[1103] = new[] { "GO", "S\u00e3o Patr\u00edcio", "5220280" }; + rows[1104] = new[] { "GO", "S\u00e3o Sim\u00e3o", "5220405" }; + rows[1105] = new[] { "GO", "Senador Canedo", "5220454" }; + rows[1106] = new[] { "GO", "Serran\u00f3polis", "5220504" }; + rows[1107] = new[] { "GO", "Silv\u00e2nia", "5220603" }; + rows[1108] = new[] { "GO", "Simol\u00e2ndia", "5220686" }; + rows[1109] = new[] { "GO", "S\u00edtio d'Abadia", "5220702" }; + rows[1110] = new[] { "GO", "Taquaral de Goi\u00e1s", "5221007" }; + rows[1111] = new[] { "GO", "Teresina de Goi\u00e1s", "5221080" }; + rows[1112] = new[] { "GO", "Terez\u00f3polis de Goi\u00e1s", "5221197" }; + rows[1113] = new[] { "GO", "Tr\u00eas Ranchos", "5221304" }; + rows[1114] = new[] { "GO", "Trindade", "5221403" }; + rows[1115] = new[] { "GO", "Trombas", "5221452" }; + rows[1116] = new[] { "GO", "Turv\u00e2nia", "5221502" }; + rows[1117] = new[] { "GO", "Turvel\u00e2ndia", "5221551" }; + rows[1118] = new[] { "GO", "Uirapuru", "5221577" }; + rows[1119] = new[] { "GO", "Urua\u00e7u", "5221601" }; + rows[1120] = new[] { "GO", "Uruana", "5221700" }; + rows[1121] = new[] { "GO", "Uruta\u00ed", "5221809" }; + rows[1122] = new[] { "GO", "Valpara\u00edso de Goi\u00e1s", "5221858" }; + rows[1123] = new[] { "GO", "Varj\u00e3o", "5221908" }; + rows[1124] = new[] { "GO", "Vian\u00f3polis", "5222005" }; + rows[1125] = new[] { "GO", "Vicentin\u00f3polis", "5222054" }; + rows[1126] = new[] { "GO", "Vila Boa", "5222203" }; + rows[1127] = new[] { "GO", "Vila Prop\u00edcio", "5222302" }; + rows[1128] = new[] { "MA", "A\u00e7ail\u00e2ndia", "2100055" }; + rows[1129] = new[] { "MA", "Afonso Cunha", "2100105" }; + rows[1130] = new[] { "MA", "\u00c1gua Doce do Maranh\u00e3o", "2100154" }; + rows[1131] = new[] { "MA", "Alc\u00e2ntara", "2100204" }; + rows[1132] = new[] { "MA", "Aldeias Altas", "2100303" }; + rows[1133] = new[] { "MA", "Altamira do Maranh\u00e3o", "2100402" }; + rows[1134] = new[] { "MA", "Alto Alegre do Maranh\u00e3o", "2100436" }; + rows[1135] = new[] { "MA", "Alto Alegre do Pindar\u00e9", "2100477" }; + rows[1136] = new[] { "MA", "Alto Parna\u00edba", "2100501" }; + rows[1137] = new[] { "MA", "Amap\u00e1 do Maranh\u00e3o", "2100550" }; + rows[1138] = new[] { "MA", "Amarante do Maranh\u00e3o", "2100600" }; + rows[1139] = new[] { "MA", "Anajatuba", "2100709" }; + rows[1140] = new[] { "MA", "Anapurus", "2100808" }; + rows[1141] = new[] { "MA", "Apicum-A\u00e7u", "2100832" }; + rows[1142] = new[] { "MA", "Araguan\u00e3", "2100873" }; + rows[1143] = new[] { "MA", "Araioses", "2100907" }; + rows[1144] = new[] { "MA", "Arame", "2100956" }; + rows[1145] = new[] { "MA", "Arari", "2101004" }; + rows[1146] = new[] { "MA", "Axix\u00e1", "2101103" }; + rows[1147] = new[] { "MA", "Bacabal", "2101202" }; + rows[1148] = new[] { "MA", "Bacabeira", "2101251" }; + rows[1149] = new[] { "MA", "Bacuri", "2101301" }; + rows[1150] = new[] { "MA", "Bacurituba", "2101350" }; + rows[1151] = new[] { "MA", "Balsas", "2101400" }; + rows[1152] = new[] { "MA", "Bar\u00e3o de Graja\u00fa", "2101509" }; + rows[1153] = new[] { "MA", "Barra do Corda", "2101608" }; + rows[1154] = new[] { "MA", "Barreirinhas", "2101707" }; + rows[1155] = new[] { "MA", "Bela Vista do Maranh\u00e3o", "2101772" }; + rows[1156] = new[] { "MA", "Bel\u00e1gua", "2101731" }; + rows[1157] = new[] { "MA", "Benedito Leite", "2101806" }; + rows[1158] = new[] { "MA", "Bequim\u00e3o", "2101905" }; + rows[1159] = new[] { "MA", "Bernardo do Mearim", "2101939" }; + rows[1160] = new[] { "MA", "Boa Vista do Gurupi", "2101970" }; + rows[1161] = new[] { "MA", "Bom Jardim", "2102002" }; + rows[1162] = new[] { "MA", "Bom Jesus das Selvas", "2102036" }; + rows[1163] = new[] { "MA", "Bom Lugar", "2102077" }; + rows[1164] = new[] { "MA", "Brejo", "2102101" }; + rows[1165] = new[] { "MA", "Brejo de Areia", "2102150" }; + rows[1166] = new[] { "MA", "Buriti", "2102200" }; + rows[1167] = new[] { "MA", "Buriti Bravo", "2102309" }; + rows[1168] = new[] { "MA", "Buriticupu", "2102325" }; + rows[1169] = new[] { "MA", "Buritirana", "2102358" }; + rows[1170] = new[] { "MA", "Cachoeira Grande", "2102374" }; + rows[1171] = new[] { "MA", "Cajapi\u00f3", "2102408" }; + rows[1172] = new[] { "MA", "Cajari", "2102507" }; + rows[1173] = new[] { "MA", "Campestre do Maranh\u00e3o", "2102556" }; + rows[1174] = new[] { "MA", "C\u00e2ndido Mendes", "2102606" }; + rows[1175] = new[] { "MA", "Cantanhede", "2102705" }; + rows[1176] = new[] { "MA", "Capinzal do Norte", "2102754" }; + rows[1177] = new[] { "MA", "Carolina", "2102804" }; + rows[1178] = new[] { "MA", "Carutapera", "2102903" }; + rows[1179] = new[] { "MA", "Caxias", "2103000" }; + rows[1180] = new[] { "MA", "Cedral", "2103109" }; + rows[1181] = new[] { "MA", "Central do Maranh\u00e3o", "2103125" }; + rows[1182] = new[] { "MA", "Centro do Guilherme", "2103158" }; + rows[1183] = new[] { "MA", "Centro Novo do Maranh\u00e3o", "2103174" }; + rows[1184] = new[] { "MA", "Chapadinha", "2103208" }; + rows[1185] = new[] { "MA", "Cidel\u00e2ndia", "2103257" }; + rows[1186] = new[] { "MA", "Cod\u00f3", "2103307" }; + rows[1187] = new[] { "MA", "Coelho Neto", "2103406" }; + rows[1188] = new[] { "MA", "Colinas", "2103505" }; + rows[1189] = new[] { "MA", "Concei\u00e7\u00e3o do Lago-A\u00e7u", "2103554" }; + rows[1190] = new[] { "MA", "Coroat\u00e1", "2103604" }; + rows[1191] = new[] { "MA", "Cururupu", "2103703" }; + rows[1192] = new[] { "MA", "Davin\u00f3polis", "2103752" }; + rows[1193] = new[] { "MA", "Dom Pedro", "2103802" }; + rows[1194] = new[] { "MA", "Duque Bacelar", "2103901" }; + rows[1195] = new[] { "MA", "Esperantin\u00f3polis", "2104008" }; + rows[1196] = new[] { "MA", "Estreito", "2104057" }; + rows[1197] = new[] { "MA", "Feira Nova do Maranh\u00e3o", "2104073" }; + rows[1198] = new[] { "MA", "Fernando Falc\u00e3o", "2104081" }; + rows[1199] = new[] { "MA", "Formosa da Serra Negra", "2104099" }; + } + + private static void MunicipalitiesRows6(string[][] rows) + { + rows[1200] = new[] { "MA", "Fortaleza dos Nogueiras", "2104107" }; + rows[1201] = new[] { "MA", "Fortuna", "2104206" }; + rows[1202] = new[] { "MA", "Godofredo Viana", "2104305" }; + rows[1203] = new[] { "MA", "Gon\u00e7alves Dias", "2104404" }; + rows[1204] = new[] { "MA", "Governador Archer", "2104503" }; + rows[1205] = new[] { "MA", "Governador Edison Lob\u00e3o", "2104552" }; + rows[1206] = new[] { "MA", "Governador Eug\u00eanio Barros", "2104602" }; + rows[1207] = new[] { "MA", "Governador Luiz Rocha", "2104628" }; + rows[1208] = new[] { "MA", "Governador Newton Bello", "2104651" }; + rows[1209] = new[] { "MA", "Governador Nunes Freire", "2104677" }; + rows[1210] = new[] { "MA", "Gra\u00e7a Aranha", "2104701" }; + rows[1211] = new[] { "MA", "Graja\u00fa", "2104800" }; + rows[1212] = new[] { "MA", "Guimar\u00e3es", "2104909" }; + rows[1213] = new[] { "MA", "Humberto de Campos", "2105005" }; + rows[1214] = new[] { "MA", "Icatu", "2105104" }; + rows[1215] = new[] { "MA", "Igarap\u00e9 do Meio", "2105153" }; + rows[1216] = new[] { "MA", "Igarap\u00e9 Grande", "2105203" }; + rows[1217] = new[] { "MA", "Imperatriz", "2105302" }; + rows[1218] = new[] { "MA", "Itaipava do Graja\u00fa", "2105351" }; + rows[1219] = new[] { "MA", "Itapecuru Mirim", "2105401" }; + rows[1220] = new[] { "MA", "Itinga do Maranh\u00e3o", "2105427" }; + rows[1221] = new[] { "MA", "Jatob\u00e1", "2105450" }; + rows[1222] = new[] { "MA", "Jenipapo dos Vieiras", "2105476" }; + rows[1223] = new[] { "MA", "Jo\u00e3o Lisboa", "2105500" }; + rows[1224] = new[] { "MA", "Josel\u00e2ndia", "2105609" }; + rows[1225] = new[] { "MA", "Junco do Maranh\u00e3o", "2105658" }; + rows[1226] = new[] { "MA", "Lago da Pedra", "2105708" }; + rows[1227] = new[] { "MA", "Lago do Junco", "2105807" }; + rows[1228] = new[] { "MA", "Lago dos Rodrigues", "2105948" }; + rows[1229] = new[] { "MA", "Lago Verde", "2105906" }; + rows[1230] = new[] { "MA", "Lagoa do Mato", "2105922" }; + rows[1231] = new[] { "MA", "Lagoa Grande do Maranh\u00e3o", "2105963" }; + rows[1232] = new[] { "MA", "Lajeado Novo", "2105989" }; + rows[1233] = new[] { "MA", "Lima Campos", "2106003" }; + rows[1234] = new[] { "MA", "Loreto", "2106102" }; + rows[1235] = new[] { "MA", "Lu\u00eds Domingues", "2106201" }; + rows[1236] = new[] { "MA", "Magalh\u00e3es de Almeida", "2106300" }; + rows[1237] = new[] { "MA", "Maraca\u00e7um\u00e9", "2106326" }; + rows[1238] = new[] { "MA", "Maraj\u00e1 do Sena", "2106359" }; + rows[1239] = new[] { "MA", "Maranh\u00e3ozinho", "2106375" }; + rows[1240] = new[] { "MA", "Mata Roma", "2106409" }; + rows[1241] = new[] { "MA", "Matinha", "2106508" }; + rows[1242] = new[] { "MA", "Mat\u00f5es", "2106607" }; + rows[1243] = new[] { "MA", "Mat\u00f5es do Norte", "2106631" }; + rows[1244] = new[] { "MA", "Milagres do Maranh\u00e3o", "2106672" }; + rows[1245] = new[] { "MA", "Mirador", "2106706" }; + rows[1246] = new[] { "MA", "Miranda do Norte", "2106755" }; + rows[1247] = new[] { "MA", "Mirinzal", "2106805" }; + rows[1248] = new[] { "MA", "Mon\u00e7\u00e3o", "2106904" }; + rows[1249] = new[] { "MA", "Montes Altos", "2107001" }; + rows[1250] = new[] { "MA", "Morros", "2107100" }; + rows[1251] = new[] { "MA", "Nina Rodrigues", "2107209" }; + rows[1252] = new[] { "MA", "Nova Colinas", "2107258" }; + rows[1253] = new[] { "MA", "Nova Iorque", "2107308" }; + rows[1254] = new[] { "MA", "Nova Olinda do Maranh\u00e3o", "2107357" }; + rows[1255] = new[] { "MA", "Olho d'\u00c1gua das Cunh\u00e3s", "2107407" }; + rows[1256] = new[] { "MA", "Olinda Nova do Maranh\u00e3o", "2107456" }; + rows[1257] = new[] { "MA", "Pa\u00e7o do Lumiar", "2107506" }; + rows[1258] = new[] { "MA", "Palmeir\u00e2ndia", "2107605" }; + rows[1259] = new[] { "MA", "Paraibano", "2107704" }; + rows[1260] = new[] { "MA", "Parnarama", "2107803" }; + rows[1261] = new[] { "MA", "Passagem Franca", "2107902" }; + rows[1262] = new[] { "MA", "Pastos Bons", "2108009" }; + rows[1263] = new[] { "MA", "Paulino Neves", "2108058" }; + rows[1264] = new[] { "MA", "Paulo Ramos", "2108108" }; + rows[1265] = new[] { "MA", "Pedreiras", "2108207" }; + rows[1266] = new[] { "MA", "Pedro do Ros\u00e1rio", "2108256" }; + rows[1267] = new[] { "MA", "Penalva", "2108306" }; + rows[1268] = new[] { "MA", "Peri Mirim", "2108405" }; + rows[1269] = new[] { "MA", "Peritor\u00f3", "2108454" }; + rows[1270] = new[] { "MA", "Pindar\u00e9-Mirim", "2108504" }; + rows[1271] = new[] { "MA", "Pinheiro", "2108603" }; + rows[1272] = new[] { "MA", "Pio XII", "2108702" }; + rows[1273] = new[] { "MA", "Pirapemas", "2108801" }; + rows[1274] = new[] { "MA", "Po\u00e7\u00e3o de Pedras", "2108900" }; + rows[1275] = new[] { "MA", "Porto Franco", "2109007" }; + rows[1276] = new[] { "MA", "Porto Rico do Maranh\u00e3o", "2109056" }; + rows[1277] = new[] { "MA", "Presidente Dutra", "2109106" }; + rows[1278] = new[] { "MA", "Presidente Juscelino", "2109205" }; + rows[1279] = new[] { "MA", "Presidente M\u00e9dici", "2109239" }; + rows[1280] = new[] { "MA", "Presidente Sarney", "2109270" }; + rows[1281] = new[] { "MA", "Presidente Vargas", "2109304" }; + rows[1282] = new[] { "MA", "Primeira Cruz", "2109403" }; + rows[1283] = new[] { "MA", "Raposa", "2109452" }; + rows[1284] = new[] { "MA", "Riach\u00e3o", "2109502" }; + rows[1285] = new[] { "MA", "Ribamar Fiquene", "2109551" }; + rows[1286] = new[] { "MA", "Ros\u00e1rio", "2109601" }; + rows[1287] = new[] { "MA", "Samba\u00edba", "2109700" }; + rows[1288] = new[] { "MA", "Santa Filomena do Maranh\u00e3o", "2109759" }; + rows[1289] = new[] { "MA", "Santa Helena", "2109809" }; + rows[1290] = new[] { "MA", "Santa In\u00eas", "2109908" }; + rows[1291] = new[] { "MA", "Santa Luzia", "2110005" }; + rows[1292] = new[] { "MA", "Santa Luzia do Paru\u00e1", "2110039" }; + rows[1293] = new[] { "MA", "Santa Quit\u00e9ria do Maranh\u00e3o", "2110104" }; + rows[1294] = new[] { "MA", "Santa Rita", "2110203" }; + rows[1295] = new[] { "MA", "Santana do Maranh\u00e3o", "2110237" }; + rows[1296] = new[] { "MA", "Santo Amaro do Maranh\u00e3o", "2110278" }; + rows[1297] = new[] { "MA", "Santo Ant\u00f4nio dos Lopes", "2110302" }; + rows[1298] = new[] { "MA", "S\u00e3o Benedito do Rio Preto", "2110401" }; + rows[1299] = new[] { "MA", "S\u00e3o Bento", "2110500" }; + rows[1300] = new[] { "MA", "S\u00e3o Bernardo", "2110609" }; + rows[1301] = new[] { "MA", "S\u00e3o Domingos do Azeit\u00e3o", "2110658" }; + rows[1302] = new[] { "MA", "S\u00e3o Domingos do Maranh\u00e3o", "2110708" }; + rows[1303] = new[] { "MA", "S\u00e3o F\u00e9lix de Balsas", "2110807" }; + rows[1304] = new[] { "MA", "S\u00e3o Francisco do Brej\u00e3o", "2110856" }; + rows[1305] = new[] { "MA", "S\u00e3o Francisco do Maranh\u00e3o", "2110906" }; + rows[1306] = new[] { "MA", "S\u00e3o Jo\u00e3o Batista", "2111003" }; + rows[1307] = new[] { "MA", "S\u00e3o Jo\u00e3o do Car\u00fa", "2111029" }; + rows[1308] = new[] { "MA", "S\u00e3o Jo\u00e3o do Para\u00edso", "2111052" }; + rows[1309] = new[] { "MA", "S\u00e3o Jo\u00e3o do Soter", "2111078" }; + rows[1310] = new[] { "MA", "S\u00e3o Jo\u00e3o dos Patos", "2111102" }; + rows[1311] = new[] { "MA", "S\u00e3o Jos\u00e9 de Ribamar", "2111201" }; + rows[1312] = new[] { "MA", "S\u00e3o Jos\u00e9 dos Bas\u00edlios", "2111250" }; + rows[1313] = new[] { "MA", "S\u00e3o Lu\u00eds", "2111300" }; + rows[1314] = new[] { "MA", "S\u00e3o Lu\u00eds Gonzaga do Maranh\u00e3o", "2111409" }; + rows[1315] = new[] { "MA", "S\u00e3o Mateus do Maranh\u00e3o", "2111508" }; + rows[1316] = new[] { "MA", "S\u00e3o Pedro da \u00c1gua Branca", "2111532" }; + rows[1317] = new[] { "MA", "S\u00e3o Pedro dos Crentes", "2111573" }; + rows[1318] = new[] { "MA", "S\u00e3o Raimundo das Mangabeiras", "2111607" }; + rows[1319] = new[] { "MA", "S\u00e3o Raimundo do Doca Bezerra", "2111631" }; + rows[1320] = new[] { "MA", "S\u00e3o Roberto", "2111672" }; + rows[1321] = new[] { "MA", "S\u00e3o Vicente Ferrer", "2111706" }; + rows[1322] = new[] { "MA", "Satubinha", "2111722" }; + rows[1323] = new[] { "MA", "Senador Alexandre Costa", "2111748" }; + rows[1324] = new[] { "MA", "Senador La Rocque", "2111763" }; + rows[1325] = new[] { "MA", "Serrano do Maranh\u00e3o", "2111789" }; + rows[1326] = new[] { "MA", "S\u00edtio Novo", "2111805" }; + rows[1327] = new[] { "MA", "Sucupira do Norte", "2111904" }; + rows[1328] = new[] { "MA", "Sucupira do Riach\u00e3o", "2111953" }; + rows[1329] = new[] { "MA", "Tasso Fragoso", "2112001" }; + rows[1330] = new[] { "MA", "Timbiras", "2112100" }; + rows[1331] = new[] { "MA", "Timon", "2112209" }; + rows[1332] = new[] { "MA", "Trizidela do Vale", "2112233" }; + rows[1333] = new[] { "MA", "Tufil\u00e2ndia", "2112274" }; + rows[1334] = new[] { "MA", "Tuntum", "2112308" }; + rows[1335] = new[] { "MA", "Turia\u00e7u", "2112407" }; + rows[1336] = new[] { "MA", "Turil\u00e2ndia", "2112456" }; + rows[1337] = new[] { "MA", "Tut\u00f3ia", "2112506" }; + rows[1338] = new[] { "MA", "Urbano Santos", "2112605" }; + rows[1339] = new[] { "MA", "Vargem Grande", "2112704" }; + rows[1340] = new[] { "MA", "Viana", "2112803" }; + rows[1341] = new[] { "MA", "Vila Nova dos Mart\u00edrios", "2112852" }; + rows[1342] = new[] { "MA", "Vit\u00f3ria do Mearim", "2112902" }; + rows[1343] = new[] { "MA", "Vitorino Freire", "2113009" }; + rows[1344] = new[] { "MA", "Z\u00e9 Doca", "2114007" }; + rows[1345] = new[] { "MT", "Acorizal", "5100102" }; + rows[1346] = new[] { "MT", "\u00c1gua Boa", "5100201" }; + rows[1347] = new[] { "MT", "Alta Floresta", "5100250" }; + rows[1348] = new[] { "MT", "Alto Araguaia", "5100300" }; + rows[1349] = new[] { "MT", "Alto Boa Vista", "5100359" }; + rows[1350] = new[] { "MT", "Alto Gar\u00e7as", "5100409" }; + rows[1351] = new[] { "MT", "Alto Paraguai", "5100508" }; + rows[1352] = new[] { "MT", "Alto Taquari", "5100607" }; + rows[1353] = new[] { "MT", "Apiac\u00e1s", "5100805" }; + rows[1354] = new[] { "MT", "Araguaiana", "5101001" }; + rows[1355] = new[] { "MT", "Araguainha", "5101209" }; + rows[1356] = new[] { "MT", "Araputanga", "5101258" }; + rows[1357] = new[] { "MT", "Aren\u00e1polis", "5101308" }; + rows[1358] = new[] { "MT", "Aripuan\u00e3", "5101407" }; + rows[1359] = new[] { "MT", "Bar\u00e3o de Melga\u00e7o", "5101605" }; + rows[1360] = new[] { "MT", "Barra do Bugres", "5101704" }; + rows[1361] = new[] { "MT", "Barra do Gar\u00e7as", "5101803" }; + rows[1362] = new[] { "MT", "Boa Esperan\u00e7a do Norte", "5101837" }; + rows[1363] = new[] { "MT", "Bom Jesus do Araguaia", "5101852" }; + rows[1364] = new[] { "MT", "Brasnorte", "5101902" }; + rows[1365] = new[] { "MT", "C\u00e1ceres", "5102504" }; + rows[1366] = new[] { "MT", "Campin\u00e1polis", "5102603" }; + rows[1367] = new[] { "MT", "Campo Novo do Parecis", "5102637" }; + rows[1368] = new[] { "MT", "Campo Verde", "5102678" }; + rows[1369] = new[] { "MT", "Campos de J\u00falio", "5102686" }; + rows[1370] = new[] { "MT", "Canabrava do Norte", "5102694" }; + rows[1371] = new[] { "MT", "Canarana", "5102702" }; + rows[1372] = new[] { "MT", "Carlinda", "5102793" }; + rows[1373] = new[] { "MT", "Castanheira", "5102850" }; + rows[1374] = new[] { "MT", "Chapada dos Guimar\u00e3es", "5103007" }; + rows[1375] = new[] { "MT", "Cl\u00e1udia", "5103056" }; + rows[1376] = new[] { "MT", "Cocalinho", "5103106" }; + rows[1377] = new[] { "MT", "Col\u00edder", "5103205" }; + rows[1378] = new[] { "MT", "Colniza", "5103254" }; + rows[1379] = new[] { "MT", "Comodoro", "5103304" }; + rows[1380] = new[] { "MT", "Confresa", "5103353" }; + rows[1381] = new[] { "MT", "Conquista D'Oeste", "5103361" }; + rows[1382] = new[] { "MT", "Cotrigua\u00e7u", "5103379" }; + rows[1383] = new[] { "MT", "Cuiab\u00e1", "5103403" }; + rows[1384] = new[] { "MT", "Curvel\u00e2ndia", "5103437" }; + rows[1385] = new[] { "MT", "Denise", "5103452" }; + rows[1386] = new[] { "MT", "Diamantino", "5103502" }; + rows[1387] = new[] { "MT", "Dom Aquino", "5103601" }; + rows[1388] = new[] { "MT", "Feliz Natal", "5103700" }; + rows[1389] = new[] { "MT", "Figueir\u00f3polis D'Oeste", "5103809" }; + rows[1390] = new[] { "MT", "Ga\u00facha do Norte", "5103858" }; + rows[1391] = new[] { "MT", "General Carneiro", "5103908" }; + rows[1392] = new[] { "MT", "Gl\u00f3ria D'Oeste", "5103957" }; + rows[1393] = new[] { "MT", "Guarant\u00e3 do Norte", "5104104" }; + rows[1394] = new[] { "MT", "Guiratinga", "5104203" }; + rows[1395] = new[] { "MT", "Indiava\u00ed", "5104500" }; + rows[1396] = new[] { "MT", "Ipiranga do Norte", "5104526" }; + rows[1397] = new[] { "MT", "Itanhang\u00e1", "5104542" }; + rows[1398] = new[] { "MT", "Ita\u00faba", "5104559" }; + rows[1399] = new[] { "MT", "Itiquira", "5104609" }; + } + + private static void MunicipalitiesRows7(string[][] rows) + { + rows[1400] = new[] { "MT", "Jaciara", "5104807" }; + rows[1401] = new[] { "MT", "Jangada", "5104906" }; + rows[1402] = new[] { "MT", "Jauru", "5105002" }; + rows[1403] = new[] { "MT", "Juara", "5105101" }; + rows[1404] = new[] { "MT", "Ju\u00edna", "5105150" }; + rows[1405] = new[] { "MT", "Juruena", "5105176" }; + rows[1406] = new[] { "MT", "Juscimeira", "5105200" }; + rows[1407] = new[] { "MT", "Lambari D'Oeste", "5105234" }; + rows[1408] = new[] { "MT", "Lucas do Rio Verde", "5105259" }; + rows[1409] = new[] { "MT", "Luciara", "5105309" }; + rows[1410] = new[] { "MT", "Marcel\u00e2ndia", "5105580" }; + rows[1411] = new[] { "MT", "Matup\u00e1", "5105606" }; + rows[1412] = new[] { "MT", "Mirassol d'Oeste", "5105622" }; + rows[1413] = new[] { "MT", "Nobres", "5105903" }; + rows[1414] = new[] { "MT", "Nortel\u00e2ndia", "5106000" }; + rows[1415] = new[] { "MT", "Nossa Senhora do Livramento", "5106109" }; + rows[1416] = new[] { "MT", "Nova Bandeirantes", "5106158" }; + rows[1417] = new[] { "MT", "Nova Brasil\u00e2ndia", "5106208" }; + rows[1418] = new[] { "MT", "Nova Cana\u00e3 do Norte", "5106216" }; + rows[1419] = new[] { "MT", "Nova Guarita", "5108808" }; + rows[1420] = new[] { "MT", "Nova Lacerda", "5106182" }; + rows[1421] = new[] { "MT", "Nova Maril\u00e2ndia", "5108857" }; + rows[1422] = new[] { "MT", "Nova Maring\u00e1", "5108907" }; + rows[1423] = new[] { "MT", "Nova Monte Verde", "5108956" }; + rows[1424] = new[] { "MT", "Nova Mutum", "5106224" }; + rows[1425] = new[] { "MT", "Nova Nazar\u00e9", "5106174" }; + rows[1426] = new[] { "MT", "Nova Ol\u00edmpia", "5106232" }; + rows[1427] = new[] { "MT", "Nova Santa Helena", "5106190" }; + rows[1428] = new[] { "MT", "Nova Ubirat\u00e3", "5106240" }; + rows[1429] = new[] { "MT", "Nova Xavantina", "5106257" }; + rows[1430] = new[] { "MT", "Novo Horizonte do Norte", "5106273" }; + rows[1431] = new[] { "MT", "Novo Mundo", "5106265" }; + rows[1432] = new[] { "MT", "Novo Santo Ant\u00f4nio", "5106315" }; + rows[1433] = new[] { "MT", "Novo S\u00e3o Joaquim", "5106281" }; + rows[1434] = new[] { "MT", "Parana\u00edta", "5106299" }; + rows[1435] = new[] { "MT", "Paranatinga", "5106307" }; + rows[1436] = new[] { "MT", "Pedra Preta", "5106372" }; + rows[1437] = new[] { "MT", "Peixoto de Azevedo", "5106422" }; + rows[1438] = new[] { "MT", "Planalto da Serra", "5106455" }; + rows[1439] = new[] { "MT", "Pocon\u00e9", "5106505" }; + rows[1440] = new[] { "MT", "Pontal do Araguaia", "5106653" }; + rows[1441] = new[] { "MT", "Ponte Branca", "5106703" }; + rows[1442] = new[] { "MT", "Pontes e Lacerda", "5106752" }; + rows[1443] = new[] { "MT", "Porto Alegre do Norte", "5106778" }; + rows[1444] = new[] { "MT", "Porto dos Ga\u00fachos", "5106802" }; + rows[1445] = new[] { "MT", "Porto Esperidi\u00e3o", "5106828" }; + rows[1446] = new[] { "MT", "Porto Estrela", "5106851" }; + rows[1447] = new[] { "MT", "Poxor\u00e9u", "5107008" }; + rows[1448] = new[] { "MT", "Primavera do Leste", "5107040" }; + rows[1449] = new[] { "MT", "Quer\u00eancia", "5107065" }; + rows[1450] = new[] { "MT", "Reserva do Caba\u00e7al", "5107156" }; + rows[1451] = new[] { "MT", "Ribeir\u00e3o Cascalheira", "5107180" }; + rows[1452] = new[] { "MT", "Ribeir\u00e3ozinho", "5107198" }; + rows[1453] = new[] { "MT", "Rio Branco", "5107206" }; + rows[1454] = new[] { "MT", "Rondol\u00e2ndia", "5107578" }; + rows[1455] = new[] { "MT", "Rondon\u00f3polis", "5107602" }; + rows[1456] = new[] { "MT", "Ros\u00e1rio Oeste", "5107701" }; + rows[1457] = new[] { "MT", "Salto do C\u00e9u", "5107750" }; + rows[1458] = new[] { "MT", "Santa Carmem", "5107248" }; + rows[1459] = new[] { "MT", "Santa Cruz do Xingu", "5107743" }; + rows[1460] = new[] { "MT", "Santa Rita do Trivelato", "5107768" }; + rows[1461] = new[] { "MT", "Santa Terezinha", "5107776" }; + rows[1462] = new[] { "MT", "Santo Afonso", "5107263" }; + rows[1463] = new[] { "MT", "Santo Ant\u00f4nio de Leverger", "5107800" }; + rows[1464] = new[] { "MT", "Santo Ant\u00f4nio do Leste", "5107792" }; + rows[1465] = new[] { "MT", "S\u00e3o F\u00e9lix do Araguaia", "5107859" }; + rows[1466] = new[] { "MT", "S\u00e3o Jos\u00e9 do Povo", "5107297" }; + rows[1467] = new[] { "MT", "S\u00e3o Jos\u00e9 do Rio Claro", "5107305" }; + rows[1468] = new[] { "MT", "S\u00e3o Jos\u00e9 do Xingu", "5107354" }; + rows[1469] = new[] { "MT", "S\u00e3o Jos\u00e9 dos Quatro Marcos", "5107107" }; + rows[1470] = new[] { "MT", "S\u00e3o Pedro da Cipa", "5107404" }; + rows[1471] = new[] { "MT", "Sapezal", "5107875" }; + rows[1472] = new[] { "MT", "Serra Nova Dourada", "5107883" }; + rows[1473] = new[] { "MT", "Sinop", "5107909" }; + rows[1474] = new[] { "MT", "Sorriso", "5107925" }; + rows[1475] = new[] { "MT", "Tabapor\u00e3", "5107941" }; + rows[1476] = new[] { "MT", "Tangar\u00e1 da Serra", "5107958" }; + rows[1477] = new[] { "MT", "Tapurah", "5108006" }; + rows[1478] = new[] { "MT", "Terra Nova do Norte", "5108055" }; + rows[1479] = new[] { "MT", "Tesouro", "5108105" }; + rows[1480] = new[] { "MT", "Torixor\u00e9u", "5108204" }; + rows[1481] = new[] { "MT", "Uni\u00e3o do Sul", "5108303" }; + rows[1482] = new[] { "MT", "Vale de S\u00e3o Domingos", "5108352" }; + rows[1483] = new[] { "MT", "V\u00e1rzea Grande", "5108402" }; + rows[1484] = new[] { "MT", "Vera", "5108501" }; + rows[1485] = new[] { "MT", "Vila Bela da Sant\u00edssima Trindade", "5105507" }; + rows[1486] = new[] { "MT", "Vila Rica", "5108600" }; + rows[1487] = new[] { "MS", "\u00c1gua Clara", "5000203" }; + rows[1488] = new[] { "MS", "Alcin\u00f3polis", "5000252" }; + rows[1489] = new[] { "MS", "Amambai", "5000609" }; + rows[1490] = new[] { "MS", "Anast\u00e1cio", "5000708" }; + rows[1491] = new[] { "MS", "Anauril\u00e2ndia", "5000807" }; + rows[1492] = new[] { "MS", "Ang\u00e9lica", "5000856" }; + rows[1493] = new[] { "MS", "Ant\u00f4nio Jo\u00e3o", "5000906" }; + rows[1494] = new[] { "MS", "Aparecida do Taboado", "5001003" }; + rows[1495] = new[] { "MS", "Aquidauana", "5001102" }; + rows[1496] = new[] { "MS", "Aral Moreira", "5001243" }; + rows[1497] = new[] { "MS", "Bandeirantes", "5001508" }; + rows[1498] = new[] { "MS", "Bataguassu", "5001904" }; + rows[1499] = new[] { "MS", "Bataypor\u00e3", "5002001" }; + rows[1500] = new[] { "MS", "Bela Vista", "5002100" }; + rows[1501] = new[] { "MS", "Bodoquena", "5002159" }; + rows[1502] = new[] { "MS", "Bonito", "5002209" }; + rows[1503] = new[] { "MS", "Brasil\u00e2ndia", "5002308" }; + rows[1504] = new[] { "MS", "Caarap\u00f3", "5002407" }; + rows[1505] = new[] { "MS", "Camapu\u00e3", "5002605" }; + rows[1506] = new[] { "MS", "Campo Grande", "5002704" }; + rows[1507] = new[] { "MS", "Caracol", "5002803" }; + rows[1508] = new[] { "MS", "Cassil\u00e2ndia", "5002902" }; + rows[1509] = new[] { "MS", "Chapad\u00e3o do Sul", "5002951" }; + rows[1510] = new[] { "MS", "Corguinho", "5003108" }; + rows[1511] = new[] { "MS", "Coronel Sapucaia", "5003157" }; + rows[1512] = new[] { "MS", "Corumb\u00e1", "5003207" }; + rows[1513] = new[] { "MS", "Costa Rica", "5003256" }; + rows[1514] = new[] { "MS", "Coxim", "5003306" }; + rows[1515] = new[] { "MS", "Deod\u00e1polis", "5003454" }; + rows[1516] = new[] { "MS", "Dois Irm\u00e3os do Buriti", "5003488" }; + rows[1517] = new[] { "MS", "Douradina", "5003504" }; + rows[1518] = new[] { "MS", "Dourados", "5003702" }; + rows[1519] = new[] { "MS", "Eldorado", "5003751" }; + rows[1520] = new[] { "MS", "F\u00e1tima do Sul", "5003801" }; + rows[1521] = new[] { "MS", "Figueir\u00e3o", "5003900" }; + rows[1522] = new[] { "MS", "Gl\u00f3ria de Dourados", "5004007" }; + rows[1523] = new[] { "MS", "Guia Lopes da Laguna", "5004106" }; + rows[1524] = new[] { "MS", "Iguatemi", "5004304" }; + rows[1525] = new[] { "MS", "Inoc\u00eancia", "5004403" }; + rows[1526] = new[] { "MS", "Itapor\u00e3", "5004502" }; + rows[1527] = new[] { "MS", "Itaquira\u00ed", "5004601" }; + rows[1528] = new[] { "MS", "Ivinhema", "5004700" }; + rows[1529] = new[] { "MS", "Japor\u00e3", "5004809" }; + rows[1530] = new[] { "MS", "Jaraguari", "5004908" }; + rows[1531] = new[] { "MS", "Jardim", "5005004" }; + rows[1532] = new[] { "MS", "Jate\u00ed", "5005103" }; + rows[1533] = new[] { "MS", "Juti", "5005152" }; + rows[1534] = new[] { "MS", "Lad\u00e1rio", "5005202" }; + rows[1535] = new[] { "MS", "Laguna Carap\u00e3", "5005251" }; + rows[1536] = new[] { "MS", "Maracaju", "5005400" }; + rows[1537] = new[] { "MS", "Miranda", "5005608" }; + rows[1538] = new[] { "MS", "Mundo Novo", "5005681" }; + rows[1539] = new[] { "MS", "Navira\u00ed", "5005707" }; + rows[1540] = new[] { "MS", "Nioaque", "5005806" }; + rows[1541] = new[] { "MS", "Nova Alvorada do Sul", "5006002" }; + rows[1542] = new[] { "MS", "Nova Andradina", "5006200" }; + rows[1543] = new[] { "MS", "Novo Horizonte do Sul", "5006259" }; + rows[1544] = new[] { "MS", "Para\u00edso das \u00c1guas", "5006275" }; + rows[1545] = new[] { "MS", "Parana\u00edba", "5006309" }; + rows[1546] = new[] { "MS", "Paranhos", "5006358" }; + rows[1547] = new[] { "MS", "Pedro Gomes", "5006408" }; + rows[1548] = new[] { "MS", "Ponta Por\u00e3", "5006606" }; + rows[1549] = new[] { "MS", "Porto Murtinho", "5006903" }; + rows[1550] = new[] { "MS", "Ribas do Rio Pardo", "5007109" }; + rows[1551] = new[] { "MS", "Rio Brilhante", "5007208" }; + rows[1552] = new[] { "MS", "Rio Negro", "5007307" }; + rows[1553] = new[] { "MS", "Rio Verde de Mato Grosso", "5007406" }; + rows[1554] = new[] { "MS", "Rochedo", "5007505" }; + rows[1555] = new[] { "MS", "Santa Rita do Pardo", "5007554" }; + rows[1556] = new[] { "MS", "S\u00e3o Gabriel do Oeste", "5007695" }; + rows[1557] = new[] { "MS", "Selv\u00edria", "5007802" }; + rows[1558] = new[] { "MS", "Sete Quedas", "5007703" }; + rows[1559] = new[] { "MS", "Sidrol\u00e2ndia", "5007901" }; + rows[1560] = new[] { "MS", "Sonora", "5007935" }; + rows[1561] = new[] { "MS", "Tacuru", "5007950" }; + rows[1562] = new[] { "MS", "Taquarussu", "5007976" }; + rows[1563] = new[] { "MS", "Terenos", "5008008" }; + rows[1564] = new[] { "MS", "Tr\u00eas Lagoas", "5008305" }; + rows[1565] = new[] { "MS", "Vicentina", "5008404" }; + rows[1566] = new[] { "MG", "Abadia dos Dourados", "3100104" }; + rows[1567] = new[] { "MG", "Abaet\u00e9", "3100203" }; + rows[1568] = new[] { "MG", "Abre Campo", "3100302" }; + rows[1569] = new[] { "MG", "Acaiaca", "3100401" }; + rows[1570] = new[] { "MG", "A\u00e7ucena", "3100500" }; + rows[1571] = new[] { "MG", "\u00c1gua Boa", "3100609" }; + rows[1572] = new[] { "MG", "\u00c1gua Comprida", "3100708" }; + rows[1573] = new[] { "MG", "Aguanil", "3100807" }; + rows[1574] = new[] { "MG", "\u00c1guas Formosas", "3100906" }; + rows[1575] = new[] { "MG", "\u00c1guas Vermelhas", "3101003" }; + rows[1576] = new[] { "MG", "Aimor\u00e9s", "3101102" }; + rows[1577] = new[] { "MG", "Aiuruoca", "3101201" }; + rows[1578] = new[] { "MG", "Alagoa", "3101300" }; + rows[1579] = new[] { "MG", "Albertina", "3101409" }; + rows[1580] = new[] { "MG", "Al\u00e9m Para\u00edba", "3101508" }; + rows[1581] = new[] { "MG", "Alfenas", "3101607" }; + rows[1582] = new[] { "MG", "Alfredo Vasconcelos", "3101631" }; + rows[1583] = new[] { "MG", "Almenara", "3101706" }; + rows[1584] = new[] { "MG", "Alpercata", "3101805" }; + rows[1585] = new[] { "MG", "Alpin\u00f3polis", "3101904" }; + rows[1586] = new[] { "MG", "Alterosa", "3102001" }; + rows[1587] = new[] { "MG", "Alto Capara\u00f3", "3102050" }; + rows[1588] = new[] { "MG", "Alto Jequitib\u00e1", "3153509" }; + rows[1589] = new[] { "MG", "Alto Rio Doce", "3102100" }; + rows[1590] = new[] { "MG", "Alvarenga", "3102209" }; + rows[1591] = new[] { "MG", "Alvin\u00f3polis", "3102308" }; + rows[1592] = new[] { "MG", "Alvorada de Minas", "3102407" }; + rows[1593] = new[] { "MG", "Amparo do Serra", "3102506" }; + rows[1594] = new[] { "MG", "Andradas", "3102605" }; + rows[1595] = new[] { "MG", "Andrel\u00e2ndia", "3102803" }; + rows[1596] = new[] { "MG", "Angel\u00e2ndia", "3102852" }; + rows[1597] = new[] { "MG", "Ant\u00f4nio Carlos", "3102902" }; + rows[1598] = new[] { "MG", "Ant\u00f4nio Dias", "3103009" }; + rows[1599] = new[] { "MG", "Ant\u00f4nio Prado de Minas", "3103108" }; + } + + private static void MunicipalitiesRows8(string[][] rows) + { + rows[1600] = new[] { "MG", "Ara\u00e7a\u00ed", "3103207" }; + rows[1601] = new[] { "MG", "Aracitaba", "3103306" }; + rows[1602] = new[] { "MG", "Ara\u00e7ua\u00ed", "3103405" }; + rows[1603] = new[] { "MG", "Araguari", "3103504" }; + rows[1604] = new[] { "MG", "Arantina", "3103603" }; + rows[1605] = new[] { "MG", "Araponga", "3103702" }; + rows[1606] = new[] { "MG", "Arapor\u00e3", "3103751" }; + rows[1607] = new[] { "MG", "Arapu\u00e1", "3103801" }; + rows[1608] = new[] { "MG", "Ara\u00fajos", "3103900" }; + rows[1609] = new[] { "MG", "Arax\u00e1", "3104007" }; + rows[1610] = new[] { "MG", "Arceburgo", "3104106" }; + rows[1611] = new[] { "MG", "Arcos", "3104205" }; + rows[1612] = new[] { "MG", "Areado", "3104304" }; + rows[1613] = new[] { "MG", "Argirita", "3104403" }; + rows[1614] = new[] { "MG", "Aricanduva", "3104452" }; + rows[1615] = new[] { "MG", "Arinos", "3104502" }; + rows[1616] = new[] { "MG", "Astolfo Dutra", "3104601" }; + rows[1617] = new[] { "MG", "Atal\u00e9ia", "3104700" }; + rows[1618] = new[] { "MG", "Augusto de Lima", "3104809" }; + rows[1619] = new[] { "MG", "Baependi", "3104908" }; + rows[1620] = new[] { "MG", "Baldim", "3105004" }; + rows[1621] = new[] { "MG", "Bambu\u00ed", "3105103" }; + rows[1622] = new[] { "MG", "Bandeira", "3105202" }; + rows[1623] = new[] { "MG", "Bandeira do Sul", "3105301" }; + rows[1624] = new[] { "MG", "Bar\u00e3o de Cocais", "3105400" }; + rows[1625] = new[] { "MG", "Bar\u00e3o do Monte Alto", "3105509" }; + rows[1626] = new[] { "MG", "Barbacena", "3105608" }; + rows[1627] = new[] { "MG", "Barra Longa", "3105707" }; + rows[1628] = new[] { "MG", "Barroso", "3105905" }; + rows[1629] = new[] { "MG", "Bela Vista de Minas", "3106002" }; + rows[1630] = new[] { "MG", "Belmiro Braga", "3106101" }; + rows[1631] = new[] { "MG", "Belo Horizonte", "3106200" }; + rows[1632] = new[] { "MG", "Belo Oriente", "3106309" }; + rows[1633] = new[] { "MG", "Belo Vale", "3106408" }; + rows[1634] = new[] { "MG", "Berilo", "3106507" }; + rows[1635] = new[] { "MG", "Berizal", "3106655" }; + rows[1636] = new[] { "MG", "Bert\u00f3polis", "3106606" }; + rows[1637] = new[] { "MG", "Betim", "3106705" }; + rows[1638] = new[] { "MG", "Bias Fortes", "3106804" }; + rows[1639] = new[] { "MG", "Bicas", "3106903" }; + rows[1640] = new[] { "MG", "Biquinhas", "3107000" }; + rows[1641] = new[] { "MG", "Boa Esperan\u00e7a", "3107109" }; + rows[1642] = new[] { "MG", "Bocaina de Minas", "3107208" }; + rows[1643] = new[] { "MG", "Bocai\u00fava", "3107307" }; + rows[1644] = new[] { "MG", "Bom Despacho", "3107406" }; + rows[1645] = new[] { "MG", "Bom Jardim de Minas", "3107505" }; + rows[1646] = new[] { "MG", "Bom Jesus da Penha", "3107604" }; + rows[1647] = new[] { "MG", "Bom Jesus do Amparo", "3107703" }; + rows[1648] = new[] { "MG", "Bom Jesus do Galho", "3107802" }; + rows[1649] = new[] { "MG", "Bom Repouso", "3107901" }; + rows[1650] = new[] { "MG", "Bom Sucesso", "3108008" }; + rows[1651] = new[] { "MG", "Bonfim", "3108107" }; + rows[1652] = new[] { "MG", "Bonfin\u00f3polis de Minas", "3108206" }; + rows[1653] = new[] { "MG", "Bonito de Minas", "3108255" }; + rows[1654] = new[] { "MG", "Borda da Mata", "3108305" }; + rows[1655] = new[] { "MG", "Botelhos", "3108404" }; + rows[1656] = new[] { "MG", "Botumirim", "3108503" }; + rows[1657] = new[] { "MG", "Br\u00e1s Pires", "3108701" }; + rows[1658] = new[] { "MG", "Brasil\u00e2ndia de Minas", "3108552" }; + rows[1659] = new[] { "MG", "Bras\u00edlia de Minas", "3108602" }; + rows[1660] = new[] { "MG", "Bra\u00fanas", "3108800" }; + rows[1661] = new[] { "MG", "Braz\u00f3polis", "3108909" }; + rows[1662] = new[] { "MG", "Brumadinho", "3109006" }; + rows[1663] = new[] { "MG", "Bueno Brand\u00e3o", "3109105" }; + rows[1664] = new[] { "MG", "Buen\u00f3polis", "3109204" }; + rows[1665] = new[] { "MG", "Bugre", "3109253" }; + rows[1666] = new[] { "MG", "Buritis", "3109303" }; + rows[1667] = new[] { "MG", "Buritizeiro", "3109402" }; + rows[1668] = new[] { "MG", "Cabeceira Grande", "3109451" }; + rows[1669] = new[] { "MG", "Cabo Verde", "3109501" }; + rows[1670] = new[] { "MG", "Cachoeira da Prata", "3109600" }; + rows[1671] = new[] { "MG", "Cachoeira de Minas", "3109709" }; + rows[1672] = new[] { "MG", "Cachoeira de Paje\u00fa", "3102704" }; + rows[1673] = new[] { "MG", "Cachoeira Dourada", "3109808" }; + rows[1674] = new[] { "MG", "Caetan\u00f3polis", "3109907" }; + rows[1675] = new[] { "MG", "Caet\u00e9", "3110004" }; + rows[1676] = new[] { "MG", "Caiana", "3110103" }; + rows[1677] = new[] { "MG", "Cajuri", "3110202" }; + rows[1678] = new[] { "MG", "Caldas", "3110301" }; + rows[1679] = new[] { "MG", "Camacho", "3110400" }; + rows[1680] = new[] { "MG", "Camanducaia", "3110509" }; + rows[1681] = new[] { "MG", "Cambu\u00ed", "3110608" }; + rows[1682] = new[] { "MG", "Cambuquira", "3110707" }; + rows[1683] = new[] { "MG", "Campan\u00e1rio", "3110806" }; + rows[1684] = new[] { "MG", "Campanha", "3110905" }; + rows[1685] = new[] { "MG", "Campestre", "3111002" }; + rows[1686] = new[] { "MG", "Campina Verde", "3111101" }; + rows[1687] = new[] { "MG", "Campo Azul", "3111150" }; + rows[1688] = new[] { "MG", "Campo Belo", "3111200" }; + rows[1689] = new[] { "MG", "Campo do Meio", "3111309" }; + rows[1690] = new[] { "MG", "Campo Florido", "3111408" }; + rows[1691] = new[] { "MG", "Campos Altos", "3111507" }; + rows[1692] = new[] { "MG", "Campos Gerais", "3111606" }; + rows[1693] = new[] { "MG", "Cana Verde", "3111903" }; + rows[1694] = new[] { "MG", "Cana\u00e3", "3111705" }; + rows[1695] = new[] { "MG", "Can\u00e1polis", "3111804" }; + rows[1696] = new[] { "MG", "Candeias", "3112000" }; + rows[1697] = new[] { "MG", "Cantagalo", "3112059" }; + rows[1698] = new[] { "MG", "Capara\u00f3", "3112109" }; + rows[1699] = new[] { "MG", "Capela Nova", "3112208" }; + rows[1700] = new[] { "MG", "Capelinha", "3112307" }; + rows[1701] = new[] { "MG", "Capetinga", "3112406" }; + rows[1702] = new[] { "MG", "Capim Branco", "3112505" }; + rows[1703] = new[] { "MG", "Capin\u00f3polis", "3112604" }; + rows[1704] = new[] { "MG", "Capit\u00e3o Andrade", "3112653" }; + rows[1705] = new[] { "MG", "Capit\u00e3o En\u00e9as", "3112703" }; + rows[1706] = new[] { "MG", "Capit\u00f3lio", "3112802" }; + rows[1707] = new[] { "MG", "Caputira", "3112901" }; + rows[1708] = new[] { "MG", "Cara\u00ed", "3113008" }; + rows[1709] = new[] { "MG", "Carana\u00edba", "3113107" }; + rows[1710] = new[] { "MG", "Caranda\u00ed", "3113206" }; + rows[1711] = new[] { "MG", "Carangola", "3113305" }; + rows[1712] = new[] { "MG", "Caratinga", "3113404" }; + rows[1713] = new[] { "MG", "Carbonita", "3113503" }; + rows[1714] = new[] { "MG", "Carea\u00e7u", "3113602" }; + rows[1715] = new[] { "MG", "Carlos Chagas", "3113701" }; + rows[1716] = new[] { "MG", "Carm\u00e9sia", "3113800" }; + rows[1717] = new[] { "MG", "Carmo da Cachoeira", "3113909" }; + rows[1718] = new[] { "MG", "Carmo da Mata", "3114006" }; + rows[1719] = new[] { "MG", "Carmo de Minas", "3114105" }; + rows[1720] = new[] { "MG", "Carmo do Cajuru", "3114204" }; + rows[1721] = new[] { "MG", "Carmo do Parana\u00edba", "3114303" }; + rows[1722] = new[] { "MG", "Carmo do Rio Claro", "3114402" }; + rows[1723] = new[] { "MG", "Carm\u00f3polis de Minas", "3114501" }; + rows[1724] = new[] { "MG", "Carneirinho", "3114550" }; + rows[1725] = new[] { "MG", "Carrancas", "3114600" }; + rows[1726] = new[] { "MG", "Carvalh\u00f3polis", "3114709" }; + rows[1727] = new[] { "MG", "Carvalhos", "3114808" }; + rows[1728] = new[] { "MG", "Casa Grande", "3114907" }; + rows[1729] = new[] { "MG", "Cascalho Rico", "3115003" }; + rows[1730] = new[] { "MG", "C\u00e1ssia", "3115102" }; + rows[1731] = new[] { "MG", "Cataguases", "3115300" }; + rows[1732] = new[] { "MG", "Catas Altas", "3115359" }; + rows[1733] = new[] { "MG", "Catas Altas da Noruega", "3115409" }; + rows[1734] = new[] { "MG", "Catuji", "3115458" }; + rows[1735] = new[] { "MG", "Catuti", "3115474" }; + rows[1736] = new[] { "MG", "Caxambu", "3115508" }; + rows[1737] = new[] { "MG", "Cedro do Abaet\u00e9", "3115607" }; + rows[1738] = new[] { "MG", "Central de Minas", "3115706" }; + rows[1739] = new[] { "MG", "Centralina", "3115805" }; + rows[1740] = new[] { "MG", "Ch\u00e1cara", "3115904" }; + rows[1741] = new[] { "MG", "Chal\u00e9", "3116001" }; + rows[1742] = new[] { "MG", "Chapada do Norte", "3116100" }; + rows[1743] = new[] { "MG", "Chapada Ga\u00facha", "3116159" }; + rows[1744] = new[] { "MG", "Chiador", "3116209" }; + rows[1745] = new[] { "MG", "Cipot\u00e2nea", "3116308" }; + rows[1746] = new[] { "MG", "Claraval", "3116407" }; + rows[1747] = new[] { "MG", "Claro dos Po\u00e7\u00f5es", "3116506" }; + rows[1748] = new[] { "MG", "Cl\u00e1udio", "3116605" }; + rows[1749] = new[] { "MG", "Coimbra", "3116704" }; + rows[1750] = new[] { "MG", "Coluna", "3116803" }; + rows[1751] = new[] { "MG", "Comendador Gomes", "3116902" }; + rows[1752] = new[] { "MG", "Comercinho", "3117009" }; + rows[1753] = new[] { "MG", "Concei\u00e7\u00e3o da Aparecida", "3117108" }; + rows[1754] = new[] { "MG", "Concei\u00e7\u00e3o da Barra de Minas", "3115201" }; + rows[1755] = new[] { "MG", "Concei\u00e7\u00e3o das Alagoas", "3117306" }; + rows[1756] = new[] { "MG", "Concei\u00e7\u00e3o das Pedras", "3117207" }; + rows[1757] = new[] { "MG", "Concei\u00e7\u00e3o de Ipanema", "3117405" }; + rows[1758] = new[] { "MG", "Concei\u00e7\u00e3o do Mato Dentro", "3117504" }; + rows[1759] = new[] { "MG", "Concei\u00e7\u00e3o do Par\u00e1", "3117603" }; + rows[1760] = new[] { "MG", "Concei\u00e7\u00e3o do Rio Verde", "3117702" }; + rows[1761] = new[] { "MG", "Concei\u00e7\u00e3o dos Ouros", "3117801" }; + rows[1762] = new[] { "MG", "C\u00f4nego Marinho", "3117836" }; + rows[1763] = new[] { "MG", "Confins", "3117876" }; + rows[1764] = new[] { "MG", "Congonhal", "3117900" }; + rows[1765] = new[] { "MG", "Congonhas", "3118007" }; + rows[1766] = new[] { "MG", "Congonhas do Norte", "3118106" }; + rows[1767] = new[] { "MG", "Conquista", "3118205" }; + rows[1768] = new[] { "MG", "Conselheiro Lafaiete", "3118304" }; + rows[1769] = new[] { "MG", "Conselheiro Pena", "3118403" }; + rows[1770] = new[] { "MG", "Consola\u00e7\u00e3o", "3118502" }; + rows[1771] = new[] { "MG", "Contagem", "3118601" }; + rows[1772] = new[] { "MG", "Coqueiral", "3118700" }; + rows[1773] = new[] { "MG", "Cora\u00e7\u00e3o de Jesus", "3118809" }; + rows[1774] = new[] { "MG", "Cordisburgo", "3118908" }; + rows[1775] = new[] { "MG", "Cordisl\u00e2ndia", "3119005" }; + rows[1776] = new[] { "MG", "Corinto", "3119104" }; + rows[1777] = new[] { "MG", "Coroaci", "3119203" }; + rows[1778] = new[] { "MG", "Coromandel", "3119302" }; + rows[1779] = new[] { "MG", "Coronel Fabriciano", "3119401" }; + rows[1780] = new[] { "MG", "Coronel Murta", "3119500" }; + rows[1781] = new[] { "MG", "Coronel Pacheco", "3119609" }; + rows[1782] = new[] { "MG", "Coronel Xavier Chaves", "3119708" }; + rows[1783] = new[] { "MG", "C\u00f3rrego Danta", "3119807" }; + rows[1784] = new[] { "MG", "C\u00f3rrego do Bom Jesus", "3119906" }; + rows[1785] = new[] { "MG", "C\u00f3rrego Fundo", "3119955" }; + rows[1786] = new[] { "MG", "C\u00f3rrego Novo", "3120003" }; + rows[1787] = new[] { "MG", "Couto de Magalh\u00e3es de Minas", "3120102" }; + rows[1788] = new[] { "MG", "Cris\u00f3lita", "3120151" }; + rows[1789] = new[] { "MG", "Cristais", "3120201" }; + rows[1790] = new[] { "MG", "Crist\u00e1lia", "3120300" }; + rows[1791] = new[] { "MG", "Cristiano Otoni", "3120409" }; + rows[1792] = new[] { "MG", "Cristina", "3120508" }; + rows[1793] = new[] { "MG", "Crucil\u00e2ndia", "3120607" }; + rows[1794] = new[] { "MG", "Cruzeiro da Fortaleza", "3120706" }; + rows[1795] = new[] { "MG", "Cruz\u00edlia", "3120805" }; + rows[1796] = new[] { "MG", "Cuparaque", "3120839" }; + rows[1797] = new[] { "MG", "Curral de Dentro", "3120870" }; + rows[1798] = new[] { "MG", "Curvelo", "3120904" }; + rows[1799] = new[] { "MG", "Datas", "3121001" }; + } + + private static void MunicipalitiesRows9(string[][] rows) + { + rows[1800] = new[] { "MG", "Delfim Moreira", "3121100" }; + rows[1801] = new[] { "MG", "Delfin\u00f3polis", "3121209" }; + rows[1802] = new[] { "MG", "Delta", "3121258" }; + rows[1803] = new[] { "MG", "Descoberto", "3121308" }; + rows[1804] = new[] { "MG", "Desterro de Entre Rios", "3121407" }; + rows[1805] = new[] { "MG", "Desterro do Melo", "3121506" }; + rows[1806] = new[] { "MG", "Diamantina", "3121605" }; + rows[1807] = new[] { "MG", "Diogo de Vasconcelos", "3121704" }; + rows[1808] = new[] { "MG", "Dion\u00edsio", "3121803" }; + rows[1809] = new[] { "MG", "Divin\u00e9sia", "3121902" }; + rows[1810] = new[] { "MG", "Divino", "3122009" }; + rows[1811] = new[] { "MG", "Divino das Laranjeiras", "3122108" }; + rows[1812] = new[] { "MG", "Divinol\u00e2ndia de Minas", "3122207" }; + rows[1813] = new[] { "MG", "Divin\u00f3polis", "3122306" }; + rows[1814] = new[] { "MG", "Divisa Alegre", "3122355" }; + rows[1815] = new[] { "MG", "Divisa Nova", "3122405" }; + rows[1816] = new[] { "MG", "Divis\u00f3polis", "3122454" }; + rows[1817] = new[] { "MG", "Dom Bosco", "3122470" }; + rows[1818] = new[] { "MG", "Dom Cavati", "3122504" }; + rows[1819] = new[] { "MG", "Dom Joaquim", "3122603" }; + rows[1820] = new[] { "MG", "Dom Silv\u00e9rio", "3122702" }; + rows[1821] = new[] { "MG", "Dom Vi\u00e7oso", "3122801" }; + rows[1822] = new[] { "MG", "Dona Euz\u00e9bia", "3122900" }; + rows[1823] = new[] { "MG", "Dores de Campos", "3123007" }; + rows[1824] = new[] { "MG", "Dores de Guanh\u00e3es", "3123106" }; + rows[1825] = new[] { "MG", "Dores do Indai\u00e1", "3123205" }; + rows[1826] = new[] { "MG", "Dores do Turvo", "3123304" }; + rows[1827] = new[] { "MG", "Dores\u00f3polis", "3123403" }; + rows[1828] = new[] { "MG", "Douradoquara", "3123502" }; + rows[1829] = new[] { "MG", "Durand\u00e9", "3123528" }; + rows[1830] = new[] { "MG", "El\u00f3i Mendes", "3123601" }; + rows[1831] = new[] { "MG", "Engenheiro Caldas", "3123700" }; + rows[1832] = new[] { "MG", "Engenheiro Navarro", "3123809" }; + rows[1833] = new[] { "MG", "Entre Folhas", "3123858" }; + rows[1834] = new[] { "MG", "Entre Rios de Minas", "3123908" }; + rows[1835] = new[] { "MG", "Erv\u00e1lia", "3124005" }; + rows[1836] = new[] { "MG", "Esmeraldas", "3124104" }; + rows[1837] = new[] { "MG", "Espera Feliz", "3124203" }; + rows[1838] = new[] { "MG", "Espinosa", "3124302" }; + rows[1839] = new[] { "MG", "Esp\u00edrito Santo do Dourado", "3124401" }; + rows[1840] = new[] { "MG", "Estiva", "3124500" }; + rows[1841] = new[] { "MG", "Estrela Dalva", "3124609" }; + rows[1842] = new[] { "MG", "Estrela do Indai\u00e1", "3124708" }; + rows[1843] = new[] { "MG", "Estrela do Sul", "3124807" }; + rows[1844] = new[] { "MG", "Eugen\u00f3polis", "3124906" }; + rows[1845] = new[] { "MG", "Ewbank da C\u00e2mara", "3125002" }; + rows[1846] = new[] { "MG", "Extrema", "3125101" }; + rows[1847] = new[] { "MG", "Fama", "3125200" }; + rows[1848] = new[] { "MG", "Faria Lemos", "3125309" }; + rows[1849] = new[] { "MG", "Fel\u00edcio dos Santos", "3125408" }; + rows[1850] = new[] { "MG", "Felisburgo", "3125606" }; + rows[1851] = new[] { "MG", "Felixl\u00e2ndia", "3125705" }; + rows[1852] = new[] { "MG", "Fernandes Tourinho", "3125804" }; + rows[1853] = new[] { "MG", "Ferros", "3125903" }; + rows[1854] = new[] { "MG", "Fervedouro", "3125952" }; + rows[1855] = new[] { "MG", "Florestal", "3126000" }; + rows[1856] = new[] { "MG", "Formiga", "3126109" }; + rows[1857] = new[] { "MG", "Formoso", "3126208" }; + rows[1858] = new[] { "MG", "Fortaleza de Minas", "3126307" }; + rows[1859] = new[] { "MG", "Fortuna de Minas", "3126406" }; + rows[1860] = new[] { "MG", "Francisco Badar\u00f3", "3126505" }; + rows[1861] = new[] { "MG", "Francisco Dumont", "3126604" }; + rows[1862] = new[] { "MG", "Francisco S\u00e1", "3126703" }; + rows[1863] = new[] { "MG", "Francisc\u00f3polis", "3126752" }; + rows[1864] = new[] { "MG", "Frei Gaspar", "3126802" }; + rows[1865] = new[] { "MG", "Frei Inoc\u00eancio", "3126901" }; + rows[1866] = new[] { "MG", "Frei Lagonegro", "3126950" }; + rows[1867] = new[] { "MG", "Fronteira", "3127008" }; + rows[1868] = new[] { "MG", "Fronteira dos Vales", "3127057" }; + rows[1869] = new[] { "MG", "Fruta de Leite", "3127073" }; + rows[1870] = new[] { "MG", "Frutal", "3127107" }; + rows[1871] = new[] { "MG", "Funil\u00e2ndia", "3127206" }; + rows[1872] = new[] { "MG", "Galil\u00e9ia", "3127305" }; + rows[1873] = new[] { "MG", "Gameleiras", "3127339" }; + rows[1874] = new[] { "MG", "Glaucil\u00e2ndia", "3127354" }; + rows[1875] = new[] { "MG", "Goiabeira", "3127370" }; + rows[1876] = new[] { "MG", "Goian\u00e1", "3127388" }; + rows[1877] = new[] { "MG", "Gon\u00e7alves", "3127404" }; + rows[1878] = new[] { "MG", "Gonzaga", "3127503" }; + rows[1879] = new[] { "MG", "Gouveia", "3127602" }; + rows[1880] = new[] { "MG", "Governador Valadares", "3127701" }; + rows[1881] = new[] { "MG", "Gr\u00e3o Mogol", "3127800" }; + rows[1882] = new[] { "MG", "Grupiara", "3127909" }; + rows[1883] = new[] { "MG", "Guanh\u00e3es", "3128006" }; + rows[1884] = new[] { "MG", "Guap\u00e9", "3128105" }; + rows[1885] = new[] { "MG", "Guaraciaba", "3128204" }; + rows[1886] = new[] { "MG", "Guaraciama", "3128253" }; + rows[1887] = new[] { "MG", "Guaran\u00e9sia", "3128303" }; + rows[1888] = new[] { "MG", "Guarani", "3128402" }; + rows[1889] = new[] { "MG", "Guarar\u00e1", "3128501" }; + rows[1890] = new[] { "MG", "Guarda-Mor", "3128600" }; + rows[1891] = new[] { "MG", "Guaxup\u00e9", "3128709" }; + rows[1892] = new[] { "MG", "Guidoval", "3128808" }; + rows[1893] = new[] { "MG", "Guimar\u00e2nia", "3128907" }; + rows[1894] = new[] { "MG", "Guiricema", "3129004" }; + rows[1895] = new[] { "MG", "Gurinhat\u00e3", "3129103" }; + rows[1896] = new[] { "MG", "Heliodora", "3129202" }; + rows[1897] = new[] { "MG", "Iapu", "3129301" }; + rows[1898] = new[] { "MG", "Ibertioga", "3129400" }; + rows[1899] = new[] { "MG", "Ibi\u00e1", "3129509" }; + rows[1900] = new[] { "MG", "Ibia\u00ed", "3129608" }; + rows[1901] = new[] { "MG", "Ibiracatu", "3129657" }; + rows[1902] = new[] { "MG", "Ibiraci", "3129707" }; + rows[1903] = new[] { "MG", "Ibirit\u00e9", "3129806" }; + rows[1904] = new[] { "MG", "Ibiti\u00fara de Minas", "3129905" }; + rows[1905] = new[] { "MG", "Ibituruna", "3130002" }; + rows[1906] = new[] { "MG", "Icara\u00ed de Minas", "3130051" }; + rows[1907] = new[] { "MG", "Igarap\u00e9", "3130101" }; + rows[1908] = new[] { "MG", "Igaratinga", "3130200" }; + rows[1909] = new[] { "MG", "Iguatama", "3130309" }; + rows[1910] = new[] { "MG", "Ijaci", "3130408" }; + rows[1911] = new[] { "MG", "Ilic\u00ednea", "3130507" }; + rows[1912] = new[] { "MG", "Imb\u00e9 de Minas", "3130556" }; + rows[1913] = new[] { "MG", "Inconfidentes", "3130606" }; + rows[1914] = new[] { "MG", "Indaiabira", "3130655" }; + rows[1915] = new[] { "MG", "Indian\u00f3polis", "3130705" }; + rows[1916] = new[] { "MG", "Inga\u00ed", "3130804" }; + rows[1917] = new[] { "MG", "Inhapim", "3130903" }; + rows[1918] = new[] { "MG", "Inha\u00fama", "3131000" }; + rows[1919] = new[] { "MG", "Inimutaba", "3131109" }; + rows[1920] = new[] { "MG", "Ipaba", "3131158" }; + rows[1921] = new[] { "MG", "Ipanema", "3131208" }; + rows[1922] = new[] { "MG", "Ipatinga", "3131307" }; + rows[1923] = new[] { "MG", "Ipia\u00e7u", "3131406" }; + rows[1924] = new[] { "MG", "Ipui\u00fana", "3131505" }; + rows[1925] = new[] { "MG", "Ira\u00ed de Minas", "3131604" }; + rows[1926] = new[] { "MG", "Itabira", "3131703" }; + rows[1927] = new[] { "MG", "Itabirinha", "3131802" }; + rows[1928] = new[] { "MG", "Itabirito", "3131901" }; + rows[1929] = new[] { "MG", "Itacambira", "3132008" }; + rows[1930] = new[] { "MG", "Itacarambi", "3132107" }; + rows[1931] = new[] { "MG", "Itaguara", "3132206" }; + rows[1932] = new[] { "MG", "Itaip\u00e9", "3132305" }; + rows[1933] = new[] { "MG", "Itajub\u00e1", "3132404" }; + rows[1934] = new[] { "MG", "Itamarandiba", "3132503" }; + rows[1935] = new[] { "MG", "Itamarati de Minas", "3132602" }; + rows[1936] = new[] { "MG", "Itambacuri", "3132701" }; + rows[1937] = new[] { "MG", "Itamb\u00e9 do Mato Dentro", "3132800" }; + rows[1938] = new[] { "MG", "Itamogi", "3132909" }; + rows[1939] = new[] { "MG", "Itamonte", "3133006" }; + rows[1940] = new[] { "MG", "Itanhandu", "3133105" }; + rows[1941] = new[] { "MG", "Itanhomi", "3133204" }; + rows[1942] = new[] { "MG", "Itaobim", "3133303" }; + rows[1943] = new[] { "MG", "Itapagipe", "3133402" }; + rows[1944] = new[] { "MG", "Itapecerica", "3133501" }; + rows[1945] = new[] { "MG", "Itapeva", "3133600" }; + rows[1946] = new[] { "MG", "Itatiaiu\u00e7u", "3133709" }; + rows[1947] = new[] { "MG", "Ita\u00fa de Minas", "3133758" }; + rows[1948] = new[] { "MG", "Ita\u00fana", "3133808" }; + rows[1949] = new[] { "MG", "Itaverava", "3133907" }; + rows[1950] = new[] { "MG", "Itinga", "3134004" }; + rows[1951] = new[] { "MG", "Itueta", "3134103" }; + rows[1952] = new[] { "MG", "Ituiutaba", "3134202" }; + rows[1953] = new[] { "MG", "Itumirim", "3134301" }; + rows[1954] = new[] { "MG", "Iturama", "3134400" }; + rows[1955] = new[] { "MG", "Itutinga", "3134509" }; + rows[1956] = new[] { "MG", "Jaboticatubas", "3134608" }; + rows[1957] = new[] { "MG", "Jacinto", "3134707" }; + rows[1958] = new[] { "MG", "Jacu\u00ed", "3134806" }; + rows[1959] = new[] { "MG", "Jacutinga", "3134905" }; + rows[1960] = new[] { "MG", "Jaguara\u00e7u", "3135001" }; + rows[1961] = new[] { "MG", "Ja\u00edba", "3135050" }; + rows[1962] = new[] { "MG", "Jampruca", "3135076" }; + rows[1963] = new[] { "MG", "Jana\u00faba", "3135100" }; + rows[1964] = new[] { "MG", "Janu\u00e1ria", "3135209" }; + rows[1965] = new[] { "MG", "Japara\u00edba", "3135308" }; + rows[1966] = new[] { "MG", "Japonvar", "3135357" }; + rows[1967] = new[] { "MG", "Jeceaba", "3135407" }; + rows[1968] = new[] { "MG", "Jenipapo de Minas", "3135456" }; + rows[1969] = new[] { "MG", "Jequeri", "3135506" }; + rows[1970] = new[] { "MG", "Jequita\u00ed", "3135605" }; + rows[1971] = new[] { "MG", "Jequitib\u00e1", "3135704" }; + rows[1972] = new[] { "MG", "Jequitinhonha", "3135803" }; + rows[1973] = new[] { "MG", "Jesu\u00e2nia", "3135902" }; + rows[1974] = new[] { "MG", "Joa\u00edma", "3136009" }; + rows[1975] = new[] { "MG", "Joan\u00e9sia", "3136108" }; + rows[1976] = new[] { "MG", "Jo\u00e3o Monlevade", "3136207" }; + rows[1977] = new[] { "MG", "Jo\u00e3o Pinheiro", "3136306" }; + rows[1978] = new[] { "MG", "Joaquim Fel\u00edcio", "3136405" }; + rows[1979] = new[] { "MG", "Jord\u00e2nia", "3136504" }; + rows[1980] = new[] { "MG", "Jos\u00e9 Gon\u00e7alves de Minas", "3136520" }; + rows[1981] = new[] { "MG", "Jos\u00e9 Raydan", "3136553" }; + rows[1982] = new[] { "MG", "Josen\u00f3polis", "3136579" }; + rows[1983] = new[] { "MG", "Juatuba", "3136652" }; + rows[1984] = new[] { "MG", "Juiz de Fora", "3136702" }; + rows[1985] = new[] { "MG", "Juramento", "3136801" }; + rows[1986] = new[] { "MG", "Juruaia", "3136900" }; + rows[1987] = new[] { "MG", "Juven\u00edlia", "3136959" }; + rows[1988] = new[] { "MG", "Ladainha", "3137007" }; + rows[1989] = new[] { "MG", "Lagamar", "3137106" }; + rows[1990] = new[] { "MG", "Lagoa da Prata", "3137205" }; + rows[1991] = new[] { "MG", "Lagoa dos Patos", "3137304" }; + rows[1992] = new[] { "MG", "Lagoa Dourada", "3137403" }; + rows[1993] = new[] { "MG", "Lagoa Formosa", "3137502" }; + rows[1994] = new[] { "MG", "Lagoa Grande", "3137536" }; + rows[1995] = new[] { "MG", "Lagoa Santa", "3137601" }; + rows[1996] = new[] { "MG", "Lajinha", "3137700" }; + rows[1997] = new[] { "MG", "Lambari", "3137809" }; + rows[1998] = new[] { "MG", "Lamim", "3137908" }; + rows[1999] = new[] { "MG", "Laranjal", "3138005" }; + } + + private static void MunicipalitiesRows10(string[][] rows) + { + rows[2000] = new[] { "MG", "Lassance", "3138104" }; + rows[2001] = new[] { "MG", "Lavras", "3138203" }; + rows[2002] = new[] { "MG", "Leandro Ferreira", "3138302" }; + rows[2003] = new[] { "MG", "Leme do Prado", "3138351" }; + rows[2004] = new[] { "MG", "Leopoldina", "3138401" }; + rows[2005] = new[] { "MG", "Liberdade", "3138500" }; + rows[2006] = new[] { "MG", "Lima Duarte", "3138609" }; + rows[2007] = new[] { "MG", "Limeira do Oeste", "3138625" }; + rows[2008] = new[] { "MG", "Lontra", "3138658" }; + rows[2009] = new[] { "MG", "Luisburgo", "3138674" }; + rows[2010] = new[] { "MG", "Luisl\u00e2ndia", "3138682" }; + rows[2011] = new[] { "MG", "Lumin\u00e1rias", "3138708" }; + rows[2012] = new[] { "MG", "Luz", "3138807" }; + rows[2013] = new[] { "MG", "Machacalis", "3138906" }; + rows[2014] = new[] { "MG", "Machado", "3139003" }; + rows[2015] = new[] { "MG", "Madre de Deus de Minas", "3139102" }; + rows[2016] = new[] { "MG", "Malacacheta", "3139201" }; + rows[2017] = new[] { "MG", "Mamonas", "3139250" }; + rows[2018] = new[] { "MG", "Manga", "3139300" }; + rows[2019] = new[] { "MG", "Manhua\u00e7u", "3139409" }; + rows[2020] = new[] { "MG", "Manhumirim", "3139508" }; + rows[2021] = new[] { "MG", "Mantena", "3139607" }; + rows[2022] = new[] { "MG", "Mar de Espanha", "3139805" }; + rows[2023] = new[] { "MG", "Maravilhas", "3139706" }; + rows[2024] = new[] { "MG", "Maria da F\u00e9", "3139904" }; + rows[2025] = new[] { "MG", "Mariana", "3140001" }; + rows[2026] = new[] { "MG", "Marilac", "3140100" }; + rows[2027] = new[] { "MG", "M\u00e1rio Campos", "3140159" }; + rows[2028] = new[] { "MG", "Marip\u00e1 de Minas", "3140209" }; + rows[2029] = new[] { "MG", "Marli\u00e9ria", "3140308" }; + rows[2030] = new[] { "MG", "Marmel\u00f3polis", "3140407" }; + rows[2031] = new[] { "MG", "Martinho Campos", "3140506" }; + rows[2032] = new[] { "MG", "Martins Soares", "3140530" }; + rows[2033] = new[] { "MG", "Mata Verde", "3140555" }; + rows[2034] = new[] { "MG", "Materl\u00e2ndia", "3140605" }; + rows[2035] = new[] { "MG", "Mateus Leme", "3140704" }; + rows[2036] = new[] { "MG", "Mathias Lobato", "3171501" }; + rows[2037] = new[] { "MG", "Matias Barbosa", "3140803" }; + rows[2038] = new[] { "MG", "Matias Cardoso", "3140852" }; + rows[2039] = new[] { "MG", "Matip\u00f3", "3140902" }; + rows[2040] = new[] { "MG", "Mato Verde", "3141009" }; + rows[2041] = new[] { "MG", "Matozinhos", "3141108" }; + rows[2042] = new[] { "MG", "Matutina", "3141207" }; + rows[2043] = new[] { "MG", "Medeiros", "3141306" }; + rows[2044] = new[] { "MG", "Medina", "3141405" }; + rows[2045] = new[] { "MG", "Mendes Pimentel", "3141504" }; + rows[2046] = new[] { "MG", "Merc\u00eas", "3141603" }; + rows[2047] = new[] { "MG", "Mesquita", "3141702" }; + rows[2048] = new[] { "MG", "Minas Novas", "3141801" }; + rows[2049] = new[] { "MG", "Minduri", "3141900" }; + rows[2050] = new[] { "MG", "Mirabela", "3142007" }; + rows[2051] = new[] { "MG", "Miradouro", "3142106" }; + rows[2052] = new[] { "MG", "Mira\u00ed", "3142205" }; + rows[2053] = new[] { "MG", "Mirav\u00e2nia", "3142254" }; + rows[2054] = new[] { "MG", "Moeda", "3142304" }; + rows[2055] = new[] { "MG", "Moema", "3142403" }; + rows[2056] = new[] { "MG", "Monjolos", "3142502" }; + rows[2057] = new[] { "MG", "Monsenhor Paulo", "3142601" }; + rows[2058] = new[] { "MG", "Montalv\u00e2nia", "3142700" }; + rows[2059] = new[] { "MG", "Monte Alegre de Minas", "3142809" }; + rows[2060] = new[] { "MG", "Monte Azul", "3142908" }; + rows[2061] = new[] { "MG", "Monte Belo", "3143005" }; + rows[2062] = new[] { "MG", "Monte Carmelo", "3143104" }; + rows[2063] = new[] { "MG", "Monte Formoso", "3143153" }; + rows[2064] = new[] { "MG", "Monte Santo de Minas", "3143203" }; + rows[2065] = new[] { "MG", "Monte Si\u00e3o", "3143401" }; + rows[2066] = new[] { "MG", "Montes Claros", "3143302" }; + rows[2067] = new[] { "MG", "Montezuma", "3143450" }; + rows[2068] = new[] { "MG", "Morada Nova de Minas", "3143500" }; + rows[2069] = new[] { "MG", "Morro da Gar\u00e7a", "3143609" }; + rows[2070] = new[] { "MG", "Morro do Pilar", "3143708" }; + rows[2071] = new[] { "MG", "Munhoz", "3143807" }; + rows[2072] = new[] { "MG", "Muria\u00e9", "3143906" }; + rows[2073] = new[] { "MG", "Mutum", "3144003" }; + rows[2074] = new[] { "MG", "Muzambinho", "3144102" }; + rows[2075] = new[] { "MG", "Nacip Raydan", "3144201" }; + rows[2076] = new[] { "MG", "Nanuque", "3144300" }; + rows[2077] = new[] { "MG", "Naque", "3144359" }; + rows[2078] = new[] { "MG", "Natal\u00e2ndia", "3144375" }; + rows[2079] = new[] { "MG", "Nat\u00e9rcia", "3144409" }; + rows[2080] = new[] { "MG", "Nazareno", "3144508" }; + rows[2081] = new[] { "MG", "Nepomuceno", "3144607" }; + rows[2082] = new[] { "MG", "Ninheira", "3144656" }; + rows[2083] = new[] { "MG", "Nova Bel\u00e9m", "3144672" }; + rows[2084] = new[] { "MG", "Nova Era", "3144706" }; + rows[2085] = new[] { "MG", "Nova Lima", "3144805" }; + rows[2086] = new[] { "MG", "Nova M\u00f3dica", "3144904" }; + rows[2087] = new[] { "MG", "Nova Ponte", "3145000" }; + rows[2088] = new[] { "MG", "Nova Porteirinha", "3145059" }; + rows[2089] = new[] { "MG", "Nova Resende", "3145109" }; + rows[2090] = new[] { "MG", "Nova Serrana", "3145208" }; + rows[2091] = new[] { "MG", "Nova Uni\u00e3o", "3136603" }; + rows[2092] = new[] { "MG", "Novo Cruzeiro", "3145307" }; + rows[2093] = new[] { "MG", "Novo Oriente de Minas", "3145356" }; + rows[2094] = new[] { "MG", "Novorizonte", "3145372" }; + rows[2095] = new[] { "MG", "Olaria", "3145406" }; + rows[2096] = new[] { "MG", "Olhos-d'\u00c1gua", "3145455" }; + rows[2097] = new[] { "MG", "Ol\u00edmpio Noronha", "3145505" }; + rows[2098] = new[] { "MG", "Oliveira", "3145604" }; + rows[2099] = new[] { "MG", "Oliveira Fortes", "3145703" }; + rows[2100] = new[] { "MG", "On\u00e7a de Pitangui", "3145802" }; + rows[2101] = new[] { "MG", "Orat\u00f3rios", "3145851" }; + rows[2102] = new[] { "MG", "Oriz\u00e2nia", "3145877" }; + rows[2103] = new[] { "MG", "Ouro Branco", "3145901" }; + rows[2104] = new[] { "MG", "Ouro Fino", "3146008" }; + rows[2105] = new[] { "MG", "Ouro Preto", "3146107" }; + rows[2106] = new[] { "MG", "Ouro Verde de Minas", "3146206" }; + rows[2107] = new[] { "MG", "Padre Carvalho", "3146255" }; + rows[2108] = new[] { "MG", "Padre Para\u00edso", "3146305" }; + rows[2109] = new[] { "MG", "Pai Pedro", "3146552" }; + rows[2110] = new[] { "MG", "Paineiras", "3146404" }; + rows[2111] = new[] { "MG", "Pains", "3146503" }; + rows[2112] = new[] { "MG", "Paiva", "3146602" }; + rows[2113] = new[] { "MG", "Palma", "3146701" }; + rows[2114] = new[] { "MG", "Palm\u00f3polis", "3146750" }; + rows[2115] = new[] { "MG", "Papagaios", "3146909" }; + rows[2116] = new[] { "MG", "Par\u00e1 de Minas", "3147105" }; + rows[2117] = new[] { "MG", "Paracatu", "3147006" }; + rows[2118] = new[] { "MG", "Paragua\u00e7u", "3147204" }; + rows[2119] = new[] { "MG", "Parais\u00f3polis", "3147303" }; + rows[2120] = new[] { "MG", "Paraopeba", "3147402" }; + rows[2121] = new[] { "MG", "Passa Quatro", "3147600" }; + rows[2122] = new[] { "MG", "Passa Tempo", "3147709" }; + rows[2123] = new[] { "MG", "Passa Vinte", "3147808" }; + rows[2124] = new[] { "MG", "Passab\u00e9m", "3147501" }; + rows[2125] = new[] { "MG", "Passos", "3147907" }; + rows[2126] = new[] { "MG", "Patis", "3147956" }; + rows[2127] = new[] { "MG", "Patos de Minas", "3148004" }; + rows[2128] = new[] { "MG", "Patroc\u00ednio", "3148103" }; + rows[2129] = new[] { "MG", "Patroc\u00ednio do Muria\u00e9", "3148202" }; + rows[2130] = new[] { "MG", "Paula C\u00e2ndido", "3148301" }; + rows[2131] = new[] { "MG", "Paulistas", "3148400" }; + rows[2132] = new[] { "MG", "Pav\u00e3o", "3148509" }; + rows[2133] = new[] { "MG", "Pe\u00e7anha", "3148608" }; + rows[2134] = new[] { "MG", "Pedra Azul", "3148707" }; + rows[2135] = new[] { "MG", "Pedra Bonita", "3148756" }; + rows[2136] = new[] { "MG", "Pedra do Anta", "3148806" }; + rows[2137] = new[] { "MG", "Pedra do Indai\u00e1", "3148905" }; + rows[2138] = new[] { "MG", "Pedra Dourada", "3149002" }; + rows[2139] = new[] { "MG", "Pedralva", "3149101" }; + rows[2140] = new[] { "MG", "Pedras de Maria da Cruz", "3149150" }; + rows[2141] = new[] { "MG", "Pedrin\u00f3polis", "3149200" }; + rows[2142] = new[] { "MG", "Pedro Leopoldo", "3149309" }; + rows[2143] = new[] { "MG", "Pedro Teixeira", "3149408" }; + rows[2144] = new[] { "MG", "Pequeri", "3149507" }; + rows[2145] = new[] { "MG", "Pequi", "3149606" }; + rows[2146] = new[] { "MG", "Perdig\u00e3o", "3149705" }; + rows[2147] = new[] { "MG", "Perdizes", "3149804" }; + rows[2148] = new[] { "MG", "Perd\u00f5es", "3149903" }; + rows[2149] = new[] { "MG", "Periquito", "3149952" }; + rows[2150] = new[] { "MG", "Pescador", "3150000" }; + rows[2151] = new[] { "MG", "Piau", "3150109" }; + rows[2152] = new[] { "MG", "Piedade de Caratinga", "3150158" }; + rows[2153] = new[] { "MG", "Piedade de Ponte Nova", "3150208" }; + rows[2154] = new[] { "MG", "Piedade do Rio Grande", "3150307" }; + rows[2155] = new[] { "MG", "Piedade dos Gerais", "3150406" }; + rows[2156] = new[] { "MG", "Pimenta", "3150505" }; + rows[2157] = new[] { "MG", "Pingo-d'\u00c1gua", "3150539" }; + rows[2158] = new[] { "MG", "Pint\u00f3polis", "3150570" }; + rows[2159] = new[] { "MG", "Piracema", "3150604" }; + rows[2160] = new[] { "MG", "Pirajuba", "3150703" }; + rows[2161] = new[] { "MG", "Piranga", "3150802" }; + rows[2162] = new[] { "MG", "Pirangu\u00e7u", "3150901" }; + rows[2163] = new[] { "MG", "Piranguinho", "3151008" }; + rows[2164] = new[] { "MG", "Pirapetinga", "3151107" }; + rows[2165] = new[] { "MG", "Pirapora", "3151206" }; + rows[2166] = new[] { "MG", "Pira\u00faba", "3151305" }; + rows[2167] = new[] { "MG", "Pitangui", "3151404" }; + rows[2168] = new[] { "MG", "Piumhi", "3151503" }; + rows[2169] = new[] { "MG", "Planura", "3151602" }; + rows[2170] = new[] { "MG", "Po\u00e7o Fundo", "3151701" }; + rows[2171] = new[] { "MG", "Po\u00e7os de Caldas", "3151800" }; + rows[2172] = new[] { "MG", "Pocrane", "3151909" }; + rows[2173] = new[] { "MG", "Pomp\u00e9u", "3152006" }; + rows[2174] = new[] { "MG", "Ponte Nova", "3152105" }; + rows[2175] = new[] { "MG", "Ponto Chique", "3152131" }; + rows[2176] = new[] { "MG", "Ponto dos Volantes", "3152170" }; + rows[2177] = new[] { "MG", "Porteirinha", "3152204" }; + rows[2178] = new[] { "MG", "Porto Firme", "3152303" }; + rows[2179] = new[] { "MG", "Pot\u00e9", "3152402" }; + rows[2180] = new[] { "MG", "Pouso Alegre", "3152501" }; + rows[2181] = new[] { "MG", "Pouso Alto", "3152600" }; + rows[2182] = new[] { "MG", "Prados", "3152709" }; + rows[2183] = new[] { "MG", "Prata", "3152808" }; + rows[2184] = new[] { "MG", "Prat\u00e1polis", "3152907" }; + rows[2185] = new[] { "MG", "Pratinha", "3153004" }; + rows[2186] = new[] { "MG", "Presidente Bernardes", "3153103" }; + rows[2187] = new[] { "MG", "Presidente Juscelino", "3153202" }; + rows[2188] = new[] { "MG", "Presidente Kubitschek", "3153301" }; + rows[2189] = new[] { "MG", "Presidente Oleg\u00e1rio", "3153400" }; + rows[2190] = new[] { "MG", "Prudente de Morais", "3153608" }; + rows[2191] = new[] { "MG", "Quartel Geral", "3153707" }; + rows[2192] = new[] { "MG", "Queluzito", "3153806" }; + rows[2193] = new[] { "MG", "Raposos", "3153905" }; + rows[2194] = new[] { "MG", "Raul Soares", "3154002" }; + rows[2195] = new[] { "MG", "Recreio", "3154101" }; + rows[2196] = new[] { "MG", "Reduto", "3154150" }; + rows[2197] = new[] { "MG", "Resende Costa", "3154200" }; + rows[2198] = new[] { "MG", "Resplendor", "3154309" }; + rows[2199] = new[] { "MG", "Ressaquinha", "3154408" }; + } + + private static void MunicipalitiesRows11(string[][] rows) + { + rows[2200] = new[] { "MG", "Riachinho", "3154457" }; + rows[2201] = new[] { "MG", "Riacho dos Machados", "3154507" }; + rows[2202] = new[] { "MG", "Ribeir\u00e3o das Neves", "3154606" }; + rows[2203] = new[] { "MG", "Ribeir\u00e3o Vermelho", "3154705" }; + rows[2204] = new[] { "MG", "Rio Acima", "3154804" }; + rows[2205] = new[] { "MG", "Rio Casca", "3154903" }; + rows[2206] = new[] { "MG", "Rio do Prado", "3155108" }; + rows[2207] = new[] { "MG", "Rio Doce", "3155009" }; + rows[2208] = new[] { "MG", "Rio Espera", "3155207" }; + rows[2209] = new[] { "MG", "Rio Manso", "3155306" }; + rows[2210] = new[] { "MG", "Rio Novo", "3155405" }; + rows[2211] = new[] { "MG", "Rio Parana\u00edba", "3155504" }; + rows[2212] = new[] { "MG", "Rio Pardo de Minas", "3155603" }; + rows[2213] = new[] { "MG", "Rio Piracicaba", "3155702" }; + rows[2214] = new[] { "MG", "Rio Pomba", "3155801" }; + rows[2215] = new[] { "MG", "Rio Preto", "3155900" }; + rows[2216] = new[] { "MG", "Rio Vermelho", "3156007" }; + rows[2217] = new[] { "MG", "Rit\u00e1polis", "3156106" }; + rows[2218] = new[] { "MG", "Rochedo de Minas", "3156205" }; + rows[2219] = new[] { "MG", "Rodeiro", "3156304" }; + rows[2220] = new[] { "MG", "Romaria", "3156403" }; + rows[2221] = new[] { "MG", "Ros\u00e1rio da Limeira", "3156452" }; + rows[2222] = new[] { "MG", "Rubelita", "3156502" }; + rows[2223] = new[] { "MG", "Rubim", "3156601" }; + rows[2224] = new[] { "MG", "Sabar\u00e1", "3156700" }; + rows[2225] = new[] { "MG", "Sabin\u00f3polis", "3156809" }; + rows[2226] = new[] { "MG", "Sacramento", "3156908" }; + rows[2227] = new[] { "MG", "Salinas", "3157005" }; + rows[2228] = new[] { "MG", "Salto da Divisa", "3157104" }; + rows[2229] = new[] { "MG", "Santa B\u00e1rbara", "3157203" }; + rows[2230] = new[] { "MG", "Santa B\u00e1rbara do Leste", "3157252" }; + rows[2231] = new[] { "MG", "Santa B\u00e1rbara do Monte Verde", "3157278" }; + rows[2232] = new[] { "MG", "Santa B\u00e1rbara do Tug\u00fario", "3157302" }; + rows[2233] = new[] { "MG", "Santa Cruz de Minas", "3157336" }; + rows[2234] = new[] { "MG", "Santa Cruz de Salinas", "3157377" }; + rows[2235] = new[] { "MG", "Santa Cruz do Escalvado", "3157401" }; + rows[2236] = new[] { "MG", "Santa Efig\u00eania de Minas", "3157500" }; + rows[2237] = new[] { "MG", "Santa F\u00e9 de Minas", "3157609" }; + rows[2238] = new[] { "MG", "Santa Helena de Minas", "3157658" }; + rows[2239] = new[] { "MG", "Santa Juliana", "3157708" }; + rows[2240] = new[] { "MG", "Santa Luzia", "3157807" }; + rows[2241] = new[] { "MG", "Santa Margarida", "3157906" }; + rows[2242] = new[] { "MG", "Santa Maria de Itabira", "3158003" }; + rows[2243] = new[] { "MG", "Santa Maria do Salto", "3158102" }; + rows[2244] = new[] { "MG", "Santa Maria do Sua\u00e7u\u00ed", "3158201" }; + rows[2245] = new[] { "MG", "Santa Rita de Caldas", "3159209" }; + rows[2246] = new[] { "MG", "Santa Rita de Ibitipoca", "3159407" }; + rows[2247] = new[] { "MG", "Santa Rita de Jacutinga", "3159308" }; + rows[2248] = new[] { "MG", "Santa Rita de Minas", "3159357" }; + rows[2249] = new[] { "MG", "Santa Rita do Itueto", "3159506" }; + rows[2250] = new[] { "MG", "Santa Rita do Sapuca\u00ed", "3159605" }; + rows[2251] = new[] { "MG", "Santa Rosa da Serra", "3159704" }; + rows[2252] = new[] { "MG", "Santa Vit\u00f3ria", "3159803" }; + rows[2253] = new[] { "MG", "Santana da Vargem", "3158300" }; + rows[2254] = new[] { "MG", "Santana de Cataguases", "3158409" }; + rows[2255] = new[] { "MG", "Santana de Pirapama", "3158508" }; + rows[2256] = new[] { "MG", "Santana do Deserto", "3158607" }; + rows[2257] = new[] { "MG", "Santana do Garamb\u00e9u", "3158706" }; + rows[2258] = new[] { "MG", "Santana do Jacar\u00e9", "3158805" }; + rows[2259] = new[] { "MG", "Santana do Manhua\u00e7u", "3158904" }; + rows[2260] = new[] { "MG", "Santana do Para\u00edso", "3158953" }; + rows[2261] = new[] { "MG", "Santana do Riacho", "3159001" }; + rows[2262] = new[] { "MG", "Santana dos Montes", "3159100" }; + rows[2263] = new[] { "MG", "Santo Ant\u00f4nio do Amparo", "3159902" }; + rows[2264] = new[] { "MG", "Santo Ant\u00f4nio do Aventureiro", "3160009" }; + rows[2265] = new[] { "MG", "Santo Ant\u00f4nio do Grama", "3160108" }; + rows[2266] = new[] { "MG", "Santo Ant\u00f4nio do Itamb\u00e9", "3160207" }; + rows[2267] = new[] { "MG", "Santo Ant\u00f4nio do Jacinto", "3160306" }; + rows[2268] = new[] { "MG", "Santo Ant\u00f4nio do Monte", "3160405" }; + rows[2269] = new[] { "MG", "Santo Ant\u00f4nio do Retiro", "3160454" }; + rows[2270] = new[] { "MG", "Santo Ant\u00f4nio do Rio Abaixo", "3160504" }; + rows[2271] = new[] { "MG", "Santo Hip\u00f3lito", "3160603" }; + rows[2272] = new[] { "MG", "Santos Dumont", "3160702" }; + rows[2273] = new[] { "MG", "S\u00e3o Bento Abade", "3160801" }; + rows[2274] = new[] { "MG", "S\u00e3o Br\u00e1s do Sua\u00e7u\u00ed", "3160900" }; + rows[2275] = new[] { "MG", "S\u00e3o Domingos das Dores", "3160959" }; + rows[2276] = new[] { "MG", "S\u00e3o Domingos do Prata", "3161007" }; + rows[2277] = new[] { "MG", "S\u00e3o F\u00e9lix de Minas", "3161056" }; + rows[2278] = new[] { "MG", "S\u00e3o Francisco", "3161106" }; + rows[2279] = new[] { "MG", "S\u00e3o Francisco de Paula", "3161205" }; + rows[2280] = new[] { "MG", "S\u00e3o Francisco de Sales", "3161304" }; + rows[2281] = new[] { "MG", "S\u00e3o Francisco do Gl\u00f3ria", "3161403" }; + rows[2282] = new[] { "MG", "S\u00e3o Geraldo", "3161502" }; + rows[2283] = new[] { "MG", "S\u00e3o Geraldo da Piedade", "3161601" }; + rows[2284] = new[] { "MG", "S\u00e3o Geraldo do Baixio", "3161650" }; + rows[2285] = new[] { "MG", "S\u00e3o Gon\u00e7alo do Abaet\u00e9", "3161700" }; + rows[2286] = new[] { "MG", "S\u00e3o Gon\u00e7alo do Par\u00e1", "3161809" }; + rows[2287] = new[] { "MG", "S\u00e3o Gon\u00e7alo do Rio Abaixo", "3161908" }; + rows[2288] = new[] { "MG", "S\u00e3o Gon\u00e7alo do Rio Preto", "3125507" }; + rows[2289] = new[] { "MG", "S\u00e3o Gon\u00e7alo do Sapuca\u00ed", "3162005" }; + rows[2290] = new[] { "MG", "S\u00e3o Gotardo", "3162104" }; + rows[2291] = new[] { "MG", "S\u00e3o Jo\u00e3o Batista do Gl\u00f3ria", "3162203" }; + rows[2292] = new[] { "MG", "S\u00e3o Jo\u00e3o da Lagoa", "3162252" }; + rows[2293] = new[] { "MG", "S\u00e3o Jo\u00e3o da Mata", "3162302" }; + rows[2294] = new[] { "MG", "S\u00e3o Jo\u00e3o da Ponte", "3162401" }; + rows[2295] = new[] { "MG", "S\u00e3o Jo\u00e3o das Miss\u00f5es", "3162450" }; + rows[2296] = new[] { "MG", "S\u00e3o Jo\u00e3o del Rei", "3162500" }; + rows[2297] = new[] { "MG", "S\u00e3o Jo\u00e3o do Manhua\u00e7u", "3162559" }; + rows[2298] = new[] { "MG", "S\u00e3o Jo\u00e3o do Manteninha", "3162575" }; + rows[2299] = new[] { "MG", "S\u00e3o Jo\u00e3o do Oriente", "3162609" }; + rows[2300] = new[] { "MG", "S\u00e3o Jo\u00e3o do Pacu\u00ed", "3162658" }; + rows[2301] = new[] { "MG", "S\u00e3o Jo\u00e3o do Para\u00edso", "3162708" }; + rows[2302] = new[] { "MG", "S\u00e3o Jo\u00e3o Evangelista", "3162807" }; + rows[2303] = new[] { "MG", "S\u00e3o Jo\u00e3o Nepomuceno", "3162906" }; + rows[2304] = new[] { "MG", "S\u00e3o Joaquim de Bicas", "3162922" }; + rows[2305] = new[] { "MG", "S\u00e3o Jos\u00e9 da Barra", "3162948" }; + rows[2306] = new[] { "MG", "S\u00e3o Jos\u00e9 da Lapa", "3162955" }; + rows[2307] = new[] { "MG", "S\u00e3o Jos\u00e9 da Safira", "3163003" }; + rows[2308] = new[] { "MG", "S\u00e3o Jos\u00e9 da Varginha", "3163102" }; + rows[2309] = new[] { "MG", "S\u00e3o Jos\u00e9 do Alegre", "3163201" }; + rows[2310] = new[] { "MG", "S\u00e3o Jos\u00e9 do Divino", "3163300" }; + rows[2311] = new[] { "MG", "S\u00e3o Jos\u00e9 do Goiabal", "3163409" }; + rows[2312] = new[] { "MG", "S\u00e3o Jos\u00e9 do Jacuri", "3163508" }; + rows[2313] = new[] { "MG", "S\u00e3o Jos\u00e9 do Mantimento", "3163607" }; + rows[2314] = new[] { "MG", "S\u00e3o Louren\u00e7o", "3163706" }; + rows[2315] = new[] { "MG", "S\u00e3o Miguel do Anta", "3163805" }; + rows[2316] = new[] { "MG", "S\u00e3o Pedro da Uni\u00e3o", "3163904" }; + rows[2317] = new[] { "MG", "S\u00e3o Pedro do Sua\u00e7u\u00ed", "3164100" }; + rows[2318] = new[] { "MG", "S\u00e3o Pedro dos Ferros", "3164001" }; + rows[2319] = new[] { "MG", "S\u00e3o Rom\u00e3o", "3164209" }; + rows[2320] = new[] { "MG", "S\u00e3o Roque de Minas", "3164308" }; + rows[2321] = new[] { "MG", "S\u00e3o Sebasti\u00e3o da Bela Vista", "3164407" }; + rows[2322] = new[] { "MG", "S\u00e3o Sebasti\u00e3o da Vargem Alegre", "3164431" }; + rows[2323] = new[] { "MG", "S\u00e3o Sebasti\u00e3o do Anta", "3164472" }; + rows[2324] = new[] { "MG", "S\u00e3o Sebasti\u00e3o do Maranh\u00e3o", "3164506" }; + rows[2325] = new[] { "MG", "S\u00e3o Sebasti\u00e3o do Oeste", "3164605" }; + rows[2326] = new[] { "MG", "S\u00e3o Sebasti\u00e3o do Para\u00edso", "3164704" }; + rows[2327] = new[] { "MG", "S\u00e3o Sebasti\u00e3o do Rio Preto", "3164803" }; + rows[2328] = new[] { "MG", "S\u00e3o Sebasti\u00e3o do Rio Verde", "3164902" }; + rows[2329] = new[] { "MG", "S\u00e3o Tiago", "3165008" }; + rows[2330] = new[] { "MG", "S\u00e3o Tom\u00e1s de Aquino", "3165107" }; + rows[2331] = new[] { "MG", "S\u00e3o Tom\u00e9 das Letras", "3165206" }; + rows[2332] = new[] { "MG", "S\u00e3o Vicente de Minas", "3165305" }; + rows[2333] = new[] { "MG", "Sapuca\u00ed-Mirim", "3165404" }; + rows[2334] = new[] { "MG", "Sardo\u00e1", "3165503" }; + rows[2335] = new[] { "MG", "Sarzedo", "3165537" }; + rows[2336] = new[] { "MG", "Sem-Peixe", "3165560" }; + rows[2337] = new[] { "MG", "Senador Amaral", "3165578" }; + rows[2338] = new[] { "MG", "Senador Cortes", "3165602" }; + rows[2339] = new[] { "MG", "Senador Firmino", "3165701" }; + rows[2340] = new[] { "MG", "Senador Jos\u00e9 Bento", "3165800" }; + rows[2341] = new[] { "MG", "Senador Modestino Gon\u00e7alves", "3165909" }; + rows[2342] = new[] { "MG", "Senhora de Oliveira", "3166006" }; + rows[2343] = new[] { "MG", "Senhora do Porto", "3166105" }; + rows[2344] = new[] { "MG", "Senhora dos Rem\u00e9dios", "3166204" }; + rows[2345] = new[] { "MG", "Sericita", "3166303" }; + rows[2346] = new[] { "MG", "Seritinga", "3166402" }; + rows[2347] = new[] { "MG", "Serra Azul de Minas", "3166501" }; + rows[2348] = new[] { "MG", "Serra da Saudade", "3166600" }; + rows[2349] = new[] { "MG", "Serra do Salitre", "3166808" }; + rows[2350] = new[] { "MG", "Serra dos Aimor\u00e9s", "3166709" }; + rows[2351] = new[] { "MG", "Serrania", "3166907" }; + rows[2352] = new[] { "MG", "Serran\u00f3polis de Minas", "3166956" }; + rows[2353] = new[] { "MG", "Serranos", "3167004" }; + rows[2354] = new[] { "MG", "Serro", "3167103" }; + rows[2355] = new[] { "MG", "Sete Lagoas", "3167202" }; + rows[2356] = new[] { "MG", "Setubinha", "3165552" }; + rows[2357] = new[] { "MG", "Silveir\u00e2nia", "3167301" }; + rows[2358] = new[] { "MG", "Silvian\u00f3polis", "3167400" }; + rows[2359] = new[] { "MG", "Sim\u00e3o Pereira", "3167509" }; + rows[2360] = new[] { "MG", "Simon\u00e9sia", "3167608" }; + rows[2361] = new[] { "MG", "Sobr\u00e1lia", "3167707" }; + rows[2362] = new[] { "MG", "Soledade de Minas", "3167806" }; + rows[2363] = new[] { "MG", "Tabuleiro", "3167905" }; + rows[2364] = new[] { "MG", "Taiobeiras", "3168002" }; + rows[2365] = new[] { "MG", "Taparuba", "3168051" }; + rows[2366] = new[] { "MG", "Tapira", "3168101" }; + rows[2367] = new[] { "MG", "Tapira\u00ed", "3168200" }; + rows[2368] = new[] { "MG", "Taquara\u00e7u de Minas", "3168309" }; + rows[2369] = new[] { "MG", "Tarumirim", "3168408" }; + rows[2370] = new[] { "MG", "Teixeiras", "3168507" }; + rows[2371] = new[] { "MG", "Te\u00f3filo Otoni", "3168606" }; + rows[2372] = new[] { "MG", "Tim\u00f3teo", "3168705" }; + rows[2373] = new[] { "MG", "Tiradentes", "3168804" }; + rows[2374] = new[] { "MG", "Tiros", "3168903" }; + rows[2375] = new[] { "MG", "Tocantins", "3169000" }; + rows[2376] = new[] { "MG", "Tocos do Moji", "3169059" }; + rows[2377] = new[] { "MG", "Toledo", "3169109" }; + rows[2378] = new[] { "MG", "Tombos", "3169208" }; + rows[2379] = new[] { "MG", "Tr\u00eas Cora\u00e7\u00f5es", "3169307" }; + rows[2380] = new[] { "MG", "Tr\u00eas Marias", "3169356" }; + rows[2381] = new[] { "MG", "Tr\u00eas Pontas", "3169406" }; + rows[2382] = new[] { "MG", "Tumiritinga", "3169505" }; + rows[2383] = new[] { "MG", "Tupaciguara", "3169604" }; + rows[2384] = new[] { "MG", "Turmalina", "3169703" }; + rows[2385] = new[] { "MG", "Turvol\u00e2ndia", "3169802" }; + rows[2386] = new[] { "MG", "Ub\u00e1", "3169901" }; + rows[2387] = new[] { "MG", "Uba\u00ed", "3170008" }; + rows[2388] = new[] { "MG", "Ubaporanga", "3170057" }; + rows[2389] = new[] { "MG", "Uberaba", "3170107" }; + rows[2390] = new[] { "MG", "Uberl\u00e2ndia", "3170206" }; + rows[2391] = new[] { "MG", "Umburatiba", "3170305" }; + rows[2392] = new[] { "MG", "Una\u00ed", "3170404" }; + rows[2393] = new[] { "MG", "Uni\u00e3o de Minas", "3170438" }; + rows[2394] = new[] { "MG", "Uruana de Minas", "3170479" }; + rows[2395] = new[] { "MG", "Uruc\u00e2nia", "3170503" }; + rows[2396] = new[] { "MG", "Urucuia", "3170529" }; + rows[2397] = new[] { "MG", "Vargem Alegre", "3170578" }; + rows[2398] = new[] { "MG", "Vargem Bonita", "3170602" }; + rows[2399] = new[] { "MG", "Vargem Grande do Rio Pardo", "3170651" }; + } + + private static void MunicipalitiesRows12(string[][] rows) + { + rows[2400] = new[] { "MG", "Varginha", "3170701" }; + rows[2401] = new[] { "MG", "Varj\u00e3o de Minas", "3170750" }; + rows[2402] = new[] { "MG", "V\u00e1rzea da Palma", "3170800" }; + rows[2403] = new[] { "MG", "Varzel\u00e2ndia", "3170909" }; + rows[2404] = new[] { "MG", "Vazante", "3171006" }; + rows[2405] = new[] { "MG", "Verdel\u00e2ndia", "3171030" }; + rows[2406] = new[] { "MG", "Veredinha", "3171071" }; + rows[2407] = new[] { "MG", "Ver\u00edssimo", "3171105" }; + rows[2408] = new[] { "MG", "Vermelho Novo", "3171154" }; + rows[2409] = new[] { "MG", "Vespasiano", "3171204" }; + rows[2410] = new[] { "MG", "Vi\u00e7osa", "3171303" }; + rows[2411] = new[] { "MG", "Vieiras", "3171402" }; + rows[2412] = new[] { "MG", "Virgem da Lapa", "3171600" }; + rows[2413] = new[] { "MG", "Virg\u00ednia", "3171709" }; + rows[2414] = new[] { "MG", "Virgin\u00f3polis", "3171808" }; + rows[2415] = new[] { "MG", "Virgol\u00e2ndia", "3171907" }; + rows[2416] = new[] { "MG", "Visconde do Rio Branco", "3172004" }; + rows[2417] = new[] { "MG", "Volta Grande", "3172103" }; + rows[2418] = new[] { "MG", "Wenceslau Braz", "3172202" }; + rows[2419] = new[] { "PA", "Abaetetuba", "1500107" }; + rows[2420] = new[] { "PA", "Abel Figueiredo", "1500131" }; + rows[2421] = new[] { "PA", "Acar\u00e1", "1500206" }; + rows[2422] = new[] { "PA", "Afu\u00e1", "1500305" }; + rows[2423] = new[] { "PA", "\u00c1gua Azul do Norte", "1500347" }; + rows[2424] = new[] { "PA", "Alenquer", "1500404" }; + rows[2425] = new[] { "PA", "Almeirim", "1500503" }; + rows[2426] = new[] { "PA", "Altamira", "1500602" }; + rows[2427] = new[] { "PA", "Anaj\u00e1s", "1500701" }; + rows[2428] = new[] { "PA", "Ananindeua", "1500800" }; + rows[2429] = new[] { "PA", "Anapu", "1500859" }; + rows[2430] = new[] { "PA", "Augusto Corr\u00eaa", "1500909" }; + rows[2431] = new[] { "PA", "Aurora do Par\u00e1", "1500958" }; + rows[2432] = new[] { "PA", "Aveiro", "1501006" }; + rows[2433] = new[] { "PA", "Bagre", "1501105" }; + rows[2434] = new[] { "PA", "Bai\u00e3o", "1501204" }; + rows[2435] = new[] { "PA", "Bannach", "1501253" }; + rows[2436] = new[] { "PA", "Barcarena", "1501303" }; + rows[2437] = new[] { "PA", "Bel\u00e9m", "1501402" }; + rows[2438] = new[] { "PA", "Belterra", "1501451" }; + rows[2439] = new[] { "PA", "Benevides", "1501501" }; + rows[2440] = new[] { "PA", "Bom Jesus do Tocantins", "1501576" }; + rows[2441] = new[] { "PA", "Bonito", "1501600" }; + rows[2442] = new[] { "PA", "Bragan\u00e7a", "1501709" }; + rows[2443] = new[] { "PA", "Brasil Novo", "1501725" }; + rows[2444] = new[] { "PA", "Brejo Grande do Araguaia", "1501758" }; + rows[2445] = new[] { "PA", "Breu Branco", "1501782" }; + rows[2446] = new[] { "PA", "Breves", "1501808" }; + rows[2447] = new[] { "PA", "Bujaru", "1501907" }; + rows[2448] = new[] { "PA", "Cachoeira do Arari", "1502004" }; + rows[2449] = new[] { "PA", "Cachoeira do Piri\u00e1", "1501956" }; + rows[2450] = new[] { "PA", "Camet\u00e1", "1502103" }; + rows[2451] = new[] { "PA", "Cana\u00e3 dos Caraj\u00e1s", "1502152" }; + rows[2452] = new[] { "PA", "Capanema", "1502202" }; + rows[2453] = new[] { "PA", "Capit\u00e3o Po\u00e7o", "1502301" }; + rows[2454] = new[] { "PA", "Castanhal", "1502400" }; + rows[2455] = new[] { "PA", "Chaves", "1502509" }; + rows[2456] = new[] { "PA", "Colares", "1502608" }; + rows[2457] = new[] { "PA", "Concei\u00e7\u00e3o do Araguaia", "1502707" }; + rows[2458] = new[] { "PA", "Conc\u00f3rdia do Par\u00e1", "1502756" }; + rows[2459] = new[] { "PA", "Cumaru do Norte", "1502764" }; + rows[2460] = new[] { "PA", "Curion\u00f3polis", "1502772" }; + rows[2461] = new[] { "PA", "Curralinho", "1502806" }; + rows[2462] = new[] { "PA", "Curu\u00e1", "1502855" }; + rows[2463] = new[] { "PA", "Curu\u00e7\u00e1", "1502905" }; + rows[2464] = new[] { "PA", "Dom Eliseu", "1502939" }; + rows[2465] = new[] { "PA", "Eldorado do Caraj\u00e1s", "1502954" }; + rows[2466] = new[] { "PA", "Faro", "1503002" }; + rows[2467] = new[] { "PA", "Floresta do Araguaia", "1503044" }; + rows[2468] = new[] { "PA", "Garraf\u00e3o do Norte", "1503077" }; + rows[2469] = new[] { "PA", "Goian\u00e9sia do Par\u00e1", "1503093" }; + rows[2470] = new[] { "PA", "Gurup\u00e1", "1503101" }; + rows[2471] = new[] { "PA", "Igarap\u00e9-A\u00e7u", "1503200" }; + rows[2472] = new[] { "PA", "Igarap\u00e9-Miri", "1503309" }; + rows[2473] = new[] { "PA", "Inhangapi", "1503408" }; + rows[2474] = new[] { "PA", "Ipixuna do Par\u00e1", "1503457" }; + rows[2475] = new[] { "PA", "Irituia", "1503507" }; + rows[2476] = new[] { "PA", "Itaituba", "1503606" }; + rows[2477] = new[] { "PA", "Itupiranga", "1503705" }; + rows[2478] = new[] { "PA", "Jacareacanga", "1503754" }; + rows[2479] = new[] { "PA", "Jacund\u00e1", "1503804" }; + rows[2480] = new[] { "PA", "Juruti", "1503903" }; + rows[2481] = new[] { "PA", "Limoeiro do Ajuru", "1504000" }; + rows[2482] = new[] { "PA", "M\u00e3e do Rio", "1504059" }; + rows[2483] = new[] { "PA", "Magalh\u00e3es Barata", "1504109" }; + rows[2484] = new[] { "PA", "Marab\u00e1", "1504208" }; + rows[2485] = new[] { "PA", "Maracan\u00e3", "1504307" }; + rows[2486] = new[] { "PA", "Marapanim", "1504406" }; + rows[2487] = new[] { "PA", "Marituba", "1504422" }; + rows[2488] = new[] { "PA", "Medicil\u00e2ndia", "1504455" }; + rows[2489] = new[] { "PA", "Melga\u00e7o", "1504505" }; + rows[2490] = new[] { "PA", "Mocajuba", "1504604" }; + rows[2491] = new[] { "PA", "Moju", "1504703" }; + rows[2492] = new[] { "PA", "Moju\u00ed dos Campos", "1504752" }; + rows[2493] = new[] { "PA", "Monte Alegre", "1504802" }; + rows[2494] = new[] { "PA", "Muan\u00e1", "1504901" }; + rows[2495] = new[] { "PA", "Nova Esperan\u00e7a do Piri\u00e1", "1504950" }; + rows[2496] = new[] { "PA", "Nova Ipixuna", "1504976" }; + rows[2497] = new[] { "PA", "Nova Timboteua", "1505007" }; + rows[2498] = new[] { "PA", "Novo Progresso", "1505031" }; + rows[2499] = new[] { "PA", "Novo Repartimento", "1505064" }; + rows[2500] = new[] { "PA", "\u00d3bidos", "1505106" }; + rows[2501] = new[] { "PA", "Oeiras do Par\u00e1", "1505205" }; + rows[2502] = new[] { "PA", "Oriximin\u00e1", "1505304" }; + rows[2503] = new[] { "PA", "Our\u00e9m", "1505403" }; + rows[2504] = new[] { "PA", "Ouril\u00e2ndia do Norte", "1505437" }; + rows[2505] = new[] { "PA", "Pacaj\u00e1", "1505486" }; + rows[2506] = new[] { "PA", "Palestina do Par\u00e1", "1505494" }; + rows[2507] = new[] { "PA", "Paragominas", "1505502" }; + rows[2508] = new[] { "PA", "Parauapebas", "1505536" }; + rows[2509] = new[] { "PA", "Pau D'Arco", "1505551" }; + rows[2510] = new[] { "PA", "Peixe-Boi", "1505601" }; + rows[2511] = new[] { "PA", "Pi\u00e7arra", "1505635" }; + rows[2512] = new[] { "PA", "Placas", "1505650" }; + rows[2513] = new[] { "PA", "Ponta de Pedras", "1505700" }; + rows[2514] = new[] { "PA", "Portel", "1505809" }; + rows[2515] = new[] { "PA", "Porto de Moz", "1505908" }; + rows[2516] = new[] { "PA", "Prainha", "1506005" }; + rows[2517] = new[] { "PA", "Primavera", "1506104" }; + rows[2518] = new[] { "PA", "Quatipuru", "1506112" }; + rows[2519] = new[] { "PA", "Reden\u00e7\u00e3o", "1506138" }; + rows[2520] = new[] { "PA", "Rio Maria", "1506161" }; + rows[2521] = new[] { "PA", "Rondon do Par\u00e1", "1506187" }; + rows[2522] = new[] { "PA", "Rur\u00f3polis", "1506195" }; + rows[2523] = new[] { "PA", "Salin\u00f3polis", "1506203" }; + rows[2524] = new[] { "PA", "Salvaterra", "1506302" }; + rows[2525] = new[] { "PA", "Santa B\u00e1rbara do Par\u00e1", "1506351" }; + rows[2526] = new[] { "PA", "Santa Cruz do Arari", "1506401" }; + rows[2527] = new[] { "PA", "Santa Izabel do Par\u00e1", "1506500" }; + rows[2528] = new[] { "PA", "Santa Luzia do Par\u00e1", "1506559" }; + rows[2529] = new[] { "PA", "Santa Maria das Barreiras", "1506583" }; + rows[2530] = new[] { "PA", "Santa Maria do Par\u00e1", "1506609" }; + rows[2531] = new[] { "PA", "Santana do Araguaia", "1506708" }; + rows[2532] = new[] { "PA", "Santar\u00e9m", "1506807" }; + rows[2533] = new[] { "PA", "Santar\u00e9m Novo", "1506906" }; + rows[2534] = new[] { "PA", "Santo Ant\u00f4nio do Tau\u00e1", "1507003" }; + rows[2535] = new[] { "PA", "S\u00e3o Caetano de Odivelas", "1507102" }; + rows[2536] = new[] { "PA", "S\u00e3o Domingos do Araguaia", "1507151" }; + rows[2537] = new[] { "PA", "S\u00e3o Domingos do Capim", "1507201" }; + rows[2538] = new[] { "PA", "S\u00e3o F\u00e9lix do Xingu", "1507300" }; + rows[2539] = new[] { "PA", "S\u00e3o Francisco do Par\u00e1", "1507409" }; + rows[2540] = new[] { "PA", "S\u00e3o Geraldo do Araguaia", "1507458" }; + rows[2541] = new[] { "PA", "S\u00e3o Jo\u00e3o da Ponta", "1507466" }; + rows[2542] = new[] { "PA", "S\u00e3o Jo\u00e3o de Pirabas", "1507474" }; + rows[2543] = new[] { "PA", "S\u00e3o Jo\u00e3o do Araguaia", "1507508" }; + rows[2544] = new[] { "PA", "S\u00e3o Miguel do Guam\u00e1", "1507607" }; + rows[2545] = new[] { "PA", "S\u00e3o Sebasti\u00e3o da Boa Vista", "1507706" }; + rows[2546] = new[] { "PA", "Sapucaia", "1507755" }; + rows[2547] = new[] { "PA", "Senador Jos\u00e9 Porf\u00edrio", "1507805" }; + rows[2548] = new[] { "PA", "Soure", "1507904" }; + rows[2549] = new[] { "PA", "Tail\u00e2ndia", "1507953" }; + rows[2550] = new[] { "PA", "Terra Alta", "1507961" }; + rows[2551] = new[] { "PA", "Terra Santa", "1507979" }; + rows[2552] = new[] { "PA", "Tom\u00e9-A\u00e7u", "1508001" }; + rows[2553] = new[] { "PA", "Tracuateua", "1508035" }; + rows[2554] = new[] { "PA", "Trair\u00e3o", "1508050" }; + rows[2555] = new[] { "PA", "Tucum\u00e3", "1508084" }; + rows[2556] = new[] { "PA", "Tucuru\u00ed", "1508100" }; + rows[2557] = new[] { "PA", "Ulian\u00f3polis", "1508126" }; + rows[2558] = new[] { "PA", "Uruar\u00e1", "1508159" }; + rows[2559] = new[] { "PA", "Vigia", "1508209" }; + rows[2560] = new[] { "PA", "Viseu", "1508308" }; + rows[2561] = new[] { "PA", "Vit\u00f3ria do Xingu", "1508357" }; + rows[2562] = new[] { "PA", "Xinguara", "1508407" }; + rows[2563] = new[] { "PB", "\u00c1gua Branca", "2500106" }; + rows[2564] = new[] { "PB", "Aguiar", "2500205" }; + rows[2565] = new[] { "PB", "Alagoa Grande", "2500304" }; + rows[2566] = new[] { "PB", "Alagoa Nova", "2500403" }; + rows[2567] = new[] { "PB", "Alagoinha", "2500502" }; + rows[2568] = new[] { "PB", "Alcantil", "2500536" }; + rows[2569] = new[] { "PB", "Algod\u00e3o de Janda\u00edra", "2500577" }; + rows[2570] = new[] { "PB", "Alhandra", "2500601" }; + rows[2571] = new[] { "PB", "Amparo", "2500734" }; + rows[2572] = new[] { "PB", "Aparecida", "2500775" }; + rows[2573] = new[] { "PB", "Ara\u00e7agi", "2500809" }; + rows[2574] = new[] { "PB", "Arara", "2500908" }; + rows[2575] = new[] { "PB", "Araruna", "2501005" }; + rows[2576] = new[] { "PB", "Areia", "2501104" }; + rows[2577] = new[] { "PB", "Areia de Bara\u00fanas", "2501153" }; + rows[2578] = new[] { "PB", "Areial", "2501203" }; + rows[2579] = new[] { "PB", "Aroeiras", "2501302" }; + rows[2580] = new[] { "PB", "Assun\u00e7\u00e3o", "2501351" }; + rows[2581] = new[] { "PB", "Ba\u00eda da Trai\u00e7\u00e3o", "2501401" }; + rows[2582] = new[] { "PB", "Bananeiras", "2501500" }; + rows[2583] = new[] { "PB", "Bara\u00fana", "2501534" }; + rows[2584] = new[] { "PB", "Barra de Santa Rosa", "2501609" }; + rows[2585] = new[] { "PB", "Barra de Santana", "2501575" }; + rows[2586] = new[] { "PB", "Barra de S\u00e3o Miguel", "2501708" }; + rows[2587] = new[] { "PB", "Bayeux", "2501807" }; + rows[2588] = new[] { "PB", "Bel\u00e9m", "2501906" }; + rows[2589] = new[] { "PB", "Bel\u00e9m do Brejo do Cruz", "2502003" }; + rows[2590] = new[] { "PB", "Bernardino Batista", "2502052" }; + rows[2591] = new[] { "PB", "Boa Ventura", "2502102" }; + rows[2592] = new[] { "PB", "Boa Vista", "2502151" }; + rows[2593] = new[] { "PB", "Bom Jesus", "2502201" }; + rows[2594] = new[] { "PB", "Bom Sucesso", "2502300" }; + rows[2595] = new[] { "PB", "Bonito de Santa F\u00e9", "2502409" }; + rows[2596] = new[] { "PB", "Boqueir\u00e3o", "2502508" }; + rows[2597] = new[] { "PB", "Borborema", "2502706" }; + rows[2598] = new[] { "PB", "Brejo do Cruz", "2502805" }; + rows[2599] = new[] { "PB", "Brejo dos Santos", "2502904" }; + } + + private static void MunicipalitiesRows13(string[][] rows) + { + rows[2600] = new[] { "PB", "Caapor\u00e3", "2503001" }; + rows[2601] = new[] { "PB", "Cabaceiras", "2503100" }; + rows[2602] = new[] { "PB", "Cabedelo", "2503209" }; + rows[2603] = new[] { "PB", "Cachoeira dos \u00cdndios", "2503308" }; + rows[2604] = new[] { "PB", "Cacimba de Areia", "2503407" }; + rows[2605] = new[] { "PB", "Cacimba de Dentro", "2503506" }; + rows[2606] = new[] { "PB", "Cacimbas", "2503555" }; + rows[2607] = new[] { "PB", "Cai\u00e7ara", "2503605" }; + rows[2608] = new[] { "PB", "Cajazeiras", "2503704" }; + rows[2609] = new[] { "PB", "Cajazeirinhas", "2503753" }; + rows[2610] = new[] { "PB", "Caldas Brand\u00e3o", "2503803" }; + rows[2611] = new[] { "PB", "Camala\u00fa", "2503902" }; + rows[2612] = new[] { "PB", "Campina Grande", "2504009" }; + rows[2613] = new[] { "PB", "Capim", "2504033" }; + rows[2614] = new[] { "PB", "Cara\u00fabas", "2504074" }; + rows[2615] = new[] { "PB", "Carrapateira", "2504108" }; + rows[2616] = new[] { "PB", "Casserengue", "2504157" }; + rows[2617] = new[] { "PB", "Catingueira", "2504207" }; + rows[2618] = new[] { "PB", "Catol\u00e9 do Rocha", "2504306" }; + rows[2619] = new[] { "PB", "Caturit\u00e9", "2504355" }; + rows[2620] = new[] { "PB", "Concei\u00e7\u00e3o", "2504405" }; + rows[2621] = new[] { "PB", "Condado", "2504504" }; + rows[2622] = new[] { "PB", "Conde", "2504603" }; + rows[2623] = new[] { "PB", "Congo", "2504702" }; + rows[2624] = new[] { "PB", "Coremas", "2504801" }; + rows[2625] = new[] { "PB", "Coxixola", "2504850" }; + rows[2626] = new[] { "PB", "Cruz do Esp\u00edrito Santo", "2504900" }; + rows[2627] = new[] { "PB", "Cubati", "2505006" }; + rows[2628] = new[] { "PB", "Cuit\u00e9", "2505105" }; + rows[2629] = new[] { "PB", "Cuit\u00e9 de Mamanguape", "2505238" }; + rows[2630] = new[] { "PB", "Cuitegi", "2505204" }; + rows[2631] = new[] { "PB", "Curral de Cima", "2505279" }; + rows[2632] = new[] { "PB", "Curral Velho", "2505303" }; + rows[2633] = new[] { "PB", "Dami\u00e3o", "2505352" }; + rows[2634] = new[] { "PB", "Desterro", "2505402" }; + rows[2635] = new[] { "PB", "Diamante", "2505600" }; + rows[2636] = new[] { "PB", "Dona In\u00eas", "2505709" }; + rows[2637] = new[] { "PB", "Duas Estradas", "2505808" }; + rows[2638] = new[] { "PB", "Emas", "2505907" }; + rows[2639] = new[] { "PB", "Esperan\u00e7a", "2506004" }; + rows[2640] = new[] { "PB", "Fagundes", "2506103" }; + rows[2641] = new[] { "PB", "Frei Martinho", "2506202" }; + rows[2642] = new[] { "PB", "Gado Bravo", "2506251" }; + rows[2643] = new[] { "PB", "Guarabira", "2506301" }; + rows[2644] = new[] { "PB", "Gurinh\u00e9m", "2506400" }; + rows[2645] = new[] { "PB", "Gurj\u00e3o", "2506509" }; + rows[2646] = new[] { "PB", "Ibiara", "2506608" }; + rows[2647] = new[] { "PB", "Igaracy", "2502607" }; + rows[2648] = new[] { "PB", "Imaculada", "2506707" }; + rows[2649] = new[] { "PB", "Ing\u00e1", "2506806" }; + rows[2650] = new[] { "PB", "Itabaiana", "2506905" }; + rows[2651] = new[] { "PB", "Itaporanga", "2507002" }; + rows[2652] = new[] { "PB", "Itapororoca", "2507101" }; + rows[2653] = new[] { "PB", "Itatuba", "2507200" }; + rows[2654] = new[] { "PB", "Jacara\u00fa", "2507309" }; + rows[2655] = new[] { "PB", "Jeric\u00f3", "2507408" }; + rows[2656] = new[] { "PB", "Jo\u00e3o Pessoa", "2507507" }; + rows[2657] = new[] { "PB", "Joca Claudino", "2513653" }; + rows[2658] = new[] { "PB", "Juarez T\u00e1vora", "2507606" }; + rows[2659] = new[] { "PB", "Juazeirinho", "2507705" }; + rows[2660] = new[] { "PB", "Junco do Serid\u00f3", "2507804" }; + rows[2661] = new[] { "PB", "Juripiranga", "2507903" }; + rows[2662] = new[] { "PB", "Juru", "2508000" }; + rows[2663] = new[] { "PB", "Lagoa", "2508109" }; + rows[2664] = new[] { "PB", "Lagoa de Dentro", "2508208" }; + rows[2665] = new[] { "PB", "Lagoa Seca", "2508307" }; + rows[2666] = new[] { "PB", "Lastro", "2508406" }; + rows[2667] = new[] { "PB", "Livramento", "2508505" }; + rows[2668] = new[] { "PB", "Logradouro", "2508554" }; + rows[2669] = new[] { "PB", "Lucena", "2508604" }; + rows[2670] = new[] { "PB", "M\u00e3e d'\u00c1gua", "2508703" }; + rows[2671] = new[] { "PB", "Malta", "2508802" }; + rows[2672] = new[] { "PB", "Mamanguape", "2508901" }; + rows[2673] = new[] { "PB", "Mana\u00edra", "2509008" }; + rows[2674] = new[] { "PB", "Marca\u00e7\u00e3o", "2509057" }; + rows[2675] = new[] { "PB", "Mari", "2509107" }; + rows[2676] = new[] { "PB", "Mariz\u00f3polis", "2509156" }; + rows[2677] = new[] { "PB", "Massaranduba", "2509206" }; + rows[2678] = new[] { "PB", "Mataraca", "2509305" }; + rows[2679] = new[] { "PB", "Matinhas", "2509339" }; + rows[2680] = new[] { "PB", "Mato Grosso", "2509370" }; + rows[2681] = new[] { "PB", "Matur\u00e9ia", "2509396" }; + rows[2682] = new[] { "PB", "Mogeiro", "2509404" }; + rows[2683] = new[] { "PB", "Montadas", "2509503" }; + rows[2684] = new[] { "PB", "Monte Horebe", "2509602" }; + rows[2685] = new[] { "PB", "Monteiro", "2509701" }; + rows[2686] = new[] { "PB", "Mulungu", "2509800" }; + rows[2687] = new[] { "PB", "Natuba", "2509909" }; + rows[2688] = new[] { "PB", "Nazarezinho", "2510006" }; + rows[2689] = new[] { "PB", "Nova Floresta", "2510105" }; + rows[2690] = new[] { "PB", "Nova Olinda", "2510204" }; + rows[2691] = new[] { "PB", "Nova Palmeira", "2510303" }; + rows[2692] = new[] { "PB", "Olho d'\u00c1gua", "2510402" }; + rows[2693] = new[] { "PB", "Olivedos", "2510501" }; + rows[2694] = new[] { "PB", "Ouro Velho", "2510600" }; + rows[2695] = new[] { "PB", "Parari", "2510659" }; + rows[2696] = new[] { "PB", "Passagem", "2510709" }; + rows[2697] = new[] { "PB", "Patos", "2510808" }; + rows[2698] = new[] { "PB", "Paulista", "2510907" }; + rows[2699] = new[] { "PB", "Pedra Branca", "2511004" }; + rows[2700] = new[] { "PB", "Pedra Lavrada", "2511103" }; + rows[2701] = new[] { "PB", "Pedras de Fogo", "2511202" }; + rows[2702] = new[] { "PB", "Pedro R\u00e9gis", "2512721" }; + rows[2703] = new[] { "PB", "Pianc\u00f3", "2511301" }; + rows[2704] = new[] { "PB", "Picu\u00ed", "2511400" }; + rows[2705] = new[] { "PB", "Pilar", "2511509" }; + rows[2706] = new[] { "PB", "Pil\u00f5es", "2511608" }; + rows[2707] = new[] { "PB", "Pil\u00f5ezinhos", "2511707" }; + rows[2708] = new[] { "PB", "Pirpirituba", "2511806" }; + rows[2709] = new[] { "PB", "Pitimbu", "2511905" }; + rows[2710] = new[] { "PB", "Pocinhos", "2512002" }; + rows[2711] = new[] { "PB", "Po\u00e7o Dantas", "2512036" }; + rows[2712] = new[] { "PB", "Po\u00e7o de Jos\u00e9 de Moura", "2512077" }; + rows[2713] = new[] { "PB", "Pombal", "2512101" }; + rows[2714] = new[] { "PB", "Prata", "2512200" }; + rows[2715] = new[] { "PB", "Princesa Isabel", "2512309" }; + rows[2716] = new[] { "PB", "Puxinan\u00e3", "2512408" }; + rows[2717] = new[] { "PB", "Queimadas", "2512507" }; + rows[2718] = new[] { "PB", "Quixaba", "2512606" }; + rows[2719] = new[] { "PB", "Rem\u00edgio", "2512705" }; + rows[2720] = new[] { "PB", "Riach\u00e3o", "2512747" }; + rows[2721] = new[] { "PB", "Riach\u00e3o do Bacamarte", "2512754" }; + rows[2722] = new[] { "PB", "Riach\u00e3o do Po\u00e7o", "2512762" }; + rows[2723] = new[] { "PB", "Riacho de Santo Ant\u00f4nio", "2512788" }; + rows[2724] = new[] { "PB", "Riacho dos Cavalos", "2512804" }; + rows[2725] = new[] { "PB", "Rio Tinto", "2512903" }; + rows[2726] = new[] { "PB", "Salgadinho", "2513000" }; + rows[2727] = new[] { "PB", "Salgado de S\u00e3o F\u00e9lix", "2513109" }; + rows[2728] = new[] { "PB", "Santa Cec\u00edlia", "2513158" }; + rows[2729] = new[] { "PB", "Santa Cruz", "2513208" }; + rows[2730] = new[] { "PB", "Santa Helena", "2513307" }; + rows[2731] = new[] { "PB", "Santa In\u00eas", "2513356" }; + rows[2732] = new[] { "PB", "Santa Luzia", "2513406" }; + rows[2733] = new[] { "PB", "Santa Rita", "2513703" }; + rows[2734] = new[] { "PB", "Santa Teresinha", "2513802" }; + rows[2735] = new[] { "PB", "Santana de Mangueira", "2513505" }; + rows[2736] = new[] { "PB", "Santana dos Garrotes", "2513604" }; + rows[2737] = new[] { "PB", "Santo Andr\u00e9", "2513851" }; + rows[2738] = new[] { "PB", "S\u00e3o Bentinho", "2513927" }; + rows[2739] = new[] { "PB", "S\u00e3o Bento", "2513901" }; + rows[2740] = new[] { "PB", "S\u00e3o Domingos", "2513968" }; + rows[2741] = new[] { "PB", "S\u00e3o Domingos do Cariri", "2513943" }; + rows[2742] = new[] { "PB", "S\u00e3o Francisco", "2513984" }; + rows[2743] = new[] { "PB", "S\u00e3o Jo\u00e3o do Cariri", "2514008" }; + rows[2744] = new[] { "PB", "S\u00e3o Jo\u00e3o do Rio do Peixe", "2500700" }; + rows[2745] = new[] { "PB", "S\u00e3o Jo\u00e3o do Tigre", "2514107" }; + rows[2746] = new[] { "PB", "S\u00e3o Jos\u00e9 da Lagoa Tapada", "2514206" }; + rows[2747] = new[] { "PB", "S\u00e3o Jos\u00e9 de Caiana", "2514305" }; + rows[2748] = new[] { "PB", "S\u00e3o Jos\u00e9 de Espinharas", "2514404" }; + rows[2749] = new[] { "PB", "S\u00e3o Jos\u00e9 de Piranhas", "2514503" }; + rows[2750] = new[] { "PB", "S\u00e3o Jos\u00e9 de Princesa", "2514552" }; + rows[2751] = new[] { "PB", "S\u00e3o Jos\u00e9 do Bonfim", "2514602" }; + rows[2752] = new[] { "PB", "S\u00e3o Jos\u00e9 do Brejo do Cruz", "2514651" }; + rows[2753] = new[] { "PB", "S\u00e3o Jos\u00e9 do Sabugi", "2514701" }; + rows[2754] = new[] { "PB", "S\u00e3o Jos\u00e9 dos Cordeiros", "2514800" }; + rows[2755] = new[] { "PB", "S\u00e3o Jos\u00e9 dos Ramos", "2514453" }; + rows[2756] = new[] { "PB", "S\u00e3o Mamede", "2514909" }; + rows[2757] = new[] { "PB", "S\u00e3o Miguel de Taipu", "2515005" }; + rows[2758] = new[] { "PB", "S\u00e3o Sebasti\u00e3o de Lagoa de Ro\u00e7a", "2515104" }; + rows[2759] = new[] { "PB", "S\u00e3o Sebasti\u00e3o do Umbuzeiro", "2515203" }; + rows[2760] = new[] { "PB", "S\u00e3o Vicente do Serid\u00f3", "2515401" }; + rows[2761] = new[] { "PB", "Sap\u00e9", "2515302" }; + rows[2762] = new[] { "PB", "Serra Branca", "2515500" }; + rows[2763] = new[] { "PB", "Serra da Raiz", "2515609" }; + rows[2764] = new[] { "PB", "Serra Grande", "2515708" }; + rows[2765] = new[] { "PB", "Serra Redonda", "2515807" }; + rows[2766] = new[] { "PB", "Serraria", "2515906" }; + rows[2767] = new[] { "PB", "Sert\u00e3ozinho", "2515930" }; + rows[2768] = new[] { "PB", "Sobrado", "2515971" }; + rows[2769] = new[] { "PB", "Sol\u00e2nea", "2516003" }; + rows[2770] = new[] { "PB", "Soledade", "2516102" }; + rows[2771] = new[] { "PB", "Soss\u00eago", "2516151" }; + rows[2772] = new[] { "PB", "Sousa", "2516201" }; + rows[2773] = new[] { "PB", "Sum\u00e9", "2516300" }; + rows[2774] = new[] { "PB", "Tacima", "2516409" }; + rows[2775] = new[] { "PB", "Tapero\u00e1", "2516508" }; + rows[2776] = new[] { "PB", "Tavares", "2516607" }; + rows[2777] = new[] { "PB", "Teixeira", "2516706" }; + rows[2778] = new[] { "PB", "Ten\u00f3rio", "2516755" }; + rows[2779] = new[] { "PB", "Triunfo", "2516805" }; + rows[2780] = new[] { "PB", "Uira\u00fana", "2516904" }; + rows[2781] = new[] { "PB", "Umbuzeiro", "2517001" }; + rows[2782] = new[] { "PB", "V\u00e1rzea", "2517100" }; + rows[2783] = new[] { "PB", "Vieir\u00f3polis", "2517209" }; + rows[2784] = new[] { "PB", "Vista Serrana", "2505501" }; + rows[2785] = new[] { "PB", "Zabel\u00ea", "2517407" }; + rows[2786] = new[] { "PR", "Abati\u00e1", "4100103" }; + rows[2787] = new[] { "PR", "Adrian\u00f3polis", "4100202" }; + rows[2788] = new[] { "PR", "Agudos do Sul", "4100301" }; + rows[2789] = new[] { "PR", "Almirante Tamandar\u00e9", "4100400" }; + rows[2790] = new[] { "PR", "Altamira do Paran\u00e1", "4100459" }; + rows[2791] = new[] { "PR", "Alto Para\u00edso", "4128625" }; + rows[2792] = new[] { "PR", "Alto Paran\u00e1", "4100608" }; + rows[2793] = new[] { "PR", "Alto Piquiri", "4100707" }; + rows[2794] = new[] { "PR", "Alt\u00f4nia", "4100509" }; + rows[2795] = new[] { "PR", "Alvorada do Sul", "4100806" }; + rows[2796] = new[] { "PR", "Amapor\u00e3", "4100905" }; + rows[2797] = new[] { "PR", "Amp\u00e9re", "4101002" }; + rows[2798] = new[] { "PR", "Anahy", "4101051" }; + rows[2799] = new[] { "PR", "Andir\u00e1", "4101101" }; + } + + private static void MunicipalitiesRows14(string[][] rows) + { + rows[2800] = new[] { "PR", "\u00c2ngulo", "4101150" }; + rows[2801] = new[] { "PR", "Antonina", "4101200" }; + rows[2802] = new[] { "PR", "Ant\u00f4nio Olinto", "4101309" }; + rows[2803] = new[] { "PR", "Apucarana", "4101408" }; + rows[2804] = new[] { "PR", "Arapongas", "4101507" }; + rows[2805] = new[] { "PR", "Arapoti", "4101606" }; + rows[2806] = new[] { "PR", "Arapu\u00e3", "4101655" }; + rows[2807] = new[] { "PR", "Araruna", "4101705" }; + rows[2808] = new[] { "PR", "Arauc\u00e1ria", "4101804" }; + rows[2809] = new[] { "PR", "Ariranha do Iva\u00ed", "4101853" }; + rows[2810] = new[] { "PR", "Assa\u00ed", "4101903" }; + rows[2811] = new[] { "PR", "Assis Chateaubriand", "4102000" }; + rows[2812] = new[] { "PR", "Astorga", "4102109" }; + rows[2813] = new[] { "PR", "Atalaia", "4102208" }; + rows[2814] = new[] { "PR", "Balsa Nova", "4102307" }; + rows[2815] = new[] { "PR", "Bandeirantes", "4102406" }; + rows[2816] = new[] { "PR", "Barbosa Ferraz", "4102505" }; + rows[2817] = new[] { "PR", "Barra do Jacar\u00e9", "4102703" }; + rows[2818] = new[] { "PR", "Barrac\u00e3o", "4102604" }; + rows[2819] = new[] { "PR", "Bela Vista da Caroba", "4102752" }; + rows[2820] = new[] { "PR", "Bela Vista do Para\u00edso", "4102802" }; + rows[2821] = new[] { "PR", "Bituruna", "4102901" }; + rows[2822] = new[] { "PR", "Boa Esperan\u00e7a", "4103008" }; + rows[2823] = new[] { "PR", "Boa Esperan\u00e7a do Igua\u00e7u", "4103024" }; + rows[2824] = new[] { "PR", "Boa Ventura de S\u00e3o Roque", "4103040" }; + rows[2825] = new[] { "PR", "Boa Vista da Aparecida", "4103057" }; + rows[2826] = new[] { "PR", "Bocai\u00fava do Sul", "4103107" }; + rows[2827] = new[] { "PR", "Bom Jesus do Sul", "4103156" }; + rows[2828] = new[] { "PR", "Bom Sucesso", "4103206" }; + rows[2829] = new[] { "PR", "Bom Sucesso do Sul", "4103222" }; + rows[2830] = new[] { "PR", "Borraz\u00f3polis", "4103305" }; + rows[2831] = new[] { "PR", "Braganey", "4103354" }; + rows[2832] = new[] { "PR", "Brasil\u00e2ndia do Sul", "4103370" }; + rows[2833] = new[] { "PR", "Cafeara", "4103404" }; + rows[2834] = new[] { "PR", "Cafel\u00e2ndia", "4103453" }; + rows[2835] = new[] { "PR", "Cafezal do Sul", "4103479" }; + rows[2836] = new[] { "PR", "Calif\u00f3rnia", "4103503" }; + rows[2837] = new[] { "PR", "Cambar\u00e1", "4103602" }; + rows[2838] = new[] { "PR", "Camb\u00e9", "4103701" }; + rows[2839] = new[] { "PR", "Cambira", "4103800" }; + rows[2840] = new[] { "PR", "Campina da Lagoa", "4103909" }; + rows[2841] = new[] { "PR", "Campina do Sim\u00e3o", "4103958" }; + rows[2842] = new[] { "PR", "Campina Grande do Sul", "4104006" }; + rows[2843] = new[] { "PR", "Campo Bonito", "4104055" }; + rows[2844] = new[] { "PR", "Campo do Tenente", "4104105" }; + rows[2845] = new[] { "PR", "Campo Largo", "4104204" }; + rows[2846] = new[] { "PR", "Campo Magro", "4104253" }; + rows[2847] = new[] { "PR", "Campo Mour\u00e3o", "4104303" }; + rows[2848] = new[] { "PR", "C\u00e2ndido de Abreu", "4104402" }; + rows[2849] = new[] { "PR", "Cand\u00f3i", "4104428" }; + rows[2850] = new[] { "PR", "Cantagalo", "4104451" }; + rows[2851] = new[] { "PR", "Capanema", "4104501" }; + rows[2852] = new[] { "PR", "Capit\u00e3o Le\u00f4nidas Marques", "4104600" }; + rows[2853] = new[] { "PR", "Carambe\u00ed", "4104659" }; + rows[2854] = new[] { "PR", "Carl\u00f3polis", "4104709" }; + rows[2855] = new[] { "PR", "Cascavel", "4104808" }; + rows[2856] = new[] { "PR", "Castro", "4104907" }; + rows[2857] = new[] { "PR", "Catanduvas", "4105003" }; + rows[2858] = new[] { "PR", "Centen\u00e1rio do Sul", "4105102" }; + rows[2859] = new[] { "PR", "Cerro Azul", "4105201" }; + rows[2860] = new[] { "PR", "C\u00e9u Azul", "4105300" }; + rows[2861] = new[] { "PR", "Chopinzinho", "4105409" }; + rows[2862] = new[] { "PR", "Cianorte", "4105508" }; + rows[2863] = new[] { "PR", "Cidade Ga\u00facha", "4105607" }; + rows[2864] = new[] { "PR", "Clevel\u00e2ndia", "4105706" }; + rows[2865] = new[] { "PR", "Colombo", "4105805" }; + rows[2866] = new[] { "PR", "Colorado", "4105904" }; + rows[2867] = new[] { "PR", "Congonhinhas", "4106001" }; + rows[2868] = new[] { "PR", "Conselheiro Mairinck", "4106100" }; + rows[2869] = new[] { "PR", "Contenda", "4106209" }; + rows[2870] = new[] { "PR", "Corb\u00e9lia", "4106308" }; + rows[2871] = new[] { "PR", "Corn\u00e9lio Proc\u00f3pio", "4106407" }; + rows[2872] = new[] { "PR", "Coronel Domingos Soares", "4106456" }; + rows[2873] = new[] { "PR", "Coronel Vivida", "4106506" }; + rows[2874] = new[] { "PR", "Corumbata\u00ed do Sul", "4106555" }; + rows[2875] = new[] { "PR", "Cruz Machado", "4106803" }; + rows[2876] = new[] { "PR", "Cruzeiro do Igua\u00e7u", "4106571" }; + rows[2877] = new[] { "PR", "Cruzeiro do Oeste", "4106605" }; + rows[2878] = new[] { "PR", "Cruzeiro do Sul", "4106704" }; + rows[2879] = new[] { "PR", "Cruzmaltina", "4106852" }; + rows[2880] = new[] { "PR", "Curitiba", "4106902" }; + rows[2881] = new[] { "PR", "Curi\u00fava", "4107009" }; + rows[2882] = new[] { "PR", "Diamante D'Oeste", "4107157" }; + rows[2883] = new[] { "PR", "Diamante do Norte", "4107108" }; + rows[2884] = new[] { "PR", "Diamante do Sul", "4107124" }; + rows[2885] = new[] { "PR", "Dois Vizinhos", "4107207" }; + rows[2886] = new[] { "PR", "Douradina", "4107256" }; + rows[2887] = new[] { "PR", "Doutor Camargo", "4107306" }; + rows[2888] = new[] { "PR", "Doutor Ulysses", "4128633" }; + rows[2889] = new[] { "PR", "En\u00e9as Marques", "4107405" }; + rows[2890] = new[] { "PR", "Engenheiro Beltr\u00e3o", "4107504" }; + rows[2891] = new[] { "PR", "Entre Rios do Oeste", "4107538" }; + rows[2892] = new[] { "PR", "Esperan\u00e7a Nova", "4107520" }; + rows[2893] = new[] { "PR", "Espig\u00e3o Alto do Igua\u00e7u", "4107546" }; + rows[2894] = new[] { "PR", "Farol", "4107553" }; + rows[2895] = new[] { "PR", "Faxinal", "4107603" }; + rows[2896] = new[] { "PR", "Fazenda Rio Grande", "4107652" }; + rows[2897] = new[] { "PR", "F\u00eanix", "4107702" }; + rows[2898] = new[] { "PR", "Fernandes Pinheiro", "4107736" }; + rows[2899] = new[] { "PR", "Figueira", "4107751" }; + rows[2900] = new[] { "PR", "Flor da Serra do Sul", "4107850" }; + rows[2901] = new[] { "PR", "Flora\u00ed", "4107801" }; + rows[2902] = new[] { "PR", "Floresta", "4107900" }; + rows[2903] = new[] { "PR", "Florest\u00f3polis", "4108007" }; + rows[2904] = new[] { "PR", "Fl\u00f3rida", "4108106" }; + rows[2905] = new[] { "PR", "Formosa do Oeste", "4108205" }; + rows[2906] = new[] { "PR", "Foz do Igua\u00e7u", "4108304" }; + rows[2907] = new[] { "PR", "Foz do Jord\u00e3o", "4108452" }; + rows[2908] = new[] { "PR", "Francisco Alves", "4108320" }; + rows[2909] = new[] { "PR", "Francisco Beltr\u00e3o", "4108403" }; + rows[2910] = new[] { "PR", "General Carneiro", "4108502" }; + rows[2911] = new[] { "PR", "Godoy Moreira", "4108551" }; + rows[2912] = new[] { "PR", "Goioer\u00ea", "4108601" }; + rows[2913] = new[] { "PR", "Goioxim", "4108650" }; + rows[2914] = new[] { "PR", "Grandes Rios", "4108700" }; + rows[2915] = new[] { "PR", "Gua\u00edra", "4108809" }; + rows[2916] = new[] { "PR", "Guaira\u00e7\u00e1", "4108908" }; + rows[2917] = new[] { "PR", "Guamiranga", "4108957" }; + rows[2918] = new[] { "PR", "Guapirama", "4109005" }; + rows[2919] = new[] { "PR", "Guaporema", "4109104" }; + rows[2920] = new[] { "PR", "Guaraci", "4109203" }; + rows[2921] = new[] { "PR", "Guarania\u00e7u", "4109302" }; + rows[2922] = new[] { "PR", "Guarapuava", "4109401" }; + rows[2923] = new[] { "PR", "Guaraque\u00e7aba", "4109500" }; + rows[2924] = new[] { "PR", "Guaratuba", "4109609" }; + rows[2925] = new[] { "PR", "Hon\u00f3rio Serpa", "4109658" }; + rows[2926] = new[] { "PR", "Ibaiti", "4109708" }; + rows[2927] = new[] { "PR", "Ibema", "4109757" }; + rows[2928] = new[] { "PR", "Ibipor\u00e3", "4109807" }; + rows[2929] = new[] { "PR", "Icara\u00edma", "4109906" }; + rows[2930] = new[] { "PR", "Iguara\u00e7u", "4110003" }; + rows[2931] = new[] { "PR", "Iguatu", "4110052" }; + rows[2932] = new[] { "PR", "Imba\u00fa", "4110078" }; + rows[2933] = new[] { "PR", "Imbituva", "4110102" }; + rows[2934] = new[] { "PR", "In\u00e1cio Martins", "4110201" }; + rows[2935] = new[] { "PR", "Inaj\u00e1", "4110300" }; + rows[2936] = new[] { "PR", "Indian\u00f3polis", "4110409" }; + rows[2937] = new[] { "PR", "Ipiranga", "4110508" }; + rows[2938] = new[] { "PR", "Ipor\u00e3", "4110607" }; + rows[2939] = new[] { "PR", "Iracema do Oeste", "4110656" }; + rows[2940] = new[] { "PR", "Irati", "4110706" }; + rows[2941] = new[] { "PR", "Iretama", "4110805" }; + rows[2942] = new[] { "PR", "Itaguaj\u00e9", "4110904" }; + rows[2943] = new[] { "PR", "Itaipul\u00e2ndia", "4110953" }; + rows[2944] = new[] { "PR", "Itambarac\u00e1", "4111001" }; + rows[2945] = new[] { "PR", "Itamb\u00e9", "4111100" }; + rows[2946] = new[] { "PR", "Itapejara d'Oeste", "4111209" }; + rows[2947] = new[] { "PR", "Itaperu\u00e7u", "4111258" }; + rows[2948] = new[] { "PR", "Ita\u00fana do Sul", "4111308" }; + rows[2949] = new[] { "PR", "Iva\u00ed", "4111407" }; + rows[2950] = new[] { "PR", "Ivaipor\u00e3", "4111506" }; + rows[2951] = new[] { "PR", "Ivat\u00e9", "4111555" }; + rows[2952] = new[] { "PR", "Ivatuba", "4111605" }; + rows[2953] = new[] { "PR", "Jaboti", "4111704" }; + rows[2954] = new[] { "PR", "Jacarezinho", "4111803" }; + rows[2955] = new[] { "PR", "Jaguapit\u00e3", "4111902" }; + rows[2956] = new[] { "PR", "Jaguaria\u00edva", "4112009" }; + rows[2957] = new[] { "PR", "Jandaia do Sul", "4112108" }; + rows[2958] = new[] { "PR", "Jani\u00f3polis", "4112207" }; + rows[2959] = new[] { "PR", "Japira", "4112306" }; + rows[2960] = new[] { "PR", "Japur\u00e1", "4112405" }; + rows[2961] = new[] { "PR", "Jardim Alegre", "4112504" }; + rows[2962] = new[] { "PR", "Jardim Olinda", "4112603" }; + rows[2963] = new[] { "PR", "Jataizinho", "4112702" }; + rows[2964] = new[] { "PR", "Jesu\u00edtas", "4112751" }; + rows[2965] = new[] { "PR", "Joaquim T\u00e1vora", "4112801" }; + rows[2966] = new[] { "PR", "Jundia\u00ed do Sul", "4112900" }; + rows[2967] = new[] { "PR", "Juranda", "4112959" }; + rows[2968] = new[] { "PR", "Jussara", "4113007" }; + rows[2969] = new[] { "PR", "Kalor\u00e9", "4113106" }; + rows[2970] = new[] { "PR", "Lapa", "4113205" }; + rows[2971] = new[] { "PR", "Laranjal", "4113254" }; + rows[2972] = new[] { "PR", "Laranjeiras do Sul", "4113304" }; + rows[2973] = new[] { "PR", "Le\u00f3polis", "4113403" }; + rows[2974] = new[] { "PR", "Lidian\u00f3polis", "4113429" }; + rows[2975] = new[] { "PR", "Lindoeste", "4113452" }; + rows[2976] = new[] { "PR", "Loanda", "4113502" }; + rows[2977] = new[] { "PR", "Lobato", "4113601" }; + rows[2978] = new[] { "PR", "Londrina", "4113700" }; + rows[2979] = new[] { "PR", "Luiziana", "4113734" }; + rows[2980] = new[] { "PR", "Lunardelli", "4113759" }; + rows[2981] = new[] { "PR", "Lupion\u00f3polis", "4113809" }; + rows[2982] = new[] { "PR", "Mallet", "4113908" }; + rows[2983] = new[] { "PR", "Mambor\u00ea", "4114005" }; + rows[2984] = new[] { "PR", "Mandagua\u00e7u", "4114104" }; + rows[2985] = new[] { "PR", "Mandaguari", "4114203" }; + rows[2986] = new[] { "PR", "Mandirituba", "4114302" }; + rows[2987] = new[] { "PR", "Manfrin\u00f3polis", "4114351" }; + rows[2988] = new[] { "PR", "Mangueirinha", "4114401" }; + rows[2989] = new[] { "PR", "Manoel Ribas", "4114500" }; + rows[2990] = new[] { "PR", "Marechal C\u00e2ndido Rondon", "4114609" }; + rows[2991] = new[] { "PR", "Maria Helena", "4114708" }; + rows[2992] = new[] { "PR", "Marialva", "4114807" }; + rows[2993] = new[] { "PR", "Maril\u00e2ndia do Sul", "4114906" }; + rows[2994] = new[] { "PR", "Marilena", "4115002" }; + rows[2995] = new[] { "PR", "Mariluz", "4115101" }; + rows[2996] = new[] { "PR", "Maring\u00e1", "4115200" }; + rows[2997] = new[] { "PR", "Mari\u00f3polis", "4115309" }; + rows[2998] = new[] { "PR", "Marip\u00e1", "4115358" }; + rows[2999] = new[] { "PR", "Marmeleiro", "4115408" }; + } + + private static void MunicipalitiesRows15(string[][] rows) + { + rows[3000] = new[] { "PR", "Marquinho", "4115457" }; + rows[3001] = new[] { "PR", "Marumbi", "4115507" }; + rows[3002] = new[] { "PR", "Matel\u00e2ndia", "4115606" }; + rows[3003] = new[] { "PR", "Matinhos", "4115705" }; + rows[3004] = new[] { "PR", "Mato Rico", "4115739" }; + rows[3005] = new[] { "PR", "Mau\u00e1 da Serra", "4115754" }; + rows[3006] = new[] { "PR", "Medianeira", "4115804" }; + rows[3007] = new[] { "PR", "Mercedes", "4115853" }; + rows[3008] = new[] { "PR", "Mirador", "4115903" }; + rows[3009] = new[] { "PR", "Miraselva", "4116000" }; + rows[3010] = new[] { "PR", "Missal", "4116059" }; + rows[3011] = new[] { "PR", "Moreira Sales", "4116109" }; + rows[3012] = new[] { "PR", "Morretes", "4116208" }; + rows[3013] = new[] { "PR", "Munhoz de Melo", "4116307" }; + rows[3014] = new[] { "PR", "Nossa Senhora das Gra\u00e7as", "4116406" }; + rows[3015] = new[] { "PR", "Nova Alian\u00e7a do Iva\u00ed", "4116505" }; + rows[3016] = new[] { "PR", "Nova Am\u00e9rica da Colina", "4116604" }; + rows[3017] = new[] { "PR", "Nova Aurora", "4116703" }; + rows[3018] = new[] { "PR", "Nova Cantu", "4116802" }; + rows[3019] = new[] { "PR", "Nova Esperan\u00e7a", "4116901" }; + rows[3020] = new[] { "PR", "Nova Esperan\u00e7a do Sudoeste", "4116950" }; + rows[3021] = new[] { "PR", "Nova F\u00e1tima", "4117008" }; + rows[3022] = new[] { "PR", "Nova Laranjeiras", "4117057" }; + rows[3023] = new[] { "PR", "Nova Londrina", "4117107" }; + rows[3024] = new[] { "PR", "Nova Ol\u00edmpia", "4117206" }; + rows[3025] = new[] { "PR", "Nova Prata do Igua\u00e7u", "4117255" }; + rows[3026] = new[] { "PR", "Nova Santa B\u00e1rbara", "4117214" }; + rows[3027] = new[] { "PR", "Nova Santa Rosa", "4117222" }; + rows[3028] = new[] { "PR", "Nova Tebas", "4117271" }; + rows[3029] = new[] { "PR", "Novo Itacolomi", "4117297" }; + rows[3030] = new[] { "PR", "Ortigueira", "4117305" }; + rows[3031] = new[] { "PR", "Ourizona", "4117404" }; + rows[3032] = new[] { "PR", "Ouro Verde do Oeste", "4117453" }; + rows[3033] = new[] { "PR", "Pai\u00e7andu", "4117503" }; + rows[3034] = new[] { "PR", "Palmas", "4117602" }; + rows[3035] = new[] { "PR", "Palmeira", "4117701" }; + rows[3036] = new[] { "PR", "Palmital", "4117800" }; + rows[3037] = new[] { "PR", "Palotina", "4117909" }; + rows[3038] = new[] { "PR", "Para\u00edso do Norte", "4118006" }; + rows[3039] = new[] { "PR", "Paranacity", "4118105" }; + rows[3040] = new[] { "PR", "Paranagu\u00e1", "4118204" }; + rows[3041] = new[] { "PR", "Paranapoema", "4118303" }; + rows[3042] = new[] { "PR", "Paranava\u00ed", "4118402" }; + rows[3043] = new[] { "PR", "Pato Bragado", "4118451" }; + rows[3044] = new[] { "PR", "Pato Branco", "4118501" }; + rows[3045] = new[] { "PR", "Paula Freitas", "4118600" }; + rows[3046] = new[] { "PR", "Paulo Frontin", "4118709" }; + rows[3047] = new[] { "PR", "Peabiru", "4118808" }; + rows[3048] = new[] { "PR", "Perobal", "4118857" }; + rows[3049] = new[] { "PR", "P\u00e9rola", "4118907" }; + rows[3050] = new[] { "PR", "P\u00e9rola d'Oeste", "4119004" }; + rows[3051] = new[] { "PR", "Pi\u00ean", "4119103" }; + rows[3052] = new[] { "PR", "Pinhais", "4119152" }; + rows[3053] = new[] { "PR", "Pinhal de S\u00e3o Bento", "4119251" }; + rows[3054] = new[] { "PR", "Pinhal\u00e3o", "4119202" }; + rows[3055] = new[] { "PR", "Pinh\u00e3o", "4119301" }; + rows[3056] = new[] { "PR", "Pira\u00ed do Sul", "4119400" }; + rows[3057] = new[] { "PR", "Piraquara", "4119509" }; + rows[3058] = new[] { "PR", "Pitanga", "4119608" }; + rows[3059] = new[] { "PR", "Pitangueiras", "4119657" }; + rows[3060] = new[] { "PR", "Planaltina do Paran\u00e1", "4119707" }; + rows[3061] = new[] { "PR", "Planalto", "4119806" }; + rows[3062] = new[] { "PR", "Ponta Grossa", "4119905" }; + rows[3063] = new[] { "PR", "Pontal do Paran\u00e1", "4119954" }; + rows[3064] = new[] { "PR", "Porecatu", "4120002" }; + rows[3065] = new[] { "PR", "Porto Amazonas", "4120101" }; + rows[3066] = new[] { "PR", "Porto Barreiro", "4120150" }; + rows[3067] = new[] { "PR", "Porto Rico", "4120200" }; + rows[3068] = new[] { "PR", "Porto Vit\u00f3ria", "4120309" }; + rows[3069] = new[] { "PR", "Prado Ferreira", "4120333" }; + rows[3070] = new[] { "PR", "Pranchita", "4120358" }; + rows[3071] = new[] { "PR", "Presidente Castelo Branco", "4120408" }; + rows[3072] = new[] { "PR", "Primeiro de Maio", "4120507" }; + rows[3073] = new[] { "PR", "Prudent\u00f3polis", "4120606" }; + rows[3074] = new[] { "PR", "Quarto Centen\u00e1rio", "4120655" }; + rows[3075] = new[] { "PR", "Quatigu\u00e1", "4120705" }; + rows[3076] = new[] { "PR", "Quatro Barras", "4120804" }; + rows[3077] = new[] { "PR", "Quatro Pontes", "4120853" }; + rows[3078] = new[] { "PR", "Quedas do Igua\u00e7u", "4120903" }; + rows[3079] = new[] { "PR", "Quer\u00eancia do Norte", "4121000" }; + rows[3080] = new[] { "PR", "Quinta do Sol", "4121109" }; + rows[3081] = new[] { "PR", "Quitandinha", "4121208" }; + rows[3082] = new[] { "PR", "Ramil\u00e2ndia", "4121257" }; + rows[3083] = new[] { "PR", "Rancho Alegre", "4121307" }; + rows[3084] = new[] { "PR", "Rancho Alegre D'Oeste", "4121356" }; + rows[3085] = new[] { "PR", "Realeza", "4121406" }; + rows[3086] = new[] { "PR", "Rebou\u00e7as", "4121505" }; + rows[3087] = new[] { "PR", "Renascen\u00e7a", "4121604" }; + rows[3088] = new[] { "PR", "Reserva", "4121703" }; + rows[3089] = new[] { "PR", "Reserva do Igua\u00e7u", "4121752" }; + rows[3090] = new[] { "PR", "Ribeir\u00e3o Claro", "4121802" }; + rows[3091] = new[] { "PR", "Ribeir\u00e3o do Pinhal", "4121901" }; + rows[3092] = new[] { "PR", "Rio Azul", "4122008" }; + rows[3093] = new[] { "PR", "Rio Bom", "4122107" }; + rows[3094] = new[] { "PR", "Rio Bonito do Igua\u00e7u", "4122156" }; + rows[3095] = new[] { "PR", "Rio Branco do Iva\u00ed", "4122172" }; + rows[3096] = new[] { "PR", "Rio Branco do Sul", "4122206" }; + rows[3097] = new[] { "PR", "Rio Negro", "4122305" }; + rows[3098] = new[] { "PR", "Rol\u00e2ndia", "4122404" }; + rows[3099] = new[] { "PR", "Roncador", "4122503" }; + rows[3100] = new[] { "PR", "Rondon", "4122602" }; + rows[3101] = new[] { "PR", "Ros\u00e1rio do Iva\u00ed", "4122651" }; + rows[3102] = new[] { "PR", "Sab\u00e1udia", "4122701" }; + rows[3103] = new[] { "PR", "Salgado Filho", "4122800" }; + rows[3104] = new[] { "PR", "Salto do Itarar\u00e9", "4122909" }; + rows[3105] = new[] { "PR", "Salto do Lontra", "4123006" }; + rows[3106] = new[] { "PR", "Santa Am\u00e9lia", "4123105" }; + rows[3107] = new[] { "PR", "Santa Cec\u00edlia do Pav\u00e3o", "4123204" }; + rows[3108] = new[] { "PR", "Santa Cruz de Monte Castelo", "4123303" }; + rows[3109] = new[] { "PR", "Santa F\u00e9", "4123402" }; + rows[3110] = new[] { "PR", "Santa Helena", "4123501" }; + rows[3111] = new[] { "PR", "Santa In\u00eas", "4123600" }; + rows[3112] = new[] { "PR", "Santa Isabel do Iva\u00ed", "4123709" }; + rows[3113] = new[] { "PR", "Santa Izabel do Oeste", "4123808" }; + rows[3114] = new[] { "PR", "Santa L\u00facia", "4123824" }; + rows[3115] = new[] { "PR", "Santa Maria do Oeste", "4123857" }; + rows[3116] = new[] { "PR", "Santa Mariana", "4123907" }; + rows[3117] = new[] { "PR", "Santa M\u00f4nica", "4123956" }; + rows[3118] = new[] { "PR", "Santa Tereza do Oeste", "4124020" }; + rows[3119] = new[] { "PR", "Santa Terezinha de Itaipu", "4124053" }; + rows[3120] = new[] { "PR", "Santana do Itarar\u00e9", "4124004" }; + rows[3121] = new[] { "PR", "Santo Ant\u00f4nio da Platina", "4124103" }; + rows[3122] = new[] { "PR", "Santo Ant\u00f4nio do Caiu\u00e1", "4124202" }; + rows[3123] = new[] { "PR", "Santo Ant\u00f4nio do Para\u00edso", "4124301" }; + rows[3124] = new[] { "PR", "Santo Ant\u00f4nio do Sudoeste", "4124400" }; + rows[3125] = new[] { "PR", "Santo In\u00e1cio", "4124509" }; + rows[3126] = new[] { "PR", "S\u00e3o Carlos do Iva\u00ed", "4124608" }; + rows[3127] = new[] { "PR", "S\u00e3o Jer\u00f4nimo da Serra", "4124707" }; + rows[3128] = new[] { "PR", "S\u00e3o Jo\u00e3o", "4124806" }; + rows[3129] = new[] { "PR", "S\u00e3o Jo\u00e3o do Caiu\u00e1", "4124905" }; + rows[3130] = new[] { "PR", "S\u00e3o Jo\u00e3o do Iva\u00ed", "4125001" }; + rows[3131] = new[] { "PR", "S\u00e3o Jo\u00e3o do Triunfo", "4125100" }; + rows[3132] = new[] { "PR", "S\u00e3o Jorge d'Oeste", "4125209" }; + rows[3133] = new[] { "PR", "S\u00e3o Jorge do Iva\u00ed", "4125308" }; + rows[3134] = new[] { "PR", "S\u00e3o Jorge do Patroc\u00ednio", "4125357" }; + rows[3135] = new[] { "PR", "S\u00e3o Jos\u00e9 da Boa Vista", "4125407" }; + rows[3136] = new[] { "PR", "S\u00e3o Jos\u00e9 das Palmeiras", "4125456" }; + rows[3137] = new[] { "PR", "S\u00e3o Jos\u00e9 dos Pinhais", "4125506" }; + rows[3138] = new[] { "PR", "S\u00e3o Manoel do Paran\u00e1", "4125555" }; + rows[3139] = new[] { "PR", "S\u00e3o Mateus do Sul", "4125605" }; + rows[3140] = new[] { "PR", "S\u00e3o Miguel do Igua\u00e7u", "4125704" }; + rows[3141] = new[] { "PR", "S\u00e3o Pedro do Igua\u00e7u", "4125753" }; + rows[3142] = new[] { "PR", "S\u00e3o Pedro do Iva\u00ed", "4125803" }; + rows[3143] = new[] { "PR", "S\u00e3o Pedro do Paran\u00e1", "4125902" }; + rows[3144] = new[] { "PR", "S\u00e3o Sebasti\u00e3o da Amoreira", "4126009" }; + rows[3145] = new[] { "PR", "S\u00e3o Tom\u00e9", "4126108" }; + rows[3146] = new[] { "PR", "Sapopema", "4126207" }; + rows[3147] = new[] { "PR", "Sarandi", "4126256" }; + rows[3148] = new[] { "PR", "Saudade do Igua\u00e7u", "4126272" }; + rows[3149] = new[] { "PR", "Seng\u00e9s", "4126306" }; + rows[3150] = new[] { "PR", "Serran\u00f3polis do Igua\u00e7u", "4126355" }; + rows[3151] = new[] { "PR", "Sertaneja", "4126405" }; + rows[3152] = new[] { "PR", "Sertan\u00f3polis", "4126504" }; + rows[3153] = new[] { "PR", "Siqueira Campos", "4126603" }; + rows[3154] = new[] { "PR", "Sulina", "4126652" }; + rows[3155] = new[] { "PR", "Tamarana", "4126678" }; + rows[3156] = new[] { "PR", "Tamboara", "4126702" }; + rows[3157] = new[] { "PR", "Tapejara", "4126801" }; + rows[3158] = new[] { "PR", "Tapira", "4126900" }; + rows[3159] = new[] { "PR", "Teixeira Soares", "4127007" }; + rows[3160] = new[] { "PR", "Tel\u00eamaco Borba", "4127106" }; + rows[3161] = new[] { "PR", "Terra Boa", "4127205" }; + rows[3162] = new[] { "PR", "Terra Rica", "4127304" }; + rows[3163] = new[] { "PR", "Terra Roxa", "4127403" }; + rows[3164] = new[] { "PR", "Tibagi", "4127502" }; + rows[3165] = new[] { "PR", "Tijucas do Sul", "4127601" }; + rows[3166] = new[] { "PR", "Toledo", "4127700" }; + rows[3167] = new[] { "PR", "Tomazina", "4127809" }; + rows[3168] = new[] { "PR", "Tr\u00eas Barras do Paran\u00e1", "4127858" }; + rows[3169] = new[] { "PR", "Tunas do Paran\u00e1", "4127882" }; + rows[3170] = new[] { "PR", "Tuneiras do Oeste", "4127908" }; + rows[3171] = new[] { "PR", "Tup\u00e3ssi", "4127957" }; + rows[3172] = new[] { "PR", "Turvo", "4127965" }; + rows[3173] = new[] { "PR", "Ubirat\u00e3", "4128005" }; + rows[3174] = new[] { "PR", "Umuarama", "4128104" }; + rows[3175] = new[] { "PR", "Uni\u00e3o da Vit\u00f3ria", "4128203" }; + rows[3176] = new[] { "PR", "Uniflor", "4128302" }; + rows[3177] = new[] { "PR", "Ura\u00ed", "4128401" }; + rows[3178] = new[] { "PR", "Ventania", "4128534" }; + rows[3179] = new[] { "PR", "Vera Cruz do Oeste", "4128559" }; + rows[3180] = new[] { "PR", "Ver\u00ea", "4128609" }; + rows[3181] = new[] { "PR", "Virmond", "4128658" }; + rows[3182] = new[] { "PR", "Vitorino", "4128708" }; + rows[3183] = new[] { "PR", "Wenceslau Braz", "4128500" }; + rows[3184] = new[] { "PR", "Xambr\u00ea", "4128807" }; + rows[3185] = new[] { "PE", "Abreu e Lima", "2600054" }; + rows[3186] = new[] { "PE", "Afogados da Ingazeira", "2600104" }; + rows[3187] = new[] { "PE", "Afr\u00e2nio", "2600203" }; + rows[3188] = new[] { "PE", "Agrestina", "2600302" }; + rows[3189] = new[] { "PE", "\u00c1gua Preta", "2600401" }; + rows[3190] = new[] { "PE", "\u00c1guas Belas", "2600500" }; + rows[3191] = new[] { "PE", "Alagoinha", "2600609" }; + rows[3192] = new[] { "PE", "Alian\u00e7a", "2600708" }; + rows[3193] = new[] { "PE", "Altinho", "2600807" }; + rows[3194] = new[] { "PE", "Amaraji", "2600906" }; + rows[3195] = new[] { "PE", "Angelim", "2601003" }; + rows[3196] = new[] { "PE", "Ara\u00e7oiaba", "2601052" }; + rows[3197] = new[] { "PE", "Araripina", "2601102" }; + rows[3198] = new[] { "PE", "Arcoverde", "2601201" }; + rows[3199] = new[] { "PE", "Barra de Guabiraba", "2601300" }; + } + + private static void MunicipalitiesRows16(string[][] rows) + { + rows[3200] = new[] { "PE", "Barreiros", "2601409" }; + rows[3201] = new[] { "PE", "Bel\u00e9m de Maria", "2601508" }; + rows[3202] = new[] { "PE", "Bel\u00e9m do S\u00e3o Francisco", "2601607" }; + rows[3203] = new[] { "PE", "Belo Jardim", "2601706" }; + rows[3204] = new[] { "PE", "Bet\u00e2nia", "2601805" }; + rows[3205] = new[] { "PE", "Bezerros", "2601904" }; + rows[3206] = new[] { "PE", "Bodoc\u00f3", "2602001" }; + rows[3207] = new[] { "PE", "Bom Conselho", "2602100" }; + rows[3208] = new[] { "PE", "Bom Jardim", "2602209" }; + rows[3209] = new[] { "PE", "Bonito", "2602308" }; + rows[3210] = new[] { "PE", "Brej\u00e3o", "2602407" }; + rows[3211] = new[] { "PE", "Brejinho", "2602506" }; + rows[3212] = new[] { "PE", "Brejo da Madre de Deus", "2602605" }; + rows[3213] = new[] { "PE", "Buenos Aires", "2602704" }; + rows[3214] = new[] { "PE", "Bu\u00edque", "2602803" }; + rows[3215] = new[] { "PE", "Cabo de Santo Agostinho", "2602902" }; + rows[3216] = new[] { "PE", "Cabrob\u00f3", "2603009" }; + rows[3217] = new[] { "PE", "Cachoeirinha", "2603108" }; + rows[3218] = new[] { "PE", "Caet\u00e9s", "2603207" }; + rows[3219] = new[] { "PE", "Cal\u00e7ado", "2603306" }; + rows[3220] = new[] { "PE", "Calumbi", "2603405" }; + rows[3221] = new[] { "PE", "Camaragibe", "2603454" }; + rows[3222] = new[] { "PE", "Camocim de S\u00e3o F\u00e9lix", "2603504" }; + rows[3223] = new[] { "PE", "Camutanga", "2603603" }; + rows[3224] = new[] { "PE", "Canhotinho", "2603702" }; + rows[3225] = new[] { "PE", "Capoeiras", "2603801" }; + rows[3226] = new[] { "PE", "Carna\u00edba", "2603900" }; + rows[3227] = new[] { "PE", "Carnaubeira da Penha", "2603926" }; + rows[3228] = new[] { "PE", "Carpina", "2604007" }; + rows[3229] = new[] { "PE", "Caruaru", "2604106" }; + rows[3230] = new[] { "PE", "Casinhas", "2604155" }; + rows[3231] = new[] { "PE", "Catende", "2604205" }; + rows[3232] = new[] { "PE", "Cedro", "2604304" }; + rows[3233] = new[] { "PE", "Ch\u00e3 de Alegria", "2604403" }; + rows[3234] = new[] { "PE", "Ch\u00e3 Grande", "2604502" }; + rows[3235] = new[] { "PE", "Condado", "2604601" }; + rows[3236] = new[] { "PE", "Correntes", "2604700" }; + rows[3237] = new[] { "PE", "Cort\u00eas", "2604809" }; + rows[3238] = new[] { "PE", "Cumaru", "2604908" }; + rows[3239] = new[] { "PE", "Cupira", "2605004" }; + rows[3240] = new[] { "PE", "Cust\u00f3dia", "2605103" }; + rows[3241] = new[] { "PE", "Dormentes", "2605152" }; + rows[3242] = new[] { "PE", "Escada", "2605202" }; + rows[3243] = new[] { "PE", "Exu", "2605301" }; + rows[3244] = new[] { "PE", "Feira Nova", "2605400" }; + rows[3245] = new[] { "PE", "Fernando de Noronha", "2605459" }; + rows[3246] = new[] { "PE", "Ferreiros", "2605509" }; + rows[3247] = new[] { "PE", "Flores", "2605608" }; + rows[3248] = new[] { "PE", "Floresta", "2605707" }; + rows[3249] = new[] { "PE", "Frei Miguelinho", "2605806" }; + rows[3250] = new[] { "PE", "Gameleira", "2605905" }; + rows[3251] = new[] { "PE", "Garanhuns", "2606002" }; + rows[3252] = new[] { "PE", "Gl\u00f3ria do Goit\u00e1", "2606101" }; + rows[3253] = new[] { "PE", "Goiana", "2606200" }; + rows[3254] = new[] { "PE", "Granito", "2606309" }; + rows[3255] = new[] { "PE", "Gravat\u00e1", "2606408" }; + rows[3256] = new[] { "PE", "Iati", "2606507" }; + rows[3257] = new[] { "PE", "Ibimirim", "2606606" }; + rows[3258] = new[] { "PE", "Ibirajuba", "2606705" }; + rows[3259] = new[] { "PE", "Igarassu", "2606804" }; + rows[3260] = new[] { "PE", "Iguaracy", "2606903" }; + rows[3261] = new[] { "PE", "Ilha de Itamarac\u00e1", "2607604" }; + rows[3262] = new[] { "PE", "Inaj\u00e1", "2607000" }; + rows[3263] = new[] { "PE", "Ingazeira", "2607109" }; + rows[3264] = new[] { "PE", "Ipojuca", "2607208" }; + rows[3265] = new[] { "PE", "Ipubi", "2607307" }; + rows[3266] = new[] { "PE", "Itacuruba", "2607406" }; + rows[3267] = new[] { "PE", "Ita\u00edba", "2607505" }; + rows[3268] = new[] { "PE", "Itamb\u00e9", "2607653" }; + rows[3269] = new[] { "PE", "Itapetim", "2607703" }; + rows[3270] = new[] { "PE", "Itapissuma", "2607752" }; + rows[3271] = new[] { "PE", "Itaquitinga", "2607802" }; + rows[3272] = new[] { "PE", "Jaboat\u00e3o dos Guararapes", "2607901" }; + rows[3273] = new[] { "PE", "Jaqueira", "2607950" }; + rows[3274] = new[] { "PE", "Jata\u00faba", "2608008" }; + rows[3275] = new[] { "PE", "Jatob\u00e1", "2608057" }; + rows[3276] = new[] { "PE", "Jo\u00e3o Alfredo", "2608107" }; + rows[3277] = new[] { "PE", "Joaquim Nabuco", "2608206" }; + rows[3278] = new[] { "PE", "Jucati", "2608255" }; + rows[3279] = new[] { "PE", "Jupi", "2608305" }; + rows[3280] = new[] { "PE", "Jurema", "2608404" }; + rows[3281] = new[] { "PE", "Lagoa de Itaenga", "2608503" }; + rows[3282] = new[] { "PE", "Lagoa do Carro", "2608453" }; + rows[3283] = new[] { "PE", "Lagoa do Ouro", "2608602" }; + rows[3284] = new[] { "PE", "Lagoa dos Gatos", "2608701" }; + rows[3285] = new[] { "PE", "Lagoa Grande", "2608750" }; + rows[3286] = new[] { "PE", "Lajedo", "2608800" }; + rows[3287] = new[] { "PE", "Limoeiro", "2608909" }; + rows[3288] = new[] { "PE", "Macaparana", "2609006" }; + rows[3289] = new[] { "PE", "Machados", "2609105" }; + rows[3290] = new[] { "PE", "Manari", "2609154" }; + rows[3291] = new[] { "PE", "Maraial", "2609204" }; + rows[3292] = new[] { "PE", "Mirandiba", "2609303" }; + rows[3293] = new[] { "PE", "Moreil\u00e2ndia", "2614303" }; + rows[3294] = new[] { "PE", "Moreno", "2609402" }; + rows[3295] = new[] { "PE", "Nazar\u00e9 da Mata", "2609501" }; + rows[3296] = new[] { "PE", "Olinda", "2609600" }; + rows[3297] = new[] { "PE", "Orob\u00f3", "2609709" }; + rows[3298] = new[] { "PE", "Oroc\u00f3", "2609808" }; + rows[3299] = new[] { "PE", "Ouricuri", "2609907" }; + rows[3300] = new[] { "PE", "Palmares", "2610004" }; + rows[3301] = new[] { "PE", "Palmeirina", "2610103" }; + rows[3302] = new[] { "PE", "Panelas", "2610202" }; + rows[3303] = new[] { "PE", "Paranatama", "2610301" }; + rows[3304] = new[] { "PE", "Parnamirim", "2610400" }; + rows[3305] = new[] { "PE", "Passira", "2610509" }; + rows[3306] = new[] { "PE", "Paudalho", "2610608" }; + rows[3307] = new[] { "PE", "Paulista", "2610707" }; + rows[3308] = new[] { "PE", "Pedra", "2610806" }; + rows[3309] = new[] { "PE", "Pesqueira", "2610905" }; + rows[3310] = new[] { "PE", "Petrol\u00e2ndia", "2611002" }; + rows[3311] = new[] { "PE", "Petrolina", "2611101" }; + rows[3312] = new[] { "PE", "Po\u00e7\u00e3o", "2611200" }; + rows[3313] = new[] { "PE", "Pombos", "2611309" }; + rows[3314] = new[] { "PE", "Primavera", "2611408" }; + rows[3315] = new[] { "PE", "Quipap\u00e1", "2611507" }; + rows[3316] = new[] { "PE", "Quixaba", "2611533" }; + rows[3317] = new[] { "PE", "Recife", "2611606" }; + rows[3318] = new[] { "PE", "Riacho das Almas", "2611705" }; + rows[3319] = new[] { "PE", "Ribeir\u00e3o", "2611804" }; + rows[3320] = new[] { "PE", "Rio Formoso", "2611903" }; + rows[3321] = new[] { "PE", "Sair\u00e9", "2612000" }; + rows[3322] = new[] { "PE", "Salgadinho", "2612109" }; + rows[3323] = new[] { "PE", "Salgueiro", "2612208" }; + rows[3324] = new[] { "PE", "Salo\u00e1", "2612307" }; + rows[3325] = new[] { "PE", "Sanhar\u00f3", "2612406" }; + rows[3326] = new[] { "PE", "Santa Cruz", "2612455" }; + rows[3327] = new[] { "PE", "Santa Cruz da Baixa Verde", "2612471" }; + rows[3328] = new[] { "PE", "Santa Cruz do Capibaribe", "2612505" }; + rows[3329] = new[] { "PE", "Santa Filomena", "2612554" }; + rows[3330] = new[] { "PE", "Santa Maria da Boa Vista", "2612604" }; + rows[3331] = new[] { "PE", "Santa Maria do Cambuc\u00e1", "2612703" }; + rows[3332] = new[] { "PE", "Santa Terezinha", "2612802" }; + rows[3333] = new[] { "PE", "S\u00e3o Benedito do Sul", "2612901" }; + rows[3334] = new[] { "PE", "S\u00e3o Bento do Una", "2613008" }; + rows[3335] = new[] { "PE", "S\u00e3o Caitano", "2613107" }; + rows[3336] = new[] { "PE", "S\u00e3o Jo\u00e3o", "2613206" }; + rows[3337] = new[] { "PE", "S\u00e3o Joaquim do Monte", "2613305" }; + rows[3338] = new[] { "PE", "S\u00e3o Jos\u00e9 da Coroa Grande", "2613404" }; + rows[3339] = new[] { "PE", "S\u00e3o Jos\u00e9 do Belmonte", "2613503" }; + rows[3340] = new[] { "PE", "S\u00e3o Jos\u00e9 do Egito", "2613602" }; + rows[3341] = new[] { "PE", "S\u00e3o Louren\u00e7o da Mata", "2613701" }; + rows[3342] = new[] { "PE", "S\u00e3o Vicente F\u00e9rrer", "2613800" }; + rows[3343] = new[] { "PE", "Serra Talhada", "2613909" }; + rows[3344] = new[] { "PE", "Serrita", "2614006" }; + rows[3345] = new[] { "PE", "Sert\u00e2nia", "2614105" }; + rows[3346] = new[] { "PE", "Sirinha\u00e9m", "2614204" }; + rows[3347] = new[] { "PE", "Solid\u00e3o", "2614402" }; + rows[3348] = new[] { "PE", "Surubim", "2614501" }; + rows[3349] = new[] { "PE", "Tabira", "2614600" }; + rows[3350] = new[] { "PE", "Tacaimb\u00f3", "2614709" }; + rows[3351] = new[] { "PE", "Tacaratu", "2614808" }; + rows[3352] = new[] { "PE", "Tamandar\u00e9", "2614857" }; + rows[3353] = new[] { "PE", "Taquaritinga do Norte", "2615003" }; + rows[3354] = new[] { "PE", "Terezinha", "2615102" }; + rows[3355] = new[] { "PE", "Terra Nova", "2615201" }; + rows[3356] = new[] { "PE", "Timba\u00faba", "2615300" }; + rows[3357] = new[] { "PE", "Toritama", "2615409" }; + rows[3358] = new[] { "PE", "Tracunha\u00e9m", "2615508" }; + rows[3359] = new[] { "PE", "Trindade", "2615607" }; + rows[3360] = new[] { "PE", "Triunfo", "2615706" }; + rows[3361] = new[] { "PE", "Tupanatinga", "2615805" }; + rows[3362] = new[] { "PE", "Tuparetama", "2615904" }; + rows[3363] = new[] { "PE", "Venturosa", "2616001" }; + rows[3364] = new[] { "PE", "Verdejante", "2616100" }; + rows[3365] = new[] { "PE", "Vertente do L\u00e9rio", "2616183" }; + rows[3366] = new[] { "PE", "Vertentes", "2616209" }; + rows[3367] = new[] { "PE", "Vic\u00eancia", "2616308" }; + rows[3368] = new[] { "PE", "Vit\u00f3ria de Santo Ant\u00e3o", "2616407" }; + rows[3369] = new[] { "PE", "Xex\u00e9u", "2616506" }; + rows[3370] = new[] { "PI", "Acau\u00e3", "2200053" }; + rows[3371] = new[] { "PI", "Agricol\u00e2ndia", "2200103" }; + rows[3372] = new[] { "PI", "\u00c1gua Branca", "2200202" }; + rows[3373] = new[] { "PI", "Alagoinha do Piau\u00ed", "2200251" }; + rows[3374] = new[] { "PI", "Alegrete do Piau\u00ed", "2200277" }; + rows[3375] = new[] { "PI", "Alto Long\u00e1", "2200301" }; + rows[3376] = new[] { "PI", "Altos", "2200400" }; + rows[3377] = new[] { "PI", "Alvorada do Gurgu\u00e9ia", "2200459" }; + rows[3378] = new[] { "PI", "Amarante", "2200509" }; + rows[3379] = new[] { "PI", "Angical do Piau\u00ed", "2200608" }; + rows[3380] = new[] { "PI", "An\u00edsio de Abreu", "2200707" }; + rows[3381] = new[] { "PI", "Ant\u00f4nio Almeida", "2200806" }; + rows[3382] = new[] { "PI", "Aroazes", "2200905" }; + rows[3383] = new[] { "PI", "Aroeiras do Itaim", "2200954" }; + rows[3384] = new[] { "PI", "Arraial", "2201002" }; + rows[3385] = new[] { "PI", "Assun\u00e7\u00e3o do Piau\u00ed", "2201051" }; + rows[3386] = new[] { "PI", "Avelino Lopes", "2201101" }; + rows[3387] = new[] { "PI", "Baixa Grande do Ribeiro", "2201150" }; + rows[3388] = new[] { "PI", "Barra D'Alc\u00e2ntara", "2201176" }; + rows[3389] = new[] { "PI", "Barras", "2201200" }; + rows[3390] = new[] { "PI", "Barreiras do Piau\u00ed", "2201309" }; + rows[3391] = new[] { "PI", "Barro Duro", "2201408" }; + rows[3392] = new[] { "PI", "Batalha", "2201507" }; + rows[3393] = new[] { "PI", "Bela Vista do Piau\u00ed", "2201556" }; + rows[3394] = new[] { "PI", "Bel\u00e9m do Piau\u00ed", "2201572" }; + rows[3395] = new[] { "PI", "Beneditinos", "2201606" }; + rows[3396] = new[] { "PI", "Bertol\u00ednia", "2201705" }; + rows[3397] = new[] { "PI", "Bet\u00e2nia do Piau\u00ed", "2201739" }; + rows[3398] = new[] { "PI", "Boa Hora", "2201770" }; + rows[3399] = new[] { "PI", "Bocaina", "2201804" }; + } + + private static void MunicipalitiesRows17(string[][] rows) + { + rows[3400] = new[] { "PI", "Bom Jesus", "2201903" }; + rows[3401] = new[] { "PI", "Bom Princ\u00edpio do Piau\u00ed", "2201919" }; + rows[3402] = new[] { "PI", "Bonfim do Piau\u00ed", "2201929" }; + rows[3403] = new[] { "PI", "Boqueir\u00e3o do Piau\u00ed", "2201945" }; + rows[3404] = new[] { "PI", "Brasileira", "2201960" }; + rows[3405] = new[] { "PI", "Brejo do Piau\u00ed", "2201988" }; + rows[3406] = new[] { "PI", "Buriti dos Lopes", "2202000" }; + rows[3407] = new[] { "PI", "Buriti dos Montes", "2202026" }; + rows[3408] = new[] { "PI", "Cabeceiras do Piau\u00ed", "2202059" }; + rows[3409] = new[] { "PI", "Cajazeiras do Piau\u00ed", "2202075" }; + rows[3410] = new[] { "PI", "Cajueiro da Praia", "2202083" }; + rows[3411] = new[] { "PI", "Caldeir\u00e3o Grande do Piau\u00ed", "2202091" }; + rows[3412] = new[] { "PI", "Campinas do Piau\u00ed", "2202109" }; + rows[3413] = new[] { "PI", "Campo Alegre do Fidalgo", "2202117" }; + rows[3414] = new[] { "PI", "Campo Grande do Piau\u00ed", "2202133" }; + rows[3415] = new[] { "PI", "Campo Largo do Piau\u00ed", "2202174" }; + rows[3416] = new[] { "PI", "Campo Maior", "2202208" }; + rows[3417] = new[] { "PI", "Canavieira", "2202251" }; + rows[3418] = new[] { "PI", "Canto do Buriti", "2202307" }; + rows[3419] = new[] { "PI", "Capit\u00e3o de Campos", "2202406" }; + rows[3420] = new[] { "PI", "Capit\u00e3o Gerv\u00e1sio Oliveira", "2202455" }; + rows[3421] = new[] { "PI", "Caracol", "2202505" }; + rows[3422] = new[] { "PI", "Cara\u00fabas do Piau\u00ed", "2202539" }; + rows[3423] = new[] { "PI", "Caridade do Piau\u00ed", "2202554" }; + rows[3424] = new[] { "PI", "Castelo do Piau\u00ed", "2202604" }; + rows[3425] = new[] { "PI", "Caxing\u00f3", "2202653" }; + rows[3426] = new[] { "PI", "Cocal", "2202703" }; + rows[3427] = new[] { "PI", "Cocal de Telha", "2202711" }; + rows[3428] = new[] { "PI", "Cocal dos Alves", "2202729" }; + rows[3429] = new[] { "PI", "Coivaras", "2202737" }; + rows[3430] = new[] { "PI", "Col\u00f4nia do Gurgu\u00e9ia", "2202752" }; + rows[3431] = new[] { "PI", "Col\u00f4nia do Piau\u00ed", "2202778" }; + rows[3432] = new[] { "PI", "Concei\u00e7\u00e3o do Canind\u00e9", "2202802" }; + rows[3433] = new[] { "PI", "Coronel Jos\u00e9 Dias", "2202851" }; + rows[3434] = new[] { "PI", "Corrente", "2202901" }; + rows[3435] = new[] { "PI", "Cristal\u00e2ndia do Piau\u00ed", "2203008" }; + rows[3436] = new[] { "PI", "Cristino Castro", "2203107" }; + rows[3437] = new[] { "PI", "Curimat\u00e1", "2203206" }; + rows[3438] = new[] { "PI", "Currais", "2203230" }; + rows[3439] = new[] { "PI", "Curral Novo do Piau\u00ed", "2203271" }; + rows[3440] = new[] { "PI", "Curralinhos", "2203255" }; + rows[3441] = new[] { "PI", "Demerval Lob\u00e3o", "2203305" }; + rows[3442] = new[] { "PI", "Dirceu Arcoverde", "2203354" }; + rows[3443] = new[] { "PI", "Dom Expedito Lopes", "2203404" }; + rows[3444] = new[] { "PI", "Dom Inoc\u00eancio", "2203453" }; + rows[3445] = new[] { "PI", "Domingos Mour\u00e3o", "2203420" }; + rows[3446] = new[] { "PI", "Elesb\u00e3o Veloso", "2203503" }; + rows[3447] = new[] { "PI", "Eliseu Martins", "2203602" }; + rows[3448] = new[] { "PI", "Esperantina", "2203701" }; + rows[3449] = new[] { "PI", "Fartura do Piau\u00ed", "2203750" }; + rows[3450] = new[] { "PI", "Flores do Piau\u00ed", "2203800" }; + rows[3451] = new[] { "PI", "Floresta do Piau\u00ed", "2203859" }; + rows[3452] = new[] { "PI", "Floriano", "2203909" }; + rows[3453] = new[] { "PI", "Francin\u00f3polis", "2204006" }; + rows[3454] = new[] { "PI", "Francisco Ayres", "2204105" }; + rows[3455] = new[] { "PI", "Francisco Macedo", "2204154" }; + rows[3456] = new[] { "PI", "Francisco Santos", "2204204" }; + rows[3457] = new[] { "PI", "Fronteiras", "2204303" }; + rows[3458] = new[] { "PI", "Geminiano", "2204352" }; + rows[3459] = new[] { "PI", "Gilbu\u00e9s", "2204402" }; + rows[3460] = new[] { "PI", "Guadalupe", "2204501" }; + rows[3461] = new[] { "PI", "Guaribas", "2204550" }; + rows[3462] = new[] { "PI", "Hugo Napole\u00e3o", "2204600" }; + rows[3463] = new[] { "PI", "Ilha Grande", "2204659" }; + rows[3464] = new[] { "PI", "Inhuma", "2204709" }; + rows[3465] = new[] { "PI", "Ipiranga do Piau\u00ed", "2204808" }; + rows[3466] = new[] { "PI", "Isa\u00edas Coelho", "2204907" }; + rows[3467] = new[] { "PI", "Itain\u00f3polis", "2205003" }; + rows[3468] = new[] { "PI", "Itaueira", "2205102" }; + rows[3469] = new[] { "PI", "Jacobina do Piau\u00ed", "2205151" }; + rows[3470] = new[] { "PI", "Jaic\u00f3s", "2205201" }; + rows[3471] = new[] { "PI", "Jardim do Mulato", "2205250" }; + rows[3472] = new[] { "PI", "Jatob\u00e1 do Piau\u00ed", "2205276" }; + rows[3473] = new[] { "PI", "Jerumenha", "2205300" }; + rows[3474] = new[] { "PI", "Jo\u00e3o Costa", "2205359" }; + rows[3475] = new[] { "PI", "Joaquim Pires", "2205409" }; + rows[3476] = new[] { "PI", "Joca Marques", "2205458" }; + rows[3477] = new[] { "PI", "Jos\u00e9 de Freitas", "2205508" }; + rows[3478] = new[] { "PI", "Juazeiro do Piau\u00ed", "2205516" }; + rows[3479] = new[] { "PI", "J\u00falio Borges", "2205524" }; + rows[3480] = new[] { "PI", "Jurema", "2205532" }; + rows[3481] = new[] { "PI", "Lagoa Alegre", "2205557" }; + rows[3482] = new[] { "PI", "Lagoa de S\u00e3o Francisco", "2205573" }; + rows[3483] = new[] { "PI", "Lagoa do Barro do Piau\u00ed", "2205565" }; + rows[3484] = new[] { "PI", "Lagoa do Piau\u00ed", "2205581" }; + rows[3485] = new[] { "PI", "Lagoa do S\u00edtio", "2205599" }; + rows[3486] = new[] { "PI", "Lagoinha do Piau\u00ed", "2205540" }; + rows[3487] = new[] { "PI", "Landri Sales", "2205607" }; + rows[3488] = new[] { "PI", "Lu\u00eds Correia", "2205706" }; + rows[3489] = new[] { "PI", "Luzil\u00e2ndia", "2205805" }; + rows[3490] = new[] { "PI", "Madeiro", "2205854" }; + rows[3491] = new[] { "PI", "Manoel Em\u00eddio", "2205904" }; + rows[3492] = new[] { "PI", "Marcol\u00e2ndia", "2205953" }; + rows[3493] = new[] { "PI", "Marcos Parente", "2206001" }; + rows[3494] = new[] { "PI", "Massap\u00ea do Piau\u00ed", "2206050" }; + rows[3495] = new[] { "PI", "Matias Ol\u00edmpio", "2206100" }; + rows[3496] = new[] { "PI", "Miguel Alves", "2206209" }; + rows[3497] = new[] { "PI", "Miguel Le\u00e3o", "2206308" }; + rows[3498] = new[] { "PI", "Milton Brand\u00e3o", "2206357" }; + rows[3499] = new[] { "PI", "Monsenhor Gil", "2206407" }; + rows[3500] = new[] { "PI", "Monsenhor Hip\u00f3lito", "2206506" }; + rows[3501] = new[] { "PI", "Monte Alegre do Piau\u00ed", "2206605" }; + rows[3502] = new[] { "PI", "Morro Cabe\u00e7a no Tempo", "2206654" }; + rows[3503] = new[] { "PI", "Morro do Chap\u00e9u do Piau\u00ed", "2206670" }; + rows[3504] = new[] { "PI", "Murici dos Portelas", "2206696" }; + rows[3505] = new[] { "PI", "Nazar\u00e9 do Piau\u00ed", "2206704" }; + rows[3506] = new[] { "PI", "Naz\u00e1ria", "2206720" }; + rows[3507] = new[] { "PI", "Nossa Senhora de Nazar\u00e9", "2206753" }; + rows[3508] = new[] { "PI", "Nossa Senhora dos Rem\u00e9dios", "2206803" }; + rows[3509] = new[] { "PI", "Nova Santa Rita", "2207959" }; + rows[3510] = new[] { "PI", "Novo Oriente do Piau\u00ed", "2206902" }; + rows[3511] = new[] { "PI", "Novo Santo Ant\u00f4nio", "2206951" }; + rows[3512] = new[] { "PI", "Oeiras", "2207009" }; + rows[3513] = new[] { "PI", "Olho D'\u00c1gua do Piau\u00ed", "2207108" }; + rows[3514] = new[] { "PI", "Padre Marcos", "2207207" }; + rows[3515] = new[] { "PI", "Paes Landim", "2207306" }; + rows[3516] = new[] { "PI", "Paje\u00fa do Piau\u00ed", "2207355" }; + rows[3517] = new[] { "PI", "Palmeira do Piau\u00ed", "2207405" }; + rows[3518] = new[] { "PI", "Palmeirais", "2207504" }; + rows[3519] = new[] { "PI", "Paquet\u00e1", "2207553" }; + rows[3520] = new[] { "PI", "Parnagu\u00e1", "2207603" }; + rows[3521] = new[] { "PI", "Parna\u00edba", "2207702" }; + rows[3522] = new[] { "PI", "Passagem Franca do Piau\u00ed", "2207751" }; + rows[3523] = new[] { "PI", "Patos do Piau\u00ed", "2207777" }; + rows[3524] = new[] { "PI", "Pau D'Arco do Piau\u00ed", "2207793" }; + rows[3525] = new[] { "PI", "Paulistana", "2207801" }; + rows[3526] = new[] { "PI", "Pavussu", "2207850" }; + rows[3527] = new[] { "PI", "Pedro II", "2207900" }; + rows[3528] = new[] { "PI", "Pedro Laurentino", "2207934" }; + rows[3529] = new[] { "PI", "Picos", "2208007" }; + rows[3530] = new[] { "PI", "Pimenteiras", "2208106" }; + rows[3531] = new[] { "PI", "Pio IX", "2208205" }; + rows[3532] = new[] { "PI", "Piracuruca", "2208304" }; + rows[3533] = new[] { "PI", "Piripiri", "2208403" }; + rows[3534] = new[] { "PI", "Porto", "2208502" }; + rows[3535] = new[] { "PI", "Porto Alegre do Piau\u00ed", "2208551" }; + rows[3536] = new[] { "PI", "Prata do Piau\u00ed", "2208601" }; + rows[3537] = new[] { "PI", "Queimada Nova", "2208650" }; + rows[3538] = new[] { "PI", "Reden\u00e7\u00e3o do Gurgu\u00e9ia", "2208700" }; + rows[3539] = new[] { "PI", "Regenera\u00e7\u00e3o", "2208809" }; + rows[3540] = new[] { "PI", "Riacho Frio", "2208858" }; + rows[3541] = new[] { "PI", "Ribeira do Piau\u00ed", "2208874" }; + rows[3542] = new[] { "PI", "Ribeiro Gon\u00e7alves", "2208908" }; + rows[3543] = new[] { "PI", "Rio Grande do Piau\u00ed", "2209005" }; + rows[3544] = new[] { "PI", "Santa Cruz do Piau\u00ed", "2209104" }; + rows[3545] = new[] { "PI", "Santa Cruz dos Milagres", "2209153" }; + rows[3546] = new[] { "PI", "Santa Filomena", "2209203" }; + rows[3547] = new[] { "PI", "Santa Luz", "2209302" }; + rows[3548] = new[] { "PI", "Santa Rosa do Piau\u00ed", "2209377" }; + rows[3549] = new[] { "PI", "Santana do Piau\u00ed", "2209351" }; + rows[3550] = new[] { "PI", "Santo Ant\u00f4nio de Lisboa", "2209401" }; + rows[3551] = new[] { "PI", "Santo Ant\u00f4nio dos Milagres", "2209450" }; + rows[3552] = new[] { "PI", "Santo In\u00e1cio do Piau\u00ed", "2209500" }; + rows[3553] = new[] { "PI", "S\u00e3o Braz do Piau\u00ed", "2209559" }; + rows[3554] = new[] { "PI", "S\u00e3o F\u00e9lix do Piau\u00ed", "2209609" }; + rows[3555] = new[] { "PI", "S\u00e3o Francisco de Assis do Piau\u00ed", "2209658" }; + rows[3556] = new[] { "PI", "S\u00e3o Francisco do Piau\u00ed", "2209708" }; + rows[3557] = new[] { "PI", "S\u00e3o Gon\u00e7alo do Gurgu\u00e9ia", "2209757" }; + rows[3558] = new[] { "PI", "S\u00e3o Gon\u00e7alo do Piau\u00ed", "2209807" }; + rows[3559] = new[] { "PI", "S\u00e3o Jo\u00e3o da Canabrava", "2209856" }; + rows[3560] = new[] { "PI", "S\u00e3o Jo\u00e3o da Fronteira", "2209872" }; + rows[3561] = new[] { "PI", "S\u00e3o Jo\u00e3o da Serra", "2209906" }; + rows[3562] = new[] { "PI", "S\u00e3o Jo\u00e3o da Varjota", "2209955" }; + rows[3563] = new[] { "PI", "S\u00e3o Jo\u00e3o do Arraial", "2209971" }; + rows[3564] = new[] { "PI", "S\u00e3o Jo\u00e3o do Piau\u00ed", "2210003" }; + rows[3565] = new[] { "PI", "S\u00e3o Jos\u00e9 do Divino", "2210052" }; + rows[3566] = new[] { "PI", "S\u00e3o Jos\u00e9 do Peixe", "2210102" }; + rows[3567] = new[] { "PI", "S\u00e3o Jos\u00e9 do Piau\u00ed", "2210201" }; + rows[3568] = new[] { "PI", "S\u00e3o Juli\u00e3o", "2210300" }; + rows[3569] = new[] { "PI", "S\u00e3o Louren\u00e7o do Piau\u00ed", "2210359" }; + rows[3570] = new[] { "PI", "S\u00e3o Luis do Piau\u00ed", "2210375" }; + rows[3571] = new[] { "PI", "S\u00e3o Miguel da Baixa Grande", "2210383" }; + rows[3572] = new[] { "PI", "S\u00e3o Miguel do Fidalgo", "2210391" }; + rows[3573] = new[] { "PI", "S\u00e3o Miguel do Tapuio", "2210409" }; + rows[3574] = new[] { "PI", "S\u00e3o Pedro do Piau\u00ed", "2210508" }; + rows[3575] = new[] { "PI", "S\u00e3o Raimundo Nonato", "2210607" }; + rows[3576] = new[] { "PI", "Sebasti\u00e3o Barros", "2210623" }; + rows[3577] = new[] { "PI", "Sebasti\u00e3o Leal", "2210631" }; + rows[3578] = new[] { "PI", "Sigefredo Pacheco", "2210656" }; + rows[3579] = new[] { "PI", "Sim\u00f5es", "2210706" }; + rows[3580] = new[] { "PI", "Simpl\u00edcio Mendes", "2210805" }; + rows[3581] = new[] { "PI", "Socorro do Piau\u00ed", "2210904" }; + rows[3582] = new[] { "PI", "Sussuapara", "2210938" }; + rows[3583] = new[] { "PI", "Tamboril do Piau\u00ed", "2210953" }; + rows[3584] = new[] { "PI", "Tanque do Piau\u00ed", "2210979" }; + rows[3585] = new[] { "PI", "Teresina", "2211001" }; + rows[3586] = new[] { "PI", "Uni\u00e3o", "2211100" }; + rows[3587] = new[] { "PI", "Uru\u00e7u\u00ed", "2211209" }; + rows[3588] = new[] { "PI", "Valen\u00e7a do Piau\u00ed", "2211308" }; + rows[3589] = new[] { "PI", "V\u00e1rzea Branca", "2211357" }; + rows[3590] = new[] { "PI", "V\u00e1rzea Grande", "2211407" }; + rows[3591] = new[] { "PI", "Vera Mendes", "2211506" }; + rows[3592] = new[] { "PI", "Vila Nova do Piau\u00ed", "2211605" }; + rows[3593] = new[] { "PI", "Wall Ferraz", "2211704" }; + rows[3594] = new[] { "RJ", "Angra dos Reis", "3300100" }; + rows[3595] = new[] { "RJ", "Aperib\u00e9", "3300159" }; + rows[3596] = new[] { "RJ", "Araruama", "3300209" }; + rows[3597] = new[] { "RJ", "Areal", "3300225" }; + rows[3598] = new[] { "RJ", "Arma\u00e7\u00e3o dos B\u00fazios", "3300233" }; + rows[3599] = new[] { "RJ", "Arraial do Cabo", "3300258" }; + } + + private static void MunicipalitiesRows18(string[][] rows) + { + rows[3600] = new[] { "RJ", "Barra do Pira\u00ed", "3300308" }; + rows[3601] = new[] { "RJ", "Barra Mansa", "3300407" }; + rows[3602] = new[] { "RJ", "Belford Roxo", "3300456" }; + rows[3603] = new[] { "RJ", "Bom Jardim", "3300506" }; + rows[3604] = new[] { "RJ", "Bom Jesus do Itabapoana", "3300605" }; + rows[3605] = new[] { "RJ", "Cabo Frio", "3300704" }; + rows[3606] = new[] { "RJ", "Cachoeiras de Macacu", "3300803" }; + rows[3607] = new[] { "RJ", "Cambuci", "3300902" }; + rows[3608] = new[] { "RJ", "Campos dos Goytacazes", "3301009" }; + rows[3609] = new[] { "RJ", "Cantagalo", "3301108" }; + rows[3610] = new[] { "RJ", "Carapebus", "3300936" }; + rows[3611] = new[] { "RJ", "Cardoso Moreira", "3301157" }; + rows[3612] = new[] { "RJ", "Carmo", "3301207" }; + rows[3613] = new[] { "RJ", "Casimiro de Abreu", "3301306" }; + rows[3614] = new[] { "RJ", "Comendador Levy Gasparian", "3300951" }; + rows[3615] = new[] { "RJ", "Concei\u00e7\u00e3o de Macabu", "3301405" }; + rows[3616] = new[] { "RJ", "Cordeiro", "3301504" }; + rows[3617] = new[] { "RJ", "Duas Barras", "3301603" }; + rows[3618] = new[] { "RJ", "Duque de Caxias", "3301702" }; + rows[3619] = new[] { "RJ", "Engenheiro Paulo de Frontin", "3301801" }; + rows[3620] = new[] { "RJ", "Guapimirim", "3301850" }; + rows[3621] = new[] { "RJ", "Iguaba Grande", "3301876" }; + rows[3622] = new[] { "RJ", "Itabora\u00ed", "3301900" }; + rows[3623] = new[] { "RJ", "Itagua\u00ed", "3302007" }; + rows[3624] = new[] { "RJ", "Italva", "3302056" }; + rows[3625] = new[] { "RJ", "Itaocara", "3302106" }; + rows[3626] = new[] { "RJ", "Itaperuna", "3302205" }; + rows[3627] = new[] { "RJ", "Itatiaia", "3302254" }; + rows[3628] = new[] { "RJ", "Japeri", "3302270" }; + rows[3629] = new[] { "RJ", "Laje do Muria\u00e9", "3302304" }; + rows[3630] = new[] { "RJ", "Maca\u00e9", "3302403" }; + rows[3631] = new[] { "RJ", "Macuco", "3302452" }; + rows[3632] = new[] { "RJ", "Mag\u00e9", "3302502" }; + rows[3633] = new[] { "RJ", "Mangaratiba", "3302601" }; + rows[3634] = new[] { "RJ", "Maric\u00e1", "3302700" }; + rows[3635] = new[] { "RJ", "Mendes", "3302809" }; + rows[3636] = new[] { "RJ", "Mesquita", "3302858" }; + rows[3637] = new[] { "RJ", "Miguel Pereira", "3302908" }; + rows[3638] = new[] { "RJ", "Miracema", "3303005" }; + rows[3639] = new[] { "RJ", "Natividade", "3303104" }; + rows[3640] = new[] { "RJ", "Nil\u00f3polis", "3303203" }; + rows[3641] = new[] { "RJ", "Niter\u00f3i", "3303302" }; + rows[3642] = new[] { "RJ", "Nova Friburgo", "3303401" }; + rows[3643] = new[] { "RJ", "Nova Igua\u00e7u", "3303500" }; + rows[3644] = new[] { "RJ", "Paracambi", "3303609" }; + rows[3645] = new[] { "RJ", "Para\u00edba do Sul", "3303708" }; + rows[3646] = new[] { "RJ", "Paraty", "3303807" }; + rows[3647] = new[] { "RJ", "Paty do Alferes", "3303856" }; + rows[3648] = new[] { "RJ", "Petr\u00f3polis", "3303906" }; + rows[3649] = new[] { "RJ", "Pinheiral", "3303955" }; + rows[3650] = new[] { "RJ", "Pira\u00ed", "3304003" }; + rows[3651] = new[] { "RJ", "Porci\u00fancula", "3304102" }; + rows[3652] = new[] { "RJ", "Porto Real", "3304110" }; + rows[3653] = new[] { "RJ", "Quatis", "3304128" }; + rows[3654] = new[] { "RJ", "Queimados", "3304144" }; + rows[3655] = new[] { "RJ", "Quissam\u00e3", "3304151" }; + rows[3656] = new[] { "RJ", "Resende", "3304201" }; + rows[3657] = new[] { "RJ", "Rio Bonito", "3304300" }; + rows[3658] = new[] { "RJ", "Rio Claro", "3304409" }; + rows[3659] = new[] { "RJ", "Rio das Flores", "3304508" }; + rows[3660] = new[] { "RJ", "Rio das Ostras", "3304524" }; + rows[3661] = new[] { "RJ", "Rio de Janeiro", "3304557" }; + rows[3662] = new[] { "RJ", "Santa Maria Madalena", "3304607" }; + rows[3663] = new[] { "RJ", "Santo Ant\u00f4nio de P\u00e1dua", "3304706" }; + rows[3664] = new[] { "RJ", "S\u00e3o Fid\u00e9lis", "3304805" }; + rows[3665] = new[] { "RJ", "S\u00e3o Francisco de Itabapoana", "3304755" }; + rows[3666] = new[] { "RJ", "S\u00e3o Gon\u00e7alo", "3304904" }; + rows[3667] = new[] { "RJ", "S\u00e3o Jo\u00e3o da Barra", "3305000" }; + rows[3668] = new[] { "RJ", "S\u00e3o Jo\u00e3o de Meriti", "3305109" }; + rows[3669] = new[] { "RJ", "S\u00e3o Jos\u00e9 de Ub\u00e1", "3305133" }; + rows[3670] = new[] { "RJ", "S\u00e3o Jos\u00e9 do Vale do Rio Preto", "3305158" }; + rows[3671] = new[] { "RJ", "S\u00e3o Pedro da Aldeia", "3305208" }; + rows[3672] = new[] { "RJ", "S\u00e3o Sebasti\u00e3o do Alto", "3305307" }; + rows[3673] = new[] { "RJ", "Sapucaia", "3305406" }; + rows[3674] = new[] { "RJ", "Saquarema", "3305505" }; + rows[3675] = new[] { "RJ", "Serop\u00e9dica", "3305554" }; + rows[3676] = new[] { "RJ", "Silva Jardim", "3305604" }; + rows[3677] = new[] { "RJ", "Sumidouro", "3305703" }; + rows[3678] = new[] { "RJ", "Tangu\u00e1", "3305752" }; + rows[3679] = new[] { "RJ", "Teres\u00f3polis", "3305802" }; + rows[3680] = new[] { "RJ", "Trajano de Moraes", "3305901" }; + rows[3681] = new[] { "RJ", "Tr\u00eas Rios", "3306008" }; + rows[3682] = new[] { "RJ", "Valen\u00e7a", "3306107" }; + rows[3683] = new[] { "RJ", "Varre-Sai", "3306156" }; + rows[3684] = new[] { "RJ", "Vassouras", "3306206" }; + rows[3685] = new[] { "RJ", "Volta Redonda", "3306305" }; + rows[3686] = new[] { "RN", "Acari", "2400109" }; + rows[3687] = new[] { "RN", "Afonso Bezerra", "2400307" }; + rows[3688] = new[] { "RN", "\u00c1gua Nova", "2400406" }; + rows[3689] = new[] { "RN", "Alexandria", "2400505" }; + rows[3690] = new[] { "RN", "Almino Afonso", "2400604" }; + rows[3691] = new[] { "RN", "Alto do Rodrigues", "2400703" }; + rows[3692] = new[] { "RN", "Angicos", "2400802" }; + rows[3693] = new[] { "RN", "Ant\u00f4nio Martins", "2400901" }; + rows[3694] = new[] { "RN", "Apodi", "2401008" }; + rows[3695] = new[] { "RN", "Areia Branca", "2401107" }; + rows[3696] = new[] { "RN", "Arez", "2401206" }; + rows[3697] = new[] { "RN", "Ass\u00fa", "2400208" }; + rows[3698] = new[] { "RN", "Ba\u00eda Formosa", "2401404" }; + rows[3699] = new[] { "RN", "Bara\u00fana", "2401453" }; + rows[3700] = new[] { "RN", "Barcelona", "2401503" }; + rows[3701] = new[] { "RN", "Bento Fernandes", "2401602" }; + rows[3702] = new[] { "RN", "Bod\u00f3", "2401651" }; + rows[3703] = new[] { "RN", "Bom Jesus", "2401701" }; + rows[3704] = new[] { "RN", "Brejinho", "2401800" }; + rows[3705] = new[] { "RN", "Cai\u00e7ara do Norte", "2401859" }; + rows[3706] = new[] { "RN", "Cai\u00e7ara do Rio do Vento", "2401909" }; + rows[3707] = new[] { "RN", "Caic\u00f3", "2402006" }; + rows[3708] = new[] { "RN", "Campo Grande", "2401305" }; + rows[3709] = new[] { "RN", "Campo Redondo", "2402105" }; + rows[3710] = new[] { "RN", "Canguaretama", "2402204" }; + rows[3711] = new[] { "RN", "Cara\u00fabas", "2402303" }; + rows[3712] = new[] { "RN", "Carna\u00faba dos Dantas", "2402402" }; + rows[3713] = new[] { "RN", "Carnaubais", "2402501" }; + rows[3714] = new[] { "RN", "Cear\u00e1-Mirim", "2402600" }; + rows[3715] = new[] { "RN", "Cerro Cor\u00e1", "2402709" }; + rows[3716] = new[] { "RN", "Coronel Ezequiel", "2402808" }; + rows[3717] = new[] { "RN", "Coronel Jo\u00e3o Pessoa", "2402907" }; + rows[3718] = new[] { "RN", "Cruzeta", "2403004" }; + rows[3719] = new[] { "RN", "Currais Novos", "2403103" }; + rows[3720] = new[] { "RN", "Doutor Severiano", "2403202" }; + rows[3721] = new[] { "RN", "Encanto", "2403301" }; + rows[3722] = new[] { "RN", "Equador", "2403400" }; + rows[3723] = new[] { "RN", "Esp\u00edrito Santo", "2403509" }; + rows[3724] = new[] { "RN", "Extremoz", "2403608" }; + rows[3725] = new[] { "RN", "Felipe Guerra", "2403707" }; + rows[3726] = new[] { "RN", "Fernando Pedroza", "2403756" }; + rows[3727] = new[] { "RN", "Flor\u00e2nia", "2403806" }; + rows[3728] = new[] { "RN", "Francisco Dantas", "2403905" }; + rows[3729] = new[] { "RN", "Frutuoso Gomes", "2404002" }; + rows[3730] = new[] { "RN", "Galinhos", "2404101" }; + rows[3731] = new[] { "RN", "Goianinha", "2404200" }; + rows[3732] = new[] { "RN", "Governador Dix-Sept Rosado", "2404309" }; + rows[3733] = new[] { "RN", "Grossos", "2404408" }; + rows[3734] = new[] { "RN", "Guamar\u00e9", "2404507" }; + rows[3735] = new[] { "RN", "Ielmo Marinho", "2404606" }; + rows[3736] = new[] { "RN", "Ipangua\u00e7u", "2404705" }; + rows[3737] = new[] { "RN", "Ipueira", "2404804" }; + rows[3738] = new[] { "RN", "Itaj\u00e1", "2404853" }; + rows[3739] = new[] { "RN", "Ita\u00fa", "2404903" }; + rows[3740] = new[] { "RN", "Ja\u00e7an\u00e3", "2405009" }; + rows[3741] = new[] { "RN", "Janda\u00edra", "2405108" }; + rows[3742] = new[] { "RN", "Jandu\u00eds", "2405207" }; + rows[3743] = new[] { "RN", "Janu\u00e1rio Cicco", "2405306" }; + rows[3744] = new[] { "RN", "Japi", "2405405" }; + rows[3745] = new[] { "RN", "Jardim de Angicos", "2405504" }; + rows[3746] = new[] { "RN", "Jardim de Piranhas", "2405603" }; + rows[3747] = new[] { "RN", "Jardim do Serid\u00f3", "2405702" }; + rows[3748] = new[] { "RN", "Jo\u00e3o C\u00e2mara", "2405801" }; + rows[3749] = new[] { "RN", "Jo\u00e3o Dias", "2405900" }; + rows[3750] = new[] { "RN", "Jos\u00e9 da Penha", "2406007" }; + rows[3751] = new[] { "RN", "Jucurutu", "2406106" }; + rows[3752] = new[] { "RN", "Jundi\u00e1", "2406155" }; + rows[3753] = new[] { "RN", "Lagoa d'Anta", "2406205" }; + rows[3754] = new[] { "RN", "Lagoa de Pedras", "2406304" }; + rows[3755] = new[] { "RN", "Lagoa de Velhos", "2406403" }; + rows[3756] = new[] { "RN", "Lagoa Nova", "2406502" }; + rows[3757] = new[] { "RN", "Lagoa Salgada", "2406601" }; + rows[3758] = new[] { "RN", "Lajes", "2406700" }; + rows[3759] = new[] { "RN", "Lajes Pintadas", "2406809" }; + rows[3760] = new[] { "RN", "Lucr\u00e9cia", "2406908" }; + rows[3761] = new[] { "RN", "Lu\u00eds Gomes", "2407005" }; + rows[3762] = new[] { "RN", "Maca\u00edba", "2407104" }; + rows[3763] = new[] { "RN", "Macau", "2407203" }; + rows[3764] = new[] { "RN", "Major Sales", "2407252" }; + rows[3765] = new[] { "RN", "Marcelino Vieira", "2407302" }; + rows[3766] = new[] { "RN", "Martins", "2407401" }; + rows[3767] = new[] { "RN", "Maxaranguape", "2407500" }; + rows[3768] = new[] { "RN", "Messias Targino", "2407609" }; + rows[3769] = new[] { "RN", "Montanhas", "2407708" }; + rows[3770] = new[] { "RN", "Monte Alegre", "2407807" }; + rows[3771] = new[] { "RN", "Monte das Gameleiras", "2407906" }; + rows[3772] = new[] { "RN", "Mossor\u00f3", "2408003" }; + rows[3773] = new[] { "RN", "Natal", "2408102" }; + rows[3774] = new[] { "RN", "N\u00edsia Floresta", "2408201" }; + rows[3775] = new[] { "RN", "Nova Cruz", "2408300" }; + rows[3776] = new[] { "RN", "Olho d'\u00c1gua do Borges", "2408409" }; + rows[3777] = new[] { "RN", "Ouro Branco", "2408508" }; + rows[3778] = new[] { "RN", "Paran\u00e1", "2408607" }; + rows[3779] = new[] { "RN", "Para\u00fa", "2408706" }; + rows[3780] = new[] { "RN", "Parazinho", "2408805" }; + rows[3781] = new[] { "RN", "Parelhas", "2408904" }; + rows[3782] = new[] { "RN", "Parnamirim", "2403251" }; + rows[3783] = new[] { "RN", "Passa e Fica", "2409100" }; + rows[3784] = new[] { "RN", "Passagem", "2409209" }; + rows[3785] = new[] { "RN", "Patu", "2409308" }; + rows[3786] = new[] { "RN", "Pau dos Ferros", "2409407" }; + rows[3787] = new[] { "RN", "Pedra Grande", "2409506" }; + rows[3788] = new[] { "RN", "Pedra Preta", "2409605" }; + rows[3789] = new[] { "RN", "Pedro Avelino", "2409704" }; + rows[3790] = new[] { "RN", "Pedro Velho", "2409803" }; + rows[3791] = new[] { "RN", "Pend\u00eancias", "2409902" }; + rows[3792] = new[] { "RN", "Pil\u00f5es", "2410009" }; + rows[3793] = new[] { "RN", "Po\u00e7o Branco", "2410108" }; + rows[3794] = new[] { "RN", "Portalegre", "2410207" }; + rows[3795] = new[] { "RN", "Porto do Mangue", "2410256" }; + rows[3796] = new[] { "RN", "Pureza", "2410405" }; + rows[3797] = new[] { "RN", "Rafael Fernandes", "2410504" }; + rows[3798] = new[] { "RN", "Rafael Godeiro", "2410603" }; + rows[3799] = new[] { "RN", "Riacho da Cruz", "2410702" }; + } + + private static void MunicipalitiesRows19(string[][] rows) + { + rows[3800] = new[] { "RN", "Riacho de Santana", "2410801" }; + rows[3801] = new[] { "RN", "Riachuelo", "2410900" }; + rows[3802] = new[] { "RN", "Rio do Fogo", "2408953" }; + rows[3803] = new[] { "RN", "Rodolfo Fernandes", "2411007" }; + rows[3804] = new[] { "RN", "Ruy Barbosa", "2411106" }; + rows[3805] = new[] { "RN", "Santa Cruz", "2411205" }; + rows[3806] = new[] { "RN", "Santa Maria", "2409332" }; + rows[3807] = new[] { "RN", "Santana do Matos", "2411403" }; + rows[3808] = new[] { "RN", "Santana do Serid\u00f3", "2411429" }; + rows[3809] = new[] { "RN", "Santo Ant\u00f4nio", "2411502" }; + rows[3810] = new[] { "RN", "S\u00e3o Bento do Norte", "2411601" }; + rows[3811] = new[] { "RN", "S\u00e3o Bento do Trair\u00ed", "2411700" }; + rows[3812] = new[] { "RN", "S\u00e3o Fernando", "2411809" }; + rows[3813] = new[] { "RN", "S\u00e3o Francisco do Oeste", "2411908" }; + rows[3814] = new[] { "RN", "S\u00e3o Gon\u00e7alo do Amarante", "2412005" }; + rows[3815] = new[] { "RN", "S\u00e3o Jo\u00e3o do Sabugi", "2412104" }; + rows[3816] = new[] { "RN", "S\u00e3o Jos\u00e9 de Mipibu", "2412203" }; + rows[3817] = new[] { "RN", "S\u00e3o Jos\u00e9 do Campestre", "2412302" }; + rows[3818] = new[] { "RN", "S\u00e3o Jos\u00e9 do Serid\u00f3", "2412401" }; + rows[3819] = new[] { "RN", "S\u00e3o Miguel", "2412500" }; + rows[3820] = new[] { "RN", "S\u00e3o Miguel do Gostoso", "2412559" }; + rows[3821] = new[] { "RN", "S\u00e3o Paulo do Potengi", "2412609" }; + rows[3822] = new[] { "RN", "S\u00e3o Pedro", "2412708" }; + rows[3823] = new[] { "RN", "S\u00e3o Rafael", "2412807" }; + rows[3824] = new[] { "RN", "S\u00e3o Tom\u00e9", "2412906" }; + rows[3825] = new[] { "RN", "S\u00e3o Vicente", "2413003" }; + rows[3826] = new[] { "RN", "Senador El\u00f3i de Souza", "2413102" }; + rows[3827] = new[] { "RN", "Senador Georgino Avelino", "2413201" }; + rows[3828] = new[] { "RN", "Serra Caiada", "2410306" }; + rows[3829] = new[] { "RN", "Serra de S\u00e3o Bento", "2413300" }; + rows[3830] = new[] { "RN", "Serra do Mel", "2413359" }; + rows[3831] = new[] { "RN", "Serra Negra do Norte", "2413409" }; + rows[3832] = new[] { "RN", "Serrinha", "2413508" }; + rows[3833] = new[] { "RN", "Serrinha dos Pintos", "2413557" }; + rows[3834] = new[] { "RN", "Severiano Melo", "2413607" }; + rows[3835] = new[] { "RN", "S\u00edtio Novo", "2413706" }; + rows[3836] = new[] { "RN", "Taboleiro Grande", "2413805" }; + rows[3837] = new[] { "RN", "Taipu", "2413904" }; + rows[3838] = new[] { "RN", "Tangar\u00e1", "2414001" }; + rows[3839] = new[] { "RN", "Tenente Ananias", "2414100" }; + rows[3840] = new[] { "RN", "Tenente Laurentino Cruz", "2414159" }; + rows[3841] = new[] { "RN", "Tibau", "2411056" }; + rows[3842] = new[] { "RN", "Tibau do Sul", "2414209" }; + rows[3843] = new[] { "RN", "Timba\u00faba dos Batistas", "2414308" }; + rows[3844] = new[] { "RN", "Touros", "2414407" }; + rows[3845] = new[] { "RN", "Triunfo Potiguar", "2414456" }; + rows[3846] = new[] { "RN", "Umarizal", "2414506" }; + rows[3847] = new[] { "RN", "Upanema", "2414605" }; + rows[3848] = new[] { "RN", "V\u00e1rzea", "2414704" }; + rows[3849] = new[] { "RN", "Venha-Ver", "2414753" }; + rows[3850] = new[] { "RN", "Vera Cruz", "2414803" }; + rows[3851] = new[] { "RN", "Vi\u00e7osa", "2414902" }; + rows[3852] = new[] { "RN", "Vila Flor", "2415008" }; + rows[3853] = new[] { "RS", "Acegu\u00e1", "4300034" }; + rows[3854] = new[] { "RS", "\u00c1gua Santa", "4300059" }; + rows[3855] = new[] { "RS", "Agudo", "4300109" }; + rows[3856] = new[] { "RS", "Ajuricaba", "4300208" }; + rows[3857] = new[] { "RS", "Alecrim", "4300307" }; + rows[3858] = new[] { "RS", "Alegrete", "4300406" }; + rows[3859] = new[] { "RS", "Alegria", "4300455" }; + rows[3860] = new[] { "RS", "Almirante Tamandar\u00e9 do Sul", "4300471" }; + rows[3861] = new[] { "RS", "Alpestre", "4300505" }; + rows[3862] = new[] { "RS", "Alto Alegre", "4300554" }; + rows[3863] = new[] { "RS", "Alto Feliz", "4300570" }; + rows[3864] = new[] { "RS", "Alvorada", "4300604" }; + rows[3865] = new[] { "RS", "Amaral Ferrador", "4300638" }; + rows[3866] = new[] { "RS", "Ametista do Sul", "4300646" }; + rows[3867] = new[] { "RS", "Andr\u00e9 da Rocha", "4300661" }; + rows[3868] = new[] { "RS", "Anta Gorda", "4300703" }; + rows[3869] = new[] { "RS", "Ant\u00f4nio Prado", "4300802" }; + rows[3870] = new[] { "RS", "Arambar\u00e9", "4300851" }; + rows[3871] = new[] { "RS", "Araric\u00e1", "4300877" }; + rows[3872] = new[] { "RS", "Aratiba", "4300901" }; + rows[3873] = new[] { "RS", "Arroio do Meio", "4301008" }; + rows[3874] = new[] { "RS", "Arroio do Padre", "4301073" }; + rows[3875] = new[] { "RS", "Arroio do Sal", "4301057" }; + rows[3876] = new[] { "RS", "Arroio do Tigre", "4301206" }; + rows[3877] = new[] { "RS", "Arroio dos Ratos", "4301107" }; + rows[3878] = new[] { "RS", "Arroio Grande", "4301305" }; + rows[3879] = new[] { "RS", "Arvorezinha", "4301404" }; + rows[3880] = new[] { "RS", "Augusto Pestana", "4301503" }; + rows[3881] = new[] { "RS", "\u00c1urea", "4301552" }; + rows[3882] = new[] { "RS", "Bag\u00e9", "4301602" }; + rows[3883] = new[] { "RS", "Balne\u00e1rio Pinhal", "4301636" }; + rows[3884] = new[] { "RS", "Bar\u00e3o", "4301651" }; + rows[3885] = new[] { "RS", "Bar\u00e3o de Cotegipe", "4301701" }; + rows[3886] = new[] { "RS", "Bar\u00e3o do Triunfo", "4301750" }; + rows[3887] = new[] { "RS", "Barra do Guarita", "4301859" }; + rows[3888] = new[] { "RS", "Barra do Quara\u00ed", "4301875" }; + rows[3889] = new[] { "RS", "Barra do Ribeiro", "4301909" }; + rows[3890] = new[] { "RS", "Barra do Rio Azul", "4301925" }; + rows[3891] = new[] { "RS", "Barra Funda", "4301958" }; + rows[3892] = new[] { "RS", "Barrac\u00e3o", "4301800" }; + rows[3893] = new[] { "RS", "Barros Cassal", "4302006" }; + rows[3894] = new[] { "RS", "Benjamin Constant do Sul", "4302055" }; + rows[3895] = new[] { "RS", "Bento Gon\u00e7alves", "4302105" }; + rows[3896] = new[] { "RS", "Boa Vista das Miss\u00f5es", "4302154" }; + rows[3897] = new[] { "RS", "Boa Vista do Buric\u00e1", "4302204" }; + rows[3898] = new[] { "RS", "Boa Vista do Cadeado", "4302220" }; + rows[3899] = new[] { "RS", "Boa Vista do Incra", "4302238" }; + rows[3900] = new[] { "RS", "Boa Vista do Sul", "4302253" }; + rows[3901] = new[] { "RS", "Bom Jesus", "4302303" }; + rows[3902] = new[] { "RS", "Bom Princ\u00edpio", "4302352" }; + rows[3903] = new[] { "RS", "Bom Progresso", "4302378" }; + rows[3904] = new[] { "RS", "Bom Retiro do Sul", "4302402" }; + rows[3905] = new[] { "RS", "Boqueir\u00e3o do Le\u00e3o", "4302451" }; + rows[3906] = new[] { "RS", "Bossoroca", "4302501" }; + rows[3907] = new[] { "RS", "Bozano", "4302584" }; + rows[3908] = new[] { "RS", "Braga", "4302600" }; + rows[3909] = new[] { "RS", "Brochier", "4302659" }; + rows[3910] = new[] { "RS", "Buti\u00e1", "4302709" }; + rows[3911] = new[] { "RS", "Ca\u00e7apava do Sul", "4302808" }; + rows[3912] = new[] { "RS", "Cacequi", "4302907" }; + rows[3913] = new[] { "RS", "Cachoeira do Sul", "4303004" }; + rows[3914] = new[] { "RS", "Cachoeirinha", "4303103" }; + rows[3915] = new[] { "RS", "Cacique Doble", "4303202" }; + rows[3916] = new[] { "RS", "Caibat\u00e9", "4303301" }; + rows[3917] = new[] { "RS", "Cai\u00e7ara", "4303400" }; + rows[3918] = new[] { "RS", "Camaqu\u00e3", "4303509" }; + rows[3919] = new[] { "RS", "Camargo", "4303558" }; + rows[3920] = new[] { "RS", "Cambar\u00e1 do Sul", "4303608" }; + rows[3921] = new[] { "RS", "Campestre da Serra", "4303673" }; + rows[3922] = new[] { "RS", "Campina das Miss\u00f5es", "4303707" }; + rows[3923] = new[] { "RS", "Campinas do Sul", "4303806" }; + rows[3924] = new[] { "RS", "Campo Bom", "4303905" }; + rows[3925] = new[] { "RS", "Campo Novo", "4304002" }; + rows[3926] = new[] { "RS", "Campos Borges", "4304101" }; + rows[3927] = new[] { "RS", "Candel\u00e1ria", "4304200" }; + rows[3928] = new[] { "RS", "C\u00e2ndido God\u00f3i", "4304309" }; + rows[3929] = new[] { "RS", "Candiota", "4304358" }; + rows[3930] = new[] { "RS", "Canela", "4304408" }; + rows[3931] = new[] { "RS", "Cangu\u00e7u", "4304507" }; + rows[3932] = new[] { "RS", "Canoas", "4304606" }; + rows[3933] = new[] { "RS", "Canudos do Vale", "4304614" }; + rows[3934] = new[] { "RS", "Cap\u00e3o Bonito do Sul", "4304622" }; + rows[3935] = new[] { "RS", "Cap\u00e3o da Canoa", "4304630" }; + rows[3936] = new[] { "RS", "Cap\u00e3o do Cip\u00f3", "4304655" }; + rows[3937] = new[] { "RS", "Cap\u00e3o do Le\u00e3o", "4304663" }; + rows[3938] = new[] { "RS", "Capela de Santana", "4304689" }; + rows[3939] = new[] { "RS", "Capit\u00e3o", "4304697" }; + rows[3940] = new[] { "RS", "Capivari do Sul", "4304671" }; + rows[3941] = new[] { "RS", "Cara\u00e1", "4304713" }; + rows[3942] = new[] { "RS", "Carazinho", "4304705" }; + rows[3943] = new[] { "RS", "Carlos Barbosa", "4304804" }; + rows[3944] = new[] { "RS", "Carlos Gomes", "4304853" }; + rows[3945] = new[] { "RS", "Casca", "4304903" }; + rows[3946] = new[] { "RS", "Caseiros", "4304952" }; + rows[3947] = new[] { "RS", "Catu\u00edpe", "4305009" }; + rows[3948] = new[] { "RS", "Caxias do Sul", "4305108" }; + rows[3949] = new[] { "RS", "Centen\u00e1rio", "4305116" }; + rows[3950] = new[] { "RS", "Cerrito", "4305124" }; + rows[3951] = new[] { "RS", "Cerro Branco", "4305132" }; + rows[3952] = new[] { "RS", "Cerro Grande", "4305157" }; + rows[3953] = new[] { "RS", "Cerro Grande do Sul", "4305173" }; + rows[3954] = new[] { "RS", "Cerro Largo", "4305207" }; + rows[3955] = new[] { "RS", "Chapada", "4305306" }; + rows[3956] = new[] { "RS", "Charqueadas", "4305355" }; + rows[3957] = new[] { "RS", "Charrua", "4305371" }; + rows[3958] = new[] { "RS", "Chiapetta", "4305405" }; + rows[3959] = new[] { "RS", "Chu\u00ed", "4305439" }; + rows[3960] = new[] { "RS", "Chuvisca", "4305447" }; + rows[3961] = new[] { "RS", "Cidreira", "4305454" }; + rows[3962] = new[] { "RS", "Cir\u00edaco", "4305504" }; + rows[3963] = new[] { "RS", "Colinas", "4305587" }; + rows[3964] = new[] { "RS", "Colorado", "4305603" }; + rows[3965] = new[] { "RS", "Condor", "4305702" }; + rows[3966] = new[] { "RS", "Constantina", "4305801" }; + rows[3967] = new[] { "RS", "Coqueiro Baixo", "4305835" }; + rows[3968] = new[] { "RS", "Coqueiros do Sul", "4305850" }; + rows[3969] = new[] { "RS", "Coronel Barros", "4305871" }; + rows[3970] = new[] { "RS", "Coronel Bicaco", "4305900" }; + rows[3971] = new[] { "RS", "Coronel Pilar", "4305934" }; + rows[3972] = new[] { "RS", "Cotipor\u00e3", "4305959" }; + rows[3973] = new[] { "RS", "Coxilha", "4305975" }; + rows[3974] = new[] { "RS", "Crissiumal", "4306007" }; + rows[3975] = new[] { "RS", "Cristal", "4306056" }; + rows[3976] = new[] { "RS", "Cristal do Sul", "4306072" }; + rows[3977] = new[] { "RS", "Cruz Alta", "4306106" }; + rows[3978] = new[] { "RS", "Cruzaltense", "4306130" }; + rows[3979] = new[] { "RS", "Cruzeiro do Sul", "4306205" }; + rows[3980] = new[] { "RS", "David Canabarro", "4306304" }; + rows[3981] = new[] { "RS", "Derrubadas", "4306320" }; + rows[3982] = new[] { "RS", "Dezesseis de Novembro", "4306353" }; + rows[3983] = new[] { "RS", "Dilermando de Aguiar", "4306379" }; + rows[3984] = new[] { "RS", "Dois Irm\u00e3os", "4306403" }; + rows[3985] = new[] { "RS", "Dois Irm\u00e3os das Miss\u00f5es", "4306429" }; + rows[3986] = new[] { "RS", "Dois Lajeados", "4306452" }; + rows[3987] = new[] { "RS", "Dom Feliciano", "4306502" }; + rows[3988] = new[] { "RS", "Dom Pedrito", "4306601" }; + rows[3989] = new[] { "RS", "Dom Pedro de Alc\u00e2ntara", "4306551" }; + rows[3990] = new[] { "RS", "Dona Francisca", "4306700" }; + rows[3991] = new[] { "RS", "Doutor Maur\u00edcio Cardoso", "4306734" }; + rows[3992] = new[] { "RS", "Doutor Ricardo", "4306759" }; + rows[3993] = new[] { "RS", "Eldorado do Sul", "4306767" }; + rows[3994] = new[] { "RS", "Encantado", "4306809" }; + rows[3995] = new[] { "RS", "Encruzilhada do Sul", "4306908" }; + rows[3996] = new[] { "RS", "Engenho Velho", "4306924" }; + rows[3997] = new[] { "RS", "Entre Rios do Sul", "4306957" }; + rows[3998] = new[] { "RS", "Entre-Iju\u00eds", "4306932" }; + rows[3999] = new[] { "RS", "Erebango", "4306973" }; + } + + private static void MunicipalitiesRows20(string[][] rows) + { + rows[4000] = new[] { "RS", "Erechim", "4307005" }; + rows[4001] = new[] { "RS", "Ernestina", "4307054" }; + rows[4002] = new[] { "RS", "Erval Grande", "4307203" }; + rows[4003] = new[] { "RS", "Erval Seco", "4307302" }; + rows[4004] = new[] { "RS", "Esmeralda", "4307401" }; + rows[4005] = new[] { "RS", "Esperan\u00e7a do Sul", "4307450" }; + rows[4006] = new[] { "RS", "Espumoso", "4307500" }; + rows[4007] = new[] { "RS", "Esta\u00e7\u00e3o", "4307559" }; + rows[4008] = new[] { "RS", "Est\u00e2ncia Velha", "4307609" }; + rows[4009] = new[] { "RS", "Esteio", "4307708" }; + rows[4010] = new[] { "RS", "Estrela", "4307807" }; + rows[4011] = new[] { "RS", "Estrela Velha", "4307815" }; + rows[4012] = new[] { "RS", "Eug\u00eanio de Castro", "4307831" }; + rows[4013] = new[] { "RS", "Fagundes Varela", "4307864" }; + rows[4014] = new[] { "RS", "Farroupilha", "4307906" }; + rows[4015] = new[] { "RS", "Faxinal do Soturno", "4308003" }; + rows[4016] = new[] { "RS", "Faxinalzinho", "4308052" }; + rows[4017] = new[] { "RS", "Fazenda Vilanova", "4308078" }; + rows[4018] = new[] { "RS", "Feliz", "4308102" }; + rows[4019] = new[] { "RS", "Flores da Cunha", "4308201" }; + rows[4020] = new[] { "RS", "Floriano Peixoto", "4308250" }; + rows[4021] = new[] { "RS", "Fontoura Xavier", "4308300" }; + rows[4022] = new[] { "RS", "Formigueiro", "4308409" }; + rows[4023] = new[] { "RS", "Forquetinha", "4308433" }; + rows[4024] = new[] { "RS", "Fortaleza dos Valos", "4308458" }; + rows[4025] = new[] { "RS", "Frederico Westphalen", "4308508" }; + rows[4026] = new[] { "RS", "Garibaldi", "4308607" }; + rows[4027] = new[] { "RS", "Garruchos", "4308656" }; + rows[4028] = new[] { "RS", "Gaurama", "4308706" }; + rows[4029] = new[] { "RS", "General C\u00e2mara", "4308805" }; + rows[4030] = new[] { "RS", "Gentil", "4308854" }; + rows[4031] = new[] { "RS", "Get\u00falio Vargas", "4308904" }; + rows[4032] = new[] { "RS", "Giru\u00e1", "4309001" }; + rows[4033] = new[] { "RS", "Glorinha", "4309050" }; + rows[4034] = new[] { "RS", "Gramado", "4309100" }; + rows[4035] = new[] { "RS", "Gramado dos Loureiros", "4309126" }; + rows[4036] = new[] { "RS", "Gramado Xavier", "4309159" }; + rows[4037] = new[] { "RS", "Gravata\u00ed", "4309209" }; + rows[4038] = new[] { "RS", "Guabiju", "4309258" }; + rows[4039] = new[] { "RS", "Gua\u00edba", "4309308" }; + rows[4040] = new[] { "RS", "Guapor\u00e9", "4309407" }; + rows[4041] = new[] { "RS", "Guarani das Miss\u00f5es", "4309506" }; + rows[4042] = new[] { "RS", "Harmonia", "4309555" }; + rows[4043] = new[] { "RS", "Herval", "4307104" }; + rows[4044] = new[] { "RS", "Herveiras", "4309571" }; + rows[4045] = new[] { "RS", "Horizontina", "4309605" }; + rows[4046] = new[] { "RS", "Hulha Negra", "4309654" }; + rows[4047] = new[] { "RS", "Humait\u00e1", "4309704" }; + rows[4048] = new[] { "RS", "Ibarama", "4309753" }; + rows[4049] = new[] { "RS", "Ibia\u00e7\u00e1", "4309803" }; + rows[4050] = new[] { "RS", "Ibiraiaras", "4309902" }; + rows[4051] = new[] { "RS", "Ibirapuit\u00e3", "4309951" }; + rows[4052] = new[] { "RS", "Ibirub\u00e1", "4310009" }; + rows[4053] = new[] { "RS", "Igrejinha", "4310108" }; + rows[4054] = new[] { "RS", "Iju\u00ed", "4310207" }; + rows[4055] = new[] { "RS", "Il\u00f3polis", "4310306" }; + rows[4056] = new[] { "RS", "Imb\u00e9", "4310330" }; + rows[4057] = new[] { "RS", "Imigrante", "4310363" }; + rows[4058] = new[] { "RS", "Independ\u00eancia", "4310405" }; + rows[4059] = new[] { "RS", "Inhacor\u00e1", "4310413" }; + rows[4060] = new[] { "RS", "Ip\u00ea", "4310439" }; + rows[4061] = new[] { "RS", "Ipiranga do Sul", "4310462" }; + rows[4062] = new[] { "RS", "Ira\u00ed", "4310504" }; + rows[4063] = new[] { "RS", "Itaara", "4310538" }; + rows[4064] = new[] { "RS", "Itacurubi", "4310553" }; + rows[4065] = new[] { "RS", "Itapuca", "4310579" }; + rows[4066] = new[] { "RS", "Itaqui", "4310603" }; + rows[4067] = new[] { "RS", "Itati", "4310652" }; + rows[4068] = new[] { "RS", "Itatiba do Sul", "4310702" }; + rows[4069] = new[] { "RS", "Ivor\u00e1", "4310751" }; + rows[4070] = new[] { "RS", "Ivoti", "4310801" }; + rows[4071] = new[] { "RS", "Jaboticaba", "4310850" }; + rows[4072] = new[] { "RS", "Jacuizinho", "4310876" }; + rows[4073] = new[] { "RS", "Jacutinga", "4310900" }; + rows[4074] = new[] { "RS", "Jaguar\u00e3o", "4311007" }; + rows[4075] = new[] { "RS", "Jaguari", "4311106" }; + rows[4076] = new[] { "RS", "Jaquirana", "4311122" }; + rows[4077] = new[] { "RS", "Jari", "4311130" }; + rows[4078] = new[] { "RS", "J\u00f3ia", "4311155" }; + rows[4079] = new[] { "RS", "J\u00falio de Castilhos", "4311205" }; + rows[4080] = new[] { "RS", "Lagoa Bonita do Sul", "4311239" }; + rows[4081] = new[] { "RS", "Lagoa dos Tr\u00eas Cantos", "4311270" }; + rows[4082] = new[] { "RS", "Lagoa Vermelha", "4311304" }; + rows[4083] = new[] { "RS", "Lago\u00e3o", "4311254" }; + rows[4084] = new[] { "RS", "Lajeado", "4311403" }; + rows[4085] = new[] { "RS", "Lajeado do Bugre", "4311429" }; + rows[4086] = new[] { "RS", "Lavras do Sul", "4311502" }; + rows[4087] = new[] { "RS", "Liberato Salzano", "4311601" }; + rows[4088] = new[] { "RS", "Lindolfo Collor", "4311627" }; + rows[4089] = new[] { "RS", "Linha Nova", "4311643" }; + rows[4090] = new[] { "RS", "Ma\u00e7ambar\u00e1", "4311718" }; + rows[4091] = new[] { "RS", "Machadinho", "4311700" }; + rows[4092] = new[] { "RS", "Mampituba", "4311734" }; + rows[4093] = new[] { "RS", "Manoel Viana", "4311759" }; + rows[4094] = new[] { "RS", "Maquin\u00e9", "4311775" }; + rows[4095] = new[] { "RS", "Marat\u00e1", "4311791" }; + rows[4096] = new[] { "RS", "Marau", "4311809" }; + rows[4097] = new[] { "RS", "Marcelino Ramos", "4311908" }; + rows[4098] = new[] { "RS", "Mariana Pimentel", "4311981" }; + rows[4099] = new[] { "RS", "Mariano Moro", "4312005" }; + rows[4100] = new[] { "RS", "Marques de Souza", "4312054" }; + rows[4101] = new[] { "RS", "Mata", "4312104" }; + rows[4102] = new[] { "RS", "Mato Castelhano", "4312138" }; + rows[4103] = new[] { "RS", "Mato Leit\u00e3o", "4312153" }; + rows[4104] = new[] { "RS", "Mato Queimado", "4312179" }; + rows[4105] = new[] { "RS", "Maximiliano de Almeida", "4312203" }; + rows[4106] = new[] { "RS", "Minas do Le\u00e3o", "4312252" }; + rows[4107] = new[] { "RS", "Miragua\u00ed", "4312302" }; + rows[4108] = new[] { "RS", "Montauri", "4312351" }; + rows[4109] = new[] { "RS", "Monte Alegre dos Campos", "4312377" }; + rows[4110] = new[] { "RS", "Monte Belo do Sul", "4312385" }; + rows[4111] = new[] { "RS", "Montenegro", "4312401" }; + rows[4112] = new[] { "RS", "Morma\u00e7o", "4312427" }; + rows[4113] = new[] { "RS", "Morrinhos do Sul", "4312443" }; + rows[4114] = new[] { "RS", "Morro Redondo", "4312450" }; + rows[4115] = new[] { "RS", "Morro Reuter", "4312476" }; + rows[4116] = new[] { "RS", "Mostardas", "4312500" }; + rows[4117] = new[] { "RS", "Mu\u00e7um", "4312609" }; + rows[4118] = new[] { "RS", "Muitos Cap\u00f5es", "4312617" }; + rows[4119] = new[] { "RS", "Muliterno", "4312625" }; + rows[4120] = new[] { "RS", "N\u00e3o-Me-Toque", "4312658" }; + rows[4121] = new[] { "RS", "Nicolau Vergueiro", "4312674" }; + rows[4122] = new[] { "RS", "Nonoai", "4312708" }; + rows[4123] = new[] { "RS", "Nova Alvorada", "4312757" }; + rows[4124] = new[] { "RS", "Nova Ara\u00e7\u00e1", "4312807" }; + rows[4125] = new[] { "RS", "Nova Bassano", "4312906" }; + rows[4126] = new[] { "RS", "Nova Boa Vista", "4312955" }; + rows[4127] = new[] { "RS", "Nova Br\u00e9scia", "4313003" }; + rows[4128] = new[] { "RS", "Nova Candel\u00e1ria", "4313011" }; + rows[4129] = new[] { "RS", "Nova Esperan\u00e7a do Sul", "4313037" }; + rows[4130] = new[] { "RS", "Nova Hartz", "4313060" }; + rows[4131] = new[] { "RS", "Nova P\u00e1dua", "4313086" }; + rows[4132] = new[] { "RS", "Nova Palma", "4313102" }; + rows[4133] = new[] { "RS", "Nova Petr\u00f3polis", "4313201" }; + rows[4134] = new[] { "RS", "Nova Prata", "4313300" }; + rows[4135] = new[] { "RS", "Nova Ramada", "4313334" }; + rows[4136] = new[] { "RS", "Nova Roma do Sul", "4313359" }; + rows[4137] = new[] { "RS", "Nova Santa Rita", "4313375" }; + rows[4138] = new[] { "RS", "Novo Barreiro", "4313490" }; + rows[4139] = new[] { "RS", "Novo Cabrais", "4313391" }; + rows[4140] = new[] { "RS", "Novo Hamburgo", "4313409" }; + rows[4141] = new[] { "RS", "Novo Machado", "4313425" }; + rows[4142] = new[] { "RS", "Novo Tiradentes", "4313441" }; + rows[4143] = new[] { "RS", "Novo Xingu", "4313466" }; + rows[4144] = new[] { "RS", "Os\u00f3rio", "4313508" }; + rows[4145] = new[] { "RS", "Paim Filho", "4313607" }; + rows[4146] = new[] { "RS", "Palmares do Sul", "4313656" }; + rows[4147] = new[] { "RS", "Palmeira das Miss\u00f5es", "4313706" }; + rows[4148] = new[] { "RS", "Palmitinho", "4313805" }; + rows[4149] = new[] { "RS", "Panambi", "4313904" }; + rows[4150] = new[] { "RS", "Pantano Grande", "4313953" }; + rows[4151] = new[] { "RS", "Para\u00ed", "4314001" }; + rows[4152] = new[] { "RS", "Para\u00edso do Sul", "4314027" }; + rows[4153] = new[] { "RS", "Pareci Novo", "4314035" }; + rows[4154] = new[] { "RS", "Parob\u00e9", "4314050" }; + rows[4155] = new[] { "RS", "Passa Sete", "4314068" }; + rows[4156] = new[] { "RS", "Passo do Sobrado", "4314076" }; + rows[4157] = new[] { "RS", "Passo Fundo", "4314100" }; + rows[4158] = new[] { "RS", "Paulo Bento", "4314134" }; + rows[4159] = new[] { "RS", "Paverama", "4314159" }; + rows[4160] = new[] { "RS", "Pedras Altas", "4314175" }; + rows[4161] = new[] { "RS", "Pedro Os\u00f3rio", "4314209" }; + rows[4162] = new[] { "RS", "Peju\u00e7ara", "4314308" }; + rows[4163] = new[] { "RS", "Pelotas", "4314407" }; + rows[4164] = new[] { "RS", "Picada Caf\u00e9", "4314423" }; + rows[4165] = new[] { "RS", "Pinhal", "4314456" }; + rows[4166] = new[] { "RS", "Pinhal da Serra", "4314464" }; + rows[4167] = new[] { "RS", "Pinhal Grande", "4314472" }; + rows[4168] = new[] { "RS", "Pinheirinho do Vale", "4314498" }; + rows[4169] = new[] { "RS", "Pinheiro Machado", "4314506" }; + rows[4170] = new[] { "RS", "Pinto Bandeira", "4314548" }; + rows[4171] = new[] { "RS", "Pirap\u00f3", "4314555" }; + rows[4172] = new[] { "RS", "Piratini", "4314605" }; + rows[4173] = new[] { "RS", "Planalto", "4314704" }; + rows[4174] = new[] { "RS", "Po\u00e7o das Antas", "4314753" }; + rows[4175] = new[] { "RS", "Pont\u00e3o", "4314779" }; + rows[4176] = new[] { "RS", "Ponte Preta", "4314787" }; + rows[4177] = new[] { "RS", "Port\u00e3o", "4314803" }; + rows[4178] = new[] { "RS", "Porto Alegre", "4314902" }; + rows[4179] = new[] { "RS", "Porto Lucena", "4315008" }; + rows[4180] = new[] { "RS", "Porto Mau\u00e1", "4315057" }; + rows[4181] = new[] { "RS", "Porto Vera Cruz", "4315073" }; + rows[4182] = new[] { "RS", "Porto Xavier", "4315107" }; + rows[4183] = new[] { "RS", "Pouso Novo", "4315131" }; + rows[4184] = new[] { "RS", "Presidente Lucena", "4315149" }; + rows[4185] = new[] { "RS", "Progresso", "4315156" }; + rows[4186] = new[] { "RS", "Prot\u00e1sio Alves", "4315172" }; + rows[4187] = new[] { "RS", "Putinga", "4315206" }; + rows[4188] = new[] { "RS", "Quara\u00ed", "4315305" }; + rows[4189] = new[] { "RS", "Quatro Irm\u00e3os", "4315313" }; + rows[4190] = new[] { "RS", "Quevedos", "4315321" }; + rows[4191] = new[] { "RS", "Quinze de Novembro", "4315354" }; + rows[4192] = new[] { "RS", "Redentora", "4315404" }; + rows[4193] = new[] { "RS", "Relvado", "4315453" }; + rows[4194] = new[] { "RS", "Restinga S\u00eaca", "4315503" }; + rows[4195] = new[] { "RS", "Rio dos \u00cdndios", "4315552" }; + rows[4196] = new[] { "RS", "Rio Grande", "4315602" }; + rows[4197] = new[] { "RS", "Rio Pardo", "4315701" }; + rows[4198] = new[] { "RS", "Riozinho", "4315750" }; + rows[4199] = new[] { "RS", "Roca Sales", "4315800" }; + } + + private static void MunicipalitiesRows21(string[][] rows) + { + rows[4200] = new[] { "RS", "Rodeio Bonito", "4315909" }; + rows[4201] = new[] { "RS", "Rolador", "4315958" }; + rows[4202] = new[] { "RS", "Rolante", "4316006" }; + rows[4203] = new[] { "RS", "Ronda Alta", "4316105" }; + rows[4204] = new[] { "RS", "Rondinha", "4316204" }; + rows[4205] = new[] { "RS", "Roque Gonzales", "4316303" }; + rows[4206] = new[] { "RS", "Ros\u00e1rio do Sul", "4316402" }; + rows[4207] = new[] { "RS", "Sagrada Fam\u00edlia", "4316428" }; + rows[4208] = new[] { "RS", "Saldanha Marinho", "4316436" }; + rows[4209] = new[] { "RS", "Salto do Jacu\u00ed", "4316451" }; + rows[4210] = new[] { "RS", "Salvador das Miss\u00f5es", "4316477" }; + rows[4211] = new[] { "RS", "Salvador do Sul", "4316501" }; + rows[4212] = new[] { "RS", "Sananduva", "4316600" }; + rows[4213] = new[] { "RS", "Sant'Ana do Livramento", "4317103" }; + rows[4214] = new[] { "RS", "Santa B\u00e1rbara do Sul", "4316709" }; + rows[4215] = new[] { "RS", "Santa Cec\u00edlia do Sul", "4316733" }; + rows[4216] = new[] { "RS", "Santa Clara do Sul", "4316758" }; + rows[4217] = new[] { "RS", "Santa Cruz do Sul", "4316808" }; + rows[4218] = new[] { "RS", "Santa Margarida do Sul", "4316972" }; + rows[4219] = new[] { "RS", "Santa Maria", "4316907" }; + rows[4220] = new[] { "RS", "Santa Maria do Herval", "4316956" }; + rows[4221] = new[] { "RS", "Santa Rosa", "4317202" }; + rows[4222] = new[] { "RS", "Santa Tereza", "4317251" }; + rows[4223] = new[] { "RS", "Santa Vit\u00f3ria do Palmar", "4317301" }; + rows[4224] = new[] { "RS", "Santana da Boa Vista", "4317004" }; + rows[4225] = new[] { "RS", "Santiago", "4317400" }; + rows[4226] = new[] { "RS", "Santo \u00c2ngelo", "4317509" }; + rows[4227] = new[] { "RS", "Santo Ant\u00f4nio da Patrulha", "4317608" }; + rows[4228] = new[] { "RS", "Santo Ant\u00f4nio das Miss\u00f5es", "4317707" }; + rows[4229] = new[] { "RS", "Santo Ant\u00f4nio do Palma", "4317558" }; + rows[4230] = new[] { "RS", "Santo Ant\u00f4nio do Planalto", "4317756" }; + rows[4231] = new[] { "RS", "Santo Augusto", "4317806" }; + rows[4232] = new[] { "RS", "Santo Cristo", "4317905" }; + rows[4233] = new[] { "RS", "Santo Expedito do Sul", "4317954" }; + rows[4234] = new[] { "RS", "S\u00e3o Borja", "4318002" }; + rows[4235] = new[] { "RS", "S\u00e3o Domingos do Sul", "4318051" }; + rows[4236] = new[] { "RS", "S\u00e3o Francisco de Assis", "4318101" }; + rows[4237] = new[] { "RS", "S\u00e3o Francisco de Paula", "4318200" }; + rows[4238] = new[] { "RS", "S\u00e3o Gabriel", "4318309" }; + rows[4239] = new[] { "RS", "S\u00e3o Jer\u00f4nimo", "4318408" }; + rows[4240] = new[] { "RS", "S\u00e3o Jo\u00e3o da Urtiga", "4318424" }; + rows[4241] = new[] { "RS", "S\u00e3o Jo\u00e3o do Pol\u00easine", "4318432" }; + rows[4242] = new[] { "RS", "S\u00e3o Jorge", "4318440" }; + rows[4243] = new[] { "RS", "S\u00e3o Jos\u00e9 das Miss\u00f5es", "4318457" }; + rows[4244] = new[] { "RS", "S\u00e3o Jos\u00e9 do Herval", "4318465" }; + rows[4245] = new[] { "RS", "S\u00e3o Jos\u00e9 do Hort\u00eancio", "4318481" }; + rows[4246] = new[] { "RS", "S\u00e3o Jos\u00e9 do Inhacor\u00e1", "4318499" }; + rows[4247] = new[] { "RS", "S\u00e3o Jos\u00e9 do Norte", "4318507" }; + rows[4248] = new[] { "RS", "S\u00e3o Jos\u00e9 do Ouro", "4318606" }; + rows[4249] = new[] { "RS", "S\u00e3o Jos\u00e9 do Sul", "4318614" }; + rows[4250] = new[] { "RS", "S\u00e3o Jos\u00e9 dos Ausentes", "4318622" }; + rows[4251] = new[] { "RS", "S\u00e3o Leopoldo", "4318705" }; + rows[4252] = new[] { "RS", "S\u00e3o Louren\u00e7o do Sul", "4318804" }; + rows[4253] = new[] { "RS", "S\u00e3o Luiz Gonzaga", "4318903" }; + rows[4254] = new[] { "RS", "S\u00e3o Marcos", "4319000" }; + rows[4255] = new[] { "RS", "S\u00e3o Martinho", "4319109" }; + rows[4256] = new[] { "RS", "S\u00e3o Martinho da Serra", "4319125" }; + rows[4257] = new[] { "RS", "S\u00e3o Miguel das Miss\u00f5es", "4319158" }; + rows[4258] = new[] { "RS", "S\u00e3o Nicolau", "4319208" }; + rows[4259] = new[] { "RS", "S\u00e3o Paulo das Miss\u00f5es", "4319307" }; + rows[4260] = new[] { "RS", "S\u00e3o Pedro da Serra", "4319356" }; + rows[4261] = new[] { "RS", "S\u00e3o Pedro das Miss\u00f5es", "4319364" }; + rows[4262] = new[] { "RS", "S\u00e3o Pedro do Buti\u00e1", "4319372" }; + rows[4263] = new[] { "RS", "S\u00e3o Pedro do Sul", "4319406" }; + rows[4264] = new[] { "RS", "S\u00e3o Sebasti\u00e3o do Ca\u00ed", "4319505" }; + rows[4265] = new[] { "RS", "S\u00e3o Sep\u00e9", "4319604" }; + rows[4266] = new[] { "RS", "S\u00e3o Valentim", "4319703" }; + rows[4267] = new[] { "RS", "S\u00e3o Valentim do Sul", "4319711" }; + rows[4268] = new[] { "RS", "S\u00e3o Val\u00e9rio do Sul", "4319737" }; + rows[4269] = new[] { "RS", "S\u00e3o Vendelino", "4319752" }; + rows[4270] = new[] { "RS", "S\u00e3o Vicente do Sul", "4319802" }; + rows[4271] = new[] { "RS", "Sapiranga", "4319901" }; + rows[4272] = new[] { "RS", "Sapucaia do Sul", "4320008" }; + rows[4273] = new[] { "RS", "Sarandi", "4320107" }; + rows[4274] = new[] { "RS", "Seberi", "4320206" }; + rows[4275] = new[] { "RS", "Sede Nova", "4320230" }; + rows[4276] = new[] { "RS", "Segredo", "4320263" }; + rows[4277] = new[] { "RS", "Selbach", "4320305" }; + rows[4278] = new[] { "RS", "Senador Salgado Filho", "4320321" }; + rows[4279] = new[] { "RS", "Sentinela do Sul", "4320354" }; + rows[4280] = new[] { "RS", "Serafina Corr\u00eaa", "4320404" }; + rows[4281] = new[] { "RS", "S\u00e9rio", "4320453" }; + rows[4282] = new[] { "RS", "Sert\u00e3o", "4320503" }; + rows[4283] = new[] { "RS", "Sert\u00e3o Santana", "4320552" }; + rows[4284] = new[] { "RS", "Sete de Setembro", "4320578" }; + rows[4285] = new[] { "RS", "Severiano de Almeida", "4320602" }; + rows[4286] = new[] { "RS", "Silveira Martins", "4320651" }; + rows[4287] = new[] { "RS", "Sinimbu", "4320677" }; + rows[4288] = new[] { "RS", "Sobradinho", "4320701" }; + rows[4289] = new[] { "RS", "Soledade", "4320800" }; + rows[4290] = new[] { "RS", "Taba\u00ed", "4320859" }; + rows[4291] = new[] { "RS", "Tapejara", "4320909" }; + rows[4292] = new[] { "RS", "Tapera", "4321006" }; + rows[4293] = new[] { "RS", "Tapes", "4321105" }; + rows[4294] = new[] { "RS", "Taquara", "4321204" }; + rows[4295] = new[] { "RS", "Taquari", "4321303" }; + rows[4296] = new[] { "RS", "Taquaru\u00e7u do Sul", "4321329" }; + rows[4297] = new[] { "RS", "Tavares", "4321352" }; + rows[4298] = new[] { "RS", "Tenente Portela", "4321402" }; + rows[4299] = new[] { "RS", "Terra de Areia", "4321436" }; + rows[4300] = new[] { "RS", "Teut\u00f4nia", "4321451" }; + rows[4301] = new[] { "RS", "Tio Hugo", "4321469" }; + rows[4302] = new[] { "RS", "Tiradentes do Sul", "4321477" }; + rows[4303] = new[] { "RS", "Toropi", "4321493" }; + rows[4304] = new[] { "RS", "Torres", "4321501" }; + rows[4305] = new[] { "RS", "Tramanda\u00ed", "4321600" }; + rows[4306] = new[] { "RS", "Travesseiro", "4321626" }; + rows[4307] = new[] { "RS", "Tr\u00eas Arroios", "4321634" }; + rows[4308] = new[] { "RS", "Tr\u00eas Cachoeiras", "4321667" }; + rows[4309] = new[] { "RS", "Tr\u00eas Coroas", "4321709" }; + rows[4310] = new[] { "RS", "Tr\u00eas de Maio", "4321808" }; + rows[4311] = new[] { "RS", "Tr\u00eas Forquilhas", "4321832" }; + rows[4312] = new[] { "RS", "Tr\u00eas Palmeiras", "4321857" }; + rows[4313] = new[] { "RS", "Tr\u00eas Passos", "4321907" }; + rows[4314] = new[] { "RS", "Trindade do Sul", "4321956" }; + rows[4315] = new[] { "RS", "Triunfo", "4322004" }; + rows[4316] = new[] { "RS", "Tucunduva", "4322103" }; + rows[4317] = new[] { "RS", "Tunas", "4322152" }; + rows[4318] = new[] { "RS", "Tupanci do Sul", "4322186" }; + rows[4319] = new[] { "RS", "Tupanciret\u00e3", "4322202" }; + rows[4320] = new[] { "RS", "Tupandi", "4322251" }; + rows[4321] = new[] { "RS", "Tuparendi", "4322301" }; + rows[4322] = new[] { "RS", "Turu\u00e7u", "4322327" }; + rows[4323] = new[] { "RS", "Ubiretama", "4322343" }; + rows[4324] = new[] { "RS", "Uni\u00e3o da Serra", "4322350" }; + rows[4325] = new[] { "RS", "Unistalda", "4322376" }; + rows[4326] = new[] { "RS", "Uruguaiana", "4322400" }; + rows[4327] = new[] { "RS", "Vacaria", "4322509" }; + rows[4328] = new[] { "RS", "Vale do Sol", "4322533" }; + rows[4329] = new[] { "RS", "Vale Real", "4322541" }; + rows[4330] = new[] { "RS", "Vale Verde", "4322525" }; + rows[4331] = new[] { "RS", "Vanini", "4322558" }; + rows[4332] = new[] { "RS", "Ven\u00e2ncio Aires", "4322608" }; + rows[4333] = new[] { "RS", "Vera Cruz", "4322707" }; + rows[4334] = new[] { "RS", "Veran\u00f3polis", "4322806" }; + rows[4335] = new[] { "RS", "Vespasiano Corr\u00eaa", "4322855" }; + rows[4336] = new[] { "RS", "Viadutos", "4322905" }; + rows[4337] = new[] { "RS", "Viam\u00e3o", "4323002" }; + rows[4338] = new[] { "RS", "Vicente Dutra", "4323101" }; + rows[4339] = new[] { "RS", "Victor Graeff", "4323200" }; + rows[4340] = new[] { "RS", "Vila Flores", "4323309" }; + rows[4341] = new[] { "RS", "Vila L\u00e2ngaro", "4323358" }; + rows[4342] = new[] { "RS", "Vila Maria", "4323408" }; + rows[4343] = new[] { "RS", "Vila Nova do Sul", "4323457" }; + rows[4344] = new[] { "RS", "Vista Alegre", "4323507" }; + rows[4345] = new[] { "RS", "Vista Alegre do Prata", "4323606" }; + rows[4346] = new[] { "RS", "Vista Ga\u00facha", "4323705" }; + rows[4347] = new[] { "RS", "Vit\u00f3ria das Miss\u00f5es", "4323754" }; + rows[4348] = new[] { "RS", "Westf\u00e1lia", "4323770" }; + rows[4349] = new[] { "RS", "Xangri-l\u00e1", "4323804" }; + rows[4350] = new[] { "RO", "Alta Floresta D'Oeste", "1100015" }; + rows[4351] = new[] { "RO", "Alto Alegre dos Parecis", "1100379" }; + rows[4352] = new[] { "RO", "Alto Para\u00edso", "1100403" }; + rows[4353] = new[] { "RO", "Alvorada D'Oeste", "1100346" }; + rows[4354] = new[] { "RO", "Ariquemes", "1100023" }; + rows[4355] = new[] { "RO", "Buritis", "1100452" }; + rows[4356] = new[] { "RO", "Cabixi", "1100031" }; + rows[4357] = new[] { "RO", "Cacaul\u00e2ndia", "1100601" }; + rows[4358] = new[] { "RO", "Cacoal", "1100049" }; + rows[4359] = new[] { "RO", "Campo Novo de Rond\u00f4nia", "1100700" }; + rows[4360] = new[] { "RO", "Candeias do Jamari", "1100809" }; + rows[4361] = new[] { "RO", "Castanheiras", "1100908" }; + rows[4362] = new[] { "RO", "Cerejeiras", "1100056" }; + rows[4363] = new[] { "RO", "Chupinguaia", "1100924" }; + rows[4364] = new[] { "RO", "Colorado do Oeste", "1100064" }; + rows[4365] = new[] { "RO", "Corumbiara", "1100072" }; + rows[4366] = new[] { "RO", "Costa Marques", "1100080" }; + rows[4367] = new[] { "RO", "Cujubim", "1100940" }; + rows[4368] = new[] { "RO", "Espig\u00e3o D'Oeste", "1100098" }; + rows[4369] = new[] { "RO", "Governador Jorge Teixeira", "1101005" }; + rows[4370] = new[] { "RO", "Guajar\u00e1-Mirim", "1100106" }; + rows[4371] = new[] { "RO", "Itapu\u00e3 do Oeste", "1101104" }; + rows[4372] = new[] { "RO", "Jaru", "1100114" }; + rows[4373] = new[] { "RO", "Ji-Paran\u00e1", "1100122" }; + rows[4374] = new[] { "RO", "Machadinho D'Oeste", "1100130" }; + rows[4375] = new[] { "RO", "Ministro Andreazza", "1101203" }; + rows[4376] = new[] { "RO", "Mirante da Serra", "1101302" }; + rows[4377] = new[] { "RO", "Monte Negro", "1101401" }; + rows[4378] = new[] { "RO", "Nova Brasil\u00e2ndia D'Oeste", "1100148" }; + rows[4379] = new[] { "RO", "Nova Mamor\u00e9", "1100338" }; + rows[4380] = new[] { "RO", "Nova Uni\u00e3o", "1101435" }; + rows[4381] = new[] { "RO", "Novo Horizonte do Oeste", "1100502" }; + rows[4382] = new[] { "RO", "Ouro Preto do Oeste", "1100155" }; + rows[4383] = new[] { "RO", "Parecis", "1101450" }; + rows[4384] = new[] { "RO", "Pimenta Bueno", "1100189" }; + rows[4385] = new[] { "RO", "Pimenteiras do Oeste", "1101468" }; + rows[4386] = new[] { "RO", "Porto Velho", "1100205" }; + rows[4387] = new[] { "RO", "Presidente M\u00e9dici", "1100254" }; + rows[4388] = new[] { "RO", "Primavera de Rond\u00f4nia", "1101476" }; + rows[4389] = new[] { "RO", "Rio Crespo", "1100262" }; + rows[4390] = new[] { "RO", "Rolim de Moura", "1100288" }; + rows[4391] = new[] { "RO", "Santa Luzia D'Oeste", "1100296" }; + rows[4392] = new[] { "RO", "S\u00e3o Felipe D'Oeste", "1101484" }; + rows[4393] = new[] { "RO", "S\u00e3o Francisco do Guapor\u00e9", "1101492" }; + rows[4394] = new[] { "RO", "S\u00e3o Miguel do Guapor\u00e9", "1100320" }; + rows[4395] = new[] { "RO", "Seringueiras", "1101500" }; + rows[4396] = new[] { "RO", "Teixeir\u00f3polis", "1101559" }; + rows[4397] = new[] { "RO", "Theobroma", "1101609" }; + rows[4398] = new[] { "RO", "Urup\u00e1", "1101708" }; + rows[4399] = new[] { "RO", "Vale do Anari", "1101757" }; + } + + private static void MunicipalitiesRows22(string[][] rows) + { + rows[4400] = new[] { "RO", "Vale do Para\u00edso", "1101807" }; + rows[4401] = new[] { "RO", "Vilhena", "1100304" }; + rows[4402] = new[] { "RR", "Alto Alegre", "1400050" }; + rows[4403] = new[] { "RR", "Amajari", "1400027" }; + rows[4404] = new[] { "RR", "Boa Vista", "1400100" }; + rows[4405] = new[] { "RR", "Bonfim", "1400159" }; + rows[4406] = new[] { "RR", "Cant\u00e1", "1400175" }; + rows[4407] = new[] { "RR", "Caracara\u00ed", "1400209" }; + rows[4408] = new[] { "RR", "Caroebe", "1400233" }; + rows[4409] = new[] { "RR", "Iracema", "1400282" }; + rows[4410] = new[] { "RR", "Mucaja\u00ed", "1400308" }; + rows[4411] = new[] { "RR", "Normandia", "1400407" }; + rows[4412] = new[] { "RR", "Pacaraima", "1400456" }; + rows[4413] = new[] { "RR", "Rorain\u00f3polis", "1400472" }; + rows[4414] = new[] { "RR", "S\u00e3o Jo\u00e3o da Baliza", "1400506" }; + rows[4415] = new[] { "RR", "S\u00e3o Luiz do Anau\u00e1", "1400605" }; + rows[4416] = new[] { "RR", "Uiramut\u00e3", "1400704" }; + rows[4417] = new[] { "SC", "Abdon Batista", "4200051" }; + rows[4418] = new[] { "SC", "Abelardo Luz", "4200101" }; + rows[4419] = new[] { "SC", "Agrol\u00e2ndia", "4200200" }; + rows[4420] = new[] { "SC", "Agron\u00f4mica", "4200309" }; + rows[4421] = new[] { "SC", "\u00c1gua Doce", "4200408" }; + rows[4422] = new[] { "SC", "\u00c1guas de Chapec\u00f3", "4200507" }; + rows[4423] = new[] { "SC", "\u00c1guas Frias", "4200556" }; + rows[4424] = new[] { "SC", "\u00c1guas Mornas", "4200606" }; + rows[4425] = new[] { "SC", "Alfredo Wagner", "4200705" }; + rows[4426] = new[] { "SC", "Alto Bela Vista", "4200754" }; + rows[4427] = new[] { "SC", "Anchieta", "4200804" }; + rows[4428] = new[] { "SC", "Angelina", "4200903" }; + rows[4429] = new[] { "SC", "Anita Garibaldi", "4201000" }; + rows[4430] = new[] { "SC", "Anit\u00e1polis", "4201109" }; + rows[4431] = new[] { "SC", "Ant\u00f4nio Carlos", "4201208" }; + rows[4432] = new[] { "SC", "Api\u00fana", "4201257" }; + rows[4433] = new[] { "SC", "Arabut\u00e3", "4201273" }; + rows[4434] = new[] { "SC", "Araquari", "4201307" }; + rows[4435] = new[] { "SC", "Ararangu\u00e1", "4201406" }; + rows[4436] = new[] { "SC", "Armaz\u00e9m", "4201505" }; + rows[4437] = new[] { "SC", "Arroio Trinta", "4201604" }; + rows[4438] = new[] { "SC", "Arvoredo", "4201653" }; + rows[4439] = new[] { "SC", "Ascurra", "4201703" }; + rows[4440] = new[] { "SC", "Atalanta", "4201802" }; + rows[4441] = new[] { "SC", "Aurora", "4201901" }; + rows[4442] = new[] { "SC", "Balne\u00e1rio Arroio do Silva", "4201950" }; + rows[4443] = new[] { "SC", "Balne\u00e1rio Barra do Sul", "4202057" }; + rows[4444] = new[] { "SC", "Balne\u00e1rio Cambori\u00fa", "4202008" }; + rows[4445] = new[] { "SC", "Balne\u00e1rio Gaivota", "4202073" }; + rows[4446] = new[] { "SC", "Balne\u00e1rio Pi\u00e7arras", "4212809" }; + rows[4447] = new[] { "SC", "Balne\u00e1rio Rinc\u00e3o", "4220000" }; + rows[4448] = new[] { "SC", "Bandeirante", "4202081" }; + rows[4449] = new[] { "SC", "Barra Bonita", "4202099" }; + rows[4450] = new[] { "SC", "Barra Velha", "4202107" }; + rows[4451] = new[] { "SC", "Bela Vista do Toldo", "4202131" }; + rows[4452] = new[] { "SC", "Belmonte", "4202156" }; + rows[4453] = new[] { "SC", "Benedito Novo", "4202206" }; + rows[4454] = new[] { "SC", "Bigua\u00e7u", "4202305" }; + rows[4455] = new[] { "SC", "Blumenau", "4202404" }; + rows[4456] = new[] { "SC", "Bocaina do Sul", "4202438" }; + rows[4457] = new[] { "SC", "Bom Jardim da Serra", "4202503" }; + rows[4458] = new[] { "SC", "Bom Jesus", "4202537" }; + rows[4459] = new[] { "SC", "Bom Jesus do Oeste", "4202578" }; + rows[4460] = new[] { "SC", "Bom Retiro", "4202602" }; + rows[4461] = new[] { "SC", "Bombinhas", "4202453" }; + rows[4462] = new[] { "SC", "Botuver\u00e1", "4202701" }; + rows[4463] = new[] { "SC", "Bra\u00e7o do Norte", "4202800" }; + rows[4464] = new[] { "SC", "Bra\u00e7o do Trombudo", "4202859" }; + rows[4465] = new[] { "SC", "Brun\u00f3polis", "4202875" }; + rows[4466] = new[] { "SC", "Brusque", "4202909" }; + rows[4467] = new[] { "SC", "Ca\u00e7ador", "4203006" }; + rows[4468] = new[] { "SC", "Caibi", "4203105" }; + rows[4469] = new[] { "SC", "Calmon", "4203154" }; + rows[4470] = new[] { "SC", "Cambori\u00fa", "4203204" }; + rows[4471] = new[] { "SC", "Campo Alegre", "4203303" }; + rows[4472] = new[] { "SC", "Campo Belo do Sul", "4203402" }; + rows[4473] = new[] { "SC", "Campo Er\u00ea", "4203501" }; + rows[4474] = new[] { "SC", "Campos Novos", "4203600" }; + rows[4475] = new[] { "SC", "Canelinha", "4203709" }; + rows[4476] = new[] { "SC", "Canoinhas", "4203808" }; + rows[4477] = new[] { "SC", "Cap\u00e3o Alto", "4203253" }; + rows[4478] = new[] { "SC", "Capinzal", "4203907" }; + rows[4479] = new[] { "SC", "Capivari de Baixo", "4203956" }; + rows[4480] = new[] { "SC", "Catanduvas", "4204004" }; + rows[4481] = new[] { "SC", "Caxambu do Sul", "4204103" }; + rows[4482] = new[] { "SC", "Celso Ramos", "4204152" }; + rows[4483] = new[] { "SC", "Cerro Negro", "4204178" }; + rows[4484] = new[] { "SC", "Chapad\u00e3o do Lageado", "4204194" }; + rows[4485] = new[] { "SC", "Chapec\u00f3", "4204202" }; + rows[4486] = new[] { "SC", "Cocal do Sul", "4204251" }; + rows[4487] = new[] { "SC", "Conc\u00f3rdia", "4204301" }; + rows[4488] = new[] { "SC", "Cordilheira Alta", "4204350" }; + rows[4489] = new[] { "SC", "Coronel Freitas", "4204400" }; + rows[4490] = new[] { "SC", "Coronel Martins", "4204459" }; + rows[4491] = new[] { "SC", "Correia Pinto", "4204558" }; + rows[4492] = new[] { "SC", "Corup\u00e1", "4204509" }; + rows[4493] = new[] { "SC", "Crici\u00fama", "4204608" }; + rows[4494] = new[] { "SC", "Cunha Por\u00e3", "4204707" }; + rows[4495] = new[] { "SC", "Cunhata\u00ed", "4204756" }; + rows[4496] = new[] { "SC", "Curitibanos", "4204806" }; + rows[4497] = new[] { "SC", "Descanso", "4204905" }; + rows[4498] = new[] { "SC", "Dion\u00edsio Cerqueira", "4205001" }; + rows[4499] = new[] { "SC", "Dona Emma", "4205100" }; + rows[4500] = new[] { "SC", "Doutor Pedrinho", "4205159" }; + rows[4501] = new[] { "SC", "Entre Rios", "4205175" }; + rows[4502] = new[] { "SC", "Ermo", "4205191" }; + rows[4503] = new[] { "SC", "Erval Velho", "4205209" }; + rows[4504] = new[] { "SC", "Faxinal dos Guedes", "4205308" }; + rows[4505] = new[] { "SC", "Flor do Sert\u00e3o", "4205357" }; + rows[4506] = new[] { "SC", "Florian\u00f3polis", "4205407" }; + rows[4507] = new[] { "SC", "Formosa do Sul", "4205431" }; + rows[4508] = new[] { "SC", "Forquilhinha", "4205456" }; + rows[4509] = new[] { "SC", "Fraiburgo", "4205506" }; + rows[4510] = new[] { "SC", "Frei Rog\u00e9rio", "4205555" }; + rows[4511] = new[] { "SC", "Galv\u00e3o", "4205605" }; + rows[4512] = new[] { "SC", "Garopaba", "4205704" }; + rows[4513] = new[] { "SC", "Garuva", "4205803" }; + rows[4514] = new[] { "SC", "Gaspar", "4205902" }; + rows[4515] = new[] { "SC", "Governador Celso Ramos", "4206009" }; + rows[4516] = new[] { "SC", "Gr\u00e3o-Par\u00e1", "4206108" }; + rows[4517] = new[] { "SC", "Gravatal", "4206207" }; + rows[4518] = new[] { "SC", "Guabiruba", "4206306" }; + rows[4519] = new[] { "SC", "Guaraciaba", "4206405" }; + rows[4520] = new[] { "SC", "Guaramirim", "4206504" }; + rows[4521] = new[] { "SC", "Guaruj\u00e1 do Sul", "4206603" }; + rows[4522] = new[] { "SC", "Guatamb\u00fa", "4206652" }; + rows[4523] = new[] { "SC", "Herval d'Oeste", "4206702" }; + rows[4524] = new[] { "SC", "Ibiam", "4206751" }; + rows[4525] = new[] { "SC", "Ibicar\u00e9", "4206801" }; + rows[4526] = new[] { "SC", "Ibirama", "4206900" }; + rows[4527] = new[] { "SC", "I\u00e7ara", "4207007" }; + rows[4528] = new[] { "SC", "Ilhota", "4207106" }; + rows[4529] = new[] { "SC", "Imaru\u00ed", "4207205" }; + rows[4530] = new[] { "SC", "Imbituba", "4207304" }; + rows[4531] = new[] { "SC", "Imbuia", "4207403" }; + rows[4532] = new[] { "SC", "Indaial", "4207502" }; + rows[4533] = new[] { "SC", "Iomer\u00ea", "4207577" }; + rows[4534] = new[] { "SC", "Ipira", "4207601" }; + rows[4535] = new[] { "SC", "Ipor\u00e3 do Oeste", "4207650" }; + rows[4536] = new[] { "SC", "Ipua\u00e7u", "4207684" }; + rows[4537] = new[] { "SC", "Ipumirim", "4207700" }; + rows[4538] = new[] { "SC", "Iraceminha", "4207759" }; + rows[4539] = new[] { "SC", "Irani", "4207809" }; + rows[4540] = new[] { "SC", "Irati", "4207858" }; + rows[4541] = new[] { "SC", "Irine\u00f3polis", "4207908" }; + rows[4542] = new[] { "SC", "It\u00e1", "4208005" }; + rows[4543] = new[] { "SC", "Itai\u00f3polis", "4208104" }; + rows[4544] = new[] { "SC", "Itaja\u00ed", "4208203" }; + rows[4545] = new[] { "SC", "Itapema", "4208302" }; + rows[4546] = new[] { "SC", "Itapiranga", "4208401" }; + rows[4547] = new[] { "SC", "Itapo\u00e1", "4208450" }; + rows[4548] = new[] { "SC", "Ituporanga", "4208500" }; + rows[4549] = new[] { "SC", "Jabor\u00e1", "4208609" }; + rows[4550] = new[] { "SC", "Jacinto Machado", "4208708" }; + rows[4551] = new[] { "SC", "Jaguaruna", "4208807" }; + rows[4552] = new[] { "SC", "Jaragu\u00e1 do Sul", "4208906" }; + rows[4553] = new[] { "SC", "Jardin\u00f3polis", "4208955" }; + rows[4554] = new[] { "SC", "Joa\u00e7aba", "4209003" }; + rows[4555] = new[] { "SC", "Joinville", "4209102" }; + rows[4556] = new[] { "SC", "Jos\u00e9 Boiteux", "4209151" }; + rows[4557] = new[] { "SC", "Jupi\u00e1", "4209177" }; + rows[4558] = new[] { "SC", "Lacerd\u00f3polis", "4209201" }; + rows[4559] = new[] { "SC", "Lages", "4209300" }; + rows[4560] = new[] { "SC", "Laguna", "4209409" }; + rows[4561] = new[] { "SC", "Lajeado Grande", "4209458" }; + rows[4562] = new[] { "SC", "Laurentino", "4209508" }; + rows[4563] = new[] { "SC", "Lauro M\u00fcller", "4209607" }; + rows[4564] = new[] { "SC", "Lebon R\u00e9gis", "4209706" }; + rows[4565] = new[] { "SC", "Leoberto Leal", "4209805" }; + rows[4566] = new[] { "SC", "Lind\u00f3ia do Sul", "4209854" }; + rows[4567] = new[] { "SC", "Lontras", "4209904" }; + rows[4568] = new[] { "SC", "Luiz Alves", "4210001" }; + rows[4569] = new[] { "SC", "Luzerna", "4210035" }; + rows[4570] = new[] { "SC", "Macieira", "4210050" }; + rows[4571] = new[] { "SC", "Mafra", "4210100" }; + rows[4572] = new[] { "SC", "Major Gercino", "4210209" }; + rows[4573] = new[] { "SC", "Major Vieira", "4210308" }; + rows[4574] = new[] { "SC", "Maracaj\u00e1", "4210407" }; + rows[4575] = new[] { "SC", "Maravilha", "4210506" }; + rows[4576] = new[] { "SC", "Marema", "4210555" }; + rows[4577] = new[] { "SC", "Massaranduba", "4210605" }; + rows[4578] = new[] { "SC", "Matos Costa", "4210704" }; + rows[4579] = new[] { "SC", "Meleiro", "4210803" }; + rows[4580] = new[] { "SC", "Mirim Doce", "4210852" }; + rows[4581] = new[] { "SC", "Modelo", "4210902" }; + rows[4582] = new[] { "SC", "Monda\u00ed", "4211009" }; + rows[4583] = new[] { "SC", "Monte Carlo", "4211058" }; + rows[4584] = new[] { "SC", "Monte Castelo", "4211108" }; + rows[4585] = new[] { "SC", "Morro da Fuma\u00e7a", "4211207" }; + rows[4586] = new[] { "SC", "Morro Grande", "4211256" }; + rows[4587] = new[] { "SC", "Navegantes", "4211306" }; + rows[4588] = new[] { "SC", "Nova Erechim", "4211405" }; + rows[4589] = new[] { "SC", "Nova Itaberaba", "4211454" }; + rows[4590] = new[] { "SC", "Nova Trento", "4211504" }; + rows[4591] = new[] { "SC", "Nova Veneza", "4211603" }; + rows[4592] = new[] { "SC", "Novo Horizonte", "4211652" }; + rows[4593] = new[] { "SC", "Orleans", "4211702" }; + rows[4594] = new[] { "SC", "Otac\u00edlio Costa", "4211751" }; + rows[4595] = new[] { "SC", "Ouro", "4211801" }; + rows[4596] = new[] { "SC", "Ouro Verde", "4211850" }; + rows[4597] = new[] { "SC", "Paial", "4211876" }; + rows[4598] = new[] { "SC", "Painel", "4211892" }; + rows[4599] = new[] { "SC", "Palho\u00e7a", "4211900" }; + } + + private static void MunicipalitiesRows23(string[][] rows) + { + rows[4600] = new[] { "SC", "Palma Sola", "4212007" }; + rows[4601] = new[] { "SC", "Palmeira", "4212056" }; + rows[4602] = new[] { "SC", "Palmitos", "4212106" }; + rows[4603] = new[] { "SC", "Papanduva", "4212205" }; + rows[4604] = new[] { "SC", "Para\u00edso", "4212239" }; + rows[4605] = new[] { "SC", "Passo de Torres", "4212254" }; + rows[4606] = new[] { "SC", "Passos Maia", "4212270" }; + rows[4607] = new[] { "SC", "Paulo Lopes", "4212304" }; + rows[4608] = new[] { "SC", "Pedras Grandes", "4212403" }; + rows[4609] = new[] { "SC", "Penha", "4212502" }; + rows[4610] = new[] { "SC", "Peritiba", "4212601" }; + rows[4611] = new[] { "SC", "Pescaria Brava", "4212650" }; + rows[4612] = new[] { "SC", "Petrol\u00e2ndia", "4212700" }; + rows[4613] = new[] { "SC", "Pinhalzinho", "4212908" }; + rows[4614] = new[] { "SC", "Pinheiro Preto", "4213005" }; + rows[4615] = new[] { "SC", "Piratuba", "4213104" }; + rows[4616] = new[] { "SC", "Planalto Alegre", "4213153" }; + rows[4617] = new[] { "SC", "Pomerode", "4213203" }; + rows[4618] = new[] { "SC", "Ponte Alta", "4213302" }; + rows[4619] = new[] { "SC", "Ponte Alta do Norte", "4213351" }; + rows[4620] = new[] { "SC", "Ponte Serrada", "4213401" }; + rows[4621] = new[] { "SC", "Porto Belo", "4213500" }; + rows[4622] = new[] { "SC", "Porto Uni\u00e3o", "4213609" }; + rows[4623] = new[] { "SC", "Pouso Redondo", "4213708" }; + rows[4624] = new[] { "SC", "Praia Grande", "4213807" }; + rows[4625] = new[] { "SC", "Presidente Castello Branco", "4213906" }; + rows[4626] = new[] { "SC", "Presidente Get\u00falio", "4214003" }; + rows[4627] = new[] { "SC", "Presidente Nereu", "4214102" }; + rows[4628] = new[] { "SC", "Princesa", "4214151" }; + rows[4629] = new[] { "SC", "Quilombo", "4214201" }; + rows[4630] = new[] { "SC", "Rancho Queimado", "4214300" }; + rows[4631] = new[] { "SC", "Rio das Antas", "4214409" }; + rows[4632] = new[] { "SC", "Rio do Campo", "4214508" }; + rows[4633] = new[] { "SC", "Rio do Oeste", "4214607" }; + rows[4634] = new[] { "SC", "Rio do Sul", "4214805" }; + rows[4635] = new[] { "SC", "Rio dos Cedros", "4214706" }; + rows[4636] = new[] { "SC", "Rio Fortuna", "4214904" }; + rows[4637] = new[] { "SC", "Rio Negrinho", "4215000" }; + rows[4638] = new[] { "SC", "Rio Rufino", "4215059" }; + rows[4639] = new[] { "SC", "Riqueza", "4215075" }; + rows[4640] = new[] { "SC", "Rodeio", "4215109" }; + rows[4641] = new[] { "SC", "Romel\u00e2ndia", "4215208" }; + rows[4642] = new[] { "SC", "Salete", "4215307" }; + rows[4643] = new[] { "SC", "Saltinho", "4215356" }; + rows[4644] = new[] { "SC", "Salto Veloso", "4215406" }; + rows[4645] = new[] { "SC", "Sang\u00e3o", "4215455" }; + rows[4646] = new[] { "SC", "Santa Cec\u00edlia", "4215505" }; + rows[4647] = new[] { "SC", "Santa Helena", "4215554" }; + rows[4648] = new[] { "SC", "Santa Rosa de Lima", "4215604" }; + rows[4649] = new[] { "SC", "Santa Rosa do Sul", "4215653" }; + rows[4650] = new[] { "SC", "Santa Terezinha", "4215679" }; + rows[4651] = new[] { "SC", "Santa Terezinha do Progresso", "4215687" }; + rows[4652] = new[] { "SC", "Santiago do Sul", "4215695" }; + rows[4653] = new[] { "SC", "Santo Amaro da Imperatriz", "4215703" }; + rows[4654] = new[] { "SC", "S\u00e3o Bento do Sul", "4215802" }; + rows[4655] = new[] { "SC", "S\u00e3o Bernardino", "4215752" }; + rows[4656] = new[] { "SC", "S\u00e3o Bonif\u00e1cio", "4215901" }; + rows[4657] = new[] { "SC", "S\u00e3o Carlos", "4216008" }; + rows[4658] = new[] { "SC", "S\u00e3o Crist\u00f3v\u00e3o do Sul", "4216057" }; + rows[4659] = new[] { "SC", "S\u00e3o Domingos", "4216107" }; + rows[4660] = new[] { "SC", "S\u00e3o Francisco do Sul", "4216206" }; + rows[4661] = new[] { "SC", "S\u00e3o Jo\u00e3o Batista", "4216305" }; + rows[4662] = new[] { "SC", "S\u00e3o Jo\u00e3o do Itaperi\u00fa", "4216354" }; + rows[4663] = new[] { "SC", "S\u00e3o Jo\u00e3o do Oeste", "4216255" }; + rows[4664] = new[] { "SC", "S\u00e3o Jo\u00e3o do Sul", "4216404" }; + rows[4665] = new[] { "SC", "S\u00e3o Joaquim", "4216503" }; + rows[4666] = new[] { "SC", "S\u00e3o Jos\u00e9", "4216602" }; + rows[4667] = new[] { "SC", "S\u00e3o Jos\u00e9 do Cedro", "4216701" }; + rows[4668] = new[] { "SC", "S\u00e3o Jos\u00e9 do Cerrito", "4216800" }; + rows[4669] = new[] { "SC", "S\u00e3o Louren\u00e7o do Oeste", "4216909" }; + rows[4670] = new[] { "SC", "S\u00e3o Ludgero", "4217006" }; + rows[4671] = new[] { "SC", "S\u00e3o Martinho", "4217105" }; + rows[4672] = new[] { "SC", "S\u00e3o Miguel da Boa Vista", "4217154" }; + rows[4673] = new[] { "SC", "S\u00e3o Miguel do Oeste", "4217204" }; + rows[4674] = new[] { "SC", "S\u00e3o Pedro de Alc\u00e2ntara", "4217253" }; + rows[4675] = new[] { "SC", "Saudades", "4217303" }; + rows[4676] = new[] { "SC", "Schroeder", "4217402" }; + rows[4677] = new[] { "SC", "Seara", "4217501" }; + rows[4678] = new[] { "SC", "Serra Alta", "4217550" }; + rows[4679] = new[] { "SC", "Sider\u00f3polis", "4217600" }; + rows[4680] = new[] { "SC", "Sombrio", "4217709" }; + rows[4681] = new[] { "SC", "Sul Brasil", "4217758" }; + rows[4682] = new[] { "SC", "Tai\u00f3", "4217808" }; + rows[4683] = new[] { "SC", "Tangar\u00e1", "4217907" }; + rows[4684] = new[] { "SC", "Tigrinhos", "4217956" }; + rows[4685] = new[] { "SC", "Tijucas", "4218004" }; + rows[4686] = new[] { "SC", "Timb\u00e9 do Sul", "4218103" }; + rows[4687] = new[] { "SC", "Timb\u00f3", "4218202" }; + rows[4688] = new[] { "SC", "Timb\u00f3 Grande", "4218251" }; + rows[4689] = new[] { "SC", "Tr\u00eas Barras", "4218301" }; + rows[4690] = new[] { "SC", "Treviso", "4218350" }; + rows[4691] = new[] { "SC", "Treze de Maio", "4218400" }; + rows[4692] = new[] { "SC", "Treze T\u00edlias", "4218509" }; + rows[4693] = new[] { "SC", "Trombudo Central", "4218608" }; + rows[4694] = new[] { "SC", "Tubar\u00e3o", "4218707" }; + rows[4695] = new[] { "SC", "Tun\u00e1polis", "4218756" }; + rows[4696] = new[] { "SC", "Turvo", "4218806" }; + rows[4697] = new[] { "SC", "Uni\u00e3o do Oeste", "4218855" }; + rows[4698] = new[] { "SC", "Urubici", "4218905" }; + rows[4699] = new[] { "SC", "Urupema", "4218954" }; + rows[4700] = new[] { "SC", "Urussanga", "4219002" }; + rows[4701] = new[] { "SC", "Varge\u00e3o", "4219101" }; + rows[4702] = new[] { "SC", "Vargem", "4219150" }; + rows[4703] = new[] { "SC", "Vargem Bonita", "4219176" }; + rows[4704] = new[] { "SC", "Vidal Ramos", "4219200" }; + rows[4705] = new[] { "SC", "Videira", "4219309" }; + rows[4706] = new[] { "SC", "Vitor Meireles", "4219358" }; + rows[4707] = new[] { "SC", "Witmarsum", "4219408" }; + rows[4708] = new[] { "SC", "Xanxer\u00ea", "4219507" }; + rows[4709] = new[] { "SC", "Xavantina", "4219606" }; + rows[4710] = new[] { "SC", "Xaxim", "4219705" }; + rows[4711] = new[] { "SC", "Zort\u00e9a", "4219853" }; + rows[4712] = new[] { "SP", "Adamantina", "3500105" }; + rows[4713] = new[] { "SP", "Adolfo", "3500204" }; + rows[4714] = new[] { "SP", "Agua\u00ed", "3500303" }; + rows[4715] = new[] { "SP", "\u00c1guas da Prata", "3500402" }; + rows[4716] = new[] { "SP", "\u00c1guas de Lind\u00f3ia", "3500501" }; + rows[4717] = new[] { "SP", "\u00c1guas de Santa B\u00e1rbara", "3500550" }; + rows[4718] = new[] { "SP", "\u00c1guas de S\u00e3o Pedro", "3500600" }; + rows[4719] = new[] { "SP", "Agudos", "3500709" }; + rows[4720] = new[] { "SP", "Alambari", "3500758" }; + rows[4721] = new[] { "SP", "Alfredo Marcondes", "3500808" }; + rows[4722] = new[] { "SP", "Altair", "3500907" }; + rows[4723] = new[] { "SP", "Altin\u00f3polis", "3501004" }; + rows[4724] = new[] { "SP", "Alto Alegre", "3501103" }; + rows[4725] = new[] { "SP", "Alum\u00ednio", "3501152" }; + rows[4726] = new[] { "SP", "\u00c1lvares Florence", "3501202" }; + rows[4727] = new[] { "SP", "\u00c1lvares Machado", "3501301" }; + rows[4728] = new[] { "SP", "\u00c1lvaro de Carvalho", "3501400" }; + rows[4729] = new[] { "SP", "Alvinl\u00e2ndia", "3501509" }; + rows[4730] = new[] { "SP", "Americana", "3501608" }; + rows[4731] = new[] { "SP", "Am\u00e9rico Brasiliense", "3501707" }; + rows[4732] = new[] { "SP", "Am\u00e9rico de Campos", "3501806" }; + rows[4733] = new[] { "SP", "Amparo", "3501905" }; + rows[4734] = new[] { "SP", "Anal\u00e2ndia", "3502002" }; + rows[4735] = new[] { "SP", "Andradina", "3502101" }; + rows[4736] = new[] { "SP", "Angatuba", "3502200" }; + rows[4737] = new[] { "SP", "Anhembi", "3502309" }; + rows[4738] = new[] { "SP", "Anhumas", "3502408" }; + rows[4739] = new[] { "SP", "Aparecida", "3502507" }; + rows[4740] = new[] { "SP", "Aparecida d'Oeste", "3502606" }; + rows[4741] = new[] { "SP", "Apia\u00ed", "3502705" }; + rows[4742] = new[] { "SP", "Ara\u00e7ariguama", "3502754" }; + rows[4743] = new[] { "SP", "Ara\u00e7atuba", "3502804" }; + rows[4744] = new[] { "SP", "Ara\u00e7oiaba da Serra", "3502903" }; + rows[4745] = new[] { "SP", "Aramina", "3503000" }; + rows[4746] = new[] { "SP", "Arandu", "3503109" }; + rows[4747] = new[] { "SP", "Arape\u00ed", "3503158" }; + rows[4748] = new[] { "SP", "Araraquara", "3503208" }; + rows[4749] = new[] { "SP", "Araras", "3503307" }; + rows[4750] = new[] { "SP", "Arco-\u00cdris", "3503356" }; + rows[4751] = new[] { "SP", "Arealva", "3503406" }; + rows[4752] = new[] { "SP", "Areias", "3503505" }; + rows[4753] = new[] { "SP", "Arei\u00f3polis", "3503604" }; + rows[4754] = new[] { "SP", "Ariranha", "3503703" }; + rows[4755] = new[] { "SP", "Artur Nogueira", "3503802" }; + rows[4756] = new[] { "SP", "Aruj\u00e1", "3503901" }; + rows[4757] = new[] { "SP", "Asp\u00e1sia", "3503950" }; + rows[4758] = new[] { "SP", "Assis", "3504008" }; + rows[4759] = new[] { "SP", "Atibaia", "3504107" }; + rows[4760] = new[] { "SP", "Auriflama", "3504206" }; + rows[4761] = new[] { "SP", "Ava\u00ed", "3504305" }; + rows[4762] = new[] { "SP", "Avanhandava", "3504404" }; + rows[4763] = new[] { "SP", "Avar\u00e9", "3504503" }; + rows[4764] = new[] { "SP", "Bady Bassitt", "3504602" }; + rows[4765] = new[] { "SP", "Balbinos", "3504701" }; + rows[4766] = new[] { "SP", "B\u00e1lsamo", "3504800" }; + rows[4767] = new[] { "SP", "Bananal", "3504909" }; + rows[4768] = new[] { "SP", "Bar\u00e3o de Antonina", "3505005" }; + rows[4769] = new[] { "SP", "Barbosa", "3505104" }; + rows[4770] = new[] { "SP", "Bariri", "3505203" }; + rows[4771] = new[] { "SP", "Barra Bonita", "3505302" }; + rows[4772] = new[] { "SP", "Barra do Chap\u00e9u", "3505351" }; + rows[4773] = new[] { "SP", "Barra do Turvo", "3505401" }; + rows[4774] = new[] { "SP", "Barretos", "3505500" }; + rows[4775] = new[] { "SP", "Barrinha", "3505609" }; + rows[4776] = new[] { "SP", "Barueri", "3505708" }; + rows[4777] = new[] { "SP", "Bastos", "3505807" }; + rows[4778] = new[] { "SP", "Batatais", "3505906" }; + rows[4779] = new[] { "SP", "Bauru", "3506003" }; + rows[4780] = new[] { "SP", "Bebedouro", "3506102" }; + rows[4781] = new[] { "SP", "Bento de Abreu", "3506201" }; + rows[4782] = new[] { "SP", "Bernardino de Campos", "3506300" }; + rows[4783] = new[] { "SP", "Bertioga", "3506359" }; + rows[4784] = new[] { "SP", "Bilac", "3506409" }; + rows[4785] = new[] { "SP", "Birigui", "3506508" }; + rows[4786] = new[] { "SP", "Biritiba Mirim", "3506607" }; + rows[4787] = new[] { "SP", "Boa Esperan\u00e7a do Sul", "3506706" }; + rows[4788] = new[] { "SP", "Bocaina", "3506805" }; + rows[4789] = new[] { "SP", "Bofete", "3506904" }; + rows[4790] = new[] { "SP", "Boituva", "3507001" }; + rows[4791] = new[] { "SP", "Bom Jesus dos Perd\u00f5es", "3507100" }; + rows[4792] = new[] { "SP", "Bom Sucesso de Itarar\u00e9", "3507159" }; + rows[4793] = new[] { "SP", "Bor\u00e1", "3507209" }; + rows[4794] = new[] { "SP", "Borac\u00e9ia", "3507308" }; + rows[4795] = new[] { "SP", "Borborema", "3507407" }; + rows[4796] = new[] { "SP", "Borebi", "3507456" }; + rows[4797] = new[] { "SP", "Botucatu", "3507506" }; + rows[4798] = new[] { "SP", "Bragan\u00e7a Paulista", "3507605" }; + rows[4799] = new[] { "SP", "Bra\u00fana", "3507704" }; + } + + private static void MunicipalitiesRows24(string[][] rows) + { + rows[4800] = new[] { "SP", "Brejo Alegre", "3507753" }; + rows[4801] = new[] { "SP", "Brodowski", "3507803" }; + rows[4802] = new[] { "SP", "Brotas", "3507902" }; + rows[4803] = new[] { "SP", "Buri", "3508009" }; + rows[4804] = new[] { "SP", "Buritama", "3508108" }; + rows[4805] = new[] { "SP", "Buritizal", "3508207" }; + rows[4806] = new[] { "SP", "Cabr\u00e1lia Paulista", "3508306" }; + rows[4807] = new[] { "SP", "Cabre\u00fava", "3508405" }; + rows[4808] = new[] { "SP", "Ca\u00e7apava", "3508504" }; + rows[4809] = new[] { "SP", "Cachoeira Paulista", "3508603" }; + rows[4810] = new[] { "SP", "Caconde", "3508702" }; + rows[4811] = new[] { "SP", "Cafel\u00e2ndia", "3508801" }; + rows[4812] = new[] { "SP", "Caiabu", "3508900" }; + rows[4813] = new[] { "SP", "Caieiras", "3509007" }; + rows[4814] = new[] { "SP", "Caiu\u00e1", "3509106" }; + rows[4815] = new[] { "SP", "Cajamar", "3509205" }; + rows[4816] = new[] { "SP", "Cajati", "3509254" }; + rows[4817] = new[] { "SP", "Cajobi", "3509304" }; + rows[4818] = new[] { "SP", "Cajuru", "3509403" }; + rows[4819] = new[] { "SP", "Campina do Monte Alegre", "3509452" }; + rows[4820] = new[] { "SP", "Campinas", "3509502" }; + rows[4821] = new[] { "SP", "Campo Limpo Paulista", "3509601" }; + rows[4822] = new[] { "SP", "Campos do Jord\u00e3o", "3509700" }; + rows[4823] = new[] { "SP", "Campos Novos Paulista", "3509809" }; + rows[4824] = new[] { "SP", "Canan\u00e9ia", "3509908" }; + rows[4825] = new[] { "SP", "Canas", "3509957" }; + rows[4826] = new[] { "SP", "C\u00e2ndido Mota", "3510005" }; + rows[4827] = new[] { "SP", "C\u00e2ndido Rodrigues", "3510104" }; + rows[4828] = new[] { "SP", "Canitar", "3510153" }; + rows[4829] = new[] { "SP", "Cap\u00e3o Bonito", "3510203" }; + rows[4830] = new[] { "SP", "Capela do Alto", "3510302" }; + rows[4831] = new[] { "SP", "Capivari", "3510401" }; + rows[4832] = new[] { "SP", "Caraguatatuba", "3510500" }; + rows[4833] = new[] { "SP", "Carapicu\u00edba", "3510609" }; + rows[4834] = new[] { "SP", "Cardoso", "3510708" }; + rows[4835] = new[] { "SP", "Casa Branca", "3510807" }; + rows[4836] = new[] { "SP", "C\u00e1ssia dos Coqueiros", "3510906" }; + rows[4837] = new[] { "SP", "Castilho", "3511003" }; + rows[4838] = new[] { "SP", "Catanduva", "3511102" }; + rows[4839] = new[] { "SP", "Catigu\u00e1", "3511201" }; + rows[4840] = new[] { "SP", "Cedral", "3511300" }; + rows[4841] = new[] { "SP", "Cerqueira C\u00e9sar", "3511409" }; + rows[4842] = new[] { "SP", "Cerquilho", "3511508" }; + rows[4843] = new[] { "SP", "Ces\u00e1rio Lange", "3511607" }; + rows[4844] = new[] { "SP", "Charqueada", "3511706" }; + rows[4845] = new[] { "SP", "Chavantes", "3557204" }; + rows[4846] = new[] { "SP", "Clementina", "3511904" }; + rows[4847] = new[] { "SP", "Colina", "3512001" }; + rows[4848] = new[] { "SP", "Col\u00f4mbia", "3512100" }; + rows[4849] = new[] { "SP", "Conchal", "3512209" }; + rows[4850] = new[] { "SP", "Conchas", "3512308" }; + rows[4851] = new[] { "SP", "Cordeir\u00f3polis", "3512407" }; + rows[4852] = new[] { "SP", "Coroados", "3512506" }; + rows[4853] = new[] { "SP", "Coronel Macedo", "3512605" }; + rows[4854] = new[] { "SP", "Corumbata\u00ed", "3512704" }; + rows[4855] = new[] { "SP", "Cosm\u00f3polis", "3512803" }; + rows[4856] = new[] { "SP", "Cosmorama", "3512902" }; + rows[4857] = new[] { "SP", "Cotia", "3513009" }; + rows[4858] = new[] { "SP", "Cravinhos", "3513108" }; + rows[4859] = new[] { "SP", "Cristais Paulista", "3513207" }; + rows[4860] = new[] { "SP", "Cruz\u00e1lia", "3513306" }; + rows[4861] = new[] { "SP", "Cruzeiro", "3513405" }; + rows[4862] = new[] { "SP", "Cubat\u00e3o", "3513504" }; + rows[4863] = new[] { "SP", "Cunha", "3513603" }; + rows[4864] = new[] { "SP", "Descalvado", "3513702" }; + rows[4865] = new[] { "SP", "Diadema", "3513801" }; + rows[4866] = new[] { "SP", "Dirce Reis", "3513850" }; + rows[4867] = new[] { "SP", "Divinol\u00e2ndia", "3513900" }; + rows[4868] = new[] { "SP", "Dobrada", "3514007" }; + rows[4869] = new[] { "SP", "Dois C\u00f3rregos", "3514106" }; + rows[4870] = new[] { "SP", "Dolcin\u00f3polis", "3514205" }; + rows[4871] = new[] { "SP", "Dourado", "3514304" }; + rows[4872] = new[] { "SP", "Dracena", "3514403" }; + rows[4873] = new[] { "SP", "Duartina", "3514502" }; + rows[4874] = new[] { "SP", "Dumont", "3514601" }; + rows[4875] = new[] { "SP", "Echapor\u00e3", "3514700" }; + rows[4876] = new[] { "SP", "Eldorado", "3514809" }; + rows[4877] = new[] { "SP", "Elias Fausto", "3514908" }; + rows[4878] = new[] { "SP", "Elisi\u00e1rio", "3514924" }; + rows[4879] = new[] { "SP", "Emba\u00faba", "3514957" }; + rows[4880] = new[] { "SP", "Embu das Artes", "3515004" }; + rows[4881] = new[] { "SP", "Embu-Gua\u00e7u", "3515103" }; + rows[4882] = new[] { "SP", "Emilian\u00f3polis", "3515129" }; + rows[4883] = new[] { "SP", "Engenheiro Coelho", "3515152" }; + rows[4884] = new[] { "SP", "Esp\u00edrito Santo do Pinhal", "3515186" }; + rows[4885] = new[] { "SP", "Esp\u00edrito Santo do Turvo", "3515194" }; + rows[4886] = new[] { "SP", "Estiva Gerbi", "3557303" }; + rows[4887] = new[] { "SP", "Estrela d'Oeste", "3515202" }; + rows[4888] = new[] { "SP", "Estrela do Norte", "3515301" }; + rows[4889] = new[] { "SP", "Euclides da Cunha Paulista", "3515350" }; + rows[4890] = new[] { "SP", "Fartura", "3515400" }; + rows[4891] = new[] { "SP", "Fernando Prestes", "3515608" }; + rows[4892] = new[] { "SP", "Fernand\u00f3polis", "3515509" }; + rows[4893] = new[] { "SP", "Fern\u00e3o", "3515657" }; + rows[4894] = new[] { "SP", "Ferraz de Vasconcelos", "3515707" }; + rows[4895] = new[] { "SP", "Flora Rica", "3515806" }; + rows[4896] = new[] { "SP", "Floreal", "3515905" }; + rows[4897] = new[] { "SP", "Fl\u00f3rida Paulista", "3516002" }; + rows[4898] = new[] { "SP", "Flor\u00ednea", "3516101" }; + rows[4899] = new[] { "SP", "Franca", "3516200" }; + rows[4900] = new[] { "SP", "Francisco Morato", "3516309" }; + rows[4901] = new[] { "SP", "Franco da Rocha", "3516408" }; + rows[4902] = new[] { "SP", "Gabriel Monteiro", "3516507" }; + rows[4903] = new[] { "SP", "G\u00e1lia", "3516606" }; + rows[4904] = new[] { "SP", "Gar\u00e7a", "3516705" }; + rows[4905] = new[] { "SP", "Gast\u00e3o Vidigal", "3516804" }; + rows[4906] = new[] { "SP", "Gavi\u00e3o Peixoto", "3516853" }; + rows[4907] = new[] { "SP", "General Salgado", "3516903" }; + rows[4908] = new[] { "SP", "Getulina", "3517000" }; + rows[4909] = new[] { "SP", "Glic\u00e9rio", "3517109" }; + rows[4910] = new[] { "SP", "Guai\u00e7ara", "3517208" }; + rows[4911] = new[] { "SP", "Guaimb\u00ea", "3517307" }; + rows[4912] = new[] { "SP", "Gua\u00edra", "3517406" }; + rows[4913] = new[] { "SP", "Guapia\u00e7u", "3517505" }; + rows[4914] = new[] { "SP", "Guapiara", "3517604" }; + rows[4915] = new[] { "SP", "Guar\u00e1", "3517703" }; + rows[4916] = new[] { "SP", "Guara\u00e7a\u00ed", "3517802" }; + rows[4917] = new[] { "SP", "Guaraci", "3517901" }; + rows[4918] = new[] { "SP", "Guarani d'Oeste", "3518008" }; + rows[4919] = new[] { "SP", "Guarant\u00e3", "3518107" }; + rows[4920] = new[] { "SP", "Guararapes", "3518206" }; + rows[4921] = new[] { "SP", "Guararema", "3518305" }; + rows[4922] = new[] { "SP", "Guaratinguet\u00e1", "3518404" }; + rows[4923] = new[] { "SP", "Guare\u00ed", "3518503" }; + rows[4924] = new[] { "SP", "Guariba", "3518602" }; + rows[4925] = new[] { "SP", "Guaruj\u00e1", "3518701" }; + rows[4926] = new[] { "SP", "Guarulhos", "3518800" }; + rows[4927] = new[] { "SP", "Guatapar\u00e1", "3518859" }; + rows[4928] = new[] { "SP", "Guzol\u00e2ndia", "3518909" }; + rows[4929] = new[] { "SP", "Hercul\u00e2ndia", "3519006" }; + rows[4930] = new[] { "SP", "Holambra", "3519055" }; + rows[4931] = new[] { "SP", "Hortol\u00e2ndia", "3519071" }; + rows[4932] = new[] { "SP", "Iacanga", "3519105" }; + rows[4933] = new[] { "SP", "Iacri", "3519204" }; + rows[4934] = new[] { "SP", "Iaras", "3519253" }; + rows[4935] = new[] { "SP", "Ibat\u00e9", "3519303" }; + rows[4936] = new[] { "SP", "Ibir\u00e1", "3519402" }; + rows[4937] = new[] { "SP", "Ibirarema", "3519501" }; + rows[4938] = new[] { "SP", "Ibitinga", "3519600" }; + rows[4939] = new[] { "SP", "Ibi\u00fana", "3519709" }; + rows[4940] = new[] { "SP", "Ic\u00e9m", "3519808" }; + rows[4941] = new[] { "SP", "Iep\u00ea", "3519907" }; + rows[4942] = new[] { "SP", "Igara\u00e7u do Tiet\u00ea", "3520004" }; + rows[4943] = new[] { "SP", "Igarapava", "3520103" }; + rows[4944] = new[] { "SP", "Igarat\u00e1", "3520202" }; + rows[4945] = new[] { "SP", "Iguape", "3520301" }; + rows[4946] = new[] { "SP", "Ilha Comprida", "3520426" }; + rows[4947] = new[] { "SP", "Ilha Solteira", "3520442" }; + rows[4948] = new[] { "SP", "Ilhabela", "3520400" }; + rows[4949] = new[] { "SP", "Indaiatuba", "3520509" }; + rows[4950] = new[] { "SP", "Indiana", "3520608" }; + rows[4951] = new[] { "SP", "Indiapor\u00e3", "3520707" }; + rows[4952] = new[] { "SP", "In\u00fabia Paulista", "3520806" }; + rows[4953] = new[] { "SP", "Ipaussu", "3520905" }; + rows[4954] = new[] { "SP", "Iper\u00f3", "3521002" }; + rows[4955] = new[] { "SP", "Ipe\u00fana", "3521101" }; + rows[4956] = new[] { "SP", "Ipigu\u00e1", "3521150" }; + rows[4957] = new[] { "SP", "Iporanga", "3521200" }; + rows[4958] = new[] { "SP", "Ipu\u00e3", "3521309" }; + rows[4959] = new[] { "SP", "Iracem\u00e1polis", "3521408" }; + rows[4960] = new[] { "SP", "Irapu\u00e3", "3521507" }; + rows[4961] = new[] { "SP", "Irapuru", "3521606" }; + rows[4962] = new[] { "SP", "Itaber\u00e1", "3521705" }; + rows[4963] = new[] { "SP", "Ita\u00ed", "3521804" }; + rows[4964] = new[] { "SP", "Itajobi", "3521903" }; + rows[4965] = new[] { "SP", "Itaju", "3522000" }; + rows[4966] = new[] { "SP", "Itanha\u00e9m", "3522109" }; + rows[4967] = new[] { "SP", "Itaoca", "3522158" }; + rows[4968] = new[] { "SP", "Itapecerica da Serra", "3522208" }; + rows[4969] = new[] { "SP", "Itapetininga", "3522307" }; + rows[4970] = new[] { "SP", "Itapeva", "3522406" }; + rows[4971] = new[] { "SP", "Itapevi", "3522505" }; + rows[4972] = new[] { "SP", "Itapira", "3522604" }; + rows[4973] = new[] { "SP", "Itapirapu\u00e3 Paulista", "3522653" }; + rows[4974] = new[] { "SP", "It\u00e1polis", "3522703" }; + rows[4975] = new[] { "SP", "Itaporanga", "3522802" }; + rows[4976] = new[] { "SP", "Itapu\u00ed", "3522901" }; + rows[4977] = new[] { "SP", "Itapura", "3523008" }; + rows[4978] = new[] { "SP", "Itaquaquecetuba", "3523107" }; + rows[4979] = new[] { "SP", "Itarar\u00e9", "3523206" }; + rows[4980] = new[] { "SP", "Itariri", "3523305" }; + rows[4981] = new[] { "SP", "Itatiba", "3523404" }; + rows[4982] = new[] { "SP", "Itatinga", "3523503" }; + rows[4983] = new[] { "SP", "Itirapina", "3523602" }; + rows[4984] = new[] { "SP", "Itirapu\u00e3", "3523701" }; + rows[4985] = new[] { "SP", "Itobi", "3523800" }; + rows[4986] = new[] { "SP", "Itu", "3523909" }; + rows[4987] = new[] { "SP", "Itupeva", "3524006" }; + rows[4988] = new[] { "SP", "Ituverava", "3524105" }; + rows[4989] = new[] { "SP", "Jaborandi", "3524204" }; + rows[4990] = new[] { "SP", "Jaboticabal", "3524303" }; + rows[4991] = new[] { "SP", "Jacare\u00ed", "3524402" }; + rows[4992] = new[] { "SP", "Jaci", "3524501" }; + rows[4993] = new[] { "SP", "Jacupiranga", "3524600" }; + rows[4994] = new[] { "SP", "Jaguari\u00fana", "3524709" }; + rows[4995] = new[] { "SP", "Jales", "3524808" }; + rows[4996] = new[] { "SP", "Jambeiro", "3524907" }; + rows[4997] = new[] { "SP", "Jandira", "3525003" }; + rows[4998] = new[] { "SP", "Jardin\u00f3polis", "3525102" }; + rows[4999] = new[] { "SP", "Jarinu", "3525201" }; + } + + private static void MunicipalitiesRows25(string[][] rows) + { + rows[5000] = new[] { "SP", "Ja\u00fa", "3525300" }; + rows[5001] = new[] { "SP", "Jeriquara", "3525409" }; + rows[5002] = new[] { "SP", "Joan\u00f3polis", "3525508" }; + rows[5003] = new[] { "SP", "Jo\u00e3o Ramalho", "3525607" }; + rows[5004] = new[] { "SP", "Jos\u00e9 Bonif\u00e1cio", "3525706" }; + rows[5005] = new[] { "SP", "J\u00falio Mesquita", "3525805" }; + rows[5006] = new[] { "SP", "Jumirim", "3525854" }; + rows[5007] = new[] { "SP", "Jundia\u00ed", "3525904" }; + rows[5008] = new[] { "SP", "Junqueir\u00f3polis", "3526001" }; + rows[5009] = new[] { "SP", "Juqui\u00e1", "3526100" }; + rows[5010] = new[] { "SP", "Juquitiba", "3526209" }; + rows[5011] = new[] { "SP", "Lagoinha", "3526308" }; + rows[5012] = new[] { "SP", "Laranjal Paulista", "3526407" }; + rows[5013] = new[] { "SP", "Lav\u00ednia", "3526506" }; + rows[5014] = new[] { "SP", "Lavrinhas", "3526605" }; + rows[5015] = new[] { "SP", "Leme", "3526704" }; + rows[5016] = new[] { "SP", "Len\u00e7\u00f3is Paulista", "3526803" }; + rows[5017] = new[] { "SP", "Limeira", "3526902" }; + rows[5018] = new[] { "SP", "Lind\u00f3ia", "3527009" }; + rows[5019] = new[] { "SP", "Lins", "3527108" }; + rows[5020] = new[] { "SP", "Lorena", "3527207" }; + rows[5021] = new[] { "SP", "Lourdes", "3527256" }; + rows[5022] = new[] { "SP", "Louveira", "3527306" }; + rows[5023] = new[] { "SP", "Luc\u00e9lia", "3527405" }; + rows[5024] = new[] { "SP", "Lucian\u00f3polis", "3527504" }; + rows[5025] = new[] { "SP", "Lu\u00eds Ant\u00f4nio", "3527603" }; + rows[5026] = new[] { "SP", "Luizi\u00e2nia", "3527702" }; + rows[5027] = new[] { "SP", "Lup\u00e9rcio", "3527801" }; + rows[5028] = new[] { "SP", "Lut\u00e9cia", "3527900" }; + rows[5029] = new[] { "SP", "Macatuba", "3528007" }; + rows[5030] = new[] { "SP", "Macaubal", "3528106" }; + rows[5031] = new[] { "SP", "Maced\u00f4nia", "3528205" }; + rows[5032] = new[] { "SP", "Magda", "3528304" }; + rows[5033] = new[] { "SP", "Mairinque", "3528403" }; + rows[5034] = new[] { "SP", "Mairipor\u00e3", "3528502" }; + rows[5035] = new[] { "SP", "Manduri", "3528601" }; + rows[5036] = new[] { "SP", "Marab\u00e1 Paulista", "3528700" }; + rows[5037] = new[] { "SP", "Maraca\u00ed", "3528809" }; + rows[5038] = new[] { "SP", "Marapoama", "3528858" }; + rows[5039] = new[] { "SP", "Mari\u00e1polis", "3528908" }; + rows[5040] = new[] { "SP", "Mar\u00edlia", "3529005" }; + rows[5041] = new[] { "SP", "Marin\u00f3polis", "3529104" }; + rows[5042] = new[] { "SP", "Martin\u00f3polis", "3529203" }; + rows[5043] = new[] { "SP", "Mat\u00e3o", "3529302" }; + rows[5044] = new[] { "SP", "Mau\u00e1", "3529401" }; + rows[5045] = new[] { "SP", "Mendon\u00e7a", "3529500" }; + rows[5046] = new[] { "SP", "Meridiano", "3529609" }; + rows[5047] = new[] { "SP", "Mes\u00f3polis", "3529658" }; + rows[5048] = new[] { "SP", "Miguel\u00f3polis", "3529708" }; + rows[5049] = new[] { "SP", "Mineiros do Tiet\u00ea", "3529807" }; + rows[5050] = new[] { "SP", "Mira Estrela", "3530003" }; + rows[5051] = new[] { "SP", "Miracatu", "3529906" }; + rows[5052] = new[] { "SP", "Mirand\u00f3polis", "3530102" }; + rows[5053] = new[] { "SP", "Mirante do Paranapanema", "3530201" }; + rows[5054] = new[] { "SP", "Mirassol", "3530300" }; + rows[5055] = new[] { "SP", "Mirassol\u00e2ndia", "3530409" }; + rows[5056] = new[] { "SP", "Mococa", "3530508" }; + rows[5057] = new[] { "SP", "Mogi das Cruzes", "3530607" }; + rows[5058] = new[] { "SP", "Mogi Gua\u00e7u", "3530706" }; + rows[5059] = new[] { "SP", "Mogi Mirim", "3530805" }; + rows[5060] = new[] { "SP", "Mombuca", "3530904" }; + rows[5061] = new[] { "SP", "Mon\u00e7\u00f5es", "3531001" }; + rows[5062] = new[] { "SP", "Mongagu\u00e1", "3531100" }; + rows[5063] = new[] { "SP", "Monte Alegre do Sul", "3531209" }; + rows[5064] = new[] { "SP", "Monte Alto", "3531308" }; + rows[5065] = new[] { "SP", "Monte Apraz\u00edvel", "3531407" }; + rows[5066] = new[] { "SP", "Monte Azul Paulista", "3531506" }; + rows[5067] = new[] { "SP", "Monte Castelo", "3531605" }; + rows[5068] = new[] { "SP", "Monte Mor", "3531803" }; + rows[5069] = new[] { "SP", "Monteiro Lobato", "3531704" }; + rows[5070] = new[] { "SP", "Morro Agudo", "3531902" }; + rows[5071] = new[] { "SP", "Morungaba", "3532009" }; + rows[5072] = new[] { "SP", "Motuca", "3532058" }; + rows[5073] = new[] { "SP", "Murutinga do Sul", "3532108" }; + rows[5074] = new[] { "SP", "Nantes", "3532157" }; + rows[5075] = new[] { "SP", "Narandiba", "3532207" }; + rows[5076] = new[] { "SP", "Natividade da Serra", "3532306" }; + rows[5077] = new[] { "SP", "Nazar\u00e9 Paulista", "3532405" }; + rows[5078] = new[] { "SP", "Neves Paulista", "3532504" }; + rows[5079] = new[] { "SP", "Nhandeara", "3532603" }; + rows[5080] = new[] { "SP", "Nipo\u00e3", "3532702" }; + rows[5081] = new[] { "SP", "Nova Alian\u00e7a", "3532801" }; + rows[5082] = new[] { "SP", "Nova Campina", "3532827" }; + rows[5083] = new[] { "SP", "Nova Cana\u00e3 Paulista", "3532843" }; + rows[5084] = new[] { "SP", "Nova Castilho", "3532868" }; + rows[5085] = new[] { "SP", "Nova Europa", "3532900" }; + rows[5086] = new[] { "SP", "Nova Granada", "3533007" }; + rows[5087] = new[] { "SP", "Nova Guataporanga", "3533106" }; + rows[5088] = new[] { "SP", "Nova Independ\u00eancia", "3533205" }; + rows[5089] = new[] { "SP", "Nova Luzit\u00e2nia", "3533304" }; + rows[5090] = new[] { "SP", "Nova Odessa", "3533403" }; + rows[5091] = new[] { "SP", "Novais", "3533254" }; + rows[5092] = new[] { "SP", "Novo Horizonte", "3533502" }; + rows[5093] = new[] { "SP", "Nuporanga", "3533601" }; + rows[5094] = new[] { "SP", "Ocau\u00e7u", "3533700" }; + rows[5095] = new[] { "SP", "\u00d3leo", "3533809" }; + rows[5096] = new[] { "SP", "Ol\u00edmpia", "3533908" }; + rows[5097] = new[] { "SP", "Onda Verde", "3534005" }; + rows[5098] = new[] { "SP", "Oriente", "3534104" }; + rows[5099] = new[] { "SP", "Orindi\u00fava", "3534203" }; + rows[5100] = new[] { "SP", "Orl\u00e2ndia", "3534302" }; + rows[5101] = new[] { "SP", "Osasco", "3534401" }; + rows[5102] = new[] { "SP", "Oscar Bressane", "3534500" }; + rows[5103] = new[] { "SP", "Osvaldo Cruz", "3534609" }; + rows[5104] = new[] { "SP", "Ourinhos", "3534708" }; + rows[5105] = new[] { "SP", "Ouro Verde", "3534807" }; + rows[5106] = new[] { "SP", "Ouroeste", "3534757" }; + rows[5107] = new[] { "SP", "Pacaembu", "3534906" }; + rows[5108] = new[] { "SP", "Palestina", "3535002" }; + rows[5109] = new[] { "SP", "Palmares Paulista", "3535101" }; + rows[5110] = new[] { "SP", "Palmeira d'Oeste", "3535200" }; + rows[5111] = new[] { "SP", "Palmital", "3535309" }; + rows[5112] = new[] { "SP", "Panorama", "3535408" }; + rows[5113] = new[] { "SP", "Paragua\u00e7u Paulista", "3535507" }; + rows[5114] = new[] { "SP", "Paraibuna", "3535606" }; + rows[5115] = new[] { "SP", "Para\u00edso", "3535705" }; + rows[5116] = new[] { "SP", "Paranapanema", "3535804" }; + rows[5117] = new[] { "SP", "Paranapu\u00e3", "3535903" }; + rows[5118] = new[] { "SP", "Parapu\u00e3", "3536000" }; + rows[5119] = new[] { "SP", "Pardinho", "3536109" }; + rows[5120] = new[] { "SP", "Pariquera-A\u00e7u", "3536208" }; + rows[5121] = new[] { "SP", "Parisi", "3536257" }; + rows[5122] = new[] { "SP", "Patroc\u00ednio Paulista", "3536307" }; + rows[5123] = new[] { "SP", "Paulic\u00e9ia", "3536406" }; + rows[5124] = new[] { "SP", "Paul\u00ednia", "3536505" }; + rows[5125] = new[] { "SP", "Paulist\u00e2nia", "3536570" }; + rows[5126] = new[] { "SP", "Paulo de Faria", "3536604" }; + rows[5127] = new[] { "SP", "Pederneiras", "3536703" }; + rows[5128] = new[] { "SP", "Pedra Bela", "3536802" }; + rows[5129] = new[] { "SP", "Pedran\u00f3polis", "3536901" }; + rows[5130] = new[] { "SP", "Pedregulho", "3537008" }; + rows[5131] = new[] { "SP", "Pedreira", "3537107" }; + rows[5132] = new[] { "SP", "Pedrinhas Paulista", "3537156" }; + rows[5133] = new[] { "SP", "Pedro de Toledo", "3537206" }; + rows[5134] = new[] { "SP", "Pen\u00e1polis", "3537305" }; + rows[5135] = new[] { "SP", "Pereira Barreto", "3537404" }; + rows[5136] = new[] { "SP", "Pereiras", "3537503" }; + rows[5137] = new[] { "SP", "Peru\u00edbe", "3537602" }; + rows[5138] = new[] { "SP", "Piacatu", "3537701" }; + rows[5139] = new[] { "SP", "Piedade", "3537800" }; + rows[5140] = new[] { "SP", "Pilar do Sul", "3537909" }; + rows[5141] = new[] { "SP", "Pindamonhangaba", "3538006" }; + rows[5142] = new[] { "SP", "Pindorama", "3538105" }; + rows[5143] = new[] { "SP", "Pinhalzinho", "3538204" }; + rows[5144] = new[] { "SP", "Piquerobi", "3538303" }; + rows[5145] = new[] { "SP", "Piquete", "3538501" }; + rows[5146] = new[] { "SP", "Piracaia", "3538600" }; + rows[5147] = new[] { "SP", "Piracicaba", "3538709" }; + rows[5148] = new[] { "SP", "Piraju", "3538808" }; + rows[5149] = new[] { "SP", "Piraju\u00ed", "3538907" }; + rows[5150] = new[] { "SP", "Pirangi", "3539004" }; + rows[5151] = new[] { "SP", "Pirapora do Bom Jesus", "3539103" }; + rows[5152] = new[] { "SP", "Pirapozinho", "3539202" }; + rows[5153] = new[] { "SP", "Pirassununga", "3539301" }; + rows[5154] = new[] { "SP", "Piratininga", "3539400" }; + rows[5155] = new[] { "SP", "Pitangueiras", "3539509" }; + rows[5156] = new[] { "SP", "Planalto", "3539608" }; + rows[5157] = new[] { "SP", "Platina", "3539707" }; + rows[5158] = new[] { "SP", "Po\u00e1", "3539806" }; + rows[5159] = new[] { "SP", "Poloni", "3539905" }; + rows[5160] = new[] { "SP", "Pomp\u00e9ia", "3540002" }; + rows[5161] = new[] { "SP", "Ponga\u00ed", "3540101" }; + rows[5162] = new[] { "SP", "Pontal", "3540200" }; + rows[5163] = new[] { "SP", "Pontalinda", "3540259" }; + rows[5164] = new[] { "SP", "Pontes Gestal", "3540309" }; + rows[5165] = new[] { "SP", "Populina", "3540408" }; + rows[5166] = new[] { "SP", "Porangaba", "3540507" }; + rows[5167] = new[] { "SP", "Porto Feliz", "3540606" }; + rows[5168] = new[] { "SP", "Porto Ferreira", "3540705" }; + rows[5169] = new[] { "SP", "Potim", "3540754" }; + rows[5170] = new[] { "SP", "Potirendaba", "3540804" }; + rows[5171] = new[] { "SP", "Pracinha", "3540853" }; + rows[5172] = new[] { "SP", "Prad\u00f3polis", "3540903" }; + rows[5173] = new[] { "SP", "Praia Grande", "3541000" }; + rows[5174] = new[] { "SP", "Prat\u00e2nia", "3541059" }; + rows[5175] = new[] { "SP", "Presidente Alves", "3541109" }; + rows[5176] = new[] { "SP", "Presidente Bernardes", "3541208" }; + rows[5177] = new[] { "SP", "Presidente Epit\u00e1cio", "3541307" }; + rows[5178] = new[] { "SP", "Presidente Prudente", "3541406" }; + rows[5179] = new[] { "SP", "Presidente Venceslau", "3541505" }; + rows[5180] = new[] { "SP", "Promiss\u00e3o", "3541604" }; + rows[5181] = new[] { "SP", "Quadra", "3541653" }; + rows[5182] = new[] { "SP", "Quat\u00e1", "3541703" }; + rows[5183] = new[] { "SP", "Queiroz", "3541802" }; + rows[5184] = new[] { "SP", "Queluz", "3541901" }; + rows[5185] = new[] { "SP", "Quintana", "3542008" }; + rows[5186] = new[] { "SP", "Rafard", "3542107" }; + rows[5187] = new[] { "SP", "Rancharia", "3542206" }; + rows[5188] = new[] { "SP", "Reden\u00e7\u00e3o da Serra", "3542305" }; + rows[5189] = new[] { "SP", "Regente Feij\u00f3", "3542404" }; + rows[5190] = new[] { "SP", "Regin\u00f3polis", "3542503" }; + rows[5191] = new[] { "SP", "Registro", "3542602" }; + rows[5192] = new[] { "SP", "Restinga", "3542701" }; + rows[5193] = new[] { "SP", "Ribeira", "3542800" }; + rows[5194] = new[] { "SP", "Ribeir\u00e3o Bonito", "3542909" }; + rows[5195] = new[] { "SP", "Ribeir\u00e3o Branco", "3543006" }; + rows[5196] = new[] { "SP", "Ribeir\u00e3o Corrente", "3543105" }; + rows[5197] = new[] { "SP", "Ribeir\u00e3o do Sul", "3543204" }; + rows[5198] = new[] { "SP", "Ribeir\u00e3o dos \u00cdndios", "3543238" }; + rows[5199] = new[] { "SP", "Ribeir\u00e3o Grande", "3543253" }; + } + + private static void MunicipalitiesRows26(string[][] rows) + { + rows[5200] = new[] { "SP", "Ribeir\u00e3o Pires", "3543303" }; + rows[5201] = new[] { "SP", "Ribeir\u00e3o Preto", "3543402" }; + rows[5202] = new[] { "SP", "Rifaina", "3543600" }; + rows[5203] = new[] { "SP", "Rinc\u00e3o", "3543709" }; + rows[5204] = new[] { "SP", "Rin\u00f3polis", "3543808" }; + rows[5205] = new[] { "SP", "Rio Claro", "3543907" }; + rows[5206] = new[] { "SP", "Rio das Pedras", "3544004" }; + rows[5207] = new[] { "SP", "Rio Grande da Serra", "3544103" }; + rows[5208] = new[] { "SP", "Riol\u00e2ndia", "3544202" }; + rows[5209] = new[] { "SP", "Riversul", "3543501" }; + rows[5210] = new[] { "SP", "Rosana", "3544251" }; + rows[5211] = new[] { "SP", "Roseira", "3544301" }; + rows[5212] = new[] { "SP", "Rubi\u00e1cea", "3544400" }; + rows[5213] = new[] { "SP", "Rubin\u00e9ia", "3544509" }; + rows[5214] = new[] { "SP", "Sabino", "3544608" }; + rows[5215] = new[] { "SP", "Sagres", "3544707" }; + rows[5216] = new[] { "SP", "Sales", "3544806" }; + rows[5217] = new[] { "SP", "Sales Oliveira", "3544905" }; + rows[5218] = new[] { "SP", "Sales\u00f3polis", "3545001" }; + rows[5219] = new[] { "SP", "Salmour\u00e3o", "3545100" }; + rows[5220] = new[] { "SP", "Saltinho", "3545159" }; + rows[5221] = new[] { "SP", "Salto", "3545209" }; + rows[5222] = new[] { "SP", "Salto de Pirapora", "3545308" }; + rows[5223] = new[] { "SP", "Salto Grande", "3545407" }; + rows[5224] = new[] { "SP", "Sandovalina", "3545506" }; + rows[5225] = new[] { "SP", "Santa Ad\u00e9lia", "3545605" }; + rows[5226] = new[] { "SP", "Santa Albertina", "3545704" }; + rows[5227] = new[] { "SP", "Santa B\u00e1rbara d'Oeste", "3545803" }; + rows[5228] = new[] { "SP", "Santa Branca", "3546009" }; + rows[5229] = new[] { "SP", "Santa Clara d'Oeste", "3546108" }; + rows[5230] = new[] { "SP", "Santa Cruz da Concei\u00e7\u00e3o", "3546207" }; + rows[5231] = new[] { "SP", "Santa Cruz da Esperan\u00e7a", "3546256" }; + rows[5232] = new[] { "SP", "Santa Cruz das Palmeiras", "3546306" }; + rows[5233] = new[] { "SP", "Santa Cruz do Rio Pardo", "3546405" }; + rows[5234] = new[] { "SP", "Santa Ernestina", "3546504" }; + rows[5235] = new[] { "SP", "Santa F\u00e9 do Sul", "3546603" }; + rows[5236] = new[] { "SP", "Santa Gertrudes", "3546702" }; + rows[5237] = new[] { "SP", "Santa Isabel", "3546801" }; + rows[5238] = new[] { "SP", "Santa L\u00facia", "3546900" }; + rows[5239] = new[] { "SP", "Santa Maria da Serra", "3547007" }; + rows[5240] = new[] { "SP", "Santa Mercedes", "3547106" }; + rows[5241] = new[] { "SP", "Santa Rita d'Oeste", "3547403" }; + rows[5242] = new[] { "SP", "Santa Rita do Passa Quatro", "3547502" }; + rows[5243] = new[] { "SP", "Santa Rosa de Viterbo", "3547601" }; + rows[5244] = new[] { "SP", "Santa Salete", "3547650" }; + rows[5245] = new[] { "SP", "Santana da Ponte Pensa", "3547205" }; + rows[5246] = new[] { "SP", "Santana de Parna\u00edba", "3547304" }; + rows[5247] = new[] { "SP", "Santo Anast\u00e1cio", "3547700" }; + rows[5248] = new[] { "SP", "Santo Andr\u00e9", "3547809" }; + rows[5249] = new[] { "SP", "Santo Ant\u00f4nio da Alegria", "3547908" }; + rows[5250] = new[] { "SP", "Santo Ant\u00f4nio de Posse", "3548005" }; + rows[5251] = new[] { "SP", "Santo Ant\u00f4nio do Aracangu\u00e1", "3548054" }; + rows[5252] = new[] { "SP", "Santo Ant\u00f4nio do Jardim", "3548104" }; + rows[5253] = new[] { "SP", "Santo Ant\u00f4nio do Pinhal", "3548203" }; + rows[5254] = new[] { "SP", "Santo Expedito", "3548302" }; + rows[5255] = new[] { "SP", "Sant\u00f3polis do Aguape\u00ed", "3548401" }; + rows[5256] = new[] { "SP", "Santos", "3548500" }; + rows[5257] = new[] { "SP", "S\u00e3o Bento do Sapuca\u00ed", "3548609" }; + rows[5258] = new[] { "SP", "S\u00e3o Bernardo do Campo", "3548708" }; + rows[5259] = new[] { "SP", "S\u00e3o Caetano do Sul", "3548807" }; + rows[5260] = new[] { "SP", "S\u00e3o Carlos", "3548906" }; + rows[5261] = new[] { "SP", "S\u00e3o Francisco", "3549003" }; + rows[5262] = new[] { "SP", "S\u00e3o Jo\u00e3o da Boa Vista", "3549102" }; + rows[5263] = new[] { "SP", "S\u00e3o Jo\u00e3o das Duas Pontes", "3549201" }; + rows[5264] = new[] { "SP", "S\u00e3o Jo\u00e3o de Iracema", "3549250" }; + rows[5265] = new[] { "SP", "S\u00e3o Jo\u00e3o do Pau d'Alho", "3549300" }; + rows[5266] = new[] { "SP", "S\u00e3o Joaquim da Barra", "3549409" }; + rows[5267] = new[] { "SP", "S\u00e3o Jos\u00e9 da Bela Vista", "3549508" }; + rows[5268] = new[] { "SP", "S\u00e3o Jos\u00e9 do Barreiro", "3549607" }; + rows[5269] = new[] { "SP", "S\u00e3o Jos\u00e9 do Rio Pardo", "3549706" }; + rows[5270] = new[] { "SP", "S\u00e3o Jos\u00e9 do Rio Preto", "3549805" }; + rows[5271] = new[] { "SP", "S\u00e3o Jos\u00e9 dos Campos", "3549904" }; + rows[5272] = new[] { "SP", "S\u00e3o Louren\u00e7o da Serra", "3549953" }; + rows[5273] = new[] { "SP", "S\u00e3o Luiz do Paraitinga", "3550001" }; + rows[5274] = new[] { "SP", "S\u00e3o Manuel", "3550100" }; + rows[5275] = new[] { "SP", "S\u00e3o Miguel Arcanjo", "3550209" }; + rows[5276] = new[] { "SP", "S\u00e3o Paulo", "3550308" }; + rows[5277] = new[] { "SP", "S\u00e3o Pedro", "3550407" }; + rows[5278] = new[] { "SP", "S\u00e3o Pedro do Turvo", "3550506" }; + rows[5279] = new[] { "SP", "S\u00e3o Roque", "3550605" }; + rows[5280] = new[] { "SP", "S\u00e3o Sebasti\u00e3o", "3550704" }; + rows[5281] = new[] { "SP", "S\u00e3o Sebasti\u00e3o da Grama", "3550803" }; + rows[5282] = new[] { "SP", "S\u00e3o Sim\u00e3o", "3550902" }; + rows[5283] = new[] { "SP", "S\u00e3o Vicente", "3551009" }; + rows[5284] = new[] { "SP", "Sarapu\u00ed", "3551108" }; + rows[5285] = new[] { "SP", "Sarutai\u00e1", "3551207" }; + rows[5286] = new[] { "SP", "Sebastian\u00f3polis do Sul", "3551306" }; + rows[5287] = new[] { "SP", "Serra Azul", "3551405" }; + rows[5288] = new[] { "SP", "Serra Negra", "3551603" }; + rows[5289] = new[] { "SP", "Serrana", "3551504" }; + rows[5290] = new[] { "SP", "Sert\u00e3ozinho", "3551702" }; + rows[5291] = new[] { "SP", "Sete Barras", "3551801" }; + rows[5292] = new[] { "SP", "Sever\u00ednia", "3551900" }; + rows[5293] = new[] { "SP", "Silveiras", "3552007" }; + rows[5294] = new[] { "SP", "Socorro", "3552106" }; + rows[5295] = new[] { "SP", "Sorocaba", "3552205" }; + rows[5296] = new[] { "SP", "Sud Mennucci", "3552304" }; + rows[5297] = new[] { "SP", "Sumar\u00e9", "3552403" }; + rows[5298] = new[] { "SP", "Suzan\u00e1polis", "3552551" }; + rows[5299] = new[] { "SP", "Suzano", "3552502" }; + rows[5300] = new[] { "SP", "Tabapu\u00e3", "3552601" }; + rows[5301] = new[] { "SP", "Tabatinga", "3552700" }; + rows[5302] = new[] { "SP", "Tabo\u00e3o da Serra", "3552809" }; + rows[5303] = new[] { "SP", "Taciba", "3552908" }; + rows[5304] = new[] { "SP", "Tagua\u00ed", "3553005" }; + rows[5305] = new[] { "SP", "Taia\u00e7u", "3553104" }; + rows[5306] = new[] { "SP", "Tai\u00fava", "3553203" }; + rows[5307] = new[] { "SP", "Tamba\u00fa", "3553302" }; + rows[5308] = new[] { "SP", "Tanabi", "3553401" }; + rows[5309] = new[] { "SP", "Tapira\u00ed", "3553500" }; + rows[5310] = new[] { "SP", "Tapiratiba", "3553609" }; + rows[5311] = new[] { "SP", "Taquaral", "3553658" }; + rows[5312] = new[] { "SP", "Taquaritinga", "3553708" }; + rows[5313] = new[] { "SP", "Taquarituba", "3553807" }; + rows[5314] = new[] { "SP", "Taquariva\u00ed", "3553856" }; + rows[5315] = new[] { "SP", "Tarabai", "3553906" }; + rows[5316] = new[] { "SP", "Tarum\u00e3", "3553955" }; + rows[5317] = new[] { "SP", "Tatu\u00ed", "3554003" }; + rows[5318] = new[] { "SP", "Taubat\u00e9", "3554102" }; + rows[5319] = new[] { "SP", "Tejup\u00e1", "3554201" }; + rows[5320] = new[] { "SP", "Teodoro Sampaio", "3554300" }; + rows[5321] = new[] { "SP", "Terra Roxa", "3554409" }; + rows[5322] = new[] { "SP", "Tiet\u00ea", "3554508" }; + rows[5323] = new[] { "SP", "Timburi", "3554607" }; + rows[5324] = new[] { "SP", "Torre de Pedra", "3554656" }; + rows[5325] = new[] { "SP", "Torrinha", "3554706" }; + rows[5326] = new[] { "SP", "Trabiju", "3554755" }; + rows[5327] = new[] { "SP", "Trememb\u00e9", "3554805" }; + rows[5328] = new[] { "SP", "Tr\u00eas Fronteiras", "3554904" }; + rows[5329] = new[] { "SP", "Tuiuti", "3554953" }; + rows[5330] = new[] { "SP", "Tup\u00e3", "3555000" }; + rows[5331] = new[] { "SP", "Tupi Paulista", "3555109" }; + rows[5332] = new[] { "SP", "Turi\u00faba", "3555208" }; + rows[5333] = new[] { "SP", "Turmalina", "3555307" }; + rows[5334] = new[] { "SP", "Ubarana", "3555356" }; + rows[5335] = new[] { "SP", "Ubatuba", "3555406" }; + rows[5336] = new[] { "SP", "Ubirajara", "3555505" }; + rows[5337] = new[] { "SP", "Uchoa", "3555604" }; + rows[5338] = new[] { "SP", "Uni\u00e3o Paulista", "3555703" }; + rows[5339] = new[] { "SP", "Ur\u00e2nia", "3555802" }; + rows[5340] = new[] { "SP", "Uru", "3555901" }; + rows[5341] = new[] { "SP", "Urup\u00eas", "3556008" }; + rows[5342] = new[] { "SP", "Valentim Gentil", "3556107" }; + rows[5343] = new[] { "SP", "Valinhos", "3556206" }; + rows[5344] = new[] { "SP", "Valpara\u00edso", "3556305" }; + rows[5345] = new[] { "SP", "Vargem", "3556354" }; + rows[5346] = new[] { "SP", "Vargem Grande do Sul", "3556404" }; + rows[5347] = new[] { "SP", "Vargem Grande Paulista", "3556453" }; + rows[5348] = new[] { "SP", "V\u00e1rzea Paulista", "3556503" }; + rows[5349] = new[] { "SP", "Vera Cruz", "3556602" }; + rows[5350] = new[] { "SP", "Vinhedo", "3556701" }; + rows[5351] = new[] { "SP", "Viradouro", "3556800" }; + rows[5352] = new[] { "SP", "Vista Alegre do Alto", "3556909" }; + rows[5353] = new[] { "SP", "Vit\u00f3ria Brasil", "3556958" }; + rows[5354] = new[] { "SP", "Votorantim", "3557006" }; + rows[5355] = new[] { "SP", "Votuporanga", "3557105" }; + rows[5356] = new[] { "SP", "Zacarias", "3557154" }; + rows[5357] = new[] { "SE", "Amparo do S\u00e3o Francisco", "2800100" }; + rows[5358] = new[] { "SE", "Aquidab\u00e3", "2800209" }; + rows[5359] = new[] { "SE", "Aracaju", "2800308" }; + rows[5360] = new[] { "SE", "Arau\u00e1", "2800407" }; + rows[5361] = new[] { "SE", "Areia Branca", "2800506" }; + rows[5362] = new[] { "SE", "Barra dos Coqueiros", "2800605" }; + rows[5363] = new[] { "SE", "Boquim", "2800670" }; + rows[5364] = new[] { "SE", "Brejo Grande", "2800704" }; + rows[5365] = new[] { "SE", "Campo do Brito", "2801009" }; + rows[5366] = new[] { "SE", "Canhoba", "2801108" }; + rows[5367] = new[] { "SE", "Canind\u00e9 de S\u00e3o Francisco", "2801207" }; + rows[5368] = new[] { "SE", "Capela", "2801306" }; + rows[5369] = new[] { "SE", "Carira", "2801405" }; + rows[5370] = new[] { "SE", "Carm\u00f3polis", "2801504" }; + rows[5371] = new[] { "SE", "Cedro de S\u00e3o Jo\u00e3o", "2801603" }; + rows[5372] = new[] { "SE", "Cristin\u00e1polis", "2801702" }; + rows[5373] = new[] { "SE", "Cumbe", "2801900" }; + rows[5374] = new[] { "SE", "Divina Pastora", "2802007" }; + rows[5375] = new[] { "SE", "Est\u00e2ncia", "2802106" }; + rows[5376] = new[] { "SE", "Feira Nova", "2802205" }; + rows[5377] = new[] { "SE", "Frei Paulo", "2802304" }; + rows[5378] = new[] { "SE", "Gararu", "2802403" }; + rows[5379] = new[] { "SE", "General Maynard", "2802502" }; + rows[5380] = new[] { "SE", "Graccho Cardoso", "2802601" }; + rows[5381] = new[] { "SE", "Ilha das Flores", "2802700" }; + rows[5382] = new[] { "SE", "Indiaroba", "2802809" }; + rows[5383] = new[] { "SE", "Itabaiana", "2802908" }; + rows[5384] = new[] { "SE", "Itabaianinha", "2803005" }; + rows[5385] = new[] { "SE", "Itabi", "2803104" }; + rows[5386] = new[] { "SE", "Itaporanga d'Ajuda", "2803203" }; + rows[5387] = new[] { "SE", "Japaratuba", "2803302" }; + rows[5388] = new[] { "SE", "Japoat\u00e3", "2803401" }; + rows[5389] = new[] { "SE", "Lagarto", "2803500" }; + rows[5390] = new[] { "SE", "Laranjeiras", "2803609" }; + rows[5391] = new[] { "SE", "Macambira", "2803708" }; + rows[5392] = new[] { "SE", "Malhada dos Bois", "2803807" }; + rows[5393] = new[] { "SE", "Malhador", "2803906" }; + rows[5394] = new[] { "SE", "Maruim", "2804003" }; + rows[5395] = new[] { "SE", "Moita Bonita", "2804102" }; + rows[5396] = new[] { "SE", "Monte Alegre de Sergipe", "2804201" }; + rows[5397] = new[] { "SE", "Muribeca", "2804300" }; + rows[5398] = new[] { "SE", "Ne\u00f3polis", "2804409" }; + rows[5399] = new[] { "SE", "Nossa Senhora Aparecida", "2804458" }; + } + + private static void MunicipalitiesRows27(string[][] rows) + { + rows[5400] = new[] { "SE", "Nossa Senhora da Gl\u00f3ria", "2804508" }; + rows[5401] = new[] { "SE", "Nossa Senhora das Dores", "2804607" }; + rows[5402] = new[] { "SE", "Nossa Senhora de Lourdes", "2804706" }; + rows[5403] = new[] { "SE", "Nossa Senhora do Socorro", "2804805" }; + rows[5404] = new[] { "SE", "Pacatuba", "2804904" }; + rows[5405] = new[] { "SE", "Pedra Mole", "2805000" }; + rows[5406] = new[] { "SE", "Pedrinhas", "2805109" }; + rows[5407] = new[] { "SE", "Pinh\u00e3o", "2805208" }; + rows[5408] = new[] { "SE", "Pirambu", "2805307" }; + rows[5409] = new[] { "SE", "Po\u00e7o Redondo", "2805406" }; + rows[5410] = new[] { "SE", "Po\u00e7o Verde", "2805505" }; + rows[5411] = new[] { "SE", "Porto da Folha", "2805604" }; + rows[5412] = new[] { "SE", "Propri\u00e1", "2805703" }; + rows[5413] = new[] { "SE", "Riach\u00e3o do Dantas", "2805802" }; + rows[5414] = new[] { "SE", "Riachuelo", "2805901" }; + rows[5415] = new[] { "SE", "Ribeir\u00f3polis", "2806008" }; + rows[5416] = new[] { "SE", "Ros\u00e1rio do Catete", "2806107" }; + rows[5417] = new[] { "SE", "Salgado", "2806206" }; + rows[5418] = new[] { "SE", "Santa Luzia do Itanhy", "2806305" }; + rows[5419] = new[] { "SE", "Santa Rosa de Lima", "2806503" }; + rows[5420] = new[] { "SE", "Santana do S\u00e3o Francisco", "2806404" }; + rows[5421] = new[] { "SE", "Santo Amaro das Brotas", "2806602" }; + rows[5422] = new[] { "SE", "S\u00e3o Crist\u00f3v\u00e3o", "2806701" }; + rows[5423] = new[] { "SE", "S\u00e3o Domingos", "2806800" }; + rows[5424] = new[] { "SE", "S\u00e3o Francisco", "2806909" }; + rows[5425] = new[] { "SE", "S\u00e3o Miguel do Aleixo", "2807006" }; + rows[5426] = new[] { "SE", "Sim\u00e3o Dias", "2807105" }; + rows[5427] = new[] { "SE", "Siriri", "2807204" }; + rows[5428] = new[] { "SE", "Telha", "2807303" }; + rows[5429] = new[] { "SE", "Tobias Barreto", "2807402" }; + rows[5430] = new[] { "SE", "Tomar do Geru", "2807501" }; + rows[5431] = new[] { "SE", "Umba\u00faba", "2807600" }; + rows[5432] = new[] { "TO", "Abreul\u00e2ndia", "1700251" }; + rows[5433] = new[] { "TO", "Aguiarn\u00f3polis", "1700301" }; + rows[5434] = new[] { "TO", "Alian\u00e7a do Tocantins", "1700350" }; + rows[5435] = new[] { "TO", "Almas", "1700400" }; + rows[5436] = new[] { "TO", "Alvorada", "1700707" }; + rows[5437] = new[] { "TO", "Anan\u00e1s", "1701002" }; + rows[5438] = new[] { "TO", "Angico", "1701051" }; + rows[5439] = new[] { "TO", "Aparecida do Rio Negro", "1701101" }; + rows[5440] = new[] { "TO", "Aragominas", "1701309" }; + rows[5441] = new[] { "TO", "Araguacema", "1701903" }; + rows[5442] = new[] { "TO", "Aragua\u00e7u", "1702000" }; + rows[5443] = new[] { "TO", "Aragua\u00edna", "1702109" }; + rows[5444] = new[] { "TO", "Araguan\u00e3", "1702158" }; + rows[5445] = new[] { "TO", "Araguatins", "1702208" }; + rows[5446] = new[] { "TO", "Arapoema", "1702307" }; + rows[5447] = new[] { "TO", "Arraias", "1702406" }; + rows[5448] = new[] { "TO", "Augustin\u00f3polis", "1702554" }; + rows[5449] = new[] { "TO", "Aurora do Tocantins", "1702703" }; + rows[5450] = new[] { "TO", "Axix\u00e1 do Tocantins", "1702901" }; + rows[5451] = new[] { "TO", "Baba\u00e7ul\u00e2ndia", "1703008" }; + rows[5452] = new[] { "TO", "Bandeirantes do Tocantins", "1703057" }; + rows[5453] = new[] { "TO", "Barra do Ouro", "1703073" }; + rows[5454] = new[] { "TO", "Barrol\u00e2ndia", "1703107" }; + rows[5455] = new[] { "TO", "Bernardo Say\u00e3o", "1703206" }; + rows[5456] = new[] { "TO", "Bom Jesus do Tocantins", "1703305" }; + rows[5457] = new[] { "TO", "Brasil\u00e2ndia do Tocantins", "1703602" }; + rows[5458] = new[] { "TO", "Brejinho de Nazar\u00e9", "1703701" }; + rows[5459] = new[] { "TO", "Buriti do Tocantins", "1703800" }; + rows[5460] = new[] { "TO", "Cachoeirinha", "1703826" }; + rows[5461] = new[] { "TO", "Campos Lindos", "1703842" }; + rows[5462] = new[] { "TO", "Cariri do Tocantins", "1703867" }; + rows[5463] = new[] { "TO", "Carmol\u00e2ndia", "1703883" }; + rows[5464] = new[] { "TO", "Carrasco Bonito", "1703891" }; + rows[5465] = new[] { "TO", "Caseara", "1703909" }; + rows[5466] = new[] { "TO", "Centen\u00e1rio", "1704105" }; + rows[5467] = new[] { "TO", "Chapada da Natividade", "1705102" }; + rows[5468] = new[] { "TO", "Chapada de Areia", "1704600" }; + rows[5469] = new[] { "TO", "Colinas do Tocantins", "1705508" }; + rows[5470] = new[] { "TO", "Colm\u00e9ia", "1716703" }; + rows[5471] = new[] { "TO", "Combinado", "1705557" }; + rows[5472] = new[] { "TO", "Concei\u00e7\u00e3o do Tocantins", "1705607" }; + rows[5473] = new[] { "TO", "Couto Magalh\u00e3es", "1706001" }; + rows[5474] = new[] { "TO", "Cristal\u00e2ndia", "1706100" }; + rows[5475] = new[] { "TO", "Crix\u00e1s do Tocantins", "1706258" }; + rows[5476] = new[] { "TO", "Darcin\u00f3polis", "1706506" }; + rows[5477] = new[] { "TO", "Dian\u00f3polis", "1707009" }; + rows[5478] = new[] { "TO", "Divin\u00f3polis do Tocantins", "1707108" }; + rows[5479] = new[] { "TO", "Dois Irm\u00e3os do Tocantins", "1707207" }; + rows[5480] = new[] { "TO", "Duer\u00e9", "1707306" }; + rows[5481] = new[] { "TO", "Esperantina", "1707405" }; + rows[5482] = new[] { "TO", "F\u00e1tima", "1707553" }; + rows[5483] = new[] { "TO", "Figueir\u00f3polis", "1707652" }; + rows[5484] = new[] { "TO", "Filad\u00e9lfia", "1707702" }; + rows[5485] = new[] { "TO", "Formoso do Araguaia", "1708205" }; + rows[5486] = new[] { "TO", "Goianorte", "1708304" }; + rows[5487] = new[] { "TO", "Goiatins", "1709005" }; + rows[5488] = new[] { "TO", "Guara\u00ed", "1709302" }; + rows[5489] = new[] { "TO", "Gurupi", "1709500" }; + rows[5490] = new[] { "TO", "Ipueiras", "1709807" }; + rows[5491] = new[] { "TO", "Itacaj\u00e1", "1710508" }; + rows[5492] = new[] { "TO", "Itaguatins", "1710706" }; + rows[5493] = new[] { "TO", "Itapiratins", "1710904" }; + rows[5494] = new[] { "TO", "Itapor\u00e3 do Tocantins", "1711100" }; + rows[5495] = new[] { "TO", "Ja\u00fa do Tocantins", "1711506" }; + rows[5496] = new[] { "TO", "Juarina", "1711803" }; + rows[5497] = new[] { "TO", "Lagoa da Confus\u00e3o", "1711902" }; + rows[5498] = new[] { "TO", "Lagoa do Tocantins", "1711951" }; + rows[5499] = new[] { "TO", "Lajeado", "1712009" }; + rows[5500] = new[] { "TO", "Lavandeira", "1712157" }; + rows[5501] = new[] { "TO", "Lizarda", "1712405" }; + rows[5502] = new[] { "TO", "Luzin\u00f3polis", "1712454" }; + rows[5503] = new[] { "TO", "Marian\u00f3polis do Tocantins", "1712504" }; + rows[5504] = new[] { "TO", "Mateiros", "1712702" }; + rows[5505] = new[] { "TO", "Mauril\u00e2ndia do Tocantins", "1712801" }; + rows[5506] = new[] { "TO", "Miracema do Tocantins", "1713205" }; + rows[5507] = new[] { "TO", "Miranorte", "1713304" }; + rows[5508] = new[] { "TO", "Monte do Carmo", "1713601" }; + rows[5509] = new[] { "TO", "Monte Santo do Tocantins", "1713700" }; + rows[5510] = new[] { "TO", "Muricil\u00e2ndia", "1713957" }; + rows[5511] = new[] { "TO", "Natividade", "1714203" }; + rows[5512] = new[] { "TO", "Nazar\u00e9", "1714302" }; + rows[5513] = new[] { "TO", "Nova Olinda", "1714880" }; + rows[5514] = new[] { "TO", "Nova Rosal\u00e2ndia", "1715002" }; + rows[5515] = new[] { "TO", "Novo Acordo", "1715101" }; + rows[5516] = new[] { "TO", "Novo Alegre", "1715150" }; + rows[5517] = new[] { "TO", "Novo Jardim", "1715259" }; + rows[5518] = new[] { "TO", "Oliveira de F\u00e1tima", "1715507" }; + rows[5519] = new[] { "TO", "Palmas", "1721000" }; + rows[5520] = new[] { "TO", "Palmeirante", "1715705" }; + rows[5521] = new[] { "TO", "Palmeiras do Tocantins", "1713809" }; + rows[5522] = new[] { "TO", "Palmeir\u00f3polis", "1715754" }; + rows[5523] = new[] { "TO", "Para\u00edso do Tocantins", "1716109" }; + rows[5524] = new[] { "TO", "Paran\u00e3", "1716208" }; + rows[5525] = new[] { "TO", "Pau D'Arco", "1716307" }; + rows[5526] = new[] { "TO", "Pedro Afonso", "1716505" }; + rows[5527] = new[] { "TO", "Peixe", "1716604" }; + rows[5528] = new[] { "TO", "Pequizeiro", "1716653" }; + rows[5529] = new[] { "TO", "Pindorama do Tocantins", "1717008" }; + rows[5530] = new[] { "TO", "Piraqu\u00ea", "1717206" }; + rows[5531] = new[] { "TO", "Pium", "1717503" }; + rows[5532] = new[] { "TO", "Ponte Alta do Bom Jesus", "1717800" }; + rows[5533] = new[] { "TO", "Ponte Alta do Tocantins", "1717909" }; + rows[5534] = new[] { "TO", "Porto Alegre do Tocantins", "1718006" }; + rows[5535] = new[] { "TO", "Porto Nacional", "1718204" }; + rows[5536] = new[] { "TO", "Praia Norte", "1718303" }; + rows[5537] = new[] { "TO", "Presidente Kennedy", "1718402" }; + rows[5538] = new[] { "TO", "Pugmil", "1718451" }; + rows[5539] = new[] { "TO", "Recursol\u00e2ndia", "1718501" }; + rows[5540] = new[] { "TO", "Riachinho", "1718550" }; + rows[5541] = new[] { "TO", "Rio da Concei\u00e7\u00e3o", "1718659" }; + rows[5542] = new[] { "TO", "Rio dos Bois", "1718709" }; + rows[5543] = new[] { "TO", "Rio Sono", "1718758" }; + rows[5544] = new[] { "TO", "Sampaio", "1718808" }; + rows[5545] = new[] { "TO", "Sandol\u00e2ndia", "1718840" }; + rows[5546] = new[] { "TO", "Santa F\u00e9 do Araguaia", "1718865" }; + rows[5547] = new[] { "TO", "Santa Maria do Tocantins", "1718881" }; + rows[5548] = new[] { "TO", "Santa Rita do Tocantins", "1718899" }; + rows[5549] = new[] { "TO", "Santa Rosa do Tocantins", "1718907" }; + rows[5550] = new[] { "TO", "Santa Tereza do Tocantins", "1719004" }; + rows[5551] = new[] { "TO", "Santa Terezinha do Tocantins", "1720002" }; + rows[5552] = new[] { "TO", "S\u00e3o Bento do Tocantins", "1720101" }; + rows[5553] = new[] { "TO", "S\u00e3o F\u00e9lix do Tocantins", "1720150" }; + rows[5554] = new[] { "TO", "S\u00e3o Miguel do Tocantins", "1720200" }; + rows[5555] = new[] { "TO", "S\u00e3o Salvador do Tocantins", "1720259" }; + rows[5556] = new[] { "TO", "S\u00e3o Sebasti\u00e3o do Tocantins", "1720309" }; + rows[5557] = new[] { "TO", "S\u00e3o Val\u00e9rio", "1720499" }; + rows[5558] = new[] { "TO", "Silvan\u00f3polis", "1720655" }; + rows[5559] = new[] { "TO", "S\u00edtio Novo do Tocantins", "1720804" }; + rows[5560] = new[] { "TO", "Sucupira", "1720853" }; + rows[5561] = new[] { "TO", "Taboc\u00e3o", "1708254" }; + rows[5562] = new[] { "TO", "Taguatinga", "1720903" }; + rows[5563] = new[] { "TO", "Taipas do Tocantins", "1720937" }; + rows[5564] = new[] { "TO", "Talism\u00e3", "1720978" }; + rows[5565] = new[] { "TO", "Tocant\u00ednia", "1721109" }; + rows[5566] = new[] { "TO", "Tocantin\u00f3polis", "1721208" }; + rows[5567] = new[] { "TO", "Tupirama", "1721257" }; + rows[5568] = new[] { "TO", "Tupiratins", "1721307" }; + rows[5569] = new[] { "TO", "Wanderl\u00e2ndia", "1722081" }; + rows[5570] = new[] { "TO", "Xambio\u00e1", "1722107" }; + } + + private static int[][] MunicipalitiesGroups() + { + var groups = new int[27][]; + MunicipalitiesGroups0(groups); + MunicipalitiesGroups1(groups); + MunicipalitiesGroups2(groups); + MunicipalitiesGroups3(groups); + MunicipalitiesGroups4(groups); + MunicipalitiesGroups5(groups); + return groups; + } + + private static void MunicipalitiesGroups0(int[][] groups) + { + groups[0] = new[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21 }; + groups[1] = new[] { 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123 }; + groups[2] = new[] { 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139 }; + groups[3] = new[] { 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201 }; + groups[4] = new[] { 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, 443, 444, 445, 446, 447, 448, 449, 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, 495, 496, 497, 498, 499, 500, 501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, 519, 520, 521, 522, 523, 524, 525, 526, 527, 528, 529, 530, 531, 532, 533, 534, 535, 536, 537, 538, 539, 540, 541, 542, 543, 544, 545, 546, 547, 548, 549, 550, 551, 552, 553, 554, 555, 556, 557, 558, 559, 560, 561, 562, 563, 564, 565, 566, 567, 568, 569, 570, 571, 572, 573, 574, 575, 576, 577, 578, 579, 580, 581, 582, 583, 584, 585, 586, 587, 588, 589, 590, 591, 592, 593, 594, 595, 596, 597, 598, 599, 600, 601, 602, 603, 604, 605, 606, 607, 608, 609, 610, 611, 612, 613, 614, 615, 616, 617, 618 }; + } + + private static void MunicipalitiesGroups1(int[][] groups) + { + groups[5] = new[] { 619, 620, 621, 622, 623, 624, 625, 626, 627, 628, 629, 630, 631, 632, 633, 634, 635, 636, 637, 638, 639, 640, 641, 642, 643, 644, 645, 646, 647, 648, 649, 650, 651, 652, 653, 654, 655, 656, 657, 658, 659, 660, 661, 662, 663, 664, 665, 666, 667, 668, 669, 670, 671, 672, 673, 674, 675, 676, 677, 678, 679, 680, 681, 682, 683, 684, 685, 686, 687, 688, 689, 690, 691, 692, 693, 694, 695, 696, 697, 698, 699, 700, 701, 702, 703, 704, 705, 706, 707, 708, 709, 710, 711, 712, 713, 714, 715, 716, 717, 718, 719, 720, 721, 722, 723, 724, 725, 726, 727, 728, 729, 730, 731, 732, 733, 734, 735, 736, 737, 738, 739, 740, 741, 742, 743, 744, 745, 746, 747, 748, 749, 750, 751, 752, 753, 754, 755, 756, 757, 758, 759, 760, 761, 762, 763, 764, 765, 766, 767, 768, 769, 770, 771, 772, 773, 774, 775, 776, 777, 778, 779, 780, 781, 782, 783, 784, 785, 786, 787, 788, 789, 790, 791, 792, 793, 794, 795, 796, 797, 798, 799, 800, 801, 802 }; + groups[6] = new[] { 803 }; + groups[7] = new[] { 804, 805, 806, 807, 808, 809, 810, 811, 812, 813, 814, 815, 816, 817, 818, 819, 820, 821, 822, 823, 824, 825, 826, 827, 828, 829, 830, 831, 832, 833, 834, 835, 836, 837, 838, 839, 840, 841, 842, 843, 844, 845, 846, 847, 848, 849, 850, 851, 852, 853, 854, 855, 856, 857, 858, 859, 860, 861, 862, 863, 864, 865, 866, 867, 868, 869, 870, 871, 872, 873, 874, 875, 876, 877, 878, 879, 880, 881 }; + groups[8] = new[] { 882, 883, 884, 885, 886, 887, 888, 889, 890, 891, 892, 893, 894, 895, 896, 897, 898, 899, 900, 901, 902, 903, 904, 905, 906, 907, 908, 909, 910, 911, 912, 913, 914, 915, 916, 917, 918, 919, 920, 921, 922, 923, 924, 925, 926, 927, 928, 929, 930, 931, 932, 933, 934, 935, 936, 937, 938, 939, 940, 941, 942, 943, 944, 945, 946, 947, 948, 949, 950, 951, 952, 953, 954, 955, 956, 957, 958, 959, 960, 961, 962, 963, 964, 965, 966, 967, 968, 969, 970, 971, 972, 973, 974, 975, 976, 977, 978, 979, 980, 981, 982, 983, 984, 985, 986, 987, 988, 989, 990, 991, 992, 993, 994, 995, 996, 997, 998, 999, 1000, 1001, 1002, 1003, 1004, 1005, 1006, 1007, 1008, 1009, 1010, 1011, 1012, 1013, 1014, 1015, 1016, 1017, 1018, 1019, 1020, 1021, 1022, 1023, 1024, 1025, 1026, 1027, 1028, 1029, 1030, 1031, 1032, 1033, 1034, 1035, 1036, 1037, 1038, 1039, 1040, 1041, 1042, 1043, 1044, 1045, 1046, 1047, 1048, 1049, 1050, 1051, 1052, 1053, 1054, 1055, 1056, 1057, 1058, 1059, 1060, 1061, 1062, 1063, 1064, 1065, 1066, 1067, 1068, 1069, 1070, 1071, 1072, 1073, 1074, 1075, 1076, 1077, 1078, 1079, 1080, 1081, 1082, 1083, 1084, 1085, 1086, 1087, 1088, 1089, 1090, 1091, 1092, 1093, 1094, 1095, 1096, 1097, 1098, 1099, 1100, 1101, 1102, 1103, 1104, 1105, 1106, 1107, 1108, 1109, 1110, 1111, 1112, 1113, 1114, 1115, 1116, 1117, 1118, 1119, 1120, 1121, 1122, 1123, 1124, 1125, 1126, 1127 }; + groups[9] = new[] { 1128, 1129, 1130, 1131, 1132, 1133, 1134, 1135, 1136, 1137, 1138, 1139, 1140, 1141, 1142, 1143, 1144, 1145, 1146, 1147, 1148, 1149, 1150, 1151, 1152, 1153, 1154, 1155, 1156, 1157, 1158, 1159, 1160, 1161, 1162, 1163, 1164, 1165, 1166, 1167, 1168, 1169, 1170, 1171, 1172, 1173, 1174, 1175, 1176, 1177, 1178, 1179, 1180, 1181, 1182, 1183, 1184, 1185, 1186, 1187, 1188, 1189, 1190, 1191, 1192, 1193, 1194, 1195, 1196, 1197, 1198, 1199, 1200, 1201, 1202, 1203, 1204, 1205, 1206, 1207, 1208, 1209, 1210, 1211, 1212, 1213, 1214, 1215, 1216, 1217, 1218, 1219, 1220, 1221, 1222, 1223, 1224, 1225, 1226, 1227, 1228, 1229, 1230, 1231, 1232, 1233, 1234, 1235, 1236, 1237, 1238, 1239, 1240, 1241, 1242, 1243, 1244, 1245, 1246, 1247, 1248, 1249, 1250, 1251, 1252, 1253, 1254, 1255, 1256, 1257, 1258, 1259, 1260, 1261, 1262, 1263, 1264, 1265, 1266, 1267, 1268, 1269, 1270, 1271, 1272, 1273, 1274, 1275, 1276, 1277, 1278, 1279, 1280, 1281, 1282, 1283, 1284, 1285, 1286, 1287, 1288, 1289, 1290, 1291, 1292, 1293, 1294, 1295, 1296, 1297, 1298, 1299, 1300, 1301, 1302, 1303, 1304, 1305, 1306, 1307, 1308, 1309, 1310, 1311, 1312, 1313, 1314, 1315, 1316, 1317, 1318, 1319, 1320, 1321, 1322, 1323, 1324, 1325, 1326, 1327, 1328, 1329, 1330, 1331, 1332, 1333, 1334, 1335, 1336, 1337, 1338, 1339, 1340, 1341, 1342, 1343, 1344 }; + } + + private static void MunicipalitiesGroups2(int[][] groups) + { + groups[10] = new[] { 1345, 1346, 1347, 1348, 1349, 1350, 1351, 1352, 1353, 1354, 1355, 1356, 1357, 1358, 1359, 1360, 1361, 1362, 1363, 1364, 1365, 1366, 1367, 1368, 1369, 1370, 1371, 1372, 1373, 1374, 1375, 1376, 1377, 1378, 1379, 1380, 1381, 1382, 1383, 1384, 1385, 1386, 1387, 1388, 1389, 1390, 1391, 1392, 1393, 1394, 1395, 1396, 1397, 1398, 1399, 1400, 1401, 1402, 1403, 1404, 1405, 1406, 1407, 1408, 1409, 1410, 1411, 1412, 1413, 1414, 1415, 1416, 1417, 1418, 1419, 1420, 1421, 1422, 1423, 1424, 1425, 1426, 1427, 1428, 1429, 1430, 1431, 1432, 1433, 1434, 1435, 1436, 1437, 1438, 1439, 1440, 1441, 1442, 1443, 1444, 1445, 1446, 1447, 1448, 1449, 1450, 1451, 1452, 1453, 1454, 1455, 1456, 1457, 1458, 1459, 1460, 1461, 1462, 1463, 1464, 1465, 1466, 1467, 1468, 1469, 1470, 1471, 1472, 1473, 1474, 1475, 1476, 1477, 1478, 1479, 1480, 1481, 1482, 1483, 1484, 1485, 1486 }; + groups[11] = new[] { 1487, 1488, 1489, 1490, 1491, 1492, 1493, 1494, 1495, 1496, 1497, 1498, 1499, 1500, 1501, 1502, 1503, 1504, 1505, 1506, 1507, 1508, 1509, 1510, 1511, 1512, 1513, 1514, 1515, 1516, 1517, 1518, 1519, 1520, 1521, 1522, 1523, 1524, 1525, 1526, 1527, 1528, 1529, 1530, 1531, 1532, 1533, 1534, 1535, 1536, 1537, 1538, 1539, 1540, 1541, 1542, 1543, 1544, 1545, 1546, 1547, 1548, 1549, 1550, 1551, 1552, 1553, 1554, 1555, 1556, 1557, 1558, 1559, 1560, 1561, 1562, 1563, 1564, 1565 }; + groups[12] = new[] { 1566, 1567, 1568, 1569, 1570, 1571, 1572, 1573, 1574, 1575, 1576, 1577, 1578, 1579, 1580, 1581, 1582, 1583, 1584, 1585, 1586, 1587, 1588, 1589, 1590, 1591, 1592, 1593, 1594, 1595, 1596, 1597, 1598, 1599, 1600, 1601, 1602, 1603, 1604, 1605, 1606, 1607, 1608, 1609, 1610, 1611, 1612, 1613, 1614, 1615, 1616, 1617, 1618, 1619, 1620, 1621, 1622, 1623, 1624, 1625, 1626, 1627, 1628, 1629, 1630, 1631, 1632, 1633, 1634, 1635, 1636, 1637, 1638, 1639, 1640, 1641, 1642, 1643, 1644, 1645, 1646, 1647, 1648, 1649, 1650, 1651, 1652, 1653, 1654, 1655, 1656, 1657, 1658, 1659, 1660, 1661, 1662, 1663, 1664, 1665, 1666, 1667, 1668, 1669, 1670, 1671, 1672, 1673, 1674, 1675, 1676, 1677, 1678, 1679, 1680, 1681, 1682, 1683, 1684, 1685, 1686, 1687, 1688, 1689, 1690, 1691, 1692, 1693, 1694, 1695, 1696, 1697, 1698, 1699, 1700, 1701, 1702, 1703, 1704, 1705, 1706, 1707, 1708, 1709, 1710, 1711, 1712, 1713, 1714, 1715, 1716, 1717, 1718, 1719, 1720, 1721, 1722, 1723, 1724, 1725, 1726, 1727, 1728, 1729, 1730, 1731, 1732, 1733, 1734, 1735, 1736, 1737, 1738, 1739, 1740, 1741, 1742, 1743, 1744, 1745, 1746, 1747, 1748, 1749, 1750, 1751, 1752, 1753, 1754, 1755, 1756, 1757, 1758, 1759, 1760, 1761, 1762, 1763, 1764, 1765, 1766, 1767, 1768, 1769, 1770, 1771, 1772, 1773, 1774, 1775, 1776, 1777, 1778, 1779, 1780, 1781, 1782, 1783, 1784, 1785, 1786, 1787, 1788, 1789, 1790, 1791, 1792, 1793, 1794, 1795, 1796, 1797, 1798, 1799, 1800, 1801, 1802, 1803, 1804, 1805, 1806, 1807, 1808, 1809, 1810, 1811, 1812, 1813, 1814, 1815, 1816, 1817, 1818, 1819, 1820, 1821, 1822, 1823, 1824, 1825, 1826, 1827, 1828, 1829, 1830, 1831, 1832, 1833, 1834, 1835, 1836, 1837, 1838, 1839, 1840, 1841, 1842, 1843, 1844, 1845, 1846, 1847, 1848, 1849, 1850, 1851, 1852, 1853, 1854, 1855, 1856, 1857, 1858, 1859, 1860, 1861, 1862, 1863, 1864, 1865, 1866, 1867, 1868, 1869, 1870, 1871, 1872, 1873, 1874, 1875, 1876, 1877, 1878, 1879, 1880, 1881, 1882, 1883, 1884, 1885, 1886, 1887, 1888, 1889, 1890, 1891, 1892, 1893, 1894, 1895, 1896, 1897, 1898, 1899, 1900, 1901, 1902, 1903, 1904, 1905, 1906, 1907, 1908, 1909, 1910, 1911, 1912, 1913, 1914, 1915, 1916, 1917, 1918, 1919, 1920, 1921, 1922, 1923, 1924, 1925, 1926, 1927, 1928, 1929, 1930, 1931, 1932, 1933, 1934, 1935, 1936, 1937, 1938, 1939, 1940, 1941, 1942, 1943, 1944, 1945, 1946, 1947, 1948, 1949, 1950, 1951, 1952, 1953, 1954, 1955, 1956, 1957, 1958, 1959, 1960, 1961, 1962, 1963, 1964, 1965, 1966, 1967, 1968, 1969, 1970, 1971, 1972, 1973, 1974, 1975, 1976, 1977, 1978, 1979, 1980, 1981, 1982, 1983, 1984, 1985, 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020, 2021, 2022, 2023, 2024, 2025, 2026, 2027, 2028, 2029, 2030, 2031, 2032, 2033, 2034, 2035, 2036, 2037, 2038, 2039, 2040, 2041, 2042, 2043, 2044, 2045, 2046, 2047, 2048, 2049, 2050, 2051, 2052, 2053, 2054, 2055, 2056, 2057, 2058, 2059, 2060, 2061, 2062, 2063, 2064, 2065, 2066, 2067, 2068, 2069, 2070, 2071, 2072, 2073, 2074, 2075, 2076, 2077, 2078, 2079, 2080, 2081, 2082, 2083, 2084, 2085, 2086, 2087, 2088, 2089, 2090, 2091, 2092, 2093, 2094, 2095, 2096, 2097, 2098, 2099, 2100, 2101, 2102, 2103, 2104, 2105, 2106, 2107, 2108, 2109, 2110, 2111, 2112, 2113, 2114, 2115, 2116, 2117, 2118, 2119, 2120, 2121, 2122, 2123, 2124, 2125, 2126, 2127, 2128, 2129, 2130, 2131, 2132, 2133, 2134, 2135, 2136, 2137, 2138, 2139, 2140, 2141, 2142, 2143, 2144, 2145, 2146, 2147, 2148, 2149, 2150, 2151, 2152, 2153, 2154, 2155, 2156, 2157, 2158, 2159, 2160, 2161, 2162, 2163, 2164, 2165, 2166, 2167, 2168, 2169, 2170, 2171, 2172, 2173, 2174, 2175, 2176, 2177, 2178, 2179, 2180, 2181, 2182, 2183, 2184, 2185, 2186, 2187, 2188, 2189, 2190, 2191, 2192, 2193, 2194, 2195, 2196, 2197, 2198, 2199, 2200, 2201, 2202, 2203, 2204, 2205, 2206, 2207, 2208, 2209, 2210, 2211, 2212, 2213, 2214, 2215, 2216, 2217, 2218, 2219, 2220, 2221, 2222, 2223, 2224, 2225, 2226, 2227, 2228, 2229, 2230, 2231, 2232, 2233, 2234, 2235, 2236, 2237, 2238, 2239, 2240, 2241, 2242, 2243, 2244, 2245, 2246, 2247, 2248, 2249, 2250, 2251, 2252, 2253, 2254, 2255, 2256, 2257, 2258, 2259, 2260, 2261, 2262, 2263, 2264, 2265, 2266, 2267, 2268, 2269, 2270, 2271, 2272, 2273, 2274, 2275, 2276, 2277, 2278, 2279, 2280, 2281, 2282, 2283, 2284, 2285, 2286, 2287, 2288, 2289, 2290, 2291, 2292, 2293, 2294, 2295, 2296, 2297, 2298, 2299, 2300, 2301, 2302, 2303, 2304, 2305, 2306, 2307, 2308, 2309, 2310, 2311, 2312, 2313, 2314, 2315, 2316, 2317, 2318, 2319, 2320, 2321, 2322, 2323, 2324, 2325, 2326, 2327, 2328, 2329, 2330, 2331, 2332, 2333, 2334, 2335, 2336, 2337, 2338, 2339, 2340, 2341, 2342, 2343, 2344, 2345, 2346, 2347, 2348, 2349, 2350, 2351, 2352, 2353, 2354, 2355, 2356, 2357, 2358, 2359, 2360, 2361, 2362, 2363, 2364, 2365, 2366, 2367, 2368, 2369, 2370, 2371, 2372, 2373, 2374, 2375, 2376, 2377, 2378, 2379, 2380, 2381, 2382, 2383, 2384, 2385, 2386, 2387, 2388, 2389, 2390, 2391, 2392, 2393, 2394, 2395, 2396, 2397, 2398, 2399, 2400, 2401, 2402, 2403, 2404, 2405, 2406, 2407, 2408, 2409, 2410, 2411, 2412, 2413, 2414, 2415, 2416, 2417, 2418 }; + groups[13] = new[] { 2419, 2420, 2421, 2422, 2423, 2424, 2425, 2426, 2427, 2428, 2429, 2430, 2431, 2432, 2433, 2434, 2435, 2436, 2437, 2438, 2439, 2440, 2441, 2442, 2443, 2444, 2445, 2446, 2447, 2448, 2449, 2450, 2451, 2452, 2453, 2454, 2455, 2456, 2457, 2458, 2459, 2460, 2461, 2462, 2463, 2464, 2465, 2466, 2467, 2468, 2469, 2470, 2471, 2472, 2473, 2474, 2475, 2476, 2477, 2478, 2479, 2480, 2481, 2482, 2483, 2484, 2485, 2486, 2487, 2488, 2489, 2490, 2491, 2492, 2493, 2494, 2495, 2496, 2497, 2498, 2499, 2500, 2501, 2502, 2503, 2504, 2505, 2506, 2507, 2508, 2509, 2510, 2511, 2512, 2513, 2514, 2515, 2516, 2517, 2518, 2519, 2520, 2521, 2522, 2523, 2524, 2525, 2526, 2527, 2528, 2529, 2530, 2531, 2532, 2533, 2534, 2535, 2536, 2537, 2538, 2539, 2540, 2541, 2542, 2543, 2544, 2545, 2546, 2547, 2548, 2549, 2550, 2551, 2552, 2553, 2554, 2555, 2556, 2557, 2558, 2559, 2560, 2561, 2562 }; + groups[14] = new[] { 2563, 2564, 2565, 2566, 2567, 2568, 2569, 2570, 2571, 2572, 2573, 2574, 2575, 2576, 2577, 2578, 2579, 2580, 2581, 2582, 2583, 2584, 2585, 2586, 2587, 2588, 2589, 2590, 2591, 2592, 2593, 2594, 2595, 2596, 2597, 2598, 2599, 2600, 2601, 2602, 2603, 2604, 2605, 2606, 2607, 2608, 2609, 2610, 2611, 2612, 2613, 2614, 2615, 2616, 2617, 2618, 2619, 2620, 2621, 2622, 2623, 2624, 2625, 2626, 2627, 2628, 2629, 2630, 2631, 2632, 2633, 2634, 2635, 2636, 2637, 2638, 2639, 2640, 2641, 2642, 2643, 2644, 2645, 2646, 2647, 2648, 2649, 2650, 2651, 2652, 2653, 2654, 2655, 2656, 2657, 2658, 2659, 2660, 2661, 2662, 2663, 2664, 2665, 2666, 2667, 2668, 2669, 2670, 2671, 2672, 2673, 2674, 2675, 2676, 2677, 2678, 2679, 2680, 2681, 2682, 2683, 2684, 2685, 2686, 2687, 2688, 2689, 2690, 2691, 2692, 2693, 2694, 2695, 2696, 2697, 2698, 2699, 2700, 2701, 2702, 2703, 2704, 2705, 2706, 2707, 2708, 2709, 2710, 2711, 2712, 2713, 2714, 2715, 2716, 2717, 2718, 2719, 2720, 2721, 2722, 2723, 2724, 2725, 2726, 2727, 2728, 2729, 2730, 2731, 2732, 2733, 2734, 2735, 2736, 2737, 2738, 2739, 2740, 2741, 2742, 2743, 2744, 2745, 2746, 2747, 2748, 2749, 2750, 2751, 2752, 2753, 2754, 2755, 2756, 2757, 2758, 2759, 2760, 2761, 2762, 2763, 2764, 2765, 2766, 2767, 2768, 2769, 2770, 2771, 2772, 2773, 2774, 2775, 2776, 2777, 2778, 2779, 2780, 2781, 2782, 2783, 2784, 2785 }; + } + + private static void MunicipalitiesGroups3(int[][] groups) + { + groups[15] = new[] { 2786, 2787, 2788, 2789, 2790, 2791, 2792, 2793, 2794, 2795, 2796, 2797, 2798, 2799, 2800, 2801, 2802, 2803, 2804, 2805, 2806, 2807, 2808, 2809, 2810, 2811, 2812, 2813, 2814, 2815, 2816, 2817, 2818, 2819, 2820, 2821, 2822, 2823, 2824, 2825, 2826, 2827, 2828, 2829, 2830, 2831, 2832, 2833, 2834, 2835, 2836, 2837, 2838, 2839, 2840, 2841, 2842, 2843, 2844, 2845, 2846, 2847, 2848, 2849, 2850, 2851, 2852, 2853, 2854, 2855, 2856, 2857, 2858, 2859, 2860, 2861, 2862, 2863, 2864, 2865, 2866, 2867, 2868, 2869, 2870, 2871, 2872, 2873, 2874, 2875, 2876, 2877, 2878, 2879, 2880, 2881, 2882, 2883, 2884, 2885, 2886, 2887, 2888, 2889, 2890, 2891, 2892, 2893, 2894, 2895, 2896, 2897, 2898, 2899, 2900, 2901, 2902, 2903, 2904, 2905, 2906, 2907, 2908, 2909, 2910, 2911, 2912, 2913, 2914, 2915, 2916, 2917, 2918, 2919, 2920, 2921, 2922, 2923, 2924, 2925, 2926, 2927, 2928, 2929, 2930, 2931, 2932, 2933, 2934, 2935, 2936, 2937, 2938, 2939, 2940, 2941, 2942, 2943, 2944, 2945, 2946, 2947, 2948, 2949, 2950, 2951, 2952, 2953, 2954, 2955, 2956, 2957, 2958, 2959, 2960, 2961, 2962, 2963, 2964, 2965, 2966, 2967, 2968, 2969, 2970, 2971, 2972, 2973, 2974, 2975, 2976, 2977, 2978, 2979, 2980, 2981, 2982, 2983, 2984, 2985, 2986, 2987, 2988, 2989, 2990, 2991, 2992, 2993, 2994, 2995, 2996, 2997, 2998, 2999, 3000, 3001, 3002, 3003, 3004, 3005, 3006, 3007, 3008, 3009, 3010, 3011, 3012, 3013, 3014, 3015, 3016, 3017, 3018, 3019, 3020, 3021, 3022, 3023, 3024, 3025, 3026, 3027, 3028, 3029, 3030, 3031, 3032, 3033, 3034, 3035, 3036, 3037, 3038, 3039, 3040, 3041, 3042, 3043, 3044, 3045, 3046, 3047, 3048, 3049, 3050, 3051, 3052, 3053, 3054, 3055, 3056, 3057, 3058, 3059, 3060, 3061, 3062, 3063, 3064, 3065, 3066, 3067, 3068, 3069, 3070, 3071, 3072, 3073, 3074, 3075, 3076, 3077, 3078, 3079, 3080, 3081, 3082, 3083, 3084, 3085, 3086, 3087, 3088, 3089, 3090, 3091, 3092, 3093, 3094, 3095, 3096, 3097, 3098, 3099, 3100, 3101, 3102, 3103, 3104, 3105, 3106, 3107, 3108, 3109, 3110, 3111, 3112, 3113, 3114, 3115, 3116, 3117, 3118, 3119, 3120, 3121, 3122, 3123, 3124, 3125, 3126, 3127, 3128, 3129, 3130, 3131, 3132, 3133, 3134, 3135, 3136, 3137, 3138, 3139, 3140, 3141, 3142, 3143, 3144, 3145, 3146, 3147, 3148, 3149, 3150, 3151, 3152, 3153, 3154, 3155, 3156, 3157, 3158, 3159, 3160, 3161, 3162, 3163, 3164, 3165, 3166, 3167, 3168, 3169, 3170, 3171, 3172, 3173, 3174, 3175, 3176, 3177, 3178, 3179, 3180, 3181, 3182, 3183, 3184 }; + groups[16] = new[] { 3185, 3186, 3187, 3188, 3189, 3190, 3191, 3192, 3193, 3194, 3195, 3196, 3197, 3198, 3199, 3200, 3201, 3202, 3203, 3204, 3205, 3206, 3207, 3208, 3209, 3210, 3211, 3212, 3213, 3214, 3215, 3216, 3217, 3218, 3219, 3220, 3221, 3222, 3223, 3224, 3225, 3226, 3227, 3228, 3229, 3230, 3231, 3232, 3233, 3234, 3235, 3236, 3237, 3238, 3239, 3240, 3241, 3242, 3243, 3244, 3245, 3246, 3247, 3248, 3249, 3250, 3251, 3252, 3253, 3254, 3255, 3256, 3257, 3258, 3259, 3260, 3261, 3262, 3263, 3264, 3265, 3266, 3267, 3268, 3269, 3270, 3271, 3272, 3273, 3274, 3275, 3276, 3277, 3278, 3279, 3280, 3281, 3282, 3283, 3284, 3285, 3286, 3287, 3288, 3289, 3290, 3291, 3292, 3293, 3294, 3295, 3296, 3297, 3298, 3299, 3300, 3301, 3302, 3303, 3304, 3305, 3306, 3307, 3308, 3309, 3310, 3311, 3312, 3313, 3314, 3315, 3316, 3317, 3318, 3319, 3320, 3321, 3322, 3323, 3324, 3325, 3326, 3327, 3328, 3329, 3330, 3331, 3332, 3333, 3334, 3335, 3336, 3337, 3338, 3339, 3340, 3341, 3342, 3343, 3344, 3345, 3346, 3347, 3348, 3349, 3350, 3351, 3352, 3353, 3354, 3355, 3356, 3357, 3358, 3359, 3360, 3361, 3362, 3363, 3364, 3365, 3366, 3367, 3368, 3369 }; + groups[17] = new[] { 3370, 3371, 3372, 3373, 3374, 3375, 3376, 3377, 3378, 3379, 3380, 3381, 3382, 3383, 3384, 3385, 3386, 3387, 3388, 3389, 3390, 3391, 3392, 3393, 3394, 3395, 3396, 3397, 3398, 3399, 3400, 3401, 3402, 3403, 3404, 3405, 3406, 3407, 3408, 3409, 3410, 3411, 3412, 3413, 3414, 3415, 3416, 3417, 3418, 3419, 3420, 3421, 3422, 3423, 3424, 3425, 3426, 3427, 3428, 3429, 3430, 3431, 3432, 3433, 3434, 3435, 3436, 3437, 3438, 3439, 3440, 3441, 3442, 3443, 3444, 3445, 3446, 3447, 3448, 3449, 3450, 3451, 3452, 3453, 3454, 3455, 3456, 3457, 3458, 3459, 3460, 3461, 3462, 3463, 3464, 3465, 3466, 3467, 3468, 3469, 3470, 3471, 3472, 3473, 3474, 3475, 3476, 3477, 3478, 3479, 3480, 3481, 3482, 3483, 3484, 3485, 3486, 3487, 3488, 3489, 3490, 3491, 3492, 3493, 3494, 3495, 3496, 3497, 3498, 3499, 3500, 3501, 3502, 3503, 3504, 3505, 3506, 3507, 3508, 3509, 3510, 3511, 3512, 3513, 3514, 3515, 3516, 3517, 3518, 3519, 3520, 3521, 3522, 3523, 3524, 3525, 3526, 3527, 3528, 3529, 3530, 3531, 3532, 3533, 3534, 3535, 3536, 3537, 3538, 3539, 3540, 3541, 3542, 3543, 3544, 3545, 3546, 3547, 3548, 3549, 3550, 3551, 3552, 3553, 3554, 3555, 3556, 3557, 3558, 3559, 3560, 3561, 3562, 3563, 3564, 3565, 3566, 3567, 3568, 3569, 3570, 3571, 3572, 3573, 3574, 3575, 3576, 3577, 3578, 3579, 3580, 3581, 3582, 3583, 3584, 3585, 3586, 3587, 3588, 3589, 3590, 3591, 3592, 3593 }; + groups[18] = new[] { 3594, 3595, 3596, 3597, 3598, 3599, 3600, 3601, 3602, 3603, 3604, 3605, 3606, 3607, 3608, 3609, 3610, 3611, 3612, 3613, 3614, 3615, 3616, 3617, 3618, 3619, 3620, 3621, 3622, 3623, 3624, 3625, 3626, 3627, 3628, 3629, 3630, 3631, 3632, 3633, 3634, 3635, 3636, 3637, 3638, 3639, 3640, 3641, 3642, 3643, 3644, 3645, 3646, 3647, 3648, 3649, 3650, 3651, 3652, 3653, 3654, 3655, 3656, 3657, 3658, 3659, 3660, 3661, 3662, 3663, 3664, 3665, 3666, 3667, 3668, 3669, 3670, 3671, 3672, 3673, 3674, 3675, 3676, 3677, 3678, 3679, 3680, 3681, 3682, 3683, 3684, 3685 }; + groups[19] = new[] { 3686, 3687, 3688, 3689, 3690, 3691, 3692, 3693, 3694, 3695, 3696, 3697, 3698, 3699, 3700, 3701, 3702, 3703, 3704, 3705, 3706, 3707, 3708, 3709, 3710, 3711, 3712, 3713, 3714, 3715, 3716, 3717, 3718, 3719, 3720, 3721, 3722, 3723, 3724, 3725, 3726, 3727, 3728, 3729, 3730, 3731, 3732, 3733, 3734, 3735, 3736, 3737, 3738, 3739, 3740, 3741, 3742, 3743, 3744, 3745, 3746, 3747, 3748, 3749, 3750, 3751, 3752, 3753, 3754, 3755, 3756, 3757, 3758, 3759, 3760, 3761, 3762, 3763, 3764, 3765, 3766, 3767, 3768, 3769, 3770, 3771, 3772, 3773, 3774, 3775, 3776, 3777, 3778, 3779, 3780, 3781, 3782, 3783, 3784, 3785, 3786, 3787, 3788, 3789, 3790, 3791, 3792, 3793, 3794, 3795, 3796, 3797, 3798, 3799, 3800, 3801, 3802, 3803, 3804, 3805, 3806, 3807, 3808, 3809, 3810, 3811, 3812, 3813, 3814, 3815, 3816, 3817, 3818, 3819, 3820, 3821, 3822, 3823, 3824, 3825, 3826, 3827, 3828, 3829, 3830, 3831, 3832, 3833, 3834, 3835, 3836, 3837, 3838, 3839, 3840, 3841, 3842, 3843, 3844, 3845, 3846, 3847, 3848, 3849, 3850, 3851, 3852 }; + } + + private static void MunicipalitiesGroups4(int[][] groups) + { + groups[20] = new[] { 3853, 3854, 3855, 3856, 3857, 3858, 3859, 3860, 3861, 3862, 3863, 3864, 3865, 3866, 3867, 3868, 3869, 3870, 3871, 3872, 3873, 3874, 3875, 3876, 3877, 3878, 3879, 3880, 3881, 3882, 3883, 3884, 3885, 3886, 3887, 3888, 3889, 3890, 3891, 3892, 3893, 3894, 3895, 3896, 3897, 3898, 3899, 3900, 3901, 3902, 3903, 3904, 3905, 3906, 3907, 3908, 3909, 3910, 3911, 3912, 3913, 3914, 3915, 3916, 3917, 3918, 3919, 3920, 3921, 3922, 3923, 3924, 3925, 3926, 3927, 3928, 3929, 3930, 3931, 3932, 3933, 3934, 3935, 3936, 3937, 3938, 3939, 3940, 3941, 3942, 3943, 3944, 3945, 3946, 3947, 3948, 3949, 3950, 3951, 3952, 3953, 3954, 3955, 3956, 3957, 3958, 3959, 3960, 3961, 3962, 3963, 3964, 3965, 3966, 3967, 3968, 3969, 3970, 3971, 3972, 3973, 3974, 3975, 3976, 3977, 3978, 3979, 3980, 3981, 3982, 3983, 3984, 3985, 3986, 3987, 3988, 3989, 3990, 3991, 3992, 3993, 3994, 3995, 3996, 3997, 3998, 3999, 4000, 4001, 4002, 4003, 4004, 4005, 4006, 4007, 4008, 4009, 4010, 4011, 4012, 4013, 4014, 4015, 4016, 4017, 4018, 4019, 4020, 4021, 4022, 4023, 4024, 4025, 4026, 4027, 4028, 4029, 4030, 4031, 4032, 4033, 4034, 4035, 4036, 4037, 4038, 4039, 4040, 4041, 4042, 4043, 4044, 4045, 4046, 4047, 4048, 4049, 4050, 4051, 4052, 4053, 4054, 4055, 4056, 4057, 4058, 4059, 4060, 4061, 4062, 4063, 4064, 4065, 4066, 4067, 4068, 4069, 4070, 4071, 4072, 4073, 4074, 4075, 4076, 4077, 4078, 4079, 4080, 4081, 4082, 4083, 4084, 4085, 4086, 4087, 4088, 4089, 4090, 4091, 4092, 4093, 4094, 4095, 4096, 4097, 4098, 4099, 4100, 4101, 4102, 4103, 4104, 4105, 4106, 4107, 4108, 4109, 4110, 4111, 4112, 4113, 4114, 4115, 4116, 4117, 4118, 4119, 4120, 4121, 4122, 4123, 4124, 4125, 4126, 4127, 4128, 4129, 4130, 4131, 4132, 4133, 4134, 4135, 4136, 4137, 4138, 4139, 4140, 4141, 4142, 4143, 4144, 4145, 4146, 4147, 4148, 4149, 4150, 4151, 4152, 4153, 4154, 4155, 4156, 4157, 4158, 4159, 4160, 4161, 4162, 4163, 4164, 4165, 4166, 4167, 4168, 4169, 4170, 4171, 4172, 4173, 4174, 4175, 4176, 4177, 4178, 4179, 4180, 4181, 4182, 4183, 4184, 4185, 4186, 4187, 4188, 4189, 4190, 4191, 4192, 4193, 4194, 4195, 4196, 4197, 4198, 4199, 4200, 4201, 4202, 4203, 4204, 4205, 4206, 4207, 4208, 4209, 4210, 4211, 4212, 4213, 4214, 4215, 4216, 4217, 4218, 4219, 4220, 4221, 4222, 4223, 4224, 4225, 4226, 4227, 4228, 4229, 4230, 4231, 4232, 4233, 4234, 4235, 4236, 4237, 4238, 4239, 4240, 4241, 4242, 4243, 4244, 4245, 4246, 4247, 4248, 4249, 4250, 4251, 4252, 4253, 4254, 4255, 4256, 4257, 4258, 4259, 4260, 4261, 4262, 4263, 4264, 4265, 4266, 4267, 4268, 4269, 4270, 4271, 4272, 4273, 4274, 4275, 4276, 4277, 4278, 4279, 4280, 4281, 4282, 4283, 4284, 4285, 4286, 4287, 4288, 4289, 4290, 4291, 4292, 4293, 4294, 4295, 4296, 4297, 4298, 4299, 4300, 4301, 4302, 4303, 4304, 4305, 4306, 4307, 4308, 4309, 4310, 4311, 4312, 4313, 4314, 4315, 4316, 4317, 4318, 4319, 4320, 4321, 4322, 4323, 4324, 4325, 4326, 4327, 4328, 4329, 4330, 4331, 4332, 4333, 4334, 4335, 4336, 4337, 4338, 4339, 4340, 4341, 4342, 4343, 4344, 4345, 4346, 4347, 4348, 4349 }; + groups[21] = new[] { 4350, 4351, 4352, 4353, 4354, 4355, 4356, 4357, 4358, 4359, 4360, 4361, 4362, 4363, 4364, 4365, 4366, 4367, 4368, 4369, 4370, 4371, 4372, 4373, 4374, 4375, 4376, 4377, 4378, 4379, 4380, 4381, 4382, 4383, 4384, 4385, 4386, 4387, 4388, 4389, 4390, 4391, 4392, 4393, 4394, 4395, 4396, 4397, 4398, 4399, 4400, 4401 }; + groups[22] = new[] { 4402, 4403, 4404, 4405, 4406, 4407, 4408, 4409, 4410, 4411, 4412, 4413, 4414, 4415, 4416 }; + groups[23] = new[] { 4417, 4418, 4419, 4420, 4421, 4422, 4423, 4424, 4425, 4426, 4427, 4428, 4429, 4430, 4431, 4432, 4433, 4434, 4435, 4436, 4437, 4438, 4439, 4440, 4441, 4442, 4443, 4444, 4445, 4446, 4447, 4448, 4449, 4450, 4451, 4452, 4453, 4454, 4455, 4456, 4457, 4458, 4459, 4460, 4461, 4462, 4463, 4464, 4465, 4466, 4467, 4468, 4469, 4470, 4471, 4472, 4473, 4474, 4475, 4476, 4477, 4478, 4479, 4480, 4481, 4482, 4483, 4484, 4485, 4486, 4487, 4488, 4489, 4490, 4491, 4492, 4493, 4494, 4495, 4496, 4497, 4498, 4499, 4500, 4501, 4502, 4503, 4504, 4505, 4506, 4507, 4508, 4509, 4510, 4511, 4512, 4513, 4514, 4515, 4516, 4517, 4518, 4519, 4520, 4521, 4522, 4523, 4524, 4525, 4526, 4527, 4528, 4529, 4530, 4531, 4532, 4533, 4534, 4535, 4536, 4537, 4538, 4539, 4540, 4541, 4542, 4543, 4544, 4545, 4546, 4547, 4548, 4549, 4550, 4551, 4552, 4553, 4554, 4555, 4556, 4557, 4558, 4559, 4560, 4561, 4562, 4563, 4564, 4565, 4566, 4567, 4568, 4569, 4570, 4571, 4572, 4573, 4574, 4575, 4576, 4577, 4578, 4579, 4580, 4581, 4582, 4583, 4584, 4585, 4586, 4587, 4588, 4589, 4590, 4591, 4592, 4593, 4594, 4595, 4596, 4597, 4598, 4599, 4600, 4601, 4602, 4603, 4604, 4605, 4606, 4607, 4608, 4609, 4610, 4611, 4612, 4613, 4614, 4615, 4616, 4617, 4618, 4619, 4620, 4621, 4622, 4623, 4624, 4625, 4626, 4627, 4628, 4629, 4630, 4631, 4632, 4633, 4634, 4635, 4636, 4637, 4638, 4639, 4640, 4641, 4642, 4643, 4644, 4645, 4646, 4647, 4648, 4649, 4650, 4651, 4652, 4653, 4654, 4655, 4656, 4657, 4658, 4659, 4660, 4661, 4662, 4663, 4664, 4665, 4666, 4667, 4668, 4669, 4670, 4671, 4672, 4673, 4674, 4675, 4676, 4677, 4678, 4679, 4680, 4681, 4682, 4683, 4684, 4685, 4686, 4687, 4688, 4689, 4690, 4691, 4692, 4693, 4694, 4695, 4696, 4697, 4698, 4699, 4700, 4701, 4702, 4703, 4704, 4705, 4706, 4707, 4708, 4709, 4710, 4711 }; + groups[24] = new[] { 4712, 4713, 4714, 4715, 4716, 4717, 4718, 4719, 4720, 4721, 4722, 4723, 4724, 4725, 4726, 4727, 4728, 4729, 4730, 4731, 4732, 4733, 4734, 4735, 4736, 4737, 4738, 4739, 4740, 4741, 4742, 4743, 4744, 4745, 4746, 4747, 4748, 4749, 4750, 4751, 4752, 4753, 4754, 4755, 4756, 4757, 4758, 4759, 4760, 4761, 4762, 4763, 4764, 4765, 4766, 4767, 4768, 4769, 4770, 4771, 4772, 4773, 4774, 4775, 4776, 4777, 4778, 4779, 4780, 4781, 4782, 4783, 4784, 4785, 4786, 4787, 4788, 4789, 4790, 4791, 4792, 4793, 4794, 4795, 4796, 4797, 4798, 4799, 4800, 4801, 4802, 4803, 4804, 4805, 4806, 4807, 4808, 4809, 4810, 4811, 4812, 4813, 4814, 4815, 4816, 4817, 4818, 4819, 4820, 4821, 4822, 4823, 4824, 4825, 4826, 4827, 4828, 4829, 4830, 4831, 4832, 4833, 4834, 4835, 4836, 4837, 4838, 4839, 4840, 4841, 4842, 4843, 4844, 4845, 4846, 4847, 4848, 4849, 4850, 4851, 4852, 4853, 4854, 4855, 4856, 4857, 4858, 4859, 4860, 4861, 4862, 4863, 4864, 4865, 4866, 4867, 4868, 4869, 4870, 4871, 4872, 4873, 4874, 4875, 4876, 4877, 4878, 4879, 4880, 4881, 4882, 4883, 4884, 4885, 4886, 4887, 4888, 4889, 4890, 4891, 4892, 4893, 4894, 4895, 4896, 4897, 4898, 4899, 4900, 4901, 4902, 4903, 4904, 4905, 4906, 4907, 4908, 4909, 4910, 4911, 4912, 4913, 4914, 4915, 4916, 4917, 4918, 4919, 4920, 4921, 4922, 4923, 4924, 4925, 4926, 4927, 4928, 4929, 4930, 4931, 4932, 4933, 4934, 4935, 4936, 4937, 4938, 4939, 4940, 4941, 4942, 4943, 4944, 4945, 4946, 4947, 4948, 4949, 4950, 4951, 4952, 4953, 4954, 4955, 4956, 4957, 4958, 4959, 4960, 4961, 4962, 4963, 4964, 4965, 4966, 4967, 4968, 4969, 4970, 4971, 4972, 4973, 4974, 4975, 4976, 4977, 4978, 4979, 4980, 4981, 4982, 4983, 4984, 4985, 4986, 4987, 4988, 4989, 4990, 4991, 4992, 4993, 4994, 4995, 4996, 4997, 4998, 4999, 5000, 5001, 5002, 5003, 5004, 5005, 5006, 5007, 5008, 5009, 5010, 5011, 5012, 5013, 5014, 5015, 5016, 5017, 5018, 5019, 5020, 5021, 5022, 5023, 5024, 5025, 5026, 5027, 5028, 5029, 5030, 5031, 5032, 5033, 5034, 5035, 5036, 5037, 5038, 5039, 5040, 5041, 5042, 5043, 5044, 5045, 5046, 5047, 5048, 5049, 5050, 5051, 5052, 5053, 5054, 5055, 5056, 5057, 5058, 5059, 5060, 5061, 5062, 5063, 5064, 5065, 5066, 5067, 5068, 5069, 5070, 5071, 5072, 5073, 5074, 5075, 5076, 5077, 5078, 5079, 5080, 5081, 5082, 5083, 5084, 5085, 5086, 5087, 5088, 5089, 5090, 5091, 5092, 5093, 5094, 5095, 5096, 5097, 5098, 5099, 5100, 5101, 5102, 5103, 5104, 5105, 5106, 5107, 5108, 5109, 5110, 5111, 5112, 5113, 5114, 5115, 5116, 5117, 5118, 5119, 5120, 5121, 5122, 5123, 5124, 5125, 5126, 5127, 5128, 5129, 5130, 5131, 5132, 5133, 5134, 5135, 5136, 5137, 5138, 5139, 5140, 5141, 5142, 5143, 5144, 5145, 5146, 5147, 5148, 5149, 5150, 5151, 5152, 5153, 5154, 5155, 5156, 5157, 5158, 5159, 5160, 5161, 5162, 5163, 5164, 5165, 5166, 5167, 5168, 5169, 5170, 5171, 5172, 5173, 5174, 5175, 5176, 5177, 5178, 5179, 5180, 5181, 5182, 5183, 5184, 5185, 5186, 5187, 5188, 5189, 5190, 5191, 5192, 5193, 5194, 5195, 5196, 5197, 5198, 5199, 5200, 5201, 5202, 5203, 5204, 5205, 5206, 5207, 5208, 5209, 5210, 5211, 5212, 5213, 5214, 5215, 5216, 5217, 5218, 5219, 5220, 5221, 5222, 5223, 5224, 5225, 5226, 5227, 5228, 5229, 5230, 5231, 5232, 5233, 5234, 5235, 5236, 5237, 5238, 5239, 5240, 5241, 5242, 5243, 5244, 5245, 5246, 5247, 5248, 5249, 5250, 5251, 5252, 5253, 5254, 5255, 5256, 5257, 5258, 5259, 5260, 5261, 5262, 5263, 5264, 5265, 5266, 5267, 5268, 5269, 5270, 5271, 5272, 5273, 5274, 5275, 5276, 5277, 5278, 5279, 5280, 5281, 5282, 5283, 5284, 5285, 5286, 5287, 5288, 5289, 5290, 5291, 5292, 5293, 5294, 5295, 5296, 5297, 5298, 5299, 5300, 5301, 5302, 5303, 5304, 5305, 5306, 5307, 5308, 5309, 5310, 5311, 5312, 5313, 5314, 5315, 5316, 5317, 5318, 5319, 5320, 5321, 5322, 5323, 5324, 5325, 5326, 5327, 5328, 5329, 5330, 5331, 5332, 5333, 5334, 5335, 5336, 5337, 5338, 5339, 5340, 5341, 5342, 5343, 5344, 5345, 5346, 5347, 5348, 5349, 5350, 5351, 5352, 5353, 5354, 5355, 5356 }; + } + + private static void MunicipalitiesGroups5(int[][] groups) + { + groups[25] = new[] { 5357, 5358, 5359, 5360, 5361, 5362, 5363, 5364, 5365, 5366, 5367, 5368, 5369, 5370, 5371, 5372, 5373, 5374, 5375, 5376, 5377, 5378, 5379, 5380, 5381, 5382, 5383, 5384, 5385, 5386, 5387, 5388, 5389, 5390, 5391, 5392, 5393, 5394, 5395, 5396, 5397, 5398, 5399, 5400, 5401, 5402, 5403, 5404, 5405, 5406, 5407, 5408, 5409, 5410, 5411, 5412, 5413, 5414, 5415, 5416, 5417, 5418, 5419, 5420, 5421, 5422, 5423, 5424, 5425, 5426, 5427, 5428, 5429, 5430, 5431 }; + groups[26] = new[] { 5432, 5433, 5434, 5435, 5436, 5437, 5438, 5439, 5440, 5441, 5442, 5443, 5444, 5445, 5446, 5447, 5448, 5449, 5450, 5451, 5452, 5453, 5454, 5455, 5456, 5457, 5458, 5459, 5460, 5461, 5462, 5463, 5464, 5465, 5466, 5467, 5468, 5469, 5470, 5471, 5472, 5473, 5474, 5475, 5476, 5477, 5478, 5479, 5480, 5481, 5482, 5483, 5484, 5485, 5486, 5487, 5488, 5489, 5490, 5491, 5492, 5493, 5494, 5495, 5496, 5497, 5498, 5499, 5500, 5501, 5502, 5503, 5504, 5505, 5506, 5507, 5508, 5509, 5510, 5511, 5512, 5513, 5514, 5515, 5516, 5517, 5518, 5519, 5520, 5521, 5522, 5523, 5524, 5525, 5526, 5527, 5528, 5529, 5530, 5531, 5532, 5533, 5534, 5535, 5536, 5537, 5538, 5539, 5540, 5541, 5542, 5543, 5544, 5545, 5546, 5547, 5548, 5549, 5550, 5551, 5552, 5553, 5554, 5555, 5556, 5557, 5558, 5559, 5560, 5561, 5562, 5563, 5564, 5565, 5566, 5567, 5568, 5569, 5570 }; + } + + /// + /// Reads one dataset row as a municipality. + /// + public static Municipality RowToMunicipality(System.Collections.Generic.List row) + { + return new Municipality(row[(int) 2L], row[(int) 1L], row[(int) 0L]); + } + + /// + /// Returns Brazilian municipalities published by the IBGE, optionally filtered by state. + /// + /// If `stateCode` is provided, only municipalities of that state are returned. If it is + /// omitted, every municipality of every state is returned, sorted with `localeCompare` in the + /// "pt-BR" locale so accented names land where a Brazilian reader expects them. Every per-state + /// list is sorted the same way. + /// + /// Only an omitted (or `undefined`) `stateCode` asks for the full list: any other value that is + /// not a known state code, `null` and `""` included, returns `[]`. + /// + /// The state code is matched exactly, case included: `getMunicipalities("sp")` returns `[]` where + /// `getMunicipalities("SP")` returns the 645 São Paulo municipalities. + /// + /// @see Official: https://servicodados.ibge.gov.br/api/docs/localidades + /// + public static System.Collections.Generic.List GetMunicipalities(string stateCode = null) + { + System.Collections.Generic.List municipalities = new System.Collections.Generic.List { }; + System.Collections.Generic.List> rows = Runtime.DataAll(MUNICIPALITIES); + if ((stateCode != null)) + { + rows = Runtime.DataRows(MUNICIPALITIES, stateCode); + } + foreach (var row in rows) + { + municipalities.Add(RowToMunicipality(row)); + } + return municipalities; + } + } +} diff --git a/spec/bridge/out/csharp/IsValidCnpjUtility.cs b/spec/bridge/out/csharp/IsValidCnpjUtility.cs new file mode 100644 index 000000000..5edd105b6 --- /dev/null +++ b/spec/bridge/out/csharp/IsValidCnpjUtility.cs @@ -0,0 +1,145 @@ +// Code generated from spec/bridge/source/is-valid-cnpj.ts. DO NOT EDIT. + +namespace BrazilianUtils.Bridge +{ + + + /// Options of `isValidCnpj`. + public sealed class IsValidCnpjOptions + { + /// Which CNPJ format to accept: `1` numeric only, `2` alphanumeric (default: `1`). + public long? Version { get; set; } + } + + /// `isValidCnpj`, written once. + public static class IsValidCnpjUtility + { + private static readonly int[][] CLASS0 = { new[] { 0x30, 0x39 }, new[] { 0x41, 0x5a } }; + private static readonly int[][] CLASS1 = { new[] { 0x9, 0xd }, new[] { 0x20, 0x20 }, new[] { 0x2d, 0x2f }, new[] { 0xa0, 0xa0 }, new[] { 0x1680, 0x1680 }, new[] { 0x2000, 0x200a }, new[] { 0x2028, 0x2029 }, new[] { 0x202f, 0x202f }, new[] { 0x205f, 0x205f }, new[] { 0x3000, 0x3000 }, new[] { 0xfeff, 0xfeff } }; + private static readonly int[][] CLASS2 = { new[] { 0x30, 0x39 } }; + private static readonly int[][] CLASS3 = { new[] { 0x41, 0x5a } }; + private static readonly int[][] CLASS4 = { new[] { 0x30, 0x39 }, new[] { 0x41, 0x5a }, new[] { 0x61, 0x7a } }; + + private static readonly PatternStep[] PATTERN_ALPHANUMERIC_FORMAT = + { + new PatternStep(CLASS0, 2, 2, false), + new PatternStep(CLASS1, 0, -1, false), + new PatternStep(CLASS0, 3, 3, false), + new PatternStep(CLASS1, 0, -1, false), + new PatternStep(CLASS0, 3, 3, false), + new PatternStep(CLASS1, 0, -1, false), + new PatternStep(CLASS0, 4, 4, false), + new PatternStep(CLASS1, 0, -1, false), + new PatternStep(CLASS2, 2, 2, false), + }; + + private static readonly PatternStep[] PATTERN_NUMERIC_FORMAT = + { + new PatternStep(CLASS2, 2, 2, false), + new PatternStep(CLASS1, 0, -1, false), + new PatternStep(CLASS2, 3, 3, false), + new PatternStep(CLASS1, 0, -1, false), + new PatternStep(CLASS2, 3, 3, false), + new PatternStep(CLASS1, 0, -1, false), + new PatternStep(CLASS2, 4, 4, false), + new PatternStep(CLASS1, 0, -1, false), + new PatternStep(CLASS2, 2, 2, false), + }; + + private static readonly long[] FIRST_DIGIT_WEIGHTS = new long[] { 5L, 4L, 3L, 2L, 9L, 8L, 7L, 6L, 5L, 4L, 3L, 2L }; + private static readonly long[] SECOND_DIGIT_WEIGHTS = new long[] { 6L, 5L, 4L, 3L, 2L, 9L, 8L, 7L, 6L, 5L, 4L, 3L, 2L }; + + + + /// + /// Validates if a CNPJ (Cadastro Nacional da Pessoa Jurídica) is valid. + /// + /// Supports both numeric (version 1) and alphanumeric (version 2) CNPJ formats, and accepts the + /// usual mask characters (`.`, `-`, `/`) and whitespace around and between groups. + /// + public static bool IsValidCnpj(string cnpj, IsValidCnpjOptions options = null) + { + long optionsVersion = -1L; + if (options != null && options.Version != null) + { + optionsVersion = options.Version.Value; + } + if (cnpj == null) + { + return false; + } + string trimmed = Runtime.JsTrim(cnpj); + if ((optionsVersion == 2L)) + { + string cleaned = Runtime.KeepClass(CLASS4, cnpj).ToUpperInvariant(); + if (Runtime.ClassHas(CLASS3, cleaned)) + { + if (!Runtime.PatternTest(PATTERN_ALPHANUMERIC_FORMAT, trimmed.ToUpperInvariant())) + { + return false; + } + return HasValidChecksum(cleaned); + } + } + string numeric = Runtime.KeepClass(CLASS2, cnpj); + if (!Runtime.PatternTest(PATTERN_NUMERIC_FORMAT, trimmed)) + { + return false; + } + if (IsRepeated(numeric)) + { + return false; + } + return HasValidChecksum(numeric); + } + + /// + /// Computes one CNPJ check digit from the base and its weight vector. + /// + public static long CheckDigit(string @base, long[] weights) + { + long sum = 0L; + for (long index = 0L; index < (long) weights.Length; index++) + { + sum = (sum + ((Runtime.CodeAt(@base, index) - 48L) * weights[(int) index])); + } + long remainder = (sum % 11L); + if ((remainder < 2L)) + { + return 0L; + } + return (11L - remainder); + } + + /// + /// Whether both check digits of a sanitized 14 character CNPJ match its base. + /// + public static bool HasValidChecksum(string cnpj) + { + if (((Runtime.CodeAt(cnpj, 12L) - 48L) != CheckDigit(cnpj, FIRST_DIGIT_WEIGHTS))) + { + return false; + } + return ((Runtime.CodeAt(cnpj, 13L) - 48L) == CheckDigit(cnpj, SECOND_DIGIT_WEIGHTS)); + } + + /// + /// Whether every character of the value is the same one. + /// + public static bool IsRepeated(string @value) + { + if (((long) @value.Length == 0L)) + { + return false; + } + for (long index = 1L; index < (long) @value.Length; index++) + { + if ((Runtime.CodeAt(@value, index) != Runtime.CodeAt(@value, 0L))) + { + return false; + } + } + return true; + } + } +} diff --git a/spec/bridge/out/csharp/Runtime.cs b/spec/bridge/out/csharp/Runtime.cs new file mode 100644 index 000000000..14fac3ad7 --- /dev/null +++ b/spec/bridge/out/csharp/Runtime.cs @@ -0,0 +1,526 @@ +// The portable runtime for the C# target. +// +// C# strings are UTF-16, the same as JavaScript's, so indexes and lengths already line up; +// what is here is the rest: the compiled classes and patterns, and the JavaScript specific +// trimming rules. + +using System; +using System.Text; + +namespace BrazilianUtils.Bridge +{ + /// One step of a compiled pattern: repeat a class between Min and Max times. + public sealed class PatternStep + { + public int[][] CharClass { get; } + public long Min { get; } + public long Max { get; } + public bool Capture { get; } + + public PatternStep(int[][] charClass, long min, long max, bool capture) + { + CharClass = charClass; + Min = min; + Max = max; + Capture = capture; + } + } + + /// Helpers shared by the generated utilities. + public static class Runtime + { + /// The code points JavaScript's trim() strips; Trim() is a different set. + private static readonly int[][] JsWhitespace = + { + new[] { 0x09, 0x0d }, new[] { 0x20, 0x20 }, new[] { 0xa0, 0xa0 }, + new[] { 0x1680, 0x1680 }, new[] { 0x2000, 0x200a }, new[] { 0x2028, 0x2029 }, + new[] { 0x202f, 0x202f }, new[] { 0x205f, 0x205f }, new[] { 0x3000, 0x3000 }, + new[] { 0xfeff, 0xfeff } + }; + + /// Whether a code point belongs to a class. + public static bool InClass(int[][] charClass, int code) + { + foreach (var span in charClass) + { + if (code >= span[0] && code <= span[1]) + { + return true; + } + } + + return false; + } + + /// Reads one code unit, or -1 when the index is out of range. + public static long CodeAt(string value, long index) + { + if (index < 0 || index >= value.Length) + { + return -1; + } + + return value[(int)index]; + } + + /// Takes the code units between two indexes, clamping like JavaScript's slice. + public static string Slice(string value, long from, long to) + { + var start = Math.Max(0, from); + var end = Math.Min(value.Length, to); + + if (start >= end) + { + return string.Empty; + } + + return value.Substring((int)start, (int)(end - start)); + } + + /// Whether any character of the value belongs to the class. + public static bool ClassHas(int[][] charClass, string value) + { + foreach (var character in value) + { + if (InClass(charClass, character)) + { + return true; + } + } + + return false; + } + + /// Keeps only the characters of the value that belong to the class. + public static string KeepClass(int[][] charClass, string value) + { + var kept = new StringBuilder(); + + foreach (var character in value) + { + if (InClass(charClass, character)) + { + kept.Append(character); + } + } + + return kept.ToString(); + } + + /// Runs a compiled pattern against the whole value, without backtracking. + public static bool PatternTest(PatternStep[] steps, string value) + { + var index = 0; + + foreach (var step in steps) + { + long count = 0; + + while ((step.Max < 0 || count < step.Max) + && index < value.Length + && InClass(step.CharClass, value[index])) + { + index++; + count++; + } + + if (count < step.Min) + { + return false; + } + } + + return index == value.Length; + } + + /// Strips the code points JavaScript's trim() strips. + public static string JsTrim(string value) + { + var start = 0; + var end = value.Length; + + while (start < end && InClass(JsWhitespace, value[start])) + { + start++; + } + + while (end > start && InClass(JsWhitespace, value[end - 1])) + { + end--; + } + + return value.Substring(start, end - start); + } + + /// Left pads the value with a filler up to a length. + public static string PadStart(string value, long length, string filler) + { + var padded = new StringBuilder(); + + while (padded.Length + value.Length < length) + { + padded.Append(filler); + } + + return padded + value; + } + + /// Repeats a value. + public static string Repeat(string value, long times) + { + return times <= 0 ? string.Empty : string.Concat(Enumerable(value, times)); + } + + private static System.Collections.Generic.IEnumerable Enumerable(string value, long times) + { + for (long index = 0; index < times; index++) + { + yield return value; + } + } + + /// Reads an optional flag the way JavaScript reads truthiness. + public static bool IsTruthy(bool? value) + { + return value == true; + } + + /// Every row of a dataset, in the baked full order. + public static System.Collections.Generic.List> DataAll(Dataset table) + { + return table.All; + } + + /// The rows whose first column is the key given, empty when the key is unknown. + public static System.Collections.Generic.List> DataRows( + Dataset table, + string key) + { + return table.Rows(key); + } + } + + /// A dataset: the rows in the baked full order, and the rows of each key. + public sealed class Dataset + { + private static readonly Rows Empty = new Rows(); + + public Rows All { get; } + + private readonly System.Collections.Generic.Dictionary byKey; + + public Dataset(string[][] rows, string[] keys, int[][] groups, int[] fullOrder) + { + var shared = new System.Collections.Generic.List>(rows.Length); + + foreach (var row in rows) + { + shared.Add(new System.Collections.Generic.List(row)); + } + + All = new Rows(); + + foreach (var index in fullOrder) + { + All.Add(shared[index]); + } + + byKey = new System.Collections.Generic.Dictionary(keys.Length); + + for (var group = 0; group < keys.Length; group++) + { + var of = new Rows(); + + foreach (var index in groups[group]) + { + of.Add(shared[index]); + } + + byKey[keys[group]] = of; + } + } + + /// The rows of one key, empty when the key is unknown. + public Rows Rows(string key) + { + return byKey.TryGetValue(key, out var found) ? found : Empty; + } + } + + /// A table of rows, which is what the generated code reads a dataset as. + public sealed class Rows : System.Collections.Generic.List> + { + } + + /// What a provider answered: the status, whether it is a success, and the body. + public sealed class HttpResponse + { + public long Status { get; } + public bool Ok { get; } + public System.Text.Json.Nodes.JsonNode Body { get; } + + public HttpResponse(long status, bool ok, System.Text.Json.Nodes.JsonNode body) + { + Status = status; + Ok = ok; + Body = body; + } + } + + /// What one attempt of a race ended with. + internal sealed class Outcome + { + public bool Ok { get; init; } + public T Value { get; init; } + public System.Collections.Generic.List Kinds { get; init; } + } + + /// The running attempts of a race, and what each one ended with. + public sealed class Attempts + { + internal System.Collections.Generic.List>> Settled { get; } = + new System.Collections.Generic.List>>(); + + internal System.Collections.Generic.List> Outcomes { get; } = + new System.Collections.Generic.List>(); + } + + /// The helpers the generated code needs for HTTP, JSON and racing. + public static class Net + { + private static readonly System.Net.Http.HttpClient Client = new System.Net.Http.HttpClient + { + Timeout = System.TimeSpan.FromSeconds(15), + }; + + /// + /// The origin every request is sent to instead of its own, when one is set. This is the + /// conformance hook: the cross language replay points all seven targets at one local + /// server, the same way the JavaScript suite points fetch at a mock. + /// + private static string Target(string url) + { + var origin = System.Environment.GetEnvironmentVariable("BRUTILS_BRIDGE_HTTP_ORIGIN"); + + if (string.IsNullOrEmpty(origin)) + { + return url; + } + + return origin + "/" + System.Text.RegularExpressions.Regex.Replace(url, "^https?://", string.Empty); + } + + /// Performs an HTTP GET, retrying a transient transport failure with a backoff. + public static async System.Threading.Tasks.Task HttpGet( + string url, + long retries, + long retryDelayMs) + { + var target = Target(url); + + for (long attempt = 0; ; attempt++) + { + try + { + var answer = await Client.GetAsync(target).ConfigureAwait(false); + var status = (long)answer.StatusCode; + var text = await answer.Content.ReadAsStringAsync().ConfigureAwait(false); + System.Text.Json.Nodes.JsonNode body = null; + + try + { + body = System.Text.Json.Nodes.JsonNode.Parse(text); + } + catch (System.Text.Json.JsonException) + { + body = null; + } + + return new HttpResponse(status, status >= 200 && status < 300, body); + } + catch (System.Exception) + { + if (attempt >= retries) + { + return new HttpResponse(0, false, null); + } + + await System.Threading.Tasks.Task.Delay((int)(retryDelayMs * (attempt + 1))).ConfigureAwait(false); + } + } + } + + /// Whether a list holds a value. + public static bool ListHas(System.Collections.Generic.List items, string value) + { + return items.Contains(value); + } + + /// Reads one field of a JSON body, treating anything that is not an object as empty. + private static System.Text.Json.Nodes.JsonNode Field(System.Text.Json.Nodes.JsonNode body, string key) + { + if (body is not System.Text.Json.Nodes.JsonObject found) + { + return null; + } + + return found.TryGetPropertyValue(key, out var value) ? value : null; + } + + /// Reads a string field of a JSON body, answering "" when it is missing. + public static string JsonString(System.Text.Json.Nodes.JsonNode body, string key) + { + var found = Field(body, key); + + if (found is System.Text.Json.Nodes.JsonValue value + && value.TryGetValue(out var text)) + { + return text; + } + + return string.Empty; + } + + /// Reads an integer field of a JSON body, answering -1 when it is missing. + public static long JsonInt(System.Text.Json.Nodes.JsonNode body, string key) + { + var found = Field(body, key); + + if (found is System.Text.Json.Nodes.JsonValue value && value.TryGetValue(out var number)) + { + return (long)number; + } + + return -1; + } + + /// Whether a field of a JSON body is truthy, the way JavaScript reads truthiness. + public static bool JsonTruthy(System.Text.Json.Nodes.JsonNode body, string key) + { + var found = Field(body, key); + + if (found is null) + { + return false; + } + + if (found is System.Text.Json.Nodes.JsonValue value) + { + if (value.TryGetValue(out var flag)) + { + return flag; + } + + if (value.TryGetValue(out var number)) + { + return number != 0; + } + + if (value.TryGetValue(out var text)) + { + return text.Length > 0; + } + } + + return true; + } + + /// Whether a field of a JSON body is exactly true. + public static bool JsonIsTrue(System.Text.Json.Nodes.JsonNode body, string key) + { + return Field(body, key) is System.Text.Json.Nodes.JsonValue value + && value.TryGetValue(out var flag) + && flag; + } + + /// The error name and every name it inherits from. + private static System.Collections.Generic.List KindsOf(System.Exception error) + { + var kinds = new System.Collections.Generic.List(); + + for (var current = error.GetType(); current != null; current = current.BaseType) + { + kinds.Add(current.Name); + } + + return kinds; + } + + /// + /// Starts one attempt per item, all at once. This is the only concurrency primitive of + /// the portable subset. + /// + public static Attempts StartAll( + System.Func> run, + System.Collections.Generic.List items, + string argument) + { + var attempts = new Attempts(); + + foreach (var item in items) + { + attempts.Settled.Add(Run(run, item, argument)); + } + + return attempts; + } + + private static async System.Threading.Tasks.Task> Run( + System.Func> run, + string item, + string argument) + { + try + { + return new Outcome + { + Ok = true, + Value = await run(item, argument).ConfigureAwait(false), + Kinds = new System.Collections.Generic.List(), + }; + } + catch (System.Exception error) + { + return new Outcome { Ok = false, Kinds = KindsOf(error) }; + } + } + + /// The value of the first attempt that succeeds, or the default once all failed. + public static async System.Threading.Tasks.Task FirstSuccess(Attempts attempts) + { + var waiting = new System.Collections.Generic.List>>(attempts.Settled); + + while (waiting.Count > 0) + { + var settled = await System.Threading.Tasks.Task.WhenAny(waiting).ConfigureAwait(false); + + waiting.Remove(settled); + + var outcome = await settled.ConfigureAwait(false); + + attempts.Outcomes.Add(outcome); + + if (outcome.Ok) + { + return outcome.Value; + } + } + + return default; + } + + /// Whether any attempt failed with a given error kind. + public static bool AnyFailedWith(Attempts attempts, string kind) + { + foreach (var outcome in attempts.Outcomes) + { + if (!outcome.Ok && outcome.Kinds.Contains(kind)) + { + return true; + } + } + + return false; + } + } +} diff --git a/spec/bridge/out/go/conformance/main.go b/spec/bridge/out/go/conformance/main.go new file mode 100644 index 000000000..0451049ad --- /dev/null +++ b/spec/bridge/out/go/conformance/main.go @@ -0,0 +1,346 @@ +// Code generated by spec/bridge/conformance/drivers.ts. DO NOT EDIT. + +// Command conformance replays the recorded tables against the generated Go. +package main + +import ( + "errors" + "fmt" + "os" + "strconv" + "strings" + + "brazilianutils/bridge/format_cnpj" + "brazilianutils/bridge/get_address_info_by_cep" + "brazilianutils/bridge/get_municipalities" + "brazilianutils/bridge/is_valid_cnpj" + "brazilianutils/bridge/runtime" +) + +const target = "go" + +type tally struct{ passed, failed, skipped int } + +// unescape reads back the three characters the table format escapes. +func unescape(value string) string { + value = strings.ReplaceAll(value, "\\t", "\t") + value = strings.ReplaceAll(value, "\\n", "\n") + + return strings.ReplaceAll(value, "\\\\", "\\") +} + +// runs reports whether this target can express the call a row describes. +func runs(targets string) bool { + if targets == "*" { + return true + } + + for _, name := range strings.Split(targets, "|") { + if name == target { + return true + } + } + + return false +} + +// mustParse reads a number the recorder wrote, which is never malformed. +func mustParse(value string) int64 { + parsed, err := strconv.ParseInt(value, 10, 64) + + if err != nil { + panic(err) + } + + return parsed +} + +// report counts one comparison, and shows the first few that disagree. +func report(fn string, actual string, expected string, counts *tally) { + if actual == expected { + counts.passed++ + + return + } + + counts.failed++ + + if counts.failed <= 3 { + fmt.Fprintf(os.Stderr, "FAIL %s expected %q got %q\n", fn, cut(expected), cut(actual)) + } +} + +// cut keeps a failure message readable when the answer is a five thousand row list. +func cut(value string) string { + if len(value) <= 120 { + return value + } + + return value[:120] +} + +func renderGetAddressInfoByCepAddressInfo(value *get_address_info_by_cep.AddressInfo) string { + return value.Cep + "|" + value.State + "|" + value.City + "|" + value.Neighborhood + "|" + value.Street +} + +func renderGetMunicipalitiesMunicipality(value *get_municipalities.Municipality) string { + return value.Code + "|" + value.Name + "|" + value.StateCode +} + +func renderListGetMunicipalitiesMunicipality(items []*get_municipalities.Municipality) string { + out := strconv.Itoa(len(items)) + + for _, item := range items { + out += "\n" + renderGetMunicipalitiesMunicipality(item) + } + + return out +} + +// checkFormatCnpj replays what formatCnpj answers. +func checkFormatCnpj() tally { + raw, err := os.ReadFile("../../conformance/recorded/format-cnpj.tsv") + + if err != nil { + panic(err) + } + + counts := tally{} + + for _, line := range strings.Split(strings.TrimRight(string(raw), "\n"), "\n")[1:] { + if line == "" { + continue + } + + parts := strings.Split(line, "\t") + + if !runs(parts[0]) { + counts.skipped++ + + continue + } + + argument0 := unescape(parts[1]) + options := &format_cnpj.FormatCnpjOptions{} + given := false + + if parts[3] != "" { + value := parts[3] == "1" + options.Pad = &value + given = true + } + + if parts[4] != "" { + value := mustParse(parts[4]) + options.Version = &value + given = true + } + + if parts[5] != "" { + value := parts[5] == "1" + options.Obfuscate = &value + given = true + } + + var chosen *format_cnpj.FormatCnpjOptions + + if given { + chosen = options + } + + actual := format_cnpj.FormatCnpj(argument0, chosen) + + report("formatCnpj", actual, unescape(parts[6]), &counts) + } + + return counts +} + +// checkGetAddressInfoByCep replays what getAddressInfoByCep answers. +func checkGetAddressInfoByCep() tally { + raw, err := os.ReadFile("../../conformance/recorded/get-address-info-by-cep.tsv") + + if err != nil { + panic(err) + } + + counts := tally{} + + for _, line := range strings.Split(strings.TrimRight(string(raw), "\n"), "\n")[1:] { + if line == "" { + continue + } + + parts := strings.Split(line, "\t") + + if !runs(parts[0]) { + counts.skipped++ + + continue + } + + argument0 := unescape(parts[1]) + options := &get_address_info_by_cep.GetAddressInfoByCepOptions{} + given := false + + if parts[3] != "" { + named := []string{} + + if parts[3] != "[]" { + named = strings.Split(parts[3], "|") + } + + options.Providers = &named + given = true + } + + var chosen *get_address_info_by_cep.GetAddressInfoByCepOptions + + if given { + chosen = options + } + + found, err := get_address_info_by_cep.GetAddressInfoByCep(argument0, chosen) + actual := "" + + if err == nil { + actual = renderGetAddressInfoByCepAddressInfo(found) + } else { + kind := "" + + var raised *runtime.Error + + if errors.As(err, &raised) { + kind = raised.Kind() + } + + actual = "!" + kind + "|" + err.Error() + } + + report("getAddressInfoByCep", actual, unescape(parts[4]), &counts) + } + + return counts +} + +// checkGetMunicipalities replays what getMunicipalities answers. +func checkGetMunicipalities() tally { + raw, err := os.ReadFile("../../conformance/recorded/get-municipalities.tsv") + + if err != nil { + panic(err) + } + + counts := tally{} + + for _, line := range strings.Split(strings.TrimRight(string(raw), "\n"), "\n")[1:] { + if line == "" { + continue + } + + parts := strings.Split(line, "\t") + + if !runs(parts[0]) { + counts.skipped++ + + continue + } + + var argument0 *string + + if parts[1] == "1" { + given := unescape(parts[2]) + argument0 = &given + } + + actual := renderListGetMunicipalitiesMunicipality(get_municipalities.GetMunicipalities(argument0)) + + report("getMunicipalities", actual, unescape(parts[3]), &counts) + } + + return counts +} + +// checkIsValidCnpj replays what isValidCnpj answers. +func checkIsValidCnpj() tally { + raw, err := os.ReadFile("../../conformance/recorded/is-valid-cnpj.tsv") + + if err != nil { + panic(err) + } + + counts := tally{} + + for _, line := range strings.Split(strings.TrimRight(string(raw), "\n"), "\n")[1:] { + if line == "" { + continue + } + + parts := strings.Split(line, "\t") + + if !runs(parts[0]) { + counts.skipped++ + + continue + } + + argument0 := unescape(parts[1]) + options := &is_valid_cnpj.IsValidCnpjOptions{} + given := false + + if parts[3] != "" { + value := mustParse(parts[3]) + options.Version = &value + given = true + } + + var chosen *is_valid_cnpj.IsValidCnpjOptions + + if given { + chosen = options + } + + actual := strconv.FormatBool(is_valid_cnpj.IsValidCnpj(argument0, chosen)) + + report("isValidCnpj", actual, unescape(parts[4]), &counts) + } + + return counts +} + +func main() { + failed := 0 + + countsFormatCnpj := checkFormatCnpj() + failed += countsFormatCnpj.failed + + fmt.Printf("%s: formatCnpj %d/%d matched%s\n", target, countsFormatCnpj.passed, countsFormatCnpj.passed+countsFormatCnpj.failed, note(countsFormatCnpj.skipped)) + + countsGetAddressInfoByCep := checkGetAddressInfoByCep() + failed += countsGetAddressInfoByCep.failed + + fmt.Printf("%s: getAddressInfoByCep %d/%d matched%s\n", target, countsGetAddressInfoByCep.passed, countsGetAddressInfoByCep.passed+countsGetAddressInfoByCep.failed, note(countsGetAddressInfoByCep.skipped)) + + countsGetMunicipalities := checkGetMunicipalities() + failed += countsGetMunicipalities.failed + + fmt.Printf("%s: getMunicipalities %d/%d matched%s\n", target, countsGetMunicipalities.passed, countsGetMunicipalities.passed+countsGetMunicipalities.failed, note(countsGetMunicipalities.skipped)) + + countsIsValidCnpj := checkIsValidCnpj() + failed += countsIsValidCnpj.failed + + fmt.Printf("%s: isValidCnpj %d/%d matched%s\n", target, countsIsValidCnpj.passed, countsIsValidCnpj.passed+countsIsValidCnpj.failed, note(countsIsValidCnpj.skipped)) + + if failed > 0 { + os.Exit(1) + } +} + +// note names how many rows this target could not be handed. +func note(skipped int) string { + if skipped == 0 { + return "" + } + + return fmt.Sprintf(" (%d not expressible)", skipped) +} diff --git a/spec/bridge/out/go/format_cnpj/format_cnpj.go b/spec/bridge/out/go/format_cnpj/format_cnpj.go new file mode 100644 index 000000000..aa03af747 --- /dev/null +++ b/spec/bridge/out/go/format_cnpj/format_cnpj.go @@ -0,0 +1,89 @@ +// Code generated from spec/bridge/source/format-cnpj.ts. DO NOT EDIT. + +// Package format_cnpj holds the generated format-cnpj utility. +package format_cnpj + +import "brazilianutils/bridge/runtime" + +var class0 = runtime.CharClass{{0x30, 0x39}} +var class1 = runtime.CharClass{{0x30, 0x39}, {0x41, 0x5a}, {0x61, 0x7a}} + + + +const PATTERN = "00.000.000/0000-00" +const OBFUSCATED_PATTERN = "**.000.000/0000-**" + + + +// FormatCnpjOptions Options of `formatCnpj`. +type FormatCnpjOptions struct { + // Whether to left pad the value with zeros up to the number of slots in the pattern (default: `false`). + Pad *bool + // Which CNPJ format to read: `1` numeric only, `2` alphanumeric (default: `1`). + Version *int64 + // Whether to hide the first 2 digits and the 2 check digits with `*` (default: `false`). + Obfuscate *bool +} + + + +// FormatCnpj Formats a given CNPJ (Cadastro Nacional da Pessoa Jurídica) value. +func FormatCnpj(value string, options *FormatCnpjOptions) string { + var optionsVersion int64 = -1 + if options != nil && options.Version != nil { + optionsVersion = *options.Version + } + var optionsObfuscate bool = false + if options != nil && options.Obfuscate != nil { + optionsObfuscate = *options.Obfuscate + } + var optionsPad bool = false + if options != nil && options.Pad != nil { + optionsPad = *options.Pad + } + text := value + cleaned := runtime.KeepClass(class0, text) + if (optionsVersion == 2) { + cleaned = runtime.Upper(runtime.KeepClass(class1, text)) + } + pattern := PATTERN + if optionsObfuscate { + pattern = OBFUSCATED_PATTERN + } + return layout(cleaned, pattern, optionsPad) +} + +// layout Lays a value over a pattern. +func layout(value string, pattern string, pad bool) string { + var slots int64 = 0 + for index := int64(0); index < int64(runtime.Len(pattern)); index++ { + if ((int64(runtime.CodeAt(pattern, int(index))) == 48) || (int64(runtime.CodeAt(pattern, int(index))) == 42)) { + slots = (slots + 1) + } + } + padded := value + if pad { + padded = runtime.PadStart(value, int(slots), "0") + } + formatted := "" + var cursor int64 = 0 + for index := int64(0); index < int64(runtime.Len(pattern)); index++ { + var slot int64 = int64(runtime.CodeAt(pattern, int(index))) + if ((slot == 48) || (slot == 42)) { + if (cursor >= int64(runtime.Len(padded))) { + return formatted + } + if (slot == 42) { + formatted = (formatted + "*") + } else { + formatted = (formatted + runtime.Slice(padded, int(cursor), int((cursor + 1)))) + } + cursor = (cursor + 1) + } else { + if (cursor < int64(runtime.Len(padded))) { + formatted = (formatted + runtime.Slice(pattern, int(index), int((index + 1)))) + } + } + } + return formatted +} diff --git a/spec/bridge/out/go/get_address_info_by_cep/get_address_info_by_cep.go b/spec/bridge/out/go/get_address_info_by_cep/get_address_info_by_cep.go new file mode 100644 index 000000000..c0e4442d7 --- /dev/null +++ b/spec/bridge/out/go/get_address_info_by_cep/get_address_info_by_cep.go @@ -0,0 +1,193 @@ +// Code generated from spec/bridge/source/get-address-info-by-cep.ts. DO NOT EDIT. + +// Package get_address_info_by_cep holds the generated get-address-info-by-cep utility. +package get_address_info_by_cep + +import "brazilianutils/bridge/runtime" + +var class0 = runtime.CharClass{{0x30, 0x39}} + +var PATTERN_CEP_FORMAT = []runtime.PatternStep{ + {Class: class0, Min: 8, Max: 8, Capture: false}, +} + +var DEFAULT_PROVIDERS = []string{"viacep", "brasilapi"} +var KNOWN_PROVIDERS = []string{"viacep", "widenet", "brasilapi"} +const BRASIL_API_NOT_FOUND_STATUS = 404 +const HTTP_RETRIES = 2 +const HTTP_RETRY_DELAY_MS = 250 + +// GetAddressInfoByCepErrorKinds names GetAddressInfoByCepError: Base class of every error `getAddressInfoByCep` rejects with. +var GetAddressInfoByCepErrorKinds = []string{"GetAddressInfoByCepError"} + +// IsGetAddressInfoByCepError reports whether err is a GetAddressInfoByCepError. +func IsGetAddressInfoByCepError(err error) bool { + return runtime.IsKind(err, "GetAddressInfoByCepError") +} + +// GetAddressInfoByCepValidationErrorKinds names GetAddressInfoByCepValidationError: Thrown by `getAddressInfoByCep` when the value given is not a valid CEP. +var GetAddressInfoByCepValidationErrorKinds = []string{"GetAddressInfoByCepValidationError", "GetAddressInfoByCepError"} + +// IsGetAddressInfoByCepValidationError reports whether err is a GetAddressInfoByCepValidationError. +func IsGetAddressInfoByCepValidationError(err error) bool { + return runtime.IsKind(err, "GetAddressInfoByCepValidationError") +} + +// GetAddressInfoByCepNotFoundErrorKinds names GetAddressInfoByCepNotFoundError: Thrown by `getAddressInfoByCep` when no CEP service knows the CEP. +var GetAddressInfoByCepNotFoundErrorKinds = []string{"GetAddressInfoByCepNotFoundError", "GetAddressInfoByCepError"} + +// IsGetAddressInfoByCepNotFoundError reports whether err is a GetAddressInfoByCepNotFoundError. +func IsGetAddressInfoByCepNotFoundError(err error) bool { + return runtime.IsKind(err, "GetAddressInfoByCepNotFoundError") +} + +// GetAddressInfoByCepServiceErrorKinds names GetAddressInfoByCepServiceError: Thrown by `getAddressInfoByCep` when every CEP service failed to answer. +var GetAddressInfoByCepServiceErrorKinds = []string{"GetAddressInfoByCepServiceError", "GetAddressInfoByCepError"} + +// IsGetAddressInfoByCepServiceError reports whether err is a GetAddressInfoByCepServiceError. +func IsGetAddressInfoByCepServiceError(err error) bool { + return runtime.IsKind(err, "GetAddressInfoByCepServiceError") +} + +// CepProviderFailureKinds names CepProviderFailure: Raised inside a provider that did not answer. Only whether a failure was a not found is looked at when the provider failures are aggregated, so this one never leaves the module. +var CepProviderFailureKinds = []string{"CepProviderFailure"} + +// IsCepProviderFailure reports whether err is a CepProviderFailure. +func IsCepProviderFailure(err error) bool { + return runtime.IsKind(err, "CepProviderFailure") +} + +// AddressInfo The address `getAddressInfoByCep` returns for a CEP. +type AddressInfo struct { + // The 8 digit CEP, no mask. + Cep string + // Two letter state code, e.g. "SP". + State string + // City name. + City string + // Neighborhood name, empty when the CEP covers a whole city. + Neighborhood string + // Street name, empty when the CEP covers a whole city. + Street string +} + +// GetAddressInfoByCepOptions Options of `getAddressInfoByCep`. +type GetAddressInfoByCepOptions struct { + // Which CEP services to race, in the order given (default: `["viacep", "brasilapi"]`; the deprecated `"widenet"` provider is excluded from the default list, but can still be requested explicitly). + Providers *[]string +} + + + +// fetchViaCep Reads the address ViaCEP answers with. +// +// @see Based on: https://viacep.com.br/ +func fetchViaCep(cep string) (*AddressInfo, error) { + response := runtime.HttpGet((("https://viacep.com.br/ws/" + cep) + "/json/"), HTTP_RETRIES, HTTP_RETRY_DELAY_MS) + if !response.Ok { + return nil, runtime.NewError(CepProviderFailureKinds, "ViaCEP request failed") + } + found := runtime.JsonString(response.Body, "cep") + if (runtime.JsonTruthy(response.Body, "erro") || (found == "")) { + return nil, runtime.NewError(GetAddressInfoByCepNotFoundErrorKinds, "CEP n\u00e3o encontrado") + } + return &AddressInfo{Cep: runtime.KeepClass(class0, found), State: runtime.JsonString(response.Body, "uf"), City: runtime.JsonString(response.Body, "localidade"), Neighborhood: runtime.JsonString(response.Body, "bairro"), Street: runtime.JsonString(response.Body, "logradouro")}, nil +} + +// fetchWidenet Reads the address Widenet answers with. +func fetchWidenet(cep string) (*AddressInfo, error) { + response := runtime.HttpGet((("https://apps.widenet.com.br/busca-cep/api/cep/" + cep) + ".json"), HTTP_RETRIES, HTTP_RETRY_DELAY_MS) + if !response.Ok { + return nil, runtime.NewError(CepProviderFailureKinds, "Widenet request failed") + } + found := runtime.JsonString(response.Body, "code") + if (((runtime.JsonInt(response.Body, "status") != 200) || !runtime.JsonIsTrue(response.Body, "ok")) || (found == "")) { + return nil, runtime.NewError(GetAddressInfoByCepNotFoundErrorKinds, "CEP n\u00e3o encontrado") + } + return &AddressInfo{Cep: runtime.KeepClass(class0, found), State: runtime.JsonString(response.Body, "state"), City: runtime.JsonString(response.Body, "city"), Neighborhood: runtime.JsonString(response.Body, "district"), Street: runtime.JsonString(response.Body, "address")}, nil +} + +// fetchBrasilApi Reads the address BrasilAPI answers with. +// +// @see Based on: https://brasilapi.com.br/docs#tag/CEP +func fetchBrasilApi(cep string) (*AddressInfo, error) { + response := runtime.HttpGet((("https://brasilapi.com.br/api/cep/v1/" + cep) + ""), HTTP_RETRIES, HTTP_RETRY_DELAY_MS) + if (response.Status == BRASIL_API_NOT_FOUND_STATUS) { + return nil, runtime.NewError(GetAddressInfoByCepNotFoundErrorKinds, "CEP n\u00e3o encontrado") + } + if !response.Ok { + return nil, runtime.NewError(CepProviderFailureKinds, "BrasilAPI request failed") + } + found := runtime.JsonString(response.Body, "cep") + if (runtime.JsonTruthy(response.Body, "errors") || (found == "")) { + return nil, runtime.NewError(GetAddressInfoByCepNotFoundErrorKinds, "CEP n\u00e3o encontrado") + } + return &AddressInfo{Cep: runtime.KeepClass(class0, found), State: runtime.JsonString(response.Body, "state"), City: runtime.JsonString(response.Body, "city"), Neighborhood: runtime.JsonString(response.Body, "neighborhood"), Street: runtime.JsonString(response.Body, "street")}, nil +} + +// fetchProvider Asks one named provider for a CEP. +func fetchProvider(provider string, cep string) (*AddressInfo, error) { + if (provider == "viacep") { + return fetchViaCep(cep) + } + if (provider == "widenet") { + return fetchWidenet(cep) + } + return fetchBrasilApi(cep) +} + +// knownProviders The providers of a list that are known, in the order they were given. +func knownProviders(given []string) []string { + kept := []string{} + for _, provider := range given { + if runtime.ListHas(KNOWN_PROVIDERS, provider) { + kept = append(kept, provider) + } + } + return kept +} + +// GetAddressInfoByCep Fetches address information for a given CEP using multiple providers simultaneously. +// Returns the result from the first provider that responds successfully. +// +// The providers are started together and raced, not tried one after the other, so a provider +// that is retrying delays nothing for the others: its retries only push back the moment its own +// failure lands, and therefore the moment an all-failed rejection can surface. +// +// @see Official: https://www.correios.com.br/enviar/precisa-de-ajuda/tudo-sobre-cep +// @see Based on: https://viacep.com.br/ +// ViaCEP, one of the two default providers. A third-party service, not a Correios one. +// @see Based on: https://brasilapi.com.br/docs#tag/CEP +// BrasilAPI, the other default provider. A third-party service, not a Correios one. +func GetAddressInfoByCep(cep string, options *GetAddressInfoByCepOptions) (*AddressInfo, error) { + var optionsProviders []string = nil + if options != nil && options.Providers != nil { + optionsProviders = *options.Providers + } + digits := runtime.KeepClass(class0, cep) + if false { + digits = runtime.PadStart(digits, int(8), "0") + } + if !runtime.PatternTest(PATTERN_CEP_FORMAT, digits) { + return nil, runtime.NewError(GetAddressInfoByCepValidationErrorKinds, "CEP inv\u00e1lido") + } + chosen := DEFAULT_PROVIDERS + if (optionsProviders != nil) { + if !true { + return nil, runtime.NewError(GetAddressInfoByCepValidationErrorKinds, "Nenhum provedor v\u00e1lido especificado") + } + chosen = knownProviders(optionsProviders) + if (int64(len(chosen)) == 0) { + return nil, runtime.NewError(GetAddressInfoByCepValidationErrorKinds, "Nenhum provedor v\u00e1lido especificado") + } + } + attempts := runtime.StartAll(func(item string, argument string) (any, error) { return fetchProvider(item, argument) }, chosen, digits) + found := runtime.FirstSuccessOf[*AddressInfo](attempts) + if (found != nil) { + return found, nil + } + if runtime.AnyFailedWith(attempts, "GetAddressInfoByCepNotFoundError") { + return nil, runtime.NewError(GetAddressInfoByCepNotFoundErrorKinds, "CEP n\u00e3o encontrado em nenhum servi\u00e7o") + } + return nil, runtime.NewError(GetAddressInfoByCepServiceErrorKinds, "Todos os servi\u00e7os est\u00e3o fora de servi\u00e7o ou indispon\u00edveis") +} diff --git a/spec/bridge/out/go/get_municipalities/get_municipalities.go b/spec/bridge/out/go/get_municipalities/get_municipalities.go new file mode 100644 index 000000000..2af828595 --- /dev/null +++ b/spec/bridge/out/go/get_municipalities/get_municipalities.go @@ -0,0 +1,5662 @@ +// Code generated from spec/bridge/source/get-municipalities.ts. DO NOT EDIT. + +// Package get_municipalities holds the generated get-municipalities utility. +package get_municipalities + +import "brazilianutils/bridge/runtime" + + + + + + + + + +// Municipality One Brazilian municipality, as the IBGE publishes it. +type Municipality struct { + // The 7-digit IBGE municipality code. + Code string + // The municipality name. + Name string + // The two-letter code of the state the municipality belongs to. + StateCode string +} + +// MUNICIPALITIES Brazilian municipalities published by the IBGE, by state, in the pt-BR collation order the JavaScript package returns. +var MUNICIPALITIES = runtime.NewDataset( + [][]string{ + {"AC", "Acrel\u00e2ndia", "1200013"}, + {"AC", "Assis Brasil", "1200054"}, + {"AC", "Brasil\u00e9ia", "1200104"}, + {"AC", "Bujari", "1200138"}, + {"AC", "Capixaba", "1200179"}, + {"AC", "Cruzeiro do Sul", "1200203"}, + {"AC", "Epitaciol\u00e2ndia", "1200252"}, + {"AC", "Feij\u00f3", "1200302"}, + {"AC", "Jord\u00e3o", "1200328"}, + {"AC", "M\u00e2ncio Lima", "1200336"}, + {"AC", "Manoel Urbano", "1200344"}, + {"AC", "Marechal Thaumaturgo", "1200351"}, + {"AC", "Pl\u00e1cido de Castro", "1200385"}, + {"AC", "Porto Acre", "1200807"}, + {"AC", "Porto Walter", "1200393"}, + {"AC", "Rio Branco", "1200401"}, + {"AC", "Rodrigues Alves", "1200427"}, + {"AC", "Santa Rosa do Purus", "1200435"}, + {"AC", "Sena Madureira", "1200500"}, + {"AC", "Senador Guiomard", "1200450"}, + {"AC", "Tarauac\u00e1", "1200609"}, + {"AC", "Xapuri", "1200708"}, + {"AL", "\u00c1gua Branca", "2700102"}, + {"AL", "Anadia", "2700201"}, + {"AL", "Arapiraca", "2700300"}, + {"AL", "Atalaia", "2700409"}, + {"AL", "Barra de Santo Ant\u00f4nio", "2700508"}, + {"AL", "Barra de S\u00e3o Miguel", "2700607"}, + {"AL", "Batalha", "2700706"}, + {"AL", "Bel\u00e9m", "2700805"}, + {"AL", "Belo Monte", "2700904"}, + {"AL", "Boca da Mata", "2701001"}, + {"AL", "Branquinha", "2701100"}, + {"AL", "Cacimbinhas", "2701209"}, + {"AL", "Cajueiro", "2701308"}, + {"AL", "Campestre", "2701357"}, + {"AL", "Campo Alegre", "2701407"}, + {"AL", "Campo Grande", "2701506"}, + {"AL", "Canapi", "2701605"}, + {"AL", "Capela", "2701704"}, + {"AL", "Carneiros", "2701803"}, + {"AL", "Ch\u00e3 Preta", "2701902"}, + {"AL", "Coit\u00e9 do N\u00f3ia", "2702009"}, + {"AL", "Col\u00f4nia Leopoldina", "2702108"}, + {"AL", "Coqueiro Seco", "2702207"}, + {"AL", "Coruripe", "2702306"}, + {"AL", "Cra\u00edbas", "2702355"}, + {"AL", "Delmiro Gouveia", "2702405"}, + {"AL", "Dois Riachos", "2702504"}, + {"AL", "Estrela de Alagoas", "2702553"}, + {"AL", "Feira Grande", "2702603"}, + {"AL", "Feliz Deserto", "2702702"}, + {"AL", "Flexeiras", "2702801"}, + {"AL", "Girau do Ponciano", "2702900"}, + {"AL", "Ibateguara", "2703007"}, + {"AL", "Igaci", "2703106"}, + {"AL", "Igreja Nova", "2703205"}, + {"AL", "Inhapi", "2703304"}, + {"AL", "Jacar\u00e9 dos Homens", "2703403"}, + {"AL", "Jacu\u00edpe", "2703502"}, + {"AL", "Japaratinga", "2703601"}, + {"AL", "Jaramataia", "2703700"}, + {"AL", "Jequi\u00e1 da Praia", "2703759"}, + {"AL", "Joaquim Gomes", "2703809"}, + {"AL", "Jundi\u00e1", "2703908"}, + {"AL", "Junqueiro", "2704005"}, + {"AL", "Lagoa da Canoa", "2704104"}, + {"AL", "Limoeiro de Anadia", "2704203"}, + {"AL", "Macei\u00f3", "2704302"}, + {"AL", "Major Isidoro", "2704401"}, + {"AL", "Mar Vermelho", "2704906"}, + {"AL", "Maragogi", "2704500"}, + {"AL", "Maravilha", "2704609"}, + {"AL", "Marechal Deodoro", "2704708"}, + {"AL", "Maribondo", "2704807"}, + {"AL", "Mata Grande", "2705002"}, + {"AL", "Matriz de Camaragibe", "2705101"}, + {"AL", "Messias", "2705200"}, + {"AL", "Minador do Negr\u00e3o", "2705309"}, + {"AL", "Monteir\u00f3polis", "2705408"}, + {"AL", "Murici", "2705507"}, + {"AL", "Novo Lino", "2705606"}, + {"AL", "Olho d'\u00c1gua das Flores", "2705705"}, + {"AL", "Olho d'\u00c1gua do Casado", "2705804"}, + {"AL", "Olho d'\u00c1gua Grande", "2705903"}, + {"AL", "Oliven\u00e7a", "2706000"}, + {"AL", "Ouro Branco", "2706109"}, + {"AL", "Palestina", "2706208"}, + {"AL", "Palmeira dos \u00cdndios", "2706307"}, + {"AL", "P\u00e3o de A\u00e7\u00facar", "2706406"}, + {"AL", "Pariconha", "2706422"}, + {"AL", "Paripueira", "2706448"}, + {"AL", "Passo de Camaragibe", "2706505"}, + {"AL", "Paulo Jacinto", "2706604"}, + {"AL", "Penedo", "2706703"}, + {"AL", "Pia\u00e7abu\u00e7u", "2706802"}, + {"AL", "Pilar", "2706901"}, + {"AL", "Pindoba", "2707008"}, + {"AL", "Piranhas", "2707107"}, + {"AL", "Po\u00e7o das Trincheiras", "2707206"}, + {"AL", "Porto Calvo", "2707305"}, + {"AL", "Porto de Pedras", "2707404"}, + {"AL", "Porto Real do Col\u00e9gio", "2707503"}, + {"AL", "Quebrangulo", "2707602"}, + {"AL", "Rio Largo", "2707701"}, + {"AL", "Roteiro", "2707800"}, + {"AL", "Santa Luzia do Norte", "2707909"}, + {"AL", "Santana do Ipanema", "2708006"}, + {"AL", "Santana do Munda\u00fa", "2708105"}, + {"AL", "S\u00e3o Br\u00e1s", "2708204"}, + {"AL", "S\u00e3o Jos\u00e9 da Laje", "2708303"}, + {"AL", "S\u00e3o Jos\u00e9 da Tapera", "2708402"}, + {"AL", "S\u00e3o Lu\u00eds do Quitunde", "2708501"}, + {"AL", "S\u00e3o Miguel dos Campos", "2708600"}, + {"AL", "S\u00e3o Miguel dos Milagres", "2708709"}, + {"AL", "S\u00e3o Sebasti\u00e3o", "2708808"}, + {"AL", "Satuba", "2708907"}, + {"AL", "Senador Rui Palmeira", "2708956"}, + {"AL", "Tanque d'Arca", "2709004"}, + {"AL", "Taquarana", "2709103"}, + {"AL", "Teot\u00f4nio Vilela", "2709152"}, + {"AL", "Traipu", "2709202"}, + {"AL", "Uni\u00e3o dos Palmares", "2709301"}, + {"AL", "Vi\u00e7osa", "2709400"}, + {"AP", "Amap\u00e1", "1600105"}, + {"AP", "Cal\u00e7oene", "1600204"}, + {"AP", "Cutias", "1600212"}, + {"AP", "Ferreira Gomes", "1600238"}, + {"AP", "Itaubal", "1600253"}, + {"AP", "Laranjal do Jari", "1600279"}, + {"AP", "Macap\u00e1", "1600303"}, + {"AP", "Mazag\u00e3o", "1600402"}, + {"AP", "Oiapoque", "1600501"}, + {"AP", "Pedra Branca do Amapari", "1600154"}, + {"AP", "Porto Grande", "1600535"}, + {"AP", "Pracu\u00faba", "1600550"}, + {"AP", "Santana", "1600600"}, + {"AP", "Serra do Navio", "1600055"}, + {"AP", "Tartarugalzinho", "1600709"}, + {"AP", "Vit\u00f3ria do Jari", "1600808"}, + {"AM", "Alvar\u00e3es", "1300029"}, + {"AM", "Amatur\u00e1", "1300060"}, + {"AM", "Anam\u00e3", "1300086"}, + {"AM", "Anori", "1300102"}, + {"AM", "Apu\u00ed", "1300144"}, + {"AM", "Atalaia do Norte", "1300201"}, + {"AM", "Autazes", "1300300"}, + {"AM", "Barcelos", "1300409"}, + {"AM", "Barreirinha", "1300508"}, + {"AM", "Benjamin Constant", "1300607"}, + {"AM", "Beruri", "1300631"}, + {"AM", "Boa Vista do Ramos", "1300680"}, + {"AM", "Boca do Acre", "1300706"}, + {"AM", "Borba", "1300805"}, + {"AM", "Caapiranga", "1300839"}, + {"AM", "Canutama", "1300904"}, + {"AM", "Carauari", "1301001"}, + {"AM", "Careiro", "1301100"}, + {"AM", "Careiro da V\u00e1rzea", "1301159"}, + {"AM", "Coari", "1301209"}, + {"AM", "Codaj\u00e1s", "1301308"}, + {"AM", "Eirunep\u00e9", "1301407"}, + {"AM", "Envira", "1301506"}, + {"AM", "Fonte Boa", "1301605"}, + {"AM", "Guajar\u00e1", "1301654"}, + {"AM", "Humait\u00e1", "1301704"}, + {"AM", "Ipixuna", "1301803"}, + {"AM", "Iranduba", "1301852"}, + {"AM", "Itacoatiara", "1301902"}, + {"AM", "Itamarati", "1301951"}, + {"AM", "Itapiranga", "1302009"}, + {"AM", "Japur\u00e1", "1302108"}, + {"AM", "Juru\u00e1", "1302207"}, + {"AM", "Juta\u00ed", "1302306"}, + {"AM", "L\u00e1brea", "1302405"}, + {"AM", "Manacapuru", "1302504"}, + {"AM", "Manaquiri", "1302553"}, + {"AM", "Manaus", "1302603"}, + {"AM", "Manicor\u00e9", "1302702"}, + {"AM", "Mara\u00e3", "1302801"}, + {"AM", "Mau\u00e9s", "1302900"}, + {"AM", "Nhamund\u00e1", "1303007"}, + {"AM", "Nova Olinda do Norte", "1303106"}, + {"AM", "Novo Air\u00e3o", "1303205"}, + {"AM", "Novo Aripuan\u00e3", "1303304"}, + {"AM", "Parintins", "1303403"}, + {"AM", "Pauini", "1303502"}, + {"AM", "Presidente Figueiredo", "1303536"}, + {"AM", "Rio Preto da Eva", "1303569"}, + {"AM", "Santa Isabel do Rio Negro", "1303601"}, + {"AM", "Santo Ant\u00f4nio do I\u00e7\u00e1", "1303700"}, + {"AM", "S\u00e3o Gabriel da Cachoeira", "1303809"}, + {"AM", "S\u00e3o Paulo de Oliven\u00e7a", "1303908"}, + {"AM", "S\u00e3o Sebasti\u00e3o do Uatum\u00e3", "1303957"}, + {"AM", "Silves", "1304005"}, + {"AM", "Tabatinga", "1304062"}, + {"AM", "Tapau\u00e1", "1304104"}, + {"AM", "Tef\u00e9", "1304203"}, + {"AM", "Tonantins", "1304237"}, + {"AM", "Uarini", "1304260"}, + {"AM", "Urucar\u00e1", "1304302"}, + {"AM", "Urucurituba", "1304401"}, + {"BA", "Aba\u00edra", "2900108"}, + {"BA", "Abar\u00e9", "2900207"}, + {"BA", "Acajutiba", "2900306"}, + {"BA", "Adustina", "2900355"}, + {"BA", "\u00c1gua Fria", "2900405"}, + {"BA", "Aiquara", "2900603"}, + {"BA", "Alagoinhas", "2900702"}, + {"BA", "Alcoba\u00e7a", "2900801"}, + {"BA", "Almadina", "2900900"}, + {"BA", "Amargosa", "2901007"}, + {"BA", "Am\u00e9lia Rodrigues", "2901106"}, + {"BA", "Am\u00e9rica Dourada", "2901155"}, + {"BA", "Anag\u00e9", "2901205"}, + {"BA", "Andara\u00ed", "2901304"}, + {"BA", "Andorinha", "2901353"}, + {"BA", "Angical", "2901403"}, + {"BA", "Anguera", "2901502"}, + {"BA", "Antas", "2901601"}, + {"BA", "Ant\u00f4nio Cardoso", "2901700"}, + {"BA", "Ant\u00f4nio Gon\u00e7alves", "2901809"}, + {"BA", "Apor\u00e1", "2901908"}, + {"BA", "Apuarema", "2901957"}, + {"BA", "Ara\u00e7\u00e1s", "2902054"}, + {"BA", "Aracatu", "2902005"}, + {"BA", "Araci", "2902104"}, + {"BA", "Aramari", "2902203"}, + {"BA", "Arataca", "2902252"}, + {"BA", "Aratu\u00edpe", "2902302"}, + {"BA", "Aurelino Leal", "2902401"}, + {"BA", "Baian\u00f3polis", "2902500"}, + {"BA", "Baixa Grande", "2902609"}, + {"BA", "Banza\u00ea", "2902658"}, + {"BA", "Barra", "2902708"}, + {"BA", "Barra da Estiva", "2902807"}, + {"BA", "Barra do Cho\u00e7a", "2902906"}, + {"BA", "Barra do Mendes", "2903003"}, + {"BA", "Barra do Rocha", "2903102"}, + {"BA", "Barreiras", "2903201"}, + {"BA", "Barro Alto", "2903235"}, + {"BA", "Barro Preto", "2903300"}, + {"BA", "Barrocas", "2903276"}, + {"BA", "Belmonte", "2903409"}, + {"BA", "Belo Campo", "2903508"}, + {"BA", "Biritinga", "2903607"}, + {"BA", "Boa Nova", "2903706"}, + {"BA", "Boa Vista do Tupim", "2903805"}, + {"BA", "Bom Jesus da Lapa", "2903904"}, + {"BA", "Bom Jesus da Serra", "2903953"}, + {"BA", "Boninal", "2904001"}, + {"BA", "Bonito", "2904050"}, + {"BA", "Boquira", "2904100"}, + {"BA", "Botupor\u00e3", "2904209"}, + {"BA", "Brej\u00f5es", "2904308"}, + {"BA", "Brejol\u00e2ndia", "2904407"}, + {"BA", "Brotas de Maca\u00fabas", "2904506"}, + {"BA", "Brumado", "2904605"}, + {"BA", "Buerarema", "2904704"}, + {"BA", "Buritirama", "2904753"}, + {"BA", "Caatiba", "2904803"}, + {"BA", "Cabaceiras do Paragua\u00e7u", "2904852"}, + {"BA", "Cachoeira", "2904902"}, + {"BA", "Cacul\u00e9", "2905008"}, + {"BA", "Ca\u00e9m", "2905107"}, + {"BA", "Caetanos", "2905156"}, + {"BA", "Caetit\u00e9", "2905206"}, + {"BA", "Cafarnaum", "2905305"}, + {"BA", "Cairu", "2905404"}, + {"BA", "Caldeir\u00e3o Grande", "2905503"}, + {"BA", "Camacan", "2905602"}, + {"BA", "Cama\u00e7ari", "2905701"}, + {"BA", "Camamu", "2905800"}, + {"BA", "Campo Alegre de Lourdes", "2905909"}, + {"BA", "Campo Formoso", "2906006"}, + {"BA", "Can\u00e1polis", "2906105"}, + {"BA", "Canarana", "2906204"}, + {"BA", "Canavieiras", "2906303"}, + {"BA", "Candeal", "2906402"}, + {"BA", "Candeias", "2906501"}, + {"BA", "Candiba", "2906600"}, + {"BA", "C\u00e2ndido Sales", "2906709"}, + {"BA", "Cansan\u00e7\u00e3o", "2906808"}, + {"BA", "Canudos", "2906824"}, + {"BA", "Capela do Alto Alegre", "2906857"}, + {"BA", "Capim Grosso", "2906873"}, + {"BA", "Cara\u00edbas", "2906899"}, + {"BA", "Caravelas", "2906907"}, + {"BA", "Cardeal da Silva", "2907004"}, + {"BA", "Carinhanha", "2907103"}, + {"BA", "Casa Nova", "2907202"}, + {"BA", "Castro Alves", "2907301"}, + {"BA", "Catol\u00e2ndia", "2907400"}, + {"BA", "Catu", "2907509"}, + {"BA", "Caturama", "2907558"}, + {"BA", "Central", "2907608"}, + {"BA", "Chorroch\u00f3", "2907707"}, + {"BA", "C\u00edcero Dantas", "2907806"}, + {"BA", "Cip\u00f3", "2907905"}, + {"BA", "Coaraci", "2908002"}, + {"BA", "Cocos", "2908101"}, + {"BA", "Concei\u00e7\u00e3o da Feira", "2908200"}, + {"BA", "Concei\u00e7\u00e3o do Almeida", "2908309"}, + {"BA", "Concei\u00e7\u00e3o do Coit\u00e9", "2908408"}, + {"BA", "Concei\u00e7\u00e3o do Jacu\u00edpe", "2908507"}, + {"BA", "Conde", "2908606"}, + {"BA", "Conde\u00faba", "2908705"}, + {"BA", "Contendas do Sincor\u00e1", "2908804"}, + {"BA", "Cora\u00e7\u00e3o de Maria", "2908903"}, + {"BA", "Cordeiros", "2909000"}, + {"BA", "Coribe", "2909109"}, + {"BA", "Coronel Jo\u00e3o S\u00e1", "2909208"}, + {"BA", "Correntina", "2909307"}, + {"BA", "Cotegipe", "2909406"}, + {"BA", "Cravol\u00e2ndia", "2909505"}, + {"BA", "Cris\u00f3polis", "2909604"}, + {"BA", "Crist\u00f3polis", "2909703"}, + {"BA", "Cruz das Almas", "2909802"}, + {"BA", "Cura\u00e7\u00e1", "2909901"}, + {"BA", "D\u00e1rio Meira", "2910008"}, + {"BA", "Dias d'\u00c1vila", "2910057"}, + {"BA", "Dom Bas\u00edlio", "2910107"}, + {"BA", "Dom Macedo Costa", "2910206"}, + {"BA", "El\u00edsio Medrado", "2910305"}, + {"BA", "Encruzilhada", "2910404"}, + {"BA", "Entre Rios", "2910503"}, + {"BA", "\u00c9rico Cardoso", "2900504"}, + {"BA", "Esplanada", "2910602"}, + {"BA", "Euclides da Cunha", "2910701"}, + {"BA", "Eun\u00e1polis", "2910727"}, + {"BA", "F\u00e1tima", "2910750"}, + {"BA", "Feira da Mata", "2910776"}, + {"BA", "Feira de Santana", "2910800"}, + {"BA", "Filad\u00e9lfia", "2910859"}, + {"BA", "Firmino Alves", "2910909"}, + {"BA", "Floresta Azul", "2911006"}, + {"BA", "Formosa do Rio Preto", "2911105"}, + {"BA", "Gandu", "2911204"}, + {"BA", "Gavi\u00e3o", "2911253"}, + {"BA", "Gentio do Ouro", "2911303"}, + {"BA", "Gl\u00f3ria", "2911402"}, + {"BA", "Gongogi", "2911501"}, + {"BA", "Governador Mangabeira", "2911600"}, + {"BA", "Guajeru", "2911659"}, + {"BA", "Guanambi", "2911709"}, + {"BA", "Guaratinga", "2911808"}, + {"BA", "Heli\u00f3polis", "2911857"}, + {"BA", "Ia\u00e7u", "2911907"}, + {"BA", "Ibiassuc\u00ea", "2912004"}, + {"BA", "Ibicara\u00ed", "2912103"}, + {"BA", "Ibicoara", "2912202"}, + {"BA", "Ibicu\u00ed", "2912301"}, + {"BA", "Ibipeba", "2912400"}, + {"BA", "Ibipitanga", "2912509"}, + {"BA", "Ibiquera", "2912608"}, + {"BA", "Ibirapitanga", "2912707"}, + {"BA", "Ibirapu\u00e3", "2912806"}, + {"BA", "Ibirataia", "2912905"}, + {"BA", "Ibitiara", "2913002"}, + {"BA", "Ibitit\u00e1", "2913101"}, + {"BA", "Ibotirama", "2913200"}, + {"BA", "Ichu", "2913309"}, + {"BA", "Igapor\u00e3", "2913408"}, + {"BA", "Igrapi\u00fana", "2913457"}, + {"BA", "Igua\u00ed", "2913507"}, + {"BA", "Ilh\u00e9us", "2913606"}, + {"BA", "Inhambupe", "2913705"}, + {"BA", "Ipecaet\u00e1", "2913804"}, + {"BA", "Ipia\u00fa", "2913903"}, + {"BA", "Ipir\u00e1", "2914000"}, + {"BA", "Ipupiara", "2914109"}, + {"BA", "Irajuba", "2914208"}, + {"BA", "Iramaia", "2914307"}, + {"BA", "Iraquara", "2914406"}, + {"BA", "Irar\u00e1", "2914505"}, + {"BA", "Irec\u00ea", "2914604"}, + {"BA", "Itabela", "2914653"}, + {"BA", "Itaberaba", "2914703"}, + {"BA", "Itabuna", "2914802"}, + {"BA", "Itacar\u00e9", "2914901"}, + {"BA", "Itaet\u00e9", "2915007"}, + {"BA", "Itagi", "2915106"}, + {"BA", "Itagib\u00e1", "2915205"}, + {"BA", "Itagimirim", "2915304"}, + {"BA", "Itagua\u00e7u da Bahia", "2915353"}, + {"BA", "Itaju do Col\u00f4nia", "2915403"}, + {"BA", "Itaju\u00edpe", "2915502"}, + {"BA", "Itamaraju", "2915601"}, + {"BA", "Itamari", "2915700"}, + {"BA", "Itamb\u00e9", "2915809"}, + {"BA", "Itanagra", "2915908"}, + {"BA", "Itanh\u00e9m", "2916005"}, + {"BA", "Itaparica", "2916104"}, + {"BA", "Itap\u00e9", "2916203"}, + {"BA", "Itapebi", "2916302"}, + {"BA", "Itapetinga", "2916401"}, + {"BA", "Itapicuru", "2916500"}, + {"BA", "Itapitanga", "2916609"}, + {"BA", "Itaquara", "2916708"}, + {"BA", "Itarantim", "2916807"}, + {"BA", "Itatim", "2916856"}, + {"BA", "Itiru\u00e7u", "2916906"}, + {"BA", "Iti\u00faba", "2917003"}, + {"BA", "Itoror\u00f3", "2917102"}, + {"BA", "Itua\u00e7u", "2917201"}, + {"BA", "Ituber\u00e1", "2917300"}, + {"BA", "Iuiu", "2917334"}, + {"BA", "Jaborandi", "2917359"}, + {"BA", "Jacaraci", "2917409"}, + {"BA", "Jacobina", "2917508"}, + {"BA", "Jaguaquara", "2917607"}, + {"BA", "Jaguarari", "2917706"}, + {"BA", "Jaguaripe", "2917805"}, + {"BA", "Janda\u00edra", "2917904"}, + {"BA", "Jequi\u00e9", "2918001"}, + {"BA", "Jeremoabo", "2918100"}, + {"BA", "Jiquiri\u00e7\u00e1", "2918209"}, + {"BA", "Jita\u00fana", "2918308"}, + {"BA", "Jo\u00e3o Dourado", "2918357"}, + {"BA", "Juazeiro", "2918407"}, + {"BA", "Jucuru\u00e7u", "2918456"}, + {"BA", "Jussara", "2918506"}, + {"BA", "Jussari", "2918555"}, + {"BA", "Jussiape", "2918605"}, + {"BA", "Lafaiete Coutinho", "2918704"}, + {"BA", "Lagoa Real", "2918753"}, + {"BA", "Laje", "2918803"}, + {"BA", "Lajed\u00e3o", "2918902"}, + {"BA", "Lajedinho", "2919009"}, + {"BA", "Lajedo do Tabocal", "2919058"}, + {"BA", "Lamar\u00e3o", "2919108"}, + {"BA", "Lap\u00e3o", "2919157"}, + {"BA", "Lauro de Freitas", "2919207"}, + {"BA", "Len\u00e7\u00f3is", "2919306"}, + {"BA", "Lic\u00ednio de Almeida", "2919405"}, + {"BA", "Livramento de Nossa Senhora", "2919504"}, + {"BA", "Lu\u00eds Eduardo Magalh\u00e3es", "2919553"}, + {"BA", "Macajuba", "2919603"}, + {"BA", "Macarani", "2919702"}, + {"BA", "Maca\u00fabas", "2919801"}, + {"BA", "Macurur\u00e9", "2919900"}, + {"BA", "Madre de Deus", "2919926"}, + {"BA", "Maetinga", "2919959"}, + {"BA", "Maiquinique", "2920007"}, + {"BA", "Mairi", "2920106"}, + {"BA", "Malhada", "2920205"}, + {"BA", "Malhada de Pedras", "2920304"}, + {"BA", "Manoel Vitorino", "2920403"}, + {"BA", "Mansid\u00e3o", "2920452"}, + {"BA", "Marac\u00e1s", "2920502"}, + {"BA", "Maragogipe", "2920601"}, + {"BA", "Mara\u00fa", "2920700"}, + {"BA", "Marcion\u00edlio Souza", "2920809"}, + {"BA", "Mascote", "2920908"}, + {"BA", "Mata de S\u00e3o Jo\u00e3o", "2921005"}, + {"BA", "Matina", "2921054"}, + {"BA", "Medeiros Neto", "2921104"}, + {"BA", "Miguel Calmon", "2921203"}, + {"BA", "Milagres", "2921302"}, + {"BA", "Mirangaba", "2921401"}, + {"BA", "Mirante", "2921450"}, + {"BA", "Monte Santo", "2921500"}, + {"BA", "Morpar\u00e1", "2921609"}, + {"BA", "Morro do Chap\u00e9u", "2921708"}, + {"BA", "Mortugaba", "2921807"}, + {"BA", "Mucug\u00ea", "2921906"}, + {"BA", "Mucuri", "2922003"}, + {"BA", "Mulungu do Morro", "2922052"}, + {"BA", "Mundo Novo", "2922102"}, + {"BA", "Muniz Ferreira", "2922201"}, + {"BA", "Muqu\u00e9m do S\u00e3o Francisco", "2922250"}, + {"BA", "Muritiba", "2922300"}, + {"BA", "Mutu\u00edpe", "2922409"}, + {"BA", "Nazar\u00e9", "2922508"}, + {"BA", "Nilo Pe\u00e7anha", "2922607"}, + {"BA", "Nordestina", "2922656"}, + {"BA", "Nova Cana\u00e3", "2922706"}, + {"BA", "Nova F\u00e1tima", "2922730"}, + {"BA", "Nova Ibi\u00e1", "2922755"}, + {"BA", "Nova Itarana", "2922805"}, + {"BA", "Nova Reden\u00e7\u00e3o", "2922854"}, + {"BA", "Nova Soure", "2922904"}, + {"BA", "Nova Vi\u00e7osa", "2923001"}, + {"BA", "Novo Horizonte", "2923035"}, + {"BA", "Novo Triunfo", "2923050"}, + {"BA", "Olindina", "2923100"}, + {"BA", "Oliveira dos Brejinhos", "2923209"}, + {"BA", "Ouri\u00e7angas", "2923308"}, + {"BA", "Ourol\u00e2ndia", "2923357"}, + {"BA", "Palmas de Monte Alto", "2923407"}, + {"BA", "Palmeiras", "2923506"}, + {"BA", "Paramirim", "2923605"}, + {"BA", "Paratinga", "2923704"}, + {"BA", "Paripiranga", "2923803"}, + {"BA", "Pau Brasil", "2923902"}, + {"BA", "Paulo Afonso", "2924009"}, + {"BA", "P\u00e9 de Serra", "2924058"}, + {"BA", "Pedr\u00e3o", "2924108"}, + {"BA", "Pedro Alexandre", "2924207"}, + {"BA", "Piat\u00e3", "2924306"}, + {"BA", "Pil\u00e3o Arcado", "2924405"}, + {"BA", "Pinda\u00ed", "2924504"}, + {"BA", "Pindoba\u00e7u", "2924603"}, + {"BA", "Pintadas", "2924652"}, + {"BA", "Pira\u00ed do Norte", "2924678"}, + {"BA", "Pirip\u00e1", "2924702"}, + {"BA", "Piritiba", "2924801"}, + {"BA", "Planaltino", "2924900"}, + {"BA", "Planalto", "2925006"}, + {"BA", "Po\u00e7\u00f5es", "2925105"}, + {"BA", "Pojuca", "2925204"}, + {"BA", "Ponto Novo", "2925253"}, + {"BA", "Porto Seguro", "2925303"}, + {"BA", "Potiragu\u00e1", "2925402"}, + {"BA", "Prado", "2925501"}, + {"BA", "Presidente Dutra", "2925600"}, + {"BA", "Presidente J\u00e2nio Quadros", "2925709"}, + {"BA", "Presidente Tancredo Neves", "2925758"}, + {"BA", "Queimadas", "2925808"}, + {"BA", "Quijingue", "2925907"}, + {"BA", "Quixabeira", "2925931"}, + {"BA", "Rafael Jambeiro", "2925956"}, + {"BA", "Remanso", "2926004"}, + {"BA", "Retirol\u00e2ndia", "2926103"}, + {"BA", "Riach\u00e3o das Neves", "2926202"}, + {"BA", "Riach\u00e3o do Jacu\u00edpe", "2926301"}, + {"BA", "Riacho de Santana", "2926400"}, + {"BA", "Ribeira do Amparo", "2926509"}, + {"BA", "Ribeira do Pombal", "2926608"}, + {"BA", "Ribeir\u00e3o do Largo", "2926657"}, + {"BA", "Rio de Contas", "2926707"}, + {"BA", "Rio do Ant\u00f4nio", "2926806"}, + {"BA", "Rio do Pires", "2926905"}, + {"BA", "Rio Real", "2927002"}, + {"BA", "Rodelas", "2927101"}, + {"BA", "Ruy Barbosa", "2927200"}, + {"BA", "Salinas da Margarida", "2927309"}, + {"BA", "Salvador", "2927408"}, + {"BA", "Santa B\u00e1rbara", "2927507"}, + {"BA", "Santa Br\u00edgida", "2927606"}, + {"BA", "Santa Cruz Cabr\u00e1lia", "2927705"}, + {"BA", "Santa Cruz da Vit\u00f3ria", "2927804"}, + {"BA", "Santa In\u00eas", "2927903"}, + {"BA", "Santa Luzia", "2928059"}, + {"BA", "Santa Maria da Vit\u00f3ria", "2928109"}, + {"BA", "Santa Rita de C\u00e1ssia", "2928406"}, + {"BA", "Santa Terezinha", "2928505"}, + {"BA", "Santaluz", "2928000"}, + {"BA", "Santana", "2928208"}, + {"BA", "Santan\u00f3polis", "2928307"}, + {"BA", "Santo Amaro", "2928604"}, + {"BA", "Santo Ant\u00f4nio de Jesus", "2928703"}, + {"BA", "Santo Est\u00eav\u00e3o", "2928802"}, + {"BA", "S\u00e3o Desid\u00e9rio", "2928901"}, + {"BA", "S\u00e3o Domingos", "2928950"}, + {"BA", "S\u00e3o Felipe", "2929107"}, + {"BA", "S\u00e3o F\u00e9lix", "2929008"}, + {"BA", "S\u00e3o F\u00e9lix do Coribe", "2929057"}, + {"BA", "S\u00e3o Francisco do Conde", "2929206"}, + {"BA", "S\u00e3o Gabriel", "2929255"}, + {"BA", "S\u00e3o Gon\u00e7alo dos Campos", "2929305"}, + {"BA", "S\u00e3o Jos\u00e9 da Vit\u00f3ria", "2929354"}, + {"BA", "S\u00e3o Jos\u00e9 do Jacu\u00edpe", "2929370"}, + {"BA", "S\u00e3o Miguel das Matas", "2929404"}, + {"BA", "S\u00e3o Sebasti\u00e3o do Pass\u00e9", "2929503"}, + {"BA", "Sapea\u00e7u", "2929602"}, + {"BA", "S\u00e1tiro Dias", "2929701"}, + {"BA", "Saubara", "2929750"}, + {"BA", "Sa\u00fade", "2929800"}, + {"BA", "Seabra", "2929909"}, + {"BA", "Sebasti\u00e3o Laranjeiras", "2930006"}, + {"BA", "Senhor do Bonfim", "2930105"}, + {"BA", "Sento S\u00e9", "2930204"}, + {"BA", "Serra do Ramalho", "2930154"}, + {"BA", "Serra Dourada", "2930303"}, + {"BA", "Serra Preta", "2930402"}, + {"BA", "Serrinha", "2930501"}, + {"BA", "Serrol\u00e2ndia", "2930600"}, + {"BA", "Sim\u00f5es Filho", "2930709"}, + {"BA", "S\u00edtio do Mato", "2930758"}, + {"BA", "S\u00edtio do Quinto", "2930766"}, + {"BA", "Sobradinho", "2930774"}, + {"BA", "Souto Soares", "2930808"}, + {"BA", "Tabocas do Brejo Velho", "2930907"}, + {"BA", "Tanha\u00e7u", "2931004"}, + {"BA", "Tanque Novo", "2931053"}, + {"BA", "Tanquinho", "2931103"}, + {"BA", "Tapero\u00e1", "2931202"}, + {"BA", "Tapiramut\u00e1", "2931301"}, + {"BA", "Teixeira de Freitas", "2931350"}, + {"BA", "Teodoro Sampaio", "2931400"}, + {"BA", "Teofil\u00e2ndia", "2931509"}, + {"BA", "Teol\u00e2ndia", "2931608"}, + {"BA", "Terra Nova", "2931707"}, + {"BA", "Tremedal", "2931806"}, + {"BA", "Tucano", "2931905"}, + {"BA", "Uau\u00e1", "2932002"}, + {"BA", "Uba\u00edra", "2932101"}, + {"BA", "Ubaitaba", "2932200"}, + {"BA", "Ubat\u00e3", "2932309"}, + {"BA", "Uiba\u00ed", "2932408"}, + {"BA", "Umburanas", "2932457"}, + {"BA", "Una", "2932507"}, + {"BA", "Urandi", "2932606"}, + {"BA", "Uru\u00e7uca", "2932705"}, + {"BA", "Utinga", "2932804"}, + {"BA", "Valen\u00e7a", "2932903"}, + {"BA", "Valente", "2933000"}, + {"BA", "V\u00e1rzea da Ro\u00e7a", "2933059"}, + {"BA", "V\u00e1rzea do Po\u00e7o", "2933109"}, + {"BA", "V\u00e1rzea Nova", "2933158"}, + {"BA", "Varzedo", "2933174"}, + {"BA", "Vera Cruz", "2933208"}, + {"BA", "Vereda", "2933257"}, + {"BA", "Vit\u00f3ria da Conquista", "2933307"}, + {"BA", "Wagner", "2933406"}, + {"BA", "Wanderley", "2933455"}, + {"BA", "Wenceslau Guimar\u00e3es", "2933505"}, + {"BA", "Xique-Xique", "2933604"}, + {"CE", "Abaiara", "2300101"}, + {"CE", "Acarape", "2300150"}, + {"CE", "Acara\u00fa", "2300200"}, + {"CE", "Acopiara", "2300309"}, + {"CE", "Aiuaba", "2300408"}, + {"CE", "Alc\u00e2ntaras", "2300507"}, + {"CE", "Altaneira", "2300606"}, + {"CE", "Alto Santo", "2300705"}, + {"CE", "Amontada", "2300754"}, + {"CE", "Antonina do Norte", "2300804"}, + {"CE", "Apuiar\u00e9s", "2300903"}, + {"CE", "Aquiraz", "2301000"}, + {"CE", "Aracati", "2301109"}, + {"CE", "Aracoiaba", "2301208"}, + {"CE", "Ararend\u00e1", "2301257"}, + {"CE", "Araripe", "2301307"}, + {"CE", "Aratuba", "2301406"}, + {"CE", "Arneiroz", "2301505"}, + {"CE", "Assar\u00e9", "2301604"}, + {"CE", "Aurora", "2301703"}, + {"CE", "Baixio", "2301802"}, + {"CE", "Banabui\u00fa", "2301851"}, + {"CE", "Barbalha", "2301901"}, + {"CE", "Barreira", "2301950"}, + {"CE", "Barro", "2302008"}, + {"CE", "Barroquinha", "2302057"}, + {"CE", "Baturit\u00e9", "2302107"}, + {"CE", "Beberibe", "2302206"}, + {"CE", "Bela Cruz", "2302305"}, + {"CE", "Boa Viagem", "2302404"}, + {"CE", "Brejo Santo", "2302503"}, + {"CE", "Camocim", "2302602"}, + {"CE", "Campos Sales", "2302701"}, + {"CE", "Canind\u00e9", "2302800"}, + {"CE", "Capistrano", "2302909"}, + {"CE", "Caridade", "2303006"}, + {"CE", "Carir\u00e9", "2303105"}, + {"CE", "Cariria\u00e7u", "2303204"}, + {"CE", "Cari\u00fas", "2303303"}, + {"CE", "Carnaubal", "2303402"}, + {"CE", "Cascavel", "2303501"}, + {"CE", "Catarina", "2303600"}, + {"CE", "Catunda", "2303659"}, + {"CE", "Caucaia", "2303709"}, + {"CE", "Cedro", "2303808"}, + {"CE", "Chaval", "2303907"}, + {"CE", "Chor\u00f3", "2303931"}, + {"CE", "Chorozinho", "2303956"}, + {"CE", "Corea\u00fa", "2304004"}, + {"CE", "Crate\u00fas", "2304103"}, + {"CE", "Crato", "2304202"}, + {"CE", "Croat\u00e1", "2304236"}, + {"CE", "Cruz", "2304251"}, + {"CE", "Deputado Irapuan Pinheiro", "2304269"}, + {"CE", "Erer\u00e9", "2304277"}, + {"CE", "Eus\u00e9bio", "2304285"}, + {"CE", "Farias Brito", "2304301"}, + {"CE", "Forquilha", "2304350"}, + {"CE", "Fortaleza", "2304400"}, + {"CE", "Fortim", "2304459"}, + {"CE", "Frecheirinha", "2304509"}, + {"CE", "General Sampaio", "2304608"}, + {"CE", "Gra\u00e7a", "2304657"}, + {"CE", "Granja", "2304707"}, + {"CE", "Granjeiro", "2304806"}, + {"CE", "Groa\u00edras", "2304905"}, + {"CE", "Guai\u00faba", "2304954"}, + {"CE", "Guaraciaba do Norte", "2305001"}, + {"CE", "Guaramiranga", "2305100"}, + {"CE", "Hidrol\u00e2ndia", "2305209"}, + {"CE", "Horizonte", "2305233"}, + {"CE", "Ibaretama", "2305266"}, + {"CE", "Ibiapina", "2305308"}, + {"CE", "Ibicuitinga", "2305332"}, + {"CE", "Icapu\u00ed", "2305357"}, + {"CE", "Ic\u00f3", "2305407"}, + {"CE", "Iguatu", "2305506"}, + {"CE", "Independ\u00eancia", "2305605"}, + {"CE", "Ipaporanga", "2305654"}, + {"CE", "Ipaumirim", "2305704"}, + {"CE", "Ipu", "2305803"}, + {"CE", "Ipueiras", "2305902"}, + {"CE", "Iracema", "2306009"}, + {"CE", "Irau\u00e7uba", "2306108"}, + {"CE", "Itai\u00e7aba", "2306207"}, + {"CE", "Itaitinga", "2306256"}, + {"CE", "Itapaj\u00e9", "2306306"}, + {"CE", "Itapipoca", "2306405"}, + {"CE", "Itapi\u00fana", "2306504"}, + {"CE", "Itarema", "2306553"}, + {"CE", "Itatira", "2306603"}, + {"CE", "Jaguaretama", "2306702"}, + {"CE", "Jaguaribara", "2306801"}, + {"CE", "Jaguaribe", "2306900"}, + {"CE", "Jaguaruana", "2307007"}, + {"CE", "Jardim", "2307106"}, + {"CE", "Jati", "2307205"}, + {"CE", "Jijoca de Jericoacoara", "2307254"}, + {"CE", "Juazeiro do Norte", "2307304"}, + {"CE", "Juc\u00e1s", "2307403"}, + {"CE", "Lavras da Mangabeira", "2307502"}, + {"CE", "Limoeiro do Norte", "2307601"}, + {"CE", "Madalena", "2307635"}, + {"CE", "Maracana\u00fa", "2307650"}, + {"CE", "Maranguape", "2307700"}, + {"CE", "Marco", "2307809"}, + {"CE", "Martin\u00f3pole", "2307908"}, + {"CE", "Massap\u00ea", "2308005"}, + {"CE", "Mauriti", "2308104"}, + {"CE", "Meruoca", "2308203"}, + {"CE", "Milagres", "2308302"}, + {"CE", "Milh\u00e3", "2308351"}, + {"CE", "Mira\u00edma", "2308377"}, + {"CE", "Miss\u00e3o Velha", "2308401"}, + {"CE", "Momba\u00e7a", "2308500"}, + {"CE", "Monsenhor Tabosa", "2308609"}, + {"CE", "Morada Nova", "2308708"}, + {"CE", "Mora\u00fajo", "2308807"}, + {"CE", "Morrinhos", "2308906"}, + {"CE", "Mucambo", "2309003"}, + {"CE", "Mulungu", "2309102"}, + {"CE", "Nova Olinda", "2309201"}, + {"CE", "Nova Russas", "2309300"}, + {"CE", "Novo Oriente", "2309409"}, + {"CE", "Ocara", "2309458"}, + {"CE", "Or\u00f3s", "2309508"}, + {"CE", "Pacajus", "2309607"}, + {"CE", "Pacatuba", "2309706"}, + {"CE", "Pacoti", "2309805"}, + {"CE", "Pacuj\u00e1", "2309904"}, + {"CE", "Palhano", "2310001"}, + {"CE", "Palm\u00e1cia", "2310100"}, + {"CE", "Paracuru", "2310209"}, + {"CE", "Paraipaba", "2310258"}, + {"CE", "Parambu", "2310308"}, + {"CE", "Paramoti", "2310407"}, + {"CE", "Pedra Branca", "2310506"}, + {"CE", "Penaforte", "2310605"}, + {"CE", "Pentecoste", "2310704"}, + {"CE", "Pereiro", "2310803"}, + {"CE", "Pindoretama", "2310852"}, + {"CE", "Piquet Carneiro", "2310902"}, + {"CE", "Pires Ferreira", "2310951"}, + {"CE", "Poranga", "2311009"}, + {"CE", "Porteiras", "2311108"}, + {"CE", "Potengi", "2311207"}, + {"CE", "Potiretama", "2311231"}, + {"CE", "Quiterian\u00f3polis", "2311264"}, + {"CE", "Quixad\u00e1", "2311306"}, + {"CE", "Quixel\u00f4", "2311355"}, + {"CE", "Quixeramobim", "2311405"}, + {"CE", "Quixer\u00e9", "2311504"}, + {"CE", "Reden\u00e7\u00e3o", "2311603"}, + {"CE", "Reriutaba", "2311702"}, + {"CE", "Russas", "2311801"}, + {"CE", "Saboeiro", "2311900"}, + {"CE", "Salitre", "2311959"}, + {"CE", "Santa Quit\u00e9ria", "2312205"}, + {"CE", "Santana do Acara\u00fa", "2312007"}, + {"CE", "Santana do Cariri", "2312106"}, + {"CE", "S\u00e3o Benedito", "2312304"}, + {"CE", "S\u00e3o Gon\u00e7alo do Amarante", "2312403"}, + {"CE", "S\u00e3o Jo\u00e3o do Jaguaribe", "2312502"}, + {"CE", "S\u00e3o Lu\u00eds do Curu", "2312601"}, + {"CE", "Senador Pompeu", "2312700"}, + {"CE", "Senador S\u00e1", "2312809"}, + {"CE", "Sobral", "2312908"}, + {"CE", "Solon\u00f3pole", "2313005"}, + {"CE", "Tabuleiro do Norte", "2313104"}, + {"CE", "Tamboril", "2313203"}, + {"CE", "Tarrafas", "2313252"}, + {"CE", "Tau\u00e1", "2313302"}, + {"CE", "Teju\u00e7uoca", "2313351"}, + {"CE", "Tiangu\u00e1", "2313401"}, + {"CE", "Trairi", "2313500"}, + {"CE", "Tururu", "2313559"}, + {"CE", "Ubajara", "2313609"}, + {"CE", "Umari", "2313708"}, + {"CE", "Umirim", "2313757"}, + {"CE", "Uruburetama", "2313807"}, + {"CE", "Uruoca", "2313906"}, + {"CE", "Varjota", "2313955"}, + {"CE", "V\u00e1rzea Alegre", "2314003"}, + {"CE", "Vi\u00e7osa do Cear\u00e1", "2314102"}, + {"DF", "Bras\u00edlia", "5300108"}, + {"ES", "Afonso Cl\u00e1udio", "3200102"}, + {"ES", "\u00c1gua Doce do Norte", "3200169"}, + {"ES", "\u00c1guia Branca", "3200136"}, + {"ES", "Alegre", "3200201"}, + {"ES", "Alfredo Chaves", "3200300"}, + {"ES", "Alto Rio Novo", "3200359"}, + {"ES", "Anchieta", "3200409"}, + {"ES", "Apiac\u00e1", "3200508"}, + {"ES", "Aracruz", "3200607"}, + {"ES", "At\u00edlio Viv\u00e1cqua", "3200706"}, + {"ES", "Baixo Guandu", "3200805"}, + {"ES", "Barra de S\u00e3o Francisco", "3200904"}, + {"ES", "Boa Esperan\u00e7a", "3201001"}, + {"ES", "Bom Jesus do Norte", "3201100"}, + {"ES", "Brejetuba", "3201159"}, + {"ES", "Cachoeiro de Itapemirim", "3201209"}, + {"ES", "Cariacica", "3201308"}, + {"ES", "Castelo", "3201407"}, + {"ES", "Colatina", "3201506"}, + {"ES", "Concei\u00e7\u00e3o da Barra", "3201605"}, + {"ES", "Concei\u00e7\u00e3o do Castelo", "3201704"}, + {"ES", "Divino de S\u00e3o Louren\u00e7o", "3201803"}, + {"ES", "Domingos Martins", "3201902"}, + {"ES", "Dores do Rio Preto", "3202009"}, + {"ES", "Ecoporanga", "3202108"}, + {"ES", "Fund\u00e3o", "3202207"}, + {"ES", "Governador Lindenberg", "3202256"}, + {"ES", "Gua\u00e7u\u00ed", "3202306"}, + {"ES", "Guarapari", "3202405"}, + {"ES", "Ibatiba", "3202454"}, + {"ES", "Ibira\u00e7u", "3202504"}, + {"ES", "Ibitirama", "3202553"}, + {"ES", "Iconha", "3202603"}, + {"ES", "Irupi", "3202652"}, + {"ES", "Itagua\u00e7u", "3202702"}, + {"ES", "Itapemirim", "3202801"}, + {"ES", "Itarana", "3202900"}, + {"ES", "I\u00fana", "3203007"}, + {"ES", "Jaguar\u00e9", "3203056"}, + {"ES", "Jer\u00f4nimo Monteiro", "3203106"}, + {"ES", "Jo\u00e3o Neiva", "3203130"}, + {"ES", "Laranja da Terra", "3203163"}, + {"ES", "Linhares", "3203205"}, + {"ES", "Manten\u00f3polis", "3203304"}, + {"ES", "Marata\u00edzes", "3203320"}, + {"ES", "Marechal Floriano", "3203346"}, + {"ES", "Maril\u00e2ndia", "3203353"}, + {"ES", "Mimoso do Sul", "3203403"}, + {"ES", "Montanha", "3203502"}, + {"ES", "Mucurici", "3203601"}, + {"ES", "Muniz Freire", "3203700"}, + {"ES", "Muqui", "3203809"}, + {"ES", "Nova Ven\u00e9cia", "3203908"}, + {"ES", "Pancas", "3204005"}, + {"ES", "Pedro Can\u00e1rio", "3204054"}, + {"ES", "Pinheiros", "3204104"}, + {"ES", "Pi\u00fama", "3204203"}, + {"ES", "Ponto Belo", "3204252"}, + {"ES", "Presidente Kennedy", "3204302"}, + {"ES", "Rio Bananal", "3204351"}, + {"ES", "Rio Novo do Sul", "3204401"}, + {"ES", "Santa Leopoldina", "3204500"}, + {"ES", "Santa Maria de Jetib\u00e1", "3204559"}, + {"ES", "Santa Teresa", "3204609"}, + {"ES", "S\u00e3o Domingos do Norte", "3204658"}, + {"ES", "S\u00e3o Gabriel da Palha", "3204708"}, + {"ES", "S\u00e3o Jos\u00e9 do Cal\u00e7ado", "3204807"}, + {"ES", "S\u00e3o Mateus", "3204906"}, + {"ES", "S\u00e3o Roque do Cana\u00e3", "3204955"}, + {"ES", "Serra", "3205002"}, + {"ES", "Sooretama", "3205010"}, + {"ES", "Vargem Alta", "3205036"}, + {"ES", "Venda Nova do Imigrante", "3205069"}, + {"ES", "Viana", "3205101"}, + {"ES", "Vila Pav\u00e3o", "3205150"}, + {"ES", "Vila Val\u00e9rio", "3205176"}, + {"ES", "Vila Velha", "3205200"}, + {"ES", "Vit\u00f3ria", "3205309"}, + {"GO", "Abadia de Goi\u00e1s", "5200050"}, + {"GO", "Abadi\u00e2nia", "5200100"}, + {"GO", "Acre\u00fana", "5200134"}, + {"GO", "Adel\u00e2ndia", "5200159"}, + {"GO", "\u00c1gua Fria de Goi\u00e1s", "5200175"}, + {"GO", "\u00c1gua Limpa", "5200209"}, + {"GO", "\u00c1guas Lindas de Goi\u00e1s", "5200258"}, + {"GO", "Alex\u00e2nia", "5200308"}, + {"GO", "Alo\u00e2ndia", "5200506"}, + {"GO", "Alto Horizonte", "5200555"}, + {"GO", "Alto Para\u00edso de Goi\u00e1s", "5200605"}, + {"GO", "Alvorada do Norte", "5200803"}, + {"GO", "Amaralina", "5200829"}, + {"GO", "Americano do Brasil", "5200852"}, + {"GO", "Amorin\u00f3polis", "5200902"}, + {"GO", "An\u00e1polis", "5201108"}, + {"GO", "Anhanguera", "5201207"}, + {"GO", "Anicuns", "5201306"}, + {"GO", "Aparecida de Goi\u00e2nia", "5201405"}, + {"GO", "Aparecida do Rio Doce", "5201454"}, + {"GO", "Apor\u00e9", "5201504"}, + {"GO", "Ara\u00e7u", "5201603"}, + {"GO", "Aragar\u00e7as", "5201702"}, + {"GO", "Aragoi\u00e2nia", "5201801"}, + {"GO", "Araguapaz", "5202155"}, + {"GO", "Aren\u00f3polis", "5202353"}, + {"GO", "Aruan\u00e3", "5202502"}, + {"GO", "Auril\u00e2ndia", "5202601"}, + {"GO", "Avelin\u00f3polis", "5202809"}, + {"GO", "Baliza", "5203104"}, + {"GO", "Barro Alto", "5203203"}, + {"GO", "Bela Vista de Goi\u00e1s", "5203302"}, + {"GO", "Bom Jardim de Goi\u00e1s", "5203401"}, + {"GO", "Bom Jesus de Goi\u00e1s", "5203500"}, + {"GO", "Bonfin\u00f3polis", "5203559"}, + {"GO", "Bon\u00f3polis", "5203575"}, + {"GO", "Brazabrantes", "5203609"}, + {"GO", "Brit\u00e2nia", "5203807"}, + {"GO", "Buriti Alegre", "5203906"}, + {"GO", "Buriti de Goi\u00e1s", "5203939"}, + {"GO", "Buritin\u00f3polis", "5203962"}, + {"GO", "Cabeceiras", "5204003"}, + {"GO", "Cachoeira Alta", "5204102"}, + {"GO", "Cachoeira de Goi\u00e1s", "5204201"}, + {"GO", "Cachoeira Dourada", "5204250"}, + {"GO", "Ca\u00e7u", "5204300"}, + {"GO", "Caiap\u00f4nia", "5204409"}, + {"GO", "Caldas Novas", "5204508"}, + {"GO", "Caldazinha", "5204557"}, + {"GO", "Campestre de Goi\u00e1s", "5204607"}, + {"GO", "Campina\u00e7u", "5204656"}, + {"GO", "Campinorte", "5204706"}, + {"GO", "Campo Alegre de Goi\u00e1s", "5204805"}, + {"GO", "Campo Limpo de Goi\u00e1s", "5204854"}, + {"GO", "Campos Belos", "5204904"}, + {"GO", "Campos Verdes", "5204953"}, + {"GO", "Carmo do Rio Verde", "5205000"}, + {"GO", "Castel\u00e2ndia", "5205059"}, + {"GO", "Catal\u00e3o", "5205109"}, + {"GO", "Catura\u00ed", "5205208"}, + {"GO", "Cavalcante", "5205307"}, + {"GO", "Ceres", "5205406"}, + {"GO", "Cezarina", "5205455"}, + {"GO", "Chapad\u00e3o do C\u00e9u", "5205471"}, + {"GO", "Cidade Ocidental", "5205497"}, + {"GO", "Cocalzinho de Goi\u00e1s", "5205513"}, + {"GO", "Colinas do Sul", "5205521"}, + {"GO", "C\u00f3rrego do Ouro", "5205703"}, + {"GO", "Corumb\u00e1 de Goi\u00e1s", "5205802"}, + {"GO", "Corumba\u00edba", "5205901"}, + {"GO", "Cristalina", "5206206"}, + {"GO", "Cristian\u00f3polis", "5206305"}, + {"GO", "Crix\u00e1s", "5206404"}, + {"GO", "Crom\u00ednia", "5206503"}, + {"GO", "Cumari", "5206602"}, + {"GO", "Damian\u00f3polis", "5206701"}, + {"GO", "Damol\u00e2ndia", "5206800"}, + {"GO", "Davin\u00f3polis", "5206909"}, + {"GO", "Diorama", "5207105"}, + {"GO", "Divin\u00f3polis de Goi\u00e1s", "5208301"}, + {"GO", "Doverl\u00e2ndia", "5207253"}, + {"GO", "Edealina", "5207352"}, + {"GO", "Ed\u00e9ia", "5207402"}, + {"GO", "Estrela do Norte", "5207501"}, + {"GO", "Faina", "5207535"}, + {"GO", "Fazenda Nova", "5207600"}, + {"GO", "Firmin\u00f3polis", "5207808"}, + {"GO", "Flores de Goi\u00e1s", "5207907"}, + {"GO", "Formosa", "5208004"}, + {"GO", "Formoso", "5208103"}, + {"GO", "Gameleira de Goi\u00e1s", "5208152"}, + {"GO", "Goian\u00e1polis", "5208400"}, + {"GO", "Goiandira", "5208509"}, + {"GO", "Goian\u00e9sia", "5208608"}, + {"GO", "Goi\u00e2nia", "5208707"}, + {"GO", "Goianira", "5208806"}, + {"GO", "Goi\u00e1s", "5208905"}, + {"GO", "Goiatuba", "5209101"}, + {"GO", "Gouvel\u00e2ndia", "5209150"}, + {"GO", "Guap\u00f3", "5209200"}, + {"GO", "Guara\u00edta", "5209291"}, + {"GO", "Guarani de Goi\u00e1s", "5209408"}, + {"GO", "Guarinos", "5209457"}, + {"GO", "Heitora\u00ed", "5209606"}, + {"GO", "Hidrol\u00e2ndia", "5209705"}, + {"GO", "Hidrolina", "5209804"}, + {"GO", "Iaciara", "5209903"}, + {"GO", "Inaciol\u00e2ndia", "5209937"}, + {"GO", "Indiara", "5209952"}, + {"GO", "Inhumas", "5210000"}, + {"GO", "Ipameri", "5210109"}, + {"GO", "Ipiranga de Goi\u00e1s", "5210158"}, + {"GO", "Ipor\u00e1", "5210208"}, + {"GO", "Israel\u00e2ndia", "5210307"}, + {"GO", "Itabera\u00ed", "5210406"}, + {"GO", "Itaguari", "5210562"}, + {"GO", "Itaguaru", "5210604"}, + {"GO", "Itaj\u00e1", "5210802"}, + {"GO", "Itapaci", "5210901"}, + {"GO", "Itapirapu\u00e3", "5211008"}, + {"GO", "Itapuranga", "5211206"}, + {"GO", "Itarum\u00e3", "5211305"}, + {"GO", "Itau\u00e7u", "5211404"}, + {"GO", "Itumbiara", "5211503"}, + {"GO", "Ivol\u00e2ndia", "5211602"}, + {"GO", "Jandaia", "5211701"}, + {"GO", "Jaragu\u00e1", "5211800"}, + {"GO", "Jata\u00ed", "5211909"}, + {"GO", "Jaupaci", "5212006"}, + {"GO", "Jes\u00fapolis", "5212055"}, + {"GO", "Jovi\u00e2nia", "5212105"}, + {"GO", "Jussara", "5212204"}, + {"GO", "Lagoa Santa", "5212253"}, + {"GO", "Leopoldo de Bulh\u00f5es", "5212303"}, + {"GO", "Luzi\u00e2nia", "5212501"}, + {"GO", "Mairipotaba", "5212600"}, + {"GO", "Mamba\u00ed", "5212709"}, + {"GO", "Mara Rosa", "5212808"}, + {"GO", "Marzag\u00e3o", "5212907"}, + {"GO", "Matrinch\u00e3", "5212956"}, + {"GO", "Mauril\u00e2ndia", "5213004"}, + {"GO", "Mimoso de Goi\u00e1s", "5213053"}, + {"GO", "Mina\u00e7u", "5213087"}, + {"GO", "Mineiros", "5213103"}, + {"GO", "Moipor\u00e1", "5213400"}, + {"GO", "Monte Alegre de Goi\u00e1s", "5213509"}, + {"GO", "Montes Claros de Goi\u00e1s", "5213707"}, + {"GO", "Montividiu", "5213756"}, + {"GO", "Montividiu do Norte", "5213772"}, + {"GO", "Morrinhos", "5213806"}, + {"GO", "Morro Agudo de Goi\u00e1s", "5213855"}, + {"GO", "Moss\u00e2medes", "5213905"}, + {"GO", "Mozarl\u00e2ndia", "5214002"}, + {"GO", "Mundo Novo", "5214051"}, + {"GO", "Mutun\u00f3polis", "5214101"}, + {"GO", "Naz\u00e1rio", "5214408"}, + {"GO", "Ner\u00f3polis", "5214507"}, + {"GO", "Niquel\u00e2ndia", "5214606"}, + {"GO", "Nova Am\u00e9rica", "5214705"}, + {"GO", "Nova Aurora", "5214804"}, + {"GO", "Nova Crix\u00e1s", "5214838"}, + {"GO", "Nova Gl\u00f3ria", "5214861"}, + {"GO", "Nova Igua\u00e7u de Goi\u00e1s", "5214879"}, + {"GO", "Nova Roma", "5214903"}, + {"GO", "Nova Veneza", "5215009"}, + {"GO", "Novo Brasil", "5215207"}, + {"GO", "Novo Gama", "5215231"}, + {"GO", "Novo Planalto", "5215256"}, + {"GO", "Orizona", "5215306"}, + {"GO", "Ouro Verde de Goi\u00e1s", "5215405"}, + {"GO", "Ouvidor", "5215504"}, + {"GO", "Padre Bernardo", "5215603"}, + {"GO", "Palestina de Goi\u00e1s", "5215652"}, + {"GO", "Palmeiras de Goi\u00e1s", "5215702"}, + {"GO", "Palmelo", "5215801"}, + {"GO", "Palmin\u00f3polis", "5215900"}, + {"GO", "Panam\u00e1", "5216007"}, + {"GO", "Paranaiguara", "5216304"}, + {"GO", "Para\u00fana", "5216403"}, + {"GO", "Perol\u00e2ndia", "5216452"}, + {"GO", "Petrolina de Goi\u00e1s", "5216809"}, + {"GO", "Pilar de Goi\u00e1s", "5216908"}, + {"GO", "Piracanjuba", "5217104"}, + {"GO", "Piranhas", "5217203"}, + {"GO", "Piren\u00f3polis", "5217302"}, + {"GO", "Pires do Rio", "5217401"}, + {"GO", "Planaltina", "5217609"}, + {"GO", "Pontalina", "5217708"}, + {"GO", "Porangatu", "5218003"}, + {"GO", "Porteir\u00e3o", "5218052"}, + {"GO", "Portel\u00e2ndia", "5218102"}, + {"GO", "Posse", "5218300"}, + {"GO", "Professor Jamil", "5218391"}, + {"GO", "Quirin\u00f3polis", "5218508"}, + {"GO", "Rialma", "5218607"}, + {"GO", "Rian\u00e1polis", "5218706"}, + {"GO", "Rio Quente", "5218789"}, + {"GO", "Rio Verde", "5218805"}, + {"GO", "Rubiataba", "5218904"}, + {"GO", "Sanclerl\u00e2ndia", "5219001"}, + {"GO", "Santa B\u00e1rbara de Goi\u00e1s", "5219100"}, + {"GO", "Santa Cruz de Goi\u00e1s", "5219209"}, + {"GO", "Santa F\u00e9 de Goi\u00e1s", "5219258"}, + {"GO", "Santa Helena de Goi\u00e1s", "5219308"}, + {"GO", "Santa Isabel", "5219357"}, + {"GO", "Santa Rita do Araguaia", "5219407"}, + {"GO", "Santa Rita do Novo Destino", "5219456"}, + {"GO", "Santa Rosa de Goi\u00e1s", "5219506"}, + {"GO", "Santa Tereza de Goi\u00e1s", "5219605"}, + {"GO", "Santa Terezinha de Goi\u00e1s", "5219704"}, + {"GO", "Santo Ant\u00f4nio da Barra", "5219712"}, + {"GO", "Santo Ant\u00f4nio de Goi\u00e1s", "5219738"}, + {"GO", "Santo Ant\u00f4nio do Descoberto", "5219753"}, + {"GO", "S\u00e3o Domingos", "5219803"}, + {"GO", "S\u00e3o Francisco de Goi\u00e1s", "5219902"}, + {"GO", "S\u00e3o Jo\u00e3o d'Alian\u00e7a", "5220009"}, + {"GO", "S\u00e3o Jo\u00e3o da Para\u00fana", "5220058"}, + {"GO", "S\u00e3o Lu\u00eds de Montes Belos", "5220108"}, + {"GO", "S\u00e3o Luiz do Norte", "5220157"}, + {"GO", "S\u00e3o Miguel do Araguaia", "5220207"}, + {"GO", "S\u00e3o Miguel do Passa Quatro", "5220264"}, + {"GO", "S\u00e3o Patr\u00edcio", "5220280"}, + {"GO", "S\u00e3o Sim\u00e3o", "5220405"}, + {"GO", "Senador Canedo", "5220454"}, + {"GO", "Serran\u00f3polis", "5220504"}, + {"GO", "Silv\u00e2nia", "5220603"}, + {"GO", "Simol\u00e2ndia", "5220686"}, + {"GO", "S\u00edtio d'Abadia", "5220702"}, + {"GO", "Taquaral de Goi\u00e1s", "5221007"}, + {"GO", "Teresina de Goi\u00e1s", "5221080"}, + {"GO", "Terez\u00f3polis de Goi\u00e1s", "5221197"}, + {"GO", "Tr\u00eas Ranchos", "5221304"}, + {"GO", "Trindade", "5221403"}, + {"GO", "Trombas", "5221452"}, + {"GO", "Turv\u00e2nia", "5221502"}, + {"GO", "Turvel\u00e2ndia", "5221551"}, + {"GO", "Uirapuru", "5221577"}, + {"GO", "Urua\u00e7u", "5221601"}, + {"GO", "Uruana", "5221700"}, + {"GO", "Uruta\u00ed", "5221809"}, + {"GO", "Valpara\u00edso de Goi\u00e1s", "5221858"}, + {"GO", "Varj\u00e3o", "5221908"}, + {"GO", "Vian\u00f3polis", "5222005"}, + {"GO", "Vicentin\u00f3polis", "5222054"}, + {"GO", "Vila Boa", "5222203"}, + {"GO", "Vila Prop\u00edcio", "5222302"}, + {"MA", "A\u00e7ail\u00e2ndia", "2100055"}, + {"MA", "Afonso Cunha", "2100105"}, + {"MA", "\u00c1gua Doce do Maranh\u00e3o", "2100154"}, + {"MA", "Alc\u00e2ntara", "2100204"}, + {"MA", "Aldeias Altas", "2100303"}, + {"MA", "Altamira do Maranh\u00e3o", "2100402"}, + {"MA", "Alto Alegre do Maranh\u00e3o", "2100436"}, + {"MA", "Alto Alegre do Pindar\u00e9", "2100477"}, + {"MA", "Alto Parna\u00edba", "2100501"}, + {"MA", "Amap\u00e1 do Maranh\u00e3o", "2100550"}, + {"MA", "Amarante do Maranh\u00e3o", "2100600"}, + {"MA", "Anajatuba", "2100709"}, + {"MA", "Anapurus", "2100808"}, + {"MA", "Apicum-A\u00e7u", "2100832"}, + {"MA", "Araguan\u00e3", "2100873"}, + {"MA", "Araioses", "2100907"}, + {"MA", "Arame", "2100956"}, + {"MA", "Arari", "2101004"}, + {"MA", "Axix\u00e1", "2101103"}, + {"MA", "Bacabal", "2101202"}, + {"MA", "Bacabeira", "2101251"}, + {"MA", "Bacuri", "2101301"}, + {"MA", "Bacurituba", "2101350"}, + {"MA", "Balsas", "2101400"}, + {"MA", "Bar\u00e3o de Graja\u00fa", "2101509"}, + {"MA", "Barra do Corda", "2101608"}, + {"MA", "Barreirinhas", "2101707"}, + {"MA", "Bela Vista do Maranh\u00e3o", "2101772"}, + {"MA", "Bel\u00e1gua", "2101731"}, + {"MA", "Benedito Leite", "2101806"}, + {"MA", "Bequim\u00e3o", "2101905"}, + {"MA", "Bernardo do Mearim", "2101939"}, + {"MA", "Boa Vista do Gurupi", "2101970"}, + {"MA", "Bom Jardim", "2102002"}, + {"MA", "Bom Jesus das Selvas", "2102036"}, + {"MA", "Bom Lugar", "2102077"}, + {"MA", "Brejo", "2102101"}, + {"MA", "Brejo de Areia", "2102150"}, + {"MA", "Buriti", "2102200"}, + {"MA", "Buriti Bravo", "2102309"}, + {"MA", "Buriticupu", "2102325"}, + {"MA", "Buritirana", "2102358"}, + {"MA", "Cachoeira Grande", "2102374"}, + {"MA", "Cajapi\u00f3", "2102408"}, + {"MA", "Cajari", "2102507"}, + {"MA", "Campestre do Maranh\u00e3o", "2102556"}, + {"MA", "C\u00e2ndido Mendes", "2102606"}, + {"MA", "Cantanhede", "2102705"}, + {"MA", "Capinzal do Norte", "2102754"}, + {"MA", "Carolina", "2102804"}, + {"MA", "Carutapera", "2102903"}, + {"MA", "Caxias", "2103000"}, + {"MA", "Cedral", "2103109"}, + {"MA", "Central do Maranh\u00e3o", "2103125"}, + {"MA", "Centro do Guilherme", "2103158"}, + {"MA", "Centro Novo do Maranh\u00e3o", "2103174"}, + {"MA", "Chapadinha", "2103208"}, + {"MA", "Cidel\u00e2ndia", "2103257"}, + {"MA", "Cod\u00f3", "2103307"}, + {"MA", "Coelho Neto", "2103406"}, + {"MA", "Colinas", "2103505"}, + {"MA", "Concei\u00e7\u00e3o do Lago-A\u00e7u", "2103554"}, + {"MA", "Coroat\u00e1", "2103604"}, + {"MA", "Cururupu", "2103703"}, + {"MA", "Davin\u00f3polis", "2103752"}, + {"MA", "Dom Pedro", "2103802"}, + {"MA", "Duque Bacelar", "2103901"}, + {"MA", "Esperantin\u00f3polis", "2104008"}, + {"MA", "Estreito", "2104057"}, + {"MA", "Feira Nova do Maranh\u00e3o", "2104073"}, + {"MA", "Fernando Falc\u00e3o", "2104081"}, + {"MA", "Formosa da Serra Negra", "2104099"}, + {"MA", "Fortaleza dos Nogueiras", "2104107"}, + {"MA", "Fortuna", "2104206"}, + {"MA", "Godofredo Viana", "2104305"}, + {"MA", "Gon\u00e7alves Dias", "2104404"}, + {"MA", "Governador Archer", "2104503"}, + {"MA", "Governador Edison Lob\u00e3o", "2104552"}, + {"MA", "Governador Eug\u00eanio Barros", "2104602"}, + {"MA", "Governador Luiz Rocha", "2104628"}, + {"MA", "Governador Newton Bello", "2104651"}, + {"MA", "Governador Nunes Freire", "2104677"}, + {"MA", "Gra\u00e7a Aranha", "2104701"}, + {"MA", "Graja\u00fa", "2104800"}, + {"MA", "Guimar\u00e3es", "2104909"}, + {"MA", "Humberto de Campos", "2105005"}, + {"MA", "Icatu", "2105104"}, + {"MA", "Igarap\u00e9 do Meio", "2105153"}, + {"MA", "Igarap\u00e9 Grande", "2105203"}, + {"MA", "Imperatriz", "2105302"}, + {"MA", "Itaipava do Graja\u00fa", "2105351"}, + {"MA", "Itapecuru Mirim", "2105401"}, + {"MA", "Itinga do Maranh\u00e3o", "2105427"}, + {"MA", "Jatob\u00e1", "2105450"}, + {"MA", "Jenipapo dos Vieiras", "2105476"}, + {"MA", "Jo\u00e3o Lisboa", "2105500"}, + {"MA", "Josel\u00e2ndia", "2105609"}, + {"MA", "Junco do Maranh\u00e3o", "2105658"}, + {"MA", "Lago da Pedra", "2105708"}, + {"MA", "Lago do Junco", "2105807"}, + {"MA", "Lago dos Rodrigues", "2105948"}, + {"MA", "Lago Verde", "2105906"}, + {"MA", "Lagoa do Mato", "2105922"}, + {"MA", "Lagoa Grande do Maranh\u00e3o", "2105963"}, + {"MA", "Lajeado Novo", "2105989"}, + {"MA", "Lima Campos", "2106003"}, + {"MA", "Loreto", "2106102"}, + {"MA", "Lu\u00eds Domingues", "2106201"}, + {"MA", "Magalh\u00e3es de Almeida", "2106300"}, + {"MA", "Maraca\u00e7um\u00e9", "2106326"}, + {"MA", "Maraj\u00e1 do Sena", "2106359"}, + {"MA", "Maranh\u00e3ozinho", "2106375"}, + {"MA", "Mata Roma", "2106409"}, + {"MA", "Matinha", "2106508"}, + {"MA", "Mat\u00f5es", "2106607"}, + {"MA", "Mat\u00f5es do Norte", "2106631"}, + {"MA", "Milagres do Maranh\u00e3o", "2106672"}, + {"MA", "Mirador", "2106706"}, + {"MA", "Miranda do Norte", "2106755"}, + {"MA", "Mirinzal", "2106805"}, + {"MA", "Mon\u00e7\u00e3o", "2106904"}, + {"MA", "Montes Altos", "2107001"}, + {"MA", "Morros", "2107100"}, + {"MA", "Nina Rodrigues", "2107209"}, + {"MA", "Nova Colinas", "2107258"}, + {"MA", "Nova Iorque", "2107308"}, + {"MA", "Nova Olinda do Maranh\u00e3o", "2107357"}, + {"MA", "Olho d'\u00c1gua das Cunh\u00e3s", "2107407"}, + {"MA", "Olinda Nova do Maranh\u00e3o", "2107456"}, + {"MA", "Pa\u00e7o do Lumiar", "2107506"}, + {"MA", "Palmeir\u00e2ndia", "2107605"}, + {"MA", "Paraibano", "2107704"}, + {"MA", "Parnarama", "2107803"}, + {"MA", "Passagem Franca", "2107902"}, + {"MA", "Pastos Bons", "2108009"}, + {"MA", "Paulino Neves", "2108058"}, + {"MA", "Paulo Ramos", "2108108"}, + {"MA", "Pedreiras", "2108207"}, + {"MA", "Pedro do Ros\u00e1rio", "2108256"}, + {"MA", "Penalva", "2108306"}, + {"MA", "Peri Mirim", "2108405"}, + {"MA", "Peritor\u00f3", "2108454"}, + {"MA", "Pindar\u00e9-Mirim", "2108504"}, + {"MA", "Pinheiro", "2108603"}, + {"MA", "Pio XII", "2108702"}, + {"MA", "Pirapemas", "2108801"}, + {"MA", "Po\u00e7\u00e3o de Pedras", "2108900"}, + {"MA", "Porto Franco", "2109007"}, + {"MA", "Porto Rico do Maranh\u00e3o", "2109056"}, + {"MA", "Presidente Dutra", "2109106"}, + {"MA", "Presidente Juscelino", "2109205"}, + {"MA", "Presidente M\u00e9dici", "2109239"}, + {"MA", "Presidente Sarney", "2109270"}, + {"MA", "Presidente Vargas", "2109304"}, + {"MA", "Primeira Cruz", "2109403"}, + {"MA", "Raposa", "2109452"}, + {"MA", "Riach\u00e3o", "2109502"}, + {"MA", "Ribamar Fiquene", "2109551"}, + {"MA", "Ros\u00e1rio", "2109601"}, + {"MA", "Samba\u00edba", "2109700"}, + {"MA", "Santa Filomena do Maranh\u00e3o", "2109759"}, + {"MA", "Santa Helena", "2109809"}, + {"MA", "Santa In\u00eas", "2109908"}, + {"MA", "Santa Luzia", "2110005"}, + {"MA", "Santa Luzia do Paru\u00e1", "2110039"}, + {"MA", "Santa Quit\u00e9ria do Maranh\u00e3o", "2110104"}, + {"MA", "Santa Rita", "2110203"}, + {"MA", "Santana do Maranh\u00e3o", "2110237"}, + {"MA", "Santo Amaro do Maranh\u00e3o", "2110278"}, + {"MA", "Santo Ant\u00f4nio dos Lopes", "2110302"}, + {"MA", "S\u00e3o Benedito do Rio Preto", "2110401"}, + {"MA", "S\u00e3o Bento", "2110500"}, + {"MA", "S\u00e3o Bernardo", "2110609"}, + {"MA", "S\u00e3o Domingos do Azeit\u00e3o", "2110658"}, + {"MA", "S\u00e3o Domingos do Maranh\u00e3o", "2110708"}, + {"MA", "S\u00e3o F\u00e9lix de Balsas", "2110807"}, + {"MA", "S\u00e3o Francisco do Brej\u00e3o", "2110856"}, + {"MA", "S\u00e3o Francisco do Maranh\u00e3o", "2110906"}, + {"MA", "S\u00e3o Jo\u00e3o Batista", "2111003"}, + {"MA", "S\u00e3o Jo\u00e3o do Car\u00fa", "2111029"}, + {"MA", "S\u00e3o Jo\u00e3o do Para\u00edso", "2111052"}, + {"MA", "S\u00e3o Jo\u00e3o do Soter", "2111078"}, + {"MA", "S\u00e3o Jo\u00e3o dos Patos", "2111102"}, + {"MA", "S\u00e3o Jos\u00e9 de Ribamar", "2111201"}, + {"MA", "S\u00e3o Jos\u00e9 dos Bas\u00edlios", "2111250"}, + {"MA", "S\u00e3o Lu\u00eds", "2111300"}, + {"MA", "S\u00e3o Lu\u00eds Gonzaga do Maranh\u00e3o", "2111409"}, + {"MA", "S\u00e3o Mateus do Maranh\u00e3o", "2111508"}, + {"MA", "S\u00e3o Pedro da \u00c1gua Branca", "2111532"}, + {"MA", "S\u00e3o Pedro dos Crentes", "2111573"}, + {"MA", "S\u00e3o Raimundo das Mangabeiras", "2111607"}, + {"MA", "S\u00e3o Raimundo do Doca Bezerra", "2111631"}, + {"MA", "S\u00e3o Roberto", "2111672"}, + {"MA", "S\u00e3o Vicente Ferrer", "2111706"}, + {"MA", "Satubinha", "2111722"}, + {"MA", "Senador Alexandre Costa", "2111748"}, + {"MA", "Senador La Rocque", "2111763"}, + {"MA", "Serrano do Maranh\u00e3o", "2111789"}, + {"MA", "S\u00edtio Novo", "2111805"}, + {"MA", "Sucupira do Norte", "2111904"}, + {"MA", "Sucupira do Riach\u00e3o", "2111953"}, + {"MA", "Tasso Fragoso", "2112001"}, + {"MA", "Timbiras", "2112100"}, + {"MA", "Timon", "2112209"}, + {"MA", "Trizidela do Vale", "2112233"}, + {"MA", "Tufil\u00e2ndia", "2112274"}, + {"MA", "Tuntum", "2112308"}, + {"MA", "Turia\u00e7u", "2112407"}, + {"MA", "Turil\u00e2ndia", "2112456"}, + {"MA", "Tut\u00f3ia", "2112506"}, + {"MA", "Urbano Santos", "2112605"}, + {"MA", "Vargem Grande", "2112704"}, + {"MA", "Viana", "2112803"}, + {"MA", "Vila Nova dos Mart\u00edrios", "2112852"}, + {"MA", "Vit\u00f3ria do Mearim", "2112902"}, + {"MA", "Vitorino Freire", "2113009"}, + {"MA", "Z\u00e9 Doca", "2114007"}, + {"MT", "Acorizal", "5100102"}, + {"MT", "\u00c1gua Boa", "5100201"}, + {"MT", "Alta Floresta", "5100250"}, + {"MT", "Alto Araguaia", "5100300"}, + {"MT", "Alto Boa Vista", "5100359"}, + {"MT", "Alto Gar\u00e7as", "5100409"}, + {"MT", "Alto Paraguai", "5100508"}, + {"MT", "Alto Taquari", "5100607"}, + {"MT", "Apiac\u00e1s", "5100805"}, + {"MT", "Araguaiana", "5101001"}, + {"MT", "Araguainha", "5101209"}, + {"MT", "Araputanga", "5101258"}, + {"MT", "Aren\u00e1polis", "5101308"}, + {"MT", "Aripuan\u00e3", "5101407"}, + {"MT", "Bar\u00e3o de Melga\u00e7o", "5101605"}, + {"MT", "Barra do Bugres", "5101704"}, + {"MT", "Barra do Gar\u00e7as", "5101803"}, + {"MT", "Boa Esperan\u00e7a do Norte", "5101837"}, + {"MT", "Bom Jesus do Araguaia", "5101852"}, + {"MT", "Brasnorte", "5101902"}, + {"MT", "C\u00e1ceres", "5102504"}, + {"MT", "Campin\u00e1polis", "5102603"}, + {"MT", "Campo Novo do Parecis", "5102637"}, + {"MT", "Campo Verde", "5102678"}, + {"MT", "Campos de J\u00falio", "5102686"}, + {"MT", "Canabrava do Norte", "5102694"}, + {"MT", "Canarana", "5102702"}, + {"MT", "Carlinda", "5102793"}, + {"MT", "Castanheira", "5102850"}, + {"MT", "Chapada dos Guimar\u00e3es", "5103007"}, + {"MT", "Cl\u00e1udia", "5103056"}, + {"MT", "Cocalinho", "5103106"}, + {"MT", "Col\u00edder", "5103205"}, + {"MT", "Colniza", "5103254"}, + {"MT", "Comodoro", "5103304"}, + {"MT", "Confresa", "5103353"}, + {"MT", "Conquista D'Oeste", "5103361"}, + {"MT", "Cotrigua\u00e7u", "5103379"}, + {"MT", "Cuiab\u00e1", "5103403"}, + {"MT", "Curvel\u00e2ndia", "5103437"}, + {"MT", "Denise", "5103452"}, + {"MT", "Diamantino", "5103502"}, + {"MT", "Dom Aquino", "5103601"}, + {"MT", "Feliz Natal", "5103700"}, + {"MT", "Figueir\u00f3polis D'Oeste", "5103809"}, + {"MT", "Ga\u00facha do Norte", "5103858"}, + {"MT", "General Carneiro", "5103908"}, + {"MT", "Gl\u00f3ria D'Oeste", "5103957"}, + {"MT", "Guarant\u00e3 do Norte", "5104104"}, + {"MT", "Guiratinga", "5104203"}, + {"MT", "Indiava\u00ed", "5104500"}, + {"MT", "Ipiranga do Norte", "5104526"}, + {"MT", "Itanhang\u00e1", "5104542"}, + {"MT", "Ita\u00faba", "5104559"}, + {"MT", "Itiquira", "5104609"}, + {"MT", "Jaciara", "5104807"}, + {"MT", "Jangada", "5104906"}, + {"MT", "Jauru", "5105002"}, + {"MT", "Juara", "5105101"}, + {"MT", "Ju\u00edna", "5105150"}, + {"MT", "Juruena", "5105176"}, + {"MT", "Juscimeira", "5105200"}, + {"MT", "Lambari D'Oeste", "5105234"}, + {"MT", "Lucas do Rio Verde", "5105259"}, + {"MT", "Luciara", "5105309"}, + {"MT", "Marcel\u00e2ndia", "5105580"}, + {"MT", "Matup\u00e1", "5105606"}, + {"MT", "Mirassol d'Oeste", "5105622"}, + {"MT", "Nobres", "5105903"}, + {"MT", "Nortel\u00e2ndia", "5106000"}, + {"MT", "Nossa Senhora do Livramento", "5106109"}, + {"MT", "Nova Bandeirantes", "5106158"}, + {"MT", "Nova Brasil\u00e2ndia", "5106208"}, + {"MT", "Nova Cana\u00e3 do Norte", "5106216"}, + {"MT", "Nova Guarita", "5108808"}, + {"MT", "Nova Lacerda", "5106182"}, + {"MT", "Nova Maril\u00e2ndia", "5108857"}, + {"MT", "Nova Maring\u00e1", "5108907"}, + {"MT", "Nova Monte Verde", "5108956"}, + {"MT", "Nova Mutum", "5106224"}, + {"MT", "Nova Nazar\u00e9", "5106174"}, + {"MT", "Nova Ol\u00edmpia", "5106232"}, + {"MT", "Nova Santa Helena", "5106190"}, + {"MT", "Nova Ubirat\u00e3", "5106240"}, + {"MT", "Nova Xavantina", "5106257"}, + {"MT", "Novo Horizonte do Norte", "5106273"}, + {"MT", "Novo Mundo", "5106265"}, + {"MT", "Novo Santo Ant\u00f4nio", "5106315"}, + {"MT", "Novo S\u00e3o Joaquim", "5106281"}, + {"MT", "Parana\u00edta", "5106299"}, + {"MT", "Paranatinga", "5106307"}, + {"MT", "Pedra Preta", "5106372"}, + {"MT", "Peixoto de Azevedo", "5106422"}, + {"MT", "Planalto da Serra", "5106455"}, + {"MT", "Pocon\u00e9", "5106505"}, + {"MT", "Pontal do Araguaia", "5106653"}, + {"MT", "Ponte Branca", "5106703"}, + {"MT", "Pontes e Lacerda", "5106752"}, + {"MT", "Porto Alegre do Norte", "5106778"}, + {"MT", "Porto dos Ga\u00fachos", "5106802"}, + {"MT", "Porto Esperidi\u00e3o", "5106828"}, + {"MT", "Porto Estrela", "5106851"}, + {"MT", "Poxor\u00e9u", "5107008"}, + {"MT", "Primavera do Leste", "5107040"}, + {"MT", "Quer\u00eancia", "5107065"}, + {"MT", "Reserva do Caba\u00e7al", "5107156"}, + {"MT", "Ribeir\u00e3o Cascalheira", "5107180"}, + {"MT", "Ribeir\u00e3ozinho", "5107198"}, + {"MT", "Rio Branco", "5107206"}, + {"MT", "Rondol\u00e2ndia", "5107578"}, + {"MT", "Rondon\u00f3polis", "5107602"}, + {"MT", "Ros\u00e1rio Oeste", "5107701"}, + {"MT", "Salto do C\u00e9u", "5107750"}, + {"MT", "Santa Carmem", "5107248"}, + {"MT", "Santa Cruz do Xingu", "5107743"}, + {"MT", "Santa Rita do Trivelato", "5107768"}, + {"MT", "Santa Terezinha", "5107776"}, + {"MT", "Santo Afonso", "5107263"}, + {"MT", "Santo Ant\u00f4nio de Leverger", "5107800"}, + {"MT", "Santo Ant\u00f4nio do Leste", "5107792"}, + {"MT", "S\u00e3o F\u00e9lix do Araguaia", "5107859"}, + {"MT", "S\u00e3o Jos\u00e9 do Povo", "5107297"}, + {"MT", "S\u00e3o Jos\u00e9 do Rio Claro", "5107305"}, + {"MT", "S\u00e3o Jos\u00e9 do Xingu", "5107354"}, + {"MT", "S\u00e3o Jos\u00e9 dos Quatro Marcos", "5107107"}, + {"MT", "S\u00e3o Pedro da Cipa", "5107404"}, + {"MT", "Sapezal", "5107875"}, + {"MT", "Serra Nova Dourada", "5107883"}, + {"MT", "Sinop", "5107909"}, + {"MT", "Sorriso", "5107925"}, + {"MT", "Tabapor\u00e3", "5107941"}, + {"MT", "Tangar\u00e1 da Serra", "5107958"}, + {"MT", "Tapurah", "5108006"}, + {"MT", "Terra Nova do Norte", "5108055"}, + {"MT", "Tesouro", "5108105"}, + {"MT", "Torixor\u00e9u", "5108204"}, + {"MT", "Uni\u00e3o do Sul", "5108303"}, + {"MT", "Vale de S\u00e3o Domingos", "5108352"}, + {"MT", "V\u00e1rzea Grande", "5108402"}, + {"MT", "Vera", "5108501"}, + {"MT", "Vila Bela da Sant\u00edssima Trindade", "5105507"}, + {"MT", "Vila Rica", "5108600"}, + {"MS", "\u00c1gua Clara", "5000203"}, + {"MS", "Alcin\u00f3polis", "5000252"}, + {"MS", "Amambai", "5000609"}, + {"MS", "Anast\u00e1cio", "5000708"}, + {"MS", "Anauril\u00e2ndia", "5000807"}, + {"MS", "Ang\u00e9lica", "5000856"}, + {"MS", "Ant\u00f4nio Jo\u00e3o", "5000906"}, + {"MS", "Aparecida do Taboado", "5001003"}, + {"MS", "Aquidauana", "5001102"}, + {"MS", "Aral Moreira", "5001243"}, + {"MS", "Bandeirantes", "5001508"}, + {"MS", "Bataguassu", "5001904"}, + {"MS", "Bataypor\u00e3", "5002001"}, + {"MS", "Bela Vista", "5002100"}, + {"MS", "Bodoquena", "5002159"}, + {"MS", "Bonito", "5002209"}, + {"MS", "Brasil\u00e2ndia", "5002308"}, + {"MS", "Caarap\u00f3", "5002407"}, + {"MS", "Camapu\u00e3", "5002605"}, + {"MS", "Campo Grande", "5002704"}, + {"MS", "Caracol", "5002803"}, + {"MS", "Cassil\u00e2ndia", "5002902"}, + {"MS", "Chapad\u00e3o do Sul", "5002951"}, + {"MS", "Corguinho", "5003108"}, + {"MS", "Coronel Sapucaia", "5003157"}, + {"MS", "Corumb\u00e1", "5003207"}, + {"MS", "Costa Rica", "5003256"}, + {"MS", "Coxim", "5003306"}, + {"MS", "Deod\u00e1polis", "5003454"}, + {"MS", "Dois Irm\u00e3os do Buriti", "5003488"}, + {"MS", "Douradina", "5003504"}, + {"MS", "Dourados", "5003702"}, + {"MS", "Eldorado", "5003751"}, + {"MS", "F\u00e1tima do Sul", "5003801"}, + {"MS", "Figueir\u00e3o", "5003900"}, + {"MS", "Gl\u00f3ria de Dourados", "5004007"}, + {"MS", "Guia Lopes da Laguna", "5004106"}, + {"MS", "Iguatemi", "5004304"}, + {"MS", "Inoc\u00eancia", "5004403"}, + {"MS", "Itapor\u00e3", "5004502"}, + {"MS", "Itaquira\u00ed", "5004601"}, + {"MS", "Ivinhema", "5004700"}, + {"MS", "Japor\u00e3", "5004809"}, + {"MS", "Jaraguari", "5004908"}, + {"MS", "Jardim", "5005004"}, + {"MS", "Jate\u00ed", "5005103"}, + {"MS", "Juti", "5005152"}, + {"MS", "Lad\u00e1rio", "5005202"}, + {"MS", "Laguna Carap\u00e3", "5005251"}, + {"MS", "Maracaju", "5005400"}, + {"MS", "Miranda", "5005608"}, + {"MS", "Mundo Novo", "5005681"}, + {"MS", "Navira\u00ed", "5005707"}, + {"MS", "Nioaque", "5005806"}, + {"MS", "Nova Alvorada do Sul", "5006002"}, + {"MS", "Nova Andradina", "5006200"}, + {"MS", "Novo Horizonte do Sul", "5006259"}, + {"MS", "Para\u00edso das \u00c1guas", "5006275"}, + {"MS", "Parana\u00edba", "5006309"}, + {"MS", "Paranhos", "5006358"}, + {"MS", "Pedro Gomes", "5006408"}, + {"MS", "Ponta Por\u00e3", "5006606"}, + {"MS", "Porto Murtinho", "5006903"}, + {"MS", "Ribas do Rio Pardo", "5007109"}, + {"MS", "Rio Brilhante", "5007208"}, + {"MS", "Rio Negro", "5007307"}, + {"MS", "Rio Verde de Mato Grosso", "5007406"}, + {"MS", "Rochedo", "5007505"}, + {"MS", "Santa Rita do Pardo", "5007554"}, + {"MS", "S\u00e3o Gabriel do Oeste", "5007695"}, + {"MS", "Selv\u00edria", "5007802"}, + {"MS", "Sete Quedas", "5007703"}, + {"MS", "Sidrol\u00e2ndia", "5007901"}, + {"MS", "Sonora", "5007935"}, + {"MS", "Tacuru", "5007950"}, + {"MS", "Taquarussu", "5007976"}, + {"MS", "Terenos", "5008008"}, + {"MS", "Tr\u00eas Lagoas", "5008305"}, + {"MS", "Vicentina", "5008404"}, + {"MG", "Abadia dos Dourados", "3100104"}, + {"MG", "Abaet\u00e9", "3100203"}, + {"MG", "Abre Campo", "3100302"}, + {"MG", "Acaiaca", "3100401"}, + {"MG", "A\u00e7ucena", "3100500"}, + {"MG", "\u00c1gua Boa", "3100609"}, + {"MG", "\u00c1gua Comprida", "3100708"}, + {"MG", "Aguanil", "3100807"}, + {"MG", "\u00c1guas Formosas", "3100906"}, + {"MG", "\u00c1guas Vermelhas", "3101003"}, + {"MG", "Aimor\u00e9s", "3101102"}, + {"MG", "Aiuruoca", "3101201"}, + {"MG", "Alagoa", "3101300"}, + {"MG", "Albertina", "3101409"}, + {"MG", "Al\u00e9m Para\u00edba", "3101508"}, + {"MG", "Alfenas", "3101607"}, + {"MG", "Alfredo Vasconcelos", "3101631"}, + {"MG", "Almenara", "3101706"}, + {"MG", "Alpercata", "3101805"}, + {"MG", "Alpin\u00f3polis", "3101904"}, + {"MG", "Alterosa", "3102001"}, + {"MG", "Alto Capara\u00f3", "3102050"}, + {"MG", "Alto Jequitib\u00e1", "3153509"}, + {"MG", "Alto Rio Doce", "3102100"}, + {"MG", "Alvarenga", "3102209"}, + {"MG", "Alvin\u00f3polis", "3102308"}, + {"MG", "Alvorada de Minas", "3102407"}, + {"MG", "Amparo do Serra", "3102506"}, + {"MG", "Andradas", "3102605"}, + {"MG", "Andrel\u00e2ndia", "3102803"}, + {"MG", "Angel\u00e2ndia", "3102852"}, + {"MG", "Ant\u00f4nio Carlos", "3102902"}, + {"MG", "Ant\u00f4nio Dias", "3103009"}, + {"MG", "Ant\u00f4nio Prado de Minas", "3103108"}, + {"MG", "Ara\u00e7a\u00ed", "3103207"}, + {"MG", "Aracitaba", "3103306"}, + {"MG", "Ara\u00e7ua\u00ed", "3103405"}, + {"MG", "Araguari", "3103504"}, + {"MG", "Arantina", "3103603"}, + {"MG", "Araponga", "3103702"}, + {"MG", "Arapor\u00e3", "3103751"}, + {"MG", "Arapu\u00e1", "3103801"}, + {"MG", "Ara\u00fajos", "3103900"}, + {"MG", "Arax\u00e1", "3104007"}, + {"MG", "Arceburgo", "3104106"}, + {"MG", "Arcos", "3104205"}, + {"MG", "Areado", "3104304"}, + {"MG", "Argirita", "3104403"}, + {"MG", "Aricanduva", "3104452"}, + {"MG", "Arinos", "3104502"}, + {"MG", "Astolfo Dutra", "3104601"}, + {"MG", "Atal\u00e9ia", "3104700"}, + {"MG", "Augusto de Lima", "3104809"}, + {"MG", "Baependi", "3104908"}, + {"MG", "Baldim", "3105004"}, + {"MG", "Bambu\u00ed", "3105103"}, + {"MG", "Bandeira", "3105202"}, + {"MG", "Bandeira do Sul", "3105301"}, + {"MG", "Bar\u00e3o de Cocais", "3105400"}, + {"MG", "Bar\u00e3o do Monte Alto", "3105509"}, + {"MG", "Barbacena", "3105608"}, + {"MG", "Barra Longa", "3105707"}, + {"MG", "Barroso", "3105905"}, + {"MG", "Bela Vista de Minas", "3106002"}, + {"MG", "Belmiro Braga", "3106101"}, + {"MG", "Belo Horizonte", "3106200"}, + {"MG", "Belo Oriente", "3106309"}, + {"MG", "Belo Vale", "3106408"}, + {"MG", "Berilo", "3106507"}, + {"MG", "Berizal", "3106655"}, + {"MG", "Bert\u00f3polis", "3106606"}, + {"MG", "Betim", "3106705"}, + {"MG", "Bias Fortes", "3106804"}, + {"MG", "Bicas", "3106903"}, + {"MG", "Biquinhas", "3107000"}, + {"MG", "Boa Esperan\u00e7a", "3107109"}, + {"MG", "Bocaina de Minas", "3107208"}, + {"MG", "Bocai\u00fava", "3107307"}, + {"MG", "Bom Despacho", "3107406"}, + {"MG", "Bom Jardim de Minas", "3107505"}, + {"MG", "Bom Jesus da Penha", "3107604"}, + {"MG", "Bom Jesus do Amparo", "3107703"}, + {"MG", "Bom Jesus do Galho", "3107802"}, + {"MG", "Bom Repouso", "3107901"}, + {"MG", "Bom Sucesso", "3108008"}, + {"MG", "Bonfim", "3108107"}, + {"MG", "Bonfin\u00f3polis de Minas", "3108206"}, + {"MG", "Bonito de Minas", "3108255"}, + {"MG", "Borda da Mata", "3108305"}, + {"MG", "Botelhos", "3108404"}, + {"MG", "Botumirim", "3108503"}, + {"MG", "Br\u00e1s Pires", "3108701"}, + {"MG", "Brasil\u00e2ndia de Minas", "3108552"}, + {"MG", "Bras\u00edlia de Minas", "3108602"}, + {"MG", "Bra\u00fanas", "3108800"}, + {"MG", "Braz\u00f3polis", "3108909"}, + {"MG", "Brumadinho", "3109006"}, + {"MG", "Bueno Brand\u00e3o", "3109105"}, + {"MG", "Buen\u00f3polis", "3109204"}, + {"MG", "Bugre", "3109253"}, + {"MG", "Buritis", "3109303"}, + {"MG", "Buritizeiro", "3109402"}, + {"MG", "Cabeceira Grande", "3109451"}, + {"MG", "Cabo Verde", "3109501"}, + {"MG", "Cachoeira da Prata", "3109600"}, + {"MG", "Cachoeira de Minas", "3109709"}, + {"MG", "Cachoeira de Paje\u00fa", "3102704"}, + {"MG", "Cachoeira Dourada", "3109808"}, + {"MG", "Caetan\u00f3polis", "3109907"}, + {"MG", "Caet\u00e9", "3110004"}, + {"MG", "Caiana", "3110103"}, + {"MG", "Cajuri", "3110202"}, + {"MG", "Caldas", "3110301"}, + {"MG", "Camacho", "3110400"}, + {"MG", "Camanducaia", "3110509"}, + {"MG", "Cambu\u00ed", "3110608"}, + {"MG", "Cambuquira", "3110707"}, + {"MG", "Campan\u00e1rio", "3110806"}, + {"MG", "Campanha", "3110905"}, + {"MG", "Campestre", "3111002"}, + {"MG", "Campina Verde", "3111101"}, + {"MG", "Campo Azul", "3111150"}, + {"MG", "Campo Belo", "3111200"}, + {"MG", "Campo do Meio", "3111309"}, + {"MG", "Campo Florido", "3111408"}, + {"MG", "Campos Altos", "3111507"}, + {"MG", "Campos Gerais", "3111606"}, + {"MG", "Cana Verde", "3111903"}, + {"MG", "Cana\u00e3", "3111705"}, + {"MG", "Can\u00e1polis", "3111804"}, + {"MG", "Candeias", "3112000"}, + {"MG", "Cantagalo", "3112059"}, + {"MG", "Capara\u00f3", "3112109"}, + {"MG", "Capela Nova", "3112208"}, + {"MG", "Capelinha", "3112307"}, + {"MG", "Capetinga", "3112406"}, + {"MG", "Capim Branco", "3112505"}, + {"MG", "Capin\u00f3polis", "3112604"}, + {"MG", "Capit\u00e3o Andrade", "3112653"}, + {"MG", "Capit\u00e3o En\u00e9as", "3112703"}, + {"MG", "Capit\u00f3lio", "3112802"}, + {"MG", "Caputira", "3112901"}, + {"MG", "Cara\u00ed", "3113008"}, + {"MG", "Carana\u00edba", "3113107"}, + {"MG", "Caranda\u00ed", "3113206"}, + {"MG", "Carangola", "3113305"}, + {"MG", "Caratinga", "3113404"}, + {"MG", "Carbonita", "3113503"}, + {"MG", "Carea\u00e7u", "3113602"}, + {"MG", "Carlos Chagas", "3113701"}, + {"MG", "Carm\u00e9sia", "3113800"}, + {"MG", "Carmo da Cachoeira", "3113909"}, + {"MG", "Carmo da Mata", "3114006"}, + {"MG", "Carmo de Minas", "3114105"}, + {"MG", "Carmo do Cajuru", "3114204"}, + {"MG", "Carmo do Parana\u00edba", "3114303"}, + {"MG", "Carmo do Rio Claro", "3114402"}, + {"MG", "Carm\u00f3polis de Minas", "3114501"}, + {"MG", "Carneirinho", "3114550"}, + {"MG", "Carrancas", "3114600"}, + {"MG", "Carvalh\u00f3polis", "3114709"}, + {"MG", "Carvalhos", "3114808"}, + {"MG", "Casa Grande", "3114907"}, + {"MG", "Cascalho Rico", "3115003"}, + {"MG", "C\u00e1ssia", "3115102"}, + {"MG", "Cataguases", "3115300"}, + {"MG", "Catas Altas", "3115359"}, + {"MG", "Catas Altas da Noruega", "3115409"}, + {"MG", "Catuji", "3115458"}, + {"MG", "Catuti", "3115474"}, + {"MG", "Caxambu", "3115508"}, + {"MG", "Cedro do Abaet\u00e9", "3115607"}, + {"MG", "Central de Minas", "3115706"}, + {"MG", "Centralina", "3115805"}, + {"MG", "Ch\u00e1cara", "3115904"}, + {"MG", "Chal\u00e9", "3116001"}, + {"MG", "Chapada do Norte", "3116100"}, + {"MG", "Chapada Ga\u00facha", "3116159"}, + {"MG", "Chiador", "3116209"}, + {"MG", "Cipot\u00e2nea", "3116308"}, + {"MG", "Claraval", "3116407"}, + {"MG", "Claro dos Po\u00e7\u00f5es", "3116506"}, + {"MG", "Cl\u00e1udio", "3116605"}, + {"MG", "Coimbra", "3116704"}, + {"MG", "Coluna", "3116803"}, + {"MG", "Comendador Gomes", "3116902"}, + {"MG", "Comercinho", "3117009"}, + {"MG", "Concei\u00e7\u00e3o da Aparecida", "3117108"}, + {"MG", "Concei\u00e7\u00e3o da Barra de Minas", "3115201"}, + {"MG", "Concei\u00e7\u00e3o das Alagoas", "3117306"}, + {"MG", "Concei\u00e7\u00e3o das Pedras", "3117207"}, + {"MG", "Concei\u00e7\u00e3o de Ipanema", "3117405"}, + {"MG", "Concei\u00e7\u00e3o do Mato Dentro", "3117504"}, + {"MG", "Concei\u00e7\u00e3o do Par\u00e1", "3117603"}, + {"MG", "Concei\u00e7\u00e3o do Rio Verde", "3117702"}, + {"MG", "Concei\u00e7\u00e3o dos Ouros", "3117801"}, + {"MG", "C\u00f4nego Marinho", "3117836"}, + {"MG", "Confins", "3117876"}, + {"MG", "Congonhal", "3117900"}, + {"MG", "Congonhas", "3118007"}, + {"MG", "Congonhas do Norte", "3118106"}, + {"MG", "Conquista", "3118205"}, + {"MG", "Conselheiro Lafaiete", "3118304"}, + {"MG", "Conselheiro Pena", "3118403"}, + {"MG", "Consola\u00e7\u00e3o", "3118502"}, + {"MG", "Contagem", "3118601"}, + {"MG", "Coqueiral", "3118700"}, + {"MG", "Cora\u00e7\u00e3o de Jesus", "3118809"}, + {"MG", "Cordisburgo", "3118908"}, + {"MG", "Cordisl\u00e2ndia", "3119005"}, + {"MG", "Corinto", "3119104"}, + {"MG", "Coroaci", "3119203"}, + {"MG", "Coromandel", "3119302"}, + {"MG", "Coronel Fabriciano", "3119401"}, + {"MG", "Coronel Murta", "3119500"}, + {"MG", "Coronel Pacheco", "3119609"}, + {"MG", "Coronel Xavier Chaves", "3119708"}, + {"MG", "C\u00f3rrego Danta", "3119807"}, + {"MG", "C\u00f3rrego do Bom Jesus", "3119906"}, + {"MG", "C\u00f3rrego Fundo", "3119955"}, + {"MG", "C\u00f3rrego Novo", "3120003"}, + {"MG", "Couto de Magalh\u00e3es de Minas", "3120102"}, + {"MG", "Cris\u00f3lita", "3120151"}, + {"MG", "Cristais", "3120201"}, + {"MG", "Crist\u00e1lia", "3120300"}, + {"MG", "Cristiano Otoni", "3120409"}, + {"MG", "Cristina", "3120508"}, + {"MG", "Crucil\u00e2ndia", "3120607"}, + {"MG", "Cruzeiro da Fortaleza", "3120706"}, + {"MG", "Cruz\u00edlia", "3120805"}, + {"MG", "Cuparaque", "3120839"}, + {"MG", "Curral de Dentro", "3120870"}, + {"MG", "Curvelo", "3120904"}, + {"MG", "Datas", "3121001"}, + {"MG", "Delfim Moreira", "3121100"}, + {"MG", "Delfin\u00f3polis", "3121209"}, + {"MG", "Delta", "3121258"}, + {"MG", "Descoberto", "3121308"}, + {"MG", "Desterro de Entre Rios", "3121407"}, + {"MG", "Desterro do Melo", "3121506"}, + {"MG", "Diamantina", "3121605"}, + {"MG", "Diogo de Vasconcelos", "3121704"}, + {"MG", "Dion\u00edsio", "3121803"}, + {"MG", "Divin\u00e9sia", "3121902"}, + {"MG", "Divino", "3122009"}, + {"MG", "Divino das Laranjeiras", "3122108"}, + {"MG", "Divinol\u00e2ndia de Minas", "3122207"}, + {"MG", "Divin\u00f3polis", "3122306"}, + {"MG", "Divisa Alegre", "3122355"}, + {"MG", "Divisa Nova", "3122405"}, + {"MG", "Divis\u00f3polis", "3122454"}, + {"MG", "Dom Bosco", "3122470"}, + {"MG", "Dom Cavati", "3122504"}, + {"MG", "Dom Joaquim", "3122603"}, + {"MG", "Dom Silv\u00e9rio", "3122702"}, + {"MG", "Dom Vi\u00e7oso", "3122801"}, + {"MG", "Dona Euz\u00e9bia", "3122900"}, + {"MG", "Dores de Campos", "3123007"}, + {"MG", "Dores de Guanh\u00e3es", "3123106"}, + {"MG", "Dores do Indai\u00e1", "3123205"}, + {"MG", "Dores do Turvo", "3123304"}, + {"MG", "Dores\u00f3polis", "3123403"}, + {"MG", "Douradoquara", "3123502"}, + {"MG", "Durand\u00e9", "3123528"}, + {"MG", "El\u00f3i Mendes", "3123601"}, + {"MG", "Engenheiro Caldas", "3123700"}, + {"MG", "Engenheiro Navarro", "3123809"}, + {"MG", "Entre Folhas", "3123858"}, + {"MG", "Entre Rios de Minas", "3123908"}, + {"MG", "Erv\u00e1lia", "3124005"}, + {"MG", "Esmeraldas", "3124104"}, + {"MG", "Espera Feliz", "3124203"}, + {"MG", "Espinosa", "3124302"}, + {"MG", "Esp\u00edrito Santo do Dourado", "3124401"}, + {"MG", "Estiva", "3124500"}, + {"MG", "Estrela Dalva", "3124609"}, + {"MG", "Estrela do Indai\u00e1", "3124708"}, + {"MG", "Estrela do Sul", "3124807"}, + {"MG", "Eugen\u00f3polis", "3124906"}, + {"MG", "Ewbank da C\u00e2mara", "3125002"}, + {"MG", "Extrema", "3125101"}, + {"MG", "Fama", "3125200"}, + {"MG", "Faria Lemos", "3125309"}, + {"MG", "Fel\u00edcio dos Santos", "3125408"}, + {"MG", "Felisburgo", "3125606"}, + {"MG", "Felixl\u00e2ndia", "3125705"}, + {"MG", "Fernandes Tourinho", "3125804"}, + {"MG", "Ferros", "3125903"}, + {"MG", "Fervedouro", "3125952"}, + {"MG", "Florestal", "3126000"}, + {"MG", "Formiga", "3126109"}, + {"MG", "Formoso", "3126208"}, + {"MG", "Fortaleza de Minas", "3126307"}, + {"MG", "Fortuna de Minas", "3126406"}, + {"MG", "Francisco Badar\u00f3", "3126505"}, + {"MG", "Francisco Dumont", "3126604"}, + {"MG", "Francisco S\u00e1", "3126703"}, + {"MG", "Francisc\u00f3polis", "3126752"}, + {"MG", "Frei Gaspar", "3126802"}, + {"MG", "Frei Inoc\u00eancio", "3126901"}, + {"MG", "Frei Lagonegro", "3126950"}, + {"MG", "Fronteira", "3127008"}, + {"MG", "Fronteira dos Vales", "3127057"}, + {"MG", "Fruta de Leite", "3127073"}, + {"MG", "Frutal", "3127107"}, + {"MG", "Funil\u00e2ndia", "3127206"}, + {"MG", "Galil\u00e9ia", "3127305"}, + {"MG", "Gameleiras", "3127339"}, + {"MG", "Glaucil\u00e2ndia", "3127354"}, + {"MG", "Goiabeira", "3127370"}, + {"MG", "Goian\u00e1", "3127388"}, + {"MG", "Gon\u00e7alves", "3127404"}, + {"MG", "Gonzaga", "3127503"}, + {"MG", "Gouveia", "3127602"}, + {"MG", "Governador Valadares", "3127701"}, + {"MG", "Gr\u00e3o Mogol", "3127800"}, + {"MG", "Grupiara", "3127909"}, + {"MG", "Guanh\u00e3es", "3128006"}, + {"MG", "Guap\u00e9", "3128105"}, + {"MG", "Guaraciaba", "3128204"}, + {"MG", "Guaraciama", "3128253"}, + {"MG", "Guaran\u00e9sia", "3128303"}, + {"MG", "Guarani", "3128402"}, + {"MG", "Guarar\u00e1", "3128501"}, + {"MG", "Guarda-Mor", "3128600"}, + {"MG", "Guaxup\u00e9", "3128709"}, + {"MG", "Guidoval", "3128808"}, + {"MG", "Guimar\u00e2nia", "3128907"}, + {"MG", "Guiricema", "3129004"}, + {"MG", "Gurinhat\u00e3", "3129103"}, + {"MG", "Heliodora", "3129202"}, + {"MG", "Iapu", "3129301"}, + {"MG", "Ibertioga", "3129400"}, + {"MG", "Ibi\u00e1", "3129509"}, + {"MG", "Ibia\u00ed", "3129608"}, + {"MG", "Ibiracatu", "3129657"}, + {"MG", "Ibiraci", "3129707"}, + {"MG", "Ibirit\u00e9", "3129806"}, + {"MG", "Ibiti\u00fara de Minas", "3129905"}, + {"MG", "Ibituruna", "3130002"}, + {"MG", "Icara\u00ed de Minas", "3130051"}, + {"MG", "Igarap\u00e9", "3130101"}, + {"MG", "Igaratinga", "3130200"}, + {"MG", "Iguatama", "3130309"}, + {"MG", "Ijaci", "3130408"}, + {"MG", "Ilic\u00ednea", "3130507"}, + {"MG", "Imb\u00e9 de Minas", "3130556"}, + {"MG", "Inconfidentes", "3130606"}, + {"MG", "Indaiabira", "3130655"}, + {"MG", "Indian\u00f3polis", "3130705"}, + {"MG", "Inga\u00ed", "3130804"}, + {"MG", "Inhapim", "3130903"}, + {"MG", "Inha\u00fama", "3131000"}, + {"MG", "Inimutaba", "3131109"}, + {"MG", "Ipaba", "3131158"}, + {"MG", "Ipanema", "3131208"}, + {"MG", "Ipatinga", "3131307"}, + {"MG", "Ipia\u00e7u", "3131406"}, + {"MG", "Ipui\u00fana", "3131505"}, + {"MG", "Ira\u00ed de Minas", "3131604"}, + {"MG", "Itabira", "3131703"}, + {"MG", "Itabirinha", "3131802"}, + {"MG", "Itabirito", "3131901"}, + {"MG", "Itacambira", "3132008"}, + {"MG", "Itacarambi", "3132107"}, + {"MG", "Itaguara", "3132206"}, + {"MG", "Itaip\u00e9", "3132305"}, + {"MG", "Itajub\u00e1", "3132404"}, + {"MG", "Itamarandiba", "3132503"}, + {"MG", "Itamarati de Minas", "3132602"}, + {"MG", "Itambacuri", "3132701"}, + {"MG", "Itamb\u00e9 do Mato Dentro", "3132800"}, + {"MG", "Itamogi", "3132909"}, + {"MG", "Itamonte", "3133006"}, + {"MG", "Itanhandu", "3133105"}, + {"MG", "Itanhomi", "3133204"}, + {"MG", "Itaobim", "3133303"}, + {"MG", "Itapagipe", "3133402"}, + {"MG", "Itapecerica", "3133501"}, + {"MG", "Itapeva", "3133600"}, + {"MG", "Itatiaiu\u00e7u", "3133709"}, + {"MG", "Ita\u00fa de Minas", "3133758"}, + {"MG", "Ita\u00fana", "3133808"}, + {"MG", "Itaverava", "3133907"}, + {"MG", "Itinga", "3134004"}, + {"MG", "Itueta", "3134103"}, + {"MG", "Ituiutaba", "3134202"}, + {"MG", "Itumirim", "3134301"}, + {"MG", "Iturama", "3134400"}, + {"MG", "Itutinga", "3134509"}, + {"MG", "Jaboticatubas", "3134608"}, + {"MG", "Jacinto", "3134707"}, + {"MG", "Jacu\u00ed", "3134806"}, + {"MG", "Jacutinga", "3134905"}, + {"MG", "Jaguara\u00e7u", "3135001"}, + {"MG", "Ja\u00edba", "3135050"}, + {"MG", "Jampruca", "3135076"}, + {"MG", "Jana\u00faba", "3135100"}, + {"MG", "Janu\u00e1ria", "3135209"}, + {"MG", "Japara\u00edba", "3135308"}, + {"MG", "Japonvar", "3135357"}, + {"MG", "Jeceaba", "3135407"}, + {"MG", "Jenipapo de Minas", "3135456"}, + {"MG", "Jequeri", "3135506"}, + {"MG", "Jequita\u00ed", "3135605"}, + {"MG", "Jequitib\u00e1", "3135704"}, + {"MG", "Jequitinhonha", "3135803"}, + {"MG", "Jesu\u00e2nia", "3135902"}, + {"MG", "Joa\u00edma", "3136009"}, + {"MG", "Joan\u00e9sia", "3136108"}, + {"MG", "Jo\u00e3o Monlevade", "3136207"}, + {"MG", "Jo\u00e3o Pinheiro", "3136306"}, + {"MG", "Joaquim Fel\u00edcio", "3136405"}, + {"MG", "Jord\u00e2nia", "3136504"}, + {"MG", "Jos\u00e9 Gon\u00e7alves de Minas", "3136520"}, + {"MG", "Jos\u00e9 Raydan", "3136553"}, + {"MG", "Josen\u00f3polis", "3136579"}, + {"MG", "Juatuba", "3136652"}, + {"MG", "Juiz de Fora", "3136702"}, + {"MG", "Juramento", "3136801"}, + {"MG", "Juruaia", "3136900"}, + {"MG", "Juven\u00edlia", "3136959"}, + {"MG", "Ladainha", "3137007"}, + {"MG", "Lagamar", "3137106"}, + {"MG", "Lagoa da Prata", "3137205"}, + {"MG", "Lagoa dos Patos", "3137304"}, + {"MG", "Lagoa Dourada", "3137403"}, + {"MG", "Lagoa Formosa", "3137502"}, + {"MG", "Lagoa Grande", "3137536"}, + {"MG", "Lagoa Santa", "3137601"}, + {"MG", "Lajinha", "3137700"}, + {"MG", "Lambari", "3137809"}, + {"MG", "Lamim", "3137908"}, + {"MG", "Laranjal", "3138005"}, + {"MG", "Lassance", "3138104"}, + {"MG", "Lavras", "3138203"}, + {"MG", "Leandro Ferreira", "3138302"}, + {"MG", "Leme do Prado", "3138351"}, + {"MG", "Leopoldina", "3138401"}, + {"MG", "Liberdade", "3138500"}, + {"MG", "Lima Duarte", "3138609"}, + {"MG", "Limeira do Oeste", "3138625"}, + {"MG", "Lontra", "3138658"}, + {"MG", "Luisburgo", "3138674"}, + {"MG", "Luisl\u00e2ndia", "3138682"}, + {"MG", "Lumin\u00e1rias", "3138708"}, + {"MG", "Luz", "3138807"}, + {"MG", "Machacalis", "3138906"}, + {"MG", "Machado", "3139003"}, + {"MG", "Madre de Deus de Minas", "3139102"}, + {"MG", "Malacacheta", "3139201"}, + {"MG", "Mamonas", "3139250"}, + {"MG", "Manga", "3139300"}, + {"MG", "Manhua\u00e7u", "3139409"}, + {"MG", "Manhumirim", "3139508"}, + {"MG", "Mantena", "3139607"}, + {"MG", "Mar de Espanha", "3139805"}, + {"MG", "Maravilhas", "3139706"}, + {"MG", "Maria da F\u00e9", "3139904"}, + {"MG", "Mariana", "3140001"}, + {"MG", "Marilac", "3140100"}, + {"MG", "M\u00e1rio Campos", "3140159"}, + {"MG", "Marip\u00e1 de Minas", "3140209"}, + {"MG", "Marli\u00e9ria", "3140308"}, + {"MG", "Marmel\u00f3polis", "3140407"}, + {"MG", "Martinho Campos", "3140506"}, + {"MG", "Martins Soares", "3140530"}, + {"MG", "Mata Verde", "3140555"}, + {"MG", "Materl\u00e2ndia", "3140605"}, + {"MG", "Mateus Leme", "3140704"}, + {"MG", "Mathias Lobato", "3171501"}, + {"MG", "Matias Barbosa", "3140803"}, + {"MG", "Matias Cardoso", "3140852"}, + {"MG", "Matip\u00f3", "3140902"}, + {"MG", "Mato Verde", "3141009"}, + {"MG", "Matozinhos", "3141108"}, + {"MG", "Matutina", "3141207"}, + {"MG", "Medeiros", "3141306"}, + {"MG", "Medina", "3141405"}, + {"MG", "Mendes Pimentel", "3141504"}, + {"MG", "Merc\u00eas", "3141603"}, + {"MG", "Mesquita", "3141702"}, + {"MG", "Minas Novas", "3141801"}, + {"MG", "Minduri", "3141900"}, + {"MG", "Mirabela", "3142007"}, + {"MG", "Miradouro", "3142106"}, + {"MG", "Mira\u00ed", "3142205"}, + {"MG", "Mirav\u00e2nia", "3142254"}, + {"MG", "Moeda", "3142304"}, + {"MG", "Moema", "3142403"}, + {"MG", "Monjolos", "3142502"}, + {"MG", "Monsenhor Paulo", "3142601"}, + {"MG", "Montalv\u00e2nia", "3142700"}, + {"MG", "Monte Alegre de Minas", "3142809"}, + {"MG", "Monte Azul", "3142908"}, + {"MG", "Monte Belo", "3143005"}, + {"MG", "Monte Carmelo", "3143104"}, + {"MG", "Monte Formoso", "3143153"}, + {"MG", "Monte Santo de Minas", "3143203"}, + {"MG", "Monte Si\u00e3o", "3143401"}, + {"MG", "Montes Claros", "3143302"}, + {"MG", "Montezuma", "3143450"}, + {"MG", "Morada Nova de Minas", "3143500"}, + {"MG", "Morro da Gar\u00e7a", "3143609"}, + {"MG", "Morro do Pilar", "3143708"}, + {"MG", "Munhoz", "3143807"}, + {"MG", "Muria\u00e9", "3143906"}, + {"MG", "Mutum", "3144003"}, + {"MG", "Muzambinho", "3144102"}, + {"MG", "Nacip Raydan", "3144201"}, + {"MG", "Nanuque", "3144300"}, + {"MG", "Naque", "3144359"}, + {"MG", "Natal\u00e2ndia", "3144375"}, + {"MG", "Nat\u00e9rcia", "3144409"}, + {"MG", "Nazareno", "3144508"}, + {"MG", "Nepomuceno", "3144607"}, + {"MG", "Ninheira", "3144656"}, + {"MG", "Nova Bel\u00e9m", "3144672"}, + {"MG", "Nova Era", "3144706"}, + {"MG", "Nova Lima", "3144805"}, + {"MG", "Nova M\u00f3dica", "3144904"}, + {"MG", "Nova Ponte", "3145000"}, + {"MG", "Nova Porteirinha", "3145059"}, + {"MG", "Nova Resende", "3145109"}, + {"MG", "Nova Serrana", "3145208"}, + {"MG", "Nova Uni\u00e3o", "3136603"}, + {"MG", "Novo Cruzeiro", "3145307"}, + {"MG", "Novo Oriente de Minas", "3145356"}, + {"MG", "Novorizonte", "3145372"}, + {"MG", "Olaria", "3145406"}, + {"MG", "Olhos-d'\u00c1gua", "3145455"}, + {"MG", "Ol\u00edmpio Noronha", "3145505"}, + {"MG", "Oliveira", "3145604"}, + {"MG", "Oliveira Fortes", "3145703"}, + {"MG", "On\u00e7a de Pitangui", "3145802"}, + {"MG", "Orat\u00f3rios", "3145851"}, + {"MG", "Oriz\u00e2nia", "3145877"}, + {"MG", "Ouro Branco", "3145901"}, + {"MG", "Ouro Fino", "3146008"}, + {"MG", "Ouro Preto", "3146107"}, + {"MG", "Ouro Verde de Minas", "3146206"}, + {"MG", "Padre Carvalho", "3146255"}, + {"MG", "Padre Para\u00edso", "3146305"}, + {"MG", "Pai Pedro", "3146552"}, + {"MG", "Paineiras", "3146404"}, + {"MG", "Pains", "3146503"}, + {"MG", "Paiva", "3146602"}, + {"MG", "Palma", "3146701"}, + {"MG", "Palm\u00f3polis", "3146750"}, + {"MG", "Papagaios", "3146909"}, + {"MG", "Par\u00e1 de Minas", "3147105"}, + {"MG", "Paracatu", "3147006"}, + {"MG", "Paragua\u00e7u", "3147204"}, + {"MG", "Parais\u00f3polis", "3147303"}, + {"MG", "Paraopeba", "3147402"}, + {"MG", "Passa Quatro", "3147600"}, + {"MG", "Passa Tempo", "3147709"}, + {"MG", "Passa Vinte", "3147808"}, + {"MG", "Passab\u00e9m", "3147501"}, + {"MG", "Passos", "3147907"}, + {"MG", "Patis", "3147956"}, + {"MG", "Patos de Minas", "3148004"}, + {"MG", "Patroc\u00ednio", "3148103"}, + {"MG", "Patroc\u00ednio do Muria\u00e9", "3148202"}, + {"MG", "Paula C\u00e2ndido", "3148301"}, + {"MG", "Paulistas", "3148400"}, + {"MG", "Pav\u00e3o", "3148509"}, + {"MG", "Pe\u00e7anha", "3148608"}, + {"MG", "Pedra Azul", "3148707"}, + {"MG", "Pedra Bonita", "3148756"}, + {"MG", "Pedra do Anta", "3148806"}, + {"MG", "Pedra do Indai\u00e1", "3148905"}, + {"MG", "Pedra Dourada", "3149002"}, + {"MG", "Pedralva", "3149101"}, + {"MG", "Pedras de Maria da Cruz", "3149150"}, + {"MG", "Pedrin\u00f3polis", "3149200"}, + {"MG", "Pedro Leopoldo", "3149309"}, + {"MG", "Pedro Teixeira", "3149408"}, + {"MG", "Pequeri", "3149507"}, + {"MG", "Pequi", "3149606"}, + {"MG", "Perdig\u00e3o", "3149705"}, + {"MG", "Perdizes", "3149804"}, + {"MG", "Perd\u00f5es", "3149903"}, + {"MG", "Periquito", "3149952"}, + {"MG", "Pescador", "3150000"}, + {"MG", "Piau", "3150109"}, + {"MG", "Piedade de Caratinga", "3150158"}, + {"MG", "Piedade de Ponte Nova", "3150208"}, + {"MG", "Piedade do Rio Grande", "3150307"}, + {"MG", "Piedade dos Gerais", "3150406"}, + {"MG", "Pimenta", "3150505"}, + {"MG", "Pingo-d'\u00c1gua", "3150539"}, + {"MG", "Pint\u00f3polis", "3150570"}, + {"MG", "Piracema", "3150604"}, + {"MG", "Pirajuba", "3150703"}, + {"MG", "Piranga", "3150802"}, + {"MG", "Pirangu\u00e7u", "3150901"}, + {"MG", "Piranguinho", "3151008"}, + {"MG", "Pirapetinga", "3151107"}, + {"MG", "Pirapora", "3151206"}, + {"MG", "Pira\u00faba", "3151305"}, + {"MG", "Pitangui", "3151404"}, + {"MG", "Piumhi", "3151503"}, + {"MG", "Planura", "3151602"}, + {"MG", "Po\u00e7o Fundo", "3151701"}, + {"MG", "Po\u00e7os de Caldas", "3151800"}, + {"MG", "Pocrane", "3151909"}, + {"MG", "Pomp\u00e9u", "3152006"}, + {"MG", "Ponte Nova", "3152105"}, + {"MG", "Ponto Chique", "3152131"}, + {"MG", "Ponto dos Volantes", "3152170"}, + {"MG", "Porteirinha", "3152204"}, + {"MG", "Porto Firme", "3152303"}, + {"MG", "Pot\u00e9", "3152402"}, + {"MG", "Pouso Alegre", "3152501"}, + {"MG", "Pouso Alto", "3152600"}, + {"MG", "Prados", "3152709"}, + {"MG", "Prata", "3152808"}, + {"MG", "Prat\u00e1polis", "3152907"}, + {"MG", "Pratinha", "3153004"}, + {"MG", "Presidente Bernardes", "3153103"}, + {"MG", "Presidente Juscelino", "3153202"}, + {"MG", "Presidente Kubitschek", "3153301"}, + {"MG", "Presidente Oleg\u00e1rio", "3153400"}, + {"MG", "Prudente de Morais", "3153608"}, + {"MG", "Quartel Geral", "3153707"}, + {"MG", "Queluzito", "3153806"}, + {"MG", "Raposos", "3153905"}, + {"MG", "Raul Soares", "3154002"}, + {"MG", "Recreio", "3154101"}, + {"MG", "Reduto", "3154150"}, + {"MG", "Resende Costa", "3154200"}, + {"MG", "Resplendor", "3154309"}, + {"MG", "Ressaquinha", "3154408"}, + {"MG", "Riachinho", "3154457"}, + {"MG", "Riacho dos Machados", "3154507"}, + {"MG", "Ribeir\u00e3o das Neves", "3154606"}, + {"MG", "Ribeir\u00e3o Vermelho", "3154705"}, + {"MG", "Rio Acima", "3154804"}, + {"MG", "Rio Casca", "3154903"}, + {"MG", "Rio do Prado", "3155108"}, + {"MG", "Rio Doce", "3155009"}, + {"MG", "Rio Espera", "3155207"}, + {"MG", "Rio Manso", "3155306"}, + {"MG", "Rio Novo", "3155405"}, + {"MG", "Rio Parana\u00edba", "3155504"}, + {"MG", "Rio Pardo de Minas", "3155603"}, + {"MG", "Rio Piracicaba", "3155702"}, + {"MG", "Rio Pomba", "3155801"}, + {"MG", "Rio Preto", "3155900"}, + {"MG", "Rio Vermelho", "3156007"}, + {"MG", "Rit\u00e1polis", "3156106"}, + {"MG", "Rochedo de Minas", "3156205"}, + {"MG", "Rodeiro", "3156304"}, + {"MG", "Romaria", "3156403"}, + {"MG", "Ros\u00e1rio da Limeira", "3156452"}, + {"MG", "Rubelita", "3156502"}, + {"MG", "Rubim", "3156601"}, + {"MG", "Sabar\u00e1", "3156700"}, + {"MG", "Sabin\u00f3polis", "3156809"}, + {"MG", "Sacramento", "3156908"}, + {"MG", "Salinas", "3157005"}, + {"MG", "Salto da Divisa", "3157104"}, + {"MG", "Santa B\u00e1rbara", "3157203"}, + {"MG", "Santa B\u00e1rbara do Leste", "3157252"}, + {"MG", "Santa B\u00e1rbara do Monte Verde", "3157278"}, + {"MG", "Santa B\u00e1rbara do Tug\u00fario", "3157302"}, + {"MG", "Santa Cruz de Minas", "3157336"}, + {"MG", "Santa Cruz de Salinas", "3157377"}, + {"MG", "Santa Cruz do Escalvado", "3157401"}, + {"MG", "Santa Efig\u00eania de Minas", "3157500"}, + {"MG", "Santa F\u00e9 de Minas", "3157609"}, + {"MG", "Santa Helena de Minas", "3157658"}, + {"MG", "Santa Juliana", "3157708"}, + {"MG", "Santa Luzia", "3157807"}, + {"MG", "Santa Margarida", "3157906"}, + {"MG", "Santa Maria de Itabira", "3158003"}, + {"MG", "Santa Maria do Salto", "3158102"}, + {"MG", "Santa Maria do Sua\u00e7u\u00ed", "3158201"}, + {"MG", "Santa Rita de Caldas", "3159209"}, + {"MG", "Santa Rita de Ibitipoca", "3159407"}, + {"MG", "Santa Rita de Jacutinga", "3159308"}, + {"MG", "Santa Rita de Minas", "3159357"}, + {"MG", "Santa Rita do Itueto", "3159506"}, + {"MG", "Santa Rita do Sapuca\u00ed", "3159605"}, + {"MG", "Santa Rosa da Serra", "3159704"}, + {"MG", "Santa Vit\u00f3ria", "3159803"}, + {"MG", "Santana da Vargem", "3158300"}, + {"MG", "Santana de Cataguases", "3158409"}, + {"MG", "Santana de Pirapama", "3158508"}, + {"MG", "Santana do Deserto", "3158607"}, + {"MG", "Santana do Garamb\u00e9u", "3158706"}, + {"MG", "Santana do Jacar\u00e9", "3158805"}, + {"MG", "Santana do Manhua\u00e7u", "3158904"}, + {"MG", "Santana do Para\u00edso", "3158953"}, + {"MG", "Santana do Riacho", "3159001"}, + {"MG", "Santana dos Montes", "3159100"}, + {"MG", "Santo Ant\u00f4nio do Amparo", "3159902"}, + {"MG", "Santo Ant\u00f4nio do Aventureiro", "3160009"}, + {"MG", "Santo Ant\u00f4nio do Grama", "3160108"}, + {"MG", "Santo Ant\u00f4nio do Itamb\u00e9", "3160207"}, + {"MG", "Santo Ant\u00f4nio do Jacinto", "3160306"}, + {"MG", "Santo Ant\u00f4nio do Monte", "3160405"}, + {"MG", "Santo Ant\u00f4nio do Retiro", "3160454"}, + {"MG", "Santo Ant\u00f4nio do Rio Abaixo", "3160504"}, + {"MG", "Santo Hip\u00f3lito", "3160603"}, + {"MG", "Santos Dumont", "3160702"}, + {"MG", "S\u00e3o Bento Abade", "3160801"}, + {"MG", "S\u00e3o Br\u00e1s do Sua\u00e7u\u00ed", "3160900"}, + {"MG", "S\u00e3o Domingos das Dores", "3160959"}, + {"MG", "S\u00e3o Domingos do Prata", "3161007"}, + {"MG", "S\u00e3o F\u00e9lix de Minas", "3161056"}, + {"MG", "S\u00e3o Francisco", "3161106"}, + {"MG", "S\u00e3o Francisco de Paula", "3161205"}, + {"MG", "S\u00e3o Francisco de Sales", "3161304"}, + {"MG", "S\u00e3o Francisco do Gl\u00f3ria", "3161403"}, + {"MG", "S\u00e3o Geraldo", "3161502"}, + {"MG", "S\u00e3o Geraldo da Piedade", "3161601"}, + {"MG", "S\u00e3o Geraldo do Baixio", "3161650"}, + {"MG", "S\u00e3o Gon\u00e7alo do Abaet\u00e9", "3161700"}, + {"MG", "S\u00e3o Gon\u00e7alo do Par\u00e1", "3161809"}, + {"MG", "S\u00e3o Gon\u00e7alo do Rio Abaixo", "3161908"}, + {"MG", "S\u00e3o Gon\u00e7alo do Rio Preto", "3125507"}, + {"MG", "S\u00e3o Gon\u00e7alo do Sapuca\u00ed", "3162005"}, + {"MG", "S\u00e3o Gotardo", "3162104"}, + {"MG", "S\u00e3o Jo\u00e3o Batista do Gl\u00f3ria", "3162203"}, + {"MG", "S\u00e3o Jo\u00e3o da Lagoa", "3162252"}, + {"MG", "S\u00e3o Jo\u00e3o da Mata", "3162302"}, + {"MG", "S\u00e3o Jo\u00e3o da Ponte", "3162401"}, + {"MG", "S\u00e3o Jo\u00e3o das Miss\u00f5es", "3162450"}, + {"MG", "S\u00e3o Jo\u00e3o del Rei", "3162500"}, + {"MG", "S\u00e3o Jo\u00e3o do Manhua\u00e7u", "3162559"}, + {"MG", "S\u00e3o Jo\u00e3o do Manteninha", "3162575"}, + {"MG", "S\u00e3o Jo\u00e3o do Oriente", "3162609"}, + {"MG", "S\u00e3o Jo\u00e3o do Pacu\u00ed", "3162658"}, + {"MG", "S\u00e3o Jo\u00e3o do Para\u00edso", "3162708"}, + {"MG", "S\u00e3o Jo\u00e3o Evangelista", "3162807"}, + {"MG", "S\u00e3o Jo\u00e3o Nepomuceno", "3162906"}, + {"MG", "S\u00e3o Joaquim de Bicas", "3162922"}, + {"MG", "S\u00e3o Jos\u00e9 da Barra", "3162948"}, + {"MG", "S\u00e3o Jos\u00e9 da Lapa", "3162955"}, + {"MG", "S\u00e3o Jos\u00e9 da Safira", "3163003"}, + {"MG", "S\u00e3o Jos\u00e9 da Varginha", "3163102"}, + {"MG", "S\u00e3o Jos\u00e9 do Alegre", "3163201"}, + {"MG", "S\u00e3o Jos\u00e9 do Divino", "3163300"}, + {"MG", "S\u00e3o Jos\u00e9 do Goiabal", "3163409"}, + {"MG", "S\u00e3o Jos\u00e9 do Jacuri", "3163508"}, + {"MG", "S\u00e3o Jos\u00e9 do Mantimento", "3163607"}, + {"MG", "S\u00e3o Louren\u00e7o", "3163706"}, + {"MG", "S\u00e3o Miguel do Anta", "3163805"}, + {"MG", "S\u00e3o Pedro da Uni\u00e3o", "3163904"}, + {"MG", "S\u00e3o Pedro do Sua\u00e7u\u00ed", "3164100"}, + {"MG", "S\u00e3o Pedro dos Ferros", "3164001"}, + {"MG", "S\u00e3o Rom\u00e3o", "3164209"}, + {"MG", "S\u00e3o Roque de Minas", "3164308"}, + {"MG", "S\u00e3o Sebasti\u00e3o da Bela Vista", "3164407"}, + {"MG", "S\u00e3o Sebasti\u00e3o da Vargem Alegre", "3164431"}, + {"MG", "S\u00e3o Sebasti\u00e3o do Anta", "3164472"}, + {"MG", "S\u00e3o Sebasti\u00e3o do Maranh\u00e3o", "3164506"}, + {"MG", "S\u00e3o Sebasti\u00e3o do Oeste", "3164605"}, + {"MG", "S\u00e3o Sebasti\u00e3o do Para\u00edso", "3164704"}, + {"MG", "S\u00e3o Sebasti\u00e3o do Rio Preto", "3164803"}, + {"MG", "S\u00e3o Sebasti\u00e3o do Rio Verde", "3164902"}, + {"MG", "S\u00e3o Tiago", "3165008"}, + {"MG", "S\u00e3o Tom\u00e1s de Aquino", "3165107"}, + {"MG", "S\u00e3o Tom\u00e9 das Letras", "3165206"}, + {"MG", "S\u00e3o Vicente de Minas", "3165305"}, + {"MG", "Sapuca\u00ed-Mirim", "3165404"}, + {"MG", "Sardo\u00e1", "3165503"}, + {"MG", "Sarzedo", "3165537"}, + {"MG", "Sem-Peixe", "3165560"}, + {"MG", "Senador Amaral", "3165578"}, + {"MG", "Senador Cortes", "3165602"}, + {"MG", "Senador Firmino", "3165701"}, + {"MG", "Senador Jos\u00e9 Bento", "3165800"}, + {"MG", "Senador Modestino Gon\u00e7alves", "3165909"}, + {"MG", "Senhora de Oliveira", "3166006"}, + {"MG", "Senhora do Porto", "3166105"}, + {"MG", "Senhora dos Rem\u00e9dios", "3166204"}, + {"MG", "Sericita", "3166303"}, + {"MG", "Seritinga", "3166402"}, + {"MG", "Serra Azul de Minas", "3166501"}, + {"MG", "Serra da Saudade", "3166600"}, + {"MG", "Serra do Salitre", "3166808"}, + {"MG", "Serra dos Aimor\u00e9s", "3166709"}, + {"MG", "Serrania", "3166907"}, + {"MG", "Serran\u00f3polis de Minas", "3166956"}, + {"MG", "Serranos", "3167004"}, + {"MG", "Serro", "3167103"}, + {"MG", "Sete Lagoas", "3167202"}, + {"MG", "Setubinha", "3165552"}, + {"MG", "Silveir\u00e2nia", "3167301"}, + {"MG", "Silvian\u00f3polis", "3167400"}, + {"MG", "Sim\u00e3o Pereira", "3167509"}, + {"MG", "Simon\u00e9sia", "3167608"}, + {"MG", "Sobr\u00e1lia", "3167707"}, + {"MG", "Soledade de Minas", "3167806"}, + {"MG", "Tabuleiro", "3167905"}, + {"MG", "Taiobeiras", "3168002"}, + {"MG", "Taparuba", "3168051"}, + {"MG", "Tapira", "3168101"}, + {"MG", "Tapira\u00ed", "3168200"}, + {"MG", "Taquara\u00e7u de Minas", "3168309"}, + {"MG", "Tarumirim", "3168408"}, + {"MG", "Teixeiras", "3168507"}, + {"MG", "Te\u00f3filo Otoni", "3168606"}, + {"MG", "Tim\u00f3teo", "3168705"}, + {"MG", "Tiradentes", "3168804"}, + {"MG", "Tiros", "3168903"}, + {"MG", "Tocantins", "3169000"}, + {"MG", "Tocos do Moji", "3169059"}, + {"MG", "Toledo", "3169109"}, + {"MG", "Tombos", "3169208"}, + {"MG", "Tr\u00eas Cora\u00e7\u00f5es", "3169307"}, + {"MG", "Tr\u00eas Marias", "3169356"}, + {"MG", "Tr\u00eas Pontas", "3169406"}, + {"MG", "Tumiritinga", "3169505"}, + {"MG", "Tupaciguara", "3169604"}, + {"MG", "Turmalina", "3169703"}, + {"MG", "Turvol\u00e2ndia", "3169802"}, + {"MG", "Ub\u00e1", "3169901"}, + {"MG", "Uba\u00ed", "3170008"}, + {"MG", "Ubaporanga", "3170057"}, + {"MG", "Uberaba", "3170107"}, + {"MG", "Uberl\u00e2ndia", "3170206"}, + {"MG", "Umburatiba", "3170305"}, + {"MG", "Una\u00ed", "3170404"}, + {"MG", "Uni\u00e3o de Minas", "3170438"}, + {"MG", "Uruana de Minas", "3170479"}, + {"MG", "Uruc\u00e2nia", "3170503"}, + {"MG", "Urucuia", "3170529"}, + {"MG", "Vargem Alegre", "3170578"}, + {"MG", "Vargem Bonita", "3170602"}, + {"MG", "Vargem Grande do Rio Pardo", "3170651"}, + {"MG", "Varginha", "3170701"}, + {"MG", "Varj\u00e3o de Minas", "3170750"}, + {"MG", "V\u00e1rzea da Palma", "3170800"}, + {"MG", "Varzel\u00e2ndia", "3170909"}, + {"MG", "Vazante", "3171006"}, + {"MG", "Verdel\u00e2ndia", "3171030"}, + {"MG", "Veredinha", "3171071"}, + {"MG", "Ver\u00edssimo", "3171105"}, + {"MG", "Vermelho Novo", "3171154"}, + {"MG", "Vespasiano", "3171204"}, + {"MG", "Vi\u00e7osa", "3171303"}, + {"MG", "Vieiras", "3171402"}, + {"MG", "Virgem da Lapa", "3171600"}, + {"MG", "Virg\u00ednia", "3171709"}, + {"MG", "Virgin\u00f3polis", "3171808"}, + {"MG", "Virgol\u00e2ndia", "3171907"}, + {"MG", "Visconde do Rio Branco", "3172004"}, + {"MG", "Volta Grande", "3172103"}, + {"MG", "Wenceslau Braz", "3172202"}, + {"PA", "Abaetetuba", "1500107"}, + {"PA", "Abel Figueiredo", "1500131"}, + {"PA", "Acar\u00e1", "1500206"}, + {"PA", "Afu\u00e1", "1500305"}, + {"PA", "\u00c1gua Azul do Norte", "1500347"}, + {"PA", "Alenquer", "1500404"}, + {"PA", "Almeirim", "1500503"}, + {"PA", "Altamira", "1500602"}, + {"PA", "Anaj\u00e1s", "1500701"}, + {"PA", "Ananindeua", "1500800"}, + {"PA", "Anapu", "1500859"}, + {"PA", "Augusto Corr\u00eaa", "1500909"}, + {"PA", "Aurora do Par\u00e1", "1500958"}, + {"PA", "Aveiro", "1501006"}, + {"PA", "Bagre", "1501105"}, + {"PA", "Bai\u00e3o", "1501204"}, + {"PA", "Bannach", "1501253"}, + {"PA", "Barcarena", "1501303"}, + {"PA", "Bel\u00e9m", "1501402"}, + {"PA", "Belterra", "1501451"}, + {"PA", "Benevides", "1501501"}, + {"PA", "Bom Jesus do Tocantins", "1501576"}, + {"PA", "Bonito", "1501600"}, + {"PA", "Bragan\u00e7a", "1501709"}, + {"PA", "Brasil Novo", "1501725"}, + {"PA", "Brejo Grande do Araguaia", "1501758"}, + {"PA", "Breu Branco", "1501782"}, + {"PA", "Breves", "1501808"}, + {"PA", "Bujaru", "1501907"}, + {"PA", "Cachoeira do Arari", "1502004"}, + {"PA", "Cachoeira do Piri\u00e1", "1501956"}, + {"PA", "Camet\u00e1", "1502103"}, + {"PA", "Cana\u00e3 dos Caraj\u00e1s", "1502152"}, + {"PA", "Capanema", "1502202"}, + {"PA", "Capit\u00e3o Po\u00e7o", "1502301"}, + {"PA", "Castanhal", "1502400"}, + {"PA", "Chaves", "1502509"}, + {"PA", "Colares", "1502608"}, + {"PA", "Concei\u00e7\u00e3o do Araguaia", "1502707"}, + {"PA", "Conc\u00f3rdia do Par\u00e1", "1502756"}, + {"PA", "Cumaru do Norte", "1502764"}, + {"PA", "Curion\u00f3polis", "1502772"}, + {"PA", "Curralinho", "1502806"}, + {"PA", "Curu\u00e1", "1502855"}, + {"PA", "Curu\u00e7\u00e1", "1502905"}, + {"PA", "Dom Eliseu", "1502939"}, + {"PA", "Eldorado do Caraj\u00e1s", "1502954"}, + {"PA", "Faro", "1503002"}, + {"PA", "Floresta do Araguaia", "1503044"}, + {"PA", "Garraf\u00e3o do Norte", "1503077"}, + {"PA", "Goian\u00e9sia do Par\u00e1", "1503093"}, + {"PA", "Gurup\u00e1", "1503101"}, + {"PA", "Igarap\u00e9-A\u00e7u", "1503200"}, + {"PA", "Igarap\u00e9-Miri", "1503309"}, + {"PA", "Inhangapi", "1503408"}, + {"PA", "Ipixuna do Par\u00e1", "1503457"}, + {"PA", "Irituia", "1503507"}, + {"PA", "Itaituba", "1503606"}, + {"PA", "Itupiranga", "1503705"}, + {"PA", "Jacareacanga", "1503754"}, + {"PA", "Jacund\u00e1", "1503804"}, + {"PA", "Juruti", "1503903"}, + {"PA", "Limoeiro do Ajuru", "1504000"}, + {"PA", "M\u00e3e do Rio", "1504059"}, + {"PA", "Magalh\u00e3es Barata", "1504109"}, + {"PA", "Marab\u00e1", "1504208"}, + {"PA", "Maracan\u00e3", "1504307"}, + {"PA", "Marapanim", "1504406"}, + {"PA", "Marituba", "1504422"}, + {"PA", "Medicil\u00e2ndia", "1504455"}, + {"PA", "Melga\u00e7o", "1504505"}, + {"PA", "Mocajuba", "1504604"}, + {"PA", "Moju", "1504703"}, + {"PA", "Moju\u00ed dos Campos", "1504752"}, + {"PA", "Monte Alegre", "1504802"}, + {"PA", "Muan\u00e1", "1504901"}, + {"PA", "Nova Esperan\u00e7a do Piri\u00e1", "1504950"}, + {"PA", "Nova Ipixuna", "1504976"}, + {"PA", "Nova Timboteua", "1505007"}, + {"PA", "Novo Progresso", "1505031"}, + {"PA", "Novo Repartimento", "1505064"}, + {"PA", "\u00d3bidos", "1505106"}, + {"PA", "Oeiras do Par\u00e1", "1505205"}, + {"PA", "Oriximin\u00e1", "1505304"}, + {"PA", "Our\u00e9m", "1505403"}, + {"PA", "Ouril\u00e2ndia do Norte", "1505437"}, + {"PA", "Pacaj\u00e1", "1505486"}, + {"PA", "Palestina do Par\u00e1", "1505494"}, + {"PA", "Paragominas", "1505502"}, + {"PA", "Parauapebas", "1505536"}, + {"PA", "Pau D'Arco", "1505551"}, + {"PA", "Peixe-Boi", "1505601"}, + {"PA", "Pi\u00e7arra", "1505635"}, + {"PA", "Placas", "1505650"}, + {"PA", "Ponta de Pedras", "1505700"}, + {"PA", "Portel", "1505809"}, + {"PA", "Porto de Moz", "1505908"}, + {"PA", "Prainha", "1506005"}, + {"PA", "Primavera", "1506104"}, + {"PA", "Quatipuru", "1506112"}, + {"PA", "Reden\u00e7\u00e3o", "1506138"}, + {"PA", "Rio Maria", "1506161"}, + {"PA", "Rondon do Par\u00e1", "1506187"}, + {"PA", "Rur\u00f3polis", "1506195"}, + {"PA", "Salin\u00f3polis", "1506203"}, + {"PA", "Salvaterra", "1506302"}, + {"PA", "Santa B\u00e1rbara do Par\u00e1", "1506351"}, + {"PA", "Santa Cruz do Arari", "1506401"}, + {"PA", "Santa Izabel do Par\u00e1", "1506500"}, + {"PA", "Santa Luzia do Par\u00e1", "1506559"}, + {"PA", "Santa Maria das Barreiras", "1506583"}, + {"PA", "Santa Maria do Par\u00e1", "1506609"}, + {"PA", "Santana do Araguaia", "1506708"}, + {"PA", "Santar\u00e9m", "1506807"}, + {"PA", "Santar\u00e9m Novo", "1506906"}, + {"PA", "Santo Ant\u00f4nio do Tau\u00e1", "1507003"}, + {"PA", "S\u00e3o Caetano de Odivelas", "1507102"}, + {"PA", "S\u00e3o Domingos do Araguaia", "1507151"}, + {"PA", "S\u00e3o Domingos do Capim", "1507201"}, + {"PA", "S\u00e3o F\u00e9lix do Xingu", "1507300"}, + {"PA", "S\u00e3o Francisco do Par\u00e1", "1507409"}, + {"PA", "S\u00e3o Geraldo do Araguaia", "1507458"}, + {"PA", "S\u00e3o Jo\u00e3o da Ponta", "1507466"}, + {"PA", "S\u00e3o Jo\u00e3o de Pirabas", "1507474"}, + {"PA", "S\u00e3o Jo\u00e3o do Araguaia", "1507508"}, + {"PA", "S\u00e3o Miguel do Guam\u00e1", "1507607"}, + {"PA", "S\u00e3o Sebasti\u00e3o da Boa Vista", "1507706"}, + {"PA", "Sapucaia", "1507755"}, + {"PA", "Senador Jos\u00e9 Porf\u00edrio", "1507805"}, + {"PA", "Soure", "1507904"}, + {"PA", "Tail\u00e2ndia", "1507953"}, + {"PA", "Terra Alta", "1507961"}, + {"PA", "Terra Santa", "1507979"}, + {"PA", "Tom\u00e9-A\u00e7u", "1508001"}, + {"PA", "Tracuateua", "1508035"}, + {"PA", "Trair\u00e3o", "1508050"}, + {"PA", "Tucum\u00e3", "1508084"}, + {"PA", "Tucuru\u00ed", "1508100"}, + {"PA", "Ulian\u00f3polis", "1508126"}, + {"PA", "Uruar\u00e1", "1508159"}, + {"PA", "Vigia", "1508209"}, + {"PA", "Viseu", "1508308"}, + {"PA", "Vit\u00f3ria do Xingu", "1508357"}, + {"PA", "Xinguara", "1508407"}, + {"PB", "\u00c1gua Branca", "2500106"}, + {"PB", "Aguiar", "2500205"}, + {"PB", "Alagoa Grande", "2500304"}, + {"PB", "Alagoa Nova", "2500403"}, + {"PB", "Alagoinha", "2500502"}, + {"PB", "Alcantil", "2500536"}, + {"PB", "Algod\u00e3o de Janda\u00edra", "2500577"}, + {"PB", "Alhandra", "2500601"}, + {"PB", "Amparo", "2500734"}, + {"PB", "Aparecida", "2500775"}, + {"PB", "Ara\u00e7agi", "2500809"}, + {"PB", "Arara", "2500908"}, + {"PB", "Araruna", "2501005"}, + {"PB", "Areia", "2501104"}, + {"PB", "Areia de Bara\u00fanas", "2501153"}, + {"PB", "Areial", "2501203"}, + {"PB", "Aroeiras", "2501302"}, + {"PB", "Assun\u00e7\u00e3o", "2501351"}, + {"PB", "Ba\u00eda da Trai\u00e7\u00e3o", "2501401"}, + {"PB", "Bananeiras", "2501500"}, + {"PB", "Bara\u00fana", "2501534"}, + {"PB", "Barra de Santa Rosa", "2501609"}, + {"PB", "Barra de Santana", "2501575"}, + {"PB", "Barra de S\u00e3o Miguel", "2501708"}, + {"PB", "Bayeux", "2501807"}, + {"PB", "Bel\u00e9m", "2501906"}, + {"PB", "Bel\u00e9m do Brejo do Cruz", "2502003"}, + {"PB", "Bernardino Batista", "2502052"}, + {"PB", "Boa Ventura", "2502102"}, + {"PB", "Boa Vista", "2502151"}, + {"PB", "Bom Jesus", "2502201"}, + {"PB", "Bom Sucesso", "2502300"}, + {"PB", "Bonito de Santa F\u00e9", "2502409"}, + {"PB", "Boqueir\u00e3o", "2502508"}, + {"PB", "Borborema", "2502706"}, + {"PB", "Brejo do Cruz", "2502805"}, + {"PB", "Brejo dos Santos", "2502904"}, + {"PB", "Caapor\u00e3", "2503001"}, + {"PB", "Cabaceiras", "2503100"}, + {"PB", "Cabedelo", "2503209"}, + {"PB", "Cachoeira dos \u00cdndios", "2503308"}, + {"PB", "Cacimba de Areia", "2503407"}, + {"PB", "Cacimba de Dentro", "2503506"}, + {"PB", "Cacimbas", "2503555"}, + {"PB", "Cai\u00e7ara", "2503605"}, + {"PB", "Cajazeiras", "2503704"}, + {"PB", "Cajazeirinhas", "2503753"}, + {"PB", "Caldas Brand\u00e3o", "2503803"}, + {"PB", "Camala\u00fa", "2503902"}, + {"PB", "Campina Grande", "2504009"}, + {"PB", "Capim", "2504033"}, + {"PB", "Cara\u00fabas", "2504074"}, + {"PB", "Carrapateira", "2504108"}, + {"PB", "Casserengue", "2504157"}, + {"PB", "Catingueira", "2504207"}, + {"PB", "Catol\u00e9 do Rocha", "2504306"}, + {"PB", "Caturit\u00e9", "2504355"}, + {"PB", "Concei\u00e7\u00e3o", "2504405"}, + {"PB", "Condado", "2504504"}, + {"PB", "Conde", "2504603"}, + {"PB", "Congo", "2504702"}, + {"PB", "Coremas", "2504801"}, + {"PB", "Coxixola", "2504850"}, + {"PB", "Cruz do Esp\u00edrito Santo", "2504900"}, + {"PB", "Cubati", "2505006"}, + {"PB", "Cuit\u00e9", "2505105"}, + {"PB", "Cuit\u00e9 de Mamanguape", "2505238"}, + {"PB", "Cuitegi", "2505204"}, + {"PB", "Curral de Cima", "2505279"}, + {"PB", "Curral Velho", "2505303"}, + {"PB", "Dami\u00e3o", "2505352"}, + {"PB", "Desterro", "2505402"}, + {"PB", "Diamante", "2505600"}, + {"PB", "Dona In\u00eas", "2505709"}, + {"PB", "Duas Estradas", "2505808"}, + {"PB", "Emas", "2505907"}, + {"PB", "Esperan\u00e7a", "2506004"}, + {"PB", "Fagundes", "2506103"}, + {"PB", "Frei Martinho", "2506202"}, + {"PB", "Gado Bravo", "2506251"}, + {"PB", "Guarabira", "2506301"}, + {"PB", "Gurinh\u00e9m", "2506400"}, + {"PB", "Gurj\u00e3o", "2506509"}, + {"PB", "Ibiara", "2506608"}, + {"PB", "Igaracy", "2502607"}, + {"PB", "Imaculada", "2506707"}, + {"PB", "Ing\u00e1", "2506806"}, + {"PB", "Itabaiana", "2506905"}, + {"PB", "Itaporanga", "2507002"}, + {"PB", "Itapororoca", "2507101"}, + {"PB", "Itatuba", "2507200"}, + {"PB", "Jacara\u00fa", "2507309"}, + {"PB", "Jeric\u00f3", "2507408"}, + {"PB", "Jo\u00e3o Pessoa", "2507507"}, + {"PB", "Joca Claudino", "2513653"}, + {"PB", "Juarez T\u00e1vora", "2507606"}, + {"PB", "Juazeirinho", "2507705"}, + {"PB", "Junco do Serid\u00f3", "2507804"}, + {"PB", "Juripiranga", "2507903"}, + {"PB", "Juru", "2508000"}, + {"PB", "Lagoa", "2508109"}, + {"PB", "Lagoa de Dentro", "2508208"}, + {"PB", "Lagoa Seca", "2508307"}, + {"PB", "Lastro", "2508406"}, + {"PB", "Livramento", "2508505"}, + {"PB", "Logradouro", "2508554"}, + {"PB", "Lucena", "2508604"}, + {"PB", "M\u00e3e d'\u00c1gua", "2508703"}, + {"PB", "Malta", "2508802"}, + {"PB", "Mamanguape", "2508901"}, + {"PB", "Mana\u00edra", "2509008"}, + {"PB", "Marca\u00e7\u00e3o", "2509057"}, + {"PB", "Mari", "2509107"}, + {"PB", "Mariz\u00f3polis", "2509156"}, + {"PB", "Massaranduba", "2509206"}, + {"PB", "Mataraca", "2509305"}, + {"PB", "Matinhas", "2509339"}, + {"PB", "Mato Grosso", "2509370"}, + {"PB", "Matur\u00e9ia", "2509396"}, + {"PB", "Mogeiro", "2509404"}, + {"PB", "Montadas", "2509503"}, + {"PB", "Monte Horebe", "2509602"}, + {"PB", "Monteiro", "2509701"}, + {"PB", "Mulungu", "2509800"}, + {"PB", "Natuba", "2509909"}, + {"PB", "Nazarezinho", "2510006"}, + {"PB", "Nova Floresta", "2510105"}, + {"PB", "Nova Olinda", "2510204"}, + {"PB", "Nova Palmeira", "2510303"}, + {"PB", "Olho d'\u00c1gua", "2510402"}, + {"PB", "Olivedos", "2510501"}, + {"PB", "Ouro Velho", "2510600"}, + {"PB", "Parari", "2510659"}, + {"PB", "Passagem", "2510709"}, + {"PB", "Patos", "2510808"}, + {"PB", "Paulista", "2510907"}, + {"PB", "Pedra Branca", "2511004"}, + {"PB", "Pedra Lavrada", "2511103"}, + {"PB", "Pedras de Fogo", "2511202"}, + {"PB", "Pedro R\u00e9gis", "2512721"}, + {"PB", "Pianc\u00f3", "2511301"}, + {"PB", "Picu\u00ed", "2511400"}, + {"PB", "Pilar", "2511509"}, + {"PB", "Pil\u00f5es", "2511608"}, + {"PB", "Pil\u00f5ezinhos", "2511707"}, + {"PB", "Pirpirituba", "2511806"}, + {"PB", "Pitimbu", "2511905"}, + {"PB", "Pocinhos", "2512002"}, + {"PB", "Po\u00e7o Dantas", "2512036"}, + {"PB", "Po\u00e7o de Jos\u00e9 de Moura", "2512077"}, + {"PB", "Pombal", "2512101"}, + {"PB", "Prata", "2512200"}, + {"PB", "Princesa Isabel", "2512309"}, + {"PB", "Puxinan\u00e3", "2512408"}, + {"PB", "Queimadas", "2512507"}, + {"PB", "Quixaba", "2512606"}, + {"PB", "Rem\u00edgio", "2512705"}, + {"PB", "Riach\u00e3o", "2512747"}, + {"PB", "Riach\u00e3o do Bacamarte", "2512754"}, + {"PB", "Riach\u00e3o do Po\u00e7o", "2512762"}, + {"PB", "Riacho de Santo Ant\u00f4nio", "2512788"}, + {"PB", "Riacho dos Cavalos", "2512804"}, + {"PB", "Rio Tinto", "2512903"}, + {"PB", "Salgadinho", "2513000"}, + {"PB", "Salgado de S\u00e3o F\u00e9lix", "2513109"}, + {"PB", "Santa Cec\u00edlia", "2513158"}, + {"PB", "Santa Cruz", "2513208"}, + {"PB", "Santa Helena", "2513307"}, + {"PB", "Santa In\u00eas", "2513356"}, + {"PB", "Santa Luzia", "2513406"}, + {"PB", "Santa Rita", "2513703"}, + {"PB", "Santa Teresinha", "2513802"}, + {"PB", "Santana de Mangueira", "2513505"}, + {"PB", "Santana dos Garrotes", "2513604"}, + {"PB", "Santo Andr\u00e9", "2513851"}, + {"PB", "S\u00e3o Bentinho", "2513927"}, + {"PB", "S\u00e3o Bento", "2513901"}, + {"PB", "S\u00e3o Domingos", "2513968"}, + {"PB", "S\u00e3o Domingos do Cariri", "2513943"}, + {"PB", "S\u00e3o Francisco", "2513984"}, + {"PB", "S\u00e3o Jo\u00e3o do Cariri", "2514008"}, + {"PB", "S\u00e3o Jo\u00e3o do Rio do Peixe", "2500700"}, + {"PB", "S\u00e3o Jo\u00e3o do Tigre", "2514107"}, + {"PB", "S\u00e3o Jos\u00e9 da Lagoa Tapada", "2514206"}, + {"PB", "S\u00e3o Jos\u00e9 de Caiana", "2514305"}, + {"PB", "S\u00e3o Jos\u00e9 de Espinharas", "2514404"}, + {"PB", "S\u00e3o Jos\u00e9 de Piranhas", "2514503"}, + {"PB", "S\u00e3o Jos\u00e9 de Princesa", "2514552"}, + {"PB", "S\u00e3o Jos\u00e9 do Bonfim", "2514602"}, + {"PB", "S\u00e3o Jos\u00e9 do Brejo do Cruz", "2514651"}, + {"PB", "S\u00e3o Jos\u00e9 do Sabugi", "2514701"}, + {"PB", "S\u00e3o Jos\u00e9 dos Cordeiros", "2514800"}, + {"PB", "S\u00e3o Jos\u00e9 dos Ramos", "2514453"}, + {"PB", "S\u00e3o Mamede", "2514909"}, + {"PB", "S\u00e3o Miguel de Taipu", "2515005"}, + {"PB", "S\u00e3o Sebasti\u00e3o de Lagoa de Ro\u00e7a", "2515104"}, + {"PB", "S\u00e3o Sebasti\u00e3o do Umbuzeiro", "2515203"}, + {"PB", "S\u00e3o Vicente do Serid\u00f3", "2515401"}, + {"PB", "Sap\u00e9", "2515302"}, + {"PB", "Serra Branca", "2515500"}, + {"PB", "Serra da Raiz", "2515609"}, + {"PB", "Serra Grande", "2515708"}, + {"PB", "Serra Redonda", "2515807"}, + {"PB", "Serraria", "2515906"}, + {"PB", "Sert\u00e3ozinho", "2515930"}, + {"PB", "Sobrado", "2515971"}, + {"PB", "Sol\u00e2nea", "2516003"}, + {"PB", "Soledade", "2516102"}, + {"PB", "Soss\u00eago", "2516151"}, + {"PB", "Sousa", "2516201"}, + {"PB", "Sum\u00e9", "2516300"}, + {"PB", "Tacima", "2516409"}, + {"PB", "Tapero\u00e1", "2516508"}, + {"PB", "Tavares", "2516607"}, + {"PB", "Teixeira", "2516706"}, + {"PB", "Ten\u00f3rio", "2516755"}, + {"PB", "Triunfo", "2516805"}, + {"PB", "Uira\u00fana", "2516904"}, + {"PB", "Umbuzeiro", "2517001"}, + {"PB", "V\u00e1rzea", "2517100"}, + {"PB", "Vieir\u00f3polis", "2517209"}, + {"PB", "Vista Serrana", "2505501"}, + {"PB", "Zabel\u00ea", "2517407"}, + {"PR", "Abati\u00e1", "4100103"}, + {"PR", "Adrian\u00f3polis", "4100202"}, + {"PR", "Agudos do Sul", "4100301"}, + {"PR", "Almirante Tamandar\u00e9", "4100400"}, + {"PR", "Altamira do Paran\u00e1", "4100459"}, + {"PR", "Alto Para\u00edso", "4128625"}, + {"PR", "Alto Paran\u00e1", "4100608"}, + {"PR", "Alto Piquiri", "4100707"}, + {"PR", "Alt\u00f4nia", "4100509"}, + {"PR", "Alvorada do Sul", "4100806"}, + {"PR", "Amapor\u00e3", "4100905"}, + {"PR", "Amp\u00e9re", "4101002"}, + {"PR", "Anahy", "4101051"}, + {"PR", "Andir\u00e1", "4101101"}, + {"PR", "\u00c2ngulo", "4101150"}, + {"PR", "Antonina", "4101200"}, + {"PR", "Ant\u00f4nio Olinto", "4101309"}, + {"PR", "Apucarana", "4101408"}, + {"PR", "Arapongas", "4101507"}, + {"PR", "Arapoti", "4101606"}, + {"PR", "Arapu\u00e3", "4101655"}, + {"PR", "Araruna", "4101705"}, + {"PR", "Arauc\u00e1ria", "4101804"}, + {"PR", "Ariranha do Iva\u00ed", "4101853"}, + {"PR", "Assa\u00ed", "4101903"}, + {"PR", "Assis Chateaubriand", "4102000"}, + {"PR", "Astorga", "4102109"}, + {"PR", "Atalaia", "4102208"}, + {"PR", "Balsa Nova", "4102307"}, + {"PR", "Bandeirantes", "4102406"}, + {"PR", "Barbosa Ferraz", "4102505"}, + {"PR", "Barra do Jacar\u00e9", "4102703"}, + {"PR", "Barrac\u00e3o", "4102604"}, + {"PR", "Bela Vista da Caroba", "4102752"}, + {"PR", "Bela Vista do Para\u00edso", "4102802"}, + {"PR", "Bituruna", "4102901"}, + {"PR", "Boa Esperan\u00e7a", "4103008"}, + {"PR", "Boa Esperan\u00e7a do Igua\u00e7u", "4103024"}, + {"PR", "Boa Ventura de S\u00e3o Roque", "4103040"}, + {"PR", "Boa Vista da Aparecida", "4103057"}, + {"PR", "Bocai\u00fava do Sul", "4103107"}, + {"PR", "Bom Jesus do Sul", "4103156"}, + {"PR", "Bom Sucesso", "4103206"}, + {"PR", "Bom Sucesso do Sul", "4103222"}, + {"PR", "Borraz\u00f3polis", "4103305"}, + {"PR", "Braganey", "4103354"}, + {"PR", "Brasil\u00e2ndia do Sul", "4103370"}, + {"PR", "Cafeara", "4103404"}, + {"PR", "Cafel\u00e2ndia", "4103453"}, + {"PR", "Cafezal do Sul", "4103479"}, + {"PR", "Calif\u00f3rnia", "4103503"}, + {"PR", "Cambar\u00e1", "4103602"}, + {"PR", "Camb\u00e9", "4103701"}, + {"PR", "Cambira", "4103800"}, + {"PR", "Campina da Lagoa", "4103909"}, + {"PR", "Campina do Sim\u00e3o", "4103958"}, + {"PR", "Campina Grande do Sul", "4104006"}, + {"PR", "Campo Bonito", "4104055"}, + {"PR", "Campo do Tenente", "4104105"}, + {"PR", "Campo Largo", "4104204"}, + {"PR", "Campo Magro", "4104253"}, + {"PR", "Campo Mour\u00e3o", "4104303"}, + {"PR", "C\u00e2ndido de Abreu", "4104402"}, + {"PR", "Cand\u00f3i", "4104428"}, + {"PR", "Cantagalo", "4104451"}, + {"PR", "Capanema", "4104501"}, + {"PR", "Capit\u00e3o Le\u00f4nidas Marques", "4104600"}, + {"PR", "Carambe\u00ed", "4104659"}, + {"PR", "Carl\u00f3polis", "4104709"}, + {"PR", "Cascavel", "4104808"}, + {"PR", "Castro", "4104907"}, + {"PR", "Catanduvas", "4105003"}, + {"PR", "Centen\u00e1rio do Sul", "4105102"}, + {"PR", "Cerro Azul", "4105201"}, + {"PR", "C\u00e9u Azul", "4105300"}, + {"PR", "Chopinzinho", "4105409"}, + {"PR", "Cianorte", "4105508"}, + {"PR", "Cidade Ga\u00facha", "4105607"}, + {"PR", "Clevel\u00e2ndia", "4105706"}, + {"PR", "Colombo", "4105805"}, + {"PR", "Colorado", "4105904"}, + {"PR", "Congonhinhas", "4106001"}, + {"PR", "Conselheiro Mairinck", "4106100"}, + {"PR", "Contenda", "4106209"}, + {"PR", "Corb\u00e9lia", "4106308"}, + {"PR", "Corn\u00e9lio Proc\u00f3pio", "4106407"}, + {"PR", "Coronel Domingos Soares", "4106456"}, + {"PR", "Coronel Vivida", "4106506"}, + {"PR", "Corumbata\u00ed do Sul", "4106555"}, + {"PR", "Cruz Machado", "4106803"}, + {"PR", "Cruzeiro do Igua\u00e7u", "4106571"}, + {"PR", "Cruzeiro do Oeste", "4106605"}, + {"PR", "Cruzeiro do Sul", "4106704"}, + {"PR", "Cruzmaltina", "4106852"}, + {"PR", "Curitiba", "4106902"}, + {"PR", "Curi\u00fava", "4107009"}, + {"PR", "Diamante D'Oeste", "4107157"}, + {"PR", "Diamante do Norte", "4107108"}, + {"PR", "Diamante do Sul", "4107124"}, + {"PR", "Dois Vizinhos", "4107207"}, + {"PR", "Douradina", "4107256"}, + {"PR", "Doutor Camargo", "4107306"}, + {"PR", "Doutor Ulysses", "4128633"}, + {"PR", "En\u00e9as Marques", "4107405"}, + {"PR", "Engenheiro Beltr\u00e3o", "4107504"}, + {"PR", "Entre Rios do Oeste", "4107538"}, + {"PR", "Esperan\u00e7a Nova", "4107520"}, + {"PR", "Espig\u00e3o Alto do Igua\u00e7u", "4107546"}, + {"PR", "Farol", "4107553"}, + {"PR", "Faxinal", "4107603"}, + {"PR", "Fazenda Rio Grande", "4107652"}, + {"PR", "F\u00eanix", "4107702"}, + {"PR", "Fernandes Pinheiro", "4107736"}, + {"PR", "Figueira", "4107751"}, + {"PR", "Flor da Serra do Sul", "4107850"}, + {"PR", "Flora\u00ed", "4107801"}, + {"PR", "Floresta", "4107900"}, + {"PR", "Florest\u00f3polis", "4108007"}, + {"PR", "Fl\u00f3rida", "4108106"}, + {"PR", "Formosa do Oeste", "4108205"}, + {"PR", "Foz do Igua\u00e7u", "4108304"}, + {"PR", "Foz do Jord\u00e3o", "4108452"}, + {"PR", "Francisco Alves", "4108320"}, + {"PR", "Francisco Beltr\u00e3o", "4108403"}, + {"PR", "General Carneiro", "4108502"}, + {"PR", "Godoy Moreira", "4108551"}, + {"PR", "Goioer\u00ea", "4108601"}, + {"PR", "Goioxim", "4108650"}, + {"PR", "Grandes Rios", "4108700"}, + {"PR", "Gua\u00edra", "4108809"}, + {"PR", "Guaira\u00e7\u00e1", "4108908"}, + {"PR", "Guamiranga", "4108957"}, + {"PR", "Guapirama", "4109005"}, + {"PR", "Guaporema", "4109104"}, + {"PR", "Guaraci", "4109203"}, + {"PR", "Guarania\u00e7u", "4109302"}, + {"PR", "Guarapuava", "4109401"}, + {"PR", "Guaraque\u00e7aba", "4109500"}, + {"PR", "Guaratuba", "4109609"}, + {"PR", "Hon\u00f3rio Serpa", "4109658"}, + {"PR", "Ibaiti", "4109708"}, + {"PR", "Ibema", "4109757"}, + {"PR", "Ibipor\u00e3", "4109807"}, + {"PR", "Icara\u00edma", "4109906"}, + {"PR", "Iguara\u00e7u", "4110003"}, + {"PR", "Iguatu", "4110052"}, + {"PR", "Imba\u00fa", "4110078"}, + {"PR", "Imbituva", "4110102"}, + {"PR", "In\u00e1cio Martins", "4110201"}, + {"PR", "Inaj\u00e1", "4110300"}, + {"PR", "Indian\u00f3polis", "4110409"}, + {"PR", "Ipiranga", "4110508"}, + {"PR", "Ipor\u00e3", "4110607"}, + {"PR", "Iracema do Oeste", "4110656"}, + {"PR", "Irati", "4110706"}, + {"PR", "Iretama", "4110805"}, + {"PR", "Itaguaj\u00e9", "4110904"}, + {"PR", "Itaipul\u00e2ndia", "4110953"}, + {"PR", "Itambarac\u00e1", "4111001"}, + {"PR", "Itamb\u00e9", "4111100"}, + {"PR", "Itapejara d'Oeste", "4111209"}, + {"PR", "Itaperu\u00e7u", "4111258"}, + {"PR", "Ita\u00fana do Sul", "4111308"}, + {"PR", "Iva\u00ed", "4111407"}, + {"PR", "Ivaipor\u00e3", "4111506"}, + {"PR", "Ivat\u00e9", "4111555"}, + {"PR", "Ivatuba", "4111605"}, + {"PR", "Jaboti", "4111704"}, + {"PR", "Jacarezinho", "4111803"}, + {"PR", "Jaguapit\u00e3", "4111902"}, + {"PR", "Jaguaria\u00edva", "4112009"}, + {"PR", "Jandaia do Sul", "4112108"}, + {"PR", "Jani\u00f3polis", "4112207"}, + {"PR", "Japira", "4112306"}, + {"PR", "Japur\u00e1", "4112405"}, + {"PR", "Jardim Alegre", "4112504"}, + {"PR", "Jardim Olinda", "4112603"}, + {"PR", "Jataizinho", "4112702"}, + {"PR", "Jesu\u00edtas", "4112751"}, + {"PR", "Joaquim T\u00e1vora", "4112801"}, + {"PR", "Jundia\u00ed do Sul", "4112900"}, + {"PR", "Juranda", "4112959"}, + {"PR", "Jussara", "4113007"}, + {"PR", "Kalor\u00e9", "4113106"}, + {"PR", "Lapa", "4113205"}, + {"PR", "Laranjal", "4113254"}, + {"PR", "Laranjeiras do Sul", "4113304"}, + {"PR", "Le\u00f3polis", "4113403"}, + {"PR", "Lidian\u00f3polis", "4113429"}, + {"PR", "Lindoeste", "4113452"}, + {"PR", "Loanda", "4113502"}, + {"PR", "Lobato", "4113601"}, + {"PR", "Londrina", "4113700"}, + {"PR", "Luiziana", "4113734"}, + {"PR", "Lunardelli", "4113759"}, + {"PR", "Lupion\u00f3polis", "4113809"}, + {"PR", "Mallet", "4113908"}, + {"PR", "Mambor\u00ea", "4114005"}, + {"PR", "Mandagua\u00e7u", "4114104"}, + {"PR", "Mandaguari", "4114203"}, + {"PR", "Mandirituba", "4114302"}, + {"PR", "Manfrin\u00f3polis", "4114351"}, + {"PR", "Mangueirinha", "4114401"}, + {"PR", "Manoel Ribas", "4114500"}, + {"PR", "Marechal C\u00e2ndido Rondon", "4114609"}, + {"PR", "Maria Helena", "4114708"}, + {"PR", "Marialva", "4114807"}, + {"PR", "Maril\u00e2ndia do Sul", "4114906"}, + {"PR", "Marilena", "4115002"}, + {"PR", "Mariluz", "4115101"}, + {"PR", "Maring\u00e1", "4115200"}, + {"PR", "Mari\u00f3polis", "4115309"}, + {"PR", "Marip\u00e1", "4115358"}, + {"PR", "Marmeleiro", "4115408"}, + {"PR", "Marquinho", "4115457"}, + {"PR", "Marumbi", "4115507"}, + {"PR", "Matel\u00e2ndia", "4115606"}, + {"PR", "Matinhos", "4115705"}, + {"PR", "Mato Rico", "4115739"}, + {"PR", "Mau\u00e1 da Serra", "4115754"}, + {"PR", "Medianeira", "4115804"}, + {"PR", "Mercedes", "4115853"}, + {"PR", "Mirador", "4115903"}, + {"PR", "Miraselva", "4116000"}, + {"PR", "Missal", "4116059"}, + {"PR", "Moreira Sales", "4116109"}, + {"PR", "Morretes", "4116208"}, + {"PR", "Munhoz de Melo", "4116307"}, + {"PR", "Nossa Senhora das Gra\u00e7as", "4116406"}, + {"PR", "Nova Alian\u00e7a do Iva\u00ed", "4116505"}, + {"PR", "Nova Am\u00e9rica da Colina", "4116604"}, + {"PR", "Nova Aurora", "4116703"}, + {"PR", "Nova Cantu", "4116802"}, + {"PR", "Nova Esperan\u00e7a", "4116901"}, + {"PR", "Nova Esperan\u00e7a do Sudoeste", "4116950"}, + {"PR", "Nova F\u00e1tima", "4117008"}, + {"PR", "Nova Laranjeiras", "4117057"}, + {"PR", "Nova Londrina", "4117107"}, + {"PR", "Nova Ol\u00edmpia", "4117206"}, + {"PR", "Nova Prata do Igua\u00e7u", "4117255"}, + {"PR", "Nova Santa B\u00e1rbara", "4117214"}, + {"PR", "Nova Santa Rosa", "4117222"}, + {"PR", "Nova Tebas", "4117271"}, + {"PR", "Novo Itacolomi", "4117297"}, + {"PR", "Ortigueira", "4117305"}, + {"PR", "Ourizona", "4117404"}, + {"PR", "Ouro Verde do Oeste", "4117453"}, + {"PR", "Pai\u00e7andu", "4117503"}, + {"PR", "Palmas", "4117602"}, + {"PR", "Palmeira", "4117701"}, + {"PR", "Palmital", "4117800"}, + {"PR", "Palotina", "4117909"}, + {"PR", "Para\u00edso do Norte", "4118006"}, + {"PR", "Paranacity", "4118105"}, + {"PR", "Paranagu\u00e1", "4118204"}, + {"PR", "Paranapoema", "4118303"}, + {"PR", "Paranava\u00ed", "4118402"}, + {"PR", "Pato Bragado", "4118451"}, + {"PR", "Pato Branco", "4118501"}, + {"PR", "Paula Freitas", "4118600"}, + {"PR", "Paulo Frontin", "4118709"}, + {"PR", "Peabiru", "4118808"}, + {"PR", "Perobal", "4118857"}, + {"PR", "P\u00e9rola", "4118907"}, + {"PR", "P\u00e9rola d'Oeste", "4119004"}, + {"PR", "Pi\u00ean", "4119103"}, + {"PR", "Pinhais", "4119152"}, + {"PR", "Pinhal de S\u00e3o Bento", "4119251"}, + {"PR", "Pinhal\u00e3o", "4119202"}, + {"PR", "Pinh\u00e3o", "4119301"}, + {"PR", "Pira\u00ed do Sul", "4119400"}, + {"PR", "Piraquara", "4119509"}, + {"PR", "Pitanga", "4119608"}, + {"PR", "Pitangueiras", "4119657"}, + {"PR", "Planaltina do Paran\u00e1", "4119707"}, + {"PR", "Planalto", "4119806"}, + {"PR", "Ponta Grossa", "4119905"}, + {"PR", "Pontal do Paran\u00e1", "4119954"}, + {"PR", "Porecatu", "4120002"}, + {"PR", "Porto Amazonas", "4120101"}, + {"PR", "Porto Barreiro", "4120150"}, + {"PR", "Porto Rico", "4120200"}, + {"PR", "Porto Vit\u00f3ria", "4120309"}, + {"PR", "Prado Ferreira", "4120333"}, + {"PR", "Pranchita", "4120358"}, + {"PR", "Presidente Castelo Branco", "4120408"}, + {"PR", "Primeiro de Maio", "4120507"}, + {"PR", "Prudent\u00f3polis", "4120606"}, + {"PR", "Quarto Centen\u00e1rio", "4120655"}, + {"PR", "Quatigu\u00e1", "4120705"}, + {"PR", "Quatro Barras", "4120804"}, + {"PR", "Quatro Pontes", "4120853"}, + {"PR", "Quedas do Igua\u00e7u", "4120903"}, + {"PR", "Quer\u00eancia do Norte", "4121000"}, + {"PR", "Quinta do Sol", "4121109"}, + {"PR", "Quitandinha", "4121208"}, + {"PR", "Ramil\u00e2ndia", "4121257"}, + {"PR", "Rancho Alegre", "4121307"}, + {"PR", "Rancho Alegre D'Oeste", "4121356"}, + {"PR", "Realeza", "4121406"}, + {"PR", "Rebou\u00e7as", "4121505"}, + {"PR", "Renascen\u00e7a", "4121604"}, + {"PR", "Reserva", "4121703"}, + {"PR", "Reserva do Igua\u00e7u", "4121752"}, + {"PR", "Ribeir\u00e3o Claro", "4121802"}, + {"PR", "Ribeir\u00e3o do Pinhal", "4121901"}, + {"PR", "Rio Azul", "4122008"}, + {"PR", "Rio Bom", "4122107"}, + {"PR", "Rio Bonito do Igua\u00e7u", "4122156"}, + {"PR", "Rio Branco do Iva\u00ed", "4122172"}, + {"PR", "Rio Branco do Sul", "4122206"}, + {"PR", "Rio Negro", "4122305"}, + {"PR", "Rol\u00e2ndia", "4122404"}, + {"PR", "Roncador", "4122503"}, + {"PR", "Rondon", "4122602"}, + {"PR", "Ros\u00e1rio do Iva\u00ed", "4122651"}, + {"PR", "Sab\u00e1udia", "4122701"}, + {"PR", "Salgado Filho", "4122800"}, + {"PR", "Salto do Itarar\u00e9", "4122909"}, + {"PR", "Salto do Lontra", "4123006"}, + {"PR", "Santa Am\u00e9lia", "4123105"}, + {"PR", "Santa Cec\u00edlia do Pav\u00e3o", "4123204"}, + {"PR", "Santa Cruz de Monte Castelo", "4123303"}, + {"PR", "Santa F\u00e9", "4123402"}, + {"PR", "Santa Helena", "4123501"}, + {"PR", "Santa In\u00eas", "4123600"}, + {"PR", "Santa Isabel do Iva\u00ed", "4123709"}, + {"PR", "Santa Izabel do Oeste", "4123808"}, + {"PR", "Santa L\u00facia", "4123824"}, + {"PR", "Santa Maria do Oeste", "4123857"}, + {"PR", "Santa Mariana", "4123907"}, + {"PR", "Santa M\u00f4nica", "4123956"}, + {"PR", "Santa Tereza do Oeste", "4124020"}, + {"PR", "Santa Terezinha de Itaipu", "4124053"}, + {"PR", "Santana do Itarar\u00e9", "4124004"}, + {"PR", "Santo Ant\u00f4nio da Platina", "4124103"}, + {"PR", "Santo Ant\u00f4nio do Caiu\u00e1", "4124202"}, + {"PR", "Santo Ant\u00f4nio do Para\u00edso", "4124301"}, + {"PR", "Santo Ant\u00f4nio do Sudoeste", "4124400"}, + {"PR", "Santo In\u00e1cio", "4124509"}, + {"PR", "S\u00e3o Carlos do Iva\u00ed", "4124608"}, + {"PR", "S\u00e3o Jer\u00f4nimo da Serra", "4124707"}, + {"PR", "S\u00e3o Jo\u00e3o", "4124806"}, + {"PR", "S\u00e3o Jo\u00e3o do Caiu\u00e1", "4124905"}, + {"PR", "S\u00e3o Jo\u00e3o do Iva\u00ed", "4125001"}, + {"PR", "S\u00e3o Jo\u00e3o do Triunfo", "4125100"}, + {"PR", "S\u00e3o Jorge d'Oeste", "4125209"}, + {"PR", "S\u00e3o Jorge do Iva\u00ed", "4125308"}, + {"PR", "S\u00e3o Jorge do Patroc\u00ednio", "4125357"}, + {"PR", "S\u00e3o Jos\u00e9 da Boa Vista", "4125407"}, + {"PR", "S\u00e3o Jos\u00e9 das Palmeiras", "4125456"}, + {"PR", "S\u00e3o Jos\u00e9 dos Pinhais", "4125506"}, + {"PR", "S\u00e3o Manoel do Paran\u00e1", "4125555"}, + {"PR", "S\u00e3o Mateus do Sul", "4125605"}, + {"PR", "S\u00e3o Miguel do Igua\u00e7u", "4125704"}, + {"PR", "S\u00e3o Pedro do Igua\u00e7u", "4125753"}, + {"PR", "S\u00e3o Pedro do Iva\u00ed", "4125803"}, + {"PR", "S\u00e3o Pedro do Paran\u00e1", "4125902"}, + {"PR", "S\u00e3o Sebasti\u00e3o da Amoreira", "4126009"}, + {"PR", "S\u00e3o Tom\u00e9", "4126108"}, + {"PR", "Sapopema", "4126207"}, + {"PR", "Sarandi", "4126256"}, + {"PR", "Saudade do Igua\u00e7u", "4126272"}, + {"PR", "Seng\u00e9s", "4126306"}, + {"PR", "Serran\u00f3polis do Igua\u00e7u", "4126355"}, + {"PR", "Sertaneja", "4126405"}, + {"PR", "Sertan\u00f3polis", "4126504"}, + {"PR", "Siqueira Campos", "4126603"}, + {"PR", "Sulina", "4126652"}, + {"PR", "Tamarana", "4126678"}, + {"PR", "Tamboara", "4126702"}, + {"PR", "Tapejara", "4126801"}, + {"PR", "Tapira", "4126900"}, + {"PR", "Teixeira Soares", "4127007"}, + {"PR", "Tel\u00eamaco Borba", "4127106"}, + {"PR", "Terra Boa", "4127205"}, + {"PR", "Terra Rica", "4127304"}, + {"PR", "Terra Roxa", "4127403"}, + {"PR", "Tibagi", "4127502"}, + {"PR", "Tijucas do Sul", "4127601"}, + {"PR", "Toledo", "4127700"}, + {"PR", "Tomazina", "4127809"}, + {"PR", "Tr\u00eas Barras do Paran\u00e1", "4127858"}, + {"PR", "Tunas do Paran\u00e1", "4127882"}, + {"PR", "Tuneiras do Oeste", "4127908"}, + {"PR", "Tup\u00e3ssi", "4127957"}, + {"PR", "Turvo", "4127965"}, + {"PR", "Ubirat\u00e3", "4128005"}, + {"PR", "Umuarama", "4128104"}, + {"PR", "Uni\u00e3o da Vit\u00f3ria", "4128203"}, + {"PR", "Uniflor", "4128302"}, + {"PR", "Ura\u00ed", "4128401"}, + {"PR", "Ventania", "4128534"}, + {"PR", "Vera Cruz do Oeste", "4128559"}, + {"PR", "Ver\u00ea", "4128609"}, + {"PR", "Virmond", "4128658"}, + {"PR", "Vitorino", "4128708"}, + {"PR", "Wenceslau Braz", "4128500"}, + {"PR", "Xambr\u00ea", "4128807"}, + {"PE", "Abreu e Lima", "2600054"}, + {"PE", "Afogados da Ingazeira", "2600104"}, + {"PE", "Afr\u00e2nio", "2600203"}, + {"PE", "Agrestina", "2600302"}, + {"PE", "\u00c1gua Preta", "2600401"}, + {"PE", "\u00c1guas Belas", "2600500"}, + {"PE", "Alagoinha", "2600609"}, + {"PE", "Alian\u00e7a", "2600708"}, + {"PE", "Altinho", "2600807"}, + {"PE", "Amaraji", "2600906"}, + {"PE", "Angelim", "2601003"}, + {"PE", "Ara\u00e7oiaba", "2601052"}, + {"PE", "Araripina", "2601102"}, + {"PE", "Arcoverde", "2601201"}, + {"PE", "Barra de Guabiraba", "2601300"}, + {"PE", "Barreiros", "2601409"}, + {"PE", "Bel\u00e9m de Maria", "2601508"}, + {"PE", "Bel\u00e9m do S\u00e3o Francisco", "2601607"}, + {"PE", "Belo Jardim", "2601706"}, + {"PE", "Bet\u00e2nia", "2601805"}, + {"PE", "Bezerros", "2601904"}, + {"PE", "Bodoc\u00f3", "2602001"}, + {"PE", "Bom Conselho", "2602100"}, + {"PE", "Bom Jardim", "2602209"}, + {"PE", "Bonito", "2602308"}, + {"PE", "Brej\u00e3o", "2602407"}, + {"PE", "Brejinho", "2602506"}, + {"PE", "Brejo da Madre de Deus", "2602605"}, + {"PE", "Buenos Aires", "2602704"}, + {"PE", "Bu\u00edque", "2602803"}, + {"PE", "Cabo de Santo Agostinho", "2602902"}, + {"PE", "Cabrob\u00f3", "2603009"}, + {"PE", "Cachoeirinha", "2603108"}, + {"PE", "Caet\u00e9s", "2603207"}, + {"PE", "Cal\u00e7ado", "2603306"}, + {"PE", "Calumbi", "2603405"}, + {"PE", "Camaragibe", "2603454"}, + {"PE", "Camocim de S\u00e3o F\u00e9lix", "2603504"}, + {"PE", "Camutanga", "2603603"}, + {"PE", "Canhotinho", "2603702"}, + {"PE", "Capoeiras", "2603801"}, + {"PE", "Carna\u00edba", "2603900"}, + {"PE", "Carnaubeira da Penha", "2603926"}, + {"PE", "Carpina", "2604007"}, + {"PE", "Caruaru", "2604106"}, + {"PE", "Casinhas", "2604155"}, + {"PE", "Catende", "2604205"}, + {"PE", "Cedro", "2604304"}, + {"PE", "Ch\u00e3 de Alegria", "2604403"}, + {"PE", "Ch\u00e3 Grande", "2604502"}, + {"PE", "Condado", "2604601"}, + {"PE", "Correntes", "2604700"}, + {"PE", "Cort\u00eas", "2604809"}, + {"PE", "Cumaru", "2604908"}, + {"PE", "Cupira", "2605004"}, + {"PE", "Cust\u00f3dia", "2605103"}, + {"PE", "Dormentes", "2605152"}, + {"PE", "Escada", "2605202"}, + {"PE", "Exu", "2605301"}, + {"PE", "Feira Nova", "2605400"}, + {"PE", "Fernando de Noronha", "2605459"}, + {"PE", "Ferreiros", "2605509"}, + {"PE", "Flores", "2605608"}, + {"PE", "Floresta", "2605707"}, + {"PE", "Frei Miguelinho", "2605806"}, + {"PE", "Gameleira", "2605905"}, + {"PE", "Garanhuns", "2606002"}, + {"PE", "Gl\u00f3ria do Goit\u00e1", "2606101"}, + {"PE", "Goiana", "2606200"}, + {"PE", "Granito", "2606309"}, + {"PE", "Gravat\u00e1", "2606408"}, + {"PE", "Iati", "2606507"}, + {"PE", "Ibimirim", "2606606"}, + {"PE", "Ibirajuba", "2606705"}, + {"PE", "Igarassu", "2606804"}, + {"PE", "Iguaracy", "2606903"}, + {"PE", "Ilha de Itamarac\u00e1", "2607604"}, + {"PE", "Inaj\u00e1", "2607000"}, + {"PE", "Ingazeira", "2607109"}, + {"PE", "Ipojuca", "2607208"}, + {"PE", "Ipubi", "2607307"}, + {"PE", "Itacuruba", "2607406"}, + {"PE", "Ita\u00edba", "2607505"}, + {"PE", "Itamb\u00e9", "2607653"}, + {"PE", "Itapetim", "2607703"}, + {"PE", "Itapissuma", "2607752"}, + {"PE", "Itaquitinga", "2607802"}, + {"PE", "Jaboat\u00e3o dos Guararapes", "2607901"}, + {"PE", "Jaqueira", "2607950"}, + {"PE", "Jata\u00faba", "2608008"}, + {"PE", "Jatob\u00e1", "2608057"}, + {"PE", "Jo\u00e3o Alfredo", "2608107"}, + {"PE", "Joaquim Nabuco", "2608206"}, + {"PE", "Jucati", "2608255"}, + {"PE", "Jupi", "2608305"}, + {"PE", "Jurema", "2608404"}, + {"PE", "Lagoa de Itaenga", "2608503"}, + {"PE", "Lagoa do Carro", "2608453"}, + {"PE", "Lagoa do Ouro", "2608602"}, + {"PE", "Lagoa dos Gatos", "2608701"}, + {"PE", "Lagoa Grande", "2608750"}, + {"PE", "Lajedo", "2608800"}, + {"PE", "Limoeiro", "2608909"}, + {"PE", "Macaparana", "2609006"}, + {"PE", "Machados", "2609105"}, + {"PE", "Manari", "2609154"}, + {"PE", "Maraial", "2609204"}, + {"PE", "Mirandiba", "2609303"}, + {"PE", "Moreil\u00e2ndia", "2614303"}, + {"PE", "Moreno", "2609402"}, + {"PE", "Nazar\u00e9 da Mata", "2609501"}, + {"PE", "Olinda", "2609600"}, + {"PE", "Orob\u00f3", "2609709"}, + {"PE", "Oroc\u00f3", "2609808"}, + {"PE", "Ouricuri", "2609907"}, + {"PE", "Palmares", "2610004"}, + {"PE", "Palmeirina", "2610103"}, + {"PE", "Panelas", "2610202"}, + {"PE", "Paranatama", "2610301"}, + {"PE", "Parnamirim", "2610400"}, + {"PE", "Passira", "2610509"}, + {"PE", "Paudalho", "2610608"}, + {"PE", "Paulista", "2610707"}, + {"PE", "Pedra", "2610806"}, + {"PE", "Pesqueira", "2610905"}, + {"PE", "Petrol\u00e2ndia", "2611002"}, + {"PE", "Petrolina", "2611101"}, + {"PE", "Po\u00e7\u00e3o", "2611200"}, + {"PE", "Pombos", "2611309"}, + {"PE", "Primavera", "2611408"}, + {"PE", "Quipap\u00e1", "2611507"}, + {"PE", "Quixaba", "2611533"}, + {"PE", "Recife", "2611606"}, + {"PE", "Riacho das Almas", "2611705"}, + {"PE", "Ribeir\u00e3o", "2611804"}, + {"PE", "Rio Formoso", "2611903"}, + {"PE", "Sair\u00e9", "2612000"}, + {"PE", "Salgadinho", "2612109"}, + {"PE", "Salgueiro", "2612208"}, + {"PE", "Salo\u00e1", "2612307"}, + {"PE", "Sanhar\u00f3", "2612406"}, + {"PE", "Santa Cruz", "2612455"}, + {"PE", "Santa Cruz da Baixa Verde", "2612471"}, + {"PE", "Santa Cruz do Capibaribe", "2612505"}, + {"PE", "Santa Filomena", "2612554"}, + {"PE", "Santa Maria da Boa Vista", "2612604"}, + {"PE", "Santa Maria do Cambuc\u00e1", "2612703"}, + {"PE", "Santa Terezinha", "2612802"}, + {"PE", "S\u00e3o Benedito do Sul", "2612901"}, + {"PE", "S\u00e3o Bento do Una", "2613008"}, + {"PE", "S\u00e3o Caitano", "2613107"}, + {"PE", "S\u00e3o Jo\u00e3o", "2613206"}, + {"PE", "S\u00e3o Joaquim do Monte", "2613305"}, + {"PE", "S\u00e3o Jos\u00e9 da Coroa Grande", "2613404"}, + {"PE", "S\u00e3o Jos\u00e9 do Belmonte", "2613503"}, + {"PE", "S\u00e3o Jos\u00e9 do Egito", "2613602"}, + {"PE", "S\u00e3o Louren\u00e7o da Mata", "2613701"}, + {"PE", "S\u00e3o Vicente F\u00e9rrer", "2613800"}, + {"PE", "Serra Talhada", "2613909"}, + {"PE", "Serrita", "2614006"}, + {"PE", "Sert\u00e2nia", "2614105"}, + {"PE", "Sirinha\u00e9m", "2614204"}, + {"PE", "Solid\u00e3o", "2614402"}, + {"PE", "Surubim", "2614501"}, + {"PE", "Tabira", "2614600"}, + {"PE", "Tacaimb\u00f3", "2614709"}, + {"PE", "Tacaratu", "2614808"}, + {"PE", "Tamandar\u00e9", "2614857"}, + {"PE", "Taquaritinga do Norte", "2615003"}, + {"PE", "Terezinha", "2615102"}, + {"PE", "Terra Nova", "2615201"}, + {"PE", "Timba\u00faba", "2615300"}, + {"PE", "Toritama", "2615409"}, + {"PE", "Tracunha\u00e9m", "2615508"}, + {"PE", "Trindade", "2615607"}, + {"PE", "Triunfo", "2615706"}, + {"PE", "Tupanatinga", "2615805"}, + {"PE", "Tuparetama", "2615904"}, + {"PE", "Venturosa", "2616001"}, + {"PE", "Verdejante", "2616100"}, + {"PE", "Vertente do L\u00e9rio", "2616183"}, + {"PE", "Vertentes", "2616209"}, + {"PE", "Vic\u00eancia", "2616308"}, + {"PE", "Vit\u00f3ria de Santo Ant\u00e3o", "2616407"}, + {"PE", "Xex\u00e9u", "2616506"}, + {"PI", "Acau\u00e3", "2200053"}, + {"PI", "Agricol\u00e2ndia", "2200103"}, + {"PI", "\u00c1gua Branca", "2200202"}, + {"PI", "Alagoinha do Piau\u00ed", "2200251"}, + {"PI", "Alegrete do Piau\u00ed", "2200277"}, + {"PI", "Alto Long\u00e1", "2200301"}, + {"PI", "Altos", "2200400"}, + {"PI", "Alvorada do Gurgu\u00e9ia", "2200459"}, + {"PI", "Amarante", "2200509"}, + {"PI", "Angical do Piau\u00ed", "2200608"}, + {"PI", "An\u00edsio de Abreu", "2200707"}, + {"PI", "Ant\u00f4nio Almeida", "2200806"}, + {"PI", "Aroazes", "2200905"}, + {"PI", "Aroeiras do Itaim", "2200954"}, + {"PI", "Arraial", "2201002"}, + {"PI", "Assun\u00e7\u00e3o do Piau\u00ed", "2201051"}, + {"PI", "Avelino Lopes", "2201101"}, + {"PI", "Baixa Grande do Ribeiro", "2201150"}, + {"PI", "Barra D'Alc\u00e2ntara", "2201176"}, + {"PI", "Barras", "2201200"}, + {"PI", "Barreiras do Piau\u00ed", "2201309"}, + {"PI", "Barro Duro", "2201408"}, + {"PI", "Batalha", "2201507"}, + {"PI", "Bela Vista do Piau\u00ed", "2201556"}, + {"PI", "Bel\u00e9m do Piau\u00ed", "2201572"}, + {"PI", "Beneditinos", "2201606"}, + {"PI", "Bertol\u00ednia", "2201705"}, + {"PI", "Bet\u00e2nia do Piau\u00ed", "2201739"}, + {"PI", "Boa Hora", "2201770"}, + {"PI", "Bocaina", "2201804"}, + {"PI", "Bom Jesus", "2201903"}, + {"PI", "Bom Princ\u00edpio do Piau\u00ed", "2201919"}, + {"PI", "Bonfim do Piau\u00ed", "2201929"}, + {"PI", "Boqueir\u00e3o do Piau\u00ed", "2201945"}, + {"PI", "Brasileira", "2201960"}, + {"PI", "Brejo do Piau\u00ed", "2201988"}, + {"PI", "Buriti dos Lopes", "2202000"}, + {"PI", "Buriti dos Montes", "2202026"}, + {"PI", "Cabeceiras do Piau\u00ed", "2202059"}, + {"PI", "Cajazeiras do Piau\u00ed", "2202075"}, + {"PI", "Cajueiro da Praia", "2202083"}, + {"PI", "Caldeir\u00e3o Grande do Piau\u00ed", "2202091"}, + {"PI", "Campinas do Piau\u00ed", "2202109"}, + {"PI", "Campo Alegre do Fidalgo", "2202117"}, + {"PI", "Campo Grande do Piau\u00ed", "2202133"}, + {"PI", "Campo Largo do Piau\u00ed", "2202174"}, + {"PI", "Campo Maior", "2202208"}, + {"PI", "Canavieira", "2202251"}, + {"PI", "Canto do Buriti", "2202307"}, + {"PI", "Capit\u00e3o de Campos", "2202406"}, + {"PI", "Capit\u00e3o Gerv\u00e1sio Oliveira", "2202455"}, + {"PI", "Caracol", "2202505"}, + {"PI", "Cara\u00fabas do Piau\u00ed", "2202539"}, + {"PI", "Caridade do Piau\u00ed", "2202554"}, + {"PI", "Castelo do Piau\u00ed", "2202604"}, + {"PI", "Caxing\u00f3", "2202653"}, + {"PI", "Cocal", "2202703"}, + {"PI", "Cocal de Telha", "2202711"}, + {"PI", "Cocal dos Alves", "2202729"}, + {"PI", "Coivaras", "2202737"}, + {"PI", "Col\u00f4nia do Gurgu\u00e9ia", "2202752"}, + {"PI", "Col\u00f4nia do Piau\u00ed", "2202778"}, + {"PI", "Concei\u00e7\u00e3o do Canind\u00e9", "2202802"}, + {"PI", "Coronel Jos\u00e9 Dias", "2202851"}, + {"PI", "Corrente", "2202901"}, + {"PI", "Cristal\u00e2ndia do Piau\u00ed", "2203008"}, + {"PI", "Cristino Castro", "2203107"}, + {"PI", "Curimat\u00e1", "2203206"}, + {"PI", "Currais", "2203230"}, + {"PI", "Curral Novo do Piau\u00ed", "2203271"}, + {"PI", "Curralinhos", "2203255"}, + {"PI", "Demerval Lob\u00e3o", "2203305"}, + {"PI", "Dirceu Arcoverde", "2203354"}, + {"PI", "Dom Expedito Lopes", "2203404"}, + {"PI", "Dom Inoc\u00eancio", "2203453"}, + {"PI", "Domingos Mour\u00e3o", "2203420"}, + {"PI", "Elesb\u00e3o Veloso", "2203503"}, + {"PI", "Eliseu Martins", "2203602"}, + {"PI", "Esperantina", "2203701"}, + {"PI", "Fartura do Piau\u00ed", "2203750"}, + {"PI", "Flores do Piau\u00ed", "2203800"}, + {"PI", "Floresta do Piau\u00ed", "2203859"}, + {"PI", "Floriano", "2203909"}, + {"PI", "Francin\u00f3polis", "2204006"}, + {"PI", "Francisco Ayres", "2204105"}, + {"PI", "Francisco Macedo", "2204154"}, + {"PI", "Francisco Santos", "2204204"}, + {"PI", "Fronteiras", "2204303"}, + {"PI", "Geminiano", "2204352"}, + {"PI", "Gilbu\u00e9s", "2204402"}, + {"PI", "Guadalupe", "2204501"}, + {"PI", "Guaribas", "2204550"}, + {"PI", "Hugo Napole\u00e3o", "2204600"}, + {"PI", "Ilha Grande", "2204659"}, + {"PI", "Inhuma", "2204709"}, + {"PI", "Ipiranga do Piau\u00ed", "2204808"}, + {"PI", "Isa\u00edas Coelho", "2204907"}, + {"PI", "Itain\u00f3polis", "2205003"}, + {"PI", "Itaueira", "2205102"}, + {"PI", "Jacobina do Piau\u00ed", "2205151"}, + {"PI", "Jaic\u00f3s", "2205201"}, + {"PI", "Jardim do Mulato", "2205250"}, + {"PI", "Jatob\u00e1 do Piau\u00ed", "2205276"}, + {"PI", "Jerumenha", "2205300"}, + {"PI", "Jo\u00e3o Costa", "2205359"}, + {"PI", "Joaquim Pires", "2205409"}, + {"PI", "Joca Marques", "2205458"}, + {"PI", "Jos\u00e9 de Freitas", "2205508"}, + {"PI", "Juazeiro do Piau\u00ed", "2205516"}, + {"PI", "J\u00falio Borges", "2205524"}, + {"PI", "Jurema", "2205532"}, + {"PI", "Lagoa Alegre", "2205557"}, + {"PI", "Lagoa de S\u00e3o Francisco", "2205573"}, + {"PI", "Lagoa do Barro do Piau\u00ed", "2205565"}, + {"PI", "Lagoa do Piau\u00ed", "2205581"}, + {"PI", "Lagoa do S\u00edtio", "2205599"}, + {"PI", "Lagoinha do Piau\u00ed", "2205540"}, + {"PI", "Landri Sales", "2205607"}, + {"PI", "Lu\u00eds Correia", "2205706"}, + {"PI", "Luzil\u00e2ndia", "2205805"}, + {"PI", "Madeiro", "2205854"}, + {"PI", "Manoel Em\u00eddio", "2205904"}, + {"PI", "Marcol\u00e2ndia", "2205953"}, + {"PI", "Marcos Parente", "2206001"}, + {"PI", "Massap\u00ea do Piau\u00ed", "2206050"}, + {"PI", "Matias Ol\u00edmpio", "2206100"}, + {"PI", "Miguel Alves", "2206209"}, + {"PI", "Miguel Le\u00e3o", "2206308"}, + {"PI", "Milton Brand\u00e3o", "2206357"}, + {"PI", "Monsenhor Gil", "2206407"}, + {"PI", "Monsenhor Hip\u00f3lito", "2206506"}, + {"PI", "Monte Alegre do Piau\u00ed", "2206605"}, + {"PI", "Morro Cabe\u00e7a no Tempo", "2206654"}, + {"PI", "Morro do Chap\u00e9u do Piau\u00ed", "2206670"}, + {"PI", "Murici dos Portelas", "2206696"}, + {"PI", "Nazar\u00e9 do Piau\u00ed", "2206704"}, + {"PI", "Naz\u00e1ria", "2206720"}, + {"PI", "Nossa Senhora de Nazar\u00e9", "2206753"}, + {"PI", "Nossa Senhora dos Rem\u00e9dios", "2206803"}, + {"PI", "Nova Santa Rita", "2207959"}, + {"PI", "Novo Oriente do Piau\u00ed", "2206902"}, + {"PI", "Novo Santo Ant\u00f4nio", "2206951"}, + {"PI", "Oeiras", "2207009"}, + {"PI", "Olho D'\u00c1gua do Piau\u00ed", "2207108"}, + {"PI", "Padre Marcos", "2207207"}, + {"PI", "Paes Landim", "2207306"}, + {"PI", "Paje\u00fa do Piau\u00ed", "2207355"}, + {"PI", "Palmeira do Piau\u00ed", "2207405"}, + {"PI", "Palmeirais", "2207504"}, + {"PI", "Paquet\u00e1", "2207553"}, + {"PI", "Parnagu\u00e1", "2207603"}, + {"PI", "Parna\u00edba", "2207702"}, + {"PI", "Passagem Franca do Piau\u00ed", "2207751"}, + {"PI", "Patos do Piau\u00ed", "2207777"}, + {"PI", "Pau D'Arco do Piau\u00ed", "2207793"}, + {"PI", "Paulistana", "2207801"}, + {"PI", "Pavussu", "2207850"}, + {"PI", "Pedro II", "2207900"}, + {"PI", "Pedro Laurentino", "2207934"}, + {"PI", "Picos", "2208007"}, + {"PI", "Pimenteiras", "2208106"}, + {"PI", "Pio IX", "2208205"}, + {"PI", "Piracuruca", "2208304"}, + {"PI", "Piripiri", "2208403"}, + {"PI", "Porto", "2208502"}, + {"PI", "Porto Alegre do Piau\u00ed", "2208551"}, + {"PI", "Prata do Piau\u00ed", "2208601"}, + {"PI", "Queimada Nova", "2208650"}, + {"PI", "Reden\u00e7\u00e3o do Gurgu\u00e9ia", "2208700"}, + {"PI", "Regenera\u00e7\u00e3o", "2208809"}, + {"PI", "Riacho Frio", "2208858"}, + {"PI", "Ribeira do Piau\u00ed", "2208874"}, + {"PI", "Ribeiro Gon\u00e7alves", "2208908"}, + {"PI", "Rio Grande do Piau\u00ed", "2209005"}, + {"PI", "Santa Cruz do Piau\u00ed", "2209104"}, + {"PI", "Santa Cruz dos Milagres", "2209153"}, + {"PI", "Santa Filomena", "2209203"}, + {"PI", "Santa Luz", "2209302"}, + {"PI", "Santa Rosa do Piau\u00ed", "2209377"}, + {"PI", "Santana do Piau\u00ed", "2209351"}, + {"PI", "Santo Ant\u00f4nio de Lisboa", "2209401"}, + {"PI", "Santo Ant\u00f4nio dos Milagres", "2209450"}, + {"PI", "Santo In\u00e1cio do Piau\u00ed", "2209500"}, + {"PI", "S\u00e3o Braz do Piau\u00ed", "2209559"}, + {"PI", "S\u00e3o F\u00e9lix do Piau\u00ed", "2209609"}, + {"PI", "S\u00e3o Francisco de Assis do Piau\u00ed", "2209658"}, + {"PI", "S\u00e3o Francisco do Piau\u00ed", "2209708"}, + {"PI", "S\u00e3o Gon\u00e7alo do Gurgu\u00e9ia", "2209757"}, + {"PI", "S\u00e3o Gon\u00e7alo do Piau\u00ed", "2209807"}, + {"PI", "S\u00e3o Jo\u00e3o da Canabrava", "2209856"}, + {"PI", "S\u00e3o Jo\u00e3o da Fronteira", "2209872"}, + {"PI", "S\u00e3o Jo\u00e3o da Serra", "2209906"}, + {"PI", "S\u00e3o Jo\u00e3o da Varjota", "2209955"}, + {"PI", "S\u00e3o Jo\u00e3o do Arraial", "2209971"}, + {"PI", "S\u00e3o Jo\u00e3o do Piau\u00ed", "2210003"}, + {"PI", "S\u00e3o Jos\u00e9 do Divino", "2210052"}, + {"PI", "S\u00e3o Jos\u00e9 do Peixe", "2210102"}, + {"PI", "S\u00e3o Jos\u00e9 do Piau\u00ed", "2210201"}, + {"PI", "S\u00e3o Juli\u00e3o", "2210300"}, + {"PI", "S\u00e3o Louren\u00e7o do Piau\u00ed", "2210359"}, + {"PI", "S\u00e3o Luis do Piau\u00ed", "2210375"}, + {"PI", "S\u00e3o Miguel da Baixa Grande", "2210383"}, + {"PI", "S\u00e3o Miguel do Fidalgo", "2210391"}, + {"PI", "S\u00e3o Miguel do Tapuio", "2210409"}, + {"PI", "S\u00e3o Pedro do Piau\u00ed", "2210508"}, + {"PI", "S\u00e3o Raimundo Nonato", "2210607"}, + {"PI", "Sebasti\u00e3o Barros", "2210623"}, + {"PI", "Sebasti\u00e3o Leal", "2210631"}, + {"PI", "Sigefredo Pacheco", "2210656"}, + {"PI", "Sim\u00f5es", "2210706"}, + {"PI", "Simpl\u00edcio Mendes", "2210805"}, + {"PI", "Socorro do Piau\u00ed", "2210904"}, + {"PI", "Sussuapara", "2210938"}, + {"PI", "Tamboril do Piau\u00ed", "2210953"}, + {"PI", "Tanque do Piau\u00ed", "2210979"}, + {"PI", "Teresina", "2211001"}, + {"PI", "Uni\u00e3o", "2211100"}, + {"PI", "Uru\u00e7u\u00ed", "2211209"}, + {"PI", "Valen\u00e7a do Piau\u00ed", "2211308"}, + {"PI", "V\u00e1rzea Branca", "2211357"}, + {"PI", "V\u00e1rzea Grande", "2211407"}, + {"PI", "Vera Mendes", "2211506"}, + {"PI", "Vila Nova do Piau\u00ed", "2211605"}, + {"PI", "Wall Ferraz", "2211704"}, + {"RJ", "Angra dos Reis", "3300100"}, + {"RJ", "Aperib\u00e9", "3300159"}, + {"RJ", "Araruama", "3300209"}, + {"RJ", "Areal", "3300225"}, + {"RJ", "Arma\u00e7\u00e3o dos B\u00fazios", "3300233"}, + {"RJ", "Arraial do Cabo", "3300258"}, + {"RJ", "Barra do Pira\u00ed", "3300308"}, + {"RJ", "Barra Mansa", "3300407"}, + {"RJ", "Belford Roxo", "3300456"}, + {"RJ", "Bom Jardim", "3300506"}, + {"RJ", "Bom Jesus do Itabapoana", "3300605"}, + {"RJ", "Cabo Frio", "3300704"}, + {"RJ", "Cachoeiras de Macacu", "3300803"}, + {"RJ", "Cambuci", "3300902"}, + {"RJ", "Campos dos Goytacazes", "3301009"}, + {"RJ", "Cantagalo", "3301108"}, + {"RJ", "Carapebus", "3300936"}, + {"RJ", "Cardoso Moreira", "3301157"}, + {"RJ", "Carmo", "3301207"}, + {"RJ", "Casimiro de Abreu", "3301306"}, + {"RJ", "Comendador Levy Gasparian", "3300951"}, + {"RJ", "Concei\u00e7\u00e3o de Macabu", "3301405"}, + {"RJ", "Cordeiro", "3301504"}, + {"RJ", "Duas Barras", "3301603"}, + {"RJ", "Duque de Caxias", "3301702"}, + {"RJ", "Engenheiro Paulo de Frontin", "3301801"}, + {"RJ", "Guapimirim", "3301850"}, + {"RJ", "Iguaba Grande", "3301876"}, + {"RJ", "Itabora\u00ed", "3301900"}, + {"RJ", "Itagua\u00ed", "3302007"}, + {"RJ", "Italva", "3302056"}, + {"RJ", "Itaocara", "3302106"}, + {"RJ", "Itaperuna", "3302205"}, + {"RJ", "Itatiaia", "3302254"}, + {"RJ", "Japeri", "3302270"}, + {"RJ", "Laje do Muria\u00e9", "3302304"}, + {"RJ", "Maca\u00e9", "3302403"}, + {"RJ", "Macuco", "3302452"}, + {"RJ", "Mag\u00e9", "3302502"}, + {"RJ", "Mangaratiba", "3302601"}, + {"RJ", "Maric\u00e1", "3302700"}, + {"RJ", "Mendes", "3302809"}, + {"RJ", "Mesquita", "3302858"}, + {"RJ", "Miguel Pereira", "3302908"}, + {"RJ", "Miracema", "3303005"}, + {"RJ", "Natividade", "3303104"}, + {"RJ", "Nil\u00f3polis", "3303203"}, + {"RJ", "Niter\u00f3i", "3303302"}, + {"RJ", "Nova Friburgo", "3303401"}, + {"RJ", "Nova Igua\u00e7u", "3303500"}, + {"RJ", "Paracambi", "3303609"}, + {"RJ", "Para\u00edba do Sul", "3303708"}, + {"RJ", "Paraty", "3303807"}, + {"RJ", "Paty do Alferes", "3303856"}, + {"RJ", "Petr\u00f3polis", "3303906"}, + {"RJ", "Pinheiral", "3303955"}, + {"RJ", "Pira\u00ed", "3304003"}, + {"RJ", "Porci\u00fancula", "3304102"}, + {"RJ", "Porto Real", "3304110"}, + {"RJ", "Quatis", "3304128"}, + {"RJ", "Queimados", "3304144"}, + {"RJ", "Quissam\u00e3", "3304151"}, + {"RJ", "Resende", "3304201"}, + {"RJ", "Rio Bonito", "3304300"}, + {"RJ", "Rio Claro", "3304409"}, + {"RJ", "Rio das Flores", "3304508"}, + {"RJ", "Rio das Ostras", "3304524"}, + {"RJ", "Rio de Janeiro", "3304557"}, + {"RJ", "Santa Maria Madalena", "3304607"}, + {"RJ", "Santo Ant\u00f4nio de P\u00e1dua", "3304706"}, + {"RJ", "S\u00e3o Fid\u00e9lis", "3304805"}, + {"RJ", "S\u00e3o Francisco de Itabapoana", "3304755"}, + {"RJ", "S\u00e3o Gon\u00e7alo", "3304904"}, + {"RJ", "S\u00e3o Jo\u00e3o da Barra", "3305000"}, + {"RJ", "S\u00e3o Jo\u00e3o de Meriti", "3305109"}, + {"RJ", "S\u00e3o Jos\u00e9 de Ub\u00e1", "3305133"}, + {"RJ", "S\u00e3o Jos\u00e9 do Vale do Rio Preto", "3305158"}, + {"RJ", "S\u00e3o Pedro da Aldeia", "3305208"}, + {"RJ", "S\u00e3o Sebasti\u00e3o do Alto", "3305307"}, + {"RJ", "Sapucaia", "3305406"}, + {"RJ", "Saquarema", "3305505"}, + {"RJ", "Serop\u00e9dica", "3305554"}, + {"RJ", "Silva Jardim", "3305604"}, + {"RJ", "Sumidouro", "3305703"}, + {"RJ", "Tangu\u00e1", "3305752"}, + {"RJ", "Teres\u00f3polis", "3305802"}, + {"RJ", "Trajano de Moraes", "3305901"}, + {"RJ", "Tr\u00eas Rios", "3306008"}, + {"RJ", "Valen\u00e7a", "3306107"}, + {"RJ", "Varre-Sai", "3306156"}, + {"RJ", "Vassouras", "3306206"}, + {"RJ", "Volta Redonda", "3306305"}, + {"RN", "Acari", "2400109"}, + {"RN", "Afonso Bezerra", "2400307"}, + {"RN", "\u00c1gua Nova", "2400406"}, + {"RN", "Alexandria", "2400505"}, + {"RN", "Almino Afonso", "2400604"}, + {"RN", "Alto do Rodrigues", "2400703"}, + {"RN", "Angicos", "2400802"}, + {"RN", "Ant\u00f4nio Martins", "2400901"}, + {"RN", "Apodi", "2401008"}, + {"RN", "Areia Branca", "2401107"}, + {"RN", "Arez", "2401206"}, + {"RN", "Ass\u00fa", "2400208"}, + {"RN", "Ba\u00eda Formosa", "2401404"}, + {"RN", "Bara\u00fana", "2401453"}, + {"RN", "Barcelona", "2401503"}, + {"RN", "Bento Fernandes", "2401602"}, + {"RN", "Bod\u00f3", "2401651"}, + {"RN", "Bom Jesus", "2401701"}, + {"RN", "Brejinho", "2401800"}, + {"RN", "Cai\u00e7ara do Norte", "2401859"}, + {"RN", "Cai\u00e7ara do Rio do Vento", "2401909"}, + {"RN", "Caic\u00f3", "2402006"}, + {"RN", "Campo Grande", "2401305"}, + {"RN", "Campo Redondo", "2402105"}, + {"RN", "Canguaretama", "2402204"}, + {"RN", "Cara\u00fabas", "2402303"}, + {"RN", "Carna\u00faba dos Dantas", "2402402"}, + {"RN", "Carnaubais", "2402501"}, + {"RN", "Cear\u00e1-Mirim", "2402600"}, + {"RN", "Cerro Cor\u00e1", "2402709"}, + {"RN", "Coronel Ezequiel", "2402808"}, + {"RN", "Coronel Jo\u00e3o Pessoa", "2402907"}, + {"RN", "Cruzeta", "2403004"}, + {"RN", "Currais Novos", "2403103"}, + {"RN", "Doutor Severiano", "2403202"}, + {"RN", "Encanto", "2403301"}, + {"RN", "Equador", "2403400"}, + {"RN", "Esp\u00edrito Santo", "2403509"}, + {"RN", "Extremoz", "2403608"}, + {"RN", "Felipe Guerra", "2403707"}, + {"RN", "Fernando Pedroza", "2403756"}, + {"RN", "Flor\u00e2nia", "2403806"}, + {"RN", "Francisco Dantas", "2403905"}, + {"RN", "Frutuoso Gomes", "2404002"}, + {"RN", "Galinhos", "2404101"}, + {"RN", "Goianinha", "2404200"}, + {"RN", "Governador Dix-Sept Rosado", "2404309"}, + {"RN", "Grossos", "2404408"}, + {"RN", "Guamar\u00e9", "2404507"}, + {"RN", "Ielmo Marinho", "2404606"}, + {"RN", "Ipangua\u00e7u", "2404705"}, + {"RN", "Ipueira", "2404804"}, + {"RN", "Itaj\u00e1", "2404853"}, + {"RN", "Ita\u00fa", "2404903"}, + {"RN", "Ja\u00e7an\u00e3", "2405009"}, + {"RN", "Janda\u00edra", "2405108"}, + {"RN", "Jandu\u00eds", "2405207"}, + {"RN", "Janu\u00e1rio Cicco", "2405306"}, + {"RN", "Japi", "2405405"}, + {"RN", "Jardim de Angicos", "2405504"}, + {"RN", "Jardim de Piranhas", "2405603"}, + {"RN", "Jardim do Serid\u00f3", "2405702"}, + {"RN", "Jo\u00e3o C\u00e2mara", "2405801"}, + {"RN", "Jo\u00e3o Dias", "2405900"}, + {"RN", "Jos\u00e9 da Penha", "2406007"}, + {"RN", "Jucurutu", "2406106"}, + {"RN", "Jundi\u00e1", "2406155"}, + {"RN", "Lagoa d'Anta", "2406205"}, + {"RN", "Lagoa de Pedras", "2406304"}, + {"RN", "Lagoa de Velhos", "2406403"}, + {"RN", "Lagoa Nova", "2406502"}, + {"RN", "Lagoa Salgada", "2406601"}, + {"RN", "Lajes", "2406700"}, + {"RN", "Lajes Pintadas", "2406809"}, + {"RN", "Lucr\u00e9cia", "2406908"}, + {"RN", "Lu\u00eds Gomes", "2407005"}, + {"RN", "Maca\u00edba", "2407104"}, + {"RN", "Macau", "2407203"}, + {"RN", "Major Sales", "2407252"}, + {"RN", "Marcelino Vieira", "2407302"}, + {"RN", "Martins", "2407401"}, + {"RN", "Maxaranguape", "2407500"}, + {"RN", "Messias Targino", "2407609"}, + {"RN", "Montanhas", "2407708"}, + {"RN", "Monte Alegre", "2407807"}, + {"RN", "Monte das Gameleiras", "2407906"}, + {"RN", "Mossor\u00f3", "2408003"}, + {"RN", "Natal", "2408102"}, + {"RN", "N\u00edsia Floresta", "2408201"}, + {"RN", "Nova Cruz", "2408300"}, + {"RN", "Olho d'\u00c1gua do Borges", "2408409"}, + {"RN", "Ouro Branco", "2408508"}, + {"RN", "Paran\u00e1", "2408607"}, + {"RN", "Para\u00fa", "2408706"}, + {"RN", "Parazinho", "2408805"}, + {"RN", "Parelhas", "2408904"}, + {"RN", "Parnamirim", "2403251"}, + {"RN", "Passa e Fica", "2409100"}, + {"RN", "Passagem", "2409209"}, + {"RN", "Patu", "2409308"}, + {"RN", "Pau dos Ferros", "2409407"}, + {"RN", "Pedra Grande", "2409506"}, + {"RN", "Pedra Preta", "2409605"}, + {"RN", "Pedro Avelino", "2409704"}, + {"RN", "Pedro Velho", "2409803"}, + {"RN", "Pend\u00eancias", "2409902"}, + {"RN", "Pil\u00f5es", "2410009"}, + {"RN", "Po\u00e7o Branco", "2410108"}, + {"RN", "Portalegre", "2410207"}, + {"RN", "Porto do Mangue", "2410256"}, + {"RN", "Pureza", "2410405"}, + {"RN", "Rafael Fernandes", "2410504"}, + {"RN", "Rafael Godeiro", "2410603"}, + {"RN", "Riacho da Cruz", "2410702"}, + {"RN", "Riacho de Santana", "2410801"}, + {"RN", "Riachuelo", "2410900"}, + {"RN", "Rio do Fogo", "2408953"}, + {"RN", "Rodolfo Fernandes", "2411007"}, + {"RN", "Ruy Barbosa", "2411106"}, + {"RN", "Santa Cruz", "2411205"}, + {"RN", "Santa Maria", "2409332"}, + {"RN", "Santana do Matos", "2411403"}, + {"RN", "Santana do Serid\u00f3", "2411429"}, + {"RN", "Santo Ant\u00f4nio", "2411502"}, + {"RN", "S\u00e3o Bento do Norte", "2411601"}, + {"RN", "S\u00e3o Bento do Trair\u00ed", "2411700"}, + {"RN", "S\u00e3o Fernando", "2411809"}, + {"RN", "S\u00e3o Francisco do Oeste", "2411908"}, + {"RN", "S\u00e3o Gon\u00e7alo do Amarante", "2412005"}, + {"RN", "S\u00e3o Jo\u00e3o do Sabugi", "2412104"}, + {"RN", "S\u00e3o Jos\u00e9 de Mipibu", "2412203"}, + {"RN", "S\u00e3o Jos\u00e9 do Campestre", "2412302"}, + {"RN", "S\u00e3o Jos\u00e9 do Serid\u00f3", "2412401"}, + {"RN", "S\u00e3o Miguel", "2412500"}, + {"RN", "S\u00e3o Miguel do Gostoso", "2412559"}, + {"RN", "S\u00e3o Paulo do Potengi", "2412609"}, + {"RN", "S\u00e3o Pedro", "2412708"}, + {"RN", "S\u00e3o Rafael", "2412807"}, + {"RN", "S\u00e3o Tom\u00e9", "2412906"}, + {"RN", "S\u00e3o Vicente", "2413003"}, + {"RN", "Senador El\u00f3i de Souza", "2413102"}, + {"RN", "Senador Georgino Avelino", "2413201"}, + {"RN", "Serra Caiada", "2410306"}, + {"RN", "Serra de S\u00e3o Bento", "2413300"}, + {"RN", "Serra do Mel", "2413359"}, + {"RN", "Serra Negra do Norte", "2413409"}, + {"RN", "Serrinha", "2413508"}, + {"RN", "Serrinha dos Pintos", "2413557"}, + {"RN", "Severiano Melo", "2413607"}, + {"RN", "S\u00edtio Novo", "2413706"}, + {"RN", "Taboleiro Grande", "2413805"}, + {"RN", "Taipu", "2413904"}, + {"RN", "Tangar\u00e1", "2414001"}, + {"RN", "Tenente Ananias", "2414100"}, + {"RN", "Tenente Laurentino Cruz", "2414159"}, + {"RN", "Tibau", "2411056"}, + {"RN", "Tibau do Sul", "2414209"}, + {"RN", "Timba\u00faba dos Batistas", "2414308"}, + {"RN", "Touros", "2414407"}, + {"RN", "Triunfo Potiguar", "2414456"}, + {"RN", "Umarizal", "2414506"}, + {"RN", "Upanema", "2414605"}, + {"RN", "V\u00e1rzea", "2414704"}, + {"RN", "Venha-Ver", "2414753"}, + {"RN", "Vera Cruz", "2414803"}, + {"RN", "Vi\u00e7osa", "2414902"}, + {"RN", "Vila Flor", "2415008"}, + {"RS", "Acegu\u00e1", "4300034"}, + {"RS", "\u00c1gua Santa", "4300059"}, + {"RS", "Agudo", "4300109"}, + {"RS", "Ajuricaba", "4300208"}, + {"RS", "Alecrim", "4300307"}, + {"RS", "Alegrete", "4300406"}, + {"RS", "Alegria", "4300455"}, + {"RS", "Almirante Tamandar\u00e9 do Sul", "4300471"}, + {"RS", "Alpestre", "4300505"}, + {"RS", "Alto Alegre", "4300554"}, + {"RS", "Alto Feliz", "4300570"}, + {"RS", "Alvorada", "4300604"}, + {"RS", "Amaral Ferrador", "4300638"}, + {"RS", "Ametista do Sul", "4300646"}, + {"RS", "Andr\u00e9 da Rocha", "4300661"}, + {"RS", "Anta Gorda", "4300703"}, + {"RS", "Ant\u00f4nio Prado", "4300802"}, + {"RS", "Arambar\u00e9", "4300851"}, + {"RS", "Araric\u00e1", "4300877"}, + {"RS", "Aratiba", "4300901"}, + {"RS", "Arroio do Meio", "4301008"}, + {"RS", "Arroio do Padre", "4301073"}, + {"RS", "Arroio do Sal", "4301057"}, + {"RS", "Arroio do Tigre", "4301206"}, + {"RS", "Arroio dos Ratos", "4301107"}, + {"RS", "Arroio Grande", "4301305"}, + {"RS", "Arvorezinha", "4301404"}, + {"RS", "Augusto Pestana", "4301503"}, + {"RS", "\u00c1urea", "4301552"}, + {"RS", "Bag\u00e9", "4301602"}, + {"RS", "Balne\u00e1rio Pinhal", "4301636"}, + {"RS", "Bar\u00e3o", "4301651"}, + {"RS", "Bar\u00e3o de Cotegipe", "4301701"}, + {"RS", "Bar\u00e3o do Triunfo", "4301750"}, + {"RS", "Barra do Guarita", "4301859"}, + {"RS", "Barra do Quara\u00ed", "4301875"}, + {"RS", "Barra do Ribeiro", "4301909"}, + {"RS", "Barra do Rio Azul", "4301925"}, + {"RS", "Barra Funda", "4301958"}, + {"RS", "Barrac\u00e3o", "4301800"}, + {"RS", "Barros Cassal", "4302006"}, + {"RS", "Benjamin Constant do Sul", "4302055"}, + {"RS", "Bento Gon\u00e7alves", "4302105"}, + {"RS", "Boa Vista das Miss\u00f5es", "4302154"}, + {"RS", "Boa Vista do Buric\u00e1", "4302204"}, + {"RS", "Boa Vista do Cadeado", "4302220"}, + {"RS", "Boa Vista do Incra", "4302238"}, + {"RS", "Boa Vista do Sul", "4302253"}, + {"RS", "Bom Jesus", "4302303"}, + {"RS", "Bom Princ\u00edpio", "4302352"}, + {"RS", "Bom Progresso", "4302378"}, + {"RS", "Bom Retiro do Sul", "4302402"}, + {"RS", "Boqueir\u00e3o do Le\u00e3o", "4302451"}, + {"RS", "Bossoroca", "4302501"}, + {"RS", "Bozano", "4302584"}, + {"RS", "Braga", "4302600"}, + {"RS", "Brochier", "4302659"}, + {"RS", "Buti\u00e1", "4302709"}, + {"RS", "Ca\u00e7apava do Sul", "4302808"}, + {"RS", "Cacequi", "4302907"}, + {"RS", "Cachoeira do Sul", "4303004"}, + {"RS", "Cachoeirinha", "4303103"}, + {"RS", "Cacique Doble", "4303202"}, + {"RS", "Caibat\u00e9", "4303301"}, + {"RS", "Cai\u00e7ara", "4303400"}, + {"RS", "Camaqu\u00e3", "4303509"}, + {"RS", "Camargo", "4303558"}, + {"RS", "Cambar\u00e1 do Sul", "4303608"}, + {"RS", "Campestre da Serra", "4303673"}, + {"RS", "Campina das Miss\u00f5es", "4303707"}, + {"RS", "Campinas do Sul", "4303806"}, + {"RS", "Campo Bom", "4303905"}, + {"RS", "Campo Novo", "4304002"}, + {"RS", "Campos Borges", "4304101"}, + {"RS", "Candel\u00e1ria", "4304200"}, + {"RS", "C\u00e2ndido God\u00f3i", "4304309"}, + {"RS", "Candiota", "4304358"}, + {"RS", "Canela", "4304408"}, + {"RS", "Cangu\u00e7u", "4304507"}, + {"RS", "Canoas", "4304606"}, + {"RS", "Canudos do Vale", "4304614"}, + {"RS", "Cap\u00e3o Bonito do Sul", "4304622"}, + {"RS", "Cap\u00e3o da Canoa", "4304630"}, + {"RS", "Cap\u00e3o do Cip\u00f3", "4304655"}, + {"RS", "Cap\u00e3o do Le\u00e3o", "4304663"}, + {"RS", "Capela de Santana", "4304689"}, + {"RS", "Capit\u00e3o", "4304697"}, + {"RS", "Capivari do Sul", "4304671"}, + {"RS", "Cara\u00e1", "4304713"}, + {"RS", "Carazinho", "4304705"}, + {"RS", "Carlos Barbosa", "4304804"}, + {"RS", "Carlos Gomes", "4304853"}, + {"RS", "Casca", "4304903"}, + {"RS", "Caseiros", "4304952"}, + {"RS", "Catu\u00edpe", "4305009"}, + {"RS", "Caxias do Sul", "4305108"}, + {"RS", "Centen\u00e1rio", "4305116"}, + {"RS", "Cerrito", "4305124"}, + {"RS", "Cerro Branco", "4305132"}, + {"RS", "Cerro Grande", "4305157"}, + {"RS", "Cerro Grande do Sul", "4305173"}, + {"RS", "Cerro Largo", "4305207"}, + {"RS", "Chapada", "4305306"}, + {"RS", "Charqueadas", "4305355"}, + {"RS", "Charrua", "4305371"}, + {"RS", "Chiapetta", "4305405"}, + {"RS", "Chu\u00ed", "4305439"}, + {"RS", "Chuvisca", "4305447"}, + {"RS", "Cidreira", "4305454"}, + {"RS", "Cir\u00edaco", "4305504"}, + {"RS", "Colinas", "4305587"}, + {"RS", "Colorado", "4305603"}, + {"RS", "Condor", "4305702"}, + {"RS", "Constantina", "4305801"}, + {"RS", "Coqueiro Baixo", "4305835"}, + {"RS", "Coqueiros do Sul", "4305850"}, + {"RS", "Coronel Barros", "4305871"}, + {"RS", "Coronel Bicaco", "4305900"}, + {"RS", "Coronel Pilar", "4305934"}, + {"RS", "Cotipor\u00e3", "4305959"}, + {"RS", "Coxilha", "4305975"}, + {"RS", "Crissiumal", "4306007"}, + {"RS", "Cristal", "4306056"}, + {"RS", "Cristal do Sul", "4306072"}, + {"RS", "Cruz Alta", "4306106"}, + {"RS", "Cruzaltense", "4306130"}, + {"RS", "Cruzeiro do Sul", "4306205"}, + {"RS", "David Canabarro", "4306304"}, + {"RS", "Derrubadas", "4306320"}, + {"RS", "Dezesseis de Novembro", "4306353"}, + {"RS", "Dilermando de Aguiar", "4306379"}, + {"RS", "Dois Irm\u00e3os", "4306403"}, + {"RS", "Dois Irm\u00e3os das Miss\u00f5es", "4306429"}, + {"RS", "Dois Lajeados", "4306452"}, + {"RS", "Dom Feliciano", "4306502"}, + {"RS", "Dom Pedrito", "4306601"}, + {"RS", "Dom Pedro de Alc\u00e2ntara", "4306551"}, + {"RS", "Dona Francisca", "4306700"}, + {"RS", "Doutor Maur\u00edcio Cardoso", "4306734"}, + {"RS", "Doutor Ricardo", "4306759"}, + {"RS", "Eldorado do Sul", "4306767"}, + {"RS", "Encantado", "4306809"}, + {"RS", "Encruzilhada do Sul", "4306908"}, + {"RS", "Engenho Velho", "4306924"}, + {"RS", "Entre Rios do Sul", "4306957"}, + {"RS", "Entre-Iju\u00eds", "4306932"}, + {"RS", "Erebango", "4306973"}, + {"RS", "Erechim", "4307005"}, + {"RS", "Ernestina", "4307054"}, + {"RS", "Erval Grande", "4307203"}, + {"RS", "Erval Seco", "4307302"}, + {"RS", "Esmeralda", "4307401"}, + {"RS", "Esperan\u00e7a do Sul", "4307450"}, + {"RS", "Espumoso", "4307500"}, + {"RS", "Esta\u00e7\u00e3o", "4307559"}, + {"RS", "Est\u00e2ncia Velha", "4307609"}, + {"RS", "Esteio", "4307708"}, + {"RS", "Estrela", "4307807"}, + {"RS", "Estrela Velha", "4307815"}, + {"RS", "Eug\u00eanio de Castro", "4307831"}, + {"RS", "Fagundes Varela", "4307864"}, + {"RS", "Farroupilha", "4307906"}, + {"RS", "Faxinal do Soturno", "4308003"}, + {"RS", "Faxinalzinho", "4308052"}, + {"RS", "Fazenda Vilanova", "4308078"}, + {"RS", "Feliz", "4308102"}, + {"RS", "Flores da Cunha", "4308201"}, + {"RS", "Floriano Peixoto", "4308250"}, + {"RS", "Fontoura Xavier", "4308300"}, + {"RS", "Formigueiro", "4308409"}, + {"RS", "Forquetinha", "4308433"}, + {"RS", "Fortaleza dos Valos", "4308458"}, + {"RS", "Frederico Westphalen", "4308508"}, + {"RS", "Garibaldi", "4308607"}, + {"RS", "Garruchos", "4308656"}, + {"RS", "Gaurama", "4308706"}, + {"RS", "General C\u00e2mara", "4308805"}, + {"RS", "Gentil", "4308854"}, + {"RS", "Get\u00falio Vargas", "4308904"}, + {"RS", "Giru\u00e1", "4309001"}, + {"RS", "Glorinha", "4309050"}, + {"RS", "Gramado", "4309100"}, + {"RS", "Gramado dos Loureiros", "4309126"}, + {"RS", "Gramado Xavier", "4309159"}, + {"RS", "Gravata\u00ed", "4309209"}, + {"RS", "Guabiju", "4309258"}, + {"RS", "Gua\u00edba", "4309308"}, + {"RS", "Guapor\u00e9", "4309407"}, + {"RS", "Guarani das Miss\u00f5es", "4309506"}, + {"RS", "Harmonia", "4309555"}, + {"RS", "Herval", "4307104"}, + {"RS", "Herveiras", "4309571"}, + {"RS", "Horizontina", "4309605"}, + {"RS", "Hulha Negra", "4309654"}, + {"RS", "Humait\u00e1", "4309704"}, + {"RS", "Ibarama", "4309753"}, + {"RS", "Ibia\u00e7\u00e1", "4309803"}, + {"RS", "Ibiraiaras", "4309902"}, + {"RS", "Ibirapuit\u00e3", "4309951"}, + {"RS", "Ibirub\u00e1", "4310009"}, + {"RS", "Igrejinha", "4310108"}, + {"RS", "Iju\u00ed", "4310207"}, + {"RS", "Il\u00f3polis", "4310306"}, + {"RS", "Imb\u00e9", "4310330"}, + {"RS", "Imigrante", "4310363"}, + {"RS", "Independ\u00eancia", "4310405"}, + {"RS", "Inhacor\u00e1", "4310413"}, + {"RS", "Ip\u00ea", "4310439"}, + {"RS", "Ipiranga do Sul", "4310462"}, + {"RS", "Ira\u00ed", "4310504"}, + {"RS", "Itaara", "4310538"}, + {"RS", "Itacurubi", "4310553"}, + {"RS", "Itapuca", "4310579"}, + {"RS", "Itaqui", "4310603"}, + {"RS", "Itati", "4310652"}, + {"RS", "Itatiba do Sul", "4310702"}, + {"RS", "Ivor\u00e1", "4310751"}, + {"RS", "Ivoti", "4310801"}, + {"RS", "Jaboticaba", "4310850"}, + {"RS", "Jacuizinho", "4310876"}, + {"RS", "Jacutinga", "4310900"}, + {"RS", "Jaguar\u00e3o", "4311007"}, + {"RS", "Jaguari", "4311106"}, + {"RS", "Jaquirana", "4311122"}, + {"RS", "Jari", "4311130"}, + {"RS", "J\u00f3ia", "4311155"}, + {"RS", "J\u00falio de Castilhos", "4311205"}, + {"RS", "Lagoa Bonita do Sul", "4311239"}, + {"RS", "Lagoa dos Tr\u00eas Cantos", "4311270"}, + {"RS", "Lagoa Vermelha", "4311304"}, + {"RS", "Lago\u00e3o", "4311254"}, + {"RS", "Lajeado", "4311403"}, + {"RS", "Lajeado do Bugre", "4311429"}, + {"RS", "Lavras do Sul", "4311502"}, + {"RS", "Liberato Salzano", "4311601"}, + {"RS", "Lindolfo Collor", "4311627"}, + {"RS", "Linha Nova", "4311643"}, + {"RS", "Ma\u00e7ambar\u00e1", "4311718"}, + {"RS", "Machadinho", "4311700"}, + {"RS", "Mampituba", "4311734"}, + {"RS", "Manoel Viana", "4311759"}, + {"RS", "Maquin\u00e9", "4311775"}, + {"RS", "Marat\u00e1", "4311791"}, + {"RS", "Marau", "4311809"}, + {"RS", "Marcelino Ramos", "4311908"}, + {"RS", "Mariana Pimentel", "4311981"}, + {"RS", "Mariano Moro", "4312005"}, + {"RS", "Marques de Souza", "4312054"}, + {"RS", "Mata", "4312104"}, + {"RS", "Mato Castelhano", "4312138"}, + {"RS", "Mato Leit\u00e3o", "4312153"}, + {"RS", "Mato Queimado", "4312179"}, + {"RS", "Maximiliano de Almeida", "4312203"}, + {"RS", "Minas do Le\u00e3o", "4312252"}, + {"RS", "Miragua\u00ed", "4312302"}, + {"RS", "Montauri", "4312351"}, + {"RS", "Monte Alegre dos Campos", "4312377"}, + {"RS", "Monte Belo do Sul", "4312385"}, + {"RS", "Montenegro", "4312401"}, + {"RS", "Morma\u00e7o", "4312427"}, + {"RS", "Morrinhos do Sul", "4312443"}, + {"RS", "Morro Redondo", "4312450"}, + {"RS", "Morro Reuter", "4312476"}, + {"RS", "Mostardas", "4312500"}, + {"RS", "Mu\u00e7um", "4312609"}, + {"RS", "Muitos Cap\u00f5es", "4312617"}, + {"RS", "Muliterno", "4312625"}, + {"RS", "N\u00e3o-Me-Toque", "4312658"}, + {"RS", "Nicolau Vergueiro", "4312674"}, + {"RS", "Nonoai", "4312708"}, + {"RS", "Nova Alvorada", "4312757"}, + {"RS", "Nova Ara\u00e7\u00e1", "4312807"}, + {"RS", "Nova Bassano", "4312906"}, + {"RS", "Nova Boa Vista", "4312955"}, + {"RS", "Nova Br\u00e9scia", "4313003"}, + {"RS", "Nova Candel\u00e1ria", "4313011"}, + {"RS", "Nova Esperan\u00e7a do Sul", "4313037"}, + {"RS", "Nova Hartz", "4313060"}, + {"RS", "Nova P\u00e1dua", "4313086"}, + {"RS", "Nova Palma", "4313102"}, + {"RS", "Nova Petr\u00f3polis", "4313201"}, + {"RS", "Nova Prata", "4313300"}, + {"RS", "Nova Ramada", "4313334"}, + {"RS", "Nova Roma do Sul", "4313359"}, + {"RS", "Nova Santa Rita", "4313375"}, + {"RS", "Novo Barreiro", "4313490"}, + {"RS", "Novo Cabrais", "4313391"}, + {"RS", "Novo Hamburgo", "4313409"}, + {"RS", "Novo Machado", "4313425"}, + {"RS", "Novo Tiradentes", "4313441"}, + {"RS", "Novo Xingu", "4313466"}, + {"RS", "Os\u00f3rio", "4313508"}, + {"RS", "Paim Filho", "4313607"}, + {"RS", "Palmares do Sul", "4313656"}, + {"RS", "Palmeira das Miss\u00f5es", "4313706"}, + {"RS", "Palmitinho", "4313805"}, + {"RS", "Panambi", "4313904"}, + {"RS", "Pantano Grande", "4313953"}, + {"RS", "Para\u00ed", "4314001"}, + {"RS", "Para\u00edso do Sul", "4314027"}, + {"RS", "Pareci Novo", "4314035"}, + {"RS", "Parob\u00e9", "4314050"}, + {"RS", "Passa Sete", "4314068"}, + {"RS", "Passo do Sobrado", "4314076"}, + {"RS", "Passo Fundo", "4314100"}, + {"RS", "Paulo Bento", "4314134"}, + {"RS", "Paverama", "4314159"}, + {"RS", "Pedras Altas", "4314175"}, + {"RS", "Pedro Os\u00f3rio", "4314209"}, + {"RS", "Peju\u00e7ara", "4314308"}, + {"RS", "Pelotas", "4314407"}, + {"RS", "Picada Caf\u00e9", "4314423"}, + {"RS", "Pinhal", "4314456"}, + {"RS", "Pinhal da Serra", "4314464"}, + {"RS", "Pinhal Grande", "4314472"}, + {"RS", "Pinheirinho do Vale", "4314498"}, + {"RS", "Pinheiro Machado", "4314506"}, + {"RS", "Pinto Bandeira", "4314548"}, + {"RS", "Pirap\u00f3", "4314555"}, + {"RS", "Piratini", "4314605"}, + {"RS", "Planalto", "4314704"}, + {"RS", "Po\u00e7o das Antas", "4314753"}, + {"RS", "Pont\u00e3o", "4314779"}, + {"RS", "Ponte Preta", "4314787"}, + {"RS", "Port\u00e3o", "4314803"}, + {"RS", "Porto Alegre", "4314902"}, + {"RS", "Porto Lucena", "4315008"}, + {"RS", "Porto Mau\u00e1", "4315057"}, + {"RS", "Porto Vera Cruz", "4315073"}, + {"RS", "Porto Xavier", "4315107"}, + {"RS", "Pouso Novo", "4315131"}, + {"RS", "Presidente Lucena", "4315149"}, + {"RS", "Progresso", "4315156"}, + {"RS", "Prot\u00e1sio Alves", "4315172"}, + {"RS", "Putinga", "4315206"}, + {"RS", "Quara\u00ed", "4315305"}, + {"RS", "Quatro Irm\u00e3os", "4315313"}, + {"RS", "Quevedos", "4315321"}, + {"RS", "Quinze de Novembro", "4315354"}, + {"RS", "Redentora", "4315404"}, + {"RS", "Relvado", "4315453"}, + {"RS", "Restinga S\u00eaca", "4315503"}, + {"RS", "Rio dos \u00cdndios", "4315552"}, + {"RS", "Rio Grande", "4315602"}, + {"RS", "Rio Pardo", "4315701"}, + {"RS", "Riozinho", "4315750"}, + {"RS", "Roca Sales", "4315800"}, + {"RS", "Rodeio Bonito", "4315909"}, + {"RS", "Rolador", "4315958"}, + {"RS", "Rolante", "4316006"}, + {"RS", "Ronda Alta", "4316105"}, + {"RS", "Rondinha", "4316204"}, + {"RS", "Roque Gonzales", "4316303"}, + {"RS", "Ros\u00e1rio do Sul", "4316402"}, + {"RS", "Sagrada Fam\u00edlia", "4316428"}, + {"RS", "Saldanha Marinho", "4316436"}, + {"RS", "Salto do Jacu\u00ed", "4316451"}, + {"RS", "Salvador das Miss\u00f5es", "4316477"}, + {"RS", "Salvador do Sul", "4316501"}, + {"RS", "Sananduva", "4316600"}, + {"RS", "Sant'Ana do Livramento", "4317103"}, + {"RS", "Santa B\u00e1rbara do Sul", "4316709"}, + {"RS", "Santa Cec\u00edlia do Sul", "4316733"}, + {"RS", "Santa Clara do Sul", "4316758"}, + {"RS", "Santa Cruz do Sul", "4316808"}, + {"RS", "Santa Margarida do Sul", "4316972"}, + {"RS", "Santa Maria", "4316907"}, + {"RS", "Santa Maria do Herval", "4316956"}, + {"RS", "Santa Rosa", "4317202"}, + {"RS", "Santa Tereza", "4317251"}, + {"RS", "Santa Vit\u00f3ria do Palmar", "4317301"}, + {"RS", "Santana da Boa Vista", "4317004"}, + {"RS", "Santiago", "4317400"}, + {"RS", "Santo \u00c2ngelo", "4317509"}, + {"RS", "Santo Ant\u00f4nio da Patrulha", "4317608"}, + {"RS", "Santo Ant\u00f4nio das Miss\u00f5es", "4317707"}, + {"RS", "Santo Ant\u00f4nio do Palma", "4317558"}, + {"RS", "Santo Ant\u00f4nio do Planalto", "4317756"}, + {"RS", "Santo Augusto", "4317806"}, + {"RS", "Santo Cristo", "4317905"}, + {"RS", "Santo Expedito do Sul", "4317954"}, + {"RS", "S\u00e3o Borja", "4318002"}, + {"RS", "S\u00e3o Domingos do Sul", "4318051"}, + {"RS", "S\u00e3o Francisco de Assis", "4318101"}, + {"RS", "S\u00e3o Francisco de Paula", "4318200"}, + {"RS", "S\u00e3o Gabriel", "4318309"}, + {"RS", "S\u00e3o Jer\u00f4nimo", "4318408"}, + {"RS", "S\u00e3o Jo\u00e3o da Urtiga", "4318424"}, + {"RS", "S\u00e3o Jo\u00e3o do Pol\u00easine", "4318432"}, + {"RS", "S\u00e3o Jorge", "4318440"}, + {"RS", "S\u00e3o Jos\u00e9 das Miss\u00f5es", "4318457"}, + {"RS", "S\u00e3o Jos\u00e9 do Herval", "4318465"}, + {"RS", "S\u00e3o Jos\u00e9 do Hort\u00eancio", "4318481"}, + {"RS", "S\u00e3o Jos\u00e9 do Inhacor\u00e1", "4318499"}, + {"RS", "S\u00e3o Jos\u00e9 do Norte", "4318507"}, + {"RS", "S\u00e3o Jos\u00e9 do Ouro", "4318606"}, + {"RS", "S\u00e3o Jos\u00e9 do Sul", "4318614"}, + {"RS", "S\u00e3o Jos\u00e9 dos Ausentes", "4318622"}, + {"RS", "S\u00e3o Leopoldo", "4318705"}, + {"RS", "S\u00e3o Louren\u00e7o do Sul", "4318804"}, + {"RS", "S\u00e3o Luiz Gonzaga", "4318903"}, + {"RS", "S\u00e3o Marcos", "4319000"}, + {"RS", "S\u00e3o Martinho", "4319109"}, + {"RS", "S\u00e3o Martinho da Serra", "4319125"}, + {"RS", "S\u00e3o Miguel das Miss\u00f5es", "4319158"}, + {"RS", "S\u00e3o Nicolau", "4319208"}, + {"RS", "S\u00e3o Paulo das Miss\u00f5es", "4319307"}, + {"RS", "S\u00e3o Pedro da Serra", "4319356"}, + {"RS", "S\u00e3o Pedro das Miss\u00f5es", "4319364"}, + {"RS", "S\u00e3o Pedro do Buti\u00e1", "4319372"}, + {"RS", "S\u00e3o Pedro do Sul", "4319406"}, + {"RS", "S\u00e3o Sebasti\u00e3o do Ca\u00ed", "4319505"}, + {"RS", "S\u00e3o Sep\u00e9", "4319604"}, + {"RS", "S\u00e3o Valentim", "4319703"}, + {"RS", "S\u00e3o Valentim do Sul", "4319711"}, + {"RS", "S\u00e3o Val\u00e9rio do Sul", "4319737"}, + {"RS", "S\u00e3o Vendelino", "4319752"}, + {"RS", "S\u00e3o Vicente do Sul", "4319802"}, + {"RS", "Sapiranga", "4319901"}, + {"RS", "Sapucaia do Sul", "4320008"}, + {"RS", "Sarandi", "4320107"}, + {"RS", "Seberi", "4320206"}, + {"RS", "Sede Nova", "4320230"}, + {"RS", "Segredo", "4320263"}, + {"RS", "Selbach", "4320305"}, + {"RS", "Senador Salgado Filho", "4320321"}, + {"RS", "Sentinela do Sul", "4320354"}, + {"RS", "Serafina Corr\u00eaa", "4320404"}, + {"RS", "S\u00e9rio", "4320453"}, + {"RS", "Sert\u00e3o", "4320503"}, + {"RS", "Sert\u00e3o Santana", "4320552"}, + {"RS", "Sete de Setembro", "4320578"}, + {"RS", "Severiano de Almeida", "4320602"}, + {"RS", "Silveira Martins", "4320651"}, + {"RS", "Sinimbu", "4320677"}, + {"RS", "Sobradinho", "4320701"}, + {"RS", "Soledade", "4320800"}, + {"RS", "Taba\u00ed", "4320859"}, + {"RS", "Tapejara", "4320909"}, + {"RS", "Tapera", "4321006"}, + {"RS", "Tapes", "4321105"}, + {"RS", "Taquara", "4321204"}, + {"RS", "Taquari", "4321303"}, + {"RS", "Taquaru\u00e7u do Sul", "4321329"}, + {"RS", "Tavares", "4321352"}, + {"RS", "Tenente Portela", "4321402"}, + {"RS", "Terra de Areia", "4321436"}, + {"RS", "Teut\u00f4nia", "4321451"}, + {"RS", "Tio Hugo", "4321469"}, + {"RS", "Tiradentes do Sul", "4321477"}, + {"RS", "Toropi", "4321493"}, + {"RS", "Torres", "4321501"}, + {"RS", "Tramanda\u00ed", "4321600"}, + {"RS", "Travesseiro", "4321626"}, + {"RS", "Tr\u00eas Arroios", "4321634"}, + {"RS", "Tr\u00eas Cachoeiras", "4321667"}, + {"RS", "Tr\u00eas Coroas", "4321709"}, + {"RS", "Tr\u00eas de Maio", "4321808"}, + {"RS", "Tr\u00eas Forquilhas", "4321832"}, + {"RS", "Tr\u00eas Palmeiras", "4321857"}, + {"RS", "Tr\u00eas Passos", "4321907"}, + {"RS", "Trindade do Sul", "4321956"}, + {"RS", "Triunfo", "4322004"}, + {"RS", "Tucunduva", "4322103"}, + {"RS", "Tunas", "4322152"}, + {"RS", "Tupanci do Sul", "4322186"}, + {"RS", "Tupanciret\u00e3", "4322202"}, + {"RS", "Tupandi", "4322251"}, + {"RS", "Tuparendi", "4322301"}, + {"RS", "Turu\u00e7u", "4322327"}, + {"RS", "Ubiretama", "4322343"}, + {"RS", "Uni\u00e3o da Serra", "4322350"}, + {"RS", "Unistalda", "4322376"}, + {"RS", "Uruguaiana", "4322400"}, + {"RS", "Vacaria", "4322509"}, + {"RS", "Vale do Sol", "4322533"}, + {"RS", "Vale Real", "4322541"}, + {"RS", "Vale Verde", "4322525"}, + {"RS", "Vanini", "4322558"}, + {"RS", "Ven\u00e2ncio Aires", "4322608"}, + {"RS", "Vera Cruz", "4322707"}, + {"RS", "Veran\u00f3polis", "4322806"}, + {"RS", "Vespasiano Corr\u00eaa", "4322855"}, + {"RS", "Viadutos", "4322905"}, + {"RS", "Viam\u00e3o", "4323002"}, + {"RS", "Vicente Dutra", "4323101"}, + {"RS", "Victor Graeff", "4323200"}, + {"RS", "Vila Flores", "4323309"}, + {"RS", "Vila L\u00e2ngaro", "4323358"}, + {"RS", "Vila Maria", "4323408"}, + {"RS", "Vila Nova do Sul", "4323457"}, + {"RS", "Vista Alegre", "4323507"}, + {"RS", "Vista Alegre do Prata", "4323606"}, + {"RS", "Vista Ga\u00facha", "4323705"}, + {"RS", "Vit\u00f3ria das Miss\u00f5es", "4323754"}, + {"RS", "Westf\u00e1lia", "4323770"}, + {"RS", "Xangri-l\u00e1", "4323804"}, + {"RO", "Alta Floresta D'Oeste", "1100015"}, + {"RO", "Alto Alegre dos Parecis", "1100379"}, + {"RO", "Alto Para\u00edso", "1100403"}, + {"RO", "Alvorada D'Oeste", "1100346"}, + {"RO", "Ariquemes", "1100023"}, + {"RO", "Buritis", "1100452"}, + {"RO", "Cabixi", "1100031"}, + {"RO", "Cacaul\u00e2ndia", "1100601"}, + {"RO", "Cacoal", "1100049"}, + {"RO", "Campo Novo de Rond\u00f4nia", "1100700"}, + {"RO", "Candeias do Jamari", "1100809"}, + {"RO", "Castanheiras", "1100908"}, + {"RO", "Cerejeiras", "1100056"}, + {"RO", "Chupinguaia", "1100924"}, + {"RO", "Colorado do Oeste", "1100064"}, + {"RO", "Corumbiara", "1100072"}, + {"RO", "Costa Marques", "1100080"}, + {"RO", "Cujubim", "1100940"}, + {"RO", "Espig\u00e3o D'Oeste", "1100098"}, + {"RO", "Governador Jorge Teixeira", "1101005"}, + {"RO", "Guajar\u00e1-Mirim", "1100106"}, + {"RO", "Itapu\u00e3 do Oeste", "1101104"}, + {"RO", "Jaru", "1100114"}, + {"RO", "Ji-Paran\u00e1", "1100122"}, + {"RO", "Machadinho D'Oeste", "1100130"}, + {"RO", "Ministro Andreazza", "1101203"}, + {"RO", "Mirante da Serra", "1101302"}, + {"RO", "Monte Negro", "1101401"}, + {"RO", "Nova Brasil\u00e2ndia D'Oeste", "1100148"}, + {"RO", "Nova Mamor\u00e9", "1100338"}, + {"RO", "Nova Uni\u00e3o", "1101435"}, + {"RO", "Novo Horizonte do Oeste", "1100502"}, + {"RO", "Ouro Preto do Oeste", "1100155"}, + {"RO", "Parecis", "1101450"}, + {"RO", "Pimenta Bueno", "1100189"}, + {"RO", "Pimenteiras do Oeste", "1101468"}, + {"RO", "Porto Velho", "1100205"}, + {"RO", "Presidente M\u00e9dici", "1100254"}, + {"RO", "Primavera de Rond\u00f4nia", "1101476"}, + {"RO", "Rio Crespo", "1100262"}, + {"RO", "Rolim de Moura", "1100288"}, + {"RO", "Santa Luzia D'Oeste", "1100296"}, + {"RO", "S\u00e3o Felipe D'Oeste", "1101484"}, + {"RO", "S\u00e3o Francisco do Guapor\u00e9", "1101492"}, + {"RO", "S\u00e3o Miguel do Guapor\u00e9", "1100320"}, + {"RO", "Seringueiras", "1101500"}, + {"RO", "Teixeir\u00f3polis", "1101559"}, + {"RO", "Theobroma", "1101609"}, + {"RO", "Urup\u00e1", "1101708"}, + {"RO", "Vale do Anari", "1101757"}, + {"RO", "Vale do Para\u00edso", "1101807"}, + {"RO", "Vilhena", "1100304"}, + {"RR", "Alto Alegre", "1400050"}, + {"RR", "Amajari", "1400027"}, + {"RR", "Boa Vista", "1400100"}, + {"RR", "Bonfim", "1400159"}, + {"RR", "Cant\u00e1", "1400175"}, + {"RR", "Caracara\u00ed", "1400209"}, + {"RR", "Caroebe", "1400233"}, + {"RR", "Iracema", "1400282"}, + {"RR", "Mucaja\u00ed", "1400308"}, + {"RR", "Normandia", "1400407"}, + {"RR", "Pacaraima", "1400456"}, + {"RR", "Rorain\u00f3polis", "1400472"}, + {"RR", "S\u00e3o Jo\u00e3o da Baliza", "1400506"}, + {"RR", "S\u00e3o Luiz do Anau\u00e1", "1400605"}, + {"RR", "Uiramut\u00e3", "1400704"}, + {"SC", "Abdon Batista", "4200051"}, + {"SC", "Abelardo Luz", "4200101"}, + {"SC", "Agrol\u00e2ndia", "4200200"}, + {"SC", "Agron\u00f4mica", "4200309"}, + {"SC", "\u00c1gua Doce", "4200408"}, + {"SC", "\u00c1guas de Chapec\u00f3", "4200507"}, + {"SC", "\u00c1guas Frias", "4200556"}, + {"SC", "\u00c1guas Mornas", "4200606"}, + {"SC", "Alfredo Wagner", "4200705"}, + {"SC", "Alto Bela Vista", "4200754"}, + {"SC", "Anchieta", "4200804"}, + {"SC", "Angelina", "4200903"}, + {"SC", "Anita Garibaldi", "4201000"}, + {"SC", "Anit\u00e1polis", "4201109"}, + {"SC", "Ant\u00f4nio Carlos", "4201208"}, + {"SC", "Api\u00fana", "4201257"}, + {"SC", "Arabut\u00e3", "4201273"}, + {"SC", "Araquari", "4201307"}, + {"SC", "Ararangu\u00e1", "4201406"}, + {"SC", "Armaz\u00e9m", "4201505"}, + {"SC", "Arroio Trinta", "4201604"}, + {"SC", "Arvoredo", "4201653"}, + {"SC", "Ascurra", "4201703"}, + {"SC", "Atalanta", "4201802"}, + {"SC", "Aurora", "4201901"}, + {"SC", "Balne\u00e1rio Arroio do Silva", "4201950"}, + {"SC", "Balne\u00e1rio Barra do Sul", "4202057"}, + {"SC", "Balne\u00e1rio Cambori\u00fa", "4202008"}, + {"SC", "Balne\u00e1rio Gaivota", "4202073"}, + {"SC", "Balne\u00e1rio Pi\u00e7arras", "4212809"}, + {"SC", "Balne\u00e1rio Rinc\u00e3o", "4220000"}, + {"SC", "Bandeirante", "4202081"}, + {"SC", "Barra Bonita", "4202099"}, + {"SC", "Barra Velha", "4202107"}, + {"SC", "Bela Vista do Toldo", "4202131"}, + {"SC", "Belmonte", "4202156"}, + {"SC", "Benedito Novo", "4202206"}, + {"SC", "Bigua\u00e7u", "4202305"}, + {"SC", "Blumenau", "4202404"}, + {"SC", "Bocaina do Sul", "4202438"}, + {"SC", "Bom Jardim da Serra", "4202503"}, + {"SC", "Bom Jesus", "4202537"}, + {"SC", "Bom Jesus do Oeste", "4202578"}, + {"SC", "Bom Retiro", "4202602"}, + {"SC", "Bombinhas", "4202453"}, + {"SC", "Botuver\u00e1", "4202701"}, + {"SC", "Bra\u00e7o do Norte", "4202800"}, + {"SC", "Bra\u00e7o do Trombudo", "4202859"}, + {"SC", "Brun\u00f3polis", "4202875"}, + {"SC", "Brusque", "4202909"}, + {"SC", "Ca\u00e7ador", "4203006"}, + {"SC", "Caibi", "4203105"}, + {"SC", "Calmon", "4203154"}, + {"SC", "Cambori\u00fa", "4203204"}, + {"SC", "Campo Alegre", "4203303"}, + {"SC", "Campo Belo do Sul", "4203402"}, + {"SC", "Campo Er\u00ea", "4203501"}, + {"SC", "Campos Novos", "4203600"}, + {"SC", "Canelinha", "4203709"}, + {"SC", "Canoinhas", "4203808"}, + {"SC", "Cap\u00e3o Alto", "4203253"}, + {"SC", "Capinzal", "4203907"}, + {"SC", "Capivari de Baixo", "4203956"}, + {"SC", "Catanduvas", "4204004"}, + {"SC", "Caxambu do Sul", "4204103"}, + {"SC", "Celso Ramos", "4204152"}, + {"SC", "Cerro Negro", "4204178"}, + {"SC", "Chapad\u00e3o do Lageado", "4204194"}, + {"SC", "Chapec\u00f3", "4204202"}, + {"SC", "Cocal do Sul", "4204251"}, + {"SC", "Conc\u00f3rdia", "4204301"}, + {"SC", "Cordilheira Alta", "4204350"}, + {"SC", "Coronel Freitas", "4204400"}, + {"SC", "Coronel Martins", "4204459"}, + {"SC", "Correia Pinto", "4204558"}, + {"SC", "Corup\u00e1", "4204509"}, + {"SC", "Crici\u00fama", "4204608"}, + {"SC", "Cunha Por\u00e3", "4204707"}, + {"SC", "Cunhata\u00ed", "4204756"}, + {"SC", "Curitibanos", "4204806"}, + {"SC", "Descanso", "4204905"}, + {"SC", "Dion\u00edsio Cerqueira", "4205001"}, + {"SC", "Dona Emma", "4205100"}, + {"SC", "Doutor Pedrinho", "4205159"}, + {"SC", "Entre Rios", "4205175"}, + {"SC", "Ermo", "4205191"}, + {"SC", "Erval Velho", "4205209"}, + {"SC", "Faxinal dos Guedes", "4205308"}, + {"SC", "Flor do Sert\u00e3o", "4205357"}, + {"SC", "Florian\u00f3polis", "4205407"}, + {"SC", "Formosa do Sul", "4205431"}, + {"SC", "Forquilhinha", "4205456"}, + {"SC", "Fraiburgo", "4205506"}, + {"SC", "Frei Rog\u00e9rio", "4205555"}, + {"SC", "Galv\u00e3o", "4205605"}, + {"SC", "Garopaba", "4205704"}, + {"SC", "Garuva", "4205803"}, + {"SC", "Gaspar", "4205902"}, + {"SC", "Governador Celso Ramos", "4206009"}, + {"SC", "Gr\u00e3o-Par\u00e1", "4206108"}, + {"SC", "Gravatal", "4206207"}, + {"SC", "Guabiruba", "4206306"}, + {"SC", "Guaraciaba", "4206405"}, + {"SC", "Guaramirim", "4206504"}, + {"SC", "Guaruj\u00e1 do Sul", "4206603"}, + {"SC", "Guatamb\u00fa", "4206652"}, + {"SC", "Herval d'Oeste", "4206702"}, + {"SC", "Ibiam", "4206751"}, + {"SC", "Ibicar\u00e9", "4206801"}, + {"SC", "Ibirama", "4206900"}, + {"SC", "I\u00e7ara", "4207007"}, + {"SC", "Ilhota", "4207106"}, + {"SC", "Imaru\u00ed", "4207205"}, + {"SC", "Imbituba", "4207304"}, + {"SC", "Imbuia", "4207403"}, + {"SC", "Indaial", "4207502"}, + {"SC", "Iomer\u00ea", "4207577"}, + {"SC", "Ipira", "4207601"}, + {"SC", "Ipor\u00e3 do Oeste", "4207650"}, + {"SC", "Ipua\u00e7u", "4207684"}, + {"SC", "Ipumirim", "4207700"}, + {"SC", "Iraceminha", "4207759"}, + {"SC", "Irani", "4207809"}, + {"SC", "Irati", "4207858"}, + {"SC", "Irine\u00f3polis", "4207908"}, + {"SC", "It\u00e1", "4208005"}, + {"SC", "Itai\u00f3polis", "4208104"}, + {"SC", "Itaja\u00ed", "4208203"}, + {"SC", "Itapema", "4208302"}, + {"SC", "Itapiranga", "4208401"}, + {"SC", "Itapo\u00e1", "4208450"}, + {"SC", "Ituporanga", "4208500"}, + {"SC", "Jabor\u00e1", "4208609"}, + {"SC", "Jacinto Machado", "4208708"}, + {"SC", "Jaguaruna", "4208807"}, + {"SC", "Jaragu\u00e1 do Sul", "4208906"}, + {"SC", "Jardin\u00f3polis", "4208955"}, + {"SC", "Joa\u00e7aba", "4209003"}, + {"SC", "Joinville", "4209102"}, + {"SC", "Jos\u00e9 Boiteux", "4209151"}, + {"SC", "Jupi\u00e1", "4209177"}, + {"SC", "Lacerd\u00f3polis", "4209201"}, + {"SC", "Lages", "4209300"}, + {"SC", "Laguna", "4209409"}, + {"SC", "Lajeado Grande", "4209458"}, + {"SC", "Laurentino", "4209508"}, + {"SC", "Lauro M\u00fcller", "4209607"}, + {"SC", "Lebon R\u00e9gis", "4209706"}, + {"SC", "Leoberto Leal", "4209805"}, + {"SC", "Lind\u00f3ia do Sul", "4209854"}, + {"SC", "Lontras", "4209904"}, + {"SC", "Luiz Alves", "4210001"}, + {"SC", "Luzerna", "4210035"}, + {"SC", "Macieira", "4210050"}, + {"SC", "Mafra", "4210100"}, + {"SC", "Major Gercino", "4210209"}, + {"SC", "Major Vieira", "4210308"}, + {"SC", "Maracaj\u00e1", "4210407"}, + {"SC", "Maravilha", "4210506"}, + {"SC", "Marema", "4210555"}, + {"SC", "Massaranduba", "4210605"}, + {"SC", "Matos Costa", "4210704"}, + {"SC", "Meleiro", "4210803"}, + {"SC", "Mirim Doce", "4210852"}, + {"SC", "Modelo", "4210902"}, + {"SC", "Monda\u00ed", "4211009"}, + {"SC", "Monte Carlo", "4211058"}, + {"SC", "Monte Castelo", "4211108"}, + {"SC", "Morro da Fuma\u00e7a", "4211207"}, + {"SC", "Morro Grande", "4211256"}, + {"SC", "Navegantes", "4211306"}, + {"SC", "Nova Erechim", "4211405"}, + {"SC", "Nova Itaberaba", "4211454"}, + {"SC", "Nova Trento", "4211504"}, + {"SC", "Nova Veneza", "4211603"}, + {"SC", "Novo Horizonte", "4211652"}, + {"SC", "Orleans", "4211702"}, + {"SC", "Otac\u00edlio Costa", "4211751"}, + {"SC", "Ouro", "4211801"}, + {"SC", "Ouro Verde", "4211850"}, + {"SC", "Paial", "4211876"}, + {"SC", "Painel", "4211892"}, + {"SC", "Palho\u00e7a", "4211900"}, + {"SC", "Palma Sola", "4212007"}, + {"SC", "Palmeira", "4212056"}, + {"SC", "Palmitos", "4212106"}, + {"SC", "Papanduva", "4212205"}, + {"SC", "Para\u00edso", "4212239"}, + {"SC", "Passo de Torres", "4212254"}, + {"SC", "Passos Maia", "4212270"}, + {"SC", "Paulo Lopes", "4212304"}, + {"SC", "Pedras Grandes", "4212403"}, + {"SC", "Penha", "4212502"}, + {"SC", "Peritiba", "4212601"}, + {"SC", "Pescaria Brava", "4212650"}, + {"SC", "Petrol\u00e2ndia", "4212700"}, + {"SC", "Pinhalzinho", "4212908"}, + {"SC", "Pinheiro Preto", "4213005"}, + {"SC", "Piratuba", "4213104"}, + {"SC", "Planalto Alegre", "4213153"}, + {"SC", "Pomerode", "4213203"}, + {"SC", "Ponte Alta", "4213302"}, + {"SC", "Ponte Alta do Norte", "4213351"}, + {"SC", "Ponte Serrada", "4213401"}, + {"SC", "Porto Belo", "4213500"}, + {"SC", "Porto Uni\u00e3o", "4213609"}, + {"SC", "Pouso Redondo", "4213708"}, + {"SC", "Praia Grande", "4213807"}, + {"SC", "Presidente Castello Branco", "4213906"}, + {"SC", "Presidente Get\u00falio", "4214003"}, + {"SC", "Presidente Nereu", "4214102"}, + {"SC", "Princesa", "4214151"}, + {"SC", "Quilombo", "4214201"}, + {"SC", "Rancho Queimado", "4214300"}, + {"SC", "Rio das Antas", "4214409"}, + {"SC", "Rio do Campo", "4214508"}, + {"SC", "Rio do Oeste", "4214607"}, + {"SC", "Rio do Sul", "4214805"}, + {"SC", "Rio dos Cedros", "4214706"}, + {"SC", "Rio Fortuna", "4214904"}, + {"SC", "Rio Negrinho", "4215000"}, + {"SC", "Rio Rufino", "4215059"}, + {"SC", "Riqueza", "4215075"}, + {"SC", "Rodeio", "4215109"}, + {"SC", "Romel\u00e2ndia", "4215208"}, + {"SC", "Salete", "4215307"}, + {"SC", "Saltinho", "4215356"}, + {"SC", "Salto Veloso", "4215406"}, + {"SC", "Sang\u00e3o", "4215455"}, + {"SC", "Santa Cec\u00edlia", "4215505"}, + {"SC", "Santa Helena", "4215554"}, + {"SC", "Santa Rosa de Lima", "4215604"}, + {"SC", "Santa Rosa do Sul", "4215653"}, + {"SC", "Santa Terezinha", "4215679"}, + {"SC", "Santa Terezinha do Progresso", "4215687"}, + {"SC", "Santiago do Sul", "4215695"}, + {"SC", "Santo Amaro da Imperatriz", "4215703"}, + {"SC", "S\u00e3o Bento do Sul", "4215802"}, + {"SC", "S\u00e3o Bernardino", "4215752"}, + {"SC", "S\u00e3o Bonif\u00e1cio", "4215901"}, + {"SC", "S\u00e3o Carlos", "4216008"}, + {"SC", "S\u00e3o Crist\u00f3v\u00e3o do Sul", "4216057"}, + {"SC", "S\u00e3o Domingos", "4216107"}, + {"SC", "S\u00e3o Francisco do Sul", "4216206"}, + {"SC", "S\u00e3o Jo\u00e3o Batista", "4216305"}, + {"SC", "S\u00e3o Jo\u00e3o do Itaperi\u00fa", "4216354"}, + {"SC", "S\u00e3o Jo\u00e3o do Oeste", "4216255"}, + {"SC", "S\u00e3o Jo\u00e3o do Sul", "4216404"}, + {"SC", "S\u00e3o Joaquim", "4216503"}, + {"SC", "S\u00e3o Jos\u00e9", "4216602"}, + {"SC", "S\u00e3o Jos\u00e9 do Cedro", "4216701"}, + {"SC", "S\u00e3o Jos\u00e9 do Cerrito", "4216800"}, + {"SC", "S\u00e3o Louren\u00e7o do Oeste", "4216909"}, + {"SC", "S\u00e3o Ludgero", "4217006"}, + {"SC", "S\u00e3o Martinho", "4217105"}, + {"SC", "S\u00e3o Miguel da Boa Vista", "4217154"}, + {"SC", "S\u00e3o Miguel do Oeste", "4217204"}, + {"SC", "S\u00e3o Pedro de Alc\u00e2ntara", "4217253"}, + {"SC", "Saudades", "4217303"}, + {"SC", "Schroeder", "4217402"}, + {"SC", "Seara", "4217501"}, + {"SC", "Serra Alta", "4217550"}, + {"SC", "Sider\u00f3polis", "4217600"}, + {"SC", "Sombrio", "4217709"}, + {"SC", "Sul Brasil", "4217758"}, + {"SC", "Tai\u00f3", "4217808"}, + {"SC", "Tangar\u00e1", "4217907"}, + {"SC", "Tigrinhos", "4217956"}, + {"SC", "Tijucas", "4218004"}, + {"SC", "Timb\u00e9 do Sul", "4218103"}, + {"SC", "Timb\u00f3", "4218202"}, + {"SC", "Timb\u00f3 Grande", "4218251"}, + {"SC", "Tr\u00eas Barras", "4218301"}, + {"SC", "Treviso", "4218350"}, + {"SC", "Treze de Maio", "4218400"}, + {"SC", "Treze T\u00edlias", "4218509"}, + {"SC", "Trombudo Central", "4218608"}, + {"SC", "Tubar\u00e3o", "4218707"}, + {"SC", "Tun\u00e1polis", "4218756"}, + {"SC", "Turvo", "4218806"}, + {"SC", "Uni\u00e3o do Oeste", "4218855"}, + {"SC", "Urubici", "4218905"}, + {"SC", "Urupema", "4218954"}, + {"SC", "Urussanga", "4219002"}, + {"SC", "Varge\u00e3o", "4219101"}, + {"SC", "Vargem", "4219150"}, + {"SC", "Vargem Bonita", "4219176"}, + {"SC", "Vidal Ramos", "4219200"}, + {"SC", "Videira", "4219309"}, + {"SC", "Vitor Meireles", "4219358"}, + {"SC", "Witmarsum", "4219408"}, + {"SC", "Xanxer\u00ea", "4219507"}, + {"SC", "Xavantina", "4219606"}, + {"SC", "Xaxim", "4219705"}, + {"SC", "Zort\u00e9a", "4219853"}, + {"SP", "Adamantina", "3500105"}, + {"SP", "Adolfo", "3500204"}, + {"SP", "Agua\u00ed", "3500303"}, + {"SP", "\u00c1guas da Prata", "3500402"}, + {"SP", "\u00c1guas de Lind\u00f3ia", "3500501"}, + {"SP", "\u00c1guas de Santa B\u00e1rbara", "3500550"}, + {"SP", "\u00c1guas de S\u00e3o Pedro", "3500600"}, + {"SP", "Agudos", "3500709"}, + {"SP", "Alambari", "3500758"}, + {"SP", "Alfredo Marcondes", "3500808"}, + {"SP", "Altair", "3500907"}, + {"SP", "Altin\u00f3polis", "3501004"}, + {"SP", "Alto Alegre", "3501103"}, + {"SP", "Alum\u00ednio", "3501152"}, + {"SP", "\u00c1lvares Florence", "3501202"}, + {"SP", "\u00c1lvares Machado", "3501301"}, + {"SP", "\u00c1lvaro de Carvalho", "3501400"}, + {"SP", "Alvinl\u00e2ndia", "3501509"}, + {"SP", "Americana", "3501608"}, + {"SP", "Am\u00e9rico Brasiliense", "3501707"}, + {"SP", "Am\u00e9rico de Campos", "3501806"}, + {"SP", "Amparo", "3501905"}, + {"SP", "Anal\u00e2ndia", "3502002"}, + {"SP", "Andradina", "3502101"}, + {"SP", "Angatuba", "3502200"}, + {"SP", "Anhembi", "3502309"}, + {"SP", "Anhumas", "3502408"}, + {"SP", "Aparecida", "3502507"}, + {"SP", "Aparecida d'Oeste", "3502606"}, + {"SP", "Apia\u00ed", "3502705"}, + {"SP", "Ara\u00e7ariguama", "3502754"}, + {"SP", "Ara\u00e7atuba", "3502804"}, + {"SP", "Ara\u00e7oiaba da Serra", "3502903"}, + {"SP", "Aramina", "3503000"}, + {"SP", "Arandu", "3503109"}, + {"SP", "Arape\u00ed", "3503158"}, + {"SP", "Araraquara", "3503208"}, + {"SP", "Araras", "3503307"}, + {"SP", "Arco-\u00cdris", "3503356"}, + {"SP", "Arealva", "3503406"}, + {"SP", "Areias", "3503505"}, + {"SP", "Arei\u00f3polis", "3503604"}, + {"SP", "Ariranha", "3503703"}, + {"SP", "Artur Nogueira", "3503802"}, + {"SP", "Aruj\u00e1", "3503901"}, + {"SP", "Asp\u00e1sia", "3503950"}, + {"SP", "Assis", "3504008"}, + {"SP", "Atibaia", "3504107"}, + {"SP", "Auriflama", "3504206"}, + {"SP", "Ava\u00ed", "3504305"}, + {"SP", "Avanhandava", "3504404"}, + {"SP", "Avar\u00e9", "3504503"}, + {"SP", "Bady Bassitt", "3504602"}, + {"SP", "Balbinos", "3504701"}, + {"SP", "B\u00e1lsamo", "3504800"}, + {"SP", "Bananal", "3504909"}, + {"SP", "Bar\u00e3o de Antonina", "3505005"}, + {"SP", "Barbosa", "3505104"}, + {"SP", "Bariri", "3505203"}, + {"SP", "Barra Bonita", "3505302"}, + {"SP", "Barra do Chap\u00e9u", "3505351"}, + {"SP", "Barra do Turvo", "3505401"}, + {"SP", "Barretos", "3505500"}, + {"SP", "Barrinha", "3505609"}, + {"SP", "Barueri", "3505708"}, + {"SP", "Bastos", "3505807"}, + {"SP", "Batatais", "3505906"}, + {"SP", "Bauru", "3506003"}, + {"SP", "Bebedouro", "3506102"}, + {"SP", "Bento de Abreu", "3506201"}, + {"SP", "Bernardino de Campos", "3506300"}, + {"SP", "Bertioga", "3506359"}, + {"SP", "Bilac", "3506409"}, + {"SP", "Birigui", "3506508"}, + {"SP", "Biritiba Mirim", "3506607"}, + {"SP", "Boa Esperan\u00e7a do Sul", "3506706"}, + {"SP", "Bocaina", "3506805"}, + {"SP", "Bofete", "3506904"}, + {"SP", "Boituva", "3507001"}, + {"SP", "Bom Jesus dos Perd\u00f5es", "3507100"}, + {"SP", "Bom Sucesso de Itarar\u00e9", "3507159"}, + {"SP", "Bor\u00e1", "3507209"}, + {"SP", "Borac\u00e9ia", "3507308"}, + {"SP", "Borborema", "3507407"}, + {"SP", "Borebi", "3507456"}, + {"SP", "Botucatu", "3507506"}, + {"SP", "Bragan\u00e7a Paulista", "3507605"}, + {"SP", "Bra\u00fana", "3507704"}, + {"SP", "Brejo Alegre", "3507753"}, + {"SP", "Brodowski", "3507803"}, + {"SP", "Brotas", "3507902"}, + {"SP", "Buri", "3508009"}, + {"SP", "Buritama", "3508108"}, + {"SP", "Buritizal", "3508207"}, + {"SP", "Cabr\u00e1lia Paulista", "3508306"}, + {"SP", "Cabre\u00fava", "3508405"}, + {"SP", "Ca\u00e7apava", "3508504"}, + {"SP", "Cachoeira Paulista", "3508603"}, + {"SP", "Caconde", "3508702"}, + {"SP", "Cafel\u00e2ndia", "3508801"}, + {"SP", "Caiabu", "3508900"}, + {"SP", "Caieiras", "3509007"}, + {"SP", "Caiu\u00e1", "3509106"}, + {"SP", "Cajamar", "3509205"}, + {"SP", "Cajati", "3509254"}, + {"SP", "Cajobi", "3509304"}, + {"SP", "Cajuru", "3509403"}, + {"SP", "Campina do Monte Alegre", "3509452"}, + {"SP", "Campinas", "3509502"}, + {"SP", "Campo Limpo Paulista", "3509601"}, + {"SP", "Campos do Jord\u00e3o", "3509700"}, + {"SP", "Campos Novos Paulista", "3509809"}, + {"SP", "Canan\u00e9ia", "3509908"}, + {"SP", "Canas", "3509957"}, + {"SP", "C\u00e2ndido Mota", "3510005"}, + {"SP", "C\u00e2ndido Rodrigues", "3510104"}, + {"SP", "Canitar", "3510153"}, + {"SP", "Cap\u00e3o Bonito", "3510203"}, + {"SP", "Capela do Alto", "3510302"}, + {"SP", "Capivari", "3510401"}, + {"SP", "Caraguatatuba", "3510500"}, + {"SP", "Carapicu\u00edba", "3510609"}, + {"SP", "Cardoso", "3510708"}, + {"SP", "Casa Branca", "3510807"}, + {"SP", "C\u00e1ssia dos Coqueiros", "3510906"}, + {"SP", "Castilho", "3511003"}, + {"SP", "Catanduva", "3511102"}, + {"SP", "Catigu\u00e1", "3511201"}, + {"SP", "Cedral", "3511300"}, + {"SP", "Cerqueira C\u00e9sar", "3511409"}, + {"SP", "Cerquilho", "3511508"}, + {"SP", "Ces\u00e1rio Lange", "3511607"}, + {"SP", "Charqueada", "3511706"}, + {"SP", "Chavantes", "3557204"}, + {"SP", "Clementina", "3511904"}, + {"SP", "Colina", "3512001"}, + {"SP", "Col\u00f4mbia", "3512100"}, + {"SP", "Conchal", "3512209"}, + {"SP", "Conchas", "3512308"}, + {"SP", "Cordeir\u00f3polis", "3512407"}, + {"SP", "Coroados", "3512506"}, + {"SP", "Coronel Macedo", "3512605"}, + {"SP", "Corumbata\u00ed", "3512704"}, + {"SP", "Cosm\u00f3polis", "3512803"}, + {"SP", "Cosmorama", "3512902"}, + {"SP", "Cotia", "3513009"}, + {"SP", "Cravinhos", "3513108"}, + {"SP", "Cristais Paulista", "3513207"}, + {"SP", "Cruz\u00e1lia", "3513306"}, + {"SP", "Cruzeiro", "3513405"}, + {"SP", "Cubat\u00e3o", "3513504"}, + {"SP", "Cunha", "3513603"}, + {"SP", "Descalvado", "3513702"}, + {"SP", "Diadema", "3513801"}, + {"SP", "Dirce Reis", "3513850"}, + {"SP", "Divinol\u00e2ndia", "3513900"}, + {"SP", "Dobrada", "3514007"}, + {"SP", "Dois C\u00f3rregos", "3514106"}, + {"SP", "Dolcin\u00f3polis", "3514205"}, + {"SP", "Dourado", "3514304"}, + {"SP", "Dracena", "3514403"}, + {"SP", "Duartina", "3514502"}, + {"SP", "Dumont", "3514601"}, + {"SP", "Echapor\u00e3", "3514700"}, + {"SP", "Eldorado", "3514809"}, + {"SP", "Elias Fausto", "3514908"}, + {"SP", "Elisi\u00e1rio", "3514924"}, + {"SP", "Emba\u00faba", "3514957"}, + {"SP", "Embu das Artes", "3515004"}, + {"SP", "Embu-Gua\u00e7u", "3515103"}, + {"SP", "Emilian\u00f3polis", "3515129"}, + {"SP", "Engenheiro Coelho", "3515152"}, + {"SP", "Esp\u00edrito Santo do Pinhal", "3515186"}, + {"SP", "Esp\u00edrito Santo do Turvo", "3515194"}, + {"SP", "Estiva Gerbi", "3557303"}, + {"SP", "Estrela d'Oeste", "3515202"}, + {"SP", "Estrela do Norte", "3515301"}, + {"SP", "Euclides da Cunha Paulista", "3515350"}, + {"SP", "Fartura", "3515400"}, + {"SP", "Fernando Prestes", "3515608"}, + {"SP", "Fernand\u00f3polis", "3515509"}, + {"SP", "Fern\u00e3o", "3515657"}, + {"SP", "Ferraz de Vasconcelos", "3515707"}, + {"SP", "Flora Rica", "3515806"}, + {"SP", "Floreal", "3515905"}, + {"SP", "Fl\u00f3rida Paulista", "3516002"}, + {"SP", "Flor\u00ednea", "3516101"}, + {"SP", "Franca", "3516200"}, + {"SP", "Francisco Morato", "3516309"}, + {"SP", "Franco da Rocha", "3516408"}, + {"SP", "Gabriel Monteiro", "3516507"}, + {"SP", "G\u00e1lia", "3516606"}, + {"SP", "Gar\u00e7a", "3516705"}, + {"SP", "Gast\u00e3o Vidigal", "3516804"}, + {"SP", "Gavi\u00e3o Peixoto", "3516853"}, + {"SP", "General Salgado", "3516903"}, + {"SP", "Getulina", "3517000"}, + {"SP", "Glic\u00e9rio", "3517109"}, + {"SP", "Guai\u00e7ara", "3517208"}, + {"SP", "Guaimb\u00ea", "3517307"}, + {"SP", "Gua\u00edra", "3517406"}, + {"SP", "Guapia\u00e7u", "3517505"}, + {"SP", "Guapiara", "3517604"}, + {"SP", "Guar\u00e1", "3517703"}, + {"SP", "Guara\u00e7a\u00ed", "3517802"}, + {"SP", "Guaraci", "3517901"}, + {"SP", "Guarani d'Oeste", "3518008"}, + {"SP", "Guarant\u00e3", "3518107"}, + {"SP", "Guararapes", "3518206"}, + {"SP", "Guararema", "3518305"}, + {"SP", "Guaratinguet\u00e1", "3518404"}, + {"SP", "Guare\u00ed", "3518503"}, + {"SP", "Guariba", "3518602"}, + {"SP", "Guaruj\u00e1", "3518701"}, + {"SP", "Guarulhos", "3518800"}, + {"SP", "Guatapar\u00e1", "3518859"}, + {"SP", "Guzol\u00e2ndia", "3518909"}, + {"SP", "Hercul\u00e2ndia", "3519006"}, + {"SP", "Holambra", "3519055"}, + {"SP", "Hortol\u00e2ndia", "3519071"}, + {"SP", "Iacanga", "3519105"}, + {"SP", "Iacri", "3519204"}, + {"SP", "Iaras", "3519253"}, + {"SP", "Ibat\u00e9", "3519303"}, + {"SP", "Ibir\u00e1", "3519402"}, + {"SP", "Ibirarema", "3519501"}, + {"SP", "Ibitinga", "3519600"}, + {"SP", "Ibi\u00fana", "3519709"}, + {"SP", "Ic\u00e9m", "3519808"}, + {"SP", "Iep\u00ea", "3519907"}, + {"SP", "Igara\u00e7u do Tiet\u00ea", "3520004"}, + {"SP", "Igarapava", "3520103"}, + {"SP", "Igarat\u00e1", "3520202"}, + {"SP", "Iguape", "3520301"}, + {"SP", "Ilha Comprida", "3520426"}, + {"SP", "Ilha Solteira", "3520442"}, + {"SP", "Ilhabela", "3520400"}, + {"SP", "Indaiatuba", "3520509"}, + {"SP", "Indiana", "3520608"}, + {"SP", "Indiapor\u00e3", "3520707"}, + {"SP", "In\u00fabia Paulista", "3520806"}, + {"SP", "Ipaussu", "3520905"}, + {"SP", "Iper\u00f3", "3521002"}, + {"SP", "Ipe\u00fana", "3521101"}, + {"SP", "Ipigu\u00e1", "3521150"}, + {"SP", "Iporanga", "3521200"}, + {"SP", "Ipu\u00e3", "3521309"}, + {"SP", "Iracem\u00e1polis", "3521408"}, + {"SP", "Irapu\u00e3", "3521507"}, + {"SP", "Irapuru", "3521606"}, + {"SP", "Itaber\u00e1", "3521705"}, + {"SP", "Ita\u00ed", "3521804"}, + {"SP", "Itajobi", "3521903"}, + {"SP", "Itaju", "3522000"}, + {"SP", "Itanha\u00e9m", "3522109"}, + {"SP", "Itaoca", "3522158"}, + {"SP", "Itapecerica da Serra", "3522208"}, + {"SP", "Itapetininga", "3522307"}, + {"SP", "Itapeva", "3522406"}, + {"SP", "Itapevi", "3522505"}, + {"SP", "Itapira", "3522604"}, + {"SP", "Itapirapu\u00e3 Paulista", "3522653"}, + {"SP", "It\u00e1polis", "3522703"}, + {"SP", "Itaporanga", "3522802"}, + {"SP", "Itapu\u00ed", "3522901"}, + {"SP", "Itapura", "3523008"}, + {"SP", "Itaquaquecetuba", "3523107"}, + {"SP", "Itarar\u00e9", "3523206"}, + {"SP", "Itariri", "3523305"}, + {"SP", "Itatiba", "3523404"}, + {"SP", "Itatinga", "3523503"}, + {"SP", "Itirapina", "3523602"}, + {"SP", "Itirapu\u00e3", "3523701"}, + {"SP", "Itobi", "3523800"}, + {"SP", "Itu", "3523909"}, + {"SP", "Itupeva", "3524006"}, + {"SP", "Ituverava", "3524105"}, + {"SP", "Jaborandi", "3524204"}, + {"SP", "Jaboticabal", "3524303"}, + {"SP", "Jacare\u00ed", "3524402"}, + {"SP", "Jaci", "3524501"}, + {"SP", "Jacupiranga", "3524600"}, + {"SP", "Jaguari\u00fana", "3524709"}, + {"SP", "Jales", "3524808"}, + {"SP", "Jambeiro", "3524907"}, + {"SP", "Jandira", "3525003"}, + {"SP", "Jardin\u00f3polis", "3525102"}, + {"SP", "Jarinu", "3525201"}, + {"SP", "Ja\u00fa", "3525300"}, + {"SP", "Jeriquara", "3525409"}, + {"SP", "Joan\u00f3polis", "3525508"}, + {"SP", "Jo\u00e3o Ramalho", "3525607"}, + {"SP", "Jos\u00e9 Bonif\u00e1cio", "3525706"}, + {"SP", "J\u00falio Mesquita", "3525805"}, + {"SP", "Jumirim", "3525854"}, + {"SP", "Jundia\u00ed", "3525904"}, + {"SP", "Junqueir\u00f3polis", "3526001"}, + {"SP", "Juqui\u00e1", "3526100"}, + {"SP", "Juquitiba", "3526209"}, + {"SP", "Lagoinha", "3526308"}, + {"SP", "Laranjal Paulista", "3526407"}, + {"SP", "Lav\u00ednia", "3526506"}, + {"SP", "Lavrinhas", "3526605"}, + {"SP", "Leme", "3526704"}, + {"SP", "Len\u00e7\u00f3is Paulista", "3526803"}, + {"SP", "Limeira", "3526902"}, + {"SP", "Lind\u00f3ia", "3527009"}, + {"SP", "Lins", "3527108"}, + {"SP", "Lorena", "3527207"}, + {"SP", "Lourdes", "3527256"}, + {"SP", "Louveira", "3527306"}, + {"SP", "Luc\u00e9lia", "3527405"}, + {"SP", "Lucian\u00f3polis", "3527504"}, + {"SP", "Lu\u00eds Ant\u00f4nio", "3527603"}, + {"SP", "Luizi\u00e2nia", "3527702"}, + {"SP", "Lup\u00e9rcio", "3527801"}, + {"SP", "Lut\u00e9cia", "3527900"}, + {"SP", "Macatuba", "3528007"}, + {"SP", "Macaubal", "3528106"}, + {"SP", "Maced\u00f4nia", "3528205"}, + {"SP", "Magda", "3528304"}, + {"SP", "Mairinque", "3528403"}, + {"SP", "Mairipor\u00e3", "3528502"}, + {"SP", "Manduri", "3528601"}, + {"SP", "Marab\u00e1 Paulista", "3528700"}, + {"SP", "Maraca\u00ed", "3528809"}, + {"SP", "Marapoama", "3528858"}, + {"SP", "Mari\u00e1polis", "3528908"}, + {"SP", "Mar\u00edlia", "3529005"}, + {"SP", "Marin\u00f3polis", "3529104"}, + {"SP", "Martin\u00f3polis", "3529203"}, + {"SP", "Mat\u00e3o", "3529302"}, + {"SP", "Mau\u00e1", "3529401"}, + {"SP", "Mendon\u00e7a", "3529500"}, + {"SP", "Meridiano", "3529609"}, + {"SP", "Mes\u00f3polis", "3529658"}, + {"SP", "Miguel\u00f3polis", "3529708"}, + {"SP", "Mineiros do Tiet\u00ea", "3529807"}, + {"SP", "Mira Estrela", "3530003"}, + {"SP", "Miracatu", "3529906"}, + {"SP", "Mirand\u00f3polis", "3530102"}, + {"SP", "Mirante do Paranapanema", "3530201"}, + {"SP", "Mirassol", "3530300"}, + {"SP", "Mirassol\u00e2ndia", "3530409"}, + {"SP", "Mococa", "3530508"}, + {"SP", "Mogi das Cruzes", "3530607"}, + {"SP", "Mogi Gua\u00e7u", "3530706"}, + {"SP", "Mogi Mirim", "3530805"}, + {"SP", "Mombuca", "3530904"}, + {"SP", "Mon\u00e7\u00f5es", "3531001"}, + {"SP", "Mongagu\u00e1", "3531100"}, + {"SP", "Monte Alegre do Sul", "3531209"}, + {"SP", "Monte Alto", "3531308"}, + {"SP", "Monte Apraz\u00edvel", "3531407"}, + {"SP", "Monte Azul Paulista", "3531506"}, + {"SP", "Monte Castelo", "3531605"}, + {"SP", "Monte Mor", "3531803"}, + {"SP", "Monteiro Lobato", "3531704"}, + {"SP", "Morro Agudo", "3531902"}, + {"SP", "Morungaba", "3532009"}, + {"SP", "Motuca", "3532058"}, + {"SP", "Murutinga do Sul", "3532108"}, + {"SP", "Nantes", "3532157"}, + {"SP", "Narandiba", "3532207"}, + {"SP", "Natividade da Serra", "3532306"}, + {"SP", "Nazar\u00e9 Paulista", "3532405"}, + {"SP", "Neves Paulista", "3532504"}, + {"SP", "Nhandeara", "3532603"}, + {"SP", "Nipo\u00e3", "3532702"}, + {"SP", "Nova Alian\u00e7a", "3532801"}, + {"SP", "Nova Campina", "3532827"}, + {"SP", "Nova Cana\u00e3 Paulista", "3532843"}, + {"SP", "Nova Castilho", "3532868"}, + {"SP", "Nova Europa", "3532900"}, + {"SP", "Nova Granada", "3533007"}, + {"SP", "Nova Guataporanga", "3533106"}, + {"SP", "Nova Independ\u00eancia", "3533205"}, + {"SP", "Nova Luzit\u00e2nia", "3533304"}, + {"SP", "Nova Odessa", "3533403"}, + {"SP", "Novais", "3533254"}, + {"SP", "Novo Horizonte", "3533502"}, + {"SP", "Nuporanga", "3533601"}, + {"SP", "Ocau\u00e7u", "3533700"}, + {"SP", "\u00d3leo", "3533809"}, + {"SP", "Ol\u00edmpia", "3533908"}, + {"SP", "Onda Verde", "3534005"}, + {"SP", "Oriente", "3534104"}, + {"SP", "Orindi\u00fava", "3534203"}, + {"SP", "Orl\u00e2ndia", "3534302"}, + {"SP", "Osasco", "3534401"}, + {"SP", "Oscar Bressane", "3534500"}, + {"SP", "Osvaldo Cruz", "3534609"}, + {"SP", "Ourinhos", "3534708"}, + {"SP", "Ouro Verde", "3534807"}, + {"SP", "Ouroeste", "3534757"}, + {"SP", "Pacaembu", "3534906"}, + {"SP", "Palestina", "3535002"}, + {"SP", "Palmares Paulista", "3535101"}, + {"SP", "Palmeira d'Oeste", "3535200"}, + {"SP", "Palmital", "3535309"}, + {"SP", "Panorama", "3535408"}, + {"SP", "Paragua\u00e7u Paulista", "3535507"}, + {"SP", "Paraibuna", "3535606"}, + {"SP", "Para\u00edso", "3535705"}, + {"SP", "Paranapanema", "3535804"}, + {"SP", "Paranapu\u00e3", "3535903"}, + {"SP", "Parapu\u00e3", "3536000"}, + {"SP", "Pardinho", "3536109"}, + {"SP", "Pariquera-A\u00e7u", "3536208"}, + {"SP", "Parisi", "3536257"}, + {"SP", "Patroc\u00ednio Paulista", "3536307"}, + {"SP", "Paulic\u00e9ia", "3536406"}, + {"SP", "Paul\u00ednia", "3536505"}, + {"SP", "Paulist\u00e2nia", "3536570"}, + {"SP", "Paulo de Faria", "3536604"}, + {"SP", "Pederneiras", "3536703"}, + {"SP", "Pedra Bela", "3536802"}, + {"SP", "Pedran\u00f3polis", "3536901"}, + {"SP", "Pedregulho", "3537008"}, + {"SP", "Pedreira", "3537107"}, + {"SP", "Pedrinhas Paulista", "3537156"}, + {"SP", "Pedro de Toledo", "3537206"}, + {"SP", "Pen\u00e1polis", "3537305"}, + {"SP", "Pereira Barreto", "3537404"}, + {"SP", "Pereiras", "3537503"}, + {"SP", "Peru\u00edbe", "3537602"}, + {"SP", "Piacatu", "3537701"}, + {"SP", "Piedade", "3537800"}, + {"SP", "Pilar do Sul", "3537909"}, + {"SP", "Pindamonhangaba", "3538006"}, + {"SP", "Pindorama", "3538105"}, + {"SP", "Pinhalzinho", "3538204"}, + {"SP", "Piquerobi", "3538303"}, + {"SP", "Piquete", "3538501"}, + {"SP", "Piracaia", "3538600"}, + {"SP", "Piracicaba", "3538709"}, + {"SP", "Piraju", "3538808"}, + {"SP", "Piraju\u00ed", "3538907"}, + {"SP", "Pirangi", "3539004"}, + {"SP", "Pirapora do Bom Jesus", "3539103"}, + {"SP", "Pirapozinho", "3539202"}, + {"SP", "Pirassununga", "3539301"}, + {"SP", "Piratininga", "3539400"}, + {"SP", "Pitangueiras", "3539509"}, + {"SP", "Planalto", "3539608"}, + {"SP", "Platina", "3539707"}, + {"SP", "Po\u00e1", "3539806"}, + {"SP", "Poloni", "3539905"}, + {"SP", "Pomp\u00e9ia", "3540002"}, + {"SP", "Ponga\u00ed", "3540101"}, + {"SP", "Pontal", "3540200"}, + {"SP", "Pontalinda", "3540259"}, + {"SP", "Pontes Gestal", "3540309"}, + {"SP", "Populina", "3540408"}, + {"SP", "Porangaba", "3540507"}, + {"SP", "Porto Feliz", "3540606"}, + {"SP", "Porto Ferreira", "3540705"}, + {"SP", "Potim", "3540754"}, + {"SP", "Potirendaba", "3540804"}, + {"SP", "Pracinha", "3540853"}, + {"SP", "Prad\u00f3polis", "3540903"}, + {"SP", "Praia Grande", "3541000"}, + {"SP", "Prat\u00e2nia", "3541059"}, + {"SP", "Presidente Alves", "3541109"}, + {"SP", "Presidente Bernardes", "3541208"}, + {"SP", "Presidente Epit\u00e1cio", "3541307"}, + {"SP", "Presidente Prudente", "3541406"}, + {"SP", "Presidente Venceslau", "3541505"}, + {"SP", "Promiss\u00e3o", "3541604"}, + {"SP", "Quadra", "3541653"}, + {"SP", "Quat\u00e1", "3541703"}, + {"SP", "Queiroz", "3541802"}, + {"SP", "Queluz", "3541901"}, + {"SP", "Quintana", "3542008"}, + {"SP", "Rafard", "3542107"}, + {"SP", "Rancharia", "3542206"}, + {"SP", "Reden\u00e7\u00e3o da Serra", "3542305"}, + {"SP", "Regente Feij\u00f3", "3542404"}, + {"SP", "Regin\u00f3polis", "3542503"}, + {"SP", "Registro", "3542602"}, + {"SP", "Restinga", "3542701"}, + {"SP", "Ribeira", "3542800"}, + {"SP", "Ribeir\u00e3o Bonito", "3542909"}, + {"SP", "Ribeir\u00e3o Branco", "3543006"}, + {"SP", "Ribeir\u00e3o Corrente", "3543105"}, + {"SP", "Ribeir\u00e3o do Sul", "3543204"}, + {"SP", "Ribeir\u00e3o dos \u00cdndios", "3543238"}, + {"SP", "Ribeir\u00e3o Grande", "3543253"}, + {"SP", "Ribeir\u00e3o Pires", "3543303"}, + {"SP", "Ribeir\u00e3o Preto", "3543402"}, + {"SP", "Rifaina", "3543600"}, + {"SP", "Rinc\u00e3o", "3543709"}, + {"SP", "Rin\u00f3polis", "3543808"}, + {"SP", "Rio Claro", "3543907"}, + {"SP", "Rio das Pedras", "3544004"}, + {"SP", "Rio Grande da Serra", "3544103"}, + {"SP", "Riol\u00e2ndia", "3544202"}, + {"SP", "Riversul", "3543501"}, + {"SP", "Rosana", "3544251"}, + {"SP", "Roseira", "3544301"}, + {"SP", "Rubi\u00e1cea", "3544400"}, + {"SP", "Rubin\u00e9ia", "3544509"}, + {"SP", "Sabino", "3544608"}, + {"SP", "Sagres", "3544707"}, + {"SP", "Sales", "3544806"}, + {"SP", "Sales Oliveira", "3544905"}, + {"SP", "Sales\u00f3polis", "3545001"}, + {"SP", "Salmour\u00e3o", "3545100"}, + {"SP", "Saltinho", "3545159"}, + {"SP", "Salto", "3545209"}, + {"SP", "Salto de Pirapora", "3545308"}, + {"SP", "Salto Grande", "3545407"}, + {"SP", "Sandovalina", "3545506"}, + {"SP", "Santa Ad\u00e9lia", "3545605"}, + {"SP", "Santa Albertina", "3545704"}, + {"SP", "Santa B\u00e1rbara d'Oeste", "3545803"}, + {"SP", "Santa Branca", "3546009"}, + {"SP", "Santa Clara d'Oeste", "3546108"}, + {"SP", "Santa Cruz da Concei\u00e7\u00e3o", "3546207"}, + {"SP", "Santa Cruz da Esperan\u00e7a", "3546256"}, + {"SP", "Santa Cruz das Palmeiras", "3546306"}, + {"SP", "Santa Cruz do Rio Pardo", "3546405"}, + {"SP", "Santa Ernestina", "3546504"}, + {"SP", "Santa F\u00e9 do Sul", "3546603"}, + {"SP", "Santa Gertrudes", "3546702"}, + {"SP", "Santa Isabel", "3546801"}, + {"SP", "Santa L\u00facia", "3546900"}, + {"SP", "Santa Maria da Serra", "3547007"}, + {"SP", "Santa Mercedes", "3547106"}, + {"SP", "Santa Rita d'Oeste", "3547403"}, + {"SP", "Santa Rita do Passa Quatro", "3547502"}, + {"SP", "Santa Rosa de Viterbo", "3547601"}, + {"SP", "Santa Salete", "3547650"}, + {"SP", "Santana da Ponte Pensa", "3547205"}, + {"SP", "Santana de Parna\u00edba", "3547304"}, + {"SP", "Santo Anast\u00e1cio", "3547700"}, + {"SP", "Santo Andr\u00e9", "3547809"}, + {"SP", "Santo Ant\u00f4nio da Alegria", "3547908"}, + {"SP", "Santo Ant\u00f4nio de Posse", "3548005"}, + {"SP", "Santo Ant\u00f4nio do Aracangu\u00e1", "3548054"}, + {"SP", "Santo Ant\u00f4nio do Jardim", "3548104"}, + {"SP", "Santo Ant\u00f4nio do Pinhal", "3548203"}, + {"SP", "Santo Expedito", "3548302"}, + {"SP", "Sant\u00f3polis do Aguape\u00ed", "3548401"}, + {"SP", "Santos", "3548500"}, + {"SP", "S\u00e3o Bento do Sapuca\u00ed", "3548609"}, + {"SP", "S\u00e3o Bernardo do Campo", "3548708"}, + {"SP", "S\u00e3o Caetano do Sul", "3548807"}, + {"SP", "S\u00e3o Carlos", "3548906"}, + {"SP", "S\u00e3o Francisco", "3549003"}, + {"SP", "S\u00e3o Jo\u00e3o da Boa Vista", "3549102"}, + {"SP", "S\u00e3o Jo\u00e3o das Duas Pontes", "3549201"}, + {"SP", "S\u00e3o Jo\u00e3o de Iracema", "3549250"}, + {"SP", "S\u00e3o Jo\u00e3o do Pau d'Alho", "3549300"}, + {"SP", "S\u00e3o Joaquim da Barra", "3549409"}, + {"SP", "S\u00e3o Jos\u00e9 da Bela Vista", "3549508"}, + {"SP", "S\u00e3o Jos\u00e9 do Barreiro", "3549607"}, + {"SP", "S\u00e3o Jos\u00e9 do Rio Pardo", "3549706"}, + {"SP", "S\u00e3o Jos\u00e9 do Rio Preto", "3549805"}, + {"SP", "S\u00e3o Jos\u00e9 dos Campos", "3549904"}, + {"SP", "S\u00e3o Louren\u00e7o da Serra", "3549953"}, + {"SP", "S\u00e3o Luiz do Paraitinga", "3550001"}, + {"SP", "S\u00e3o Manuel", "3550100"}, + {"SP", "S\u00e3o Miguel Arcanjo", "3550209"}, + {"SP", "S\u00e3o Paulo", "3550308"}, + {"SP", "S\u00e3o Pedro", "3550407"}, + {"SP", "S\u00e3o Pedro do Turvo", "3550506"}, + {"SP", "S\u00e3o Roque", "3550605"}, + {"SP", "S\u00e3o Sebasti\u00e3o", "3550704"}, + {"SP", "S\u00e3o Sebasti\u00e3o da Grama", "3550803"}, + {"SP", "S\u00e3o Sim\u00e3o", "3550902"}, + {"SP", "S\u00e3o Vicente", "3551009"}, + {"SP", "Sarapu\u00ed", "3551108"}, + {"SP", "Sarutai\u00e1", "3551207"}, + {"SP", "Sebastian\u00f3polis do Sul", "3551306"}, + {"SP", "Serra Azul", "3551405"}, + {"SP", "Serra Negra", "3551603"}, + {"SP", "Serrana", "3551504"}, + {"SP", "Sert\u00e3ozinho", "3551702"}, + {"SP", "Sete Barras", "3551801"}, + {"SP", "Sever\u00ednia", "3551900"}, + {"SP", "Silveiras", "3552007"}, + {"SP", "Socorro", "3552106"}, + {"SP", "Sorocaba", "3552205"}, + {"SP", "Sud Mennucci", "3552304"}, + {"SP", "Sumar\u00e9", "3552403"}, + {"SP", "Suzan\u00e1polis", "3552551"}, + {"SP", "Suzano", "3552502"}, + {"SP", "Tabapu\u00e3", "3552601"}, + {"SP", "Tabatinga", "3552700"}, + {"SP", "Tabo\u00e3o da Serra", "3552809"}, + {"SP", "Taciba", "3552908"}, + {"SP", "Tagua\u00ed", "3553005"}, + {"SP", "Taia\u00e7u", "3553104"}, + {"SP", "Tai\u00fava", "3553203"}, + {"SP", "Tamba\u00fa", "3553302"}, + {"SP", "Tanabi", "3553401"}, + {"SP", "Tapira\u00ed", "3553500"}, + {"SP", "Tapiratiba", "3553609"}, + {"SP", "Taquaral", "3553658"}, + {"SP", "Taquaritinga", "3553708"}, + {"SP", "Taquarituba", "3553807"}, + {"SP", "Taquariva\u00ed", "3553856"}, + {"SP", "Tarabai", "3553906"}, + {"SP", "Tarum\u00e3", "3553955"}, + {"SP", "Tatu\u00ed", "3554003"}, + {"SP", "Taubat\u00e9", "3554102"}, + {"SP", "Tejup\u00e1", "3554201"}, + {"SP", "Teodoro Sampaio", "3554300"}, + {"SP", "Terra Roxa", "3554409"}, + {"SP", "Tiet\u00ea", "3554508"}, + {"SP", "Timburi", "3554607"}, + {"SP", "Torre de Pedra", "3554656"}, + {"SP", "Torrinha", "3554706"}, + {"SP", "Trabiju", "3554755"}, + {"SP", "Trememb\u00e9", "3554805"}, + {"SP", "Tr\u00eas Fronteiras", "3554904"}, + {"SP", "Tuiuti", "3554953"}, + {"SP", "Tup\u00e3", "3555000"}, + {"SP", "Tupi Paulista", "3555109"}, + {"SP", "Turi\u00faba", "3555208"}, + {"SP", "Turmalina", "3555307"}, + {"SP", "Ubarana", "3555356"}, + {"SP", "Ubatuba", "3555406"}, + {"SP", "Ubirajara", "3555505"}, + {"SP", "Uchoa", "3555604"}, + {"SP", "Uni\u00e3o Paulista", "3555703"}, + {"SP", "Ur\u00e2nia", "3555802"}, + {"SP", "Uru", "3555901"}, + {"SP", "Urup\u00eas", "3556008"}, + {"SP", "Valentim Gentil", "3556107"}, + {"SP", "Valinhos", "3556206"}, + {"SP", "Valpara\u00edso", "3556305"}, + {"SP", "Vargem", "3556354"}, + {"SP", "Vargem Grande do Sul", "3556404"}, + {"SP", "Vargem Grande Paulista", "3556453"}, + {"SP", "V\u00e1rzea Paulista", "3556503"}, + {"SP", "Vera Cruz", "3556602"}, + {"SP", "Vinhedo", "3556701"}, + {"SP", "Viradouro", "3556800"}, + {"SP", "Vista Alegre do Alto", "3556909"}, + {"SP", "Vit\u00f3ria Brasil", "3556958"}, + {"SP", "Votorantim", "3557006"}, + {"SP", "Votuporanga", "3557105"}, + {"SP", "Zacarias", "3557154"}, + {"SE", "Amparo do S\u00e3o Francisco", "2800100"}, + {"SE", "Aquidab\u00e3", "2800209"}, + {"SE", "Aracaju", "2800308"}, + {"SE", "Arau\u00e1", "2800407"}, + {"SE", "Areia Branca", "2800506"}, + {"SE", "Barra dos Coqueiros", "2800605"}, + {"SE", "Boquim", "2800670"}, + {"SE", "Brejo Grande", "2800704"}, + {"SE", "Campo do Brito", "2801009"}, + {"SE", "Canhoba", "2801108"}, + {"SE", "Canind\u00e9 de S\u00e3o Francisco", "2801207"}, + {"SE", "Capela", "2801306"}, + {"SE", "Carira", "2801405"}, + {"SE", "Carm\u00f3polis", "2801504"}, + {"SE", "Cedro de S\u00e3o Jo\u00e3o", "2801603"}, + {"SE", "Cristin\u00e1polis", "2801702"}, + {"SE", "Cumbe", "2801900"}, + {"SE", "Divina Pastora", "2802007"}, + {"SE", "Est\u00e2ncia", "2802106"}, + {"SE", "Feira Nova", "2802205"}, + {"SE", "Frei Paulo", "2802304"}, + {"SE", "Gararu", "2802403"}, + {"SE", "General Maynard", "2802502"}, + {"SE", "Graccho Cardoso", "2802601"}, + {"SE", "Ilha das Flores", "2802700"}, + {"SE", "Indiaroba", "2802809"}, + {"SE", "Itabaiana", "2802908"}, + {"SE", "Itabaianinha", "2803005"}, + {"SE", "Itabi", "2803104"}, + {"SE", "Itaporanga d'Ajuda", "2803203"}, + {"SE", "Japaratuba", "2803302"}, + {"SE", "Japoat\u00e3", "2803401"}, + {"SE", "Lagarto", "2803500"}, + {"SE", "Laranjeiras", "2803609"}, + {"SE", "Macambira", "2803708"}, + {"SE", "Malhada dos Bois", "2803807"}, + {"SE", "Malhador", "2803906"}, + {"SE", "Maruim", "2804003"}, + {"SE", "Moita Bonita", "2804102"}, + {"SE", "Monte Alegre de Sergipe", "2804201"}, + {"SE", "Muribeca", "2804300"}, + {"SE", "Ne\u00f3polis", "2804409"}, + {"SE", "Nossa Senhora Aparecida", "2804458"}, + {"SE", "Nossa Senhora da Gl\u00f3ria", "2804508"}, + {"SE", "Nossa Senhora das Dores", "2804607"}, + {"SE", "Nossa Senhora de Lourdes", "2804706"}, + {"SE", "Nossa Senhora do Socorro", "2804805"}, + {"SE", "Pacatuba", "2804904"}, + {"SE", "Pedra Mole", "2805000"}, + {"SE", "Pedrinhas", "2805109"}, + {"SE", "Pinh\u00e3o", "2805208"}, + {"SE", "Pirambu", "2805307"}, + {"SE", "Po\u00e7o Redondo", "2805406"}, + {"SE", "Po\u00e7o Verde", "2805505"}, + {"SE", "Porto da Folha", "2805604"}, + {"SE", "Propri\u00e1", "2805703"}, + {"SE", "Riach\u00e3o do Dantas", "2805802"}, + {"SE", "Riachuelo", "2805901"}, + {"SE", "Ribeir\u00f3polis", "2806008"}, + {"SE", "Ros\u00e1rio do Catete", "2806107"}, + {"SE", "Salgado", "2806206"}, + {"SE", "Santa Luzia do Itanhy", "2806305"}, + {"SE", "Santa Rosa de Lima", "2806503"}, + {"SE", "Santana do S\u00e3o Francisco", "2806404"}, + {"SE", "Santo Amaro das Brotas", "2806602"}, + {"SE", "S\u00e3o Crist\u00f3v\u00e3o", "2806701"}, + {"SE", "S\u00e3o Domingos", "2806800"}, + {"SE", "S\u00e3o Francisco", "2806909"}, + {"SE", "S\u00e3o Miguel do Aleixo", "2807006"}, + {"SE", "Sim\u00e3o Dias", "2807105"}, + {"SE", "Siriri", "2807204"}, + {"SE", "Telha", "2807303"}, + {"SE", "Tobias Barreto", "2807402"}, + {"SE", "Tomar do Geru", "2807501"}, + {"SE", "Umba\u00faba", "2807600"}, + {"TO", "Abreul\u00e2ndia", "1700251"}, + {"TO", "Aguiarn\u00f3polis", "1700301"}, + {"TO", "Alian\u00e7a do Tocantins", "1700350"}, + {"TO", "Almas", "1700400"}, + {"TO", "Alvorada", "1700707"}, + {"TO", "Anan\u00e1s", "1701002"}, + {"TO", "Angico", "1701051"}, + {"TO", "Aparecida do Rio Negro", "1701101"}, + {"TO", "Aragominas", "1701309"}, + {"TO", "Araguacema", "1701903"}, + {"TO", "Aragua\u00e7u", "1702000"}, + {"TO", "Aragua\u00edna", "1702109"}, + {"TO", "Araguan\u00e3", "1702158"}, + {"TO", "Araguatins", "1702208"}, + {"TO", "Arapoema", "1702307"}, + {"TO", "Arraias", "1702406"}, + {"TO", "Augustin\u00f3polis", "1702554"}, + {"TO", "Aurora do Tocantins", "1702703"}, + {"TO", "Axix\u00e1 do Tocantins", "1702901"}, + {"TO", "Baba\u00e7ul\u00e2ndia", "1703008"}, + {"TO", "Bandeirantes do Tocantins", "1703057"}, + {"TO", "Barra do Ouro", "1703073"}, + {"TO", "Barrol\u00e2ndia", "1703107"}, + {"TO", "Bernardo Say\u00e3o", "1703206"}, + {"TO", "Bom Jesus do Tocantins", "1703305"}, + {"TO", "Brasil\u00e2ndia do Tocantins", "1703602"}, + {"TO", "Brejinho de Nazar\u00e9", "1703701"}, + {"TO", "Buriti do Tocantins", "1703800"}, + {"TO", "Cachoeirinha", "1703826"}, + {"TO", "Campos Lindos", "1703842"}, + {"TO", "Cariri do Tocantins", "1703867"}, + {"TO", "Carmol\u00e2ndia", "1703883"}, + {"TO", "Carrasco Bonito", "1703891"}, + {"TO", "Caseara", "1703909"}, + {"TO", "Centen\u00e1rio", "1704105"}, + {"TO", "Chapada da Natividade", "1705102"}, + {"TO", "Chapada de Areia", "1704600"}, + {"TO", "Colinas do Tocantins", "1705508"}, + {"TO", "Colm\u00e9ia", "1716703"}, + {"TO", "Combinado", "1705557"}, + {"TO", "Concei\u00e7\u00e3o do Tocantins", "1705607"}, + {"TO", "Couto Magalh\u00e3es", "1706001"}, + {"TO", "Cristal\u00e2ndia", "1706100"}, + {"TO", "Crix\u00e1s do Tocantins", "1706258"}, + {"TO", "Darcin\u00f3polis", "1706506"}, + {"TO", "Dian\u00f3polis", "1707009"}, + {"TO", "Divin\u00f3polis do Tocantins", "1707108"}, + {"TO", "Dois Irm\u00e3os do Tocantins", "1707207"}, + {"TO", "Duer\u00e9", "1707306"}, + {"TO", "Esperantina", "1707405"}, + {"TO", "F\u00e1tima", "1707553"}, + {"TO", "Figueir\u00f3polis", "1707652"}, + {"TO", "Filad\u00e9lfia", "1707702"}, + {"TO", "Formoso do Araguaia", "1708205"}, + {"TO", "Goianorte", "1708304"}, + {"TO", "Goiatins", "1709005"}, + {"TO", "Guara\u00ed", "1709302"}, + {"TO", "Gurupi", "1709500"}, + {"TO", "Ipueiras", "1709807"}, + {"TO", "Itacaj\u00e1", "1710508"}, + {"TO", "Itaguatins", "1710706"}, + {"TO", "Itapiratins", "1710904"}, + {"TO", "Itapor\u00e3 do Tocantins", "1711100"}, + {"TO", "Ja\u00fa do Tocantins", "1711506"}, + {"TO", "Juarina", "1711803"}, + {"TO", "Lagoa da Confus\u00e3o", "1711902"}, + {"TO", "Lagoa do Tocantins", "1711951"}, + {"TO", "Lajeado", "1712009"}, + {"TO", "Lavandeira", "1712157"}, + {"TO", "Lizarda", "1712405"}, + {"TO", "Luzin\u00f3polis", "1712454"}, + {"TO", "Marian\u00f3polis do Tocantins", "1712504"}, + {"TO", "Mateiros", "1712702"}, + {"TO", "Mauril\u00e2ndia do Tocantins", "1712801"}, + {"TO", "Miracema do Tocantins", "1713205"}, + {"TO", "Miranorte", "1713304"}, + {"TO", "Monte do Carmo", "1713601"}, + {"TO", "Monte Santo do Tocantins", "1713700"}, + {"TO", "Muricil\u00e2ndia", "1713957"}, + {"TO", "Natividade", "1714203"}, + {"TO", "Nazar\u00e9", "1714302"}, + {"TO", "Nova Olinda", "1714880"}, + {"TO", "Nova Rosal\u00e2ndia", "1715002"}, + {"TO", "Novo Acordo", "1715101"}, + {"TO", "Novo Alegre", "1715150"}, + {"TO", "Novo Jardim", "1715259"}, + {"TO", "Oliveira de F\u00e1tima", "1715507"}, + {"TO", "Palmas", "1721000"}, + {"TO", "Palmeirante", "1715705"}, + {"TO", "Palmeiras do Tocantins", "1713809"}, + {"TO", "Palmeir\u00f3polis", "1715754"}, + {"TO", "Para\u00edso do Tocantins", "1716109"}, + {"TO", "Paran\u00e3", "1716208"}, + {"TO", "Pau D'Arco", "1716307"}, + {"TO", "Pedro Afonso", "1716505"}, + {"TO", "Peixe", "1716604"}, + {"TO", "Pequizeiro", "1716653"}, + {"TO", "Pindorama do Tocantins", "1717008"}, + {"TO", "Piraqu\u00ea", "1717206"}, + {"TO", "Pium", "1717503"}, + {"TO", "Ponte Alta do Bom Jesus", "1717800"}, + {"TO", "Ponte Alta do Tocantins", "1717909"}, + {"TO", "Porto Alegre do Tocantins", "1718006"}, + {"TO", "Porto Nacional", "1718204"}, + {"TO", "Praia Norte", "1718303"}, + {"TO", "Presidente Kennedy", "1718402"}, + {"TO", "Pugmil", "1718451"}, + {"TO", "Recursol\u00e2ndia", "1718501"}, + {"TO", "Riachinho", "1718550"}, + {"TO", "Rio da Concei\u00e7\u00e3o", "1718659"}, + {"TO", "Rio dos Bois", "1718709"}, + {"TO", "Rio Sono", "1718758"}, + {"TO", "Sampaio", "1718808"}, + {"TO", "Sandol\u00e2ndia", "1718840"}, + {"TO", "Santa F\u00e9 do Araguaia", "1718865"}, + {"TO", "Santa Maria do Tocantins", "1718881"}, + {"TO", "Santa Rita do Tocantins", "1718899"}, + {"TO", "Santa Rosa do Tocantins", "1718907"}, + {"TO", "Santa Tereza do Tocantins", "1719004"}, + {"TO", "Santa Terezinha do Tocantins", "1720002"}, + {"TO", "S\u00e3o Bento do Tocantins", "1720101"}, + {"TO", "S\u00e3o F\u00e9lix do Tocantins", "1720150"}, + {"TO", "S\u00e3o Miguel do Tocantins", "1720200"}, + {"TO", "S\u00e3o Salvador do Tocantins", "1720259"}, + {"TO", "S\u00e3o Sebasti\u00e3o do Tocantins", "1720309"}, + {"TO", "S\u00e3o Val\u00e9rio", "1720499"}, + {"TO", "Silvan\u00f3polis", "1720655"}, + {"TO", "S\u00edtio Novo do Tocantins", "1720804"}, + {"TO", "Sucupira", "1720853"}, + {"TO", "Taboc\u00e3o", "1708254"}, + {"TO", "Taguatinga", "1720903"}, + {"TO", "Taipas do Tocantins", "1720937"}, + {"TO", "Talism\u00e3", "1720978"}, + {"TO", "Tocant\u00ednia", "1721109"}, + {"TO", "Tocantin\u00f3polis", "1721208"}, + {"TO", "Tupirama", "1721257"}, + {"TO", "Tupiratins", "1721307"}, + {"TO", "Wanderl\u00e2ndia", "1722081"}, + {"TO", "Xambio\u00e1", "1722107"}, + }, + []runtime.DataGroup{ + {Key: "AC", Rows: []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21}}, + {Key: "AL", Rows: []int{22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123}}, + {Key: "AP", Rows: []int{124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139}}, + {Key: "AM", Rows: []int{140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201}}, + {Key: "BA", Rows: []int{202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, 443, 444, 445, 446, 447, 448, 449, 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, 495, 496, 497, 498, 499, 500, 501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, 519, 520, 521, 522, 523, 524, 525, 526, 527, 528, 529, 530, 531, 532, 533, 534, 535, 536, 537, 538, 539, 540, 541, 542, 543, 544, 545, 546, 547, 548, 549, 550, 551, 552, 553, 554, 555, 556, 557, 558, 559, 560, 561, 562, 563, 564, 565, 566, 567, 568, 569, 570, 571, 572, 573, 574, 575, 576, 577, 578, 579, 580, 581, 582, 583, 584, 585, 586, 587, 588, 589, 590, 591, 592, 593, 594, 595, 596, 597, 598, 599, 600, 601, 602, 603, 604, 605, 606, 607, 608, 609, 610, 611, 612, 613, 614, 615, 616, 617, 618}}, + {Key: "CE", Rows: []int{619, 620, 621, 622, 623, 624, 625, 626, 627, 628, 629, 630, 631, 632, 633, 634, 635, 636, 637, 638, 639, 640, 641, 642, 643, 644, 645, 646, 647, 648, 649, 650, 651, 652, 653, 654, 655, 656, 657, 658, 659, 660, 661, 662, 663, 664, 665, 666, 667, 668, 669, 670, 671, 672, 673, 674, 675, 676, 677, 678, 679, 680, 681, 682, 683, 684, 685, 686, 687, 688, 689, 690, 691, 692, 693, 694, 695, 696, 697, 698, 699, 700, 701, 702, 703, 704, 705, 706, 707, 708, 709, 710, 711, 712, 713, 714, 715, 716, 717, 718, 719, 720, 721, 722, 723, 724, 725, 726, 727, 728, 729, 730, 731, 732, 733, 734, 735, 736, 737, 738, 739, 740, 741, 742, 743, 744, 745, 746, 747, 748, 749, 750, 751, 752, 753, 754, 755, 756, 757, 758, 759, 760, 761, 762, 763, 764, 765, 766, 767, 768, 769, 770, 771, 772, 773, 774, 775, 776, 777, 778, 779, 780, 781, 782, 783, 784, 785, 786, 787, 788, 789, 790, 791, 792, 793, 794, 795, 796, 797, 798, 799, 800, 801, 802}}, + {Key: "DF", Rows: []int{803}}, + {Key: "ES", Rows: []int{804, 805, 806, 807, 808, 809, 810, 811, 812, 813, 814, 815, 816, 817, 818, 819, 820, 821, 822, 823, 824, 825, 826, 827, 828, 829, 830, 831, 832, 833, 834, 835, 836, 837, 838, 839, 840, 841, 842, 843, 844, 845, 846, 847, 848, 849, 850, 851, 852, 853, 854, 855, 856, 857, 858, 859, 860, 861, 862, 863, 864, 865, 866, 867, 868, 869, 870, 871, 872, 873, 874, 875, 876, 877, 878, 879, 880, 881}}, + {Key: "GO", Rows: []int{882, 883, 884, 885, 886, 887, 888, 889, 890, 891, 892, 893, 894, 895, 896, 897, 898, 899, 900, 901, 902, 903, 904, 905, 906, 907, 908, 909, 910, 911, 912, 913, 914, 915, 916, 917, 918, 919, 920, 921, 922, 923, 924, 925, 926, 927, 928, 929, 930, 931, 932, 933, 934, 935, 936, 937, 938, 939, 940, 941, 942, 943, 944, 945, 946, 947, 948, 949, 950, 951, 952, 953, 954, 955, 956, 957, 958, 959, 960, 961, 962, 963, 964, 965, 966, 967, 968, 969, 970, 971, 972, 973, 974, 975, 976, 977, 978, 979, 980, 981, 982, 983, 984, 985, 986, 987, 988, 989, 990, 991, 992, 993, 994, 995, 996, 997, 998, 999, 1000, 1001, 1002, 1003, 1004, 1005, 1006, 1007, 1008, 1009, 1010, 1011, 1012, 1013, 1014, 1015, 1016, 1017, 1018, 1019, 1020, 1021, 1022, 1023, 1024, 1025, 1026, 1027, 1028, 1029, 1030, 1031, 1032, 1033, 1034, 1035, 1036, 1037, 1038, 1039, 1040, 1041, 1042, 1043, 1044, 1045, 1046, 1047, 1048, 1049, 1050, 1051, 1052, 1053, 1054, 1055, 1056, 1057, 1058, 1059, 1060, 1061, 1062, 1063, 1064, 1065, 1066, 1067, 1068, 1069, 1070, 1071, 1072, 1073, 1074, 1075, 1076, 1077, 1078, 1079, 1080, 1081, 1082, 1083, 1084, 1085, 1086, 1087, 1088, 1089, 1090, 1091, 1092, 1093, 1094, 1095, 1096, 1097, 1098, 1099, 1100, 1101, 1102, 1103, 1104, 1105, 1106, 1107, 1108, 1109, 1110, 1111, 1112, 1113, 1114, 1115, 1116, 1117, 1118, 1119, 1120, 1121, 1122, 1123, 1124, 1125, 1126, 1127}}, + {Key: "MA", Rows: []int{1128, 1129, 1130, 1131, 1132, 1133, 1134, 1135, 1136, 1137, 1138, 1139, 1140, 1141, 1142, 1143, 1144, 1145, 1146, 1147, 1148, 1149, 1150, 1151, 1152, 1153, 1154, 1155, 1156, 1157, 1158, 1159, 1160, 1161, 1162, 1163, 1164, 1165, 1166, 1167, 1168, 1169, 1170, 1171, 1172, 1173, 1174, 1175, 1176, 1177, 1178, 1179, 1180, 1181, 1182, 1183, 1184, 1185, 1186, 1187, 1188, 1189, 1190, 1191, 1192, 1193, 1194, 1195, 1196, 1197, 1198, 1199, 1200, 1201, 1202, 1203, 1204, 1205, 1206, 1207, 1208, 1209, 1210, 1211, 1212, 1213, 1214, 1215, 1216, 1217, 1218, 1219, 1220, 1221, 1222, 1223, 1224, 1225, 1226, 1227, 1228, 1229, 1230, 1231, 1232, 1233, 1234, 1235, 1236, 1237, 1238, 1239, 1240, 1241, 1242, 1243, 1244, 1245, 1246, 1247, 1248, 1249, 1250, 1251, 1252, 1253, 1254, 1255, 1256, 1257, 1258, 1259, 1260, 1261, 1262, 1263, 1264, 1265, 1266, 1267, 1268, 1269, 1270, 1271, 1272, 1273, 1274, 1275, 1276, 1277, 1278, 1279, 1280, 1281, 1282, 1283, 1284, 1285, 1286, 1287, 1288, 1289, 1290, 1291, 1292, 1293, 1294, 1295, 1296, 1297, 1298, 1299, 1300, 1301, 1302, 1303, 1304, 1305, 1306, 1307, 1308, 1309, 1310, 1311, 1312, 1313, 1314, 1315, 1316, 1317, 1318, 1319, 1320, 1321, 1322, 1323, 1324, 1325, 1326, 1327, 1328, 1329, 1330, 1331, 1332, 1333, 1334, 1335, 1336, 1337, 1338, 1339, 1340, 1341, 1342, 1343, 1344}}, + {Key: "MT", Rows: []int{1345, 1346, 1347, 1348, 1349, 1350, 1351, 1352, 1353, 1354, 1355, 1356, 1357, 1358, 1359, 1360, 1361, 1362, 1363, 1364, 1365, 1366, 1367, 1368, 1369, 1370, 1371, 1372, 1373, 1374, 1375, 1376, 1377, 1378, 1379, 1380, 1381, 1382, 1383, 1384, 1385, 1386, 1387, 1388, 1389, 1390, 1391, 1392, 1393, 1394, 1395, 1396, 1397, 1398, 1399, 1400, 1401, 1402, 1403, 1404, 1405, 1406, 1407, 1408, 1409, 1410, 1411, 1412, 1413, 1414, 1415, 1416, 1417, 1418, 1419, 1420, 1421, 1422, 1423, 1424, 1425, 1426, 1427, 1428, 1429, 1430, 1431, 1432, 1433, 1434, 1435, 1436, 1437, 1438, 1439, 1440, 1441, 1442, 1443, 1444, 1445, 1446, 1447, 1448, 1449, 1450, 1451, 1452, 1453, 1454, 1455, 1456, 1457, 1458, 1459, 1460, 1461, 1462, 1463, 1464, 1465, 1466, 1467, 1468, 1469, 1470, 1471, 1472, 1473, 1474, 1475, 1476, 1477, 1478, 1479, 1480, 1481, 1482, 1483, 1484, 1485, 1486}}, + {Key: "MS", Rows: []int{1487, 1488, 1489, 1490, 1491, 1492, 1493, 1494, 1495, 1496, 1497, 1498, 1499, 1500, 1501, 1502, 1503, 1504, 1505, 1506, 1507, 1508, 1509, 1510, 1511, 1512, 1513, 1514, 1515, 1516, 1517, 1518, 1519, 1520, 1521, 1522, 1523, 1524, 1525, 1526, 1527, 1528, 1529, 1530, 1531, 1532, 1533, 1534, 1535, 1536, 1537, 1538, 1539, 1540, 1541, 1542, 1543, 1544, 1545, 1546, 1547, 1548, 1549, 1550, 1551, 1552, 1553, 1554, 1555, 1556, 1557, 1558, 1559, 1560, 1561, 1562, 1563, 1564, 1565}}, + {Key: "MG", Rows: []int{1566, 1567, 1568, 1569, 1570, 1571, 1572, 1573, 1574, 1575, 1576, 1577, 1578, 1579, 1580, 1581, 1582, 1583, 1584, 1585, 1586, 1587, 1588, 1589, 1590, 1591, 1592, 1593, 1594, 1595, 1596, 1597, 1598, 1599, 1600, 1601, 1602, 1603, 1604, 1605, 1606, 1607, 1608, 1609, 1610, 1611, 1612, 1613, 1614, 1615, 1616, 1617, 1618, 1619, 1620, 1621, 1622, 1623, 1624, 1625, 1626, 1627, 1628, 1629, 1630, 1631, 1632, 1633, 1634, 1635, 1636, 1637, 1638, 1639, 1640, 1641, 1642, 1643, 1644, 1645, 1646, 1647, 1648, 1649, 1650, 1651, 1652, 1653, 1654, 1655, 1656, 1657, 1658, 1659, 1660, 1661, 1662, 1663, 1664, 1665, 1666, 1667, 1668, 1669, 1670, 1671, 1672, 1673, 1674, 1675, 1676, 1677, 1678, 1679, 1680, 1681, 1682, 1683, 1684, 1685, 1686, 1687, 1688, 1689, 1690, 1691, 1692, 1693, 1694, 1695, 1696, 1697, 1698, 1699, 1700, 1701, 1702, 1703, 1704, 1705, 1706, 1707, 1708, 1709, 1710, 1711, 1712, 1713, 1714, 1715, 1716, 1717, 1718, 1719, 1720, 1721, 1722, 1723, 1724, 1725, 1726, 1727, 1728, 1729, 1730, 1731, 1732, 1733, 1734, 1735, 1736, 1737, 1738, 1739, 1740, 1741, 1742, 1743, 1744, 1745, 1746, 1747, 1748, 1749, 1750, 1751, 1752, 1753, 1754, 1755, 1756, 1757, 1758, 1759, 1760, 1761, 1762, 1763, 1764, 1765, 1766, 1767, 1768, 1769, 1770, 1771, 1772, 1773, 1774, 1775, 1776, 1777, 1778, 1779, 1780, 1781, 1782, 1783, 1784, 1785, 1786, 1787, 1788, 1789, 1790, 1791, 1792, 1793, 1794, 1795, 1796, 1797, 1798, 1799, 1800, 1801, 1802, 1803, 1804, 1805, 1806, 1807, 1808, 1809, 1810, 1811, 1812, 1813, 1814, 1815, 1816, 1817, 1818, 1819, 1820, 1821, 1822, 1823, 1824, 1825, 1826, 1827, 1828, 1829, 1830, 1831, 1832, 1833, 1834, 1835, 1836, 1837, 1838, 1839, 1840, 1841, 1842, 1843, 1844, 1845, 1846, 1847, 1848, 1849, 1850, 1851, 1852, 1853, 1854, 1855, 1856, 1857, 1858, 1859, 1860, 1861, 1862, 1863, 1864, 1865, 1866, 1867, 1868, 1869, 1870, 1871, 1872, 1873, 1874, 1875, 1876, 1877, 1878, 1879, 1880, 1881, 1882, 1883, 1884, 1885, 1886, 1887, 1888, 1889, 1890, 1891, 1892, 1893, 1894, 1895, 1896, 1897, 1898, 1899, 1900, 1901, 1902, 1903, 1904, 1905, 1906, 1907, 1908, 1909, 1910, 1911, 1912, 1913, 1914, 1915, 1916, 1917, 1918, 1919, 1920, 1921, 1922, 1923, 1924, 1925, 1926, 1927, 1928, 1929, 1930, 1931, 1932, 1933, 1934, 1935, 1936, 1937, 1938, 1939, 1940, 1941, 1942, 1943, 1944, 1945, 1946, 1947, 1948, 1949, 1950, 1951, 1952, 1953, 1954, 1955, 1956, 1957, 1958, 1959, 1960, 1961, 1962, 1963, 1964, 1965, 1966, 1967, 1968, 1969, 1970, 1971, 1972, 1973, 1974, 1975, 1976, 1977, 1978, 1979, 1980, 1981, 1982, 1983, 1984, 1985, 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020, 2021, 2022, 2023, 2024, 2025, 2026, 2027, 2028, 2029, 2030, 2031, 2032, 2033, 2034, 2035, 2036, 2037, 2038, 2039, 2040, 2041, 2042, 2043, 2044, 2045, 2046, 2047, 2048, 2049, 2050, 2051, 2052, 2053, 2054, 2055, 2056, 2057, 2058, 2059, 2060, 2061, 2062, 2063, 2064, 2065, 2066, 2067, 2068, 2069, 2070, 2071, 2072, 2073, 2074, 2075, 2076, 2077, 2078, 2079, 2080, 2081, 2082, 2083, 2084, 2085, 2086, 2087, 2088, 2089, 2090, 2091, 2092, 2093, 2094, 2095, 2096, 2097, 2098, 2099, 2100, 2101, 2102, 2103, 2104, 2105, 2106, 2107, 2108, 2109, 2110, 2111, 2112, 2113, 2114, 2115, 2116, 2117, 2118, 2119, 2120, 2121, 2122, 2123, 2124, 2125, 2126, 2127, 2128, 2129, 2130, 2131, 2132, 2133, 2134, 2135, 2136, 2137, 2138, 2139, 2140, 2141, 2142, 2143, 2144, 2145, 2146, 2147, 2148, 2149, 2150, 2151, 2152, 2153, 2154, 2155, 2156, 2157, 2158, 2159, 2160, 2161, 2162, 2163, 2164, 2165, 2166, 2167, 2168, 2169, 2170, 2171, 2172, 2173, 2174, 2175, 2176, 2177, 2178, 2179, 2180, 2181, 2182, 2183, 2184, 2185, 2186, 2187, 2188, 2189, 2190, 2191, 2192, 2193, 2194, 2195, 2196, 2197, 2198, 2199, 2200, 2201, 2202, 2203, 2204, 2205, 2206, 2207, 2208, 2209, 2210, 2211, 2212, 2213, 2214, 2215, 2216, 2217, 2218, 2219, 2220, 2221, 2222, 2223, 2224, 2225, 2226, 2227, 2228, 2229, 2230, 2231, 2232, 2233, 2234, 2235, 2236, 2237, 2238, 2239, 2240, 2241, 2242, 2243, 2244, 2245, 2246, 2247, 2248, 2249, 2250, 2251, 2252, 2253, 2254, 2255, 2256, 2257, 2258, 2259, 2260, 2261, 2262, 2263, 2264, 2265, 2266, 2267, 2268, 2269, 2270, 2271, 2272, 2273, 2274, 2275, 2276, 2277, 2278, 2279, 2280, 2281, 2282, 2283, 2284, 2285, 2286, 2287, 2288, 2289, 2290, 2291, 2292, 2293, 2294, 2295, 2296, 2297, 2298, 2299, 2300, 2301, 2302, 2303, 2304, 2305, 2306, 2307, 2308, 2309, 2310, 2311, 2312, 2313, 2314, 2315, 2316, 2317, 2318, 2319, 2320, 2321, 2322, 2323, 2324, 2325, 2326, 2327, 2328, 2329, 2330, 2331, 2332, 2333, 2334, 2335, 2336, 2337, 2338, 2339, 2340, 2341, 2342, 2343, 2344, 2345, 2346, 2347, 2348, 2349, 2350, 2351, 2352, 2353, 2354, 2355, 2356, 2357, 2358, 2359, 2360, 2361, 2362, 2363, 2364, 2365, 2366, 2367, 2368, 2369, 2370, 2371, 2372, 2373, 2374, 2375, 2376, 2377, 2378, 2379, 2380, 2381, 2382, 2383, 2384, 2385, 2386, 2387, 2388, 2389, 2390, 2391, 2392, 2393, 2394, 2395, 2396, 2397, 2398, 2399, 2400, 2401, 2402, 2403, 2404, 2405, 2406, 2407, 2408, 2409, 2410, 2411, 2412, 2413, 2414, 2415, 2416, 2417, 2418}}, + {Key: "PA", Rows: []int{2419, 2420, 2421, 2422, 2423, 2424, 2425, 2426, 2427, 2428, 2429, 2430, 2431, 2432, 2433, 2434, 2435, 2436, 2437, 2438, 2439, 2440, 2441, 2442, 2443, 2444, 2445, 2446, 2447, 2448, 2449, 2450, 2451, 2452, 2453, 2454, 2455, 2456, 2457, 2458, 2459, 2460, 2461, 2462, 2463, 2464, 2465, 2466, 2467, 2468, 2469, 2470, 2471, 2472, 2473, 2474, 2475, 2476, 2477, 2478, 2479, 2480, 2481, 2482, 2483, 2484, 2485, 2486, 2487, 2488, 2489, 2490, 2491, 2492, 2493, 2494, 2495, 2496, 2497, 2498, 2499, 2500, 2501, 2502, 2503, 2504, 2505, 2506, 2507, 2508, 2509, 2510, 2511, 2512, 2513, 2514, 2515, 2516, 2517, 2518, 2519, 2520, 2521, 2522, 2523, 2524, 2525, 2526, 2527, 2528, 2529, 2530, 2531, 2532, 2533, 2534, 2535, 2536, 2537, 2538, 2539, 2540, 2541, 2542, 2543, 2544, 2545, 2546, 2547, 2548, 2549, 2550, 2551, 2552, 2553, 2554, 2555, 2556, 2557, 2558, 2559, 2560, 2561, 2562}}, + {Key: "PB", Rows: []int{2563, 2564, 2565, 2566, 2567, 2568, 2569, 2570, 2571, 2572, 2573, 2574, 2575, 2576, 2577, 2578, 2579, 2580, 2581, 2582, 2583, 2584, 2585, 2586, 2587, 2588, 2589, 2590, 2591, 2592, 2593, 2594, 2595, 2596, 2597, 2598, 2599, 2600, 2601, 2602, 2603, 2604, 2605, 2606, 2607, 2608, 2609, 2610, 2611, 2612, 2613, 2614, 2615, 2616, 2617, 2618, 2619, 2620, 2621, 2622, 2623, 2624, 2625, 2626, 2627, 2628, 2629, 2630, 2631, 2632, 2633, 2634, 2635, 2636, 2637, 2638, 2639, 2640, 2641, 2642, 2643, 2644, 2645, 2646, 2647, 2648, 2649, 2650, 2651, 2652, 2653, 2654, 2655, 2656, 2657, 2658, 2659, 2660, 2661, 2662, 2663, 2664, 2665, 2666, 2667, 2668, 2669, 2670, 2671, 2672, 2673, 2674, 2675, 2676, 2677, 2678, 2679, 2680, 2681, 2682, 2683, 2684, 2685, 2686, 2687, 2688, 2689, 2690, 2691, 2692, 2693, 2694, 2695, 2696, 2697, 2698, 2699, 2700, 2701, 2702, 2703, 2704, 2705, 2706, 2707, 2708, 2709, 2710, 2711, 2712, 2713, 2714, 2715, 2716, 2717, 2718, 2719, 2720, 2721, 2722, 2723, 2724, 2725, 2726, 2727, 2728, 2729, 2730, 2731, 2732, 2733, 2734, 2735, 2736, 2737, 2738, 2739, 2740, 2741, 2742, 2743, 2744, 2745, 2746, 2747, 2748, 2749, 2750, 2751, 2752, 2753, 2754, 2755, 2756, 2757, 2758, 2759, 2760, 2761, 2762, 2763, 2764, 2765, 2766, 2767, 2768, 2769, 2770, 2771, 2772, 2773, 2774, 2775, 2776, 2777, 2778, 2779, 2780, 2781, 2782, 2783, 2784, 2785}}, + {Key: "PR", Rows: []int{2786, 2787, 2788, 2789, 2790, 2791, 2792, 2793, 2794, 2795, 2796, 2797, 2798, 2799, 2800, 2801, 2802, 2803, 2804, 2805, 2806, 2807, 2808, 2809, 2810, 2811, 2812, 2813, 2814, 2815, 2816, 2817, 2818, 2819, 2820, 2821, 2822, 2823, 2824, 2825, 2826, 2827, 2828, 2829, 2830, 2831, 2832, 2833, 2834, 2835, 2836, 2837, 2838, 2839, 2840, 2841, 2842, 2843, 2844, 2845, 2846, 2847, 2848, 2849, 2850, 2851, 2852, 2853, 2854, 2855, 2856, 2857, 2858, 2859, 2860, 2861, 2862, 2863, 2864, 2865, 2866, 2867, 2868, 2869, 2870, 2871, 2872, 2873, 2874, 2875, 2876, 2877, 2878, 2879, 2880, 2881, 2882, 2883, 2884, 2885, 2886, 2887, 2888, 2889, 2890, 2891, 2892, 2893, 2894, 2895, 2896, 2897, 2898, 2899, 2900, 2901, 2902, 2903, 2904, 2905, 2906, 2907, 2908, 2909, 2910, 2911, 2912, 2913, 2914, 2915, 2916, 2917, 2918, 2919, 2920, 2921, 2922, 2923, 2924, 2925, 2926, 2927, 2928, 2929, 2930, 2931, 2932, 2933, 2934, 2935, 2936, 2937, 2938, 2939, 2940, 2941, 2942, 2943, 2944, 2945, 2946, 2947, 2948, 2949, 2950, 2951, 2952, 2953, 2954, 2955, 2956, 2957, 2958, 2959, 2960, 2961, 2962, 2963, 2964, 2965, 2966, 2967, 2968, 2969, 2970, 2971, 2972, 2973, 2974, 2975, 2976, 2977, 2978, 2979, 2980, 2981, 2982, 2983, 2984, 2985, 2986, 2987, 2988, 2989, 2990, 2991, 2992, 2993, 2994, 2995, 2996, 2997, 2998, 2999, 3000, 3001, 3002, 3003, 3004, 3005, 3006, 3007, 3008, 3009, 3010, 3011, 3012, 3013, 3014, 3015, 3016, 3017, 3018, 3019, 3020, 3021, 3022, 3023, 3024, 3025, 3026, 3027, 3028, 3029, 3030, 3031, 3032, 3033, 3034, 3035, 3036, 3037, 3038, 3039, 3040, 3041, 3042, 3043, 3044, 3045, 3046, 3047, 3048, 3049, 3050, 3051, 3052, 3053, 3054, 3055, 3056, 3057, 3058, 3059, 3060, 3061, 3062, 3063, 3064, 3065, 3066, 3067, 3068, 3069, 3070, 3071, 3072, 3073, 3074, 3075, 3076, 3077, 3078, 3079, 3080, 3081, 3082, 3083, 3084, 3085, 3086, 3087, 3088, 3089, 3090, 3091, 3092, 3093, 3094, 3095, 3096, 3097, 3098, 3099, 3100, 3101, 3102, 3103, 3104, 3105, 3106, 3107, 3108, 3109, 3110, 3111, 3112, 3113, 3114, 3115, 3116, 3117, 3118, 3119, 3120, 3121, 3122, 3123, 3124, 3125, 3126, 3127, 3128, 3129, 3130, 3131, 3132, 3133, 3134, 3135, 3136, 3137, 3138, 3139, 3140, 3141, 3142, 3143, 3144, 3145, 3146, 3147, 3148, 3149, 3150, 3151, 3152, 3153, 3154, 3155, 3156, 3157, 3158, 3159, 3160, 3161, 3162, 3163, 3164, 3165, 3166, 3167, 3168, 3169, 3170, 3171, 3172, 3173, 3174, 3175, 3176, 3177, 3178, 3179, 3180, 3181, 3182, 3183, 3184}}, + {Key: "PE", Rows: []int{3185, 3186, 3187, 3188, 3189, 3190, 3191, 3192, 3193, 3194, 3195, 3196, 3197, 3198, 3199, 3200, 3201, 3202, 3203, 3204, 3205, 3206, 3207, 3208, 3209, 3210, 3211, 3212, 3213, 3214, 3215, 3216, 3217, 3218, 3219, 3220, 3221, 3222, 3223, 3224, 3225, 3226, 3227, 3228, 3229, 3230, 3231, 3232, 3233, 3234, 3235, 3236, 3237, 3238, 3239, 3240, 3241, 3242, 3243, 3244, 3245, 3246, 3247, 3248, 3249, 3250, 3251, 3252, 3253, 3254, 3255, 3256, 3257, 3258, 3259, 3260, 3261, 3262, 3263, 3264, 3265, 3266, 3267, 3268, 3269, 3270, 3271, 3272, 3273, 3274, 3275, 3276, 3277, 3278, 3279, 3280, 3281, 3282, 3283, 3284, 3285, 3286, 3287, 3288, 3289, 3290, 3291, 3292, 3293, 3294, 3295, 3296, 3297, 3298, 3299, 3300, 3301, 3302, 3303, 3304, 3305, 3306, 3307, 3308, 3309, 3310, 3311, 3312, 3313, 3314, 3315, 3316, 3317, 3318, 3319, 3320, 3321, 3322, 3323, 3324, 3325, 3326, 3327, 3328, 3329, 3330, 3331, 3332, 3333, 3334, 3335, 3336, 3337, 3338, 3339, 3340, 3341, 3342, 3343, 3344, 3345, 3346, 3347, 3348, 3349, 3350, 3351, 3352, 3353, 3354, 3355, 3356, 3357, 3358, 3359, 3360, 3361, 3362, 3363, 3364, 3365, 3366, 3367, 3368, 3369}}, + {Key: "PI", Rows: []int{3370, 3371, 3372, 3373, 3374, 3375, 3376, 3377, 3378, 3379, 3380, 3381, 3382, 3383, 3384, 3385, 3386, 3387, 3388, 3389, 3390, 3391, 3392, 3393, 3394, 3395, 3396, 3397, 3398, 3399, 3400, 3401, 3402, 3403, 3404, 3405, 3406, 3407, 3408, 3409, 3410, 3411, 3412, 3413, 3414, 3415, 3416, 3417, 3418, 3419, 3420, 3421, 3422, 3423, 3424, 3425, 3426, 3427, 3428, 3429, 3430, 3431, 3432, 3433, 3434, 3435, 3436, 3437, 3438, 3439, 3440, 3441, 3442, 3443, 3444, 3445, 3446, 3447, 3448, 3449, 3450, 3451, 3452, 3453, 3454, 3455, 3456, 3457, 3458, 3459, 3460, 3461, 3462, 3463, 3464, 3465, 3466, 3467, 3468, 3469, 3470, 3471, 3472, 3473, 3474, 3475, 3476, 3477, 3478, 3479, 3480, 3481, 3482, 3483, 3484, 3485, 3486, 3487, 3488, 3489, 3490, 3491, 3492, 3493, 3494, 3495, 3496, 3497, 3498, 3499, 3500, 3501, 3502, 3503, 3504, 3505, 3506, 3507, 3508, 3509, 3510, 3511, 3512, 3513, 3514, 3515, 3516, 3517, 3518, 3519, 3520, 3521, 3522, 3523, 3524, 3525, 3526, 3527, 3528, 3529, 3530, 3531, 3532, 3533, 3534, 3535, 3536, 3537, 3538, 3539, 3540, 3541, 3542, 3543, 3544, 3545, 3546, 3547, 3548, 3549, 3550, 3551, 3552, 3553, 3554, 3555, 3556, 3557, 3558, 3559, 3560, 3561, 3562, 3563, 3564, 3565, 3566, 3567, 3568, 3569, 3570, 3571, 3572, 3573, 3574, 3575, 3576, 3577, 3578, 3579, 3580, 3581, 3582, 3583, 3584, 3585, 3586, 3587, 3588, 3589, 3590, 3591, 3592, 3593}}, + {Key: "RJ", Rows: []int{3594, 3595, 3596, 3597, 3598, 3599, 3600, 3601, 3602, 3603, 3604, 3605, 3606, 3607, 3608, 3609, 3610, 3611, 3612, 3613, 3614, 3615, 3616, 3617, 3618, 3619, 3620, 3621, 3622, 3623, 3624, 3625, 3626, 3627, 3628, 3629, 3630, 3631, 3632, 3633, 3634, 3635, 3636, 3637, 3638, 3639, 3640, 3641, 3642, 3643, 3644, 3645, 3646, 3647, 3648, 3649, 3650, 3651, 3652, 3653, 3654, 3655, 3656, 3657, 3658, 3659, 3660, 3661, 3662, 3663, 3664, 3665, 3666, 3667, 3668, 3669, 3670, 3671, 3672, 3673, 3674, 3675, 3676, 3677, 3678, 3679, 3680, 3681, 3682, 3683, 3684, 3685}}, + {Key: "RN", Rows: []int{3686, 3687, 3688, 3689, 3690, 3691, 3692, 3693, 3694, 3695, 3696, 3697, 3698, 3699, 3700, 3701, 3702, 3703, 3704, 3705, 3706, 3707, 3708, 3709, 3710, 3711, 3712, 3713, 3714, 3715, 3716, 3717, 3718, 3719, 3720, 3721, 3722, 3723, 3724, 3725, 3726, 3727, 3728, 3729, 3730, 3731, 3732, 3733, 3734, 3735, 3736, 3737, 3738, 3739, 3740, 3741, 3742, 3743, 3744, 3745, 3746, 3747, 3748, 3749, 3750, 3751, 3752, 3753, 3754, 3755, 3756, 3757, 3758, 3759, 3760, 3761, 3762, 3763, 3764, 3765, 3766, 3767, 3768, 3769, 3770, 3771, 3772, 3773, 3774, 3775, 3776, 3777, 3778, 3779, 3780, 3781, 3782, 3783, 3784, 3785, 3786, 3787, 3788, 3789, 3790, 3791, 3792, 3793, 3794, 3795, 3796, 3797, 3798, 3799, 3800, 3801, 3802, 3803, 3804, 3805, 3806, 3807, 3808, 3809, 3810, 3811, 3812, 3813, 3814, 3815, 3816, 3817, 3818, 3819, 3820, 3821, 3822, 3823, 3824, 3825, 3826, 3827, 3828, 3829, 3830, 3831, 3832, 3833, 3834, 3835, 3836, 3837, 3838, 3839, 3840, 3841, 3842, 3843, 3844, 3845, 3846, 3847, 3848, 3849, 3850, 3851, 3852}}, + {Key: "RS", Rows: []int{3853, 3854, 3855, 3856, 3857, 3858, 3859, 3860, 3861, 3862, 3863, 3864, 3865, 3866, 3867, 3868, 3869, 3870, 3871, 3872, 3873, 3874, 3875, 3876, 3877, 3878, 3879, 3880, 3881, 3882, 3883, 3884, 3885, 3886, 3887, 3888, 3889, 3890, 3891, 3892, 3893, 3894, 3895, 3896, 3897, 3898, 3899, 3900, 3901, 3902, 3903, 3904, 3905, 3906, 3907, 3908, 3909, 3910, 3911, 3912, 3913, 3914, 3915, 3916, 3917, 3918, 3919, 3920, 3921, 3922, 3923, 3924, 3925, 3926, 3927, 3928, 3929, 3930, 3931, 3932, 3933, 3934, 3935, 3936, 3937, 3938, 3939, 3940, 3941, 3942, 3943, 3944, 3945, 3946, 3947, 3948, 3949, 3950, 3951, 3952, 3953, 3954, 3955, 3956, 3957, 3958, 3959, 3960, 3961, 3962, 3963, 3964, 3965, 3966, 3967, 3968, 3969, 3970, 3971, 3972, 3973, 3974, 3975, 3976, 3977, 3978, 3979, 3980, 3981, 3982, 3983, 3984, 3985, 3986, 3987, 3988, 3989, 3990, 3991, 3992, 3993, 3994, 3995, 3996, 3997, 3998, 3999, 4000, 4001, 4002, 4003, 4004, 4005, 4006, 4007, 4008, 4009, 4010, 4011, 4012, 4013, 4014, 4015, 4016, 4017, 4018, 4019, 4020, 4021, 4022, 4023, 4024, 4025, 4026, 4027, 4028, 4029, 4030, 4031, 4032, 4033, 4034, 4035, 4036, 4037, 4038, 4039, 4040, 4041, 4042, 4043, 4044, 4045, 4046, 4047, 4048, 4049, 4050, 4051, 4052, 4053, 4054, 4055, 4056, 4057, 4058, 4059, 4060, 4061, 4062, 4063, 4064, 4065, 4066, 4067, 4068, 4069, 4070, 4071, 4072, 4073, 4074, 4075, 4076, 4077, 4078, 4079, 4080, 4081, 4082, 4083, 4084, 4085, 4086, 4087, 4088, 4089, 4090, 4091, 4092, 4093, 4094, 4095, 4096, 4097, 4098, 4099, 4100, 4101, 4102, 4103, 4104, 4105, 4106, 4107, 4108, 4109, 4110, 4111, 4112, 4113, 4114, 4115, 4116, 4117, 4118, 4119, 4120, 4121, 4122, 4123, 4124, 4125, 4126, 4127, 4128, 4129, 4130, 4131, 4132, 4133, 4134, 4135, 4136, 4137, 4138, 4139, 4140, 4141, 4142, 4143, 4144, 4145, 4146, 4147, 4148, 4149, 4150, 4151, 4152, 4153, 4154, 4155, 4156, 4157, 4158, 4159, 4160, 4161, 4162, 4163, 4164, 4165, 4166, 4167, 4168, 4169, 4170, 4171, 4172, 4173, 4174, 4175, 4176, 4177, 4178, 4179, 4180, 4181, 4182, 4183, 4184, 4185, 4186, 4187, 4188, 4189, 4190, 4191, 4192, 4193, 4194, 4195, 4196, 4197, 4198, 4199, 4200, 4201, 4202, 4203, 4204, 4205, 4206, 4207, 4208, 4209, 4210, 4211, 4212, 4213, 4214, 4215, 4216, 4217, 4218, 4219, 4220, 4221, 4222, 4223, 4224, 4225, 4226, 4227, 4228, 4229, 4230, 4231, 4232, 4233, 4234, 4235, 4236, 4237, 4238, 4239, 4240, 4241, 4242, 4243, 4244, 4245, 4246, 4247, 4248, 4249, 4250, 4251, 4252, 4253, 4254, 4255, 4256, 4257, 4258, 4259, 4260, 4261, 4262, 4263, 4264, 4265, 4266, 4267, 4268, 4269, 4270, 4271, 4272, 4273, 4274, 4275, 4276, 4277, 4278, 4279, 4280, 4281, 4282, 4283, 4284, 4285, 4286, 4287, 4288, 4289, 4290, 4291, 4292, 4293, 4294, 4295, 4296, 4297, 4298, 4299, 4300, 4301, 4302, 4303, 4304, 4305, 4306, 4307, 4308, 4309, 4310, 4311, 4312, 4313, 4314, 4315, 4316, 4317, 4318, 4319, 4320, 4321, 4322, 4323, 4324, 4325, 4326, 4327, 4328, 4329, 4330, 4331, 4332, 4333, 4334, 4335, 4336, 4337, 4338, 4339, 4340, 4341, 4342, 4343, 4344, 4345, 4346, 4347, 4348, 4349}}, + {Key: "RO", Rows: []int{4350, 4351, 4352, 4353, 4354, 4355, 4356, 4357, 4358, 4359, 4360, 4361, 4362, 4363, 4364, 4365, 4366, 4367, 4368, 4369, 4370, 4371, 4372, 4373, 4374, 4375, 4376, 4377, 4378, 4379, 4380, 4381, 4382, 4383, 4384, 4385, 4386, 4387, 4388, 4389, 4390, 4391, 4392, 4393, 4394, 4395, 4396, 4397, 4398, 4399, 4400, 4401}}, + {Key: "RR", Rows: []int{4402, 4403, 4404, 4405, 4406, 4407, 4408, 4409, 4410, 4411, 4412, 4413, 4414, 4415, 4416}}, + {Key: "SC", Rows: []int{4417, 4418, 4419, 4420, 4421, 4422, 4423, 4424, 4425, 4426, 4427, 4428, 4429, 4430, 4431, 4432, 4433, 4434, 4435, 4436, 4437, 4438, 4439, 4440, 4441, 4442, 4443, 4444, 4445, 4446, 4447, 4448, 4449, 4450, 4451, 4452, 4453, 4454, 4455, 4456, 4457, 4458, 4459, 4460, 4461, 4462, 4463, 4464, 4465, 4466, 4467, 4468, 4469, 4470, 4471, 4472, 4473, 4474, 4475, 4476, 4477, 4478, 4479, 4480, 4481, 4482, 4483, 4484, 4485, 4486, 4487, 4488, 4489, 4490, 4491, 4492, 4493, 4494, 4495, 4496, 4497, 4498, 4499, 4500, 4501, 4502, 4503, 4504, 4505, 4506, 4507, 4508, 4509, 4510, 4511, 4512, 4513, 4514, 4515, 4516, 4517, 4518, 4519, 4520, 4521, 4522, 4523, 4524, 4525, 4526, 4527, 4528, 4529, 4530, 4531, 4532, 4533, 4534, 4535, 4536, 4537, 4538, 4539, 4540, 4541, 4542, 4543, 4544, 4545, 4546, 4547, 4548, 4549, 4550, 4551, 4552, 4553, 4554, 4555, 4556, 4557, 4558, 4559, 4560, 4561, 4562, 4563, 4564, 4565, 4566, 4567, 4568, 4569, 4570, 4571, 4572, 4573, 4574, 4575, 4576, 4577, 4578, 4579, 4580, 4581, 4582, 4583, 4584, 4585, 4586, 4587, 4588, 4589, 4590, 4591, 4592, 4593, 4594, 4595, 4596, 4597, 4598, 4599, 4600, 4601, 4602, 4603, 4604, 4605, 4606, 4607, 4608, 4609, 4610, 4611, 4612, 4613, 4614, 4615, 4616, 4617, 4618, 4619, 4620, 4621, 4622, 4623, 4624, 4625, 4626, 4627, 4628, 4629, 4630, 4631, 4632, 4633, 4634, 4635, 4636, 4637, 4638, 4639, 4640, 4641, 4642, 4643, 4644, 4645, 4646, 4647, 4648, 4649, 4650, 4651, 4652, 4653, 4654, 4655, 4656, 4657, 4658, 4659, 4660, 4661, 4662, 4663, 4664, 4665, 4666, 4667, 4668, 4669, 4670, 4671, 4672, 4673, 4674, 4675, 4676, 4677, 4678, 4679, 4680, 4681, 4682, 4683, 4684, 4685, 4686, 4687, 4688, 4689, 4690, 4691, 4692, 4693, 4694, 4695, 4696, 4697, 4698, 4699, 4700, 4701, 4702, 4703, 4704, 4705, 4706, 4707, 4708, 4709, 4710, 4711}}, + {Key: "SP", Rows: []int{4712, 4713, 4714, 4715, 4716, 4717, 4718, 4719, 4720, 4721, 4722, 4723, 4724, 4725, 4726, 4727, 4728, 4729, 4730, 4731, 4732, 4733, 4734, 4735, 4736, 4737, 4738, 4739, 4740, 4741, 4742, 4743, 4744, 4745, 4746, 4747, 4748, 4749, 4750, 4751, 4752, 4753, 4754, 4755, 4756, 4757, 4758, 4759, 4760, 4761, 4762, 4763, 4764, 4765, 4766, 4767, 4768, 4769, 4770, 4771, 4772, 4773, 4774, 4775, 4776, 4777, 4778, 4779, 4780, 4781, 4782, 4783, 4784, 4785, 4786, 4787, 4788, 4789, 4790, 4791, 4792, 4793, 4794, 4795, 4796, 4797, 4798, 4799, 4800, 4801, 4802, 4803, 4804, 4805, 4806, 4807, 4808, 4809, 4810, 4811, 4812, 4813, 4814, 4815, 4816, 4817, 4818, 4819, 4820, 4821, 4822, 4823, 4824, 4825, 4826, 4827, 4828, 4829, 4830, 4831, 4832, 4833, 4834, 4835, 4836, 4837, 4838, 4839, 4840, 4841, 4842, 4843, 4844, 4845, 4846, 4847, 4848, 4849, 4850, 4851, 4852, 4853, 4854, 4855, 4856, 4857, 4858, 4859, 4860, 4861, 4862, 4863, 4864, 4865, 4866, 4867, 4868, 4869, 4870, 4871, 4872, 4873, 4874, 4875, 4876, 4877, 4878, 4879, 4880, 4881, 4882, 4883, 4884, 4885, 4886, 4887, 4888, 4889, 4890, 4891, 4892, 4893, 4894, 4895, 4896, 4897, 4898, 4899, 4900, 4901, 4902, 4903, 4904, 4905, 4906, 4907, 4908, 4909, 4910, 4911, 4912, 4913, 4914, 4915, 4916, 4917, 4918, 4919, 4920, 4921, 4922, 4923, 4924, 4925, 4926, 4927, 4928, 4929, 4930, 4931, 4932, 4933, 4934, 4935, 4936, 4937, 4938, 4939, 4940, 4941, 4942, 4943, 4944, 4945, 4946, 4947, 4948, 4949, 4950, 4951, 4952, 4953, 4954, 4955, 4956, 4957, 4958, 4959, 4960, 4961, 4962, 4963, 4964, 4965, 4966, 4967, 4968, 4969, 4970, 4971, 4972, 4973, 4974, 4975, 4976, 4977, 4978, 4979, 4980, 4981, 4982, 4983, 4984, 4985, 4986, 4987, 4988, 4989, 4990, 4991, 4992, 4993, 4994, 4995, 4996, 4997, 4998, 4999, 5000, 5001, 5002, 5003, 5004, 5005, 5006, 5007, 5008, 5009, 5010, 5011, 5012, 5013, 5014, 5015, 5016, 5017, 5018, 5019, 5020, 5021, 5022, 5023, 5024, 5025, 5026, 5027, 5028, 5029, 5030, 5031, 5032, 5033, 5034, 5035, 5036, 5037, 5038, 5039, 5040, 5041, 5042, 5043, 5044, 5045, 5046, 5047, 5048, 5049, 5050, 5051, 5052, 5053, 5054, 5055, 5056, 5057, 5058, 5059, 5060, 5061, 5062, 5063, 5064, 5065, 5066, 5067, 5068, 5069, 5070, 5071, 5072, 5073, 5074, 5075, 5076, 5077, 5078, 5079, 5080, 5081, 5082, 5083, 5084, 5085, 5086, 5087, 5088, 5089, 5090, 5091, 5092, 5093, 5094, 5095, 5096, 5097, 5098, 5099, 5100, 5101, 5102, 5103, 5104, 5105, 5106, 5107, 5108, 5109, 5110, 5111, 5112, 5113, 5114, 5115, 5116, 5117, 5118, 5119, 5120, 5121, 5122, 5123, 5124, 5125, 5126, 5127, 5128, 5129, 5130, 5131, 5132, 5133, 5134, 5135, 5136, 5137, 5138, 5139, 5140, 5141, 5142, 5143, 5144, 5145, 5146, 5147, 5148, 5149, 5150, 5151, 5152, 5153, 5154, 5155, 5156, 5157, 5158, 5159, 5160, 5161, 5162, 5163, 5164, 5165, 5166, 5167, 5168, 5169, 5170, 5171, 5172, 5173, 5174, 5175, 5176, 5177, 5178, 5179, 5180, 5181, 5182, 5183, 5184, 5185, 5186, 5187, 5188, 5189, 5190, 5191, 5192, 5193, 5194, 5195, 5196, 5197, 5198, 5199, 5200, 5201, 5202, 5203, 5204, 5205, 5206, 5207, 5208, 5209, 5210, 5211, 5212, 5213, 5214, 5215, 5216, 5217, 5218, 5219, 5220, 5221, 5222, 5223, 5224, 5225, 5226, 5227, 5228, 5229, 5230, 5231, 5232, 5233, 5234, 5235, 5236, 5237, 5238, 5239, 5240, 5241, 5242, 5243, 5244, 5245, 5246, 5247, 5248, 5249, 5250, 5251, 5252, 5253, 5254, 5255, 5256, 5257, 5258, 5259, 5260, 5261, 5262, 5263, 5264, 5265, 5266, 5267, 5268, 5269, 5270, 5271, 5272, 5273, 5274, 5275, 5276, 5277, 5278, 5279, 5280, 5281, 5282, 5283, 5284, 5285, 5286, 5287, 5288, 5289, 5290, 5291, 5292, 5293, 5294, 5295, 5296, 5297, 5298, 5299, 5300, 5301, 5302, 5303, 5304, 5305, 5306, 5307, 5308, 5309, 5310, 5311, 5312, 5313, 5314, 5315, 5316, 5317, 5318, 5319, 5320, 5321, 5322, 5323, 5324, 5325, 5326, 5327, 5328, 5329, 5330, 5331, 5332, 5333, 5334, 5335, 5336, 5337, 5338, 5339, 5340, 5341, 5342, 5343, 5344, 5345, 5346, 5347, 5348, 5349, 5350, 5351, 5352, 5353, 5354, 5355, 5356}}, + {Key: "SE", Rows: []int{5357, 5358, 5359, 5360, 5361, 5362, 5363, 5364, 5365, 5366, 5367, 5368, 5369, 5370, 5371, 5372, 5373, 5374, 5375, 5376, 5377, 5378, 5379, 5380, 5381, 5382, 5383, 5384, 5385, 5386, 5387, 5388, 5389, 5390, 5391, 5392, 5393, 5394, 5395, 5396, 5397, 5398, 5399, 5400, 5401, 5402, 5403, 5404, 5405, 5406, 5407, 5408, 5409, 5410, 5411, 5412, 5413, 5414, 5415, 5416, 5417, 5418, 5419, 5420, 5421, 5422, 5423, 5424, 5425, 5426, 5427, 5428, 5429, 5430, 5431}}, + {Key: "TO", Rows: []int{5432, 5433, 5434, 5435, 5436, 5437, 5438, 5439, 5440, 5441, 5442, 5443, 5444, 5445, 5446, 5447, 5448, 5449, 5450, 5451, 5452, 5453, 5454, 5455, 5456, 5457, 5458, 5459, 5460, 5461, 5462, 5463, 5464, 5465, 5466, 5467, 5468, 5469, 5470, 5471, 5472, 5473, 5474, 5475, 5476, 5477, 5478, 5479, 5480, 5481, 5482, 5483, 5484, 5485, 5486, 5487, 5488, 5489, 5490, 5491, 5492, 5493, 5494, 5495, 5496, 5497, 5498, 5499, 5500, 5501, 5502, 5503, 5504, 5505, 5506, 5507, 5508, 5509, 5510, 5511, 5512, 5513, 5514, 5515, 5516, 5517, 5518, 5519, 5520, 5521, 5522, 5523, 5524, 5525, 5526, 5527, 5528, 5529, 5530, 5531, 5532, 5533, 5534, 5535, 5536, 5537, 5538, 5539, 5540, 5541, 5542, 5543, 5544, 5545, 5546, 5547, 5548, 5549, 5550, 5551, 5552, 5553, 5554, 5555, 5556, 5557, 5558, 5559, 5560, 5561, 5562, 5563, 5564, 5565, 5566, 5567, 5568, 5569, 5570}}, + }, + []int{882, 1566, 883, 1567, 2419, 619, 202, 203, 2786, 4417, 2420, 4418, 1568, 3185, 5432, 1569, 1128, 204, 2421, 620, 621, 3686, 3370, 3853, 622, 1345, 0, 884, 1570, 4712, 885, 4713, 2787, 205, 3186, 3687, 804, 1129, 3187, 2422, 3188, 3371, 4419, 4420, 2423, 1346, 1571, 22, 2563, 3372, 1487, 1572, 4421, 1130, 805, 206, 886, 887, 3688, 3189, 3854, 4714, 1573, 3190, 4715, 4422, 4716, 4717, 4718, 1574, 4423, 888, 4424, 1575, 3855, 4719, 2788, 806, 2564, 5433, 1576, 207, 623, 1577, 3856, 1578, 2565, 2566, 2567, 3191, 3373, 208, 4720, 1579, 1131, 624, 2568, 1488, 209, 1132, 3857, 807, 3858, 3374, 3859, 1580, 2424, 3689, 889, 1581, 808, 4721, 1582, 4425, 2569, 2570, 3192, 5434, 210, 5435, 2425, 1583, 3690, 2789, 3860, 890, 1584, 3861, 1585, 1347, 4350, 4722, 2426, 1133, 2790, 625, 1586, 3193, 4723, 3862, 4402, 4724, 1134, 1135, 4351, 1348, 4426, 1349, 1587, 3691, 3863, 1350, 891, 1588, 3375, 1351, 2791, 4352, 892, 2792, 1136, 2793, 1589, 809, 626, 1352, 2794, 3376, 4725, 140, 1590, 4726, 4727, 4728, 4729, 1591, 3864, 5436, 4353, 1592, 3377, 893, 2795, 4403, 1489, 124, 1137, 2796, 3194, 3865, 894, 3378, 1138, 211, 141, 212, 213, 4730, 895, 4731, 4732, 3866, 627, 896, 2571, 4733, 5357, 1593, 2797, 23, 214, 2798, 2427, 1139, 4734, 142, 5437, 2428, 897, 2429, 1140, 1490, 1491, 810, 4427, 215, 2799, 216, 1594, 4735, 3867, 1595, 4736, 1596, 1492, 3195, 4428, 217, 3379, 5438, 3692, 3594, 218, 2800, 898, 4737, 4738, 899, 3380, 4429, 4430, 143, 3868, 219, 2801, 628, 3381, 220, 1597, 4431, 1598, 221, 1493, 3693, 2802, 3869, 1599, 2572, 4739, 4740, 900, 901, 5439, 1494, 3595, 811, 1353, 4741, 1141, 4432, 3694, 222, 902, 223, 2803, 144, 629, 5358, 1495, 630, 4433, 2573, 1600, 5359, 4742, 224, 631, 225, 4743, 226, 1601, 632, 3196, 4744, 812, 903, 1602, 904, 905, 5440, 5441, 5442, 1354, 5443, 1355, 1142, 5444, 906, 1603, 5445, 1143, 1496, 227, 3870, 1144, 4745, 4746, 1604, 4747, 24, 5446, 1605, 2804, 1606, 2805, 1607, 2806, 1356, 4434, 2574, 4435, 4748, 4749, 633, 1145, 3871, 634, 3197, 3596, 2575, 2807, 228, 3872, 635, 229, 5360, 2808, 1608, 1609, 1610, 4750, 1611, 3198, 1612, 3597, 4751, 2576, 3695, 5361, 2577, 2578, 4752, 4753, 1357, 907, 3696, 1613, 1614, 1615, 1358, 4354, 4754, 2809, 3598, 4436, 636, 3382, 2579, 3383, 3384, 3599, 5447, 3873, 3874, 3875, 3876, 3877, 3878, 4437, 4755, 908, 4756, 4438, 3879, 4439, 4757, 2810, 637, 4758, 1, 2811, 3697, 2580, 3385, 1616, 2812, 25, 2813, 145, 4440, 1617, 4759, 813, 5448, 2430, 1618, 3880, 3881, 230, 4760, 909, 638, 4441, 2431, 5449, 146, 4761, 4762, 4763, 2432, 3386, 910, 1146, 5450, 5451, 1147, 1148, 1149, 1150, 4764, 1619, 3882, 2433, 2581, 3698, 231, 2434, 232, 3387, 639, 814, 4765, 1620, 911, 4442, 4443, 4444, 4445, 4446, 3883, 4447, 2814, 4766, 1151, 1621, 640, 4767, 2582, 1622, 1623, 4448, 1497, 2815, 5452, 2435, 233, 3884, 4768, 1624, 3885, 1152, 1359, 1625, 3886, 2583, 3699, 1626, 641, 4769, 2816, 2436, 3700, 147, 4770, 234, 4449, 4771, 3388, 235, 3199, 2584, 2585, 26, 815, 27, 2586, 1360, 4772, 236, 1153, 1361, 3887, 2817, 237, 5453, 3600, 3888, 3889, 3890, 238, 4773, 5362, 3891, 1627, 3601, 4450, 2818, 3892, 3389, 642, 239, 3390, 148, 1154, 3200, 4774, 4775, 643, 240, 912, 3391, 241, 242, 5454, 644, 3893, 1628, 4776, 4777, 1498, 28, 3392, 4778, 1499, 645, 4779, 2587, 4780, 646, 647, 1500, 2819, 913, 1629, 1155, 2820, 3393, 4451, 1156, 29, 2437, 2588, 3201, 2589, 3394, 3202, 3602, 1630, 243, 4452, 244, 1631, 3203, 30, 1632, 1633, 2438, 3395, 1157, 4453, 2439, 149, 3894, 4781, 3701, 3895, 1158, 1634, 1635, 2590, 4782, 1159, 5455, 4783, 3396, 1636, 150, 3204, 3397, 1637, 3205, 1638, 1639, 4454, 4784, 1640, 4785, 4786, 245, 2821, 4455, 816, 1641, 2822, 2823, 1362, 4787, 3398, 246, 2591, 2824, 648, 2592, 4404, 2825, 3896, 3897, 3898, 1160, 3899, 151, 3900, 247, 31, 152, 3399, 4788, 1642, 4456, 1643, 2826, 3702, 3206, 1501, 4789, 4790, 3207, 1644, 1161, 3208, 3603, 4457, 914, 1645, 2593, 3400, 3703, 3901, 4458, 248, 1646, 249, 1162, 915, 1647, 1363, 1648, 3604, 817, 4459, 2827, 2440, 5456, 4791, 1163, 3902, 3401, 3903, 1649, 4460, 3904, 1650, 2594, 2828, 4792, 2829, 4461, 1651, 4405, 3402, 916, 1652, 250, 251, 1502, 2441, 3209, 1653, 2595, 917, 2596, 3905, 3403, 5363, 252, 4793, 4794, 153, 2597, 4795, 1654, 4796, 2830, 3906, 1655, 4797, 1656, 253, 4462, 3907, 4463, 4464, 3908, 2442, 4798, 2831, 32, 1657, 2443, 1503, 1658, 2832, 5457, 2, 3404, 803, 1659, 1364, 4799, 1660, 918, 1661, 3210, 818, 3211, 3704, 5458, 1164, 4800, 3212, 1165, 2598, 3405, 2599, 5364, 2444, 649, 254, 255, 2445, 2446, 919, 3909, 4801, 4802, 256, 1662, 257, 4465, 4466, 1663, 1664, 3213, 258, 1665, 3214, 3, 2447, 4803, 4804, 1166, 920, 1167, 921, 5459, 3406, 3407, 1168, 922, 259, 1169, 1666, 4355, 4805, 1667, 3910, 154, 2600, 1504, 260, 2601, 261, 1668, 923, 3408, 2602, 4356, 3215, 3605, 1669, 4806, 4807, 3216, 4467, 4808, 3911, 4357, 3912, 1365, 262, 924, 1670, 925, 1671, 1672, 2448, 2449, 3913, 2603, 926, 1673, 1170, 4809, 3606, 3217, 3914, 5460, 819, 2604, 2605, 2606, 33, 3915, 4358, 4810, 927, 263, 264, 1674, 265, 1675, 3218, 266, 267, 2833, 2834, 4811, 2835, 4812, 1676, 928, 3916, 4468, 2607, 3917, 3705, 3706, 3707, 4813, 268, 4814, 4815, 1171, 1172, 4816, 2608, 3409, 2609, 4817, 34, 3410, 1677, 4818, 3219, 125, 1678, 2610, 929, 930, 269, 3411, 2836, 4469, 3220, 270, 271, 1679, 2611, 272, 1680, 1505, 3918, 3221, 3919, 2837, 3920, 2838, 2839, 4470, 3607, 1681, 1682, 2450, 650, 3222, 1683, 1684, 35, 1685, 3921, 931, 1173, 2840, 3922, 4819, 2841, 2612, 2842, 1686, 932, 1366, 4820, 3412, 3923, 933, 36, 4471, 934, 273, 3413, 1687, 1688, 4472, 3924, 2843, 5365, 1689, 2844, 4473, 1690, 274, 37, 1506, 3708, 3414, 2845, 3415, 935, 4821, 2846, 3416, 2847, 3925, 4359, 1367, 3709, 1368, 1691, 936, 3926, 1369, 4822, 3608, 1692, 5461, 4474, 4823, 651, 937, 3223, 1693, 1694, 2451, 1370, 4824, 38, 275, 1695, 276, 1371, 4825, 3417, 277, 278, 279, 1696, 4360, 3927, 280, 2848, 3928, 1174, 4826, 4827, 281, 3929, 2849, 3930, 4475, 3710, 3931, 5366, 3224, 652, 5367, 4828, 3932, 4476, 282, 4406, 1697, 2850, 3609, 1175, 3418, 283, 3933, 155, 2452, 2851, 4477, 4829, 3934, 3935, 3936, 3937, 1698, 39, 5368, 3938, 4830, 284, 1699, 1700, 1701, 2613, 1702, 285, 1703, 4478, 1176, 653, 3939, 1704, 3419, 1705, 3420, 2852, 2453, 1706, 4831, 4479, 3940, 4, 3225, 1707, 3941, 4407, 1507, 3421, 4832, 1708, 286, 2853, 1709, 1710, 1711, 3610, 4833, 1712, 156, 2614, 3711, 3422, 287, 3942, 1713, 288, 4834, 3611, 1714, 157, 158, 820, 654, 3423, 289, 5369, 655, 5462, 656, 657, 1372, 2854, 3943, 1715, 3944, 1716, 3612, 1717, 1718, 1719, 1720, 1721, 1722, 938, 5463, 5370, 1723, 3226, 3712, 3713, 658, 3227, 1724, 40, 4408, 1177, 3228, 1725, 2615, 5464, 3229, 1178, 1726, 1727, 4835, 1728, 290, 3945, 1729, 659, 2855, 5465, 3946, 3613, 3230, 2616, 1730, 4836, 1508, 2454, 1373, 4361, 939, 821, 3424, 4837, 2856, 291, 1731, 940, 4838, 2857, 4480, 660, 1732, 1733, 3231, 4839, 2617, 292, 2618, 293, 3947, 1734, 661, 941, 294, 2619, 1735, 662, 942, 1736, 4481, 1179, 3948, 3425, 3714, 1180, 4840, 663, 3232, 5371, 1737, 4482, 3949, 5466, 2858, 295, 1738, 1181, 1739, 1182, 1183, 4362, 943, 4841, 4842, 3950, 2859, 3951, 3715, 3952, 3953, 3954, 4483, 4843, 2860, 944, 3233, 3234, 41, 1740, 1741, 3955, 5467, 5468, 1742, 1374, 1743, 945, 4484, 1509, 1184, 4485, 4844, 3956, 3957, 664, 4845, 2455, 1744, 3958, 2861, 665, 666, 296, 3959, 4363, 3960, 2862, 297, 2863, 946, 1185, 3961, 298, 1745, 3962, 1746, 1747, 1375, 1748, 4846, 2864, 299, 159, 3426, 3427, 4486, 3428, 1376, 947, 300, 160, 1186, 1187, 1749, 42, 3429, 2456, 822, 1377, 4847, 1188, 3963, 948, 5469, 5470, 1378, 4848, 2865, 3430, 3431, 43, 2866, 3964, 4364, 1750, 5471, 1751, 3614, 1752, 1379, 2620, 1753, 823, 1754, 301, 1755, 1756, 1757, 3615, 302, 2457, 3432, 824, 303, 304, 1189, 1758, 1759, 1760, 5472, 1761, 4849, 4850, 4487, 2458, 2621, 3235, 305, 2622, 306, 3965, 1762, 1763, 1380, 2623, 1764, 1765, 1766, 2867, 1767, 1381, 1768, 2868, 1769, 1770, 3966, 1771, 2869, 307, 1772, 3967, 44, 3968, 1773, 308, 2870, 3616, 4851, 309, 4488, 1774, 1775, 667, 2624, 1510, 310, 1776, 2871, 1777, 4852, 1190, 1778, 3969, 3970, 2872, 3716, 1779, 4489, 3717, 311, 3433, 4853, 4490, 1780, 1781, 3971, 1511, 2873, 1782, 1783, 1784, 949, 1785, 1786, 4491, 3434, 3236, 312, 3237, 1512, 950, 951, 4854, 2874, 4365, 4492, 45, 4855, 4856, 4366, 1513, 313, 4857, 3972, 1382, 1787, 5473, 3973, 1514, 2625, 46, 668, 669, 4858, 314, 4493, 1788, 315, 3974, 1789, 4859, 3975, 3976, 5474, 3435, 1790, 952, 1791, 953, 1792, 5372, 3436, 316, 954, 5475, 670, 955, 1793, 671, 3977, 317, 2626, 2875, 4860, 3978, 4861, 1794, 2876, 2877, 5, 2878, 3979, 3718, 1795, 2879, 4862, 2627, 1383, 2628, 2629, 2630, 4367, 956, 3238, 2459, 5373, 4863, 4494, 4495, 1796, 3239, 318, 3437, 2460, 2880, 4496, 2881, 3438, 3719, 2631, 1797, 3439, 2632, 2461, 3440, 2462, 2463, 1191, 1384, 1798, 3240, 126, 957, 2633, 958, 5476, 319, 1799, 3980, 959, 1192, 1800, 1801, 47, 1802, 3441, 1385, 1515, 672, 3981, 4864, 4497, 1803, 2634, 1804, 1805, 3982, 4865, 2635, 2882, 2883, 2884, 1806, 1386, 5477, 320, 3983, 1807, 1808, 4498, 960, 4866, 3442, 5374, 1809, 1810, 1811, 825, 4867, 1812, 1813, 961, 5478, 1814, 1815, 1816, 4868, 4869, 3984, 3985, 1516, 5479, 3986, 48, 2885, 4870, 1387, 321, 1817, 1818, 2464, 3443, 3987, 3444, 1819, 322, 3988, 1193, 3989, 1820, 1821, 826, 3445, 4499, 1822, 3990, 2636, 1823, 1824, 1825, 827, 1826, 1827, 3241, 1517, 2886, 4871, 1828, 1518, 2887, 3991, 4500, 3992, 3720, 2888, 962, 4872, 4873, 3617, 2637, 5480, 4874, 1194, 3618, 1829, 4875, 828, 963, 964, 161, 1519, 4876, 2465, 3993, 3446, 4877, 3447, 4878, 323, 1830, 2638, 4879, 4880, 4881, 4882, 3994, 3721, 324, 3995, 2889, 2890, 1831, 4883, 1832, 3619, 3996, 1833, 325, 4501, 1834, 2891, 3997, 3998, 162, 6, 3722, 3999, 4000, 673, 326, 4502, 4001, 4002, 4003, 4503, 1835, 3242, 4004, 1836, 1837, 2639, 4005, 2892, 3448, 5481, 1195, 2893, 4368, 1838, 3723, 1839, 4884, 4885, 327, 4006, 4007, 5375, 4008, 4009, 1840, 4886, 1196, 4010, 4887, 1841, 49, 1842, 965, 4888, 1843, 4011, 328, 4889, 4012, 1844, 329, 674, 1845, 1846, 3724, 3243, 2640, 4013, 966, 1847, 1848, 675, 2466, 2894, 4014, 4890, 3449, 330, 5482, 1520, 2895, 4015, 4504, 4016, 967, 2896, 4017, 7, 331, 332, 50, 3244, 5376, 1197, 1849, 3725, 1850, 1851, 4018, 51, 1388, 2897, 2898, 1852, 3245, 1198, 3726, 4891, 4892, 4893, 4894, 127, 3246, 1853, 1854, 2899, 1521, 5483, 1389, 333, 5484, 334, 968, 52, 2900, 4505, 4895, 2901, 3727, 4896, 3247, 4019, 969, 3450, 2902, 3248, 335, 2467, 3451, 1855, 2903, 3452, 4020, 4506, 2904, 4897, 4898, 163, 4021, 1856, 4022, 970, 1199, 2905, 336, 4507, 971, 1857, 5485, 4023, 676, 4508, 677, 1858, 1200, 4024, 678, 1201, 1859, 2906, 2907, 4509, 4899, 3453, 2908, 3454, 1860, 2909, 3728, 1861, 3455, 4900, 1862, 3456, 1863, 4901, 679, 4025, 1864, 1865, 1866, 2641, 3249, 5377, 4510, 1867, 1868, 3457, 1869, 1870, 3729, 829, 1871, 4902, 2642, 4903, 1872, 3730, 4511, 3250, 972, 1873, 337, 3251, 5378, 4904, 4026, 4512, 2468, 4027, 4513, 4514, 4905, 1390, 4028, 338, 4906, 3458, 4029, 1391, 2910, 5379, 4907, 680, 4030, 339, 4908, 4031, 3459, 53, 4032, 1874, 4909, 340, 1392, 1522, 3252, 4033, 1202, 2911, 1875, 3253, 1876, 973, 974, 975, 2469, 976, 3731, 977, 5486, 978, 5487, 979, 2912, 2913, 1877, 1203, 341, 1878, 1879, 980, 1204, 4515, 3732, 1205, 1206, 4369, 830, 1207, 342, 1208, 1209, 1880, 681, 1210, 5380, 1211, 4034, 4035, 4036, 2914, 3254, 682, 683, 1881, 4516, 3255, 4037, 4517, 684, 3733, 1882, 4038, 4518, 831, 3460, 4039, 4910, 4911, 2915, 4912, 2916, 685, 164, 4370, 343, 3734, 2917, 344, 1883, 1884, 4913, 4914, 3620, 2918, 981, 4040, 2919, 4915, 2643, 4916, 2920, 4917, 1885, 4519, 686, 1886, 5488, 982, 687, 4520, 1887, 1888, 4918, 4041, 983, 2921, 4919, 1393, 832, 2922, 2923, 1889, 4920, 4921, 345, 4922, 2924, 1890, 4923, 4924, 3461, 984, 4925, 4521, 4926, 4522, 4927, 1891, 1523, 1892, 1212, 1893, 1394, 1894, 1895, 2644, 2645, 2470, 5489, 4928, 4042, 985, 1896, 346, 4929, 4043, 4523, 4044, 688, 986, 987, 4930, 2925, 689, 4045, 4931, 3462, 4046, 165, 4047, 1213, 4932, 988, 4933, 347, 1897, 4934, 3256, 2926, 4048, 690, 4935, 54, 833, 2927, 1898, 1899, 4049, 1900, 4524, 691, 2646, 348, 349, 4525, 350, 351, 692, 3257, 352, 353, 2928, 354, 4936, 1901, 1902, 834, 4050, 3258, 4526, 355, 356, 4051, 4937, 357, 1903, 4052, 358, 4938, 835, 359, 1904, 1905, 4939, 360, 693, 4527, 1906, 2929, 1214, 4940, 361, 694, 836, 3735, 4941, 55, 362, 4942, 2647, 4943, 1907, 1215, 1216, 2471, 2472, 3259, 4944, 1908, 363, 56, 4053, 3621, 364, 4945, 2930, 3260, 1909, 1524, 695, 2931, 1910, 4054, 4946, 5381, 3261, 3463, 4947, 4948, 365, 4528, 1911, 4055, 2648, 4529, 2932, 4056, 1912, 4530, 2933, 4531, 4057, 1217, 2934, 989, 2935, 3262, 1913, 1914, 4532, 4949, 696, 4058, 4950, 1915, 2936, 4951, 990, 5382, 1395, 2649, 1916, 3263, 4059, 366, 2473, 57, 1917, 1918, 3464, 991, 1919, 1525, 4952, 4533, 1920, 992, 1921, 3736, 697, 1922, 698, 4953, 4060, 367, 4954, 4955, 1923, 368, 4956, 4534, 369, 2937, 993, 1396, 3465, 4061, 166, 2474, 3264, 994, 2938, 4535, 4957, 699, 4958, 4536, 3265, 3737, 700, 5490, 1924, 4537, 370, 701, 4409, 2939, 4959, 4538, 4062, 1925, 371, 372, 167, 4539, 4960, 4961, 373, 374, 2940, 4540, 702, 375, 2941, 4541, 2475, 837, 3466, 995, 4542, 4063, 2650, 5383, 5384, 376, 4962, 377, 996, 5385, 1926, 1927, 1928, 3622, 378, 5491, 1929, 1930, 379, 168, 3266, 4064, 380, 381, 382, 383, 838, 384, 3623, 2942, 1931, 997, 998, 5492, 4963, 3267, 703, 3467, 4543, 1218, 1932, 2943, 704, 2476, 999, 3738, 4544, 4964, 4965, 385, 1933, 386, 3624, 387, 1934, 169, 1935, 388, 1936, 2944, 389, 2945, 3268, 1937, 1938, 1939, 390, 4966, 1940, 1397, 391, 1941, 1942, 4967, 3625, 1000, 1943, 705, 392, 393, 394, 1944, 4968, 1219, 2946, 4545, 839, 2947, 3626, 3269, 395, 4969, 1945, 4970, 4971, 396, 706, 4972, 170, 4546, 1001, 4973, 5493, 3270, 397, 707, 4547, 4974, 1526, 5494, 2651, 4975, 5386, 2652, 4371, 4065, 4976, 4977, 1002, 4978, 398, 4066, 1527, 3271, 840, 399, 4979, 708, 4980, 1003, 4067, 3627, 1946, 4981, 4068, 400, 4982, 709, 2653, 3739, 1947, 1398, 128, 1004, 3468, 1948, 2948, 1949, 1950, 1220, 1399, 4983, 4984, 401, 402, 4985, 403, 4986, 404, 405, 1951, 1952, 1005, 1953, 4987, 2477, 4548, 1954, 1955, 4988, 406, 841, 2949, 2950, 2951, 2952, 1528, 1006, 4069, 4070, 3272, 4549, 407, 4989, 2953, 4071, 4990, 1956, 3740, 408, 2654, 58, 2478, 4991, 2954, 4992, 1400, 1957, 4550, 409, 3469, 1958, 59, 4072, 2479, 4993, 1959, 4073, 2955, 410, 1960, 4074, 411, 842, 710, 4075, 2956, 711, 712, 412, 4994, 713, 4551, 1961, 3470, 4995, 4996, 1962, 1963, 1007, 2957, 413, 3741, 4997, 3742, 1401, 2958, 1964, 3743, 1965, 60, 5387, 3628, 3744, 2959, 5388, 1966, 1529, 171, 2960, 3273, 4076, 1008, 4552, 1530, 61, 714, 1531, 2961, 3745, 3746, 3471, 3747, 2962, 4553, 4998, 4077, 4999, 4372, 1009, 2963, 3274, 1532, 715, 1221, 3275, 3472, 5000, 5495, 1010, 1402, 1967, 1968, 1222, 1969, 62, 414, 1970, 1971, 1972, 415, 2655, 5001, 843, 3473, 1973, 2964, 1011, 4373, 716, 416, 417, 4554, 1974, 1975, 5002, 3276, 3748, 3474, 3749, 418, 1223, 1976, 844, 2656, 1977, 5003, 1978, 63, 3277, 3475, 2965, 2657, 3476, 4078, 4555, 1979, 8, 4556, 5004, 3750, 3477, 1980, 1981, 1224, 1982, 1012, 1403, 2658, 5496, 1983, 2659, 419, 717, 3478, 718, 3278, 420, 3751, 1404, 1984, 3479, 4079, 5005, 5006, 1225, 2660, 64, 3752, 5007, 2966, 65, 5008, 3279, 4557, 5009, 5010, 1985, 2967, 3280, 3480, 2661, 2662, 172, 1986, 1405, 2480, 1406, 421, 1013, 2968, 422, 423, 173, 1533, 1987, 2969, 174, 4558, 1988, 1534, 424, 1989, 5389, 4559, 1226, 1227, 1228, 1229, 2663, 3481, 4080, 3753, 66, 5497, 1990, 2664, 3281, 3754, 3482, 3755, 3483, 3282, 1230, 3283, 3484, 3485, 5498, 3284, 1991, 4081, 1992, 1993, 1994, 3285, 1231, 3756, 425, 3757, 1014, 1995, 2665, 4082, 4083, 5011, 3486, 4560, 1535, 426, 3629, 4084, 5499, 4085, 4561, 1232, 427, 428, 3286, 429, 3758, 3759, 1996, 430, 1997, 1407, 1998, 3487, 2970, 431, 845, 1999, 2971, 129, 5012, 5390, 2972, 2000, 2666, 4562, 432, 4563, 5500, 5013, 2001, 719, 4086, 5014, 2002, 4564, 5015, 2003, 433, 5016, 4565, 2004, 1015, 2973, 4087, 2005, 434, 2974, 1233, 2006, 5017, 2007, 3287, 67, 2481, 720, 2975, 5018, 4566, 4088, 4089, 846, 5019, 2667, 435, 5501, 2976, 2977, 2668, 2978, 2008, 4567, 5020, 1234, 5021, 5022, 1408, 5023, 2669, 5024, 1409, 3760, 5025, 3488, 1235, 436, 3761, 2009, 2010, 4568, 2979, 5026, 2011, 2980, 5027, 2981, 5028, 2012, 4569, 1016, 3489, 5502, 3630, 3762, 437, 4090, 5391, 130, 3288, 438, 5029, 3763, 5030, 439, 5031, 68, 2013, 4091, 4374, 2014, 3289, 4570, 3631, 440, 721, 3490, 441, 2015, 2670, 2482, 442, 4571, 2483, 1236, 5032, 3632, 443, 444, 5033, 5034, 1017, 4572, 69, 3764, 4573, 2016, 445, 446, 5392, 5393, 2982, 2671, 2672, 1018, 2983, 2017, 4092, 175, 2673, 176, 3290, 177, 9, 2984, 2985, 2986, 5035, 2987, 2018, 3633, 2988, 2019, 2020, 178, 3491, 2989, 10, 4093, 447, 448, 2021, 847, 4094, 2022, 70, 1019, 179, 2484, 5036, 1237, 5037, 4574, 1536, 2485, 722, 449, 71, 450, 3291, 1238, 723, 1239, 2486, 5038, 4095, 848, 4096, 451, 72, 4575, 2023, 2674, 1410, 4097, 3765, 452, 724, 3492, 3493, 2990, 73, 849, 11, 4576, 2675, 2024, 2991, 2992, 2025, 4098, 4099, 5503, 5039, 74, 3634, 2026, 850, 2993, 2994, 5040, 2995, 2996, 5041, 2027, 2997, 2998, 2028, 2487, 2676, 2029, 2999, 2030, 4100, 3000, 2031, 725, 5042, 3766, 2032, 5394, 3001, 1020, 453, 726, 3494, 2677, 4577, 4101, 454, 75, 1240, 2033, 5043, 2678, 5504, 3002, 2034, 2035, 2036, 2037, 2038, 3495, 455, 1241, 2679, 3003, 2039, 4102, 2680, 4103, 4104, 3004, 2040, 1242, 1243, 4578, 2041, 1021, 76, 1411, 2681, 2042, 5044, 3005, 180, 1022, 5505, 727, 3767, 4105, 131, 2043, 456, 3006, 2488, 2044, 4579, 2489, 3635, 2045, 5045, 3007, 2046, 5046, 728, 5047, 2047, 3636, 77, 3768, 3496, 457, 3497, 3637, 5048, 458, 729, 1244, 730, 3498, 1023, 851, 1024, 78, 4106, 2048, 2049, 1025, 5049, 4375, 5050, 2050, 5051, 3638, 5506, 1245, 3008, 2051, 4107, 2052, 731, 1537, 1246, 3292, 5052, 459, 5507, 460, 4376, 5053, 3009, 5054, 1412, 5055, 2053, 4580, 1247, 3010, 732, 2490, 5056, 4581, 2054, 2055, 2682, 5057, 5058, 5059, 1026, 5395, 2491, 2492, 733, 5060, 1248, 5061, 4582, 5062, 2056, 3499, 3500, 2057, 734, 2683, 2058, 852, 3769, 4108, 2493, 3770, 1027, 2059, 5396, 3501, 5063, 4109, 5064, 5065, 2060, 5066, 2061, 4110, 4583, 2062, 4584, 5067, 3771, 5508, 2063, 2684, 5068, 4377, 461, 2064, 5509, 2065, 2685, 5069, 79, 4111, 1249, 2066, 1028, 2067, 1029, 1030, 735, 2068, 736, 3293, 3011, 3294, 4112, 462, 3012, 737, 1031, 4113, 5070, 1032, 3502, 4585, 2069, 463, 3503, 2070, 4586, 4114, 4115, 1250, 464, 5071, 1033, 3772, 4116, 5072, 1034, 2494, 4410, 738, 465, 4117, 466, 853, 4118, 4119, 739, 2686, 467, 468, 1035, 1538, 2071, 3013, 469, 854, 470, 855, 2072, 5397, 80, 3504, 5510, 471, 5073, 472, 2073, 1036, 2074, 2075, 5074, 2076, 4120, 2077, 5075, 3773, 2078, 2079, 3639, 5511, 5076, 2687, 4587, 1539, 473, 5512, 3295, 3505, 5077, 2080, 2688, 3506, 1037, 5398, 2081, 1038, 5078, 181, 5079, 4121, 474, 3640, 1251, 2082, 1540, 5080, 1039, 3774, 3641, 1413, 4122, 475, 4411, 1414, 5399, 5400, 5401, 3014, 5402, 3507, 1415, 5403, 3508, 5081, 3015, 4123, 1541, 1040, 3016, 1542, 4124, 1041, 3017, 1416, 4125, 2083, 4126, 1417, 4378, 4127, 5082, 476, 1418, 5083, 4128, 3018, 5084, 1252, 1042, 3775, 2084, 4588, 3019, 2495, 3020, 4129, 5085, 477, 3021, 2689, 3642, 1043, 5086, 1419, 5087, 4130, 478, 3643, 1044, 5088, 1253, 2496, 4589, 479, 1420, 3022, 2085, 3023, 5089, 4379, 1421, 1422, 2086, 1423, 1424, 1425, 5090, 1426, 3024, 740, 2690, 5513, 1254, 182, 4131, 4132, 2691, 4133, 2087, 2088, 4134, 3025, 4135, 480, 2089, 1045, 4136, 5514, 741, 3026, 1427, 3509, 4137, 3027, 2090, 481, 3028, 2497, 4590, 1428, 2091, 4380, 856, 1046, 4591, 482, 1429, 5091, 5515, 183, 5516, 184, 4138, 1047, 4139, 2092, 1048, 4140, 483, 4592, 5092, 1430, 4381, 1543, 3029, 5517, 81, 4141, 1431, 742, 2093, 3510, 1049, 2498, 2499, 1432, 3511, 1433, 4142, 484, 4143, 2094, 5093, 2500, 743, 5094, 3512, 2501, 132, 2095, 5095, 2692, 1255, 82, 3776, 83, 3513, 84, 2096, 5096, 2097, 3296, 1256, 485, 2693, 2098, 5518, 486, 2099, 85, 2100, 5097, 2101, 5098, 5099, 2502, 2102, 1050, 5100, 4593, 3297, 3298, 744, 3030, 5101, 5102, 4144, 5103, 4594, 2503, 487, 3299, 2504, 5104, 3031, 4595, 86, 2103, 3777, 2104, 2105, 4382, 2694, 4596, 5105, 1051, 2106, 3032, 5106, 488, 1052, 5107, 2505, 745, 4412, 746, 5404, 1257, 747, 748, 1053, 2107, 3514, 2108, 3515, 2109, 4597, 3033, 4145, 2110, 4598, 2111, 2112, 3516, 87, 5108, 1054, 2506, 749, 4599, 2113, 4600, 750, 3300, 4146, 5109, 3034, 5519, 489, 3035, 4601, 5110, 4147, 3517, 88, 3518, 1258, 5520, 490, 1055, 5521, 3301, 5522, 1056, 1057, 3036, 5111, 4148, 4602, 2114, 3037, 1058, 4149, 857, 3302, 5112, 4150, 89, 2115, 4603, 3519, 2116, 3644, 2117, 751, 2507, 2118, 5113, 4151, 3645, 1259, 5114, 752, 4604, 5115, 1544, 3038, 4152, 5523, 2119, 753, 491, 754, 3778, 5524, 3039, 3040, 1545, 1059, 1434, 5116, 3041, 5117, 3303, 1435, 3042, 1546, 2120, 5118, 2695, 492, 3646, 3779, 2508, 1060, 3780, 5119, 4153, 4383, 3781, 90, 185, 493, 91, 5120, 5121, 3520, 3521, 3304, 3782, 1260, 4154, 3783, 2121, 4155, 2122, 2123, 2124, 2696, 3784, 1261, 3522, 3305, 92, 4605, 4156, 4157, 2125, 4606, 1262, 2126, 3043, 3044, 2697, 2127, 3523, 2128, 2129, 5122, 3785, 3647, 494, 2509, 5525, 3524, 3786, 3306, 186, 2130, 3045, 5123, 5124, 1263, 2698, 3307, 3525, 5125, 2131, 495, 4158, 5126, 3046, 93, 4607, 1264, 2132, 4159, 3526, 496, 3047, 2133, 5127, 3308, 2134, 5128, 2135, 755, 2699, 133, 2136, 2137, 2138, 3787, 2700, 5405, 1436, 3788, 2139, 5129, 497, 4160, 2701, 2140, 4608, 5130, 5131, 1265, 5406, 5132, 2141, 5526, 498, 3789, 858, 5133, 1266, 1547, 3527, 3528, 2142, 4161, 2702, 2143, 3790, 5527, 2510, 1437, 4162, 4163, 756, 1267, 5134, 3791, 94, 4609, 757, 2144, 2145, 5528, 2146, 2147, 2148, 5135, 5136, 758, 1268, 2149, 4610, 1269, 3048, 3049, 3050, 1061, 5137, 2150, 4611, 3309, 3310, 4612, 3311, 1062, 3648, 95, 5138, 2703, 499, 2151, 4164, 2511, 3529, 2704, 5139, 2152, 2153, 2154, 2155, 3051, 500, 96, 2705, 1063, 5140, 2706, 3792, 2707, 2156, 4384, 3530, 4385, 501, 5141, 1270, 97, 502, 5142, 5529, 759, 2157, 3052, 4165, 4166, 3053, 4167, 3054, 4613, 5143, 3055, 5407, 3649, 4168, 1271, 4169, 4614, 859, 503, 4170, 2158, 3531, 1272, 5144, 760, 5145, 5146, 1064, 2159, 5147, 3532, 3650, 504, 3056, 5148, 2160, 5149, 5408, 2161, 5150, 2162, 2163, 98, 1065, 1273, 2164, 4171, 2165, 5151, 5152, 3057, 5530, 5153, 4172, 5154, 4615, 2166, 1066, 1067, 761, 505, 3533, 506, 2708, 3058, 3059, 5155, 2167, 2709, 5531, 860, 2168, 2512, 12, 1068, 3060, 507, 508, 3061, 4173, 5156, 4616, 1438, 2169, 5157, 5158, 3312, 1274, 2710, 3793, 2711, 4174, 99, 2712, 2170, 5409, 5410, 509, 1439, 2171, 2172, 510, 5159, 2713, 3313, 4617, 5160, 2173, 5161, 2513, 3062, 1548, 5162, 1440, 3063, 1069, 5163, 4175, 4618, 5532, 4619, 5533, 1441, 2174, 4176, 4620, 1442, 5164, 861, 2175, 2176, 511, 5165, 762, 5166, 1070, 3651, 3064, 3794, 4177, 1071, 763, 2177, 2514, 1072, 3534, 13, 4178, 1443, 3535, 5534, 3065, 3066, 4621, 100, 5411, 2515, 101, 3795, 1444, 1445, 1446, 5167, 5168, 2178, 1275, 134, 4179, 4180, 1549, 5535, 3652, 102, 3067, 1276, 512, 4622, 4386, 4181, 3068, 14, 4182, 1073, 2179, 764, 5169, 513, 5170, 765, 2180, 2181, 4183, 4623, 1447, 5171, 135, 514, 3069, 5172, 2182, 4624, 5173, 5536, 2516, 3070, 2183, 2714, 3536, 5174, 2184, 2185, 5175, 2186, 5176, 4625, 3071, 515, 1277, 5177, 187, 4626, 516, 1278, 2187, 862, 5537, 2188, 4184, 1279, 4387, 4627, 2189, 5178, 1280, 517, 1281, 5179, 2517, 3314, 4388, 1448, 1282, 3072, 4628, 2715, 1074, 4185, 5180, 5412, 4186, 2190, 3073, 5538, 3796, 4187, 2716, 5181, 4188, 2191, 3074, 5182, 3075, 2518, 3653, 3076, 4189, 3077, 103, 3078, 3537, 518, 2717, 3654, 5183, 5184, 2192, 1449, 3079, 4190, 519, 4629, 3080, 5185, 4191, 3315, 1075, 3655, 3081, 766, 2718, 3316, 520, 767, 768, 769, 770, 3797, 3798, 521, 5186, 3082, 5187, 3083, 3084, 4630, 1283, 2193, 2194, 3085, 3086, 3317, 2195, 5539, 771, 2519, 5188, 3538, 4192, 2196, 3539, 5189, 5190, 5191, 4193, 522, 2719, 3087, 772, 3656, 2197, 3088, 1450, 3089, 2198, 2199, 5192, 4194, 523, 1284, 2720, 524, 2721, 5413, 525, 2722, 2200, 5540, 3799, 3318, 526, 3800, 2723, 2724, 2201, 3540, 3801, 5414, 1076, 1077, 1285, 1550, 5193, 527, 3541, 528, 3319, 5194, 5195, 1451, 3090, 5196, 2202, 529, 3091, 5197, 5198, 5199, 5200, 5201, 2203, 1452, 3542, 5415, 5202, 5203, 5204, 2204, 3092, 863, 3093, 3657, 3094, 15, 1453, 3095, 3096, 1551, 2205, 3658, 5205, 4389, 5541, 4631, 3659, 3660, 5206, 530, 3661, 531, 4632, 3802, 4633, 532, 2206, 4634, 2207, 5542, 4635, 4195, 2208, 3320, 4636, 4196, 5207, 3543, 104, 2209, 2520, 4637, 1552, 3097, 2210, 864, 2211, 4197, 2212, 2213, 2214, 2215, 188, 1078, 533, 4638, 5543, 2725, 1079, 1553, 2216, 5208, 4198, 4639, 2217, 5209, 4199, 1554, 2218, 4640, 4200, 2219, 534, 3803, 16, 4201, 3098, 4202, 4390, 2220, 4641, 3099, 4203, 4204, 1454, 3100, 2521, 1455, 4205, 4413, 5210, 1286, 2221, 5416, 3101, 4206, 1456, 5211, 105, 2222, 5212, 1080, 2223, 5213, 2522, 773, 535, 3804, 2224, 3102, 5214, 2225, 774, 2226, 4207, 5215, 3321, 4208, 5216, 5217, 5218, 4642, 2726, 3322, 5417, 2727, 3103, 3323, 2227, 536, 2523, 775, 5219, 3324, 4643, 5220, 5221, 2228, 5222, 1457, 3104, 4209, 3105, 5223, 4644, 537, 4210, 4211, 2524, 1287, 5544, 4212, 1081, 5545, 5224, 4645, 3325, 4213, 5225, 5226, 3106, 538, 2229, 5227, 1082, 2230, 2231, 2525, 4214, 2232, 5228, 539, 1458, 2728, 4646, 3107, 4215, 5229, 4216, 2729, 3326, 3805, 540, 3327, 5230, 5231, 541, 5232, 1083, 2233, 3108, 2234, 2526, 3328, 2235, 3544, 5233, 4217, 1459, 3545, 2236, 5234, 3109, 1084, 2237, 5546, 5235, 3329, 3546, 1288, 5236, 1289, 2730, 3110, 4647, 1085, 2238, 542, 1290, 2731, 3111, 1086, 5237, 3112, 189, 3113, 2527, 2239, 865, 3114, 5238, 3547, 543, 1291, 2240, 2732, 4391, 5418, 106, 2528, 1292, 2241, 4218, 3806, 4219, 3330, 5239, 544, 2529, 2242, 866, 3331, 4220, 3115, 2530, 2243, 2244, 5547, 3662, 3116, 5240, 3117, 776, 1293, 1294, 2733, 5241, 2245, 545, 2246, 2247, 2248, 1087, 2249, 1088, 1555, 5242, 2250, 5548, 1460, 4221, 2251, 1089, 4648, 5419, 5243, 3548, 17, 4649, 5549, 5244, 867, 2734, 4222, 1090, 3118, 5550, 546, 1461, 3332, 4650, 1091, 3119, 4651, 5551, 2252, 4223, 547, 136, 548, 4224, 5245, 2253, 2254, 2735, 5246, 2255, 777, 2531, 778, 2256, 2257, 107, 3120, 2258, 2259, 1295, 3807, 108, 2260, 3549, 2261, 5420, 3808, 2736, 2262, 549, 2532, 2533, 4225, 4652, 1462, 550, 4653, 5421, 1296, 5247, 2737, 5248, 4226, 3809, 5249, 1092, 4227, 3121, 4228, 1093, 551, 1463, 3550, 3663, 5250, 2263, 5251, 2264, 3122, 1094, 2265, 190, 2266, 2267, 5252, 1464, 2268, 4229, 3123, 5253, 4230, 2269, 2270, 3124, 2534, 1297, 3551, 4231, 4232, 552, 5254, 4233, 2271, 3125, 3552, 5255, 5256, 2272, 779, 1298, 3333, 2738, 1299, 2739, 2273, 3810, 5257, 4654, 5552, 3811, 3334, 4655, 1300, 5258, 4656, 4234, 109, 2274, 3553, 2535, 5259, 3335, 4657, 5260, 3126, 5422, 4658, 553, 554, 1095, 2740, 4659, 5423, 2275, 2536, 1301, 2537, 2741, 1302, 868, 2276, 4235, 555, 4392, 556, 1303, 2277, 1465, 557, 3554, 5553, 2538, 3812, 3664, 2278, 2742, 5261, 5424, 4236, 3555, 1096, 3665, 2279, 4237, 2280, 1304, 558, 2281, 4393, 1305, 3813, 2539, 3556, 4660, 559, 4238, 191, 869, 1556, 2282, 2283, 2540, 2284, 3666, 2285, 780, 3814, 3557, 2286, 3558, 2287, 2288, 2289, 560, 2290, 4239, 3127, 3128, 3336, 1306, 4661, 2291, 1097, 4414, 3667, 5262, 3559, 3560, 2292, 2293, 1098, 2541, 2294, 3561, 4240, 3562, 5263, 2295, 5264, 3668, 2542, 2296, 2543, 3563, 3129, 2743, 1307, 4662, 3130, 781, 2297, 2298, 4663, 2299, 2300, 1308, 2301, 5265, 3564, 4241, 2744, 3815, 1309, 4664, 2745, 3131, 1310, 2302, 2303, 4665, 5266, 2304, 3337, 4242, 3132, 3133, 3134, 4666, 2305, 5267, 3135, 3338, 2746, 110, 2306, 2307, 111, 2308, 561, 4243, 3136, 2747, 2748, 3816, 2749, 2750, 1311, 3669, 2309, 5268, 3339, 2751, 2752, 870, 3817, 4667, 4668, 2310, 3565, 3340, 2311, 4244, 4245, 4246, 562, 2312, 2313, 4247, 4248, 3566, 3567, 1466, 1467, 5269, 5270, 2753, 3818, 4249, 3670, 1468, 4250, 1312, 5271, 2754, 3137, 1469, 2755, 3568, 4251, 2314, 3341, 5272, 4669, 3569, 4252, 4670, 1313, 1099, 782, 3570, 112, 1314, 4415, 1100, 5273, 4253, 2756, 3138, 5274, 4254, 4255, 4671, 4256, 871, 1315, 3139, 3819, 5275, 3571, 4672, 563, 4257, 2757, 5425, 2315, 1101, 3572, 3820, 2544, 4394, 3140, 4673, 1102, 3573, 5554, 113, 114, 4258, 1103, 5276, 4259, 192, 3821, 3822, 5277, 1316, 3671, 1470, 4260, 2316, 4261, 4674, 4262, 3141, 3142, 3143, 3574, 2317, 4263, 5278, 1317, 2318, 3823, 1318, 1319, 3575, 1320, 2319, 5279, 2320, 872, 5555, 115, 5280, 3144, 2321, 2545, 5281, 2322, 2758, 3672, 2323, 4264, 2324, 2325, 2326, 564, 2327, 2328, 5556, 193, 2759, 4265, 1104, 5282, 2329, 2330, 3145, 3824, 2331, 4266, 4267, 5557, 4268, 4269, 3825, 5283, 2332, 2760, 4270, 1321, 3342, 2761, 565, 1471, 4271, 3146, 2333, 2546, 3673, 4272, 3674, 3147, 4273, 5284, 2334, 5285, 2335, 566, 116, 1322, 567, 3148, 4675, 568, 4676, 569, 4677, 5286, 3576, 570, 3577, 4274, 4275, 4276, 4277, 1557, 2336, 18, 1323, 2337, 1105, 2338, 3826, 2339, 3827, 19, 2340, 2547, 1324, 2341, 783, 117, 784, 4278, 3149, 571, 2342, 2343, 2344, 4279, 572, 4280, 2345, 4395, 4281, 2346, 3675, 873, 4678, 5287, 2347, 2762, 3828, 2763, 2348, 3829, 3830, 137, 573, 2349, 2350, 574, 2764, 5288, 3831, 1472, 575, 2765, 3343, 5289, 2351, 1325, 1106, 2352, 3150, 2353, 2766, 576, 3832, 3833, 3344, 2354, 577, 3151, 3345, 3152, 4282, 4283, 2767, 5290, 5291, 4284, 2355, 1558, 2356, 4285, 3834, 5292, 4679, 1559, 3578, 3676, 1107, 5558, 4286, 2357, 5293, 194, 2358, 5426, 2359, 3579, 578, 1108, 2360, 3580, 4287, 1473, 3153, 3346, 5427, 1109, 579, 580, 1326, 3835, 5559, 581, 4288, 2768, 785, 2361, 5294, 3581, 2769, 2770, 4289, 2362, 3347, 786, 4680, 1560, 874, 5295, 1474, 2771, 2548, 2772, 582, 5560, 1327, 1328, 5296, 4681, 3154, 5297, 2773, 3677, 3348, 3582, 5298, 5299, 4290, 1475, 5300, 195, 5301, 3349, 5302, 5561, 583, 3836, 2363, 787, 3350, 3351, 5303, 2774, 1561, 5304, 5562, 5305, 2549, 4682, 2364, 5563, 3837, 5306, 5564, 3352, 3155, 5307, 3156, 788, 3583, 5308, 3838, 4683, 1476, 3678, 584, 118, 3584, 585, 586, 2365, 196, 3157, 4291, 4292, 587, 2775, 4293, 2366, 3158, 2367, 5309, 588, 5310, 1477, 4294, 2368, 5311, 1110, 119, 4295, 5312, 3353, 5313, 5314, 4296, 1562, 5315, 20, 789, 138, 5316, 2369, 1329, 5317, 790, 5318, 2776, 4297, 197, 2777, 589, 3159, 2370, 4396, 791, 5319, 3160, 5428, 3839, 3840, 4298, 2778, 590, 5320, 591, 2371, 592, 120, 1563, 3585, 1111, 3679, 3354, 1112, 2550, 3161, 4299, 593, 3355, 1478, 3162, 3163, 5321, 2551, 1479, 4300, 4397, 792, 3164, 3841, 3842, 5322, 4684, 4685, 3165, 3356, 3843, 4686, 1330, 4687, 4688, 5323, 1331, 2372, 4301, 2373, 4302, 2374, 5429, 5565, 5566, 2375, 2376, 2377, 3166, 5430, 3167, 2378, 2552, 198, 3357, 1480, 4303, 5324, 4304, 5325, 3844, 5326, 2553, 3358, 121, 2554, 793, 3680, 4305, 4306, 594, 5327, 4307, 4689, 3168, 4308, 2379, 4309, 4310, 4311, 5328, 1564, 2380, 4312, 4313, 2381, 1113, 3681, 4690, 4691, 4692, 1114, 3359, 4314, 2779, 3360, 4315, 3845, 1332, 1115, 4693, 4694, 595, 2555, 4316, 2556, 1333, 5329, 2382, 4695, 4317, 3169, 3170, 1334, 5330, 2383, 3361, 4318, 4319, 4320, 4321, 3362, 3171, 5331, 5567, 5568, 1335, 1336, 5332, 2384, 5333, 4322, 794, 1116, 1117, 3172, 4696, 2385, 1337, 199, 596, 2386, 2387, 597, 598, 795, 2388, 5334, 599, 5335, 2389, 2390, 5336, 3173, 4323, 5337, 600, 4416, 1118, 2780, 2557, 796, 3846, 5431, 601, 2391, 2781, 797, 3174, 602, 2392, 3586, 4324, 3175, 2393, 4697, 1481, 122, 5338, 3176, 4325, 3847, 3177, 603, 5339, 1338, 5340, 1119, 1120, 2394, 2558, 4698, 798, 2395, 200, 604, 3587, 2396, 201, 4326, 799, 4398, 4699, 5341, 4700, 1121, 605, 4327, 1482, 4399, 4400, 4328, 4329, 4330, 606, 3682, 3588, 607, 5342, 5343, 5344, 1122, 4331, 4701, 4702, 5345, 2397, 875, 2398, 4703, 1339, 2399, 5346, 5347, 2400, 1123, 2401, 800, 3683, 2782, 3848, 801, 3589, 2402, 608, 609, 1483, 3590, 610, 5348, 611, 2403, 3684, 2404, 4332, 876, 3849, 3178, 3363, 1484, 612, 3850, 4333, 5349, 3179, 3591, 4334, 3364, 2405, 3180, 613, 2406, 2407, 2408, 3365, 3366, 2409, 4335, 4336, 4337, 877, 1340, 1124, 3367, 4338, 1565, 1125, 123, 2410, 3851, 802, 4339, 4704, 4705, 2411, 2783, 2559, 1485, 1126, 3852, 4340, 4341, 4342, 3592, 4343, 1341, 878, 1127, 1486, 879, 880, 4401, 5350, 5351, 2412, 2413, 2414, 2415, 3181, 2416, 2560, 4344, 5352, 4345, 4346, 2784, 4706, 881, 5353, 614, 4347, 3368, 139, 1342, 2561, 3182, 1343, 2417, 3685, 5354, 5355, 615, 3593, 5569, 616, 2418, 3183, 617, 4348, 4707, 5570, 3184, 4349, 4708, 21, 4709, 4710, 3369, 2562, 618, 2785, 5356, 1344, 4711}, +) + +// rowToMunicipality Reads one dataset row as a municipality. +func rowToMunicipality(row []string) *Municipality { + return &Municipality{Code: row[2], Name: row[1], StateCode: row[0]} +} + +// GetMunicipalities Returns Brazilian municipalities published by the IBGE, optionally filtered by state. +// +// If `stateCode` is provided, only municipalities of that state are returned. If it is +// omitted, every municipality of every state is returned, sorted with `localeCompare` in the +// "pt-BR" locale so accented names land where a Brazilian reader expects them. Every per-state +// list is sorted the same way. +// +// Only an omitted (or `undefined`) `stateCode` asks for the full list: any other value that is +// not a known state code, `null` and `""` included, returns `[]`. +// +// The state code is matched exactly, case included: `getMunicipalities("sp")` returns `[]` where +// `getMunicipalities("SP")` returns the 645 São Paulo municipalities. +// +// @see Official: https://servicodados.ibge.gov.br/api/docs/localidades +func GetMunicipalities(stateCode *string) []*Municipality { + municipalities := []*Municipality{} + rows := runtime.DataAll(MUNICIPALITIES) + if (stateCode != nil) { + rows = runtime.DataRows(MUNICIPALITIES, *stateCode) + } + for _, row := range rows { + municipalities = append(municipalities, rowToMunicipality(row)) + } + return municipalities +} diff --git a/spec/bridge/out/go/go.mod b/spec/bridge/out/go/go.mod new file mode 100644 index 000000000..ffa32fe86 --- /dev/null +++ b/spec/bridge/out/go/go.mod @@ -0,0 +1,3 @@ +module brazilianutils/bridge + +go 1.22 diff --git a/spec/bridge/out/go/is_valid_cnpj/is_valid_cnpj.go b/spec/bridge/out/go/is_valid_cnpj/is_valid_cnpj.go new file mode 100644 index 000000000..dd670f68e --- /dev/null +++ b/spec/bridge/out/go/is_valid_cnpj/is_valid_cnpj.go @@ -0,0 +1,112 @@ +// Code generated from spec/bridge/source/is-valid-cnpj.ts. DO NOT EDIT. + +// Package is_valid_cnpj holds the generated is-valid-cnpj utility. +package is_valid_cnpj + +import "brazilianutils/bridge/runtime" + +var class0 = runtime.CharClass{{0x30, 0x39}, {0x41, 0x5a}} +var class1 = runtime.CharClass{{0x9, 0xd}, {0x20, 0x20}, {0x2d, 0x2f}, {0xa0, 0xa0}, {0x1680, 0x1680}, {0x2000, 0x200a}, {0x2028, 0x2029}, {0x202f, 0x202f}, {0x205f, 0x205f}, {0x3000, 0x3000}, {0xfeff, 0xfeff}} +var class2 = runtime.CharClass{{0x30, 0x39}} +var class3 = runtime.CharClass{{0x41, 0x5a}} +var class4 = runtime.CharClass{{0x30, 0x39}, {0x41, 0x5a}, {0x61, 0x7a}} + +var PATTERN_ALPHANUMERIC_FORMAT = []runtime.PatternStep{ + {Class: class0, Min: 2, Max: 2, Capture: false}, + {Class: class1, Min: 0, Max: -1, Capture: false}, + {Class: class0, Min: 3, Max: 3, Capture: false}, + {Class: class1, Min: 0, Max: -1, Capture: false}, + {Class: class0, Min: 3, Max: 3, Capture: false}, + {Class: class1, Min: 0, Max: -1, Capture: false}, + {Class: class0, Min: 4, Max: 4, Capture: false}, + {Class: class1, Min: 0, Max: -1, Capture: false}, + {Class: class2, Min: 2, Max: 2, Capture: false}, +} + +var PATTERN_NUMERIC_FORMAT = []runtime.PatternStep{ + {Class: class2, Min: 2, Max: 2, Capture: false}, + {Class: class1, Min: 0, Max: -1, Capture: false}, + {Class: class2, Min: 3, Max: 3, Capture: false}, + {Class: class1, Min: 0, Max: -1, Capture: false}, + {Class: class2, Min: 3, Max: 3, Capture: false}, + {Class: class1, Min: 0, Max: -1, Capture: false}, + {Class: class2, Min: 4, Max: 4, Capture: false}, + {Class: class1, Min: 0, Max: -1, Capture: false}, + {Class: class2, Min: 2, Max: 2, Capture: false}, +} + +var FIRST_DIGIT_WEIGHTS = []int64{5, 4, 3, 2, 9, 8, 7, 6, 5, 4, 3, 2} +var SECOND_DIGIT_WEIGHTS = []int64{6, 5, 4, 3, 2, 9, 8, 7, 6, 5, 4, 3, 2} + + + +// IsValidCnpjOptions Options of `isValidCnpj`. +type IsValidCnpjOptions struct { + // Which CNPJ format to accept: `1` numeric only, `2` alphanumeric (default: `1`). + Version *int64 +} + + + +// IsValidCnpj Validates if a CNPJ (Cadastro Nacional da Pessoa Jurídica) is valid. +// +// Supports both numeric (version 1) and alphanumeric (version 2) CNPJ formats, and accepts the +// usual mask characters (`.`, `-`, `/`) and whitespace around and between groups. +func IsValidCnpj(cnpj string, options *IsValidCnpjOptions) bool { + var optionsVersion int64 = -1 + if options != nil && options.Version != nil { + optionsVersion = *options.Version + } + trimmed := runtime.JsTrim(cnpj) + if (optionsVersion == 2) { + cleaned := runtime.Upper(runtime.KeepClass(class4, cnpj)) + if runtime.ClassHas(class3, cleaned) { + if !runtime.PatternTest(PATTERN_ALPHANUMERIC_FORMAT, runtime.Upper(trimmed)) { + return false + } + return hasValidChecksum(cleaned) + } + } + numeric := runtime.KeepClass(class2, cnpj) + if !runtime.PatternTest(PATTERN_NUMERIC_FORMAT, trimmed) { + return false + } + if isRepeated(numeric) { + return false + } + return hasValidChecksum(numeric) +} + +// checkDigit Computes one CNPJ check digit from the base and its weight vector. +func checkDigit(base string, weights []int64) int64 { + var sum int64 = 0 + for index := int64(0); index < int64(len(weights)); index++ { + sum = (sum + ((int64(runtime.CodeAt(base, int(index))) - 48) * weights[index])) + } + var remainder int64 = (sum % 11) + if (remainder < 2) { + return 0 + } + return (11 - remainder) +} + +// hasValidChecksum Whether both check digits of a sanitized 14 character CNPJ match its base. +func hasValidChecksum(cnpj string) bool { + if ((int64(runtime.CodeAt(cnpj, int(12))) - 48) != checkDigit(cnpj, FIRST_DIGIT_WEIGHTS)) { + return false + } + return ((int64(runtime.CodeAt(cnpj, int(13))) - 48) == checkDigit(cnpj, SECOND_DIGIT_WEIGHTS)) +} + +// isRepeated Whether every character of the value is the same one. +func isRepeated(value string) bool { + if (int64(runtime.Len(value)) == 0) { + return false + } + for index := int64(1); index < int64(runtime.Len(value)); index++ { + if (int64(runtime.CodeAt(value, int(index))) != int64(runtime.CodeAt(value, int(0)))) { + return false + } + } + return true +} diff --git a/spec/bridge/out/go/runtime/runtime.go b/spec/bridge/out/go/runtime/runtime.go new file mode 100644 index 000000000..7a1c29b10 --- /dev/null +++ b/spec/bridge/out/go/runtime/runtime.go @@ -0,0 +1,465 @@ +// Package runtime holds everything the generated Go code needs that is not plain syntax. +// +// Strings are indexed by code point, not by byte, so that the generated code means the same +// thing it does in the other targets. +package runtime + +import ( + "encoding/json" + "errors" + "io" + "net/http" + "os" + "regexp" + "strings" + "time" +) + +// CharClass is a set of code points, as sorted non overlapping ranges. +type CharClass [][2]rune + +// PatternStep repeats a class between Min and Max times; Max -1 means unbounded. +type PatternStep struct { + Class CharClass + Min int + Max int + Capture bool +} + +// The code points JavaScript's trim() strips. Go's strings.TrimSpace is a different set. +var jsWhitespace = CharClass{ + {0x09, 0x0d}, {0x20, 0x20}, {0xa0, 0xa0}, {0x1680, 0x1680}, {0x2000, 0x200a}, + {0x2028, 0x2029}, {0x202f, 0x202f}, {0x205f, 0x205f}, {0x3000, 0x3000}, {0xfeff, 0xfeff}, +} + +// InClass reports whether a code point belongs to a class. +func InClass(class CharClass, code rune) bool { + for _, span := range class { + if code >= span[0] && code <= span[1] { + return true + } + } + + return false +} + +// Len counts the code points of a value. +func Len(value string) int { + return len([]rune(value)) +} + +// CodeAt reads one code point, or -1 when the index is out of range. +func CodeAt(value string, index int) int { + if index < 0 { + return -1 + } + + position := 0 + + for _, char := range value { + if position == index { + return int(char) + } + + position++ + } + + return -1 +} + +// Slice takes the code points between two indexes. +func Slice(value string, from int, to int) string { + runes := []rune(value) + + if from < 0 { + from = 0 + } + + if to > len(runes) { + to = len(runes) + } + + if from >= to { + return "" + } + + return string(runes[from:to]) +} + +// ClassHas reports whether any character of the value belongs to the class. +func ClassHas(class CharClass, value string) bool { + for _, char := range value { + if InClass(class, char) { + return true + } + } + + return false +} + +// KeepClass keeps only the characters of the value that belong to the class. +func KeepClass(class CharClass, value string) string { + var kept strings.Builder + + for _, char := range value { + if InClass(class, char) { + kept.WriteRune(char) + } + } + + return kept.String() +} + +// PatternTest runs a compiled pattern against the whole value, greedily and without backtracking. +func PatternTest(steps []PatternStep, value string) bool { + runes := []rune(value) + index := 0 + + for _, step := range steps { + count := 0 + + for (step.Max < 0 || count < step.Max) && index < len(runes) && InClass(step.Class, runes[index]) { + index++ + count++ + } + + if count < step.Min { + return false + } + } + + return index == len(runes) +} + +// JsTrim strips the code points JavaScript's trim() strips. +func JsTrim(value string) string { + return strings.TrimFunc(value, func(char rune) bool { return InClass(jsWhitespace, char) }) +} + +// PadStart left pads the value with a filler up to a length, counted in code points. +func PadStart(value string, length int, filler string) string { + missing := length - Len(value) + + if missing <= 0 { + return value + } + + return strings.Repeat(filler, missing) + value +} + +// Upper uppercases a value. +func Upper(value string) string { + return strings.ToUpper(value) +} + +// Repeat repeats a value. +func Repeat(value string, times int) string { + if times <= 0 { + return "" + } + + return strings.Repeat(value, times) +} + +// DataGroup names the rows of one key of a dataset. +type DataGroup struct { + Key string + Rows []int +} + +// Dataset holds the rows of a table in the two orders the generated code asks for. +type Dataset struct { + all [][]string + byKey map[string][][]string +} + +// NewDataset materialises a dataset, resolving both orders once. +func NewDataset(rows [][]string, groups []DataGroup, fullOrder []int) *Dataset { + table := &Dataset{all: make([][]string, 0, len(fullOrder)), byKey: make(map[string][][]string, len(groups))} + + for _, index := range fullOrder { + table.all = append(table.all, rows[index]) + } + + for _, group := range groups { + of := make([][]string, 0, len(group.Rows)) + + for _, index := range group.Rows { + of = append(of, rows[index]) + } + + table.byKey[group.Key] = of + } + + return table +} + +// DataAll returns every row of a dataset, in the baked full order. +func DataAll(table *Dataset) [][]string { + return table.all +} + +// DataRows returns the rows whose first column is the key given, empty when the key is unknown. +func DataRows(table *Dataset, key string) [][]string { + if rows, ok := table.byKey[key]; ok { + return rows + } + + return [][]string{} +} + +// HttpResponse is what a provider answered: the status, whether it counts as a success, and +// the decoded body. +type HttpResponse struct { + Status int64 + Ok bool + Body any +} + +// httpTarget is the origin every request is sent to instead of its own, when one is set. +// +// This is the conformance hook: the cross language replay points all seven targets at one +// local server, the same way the JavaScript suite points fetch at a mock. +func httpTarget(url string) string { + base := os.Getenv("BRUTILS_BRIDGE_HTTP_ORIGIN") + + if base == "" { + return url + } + + return base + "/" + originPrefix.ReplaceAllString(url, "") +} + +var originPrefix = regexp.MustCompile(`^https?://`) + +var httpClient = &http.Client{Timeout: 15 * time.Second} + +// HttpGet performs an HTTP GET, retrying a transient transport failure with a linear backoff. +func HttpGet(url string, retries int64, retryDelayMs int64) *HttpResponse { + target := httpTarget(url) + + for attempt := int64(0); ; attempt++ { + answer, err := httpClient.Get(target) + + if err != nil { + if attempt >= retries { + return &HttpResponse{Status: 0, Ok: false, Body: nil} + } + + time.Sleep(time.Duration(retryDelayMs*(attempt+1)) * time.Millisecond) + + continue + } + + raw, readErr := io.ReadAll(answer.Body) + answer.Body.Close() + + var body any + + if readErr == nil { + if json.Unmarshal(raw, &body) != nil { + body = nil + } + } + + status := int64(answer.StatusCode) + + return &HttpResponse{Status: status, Ok: status >= 200 && status < 300, Body: body} + } +} + +// ListHas reports whether a list holds a value. +func ListHas(items []string, value string) bool { + for _, item := range items { + if item == value { + return true + } + } + + return false +} + +// jsonField reads one field of a JSON body, treating anything that is not an object as empty. +func jsonField(body any, key string) any { + object, ok := body.(map[string]any) + + if !ok { + return nil + } + + return object[key] +} + +// JsonString reads a string field of a JSON body, answering "" when it is missing. +func JsonString(body any, key string) string { + found, ok := jsonField(body, key).(string) + + if !ok { + return "" + } + + return found +} + +// JsonInt reads an integer field of a JSON body, answering -1 when it is missing. +func JsonInt(body any, key string) int64 { + found, ok := jsonField(body, key).(float64) + + if !ok { + return -1 + } + + return int64(found) +} + +// JsonTruthy reports whether a field of a JSON body is truthy, the way JavaScript reads it. +func JsonTruthy(body any, key string) bool { + switch found := jsonField(body, key).(type) { + case nil: + return false + case bool: + return found + case float64: + return found != 0 + case string: + return found != "" + default: + return true + } +} + +// JsonIsTrue reports whether a field of a JSON body is exactly true. +func JsonIsTrue(body any, key string) bool { + found, ok := jsonField(body, key).(bool) + + return ok && found +} + +// Error is a failure raised by the generated code. Go has no exception hierarchy, so the kinds +// the source declared travel with the value. +type Error struct { + Kinds []string + Message string +} + +// Error returns the message. +func (e *Error) Error() string { + return e.Message +} + +// Kind returns the most specific kind of the failure. +func (e *Error) Kind() string { + if len(e.Kinds) == 0 { + return "" + } + + return e.Kinds[0] +} + +// NewError builds a failure of the given kinds. +func NewError(kinds []string, message string) error { + return &Error{Kinds: kinds, Message: message} +} + +// IsKind reports whether an error is of a kind, its bases included. +func IsKind(err error, kind string) bool { + var found *Error + + if !errors.As(err, &found) { + return false + } + + for _, candidate := range found.Kinds { + if candidate == kind { + return true + } + } + + return false +} + +// Outcome is what one attempt of a race ended with. +type Outcome struct { + Ok bool + Value any + Kinds []string +} + +// Attempts holds the running attempts of a race and what each one ended with. +type Attempts struct { + settled chan Outcome + total int + Outcomes []Outcome +} + +// StartAll starts one attempt per item, all at once. +// +// This is the only concurrency primitive of the portable subset: the author never writes a +// goroutine, and the emitter never has to decide where one belongs. +func StartAll(run func(string, string) (any, error), items []string, argument string) *Attempts { + attempts := &Attempts{settled: make(chan Outcome, len(items)), total: len(items)} + + for _, item := range items { + go func(item string) { + value, err := run(item, argument) + + if err != nil { + kinds := []string{} + + var raised *Error + + if errors.As(err, &raised) { + kinds = raised.Kinds + } + + attempts.settled <- Outcome{Ok: false, Kinds: kinds} + + return + } + + attempts.settled <- Outcome{Ok: true, Value: value} + }(item) + } + + return attempts +} + +// FirstSuccessOf returns the value of the first attempt that succeeds, or the zero value once +// every attempt has failed. +func FirstSuccessOf[T any](attempts *Attempts) T { + var zero T + + for len(attempts.Outcomes) < attempts.total { + outcome := <-attempts.settled + attempts.Outcomes = append(attempts.Outcomes, outcome) + + if outcome.Ok { + found, ok := outcome.Value.(T) + + if ok { + return found + } + + return zero + } + } + + return zero +} + +// AnyFailedWith reports whether any attempt failed with a given error kind. +func AnyFailedWith(attempts *Attempts, kind string) bool { + for _, outcome := range attempts.Outcomes { + if outcome.Ok { + continue + } + + for _, candidate := range outcome.Kinds { + if candidate == kind { + return true + } + } + } + + return false +} diff --git a/spec/bridge/out/java/AddressInfo.java b/spec/bridge/out/java/AddressInfo.java new file mode 100644 index 000000000..52e4cab7a --- /dev/null +++ b/spec/bridge/out/java/AddressInfo.java @@ -0,0 +1,25 @@ +/** The address `getAddressInfoByCep` returns for a CEP. */ +public final class AddressInfo { + /** The 8 digit CEP, no mask. */ + public String cep; + + /** Two letter state code, e.g. "SP". */ + public String state; + + /** City name. */ + public String city; + + /** Neighborhood name, empty when the CEP covers a whole city. */ + public String neighborhood; + + /** Street name, empty when the CEP covers a whole city. */ + public String street; + + public AddressInfo(String cep, String state, String city, String neighborhood, String street) { + this.cep = cep; + this.state = state; + this.city = city; + this.neighborhood = neighborhood; + this.street = street; + } +} diff --git a/spec/bridge/out/java/CepProviderFailure.java b/spec/bridge/out/java/CepProviderFailure.java new file mode 100644 index 000000000..68168ed15 --- /dev/null +++ b/spec/bridge/out/java/CepProviderFailure.java @@ -0,0 +1,6 @@ +/** Raised inside a provider that did not answer. Only whether a failure was a not found is looked at when the provider failures are aggregated, so this one never leaves the module. */ +public class CepProviderFailure extends RuntimeException { + public CepProviderFailure(String message) { + super(message); + } +} diff --git a/spec/bridge/out/java/Conformance.java b/spec/bridge/out/java/Conformance.java new file mode 100644 index 000000000..96547671e --- /dev/null +++ b/spec/bridge/out/java/Conformance.java @@ -0,0 +1,266 @@ +// Code generated by spec/bridge/conformance/drivers.ts. DO NOT EDIT. + +import java.nio.file.Files; +import java.nio.file.Path; + +/** Replays the recorded tables against the generated Java. */ +public final class Conformance { + private static final String TARGET = "java"; + + private Conformance() {} + + /** One utility's score. */ + private static final class Tally { + private int passed; + private int failed; + private int skipped; + } + + /** Reads back the three characters the table format escapes. */ + private static String unescape(String value) { + return value.replace("\\t", "\t").replace("\\n", "\n").replace("\\\\", "\\"); + } + + /** Whether this target can express the call a row describes. */ + private static boolean runs(String targets) { + if (targets.equals("*")) { + return true; + } + + for (String name : targets.split("\\|", -1)) { + if (name.equals(TARGET)) { + return true; + } + } + + return false; + } + + /** Keeps a failure message readable when the answer is a five thousand row list. */ + private static String cut(String value) { + return value.length() <= 120 ? value : value.substring(0, 120); + } + + /** Counts one comparison, and shows the first few that disagree. */ + private static void report(String fn, String actual, String expected, Tally counts) { + if (actual.equals(expected)) { + counts.passed++; + + return; + } + + counts.failed++; + + if (counts.failed <= 3) { + System.err.printf("FAIL %s expected %s got %s%n", fn, cut(expected), cut(actual)); + } + } + + private static String renderGetAddressInfoByCepAddressInfo(AddressInfo value) { + return value.cep + "|" + value.state + "|" + value.city + "|" + value.neighborhood + "|" + value.street; + } + + private static String renderGetMunicipalitiesMunicipality(Municipality value) { + return value.code + "|" + value.name + "|" + value.stateCode; + } + + private static String renderListGetMunicipalitiesMunicipality(java.util.List items) { + StringBuilder out = new StringBuilder(String.valueOf(items.size())); + + for (Municipality item : items) { + out.append("\n").append(renderGetMunicipalitiesMunicipality(item)); + } + + return out.toString(); + } + + /** Replays what {@code formatCnpj} answers. */ + private static Tally checkFormatCnpj() throws java.io.IOException { + Tally counts = new Tally(); + + for (String line : Files.readString(Path.of("../../conformance/recorded/format-cnpj.tsv")).stripTrailing().split("\n", -1)) { + if (line.isEmpty() || line.startsWith("targets\t")) { + continue; + } + + String[] cells = line.split("\t", -1); + + if (!runs(cells[0])) { + counts.skipped++; + + continue; + } + + String argument0 = unescape(cells[1]); + FormatCnpjOptions options = new FormatCnpjOptions(); + boolean given = false; + + if (!cells[3].isEmpty()) { + options.pad = cells[3].equals("1"); + given = true; + } + + if (!cells[4].isEmpty()) { + options.version = Long.parseLong(cells[4]); + given = true; + } + + if (!cells[5].isEmpty()) { + options.obfuscate = cells[5].equals("1"); + given = true; + } + + String actual = FormatCnpj.formatCnpj(argument0, given ? options : null); + + report("formatCnpj", actual, unescape(cells[6]), counts); + } + + return counts; + } + + /** Replays what {@code getAddressInfoByCep} answers. */ + private static Tally checkGetAddressInfoByCep() throws java.io.IOException { + Tally counts = new Tally(); + + for (String line : Files.readString(Path.of("../../conformance/recorded/get-address-info-by-cep.tsv")).stripTrailing().split("\n", -1)) { + if (line.isEmpty() || line.startsWith("targets\t")) { + continue; + } + + String[] cells = line.split("\t", -1); + + if (!runs(cells[0])) { + counts.skipped++; + + continue; + } + + String argument0 = unescape(cells[1]); + GetAddressInfoByCepOptions options = new GetAddressInfoByCepOptions(); + boolean given = false; + + if (!cells[3].isEmpty()) { + options.providers = cells[3].equals("[]") ? java.util.List.of() : java.util.List.of(cells[3].split("\\|", -1)); + given = true; + } + + String actual; + + try { + actual = renderGetAddressInfoByCepAddressInfo(GetAddressInfoByCep.getAddressInfoByCep(argument0, given ? options : null)); + } catch (RuntimeException error) { + actual = "!" + error.getClass().getSimpleName() + "|" + error.getMessage(); + } + + report("getAddressInfoByCep", actual, unescape(cells[4]), counts); + } + + return counts; + } + + /** Replays what {@code getMunicipalities} answers. */ + private static Tally checkGetMunicipalities() throws java.io.IOException { + Tally counts = new Tally(); + + for (String line : Files.readString(Path.of("../../conformance/recorded/get-municipalities.tsv")).stripTrailing().split("\n", -1)) { + if (line.isEmpty() || line.startsWith("targets\t")) { + continue; + } + + String[] cells = line.split("\t", -1); + + if (!runs(cells[0])) { + counts.skipped++; + + continue; + } + + String argument0 = cells[1].equals("1") ? unescape(cells[2]) : null; + + String actual = renderListGetMunicipalitiesMunicipality(GetMunicipalities.getMunicipalities(argument0)); + + report("getMunicipalities", actual, unescape(cells[3]), counts); + } + + return counts; + } + + /** Replays what {@code isValidCnpj} answers. */ + private static Tally checkIsValidCnpj() throws java.io.IOException { + Tally counts = new Tally(); + + for (String line : Files.readString(Path.of("../../conformance/recorded/is-valid-cnpj.tsv")).stripTrailing().split("\n", -1)) { + if (line.isEmpty() || line.startsWith("targets\t")) { + continue; + } + + String[] cells = line.split("\t", -1); + + if (!runs(cells[0])) { + counts.skipped++; + + continue; + } + + String argument0 = unescape(cells[1]); + IsValidCnpjOptions options = new IsValidCnpjOptions(); + boolean given = false; + + if (!cells[3].isEmpty()) { + options.version = Long.parseLong(cells[3]); + given = true; + } + + String actual = String.valueOf(IsValidCnpj.isValidCnpj(argument0, given ? options : null)); + + report("isValidCnpj", actual, unescape(cells[4]), counts); + } + + return counts; + } + + public static void main(String[] args) throws java.io.IOException { + int failed = 0; + Tally counts; + + counts = checkFormatCnpj(); + failed += counts.failed; + System.out.printf( + "%s: formatCnpj %d/%d matched%s%n", + TARGET, + counts.passed, + counts.passed + counts.failed, + counts.skipped == 0 ? "" : String.format(" (%d not expressible)", counts.skipped)); + + counts = checkGetAddressInfoByCep(); + failed += counts.failed; + System.out.printf( + "%s: getAddressInfoByCep %d/%d matched%s%n", + TARGET, + counts.passed, + counts.passed + counts.failed, + counts.skipped == 0 ? "" : String.format(" (%d not expressible)", counts.skipped)); + + counts = checkGetMunicipalities(); + failed += counts.failed; + System.out.printf( + "%s: getMunicipalities %d/%d matched%s%n", + TARGET, + counts.passed, + counts.passed + counts.failed, + counts.skipped == 0 ? "" : String.format(" (%d not expressible)", counts.skipped)); + + counts = checkIsValidCnpj(); + failed += counts.failed; + System.out.printf( + "%s: isValidCnpj %d/%d matched%s%n", + TARGET, + counts.passed, + counts.passed + counts.failed, + counts.skipped == 0 ? "" : String.format(" (%d not expressible)", counts.skipped)); + + if (failed > 0) { + System.exit(1); + } + } +} diff --git a/spec/bridge/out/java/FormatCnpj.java b/spec/bridge/out/java/FormatCnpj.java new file mode 100644 index 000000000..2d0212974 --- /dev/null +++ b/spec/bridge/out/java/FormatCnpj.java @@ -0,0 +1,84 @@ +// Code generated from spec/bridge/source/format-cnpj.ts. DO NOT EDIT. + +/** `formatCnpj`, written once. */ +public final class FormatCnpj { + private FormatCnpj() {} + + private static final int[][] CLASS0 = {{0x30, 0x39}}; + private static final int[][] CLASS1 = {{0x30, 0x39}, {0x41, 0x5a}, {0x61, 0x7a}}; + + + + private static final String PATTERN = "00.000.000/0000-00"; + private static final String OBFUSCATED_PATTERN = "**.000.000/0000-**"; + + + + /** + * Formats a given CNPJ (Cadastro Nacional da Pessoa Jurídica) value. + */ + public static String formatCnpj(String value, FormatCnpjOptions options) { + long optionsVersion = -1L; + if (options != null && options.version != null) { + optionsVersion = options.version; + } + boolean optionsObfuscate = false; + if (options != null && options.obfuscate != null) { + optionsObfuscate = options.obfuscate; + } + boolean optionsPad = false; + if (options != null && options.pad != null) { + optionsPad = options.pad; + } + if (value == null) { + return ""; + } + String text = value; + String cleaned = Runtime.keepClass(CLASS0, text); + if ((optionsVersion == 2L)) { + cleaned = Runtime.keepClass(CLASS1, text).toUpperCase(java.util.Locale.ROOT); + } + String pattern = PATTERN; + if (optionsObfuscate) { + pattern = OBFUSCATED_PATTERN; + } + return layout(cleaned, pattern, optionsPad); + } + + /** + * Lays a value over a pattern. + */ + public static String layout(String value, String pattern, boolean pad) { + long slots = 0L; + for (long index = 0L; index < (long) pattern.length(); index++) { + if (((Runtime.codeAt(pattern, index) == 48L) || (Runtime.codeAt(pattern, index) == 42L))) { + slots = (slots + 1L); + } + } + String padded = value; + if (pad) { + padded = Runtime.padStart(value, slots, "0"); + } + String formatted = ""; + long cursor = 0L; + for (long index = 0L; index < (long) pattern.length(); index++) { + long slot = Runtime.codeAt(pattern, index); + if (((slot == 48L) || (slot == 42L))) { + if ((cursor >= (long) padded.length())) { + return formatted; + } + if ((slot == 42L)) { + formatted = (formatted + "*"); + } else { + formatted = (formatted + Runtime.slice(padded, cursor, (cursor + 1L))); + } + cursor = (cursor + 1L); + } else { + if ((cursor < (long) padded.length())) { + formatted = (formatted + Runtime.slice(pattern, index, (index + 1L))); + } + } + } + return formatted; + } +} diff --git a/spec/bridge/out/java/FormatCnpjOptions.java b/spec/bridge/out/java/FormatCnpjOptions.java new file mode 100644 index 000000000..50af215e6 --- /dev/null +++ b/spec/bridge/out/java/FormatCnpjOptions.java @@ -0,0 +1,11 @@ +/** Options of `formatCnpj`. */ +public final class FormatCnpjOptions { + /** Whether to left pad the value with zeros up to the number of slots in the pattern (default: `false`). */ + public Boolean pad; + + /** Which CNPJ format to read: `1` numeric only, `2` alphanumeric (default: `1`). */ + public Long version; + + /** Whether to hide the first 2 digits and the 2 check digits with `*` (default: `false`). */ + public Boolean obfuscate; +} diff --git a/spec/bridge/out/java/GetAddressInfoByCep.java b/spec/bridge/out/java/GetAddressInfoByCep.java new file mode 100644 index 000000000..a2e10ffb5 --- /dev/null +++ b/spec/bridge/out/java/GetAddressInfoByCep.java @@ -0,0 +1,145 @@ +// Code generated from spec/bridge/source/get-address-info-by-cep.ts. DO NOT EDIT. + +/** Address lookup by CEP, written once. */ +public final class GetAddressInfoByCep { + private GetAddressInfoByCep() {} + + private static final int[][] CLASS0 = {{0x30, 0x39}}; + + private static final Runtime.PatternStep[] PATTERN_CEP_FORMAT = { + new Runtime.PatternStep(CLASS0, 8, 8, false), + }; + + private static final java.util.List DEFAULT_PROVIDERS = new java.util.ArrayList(java.util.List.of("viacep", "brasilapi")); + private static final java.util.List KNOWN_PROVIDERS = new java.util.ArrayList(java.util.List.of("viacep", "widenet", "brasilapi")); + private static final long BRASIL_API_NOT_FOUND_STATUS = 404L; + private static final long HTTP_RETRIES = 2L; + private static final long HTTP_RETRY_DELAY_MS = 250L; + + + + /** + * Reads the address ViaCEP answers with. + * + * @see Based on: https://viacep.com.br/ + */ + public static AddressInfo fetchViaCep(String cep) { + Runtime.HttpResponse response = Runtime.httpGet((("https://viacep.com.br/ws/" + cep) + "/json/"), HTTP_RETRIES, HTTP_RETRY_DELAY_MS); + if (!response.ok) { + throw new CepProviderFailure("ViaCEP request failed"); + } + String found = Runtime.jsonString(response.body, "cep"); + if ((Runtime.jsonTruthy(response.body, "erro") || found.equals(""))) { + throw new GetAddressInfoByCepNotFoundError("CEP n\u00e3o encontrado"); + } + return new AddressInfo(Runtime.keepClass(CLASS0, found), Runtime.jsonString(response.body, "uf"), Runtime.jsonString(response.body, "localidade"), Runtime.jsonString(response.body, "bairro"), Runtime.jsonString(response.body, "logradouro")); + } + + /** + * Reads the address Widenet answers with. + */ + public static AddressInfo fetchWidenet(String cep) { + Runtime.HttpResponse response = Runtime.httpGet((("https://apps.widenet.com.br/busca-cep/api/cep/" + cep) + ".json"), HTTP_RETRIES, HTTP_RETRY_DELAY_MS); + if (!response.ok) { + throw new CepProviderFailure("Widenet request failed"); + } + String found = Runtime.jsonString(response.body, "code"); + if ((((Runtime.jsonInt(response.body, "status") != 200L) || !Runtime.jsonIsTrue(response.body, "ok")) || found.equals(""))) { + throw new GetAddressInfoByCepNotFoundError("CEP n\u00e3o encontrado"); + } + return new AddressInfo(Runtime.keepClass(CLASS0, found), Runtime.jsonString(response.body, "state"), Runtime.jsonString(response.body, "city"), Runtime.jsonString(response.body, "district"), Runtime.jsonString(response.body, "address")); + } + + /** + * Reads the address BrasilAPI answers with. + * + * @see Based on: https://brasilapi.com.br/docs#tag/CEP + */ + public static AddressInfo fetchBrasilApi(String cep) { + Runtime.HttpResponse response = Runtime.httpGet((("https://brasilapi.com.br/api/cep/v1/" + cep) + ""), HTTP_RETRIES, HTTP_RETRY_DELAY_MS); + if ((response.status == BRASIL_API_NOT_FOUND_STATUS)) { + throw new GetAddressInfoByCepNotFoundError("CEP n\u00e3o encontrado"); + } + if (!response.ok) { + throw new CepProviderFailure("BrasilAPI request failed"); + } + String found = Runtime.jsonString(response.body, "cep"); + if ((Runtime.jsonTruthy(response.body, "errors") || found.equals(""))) { + throw new GetAddressInfoByCepNotFoundError("CEP n\u00e3o encontrado"); + } + return new AddressInfo(Runtime.keepClass(CLASS0, found), Runtime.jsonString(response.body, "state"), Runtime.jsonString(response.body, "city"), Runtime.jsonString(response.body, "neighborhood"), Runtime.jsonString(response.body, "street")); + } + + /** + * Asks one named provider for a CEP. + */ + public static AddressInfo fetchProvider(String provider, String cep) { + if (provider.equals("viacep")) { + return fetchViaCep(cep); + } + if (provider.equals("widenet")) { + return fetchWidenet(cep); + } + return fetchBrasilApi(cep); + } + + /** + * The providers of a list that are known, in the order they were given. + */ + public static java.util.List knownProviders(java.util.List given) { + java.util.List kept = new java.util.ArrayList(java.util.List.of()); + for (var provider : given) { + if (Runtime.listHas(KNOWN_PROVIDERS, provider)) { + kept.add(provider); + } + } + return kept; + } + + /** + * Fetches address information for a given CEP using multiple providers simultaneously. + * Returns the result from the first provider that responds successfully. + * + * The providers are started together and raced, not tried one after the other, so a provider + * that is retrying delays nothing for the others: its retries only push back the moment its own + * failure lands, and therefore the moment an all-failed rejection can surface. + * + * @see Official: https://www.correios.com.br/enviar/precisa-de-ajuda/tudo-sobre-cep + * @see Based on: https://viacep.com.br/ + * ViaCEP, one of the two default providers. A third-party service, not a Correios one. + * @see Based on: https://brasilapi.com.br/docs#tag/CEP + * BrasilAPI, the other default provider. A third-party service, not a Correios one. + */ + public static AddressInfo getAddressInfoByCep(String cep, GetAddressInfoByCepOptions options) { + java.util.List optionsProviders = null; + if (options != null && options.providers != null) { + optionsProviders = options.providers; + } + String digits = Runtime.keepClass(CLASS0, cep); + if (false) { + digits = Runtime.padStart(digits, 8L, "0"); + } + if (!Runtime.patternTest(PATTERN_CEP_FORMAT, digits)) { + throw new GetAddressInfoByCepValidationError("CEP inv\u00e1lido"); + } + java.util.List chosen = DEFAULT_PROVIDERS; + if ((optionsProviders != null)) { + if (!true) { + throw new GetAddressInfoByCepValidationError("Nenhum provedor v\u00e1lido especificado"); + } + chosen = knownProviders(optionsProviders); + if (((long) chosen.size() == 0L)) { + throw new GetAddressInfoByCepValidationError("Nenhum provedor v\u00e1lido especificado"); + } + } + Runtime.Attempts attempts = Runtime.startAll(GetAddressInfoByCep::fetchProvider, chosen, digits); + AddressInfo found = (AddressInfo) Runtime.firstSuccess(attempts); + if ((found != null)) { + return found; + } + if (Runtime.anyFailedWith(attempts, "GetAddressInfoByCepNotFoundError")) { + throw new GetAddressInfoByCepNotFoundError("CEP n\u00e3o encontrado em nenhum servi\u00e7o"); + } + throw new GetAddressInfoByCepServiceError("Todos os servi\u00e7os est\u00e3o fora de servi\u00e7o ou indispon\u00edveis"); + } +} diff --git a/spec/bridge/out/java/GetAddressInfoByCepError.java b/spec/bridge/out/java/GetAddressInfoByCepError.java new file mode 100644 index 000000000..8f9c2cc60 --- /dev/null +++ b/spec/bridge/out/java/GetAddressInfoByCepError.java @@ -0,0 +1,6 @@ +/** Base class of every error `getAddressInfoByCep` rejects with. */ +public class GetAddressInfoByCepError extends RuntimeException { + public GetAddressInfoByCepError(String message) { + super(message); + } +} diff --git a/spec/bridge/out/java/GetAddressInfoByCepNotFoundError.java b/spec/bridge/out/java/GetAddressInfoByCepNotFoundError.java new file mode 100644 index 000000000..97fee816b --- /dev/null +++ b/spec/bridge/out/java/GetAddressInfoByCepNotFoundError.java @@ -0,0 +1,6 @@ +/** Thrown by `getAddressInfoByCep` when no CEP service knows the CEP. */ +public class GetAddressInfoByCepNotFoundError extends GetAddressInfoByCepError { + public GetAddressInfoByCepNotFoundError(String message) { + super(message); + } +} diff --git a/spec/bridge/out/java/GetAddressInfoByCepOptions.java b/spec/bridge/out/java/GetAddressInfoByCepOptions.java new file mode 100644 index 000000000..e1c73a2b7 --- /dev/null +++ b/spec/bridge/out/java/GetAddressInfoByCepOptions.java @@ -0,0 +1,5 @@ +/** Options of `getAddressInfoByCep`. */ +public final class GetAddressInfoByCepOptions { + /** Which CEP services to race, in the order given (default: `["viacep", "brasilapi"]`; the deprecated `"widenet"` provider is excluded from the default list, but can still be requested explicitly). */ + public java.util.List providers; +} diff --git a/spec/bridge/out/java/GetAddressInfoByCepServiceError.java b/spec/bridge/out/java/GetAddressInfoByCepServiceError.java new file mode 100644 index 000000000..95ceb736f --- /dev/null +++ b/spec/bridge/out/java/GetAddressInfoByCepServiceError.java @@ -0,0 +1,6 @@ +/** Thrown by `getAddressInfoByCep` when every CEP service failed to answer. */ +public class GetAddressInfoByCepServiceError extends GetAddressInfoByCepError { + public GetAddressInfoByCepServiceError(String message) { + super(message); + } +} diff --git a/spec/bridge/out/java/GetAddressInfoByCepValidationError.java b/spec/bridge/out/java/GetAddressInfoByCepValidationError.java new file mode 100644 index 000000000..95a69e09f --- /dev/null +++ b/spec/bridge/out/java/GetAddressInfoByCepValidationError.java @@ -0,0 +1,6 @@ +/** Thrown by `getAddressInfoByCep` when the value given is not a valid CEP. */ +public class GetAddressInfoByCepValidationError extends GetAddressInfoByCepError { + public GetAddressInfoByCepValidationError(String message) { + super(message); + } +} diff --git a/spec/bridge/out/java/GetMunicipalities.java b/spec/bridge/out/java/GetMunicipalities.java new file mode 100644 index 000000000..f18b11b8b --- /dev/null +++ b/spec/bridge/out/java/GetMunicipalities.java @@ -0,0 +1,11419 @@ +// Code generated from spec/bridge/source/get-municipalities.ts. DO NOT EDIT. + +/** Brazilian municipalities, written once. */ +public final class GetMunicipalities { + private GetMunicipalities() {} + + + + + + + + /** Brazilian municipalities published by the IBGE, by state, in the pt-BR collation order the JavaScript package returns. */ + private static final Runtime.Dataset MUNICIPALITIES = new Runtime.Dataset( + municipalitiesRows(), new String[] {"AC", "AL", "AP", "AM", "BA", "CE", "DF", "ES", "GO", "MA", "MT", "MS", "MG", "PA", "PB", "PR", "PE", "PI", "RJ", "RN", "RS", "RO", "RR", "SC", "SP", "SE", "TO"}, municipalitiesGroups(), municipalitiesOrder()); + + private static String[][] municipalitiesRows() { + String[][] rows = new String[5571][]; + municipalitiesRows0(rows); + municipalitiesRows1(rows); + municipalitiesRows2(rows); + municipalitiesRows3(rows); + municipalitiesRows4(rows); + municipalitiesRows5(rows); + municipalitiesRows6(rows); + municipalitiesRows7(rows); + municipalitiesRows8(rows); + municipalitiesRows9(rows); + municipalitiesRows10(rows); + municipalitiesRows11(rows); + municipalitiesRows12(rows); + municipalitiesRows13(rows); + municipalitiesRows14(rows); + municipalitiesRows15(rows); + municipalitiesRows16(rows); + municipalitiesRows17(rows); + municipalitiesRows18(rows); + municipalitiesRows19(rows); + municipalitiesRows20(rows); + municipalitiesRows21(rows); + municipalitiesRows22(rows); + municipalitiesRows23(rows); + municipalitiesRows24(rows); + municipalitiesRows25(rows); + municipalitiesRows26(rows); + municipalitiesRows27(rows); + return rows; + } + + private static void municipalitiesRows0(String[][] rows) { + rows[0] = new String[] {"AC", "Acrel\u00e2ndia", "1200013"}; + rows[1] = new String[] {"AC", "Assis Brasil", "1200054"}; + rows[2] = new String[] {"AC", "Brasil\u00e9ia", "1200104"}; + rows[3] = new String[] {"AC", "Bujari", "1200138"}; + rows[4] = new String[] {"AC", "Capixaba", "1200179"}; + rows[5] = new String[] {"AC", "Cruzeiro do Sul", "1200203"}; + rows[6] = new String[] {"AC", "Epitaciol\u00e2ndia", "1200252"}; + rows[7] = new String[] {"AC", "Feij\u00f3", "1200302"}; + rows[8] = new String[] {"AC", "Jord\u00e3o", "1200328"}; + rows[9] = new String[] {"AC", "M\u00e2ncio Lima", "1200336"}; + rows[10] = new String[] {"AC", "Manoel Urbano", "1200344"}; + rows[11] = new String[] {"AC", "Marechal Thaumaturgo", "1200351"}; + rows[12] = new String[] {"AC", "Pl\u00e1cido de Castro", "1200385"}; + rows[13] = new String[] {"AC", "Porto Acre", "1200807"}; + rows[14] = new String[] {"AC", "Porto Walter", "1200393"}; + rows[15] = new String[] {"AC", "Rio Branco", "1200401"}; + rows[16] = new String[] {"AC", "Rodrigues Alves", "1200427"}; + rows[17] = new String[] {"AC", "Santa Rosa do Purus", "1200435"}; + rows[18] = new String[] {"AC", "Sena Madureira", "1200500"}; + rows[19] = new String[] {"AC", "Senador Guiomard", "1200450"}; + rows[20] = new String[] {"AC", "Tarauac\u00e1", "1200609"}; + rows[21] = new String[] {"AC", "Xapuri", "1200708"}; + rows[22] = new String[] {"AL", "\u00c1gua Branca", "2700102"}; + rows[23] = new String[] {"AL", "Anadia", "2700201"}; + rows[24] = new String[] {"AL", "Arapiraca", "2700300"}; + rows[25] = new String[] {"AL", "Atalaia", "2700409"}; + rows[26] = new String[] {"AL", "Barra de Santo Ant\u00f4nio", "2700508"}; + rows[27] = new String[] {"AL", "Barra de S\u00e3o Miguel", "2700607"}; + rows[28] = new String[] {"AL", "Batalha", "2700706"}; + rows[29] = new String[] {"AL", "Bel\u00e9m", "2700805"}; + rows[30] = new String[] {"AL", "Belo Monte", "2700904"}; + rows[31] = new String[] {"AL", "Boca da Mata", "2701001"}; + rows[32] = new String[] {"AL", "Branquinha", "2701100"}; + rows[33] = new String[] {"AL", "Cacimbinhas", "2701209"}; + rows[34] = new String[] {"AL", "Cajueiro", "2701308"}; + rows[35] = new String[] {"AL", "Campestre", "2701357"}; + rows[36] = new String[] {"AL", "Campo Alegre", "2701407"}; + rows[37] = new String[] {"AL", "Campo Grande", "2701506"}; + rows[38] = new String[] {"AL", "Canapi", "2701605"}; + rows[39] = new String[] {"AL", "Capela", "2701704"}; + rows[40] = new String[] {"AL", "Carneiros", "2701803"}; + rows[41] = new String[] {"AL", "Ch\u00e3 Preta", "2701902"}; + rows[42] = new String[] {"AL", "Coit\u00e9 do N\u00f3ia", "2702009"}; + rows[43] = new String[] {"AL", "Col\u00f4nia Leopoldina", "2702108"}; + rows[44] = new String[] {"AL", "Coqueiro Seco", "2702207"}; + rows[45] = new String[] {"AL", "Coruripe", "2702306"}; + rows[46] = new String[] {"AL", "Cra\u00edbas", "2702355"}; + rows[47] = new String[] {"AL", "Delmiro Gouveia", "2702405"}; + rows[48] = new String[] {"AL", "Dois Riachos", "2702504"}; + rows[49] = new String[] {"AL", "Estrela de Alagoas", "2702553"}; + rows[50] = new String[] {"AL", "Feira Grande", "2702603"}; + rows[51] = new String[] {"AL", "Feliz Deserto", "2702702"}; + rows[52] = new String[] {"AL", "Flexeiras", "2702801"}; + rows[53] = new String[] {"AL", "Girau do Ponciano", "2702900"}; + rows[54] = new String[] {"AL", "Ibateguara", "2703007"}; + rows[55] = new String[] {"AL", "Igaci", "2703106"}; + rows[56] = new String[] {"AL", "Igreja Nova", "2703205"}; + rows[57] = new String[] {"AL", "Inhapi", "2703304"}; + rows[58] = new String[] {"AL", "Jacar\u00e9 dos Homens", "2703403"}; + rows[59] = new String[] {"AL", "Jacu\u00edpe", "2703502"}; + rows[60] = new String[] {"AL", "Japaratinga", "2703601"}; + rows[61] = new String[] {"AL", "Jaramataia", "2703700"}; + rows[62] = new String[] {"AL", "Jequi\u00e1 da Praia", "2703759"}; + rows[63] = new String[] {"AL", "Joaquim Gomes", "2703809"}; + rows[64] = new String[] {"AL", "Jundi\u00e1", "2703908"}; + rows[65] = new String[] {"AL", "Junqueiro", "2704005"}; + rows[66] = new String[] {"AL", "Lagoa da Canoa", "2704104"}; + rows[67] = new String[] {"AL", "Limoeiro de Anadia", "2704203"}; + rows[68] = new String[] {"AL", "Macei\u00f3", "2704302"}; + rows[69] = new String[] {"AL", "Major Isidoro", "2704401"}; + rows[70] = new String[] {"AL", "Mar Vermelho", "2704906"}; + rows[71] = new String[] {"AL", "Maragogi", "2704500"}; + rows[72] = new String[] {"AL", "Maravilha", "2704609"}; + rows[73] = new String[] {"AL", "Marechal Deodoro", "2704708"}; + rows[74] = new String[] {"AL", "Maribondo", "2704807"}; + rows[75] = new String[] {"AL", "Mata Grande", "2705002"}; + rows[76] = new String[] {"AL", "Matriz de Camaragibe", "2705101"}; + rows[77] = new String[] {"AL", "Messias", "2705200"}; + rows[78] = new String[] {"AL", "Minador do Negr\u00e3o", "2705309"}; + rows[79] = new String[] {"AL", "Monteir\u00f3polis", "2705408"}; + rows[80] = new String[] {"AL", "Murici", "2705507"}; + rows[81] = new String[] {"AL", "Novo Lino", "2705606"}; + rows[82] = new String[] {"AL", "Olho d'\u00c1gua das Flores", "2705705"}; + rows[83] = new String[] {"AL", "Olho d'\u00c1gua do Casado", "2705804"}; + rows[84] = new String[] {"AL", "Olho d'\u00c1gua Grande", "2705903"}; + rows[85] = new String[] {"AL", "Oliven\u00e7a", "2706000"}; + rows[86] = new String[] {"AL", "Ouro Branco", "2706109"}; + rows[87] = new String[] {"AL", "Palestina", "2706208"}; + rows[88] = new String[] {"AL", "Palmeira dos \u00cdndios", "2706307"}; + rows[89] = new String[] {"AL", "P\u00e3o de A\u00e7\u00facar", "2706406"}; + rows[90] = new String[] {"AL", "Pariconha", "2706422"}; + rows[91] = new String[] {"AL", "Paripueira", "2706448"}; + rows[92] = new String[] {"AL", "Passo de Camaragibe", "2706505"}; + rows[93] = new String[] {"AL", "Paulo Jacinto", "2706604"}; + rows[94] = new String[] {"AL", "Penedo", "2706703"}; + rows[95] = new String[] {"AL", "Pia\u00e7abu\u00e7u", "2706802"}; + rows[96] = new String[] {"AL", "Pilar", "2706901"}; + rows[97] = new String[] {"AL", "Pindoba", "2707008"}; + rows[98] = new String[] {"AL", "Piranhas", "2707107"}; + rows[99] = new String[] {"AL", "Po\u00e7o das Trincheiras", "2707206"}; + rows[100] = new String[] {"AL", "Porto Calvo", "2707305"}; + rows[101] = new String[] {"AL", "Porto de Pedras", "2707404"}; + rows[102] = new String[] {"AL", "Porto Real do Col\u00e9gio", "2707503"}; + rows[103] = new String[] {"AL", "Quebrangulo", "2707602"}; + rows[104] = new String[] {"AL", "Rio Largo", "2707701"}; + rows[105] = new String[] {"AL", "Roteiro", "2707800"}; + rows[106] = new String[] {"AL", "Santa Luzia do Norte", "2707909"}; + rows[107] = new String[] {"AL", "Santana do Ipanema", "2708006"}; + rows[108] = new String[] {"AL", "Santana do Munda\u00fa", "2708105"}; + rows[109] = new String[] {"AL", "S\u00e3o Br\u00e1s", "2708204"}; + rows[110] = new String[] {"AL", "S\u00e3o Jos\u00e9 da Laje", "2708303"}; + rows[111] = new String[] {"AL", "S\u00e3o Jos\u00e9 da Tapera", "2708402"}; + rows[112] = new String[] {"AL", "S\u00e3o Lu\u00eds do Quitunde", "2708501"}; + rows[113] = new String[] {"AL", "S\u00e3o Miguel dos Campos", "2708600"}; + rows[114] = new String[] {"AL", "S\u00e3o Miguel dos Milagres", "2708709"}; + rows[115] = new String[] {"AL", "S\u00e3o Sebasti\u00e3o", "2708808"}; + rows[116] = new String[] {"AL", "Satuba", "2708907"}; + rows[117] = new String[] {"AL", "Senador Rui Palmeira", "2708956"}; + rows[118] = new String[] {"AL", "Tanque d'Arca", "2709004"}; + rows[119] = new String[] {"AL", "Taquarana", "2709103"}; + rows[120] = new String[] {"AL", "Teot\u00f4nio Vilela", "2709152"}; + rows[121] = new String[] {"AL", "Traipu", "2709202"}; + rows[122] = new String[] {"AL", "Uni\u00e3o dos Palmares", "2709301"}; + rows[123] = new String[] {"AL", "Vi\u00e7osa", "2709400"}; + rows[124] = new String[] {"AP", "Amap\u00e1", "1600105"}; + rows[125] = new String[] {"AP", "Cal\u00e7oene", "1600204"}; + rows[126] = new String[] {"AP", "Cutias", "1600212"}; + rows[127] = new String[] {"AP", "Ferreira Gomes", "1600238"}; + rows[128] = new String[] {"AP", "Itaubal", "1600253"}; + rows[129] = new String[] {"AP", "Laranjal do Jari", "1600279"}; + rows[130] = new String[] {"AP", "Macap\u00e1", "1600303"}; + rows[131] = new String[] {"AP", "Mazag\u00e3o", "1600402"}; + rows[132] = new String[] {"AP", "Oiapoque", "1600501"}; + rows[133] = new String[] {"AP", "Pedra Branca do Amapari", "1600154"}; + rows[134] = new String[] {"AP", "Porto Grande", "1600535"}; + rows[135] = new String[] {"AP", "Pracu\u00faba", "1600550"}; + rows[136] = new String[] {"AP", "Santana", "1600600"}; + rows[137] = new String[] {"AP", "Serra do Navio", "1600055"}; + rows[138] = new String[] {"AP", "Tartarugalzinho", "1600709"}; + rows[139] = new String[] {"AP", "Vit\u00f3ria do Jari", "1600808"}; + rows[140] = new String[] {"AM", "Alvar\u00e3es", "1300029"}; + rows[141] = new String[] {"AM", "Amatur\u00e1", "1300060"}; + rows[142] = new String[] {"AM", "Anam\u00e3", "1300086"}; + rows[143] = new String[] {"AM", "Anori", "1300102"}; + rows[144] = new String[] {"AM", "Apu\u00ed", "1300144"}; + rows[145] = new String[] {"AM", "Atalaia do Norte", "1300201"}; + rows[146] = new String[] {"AM", "Autazes", "1300300"}; + rows[147] = new String[] {"AM", "Barcelos", "1300409"}; + rows[148] = new String[] {"AM", "Barreirinha", "1300508"}; + rows[149] = new String[] {"AM", "Benjamin Constant", "1300607"}; + rows[150] = new String[] {"AM", "Beruri", "1300631"}; + rows[151] = new String[] {"AM", "Boa Vista do Ramos", "1300680"}; + rows[152] = new String[] {"AM", "Boca do Acre", "1300706"}; + rows[153] = new String[] {"AM", "Borba", "1300805"}; + rows[154] = new String[] {"AM", "Caapiranga", "1300839"}; + rows[155] = new String[] {"AM", "Canutama", "1300904"}; + rows[156] = new String[] {"AM", "Carauari", "1301001"}; + rows[157] = new String[] {"AM", "Careiro", "1301100"}; + rows[158] = new String[] {"AM", "Careiro da V\u00e1rzea", "1301159"}; + rows[159] = new String[] {"AM", "Coari", "1301209"}; + rows[160] = new String[] {"AM", "Codaj\u00e1s", "1301308"}; + rows[161] = new String[] {"AM", "Eirunep\u00e9", "1301407"}; + rows[162] = new String[] {"AM", "Envira", "1301506"}; + rows[163] = new String[] {"AM", "Fonte Boa", "1301605"}; + rows[164] = new String[] {"AM", "Guajar\u00e1", "1301654"}; + rows[165] = new String[] {"AM", "Humait\u00e1", "1301704"}; + rows[166] = new String[] {"AM", "Ipixuna", "1301803"}; + rows[167] = new String[] {"AM", "Iranduba", "1301852"}; + rows[168] = new String[] {"AM", "Itacoatiara", "1301902"}; + rows[169] = new String[] {"AM", "Itamarati", "1301951"}; + rows[170] = new String[] {"AM", "Itapiranga", "1302009"}; + rows[171] = new String[] {"AM", "Japur\u00e1", "1302108"}; + rows[172] = new String[] {"AM", "Juru\u00e1", "1302207"}; + rows[173] = new String[] {"AM", "Juta\u00ed", "1302306"}; + rows[174] = new String[] {"AM", "L\u00e1brea", "1302405"}; + rows[175] = new String[] {"AM", "Manacapuru", "1302504"}; + rows[176] = new String[] {"AM", "Manaquiri", "1302553"}; + rows[177] = new String[] {"AM", "Manaus", "1302603"}; + rows[178] = new String[] {"AM", "Manicor\u00e9", "1302702"}; + rows[179] = new String[] {"AM", "Mara\u00e3", "1302801"}; + rows[180] = new String[] {"AM", "Mau\u00e9s", "1302900"}; + rows[181] = new String[] {"AM", "Nhamund\u00e1", "1303007"}; + rows[182] = new String[] {"AM", "Nova Olinda do Norte", "1303106"}; + rows[183] = new String[] {"AM", "Novo Air\u00e3o", "1303205"}; + rows[184] = new String[] {"AM", "Novo Aripuan\u00e3", "1303304"}; + rows[185] = new String[] {"AM", "Parintins", "1303403"}; + rows[186] = new String[] {"AM", "Pauini", "1303502"}; + rows[187] = new String[] {"AM", "Presidente Figueiredo", "1303536"}; + rows[188] = new String[] {"AM", "Rio Preto da Eva", "1303569"}; + rows[189] = new String[] {"AM", "Santa Isabel do Rio Negro", "1303601"}; + rows[190] = new String[] {"AM", "Santo Ant\u00f4nio do I\u00e7\u00e1", "1303700"}; + rows[191] = new String[] {"AM", "S\u00e3o Gabriel da Cachoeira", "1303809"}; + rows[192] = new String[] {"AM", "S\u00e3o Paulo de Oliven\u00e7a", "1303908"}; + rows[193] = new String[] {"AM", "S\u00e3o Sebasti\u00e3o do Uatum\u00e3", "1303957"}; + rows[194] = new String[] {"AM", "Silves", "1304005"}; + rows[195] = new String[] {"AM", "Tabatinga", "1304062"}; + rows[196] = new String[] {"AM", "Tapau\u00e1", "1304104"}; + rows[197] = new String[] {"AM", "Tef\u00e9", "1304203"}; + rows[198] = new String[] {"AM", "Tonantins", "1304237"}; + rows[199] = new String[] {"AM", "Uarini", "1304260"}; + } + + private static void municipalitiesRows1(String[][] rows) { + rows[200] = new String[] {"AM", "Urucar\u00e1", "1304302"}; + rows[201] = new String[] {"AM", "Urucurituba", "1304401"}; + rows[202] = new String[] {"BA", "Aba\u00edra", "2900108"}; + rows[203] = new String[] {"BA", "Abar\u00e9", "2900207"}; + rows[204] = new String[] {"BA", "Acajutiba", "2900306"}; + rows[205] = new String[] {"BA", "Adustina", "2900355"}; + rows[206] = new String[] {"BA", "\u00c1gua Fria", "2900405"}; + rows[207] = new String[] {"BA", "Aiquara", "2900603"}; + rows[208] = new String[] {"BA", "Alagoinhas", "2900702"}; + rows[209] = new String[] {"BA", "Alcoba\u00e7a", "2900801"}; + rows[210] = new String[] {"BA", "Almadina", "2900900"}; + rows[211] = new String[] {"BA", "Amargosa", "2901007"}; + rows[212] = new String[] {"BA", "Am\u00e9lia Rodrigues", "2901106"}; + rows[213] = new String[] {"BA", "Am\u00e9rica Dourada", "2901155"}; + rows[214] = new String[] {"BA", "Anag\u00e9", "2901205"}; + rows[215] = new String[] {"BA", "Andara\u00ed", "2901304"}; + rows[216] = new String[] {"BA", "Andorinha", "2901353"}; + rows[217] = new String[] {"BA", "Angical", "2901403"}; + rows[218] = new String[] {"BA", "Anguera", "2901502"}; + rows[219] = new String[] {"BA", "Antas", "2901601"}; + rows[220] = new String[] {"BA", "Ant\u00f4nio Cardoso", "2901700"}; + rows[221] = new String[] {"BA", "Ant\u00f4nio Gon\u00e7alves", "2901809"}; + rows[222] = new String[] {"BA", "Apor\u00e1", "2901908"}; + rows[223] = new String[] {"BA", "Apuarema", "2901957"}; + rows[224] = new String[] {"BA", "Ara\u00e7\u00e1s", "2902054"}; + rows[225] = new String[] {"BA", "Aracatu", "2902005"}; + rows[226] = new String[] {"BA", "Araci", "2902104"}; + rows[227] = new String[] {"BA", "Aramari", "2902203"}; + rows[228] = new String[] {"BA", "Arataca", "2902252"}; + rows[229] = new String[] {"BA", "Aratu\u00edpe", "2902302"}; + rows[230] = new String[] {"BA", "Aurelino Leal", "2902401"}; + rows[231] = new String[] {"BA", "Baian\u00f3polis", "2902500"}; + rows[232] = new String[] {"BA", "Baixa Grande", "2902609"}; + rows[233] = new String[] {"BA", "Banza\u00ea", "2902658"}; + rows[234] = new String[] {"BA", "Barra", "2902708"}; + rows[235] = new String[] {"BA", "Barra da Estiva", "2902807"}; + rows[236] = new String[] {"BA", "Barra do Cho\u00e7a", "2902906"}; + rows[237] = new String[] {"BA", "Barra do Mendes", "2903003"}; + rows[238] = new String[] {"BA", "Barra do Rocha", "2903102"}; + rows[239] = new String[] {"BA", "Barreiras", "2903201"}; + rows[240] = new String[] {"BA", "Barro Alto", "2903235"}; + rows[241] = new String[] {"BA", "Barro Preto", "2903300"}; + rows[242] = new String[] {"BA", "Barrocas", "2903276"}; + rows[243] = new String[] {"BA", "Belmonte", "2903409"}; + rows[244] = new String[] {"BA", "Belo Campo", "2903508"}; + rows[245] = new String[] {"BA", "Biritinga", "2903607"}; + rows[246] = new String[] {"BA", "Boa Nova", "2903706"}; + rows[247] = new String[] {"BA", "Boa Vista do Tupim", "2903805"}; + rows[248] = new String[] {"BA", "Bom Jesus da Lapa", "2903904"}; + rows[249] = new String[] {"BA", "Bom Jesus da Serra", "2903953"}; + rows[250] = new String[] {"BA", "Boninal", "2904001"}; + rows[251] = new String[] {"BA", "Bonito", "2904050"}; + rows[252] = new String[] {"BA", "Boquira", "2904100"}; + rows[253] = new String[] {"BA", "Botupor\u00e3", "2904209"}; + rows[254] = new String[] {"BA", "Brej\u00f5es", "2904308"}; + rows[255] = new String[] {"BA", "Brejol\u00e2ndia", "2904407"}; + rows[256] = new String[] {"BA", "Brotas de Maca\u00fabas", "2904506"}; + rows[257] = new String[] {"BA", "Brumado", "2904605"}; + rows[258] = new String[] {"BA", "Buerarema", "2904704"}; + rows[259] = new String[] {"BA", "Buritirama", "2904753"}; + rows[260] = new String[] {"BA", "Caatiba", "2904803"}; + rows[261] = new String[] {"BA", "Cabaceiras do Paragua\u00e7u", "2904852"}; + rows[262] = new String[] {"BA", "Cachoeira", "2904902"}; + rows[263] = new String[] {"BA", "Cacul\u00e9", "2905008"}; + rows[264] = new String[] {"BA", "Ca\u00e9m", "2905107"}; + rows[265] = new String[] {"BA", "Caetanos", "2905156"}; + rows[266] = new String[] {"BA", "Caetit\u00e9", "2905206"}; + rows[267] = new String[] {"BA", "Cafarnaum", "2905305"}; + rows[268] = new String[] {"BA", "Cairu", "2905404"}; + rows[269] = new String[] {"BA", "Caldeir\u00e3o Grande", "2905503"}; + rows[270] = new String[] {"BA", "Camacan", "2905602"}; + rows[271] = new String[] {"BA", "Cama\u00e7ari", "2905701"}; + rows[272] = new String[] {"BA", "Camamu", "2905800"}; + rows[273] = new String[] {"BA", "Campo Alegre de Lourdes", "2905909"}; + rows[274] = new String[] {"BA", "Campo Formoso", "2906006"}; + rows[275] = new String[] {"BA", "Can\u00e1polis", "2906105"}; + rows[276] = new String[] {"BA", "Canarana", "2906204"}; + rows[277] = new String[] {"BA", "Canavieiras", "2906303"}; + rows[278] = new String[] {"BA", "Candeal", "2906402"}; + rows[279] = new String[] {"BA", "Candeias", "2906501"}; + rows[280] = new String[] {"BA", "Candiba", "2906600"}; + rows[281] = new String[] {"BA", "C\u00e2ndido Sales", "2906709"}; + rows[282] = new String[] {"BA", "Cansan\u00e7\u00e3o", "2906808"}; + rows[283] = new String[] {"BA", "Canudos", "2906824"}; + rows[284] = new String[] {"BA", "Capela do Alto Alegre", "2906857"}; + rows[285] = new String[] {"BA", "Capim Grosso", "2906873"}; + rows[286] = new String[] {"BA", "Cara\u00edbas", "2906899"}; + rows[287] = new String[] {"BA", "Caravelas", "2906907"}; + rows[288] = new String[] {"BA", "Cardeal da Silva", "2907004"}; + rows[289] = new String[] {"BA", "Carinhanha", "2907103"}; + rows[290] = new String[] {"BA", "Casa Nova", "2907202"}; + rows[291] = new String[] {"BA", "Castro Alves", "2907301"}; + rows[292] = new String[] {"BA", "Catol\u00e2ndia", "2907400"}; + rows[293] = new String[] {"BA", "Catu", "2907509"}; + rows[294] = new String[] {"BA", "Caturama", "2907558"}; + rows[295] = new String[] {"BA", "Central", "2907608"}; + rows[296] = new String[] {"BA", "Chorroch\u00f3", "2907707"}; + rows[297] = new String[] {"BA", "C\u00edcero Dantas", "2907806"}; + rows[298] = new String[] {"BA", "Cip\u00f3", "2907905"}; + rows[299] = new String[] {"BA", "Coaraci", "2908002"}; + rows[300] = new String[] {"BA", "Cocos", "2908101"}; + rows[301] = new String[] {"BA", "Concei\u00e7\u00e3o da Feira", "2908200"}; + rows[302] = new String[] {"BA", "Concei\u00e7\u00e3o do Almeida", "2908309"}; + rows[303] = new String[] {"BA", "Concei\u00e7\u00e3o do Coit\u00e9", "2908408"}; + rows[304] = new String[] {"BA", "Concei\u00e7\u00e3o do Jacu\u00edpe", "2908507"}; + rows[305] = new String[] {"BA", "Conde", "2908606"}; + rows[306] = new String[] {"BA", "Conde\u00faba", "2908705"}; + rows[307] = new String[] {"BA", "Contendas do Sincor\u00e1", "2908804"}; + rows[308] = new String[] {"BA", "Cora\u00e7\u00e3o de Maria", "2908903"}; + rows[309] = new String[] {"BA", "Cordeiros", "2909000"}; + rows[310] = new String[] {"BA", "Coribe", "2909109"}; + rows[311] = new String[] {"BA", "Coronel Jo\u00e3o S\u00e1", "2909208"}; + rows[312] = new String[] {"BA", "Correntina", "2909307"}; + rows[313] = new String[] {"BA", "Cotegipe", "2909406"}; + rows[314] = new String[] {"BA", "Cravol\u00e2ndia", "2909505"}; + rows[315] = new String[] {"BA", "Cris\u00f3polis", "2909604"}; + rows[316] = new String[] {"BA", "Crist\u00f3polis", "2909703"}; + rows[317] = new String[] {"BA", "Cruz das Almas", "2909802"}; + rows[318] = new String[] {"BA", "Cura\u00e7\u00e1", "2909901"}; + rows[319] = new String[] {"BA", "D\u00e1rio Meira", "2910008"}; + rows[320] = new String[] {"BA", "Dias d'\u00c1vila", "2910057"}; + rows[321] = new String[] {"BA", "Dom Bas\u00edlio", "2910107"}; + rows[322] = new String[] {"BA", "Dom Macedo Costa", "2910206"}; + rows[323] = new String[] {"BA", "El\u00edsio Medrado", "2910305"}; + rows[324] = new String[] {"BA", "Encruzilhada", "2910404"}; + rows[325] = new String[] {"BA", "Entre Rios", "2910503"}; + rows[326] = new String[] {"BA", "\u00c9rico Cardoso", "2900504"}; + rows[327] = new String[] {"BA", "Esplanada", "2910602"}; + rows[328] = new String[] {"BA", "Euclides da Cunha", "2910701"}; + rows[329] = new String[] {"BA", "Eun\u00e1polis", "2910727"}; + rows[330] = new String[] {"BA", "F\u00e1tima", "2910750"}; + rows[331] = new String[] {"BA", "Feira da Mata", "2910776"}; + rows[332] = new String[] {"BA", "Feira de Santana", "2910800"}; + rows[333] = new String[] {"BA", "Filad\u00e9lfia", "2910859"}; + rows[334] = new String[] {"BA", "Firmino Alves", "2910909"}; + rows[335] = new String[] {"BA", "Floresta Azul", "2911006"}; + rows[336] = new String[] {"BA", "Formosa do Rio Preto", "2911105"}; + rows[337] = new String[] {"BA", "Gandu", "2911204"}; + rows[338] = new String[] {"BA", "Gavi\u00e3o", "2911253"}; + rows[339] = new String[] {"BA", "Gentio do Ouro", "2911303"}; + rows[340] = new String[] {"BA", "Gl\u00f3ria", "2911402"}; + rows[341] = new String[] {"BA", "Gongogi", "2911501"}; + rows[342] = new String[] {"BA", "Governador Mangabeira", "2911600"}; + rows[343] = new String[] {"BA", "Guajeru", "2911659"}; + rows[344] = new String[] {"BA", "Guanambi", "2911709"}; + rows[345] = new String[] {"BA", "Guaratinga", "2911808"}; + rows[346] = new String[] {"BA", "Heli\u00f3polis", "2911857"}; + rows[347] = new String[] {"BA", "Ia\u00e7u", "2911907"}; + rows[348] = new String[] {"BA", "Ibiassuc\u00ea", "2912004"}; + rows[349] = new String[] {"BA", "Ibicara\u00ed", "2912103"}; + rows[350] = new String[] {"BA", "Ibicoara", "2912202"}; + rows[351] = new String[] {"BA", "Ibicu\u00ed", "2912301"}; + rows[352] = new String[] {"BA", "Ibipeba", "2912400"}; + rows[353] = new String[] {"BA", "Ibipitanga", "2912509"}; + rows[354] = new String[] {"BA", "Ibiquera", "2912608"}; + rows[355] = new String[] {"BA", "Ibirapitanga", "2912707"}; + rows[356] = new String[] {"BA", "Ibirapu\u00e3", "2912806"}; + rows[357] = new String[] {"BA", "Ibirataia", "2912905"}; + rows[358] = new String[] {"BA", "Ibitiara", "2913002"}; + rows[359] = new String[] {"BA", "Ibitit\u00e1", "2913101"}; + rows[360] = new String[] {"BA", "Ibotirama", "2913200"}; + rows[361] = new String[] {"BA", "Ichu", "2913309"}; + rows[362] = new String[] {"BA", "Igapor\u00e3", "2913408"}; + rows[363] = new String[] {"BA", "Igrapi\u00fana", "2913457"}; + rows[364] = new String[] {"BA", "Igua\u00ed", "2913507"}; + rows[365] = new String[] {"BA", "Ilh\u00e9us", "2913606"}; + rows[366] = new String[] {"BA", "Inhambupe", "2913705"}; + rows[367] = new String[] {"BA", "Ipecaet\u00e1", "2913804"}; + rows[368] = new String[] {"BA", "Ipia\u00fa", "2913903"}; + rows[369] = new String[] {"BA", "Ipir\u00e1", "2914000"}; + rows[370] = new String[] {"BA", "Ipupiara", "2914109"}; + rows[371] = new String[] {"BA", "Irajuba", "2914208"}; + rows[372] = new String[] {"BA", "Iramaia", "2914307"}; + rows[373] = new String[] {"BA", "Iraquara", "2914406"}; + rows[374] = new String[] {"BA", "Irar\u00e1", "2914505"}; + rows[375] = new String[] {"BA", "Irec\u00ea", "2914604"}; + rows[376] = new String[] {"BA", "Itabela", "2914653"}; + rows[377] = new String[] {"BA", "Itaberaba", "2914703"}; + rows[378] = new String[] {"BA", "Itabuna", "2914802"}; + rows[379] = new String[] {"BA", "Itacar\u00e9", "2914901"}; + rows[380] = new String[] {"BA", "Itaet\u00e9", "2915007"}; + rows[381] = new String[] {"BA", "Itagi", "2915106"}; + rows[382] = new String[] {"BA", "Itagib\u00e1", "2915205"}; + rows[383] = new String[] {"BA", "Itagimirim", "2915304"}; + rows[384] = new String[] {"BA", "Itagua\u00e7u da Bahia", "2915353"}; + rows[385] = new String[] {"BA", "Itaju do Col\u00f4nia", "2915403"}; + rows[386] = new String[] {"BA", "Itaju\u00edpe", "2915502"}; + rows[387] = new String[] {"BA", "Itamaraju", "2915601"}; + rows[388] = new String[] {"BA", "Itamari", "2915700"}; + rows[389] = new String[] {"BA", "Itamb\u00e9", "2915809"}; + rows[390] = new String[] {"BA", "Itanagra", "2915908"}; + rows[391] = new String[] {"BA", "Itanh\u00e9m", "2916005"}; + rows[392] = new String[] {"BA", "Itaparica", "2916104"}; + rows[393] = new String[] {"BA", "Itap\u00e9", "2916203"}; + rows[394] = new String[] {"BA", "Itapebi", "2916302"}; + rows[395] = new String[] {"BA", "Itapetinga", "2916401"}; + rows[396] = new String[] {"BA", "Itapicuru", "2916500"}; + rows[397] = new String[] {"BA", "Itapitanga", "2916609"}; + rows[398] = new String[] {"BA", "Itaquara", "2916708"}; + rows[399] = new String[] {"BA", "Itarantim", "2916807"}; + } + + private static void municipalitiesRows2(String[][] rows) { + rows[400] = new String[] {"BA", "Itatim", "2916856"}; + rows[401] = new String[] {"BA", "Itiru\u00e7u", "2916906"}; + rows[402] = new String[] {"BA", "Iti\u00faba", "2917003"}; + rows[403] = new String[] {"BA", "Itoror\u00f3", "2917102"}; + rows[404] = new String[] {"BA", "Itua\u00e7u", "2917201"}; + rows[405] = new String[] {"BA", "Ituber\u00e1", "2917300"}; + rows[406] = new String[] {"BA", "Iuiu", "2917334"}; + rows[407] = new String[] {"BA", "Jaborandi", "2917359"}; + rows[408] = new String[] {"BA", "Jacaraci", "2917409"}; + rows[409] = new String[] {"BA", "Jacobina", "2917508"}; + rows[410] = new String[] {"BA", "Jaguaquara", "2917607"}; + rows[411] = new String[] {"BA", "Jaguarari", "2917706"}; + rows[412] = new String[] {"BA", "Jaguaripe", "2917805"}; + rows[413] = new String[] {"BA", "Janda\u00edra", "2917904"}; + rows[414] = new String[] {"BA", "Jequi\u00e9", "2918001"}; + rows[415] = new String[] {"BA", "Jeremoabo", "2918100"}; + rows[416] = new String[] {"BA", "Jiquiri\u00e7\u00e1", "2918209"}; + rows[417] = new String[] {"BA", "Jita\u00fana", "2918308"}; + rows[418] = new String[] {"BA", "Jo\u00e3o Dourado", "2918357"}; + rows[419] = new String[] {"BA", "Juazeiro", "2918407"}; + rows[420] = new String[] {"BA", "Jucuru\u00e7u", "2918456"}; + rows[421] = new String[] {"BA", "Jussara", "2918506"}; + rows[422] = new String[] {"BA", "Jussari", "2918555"}; + rows[423] = new String[] {"BA", "Jussiape", "2918605"}; + rows[424] = new String[] {"BA", "Lafaiete Coutinho", "2918704"}; + rows[425] = new String[] {"BA", "Lagoa Real", "2918753"}; + rows[426] = new String[] {"BA", "Laje", "2918803"}; + rows[427] = new String[] {"BA", "Lajed\u00e3o", "2918902"}; + rows[428] = new String[] {"BA", "Lajedinho", "2919009"}; + rows[429] = new String[] {"BA", "Lajedo do Tabocal", "2919058"}; + rows[430] = new String[] {"BA", "Lamar\u00e3o", "2919108"}; + rows[431] = new String[] {"BA", "Lap\u00e3o", "2919157"}; + rows[432] = new String[] {"BA", "Lauro de Freitas", "2919207"}; + rows[433] = new String[] {"BA", "Len\u00e7\u00f3is", "2919306"}; + rows[434] = new String[] {"BA", "Lic\u00ednio de Almeida", "2919405"}; + rows[435] = new String[] {"BA", "Livramento de Nossa Senhora", "2919504"}; + rows[436] = new String[] {"BA", "Lu\u00eds Eduardo Magalh\u00e3es", "2919553"}; + rows[437] = new String[] {"BA", "Macajuba", "2919603"}; + rows[438] = new String[] {"BA", "Macarani", "2919702"}; + rows[439] = new String[] {"BA", "Maca\u00fabas", "2919801"}; + rows[440] = new String[] {"BA", "Macurur\u00e9", "2919900"}; + rows[441] = new String[] {"BA", "Madre de Deus", "2919926"}; + rows[442] = new String[] {"BA", "Maetinga", "2919959"}; + rows[443] = new String[] {"BA", "Maiquinique", "2920007"}; + rows[444] = new String[] {"BA", "Mairi", "2920106"}; + rows[445] = new String[] {"BA", "Malhada", "2920205"}; + rows[446] = new String[] {"BA", "Malhada de Pedras", "2920304"}; + rows[447] = new String[] {"BA", "Manoel Vitorino", "2920403"}; + rows[448] = new String[] {"BA", "Mansid\u00e3o", "2920452"}; + rows[449] = new String[] {"BA", "Marac\u00e1s", "2920502"}; + rows[450] = new String[] {"BA", "Maragogipe", "2920601"}; + rows[451] = new String[] {"BA", "Mara\u00fa", "2920700"}; + rows[452] = new String[] {"BA", "Marcion\u00edlio Souza", "2920809"}; + rows[453] = new String[] {"BA", "Mascote", "2920908"}; + rows[454] = new String[] {"BA", "Mata de S\u00e3o Jo\u00e3o", "2921005"}; + rows[455] = new String[] {"BA", "Matina", "2921054"}; + rows[456] = new String[] {"BA", "Medeiros Neto", "2921104"}; + rows[457] = new String[] {"BA", "Miguel Calmon", "2921203"}; + rows[458] = new String[] {"BA", "Milagres", "2921302"}; + rows[459] = new String[] {"BA", "Mirangaba", "2921401"}; + rows[460] = new String[] {"BA", "Mirante", "2921450"}; + rows[461] = new String[] {"BA", "Monte Santo", "2921500"}; + rows[462] = new String[] {"BA", "Morpar\u00e1", "2921609"}; + rows[463] = new String[] {"BA", "Morro do Chap\u00e9u", "2921708"}; + rows[464] = new String[] {"BA", "Mortugaba", "2921807"}; + rows[465] = new String[] {"BA", "Mucug\u00ea", "2921906"}; + rows[466] = new String[] {"BA", "Mucuri", "2922003"}; + rows[467] = new String[] {"BA", "Mulungu do Morro", "2922052"}; + rows[468] = new String[] {"BA", "Mundo Novo", "2922102"}; + rows[469] = new String[] {"BA", "Muniz Ferreira", "2922201"}; + rows[470] = new String[] {"BA", "Muqu\u00e9m do S\u00e3o Francisco", "2922250"}; + rows[471] = new String[] {"BA", "Muritiba", "2922300"}; + rows[472] = new String[] {"BA", "Mutu\u00edpe", "2922409"}; + rows[473] = new String[] {"BA", "Nazar\u00e9", "2922508"}; + rows[474] = new String[] {"BA", "Nilo Pe\u00e7anha", "2922607"}; + rows[475] = new String[] {"BA", "Nordestina", "2922656"}; + rows[476] = new String[] {"BA", "Nova Cana\u00e3", "2922706"}; + rows[477] = new String[] {"BA", "Nova F\u00e1tima", "2922730"}; + rows[478] = new String[] {"BA", "Nova Ibi\u00e1", "2922755"}; + rows[479] = new String[] {"BA", "Nova Itarana", "2922805"}; + rows[480] = new String[] {"BA", "Nova Reden\u00e7\u00e3o", "2922854"}; + rows[481] = new String[] {"BA", "Nova Soure", "2922904"}; + rows[482] = new String[] {"BA", "Nova Vi\u00e7osa", "2923001"}; + rows[483] = new String[] {"BA", "Novo Horizonte", "2923035"}; + rows[484] = new String[] {"BA", "Novo Triunfo", "2923050"}; + rows[485] = new String[] {"BA", "Olindina", "2923100"}; + rows[486] = new String[] {"BA", "Oliveira dos Brejinhos", "2923209"}; + rows[487] = new String[] {"BA", "Ouri\u00e7angas", "2923308"}; + rows[488] = new String[] {"BA", "Ourol\u00e2ndia", "2923357"}; + rows[489] = new String[] {"BA", "Palmas de Monte Alto", "2923407"}; + rows[490] = new String[] {"BA", "Palmeiras", "2923506"}; + rows[491] = new String[] {"BA", "Paramirim", "2923605"}; + rows[492] = new String[] {"BA", "Paratinga", "2923704"}; + rows[493] = new String[] {"BA", "Paripiranga", "2923803"}; + rows[494] = new String[] {"BA", "Pau Brasil", "2923902"}; + rows[495] = new String[] {"BA", "Paulo Afonso", "2924009"}; + rows[496] = new String[] {"BA", "P\u00e9 de Serra", "2924058"}; + rows[497] = new String[] {"BA", "Pedr\u00e3o", "2924108"}; + rows[498] = new String[] {"BA", "Pedro Alexandre", "2924207"}; + rows[499] = new String[] {"BA", "Piat\u00e3", "2924306"}; + rows[500] = new String[] {"BA", "Pil\u00e3o Arcado", "2924405"}; + rows[501] = new String[] {"BA", "Pinda\u00ed", "2924504"}; + rows[502] = new String[] {"BA", "Pindoba\u00e7u", "2924603"}; + rows[503] = new String[] {"BA", "Pintadas", "2924652"}; + rows[504] = new String[] {"BA", "Pira\u00ed do Norte", "2924678"}; + rows[505] = new String[] {"BA", "Pirip\u00e1", "2924702"}; + rows[506] = new String[] {"BA", "Piritiba", "2924801"}; + rows[507] = new String[] {"BA", "Planaltino", "2924900"}; + rows[508] = new String[] {"BA", "Planalto", "2925006"}; + rows[509] = new String[] {"BA", "Po\u00e7\u00f5es", "2925105"}; + rows[510] = new String[] {"BA", "Pojuca", "2925204"}; + rows[511] = new String[] {"BA", "Ponto Novo", "2925253"}; + rows[512] = new String[] {"BA", "Porto Seguro", "2925303"}; + rows[513] = new String[] {"BA", "Potiragu\u00e1", "2925402"}; + rows[514] = new String[] {"BA", "Prado", "2925501"}; + rows[515] = new String[] {"BA", "Presidente Dutra", "2925600"}; + rows[516] = new String[] {"BA", "Presidente J\u00e2nio Quadros", "2925709"}; + rows[517] = new String[] {"BA", "Presidente Tancredo Neves", "2925758"}; + rows[518] = new String[] {"BA", "Queimadas", "2925808"}; + rows[519] = new String[] {"BA", "Quijingue", "2925907"}; + rows[520] = new String[] {"BA", "Quixabeira", "2925931"}; + rows[521] = new String[] {"BA", "Rafael Jambeiro", "2925956"}; + rows[522] = new String[] {"BA", "Remanso", "2926004"}; + rows[523] = new String[] {"BA", "Retirol\u00e2ndia", "2926103"}; + rows[524] = new String[] {"BA", "Riach\u00e3o das Neves", "2926202"}; + rows[525] = new String[] {"BA", "Riach\u00e3o do Jacu\u00edpe", "2926301"}; + rows[526] = new String[] {"BA", "Riacho de Santana", "2926400"}; + rows[527] = new String[] {"BA", "Ribeira do Amparo", "2926509"}; + rows[528] = new String[] {"BA", "Ribeira do Pombal", "2926608"}; + rows[529] = new String[] {"BA", "Ribeir\u00e3o do Largo", "2926657"}; + rows[530] = new String[] {"BA", "Rio de Contas", "2926707"}; + rows[531] = new String[] {"BA", "Rio do Ant\u00f4nio", "2926806"}; + rows[532] = new String[] {"BA", "Rio do Pires", "2926905"}; + rows[533] = new String[] {"BA", "Rio Real", "2927002"}; + rows[534] = new String[] {"BA", "Rodelas", "2927101"}; + rows[535] = new String[] {"BA", "Ruy Barbosa", "2927200"}; + rows[536] = new String[] {"BA", "Salinas da Margarida", "2927309"}; + rows[537] = new String[] {"BA", "Salvador", "2927408"}; + rows[538] = new String[] {"BA", "Santa B\u00e1rbara", "2927507"}; + rows[539] = new String[] {"BA", "Santa Br\u00edgida", "2927606"}; + rows[540] = new String[] {"BA", "Santa Cruz Cabr\u00e1lia", "2927705"}; + rows[541] = new String[] {"BA", "Santa Cruz da Vit\u00f3ria", "2927804"}; + rows[542] = new String[] {"BA", "Santa In\u00eas", "2927903"}; + rows[543] = new String[] {"BA", "Santa Luzia", "2928059"}; + rows[544] = new String[] {"BA", "Santa Maria da Vit\u00f3ria", "2928109"}; + rows[545] = new String[] {"BA", "Santa Rita de C\u00e1ssia", "2928406"}; + rows[546] = new String[] {"BA", "Santa Terezinha", "2928505"}; + rows[547] = new String[] {"BA", "Santaluz", "2928000"}; + rows[548] = new String[] {"BA", "Santana", "2928208"}; + rows[549] = new String[] {"BA", "Santan\u00f3polis", "2928307"}; + rows[550] = new String[] {"BA", "Santo Amaro", "2928604"}; + rows[551] = new String[] {"BA", "Santo Ant\u00f4nio de Jesus", "2928703"}; + rows[552] = new String[] {"BA", "Santo Est\u00eav\u00e3o", "2928802"}; + rows[553] = new String[] {"BA", "S\u00e3o Desid\u00e9rio", "2928901"}; + rows[554] = new String[] {"BA", "S\u00e3o Domingos", "2928950"}; + rows[555] = new String[] {"BA", "S\u00e3o Felipe", "2929107"}; + rows[556] = new String[] {"BA", "S\u00e3o F\u00e9lix", "2929008"}; + rows[557] = new String[] {"BA", "S\u00e3o F\u00e9lix do Coribe", "2929057"}; + rows[558] = new String[] {"BA", "S\u00e3o Francisco do Conde", "2929206"}; + rows[559] = new String[] {"BA", "S\u00e3o Gabriel", "2929255"}; + rows[560] = new String[] {"BA", "S\u00e3o Gon\u00e7alo dos Campos", "2929305"}; + rows[561] = new String[] {"BA", "S\u00e3o Jos\u00e9 da Vit\u00f3ria", "2929354"}; + rows[562] = new String[] {"BA", "S\u00e3o Jos\u00e9 do Jacu\u00edpe", "2929370"}; + rows[563] = new String[] {"BA", "S\u00e3o Miguel das Matas", "2929404"}; + rows[564] = new String[] {"BA", "S\u00e3o Sebasti\u00e3o do Pass\u00e9", "2929503"}; + rows[565] = new String[] {"BA", "Sapea\u00e7u", "2929602"}; + rows[566] = new String[] {"BA", "S\u00e1tiro Dias", "2929701"}; + rows[567] = new String[] {"BA", "Saubara", "2929750"}; + rows[568] = new String[] {"BA", "Sa\u00fade", "2929800"}; + rows[569] = new String[] {"BA", "Seabra", "2929909"}; + rows[570] = new String[] {"BA", "Sebasti\u00e3o Laranjeiras", "2930006"}; + rows[571] = new String[] {"BA", "Senhor do Bonfim", "2930105"}; + rows[572] = new String[] {"BA", "Sento S\u00e9", "2930204"}; + rows[573] = new String[] {"BA", "Serra do Ramalho", "2930154"}; + rows[574] = new String[] {"BA", "Serra Dourada", "2930303"}; + rows[575] = new String[] {"BA", "Serra Preta", "2930402"}; + rows[576] = new String[] {"BA", "Serrinha", "2930501"}; + rows[577] = new String[] {"BA", "Serrol\u00e2ndia", "2930600"}; + rows[578] = new String[] {"BA", "Sim\u00f5es Filho", "2930709"}; + rows[579] = new String[] {"BA", "S\u00edtio do Mato", "2930758"}; + rows[580] = new String[] {"BA", "S\u00edtio do Quinto", "2930766"}; + rows[581] = new String[] {"BA", "Sobradinho", "2930774"}; + rows[582] = new String[] {"BA", "Souto Soares", "2930808"}; + rows[583] = new String[] {"BA", "Tabocas do Brejo Velho", "2930907"}; + rows[584] = new String[] {"BA", "Tanha\u00e7u", "2931004"}; + rows[585] = new String[] {"BA", "Tanque Novo", "2931053"}; + rows[586] = new String[] {"BA", "Tanquinho", "2931103"}; + rows[587] = new String[] {"BA", "Tapero\u00e1", "2931202"}; + rows[588] = new String[] {"BA", "Tapiramut\u00e1", "2931301"}; + rows[589] = new String[] {"BA", "Teixeira de Freitas", "2931350"}; + rows[590] = new String[] {"BA", "Teodoro Sampaio", "2931400"}; + rows[591] = new String[] {"BA", "Teofil\u00e2ndia", "2931509"}; + rows[592] = new String[] {"BA", "Teol\u00e2ndia", "2931608"}; + rows[593] = new String[] {"BA", "Terra Nova", "2931707"}; + rows[594] = new String[] {"BA", "Tremedal", "2931806"}; + rows[595] = new String[] {"BA", "Tucano", "2931905"}; + rows[596] = new String[] {"BA", "Uau\u00e1", "2932002"}; + rows[597] = new String[] {"BA", "Uba\u00edra", "2932101"}; + rows[598] = new String[] {"BA", "Ubaitaba", "2932200"}; + rows[599] = new String[] {"BA", "Ubat\u00e3", "2932309"}; + } + + private static void municipalitiesRows3(String[][] rows) { + rows[600] = new String[] {"BA", "Uiba\u00ed", "2932408"}; + rows[601] = new String[] {"BA", "Umburanas", "2932457"}; + rows[602] = new String[] {"BA", "Una", "2932507"}; + rows[603] = new String[] {"BA", "Urandi", "2932606"}; + rows[604] = new String[] {"BA", "Uru\u00e7uca", "2932705"}; + rows[605] = new String[] {"BA", "Utinga", "2932804"}; + rows[606] = new String[] {"BA", "Valen\u00e7a", "2932903"}; + rows[607] = new String[] {"BA", "Valente", "2933000"}; + rows[608] = new String[] {"BA", "V\u00e1rzea da Ro\u00e7a", "2933059"}; + rows[609] = new String[] {"BA", "V\u00e1rzea do Po\u00e7o", "2933109"}; + rows[610] = new String[] {"BA", "V\u00e1rzea Nova", "2933158"}; + rows[611] = new String[] {"BA", "Varzedo", "2933174"}; + rows[612] = new String[] {"BA", "Vera Cruz", "2933208"}; + rows[613] = new String[] {"BA", "Vereda", "2933257"}; + rows[614] = new String[] {"BA", "Vit\u00f3ria da Conquista", "2933307"}; + rows[615] = new String[] {"BA", "Wagner", "2933406"}; + rows[616] = new String[] {"BA", "Wanderley", "2933455"}; + rows[617] = new String[] {"BA", "Wenceslau Guimar\u00e3es", "2933505"}; + rows[618] = new String[] {"BA", "Xique-Xique", "2933604"}; + rows[619] = new String[] {"CE", "Abaiara", "2300101"}; + rows[620] = new String[] {"CE", "Acarape", "2300150"}; + rows[621] = new String[] {"CE", "Acara\u00fa", "2300200"}; + rows[622] = new String[] {"CE", "Acopiara", "2300309"}; + rows[623] = new String[] {"CE", "Aiuaba", "2300408"}; + rows[624] = new String[] {"CE", "Alc\u00e2ntaras", "2300507"}; + rows[625] = new String[] {"CE", "Altaneira", "2300606"}; + rows[626] = new String[] {"CE", "Alto Santo", "2300705"}; + rows[627] = new String[] {"CE", "Amontada", "2300754"}; + rows[628] = new String[] {"CE", "Antonina do Norte", "2300804"}; + rows[629] = new String[] {"CE", "Apuiar\u00e9s", "2300903"}; + rows[630] = new String[] {"CE", "Aquiraz", "2301000"}; + rows[631] = new String[] {"CE", "Aracati", "2301109"}; + rows[632] = new String[] {"CE", "Aracoiaba", "2301208"}; + rows[633] = new String[] {"CE", "Ararend\u00e1", "2301257"}; + rows[634] = new String[] {"CE", "Araripe", "2301307"}; + rows[635] = new String[] {"CE", "Aratuba", "2301406"}; + rows[636] = new String[] {"CE", "Arneiroz", "2301505"}; + rows[637] = new String[] {"CE", "Assar\u00e9", "2301604"}; + rows[638] = new String[] {"CE", "Aurora", "2301703"}; + rows[639] = new String[] {"CE", "Baixio", "2301802"}; + rows[640] = new String[] {"CE", "Banabui\u00fa", "2301851"}; + rows[641] = new String[] {"CE", "Barbalha", "2301901"}; + rows[642] = new String[] {"CE", "Barreira", "2301950"}; + rows[643] = new String[] {"CE", "Barro", "2302008"}; + rows[644] = new String[] {"CE", "Barroquinha", "2302057"}; + rows[645] = new String[] {"CE", "Baturit\u00e9", "2302107"}; + rows[646] = new String[] {"CE", "Beberibe", "2302206"}; + rows[647] = new String[] {"CE", "Bela Cruz", "2302305"}; + rows[648] = new String[] {"CE", "Boa Viagem", "2302404"}; + rows[649] = new String[] {"CE", "Brejo Santo", "2302503"}; + rows[650] = new String[] {"CE", "Camocim", "2302602"}; + rows[651] = new String[] {"CE", "Campos Sales", "2302701"}; + rows[652] = new String[] {"CE", "Canind\u00e9", "2302800"}; + rows[653] = new String[] {"CE", "Capistrano", "2302909"}; + rows[654] = new String[] {"CE", "Caridade", "2303006"}; + rows[655] = new String[] {"CE", "Carir\u00e9", "2303105"}; + rows[656] = new String[] {"CE", "Cariria\u00e7u", "2303204"}; + rows[657] = new String[] {"CE", "Cari\u00fas", "2303303"}; + rows[658] = new String[] {"CE", "Carnaubal", "2303402"}; + rows[659] = new String[] {"CE", "Cascavel", "2303501"}; + rows[660] = new String[] {"CE", "Catarina", "2303600"}; + rows[661] = new String[] {"CE", "Catunda", "2303659"}; + rows[662] = new String[] {"CE", "Caucaia", "2303709"}; + rows[663] = new String[] {"CE", "Cedro", "2303808"}; + rows[664] = new String[] {"CE", "Chaval", "2303907"}; + rows[665] = new String[] {"CE", "Chor\u00f3", "2303931"}; + rows[666] = new String[] {"CE", "Chorozinho", "2303956"}; + rows[667] = new String[] {"CE", "Corea\u00fa", "2304004"}; + rows[668] = new String[] {"CE", "Crate\u00fas", "2304103"}; + rows[669] = new String[] {"CE", "Crato", "2304202"}; + rows[670] = new String[] {"CE", "Croat\u00e1", "2304236"}; + rows[671] = new String[] {"CE", "Cruz", "2304251"}; + rows[672] = new String[] {"CE", "Deputado Irapuan Pinheiro", "2304269"}; + rows[673] = new String[] {"CE", "Erer\u00e9", "2304277"}; + rows[674] = new String[] {"CE", "Eus\u00e9bio", "2304285"}; + rows[675] = new String[] {"CE", "Farias Brito", "2304301"}; + rows[676] = new String[] {"CE", "Forquilha", "2304350"}; + rows[677] = new String[] {"CE", "Fortaleza", "2304400"}; + rows[678] = new String[] {"CE", "Fortim", "2304459"}; + rows[679] = new String[] {"CE", "Frecheirinha", "2304509"}; + rows[680] = new String[] {"CE", "General Sampaio", "2304608"}; + rows[681] = new String[] {"CE", "Gra\u00e7a", "2304657"}; + rows[682] = new String[] {"CE", "Granja", "2304707"}; + rows[683] = new String[] {"CE", "Granjeiro", "2304806"}; + rows[684] = new String[] {"CE", "Groa\u00edras", "2304905"}; + rows[685] = new String[] {"CE", "Guai\u00faba", "2304954"}; + rows[686] = new String[] {"CE", "Guaraciaba do Norte", "2305001"}; + rows[687] = new String[] {"CE", "Guaramiranga", "2305100"}; + rows[688] = new String[] {"CE", "Hidrol\u00e2ndia", "2305209"}; + rows[689] = new String[] {"CE", "Horizonte", "2305233"}; + rows[690] = new String[] {"CE", "Ibaretama", "2305266"}; + rows[691] = new String[] {"CE", "Ibiapina", "2305308"}; + rows[692] = new String[] {"CE", "Ibicuitinga", "2305332"}; + rows[693] = new String[] {"CE", "Icapu\u00ed", "2305357"}; + rows[694] = new String[] {"CE", "Ic\u00f3", "2305407"}; + rows[695] = new String[] {"CE", "Iguatu", "2305506"}; + rows[696] = new String[] {"CE", "Independ\u00eancia", "2305605"}; + rows[697] = new String[] {"CE", "Ipaporanga", "2305654"}; + rows[698] = new String[] {"CE", "Ipaumirim", "2305704"}; + rows[699] = new String[] {"CE", "Ipu", "2305803"}; + rows[700] = new String[] {"CE", "Ipueiras", "2305902"}; + rows[701] = new String[] {"CE", "Iracema", "2306009"}; + rows[702] = new String[] {"CE", "Irau\u00e7uba", "2306108"}; + rows[703] = new String[] {"CE", "Itai\u00e7aba", "2306207"}; + rows[704] = new String[] {"CE", "Itaitinga", "2306256"}; + rows[705] = new String[] {"CE", "Itapaj\u00e9", "2306306"}; + rows[706] = new String[] {"CE", "Itapipoca", "2306405"}; + rows[707] = new String[] {"CE", "Itapi\u00fana", "2306504"}; + rows[708] = new String[] {"CE", "Itarema", "2306553"}; + rows[709] = new String[] {"CE", "Itatira", "2306603"}; + rows[710] = new String[] {"CE", "Jaguaretama", "2306702"}; + rows[711] = new String[] {"CE", "Jaguaribara", "2306801"}; + rows[712] = new String[] {"CE", "Jaguaribe", "2306900"}; + rows[713] = new String[] {"CE", "Jaguaruana", "2307007"}; + rows[714] = new String[] {"CE", "Jardim", "2307106"}; + rows[715] = new String[] {"CE", "Jati", "2307205"}; + rows[716] = new String[] {"CE", "Jijoca de Jericoacoara", "2307254"}; + rows[717] = new String[] {"CE", "Juazeiro do Norte", "2307304"}; + rows[718] = new String[] {"CE", "Juc\u00e1s", "2307403"}; + rows[719] = new String[] {"CE", "Lavras da Mangabeira", "2307502"}; + rows[720] = new String[] {"CE", "Limoeiro do Norte", "2307601"}; + rows[721] = new String[] {"CE", "Madalena", "2307635"}; + rows[722] = new String[] {"CE", "Maracana\u00fa", "2307650"}; + rows[723] = new String[] {"CE", "Maranguape", "2307700"}; + rows[724] = new String[] {"CE", "Marco", "2307809"}; + rows[725] = new String[] {"CE", "Martin\u00f3pole", "2307908"}; + rows[726] = new String[] {"CE", "Massap\u00ea", "2308005"}; + rows[727] = new String[] {"CE", "Mauriti", "2308104"}; + rows[728] = new String[] {"CE", "Meruoca", "2308203"}; + rows[729] = new String[] {"CE", "Milagres", "2308302"}; + rows[730] = new String[] {"CE", "Milh\u00e3", "2308351"}; + rows[731] = new String[] {"CE", "Mira\u00edma", "2308377"}; + rows[732] = new String[] {"CE", "Miss\u00e3o Velha", "2308401"}; + rows[733] = new String[] {"CE", "Momba\u00e7a", "2308500"}; + rows[734] = new String[] {"CE", "Monsenhor Tabosa", "2308609"}; + rows[735] = new String[] {"CE", "Morada Nova", "2308708"}; + rows[736] = new String[] {"CE", "Mora\u00fajo", "2308807"}; + rows[737] = new String[] {"CE", "Morrinhos", "2308906"}; + rows[738] = new String[] {"CE", "Mucambo", "2309003"}; + rows[739] = new String[] {"CE", "Mulungu", "2309102"}; + rows[740] = new String[] {"CE", "Nova Olinda", "2309201"}; + rows[741] = new String[] {"CE", "Nova Russas", "2309300"}; + rows[742] = new String[] {"CE", "Novo Oriente", "2309409"}; + rows[743] = new String[] {"CE", "Ocara", "2309458"}; + rows[744] = new String[] {"CE", "Or\u00f3s", "2309508"}; + rows[745] = new String[] {"CE", "Pacajus", "2309607"}; + rows[746] = new String[] {"CE", "Pacatuba", "2309706"}; + rows[747] = new String[] {"CE", "Pacoti", "2309805"}; + rows[748] = new String[] {"CE", "Pacuj\u00e1", "2309904"}; + rows[749] = new String[] {"CE", "Palhano", "2310001"}; + rows[750] = new String[] {"CE", "Palm\u00e1cia", "2310100"}; + rows[751] = new String[] {"CE", "Paracuru", "2310209"}; + rows[752] = new String[] {"CE", "Paraipaba", "2310258"}; + rows[753] = new String[] {"CE", "Parambu", "2310308"}; + rows[754] = new String[] {"CE", "Paramoti", "2310407"}; + rows[755] = new String[] {"CE", "Pedra Branca", "2310506"}; + rows[756] = new String[] {"CE", "Penaforte", "2310605"}; + rows[757] = new String[] {"CE", "Pentecoste", "2310704"}; + rows[758] = new String[] {"CE", "Pereiro", "2310803"}; + rows[759] = new String[] {"CE", "Pindoretama", "2310852"}; + rows[760] = new String[] {"CE", "Piquet Carneiro", "2310902"}; + rows[761] = new String[] {"CE", "Pires Ferreira", "2310951"}; + rows[762] = new String[] {"CE", "Poranga", "2311009"}; + rows[763] = new String[] {"CE", "Porteiras", "2311108"}; + rows[764] = new String[] {"CE", "Potengi", "2311207"}; + rows[765] = new String[] {"CE", "Potiretama", "2311231"}; + rows[766] = new String[] {"CE", "Quiterian\u00f3polis", "2311264"}; + rows[767] = new String[] {"CE", "Quixad\u00e1", "2311306"}; + rows[768] = new String[] {"CE", "Quixel\u00f4", "2311355"}; + rows[769] = new String[] {"CE", "Quixeramobim", "2311405"}; + rows[770] = new String[] {"CE", "Quixer\u00e9", "2311504"}; + rows[771] = new String[] {"CE", "Reden\u00e7\u00e3o", "2311603"}; + rows[772] = new String[] {"CE", "Reriutaba", "2311702"}; + rows[773] = new String[] {"CE", "Russas", "2311801"}; + rows[774] = new String[] {"CE", "Saboeiro", "2311900"}; + rows[775] = new String[] {"CE", "Salitre", "2311959"}; + rows[776] = new String[] {"CE", "Santa Quit\u00e9ria", "2312205"}; + rows[777] = new String[] {"CE", "Santana do Acara\u00fa", "2312007"}; + rows[778] = new String[] {"CE", "Santana do Cariri", "2312106"}; + rows[779] = new String[] {"CE", "S\u00e3o Benedito", "2312304"}; + rows[780] = new String[] {"CE", "S\u00e3o Gon\u00e7alo do Amarante", "2312403"}; + rows[781] = new String[] {"CE", "S\u00e3o Jo\u00e3o do Jaguaribe", "2312502"}; + rows[782] = new String[] {"CE", "S\u00e3o Lu\u00eds do Curu", "2312601"}; + rows[783] = new String[] {"CE", "Senador Pompeu", "2312700"}; + rows[784] = new String[] {"CE", "Senador S\u00e1", "2312809"}; + rows[785] = new String[] {"CE", "Sobral", "2312908"}; + rows[786] = new String[] {"CE", "Solon\u00f3pole", "2313005"}; + rows[787] = new String[] {"CE", "Tabuleiro do Norte", "2313104"}; + rows[788] = new String[] {"CE", "Tamboril", "2313203"}; + rows[789] = new String[] {"CE", "Tarrafas", "2313252"}; + rows[790] = new String[] {"CE", "Tau\u00e1", "2313302"}; + rows[791] = new String[] {"CE", "Teju\u00e7uoca", "2313351"}; + rows[792] = new String[] {"CE", "Tiangu\u00e1", "2313401"}; + rows[793] = new String[] {"CE", "Trairi", "2313500"}; + rows[794] = new String[] {"CE", "Tururu", "2313559"}; + rows[795] = new String[] {"CE", "Ubajara", "2313609"}; + rows[796] = new String[] {"CE", "Umari", "2313708"}; + rows[797] = new String[] {"CE", "Umirim", "2313757"}; + rows[798] = new String[] {"CE", "Uruburetama", "2313807"}; + rows[799] = new String[] {"CE", "Uruoca", "2313906"}; + } + + private static void municipalitiesRows4(String[][] rows) { + rows[800] = new String[] {"CE", "Varjota", "2313955"}; + rows[801] = new String[] {"CE", "V\u00e1rzea Alegre", "2314003"}; + rows[802] = new String[] {"CE", "Vi\u00e7osa do Cear\u00e1", "2314102"}; + rows[803] = new String[] {"DF", "Bras\u00edlia", "5300108"}; + rows[804] = new String[] {"ES", "Afonso Cl\u00e1udio", "3200102"}; + rows[805] = new String[] {"ES", "\u00c1gua Doce do Norte", "3200169"}; + rows[806] = new String[] {"ES", "\u00c1guia Branca", "3200136"}; + rows[807] = new String[] {"ES", "Alegre", "3200201"}; + rows[808] = new String[] {"ES", "Alfredo Chaves", "3200300"}; + rows[809] = new String[] {"ES", "Alto Rio Novo", "3200359"}; + rows[810] = new String[] {"ES", "Anchieta", "3200409"}; + rows[811] = new String[] {"ES", "Apiac\u00e1", "3200508"}; + rows[812] = new String[] {"ES", "Aracruz", "3200607"}; + rows[813] = new String[] {"ES", "At\u00edlio Viv\u00e1cqua", "3200706"}; + rows[814] = new String[] {"ES", "Baixo Guandu", "3200805"}; + rows[815] = new String[] {"ES", "Barra de S\u00e3o Francisco", "3200904"}; + rows[816] = new String[] {"ES", "Boa Esperan\u00e7a", "3201001"}; + rows[817] = new String[] {"ES", "Bom Jesus do Norte", "3201100"}; + rows[818] = new String[] {"ES", "Brejetuba", "3201159"}; + rows[819] = new String[] {"ES", "Cachoeiro de Itapemirim", "3201209"}; + rows[820] = new String[] {"ES", "Cariacica", "3201308"}; + rows[821] = new String[] {"ES", "Castelo", "3201407"}; + rows[822] = new String[] {"ES", "Colatina", "3201506"}; + rows[823] = new String[] {"ES", "Concei\u00e7\u00e3o da Barra", "3201605"}; + rows[824] = new String[] {"ES", "Concei\u00e7\u00e3o do Castelo", "3201704"}; + rows[825] = new String[] {"ES", "Divino de S\u00e3o Louren\u00e7o", "3201803"}; + rows[826] = new String[] {"ES", "Domingos Martins", "3201902"}; + rows[827] = new String[] {"ES", "Dores do Rio Preto", "3202009"}; + rows[828] = new String[] {"ES", "Ecoporanga", "3202108"}; + rows[829] = new String[] {"ES", "Fund\u00e3o", "3202207"}; + rows[830] = new String[] {"ES", "Governador Lindenberg", "3202256"}; + rows[831] = new String[] {"ES", "Gua\u00e7u\u00ed", "3202306"}; + rows[832] = new String[] {"ES", "Guarapari", "3202405"}; + rows[833] = new String[] {"ES", "Ibatiba", "3202454"}; + rows[834] = new String[] {"ES", "Ibira\u00e7u", "3202504"}; + rows[835] = new String[] {"ES", "Ibitirama", "3202553"}; + rows[836] = new String[] {"ES", "Iconha", "3202603"}; + rows[837] = new String[] {"ES", "Irupi", "3202652"}; + rows[838] = new String[] {"ES", "Itagua\u00e7u", "3202702"}; + rows[839] = new String[] {"ES", "Itapemirim", "3202801"}; + rows[840] = new String[] {"ES", "Itarana", "3202900"}; + rows[841] = new String[] {"ES", "I\u00fana", "3203007"}; + rows[842] = new String[] {"ES", "Jaguar\u00e9", "3203056"}; + rows[843] = new String[] {"ES", "Jer\u00f4nimo Monteiro", "3203106"}; + rows[844] = new String[] {"ES", "Jo\u00e3o Neiva", "3203130"}; + rows[845] = new String[] {"ES", "Laranja da Terra", "3203163"}; + rows[846] = new String[] {"ES", "Linhares", "3203205"}; + rows[847] = new String[] {"ES", "Manten\u00f3polis", "3203304"}; + rows[848] = new String[] {"ES", "Marata\u00edzes", "3203320"}; + rows[849] = new String[] {"ES", "Marechal Floriano", "3203346"}; + rows[850] = new String[] {"ES", "Maril\u00e2ndia", "3203353"}; + rows[851] = new String[] {"ES", "Mimoso do Sul", "3203403"}; + rows[852] = new String[] {"ES", "Montanha", "3203502"}; + rows[853] = new String[] {"ES", "Mucurici", "3203601"}; + rows[854] = new String[] {"ES", "Muniz Freire", "3203700"}; + rows[855] = new String[] {"ES", "Muqui", "3203809"}; + rows[856] = new String[] {"ES", "Nova Ven\u00e9cia", "3203908"}; + rows[857] = new String[] {"ES", "Pancas", "3204005"}; + rows[858] = new String[] {"ES", "Pedro Can\u00e1rio", "3204054"}; + rows[859] = new String[] {"ES", "Pinheiros", "3204104"}; + rows[860] = new String[] {"ES", "Pi\u00fama", "3204203"}; + rows[861] = new String[] {"ES", "Ponto Belo", "3204252"}; + rows[862] = new String[] {"ES", "Presidente Kennedy", "3204302"}; + rows[863] = new String[] {"ES", "Rio Bananal", "3204351"}; + rows[864] = new String[] {"ES", "Rio Novo do Sul", "3204401"}; + rows[865] = new String[] {"ES", "Santa Leopoldina", "3204500"}; + rows[866] = new String[] {"ES", "Santa Maria de Jetib\u00e1", "3204559"}; + rows[867] = new String[] {"ES", "Santa Teresa", "3204609"}; + rows[868] = new String[] {"ES", "S\u00e3o Domingos do Norte", "3204658"}; + rows[869] = new String[] {"ES", "S\u00e3o Gabriel da Palha", "3204708"}; + rows[870] = new String[] {"ES", "S\u00e3o Jos\u00e9 do Cal\u00e7ado", "3204807"}; + rows[871] = new String[] {"ES", "S\u00e3o Mateus", "3204906"}; + rows[872] = new String[] {"ES", "S\u00e3o Roque do Cana\u00e3", "3204955"}; + rows[873] = new String[] {"ES", "Serra", "3205002"}; + rows[874] = new String[] {"ES", "Sooretama", "3205010"}; + rows[875] = new String[] {"ES", "Vargem Alta", "3205036"}; + rows[876] = new String[] {"ES", "Venda Nova do Imigrante", "3205069"}; + rows[877] = new String[] {"ES", "Viana", "3205101"}; + rows[878] = new String[] {"ES", "Vila Pav\u00e3o", "3205150"}; + rows[879] = new String[] {"ES", "Vila Val\u00e9rio", "3205176"}; + rows[880] = new String[] {"ES", "Vila Velha", "3205200"}; + rows[881] = new String[] {"ES", "Vit\u00f3ria", "3205309"}; + rows[882] = new String[] {"GO", "Abadia de Goi\u00e1s", "5200050"}; + rows[883] = new String[] {"GO", "Abadi\u00e2nia", "5200100"}; + rows[884] = new String[] {"GO", "Acre\u00fana", "5200134"}; + rows[885] = new String[] {"GO", "Adel\u00e2ndia", "5200159"}; + rows[886] = new String[] {"GO", "\u00c1gua Fria de Goi\u00e1s", "5200175"}; + rows[887] = new String[] {"GO", "\u00c1gua Limpa", "5200209"}; + rows[888] = new String[] {"GO", "\u00c1guas Lindas de Goi\u00e1s", "5200258"}; + rows[889] = new String[] {"GO", "Alex\u00e2nia", "5200308"}; + rows[890] = new String[] {"GO", "Alo\u00e2ndia", "5200506"}; + rows[891] = new String[] {"GO", "Alto Horizonte", "5200555"}; + rows[892] = new String[] {"GO", "Alto Para\u00edso de Goi\u00e1s", "5200605"}; + rows[893] = new String[] {"GO", "Alvorada do Norte", "5200803"}; + rows[894] = new String[] {"GO", "Amaralina", "5200829"}; + rows[895] = new String[] {"GO", "Americano do Brasil", "5200852"}; + rows[896] = new String[] {"GO", "Amorin\u00f3polis", "5200902"}; + rows[897] = new String[] {"GO", "An\u00e1polis", "5201108"}; + rows[898] = new String[] {"GO", "Anhanguera", "5201207"}; + rows[899] = new String[] {"GO", "Anicuns", "5201306"}; + rows[900] = new String[] {"GO", "Aparecida de Goi\u00e2nia", "5201405"}; + rows[901] = new String[] {"GO", "Aparecida do Rio Doce", "5201454"}; + rows[902] = new String[] {"GO", "Apor\u00e9", "5201504"}; + rows[903] = new String[] {"GO", "Ara\u00e7u", "5201603"}; + rows[904] = new String[] {"GO", "Aragar\u00e7as", "5201702"}; + rows[905] = new String[] {"GO", "Aragoi\u00e2nia", "5201801"}; + rows[906] = new String[] {"GO", "Araguapaz", "5202155"}; + rows[907] = new String[] {"GO", "Aren\u00f3polis", "5202353"}; + rows[908] = new String[] {"GO", "Aruan\u00e3", "5202502"}; + rows[909] = new String[] {"GO", "Auril\u00e2ndia", "5202601"}; + rows[910] = new String[] {"GO", "Avelin\u00f3polis", "5202809"}; + rows[911] = new String[] {"GO", "Baliza", "5203104"}; + rows[912] = new String[] {"GO", "Barro Alto", "5203203"}; + rows[913] = new String[] {"GO", "Bela Vista de Goi\u00e1s", "5203302"}; + rows[914] = new String[] {"GO", "Bom Jardim de Goi\u00e1s", "5203401"}; + rows[915] = new String[] {"GO", "Bom Jesus de Goi\u00e1s", "5203500"}; + rows[916] = new String[] {"GO", "Bonfin\u00f3polis", "5203559"}; + rows[917] = new String[] {"GO", "Bon\u00f3polis", "5203575"}; + rows[918] = new String[] {"GO", "Brazabrantes", "5203609"}; + rows[919] = new String[] {"GO", "Brit\u00e2nia", "5203807"}; + rows[920] = new String[] {"GO", "Buriti Alegre", "5203906"}; + rows[921] = new String[] {"GO", "Buriti de Goi\u00e1s", "5203939"}; + rows[922] = new String[] {"GO", "Buritin\u00f3polis", "5203962"}; + rows[923] = new String[] {"GO", "Cabeceiras", "5204003"}; + rows[924] = new String[] {"GO", "Cachoeira Alta", "5204102"}; + rows[925] = new String[] {"GO", "Cachoeira de Goi\u00e1s", "5204201"}; + rows[926] = new String[] {"GO", "Cachoeira Dourada", "5204250"}; + rows[927] = new String[] {"GO", "Ca\u00e7u", "5204300"}; + rows[928] = new String[] {"GO", "Caiap\u00f4nia", "5204409"}; + rows[929] = new String[] {"GO", "Caldas Novas", "5204508"}; + rows[930] = new String[] {"GO", "Caldazinha", "5204557"}; + rows[931] = new String[] {"GO", "Campestre de Goi\u00e1s", "5204607"}; + rows[932] = new String[] {"GO", "Campina\u00e7u", "5204656"}; + rows[933] = new String[] {"GO", "Campinorte", "5204706"}; + rows[934] = new String[] {"GO", "Campo Alegre de Goi\u00e1s", "5204805"}; + rows[935] = new String[] {"GO", "Campo Limpo de Goi\u00e1s", "5204854"}; + rows[936] = new String[] {"GO", "Campos Belos", "5204904"}; + rows[937] = new String[] {"GO", "Campos Verdes", "5204953"}; + rows[938] = new String[] {"GO", "Carmo do Rio Verde", "5205000"}; + rows[939] = new String[] {"GO", "Castel\u00e2ndia", "5205059"}; + rows[940] = new String[] {"GO", "Catal\u00e3o", "5205109"}; + rows[941] = new String[] {"GO", "Catura\u00ed", "5205208"}; + rows[942] = new String[] {"GO", "Cavalcante", "5205307"}; + rows[943] = new String[] {"GO", "Ceres", "5205406"}; + rows[944] = new String[] {"GO", "Cezarina", "5205455"}; + rows[945] = new String[] {"GO", "Chapad\u00e3o do C\u00e9u", "5205471"}; + rows[946] = new String[] {"GO", "Cidade Ocidental", "5205497"}; + rows[947] = new String[] {"GO", "Cocalzinho de Goi\u00e1s", "5205513"}; + rows[948] = new String[] {"GO", "Colinas do Sul", "5205521"}; + rows[949] = new String[] {"GO", "C\u00f3rrego do Ouro", "5205703"}; + rows[950] = new String[] {"GO", "Corumb\u00e1 de Goi\u00e1s", "5205802"}; + rows[951] = new String[] {"GO", "Corumba\u00edba", "5205901"}; + rows[952] = new String[] {"GO", "Cristalina", "5206206"}; + rows[953] = new String[] {"GO", "Cristian\u00f3polis", "5206305"}; + rows[954] = new String[] {"GO", "Crix\u00e1s", "5206404"}; + rows[955] = new String[] {"GO", "Crom\u00ednia", "5206503"}; + rows[956] = new String[] {"GO", "Cumari", "5206602"}; + rows[957] = new String[] {"GO", "Damian\u00f3polis", "5206701"}; + rows[958] = new String[] {"GO", "Damol\u00e2ndia", "5206800"}; + rows[959] = new String[] {"GO", "Davin\u00f3polis", "5206909"}; + rows[960] = new String[] {"GO", "Diorama", "5207105"}; + rows[961] = new String[] {"GO", "Divin\u00f3polis de Goi\u00e1s", "5208301"}; + rows[962] = new String[] {"GO", "Doverl\u00e2ndia", "5207253"}; + rows[963] = new String[] {"GO", "Edealina", "5207352"}; + rows[964] = new String[] {"GO", "Ed\u00e9ia", "5207402"}; + rows[965] = new String[] {"GO", "Estrela do Norte", "5207501"}; + rows[966] = new String[] {"GO", "Faina", "5207535"}; + rows[967] = new String[] {"GO", "Fazenda Nova", "5207600"}; + rows[968] = new String[] {"GO", "Firmin\u00f3polis", "5207808"}; + rows[969] = new String[] {"GO", "Flores de Goi\u00e1s", "5207907"}; + rows[970] = new String[] {"GO", "Formosa", "5208004"}; + rows[971] = new String[] {"GO", "Formoso", "5208103"}; + rows[972] = new String[] {"GO", "Gameleira de Goi\u00e1s", "5208152"}; + rows[973] = new String[] {"GO", "Goian\u00e1polis", "5208400"}; + rows[974] = new String[] {"GO", "Goiandira", "5208509"}; + rows[975] = new String[] {"GO", "Goian\u00e9sia", "5208608"}; + rows[976] = new String[] {"GO", "Goi\u00e2nia", "5208707"}; + rows[977] = new String[] {"GO", "Goianira", "5208806"}; + rows[978] = new String[] {"GO", "Goi\u00e1s", "5208905"}; + rows[979] = new String[] {"GO", "Goiatuba", "5209101"}; + rows[980] = new String[] {"GO", "Gouvel\u00e2ndia", "5209150"}; + rows[981] = new String[] {"GO", "Guap\u00f3", "5209200"}; + rows[982] = new String[] {"GO", "Guara\u00edta", "5209291"}; + rows[983] = new String[] {"GO", "Guarani de Goi\u00e1s", "5209408"}; + rows[984] = new String[] {"GO", "Guarinos", "5209457"}; + rows[985] = new String[] {"GO", "Heitora\u00ed", "5209606"}; + rows[986] = new String[] {"GO", "Hidrol\u00e2ndia", "5209705"}; + rows[987] = new String[] {"GO", "Hidrolina", "5209804"}; + rows[988] = new String[] {"GO", "Iaciara", "5209903"}; + rows[989] = new String[] {"GO", "Inaciol\u00e2ndia", "5209937"}; + rows[990] = new String[] {"GO", "Indiara", "5209952"}; + rows[991] = new String[] {"GO", "Inhumas", "5210000"}; + rows[992] = new String[] {"GO", "Ipameri", "5210109"}; + rows[993] = new String[] {"GO", "Ipiranga de Goi\u00e1s", "5210158"}; + rows[994] = new String[] {"GO", "Ipor\u00e1", "5210208"}; + rows[995] = new String[] {"GO", "Israel\u00e2ndia", "5210307"}; + rows[996] = new String[] {"GO", "Itabera\u00ed", "5210406"}; + rows[997] = new String[] {"GO", "Itaguari", "5210562"}; + rows[998] = new String[] {"GO", "Itaguaru", "5210604"}; + rows[999] = new String[] {"GO", "Itaj\u00e1", "5210802"}; + } + + private static void municipalitiesRows5(String[][] rows) { + rows[1000] = new String[] {"GO", "Itapaci", "5210901"}; + rows[1001] = new String[] {"GO", "Itapirapu\u00e3", "5211008"}; + rows[1002] = new String[] {"GO", "Itapuranga", "5211206"}; + rows[1003] = new String[] {"GO", "Itarum\u00e3", "5211305"}; + rows[1004] = new String[] {"GO", "Itau\u00e7u", "5211404"}; + rows[1005] = new String[] {"GO", "Itumbiara", "5211503"}; + rows[1006] = new String[] {"GO", "Ivol\u00e2ndia", "5211602"}; + rows[1007] = new String[] {"GO", "Jandaia", "5211701"}; + rows[1008] = new String[] {"GO", "Jaragu\u00e1", "5211800"}; + rows[1009] = new String[] {"GO", "Jata\u00ed", "5211909"}; + rows[1010] = new String[] {"GO", "Jaupaci", "5212006"}; + rows[1011] = new String[] {"GO", "Jes\u00fapolis", "5212055"}; + rows[1012] = new String[] {"GO", "Jovi\u00e2nia", "5212105"}; + rows[1013] = new String[] {"GO", "Jussara", "5212204"}; + rows[1014] = new String[] {"GO", "Lagoa Santa", "5212253"}; + rows[1015] = new String[] {"GO", "Leopoldo de Bulh\u00f5es", "5212303"}; + rows[1016] = new String[] {"GO", "Luzi\u00e2nia", "5212501"}; + rows[1017] = new String[] {"GO", "Mairipotaba", "5212600"}; + rows[1018] = new String[] {"GO", "Mamba\u00ed", "5212709"}; + rows[1019] = new String[] {"GO", "Mara Rosa", "5212808"}; + rows[1020] = new String[] {"GO", "Marzag\u00e3o", "5212907"}; + rows[1021] = new String[] {"GO", "Matrinch\u00e3", "5212956"}; + rows[1022] = new String[] {"GO", "Mauril\u00e2ndia", "5213004"}; + rows[1023] = new String[] {"GO", "Mimoso de Goi\u00e1s", "5213053"}; + rows[1024] = new String[] {"GO", "Mina\u00e7u", "5213087"}; + rows[1025] = new String[] {"GO", "Mineiros", "5213103"}; + rows[1026] = new String[] {"GO", "Moipor\u00e1", "5213400"}; + rows[1027] = new String[] {"GO", "Monte Alegre de Goi\u00e1s", "5213509"}; + rows[1028] = new String[] {"GO", "Montes Claros de Goi\u00e1s", "5213707"}; + rows[1029] = new String[] {"GO", "Montividiu", "5213756"}; + rows[1030] = new String[] {"GO", "Montividiu do Norte", "5213772"}; + rows[1031] = new String[] {"GO", "Morrinhos", "5213806"}; + rows[1032] = new String[] {"GO", "Morro Agudo de Goi\u00e1s", "5213855"}; + rows[1033] = new String[] {"GO", "Moss\u00e2medes", "5213905"}; + rows[1034] = new String[] {"GO", "Mozarl\u00e2ndia", "5214002"}; + rows[1035] = new String[] {"GO", "Mundo Novo", "5214051"}; + rows[1036] = new String[] {"GO", "Mutun\u00f3polis", "5214101"}; + rows[1037] = new String[] {"GO", "Naz\u00e1rio", "5214408"}; + rows[1038] = new String[] {"GO", "Ner\u00f3polis", "5214507"}; + rows[1039] = new String[] {"GO", "Niquel\u00e2ndia", "5214606"}; + rows[1040] = new String[] {"GO", "Nova Am\u00e9rica", "5214705"}; + rows[1041] = new String[] {"GO", "Nova Aurora", "5214804"}; + rows[1042] = new String[] {"GO", "Nova Crix\u00e1s", "5214838"}; + rows[1043] = new String[] {"GO", "Nova Gl\u00f3ria", "5214861"}; + rows[1044] = new String[] {"GO", "Nova Igua\u00e7u de Goi\u00e1s", "5214879"}; + rows[1045] = new String[] {"GO", "Nova Roma", "5214903"}; + rows[1046] = new String[] {"GO", "Nova Veneza", "5215009"}; + rows[1047] = new String[] {"GO", "Novo Brasil", "5215207"}; + rows[1048] = new String[] {"GO", "Novo Gama", "5215231"}; + rows[1049] = new String[] {"GO", "Novo Planalto", "5215256"}; + rows[1050] = new String[] {"GO", "Orizona", "5215306"}; + rows[1051] = new String[] {"GO", "Ouro Verde de Goi\u00e1s", "5215405"}; + rows[1052] = new String[] {"GO", "Ouvidor", "5215504"}; + rows[1053] = new String[] {"GO", "Padre Bernardo", "5215603"}; + rows[1054] = new String[] {"GO", "Palestina de Goi\u00e1s", "5215652"}; + rows[1055] = new String[] {"GO", "Palmeiras de Goi\u00e1s", "5215702"}; + rows[1056] = new String[] {"GO", "Palmelo", "5215801"}; + rows[1057] = new String[] {"GO", "Palmin\u00f3polis", "5215900"}; + rows[1058] = new String[] {"GO", "Panam\u00e1", "5216007"}; + rows[1059] = new String[] {"GO", "Paranaiguara", "5216304"}; + rows[1060] = new String[] {"GO", "Para\u00fana", "5216403"}; + rows[1061] = new String[] {"GO", "Perol\u00e2ndia", "5216452"}; + rows[1062] = new String[] {"GO", "Petrolina de Goi\u00e1s", "5216809"}; + rows[1063] = new String[] {"GO", "Pilar de Goi\u00e1s", "5216908"}; + rows[1064] = new String[] {"GO", "Piracanjuba", "5217104"}; + rows[1065] = new String[] {"GO", "Piranhas", "5217203"}; + rows[1066] = new String[] {"GO", "Piren\u00f3polis", "5217302"}; + rows[1067] = new String[] {"GO", "Pires do Rio", "5217401"}; + rows[1068] = new String[] {"GO", "Planaltina", "5217609"}; + rows[1069] = new String[] {"GO", "Pontalina", "5217708"}; + rows[1070] = new String[] {"GO", "Porangatu", "5218003"}; + rows[1071] = new String[] {"GO", "Porteir\u00e3o", "5218052"}; + rows[1072] = new String[] {"GO", "Portel\u00e2ndia", "5218102"}; + rows[1073] = new String[] {"GO", "Posse", "5218300"}; + rows[1074] = new String[] {"GO", "Professor Jamil", "5218391"}; + rows[1075] = new String[] {"GO", "Quirin\u00f3polis", "5218508"}; + rows[1076] = new String[] {"GO", "Rialma", "5218607"}; + rows[1077] = new String[] {"GO", "Rian\u00e1polis", "5218706"}; + rows[1078] = new String[] {"GO", "Rio Quente", "5218789"}; + rows[1079] = new String[] {"GO", "Rio Verde", "5218805"}; + rows[1080] = new String[] {"GO", "Rubiataba", "5218904"}; + rows[1081] = new String[] {"GO", "Sanclerl\u00e2ndia", "5219001"}; + rows[1082] = new String[] {"GO", "Santa B\u00e1rbara de Goi\u00e1s", "5219100"}; + rows[1083] = new String[] {"GO", "Santa Cruz de Goi\u00e1s", "5219209"}; + rows[1084] = new String[] {"GO", "Santa F\u00e9 de Goi\u00e1s", "5219258"}; + rows[1085] = new String[] {"GO", "Santa Helena de Goi\u00e1s", "5219308"}; + rows[1086] = new String[] {"GO", "Santa Isabel", "5219357"}; + rows[1087] = new String[] {"GO", "Santa Rita do Araguaia", "5219407"}; + rows[1088] = new String[] {"GO", "Santa Rita do Novo Destino", "5219456"}; + rows[1089] = new String[] {"GO", "Santa Rosa de Goi\u00e1s", "5219506"}; + rows[1090] = new String[] {"GO", "Santa Tereza de Goi\u00e1s", "5219605"}; + rows[1091] = new String[] {"GO", "Santa Terezinha de Goi\u00e1s", "5219704"}; + rows[1092] = new String[] {"GO", "Santo Ant\u00f4nio da Barra", "5219712"}; + rows[1093] = new String[] {"GO", "Santo Ant\u00f4nio de Goi\u00e1s", "5219738"}; + rows[1094] = new String[] {"GO", "Santo Ant\u00f4nio do Descoberto", "5219753"}; + rows[1095] = new String[] {"GO", "S\u00e3o Domingos", "5219803"}; + rows[1096] = new String[] {"GO", "S\u00e3o Francisco de Goi\u00e1s", "5219902"}; + rows[1097] = new String[] {"GO", "S\u00e3o Jo\u00e3o d'Alian\u00e7a", "5220009"}; + rows[1098] = new String[] {"GO", "S\u00e3o Jo\u00e3o da Para\u00fana", "5220058"}; + rows[1099] = new String[] {"GO", "S\u00e3o Lu\u00eds de Montes Belos", "5220108"}; + rows[1100] = new String[] {"GO", "S\u00e3o Luiz do Norte", "5220157"}; + rows[1101] = new String[] {"GO", "S\u00e3o Miguel do Araguaia", "5220207"}; + rows[1102] = new String[] {"GO", "S\u00e3o Miguel do Passa Quatro", "5220264"}; + rows[1103] = new String[] {"GO", "S\u00e3o Patr\u00edcio", "5220280"}; + rows[1104] = new String[] {"GO", "S\u00e3o Sim\u00e3o", "5220405"}; + rows[1105] = new String[] {"GO", "Senador Canedo", "5220454"}; + rows[1106] = new String[] {"GO", "Serran\u00f3polis", "5220504"}; + rows[1107] = new String[] {"GO", "Silv\u00e2nia", "5220603"}; + rows[1108] = new String[] {"GO", "Simol\u00e2ndia", "5220686"}; + rows[1109] = new String[] {"GO", "S\u00edtio d'Abadia", "5220702"}; + rows[1110] = new String[] {"GO", "Taquaral de Goi\u00e1s", "5221007"}; + rows[1111] = new String[] {"GO", "Teresina de Goi\u00e1s", "5221080"}; + rows[1112] = new String[] {"GO", "Terez\u00f3polis de Goi\u00e1s", "5221197"}; + rows[1113] = new String[] {"GO", "Tr\u00eas Ranchos", "5221304"}; + rows[1114] = new String[] {"GO", "Trindade", "5221403"}; + rows[1115] = new String[] {"GO", "Trombas", "5221452"}; + rows[1116] = new String[] {"GO", "Turv\u00e2nia", "5221502"}; + rows[1117] = new String[] {"GO", "Turvel\u00e2ndia", "5221551"}; + rows[1118] = new String[] {"GO", "Uirapuru", "5221577"}; + rows[1119] = new String[] {"GO", "Urua\u00e7u", "5221601"}; + rows[1120] = new String[] {"GO", "Uruana", "5221700"}; + rows[1121] = new String[] {"GO", "Uruta\u00ed", "5221809"}; + rows[1122] = new String[] {"GO", "Valpara\u00edso de Goi\u00e1s", "5221858"}; + rows[1123] = new String[] {"GO", "Varj\u00e3o", "5221908"}; + rows[1124] = new String[] {"GO", "Vian\u00f3polis", "5222005"}; + rows[1125] = new String[] {"GO", "Vicentin\u00f3polis", "5222054"}; + rows[1126] = new String[] {"GO", "Vila Boa", "5222203"}; + rows[1127] = new String[] {"GO", "Vila Prop\u00edcio", "5222302"}; + rows[1128] = new String[] {"MA", "A\u00e7ail\u00e2ndia", "2100055"}; + rows[1129] = new String[] {"MA", "Afonso Cunha", "2100105"}; + rows[1130] = new String[] {"MA", "\u00c1gua Doce do Maranh\u00e3o", "2100154"}; + rows[1131] = new String[] {"MA", "Alc\u00e2ntara", "2100204"}; + rows[1132] = new String[] {"MA", "Aldeias Altas", "2100303"}; + rows[1133] = new String[] {"MA", "Altamira do Maranh\u00e3o", "2100402"}; + rows[1134] = new String[] {"MA", "Alto Alegre do Maranh\u00e3o", "2100436"}; + rows[1135] = new String[] {"MA", "Alto Alegre do Pindar\u00e9", "2100477"}; + rows[1136] = new String[] {"MA", "Alto Parna\u00edba", "2100501"}; + rows[1137] = new String[] {"MA", "Amap\u00e1 do Maranh\u00e3o", "2100550"}; + rows[1138] = new String[] {"MA", "Amarante do Maranh\u00e3o", "2100600"}; + rows[1139] = new String[] {"MA", "Anajatuba", "2100709"}; + rows[1140] = new String[] {"MA", "Anapurus", "2100808"}; + rows[1141] = new String[] {"MA", "Apicum-A\u00e7u", "2100832"}; + rows[1142] = new String[] {"MA", "Araguan\u00e3", "2100873"}; + rows[1143] = new String[] {"MA", "Araioses", "2100907"}; + rows[1144] = new String[] {"MA", "Arame", "2100956"}; + rows[1145] = new String[] {"MA", "Arari", "2101004"}; + rows[1146] = new String[] {"MA", "Axix\u00e1", "2101103"}; + rows[1147] = new String[] {"MA", "Bacabal", "2101202"}; + rows[1148] = new String[] {"MA", "Bacabeira", "2101251"}; + rows[1149] = new String[] {"MA", "Bacuri", "2101301"}; + rows[1150] = new String[] {"MA", "Bacurituba", "2101350"}; + rows[1151] = new String[] {"MA", "Balsas", "2101400"}; + rows[1152] = new String[] {"MA", "Bar\u00e3o de Graja\u00fa", "2101509"}; + rows[1153] = new String[] {"MA", "Barra do Corda", "2101608"}; + rows[1154] = new String[] {"MA", "Barreirinhas", "2101707"}; + rows[1155] = new String[] {"MA", "Bela Vista do Maranh\u00e3o", "2101772"}; + rows[1156] = new String[] {"MA", "Bel\u00e1gua", "2101731"}; + rows[1157] = new String[] {"MA", "Benedito Leite", "2101806"}; + rows[1158] = new String[] {"MA", "Bequim\u00e3o", "2101905"}; + rows[1159] = new String[] {"MA", "Bernardo do Mearim", "2101939"}; + rows[1160] = new String[] {"MA", "Boa Vista do Gurupi", "2101970"}; + rows[1161] = new String[] {"MA", "Bom Jardim", "2102002"}; + rows[1162] = new String[] {"MA", "Bom Jesus das Selvas", "2102036"}; + rows[1163] = new String[] {"MA", "Bom Lugar", "2102077"}; + rows[1164] = new String[] {"MA", "Brejo", "2102101"}; + rows[1165] = new String[] {"MA", "Brejo de Areia", "2102150"}; + rows[1166] = new String[] {"MA", "Buriti", "2102200"}; + rows[1167] = new String[] {"MA", "Buriti Bravo", "2102309"}; + rows[1168] = new String[] {"MA", "Buriticupu", "2102325"}; + rows[1169] = new String[] {"MA", "Buritirana", "2102358"}; + rows[1170] = new String[] {"MA", "Cachoeira Grande", "2102374"}; + rows[1171] = new String[] {"MA", "Cajapi\u00f3", "2102408"}; + rows[1172] = new String[] {"MA", "Cajari", "2102507"}; + rows[1173] = new String[] {"MA", "Campestre do Maranh\u00e3o", "2102556"}; + rows[1174] = new String[] {"MA", "C\u00e2ndido Mendes", "2102606"}; + rows[1175] = new String[] {"MA", "Cantanhede", "2102705"}; + rows[1176] = new String[] {"MA", "Capinzal do Norte", "2102754"}; + rows[1177] = new String[] {"MA", "Carolina", "2102804"}; + rows[1178] = new String[] {"MA", "Carutapera", "2102903"}; + rows[1179] = new String[] {"MA", "Caxias", "2103000"}; + rows[1180] = new String[] {"MA", "Cedral", "2103109"}; + rows[1181] = new String[] {"MA", "Central do Maranh\u00e3o", "2103125"}; + rows[1182] = new String[] {"MA", "Centro do Guilherme", "2103158"}; + rows[1183] = new String[] {"MA", "Centro Novo do Maranh\u00e3o", "2103174"}; + rows[1184] = new String[] {"MA", "Chapadinha", "2103208"}; + rows[1185] = new String[] {"MA", "Cidel\u00e2ndia", "2103257"}; + rows[1186] = new String[] {"MA", "Cod\u00f3", "2103307"}; + rows[1187] = new String[] {"MA", "Coelho Neto", "2103406"}; + rows[1188] = new String[] {"MA", "Colinas", "2103505"}; + rows[1189] = new String[] {"MA", "Concei\u00e7\u00e3o do Lago-A\u00e7u", "2103554"}; + rows[1190] = new String[] {"MA", "Coroat\u00e1", "2103604"}; + rows[1191] = new String[] {"MA", "Cururupu", "2103703"}; + rows[1192] = new String[] {"MA", "Davin\u00f3polis", "2103752"}; + rows[1193] = new String[] {"MA", "Dom Pedro", "2103802"}; + rows[1194] = new String[] {"MA", "Duque Bacelar", "2103901"}; + rows[1195] = new String[] {"MA", "Esperantin\u00f3polis", "2104008"}; + rows[1196] = new String[] {"MA", "Estreito", "2104057"}; + rows[1197] = new String[] {"MA", "Feira Nova do Maranh\u00e3o", "2104073"}; + rows[1198] = new String[] {"MA", "Fernando Falc\u00e3o", "2104081"}; + rows[1199] = new String[] {"MA", "Formosa da Serra Negra", "2104099"}; + } + + private static void municipalitiesRows6(String[][] rows) { + rows[1200] = new String[] {"MA", "Fortaleza dos Nogueiras", "2104107"}; + rows[1201] = new String[] {"MA", "Fortuna", "2104206"}; + rows[1202] = new String[] {"MA", "Godofredo Viana", "2104305"}; + rows[1203] = new String[] {"MA", "Gon\u00e7alves Dias", "2104404"}; + rows[1204] = new String[] {"MA", "Governador Archer", "2104503"}; + rows[1205] = new String[] {"MA", "Governador Edison Lob\u00e3o", "2104552"}; + rows[1206] = new String[] {"MA", "Governador Eug\u00eanio Barros", "2104602"}; + rows[1207] = new String[] {"MA", "Governador Luiz Rocha", "2104628"}; + rows[1208] = new String[] {"MA", "Governador Newton Bello", "2104651"}; + rows[1209] = new String[] {"MA", "Governador Nunes Freire", "2104677"}; + rows[1210] = new String[] {"MA", "Gra\u00e7a Aranha", "2104701"}; + rows[1211] = new String[] {"MA", "Graja\u00fa", "2104800"}; + rows[1212] = new String[] {"MA", "Guimar\u00e3es", "2104909"}; + rows[1213] = new String[] {"MA", "Humberto de Campos", "2105005"}; + rows[1214] = new String[] {"MA", "Icatu", "2105104"}; + rows[1215] = new String[] {"MA", "Igarap\u00e9 do Meio", "2105153"}; + rows[1216] = new String[] {"MA", "Igarap\u00e9 Grande", "2105203"}; + rows[1217] = new String[] {"MA", "Imperatriz", "2105302"}; + rows[1218] = new String[] {"MA", "Itaipava do Graja\u00fa", "2105351"}; + rows[1219] = new String[] {"MA", "Itapecuru Mirim", "2105401"}; + rows[1220] = new String[] {"MA", "Itinga do Maranh\u00e3o", "2105427"}; + rows[1221] = new String[] {"MA", "Jatob\u00e1", "2105450"}; + rows[1222] = new String[] {"MA", "Jenipapo dos Vieiras", "2105476"}; + rows[1223] = new String[] {"MA", "Jo\u00e3o Lisboa", "2105500"}; + rows[1224] = new String[] {"MA", "Josel\u00e2ndia", "2105609"}; + rows[1225] = new String[] {"MA", "Junco do Maranh\u00e3o", "2105658"}; + rows[1226] = new String[] {"MA", "Lago da Pedra", "2105708"}; + rows[1227] = new String[] {"MA", "Lago do Junco", "2105807"}; + rows[1228] = new String[] {"MA", "Lago dos Rodrigues", "2105948"}; + rows[1229] = new String[] {"MA", "Lago Verde", "2105906"}; + rows[1230] = new String[] {"MA", "Lagoa do Mato", "2105922"}; + rows[1231] = new String[] {"MA", "Lagoa Grande do Maranh\u00e3o", "2105963"}; + rows[1232] = new String[] {"MA", "Lajeado Novo", "2105989"}; + rows[1233] = new String[] {"MA", "Lima Campos", "2106003"}; + rows[1234] = new String[] {"MA", "Loreto", "2106102"}; + rows[1235] = new String[] {"MA", "Lu\u00eds Domingues", "2106201"}; + rows[1236] = new String[] {"MA", "Magalh\u00e3es de Almeida", "2106300"}; + rows[1237] = new String[] {"MA", "Maraca\u00e7um\u00e9", "2106326"}; + rows[1238] = new String[] {"MA", "Maraj\u00e1 do Sena", "2106359"}; + rows[1239] = new String[] {"MA", "Maranh\u00e3ozinho", "2106375"}; + rows[1240] = new String[] {"MA", "Mata Roma", "2106409"}; + rows[1241] = new String[] {"MA", "Matinha", "2106508"}; + rows[1242] = new String[] {"MA", "Mat\u00f5es", "2106607"}; + rows[1243] = new String[] {"MA", "Mat\u00f5es do Norte", "2106631"}; + rows[1244] = new String[] {"MA", "Milagres do Maranh\u00e3o", "2106672"}; + rows[1245] = new String[] {"MA", "Mirador", "2106706"}; + rows[1246] = new String[] {"MA", "Miranda do Norte", "2106755"}; + rows[1247] = new String[] {"MA", "Mirinzal", "2106805"}; + rows[1248] = new String[] {"MA", "Mon\u00e7\u00e3o", "2106904"}; + rows[1249] = new String[] {"MA", "Montes Altos", "2107001"}; + rows[1250] = new String[] {"MA", "Morros", "2107100"}; + rows[1251] = new String[] {"MA", "Nina Rodrigues", "2107209"}; + rows[1252] = new String[] {"MA", "Nova Colinas", "2107258"}; + rows[1253] = new String[] {"MA", "Nova Iorque", "2107308"}; + rows[1254] = new String[] {"MA", "Nova Olinda do Maranh\u00e3o", "2107357"}; + rows[1255] = new String[] {"MA", "Olho d'\u00c1gua das Cunh\u00e3s", "2107407"}; + rows[1256] = new String[] {"MA", "Olinda Nova do Maranh\u00e3o", "2107456"}; + rows[1257] = new String[] {"MA", "Pa\u00e7o do Lumiar", "2107506"}; + rows[1258] = new String[] {"MA", "Palmeir\u00e2ndia", "2107605"}; + rows[1259] = new String[] {"MA", "Paraibano", "2107704"}; + rows[1260] = new String[] {"MA", "Parnarama", "2107803"}; + rows[1261] = new String[] {"MA", "Passagem Franca", "2107902"}; + rows[1262] = new String[] {"MA", "Pastos Bons", "2108009"}; + rows[1263] = new String[] {"MA", "Paulino Neves", "2108058"}; + rows[1264] = new String[] {"MA", "Paulo Ramos", "2108108"}; + rows[1265] = new String[] {"MA", "Pedreiras", "2108207"}; + rows[1266] = new String[] {"MA", "Pedro do Ros\u00e1rio", "2108256"}; + rows[1267] = new String[] {"MA", "Penalva", "2108306"}; + rows[1268] = new String[] {"MA", "Peri Mirim", "2108405"}; + rows[1269] = new String[] {"MA", "Peritor\u00f3", "2108454"}; + rows[1270] = new String[] {"MA", "Pindar\u00e9-Mirim", "2108504"}; + rows[1271] = new String[] {"MA", "Pinheiro", "2108603"}; + rows[1272] = new String[] {"MA", "Pio XII", "2108702"}; + rows[1273] = new String[] {"MA", "Pirapemas", "2108801"}; + rows[1274] = new String[] {"MA", "Po\u00e7\u00e3o de Pedras", "2108900"}; + rows[1275] = new String[] {"MA", "Porto Franco", "2109007"}; + rows[1276] = new String[] {"MA", "Porto Rico do Maranh\u00e3o", "2109056"}; + rows[1277] = new String[] {"MA", "Presidente Dutra", "2109106"}; + rows[1278] = new String[] {"MA", "Presidente Juscelino", "2109205"}; + rows[1279] = new String[] {"MA", "Presidente M\u00e9dici", "2109239"}; + rows[1280] = new String[] {"MA", "Presidente Sarney", "2109270"}; + rows[1281] = new String[] {"MA", "Presidente Vargas", "2109304"}; + rows[1282] = new String[] {"MA", "Primeira Cruz", "2109403"}; + rows[1283] = new String[] {"MA", "Raposa", "2109452"}; + rows[1284] = new String[] {"MA", "Riach\u00e3o", "2109502"}; + rows[1285] = new String[] {"MA", "Ribamar Fiquene", "2109551"}; + rows[1286] = new String[] {"MA", "Ros\u00e1rio", "2109601"}; + rows[1287] = new String[] {"MA", "Samba\u00edba", "2109700"}; + rows[1288] = new String[] {"MA", "Santa Filomena do Maranh\u00e3o", "2109759"}; + rows[1289] = new String[] {"MA", "Santa Helena", "2109809"}; + rows[1290] = new String[] {"MA", "Santa In\u00eas", "2109908"}; + rows[1291] = new String[] {"MA", "Santa Luzia", "2110005"}; + rows[1292] = new String[] {"MA", "Santa Luzia do Paru\u00e1", "2110039"}; + rows[1293] = new String[] {"MA", "Santa Quit\u00e9ria do Maranh\u00e3o", "2110104"}; + rows[1294] = new String[] {"MA", "Santa Rita", "2110203"}; + rows[1295] = new String[] {"MA", "Santana do Maranh\u00e3o", "2110237"}; + rows[1296] = new String[] {"MA", "Santo Amaro do Maranh\u00e3o", "2110278"}; + rows[1297] = new String[] {"MA", "Santo Ant\u00f4nio dos Lopes", "2110302"}; + rows[1298] = new String[] {"MA", "S\u00e3o Benedito do Rio Preto", "2110401"}; + rows[1299] = new String[] {"MA", "S\u00e3o Bento", "2110500"}; + rows[1300] = new String[] {"MA", "S\u00e3o Bernardo", "2110609"}; + rows[1301] = new String[] {"MA", "S\u00e3o Domingos do Azeit\u00e3o", "2110658"}; + rows[1302] = new String[] {"MA", "S\u00e3o Domingos do Maranh\u00e3o", "2110708"}; + rows[1303] = new String[] {"MA", "S\u00e3o F\u00e9lix de Balsas", "2110807"}; + rows[1304] = new String[] {"MA", "S\u00e3o Francisco do Brej\u00e3o", "2110856"}; + rows[1305] = new String[] {"MA", "S\u00e3o Francisco do Maranh\u00e3o", "2110906"}; + rows[1306] = new String[] {"MA", "S\u00e3o Jo\u00e3o Batista", "2111003"}; + rows[1307] = new String[] {"MA", "S\u00e3o Jo\u00e3o do Car\u00fa", "2111029"}; + rows[1308] = new String[] {"MA", "S\u00e3o Jo\u00e3o do Para\u00edso", "2111052"}; + rows[1309] = new String[] {"MA", "S\u00e3o Jo\u00e3o do Soter", "2111078"}; + rows[1310] = new String[] {"MA", "S\u00e3o Jo\u00e3o dos Patos", "2111102"}; + rows[1311] = new String[] {"MA", "S\u00e3o Jos\u00e9 de Ribamar", "2111201"}; + rows[1312] = new String[] {"MA", "S\u00e3o Jos\u00e9 dos Bas\u00edlios", "2111250"}; + rows[1313] = new String[] {"MA", "S\u00e3o Lu\u00eds", "2111300"}; + rows[1314] = new String[] {"MA", "S\u00e3o Lu\u00eds Gonzaga do Maranh\u00e3o", "2111409"}; + rows[1315] = new String[] {"MA", "S\u00e3o Mateus do Maranh\u00e3o", "2111508"}; + rows[1316] = new String[] {"MA", "S\u00e3o Pedro da \u00c1gua Branca", "2111532"}; + rows[1317] = new String[] {"MA", "S\u00e3o Pedro dos Crentes", "2111573"}; + rows[1318] = new String[] {"MA", "S\u00e3o Raimundo das Mangabeiras", "2111607"}; + rows[1319] = new String[] {"MA", "S\u00e3o Raimundo do Doca Bezerra", "2111631"}; + rows[1320] = new String[] {"MA", "S\u00e3o Roberto", "2111672"}; + rows[1321] = new String[] {"MA", "S\u00e3o Vicente Ferrer", "2111706"}; + rows[1322] = new String[] {"MA", "Satubinha", "2111722"}; + rows[1323] = new String[] {"MA", "Senador Alexandre Costa", "2111748"}; + rows[1324] = new String[] {"MA", "Senador La Rocque", "2111763"}; + rows[1325] = new String[] {"MA", "Serrano do Maranh\u00e3o", "2111789"}; + rows[1326] = new String[] {"MA", "S\u00edtio Novo", "2111805"}; + rows[1327] = new String[] {"MA", "Sucupira do Norte", "2111904"}; + rows[1328] = new String[] {"MA", "Sucupira do Riach\u00e3o", "2111953"}; + rows[1329] = new String[] {"MA", "Tasso Fragoso", "2112001"}; + rows[1330] = new String[] {"MA", "Timbiras", "2112100"}; + rows[1331] = new String[] {"MA", "Timon", "2112209"}; + rows[1332] = new String[] {"MA", "Trizidela do Vale", "2112233"}; + rows[1333] = new String[] {"MA", "Tufil\u00e2ndia", "2112274"}; + rows[1334] = new String[] {"MA", "Tuntum", "2112308"}; + rows[1335] = new String[] {"MA", "Turia\u00e7u", "2112407"}; + rows[1336] = new String[] {"MA", "Turil\u00e2ndia", "2112456"}; + rows[1337] = new String[] {"MA", "Tut\u00f3ia", "2112506"}; + rows[1338] = new String[] {"MA", "Urbano Santos", "2112605"}; + rows[1339] = new String[] {"MA", "Vargem Grande", "2112704"}; + rows[1340] = new String[] {"MA", "Viana", "2112803"}; + rows[1341] = new String[] {"MA", "Vila Nova dos Mart\u00edrios", "2112852"}; + rows[1342] = new String[] {"MA", "Vit\u00f3ria do Mearim", "2112902"}; + rows[1343] = new String[] {"MA", "Vitorino Freire", "2113009"}; + rows[1344] = new String[] {"MA", "Z\u00e9 Doca", "2114007"}; + rows[1345] = new String[] {"MT", "Acorizal", "5100102"}; + rows[1346] = new String[] {"MT", "\u00c1gua Boa", "5100201"}; + rows[1347] = new String[] {"MT", "Alta Floresta", "5100250"}; + rows[1348] = new String[] {"MT", "Alto Araguaia", "5100300"}; + rows[1349] = new String[] {"MT", "Alto Boa Vista", "5100359"}; + rows[1350] = new String[] {"MT", "Alto Gar\u00e7as", "5100409"}; + rows[1351] = new String[] {"MT", "Alto Paraguai", "5100508"}; + rows[1352] = new String[] {"MT", "Alto Taquari", "5100607"}; + rows[1353] = new String[] {"MT", "Apiac\u00e1s", "5100805"}; + rows[1354] = new String[] {"MT", "Araguaiana", "5101001"}; + rows[1355] = new String[] {"MT", "Araguainha", "5101209"}; + rows[1356] = new String[] {"MT", "Araputanga", "5101258"}; + rows[1357] = new String[] {"MT", "Aren\u00e1polis", "5101308"}; + rows[1358] = new String[] {"MT", "Aripuan\u00e3", "5101407"}; + rows[1359] = new String[] {"MT", "Bar\u00e3o de Melga\u00e7o", "5101605"}; + rows[1360] = new String[] {"MT", "Barra do Bugres", "5101704"}; + rows[1361] = new String[] {"MT", "Barra do Gar\u00e7as", "5101803"}; + rows[1362] = new String[] {"MT", "Boa Esperan\u00e7a do Norte", "5101837"}; + rows[1363] = new String[] {"MT", "Bom Jesus do Araguaia", "5101852"}; + rows[1364] = new String[] {"MT", "Brasnorte", "5101902"}; + rows[1365] = new String[] {"MT", "C\u00e1ceres", "5102504"}; + rows[1366] = new String[] {"MT", "Campin\u00e1polis", "5102603"}; + rows[1367] = new String[] {"MT", "Campo Novo do Parecis", "5102637"}; + rows[1368] = new String[] {"MT", "Campo Verde", "5102678"}; + rows[1369] = new String[] {"MT", "Campos de J\u00falio", "5102686"}; + rows[1370] = new String[] {"MT", "Canabrava do Norte", "5102694"}; + rows[1371] = new String[] {"MT", "Canarana", "5102702"}; + rows[1372] = new String[] {"MT", "Carlinda", "5102793"}; + rows[1373] = new String[] {"MT", "Castanheira", "5102850"}; + rows[1374] = new String[] {"MT", "Chapada dos Guimar\u00e3es", "5103007"}; + rows[1375] = new String[] {"MT", "Cl\u00e1udia", "5103056"}; + rows[1376] = new String[] {"MT", "Cocalinho", "5103106"}; + rows[1377] = new String[] {"MT", "Col\u00edder", "5103205"}; + rows[1378] = new String[] {"MT", "Colniza", "5103254"}; + rows[1379] = new String[] {"MT", "Comodoro", "5103304"}; + rows[1380] = new String[] {"MT", "Confresa", "5103353"}; + rows[1381] = new String[] {"MT", "Conquista D'Oeste", "5103361"}; + rows[1382] = new String[] {"MT", "Cotrigua\u00e7u", "5103379"}; + rows[1383] = new String[] {"MT", "Cuiab\u00e1", "5103403"}; + rows[1384] = new String[] {"MT", "Curvel\u00e2ndia", "5103437"}; + rows[1385] = new String[] {"MT", "Denise", "5103452"}; + rows[1386] = new String[] {"MT", "Diamantino", "5103502"}; + rows[1387] = new String[] {"MT", "Dom Aquino", "5103601"}; + rows[1388] = new String[] {"MT", "Feliz Natal", "5103700"}; + rows[1389] = new String[] {"MT", "Figueir\u00f3polis D'Oeste", "5103809"}; + rows[1390] = new String[] {"MT", "Ga\u00facha do Norte", "5103858"}; + rows[1391] = new String[] {"MT", "General Carneiro", "5103908"}; + rows[1392] = new String[] {"MT", "Gl\u00f3ria D'Oeste", "5103957"}; + rows[1393] = new String[] {"MT", "Guarant\u00e3 do Norte", "5104104"}; + rows[1394] = new String[] {"MT", "Guiratinga", "5104203"}; + rows[1395] = new String[] {"MT", "Indiava\u00ed", "5104500"}; + rows[1396] = new String[] {"MT", "Ipiranga do Norte", "5104526"}; + rows[1397] = new String[] {"MT", "Itanhang\u00e1", "5104542"}; + rows[1398] = new String[] {"MT", "Ita\u00faba", "5104559"}; + rows[1399] = new String[] {"MT", "Itiquira", "5104609"}; + } + + private static void municipalitiesRows7(String[][] rows) { + rows[1400] = new String[] {"MT", "Jaciara", "5104807"}; + rows[1401] = new String[] {"MT", "Jangada", "5104906"}; + rows[1402] = new String[] {"MT", "Jauru", "5105002"}; + rows[1403] = new String[] {"MT", "Juara", "5105101"}; + rows[1404] = new String[] {"MT", "Ju\u00edna", "5105150"}; + rows[1405] = new String[] {"MT", "Juruena", "5105176"}; + rows[1406] = new String[] {"MT", "Juscimeira", "5105200"}; + rows[1407] = new String[] {"MT", "Lambari D'Oeste", "5105234"}; + rows[1408] = new String[] {"MT", "Lucas do Rio Verde", "5105259"}; + rows[1409] = new String[] {"MT", "Luciara", "5105309"}; + rows[1410] = new String[] {"MT", "Marcel\u00e2ndia", "5105580"}; + rows[1411] = new String[] {"MT", "Matup\u00e1", "5105606"}; + rows[1412] = new String[] {"MT", "Mirassol d'Oeste", "5105622"}; + rows[1413] = new String[] {"MT", "Nobres", "5105903"}; + rows[1414] = new String[] {"MT", "Nortel\u00e2ndia", "5106000"}; + rows[1415] = new String[] {"MT", "Nossa Senhora do Livramento", "5106109"}; + rows[1416] = new String[] {"MT", "Nova Bandeirantes", "5106158"}; + rows[1417] = new String[] {"MT", "Nova Brasil\u00e2ndia", "5106208"}; + rows[1418] = new String[] {"MT", "Nova Cana\u00e3 do Norte", "5106216"}; + rows[1419] = new String[] {"MT", "Nova Guarita", "5108808"}; + rows[1420] = new String[] {"MT", "Nova Lacerda", "5106182"}; + rows[1421] = new String[] {"MT", "Nova Maril\u00e2ndia", "5108857"}; + rows[1422] = new String[] {"MT", "Nova Maring\u00e1", "5108907"}; + rows[1423] = new String[] {"MT", "Nova Monte Verde", "5108956"}; + rows[1424] = new String[] {"MT", "Nova Mutum", "5106224"}; + rows[1425] = new String[] {"MT", "Nova Nazar\u00e9", "5106174"}; + rows[1426] = new String[] {"MT", "Nova Ol\u00edmpia", "5106232"}; + rows[1427] = new String[] {"MT", "Nova Santa Helena", "5106190"}; + rows[1428] = new String[] {"MT", "Nova Ubirat\u00e3", "5106240"}; + rows[1429] = new String[] {"MT", "Nova Xavantina", "5106257"}; + rows[1430] = new String[] {"MT", "Novo Horizonte do Norte", "5106273"}; + rows[1431] = new String[] {"MT", "Novo Mundo", "5106265"}; + rows[1432] = new String[] {"MT", "Novo Santo Ant\u00f4nio", "5106315"}; + rows[1433] = new String[] {"MT", "Novo S\u00e3o Joaquim", "5106281"}; + rows[1434] = new String[] {"MT", "Parana\u00edta", "5106299"}; + rows[1435] = new String[] {"MT", "Paranatinga", "5106307"}; + rows[1436] = new String[] {"MT", "Pedra Preta", "5106372"}; + rows[1437] = new String[] {"MT", "Peixoto de Azevedo", "5106422"}; + rows[1438] = new String[] {"MT", "Planalto da Serra", "5106455"}; + rows[1439] = new String[] {"MT", "Pocon\u00e9", "5106505"}; + rows[1440] = new String[] {"MT", "Pontal do Araguaia", "5106653"}; + rows[1441] = new String[] {"MT", "Ponte Branca", "5106703"}; + rows[1442] = new String[] {"MT", "Pontes e Lacerda", "5106752"}; + rows[1443] = new String[] {"MT", "Porto Alegre do Norte", "5106778"}; + rows[1444] = new String[] {"MT", "Porto dos Ga\u00fachos", "5106802"}; + rows[1445] = new String[] {"MT", "Porto Esperidi\u00e3o", "5106828"}; + rows[1446] = new String[] {"MT", "Porto Estrela", "5106851"}; + rows[1447] = new String[] {"MT", "Poxor\u00e9u", "5107008"}; + rows[1448] = new String[] {"MT", "Primavera do Leste", "5107040"}; + rows[1449] = new String[] {"MT", "Quer\u00eancia", "5107065"}; + rows[1450] = new String[] {"MT", "Reserva do Caba\u00e7al", "5107156"}; + rows[1451] = new String[] {"MT", "Ribeir\u00e3o Cascalheira", "5107180"}; + rows[1452] = new String[] {"MT", "Ribeir\u00e3ozinho", "5107198"}; + rows[1453] = new String[] {"MT", "Rio Branco", "5107206"}; + rows[1454] = new String[] {"MT", "Rondol\u00e2ndia", "5107578"}; + rows[1455] = new String[] {"MT", "Rondon\u00f3polis", "5107602"}; + rows[1456] = new String[] {"MT", "Ros\u00e1rio Oeste", "5107701"}; + rows[1457] = new String[] {"MT", "Salto do C\u00e9u", "5107750"}; + rows[1458] = new String[] {"MT", "Santa Carmem", "5107248"}; + rows[1459] = new String[] {"MT", "Santa Cruz do Xingu", "5107743"}; + rows[1460] = new String[] {"MT", "Santa Rita do Trivelato", "5107768"}; + rows[1461] = new String[] {"MT", "Santa Terezinha", "5107776"}; + rows[1462] = new String[] {"MT", "Santo Afonso", "5107263"}; + rows[1463] = new String[] {"MT", "Santo Ant\u00f4nio de Leverger", "5107800"}; + rows[1464] = new String[] {"MT", "Santo Ant\u00f4nio do Leste", "5107792"}; + rows[1465] = new String[] {"MT", "S\u00e3o F\u00e9lix do Araguaia", "5107859"}; + rows[1466] = new String[] {"MT", "S\u00e3o Jos\u00e9 do Povo", "5107297"}; + rows[1467] = new String[] {"MT", "S\u00e3o Jos\u00e9 do Rio Claro", "5107305"}; + rows[1468] = new String[] {"MT", "S\u00e3o Jos\u00e9 do Xingu", "5107354"}; + rows[1469] = new String[] {"MT", "S\u00e3o Jos\u00e9 dos Quatro Marcos", "5107107"}; + rows[1470] = new String[] {"MT", "S\u00e3o Pedro da Cipa", "5107404"}; + rows[1471] = new String[] {"MT", "Sapezal", "5107875"}; + rows[1472] = new String[] {"MT", "Serra Nova Dourada", "5107883"}; + rows[1473] = new String[] {"MT", "Sinop", "5107909"}; + rows[1474] = new String[] {"MT", "Sorriso", "5107925"}; + rows[1475] = new String[] {"MT", "Tabapor\u00e3", "5107941"}; + rows[1476] = new String[] {"MT", "Tangar\u00e1 da Serra", "5107958"}; + rows[1477] = new String[] {"MT", "Tapurah", "5108006"}; + rows[1478] = new String[] {"MT", "Terra Nova do Norte", "5108055"}; + rows[1479] = new String[] {"MT", "Tesouro", "5108105"}; + rows[1480] = new String[] {"MT", "Torixor\u00e9u", "5108204"}; + rows[1481] = new String[] {"MT", "Uni\u00e3o do Sul", "5108303"}; + rows[1482] = new String[] {"MT", "Vale de S\u00e3o Domingos", "5108352"}; + rows[1483] = new String[] {"MT", "V\u00e1rzea Grande", "5108402"}; + rows[1484] = new String[] {"MT", "Vera", "5108501"}; + rows[1485] = new String[] {"MT", "Vila Bela da Sant\u00edssima Trindade", "5105507"}; + rows[1486] = new String[] {"MT", "Vila Rica", "5108600"}; + rows[1487] = new String[] {"MS", "\u00c1gua Clara", "5000203"}; + rows[1488] = new String[] {"MS", "Alcin\u00f3polis", "5000252"}; + rows[1489] = new String[] {"MS", "Amambai", "5000609"}; + rows[1490] = new String[] {"MS", "Anast\u00e1cio", "5000708"}; + rows[1491] = new String[] {"MS", "Anauril\u00e2ndia", "5000807"}; + rows[1492] = new String[] {"MS", "Ang\u00e9lica", "5000856"}; + rows[1493] = new String[] {"MS", "Ant\u00f4nio Jo\u00e3o", "5000906"}; + rows[1494] = new String[] {"MS", "Aparecida do Taboado", "5001003"}; + rows[1495] = new String[] {"MS", "Aquidauana", "5001102"}; + rows[1496] = new String[] {"MS", "Aral Moreira", "5001243"}; + rows[1497] = new String[] {"MS", "Bandeirantes", "5001508"}; + rows[1498] = new String[] {"MS", "Bataguassu", "5001904"}; + rows[1499] = new String[] {"MS", "Bataypor\u00e3", "5002001"}; + rows[1500] = new String[] {"MS", "Bela Vista", "5002100"}; + rows[1501] = new String[] {"MS", "Bodoquena", "5002159"}; + rows[1502] = new String[] {"MS", "Bonito", "5002209"}; + rows[1503] = new String[] {"MS", "Brasil\u00e2ndia", "5002308"}; + rows[1504] = new String[] {"MS", "Caarap\u00f3", "5002407"}; + rows[1505] = new String[] {"MS", "Camapu\u00e3", "5002605"}; + rows[1506] = new String[] {"MS", "Campo Grande", "5002704"}; + rows[1507] = new String[] {"MS", "Caracol", "5002803"}; + rows[1508] = new String[] {"MS", "Cassil\u00e2ndia", "5002902"}; + rows[1509] = new String[] {"MS", "Chapad\u00e3o do Sul", "5002951"}; + rows[1510] = new String[] {"MS", "Corguinho", "5003108"}; + rows[1511] = new String[] {"MS", "Coronel Sapucaia", "5003157"}; + rows[1512] = new String[] {"MS", "Corumb\u00e1", "5003207"}; + rows[1513] = new String[] {"MS", "Costa Rica", "5003256"}; + rows[1514] = new String[] {"MS", "Coxim", "5003306"}; + rows[1515] = new String[] {"MS", "Deod\u00e1polis", "5003454"}; + rows[1516] = new String[] {"MS", "Dois Irm\u00e3os do Buriti", "5003488"}; + rows[1517] = new String[] {"MS", "Douradina", "5003504"}; + rows[1518] = new String[] {"MS", "Dourados", "5003702"}; + rows[1519] = new String[] {"MS", "Eldorado", "5003751"}; + rows[1520] = new String[] {"MS", "F\u00e1tima do Sul", "5003801"}; + rows[1521] = new String[] {"MS", "Figueir\u00e3o", "5003900"}; + rows[1522] = new String[] {"MS", "Gl\u00f3ria de Dourados", "5004007"}; + rows[1523] = new String[] {"MS", "Guia Lopes da Laguna", "5004106"}; + rows[1524] = new String[] {"MS", "Iguatemi", "5004304"}; + rows[1525] = new String[] {"MS", "Inoc\u00eancia", "5004403"}; + rows[1526] = new String[] {"MS", "Itapor\u00e3", "5004502"}; + rows[1527] = new String[] {"MS", "Itaquira\u00ed", "5004601"}; + rows[1528] = new String[] {"MS", "Ivinhema", "5004700"}; + rows[1529] = new String[] {"MS", "Japor\u00e3", "5004809"}; + rows[1530] = new String[] {"MS", "Jaraguari", "5004908"}; + rows[1531] = new String[] {"MS", "Jardim", "5005004"}; + rows[1532] = new String[] {"MS", "Jate\u00ed", "5005103"}; + rows[1533] = new String[] {"MS", "Juti", "5005152"}; + rows[1534] = new String[] {"MS", "Lad\u00e1rio", "5005202"}; + rows[1535] = new String[] {"MS", "Laguna Carap\u00e3", "5005251"}; + rows[1536] = new String[] {"MS", "Maracaju", "5005400"}; + rows[1537] = new String[] {"MS", "Miranda", "5005608"}; + rows[1538] = new String[] {"MS", "Mundo Novo", "5005681"}; + rows[1539] = new String[] {"MS", "Navira\u00ed", "5005707"}; + rows[1540] = new String[] {"MS", "Nioaque", "5005806"}; + rows[1541] = new String[] {"MS", "Nova Alvorada do Sul", "5006002"}; + rows[1542] = new String[] {"MS", "Nova Andradina", "5006200"}; + rows[1543] = new String[] {"MS", "Novo Horizonte do Sul", "5006259"}; + rows[1544] = new String[] {"MS", "Para\u00edso das \u00c1guas", "5006275"}; + rows[1545] = new String[] {"MS", "Parana\u00edba", "5006309"}; + rows[1546] = new String[] {"MS", "Paranhos", "5006358"}; + rows[1547] = new String[] {"MS", "Pedro Gomes", "5006408"}; + rows[1548] = new String[] {"MS", "Ponta Por\u00e3", "5006606"}; + rows[1549] = new String[] {"MS", "Porto Murtinho", "5006903"}; + rows[1550] = new String[] {"MS", "Ribas do Rio Pardo", "5007109"}; + rows[1551] = new String[] {"MS", "Rio Brilhante", "5007208"}; + rows[1552] = new String[] {"MS", "Rio Negro", "5007307"}; + rows[1553] = new String[] {"MS", "Rio Verde de Mato Grosso", "5007406"}; + rows[1554] = new String[] {"MS", "Rochedo", "5007505"}; + rows[1555] = new String[] {"MS", "Santa Rita do Pardo", "5007554"}; + rows[1556] = new String[] {"MS", "S\u00e3o Gabriel do Oeste", "5007695"}; + rows[1557] = new String[] {"MS", "Selv\u00edria", "5007802"}; + rows[1558] = new String[] {"MS", "Sete Quedas", "5007703"}; + rows[1559] = new String[] {"MS", "Sidrol\u00e2ndia", "5007901"}; + rows[1560] = new String[] {"MS", "Sonora", "5007935"}; + rows[1561] = new String[] {"MS", "Tacuru", "5007950"}; + rows[1562] = new String[] {"MS", "Taquarussu", "5007976"}; + rows[1563] = new String[] {"MS", "Terenos", "5008008"}; + rows[1564] = new String[] {"MS", "Tr\u00eas Lagoas", "5008305"}; + rows[1565] = new String[] {"MS", "Vicentina", "5008404"}; + rows[1566] = new String[] {"MG", "Abadia dos Dourados", "3100104"}; + rows[1567] = new String[] {"MG", "Abaet\u00e9", "3100203"}; + rows[1568] = new String[] {"MG", "Abre Campo", "3100302"}; + rows[1569] = new String[] {"MG", "Acaiaca", "3100401"}; + rows[1570] = new String[] {"MG", "A\u00e7ucena", "3100500"}; + rows[1571] = new String[] {"MG", "\u00c1gua Boa", "3100609"}; + rows[1572] = new String[] {"MG", "\u00c1gua Comprida", "3100708"}; + rows[1573] = new String[] {"MG", "Aguanil", "3100807"}; + rows[1574] = new String[] {"MG", "\u00c1guas Formosas", "3100906"}; + rows[1575] = new String[] {"MG", "\u00c1guas Vermelhas", "3101003"}; + rows[1576] = new String[] {"MG", "Aimor\u00e9s", "3101102"}; + rows[1577] = new String[] {"MG", "Aiuruoca", "3101201"}; + rows[1578] = new String[] {"MG", "Alagoa", "3101300"}; + rows[1579] = new String[] {"MG", "Albertina", "3101409"}; + rows[1580] = new String[] {"MG", "Al\u00e9m Para\u00edba", "3101508"}; + rows[1581] = new String[] {"MG", "Alfenas", "3101607"}; + rows[1582] = new String[] {"MG", "Alfredo Vasconcelos", "3101631"}; + rows[1583] = new String[] {"MG", "Almenara", "3101706"}; + rows[1584] = new String[] {"MG", "Alpercata", "3101805"}; + rows[1585] = new String[] {"MG", "Alpin\u00f3polis", "3101904"}; + rows[1586] = new String[] {"MG", "Alterosa", "3102001"}; + rows[1587] = new String[] {"MG", "Alto Capara\u00f3", "3102050"}; + rows[1588] = new String[] {"MG", "Alto Jequitib\u00e1", "3153509"}; + rows[1589] = new String[] {"MG", "Alto Rio Doce", "3102100"}; + rows[1590] = new String[] {"MG", "Alvarenga", "3102209"}; + rows[1591] = new String[] {"MG", "Alvin\u00f3polis", "3102308"}; + rows[1592] = new String[] {"MG", "Alvorada de Minas", "3102407"}; + rows[1593] = new String[] {"MG", "Amparo do Serra", "3102506"}; + rows[1594] = new String[] {"MG", "Andradas", "3102605"}; + rows[1595] = new String[] {"MG", "Andrel\u00e2ndia", "3102803"}; + rows[1596] = new String[] {"MG", "Angel\u00e2ndia", "3102852"}; + rows[1597] = new String[] {"MG", "Ant\u00f4nio Carlos", "3102902"}; + rows[1598] = new String[] {"MG", "Ant\u00f4nio Dias", "3103009"}; + rows[1599] = new String[] {"MG", "Ant\u00f4nio Prado de Minas", "3103108"}; + } + + private static void municipalitiesRows8(String[][] rows) { + rows[1600] = new String[] {"MG", "Ara\u00e7a\u00ed", "3103207"}; + rows[1601] = new String[] {"MG", "Aracitaba", "3103306"}; + rows[1602] = new String[] {"MG", "Ara\u00e7ua\u00ed", "3103405"}; + rows[1603] = new String[] {"MG", "Araguari", "3103504"}; + rows[1604] = new String[] {"MG", "Arantina", "3103603"}; + rows[1605] = new String[] {"MG", "Araponga", "3103702"}; + rows[1606] = new String[] {"MG", "Arapor\u00e3", "3103751"}; + rows[1607] = new String[] {"MG", "Arapu\u00e1", "3103801"}; + rows[1608] = new String[] {"MG", "Ara\u00fajos", "3103900"}; + rows[1609] = new String[] {"MG", "Arax\u00e1", "3104007"}; + rows[1610] = new String[] {"MG", "Arceburgo", "3104106"}; + rows[1611] = new String[] {"MG", "Arcos", "3104205"}; + rows[1612] = new String[] {"MG", "Areado", "3104304"}; + rows[1613] = new String[] {"MG", "Argirita", "3104403"}; + rows[1614] = new String[] {"MG", "Aricanduva", "3104452"}; + rows[1615] = new String[] {"MG", "Arinos", "3104502"}; + rows[1616] = new String[] {"MG", "Astolfo Dutra", "3104601"}; + rows[1617] = new String[] {"MG", "Atal\u00e9ia", "3104700"}; + rows[1618] = new String[] {"MG", "Augusto de Lima", "3104809"}; + rows[1619] = new String[] {"MG", "Baependi", "3104908"}; + rows[1620] = new String[] {"MG", "Baldim", "3105004"}; + rows[1621] = new String[] {"MG", "Bambu\u00ed", "3105103"}; + rows[1622] = new String[] {"MG", "Bandeira", "3105202"}; + rows[1623] = new String[] {"MG", "Bandeira do Sul", "3105301"}; + rows[1624] = new String[] {"MG", "Bar\u00e3o de Cocais", "3105400"}; + rows[1625] = new String[] {"MG", "Bar\u00e3o do Monte Alto", "3105509"}; + rows[1626] = new String[] {"MG", "Barbacena", "3105608"}; + rows[1627] = new String[] {"MG", "Barra Longa", "3105707"}; + rows[1628] = new String[] {"MG", "Barroso", "3105905"}; + rows[1629] = new String[] {"MG", "Bela Vista de Minas", "3106002"}; + rows[1630] = new String[] {"MG", "Belmiro Braga", "3106101"}; + rows[1631] = new String[] {"MG", "Belo Horizonte", "3106200"}; + rows[1632] = new String[] {"MG", "Belo Oriente", "3106309"}; + rows[1633] = new String[] {"MG", "Belo Vale", "3106408"}; + rows[1634] = new String[] {"MG", "Berilo", "3106507"}; + rows[1635] = new String[] {"MG", "Berizal", "3106655"}; + rows[1636] = new String[] {"MG", "Bert\u00f3polis", "3106606"}; + rows[1637] = new String[] {"MG", "Betim", "3106705"}; + rows[1638] = new String[] {"MG", "Bias Fortes", "3106804"}; + rows[1639] = new String[] {"MG", "Bicas", "3106903"}; + rows[1640] = new String[] {"MG", "Biquinhas", "3107000"}; + rows[1641] = new String[] {"MG", "Boa Esperan\u00e7a", "3107109"}; + rows[1642] = new String[] {"MG", "Bocaina de Minas", "3107208"}; + rows[1643] = new String[] {"MG", "Bocai\u00fava", "3107307"}; + rows[1644] = new String[] {"MG", "Bom Despacho", "3107406"}; + rows[1645] = new String[] {"MG", "Bom Jardim de Minas", "3107505"}; + rows[1646] = new String[] {"MG", "Bom Jesus da Penha", "3107604"}; + rows[1647] = new String[] {"MG", "Bom Jesus do Amparo", "3107703"}; + rows[1648] = new String[] {"MG", "Bom Jesus do Galho", "3107802"}; + rows[1649] = new String[] {"MG", "Bom Repouso", "3107901"}; + rows[1650] = new String[] {"MG", "Bom Sucesso", "3108008"}; + rows[1651] = new String[] {"MG", "Bonfim", "3108107"}; + rows[1652] = new String[] {"MG", "Bonfin\u00f3polis de Minas", "3108206"}; + rows[1653] = new String[] {"MG", "Bonito de Minas", "3108255"}; + rows[1654] = new String[] {"MG", "Borda da Mata", "3108305"}; + rows[1655] = new String[] {"MG", "Botelhos", "3108404"}; + rows[1656] = new String[] {"MG", "Botumirim", "3108503"}; + rows[1657] = new String[] {"MG", "Br\u00e1s Pires", "3108701"}; + rows[1658] = new String[] {"MG", "Brasil\u00e2ndia de Minas", "3108552"}; + rows[1659] = new String[] {"MG", "Bras\u00edlia de Minas", "3108602"}; + rows[1660] = new String[] {"MG", "Bra\u00fanas", "3108800"}; + rows[1661] = new String[] {"MG", "Braz\u00f3polis", "3108909"}; + rows[1662] = new String[] {"MG", "Brumadinho", "3109006"}; + rows[1663] = new String[] {"MG", "Bueno Brand\u00e3o", "3109105"}; + rows[1664] = new String[] {"MG", "Buen\u00f3polis", "3109204"}; + rows[1665] = new String[] {"MG", "Bugre", "3109253"}; + rows[1666] = new String[] {"MG", "Buritis", "3109303"}; + rows[1667] = new String[] {"MG", "Buritizeiro", "3109402"}; + rows[1668] = new String[] {"MG", "Cabeceira Grande", "3109451"}; + rows[1669] = new String[] {"MG", "Cabo Verde", "3109501"}; + rows[1670] = new String[] {"MG", "Cachoeira da Prata", "3109600"}; + rows[1671] = new String[] {"MG", "Cachoeira de Minas", "3109709"}; + rows[1672] = new String[] {"MG", "Cachoeira de Paje\u00fa", "3102704"}; + rows[1673] = new String[] {"MG", "Cachoeira Dourada", "3109808"}; + rows[1674] = new String[] {"MG", "Caetan\u00f3polis", "3109907"}; + rows[1675] = new String[] {"MG", "Caet\u00e9", "3110004"}; + rows[1676] = new String[] {"MG", "Caiana", "3110103"}; + rows[1677] = new String[] {"MG", "Cajuri", "3110202"}; + rows[1678] = new String[] {"MG", "Caldas", "3110301"}; + rows[1679] = new String[] {"MG", "Camacho", "3110400"}; + rows[1680] = new String[] {"MG", "Camanducaia", "3110509"}; + rows[1681] = new String[] {"MG", "Cambu\u00ed", "3110608"}; + rows[1682] = new String[] {"MG", "Cambuquira", "3110707"}; + rows[1683] = new String[] {"MG", "Campan\u00e1rio", "3110806"}; + rows[1684] = new String[] {"MG", "Campanha", "3110905"}; + rows[1685] = new String[] {"MG", "Campestre", "3111002"}; + rows[1686] = new String[] {"MG", "Campina Verde", "3111101"}; + rows[1687] = new String[] {"MG", "Campo Azul", "3111150"}; + rows[1688] = new String[] {"MG", "Campo Belo", "3111200"}; + rows[1689] = new String[] {"MG", "Campo do Meio", "3111309"}; + rows[1690] = new String[] {"MG", "Campo Florido", "3111408"}; + rows[1691] = new String[] {"MG", "Campos Altos", "3111507"}; + rows[1692] = new String[] {"MG", "Campos Gerais", "3111606"}; + rows[1693] = new String[] {"MG", "Cana Verde", "3111903"}; + rows[1694] = new String[] {"MG", "Cana\u00e3", "3111705"}; + rows[1695] = new String[] {"MG", "Can\u00e1polis", "3111804"}; + rows[1696] = new String[] {"MG", "Candeias", "3112000"}; + rows[1697] = new String[] {"MG", "Cantagalo", "3112059"}; + rows[1698] = new String[] {"MG", "Capara\u00f3", "3112109"}; + rows[1699] = new String[] {"MG", "Capela Nova", "3112208"}; + rows[1700] = new String[] {"MG", "Capelinha", "3112307"}; + rows[1701] = new String[] {"MG", "Capetinga", "3112406"}; + rows[1702] = new String[] {"MG", "Capim Branco", "3112505"}; + rows[1703] = new String[] {"MG", "Capin\u00f3polis", "3112604"}; + rows[1704] = new String[] {"MG", "Capit\u00e3o Andrade", "3112653"}; + rows[1705] = new String[] {"MG", "Capit\u00e3o En\u00e9as", "3112703"}; + rows[1706] = new String[] {"MG", "Capit\u00f3lio", "3112802"}; + rows[1707] = new String[] {"MG", "Caputira", "3112901"}; + rows[1708] = new String[] {"MG", "Cara\u00ed", "3113008"}; + rows[1709] = new String[] {"MG", "Carana\u00edba", "3113107"}; + rows[1710] = new String[] {"MG", "Caranda\u00ed", "3113206"}; + rows[1711] = new String[] {"MG", "Carangola", "3113305"}; + rows[1712] = new String[] {"MG", "Caratinga", "3113404"}; + rows[1713] = new String[] {"MG", "Carbonita", "3113503"}; + rows[1714] = new String[] {"MG", "Carea\u00e7u", "3113602"}; + rows[1715] = new String[] {"MG", "Carlos Chagas", "3113701"}; + rows[1716] = new String[] {"MG", "Carm\u00e9sia", "3113800"}; + rows[1717] = new String[] {"MG", "Carmo da Cachoeira", "3113909"}; + rows[1718] = new String[] {"MG", "Carmo da Mata", "3114006"}; + rows[1719] = new String[] {"MG", "Carmo de Minas", "3114105"}; + rows[1720] = new String[] {"MG", "Carmo do Cajuru", "3114204"}; + rows[1721] = new String[] {"MG", "Carmo do Parana\u00edba", "3114303"}; + rows[1722] = new String[] {"MG", "Carmo do Rio Claro", "3114402"}; + rows[1723] = new String[] {"MG", "Carm\u00f3polis de Minas", "3114501"}; + rows[1724] = new String[] {"MG", "Carneirinho", "3114550"}; + rows[1725] = new String[] {"MG", "Carrancas", "3114600"}; + rows[1726] = new String[] {"MG", "Carvalh\u00f3polis", "3114709"}; + rows[1727] = new String[] {"MG", "Carvalhos", "3114808"}; + rows[1728] = new String[] {"MG", "Casa Grande", "3114907"}; + rows[1729] = new String[] {"MG", "Cascalho Rico", "3115003"}; + rows[1730] = new String[] {"MG", "C\u00e1ssia", "3115102"}; + rows[1731] = new String[] {"MG", "Cataguases", "3115300"}; + rows[1732] = new String[] {"MG", "Catas Altas", "3115359"}; + rows[1733] = new String[] {"MG", "Catas Altas da Noruega", "3115409"}; + rows[1734] = new String[] {"MG", "Catuji", "3115458"}; + rows[1735] = new String[] {"MG", "Catuti", "3115474"}; + rows[1736] = new String[] {"MG", "Caxambu", "3115508"}; + rows[1737] = new String[] {"MG", "Cedro do Abaet\u00e9", "3115607"}; + rows[1738] = new String[] {"MG", "Central de Minas", "3115706"}; + rows[1739] = new String[] {"MG", "Centralina", "3115805"}; + rows[1740] = new String[] {"MG", "Ch\u00e1cara", "3115904"}; + rows[1741] = new String[] {"MG", "Chal\u00e9", "3116001"}; + rows[1742] = new String[] {"MG", "Chapada do Norte", "3116100"}; + rows[1743] = new String[] {"MG", "Chapada Ga\u00facha", "3116159"}; + rows[1744] = new String[] {"MG", "Chiador", "3116209"}; + rows[1745] = new String[] {"MG", "Cipot\u00e2nea", "3116308"}; + rows[1746] = new String[] {"MG", "Claraval", "3116407"}; + rows[1747] = new String[] {"MG", "Claro dos Po\u00e7\u00f5es", "3116506"}; + rows[1748] = new String[] {"MG", "Cl\u00e1udio", "3116605"}; + rows[1749] = new String[] {"MG", "Coimbra", "3116704"}; + rows[1750] = new String[] {"MG", "Coluna", "3116803"}; + rows[1751] = new String[] {"MG", "Comendador Gomes", "3116902"}; + rows[1752] = new String[] {"MG", "Comercinho", "3117009"}; + rows[1753] = new String[] {"MG", "Concei\u00e7\u00e3o da Aparecida", "3117108"}; + rows[1754] = new String[] {"MG", "Concei\u00e7\u00e3o da Barra de Minas", "3115201"}; + rows[1755] = new String[] {"MG", "Concei\u00e7\u00e3o das Alagoas", "3117306"}; + rows[1756] = new String[] {"MG", "Concei\u00e7\u00e3o das Pedras", "3117207"}; + rows[1757] = new String[] {"MG", "Concei\u00e7\u00e3o de Ipanema", "3117405"}; + rows[1758] = new String[] {"MG", "Concei\u00e7\u00e3o do Mato Dentro", "3117504"}; + rows[1759] = new String[] {"MG", "Concei\u00e7\u00e3o do Par\u00e1", "3117603"}; + rows[1760] = new String[] {"MG", "Concei\u00e7\u00e3o do Rio Verde", "3117702"}; + rows[1761] = new String[] {"MG", "Concei\u00e7\u00e3o dos Ouros", "3117801"}; + rows[1762] = new String[] {"MG", "C\u00f4nego Marinho", "3117836"}; + rows[1763] = new String[] {"MG", "Confins", "3117876"}; + rows[1764] = new String[] {"MG", "Congonhal", "3117900"}; + rows[1765] = new String[] {"MG", "Congonhas", "3118007"}; + rows[1766] = new String[] {"MG", "Congonhas do Norte", "3118106"}; + rows[1767] = new String[] {"MG", "Conquista", "3118205"}; + rows[1768] = new String[] {"MG", "Conselheiro Lafaiete", "3118304"}; + rows[1769] = new String[] {"MG", "Conselheiro Pena", "3118403"}; + rows[1770] = new String[] {"MG", "Consola\u00e7\u00e3o", "3118502"}; + rows[1771] = new String[] {"MG", "Contagem", "3118601"}; + rows[1772] = new String[] {"MG", "Coqueiral", "3118700"}; + rows[1773] = new String[] {"MG", "Cora\u00e7\u00e3o de Jesus", "3118809"}; + rows[1774] = new String[] {"MG", "Cordisburgo", "3118908"}; + rows[1775] = new String[] {"MG", "Cordisl\u00e2ndia", "3119005"}; + rows[1776] = new String[] {"MG", "Corinto", "3119104"}; + rows[1777] = new String[] {"MG", "Coroaci", "3119203"}; + rows[1778] = new String[] {"MG", "Coromandel", "3119302"}; + rows[1779] = new String[] {"MG", "Coronel Fabriciano", "3119401"}; + rows[1780] = new String[] {"MG", "Coronel Murta", "3119500"}; + rows[1781] = new String[] {"MG", "Coronel Pacheco", "3119609"}; + rows[1782] = new String[] {"MG", "Coronel Xavier Chaves", "3119708"}; + rows[1783] = new String[] {"MG", "C\u00f3rrego Danta", "3119807"}; + rows[1784] = new String[] {"MG", "C\u00f3rrego do Bom Jesus", "3119906"}; + rows[1785] = new String[] {"MG", "C\u00f3rrego Fundo", "3119955"}; + rows[1786] = new String[] {"MG", "C\u00f3rrego Novo", "3120003"}; + rows[1787] = new String[] {"MG", "Couto de Magalh\u00e3es de Minas", "3120102"}; + rows[1788] = new String[] {"MG", "Cris\u00f3lita", "3120151"}; + rows[1789] = new String[] {"MG", "Cristais", "3120201"}; + rows[1790] = new String[] {"MG", "Crist\u00e1lia", "3120300"}; + rows[1791] = new String[] {"MG", "Cristiano Otoni", "3120409"}; + rows[1792] = new String[] {"MG", "Cristina", "3120508"}; + rows[1793] = new String[] {"MG", "Crucil\u00e2ndia", "3120607"}; + rows[1794] = new String[] {"MG", "Cruzeiro da Fortaleza", "3120706"}; + rows[1795] = new String[] {"MG", "Cruz\u00edlia", "3120805"}; + rows[1796] = new String[] {"MG", "Cuparaque", "3120839"}; + rows[1797] = new String[] {"MG", "Curral de Dentro", "3120870"}; + rows[1798] = new String[] {"MG", "Curvelo", "3120904"}; + rows[1799] = new String[] {"MG", "Datas", "3121001"}; + } + + private static void municipalitiesRows9(String[][] rows) { + rows[1800] = new String[] {"MG", "Delfim Moreira", "3121100"}; + rows[1801] = new String[] {"MG", "Delfin\u00f3polis", "3121209"}; + rows[1802] = new String[] {"MG", "Delta", "3121258"}; + rows[1803] = new String[] {"MG", "Descoberto", "3121308"}; + rows[1804] = new String[] {"MG", "Desterro de Entre Rios", "3121407"}; + rows[1805] = new String[] {"MG", "Desterro do Melo", "3121506"}; + rows[1806] = new String[] {"MG", "Diamantina", "3121605"}; + rows[1807] = new String[] {"MG", "Diogo de Vasconcelos", "3121704"}; + rows[1808] = new String[] {"MG", "Dion\u00edsio", "3121803"}; + rows[1809] = new String[] {"MG", "Divin\u00e9sia", "3121902"}; + rows[1810] = new String[] {"MG", "Divino", "3122009"}; + rows[1811] = new String[] {"MG", "Divino das Laranjeiras", "3122108"}; + rows[1812] = new String[] {"MG", "Divinol\u00e2ndia de Minas", "3122207"}; + rows[1813] = new String[] {"MG", "Divin\u00f3polis", "3122306"}; + rows[1814] = new String[] {"MG", "Divisa Alegre", "3122355"}; + rows[1815] = new String[] {"MG", "Divisa Nova", "3122405"}; + rows[1816] = new String[] {"MG", "Divis\u00f3polis", "3122454"}; + rows[1817] = new String[] {"MG", "Dom Bosco", "3122470"}; + rows[1818] = new String[] {"MG", "Dom Cavati", "3122504"}; + rows[1819] = new String[] {"MG", "Dom Joaquim", "3122603"}; + rows[1820] = new String[] {"MG", "Dom Silv\u00e9rio", "3122702"}; + rows[1821] = new String[] {"MG", "Dom Vi\u00e7oso", "3122801"}; + rows[1822] = new String[] {"MG", "Dona Euz\u00e9bia", "3122900"}; + rows[1823] = new String[] {"MG", "Dores de Campos", "3123007"}; + rows[1824] = new String[] {"MG", "Dores de Guanh\u00e3es", "3123106"}; + rows[1825] = new String[] {"MG", "Dores do Indai\u00e1", "3123205"}; + rows[1826] = new String[] {"MG", "Dores do Turvo", "3123304"}; + rows[1827] = new String[] {"MG", "Dores\u00f3polis", "3123403"}; + rows[1828] = new String[] {"MG", "Douradoquara", "3123502"}; + rows[1829] = new String[] {"MG", "Durand\u00e9", "3123528"}; + rows[1830] = new String[] {"MG", "El\u00f3i Mendes", "3123601"}; + rows[1831] = new String[] {"MG", "Engenheiro Caldas", "3123700"}; + rows[1832] = new String[] {"MG", "Engenheiro Navarro", "3123809"}; + rows[1833] = new String[] {"MG", "Entre Folhas", "3123858"}; + rows[1834] = new String[] {"MG", "Entre Rios de Minas", "3123908"}; + rows[1835] = new String[] {"MG", "Erv\u00e1lia", "3124005"}; + rows[1836] = new String[] {"MG", "Esmeraldas", "3124104"}; + rows[1837] = new String[] {"MG", "Espera Feliz", "3124203"}; + rows[1838] = new String[] {"MG", "Espinosa", "3124302"}; + rows[1839] = new String[] {"MG", "Esp\u00edrito Santo do Dourado", "3124401"}; + rows[1840] = new String[] {"MG", "Estiva", "3124500"}; + rows[1841] = new String[] {"MG", "Estrela Dalva", "3124609"}; + rows[1842] = new String[] {"MG", "Estrela do Indai\u00e1", "3124708"}; + rows[1843] = new String[] {"MG", "Estrela do Sul", "3124807"}; + rows[1844] = new String[] {"MG", "Eugen\u00f3polis", "3124906"}; + rows[1845] = new String[] {"MG", "Ewbank da C\u00e2mara", "3125002"}; + rows[1846] = new String[] {"MG", "Extrema", "3125101"}; + rows[1847] = new String[] {"MG", "Fama", "3125200"}; + rows[1848] = new String[] {"MG", "Faria Lemos", "3125309"}; + rows[1849] = new String[] {"MG", "Fel\u00edcio dos Santos", "3125408"}; + rows[1850] = new String[] {"MG", "Felisburgo", "3125606"}; + rows[1851] = new String[] {"MG", "Felixl\u00e2ndia", "3125705"}; + rows[1852] = new String[] {"MG", "Fernandes Tourinho", "3125804"}; + rows[1853] = new String[] {"MG", "Ferros", "3125903"}; + rows[1854] = new String[] {"MG", "Fervedouro", "3125952"}; + rows[1855] = new String[] {"MG", "Florestal", "3126000"}; + rows[1856] = new String[] {"MG", "Formiga", "3126109"}; + rows[1857] = new String[] {"MG", "Formoso", "3126208"}; + rows[1858] = new String[] {"MG", "Fortaleza de Minas", "3126307"}; + rows[1859] = new String[] {"MG", "Fortuna de Minas", "3126406"}; + rows[1860] = new String[] {"MG", "Francisco Badar\u00f3", "3126505"}; + rows[1861] = new String[] {"MG", "Francisco Dumont", "3126604"}; + rows[1862] = new String[] {"MG", "Francisco S\u00e1", "3126703"}; + rows[1863] = new String[] {"MG", "Francisc\u00f3polis", "3126752"}; + rows[1864] = new String[] {"MG", "Frei Gaspar", "3126802"}; + rows[1865] = new String[] {"MG", "Frei Inoc\u00eancio", "3126901"}; + rows[1866] = new String[] {"MG", "Frei Lagonegro", "3126950"}; + rows[1867] = new String[] {"MG", "Fronteira", "3127008"}; + rows[1868] = new String[] {"MG", "Fronteira dos Vales", "3127057"}; + rows[1869] = new String[] {"MG", "Fruta de Leite", "3127073"}; + rows[1870] = new String[] {"MG", "Frutal", "3127107"}; + rows[1871] = new String[] {"MG", "Funil\u00e2ndia", "3127206"}; + rows[1872] = new String[] {"MG", "Galil\u00e9ia", "3127305"}; + rows[1873] = new String[] {"MG", "Gameleiras", "3127339"}; + rows[1874] = new String[] {"MG", "Glaucil\u00e2ndia", "3127354"}; + rows[1875] = new String[] {"MG", "Goiabeira", "3127370"}; + rows[1876] = new String[] {"MG", "Goian\u00e1", "3127388"}; + rows[1877] = new String[] {"MG", "Gon\u00e7alves", "3127404"}; + rows[1878] = new String[] {"MG", "Gonzaga", "3127503"}; + rows[1879] = new String[] {"MG", "Gouveia", "3127602"}; + rows[1880] = new String[] {"MG", "Governador Valadares", "3127701"}; + rows[1881] = new String[] {"MG", "Gr\u00e3o Mogol", "3127800"}; + rows[1882] = new String[] {"MG", "Grupiara", "3127909"}; + rows[1883] = new String[] {"MG", "Guanh\u00e3es", "3128006"}; + rows[1884] = new String[] {"MG", "Guap\u00e9", "3128105"}; + rows[1885] = new String[] {"MG", "Guaraciaba", "3128204"}; + rows[1886] = new String[] {"MG", "Guaraciama", "3128253"}; + rows[1887] = new String[] {"MG", "Guaran\u00e9sia", "3128303"}; + rows[1888] = new String[] {"MG", "Guarani", "3128402"}; + rows[1889] = new String[] {"MG", "Guarar\u00e1", "3128501"}; + rows[1890] = new String[] {"MG", "Guarda-Mor", "3128600"}; + rows[1891] = new String[] {"MG", "Guaxup\u00e9", "3128709"}; + rows[1892] = new String[] {"MG", "Guidoval", "3128808"}; + rows[1893] = new String[] {"MG", "Guimar\u00e2nia", "3128907"}; + rows[1894] = new String[] {"MG", "Guiricema", "3129004"}; + rows[1895] = new String[] {"MG", "Gurinhat\u00e3", "3129103"}; + rows[1896] = new String[] {"MG", "Heliodora", "3129202"}; + rows[1897] = new String[] {"MG", "Iapu", "3129301"}; + rows[1898] = new String[] {"MG", "Ibertioga", "3129400"}; + rows[1899] = new String[] {"MG", "Ibi\u00e1", "3129509"}; + rows[1900] = new String[] {"MG", "Ibia\u00ed", "3129608"}; + rows[1901] = new String[] {"MG", "Ibiracatu", "3129657"}; + rows[1902] = new String[] {"MG", "Ibiraci", "3129707"}; + rows[1903] = new String[] {"MG", "Ibirit\u00e9", "3129806"}; + rows[1904] = new String[] {"MG", "Ibiti\u00fara de Minas", "3129905"}; + rows[1905] = new String[] {"MG", "Ibituruna", "3130002"}; + rows[1906] = new String[] {"MG", "Icara\u00ed de Minas", "3130051"}; + rows[1907] = new String[] {"MG", "Igarap\u00e9", "3130101"}; + rows[1908] = new String[] {"MG", "Igaratinga", "3130200"}; + rows[1909] = new String[] {"MG", "Iguatama", "3130309"}; + rows[1910] = new String[] {"MG", "Ijaci", "3130408"}; + rows[1911] = new String[] {"MG", "Ilic\u00ednea", "3130507"}; + rows[1912] = new String[] {"MG", "Imb\u00e9 de Minas", "3130556"}; + rows[1913] = new String[] {"MG", "Inconfidentes", "3130606"}; + rows[1914] = new String[] {"MG", "Indaiabira", "3130655"}; + rows[1915] = new String[] {"MG", "Indian\u00f3polis", "3130705"}; + rows[1916] = new String[] {"MG", "Inga\u00ed", "3130804"}; + rows[1917] = new String[] {"MG", "Inhapim", "3130903"}; + rows[1918] = new String[] {"MG", "Inha\u00fama", "3131000"}; + rows[1919] = new String[] {"MG", "Inimutaba", "3131109"}; + rows[1920] = new String[] {"MG", "Ipaba", "3131158"}; + rows[1921] = new String[] {"MG", "Ipanema", "3131208"}; + rows[1922] = new String[] {"MG", "Ipatinga", "3131307"}; + rows[1923] = new String[] {"MG", "Ipia\u00e7u", "3131406"}; + rows[1924] = new String[] {"MG", "Ipui\u00fana", "3131505"}; + rows[1925] = new String[] {"MG", "Ira\u00ed de Minas", "3131604"}; + rows[1926] = new String[] {"MG", "Itabira", "3131703"}; + rows[1927] = new String[] {"MG", "Itabirinha", "3131802"}; + rows[1928] = new String[] {"MG", "Itabirito", "3131901"}; + rows[1929] = new String[] {"MG", "Itacambira", "3132008"}; + rows[1930] = new String[] {"MG", "Itacarambi", "3132107"}; + rows[1931] = new String[] {"MG", "Itaguara", "3132206"}; + rows[1932] = new String[] {"MG", "Itaip\u00e9", "3132305"}; + rows[1933] = new String[] {"MG", "Itajub\u00e1", "3132404"}; + rows[1934] = new String[] {"MG", "Itamarandiba", "3132503"}; + rows[1935] = new String[] {"MG", "Itamarati de Minas", "3132602"}; + rows[1936] = new String[] {"MG", "Itambacuri", "3132701"}; + rows[1937] = new String[] {"MG", "Itamb\u00e9 do Mato Dentro", "3132800"}; + rows[1938] = new String[] {"MG", "Itamogi", "3132909"}; + rows[1939] = new String[] {"MG", "Itamonte", "3133006"}; + rows[1940] = new String[] {"MG", "Itanhandu", "3133105"}; + rows[1941] = new String[] {"MG", "Itanhomi", "3133204"}; + rows[1942] = new String[] {"MG", "Itaobim", "3133303"}; + rows[1943] = new String[] {"MG", "Itapagipe", "3133402"}; + rows[1944] = new String[] {"MG", "Itapecerica", "3133501"}; + rows[1945] = new String[] {"MG", "Itapeva", "3133600"}; + rows[1946] = new String[] {"MG", "Itatiaiu\u00e7u", "3133709"}; + rows[1947] = new String[] {"MG", "Ita\u00fa de Minas", "3133758"}; + rows[1948] = new String[] {"MG", "Ita\u00fana", "3133808"}; + rows[1949] = new String[] {"MG", "Itaverava", "3133907"}; + rows[1950] = new String[] {"MG", "Itinga", "3134004"}; + rows[1951] = new String[] {"MG", "Itueta", "3134103"}; + rows[1952] = new String[] {"MG", "Ituiutaba", "3134202"}; + rows[1953] = new String[] {"MG", "Itumirim", "3134301"}; + rows[1954] = new String[] {"MG", "Iturama", "3134400"}; + rows[1955] = new String[] {"MG", "Itutinga", "3134509"}; + rows[1956] = new String[] {"MG", "Jaboticatubas", "3134608"}; + rows[1957] = new String[] {"MG", "Jacinto", "3134707"}; + rows[1958] = new String[] {"MG", "Jacu\u00ed", "3134806"}; + rows[1959] = new String[] {"MG", "Jacutinga", "3134905"}; + rows[1960] = new String[] {"MG", "Jaguara\u00e7u", "3135001"}; + rows[1961] = new String[] {"MG", "Ja\u00edba", "3135050"}; + rows[1962] = new String[] {"MG", "Jampruca", "3135076"}; + rows[1963] = new String[] {"MG", "Jana\u00faba", "3135100"}; + rows[1964] = new String[] {"MG", "Janu\u00e1ria", "3135209"}; + rows[1965] = new String[] {"MG", "Japara\u00edba", "3135308"}; + rows[1966] = new String[] {"MG", "Japonvar", "3135357"}; + rows[1967] = new String[] {"MG", "Jeceaba", "3135407"}; + rows[1968] = new String[] {"MG", "Jenipapo de Minas", "3135456"}; + rows[1969] = new String[] {"MG", "Jequeri", "3135506"}; + rows[1970] = new String[] {"MG", "Jequita\u00ed", "3135605"}; + rows[1971] = new String[] {"MG", "Jequitib\u00e1", "3135704"}; + rows[1972] = new String[] {"MG", "Jequitinhonha", "3135803"}; + rows[1973] = new String[] {"MG", "Jesu\u00e2nia", "3135902"}; + rows[1974] = new String[] {"MG", "Joa\u00edma", "3136009"}; + rows[1975] = new String[] {"MG", "Joan\u00e9sia", "3136108"}; + rows[1976] = new String[] {"MG", "Jo\u00e3o Monlevade", "3136207"}; + rows[1977] = new String[] {"MG", "Jo\u00e3o Pinheiro", "3136306"}; + rows[1978] = new String[] {"MG", "Joaquim Fel\u00edcio", "3136405"}; + rows[1979] = new String[] {"MG", "Jord\u00e2nia", "3136504"}; + rows[1980] = new String[] {"MG", "Jos\u00e9 Gon\u00e7alves de Minas", "3136520"}; + rows[1981] = new String[] {"MG", "Jos\u00e9 Raydan", "3136553"}; + rows[1982] = new String[] {"MG", "Josen\u00f3polis", "3136579"}; + rows[1983] = new String[] {"MG", "Juatuba", "3136652"}; + rows[1984] = new String[] {"MG", "Juiz de Fora", "3136702"}; + rows[1985] = new String[] {"MG", "Juramento", "3136801"}; + rows[1986] = new String[] {"MG", "Juruaia", "3136900"}; + rows[1987] = new String[] {"MG", "Juven\u00edlia", "3136959"}; + rows[1988] = new String[] {"MG", "Ladainha", "3137007"}; + rows[1989] = new String[] {"MG", "Lagamar", "3137106"}; + rows[1990] = new String[] {"MG", "Lagoa da Prata", "3137205"}; + rows[1991] = new String[] {"MG", "Lagoa dos Patos", "3137304"}; + rows[1992] = new String[] {"MG", "Lagoa Dourada", "3137403"}; + rows[1993] = new String[] {"MG", "Lagoa Formosa", "3137502"}; + rows[1994] = new String[] {"MG", "Lagoa Grande", "3137536"}; + rows[1995] = new String[] {"MG", "Lagoa Santa", "3137601"}; + rows[1996] = new String[] {"MG", "Lajinha", "3137700"}; + rows[1997] = new String[] {"MG", "Lambari", "3137809"}; + rows[1998] = new String[] {"MG", "Lamim", "3137908"}; + rows[1999] = new String[] {"MG", "Laranjal", "3138005"}; + } + + private static void municipalitiesRows10(String[][] rows) { + rows[2000] = new String[] {"MG", "Lassance", "3138104"}; + rows[2001] = new String[] {"MG", "Lavras", "3138203"}; + rows[2002] = new String[] {"MG", "Leandro Ferreira", "3138302"}; + rows[2003] = new String[] {"MG", "Leme do Prado", "3138351"}; + rows[2004] = new String[] {"MG", "Leopoldina", "3138401"}; + rows[2005] = new String[] {"MG", "Liberdade", "3138500"}; + rows[2006] = new String[] {"MG", "Lima Duarte", "3138609"}; + rows[2007] = new String[] {"MG", "Limeira do Oeste", "3138625"}; + rows[2008] = new String[] {"MG", "Lontra", "3138658"}; + rows[2009] = new String[] {"MG", "Luisburgo", "3138674"}; + rows[2010] = new String[] {"MG", "Luisl\u00e2ndia", "3138682"}; + rows[2011] = new String[] {"MG", "Lumin\u00e1rias", "3138708"}; + rows[2012] = new String[] {"MG", "Luz", "3138807"}; + rows[2013] = new String[] {"MG", "Machacalis", "3138906"}; + rows[2014] = new String[] {"MG", "Machado", "3139003"}; + rows[2015] = new String[] {"MG", "Madre de Deus de Minas", "3139102"}; + rows[2016] = new String[] {"MG", "Malacacheta", "3139201"}; + rows[2017] = new String[] {"MG", "Mamonas", "3139250"}; + rows[2018] = new String[] {"MG", "Manga", "3139300"}; + rows[2019] = new String[] {"MG", "Manhua\u00e7u", "3139409"}; + rows[2020] = new String[] {"MG", "Manhumirim", "3139508"}; + rows[2021] = new String[] {"MG", "Mantena", "3139607"}; + rows[2022] = new String[] {"MG", "Mar de Espanha", "3139805"}; + rows[2023] = new String[] {"MG", "Maravilhas", "3139706"}; + rows[2024] = new String[] {"MG", "Maria da F\u00e9", "3139904"}; + rows[2025] = new String[] {"MG", "Mariana", "3140001"}; + rows[2026] = new String[] {"MG", "Marilac", "3140100"}; + rows[2027] = new String[] {"MG", "M\u00e1rio Campos", "3140159"}; + rows[2028] = new String[] {"MG", "Marip\u00e1 de Minas", "3140209"}; + rows[2029] = new String[] {"MG", "Marli\u00e9ria", "3140308"}; + rows[2030] = new String[] {"MG", "Marmel\u00f3polis", "3140407"}; + rows[2031] = new String[] {"MG", "Martinho Campos", "3140506"}; + rows[2032] = new String[] {"MG", "Martins Soares", "3140530"}; + rows[2033] = new String[] {"MG", "Mata Verde", "3140555"}; + rows[2034] = new String[] {"MG", "Materl\u00e2ndia", "3140605"}; + rows[2035] = new String[] {"MG", "Mateus Leme", "3140704"}; + rows[2036] = new String[] {"MG", "Mathias Lobato", "3171501"}; + rows[2037] = new String[] {"MG", "Matias Barbosa", "3140803"}; + rows[2038] = new String[] {"MG", "Matias Cardoso", "3140852"}; + rows[2039] = new String[] {"MG", "Matip\u00f3", "3140902"}; + rows[2040] = new String[] {"MG", "Mato Verde", "3141009"}; + rows[2041] = new String[] {"MG", "Matozinhos", "3141108"}; + rows[2042] = new String[] {"MG", "Matutina", "3141207"}; + rows[2043] = new String[] {"MG", "Medeiros", "3141306"}; + rows[2044] = new String[] {"MG", "Medina", "3141405"}; + rows[2045] = new String[] {"MG", "Mendes Pimentel", "3141504"}; + rows[2046] = new String[] {"MG", "Merc\u00eas", "3141603"}; + rows[2047] = new String[] {"MG", "Mesquita", "3141702"}; + rows[2048] = new String[] {"MG", "Minas Novas", "3141801"}; + rows[2049] = new String[] {"MG", "Minduri", "3141900"}; + rows[2050] = new String[] {"MG", "Mirabela", "3142007"}; + rows[2051] = new String[] {"MG", "Miradouro", "3142106"}; + rows[2052] = new String[] {"MG", "Mira\u00ed", "3142205"}; + rows[2053] = new String[] {"MG", "Mirav\u00e2nia", "3142254"}; + rows[2054] = new String[] {"MG", "Moeda", "3142304"}; + rows[2055] = new String[] {"MG", "Moema", "3142403"}; + rows[2056] = new String[] {"MG", "Monjolos", "3142502"}; + rows[2057] = new String[] {"MG", "Monsenhor Paulo", "3142601"}; + rows[2058] = new String[] {"MG", "Montalv\u00e2nia", "3142700"}; + rows[2059] = new String[] {"MG", "Monte Alegre de Minas", "3142809"}; + rows[2060] = new String[] {"MG", "Monte Azul", "3142908"}; + rows[2061] = new String[] {"MG", "Monte Belo", "3143005"}; + rows[2062] = new String[] {"MG", "Monte Carmelo", "3143104"}; + rows[2063] = new String[] {"MG", "Monte Formoso", "3143153"}; + rows[2064] = new String[] {"MG", "Monte Santo de Minas", "3143203"}; + rows[2065] = new String[] {"MG", "Monte Si\u00e3o", "3143401"}; + rows[2066] = new String[] {"MG", "Montes Claros", "3143302"}; + rows[2067] = new String[] {"MG", "Montezuma", "3143450"}; + rows[2068] = new String[] {"MG", "Morada Nova de Minas", "3143500"}; + rows[2069] = new String[] {"MG", "Morro da Gar\u00e7a", "3143609"}; + rows[2070] = new String[] {"MG", "Morro do Pilar", "3143708"}; + rows[2071] = new String[] {"MG", "Munhoz", "3143807"}; + rows[2072] = new String[] {"MG", "Muria\u00e9", "3143906"}; + rows[2073] = new String[] {"MG", "Mutum", "3144003"}; + rows[2074] = new String[] {"MG", "Muzambinho", "3144102"}; + rows[2075] = new String[] {"MG", "Nacip Raydan", "3144201"}; + rows[2076] = new String[] {"MG", "Nanuque", "3144300"}; + rows[2077] = new String[] {"MG", "Naque", "3144359"}; + rows[2078] = new String[] {"MG", "Natal\u00e2ndia", "3144375"}; + rows[2079] = new String[] {"MG", "Nat\u00e9rcia", "3144409"}; + rows[2080] = new String[] {"MG", "Nazareno", "3144508"}; + rows[2081] = new String[] {"MG", "Nepomuceno", "3144607"}; + rows[2082] = new String[] {"MG", "Ninheira", "3144656"}; + rows[2083] = new String[] {"MG", "Nova Bel\u00e9m", "3144672"}; + rows[2084] = new String[] {"MG", "Nova Era", "3144706"}; + rows[2085] = new String[] {"MG", "Nova Lima", "3144805"}; + rows[2086] = new String[] {"MG", "Nova M\u00f3dica", "3144904"}; + rows[2087] = new String[] {"MG", "Nova Ponte", "3145000"}; + rows[2088] = new String[] {"MG", "Nova Porteirinha", "3145059"}; + rows[2089] = new String[] {"MG", "Nova Resende", "3145109"}; + rows[2090] = new String[] {"MG", "Nova Serrana", "3145208"}; + rows[2091] = new String[] {"MG", "Nova Uni\u00e3o", "3136603"}; + rows[2092] = new String[] {"MG", "Novo Cruzeiro", "3145307"}; + rows[2093] = new String[] {"MG", "Novo Oriente de Minas", "3145356"}; + rows[2094] = new String[] {"MG", "Novorizonte", "3145372"}; + rows[2095] = new String[] {"MG", "Olaria", "3145406"}; + rows[2096] = new String[] {"MG", "Olhos-d'\u00c1gua", "3145455"}; + rows[2097] = new String[] {"MG", "Ol\u00edmpio Noronha", "3145505"}; + rows[2098] = new String[] {"MG", "Oliveira", "3145604"}; + rows[2099] = new String[] {"MG", "Oliveira Fortes", "3145703"}; + rows[2100] = new String[] {"MG", "On\u00e7a de Pitangui", "3145802"}; + rows[2101] = new String[] {"MG", "Orat\u00f3rios", "3145851"}; + rows[2102] = new String[] {"MG", "Oriz\u00e2nia", "3145877"}; + rows[2103] = new String[] {"MG", "Ouro Branco", "3145901"}; + rows[2104] = new String[] {"MG", "Ouro Fino", "3146008"}; + rows[2105] = new String[] {"MG", "Ouro Preto", "3146107"}; + rows[2106] = new String[] {"MG", "Ouro Verde de Minas", "3146206"}; + rows[2107] = new String[] {"MG", "Padre Carvalho", "3146255"}; + rows[2108] = new String[] {"MG", "Padre Para\u00edso", "3146305"}; + rows[2109] = new String[] {"MG", "Pai Pedro", "3146552"}; + rows[2110] = new String[] {"MG", "Paineiras", "3146404"}; + rows[2111] = new String[] {"MG", "Pains", "3146503"}; + rows[2112] = new String[] {"MG", "Paiva", "3146602"}; + rows[2113] = new String[] {"MG", "Palma", "3146701"}; + rows[2114] = new String[] {"MG", "Palm\u00f3polis", "3146750"}; + rows[2115] = new String[] {"MG", "Papagaios", "3146909"}; + rows[2116] = new String[] {"MG", "Par\u00e1 de Minas", "3147105"}; + rows[2117] = new String[] {"MG", "Paracatu", "3147006"}; + rows[2118] = new String[] {"MG", "Paragua\u00e7u", "3147204"}; + rows[2119] = new String[] {"MG", "Parais\u00f3polis", "3147303"}; + rows[2120] = new String[] {"MG", "Paraopeba", "3147402"}; + rows[2121] = new String[] {"MG", "Passa Quatro", "3147600"}; + rows[2122] = new String[] {"MG", "Passa Tempo", "3147709"}; + rows[2123] = new String[] {"MG", "Passa Vinte", "3147808"}; + rows[2124] = new String[] {"MG", "Passab\u00e9m", "3147501"}; + rows[2125] = new String[] {"MG", "Passos", "3147907"}; + rows[2126] = new String[] {"MG", "Patis", "3147956"}; + rows[2127] = new String[] {"MG", "Patos de Minas", "3148004"}; + rows[2128] = new String[] {"MG", "Patroc\u00ednio", "3148103"}; + rows[2129] = new String[] {"MG", "Patroc\u00ednio do Muria\u00e9", "3148202"}; + rows[2130] = new String[] {"MG", "Paula C\u00e2ndido", "3148301"}; + rows[2131] = new String[] {"MG", "Paulistas", "3148400"}; + rows[2132] = new String[] {"MG", "Pav\u00e3o", "3148509"}; + rows[2133] = new String[] {"MG", "Pe\u00e7anha", "3148608"}; + rows[2134] = new String[] {"MG", "Pedra Azul", "3148707"}; + rows[2135] = new String[] {"MG", "Pedra Bonita", "3148756"}; + rows[2136] = new String[] {"MG", "Pedra do Anta", "3148806"}; + rows[2137] = new String[] {"MG", "Pedra do Indai\u00e1", "3148905"}; + rows[2138] = new String[] {"MG", "Pedra Dourada", "3149002"}; + rows[2139] = new String[] {"MG", "Pedralva", "3149101"}; + rows[2140] = new String[] {"MG", "Pedras de Maria da Cruz", "3149150"}; + rows[2141] = new String[] {"MG", "Pedrin\u00f3polis", "3149200"}; + rows[2142] = new String[] {"MG", "Pedro Leopoldo", "3149309"}; + rows[2143] = new String[] {"MG", "Pedro Teixeira", "3149408"}; + rows[2144] = new String[] {"MG", "Pequeri", "3149507"}; + rows[2145] = new String[] {"MG", "Pequi", "3149606"}; + rows[2146] = new String[] {"MG", "Perdig\u00e3o", "3149705"}; + rows[2147] = new String[] {"MG", "Perdizes", "3149804"}; + rows[2148] = new String[] {"MG", "Perd\u00f5es", "3149903"}; + rows[2149] = new String[] {"MG", "Periquito", "3149952"}; + rows[2150] = new String[] {"MG", "Pescador", "3150000"}; + rows[2151] = new String[] {"MG", "Piau", "3150109"}; + rows[2152] = new String[] {"MG", "Piedade de Caratinga", "3150158"}; + rows[2153] = new String[] {"MG", "Piedade de Ponte Nova", "3150208"}; + rows[2154] = new String[] {"MG", "Piedade do Rio Grande", "3150307"}; + rows[2155] = new String[] {"MG", "Piedade dos Gerais", "3150406"}; + rows[2156] = new String[] {"MG", "Pimenta", "3150505"}; + rows[2157] = new String[] {"MG", "Pingo-d'\u00c1gua", "3150539"}; + rows[2158] = new String[] {"MG", "Pint\u00f3polis", "3150570"}; + rows[2159] = new String[] {"MG", "Piracema", "3150604"}; + rows[2160] = new String[] {"MG", "Pirajuba", "3150703"}; + rows[2161] = new String[] {"MG", "Piranga", "3150802"}; + rows[2162] = new String[] {"MG", "Pirangu\u00e7u", "3150901"}; + rows[2163] = new String[] {"MG", "Piranguinho", "3151008"}; + rows[2164] = new String[] {"MG", "Pirapetinga", "3151107"}; + rows[2165] = new String[] {"MG", "Pirapora", "3151206"}; + rows[2166] = new String[] {"MG", "Pira\u00faba", "3151305"}; + rows[2167] = new String[] {"MG", "Pitangui", "3151404"}; + rows[2168] = new String[] {"MG", "Piumhi", "3151503"}; + rows[2169] = new String[] {"MG", "Planura", "3151602"}; + rows[2170] = new String[] {"MG", "Po\u00e7o Fundo", "3151701"}; + rows[2171] = new String[] {"MG", "Po\u00e7os de Caldas", "3151800"}; + rows[2172] = new String[] {"MG", "Pocrane", "3151909"}; + rows[2173] = new String[] {"MG", "Pomp\u00e9u", "3152006"}; + rows[2174] = new String[] {"MG", "Ponte Nova", "3152105"}; + rows[2175] = new String[] {"MG", "Ponto Chique", "3152131"}; + rows[2176] = new String[] {"MG", "Ponto dos Volantes", "3152170"}; + rows[2177] = new String[] {"MG", "Porteirinha", "3152204"}; + rows[2178] = new String[] {"MG", "Porto Firme", "3152303"}; + rows[2179] = new String[] {"MG", "Pot\u00e9", "3152402"}; + rows[2180] = new String[] {"MG", "Pouso Alegre", "3152501"}; + rows[2181] = new String[] {"MG", "Pouso Alto", "3152600"}; + rows[2182] = new String[] {"MG", "Prados", "3152709"}; + rows[2183] = new String[] {"MG", "Prata", "3152808"}; + rows[2184] = new String[] {"MG", "Prat\u00e1polis", "3152907"}; + rows[2185] = new String[] {"MG", "Pratinha", "3153004"}; + rows[2186] = new String[] {"MG", "Presidente Bernardes", "3153103"}; + rows[2187] = new String[] {"MG", "Presidente Juscelino", "3153202"}; + rows[2188] = new String[] {"MG", "Presidente Kubitschek", "3153301"}; + rows[2189] = new String[] {"MG", "Presidente Oleg\u00e1rio", "3153400"}; + rows[2190] = new String[] {"MG", "Prudente de Morais", "3153608"}; + rows[2191] = new String[] {"MG", "Quartel Geral", "3153707"}; + rows[2192] = new String[] {"MG", "Queluzito", "3153806"}; + rows[2193] = new String[] {"MG", "Raposos", "3153905"}; + rows[2194] = new String[] {"MG", "Raul Soares", "3154002"}; + rows[2195] = new String[] {"MG", "Recreio", "3154101"}; + rows[2196] = new String[] {"MG", "Reduto", "3154150"}; + rows[2197] = new String[] {"MG", "Resende Costa", "3154200"}; + rows[2198] = new String[] {"MG", "Resplendor", "3154309"}; + rows[2199] = new String[] {"MG", "Ressaquinha", "3154408"}; + } + + private static void municipalitiesRows11(String[][] rows) { + rows[2200] = new String[] {"MG", "Riachinho", "3154457"}; + rows[2201] = new String[] {"MG", "Riacho dos Machados", "3154507"}; + rows[2202] = new String[] {"MG", "Ribeir\u00e3o das Neves", "3154606"}; + rows[2203] = new String[] {"MG", "Ribeir\u00e3o Vermelho", "3154705"}; + rows[2204] = new String[] {"MG", "Rio Acima", "3154804"}; + rows[2205] = new String[] {"MG", "Rio Casca", "3154903"}; + rows[2206] = new String[] {"MG", "Rio do Prado", "3155108"}; + rows[2207] = new String[] {"MG", "Rio Doce", "3155009"}; + rows[2208] = new String[] {"MG", "Rio Espera", "3155207"}; + rows[2209] = new String[] {"MG", "Rio Manso", "3155306"}; + rows[2210] = new String[] {"MG", "Rio Novo", "3155405"}; + rows[2211] = new String[] {"MG", "Rio Parana\u00edba", "3155504"}; + rows[2212] = new String[] {"MG", "Rio Pardo de Minas", "3155603"}; + rows[2213] = new String[] {"MG", "Rio Piracicaba", "3155702"}; + rows[2214] = new String[] {"MG", "Rio Pomba", "3155801"}; + rows[2215] = new String[] {"MG", "Rio Preto", "3155900"}; + rows[2216] = new String[] {"MG", "Rio Vermelho", "3156007"}; + rows[2217] = new String[] {"MG", "Rit\u00e1polis", "3156106"}; + rows[2218] = new String[] {"MG", "Rochedo de Minas", "3156205"}; + rows[2219] = new String[] {"MG", "Rodeiro", "3156304"}; + rows[2220] = new String[] {"MG", "Romaria", "3156403"}; + rows[2221] = new String[] {"MG", "Ros\u00e1rio da Limeira", "3156452"}; + rows[2222] = new String[] {"MG", "Rubelita", "3156502"}; + rows[2223] = new String[] {"MG", "Rubim", "3156601"}; + rows[2224] = new String[] {"MG", "Sabar\u00e1", "3156700"}; + rows[2225] = new String[] {"MG", "Sabin\u00f3polis", "3156809"}; + rows[2226] = new String[] {"MG", "Sacramento", "3156908"}; + rows[2227] = new String[] {"MG", "Salinas", "3157005"}; + rows[2228] = new String[] {"MG", "Salto da Divisa", "3157104"}; + rows[2229] = new String[] {"MG", "Santa B\u00e1rbara", "3157203"}; + rows[2230] = new String[] {"MG", "Santa B\u00e1rbara do Leste", "3157252"}; + rows[2231] = new String[] {"MG", "Santa B\u00e1rbara do Monte Verde", "3157278"}; + rows[2232] = new String[] {"MG", "Santa B\u00e1rbara do Tug\u00fario", "3157302"}; + rows[2233] = new String[] {"MG", "Santa Cruz de Minas", "3157336"}; + rows[2234] = new String[] {"MG", "Santa Cruz de Salinas", "3157377"}; + rows[2235] = new String[] {"MG", "Santa Cruz do Escalvado", "3157401"}; + rows[2236] = new String[] {"MG", "Santa Efig\u00eania de Minas", "3157500"}; + rows[2237] = new String[] {"MG", "Santa F\u00e9 de Minas", "3157609"}; + rows[2238] = new String[] {"MG", "Santa Helena de Minas", "3157658"}; + rows[2239] = new String[] {"MG", "Santa Juliana", "3157708"}; + rows[2240] = new String[] {"MG", "Santa Luzia", "3157807"}; + rows[2241] = new String[] {"MG", "Santa Margarida", "3157906"}; + rows[2242] = new String[] {"MG", "Santa Maria de Itabira", "3158003"}; + rows[2243] = new String[] {"MG", "Santa Maria do Salto", "3158102"}; + rows[2244] = new String[] {"MG", "Santa Maria do Sua\u00e7u\u00ed", "3158201"}; + rows[2245] = new String[] {"MG", "Santa Rita de Caldas", "3159209"}; + rows[2246] = new String[] {"MG", "Santa Rita de Ibitipoca", "3159407"}; + rows[2247] = new String[] {"MG", "Santa Rita de Jacutinga", "3159308"}; + rows[2248] = new String[] {"MG", "Santa Rita de Minas", "3159357"}; + rows[2249] = new String[] {"MG", "Santa Rita do Itueto", "3159506"}; + rows[2250] = new String[] {"MG", "Santa Rita do Sapuca\u00ed", "3159605"}; + rows[2251] = new String[] {"MG", "Santa Rosa da Serra", "3159704"}; + rows[2252] = new String[] {"MG", "Santa Vit\u00f3ria", "3159803"}; + rows[2253] = new String[] {"MG", "Santana da Vargem", "3158300"}; + rows[2254] = new String[] {"MG", "Santana de Cataguases", "3158409"}; + rows[2255] = new String[] {"MG", "Santana de Pirapama", "3158508"}; + rows[2256] = new String[] {"MG", "Santana do Deserto", "3158607"}; + rows[2257] = new String[] {"MG", "Santana do Garamb\u00e9u", "3158706"}; + rows[2258] = new String[] {"MG", "Santana do Jacar\u00e9", "3158805"}; + rows[2259] = new String[] {"MG", "Santana do Manhua\u00e7u", "3158904"}; + rows[2260] = new String[] {"MG", "Santana do Para\u00edso", "3158953"}; + rows[2261] = new String[] {"MG", "Santana do Riacho", "3159001"}; + rows[2262] = new String[] {"MG", "Santana dos Montes", "3159100"}; + rows[2263] = new String[] {"MG", "Santo Ant\u00f4nio do Amparo", "3159902"}; + rows[2264] = new String[] {"MG", "Santo Ant\u00f4nio do Aventureiro", "3160009"}; + rows[2265] = new String[] {"MG", "Santo Ant\u00f4nio do Grama", "3160108"}; + rows[2266] = new String[] {"MG", "Santo Ant\u00f4nio do Itamb\u00e9", "3160207"}; + rows[2267] = new String[] {"MG", "Santo Ant\u00f4nio do Jacinto", "3160306"}; + rows[2268] = new String[] {"MG", "Santo Ant\u00f4nio do Monte", "3160405"}; + rows[2269] = new String[] {"MG", "Santo Ant\u00f4nio do Retiro", "3160454"}; + rows[2270] = new String[] {"MG", "Santo Ant\u00f4nio do Rio Abaixo", "3160504"}; + rows[2271] = new String[] {"MG", "Santo Hip\u00f3lito", "3160603"}; + rows[2272] = new String[] {"MG", "Santos Dumont", "3160702"}; + rows[2273] = new String[] {"MG", "S\u00e3o Bento Abade", "3160801"}; + rows[2274] = new String[] {"MG", "S\u00e3o Br\u00e1s do Sua\u00e7u\u00ed", "3160900"}; + rows[2275] = new String[] {"MG", "S\u00e3o Domingos das Dores", "3160959"}; + rows[2276] = new String[] {"MG", "S\u00e3o Domingos do Prata", "3161007"}; + rows[2277] = new String[] {"MG", "S\u00e3o F\u00e9lix de Minas", "3161056"}; + rows[2278] = new String[] {"MG", "S\u00e3o Francisco", "3161106"}; + rows[2279] = new String[] {"MG", "S\u00e3o Francisco de Paula", "3161205"}; + rows[2280] = new String[] {"MG", "S\u00e3o Francisco de Sales", "3161304"}; + rows[2281] = new String[] {"MG", "S\u00e3o Francisco do Gl\u00f3ria", "3161403"}; + rows[2282] = new String[] {"MG", "S\u00e3o Geraldo", "3161502"}; + rows[2283] = new String[] {"MG", "S\u00e3o Geraldo da Piedade", "3161601"}; + rows[2284] = new String[] {"MG", "S\u00e3o Geraldo do Baixio", "3161650"}; + rows[2285] = new String[] {"MG", "S\u00e3o Gon\u00e7alo do Abaet\u00e9", "3161700"}; + rows[2286] = new String[] {"MG", "S\u00e3o Gon\u00e7alo do Par\u00e1", "3161809"}; + rows[2287] = new String[] {"MG", "S\u00e3o Gon\u00e7alo do Rio Abaixo", "3161908"}; + rows[2288] = new String[] {"MG", "S\u00e3o Gon\u00e7alo do Rio Preto", "3125507"}; + rows[2289] = new String[] {"MG", "S\u00e3o Gon\u00e7alo do Sapuca\u00ed", "3162005"}; + rows[2290] = new String[] {"MG", "S\u00e3o Gotardo", "3162104"}; + rows[2291] = new String[] {"MG", "S\u00e3o Jo\u00e3o Batista do Gl\u00f3ria", "3162203"}; + rows[2292] = new String[] {"MG", "S\u00e3o Jo\u00e3o da Lagoa", "3162252"}; + rows[2293] = new String[] {"MG", "S\u00e3o Jo\u00e3o da Mata", "3162302"}; + rows[2294] = new String[] {"MG", "S\u00e3o Jo\u00e3o da Ponte", "3162401"}; + rows[2295] = new String[] {"MG", "S\u00e3o Jo\u00e3o das Miss\u00f5es", "3162450"}; + rows[2296] = new String[] {"MG", "S\u00e3o Jo\u00e3o del Rei", "3162500"}; + rows[2297] = new String[] {"MG", "S\u00e3o Jo\u00e3o do Manhua\u00e7u", "3162559"}; + rows[2298] = new String[] {"MG", "S\u00e3o Jo\u00e3o do Manteninha", "3162575"}; + rows[2299] = new String[] {"MG", "S\u00e3o Jo\u00e3o do Oriente", "3162609"}; + rows[2300] = new String[] {"MG", "S\u00e3o Jo\u00e3o do Pacu\u00ed", "3162658"}; + rows[2301] = new String[] {"MG", "S\u00e3o Jo\u00e3o do Para\u00edso", "3162708"}; + rows[2302] = new String[] {"MG", "S\u00e3o Jo\u00e3o Evangelista", "3162807"}; + rows[2303] = new String[] {"MG", "S\u00e3o Jo\u00e3o Nepomuceno", "3162906"}; + rows[2304] = new String[] {"MG", "S\u00e3o Joaquim de Bicas", "3162922"}; + rows[2305] = new String[] {"MG", "S\u00e3o Jos\u00e9 da Barra", "3162948"}; + rows[2306] = new String[] {"MG", "S\u00e3o Jos\u00e9 da Lapa", "3162955"}; + rows[2307] = new String[] {"MG", "S\u00e3o Jos\u00e9 da Safira", "3163003"}; + rows[2308] = new String[] {"MG", "S\u00e3o Jos\u00e9 da Varginha", "3163102"}; + rows[2309] = new String[] {"MG", "S\u00e3o Jos\u00e9 do Alegre", "3163201"}; + rows[2310] = new String[] {"MG", "S\u00e3o Jos\u00e9 do Divino", "3163300"}; + rows[2311] = new String[] {"MG", "S\u00e3o Jos\u00e9 do Goiabal", "3163409"}; + rows[2312] = new String[] {"MG", "S\u00e3o Jos\u00e9 do Jacuri", "3163508"}; + rows[2313] = new String[] {"MG", "S\u00e3o Jos\u00e9 do Mantimento", "3163607"}; + rows[2314] = new String[] {"MG", "S\u00e3o Louren\u00e7o", "3163706"}; + rows[2315] = new String[] {"MG", "S\u00e3o Miguel do Anta", "3163805"}; + rows[2316] = new String[] {"MG", "S\u00e3o Pedro da Uni\u00e3o", "3163904"}; + rows[2317] = new String[] {"MG", "S\u00e3o Pedro do Sua\u00e7u\u00ed", "3164100"}; + rows[2318] = new String[] {"MG", "S\u00e3o Pedro dos Ferros", "3164001"}; + rows[2319] = new String[] {"MG", "S\u00e3o Rom\u00e3o", "3164209"}; + rows[2320] = new String[] {"MG", "S\u00e3o Roque de Minas", "3164308"}; + rows[2321] = new String[] {"MG", "S\u00e3o Sebasti\u00e3o da Bela Vista", "3164407"}; + rows[2322] = new String[] {"MG", "S\u00e3o Sebasti\u00e3o da Vargem Alegre", "3164431"}; + rows[2323] = new String[] {"MG", "S\u00e3o Sebasti\u00e3o do Anta", "3164472"}; + rows[2324] = new String[] {"MG", "S\u00e3o Sebasti\u00e3o do Maranh\u00e3o", "3164506"}; + rows[2325] = new String[] {"MG", "S\u00e3o Sebasti\u00e3o do Oeste", "3164605"}; + rows[2326] = new String[] {"MG", "S\u00e3o Sebasti\u00e3o do Para\u00edso", "3164704"}; + rows[2327] = new String[] {"MG", "S\u00e3o Sebasti\u00e3o do Rio Preto", "3164803"}; + rows[2328] = new String[] {"MG", "S\u00e3o Sebasti\u00e3o do Rio Verde", "3164902"}; + rows[2329] = new String[] {"MG", "S\u00e3o Tiago", "3165008"}; + rows[2330] = new String[] {"MG", "S\u00e3o Tom\u00e1s de Aquino", "3165107"}; + rows[2331] = new String[] {"MG", "S\u00e3o Tom\u00e9 das Letras", "3165206"}; + rows[2332] = new String[] {"MG", "S\u00e3o Vicente de Minas", "3165305"}; + rows[2333] = new String[] {"MG", "Sapuca\u00ed-Mirim", "3165404"}; + rows[2334] = new String[] {"MG", "Sardo\u00e1", "3165503"}; + rows[2335] = new String[] {"MG", "Sarzedo", "3165537"}; + rows[2336] = new String[] {"MG", "Sem-Peixe", "3165560"}; + rows[2337] = new String[] {"MG", "Senador Amaral", "3165578"}; + rows[2338] = new String[] {"MG", "Senador Cortes", "3165602"}; + rows[2339] = new String[] {"MG", "Senador Firmino", "3165701"}; + rows[2340] = new String[] {"MG", "Senador Jos\u00e9 Bento", "3165800"}; + rows[2341] = new String[] {"MG", "Senador Modestino Gon\u00e7alves", "3165909"}; + rows[2342] = new String[] {"MG", "Senhora de Oliveira", "3166006"}; + rows[2343] = new String[] {"MG", "Senhora do Porto", "3166105"}; + rows[2344] = new String[] {"MG", "Senhora dos Rem\u00e9dios", "3166204"}; + rows[2345] = new String[] {"MG", "Sericita", "3166303"}; + rows[2346] = new String[] {"MG", "Seritinga", "3166402"}; + rows[2347] = new String[] {"MG", "Serra Azul de Minas", "3166501"}; + rows[2348] = new String[] {"MG", "Serra da Saudade", "3166600"}; + rows[2349] = new String[] {"MG", "Serra do Salitre", "3166808"}; + rows[2350] = new String[] {"MG", "Serra dos Aimor\u00e9s", "3166709"}; + rows[2351] = new String[] {"MG", "Serrania", "3166907"}; + rows[2352] = new String[] {"MG", "Serran\u00f3polis de Minas", "3166956"}; + rows[2353] = new String[] {"MG", "Serranos", "3167004"}; + rows[2354] = new String[] {"MG", "Serro", "3167103"}; + rows[2355] = new String[] {"MG", "Sete Lagoas", "3167202"}; + rows[2356] = new String[] {"MG", "Setubinha", "3165552"}; + rows[2357] = new String[] {"MG", "Silveir\u00e2nia", "3167301"}; + rows[2358] = new String[] {"MG", "Silvian\u00f3polis", "3167400"}; + rows[2359] = new String[] {"MG", "Sim\u00e3o Pereira", "3167509"}; + rows[2360] = new String[] {"MG", "Simon\u00e9sia", "3167608"}; + rows[2361] = new String[] {"MG", "Sobr\u00e1lia", "3167707"}; + rows[2362] = new String[] {"MG", "Soledade de Minas", "3167806"}; + rows[2363] = new String[] {"MG", "Tabuleiro", "3167905"}; + rows[2364] = new String[] {"MG", "Taiobeiras", "3168002"}; + rows[2365] = new String[] {"MG", "Taparuba", "3168051"}; + rows[2366] = new String[] {"MG", "Tapira", "3168101"}; + rows[2367] = new String[] {"MG", "Tapira\u00ed", "3168200"}; + rows[2368] = new String[] {"MG", "Taquara\u00e7u de Minas", "3168309"}; + rows[2369] = new String[] {"MG", "Tarumirim", "3168408"}; + rows[2370] = new String[] {"MG", "Teixeiras", "3168507"}; + rows[2371] = new String[] {"MG", "Te\u00f3filo Otoni", "3168606"}; + rows[2372] = new String[] {"MG", "Tim\u00f3teo", "3168705"}; + rows[2373] = new String[] {"MG", "Tiradentes", "3168804"}; + rows[2374] = new String[] {"MG", "Tiros", "3168903"}; + rows[2375] = new String[] {"MG", "Tocantins", "3169000"}; + rows[2376] = new String[] {"MG", "Tocos do Moji", "3169059"}; + rows[2377] = new String[] {"MG", "Toledo", "3169109"}; + rows[2378] = new String[] {"MG", "Tombos", "3169208"}; + rows[2379] = new String[] {"MG", "Tr\u00eas Cora\u00e7\u00f5es", "3169307"}; + rows[2380] = new String[] {"MG", "Tr\u00eas Marias", "3169356"}; + rows[2381] = new String[] {"MG", "Tr\u00eas Pontas", "3169406"}; + rows[2382] = new String[] {"MG", "Tumiritinga", "3169505"}; + rows[2383] = new String[] {"MG", "Tupaciguara", "3169604"}; + rows[2384] = new String[] {"MG", "Turmalina", "3169703"}; + rows[2385] = new String[] {"MG", "Turvol\u00e2ndia", "3169802"}; + rows[2386] = new String[] {"MG", "Ub\u00e1", "3169901"}; + rows[2387] = new String[] {"MG", "Uba\u00ed", "3170008"}; + rows[2388] = new String[] {"MG", "Ubaporanga", "3170057"}; + rows[2389] = new String[] {"MG", "Uberaba", "3170107"}; + rows[2390] = new String[] {"MG", "Uberl\u00e2ndia", "3170206"}; + rows[2391] = new String[] {"MG", "Umburatiba", "3170305"}; + rows[2392] = new String[] {"MG", "Una\u00ed", "3170404"}; + rows[2393] = new String[] {"MG", "Uni\u00e3o de Minas", "3170438"}; + rows[2394] = new String[] {"MG", "Uruana de Minas", "3170479"}; + rows[2395] = new String[] {"MG", "Uruc\u00e2nia", "3170503"}; + rows[2396] = new String[] {"MG", "Urucuia", "3170529"}; + rows[2397] = new String[] {"MG", "Vargem Alegre", "3170578"}; + rows[2398] = new String[] {"MG", "Vargem Bonita", "3170602"}; + rows[2399] = new String[] {"MG", "Vargem Grande do Rio Pardo", "3170651"}; + } + + private static void municipalitiesRows12(String[][] rows) { + rows[2400] = new String[] {"MG", "Varginha", "3170701"}; + rows[2401] = new String[] {"MG", "Varj\u00e3o de Minas", "3170750"}; + rows[2402] = new String[] {"MG", "V\u00e1rzea da Palma", "3170800"}; + rows[2403] = new String[] {"MG", "Varzel\u00e2ndia", "3170909"}; + rows[2404] = new String[] {"MG", "Vazante", "3171006"}; + rows[2405] = new String[] {"MG", "Verdel\u00e2ndia", "3171030"}; + rows[2406] = new String[] {"MG", "Veredinha", "3171071"}; + rows[2407] = new String[] {"MG", "Ver\u00edssimo", "3171105"}; + rows[2408] = new String[] {"MG", "Vermelho Novo", "3171154"}; + rows[2409] = new String[] {"MG", "Vespasiano", "3171204"}; + rows[2410] = new String[] {"MG", "Vi\u00e7osa", "3171303"}; + rows[2411] = new String[] {"MG", "Vieiras", "3171402"}; + rows[2412] = new String[] {"MG", "Virgem da Lapa", "3171600"}; + rows[2413] = new String[] {"MG", "Virg\u00ednia", "3171709"}; + rows[2414] = new String[] {"MG", "Virgin\u00f3polis", "3171808"}; + rows[2415] = new String[] {"MG", "Virgol\u00e2ndia", "3171907"}; + rows[2416] = new String[] {"MG", "Visconde do Rio Branco", "3172004"}; + rows[2417] = new String[] {"MG", "Volta Grande", "3172103"}; + rows[2418] = new String[] {"MG", "Wenceslau Braz", "3172202"}; + rows[2419] = new String[] {"PA", "Abaetetuba", "1500107"}; + rows[2420] = new String[] {"PA", "Abel Figueiredo", "1500131"}; + rows[2421] = new String[] {"PA", "Acar\u00e1", "1500206"}; + rows[2422] = new String[] {"PA", "Afu\u00e1", "1500305"}; + rows[2423] = new String[] {"PA", "\u00c1gua Azul do Norte", "1500347"}; + rows[2424] = new String[] {"PA", "Alenquer", "1500404"}; + rows[2425] = new String[] {"PA", "Almeirim", "1500503"}; + rows[2426] = new String[] {"PA", "Altamira", "1500602"}; + rows[2427] = new String[] {"PA", "Anaj\u00e1s", "1500701"}; + rows[2428] = new String[] {"PA", "Ananindeua", "1500800"}; + rows[2429] = new String[] {"PA", "Anapu", "1500859"}; + rows[2430] = new String[] {"PA", "Augusto Corr\u00eaa", "1500909"}; + rows[2431] = new String[] {"PA", "Aurora do Par\u00e1", "1500958"}; + rows[2432] = new String[] {"PA", "Aveiro", "1501006"}; + rows[2433] = new String[] {"PA", "Bagre", "1501105"}; + rows[2434] = new String[] {"PA", "Bai\u00e3o", "1501204"}; + rows[2435] = new String[] {"PA", "Bannach", "1501253"}; + rows[2436] = new String[] {"PA", "Barcarena", "1501303"}; + rows[2437] = new String[] {"PA", "Bel\u00e9m", "1501402"}; + rows[2438] = new String[] {"PA", "Belterra", "1501451"}; + rows[2439] = new String[] {"PA", "Benevides", "1501501"}; + rows[2440] = new String[] {"PA", "Bom Jesus do Tocantins", "1501576"}; + rows[2441] = new String[] {"PA", "Bonito", "1501600"}; + rows[2442] = new String[] {"PA", "Bragan\u00e7a", "1501709"}; + rows[2443] = new String[] {"PA", "Brasil Novo", "1501725"}; + rows[2444] = new String[] {"PA", "Brejo Grande do Araguaia", "1501758"}; + rows[2445] = new String[] {"PA", "Breu Branco", "1501782"}; + rows[2446] = new String[] {"PA", "Breves", "1501808"}; + rows[2447] = new String[] {"PA", "Bujaru", "1501907"}; + rows[2448] = new String[] {"PA", "Cachoeira do Arari", "1502004"}; + rows[2449] = new String[] {"PA", "Cachoeira do Piri\u00e1", "1501956"}; + rows[2450] = new String[] {"PA", "Camet\u00e1", "1502103"}; + rows[2451] = new String[] {"PA", "Cana\u00e3 dos Caraj\u00e1s", "1502152"}; + rows[2452] = new String[] {"PA", "Capanema", "1502202"}; + rows[2453] = new String[] {"PA", "Capit\u00e3o Po\u00e7o", "1502301"}; + rows[2454] = new String[] {"PA", "Castanhal", "1502400"}; + rows[2455] = new String[] {"PA", "Chaves", "1502509"}; + rows[2456] = new String[] {"PA", "Colares", "1502608"}; + rows[2457] = new String[] {"PA", "Concei\u00e7\u00e3o do Araguaia", "1502707"}; + rows[2458] = new String[] {"PA", "Conc\u00f3rdia do Par\u00e1", "1502756"}; + rows[2459] = new String[] {"PA", "Cumaru do Norte", "1502764"}; + rows[2460] = new String[] {"PA", "Curion\u00f3polis", "1502772"}; + rows[2461] = new String[] {"PA", "Curralinho", "1502806"}; + rows[2462] = new String[] {"PA", "Curu\u00e1", "1502855"}; + rows[2463] = new String[] {"PA", "Curu\u00e7\u00e1", "1502905"}; + rows[2464] = new String[] {"PA", "Dom Eliseu", "1502939"}; + rows[2465] = new String[] {"PA", "Eldorado do Caraj\u00e1s", "1502954"}; + rows[2466] = new String[] {"PA", "Faro", "1503002"}; + rows[2467] = new String[] {"PA", "Floresta do Araguaia", "1503044"}; + rows[2468] = new String[] {"PA", "Garraf\u00e3o do Norte", "1503077"}; + rows[2469] = new String[] {"PA", "Goian\u00e9sia do Par\u00e1", "1503093"}; + rows[2470] = new String[] {"PA", "Gurup\u00e1", "1503101"}; + rows[2471] = new String[] {"PA", "Igarap\u00e9-A\u00e7u", "1503200"}; + rows[2472] = new String[] {"PA", "Igarap\u00e9-Miri", "1503309"}; + rows[2473] = new String[] {"PA", "Inhangapi", "1503408"}; + rows[2474] = new String[] {"PA", "Ipixuna do Par\u00e1", "1503457"}; + rows[2475] = new String[] {"PA", "Irituia", "1503507"}; + rows[2476] = new String[] {"PA", "Itaituba", "1503606"}; + rows[2477] = new String[] {"PA", "Itupiranga", "1503705"}; + rows[2478] = new String[] {"PA", "Jacareacanga", "1503754"}; + rows[2479] = new String[] {"PA", "Jacund\u00e1", "1503804"}; + rows[2480] = new String[] {"PA", "Juruti", "1503903"}; + rows[2481] = new String[] {"PA", "Limoeiro do Ajuru", "1504000"}; + rows[2482] = new String[] {"PA", "M\u00e3e do Rio", "1504059"}; + rows[2483] = new String[] {"PA", "Magalh\u00e3es Barata", "1504109"}; + rows[2484] = new String[] {"PA", "Marab\u00e1", "1504208"}; + rows[2485] = new String[] {"PA", "Maracan\u00e3", "1504307"}; + rows[2486] = new String[] {"PA", "Marapanim", "1504406"}; + rows[2487] = new String[] {"PA", "Marituba", "1504422"}; + rows[2488] = new String[] {"PA", "Medicil\u00e2ndia", "1504455"}; + rows[2489] = new String[] {"PA", "Melga\u00e7o", "1504505"}; + rows[2490] = new String[] {"PA", "Mocajuba", "1504604"}; + rows[2491] = new String[] {"PA", "Moju", "1504703"}; + rows[2492] = new String[] {"PA", "Moju\u00ed dos Campos", "1504752"}; + rows[2493] = new String[] {"PA", "Monte Alegre", "1504802"}; + rows[2494] = new String[] {"PA", "Muan\u00e1", "1504901"}; + rows[2495] = new String[] {"PA", "Nova Esperan\u00e7a do Piri\u00e1", "1504950"}; + rows[2496] = new String[] {"PA", "Nova Ipixuna", "1504976"}; + rows[2497] = new String[] {"PA", "Nova Timboteua", "1505007"}; + rows[2498] = new String[] {"PA", "Novo Progresso", "1505031"}; + rows[2499] = new String[] {"PA", "Novo Repartimento", "1505064"}; + rows[2500] = new String[] {"PA", "\u00d3bidos", "1505106"}; + rows[2501] = new String[] {"PA", "Oeiras do Par\u00e1", "1505205"}; + rows[2502] = new String[] {"PA", "Oriximin\u00e1", "1505304"}; + rows[2503] = new String[] {"PA", "Our\u00e9m", "1505403"}; + rows[2504] = new String[] {"PA", "Ouril\u00e2ndia do Norte", "1505437"}; + rows[2505] = new String[] {"PA", "Pacaj\u00e1", "1505486"}; + rows[2506] = new String[] {"PA", "Palestina do Par\u00e1", "1505494"}; + rows[2507] = new String[] {"PA", "Paragominas", "1505502"}; + rows[2508] = new String[] {"PA", "Parauapebas", "1505536"}; + rows[2509] = new String[] {"PA", "Pau D'Arco", "1505551"}; + rows[2510] = new String[] {"PA", "Peixe-Boi", "1505601"}; + rows[2511] = new String[] {"PA", "Pi\u00e7arra", "1505635"}; + rows[2512] = new String[] {"PA", "Placas", "1505650"}; + rows[2513] = new String[] {"PA", "Ponta de Pedras", "1505700"}; + rows[2514] = new String[] {"PA", "Portel", "1505809"}; + rows[2515] = new String[] {"PA", "Porto de Moz", "1505908"}; + rows[2516] = new String[] {"PA", "Prainha", "1506005"}; + rows[2517] = new String[] {"PA", "Primavera", "1506104"}; + rows[2518] = new String[] {"PA", "Quatipuru", "1506112"}; + rows[2519] = new String[] {"PA", "Reden\u00e7\u00e3o", "1506138"}; + rows[2520] = new String[] {"PA", "Rio Maria", "1506161"}; + rows[2521] = new String[] {"PA", "Rondon do Par\u00e1", "1506187"}; + rows[2522] = new String[] {"PA", "Rur\u00f3polis", "1506195"}; + rows[2523] = new String[] {"PA", "Salin\u00f3polis", "1506203"}; + rows[2524] = new String[] {"PA", "Salvaterra", "1506302"}; + rows[2525] = new String[] {"PA", "Santa B\u00e1rbara do Par\u00e1", "1506351"}; + rows[2526] = new String[] {"PA", "Santa Cruz do Arari", "1506401"}; + rows[2527] = new String[] {"PA", "Santa Izabel do Par\u00e1", "1506500"}; + rows[2528] = new String[] {"PA", "Santa Luzia do Par\u00e1", "1506559"}; + rows[2529] = new String[] {"PA", "Santa Maria das Barreiras", "1506583"}; + rows[2530] = new String[] {"PA", "Santa Maria do Par\u00e1", "1506609"}; + rows[2531] = new String[] {"PA", "Santana do Araguaia", "1506708"}; + rows[2532] = new String[] {"PA", "Santar\u00e9m", "1506807"}; + rows[2533] = new String[] {"PA", "Santar\u00e9m Novo", "1506906"}; + rows[2534] = new String[] {"PA", "Santo Ant\u00f4nio do Tau\u00e1", "1507003"}; + rows[2535] = new String[] {"PA", "S\u00e3o Caetano de Odivelas", "1507102"}; + rows[2536] = new String[] {"PA", "S\u00e3o Domingos do Araguaia", "1507151"}; + rows[2537] = new String[] {"PA", "S\u00e3o Domingos do Capim", "1507201"}; + rows[2538] = new String[] {"PA", "S\u00e3o F\u00e9lix do Xingu", "1507300"}; + rows[2539] = new String[] {"PA", "S\u00e3o Francisco do Par\u00e1", "1507409"}; + rows[2540] = new String[] {"PA", "S\u00e3o Geraldo do Araguaia", "1507458"}; + rows[2541] = new String[] {"PA", "S\u00e3o Jo\u00e3o da Ponta", "1507466"}; + rows[2542] = new String[] {"PA", "S\u00e3o Jo\u00e3o de Pirabas", "1507474"}; + rows[2543] = new String[] {"PA", "S\u00e3o Jo\u00e3o do Araguaia", "1507508"}; + rows[2544] = new String[] {"PA", "S\u00e3o Miguel do Guam\u00e1", "1507607"}; + rows[2545] = new String[] {"PA", "S\u00e3o Sebasti\u00e3o da Boa Vista", "1507706"}; + rows[2546] = new String[] {"PA", "Sapucaia", "1507755"}; + rows[2547] = new String[] {"PA", "Senador Jos\u00e9 Porf\u00edrio", "1507805"}; + rows[2548] = new String[] {"PA", "Soure", "1507904"}; + rows[2549] = new String[] {"PA", "Tail\u00e2ndia", "1507953"}; + rows[2550] = new String[] {"PA", "Terra Alta", "1507961"}; + rows[2551] = new String[] {"PA", "Terra Santa", "1507979"}; + rows[2552] = new String[] {"PA", "Tom\u00e9-A\u00e7u", "1508001"}; + rows[2553] = new String[] {"PA", "Tracuateua", "1508035"}; + rows[2554] = new String[] {"PA", "Trair\u00e3o", "1508050"}; + rows[2555] = new String[] {"PA", "Tucum\u00e3", "1508084"}; + rows[2556] = new String[] {"PA", "Tucuru\u00ed", "1508100"}; + rows[2557] = new String[] {"PA", "Ulian\u00f3polis", "1508126"}; + rows[2558] = new String[] {"PA", "Uruar\u00e1", "1508159"}; + rows[2559] = new String[] {"PA", "Vigia", "1508209"}; + rows[2560] = new String[] {"PA", "Viseu", "1508308"}; + rows[2561] = new String[] {"PA", "Vit\u00f3ria do Xingu", "1508357"}; + rows[2562] = new String[] {"PA", "Xinguara", "1508407"}; + rows[2563] = new String[] {"PB", "\u00c1gua Branca", "2500106"}; + rows[2564] = new String[] {"PB", "Aguiar", "2500205"}; + rows[2565] = new String[] {"PB", "Alagoa Grande", "2500304"}; + rows[2566] = new String[] {"PB", "Alagoa Nova", "2500403"}; + rows[2567] = new String[] {"PB", "Alagoinha", "2500502"}; + rows[2568] = new String[] {"PB", "Alcantil", "2500536"}; + rows[2569] = new String[] {"PB", "Algod\u00e3o de Janda\u00edra", "2500577"}; + rows[2570] = new String[] {"PB", "Alhandra", "2500601"}; + rows[2571] = new String[] {"PB", "Amparo", "2500734"}; + rows[2572] = new String[] {"PB", "Aparecida", "2500775"}; + rows[2573] = new String[] {"PB", "Ara\u00e7agi", "2500809"}; + rows[2574] = new String[] {"PB", "Arara", "2500908"}; + rows[2575] = new String[] {"PB", "Araruna", "2501005"}; + rows[2576] = new String[] {"PB", "Areia", "2501104"}; + rows[2577] = new String[] {"PB", "Areia de Bara\u00fanas", "2501153"}; + rows[2578] = new String[] {"PB", "Areial", "2501203"}; + rows[2579] = new String[] {"PB", "Aroeiras", "2501302"}; + rows[2580] = new String[] {"PB", "Assun\u00e7\u00e3o", "2501351"}; + rows[2581] = new String[] {"PB", "Ba\u00eda da Trai\u00e7\u00e3o", "2501401"}; + rows[2582] = new String[] {"PB", "Bananeiras", "2501500"}; + rows[2583] = new String[] {"PB", "Bara\u00fana", "2501534"}; + rows[2584] = new String[] {"PB", "Barra de Santa Rosa", "2501609"}; + rows[2585] = new String[] {"PB", "Barra de Santana", "2501575"}; + rows[2586] = new String[] {"PB", "Barra de S\u00e3o Miguel", "2501708"}; + rows[2587] = new String[] {"PB", "Bayeux", "2501807"}; + rows[2588] = new String[] {"PB", "Bel\u00e9m", "2501906"}; + rows[2589] = new String[] {"PB", "Bel\u00e9m do Brejo do Cruz", "2502003"}; + rows[2590] = new String[] {"PB", "Bernardino Batista", "2502052"}; + rows[2591] = new String[] {"PB", "Boa Ventura", "2502102"}; + rows[2592] = new String[] {"PB", "Boa Vista", "2502151"}; + rows[2593] = new String[] {"PB", "Bom Jesus", "2502201"}; + rows[2594] = new String[] {"PB", "Bom Sucesso", "2502300"}; + rows[2595] = new String[] {"PB", "Bonito de Santa F\u00e9", "2502409"}; + rows[2596] = new String[] {"PB", "Boqueir\u00e3o", "2502508"}; + rows[2597] = new String[] {"PB", "Borborema", "2502706"}; + rows[2598] = new String[] {"PB", "Brejo do Cruz", "2502805"}; + rows[2599] = new String[] {"PB", "Brejo dos Santos", "2502904"}; + } + + private static void municipalitiesRows13(String[][] rows) { + rows[2600] = new String[] {"PB", "Caapor\u00e3", "2503001"}; + rows[2601] = new String[] {"PB", "Cabaceiras", "2503100"}; + rows[2602] = new String[] {"PB", "Cabedelo", "2503209"}; + rows[2603] = new String[] {"PB", "Cachoeira dos \u00cdndios", "2503308"}; + rows[2604] = new String[] {"PB", "Cacimba de Areia", "2503407"}; + rows[2605] = new String[] {"PB", "Cacimba de Dentro", "2503506"}; + rows[2606] = new String[] {"PB", "Cacimbas", "2503555"}; + rows[2607] = new String[] {"PB", "Cai\u00e7ara", "2503605"}; + rows[2608] = new String[] {"PB", "Cajazeiras", "2503704"}; + rows[2609] = new String[] {"PB", "Cajazeirinhas", "2503753"}; + rows[2610] = new String[] {"PB", "Caldas Brand\u00e3o", "2503803"}; + rows[2611] = new String[] {"PB", "Camala\u00fa", "2503902"}; + rows[2612] = new String[] {"PB", "Campina Grande", "2504009"}; + rows[2613] = new String[] {"PB", "Capim", "2504033"}; + rows[2614] = new String[] {"PB", "Cara\u00fabas", "2504074"}; + rows[2615] = new String[] {"PB", "Carrapateira", "2504108"}; + rows[2616] = new String[] {"PB", "Casserengue", "2504157"}; + rows[2617] = new String[] {"PB", "Catingueira", "2504207"}; + rows[2618] = new String[] {"PB", "Catol\u00e9 do Rocha", "2504306"}; + rows[2619] = new String[] {"PB", "Caturit\u00e9", "2504355"}; + rows[2620] = new String[] {"PB", "Concei\u00e7\u00e3o", "2504405"}; + rows[2621] = new String[] {"PB", "Condado", "2504504"}; + rows[2622] = new String[] {"PB", "Conde", "2504603"}; + rows[2623] = new String[] {"PB", "Congo", "2504702"}; + rows[2624] = new String[] {"PB", "Coremas", "2504801"}; + rows[2625] = new String[] {"PB", "Coxixola", "2504850"}; + rows[2626] = new String[] {"PB", "Cruz do Esp\u00edrito Santo", "2504900"}; + rows[2627] = new String[] {"PB", "Cubati", "2505006"}; + rows[2628] = new String[] {"PB", "Cuit\u00e9", "2505105"}; + rows[2629] = new String[] {"PB", "Cuit\u00e9 de Mamanguape", "2505238"}; + rows[2630] = new String[] {"PB", "Cuitegi", "2505204"}; + rows[2631] = new String[] {"PB", "Curral de Cima", "2505279"}; + rows[2632] = new String[] {"PB", "Curral Velho", "2505303"}; + rows[2633] = new String[] {"PB", "Dami\u00e3o", "2505352"}; + rows[2634] = new String[] {"PB", "Desterro", "2505402"}; + rows[2635] = new String[] {"PB", "Diamante", "2505600"}; + rows[2636] = new String[] {"PB", "Dona In\u00eas", "2505709"}; + rows[2637] = new String[] {"PB", "Duas Estradas", "2505808"}; + rows[2638] = new String[] {"PB", "Emas", "2505907"}; + rows[2639] = new String[] {"PB", "Esperan\u00e7a", "2506004"}; + rows[2640] = new String[] {"PB", "Fagundes", "2506103"}; + rows[2641] = new String[] {"PB", "Frei Martinho", "2506202"}; + rows[2642] = new String[] {"PB", "Gado Bravo", "2506251"}; + rows[2643] = new String[] {"PB", "Guarabira", "2506301"}; + rows[2644] = new String[] {"PB", "Gurinh\u00e9m", "2506400"}; + rows[2645] = new String[] {"PB", "Gurj\u00e3o", "2506509"}; + rows[2646] = new String[] {"PB", "Ibiara", "2506608"}; + rows[2647] = new String[] {"PB", "Igaracy", "2502607"}; + rows[2648] = new String[] {"PB", "Imaculada", "2506707"}; + rows[2649] = new String[] {"PB", "Ing\u00e1", "2506806"}; + rows[2650] = new String[] {"PB", "Itabaiana", "2506905"}; + rows[2651] = new String[] {"PB", "Itaporanga", "2507002"}; + rows[2652] = new String[] {"PB", "Itapororoca", "2507101"}; + rows[2653] = new String[] {"PB", "Itatuba", "2507200"}; + rows[2654] = new String[] {"PB", "Jacara\u00fa", "2507309"}; + rows[2655] = new String[] {"PB", "Jeric\u00f3", "2507408"}; + rows[2656] = new String[] {"PB", "Jo\u00e3o Pessoa", "2507507"}; + rows[2657] = new String[] {"PB", "Joca Claudino", "2513653"}; + rows[2658] = new String[] {"PB", "Juarez T\u00e1vora", "2507606"}; + rows[2659] = new String[] {"PB", "Juazeirinho", "2507705"}; + rows[2660] = new String[] {"PB", "Junco do Serid\u00f3", "2507804"}; + rows[2661] = new String[] {"PB", "Juripiranga", "2507903"}; + rows[2662] = new String[] {"PB", "Juru", "2508000"}; + rows[2663] = new String[] {"PB", "Lagoa", "2508109"}; + rows[2664] = new String[] {"PB", "Lagoa de Dentro", "2508208"}; + rows[2665] = new String[] {"PB", "Lagoa Seca", "2508307"}; + rows[2666] = new String[] {"PB", "Lastro", "2508406"}; + rows[2667] = new String[] {"PB", "Livramento", "2508505"}; + rows[2668] = new String[] {"PB", "Logradouro", "2508554"}; + rows[2669] = new String[] {"PB", "Lucena", "2508604"}; + rows[2670] = new String[] {"PB", "M\u00e3e d'\u00c1gua", "2508703"}; + rows[2671] = new String[] {"PB", "Malta", "2508802"}; + rows[2672] = new String[] {"PB", "Mamanguape", "2508901"}; + rows[2673] = new String[] {"PB", "Mana\u00edra", "2509008"}; + rows[2674] = new String[] {"PB", "Marca\u00e7\u00e3o", "2509057"}; + rows[2675] = new String[] {"PB", "Mari", "2509107"}; + rows[2676] = new String[] {"PB", "Mariz\u00f3polis", "2509156"}; + rows[2677] = new String[] {"PB", "Massaranduba", "2509206"}; + rows[2678] = new String[] {"PB", "Mataraca", "2509305"}; + rows[2679] = new String[] {"PB", "Matinhas", "2509339"}; + rows[2680] = new String[] {"PB", "Mato Grosso", "2509370"}; + rows[2681] = new String[] {"PB", "Matur\u00e9ia", "2509396"}; + rows[2682] = new String[] {"PB", "Mogeiro", "2509404"}; + rows[2683] = new String[] {"PB", "Montadas", "2509503"}; + rows[2684] = new String[] {"PB", "Monte Horebe", "2509602"}; + rows[2685] = new String[] {"PB", "Monteiro", "2509701"}; + rows[2686] = new String[] {"PB", "Mulungu", "2509800"}; + rows[2687] = new String[] {"PB", "Natuba", "2509909"}; + rows[2688] = new String[] {"PB", "Nazarezinho", "2510006"}; + rows[2689] = new String[] {"PB", "Nova Floresta", "2510105"}; + rows[2690] = new String[] {"PB", "Nova Olinda", "2510204"}; + rows[2691] = new String[] {"PB", "Nova Palmeira", "2510303"}; + rows[2692] = new String[] {"PB", "Olho d'\u00c1gua", "2510402"}; + rows[2693] = new String[] {"PB", "Olivedos", "2510501"}; + rows[2694] = new String[] {"PB", "Ouro Velho", "2510600"}; + rows[2695] = new String[] {"PB", "Parari", "2510659"}; + rows[2696] = new String[] {"PB", "Passagem", "2510709"}; + rows[2697] = new String[] {"PB", "Patos", "2510808"}; + rows[2698] = new String[] {"PB", "Paulista", "2510907"}; + rows[2699] = new String[] {"PB", "Pedra Branca", "2511004"}; + rows[2700] = new String[] {"PB", "Pedra Lavrada", "2511103"}; + rows[2701] = new String[] {"PB", "Pedras de Fogo", "2511202"}; + rows[2702] = new String[] {"PB", "Pedro R\u00e9gis", "2512721"}; + rows[2703] = new String[] {"PB", "Pianc\u00f3", "2511301"}; + rows[2704] = new String[] {"PB", "Picu\u00ed", "2511400"}; + rows[2705] = new String[] {"PB", "Pilar", "2511509"}; + rows[2706] = new String[] {"PB", "Pil\u00f5es", "2511608"}; + rows[2707] = new String[] {"PB", "Pil\u00f5ezinhos", "2511707"}; + rows[2708] = new String[] {"PB", "Pirpirituba", "2511806"}; + rows[2709] = new String[] {"PB", "Pitimbu", "2511905"}; + rows[2710] = new String[] {"PB", "Pocinhos", "2512002"}; + rows[2711] = new String[] {"PB", "Po\u00e7o Dantas", "2512036"}; + rows[2712] = new String[] {"PB", "Po\u00e7o de Jos\u00e9 de Moura", "2512077"}; + rows[2713] = new String[] {"PB", "Pombal", "2512101"}; + rows[2714] = new String[] {"PB", "Prata", "2512200"}; + rows[2715] = new String[] {"PB", "Princesa Isabel", "2512309"}; + rows[2716] = new String[] {"PB", "Puxinan\u00e3", "2512408"}; + rows[2717] = new String[] {"PB", "Queimadas", "2512507"}; + rows[2718] = new String[] {"PB", "Quixaba", "2512606"}; + rows[2719] = new String[] {"PB", "Rem\u00edgio", "2512705"}; + rows[2720] = new String[] {"PB", "Riach\u00e3o", "2512747"}; + rows[2721] = new String[] {"PB", "Riach\u00e3o do Bacamarte", "2512754"}; + rows[2722] = new String[] {"PB", "Riach\u00e3o do Po\u00e7o", "2512762"}; + rows[2723] = new String[] {"PB", "Riacho de Santo Ant\u00f4nio", "2512788"}; + rows[2724] = new String[] {"PB", "Riacho dos Cavalos", "2512804"}; + rows[2725] = new String[] {"PB", "Rio Tinto", "2512903"}; + rows[2726] = new String[] {"PB", "Salgadinho", "2513000"}; + rows[2727] = new String[] {"PB", "Salgado de S\u00e3o F\u00e9lix", "2513109"}; + rows[2728] = new String[] {"PB", "Santa Cec\u00edlia", "2513158"}; + rows[2729] = new String[] {"PB", "Santa Cruz", "2513208"}; + rows[2730] = new String[] {"PB", "Santa Helena", "2513307"}; + rows[2731] = new String[] {"PB", "Santa In\u00eas", "2513356"}; + rows[2732] = new String[] {"PB", "Santa Luzia", "2513406"}; + rows[2733] = new String[] {"PB", "Santa Rita", "2513703"}; + rows[2734] = new String[] {"PB", "Santa Teresinha", "2513802"}; + rows[2735] = new String[] {"PB", "Santana de Mangueira", "2513505"}; + rows[2736] = new String[] {"PB", "Santana dos Garrotes", "2513604"}; + rows[2737] = new String[] {"PB", "Santo Andr\u00e9", "2513851"}; + rows[2738] = new String[] {"PB", "S\u00e3o Bentinho", "2513927"}; + rows[2739] = new String[] {"PB", "S\u00e3o Bento", "2513901"}; + rows[2740] = new String[] {"PB", "S\u00e3o Domingos", "2513968"}; + rows[2741] = new String[] {"PB", "S\u00e3o Domingos do Cariri", "2513943"}; + rows[2742] = new String[] {"PB", "S\u00e3o Francisco", "2513984"}; + rows[2743] = new String[] {"PB", "S\u00e3o Jo\u00e3o do Cariri", "2514008"}; + rows[2744] = new String[] {"PB", "S\u00e3o Jo\u00e3o do Rio do Peixe", "2500700"}; + rows[2745] = new String[] {"PB", "S\u00e3o Jo\u00e3o do Tigre", "2514107"}; + rows[2746] = new String[] {"PB", "S\u00e3o Jos\u00e9 da Lagoa Tapada", "2514206"}; + rows[2747] = new String[] {"PB", "S\u00e3o Jos\u00e9 de Caiana", "2514305"}; + rows[2748] = new String[] {"PB", "S\u00e3o Jos\u00e9 de Espinharas", "2514404"}; + rows[2749] = new String[] {"PB", "S\u00e3o Jos\u00e9 de Piranhas", "2514503"}; + rows[2750] = new String[] {"PB", "S\u00e3o Jos\u00e9 de Princesa", "2514552"}; + rows[2751] = new String[] {"PB", "S\u00e3o Jos\u00e9 do Bonfim", "2514602"}; + rows[2752] = new String[] {"PB", "S\u00e3o Jos\u00e9 do Brejo do Cruz", "2514651"}; + rows[2753] = new String[] {"PB", "S\u00e3o Jos\u00e9 do Sabugi", "2514701"}; + rows[2754] = new String[] {"PB", "S\u00e3o Jos\u00e9 dos Cordeiros", "2514800"}; + rows[2755] = new String[] {"PB", "S\u00e3o Jos\u00e9 dos Ramos", "2514453"}; + rows[2756] = new String[] {"PB", "S\u00e3o Mamede", "2514909"}; + rows[2757] = new String[] {"PB", "S\u00e3o Miguel de Taipu", "2515005"}; + rows[2758] = new String[] {"PB", "S\u00e3o Sebasti\u00e3o de Lagoa de Ro\u00e7a", "2515104"}; + rows[2759] = new String[] {"PB", "S\u00e3o Sebasti\u00e3o do Umbuzeiro", "2515203"}; + rows[2760] = new String[] {"PB", "S\u00e3o Vicente do Serid\u00f3", "2515401"}; + rows[2761] = new String[] {"PB", "Sap\u00e9", "2515302"}; + rows[2762] = new String[] {"PB", "Serra Branca", "2515500"}; + rows[2763] = new String[] {"PB", "Serra da Raiz", "2515609"}; + rows[2764] = new String[] {"PB", "Serra Grande", "2515708"}; + rows[2765] = new String[] {"PB", "Serra Redonda", "2515807"}; + rows[2766] = new String[] {"PB", "Serraria", "2515906"}; + rows[2767] = new String[] {"PB", "Sert\u00e3ozinho", "2515930"}; + rows[2768] = new String[] {"PB", "Sobrado", "2515971"}; + rows[2769] = new String[] {"PB", "Sol\u00e2nea", "2516003"}; + rows[2770] = new String[] {"PB", "Soledade", "2516102"}; + rows[2771] = new String[] {"PB", "Soss\u00eago", "2516151"}; + rows[2772] = new String[] {"PB", "Sousa", "2516201"}; + rows[2773] = new String[] {"PB", "Sum\u00e9", "2516300"}; + rows[2774] = new String[] {"PB", "Tacima", "2516409"}; + rows[2775] = new String[] {"PB", "Tapero\u00e1", "2516508"}; + rows[2776] = new String[] {"PB", "Tavares", "2516607"}; + rows[2777] = new String[] {"PB", "Teixeira", "2516706"}; + rows[2778] = new String[] {"PB", "Ten\u00f3rio", "2516755"}; + rows[2779] = new String[] {"PB", "Triunfo", "2516805"}; + rows[2780] = new String[] {"PB", "Uira\u00fana", "2516904"}; + rows[2781] = new String[] {"PB", "Umbuzeiro", "2517001"}; + rows[2782] = new String[] {"PB", "V\u00e1rzea", "2517100"}; + rows[2783] = new String[] {"PB", "Vieir\u00f3polis", "2517209"}; + rows[2784] = new String[] {"PB", "Vista Serrana", "2505501"}; + rows[2785] = new String[] {"PB", "Zabel\u00ea", "2517407"}; + rows[2786] = new String[] {"PR", "Abati\u00e1", "4100103"}; + rows[2787] = new String[] {"PR", "Adrian\u00f3polis", "4100202"}; + rows[2788] = new String[] {"PR", "Agudos do Sul", "4100301"}; + rows[2789] = new String[] {"PR", "Almirante Tamandar\u00e9", "4100400"}; + rows[2790] = new String[] {"PR", "Altamira do Paran\u00e1", "4100459"}; + rows[2791] = new String[] {"PR", "Alto Para\u00edso", "4128625"}; + rows[2792] = new String[] {"PR", "Alto Paran\u00e1", "4100608"}; + rows[2793] = new String[] {"PR", "Alto Piquiri", "4100707"}; + rows[2794] = new String[] {"PR", "Alt\u00f4nia", "4100509"}; + rows[2795] = new String[] {"PR", "Alvorada do Sul", "4100806"}; + rows[2796] = new String[] {"PR", "Amapor\u00e3", "4100905"}; + rows[2797] = new String[] {"PR", "Amp\u00e9re", "4101002"}; + rows[2798] = new String[] {"PR", "Anahy", "4101051"}; + rows[2799] = new String[] {"PR", "Andir\u00e1", "4101101"}; + } + + private static void municipalitiesRows14(String[][] rows) { + rows[2800] = new String[] {"PR", "\u00c2ngulo", "4101150"}; + rows[2801] = new String[] {"PR", "Antonina", "4101200"}; + rows[2802] = new String[] {"PR", "Ant\u00f4nio Olinto", "4101309"}; + rows[2803] = new String[] {"PR", "Apucarana", "4101408"}; + rows[2804] = new String[] {"PR", "Arapongas", "4101507"}; + rows[2805] = new String[] {"PR", "Arapoti", "4101606"}; + rows[2806] = new String[] {"PR", "Arapu\u00e3", "4101655"}; + rows[2807] = new String[] {"PR", "Araruna", "4101705"}; + rows[2808] = new String[] {"PR", "Arauc\u00e1ria", "4101804"}; + rows[2809] = new String[] {"PR", "Ariranha do Iva\u00ed", "4101853"}; + rows[2810] = new String[] {"PR", "Assa\u00ed", "4101903"}; + rows[2811] = new String[] {"PR", "Assis Chateaubriand", "4102000"}; + rows[2812] = new String[] {"PR", "Astorga", "4102109"}; + rows[2813] = new String[] {"PR", "Atalaia", "4102208"}; + rows[2814] = new String[] {"PR", "Balsa Nova", "4102307"}; + rows[2815] = new String[] {"PR", "Bandeirantes", "4102406"}; + rows[2816] = new String[] {"PR", "Barbosa Ferraz", "4102505"}; + rows[2817] = new String[] {"PR", "Barra do Jacar\u00e9", "4102703"}; + rows[2818] = new String[] {"PR", "Barrac\u00e3o", "4102604"}; + rows[2819] = new String[] {"PR", "Bela Vista da Caroba", "4102752"}; + rows[2820] = new String[] {"PR", "Bela Vista do Para\u00edso", "4102802"}; + rows[2821] = new String[] {"PR", "Bituruna", "4102901"}; + rows[2822] = new String[] {"PR", "Boa Esperan\u00e7a", "4103008"}; + rows[2823] = new String[] {"PR", "Boa Esperan\u00e7a do Igua\u00e7u", "4103024"}; + rows[2824] = new String[] {"PR", "Boa Ventura de S\u00e3o Roque", "4103040"}; + rows[2825] = new String[] {"PR", "Boa Vista da Aparecida", "4103057"}; + rows[2826] = new String[] {"PR", "Bocai\u00fava do Sul", "4103107"}; + rows[2827] = new String[] {"PR", "Bom Jesus do Sul", "4103156"}; + rows[2828] = new String[] {"PR", "Bom Sucesso", "4103206"}; + rows[2829] = new String[] {"PR", "Bom Sucesso do Sul", "4103222"}; + rows[2830] = new String[] {"PR", "Borraz\u00f3polis", "4103305"}; + rows[2831] = new String[] {"PR", "Braganey", "4103354"}; + rows[2832] = new String[] {"PR", "Brasil\u00e2ndia do Sul", "4103370"}; + rows[2833] = new String[] {"PR", "Cafeara", "4103404"}; + rows[2834] = new String[] {"PR", "Cafel\u00e2ndia", "4103453"}; + rows[2835] = new String[] {"PR", "Cafezal do Sul", "4103479"}; + rows[2836] = new String[] {"PR", "Calif\u00f3rnia", "4103503"}; + rows[2837] = new String[] {"PR", "Cambar\u00e1", "4103602"}; + rows[2838] = new String[] {"PR", "Camb\u00e9", "4103701"}; + rows[2839] = new String[] {"PR", "Cambira", "4103800"}; + rows[2840] = new String[] {"PR", "Campina da Lagoa", "4103909"}; + rows[2841] = new String[] {"PR", "Campina do Sim\u00e3o", "4103958"}; + rows[2842] = new String[] {"PR", "Campina Grande do Sul", "4104006"}; + rows[2843] = new String[] {"PR", "Campo Bonito", "4104055"}; + rows[2844] = new String[] {"PR", "Campo do Tenente", "4104105"}; + rows[2845] = new String[] {"PR", "Campo Largo", "4104204"}; + rows[2846] = new String[] {"PR", "Campo Magro", "4104253"}; + rows[2847] = new String[] {"PR", "Campo Mour\u00e3o", "4104303"}; + rows[2848] = new String[] {"PR", "C\u00e2ndido de Abreu", "4104402"}; + rows[2849] = new String[] {"PR", "Cand\u00f3i", "4104428"}; + rows[2850] = new String[] {"PR", "Cantagalo", "4104451"}; + rows[2851] = new String[] {"PR", "Capanema", "4104501"}; + rows[2852] = new String[] {"PR", "Capit\u00e3o Le\u00f4nidas Marques", "4104600"}; + rows[2853] = new String[] {"PR", "Carambe\u00ed", "4104659"}; + rows[2854] = new String[] {"PR", "Carl\u00f3polis", "4104709"}; + rows[2855] = new String[] {"PR", "Cascavel", "4104808"}; + rows[2856] = new String[] {"PR", "Castro", "4104907"}; + rows[2857] = new String[] {"PR", "Catanduvas", "4105003"}; + rows[2858] = new String[] {"PR", "Centen\u00e1rio do Sul", "4105102"}; + rows[2859] = new String[] {"PR", "Cerro Azul", "4105201"}; + rows[2860] = new String[] {"PR", "C\u00e9u Azul", "4105300"}; + rows[2861] = new String[] {"PR", "Chopinzinho", "4105409"}; + rows[2862] = new String[] {"PR", "Cianorte", "4105508"}; + rows[2863] = new String[] {"PR", "Cidade Ga\u00facha", "4105607"}; + rows[2864] = new String[] {"PR", "Clevel\u00e2ndia", "4105706"}; + rows[2865] = new String[] {"PR", "Colombo", "4105805"}; + rows[2866] = new String[] {"PR", "Colorado", "4105904"}; + rows[2867] = new String[] {"PR", "Congonhinhas", "4106001"}; + rows[2868] = new String[] {"PR", "Conselheiro Mairinck", "4106100"}; + rows[2869] = new String[] {"PR", "Contenda", "4106209"}; + rows[2870] = new String[] {"PR", "Corb\u00e9lia", "4106308"}; + rows[2871] = new String[] {"PR", "Corn\u00e9lio Proc\u00f3pio", "4106407"}; + rows[2872] = new String[] {"PR", "Coronel Domingos Soares", "4106456"}; + rows[2873] = new String[] {"PR", "Coronel Vivida", "4106506"}; + rows[2874] = new String[] {"PR", "Corumbata\u00ed do Sul", "4106555"}; + rows[2875] = new String[] {"PR", "Cruz Machado", "4106803"}; + rows[2876] = new String[] {"PR", "Cruzeiro do Igua\u00e7u", "4106571"}; + rows[2877] = new String[] {"PR", "Cruzeiro do Oeste", "4106605"}; + rows[2878] = new String[] {"PR", "Cruzeiro do Sul", "4106704"}; + rows[2879] = new String[] {"PR", "Cruzmaltina", "4106852"}; + rows[2880] = new String[] {"PR", "Curitiba", "4106902"}; + rows[2881] = new String[] {"PR", "Curi\u00fava", "4107009"}; + rows[2882] = new String[] {"PR", "Diamante D'Oeste", "4107157"}; + rows[2883] = new String[] {"PR", "Diamante do Norte", "4107108"}; + rows[2884] = new String[] {"PR", "Diamante do Sul", "4107124"}; + rows[2885] = new String[] {"PR", "Dois Vizinhos", "4107207"}; + rows[2886] = new String[] {"PR", "Douradina", "4107256"}; + rows[2887] = new String[] {"PR", "Doutor Camargo", "4107306"}; + rows[2888] = new String[] {"PR", "Doutor Ulysses", "4128633"}; + rows[2889] = new String[] {"PR", "En\u00e9as Marques", "4107405"}; + rows[2890] = new String[] {"PR", "Engenheiro Beltr\u00e3o", "4107504"}; + rows[2891] = new String[] {"PR", "Entre Rios do Oeste", "4107538"}; + rows[2892] = new String[] {"PR", "Esperan\u00e7a Nova", "4107520"}; + rows[2893] = new String[] {"PR", "Espig\u00e3o Alto do Igua\u00e7u", "4107546"}; + rows[2894] = new String[] {"PR", "Farol", "4107553"}; + rows[2895] = new String[] {"PR", "Faxinal", "4107603"}; + rows[2896] = new String[] {"PR", "Fazenda Rio Grande", "4107652"}; + rows[2897] = new String[] {"PR", "F\u00eanix", "4107702"}; + rows[2898] = new String[] {"PR", "Fernandes Pinheiro", "4107736"}; + rows[2899] = new String[] {"PR", "Figueira", "4107751"}; + rows[2900] = new String[] {"PR", "Flor da Serra do Sul", "4107850"}; + rows[2901] = new String[] {"PR", "Flora\u00ed", "4107801"}; + rows[2902] = new String[] {"PR", "Floresta", "4107900"}; + rows[2903] = new String[] {"PR", "Florest\u00f3polis", "4108007"}; + rows[2904] = new String[] {"PR", "Fl\u00f3rida", "4108106"}; + rows[2905] = new String[] {"PR", "Formosa do Oeste", "4108205"}; + rows[2906] = new String[] {"PR", "Foz do Igua\u00e7u", "4108304"}; + rows[2907] = new String[] {"PR", "Foz do Jord\u00e3o", "4108452"}; + rows[2908] = new String[] {"PR", "Francisco Alves", "4108320"}; + rows[2909] = new String[] {"PR", "Francisco Beltr\u00e3o", "4108403"}; + rows[2910] = new String[] {"PR", "General Carneiro", "4108502"}; + rows[2911] = new String[] {"PR", "Godoy Moreira", "4108551"}; + rows[2912] = new String[] {"PR", "Goioer\u00ea", "4108601"}; + rows[2913] = new String[] {"PR", "Goioxim", "4108650"}; + rows[2914] = new String[] {"PR", "Grandes Rios", "4108700"}; + rows[2915] = new String[] {"PR", "Gua\u00edra", "4108809"}; + rows[2916] = new String[] {"PR", "Guaira\u00e7\u00e1", "4108908"}; + rows[2917] = new String[] {"PR", "Guamiranga", "4108957"}; + rows[2918] = new String[] {"PR", "Guapirama", "4109005"}; + rows[2919] = new String[] {"PR", "Guaporema", "4109104"}; + rows[2920] = new String[] {"PR", "Guaraci", "4109203"}; + rows[2921] = new String[] {"PR", "Guarania\u00e7u", "4109302"}; + rows[2922] = new String[] {"PR", "Guarapuava", "4109401"}; + rows[2923] = new String[] {"PR", "Guaraque\u00e7aba", "4109500"}; + rows[2924] = new String[] {"PR", "Guaratuba", "4109609"}; + rows[2925] = new String[] {"PR", "Hon\u00f3rio Serpa", "4109658"}; + rows[2926] = new String[] {"PR", "Ibaiti", "4109708"}; + rows[2927] = new String[] {"PR", "Ibema", "4109757"}; + rows[2928] = new String[] {"PR", "Ibipor\u00e3", "4109807"}; + rows[2929] = new String[] {"PR", "Icara\u00edma", "4109906"}; + rows[2930] = new String[] {"PR", "Iguara\u00e7u", "4110003"}; + rows[2931] = new String[] {"PR", "Iguatu", "4110052"}; + rows[2932] = new String[] {"PR", "Imba\u00fa", "4110078"}; + rows[2933] = new String[] {"PR", "Imbituva", "4110102"}; + rows[2934] = new String[] {"PR", "In\u00e1cio Martins", "4110201"}; + rows[2935] = new String[] {"PR", "Inaj\u00e1", "4110300"}; + rows[2936] = new String[] {"PR", "Indian\u00f3polis", "4110409"}; + rows[2937] = new String[] {"PR", "Ipiranga", "4110508"}; + rows[2938] = new String[] {"PR", "Ipor\u00e3", "4110607"}; + rows[2939] = new String[] {"PR", "Iracema do Oeste", "4110656"}; + rows[2940] = new String[] {"PR", "Irati", "4110706"}; + rows[2941] = new String[] {"PR", "Iretama", "4110805"}; + rows[2942] = new String[] {"PR", "Itaguaj\u00e9", "4110904"}; + rows[2943] = new String[] {"PR", "Itaipul\u00e2ndia", "4110953"}; + rows[2944] = new String[] {"PR", "Itambarac\u00e1", "4111001"}; + rows[2945] = new String[] {"PR", "Itamb\u00e9", "4111100"}; + rows[2946] = new String[] {"PR", "Itapejara d'Oeste", "4111209"}; + rows[2947] = new String[] {"PR", "Itaperu\u00e7u", "4111258"}; + rows[2948] = new String[] {"PR", "Ita\u00fana do Sul", "4111308"}; + rows[2949] = new String[] {"PR", "Iva\u00ed", "4111407"}; + rows[2950] = new String[] {"PR", "Ivaipor\u00e3", "4111506"}; + rows[2951] = new String[] {"PR", "Ivat\u00e9", "4111555"}; + rows[2952] = new String[] {"PR", "Ivatuba", "4111605"}; + rows[2953] = new String[] {"PR", "Jaboti", "4111704"}; + rows[2954] = new String[] {"PR", "Jacarezinho", "4111803"}; + rows[2955] = new String[] {"PR", "Jaguapit\u00e3", "4111902"}; + rows[2956] = new String[] {"PR", "Jaguaria\u00edva", "4112009"}; + rows[2957] = new String[] {"PR", "Jandaia do Sul", "4112108"}; + rows[2958] = new String[] {"PR", "Jani\u00f3polis", "4112207"}; + rows[2959] = new String[] {"PR", "Japira", "4112306"}; + rows[2960] = new String[] {"PR", "Japur\u00e1", "4112405"}; + rows[2961] = new String[] {"PR", "Jardim Alegre", "4112504"}; + rows[2962] = new String[] {"PR", "Jardim Olinda", "4112603"}; + rows[2963] = new String[] {"PR", "Jataizinho", "4112702"}; + rows[2964] = new String[] {"PR", "Jesu\u00edtas", "4112751"}; + rows[2965] = new String[] {"PR", "Joaquim T\u00e1vora", "4112801"}; + rows[2966] = new String[] {"PR", "Jundia\u00ed do Sul", "4112900"}; + rows[2967] = new String[] {"PR", "Juranda", "4112959"}; + rows[2968] = new String[] {"PR", "Jussara", "4113007"}; + rows[2969] = new String[] {"PR", "Kalor\u00e9", "4113106"}; + rows[2970] = new String[] {"PR", "Lapa", "4113205"}; + rows[2971] = new String[] {"PR", "Laranjal", "4113254"}; + rows[2972] = new String[] {"PR", "Laranjeiras do Sul", "4113304"}; + rows[2973] = new String[] {"PR", "Le\u00f3polis", "4113403"}; + rows[2974] = new String[] {"PR", "Lidian\u00f3polis", "4113429"}; + rows[2975] = new String[] {"PR", "Lindoeste", "4113452"}; + rows[2976] = new String[] {"PR", "Loanda", "4113502"}; + rows[2977] = new String[] {"PR", "Lobato", "4113601"}; + rows[2978] = new String[] {"PR", "Londrina", "4113700"}; + rows[2979] = new String[] {"PR", "Luiziana", "4113734"}; + rows[2980] = new String[] {"PR", "Lunardelli", "4113759"}; + rows[2981] = new String[] {"PR", "Lupion\u00f3polis", "4113809"}; + rows[2982] = new String[] {"PR", "Mallet", "4113908"}; + rows[2983] = new String[] {"PR", "Mambor\u00ea", "4114005"}; + rows[2984] = new String[] {"PR", "Mandagua\u00e7u", "4114104"}; + rows[2985] = new String[] {"PR", "Mandaguari", "4114203"}; + rows[2986] = new String[] {"PR", "Mandirituba", "4114302"}; + rows[2987] = new String[] {"PR", "Manfrin\u00f3polis", "4114351"}; + rows[2988] = new String[] {"PR", "Mangueirinha", "4114401"}; + rows[2989] = new String[] {"PR", "Manoel Ribas", "4114500"}; + rows[2990] = new String[] {"PR", "Marechal C\u00e2ndido Rondon", "4114609"}; + rows[2991] = new String[] {"PR", "Maria Helena", "4114708"}; + rows[2992] = new String[] {"PR", "Marialva", "4114807"}; + rows[2993] = new String[] {"PR", "Maril\u00e2ndia do Sul", "4114906"}; + rows[2994] = new String[] {"PR", "Marilena", "4115002"}; + rows[2995] = new String[] {"PR", "Mariluz", "4115101"}; + rows[2996] = new String[] {"PR", "Maring\u00e1", "4115200"}; + rows[2997] = new String[] {"PR", "Mari\u00f3polis", "4115309"}; + rows[2998] = new String[] {"PR", "Marip\u00e1", "4115358"}; + rows[2999] = new String[] {"PR", "Marmeleiro", "4115408"}; + } + + private static void municipalitiesRows15(String[][] rows) { + rows[3000] = new String[] {"PR", "Marquinho", "4115457"}; + rows[3001] = new String[] {"PR", "Marumbi", "4115507"}; + rows[3002] = new String[] {"PR", "Matel\u00e2ndia", "4115606"}; + rows[3003] = new String[] {"PR", "Matinhos", "4115705"}; + rows[3004] = new String[] {"PR", "Mato Rico", "4115739"}; + rows[3005] = new String[] {"PR", "Mau\u00e1 da Serra", "4115754"}; + rows[3006] = new String[] {"PR", "Medianeira", "4115804"}; + rows[3007] = new String[] {"PR", "Mercedes", "4115853"}; + rows[3008] = new String[] {"PR", "Mirador", "4115903"}; + rows[3009] = new String[] {"PR", "Miraselva", "4116000"}; + rows[3010] = new String[] {"PR", "Missal", "4116059"}; + rows[3011] = new String[] {"PR", "Moreira Sales", "4116109"}; + rows[3012] = new String[] {"PR", "Morretes", "4116208"}; + rows[3013] = new String[] {"PR", "Munhoz de Melo", "4116307"}; + rows[3014] = new String[] {"PR", "Nossa Senhora das Gra\u00e7as", "4116406"}; + rows[3015] = new String[] {"PR", "Nova Alian\u00e7a do Iva\u00ed", "4116505"}; + rows[3016] = new String[] {"PR", "Nova Am\u00e9rica da Colina", "4116604"}; + rows[3017] = new String[] {"PR", "Nova Aurora", "4116703"}; + rows[3018] = new String[] {"PR", "Nova Cantu", "4116802"}; + rows[3019] = new String[] {"PR", "Nova Esperan\u00e7a", "4116901"}; + rows[3020] = new String[] {"PR", "Nova Esperan\u00e7a do Sudoeste", "4116950"}; + rows[3021] = new String[] {"PR", "Nova F\u00e1tima", "4117008"}; + rows[3022] = new String[] {"PR", "Nova Laranjeiras", "4117057"}; + rows[3023] = new String[] {"PR", "Nova Londrina", "4117107"}; + rows[3024] = new String[] {"PR", "Nova Ol\u00edmpia", "4117206"}; + rows[3025] = new String[] {"PR", "Nova Prata do Igua\u00e7u", "4117255"}; + rows[3026] = new String[] {"PR", "Nova Santa B\u00e1rbara", "4117214"}; + rows[3027] = new String[] {"PR", "Nova Santa Rosa", "4117222"}; + rows[3028] = new String[] {"PR", "Nova Tebas", "4117271"}; + rows[3029] = new String[] {"PR", "Novo Itacolomi", "4117297"}; + rows[3030] = new String[] {"PR", "Ortigueira", "4117305"}; + rows[3031] = new String[] {"PR", "Ourizona", "4117404"}; + rows[3032] = new String[] {"PR", "Ouro Verde do Oeste", "4117453"}; + rows[3033] = new String[] {"PR", "Pai\u00e7andu", "4117503"}; + rows[3034] = new String[] {"PR", "Palmas", "4117602"}; + rows[3035] = new String[] {"PR", "Palmeira", "4117701"}; + rows[3036] = new String[] {"PR", "Palmital", "4117800"}; + rows[3037] = new String[] {"PR", "Palotina", "4117909"}; + rows[3038] = new String[] {"PR", "Para\u00edso do Norte", "4118006"}; + rows[3039] = new String[] {"PR", "Paranacity", "4118105"}; + rows[3040] = new String[] {"PR", "Paranagu\u00e1", "4118204"}; + rows[3041] = new String[] {"PR", "Paranapoema", "4118303"}; + rows[3042] = new String[] {"PR", "Paranava\u00ed", "4118402"}; + rows[3043] = new String[] {"PR", "Pato Bragado", "4118451"}; + rows[3044] = new String[] {"PR", "Pato Branco", "4118501"}; + rows[3045] = new String[] {"PR", "Paula Freitas", "4118600"}; + rows[3046] = new String[] {"PR", "Paulo Frontin", "4118709"}; + rows[3047] = new String[] {"PR", "Peabiru", "4118808"}; + rows[3048] = new String[] {"PR", "Perobal", "4118857"}; + rows[3049] = new String[] {"PR", "P\u00e9rola", "4118907"}; + rows[3050] = new String[] {"PR", "P\u00e9rola d'Oeste", "4119004"}; + rows[3051] = new String[] {"PR", "Pi\u00ean", "4119103"}; + rows[3052] = new String[] {"PR", "Pinhais", "4119152"}; + rows[3053] = new String[] {"PR", "Pinhal de S\u00e3o Bento", "4119251"}; + rows[3054] = new String[] {"PR", "Pinhal\u00e3o", "4119202"}; + rows[3055] = new String[] {"PR", "Pinh\u00e3o", "4119301"}; + rows[3056] = new String[] {"PR", "Pira\u00ed do Sul", "4119400"}; + rows[3057] = new String[] {"PR", "Piraquara", "4119509"}; + rows[3058] = new String[] {"PR", "Pitanga", "4119608"}; + rows[3059] = new String[] {"PR", "Pitangueiras", "4119657"}; + rows[3060] = new String[] {"PR", "Planaltina do Paran\u00e1", "4119707"}; + rows[3061] = new String[] {"PR", "Planalto", "4119806"}; + rows[3062] = new String[] {"PR", "Ponta Grossa", "4119905"}; + rows[3063] = new String[] {"PR", "Pontal do Paran\u00e1", "4119954"}; + rows[3064] = new String[] {"PR", "Porecatu", "4120002"}; + rows[3065] = new String[] {"PR", "Porto Amazonas", "4120101"}; + rows[3066] = new String[] {"PR", "Porto Barreiro", "4120150"}; + rows[3067] = new String[] {"PR", "Porto Rico", "4120200"}; + rows[3068] = new String[] {"PR", "Porto Vit\u00f3ria", "4120309"}; + rows[3069] = new String[] {"PR", "Prado Ferreira", "4120333"}; + rows[3070] = new String[] {"PR", "Pranchita", "4120358"}; + rows[3071] = new String[] {"PR", "Presidente Castelo Branco", "4120408"}; + rows[3072] = new String[] {"PR", "Primeiro de Maio", "4120507"}; + rows[3073] = new String[] {"PR", "Prudent\u00f3polis", "4120606"}; + rows[3074] = new String[] {"PR", "Quarto Centen\u00e1rio", "4120655"}; + rows[3075] = new String[] {"PR", "Quatigu\u00e1", "4120705"}; + rows[3076] = new String[] {"PR", "Quatro Barras", "4120804"}; + rows[3077] = new String[] {"PR", "Quatro Pontes", "4120853"}; + rows[3078] = new String[] {"PR", "Quedas do Igua\u00e7u", "4120903"}; + rows[3079] = new String[] {"PR", "Quer\u00eancia do Norte", "4121000"}; + rows[3080] = new String[] {"PR", "Quinta do Sol", "4121109"}; + rows[3081] = new String[] {"PR", "Quitandinha", "4121208"}; + rows[3082] = new String[] {"PR", "Ramil\u00e2ndia", "4121257"}; + rows[3083] = new String[] {"PR", "Rancho Alegre", "4121307"}; + rows[3084] = new String[] {"PR", "Rancho Alegre D'Oeste", "4121356"}; + rows[3085] = new String[] {"PR", "Realeza", "4121406"}; + rows[3086] = new String[] {"PR", "Rebou\u00e7as", "4121505"}; + rows[3087] = new String[] {"PR", "Renascen\u00e7a", "4121604"}; + rows[3088] = new String[] {"PR", "Reserva", "4121703"}; + rows[3089] = new String[] {"PR", "Reserva do Igua\u00e7u", "4121752"}; + rows[3090] = new String[] {"PR", "Ribeir\u00e3o Claro", "4121802"}; + rows[3091] = new String[] {"PR", "Ribeir\u00e3o do Pinhal", "4121901"}; + rows[3092] = new String[] {"PR", "Rio Azul", "4122008"}; + rows[3093] = new String[] {"PR", "Rio Bom", "4122107"}; + rows[3094] = new String[] {"PR", "Rio Bonito do Igua\u00e7u", "4122156"}; + rows[3095] = new String[] {"PR", "Rio Branco do Iva\u00ed", "4122172"}; + rows[3096] = new String[] {"PR", "Rio Branco do Sul", "4122206"}; + rows[3097] = new String[] {"PR", "Rio Negro", "4122305"}; + rows[3098] = new String[] {"PR", "Rol\u00e2ndia", "4122404"}; + rows[3099] = new String[] {"PR", "Roncador", "4122503"}; + rows[3100] = new String[] {"PR", "Rondon", "4122602"}; + rows[3101] = new String[] {"PR", "Ros\u00e1rio do Iva\u00ed", "4122651"}; + rows[3102] = new String[] {"PR", "Sab\u00e1udia", "4122701"}; + rows[3103] = new String[] {"PR", "Salgado Filho", "4122800"}; + rows[3104] = new String[] {"PR", "Salto do Itarar\u00e9", "4122909"}; + rows[3105] = new String[] {"PR", "Salto do Lontra", "4123006"}; + rows[3106] = new String[] {"PR", "Santa Am\u00e9lia", "4123105"}; + rows[3107] = new String[] {"PR", "Santa Cec\u00edlia do Pav\u00e3o", "4123204"}; + rows[3108] = new String[] {"PR", "Santa Cruz de Monte Castelo", "4123303"}; + rows[3109] = new String[] {"PR", "Santa F\u00e9", "4123402"}; + rows[3110] = new String[] {"PR", "Santa Helena", "4123501"}; + rows[3111] = new String[] {"PR", "Santa In\u00eas", "4123600"}; + rows[3112] = new String[] {"PR", "Santa Isabel do Iva\u00ed", "4123709"}; + rows[3113] = new String[] {"PR", "Santa Izabel do Oeste", "4123808"}; + rows[3114] = new String[] {"PR", "Santa L\u00facia", "4123824"}; + rows[3115] = new String[] {"PR", "Santa Maria do Oeste", "4123857"}; + rows[3116] = new String[] {"PR", "Santa Mariana", "4123907"}; + rows[3117] = new String[] {"PR", "Santa M\u00f4nica", "4123956"}; + rows[3118] = new String[] {"PR", "Santa Tereza do Oeste", "4124020"}; + rows[3119] = new String[] {"PR", "Santa Terezinha de Itaipu", "4124053"}; + rows[3120] = new String[] {"PR", "Santana do Itarar\u00e9", "4124004"}; + rows[3121] = new String[] {"PR", "Santo Ant\u00f4nio da Platina", "4124103"}; + rows[3122] = new String[] {"PR", "Santo Ant\u00f4nio do Caiu\u00e1", "4124202"}; + rows[3123] = new String[] {"PR", "Santo Ant\u00f4nio do Para\u00edso", "4124301"}; + rows[3124] = new String[] {"PR", "Santo Ant\u00f4nio do Sudoeste", "4124400"}; + rows[3125] = new String[] {"PR", "Santo In\u00e1cio", "4124509"}; + rows[3126] = new String[] {"PR", "S\u00e3o Carlos do Iva\u00ed", "4124608"}; + rows[3127] = new String[] {"PR", "S\u00e3o Jer\u00f4nimo da Serra", "4124707"}; + rows[3128] = new String[] {"PR", "S\u00e3o Jo\u00e3o", "4124806"}; + rows[3129] = new String[] {"PR", "S\u00e3o Jo\u00e3o do Caiu\u00e1", "4124905"}; + rows[3130] = new String[] {"PR", "S\u00e3o Jo\u00e3o do Iva\u00ed", "4125001"}; + rows[3131] = new String[] {"PR", "S\u00e3o Jo\u00e3o do Triunfo", "4125100"}; + rows[3132] = new String[] {"PR", "S\u00e3o Jorge d'Oeste", "4125209"}; + rows[3133] = new String[] {"PR", "S\u00e3o Jorge do Iva\u00ed", "4125308"}; + rows[3134] = new String[] {"PR", "S\u00e3o Jorge do Patroc\u00ednio", "4125357"}; + rows[3135] = new String[] {"PR", "S\u00e3o Jos\u00e9 da Boa Vista", "4125407"}; + rows[3136] = new String[] {"PR", "S\u00e3o Jos\u00e9 das Palmeiras", "4125456"}; + rows[3137] = new String[] {"PR", "S\u00e3o Jos\u00e9 dos Pinhais", "4125506"}; + rows[3138] = new String[] {"PR", "S\u00e3o Manoel do Paran\u00e1", "4125555"}; + rows[3139] = new String[] {"PR", "S\u00e3o Mateus do Sul", "4125605"}; + rows[3140] = new String[] {"PR", "S\u00e3o Miguel do Igua\u00e7u", "4125704"}; + rows[3141] = new String[] {"PR", "S\u00e3o Pedro do Igua\u00e7u", "4125753"}; + rows[3142] = new String[] {"PR", "S\u00e3o Pedro do Iva\u00ed", "4125803"}; + rows[3143] = new String[] {"PR", "S\u00e3o Pedro do Paran\u00e1", "4125902"}; + rows[3144] = new String[] {"PR", "S\u00e3o Sebasti\u00e3o da Amoreira", "4126009"}; + rows[3145] = new String[] {"PR", "S\u00e3o Tom\u00e9", "4126108"}; + rows[3146] = new String[] {"PR", "Sapopema", "4126207"}; + rows[3147] = new String[] {"PR", "Sarandi", "4126256"}; + rows[3148] = new String[] {"PR", "Saudade do Igua\u00e7u", "4126272"}; + rows[3149] = new String[] {"PR", "Seng\u00e9s", "4126306"}; + rows[3150] = new String[] {"PR", "Serran\u00f3polis do Igua\u00e7u", "4126355"}; + rows[3151] = new String[] {"PR", "Sertaneja", "4126405"}; + rows[3152] = new String[] {"PR", "Sertan\u00f3polis", "4126504"}; + rows[3153] = new String[] {"PR", "Siqueira Campos", "4126603"}; + rows[3154] = new String[] {"PR", "Sulina", "4126652"}; + rows[3155] = new String[] {"PR", "Tamarana", "4126678"}; + rows[3156] = new String[] {"PR", "Tamboara", "4126702"}; + rows[3157] = new String[] {"PR", "Tapejara", "4126801"}; + rows[3158] = new String[] {"PR", "Tapira", "4126900"}; + rows[3159] = new String[] {"PR", "Teixeira Soares", "4127007"}; + rows[3160] = new String[] {"PR", "Tel\u00eamaco Borba", "4127106"}; + rows[3161] = new String[] {"PR", "Terra Boa", "4127205"}; + rows[3162] = new String[] {"PR", "Terra Rica", "4127304"}; + rows[3163] = new String[] {"PR", "Terra Roxa", "4127403"}; + rows[3164] = new String[] {"PR", "Tibagi", "4127502"}; + rows[3165] = new String[] {"PR", "Tijucas do Sul", "4127601"}; + rows[3166] = new String[] {"PR", "Toledo", "4127700"}; + rows[3167] = new String[] {"PR", "Tomazina", "4127809"}; + rows[3168] = new String[] {"PR", "Tr\u00eas Barras do Paran\u00e1", "4127858"}; + rows[3169] = new String[] {"PR", "Tunas do Paran\u00e1", "4127882"}; + rows[3170] = new String[] {"PR", "Tuneiras do Oeste", "4127908"}; + rows[3171] = new String[] {"PR", "Tup\u00e3ssi", "4127957"}; + rows[3172] = new String[] {"PR", "Turvo", "4127965"}; + rows[3173] = new String[] {"PR", "Ubirat\u00e3", "4128005"}; + rows[3174] = new String[] {"PR", "Umuarama", "4128104"}; + rows[3175] = new String[] {"PR", "Uni\u00e3o da Vit\u00f3ria", "4128203"}; + rows[3176] = new String[] {"PR", "Uniflor", "4128302"}; + rows[3177] = new String[] {"PR", "Ura\u00ed", "4128401"}; + rows[3178] = new String[] {"PR", "Ventania", "4128534"}; + rows[3179] = new String[] {"PR", "Vera Cruz do Oeste", "4128559"}; + rows[3180] = new String[] {"PR", "Ver\u00ea", "4128609"}; + rows[3181] = new String[] {"PR", "Virmond", "4128658"}; + rows[3182] = new String[] {"PR", "Vitorino", "4128708"}; + rows[3183] = new String[] {"PR", "Wenceslau Braz", "4128500"}; + rows[3184] = new String[] {"PR", "Xambr\u00ea", "4128807"}; + rows[3185] = new String[] {"PE", "Abreu e Lima", "2600054"}; + rows[3186] = new String[] {"PE", "Afogados da Ingazeira", "2600104"}; + rows[3187] = new String[] {"PE", "Afr\u00e2nio", "2600203"}; + rows[3188] = new String[] {"PE", "Agrestina", "2600302"}; + rows[3189] = new String[] {"PE", "\u00c1gua Preta", "2600401"}; + rows[3190] = new String[] {"PE", "\u00c1guas Belas", "2600500"}; + rows[3191] = new String[] {"PE", "Alagoinha", "2600609"}; + rows[3192] = new String[] {"PE", "Alian\u00e7a", "2600708"}; + rows[3193] = new String[] {"PE", "Altinho", "2600807"}; + rows[3194] = new String[] {"PE", "Amaraji", "2600906"}; + rows[3195] = new String[] {"PE", "Angelim", "2601003"}; + rows[3196] = new String[] {"PE", "Ara\u00e7oiaba", "2601052"}; + rows[3197] = new String[] {"PE", "Araripina", "2601102"}; + rows[3198] = new String[] {"PE", "Arcoverde", "2601201"}; + rows[3199] = new String[] {"PE", "Barra de Guabiraba", "2601300"}; + } + + private static void municipalitiesRows16(String[][] rows) { + rows[3200] = new String[] {"PE", "Barreiros", "2601409"}; + rows[3201] = new String[] {"PE", "Bel\u00e9m de Maria", "2601508"}; + rows[3202] = new String[] {"PE", "Bel\u00e9m do S\u00e3o Francisco", "2601607"}; + rows[3203] = new String[] {"PE", "Belo Jardim", "2601706"}; + rows[3204] = new String[] {"PE", "Bet\u00e2nia", "2601805"}; + rows[3205] = new String[] {"PE", "Bezerros", "2601904"}; + rows[3206] = new String[] {"PE", "Bodoc\u00f3", "2602001"}; + rows[3207] = new String[] {"PE", "Bom Conselho", "2602100"}; + rows[3208] = new String[] {"PE", "Bom Jardim", "2602209"}; + rows[3209] = new String[] {"PE", "Bonito", "2602308"}; + rows[3210] = new String[] {"PE", "Brej\u00e3o", "2602407"}; + rows[3211] = new String[] {"PE", "Brejinho", "2602506"}; + rows[3212] = new String[] {"PE", "Brejo da Madre de Deus", "2602605"}; + rows[3213] = new String[] {"PE", "Buenos Aires", "2602704"}; + rows[3214] = new String[] {"PE", "Bu\u00edque", "2602803"}; + rows[3215] = new String[] {"PE", "Cabo de Santo Agostinho", "2602902"}; + rows[3216] = new String[] {"PE", "Cabrob\u00f3", "2603009"}; + rows[3217] = new String[] {"PE", "Cachoeirinha", "2603108"}; + rows[3218] = new String[] {"PE", "Caet\u00e9s", "2603207"}; + rows[3219] = new String[] {"PE", "Cal\u00e7ado", "2603306"}; + rows[3220] = new String[] {"PE", "Calumbi", "2603405"}; + rows[3221] = new String[] {"PE", "Camaragibe", "2603454"}; + rows[3222] = new String[] {"PE", "Camocim de S\u00e3o F\u00e9lix", "2603504"}; + rows[3223] = new String[] {"PE", "Camutanga", "2603603"}; + rows[3224] = new String[] {"PE", "Canhotinho", "2603702"}; + rows[3225] = new String[] {"PE", "Capoeiras", "2603801"}; + rows[3226] = new String[] {"PE", "Carna\u00edba", "2603900"}; + rows[3227] = new String[] {"PE", "Carnaubeira da Penha", "2603926"}; + rows[3228] = new String[] {"PE", "Carpina", "2604007"}; + rows[3229] = new String[] {"PE", "Caruaru", "2604106"}; + rows[3230] = new String[] {"PE", "Casinhas", "2604155"}; + rows[3231] = new String[] {"PE", "Catende", "2604205"}; + rows[3232] = new String[] {"PE", "Cedro", "2604304"}; + rows[3233] = new String[] {"PE", "Ch\u00e3 de Alegria", "2604403"}; + rows[3234] = new String[] {"PE", "Ch\u00e3 Grande", "2604502"}; + rows[3235] = new String[] {"PE", "Condado", "2604601"}; + rows[3236] = new String[] {"PE", "Correntes", "2604700"}; + rows[3237] = new String[] {"PE", "Cort\u00eas", "2604809"}; + rows[3238] = new String[] {"PE", "Cumaru", "2604908"}; + rows[3239] = new String[] {"PE", "Cupira", "2605004"}; + rows[3240] = new String[] {"PE", "Cust\u00f3dia", "2605103"}; + rows[3241] = new String[] {"PE", "Dormentes", "2605152"}; + rows[3242] = new String[] {"PE", "Escada", "2605202"}; + rows[3243] = new String[] {"PE", "Exu", "2605301"}; + rows[3244] = new String[] {"PE", "Feira Nova", "2605400"}; + rows[3245] = new String[] {"PE", "Fernando de Noronha", "2605459"}; + rows[3246] = new String[] {"PE", "Ferreiros", "2605509"}; + rows[3247] = new String[] {"PE", "Flores", "2605608"}; + rows[3248] = new String[] {"PE", "Floresta", "2605707"}; + rows[3249] = new String[] {"PE", "Frei Miguelinho", "2605806"}; + rows[3250] = new String[] {"PE", "Gameleira", "2605905"}; + rows[3251] = new String[] {"PE", "Garanhuns", "2606002"}; + rows[3252] = new String[] {"PE", "Gl\u00f3ria do Goit\u00e1", "2606101"}; + rows[3253] = new String[] {"PE", "Goiana", "2606200"}; + rows[3254] = new String[] {"PE", "Granito", "2606309"}; + rows[3255] = new String[] {"PE", "Gravat\u00e1", "2606408"}; + rows[3256] = new String[] {"PE", "Iati", "2606507"}; + rows[3257] = new String[] {"PE", "Ibimirim", "2606606"}; + rows[3258] = new String[] {"PE", "Ibirajuba", "2606705"}; + rows[3259] = new String[] {"PE", "Igarassu", "2606804"}; + rows[3260] = new String[] {"PE", "Iguaracy", "2606903"}; + rows[3261] = new String[] {"PE", "Ilha de Itamarac\u00e1", "2607604"}; + rows[3262] = new String[] {"PE", "Inaj\u00e1", "2607000"}; + rows[3263] = new String[] {"PE", "Ingazeira", "2607109"}; + rows[3264] = new String[] {"PE", "Ipojuca", "2607208"}; + rows[3265] = new String[] {"PE", "Ipubi", "2607307"}; + rows[3266] = new String[] {"PE", "Itacuruba", "2607406"}; + rows[3267] = new String[] {"PE", "Ita\u00edba", "2607505"}; + rows[3268] = new String[] {"PE", "Itamb\u00e9", "2607653"}; + rows[3269] = new String[] {"PE", "Itapetim", "2607703"}; + rows[3270] = new String[] {"PE", "Itapissuma", "2607752"}; + rows[3271] = new String[] {"PE", "Itaquitinga", "2607802"}; + rows[3272] = new String[] {"PE", "Jaboat\u00e3o dos Guararapes", "2607901"}; + rows[3273] = new String[] {"PE", "Jaqueira", "2607950"}; + rows[3274] = new String[] {"PE", "Jata\u00faba", "2608008"}; + rows[3275] = new String[] {"PE", "Jatob\u00e1", "2608057"}; + rows[3276] = new String[] {"PE", "Jo\u00e3o Alfredo", "2608107"}; + rows[3277] = new String[] {"PE", "Joaquim Nabuco", "2608206"}; + rows[3278] = new String[] {"PE", "Jucati", "2608255"}; + rows[3279] = new String[] {"PE", "Jupi", "2608305"}; + rows[3280] = new String[] {"PE", "Jurema", "2608404"}; + rows[3281] = new String[] {"PE", "Lagoa de Itaenga", "2608503"}; + rows[3282] = new String[] {"PE", "Lagoa do Carro", "2608453"}; + rows[3283] = new String[] {"PE", "Lagoa do Ouro", "2608602"}; + rows[3284] = new String[] {"PE", "Lagoa dos Gatos", "2608701"}; + rows[3285] = new String[] {"PE", "Lagoa Grande", "2608750"}; + rows[3286] = new String[] {"PE", "Lajedo", "2608800"}; + rows[3287] = new String[] {"PE", "Limoeiro", "2608909"}; + rows[3288] = new String[] {"PE", "Macaparana", "2609006"}; + rows[3289] = new String[] {"PE", "Machados", "2609105"}; + rows[3290] = new String[] {"PE", "Manari", "2609154"}; + rows[3291] = new String[] {"PE", "Maraial", "2609204"}; + rows[3292] = new String[] {"PE", "Mirandiba", "2609303"}; + rows[3293] = new String[] {"PE", "Moreil\u00e2ndia", "2614303"}; + rows[3294] = new String[] {"PE", "Moreno", "2609402"}; + rows[3295] = new String[] {"PE", "Nazar\u00e9 da Mata", "2609501"}; + rows[3296] = new String[] {"PE", "Olinda", "2609600"}; + rows[3297] = new String[] {"PE", "Orob\u00f3", "2609709"}; + rows[3298] = new String[] {"PE", "Oroc\u00f3", "2609808"}; + rows[3299] = new String[] {"PE", "Ouricuri", "2609907"}; + rows[3300] = new String[] {"PE", "Palmares", "2610004"}; + rows[3301] = new String[] {"PE", "Palmeirina", "2610103"}; + rows[3302] = new String[] {"PE", "Panelas", "2610202"}; + rows[3303] = new String[] {"PE", "Paranatama", "2610301"}; + rows[3304] = new String[] {"PE", "Parnamirim", "2610400"}; + rows[3305] = new String[] {"PE", "Passira", "2610509"}; + rows[3306] = new String[] {"PE", "Paudalho", "2610608"}; + rows[3307] = new String[] {"PE", "Paulista", "2610707"}; + rows[3308] = new String[] {"PE", "Pedra", "2610806"}; + rows[3309] = new String[] {"PE", "Pesqueira", "2610905"}; + rows[3310] = new String[] {"PE", "Petrol\u00e2ndia", "2611002"}; + rows[3311] = new String[] {"PE", "Petrolina", "2611101"}; + rows[3312] = new String[] {"PE", "Po\u00e7\u00e3o", "2611200"}; + rows[3313] = new String[] {"PE", "Pombos", "2611309"}; + rows[3314] = new String[] {"PE", "Primavera", "2611408"}; + rows[3315] = new String[] {"PE", "Quipap\u00e1", "2611507"}; + rows[3316] = new String[] {"PE", "Quixaba", "2611533"}; + rows[3317] = new String[] {"PE", "Recife", "2611606"}; + rows[3318] = new String[] {"PE", "Riacho das Almas", "2611705"}; + rows[3319] = new String[] {"PE", "Ribeir\u00e3o", "2611804"}; + rows[3320] = new String[] {"PE", "Rio Formoso", "2611903"}; + rows[3321] = new String[] {"PE", "Sair\u00e9", "2612000"}; + rows[3322] = new String[] {"PE", "Salgadinho", "2612109"}; + rows[3323] = new String[] {"PE", "Salgueiro", "2612208"}; + rows[3324] = new String[] {"PE", "Salo\u00e1", "2612307"}; + rows[3325] = new String[] {"PE", "Sanhar\u00f3", "2612406"}; + rows[3326] = new String[] {"PE", "Santa Cruz", "2612455"}; + rows[3327] = new String[] {"PE", "Santa Cruz da Baixa Verde", "2612471"}; + rows[3328] = new String[] {"PE", "Santa Cruz do Capibaribe", "2612505"}; + rows[3329] = new String[] {"PE", "Santa Filomena", "2612554"}; + rows[3330] = new String[] {"PE", "Santa Maria da Boa Vista", "2612604"}; + rows[3331] = new String[] {"PE", "Santa Maria do Cambuc\u00e1", "2612703"}; + rows[3332] = new String[] {"PE", "Santa Terezinha", "2612802"}; + rows[3333] = new String[] {"PE", "S\u00e3o Benedito do Sul", "2612901"}; + rows[3334] = new String[] {"PE", "S\u00e3o Bento do Una", "2613008"}; + rows[3335] = new String[] {"PE", "S\u00e3o Caitano", "2613107"}; + rows[3336] = new String[] {"PE", "S\u00e3o Jo\u00e3o", "2613206"}; + rows[3337] = new String[] {"PE", "S\u00e3o Joaquim do Monte", "2613305"}; + rows[3338] = new String[] {"PE", "S\u00e3o Jos\u00e9 da Coroa Grande", "2613404"}; + rows[3339] = new String[] {"PE", "S\u00e3o Jos\u00e9 do Belmonte", "2613503"}; + rows[3340] = new String[] {"PE", "S\u00e3o Jos\u00e9 do Egito", "2613602"}; + rows[3341] = new String[] {"PE", "S\u00e3o Louren\u00e7o da Mata", "2613701"}; + rows[3342] = new String[] {"PE", "S\u00e3o Vicente F\u00e9rrer", "2613800"}; + rows[3343] = new String[] {"PE", "Serra Talhada", "2613909"}; + rows[3344] = new String[] {"PE", "Serrita", "2614006"}; + rows[3345] = new String[] {"PE", "Sert\u00e2nia", "2614105"}; + rows[3346] = new String[] {"PE", "Sirinha\u00e9m", "2614204"}; + rows[3347] = new String[] {"PE", "Solid\u00e3o", "2614402"}; + rows[3348] = new String[] {"PE", "Surubim", "2614501"}; + rows[3349] = new String[] {"PE", "Tabira", "2614600"}; + rows[3350] = new String[] {"PE", "Tacaimb\u00f3", "2614709"}; + rows[3351] = new String[] {"PE", "Tacaratu", "2614808"}; + rows[3352] = new String[] {"PE", "Tamandar\u00e9", "2614857"}; + rows[3353] = new String[] {"PE", "Taquaritinga do Norte", "2615003"}; + rows[3354] = new String[] {"PE", "Terezinha", "2615102"}; + rows[3355] = new String[] {"PE", "Terra Nova", "2615201"}; + rows[3356] = new String[] {"PE", "Timba\u00faba", "2615300"}; + rows[3357] = new String[] {"PE", "Toritama", "2615409"}; + rows[3358] = new String[] {"PE", "Tracunha\u00e9m", "2615508"}; + rows[3359] = new String[] {"PE", "Trindade", "2615607"}; + rows[3360] = new String[] {"PE", "Triunfo", "2615706"}; + rows[3361] = new String[] {"PE", "Tupanatinga", "2615805"}; + rows[3362] = new String[] {"PE", "Tuparetama", "2615904"}; + rows[3363] = new String[] {"PE", "Venturosa", "2616001"}; + rows[3364] = new String[] {"PE", "Verdejante", "2616100"}; + rows[3365] = new String[] {"PE", "Vertente do L\u00e9rio", "2616183"}; + rows[3366] = new String[] {"PE", "Vertentes", "2616209"}; + rows[3367] = new String[] {"PE", "Vic\u00eancia", "2616308"}; + rows[3368] = new String[] {"PE", "Vit\u00f3ria de Santo Ant\u00e3o", "2616407"}; + rows[3369] = new String[] {"PE", "Xex\u00e9u", "2616506"}; + rows[3370] = new String[] {"PI", "Acau\u00e3", "2200053"}; + rows[3371] = new String[] {"PI", "Agricol\u00e2ndia", "2200103"}; + rows[3372] = new String[] {"PI", "\u00c1gua Branca", "2200202"}; + rows[3373] = new String[] {"PI", "Alagoinha do Piau\u00ed", "2200251"}; + rows[3374] = new String[] {"PI", "Alegrete do Piau\u00ed", "2200277"}; + rows[3375] = new String[] {"PI", "Alto Long\u00e1", "2200301"}; + rows[3376] = new String[] {"PI", "Altos", "2200400"}; + rows[3377] = new String[] {"PI", "Alvorada do Gurgu\u00e9ia", "2200459"}; + rows[3378] = new String[] {"PI", "Amarante", "2200509"}; + rows[3379] = new String[] {"PI", "Angical do Piau\u00ed", "2200608"}; + rows[3380] = new String[] {"PI", "An\u00edsio de Abreu", "2200707"}; + rows[3381] = new String[] {"PI", "Ant\u00f4nio Almeida", "2200806"}; + rows[3382] = new String[] {"PI", "Aroazes", "2200905"}; + rows[3383] = new String[] {"PI", "Aroeiras do Itaim", "2200954"}; + rows[3384] = new String[] {"PI", "Arraial", "2201002"}; + rows[3385] = new String[] {"PI", "Assun\u00e7\u00e3o do Piau\u00ed", "2201051"}; + rows[3386] = new String[] {"PI", "Avelino Lopes", "2201101"}; + rows[3387] = new String[] {"PI", "Baixa Grande do Ribeiro", "2201150"}; + rows[3388] = new String[] {"PI", "Barra D'Alc\u00e2ntara", "2201176"}; + rows[3389] = new String[] {"PI", "Barras", "2201200"}; + rows[3390] = new String[] {"PI", "Barreiras do Piau\u00ed", "2201309"}; + rows[3391] = new String[] {"PI", "Barro Duro", "2201408"}; + rows[3392] = new String[] {"PI", "Batalha", "2201507"}; + rows[3393] = new String[] {"PI", "Bela Vista do Piau\u00ed", "2201556"}; + rows[3394] = new String[] {"PI", "Bel\u00e9m do Piau\u00ed", "2201572"}; + rows[3395] = new String[] {"PI", "Beneditinos", "2201606"}; + rows[3396] = new String[] {"PI", "Bertol\u00ednia", "2201705"}; + rows[3397] = new String[] {"PI", "Bet\u00e2nia do Piau\u00ed", "2201739"}; + rows[3398] = new String[] {"PI", "Boa Hora", "2201770"}; + rows[3399] = new String[] {"PI", "Bocaina", "2201804"}; + } + + private static void municipalitiesRows17(String[][] rows) { + rows[3400] = new String[] {"PI", "Bom Jesus", "2201903"}; + rows[3401] = new String[] {"PI", "Bom Princ\u00edpio do Piau\u00ed", "2201919"}; + rows[3402] = new String[] {"PI", "Bonfim do Piau\u00ed", "2201929"}; + rows[3403] = new String[] {"PI", "Boqueir\u00e3o do Piau\u00ed", "2201945"}; + rows[3404] = new String[] {"PI", "Brasileira", "2201960"}; + rows[3405] = new String[] {"PI", "Brejo do Piau\u00ed", "2201988"}; + rows[3406] = new String[] {"PI", "Buriti dos Lopes", "2202000"}; + rows[3407] = new String[] {"PI", "Buriti dos Montes", "2202026"}; + rows[3408] = new String[] {"PI", "Cabeceiras do Piau\u00ed", "2202059"}; + rows[3409] = new String[] {"PI", "Cajazeiras do Piau\u00ed", "2202075"}; + rows[3410] = new String[] {"PI", "Cajueiro da Praia", "2202083"}; + rows[3411] = new String[] {"PI", "Caldeir\u00e3o Grande do Piau\u00ed", "2202091"}; + rows[3412] = new String[] {"PI", "Campinas do Piau\u00ed", "2202109"}; + rows[3413] = new String[] {"PI", "Campo Alegre do Fidalgo", "2202117"}; + rows[3414] = new String[] {"PI", "Campo Grande do Piau\u00ed", "2202133"}; + rows[3415] = new String[] {"PI", "Campo Largo do Piau\u00ed", "2202174"}; + rows[3416] = new String[] {"PI", "Campo Maior", "2202208"}; + rows[3417] = new String[] {"PI", "Canavieira", "2202251"}; + rows[3418] = new String[] {"PI", "Canto do Buriti", "2202307"}; + rows[3419] = new String[] {"PI", "Capit\u00e3o de Campos", "2202406"}; + rows[3420] = new String[] {"PI", "Capit\u00e3o Gerv\u00e1sio Oliveira", "2202455"}; + rows[3421] = new String[] {"PI", "Caracol", "2202505"}; + rows[3422] = new String[] {"PI", "Cara\u00fabas do Piau\u00ed", "2202539"}; + rows[3423] = new String[] {"PI", "Caridade do Piau\u00ed", "2202554"}; + rows[3424] = new String[] {"PI", "Castelo do Piau\u00ed", "2202604"}; + rows[3425] = new String[] {"PI", "Caxing\u00f3", "2202653"}; + rows[3426] = new String[] {"PI", "Cocal", "2202703"}; + rows[3427] = new String[] {"PI", "Cocal de Telha", "2202711"}; + rows[3428] = new String[] {"PI", "Cocal dos Alves", "2202729"}; + rows[3429] = new String[] {"PI", "Coivaras", "2202737"}; + rows[3430] = new String[] {"PI", "Col\u00f4nia do Gurgu\u00e9ia", "2202752"}; + rows[3431] = new String[] {"PI", "Col\u00f4nia do Piau\u00ed", "2202778"}; + rows[3432] = new String[] {"PI", "Concei\u00e7\u00e3o do Canind\u00e9", "2202802"}; + rows[3433] = new String[] {"PI", "Coronel Jos\u00e9 Dias", "2202851"}; + rows[3434] = new String[] {"PI", "Corrente", "2202901"}; + rows[3435] = new String[] {"PI", "Cristal\u00e2ndia do Piau\u00ed", "2203008"}; + rows[3436] = new String[] {"PI", "Cristino Castro", "2203107"}; + rows[3437] = new String[] {"PI", "Curimat\u00e1", "2203206"}; + rows[3438] = new String[] {"PI", "Currais", "2203230"}; + rows[3439] = new String[] {"PI", "Curral Novo do Piau\u00ed", "2203271"}; + rows[3440] = new String[] {"PI", "Curralinhos", "2203255"}; + rows[3441] = new String[] {"PI", "Demerval Lob\u00e3o", "2203305"}; + rows[3442] = new String[] {"PI", "Dirceu Arcoverde", "2203354"}; + rows[3443] = new String[] {"PI", "Dom Expedito Lopes", "2203404"}; + rows[3444] = new String[] {"PI", "Dom Inoc\u00eancio", "2203453"}; + rows[3445] = new String[] {"PI", "Domingos Mour\u00e3o", "2203420"}; + rows[3446] = new String[] {"PI", "Elesb\u00e3o Veloso", "2203503"}; + rows[3447] = new String[] {"PI", "Eliseu Martins", "2203602"}; + rows[3448] = new String[] {"PI", "Esperantina", "2203701"}; + rows[3449] = new String[] {"PI", "Fartura do Piau\u00ed", "2203750"}; + rows[3450] = new String[] {"PI", "Flores do Piau\u00ed", "2203800"}; + rows[3451] = new String[] {"PI", "Floresta do Piau\u00ed", "2203859"}; + rows[3452] = new String[] {"PI", "Floriano", "2203909"}; + rows[3453] = new String[] {"PI", "Francin\u00f3polis", "2204006"}; + rows[3454] = new String[] {"PI", "Francisco Ayres", "2204105"}; + rows[3455] = new String[] {"PI", "Francisco Macedo", "2204154"}; + rows[3456] = new String[] {"PI", "Francisco Santos", "2204204"}; + rows[3457] = new String[] {"PI", "Fronteiras", "2204303"}; + rows[3458] = new String[] {"PI", "Geminiano", "2204352"}; + rows[3459] = new String[] {"PI", "Gilbu\u00e9s", "2204402"}; + rows[3460] = new String[] {"PI", "Guadalupe", "2204501"}; + rows[3461] = new String[] {"PI", "Guaribas", "2204550"}; + rows[3462] = new String[] {"PI", "Hugo Napole\u00e3o", "2204600"}; + rows[3463] = new String[] {"PI", "Ilha Grande", "2204659"}; + rows[3464] = new String[] {"PI", "Inhuma", "2204709"}; + rows[3465] = new String[] {"PI", "Ipiranga do Piau\u00ed", "2204808"}; + rows[3466] = new String[] {"PI", "Isa\u00edas Coelho", "2204907"}; + rows[3467] = new String[] {"PI", "Itain\u00f3polis", "2205003"}; + rows[3468] = new String[] {"PI", "Itaueira", "2205102"}; + rows[3469] = new String[] {"PI", "Jacobina do Piau\u00ed", "2205151"}; + rows[3470] = new String[] {"PI", "Jaic\u00f3s", "2205201"}; + rows[3471] = new String[] {"PI", "Jardim do Mulato", "2205250"}; + rows[3472] = new String[] {"PI", "Jatob\u00e1 do Piau\u00ed", "2205276"}; + rows[3473] = new String[] {"PI", "Jerumenha", "2205300"}; + rows[3474] = new String[] {"PI", "Jo\u00e3o Costa", "2205359"}; + rows[3475] = new String[] {"PI", "Joaquim Pires", "2205409"}; + rows[3476] = new String[] {"PI", "Joca Marques", "2205458"}; + rows[3477] = new String[] {"PI", "Jos\u00e9 de Freitas", "2205508"}; + rows[3478] = new String[] {"PI", "Juazeiro do Piau\u00ed", "2205516"}; + rows[3479] = new String[] {"PI", "J\u00falio Borges", "2205524"}; + rows[3480] = new String[] {"PI", "Jurema", "2205532"}; + rows[3481] = new String[] {"PI", "Lagoa Alegre", "2205557"}; + rows[3482] = new String[] {"PI", "Lagoa de S\u00e3o Francisco", "2205573"}; + rows[3483] = new String[] {"PI", "Lagoa do Barro do Piau\u00ed", "2205565"}; + rows[3484] = new String[] {"PI", "Lagoa do Piau\u00ed", "2205581"}; + rows[3485] = new String[] {"PI", "Lagoa do S\u00edtio", "2205599"}; + rows[3486] = new String[] {"PI", "Lagoinha do Piau\u00ed", "2205540"}; + rows[3487] = new String[] {"PI", "Landri Sales", "2205607"}; + rows[3488] = new String[] {"PI", "Lu\u00eds Correia", "2205706"}; + rows[3489] = new String[] {"PI", "Luzil\u00e2ndia", "2205805"}; + rows[3490] = new String[] {"PI", "Madeiro", "2205854"}; + rows[3491] = new String[] {"PI", "Manoel Em\u00eddio", "2205904"}; + rows[3492] = new String[] {"PI", "Marcol\u00e2ndia", "2205953"}; + rows[3493] = new String[] {"PI", "Marcos Parente", "2206001"}; + rows[3494] = new String[] {"PI", "Massap\u00ea do Piau\u00ed", "2206050"}; + rows[3495] = new String[] {"PI", "Matias Ol\u00edmpio", "2206100"}; + rows[3496] = new String[] {"PI", "Miguel Alves", "2206209"}; + rows[3497] = new String[] {"PI", "Miguel Le\u00e3o", "2206308"}; + rows[3498] = new String[] {"PI", "Milton Brand\u00e3o", "2206357"}; + rows[3499] = new String[] {"PI", "Monsenhor Gil", "2206407"}; + rows[3500] = new String[] {"PI", "Monsenhor Hip\u00f3lito", "2206506"}; + rows[3501] = new String[] {"PI", "Monte Alegre do Piau\u00ed", "2206605"}; + rows[3502] = new String[] {"PI", "Morro Cabe\u00e7a no Tempo", "2206654"}; + rows[3503] = new String[] {"PI", "Morro do Chap\u00e9u do Piau\u00ed", "2206670"}; + rows[3504] = new String[] {"PI", "Murici dos Portelas", "2206696"}; + rows[3505] = new String[] {"PI", "Nazar\u00e9 do Piau\u00ed", "2206704"}; + rows[3506] = new String[] {"PI", "Naz\u00e1ria", "2206720"}; + rows[3507] = new String[] {"PI", "Nossa Senhora de Nazar\u00e9", "2206753"}; + rows[3508] = new String[] {"PI", "Nossa Senhora dos Rem\u00e9dios", "2206803"}; + rows[3509] = new String[] {"PI", "Nova Santa Rita", "2207959"}; + rows[3510] = new String[] {"PI", "Novo Oriente do Piau\u00ed", "2206902"}; + rows[3511] = new String[] {"PI", "Novo Santo Ant\u00f4nio", "2206951"}; + rows[3512] = new String[] {"PI", "Oeiras", "2207009"}; + rows[3513] = new String[] {"PI", "Olho D'\u00c1gua do Piau\u00ed", "2207108"}; + rows[3514] = new String[] {"PI", "Padre Marcos", "2207207"}; + rows[3515] = new String[] {"PI", "Paes Landim", "2207306"}; + rows[3516] = new String[] {"PI", "Paje\u00fa do Piau\u00ed", "2207355"}; + rows[3517] = new String[] {"PI", "Palmeira do Piau\u00ed", "2207405"}; + rows[3518] = new String[] {"PI", "Palmeirais", "2207504"}; + rows[3519] = new String[] {"PI", "Paquet\u00e1", "2207553"}; + rows[3520] = new String[] {"PI", "Parnagu\u00e1", "2207603"}; + rows[3521] = new String[] {"PI", "Parna\u00edba", "2207702"}; + rows[3522] = new String[] {"PI", "Passagem Franca do Piau\u00ed", "2207751"}; + rows[3523] = new String[] {"PI", "Patos do Piau\u00ed", "2207777"}; + rows[3524] = new String[] {"PI", "Pau D'Arco do Piau\u00ed", "2207793"}; + rows[3525] = new String[] {"PI", "Paulistana", "2207801"}; + rows[3526] = new String[] {"PI", "Pavussu", "2207850"}; + rows[3527] = new String[] {"PI", "Pedro II", "2207900"}; + rows[3528] = new String[] {"PI", "Pedro Laurentino", "2207934"}; + rows[3529] = new String[] {"PI", "Picos", "2208007"}; + rows[3530] = new String[] {"PI", "Pimenteiras", "2208106"}; + rows[3531] = new String[] {"PI", "Pio IX", "2208205"}; + rows[3532] = new String[] {"PI", "Piracuruca", "2208304"}; + rows[3533] = new String[] {"PI", "Piripiri", "2208403"}; + rows[3534] = new String[] {"PI", "Porto", "2208502"}; + rows[3535] = new String[] {"PI", "Porto Alegre do Piau\u00ed", "2208551"}; + rows[3536] = new String[] {"PI", "Prata do Piau\u00ed", "2208601"}; + rows[3537] = new String[] {"PI", "Queimada Nova", "2208650"}; + rows[3538] = new String[] {"PI", "Reden\u00e7\u00e3o do Gurgu\u00e9ia", "2208700"}; + rows[3539] = new String[] {"PI", "Regenera\u00e7\u00e3o", "2208809"}; + rows[3540] = new String[] {"PI", "Riacho Frio", "2208858"}; + rows[3541] = new String[] {"PI", "Ribeira do Piau\u00ed", "2208874"}; + rows[3542] = new String[] {"PI", "Ribeiro Gon\u00e7alves", "2208908"}; + rows[3543] = new String[] {"PI", "Rio Grande do Piau\u00ed", "2209005"}; + rows[3544] = new String[] {"PI", "Santa Cruz do Piau\u00ed", "2209104"}; + rows[3545] = new String[] {"PI", "Santa Cruz dos Milagres", "2209153"}; + rows[3546] = new String[] {"PI", "Santa Filomena", "2209203"}; + rows[3547] = new String[] {"PI", "Santa Luz", "2209302"}; + rows[3548] = new String[] {"PI", "Santa Rosa do Piau\u00ed", "2209377"}; + rows[3549] = new String[] {"PI", "Santana do Piau\u00ed", "2209351"}; + rows[3550] = new String[] {"PI", "Santo Ant\u00f4nio de Lisboa", "2209401"}; + rows[3551] = new String[] {"PI", "Santo Ant\u00f4nio dos Milagres", "2209450"}; + rows[3552] = new String[] {"PI", "Santo In\u00e1cio do Piau\u00ed", "2209500"}; + rows[3553] = new String[] {"PI", "S\u00e3o Braz do Piau\u00ed", "2209559"}; + rows[3554] = new String[] {"PI", "S\u00e3o F\u00e9lix do Piau\u00ed", "2209609"}; + rows[3555] = new String[] {"PI", "S\u00e3o Francisco de Assis do Piau\u00ed", "2209658"}; + rows[3556] = new String[] {"PI", "S\u00e3o Francisco do Piau\u00ed", "2209708"}; + rows[3557] = new String[] {"PI", "S\u00e3o Gon\u00e7alo do Gurgu\u00e9ia", "2209757"}; + rows[3558] = new String[] {"PI", "S\u00e3o Gon\u00e7alo do Piau\u00ed", "2209807"}; + rows[3559] = new String[] {"PI", "S\u00e3o Jo\u00e3o da Canabrava", "2209856"}; + rows[3560] = new String[] {"PI", "S\u00e3o Jo\u00e3o da Fronteira", "2209872"}; + rows[3561] = new String[] {"PI", "S\u00e3o Jo\u00e3o da Serra", "2209906"}; + rows[3562] = new String[] {"PI", "S\u00e3o Jo\u00e3o da Varjota", "2209955"}; + rows[3563] = new String[] {"PI", "S\u00e3o Jo\u00e3o do Arraial", "2209971"}; + rows[3564] = new String[] {"PI", "S\u00e3o Jo\u00e3o do Piau\u00ed", "2210003"}; + rows[3565] = new String[] {"PI", "S\u00e3o Jos\u00e9 do Divino", "2210052"}; + rows[3566] = new String[] {"PI", "S\u00e3o Jos\u00e9 do Peixe", "2210102"}; + rows[3567] = new String[] {"PI", "S\u00e3o Jos\u00e9 do Piau\u00ed", "2210201"}; + rows[3568] = new String[] {"PI", "S\u00e3o Juli\u00e3o", "2210300"}; + rows[3569] = new String[] {"PI", "S\u00e3o Louren\u00e7o do Piau\u00ed", "2210359"}; + rows[3570] = new String[] {"PI", "S\u00e3o Luis do Piau\u00ed", "2210375"}; + rows[3571] = new String[] {"PI", "S\u00e3o Miguel da Baixa Grande", "2210383"}; + rows[3572] = new String[] {"PI", "S\u00e3o Miguel do Fidalgo", "2210391"}; + rows[3573] = new String[] {"PI", "S\u00e3o Miguel do Tapuio", "2210409"}; + rows[3574] = new String[] {"PI", "S\u00e3o Pedro do Piau\u00ed", "2210508"}; + rows[3575] = new String[] {"PI", "S\u00e3o Raimundo Nonato", "2210607"}; + rows[3576] = new String[] {"PI", "Sebasti\u00e3o Barros", "2210623"}; + rows[3577] = new String[] {"PI", "Sebasti\u00e3o Leal", "2210631"}; + rows[3578] = new String[] {"PI", "Sigefredo Pacheco", "2210656"}; + rows[3579] = new String[] {"PI", "Sim\u00f5es", "2210706"}; + rows[3580] = new String[] {"PI", "Simpl\u00edcio Mendes", "2210805"}; + rows[3581] = new String[] {"PI", "Socorro do Piau\u00ed", "2210904"}; + rows[3582] = new String[] {"PI", "Sussuapara", "2210938"}; + rows[3583] = new String[] {"PI", "Tamboril do Piau\u00ed", "2210953"}; + rows[3584] = new String[] {"PI", "Tanque do Piau\u00ed", "2210979"}; + rows[3585] = new String[] {"PI", "Teresina", "2211001"}; + rows[3586] = new String[] {"PI", "Uni\u00e3o", "2211100"}; + rows[3587] = new String[] {"PI", "Uru\u00e7u\u00ed", "2211209"}; + rows[3588] = new String[] {"PI", "Valen\u00e7a do Piau\u00ed", "2211308"}; + rows[3589] = new String[] {"PI", "V\u00e1rzea Branca", "2211357"}; + rows[3590] = new String[] {"PI", "V\u00e1rzea Grande", "2211407"}; + rows[3591] = new String[] {"PI", "Vera Mendes", "2211506"}; + rows[3592] = new String[] {"PI", "Vila Nova do Piau\u00ed", "2211605"}; + rows[3593] = new String[] {"PI", "Wall Ferraz", "2211704"}; + rows[3594] = new String[] {"RJ", "Angra dos Reis", "3300100"}; + rows[3595] = new String[] {"RJ", "Aperib\u00e9", "3300159"}; + rows[3596] = new String[] {"RJ", "Araruama", "3300209"}; + rows[3597] = new String[] {"RJ", "Areal", "3300225"}; + rows[3598] = new String[] {"RJ", "Arma\u00e7\u00e3o dos B\u00fazios", "3300233"}; + rows[3599] = new String[] {"RJ", "Arraial do Cabo", "3300258"}; + } + + private static void municipalitiesRows18(String[][] rows) { + rows[3600] = new String[] {"RJ", "Barra do Pira\u00ed", "3300308"}; + rows[3601] = new String[] {"RJ", "Barra Mansa", "3300407"}; + rows[3602] = new String[] {"RJ", "Belford Roxo", "3300456"}; + rows[3603] = new String[] {"RJ", "Bom Jardim", "3300506"}; + rows[3604] = new String[] {"RJ", "Bom Jesus do Itabapoana", "3300605"}; + rows[3605] = new String[] {"RJ", "Cabo Frio", "3300704"}; + rows[3606] = new String[] {"RJ", "Cachoeiras de Macacu", "3300803"}; + rows[3607] = new String[] {"RJ", "Cambuci", "3300902"}; + rows[3608] = new String[] {"RJ", "Campos dos Goytacazes", "3301009"}; + rows[3609] = new String[] {"RJ", "Cantagalo", "3301108"}; + rows[3610] = new String[] {"RJ", "Carapebus", "3300936"}; + rows[3611] = new String[] {"RJ", "Cardoso Moreira", "3301157"}; + rows[3612] = new String[] {"RJ", "Carmo", "3301207"}; + rows[3613] = new String[] {"RJ", "Casimiro de Abreu", "3301306"}; + rows[3614] = new String[] {"RJ", "Comendador Levy Gasparian", "3300951"}; + rows[3615] = new String[] {"RJ", "Concei\u00e7\u00e3o de Macabu", "3301405"}; + rows[3616] = new String[] {"RJ", "Cordeiro", "3301504"}; + rows[3617] = new String[] {"RJ", "Duas Barras", "3301603"}; + rows[3618] = new String[] {"RJ", "Duque de Caxias", "3301702"}; + rows[3619] = new String[] {"RJ", "Engenheiro Paulo de Frontin", "3301801"}; + rows[3620] = new String[] {"RJ", "Guapimirim", "3301850"}; + rows[3621] = new String[] {"RJ", "Iguaba Grande", "3301876"}; + rows[3622] = new String[] {"RJ", "Itabora\u00ed", "3301900"}; + rows[3623] = new String[] {"RJ", "Itagua\u00ed", "3302007"}; + rows[3624] = new String[] {"RJ", "Italva", "3302056"}; + rows[3625] = new String[] {"RJ", "Itaocara", "3302106"}; + rows[3626] = new String[] {"RJ", "Itaperuna", "3302205"}; + rows[3627] = new String[] {"RJ", "Itatiaia", "3302254"}; + rows[3628] = new String[] {"RJ", "Japeri", "3302270"}; + rows[3629] = new String[] {"RJ", "Laje do Muria\u00e9", "3302304"}; + rows[3630] = new String[] {"RJ", "Maca\u00e9", "3302403"}; + rows[3631] = new String[] {"RJ", "Macuco", "3302452"}; + rows[3632] = new String[] {"RJ", "Mag\u00e9", "3302502"}; + rows[3633] = new String[] {"RJ", "Mangaratiba", "3302601"}; + rows[3634] = new String[] {"RJ", "Maric\u00e1", "3302700"}; + rows[3635] = new String[] {"RJ", "Mendes", "3302809"}; + rows[3636] = new String[] {"RJ", "Mesquita", "3302858"}; + rows[3637] = new String[] {"RJ", "Miguel Pereira", "3302908"}; + rows[3638] = new String[] {"RJ", "Miracema", "3303005"}; + rows[3639] = new String[] {"RJ", "Natividade", "3303104"}; + rows[3640] = new String[] {"RJ", "Nil\u00f3polis", "3303203"}; + rows[3641] = new String[] {"RJ", "Niter\u00f3i", "3303302"}; + rows[3642] = new String[] {"RJ", "Nova Friburgo", "3303401"}; + rows[3643] = new String[] {"RJ", "Nova Igua\u00e7u", "3303500"}; + rows[3644] = new String[] {"RJ", "Paracambi", "3303609"}; + rows[3645] = new String[] {"RJ", "Para\u00edba do Sul", "3303708"}; + rows[3646] = new String[] {"RJ", "Paraty", "3303807"}; + rows[3647] = new String[] {"RJ", "Paty do Alferes", "3303856"}; + rows[3648] = new String[] {"RJ", "Petr\u00f3polis", "3303906"}; + rows[3649] = new String[] {"RJ", "Pinheiral", "3303955"}; + rows[3650] = new String[] {"RJ", "Pira\u00ed", "3304003"}; + rows[3651] = new String[] {"RJ", "Porci\u00fancula", "3304102"}; + rows[3652] = new String[] {"RJ", "Porto Real", "3304110"}; + rows[3653] = new String[] {"RJ", "Quatis", "3304128"}; + rows[3654] = new String[] {"RJ", "Queimados", "3304144"}; + rows[3655] = new String[] {"RJ", "Quissam\u00e3", "3304151"}; + rows[3656] = new String[] {"RJ", "Resende", "3304201"}; + rows[3657] = new String[] {"RJ", "Rio Bonito", "3304300"}; + rows[3658] = new String[] {"RJ", "Rio Claro", "3304409"}; + rows[3659] = new String[] {"RJ", "Rio das Flores", "3304508"}; + rows[3660] = new String[] {"RJ", "Rio das Ostras", "3304524"}; + rows[3661] = new String[] {"RJ", "Rio de Janeiro", "3304557"}; + rows[3662] = new String[] {"RJ", "Santa Maria Madalena", "3304607"}; + rows[3663] = new String[] {"RJ", "Santo Ant\u00f4nio de P\u00e1dua", "3304706"}; + rows[3664] = new String[] {"RJ", "S\u00e3o Fid\u00e9lis", "3304805"}; + rows[3665] = new String[] {"RJ", "S\u00e3o Francisco de Itabapoana", "3304755"}; + rows[3666] = new String[] {"RJ", "S\u00e3o Gon\u00e7alo", "3304904"}; + rows[3667] = new String[] {"RJ", "S\u00e3o Jo\u00e3o da Barra", "3305000"}; + rows[3668] = new String[] {"RJ", "S\u00e3o Jo\u00e3o de Meriti", "3305109"}; + rows[3669] = new String[] {"RJ", "S\u00e3o Jos\u00e9 de Ub\u00e1", "3305133"}; + rows[3670] = new String[] {"RJ", "S\u00e3o Jos\u00e9 do Vale do Rio Preto", "3305158"}; + rows[3671] = new String[] {"RJ", "S\u00e3o Pedro da Aldeia", "3305208"}; + rows[3672] = new String[] {"RJ", "S\u00e3o Sebasti\u00e3o do Alto", "3305307"}; + rows[3673] = new String[] {"RJ", "Sapucaia", "3305406"}; + rows[3674] = new String[] {"RJ", "Saquarema", "3305505"}; + rows[3675] = new String[] {"RJ", "Serop\u00e9dica", "3305554"}; + rows[3676] = new String[] {"RJ", "Silva Jardim", "3305604"}; + rows[3677] = new String[] {"RJ", "Sumidouro", "3305703"}; + rows[3678] = new String[] {"RJ", "Tangu\u00e1", "3305752"}; + rows[3679] = new String[] {"RJ", "Teres\u00f3polis", "3305802"}; + rows[3680] = new String[] {"RJ", "Trajano de Moraes", "3305901"}; + rows[3681] = new String[] {"RJ", "Tr\u00eas Rios", "3306008"}; + rows[3682] = new String[] {"RJ", "Valen\u00e7a", "3306107"}; + rows[3683] = new String[] {"RJ", "Varre-Sai", "3306156"}; + rows[3684] = new String[] {"RJ", "Vassouras", "3306206"}; + rows[3685] = new String[] {"RJ", "Volta Redonda", "3306305"}; + rows[3686] = new String[] {"RN", "Acari", "2400109"}; + rows[3687] = new String[] {"RN", "Afonso Bezerra", "2400307"}; + rows[3688] = new String[] {"RN", "\u00c1gua Nova", "2400406"}; + rows[3689] = new String[] {"RN", "Alexandria", "2400505"}; + rows[3690] = new String[] {"RN", "Almino Afonso", "2400604"}; + rows[3691] = new String[] {"RN", "Alto do Rodrigues", "2400703"}; + rows[3692] = new String[] {"RN", "Angicos", "2400802"}; + rows[3693] = new String[] {"RN", "Ant\u00f4nio Martins", "2400901"}; + rows[3694] = new String[] {"RN", "Apodi", "2401008"}; + rows[3695] = new String[] {"RN", "Areia Branca", "2401107"}; + rows[3696] = new String[] {"RN", "Arez", "2401206"}; + rows[3697] = new String[] {"RN", "Ass\u00fa", "2400208"}; + rows[3698] = new String[] {"RN", "Ba\u00eda Formosa", "2401404"}; + rows[3699] = new String[] {"RN", "Bara\u00fana", "2401453"}; + rows[3700] = new String[] {"RN", "Barcelona", "2401503"}; + rows[3701] = new String[] {"RN", "Bento Fernandes", "2401602"}; + rows[3702] = new String[] {"RN", "Bod\u00f3", "2401651"}; + rows[3703] = new String[] {"RN", "Bom Jesus", "2401701"}; + rows[3704] = new String[] {"RN", "Brejinho", "2401800"}; + rows[3705] = new String[] {"RN", "Cai\u00e7ara do Norte", "2401859"}; + rows[3706] = new String[] {"RN", "Cai\u00e7ara do Rio do Vento", "2401909"}; + rows[3707] = new String[] {"RN", "Caic\u00f3", "2402006"}; + rows[3708] = new String[] {"RN", "Campo Grande", "2401305"}; + rows[3709] = new String[] {"RN", "Campo Redondo", "2402105"}; + rows[3710] = new String[] {"RN", "Canguaretama", "2402204"}; + rows[3711] = new String[] {"RN", "Cara\u00fabas", "2402303"}; + rows[3712] = new String[] {"RN", "Carna\u00faba dos Dantas", "2402402"}; + rows[3713] = new String[] {"RN", "Carnaubais", "2402501"}; + rows[3714] = new String[] {"RN", "Cear\u00e1-Mirim", "2402600"}; + rows[3715] = new String[] {"RN", "Cerro Cor\u00e1", "2402709"}; + rows[3716] = new String[] {"RN", "Coronel Ezequiel", "2402808"}; + rows[3717] = new String[] {"RN", "Coronel Jo\u00e3o Pessoa", "2402907"}; + rows[3718] = new String[] {"RN", "Cruzeta", "2403004"}; + rows[3719] = new String[] {"RN", "Currais Novos", "2403103"}; + rows[3720] = new String[] {"RN", "Doutor Severiano", "2403202"}; + rows[3721] = new String[] {"RN", "Encanto", "2403301"}; + rows[3722] = new String[] {"RN", "Equador", "2403400"}; + rows[3723] = new String[] {"RN", "Esp\u00edrito Santo", "2403509"}; + rows[3724] = new String[] {"RN", "Extremoz", "2403608"}; + rows[3725] = new String[] {"RN", "Felipe Guerra", "2403707"}; + rows[3726] = new String[] {"RN", "Fernando Pedroza", "2403756"}; + rows[3727] = new String[] {"RN", "Flor\u00e2nia", "2403806"}; + rows[3728] = new String[] {"RN", "Francisco Dantas", "2403905"}; + rows[3729] = new String[] {"RN", "Frutuoso Gomes", "2404002"}; + rows[3730] = new String[] {"RN", "Galinhos", "2404101"}; + rows[3731] = new String[] {"RN", "Goianinha", "2404200"}; + rows[3732] = new String[] {"RN", "Governador Dix-Sept Rosado", "2404309"}; + rows[3733] = new String[] {"RN", "Grossos", "2404408"}; + rows[3734] = new String[] {"RN", "Guamar\u00e9", "2404507"}; + rows[3735] = new String[] {"RN", "Ielmo Marinho", "2404606"}; + rows[3736] = new String[] {"RN", "Ipangua\u00e7u", "2404705"}; + rows[3737] = new String[] {"RN", "Ipueira", "2404804"}; + rows[3738] = new String[] {"RN", "Itaj\u00e1", "2404853"}; + rows[3739] = new String[] {"RN", "Ita\u00fa", "2404903"}; + rows[3740] = new String[] {"RN", "Ja\u00e7an\u00e3", "2405009"}; + rows[3741] = new String[] {"RN", "Janda\u00edra", "2405108"}; + rows[3742] = new String[] {"RN", "Jandu\u00eds", "2405207"}; + rows[3743] = new String[] {"RN", "Janu\u00e1rio Cicco", "2405306"}; + rows[3744] = new String[] {"RN", "Japi", "2405405"}; + rows[3745] = new String[] {"RN", "Jardim de Angicos", "2405504"}; + rows[3746] = new String[] {"RN", "Jardim de Piranhas", "2405603"}; + rows[3747] = new String[] {"RN", "Jardim do Serid\u00f3", "2405702"}; + rows[3748] = new String[] {"RN", "Jo\u00e3o C\u00e2mara", "2405801"}; + rows[3749] = new String[] {"RN", "Jo\u00e3o Dias", "2405900"}; + rows[3750] = new String[] {"RN", "Jos\u00e9 da Penha", "2406007"}; + rows[3751] = new String[] {"RN", "Jucurutu", "2406106"}; + rows[3752] = new String[] {"RN", "Jundi\u00e1", "2406155"}; + rows[3753] = new String[] {"RN", "Lagoa d'Anta", "2406205"}; + rows[3754] = new String[] {"RN", "Lagoa de Pedras", "2406304"}; + rows[3755] = new String[] {"RN", "Lagoa de Velhos", "2406403"}; + rows[3756] = new String[] {"RN", "Lagoa Nova", "2406502"}; + rows[3757] = new String[] {"RN", "Lagoa Salgada", "2406601"}; + rows[3758] = new String[] {"RN", "Lajes", "2406700"}; + rows[3759] = new String[] {"RN", "Lajes Pintadas", "2406809"}; + rows[3760] = new String[] {"RN", "Lucr\u00e9cia", "2406908"}; + rows[3761] = new String[] {"RN", "Lu\u00eds Gomes", "2407005"}; + rows[3762] = new String[] {"RN", "Maca\u00edba", "2407104"}; + rows[3763] = new String[] {"RN", "Macau", "2407203"}; + rows[3764] = new String[] {"RN", "Major Sales", "2407252"}; + rows[3765] = new String[] {"RN", "Marcelino Vieira", "2407302"}; + rows[3766] = new String[] {"RN", "Martins", "2407401"}; + rows[3767] = new String[] {"RN", "Maxaranguape", "2407500"}; + rows[3768] = new String[] {"RN", "Messias Targino", "2407609"}; + rows[3769] = new String[] {"RN", "Montanhas", "2407708"}; + rows[3770] = new String[] {"RN", "Monte Alegre", "2407807"}; + rows[3771] = new String[] {"RN", "Monte das Gameleiras", "2407906"}; + rows[3772] = new String[] {"RN", "Mossor\u00f3", "2408003"}; + rows[3773] = new String[] {"RN", "Natal", "2408102"}; + rows[3774] = new String[] {"RN", "N\u00edsia Floresta", "2408201"}; + rows[3775] = new String[] {"RN", "Nova Cruz", "2408300"}; + rows[3776] = new String[] {"RN", "Olho d'\u00c1gua do Borges", "2408409"}; + rows[3777] = new String[] {"RN", "Ouro Branco", "2408508"}; + rows[3778] = new String[] {"RN", "Paran\u00e1", "2408607"}; + rows[3779] = new String[] {"RN", "Para\u00fa", "2408706"}; + rows[3780] = new String[] {"RN", "Parazinho", "2408805"}; + rows[3781] = new String[] {"RN", "Parelhas", "2408904"}; + rows[3782] = new String[] {"RN", "Parnamirim", "2403251"}; + rows[3783] = new String[] {"RN", "Passa e Fica", "2409100"}; + rows[3784] = new String[] {"RN", "Passagem", "2409209"}; + rows[3785] = new String[] {"RN", "Patu", "2409308"}; + rows[3786] = new String[] {"RN", "Pau dos Ferros", "2409407"}; + rows[3787] = new String[] {"RN", "Pedra Grande", "2409506"}; + rows[3788] = new String[] {"RN", "Pedra Preta", "2409605"}; + rows[3789] = new String[] {"RN", "Pedro Avelino", "2409704"}; + rows[3790] = new String[] {"RN", "Pedro Velho", "2409803"}; + rows[3791] = new String[] {"RN", "Pend\u00eancias", "2409902"}; + rows[3792] = new String[] {"RN", "Pil\u00f5es", "2410009"}; + rows[3793] = new String[] {"RN", "Po\u00e7o Branco", "2410108"}; + rows[3794] = new String[] {"RN", "Portalegre", "2410207"}; + rows[3795] = new String[] {"RN", "Porto do Mangue", "2410256"}; + rows[3796] = new String[] {"RN", "Pureza", "2410405"}; + rows[3797] = new String[] {"RN", "Rafael Fernandes", "2410504"}; + rows[3798] = new String[] {"RN", "Rafael Godeiro", "2410603"}; + rows[3799] = new String[] {"RN", "Riacho da Cruz", "2410702"}; + } + + private static void municipalitiesRows19(String[][] rows) { + rows[3800] = new String[] {"RN", "Riacho de Santana", "2410801"}; + rows[3801] = new String[] {"RN", "Riachuelo", "2410900"}; + rows[3802] = new String[] {"RN", "Rio do Fogo", "2408953"}; + rows[3803] = new String[] {"RN", "Rodolfo Fernandes", "2411007"}; + rows[3804] = new String[] {"RN", "Ruy Barbosa", "2411106"}; + rows[3805] = new String[] {"RN", "Santa Cruz", "2411205"}; + rows[3806] = new String[] {"RN", "Santa Maria", "2409332"}; + rows[3807] = new String[] {"RN", "Santana do Matos", "2411403"}; + rows[3808] = new String[] {"RN", "Santana do Serid\u00f3", "2411429"}; + rows[3809] = new String[] {"RN", "Santo Ant\u00f4nio", "2411502"}; + rows[3810] = new String[] {"RN", "S\u00e3o Bento do Norte", "2411601"}; + rows[3811] = new String[] {"RN", "S\u00e3o Bento do Trair\u00ed", "2411700"}; + rows[3812] = new String[] {"RN", "S\u00e3o Fernando", "2411809"}; + rows[3813] = new String[] {"RN", "S\u00e3o Francisco do Oeste", "2411908"}; + rows[3814] = new String[] {"RN", "S\u00e3o Gon\u00e7alo do Amarante", "2412005"}; + rows[3815] = new String[] {"RN", "S\u00e3o Jo\u00e3o do Sabugi", "2412104"}; + rows[3816] = new String[] {"RN", "S\u00e3o Jos\u00e9 de Mipibu", "2412203"}; + rows[3817] = new String[] {"RN", "S\u00e3o Jos\u00e9 do Campestre", "2412302"}; + rows[3818] = new String[] {"RN", "S\u00e3o Jos\u00e9 do Serid\u00f3", "2412401"}; + rows[3819] = new String[] {"RN", "S\u00e3o Miguel", "2412500"}; + rows[3820] = new String[] {"RN", "S\u00e3o Miguel do Gostoso", "2412559"}; + rows[3821] = new String[] {"RN", "S\u00e3o Paulo do Potengi", "2412609"}; + rows[3822] = new String[] {"RN", "S\u00e3o Pedro", "2412708"}; + rows[3823] = new String[] {"RN", "S\u00e3o Rafael", "2412807"}; + rows[3824] = new String[] {"RN", "S\u00e3o Tom\u00e9", "2412906"}; + rows[3825] = new String[] {"RN", "S\u00e3o Vicente", "2413003"}; + rows[3826] = new String[] {"RN", "Senador El\u00f3i de Souza", "2413102"}; + rows[3827] = new String[] {"RN", "Senador Georgino Avelino", "2413201"}; + rows[3828] = new String[] {"RN", "Serra Caiada", "2410306"}; + rows[3829] = new String[] {"RN", "Serra de S\u00e3o Bento", "2413300"}; + rows[3830] = new String[] {"RN", "Serra do Mel", "2413359"}; + rows[3831] = new String[] {"RN", "Serra Negra do Norte", "2413409"}; + rows[3832] = new String[] {"RN", "Serrinha", "2413508"}; + rows[3833] = new String[] {"RN", "Serrinha dos Pintos", "2413557"}; + rows[3834] = new String[] {"RN", "Severiano Melo", "2413607"}; + rows[3835] = new String[] {"RN", "S\u00edtio Novo", "2413706"}; + rows[3836] = new String[] {"RN", "Taboleiro Grande", "2413805"}; + rows[3837] = new String[] {"RN", "Taipu", "2413904"}; + rows[3838] = new String[] {"RN", "Tangar\u00e1", "2414001"}; + rows[3839] = new String[] {"RN", "Tenente Ananias", "2414100"}; + rows[3840] = new String[] {"RN", "Tenente Laurentino Cruz", "2414159"}; + rows[3841] = new String[] {"RN", "Tibau", "2411056"}; + rows[3842] = new String[] {"RN", "Tibau do Sul", "2414209"}; + rows[3843] = new String[] {"RN", "Timba\u00faba dos Batistas", "2414308"}; + rows[3844] = new String[] {"RN", "Touros", "2414407"}; + rows[3845] = new String[] {"RN", "Triunfo Potiguar", "2414456"}; + rows[3846] = new String[] {"RN", "Umarizal", "2414506"}; + rows[3847] = new String[] {"RN", "Upanema", "2414605"}; + rows[3848] = new String[] {"RN", "V\u00e1rzea", "2414704"}; + rows[3849] = new String[] {"RN", "Venha-Ver", "2414753"}; + rows[3850] = new String[] {"RN", "Vera Cruz", "2414803"}; + rows[3851] = new String[] {"RN", "Vi\u00e7osa", "2414902"}; + rows[3852] = new String[] {"RN", "Vila Flor", "2415008"}; + rows[3853] = new String[] {"RS", "Acegu\u00e1", "4300034"}; + rows[3854] = new String[] {"RS", "\u00c1gua Santa", "4300059"}; + rows[3855] = new String[] {"RS", "Agudo", "4300109"}; + rows[3856] = new String[] {"RS", "Ajuricaba", "4300208"}; + rows[3857] = new String[] {"RS", "Alecrim", "4300307"}; + rows[3858] = new String[] {"RS", "Alegrete", "4300406"}; + rows[3859] = new String[] {"RS", "Alegria", "4300455"}; + rows[3860] = new String[] {"RS", "Almirante Tamandar\u00e9 do Sul", "4300471"}; + rows[3861] = new String[] {"RS", "Alpestre", "4300505"}; + rows[3862] = new String[] {"RS", "Alto Alegre", "4300554"}; + rows[3863] = new String[] {"RS", "Alto Feliz", "4300570"}; + rows[3864] = new String[] {"RS", "Alvorada", "4300604"}; + rows[3865] = new String[] {"RS", "Amaral Ferrador", "4300638"}; + rows[3866] = new String[] {"RS", "Ametista do Sul", "4300646"}; + rows[3867] = new String[] {"RS", "Andr\u00e9 da Rocha", "4300661"}; + rows[3868] = new String[] {"RS", "Anta Gorda", "4300703"}; + rows[3869] = new String[] {"RS", "Ant\u00f4nio Prado", "4300802"}; + rows[3870] = new String[] {"RS", "Arambar\u00e9", "4300851"}; + rows[3871] = new String[] {"RS", "Araric\u00e1", "4300877"}; + rows[3872] = new String[] {"RS", "Aratiba", "4300901"}; + rows[3873] = new String[] {"RS", "Arroio do Meio", "4301008"}; + rows[3874] = new String[] {"RS", "Arroio do Padre", "4301073"}; + rows[3875] = new String[] {"RS", "Arroio do Sal", "4301057"}; + rows[3876] = new String[] {"RS", "Arroio do Tigre", "4301206"}; + rows[3877] = new String[] {"RS", "Arroio dos Ratos", "4301107"}; + rows[3878] = new String[] {"RS", "Arroio Grande", "4301305"}; + rows[3879] = new String[] {"RS", "Arvorezinha", "4301404"}; + rows[3880] = new String[] {"RS", "Augusto Pestana", "4301503"}; + rows[3881] = new String[] {"RS", "\u00c1urea", "4301552"}; + rows[3882] = new String[] {"RS", "Bag\u00e9", "4301602"}; + rows[3883] = new String[] {"RS", "Balne\u00e1rio Pinhal", "4301636"}; + rows[3884] = new String[] {"RS", "Bar\u00e3o", "4301651"}; + rows[3885] = new String[] {"RS", "Bar\u00e3o de Cotegipe", "4301701"}; + rows[3886] = new String[] {"RS", "Bar\u00e3o do Triunfo", "4301750"}; + rows[3887] = new String[] {"RS", "Barra do Guarita", "4301859"}; + rows[3888] = new String[] {"RS", "Barra do Quara\u00ed", "4301875"}; + rows[3889] = new String[] {"RS", "Barra do Ribeiro", "4301909"}; + rows[3890] = new String[] {"RS", "Barra do Rio Azul", "4301925"}; + rows[3891] = new String[] {"RS", "Barra Funda", "4301958"}; + rows[3892] = new String[] {"RS", "Barrac\u00e3o", "4301800"}; + rows[3893] = new String[] {"RS", "Barros Cassal", "4302006"}; + rows[3894] = new String[] {"RS", "Benjamin Constant do Sul", "4302055"}; + rows[3895] = new String[] {"RS", "Bento Gon\u00e7alves", "4302105"}; + rows[3896] = new String[] {"RS", "Boa Vista das Miss\u00f5es", "4302154"}; + rows[3897] = new String[] {"RS", "Boa Vista do Buric\u00e1", "4302204"}; + rows[3898] = new String[] {"RS", "Boa Vista do Cadeado", "4302220"}; + rows[3899] = new String[] {"RS", "Boa Vista do Incra", "4302238"}; + rows[3900] = new String[] {"RS", "Boa Vista do Sul", "4302253"}; + rows[3901] = new String[] {"RS", "Bom Jesus", "4302303"}; + rows[3902] = new String[] {"RS", "Bom Princ\u00edpio", "4302352"}; + rows[3903] = new String[] {"RS", "Bom Progresso", "4302378"}; + rows[3904] = new String[] {"RS", "Bom Retiro do Sul", "4302402"}; + rows[3905] = new String[] {"RS", "Boqueir\u00e3o do Le\u00e3o", "4302451"}; + rows[3906] = new String[] {"RS", "Bossoroca", "4302501"}; + rows[3907] = new String[] {"RS", "Bozano", "4302584"}; + rows[3908] = new String[] {"RS", "Braga", "4302600"}; + rows[3909] = new String[] {"RS", "Brochier", "4302659"}; + rows[3910] = new String[] {"RS", "Buti\u00e1", "4302709"}; + rows[3911] = new String[] {"RS", "Ca\u00e7apava do Sul", "4302808"}; + rows[3912] = new String[] {"RS", "Cacequi", "4302907"}; + rows[3913] = new String[] {"RS", "Cachoeira do Sul", "4303004"}; + rows[3914] = new String[] {"RS", "Cachoeirinha", "4303103"}; + rows[3915] = new String[] {"RS", "Cacique Doble", "4303202"}; + rows[3916] = new String[] {"RS", "Caibat\u00e9", "4303301"}; + rows[3917] = new String[] {"RS", "Cai\u00e7ara", "4303400"}; + rows[3918] = new String[] {"RS", "Camaqu\u00e3", "4303509"}; + rows[3919] = new String[] {"RS", "Camargo", "4303558"}; + rows[3920] = new String[] {"RS", "Cambar\u00e1 do Sul", "4303608"}; + rows[3921] = new String[] {"RS", "Campestre da Serra", "4303673"}; + rows[3922] = new String[] {"RS", "Campina das Miss\u00f5es", "4303707"}; + rows[3923] = new String[] {"RS", "Campinas do Sul", "4303806"}; + rows[3924] = new String[] {"RS", "Campo Bom", "4303905"}; + rows[3925] = new String[] {"RS", "Campo Novo", "4304002"}; + rows[3926] = new String[] {"RS", "Campos Borges", "4304101"}; + rows[3927] = new String[] {"RS", "Candel\u00e1ria", "4304200"}; + rows[3928] = new String[] {"RS", "C\u00e2ndido God\u00f3i", "4304309"}; + rows[3929] = new String[] {"RS", "Candiota", "4304358"}; + rows[3930] = new String[] {"RS", "Canela", "4304408"}; + rows[3931] = new String[] {"RS", "Cangu\u00e7u", "4304507"}; + rows[3932] = new String[] {"RS", "Canoas", "4304606"}; + rows[3933] = new String[] {"RS", "Canudos do Vale", "4304614"}; + rows[3934] = new String[] {"RS", "Cap\u00e3o Bonito do Sul", "4304622"}; + rows[3935] = new String[] {"RS", "Cap\u00e3o da Canoa", "4304630"}; + rows[3936] = new String[] {"RS", "Cap\u00e3o do Cip\u00f3", "4304655"}; + rows[3937] = new String[] {"RS", "Cap\u00e3o do Le\u00e3o", "4304663"}; + rows[3938] = new String[] {"RS", "Capela de Santana", "4304689"}; + rows[3939] = new String[] {"RS", "Capit\u00e3o", "4304697"}; + rows[3940] = new String[] {"RS", "Capivari do Sul", "4304671"}; + rows[3941] = new String[] {"RS", "Cara\u00e1", "4304713"}; + rows[3942] = new String[] {"RS", "Carazinho", "4304705"}; + rows[3943] = new String[] {"RS", "Carlos Barbosa", "4304804"}; + rows[3944] = new String[] {"RS", "Carlos Gomes", "4304853"}; + rows[3945] = new String[] {"RS", "Casca", "4304903"}; + rows[3946] = new String[] {"RS", "Caseiros", "4304952"}; + rows[3947] = new String[] {"RS", "Catu\u00edpe", "4305009"}; + rows[3948] = new String[] {"RS", "Caxias do Sul", "4305108"}; + rows[3949] = new String[] {"RS", "Centen\u00e1rio", "4305116"}; + rows[3950] = new String[] {"RS", "Cerrito", "4305124"}; + rows[3951] = new String[] {"RS", "Cerro Branco", "4305132"}; + rows[3952] = new String[] {"RS", "Cerro Grande", "4305157"}; + rows[3953] = new String[] {"RS", "Cerro Grande do Sul", "4305173"}; + rows[3954] = new String[] {"RS", "Cerro Largo", "4305207"}; + rows[3955] = new String[] {"RS", "Chapada", "4305306"}; + rows[3956] = new String[] {"RS", "Charqueadas", "4305355"}; + rows[3957] = new String[] {"RS", "Charrua", "4305371"}; + rows[3958] = new String[] {"RS", "Chiapetta", "4305405"}; + rows[3959] = new String[] {"RS", "Chu\u00ed", "4305439"}; + rows[3960] = new String[] {"RS", "Chuvisca", "4305447"}; + rows[3961] = new String[] {"RS", "Cidreira", "4305454"}; + rows[3962] = new String[] {"RS", "Cir\u00edaco", "4305504"}; + rows[3963] = new String[] {"RS", "Colinas", "4305587"}; + rows[3964] = new String[] {"RS", "Colorado", "4305603"}; + rows[3965] = new String[] {"RS", "Condor", "4305702"}; + rows[3966] = new String[] {"RS", "Constantina", "4305801"}; + rows[3967] = new String[] {"RS", "Coqueiro Baixo", "4305835"}; + rows[3968] = new String[] {"RS", "Coqueiros do Sul", "4305850"}; + rows[3969] = new String[] {"RS", "Coronel Barros", "4305871"}; + rows[3970] = new String[] {"RS", "Coronel Bicaco", "4305900"}; + rows[3971] = new String[] {"RS", "Coronel Pilar", "4305934"}; + rows[3972] = new String[] {"RS", "Cotipor\u00e3", "4305959"}; + rows[3973] = new String[] {"RS", "Coxilha", "4305975"}; + rows[3974] = new String[] {"RS", "Crissiumal", "4306007"}; + rows[3975] = new String[] {"RS", "Cristal", "4306056"}; + rows[3976] = new String[] {"RS", "Cristal do Sul", "4306072"}; + rows[3977] = new String[] {"RS", "Cruz Alta", "4306106"}; + rows[3978] = new String[] {"RS", "Cruzaltense", "4306130"}; + rows[3979] = new String[] {"RS", "Cruzeiro do Sul", "4306205"}; + rows[3980] = new String[] {"RS", "David Canabarro", "4306304"}; + rows[3981] = new String[] {"RS", "Derrubadas", "4306320"}; + rows[3982] = new String[] {"RS", "Dezesseis de Novembro", "4306353"}; + rows[3983] = new String[] {"RS", "Dilermando de Aguiar", "4306379"}; + rows[3984] = new String[] {"RS", "Dois Irm\u00e3os", "4306403"}; + rows[3985] = new String[] {"RS", "Dois Irm\u00e3os das Miss\u00f5es", "4306429"}; + rows[3986] = new String[] {"RS", "Dois Lajeados", "4306452"}; + rows[3987] = new String[] {"RS", "Dom Feliciano", "4306502"}; + rows[3988] = new String[] {"RS", "Dom Pedrito", "4306601"}; + rows[3989] = new String[] {"RS", "Dom Pedro de Alc\u00e2ntara", "4306551"}; + rows[3990] = new String[] {"RS", "Dona Francisca", "4306700"}; + rows[3991] = new String[] {"RS", "Doutor Maur\u00edcio Cardoso", "4306734"}; + rows[3992] = new String[] {"RS", "Doutor Ricardo", "4306759"}; + rows[3993] = new String[] {"RS", "Eldorado do Sul", "4306767"}; + rows[3994] = new String[] {"RS", "Encantado", "4306809"}; + rows[3995] = new String[] {"RS", "Encruzilhada do Sul", "4306908"}; + rows[3996] = new String[] {"RS", "Engenho Velho", "4306924"}; + rows[3997] = new String[] {"RS", "Entre Rios do Sul", "4306957"}; + rows[3998] = new String[] {"RS", "Entre-Iju\u00eds", "4306932"}; + rows[3999] = new String[] {"RS", "Erebango", "4306973"}; + } + + private static void municipalitiesRows20(String[][] rows) { + rows[4000] = new String[] {"RS", "Erechim", "4307005"}; + rows[4001] = new String[] {"RS", "Ernestina", "4307054"}; + rows[4002] = new String[] {"RS", "Erval Grande", "4307203"}; + rows[4003] = new String[] {"RS", "Erval Seco", "4307302"}; + rows[4004] = new String[] {"RS", "Esmeralda", "4307401"}; + rows[4005] = new String[] {"RS", "Esperan\u00e7a do Sul", "4307450"}; + rows[4006] = new String[] {"RS", "Espumoso", "4307500"}; + rows[4007] = new String[] {"RS", "Esta\u00e7\u00e3o", "4307559"}; + rows[4008] = new String[] {"RS", "Est\u00e2ncia Velha", "4307609"}; + rows[4009] = new String[] {"RS", "Esteio", "4307708"}; + rows[4010] = new String[] {"RS", "Estrela", "4307807"}; + rows[4011] = new String[] {"RS", "Estrela Velha", "4307815"}; + rows[4012] = new String[] {"RS", "Eug\u00eanio de Castro", "4307831"}; + rows[4013] = new String[] {"RS", "Fagundes Varela", "4307864"}; + rows[4014] = new String[] {"RS", "Farroupilha", "4307906"}; + rows[4015] = new String[] {"RS", "Faxinal do Soturno", "4308003"}; + rows[4016] = new String[] {"RS", "Faxinalzinho", "4308052"}; + rows[4017] = new String[] {"RS", "Fazenda Vilanova", "4308078"}; + rows[4018] = new String[] {"RS", "Feliz", "4308102"}; + rows[4019] = new String[] {"RS", "Flores da Cunha", "4308201"}; + rows[4020] = new String[] {"RS", "Floriano Peixoto", "4308250"}; + rows[4021] = new String[] {"RS", "Fontoura Xavier", "4308300"}; + rows[4022] = new String[] {"RS", "Formigueiro", "4308409"}; + rows[4023] = new String[] {"RS", "Forquetinha", "4308433"}; + rows[4024] = new String[] {"RS", "Fortaleza dos Valos", "4308458"}; + rows[4025] = new String[] {"RS", "Frederico Westphalen", "4308508"}; + rows[4026] = new String[] {"RS", "Garibaldi", "4308607"}; + rows[4027] = new String[] {"RS", "Garruchos", "4308656"}; + rows[4028] = new String[] {"RS", "Gaurama", "4308706"}; + rows[4029] = new String[] {"RS", "General C\u00e2mara", "4308805"}; + rows[4030] = new String[] {"RS", "Gentil", "4308854"}; + rows[4031] = new String[] {"RS", "Get\u00falio Vargas", "4308904"}; + rows[4032] = new String[] {"RS", "Giru\u00e1", "4309001"}; + rows[4033] = new String[] {"RS", "Glorinha", "4309050"}; + rows[4034] = new String[] {"RS", "Gramado", "4309100"}; + rows[4035] = new String[] {"RS", "Gramado dos Loureiros", "4309126"}; + rows[4036] = new String[] {"RS", "Gramado Xavier", "4309159"}; + rows[4037] = new String[] {"RS", "Gravata\u00ed", "4309209"}; + rows[4038] = new String[] {"RS", "Guabiju", "4309258"}; + rows[4039] = new String[] {"RS", "Gua\u00edba", "4309308"}; + rows[4040] = new String[] {"RS", "Guapor\u00e9", "4309407"}; + rows[4041] = new String[] {"RS", "Guarani das Miss\u00f5es", "4309506"}; + rows[4042] = new String[] {"RS", "Harmonia", "4309555"}; + rows[4043] = new String[] {"RS", "Herval", "4307104"}; + rows[4044] = new String[] {"RS", "Herveiras", "4309571"}; + rows[4045] = new String[] {"RS", "Horizontina", "4309605"}; + rows[4046] = new String[] {"RS", "Hulha Negra", "4309654"}; + rows[4047] = new String[] {"RS", "Humait\u00e1", "4309704"}; + rows[4048] = new String[] {"RS", "Ibarama", "4309753"}; + rows[4049] = new String[] {"RS", "Ibia\u00e7\u00e1", "4309803"}; + rows[4050] = new String[] {"RS", "Ibiraiaras", "4309902"}; + rows[4051] = new String[] {"RS", "Ibirapuit\u00e3", "4309951"}; + rows[4052] = new String[] {"RS", "Ibirub\u00e1", "4310009"}; + rows[4053] = new String[] {"RS", "Igrejinha", "4310108"}; + rows[4054] = new String[] {"RS", "Iju\u00ed", "4310207"}; + rows[4055] = new String[] {"RS", "Il\u00f3polis", "4310306"}; + rows[4056] = new String[] {"RS", "Imb\u00e9", "4310330"}; + rows[4057] = new String[] {"RS", "Imigrante", "4310363"}; + rows[4058] = new String[] {"RS", "Independ\u00eancia", "4310405"}; + rows[4059] = new String[] {"RS", "Inhacor\u00e1", "4310413"}; + rows[4060] = new String[] {"RS", "Ip\u00ea", "4310439"}; + rows[4061] = new String[] {"RS", "Ipiranga do Sul", "4310462"}; + rows[4062] = new String[] {"RS", "Ira\u00ed", "4310504"}; + rows[4063] = new String[] {"RS", "Itaara", "4310538"}; + rows[4064] = new String[] {"RS", "Itacurubi", "4310553"}; + rows[4065] = new String[] {"RS", "Itapuca", "4310579"}; + rows[4066] = new String[] {"RS", "Itaqui", "4310603"}; + rows[4067] = new String[] {"RS", "Itati", "4310652"}; + rows[4068] = new String[] {"RS", "Itatiba do Sul", "4310702"}; + rows[4069] = new String[] {"RS", "Ivor\u00e1", "4310751"}; + rows[4070] = new String[] {"RS", "Ivoti", "4310801"}; + rows[4071] = new String[] {"RS", "Jaboticaba", "4310850"}; + rows[4072] = new String[] {"RS", "Jacuizinho", "4310876"}; + rows[4073] = new String[] {"RS", "Jacutinga", "4310900"}; + rows[4074] = new String[] {"RS", "Jaguar\u00e3o", "4311007"}; + rows[4075] = new String[] {"RS", "Jaguari", "4311106"}; + rows[4076] = new String[] {"RS", "Jaquirana", "4311122"}; + rows[4077] = new String[] {"RS", "Jari", "4311130"}; + rows[4078] = new String[] {"RS", "J\u00f3ia", "4311155"}; + rows[4079] = new String[] {"RS", "J\u00falio de Castilhos", "4311205"}; + rows[4080] = new String[] {"RS", "Lagoa Bonita do Sul", "4311239"}; + rows[4081] = new String[] {"RS", "Lagoa dos Tr\u00eas Cantos", "4311270"}; + rows[4082] = new String[] {"RS", "Lagoa Vermelha", "4311304"}; + rows[4083] = new String[] {"RS", "Lago\u00e3o", "4311254"}; + rows[4084] = new String[] {"RS", "Lajeado", "4311403"}; + rows[4085] = new String[] {"RS", "Lajeado do Bugre", "4311429"}; + rows[4086] = new String[] {"RS", "Lavras do Sul", "4311502"}; + rows[4087] = new String[] {"RS", "Liberato Salzano", "4311601"}; + rows[4088] = new String[] {"RS", "Lindolfo Collor", "4311627"}; + rows[4089] = new String[] {"RS", "Linha Nova", "4311643"}; + rows[4090] = new String[] {"RS", "Ma\u00e7ambar\u00e1", "4311718"}; + rows[4091] = new String[] {"RS", "Machadinho", "4311700"}; + rows[4092] = new String[] {"RS", "Mampituba", "4311734"}; + rows[4093] = new String[] {"RS", "Manoel Viana", "4311759"}; + rows[4094] = new String[] {"RS", "Maquin\u00e9", "4311775"}; + rows[4095] = new String[] {"RS", "Marat\u00e1", "4311791"}; + rows[4096] = new String[] {"RS", "Marau", "4311809"}; + rows[4097] = new String[] {"RS", "Marcelino Ramos", "4311908"}; + rows[4098] = new String[] {"RS", "Mariana Pimentel", "4311981"}; + rows[4099] = new String[] {"RS", "Mariano Moro", "4312005"}; + rows[4100] = new String[] {"RS", "Marques de Souza", "4312054"}; + rows[4101] = new String[] {"RS", "Mata", "4312104"}; + rows[4102] = new String[] {"RS", "Mato Castelhano", "4312138"}; + rows[4103] = new String[] {"RS", "Mato Leit\u00e3o", "4312153"}; + rows[4104] = new String[] {"RS", "Mato Queimado", "4312179"}; + rows[4105] = new String[] {"RS", "Maximiliano de Almeida", "4312203"}; + rows[4106] = new String[] {"RS", "Minas do Le\u00e3o", "4312252"}; + rows[4107] = new String[] {"RS", "Miragua\u00ed", "4312302"}; + rows[4108] = new String[] {"RS", "Montauri", "4312351"}; + rows[4109] = new String[] {"RS", "Monte Alegre dos Campos", "4312377"}; + rows[4110] = new String[] {"RS", "Monte Belo do Sul", "4312385"}; + rows[4111] = new String[] {"RS", "Montenegro", "4312401"}; + rows[4112] = new String[] {"RS", "Morma\u00e7o", "4312427"}; + rows[4113] = new String[] {"RS", "Morrinhos do Sul", "4312443"}; + rows[4114] = new String[] {"RS", "Morro Redondo", "4312450"}; + rows[4115] = new String[] {"RS", "Morro Reuter", "4312476"}; + rows[4116] = new String[] {"RS", "Mostardas", "4312500"}; + rows[4117] = new String[] {"RS", "Mu\u00e7um", "4312609"}; + rows[4118] = new String[] {"RS", "Muitos Cap\u00f5es", "4312617"}; + rows[4119] = new String[] {"RS", "Muliterno", "4312625"}; + rows[4120] = new String[] {"RS", "N\u00e3o-Me-Toque", "4312658"}; + rows[4121] = new String[] {"RS", "Nicolau Vergueiro", "4312674"}; + rows[4122] = new String[] {"RS", "Nonoai", "4312708"}; + rows[4123] = new String[] {"RS", "Nova Alvorada", "4312757"}; + rows[4124] = new String[] {"RS", "Nova Ara\u00e7\u00e1", "4312807"}; + rows[4125] = new String[] {"RS", "Nova Bassano", "4312906"}; + rows[4126] = new String[] {"RS", "Nova Boa Vista", "4312955"}; + rows[4127] = new String[] {"RS", "Nova Br\u00e9scia", "4313003"}; + rows[4128] = new String[] {"RS", "Nova Candel\u00e1ria", "4313011"}; + rows[4129] = new String[] {"RS", "Nova Esperan\u00e7a do Sul", "4313037"}; + rows[4130] = new String[] {"RS", "Nova Hartz", "4313060"}; + rows[4131] = new String[] {"RS", "Nova P\u00e1dua", "4313086"}; + rows[4132] = new String[] {"RS", "Nova Palma", "4313102"}; + rows[4133] = new String[] {"RS", "Nova Petr\u00f3polis", "4313201"}; + rows[4134] = new String[] {"RS", "Nova Prata", "4313300"}; + rows[4135] = new String[] {"RS", "Nova Ramada", "4313334"}; + rows[4136] = new String[] {"RS", "Nova Roma do Sul", "4313359"}; + rows[4137] = new String[] {"RS", "Nova Santa Rita", "4313375"}; + rows[4138] = new String[] {"RS", "Novo Barreiro", "4313490"}; + rows[4139] = new String[] {"RS", "Novo Cabrais", "4313391"}; + rows[4140] = new String[] {"RS", "Novo Hamburgo", "4313409"}; + rows[4141] = new String[] {"RS", "Novo Machado", "4313425"}; + rows[4142] = new String[] {"RS", "Novo Tiradentes", "4313441"}; + rows[4143] = new String[] {"RS", "Novo Xingu", "4313466"}; + rows[4144] = new String[] {"RS", "Os\u00f3rio", "4313508"}; + rows[4145] = new String[] {"RS", "Paim Filho", "4313607"}; + rows[4146] = new String[] {"RS", "Palmares do Sul", "4313656"}; + rows[4147] = new String[] {"RS", "Palmeira das Miss\u00f5es", "4313706"}; + rows[4148] = new String[] {"RS", "Palmitinho", "4313805"}; + rows[4149] = new String[] {"RS", "Panambi", "4313904"}; + rows[4150] = new String[] {"RS", "Pantano Grande", "4313953"}; + rows[4151] = new String[] {"RS", "Para\u00ed", "4314001"}; + rows[4152] = new String[] {"RS", "Para\u00edso do Sul", "4314027"}; + rows[4153] = new String[] {"RS", "Pareci Novo", "4314035"}; + rows[4154] = new String[] {"RS", "Parob\u00e9", "4314050"}; + rows[4155] = new String[] {"RS", "Passa Sete", "4314068"}; + rows[4156] = new String[] {"RS", "Passo do Sobrado", "4314076"}; + rows[4157] = new String[] {"RS", "Passo Fundo", "4314100"}; + rows[4158] = new String[] {"RS", "Paulo Bento", "4314134"}; + rows[4159] = new String[] {"RS", "Paverama", "4314159"}; + rows[4160] = new String[] {"RS", "Pedras Altas", "4314175"}; + rows[4161] = new String[] {"RS", "Pedro Os\u00f3rio", "4314209"}; + rows[4162] = new String[] {"RS", "Peju\u00e7ara", "4314308"}; + rows[4163] = new String[] {"RS", "Pelotas", "4314407"}; + rows[4164] = new String[] {"RS", "Picada Caf\u00e9", "4314423"}; + rows[4165] = new String[] {"RS", "Pinhal", "4314456"}; + rows[4166] = new String[] {"RS", "Pinhal da Serra", "4314464"}; + rows[4167] = new String[] {"RS", "Pinhal Grande", "4314472"}; + rows[4168] = new String[] {"RS", "Pinheirinho do Vale", "4314498"}; + rows[4169] = new String[] {"RS", "Pinheiro Machado", "4314506"}; + rows[4170] = new String[] {"RS", "Pinto Bandeira", "4314548"}; + rows[4171] = new String[] {"RS", "Pirap\u00f3", "4314555"}; + rows[4172] = new String[] {"RS", "Piratini", "4314605"}; + rows[4173] = new String[] {"RS", "Planalto", "4314704"}; + rows[4174] = new String[] {"RS", "Po\u00e7o das Antas", "4314753"}; + rows[4175] = new String[] {"RS", "Pont\u00e3o", "4314779"}; + rows[4176] = new String[] {"RS", "Ponte Preta", "4314787"}; + rows[4177] = new String[] {"RS", "Port\u00e3o", "4314803"}; + rows[4178] = new String[] {"RS", "Porto Alegre", "4314902"}; + rows[4179] = new String[] {"RS", "Porto Lucena", "4315008"}; + rows[4180] = new String[] {"RS", "Porto Mau\u00e1", "4315057"}; + rows[4181] = new String[] {"RS", "Porto Vera Cruz", "4315073"}; + rows[4182] = new String[] {"RS", "Porto Xavier", "4315107"}; + rows[4183] = new String[] {"RS", "Pouso Novo", "4315131"}; + rows[4184] = new String[] {"RS", "Presidente Lucena", "4315149"}; + rows[4185] = new String[] {"RS", "Progresso", "4315156"}; + rows[4186] = new String[] {"RS", "Prot\u00e1sio Alves", "4315172"}; + rows[4187] = new String[] {"RS", "Putinga", "4315206"}; + rows[4188] = new String[] {"RS", "Quara\u00ed", "4315305"}; + rows[4189] = new String[] {"RS", "Quatro Irm\u00e3os", "4315313"}; + rows[4190] = new String[] {"RS", "Quevedos", "4315321"}; + rows[4191] = new String[] {"RS", "Quinze de Novembro", "4315354"}; + rows[4192] = new String[] {"RS", "Redentora", "4315404"}; + rows[4193] = new String[] {"RS", "Relvado", "4315453"}; + rows[4194] = new String[] {"RS", "Restinga S\u00eaca", "4315503"}; + rows[4195] = new String[] {"RS", "Rio dos \u00cdndios", "4315552"}; + rows[4196] = new String[] {"RS", "Rio Grande", "4315602"}; + rows[4197] = new String[] {"RS", "Rio Pardo", "4315701"}; + rows[4198] = new String[] {"RS", "Riozinho", "4315750"}; + rows[4199] = new String[] {"RS", "Roca Sales", "4315800"}; + } + + private static void municipalitiesRows21(String[][] rows) { + rows[4200] = new String[] {"RS", "Rodeio Bonito", "4315909"}; + rows[4201] = new String[] {"RS", "Rolador", "4315958"}; + rows[4202] = new String[] {"RS", "Rolante", "4316006"}; + rows[4203] = new String[] {"RS", "Ronda Alta", "4316105"}; + rows[4204] = new String[] {"RS", "Rondinha", "4316204"}; + rows[4205] = new String[] {"RS", "Roque Gonzales", "4316303"}; + rows[4206] = new String[] {"RS", "Ros\u00e1rio do Sul", "4316402"}; + rows[4207] = new String[] {"RS", "Sagrada Fam\u00edlia", "4316428"}; + rows[4208] = new String[] {"RS", "Saldanha Marinho", "4316436"}; + rows[4209] = new String[] {"RS", "Salto do Jacu\u00ed", "4316451"}; + rows[4210] = new String[] {"RS", "Salvador das Miss\u00f5es", "4316477"}; + rows[4211] = new String[] {"RS", "Salvador do Sul", "4316501"}; + rows[4212] = new String[] {"RS", "Sananduva", "4316600"}; + rows[4213] = new String[] {"RS", "Sant'Ana do Livramento", "4317103"}; + rows[4214] = new String[] {"RS", "Santa B\u00e1rbara do Sul", "4316709"}; + rows[4215] = new String[] {"RS", "Santa Cec\u00edlia do Sul", "4316733"}; + rows[4216] = new String[] {"RS", "Santa Clara do Sul", "4316758"}; + rows[4217] = new String[] {"RS", "Santa Cruz do Sul", "4316808"}; + rows[4218] = new String[] {"RS", "Santa Margarida do Sul", "4316972"}; + rows[4219] = new String[] {"RS", "Santa Maria", "4316907"}; + rows[4220] = new String[] {"RS", "Santa Maria do Herval", "4316956"}; + rows[4221] = new String[] {"RS", "Santa Rosa", "4317202"}; + rows[4222] = new String[] {"RS", "Santa Tereza", "4317251"}; + rows[4223] = new String[] {"RS", "Santa Vit\u00f3ria do Palmar", "4317301"}; + rows[4224] = new String[] {"RS", "Santana da Boa Vista", "4317004"}; + rows[4225] = new String[] {"RS", "Santiago", "4317400"}; + rows[4226] = new String[] {"RS", "Santo \u00c2ngelo", "4317509"}; + rows[4227] = new String[] {"RS", "Santo Ant\u00f4nio da Patrulha", "4317608"}; + rows[4228] = new String[] {"RS", "Santo Ant\u00f4nio das Miss\u00f5es", "4317707"}; + rows[4229] = new String[] {"RS", "Santo Ant\u00f4nio do Palma", "4317558"}; + rows[4230] = new String[] {"RS", "Santo Ant\u00f4nio do Planalto", "4317756"}; + rows[4231] = new String[] {"RS", "Santo Augusto", "4317806"}; + rows[4232] = new String[] {"RS", "Santo Cristo", "4317905"}; + rows[4233] = new String[] {"RS", "Santo Expedito do Sul", "4317954"}; + rows[4234] = new String[] {"RS", "S\u00e3o Borja", "4318002"}; + rows[4235] = new String[] {"RS", "S\u00e3o Domingos do Sul", "4318051"}; + rows[4236] = new String[] {"RS", "S\u00e3o Francisco de Assis", "4318101"}; + rows[4237] = new String[] {"RS", "S\u00e3o Francisco de Paula", "4318200"}; + rows[4238] = new String[] {"RS", "S\u00e3o Gabriel", "4318309"}; + rows[4239] = new String[] {"RS", "S\u00e3o Jer\u00f4nimo", "4318408"}; + rows[4240] = new String[] {"RS", "S\u00e3o Jo\u00e3o da Urtiga", "4318424"}; + rows[4241] = new String[] {"RS", "S\u00e3o Jo\u00e3o do Pol\u00easine", "4318432"}; + rows[4242] = new String[] {"RS", "S\u00e3o Jorge", "4318440"}; + rows[4243] = new String[] {"RS", "S\u00e3o Jos\u00e9 das Miss\u00f5es", "4318457"}; + rows[4244] = new String[] {"RS", "S\u00e3o Jos\u00e9 do Herval", "4318465"}; + rows[4245] = new String[] {"RS", "S\u00e3o Jos\u00e9 do Hort\u00eancio", "4318481"}; + rows[4246] = new String[] {"RS", "S\u00e3o Jos\u00e9 do Inhacor\u00e1", "4318499"}; + rows[4247] = new String[] {"RS", "S\u00e3o Jos\u00e9 do Norte", "4318507"}; + rows[4248] = new String[] {"RS", "S\u00e3o Jos\u00e9 do Ouro", "4318606"}; + rows[4249] = new String[] {"RS", "S\u00e3o Jos\u00e9 do Sul", "4318614"}; + rows[4250] = new String[] {"RS", "S\u00e3o Jos\u00e9 dos Ausentes", "4318622"}; + rows[4251] = new String[] {"RS", "S\u00e3o Leopoldo", "4318705"}; + rows[4252] = new String[] {"RS", "S\u00e3o Louren\u00e7o do Sul", "4318804"}; + rows[4253] = new String[] {"RS", "S\u00e3o Luiz Gonzaga", "4318903"}; + rows[4254] = new String[] {"RS", "S\u00e3o Marcos", "4319000"}; + rows[4255] = new String[] {"RS", "S\u00e3o Martinho", "4319109"}; + rows[4256] = new String[] {"RS", "S\u00e3o Martinho da Serra", "4319125"}; + rows[4257] = new String[] {"RS", "S\u00e3o Miguel das Miss\u00f5es", "4319158"}; + rows[4258] = new String[] {"RS", "S\u00e3o Nicolau", "4319208"}; + rows[4259] = new String[] {"RS", "S\u00e3o Paulo das Miss\u00f5es", "4319307"}; + rows[4260] = new String[] {"RS", "S\u00e3o Pedro da Serra", "4319356"}; + rows[4261] = new String[] {"RS", "S\u00e3o Pedro das Miss\u00f5es", "4319364"}; + rows[4262] = new String[] {"RS", "S\u00e3o Pedro do Buti\u00e1", "4319372"}; + rows[4263] = new String[] {"RS", "S\u00e3o Pedro do Sul", "4319406"}; + rows[4264] = new String[] {"RS", "S\u00e3o Sebasti\u00e3o do Ca\u00ed", "4319505"}; + rows[4265] = new String[] {"RS", "S\u00e3o Sep\u00e9", "4319604"}; + rows[4266] = new String[] {"RS", "S\u00e3o Valentim", "4319703"}; + rows[4267] = new String[] {"RS", "S\u00e3o Valentim do Sul", "4319711"}; + rows[4268] = new String[] {"RS", "S\u00e3o Val\u00e9rio do Sul", "4319737"}; + rows[4269] = new String[] {"RS", "S\u00e3o Vendelino", "4319752"}; + rows[4270] = new String[] {"RS", "S\u00e3o Vicente do Sul", "4319802"}; + rows[4271] = new String[] {"RS", "Sapiranga", "4319901"}; + rows[4272] = new String[] {"RS", "Sapucaia do Sul", "4320008"}; + rows[4273] = new String[] {"RS", "Sarandi", "4320107"}; + rows[4274] = new String[] {"RS", "Seberi", "4320206"}; + rows[4275] = new String[] {"RS", "Sede Nova", "4320230"}; + rows[4276] = new String[] {"RS", "Segredo", "4320263"}; + rows[4277] = new String[] {"RS", "Selbach", "4320305"}; + rows[4278] = new String[] {"RS", "Senador Salgado Filho", "4320321"}; + rows[4279] = new String[] {"RS", "Sentinela do Sul", "4320354"}; + rows[4280] = new String[] {"RS", "Serafina Corr\u00eaa", "4320404"}; + rows[4281] = new String[] {"RS", "S\u00e9rio", "4320453"}; + rows[4282] = new String[] {"RS", "Sert\u00e3o", "4320503"}; + rows[4283] = new String[] {"RS", "Sert\u00e3o Santana", "4320552"}; + rows[4284] = new String[] {"RS", "Sete de Setembro", "4320578"}; + rows[4285] = new String[] {"RS", "Severiano de Almeida", "4320602"}; + rows[4286] = new String[] {"RS", "Silveira Martins", "4320651"}; + rows[4287] = new String[] {"RS", "Sinimbu", "4320677"}; + rows[4288] = new String[] {"RS", "Sobradinho", "4320701"}; + rows[4289] = new String[] {"RS", "Soledade", "4320800"}; + rows[4290] = new String[] {"RS", "Taba\u00ed", "4320859"}; + rows[4291] = new String[] {"RS", "Tapejara", "4320909"}; + rows[4292] = new String[] {"RS", "Tapera", "4321006"}; + rows[4293] = new String[] {"RS", "Tapes", "4321105"}; + rows[4294] = new String[] {"RS", "Taquara", "4321204"}; + rows[4295] = new String[] {"RS", "Taquari", "4321303"}; + rows[4296] = new String[] {"RS", "Taquaru\u00e7u do Sul", "4321329"}; + rows[4297] = new String[] {"RS", "Tavares", "4321352"}; + rows[4298] = new String[] {"RS", "Tenente Portela", "4321402"}; + rows[4299] = new String[] {"RS", "Terra de Areia", "4321436"}; + rows[4300] = new String[] {"RS", "Teut\u00f4nia", "4321451"}; + rows[4301] = new String[] {"RS", "Tio Hugo", "4321469"}; + rows[4302] = new String[] {"RS", "Tiradentes do Sul", "4321477"}; + rows[4303] = new String[] {"RS", "Toropi", "4321493"}; + rows[4304] = new String[] {"RS", "Torres", "4321501"}; + rows[4305] = new String[] {"RS", "Tramanda\u00ed", "4321600"}; + rows[4306] = new String[] {"RS", "Travesseiro", "4321626"}; + rows[4307] = new String[] {"RS", "Tr\u00eas Arroios", "4321634"}; + rows[4308] = new String[] {"RS", "Tr\u00eas Cachoeiras", "4321667"}; + rows[4309] = new String[] {"RS", "Tr\u00eas Coroas", "4321709"}; + rows[4310] = new String[] {"RS", "Tr\u00eas de Maio", "4321808"}; + rows[4311] = new String[] {"RS", "Tr\u00eas Forquilhas", "4321832"}; + rows[4312] = new String[] {"RS", "Tr\u00eas Palmeiras", "4321857"}; + rows[4313] = new String[] {"RS", "Tr\u00eas Passos", "4321907"}; + rows[4314] = new String[] {"RS", "Trindade do Sul", "4321956"}; + rows[4315] = new String[] {"RS", "Triunfo", "4322004"}; + rows[4316] = new String[] {"RS", "Tucunduva", "4322103"}; + rows[4317] = new String[] {"RS", "Tunas", "4322152"}; + rows[4318] = new String[] {"RS", "Tupanci do Sul", "4322186"}; + rows[4319] = new String[] {"RS", "Tupanciret\u00e3", "4322202"}; + rows[4320] = new String[] {"RS", "Tupandi", "4322251"}; + rows[4321] = new String[] {"RS", "Tuparendi", "4322301"}; + rows[4322] = new String[] {"RS", "Turu\u00e7u", "4322327"}; + rows[4323] = new String[] {"RS", "Ubiretama", "4322343"}; + rows[4324] = new String[] {"RS", "Uni\u00e3o da Serra", "4322350"}; + rows[4325] = new String[] {"RS", "Unistalda", "4322376"}; + rows[4326] = new String[] {"RS", "Uruguaiana", "4322400"}; + rows[4327] = new String[] {"RS", "Vacaria", "4322509"}; + rows[4328] = new String[] {"RS", "Vale do Sol", "4322533"}; + rows[4329] = new String[] {"RS", "Vale Real", "4322541"}; + rows[4330] = new String[] {"RS", "Vale Verde", "4322525"}; + rows[4331] = new String[] {"RS", "Vanini", "4322558"}; + rows[4332] = new String[] {"RS", "Ven\u00e2ncio Aires", "4322608"}; + rows[4333] = new String[] {"RS", "Vera Cruz", "4322707"}; + rows[4334] = new String[] {"RS", "Veran\u00f3polis", "4322806"}; + rows[4335] = new String[] {"RS", "Vespasiano Corr\u00eaa", "4322855"}; + rows[4336] = new String[] {"RS", "Viadutos", "4322905"}; + rows[4337] = new String[] {"RS", "Viam\u00e3o", "4323002"}; + rows[4338] = new String[] {"RS", "Vicente Dutra", "4323101"}; + rows[4339] = new String[] {"RS", "Victor Graeff", "4323200"}; + rows[4340] = new String[] {"RS", "Vila Flores", "4323309"}; + rows[4341] = new String[] {"RS", "Vila L\u00e2ngaro", "4323358"}; + rows[4342] = new String[] {"RS", "Vila Maria", "4323408"}; + rows[4343] = new String[] {"RS", "Vila Nova do Sul", "4323457"}; + rows[4344] = new String[] {"RS", "Vista Alegre", "4323507"}; + rows[4345] = new String[] {"RS", "Vista Alegre do Prata", "4323606"}; + rows[4346] = new String[] {"RS", "Vista Ga\u00facha", "4323705"}; + rows[4347] = new String[] {"RS", "Vit\u00f3ria das Miss\u00f5es", "4323754"}; + rows[4348] = new String[] {"RS", "Westf\u00e1lia", "4323770"}; + rows[4349] = new String[] {"RS", "Xangri-l\u00e1", "4323804"}; + rows[4350] = new String[] {"RO", "Alta Floresta D'Oeste", "1100015"}; + rows[4351] = new String[] {"RO", "Alto Alegre dos Parecis", "1100379"}; + rows[4352] = new String[] {"RO", "Alto Para\u00edso", "1100403"}; + rows[4353] = new String[] {"RO", "Alvorada D'Oeste", "1100346"}; + rows[4354] = new String[] {"RO", "Ariquemes", "1100023"}; + rows[4355] = new String[] {"RO", "Buritis", "1100452"}; + rows[4356] = new String[] {"RO", "Cabixi", "1100031"}; + rows[4357] = new String[] {"RO", "Cacaul\u00e2ndia", "1100601"}; + rows[4358] = new String[] {"RO", "Cacoal", "1100049"}; + rows[4359] = new String[] {"RO", "Campo Novo de Rond\u00f4nia", "1100700"}; + rows[4360] = new String[] {"RO", "Candeias do Jamari", "1100809"}; + rows[4361] = new String[] {"RO", "Castanheiras", "1100908"}; + rows[4362] = new String[] {"RO", "Cerejeiras", "1100056"}; + rows[4363] = new String[] {"RO", "Chupinguaia", "1100924"}; + rows[4364] = new String[] {"RO", "Colorado do Oeste", "1100064"}; + rows[4365] = new String[] {"RO", "Corumbiara", "1100072"}; + rows[4366] = new String[] {"RO", "Costa Marques", "1100080"}; + rows[4367] = new String[] {"RO", "Cujubim", "1100940"}; + rows[4368] = new String[] {"RO", "Espig\u00e3o D'Oeste", "1100098"}; + rows[4369] = new String[] {"RO", "Governador Jorge Teixeira", "1101005"}; + rows[4370] = new String[] {"RO", "Guajar\u00e1-Mirim", "1100106"}; + rows[4371] = new String[] {"RO", "Itapu\u00e3 do Oeste", "1101104"}; + rows[4372] = new String[] {"RO", "Jaru", "1100114"}; + rows[4373] = new String[] {"RO", "Ji-Paran\u00e1", "1100122"}; + rows[4374] = new String[] {"RO", "Machadinho D'Oeste", "1100130"}; + rows[4375] = new String[] {"RO", "Ministro Andreazza", "1101203"}; + rows[4376] = new String[] {"RO", "Mirante da Serra", "1101302"}; + rows[4377] = new String[] {"RO", "Monte Negro", "1101401"}; + rows[4378] = new String[] {"RO", "Nova Brasil\u00e2ndia D'Oeste", "1100148"}; + rows[4379] = new String[] {"RO", "Nova Mamor\u00e9", "1100338"}; + rows[4380] = new String[] {"RO", "Nova Uni\u00e3o", "1101435"}; + rows[4381] = new String[] {"RO", "Novo Horizonte do Oeste", "1100502"}; + rows[4382] = new String[] {"RO", "Ouro Preto do Oeste", "1100155"}; + rows[4383] = new String[] {"RO", "Parecis", "1101450"}; + rows[4384] = new String[] {"RO", "Pimenta Bueno", "1100189"}; + rows[4385] = new String[] {"RO", "Pimenteiras do Oeste", "1101468"}; + rows[4386] = new String[] {"RO", "Porto Velho", "1100205"}; + rows[4387] = new String[] {"RO", "Presidente M\u00e9dici", "1100254"}; + rows[4388] = new String[] {"RO", "Primavera de Rond\u00f4nia", "1101476"}; + rows[4389] = new String[] {"RO", "Rio Crespo", "1100262"}; + rows[4390] = new String[] {"RO", "Rolim de Moura", "1100288"}; + rows[4391] = new String[] {"RO", "Santa Luzia D'Oeste", "1100296"}; + rows[4392] = new String[] {"RO", "S\u00e3o Felipe D'Oeste", "1101484"}; + rows[4393] = new String[] {"RO", "S\u00e3o Francisco do Guapor\u00e9", "1101492"}; + rows[4394] = new String[] {"RO", "S\u00e3o Miguel do Guapor\u00e9", "1100320"}; + rows[4395] = new String[] {"RO", "Seringueiras", "1101500"}; + rows[4396] = new String[] {"RO", "Teixeir\u00f3polis", "1101559"}; + rows[4397] = new String[] {"RO", "Theobroma", "1101609"}; + rows[4398] = new String[] {"RO", "Urup\u00e1", "1101708"}; + rows[4399] = new String[] {"RO", "Vale do Anari", "1101757"}; + } + + private static void municipalitiesRows22(String[][] rows) { + rows[4400] = new String[] {"RO", "Vale do Para\u00edso", "1101807"}; + rows[4401] = new String[] {"RO", "Vilhena", "1100304"}; + rows[4402] = new String[] {"RR", "Alto Alegre", "1400050"}; + rows[4403] = new String[] {"RR", "Amajari", "1400027"}; + rows[4404] = new String[] {"RR", "Boa Vista", "1400100"}; + rows[4405] = new String[] {"RR", "Bonfim", "1400159"}; + rows[4406] = new String[] {"RR", "Cant\u00e1", "1400175"}; + rows[4407] = new String[] {"RR", "Caracara\u00ed", "1400209"}; + rows[4408] = new String[] {"RR", "Caroebe", "1400233"}; + rows[4409] = new String[] {"RR", "Iracema", "1400282"}; + rows[4410] = new String[] {"RR", "Mucaja\u00ed", "1400308"}; + rows[4411] = new String[] {"RR", "Normandia", "1400407"}; + rows[4412] = new String[] {"RR", "Pacaraima", "1400456"}; + rows[4413] = new String[] {"RR", "Rorain\u00f3polis", "1400472"}; + rows[4414] = new String[] {"RR", "S\u00e3o Jo\u00e3o da Baliza", "1400506"}; + rows[4415] = new String[] {"RR", "S\u00e3o Luiz do Anau\u00e1", "1400605"}; + rows[4416] = new String[] {"RR", "Uiramut\u00e3", "1400704"}; + rows[4417] = new String[] {"SC", "Abdon Batista", "4200051"}; + rows[4418] = new String[] {"SC", "Abelardo Luz", "4200101"}; + rows[4419] = new String[] {"SC", "Agrol\u00e2ndia", "4200200"}; + rows[4420] = new String[] {"SC", "Agron\u00f4mica", "4200309"}; + rows[4421] = new String[] {"SC", "\u00c1gua Doce", "4200408"}; + rows[4422] = new String[] {"SC", "\u00c1guas de Chapec\u00f3", "4200507"}; + rows[4423] = new String[] {"SC", "\u00c1guas Frias", "4200556"}; + rows[4424] = new String[] {"SC", "\u00c1guas Mornas", "4200606"}; + rows[4425] = new String[] {"SC", "Alfredo Wagner", "4200705"}; + rows[4426] = new String[] {"SC", "Alto Bela Vista", "4200754"}; + rows[4427] = new String[] {"SC", "Anchieta", "4200804"}; + rows[4428] = new String[] {"SC", "Angelina", "4200903"}; + rows[4429] = new String[] {"SC", "Anita Garibaldi", "4201000"}; + rows[4430] = new String[] {"SC", "Anit\u00e1polis", "4201109"}; + rows[4431] = new String[] {"SC", "Ant\u00f4nio Carlos", "4201208"}; + rows[4432] = new String[] {"SC", "Api\u00fana", "4201257"}; + rows[4433] = new String[] {"SC", "Arabut\u00e3", "4201273"}; + rows[4434] = new String[] {"SC", "Araquari", "4201307"}; + rows[4435] = new String[] {"SC", "Ararangu\u00e1", "4201406"}; + rows[4436] = new String[] {"SC", "Armaz\u00e9m", "4201505"}; + rows[4437] = new String[] {"SC", "Arroio Trinta", "4201604"}; + rows[4438] = new String[] {"SC", "Arvoredo", "4201653"}; + rows[4439] = new String[] {"SC", "Ascurra", "4201703"}; + rows[4440] = new String[] {"SC", "Atalanta", "4201802"}; + rows[4441] = new String[] {"SC", "Aurora", "4201901"}; + rows[4442] = new String[] {"SC", "Balne\u00e1rio Arroio do Silva", "4201950"}; + rows[4443] = new String[] {"SC", "Balne\u00e1rio Barra do Sul", "4202057"}; + rows[4444] = new String[] {"SC", "Balne\u00e1rio Cambori\u00fa", "4202008"}; + rows[4445] = new String[] {"SC", "Balne\u00e1rio Gaivota", "4202073"}; + rows[4446] = new String[] {"SC", "Balne\u00e1rio Pi\u00e7arras", "4212809"}; + rows[4447] = new String[] {"SC", "Balne\u00e1rio Rinc\u00e3o", "4220000"}; + rows[4448] = new String[] {"SC", "Bandeirante", "4202081"}; + rows[4449] = new String[] {"SC", "Barra Bonita", "4202099"}; + rows[4450] = new String[] {"SC", "Barra Velha", "4202107"}; + rows[4451] = new String[] {"SC", "Bela Vista do Toldo", "4202131"}; + rows[4452] = new String[] {"SC", "Belmonte", "4202156"}; + rows[4453] = new String[] {"SC", "Benedito Novo", "4202206"}; + rows[4454] = new String[] {"SC", "Bigua\u00e7u", "4202305"}; + rows[4455] = new String[] {"SC", "Blumenau", "4202404"}; + rows[4456] = new String[] {"SC", "Bocaina do Sul", "4202438"}; + rows[4457] = new String[] {"SC", "Bom Jardim da Serra", "4202503"}; + rows[4458] = new String[] {"SC", "Bom Jesus", "4202537"}; + rows[4459] = new String[] {"SC", "Bom Jesus do Oeste", "4202578"}; + rows[4460] = new String[] {"SC", "Bom Retiro", "4202602"}; + rows[4461] = new String[] {"SC", "Bombinhas", "4202453"}; + rows[4462] = new String[] {"SC", "Botuver\u00e1", "4202701"}; + rows[4463] = new String[] {"SC", "Bra\u00e7o do Norte", "4202800"}; + rows[4464] = new String[] {"SC", "Bra\u00e7o do Trombudo", "4202859"}; + rows[4465] = new String[] {"SC", "Brun\u00f3polis", "4202875"}; + rows[4466] = new String[] {"SC", "Brusque", "4202909"}; + rows[4467] = new String[] {"SC", "Ca\u00e7ador", "4203006"}; + rows[4468] = new String[] {"SC", "Caibi", "4203105"}; + rows[4469] = new String[] {"SC", "Calmon", "4203154"}; + rows[4470] = new String[] {"SC", "Cambori\u00fa", "4203204"}; + rows[4471] = new String[] {"SC", "Campo Alegre", "4203303"}; + rows[4472] = new String[] {"SC", "Campo Belo do Sul", "4203402"}; + rows[4473] = new String[] {"SC", "Campo Er\u00ea", "4203501"}; + rows[4474] = new String[] {"SC", "Campos Novos", "4203600"}; + rows[4475] = new String[] {"SC", "Canelinha", "4203709"}; + rows[4476] = new String[] {"SC", "Canoinhas", "4203808"}; + rows[4477] = new String[] {"SC", "Cap\u00e3o Alto", "4203253"}; + rows[4478] = new String[] {"SC", "Capinzal", "4203907"}; + rows[4479] = new String[] {"SC", "Capivari de Baixo", "4203956"}; + rows[4480] = new String[] {"SC", "Catanduvas", "4204004"}; + rows[4481] = new String[] {"SC", "Caxambu do Sul", "4204103"}; + rows[4482] = new String[] {"SC", "Celso Ramos", "4204152"}; + rows[4483] = new String[] {"SC", "Cerro Negro", "4204178"}; + rows[4484] = new String[] {"SC", "Chapad\u00e3o do Lageado", "4204194"}; + rows[4485] = new String[] {"SC", "Chapec\u00f3", "4204202"}; + rows[4486] = new String[] {"SC", "Cocal do Sul", "4204251"}; + rows[4487] = new String[] {"SC", "Conc\u00f3rdia", "4204301"}; + rows[4488] = new String[] {"SC", "Cordilheira Alta", "4204350"}; + rows[4489] = new String[] {"SC", "Coronel Freitas", "4204400"}; + rows[4490] = new String[] {"SC", "Coronel Martins", "4204459"}; + rows[4491] = new String[] {"SC", "Correia Pinto", "4204558"}; + rows[4492] = new String[] {"SC", "Corup\u00e1", "4204509"}; + rows[4493] = new String[] {"SC", "Crici\u00fama", "4204608"}; + rows[4494] = new String[] {"SC", "Cunha Por\u00e3", "4204707"}; + rows[4495] = new String[] {"SC", "Cunhata\u00ed", "4204756"}; + rows[4496] = new String[] {"SC", "Curitibanos", "4204806"}; + rows[4497] = new String[] {"SC", "Descanso", "4204905"}; + rows[4498] = new String[] {"SC", "Dion\u00edsio Cerqueira", "4205001"}; + rows[4499] = new String[] {"SC", "Dona Emma", "4205100"}; + rows[4500] = new String[] {"SC", "Doutor Pedrinho", "4205159"}; + rows[4501] = new String[] {"SC", "Entre Rios", "4205175"}; + rows[4502] = new String[] {"SC", "Ermo", "4205191"}; + rows[4503] = new String[] {"SC", "Erval Velho", "4205209"}; + rows[4504] = new String[] {"SC", "Faxinal dos Guedes", "4205308"}; + rows[4505] = new String[] {"SC", "Flor do Sert\u00e3o", "4205357"}; + rows[4506] = new String[] {"SC", "Florian\u00f3polis", "4205407"}; + rows[4507] = new String[] {"SC", "Formosa do Sul", "4205431"}; + rows[4508] = new String[] {"SC", "Forquilhinha", "4205456"}; + rows[4509] = new String[] {"SC", "Fraiburgo", "4205506"}; + rows[4510] = new String[] {"SC", "Frei Rog\u00e9rio", "4205555"}; + rows[4511] = new String[] {"SC", "Galv\u00e3o", "4205605"}; + rows[4512] = new String[] {"SC", "Garopaba", "4205704"}; + rows[4513] = new String[] {"SC", "Garuva", "4205803"}; + rows[4514] = new String[] {"SC", "Gaspar", "4205902"}; + rows[4515] = new String[] {"SC", "Governador Celso Ramos", "4206009"}; + rows[4516] = new String[] {"SC", "Gr\u00e3o-Par\u00e1", "4206108"}; + rows[4517] = new String[] {"SC", "Gravatal", "4206207"}; + rows[4518] = new String[] {"SC", "Guabiruba", "4206306"}; + rows[4519] = new String[] {"SC", "Guaraciaba", "4206405"}; + rows[4520] = new String[] {"SC", "Guaramirim", "4206504"}; + rows[4521] = new String[] {"SC", "Guaruj\u00e1 do Sul", "4206603"}; + rows[4522] = new String[] {"SC", "Guatamb\u00fa", "4206652"}; + rows[4523] = new String[] {"SC", "Herval d'Oeste", "4206702"}; + rows[4524] = new String[] {"SC", "Ibiam", "4206751"}; + rows[4525] = new String[] {"SC", "Ibicar\u00e9", "4206801"}; + rows[4526] = new String[] {"SC", "Ibirama", "4206900"}; + rows[4527] = new String[] {"SC", "I\u00e7ara", "4207007"}; + rows[4528] = new String[] {"SC", "Ilhota", "4207106"}; + rows[4529] = new String[] {"SC", "Imaru\u00ed", "4207205"}; + rows[4530] = new String[] {"SC", "Imbituba", "4207304"}; + rows[4531] = new String[] {"SC", "Imbuia", "4207403"}; + rows[4532] = new String[] {"SC", "Indaial", "4207502"}; + rows[4533] = new String[] {"SC", "Iomer\u00ea", "4207577"}; + rows[4534] = new String[] {"SC", "Ipira", "4207601"}; + rows[4535] = new String[] {"SC", "Ipor\u00e3 do Oeste", "4207650"}; + rows[4536] = new String[] {"SC", "Ipua\u00e7u", "4207684"}; + rows[4537] = new String[] {"SC", "Ipumirim", "4207700"}; + rows[4538] = new String[] {"SC", "Iraceminha", "4207759"}; + rows[4539] = new String[] {"SC", "Irani", "4207809"}; + rows[4540] = new String[] {"SC", "Irati", "4207858"}; + rows[4541] = new String[] {"SC", "Irine\u00f3polis", "4207908"}; + rows[4542] = new String[] {"SC", "It\u00e1", "4208005"}; + rows[4543] = new String[] {"SC", "Itai\u00f3polis", "4208104"}; + rows[4544] = new String[] {"SC", "Itaja\u00ed", "4208203"}; + rows[4545] = new String[] {"SC", "Itapema", "4208302"}; + rows[4546] = new String[] {"SC", "Itapiranga", "4208401"}; + rows[4547] = new String[] {"SC", "Itapo\u00e1", "4208450"}; + rows[4548] = new String[] {"SC", "Ituporanga", "4208500"}; + rows[4549] = new String[] {"SC", "Jabor\u00e1", "4208609"}; + rows[4550] = new String[] {"SC", "Jacinto Machado", "4208708"}; + rows[4551] = new String[] {"SC", "Jaguaruna", "4208807"}; + rows[4552] = new String[] {"SC", "Jaragu\u00e1 do Sul", "4208906"}; + rows[4553] = new String[] {"SC", "Jardin\u00f3polis", "4208955"}; + rows[4554] = new String[] {"SC", "Joa\u00e7aba", "4209003"}; + rows[4555] = new String[] {"SC", "Joinville", "4209102"}; + rows[4556] = new String[] {"SC", "Jos\u00e9 Boiteux", "4209151"}; + rows[4557] = new String[] {"SC", "Jupi\u00e1", "4209177"}; + rows[4558] = new String[] {"SC", "Lacerd\u00f3polis", "4209201"}; + rows[4559] = new String[] {"SC", "Lages", "4209300"}; + rows[4560] = new String[] {"SC", "Laguna", "4209409"}; + rows[4561] = new String[] {"SC", "Lajeado Grande", "4209458"}; + rows[4562] = new String[] {"SC", "Laurentino", "4209508"}; + rows[4563] = new String[] {"SC", "Lauro M\u00fcller", "4209607"}; + rows[4564] = new String[] {"SC", "Lebon R\u00e9gis", "4209706"}; + rows[4565] = new String[] {"SC", "Leoberto Leal", "4209805"}; + rows[4566] = new String[] {"SC", "Lind\u00f3ia do Sul", "4209854"}; + rows[4567] = new String[] {"SC", "Lontras", "4209904"}; + rows[4568] = new String[] {"SC", "Luiz Alves", "4210001"}; + rows[4569] = new String[] {"SC", "Luzerna", "4210035"}; + rows[4570] = new String[] {"SC", "Macieira", "4210050"}; + rows[4571] = new String[] {"SC", "Mafra", "4210100"}; + rows[4572] = new String[] {"SC", "Major Gercino", "4210209"}; + rows[4573] = new String[] {"SC", "Major Vieira", "4210308"}; + rows[4574] = new String[] {"SC", "Maracaj\u00e1", "4210407"}; + rows[4575] = new String[] {"SC", "Maravilha", "4210506"}; + rows[4576] = new String[] {"SC", "Marema", "4210555"}; + rows[4577] = new String[] {"SC", "Massaranduba", "4210605"}; + rows[4578] = new String[] {"SC", "Matos Costa", "4210704"}; + rows[4579] = new String[] {"SC", "Meleiro", "4210803"}; + rows[4580] = new String[] {"SC", "Mirim Doce", "4210852"}; + rows[4581] = new String[] {"SC", "Modelo", "4210902"}; + rows[4582] = new String[] {"SC", "Monda\u00ed", "4211009"}; + rows[4583] = new String[] {"SC", "Monte Carlo", "4211058"}; + rows[4584] = new String[] {"SC", "Monte Castelo", "4211108"}; + rows[4585] = new String[] {"SC", "Morro da Fuma\u00e7a", "4211207"}; + rows[4586] = new String[] {"SC", "Morro Grande", "4211256"}; + rows[4587] = new String[] {"SC", "Navegantes", "4211306"}; + rows[4588] = new String[] {"SC", "Nova Erechim", "4211405"}; + rows[4589] = new String[] {"SC", "Nova Itaberaba", "4211454"}; + rows[4590] = new String[] {"SC", "Nova Trento", "4211504"}; + rows[4591] = new String[] {"SC", "Nova Veneza", "4211603"}; + rows[4592] = new String[] {"SC", "Novo Horizonte", "4211652"}; + rows[4593] = new String[] {"SC", "Orleans", "4211702"}; + rows[4594] = new String[] {"SC", "Otac\u00edlio Costa", "4211751"}; + rows[4595] = new String[] {"SC", "Ouro", "4211801"}; + rows[4596] = new String[] {"SC", "Ouro Verde", "4211850"}; + rows[4597] = new String[] {"SC", "Paial", "4211876"}; + rows[4598] = new String[] {"SC", "Painel", "4211892"}; + rows[4599] = new String[] {"SC", "Palho\u00e7a", "4211900"}; + } + + private static void municipalitiesRows23(String[][] rows) { + rows[4600] = new String[] {"SC", "Palma Sola", "4212007"}; + rows[4601] = new String[] {"SC", "Palmeira", "4212056"}; + rows[4602] = new String[] {"SC", "Palmitos", "4212106"}; + rows[4603] = new String[] {"SC", "Papanduva", "4212205"}; + rows[4604] = new String[] {"SC", "Para\u00edso", "4212239"}; + rows[4605] = new String[] {"SC", "Passo de Torres", "4212254"}; + rows[4606] = new String[] {"SC", "Passos Maia", "4212270"}; + rows[4607] = new String[] {"SC", "Paulo Lopes", "4212304"}; + rows[4608] = new String[] {"SC", "Pedras Grandes", "4212403"}; + rows[4609] = new String[] {"SC", "Penha", "4212502"}; + rows[4610] = new String[] {"SC", "Peritiba", "4212601"}; + rows[4611] = new String[] {"SC", "Pescaria Brava", "4212650"}; + rows[4612] = new String[] {"SC", "Petrol\u00e2ndia", "4212700"}; + rows[4613] = new String[] {"SC", "Pinhalzinho", "4212908"}; + rows[4614] = new String[] {"SC", "Pinheiro Preto", "4213005"}; + rows[4615] = new String[] {"SC", "Piratuba", "4213104"}; + rows[4616] = new String[] {"SC", "Planalto Alegre", "4213153"}; + rows[4617] = new String[] {"SC", "Pomerode", "4213203"}; + rows[4618] = new String[] {"SC", "Ponte Alta", "4213302"}; + rows[4619] = new String[] {"SC", "Ponte Alta do Norte", "4213351"}; + rows[4620] = new String[] {"SC", "Ponte Serrada", "4213401"}; + rows[4621] = new String[] {"SC", "Porto Belo", "4213500"}; + rows[4622] = new String[] {"SC", "Porto Uni\u00e3o", "4213609"}; + rows[4623] = new String[] {"SC", "Pouso Redondo", "4213708"}; + rows[4624] = new String[] {"SC", "Praia Grande", "4213807"}; + rows[4625] = new String[] {"SC", "Presidente Castello Branco", "4213906"}; + rows[4626] = new String[] {"SC", "Presidente Get\u00falio", "4214003"}; + rows[4627] = new String[] {"SC", "Presidente Nereu", "4214102"}; + rows[4628] = new String[] {"SC", "Princesa", "4214151"}; + rows[4629] = new String[] {"SC", "Quilombo", "4214201"}; + rows[4630] = new String[] {"SC", "Rancho Queimado", "4214300"}; + rows[4631] = new String[] {"SC", "Rio das Antas", "4214409"}; + rows[4632] = new String[] {"SC", "Rio do Campo", "4214508"}; + rows[4633] = new String[] {"SC", "Rio do Oeste", "4214607"}; + rows[4634] = new String[] {"SC", "Rio do Sul", "4214805"}; + rows[4635] = new String[] {"SC", "Rio dos Cedros", "4214706"}; + rows[4636] = new String[] {"SC", "Rio Fortuna", "4214904"}; + rows[4637] = new String[] {"SC", "Rio Negrinho", "4215000"}; + rows[4638] = new String[] {"SC", "Rio Rufino", "4215059"}; + rows[4639] = new String[] {"SC", "Riqueza", "4215075"}; + rows[4640] = new String[] {"SC", "Rodeio", "4215109"}; + rows[4641] = new String[] {"SC", "Romel\u00e2ndia", "4215208"}; + rows[4642] = new String[] {"SC", "Salete", "4215307"}; + rows[4643] = new String[] {"SC", "Saltinho", "4215356"}; + rows[4644] = new String[] {"SC", "Salto Veloso", "4215406"}; + rows[4645] = new String[] {"SC", "Sang\u00e3o", "4215455"}; + rows[4646] = new String[] {"SC", "Santa Cec\u00edlia", "4215505"}; + rows[4647] = new String[] {"SC", "Santa Helena", "4215554"}; + rows[4648] = new String[] {"SC", "Santa Rosa de Lima", "4215604"}; + rows[4649] = new String[] {"SC", "Santa Rosa do Sul", "4215653"}; + rows[4650] = new String[] {"SC", "Santa Terezinha", "4215679"}; + rows[4651] = new String[] {"SC", "Santa Terezinha do Progresso", "4215687"}; + rows[4652] = new String[] {"SC", "Santiago do Sul", "4215695"}; + rows[4653] = new String[] {"SC", "Santo Amaro da Imperatriz", "4215703"}; + rows[4654] = new String[] {"SC", "S\u00e3o Bento do Sul", "4215802"}; + rows[4655] = new String[] {"SC", "S\u00e3o Bernardino", "4215752"}; + rows[4656] = new String[] {"SC", "S\u00e3o Bonif\u00e1cio", "4215901"}; + rows[4657] = new String[] {"SC", "S\u00e3o Carlos", "4216008"}; + rows[4658] = new String[] {"SC", "S\u00e3o Crist\u00f3v\u00e3o do Sul", "4216057"}; + rows[4659] = new String[] {"SC", "S\u00e3o Domingos", "4216107"}; + rows[4660] = new String[] {"SC", "S\u00e3o Francisco do Sul", "4216206"}; + rows[4661] = new String[] {"SC", "S\u00e3o Jo\u00e3o Batista", "4216305"}; + rows[4662] = new String[] {"SC", "S\u00e3o Jo\u00e3o do Itaperi\u00fa", "4216354"}; + rows[4663] = new String[] {"SC", "S\u00e3o Jo\u00e3o do Oeste", "4216255"}; + rows[4664] = new String[] {"SC", "S\u00e3o Jo\u00e3o do Sul", "4216404"}; + rows[4665] = new String[] {"SC", "S\u00e3o Joaquim", "4216503"}; + rows[4666] = new String[] {"SC", "S\u00e3o Jos\u00e9", "4216602"}; + rows[4667] = new String[] {"SC", "S\u00e3o Jos\u00e9 do Cedro", "4216701"}; + rows[4668] = new String[] {"SC", "S\u00e3o Jos\u00e9 do Cerrito", "4216800"}; + rows[4669] = new String[] {"SC", "S\u00e3o Louren\u00e7o do Oeste", "4216909"}; + rows[4670] = new String[] {"SC", "S\u00e3o Ludgero", "4217006"}; + rows[4671] = new String[] {"SC", "S\u00e3o Martinho", "4217105"}; + rows[4672] = new String[] {"SC", "S\u00e3o Miguel da Boa Vista", "4217154"}; + rows[4673] = new String[] {"SC", "S\u00e3o Miguel do Oeste", "4217204"}; + rows[4674] = new String[] {"SC", "S\u00e3o Pedro de Alc\u00e2ntara", "4217253"}; + rows[4675] = new String[] {"SC", "Saudades", "4217303"}; + rows[4676] = new String[] {"SC", "Schroeder", "4217402"}; + rows[4677] = new String[] {"SC", "Seara", "4217501"}; + rows[4678] = new String[] {"SC", "Serra Alta", "4217550"}; + rows[4679] = new String[] {"SC", "Sider\u00f3polis", "4217600"}; + rows[4680] = new String[] {"SC", "Sombrio", "4217709"}; + rows[4681] = new String[] {"SC", "Sul Brasil", "4217758"}; + rows[4682] = new String[] {"SC", "Tai\u00f3", "4217808"}; + rows[4683] = new String[] {"SC", "Tangar\u00e1", "4217907"}; + rows[4684] = new String[] {"SC", "Tigrinhos", "4217956"}; + rows[4685] = new String[] {"SC", "Tijucas", "4218004"}; + rows[4686] = new String[] {"SC", "Timb\u00e9 do Sul", "4218103"}; + rows[4687] = new String[] {"SC", "Timb\u00f3", "4218202"}; + rows[4688] = new String[] {"SC", "Timb\u00f3 Grande", "4218251"}; + rows[4689] = new String[] {"SC", "Tr\u00eas Barras", "4218301"}; + rows[4690] = new String[] {"SC", "Treviso", "4218350"}; + rows[4691] = new String[] {"SC", "Treze de Maio", "4218400"}; + rows[4692] = new String[] {"SC", "Treze T\u00edlias", "4218509"}; + rows[4693] = new String[] {"SC", "Trombudo Central", "4218608"}; + rows[4694] = new String[] {"SC", "Tubar\u00e3o", "4218707"}; + rows[4695] = new String[] {"SC", "Tun\u00e1polis", "4218756"}; + rows[4696] = new String[] {"SC", "Turvo", "4218806"}; + rows[4697] = new String[] {"SC", "Uni\u00e3o do Oeste", "4218855"}; + rows[4698] = new String[] {"SC", "Urubici", "4218905"}; + rows[4699] = new String[] {"SC", "Urupema", "4218954"}; + rows[4700] = new String[] {"SC", "Urussanga", "4219002"}; + rows[4701] = new String[] {"SC", "Varge\u00e3o", "4219101"}; + rows[4702] = new String[] {"SC", "Vargem", "4219150"}; + rows[4703] = new String[] {"SC", "Vargem Bonita", "4219176"}; + rows[4704] = new String[] {"SC", "Vidal Ramos", "4219200"}; + rows[4705] = new String[] {"SC", "Videira", "4219309"}; + rows[4706] = new String[] {"SC", "Vitor Meireles", "4219358"}; + rows[4707] = new String[] {"SC", "Witmarsum", "4219408"}; + rows[4708] = new String[] {"SC", "Xanxer\u00ea", "4219507"}; + rows[4709] = new String[] {"SC", "Xavantina", "4219606"}; + rows[4710] = new String[] {"SC", "Xaxim", "4219705"}; + rows[4711] = new String[] {"SC", "Zort\u00e9a", "4219853"}; + rows[4712] = new String[] {"SP", "Adamantina", "3500105"}; + rows[4713] = new String[] {"SP", "Adolfo", "3500204"}; + rows[4714] = new String[] {"SP", "Agua\u00ed", "3500303"}; + rows[4715] = new String[] {"SP", "\u00c1guas da Prata", "3500402"}; + rows[4716] = new String[] {"SP", "\u00c1guas de Lind\u00f3ia", "3500501"}; + rows[4717] = new String[] {"SP", "\u00c1guas de Santa B\u00e1rbara", "3500550"}; + rows[4718] = new String[] {"SP", "\u00c1guas de S\u00e3o Pedro", "3500600"}; + rows[4719] = new String[] {"SP", "Agudos", "3500709"}; + rows[4720] = new String[] {"SP", "Alambari", "3500758"}; + rows[4721] = new String[] {"SP", "Alfredo Marcondes", "3500808"}; + rows[4722] = new String[] {"SP", "Altair", "3500907"}; + rows[4723] = new String[] {"SP", "Altin\u00f3polis", "3501004"}; + rows[4724] = new String[] {"SP", "Alto Alegre", "3501103"}; + rows[4725] = new String[] {"SP", "Alum\u00ednio", "3501152"}; + rows[4726] = new String[] {"SP", "\u00c1lvares Florence", "3501202"}; + rows[4727] = new String[] {"SP", "\u00c1lvares Machado", "3501301"}; + rows[4728] = new String[] {"SP", "\u00c1lvaro de Carvalho", "3501400"}; + rows[4729] = new String[] {"SP", "Alvinl\u00e2ndia", "3501509"}; + rows[4730] = new String[] {"SP", "Americana", "3501608"}; + rows[4731] = new String[] {"SP", "Am\u00e9rico Brasiliense", "3501707"}; + rows[4732] = new String[] {"SP", "Am\u00e9rico de Campos", "3501806"}; + rows[4733] = new String[] {"SP", "Amparo", "3501905"}; + rows[4734] = new String[] {"SP", "Anal\u00e2ndia", "3502002"}; + rows[4735] = new String[] {"SP", "Andradina", "3502101"}; + rows[4736] = new String[] {"SP", "Angatuba", "3502200"}; + rows[4737] = new String[] {"SP", "Anhembi", "3502309"}; + rows[4738] = new String[] {"SP", "Anhumas", "3502408"}; + rows[4739] = new String[] {"SP", "Aparecida", "3502507"}; + rows[4740] = new String[] {"SP", "Aparecida d'Oeste", "3502606"}; + rows[4741] = new String[] {"SP", "Apia\u00ed", "3502705"}; + rows[4742] = new String[] {"SP", "Ara\u00e7ariguama", "3502754"}; + rows[4743] = new String[] {"SP", "Ara\u00e7atuba", "3502804"}; + rows[4744] = new String[] {"SP", "Ara\u00e7oiaba da Serra", "3502903"}; + rows[4745] = new String[] {"SP", "Aramina", "3503000"}; + rows[4746] = new String[] {"SP", "Arandu", "3503109"}; + rows[4747] = new String[] {"SP", "Arape\u00ed", "3503158"}; + rows[4748] = new String[] {"SP", "Araraquara", "3503208"}; + rows[4749] = new String[] {"SP", "Araras", "3503307"}; + rows[4750] = new String[] {"SP", "Arco-\u00cdris", "3503356"}; + rows[4751] = new String[] {"SP", "Arealva", "3503406"}; + rows[4752] = new String[] {"SP", "Areias", "3503505"}; + rows[4753] = new String[] {"SP", "Arei\u00f3polis", "3503604"}; + rows[4754] = new String[] {"SP", "Ariranha", "3503703"}; + rows[4755] = new String[] {"SP", "Artur Nogueira", "3503802"}; + rows[4756] = new String[] {"SP", "Aruj\u00e1", "3503901"}; + rows[4757] = new String[] {"SP", "Asp\u00e1sia", "3503950"}; + rows[4758] = new String[] {"SP", "Assis", "3504008"}; + rows[4759] = new String[] {"SP", "Atibaia", "3504107"}; + rows[4760] = new String[] {"SP", "Auriflama", "3504206"}; + rows[4761] = new String[] {"SP", "Ava\u00ed", "3504305"}; + rows[4762] = new String[] {"SP", "Avanhandava", "3504404"}; + rows[4763] = new String[] {"SP", "Avar\u00e9", "3504503"}; + rows[4764] = new String[] {"SP", "Bady Bassitt", "3504602"}; + rows[4765] = new String[] {"SP", "Balbinos", "3504701"}; + rows[4766] = new String[] {"SP", "B\u00e1lsamo", "3504800"}; + rows[4767] = new String[] {"SP", "Bananal", "3504909"}; + rows[4768] = new String[] {"SP", "Bar\u00e3o de Antonina", "3505005"}; + rows[4769] = new String[] {"SP", "Barbosa", "3505104"}; + rows[4770] = new String[] {"SP", "Bariri", "3505203"}; + rows[4771] = new String[] {"SP", "Barra Bonita", "3505302"}; + rows[4772] = new String[] {"SP", "Barra do Chap\u00e9u", "3505351"}; + rows[4773] = new String[] {"SP", "Barra do Turvo", "3505401"}; + rows[4774] = new String[] {"SP", "Barretos", "3505500"}; + rows[4775] = new String[] {"SP", "Barrinha", "3505609"}; + rows[4776] = new String[] {"SP", "Barueri", "3505708"}; + rows[4777] = new String[] {"SP", "Bastos", "3505807"}; + rows[4778] = new String[] {"SP", "Batatais", "3505906"}; + rows[4779] = new String[] {"SP", "Bauru", "3506003"}; + rows[4780] = new String[] {"SP", "Bebedouro", "3506102"}; + rows[4781] = new String[] {"SP", "Bento de Abreu", "3506201"}; + rows[4782] = new String[] {"SP", "Bernardino de Campos", "3506300"}; + rows[4783] = new String[] {"SP", "Bertioga", "3506359"}; + rows[4784] = new String[] {"SP", "Bilac", "3506409"}; + rows[4785] = new String[] {"SP", "Birigui", "3506508"}; + rows[4786] = new String[] {"SP", "Biritiba Mirim", "3506607"}; + rows[4787] = new String[] {"SP", "Boa Esperan\u00e7a do Sul", "3506706"}; + rows[4788] = new String[] {"SP", "Bocaina", "3506805"}; + rows[4789] = new String[] {"SP", "Bofete", "3506904"}; + rows[4790] = new String[] {"SP", "Boituva", "3507001"}; + rows[4791] = new String[] {"SP", "Bom Jesus dos Perd\u00f5es", "3507100"}; + rows[4792] = new String[] {"SP", "Bom Sucesso de Itarar\u00e9", "3507159"}; + rows[4793] = new String[] {"SP", "Bor\u00e1", "3507209"}; + rows[4794] = new String[] {"SP", "Borac\u00e9ia", "3507308"}; + rows[4795] = new String[] {"SP", "Borborema", "3507407"}; + rows[4796] = new String[] {"SP", "Borebi", "3507456"}; + rows[4797] = new String[] {"SP", "Botucatu", "3507506"}; + rows[4798] = new String[] {"SP", "Bragan\u00e7a Paulista", "3507605"}; + rows[4799] = new String[] {"SP", "Bra\u00fana", "3507704"}; + } + + private static void municipalitiesRows24(String[][] rows) { + rows[4800] = new String[] {"SP", "Brejo Alegre", "3507753"}; + rows[4801] = new String[] {"SP", "Brodowski", "3507803"}; + rows[4802] = new String[] {"SP", "Brotas", "3507902"}; + rows[4803] = new String[] {"SP", "Buri", "3508009"}; + rows[4804] = new String[] {"SP", "Buritama", "3508108"}; + rows[4805] = new String[] {"SP", "Buritizal", "3508207"}; + rows[4806] = new String[] {"SP", "Cabr\u00e1lia Paulista", "3508306"}; + rows[4807] = new String[] {"SP", "Cabre\u00fava", "3508405"}; + rows[4808] = new String[] {"SP", "Ca\u00e7apava", "3508504"}; + rows[4809] = new String[] {"SP", "Cachoeira Paulista", "3508603"}; + rows[4810] = new String[] {"SP", "Caconde", "3508702"}; + rows[4811] = new String[] {"SP", "Cafel\u00e2ndia", "3508801"}; + rows[4812] = new String[] {"SP", "Caiabu", "3508900"}; + rows[4813] = new String[] {"SP", "Caieiras", "3509007"}; + rows[4814] = new String[] {"SP", "Caiu\u00e1", "3509106"}; + rows[4815] = new String[] {"SP", "Cajamar", "3509205"}; + rows[4816] = new String[] {"SP", "Cajati", "3509254"}; + rows[4817] = new String[] {"SP", "Cajobi", "3509304"}; + rows[4818] = new String[] {"SP", "Cajuru", "3509403"}; + rows[4819] = new String[] {"SP", "Campina do Monte Alegre", "3509452"}; + rows[4820] = new String[] {"SP", "Campinas", "3509502"}; + rows[4821] = new String[] {"SP", "Campo Limpo Paulista", "3509601"}; + rows[4822] = new String[] {"SP", "Campos do Jord\u00e3o", "3509700"}; + rows[4823] = new String[] {"SP", "Campos Novos Paulista", "3509809"}; + rows[4824] = new String[] {"SP", "Canan\u00e9ia", "3509908"}; + rows[4825] = new String[] {"SP", "Canas", "3509957"}; + rows[4826] = new String[] {"SP", "C\u00e2ndido Mota", "3510005"}; + rows[4827] = new String[] {"SP", "C\u00e2ndido Rodrigues", "3510104"}; + rows[4828] = new String[] {"SP", "Canitar", "3510153"}; + rows[4829] = new String[] {"SP", "Cap\u00e3o Bonito", "3510203"}; + rows[4830] = new String[] {"SP", "Capela do Alto", "3510302"}; + rows[4831] = new String[] {"SP", "Capivari", "3510401"}; + rows[4832] = new String[] {"SP", "Caraguatatuba", "3510500"}; + rows[4833] = new String[] {"SP", "Carapicu\u00edba", "3510609"}; + rows[4834] = new String[] {"SP", "Cardoso", "3510708"}; + rows[4835] = new String[] {"SP", "Casa Branca", "3510807"}; + rows[4836] = new String[] {"SP", "C\u00e1ssia dos Coqueiros", "3510906"}; + rows[4837] = new String[] {"SP", "Castilho", "3511003"}; + rows[4838] = new String[] {"SP", "Catanduva", "3511102"}; + rows[4839] = new String[] {"SP", "Catigu\u00e1", "3511201"}; + rows[4840] = new String[] {"SP", "Cedral", "3511300"}; + rows[4841] = new String[] {"SP", "Cerqueira C\u00e9sar", "3511409"}; + rows[4842] = new String[] {"SP", "Cerquilho", "3511508"}; + rows[4843] = new String[] {"SP", "Ces\u00e1rio Lange", "3511607"}; + rows[4844] = new String[] {"SP", "Charqueada", "3511706"}; + rows[4845] = new String[] {"SP", "Chavantes", "3557204"}; + rows[4846] = new String[] {"SP", "Clementina", "3511904"}; + rows[4847] = new String[] {"SP", "Colina", "3512001"}; + rows[4848] = new String[] {"SP", "Col\u00f4mbia", "3512100"}; + rows[4849] = new String[] {"SP", "Conchal", "3512209"}; + rows[4850] = new String[] {"SP", "Conchas", "3512308"}; + rows[4851] = new String[] {"SP", "Cordeir\u00f3polis", "3512407"}; + rows[4852] = new String[] {"SP", "Coroados", "3512506"}; + rows[4853] = new String[] {"SP", "Coronel Macedo", "3512605"}; + rows[4854] = new String[] {"SP", "Corumbata\u00ed", "3512704"}; + rows[4855] = new String[] {"SP", "Cosm\u00f3polis", "3512803"}; + rows[4856] = new String[] {"SP", "Cosmorama", "3512902"}; + rows[4857] = new String[] {"SP", "Cotia", "3513009"}; + rows[4858] = new String[] {"SP", "Cravinhos", "3513108"}; + rows[4859] = new String[] {"SP", "Cristais Paulista", "3513207"}; + rows[4860] = new String[] {"SP", "Cruz\u00e1lia", "3513306"}; + rows[4861] = new String[] {"SP", "Cruzeiro", "3513405"}; + rows[4862] = new String[] {"SP", "Cubat\u00e3o", "3513504"}; + rows[4863] = new String[] {"SP", "Cunha", "3513603"}; + rows[4864] = new String[] {"SP", "Descalvado", "3513702"}; + rows[4865] = new String[] {"SP", "Diadema", "3513801"}; + rows[4866] = new String[] {"SP", "Dirce Reis", "3513850"}; + rows[4867] = new String[] {"SP", "Divinol\u00e2ndia", "3513900"}; + rows[4868] = new String[] {"SP", "Dobrada", "3514007"}; + rows[4869] = new String[] {"SP", "Dois C\u00f3rregos", "3514106"}; + rows[4870] = new String[] {"SP", "Dolcin\u00f3polis", "3514205"}; + rows[4871] = new String[] {"SP", "Dourado", "3514304"}; + rows[4872] = new String[] {"SP", "Dracena", "3514403"}; + rows[4873] = new String[] {"SP", "Duartina", "3514502"}; + rows[4874] = new String[] {"SP", "Dumont", "3514601"}; + rows[4875] = new String[] {"SP", "Echapor\u00e3", "3514700"}; + rows[4876] = new String[] {"SP", "Eldorado", "3514809"}; + rows[4877] = new String[] {"SP", "Elias Fausto", "3514908"}; + rows[4878] = new String[] {"SP", "Elisi\u00e1rio", "3514924"}; + rows[4879] = new String[] {"SP", "Emba\u00faba", "3514957"}; + rows[4880] = new String[] {"SP", "Embu das Artes", "3515004"}; + rows[4881] = new String[] {"SP", "Embu-Gua\u00e7u", "3515103"}; + rows[4882] = new String[] {"SP", "Emilian\u00f3polis", "3515129"}; + rows[4883] = new String[] {"SP", "Engenheiro Coelho", "3515152"}; + rows[4884] = new String[] {"SP", "Esp\u00edrito Santo do Pinhal", "3515186"}; + rows[4885] = new String[] {"SP", "Esp\u00edrito Santo do Turvo", "3515194"}; + rows[4886] = new String[] {"SP", "Estiva Gerbi", "3557303"}; + rows[4887] = new String[] {"SP", "Estrela d'Oeste", "3515202"}; + rows[4888] = new String[] {"SP", "Estrela do Norte", "3515301"}; + rows[4889] = new String[] {"SP", "Euclides da Cunha Paulista", "3515350"}; + rows[4890] = new String[] {"SP", "Fartura", "3515400"}; + rows[4891] = new String[] {"SP", "Fernando Prestes", "3515608"}; + rows[4892] = new String[] {"SP", "Fernand\u00f3polis", "3515509"}; + rows[4893] = new String[] {"SP", "Fern\u00e3o", "3515657"}; + rows[4894] = new String[] {"SP", "Ferraz de Vasconcelos", "3515707"}; + rows[4895] = new String[] {"SP", "Flora Rica", "3515806"}; + rows[4896] = new String[] {"SP", "Floreal", "3515905"}; + rows[4897] = new String[] {"SP", "Fl\u00f3rida Paulista", "3516002"}; + rows[4898] = new String[] {"SP", "Flor\u00ednea", "3516101"}; + rows[4899] = new String[] {"SP", "Franca", "3516200"}; + rows[4900] = new String[] {"SP", "Francisco Morato", "3516309"}; + rows[4901] = new String[] {"SP", "Franco da Rocha", "3516408"}; + rows[4902] = new String[] {"SP", "Gabriel Monteiro", "3516507"}; + rows[4903] = new String[] {"SP", "G\u00e1lia", "3516606"}; + rows[4904] = new String[] {"SP", "Gar\u00e7a", "3516705"}; + rows[4905] = new String[] {"SP", "Gast\u00e3o Vidigal", "3516804"}; + rows[4906] = new String[] {"SP", "Gavi\u00e3o Peixoto", "3516853"}; + rows[4907] = new String[] {"SP", "General Salgado", "3516903"}; + rows[4908] = new String[] {"SP", "Getulina", "3517000"}; + rows[4909] = new String[] {"SP", "Glic\u00e9rio", "3517109"}; + rows[4910] = new String[] {"SP", "Guai\u00e7ara", "3517208"}; + rows[4911] = new String[] {"SP", "Guaimb\u00ea", "3517307"}; + rows[4912] = new String[] {"SP", "Gua\u00edra", "3517406"}; + rows[4913] = new String[] {"SP", "Guapia\u00e7u", "3517505"}; + rows[4914] = new String[] {"SP", "Guapiara", "3517604"}; + rows[4915] = new String[] {"SP", "Guar\u00e1", "3517703"}; + rows[4916] = new String[] {"SP", "Guara\u00e7a\u00ed", "3517802"}; + rows[4917] = new String[] {"SP", "Guaraci", "3517901"}; + rows[4918] = new String[] {"SP", "Guarani d'Oeste", "3518008"}; + rows[4919] = new String[] {"SP", "Guarant\u00e3", "3518107"}; + rows[4920] = new String[] {"SP", "Guararapes", "3518206"}; + rows[4921] = new String[] {"SP", "Guararema", "3518305"}; + rows[4922] = new String[] {"SP", "Guaratinguet\u00e1", "3518404"}; + rows[4923] = new String[] {"SP", "Guare\u00ed", "3518503"}; + rows[4924] = new String[] {"SP", "Guariba", "3518602"}; + rows[4925] = new String[] {"SP", "Guaruj\u00e1", "3518701"}; + rows[4926] = new String[] {"SP", "Guarulhos", "3518800"}; + rows[4927] = new String[] {"SP", "Guatapar\u00e1", "3518859"}; + rows[4928] = new String[] {"SP", "Guzol\u00e2ndia", "3518909"}; + rows[4929] = new String[] {"SP", "Hercul\u00e2ndia", "3519006"}; + rows[4930] = new String[] {"SP", "Holambra", "3519055"}; + rows[4931] = new String[] {"SP", "Hortol\u00e2ndia", "3519071"}; + rows[4932] = new String[] {"SP", "Iacanga", "3519105"}; + rows[4933] = new String[] {"SP", "Iacri", "3519204"}; + rows[4934] = new String[] {"SP", "Iaras", "3519253"}; + rows[4935] = new String[] {"SP", "Ibat\u00e9", "3519303"}; + rows[4936] = new String[] {"SP", "Ibir\u00e1", "3519402"}; + rows[4937] = new String[] {"SP", "Ibirarema", "3519501"}; + rows[4938] = new String[] {"SP", "Ibitinga", "3519600"}; + rows[4939] = new String[] {"SP", "Ibi\u00fana", "3519709"}; + rows[4940] = new String[] {"SP", "Ic\u00e9m", "3519808"}; + rows[4941] = new String[] {"SP", "Iep\u00ea", "3519907"}; + rows[4942] = new String[] {"SP", "Igara\u00e7u do Tiet\u00ea", "3520004"}; + rows[4943] = new String[] {"SP", "Igarapava", "3520103"}; + rows[4944] = new String[] {"SP", "Igarat\u00e1", "3520202"}; + rows[4945] = new String[] {"SP", "Iguape", "3520301"}; + rows[4946] = new String[] {"SP", "Ilha Comprida", "3520426"}; + rows[4947] = new String[] {"SP", "Ilha Solteira", "3520442"}; + rows[4948] = new String[] {"SP", "Ilhabela", "3520400"}; + rows[4949] = new String[] {"SP", "Indaiatuba", "3520509"}; + rows[4950] = new String[] {"SP", "Indiana", "3520608"}; + rows[4951] = new String[] {"SP", "Indiapor\u00e3", "3520707"}; + rows[4952] = new String[] {"SP", "In\u00fabia Paulista", "3520806"}; + rows[4953] = new String[] {"SP", "Ipaussu", "3520905"}; + rows[4954] = new String[] {"SP", "Iper\u00f3", "3521002"}; + rows[4955] = new String[] {"SP", "Ipe\u00fana", "3521101"}; + rows[4956] = new String[] {"SP", "Ipigu\u00e1", "3521150"}; + rows[4957] = new String[] {"SP", "Iporanga", "3521200"}; + rows[4958] = new String[] {"SP", "Ipu\u00e3", "3521309"}; + rows[4959] = new String[] {"SP", "Iracem\u00e1polis", "3521408"}; + rows[4960] = new String[] {"SP", "Irapu\u00e3", "3521507"}; + rows[4961] = new String[] {"SP", "Irapuru", "3521606"}; + rows[4962] = new String[] {"SP", "Itaber\u00e1", "3521705"}; + rows[4963] = new String[] {"SP", "Ita\u00ed", "3521804"}; + rows[4964] = new String[] {"SP", "Itajobi", "3521903"}; + rows[4965] = new String[] {"SP", "Itaju", "3522000"}; + rows[4966] = new String[] {"SP", "Itanha\u00e9m", "3522109"}; + rows[4967] = new String[] {"SP", "Itaoca", "3522158"}; + rows[4968] = new String[] {"SP", "Itapecerica da Serra", "3522208"}; + rows[4969] = new String[] {"SP", "Itapetininga", "3522307"}; + rows[4970] = new String[] {"SP", "Itapeva", "3522406"}; + rows[4971] = new String[] {"SP", "Itapevi", "3522505"}; + rows[4972] = new String[] {"SP", "Itapira", "3522604"}; + rows[4973] = new String[] {"SP", "Itapirapu\u00e3 Paulista", "3522653"}; + rows[4974] = new String[] {"SP", "It\u00e1polis", "3522703"}; + rows[4975] = new String[] {"SP", "Itaporanga", "3522802"}; + rows[4976] = new String[] {"SP", "Itapu\u00ed", "3522901"}; + rows[4977] = new String[] {"SP", "Itapura", "3523008"}; + rows[4978] = new String[] {"SP", "Itaquaquecetuba", "3523107"}; + rows[4979] = new String[] {"SP", "Itarar\u00e9", "3523206"}; + rows[4980] = new String[] {"SP", "Itariri", "3523305"}; + rows[4981] = new String[] {"SP", "Itatiba", "3523404"}; + rows[4982] = new String[] {"SP", "Itatinga", "3523503"}; + rows[4983] = new String[] {"SP", "Itirapina", "3523602"}; + rows[4984] = new String[] {"SP", "Itirapu\u00e3", "3523701"}; + rows[4985] = new String[] {"SP", "Itobi", "3523800"}; + rows[4986] = new String[] {"SP", "Itu", "3523909"}; + rows[4987] = new String[] {"SP", "Itupeva", "3524006"}; + rows[4988] = new String[] {"SP", "Ituverava", "3524105"}; + rows[4989] = new String[] {"SP", "Jaborandi", "3524204"}; + rows[4990] = new String[] {"SP", "Jaboticabal", "3524303"}; + rows[4991] = new String[] {"SP", "Jacare\u00ed", "3524402"}; + rows[4992] = new String[] {"SP", "Jaci", "3524501"}; + rows[4993] = new String[] {"SP", "Jacupiranga", "3524600"}; + rows[4994] = new String[] {"SP", "Jaguari\u00fana", "3524709"}; + rows[4995] = new String[] {"SP", "Jales", "3524808"}; + rows[4996] = new String[] {"SP", "Jambeiro", "3524907"}; + rows[4997] = new String[] {"SP", "Jandira", "3525003"}; + rows[4998] = new String[] {"SP", "Jardin\u00f3polis", "3525102"}; + rows[4999] = new String[] {"SP", "Jarinu", "3525201"}; + } + + private static void municipalitiesRows25(String[][] rows) { + rows[5000] = new String[] {"SP", "Ja\u00fa", "3525300"}; + rows[5001] = new String[] {"SP", "Jeriquara", "3525409"}; + rows[5002] = new String[] {"SP", "Joan\u00f3polis", "3525508"}; + rows[5003] = new String[] {"SP", "Jo\u00e3o Ramalho", "3525607"}; + rows[5004] = new String[] {"SP", "Jos\u00e9 Bonif\u00e1cio", "3525706"}; + rows[5005] = new String[] {"SP", "J\u00falio Mesquita", "3525805"}; + rows[5006] = new String[] {"SP", "Jumirim", "3525854"}; + rows[5007] = new String[] {"SP", "Jundia\u00ed", "3525904"}; + rows[5008] = new String[] {"SP", "Junqueir\u00f3polis", "3526001"}; + rows[5009] = new String[] {"SP", "Juqui\u00e1", "3526100"}; + rows[5010] = new String[] {"SP", "Juquitiba", "3526209"}; + rows[5011] = new String[] {"SP", "Lagoinha", "3526308"}; + rows[5012] = new String[] {"SP", "Laranjal Paulista", "3526407"}; + rows[5013] = new String[] {"SP", "Lav\u00ednia", "3526506"}; + rows[5014] = new String[] {"SP", "Lavrinhas", "3526605"}; + rows[5015] = new String[] {"SP", "Leme", "3526704"}; + rows[5016] = new String[] {"SP", "Len\u00e7\u00f3is Paulista", "3526803"}; + rows[5017] = new String[] {"SP", "Limeira", "3526902"}; + rows[5018] = new String[] {"SP", "Lind\u00f3ia", "3527009"}; + rows[5019] = new String[] {"SP", "Lins", "3527108"}; + rows[5020] = new String[] {"SP", "Lorena", "3527207"}; + rows[5021] = new String[] {"SP", "Lourdes", "3527256"}; + rows[5022] = new String[] {"SP", "Louveira", "3527306"}; + rows[5023] = new String[] {"SP", "Luc\u00e9lia", "3527405"}; + rows[5024] = new String[] {"SP", "Lucian\u00f3polis", "3527504"}; + rows[5025] = new String[] {"SP", "Lu\u00eds Ant\u00f4nio", "3527603"}; + rows[5026] = new String[] {"SP", "Luizi\u00e2nia", "3527702"}; + rows[5027] = new String[] {"SP", "Lup\u00e9rcio", "3527801"}; + rows[5028] = new String[] {"SP", "Lut\u00e9cia", "3527900"}; + rows[5029] = new String[] {"SP", "Macatuba", "3528007"}; + rows[5030] = new String[] {"SP", "Macaubal", "3528106"}; + rows[5031] = new String[] {"SP", "Maced\u00f4nia", "3528205"}; + rows[5032] = new String[] {"SP", "Magda", "3528304"}; + rows[5033] = new String[] {"SP", "Mairinque", "3528403"}; + rows[5034] = new String[] {"SP", "Mairipor\u00e3", "3528502"}; + rows[5035] = new String[] {"SP", "Manduri", "3528601"}; + rows[5036] = new String[] {"SP", "Marab\u00e1 Paulista", "3528700"}; + rows[5037] = new String[] {"SP", "Maraca\u00ed", "3528809"}; + rows[5038] = new String[] {"SP", "Marapoama", "3528858"}; + rows[5039] = new String[] {"SP", "Mari\u00e1polis", "3528908"}; + rows[5040] = new String[] {"SP", "Mar\u00edlia", "3529005"}; + rows[5041] = new String[] {"SP", "Marin\u00f3polis", "3529104"}; + rows[5042] = new String[] {"SP", "Martin\u00f3polis", "3529203"}; + rows[5043] = new String[] {"SP", "Mat\u00e3o", "3529302"}; + rows[5044] = new String[] {"SP", "Mau\u00e1", "3529401"}; + rows[5045] = new String[] {"SP", "Mendon\u00e7a", "3529500"}; + rows[5046] = new String[] {"SP", "Meridiano", "3529609"}; + rows[5047] = new String[] {"SP", "Mes\u00f3polis", "3529658"}; + rows[5048] = new String[] {"SP", "Miguel\u00f3polis", "3529708"}; + rows[5049] = new String[] {"SP", "Mineiros do Tiet\u00ea", "3529807"}; + rows[5050] = new String[] {"SP", "Mira Estrela", "3530003"}; + rows[5051] = new String[] {"SP", "Miracatu", "3529906"}; + rows[5052] = new String[] {"SP", "Mirand\u00f3polis", "3530102"}; + rows[5053] = new String[] {"SP", "Mirante do Paranapanema", "3530201"}; + rows[5054] = new String[] {"SP", "Mirassol", "3530300"}; + rows[5055] = new String[] {"SP", "Mirassol\u00e2ndia", "3530409"}; + rows[5056] = new String[] {"SP", "Mococa", "3530508"}; + rows[5057] = new String[] {"SP", "Mogi das Cruzes", "3530607"}; + rows[5058] = new String[] {"SP", "Mogi Gua\u00e7u", "3530706"}; + rows[5059] = new String[] {"SP", "Mogi Mirim", "3530805"}; + rows[5060] = new String[] {"SP", "Mombuca", "3530904"}; + rows[5061] = new String[] {"SP", "Mon\u00e7\u00f5es", "3531001"}; + rows[5062] = new String[] {"SP", "Mongagu\u00e1", "3531100"}; + rows[5063] = new String[] {"SP", "Monte Alegre do Sul", "3531209"}; + rows[5064] = new String[] {"SP", "Monte Alto", "3531308"}; + rows[5065] = new String[] {"SP", "Monte Apraz\u00edvel", "3531407"}; + rows[5066] = new String[] {"SP", "Monte Azul Paulista", "3531506"}; + rows[5067] = new String[] {"SP", "Monte Castelo", "3531605"}; + rows[5068] = new String[] {"SP", "Monte Mor", "3531803"}; + rows[5069] = new String[] {"SP", "Monteiro Lobato", "3531704"}; + rows[5070] = new String[] {"SP", "Morro Agudo", "3531902"}; + rows[5071] = new String[] {"SP", "Morungaba", "3532009"}; + rows[5072] = new String[] {"SP", "Motuca", "3532058"}; + rows[5073] = new String[] {"SP", "Murutinga do Sul", "3532108"}; + rows[5074] = new String[] {"SP", "Nantes", "3532157"}; + rows[5075] = new String[] {"SP", "Narandiba", "3532207"}; + rows[5076] = new String[] {"SP", "Natividade da Serra", "3532306"}; + rows[5077] = new String[] {"SP", "Nazar\u00e9 Paulista", "3532405"}; + rows[5078] = new String[] {"SP", "Neves Paulista", "3532504"}; + rows[5079] = new String[] {"SP", "Nhandeara", "3532603"}; + rows[5080] = new String[] {"SP", "Nipo\u00e3", "3532702"}; + rows[5081] = new String[] {"SP", "Nova Alian\u00e7a", "3532801"}; + rows[5082] = new String[] {"SP", "Nova Campina", "3532827"}; + rows[5083] = new String[] {"SP", "Nova Cana\u00e3 Paulista", "3532843"}; + rows[5084] = new String[] {"SP", "Nova Castilho", "3532868"}; + rows[5085] = new String[] {"SP", "Nova Europa", "3532900"}; + rows[5086] = new String[] {"SP", "Nova Granada", "3533007"}; + rows[5087] = new String[] {"SP", "Nova Guataporanga", "3533106"}; + rows[5088] = new String[] {"SP", "Nova Independ\u00eancia", "3533205"}; + rows[5089] = new String[] {"SP", "Nova Luzit\u00e2nia", "3533304"}; + rows[5090] = new String[] {"SP", "Nova Odessa", "3533403"}; + rows[5091] = new String[] {"SP", "Novais", "3533254"}; + rows[5092] = new String[] {"SP", "Novo Horizonte", "3533502"}; + rows[5093] = new String[] {"SP", "Nuporanga", "3533601"}; + rows[5094] = new String[] {"SP", "Ocau\u00e7u", "3533700"}; + rows[5095] = new String[] {"SP", "\u00d3leo", "3533809"}; + rows[5096] = new String[] {"SP", "Ol\u00edmpia", "3533908"}; + rows[5097] = new String[] {"SP", "Onda Verde", "3534005"}; + rows[5098] = new String[] {"SP", "Oriente", "3534104"}; + rows[5099] = new String[] {"SP", "Orindi\u00fava", "3534203"}; + rows[5100] = new String[] {"SP", "Orl\u00e2ndia", "3534302"}; + rows[5101] = new String[] {"SP", "Osasco", "3534401"}; + rows[5102] = new String[] {"SP", "Oscar Bressane", "3534500"}; + rows[5103] = new String[] {"SP", "Osvaldo Cruz", "3534609"}; + rows[5104] = new String[] {"SP", "Ourinhos", "3534708"}; + rows[5105] = new String[] {"SP", "Ouro Verde", "3534807"}; + rows[5106] = new String[] {"SP", "Ouroeste", "3534757"}; + rows[5107] = new String[] {"SP", "Pacaembu", "3534906"}; + rows[5108] = new String[] {"SP", "Palestina", "3535002"}; + rows[5109] = new String[] {"SP", "Palmares Paulista", "3535101"}; + rows[5110] = new String[] {"SP", "Palmeira d'Oeste", "3535200"}; + rows[5111] = new String[] {"SP", "Palmital", "3535309"}; + rows[5112] = new String[] {"SP", "Panorama", "3535408"}; + rows[5113] = new String[] {"SP", "Paragua\u00e7u Paulista", "3535507"}; + rows[5114] = new String[] {"SP", "Paraibuna", "3535606"}; + rows[5115] = new String[] {"SP", "Para\u00edso", "3535705"}; + rows[5116] = new String[] {"SP", "Paranapanema", "3535804"}; + rows[5117] = new String[] {"SP", "Paranapu\u00e3", "3535903"}; + rows[5118] = new String[] {"SP", "Parapu\u00e3", "3536000"}; + rows[5119] = new String[] {"SP", "Pardinho", "3536109"}; + rows[5120] = new String[] {"SP", "Pariquera-A\u00e7u", "3536208"}; + rows[5121] = new String[] {"SP", "Parisi", "3536257"}; + rows[5122] = new String[] {"SP", "Patroc\u00ednio Paulista", "3536307"}; + rows[5123] = new String[] {"SP", "Paulic\u00e9ia", "3536406"}; + rows[5124] = new String[] {"SP", "Paul\u00ednia", "3536505"}; + rows[5125] = new String[] {"SP", "Paulist\u00e2nia", "3536570"}; + rows[5126] = new String[] {"SP", "Paulo de Faria", "3536604"}; + rows[5127] = new String[] {"SP", "Pederneiras", "3536703"}; + rows[5128] = new String[] {"SP", "Pedra Bela", "3536802"}; + rows[5129] = new String[] {"SP", "Pedran\u00f3polis", "3536901"}; + rows[5130] = new String[] {"SP", "Pedregulho", "3537008"}; + rows[5131] = new String[] {"SP", "Pedreira", "3537107"}; + rows[5132] = new String[] {"SP", "Pedrinhas Paulista", "3537156"}; + rows[5133] = new String[] {"SP", "Pedro de Toledo", "3537206"}; + rows[5134] = new String[] {"SP", "Pen\u00e1polis", "3537305"}; + rows[5135] = new String[] {"SP", "Pereira Barreto", "3537404"}; + rows[5136] = new String[] {"SP", "Pereiras", "3537503"}; + rows[5137] = new String[] {"SP", "Peru\u00edbe", "3537602"}; + rows[5138] = new String[] {"SP", "Piacatu", "3537701"}; + rows[5139] = new String[] {"SP", "Piedade", "3537800"}; + rows[5140] = new String[] {"SP", "Pilar do Sul", "3537909"}; + rows[5141] = new String[] {"SP", "Pindamonhangaba", "3538006"}; + rows[5142] = new String[] {"SP", "Pindorama", "3538105"}; + rows[5143] = new String[] {"SP", "Pinhalzinho", "3538204"}; + rows[5144] = new String[] {"SP", "Piquerobi", "3538303"}; + rows[5145] = new String[] {"SP", "Piquete", "3538501"}; + rows[5146] = new String[] {"SP", "Piracaia", "3538600"}; + rows[5147] = new String[] {"SP", "Piracicaba", "3538709"}; + rows[5148] = new String[] {"SP", "Piraju", "3538808"}; + rows[5149] = new String[] {"SP", "Piraju\u00ed", "3538907"}; + rows[5150] = new String[] {"SP", "Pirangi", "3539004"}; + rows[5151] = new String[] {"SP", "Pirapora do Bom Jesus", "3539103"}; + rows[5152] = new String[] {"SP", "Pirapozinho", "3539202"}; + rows[5153] = new String[] {"SP", "Pirassununga", "3539301"}; + rows[5154] = new String[] {"SP", "Piratininga", "3539400"}; + rows[5155] = new String[] {"SP", "Pitangueiras", "3539509"}; + rows[5156] = new String[] {"SP", "Planalto", "3539608"}; + rows[5157] = new String[] {"SP", "Platina", "3539707"}; + rows[5158] = new String[] {"SP", "Po\u00e1", "3539806"}; + rows[5159] = new String[] {"SP", "Poloni", "3539905"}; + rows[5160] = new String[] {"SP", "Pomp\u00e9ia", "3540002"}; + rows[5161] = new String[] {"SP", "Ponga\u00ed", "3540101"}; + rows[5162] = new String[] {"SP", "Pontal", "3540200"}; + rows[5163] = new String[] {"SP", "Pontalinda", "3540259"}; + rows[5164] = new String[] {"SP", "Pontes Gestal", "3540309"}; + rows[5165] = new String[] {"SP", "Populina", "3540408"}; + rows[5166] = new String[] {"SP", "Porangaba", "3540507"}; + rows[5167] = new String[] {"SP", "Porto Feliz", "3540606"}; + rows[5168] = new String[] {"SP", "Porto Ferreira", "3540705"}; + rows[5169] = new String[] {"SP", "Potim", "3540754"}; + rows[5170] = new String[] {"SP", "Potirendaba", "3540804"}; + rows[5171] = new String[] {"SP", "Pracinha", "3540853"}; + rows[5172] = new String[] {"SP", "Prad\u00f3polis", "3540903"}; + rows[5173] = new String[] {"SP", "Praia Grande", "3541000"}; + rows[5174] = new String[] {"SP", "Prat\u00e2nia", "3541059"}; + rows[5175] = new String[] {"SP", "Presidente Alves", "3541109"}; + rows[5176] = new String[] {"SP", "Presidente Bernardes", "3541208"}; + rows[5177] = new String[] {"SP", "Presidente Epit\u00e1cio", "3541307"}; + rows[5178] = new String[] {"SP", "Presidente Prudente", "3541406"}; + rows[5179] = new String[] {"SP", "Presidente Venceslau", "3541505"}; + rows[5180] = new String[] {"SP", "Promiss\u00e3o", "3541604"}; + rows[5181] = new String[] {"SP", "Quadra", "3541653"}; + rows[5182] = new String[] {"SP", "Quat\u00e1", "3541703"}; + rows[5183] = new String[] {"SP", "Queiroz", "3541802"}; + rows[5184] = new String[] {"SP", "Queluz", "3541901"}; + rows[5185] = new String[] {"SP", "Quintana", "3542008"}; + rows[5186] = new String[] {"SP", "Rafard", "3542107"}; + rows[5187] = new String[] {"SP", "Rancharia", "3542206"}; + rows[5188] = new String[] {"SP", "Reden\u00e7\u00e3o da Serra", "3542305"}; + rows[5189] = new String[] {"SP", "Regente Feij\u00f3", "3542404"}; + rows[5190] = new String[] {"SP", "Regin\u00f3polis", "3542503"}; + rows[5191] = new String[] {"SP", "Registro", "3542602"}; + rows[5192] = new String[] {"SP", "Restinga", "3542701"}; + rows[5193] = new String[] {"SP", "Ribeira", "3542800"}; + rows[5194] = new String[] {"SP", "Ribeir\u00e3o Bonito", "3542909"}; + rows[5195] = new String[] {"SP", "Ribeir\u00e3o Branco", "3543006"}; + rows[5196] = new String[] {"SP", "Ribeir\u00e3o Corrente", "3543105"}; + rows[5197] = new String[] {"SP", "Ribeir\u00e3o do Sul", "3543204"}; + rows[5198] = new String[] {"SP", "Ribeir\u00e3o dos \u00cdndios", "3543238"}; + rows[5199] = new String[] {"SP", "Ribeir\u00e3o Grande", "3543253"}; + } + + private static void municipalitiesRows26(String[][] rows) { + rows[5200] = new String[] {"SP", "Ribeir\u00e3o Pires", "3543303"}; + rows[5201] = new String[] {"SP", "Ribeir\u00e3o Preto", "3543402"}; + rows[5202] = new String[] {"SP", "Rifaina", "3543600"}; + rows[5203] = new String[] {"SP", "Rinc\u00e3o", "3543709"}; + rows[5204] = new String[] {"SP", "Rin\u00f3polis", "3543808"}; + rows[5205] = new String[] {"SP", "Rio Claro", "3543907"}; + rows[5206] = new String[] {"SP", "Rio das Pedras", "3544004"}; + rows[5207] = new String[] {"SP", "Rio Grande da Serra", "3544103"}; + rows[5208] = new String[] {"SP", "Riol\u00e2ndia", "3544202"}; + rows[5209] = new String[] {"SP", "Riversul", "3543501"}; + rows[5210] = new String[] {"SP", "Rosana", "3544251"}; + rows[5211] = new String[] {"SP", "Roseira", "3544301"}; + rows[5212] = new String[] {"SP", "Rubi\u00e1cea", "3544400"}; + rows[5213] = new String[] {"SP", "Rubin\u00e9ia", "3544509"}; + rows[5214] = new String[] {"SP", "Sabino", "3544608"}; + rows[5215] = new String[] {"SP", "Sagres", "3544707"}; + rows[5216] = new String[] {"SP", "Sales", "3544806"}; + rows[5217] = new String[] {"SP", "Sales Oliveira", "3544905"}; + rows[5218] = new String[] {"SP", "Sales\u00f3polis", "3545001"}; + rows[5219] = new String[] {"SP", "Salmour\u00e3o", "3545100"}; + rows[5220] = new String[] {"SP", "Saltinho", "3545159"}; + rows[5221] = new String[] {"SP", "Salto", "3545209"}; + rows[5222] = new String[] {"SP", "Salto de Pirapora", "3545308"}; + rows[5223] = new String[] {"SP", "Salto Grande", "3545407"}; + rows[5224] = new String[] {"SP", "Sandovalina", "3545506"}; + rows[5225] = new String[] {"SP", "Santa Ad\u00e9lia", "3545605"}; + rows[5226] = new String[] {"SP", "Santa Albertina", "3545704"}; + rows[5227] = new String[] {"SP", "Santa B\u00e1rbara d'Oeste", "3545803"}; + rows[5228] = new String[] {"SP", "Santa Branca", "3546009"}; + rows[5229] = new String[] {"SP", "Santa Clara d'Oeste", "3546108"}; + rows[5230] = new String[] {"SP", "Santa Cruz da Concei\u00e7\u00e3o", "3546207"}; + rows[5231] = new String[] {"SP", "Santa Cruz da Esperan\u00e7a", "3546256"}; + rows[5232] = new String[] {"SP", "Santa Cruz das Palmeiras", "3546306"}; + rows[5233] = new String[] {"SP", "Santa Cruz do Rio Pardo", "3546405"}; + rows[5234] = new String[] {"SP", "Santa Ernestina", "3546504"}; + rows[5235] = new String[] {"SP", "Santa F\u00e9 do Sul", "3546603"}; + rows[5236] = new String[] {"SP", "Santa Gertrudes", "3546702"}; + rows[5237] = new String[] {"SP", "Santa Isabel", "3546801"}; + rows[5238] = new String[] {"SP", "Santa L\u00facia", "3546900"}; + rows[5239] = new String[] {"SP", "Santa Maria da Serra", "3547007"}; + rows[5240] = new String[] {"SP", "Santa Mercedes", "3547106"}; + rows[5241] = new String[] {"SP", "Santa Rita d'Oeste", "3547403"}; + rows[5242] = new String[] {"SP", "Santa Rita do Passa Quatro", "3547502"}; + rows[5243] = new String[] {"SP", "Santa Rosa de Viterbo", "3547601"}; + rows[5244] = new String[] {"SP", "Santa Salete", "3547650"}; + rows[5245] = new String[] {"SP", "Santana da Ponte Pensa", "3547205"}; + rows[5246] = new String[] {"SP", "Santana de Parna\u00edba", "3547304"}; + rows[5247] = new String[] {"SP", "Santo Anast\u00e1cio", "3547700"}; + rows[5248] = new String[] {"SP", "Santo Andr\u00e9", "3547809"}; + rows[5249] = new String[] {"SP", "Santo Ant\u00f4nio da Alegria", "3547908"}; + rows[5250] = new String[] {"SP", "Santo Ant\u00f4nio de Posse", "3548005"}; + rows[5251] = new String[] {"SP", "Santo Ant\u00f4nio do Aracangu\u00e1", "3548054"}; + rows[5252] = new String[] {"SP", "Santo Ant\u00f4nio do Jardim", "3548104"}; + rows[5253] = new String[] {"SP", "Santo Ant\u00f4nio do Pinhal", "3548203"}; + rows[5254] = new String[] {"SP", "Santo Expedito", "3548302"}; + rows[5255] = new String[] {"SP", "Sant\u00f3polis do Aguape\u00ed", "3548401"}; + rows[5256] = new String[] {"SP", "Santos", "3548500"}; + rows[5257] = new String[] {"SP", "S\u00e3o Bento do Sapuca\u00ed", "3548609"}; + rows[5258] = new String[] {"SP", "S\u00e3o Bernardo do Campo", "3548708"}; + rows[5259] = new String[] {"SP", "S\u00e3o Caetano do Sul", "3548807"}; + rows[5260] = new String[] {"SP", "S\u00e3o Carlos", "3548906"}; + rows[5261] = new String[] {"SP", "S\u00e3o Francisco", "3549003"}; + rows[5262] = new String[] {"SP", "S\u00e3o Jo\u00e3o da Boa Vista", "3549102"}; + rows[5263] = new String[] {"SP", "S\u00e3o Jo\u00e3o das Duas Pontes", "3549201"}; + rows[5264] = new String[] {"SP", "S\u00e3o Jo\u00e3o de Iracema", "3549250"}; + rows[5265] = new String[] {"SP", "S\u00e3o Jo\u00e3o do Pau d'Alho", "3549300"}; + rows[5266] = new String[] {"SP", "S\u00e3o Joaquim da Barra", "3549409"}; + rows[5267] = new String[] {"SP", "S\u00e3o Jos\u00e9 da Bela Vista", "3549508"}; + rows[5268] = new String[] {"SP", "S\u00e3o Jos\u00e9 do Barreiro", "3549607"}; + rows[5269] = new String[] {"SP", "S\u00e3o Jos\u00e9 do Rio Pardo", "3549706"}; + rows[5270] = new String[] {"SP", "S\u00e3o Jos\u00e9 do Rio Preto", "3549805"}; + rows[5271] = new String[] {"SP", "S\u00e3o Jos\u00e9 dos Campos", "3549904"}; + rows[5272] = new String[] {"SP", "S\u00e3o Louren\u00e7o da Serra", "3549953"}; + rows[5273] = new String[] {"SP", "S\u00e3o Luiz do Paraitinga", "3550001"}; + rows[5274] = new String[] {"SP", "S\u00e3o Manuel", "3550100"}; + rows[5275] = new String[] {"SP", "S\u00e3o Miguel Arcanjo", "3550209"}; + rows[5276] = new String[] {"SP", "S\u00e3o Paulo", "3550308"}; + rows[5277] = new String[] {"SP", "S\u00e3o Pedro", "3550407"}; + rows[5278] = new String[] {"SP", "S\u00e3o Pedro do Turvo", "3550506"}; + rows[5279] = new String[] {"SP", "S\u00e3o Roque", "3550605"}; + rows[5280] = new String[] {"SP", "S\u00e3o Sebasti\u00e3o", "3550704"}; + rows[5281] = new String[] {"SP", "S\u00e3o Sebasti\u00e3o da Grama", "3550803"}; + rows[5282] = new String[] {"SP", "S\u00e3o Sim\u00e3o", "3550902"}; + rows[5283] = new String[] {"SP", "S\u00e3o Vicente", "3551009"}; + rows[5284] = new String[] {"SP", "Sarapu\u00ed", "3551108"}; + rows[5285] = new String[] {"SP", "Sarutai\u00e1", "3551207"}; + rows[5286] = new String[] {"SP", "Sebastian\u00f3polis do Sul", "3551306"}; + rows[5287] = new String[] {"SP", "Serra Azul", "3551405"}; + rows[5288] = new String[] {"SP", "Serra Negra", "3551603"}; + rows[5289] = new String[] {"SP", "Serrana", "3551504"}; + rows[5290] = new String[] {"SP", "Sert\u00e3ozinho", "3551702"}; + rows[5291] = new String[] {"SP", "Sete Barras", "3551801"}; + rows[5292] = new String[] {"SP", "Sever\u00ednia", "3551900"}; + rows[5293] = new String[] {"SP", "Silveiras", "3552007"}; + rows[5294] = new String[] {"SP", "Socorro", "3552106"}; + rows[5295] = new String[] {"SP", "Sorocaba", "3552205"}; + rows[5296] = new String[] {"SP", "Sud Mennucci", "3552304"}; + rows[5297] = new String[] {"SP", "Sumar\u00e9", "3552403"}; + rows[5298] = new String[] {"SP", "Suzan\u00e1polis", "3552551"}; + rows[5299] = new String[] {"SP", "Suzano", "3552502"}; + rows[5300] = new String[] {"SP", "Tabapu\u00e3", "3552601"}; + rows[5301] = new String[] {"SP", "Tabatinga", "3552700"}; + rows[5302] = new String[] {"SP", "Tabo\u00e3o da Serra", "3552809"}; + rows[5303] = new String[] {"SP", "Taciba", "3552908"}; + rows[5304] = new String[] {"SP", "Tagua\u00ed", "3553005"}; + rows[5305] = new String[] {"SP", "Taia\u00e7u", "3553104"}; + rows[5306] = new String[] {"SP", "Tai\u00fava", "3553203"}; + rows[5307] = new String[] {"SP", "Tamba\u00fa", "3553302"}; + rows[5308] = new String[] {"SP", "Tanabi", "3553401"}; + rows[5309] = new String[] {"SP", "Tapira\u00ed", "3553500"}; + rows[5310] = new String[] {"SP", "Tapiratiba", "3553609"}; + rows[5311] = new String[] {"SP", "Taquaral", "3553658"}; + rows[5312] = new String[] {"SP", "Taquaritinga", "3553708"}; + rows[5313] = new String[] {"SP", "Taquarituba", "3553807"}; + rows[5314] = new String[] {"SP", "Taquariva\u00ed", "3553856"}; + rows[5315] = new String[] {"SP", "Tarabai", "3553906"}; + rows[5316] = new String[] {"SP", "Tarum\u00e3", "3553955"}; + rows[5317] = new String[] {"SP", "Tatu\u00ed", "3554003"}; + rows[5318] = new String[] {"SP", "Taubat\u00e9", "3554102"}; + rows[5319] = new String[] {"SP", "Tejup\u00e1", "3554201"}; + rows[5320] = new String[] {"SP", "Teodoro Sampaio", "3554300"}; + rows[5321] = new String[] {"SP", "Terra Roxa", "3554409"}; + rows[5322] = new String[] {"SP", "Tiet\u00ea", "3554508"}; + rows[5323] = new String[] {"SP", "Timburi", "3554607"}; + rows[5324] = new String[] {"SP", "Torre de Pedra", "3554656"}; + rows[5325] = new String[] {"SP", "Torrinha", "3554706"}; + rows[5326] = new String[] {"SP", "Trabiju", "3554755"}; + rows[5327] = new String[] {"SP", "Trememb\u00e9", "3554805"}; + rows[5328] = new String[] {"SP", "Tr\u00eas Fronteiras", "3554904"}; + rows[5329] = new String[] {"SP", "Tuiuti", "3554953"}; + rows[5330] = new String[] {"SP", "Tup\u00e3", "3555000"}; + rows[5331] = new String[] {"SP", "Tupi Paulista", "3555109"}; + rows[5332] = new String[] {"SP", "Turi\u00faba", "3555208"}; + rows[5333] = new String[] {"SP", "Turmalina", "3555307"}; + rows[5334] = new String[] {"SP", "Ubarana", "3555356"}; + rows[5335] = new String[] {"SP", "Ubatuba", "3555406"}; + rows[5336] = new String[] {"SP", "Ubirajara", "3555505"}; + rows[5337] = new String[] {"SP", "Uchoa", "3555604"}; + rows[5338] = new String[] {"SP", "Uni\u00e3o Paulista", "3555703"}; + rows[5339] = new String[] {"SP", "Ur\u00e2nia", "3555802"}; + rows[5340] = new String[] {"SP", "Uru", "3555901"}; + rows[5341] = new String[] {"SP", "Urup\u00eas", "3556008"}; + rows[5342] = new String[] {"SP", "Valentim Gentil", "3556107"}; + rows[5343] = new String[] {"SP", "Valinhos", "3556206"}; + rows[5344] = new String[] {"SP", "Valpara\u00edso", "3556305"}; + rows[5345] = new String[] {"SP", "Vargem", "3556354"}; + rows[5346] = new String[] {"SP", "Vargem Grande do Sul", "3556404"}; + rows[5347] = new String[] {"SP", "Vargem Grande Paulista", "3556453"}; + rows[5348] = new String[] {"SP", "V\u00e1rzea Paulista", "3556503"}; + rows[5349] = new String[] {"SP", "Vera Cruz", "3556602"}; + rows[5350] = new String[] {"SP", "Vinhedo", "3556701"}; + rows[5351] = new String[] {"SP", "Viradouro", "3556800"}; + rows[5352] = new String[] {"SP", "Vista Alegre do Alto", "3556909"}; + rows[5353] = new String[] {"SP", "Vit\u00f3ria Brasil", "3556958"}; + rows[5354] = new String[] {"SP", "Votorantim", "3557006"}; + rows[5355] = new String[] {"SP", "Votuporanga", "3557105"}; + rows[5356] = new String[] {"SP", "Zacarias", "3557154"}; + rows[5357] = new String[] {"SE", "Amparo do S\u00e3o Francisco", "2800100"}; + rows[5358] = new String[] {"SE", "Aquidab\u00e3", "2800209"}; + rows[5359] = new String[] {"SE", "Aracaju", "2800308"}; + rows[5360] = new String[] {"SE", "Arau\u00e1", "2800407"}; + rows[5361] = new String[] {"SE", "Areia Branca", "2800506"}; + rows[5362] = new String[] {"SE", "Barra dos Coqueiros", "2800605"}; + rows[5363] = new String[] {"SE", "Boquim", "2800670"}; + rows[5364] = new String[] {"SE", "Brejo Grande", "2800704"}; + rows[5365] = new String[] {"SE", "Campo do Brito", "2801009"}; + rows[5366] = new String[] {"SE", "Canhoba", "2801108"}; + rows[5367] = new String[] {"SE", "Canind\u00e9 de S\u00e3o Francisco", "2801207"}; + rows[5368] = new String[] {"SE", "Capela", "2801306"}; + rows[5369] = new String[] {"SE", "Carira", "2801405"}; + rows[5370] = new String[] {"SE", "Carm\u00f3polis", "2801504"}; + rows[5371] = new String[] {"SE", "Cedro de S\u00e3o Jo\u00e3o", "2801603"}; + rows[5372] = new String[] {"SE", "Cristin\u00e1polis", "2801702"}; + rows[5373] = new String[] {"SE", "Cumbe", "2801900"}; + rows[5374] = new String[] {"SE", "Divina Pastora", "2802007"}; + rows[5375] = new String[] {"SE", "Est\u00e2ncia", "2802106"}; + rows[5376] = new String[] {"SE", "Feira Nova", "2802205"}; + rows[5377] = new String[] {"SE", "Frei Paulo", "2802304"}; + rows[5378] = new String[] {"SE", "Gararu", "2802403"}; + rows[5379] = new String[] {"SE", "General Maynard", "2802502"}; + rows[5380] = new String[] {"SE", "Graccho Cardoso", "2802601"}; + rows[5381] = new String[] {"SE", "Ilha das Flores", "2802700"}; + rows[5382] = new String[] {"SE", "Indiaroba", "2802809"}; + rows[5383] = new String[] {"SE", "Itabaiana", "2802908"}; + rows[5384] = new String[] {"SE", "Itabaianinha", "2803005"}; + rows[5385] = new String[] {"SE", "Itabi", "2803104"}; + rows[5386] = new String[] {"SE", "Itaporanga d'Ajuda", "2803203"}; + rows[5387] = new String[] {"SE", "Japaratuba", "2803302"}; + rows[5388] = new String[] {"SE", "Japoat\u00e3", "2803401"}; + rows[5389] = new String[] {"SE", "Lagarto", "2803500"}; + rows[5390] = new String[] {"SE", "Laranjeiras", "2803609"}; + rows[5391] = new String[] {"SE", "Macambira", "2803708"}; + rows[5392] = new String[] {"SE", "Malhada dos Bois", "2803807"}; + rows[5393] = new String[] {"SE", "Malhador", "2803906"}; + rows[5394] = new String[] {"SE", "Maruim", "2804003"}; + rows[5395] = new String[] {"SE", "Moita Bonita", "2804102"}; + rows[5396] = new String[] {"SE", "Monte Alegre de Sergipe", "2804201"}; + rows[5397] = new String[] {"SE", "Muribeca", "2804300"}; + rows[5398] = new String[] {"SE", "Ne\u00f3polis", "2804409"}; + rows[5399] = new String[] {"SE", "Nossa Senhora Aparecida", "2804458"}; + } + + private static void municipalitiesRows27(String[][] rows) { + rows[5400] = new String[] {"SE", "Nossa Senhora da Gl\u00f3ria", "2804508"}; + rows[5401] = new String[] {"SE", "Nossa Senhora das Dores", "2804607"}; + rows[5402] = new String[] {"SE", "Nossa Senhora de Lourdes", "2804706"}; + rows[5403] = new String[] {"SE", "Nossa Senhora do Socorro", "2804805"}; + rows[5404] = new String[] {"SE", "Pacatuba", "2804904"}; + rows[5405] = new String[] {"SE", "Pedra Mole", "2805000"}; + rows[5406] = new String[] {"SE", "Pedrinhas", "2805109"}; + rows[5407] = new String[] {"SE", "Pinh\u00e3o", "2805208"}; + rows[5408] = new String[] {"SE", "Pirambu", "2805307"}; + rows[5409] = new String[] {"SE", "Po\u00e7o Redondo", "2805406"}; + rows[5410] = new String[] {"SE", "Po\u00e7o Verde", "2805505"}; + rows[5411] = new String[] {"SE", "Porto da Folha", "2805604"}; + rows[5412] = new String[] {"SE", "Propri\u00e1", "2805703"}; + rows[5413] = new String[] {"SE", "Riach\u00e3o do Dantas", "2805802"}; + rows[5414] = new String[] {"SE", "Riachuelo", "2805901"}; + rows[5415] = new String[] {"SE", "Ribeir\u00f3polis", "2806008"}; + rows[5416] = new String[] {"SE", "Ros\u00e1rio do Catete", "2806107"}; + rows[5417] = new String[] {"SE", "Salgado", "2806206"}; + rows[5418] = new String[] {"SE", "Santa Luzia do Itanhy", "2806305"}; + rows[5419] = new String[] {"SE", "Santa Rosa de Lima", "2806503"}; + rows[5420] = new String[] {"SE", "Santana do S\u00e3o Francisco", "2806404"}; + rows[5421] = new String[] {"SE", "Santo Amaro das Brotas", "2806602"}; + rows[5422] = new String[] {"SE", "S\u00e3o Crist\u00f3v\u00e3o", "2806701"}; + rows[5423] = new String[] {"SE", "S\u00e3o Domingos", "2806800"}; + rows[5424] = new String[] {"SE", "S\u00e3o Francisco", "2806909"}; + rows[5425] = new String[] {"SE", "S\u00e3o Miguel do Aleixo", "2807006"}; + rows[5426] = new String[] {"SE", "Sim\u00e3o Dias", "2807105"}; + rows[5427] = new String[] {"SE", "Siriri", "2807204"}; + rows[5428] = new String[] {"SE", "Telha", "2807303"}; + rows[5429] = new String[] {"SE", "Tobias Barreto", "2807402"}; + rows[5430] = new String[] {"SE", "Tomar do Geru", "2807501"}; + rows[5431] = new String[] {"SE", "Umba\u00faba", "2807600"}; + rows[5432] = new String[] {"TO", "Abreul\u00e2ndia", "1700251"}; + rows[5433] = new String[] {"TO", "Aguiarn\u00f3polis", "1700301"}; + rows[5434] = new String[] {"TO", "Alian\u00e7a do Tocantins", "1700350"}; + rows[5435] = new String[] {"TO", "Almas", "1700400"}; + rows[5436] = new String[] {"TO", "Alvorada", "1700707"}; + rows[5437] = new String[] {"TO", "Anan\u00e1s", "1701002"}; + rows[5438] = new String[] {"TO", "Angico", "1701051"}; + rows[5439] = new String[] {"TO", "Aparecida do Rio Negro", "1701101"}; + rows[5440] = new String[] {"TO", "Aragominas", "1701309"}; + rows[5441] = new String[] {"TO", "Araguacema", "1701903"}; + rows[5442] = new String[] {"TO", "Aragua\u00e7u", "1702000"}; + rows[5443] = new String[] {"TO", "Aragua\u00edna", "1702109"}; + rows[5444] = new String[] {"TO", "Araguan\u00e3", "1702158"}; + rows[5445] = new String[] {"TO", "Araguatins", "1702208"}; + rows[5446] = new String[] {"TO", "Arapoema", "1702307"}; + rows[5447] = new String[] {"TO", "Arraias", "1702406"}; + rows[5448] = new String[] {"TO", "Augustin\u00f3polis", "1702554"}; + rows[5449] = new String[] {"TO", "Aurora do Tocantins", "1702703"}; + rows[5450] = new String[] {"TO", "Axix\u00e1 do Tocantins", "1702901"}; + rows[5451] = new String[] {"TO", "Baba\u00e7ul\u00e2ndia", "1703008"}; + rows[5452] = new String[] {"TO", "Bandeirantes do Tocantins", "1703057"}; + rows[5453] = new String[] {"TO", "Barra do Ouro", "1703073"}; + rows[5454] = new String[] {"TO", "Barrol\u00e2ndia", "1703107"}; + rows[5455] = new String[] {"TO", "Bernardo Say\u00e3o", "1703206"}; + rows[5456] = new String[] {"TO", "Bom Jesus do Tocantins", "1703305"}; + rows[5457] = new String[] {"TO", "Brasil\u00e2ndia do Tocantins", "1703602"}; + rows[5458] = new String[] {"TO", "Brejinho de Nazar\u00e9", "1703701"}; + rows[5459] = new String[] {"TO", "Buriti do Tocantins", "1703800"}; + rows[5460] = new String[] {"TO", "Cachoeirinha", "1703826"}; + rows[5461] = new String[] {"TO", "Campos Lindos", "1703842"}; + rows[5462] = new String[] {"TO", "Cariri do Tocantins", "1703867"}; + rows[5463] = new String[] {"TO", "Carmol\u00e2ndia", "1703883"}; + rows[5464] = new String[] {"TO", "Carrasco Bonito", "1703891"}; + rows[5465] = new String[] {"TO", "Caseara", "1703909"}; + rows[5466] = new String[] {"TO", "Centen\u00e1rio", "1704105"}; + rows[5467] = new String[] {"TO", "Chapada da Natividade", "1705102"}; + rows[5468] = new String[] {"TO", "Chapada de Areia", "1704600"}; + rows[5469] = new String[] {"TO", "Colinas do Tocantins", "1705508"}; + rows[5470] = new String[] {"TO", "Colm\u00e9ia", "1716703"}; + rows[5471] = new String[] {"TO", "Combinado", "1705557"}; + rows[5472] = new String[] {"TO", "Concei\u00e7\u00e3o do Tocantins", "1705607"}; + rows[5473] = new String[] {"TO", "Couto Magalh\u00e3es", "1706001"}; + rows[5474] = new String[] {"TO", "Cristal\u00e2ndia", "1706100"}; + rows[5475] = new String[] {"TO", "Crix\u00e1s do Tocantins", "1706258"}; + rows[5476] = new String[] {"TO", "Darcin\u00f3polis", "1706506"}; + rows[5477] = new String[] {"TO", "Dian\u00f3polis", "1707009"}; + rows[5478] = new String[] {"TO", "Divin\u00f3polis do Tocantins", "1707108"}; + rows[5479] = new String[] {"TO", "Dois Irm\u00e3os do Tocantins", "1707207"}; + rows[5480] = new String[] {"TO", "Duer\u00e9", "1707306"}; + rows[5481] = new String[] {"TO", "Esperantina", "1707405"}; + rows[5482] = new String[] {"TO", "F\u00e1tima", "1707553"}; + rows[5483] = new String[] {"TO", "Figueir\u00f3polis", "1707652"}; + rows[5484] = new String[] {"TO", "Filad\u00e9lfia", "1707702"}; + rows[5485] = new String[] {"TO", "Formoso do Araguaia", "1708205"}; + rows[5486] = new String[] {"TO", "Goianorte", "1708304"}; + rows[5487] = new String[] {"TO", "Goiatins", "1709005"}; + rows[5488] = new String[] {"TO", "Guara\u00ed", "1709302"}; + rows[5489] = new String[] {"TO", "Gurupi", "1709500"}; + rows[5490] = new String[] {"TO", "Ipueiras", "1709807"}; + rows[5491] = new String[] {"TO", "Itacaj\u00e1", "1710508"}; + rows[5492] = new String[] {"TO", "Itaguatins", "1710706"}; + rows[5493] = new String[] {"TO", "Itapiratins", "1710904"}; + rows[5494] = new String[] {"TO", "Itapor\u00e3 do Tocantins", "1711100"}; + rows[5495] = new String[] {"TO", "Ja\u00fa do Tocantins", "1711506"}; + rows[5496] = new String[] {"TO", "Juarina", "1711803"}; + rows[5497] = new String[] {"TO", "Lagoa da Confus\u00e3o", "1711902"}; + rows[5498] = new String[] {"TO", "Lagoa do Tocantins", "1711951"}; + rows[5499] = new String[] {"TO", "Lajeado", "1712009"}; + rows[5500] = new String[] {"TO", "Lavandeira", "1712157"}; + rows[5501] = new String[] {"TO", "Lizarda", "1712405"}; + rows[5502] = new String[] {"TO", "Luzin\u00f3polis", "1712454"}; + rows[5503] = new String[] {"TO", "Marian\u00f3polis do Tocantins", "1712504"}; + rows[5504] = new String[] {"TO", "Mateiros", "1712702"}; + rows[5505] = new String[] {"TO", "Mauril\u00e2ndia do Tocantins", "1712801"}; + rows[5506] = new String[] {"TO", "Miracema do Tocantins", "1713205"}; + rows[5507] = new String[] {"TO", "Miranorte", "1713304"}; + rows[5508] = new String[] {"TO", "Monte do Carmo", "1713601"}; + rows[5509] = new String[] {"TO", "Monte Santo do Tocantins", "1713700"}; + rows[5510] = new String[] {"TO", "Muricil\u00e2ndia", "1713957"}; + rows[5511] = new String[] {"TO", "Natividade", "1714203"}; + rows[5512] = new String[] {"TO", "Nazar\u00e9", "1714302"}; + rows[5513] = new String[] {"TO", "Nova Olinda", "1714880"}; + rows[5514] = new String[] {"TO", "Nova Rosal\u00e2ndia", "1715002"}; + rows[5515] = new String[] {"TO", "Novo Acordo", "1715101"}; + rows[5516] = new String[] {"TO", "Novo Alegre", "1715150"}; + rows[5517] = new String[] {"TO", "Novo Jardim", "1715259"}; + rows[5518] = new String[] {"TO", "Oliveira de F\u00e1tima", "1715507"}; + rows[5519] = new String[] {"TO", "Palmas", "1721000"}; + rows[5520] = new String[] {"TO", "Palmeirante", "1715705"}; + rows[5521] = new String[] {"TO", "Palmeiras do Tocantins", "1713809"}; + rows[5522] = new String[] {"TO", "Palmeir\u00f3polis", "1715754"}; + rows[5523] = new String[] {"TO", "Para\u00edso do Tocantins", "1716109"}; + rows[5524] = new String[] {"TO", "Paran\u00e3", "1716208"}; + rows[5525] = new String[] {"TO", "Pau D'Arco", "1716307"}; + rows[5526] = new String[] {"TO", "Pedro Afonso", "1716505"}; + rows[5527] = new String[] {"TO", "Peixe", "1716604"}; + rows[5528] = new String[] {"TO", "Pequizeiro", "1716653"}; + rows[5529] = new String[] {"TO", "Pindorama do Tocantins", "1717008"}; + rows[5530] = new String[] {"TO", "Piraqu\u00ea", "1717206"}; + rows[5531] = new String[] {"TO", "Pium", "1717503"}; + rows[5532] = new String[] {"TO", "Ponte Alta do Bom Jesus", "1717800"}; + rows[5533] = new String[] {"TO", "Ponte Alta do Tocantins", "1717909"}; + rows[5534] = new String[] {"TO", "Porto Alegre do Tocantins", "1718006"}; + rows[5535] = new String[] {"TO", "Porto Nacional", "1718204"}; + rows[5536] = new String[] {"TO", "Praia Norte", "1718303"}; + rows[5537] = new String[] {"TO", "Presidente Kennedy", "1718402"}; + rows[5538] = new String[] {"TO", "Pugmil", "1718451"}; + rows[5539] = new String[] {"TO", "Recursol\u00e2ndia", "1718501"}; + rows[5540] = new String[] {"TO", "Riachinho", "1718550"}; + rows[5541] = new String[] {"TO", "Rio da Concei\u00e7\u00e3o", "1718659"}; + rows[5542] = new String[] {"TO", "Rio dos Bois", "1718709"}; + rows[5543] = new String[] {"TO", "Rio Sono", "1718758"}; + rows[5544] = new String[] {"TO", "Sampaio", "1718808"}; + rows[5545] = new String[] {"TO", "Sandol\u00e2ndia", "1718840"}; + rows[5546] = new String[] {"TO", "Santa F\u00e9 do Araguaia", "1718865"}; + rows[5547] = new String[] {"TO", "Santa Maria do Tocantins", "1718881"}; + rows[5548] = new String[] {"TO", "Santa Rita do Tocantins", "1718899"}; + rows[5549] = new String[] {"TO", "Santa Rosa do Tocantins", "1718907"}; + rows[5550] = new String[] {"TO", "Santa Tereza do Tocantins", "1719004"}; + rows[5551] = new String[] {"TO", "Santa Terezinha do Tocantins", "1720002"}; + rows[5552] = new String[] {"TO", "S\u00e3o Bento do Tocantins", "1720101"}; + rows[5553] = new String[] {"TO", "S\u00e3o F\u00e9lix do Tocantins", "1720150"}; + rows[5554] = new String[] {"TO", "S\u00e3o Miguel do Tocantins", "1720200"}; + rows[5555] = new String[] {"TO", "S\u00e3o Salvador do Tocantins", "1720259"}; + rows[5556] = new String[] {"TO", "S\u00e3o Sebasti\u00e3o do Tocantins", "1720309"}; + rows[5557] = new String[] {"TO", "S\u00e3o Val\u00e9rio", "1720499"}; + rows[5558] = new String[] {"TO", "Silvan\u00f3polis", "1720655"}; + rows[5559] = new String[] {"TO", "S\u00edtio Novo do Tocantins", "1720804"}; + rows[5560] = new String[] {"TO", "Sucupira", "1720853"}; + rows[5561] = new String[] {"TO", "Taboc\u00e3o", "1708254"}; + rows[5562] = new String[] {"TO", "Taguatinga", "1720903"}; + rows[5563] = new String[] {"TO", "Taipas do Tocantins", "1720937"}; + rows[5564] = new String[] {"TO", "Talism\u00e3", "1720978"}; + rows[5565] = new String[] {"TO", "Tocant\u00ednia", "1721109"}; + rows[5566] = new String[] {"TO", "Tocantin\u00f3polis", "1721208"}; + rows[5567] = new String[] {"TO", "Tupirama", "1721257"}; + rows[5568] = new String[] {"TO", "Tupiratins", "1721307"}; + rows[5569] = new String[] {"TO", "Wanderl\u00e2ndia", "1722081"}; + rows[5570] = new String[] {"TO", "Xambio\u00e1", "1722107"}; + } + + private static int[][] municipalitiesGroups() { + int[][] groups = new int[27][]; + municipalitiesGroups0(groups); + municipalitiesGroups1(groups); + municipalitiesGroups2(groups); + municipalitiesGroups3(groups); + municipalitiesGroups4(groups); + municipalitiesGroups5(groups); + return groups; + } + + private static void municipalitiesGroups0(int[][] groups) { + groups[0] = new int[] {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21}; + groups[1] = new int[] {22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123}; + groups[2] = new int[] {124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139}; + groups[3] = new int[] {140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201}; + groups[4] = new int[] {202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, 443, 444, 445, 446, 447, 448, 449, 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, 495, 496, 497, 498, 499, 500, 501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, 519, 520, 521, 522, 523, 524, 525, 526, 527, 528, 529, 530, 531, 532, 533, 534, 535, 536, 537, 538, 539, 540, 541, 542, 543, 544, 545, 546, 547, 548, 549, 550, 551, 552, 553, 554, 555, 556, 557, 558, 559, 560, 561, 562, 563, 564, 565, 566, 567, 568, 569, 570, 571, 572, 573, 574, 575, 576, 577, 578, 579, 580, 581, 582, 583, 584, 585, 586, 587, 588, 589, 590, 591, 592, 593, 594, 595, 596, 597, 598, 599, 600, 601, 602, 603, 604, 605, 606, 607, 608, 609, 610, 611, 612, 613, 614, 615, 616, 617, 618}; + } + + private static void municipalitiesGroups1(int[][] groups) { + groups[5] = new int[] {619, 620, 621, 622, 623, 624, 625, 626, 627, 628, 629, 630, 631, 632, 633, 634, 635, 636, 637, 638, 639, 640, 641, 642, 643, 644, 645, 646, 647, 648, 649, 650, 651, 652, 653, 654, 655, 656, 657, 658, 659, 660, 661, 662, 663, 664, 665, 666, 667, 668, 669, 670, 671, 672, 673, 674, 675, 676, 677, 678, 679, 680, 681, 682, 683, 684, 685, 686, 687, 688, 689, 690, 691, 692, 693, 694, 695, 696, 697, 698, 699, 700, 701, 702, 703, 704, 705, 706, 707, 708, 709, 710, 711, 712, 713, 714, 715, 716, 717, 718, 719, 720, 721, 722, 723, 724, 725, 726, 727, 728, 729, 730, 731, 732, 733, 734, 735, 736, 737, 738, 739, 740, 741, 742, 743, 744, 745, 746, 747, 748, 749, 750, 751, 752, 753, 754, 755, 756, 757, 758, 759, 760, 761, 762, 763, 764, 765, 766, 767, 768, 769, 770, 771, 772, 773, 774, 775, 776, 777, 778, 779, 780, 781, 782, 783, 784, 785, 786, 787, 788, 789, 790, 791, 792, 793, 794, 795, 796, 797, 798, 799, 800, 801, 802}; + groups[6] = new int[] {803}; + groups[7] = new int[] {804, 805, 806, 807, 808, 809, 810, 811, 812, 813, 814, 815, 816, 817, 818, 819, 820, 821, 822, 823, 824, 825, 826, 827, 828, 829, 830, 831, 832, 833, 834, 835, 836, 837, 838, 839, 840, 841, 842, 843, 844, 845, 846, 847, 848, 849, 850, 851, 852, 853, 854, 855, 856, 857, 858, 859, 860, 861, 862, 863, 864, 865, 866, 867, 868, 869, 870, 871, 872, 873, 874, 875, 876, 877, 878, 879, 880, 881}; + groups[8] = new int[] {882, 883, 884, 885, 886, 887, 888, 889, 890, 891, 892, 893, 894, 895, 896, 897, 898, 899, 900, 901, 902, 903, 904, 905, 906, 907, 908, 909, 910, 911, 912, 913, 914, 915, 916, 917, 918, 919, 920, 921, 922, 923, 924, 925, 926, 927, 928, 929, 930, 931, 932, 933, 934, 935, 936, 937, 938, 939, 940, 941, 942, 943, 944, 945, 946, 947, 948, 949, 950, 951, 952, 953, 954, 955, 956, 957, 958, 959, 960, 961, 962, 963, 964, 965, 966, 967, 968, 969, 970, 971, 972, 973, 974, 975, 976, 977, 978, 979, 980, 981, 982, 983, 984, 985, 986, 987, 988, 989, 990, 991, 992, 993, 994, 995, 996, 997, 998, 999, 1000, 1001, 1002, 1003, 1004, 1005, 1006, 1007, 1008, 1009, 1010, 1011, 1012, 1013, 1014, 1015, 1016, 1017, 1018, 1019, 1020, 1021, 1022, 1023, 1024, 1025, 1026, 1027, 1028, 1029, 1030, 1031, 1032, 1033, 1034, 1035, 1036, 1037, 1038, 1039, 1040, 1041, 1042, 1043, 1044, 1045, 1046, 1047, 1048, 1049, 1050, 1051, 1052, 1053, 1054, 1055, 1056, 1057, 1058, 1059, 1060, 1061, 1062, 1063, 1064, 1065, 1066, 1067, 1068, 1069, 1070, 1071, 1072, 1073, 1074, 1075, 1076, 1077, 1078, 1079, 1080, 1081, 1082, 1083, 1084, 1085, 1086, 1087, 1088, 1089, 1090, 1091, 1092, 1093, 1094, 1095, 1096, 1097, 1098, 1099, 1100, 1101, 1102, 1103, 1104, 1105, 1106, 1107, 1108, 1109, 1110, 1111, 1112, 1113, 1114, 1115, 1116, 1117, 1118, 1119, 1120, 1121, 1122, 1123, 1124, 1125, 1126, 1127}; + groups[9] = new int[] {1128, 1129, 1130, 1131, 1132, 1133, 1134, 1135, 1136, 1137, 1138, 1139, 1140, 1141, 1142, 1143, 1144, 1145, 1146, 1147, 1148, 1149, 1150, 1151, 1152, 1153, 1154, 1155, 1156, 1157, 1158, 1159, 1160, 1161, 1162, 1163, 1164, 1165, 1166, 1167, 1168, 1169, 1170, 1171, 1172, 1173, 1174, 1175, 1176, 1177, 1178, 1179, 1180, 1181, 1182, 1183, 1184, 1185, 1186, 1187, 1188, 1189, 1190, 1191, 1192, 1193, 1194, 1195, 1196, 1197, 1198, 1199, 1200, 1201, 1202, 1203, 1204, 1205, 1206, 1207, 1208, 1209, 1210, 1211, 1212, 1213, 1214, 1215, 1216, 1217, 1218, 1219, 1220, 1221, 1222, 1223, 1224, 1225, 1226, 1227, 1228, 1229, 1230, 1231, 1232, 1233, 1234, 1235, 1236, 1237, 1238, 1239, 1240, 1241, 1242, 1243, 1244, 1245, 1246, 1247, 1248, 1249, 1250, 1251, 1252, 1253, 1254, 1255, 1256, 1257, 1258, 1259, 1260, 1261, 1262, 1263, 1264, 1265, 1266, 1267, 1268, 1269, 1270, 1271, 1272, 1273, 1274, 1275, 1276, 1277, 1278, 1279, 1280, 1281, 1282, 1283, 1284, 1285, 1286, 1287, 1288, 1289, 1290, 1291, 1292, 1293, 1294, 1295, 1296, 1297, 1298, 1299, 1300, 1301, 1302, 1303, 1304, 1305, 1306, 1307, 1308, 1309, 1310, 1311, 1312, 1313, 1314, 1315, 1316, 1317, 1318, 1319, 1320, 1321, 1322, 1323, 1324, 1325, 1326, 1327, 1328, 1329, 1330, 1331, 1332, 1333, 1334, 1335, 1336, 1337, 1338, 1339, 1340, 1341, 1342, 1343, 1344}; + } + + private static void municipalitiesGroups2(int[][] groups) { + groups[10] = new int[] {1345, 1346, 1347, 1348, 1349, 1350, 1351, 1352, 1353, 1354, 1355, 1356, 1357, 1358, 1359, 1360, 1361, 1362, 1363, 1364, 1365, 1366, 1367, 1368, 1369, 1370, 1371, 1372, 1373, 1374, 1375, 1376, 1377, 1378, 1379, 1380, 1381, 1382, 1383, 1384, 1385, 1386, 1387, 1388, 1389, 1390, 1391, 1392, 1393, 1394, 1395, 1396, 1397, 1398, 1399, 1400, 1401, 1402, 1403, 1404, 1405, 1406, 1407, 1408, 1409, 1410, 1411, 1412, 1413, 1414, 1415, 1416, 1417, 1418, 1419, 1420, 1421, 1422, 1423, 1424, 1425, 1426, 1427, 1428, 1429, 1430, 1431, 1432, 1433, 1434, 1435, 1436, 1437, 1438, 1439, 1440, 1441, 1442, 1443, 1444, 1445, 1446, 1447, 1448, 1449, 1450, 1451, 1452, 1453, 1454, 1455, 1456, 1457, 1458, 1459, 1460, 1461, 1462, 1463, 1464, 1465, 1466, 1467, 1468, 1469, 1470, 1471, 1472, 1473, 1474, 1475, 1476, 1477, 1478, 1479, 1480, 1481, 1482, 1483, 1484, 1485, 1486}; + groups[11] = new int[] {1487, 1488, 1489, 1490, 1491, 1492, 1493, 1494, 1495, 1496, 1497, 1498, 1499, 1500, 1501, 1502, 1503, 1504, 1505, 1506, 1507, 1508, 1509, 1510, 1511, 1512, 1513, 1514, 1515, 1516, 1517, 1518, 1519, 1520, 1521, 1522, 1523, 1524, 1525, 1526, 1527, 1528, 1529, 1530, 1531, 1532, 1533, 1534, 1535, 1536, 1537, 1538, 1539, 1540, 1541, 1542, 1543, 1544, 1545, 1546, 1547, 1548, 1549, 1550, 1551, 1552, 1553, 1554, 1555, 1556, 1557, 1558, 1559, 1560, 1561, 1562, 1563, 1564, 1565}; + groups[12] = new int[] {1566, 1567, 1568, 1569, 1570, 1571, 1572, 1573, 1574, 1575, 1576, 1577, 1578, 1579, 1580, 1581, 1582, 1583, 1584, 1585, 1586, 1587, 1588, 1589, 1590, 1591, 1592, 1593, 1594, 1595, 1596, 1597, 1598, 1599, 1600, 1601, 1602, 1603, 1604, 1605, 1606, 1607, 1608, 1609, 1610, 1611, 1612, 1613, 1614, 1615, 1616, 1617, 1618, 1619, 1620, 1621, 1622, 1623, 1624, 1625, 1626, 1627, 1628, 1629, 1630, 1631, 1632, 1633, 1634, 1635, 1636, 1637, 1638, 1639, 1640, 1641, 1642, 1643, 1644, 1645, 1646, 1647, 1648, 1649, 1650, 1651, 1652, 1653, 1654, 1655, 1656, 1657, 1658, 1659, 1660, 1661, 1662, 1663, 1664, 1665, 1666, 1667, 1668, 1669, 1670, 1671, 1672, 1673, 1674, 1675, 1676, 1677, 1678, 1679, 1680, 1681, 1682, 1683, 1684, 1685, 1686, 1687, 1688, 1689, 1690, 1691, 1692, 1693, 1694, 1695, 1696, 1697, 1698, 1699, 1700, 1701, 1702, 1703, 1704, 1705, 1706, 1707, 1708, 1709, 1710, 1711, 1712, 1713, 1714, 1715, 1716, 1717, 1718, 1719, 1720, 1721, 1722, 1723, 1724, 1725, 1726, 1727, 1728, 1729, 1730, 1731, 1732, 1733, 1734, 1735, 1736, 1737, 1738, 1739, 1740, 1741, 1742, 1743, 1744, 1745, 1746, 1747, 1748, 1749, 1750, 1751, 1752, 1753, 1754, 1755, 1756, 1757, 1758, 1759, 1760, 1761, 1762, 1763, 1764, 1765, 1766, 1767, 1768, 1769, 1770, 1771, 1772, 1773, 1774, 1775, 1776, 1777, 1778, 1779, 1780, 1781, 1782, 1783, 1784, 1785, 1786, 1787, 1788, 1789, 1790, 1791, 1792, 1793, 1794, 1795, 1796, 1797, 1798, 1799, 1800, 1801, 1802, 1803, 1804, 1805, 1806, 1807, 1808, 1809, 1810, 1811, 1812, 1813, 1814, 1815, 1816, 1817, 1818, 1819, 1820, 1821, 1822, 1823, 1824, 1825, 1826, 1827, 1828, 1829, 1830, 1831, 1832, 1833, 1834, 1835, 1836, 1837, 1838, 1839, 1840, 1841, 1842, 1843, 1844, 1845, 1846, 1847, 1848, 1849, 1850, 1851, 1852, 1853, 1854, 1855, 1856, 1857, 1858, 1859, 1860, 1861, 1862, 1863, 1864, 1865, 1866, 1867, 1868, 1869, 1870, 1871, 1872, 1873, 1874, 1875, 1876, 1877, 1878, 1879, 1880, 1881, 1882, 1883, 1884, 1885, 1886, 1887, 1888, 1889, 1890, 1891, 1892, 1893, 1894, 1895, 1896, 1897, 1898, 1899, 1900, 1901, 1902, 1903, 1904, 1905, 1906, 1907, 1908, 1909, 1910, 1911, 1912, 1913, 1914, 1915, 1916, 1917, 1918, 1919, 1920, 1921, 1922, 1923, 1924, 1925, 1926, 1927, 1928, 1929, 1930, 1931, 1932, 1933, 1934, 1935, 1936, 1937, 1938, 1939, 1940, 1941, 1942, 1943, 1944, 1945, 1946, 1947, 1948, 1949, 1950, 1951, 1952, 1953, 1954, 1955, 1956, 1957, 1958, 1959, 1960, 1961, 1962, 1963, 1964, 1965, 1966, 1967, 1968, 1969, 1970, 1971, 1972, 1973, 1974, 1975, 1976, 1977, 1978, 1979, 1980, 1981, 1982, 1983, 1984, 1985, 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020, 2021, 2022, 2023, 2024, 2025, 2026, 2027, 2028, 2029, 2030, 2031, 2032, 2033, 2034, 2035, 2036, 2037, 2038, 2039, 2040, 2041, 2042, 2043, 2044, 2045, 2046, 2047, 2048, 2049, 2050, 2051, 2052, 2053, 2054, 2055, 2056, 2057, 2058, 2059, 2060, 2061, 2062, 2063, 2064, 2065, 2066, 2067, 2068, 2069, 2070, 2071, 2072, 2073, 2074, 2075, 2076, 2077, 2078, 2079, 2080, 2081, 2082, 2083, 2084, 2085, 2086, 2087, 2088, 2089, 2090, 2091, 2092, 2093, 2094, 2095, 2096, 2097, 2098, 2099, 2100, 2101, 2102, 2103, 2104, 2105, 2106, 2107, 2108, 2109, 2110, 2111, 2112, 2113, 2114, 2115, 2116, 2117, 2118, 2119, 2120, 2121, 2122, 2123, 2124, 2125, 2126, 2127, 2128, 2129, 2130, 2131, 2132, 2133, 2134, 2135, 2136, 2137, 2138, 2139, 2140, 2141, 2142, 2143, 2144, 2145, 2146, 2147, 2148, 2149, 2150, 2151, 2152, 2153, 2154, 2155, 2156, 2157, 2158, 2159, 2160, 2161, 2162, 2163, 2164, 2165, 2166, 2167, 2168, 2169, 2170, 2171, 2172, 2173, 2174, 2175, 2176, 2177, 2178, 2179, 2180, 2181, 2182, 2183, 2184, 2185, 2186, 2187, 2188, 2189, 2190, 2191, 2192, 2193, 2194, 2195, 2196, 2197, 2198, 2199, 2200, 2201, 2202, 2203, 2204, 2205, 2206, 2207, 2208, 2209, 2210, 2211, 2212, 2213, 2214, 2215, 2216, 2217, 2218, 2219, 2220, 2221, 2222, 2223, 2224, 2225, 2226, 2227, 2228, 2229, 2230, 2231, 2232, 2233, 2234, 2235, 2236, 2237, 2238, 2239, 2240, 2241, 2242, 2243, 2244, 2245, 2246, 2247, 2248, 2249, 2250, 2251, 2252, 2253, 2254, 2255, 2256, 2257, 2258, 2259, 2260, 2261, 2262, 2263, 2264, 2265, 2266, 2267, 2268, 2269, 2270, 2271, 2272, 2273, 2274, 2275, 2276, 2277, 2278, 2279, 2280, 2281, 2282, 2283, 2284, 2285, 2286, 2287, 2288, 2289, 2290, 2291, 2292, 2293, 2294, 2295, 2296, 2297, 2298, 2299, 2300, 2301, 2302, 2303, 2304, 2305, 2306, 2307, 2308, 2309, 2310, 2311, 2312, 2313, 2314, 2315, 2316, 2317, 2318, 2319, 2320, 2321, 2322, 2323, 2324, 2325, 2326, 2327, 2328, 2329, 2330, 2331, 2332, 2333, 2334, 2335, 2336, 2337, 2338, 2339, 2340, 2341, 2342, 2343, 2344, 2345, 2346, 2347, 2348, 2349, 2350, 2351, 2352, 2353, 2354, 2355, 2356, 2357, 2358, 2359, 2360, 2361, 2362, 2363, 2364, 2365, 2366, 2367, 2368, 2369, 2370, 2371, 2372, 2373, 2374, 2375, 2376, 2377, 2378, 2379, 2380, 2381, 2382, 2383, 2384, 2385, 2386, 2387, 2388, 2389, 2390, 2391, 2392, 2393, 2394, 2395, 2396, 2397, 2398, 2399, 2400, 2401, 2402, 2403, 2404, 2405, 2406, 2407, 2408, 2409, 2410, 2411, 2412, 2413, 2414, 2415, 2416, 2417, 2418}; + groups[13] = new int[] {2419, 2420, 2421, 2422, 2423, 2424, 2425, 2426, 2427, 2428, 2429, 2430, 2431, 2432, 2433, 2434, 2435, 2436, 2437, 2438, 2439, 2440, 2441, 2442, 2443, 2444, 2445, 2446, 2447, 2448, 2449, 2450, 2451, 2452, 2453, 2454, 2455, 2456, 2457, 2458, 2459, 2460, 2461, 2462, 2463, 2464, 2465, 2466, 2467, 2468, 2469, 2470, 2471, 2472, 2473, 2474, 2475, 2476, 2477, 2478, 2479, 2480, 2481, 2482, 2483, 2484, 2485, 2486, 2487, 2488, 2489, 2490, 2491, 2492, 2493, 2494, 2495, 2496, 2497, 2498, 2499, 2500, 2501, 2502, 2503, 2504, 2505, 2506, 2507, 2508, 2509, 2510, 2511, 2512, 2513, 2514, 2515, 2516, 2517, 2518, 2519, 2520, 2521, 2522, 2523, 2524, 2525, 2526, 2527, 2528, 2529, 2530, 2531, 2532, 2533, 2534, 2535, 2536, 2537, 2538, 2539, 2540, 2541, 2542, 2543, 2544, 2545, 2546, 2547, 2548, 2549, 2550, 2551, 2552, 2553, 2554, 2555, 2556, 2557, 2558, 2559, 2560, 2561, 2562}; + groups[14] = new int[] {2563, 2564, 2565, 2566, 2567, 2568, 2569, 2570, 2571, 2572, 2573, 2574, 2575, 2576, 2577, 2578, 2579, 2580, 2581, 2582, 2583, 2584, 2585, 2586, 2587, 2588, 2589, 2590, 2591, 2592, 2593, 2594, 2595, 2596, 2597, 2598, 2599, 2600, 2601, 2602, 2603, 2604, 2605, 2606, 2607, 2608, 2609, 2610, 2611, 2612, 2613, 2614, 2615, 2616, 2617, 2618, 2619, 2620, 2621, 2622, 2623, 2624, 2625, 2626, 2627, 2628, 2629, 2630, 2631, 2632, 2633, 2634, 2635, 2636, 2637, 2638, 2639, 2640, 2641, 2642, 2643, 2644, 2645, 2646, 2647, 2648, 2649, 2650, 2651, 2652, 2653, 2654, 2655, 2656, 2657, 2658, 2659, 2660, 2661, 2662, 2663, 2664, 2665, 2666, 2667, 2668, 2669, 2670, 2671, 2672, 2673, 2674, 2675, 2676, 2677, 2678, 2679, 2680, 2681, 2682, 2683, 2684, 2685, 2686, 2687, 2688, 2689, 2690, 2691, 2692, 2693, 2694, 2695, 2696, 2697, 2698, 2699, 2700, 2701, 2702, 2703, 2704, 2705, 2706, 2707, 2708, 2709, 2710, 2711, 2712, 2713, 2714, 2715, 2716, 2717, 2718, 2719, 2720, 2721, 2722, 2723, 2724, 2725, 2726, 2727, 2728, 2729, 2730, 2731, 2732, 2733, 2734, 2735, 2736, 2737, 2738, 2739, 2740, 2741, 2742, 2743, 2744, 2745, 2746, 2747, 2748, 2749, 2750, 2751, 2752, 2753, 2754, 2755, 2756, 2757, 2758, 2759, 2760, 2761, 2762, 2763, 2764, 2765, 2766, 2767, 2768, 2769, 2770, 2771, 2772, 2773, 2774, 2775, 2776, 2777, 2778, 2779, 2780, 2781, 2782, 2783, 2784, 2785}; + } + + private static void municipalitiesGroups3(int[][] groups) { + groups[15] = new int[] {2786, 2787, 2788, 2789, 2790, 2791, 2792, 2793, 2794, 2795, 2796, 2797, 2798, 2799, 2800, 2801, 2802, 2803, 2804, 2805, 2806, 2807, 2808, 2809, 2810, 2811, 2812, 2813, 2814, 2815, 2816, 2817, 2818, 2819, 2820, 2821, 2822, 2823, 2824, 2825, 2826, 2827, 2828, 2829, 2830, 2831, 2832, 2833, 2834, 2835, 2836, 2837, 2838, 2839, 2840, 2841, 2842, 2843, 2844, 2845, 2846, 2847, 2848, 2849, 2850, 2851, 2852, 2853, 2854, 2855, 2856, 2857, 2858, 2859, 2860, 2861, 2862, 2863, 2864, 2865, 2866, 2867, 2868, 2869, 2870, 2871, 2872, 2873, 2874, 2875, 2876, 2877, 2878, 2879, 2880, 2881, 2882, 2883, 2884, 2885, 2886, 2887, 2888, 2889, 2890, 2891, 2892, 2893, 2894, 2895, 2896, 2897, 2898, 2899, 2900, 2901, 2902, 2903, 2904, 2905, 2906, 2907, 2908, 2909, 2910, 2911, 2912, 2913, 2914, 2915, 2916, 2917, 2918, 2919, 2920, 2921, 2922, 2923, 2924, 2925, 2926, 2927, 2928, 2929, 2930, 2931, 2932, 2933, 2934, 2935, 2936, 2937, 2938, 2939, 2940, 2941, 2942, 2943, 2944, 2945, 2946, 2947, 2948, 2949, 2950, 2951, 2952, 2953, 2954, 2955, 2956, 2957, 2958, 2959, 2960, 2961, 2962, 2963, 2964, 2965, 2966, 2967, 2968, 2969, 2970, 2971, 2972, 2973, 2974, 2975, 2976, 2977, 2978, 2979, 2980, 2981, 2982, 2983, 2984, 2985, 2986, 2987, 2988, 2989, 2990, 2991, 2992, 2993, 2994, 2995, 2996, 2997, 2998, 2999, 3000, 3001, 3002, 3003, 3004, 3005, 3006, 3007, 3008, 3009, 3010, 3011, 3012, 3013, 3014, 3015, 3016, 3017, 3018, 3019, 3020, 3021, 3022, 3023, 3024, 3025, 3026, 3027, 3028, 3029, 3030, 3031, 3032, 3033, 3034, 3035, 3036, 3037, 3038, 3039, 3040, 3041, 3042, 3043, 3044, 3045, 3046, 3047, 3048, 3049, 3050, 3051, 3052, 3053, 3054, 3055, 3056, 3057, 3058, 3059, 3060, 3061, 3062, 3063, 3064, 3065, 3066, 3067, 3068, 3069, 3070, 3071, 3072, 3073, 3074, 3075, 3076, 3077, 3078, 3079, 3080, 3081, 3082, 3083, 3084, 3085, 3086, 3087, 3088, 3089, 3090, 3091, 3092, 3093, 3094, 3095, 3096, 3097, 3098, 3099, 3100, 3101, 3102, 3103, 3104, 3105, 3106, 3107, 3108, 3109, 3110, 3111, 3112, 3113, 3114, 3115, 3116, 3117, 3118, 3119, 3120, 3121, 3122, 3123, 3124, 3125, 3126, 3127, 3128, 3129, 3130, 3131, 3132, 3133, 3134, 3135, 3136, 3137, 3138, 3139, 3140, 3141, 3142, 3143, 3144, 3145, 3146, 3147, 3148, 3149, 3150, 3151, 3152, 3153, 3154, 3155, 3156, 3157, 3158, 3159, 3160, 3161, 3162, 3163, 3164, 3165, 3166, 3167, 3168, 3169, 3170, 3171, 3172, 3173, 3174, 3175, 3176, 3177, 3178, 3179, 3180, 3181, 3182, 3183, 3184}; + groups[16] = new int[] {3185, 3186, 3187, 3188, 3189, 3190, 3191, 3192, 3193, 3194, 3195, 3196, 3197, 3198, 3199, 3200, 3201, 3202, 3203, 3204, 3205, 3206, 3207, 3208, 3209, 3210, 3211, 3212, 3213, 3214, 3215, 3216, 3217, 3218, 3219, 3220, 3221, 3222, 3223, 3224, 3225, 3226, 3227, 3228, 3229, 3230, 3231, 3232, 3233, 3234, 3235, 3236, 3237, 3238, 3239, 3240, 3241, 3242, 3243, 3244, 3245, 3246, 3247, 3248, 3249, 3250, 3251, 3252, 3253, 3254, 3255, 3256, 3257, 3258, 3259, 3260, 3261, 3262, 3263, 3264, 3265, 3266, 3267, 3268, 3269, 3270, 3271, 3272, 3273, 3274, 3275, 3276, 3277, 3278, 3279, 3280, 3281, 3282, 3283, 3284, 3285, 3286, 3287, 3288, 3289, 3290, 3291, 3292, 3293, 3294, 3295, 3296, 3297, 3298, 3299, 3300, 3301, 3302, 3303, 3304, 3305, 3306, 3307, 3308, 3309, 3310, 3311, 3312, 3313, 3314, 3315, 3316, 3317, 3318, 3319, 3320, 3321, 3322, 3323, 3324, 3325, 3326, 3327, 3328, 3329, 3330, 3331, 3332, 3333, 3334, 3335, 3336, 3337, 3338, 3339, 3340, 3341, 3342, 3343, 3344, 3345, 3346, 3347, 3348, 3349, 3350, 3351, 3352, 3353, 3354, 3355, 3356, 3357, 3358, 3359, 3360, 3361, 3362, 3363, 3364, 3365, 3366, 3367, 3368, 3369}; + groups[17] = new int[] {3370, 3371, 3372, 3373, 3374, 3375, 3376, 3377, 3378, 3379, 3380, 3381, 3382, 3383, 3384, 3385, 3386, 3387, 3388, 3389, 3390, 3391, 3392, 3393, 3394, 3395, 3396, 3397, 3398, 3399, 3400, 3401, 3402, 3403, 3404, 3405, 3406, 3407, 3408, 3409, 3410, 3411, 3412, 3413, 3414, 3415, 3416, 3417, 3418, 3419, 3420, 3421, 3422, 3423, 3424, 3425, 3426, 3427, 3428, 3429, 3430, 3431, 3432, 3433, 3434, 3435, 3436, 3437, 3438, 3439, 3440, 3441, 3442, 3443, 3444, 3445, 3446, 3447, 3448, 3449, 3450, 3451, 3452, 3453, 3454, 3455, 3456, 3457, 3458, 3459, 3460, 3461, 3462, 3463, 3464, 3465, 3466, 3467, 3468, 3469, 3470, 3471, 3472, 3473, 3474, 3475, 3476, 3477, 3478, 3479, 3480, 3481, 3482, 3483, 3484, 3485, 3486, 3487, 3488, 3489, 3490, 3491, 3492, 3493, 3494, 3495, 3496, 3497, 3498, 3499, 3500, 3501, 3502, 3503, 3504, 3505, 3506, 3507, 3508, 3509, 3510, 3511, 3512, 3513, 3514, 3515, 3516, 3517, 3518, 3519, 3520, 3521, 3522, 3523, 3524, 3525, 3526, 3527, 3528, 3529, 3530, 3531, 3532, 3533, 3534, 3535, 3536, 3537, 3538, 3539, 3540, 3541, 3542, 3543, 3544, 3545, 3546, 3547, 3548, 3549, 3550, 3551, 3552, 3553, 3554, 3555, 3556, 3557, 3558, 3559, 3560, 3561, 3562, 3563, 3564, 3565, 3566, 3567, 3568, 3569, 3570, 3571, 3572, 3573, 3574, 3575, 3576, 3577, 3578, 3579, 3580, 3581, 3582, 3583, 3584, 3585, 3586, 3587, 3588, 3589, 3590, 3591, 3592, 3593}; + groups[18] = new int[] {3594, 3595, 3596, 3597, 3598, 3599, 3600, 3601, 3602, 3603, 3604, 3605, 3606, 3607, 3608, 3609, 3610, 3611, 3612, 3613, 3614, 3615, 3616, 3617, 3618, 3619, 3620, 3621, 3622, 3623, 3624, 3625, 3626, 3627, 3628, 3629, 3630, 3631, 3632, 3633, 3634, 3635, 3636, 3637, 3638, 3639, 3640, 3641, 3642, 3643, 3644, 3645, 3646, 3647, 3648, 3649, 3650, 3651, 3652, 3653, 3654, 3655, 3656, 3657, 3658, 3659, 3660, 3661, 3662, 3663, 3664, 3665, 3666, 3667, 3668, 3669, 3670, 3671, 3672, 3673, 3674, 3675, 3676, 3677, 3678, 3679, 3680, 3681, 3682, 3683, 3684, 3685}; + groups[19] = new int[] {3686, 3687, 3688, 3689, 3690, 3691, 3692, 3693, 3694, 3695, 3696, 3697, 3698, 3699, 3700, 3701, 3702, 3703, 3704, 3705, 3706, 3707, 3708, 3709, 3710, 3711, 3712, 3713, 3714, 3715, 3716, 3717, 3718, 3719, 3720, 3721, 3722, 3723, 3724, 3725, 3726, 3727, 3728, 3729, 3730, 3731, 3732, 3733, 3734, 3735, 3736, 3737, 3738, 3739, 3740, 3741, 3742, 3743, 3744, 3745, 3746, 3747, 3748, 3749, 3750, 3751, 3752, 3753, 3754, 3755, 3756, 3757, 3758, 3759, 3760, 3761, 3762, 3763, 3764, 3765, 3766, 3767, 3768, 3769, 3770, 3771, 3772, 3773, 3774, 3775, 3776, 3777, 3778, 3779, 3780, 3781, 3782, 3783, 3784, 3785, 3786, 3787, 3788, 3789, 3790, 3791, 3792, 3793, 3794, 3795, 3796, 3797, 3798, 3799, 3800, 3801, 3802, 3803, 3804, 3805, 3806, 3807, 3808, 3809, 3810, 3811, 3812, 3813, 3814, 3815, 3816, 3817, 3818, 3819, 3820, 3821, 3822, 3823, 3824, 3825, 3826, 3827, 3828, 3829, 3830, 3831, 3832, 3833, 3834, 3835, 3836, 3837, 3838, 3839, 3840, 3841, 3842, 3843, 3844, 3845, 3846, 3847, 3848, 3849, 3850, 3851, 3852}; + } + + private static void municipalitiesGroups4(int[][] groups) { + groups[20] = new int[] {3853, 3854, 3855, 3856, 3857, 3858, 3859, 3860, 3861, 3862, 3863, 3864, 3865, 3866, 3867, 3868, 3869, 3870, 3871, 3872, 3873, 3874, 3875, 3876, 3877, 3878, 3879, 3880, 3881, 3882, 3883, 3884, 3885, 3886, 3887, 3888, 3889, 3890, 3891, 3892, 3893, 3894, 3895, 3896, 3897, 3898, 3899, 3900, 3901, 3902, 3903, 3904, 3905, 3906, 3907, 3908, 3909, 3910, 3911, 3912, 3913, 3914, 3915, 3916, 3917, 3918, 3919, 3920, 3921, 3922, 3923, 3924, 3925, 3926, 3927, 3928, 3929, 3930, 3931, 3932, 3933, 3934, 3935, 3936, 3937, 3938, 3939, 3940, 3941, 3942, 3943, 3944, 3945, 3946, 3947, 3948, 3949, 3950, 3951, 3952, 3953, 3954, 3955, 3956, 3957, 3958, 3959, 3960, 3961, 3962, 3963, 3964, 3965, 3966, 3967, 3968, 3969, 3970, 3971, 3972, 3973, 3974, 3975, 3976, 3977, 3978, 3979, 3980, 3981, 3982, 3983, 3984, 3985, 3986, 3987, 3988, 3989, 3990, 3991, 3992, 3993, 3994, 3995, 3996, 3997, 3998, 3999, 4000, 4001, 4002, 4003, 4004, 4005, 4006, 4007, 4008, 4009, 4010, 4011, 4012, 4013, 4014, 4015, 4016, 4017, 4018, 4019, 4020, 4021, 4022, 4023, 4024, 4025, 4026, 4027, 4028, 4029, 4030, 4031, 4032, 4033, 4034, 4035, 4036, 4037, 4038, 4039, 4040, 4041, 4042, 4043, 4044, 4045, 4046, 4047, 4048, 4049, 4050, 4051, 4052, 4053, 4054, 4055, 4056, 4057, 4058, 4059, 4060, 4061, 4062, 4063, 4064, 4065, 4066, 4067, 4068, 4069, 4070, 4071, 4072, 4073, 4074, 4075, 4076, 4077, 4078, 4079, 4080, 4081, 4082, 4083, 4084, 4085, 4086, 4087, 4088, 4089, 4090, 4091, 4092, 4093, 4094, 4095, 4096, 4097, 4098, 4099, 4100, 4101, 4102, 4103, 4104, 4105, 4106, 4107, 4108, 4109, 4110, 4111, 4112, 4113, 4114, 4115, 4116, 4117, 4118, 4119, 4120, 4121, 4122, 4123, 4124, 4125, 4126, 4127, 4128, 4129, 4130, 4131, 4132, 4133, 4134, 4135, 4136, 4137, 4138, 4139, 4140, 4141, 4142, 4143, 4144, 4145, 4146, 4147, 4148, 4149, 4150, 4151, 4152, 4153, 4154, 4155, 4156, 4157, 4158, 4159, 4160, 4161, 4162, 4163, 4164, 4165, 4166, 4167, 4168, 4169, 4170, 4171, 4172, 4173, 4174, 4175, 4176, 4177, 4178, 4179, 4180, 4181, 4182, 4183, 4184, 4185, 4186, 4187, 4188, 4189, 4190, 4191, 4192, 4193, 4194, 4195, 4196, 4197, 4198, 4199, 4200, 4201, 4202, 4203, 4204, 4205, 4206, 4207, 4208, 4209, 4210, 4211, 4212, 4213, 4214, 4215, 4216, 4217, 4218, 4219, 4220, 4221, 4222, 4223, 4224, 4225, 4226, 4227, 4228, 4229, 4230, 4231, 4232, 4233, 4234, 4235, 4236, 4237, 4238, 4239, 4240, 4241, 4242, 4243, 4244, 4245, 4246, 4247, 4248, 4249, 4250, 4251, 4252, 4253, 4254, 4255, 4256, 4257, 4258, 4259, 4260, 4261, 4262, 4263, 4264, 4265, 4266, 4267, 4268, 4269, 4270, 4271, 4272, 4273, 4274, 4275, 4276, 4277, 4278, 4279, 4280, 4281, 4282, 4283, 4284, 4285, 4286, 4287, 4288, 4289, 4290, 4291, 4292, 4293, 4294, 4295, 4296, 4297, 4298, 4299, 4300, 4301, 4302, 4303, 4304, 4305, 4306, 4307, 4308, 4309, 4310, 4311, 4312, 4313, 4314, 4315, 4316, 4317, 4318, 4319, 4320, 4321, 4322, 4323, 4324, 4325, 4326, 4327, 4328, 4329, 4330, 4331, 4332, 4333, 4334, 4335, 4336, 4337, 4338, 4339, 4340, 4341, 4342, 4343, 4344, 4345, 4346, 4347, 4348, 4349}; + groups[21] = new int[] {4350, 4351, 4352, 4353, 4354, 4355, 4356, 4357, 4358, 4359, 4360, 4361, 4362, 4363, 4364, 4365, 4366, 4367, 4368, 4369, 4370, 4371, 4372, 4373, 4374, 4375, 4376, 4377, 4378, 4379, 4380, 4381, 4382, 4383, 4384, 4385, 4386, 4387, 4388, 4389, 4390, 4391, 4392, 4393, 4394, 4395, 4396, 4397, 4398, 4399, 4400, 4401}; + groups[22] = new int[] {4402, 4403, 4404, 4405, 4406, 4407, 4408, 4409, 4410, 4411, 4412, 4413, 4414, 4415, 4416}; + groups[23] = new int[] {4417, 4418, 4419, 4420, 4421, 4422, 4423, 4424, 4425, 4426, 4427, 4428, 4429, 4430, 4431, 4432, 4433, 4434, 4435, 4436, 4437, 4438, 4439, 4440, 4441, 4442, 4443, 4444, 4445, 4446, 4447, 4448, 4449, 4450, 4451, 4452, 4453, 4454, 4455, 4456, 4457, 4458, 4459, 4460, 4461, 4462, 4463, 4464, 4465, 4466, 4467, 4468, 4469, 4470, 4471, 4472, 4473, 4474, 4475, 4476, 4477, 4478, 4479, 4480, 4481, 4482, 4483, 4484, 4485, 4486, 4487, 4488, 4489, 4490, 4491, 4492, 4493, 4494, 4495, 4496, 4497, 4498, 4499, 4500, 4501, 4502, 4503, 4504, 4505, 4506, 4507, 4508, 4509, 4510, 4511, 4512, 4513, 4514, 4515, 4516, 4517, 4518, 4519, 4520, 4521, 4522, 4523, 4524, 4525, 4526, 4527, 4528, 4529, 4530, 4531, 4532, 4533, 4534, 4535, 4536, 4537, 4538, 4539, 4540, 4541, 4542, 4543, 4544, 4545, 4546, 4547, 4548, 4549, 4550, 4551, 4552, 4553, 4554, 4555, 4556, 4557, 4558, 4559, 4560, 4561, 4562, 4563, 4564, 4565, 4566, 4567, 4568, 4569, 4570, 4571, 4572, 4573, 4574, 4575, 4576, 4577, 4578, 4579, 4580, 4581, 4582, 4583, 4584, 4585, 4586, 4587, 4588, 4589, 4590, 4591, 4592, 4593, 4594, 4595, 4596, 4597, 4598, 4599, 4600, 4601, 4602, 4603, 4604, 4605, 4606, 4607, 4608, 4609, 4610, 4611, 4612, 4613, 4614, 4615, 4616, 4617, 4618, 4619, 4620, 4621, 4622, 4623, 4624, 4625, 4626, 4627, 4628, 4629, 4630, 4631, 4632, 4633, 4634, 4635, 4636, 4637, 4638, 4639, 4640, 4641, 4642, 4643, 4644, 4645, 4646, 4647, 4648, 4649, 4650, 4651, 4652, 4653, 4654, 4655, 4656, 4657, 4658, 4659, 4660, 4661, 4662, 4663, 4664, 4665, 4666, 4667, 4668, 4669, 4670, 4671, 4672, 4673, 4674, 4675, 4676, 4677, 4678, 4679, 4680, 4681, 4682, 4683, 4684, 4685, 4686, 4687, 4688, 4689, 4690, 4691, 4692, 4693, 4694, 4695, 4696, 4697, 4698, 4699, 4700, 4701, 4702, 4703, 4704, 4705, 4706, 4707, 4708, 4709, 4710, 4711}; + groups[24] = new int[] {4712, 4713, 4714, 4715, 4716, 4717, 4718, 4719, 4720, 4721, 4722, 4723, 4724, 4725, 4726, 4727, 4728, 4729, 4730, 4731, 4732, 4733, 4734, 4735, 4736, 4737, 4738, 4739, 4740, 4741, 4742, 4743, 4744, 4745, 4746, 4747, 4748, 4749, 4750, 4751, 4752, 4753, 4754, 4755, 4756, 4757, 4758, 4759, 4760, 4761, 4762, 4763, 4764, 4765, 4766, 4767, 4768, 4769, 4770, 4771, 4772, 4773, 4774, 4775, 4776, 4777, 4778, 4779, 4780, 4781, 4782, 4783, 4784, 4785, 4786, 4787, 4788, 4789, 4790, 4791, 4792, 4793, 4794, 4795, 4796, 4797, 4798, 4799, 4800, 4801, 4802, 4803, 4804, 4805, 4806, 4807, 4808, 4809, 4810, 4811, 4812, 4813, 4814, 4815, 4816, 4817, 4818, 4819, 4820, 4821, 4822, 4823, 4824, 4825, 4826, 4827, 4828, 4829, 4830, 4831, 4832, 4833, 4834, 4835, 4836, 4837, 4838, 4839, 4840, 4841, 4842, 4843, 4844, 4845, 4846, 4847, 4848, 4849, 4850, 4851, 4852, 4853, 4854, 4855, 4856, 4857, 4858, 4859, 4860, 4861, 4862, 4863, 4864, 4865, 4866, 4867, 4868, 4869, 4870, 4871, 4872, 4873, 4874, 4875, 4876, 4877, 4878, 4879, 4880, 4881, 4882, 4883, 4884, 4885, 4886, 4887, 4888, 4889, 4890, 4891, 4892, 4893, 4894, 4895, 4896, 4897, 4898, 4899, 4900, 4901, 4902, 4903, 4904, 4905, 4906, 4907, 4908, 4909, 4910, 4911, 4912, 4913, 4914, 4915, 4916, 4917, 4918, 4919, 4920, 4921, 4922, 4923, 4924, 4925, 4926, 4927, 4928, 4929, 4930, 4931, 4932, 4933, 4934, 4935, 4936, 4937, 4938, 4939, 4940, 4941, 4942, 4943, 4944, 4945, 4946, 4947, 4948, 4949, 4950, 4951, 4952, 4953, 4954, 4955, 4956, 4957, 4958, 4959, 4960, 4961, 4962, 4963, 4964, 4965, 4966, 4967, 4968, 4969, 4970, 4971, 4972, 4973, 4974, 4975, 4976, 4977, 4978, 4979, 4980, 4981, 4982, 4983, 4984, 4985, 4986, 4987, 4988, 4989, 4990, 4991, 4992, 4993, 4994, 4995, 4996, 4997, 4998, 4999, 5000, 5001, 5002, 5003, 5004, 5005, 5006, 5007, 5008, 5009, 5010, 5011, 5012, 5013, 5014, 5015, 5016, 5017, 5018, 5019, 5020, 5021, 5022, 5023, 5024, 5025, 5026, 5027, 5028, 5029, 5030, 5031, 5032, 5033, 5034, 5035, 5036, 5037, 5038, 5039, 5040, 5041, 5042, 5043, 5044, 5045, 5046, 5047, 5048, 5049, 5050, 5051, 5052, 5053, 5054, 5055, 5056, 5057, 5058, 5059, 5060, 5061, 5062, 5063, 5064, 5065, 5066, 5067, 5068, 5069, 5070, 5071, 5072, 5073, 5074, 5075, 5076, 5077, 5078, 5079, 5080, 5081, 5082, 5083, 5084, 5085, 5086, 5087, 5088, 5089, 5090, 5091, 5092, 5093, 5094, 5095, 5096, 5097, 5098, 5099, 5100, 5101, 5102, 5103, 5104, 5105, 5106, 5107, 5108, 5109, 5110, 5111, 5112, 5113, 5114, 5115, 5116, 5117, 5118, 5119, 5120, 5121, 5122, 5123, 5124, 5125, 5126, 5127, 5128, 5129, 5130, 5131, 5132, 5133, 5134, 5135, 5136, 5137, 5138, 5139, 5140, 5141, 5142, 5143, 5144, 5145, 5146, 5147, 5148, 5149, 5150, 5151, 5152, 5153, 5154, 5155, 5156, 5157, 5158, 5159, 5160, 5161, 5162, 5163, 5164, 5165, 5166, 5167, 5168, 5169, 5170, 5171, 5172, 5173, 5174, 5175, 5176, 5177, 5178, 5179, 5180, 5181, 5182, 5183, 5184, 5185, 5186, 5187, 5188, 5189, 5190, 5191, 5192, 5193, 5194, 5195, 5196, 5197, 5198, 5199, 5200, 5201, 5202, 5203, 5204, 5205, 5206, 5207, 5208, 5209, 5210, 5211, 5212, 5213, 5214, 5215, 5216, 5217, 5218, 5219, 5220, 5221, 5222, 5223, 5224, 5225, 5226, 5227, 5228, 5229, 5230, 5231, 5232, 5233, 5234, 5235, 5236, 5237, 5238, 5239, 5240, 5241, 5242, 5243, 5244, 5245, 5246, 5247, 5248, 5249, 5250, 5251, 5252, 5253, 5254, 5255, 5256, 5257, 5258, 5259, 5260, 5261, 5262, 5263, 5264, 5265, 5266, 5267, 5268, 5269, 5270, 5271, 5272, 5273, 5274, 5275, 5276, 5277, 5278, 5279, 5280, 5281, 5282, 5283, 5284, 5285, 5286, 5287, 5288, 5289, 5290, 5291, 5292, 5293, 5294, 5295, 5296, 5297, 5298, 5299, 5300, 5301, 5302, 5303, 5304, 5305, 5306, 5307, 5308, 5309, 5310, 5311, 5312, 5313, 5314, 5315, 5316, 5317, 5318, 5319, 5320, 5321, 5322, 5323, 5324, 5325, 5326, 5327, 5328, 5329, 5330, 5331, 5332, 5333, 5334, 5335, 5336, 5337, 5338, 5339, 5340, 5341, 5342, 5343, 5344, 5345, 5346, 5347, 5348, 5349, 5350, 5351, 5352, 5353, 5354, 5355, 5356}; + } + + private static void municipalitiesGroups5(int[][] groups) { + groups[25] = new int[] {5357, 5358, 5359, 5360, 5361, 5362, 5363, 5364, 5365, 5366, 5367, 5368, 5369, 5370, 5371, 5372, 5373, 5374, 5375, 5376, 5377, 5378, 5379, 5380, 5381, 5382, 5383, 5384, 5385, 5386, 5387, 5388, 5389, 5390, 5391, 5392, 5393, 5394, 5395, 5396, 5397, 5398, 5399, 5400, 5401, 5402, 5403, 5404, 5405, 5406, 5407, 5408, 5409, 5410, 5411, 5412, 5413, 5414, 5415, 5416, 5417, 5418, 5419, 5420, 5421, 5422, 5423, 5424, 5425, 5426, 5427, 5428, 5429, 5430, 5431}; + groups[26] = new int[] {5432, 5433, 5434, 5435, 5436, 5437, 5438, 5439, 5440, 5441, 5442, 5443, 5444, 5445, 5446, 5447, 5448, 5449, 5450, 5451, 5452, 5453, 5454, 5455, 5456, 5457, 5458, 5459, 5460, 5461, 5462, 5463, 5464, 5465, 5466, 5467, 5468, 5469, 5470, 5471, 5472, 5473, 5474, 5475, 5476, 5477, 5478, 5479, 5480, 5481, 5482, 5483, 5484, 5485, 5486, 5487, 5488, 5489, 5490, 5491, 5492, 5493, 5494, 5495, 5496, 5497, 5498, 5499, 5500, 5501, 5502, 5503, 5504, 5505, 5506, 5507, 5508, 5509, 5510, 5511, 5512, 5513, 5514, 5515, 5516, 5517, 5518, 5519, 5520, 5521, 5522, 5523, 5524, 5525, 5526, 5527, 5528, 5529, 5530, 5531, 5532, 5533, 5534, 5535, 5536, 5537, 5538, 5539, 5540, 5541, 5542, 5543, 5544, 5545, 5546, 5547, 5548, 5549, 5550, 5551, 5552, 5553, 5554, 5555, 5556, 5557, 5558, 5559, 5560, 5561, 5562, 5563, 5564, 5565, 5566, 5567, 5568, 5569, 5570}; + } + + private static int[] municipalitiesOrder() { + int[] order = new int[5571]; + municipalitiesOrder0(order); + municipalitiesOrder1(order); + municipalitiesOrder2(order); + municipalitiesOrder3(order); + municipalitiesOrder4(order); + municipalitiesOrder5(order); + municipalitiesOrder6(order); + municipalitiesOrder7(order); + municipalitiesOrder8(order); + municipalitiesOrder9(order); + municipalitiesOrder10(order); + municipalitiesOrder11(order); + return order; + } + + private static void municipalitiesOrder0(int[] order) { + order[0] = 882; + order[1] = 1566; + order[2] = 883; + order[3] = 1567; + order[4] = 2419; + order[5] = 619; + order[6] = 202; + order[7] = 203; + order[8] = 2786; + order[9] = 4417; + order[10] = 2420; + order[11] = 4418; + order[12] = 1568; + order[13] = 3185; + order[14] = 5432; + order[15] = 1569; + order[16] = 1128; + order[17] = 204; + order[18] = 2421; + order[19] = 620; + order[20] = 621; + order[21] = 3686; + order[22] = 3370; + order[23] = 3853; + order[24] = 622; + order[25] = 1345; + order[26] = 0; + order[27] = 884; + order[28] = 1570; + order[29] = 4712; + order[30] = 885; + order[31] = 4713; + order[32] = 2787; + order[33] = 205; + order[34] = 3186; + order[35] = 3687; + order[36] = 804; + order[37] = 1129; + order[38] = 3187; + order[39] = 2422; + order[40] = 3188; + order[41] = 3371; + order[42] = 4419; + order[43] = 4420; + order[44] = 2423; + order[45] = 1346; + order[46] = 1571; + order[47] = 22; + order[48] = 2563; + order[49] = 3372; + order[50] = 1487; + order[51] = 1572; + order[52] = 4421; + order[53] = 1130; + order[54] = 805; + order[55] = 206; + order[56] = 886; + order[57] = 887; + order[58] = 3688; + order[59] = 3189; + order[60] = 3854; + order[61] = 4714; + order[62] = 1573; + order[63] = 3190; + order[64] = 4715; + order[65] = 4422; + order[66] = 4716; + order[67] = 4717; + order[68] = 4718; + order[69] = 1574; + order[70] = 4423; + order[71] = 888; + order[72] = 4424; + order[73] = 1575; + order[74] = 3855; + order[75] = 4719; + order[76] = 2788; + order[77] = 806; + order[78] = 2564; + order[79] = 5433; + order[80] = 1576; + order[81] = 207; + order[82] = 623; + order[83] = 1577; + order[84] = 3856; + order[85] = 1578; + order[86] = 2565; + order[87] = 2566; + order[88] = 2567; + order[89] = 3191; + order[90] = 3373; + order[91] = 208; + order[92] = 4720; + order[93] = 1579; + order[94] = 1131; + order[95] = 624; + order[96] = 2568; + order[97] = 1488; + order[98] = 209; + order[99] = 1132; + order[100] = 3857; + order[101] = 807; + order[102] = 3858; + order[103] = 3374; + order[104] = 3859; + order[105] = 1580; + order[106] = 2424; + order[107] = 3689; + order[108] = 889; + order[109] = 1581; + order[110] = 808; + order[111] = 4721; + order[112] = 1582; + order[113] = 4425; + order[114] = 2569; + order[115] = 2570; + order[116] = 3192; + order[117] = 5434; + order[118] = 210; + order[119] = 5435; + order[120] = 2425; + order[121] = 1583; + order[122] = 3690; + order[123] = 2789; + order[124] = 3860; + order[125] = 890; + order[126] = 1584; + order[127] = 3861; + order[128] = 1585; + order[129] = 1347; + order[130] = 4350; + order[131] = 4722; + order[132] = 2426; + order[133] = 1133; + order[134] = 2790; + order[135] = 625; + order[136] = 1586; + order[137] = 3193; + order[138] = 4723; + order[139] = 3862; + order[140] = 4402; + order[141] = 4724; + order[142] = 1134; + order[143] = 1135; + order[144] = 4351; + order[145] = 1348; + order[146] = 4426; + order[147] = 1349; + order[148] = 1587; + order[149] = 3691; + order[150] = 3863; + order[151] = 1350; + order[152] = 891; + order[153] = 1588; + order[154] = 3375; + order[155] = 1351; + order[156] = 2791; + order[157] = 4352; + order[158] = 892; + order[159] = 2792; + order[160] = 1136; + order[161] = 2793; + order[162] = 1589; + order[163] = 809; + order[164] = 626; + order[165] = 1352; + order[166] = 2794; + order[167] = 3376; + order[168] = 4725; + order[169] = 140; + order[170] = 1590; + order[171] = 4726; + order[172] = 4727; + order[173] = 4728; + order[174] = 4729; + order[175] = 1591; + order[176] = 3864; + order[177] = 5436; + order[178] = 4353; + order[179] = 1592; + order[180] = 3377; + order[181] = 893; + order[182] = 2795; + order[183] = 4403; + order[184] = 1489; + order[185] = 124; + order[186] = 1137; + order[187] = 2796; + order[188] = 3194; + order[189] = 3865; + order[190] = 894; + order[191] = 3378; + order[192] = 1138; + order[193] = 211; + order[194] = 141; + order[195] = 212; + order[196] = 213; + order[197] = 4730; + order[198] = 895; + order[199] = 4731; + order[200] = 4732; + order[201] = 3866; + order[202] = 627; + order[203] = 896; + order[204] = 2571; + order[205] = 4733; + order[206] = 5357; + order[207] = 1593; + order[208] = 2797; + order[209] = 23; + order[210] = 214; + order[211] = 2798; + order[212] = 2427; + order[213] = 1139; + order[214] = 4734; + order[215] = 142; + order[216] = 5437; + order[217] = 2428; + order[218] = 897; + order[219] = 2429; + order[220] = 1140; + order[221] = 1490; + order[222] = 1491; + order[223] = 810; + order[224] = 4427; + order[225] = 215; + order[226] = 2799; + order[227] = 216; + order[228] = 1594; + order[229] = 4735; + order[230] = 3867; + order[231] = 1595; + order[232] = 4736; + order[233] = 1596; + order[234] = 1492; + order[235] = 3195; + order[236] = 4428; + order[237] = 217; + order[238] = 3379; + order[239] = 5438; + order[240] = 3692; + order[241] = 3594; + order[242] = 218; + order[243] = 2800; + order[244] = 898; + order[245] = 4737; + order[246] = 4738; + order[247] = 899; + order[248] = 3380; + order[249] = 4429; + order[250] = 4430; + order[251] = 143; + order[252] = 3868; + order[253] = 219; + order[254] = 2801; + order[255] = 628; + order[256] = 3381; + order[257] = 220; + order[258] = 1597; + order[259] = 4431; + order[260] = 1598; + order[261] = 221; + order[262] = 1493; + order[263] = 3693; + order[264] = 2802; + order[265] = 3869; + order[266] = 1599; + order[267] = 2572; + order[268] = 4739; + order[269] = 4740; + order[270] = 900; + order[271] = 901; + order[272] = 5439; + order[273] = 1494; + order[274] = 3595; + order[275] = 811; + order[276] = 1353; + order[277] = 4741; + order[278] = 1141; + order[279] = 4432; + order[280] = 3694; + order[281] = 222; + order[282] = 902; + order[283] = 223; + order[284] = 2803; + order[285] = 144; + order[286] = 629; + order[287] = 5358; + order[288] = 1495; + order[289] = 630; + order[290] = 4433; + order[291] = 2573; + order[292] = 1600; + order[293] = 5359; + order[294] = 4742; + order[295] = 224; + order[296] = 631; + order[297] = 225; + order[298] = 4743; + order[299] = 226; + order[300] = 1601; + order[301] = 632; + order[302] = 3196; + order[303] = 4744; + order[304] = 812; + order[305] = 903; + order[306] = 1602; + order[307] = 904; + order[308] = 905; + order[309] = 5440; + order[310] = 5441; + order[311] = 5442; + order[312] = 1354; + order[313] = 5443; + order[314] = 1355; + order[315] = 1142; + order[316] = 5444; + order[317] = 906; + order[318] = 1603; + order[319] = 5445; + order[320] = 1143; + order[321] = 1496; + order[322] = 227; + order[323] = 3870; + order[324] = 1144; + order[325] = 4745; + order[326] = 4746; + order[327] = 1604; + order[328] = 4747; + order[329] = 24; + order[330] = 5446; + order[331] = 1605; + order[332] = 2804; + order[333] = 1606; + order[334] = 2805; + order[335] = 1607; + order[336] = 2806; + order[337] = 1356; + order[338] = 4434; + order[339] = 2574; + order[340] = 4435; + order[341] = 4748; + order[342] = 4749; + order[343] = 633; + order[344] = 1145; + order[345] = 3871; + order[346] = 634; + order[347] = 3197; + order[348] = 3596; + order[349] = 2575; + order[350] = 2807; + order[351] = 228; + order[352] = 3872; + order[353] = 635; + order[354] = 229; + order[355] = 5360; + order[356] = 2808; + order[357] = 1608; + order[358] = 1609; + order[359] = 1610; + order[360] = 4750; + order[361] = 1611; + order[362] = 3198; + order[363] = 1612; + order[364] = 3597; + order[365] = 4751; + order[366] = 2576; + order[367] = 3695; + order[368] = 5361; + order[369] = 2577; + order[370] = 2578; + order[371] = 4752; + order[372] = 4753; + order[373] = 1357; + order[374] = 907; + order[375] = 3696; + order[376] = 1613; + order[377] = 1614; + order[378] = 1615; + order[379] = 1358; + order[380] = 4354; + order[381] = 4754; + order[382] = 2809; + order[383] = 3598; + order[384] = 4436; + order[385] = 636; + order[386] = 3382; + order[387] = 2579; + order[388] = 3383; + order[389] = 3384; + order[390] = 3599; + order[391] = 5447; + order[392] = 3873; + order[393] = 3874; + order[394] = 3875; + order[395] = 3876; + order[396] = 3877; + order[397] = 3878; + order[398] = 4437; + order[399] = 4755; + order[400] = 908; + order[401] = 4756; + order[402] = 4438; + order[403] = 3879; + order[404] = 4439; + order[405] = 4757; + order[406] = 2810; + order[407] = 637; + order[408] = 4758; + order[409] = 1; + order[410] = 2811; + order[411] = 3697; + order[412] = 2580; + order[413] = 3385; + order[414] = 1616; + order[415] = 2812; + order[416] = 25; + order[417] = 2813; + order[418] = 145; + order[419] = 4440; + order[420] = 1617; + order[421] = 4759; + order[422] = 813; + order[423] = 5448; + order[424] = 2430; + order[425] = 1618; + order[426] = 3880; + order[427] = 3881; + order[428] = 230; + order[429] = 4760; + order[430] = 909; + order[431] = 638; + order[432] = 4441; + order[433] = 2431; + order[434] = 5449; + order[435] = 146; + order[436] = 4761; + order[437] = 4762; + order[438] = 4763; + order[439] = 2432; + order[440] = 3386; + order[441] = 910; + order[442] = 1146; + order[443] = 5450; + order[444] = 5451; + order[445] = 1147; + order[446] = 1148; + order[447] = 1149; + order[448] = 1150; + order[449] = 4764; + order[450] = 1619; + order[451] = 3882; + order[452] = 2433; + order[453] = 2581; + order[454] = 3698; + order[455] = 231; + order[456] = 2434; + order[457] = 232; + order[458] = 3387; + order[459] = 639; + order[460] = 814; + order[461] = 4765; + order[462] = 1620; + order[463] = 911; + order[464] = 4442; + order[465] = 4443; + order[466] = 4444; + order[467] = 4445; + order[468] = 4446; + order[469] = 3883; + order[470] = 4447; + order[471] = 2814; + order[472] = 4766; + order[473] = 1151; + order[474] = 1621; + order[475] = 640; + order[476] = 4767; + order[477] = 2582; + order[478] = 1622; + order[479] = 1623; + order[480] = 4448; + order[481] = 1497; + order[482] = 2815; + order[483] = 5452; + order[484] = 2435; + order[485] = 233; + order[486] = 3884; + order[487] = 4768; + order[488] = 1624; + order[489] = 3885; + order[490] = 1152; + order[491] = 1359; + order[492] = 1625; + order[493] = 3886; + order[494] = 2583; + order[495] = 3699; + order[496] = 1626; + order[497] = 641; + order[498] = 4769; + order[499] = 2816; + } + + private static void municipalitiesOrder1(int[] order) { + order[500] = 2436; + order[501] = 3700; + order[502] = 147; + order[503] = 4770; + order[504] = 234; + order[505] = 4449; + order[506] = 4771; + order[507] = 3388; + order[508] = 235; + order[509] = 3199; + order[510] = 2584; + order[511] = 2585; + order[512] = 26; + order[513] = 815; + order[514] = 27; + order[515] = 2586; + order[516] = 1360; + order[517] = 4772; + order[518] = 236; + order[519] = 1153; + order[520] = 1361; + order[521] = 3887; + order[522] = 2817; + order[523] = 237; + order[524] = 5453; + order[525] = 3600; + order[526] = 3888; + order[527] = 3889; + order[528] = 3890; + order[529] = 238; + order[530] = 4773; + order[531] = 5362; + order[532] = 3891; + order[533] = 1627; + order[534] = 3601; + order[535] = 4450; + order[536] = 2818; + order[537] = 3892; + order[538] = 3389; + order[539] = 642; + order[540] = 239; + order[541] = 3390; + order[542] = 148; + order[543] = 1154; + order[544] = 3200; + order[545] = 4774; + order[546] = 4775; + order[547] = 643; + order[548] = 240; + order[549] = 912; + order[550] = 3391; + order[551] = 241; + order[552] = 242; + order[553] = 5454; + order[554] = 644; + order[555] = 3893; + order[556] = 1628; + order[557] = 4776; + order[558] = 4777; + order[559] = 1498; + order[560] = 28; + order[561] = 3392; + order[562] = 4778; + order[563] = 1499; + order[564] = 645; + order[565] = 4779; + order[566] = 2587; + order[567] = 4780; + order[568] = 646; + order[569] = 647; + order[570] = 1500; + order[571] = 2819; + order[572] = 913; + order[573] = 1629; + order[574] = 1155; + order[575] = 2820; + order[576] = 3393; + order[577] = 4451; + order[578] = 1156; + order[579] = 29; + order[580] = 2437; + order[581] = 2588; + order[582] = 3201; + order[583] = 2589; + order[584] = 3394; + order[585] = 3202; + order[586] = 3602; + order[587] = 1630; + order[588] = 243; + order[589] = 4452; + order[590] = 244; + order[591] = 1631; + order[592] = 3203; + order[593] = 30; + order[594] = 1632; + order[595] = 1633; + order[596] = 2438; + order[597] = 3395; + order[598] = 1157; + order[599] = 4453; + order[600] = 2439; + order[601] = 149; + order[602] = 3894; + order[603] = 4781; + order[604] = 3701; + order[605] = 3895; + order[606] = 1158; + order[607] = 1634; + order[608] = 1635; + order[609] = 2590; + order[610] = 4782; + order[611] = 1159; + order[612] = 5455; + order[613] = 4783; + order[614] = 3396; + order[615] = 1636; + order[616] = 150; + order[617] = 3204; + order[618] = 3397; + order[619] = 1637; + order[620] = 3205; + order[621] = 1638; + order[622] = 1639; + order[623] = 4454; + order[624] = 4784; + order[625] = 1640; + order[626] = 4785; + order[627] = 4786; + order[628] = 245; + order[629] = 2821; + order[630] = 4455; + order[631] = 816; + order[632] = 1641; + order[633] = 2822; + order[634] = 2823; + order[635] = 1362; + order[636] = 4787; + order[637] = 3398; + order[638] = 246; + order[639] = 2591; + order[640] = 2824; + order[641] = 648; + order[642] = 2592; + order[643] = 4404; + order[644] = 2825; + order[645] = 3896; + order[646] = 3897; + order[647] = 3898; + order[648] = 1160; + order[649] = 3899; + order[650] = 151; + order[651] = 3900; + order[652] = 247; + order[653] = 31; + order[654] = 152; + order[655] = 3399; + order[656] = 4788; + order[657] = 1642; + order[658] = 4456; + order[659] = 1643; + order[660] = 2826; + order[661] = 3702; + order[662] = 3206; + order[663] = 1501; + order[664] = 4789; + order[665] = 4790; + order[666] = 3207; + order[667] = 1644; + order[668] = 1161; + order[669] = 3208; + order[670] = 3603; + order[671] = 4457; + order[672] = 914; + order[673] = 1645; + order[674] = 2593; + order[675] = 3400; + order[676] = 3703; + order[677] = 3901; + order[678] = 4458; + order[679] = 248; + order[680] = 1646; + order[681] = 249; + order[682] = 1162; + order[683] = 915; + order[684] = 1647; + order[685] = 1363; + order[686] = 1648; + order[687] = 3604; + order[688] = 817; + order[689] = 4459; + order[690] = 2827; + order[691] = 2440; + order[692] = 5456; + order[693] = 4791; + order[694] = 1163; + order[695] = 3902; + order[696] = 3401; + order[697] = 3903; + order[698] = 1649; + order[699] = 4460; + order[700] = 3904; + order[701] = 1650; + order[702] = 2594; + order[703] = 2828; + order[704] = 4792; + order[705] = 2829; + order[706] = 4461; + order[707] = 1651; + order[708] = 4405; + order[709] = 3402; + order[710] = 916; + order[711] = 1652; + order[712] = 250; + order[713] = 251; + order[714] = 1502; + order[715] = 2441; + order[716] = 3209; + order[717] = 1653; + order[718] = 2595; + order[719] = 917; + order[720] = 2596; + order[721] = 3905; + order[722] = 3403; + order[723] = 5363; + order[724] = 252; + order[725] = 4793; + order[726] = 4794; + order[727] = 153; + order[728] = 2597; + order[729] = 4795; + order[730] = 1654; + order[731] = 4796; + order[732] = 2830; + order[733] = 3906; + order[734] = 1655; + order[735] = 4797; + order[736] = 1656; + order[737] = 253; + order[738] = 4462; + order[739] = 3907; + order[740] = 4463; + order[741] = 4464; + order[742] = 3908; + order[743] = 2442; + order[744] = 4798; + order[745] = 2831; + order[746] = 32; + order[747] = 1657; + order[748] = 2443; + order[749] = 1503; + order[750] = 1658; + order[751] = 2832; + order[752] = 5457; + order[753] = 2; + order[754] = 3404; + order[755] = 803; + order[756] = 1659; + order[757] = 1364; + order[758] = 4799; + order[759] = 1660; + order[760] = 918; + order[761] = 1661; + order[762] = 3210; + order[763] = 818; + order[764] = 3211; + order[765] = 3704; + order[766] = 5458; + order[767] = 1164; + order[768] = 4800; + order[769] = 3212; + order[770] = 1165; + order[771] = 2598; + order[772] = 3405; + order[773] = 2599; + order[774] = 5364; + order[775] = 2444; + order[776] = 649; + order[777] = 254; + order[778] = 255; + order[779] = 2445; + order[780] = 2446; + order[781] = 919; + order[782] = 3909; + order[783] = 4801; + order[784] = 4802; + order[785] = 256; + order[786] = 1662; + order[787] = 257; + order[788] = 4465; + order[789] = 4466; + order[790] = 1663; + order[791] = 1664; + order[792] = 3213; + order[793] = 258; + order[794] = 1665; + order[795] = 3214; + order[796] = 3; + order[797] = 2447; + order[798] = 4803; + order[799] = 4804; + order[800] = 1166; + order[801] = 920; + order[802] = 1167; + order[803] = 921; + order[804] = 5459; + order[805] = 3406; + order[806] = 3407; + order[807] = 1168; + order[808] = 922; + order[809] = 259; + order[810] = 1169; + order[811] = 1666; + order[812] = 4355; + order[813] = 4805; + order[814] = 1667; + order[815] = 3910; + order[816] = 154; + order[817] = 2600; + order[818] = 1504; + order[819] = 260; + order[820] = 2601; + order[821] = 261; + order[822] = 1668; + order[823] = 923; + order[824] = 3408; + order[825] = 2602; + order[826] = 4356; + order[827] = 3215; + order[828] = 3605; + order[829] = 1669; + order[830] = 4806; + order[831] = 4807; + order[832] = 3216; + order[833] = 4467; + order[834] = 4808; + order[835] = 3911; + order[836] = 4357; + order[837] = 3912; + order[838] = 1365; + order[839] = 262; + order[840] = 924; + order[841] = 1670; + order[842] = 925; + order[843] = 1671; + order[844] = 1672; + order[845] = 2448; + order[846] = 2449; + order[847] = 3913; + order[848] = 2603; + order[849] = 926; + order[850] = 1673; + order[851] = 1170; + order[852] = 4809; + order[853] = 3606; + order[854] = 3217; + order[855] = 3914; + order[856] = 5460; + order[857] = 819; + order[858] = 2604; + order[859] = 2605; + order[860] = 2606; + order[861] = 33; + order[862] = 3915; + order[863] = 4358; + order[864] = 4810; + order[865] = 927; + order[866] = 263; + order[867] = 264; + order[868] = 1674; + order[869] = 265; + order[870] = 1675; + order[871] = 3218; + order[872] = 266; + order[873] = 267; + order[874] = 2833; + order[875] = 2834; + order[876] = 4811; + order[877] = 2835; + order[878] = 4812; + order[879] = 1676; + order[880] = 928; + order[881] = 3916; + order[882] = 4468; + order[883] = 2607; + order[884] = 3917; + order[885] = 3705; + order[886] = 3706; + order[887] = 3707; + order[888] = 4813; + order[889] = 268; + order[890] = 4814; + order[891] = 4815; + order[892] = 1171; + order[893] = 1172; + order[894] = 4816; + order[895] = 2608; + order[896] = 3409; + order[897] = 2609; + order[898] = 4817; + order[899] = 34; + order[900] = 3410; + order[901] = 1677; + order[902] = 4818; + order[903] = 3219; + order[904] = 125; + order[905] = 1678; + order[906] = 2610; + order[907] = 929; + order[908] = 930; + order[909] = 269; + order[910] = 3411; + order[911] = 2836; + order[912] = 4469; + order[913] = 3220; + order[914] = 270; + order[915] = 271; + order[916] = 1679; + order[917] = 2611; + order[918] = 272; + order[919] = 1680; + order[920] = 1505; + order[921] = 3918; + order[922] = 3221; + order[923] = 3919; + order[924] = 2837; + order[925] = 3920; + order[926] = 2838; + order[927] = 2839; + order[928] = 4470; + order[929] = 3607; + order[930] = 1681; + order[931] = 1682; + order[932] = 2450; + order[933] = 650; + order[934] = 3222; + order[935] = 1683; + order[936] = 1684; + order[937] = 35; + order[938] = 1685; + order[939] = 3921; + order[940] = 931; + order[941] = 1173; + order[942] = 2840; + order[943] = 3922; + order[944] = 4819; + order[945] = 2841; + order[946] = 2612; + order[947] = 2842; + order[948] = 1686; + order[949] = 932; + order[950] = 1366; + order[951] = 4820; + order[952] = 3412; + order[953] = 3923; + order[954] = 933; + order[955] = 36; + order[956] = 4471; + order[957] = 934; + order[958] = 273; + order[959] = 3413; + order[960] = 1687; + order[961] = 1688; + order[962] = 4472; + order[963] = 3924; + order[964] = 2843; + order[965] = 5365; + order[966] = 1689; + order[967] = 2844; + order[968] = 4473; + order[969] = 1690; + order[970] = 274; + order[971] = 37; + order[972] = 1506; + order[973] = 3708; + order[974] = 3414; + order[975] = 2845; + order[976] = 3415; + order[977] = 935; + order[978] = 4821; + order[979] = 2846; + order[980] = 3416; + order[981] = 2847; + order[982] = 3925; + order[983] = 4359; + order[984] = 1367; + order[985] = 3709; + order[986] = 1368; + order[987] = 1691; + order[988] = 936; + order[989] = 3926; + order[990] = 1369; + order[991] = 4822; + order[992] = 3608; + order[993] = 1692; + order[994] = 5461; + order[995] = 4474; + order[996] = 4823; + order[997] = 651; + order[998] = 937; + order[999] = 3223; + } + + private static void municipalitiesOrder2(int[] order) { + order[1000] = 1693; + order[1001] = 1694; + order[1002] = 2451; + order[1003] = 1370; + order[1004] = 4824; + order[1005] = 38; + order[1006] = 275; + order[1007] = 1695; + order[1008] = 276; + order[1009] = 1371; + order[1010] = 4825; + order[1011] = 3417; + order[1012] = 277; + order[1013] = 278; + order[1014] = 279; + order[1015] = 1696; + order[1016] = 4360; + order[1017] = 3927; + order[1018] = 280; + order[1019] = 2848; + order[1020] = 3928; + order[1021] = 1174; + order[1022] = 4826; + order[1023] = 4827; + order[1024] = 281; + order[1025] = 3929; + order[1026] = 2849; + order[1027] = 3930; + order[1028] = 4475; + order[1029] = 3710; + order[1030] = 3931; + order[1031] = 5366; + order[1032] = 3224; + order[1033] = 652; + order[1034] = 5367; + order[1035] = 4828; + order[1036] = 3932; + order[1037] = 4476; + order[1038] = 282; + order[1039] = 4406; + order[1040] = 1697; + order[1041] = 2850; + order[1042] = 3609; + order[1043] = 1175; + order[1044] = 3418; + order[1045] = 283; + order[1046] = 3933; + order[1047] = 155; + order[1048] = 2452; + order[1049] = 2851; + order[1050] = 4477; + order[1051] = 4829; + order[1052] = 3934; + order[1053] = 3935; + order[1054] = 3936; + order[1055] = 3937; + order[1056] = 1698; + order[1057] = 39; + order[1058] = 5368; + order[1059] = 3938; + order[1060] = 4830; + order[1061] = 284; + order[1062] = 1699; + order[1063] = 1700; + order[1064] = 1701; + order[1065] = 2613; + order[1066] = 1702; + order[1067] = 285; + order[1068] = 1703; + order[1069] = 4478; + order[1070] = 1176; + order[1071] = 653; + order[1072] = 3939; + order[1073] = 1704; + order[1074] = 3419; + order[1075] = 1705; + order[1076] = 3420; + order[1077] = 2852; + order[1078] = 2453; + order[1079] = 1706; + order[1080] = 4831; + order[1081] = 4479; + order[1082] = 3940; + order[1083] = 4; + order[1084] = 3225; + order[1085] = 1707; + order[1086] = 3941; + order[1087] = 4407; + order[1088] = 1507; + order[1089] = 3421; + order[1090] = 4832; + order[1091] = 1708; + order[1092] = 286; + order[1093] = 2853; + order[1094] = 1709; + order[1095] = 1710; + order[1096] = 1711; + order[1097] = 3610; + order[1098] = 4833; + order[1099] = 1712; + order[1100] = 156; + order[1101] = 2614; + order[1102] = 3711; + order[1103] = 3422; + order[1104] = 287; + order[1105] = 3942; + order[1106] = 1713; + order[1107] = 288; + order[1108] = 4834; + order[1109] = 3611; + order[1110] = 1714; + order[1111] = 157; + order[1112] = 158; + order[1113] = 820; + order[1114] = 654; + order[1115] = 3423; + order[1116] = 289; + order[1117] = 5369; + order[1118] = 655; + order[1119] = 5462; + order[1120] = 656; + order[1121] = 657; + order[1122] = 1372; + order[1123] = 2854; + order[1124] = 3943; + order[1125] = 1715; + order[1126] = 3944; + order[1127] = 1716; + order[1128] = 3612; + order[1129] = 1717; + order[1130] = 1718; + order[1131] = 1719; + order[1132] = 1720; + order[1133] = 1721; + order[1134] = 1722; + order[1135] = 938; + order[1136] = 5463; + order[1137] = 5370; + order[1138] = 1723; + order[1139] = 3226; + order[1140] = 3712; + order[1141] = 3713; + order[1142] = 658; + order[1143] = 3227; + order[1144] = 1724; + order[1145] = 40; + order[1146] = 4408; + order[1147] = 1177; + order[1148] = 3228; + order[1149] = 1725; + order[1150] = 2615; + order[1151] = 5464; + order[1152] = 3229; + order[1153] = 1178; + order[1154] = 1726; + order[1155] = 1727; + order[1156] = 4835; + order[1157] = 1728; + order[1158] = 290; + order[1159] = 3945; + order[1160] = 1729; + order[1161] = 659; + order[1162] = 2855; + order[1163] = 5465; + order[1164] = 3946; + order[1165] = 3613; + order[1166] = 3230; + order[1167] = 2616; + order[1168] = 1730; + order[1169] = 4836; + order[1170] = 1508; + order[1171] = 2454; + order[1172] = 1373; + order[1173] = 4361; + order[1174] = 939; + order[1175] = 821; + order[1176] = 3424; + order[1177] = 4837; + order[1178] = 2856; + order[1179] = 291; + order[1180] = 1731; + order[1181] = 940; + order[1182] = 4838; + order[1183] = 2857; + order[1184] = 4480; + order[1185] = 660; + order[1186] = 1732; + order[1187] = 1733; + order[1188] = 3231; + order[1189] = 4839; + order[1190] = 2617; + order[1191] = 292; + order[1192] = 2618; + order[1193] = 293; + order[1194] = 3947; + order[1195] = 1734; + order[1196] = 661; + order[1197] = 941; + order[1198] = 294; + order[1199] = 2619; + order[1200] = 1735; + order[1201] = 662; + order[1202] = 942; + order[1203] = 1736; + order[1204] = 4481; + order[1205] = 1179; + order[1206] = 3948; + order[1207] = 3425; + order[1208] = 3714; + order[1209] = 1180; + order[1210] = 4840; + order[1211] = 663; + order[1212] = 3232; + order[1213] = 5371; + order[1214] = 1737; + order[1215] = 4482; + order[1216] = 3949; + order[1217] = 5466; + order[1218] = 2858; + order[1219] = 295; + order[1220] = 1738; + order[1221] = 1181; + order[1222] = 1739; + order[1223] = 1182; + order[1224] = 1183; + order[1225] = 4362; + order[1226] = 943; + order[1227] = 4841; + order[1228] = 4842; + order[1229] = 3950; + order[1230] = 2859; + order[1231] = 3951; + order[1232] = 3715; + order[1233] = 3952; + order[1234] = 3953; + order[1235] = 3954; + order[1236] = 4483; + order[1237] = 4843; + order[1238] = 2860; + order[1239] = 944; + order[1240] = 3233; + order[1241] = 3234; + order[1242] = 41; + order[1243] = 1740; + order[1244] = 1741; + order[1245] = 3955; + order[1246] = 5467; + order[1247] = 5468; + order[1248] = 1742; + order[1249] = 1374; + order[1250] = 1743; + order[1251] = 945; + order[1252] = 4484; + order[1253] = 1509; + order[1254] = 1184; + order[1255] = 4485; + order[1256] = 4844; + order[1257] = 3956; + order[1258] = 3957; + order[1259] = 664; + order[1260] = 4845; + order[1261] = 2455; + order[1262] = 1744; + order[1263] = 3958; + order[1264] = 2861; + order[1265] = 665; + order[1266] = 666; + order[1267] = 296; + order[1268] = 3959; + order[1269] = 4363; + order[1270] = 3960; + order[1271] = 2862; + order[1272] = 297; + order[1273] = 2863; + order[1274] = 946; + order[1275] = 1185; + order[1276] = 3961; + order[1277] = 298; + order[1278] = 1745; + order[1279] = 3962; + order[1280] = 1746; + order[1281] = 1747; + order[1282] = 1375; + order[1283] = 1748; + order[1284] = 4846; + order[1285] = 2864; + order[1286] = 299; + order[1287] = 159; + order[1288] = 3426; + order[1289] = 3427; + order[1290] = 4486; + order[1291] = 3428; + order[1292] = 1376; + order[1293] = 947; + order[1294] = 300; + order[1295] = 160; + order[1296] = 1186; + order[1297] = 1187; + order[1298] = 1749; + order[1299] = 42; + order[1300] = 3429; + order[1301] = 2456; + order[1302] = 822; + order[1303] = 1377; + order[1304] = 4847; + order[1305] = 1188; + order[1306] = 3963; + order[1307] = 948; + order[1308] = 5469; + order[1309] = 5470; + order[1310] = 1378; + order[1311] = 4848; + order[1312] = 2865; + order[1313] = 3430; + order[1314] = 3431; + order[1315] = 43; + order[1316] = 2866; + order[1317] = 3964; + order[1318] = 4364; + order[1319] = 1750; + order[1320] = 5471; + order[1321] = 1751; + order[1322] = 3614; + order[1323] = 1752; + order[1324] = 1379; + order[1325] = 2620; + order[1326] = 1753; + order[1327] = 823; + order[1328] = 1754; + order[1329] = 301; + order[1330] = 1755; + order[1331] = 1756; + order[1332] = 1757; + order[1333] = 3615; + order[1334] = 302; + order[1335] = 2457; + order[1336] = 3432; + order[1337] = 824; + order[1338] = 303; + order[1339] = 304; + order[1340] = 1189; + order[1341] = 1758; + order[1342] = 1759; + order[1343] = 1760; + order[1344] = 5472; + order[1345] = 1761; + order[1346] = 4849; + order[1347] = 4850; + order[1348] = 4487; + order[1349] = 2458; + order[1350] = 2621; + order[1351] = 3235; + order[1352] = 305; + order[1353] = 2622; + order[1354] = 306; + order[1355] = 3965; + order[1356] = 1762; + order[1357] = 1763; + order[1358] = 1380; + order[1359] = 2623; + order[1360] = 1764; + order[1361] = 1765; + order[1362] = 1766; + order[1363] = 2867; + order[1364] = 1767; + order[1365] = 1381; + order[1366] = 1768; + order[1367] = 2868; + order[1368] = 1769; + order[1369] = 1770; + order[1370] = 3966; + order[1371] = 1771; + order[1372] = 2869; + order[1373] = 307; + order[1374] = 1772; + order[1375] = 3967; + order[1376] = 44; + order[1377] = 3968; + order[1378] = 1773; + order[1379] = 308; + order[1380] = 2870; + order[1381] = 3616; + order[1382] = 4851; + order[1383] = 309; + order[1384] = 4488; + order[1385] = 1774; + order[1386] = 1775; + order[1387] = 667; + order[1388] = 2624; + order[1389] = 1510; + order[1390] = 310; + order[1391] = 1776; + order[1392] = 2871; + order[1393] = 1777; + order[1394] = 4852; + order[1395] = 1190; + order[1396] = 1778; + order[1397] = 3969; + order[1398] = 3970; + order[1399] = 2872; + order[1400] = 3716; + order[1401] = 1779; + order[1402] = 4489; + order[1403] = 3717; + order[1404] = 311; + order[1405] = 3433; + order[1406] = 4853; + order[1407] = 4490; + order[1408] = 1780; + order[1409] = 1781; + order[1410] = 3971; + order[1411] = 1511; + order[1412] = 2873; + order[1413] = 1782; + order[1414] = 1783; + order[1415] = 1784; + order[1416] = 949; + order[1417] = 1785; + order[1418] = 1786; + order[1419] = 4491; + order[1420] = 3434; + order[1421] = 3236; + order[1422] = 312; + order[1423] = 3237; + order[1424] = 1512; + order[1425] = 950; + order[1426] = 951; + order[1427] = 4854; + order[1428] = 2874; + order[1429] = 4365; + order[1430] = 4492; + order[1431] = 45; + order[1432] = 4855; + order[1433] = 4856; + order[1434] = 4366; + order[1435] = 1513; + order[1436] = 313; + order[1437] = 4857; + order[1438] = 3972; + order[1439] = 1382; + order[1440] = 1787; + order[1441] = 5473; + order[1442] = 3973; + order[1443] = 1514; + order[1444] = 2625; + order[1445] = 46; + order[1446] = 668; + order[1447] = 669; + order[1448] = 4858; + order[1449] = 314; + order[1450] = 4493; + order[1451] = 1788; + order[1452] = 315; + order[1453] = 3974; + order[1454] = 1789; + order[1455] = 4859; + order[1456] = 3975; + order[1457] = 3976; + order[1458] = 5474; + order[1459] = 3435; + order[1460] = 1790; + order[1461] = 952; + order[1462] = 1791; + order[1463] = 953; + order[1464] = 1792; + order[1465] = 5372; + order[1466] = 3436; + order[1467] = 316; + order[1468] = 954; + order[1469] = 5475; + order[1470] = 670; + order[1471] = 955; + order[1472] = 1793; + order[1473] = 671; + order[1474] = 3977; + order[1475] = 317; + order[1476] = 2626; + order[1477] = 2875; + order[1478] = 4860; + order[1479] = 3978; + order[1480] = 4861; + order[1481] = 1794; + order[1482] = 2876; + order[1483] = 2877; + order[1484] = 5; + order[1485] = 2878; + order[1486] = 3979; + order[1487] = 3718; + order[1488] = 1795; + order[1489] = 2879; + order[1490] = 4862; + order[1491] = 2627; + order[1492] = 1383; + order[1493] = 2628; + order[1494] = 2629; + order[1495] = 2630; + order[1496] = 4367; + order[1497] = 956; + order[1498] = 3238; + order[1499] = 2459; + } + + private static void municipalitiesOrder3(int[] order) { + order[1500] = 5373; + order[1501] = 4863; + order[1502] = 4494; + order[1503] = 4495; + order[1504] = 1796; + order[1505] = 3239; + order[1506] = 318; + order[1507] = 3437; + order[1508] = 2460; + order[1509] = 2880; + order[1510] = 4496; + order[1511] = 2881; + order[1512] = 3438; + order[1513] = 3719; + order[1514] = 2631; + order[1515] = 1797; + order[1516] = 3439; + order[1517] = 2632; + order[1518] = 2461; + order[1519] = 3440; + order[1520] = 2462; + order[1521] = 2463; + order[1522] = 1191; + order[1523] = 1384; + order[1524] = 1798; + order[1525] = 3240; + order[1526] = 126; + order[1527] = 957; + order[1528] = 2633; + order[1529] = 958; + order[1530] = 5476; + order[1531] = 319; + order[1532] = 1799; + order[1533] = 3980; + order[1534] = 959; + order[1535] = 1192; + order[1536] = 1800; + order[1537] = 1801; + order[1538] = 47; + order[1539] = 1802; + order[1540] = 3441; + order[1541] = 1385; + order[1542] = 1515; + order[1543] = 672; + order[1544] = 3981; + order[1545] = 4864; + order[1546] = 4497; + order[1547] = 1803; + order[1548] = 2634; + order[1549] = 1804; + order[1550] = 1805; + order[1551] = 3982; + order[1552] = 4865; + order[1553] = 2635; + order[1554] = 2882; + order[1555] = 2883; + order[1556] = 2884; + order[1557] = 1806; + order[1558] = 1386; + order[1559] = 5477; + order[1560] = 320; + order[1561] = 3983; + order[1562] = 1807; + order[1563] = 1808; + order[1564] = 4498; + order[1565] = 960; + order[1566] = 4866; + order[1567] = 3442; + order[1568] = 5374; + order[1569] = 1809; + order[1570] = 1810; + order[1571] = 1811; + order[1572] = 825; + order[1573] = 4867; + order[1574] = 1812; + order[1575] = 1813; + order[1576] = 961; + order[1577] = 5478; + order[1578] = 1814; + order[1579] = 1815; + order[1580] = 1816; + order[1581] = 4868; + order[1582] = 4869; + order[1583] = 3984; + order[1584] = 3985; + order[1585] = 1516; + order[1586] = 5479; + order[1587] = 3986; + order[1588] = 48; + order[1589] = 2885; + order[1590] = 4870; + order[1591] = 1387; + order[1592] = 321; + order[1593] = 1817; + order[1594] = 1818; + order[1595] = 2464; + order[1596] = 3443; + order[1597] = 3987; + order[1598] = 3444; + order[1599] = 1819; + order[1600] = 322; + order[1601] = 3988; + order[1602] = 1193; + order[1603] = 3989; + order[1604] = 1820; + order[1605] = 1821; + order[1606] = 826; + order[1607] = 3445; + order[1608] = 4499; + order[1609] = 1822; + order[1610] = 3990; + order[1611] = 2636; + order[1612] = 1823; + order[1613] = 1824; + order[1614] = 1825; + order[1615] = 827; + order[1616] = 1826; + order[1617] = 1827; + order[1618] = 3241; + order[1619] = 1517; + order[1620] = 2886; + order[1621] = 4871; + order[1622] = 1828; + order[1623] = 1518; + order[1624] = 2887; + order[1625] = 3991; + order[1626] = 4500; + order[1627] = 3992; + order[1628] = 3720; + order[1629] = 2888; + order[1630] = 962; + order[1631] = 4872; + order[1632] = 4873; + order[1633] = 3617; + order[1634] = 2637; + order[1635] = 5480; + order[1636] = 4874; + order[1637] = 1194; + order[1638] = 3618; + order[1639] = 1829; + order[1640] = 4875; + order[1641] = 828; + order[1642] = 963; + order[1643] = 964; + order[1644] = 161; + order[1645] = 1519; + order[1646] = 4876; + order[1647] = 2465; + order[1648] = 3993; + order[1649] = 3446; + order[1650] = 4877; + order[1651] = 3447; + order[1652] = 4878; + order[1653] = 323; + order[1654] = 1830; + order[1655] = 2638; + order[1656] = 4879; + order[1657] = 4880; + order[1658] = 4881; + order[1659] = 4882; + order[1660] = 3994; + order[1661] = 3721; + order[1662] = 324; + order[1663] = 3995; + order[1664] = 2889; + order[1665] = 2890; + order[1666] = 1831; + order[1667] = 4883; + order[1668] = 1832; + order[1669] = 3619; + order[1670] = 3996; + order[1671] = 1833; + order[1672] = 325; + order[1673] = 4501; + order[1674] = 1834; + order[1675] = 2891; + order[1676] = 3997; + order[1677] = 3998; + order[1678] = 162; + order[1679] = 6; + order[1680] = 3722; + order[1681] = 3999; + order[1682] = 4000; + order[1683] = 673; + order[1684] = 326; + order[1685] = 4502; + order[1686] = 4001; + order[1687] = 4002; + order[1688] = 4003; + order[1689] = 4503; + order[1690] = 1835; + order[1691] = 3242; + order[1692] = 4004; + order[1693] = 1836; + order[1694] = 1837; + order[1695] = 2639; + order[1696] = 4005; + order[1697] = 2892; + order[1698] = 3448; + order[1699] = 5481; + order[1700] = 1195; + order[1701] = 2893; + order[1702] = 4368; + order[1703] = 1838; + order[1704] = 3723; + order[1705] = 1839; + order[1706] = 4884; + order[1707] = 4885; + order[1708] = 327; + order[1709] = 4006; + order[1710] = 4007; + order[1711] = 5375; + order[1712] = 4008; + order[1713] = 4009; + order[1714] = 1840; + order[1715] = 4886; + order[1716] = 1196; + order[1717] = 4010; + order[1718] = 4887; + order[1719] = 1841; + order[1720] = 49; + order[1721] = 1842; + order[1722] = 965; + order[1723] = 4888; + order[1724] = 1843; + order[1725] = 4011; + order[1726] = 328; + order[1727] = 4889; + order[1728] = 4012; + order[1729] = 1844; + order[1730] = 329; + order[1731] = 674; + order[1732] = 1845; + order[1733] = 1846; + order[1734] = 3724; + order[1735] = 3243; + order[1736] = 2640; + order[1737] = 4013; + order[1738] = 966; + order[1739] = 1847; + order[1740] = 1848; + order[1741] = 675; + order[1742] = 2466; + order[1743] = 2894; + order[1744] = 4014; + order[1745] = 4890; + order[1746] = 3449; + order[1747] = 330; + order[1748] = 5482; + order[1749] = 1520; + order[1750] = 2895; + order[1751] = 4015; + order[1752] = 4504; + order[1753] = 4016; + order[1754] = 967; + order[1755] = 2896; + order[1756] = 4017; + order[1757] = 7; + order[1758] = 331; + order[1759] = 332; + order[1760] = 50; + order[1761] = 3244; + order[1762] = 5376; + order[1763] = 1197; + order[1764] = 1849; + order[1765] = 3725; + order[1766] = 1850; + order[1767] = 1851; + order[1768] = 4018; + order[1769] = 51; + order[1770] = 1388; + order[1771] = 2897; + order[1772] = 2898; + order[1773] = 1852; + order[1774] = 3245; + order[1775] = 1198; + order[1776] = 3726; + order[1777] = 4891; + order[1778] = 4892; + order[1779] = 4893; + order[1780] = 4894; + order[1781] = 127; + order[1782] = 3246; + order[1783] = 1853; + order[1784] = 1854; + order[1785] = 2899; + order[1786] = 1521; + order[1787] = 5483; + order[1788] = 1389; + order[1789] = 333; + order[1790] = 5484; + order[1791] = 334; + order[1792] = 968; + order[1793] = 52; + order[1794] = 2900; + order[1795] = 4505; + order[1796] = 4895; + order[1797] = 2901; + order[1798] = 3727; + order[1799] = 4896; + order[1800] = 3247; + order[1801] = 4019; + order[1802] = 969; + order[1803] = 3450; + order[1804] = 2902; + order[1805] = 3248; + order[1806] = 335; + order[1807] = 2467; + order[1808] = 3451; + order[1809] = 1855; + order[1810] = 2903; + order[1811] = 3452; + order[1812] = 4020; + order[1813] = 4506; + order[1814] = 2904; + order[1815] = 4897; + order[1816] = 4898; + order[1817] = 163; + order[1818] = 4021; + order[1819] = 1856; + order[1820] = 4022; + order[1821] = 970; + order[1822] = 1199; + order[1823] = 2905; + order[1824] = 336; + order[1825] = 4507; + order[1826] = 971; + order[1827] = 1857; + order[1828] = 5485; + order[1829] = 4023; + order[1830] = 676; + order[1831] = 4508; + order[1832] = 677; + order[1833] = 1858; + order[1834] = 1200; + order[1835] = 4024; + order[1836] = 678; + order[1837] = 1201; + order[1838] = 1859; + order[1839] = 2906; + order[1840] = 2907; + order[1841] = 4509; + order[1842] = 4899; + order[1843] = 3453; + order[1844] = 2908; + order[1845] = 3454; + order[1846] = 1860; + order[1847] = 2909; + order[1848] = 3728; + order[1849] = 1861; + order[1850] = 3455; + order[1851] = 4900; + order[1852] = 1862; + order[1853] = 3456; + order[1854] = 1863; + order[1855] = 4901; + order[1856] = 679; + order[1857] = 4025; + order[1858] = 1864; + order[1859] = 1865; + order[1860] = 1866; + order[1861] = 2641; + order[1862] = 3249; + order[1863] = 5377; + order[1864] = 4510; + order[1865] = 1867; + order[1866] = 1868; + order[1867] = 3457; + order[1868] = 1869; + order[1869] = 1870; + order[1870] = 3729; + order[1871] = 829; + order[1872] = 1871; + order[1873] = 4902; + order[1874] = 2642; + order[1875] = 4903; + order[1876] = 1872; + order[1877] = 3730; + order[1878] = 4511; + order[1879] = 3250; + order[1880] = 972; + order[1881] = 1873; + order[1882] = 337; + order[1883] = 3251; + order[1884] = 5378; + order[1885] = 4904; + order[1886] = 4026; + order[1887] = 4512; + order[1888] = 2468; + order[1889] = 4027; + order[1890] = 4513; + order[1891] = 4514; + order[1892] = 4905; + order[1893] = 1390; + order[1894] = 4028; + order[1895] = 338; + order[1896] = 4906; + order[1897] = 3458; + order[1898] = 4029; + order[1899] = 1391; + order[1900] = 2910; + order[1901] = 5379; + order[1902] = 4907; + order[1903] = 680; + order[1904] = 4030; + order[1905] = 339; + order[1906] = 4908; + order[1907] = 4031; + order[1908] = 3459; + order[1909] = 53; + order[1910] = 4032; + order[1911] = 1874; + order[1912] = 4909; + order[1913] = 340; + order[1914] = 1392; + order[1915] = 1522; + order[1916] = 3252; + order[1917] = 4033; + order[1918] = 1202; + order[1919] = 2911; + order[1920] = 1875; + order[1921] = 3253; + order[1922] = 1876; + order[1923] = 973; + order[1924] = 974; + order[1925] = 975; + order[1926] = 2469; + order[1927] = 976; + order[1928] = 3731; + order[1929] = 977; + order[1930] = 5486; + order[1931] = 978; + order[1932] = 5487; + order[1933] = 979; + order[1934] = 2912; + order[1935] = 2913; + order[1936] = 1877; + order[1937] = 1203; + order[1938] = 341; + order[1939] = 1878; + order[1940] = 1879; + order[1941] = 980; + order[1942] = 1204; + order[1943] = 4515; + order[1944] = 3732; + order[1945] = 1205; + order[1946] = 1206; + order[1947] = 4369; + order[1948] = 830; + order[1949] = 1207; + order[1950] = 342; + order[1951] = 1208; + order[1952] = 1209; + order[1953] = 1880; + order[1954] = 681; + order[1955] = 1210; + order[1956] = 5380; + order[1957] = 1211; + order[1958] = 4034; + order[1959] = 4035; + order[1960] = 4036; + order[1961] = 2914; + order[1962] = 3254; + order[1963] = 682; + order[1964] = 683; + order[1965] = 1881; + order[1966] = 4516; + order[1967] = 3255; + order[1968] = 4037; + order[1969] = 4517; + order[1970] = 684; + order[1971] = 3733; + order[1972] = 1882; + order[1973] = 4038; + order[1974] = 4518; + order[1975] = 831; + order[1976] = 3460; + order[1977] = 4039; + order[1978] = 4910; + order[1979] = 4911; + order[1980] = 2915; + order[1981] = 4912; + order[1982] = 2916; + order[1983] = 685; + order[1984] = 164; + order[1985] = 4370; + order[1986] = 343; + order[1987] = 3734; + order[1988] = 2917; + order[1989] = 344; + order[1990] = 1883; + order[1991] = 1884; + order[1992] = 4913; + order[1993] = 4914; + order[1994] = 3620; + order[1995] = 2918; + order[1996] = 981; + order[1997] = 4040; + order[1998] = 2919; + order[1999] = 4915; + } + + private static void municipalitiesOrder4(int[] order) { + order[2000] = 2643; + order[2001] = 4916; + order[2002] = 2920; + order[2003] = 4917; + order[2004] = 1885; + order[2005] = 4519; + order[2006] = 686; + order[2007] = 1886; + order[2008] = 5488; + order[2009] = 982; + order[2010] = 687; + order[2011] = 4520; + order[2012] = 1887; + order[2013] = 1888; + order[2014] = 4918; + order[2015] = 4041; + order[2016] = 983; + order[2017] = 2921; + order[2018] = 4919; + order[2019] = 1393; + order[2020] = 832; + order[2021] = 2922; + order[2022] = 2923; + order[2023] = 1889; + order[2024] = 4920; + order[2025] = 4921; + order[2026] = 345; + order[2027] = 4922; + order[2028] = 2924; + order[2029] = 1890; + order[2030] = 4923; + order[2031] = 4924; + order[2032] = 3461; + order[2033] = 984; + order[2034] = 4925; + order[2035] = 4521; + order[2036] = 4926; + order[2037] = 4522; + order[2038] = 4927; + order[2039] = 1891; + order[2040] = 1523; + order[2041] = 1892; + order[2042] = 1212; + order[2043] = 1893; + order[2044] = 1394; + order[2045] = 1894; + order[2046] = 1895; + order[2047] = 2644; + order[2048] = 2645; + order[2049] = 2470; + order[2050] = 5489; + order[2051] = 4928; + order[2052] = 4042; + order[2053] = 985; + order[2054] = 1896; + order[2055] = 346; + order[2056] = 4929; + order[2057] = 4043; + order[2058] = 4523; + order[2059] = 4044; + order[2060] = 688; + order[2061] = 986; + order[2062] = 987; + order[2063] = 4930; + order[2064] = 2925; + order[2065] = 689; + order[2066] = 4045; + order[2067] = 4931; + order[2068] = 3462; + order[2069] = 4046; + order[2070] = 165; + order[2071] = 4047; + order[2072] = 1213; + order[2073] = 4932; + order[2074] = 988; + order[2075] = 4933; + order[2076] = 347; + order[2077] = 1897; + order[2078] = 4934; + order[2079] = 3256; + order[2080] = 2926; + order[2081] = 4048; + order[2082] = 690; + order[2083] = 4935; + order[2084] = 54; + order[2085] = 833; + order[2086] = 2927; + order[2087] = 1898; + order[2088] = 1899; + order[2089] = 4049; + order[2090] = 1900; + order[2091] = 4524; + order[2092] = 691; + order[2093] = 2646; + order[2094] = 348; + order[2095] = 349; + order[2096] = 4525; + order[2097] = 350; + order[2098] = 351; + order[2099] = 692; + order[2100] = 3257; + order[2101] = 352; + order[2102] = 353; + order[2103] = 2928; + order[2104] = 354; + order[2105] = 4936; + order[2106] = 1901; + order[2107] = 1902; + order[2108] = 834; + order[2109] = 4050; + order[2110] = 3258; + order[2111] = 4526; + order[2112] = 355; + order[2113] = 356; + order[2114] = 4051; + order[2115] = 4937; + order[2116] = 357; + order[2117] = 1903; + order[2118] = 4052; + order[2119] = 358; + order[2120] = 4938; + order[2121] = 835; + order[2122] = 359; + order[2123] = 1904; + order[2124] = 1905; + order[2125] = 4939; + order[2126] = 360; + order[2127] = 693; + order[2128] = 4527; + order[2129] = 1906; + order[2130] = 2929; + order[2131] = 1214; + order[2132] = 4940; + order[2133] = 361; + order[2134] = 694; + order[2135] = 836; + order[2136] = 3735; + order[2137] = 4941; + order[2138] = 55; + order[2139] = 362; + order[2140] = 4942; + order[2141] = 2647; + order[2142] = 4943; + order[2143] = 1907; + order[2144] = 1215; + order[2145] = 1216; + order[2146] = 2471; + order[2147] = 2472; + order[2148] = 3259; + order[2149] = 4944; + order[2150] = 1908; + order[2151] = 363; + order[2152] = 56; + order[2153] = 4053; + order[2154] = 3621; + order[2155] = 364; + order[2156] = 4945; + order[2157] = 2930; + order[2158] = 3260; + order[2159] = 1909; + order[2160] = 1524; + order[2161] = 695; + order[2162] = 2931; + order[2163] = 1910; + order[2164] = 4054; + order[2165] = 4946; + order[2166] = 5381; + order[2167] = 3261; + order[2168] = 3463; + order[2169] = 4947; + order[2170] = 4948; + order[2171] = 365; + order[2172] = 4528; + order[2173] = 1911; + order[2174] = 4055; + order[2175] = 2648; + order[2176] = 4529; + order[2177] = 2932; + order[2178] = 4056; + order[2179] = 1912; + order[2180] = 4530; + order[2181] = 2933; + order[2182] = 4531; + order[2183] = 4057; + order[2184] = 1217; + order[2185] = 2934; + order[2186] = 989; + order[2187] = 2935; + order[2188] = 3262; + order[2189] = 1913; + order[2190] = 1914; + order[2191] = 4532; + order[2192] = 4949; + order[2193] = 696; + order[2194] = 4058; + order[2195] = 4950; + order[2196] = 1915; + order[2197] = 2936; + order[2198] = 4951; + order[2199] = 990; + order[2200] = 5382; + order[2201] = 1395; + order[2202] = 2649; + order[2203] = 1916; + order[2204] = 3263; + order[2205] = 4059; + order[2206] = 366; + order[2207] = 2473; + order[2208] = 57; + order[2209] = 1917; + order[2210] = 1918; + order[2211] = 3464; + order[2212] = 991; + order[2213] = 1919; + order[2214] = 1525; + order[2215] = 4952; + order[2216] = 4533; + order[2217] = 1920; + order[2218] = 992; + order[2219] = 1921; + order[2220] = 3736; + order[2221] = 697; + order[2222] = 1922; + order[2223] = 698; + order[2224] = 4953; + order[2225] = 4060; + order[2226] = 367; + order[2227] = 4954; + order[2228] = 4955; + order[2229] = 1923; + order[2230] = 368; + order[2231] = 4956; + order[2232] = 4534; + order[2233] = 369; + order[2234] = 2937; + order[2235] = 993; + order[2236] = 1396; + order[2237] = 3465; + order[2238] = 4061; + order[2239] = 166; + order[2240] = 2474; + order[2241] = 3264; + order[2242] = 994; + order[2243] = 2938; + order[2244] = 4535; + order[2245] = 4957; + order[2246] = 699; + order[2247] = 4958; + order[2248] = 4536; + order[2249] = 3265; + order[2250] = 3737; + order[2251] = 700; + order[2252] = 5490; + order[2253] = 1924; + order[2254] = 4537; + order[2255] = 370; + order[2256] = 701; + order[2257] = 4409; + order[2258] = 2939; + order[2259] = 4959; + order[2260] = 4538; + order[2261] = 4062; + order[2262] = 1925; + order[2263] = 371; + order[2264] = 372; + order[2265] = 167; + order[2266] = 4539; + order[2267] = 4960; + order[2268] = 4961; + order[2269] = 373; + order[2270] = 374; + order[2271] = 2940; + order[2272] = 4540; + order[2273] = 702; + order[2274] = 375; + order[2275] = 2941; + order[2276] = 4541; + order[2277] = 2475; + order[2278] = 837; + order[2279] = 3466; + order[2280] = 995; + order[2281] = 4542; + order[2282] = 4063; + order[2283] = 2650; + order[2284] = 5383; + order[2285] = 5384; + order[2286] = 376; + order[2287] = 4962; + order[2288] = 377; + order[2289] = 996; + order[2290] = 5385; + order[2291] = 1926; + order[2292] = 1927; + order[2293] = 1928; + order[2294] = 3622; + order[2295] = 378; + order[2296] = 5491; + order[2297] = 1929; + order[2298] = 1930; + order[2299] = 379; + order[2300] = 168; + order[2301] = 3266; + order[2302] = 4064; + order[2303] = 380; + order[2304] = 381; + order[2305] = 382; + order[2306] = 383; + order[2307] = 838; + order[2308] = 384; + order[2309] = 3623; + order[2310] = 2942; + order[2311] = 1931; + order[2312] = 997; + order[2313] = 998; + order[2314] = 5492; + order[2315] = 4963; + order[2316] = 3267; + order[2317] = 703; + order[2318] = 3467; + order[2319] = 4543; + order[2320] = 1218; + order[2321] = 1932; + order[2322] = 2943; + order[2323] = 704; + order[2324] = 2476; + order[2325] = 999; + order[2326] = 3738; + order[2327] = 4544; + order[2328] = 4964; + order[2329] = 4965; + order[2330] = 385; + order[2331] = 1933; + order[2332] = 386; + order[2333] = 3624; + order[2334] = 387; + order[2335] = 1934; + order[2336] = 169; + order[2337] = 1935; + order[2338] = 388; + order[2339] = 1936; + order[2340] = 2944; + order[2341] = 389; + order[2342] = 2945; + order[2343] = 3268; + order[2344] = 1937; + order[2345] = 1938; + order[2346] = 1939; + order[2347] = 390; + order[2348] = 4966; + order[2349] = 1940; + order[2350] = 1397; + order[2351] = 391; + order[2352] = 1941; + order[2353] = 1942; + order[2354] = 4967; + order[2355] = 3625; + order[2356] = 1000; + order[2357] = 1943; + order[2358] = 705; + order[2359] = 392; + order[2360] = 393; + order[2361] = 394; + order[2362] = 1944; + order[2363] = 4968; + order[2364] = 1219; + order[2365] = 2946; + order[2366] = 4545; + order[2367] = 839; + order[2368] = 2947; + order[2369] = 3626; + order[2370] = 3269; + order[2371] = 395; + order[2372] = 4969; + order[2373] = 1945; + order[2374] = 4970; + order[2375] = 4971; + order[2376] = 396; + order[2377] = 706; + order[2378] = 4972; + order[2379] = 170; + order[2380] = 4546; + order[2381] = 1001; + order[2382] = 4973; + order[2383] = 5493; + order[2384] = 3270; + order[2385] = 397; + order[2386] = 707; + order[2387] = 4547; + order[2388] = 4974; + order[2389] = 1526; + order[2390] = 5494; + order[2391] = 2651; + order[2392] = 4975; + order[2393] = 5386; + order[2394] = 2652; + order[2395] = 4371; + order[2396] = 4065; + order[2397] = 4976; + order[2398] = 4977; + order[2399] = 1002; + order[2400] = 4978; + order[2401] = 398; + order[2402] = 4066; + order[2403] = 1527; + order[2404] = 3271; + order[2405] = 840; + order[2406] = 399; + order[2407] = 4979; + order[2408] = 708; + order[2409] = 4980; + order[2410] = 1003; + order[2411] = 4067; + order[2412] = 3627; + order[2413] = 1946; + order[2414] = 4981; + order[2415] = 4068; + order[2416] = 400; + order[2417] = 4982; + order[2418] = 709; + order[2419] = 2653; + order[2420] = 3739; + order[2421] = 1947; + order[2422] = 1398; + order[2423] = 128; + order[2424] = 1004; + order[2425] = 3468; + order[2426] = 1948; + order[2427] = 2948; + order[2428] = 1949; + order[2429] = 1950; + order[2430] = 1220; + order[2431] = 1399; + order[2432] = 4983; + order[2433] = 4984; + order[2434] = 401; + order[2435] = 402; + order[2436] = 4985; + order[2437] = 403; + order[2438] = 4986; + order[2439] = 404; + order[2440] = 405; + order[2441] = 1951; + order[2442] = 1952; + order[2443] = 1005; + order[2444] = 1953; + order[2445] = 4987; + order[2446] = 2477; + order[2447] = 4548; + order[2448] = 1954; + order[2449] = 1955; + order[2450] = 4988; + order[2451] = 406; + order[2452] = 841; + order[2453] = 2949; + order[2454] = 2950; + order[2455] = 2951; + order[2456] = 2952; + order[2457] = 1528; + order[2458] = 1006; + order[2459] = 4069; + order[2460] = 4070; + order[2461] = 3272; + order[2462] = 4549; + order[2463] = 407; + order[2464] = 4989; + order[2465] = 2953; + order[2466] = 4071; + order[2467] = 4990; + order[2468] = 1956; + order[2469] = 3740; + order[2470] = 408; + order[2471] = 2654; + order[2472] = 58; + order[2473] = 2478; + order[2474] = 4991; + order[2475] = 2954; + order[2476] = 4992; + order[2477] = 1400; + order[2478] = 1957; + order[2479] = 4550; + order[2480] = 409; + order[2481] = 3469; + order[2482] = 1958; + order[2483] = 59; + order[2484] = 4072; + order[2485] = 2479; + order[2486] = 4993; + order[2487] = 1959; + order[2488] = 4073; + order[2489] = 2955; + order[2490] = 410; + order[2491] = 1960; + order[2492] = 4074; + order[2493] = 411; + order[2494] = 842; + order[2495] = 710; + order[2496] = 4075; + order[2497] = 2956; + order[2498] = 711; + order[2499] = 712; + } + + private static void municipalitiesOrder5(int[] order) { + order[2500] = 412; + order[2501] = 4994; + order[2502] = 713; + order[2503] = 4551; + order[2504] = 1961; + order[2505] = 3470; + order[2506] = 4995; + order[2507] = 4996; + order[2508] = 1962; + order[2509] = 1963; + order[2510] = 1007; + order[2511] = 2957; + order[2512] = 413; + order[2513] = 3741; + order[2514] = 4997; + order[2515] = 3742; + order[2516] = 1401; + order[2517] = 2958; + order[2518] = 1964; + order[2519] = 3743; + order[2520] = 1965; + order[2521] = 60; + order[2522] = 5387; + order[2523] = 3628; + order[2524] = 3744; + order[2525] = 2959; + order[2526] = 5388; + order[2527] = 1966; + order[2528] = 1529; + order[2529] = 171; + order[2530] = 2960; + order[2531] = 3273; + order[2532] = 4076; + order[2533] = 1008; + order[2534] = 4552; + order[2535] = 1530; + order[2536] = 61; + order[2537] = 714; + order[2538] = 1531; + order[2539] = 2961; + order[2540] = 3745; + order[2541] = 3746; + order[2542] = 3471; + order[2543] = 3747; + order[2544] = 2962; + order[2545] = 4553; + order[2546] = 4998; + order[2547] = 4077; + order[2548] = 4999; + order[2549] = 4372; + order[2550] = 1009; + order[2551] = 2963; + order[2552] = 3274; + order[2553] = 1532; + order[2554] = 715; + order[2555] = 1221; + order[2556] = 3275; + order[2557] = 3472; + order[2558] = 5000; + order[2559] = 5495; + order[2560] = 1010; + order[2561] = 1402; + order[2562] = 1967; + order[2563] = 1968; + order[2564] = 1222; + order[2565] = 1969; + order[2566] = 62; + order[2567] = 414; + order[2568] = 1970; + order[2569] = 1971; + order[2570] = 1972; + order[2571] = 415; + order[2572] = 2655; + order[2573] = 5001; + order[2574] = 843; + order[2575] = 3473; + order[2576] = 1973; + order[2577] = 2964; + order[2578] = 1011; + order[2579] = 4373; + order[2580] = 716; + order[2581] = 416; + order[2582] = 417; + order[2583] = 4554; + order[2584] = 1974; + order[2585] = 1975; + order[2586] = 5002; + order[2587] = 3276; + order[2588] = 3748; + order[2589] = 3474; + order[2590] = 3749; + order[2591] = 418; + order[2592] = 1223; + order[2593] = 1976; + order[2594] = 844; + order[2595] = 2656; + order[2596] = 1977; + order[2597] = 5003; + order[2598] = 1978; + order[2599] = 63; + order[2600] = 3277; + order[2601] = 3475; + order[2602] = 2965; + order[2603] = 2657; + order[2604] = 3476; + order[2605] = 4078; + order[2606] = 4555; + order[2607] = 1979; + order[2608] = 8; + order[2609] = 4556; + order[2610] = 5004; + order[2611] = 3750; + order[2612] = 3477; + order[2613] = 1980; + order[2614] = 1981; + order[2615] = 1224; + order[2616] = 1982; + order[2617] = 1012; + order[2618] = 1403; + order[2619] = 2658; + order[2620] = 5496; + order[2621] = 1983; + order[2622] = 2659; + order[2623] = 419; + order[2624] = 717; + order[2625] = 3478; + order[2626] = 718; + order[2627] = 3278; + order[2628] = 420; + order[2629] = 3751; + order[2630] = 1404; + order[2631] = 1984; + order[2632] = 3479; + order[2633] = 4079; + order[2634] = 5005; + order[2635] = 5006; + order[2636] = 1225; + order[2637] = 2660; + order[2638] = 64; + order[2639] = 3752; + order[2640] = 5007; + order[2641] = 2966; + order[2642] = 65; + order[2643] = 5008; + order[2644] = 3279; + order[2645] = 4557; + order[2646] = 5009; + order[2647] = 5010; + order[2648] = 1985; + order[2649] = 2967; + order[2650] = 3280; + order[2651] = 3480; + order[2652] = 2661; + order[2653] = 2662; + order[2654] = 172; + order[2655] = 1986; + order[2656] = 1405; + order[2657] = 2480; + order[2658] = 1406; + order[2659] = 421; + order[2660] = 1013; + order[2661] = 2968; + order[2662] = 422; + order[2663] = 423; + order[2664] = 173; + order[2665] = 1533; + order[2666] = 1987; + order[2667] = 2969; + order[2668] = 174; + order[2669] = 4558; + order[2670] = 1988; + order[2671] = 1534; + order[2672] = 424; + order[2673] = 1989; + order[2674] = 5389; + order[2675] = 4559; + order[2676] = 1226; + order[2677] = 1227; + order[2678] = 1228; + order[2679] = 1229; + order[2680] = 2663; + order[2681] = 3481; + order[2682] = 4080; + order[2683] = 3753; + order[2684] = 66; + order[2685] = 5497; + order[2686] = 1990; + order[2687] = 2664; + order[2688] = 3281; + order[2689] = 3754; + order[2690] = 3482; + order[2691] = 3755; + order[2692] = 3483; + order[2693] = 3282; + order[2694] = 1230; + order[2695] = 3283; + order[2696] = 3484; + order[2697] = 3485; + order[2698] = 5498; + order[2699] = 3284; + order[2700] = 1991; + order[2701] = 4081; + order[2702] = 1992; + order[2703] = 1993; + order[2704] = 1994; + order[2705] = 3285; + order[2706] = 1231; + order[2707] = 3756; + order[2708] = 425; + order[2709] = 3757; + order[2710] = 1014; + order[2711] = 1995; + order[2712] = 2665; + order[2713] = 4082; + order[2714] = 4083; + order[2715] = 5011; + order[2716] = 3486; + order[2717] = 4560; + order[2718] = 1535; + order[2719] = 426; + order[2720] = 3629; + order[2721] = 4084; + order[2722] = 5499; + order[2723] = 4085; + order[2724] = 4561; + order[2725] = 1232; + order[2726] = 427; + order[2727] = 428; + order[2728] = 3286; + order[2729] = 429; + order[2730] = 3758; + order[2731] = 3759; + order[2732] = 1996; + order[2733] = 430; + order[2734] = 1997; + order[2735] = 1407; + order[2736] = 1998; + order[2737] = 3487; + order[2738] = 2970; + order[2739] = 431; + order[2740] = 845; + order[2741] = 1999; + order[2742] = 2971; + order[2743] = 129; + order[2744] = 5012; + order[2745] = 5390; + order[2746] = 2972; + order[2747] = 2000; + order[2748] = 2666; + order[2749] = 4562; + order[2750] = 432; + order[2751] = 4563; + order[2752] = 5500; + order[2753] = 5013; + order[2754] = 2001; + order[2755] = 719; + order[2756] = 4086; + order[2757] = 5014; + order[2758] = 2002; + order[2759] = 4564; + order[2760] = 5015; + order[2761] = 2003; + order[2762] = 433; + order[2763] = 5016; + order[2764] = 4565; + order[2765] = 2004; + order[2766] = 1015; + order[2767] = 2973; + order[2768] = 4087; + order[2769] = 2005; + order[2770] = 434; + order[2771] = 2974; + order[2772] = 1233; + order[2773] = 2006; + order[2774] = 5017; + order[2775] = 2007; + order[2776] = 3287; + order[2777] = 67; + order[2778] = 2481; + order[2779] = 720; + order[2780] = 2975; + order[2781] = 5018; + order[2782] = 4566; + order[2783] = 4088; + order[2784] = 4089; + order[2785] = 846; + order[2786] = 5019; + order[2787] = 2667; + order[2788] = 435; + order[2789] = 5501; + order[2790] = 2976; + order[2791] = 2977; + order[2792] = 2668; + order[2793] = 2978; + order[2794] = 2008; + order[2795] = 4567; + order[2796] = 5020; + order[2797] = 1234; + order[2798] = 5021; + order[2799] = 5022; + order[2800] = 1408; + order[2801] = 5023; + order[2802] = 2669; + order[2803] = 5024; + order[2804] = 1409; + order[2805] = 3760; + order[2806] = 5025; + order[2807] = 3488; + order[2808] = 1235; + order[2809] = 436; + order[2810] = 3761; + order[2811] = 2009; + order[2812] = 2010; + order[2813] = 4568; + order[2814] = 2979; + order[2815] = 5026; + order[2816] = 2011; + order[2817] = 2980; + order[2818] = 5027; + order[2819] = 2981; + order[2820] = 5028; + order[2821] = 2012; + order[2822] = 4569; + order[2823] = 1016; + order[2824] = 3489; + order[2825] = 5502; + order[2826] = 3630; + order[2827] = 3762; + order[2828] = 437; + order[2829] = 4090; + order[2830] = 5391; + order[2831] = 130; + order[2832] = 3288; + order[2833] = 438; + order[2834] = 5029; + order[2835] = 3763; + order[2836] = 5030; + order[2837] = 439; + order[2838] = 5031; + order[2839] = 68; + order[2840] = 2013; + order[2841] = 4091; + order[2842] = 4374; + order[2843] = 2014; + order[2844] = 3289; + order[2845] = 4570; + order[2846] = 3631; + order[2847] = 440; + order[2848] = 721; + order[2849] = 3490; + order[2850] = 441; + order[2851] = 2015; + order[2852] = 2670; + order[2853] = 2482; + order[2854] = 442; + order[2855] = 4571; + order[2856] = 2483; + order[2857] = 1236; + order[2858] = 5032; + order[2859] = 3632; + order[2860] = 443; + order[2861] = 444; + order[2862] = 5033; + order[2863] = 5034; + order[2864] = 1017; + order[2865] = 4572; + order[2866] = 69; + order[2867] = 3764; + order[2868] = 4573; + order[2869] = 2016; + order[2870] = 445; + order[2871] = 446; + order[2872] = 5392; + order[2873] = 5393; + order[2874] = 2982; + order[2875] = 2671; + order[2876] = 2672; + order[2877] = 1018; + order[2878] = 2983; + order[2879] = 2017; + order[2880] = 4092; + order[2881] = 175; + order[2882] = 2673; + order[2883] = 176; + order[2884] = 3290; + order[2885] = 177; + order[2886] = 9; + order[2887] = 2984; + order[2888] = 2985; + order[2889] = 2986; + order[2890] = 5035; + order[2891] = 2987; + order[2892] = 2018; + order[2893] = 3633; + order[2894] = 2988; + order[2895] = 2019; + order[2896] = 2020; + order[2897] = 178; + order[2898] = 3491; + order[2899] = 2989; + order[2900] = 10; + order[2901] = 4093; + order[2902] = 447; + order[2903] = 448; + order[2904] = 2021; + order[2905] = 847; + order[2906] = 4094; + order[2907] = 2022; + order[2908] = 70; + order[2909] = 1019; + order[2910] = 179; + order[2911] = 2484; + order[2912] = 5036; + order[2913] = 1237; + order[2914] = 5037; + order[2915] = 4574; + order[2916] = 1536; + order[2917] = 2485; + order[2918] = 722; + order[2919] = 449; + order[2920] = 71; + order[2921] = 450; + order[2922] = 3291; + order[2923] = 1238; + order[2924] = 723; + order[2925] = 1239; + order[2926] = 2486; + order[2927] = 5038; + order[2928] = 4095; + order[2929] = 848; + order[2930] = 4096; + order[2931] = 451; + order[2932] = 72; + order[2933] = 4575; + order[2934] = 2023; + order[2935] = 2674; + order[2936] = 1410; + order[2937] = 4097; + order[2938] = 3765; + order[2939] = 452; + order[2940] = 724; + order[2941] = 3492; + order[2942] = 3493; + order[2943] = 2990; + order[2944] = 73; + order[2945] = 849; + order[2946] = 11; + order[2947] = 4576; + order[2948] = 2675; + order[2949] = 2024; + order[2950] = 2991; + order[2951] = 2992; + order[2952] = 2025; + order[2953] = 4098; + order[2954] = 4099; + order[2955] = 5503; + order[2956] = 5039; + order[2957] = 74; + order[2958] = 3634; + order[2959] = 2026; + order[2960] = 850; + order[2961] = 2993; + order[2962] = 2994; + order[2963] = 5040; + order[2964] = 2995; + order[2965] = 2996; + order[2966] = 5041; + order[2967] = 2027; + order[2968] = 2997; + order[2969] = 2998; + order[2970] = 2028; + order[2971] = 2487; + order[2972] = 2676; + order[2973] = 2029; + order[2974] = 2999; + order[2975] = 2030; + order[2976] = 4100; + order[2977] = 3000; + order[2978] = 2031; + order[2979] = 725; + order[2980] = 5042; + order[2981] = 3766; + order[2982] = 2032; + order[2983] = 5394; + order[2984] = 3001; + order[2985] = 1020; + order[2986] = 453; + order[2987] = 726; + order[2988] = 3494; + order[2989] = 2677; + order[2990] = 4577; + order[2991] = 4101; + order[2992] = 454; + order[2993] = 75; + order[2994] = 1240; + order[2995] = 2033; + order[2996] = 5043; + order[2997] = 2678; + order[2998] = 5504; + order[2999] = 3002; + } + + private static void municipalitiesOrder6(int[] order) { + order[3000] = 2034; + order[3001] = 2035; + order[3002] = 2036; + order[3003] = 2037; + order[3004] = 2038; + order[3005] = 3495; + order[3006] = 455; + order[3007] = 1241; + order[3008] = 2679; + order[3009] = 3003; + order[3010] = 2039; + order[3011] = 4102; + order[3012] = 2680; + order[3013] = 4103; + order[3014] = 4104; + order[3015] = 3004; + order[3016] = 2040; + order[3017] = 1242; + order[3018] = 1243; + order[3019] = 4578; + order[3020] = 2041; + order[3021] = 1021; + order[3022] = 76; + order[3023] = 1411; + order[3024] = 2681; + order[3025] = 2042; + order[3026] = 5044; + order[3027] = 3005; + order[3028] = 180; + order[3029] = 1022; + order[3030] = 5505; + order[3031] = 727; + order[3032] = 3767; + order[3033] = 4105; + order[3034] = 131; + order[3035] = 2043; + order[3036] = 456; + order[3037] = 3006; + order[3038] = 2488; + order[3039] = 2044; + order[3040] = 4579; + order[3041] = 2489; + order[3042] = 3635; + order[3043] = 2045; + order[3044] = 5045; + order[3045] = 3007; + order[3046] = 2046; + order[3047] = 5046; + order[3048] = 728; + order[3049] = 5047; + order[3050] = 2047; + order[3051] = 3636; + order[3052] = 77; + order[3053] = 3768; + order[3054] = 3496; + order[3055] = 457; + order[3056] = 3497; + order[3057] = 3637; + order[3058] = 5048; + order[3059] = 458; + order[3060] = 729; + order[3061] = 1244; + order[3062] = 730; + order[3063] = 3498; + order[3064] = 1023; + order[3065] = 851; + order[3066] = 1024; + order[3067] = 78; + order[3068] = 4106; + order[3069] = 2048; + order[3070] = 2049; + order[3071] = 1025; + order[3072] = 5049; + order[3073] = 4375; + order[3074] = 5050; + order[3075] = 2050; + order[3076] = 5051; + order[3077] = 3638; + order[3078] = 5506; + order[3079] = 1245; + order[3080] = 3008; + order[3081] = 2051; + order[3082] = 4107; + order[3083] = 2052; + order[3084] = 731; + order[3085] = 1537; + order[3086] = 1246; + order[3087] = 3292; + order[3088] = 5052; + order[3089] = 459; + order[3090] = 5507; + order[3091] = 460; + order[3092] = 4376; + order[3093] = 5053; + order[3094] = 3009; + order[3095] = 5054; + order[3096] = 1412; + order[3097] = 5055; + order[3098] = 2053; + order[3099] = 4580; + order[3100] = 1247; + order[3101] = 3010; + order[3102] = 732; + order[3103] = 2490; + order[3104] = 5056; + order[3105] = 4581; + order[3106] = 2054; + order[3107] = 2055; + order[3108] = 2682; + order[3109] = 5057; + order[3110] = 5058; + order[3111] = 5059; + order[3112] = 1026; + order[3113] = 5395; + order[3114] = 2491; + order[3115] = 2492; + order[3116] = 733; + order[3117] = 5060; + order[3118] = 1248; + order[3119] = 5061; + order[3120] = 4582; + order[3121] = 5062; + order[3122] = 2056; + order[3123] = 3499; + order[3124] = 3500; + order[3125] = 2057; + order[3126] = 734; + order[3127] = 2683; + order[3128] = 2058; + order[3129] = 852; + order[3130] = 3769; + order[3131] = 4108; + order[3132] = 2493; + order[3133] = 3770; + order[3134] = 1027; + order[3135] = 2059; + order[3136] = 5396; + order[3137] = 3501; + order[3138] = 5063; + order[3139] = 4109; + order[3140] = 5064; + order[3141] = 5065; + order[3142] = 2060; + order[3143] = 5066; + order[3144] = 2061; + order[3145] = 4110; + order[3146] = 4583; + order[3147] = 2062; + order[3148] = 4584; + order[3149] = 5067; + order[3150] = 3771; + order[3151] = 5508; + order[3152] = 2063; + order[3153] = 2684; + order[3154] = 5068; + order[3155] = 4377; + order[3156] = 461; + order[3157] = 2064; + order[3158] = 5509; + order[3159] = 2065; + order[3160] = 2685; + order[3161] = 5069; + order[3162] = 79; + order[3163] = 4111; + order[3164] = 1249; + order[3165] = 2066; + order[3166] = 1028; + order[3167] = 2067; + order[3168] = 1029; + order[3169] = 1030; + order[3170] = 735; + order[3171] = 2068; + order[3172] = 736; + order[3173] = 3293; + order[3174] = 3011; + order[3175] = 3294; + order[3176] = 4112; + order[3177] = 462; + order[3178] = 3012; + order[3179] = 737; + order[3180] = 1031; + order[3181] = 4113; + order[3182] = 5070; + order[3183] = 1032; + order[3184] = 3502; + order[3185] = 4585; + order[3186] = 2069; + order[3187] = 463; + order[3188] = 3503; + order[3189] = 2070; + order[3190] = 4586; + order[3191] = 4114; + order[3192] = 4115; + order[3193] = 1250; + order[3194] = 464; + order[3195] = 5071; + order[3196] = 1033; + order[3197] = 3772; + order[3198] = 4116; + order[3199] = 5072; + order[3200] = 1034; + order[3201] = 2494; + order[3202] = 4410; + order[3203] = 738; + order[3204] = 465; + order[3205] = 4117; + order[3206] = 466; + order[3207] = 853; + order[3208] = 4118; + order[3209] = 4119; + order[3210] = 739; + order[3211] = 2686; + order[3212] = 467; + order[3213] = 468; + order[3214] = 1035; + order[3215] = 1538; + order[3216] = 2071; + order[3217] = 3013; + order[3218] = 469; + order[3219] = 854; + order[3220] = 470; + order[3221] = 855; + order[3222] = 2072; + order[3223] = 5397; + order[3224] = 80; + order[3225] = 3504; + order[3226] = 5510; + order[3227] = 471; + order[3228] = 5073; + order[3229] = 472; + order[3230] = 2073; + order[3231] = 1036; + order[3232] = 2074; + order[3233] = 2075; + order[3234] = 5074; + order[3235] = 2076; + order[3236] = 4120; + order[3237] = 2077; + order[3238] = 5075; + order[3239] = 3773; + order[3240] = 2078; + order[3241] = 2079; + order[3242] = 3639; + order[3243] = 5511; + order[3244] = 5076; + order[3245] = 2687; + order[3246] = 4587; + order[3247] = 1539; + order[3248] = 473; + order[3249] = 5512; + order[3250] = 3295; + order[3251] = 3505; + order[3252] = 5077; + order[3253] = 2080; + order[3254] = 2688; + order[3255] = 3506; + order[3256] = 1037; + order[3257] = 5398; + order[3258] = 2081; + order[3259] = 1038; + order[3260] = 5078; + order[3261] = 181; + order[3262] = 5079; + order[3263] = 4121; + order[3264] = 474; + order[3265] = 3640; + order[3266] = 1251; + order[3267] = 2082; + order[3268] = 1540; + order[3269] = 5080; + order[3270] = 1039; + order[3271] = 3774; + order[3272] = 3641; + order[3273] = 1413; + order[3274] = 4122; + order[3275] = 475; + order[3276] = 4411; + order[3277] = 1414; + order[3278] = 5399; + order[3279] = 5400; + order[3280] = 5401; + order[3281] = 3014; + order[3282] = 5402; + order[3283] = 3507; + order[3284] = 1415; + order[3285] = 5403; + order[3286] = 3508; + order[3287] = 5081; + order[3288] = 3015; + order[3289] = 4123; + order[3290] = 1541; + order[3291] = 1040; + order[3292] = 3016; + order[3293] = 1542; + order[3294] = 4124; + order[3295] = 1041; + order[3296] = 3017; + order[3297] = 1416; + order[3298] = 4125; + order[3299] = 2083; + order[3300] = 4126; + order[3301] = 1417; + order[3302] = 4378; + order[3303] = 4127; + order[3304] = 5082; + order[3305] = 476; + order[3306] = 1418; + order[3307] = 5083; + order[3308] = 4128; + order[3309] = 3018; + order[3310] = 5084; + order[3311] = 1252; + order[3312] = 1042; + order[3313] = 3775; + order[3314] = 2084; + order[3315] = 4588; + order[3316] = 3019; + order[3317] = 2495; + order[3318] = 3020; + order[3319] = 4129; + order[3320] = 5085; + order[3321] = 477; + order[3322] = 3021; + order[3323] = 2689; + order[3324] = 3642; + order[3325] = 1043; + order[3326] = 5086; + order[3327] = 1419; + order[3328] = 5087; + order[3329] = 4130; + order[3330] = 478; + order[3331] = 3643; + order[3332] = 1044; + order[3333] = 5088; + order[3334] = 1253; + order[3335] = 2496; + order[3336] = 4589; + order[3337] = 479; + order[3338] = 1420; + order[3339] = 3022; + order[3340] = 2085; + order[3341] = 3023; + order[3342] = 5089; + order[3343] = 4379; + order[3344] = 1421; + order[3345] = 1422; + order[3346] = 2086; + order[3347] = 1423; + order[3348] = 1424; + order[3349] = 1425; + order[3350] = 5090; + order[3351] = 1426; + order[3352] = 3024; + order[3353] = 740; + order[3354] = 2690; + order[3355] = 5513; + order[3356] = 1254; + order[3357] = 182; + order[3358] = 4131; + order[3359] = 4132; + order[3360] = 2691; + order[3361] = 4133; + order[3362] = 2087; + order[3363] = 2088; + order[3364] = 4134; + order[3365] = 3025; + order[3366] = 4135; + order[3367] = 480; + order[3368] = 2089; + order[3369] = 1045; + order[3370] = 4136; + order[3371] = 5514; + order[3372] = 741; + order[3373] = 3026; + order[3374] = 1427; + order[3375] = 3509; + order[3376] = 4137; + order[3377] = 3027; + order[3378] = 2090; + order[3379] = 481; + order[3380] = 3028; + order[3381] = 2497; + order[3382] = 4590; + order[3383] = 1428; + order[3384] = 2091; + order[3385] = 4380; + order[3386] = 856; + order[3387] = 1046; + order[3388] = 4591; + order[3389] = 482; + order[3390] = 1429; + order[3391] = 5091; + order[3392] = 5515; + order[3393] = 183; + order[3394] = 5516; + order[3395] = 184; + order[3396] = 4138; + order[3397] = 1047; + order[3398] = 4139; + order[3399] = 2092; + order[3400] = 1048; + order[3401] = 4140; + order[3402] = 483; + order[3403] = 4592; + order[3404] = 5092; + order[3405] = 1430; + order[3406] = 4381; + order[3407] = 1543; + order[3408] = 3029; + order[3409] = 5517; + order[3410] = 81; + order[3411] = 4141; + order[3412] = 1431; + order[3413] = 742; + order[3414] = 2093; + order[3415] = 3510; + order[3416] = 1049; + order[3417] = 2498; + order[3418] = 2499; + order[3419] = 1432; + order[3420] = 3511; + order[3421] = 1433; + order[3422] = 4142; + order[3423] = 484; + order[3424] = 4143; + order[3425] = 2094; + order[3426] = 5093; + order[3427] = 2500; + order[3428] = 743; + order[3429] = 5094; + order[3430] = 3512; + order[3431] = 2501; + order[3432] = 132; + order[3433] = 2095; + order[3434] = 5095; + order[3435] = 2692; + order[3436] = 1255; + order[3437] = 82; + order[3438] = 3776; + order[3439] = 83; + order[3440] = 3513; + order[3441] = 84; + order[3442] = 2096; + order[3443] = 5096; + order[3444] = 2097; + order[3445] = 3296; + order[3446] = 1256; + order[3447] = 485; + order[3448] = 2693; + order[3449] = 2098; + order[3450] = 5518; + order[3451] = 486; + order[3452] = 2099; + order[3453] = 85; + order[3454] = 2100; + order[3455] = 5097; + order[3456] = 2101; + order[3457] = 5098; + order[3458] = 5099; + order[3459] = 2502; + order[3460] = 2102; + order[3461] = 1050; + order[3462] = 5100; + order[3463] = 4593; + order[3464] = 3297; + order[3465] = 3298; + order[3466] = 744; + order[3467] = 3030; + order[3468] = 5101; + order[3469] = 5102; + order[3470] = 4144; + order[3471] = 5103; + order[3472] = 4594; + order[3473] = 2503; + order[3474] = 487; + order[3475] = 3299; + order[3476] = 2504; + order[3477] = 5104; + order[3478] = 3031; + order[3479] = 4595; + order[3480] = 86; + order[3481] = 2103; + order[3482] = 3777; + order[3483] = 2104; + order[3484] = 2105; + order[3485] = 4382; + order[3486] = 2694; + order[3487] = 4596; + order[3488] = 5105; + order[3489] = 1051; + order[3490] = 2106; + order[3491] = 3032; + order[3492] = 5106; + order[3493] = 488; + order[3494] = 1052; + order[3495] = 5107; + order[3496] = 2505; + order[3497] = 745; + order[3498] = 4412; + order[3499] = 746; + } + + private static void municipalitiesOrder7(int[] order) { + order[3500] = 5404; + order[3501] = 1257; + order[3502] = 747; + order[3503] = 748; + order[3504] = 1053; + order[3505] = 2107; + order[3506] = 3514; + order[3507] = 2108; + order[3508] = 3515; + order[3509] = 2109; + order[3510] = 4597; + order[3511] = 3033; + order[3512] = 4145; + order[3513] = 2110; + order[3514] = 4598; + order[3515] = 2111; + order[3516] = 2112; + order[3517] = 3516; + order[3518] = 87; + order[3519] = 5108; + order[3520] = 1054; + order[3521] = 2506; + order[3522] = 749; + order[3523] = 4599; + order[3524] = 2113; + order[3525] = 4600; + order[3526] = 750; + order[3527] = 3300; + order[3528] = 4146; + order[3529] = 5109; + order[3530] = 3034; + order[3531] = 5519; + order[3532] = 489; + order[3533] = 3035; + order[3534] = 4601; + order[3535] = 5110; + order[3536] = 4147; + order[3537] = 3517; + order[3538] = 88; + order[3539] = 3518; + order[3540] = 1258; + order[3541] = 5520; + order[3542] = 490; + order[3543] = 1055; + order[3544] = 5521; + order[3545] = 3301; + order[3546] = 5522; + order[3547] = 1056; + order[3548] = 1057; + order[3549] = 3036; + order[3550] = 5111; + order[3551] = 4148; + order[3552] = 4602; + order[3553] = 2114; + order[3554] = 3037; + order[3555] = 1058; + order[3556] = 4149; + order[3557] = 857; + order[3558] = 3302; + order[3559] = 5112; + order[3560] = 4150; + order[3561] = 89; + order[3562] = 2115; + order[3563] = 4603; + order[3564] = 3519; + order[3565] = 2116; + order[3566] = 3644; + order[3567] = 2117; + order[3568] = 751; + order[3569] = 2507; + order[3570] = 2118; + order[3571] = 5113; + order[3572] = 4151; + order[3573] = 3645; + order[3574] = 1259; + order[3575] = 5114; + order[3576] = 752; + order[3577] = 4604; + order[3578] = 5115; + order[3579] = 1544; + order[3580] = 3038; + order[3581] = 4152; + order[3582] = 5523; + order[3583] = 2119; + order[3584] = 753; + order[3585] = 491; + order[3586] = 754; + order[3587] = 3778; + order[3588] = 5524; + order[3589] = 3039; + order[3590] = 3040; + order[3591] = 1545; + order[3592] = 1059; + order[3593] = 1434; + order[3594] = 5116; + order[3595] = 3041; + order[3596] = 5117; + order[3597] = 3303; + order[3598] = 1435; + order[3599] = 3042; + order[3600] = 1546; + order[3601] = 2120; + order[3602] = 5118; + order[3603] = 2695; + order[3604] = 492; + order[3605] = 3646; + order[3606] = 3779; + order[3607] = 2508; + order[3608] = 1060; + order[3609] = 3780; + order[3610] = 5119; + order[3611] = 4153; + order[3612] = 4383; + order[3613] = 3781; + order[3614] = 90; + order[3615] = 185; + order[3616] = 493; + order[3617] = 91; + order[3618] = 5120; + order[3619] = 5121; + order[3620] = 3520; + order[3621] = 3521; + order[3622] = 3304; + order[3623] = 3782; + order[3624] = 1260; + order[3625] = 4154; + order[3626] = 3783; + order[3627] = 2121; + order[3628] = 4155; + order[3629] = 2122; + order[3630] = 2123; + order[3631] = 2124; + order[3632] = 2696; + order[3633] = 3784; + order[3634] = 1261; + order[3635] = 3522; + order[3636] = 3305; + order[3637] = 92; + order[3638] = 4605; + order[3639] = 4156; + order[3640] = 4157; + order[3641] = 2125; + order[3642] = 4606; + order[3643] = 1262; + order[3644] = 2126; + order[3645] = 3043; + order[3646] = 3044; + order[3647] = 2697; + order[3648] = 2127; + order[3649] = 3523; + order[3650] = 2128; + order[3651] = 2129; + order[3652] = 5122; + order[3653] = 3785; + order[3654] = 3647; + order[3655] = 494; + order[3656] = 2509; + order[3657] = 5525; + order[3658] = 3524; + order[3659] = 3786; + order[3660] = 3306; + order[3661] = 186; + order[3662] = 2130; + order[3663] = 3045; + order[3664] = 5123; + order[3665] = 5124; + order[3666] = 1263; + order[3667] = 2698; + order[3668] = 3307; + order[3669] = 3525; + order[3670] = 5125; + order[3671] = 2131; + order[3672] = 495; + order[3673] = 4158; + order[3674] = 5126; + order[3675] = 3046; + order[3676] = 93; + order[3677] = 4607; + order[3678] = 1264; + order[3679] = 2132; + order[3680] = 4159; + order[3681] = 3526; + order[3682] = 496; + order[3683] = 3047; + order[3684] = 2133; + order[3685] = 5127; + order[3686] = 3308; + order[3687] = 2134; + order[3688] = 5128; + order[3689] = 2135; + order[3690] = 755; + order[3691] = 2699; + order[3692] = 133; + order[3693] = 2136; + order[3694] = 2137; + order[3695] = 2138; + order[3696] = 3787; + order[3697] = 2700; + order[3698] = 5405; + order[3699] = 1436; + order[3700] = 3788; + order[3701] = 2139; + order[3702] = 5129; + order[3703] = 497; + order[3704] = 4160; + order[3705] = 2701; + order[3706] = 2140; + order[3707] = 4608; + order[3708] = 5130; + order[3709] = 5131; + order[3710] = 1265; + order[3711] = 5406; + order[3712] = 5132; + order[3713] = 2141; + order[3714] = 5526; + order[3715] = 498; + order[3716] = 3789; + order[3717] = 858; + order[3718] = 5133; + order[3719] = 1266; + order[3720] = 1547; + order[3721] = 3527; + order[3722] = 3528; + order[3723] = 2142; + order[3724] = 4161; + order[3725] = 2702; + order[3726] = 2143; + order[3727] = 3790; + order[3728] = 5527; + order[3729] = 2510; + order[3730] = 1437; + order[3731] = 4162; + order[3732] = 4163; + order[3733] = 756; + order[3734] = 1267; + order[3735] = 5134; + order[3736] = 3791; + order[3737] = 94; + order[3738] = 4609; + order[3739] = 757; + order[3740] = 2144; + order[3741] = 2145; + order[3742] = 5528; + order[3743] = 2146; + order[3744] = 2147; + order[3745] = 2148; + order[3746] = 5135; + order[3747] = 5136; + order[3748] = 758; + order[3749] = 1268; + order[3750] = 2149; + order[3751] = 4610; + order[3752] = 1269; + order[3753] = 3048; + order[3754] = 3049; + order[3755] = 3050; + order[3756] = 1061; + order[3757] = 5137; + order[3758] = 2150; + order[3759] = 4611; + order[3760] = 3309; + order[3761] = 3310; + order[3762] = 4612; + order[3763] = 3311; + order[3764] = 1062; + order[3765] = 3648; + order[3766] = 95; + order[3767] = 5138; + order[3768] = 2703; + order[3769] = 499; + order[3770] = 2151; + order[3771] = 4164; + order[3772] = 2511; + order[3773] = 3529; + order[3774] = 2704; + order[3775] = 5139; + order[3776] = 2152; + order[3777] = 2153; + order[3778] = 2154; + order[3779] = 2155; + order[3780] = 3051; + order[3781] = 500; + order[3782] = 96; + order[3783] = 2705; + order[3784] = 1063; + order[3785] = 5140; + order[3786] = 2706; + order[3787] = 3792; + order[3788] = 2707; + order[3789] = 2156; + order[3790] = 4384; + order[3791] = 3530; + order[3792] = 4385; + order[3793] = 501; + order[3794] = 5141; + order[3795] = 1270; + order[3796] = 97; + order[3797] = 502; + order[3798] = 5142; + order[3799] = 5529; + order[3800] = 759; + order[3801] = 2157; + order[3802] = 3052; + order[3803] = 4165; + order[3804] = 4166; + order[3805] = 3053; + order[3806] = 4167; + order[3807] = 3054; + order[3808] = 4613; + order[3809] = 5143; + order[3810] = 3055; + order[3811] = 5407; + order[3812] = 3649; + order[3813] = 4168; + order[3814] = 1271; + order[3815] = 4169; + order[3816] = 4614; + order[3817] = 859; + order[3818] = 503; + order[3819] = 4170; + order[3820] = 2158; + order[3821] = 3531; + order[3822] = 1272; + order[3823] = 5144; + order[3824] = 760; + order[3825] = 5145; + order[3826] = 5146; + order[3827] = 1064; + order[3828] = 2159; + order[3829] = 5147; + order[3830] = 3532; + order[3831] = 3650; + order[3832] = 504; + order[3833] = 3056; + order[3834] = 5148; + order[3835] = 2160; + order[3836] = 5149; + order[3837] = 5408; + order[3838] = 2161; + order[3839] = 5150; + order[3840] = 2162; + order[3841] = 2163; + order[3842] = 98; + order[3843] = 1065; + order[3844] = 1273; + order[3845] = 2164; + order[3846] = 4171; + order[3847] = 2165; + order[3848] = 5151; + order[3849] = 5152; + order[3850] = 3057; + order[3851] = 5530; + order[3852] = 5153; + order[3853] = 4172; + order[3854] = 5154; + order[3855] = 4615; + order[3856] = 2166; + order[3857] = 1066; + order[3858] = 1067; + order[3859] = 761; + order[3860] = 505; + order[3861] = 3533; + order[3862] = 506; + order[3863] = 2708; + order[3864] = 3058; + order[3865] = 3059; + order[3866] = 5155; + order[3867] = 2167; + order[3868] = 2709; + order[3869] = 5531; + order[3870] = 860; + order[3871] = 2168; + order[3872] = 2512; + order[3873] = 12; + order[3874] = 1068; + order[3875] = 3060; + order[3876] = 507; + order[3877] = 508; + order[3878] = 3061; + order[3879] = 4173; + order[3880] = 5156; + order[3881] = 4616; + order[3882] = 1438; + order[3883] = 2169; + order[3884] = 5157; + order[3885] = 5158; + order[3886] = 3312; + order[3887] = 1274; + order[3888] = 2710; + order[3889] = 3793; + order[3890] = 2711; + order[3891] = 4174; + order[3892] = 99; + order[3893] = 2712; + order[3894] = 2170; + order[3895] = 5409; + order[3896] = 5410; + order[3897] = 509; + order[3898] = 1439; + order[3899] = 2171; + order[3900] = 2172; + order[3901] = 510; + order[3902] = 5159; + order[3903] = 2713; + order[3904] = 3313; + order[3905] = 4617; + order[3906] = 5160; + order[3907] = 2173; + order[3908] = 5161; + order[3909] = 2513; + order[3910] = 3062; + order[3911] = 1548; + order[3912] = 5162; + order[3913] = 1440; + order[3914] = 3063; + order[3915] = 1069; + order[3916] = 5163; + order[3917] = 4175; + order[3918] = 4618; + order[3919] = 5532; + order[3920] = 4619; + order[3921] = 5533; + order[3922] = 1441; + order[3923] = 2174; + order[3924] = 4176; + order[3925] = 4620; + order[3926] = 1442; + order[3927] = 5164; + order[3928] = 861; + order[3929] = 2175; + order[3930] = 2176; + order[3931] = 511; + order[3932] = 5165; + order[3933] = 762; + order[3934] = 5166; + order[3935] = 1070; + order[3936] = 3651; + order[3937] = 3064; + order[3938] = 3794; + order[3939] = 4177; + order[3940] = 1071; + order[3941] = 763; + order[3942] = 2177; + order[3943] = 2514; + order[3944] = 1072; + order[3945] = 3534; + order[3946] = 13; + order[3947] = 4178; + order[3948] = 1443; + order[3949] = 3535; + order[3950] = 5534; + order[3951] = 3065; + order[3952] = 3066; + order[3953] = 4621; + order[3954] = 100; + order[3955] = 5411; + order[3956] = 2515; + order[3957] = 101; + order[3958] = 3795; + order[3959] = 1444; + order[3960] = 1445; + order[3961] = 1446; + order[3962] = 5167; + order[3963] = 5168; + order[3964] = 2178; + order[3965] = 1275; + order[3966] = 134; + order[3967] = 4179; + order[3968] = 4180; + order[3969] = 1549; + order[3970] = 5535; + order[3971] = 3652; + order[3972] = 102; + order[3973] = 3067; + order[3974] = 1276; + order[3975] = 512; + order[3976] = 4622; + order[3977] = 4386; + order[3978] = 4181; + order[3979] = 3068; + order[3980] = 14; + order[3981] = 4182; + order[3982] = 1073; + order[3983] = 2179; + order[3984] = 764; + order[3985] = 5169; + order[3986] = 513; + order[3987] = 5170; + order[3988] = 765; + order[3989] = 2180; + order[3990] = 2181; + order[3991] = 4183; + order[3992] = 4623; + order[3993] = 1447; + order[3994] = 5171; + order[3995] = 135; + order[3996] = 514; + order[3997] = 3069; + order[3998] = 5172; + order[3999] = 2182; + } + + private static void municipalitiesOrder8(int[] order) { + order[4000] = 4624; + order[4001] = 5173; + order[4002] = 5536; + order[4003] = 2516; + order[4004] = 3070; + order[4005] = 2183; + order[4006] = 2714; + order[4007] = 3536; + order[4008] = 5174; + order[4009] = 2184; + order[4010] = 2185; + order[4011] = 5175; + order[4012] = 2186; + order[4013] = 5176; + order[4014] = 4625; + order[4015] = 3071; + order[4016] = 515; + order[4017] = 1277; + order[4018] = 5177; + order[4019] = 187; + order[4020] = 4626; + order[4021] = 516; + order[4022] = 1278; + order[4023] = 2187; + order[4024] = 862; + order[4025] = 5537; + order[4026] = 2188; + order[4027] = 4184; + order[4028] = 1279; + order[4029] = 4387; + order[4030] = 4627; + order[4031] = 2189; + order[4032] = 5178; + order[4033] = 1280; + order[4034] = 517; + order[4035] = 1281; + order[4036] = 5179; + order[4037] = 2517; + order[4038] = 3314; + order[4039] = 4388; + order[4040] = 1448; + order[4041] = 1282; + order[4042] = 3072; + order[4043] = 4628; + order[4044] = 2715; + order[4045] = 1074; + order[4046] = 4185; + order[4047] = 5180; + order[4048] = 5412; + order[4049] = 4186; + order[4050] = 2190; + order[4051] = 3073; + order[4052] = 5538; + order[4053] = 3796; + order[4054] = 4187; + order[4055] = 2716; + order[4056] = 5181; + order[4057] = 4188; + order[4058] = 2191; + order[4059] = 3074; + order[4060] = 5182; + order[4061] = 3075; + order[4062] = 2518; + order[4063] = 3653; + order[4064] = 3076; + order[4065] = 4189; + order[4066] = 3077; + order[4067] = 103; + order[4068] = 3078; + order[4069] = 3537; + order[4070] = 518; + order[4071] = 2717; + order[4072] = 3654; + order[4073] = 5183; + order[4074] = 5184; + order[4075] = 2192; + order[4076] = 1449; + order[4077] = 3079; + order[4078] = 4190; + order[4079] = 519; + order[4080] = 4629; + order[4081] = 3080; + order[4082] = 5185; + order[4083] = 4191; + order[4084] = 3315; + order[4085] = 1075; + order[4086] = 3655; + order[4087] = 3081; + order[4088] = 766; + order[4089] = 2718; + order[4090] = 3316; + order[4091] = 520; + order[4092] = 767; + order[4093] = 768; + order[4094] = 769; + order[4095] = 770; + order[4096] = 3797; + order[4097] = 3798; + order[4098] = 521; + order[4099] = 5186; + order[4100] = 3082; + order[4101] = 5187; + order[4102] = 3083; + order[4103] = 3084; + order[4104] = 4630; + order[4105] = 1283; + order[4106] = 2193; + order[4107] = 2194; + order[4108] = 3085; + order[4109] = 3086; + order[4110] = 3317; + order[4111] = 2195; + order[4112] = 5539; + order[4113] = 771; + order[4114] = 2519; + order[4115] = 5188; + order[4116] = 3538; + order[4117] = 4192; + order[4118] = 2196; + order[4119] = 3539; + order[4120] = 5189; + order[4121] = 5190; + order[4122] = 5191; + order[4123] = 4193; + order[4124] = 522; + order[4125] = 2719; + order[4126] = 3087; + order[4127] = 772; + order[4128] = 3656; + order[4129] = 2197; + order[4130] = 3088; + order[4131] = 1450; + order[4132] = 3089; + order[4133] = 2198; + order[4134] = 2199; + order[4135] = 5192; + order[4136] = 4194; + order[4137] = 523; + order[4138] = 1284; + order[4139] = 2720; + order[4140] = 524; + order[4141] = 2721; + order[4142] = 5413; + order[4143] = 525; + order[4144] = 2722; + order[4145] = 2200; + order[4146] = 5540; + order[4147] = 3799; + order[4148] = 3318; + order[4149] = 526; + order[4150] = 3800; + order[4151] = 2723; + order[4152] = 2724; + order[4153] = 2201; + order[4154] = 3540; + order[4155] = 3801; + order[4156] = 5414; + order[4157] = 1076; + order[4158] = 1077; + order[4159] = 1285; + order[4160] = 1550; + order[4161] = 5193; + order[4162] = 527; + order[4163] = 3541; + order[4164] = 528; + order[4165] = 3319; + order[4166] = 5194; + order[4167] = 5195; + order[4168] = 1451; + order[4169] = 3090; + order[4170] = 5196; + order[4171] = 2202; + order[4172] = 529; + order[4173] = 3091; + order[4174] = 5197; + order[4175] = 5198; + order[4176] = 5199; + order[4177] = 5200; + order[4178] = 5201; + order[4179] = 2203; + order[4180] = 1452; + order[4181] = 3542; + order[4182] = 5415; + order[4183] = 5202; + order[4184] = 5203; + order[4185] = 5204; + order[4186] = 2204; + order[4187] = 3092; + order[4188] = 863; + order[4189] = 3093; + order[4190] = 3657; + order[4191] = 3094; + order[4192] = 15; + order[4193] = 1453; + order[4194] = 3095; + order[4195] = 3096; + order[4196] = 1551; + order[4197] = 2205; + order[4198] = 3658; + order[4199] = 5205; + order[4200] = 4389; + order[4201] = 5541; + order[4202] = 4631; + order[4203] = 3659; + order[4204] = 3660; + order[4205] = 5206; + order[4206] = 530; + order[4207] = 3661; + order[4208] = 531; + order[4209] = 4632; + order[4210] = 3802; + order[4211] = 4633; + order[4212] = 532; + order[4213] = 2206; + order[4214] = 4634; + order[4215] = 2207; + order[4216] = 5542; + order[4217] = 4635; + order[4218] = 4195; + order[4219] = 2208; + order[4220] = 3320; + order[4221] = 4636; + order[4222] = 4196; + order[4223] = 5207; + order[4224] = 3543; + order[4225] = 104; + order[4226] = 2209; + order[4227] = 2520; + order[4228] = 4637; + order[4229] = 1552; + order[4230] = 3097; + order[4231] = 2210; + order[4232] = 864; + order[4233] = 2211; + order[4234] = 4197; + order[4235] = 2212; + order[4236] = 2213; + order[4237] = 2214; + order[4238] = 2215; + order[4239] = 188; + order[4240] = 1078; + order[4241] = 533; + order[4242] = 4638; + order[4243] = 5543; + order[4244] = 2725; + order[4245] = 1079; + order[4246] = 1553; + order[4247] = 2216; + order[4248] = 5208; + order[4249] = 4198; + order[4250] = 4639; + order[4251] = 2217; + order[4252] = 5209; + order[4253] = 4199; + order[4254] = 1554; + order[4255] = 2218; + order[4256] = 4640; + order[4257] = 4200; + order[4258] = 2219; + order[4259] = 534; + order[4260] = 3803; + order[4261] = 16; + order[4262] = 4201; + order[4263] = 3098; + order[4264] = 4202; + order[4265] = 4390; + order[4266] = 2220; + order[4267] = 4641; + order[4268] = 3099; + order[4269] = 4203; + order[4270] = 4204; + order[4271] = 1454; + order[4272] = 3100; + order[4273] = 2521; + order[4274] = 1455; + order[4275] = 4205; + order[4276] = 4413; + order[4277] = 5210; + order[4278] = 1286; + order[4279] = 2221; + order[4280] = 5416; + order[4281] = 3101; + order[4282] = 4206; + order[4283] = 1456; + order[4284] = 5211; + order[4285] = 105; + order[4286] = 2222; + order[4287] = 5212; + order[4288] = 1080; + order[4289] = 2223; + order[4290] = 5213; + order[4291] = 2522; + order[4292] = 773; + order[4293] = 535; + order[4294] = 3804; + order[4295] = 2224; + order[4296] = 3102; + order[4297] = 5214; + order[4298] = 2225; + order[4299] = 774; + order[4300] = 2226; + order[4301] = 4207; + order[4302] = 5215; + order[4303] = 3321; + order[4304] = 4208; + order[4305] = 5216; + order[4306] = 5217; + order[4307] = 5218; + order[4308] = 4642; + order[4309] = 2726; + order[4310] = 3322; + order[4311] = 5417; + order[4312] = 2727; + order[4313] = 3103; + order[4314] = 3323; + order[4315] = 2227; + order[4316] = 536; + order[4317] = 2523; + order[4318] = 775; + order[4319] = 5219; + order[4320] = 3324; + order[4321] = 4643; + order[4322] = 5220; + order[4323] = 5221; + order[4324] = 2228; + order[4325] = 5222; + order[4326] = 1457; + order[4327] = 3104; + order[4328] = 4209; + order[4329] = 3105; + order[4330] = 5223; + order[4331] = 4644; + order[4332] = 537; + order[4333] = 4210; + order[4334] = 4211; + order[4335] = 2524; + order[4336] = 1287; + order[4337] = 5544; + order[4338] = 4212; + order[4339] = 1081; + order[4340] = 5545; + order[4341] = 5224; + order[4342] = 4645; + order[4343] = 3325; + order[4344] = 4213; + order[4345] = 5225; + order[4346] = 5226; + order[4347] = 3106; + order[4348] = 538; + order[4349] = 2229; + order[4350] = 5227; + order[4351] = 1082; + order[4352] = 2230; + order[4353] = 2231; + order[4354] = 2525; + order[4355] = 4214; + order[4356] = 2232; + order[4357] = 5228; + order[4358] = 539; + order[4359] = 1458; + order[4360] = 2728; + order[4361] = 4646; + order[4362] = 3107; + order[4363] = 4215; + order[4364] = 5229; + order[4365] = 4216; + order[4366] = 2729; + order[4367] = 3326; + order[4368] = 3805; + order[4369] = 540; + order[4370] = 3327; + order[4371] = 5230; + order[4372] = 5231; + order[4373] = 541; + order[4374] = 5232; + order[4375] = 1083; + order[4376] = 2233; + order[4377] = 3108; + order[4378] = 2234; + order[4379] = 2526; + order[4380] = 3328; + order[4381] = 2235; + order[4382] = 3544; + order[4383] = 5233; + order[4384] = 4217; + order[4385] = 1459; + order[4386] = 3545; + order[4387] = 2236; + order[4388] = 5234; + order[4389] = 3109; + order[4390] = 1084; + order[4391] = 2237; + order[4392] = 5546; + order[4393] = 5235; + order[4394] = 3329; + order[4395] = 3546; + order[4396] = 1288; + order[4397] = 5236; + order[4398] = 1289; + order[4399] = 2730; + order[4400] = 3110; + order[4401] = 4647; + order[4402] = 1085; + order[4403] = 2238; + order[4404] = 542; + order[4405] = 1290; + order[4406] = 2731; + order[4407] = 3111; + order[4408] = 1086; + order[4409] = 5237; + order[4410] = 3112; + order[4411] = 189; + order[4412] = 3113; + order[4413] = 2527; + order[4414] = 2239; + order[4415] = 865; + order[4416] = 3114; + order[4417] = 5238; + order[4418] = 3547; + order[4419] = 543; + order[4420] = 1291; + order[4421] = 2240; + order[4422] = 2732; + order[4423] = 4391; + order[4424] = 5418; + order[4425] = 106; + order[4426] = 2528; + order[4427] = 1292; + order[4428] = 2241; + order[4429] = 4218; + order[4430] = 3806; + order[4431] = 4219; + order[4432] = 3330; + order[4433] = 5239; + order[4434] = 544; + order[4435] = 2529; + order[4436] = 2242; + order[4437] = 866; + order[4438] = 3331; + order[4439] = 4220; + order[4440] = 3115; + order[4441] = 2530; + order[4442] = 2243; + order[4443] = 2244; + order[4444] = 5547; + order[4445] = 3662; + order[4446] = 3116; + order[4447] = 5240; + order[4448] = 3117; + order[4449] = 776; + order[4450] = 1293; + order[4451] = 1294; + order[4452] = 2733; + order[4453] = 5241; + order[4454] = 2245; + order[4455] = 545; + order[4456] = 2246; + order[4457] = 2247; + order[4458] = 2248; + order[4459] = 1087; + order[4460] = 2249; + order[4461] = 1088; + order[4462] = 1555; + order[4463] = 5242; + order[4464] = 2250; + order[4465] = 5548; + order[4466] = 1460; + order[4467] = 4221; + order[4468] = 2251; + order[4469] = 1089; + order[4470] = 4648; + order[4471] = 5419; + order[4472] = 5243; + order[4473] = 3548; + order[4474] = 17; + order[4475] = 4649; + order[4476] = 5549; + order[4477] = 5244; + order[4478] = 867; + order[4479] = 2734; + order[4480] = 4222; + order[4481] = 1090; + order[4482] = 3118; + order[4483] = 5550; + order[4484] = 546; + order[4485] = 1461; + order[4486] = 3332; + order[4487] = 4650; + order[4488] = 1091; + order[4489] = 3119; + order[4490] = 4651; + order[4491] = 5551; + order[4492] = 2252; + order[4493] = 4223; + order[4494] = 547; + order[4495] = 136; + order[4496] = 548; + order[4497] = 4224; + order[4498] = 5245; + order[4499] = 2253; + } + + private static void municipalitiesOrder9(int[] order) { + order[4500] = 2254; + order[4501] = 2735; + order[4502] = 5246; + order[4503] = 2255; + order[4504] = 777; + order[4505] = 2531; + order[4506] = 778; + order[4507] = 2256; + order[4508] = 2257; + order[4509] = 107; + order[4510] = 3120; + order[4511] = 2258; + order[4512] = 2259; + order[4513] = 1295; + order[4514] = 3807; + order[4515] = 108; + order[4516] = 2260; + order[4517] = 3549; + order[4518] = 2261; + order[4519] = 5420; + order[4520] = 3808; + order[4521] = 2736; + order[4522] = 2262; + order[4523] = 549; + order[4524] = 2532; + order[4525] = 2533; + order[4526] = 4225; + order[4527] = 4652; + order[4528] = 1462; + order[4529] = 550; + order[4530] = 4653; + order[4531] = 5421; + order[4532] = 1296; + order[4533] = 5247; + order[4534] = 2737; + order[4535] = 5248; + order[4536] = 4226; + order[4537] = 3809; + order[4538] = 5249; + order[4539] = 1092; + order[4540] = 4227; + order[4541] = 3121; + order[4542] = 4228; + order[4543] = 1093; + order[4544] = 551; + order[4545] = 1463; + order[4546] = 3550; + order[4547] = 3663; + order[4548] = 5250; + order[4549] = 2263; + order[4550] = 5251; + order[4551] = 2264; + order[4552] = 3122; + order[4553] = 1094; + order[4554] = 2265; + order[4555] = 190; + order[4556] = 2266; + order[4557] = 2267; + order[4558] = 5252; + order[4559] = 1464; + order[4560] = 2268; + order[4561] = 4229; + order[4562] = 3123; + order[4563] = 5253; + order[4564] = 4230; + order[4565] = 2269; + order[4566] = 2270; + order[4567] = 3124; + order[4568] = 2534; + order[4569] = 1297; + order[4570] = 3551; + order[4571] = 4231; + order[4572] = 4232; + order[4573] = 552; + order[4574] = 5254; + order[4575] = 4233; + order[4576] = 2271; + order[4577] = 3125; + order[4578] = 3552; + order[4579] = 5255; + order[4580] = 5256; + order[4581] = 2272; + order[4582] = 779; + order[4583] = 1298; + order[4584] = 3333; + order[4585] = 2738; + order[4586] = 1299; + order[4587] = 2739; + order[4588] = 2273; + order[4589] = 3810; + order[4590] = 5257; + order[4591] = 4654; + order[4592] = 5552; + order[4593] = 3811; + order[4594] = 3334; + order[4595] = 4655; + order[4596] = 1300; + order[4597] = 5258; + order[4598] = 4656; + order[4599] = 4234; + order[4600] = 109; + order[4601] = 2274; + order[4602] = 3553; + order[4603] = 2535; + order[4604] = 5259; + order[4605] = 3335; + order[4606] = 4657; + order[4607] = 5260; + order[4608] = 3126; + order[4609] = 5422; + order[4610] = 4658; + order[4611] = 553; + order[4612] = 554; + order[4613] = 1095; + order[4614] = 2740; + order[4615] = 4659; + order[4616] = 5423; + order[4617] = 2275; + order[4618] = 2536; + order[4619] = 1301; + order[4620] = 2537; + order[4621] = 2741; + order[4622] = 1302; + order[4623] = 868; + order[4624] = 2276; + order[4625] = 4235; + order[4626] = 555; + order[4627] = 4392; + order[4628] = 556; + order[4629] = 1303; + order[4630] = 2277; + order[4631] = 1465; + order[4632] = 557; + order[4633] = 3554; + order[4634] = 5553; + order[4635] = 2538; + order[4636] = 3812; + order[4637] = 3664; + order[4638] = 2278; + order[4639] = 2742; + order[4640] = 5261; + order[4641] = 5424; + order[4642] = 4236; + order[4643] = 3555; + order[4644] = 1096; + order[4645] = 3665; + order[4646] = 2279; + order[4647] = 4237; + order[4648] = 2280; + order[4649] = 1304; + order[4650] = 558; + order[4651] = 2281; + order[4652] = 4393; + order[4653] = 1305; + order[4654] = 3813; + order[4655] = 2539; + order[4656] = 3556; + order[4657] = 4660; + order[4658] = 559; + order[4659] = 4238; + order[4660] = 191; + order[4661] = 869; + order[4662] = 1556; + order[4663] = 2282; + order[4664] = 2283; + order[4665] = 2540; + order[4666] = 2284; + order[4667] = 3666; + order[4668] = 2285; + order[4669] = 780; + order[4670] = 3814; + order[4671] = 3557; + order[4672] = 2286; + order[4673] = 3558; + order[4674] = 2287; + order[4675] = 2288; + order[4676] = 2289; + order[4677] = 560; + order[4678] = 2290; + order[4679] = 4239; + order[4680] = 3127; + order[4681] = 3128; + order[4682] = 3336; + order[4683] = 1306; + order[4684] = 4661; + order[4685] = 2291; + order[4686] = 1097; + order[4687] = 4414; + order[4688] = 3667; + order[4689] = 5262; + order[4690] = 3559; + order[4691] = 3560; + order[4692] = 2292; + order[4693] = 2293; + order[4694] = 1098; + order[4695] = 2541; + order[4696] = 2294; + order[4697] = 3561; + order[4698] = 4240; + order[4699] = 3562; + order[4700] = 5263; + order[4701] = 2295; + order[4702] = 5264; + order[4703] = 3668; + order[4704] = 2542; + order[4705] = 2296; + order[4706] = 2543; + order[4707] = 3563; + order[4708] = 3129; + order[4709] = 2743; + order[4710] = 1307; + order[4711] = 4662; + order[4712] = 3130; + order[4713] = 781; + order[4714] = 2297; + order[4715] = 2298; + order[4716] = 4663; + order[4717] = 2299; + order[4718] = 2300; + order[4719] = 1308; + order[4720] = 2301; + order[4721] = 5265; + order[4722] = 3564; + order[4723] = 4241; + order[4724] = 2744; + order[4725] = 3815; + order[4726] = 1309; + order[4727] = 4664; + order[4728] = 2745; + order[4729] = 3131; + order[4730] = 1310; + order[4731] = 2302; + order[4732] = 2303; + order[4733] = 4665; + order[4734] = 5266; + order[4735] = 2304; + order[4736] = 3337; + order[4737] = 4242; + order[4738] = 3132; + order[4739] = 3133; + order[4740] = 3134; + order[4741] = 4666; + order[4742] = 2305; + order[4743] = 5267; + order[4744] = 3135; + order[4745] = 3338; + order[4746] = 2746; + order[4747] = 110; + order[4748] = 2306; + order[4749] = 2307; + order[4750] = 111; + order[4751] = 2308; + order[4752] = 561; + order[4753] = 4243; + order[4754] = 3136; + order[4755] = 2747; + order[4756] = 2748; + order[4757] = 3816; + order[4758] = 2749; + order[4759] = 2750; + order[4760] = 1311; + order[4761] = 3669; + order[4762] = 2309; + order[4763] = 5268; + order[4764] = 3339; + order[4765] = 2751; + order[4766] = 2752; + order[4767] = 870; + order[4768] = 3817; + order[4769] = 4667; + order[4770] = 4668; + order[4771] = 2310; + order[4772] = 3565; + order[4773] = 3340; + order[4774] = 2311; + order[4775] = 4244; + order[4776] = 4245; + order[4777] = 4246; + order[4778] = 562; + order[4779] = 2312; + order[4780] = 2313; + order[4781] = 4247; + order[4782] = 4248; + order[4783] = 3566; + order[4784] = 3567; + order[4785] = 1466; + order[4786] = 1467; + order[4787] = 5269; + order[4788] = 5270; + order[4789] = 2753; + order[4790] = 3818; + order[4791] = 4249; + order[4792] = 3670; + order[4793] = 1468; + order[4794] = 4250; + order[4795] = 1312; + order[4796] = 5271; + order[4797] = 2754; + order[4798] = 3137; + order[4799] = 1469; + order[4800] = 2755; + order[4801] = 3568; + order[4802] = 4251; + order[4803] = 2314; + order[4804] = 3341; + order[4805] = 5272; + order[4806] = 4669; + order[4807] = 3569; + order[4808] = 4252; + order[4809] = 4670; + order[4810] = 1313; + order[4811] = 1099; + order[4812] = 782; + order[4813] = 3570; + order[4814] = 112; + order[4815] = 1314; + order[4816] = 4415; + order[4817] = 1100; + order[4818] = 5273; + order[4819] = 4253; + order[4820] = 2756; + order[4821] = 3138; + order[4822] = 5274; + order[4823] = 4254; + order[4824] = 4255; + order[4825] = 4671; + order[4826] = 4256; + order[4827] = 871; + order[4828] = 1315; + order[4829] = 3139; + order[4830] = 3819; + order[4831] = 5275; + order[4832] = 3571; + order[4833] = 4672; + order[4834] = 563; + order[4835] = 4257; + order[4836] = 2757; + order[4837] = 5425; + order[4838] = 2315; + order[4839] = 1101; + order[4840] = 3572; + order[4841] = 3820; + order[4842] = 2544; + order[4843] = 4394; + order[4844] = 3140; + order[4845] = 4673; + order[4846] = 1102; + order[4847] = 3573; + order[4848] = 5554; + order[4849] = 113; + order[4850] = 114; + order[4851] = 4258; + order[4852] = 1103; + order[4853] = 5276; + order[4854] = 4259; + order[4855] = 192; + order[4856] = 3821; + order[4857] = 3822; + order[4858] = 5277; + order[4859] = 1316; + order[4860] = 3671; + order[4861] = 1470; + order[4862] = 4260; + order[4863] = 2316; + order[4864] = 4261; + order[4865] = 4674; + order[4866] = 4262; + order[4867] = 3141; + order[4868] = 3142; + order[4869] = 3143; + order[4870] = 3574; + order[4871] = 2317; + order[4872] = 4263; + order[4873] = 5278; + order[4874] = 1317; + order[4875] = 2318; + order[4876] = 3823; + order[4877] = 1318; + order[4878] = 1319; + order[4879] = 3575; + order[4880] = 1320; + order[4881] = 2319; + order[4882] = 5279; + order[4883] = 2320; + order[4884] = 872; + order[4885] = 5555; + order[4886] = 115; + order[4887] = 5280; + order[4888] = 3144; + order[4889] = 2321; + order[4890] = 2545; + order[4891] = 5281; + order[4892] = 2322; + order[4893] = 2758; + order[4894] = 3672; + order[4895] = 2323; + order[4896] = 4264; + order[4897] = 2324; + order[4898] = 2325; + order[4899] = 2326; + order[4900] = 564; + order[4901] = 2327; + order[4902] = 2328; + order[4903] = 5556; + order[4904] = 193; + order[4905] = 2759; + order[4906] = 4265; + order[4907] = 1104; + order[4908] = 5282; + order[4909] = 2329; + order[4910] = 2330; + order[4911] = 3145; + order[4912] = 3824; + order[4913] = 2331; + order[4914] = 4266; + order[4915] = 4267; + order[4916] = 5557; + order[4917] = 4268; + order[4918] = 4269; + order[4919] = 3825; + order[4920] = 5283; + order[4921] = 2332; + order[4922] = 2760; + order[4923] = 4270; + order[4924] = 1321; + order[4925] = 3342; + order[4926] = 2761; + order[4927] = 565; + order[4928] = 1471; + order[4929] = 4271; + order[4930] = 3146; + order[4931] = 2333; + order[4932] = 2546; + order[4933] = 3673; + order[4934] = 4272; + order[4935] = 3674; + order[4936] = 3147; + order[4937] = 4273; + order[4938] = 5284; + order[4939] = 2334; + order[4940] = 5285; + order[4941] = 2335; + order[4942] = 566; + order[4943] = 116; + order[4944] = 1322; + order[4945] = 567; + order[4946] = 3148; + order[4947] = 4675; + order[4948] = 568; + order[4949] = 4676; + order[4950] = 569; + order[4951] = 4677; + order[4952] = 5286; + order[4953] = 3576; + order[4954] = 570; + order[4955] = 3577; + order[4956] = 4274; + order[4957] = 4275; + order[4958] = 4276; + order[4959] = 4277; + order[4960] = 1557; + order[4961] = 2336; + order[4962] = 18; + order[4963] = 1323; + order[4964] = 2337; + order[4965] = 1105; + order[4966] = 2338; + order[4967] = 3826; + order[4968] = 2339; + order[4969] = 3827; + order[4970] = 19; + order[4971] = 2340; + order[4972] = 2547; + order[4973] = 1324; + order[4974] = 2341; + order[4975] = 783; + order[4976] = 117; + order[4977] = 784; + order[4978] = 4278; + order[4979] = 3149; + order[4980] = 571; + order[4981] = 2342; + order[4982] = 2343; + order[4983] = 2344; + order[4984] = 4279; + order[4985] = 572; + order[4986] = 4280; + order[4987] = 2345; + order[4988] = 4395; + order[4989] = 4281; + order[4990] = 2346; + order[4991] = 3675; + order[4992] = 873; + order[4993] = 4678; + order[4994] = 5287; + order[4995] = 2347; + order[4996] = 2762; + order[4997] = 3828; + order[4998] = 2763; + order[4999] = 2348; + } + + private static void municipalitiesOrder10(int[] order) { + order[5000] = 3829; + order[5001] = 3830; + order[5002] = 137; + order[5003] = 573; + order[5004] = 2349; + order[5005] = 2350; + order[5006] = 574; + order[5007] = 2764; + order[5008] = 5288; + order[5009] = 3831; + order[5010] = 1472; + order[5011] = 575; + order[5012] = 2765; + order[5013] = 3343; + order[5014] = 5289; + order[5015] = 2351; + order[5016] = 1325; + order[5017] = 1106; + order[5018] = 2352; + order[5019] = 3150; + order[5020] = 2353; + order[5021] = 2766; + order[5022] = 576; + order[5023] = 3832; + order[5024] = 3833; + order[5025] = 3344; + order[5026] = 2354; + order[5027] = 577; + order[5028] = 3151; + order[5029] = 3345; + order[5030] = 3152; + order[5031] = 4282; + order[5032] = 4283; + order[5033] = 2767; + order[5034] = 5290; + order[5035] = 5291; + order[5036] = 4284; + order[5037] = 2355; + order[5038] = 1558; + order[5039] = 2356; + order[5040] = 4285; + order[5041] = 3834; + order[5042] = 5292; + order[5043] = 4679; + order[5044] = 1559; + order[5045] = 3578; + order[5046] = 3676; + order[5047] = 1107; + order[5048] = 5558; + order[5049] = 4286; + order[5050] = 2357; + order[5051] = 5293; + order[5052] = 194; + order[5053] = 2358; + order[5054] = 5426; + order[5055] = 2359; + order[5056] = 3579; + order[5057] = 578; + order[5058] = 1108; + order[5059] = 2360; + order[5060] = 3580; + order[5061] = 4287; + order[5062] = 1473; + order[5063] = 3153; + order[5064] = 3346; + order[5065] = 5427; + order[5066] = 1109; + order[5067] = 579; + order[5068] = 580; + order[5069] = 1326; + order[5070] = 3835; + order[5071] = 5559; + order[5072] = 581; + order[5073] = 4288; + order[5074] = 2768; + order[5075] = 785; + order[5076] = 2361; + order[5077] = 5294; + order[5078] = 3581; + order[5079] = 2769; + order[5080] = 2770; + order[5081] = 4289; + order[5082] = 2362; + order[5083] = 3347; + order[5084] = 786; + order[5085] = 4680; + order[5086] = 1560; + order[5087] = 874; + order[5088] = 5295; + order[5089] = 1474; + order[5090] = 2771; + order[5091] = 2548; + order[5092] = 2772; + order[5093] = 582; + order[5094] = 5560; + order[5095] = 1327; + order[5096] = 1328; + order[5097] = 5296; + order[5098] = 4681; + order[5099] = 3154; + order[5100] = 5297; + order[5101] = 2773; + order[5102] = 3677; + order[5103] = 3348; + order[5104] = 3582; + order[5105] = 5298; + order[5106] = 5299; + order[5107] = 4290; + order[5108] = 1475; + order[5109] = 5300; + order[5110] = 195; + order[5111] = 5301; + order[5112] = 3349; + order[5113] = 5302; + order[5114] = 5561; + order[5115] = 583; + order[5116] = 3836; + order[5117] = 2363; + order[5118] = 787; + order[5119] = 3350; + order[5120] = 3351; + order[5121] = 5303; + order[5122] = 2774; + order[5123] = 1561; + order[5124] = 5304; + order[5125] = 5562; + order[5126] = 5305; + order[5127] = 2549; + order[5128] = 4682; + order[5129] = 2364; + order[5130] = 5563; + order[5131] = 3837; + order[5132] = 5306; + order[5133] = 5564; + order[5134] = 3352; + order[5135] = 3155; + order[5136] = 5307; + order[5137] = 3156; + order[5138] = 788; + order[5139] = 3583; + order[5140] = 5308; + order[5141] = 3838; + order[5142] = 4683; + order[5143] = 1476; + order[5144] = 3678; + order[5145] = 584; + order[5146] = 118; + order[5147] = 3584; + order[5148] = 585; + order[5149] = 586; + order[5150] = 2365; + order[5151] = 196; + order[5152] = 3157; + order[5153] = 4291; + order[5154] = 4292; + order[5155] = 587; + order[5156] = 2775; + order[5157] = 4293; + order[5158] = 2366; + order[5159] = 3158; + order[5160] = 2367; + order[5161] = 5309; + order[5162] = 588; + order[5163] = 5310; + order[5164] = 1477; + order[5165] = 4294; + order[5166] = 2368; + order[5167] = 5311; + order[5168] = 1110; + order[5169] = 119; + order[5170] = 4295; + order[5171] = 5312; + order[5172] = 3353; + order[5173] = 5313; + order[5174] = 5314; + order[5175] = 4296; + order[5176] = 1562; + order[5177] = 5315; + order[5178] = 20; + order[5179] = 789; + order[5180] = 138; + order[5181] = 5316; + order[5182] = 2369; + order[5183] = 1329; + order[5184] = 5317; + order[5185] = 790; + order[5186] = 5318; + order[5187] = 2776; + order[5188] = 4297; + order[5189] = 197; + order[5190] = 2777; + order[5191] = 589; + order[5192] = 3159; + order[5193] = 2370; + order[5194] = 4396; + order[5195] = 791; + order[5196] = 5319; + order[5197] = 3160; + order[5198] = 5428; + order[5199] = 3839; + order[5200] = 3840; + order[5201] = 4298; + order[5202] = 2778; + order[5203] = 590; + order[5204] = 5320; + order[5205] = 591; + order[5206] = 2371; + order[5207] = 592; + order[5208] = 120; + order[5209] = 1563; + order[5210] = 3585; + order[5211] = 1111; + order[5212] = 3679; + order[5213] = 3354; + order[5214] = 1112; + order[5215] = 2550; + order[5216] = 3161; + order[5217] = 4299; + order[5218] = 593; + order[5219] = 3355; + order[5220] = 1478; + order[5221] = 3162; + order[5222] = 3163; + order[5223] = 5321; + order[5224] = 2551; + order[5225] = 1479; + order[5226] = 4300; + order[5227] = 4397; + order[5228] = 792; + order[5229] = 3164; + order[5230] = 3841; + order[5231] = 3842; + order[5232] = 5322; + order[5233] = 4684; + order[5234] = 4685; + order[5235] = 3165; + order[5236] = 3356; + order[5237] = 3843; + order[5238] = 4686; + order[5239] = 1330; + order[5240] = 4687; + order[5241] = 4688; + order[5242] = 5323; + order[5243] = 1331; + order[5244] = 2372; + order[5245] = 4301; + order[5246] = 2373; + order[5247] = 4302; + order[5248] = 2374; + order[5249] = 5429; + order[5250] = 5565; + order[5251] = 5566; + order[5252] = 2375; + order[5253] = 2376; + order[5254] = 2377; + order[5255] = 3166; + order[5256] = 5430; + order[5257] = 3167; + order[5258] = 2378; + order[5259] = 2552; + order[5260] = 198; + order[5261] = 3357; + order[5262] = 1480; + order[5263] = 4303; + order[5264] = 5324; + order[5265] = 4304; + order[5266] = 5325; + order[5267] = 3844; + order[5268] = 5326; + order[5269] = 2553; + order[5270] = 3358; + order[5271] = 121; + order[5272] = 2554; + order[5273] = 793; + order[5274] = 3680; + order[5275] = 4305; + order[5276] = 4306; + order[5277] = 594; + order[5278] = 5327; + order[5279] = 4307; + order[5280] = 4689; + order[5281] = 3168; + order[5282] = 4308; + order[5283] = 2379; + order[5284] = 4309; + order[5285] = 4310; + order[5286] = 4311; + order[5287] = 5328; + order[5288] = 1564; + order[5289] = 2380; + order[5290] = 4312; + order[5291] = 4313; + order[5292] = 2381; + order[5293] = 1113; + order[5294] = 3681; + order[5295] = 4690; + order[5296] = 4691; + order[5297] = 4692; + order[5298] = 1114; + order[5299] = 3359; + order[5300] = 4314; + order[5301] = 2779; + order[5302] = 3360; + order[5303] = 4315; + order[5304] = 3845; + order[5305] = 1332; + order[5306] = 1115; + order[5307] = 4693; + order[5308] = 4694; + order[5309] = 595; + order[5310] = 2555; + order[5311] = 4316; + order[5312] = 2556; + order[5313] = 1333; + order[5314] = 5329; + order[5315] = 2382; + order[5316] = 4695; + order[5317] = 4317; + order[5318] = 3169; + order[5319] = 3170; + order[5320] = 1334; + order[5321] = 5330; + order[5322] = 2383; + order[5323] = 3361; + order[5324] = 4318; + order[5325] = 4319; + order[5326] = 4320; + order[5327] = 4321; + order[5328] = 3362; + order[5329] = 3171; + order[5330] = 5331; + order[5331] = 5567; + order[5332] = 5568; + order[5333] = 1335; + order[5334] = 1336; + order[5335] = 5332; + order[5336] = 2384; + order[5337] = 5333; + order[5338] = 4322; + order[5339] = 794; + order[5340] = 1116; + order[5341] = 1117; + order[5342] = 3172; + order[5343] = 4696; + order[5344] = 2385; + order[5345] = 1337; + order[5346] = 199; + order[5347] = 596; + order[5348] = 2386; + order[5349] = 2387; + order[5350] = 597; + order[5351] = 598; + order[5352] = 795; + order[5353] = 2388; + order[5354] = 5334; + order[5355] = 599; + order[5356] = 5335; + order[5357] = 2389; + order[5358] = 2390; + order[5359] = 5336; + order[5360] = 3173; + order[5361] = 4323; + order[5362] = 5337; + order[5363] = 600; + order[5364] = 4416; + order[5365] = 1118; + order[5366] = 2780; + order[5367] = 2557; + order[5368] = 796; + order[5369] = 3846; + order[5370] = 5431; + order[5371] = 601; + order[5372] = 2391; + order[5373] = 2781; + order[5374] = 797; + order[5375] = 3174; + order[5376] = 602; + order[5377] = 2392; + order[5378] = 3586; + order[5379] = 4324; + order[5380] = 3175; + order[5381] = 2393; + order[5382] = 4697; + order[5383] = 1481; + order[5384] = 122; + order[5385] = 5338; + order[5386] = 3176; + order[5387] = 4325; + order[5388] = 3847; + order[5389] = 3177; + order[5390] = 603; + order[5391] = 5339; + order[5392] = 1338; + order[5393] = 5340; + order[5394] = 1119; + order[5395] = 1120; + order[5396] = 2394; + order[5397] = 2558; + order[5398] = 4698; + order[5399] = 798; + order[5400] = 2395; + order[5401] = 200; + order[5402] = 604; + order[5403] = 3587; + order[5404] = 2396; + order[5405] = 201; + order[5406] = 4326; + order[5407] = 799; + order[5408] = 4398; + order[5409] = 4699; + order[5410] = 5341; + order[5411] = 4700; + order[5412] = 1121; + order[5413] = 605; + order[5414] = 4327; + order[5415] = 1482; + order[5416] = 4399; + order[5417] = 4400; + order[5418] = 4328; + order[5419] = 4329; + order[5420] = 4330; + order[5421] = 606; + order[5422] = 3682; + order[5423] = 3588; + order[5424] = 607; + order[5425] = 5342; + order[5426] = 5343; + order[5427] = 5344; + order[5428] = 1122; + order[5429] = 4331; + order[5430] = 4701; + order[5431] = 4702; + order[5432] = 5345; + order[5433] = 2397; + order[5434] = 875; + order[5435] = 2398; + order[5436] = 4703; + order[5437] = 1339; + order[5438] = 2399; + order[5439] = 5346; + order[5440] = 5347; + order[5441] = 2400; + order[5442] = 1123; + order[5443] = 2401; + order[5444] = 800; + order[5445] = 3683; + order[5446] = 2782; + order[5447] = 3848; + order[5448] = 801; + order[5449] = 3589; + order[5450] = 2402; + order[5451] = 608; + order[5452] = 609; + order[5453] = 1483; + order[5454] = 3590; + order[5455] = 610; + order[5456] = 5348; + order[5457] = 611; + order[5458] = 2403; + order[5459] = 3684; + order[5460] = 2404; + order[5461] = 4332; + order[5462] = 876; + order[5463] = 3849; + order[5464] = 3178; + order[5465] = 3363; + order[5466] = 1484; + order[5467] = 612; + order[5468] = 3850; + order[5469] = 4333; + order[5470] = 5349; + order[5471] = 3179; + order[5472] = 3591; + order[5473] = 4334; + order[5474] = 3364; + order[5475] = 2405; + order[5476] = 3180; + order[5477] = 613; + order[5478] = 2406; + order[5479] = 2407; + order[5480] = 2408; + order[5481] = 3365; + order[5482] = 3366; + order[5483] = 2409; + order[5484] = 4335; + order[5485] = 4336; + order[5486] = 4337; + order[5487] = 877; + order[5488] = 1340; + order[5489] = 1124; + order[5490] = 3367; + order[5491] = 4338; + order[5492] = 1565; + order[5493] = 1125; + order[5494] = 123; + order[5495] = 2410; + order[5496] = 3851; + order[5497] = 802; + order[5498] = 4339; + order[5499] = 4704; + } + + private static void municipalitiesOrder11(int[] order) { + order[5500] = 4705; + order[5501] = 2411; + order[5502] = 2783; + order[5503] = 2559; + order[5504] = 1485; + order[5505] = 1126; + order[5506] = 3852; + order[5507] = 4340; + order[5508] = 4341; + order[5509] = 4342; + order[5510] = 3592; + order[5511] = 4343; + order[5512] = 1341; + order[5513] = 878; + order[5514] = 1127; + order[5515] = 1486; + order[5516] = 879; + order[5517] = 880; + order[5518] = 4401; + order[5519] = 5350; + order[5520] = 5351; + order[5521] = 2412; + order[5522] = 2413; + order[5523] = 2414; + order[5524] = 2415; + order[5525] = 3181; + order[5526] = 2416; + order[5527] = 2560; + order[5528] = 4344; + order[5529] = 5352; + order[5530] = 4345; + order[5531] = 4346; + order[5532] = 2784; + order[5533] = 4706; + order[5534] = 881; + order[5535] = 5353; + order[5536] = 614; + order[5537] = 4347; + order[5538] = 3368; + order[5539] = 139; + order[5540] = 1342; + order[5541] = 2561; + order[5542] = 3182; + order[5543] = 1343; + order[5544] = 2417; + order[5545] = 3685; + order[5546] = 5354; + order[5547] = 5355; + order[5548] = 615; + order[5549] = 3593; + order[5550] = 5569; + order[5551] = 616; + order[5552] = 2418; + order[5553] = 3183; + order[5554] = 617; + order[5555] = 4348; + order[5556] = 4707; + order[5557] = 5570; + order[5558] = 3184; + order[5559] = 4349; + order[5560] = 4708; + order[5561] = 21; + order[5562] = 4709; + order[5563] = 4710; + order[5564] = 3369; + order[5565] = 2562; + order[5566] = 618; + order[5567] = 2785; + order[5568] = 5356; + order[5569] = 1344; + order[5570] = 4711; + } + + /** + * Reads one dataset row as a municipality. + */ + public static Municipality rowToMunicipality(java.util.List row) { + return new Municipality(row.get((int) 2L), row.get((int) 1L), row.get((int) 0L)); + } + + /** + * Returns Brazilian municipalities published by the IBGE, optionally filtered by state. + * + * If `stateCode` is provided, only municipalities of that state are returned. If it is + * omitted, every municipality of every state is returned, sorted with `localeCompare` in the + * "pt-BR" locale so accented names land where a Brazilian reader expects them. Every per-state + * list is sorted the same way. + * + * Only an omitted (or `undefined`) `stateCode` asks for the full list: any other value that is + * not a known state code, `null` and `""` included, returns `[]`. + * + * The state code is matched exactly, case included: `getMunicipalities("sp")` returns `[]` where + * `getMunicipalities("SP")` returns the 645 São Paulo municipalities. + * + * @see Official: https://servicodados.ibge.gov.br/api/docs/localidades + */ + public static java.util.List getMunicipalities(String stateCode) { + java.util.List municipalities = new java.util.ArrayList(java.util.List.of()); + java.util.List> rows = Runtime.dataAll(MUNICIPALITIES); + if ((stateCode != null)) { + rows = Runtime.dataRows(MUNICIPALITIES, stateCode); + } + for (var row : rows) { + municipalities.add(rowToMunicipality(row)); + } + return municipalities; + } +} diff --git a/spec/bridge/out/java/IsValidCnpj.java b/spec/bridge/out/java/IsValidCnpj.java new file mode 100644 index 000000000..cc5d8f476 --- /dev/null +++ b/spec/bridge/out/java/IsValidCnpj.java @@ -0,0 +1,115 @@ +// Code generated from spec/bridge/source/is-valid-cnpj.ts. DO NOT EDIT. + +/** `isValidCnpj`, written once. */ +public final class IsValidCnpj { + private IsValidCnpj() {} + + private static final int[][] CLASS0 = {{0x30, 0x39}, {0x41, 0x5a}}; + private static final int[][] CLASS1 = {{0x9, 0xd}, {0x20, 0x20}, {0x2d, 0x2f}, {0xa0, 0xa0}, {0x1680, 0x1680}, {0x2000, 0x200a}, {0x2028, 0x2029}, {0x202f, 0x202f}, {0x205f, 0x205f}, {0x3000, 0x3000}, {0xfeff, 0xfeff}}; + private static final int[][] CLASS2 = {{0x30, 0x39}}; + private static final int[][] CLASS3 = {{0x41, 0x5a}}; + private static final int[][] CLASS4 = {{0x30, 0x39}, {0x41, 0x5a}, {0x61, 0x7a}}; + + private static final Runtime.PatternStep[] PATTERN_ALPHANUMERIC_FORMAT = { + new Runtime.PatternStep(CLASS0, 2, 2, false), + new Runtime.PatternStep(CLASS1, 0, -1, false), + new Runtime.PatternStep(CLASS0, 3, 3, false), + new Runtime.PatternStep(CLASS1, 0, -1, false), + new Runtime.PatternStep(CLASS0, 3, 3, false), + new Runtime.PatternStep(CLASS1, 0, -1, false), + new Runtime.PatternStep(CLASS0, 4, 4, false), + new Runtime.PatternStep(CLASS1, 0, -1, false), + new Runtime.PatternStep(CLASS2, 2, 2, false), + }; + + private static final Runtime.PatternStep[] PATTERN_NUMERIC_FORMAT = { + new Runtime.PatternStep(CLASS2, 2, 2, false), + new Runtime.PatternStep(CLASS1, 0, -1, false), + new Runtime.PatternStep(CLASS2, 3, 3, false), + new Runtime.PatternStep(CLASS1, 0, -1, false), + new Runtime.PatternStep(CLASS2, 3, 3, false), + new Runtime.PatternStep(CLASS1, 0, -1, false), + new Runtime.PatternStep(CLASS2, 4, 4, false), + new Runtime.PatternStep(CLASS1, 0, -1, false), + new Runtime.PatternStep(CLASS2, 2, 2, false), + }; + + private static final long[] FIRST_DIGIT_WEIGHTS = new long[] {5L, 4L, 3L, 2L, 9L, 8L, 7L, 6L, 5L, 4L, 3L, 2L}; + private static final long[] SECOND_DIGIT_WEIGHTS = new long[] {6L, 5L, 4L, 3L, 2L, 9L, 8L, 7L, 6L, 5L, 4L, 3L, 2L}; + + + + /** + * Validates if a CNPJ (Cadastro Nacional da Pessoa Jurídica) is valid. + * + * Supports both numeric (version 1) and alphanumeric (version 2) CNPJ formats, and accepts the + * usual mask characters (`.`, `-`, `/`) and whitespace around and between groups. + */ + public static boolean isValidCnpj(String cnpj, IsValidCnpjOptions options) { + long optionsVersion = -1L; + if (options != null && options.version != null) { + optionsVersion = options.version; + } + if (cnpj == null) { + return false; + } + String trimmed = Runtime.jsTrim(cnpj); + if ((optionsVersion == 2L)) { + String cleaned = Runtime.keepClass(CLASS4, cnpj).toUpperCase(java.util.Locale.ROOT); + if (Runtime.classHas(CLASS3, cleaned)) { + if (!Runtime.patternTest(PATTERN_ALPHANUMERIC_FORMAT, trimmed.toUpperCase(java.util.Locale.ROOT))) { + return false; + } + return hasValidChecksum(cleaned); + } + } + String numeric = Runtime.keepClass(CLASS2, cnpj); + if (!Runtime.patternTest(PATTERN_NUMERIC_FORMAT, trimmed)) { + return false; + } + if (isRepeated(numeric)) { + return false; + } + return hasValidChecksum(numeric); + } + + /** + * Computes one CNPJ check digit from the base and its weight vector. + */ + public static long checkDigit(String base, long[] weights) { + long sum = 0L; + for (long index = 0L; index < (long) weights.length; index++) { + sum = (sum + ((Runtime.codeAt(base, index) - 48L) * weights[(int) index])); + } + long remainder = (sum % 11L); + if ((remainder < 2L)) { + return 0L; + } + return (11L - remainder); + } + + /** + * Whether both check digits of a sanitized 14 character CNPJ match its base. + */ + public static boolean hasValidChecksum(String cnpj) { + if (((Runtime.codeAt(cnpj, 12L) - 48L) != checkDigit(cnpj, FIRST_DIGIT_WEIGHTS))) { + return false; + } + return ((Runtime.codeAt(cnpj, 13L) - 48L) == checkDigit(cnpj, SECOND_DIGIT_WEIGHTS)); + } + + /** + * Whether every character of the value is the same one. + */ + public static boolean isRepeated(String value) { + if (((long) value.length() == 0L)) { + return false; + } + for (long index = 1L; index < (long) value.length(); index++) { + if ((Runtime.codeAt(value, index) != Runtime.codeAt(value, 0L))) { + return false; + } + } + return true; + } +} diff --git a/spec/bridge/out/java/IsValidCnpjOptions.java b/spec/bridge/out/java/IsValidCnpjOptions.java new file mode 100644 index 000000000..87c95f8bc --- /dev/null +++ b/spec/bridge/out/java/IsValidCnpjOptions.java @@ -0,0 +1,5 @@ +/** Options of `isValidCnpj`. */ +public final class IsValidCnpjOptions { + /** Which CNPJ format to accept: `1` numeric only, `2` alphanumeric (default: `1`). */ + public Long version; +} diff --git a/spec/bridge/out/java/Municipality.java b/spec/bridge/out/java/Municipality.java new file mode 100644 index 000000000..17f547871 --- /dev/null +++ b/spec/bridge/out/java/Municipality.java @@ -0,0 +1,17 @@ +/** One Brazilian municipality, as the IBGE publishes it. */ +public final class Municipality { + /** The 7-digit IBGE municipality code. */ + public String code; + + /** The municipality name. */ + public String name; + + /** The two-letter code of the state the municipality belongs to. */ + public String stateCode; + + public Municipality(String code, String name, String stateCode) { + this.code = code; + this.name = name; + this.stateCode = stateCode; + } +} diff --git a/spec/bridge/out/java/Runtime.java b/spec/bridge/out/java/Runtime.java new file mode 100644 index 000000000..e483e96d6 --- /dev/null +++ b/spec/bridge/out/java/Runtime.java @@ -0,0 +1,617 @@ +// The portable runtime for the Java target. +// +// Java strings are UTF-16, the same as JavaScript's, so indexes and lengths already line up; +// what is here is the rest: the compiled classes and patterns, and the JavaScript specific +// trimming and coercion rules. + +/** Helpers shared by the generated utilities. */ +public final class Runtime { + private Runtime() {} + + /** The code points JavaScript's trim() strips. Java's String.strip() is a different set. */ + private static final int[][] JS_WHITESPACE = { + {0x09, 0x0d}, {0x20, 0x20}, {0xa0, 0xa0}, {0x1680, 0x1680}, {0x2000, 0x200a}, + {0x2028, 0x2029}, {0x202f, 0x202f}, {0x205f, 0x205f}, {0x3000, 0x3000}, {0xfeff, 0xfeff} + }; + + /** One step of a compiled pattern: repeat a class between min and max times. */ + public static final class PatternStep { + public final int[][] charClass; + public final long min; + public final long max; + public final boolean capture; + + public PatternStep(int[][] charClass, long min, long max, boolean capture) { + this.charClass = charClass; + this.min = min; + this.max = max; + this.capture = capture; + } + } + + /** Whether a code point belongs to a class. */ + public static boolean inClass(int[][] charClass, int code) { + for (int[] span : charClass) { + if (code >= span[0] && code <= span[1]) { + return true; + } + } + + return false; + } + + /** Reads one code unit, or -1 when the index is out of range. */ + public static long codeAt(String value, long index) { + if (index < 0 || index >= value.length()) { + return -1; + } + + return value.charAt((int) index); + } + + /** Takes the code units between two indexes, clamping like JavaScript's slice. */ + public static String slice(String value, long from, long to) { + long start = Math.max(0, from); + long end = Math.min(value.length(), to); + + if (start >= end) { + return ""; + } + + return value.substring((int) start, (int) end); + } + + /** Whether any character of the value belongs to the class. */ + public static boolean classHas(int[][] charClass, String value) { + for (int index = 0; index < value.length(); index++) { + if (inClass(charClass, value.charAt(index))) { + return true; + } + } + + return false; + } + + /** Keeps only the characters of the value that belong to the class. */ + public static String keepClass(int[][] charClass, String value) { + StringBuilder kept = new StringBuilder(); + + for (int index = 0; index < value.length(); index++) { + if (inClass(charClass, value.charAt(index))) { + kept.append(value.charAt(index)); + } + } + + return kept.toString(); + } + + /** Runs a compiled pattern against the whole value, greedily and without backtracking. */ + public static boolean patternTest(PatternStep[] steps, String value) { + int index = 0; + + for (PatternStep step : steps) { + long count = 0; + + while ((step.max < 0 || count < step.max) + && index < value.length() + && inClass(step.charClass, value.charAt(index))) { + index++; + count++; + } + + if (count < step.min) { + return false; + } + } + + return index == value.length(); + } + + /** Strips the code points JavaScript's trim() strips. */ + public static String jsTrim(String value) { + int start = 0; + int end = value.length(); + + while (start < end && inClass(JS_WHITESPACE, value.charAt(start))) { + start++; + } + while (end > start && inClass(JS_WHITESPACE, value.charAt(end - 1))) { + end--; + } + + return value.substring(start, end); + } + + /** Left pads the value with a filler up to a length. */ + public static String padStart(String value, long length, String filler) { + StringBuilder padded = new StringBuilder(); + + while (padded.length() + value.length() < length) { + padded.append(filler); + } + + return padded + value; + } + + /** Repeats a value. */ + public static String repeat(String value, long times) { + return times <= 0 ? "" : value.repeat((int) times); + } + + /** Reads an optional flag the way JavaScript reads truthiness. */ + public static boolean isTruthy(Boolean value) { + return value != null && value; + } + + /** A dataset: the rows in the baked full order, and the rows of each key. */ + public static final class Dataset { + private final java.util.List> all; + private final java.util.Map>> byKey; + + public Dataset(String[][] rows, String[] keys, int[][] groups, int[] fullOrder) { + java.util.List> shared = new java.util.ArrayList<>(rows.length); + + for (String[] row : rows) { + shared.add(java.util.List.of(row)); + } + + this.all = new java.util.ArrayList<>(fullOrder.length); + + for (int index : fullOrder) { + this.all.add(shared.get(index)); + } + + this.byKey = new java.util.HashMap<>(keys.length * 2); + + for (int group = 0; group < keys.length; group++) { + java.util.List> of = new java.util.ArrayList<>(groups[group].length); + + for (int index : groups[group]) { + of.add(shared.get(index)); + } + + this.byKey.put(keys[group], of); + } + } + + /** Every row, in the baked full order. */ + public java.util.List> all() { + return this.all; + } + + /** The rows whose first column is the key given, empty when the key is unknown. */ + public java.util.List> rows(String key) { + return this.byKey.getOrDefault(key, java.util.List.of()); + } + } + + /** Every row of a dataset, in the baked full order. */ + public static java.util.List> dataAll(Dataset table) { + return table.all(); + } + + /** The rows whose first column is the key given, empty when the key is unknown. */ + public static java.util.List> dataRows(Dataset table, String key) { + return table.rows(key); + } + + /** What a provider answered: the HTTP status, whether it counts as a success, and the body. */ + public static final class HttpResponse { + public final long status; + public final boolean ok; + public final Object body; + + public HttpResponse(long status, boolean ok, Object body) { + this.status = status; + this.ok = ok; + this.body = body; + } + } + + private static final java.net.http.HttpClient HTTP = java.net.http.HttpClient.newBuilder() + .connectTimeout(java.time.Duration.ofSeconds(15)) + .build(); + + /** + * The origin every request is sent to instead of its own, when one is set. + * + * This is the conformance hook: the cross language replay points all seven targets at one + * local server, the same way the JavaScript suite points fetch at a mock. + */ + private static String httpTarget(String url) { + String base = System.getenv("BRUTILS_BRIDGE_HTTP_ORIGIN"); + + if (base == null || base.isEmpty()) { + return url; + } + + return base + "/" + url.replaceFirst("^https?://", ""); + } + + /** Performs an HTTP GET, retrying a transient transport failure with a linear backoff. */ + public static HttpResponse httpGet(String url, long retries, long retryDelayMs) { + String target = httpTarget(url); + + for (long attempt = 0; ; attempt++) { + try { + java.net.http.HttpRequest request = java.net.http.HttpRequest.newBuilder() + .uri(java.net.URI.create(target)) + .timeout(java.time.Duration.ofSeconds(15)) + .GET() + .build(); + java.net.http.HttpResponse answer = + HTTP.send(request, java.net.http.HttpResponse.BodyHandlers.ofString()); + long status = answer.statusCode(); + Object body; + + try { + body = Json.parse(answer.body()); + } catch (RuntimeException error) { + body = null; + } + + return new HttpResponse(status, status >= 200 && status < 300, body); + } catch (Exception error) { + if (attempt >= retries) { + return new HttpResponse(0, false, null); + } + + try { + Thread.sleep(retryDelayMs * (attempt + 1)); + } catch (InterruptedException interrupted) { + Thread.currentThread().interrupt(); + + return new HttpResponse(0, false, null); + } + } + } + } + + /** Whether a list holds a value. */ + public static boolean listHas(java.util.List items, String value) { + for (String item : items) { + if (item.equals(value)) { + return true; + } + } + + return false; + } + + /** Reads one field of a JSON body, treating anything that is not an object as empty. */ + private static Object jsonField(Object body, String key) { + if (!(body instanceof java.util.Map)) { + return null; + } + + return ((java.util.Map) body).get(key); + } + + /** Reads a string field of a JSON body, answering "" when it is missing. */ + public static String jsonString(Object body, String key) { + Object found = jsonField(body, key); + + return found instanceof String ? (String) found : ""; + } + + /** Reads an integer field of a JSON body, answering -1 when it is missing. */ + public static long jsonInt(Object body, String key) { + Object found = jsonField(body, key); + + return found instanceof Double ? (long) (double) (Double) found : -1L; + } + + /** Whether a field of a JSON body is truthy, the way JavaScript reads truthiness. */ + public static boolean jsonTruthy(Object body, String key) { + Object found = jsonField(body, key); + + if (found == null) { + return false; + } + + if (found instanceof Boolean) { + return (Boolean) found; + } + + if (found instanceof Double) { + return (Double) found != 0.0; + } + + if (found instanceof String) { + return !((String) found).isEmpty(); + } + + return true; + } + + /** Whether a field of a JSON body is exactly true. */ + public static boolean jsonIsTrue(Object body, String key) { + return Boolean.TRUE.equals(jsonField(body, key)); + } + + /** A JSON reader, so the target needs nothing outside the JDK. */ + static final class Json { + private final String text; + private int at; + + private Json(String text) { + this.text = text; + } + + static Object parse(String text) { + Json reader = new Json(text); + + reader.space(); + + Object value = reader.value(); + + reader.space(); + + if (reader.at != text.length()) { + throw new IllegalArgumentException("trailing JSON"); + } + + return value; + } + + private void space() { + while (at < text.length() && Character.isWhitespace(text.charAt(at))) { + at++; + } + } + + private Object value() { + if (at >= text.length()) { + throw new IllegalArgumentException("empty JSON"); + } + + char head = text.charAt(at); + + if (head == '{') { + return object(); + } + + if (head == '[') { + return array(); + } + + if (head == '"') { + return string(); + } + + if (text.startsWith("true", at)) { + at += 4; + + return Boolean.TRUE; + } + + if (text.startsWith("false", at)) { + at += 5; + + return Boolean.FALSE; + } + + if (text.startsWith("null", at)) { + at += 4; + + return null; + } + + return number(); + } + + private java.util.Map object() { + java.util.Map found = new java.util.LinkedHashMap<>(); + + at++; + space(); + + if (at < text.length() && text.charAt(at) == '}') { + at++; + + return found; + } + + while (true) { + space(); + + String key = string(); + + space(); + at++; // ':' + space(); + found.put(key, value()); + space(); + + if (at < text.length() && text.charAt(at) == ',') { + at++; + + continue; + } + + at++; // '}' + + return found; + } + } + + private java.util.List array() { + java.util.List found = new java.util.ArrayList<>(); + + at++; + space(); + + if (at < text.length() && text.charAt(at) == ']') { + at++; + + return found; + } + + while (true) { + space(); + found.add(value()); + space(); + + if (at < text.length() && text.charAt(at) == ',') { + at++; + + continue; + } + + at++; // ']' + + return found; + } + } + + private String string() { + StringBuilder out = new StringBuilder(); + + at++; + + while (at < text.length()) { + char here = text.charAt(at++); + + if (here == '"') { + return out.toString(); + } + + if (here != '\\') { + out.append(here); + + continue; + } + + char escaped = text.charAt(at++); + + switch (escaped) { + case 'n': out.append('\n'); break; + case 't': out.append('\t'); break; + case 'r': out.append('\r'); break; + case 'b': out.append('\b'); break; + case 'f': out.append('\f'); break; + case 'u': + out.append((char) Integer.parseInt(text.substring(at, at + 4), 16)); + at += 4; + break; + default: out.append(escaped); + } + } + + throw new IllegalArgumentException("unterminated string"); + } + + private Double number() { + int start = at; + + while (at < text.length() && "+-.eE0123456789".indexOf(text.charAt(at)) >= 0) { + at++; + } + + return Double.valueOf(text.substring(start, at)); + } + } + + /** What one attempt of a race ended with. */ + private static final class Outcome { + final boolean ok; + final Object value; + final java.util.List kinds; + + Outcome(boolean ok, Object value, java.util.List kinds) { + this.ok = ok; + this.value = value; + this.kinds = kinds; + } + } + + /** One attempt of a race: the function the source named, applied to one item. */ + public interface Task { + Object run(String item, String argument); + } + + /** The running attempts of a race, and what each one ended with. */ + public static final class Attempts { + private final java.util.concurrent.BlockingQueue settled; + private final int total; + private final java.util.List outcomes = new java.util.ArrayList<>(); + + Attempts(int total) { + this.settled = new java.util.concurrent.ArrayBlockingQueue<>(Math.max(total, 1)); + this.total = total; + } + } + + /** The error name and every name it inherits from, which is what a failure is matched on. */ + private static java.util.List kindsOf(Throwable error) { + java.util.List kinds = new java.util.ArrayList<>(); + + for (Class current = error.getClass(); current != null; current = current.getSuperclass()) { + kinds.add(current.getSimpleName()); + } + + return kinds; + } + + /** + * Starts one attempt per item, all at once. + * + * This is the only concurrency primitive of the portable subset. Java has virtual threads, + * so the work goes on one each and the caller simply waits. + */ + public static Attempts startAll(Task run, java.util.List items, String argument) { + Attempts attempts = new Attempts(items.size()); + + for (String item : items) { + Thread.ofVirtual().start(() -> { + try { + attempts.settled.put(new Outcome(true, run.run(item, argument), java.util.List.of())); + } catch (InterruptedException interrupted) { + Thread.currentThread().interrupt(); + } catch (Throwable error) { + try { + attempts.settled.put(new Outcome(false, null, kindsOf(error))); + } catch (InterruptedException interrupted) { + Thread.currentThread().interrupt(); + } + } + }); + } + + return attempts; + } + + /** The value of the first attempt that succeeds, or null once every attempt has failed. */ + public static Object firstSuccess(Attempts attempts) { + while (attempts.outcomes.size() < attempts.total) { + Outcome outcome; + + try { + outcome = attempts.settled.take(); + } catch (InterruptedException interrupted) { + Thread.currentThread().interrupt(); + + return null; + } + + attempts.outcomes.add(outcome); + + if (outcome.ok) { + return outcome.value; + } + } + + return null; + } + + /** Whether any attempt failed with a given error kind. */ + public static boolean anyFailedWith(Attempts attempts, String kind) { + for (Outcome outcome : attempts.outcomes) { + if (!outcome.ok && outcome.kinds.contains(kind)) { + return true; + } + } + + return false; + } +} diff --git a/spec/bridge/out/python/brutils_bridge/__init__.py b/spec/bridge/out/python/brutils_bridge/__init__.py new file mode 100644 index 000000000..a9850c0ff --- /dev/null +++ b/spec/bridge/out/python/brutils_bridge/__init__.py @@ -0,0 +1,6 @@ +"""Generated Brazilian Utils.""" + +from .format_cnpj import * # noqa: F401,F403 +from .get_address_info_by_cep import * # noqa: F401,F403 +from .get_municipalities import * # noqa: F401,F403 +from .is_valid_cnpj import * # noqa: F401,F403 diff --git a/spec/bridge/out/python/brutils_bridge/format_cnpj.py b/spec/bridge/out/python/brutils_bridge/format_cnpj.py new file mode 100644 index 000000000..b3692d81f --- /dev/null +++ b/spec/bridge/out/python/brutils_bridge/format_cnpj.py @@ -0,0 +1,110 @@ +# Code generated from spec/bridge/source/format-cnpj.ts. DO NOT EDIT. +"""`formatCnpj`, written once.""" + +from dataclasses import dataclass +from typing import Any, List, Optional + +from .runtime import ( + CharClass, + PatternStep, + any_failed_with, + as_string, + class_has, + code_at, + data_all, + data_rows, + first_success, + http_get, + is_list, + is_number, + is_truthy, + js_trim, + json_int, + json_is_true, + json_string, + json_truthy, + keep_class, + list_has, + make_dataset, + pad_start, + pattern_test, + start_all, +) + +class0: CharClass = ((0x30, 0x39),) +class1: CharClass = ((0x30, 0x39), (0x41, 0x5a), (0x61, 0x7a),) + + + +PATTERN = "00.000.000/0000-00" +OBFUSCATED_PATTERN = "**.000.000/0000-**" + + + + + +@dataclass +class FormatCnpjOptions: + """Options of `formatCnpj`.""" + + # Whether to left pad the value with zeros up to the number of slots in the pattern (default: `false`). + pad: Optional[bool] = None + # Which CNPJ format to read: `1` numeric only, `2` alphanumeric (default: `1`). + version: Optional[int] = None + # Whether to hide the first 2 digits and the 2 check digits with `*` (default: `false`). + obfuscate: Optional[bool] = None + + + + + +def format_cnpj(value: Any, options: Optional[FormatCnpjOptions] = None) -> str: + """Formats a given CNPJ (Cadastro Nacional da Pessoa Jurídica) value. + """ + options_version = -1 + if options is not None and options.version is not None: + options_version = options.version + options_obfuscate = False + if options is not None and options.obfuscate is not None: + options_obfuscate = options.obfuscate + options_pad = False + if options is not None and options.pad is not None: + options_pad = options.pad + if value is None: + return "" + text = as_string(value) + cleaned = keep_class(class0, text) + if (options_version == 2): + cleaned = keep_class(class1, text).upper() + pattern = PATTERN + if is_truthy(options_obfuscate): + pattern = OBFUSCATED_PATTERN + return layout(cleaned, pattern, is_truthy(options_pad)) + + +def layout(value: str, pattern: str, pad: bool) -> str: + """Lays a value over a pattern. + """ + slots = 0 + for index in range(0, len(pattern)): + if ((code_at(pattern, index) == 48) or (code_at(pattern, index) == 42)): + slots = (slots + 1) + padded = value + if pad: + padded = pad_start(value, slots, "0") + formatted = "" + cursor = 0 + for index in range(0, len(pattern)): + slot = code_at(pattern, index) + if ((slot == 48) or (slot == 42)): + if (cursor >= len(padded)): + return formatted + if (slot == 42): + formatted = (formatted + "*") + else: + formatted = (formatted + padded[cursor:(cursor + 1)]) + cursor = (cursor + 1) + else: + if (cursor < len(padded)): + formatted = (formatted + pattern[index:(index + 1)]) + return formatted diff --git a/spec/bridge/out/python/brutils_bridge/get_address_info_by_cep.py b/spec/bridge/out/python/brutils_bridge/get_address_info_by_cep.py new file mode 100644 index 000000000..837e50d25 --- /dev/null +++ b/spec/bridge/out/python/brutils_bridge/get_address_info_by_cep.py @@ -0,0 +1,191 @@ +# Code generated from spec/bridge/source/get-address-info-by-cep.ts. DO NOT EDIT. +"""Address lookup by CEP, written once.""" + +from dataclasses import dataclass +from typing import Any, List, Optional + +from .runtime import ( + CharClass, + PatternStep, + any_failed_with, + as_string, + class_has, + code_at, + data_all, + data_rows, + first_success, + http_get, + is_list, + is_number, + is_truthy, + js_trim, + json_int, + json_is_true, + json_string, + json_truthy, + keep_class, + list_has, + make_dataset, + pad_start, + pattern_test, + start_all, +) + +class0: CharClass = ((0x30, 0x39),) + +PATTERN_CEP_FORMAT = ( + PatternStep(class0, 8, 8, False), +) + +DEFAULT_PROVIDERS = ["viacep", "brasilapi"] +KNOWN_PROVIDERS = ["viacep", "widenet", "brasilapi"] +BRASIL_API_NOT_FOUND_STATUS = 404 +HTTP_RETRIES = 2 +HTTP_RETRY_DELAY_MS = 250 + + +class GetAddressInfoByCepError(Exception): + """Base class of every error `getAddressInfoByCep` rejects with.""" + + +class GetAddressInfoByCepValidationError(GetAddressInfoByCepError): + """Thrown by `getAddressInfoByCep` when the value given is not a valid CEP.""" + + +class GetAddressInfoByCepNotFoundError(GetAddressInfoByCepError): + """Thrown by `getAddressInfoByCep` when no CEP service knows the CEP.""" + + +class GetAddressInfoByCepServiceError(GetAddressInfoByCepError): + """Thrown by `getAddressInfoByCep` when every CEP service failed to answer.""" + + +class CepProviderFailure(Exception): + """Raised inside a provider that did not answer. Only whether a failure was a not found is looked at when the provider failures are aggregated, so this one never leaves the module.""" + + +@dataclass +class AddressInfo: + """The address `getAddressInfoByCep` returns for a CEP.""" + + # The 8 digit CEP, no mask. + cep: str + # Two letter state code, e.g. "SP". + state: str + # City name. + city: str + # Neighborhood name, empty when the CEP covers a whole city. + neighborhood: str + # Street name, empty when the CEP covers a whole city. + street: str + + +@dataclass +class GetAddressInfoByCepOptions: + """Options of `getAddressInfoByCep`.""" + + # Which CEP services to race, in the order given (default: `["viacep", "brasilapi"]`; the deprecated `"widenet"` provider is excluded from the default list, but can still be requested explicitly). + providers: Optional[List[str]] = None + + + + + +def fetch_via_cep(cep: str) -> AddressInfo: + """Reads the address ViaCEP answers with. + + @see Based on: https://viacep.com.br/ + """ + response = http_get((("https://viacep.com.br/ws/" + cep) + "/json/"), HTTP_RETRIES, HTTP_RETRY_DELAY_MS) + if not response.ok: + raise CepProviderFailure("ViaCEP request failed") + found = json_string(response.body, "cep") + if (json_truthy(response.body, "erro") or (found == "")): + raise GetAddressInfoByCepNotFoundError("CEP n\U000000e3o encontrado") + return AddressInfo(cep=keep_class(class0, found), state=json_string(response.body, "uf"), city=json_string(response.body, "localidade"), neighborhood=json_string(response.body, "bairro"), street=json_string(response.body, "logradouro")) + + +def fetch_widenet(cep: str) -> AddressInfo: + """Reads the address Widenet answers with. + """ + response = http_get((("https://apps.widenet.com.br/busca-cep/api/cep/" + cep) + ".json"), HTTP_RETRIES, HTTP_RETRY_DELAY_MS) + if not response.ok: + raise CepProviderFailure("Widenet request failed") + found = json_string(response.body, "code") + if (((json_int(response.body, "status") != 200) or not json_is_true(response.body, "ok")) or (found == "")): + raise GetAddressInfoByCepNotFoundError("CEP n\U000000e3o encontrado") + return AddressInfo(cep=keep_class(class0, found), state=json_string(response.body, "state"), city=json_string(response.body, "city"), neighborhood=json_string(response.body, "district"), street=json_string(response.body, "address")) + + +def fetch_brasil_api(cep: str) -> AddressInfo: + """Reads the address BrasilAPI answers with. + + @see Based on: https://brasilapi.com.br/docs#tag/CEP + """ + response = http_get((("https://brasilapi.com.br/api/cep/v1/" + cep) + ""), HTTP_RETRIES, HTTP_RETRY_DELAY_MS) + if (response.status == BRASIL_API_NOT_FOUND_STATUS): + raise GetAddressInfoByCepNotFoundError("CEP n\U000000e3o encontrado") + if not response.ok: + raise CepProviderFailure("BrasilAPI request failed") + found = json_string(response.body, "cep") + if (json_truthy(response.body, "errors") or (found == "")): + raise GetAddressInfoByCepNotFoundError("CEP n\U000000e3o encontrado") + return AddressInfo(cep=keep_class(class0, found), state=json_string(response.body, "state"), city=json_string(response.body, "city"), neighborhood=json_string(response.body, "neighborhood"), street=json_string(response.body, "street")) + + +def fetch_provider(provider: str, cep: str) -> AddressInfo: + """Asks one named provider for a CEP. + """ + if (provider == "viacep"): + return fetch_via_cep(cep) + if (provider == "widenet"): + return fetch_widenet(cep) + return fetch_brasil_api(cep) + + +def known_providers(given: List[str]) -> List[str]: + """The providers of a list that are known, in the order they were given. + """ + kept = [] + for provider in given: + if list_has(KNOWN_PROVIDERS, provider): + kept.append(provider) + return kept + + +def get_address_info_by_cep(cep: Any, options: Optional[GetAddressInfoByCepOptions] = None) -> AddressInfo: + """Fetches address information for a given CEP using multiple providers simultaneously. + Returns the result from the first provider that responds successfully. + + The providers are started together and raced, not tried one after the other, so a provider + that is retrying delays nothing for the others: its retries only push back the moment its own + failure lands, and therefore the moment an all-failed rejection can surface. + + @see Official: https://www.correios.com.br/enviar/precisa-de-ajuda/tudo-sobre-cep + @see Based on: https://viacep.com.br/ + ViaCEP, one of the two default providers. A third-party service, not a Correios one. + @see Based on: https://brasilapi.com.br/docs#tag/CEP + BrasilAPI, the other default provider. A third-party service, not a Correios one. + """ + options_providers = None + if options is not None and options.providers is not None: + options_providers = options.providers + digits = keep_class(class0, as_string(cep)) + if is_number(cep): + digits = pad_start(digits, 8, "0") + if not pattern_test(PATTERN_CEP_FORMAT, digits): + raise GetAddressInfoByCepValidationError("CEP inv\U000000e1lido") + chosen = DEFAULT_PROVIDERS + if (options_providers is not None): + if not is_list(options_providers): + raise GetAddressInfoByCepValidationError("Nenhum provedor v\U000000e1lido especificado") + chosen = known_providers(options_providers) + if (len(chosen) == 0): + raise GetAddressInfoByCepValidationError("Nenhum provedor v\U000000e1lido especificado") + attempts = start_all(fetch_provider, chosen, digits) + found = first_success(attempts) + if (found is not None): + return found + if any_failed_with(attempts, "GetAddressInfoByCepNotFoundError"): + raise GetAddressInfoByCepNotFoundError("CEP n\U000000e3o encontrado em nenhum servi\U000000e7o") + raise GetAddressInfoByCepServiceError("Todos os servi\U000000e7os est\U000000e3o fora de servi\U000000e7o ou indispon\U000000edveis") diff --git a/spec/bridge/out/python/brutils_bridge/get_municipalities.py b/spec/bridge/out/python/brutils_bridge/get_municipalities.py new file mode 100644 index 000000000..722fbc55d --- /dev/null +++ b/spec/bridge/out/python/brutils_bridge/get_municipalities.py @@ -0,0 +1,5692 @@ +# Code generated from spec/bridge/source/get-municipalities.ts. DO NOT EDIT. +"""Brazilian municipalities, written once.""" + +from dataclasses import dataclass +from typing import Any, List, Optional + +from .runtime import ( + CharClass, + PatternStep, + any_failed_with, + as_string, + class_has, + code_at, + data_all, + data_rows, + first_success, + http_get, + is_list, + is_number, + is_truthy, + js_trim, + json_int, + json_is_true, + json_string, + json_truthy, + keep_class, + list_has, + make_dataset, + pad_start, + pattern_test, + start_all, +) + + + + + + + + + + + +@dataclass +class Municipality: + """One Brazilian municipality, as the IBGE publishes it.""" + + # The 7-digit IBGE municipality code. + code: str + # The municipality name. + name: str + # The two-letter code of the state the municipality belongs to. + state_code: str + + +# Brazilian municipalities published by the IBGE, by state, in the pt-BR collation order the JavaScript package returns. +MUNICIPALITIES = make_dataset( + [ + ["AC", "Acrel\U000000e2ndia", "1200013"], + ["AC", "Assis Brasil", "1200054"], + ["AC", "Brasil\U000000e9ia", "1200104"], + ["AC", "Bujari", "1200138"], + ["AC", "Capixaba", "1200179"], + ["AC", "Cruzeiro do Sul", "1200203"], + ["AC", "Epitaciol\U000000e2ndia", "1200252"], + ["AC", "Feij\U000000f3", "1200302"], + ["AC", "Jord\U000000e3o", "1200328"], + ["AC", "M\U000000e2ncio Lima", "1200336"], + ["AC", "Manoel Urbano", "1200344"], + ["AC", "Marechal Thaumaturgo", "1200351"], + ["AC", "Pl\U000000e1cido de Castro", "1200385"], + ["AC", "Porto Acre", "1200807"], + ["AC", "Porto Walter", "1200393"], + ["AC", "Rio Branco", "1200401"], + ["AC", "Rodrigues Alves", "1200427"], + ["AC", "Santa Rosa do Purus", "1200435"], + ["AC", "Sena Madureira", "1200500"], + ["AC", "Senador Guiomard", "1200450"], + ["AC", "Tarauac\U000000e1", "1200609"], + ["AC", "Xapuri", "1200708"], + ["AL", "\U000000c1gua Branca", "2700102"], + ["AL", "Anadia", "2700201"], + ["AL", "Arapiraca", "2700300"], + ["AL", "Atalaia", "2700409"], + ["AL", "Barra de Santo Ant\U000000f4nio", "2700508"], + ["AL", "Barra de S\U000000e3o Miguel", "2700607"], + ["AL", "Batalha", "2700706"], + ["AL", "Bel\U000000e9m", "2700805"], + ["AL", "Belo Monte", "2700904"], + ["AL", "Boca da Mata", "2701001"], + ["AL", "Branquinha", "2701100"], + ["AL", "Cacimbinhas", "2701209"], + ["AL", "Cajueiro", "2701308"], + ["AL", "Campestre", "2701357"], + ["AL", "Campo Alegre", "2701407"], + ["AL", "Campo Grande", "2701506"], + ["AL", "Canapi", "2701605"], + ["AL", "Capela", "2701704"], + ["AL", "Carneiros", "2701803"], + ["AL", "Ch\U000000e3 Preta", "2701902"], + ["AL", "Coit\U000000e9 do N\U000000f3ia", "2702009"], + ["AL", "Col\U000000f4nia Leopoldina", "2702108"], + ["AL", "Coqueiro Seco", "2702207"], + ["AL", "Coruripe", "2702306"], + ["AL", "Cra\U000000edbas", "2702355"], + ["AL", "Delmiro Gouveia", "2702405"], + ["AL", "Dois Riachos", "2702504"], + ["AL", "Estrela de Alagoas", "2702553"], + ["AL", "Feira Grande", "2702603"], + ["AL", "Feliz Deserto", "2702702"], + ["AL", "Flexeiras", "2702801"], + ["AL", "Girau do Ponciano", "2702900"], + ["AL", "Ibateguara", "2703007"], + ["AL", "Igaci", "2703106"], + ["AL", "Igreja Nova", "2703205"], + ["AL", "Inhapi", "2703304"], + ["AL", "Jacar\U000000e9 dos Homens", "2703403"], + ["AL", "Jacu\U000000edpe", "2703502"], + ["AL", "Japaratinga", "2703601"], + ["AL", "Jaramataia", "2703700"], + ["AL", "Jequi\U000000e1 da Praia", "2703759"], + ["AL", "Joaquim Gomes", "2703809"], + ["AL", "Jundi\U000000e1", "2703908"], + ["AL", "Junqueiro", "2704005"], + ["AL", "Lagoa da Canoa", "2704104"], + ["AL", "Limoeiro de Anadia", "2704203"], + ["AL", "Macei\U000000f3", "2704302"], + ["AL", "Major Isidoro", "2704401"], + ["AL", "Mar Vermelho", "2704906"], + ["AL", "Maragogi", "2704500"], + ["AL", "Maravilha", "2704609"], + ["AL", "Marechal Deodoro", "2704708"], + ["AL", "Maribondo", "2704807"], + ["AL", "Mata Grande", "2705002"], + ["AL", "Matriz de Camaragibe", "2705101"], + ["AL", "Messias", "2705200"], + ["AL", "Minador do Negr\U000000e3o", "2705309"], + ["AL", "Monteir\U000000f3polis", "2705408"], + ["AL", "Murici", "2705507"], + ["AL", "Novo Lino", "2705606"], + ["AL", "Olho d'\U000000c1gua das Flores", "2705705"], + ["AL", "Olho d'\U000000c1gua do Casado", "2705804"], + ["AL", "Olho d'\U000000c1gua Grande", "2705903"], + ["AL", "Oliven\U000000e7a", "2706000"], + ["AL", "Ouro Branco", "2706109"], + ["AL", "Palestina", "2706208"], + ["AL", "Palmeira dos \U000000cdndios", "2706307"], + ["AL", "P\U000000e3o de A\U000000e7\U000000facar", "2706406"], + ["AL", "Pariconha", "2706422"], + ["AL", "Paripueira", "2706448"], + ["AL", "Passo de Camaragibe", "2706505"], + ["AL", "Paulo Jacinto", "2706604"], + ["AL", "Penedo", "2706703"], + ["AL", "Pia\U000000e7abu\U000000e7u", "2706802"], + ["AL", "Pilar", "2706901"], + ["AL", "Pindoba", "2707008"], + ["AL", "Piranhas", "2707107"], + ["AL", "Po\U000000e7o das Trincheiras", "2707206"], + ["AL", "Porto Calvo", "2707305"], + ["AL", "Porto de Pedras", "2707404"], + ["AL", "Porto Real do Col\U000000e9gio", "2707503"], + ["AL", "Quebrangulo", "2707602"], + ["AL", "Rio Largo", "2707701"], + ["AL", "Roteiro", "2707800"], + ["AL", "Santa Luzia do Norte", "2707909"], + ["AL", "Santana do Ipanema", "2708006"], + ["AL", "Santana do Munda\U000000fa", "2708105"], + ["AL", "S\U000000e3o Br\U000000e1s", "2708204"], + ["AL", "S\U000000e3o Jos\U000000e9 da Laje", "2708303"], + ["AL", "S\U000000e3o Jos\U000000e9 da Tapera", "2708402"], + ["AL", "S\U000000e3o Lu\U000000eds do Quitunde", "2708501"], + ["AL", "S\U000000e3o Miguel dos Campos", "2708600"], + ["AL", "S\U000000e3o Miguel dos Milagres", "2708709"], + ["AL", "S\U000000e3o Sebasti\U000000e3o", "2708808"], + ["AL", "Satuba", "2708907"], + ["AL", "Senador Rui Palmeira", "2708956"], + ["AL", "Tanque d'Arca", "2709004"], + ["AL", "Taquarana", "2709103"], + ["AL", "Teot\U000000f4nio Vilela", "2709152"], + ["AL", "Traipu", "2709202"], + ["AL", "Uni\U000000e3o dos Palmares", "2709301"], + ["AL", "Vi\U000000e7osa", "2709400"], + ["AP", "Amap\U000000e1", "1600105"], + ["AP", "Cal\U000000e7oene", "1600204"], + ["AP", "Cutias", "1600212"], + ["AP", "Ferreira Gomes", "1600238"], + ["AP", "Itaubal", "1600253"], + ["AP", "Laranjal do Jari", "1600279"], + ["AP", "Macap\U000000e1", "1600303"], + ["AP", "Mazag\U000000e3o", "1600402"], + ["AP", "Oiapoque", "1600501"], + ["AP", "Pedra Branca do Amapari", "1600154"], + ["AP", "Porto Grande", "1600535"], + ["AP", "Pracu\U000000faba", "1600550"], + ["AP", "Santana", "1600600"], + ["AP", "Serra do Navio", "1600055"], + ["AP", "Tartarugalzinho", "1600709"], + ["AP", "Vit\U000000f3ria do Jari", "1600808"], + ["AM", "Alvar\U000000e3es", "1300029"], + ["AM", "Amatur\U000000e1", "1300060"], + ["AM", "Anam\U000000e3", "1300086"], + ["AM", "Anori", "1300102"], + ["AM", "Apu\U000000ed", "1300144"], + ["AM", "Atalaia do Norte", "1300201"], + ["AM", "Autazes", "1300300"], + ["AM", "Barcelos", "1300409"], + ["AM", "Barreirinha", "1300508"], + ["AM", "Benjamin Constant", "1300607"], + ["AM", "Beruri", "1300631"], + ["AM", "Boa Vista do Ramos", "1300680"], + ["AM", "Boca do Acre", "1300706"], + ["AM", "Borba", "1300805"], + ["AM", "Caapiranga", "1300839"], + ["AM", "Canutama", "1300904"], + ["AM", "Carauari", "1301001"], + ["AM", "Careiro", "1301100"], + ["AM", "Careiro da V\U000000e1rzea", "1301159"], + ["AM", "Coari", "1301209"], + ["AM", "Codaj\U000000e1s", "1301308"], + ["AM", "Eirunep\U000000e9", "1301407"], + ["AM", "Envira", "1301506"], + ["AM", "Fonte Boa", "1301605"], + ["AM", "Guajar\U000000e1", "1301654"], + ["AM", "Humait\U000000e1", "1301704"], + ["AM", "Ipixuna", "1301803"], + ["AM", "Iranduba", "1301852"], + ["AM", "Itacoatiara", "1301902"], + ["AM", "Itamarati", "1301951"], + ["AM", "Itapiranga", "1302009"], + ["AM", "Japur\U000000e1", "1302108"], + ["AM", "Juru\U000000e1", "1302207"], + ["AM", "Juta\U000000ed", "1302306"], + ["AM", "L\U000000e1brea", "1302405"], + ["AM", "Manacapuru", "1302504"], + ["AM", "Manaquiri", "1302553"], + ["AM", "Manaus", "1302603"], + ["AM", "Manicor\U000000e9", "1302702"], + ["AM", "Mara\U000000e3", "1302801"], + ["AM", "Mau\U000000e9s", "1302900"], + ["AM", "Nhamund\U000000e1", "1303007"], + ["AM", "Nova Olinda do Norte", "1303106"], + ["AM", "Novo Air\U000000e3o", "1303205"], + ["AM", "Novo Aripuan\U000000e3", "1303304"], + ["AM", "Parintins", "1303403"], + ["AM", "Pauini", "1303502"], + ["AM", "Presidente Figueiredo", "1303536"], + ["AM", "Rio Preto da Eva", "1303569"], + ["AM", "Santa Isabel do Rio Negro", "1303601"], + ["AM", "Santo Ant\U000000f4nio do I\U000000e7\U000000e1", "1303700"], + ["AM", "S\U000000e3o Gabriel da Cachoeira", "1303809"], + ["AM", "S\U000000e3o Paulo de Oliven\U000000e7a", "1303908"], + ["AM", "S\U000000e3o Sebasti\U000000e3o do Uatum\U000000e3", "1303957"], + ["AM", "Silves", "1304005"], + ["AM", "Tabatinga", "1304062"], + ["AM", "Tapau\U000000e1", "1304104"], + ["AM", "Tef\U000000e9", "1304203"], + ["AM", "Tonantins", "1304237"], + ["AM", "Uarini", "1304260"], + ["AM", "Urucar\U000000e1", "1304302"], + ["AM", "Urucurituba", "1304401"], + ["BA", "Aba\U000000edra", "2900108"], + ["BA", "Abar\U000000e9", "2900207"], + ["BA", "Acajutiba", "2900306"], + ["BA", "Adustina", "2900355"], + ["BA", "\U000000c1gua Fria", "2900405"], + ["BA", "Aiquara", "2900603"], + ["BA", "Alagoinhas", "2900702"], + ["BA", "Alcoba\U000000e7a", "2900801"], + ["BA", "Almadina", "2900900"], + ["BA", "Amargosa", "2901007"], + ["BA", "Am\U000000e9lia Rodrigues", "2901106"], + ["BA", "Am\U000000e9rica Dourada", "2901155"], + ["BA", "Anag\U000000e9", "2901205"], + ["BA", "Andara\U000000ed", "2901304"], + ["BA", "Andorinha", "2901353"], + ["BA", "Angical", "2901403"], + ["BA", "Anguera", "2901502"], + ["BA", "Antas", "2901601"], + ["BA", "Ant\U000000f4nio Cardoso", "2901700"], + ["BA", "Ant\U000000f4nio Gon\U000000e7alves", "2901809"], + ["BA", "Apor\U000000e1", "2901908"], + ["BA", "Apuarema", "2901957"], + ["BA", "Ara\U000000e7\U000000e1s", "2902054"], + ["BA", "Aracatu", "2902005"], + ["BA", "Araci", "2902104"], + ["BA", "Aramari", "2902203"], + ["BA", "Arataca", "2902252"], + ["BA", "Aratu\U000000edpe", "2902302"], + ["BA", "Aurelino Leal", "2902401"], + ["BA", "Baian\U000000f3polis", "2902500"], + ["BA", "Baixa Grande", "2902609"], + ["BA", "Banza\U000000ea", "2902658"], + ["BA", "Barra", "2902708"], + ["BA", "Barra da Estiva", "2902807"], + ["BA", "Barra do Cho\U000000e7a", "2902906"], + ["BA", "Barra do Mendes", "2903003"], + ["BA", "Barra do Rocha", "2903102"], + ["BA", "Barreiras", "2903201"], + ["BA", "Barro Alto", "2903235"], + ["BA", "Barro Preto", "2903300"], + ["BA", "Barrocas", "2903276"], + ["BA", "Belmonte", "2903409"], + ["BA", "Belo Campo", "2903508"], + ["BA", "Biritinga", "2903607"], + ["BA", "Boa Nova", "2903706"], + ["BA", "Boa Vista do Tupim", "2903805"], + ["BA", "Bom Jesus da Lapa", "2903904"], + ["BA", "Bom Jesus da Serra", "2903953"], + ["BA", "Boninal", "2904001"], + ["BA", "Bonito", "2904050"], + ["BA", "Boquira", "2904100"], + ["BA", "Botupor\U000000e3", "2904209"], + ["BA", "Brej\U000000f5es", "2904308"], + ["BA", "Brejol\U000000e2ndia", "2904407"], + ["BA", "Brotas de Maca\U000000fabas", "2904506"], + ["BA", "Brumado", "2904605"], + ["BA", "Buerarema", "2904704"], + ["BA", "Buritirama", "2904753"], + ["BA", "Caatiba", "2904803"], + ["BA", "Cabaceiras do Paragua\U000000e7u", "2904852"], + ["BA", "Cachoeira", "2904902"], + ["BA", "Cacul\U000000e9", "2905008"], + ["BA", "Ca\U000000e9m", "2905107"], + ["BA", "Caetanos", "2905156"], + ["BA", "Caetit\U000000e9", "2905206"], + ["BA", "Cafarnaum", "2905305"], + ["BA", "Cairu", "2905404"], + ["BA", "Caldeir\U000000e3o Grande", "2905503"], + ["BA", "Camacan", "2905602"], + ["BA", "Cama\U000000e7ari", "2905701"], + ["BA", "Camamu", "2905800"], + ["BA", "Campo Alegre de Lourdes", "2905909"], + ["BA", "Campo Formoso", "2906006"], + ["BA", "Can\U000000e1polis", "2906105"], + ["BA", "Canarana", "2906204"], + ["BA", "Canavieiras", "2906303"], + ["BA", "Candeal", "2906402"], + ["BA", "Candeias", "2906501"], + ["BA", "Candiba", "2906600"], + ["BA", "C\U000000e2ndido Sales", "2906709"], + ["BA", "Cansan\U000000e7\U000000e3o", "2906808"], + ["BA", "Canudos", "2906824"], + ["BA", "Capela do Alto Alegre", "2906857"], + ["BA", "Capim Grosso", "2906873"], + ["BA", "Cara\U000000edbas", "2906899"], + ["BA", "Caravelas", "2906907"], + ["BA", "Cardeal da Silva", "2907004"], + ["BA", "Carinhanha", "2907103"], + ["BA", "Casa Nova", "2907202"], + ["BA", "Castro Alves", "2907301"], + ["BA", "Catol\U000000e2ndia", "2907400"], + ["BA", "Catu", "2907509"], + ["BA", "Caturama", "2907558"], + ["BA", "Central", "2907608"], + ["BA", "Chorroch\U000000f3", "2907707"], + ["BA", "C\U000000edcero Dantas", "2907806"], + ["BA", "Cip\U000000f3", "2907905"], + ["BA", "Coaraci", "2908002"], + ["BA", "Cocos", "2908101"], + ["BA", "Concei\U000000e7\U000000e3o da Feira", "2908200"], + ["BA", "Concei\U000000e7\U000000e3o do Almeida", "2908309"], + ["BA", "Concei\U000000e7\U000000e3o do Coit\U000000e9", "2908408"], + ["BA", "Concei\U000000e7\U000000e3o do Jacu\U000000edpe", "2908507"], + ["BA", "Conde", "2908606"], + ["BA", "Conde\U000000faba", "2908705"], + ["BA", "Contendas do Sincor\U000000e1", "2908804"], + ["BA", "Cora\U000000e7\U000000e3o de Maria", "2908903"], + ["BA", "Cordeiros", "2909000"], + ["BA", "Coribe", "2909109"], + ["BA", "Coronel Jo\U000000e3o S\U000000e1", "2909208"], + ["BA", "Correntina", "2909307"], + ["BA", "Cotegipe", "2909406"], + ["BA", "Cravol\U000000e2ndia", "2909505"], + ["BA", "Cris\U000000f3polis", "2909604"], + ["BA", "Crist\U000000f3polis", "2909703"], + ["BA", "Cruz das Almas", "2909802"], + ["BA", "Cura\U000000e7\U000000e1", "2909901"], + ["BA", "D\U000000e1rio Meira", "2910008"], + ["BA", "Dias d'\U000000c1vila", "2910057"], + ["BA", "Dom Bas\U000000edlio", "2910107"], + ["BA", "Dom Macedo Costa", "2910206"], + ["BA", "El\U000000edsio Medrado", "2910305"], + ["BA", "Encruzilhada", "2910404"], + ["BA", "Entre Rios", "2910503"], + ["BA", "\U000000c9rico Cardoso", "2900504"], + ["BA", "Esplanada", "2910602"], + ["BA", "Euclides da Cunha", "2910701"], + ["BA", "Eun\U000000e1polis", "2910727"], + ["BA", "F\U000000e1tima", "2910750"], + ["BA", "Feira da Mata", "2910776"], + ["BA", "Feira de Santana", "2910800"], + ["BA", "Filad\U000000e9lfia", "2910859"], + ["BA", "Firmino Alves", "2910909"], + ["BA", "Floresta Azul", "2911006"], + ["BA", "Formosa do Rio Preto", "2911105"], + ["BA", "Gandu", "2911204"], + ["BA", "Gavi\U000000e3o", "2911253"], + ["BA", "Gentio do Ouro", "2911303"], + ["BA", "Gl\U000000f3ria", "2911402"], + ["BA", "Gongogi", "2911501"], + ["BA", "Governador Mangabeira", "2911600"], + ["BA", "Guajeru", "2911659"], + ["BA", "Guanambi", "2911709"], + ["BA", "Guaratinga", "2911808"], + ["BA", "Heli\U000000f3polis", "2911857"], + ["BA", "Ia\U000000e7u", "2911907"], + ["BA", "Ibiassuc\U000000ea", "2912004"], + ["BA", "Ibicara\U000000ed", "2912103"], + ["BA", "Ibicoara", "2912202"], + ["BA", "Ibicu\U000000ed", "2912301"], + ["BA", "Ibipeba", "2912400"], + ["BA", "Ibipitanga", "2912509"], + ["BA", "Ibiquera", "2912608"], + ["BA", "Ibirapitanga", "2912707"], + ["BA", "Ibirapu\U000000e3", "2912806"], + ["BA", "Ibirataia", "2912905"], + ["BA", "Ibitiara", "2913002"], + ["BA", "Ibitit\U000000e1", "2913101"], + ["BA", "Ibotirama", "2913200"], + ["BA", "Ichu", "2913309"], + ["BA", "Igapor\U000000e3", "2913408"], + ["BA", "Igrapi\U000000fana", "2913457"], + ["BA", "Igua\U000000ed", "2913507"], + ["BA", "Ilh\U000000e9us", "2913606"], + ["BA", "Inhambupe", "2913705"], + ["BA", "Ipecaet\U000000e1", "2913804"], + ["BA", "Ipia\U000000fa", "2913903"], + ["BA", "Ipir\U000000e1", "2914000"], + ["BA", "Ipupiara", "2914109"], + ["BA", "Irajuba", "2914208"], + ["BA", "Iramaia", "2914307"], + ["BA", "Iraquara", "2914406"], + ["BA", "Irar\U000000e1", "2914505"], + ["BA", "Irec\U000000ea", "2914604"], + ["BA", "Itabela", "2914653"], + ["BA", "Itaberaba", "2914703"], + ["BA", "Itabuna", "2914802"], + ["BA", "Itacar\U000000e9", "2914901"], + ["BA", "Itaet\U000000e9", "2915007"], + ["BA", "Itagi", "2915106"], + ["BA", "Itagib\U000000e1", "2915205"], + ["BA", "Itagimirim", "2915304"], + ["BA", "Itagua\U000000e7u da Bahia", "2915353"], + ["BA", "Itaju do Col\U000000f4nia", "2915403"], + ["BA", "Itaju\U000000edpe", "2915502"], + ["BA", "Itamaraju", "2915601"], + ["BA", "Itamari", "2915700"], + ["BA", "Itamb\U000000e9", "2915809"], + ["BA", "Itanagra", "2915908"], + ["BA", "Itanh\U000000e9m", "2916005"], + ["BA", "Itaparica", "2916104"], + ["BA", "Itap\U000000e9", "2916203"], + ["BA", "Itapebi", "2916302"], + ["BA", "Itapetinga", "2916401"], + ["BA", "Itapicuru", "2916500"], + ["BA", "Itapitanga", "2916609"], + ["BA", "Itaquara", "2916708"], + ["BA", "Itarantim", "2916807"], + ["BA", "Itatim", "2916856"], + ["BA", "Itiru\U000000e7u", "2916906"], + ["BA", "Iti\U000000faba", "2917003"], + ["BA", "Itoror\U000000f3", "2917102"], + ["BA", "Itua\U000000e7u", "2917201"], + ["BA", "Ituber\U000000e1", "2917300"], + ["BA", "Iuiu", "2917334"], + ["BA", "Jaborandi", "2917359"], + ["BA", "Jacaraci", "2917409"], + ["BA", "Jacobina", "2917508"], + ["BA", "Jaguaquara", "2917607"], + ["BA", "Jaguarari", "2917706"], + ["BA", "Jaguaripe", "2917805"], + ["BA", "Janda\U000000edra", "2917904"], + ["BA", "Jequi\U000000e9", "2918001"], + ["BA", "Jeremoabo", "2918100"], + ["BA", "Jiquiri\U000000e7\U000000e1", "2918209"], + ["BA", "Jita\U000000fana", "2918308"], + ["BA", "Jo\U000000e3o Dourado", "2918357"], + ["BA", "Juazeiro", "2918407"], + ["BA", "Jucuru\U000000e7u", "2918456"], + ["BA", "Jussara", "2918506"], + ["BA", "Jussari", "2918555"], + ["BA", "Jussiape", "2918605"], + ["BA", "Lafaiete Coutinho", "2918704"], + ["BA", "Lagoa Real", "2918753"], + ["BA", "Laje", "2918803"], + ["BA", "Lajed\U000000e3o", "2918902"], + ["BA", "Lajedinho", "2919009"], + ["BA", "Lajedo do Tabocal", "2919058"], + ["BA", "Lamar\U000000e3o", "2919108"], + ["BA", "Lap\U000000e3o", "2919157"], + ["BA", "Lauro de Freitas", "2919207"], + ["BA", "Len\U000000e7\U000000f3is", "2919306"], + ["BA", "Lic\U000000ednio de Almeida", "2919405"], + ["BA", "Livramento de Nossa Senhora", "2919504"], + ["BA", "Lu\U000000eds Eduardo Magalh\U000000e3es", "2919553"], + ["BA", "Macajuba", "2919603"], + ["BA", "Macarani", "2919702"], + ["BA", "Maca\U000000fabas", "2919801"], + ["BA", "Macurur\U000000e9", "2919900"], + ["BA", "Madre de Deus", "2919926"], + ["BA", "Maetinga", "2919959"], + ["BA", "Maiquinique", "2920007"], + ["BA", "Mairi", "2920106"], + ["BA", "Malhada", "2920205"], + ["BA", "Malhada de Pedras", "2920304"], + ["BA", "Manoel Vitorino", "2920403"], + ["BA", "Mansid\U000000e3o", "2920452"], + ["BA", "Marac\U000000e1s", "2920502"], + ["BA", "Maragogipe", "2920601"], + ["BA", "Mara\U000000fa", "2920700"], + ["BA", "Marcion\U000000edlio Souza", "2920809"], + ["BA", "Mascote", "2920908"], + ["BA", "Mata de S\U000000e3o Jo\U000000e3o", "2921005"], + ["BA", "Matina", "2921054"], + ["BA", "Medeiros Neto", "2921104"], + ["BA", "Miguel Calmon", "2921203"], + ["BA", "Milagres", "2921302"], + ["BA", "Mirangaba", "2921401"], + ["BA", "Mirante", "2921450"], + ["BA", "Monte Santo", "2921500"], + ["BA", "Morpar\U000000e1", "2921609"], + ["BA", "Morro do Chap\U000000e9u", "2921708"], + ["BA", "Mortugaba", "2921807"], + ["BA", "Mucug\U000000ea", "2921906"], + ["BA", "Mucuri", "2922003"], + ["BA", "Mulungu do Morro", "2922052"], + ["BA", "Mundo Novo", "2922102"], + ["BA", "Muniz Ferreira", "2922201"], + ["BA", "Muqu\U000000e9m do S\U000000e3o Francisco", "2922250"], + ["BA", "Muritiba", "2922300"], + ["BA", "Mutu\U000000edpe", "2922409"], + ["BA", "Nazar\U000000e9", "2922508"], + ["BA", "Nilo Pe\U000000e7anha", "2922607"], + ["BA", "Nordestina", "2922656"], + ["BA", "Nova Cana\U000000e3", "2922706"], + ["BA", "Nova F\U000000e1tima", "2922730"], + ["BA", "Nova Ibi\U000000e1", "2922755"], + ["BA", "Nova Itarana", "2922805"], + ["BA", "Nova Reden\U000000e7\U000000e3o", "2922854"], + ["BA", "Nova Soure", "2922904"], + ["BA", "Nova Vi\U000000e7osa", "2923001"], + ["BA", "Novo Horizonte", "2923035"], + ["BA", "Novo Triunfo", "2923050"], + ["BA", "Olindina", "2923100"], + ["BA", "Oliveira dos Brejinhos", "2923209"], + ["BA", "Ouri\U000000e7angas", "2923308"], + ["BA", "Ourol\U000000e2ndia", "2923357"], + ["BA", "Palmas de Monte Alto", "2923407"], + ["BA", "Palmeiras", "2923506"], + ["BA", "Paramirim", "2923605"], + ["BA", "Paratinga", "2923704"], + ["BA", "Paripiranga", "2923803"], + ["BA", "Pau Brasil", "2923902"], + ["BA", "Paulo Afonso", "2924009"], + ["BA", "P\U000000e9 de Serra", "2924058"], + ["BA", "Pedr\U000000e3o", "2924108"], + ["BA", "Pedro Alexandre", "2924207"], + ["BA", "Piat\U000000e3", "2924306"], + ["BA", "Pil\U000000e3o Arcado", "2924405"], + ["BA", "Pinda\U000000ed", "2924504"], + ["BA", "Pindoba\U000000e7u", "2924603"], + ["BA", "Pintadas", "2924652"], + ["BA", "Pira\U000000ed do Norte", "2924678"], + ["BA", "Pirip\U000000e1", "2924702"], + ["BA", "Piritiba", "2924801"], + ["BA", "Planaltino", "2924900"], + ["BA", "Planalto", "2925006"], + ["BA", "Po\U000000e7\U000000f5es", "2925105"], + ["BA", "Pojuca", "2925204"], + ["BA", "Ponto Novo", "2925253"], + ["BA", "Porto Seguro", "2925303"], + ["BA", "Potiragu\U000000e1", "2925402"], + ["BA", "Prado", "2925501"], + ["BA", "Presidente Dutra", "2925600"], + ["BA", "Presidente J\U000000e2nio Quadros", "2925709"], + ["BA", "Presidente Tancredo Neves", "2925758"], + ["BA", "Queimadas", "2925808"], + ["BA", "Quijingue", "2925907"], + ["BA", "Quixabeira", "2925931"], + ["BA", "Rafael Jambeiro", "2925956"], + ["BA", "Remanso", "2926004"], + ["BA", "Retirol\U000000e2ndia", "2926103"], + ["BA", "Riach\U000000e3o das Neves", "2926202"], + ["BA", "Riach\U000000e3o do Jacu\U000000edpe", "2926301"], + ["BA", "Riacho de Santana", "2926400"], + ["BA", "Ribeira do Amparo", "2926509"], + ["BA", "Ribeira do Pombal", "2926608"], + ["BA", "Ribeir\U000000e3o do Largo", "2926657"], + ["BA", "Rio de Contas", "2926707"], + ["BA", "Rio do Ant\U000000f4nio", "2926806"], + ["BA", "Rio do Pires", "2926905"], + ["BA", "Rio Real", "2927002"], + ["BA", "Rodelas", "2927101"], + ["BA", "Ruy Barbosa", "2927200"], + ["BA", "Salinas da Margarida", "2927309"], + ["BA", "Salvador", "2927408"], + ["BA", "Santa B\U000000e1rbara", "2927507"], + ["BA", "Santa Br\U000000edgida", "2927606"], + ["BA", "Santa Cruz Cabr\U000000e1lia", "2927705"], + ["BA", "Santa Cruz da Vit\U000000f3ria", "2927804"], + ["BA", "Santa In\U000000eas", "2927903"], + ["BA", "Santa Luzia", "2928059"], + ["BA", "Santa Maria da Vit\U000000f3ria", "2928109"], + ["BA", "Santa Rita de C\U000000e1ssia", "2928406"], + ["BA", "Santa Terezinha", "2928505"], + ["BA", "Santaluz", "2928000"], + ["BA", "Santana", "2928208"], + ["BA", "Santan\U000000f3polis", "2928307"], + ["BA", "Santo Amaro", "2928604"], + ["BA", "Santo Ant\U000000f4nio de Jesus", "2928703"], + ["BA", "Santo Est\U000000eav\U000000e3o", "2928802"], + ["BA", "S\U000000e3o Desid\U000000e9rio", "2928901"], + ["BA", "S\U000000e3o Domingos", "2928950"], + ["BA", "S\U000000e3o Felipe", "2929107"], + ["BA", "S\U000000e3o F\U000000e9lix", "2929008"], + ["BA", "S\U000000e3o F\U000000e9lix do Coribe", "2929057"], + ["BA", "S\U000000e3o Francisco do Conde", "2929206"], + ["BA", "S\U000000e3o Gabriel", "2929255"], + ["BA", "S\U000000e3o Gon\U000000e7alo dos Campos", "2929305"], + ["BA", "S\U000000e3o Jos\U000000e9 da Vit\U000000f3ria", "2929354"], + ["BA", "S\U000000e3o Jos\U000000e9 do Jacu\U000000edpe", "2929370"], + ["BA", "S\U000000e3o Miguel das Matas", "2929404"], + ["BA", "S\U000000e3o Sebasti\U000000e3o do Pass\U000000e9", "2929503"], + ["BA", "Sapea\U000000e7u", "2929602"], + ["BA", "S\U000000e1tiro Dias", "2929701"], + ["BA", "Saubara", "2929750"], + ["BA", "Sa\U000000fade", "2929800"], + ["BA", "Seabra", "2929909"], + ["BA", "Sebasti\U000000e3o Laranjeiras", "2930006"], + ["BA", "Senhor do Bonfim", "2930105"], + ["BA", "Sento S\U000000e9", "2930204"], + ["BA", "Serra do Ramalho", "2930154"], + ["BA", "Serra Dourada", "2930303"], + ["BA", "Serra Preta", "2930402"], + ["BA", "Serrinha", "2930501"], + ["BA", "Serrol\U000000e2ndia", "2930600"], + ["BA", "Sim\U000000f5es Filho", "2930709"], + ["BA", "S\U000000edtio do Mato", "2930758"], + ["BA", "S\U000000edtio do Quinto", "2930766"], + ["BA", "Sobradinho", "2930774"], + ["BA", "Souto Soares", "2930808"], + ["BA", "Tabocas do Brejo Velho", "2930907"], + ["BA", "Tanha\U000000e7u", "2931004"], + ["BA", "Tanque Novo", "2931053"], + ["BA", "Tanquinho", "2931103"], + ["BA", "Tapero\U000000e1", "2931202"], + ["BA", "Tapiramut\U000000e1", "2931301"], + ["BA", "Teixeira de Freitas", "2931350"], + ["BA", "Teodoro Sampaio", "2931400"], + ["BA", "Teofil\U000000e2ndia", "2931509"], + ["BA", "Teol\U000000e2ndia", "2931608"], + ["BA", "Terra Nova", "2931707"], + ["BA", "Tremedal", "2931806"], + ["BA", "Tucano", "2931905"], + ["BA", "Uau\U000000e1", "2932002"], + ["BA", "Uba\U000000edra", "2932101"], + ["BA", "Ubaitaba", "2932200"], + ["BA", "Ubat\U000000e3", "2932309"], + ["BA", "Uiba\U000000ed", "2932408"], + ["BA", "Umburanas", "2932457"], + ["BA", "Una", "2932507"], + ["BA", "Urandi", "2932606"], + ["BA", "Uru\U000000e7uca", "2932705"], + ["BA", "Utinga", "2932804"], + ["BA", "Valen\U000000e7a", "2932903"], + ["BA", "Valente", "2933000"], + ["BA", "V\U000000e1rzea da Ro\U000000e7a", "2933059"], + ["BA", "V\U000000e1rzea do Po\U000000e7o", "2933109"], + ["BA", "V\U000000e1rzea Nova", "2933158"], + ["BA", "Varzedo", "2933174"], + ["BA", "Vera Cruz", "2933208"], + ["BA", "Vereda", "2933257"], + ["BA", "Vit\U000000f3ria da Conquista", "2933307"], + ["BA", "Wagner", "2933406"], + ["BA", "Wanderley", "2933455"], + ["BA", "Wenceslau Guimar\U000000e3es", "2933505"], + ["BA", "Xique-Xique", "2933604"], + ["CE", "Abaiara", "2300101"], + ["CE", "Acarape", "2300150"], + ["CE", "Acara\U000000fa", "2300200"], + ["CE", "Acopiara", "2300309"], + ["CE", "Aiuaba", "2300408"], + ["CE", "Alc\U000000e2ntaras", "2300507"], + ["CE", "Altaneira", "2300606"], + ["CE", "Alto Santo", "2300705"], + ["CE", "Amontada", "2300754"], + ["CE", "Antonina do Norte", "2300804"], + ["CE", "Apuiar\U000000e9s", "2300903"], + ["CE", "Aquiraz", "2301000"], + ["CE", "Aracati", "2301109"], + ["CE", "Aracoiaba", "2301208"], + ["CE", "Ararend\U000000e1", "2301257"], + ["CE", "Araripe", "2301307"], + ["CE", "Aratuba", "2301406"], + ["CE", "Arneiroz", "2301505"], + ["CE", "Assar\U000000e9", "2301604"], + ["CE", "Aurora", "2301703"], + ["CE", "Baixio", "2301802"], + ["CE", "Banabui\U000000fa", "2301851"], + ["CE", "Barbalha", "2301901"], + ["CE", "Barreira", "2301950"], + ["CE", "Barro", "2302008"], + ["CE", "Barroquinha", "2302057"], + ["CE", "Baturit\U000000e9", "2302107"], + ["CE", "Beberibe", "2302206"], + ["CE", "Bela Cruz", "2302305"], + ["CE", "Boa Viagem", "2302404"], + ["CE", "Brejo Santo", "2302503"], + ["CE", "Camocim", "2302602"], + ["CE", "Campos Sales", "2302701"], + ["CE", "Canind\U000000e9", "2302800"], + ["CE", "Capistrano", "2302909"], + ["CE", "Caridade", "2303006"], + ["CE", "Carir\U000000e9", "2303105"], + ["CE", "Cariria\U000000e7u", "2303204"], + ["CE", "Cari\U000000fas", "2303303"], + ["CE", "Carnaubal", "2303402"], + ["CE", "Cascavel", "2303501"], + ["CE", "Catarina", "2303600"], + ["CE", "Catunda", "2303659"], + ["CE", "Caucaia", "2303709"], + ["CE", "Cedro", "2303808"], + ["CE", "Chaval", "2303907"], + ["CE", "Chor\U000000f3", "2303931"], + ["CE", "Chorozinho", "2303956"], + ["CE", "Corea\U000000fa", "2304004"], + ["CE", "Crate\U000000fas", "2304103"], + ["CE", "Crato", "2304202"], + ["CE", "Croat\U000000e1", "2304236"], + ["CE", "Cruz", "2304251"], + ["CE", "Deputado Irapuan Pinheiro", "2304269"], + ["CE", "Erer\U000000e9", "2304277"], + ["CE", "Eus\U000000e9bio", "2304285"], + ["CE", "Farias Brito", "2304301"], + ["CE", "Forquilha", "2304350"], + ["CE", "Fortaleza", "2304400"], + ["CE", "Fortim", "2304459"], + ["CE", "Frecheirinha", "2304509"], + ["CE", "General Sampaio", "2304608"], + ["CE", "Gra\U000000e7a", "2304657"], + ["CE", "Granja", "2304707"], + ["CE", "Granjeiro", "2304806"], + ["CE", "Groa\U000000edras", "2304905"], + ["CE", "Guai\U000000faba", "2304954"], + ["CE", "Guaraciaba do Norte", "2305001"], + ["CE", "Guaramiranga", "2305100"], + ["CE", "Hidrol\U000000e2ndia", "2305209"], + ["CE", "Horizonte", "2305233"], + ["CE", "Ibaretama", "2305266"], + ["CE", "Ibiapina", "2305308"], + ["CE", "Ibicuitinga", "2305332"], + ["CE", "Icapu\U000000ed", "2305357"], + ["CE", "Ic\U000000f3", "2305407"], + ["CE", "Iguatu", "2305506"], + ["CE", "Independ\U000000eancia", "2305605"], + ["CE", "Ipaporanga", "2305654"], + ["CE", "Ipaumirim", "2305704"], + ["CE", "Ipu", "2305803"], + ["CE", "Ipueiras", "2305902"], + ["CE", "Iracema", "2306009"], + ["CE", "Irau\U000000e7uba", "2306108"], + ["CE", "Itai\U000000e7aba", "2306207"], + ["CE", "Itaitinga", "2306256"], + ["CE", "Itapaj\U000000e9", "2306306"], + ["CE", "Itapipoca", "2306405"], + ["CE", "Itapi\U000000fana", "2306504"], + ["CE", "Itarema", "2306553"], + ["CE", "Itatira", "2306603"], + ["CE", "Jaguaretama", "2306702"], + ["CE", "Jaguaribara", "2306801"], + ["CE", "Jaguaribe", "2306900"], + ["CE", "Jaguaruana", "2307007"], + ["CE", "Jardim", "2307106"], + ["CE", "Jati", "2307205"], + ["CE", "Jijoca de Jericoacoara", "2307254"], + ["CE", "Juazeiro do Norte", "2307304"], + ["CE", "Juc\U000000e1s", "2307403"], + ["CE", "Lavras da Mangabeira", "2307502"], + ["CE", "Limoeiro do Norte", "2307601"], + ["CE", "Madalena", "2307635"], + ["CE", "Maracana\U000000fa", "2307650"], + ["CE", "Maranguape", "2307700"], + ["CE", "Marco", "2307809"], + ["CE", "Martin\U000000f3pole", "2307908"], + ["CE", "Massap\U000000ea", "2308005"], + ["CE", "Mauriti", "2308104"], + ["CE", "Meruoca", "2308203"], + ["CE", "Milagres", "2308302"], + ["CE", "Milh\U000000e3", "2308351"], + ["CE", "Mira\U000000edma", "2308377"], + ["CE", "Miss\U000000e3o Velha", "2308401"], + ["CE", "Momba\U000000e7a", "2308500"], + ["CE", "Monsenhor Tabosa", "2308609"], + ["CE", "Morada Nova", "2308708"], + ["CE", "Mora\U000000fajo", "2308807"], + ["CE", "Morrinhos", "2308906"], + ["CE", "Mucambo", "2309003"], + ["CE", "Mulungu", "2309102"], + ["CE", "Nova Olinda", "2309201"], + ["CE", "Nova Russas", "2309300"], + ["CE", "Novo Oriente", "2309409"], + ["CE", "Ocara", "2309458"], + ["CE", "Or\U000000f3s", "2309508"], + ["CE", "Pacajus", "2309607"], + ["CE", "Pacatuba", "2309706"], + ["CE", "Pacoti", "2309805"], + ["CE", "Pacuj\U000000e1", "2309904"], + ["CE", "Palhano", "2310001"], + ["CE", "Palm\U000000e1cia", "2310100"], + ["CE", "Paracuru", "2310209"], + ["CE", "Paraipaba", "2310258"], + ["CE", "Parambu", "2310308"], + ["CE", "Paramoti", "2310407"], + ["CE", "Pedra Branca", "2310506"], + ["CE", "Penaforte", "2310605"], + ["CE", "Pentecoste", "2310704"], + ["CE", "Pereiro", "2310803"], + ["CE", "Pindoretama", "2310852"], + ["CE", "Piquet Carneiro", "2310902"], + ["CE", "Pires Ferreira", "2310951"], + ["CE", "Poranga", "2311009"], + ["CE", "Porteiras", "2311108"], + ["CE", "Potengi", "2311207"], + ["CE", "Potiretama", "2311231"], + ["CE", "Quiterian\U000000f3polis", "2311264"], + ["CE", "Quixad\U000000e1", "2311306"], + ["CE", "Quixel\U000000f4", "2311355"], + ["CE", "Quixeramobim", "2311405"], + ["CE", "Quixer\U000000e9", "2311504"], + ["CE", "Reden\U000000e7\U000000e3o", "2311603"], + ["CE", "Reriutaba", "2311702"], + ["CE", "Russas", "2311801"], + ["CE", "Saboeiro", "2311900"], + ["CE", "Salitre", "2311959"], + ["CE", "Santa Quit\U000000e9ria", "2312205"], + ["CE", "Santana do Acara\U000000fa", "2312007"], + ["CE", "Santana do Cariri", "2312106"], + ["CE", "S\U000000e3o Benedito", "2312304"], + ["CE", "S\U000000e3o Gon\U000000e7alo do Amarante", "2312403"], + ["CE", "S\U000000e3o Jo\U000000e3o do Jaguaribe", "2312502"], + ["CE", "S\U000000e3o Lu\U000000eds do Curu", "2312601"], + ["CE", "Senador Pompeu", "2312700"], + ["CE", "Senador S\U000000e1", "2312809"], + ["CE", "Sobral", "2312908"], + ["CE", "Solon\U000000f3pole", "2313005"], + ["CE", "Tabuleiro do Norte", "2313104"], + ["CE", "Tamboril", "2313203"], + ["CE", "Tarrafas", "2313252"], + ["CE", "Tau\U000000e1", "2313302"], + ["CE", "Teju\U000000e7uoca", "2313351"], + ["CE", "Tiangu\U000000e1", "2313401"], + ["CE", "Trairi", "2313500"], + ["CE", "Tururu", "2313559"], + ["CE", "Ubajara", "2313609"], + ["CE", "Umari", "2313708"], + ["CE", "Umirim", "2313757"], + ["CE", "Uruburetama", "2313807"], + ["CE", "Uruoca", "2313906"], + ["CE", "Varjota", "2313955"], + ["CE", "V\U000000e1rzea Alegre", "2314003"], + ["CE", "Vi\U000000e7osa do Cear\U000000e1", "2314102"], + ["DF", "Bras\U000000edlia", "5300108"], + ["ES", "Afonso Cl\U000000e1udio", "3200102"], + ["ES", "\U000000c1gua Doce do Norte", "3200169"], + ["ES", "\U000000c1guia Branca", "3200136"], + ["ES", "Alegre", "3200201"], + ["ES", "Alfredo Chaves", "3200300"], + ["ES", "Alto Rio Novo", "3200359"], + ["ES", "Anchieta", "3200409"], + ["ES", "Apiac\U000000e1", "3200508"], + ["ES", "Aracruz", "3200607"], + ["ES", "At\U000000edlio Viv\U000000e1cqua", "3200706"], + ["ES", "Baixo Guandu", "3200805"], + ["ES", "Barra de S\U000000e3o Francisco", "3200904"], + ["ES", "Boa Esperan\U000000e7a", "3201001"], + ["ES", "Bom Jesus do Norte", "3201100"], + ["ES", "Brejetuba", "3201159"], + ["ES", "Cachoeiro de Itapemirim", "3201209"], + ["ES", "Cariacica", "3201308"], + ["ES", "Castelo", "3201407"], + ["ES", "Colatina", "3201506"], + ["ES", "Concei\U000000e7\U000000e3o da Barra", "3201605"], + ["ES", "Concei\U000000e7\U000000e3o do Castelo", "3201704"], + ["ES", "Divino de S\U000000e3o Louren\U000000e7o", "3201803"], + ["ES", "Domingos Martins", "3201902"], + ["ES", "Dores do Rio Preto", "3202009"], + ["ES", "Ecoporanga", "3202108"], + ["ES", "Fund\U000000e3o", "3202207"], + ["ES", "Governador Lindenberg", "3202256"], + ["ES", "Gua\U000000e7u\U000000ed", "3202306"], + ["ES", "Guarapari", "3202405"], + ["ES", "Ibatiba", "3202454"], + ["ES", "Ibira\U000000e7u", "3202504"], + ["ES", "Ibitirama", "3202553"], + ["ES", "Iconha", "3202603"], + ["ES", "Irupi", "3202652"], + ["ES", "Itagua\U000000e7u", "3202702"], + ["ES", "Itapemirim", "3202801"], + ["ES", "Itarana", "3202900"], + ["ES", "I\U000000fana", "3203007"], + ["ES", "Jaguar\U000000e9", "3203056"], + ["ES", "Jer\U000000f4nimo Monteiro", "3203106"], + ["ES", "Jo\U000000e3o Neiva", "3203130"], + ["ES", "Laranja da Terra", "3203163"], + ["ES", "Linhares", "3203205"], + ["ES", "Manten\U000000f3polis", "3203304"], + ["ES", "Marata\U000000edzes", "3203320"], + ["ES", "Marechal Floriano", "3203346"], + ["ES", "Maril\U000000e2ndia", "3203353"], + ["ES", "Mimoso do Sul", "3203403"], + ["ES", "Montanha", "3203502"], + ["ES", "Mucurici", "3203601"], + ["ES", "Muniz Freire", "3203700"], + ["ES", "Muqui", "3203809"], + ["ES", "Nova Ven\U000000e9cia", "3203908"], + ["ES", "Pancas", "3204005"], + ["ES", "Pedro Can\U000000e1rio", "3204054"], + ["ES", "Pinheiros", "3204104"], + ["ES", "Pi\U000000fama", "3204203"], + ["ES", "Ponto Belo", "3204252"], + ["ES", "Presidente Kennedy", "3204302"], + ["ES", "Rio Bananal", "3204351"], + ["ES", "Rio Novo do Sul", "3204401"], + ["ES", "Santa Leopoldina", "3204500"], + ["ES", "Santa Maria de Jetib\U000000e1", "3204559"], + ["ES", "Santa Teresa", "3204609"], + ["ES", "S\U000000e3o Domingos do Norte", "3204658"], + ["ES", "S\U000000e3o Gabriel da Palha", "3204708"], + ["ES", "S\U000000e3o Jos\U000000e9 do Cal\U000000e7ado", "3204807"], + ["ES", "S\U000000e3o Mateus", "3204906"], + ["ES", "S\U000000e3o Roque do Cana\U000000e3", "3204955"], + ["ES", "Serra", "3205002"], + ["ES", "Sooretama", "3205010"], + ["ES", "Vargem Alta", "3205036"], + ["ES", "Venda Nova do Imigrante", "3205069"], + ["ES", "Viana", "3205101"], + ["ES", "Vila Pav\U000000e3o", "3205150"], + ["ES", "Vila Val\U000000e9rio", "3205176"], + ["ES", "Vila Velha", "3205200"], + ["ES", "Vit\U000000f3ria", "3205309"], + ["GO", "Abadia de Goi\U000000e1s", "5200050"], + ["GO", "Abadi\U000000e2nia", "5200100"], + ["GO", "Acre\U000000fana", "5200134"], + ["GO", "Adel\U000000e2ndia", "5200159"], + ["GO", "\U000000c1gua Fria de Goi\U000000e1s", "5200175"], + ["GO", "\U000000c1gua Limpa", "5200209"], + ["GO", "\U000000c1guas Lindas de Goi\U000000e1s", "5200258"], + ["GO", "Alex\U000000e2nia", "5200308"], + ["GO", "Alo\U000000e2ndia", "5200506"], + ["GO", "Alto Horizonte", "5200555"], + ["GO", "Alto Para\U000000edso de Goi\U000000e1s", "5200605"], + ["GO", "Alvorada do Norte", "5200803"], + ["GO", "Amaralina", "5200829"], + ["GO", "Americano do Brasil", "5200852"], + ["GO", "Amorin\U000000f3polis", "5200902"], + ["GO", "An\U000000e1polis", "5201108"], + ["GO", "Anhanguera", "5201207"], + ["GO", "Anicuns", "5201306"], + ["GO", "Aparecida de Goi\U000000e2nia", "5201405"], + ["GO", "Aparecida do Rio Doce", "5201454"], + ["GO", "Apor\U000000e9", "5201504"], + ["GO", "Ara\U000000e7u", "5201603"], + ["GO", "Aragar\U000000e7as", "5201702"], + ["GO", "Aragoi\U000000e2nia", "5201801"], + ["GO", "Araguapaz", "5202155"], + ["GO", "Aren\U000000f3polis", "5202353"], + ["GO", "Aruan\U000000e3", "5202502"], + ["GO", "Auril\U000000e2ndia", "5202601"], + ["GO", "Avelin\U000000f3polis", "5202809"], + ["GO", "Baliza", "5203104"], + ["GO", "Barro Alto", "5203203"], + ["GO", "Bela Vista de Goi\U000000e1s", "5203302"], + ["GO", "Bom Jardim de Goi\U000000e1s", "5203401"], + ["GO", "Bom Jesus de Goi\U000000e1s", "5203500"], + ["GO", "Bonfin\U000000f3polis", "5203559"], + ["GO", "Bon\U000000f3polis", "5203575"], + ["GO", "Brazabrantes", "5203609"], + ["GO", "Brit\U000000e2nia", "5203807"], + ["GO", "Buriti Alegre", "5203906"], + ["GO", "Buriti de Goi\U000000e1s", "5203939"], + ["GO", "Buritin\U000000f3polis", "5203962"], + ["GO", "Cabeceiras", "5204003"], + ["GO", "Cachoeira Alta", "5204102"], + ["GO", "Cachoeira de Goi\U000000e1s", "5204201"], + ["GO", "Cachoeira Dourada", "5204250"], + ["GO", "Ca\U000000e7u", "5204300"], + ["GO", "Caiap\U000000f4nia", "5204409"], + ["GO", "Caldas Novas", "5204508"], + ["GO", "Caldazinha", "5204557"], + ["GO", "Campestre de Goi\U000000e1s", "5204607"], + ["GO", "Campina\U000000e7u", "5204656"], + ["GO", "Campinorte", "5204706"], + ["GO", "Campo Alegre de Goi\U000000e1s", "5204805"], + ["GO", "Campo Limpo de Goi\U000000e1s", "5204854"], + ["GO", "Campos Belos", "5204904"], + ["GO", "Campos Verdes", "5204953"], + ["GO", "Carmo do Rio Verde", "5205000"], + ["GO", "Castel\U000000e2ndia", "5205059"], + ["GO", "Catal\U000000e3o", "5205109"], + ["GO", "Catura\U000000ed", "5205208"], + ["GO", "Cavalcante", "5205307"], + ["GO", "Ceres", "5205406"], + ["GO", "Cezarina", "5205455"], + ["GO", "Chapad\U000000e3o do C\U000000e9u", "5205471"], + ["GO", "Cidade Ocidental", "5205497"], + ["GO", "Cocalzinho de Goi\U000000e1s", "5205513"], + ["GO", "Colinas do Sul", "5205521"], + ["GO", "C\U000000f3rrego do Ouro", "5205703"], + ["GO", "Corumb\U000000e1 de Goi\U000000e1s", "5205802"], + ["GO", "Corumba\U000000edba", "5205901"], + ["GO", "Cristalina", "5206206"], + ["GO", "Cristian\U000000f3polis", "5206305"], + ["GO", "Crix\U000000e1s", "5206404"], + ["GO", "Crom\U000000ednia", "5206503"], + ["GO", "Cumari", "5206602"], + ["GO", "Damian\U000000f3polis", "5206701"], + ["GO", "Damol\U000000e2ndia", "5206800"], + ["GO", "Davin\U000000f3polis", "5206909"], + ["GO", "Diorama", "5207105"], + ["GO", "Divin\U000000f3polis de Goi\U000000e1s", "5208301"], + ["GO", "Doverl\U000000e2ndia", "5207253"], + ["GO", "Edealina", "5207352"], + ["GO", "Ed\U000000e9ia", "5207402"], + ["GO", "Estrela do Norte", "5207501"], + ["GO", "Faina", "5207535"], + ["GO", "Fazenda Nova", "5207600"], + ["GO", "Firmin\U000000f3polis", "5207808"], + ["GO", "Flores de Goi\U000000e1s", "5207907"], + ["GO", "Formosa", "5208004"], + ["GO", "Formoso", "5208103"], + ["GO", "Gameleira de Goi\U000000e1s", "5208152"], + ["GO", "Goian\U000000e1polis", "5208400"], + ["GO", "Goiandira", "5208509"], + ["GO", "Goian\U000000e9sia", "5208608"], + ["GO", "Goi\U000000e2nia", "5208707"], + ["GO", "Goianira", "5208806"], + ["GO", "Goi\U000000e1s", "5208905"], + ["GO", "Goiatuba", "5209101"], + ["GO", "Gouvel\U000000e2ndia", "5209150"], + ["GO", "Guap\U000000f3", "5209200"], + ["GO", "Guara\U000000edta", "5209291"], + ["GO", "Guarani de Goi\U000000e1s", "5209408"], + ["GO", "Guarinos", "5209457"], + ["GO", "Heitora\U000000ed", "5209606"], + ["GO", "Hidrol\U000000e2ndia", "5209705"], + ["GO", "Hidrolina", "5209804"], + ["GO", "Iaciara", "5209903"], + ["GO", "Inaciol\U000000e2ndia", "5209937"], + ["GO", "Indiara", "5209952"], + ["GO", "Inhumas", "5210000"], + ["GO", "Ipameri", "5210109"], + ["GO", "Ipiranga de Goi\U000000e1s", "5210158"], + ["GO", "Ipor\U000000e1", "5210208"], + ["GO", "Israel\U000000e2ndia", "5210307"], + ["GO", "Itabera\U000000ed", "5210406"], + ["GO", "Itaguari", "5210562"], + ["GO", "Itaguaru", "5210604"], + ["GO", "Itaj\U000000e1", "5210802"], + ["GO", "Itapaci", "5210901"], + ["GO", "Itapirapu\U000000e3", "5211008"], + ["GO", "Itapuranga", "5211206"], + ["GO", "Itarum\U000000e3", "5211305"], + ["GO", "Itau\U000000e7u", "5211404"], + ["GO", "Itumbiara", "5211503"], + ["GO", "Ivol\U000000e2ndia", "5211602"], + ["GO", "Jandaia", "5211701"], + ["GO", "Jaragu\U000000e1", "5211800"], + ["GO", "Jata\U000000ed", "5211909"], + ["GO", "Jaupaci", "5212006"], + ["GO", "Jes\U000000fapolis", "5212055"], + ["GO", "Jovi\U000000e2nia", "5212105"], + ["GO", "Jussara", "5212204"], + ["GO", "Lagoa Santa", "5212253"], + ["GO", "Leopoldo de Bulh\U000000f5es", "5212303"], + ["GO", "Luzi\U000000e2nia", "5212501"], + ["GO", "Mairipotaba", "5212600"], + ["GO", "Mamba\U000000ed", "5212709"], + ["GO", "Mara Rosa", "5212808"], + ["GO", "Marzag\U000000e3o", "5212907"], + ["GO", "Matrinch\U000000e3", "5212956"], + ["GO", "Mauril\U000000e2ndia", "5213004"], + ["GO", "Mimoso de Goi\U000000e1s", "5213053"], + ["GO", "Mina\U000000e7u", "5213087"], + ["GO", "Mineiros", "5213103"], + ["GO", "Moipor\U000000e1", "5213400"], + ["GO", "Monte Alegre de Goi\U000000e1s", "5213509"], + ["GO", "Montes Claros de Goi\U000000e1s", "5213707"], + ["GO", "Montividiu", "5213756"], + ["GO", "Montividiu do Norte", "5213772"], + ["GO", "Morrinhos", "5213806"], + ["GO", "Morro Agudo de Goi\U000000e1s", "5213855"], + ["GO", "Moss\U000000e2medes", "5213905"], + ["GO", "Mozarl\U000000e2ndia", "5214002"], + ["GO", "Mundo Novo", "5214051"], + ["GO", "Mutun\U000000f3polis", "5214101"], + ["GO", "Naz\U000000e1rio", "5214408"], + ["GO", "Ner\U000000f3polis", "5214507"], + ["GO", "Niquel\U000000e2ndia", "5214606"], + ["GO", "Nova Am\U000000e9rica", "5214705"], + ["GO", "Nova Aurora", "5214804"], + ["GO", "Nova Crix\U000000e1s", "5214838"], + ["GO", "Nova Gl\U000000f3ria", "5214861"], + ["GO", "Nova Igua\U000000e7u de Goi\U000000e1s", "5214879"], + ["GO", "Nova Roma", "5214903"], + ["GO", "Nova Veneza", "5215009"], + ["GO", "Novo Brasil", "5215207"], + ["GO", "Novo Gama", "5215231"], + ["GO", "Novo Planalto", "5215256"], + ["GO", "Orizona", "5215306"], + ["GO", "Ouro Verde de Goi\U000000e1s", "5215405"], + ["GO", "Ouvidor", "5215504"], + ["GO", "Padre Bernardo", "5215603"], + ["GO", "Palestina de Goi\U000000e1s", "5215652"], + ["GO", "Palmeiras de Goi\U000000e1s", "5215702"], + ["GO", "Palmelo", "5215801"], + ["GO", "Palmin\U000000f3polis", "5215900"], + ["GO", "Panam\U000000e1", "5216007"], + ["GO", "Paranaiguara", "5216304"], + ["GO", "Para\U000000fana", "5216403"], + ["GO", "Perol\U000000e2ndia", "5216452"], + ["GO", "Petrolina de Goi\U000000e1s", "5216809"], + ["GO", "Pilar de Goi\U000000e1s", "5216908"], + ["GO", "Piracanjuba", "5217104"], + ["GO", "Piranhas", "5217203"], + ["GO", "Piren\U000000f3polis", "5217302"], + ["GO", "Pires do Rio", "5217401"], + ["GO", "Planaltina", "5217609"], + ["GO", "Pontalina", "5217708"], + ["GO", "Porangatu", "5218003"], + ["GO", "Porteir\U000000e3o", "5218052"], + ["GO", "Portel\U000000e2ndia", "5218102"], + ["GO", "Posse", "5218300"], + ["GO", "Professor Jamil", "5218391"], + ["GO", "Quirin\U000000f3polis", "5218508"], + ["GO", "Rialma", "5218607"], + ["GO", "Rian\U000000e1polis", "5218706"], + ["GO", "Rio Quente", "5218789"], + ["GO", "Rio Verde", "5218805"], + ["GO", "Rubiataba", "5218904"], + ["GO", "Sanclerl\U000000e2ndia", "5219001"], + ["GO", "Santa B\U000000e1rbara de Goi\U000000e1s", "5219100"], + ["GO", "Santa Cruz de Goi\U000000e1s", "5219209"], + ["GO", "Santa F\U000000e9 de Goi\U000000e1s", "5219258"], + ["GO", "Santa Helena de Goi\U000000e1s", "5219308"], + ["GO", "Santa Isabel", "5219357"], + ["GO", "Santa Rita do Araguaia", "5219407"], + ["GO", "Santa Rita do Novo Destino", "5219456"], + ["GO", "Santa Rosa de Goi\U000000e1s", "5219506"], + ["GO", "Santa Tereza de Goi\U000000e1s", "5219605"], + ["GO", "Santa Terezinha de Goi\U000000e1s", "5219704"], + ["GO", "Santo Ant\U000000f4nio da Barra", "5219712"], + ["GO", "Santo Ant\U000000f4nio de Goi\U000000e1s", "5219738"], + ["GO", "Santo Ant\U000000f4nio do Descoberto", "5219753"], + ["GO", "S\U000000e3o Domingos", "5219803"], + ["GO", "S\U000000e3o Francisco de Goi\U000000e1s", "5219902"], + ["GO", "S\U000000e3o Jo\U000000e3o d'Alian\U000000e7a", "5220009"], + ["GO", "S\U000000e3o Jo\U000000e3o da Para\U000000fana", "5220058"], + ["GO", "S\U000000e3o Lu\U000000eds de Montes Belos", "5220108"], + ["GO", "S\U000000e3o Luiz do Norte", "5220157"], + ["GO", "S\U000000e3o Miguel do Araguaia", "5220207"], + ["GO", "S\U000000e3o Miguel do Passa Quatro", "5220264"], + ["GO", "S\U000000e3o Patr\U000000edcio", "5220280"], + ["GO", "S\U000000e3o Sim\U000000e3o", "5220405"], + ["GO", "Senador Canedo", "5220454"], + ["GO", "Serran\U000000f3polis", "5220504"], + ["GO", "Silv\U000000e2nia", "5220603"], + ["GO", "Simol\U000000e2ndia", "5220686"], + ["GO", "S\U000000edtio d'Abadia", "5220702"], + ["GO", "Taquaral de Goi\U000000e1s", "5221007"], + ["GO", "Teresina de Goi\U000000e1s", "5221080"], + ["GO", "Terez\U000000f3polis de Goi\U000000e1s", "5221197"], + ["GO", "Tr\U000000eas Ranchos", "5221304"], + ["GO", "Trindade", "5221403"], + ["GO", "Trombas", "5221452"], + ["GO", "Turv\U000000e2nia", "5221502"], + ["GO", "Turvel\U000000e2ndia", "5221551"], + ["GO", "Uirapuru", "5221577"], + ["GO", "Urua\U000000e7u", "5221601"], + ["GO", "Uruana", "5221700"], + ["GO", "Uruta\U000000ed", "5221809"], + ["GO", "Valpara\U000000edso de Goi\U000000e1s", "5221858"], + ["GO", "Varj\U000000e3o", "5221908"], + ["GO", "Vian\U000000f3polis", "5222005"], + ["GO", "Vicentin\U000000f3polis", "5222054"], + ["GO", "Vila Boa", "5222203"], + ["GO", "Vila Prop\U000000edcio", "5222302"], + ["MA", "A\U000000e7ail\U000000e2ndia", "2100055"], + ["MA", "Afonso Cunha", "2100105"], + ["MA", "\U000000c1gua Doce do Maranh\U000000e3o", "2100154"], + ["MA", "Alc\U000000e2ntara", "2100204"], + ["MA", "Aldeias Altas", "2100303"], + ["MA", "Altamira do Maranh\U000000e3o", "2100402"], + ["MA", "Alto Alegre do Maranh\U000000e3o", "2100436"], + ["MA", "Alto Alegre do Pindar\U000000e9", "2100477"], + ["MA", "Alto Parna\U000000edba", "2100501"], + ["MA", "Amap\U000000e1 do Maranh\U000000e3o", "2100550"], + ["MA", "Amarante do Maranh\U000000e3o", "2100600"], + ["MA", "Anajatuba", "2100709"], + ["MA", "Anapurus", "2100808"], + ["MA", "Apicum-A\U000000e7u", "2100832"], + ["MA", "Araguan\U000000e3", "2100873"], + ["MA", "Araioses", "2100907"], + ["MA", "Arame", "2100956"], + ["MA", "Arari", "2101004"], + ["MA", "Axix\U000000e1", "2101103"], + ["MA", "Bacabal", "2101202"], + ["MA", "Bacabeira", "2101251"], + ["MA", "Bacuri", "2101301"], + ["MA", "Bacurituba", "2101350"], + ["MA", "Balsas", "2101400"], + ["MA", "Bar\U000000e3o de Graja\U000000fa", "2101509"], + ["MA", "Barra do Corda", "2101608"], + ["MA", "Barreirinhas", "2101707"], + ["MA", "Bela Vista do Maranh\U000000e3o", "2101772"], + ["MA", "Bel\U000000e1gua", "2101731"], + ["MA", "Benedito Leite", "2101806"], + ["MA", "Bequim\U000000e3o", "2101905"], + ["MA", "Bernardo do Mearim", "2101939"], + ["MA", "Boa Vista do Gurupi", "2101970"], + ["MA", "Bom Jardim", "2102002"], + ["MA", "Bom Jesus das Selvas", "2102036"], + ["MA", "Bom Lugar", "2102077"], + ["MA", "Brejo", "2102101"], + ["MA", "Brejo de Areia", "2102150"], + ["MA", "Buriti", "2102200"], + ["MA", "Buriti Bravo", "2102309"], + ["MA", "Buriticupu", "2102325"], + ["MA", "Buritirana", "2102358"], + ["MA", "Cachoeira Grande", "2102374"], + ["MA", "Cajapi\U000000f3", "2102408"], + ["MA", "Cajari", "2102507"], + ["MA", "Campestre do Maranh\U000000e3o", "2102556"], + ["MA", "C\U000000e2ndido Mendes", "2102606"], + ["MA", "Cantanhede", "2102705"], + ["MA", "Capinzal do Norte", "2102754"], + ["MA", "Carolina", "2102804"], + ["MA", "Carutapera", "2102903"], + ["MA", "Caxias", "2103000"], + ["MA", "Cedral", "2103109"], + ["MA", "Central do Maranh\U000000e3o", "2103125"], + ["MA", "Centro do Guilherme", "2103158"], + ["MA", "Centro Novo do Maranh\U000000e3o", "2103174"], + ["MA", "Chapadinha", "2103208"], + ["MA", "Cidel\U000000e2ndia", "2103257"], + ["MA", "Cod\U000000f3", "2103307"], + ["MA", "Coelho Neto", "2103406"], + ["MA", "Colinas", "2103505"], + ["MA", "Concei\U000000e7\U000000e3o do Lago-A\U000000e7u", "2103554"], + ["MA", "Coroat\U000000e1", "2103604"], + ["MA", "Cururupu", "2103703"], + ["MA", "Davin\U000000f3polis", "2103752"], + ["MA", "Dom Pedro", "2103802"], + ["MA", "Duque Bacelar", "2103901"], + ["MA", "Esperantin\U000000f3polis", "2104008"], + ["MA", "Estreito", "2104057"], + ["MA", "Feira Nova do Maranh\U000000e3o", "2104073"], + ["MA", "Fernando Falc\U000000e3o", "2104081"], + ["MA", "Formosa da Serra Negra", "2104099"], + ["MA", "Fortaleza dos Nogueiras", "2104107"], + ["MA", "Fortuna", "2104206"], + ["MA", "Godofredo Viana", "2104305"], + ["MA", "Gon\U000000e7alves Dias", "2104404"], + ["MA", "Governador Archer", "2104503"], + ["MA", "Governador Edison Lob\U000000e3o", "2104552"], + ["MA", "Governador Eug\U000000eanio Barros", "2104602"], + ["MA", "Governador Luiz Rocha", "2104628"], + ["MA", "Governador Newton Bello", "2104651"], + ["MA", "Governador Nunes Freire", "2104677"], + ["MA", "Gra\U000000e7a Aranha", "2104701"], + ["MA", "Graja\U000000fa", "2104800"], + ["MA", "Guimar\U000000e3es", "2104909"], + ["MA", "Humberto de Campos", "2105005"], + ["MA", "Icatu", "2105104"], + ["MA", "Igarap\U000000e9 do Meio", "2105153"], + ["MA", "Igarap\U000000e9 Grande", "2105203"], + ["MA", "Imperatriz", "2105302"], + ["MA", "Itaipava do Graja\U000000fa", "2105351"], + ["MA", "Itapecuru Mirim", "2105401"], + ["MA", "Itinga do Maranh\U000000e3o", "2105427"], + ["MA", "Jatob\U000000e1", "2105450"], + ["MA", "Jenipapo dos Vieiras", "2105476"], + ["MA", "Jo\U000000e3o Lisboa", "2105500"], + ["MA", "Josel\U000000e2ndia", "2105609"], + ["MA", "Junco do Maranh\U000000e3o", "2105658"], + ["MA", "Lago da Pedra", "2105708"], + ["MA", "Lago do Junco", "2105807"], + ["MA", "Lago dos Rodrigues", "2105948"], + ["MA", "Lago Verde", "2105906"], + ["MA", "Lagoa do Mato", "2105922"], + ["MA", "Lagoa Grande do Maranh\U000000e3o", "2105963"], + ["MA", "Lajeado Novo", "2105989"], + ["MA", "Lima Campos", "2106003"], + ["MA", "Loreto", "2106102"], + ["MA", "Lu\U000000eds Domingues", "2106201"], + ["MA", "Magalh\U000000e3es de Almeida", "2106300"], + ["MA", "Maraca\U000000e7um\U000000e9", "2106326"], + ["MA", "Maraj\U000000e1 do Sena", "2106359"], + ["MA", "Maranh\U000000e3ozinho", "2106375"], + ["MA", "Mata Roma", "2106409"], + ["MA", "Matinha", "2106508"], + ["MA", "Mat\U000000f5es", "2106607"], + ["MA", "Mat\U000000f5es do Norte", "2106631"], + ["MA", "Milagres do Maranh\U000000e3o", "2106672"], + ["MA", "Mirador", "2106706"], + ["MA", "Miranda do Norte", "2106755"], + ["MA", "Mirinzal", "2106805"], + ["MA", "Mon\U000000e7\U000000e3o", "2106904"], + ["MA", "Montes Altos", "2107001"], + ["MA", "Morros", "2107100"], + ["MA", "Nina Rodrigues", "2107209"], + ["MA", "Nova Colinas", "2107258"], + ["MA", "Nova Iorque", "2107308"], + ["MA", "Nova Olinda do Maranh\U000000e3o", "2107357"], + ["MA", "Olho d'\U000000c1gua das Cunh\U000000e3s", "2107407"], + ["MA", "Olinda Nova do Maranh\U000000e3o", "2107456"], + ["MA", "Pa\U000000e7o do Lumiar", "2107506"], + ["MA", "Palmeir\U000000e2ndia", "2107605"], + ["MA", "Paraibano", "2107704"], + ["MA", "Parnarama", "2107803"], + ["MA", "Passagem Franca", "2107902"], + ["MA", "Pastos Bons", "2108009"], + ["MA", "Paulino Neves", "2108058"], + ["MA", "Paulo Ramos", "2108108"], + ["MA", "Pedreiras", "2108207"], + ["MA", "Pedro do Ros\U000000e1rio", "2108256"], + ["MA", "Penalva", "2108306"], + ["MA", "Peri Mirim", "2108405"], + ["MA", "Peritor\U000000f3", "2108454"], + ["MA", "Pindar\U000000e9-Mirim", "2108504"], + ["MA", "Pinheiro", "2108603"], + ["MA", "Pio XII", "2108702"], + ["MA", "Pirapemas", "2108801"], + ["MA", "Po\U000000e7\U000000e3o de Pedras", "2108900"], + ["MA", "Porto Franco", "2109007"], + ["MA", "Porto Rico do Maranh\U000000e3o", "2109056"], + ["MA", "Presidente Dutra", "2109106"], + ["MA", "Presidente Juscelino", "2109205"], + ["MA", "Presidente M\U000000e9dici", "2109239"], + ["MA", "Presidente Sarney", "2109270"], + ["MA", "Presidente Vargas", "2109304"], + ["MA", "Primeira Cruz", "2109403"], + ["MA", "Raposa", "2109452"], + ["MA", "Riach\U000000e3o", "2109502"], + ["MA", "Ribamar Fiquene", "2109551"], + ["MA", "Ros\U000000e1rio", "2109601"], + ["MA", "Samba\U000000edba", "2109700"], + ["MA", "Santa Filomena do Maranh\U000000e3o", "2109759"], + ["MA", "Santa Helena", "2109809"], + ["MA", "Santa In\U000000eas", "2109908"], + ["MA", "Santa Luzia", "2110005"], + ["MA", "Santa Luzia do Paru\U000000e1", "2110039"], + ["MA", "Santa Quit\U000000e9ria do Maranh\U000000e3o", "2110104"], + ["MA", "Santa Rita", "2110203"], + ["MA", "Santana do Maranh\U000000e3o", "2110237"], + ["MA", "Santo Amaro do Maranh\U000000e3o", "2110278"], + ["MA", "Santo Ant\U000000f4nio dos Lopes", "2110302"], + ["MA", "S\U000000e3o Benedito do Rio Preto", "2110401"], + ["MA", "S\U000000e3o Bento", "2110500"], + ["MA", "S\U000000e3o Bernardo", "2110609"], + ["MA", "S\U000000e3o Domingos do Azeit\U000000e3o", "2110658"], + ["MA", "S\U000000e3o Domingos do Maranh\U000000e3o", "2110708"], + ["MA", "S\U000000e3o F\U000000e9lix de Balsas", "2110807"], + ["MA", "S\U000000e3o Francisco do Brej\U000000e3o", "2110856"], + ["MA", "S\U000000e3o Francisco do Maranh\U000000e3o", "2110906"], + ["MA", "S\U000000e3o Jo\U000000e3o Batista", "2111003"], + ["MA", "S\U000000e3o Jo\U000000e3o do Car\U000000fa", "2111029"], + ["MA", "S\U000000e3o Jo\U000000e3o do Para\U000000edso", "2111052"], + ["MA", "S\U000000e3o Jo\U000000e3o do Soter", "2111078"], + ["MA", "S\U000000e3o Jo\U000000e3o dos Patos", "2111102"], + ["MA", "S\U000000e3o Jos\U000000e9 de Ribamar", "2111201"], + ["MA", "S\U000000e3o Jos\U000000e9 dos Bas\U000000edlios", "2111250"], + ["MA", "S\U000000e3o Lu\U000000eds", "2111300"], + ["MA", "S\U000000e3o Lu\U000000eds Gonzaga do Maranh\U000000e3o", "2111409"], + ["MA", "S\U000000e3o Mateus do Maranh\U000000e3o", "2111508"], + ["MA", "S\U000000e3o Pedro da \U000000c1gua Branca", "2111532"], + ["MA", "S\U000000e3o Pedro dos Crentes", "2111573"], + ["MA", "S\U000000e3o Raimundo das Mangabeiras", "2111607"], + ["MA", "S\U000000e3o Raimundo do Doca Bezerra", "2111631"], + ["MA", "S\U000000e3o Roberto", "2111672"], + ["MA", "S\U000000e3o Vicente Ferrer", "2111706"], + ["MA", "Satubinha", "2111722"], + ["MA", "Senador Alexandre Costa", "2111748"], + ["MA", "Senador La Rocque", "2111763"], + ["MA", "Serrano do Maranh\U000000e3o", "2111789"], + ["MA", "S\U000000edtio Novo", "2111805"], + ["MA", "Sucupira do Norte", "2111904"], + ["MA", "Sucupira do Riach\U000000e3o", "2111953"], + ["MA", "Tasso Fragoso", "2112001"], + ["MA", "Timbiras", "2112100"], + ["MA", "Timon", "2112209"], + ["MA", "Trizidela do Vale", "2112233"], + ["MA", "Tufil\U000000e2ndia", "2112274"], + ["MA", "Tuntum", "2112308"], + ["MA", "Turia\U000000e7u", "2112407"], + ["MA", "Turil\U000000e2ndia", "2112456"], + ["MA", "Tut\U000000f3ia", "2112506"], + ["MA", "Urbano Santos", "2112605"], + ["MA", "Vargem Grande", "2112704"], + ["MA", "Viana", "2112803"], + ["MA", "Vila Nova dos Mart\U000000edrios", "2112852"], + ["MA", "Vit\U000000f3ria do Mearim", "2112902"], + ["MA", "Vitorino Freire", "2113009"], + ["MA", "Z\U000000e9 Doca", "2114007"], + ["MT", "Acorizal", "5100102"], + ["MT", "\U000000c1gua Boa", "5100201"], + ["MT", "Alta Floresta", "5100250"], + ["MT", "Alto Araguaia", "5100300"], + ["MT", "Alto Boa Vista", "5100359"], + ["MT", "Alto Gar\U000000e7as", "5100409"], + ["MT", "Alto Paraguai", "5100508"], + ["MT", "Alto Taquari", "5100607"], + ["MT", "Apiac\U000000e1s", "5100805"], + ["MT", "Araguaiana", "5101001"], + ["MT", "Araguainha", "5101209"], + ["MT", "Araputanga", "5101258"], + ["MT", "Aren\U000000e1polis", "5101308"], + ["MT", "Aripuan\U000000e3", "5101407"], + ["MT", "Bar\U000000e3o de Melga\U000000e7o", "5101605"], + ["MT", "Barra do Bugres", "5101704"], + ["MT", "Barra do Gar\U000000e7as", "5101803"], + ["MT", "Boa Esperan\U000000e7a do Norte", "5101837"], + ["MT", "Bom Jesus do Araguaia", "5101852"], + ["MT", "Brasnorte", "5101902"], + ["MT", "C\U000000e1ceres", "5102504"], + ["MT", "Campin\U000000e1polis", "5102603"], + ["MT", "Campo Novo do Parecis", "5102637"], + ["MT", "Campo Verde", "5102678"], + ["MT", "Campos de J\U000000falio", "5102686"], + ["MT", "Canabrava do Norte", "5102694"], + ["MT", "Canarana", "5102702"], + ["MT", "Carlinda", "5102793"], + ["MT", "Castanheira", "5102850"], + ["MT", "Chapada dos Guimar\U000000e3es", "5103007"], + ["MT", "Cl\U000000e1udia", "5103056"], + ["MT", "Cocalinho", "5103106"], + ["MT", "Col\U000000edder", "5103205"], + ["MT", "Colniza", "5103254"], + ["MT", "Comodoro", "5103304"], + ["MT", "Confresa", "5103353"], + ["MT", "Conquista D'Oeste", "5103361"], + ["MT", "Cotrigua\U000000e7u", "5103379"], + ["MT", "Cuiab\U000000e1", "5103403"], + ["MT", "Curvel\U000000e2ndia", "5103437"], + ["MT", "Denise", "5103452"], + ["MT", "Diamantino", "5103502"], + ["MT", "Dom Aquino", "5103601"], + ["MT", "Feliz Natal", "5103700"], + ["MT", "Figueir\U000000f3polis D'Oeste", "5103809"], + ["MT", "Ga\U000000facha do Norte", "5103858"], + ["MT", "General Carneiro", "5103908"], + ["MT", "Gl\U000000f3ria D'Oeste", "5103957"], + ["MT", "Guarant\U000000e3 do Norte", "5104104"], + ["MT", "Guiratinga", "5104203"], + ["MT", "Indiava\U000000ed", "5104500"], + ["MT", "Ipiranga do Norte", "5104526"], + ["MT", "Itanhang\U000000e1", "5104542"], + ["MT", "Ita\U000000faba", "5104559"], + ["MT", "Itiquira", "5104609"], + ["MT", "Jaciara", "5104807"], + ["MT", "Jangada", "5104906"], + ["MT", "Jauru", "5105002"], + ["MT", "Juara", "5105101"], + ["MT", "Ju\U000000edna", "5105150"], + ["MT", "Juruena", "5105176"], + ["MT", "Juscimeira", "5105200"], + ["MT", "Lambari D'Oeste", "5105234"], + ["MT", "Lucas do Rio Verde", "5105259"], + ["MT", "Luciara", "5105309"], + ["MT", "Marcel\U000000e2ndia", "5105580"], + ["MT", "Matup\U000000e1", "5105606"], + ["MT", "Mirassol d'Oeste", "5105622"], + ["MT", "Nobres", "5105903"], + ["MT", "Nortel\U000000e2ndia", "5106000"], + ["MT", "Nossa Senhora do Livramento", "5106109"], + ["MT", "Nova Bandeirantes", "5106158"], + ["MT", "Nova Brasil\U000000e2ndia", "5106208"], + ["MT", "Nova Cana\U000000e3 do Norte", "5106216"], + ["MT", "Nova Guarita", "5108808"], + ["MT", "Nova Lacerda", "5106182"], + ["MT", "Nova Maril\U000000e2ndia", "5108857"], + ["MT", "Nova Maring\U000000e1", "5108907"], + ["MT", "Nova Monte Verde", "5108956"], + ["MT", "Nova Mutum", "5106224"], + ["MT", "Nova Nazar\U000000e9", "5106174"], + ["MT", "Nova Ol\U000000edmpia", "5106232"], + ["MT", "Nova Santa Helena", "5106190"], + ["MT", "Nova Ubirat\U000000e3", "5106240"], + ["MT", "Nova Xavantina", "5106257"], + ["MT", "Novo Horizonte do Norte", "5106273"], + ["MT", "Novo Mundo", "5106265"], + ["MT", "Novo Santo Ant\U000000f4nio", "5106315"], + ["MT", "Novo S\U000000e3o Joaquim", "5106281"], + ["MT", "Parana\U000000edta", "5106299"], + ["MT", "Paranatinga", "5106307"], + ["MT", "Pedra Preta", "5106372"], + ["MT", "Peixoto de Azevedo", "5106422"], + ["MT", "Planalto da Serra", "5106455"], + ["MT", "Pocon\U000000e9", "5106505"], + ["MT", "Pontal do Araguaia", "5106653"], + ["MT", "Ponte Branca", "5106703"], + ["MT", "Pontes e Lacerda", "5106752"], + ["MT", "Porto Alegre do Norte", "5106778"], + ["MT", "Porto dos Ga\U000000fachos", "5106802"], + ["MT", "Porto Esperidi\U000000e3o", "5106828"], + ["MT", "Porto Estrela", "5106851"], + ["MT", "Poxor\U000000e9u", "5107008"], + ["MT", "Primavera do Leste", "5107040"], + ["MT", "Quer\U000000eancia", "5107065"], + ["MT", "Reserva do Caba\U000000e7al", "5107156"], + ["MT", "Ribeir\U000000e3o Cascalheira", "5107180"], + ["MT", "Ribeir\U000000e3ozinho", "5107198"], + ["MT", "Rio Branco", "5107206"], + ["MT", "Rondol\U000000e2ndia", "5107578"], + ["MT", "Rondon\U000000f3polis", "5107602"], + ["MT", "Ros\U000000e1rio Oeste", "5107701"], + ["MT", "Salto do C\U000000e9u", "5107750"], + ["MT", "Santa Carmem", "5107248"], + ["MT", "Santa Cruz do Xingu", "5107743"], + ["MT", "Santa Rita do Trivelato", "5107768"], + ["MT", "Santa Terezinha", "5107776"], + ["MT", "Santo Afonso", "5107263"], + ["MT", "Santo Ant\U000000f4nio de Leverger", "5107800"], + ["MT", "Santo Ant\U000000f4nio do Leste", "5107792"], + ["MT", "S\U000000e3o F\U000000e9lix do Araguaia", "5107859"], + ["MT", "S\U000000e3o Jos\U000000e9 do Povo", "5107297"], + ["MT", "S\U000000e3o Jos\U000000e9 do Rio Claro", "5107305"], + ["MT", "S\U000000e3o Jos\U000000e9 do Xingu", "5107354"], + ["MT", "S\U000000e3o Jos\U000000e9 dos Quatro Marcos", "5107107"], + ["MT", "S\U000000e3o Pedro da Cipa", "5107404"], + ["MT", "Sapezal", "5107875"], + ["MT", "Serra Nova Dourada", "5107883"], + ["MT", "Sinop", "5107909"], + ["MT", "Sorriso", "5107925"], + ["MT", "Tabapor\U000000e3", "5107941"], + ["MT", "Tangar\U000000e1 da Serra", "5107958"], + ["MT", "Tapurah", "5108006"], + ["MT", "Terra Nova do Norte", "5108055"], + ["MT", "Tesouro", "5108105"], + ["MT", "Torixor\U000000e9u", "5108204"], + ["MT", "Uni\U000000e3o do Sul", "5108303"], + ["MT", "Vale de S\U000000e3o Domingos", "5108352"], + ["MT", "V\U000000e1rzea Grande", "5108402"], + ["MT", "Vera", "5108501"], + ["MT", "Vila Bela da Sant\U000000edssima Trindade", "5105507"], + ["MT", "Vila Rica", "5108600"], + ["MS", "\U000000c1gua Clara", "5000203"], + ["MS", "Alcin\U000000f3polis", "5000252"], + ["MS", "Amambai", "5000609"], + ["MS", "Anast\U000000e1cio", "5000708"], + ["MS", "Anauril\U000000e2ndia", "5000807"], + ["MS", "Ang\U000000e9lica", "5000856"], + ["MS", "Ant\U000000f4nio Jo\U000000e3o", "5000906"], + ["MS", "Aparecida do Taboado", "5001003"], + ["MS", "Aquidauana", "5001102"], + ["MS", "Aral Moreira", "5001243"], + ["MS", "Bandeirantes", "5001508"], + ["MS", "Bataguassu", "5001904"], + ["MS", "Bataypor\U000000e3", "5002001"], + ["MS", "Bela Vista", "5002100"], + ["MS", "Bodoquena", "5002159"], + ["MS", "Bonito", "5002209"], + ["MS", "Brasil\U000000e2ndia", "5002308"], + ["MS", "Caarap\U000000f3", "5002407"], + ["MS", "Camapu\U000000e3", "5002605"], + ["MS", "Campo Grande", "5002704"], + ["MS", "Caracol", "5002803"], + ["MS", "Cassil\U000000e2ndia", "5002902"], + ["MS", "Chapad\U000000e3o do Sul", "5002951"], + ["MS", "Corguinho", "5003108"], + ["MS", "Coronel Sapucaia", "5003157"], + ["MS", "Corumb\U000000e1", "5003207"], + ["MS", "Costa Rica", "5003256"], + ["MS", "Coxim", "5003306"], + ["MS", "Deod\U000000e1polis", "5003454"], + ["MS", "Dois Irm\U000000e3os do Buriti", "5003488"], + ["MS", "Douradina", "5003504"], + ["MS", "Dourados", "5003702"], + ["MS", "Eldorado", "5003751"], + ["MS", "F\U000000e1tima do Sul", "5003801"], + ["MS", "Figueir\U000000e3o", "5003900"], + ["MS", "Gl\U000000f3ria de Dourados", "5004007"], + ["MS", "Guia Lopes da Laguna", "5004106"], + ["MS", "Iguatemi", "5004304"], + ["MS", "Inoc\U000000eancia", "5004403"], + ["MS", "Itapor\U000000e3", "5004502"], + ["MS", "Itaquira\U000000ed", "5004601"], + ["MS", "Ivinhema", "5004700"], + ["MS", "Japor\U000000e3", "5004809"], + ["MS", "Jaraguari", "5004908"], + ["MS", "Jardim", "5005004"], + ["MS", "Jate\U000000ed", "5005103"], + ["MS", "Juti", "5005152"], + ["MS", "Lad\U000000e1rio", "5005202"], + ["MS", "Laguna Carap\U000000e3", "5005251"], + ["MS", "Maracaju", "5005400"], + ["MS", "Miranda", "5005608"], + ["MS", "Mundo Novo", "5005681"], + ["MS", "Navira\U000000ed", "5005707"], + ["MS", "Nioaque", "5005806"], + ["MS", "Nova Alvorada do Sul", "5006002"], + ["MS", "Nova Andradina", "5006200"], + ["MS", "Novo Horizonte do Sul", "5006259"], + ["MS", "Para\U000000edso das \U000000c1guas", "5006275"], + ["MS", "Parana\U000000edba", "5006309"], + ["MS", "Paranhos", "5006358"], + ["MS", "Pedro Gomes", "5006408"], + ["MS", "Ponta Por\U000000e3", "5006606"], + ["MS", "Porto Murtinho", "5006903"], + ["MS", "Ribas do Rio Pardo", "5007109"], + ["MS", "Rio Brilhante", "5007208"], + ["MS", "Rio Negro", "5007307"], + ["MS", "Rio Verde de Mato Grosso", "5007406"], + ["MS", "Rochedo", "5007505"], + ["MS", "Santa Rita do Pardo", "5007554"], + ["MS", "S\U000000e3o Gabriel do Oeste", "5007695"], + ["MS", "Selv\U000000edria", "5007802"], + ["MS", "Sete Quedas", "5007703"], + ["MS", "Sidrol\U000000e2ndia", "5007901"], + ["MS", "Sonora", "5007935"], + ["MS", "Tacuru", "5007950"], + ["MS", "Taquarussu", "5007976"], + ["MS", "Terenos", "5008008"], + ["MS", "Tr\U000000eas Lagoas", "5008305"], + ["MS", "Vicentina", "5008404"], + ["MG", "Abadia dos Dourados", "3100104"], + ["MG", "Abaet\U000000e9", "3100203"], + ["MG", "Abre Campo", "3100302"], + ["MG", "Acaiaca", "3100401"], + ["MG", "A\U000000e7ucena", "3100500"], + ["MG", "\U000000c1gua Boa", "3100609"], + ["MG", "\U000000c1gua Comprida", "3100708"], + ["MG", "Aguanil", "3100807"], + ["MG", "\U000000c1guas Formosas", "3100906"], + ["MG", "\U000000c1guas Vermelhas", "3101003"], + ["MG", "Aimor\U000000e9s", "3101102"], + ["MG", "Aiuruoca", "3101201"], + ["MG", "Alagoa", "3101300"], + ["MG", "Albertina", "3101409"], + ["MG", "Al\U000000e9m Para\U000000edba", "3101508"], + ["MG", "Alfenas", "3101607"], + ["MG", "Alfredo Vasconcelos", "3101631"], + ["MG", "Almenara", "3101706"], + ["MG", "Alpercata", "3101805"], + ["MG", "Alpin\U000000f3polis", "3101904"], + ["MG", "Alterosa", "3102001"], + ["MG", "Alto Capara\U000000f3", "3102050"], + ["MG", "Alto Jequitib\U000000e1", "3153509"], + ["MG", "Alto Rio Doce", "3102100"], + ["MG", "Alvarenga", "3102209"], + ["MG", "Alvin\U000000f3polis", "3102308"], + ["MG", "Alvorada de Minas", "3102407"], + ["MG", "Amparo do Serra", "3102506"], + ["MG", "Andradas", "3102605"], + ["MG", "Andrel\U000000e2ndia", "3102803"], + ["MG", "Angel\U000000e2ndia", "3102852"], + ["MG", "Ant\U000000f4nio Carlos", "3102902"], + ["MG", "Ant\U000000f4nio Dias", "3103009"], + ["MG", "Ant\U000000f4nio Prado de Minas", "3103108"], + ["MG", "Ara\U000000e7a\U000000ed", "3103207"], + ["MG", "Aracitaba", "3103306"], + ["MG", "Ara\U000000e7ua\U000000ed", "3103405"], + ["MG", "Araguari", "3103504"], + ["MG", "Arantina", "3103603"], + ["MG", "Araponga", "3103702"], + ["MG", "Arapor\U000000e3", "3103751"], + ["MG", "Arapu\U000000e1", "3103801"], + ["MG", "Ara\U000000fajos", "3103900"], + ["MG", "Arax\U000000e1", "3104007"], + ["MG", "Arceburgo", "3104106"], + ["MG", "Arcos", "3104205"], + ["MG", "Areado", "3104304"], + ["MG", "Argirita", "3104403"], + ["MG", "Aricanduva", "3104452"], + ["MG", "Arinos", "3104502"], + ["MG", "Astolfo Dutra", "3104601"], + ["MG", "Atal\U000000e9ia", "3104700"], + ["MG", "Augusto de Lima", "3104809"], + ["MG", "Baependi", "3104908"], + ["MG", "Baldim", "3105004"], + ["MG", "Bambu\U000000ed", "3105103"], + ["MG", "Bandeira", "3105202"], + ["MG", "Bandeira do Sul", "3105301"], + ["MG", "Bar\U000000e3o de Cocais", "3105400"], + ["MG", "Bar\U000000e3o do Monte Alto", "3105509"], + ["MG", "Barbacena", "3105608"], + ["MG", "Barra Longa", "3105707"], + ["MG", "Barroso", "3105905"], + ["MG", "Bela Vista de Minas", "3106002"], + ["MG", "Belmiro Braga", "3106101"], + ["MG", "Belo Horizonte", "3106200"], + ["MG", "Belo Oriente", "3106309"], + ["MG", "Belo Vale", "3106408"], + ["MG", "Berilo", "3106507"], + ["MG", "Berizal", "3106655"], + ["MG", "Bert\U000000f3polis", "3106606"], + ["MG", "Betim", "3106705"], + ["MG", "Bias Fortes", "3106804"], + ["MG", "Bicas", "3106903"], + ["MG", "Biquinhas", "3107000"], + ["MG", "Boa Esperan\U000000e7a", "3107109"], + ["MG", "Bocaina de Minas", "3107208"], + ["MG", "Bocai\U000000fava", "3107307"], + ["MG", "Bom Despacho", "3107406"], + ["MG", "Bom Jardim de Minas", "3107505"], + ["MG", "Bom Jesus da Penha", "3107604"], + ["MG", "Bom Jesus do Amparo", "3107703"], + ["MG", "Bom Jesus do Galho", "3107802"], + ["MG", "Bom Repouso", "3107901"], + ["MG", "Bom Sucesso", "3108008"], + ["MG", "Bonfim", "3108107"], + ["MG", "Bonfin\U000000f3polis de Minas", "3108206"], + ["MG", "Bonito de Minas", "3108255"], + ["MG", "Borda da Mata", "3108305"], + ["MG", "Botelhos", "3108404"], + ["MG", "Botumirim", "3108503"], + ["MG", "Br\U000000e1s Pires", "3108701"], + ["MG", "Brasil\U000000e2ndia de Minas", "3108552"], + ["MG", "Bras\U000000edlia de Minas", "3108602"], + ["MG", "Bra\U000000fanas", "3108800"], + ["MG", "Braz\U000000f3polis", "3108909"], + ["MG", "Brumadinho", "3109006"], + ["MG", "Bueno Brand\U000000e3o", "3109105"], + ["MG", "Buen\U000000f3polis", "3109204"], + ["MG", "Bugre", "3109253"], + ["MG", "Buritis", "3109303"], + ["MG", "Buritizeiro", "3109402"], + ["MG", "Cabeceira Grande", "3109451"], + ["MG", "Cabo Verde", "3109501"], + ["MG", "Cachoeira da Prata", "3109600"], + ["MG", "Cachoeira de Minas", "3109709"], + ["MG", "Cachoeira de Paje\U000000fa", "3102704"], + ["MG", "Cachoeira Dourada", "3109808"], + ["MG", "Caetan\U000000f3polis", "3109907"], + ["MG", "Caet\U000000e9", "3110004"], + ["MG", "Caiana", "3110103"], + ["MG", "Cajuri", "3110202"], + ["MG", "Caldas", "3110301"], + ["MG", "Camacho", "3110400"], + ["MG", "Camanducaia", "3110509"], + ["MG", "Cambu\U000000ed", "3110608"], + ["MG", "Cambuquira", "3110707"], + ["MG", "Campan\U000000e1rio", "3110806"], + ["MG", "Campanha", "3110905"], + ["MG", "Campestre", "3111002"], + ["MG", "Campina Verde", "3111101"], + ["MG", "Campo Azul", "3111150"], + ["MG", "Campo Belo", "3111200"], + ["MG", "Campo do Meio", "3111309"], + ["MG", "Campo Florido", "3111408"], + ["MG", "Campos Altos", "3111507"], + ["MG", "Campos Gerais", "3111606"], + ["MG", "Cana Verde", "3111903"], + ["MG", "Cana\U000000e3", "3111705"], + ["MG", "Can\U000000e1polis", "3111804"], + ["MG", "Candeias", "3112000"], + ["MG", "Cantagalo", "3112059"], + ["MG", "Capara\U000000f3", "3112109"], + ["MG", "Capela Nova", "3112208"], + ["MG", "Capelinha", "3112307"], + ["MG", "Capetinga", "3112406"], + ["MG", "Capim Branco", "3112505"], + ["MG", "Capin\U000000f3polis", "3112604"], + ["MG", "Capit\U000000e3o Andrade", "3112653"], + ["MG", "Capit\U000000e3o En\U000000e9as", "3112703"], + ["MG", "Capit\U000000f3lio", "3112802"], + ["MG", "Caputira", "3112901"], + ["MG", "Cara\U000000ed", "3113008"], + ["MG", "Carana\U000000edba", "3113107"], + ["MG", "Caranda\U000000ed", "3113206"], + ["MG", "Carangola", "3113305"], + ["MG", "Caratinga", "3113404"], + ["MG", "Carbonita", "3113503"], + ["MG", "Carea\U000000e7u", "3113602"], + ["MG", "Carlos Chagas", "3113701"], + ["MG", "Carm\U000000e9sia", "3113800"], + ["MG", "Carmo da Cachoeira", "3113909"], + ["MG", "Carmo da Mata", "3114006"], + ["MG", "Carmo de Minas", "3114105"], + ["MG", "Carmo do Cajuru", "3114204"], + ["MG", "Carmo do Parana\U000000edba", "3114303"], + ["MG", "Carmo do Rio Claro", "3114402"], + ["MG", "Carm\U000000f3polis de Minas", "3114501"], + ["MG", "Carneirinho", "3114550"], + ["MG", "Carrancas", "3114600"], + ["MG", "Carvalh\U000000f3polis", "3114709"], + ["MG", "Carvalhos", "3114808"], + ["MG", "Casa Grande", "3114907"], + ["MG", "Cascalho Rico", "3115003"], + ["MG", "C\U000000e1ssia", "3115102"], + ["MG", "Cataguases", "3115300"], + ["MG", "Catas Altas", "3115359"], + ["MG", "Catas Altas da Noruega", "3115409"], + ["MG", "Catuji", "3115458"], + ["MG", "Catuti", "3115474"], + ["MG", "Caxambu", "3115508"], + ["MG", "Cedro do Abaet\U000000e9", "3115607"], + ["MG", "Central de Minas", "3115706"], + ["MG", "Centralina", "3115805"], + ["MG", "Ch\U000000e1cara", "3115904"], + ["MG", "Chal\U000000e9", "3116001"], + ["MG", "Chapada do Norte", "3116100"], + ["MG", "Chapada Ga\U000000facha", "3116159"], + ["MG", "Chiador", "3116209"], + ["MG", "Cipot\U000000e2nea", "3116308"], + ["MG", "Claraval", "3116407"], + ["MG", "Claro dos Po\U000000e7\U000000f5es", "3116506"], + ["MG", "Cl\U000000e1udio", "3116605"], + ["MG", "Coimbra", "3116704"], + ["MG", "Coluna", "3116803"], + ["MG", "Comendador Gomes", "3116902"], + ["MG", "Comercinho", "3117009"], + ["MG", "Concei\U000000e7\U000000e3o da Aparecida", "3117108"], + ["MG", "Concei\U000000e7\U000000e3o da Barra de Minas", "3115201"], + ["MG", "Concei\U000000e7\U000000e3o das Alagoas", "3117306"], + ["MG", "Concei\U000000e7\U000000e3o das Pedras", "3117207"], + ["MG", "Concei\U000000e7\U000000e3o de Ipanema", "3117405"], + ["MG", "Concei\U000000e7\U000000e3o do Mato Dentro", "3117504"], + ["MG", "Concei\U000000e7\U000000e3o do Par\U000000e1", "3117603"], + ["MG", "Concei\U000000e7\U000000e3o do Rio Verde", "3117702"], + ["MG", "Concei\U000000e7\U000000e3o dos Ouros", "3117801"], + ["MG", "C\U000000f4nego Marinho", "3117836"], + ["MG", "Confins", "3117876"], + ["MG", "Congonhal", "3117900"], + ["MG", "Congonhas", "3118007"], + ["MG", "Congonhas do Norte", "3118106"], + ["MG", "Conquista", "3118205"], + ["MG", "Conselheiro Lafaiete", "3118304"], + ["MG", "Conselheiro Pena", "3118403"], + ["MG", "Consola\U000000e7\U000000e3o", "3118502"], + ["MG", "Contagem", "3118601"], + ["MG", "Coqueiral", "3118700"], + ["MG", "Cora\U000000e7\U000000e3o de Jesus", "3118809"], + ["MG", "Cordisburgo", "3118908"], + ["MG", "Cordisl\U000000e2ndia", "3119005"], + ["MG", "Corinto", "3119104"], + ["MG", "Coroaci", "3119203"], + ["MG", "Coromandel", "3119302"], + ["MG", "Coronel Fabriciano", "3119401"], + ["MG", "Coronel Murta", "3119500"], + ["MG", "Coronel Pacheco", "3119609"], + ["MG", "Coronel Xavier Chaves", "3119708"], + ["MG", "C\U000000f3rrego Danta", "3119807"], + ["MG", "C\U000000f3rrego do Bom Jesus", "3119906"], + ["MG", "C\U000000f3rrego Fundo", "3119955"], + ["MG", "C\U000000f3rrego Novo", "3120003"], + ["MG", "Couto de Magalh\U000000e3es de Minas", "3120102"], + ["MG", "Cris\U000000f3lita", "3120151"], + ["MG", "Cristais", "3120201"], + ["MG", "Crist\U000000e1lia", "3120300"], + ["MG", "Cristiano Otoni", "3120409"], + ["MG", "Cristina", "3120508"], + ["MG", "Crucil\U000000e2ndia", "3120607"], + ["MG", "Cruzeiro da Fortaleza", "3120706"], + ["MG", "Cruz\U000000edlia", "3120805"], + ["MG", "Cuparaque", "3120839"], + ["MG", "Curral de Dentro", "3120870"], + ["MG", "Curvelo", "3120904"], + ["MG", "Datas", "3121001"], + ["MG", "Delfim Moreira", "3121100"], + ["MG", "Delfin\U000000f3polis", "3121209"], + ["MG", "Delta", "3121258"], + ["MG", "Descoberto", "3121308"], + ["MG", "Desterro de Entre Rios", "3121407"], + ["MG", "Desterro do Melo", "3121506"], + ["MG", "Diamantina", "3121605"], + ["MG", "Diogo de Vasconcelos", "3121704"], + ["MG", "Dion\U000000edsio", "3121803"], + ["MG", "Divin\U000000e9sia", "3121902"], + ["MG", "Divino", "3122009"], + ["MG", "Divino das Laranjeiras", "3122108"], + ["MG", "Divinol\U000000e2ndia de Minas", "3122207"], + ["MG", "Divin\U000000f3polis", "3122306"], + ["MG", "Divisa Alegre", "3122355"], + ["MG", "Divisa Nova", "3122405"], + ["MG", "Divis\U000000f3polis", "3122454"], + ["MG", "Dom Bosco", "3122470"], + ["MG", "Dom Cavati", "3122504"], + ["MG", "Dom Joaquim", "3122603"], + ["MG", "Dom Silv\U000000e9rio", "3122702"], + ["MG", "Dom Vi\U000000e7oso", "3122801"], + ["MG", "Dona Euz\U000000e9bia", "3122900"], + ["MG", "Dores de Campos", "3123007"], + ["MG", "Dores de Guanh\U000000e3es", "3123106"], + ["MG", "Dores do Indai\U000000e1", "3123205"], + ["MG", "Dores do Turvo", "3123304"], + ["MG", "Dores\U000000f3polis", "3123403"], + ["MG", "Douradoquara", "3123502"], + ["MG", "Durand\U000000e9", "3123528"], + ["MG", "El\U000000f3i Mendes", "3123601"], + ["MG", "Engenheiro Caldas", "3123700"], + ["MG", "Engenheiro Navarro", "3123809"], + ["MG", "Entre Folhas", "3123858"], + ["MG", "Entre Rios de Minas", "3123908"], + ["MG", "Erv\U000000e1lia", "3124005"], + ["MG", "Esmeraldas", "3124104"], + ["MG", "Espera Feliz", "3124203"], + ["MG", "Espinosa", "3124302"], + ["MG", "Esp\U000000edrito Santo do Dourado", "3124401"], + ["MG", "Estiva", "3124500"], + ["MG", "Estrela Dalva", "3124609"], + ["MG", "Estrela do Indai\U000000e1", "3124708"], + ["MG", "Estrela do Sul", "3124807"], + ["MG", "Eugen\U000000f3polis", "3124906"], + ["MG", "Ewbank da C\U000000e2mara", "3125002"], + ["MG", "Extrema", "3125101"], + ["MG", "Fama", "3125200"], + ["MG", "Faria Lemos", "3125309"], + ["MG", "Fel\U000000edcio dos Santos", "3125408"], + ["MG", "Felisburgo", "3125606"], + ["MG", "Felixl\U000000e2ndia", "3125705"], + ["MG", "Fernandes Tourinho", "3125804"], + ["MG", "Ferros", "3125903"], + ["MG", "Fervedouro", "3125952"], + ["MG", "Florestal", "3126000"], + ["MG", "Formiga", "3126109"], + ["MG", "Formoso", "3126208"], + ["MG", "Fortaleza de Minas", "3126307"], + ["MG", "Fortuna de Minas", "3126406"], + ["MG", "Francisco Badar\U000000f3", "3126505"], + ["MG", "Francisco Dumont", "3126604"], + ["MG", "Francisco S\U000000e1", "3126703"], + ["MG", "Francisc\U000000f3polis", "3126752"], + ["MG", "Frei Gaspar", "3126802"], + ["MG", "Frei Inoc\U000000eancio", "3126901"], + ["MG", "Frei Lagonegro", "3126950"], + ["MG", "Fronteira", "3127008"], + ["MG", "Fronteira dos Vales", "3127057"], + ["MG", "Fruta de Leite", "3127073"], + ["MG", "Frutal", "3127107"], + ["MG", "Funil\U000000e2ndia", "3127206"], + ["MG", "Galil\U000000e9ia", "3127305"], + ["MG", "Gameleiras", "3127339"], + ["MG", "Glaucil\U000000e2ndia", "3127354"], + ["MG", "Goiabeira", "3127370"], + ["MG", "Goian\U000000e1", "3127388"], + ["MG", "Gon\U000000e7alves", "3127404"], + ["MG", "Gonzaga", "3127503"], + ["MG", "Gouveia", "3127602"], + ["MG", "Governador Valadares", "3127701"], + ["MG", "Gr\U000000e3o Mogol", "3127800"], + ["MG", "Grupiara", "3127909"], + ["MG", "Guanh\U000000e3es", "3128006"], + ["MG", "Guap\U000000e9", "3128105"], + ["MG", "Guaraciaba", "3128204"], + ["MG", "Guaraciama", "3128253"], + ["MG", "Guaran\U000000e9sia", "3128303"], + ["MG", "Guarani", "3128402"], + ["MG", "Guarar\U000000e1", "3128501"], + ["MG", "Guarda-Mor", "3128600"], + ["MG", "Guaxup\U000000e9", "3128709"], + ["MG", "Guidoval", "3128808"], + ["MG", "Guimar\U000000e2nia", "3128907"], + ["MG", "Guiricema", "3129004"], + ["MG", "Gurinhat\U000000e3", "3129103"], + ["MG", "Heliodora", "3129202"], + ["MG", "Iapu", "3129301"], + ["MG", "Ibertioga", "3129400"], + ["MG", "Ibi\U000000e1", "3129509"], + ["MG", "Ibia\U000000ed", "3129608"], + ["MG", "Ibiracatu", "3129657"], + ["MG", "Ibiraci", "3129707"], + ["MG", "Ibirit\U000000e9", "3129806"], + ["MG", "Ibiti\U000000fara de Minas", "3129905"], + ["MG", "Ibituruna", "3130002"], + ["MG", "Icara\U000000ed de Minas", "3130051"], + ["MG", "Igarap\U000000e9", "3130101"], + ["MG", "Igaratinga", "3130200"], + ["MG", "Iguatama", "3130309"], + ["MG", "Ijaci", "3130408"], + ["MG", "Ilic\U000000ednea", "3130507"], + ["MG", "Imb\U000000e9 de Minas", "3130556"], + ["MG", "Inconfidentes", "3130606"], + ["MG", "Indaiabira", "3130655"], + ["MG", "Indian\U000000f3polis", "3130705"], + ["MG", "Inga\U000000ed", "3130804"], + ["MG", "Inhapim", "3130903"], + ["MG", "Inha\U000000fama", "3131000"], + ["MG", "Inimutaba", "3131109"], + ["MG", "Ipaba", "3131158"], + ["MG", "Ipanema", "3131208"], + ["MG", "Ipatinga", "3131307"], + ["MG", "Ipia\U000000e7u", "3131406"], + ["MG", "Ipui\U000000fana", "3131505"], + ["MG", "Ira\U000000ed de Minas", "3131604"], + ["MG", "Itabira", "3131703"], + ["MG", "Itabirinha", "3131802"], + ["MG", "Itabirito", "3131901"], + ["MG", "Itacambira", "3132008"], + ["MG", "Itacarambi", "3132107"], + ["MG", "Itaguara", "3132206"], + ["MG", "Itaip\U000000e9", "3132305"], + ["MG", "Itajub\U000000e1", "3132404"], + ["MG", "Itamarandiba", "3132503"], + ["MG", "Itamarati de Minas", "3132602"], + ["MG", "Itambacuri", "3132701"], + ["MG", "Itamb\U000000e9 do Mato Dentro", "3132800"], + ["MG", "Itamogi", "3132909"], + ["MG", "Itamonte", "3133006"], + ["MG", "Itanhandu", "3133105"], + ["MG", "Itanhomi", "3133204"], + ["MG", "Itaobim", "3133303"], + ["MG", "Itapagipe", "3133402"], + ["MG", "Itapecerica", "3133501"], + ["MG", "Itapeva", "3133600"], + ["MG", "Itatiaiu\U000000e7u", "3133709"], + ["MG", "Ita\U000000fa de Minas", "3133758"], + ["MG", "Ita\U000000fana", "3133808"], + ["MG", "Itaverava", "3133907"], + ["MG", "Itinga", "3134004"], + ["MG", "Itueta", "3134103"], + ["MG", "Ituiutaba", "3134202"], + ["MG", "Itumirim", "3134301"], + ["MG", "Iturama", "3134400"], + ["MG", "Itutinga", "3134509"], + ["MG", "Jaboticatubas", "3134608"], + ["MG", "Jacinto", "3134707"], + ["MG", "Jacu\U000000ed", "3134806"], + ["MG", "Jacutinga", "3134905"], + ["MG", "Jaguara\U000000e7u", "3135001"], + ["MG", "Ja\U000000edba", "3135050"], + ["MG", "Jampruca", "3135076"], + ["MG", "Jana\U000000faba", "3135100"], + ["MG", "Janu\U000000e1ria", "3135209"], + ["MG", "Japara\U000000edba", "3135308"], + ["MG", "Japonvar", "3135357"], + ["MG", "Jeceaba", "3135407"], + ["MG", "Jenipapo de Minas", "3135456"], + ["MG", "Jequeri", "3135506"], + ["MG", "Jequita\U000000ed", "3135605"], + ["MG", "Jequitib\U000000e1", "3135704"], + ["MG", "Jequitinhonha", "3135803"], + ["MG", "Jesu\U000000e2nia", "3135902"], + ["MG", "Joa\U000000edma", "3136009"], + ["MG", "Joan\U000000e9sia", "3136108"], + ["MG", "Jo\U000000e3o Monlevade", "3136207"], + ["MG", "Jo\U000000e3o Pinheiro", "3136306"], + ["MG", "Joaquim Fel\U000000edcio", "3136405"], + ["MG", "Jord\U000000e2nia", "3136504"], + ["MG", "Jos\U000000e9 Gon\U000000e7alves de Minas", "3136520"], + ["MG", "Jos\U000000e9 Raydan", "3136553"], + ["MG", "Josen\U000000f3polis", "3136579"], + ["MG", "Juatuba", "3136652"], + ["MG", "Juiz de Fora", "3136702"], + ["MG", "Juramento", "3136801"], + ["MG", "Juruaia", "3136900"], + ["MG", "Juven\U000000edlia", "3136959"], + ["MG", "Ladainha", "3137007"], + ["MG", "Lagamar", "3137106"], + ["MG", "Lagoa da Prata", "3137205"], + ["MG", "Lagoa dos Patos", "3137304"], + ["MG", "Lagoa Dourada", "3137403"], + ["MG", "Lagoa Formosa", "3137502"], + ["MG", "Lagoa Grande", "3137536"], + ["MG", "Lagoa Santa", "3137601"], + ["MG", "Lajinha", "3137700"], + ["MG", "Lambari", "3137809"], + ["MG", "Lamim", "3137908"], + ["MG", "Laranjal", "3138005"], + ["MG", "Lassance", "3138104"], + ["MG", "Lavras", "3138203"], + ["MG", "Leandro Ferreira", "3138302"], + ["MG", "Leme do Prado", "3138351"], + ["MG", "Leopoldina", "3138401"], + ["MG", "Liberdade", "3138500"], + ["MG", "Lima Duarte", "3138609"], + ["MG", "Limeira do Oeste", "3138625"], + ["MG", "Lontra", "3138658"], + ["MG", "Luisburgo", "3138674"], + ["MG", "Luisl\U000000e2ndia", "3138682"], + ["MG", "Lumin\U000000e1rias", "3138708"], + ["MG", "Luz", "3138807"], + ["MG", "Machacalis", "3138906"], + ["MG", "Machado", "3139003"], + ["MG", "Madre de Deus de Minas", "3139102"], + ["MG", "Malacacheta", "3139201"], + ["MG", "Mamonas", "3139250"], + ["MG", "Manga", "3139300"], + ["MG", "Manhua\U000000e7u", "3139409"], + ["MG", "Manhumirim", "3139508"], + ["MG", "Mantena", "3139607"], + ["MG", "Mar de Espanha", "3139805"], + ["MG", "Maravilhas", "3139706"], + ["MG", "Maria da F\U000000e9", "3139904"], + ["MG", "Mariana", "3140001"], + ["MG", "Marilac", "3140100"], + ["MG", "M\U000000e1rio Campos", "3140159"], + ["MG", "Marip\U000000e1 de Minas", "3140209"], + ["MG", "Marli\U000000e9ria", "3140308"], + ["MG", "Marmel\U000000f3polis", "3140407"], + ["MG", "Martinho Campos", "3140506"], + ["MG", "Martins Soares", "3140530"], + ["MG", "Mata Verde", "3140555"], + ["MG", "Materl\U000000e2ndia", "3140605"], + ["MG", "Mateus Leme", "3140704"], + ["MG", "Mathias Lobato", "3171501"], + ["MG", "Matias Barbosa", "3140803"], + ["MG", "Matias Cardoso", "3140852"], + ["MG", "Matip\U000000f3", "3140902"], + ["MG", "Mato Verde", "3141009"], + ["MG", "Matozinhos", "3141108"], + ["MG", "Matutina", "3141207"], + ["MG", "Medeiros", "3141306"], + ["MG", "Medina", "3141405"], + ["MG", "Mendes Pimentel", "3141504"], + ["MG", "Merc\U000000eas", "3141603"], + ["MG", "Mesquita", "3141702"], + ["MG", "Minas Novas", "3141801"], + ["MG", "Minduri", "3141900"], + ["MG", "Mirabela", "3142007"], + ["MG", "Miradouro", "3142106"], + ["MG", "Mira\U000000ed", "3142205"], + ["MG", "Mirav\U000000e2nia", "3142254"], + ["MG", "Moeda", "3142304"], + ["MG", "Moema", "3142403"], + ["MG", "Monjolos", "3142502"], + ["MG", "Monsenhor Paulo", "3142601"], + ["MG", "Montalv\U000000e2nia", "3142700"], + ["MG", "Monte Alegre de Minas", "3142809"], + ["MG", "Monte Azul", "3142908"], + ["MG", "Monte Belo", "3143005"], + ["MG", "Monte Carmelo", "3143104"], + ["MG", "Monte Formoso", "3143153"], + ["MG", "Monte Santo de Minas", "3143203"], + ["MG", "Monte Si\U000000e3o", "3143401"], + ["MG", "Montes Claros", "3143302"], + ["MG", "Montezuma", "3143450"], + ["MG", "Morada Nova de Minas", "3143500"], + ["MG", "Morro da Gar\U000000e7a", "3143609"], + ["MG", "Morro do Pilar", "3143708"], + ["MG", "Munhoz", "3143807"], + ["MG", "Muria\U000000e9", "3143906"], + ["MG", "Mutum", "3144003"], + ["MG", "Muzambinho", "3144102"], + ["MG", "Nacip Raydan", "3144201"], + ["MG", "Nanuque", "3144300"], + ["MG", "Naque", "3144359"], + ["MG", "Natal\U000000e2ndia", "3144375"], + ["MG", "Nat\U000000e9rcia", "3144409"], + ["MG", "Nazareno", "3144508"], + ["MG", "Nepomuceno", "3144607"], + ["MG", "Ninheira", "3144656"], + ["MG", "Nova Bel\U000000e9m", "3144672"], + ["MG", "Nova Era", "3144706"], + ["MG", "Nova Lima", "3144805"], + ["MG", "Nova M\U000000f3dica", "3144904"], + ["MG", "Nova Ponte", "3145000"], + ["MG", "Nova Porteirinha", "3145059"], + ["MG", "Nova Resende", "3145109"], + ["MG", "Nova Serrana", "3145208"], + ["MG", "Nova Uni\U000000e3o", "3136603"], + ["MG", "Novo Cruzeiro", "3145307"], + ["MG", "Novo Oriente de Minas", "3145356"], + ["MG", "Novorizonte", "3145372"], + ["MG", "Olaria", "3145406"], + ["MG", "Olhos-d'\U000000c1gua", "3145455"], + ["MG", "Ol\U000000edmpio Noronha", "3145505"], + ["MG", "Oliveira", "3145604"], + ["MG", "Oliveira Fortes", "3145703"], + ["MG", "On\U000000e7a de Pitangui", "3145802"], + ["MG", "Orat\U000000f3rios", "3145851"], + ["MG", "Oriz\U000000e2nia", "3145877"], + ["MG", "Ouro Branco", "3145901"], + ["MG", "Ouro Fino", "3146008"], + ["MG", "Ouro Preto", "3146107"], + ["MG", "Ouro Verde de Minas", "3146206"], + ["MG", "Padre Carvalho", "3146255"], + ["MG", "Padre Para\U000000edso", "3146305"], + ["MG", "Pai Pedro", "3146552"], + ["MG", "Paineiras", "3146404"], + ["MG", "Pains", "3146503"], + ["MG", "Paiva", "3146602"], + ["MG", "Palma", "3146701"], + ["MG", "Palm\U000000f3polis", "3146750"], + ["MG", "Papagaios", "3146909"], + ["MG", "Par\U000000e1 de Minas", "3147105"], + ["MG", "Paracatu", "3147006"], + ["MG", "Paragua\U000000e7u", "3147204"], + ["MG", "Parais\U000000f3polis", "3147303"], + ["MG", "Paraopeba", "3147402"], + ["MG", "Passa Quatro", "3147600"], + ["MG", "Passa Tempo", "3147709"], + ["MG", "Passa Vinte", "3147808"], + ["MG", "Passab\U000000e9m", "3147501"], + ["MG", "Passos", "3147907"], + ["MG", "Patis", "3147956"], + ["MG", "Patos de Minas", "3148004"], + ["MG", "Patroc\U000000ednio", "3148103"], + ["MG", "Patroc\U000000ednio do Muria\U000000e9", "3148202"], + ["MG", "Paula C\U000000e2ndido", "3148301"], + ["MG", "Paulistas", "3148400"], + ["MG", "Pav\U000000e3o", "3148509"], + ["MG", "Pe\U000000e7anha", "3148608"], + ["MG", "Pedra Azul", "3148707"], + ["MG", "Pedra Bonita", "3148756"], + ["MG", "Pedra do Anta", "3148806"], + ["MG", "Pedra do Indai\U000000e1", "3148905"], + ["MG", "Pedra Dourada", "3149002"], + ["MG", "Pedralva", "3149101"], + ["MG", "Pedras de Maria da Cruz", "3149150"], + ["MG", "Pedrin\U000000f3polis", "3149200"], + ["MG", "Pedro Leopoldo", "3149309"], + ["MG", "Pedro Teixeira", "3149408"], + ["MG", "Pequeri", "3149507"], + ["MG", "Pequi", "3149606"], + ["MG", "Perdig\U000000e3o", "3149705"], + ["MG", "Perdizes", "3149804"], + ["MG", "Perd\U000000f5es", "3149903"], + ["MG", "Periquito", "3149952"], + ["MG", "Pescador", "3150000"], + ["MG", "Piau", "3150109"], + ["MG", "Piedade de Caratinga", "3150158"], + ["MG", "Piedade de Ponte Nova", "3150208"], + ["MG", "Piedade do Rio Grande", "3150307"], + ["MG", "Piedade dos Gerais", "3150406"], + ["MG", "Pimenta", "3150505"], + ["MG", "Pingo-d'\U000000c1gua", "3150539"], + ["MG", "Pint\U000000f3polis", "3150570"], + ["MG", "Piracema", "3150604"], + ["MG", "Pirajuba", "3150703"], + ["MG", "Piranga", "3150802"], + ["MG", "Pirangu\U000000e7u", "3150901"], + ["MG", "Piranguinho", "3151008"], + ["MG", "Pirapetinga", "3151107"], + ["MG", "Pirapora", "3151206"], + ["MG", "Pira\U000000faba", "3151305"], + ["MG", "Pitangui", "3151404"], + ["MG", "Piumhi", "3151503"], + ["MG", "Planura", "3151602"], + ["MG", "Po\U000000e7o Fundo", "3151701"], + ["MG", "Po\U000000e7os de Caldas", "3151800"], + ["MG", "Pocrane", "3151909"], + ["MG", "Pomp\U000000e9u", "3152006"], + ["MG", "Ponte Nova", "3152105"], + ["MG", "Ponto Chique", "3152131"], + ["MG", "Ponto dos Volantes", "3152170"], + ["MG", "Porteirinha", "3152204"], + ["MG", "Porto Firme", "3152303"], + ["MG", "Pot\U000000e9", "3152402"], + ["MG", "Pouso Alegre", "3152501"], + ["MG", "Pouso Alto", "3152600"], + ["MG", "Prados", "3152709"], + ["MG", "Prata", "3152808"], + ["MG", "Prat\U000000e1polis", "3152907"], + ["MG", "Pratinha", "3153004"], + ["MG", "Presidente Bernardes", "3153103"], + ["MG", "Presidente Juscelino", "3153202"], + ["MG", "Presidente Kubitschek", "3153301"], + ["MG", "Presidente Oleg\U000000e1rio", "3153400"], + ["MG", "Prudente de Morais", "3153608"], + ["MG", "Quartel Geral", "3153707"], + ["MG", "Queluzito", "3153806"], + ["MG", "Raposos", "3153905"], + ["MG", "Raul Soares", "3154002"], + ["MG", "Recreio", "3154101"], + ["MG", "Reduto", "3154150"], + ["MG", "Resende Costa", "3154200"], + ["MG", "Resplendor", "3154309"], + ["MG", "Ressaquinha", "3154408"], + ["MG", "Riachinho", "3154457"], + ["MG", "Riacho dos Machados", "3154507"], + ["MG", "Ribeir\U000000e3o das Neves", "3154606"], + ["MG", "Ribeir\U000000e3o Vermelho", "3154705"], + ["MG", "Rio Acima", "3154804"], + ["MG", "Rio Casca", "3154903"], + ["MG", "Rio do Prado", "3155108"], + ["MG", "Rio Doce", "3155009"], + ["MG", "Rio Espera", "3155207"], + ["MG", "Rio Manso", "3155306"], + ["MG", "Rio Novo", "3155405"], + ["MG", "Rio Parana\U000000edba", "3155504"], + ["MG", "Rio Pardo de Minas", "3155603"], + ["MG", "Rio Piracicaba", "3155702"], + ["MG", "Rio Pomba", "3155801"], + ["MG", "Rio Preto", "3155900"], + ["MG", "Rio Vermelho", "3156007"], + ["MG", "Rit\U000000e1polis", "3156106"], + ["MG", "Rochedo de Minas", "3156205"], + ["MG", "Rodeiro", "3156304"], + ["MG", "Romaria", "3156403"], + ["MG", "Ros\U000000e1rio da Limeira", "3156452"], + ["MG", "Rubelita", "3156502"], + ["MG", "Rubim", "3156601"], + ["MG", "Sabar\U000000e1", "3156700"], + ["MG", "Sabin\U000000f3polis", "3156809"], + ["MG", "Sacramento", "3156908"], + ["MG", "Salinas", "3157005"], + ["MG", "Salto da Divisa", "3157104"], + ["MG", "Santa B\U000000e1rbara", "3157203"], + ["MG", "Santa B\U000000e1rbara do Leste", "3157252"], + ["MG", "Santa B\U000000e1rbara do Monte Verde", "3157278"], + ["MG", "Santa B\U000000e1rbara do Tug\U000000fario", "3157302"], + ["MG", "Santa Cruz de Minas", "3157336"], + ["MG", "Santa Cruz de Salinas", "3157377"], + ["MG", "Santa Cruz do Escalvado", "3157401"], + ["MG", "Santa Efig\U000000eania de Minas", "3157500"], + ["MG", "Santa F\U000000e9 de Minas", "3157609"], + ["MG", "Santa Helena de Minas", "3157658"], + ["MG", "Santa Juliana", "3157708"], + ["MG", "Santa Luzia", "3157807"], + ["MG", "Santa Margarida", "3157906"], + ["MG", "Santa Maria de Itabira", "3158003"], + ["MG", "Santa Maria do Salto", "3158102"], + ["MG", "Santa Maria do Sua\U000000e7u\U000000ed", "3158201"], + ["MG", "Santa Rita de Caldas", "3159209"], + ["MG", "Santa Rita de Ibitipoca", "3159407"], + ["MG", "Santa Rita de Jacutinga", "3159308"], + ["MG", "Santa Rita de Minas", "3159357"], + ["MG", "Santa Rita do Itueto", "3159506"], + ["MG", "Santa Rita do Sapuca\U000000ed", "3159605"], + ["MG", "Santa Rosa da Serra", "3159704"], + ["MG", "Santa Vit\U000000f3ria", "3159803"], + ["MG", "Santana da Vargem", "3158300"], + ["MG", "Santana de Cataguases", "3158409"], + ["MG", "Santana de Pirapama", "3158508"], + ["MG", "Santana do Deserto", "3158607"], + ["MG", "Santana do Garamb\U000000e9u", "3158706"], + ["MG", "Santana do Jacar\U000000e9", "3158805"], + ["MG", "Santana do Manhua\U000000e7u", "3158904"], + ["MG", "Santana do Para\U000000edso", "3158953"], + ["MG", "Santana do Riacho", "3159001"], + ["MG", "Santana dos Montes", "3159100"], + ["MG", "Santo Ant\U000000f4nio do Amparo", "3159902"], + ["MG", "Santo Ant\U000000f4nio do Aventureiro", "3160009"], + ["MG", "Santo Ant\U000000f4nio do Grama", "3160108"], + ["MG", "Santo Ant\U000000f4nio do Itamb\U000000e9", "3160207"], + ["MG", "Santo Ant\U000000f4nio do Jacinto", "3160306"], + ["MG", "Santo Ant\U000000f4nio do Monte", "3160405"], + ["MG", "Santo Ant\U000000f4nio do Retiro", "3160454"], + ["MG", "Santo Ant\U000000f4nio do Rio Abaixo", "3160504"], + ["MG", "Santo Hip\U000000f3lito", "3160603"], + ["MG", "Santos Dumont", "3160702"], + ["MG", "S\U000000e3o Bento Abade", "3160801"], + ["MG", "S\U000000e3o Br\U000000e1s do Sua\U000000e7u\U000000ed", "3160900"], + ["MG", "S\U000000e3o Domingos das Dores", "3160959"], + ["MG", "S\U000000e3o Domingos do Prata", "3161007"], + ["MG", "S\U000000e3o F\U000000e9lix de Minas", "3161056"], + ["MG", "S\U000000e3o Francisco", "3161106"], + ["MG", "S\U000000e3o Francisco de Paula", "3161205"], + ["MG", "S\U000000e3o Francisco de Sales", "3161304"], + ["MG", "S\U000000e3o Francisco do Gl\U000000f3ria", "3161403"], + ["MG", "S\U000000e3o Geraldo", "3161502"], + ["MG", "S\U000000e3o Geraldo da Piedade", "3161601"], + ["MG", "S\U000000e3o Geraldo do Baixio", "3161650"], + ["MG", "S\U000000e3o Gon\U000000e7alo do Abaet\U000000e9", "3161700"], + ["MG", "S\U000000e3o Gon\U000000e7alo do Par\U000000e1", "3161809"], + ["MG", "S\U000000e3o Gon\U000000e7alo do Rio Abaixo", "3161908"], + ["MG", "S\U000000e3o Gon\U000000e7alo do Rio Preto", "3125507"], + ["MG", "S\U000000e3o Gon\U000000e7alo do Sapuca\U000000ed", "3162005"], + ["MG", "S\U000000e3o Gotardo", "3162104"], + ["MG", "S\U000000e3o Jo\U000000e3o Batista do Gl\U000000f3ria", "3162203"], + ["MG", "S\U000000e3o Jo\U000000e3o da Lagoa", "3162252"], + ["MG", "S\U000000e3o Jo\U000000e3o da Mata", "3162302"], + ["MG", "S\U000000e3o Jo\U000000e3o da Ponte", "3162401"], + ["MG", "S\U000000e3o Jo\U000000e3o das Miss\U000000f5es", "3162450"], + ["MG", "S\U000000e3o Jo\U000000e3o del Rei", "3162500"], + ["MG", "S\U000000e3o Jo\U000000e3o do Manhua\U000000e7u", "3162559"], + ["MG", "S\U000000e3o Jo\U000000e3o do Manteninha", "3162575"], + ["MG", "S\U000000e3o Jo\U000000e3o do Oriente", "3162609"], + ["MG", "S\U000000e3o Jo\U000000e3o do Pacu\U000000ed", "3162658"], + ["MG", "S\U000000e3o Jo\U000000e3o do Para\U000000edso", "3162708"], + ["MG", "S\U000000e3o Jo\U000000e3o Evangelista", "3162807"], + ["MG", "S\U000000e3o Jo\U000000e3o Nepomuceno", "3162906"], + ["MG", "S\U000000e3o Joaquim de Bicas", "3162922"], + ["MG", "S\U000000e3o Jos\U000000e9 da Barra", "3162948"], + ["MG", "S\U000000e3o Jos\U000000e9 da Lapa", "3162955"], + ["MG", "S\U000000e3o Jos\U000000e9 da Safira", "3163003"], + ["MG", "S\U000000e3o Jos\U000000e9 da Varginha", "3163102"], + ["MG", "S\U000000e3o Jos\U000000e9 do Alegre", "3163201"], + ["MG", "S\U000000e3o Jos\U000000e9 do Divino", "3163300"], + ["MG", "S\U000000e3o Jos\U000000e9 do Goiabal", "3163409"], + ["MG", "S\U000000e3o Jos\U000000e9 do Jacuri", "3163508"], + ["MG", "S\U000000e3o Jos\U000000e9 do Mantimento", "3163607"], + ["MG", "S\U000000e3o Louren\U000000e7o", "3163706"], + ["MG", "S\U000000e3o Miguel do Anta", "3163805"], + ["MG", "S\U000000e3o Pedro da Uni\U000000e3o", "3163904"], + ["MG", "S\U000000e3o Pedro do Sua\U000000e7u\U000000ed", "3164100"], + ["MG", "S\U000000e3o Pedro dos Ferros", "3164001"], + ["MG", "S\U000000e3o Rom\U000000e3o", "3164209"], + ["MG", "S\U000000e3o Roque de Minas", "3164308"], + ["MG", "S\U000000e3o Sebasti\U000000e3o da Bela Vista", "3164407"], + ["MG", "S\U000000e3o Sebasti\U000000e3o da Vargem Alegre", "3164431"], + ["MG", "S\U000000e3o Sebasti\U000000e3o do Anta", "3164472"], + ["MG", "S\U000000e3o Sebasti\U000000e3o do Maranh\U000000e3o", "3164506"], + ["MG", "S\U000000e3o Sebasti\U000000e3o do Oeste", "3164605"], + ["MG", "S\U000000e3o Sebasti\U000000e3o do Para\U000000edso", "3164704"], + ["MG", "S\U000000e3o Sebasti\U000000e3o do Rio Preto", "3164803"], + ["MG", "S\U000000e3o Sebasti\U000000e3o do Rio Verde", "3164902"], + ["MG", "S\U000000e3o Tiago", "3165008"], + ["MG", "S\U000000e3o Tom\U000000e1s de Aquino", "3165107"], + ["MG", "S\U000000e3o Tom\U000000e9 das Letras", "3165206"], + ["MG", "S\U000000e3o Vicente de Minas", "3165305"], + ["MG", "Sapuca\U000000ed-Mirim", "3165404"], + ["MG", "Sardo\U000000e1", "3165503"], + ["MG", "Sarzedo", "3165537"], + ["MG", "Sem-Peixe", "3165560"], + ["MG", "Senador Amaral", "3165578"], + ["MG", "Senador Cortes", "3165602"], + ["MG", "Senador Firmino", "3165701"], + ["MG", "Senador Jos\U000000e9 Bento", "3165800"], + ["MG", "Senador Modestino Gon\U000000e7alves", "3165909"], + ["MG", "Senhora de Oliveira", "3166006"], + ["MG", "Senhora do Porto", "3166105"], + ["MG", "Senhora dos Rem\U000000e9dios", "3166204"], + ["MG", "Sericita", "3166303"], + ["MG", "Seritinga", "3166402"], + ["MG", "Serra Azul de Minas", "3166501"], + ["MG", "Serra da Saudade", "3166600"], + ["MG", "Serra do Salitre", "3166808"], + ["MG", "Serra dos Aimor\U000000e9s", "3166709"], + ["MG", "Serrania", "3166907"], + ["MG", "Serran\U000000f3polis de Minas", "3166956"], + ["MG", "Serranos", "3167004"], + ["MG", "Serro", "3167103"], + ["MG", "Sete Lagoas", "3167202"], + ["MG", "Setubinha", "3165552"], + ["MG", "Silveir\U000000e2nia", "3167301"], + ["MG", "Silvian\U000000f3polis", "3167400"], + ["MG", "Sim\U000000e3o Pereira", "3167509"], + ["MG", "Simon\U000000e9sia", "3167608"], + ["MG", "Sobr\U000000e1lia", "3167707"], + ["MG", "Soledade de Minas", "3167806"], + ["MG", "Tabuleiro", "3167905"], + ["MG", "Taiobeiras", "3168002"], + ["MG", "Taparuba", "3168051"], + ["MG", "Tapira", "3168101"], + ["MG", "Tapira\U000000ed", "3168200"], + ["MG", "Taquara\U000000e7u de Minas", "3168309"], + ["MG", "Tarumirim", "3168408"], + ["MG", "Teixeiras", "3168507"], + ["MG", "Te\U000000f3filo Otoni", "3168606"], + ["MG", "Tim\U000000f3teo", "3168705"], + ["MG", "Tiradentes", "3168804"], + ["MG", "Tiros", "3168903"], + ["MG", "Tocantins", "3169000"], + ["MG", "Tocos do Moji", "3169059"], + ["MG", "Toledo", "3169109"], + ["MG", "Tombos", "3169208"], + ["MG", "Tr\U000000eas Cora\U000000e7\U000000f5es", "3169307"], + ["MG", "Tr\U000000eas Marias", "3169356"], + ["MG", "Tr\U000000eas Pontas", "3169406"], + ["MG", "Tumiritinga", "3169505"], + ["MG", "Tupaciguara", "3169604"], + ["MG", "Turmalina", "3169703"], + ["MG", "Turvol\U000000e2ndia", "3169802"], + ["MG", "Ub\U000000e1", "3169901"], + ["MG", "Uba\U000000ed", "3170008"], + ["MG", "Ubaporanga", "3170057"], + ["MG", "Uberaba", "3170107"], + ["MG", "Uberl\U000000e2ndia", "3170206"], + ["MG", "Umburatiba", "3170305"], + ["MG", "Una\U000000ed", "3170404"], + ["MG", "Uni\U000000e3o de Minas", "3170438"], + ["MG", "Uruana de Minas", "3170479"], + ["MG", "Uruc\U000000e2nia", "3170503"], + ["MG", "Urucuia", "3170529"], + ["MG", "Vargem Alegre", "3170578"], + ["MG", "Vargem Bonita", "3170602"], + ["MG", "Vargem Grande do Rio Pardo", "3170651"], + ["MG", "Varginha", "3170701"], + ["MG", "Varj\U000000e3o de Minas", "3170750"], + ["MG", "V\U000000e1rzea da Palma", "3170800"], + ["MG", "Varzel\U000000e2ndia", "3170909"], + ["MG", "Vazante", "3171006"], + ["MG", "Verdel\U000000e2ndia", "3171030"], + ["MG", "Veredinha", "3171071"], + ["MG", "Ver\U000000edssimo", "3171105"], + ["MG", "Vermelho Novo", "3171154"], + ["MG", "Vespasiano", "3171204"], + ["MG", "Vi\U000000e7osa", "3171303"], + ["MG", "Vieiras", "3171402"], + ["MG", "Virgem da Lapa", "3171600"], + ["MG", "Virg\U000000ednia", "3171709"], + ["MG", "Virgin\U000000f3polis", "3171808"], + ["MG", "Virgol\U000000e2ndia", "3171907"], + ["MG", "Visconde do Rio Branco", "3172004"], + ["MG", "Volta Grande", "3172103"], + ["MG", "Wenceslau Braz", "3172202"], + ["PA", "Abaetetuba", "1500107"], + ["PA", "Abel Figueiredo", "1500131"], + ["PA", "Acar\U000000e1", "1500206"], + ["PA", "Afu\U000000e1", "1500305"], + ["PA", "\U000000c1gua Azul do Norte", "1500347"], + ["PA", "Alenquer", "1500404"], + ["PA", "Almeirim", "1500503"], + ["PA", "Altamira", "1500602"], + ["PA", "Anaj\U000000e1s", "1500701"], + ["PA", "Ananindeua", "1500800"], + ["PA", "Anapu", "1500859"], + ["PA", "Augusto Corr\U000000eaa", "1500909"], + ["PA", "Aurora do Par\U000000e1", "1500958"], + ["PA", "Aveiro", "1501006"], + ["PA", "Bagre", "1501105"], + ["PA", "Bai\U000000e3o", "1501204"], + ["PA", "Bannach", "1501253"], + ["PA", "Barcarena", "1501303"], + ["PA", "Bel\U000000e9m", "1501402"], + ["PA", "Belterra", "1501451"], + ["PA", "Benevides", "1501501"], + ["PA", "Bom Jesus do Tocantins", "1501576"], + ["PA", "Bonito", "1501600"], + ["PA", "Bragan\U000000e7a", "1501709"], + ["PA", "Brasil Novo", "1501725"], + ["PA", "Brejo Grande do Araguaia", "1501758"], + ["PA", "Breu Branco", "1501782"], + ["PA", "Breves", "1501808"], + ["PA", "Bujaru", "1501907"], + ["PA", "Cachoeira do Arari", "1502004"], + ["PA", "Cachoeira do Piri\U000000e1", "1501956"], + ["PA", "Camet\U000000e1", "1502103"], + ["PA", "Cana\U000000e3 dos Caraj\U000000e1s", "1502152"], + ["PA", "Capanema", "1502202"], + ["PA", "Capit\U000000e3o Po\U000000e7o", "1502301"], + ["PA", "Castanhal", "1502400"], + ["PA", "Chaves", "1502509"], + ["PA", "Colares", "1502608"], + ["PA", "Concei\U000000e7\U000000e3o do Araguaia", "1502707"], + ["PA", "Conc\U000000f3rdia do Par\U000000e1", "1502756"], + ["PA", "Cumaru do Norte", "1502764"], + ["PA", "Curion\U000000f3polis", "1502772"], + ["PA", "Curralinho", "1502806"], + ["PA", "Curu\U000000e1", "1502855"], + ["PA", "Curu\U000000e7\U000000e1", "1502905"], + ["PA", "Dom Eliseu", "1502939"], + ["PA", "Eldorado do Caraj\U000000e1s", "1502954"], + ["PA", "Faro", "1503002"], + ["PA", "Floresta do Araguaia", "1503044"], + ["PA", "Garraf\U000000e3o do Norte", "1503077"], + ["PA", "Goian\U000000e9sia do Par\U000000e1", "1503093"], + ["PA", "Gurup\U000000e1", "1503101"], + ["PA", "Igarap\U000000e9-A\U000000e7u", "1503200"], + ["PA", "Igarap\U000000e9-Miri", "1503309"], + ["PA", "Inhangapi", "1503408"], + ["PA", "Ipixuna do Par\U000000e1", "1503457"], + ["PA", "Irituia", "1503507"], + ["PA", "Itaituba", "1503606"], + ["PA", "Itupiranga", "1503705"], + ["PA", "Jacareacanga", "1503754"], + ["PA", "Jacund\U000000e1", "1503804"], + ["PA", "Juruti", "1503903"], + ["PA", "Limoeiro do Ajuru", "1504000"], + ["PA", "M\U000000e3e do Rio", "1504059"], + ["PA", "Magalh\U000000e3es Barata", "1504109"], + ["PA", "Marab\U000000e1", "1504208"], + ["PA", "Maracan\U000000e3", "1504307"], + ["PA", "Marapanim", "1504406"], + ["PA", "Marituba", "1504422"], + ["PA", "Medicil\U000000e2ndia", "1504455"], + ["PA", "Melga\U000000e7o", "1504505"], + ["PA", "Mocajuba", "1504604"], + ["PA", "Moju", "1504703"], + ["PA", "Moju\U000000ed dos Campos", "1504752"], + ["PA", "Monte Alegre", "1504802"], + ["PA", "Muan\U000000e1", "1504901"], + ["PA", "Nova Esperan\U000000e7a do Piri\U000000e1", "1504950"], + ["PA", "Nova Ipixuna", "1504976"], + ["PA", "Nova Timboteua", "1505007"], + ["PA", "Novo Progresso", "1505031"], + ["PA", "Novo Repartimento", "1505064"], + ["PA", "\U000000d3bidos", "1505106"], + ["PA", "Oeiras do Par\U000000e1", "1505205"], + ["PA", "Oriximin\U000000e1", "1505304"], + ["PA", "Our\U000000e9m", "1505403"], + ["PA", "Ouril\U000000e2ndia do Norte", "1505437"], + ["PA", "Pacaj\U000000e1", "1505486"], + ["PA", "Palestina do Par\U000000e1", "1505494"], + ["PA", "Paragominas", "1505502"], + ["PA", "Parauapebas", "1505536"], + ["PA", "Pau D'Arco", "1505551"], + ["PA", "Peixe-Boi", "1505601"], + ["PA", "Pi\U000000e7arra", "1505635"], + ["PA", "Placas", "1505650"], + ["PA", "Ponta de Pedras", "1505700"], + ["PA", "Portel", "1505809"], + ["PA", "Porto de Moz", "1505908"], + ["PA", "Prainha", "1506005"], + ["PA", "Primavera", "1506104"], + ["PA", "Quatipuru", "1506112"], + ["PA", "Reden\U000000e7\U000000e3o", "1506138"], + ["PA", "Rio Maria", "1506161"], + ["PA", "Rondon do Par\U000000e1", "1506187"], + ["PA", "Rur\U000000f3polis", "1506195"], + ["PA", "Salin\U000000f3polis", "1506203"], + ["PA", "Salvaterra", "1506302"], + ["PA", "Santa B\U000000e1rbara do Par\U000000e1", "1506351"], + ["PA", "Santa Cruz do Arari", "1506401"], + ["PA", "Santa Izabel do Par\U000000e1", "1506500"], + ["PA", "Santa Luzia do Par\U000000e1", "1506559"], + ["PA", "Santa Maria das Barreiras", "1506583"], + ["PA", "Santa Maria do Par\U000000e1", "1506609"], + ["PA", "Santana do Araguaia", "1506708"], + ["PA", "Santar\U000000e9m", "1506807"], + ["PA", "Santar\U000000e9m Novo", "1506906"], + ["PA", "Santo Ant\U000000f4nio do Tau\U000000e1", "1507003"], + ["PA", "S\U000000e3o Caetano de Odivelas", "1507102"], + ["PA", "S\U000000e3o Domingos do Araguaia", "1507151"], + ["PA", "S\U000000e3o Domingos do Capim", "1507201"], + ["PA", "S\U000000e3o F\U000000e9lix do Xingu", "1507300"], + ["PA", "S\U000000e3o Francisco do Par\U000000e1", "1507409"], + ["PA", "S\U000000e3o Geraldo do Araguaia", "1507458"], + ["PA", "S\U000000e3o Jo\U000000e3o da Ponta", "1507466"], + ["PA", "S\U000000e3o Jo\U000000e3o de Pirabas", "1507474"], + ["PA", "S\U000000e3o Jo\U000000e3o do Araguaia", "1507508"], + ["PA", "S\U000000e3o Miguel do Guam\U000000e1", "1507607"], + ["PA", "S\U000000e3o Sebasti\U000000e3o da Boa Vista", "1507706"], + ["PA", "Sapucaia", "1507755"], + ["PA", "Senador Jos\U000000e9 Porf\U000000edrio", "1507805"], + ["PA", "Soure", "1507904"], + ["PA", "Tail\U000000e2ndia", "1507953"], + ["PA", "Terra Alta", "1507961"], + ["PA", "Terra Santa", "1507979"], + ["PA", "Tom\U000000e9-A\U000000e7u", "1508001"], + ["PA", "Tracuateua", "1508035"], + ["PA", "Trair\U000000e3o", "1508050"], + ["PA", "Tucum\U000000e3", "1508084"], + ["PA", "Tucuru\U000000ed", "1508100"], + ["PA", "Ulian\U000000f3polis", "1508126"], + ["PA", "Uruar\U000000e1", "1508159"], + ["PA", "Vigia", "1508209"], + ["PA", "Viseu", "1508308"], + ["PA", "Vit\U000000f3ria do Xingu", "1508357"], + ["PA", "Xinguara", "1508407"], + ["PB", "\U000000c1gua Branca", "2500106"], + ["PB", "Aguiar", "2500205"], + ["PB", "Alagoa Grande", "2500304"], + ["PB", "Alagoa Nova", "2500403"], + ["PB", "Alagoinha", "2500502"], + ["PB", "Alcantil", "2500536"], + ["PB", "Algod\U000000e3o de Janda\U000000edra", "2500577"], + ["PB", "Alhandra", "2500601"], + ["PB", "Amparo", "2500734"], + ["PB", "Aparecida", "2500775"], + ["PB", "Ara\U000000e7agi", "2500809"], + ["PB", "Arara", "2500908"], + ["PB", "Araruna", "2501005"], + ["PB", "Areia", "2501104"], + ["PB", "Areia de Bara\U000000fanas", "2501153"], + ["PB", "Areial", "2501203"], + ["PB", "Aroeiras", "2501302"], + ["PB", "Assun\U000000e7\U000000e3o", "2501351"], + ["PB", "Ba\U000000eda da Trai\U000000e7\U000000e3o", "2501401"], + ["PB", "Bananeiras", "2501500"], + ["PB", "Bara\U000000fana", "2501534"], + ["PB", "Barra de Santa Rosa", "2501609"], + ["PB", "Barra de Santana", "2501575"], + ["PB", "Barra de S\U000000e3o Miguel", "2501708"], + ["PB", "Bayeux", "2501807"], + ["PB", "Bel\U000000e9m", "2501906"], + ["PB", "Bel\U000000e9m do Brejo do Cruz", "2502003"], + ["PB", "Bernardino Batista", "2502052"], + ["PB", "Boa Ventura", "2502102"], + ["PB", "Boa Vista", "2502151"], + ["PB", "Bom Jesus", "2502201"], + ["PB", "Bom Sucesso", "2502300"], + ["PB", "Bonito de Santa F\U000000e9", "2502409"], + ["PB", "Boqueir\U000000e3o", "2502508"], + ["PB", "Borborema", "2502706"], + ["PB", "Brejo do Cruz", "2502805"], + ["PB", "Brejo dos Santos", "2502904"], + ["PB", "Caapor\U000000e3", "2503001"], + ["PB", "Cabaceiras", "2503100"], + ["PB", "Cabedelo", "2503209"], + ["PB", "Cachoeira dos \U000000cdndios", "2503308"], + ["PB", "Cacimba de Areia", "2503407"], + ["PB", "Cacimba de Dentro", "2503506"], + ["PB", "Cacimbas", "2503555"], + ["PB", "Cai\U000000e7ara", "2503605"], + ["PB", "Cajazeiras", "2503704"], + ["PB", "Cajazeirinhas", "2503753"], + ["PB", "Caldas Brand\U000000e3o", "2503803"], + ["PB", "Camala\U000000fa", "2503902"], + ["PB", "Campina Grande", "2504009"], + ["PB", "Capim", "2504033"], + ["PB", "Cara\U000000fabas", "2504074"], + ["PB", "Carrapateira", "2504108"], + ["PB", "Casserengue", "2504157"], + ["PB", "Catingueira", "2504207"], + ["PB", "Catol\U000000e9 do Rocha", "2504306"], + ["PB", "Caturit\U000000e9", "2504355"], + ["PB", "Concei\U000000e7\U000000e3o", "2504405"], + ["PB", "Condado", "2504504"], + ["PB", "Conde", "2504603"], + ["PB", "Congo", "2504702"], + ["PB", "Coremas", "2504801"], + ["PB", "Coxixola", "2504850"], + ["PB", "Cruz do Esp\U000000edrito Santo", "2504900"], + ["PB", "Cubati", "2505006"], + ["PB", "Cuit\U000000e9", "2505105"], + ["PB", "Cuit\U000000e9 de Mamanguape", "2505238"], + ["PB", "Cuitegi", "2505204"], + ["PB", "Curral de Cima", "2505279"], + ["PB", "Curral Velho", "2505303"], + ["PB", "Dami\U000000e3o", "2505352"], + ["PB", "Desterro", "2505402"], + ["PB", "Diamante", "2505600"], + ["PB", "Dona In\U000000eas", "2505709"], + ["PB", "Duas Estradas", "2505808"], + ["PB", "Emas", "2505907"], + ["PB", "Esperan\U000000e7a", "2506004"], + ["PB", "Fagundes", "2506103"], + ["PB", "Frei Martinho", "2506202"], + ["PB", "Gado Bravo", "2506251"], + ["PB", "Guarabira", "2506301"], + ["PB", "Gurinh\U000000e9m", "2506400"], + ["PB", "Gurj\U000000e3o", "2506509"], + ["PB", "Ibiara", "2506608"], + ["PB", "Igaracy", "2502607"], + ["PB", "Imaculada", "2506707"], + ["PB", "Ing\U000000e1", "2506806"], + ["PB", "Itabaiana", "2506905"], + ["PB", "Itaporanga", "2507002"], + ["PB", "Itapororoca", "2507101"], + ["PB", "Itatuba", "2507200"], + ["PB", "Jacara\U000000fa", "2507309"], + ["PB", "Jeric\U000000f3", "2507408"], + ["PB", "Jo\U000000e3o Pessoa", "2507507"], + ["PB", "Joca Claudino", "2513653"], + ["PB", "Juarez T\U000000e1vora", "2507606"], + ["PB", "Juazeirinho", "2507705"], + ["PB", "Junco do Serid\U000000f3", "2507804"], + ["PB", "Juripiranga", "2507903"], + ["PB", "Juru", "2508000"], + ["PB", "Lagoa", "2508109"], + ["PB", "Lagoa de Dentro", "2508208"], + ["PB", "Lagoa Seca", "2508307"], + ["PB", "Lastro", "2508406"], + ["PB", "Livramento", "2508505"], + ["PB", "Logradouro", "2508554"], + ["PB", "Lucena", "2508604"], + ["PB", "M\U000000e3e d'\U000000c1gua", "2508703"], + ["PB", "Malta", "2508802"], + ["PB", "Mamanguape", "2508901"], + ["PB", "Mana\U000000edra", "2509008"], + ["PB", "Marca\U000000e7\U000000e3o", "2509057"], + ["PB", "Mari", "2509107"], + ["PB", "Mariz\U000000f3polis", "2509156"], + ["PB", "Massaranduba", "2509206"], + ["PB", "Mataraca", "2509305"], + ["PB", "Matinhas", "2509339"], + ["PB", "Mato Grosso", "2509370"], + ["PB", "Matur\U000000e9ia", "2509396"], + ["PB", "Mogeiro", "2509404"], + ["PB", "Montadas", "2509503"], + ["PB", "Monte Horebe", "2509602"], + ["PB", "Monteiro", "2509701"], + ["PB", "Mulungu", "2509800"], + ["PB", "Natuba", "2509909"], + ["PB", "Nazarezinho", "2510006"], + ["PB", "Nova Floresta", "2510105"], + ["PB", "Nova Olinda", "2510204"], + ["PB", "Nova Palmeira", "2510303"], + ["PB", "Olho d'\U000000c1gua", "2510402"], + ["PB", "Olivedos", "2510501"], + ["PB", "Ouro Velho", "2510600"], + ["PB", "Parari", "2510659"], + ["PB", "Passagem", "2510709"], + ["PB", "Patos", "2510808"], + ["PB", "Paulista", "2510907"], + ["PB", "Pedra Branca", "2511004"], + ["PB", "Pedra Lavrada", "2511103"], + ["PB", "Pedras de Fogo", "2511202"], + ["PB", "Pedro R\U000000e9gis", "2512721"], + ["PB", "Pianc\U000000f3", "2511301"], + ["PB", "Picu\U000000ed", "2511400"], + ["PB", "Pilar", "2511509"], + ["PB", "Pil\U000000f5es", "2511608"], + ["PB", "Pil\U000000f5ezinhos", "2511707"], + ["PB", "Pirpirituba", "2511806"], + ["PB", "Pitimbu", "2511905"], + ["PB", "Pocinhos", "2512002"], + ["PB", "Po\U000000e7o Dantas", "2512036"], + ["PB", "Po\U000000e7o de Jos\U000000e9 de Moura", "2512077"], + ["PB", "Pombal", "2512101"], + ["PB", "Prata", "2512200"], + ["PB", "Princesa Isabel", "2512309"], + ["PB", "Puxinan\U000000e3", "2512408"], + ["PB", "Queimadas", "2512507"], + ["PB", "Quixaba", "2512606"], + ["PB", "Rem\U000000edgio", "2512705"], + ["PB", "Riach\U000000e3o", "2512747"], + ["PB", "Riach\U000000e3o do Bacamarte", "2512754"], + ["PB", "Riach\U000000e3o do Po\U000000e7o", "2512762"], + ["PB", "Riacho de Santo Ant\U000000f4nio", "2512788"], + ["PB", "Riacho dos Cavalos", "2512804"], + ["PB", "Rio Tinto", "2512903"], + ["PB", "Salgadinho", "2513000"], + ["PB", "Salgado de S\U000000e3o F\U000000e9lix", "2513109"], + ["PB", "Santa Cec\U000000edlia", "2513158"], + ["PB", "Santa Cruz", "2513208"], + ["PB", "Santa Helena", "2513307"], + ["PB", "Santa In\U000000eas", "2513356"], + ["PB", "Santa Luzia", "2513406"], + ["PB", "Santa Rita", "2513703"], + ["PB", "Santa Teresinha", "2513802"], + ["PB", "Santana de Mangueira", "2513505"], + ["PB", "Santana dos Garrotes", "2513604"], + ["PB", "Santo Andr\U000000e9", "2513851"], + ["PB", "S\U000000e3o Bentinho", "2513927"], + ["PB", "S\U000000e3o Bento", "2513901"], + ["PB", "S\U000000e3o Domingos", "2513968"], + ["PB", "S\U000000e3o Domingos do Cariri", "2513943"], + ["PB", "S\U000000e3o Francisco", "2513984"], + ["PB", "S\U000000e3o Jo\U000000e3o do Cariri", "2514008"], + ["PB", "S\U000000e3o Jo\U000000e3o do Rio do Peixe", "2500700"], + ["PB", "S\U000000e3o Jo\U000000e3o do Tigre", "2514107"], + ["PB", "S\U000000e3o Jos\U000000e9 da Lagoa Tapada", "2514206"], + ["PB", "S\U000000e3o Jos\U000000e9 de Caiana", "2514305"], + ["PB", "S\U000000e3o Jos\U000000e9 de Espinharas", "2514404"], + ["PB", "S\U000000e3o Jos\U000000e9 de Piranhas", "2514503"], + ["PB", "S\U000000e3o Jos\U000000e9 de Princesa", "2514552"], + ["PB", "S\U000000e3o Jos\U000000e9 do Bonfim", "2514602"], + ["PB", "S\U000000e3o Jos\U000000e9 do Brejo do Cruz", "2514651"], + ["PB", "S\U000000e3o Jos\U000000e9 do Sabugi", "2514701"], + ["PB", "S\U000000e3o Jos\U000000e9 dos Cordeiros", "2514800"], + ["PB", "S\U000000e3o Jos\U000000e9 dos Ramos", "2514453"], + ["PB", "S\U000000e3o Mamede", "2514909"], + ["PB", "S\U000000e3o Miguel de Taipu", "2515005"], + ["PB", "S\U000000e3o Sebasti\U000000e3o de Lagoa de Ro\U000000e7a", "2515104"], + ["PB", "S\U000000e3o Sebasti\U000000e3o do Umbuzeiro", "2515203"], + ["PB", "S\U000000e3o Vicente do Serid\U000000f3", "2515401"], + ["PB", "Sap\U000000e9", "2515302"], + ["PB", "Serra Branca", "2515500"], + ["PB", "Serra da Raiz", "2515609"], + ["PB", "Serra Grande", "2515708"], + ["PB", "Serra Redonda", "2515807"], + ["PB", "Serraria", "2515906"], + ["PB", "Sert\U000000e3ozinho", "2515930"], + ["PB", "Sobrado", "2515971"], + ["PB", "Sol\U000000e2nea", "2516003"], + ["PB", "Soledade", "2516102"], + ["PB", "Soss\U000000eago", "2516151"], + ["PB", "Sousa", "2516201"], + ["PB", "Sum\U000000e9", "2516300"], + ["PB", "Tacima", "2516409"], + ["PB", "Tapero\U000000e1", "2516508"], + ["PB", "Tavares", "2516607"], + ["PB", "Teixeira", "2516706"], + ["PB", "Ten\U000000f3rio", "2516755"], + ["PB", "Triunfo", "2516805"], + ["PB", "Uira\U000000fana", "2516904"], + ["PB", "Umbuzeiro", "2517001"], + ["PB", "V\U000000e1rzea", "2517100"], + ["PB", "Vieir\U000000f3polis", "2517209"], + ["PB", "Vista Serrana", "2505501"], + ["PB", "Zabel\U000000ea", "2517407"], + ["PR", "Abati\U000000e1", "4100103"], + ["PR", "Adrian\U000000f3polis", "4100202"], + ["PR", "Agudos do Sul", "4100301"], + ["PR", "Almirante Tamandar\U000000e9", "4100400"], + ["PR", "Altamira do Paran\U000000e1", "4100459"], + ["PR", "Alto Para\U000000edso", "4128625"], + ["PR", "Alto Paran\U000000e1", "4100608"], + ["PR", "Alto Piquiri", "4100707"], + ["PR", "Alt\U000000f4nia", "4100509"], + ["PR", "Alvorada do Sul", "4100806"], + ["PR", "Amapor\U000000e3", "4100905"], + ["PR", "Amp\U000000e9re", "4101002"], + ["PR", "Anahy", "4101051"], + ["PR", "Andir\U000000e1", "4101101"], + ["PR", "\U000000c2ngulo", "4101150"], + ["PR", "Antonina", "4101200"], + ["PR", "Ant\U000000f4nio Olinto", "4101309"], + ["PR", "Apucarana", "4101408"], + ["PR", "Arapongas", "4101507"], + ["PR", "Arapoti", "4101606"], + ["PR", "Arapu\U000000e3", "4101655"], + ["PR", "Araruna", "4101705"], + ["PR", "Arauc\U000000e1ria", "4101804"], + ["PR", "Ariranha do Iva\U000000ed", "4101853"], + ["PR", "Assa\U000000ed", "4101903"], + ["PR", "Assis Chateaubriand", "4102000"], + ["PR", "Astorga", "4102109"], + ["PR", "Atalaia", "4102208"], + ["PR", "Balsa Nova", "4102307"], + ["PR", "Bandeirantes", "4102406"], + ["PR", "Barbosa Ferraz", "4102505"], + ["PR", "Barra do Jacar\U000000e9", "4102703"], + ["PR", "Barrac\U000000e3o", "4102604"], + ["PR", "Bela Vista da Caroba", "4102752"], + ["PR", "Bela Vista do Para\U000000edso", "4102802"], + ["PR", "Bituruna", "4102901"], + ["PR", "Boa Esperan\U000000e7a", "4103008"], + ["PR", "Boa Esperan\U000000e7a do Igua\U000000e7u", "4103024"], + ["PR", "Boa Ventura de S\U000000e3o Roque", "4103040"], + ["PR", "Boa Vista da Aparecida", "4103057"], + ["PR", "Bocai\U000000fava do Sul", "4103107"], + ["PR", "Bom Jesus do Sul", "4103156"], + ["PR", "Bom Sucesso", "4103206"], + ["PR", "Bom Sucesso do Sul", "4103222"], + ["PR", "Borraz\U000000f3polis", "4103305"], + ["PR", "Braganey", "4103354"], + ["PR", "Brasil\U000000e2ndia do Sul", "4103370"], + ["PR", "Cafeara", "4103404"], + ["PR", "Cafel\U000000e2ndia", "4103453"], + ["PR", "Cafezal do Sul", "4103479"], + ["PR", "Calif\U000000f3rnia", "4103503"], + ["PR", "Cambar\U000000e1", "4103602"], + ["PR", "Camb\U000000e9", "4103701"], + ["PR", "Cambira", "4103800"], + ["PR", "Campina da Lagoa", "4103909"], + ["PR", "Campina do Sim\U000000e3o", "4103958"], + ["PR", "Campina Grande do Sul", "4104006"], + ["PR", "Campo Bonito", "4104055"], + ["PR", "Campo do Tenente", "4104105"], + ["PR", "Campo Largo", "4104204"], + ["PR", "Campo Magro", "4104253"], + ["PR", "Campo Mour\U000000e3o", "4104303"], + ["PR", "C\U000000e2ndido de Abreu", "4104402"], + ["PR", "Cand\U000000f3i", "4104428"], + ["PR", "Cantagalo", "4104451"], + ["PR", "Capanema", "4104501"], + ["PR", "Capit\U000000e3o Le\U000000f4nidas Marques", "4104600"], + ["PR", "Carambe\U000000ed", "4104659"], + ["PR", "Carl\U000000f3polis", "4104709"], + ["PR", "Cascavel", "4104808"], + ["PR", "Castro", "4104907"], + ["PR", "Catanduvas", "4105003"], + ["PR", "Centen\U000000e1rio do Sul", "4105102"], + ["PR", "Cerro Azul", "4105201"], + ["PR", "C\U000000e9u Azul", "4105300"], + ["PR", "Chopinzinho", "4105409"], + ["PR", "Cianorte", "4105508"], + ["PR", "Cidade Ga\U000000facha", "4105607"], + ["PR", "Clevel\U000000e2ndia", "4105706"], + ["PR", "Colombo", "4105805"], + ["PR", "Colorado", "4105904"], + ["PR", "Congonhinhas", "4106001"], + ["PR", "Conselheiro Mairinck", "4106100"], + ["PR", "Contenda", "4106209"], + ["PR", "Corb\U000000e9lia", "4106308"], + ["PR", "Corn\U000000e9lio Proc\U000000f3pio", "4106407"], + ["PR", "Coronel Domingos Soares", "4106456"], + ["PR", "Coronel Vivida", "4106506"], + ["PR", "Corumbata\U000000ed do Sul", "4106555"], + ["PR", "Cruz Machado", "4106803"], + ["PR", "Cruzeiro do Igua\U000000e7u", "4106571"], + ["PR", "Cruzeiro do Oeste", "4106605"], + ["PR", "Cruzeiro do Sul", "4106704"], + ["PR", "Cruzmaltina", "4106852"], + ["PR", "Curitiba", "4106902"], + ["PR", "Curi\U000000fava", "4107009"], + ["PR", "Diamante D'Oeste", "4107157"], + ["PR", "Diamante do Norte", "4107108"], + ["PR", "Diamante do Sul", "4107124"], + ["PR", "Dois Vizinhos", "4107207"], + ["PR", "Douradina", "4107256"], + ["PR", "Doutor Camargo", "4107306"], + ["PR", "Doutor Ulysses", "4128633"], + ["PR", "En\U000000e9as Marques", "4107405"], + ["PR", "Engenheiro Beltr\U000000e3o", "4107504"], + ["PR", "Entre Rios do Oeste", "4107538"], + ["PR", "Esperan\U000000e7a Nova", "4107520"], + ["PR", "Espig\U000000e3o Alto do Igua\U000000e7u", "4107546"], + ["PR", "Farol", "4107553"], + ["PR", "Faxinal", "4107603"], + ["PR", "Fazenda Rio Grande", "4107652"], + ["PR", "F\U000000eanix", "4107702"], + ["PR", "Fernandes Pinheiro", "4107736"], + ["PR", "Figueira", "4107751"], + ["PR", "Flor da Serra do Sul", "4107850"], + ["PR", "Flora\U000000ed", "4107801"], + ["PR", "Floresta", "4107900"], + ["PR", "Florest\U000000f3polis", "4108007"], + ["PR", "Fl\U000000f3rida", "4108106"], + ["PR", "Formosa do Oeste", "4108205"], + ["PR", "Foz do Igua\U000000e7u", "4108304"], + ["PR", "Foz do Jord\U000000e3o", "4108452"], + ["PR", "Francisco Alves", "4108320"], + ["PR", "Francisco Beltr\U000000e3o", "4108403"], + ["PR", "General Carneiro", "4108502"], + ["PR", "Godoy Moreira", "4108551"], + ["PR", "Goioer\U000000ea", "4108601"], + ["PR", "Goioxim", "4108650"], + ["PR", "Grandes Rios", "4108700"], + ["PR", "Gua\U000000edra", "4108809"], + ["PR", "Guaira\U000000e7\U000000e1", "4108908"], + ["PR", "Guamiranga", "4108957"], + ["PR", "Guapirama", "4109005"], + ["PR", "Guaporema", "4109104"], + ["PR", "Guaraci", "4109203"], + ["PR", "Guarania\U000000e7u", "4109302"], + ["PR", "Guarapuava", "4109401"], + ["PR", "Guaraque\U000000e7aba", "4109500"], + ["PR", "Guaratuba", "4109609"], + ["PR", "Hon\U000000f3rio Serpa", "4109658"], + ["PR", "Ibaiti", "4109708"], + ["PR", "Ibema", "4109757"], + ["PR", "Ibipor\U000000e3", "4109807"], + ["PR", "Icara\U000000edma", "4109906"], + ["PR", "Iguara\U000000e7u", "4110003"], + ["PR", "Iguatu", "4110052"], + ["PR", "Imba\U000000fa", "4110078"], + ["PR", "Imbituva", "4110102"], + ["PR", "In\U000000e1cio Martins", "4110201"], + ["PR", "Inaj\U000000e1", "4110300"], + ["PR", "Indian\U000000f3polis", "4110409"], + ["PR", "Ipiranga", "4110508"], + ["PR", "Ipor\U000000e3", "4110607"], + ["PR", "Iracema do Oeste", "4110656"], + ["PR", "Irati", "4110706"], + ["PR", "Iretama", "4110805"], + ["PR", "Itaguaj\U000000e9", "4110904"], + ["PR", "Itaipul\U000000e2ndia", "4110953"], + ["PR", "Itambarac\U000000e1", "4111001"], + ["PR", "Itamb\U000000e9", "4111100"], + ["PR", "Itapejara d'Oeste", "4111209"], + ["PR", "Itaperu\U000000e7u", "4111258"], + ["PR", "Ita\U000000fana do Sul", "4111308"], + ["PR", "Iva\U000000ed", "4111407"], + ["PR", "Ivaipor\U000000e3", "4111506"], + ["PR", "Ivat\U000000e9", "4111555"], + ["PR", "Ivatuba", "4111605"], + ["PR", "Jaboti", "4111704"], + ["PR", "Jacarezinho", "4111803"], + ["PR", "Jaguapit\U000000e3", "4111902"], + ["PR", "Jaguaria\U000000edva", "4112009"], + ["PR", "Jandaia do Sul", "4112108"], + ["PR", "Jani\U000000f3polis", "4112207"], + ["PR", "Japira", "4112306"], + ["PR", "Japur\U000000e1", "4112405"], + ["PR", "Jardim Alegre", "4112504"], + ["PR", "Jardim Olinda", "4112603"], + ["PR", "Jataizinho", "4112702"], + ["PR", "Jesu\U000000edtas", "4112751"], + ["PR", "Joaquim T\U000000e1vora", "4112801"], + ["PR", "Jundia\U000000ed do Sul", "4112900"], + ["PR", "Juranda", "4112959"], + ["PR", "Jussara", "4113007"], + ["PR", "Kalor\U000000e9", "4113106"], + ["PR", "Lapa", "4113205"], + ["PR", "Laranjal", "4113254"], + ["PR", "Laranjeiras do Sul", "4113304"], + ["PR", "Le\U000000f3polis", "4113403"], + ["PR", "Lidian\U000000f3polis", "4113429"], + ["PR", "Lindoeste", "4113452"], + ["PR", "Loanda", "4113502"], + ["PR", "Lobato", "4113601"], + ["PR", "Londrina", "4113700"], + ["PR", "Luiziana", "4113734"], + ["PR", "Lunardelli", "4113759"], + ["PR", "Lupion\U000000f3polis", "4113809"], + ["PR", "Mallet", "4113908"], + ["PR", "Mambor\U000000ea", "4114005"], + ["PR", "Mandagua\U000000e7u", "4114104"], + ["PR", "Mandaguari", "4114203"], + ["PR", "Mandirituba", "4114302"], + ["PR", "Manfrin\U000000f3polis", "4114351"], + ["PR", "Mangueirinha", "4114401"], + ["PR", "Manoel Ribas", "4114500"], + ["PR", "Marechal C\U000000e2ndido Rondon", "4114609"], + ["PR", "Maria Helena", "4114708"], + ["PR", "Marialva", "4114807"], + ["PR", "Maril\U000000e2ndia do Sul", "4114906"], + ["PR", "Marilena", "4115002"], + ["PR", "Mariluz", "4115101"], + ["PR", "Maring\U000000e1", "4115200"], + ["PR", "Mari\U000000f3polis", "4115309"], + ["PR", "Marip\U000000e1", "4115358"], + ["PR", "Marmeleiro", "4115408"], + ["PR", "Marquinho", "4115457"], + ["PR", "Marumbi", "4115507"], + ["PR", "Matel\U000000e2ndia", "4115606"], + ["PR", "Matinhos", "4115705"], + ["PR", "Mato Rico", "4115739"], + ["PR", "Mau\U000000e1 da Serra", "4115754"], + ["PR", "Medianeira", "4115804"], + ["PR", "Mercedes", "4115853"], + ["PR", "Mirador", "4115903"], + ["PR", "Miraselva", "4116000"], + ["PR", "Missal", "4116059"], + ["PR", "Moreira Sales", "4116109"], + ["PR", "Morretes", "4116208"], + ["PR", "Munhoz de Melo", "4116307"], + ["PR", "Nossa Senhora das Gra\U000000e7as", "4116406"], + ["PR", "Nova Alian\U000000e7a do Iva\U000000ed", "4116505"], + ["PR", "Nova Am\U000000e9rica da Colina", "4116604"], + ["PR", "Nova Aurora", "4116703"], + ["PR", "Nova Cantu", "4116802"], + ["PR", "Nova Esperan\U000000e7a", "4116901"], + ["PR", "Nova Esperan\U000000e7a do Sudoeste", "4116950"], + ["PR", "Nova F\U000000e1tima", "4117008"], + ["PR", "Nova Laranjeiras", "4117057"], + ["PR", "Nova Londrina", "4117107"], + ["PR", "Nova Ol\U000000edmpia", "4117206"], + ["PR", "Nova Prata do Igua\U000000e7u", "4117255"], + ["PR", "Nova Santa B\U000000e1rbara", "4117214"], + ["PR", "Nova Santa Rosa", "4117222"], + ["PR", "Nova Tebas", "4117271"], + ["PR", "Novo Itacolomi", "4117297"], + ["PR", "Ortigueira", "4117305"], + ["PR", "Ourizona", "4117404"], + ["PR", "Ouro Verde do Oeste", "4117453"], + ["PR", "Pai\U000000e7andu", "4117503"], + ["PR", "Palmas", "4117602"], + ["PR", "Palmeira", "4117701"], + ["PR", "Palmital", "4117800"], + ["PR", "Palotina", "4117909"], + ["PR", "Para\U000000edso do Norte", "4118006"], + ["PR", "Paranacity", "4118105"], + ["PR", "Paranagu\U000000e1", "4118204"], + ["PR", "Paranapoema", "4118303"], + ["PR", "Paranava\U000000ed", "4118402"], + ["PR", "Pato Bragado", "4118451"], + ["PR", "Pato Branco", "4118501"], + ["PR", "Paula Freitas", "4118600"], + ["PR", "Paulo Frontin", "4118709"], + ["PR", "Peabiru", "4118808"], + ["PR", "Perobal", "4118857"], + ["PR", "P\U000000e9rola", "4118907"], + ["PR", "P\U000000e9rola d'Oeste", "4119004"], + ["PR", "Pi\U000000ean", "4119103"], + ["PR", "Pinhais", "4119152"], + ["PR", "Pinhal de S\U000000e3o Bento", "4119251"], + ["PR", "Pinhal\U000000e3o", "4119202"], + ["PR", "Pinh\U000000e3o", "4119301"], + ["PR", "Pira\U000000ed do Sul", "4119400"], + ["PR", "Piraquara", "4119509"], + ["PR", "Pitanga", "4119608"], + ["PR", "Pitangueiras", "4119657"], + ["PR", "Planaltina do Paran\U000000e1", "4119707"], + ["PR", "Planalto", "4119806"], + ["PR", "Ponta Grossa", "4119905"], + ["PR", "Pontal do Paran\U000000e1", "4119954"], + ["PR", "Porecatu", "4120002"], + ["PR", "Porto Amazonas", "4120101"], + ["PR", "Porto Barreiro", "4120150"], + ["PR", "Porto Rico", "4120200"], + ["PR", "Porto Vit\U000000f3ria", "4120309"], + ["PR", "Prado Ferreira", "4120333"], + ["PR", "Pranchita", "4120358"], + ["PR", "Presidente Castelo Branco", "4120408"], + ["PR", "Primeiro de Maio", "4120507"], + ["PR", "Prudent\U000000f3polis", "4120606"], + ["PR", "Quarto Centen\U000000e1rio", "4120655"], + ["PR", "Quatigu\U000000e1", "4120705"], + ["PR", "Quatro Barras", "4120804"], + ["PR", "Quatro Pontes", "4120853"], + ["PR", "Quedas do Igua\U000000e7u", "4120903"], + ["PR", "Quer\U000000eancia do Norte", "4121000"], + ["PR", "Quinta do Sol", "4121109"], + ["PR", "Quitandinha", "4121208"], + ["PR", "Ramil\U000000e2ndia", "4121257"], + ["PR", "Rancho Alegre", "4121307"], + ["PR", "Rancho Alegre D'Oeste", "4121356"], + ["PR", "Realeza", "4121406"], + ["PR", "Rebou\U000000e7as", "4121505"], + ["PR", "Renascen\U000000e7a", "4121604"], + ["PR", "Reserva", "4121703"], + ["PR", "Reserva do Igua\U000000e7u", "4121752"], + ["PR", "Ribeir\U000000e3o Claro", "4121802"], + ["PR", "Ribeir\U000000e3o do Pinhal", "4121901"], + ["PR", "Rio Azul", "4122008"], + ["PR", "Rio Bom", "4122107"], + ["PR", "Rio Bonito do Igua\U000000e7u", "4122156"], + ["PR", "Rio Branco do Iva\U000000ed", "4122172"], + ["PR", "Rio Branco do Sul", "4122206"], + ["PR", "Rio Negro", "4122305"], + ["PR", "Rol\U000000e2ndia", "4122404"], + ["PR", "Roncador", "4122503"], + ["PR", "Rondon", "4122602"], + ["PR", "Ros\U000000e1rio do Iva\U000000ed", "4122651"], + ["PR", "Sab\U000000e1udia", "4122701"], + ["PR", "Salgado Filho", "4122800"], + ["PR", "Salto do Itarar\U000000e9", "4122909"], + ["PR", "Salto do Lontra", "4123006"], + ["PR", "Santa Am\U000000e9lia", "4123105"], + ["PR", "Santa Cec\U000000edlia do Pav\U000000e3o", "4123204"], + ["PR", "Santa Cruz de Monte Castelo", "4123303"], + ["PR", "Santa F\U000000e9", "4123402"], + ["PR", "Santa Helena", "4123501"], + ["PR", "Santa In\U000000eas", "4123600"], + ["PR", "Santa Isabel do Iva\U000000ed", "4123709"], + ["PR", "Santa Izabel do Oeste", "4123808"], + ["PR", "Santa L\U000000facia", "4123824"], + ["PR", "Santa Maria do Oeste", "4123857"], + ["PR", "Santa Mariana", "4123907"], + ["PR", "Santa M\U000000f4nica", "4123956"], + ["PR", "Santa Tereza do Oeste", "4124020"], + ["PR", "Santa Terezinha de Itaipu", "4124053"], + ["PR", "Santana do Itarar\U000000e9", "4124004"], + ["PR", "Santo Ant\U000000f4nio da Platina", "4124103"], + ["PR", "Santo Ant\U000000f4nio do Caiu\U000000e1", "4124202"], + ["PR", "Santo Ant\U000000f4nio do Para\U000000edso", "4124301"], + ["PR", "Santo Ant\U000000f4nio do Sudoeste", "4124400"], + ["PR", "Santo In\U000000e1cio", "4124509"], + ["PR", "S\U000000e3o Carlos do Iva\U000000ed", "4124608"], + ["PR", "S\U000000e3o Jer\U000000f4nimo da Serra", "4124707"], + ["PR", "S\U000000e3o Jo\U000000e3o", "4124806"], + ["PR", "S\U000000e3o Jo\U000000e3o do Caiu\U000000e1", "4124905"], + ["PR", "S\U000000e3o Jo\U000000e3o do Iva\U000000ed", "4125001"], + ["PR", "S\U000000e3o Jo\U000000e3o do Triunfo", "4125100"], + ["PR", "S\U000000e3o Jorge d'Oeste", "4125209"], + ["PR", "S\U000000e3o Jorge do Iva\U000000ed", "4125308"], + ["PR", "S\U000000e3o Jorge do Patroc\U000000ednio", "4125357"], + ["PR", "S\U000000e3o Jos\U000000e9 da Boa Vista", "4125407"], + ["PR", "S\U000000e3o Jos\U000000e9 das Palmeiras", "4125456"], + ["PR", "S\U000000e3o Jos\U000000e9 dos Pinhais", "4125506"], + ["PR", "S\U000000e3o Manoel do Paran\U000000e1", "4125555"], + ["PR", "S\U000000e3o Mateus do Sul", "4125605"], + ["PR", "S\U000000e3o Miguel do Igua\U000000e7u", "4125704"], + ["PR", "S\U000000e3o Pedro do Igua\U000000e7u", "4125753"], + ["PR", "S\U000000e3o Pedro do Iva\U000000ed", "4125803"], + ["PR", "S\U000000e3o Pedro do Paran\U000000e1", "4125902"], + ["PR", "S\U000000e3o Sebasti\U000000e3o da Amoreira", "4126009"], + ["PR", "S\U000000e3o Tom\U000000e9", "4126108"], + ["PR", "Sapopema", "4126207"], + ["PR", "Sarandi", "4126256"], + ["PR", "Saudade do Igua\U000000e7u", "4126272"], + ["PR", "Seng\U000000e9s", "4126306"], + ["PR", "Serran\U000000f3polis do Igua\U000000e7u", "4126355"], + ["PR", "Sertaneja", "4126405"], + ["PR", "Sertan\U000000f3polis", "4126504"], + ["PR", "Siqueira Campos", "4126603"], + ["PR", "Sulina", "4126652"], + ["PR", "Tamarana", "4126678"], + ["PR", "Tamboara", "4126702"], + ["PR", "Tapejara", "4126801"], + ["PR", "Tapira", "4126900"], + ["PR", "Teixeira Soares", "4127007"], + ["PR", "Tel\U000000eamaco Borba", "4127106"], + ["PR", "Terra Boa", "4127205"], + ["PR", "Terra Rica", "4127304"], + ["PR", "Terra Roxa", "4127403"], + ["PR", "Tibagi", "4127502"], + ["PR", "Tijucas do Sul", "4127601"], + ["PR", "Toledo", "4127700"], + ["PR", "Tomazina", "4127809"], + ["PR", "Tr\U000000eas Barras do Paran\U000000e1", "4127858"], + ["PR", "Tunas do Paran\U000000e1", "4127882"], + ["PR", "Tuneiras do Oeste", "4127908"], + ["PR", "Tup\U000000e3ssi", "4127957"], + ["PR", "Turvo", "4127965"], + ["PR", "Ubirat\U000000e3", "4128005"], + ["PR", "Umuarama", "4128104"], + ["PR", "Uni\U000000e3o da Vit\U000000f3ria", "4128203"], + ["PR", "Uniflor", "4128302"], + ["PR", "Ura\U000000ed", "4128401"], + ["PR", "Ventania", "4128534"], + ["PR", "Vera Cruz do Oeste", "4128559"], + ["PR", "Ver\U000000ea", "4128609"], + ["PR", "Virmond", "4128658"], + ["PR", "Vitorino", "4128708"], + ["PR", "Wenceslau Braz", "4128500"], + ["PR", "Xambr\U000000ea", "4128807"], + ["PE", "Abreu e Lima", "2600054"], + ["PE", "Afogados da Ingazeira", "2600104"], + ["PE", "Afr\U000000e2nio", "2600203"], + ["PE", "Agrestina", "2600302"], + ["PE", "\U000000c1gua Preta", "2600401"], + ["PE", "\U000000c1guas Belas", "2600500"], + ["PE", "Alagoinha", "2600609"], + ["PE", "Alian\U000000e7a", "2600708"], + ["PE", "Altinho", "2600807"], + ["PE", "Amaraji", "2600906"], + ["PE", "Angelim", "2601003"], + ["PE", "Ara\U000000e7oiaba", "2601052"], + ["PE", "Araripina", "2601102"], + ["PE", "Arcoverde", "2601201"], + ["PE", "Barra de Guabiraba", "2601300"], + ["PE", "Barreiros", "2601409"], + ["PE", "Bel\U000000e9m de Maria", "2601508"], + ["PE", "Bel\U000000e9m do S\U000000e3o Francisco", "2601607"], + ["PE", "Belo Jardim", "2601706"], + ["PE", "Bet\U000000e2nia", "2601805"], + ["PE", "Bezerros", "2601904"], + ["PE", "Bodoc\U000000f3", "2602001"], + ["PE", "Bom Conselho", "2602100"], + ["PE", "Bom Jardim", "2602209"], + ["PE", "Bonito", "2602308"], + ["PE", "Brej\U000000e3o", "2602407"], + ["PE", "Brejinho", "2602506"], + ["PE", "Brejo da Madre de Deus", "2602605"], + ["PE", "Buenos Aires", "2602704"], + ["PE", "Bu\U000000edque", "2602803"], + ["PE", "Cabo de Santo Agostinho", "2602902"], + ["PE", "Cabrob\U000000f3", "2603009"], + ["PE", "Cachoeirinha", "2603108"], + ["PE", "Caet\U000000e9s", "2603207"], + ["PE", "Cal\U000000e7ado", "2603306"], + ["PE", "Calumbi", "2603405"], + ["PE", "Camaragibe", "2603454"], + ["PE", "Camocim de S\U000000e3o F\U000000e9lix", "2603504"], + ["PE", "Camutanga", "2603603"], + ["PE", "Canhotinho", "2603702"], + ["PE", "Capoeiras", "2603801"], + ["PE", "Carna\U000000edba", "2603900"], + ["PE", "Carnaubeira da Penha", "2603926"], + ["PE", "Carpina", "2604007"], + ["PE", "Caruaru", "2604106"], + ["PE", "Casinhas", "2604155"], + ["PE", "Catende", "2604205"], + ["PE", "Cedro", "2604304"], + ["PE", "Ch\U000000e3 de Alegria", "2604403"], + ["PE", "Ch\U000000e3 Grande", "2604502"], + ["PE", "Condado", "2604601"], + ["PE", "Correntes", "2604700"], + ["PE", "Cort\U000000eas", "2604809"], + ["PE", "Cumaru", "2604908"], + ["PE", "Cupira", "2605004"], + ["PE", "Cust\U000000f3dia", "2605103"], + ["PE", "Dormentes", "2605152"], + ["PE", "Escada", "2605202"], + ["PE", "Exu", "2605301"], + ["PE", "Feira Nova", "2605400"], + ["PE", "Fernando de Noronha", "2605459"], + ["PE", "Ferreiros", "2605509"], + ["PE", "Flores", "2605608"], + ["PE", "Floresta", "2605707"], + ["PE", "Frei Miguelinho", "2605806"], + ["PE", "Gameleira", "2605905"], + ["PE", "Garanhuns", "2606002"], + ["PE", "Gl\U000000f3ria do Goit\U000000e1", "2606101"], + ["PE", "Goiana", "2606200"], + ["PE", "Granito", "2606309"], + ["PE", "Gravat\U000000e1", "2606408"], + ["PE", "Iati", "2606507"], + ["PE", "Ibimirim", "2606606"], + ["PE", "Ibirajuba", "2606705"], + ["PE", "Igarassu", "2606804"], + ["PE", "Iguaracy", "2606903"], + ["PE", "Ilha de Itamarac\U000000e1", "2607604"], + ["PE", "Inaj\U000000e1", "2607000"], + ["PE", "Ingazeira", "2607109"], + ["PE", "Ipojuca", "2607208"], + ["PE", "Ipubi", "2607307"], + ["PE", "Itacuruba", "2607406"], + ["PE", "Ita\U000000edba", "2607505"], + ["PE", "Itamb\U000000e9", "2607653"], + ["PE", "Itapetim", "2607703"], + ["PE", "Itapissuma", "2607752"], + ["PE", "Itaquitinga", "2607802"], + ["PE", "Jaboat\U000000e3o dos Guararapes", "2607901"], + ["PE", "Jaqueira", "2607950"], + ["PE", "Jata\U000000faba", "2608008"], + ["PE", "Jatob\U000000e1", "2608057"], + ["PE", "Jo\U000000e3o Alfredo", "2608107"], + ["PE", "Joaquim Nabuco", "2608206"], + ["PE", "Jucati", "2608255"], + ["PE", "Jupi", "2608305"], + ["PE", "Jurema", "2608404"], + ["PE", "Lagoa de Itaenga", "2608503"], + ["PE", "Lagoa do Carro", "2608453"], + ["PE", "Lagoa do Ouro", "2608602"], + ["PE", "Lagoa dos Gatos", "2608701"], + ["PE", "Lagoa Grande", "2608750"], + ["PE", "Lajedo", "2608800"], + ["PE", "Limoeiro", "2608909"], + ["PE", "Macaparana", "2609006"], + ["PE", "Machados", "2609105"], + ["PE", "Manari", "2609154"], + ["PE", "Maraial", "2609204"], + ["PE", "Mirandiba", "2609303"], + ["PE", "Moreil\U000000e2ndia", "2614303"], + ["PE", "Moreno", "2609402"], + ["PE", "Nazar\U000000e9 da Mata", "2609501"], + ["PE", "Olinda", "2609600"], + ["PE", "Orob\U000000f3", "2609709"], + ["PE", "Oroc\U000000f3", "2609808"], + ["PE", "Ouricuri", "2609907"], + ["PE", "Palmares", "2610004"], + ["PE", "Palmeirina", "2610103"], + ["PE", "Panelas", "2610202"], + ["PE", "Paranatama", "2610301"], + ["PE", "Parnamirim", "2610400"], + ["PE", "Passira", "2610509"], + ["PE", "Paudalho", "2610608"], + ["PE", "Paulista", "2610707"], + ["PE", "Pedra", "2610806"], + ["PE", "Pesqueira", "2610905"], + ["PE", "Petrol\U000000e2ndia", "2611002"], + ["PE", "Petrolina", "2611101"], + ["PE", "Po\U000000e7\U000000e3o", "2611200"], + ["PE", "Pombos", "2611309"], + ["PE", "Primavera", "2611408"], + ["PE", "Quipap\U000000e1", "2611507"], + ["PE", "Quixaba", "2611533"], + ["PE", "Recife", "2611606"], + ["PE", "Riacho das Almas", "2611705"], + ["PE", "Ribeir\U000000e3o", "2611804"], + ["PE", "Rio Formoso", "2611903"], + ["PE", "Sair\U000000e9", "2612000"], + ["PE", "Salgadinho", "2612109"], + ["PE", "Salgueiro", "2612208"], + ["PE", "Salo\U000000e1", "2612307"], + ["PE", "Sanhar\U000000f3", "2612406"], + ["PE", "Santa Cruz", "2612455"], + ["PE", "Santa Cruz da Baixa Verde", "2612471"], + ["PE", "Santa Cruz do Capibaribe", "2612505"], + ["PE", "Santa Filomena", "2612554"], + ["PE", "Santa Maria da Boa Vista", "2612604"], + ["PE", "Santa Maria do Cambuc\U000000e1", "2612703"], + ["PE", "Santa Terezinha", "2612802"], + ["PE", "S\U000000e3o Benedito do Sul", "2612901"], + ["PE", "S\U000000e3o Bento do Una", "2613008"], + ["PE", "S\U000000e3o Caitano", "2613107"], + ["PE", "S\U000000e3o Jo\U000000e3o", "2613206"], + ["PE", "S\U000000e3o Joaquim do Monte", "2613305"], + ["PE", "S\U000000e3o Jos\U000000e9 da Coroa Grande", "2613404"], + ["PE", "S\U000000e3o Jos\U000000e9 do Belmonte", "2613503"], + ["PE", "S\U000000e3o Jos\U000000e9 do Egito", "2613602"], + ["PE", "S\U000000e3o Louren\U000000e7o da Mata", "2613701"], + ["PE", "S\U000000e3o Vicente F\U000000e9rrer", "2613800"], + ["PE", "Serra Talhada", "2613909"], + ["PE", "Serrita", "2614006"], + ["PE", "Sert\U000000e2nia", "2614105"], + ["PE", "Sirinha\U000000e9m", "2614204"], + ["PE", "Solid\U000000e3o", "2614402"], + ["PE", "Surubim", "2614501"], + ["PE", "Tabira", "2614600"], + ["PE", "Tacaimb\U000000f3", "2614709"], + ["PE", "Tacaratu", "2614808"], + ["PE", "Tamandar\U000000e9", "2614857"], + ["PE", "Taquaritinga do Norte", "2615003"], + ["PE", "Terezinha", "2615102"], + ["PE", "Terra Nova", "2615201"], + ["PE", "Timba\U000000faba", "2615300"], + ["PE", "Toritama", "2615409"], + ["PE", "Tracunha\U000000e9m", "2615508"], + ["PE", "Trindade", "2615607"], + ["PE", "Triunfo", "2615706"], + ["PE", "Tupanatinga", "2615805"], + ["PE", "Tuparetama", "2615904"], + ["PE", "Venturosa", "2616001"], + ["PE", "Verdejante", "2616100"], + ["PE", "Vertente do L\U000000e9rio", "2616183"], + ["PE", "Vertentes", "2616209"], + ["PE", "Vic\U000000eancia", "2616308"], + ["PE", "Vit\U000000f3ria de Santo Ant\U000000e3o", "2616407"], + ["PE", "Xex\U000000e9u", "2616506"], + ["PI", "Acau\U000000e3", "2200053"], + ["PI", "Agricol\U000000e2ndia", "2200103"], + ["PI", "\U000000c1gua Branca", "2200202"], + ["PI", "Alagoinha do Piau\U000000ed", "2200251"], + ["PI", "Alegrete do Piau\U000000ed", "2200277"], + ["PI", "Alto Long\U000000e1", "2200301"], + ["PI", "Altos", "2200400"], + ["PI", "Alvorada do Gurgu\U000000e9ia", "2200459"], + ["PI", "Amarante", "2200509"], + ["PI", "Angical do Piau\U000000ed", "2200608"], + ["PI", "An\U000000edsio de Abreu", "2200707"], + ["PI", "Ant\U000000f4nio Almeida", "2200806"], + ["PI", "Aroazes", "2200905"], + ["PI", "Aroeiras do Itaim", "2200954"], + ["PI", "Arraial", "2201002"], + ["PI", "Assun\U000000e7\U000000e3o do Piau\U000000ed", "2201051"], + ["PI", "Avelino Lopes", "2201101"], + ["PI", "Baixa Grande do Ribeiro", "2201150"], + ["PI", "Barra D'Alc\U000000e2ntara", "2201176"], + ["PI", "Barras", "2201200"], + ["PI", "Barreiras do Piau\U000000ed", "2201309"], + ["PI", "Barro Duro", "2201408"], + ["PI", "Batalha", "2201507"], + ["PI", "Bela Vista do Piau\U000000ed", "2201556"], + ["PI", "Bel\U000000e9m do Piau\U000000ed", "2201572"], + ["PI", "Beneditinos", "2201606"], + ["PI", "Bertol\U000000ednia", "2201705"], + ["PI", "Bet\U000000e2nia do Piau\U000000ed", "2201739"], + ["PI", "Boa Hora", "2201770"], + ["PI", "Bocaina", "2201804"], + ["PI", "Bom Jesus", "2201903"], + ["PI", "Bom Princ\U000000edpio do Piau\U000000ed", "2201919"], + ["PI", "Bonfim do Piau\U000000ed", "2201929"], + ["PI", "Boqueir\U000000e3o do Piau\U000000ed", "2201945"], + ["PI", "Brasileira", "2201960"], + ["PI", "Brejo do Piau\U000000ed", "2201988"], + ["PI", "Buriti dos Lopes", "2202000"], + ["PI", "Buriti dos Montes", "2202026"], + ["PI", "Cabeceiras do Piau\U000000ed", "2202059"], + ["PI", "Cajazeiras do Piau\U000000ed", "2202075"], + ["PI", "Cajueiro da Praia", "2202083"], + ["PI", "Caldeir\U000000e3o Grande do Piau\U000000ed", "2202091"], + ["PI", "Campinas do Piau\U000000ed", "2202109"], + ["PI", "Campo Alegre do Fidalgo", "2202117"], + ["PI", "Campo Grande do Piau\U000000ed", "2202133"], + ["PI", "Campo Largo do Piau\U000000ed", "2202174"], + ["PI", "Campo Maior", "2202208"], + ["PI", "Canavieira", "2202251"], + ["PI", "Canto do Buriti", "2202307"], + ["PI", "Capit\U000000e3o de Campos", "2202406"], + ["PI", "Capit\U000000e3o Gerv\U000000e1sio Oliveira", "2202455"], + ["PI", "Caracol", "2202505"], + ["PI", "Cara\U000000fabas do Piau\U000000ed", "2202539"], + ["PI", "Caridade do Piau\U000000ed", "2202554"], + ["PI", "Castelo do Piau\U000000ed", "2202604"], + ["PI", "Caxing\U000000f3", "2202653"], + ["PI", "Cocal", "2202703"], + ["PI", "Cocal de Telha", "2202711"], + ["PI", "Cocal dos Alves", "2202729"], + ["PI", "Coivaras", "2202737"], + ["PI", "Col\U000000f4nia do Gurgu\U000000e9ia", "2202752"], + ["PI", "Col\U000000f4nia do Piau\U000000ed", "2202778"], + ["PI", "Concei\U000000e7\U000000e3o do Canind\U000000e9", "2202802"], + ["PI", "Coronel Jos\U000000e9 Dias", "2202851"], + ["PI", "Corrente", "2202901"], + ["PI", "Cristal\U000000e2ndia do Piau\U000000ed", "2203008"], + ["PI", "Cristino Castro", "2203107"], + ["PI", "Curimat\U000000e1", "2203206"], + ["PI", "Currais", "2203230"], + ["PI", "Curral Novo do Piau\U000000ed", "2203271"], + ["PI", "Curralinhos", "2203255"], + ["PI", "Demerval Lob\U000000e3o", "2203305"], + ["PI", "Dirceu Arcoverde", "2203354"], + ["PI", "Dom Expedito Lopes", "2203404"], + ["PI", "Dom Inoc\U000000eancio", "2203453"], + ["PI", "Domingos Mour\U000000e3o", "2203420"], + ["PI", "Elesb\U000000e3o Veloso", "2203503"], + ["PI", "Eliseu Martins", "2203602"], + ["PI", "Esperantina", "2203701"], + ["PI", "Fartura do Piau\U000000ed", "2203750"], + ["PI", "Flores do Piau\U000000ed", "2203800"], + ["PI", "Floresta do Piau\U000000ed", "2203859"], + ["PI", "Floriano", "2203909"], + ["PI", "Francin\U000000f3polis", "2204006"], + ["PI", "Francisco Ayres", "2204105"], + ["PI", "Francisco Macedo", "2204154"], + ["PI", "Francisco Santos", "2204204"], + ["PI", "Fronteiras", "2204303"], + ["PI", "Geminiano", "2204352"], + ["PI", "Gilbu\U000000e9s", "2204402"], + ["PI", "Guadalupe", "2204501"], + ["PI", "Guaribas", "2204550"], + ["PI", "Hugo Napole\U000000e3o", "2204600"], + ["PI", "Ilha Grande", "2204659"], + ["PI", "Inhuma", "2204709"], + ["PI", "Ipiranga do Piau\U000000ed", "2204808"], + ["PI", "Isa\U000000edas Coelho", "2204907"], + ["PI", "Itain\U000000f3polis", "2205003"], + ["PI", "Itaueira", "2205102"], + ["PI", "Jacobina do Piau\U000000ed", "2205151"], + ["PI", "Jaic\U000000f3s", "2205201"], + ["PI", "Jardim do Mulato", "2205250"], + ["PI", "Jatob\U000000e1 do Piau\U000000ed", "2205276"], + ["PI", "Jerumenha", "2205300"], + ["PI", "Jo\U000000e3o Costa", "2205359"], + ["PI", "Joaquim Pires", "2205409"], + ["PI", "Joca Marques", "2205458"], + ["PI", "Jos\U000000e9 de Freitas", "2205508"], + ["PI", "Juazeiro do Piau\U000000ed", "2205516"], + ["PI", "J\U000000falio Borges", "2205524"], + ["PI", "Jurema", "2205532"], + ["PI", "Lagoa Alegre", "2205557"], + ["PI", "Lagoa de S\U000000e3o Francisco", "2205573"], + ["PI", "Lagoa do Barro do Piau\U000000ed", "2205565"], + ["PI", "Lagoa do Piau\U000000ed", "2205581"], + ["PI", "Lagoa do S\U000000edtio", "2205599"], + ["PI", "Lagoinha do Piau\U000000ed", "2205540"], + ["PI", "Landri Sales", "2205607"], + ["PI", "Lu\U000000eds Correia", "2205706"], + ["PI", "Luzil\U000000e2ndia", "2205805"], + ["PI", "Madeiro", "2205854"], + ["PI", "Manoel Em\U000000eddio", "2205904"], + ["PI", "Marcol\U000000e2ndia", "2205953"], + ["PI", "Marcos Parente", "2206001"], + ["PI", "Massap\U000000ea do Piau\U000000ed", "2206050"], + ["PI", "Matias Ol\U000000edmpio", "2206100"], + ["PI", "Miguel Alves", "2206209"], + ["PI", "Miguel Le\U000000e3o", "2206308"], + ["PI", "Milton Brand\U000000e3o", "2206357"], + ["PI", "Monsenhor Gil", "2206407"], + ["PI", "Monsenhor Hip\U000000f3lito", "2206506"], + ["PI", "Monte Alegre do Piau\U000000ed", "2206605"], + ["PI", "Morro Cabe\U000000e7a no Tempo", "2206654"], + ["PI", "Morro do Chap\U000000e9u do Piau\U000000ed", "2206670"], + ["PI", "Murici dos Portelas", "2206696"], + ["PI", "Nazar\U000000e9 do Piau\U000000ed", "2206704"], + ["PI", "Naz\U000000e1ria", "2206720"], + ["PI", "Nossa Senhora de Nazar\U000000e9", "2206753"], + ["PI", "Nossa Senhora dos Rem\U000000e9dios", "2206803"], + ["PI", "Nova Santa Rita", "2207959"], + ["PI", "Novo Oriente do Piau\U000000ed", "2206902"], + ["PI", "Novo Santo Ant\U000000f4nio", "2206951"], + ["PI", "Oeiras", "2207009"], + ["PI", "Olho D'\U000000c1gua do Piau\U000000ed", "2207108"], + ["PI", "Padre Marcos", "2207207"], + ["PI", "Paes Landim", "2207306"], + ["PI", "Paje\U000000fa do Piau\U000000ed", "2207355"], + ["PI", "Palmeira do Piau\U000000ed", "2207405"], + ["PI", "Palmeirais", "2207504"], + ["PI", "Paquet\U000000e1", "2207553"], + ["PI", "Parnagu\U000000e1", "2207603"], + ["PI", "Parna\U000000edba", "2207702"], + ["PI", "Passagem Franca do Piau\U000000ed", "2207751"], + ["PI", "Patos do Piau\U000000ed", "2207777"], + ["PI", "Pau D'Arco do Piau\U000000ed", "2207793"], + ["PI", "Paulistana", "2207801"], + ["PI", "Pavussu", "2207850"], + ["PI", "Pedro II", "2207900"], + ["PI", "Pedro Laurentino", "2207934"], + ["PI", "Picos", "2208007"], + ["PI", "Pimenteiras", "2208106"], + ["PI", "Pio IX", "2208205"], + ["PI", "Piracuruca", "2208304"], + ["PI", "Piripiri", "2208403"], + ["PI", "Porto", "2208502"], + ["PI", "Porto Alegre do Piau\U000000ed", "2208551"], + ["PI", "Prata do Piau\U000000ed", "2208601"], + ["PI", "Queimada Nova", "2208650"], + ["PI", "Reden\U000000e7\U000000e3o do Gurgu\U000000e9ia", "2208700"], + ["PI", "Regenera\U000000e7\U000000e3o", "2208809"], + ["PI", "Riacho Frio", "2208858"], + ["PI", "Ribeira do Piau\U000000ed", "2208874"], + ["PI", "Ribeiro Gon\U000000e7alves", "2208908"], + ["PI", "Rio Grande do Piau\U000000ed", "2209005"], + ["PI", "Santa Cruz do Piau\U000000ed", "2209104"], + ["PI", "Santa Cruz dos Milagres", "2209153"], + ["PI", "Santa Filomena", "2209203"], + ["PI", "Santa Luz", "2209302"], + ["PI", "Santa Rosa do Piau\U000000ed", "2209377"], + ["PI", "Santana do Piau\U000000ed", "2209351"], + ["PI", "Santo Ant\U000000f4nio de Lisboa", "2209401"], + ["PI", "Santo Ant\U000000f4nio dos Milagres", "2209450"], + ["PI", "Santo In\U000000e1cio do Piau\U000000ed", "2209500"], + ["PI", "S\U000000e3o Braz do Piau\U000000ed", "2209559"], + ["PI", "S\U000000e3o F\U000000e9lix do Piau\U000000ed", "2209609"], + ["PI", "S\U000000e3o Francisco de Assis do Piau\U000000ed", "2209658"], + ["PI", "S\U000000e3o Francisco do Piau\U000000ed", "2209708"], + ["PI", "S\U000000e3o Gon\U000000e7alo do Gurgu\U000000e9ia", "2209757"], + ["PI", "S\U000000e3o Gon\U000000e7alo do Piau\U000000ed", "2209807"], + ["PI", "S\U000000e3o Jo\U000000e3o da Canabrava", "2209856"], + ["PI", "S\U000000e3o Jo\U000000e3o da Fronteira", "2209872"], + ["PI", "S\U000000e3o Jo\U000000e3o da Serra", "2209906"], + ["PI", "S\U000000e3o Jo\U000000e3o da Varjota", "2209955"], + ["PI", "S\U000000e3o Jo\U000000e3o do Arraial", "2209971"], + ["PI", "S\U000000e3o Jo\U000000e3o do Piau\U000000ed", "2210003"], + ["PI", "S\U000000e3o Jos\U000000e9 do Divino", "2210052"], + ["PI", "S\U000000e3o Jos\U000000e9 do Peixe", "2210102"], + ["PI", "S\U000000e3o Jos\U000000e9 do Piau\U000000ed", "2210201"], + ["PI", "S\U000000e3o Juli\U000000e3o", "2210300"], + ["PI", "S\U000000e3o Louren\U000000e7o do Piau\U000000ed", "2210359"], + ["PI", "S\U000000e3o Luis do Piau\U000000ed", "2210375"], + ["PI", "S\U000000e3o Miguel da Baixa Grande", "2210383"], + ["PI", "S\U000000e3o Miguel do Fidalgo", "2210391"], + ["PI", "S\U000000e3o Miguel do Tapuio", "2210409"], + ["PI", "S\U000000e3o Pedro do Piau\U000000ed", "2210508"], + ["PI", "S\U000000e3o Raimundo Nonato", "2210607"], + ["PI", "Sebasti\U000000e3o Barros", "2210623"], + ["PI", "Sebasti\U000000e3o Leal", "2210631"], + ["PI", "Sigefredo Pacheco", "2210656"], + ["PI", "Sim\U000000f5es", "2210706"], + ["PI", "Simpl\U000000edcio Mendes", "2210805"], + ["PI", "Socorro do Piau\U000000ed", "2210904"], + ["PI", "Sussuapara", "2210938"], + ["PI", "Tamboril do Piau\U000000ed", "2210953"], + ["PI", "Tanque do Piau\U000000ed", "2210979"], + ["PI", "Teresina", "2211001"], + ["PI", "Uni\U000000e3o", "2211100"], + ["PI", "Uru\U000000e7u\U000000ed", "2211209"], + ["PI", "Valen\U000000e7a do Piau\U000000ed", "2211308"], + ["PI", "V\U000000e1rzea Branca", "2211357"], + ["PI", "V\U000000e1rzea Grande", "2211407"], + ["PI", "Vera Mendes", "2211506"], + ["PI", "Vila Nova do Piau\U000000ed", "2211605"], + ["PI", "Wall Ferraz", "2211704"], + ["RJ", "Angra dos Reis", "3300100"], + ["RJ", "Aperib\U000000e9", "3300159"], + ["RJ", "Araruama", "3300209"], + ["RJ", "Areal", "3300225"], + ["RJ", "Arma\U000000e7\U000000e3o dos B\U000000fazios", "3300233"], + ["RJ", "Arraial do Cabo", "3300258"], + ["RJ", "Barra do Pira\U000000ed", "3300308"], + ["RJ", "Barra Mansa", "3300407"], + ["RJ", "Belford Roxo", "3300456"], + ["RJ", "Bom Jardim", "3300506"], + ["RJ", "Bom Jesus do Itabapoana", "3300605"], + ["RJ", "Cabo Frio", "3300704"], + ["RJ", "Cachoeiras de Macacu", "3300803"], + ["RJ", "Cambuci", "3300902"], + ["RJ", "Campos dos Goytacazes", "3301009"], + ["RJ", "Cantagalo", "3301108"], + ["RJ", "Carapebus", "3300936"], + ["RJ", "Cardoso Moreira", "3301157"], + ["RJ", "Carmo", "3301207"], + ["RJ", "Casimiro de Abreu", "3301306"], + ["RJ", "Comendador Levy Gasparian", "3300951"], + ["RJ", "Concei\U000000e7\U000000e3o de Macabu", "3301405"], + ["RJ", "Cordeiro", "3301504"], + ["RJ", "Duas Barras", "3301603"], + ["RJ", "Duque de Caxias", "3301702"], + ["RJ", "Engenheiro Paulo de Frontin", "3301801"], + ["RJ", "Guapimirim", "3301850"], + ["RJ", "Iguaba Grande", "3301876"], + ["RJ", "Itabora\U000000ed", "3301900"], + ["RJ", "Itagua\U000000ed", "3302007"], + ["RJ", "Italva", "3302056"], + ["RJ", "Itaocara", "3302106"], + ["RJ", "Itaperuna", "3302205"], + ["RJ", "Itatiaia", "3302254"], + ["RJ", "Japeri", "3302270"], + ["RJ", "Laje do Muria\U000000e9", "3302304"], + ["RJ", "Maca\U000000e9", "3302403"], + ["RJ", "Macuco", "3302452"], + ["RJ", "Mag\U000000e9", "3302502"], + ["RJ", "Mangaratiba", "3302601"], + ["RJ", "Maric\U000000e1", "3302700"], + ["RJ", "Mendes", "3302809"], + ["RJ", "Mesquita", "3302858"], + ["RJ", "Miguel Pereira", "3302908"], + ["RJ", "Miracema", "3303005"], + ["RJ", "Natividade", "3303104"], + ["RJ", "Nil\U000000f3polis", "3303203"], + ["RJ", "Niter\U000000f3i", "3303302"], + ["RJ", "Nova Friburgo", "3303401"], + ["RJ", "Nova Igua\U000000e7u", "3303500"], + ["RJ", "Paracambi", "3303609"], + ["RJ", "Para\U000000edba do Sul", "3303708"], + ["RJ", "Paraty", "3303807"], + ["RJ", "Paty do Alferes", "3303856"], + ["RJ", "Petr\U000000f3polis", "3303906"], + ["RJ", "Pinheiral", "3303955"], + ["RJ", "Pira\U000000ed", "3304003"], + ["RJ", "Porci\U000000fancula", "3304102"], + ["RJ", "Porto Real", "3304110"], + ["RJ", "Quatis", "3304128"], + ["RJ", "Queimados", "3304144"], + ["RJ", "Quissam\U000000e3", "3304151"], + ["RJ", "Resende", "3304201"], + ["RJ", "Rio Bonito", "3304300"], + ["RJ", "Rio Claro", "3304409"], + ["RJ", "Rio das Flores", "3304508"], + ["RJ", "Rio das Ostras", "3304524"], + ["RJ", "Rio de Janeiro", "3304557"], + ["RJ", "Santa Maria Madalena", "3304607"], + ["RJ", "Santo Ant\U000000f4nio de P\U000000e1dua", "3304706"], + ["RJ", "S\U000000e3o Fid\U000000e9lis", "3304805"], + ["RJ", "S\U000000e3o Francisco de Itabapoana", "3304755"], + ["RJ", "S\U000000e3o Gon\U000000e7alo", "3304904"], + ["RJ", "S\U000000e3o Jo\U000000e3o da Barra", "3305000"], + ["RJ", "S\U000000e3o Jo\U000000e3o de Meriti", "3305109"], + ["RJ", "S\U000000e3o Jos\U000000e9 de Ub\U000000e1", "3305133"], + ["RJ", "S\U000000e3o Jos\U000000e9 do Vale do Rio Preto", "3305158"], + ["RJ", "S\U000000e3o Pedro da Aldeia", "3305208"], + ["RJ", "S\U000000e3o Sebasti\U000000e3o do Alto", "3305307"], + ["RJ", "Sapucaia", "3305406"], + ["RJ", "Saquarema", "3305505"], + ["RJ", "Serop\U000000e9dica", "3305554"], + ["RJ", "Silva Jardim", "3305604"], + ["RJ", "Sumidouro", "3305703"], + ["RJ", "Tangu\U000000e1", "3305752"], + ["RJ", "Teres\U000000f3polis", "3305802"], + ["RJ", "Trajano de Moraes", "3305901"], + ["RJ", "Tr\U000000eas Rios", "3306008"], + ["RJ", "Valen\U000000e7a", "3306107"], + ["RJ", "Varre-Sai", "3306156"], + ["RJ", "Vassouras", "3306206"], + ["RJ", "Volta Redonda", "3306305"], + ["RN", "Acari", "2400109"], + ["RN", "Afonso Bezerra", "2400307"], + ["RN", "\U000000c1gua Nova", "2400406"], + ["RN", "Alexandria", "2400505"], + ["RN", "Almino Afonso", "2400604"], + ["RN", "Alto do Rodrigues", "2400703"], + ["RN", "Angicos", "2400802"], + ["RN", "Ant\U000000f4nio Martins", "2400901"], + ["RN", "Apodi", "2401008"], + ["RN", "Areia Branca", "2401107"], + ["RN", "Arez", "2401206"], + ["RN", "Ass\U000000fa", "2400208"], + ["RN", "Ba\U000000eda Formosa", "2401404"], + ["RN", "Bara\U000000fana", "2401453"], + ["RN", "Barcelona", "2401503"], + ["RN", "Bento Fernandes", "2401602"], + ["RN", "Bod\U000000f3", "2401651"], + ["RN", "Bom Jesus", "2401701"], + ["RN", "Brejinho", "2401800"], + ["RN", "Cai\U000000e7ara do Norte", "2401859"], + ["RN", "Cai\U000000e7ara do Rio do Vento", "2401909"], + ["RN", "Caic\U000000f3", "2402006"], + ["RN", "Campo Grande", "2401305"], + ["RN", "Campo Redondo", "2402105"], + ["RN", "Canguaretama", "2402204"], + ["RN", "Cara\U000000fabas", "2402303"], + ["RN", "Carna\U000000faba dos Dantas", "2402402"], + ["RN", "Carnaubais", "2402501"], + ["RN", "Cear\U000000e1-Mirim", "2402600"], + ["RN", "Cerro Cor\U000000e1", "2402709"], + ["RN", "Coronel Ezequiel", "2402808"], + ["RN", "Coronel Jo\U000000e3o Pessoa", "2402907"], + ["RN", "Cruzeta", "2403004"], + ["RN", "Currais Novos", "2403103"], + ["RN", "Doutor Severiano", "2403202"], + ["RN", "Encanto", "2403301"], + ["RN", "Equador", "2403400"], + ["RN", "Esp\U000000edrito Santo", "2403509"], + ["RN", "Extremoz", "2403608"], + ["RN", "Felipe Guerra", "2403707"], + ["RN", "Fernando Pedroza", "2403756"], + ["RN", "Flor\U000000e2nia", "2403806"], + ["RN", "Francisco Dantas", "2403905"], + ["RN", "Frutuoso Gomes", "2404002"], + ["RN", "Galinhos", "2404101"], + ["RN", "Goianinha", "2404200"], + ["RN", "Governador Dix-Sept Rosado", "2404309"], + ["RN", "Grossos", "2404408"], + ["RN", "Guamar\U000000e9", "2404507"], + ["RN", "Ielmo Marinho", "2404606"], + ["RN", "Ipangua\U000000e7u", "2404705"], + ["RN", "Ipueira", "2404804"], + ["RN", "Itaj\U000000e1", "2404853"], + ["RN", "Ita\U000000fa", "2404903"], + ["RN", "Ja\U000000e7an\U000000e3", "2405009"], + ["RN", "Janda\U000000edra", "2405108"], + ["RN", "Jandu\U000000eds", "2405207"], + ["RN", "Janu\U000000e1rio Cicco", "2405306"], + ["RN", "Japi", "2405405"], + ["RN", "Jardim de Angicos", "2405504"], + ["RN", "Jardim de Piranhas", "2405603"], + ["RN", "Jardim do Serid\U000000f3", "2405702"], + ["RN", "Jo\U000000e3o C\U000000e2mara", "2405801"], + ["RN", "Jo\U000000e3o Dias", "2405900"], + ["RN", "Jos\U000000e9 da Penha", "2406007"], + ["RN", "Jucurutu", "2406106"], + ["RN", "Jundi\U000000e1", "2406155"], + ["RN", "Lagoa d'Anta", "2406205"], + ["RN", "Lagoa de Pedras", "2406304"], + ["RN", "Lagoa de Velhos", "2406403"], + ["RN", "Lagoa Nova", "2406502"], + ["RN", "Lagoa Salgada", "2406601"], + ["RN", "Lajes", "2406700"], + ["RN", "Lajes Pintadas", "2406809"], + ["RN", "Lucr\U000000e9cia", "2406908"], + ["RN", "Lu\U000000eds Gomes", "2407005"], + ["RN", "Maca\U000000edba", "2407104"], + ["RN", "Macau", "2407203"], + ["RN", "Major Sales", "2407252"], + ["RN", "Marcelino Vieira", "2407302"], + ["RN", "Martins", "2407401"], + ["RN", "Maxaranguape", "2407500"], + ["RN", "Messias Targino", "2407609"], + ["RN", "Montanhas", "2407708"], + ["RN", "Monte Alegre", "2407807"], + ["RN", "Monte das Gameleiras", "2407906"], + ["RN", "Mossor\U000000f3", "2408003"], + ["RN", "Natal", "2408102"], + ["RN", "N\U000000edsia Floresta", "2408201"], + ["RN", "Nova Cruz", "2408300"], + ["RN", "Olho d'\U000000c1gua do Borges", "2408409"], + ["RN", "Ouro Branco", "2408508"], + ["RN", "Paran\U000000e1", "2408607"], + ["RN", "Para\U000000fa", "2408706"], + ["RN", "Parazinho", "2408805"], + ["RN", "Parelhas", "2408904"], + ["RN", "Parnamirim", "2403251"], + ["RN", "Passa e Fica", "2409100"], + ["RN", "Passagem", "2409209"], + ["RN", "Patu", "2409308"], + ["RN", "Pau dos Ferros", "2409407"], + ["RN", "Pedra Grande", "2409506"], + ["RN", "Pedra Preta", "2409605"], + ["RN", "Pedro Avelino", "2409704"], + ["RN", "Pedro Velho", "2409803"], + ["RN", "Pend\U000000eancias", "2409902"], + ["RN", "Pil\U000000f5es", "2410009"], + ["RN", "Po\U000000e7o Branco", "2410108"], + ["RN", "Portalegre", "2410207"], + ["RN", "Porto do Mangue", "2410256"], + ["RN", "Pureza", "2410405"], + ["RN", "Rafael Fernandes", "2410504"], + ["RN", "Rafael Godeiro", "2410603"], + ["RN", "Riacho da Cruz", "2410702"], + ["RN", "Riacho de Santana", "2410801"], + ["RN", "Riachuelo", "2410900"], + ["RN", "Rio do Fogo", "2408953"], + ["RN", "Rodolfo Fernandes", "2411007"], + ["RN", "Ruy Barbosa", "2411106"], + ["RN", "Santa Cruz", "2411205"], + ["RN", "Santa Maria", "2409332"], + ["RN", "Santana do Matos", "2411403"], + ["RN", "Santana do Serid\U000000f3", "2411429"], + ["RN", "Santo Ant\U000000f4nio", "2411502"], + ["RN", "S\U000000e3o Bento do Norte", "2411601"], + ["RN", "S\U000000e3o Bento do Trair\U000000ed", "2411700"], + ["RN", "S\U000000e3o Fernando", "2411809"], + ["RN", "S\U000000e3o Francisco do Oeste", "2411908"], + ["RN", "S\U000000e3o Gon\U000000e7alo do Amarante", "2412005"], + ["RN", "S\U000000e3o Jo\U000000e3o do Sabugi", "2412104"], + ["RN", "S\U000000e3o Jos\U000000e9 de Mipibu", "2412203"], + ["RN", "S\U000000e3o Jos\U000000e9 do Campestre", "2412302"], + ["RN", "S\U000000e3o Jos\U000000e9 do Serid\U000000f3", "2412401"], + ["RN", "S\U000000e3o Miguel", "2412500"], + ["RN", "S\U000000e3o Miguel do Gostoso", "2412559"], + ["RN", "S\U000000e3o Paulo do Potengi", "2412609"], + ["RN", "S\U000000e3o Pedro", "2412708"], + ["RN", "S\U000000e3o Rafael", "2412807"], + ["RN", "S\U000000e3o Tom\U000000e9", "2412906"], + ["RN", "S\U000000e3o Vicente", "2413003"], + ["RN", "Senador El\U000000f3i de Souza", "2413102"], + ["RN", "Senador Georgino Avelino", "2413201"], + ["RN", "Serra Caiada", "2410306"], + ["RN", "Serra de S\U000000e3o Bento", "2413300"], + ["RN", "Serra do Mel", "2413359"], + ["RN", "Serra Negra do Norte", "2413409"], + ["RN", "Serrinha", "2413508"], + ["RN", "Serrinha dos Pintos", "2413557"], + ["RN", "Severiano Melo", "2413607"], + ["RN", "S\U000000edtio Novo", "2413706"], + ["RN", "Taboleiro Grande", "2413805"], + ["RN", "Taipu", "2413904"], + ["RN", "Tangar\U000000e1", "2414001"], + ["RN", "Tenente Ananias", "2414100"], + ["RN", "Tenente Laurentino Cruz", "2414159"], + ["RN", "Tibau", "2411056"], + ["RN", "Tibau do Sul", "2414209"], + ["RN", "Timba\U000000faba dos Batistas", "2414308"], + ["RN", "Touros", "2414407"], + ["RN", "Triunfo Potiguar", "2414456"], + ["RN", "Umarizal", "2414506"], + ["RN", "Upanema", "2414605"], + ["RN", "V\U000000e1rzea", "2414704"], + ["RN", "Venha-Ver", "2414753"], + ["RN", "Vera Cruz", "2414803"], + ["RN", "Vi\U000000e7osa", "2414902"], + ["RN", "Vila Flor", "2415008"], + ["RS", "Acegu\U000000e1", "4300034"], + ["RS", "\U000000c1gua Santa", "4300059"], + ["RS", "Agudo", "4300109"], + ["RS", "Ajuricaba", "4300208"], + ["RS", "Alecrim", "4300307"], + ["RS", "Alegrete", "4300406"], + ["RS", "Alegria", "4300455"], + ["RS", "Almirante Tamandar\U000000e9 do Sul", "4300471"], + ["RS", "Alpestre", "4300505"], + ["RS", "Alto Alegre", "4300554"], + ["RS", "Alto Feliz", "4300570"], + ["RS", "Alvorada", "4300604"], + ["RS", "Amaral Ferrador", "4300638"], + ["RS", "Ametista do Sul", "4300646"], + ["RS", "Andr\U000000e9 da Rocha", "4300661"], + ["RS", "Anta Gorda", "4300703"], + ["RS", "Ant\U000000f4nio Prado", "4300802"], + ["RS", "Arambar\U000000e9", "4300851"], + ["RS", "Araric\U000000e1", "4300877"], + ["RS", "Aratiba", "4300901"], + ["RS", "Arroio do Meio", "4301008"], + ["RS", "Arroio do Padre", "4301073"], + ["RS", "Arroio do Sal", "4301057"], + ["RS", "Arroio do Tigre", "4301206"], + ["RS", "Arroio dos Ratos", "4301107"], + ["RS", "Arroio Grande", "4301305"], + ["RS", "Arvorezinha", "4301404"], + ["RS", "Augusto Pestana", "4301503"], + ["RS", "\U000000c1urea", "4301552"], + ["RS", "Bag\U000000e9", "4301602"], + ["RS", "Balne\U000000e1rio Pinhal", "4301636"], + ["RS", "Bar\U000000e3o", "4301651"], + ["RS", "Bar\U000000e3o de Cotegipe", "4301701"], + ["RS", "Bar\U000000e3o do Triunfo", "4301750"], + ["RS", "Barra do Guarita", "4301859"], + ["RS", "Barra do Quara\U000000ed", "4301875"], + ["RS", "Barra do Ribeiro", "4301909"], + ["RS", "Barra do Rio Azul", "4301925"], + ["RS", "Barra Funda", "4301958"], + ["RS", "Barrac\U000000e3o", "4301800"], + ["RS", "Barros Cassal", "4302006"], + ["RS", "Benjamin Constant do Sul", "4302055"], + ["RS", "Bento Gon\U000000e7alves", "4302105"], + ["RS", "Boa Vista das Miss\U000000f5es", "4302154"], + ["RS", "Boa Vista do Buric\U000000e1", "4302204"], + ["RS", "Boa Vista do Cadeado", "4302220"], + ["RS", "Boa Vista do Incra", "4302238"], + ["RS", "Boa Vista do Sul", "4302253"], + ["RS", "Bom Jesus", "4302303"], + ["RS", "Bom Princ\U000000edpio", "4302352"], + ["RS", "Bom Progresso", "4302378"], + ["RS", "Bom Retiro do Sul", "4302402"], + ["RS", "Boqueir\U000000e3o do Le\U000000e3o", "4302451"], + ["RS", "Bossoroca", "4302501"], + ["RS", "Bozano", "4302584"], + ["RS", "Braga", "4302600"], + ["RS", "Brochier", "4302659"], + ["RS", "Buti\U000000e1", "4302709"], + ["RS", "Ca\U000000e7apava do Sul", "4302808"], + ["RS", "Cacequi", "4302907"], + ["RS", "Cachoeira do Sul", "4303004"], + ["RS", "Cachoeirinha", "4303103"], + ["RS", "Cacique Doble", "4303202"], + ["RS", "Caibat\U000000e9", "4303301"], + ["RS", "Cai\U000000e7ara", "4303400"], + ["RS", "Camaqu\U000000e3", "4303509"], + ["RS", "Camargo", "4303558"], + ["RS", "Cambar\U000000e1 do Sul", "4303608"], + ["RS", "Campestre da Serra", "4303673"], + ["RS", "Campina das Miss\U000000f5es", "4303707"], + ["RS", "Campinas do Sul", "4303806"], + ["RS", "Campo Bom", "4303905"], + ["RS", "Campo Novo", "4304002"], + ["RS", "Campos Borges", "4304101"], + ["RS", "Candel\U000000e1ria", "4304200"], + ["RS", "C\U000000e2ndido God\U000000f3i", "4304309"], + ["RS", "Candiota", "4304358"], + ["RS", "Canela", "4304408"], + ["RS", "Cangu\U000000e7u", "4304507"], + ["RS", "Canoas", "4304606"], + ["RS", "Canudos do Vale", "4304614"], + ["RS", "Cap\U000000e3o Bonito do Sul", "4304622"], + ["RS", "Cap\U000000e3o da Canoa", "4304630"], + ["RS", "Cap\U000000e3o do Cip\U000000f3", "4304655"], + ["RS", "Cap\U000000e3o do Le\U000000e3o", "4304663"], + ["RS", "Capela de Santana", "4304689"], + ["RS", "Capit\U000000e3o", "4304697"], + ["RS", "Capivari do Sul", "4304671"], + ["RS", "Cara\U000000e1", "4304713"], + ["RS", "Carazinho", "4304705"], + ["RS", "Carlos Barbosa", "4304804"], + ["RS", "Carlos Gomes", "4304853"], + ["RS", "Casca", "4304903"], + ["RS", "Caseiros", "4304952"], + ["RS", "Catu\U000000edpe", "4305009"], + ["RS", "Caxias do Sul", "4305108"], + ["RS", "Centen\U000000e1rio", "4305116"], + ["RS", "Cerrito", "4305124"], + ["RS", "Cerro Branco", "4305132"], + ["RS", "Cerro Grande", "4305157"], + ["RS", "Cerro Grande do Sul", "4305173"], + ["RS", "Cerro Largo", "4305207"], + ["RS", "Chapada", "4305306"], + ["RS", "Charqueadas", "4305355"], + ["RS", "Charrua", "4305371"], + ["RS", "Chiapetta", "4305405"], + ["RS", "Chu\U000000ed", "4305439"], + ["RS", "Chuvisca", "4305447"], + ["RS", "Cidreira", "4305454"], + ["RS", "Cir\U000000edaco", "4305504"], + ["RS", "Colinas", "4305587"], + ["RS", "Colorado", "4305603"], + ["RS", "Condor", "4305702"], + ["RS", "Constantina", "4305801"], + ["RS", "Coqueiro Baixo", "4305835"], + ["RS", "Coqueiros do Sul", "4305850"], + ["RS", "Coronel Barros", "4305871"], + ["RS", "Coronel Bicaco", "4305900"], + ["RS", "Coronel Pilar", "4305934"], + ["RS", "Cotipor\U000000e3", "4305959"], + ["RS", "Coxilha", "4305975"], + ["RS", "Crissiumal", "4306007"], + ["RS", "Cristal", "4306056"], + ["RS", "Cristal do Sul", "4306072"], + ["RS", "Cruz Alta", "4306106"], + ["RS", "Cruzaltense", "4306130"], + ["RS", "Cruzeiro do Sul", "4306205"], + ["RS", "David Canabarro", "4306304"], + ["RS", "Derrubadas", "4306320"], + ["RS", "Dezesseis de Novembro", "4306353"], + ["RS", "Dilermando de Aguiar", "4306379"], + ["RS", "Dois Irm\U000000e3os", "4306403"], + ["RS", "Dois Irm\U000000e3os das Miss\U000000f5es", "4306429"], + ["RS", "Dois Lajeados", "4306452"], + ["RS", "Dom Feliciano", "4306502"], + ["RS", "Dom Pedrito", "4306601"], + ["RS", "Dom Pedro de Alc\U000000e2ntara", "4306551"], + ["RS", "Dona Francisca", "4306700"], + ["RS", "Doutor Maur\U000000edcio Cardoso", "4306734"], + ["RS", "Doutor Ricardo", "4306759"], + ["RS", "Eldorado do Sul", "4306767"], + ["RS", "Encantado", "4306809"], + ["RS", "Encruzilhada do Sul", "4306908"], + ["RS", "Engenho Velho", "4306924"], + ["RS", "Entre Rios do Sul", "4306957"], + ["RS", "Entre-Iju\U000000eds", "4306932"], + ["RS", "Erebango", "4306973"], + ["RS", "Erechim", "4307005"], + ["RS", "Ernestina", "4307054"], + ["RS", "Erval Grande", "4307203"], + ["RS", "Erval Seco", "4307302"], + ["RS", "Esmeralda", "4307401"], + ["RS", "Esperan\U000000e7a do Sul", "4307450"], + ["RS", "Espumoso", "4307500"], + ["RS", "Esta\U000000e7\U000000e3o", "4307559"], + ["RS", "Est\U000000e2ncia Velha", "4307609"], + ["RS", "Esteio", "4307708"], + ["RS", "Estrela", "4307807"], + ["RS", "Estrela Velha", "4307815"], + ["RS", "Eug\U000000eanio de Castro", "4307831"], + ["RS", "Fagundes Varela", "4307864"], + ["RS", "Farroupilha", "4307906"], + ["RS", "Faxinal do Soturno", "4308003"], + ["RS", "Faxinalzinho", "4308052"], + ["RS", "Fazenda Vilanova", "4308078"], + ["RS", "Feliz", "4308102"], + ["RS", "Flores da Cunha", "4308201"], + ["RS", "Floriano Peixoto", "4308250"], + ["RS", "Fontoura Xavier", "4308300"], + ["RS", "Formigueiro", "4308409"], + ["RS", "Forquetinha", "4308433"], + ["RS", "Fortaleza dos Valos", "4308458"], + ["RS", "Frederico Westphalen", "4308508"], + ["RS", "Garibaldi", "4308607"], + ["RS", "Garruchos", "4308656"], + ["RS", "Gaurama", "4308706"], + ["RS", "General C\U000000e2mara", "4308805"], + ["RS", "Gentil", "4308854"], + ["RS", "Get\U000000falio Vargas", "4308904"], + ["RS", "Giru\U000000e1", "4309001"], + ["RS", "Glorinha", "4309050"], + ["RS", "Gramado", "4309100"], + ["RS", "Gramado dos Loureiros", "4309126"], + ["RS", "Gramado Xavier", "4309159"], + ["RS", "Gravata\U000000ed", "4309209"], + ["RS", "Guabiju", "4309258"], + ["RS", "Gua\U000000edba", "4309308"], + ["RS", "Guapor\U000000e9", "4309407"], + ["RS", "Guarani das Miss\U000000f5es", "4309506"], + ["RS", "Harmonia", "4309555"], + ["RS", "Herval", "4307104"], + ["RS", "Herveiras", "4309571"], + ["RS", "Horizontina", "4309605"], + ["RS", "Hulha Negra", "4309654"], + ["RS", "Humait\U000000e1", "4309704"], + ["RS", "Ibarama", "4309753"], + ["RS", "Ibia\U000000e7\U000000e1", "4309803"], + ["RS", "Ibiraiaras", "4309902"], + ["RS", "Ibirapuit\U000000e3", "4309951"], + ["RS", "Ibirub\U000000e1", "4310009"], + ["RS", "Igrejinha", "4310108"], + ["RS", "Iju\U000000ed", "4310207"], + ["RS", "Il\U000000f3polis", "4310306"], + ["RS", "Imb\U000000e9", "4310330"], + ["RS", "Imigrante", "4310363"], + ["RS", "Independ\U000000eancia", "4310405"], + ["RS", "Inhacor\U000000e1", "4310413"], + ["RS", "Ip\U000000ea", "4310439"], + ["RS", "Ipiranga do Sul", "4310462"], + ["RS", "Ira\U000000ed", "4310504"], + ["RS", "Itaara", "4310538"], + ["RS", "Itacurubi", "4310553"], + ["RS", "Itapuca", "4310579"], + ["RS", "Itaqui", "4310603"], + ["RS", "Itati", "4310652"], + ["RS", "Itatiba do Sul", "4310702"], + ["RS", "Ivor\U000000e1", "4310751"], + ["RS", "Ivoti", "4310801"], + ["RS", "Jaboticaba", "4310850"], + ["RS", "Jacuizinho", "4310876"], + ["RS", "Jacutinga", "4310900"], + ["RS", "Jaguar\U000000e3o", "4311007"], + ["RS", "Jaguari", "4311106"], + ["RS", "Jaquirana", "4311122"], + ["RS", "Jari", "4311130"], + ["RS", "J\U000000f3ia", "4311155"], + ["RS", "J\U000000falio de Castilhos", "4311205"], + ["RS", "Lagoa Bonita do Sul", "4311239"], + ["RS", "Lagoa dos Tr\U000000eas Cantos", "4311270"], + ["RS", "Lagoa Vermelha", "4311304"], + ["RS", "Lago\U000000e3o", "4311254"], + ["RS", "Lajeado", "4311403"], + ["RS", "Lajeado do Bugre", "4311429"], + ["RS", "Lavras do Sul", "4311502"], + ["RS", "Liberato Salzano", "4311601"], + ["RS", "Lindolfo Collor", "4311627"], + ["RS", "Linha Nova", "4311643"], + ["RS", "Ma\U000000e7ambar\U000000e1", "4311718"], + ["RS", "Machadinho", "4311700"], + ["RS", "Mampituba", "4311734"], + ["RS", "Manoel Viana", "4311759"], + ["RS", "Maquin\U000000e9", "4311775"], + ["RS", "Marat\U000000e1", "4311791"], + ["RS", "Marau", "4311809"], + ["RS", "Marcelino Ramos", "4311908"], + ["RS", "Mariana Pimentel", "4311981"], + ["RS", "Mariano Moro", "4312005"], + ["RS", "Marques de Souza", "4312054"], + ["RS", "Mata", "4312104"], + ["RS", "Mato Castelhano", "4312138"], + ["RS", "Mato Leit\U000000e3o", "4312153"], + ["RS", "Mato Queimado", "4312179"], + ["RS", "Maximiliano de Almeida", "4312203"], + ["RS", "Minas do Le\U000000e3o", "4312252"], + ["RS", "Miragua\U000000ed", "4312302"], + ["RS", "Montauri", "4312351"], + ["RS", "Monte Alegre dos Campos", "4312377"], + ["RS", "Monte Belo do Sul", "4312385"], + ["RS", "Montenegro", "4312401"], + ["RS", "Morma\U000000e7o", "4312427"], + ["RS", "Morrinhos do Sul", "4312443"], + ["RS", "Morro Redondo", "4312450"], + ["RS", "Morro Reuter", "4312476"], + ["RS", "Mostardas", "4312500"], + ["RS", "Mu\U000000e7um", "4312609"], + ["RS", "Muitos Cap\U000000f5es", "4312617"], + ["RS", "Muliterno", "4312625"], + ["RS", "N\U000000e3o-Me-Toque", "4312658"], + ["RS", "Nicolau Vergueiro", "4312674"], + ["RS", "Nonoai", "4312708"], + ["RS", "Nova Alvorada", "4312757"], + ["RS", "Nova Ara\U000000e7\U000000e1", "4312807"], + ["RS", "Nova Bassano", "4312906"], + ["RS", "Nova Boa Vista", "4312955"], + ["RS", "Nova Br\U000000e9scia", "4313003"], + ["RS", "Nova Candel\U000000e1ria", "4313011"], + ["RS", "Nova Esperan\U000000e7a do Sul", "4313037"], + ["RS", "Nova Hartz", "4313060"], + ["RS", "Nova P\U000000e1dua", "4313086"], + ["RS", "Nova Palma", "4313102"], + ["RS", "Nova Petr\U000000f3polis", "4313201"], + ["RS", "Nova Prata", "4313300"], + ["RS", "Nova Ramada", "4313334"], + ["RS", "Nova Roma do Sul", "4313359"], + ["RS", "Nova Santa Rita", "4313375"], + ["RS", "Novo Barreiro", "4313490"], + ["RS", "Novo Cabrais", "4313391"], + ["RS", "Novo Hamburgo", "4313409"], + ["RS", "Novo Machado", "4313425"], + ["RS", "Novo Tiradentes", "4313441"], + ["RS", "Novo Xingu", "4313466"], + ["RS", "Os\U000000f3rio", "4313508"], + ["RS", "Paim Filho", "4313607"], + ["RS", "Palmares do Sul", "4313656"], + ["RS", "Palmeira das Miss\U000000f5es", "4313706"], + ["RS", "Palmitinho", "4313805"], + ["RS", "Panambi", "4313904"], + ["RS", "Pantano Grande", "4313953"], + ["RS", "Para\U000000ed", "4314001"], + ["RS", "Para\U000000edso do Sul", "4314027"], + ["RS", "Pareci Novo", "4314035"], + ["RS", "Parob\U000000e9", "4314050"], + ["RS", "Passa Sete", "4314068"], + ["RS", "Passo do Sobrado", "4314076"], + ["RS", "Passo Fundo", "4314100"], + ["RS", "Paulo Bento", "4314134"], + ["RS", "Paverama", "4314159"], + ["RS", "Pedras Altas", "4314175"], + ["RS", "Pedro Os\U000000f3rio", "4314209"], + ["RS", "Peju\U000000e7ara", "4314308"], + ["RS", "Pelotas", "4314407"], + ["RS", "Picada Caf\U000000e9", "4314423"], + ["RS", "Pinhal", "4314456"], + ["RS", "Pinhal da Serra", "4314464"], + ["RS", "Pinhal Grande", "4314472"], + ["RS", "Pinheirinho do Vale", "4314498"], + ["RS", "Pinheiro Machado", "4314506"], + ["RS", "Pinto Bandeira", "4314548"], + ["RS", "Pirap\U000000f3", "4314555"], + ["RS", "Piratini", "4314605"], + ["RS", "Planalto", "4314704"], + ["RS", "Po\U000000e7o das Antas", "4314753"], + ["RS", "Pont\U000000e3o", "4314779"], + ["RS", "Ponte Preta", "4314787"], + ["RS", "Port\U000000e3o", "4314803"], + ["RS", "Porto Alegre", "4314902"], + ["RS", "Porto Lucena", "4315008"], + ["RS", "Porto Mau\U000000e1", "4315057"], + ["RS", "Porto Vera Cruz", "4315073"], + ["RS", "Porto Xavier", "4315107"], + ["RS", "Pouso Novo", "4315131"], + ["RS", "Presidente Lucena", "4315149"], + ["RS", "Progresso", "4315156"], + ["RS", "Prot\U000000e1sio Alves", "4315172"], + ["RS", "Putinga", "4315206"], + ["RS", "Quara\U000000ed", "4315305"], + ["RS", "Quatro Irm\U000000e3os", "4315313"], + ["RS", "Quevedos", "4315321"], + ["RS", "Quinze de Novembro", "4315354"], + ["RS", "Redentora", "4315404"], + ["RS", "Relvado", "4315453"], + ["RS", "Restinga S\U000000eaca", "4315503"], + ["RS", "Rio dos \U000000cdndios", "4315552"], + ["RS", "Rio Grande", "4315602"], + ["RS", "Rio Pardo", "4315701"], + ["RS", "Riozinho", "4315750"], + ["RS", "Roca Sales", "4315800"], + ["RS", "Rodeio Bonito", "4315909"], + ["RS", "Rolador", "4315958"], + ["RS", "Rolante", "4316006"], + ["RS", "Ronda Alta", "4316105"], + ["RS", "Rondinha", "4316204"], + ["RS", "Roque Gonzales", "4316303"], + ["RS", "Ros\U000000e1rio do Sul", "4316402"], + ["RS", "Sagrada Fam\U000000edlia", "4316428"], + ["RS", "Saldanha Marinho", "4316436"], + ["RS", "Salto do Jacu\U000000ed", "4316451"], + ["RS", "Salvador das Miss\U000000f5es", "4316477"], + ["RS", "Salvador do Sul", "4316501"], + ["RS", "Sananduva", "4316600"], + ["RS", "Sant'Ana do Livramento", "4317103"], + ["RS", "Santa B\U000000e1rbara do Sul", "4316709"], + ["RS", "Santa Cec\U000000edlia do Sul", "4316733"], + ["RS", "Santa Clara do Sul", "4316758"], + ["RS", "Santa Cruz do Sul", "4316808"], + ["RS", "Santa Margarida do Sul", "4316972"], + ["RS", "Santa Maria", "4316907"], + ["RS", "Santa Maria do Herval", "4316956"], + ["RS", "Santa Rosa", "4317202"], + ["RS", "Santa Tereza", "4317251"], + ["RS", "Santa Vit\U000000f3ria do Palmar", "4317301"], + ["RS", "Santana da Boa Vista", "4317004"], + ["RS", "Santiago", "4317400"], + ["RS", "Santo \U000000c2ngelo", "4317509"], + ["RS", "Santo Ant\U000000f4nio da Patrulha", "4317608"], + ["RS", "Santo Ant\U000000f4nio das Miss\U000000f5es", "4317707"], + ["RS", "Santo Ant\U000000f4nio do Palma", "4317558"], + ["RS", "Santo Ant\U000000f4nio do Planalto", "4317756"], + ["RS", "Santo Augusto", "4317806"], + ["RS", "Santo Cristo", "4317905"], + ["RS", "Santo Expedito do Sul", "4317954"], + ["RS", "S\U000000e3o Borja", "4318002"], + ["RS", "S\U000000e3o Domingos do Sul", "4318051"], + ["RS", "S\U000000e3o Francisco de Assis", "4318101"], + ["RS", "S\U000000e3o Francisco de Paula", "4318200"], + ["RS", "S\U000000e3o Gabriel", "4318309"], + ["RS", "S\U000000e3o Jer\U000000f4nimo", "4318408"], + ["RS", "S\U000000e3o Jo\U000000e3o da Urtiga", "4318424"], + ["RS", "S\U000000e3o Jo\U000000e3o do Pol\U000000easine", "4318432"], + ["RS", "S\U000000e3o Jorge", "4318440"], + ["RS", "S\U000000e3o Jos\U000000e9 das Miss\U000000f5es", "4318457"], + ["RS", "S\U000000e3o Jos\U000000e9 do Herval", "4318465"], + ["RS", "S\U000000e3o Jos\U000000e9 do Hort\U000000eancio", "4318481"], + ["RS", "S\U000000e3o Jos\U000000e9 do Inhacor\U000000e1", "4318499"], + ["RS", "S\U000000e3o Jos\U000000e9 do Norte", "4318507"], + ["RS", "S\U000000e3o Jos\U000000e9 do Ouro", "4318606"], + ["RS", "S\U000000e3o Jos\U000000e9 do Sul", "4318614"], + ["RS", "S\U000000e3o Jos\U000000e9 dos Ausentes", "4318622"], + ["RS", "S\U000000e3o Leopoldo", "4318705"], + ["RS", "S\U000000e3o Louren\U000000e7o do Sul", "4318804"], + ["RS", "S\U000000e3o Luiz Gonzaga", "4318903"], + ["RS", "S\U000000e3o Marcos", "4319000"], + ["RS", "S\U000000e3o Martinho", "4319109"], + ["RS", "S\U000000e3o Martinho da Serra", "4319125"], + ["RS", "S\U000000e3o Miguel das Miss\U000000f5es", "4319158"], + ["RS", "S\U000000e3o Nicolau", "4319208"], + ["RS", "S\U000000e3o Paulo das Miss\U000000f5es", "4319307"], + ["RS", "S\U000000e3o Pedro da Serra", "4319356"], + ["RS", "S\U000000e3o Pedro das Miss\U000000f5es", "4319364"], + ["RS", "S\U000000e3o Pedro do Buti\U000000e1", "4319372"], + ["RS", "S\U000000e3o Pedro do Sul", "4319406"], + ["RS", "S\U000000e3o Sebasti\U000000e3o do Ca\U000000ed", "4319505"], + ["RS", "S\U000000e3o Sep\U000000e9", "4319604"], + ["RS", "S\U000000e3o Valentim", "4319703"], + ["RS", "S\U000000e3o Valentim do Sul", "4319711"], + ["RS", "S\U000000e3o Val\U000000e9rio do Sul", "4319737"], + ["RS", "S\U000000e3o Vendelino", "4319752"], + ["RS", "S\U000000e3o Vicente do Sul", "4319802"], + ["RS", "Sapiranga", "4319901"], + ["RS", "Sapucaia do Sul", "4320008"], + ["RS", "Sarandi", "4320107"], + ["RS", "Seberi", "4320206"], + ["RS", "Sede Nova", "4320230"], + ["RS", "Segredo", "4320263"], + ["RS", "Selbach", "4320305"], + ["RS", "Senador Salgado Filho", "4320321"], + ["RS", "Sentinela do Sul", "4320354"], + ["RS", "Serafina Corr\U000000eaa", "4320404"], + ["RS", "S\U000000e9rio", "4320453"], + ["RS", "Sert\U000000e3o", "4320503"], + ["RS", "Sert\U000000e3o Santana", "4320552"], + ["RS", "Sete de Setembro", "4320578"], + ["RS", "Severiano de Almeida", "4320602"], + ["RS", "Silveira Martins", "4320651"], + ["RS", "Sinimbu", "4320677"], + ["RS", "Sobradinho", "4320701"], + ["RS", "Soledade", "4320800"], + ["RS", "Taba\U000000ed", "4320859"], + ["RS", "Tapejara", "4320909"], + ["RS", "Tapera", "4321006"], + ["RS", "Tapes", "4321105"], + ["RS", "Taquara", "4321204"], + ["RS", "Taquari", "4321303"], + ["RS", "Taquaru\U000000e7u do Sul", "4321329"], + ["RS", "Tavares", "4321352"], + ["RS", "Tenente Portela", "4321402"], + ["RS", "Terra de Areia", "4321436"], + ["RS", "Teut\U000000f4nia", "4321451"], + ["RS", "Tio Hugo", "4321469"], + ["RS", "Tiradentes do Sul", "4321477"], + ["RS", "Toropi", "4321493"], + ["RS", "Torres", "4321501"], + ["RS", "Tramanda\U000000ed", "4321600"], + ["RS", "Travesseiro", "4321626"], + ["RS", "Tr\U000000eas Arroios", "4321634"], + ["RS", "Tr\U000000eas Cachoeiras", "4321667"], + ["RS", "Tr\U000000eas Coroas", "4321709"], + ["RS", "Tr\U000000eas de Maio", "4321808"], + ["RS", "Tr\U000000eas Forquilhas", "4321832"], + ["RS", "Tr\U000000eas Palmeiras", "4321857"], + ["RS", "Tr\U000000eas Passos", "4321907"], + ["RS", "Trindade do Sul", "4321956"], + ["RS", "Triunfo", "4322004"], + ["RS", "Tucunduva", "4322103"], + ["RS", "Tunas", "4322152"], + ["RS", "Tupanci do Sul", "4322186"], + ["RS", "Tupanciret\U000000e3", "4322202"], + ["RS", "Tupandi", "4322251"], + ["RS", "Tuparendi", "4322301"], + ["RS", "Turu\U000000e7u", "4322327"], + ["RS", "Ubiretama", "4322343"], + ["RS", "Uni\U000000e3o da Serra", "4322350"], + ["RS", "Unistalda", "4322376"], + ["RS", "Uruguaiana", "4322400"], + ["RS", "Vacaria", "4322509"], + ["RS", "Vale do Sol", "4322533"], + ["RS", "Vale Real", "4322541"], + ["RS", "Vale Verde", "4322525"], + ["RS", "Vanini", "4322558"], + ["RS", "Ven\U000000e2ncio Aires", "4322608"], + ["RS", "Vera Cruz", "4322707"], + ["RS", "Veran\U000000f3polis", "4322806"], + ["RS", "Vespasiano Corr\U000000eaa", "4322855"], + ["RS", "Viadutos", "4322905"], + ["RS", "Viam\U000000e3o", "4323002"], + ["RS", "Vicente Dutra", "4323101"], + ["RS", "Victor Graeff", "4323200"], + ["RS", "Vila Flores", "4323309"], + ["RS", "Vila L\U000000e2ngaro", "4323358"], + ["RS", "Vila Maria", "4323408"], + ["RS", "Vila Nova do Sul", "4323457"], + ["RS", "Vista Alegre", "4323507"], + ["RS", "Vista Alegre do Prata", "4323606"], + ["RS", "Vista Ga\U000000facha", "4323705"], + ["RS", "Vit\U000000f3ria das Miss\U000000f5es", "4323754"], + ["RS", "Westf\U000000e1lia", "4323770"], + ["RS", "Xangri-l\U000000e1", "4323804"], + ["RO", "Alta Floresta D'Oeste", "1100015"], + ["RO", "Alto Alegre dos Parecis", "1100379"], + ["RO", "Alto Para\U000000edso", "1100403"], + ["RO", "Alvorada D'Oeste", "1100346"], + ["RO", "Ariquemes", "1100023"], + ["RO", "Buritis", "1100452"], + ["RO", "Cabixi", "1100031"], + ["RO", "Cacaul\U000000e2ndia", "1100601"], + ["RO", "Cacoal", "1100049"], + ["RO", "Campo Novo de Rond\U000000f4nia", "1100700"], + ["RO", "Candeias do Jamari", "1100809"], + ["RO", "Castanheiras", "1100908"], + ["RO", "Cerejeiras", "1100056"], + ["RO", "Chupinguaia", "1100924"], + ["RO", "Colorado do Oeste", "1100064"], + ["RO", "Corumbiara", "1100072"], + ["RO", "Costa Marques", "1100080"], + ["RO", "Cujubim", "1100940"], + ["RO", "Espig\U000000e3o D'Oeste", "1100098"], + ["RO", "Governador Jorge Teixeira", "1101005"], + ["RO", "Guajar\U000000e1-Mirim", "1100106"], + ["RO", "Itapu\U000000e3 do Oeste", "1101104"], + ["RO", "Jaru", "1100114"], + ["RO", "Ji-Paran\U000000e1", "1100122"], + ["RO", "Machadinho D'Oeste", "1100130"], + ["RO", "Ministro Andreazza", "1101203"], + ["RO", "Mirante da Serra", "1101302"], + ["RO", "Monte Negro", "1101401"], + ["RO", "Nova Brasil\U000000e2ndia D'Oeste", "1100148"], + ["RO", "Nova Mamor\U000000e9", "1100338"], + ["RO", "Nova Uni\U000000e3o", "1101435"], + ["RO", "Novo Horizonte do Oeste", "1100502"], + ["RO", "Ouro Preto do Oeste", "1100155"], + ["RO", "Parecis", "1101450"], + ["RO", "Pimenta Bueno", "1100189"], + ["RO", "Pimenteiras do Oeste", "1101468"], + ["RO", "Porto Velho", "1100205"], + ["RO", "Presidente M\U000000e9dici", "1100254"], + ["RO", "Primavera de Rond\U000000f4nia", "1101476"], + ["RO", "Rio Crespo", "1100262"], + ["RO", "Rolim de Moura", "1100288"], + ["RO", "Santa Luzia D'Oeste", "1100296"], + ["RO", "S\U000000e3o Felipe D'Oeste", "1101484"], + ["RO", "S\U000000e3o Francisco do Guapor\U000000e9", "1101492"], + ["RO", "S\U000000e3o Miguel do Guapor\U000000e9", "1100320"], + ["RO", "Seringueiras", "1101500"], + ["RO", "Teixeir\U000000f3polis", "1101559"], + ["RO", "Theobroma", "1101609"], + ["RO", "Urup\U000000e1", "1101708"], + ["RO", "Vale do Anari", "1101757"], + ["RO", "Vale do Para\U000000edso", "1101807"], + ["RO", "Vilhena", "1100304"], + ["RR", "Alto Alegre", "1400050"], + ["RR", "Amajari", "1400027"], + ["RR", "Boa Vista", "1400100"], + ["RR", "Bonfim", "1400159"], + ["RR", "Cant\U000000e1", "1400175"], + ["RR", "Caracara\U000000ed", "1400209"], + ["RR", "Caroebe", "1400233"], + ["RR", "Iracema", "1400282"], + ["RR", "Mucaja\U000000ed", "1400308"], + ["RR", "Normandia", "1400407"], + ["RR", "Pacaraima", "1400456"], + ["RR", "Rorain\U000000f3polis", "1400472"], + ["RR", "S\U000000e3o Jo\U000000e3o da Baliza", "1400506"], + ["RR", "S\U000000e3o Luiz do Anau\U000000e1", "1400605"], + ["RR", "Uiramut\U000000e3", "1400704"], + ["SC", "Abdon Batista", "4200051"], + ["SC", "Abelardo Luz", "4200101"], + ["SC", "Agrol\U000000e2ndia", "4200200"], + ["SC", "Agron\U000000f4mica", "4200309"], + ["SC", "\U000000c1gua Doce", "4200408"], + ["SC", "\U000000c1guas de Chapec\U000000f3", "4200507"], + ["SC", "\U000000c1guas Frias", "4200556"], + ["SC", "\U000000c1guas Mornas", "4200606"], + ["SC", "Alfredo Wagner", "4200705"], + ["SC", "Alto Bela Vista", "4200754"], + ["SC", "Anchieta", "4200804"], + ["SC", "Angelina", "4200903"], + ["SC", "Anita Garibaldi", "4201000"], + ["SC", "Anit\U000000e1polis", "4201109"], + ["SC", "Ant\U000000f4nio Carlos", "4201208"], + ["SC", "Api\U000000fana", "4201257"], + ["SC", "Arabut\U000000e3", "4201273"], + ["SC", "Araquari", "4201307"], + ["SC", "Ararangu\U000000e1", "4201406"], + ["SC", "Armaz\U000000e9m", "4201505"], + ["SC", "Arroio Trinta", "4201604"], + ["SC", "Arvoredo", "4201653"], + ["SC", "Ascurra", "4201703"], + ["SC", "Atalanta", "4201802"], + ["SC", "Aurora", "4201901"], + ["SC", "Balne\U000000e1rio Arroio do Silva", "4201950"], + ["SC", "Balne\U000000e1rio Barra do Sul", "4202057"], + ["SC", "Balne\U000000e1rio Cambori\U000000fa", "4202008"], + ["SC", "Balne\U000000e1rio Gaivota", "4202073"], + ["SC", "Balne\U000000e1rio Pi\U000000e7arras", "4212809"], + ["SC", "Balne\U000000e1rio Rinc\U000000e3o", "4220000"], + ["SC", "Bandeirante", "4202081"], + ["SC", "Barra Bonita", "4202099"], + ["SC", "Barra Velha", "4202107"], + ["SC", "Bela Vista do Toldo", "4202131"], + ["SC", "Belmonte", "4202156"], + ["SC", "Benedito Novo", "4202206"], + ["SC", "Bigua\U000000e7u", "4202305"], + ["SC", "Blumenau", "4202404"], + ["SC", "Bocaina do Sul", "4202438"], + ["SC", "Bom Jardim da Serra", "4202503"], + ["SC", "Bom Jesus", "4202537"], + ["SC", "Bom Jesus do Oeste", "4202578"], + ["SC", "Bom Retiro", "4202602"], + ["SC", "Bombinhas", "4202453"], + ["SC", "Botuver\U000000e1", "4202701"], + ["SC", "Bra\U000000e7o do Norte", "4202800"], + ["SC", "Bra\U000000e7o do Trombudo", "4202859"], + ["SC", "Brun\U000000f3polis", "4202875"], + ["SC", "Brusque", "4202909"], + ["SC", "Ca\U000000e7ador", "4203006"], + ["SC", "Caibi", "4203105"], + ["SC", "Calmon", "4203154"], + ["SC", "Cambori\U000000fa", "4203204"], + ["SC", "Campo Alegre", "4203303"], + ["SC", "Campo Belo do Sul", "4203402"], + ["SC", "Campo Er\U000000ea", "4203501"], + ["SC", "Campos Novos", "4203600"], + ["SC", "Canelinha", "4203709"], + ["SC", "Canoinhas", "4203808"], + ["SC", "Cap\U000000e3o Alto", "4203253"], + ["SC", "Capinzal", "4203907"], + ["SC", "Capivari de Baixo", "4203956"], + ["SC", "Catanduvas", "4204004"], + ["SC", "Caxambu do Sul", "4204103"], + ["SC", "Celso Ramos", "4204152"], + ["SC", "Cerro Negro", "4204178"], + ["SC", "Chapad\U000000e3o do Lageado", "4204194"], + ["SC", "Chapec\U000000f3", "4204202"], + ["SC", "Cocal do Sul", "4204251"], + ["SC", "Conc\U000000f3rdia", "4204301"], + ["SC", "Cordilheira Alta", "4204350"], + ["SC", "Coronel Freitas", "4204400"], + ["SC", "Coronel Martins", "4204459"], + ["SC", "Correia Pinto", "4204558"], + ["SC", "Corup\U000000e1", "4204509"], + ["SC", "Crici\U000000fama", "4204608"], + ["SC", "Cunha Por\U000000e3", "4204707"], + ["SC", "Cunhata\U000000ed", "4204756"], + ["SC", "Curitibanos", "4204806"], + ["SC", "Descanso", "4204905"], + ["SC", "Dion\U000000edsio Cerqueira", "4205001"], + ["SC", "Dona Emma", "4205100"], + ["SC", "Doutor Pedrinho", "4205159"], + ["SC", "Entre Rios", "4205175"], + ["SC", "Ermo", "4205191"], + ["SC", "Erval Velho", "4205209"], + ["SC", "Faxinal dos Guedes", "4205308"], + ["SC", "Flor do Sert\U000000e3o", "4205357"], + ["SC", "Florian\U000000f3polis", "4205407"], + ["SC", "Formosa do Sul", "4205431"], + ["SC", "Forquilhinha", "4205456"], + ["SC", "Fraiburgo", "4205506"], + ["SC", "Frei Rog\U000000e9rio", "4205555"], + ["SC", "Galv\U000000e3o", "4205605"], + ["SC", "Garopaba", "4205704"], + ["SC", "Garuva", "4205803"], + ["SC", "Gaspar", "4205902"], + ["SC", "Governador Celso Ramos", "4206009"], + ["SC", "Gr\U000000e3o-Par\U000000e1", "4206108"], + ["SC", "Gravatal", "4206207"], + ["SC", "Guabiruba", "4206306"], + ["SC", "Guaraciaba", "4206405"], + ["SC", "Guaramirim", "4206504"], + ["SC", "Guaruj\U000000e1 do Sul", "4206603"], + ["SC", "Guatamb\U000000fa", "4206652"], + ["SC", "Herval d'Oeste", "4206702"], + ["SC", "Ibiam", "4206751"], + ["SC", "Ibicar\U000000e9", "4206801"], + ["SC", "Ibirama", "4206900"], + ["SC", "I\U000000e7ara", "4207007"], + ["SC", "Ilhota", "4207106"], + ["SC", "Imaru\U000000ed", "4207205"], + ["SC", "Imbituba", "4207304"], + ["SC", "Imbuia", "4207403"], + ["SC", "Indaial", "4207502"], + ["SC", "Iomer\U000000ea", "4207577"], + ["SC", "Ipira", "4207601"], + ["SC", "Ipor\U000000e3 do Oeste", "4207650"], + ["SC", "Ipua\U000000e7u", "4207684"], + ["SC", "Ipumirim", "4207700"], + ["SC", "Iraceminha", "4207759"], + ["SC", "Irani", "4207809"], + ["SC", "Irati", "4207858"], + ["SC", "Irine\U000000f3polis", "4207908"], + ["SC", "It\U000000e1", "4208005"], + ["SC", "Itai\U000000f3polis", "4208104"], + ["SC", "Itaja\U000000ed", "4208203"], + ["SC", "Itapema", "4208302"], + ["SC", "Itapiranga", "4208401"], + ["SC", "Itapo\U000000e1", "4208450"], + ["SC", "Ituporanga", "4208500"], + ["SC", "Jabor\U000000e1", "4208609"], + ["SC", "Jacinto Machado", "4208708"], + ["SC", "Jaguaruna", "4208807"], + ["SC", "Jaragu\U000000e1 do Sul", "4208906"], + ["SC", "Jardin\U000000f3polis", "4208955"], + ["SC", "Joa\U000000e7aba", "4209003"], + ["SC", "Joinville", "4209102"], + ["SC", "Jos\U000000e9 Boiteux", "4209151"], + ["SC", "Jupi\U000000e1", "4209177"], + ["SC", "Lacerd\U000000f3polis", "4209201"], + ["SC", "Lages", "4209300"], + ["SC", "Laguna", "4209409"], + ["SC", "Lajeado Grande", "4209458"], + ["SC", "Laurentino", "4209508"], + ["SC", "Lauro M\U000000fcller", "4209607"], + ["SC", "Lebon R\U000000e9gis", "4209706"], + ["SC", "Leoberto Leal", "4209805"], + ["SC", "Lind\U000000f3ia do Sul", "4209854"], + ["SC", "Lontras", "4209904"], + ["SC", "Luiz Alves", "4210001"], + ["SC", "Luzerna", "4210035"], + ["SC", "Macieira", "4210050"], + ["SC", "Mafra", "4210100"], + ["SC", "Major Gercino", "4210209"], + ["SC", "Major Vieira", "4210308"], + ["SC", "Maracaj\U000000e1", "4210407"], + ["SC", "Maravilha", "4210506"], + ["SC", "Marema", "4210555"], + ["SC", "Massaranduba", "4210605"], + ["SC", "Matos Costa", "4210704"], + ["SC", "Meleiro", "4210803"], + ["SC", "Mirim Doce", "4210852"], + ["SC", "Modelo", "4210902"], + ["SC", "Monda\U000000ed", "4211009"], + ["SC", "Monte Carlo", "4211058"], + ["SC", "Monte Castelo", "4211108"], + ["SC", "Morro da Fuma\U000000e7a", "4211207"], + ["SC", "Morro Grande", "4211256"], + ["SC", "Navegantes", "4211306"], + ["SC", "Nova Erechim", "4211405"], + ["SC", "Nova Itaberaba", "4211454"], + ["SC", "Nova Trento", "4211504"], + ["SC", "Nova Veneza", "4211603"], + ["SC", "Novo Horizonte", "4211652"], + ["SC", "Orleans", "4211702"], + ["SC", "Otac\U000000edlio Costa", "4211751"], + ["SC", "Ouro", "4211801"], + ["SC", "Ouro Verde", "4211850"], + ["SC", "Paial", "4211876"], + ["SC", "Painel", "4211892"], + ["SC", "Palho\U000000e7a", "4211900"], + ["SC", "Palma Sola", "4212007"], + ["SC", "Palmeira", "4212056"], + ["SC", "Palmitos", "4212106"], + ["SC", "Papanduva", "4212205"], + ["SC", "Para\U000000edso", "4212239"], + ["SC", "Passo de Torres", "4212254"], + ["SC", "Passos Maia", "4212270"], + ["SC", "Paulo Lopes", "4212304"], + ["SC", "Pedras Grandes", "4212403"], + ["SC", "Penha", "4212502"], + ["SC", "Peritiba", "4212601"], + ["SC", "Pescaria Brava", "4212650"], + ["SC", "Petrol\U000000e2ndia", "4212700"], + ["SC", "Pinhalzinho", "4212908"], + ["SC", "Pinheiro Preto", "4213005"], + ["SC", "Piratuba", "4213104"], + ["SC", "Planalto Alegre", "4213153"], + ["SC", "Pomerode", "4213203"], + ["SC", "Ponte Alta", "4213302"], + ["SC", "Ponte Alta do Norte", "4213351"], + ["SC", "Ponte Serrada", "4213401"], + ["SC", "Porto Belo", "4213500"], + ["SC", "Porto Uni\U000000e3o", "4213609"], + ["SC", "Pouso Redondo", "4213708"], + ["SC", "Praia Grande", "4213807"], + ["SC", "Presidente Castello Branco", "4213906"], + ["SC", "Presidente Get\U000000falio", "4214003"], + ["SC", "Presidente Nereu", "4214102"], + ["SC", "Princesa", "4214151"], + ["SC", "Quilombo", "4214201"], + ["SC", "Rancho Queimado", "4214300"], + ["SC", "Rio das Antas", "4214409"], + ["SC", "Rio do Campo", "4214508"], + ["SC", "Rio do Oeste", "4214607"], + ["SC", "Rio do Sul", "4214805"], + ["SC", "Rio dos Cedros", "4214706"], + ["SC", "Rio Fortuna", "4214904"], + ["SC", "Rio Negrinho", "4215000"], + ["SC", "Rio Rufino", "4215059"], + ["SC", "Riqueza", "4215075"], + ["SC", "Rodeio", "4215109"], + ["SC", "Romel\U000000e2ndia", "4215208"], + ["SC", "Salete", "4215307"], + ["SC", "Saltinho", "4215356"], + ["SC", "Salto Veloso", "4215406"], + ["SC", "Sang\U000000e3o", "4215455"], + ["SC", "Santa Cec\U000000edlia", "4215505"], + ["SC", "Santa Helena", "4215554"], + ["SC", "Santa Rosa de Lima", "4215604"], + ["SC", "Santa Rosa do Sul", "4215653"], + ["SC", "Santa Terezinha", "4215679"], + ["SC", "Santa Terezinha do Progresso", "4215687"], + ["SC", "Santiago do Sul", "4215695"], + ["SC", "Santo Amaro da Imperatriz", "4215703"], + ["SC", "S\U000000e3o Bento do Sul", "4215802"], + ["SC", "S\U000000e3o Bernardino", "4215752"], + ["SC", "S\U000000e3o Bonif\U000000e1cio", "4215901"], + ["SC", "S\U000000e3o Carlos", "4216008"], + ["SC", "S\U000000e3o Crist\U000000f3v\U000000e3o do Sul", "4216057"], + ["SC", "S\U000000e3o Domingos", "4216107"], + ["SC", "S\U000000e3o Francisco do Sul", "4216206"], + ["SC", "S\U000000e3o Jo\U000000e3o Batista", "4216305"], + ["SC", "S\U000000e3o Jo\U000000e3o do Itaperi\U000000fa", "4216354"], + ["SC", "S\U000000e3o Jo\U000000e3o do Oeste", "4216255"], + ["SC", "S\U000000e3o Jo\U000000e3o do Sul", "4216404"], + ["SC", "S\U000000e3o Joaquim", "4216503"], + ["SC", "S\U000000e3o Jos\U000000e9", "4216602"], + ["SC", "S\U000000e3o Jos\U000000e9 do Cedro", "4216701"], + ["SC", "S\U000000e3o Jos\U000000e9 do Cerrito", "4216800"], + ["SC", "S\U000000e3o Louren\U000000e7o do Oeste", "4216909"], + ["SC", "S\U000000e3o Ludgero", "4217006"], + ["SC", "S\U000000e3o Martinho", "4217105"], + ["SC", "S\U000000e3o Miguel da Boa Vista", "4217154"], + ["SC", "S\U000000e3o Miguel do Oeste", "4217204"], + ["SC", "S\U000000e3o Pedro de Alc\U000000e2ntara", "4217253"], + ["SC", "Saudades", "4217303"], + ["SC", "Schroeder", "4217402"], + ["SC", "Seara", "4217501"], + ["SC", "Serra Alta", "4217550"], + ["SC", "Sider\U000000f3polis", "4217600"], + ["SC", "Sombrio", "4217709"], + ["SC", "Sul Brasil", "4217758"], + ["SC", "Tai\U000000f3", "4217808"], + ["SC", "Tangar\U000000e1", "4217907"], + ["SC", "Tigrinhos", "4217956"], + ["SC", "Tijucas", "4218004"], + ["SC", "Timb\U000000e9 do Sul", "4218103"], + ["SC", "Timb\U000000f3", "4218202"], + ["SC", "Timb\U000000f3 Grande", "4218251"], + ["SC", "Tr\U000000eas Barras", "4218301"], + ["SC", "Treviso", "4218350"], + ["SC", "Treze de Maio", "4218400"], + ["SC", "Treze T\U000000edlias", "4218509"], + ["SC", "Trombudo Central", "4218608"], + ["SC", "Tubar\U000000e3o", "4218707"], + ["SC", "Tun\U000000e1polis", "4218756"], + ["SC", "Turvo", "4218806"], + ["SC", "Uni\U000000e3o do Oeste", "4218855"], + ["SC", "Urubici", "4218905"], + ["SC", "Urupema", "4218954"], + ["SC", "Urussanga", "4219002"], + ["SC", "Varge\U000000e3o", "4219101"], + ["SC", "Vargem", "4219150"], + ["SC", "Vargem Bonita", "4219176"], + ["SC", "Vidal Ramos", "4219200"], + ["SC", "Videira", "4219309"], + ["SC", "Vitor Meireles", "4219358"], + ["SC", "Witmarsum", "4219408"], + ["SC", "Xanxer\U000000ea", "4219507"], + ["SC", "Xavantina", "4219606"], + ["SC", "Xaxim", "4219705"], + ["SC", "Zort\U000000e9a", "4219853"], + ["SP", "Adamantina", "3500105"], + ["SP", "Adolfo", "3500204"], + ["SP", "Agua\U000000ed", "3500303"], + ["SP", "\U000000c1guas da Prata", "3500402"], + ["SP", "\U000000c1guas de Lind\U000000f3ia", "3500501"], + ["SP", "\U000000c1guas de Santa B\U000000e1rbara", "3500550"], + ["SP", "\U000000c1guas de S\U000000e3o Pedro", "3500600"], + ["SP", "Agudos", "3500709"], + ["SP", "Alambari", "3500758"], + ["SP", "Alfredo Marcondes", "3500808"], + ["SP", "Altair", "3500907"], + ["SP", "Altin\U000000f3polis", "3501004"], + ["SP", "Alto Alegre", "3501103"], + ["SP", "Alum\U000000ednio", "3501152"], + ["SP", "\U000000c1lvares Florence", "3501202"], + ["SP", "\U000000c1lvares Machado", "3501301"], + ["SP", "\U000000c1lvaro de Carvalho", "3501400"], + ["SP", "Alvinl\U000000e2ndia", "3501509"], + ["SP", "Americana", "3501608"], + ["SP", "Am\U000000e9rico Brasiliense", "3501707"], + ["SP", "Am\U000000e9rico de Campos", "3501806"], + ["SP", "Amparo", "3501905"], + ["SP", "Anal\U000000e2ndia", "3502002"], + ["SP", "Andradina", "3502101"], + ["SP", "Angatuba", "3502200"], + ["SP", "Anhembi", "3502309"], + ["SP", "Anhumas", "3502408"], + ["SP", "Aparecida", "3502507"], + ["SP", "Aparecida d'Oeste", "3502606"], + ["SP", "Apia\U000000ed", "3502705"], + ["SP", "Ara\U000000e7ariguama", "3502754"], + ["SP", "Ara\U000000e7atuba", "3502804"], + ["SP", "Ara\U000000e7oiaba da Serra", "3502903"], + ["SP", "Aramina", "3503000"], + ["SP", "Arandu", "3503109"], + ["SP", "Arape\U000000ed", "3503158"], + ["SP", "Araraquara", "3503208"], + ["SP", "Araras", "3503307"], + ["SP", "Arco-\U000000cdris", "3503356"], + ["SP", "Arealva", "3503406"], + ["SP", "Areias", "3503505"], + ["SP", "Arei\U000000f3polis", "3503604"], + ["SP", "Ariranha", "3503703"], + ["SP", "Artur Nogueira", "3503802"], + ["SP", "Aruj\U000000e1", "3503901"], + ["SP", "Asp\U000000e1sia", "3503950"], + ["SP", "Assis", "3504008"], + ["SP", "Atibaia", "3504107"], + ["SP", "Auriflama", "3504206"], + ["SP", "Ava\U000000ed", "3504305"], + ["SP", "Avanhandava", "3504404"], + ["SP", "Avar\U000000e9", "3504503"], + ["SP", "Bady Bassitt", "3504602"], + ["SP", "Balbinos", "3504701"], + ["SP", "B\U000000e1lsamo", "3504800"], + ["SP", "Bananal", "3504909"], + ["SP", "Bar\U000000e3o de Antonina", "3505005"], + ["SP", "Barbosa", "3505104"], + ["SP", "Bariri", "3505203"], + ["SP", "Barra Bonita", "3505302"], + ["SP", "Barra do Chap\U000000e9u", "3505351"], + ["SP", "Barra do Turvo", "3505401"], + ["SP", "Barretos", "3505500"], + ["SP", "Barrinha", "3505609"], + ["SP", "Barueri", "3505708"], + ["SP", "Bastos", "3505807"], + ["SP", "Batatais", "3505906"], + ["SP", "Bauru", "3506003"], + ["SP", "Bebedouro", "3506102"], + ["SP", "Bento de Abreu", "3506201"], + ["SP", "Bernardino de Campos", "3506300"], + ["SP", "Bertioga", "3506359"], + ["SP", "Bilac", "3506409"], + ["SP", "Birigui", "3506508"], + ["SP", "Biritiba Mirim", "3506607"], + ["SP", "Boa Esperan\U000000e7a do Sul", "3506706"], + ["SP", "Bocaina", "3506805"], + ["SP", "Bofete", "3506904"], + ["SP", "Boituva", "3507001"], + ["SP", "Bom Jesus dos Perd\U000000f5es", "3507100"], + ["SP", "Bom Sucesso de Itarar\U000000e9", "3507159"], + ["SP", "Bor\U000000e1", "3507209"], + ["SP", "Borac\U000000e9ia", "3507308"], + ["SP", "Borborema", "3507407"], + ["SP", "Borebi", "3507456"], + ["SP", "Botucatu", "3507506"], + ["SP", "Bragan\U000000e7a Paulista", "3507605"], + ["SP", "Bra\U000000fana", "3507704"], + ["SP", "Brejo Alegre", "3507753"], + ["SP", "Brodowski", "3507803"], + ["SP", "Brotas", "3507902"], + ["SP", "Buri", "3508009"], + ["SP", "Buritama", "3508108"], + ["SP", "Buritizal", "3508207"], + ["SP", "Cabr\U000000e1lia Paulista", "3508306"], + ["SP", "Cabre\U000000fava", "3508405"], + ["SP", "Ca\U000000e7apava", "3508504"], + ["SP", "Cachoeira Paulista", "3508603"], + ["SP", "Caconde", "3508702"], + ["SP", "Cafel\U000000e2ndia", "3508801"], + ["SP", "Caiabu", "3508900"], + ["SP", "Caieiras", "3509007"], + ["SP", "Caiu\U000000e1", "3509106"], + ["SP", "Cajamar", "3509205"], + ["SP", "Cajati", "3509254"], + ["SP", "Cajobi", "3509304"], + ["SP", "Cajuru", "3509403"], + ["SP", "Campina do Monte Alegre", "3509452"], + ["SP", "Campinas", "3509502"], + ["SP", "Campo Limpo Paulista", "3509601"], + ["SP", "Campos do Jord\U000000e3o", "3509700"], + ["SP", "Campos Novos Paulista", "3509809"], + ["SP", "Canan\U000000e9ia", "3509908"], + ["SP", "Canas", "3509957"], + ["SP", "C\U000000e2ndido Mota", "3510005"], + ["SP", "C\U000000e2ndido Rodrigues", "3510104"], + ["SP", "Canitar", "3510153"], + ["SP", "Cap\U000000e3o Bonito", "3510203"], + ["SP", "Capela do Alto", "3510302"], + ["SP", "Capivari", "3510401"], + ["SP", "Caraguatatuba", "3510500"], + ["SP", "Carapicu\U000000edba", "3510609"], + ["SP", "Cardoso", "3510708"], + ["SP", "Casa Branca", "3510807"], + ["SP", "C\U000000e1ssia dos Coqueiros", "3510906"], + ["SP", "Castilho", "3511003"], + ["SP", "Catanduva", "3511102"], + ["SP", "Catigu\U000000e1", "3511201"], + ["SP", "Cedral", "3511300"], + ["SP", "Cerqueira C\U000000e9sar", "3511409"], + ["SP", "Cerquilho", "3511508"], + ["SP", "Ces\U000000e1rio Lange", "3511607"], + ["SP", "Charqueada", "3511706"], + ["SP", "Chavantes", "3557204"], + ["SP", "Clementina", "3511904"], + ["SP", "Colina", "3512001"], + ["SP", "Col\U000000f4mbia", "3512100"], + ["SP", "Conchal", "3512209"], + ["SP", "Conchas", "3512308"], + ["SP", "Cordeir\U000000f3polis", "3512407"], + ["SP", "Coroados", "3512506"], + ["SP", "Coronel Macedo", "3512605"], + ["SP", "Corumbata\U000000ed", "3512704"], + ["SP", "Cosm\U000000f3polis", "3512803"], + ["SP", "Cosmorama", "3512902"], + ["SP", "Cotia", "3513009"], + ["SP", "Cravinhos", "3513108"], + ["SP", "Cristais Paulista", "3513207"], + ["SP", "Cruz\U000000e1lia", "3513306"], + ["SP", "Cruzeiro", "3513405"], + ["SP", "Cubat\U000000e3o", "3513504"], + ["SP", "Cunha", "3513603"], + ["SP", "Descalvado", "3513702"], + ["SP", "Diadema", "3513801"], + ["SP", "Dirce Reis", "3513850"], + ["SP", "Divinol\U000000e2ndia", "3513900"], + ["SP", "Dobrada", "3514007"], + ["SP", "Dois C\U000000f3rregos", "3514106"], + ["SP", "Dolcin\U000000f3polis", "3514205"], + ["SP", "Dourado", "3514304"], + ["SP", "Dracena", "3514403"], + ["SP", "Duartina", "3514502"], + ["SP", "Dumont", "3514601"], + ["SP", "Echapor\U000000e3", "3514700"], + ["SP", "Eldorado", "3514809"], + ["SP", "Elias Fausto", "3514908"], + ["SP", "Elisi\U000000e1rio", "3514924"], + ["SP", "Emba\U000000faba", "3514957"], + ["SP", "Embu das Artes", "3515004"], + ["SP", "Embu-Gua\U000000e7u", "3515103"], + ["SP", "Emilian\U000000f3polis", "3515129"], + ["SP", "Engenheiro Coelho", "3515152"], + ["SP", "Esp\U000000edrito Santo do Pinhal", "3515186"], + ["SP", "Esp\U000000edrito Santo do Turvo", "3515194"], + ["SP", "Estiva Gerbi", "3557303"], + ["SP", "Estrela d'Oeste", "3515202"], + ["SP", "Estrela do Norte", "3515301"], + ["SP", "Euclides da Cunha Paulista", "3515350"], + ["SP", "Fartura", "3515400"], + ["SP", "Fernando Prestes", "3515608"], + ["SP", "Fernand\U000000f3polis", "3515509"], + ["SP", "Fern\U000000e3o", "3515657"], + ["SP", "Ferraz de Vasconcelos", "3515707"], + ["SP", "Flora Rica", "3515806"], + ["SP", "Floreal", "3515905"], + ["SP", "Fl\U000000f3rida Paulista", "3516002"], + ["SP", "Flor\U000000ednea", "3516101"], + ["SP", "Franca", "3516200"], + ["SP", "Francisco Morato", "3516309"], + ["SP", "Franco da Rocha", "3516408"], + ["SP", "Gabriel Monteiro", "3516507"], + ["SP", "G\U000000e1lia", "3516606"], + ["SP", "Gar\U000000e7a", "3516705"], + ["SP", "Gast\U000000e3o Vidigal", "3516804"], + ["SP", "Gavi\U000000e3o Peixoto", "3516853"], + ["SP", "General Salgado", "3516903"], + ["SP", "Getulina", "3517000"], + ["SP", "Glic\U000000e9rio", "3517109"], + ["SP", "Guai\U000000e7ara", "3517208"], + ["SP", "Guaimb\U000000ea", "3517307"], + ["SP", "Gua\U000000edra", "3517406"], + ["SP", "Guapia\U000000e7u", "3517505"], + ["SP", "Guapiara", "3517604"], + ["SP", "Guar\U000000e1", "3517703"], + ["SP", "Guara\U000000e7a\U000000ed", "3517802"], + ["SP", "Guaraci", "3517901"], + ["SP", "Guarani d'Oeste", "3518008"], + ["SP", "Guarant\U000000e3", "3518107"], + ["SP", "Guararapes", "3518206"], + ["SP", "Guararema", "3518305"], + ["SP", "Guaratinguet\U000000e1", "3518404"], + ["SP", "Guare\U000000ed", "3518503"], + ["SP", "Guariba", "3518602"], + ["SP", "Guaruj\U000000e1", "3518701"], + ["SP", "Guarulhos", "3518800"], + ["SP", "Guatapar\U000000e1", "3518859"], + ["SP", "Guzol\U000000e2ndia", "3518909"], + ["SP", "Hercul\U000000e2ndia", "3519006"], + ["SP", "Holambra", "3519055"], + ["SP", "Hortol\U000000e2ndia", "3519071"], + ["SP", "Iacanga", "3519105"], + ["SP", "Iacri", "3519204"], + ["SP", "Iaras", "3519253"], + ["SP", "Ibat\U000000e9", "3519303"], + ["SP", "Ibir\U000000e1", "3519402"], + ["SP", "Ibirarema", "3519501"], + ["SP", "Ibitinga", "3519600"], + ["SP", "Ibi\U000000fana", "3519709"], + ["SP", "Ic\U000000e9m", "3519808"], + ["SP", "Iep\U000000ea", "3519907"], + ["SP", "Igara\U000000e7u do Tiet\U000000ea", "3520004"], + ["SP", "Igarapava", "3520103"], + ["SP", "Igarat\U000000e1", "3520202"], + ["SP", "Iguape", "3520301"], + ["SP", "Ilha Comprida", "3520426"], + ["SP", "Ilha Solteira", "3520442"], + ["SP", "Ilhabela", "3520400"], + ["SP", "Indaiatuba", "3520509"], + ["SP", "Indiana", "3520608"], + ["SP", "Indiapor\U000000e3", "3520707"], + ["SP", "In\U000000fabia Paulista", "3520806"], + ["SP", "Ipaussu", "3520905"], + ["SP", "Iper\U000000f3", "3521002"], + ["SP", "Ipe\U000000fana", "3521101"], + ["SP", "Ipigu\U000000e1", "3521150"], + ["SP", "Iporanga", "3521200"], + ["SP", "Ipu\U000000e3", "3521309"], + ["SP", "Iracem\U000000e1polis", "3521408"], + ["SP", "Irapu\U000000e3", "3521507"], + ["SP", "Irapuru", "3521606"], + ["SP", "Itaber\U000000e1", "3521705"], + ["SP", "Ita\U000000ed", "3521804"], + ["SP", "Itajobi", "3521903"], + ["SP", "Itaju", "3522000"], + ["SP", "Itanha\U000000e9m", "3522109"], + ["SP", "Itaoca", "3522158"], + ["SP", "Itapecerica da Serra", "3522208"], + ["SP", "Itapetininga", "3522307"], + ["SP", "Itapeva", "3522406"], + ["SP", "Itapevi", "3522505"], + ["SP", "Itapira", "3522604"], + ["SP", "Itapirapu\U000000e3 Paulista", "3522653"], + ["SP", "It\U000000e1polis", "3522703"], + ["SP", "Itaporanga", "3522802"], + ["SP", "Itapu\U000000ed", "3522901"], + ["SP", "Itapura", "3523008"], + ["SP", "Itaquaquecetuba", "3523107"], + ["SP", "Itarar\U000000e9", "3523206"], + ["SP", "Itariri", "3523305"], + ["SP", "Itatiba", "3523404"], + ["SP", "Itatinga", "3523503"], + ["SP", "Itirapina", "3523602"], + ["SP", "Itirapu\U000000e3", "3523701"], + ["SP", "Itobi", "3523800"], + ["SP", "Itu", "3523909"], + ["SP", "Itupeva", "3524006"], + ["SP", "Ituverava", "3524105"], + ["SP", "Jaborandi", "3524204"], + ["SP", "Jaboticabal", "3524303"], + ["SP", "Jacare\U000000ed", "3524402"], + ["SP", "Jaci", "3524501"], + ["SP", "Jacupiranga", "3524600"], + ["SP", "Jaguari\U000000fana", "3524709"], + ["SP", "Jales", "3524808"], + ["SP", "Jambeiro", "3524907"], + ["SP", "Jandira", "3525003"], + ["SP", "Jardin\U000000f3polis", "3525102"], + ["SP", "Jarinu", "3525201"], + ["SP", "Ja\U000000fa", "3525300"], + ["SP", "Jeriquara", "3525409"], + ["SP", "Joan\U000000f3polis", "3525508"], + ["SP", "Jo\U000000e3o Ramalho", "3525607"], + ["SP", "Jos\U000000e9 Bonif\U000000e1cio", "3525706"], + ["SP", "J\U000000falio Mesquita", "3525805"], + ["SP", "Jumirim", "3525854"], + ["SP", "Jundia\U000000ed", "3525904"], + ["SP", "Junqueir\U000000f3polis", "3526001"], + ["SP", "Juqui\U000000e1", "3526100"], + ["SP", "Juquitiba", "3526209"], + ["SP", "Lagoinha", "3526308"], + ["SP", "Laranjal Paulista", "3526407"], + ["SP", "Lav\U000000ednia", "3526506"], + ["SP", "Lavrinhas", "3526605"], + ["SP", "Leme", "3526704"], + ["SP", "Len\U000000e7\U000000f3is Paulista", "3526803"], + ["SP", "Limeira", "3526902"], + ["SP", "Lind\U000000f3ia", "3527009"], + ["SP", "Lins", "3527108"], + ["SP", "Lorena", "3527207"], + ["SP", "Lourdes", "3527256"], + ["SP", "Louveira", "3527306"], + ["SP", "Luc\U000000e9lia", "3527405"], + ["SP", "Lucian\U000000f3polis", "3527504"], + ["SP", "Lu\U000000eds Ant\U000000f4nio", "3527603"], + ["SP", "Luizi\U000000e2nia", "3527702"], + ["SP", "Lup\U000000e9rcio", "3527801"], + ["SP", "Lut\U000000e9cia", "3527900"], + ["SP", "Macatuba", "3528007"], + ["SP", "Macaubal", "3528106"], + ["SP", "Maced\U000000f4nia", "3528205"], + ["SP", "Magda", "3528304"], + ["SP", "Mairinque", "3528403"], + ["SP", "Mairipor\U000000e3", "3528502"], + ["SP", "Manduri", "3528601"], + ["SP", "Marab\U000000e1 Paulista", "3528700"], + ["SP", "Maraca\U000000ed", "3528809"], + ["SP", "Marapoama", "3528858"], + ["SP", "Mari\U000000e1polis", "3528908"], + ["SP", "Mar\U000000edlia", "3529005"], + ["SP", "Marin\U000000f3polis", "3529104"], + ["SP", "Martin\U000000f3polis", "3529203"], + ["SP", "Mat\U000000e3o", "3529302"], + ["SP", "Mau\U000000e1", "3529401"], + ["SP", "Mendon\U000000e7a", "3529500"], + ["SP", "Meridiano", "3529609"], + ["SP", "Mes\U000000f3polis", "3529658"], + ["SP", "Miguel\U000000f3polis", "3529708"], + ["SP", "Mineiros do Tiet\U000000ea", "3529807"], + ["SP", "Mira Estrela", "3530003"], + ["SP", "Miracatu", "3529906"], + ["SP", "Mirand\U000000f3polis", "3530102"], + ["SP", "Mirante do Paranapanema", "3530201"], + ["SP", "Mirassol", "3530300"], + ["SP", "Mirassol\U000000e2ndia", "3530409"], + ["SP", "Mococa", "3530508"], + ["SP", "Mogi das Cruzes", "3530607"], + ["SP", "Mogi Gua\U000000e7u", "3530706"], + ["SP", "Mogi Mirim", "3530805"], + ["SP", "Mombuca", "3530904"], + ["SP", "Mon\U000000e7\U000000f5es", "3531001"], + ["SP", "Mongagu\U000000e1", "3531100"], + ["SP", "Monte Alegre do Sul", "3531209"], + ["SP", "Monte Alto", "3531308"], + ["SP", "Monte Apraz\U000000edvel", "3531407"], + ["SP", "Monte Azul Paulista", "3531506"], + ["SP", "Monte Castelo", "3531605"], + ["SP", "Monte Mor", "3531803"], + ["SP", "Monteiro Lobato", "3531704"], + ["SP", "Morro Agudo", "3531902"], + ["SP", "Morungaba", "3532009"], + ["SP", "Motuca", "3532058"], + ["SP", "Murutinga do Sul", "3532108"], + ["SP", "Nantes", "3532157"], + ["SP", "Narandiba", "3532207"], + ["SP", "Natividade da Serra", "3532306"], + ["SP", "Nazar\U000000e9 Paulista", "3532405"], + ["SP", "Neves Paulista", "3532504"], + ["SP", "Nhandeara", "3532603"], + ["SP", "Nipo\U000000e3", "3532702"], + ["SP", "Nova Alian\U000000e7a", "3532801"], + ["SP", "Nova Campina", "3532827"], + ["SP", "Nova Cana\U000000e3 Paulista", "3532843"], + ["SP", "Nova Castilho", "3532868"], + ["SP", "Nova Europa", "3532900"], + ["SP", "Nova Granada", "3533007"], + ["SP", "Nova Guataporanga", "3533106"], + ["SP", "Nova Independ\U000000eancia", "3533205"], + ["SP", "Nova Luzit\U000000e2nia", "3533304"], + ["SP", "Nova Odessa", "3533403"], + ["SP", "Novais", "3533254"], + ["SP", "Novo Horizonte", "3533502"], + ["SP", "Nuporanga", "3533601"], + ["SP", "Ocau\U000000e7u", "3533700"], + ["SP", "\U000000d3leo", "3533809"], + ["SP", "Ol\U000000edmpia", "3533908"], + ["SP", "Onda Verde", "3534005"], + ["SP", "Oriente", "3534104"], + ["SP", "Orindi\U000000fava", "3534203"], + ["SP", "Orl\U000000e2ndia", "3534302"], + ["SP", "Osasco", "3534401"], + ["SP", "Oscar Bressane", "3534500"], + ["SP", "Osvaldo Cruz", "3534609"], + ["SP", "Ourinhos", "3534708"], + ["SP", "Ouro Verde", "3534807"], + ["SP", "Ouroeste", "3534757"], + ["SP", "Pacaembu", "3534906"], + ["SP", "Palestina", "3535002"], + ["SP", "Palmares Paulista", "3535101"], + ["SP", "Palmeira d'Oeste", "3535200"], + ["SP", "Palmital", "3535309"], + ["SP", "Panorama", "3535408"], + ["SP", "Paragua\U000000e7u Paulista", "3535507"], + ["SP", "Paraibuna", "3535606"], + ["SP", "Para\U000000edso", "3535705"], + ["SP", "Paranapanema", "3535804"], + ["SP", "Paranapu\U000000e3", "3535903"], + ["SP", "Parapu\U000000e3", "3536000"], + ["SP", "Pardinho", "3536109"], + ["SP", "Pariquera-A\U000000e7u", "3536208"], + ["SP", "Parisi", "3536257"], + ["SP", "Patroc\U000000ednio Paulista", "3536307"], + ["SP", "Paulic\U000000e9ia", "3536406"], + ["SP", "Paul\U000000ednia", "3536505"], + ["SP", "Paulist\U000000e2nia", "3536570"], + ["SP", "Paulo de Faria", "3536604"], + ["SP", "Pederneiras", "3536703"], + ["SP", "Pedra Bela", "3536802"], + ["SP", "Pedran\U000000f3polis", "3536901"], + ["SP", "Pedregulho", "3537008"], + ["SP", "Pedreira", "3537107"], + ["SP", "Pedrinhas Paulista", "3537156"], + ["SP", "Pedro de Toledo", "3537206"], + ["SP", "Pen\U000000e1polis", "3537305"], + ["SP", "Pereira Barreto", "3537404"], + ["SP", "Pereiras", "3537503"], + ["SP", "Peru\U000000edbe", "3537602"], + ["SP", "Piacatu", "3537701"], + ["SP", "Piedade", "3537800"], + ["SP", "Pilar do Sul", "3537909"], + ["SP", "Pindamonhangaba", "3538006"], + ["SP", "Pindorama", "3538105"], + ["SP", "Pinhalzinho", "3538204"], + ["SP", "Piquerobi", "3538303"], + ["SP", "Piquete", "3538501"], + ["SP", "Piracaia", "3538600"], + ["SP", "Piracicaba", "3538709"], + ["SP", "Piraju", "3538808"], + ["SP", "Piraju\U000000ed", "3538907"], + ["SP", "Pirangi", "3539004"], + ["SP", "Pirapora do Bom Jesus", "3539103"], + ["SP", "Pirapozinho", "3539202"], + ["SP", "Pirassununga", "3539301"], + ["SP", "Piratininga", "3539400"], + ["SP", "Pitangueiras", "3539509"], + ["SP", "Planalto", "3539608"], + ["SP", "Platina", "3539707"], + ["SP", "Po\U000000e1", "3539806"], + ["SP", "Poloni", "3539905"], + ["SP", "Pomp\U000000e9ia", "3540002"], + ["SP", "Ponga\U000000ed", "3540101"], + ["SP", "Pontal", "3540200"], + ["SP", "Pontalinda", "3540259"], + ["SP", "Pontes Gestal", "3540309"], + ["SP", "Populina", "3540408"], + ["SP", "Porangaba", "3540507"], + ["SP", "Porto Feliz", "3540606"], + ["SP", "Porto Ferreira", "3540705"], + ["SP", "Potim", "3540754"], + ["SP", "Potirendaba", "3540804"], + ["SP", "Pracinha", "3540853"], + ["SP", "Prad\U000000f3polis", "3540903"], + ["SP", "Praia Grande", "3541000"], + ["SP", "Prat\U000000e2nia", "3541059"], + ["SP", "Presidente Alves", "3541109"], + ["SP", "Presidente Bernardes", "3541208"], + ["SP", "Presidente Epit\U000000e1cio", "3541307"], + ["SP", "Presidente Prudente", "3541406"], + ["SP", "Presidente Venceslau", "3541505"], + ["SP", "Promiss\U000000e3o", "3541604"], + ["SP", "Quadra", "3541653"], + ["SP", "Quat\U000000e1", "3541703"], + ["SP", "Queiroz", "3541802"], + ["SP", "Queluz", "3541901"], + ["SP", "Quintana", "3542008"], + ["SP", "Rafard", "3542107"], + ["SP", "Rancharia", "3542206"], + ["SP", "Reden\U000000e7\U000000e3o da Serra", "3542305"], + ["SP", "Regente Feij\U000000f3", "3542404"], + ["SP", "Regin\U000000f3polis", "3542503"], + ["SP", "Registro", "3542602"], + ["SP", "Restinga", "3542701"], + ["SP", "Ribeira", "3542800"], + ["SP", "Ribeir\U000000e3o Bonito", "3542909"], + ["SP", "Ribeir\U000000e3o Branco", "3543006"], + ["SP", "Ribeir\U000000e3o Corrente", "3543105"], + ["SP", "Ribeir\U000000e3o do Sul", "3543204"], + ["SP", "Ribeir\U000000e3o dos \U000000cdndios", "3543238"], + ["SP", "Ribeir\U000000e3o Grande", "3543253"], + ["SP", "Ribeir\U000000e3o Pires", "3543303"], + ["SP", "Ribeir\U000000e3o Preto", "3543402"], + ["SP", "Rifaina", "3543600"], + ["SP", "Rinc\U000000e3o", "3543709"], + ["SP", "Rin\U000000f3polis", "3543808"], + ["SP", "Rio Claro", "3543907"], + ["SP", "Rio das Pedras", "3544004"], + ["SP", "Rio Grande da Serra", "3544103"], + ["SP", "Riol\U000000e2ndia", "3544202"], + ["SP", "Riversul", "3543501"], + ["SP", "Rosana", "3544251"], + ["SP", "Roseira", "3544301"], + ["SP", "Rubi\U000000e1cea", "3544400"], + ["SP", "Rubin\U000000e9ia", "3544509"], + ["SP", "Sabino", "3544608"], + ["SP", "Sagres", "3544707"], + ["SP", "Sales", "3544806"], + ["SP", "Sales Oliveira", "3544905"], + ["SP", "Sales\U000000f3polis", "3545001"], + ["SP", "Salmour\U000000e3o", "3545100"], + ["SP", "Saltinho", "3545159"], + ["SP", "Salto", "3545209"], + ["SP", "Salto de Pirapora", "3545308"], + ["SP", "Salto Grande", "3545407"], + ["SP", "Sandovalina", "3545506"], + ["SP", "Santa Ad\U000000e9lia", "3545605"], + ["SP", "Santa Albertina", "3545704"], + ["SP", "Santa B\U000000e1rbara d'Oeste", "3545803"], + ["SP", "Santa Branca", "3546009"], + ["SP", "Santa Clara d'Oeste", "3546108"], + ["SP", "Santa Cruz da Concei\U000000e7\U000000e3o", "3546207"], + ["SP", "Santa Cruz da Esperan\U000000e7a", "3546256"], + ["SP", "Santa Cruz das Palmeiras", "3546306"], + ["SP", "Santa Cruz do Rio Pardo", "3546405"], + ["SP", "Santa Ernestina", "3546504"], + ["SP", "Santa F\U000000e9 do Sul", "3546603"], + ["SP", "Santa Gertrudes", "3546702"], + ["SP", "Santa Isabel", "3546801"], + ["SP", "Santa L\U000000facia", "3546900"], + ["SP", "Santa Maria da Serra", "3547007"], + ["SP", "Santa Mercedes", "3547106"], + ["SP", "Santa Rita d'Oeste", "3547403"], + ["SP", "Santa Rita do Passa Quatro", "3547502"], + ["SP", "Santa Rosa de Viterbo", "3547601"], + ["SP", "Santa Salete", "3547650"], + ["SP", "Santana da Ponte Pensa", "3547205"], + ["SP", "Santana de Parna\U000000edba", "3547304"], + ["SP", "Santo Anast\U000000e1cio", "3547700"], + ["SP", "Santo Andr\U000000e9", "3547809"], + ["SP", "Santo Ant\U000000f4nio da Alegria", "3547908"], + ["SP", "Santo Ant\U000000f4nio de Posse", "3548005"], + ["SP", "Santo Ant\U000000f4nio do Aracangu\U000000e1", "3548054"], + ["SP", "Santo Ant\U000000f4nio do Jardim", "3548104"], + ["SP", "Santo Ant\U000000f4nio do Pinhal", "3548203"], + ["SP", "Santo Expedito", "3548302"], + ["SP", "Sant\U000000f3polis do Aguape\U000000ed", "3548401"], + ["SP", "Santos", "3548500"], + ["SP", "S\U000000e3o Bento do Sapuca\U000000ed", "3548609"], + ["SP", "S\U000000e3o Bernardo do Campo", "3548708"], + ["SP", "S\U000000e3o Caetano do Sul", "3548807"], + ["SP", "S\U000000e3o Carlos", "3548906"], + ["SP", "S\U000000e3o Francisco", "3549003"], + ["SP", "S\U000000e3o Jo\U000000e3o da Boa Vista", "3549102"], + ["SP", "S\U000000e3o Jo\U000000e3o das Duas Pontes", "3549201"], + ["SP", "S\U000000e3o Jo\U000000e3o de Iracema", "3549250"], + ["SP", "S\U000000e3o Jo\U000000e3o do Pau d'Alho", "3549300"], + ["SP", "S\U000000e3o Joaquim da Barra", "3549409"], + ["SP", "S\U000000e3o Jos\U000000e9 da Bela Vista", "3549508"], + ["SP", "S\U000000e3o Jos\U000000e9 do Barreiro", "3549607"], + ["SP", "S\U000000e3o Jos\U000000e9 do Rio Pardo", "3549706"], + ["SP", "S\U000000e3o Jos\U000000e9 do Rio Preto", "3549805"], + ["SP", "S\U000000e3o Jos\U000000e9 dos Campos", "3549904"], + ["SP", "S\U000000e3o Louren\U000000e7o da Serra", "3549953"], + ["SP", "S\U000000e3o Luiz do Paraitinga", "3550001"], + ["SP", "S\U000000e3o Manuel", "3550100"], + ["SP", "S\U000000e3o Miguel Arcanjo", "3550209"], + ["SP", "S\U000000e3o Paulo", "3550308"], + ["SP", "S\U000000e3o Pedro", "3550407"], + ["SP", "S\U000000e3o Pedro do Turvo", "3550506"], + ["SP", "S\U000000e3o Roque", "3550605"], + ["SP", "S\U000000e3o Sebasti\U000000e3o", "3550704"], + ["SP", "S\U000000e3o Sebasti\U000000e3o da Grama", "3550803"], + ["SP", "S\U000000e3o Sim\U000000e3o", "3550902"], + ["SP", "S\U000000e3o Vicente", "3551009"], + ["SP", "Sarapu\U000000ed", "3551108"], + ["SP", "Sarutai\U000000e1", "3551207"], + ["SP", "Sebastian\U000000f3polis do Sul", "3551306"], + ["SP", "Serra Azul", "3551405"], + ["SP", "Serra Negra", "3551603"], + ["SP", "Serrana", "3551504"], + ["SP", "Sert\U000000e3ozinho", "3551702"], + ["SP", "Sete Barras", "3551801"], + ["SP", "Sever\U000000ednia", "3551900"], + ["SP", "Silveiras", "3552007"], + ["SP", "Socorro", "3552106"], + ["SP", "Sorocaba", "3552205"], + ["SP", "Sud Mennucci", "3552304"], + ["SP", "Sumar\U000000e9", "3552403"], + ["SP", "Suzan\U000000e1polis", "3552551"], + ["SP", "Suzano", "3552502"], + ["SP", "Tabapu\U000000e3", "3552601"], + ["SP", "Tabatinga", "3552700"], + ["SP", "Tabo\U000000e3o da Serra", "3552809"], + ["SP", "Taciba", "3552908"], + ["SP", "Tagua\U000000ed", "3553005"], + ["SP", "Taia\U000000e7u", "3553104"], + ["SP", "Tai\U000000fava", "3553203"], + ["SP", "Tamba\U000000fa", "3553302"], + ["SP", "Tanabi", "3553401"], + ["SP", "Tapira\U000000ed", "3553500"], + ["SP", "Tapiratiba", "3553609"], + ["SP", "Taquaral", "3553658"], + ["SP", "Taquaritinga", "3553708"], + ["SP", "Taquarituba", "3553807"], + ["SP", "Taquariva\U000000ed", "3553856"], + ["SP", "Tarabai", "3553906"], + ["SP", "Tarum\U000000e3", "3553955"], + ["SP", "Tatu\U000000ed", "3554003"], + ["SP", "Taubat\U000000e9", "3554102"], + ["SP", "Tejup\U000000e1", "3554201"], + ["SP", "Teodoro Sampaio", "3554300"], + ["SP", "Terra Roxa", "3554409"], + ["SP", "Tiet\U000000ea", "3554508"], + ["SP", "Timburi", "3554607"], + ["SP", "Torre de Pedra", "3554656"], + ["SP", "Torrinha", "3554706"], + ["SP", "Trabiju", "3554755"], + ["SP", "Trememb\U000000e9", "3554805"], + ["SP", "Tr\U000000eas Fronteiras", "3554904"], + ["SP", "Tuiuti", "3554953"], + ["SP", "Tup\U000000e3", "3555000"], + ["SP", "Tupi Paulista", "3555109"], + ["SP", "Turi\U000000faba", "3555208"], + ["SP", "Turmalina", "3555307"], + ["SP", "Ubarana", "3555356"], + ["SP", "Ubatuba", "3555406"], + ["SP", "Ubirajara", "3555505"], + ["SP", "Uchoa", "3555604"], + ["SP", "Uni\U000000e3o Paulista", "3555703"], + ["SP", "Ur\U000000e2nia", "3555802"], + ["SP", "Uru", "3555901"], + ["SP", "Urup\U000000eas", "3556008"], + ["SP", "Valentim Gentil", "3556107"], + ["SP", "Valinhos", "3556206"], + ["SP", "Valpara\U000000edso", "3556305"], + ["SP", "Vargem", "3556354"], + ["SP", "Vargem Grande do Sul", "3556404"], + ["SP", "Vargem Grande Paulista", "3556453"], + ["SP", "V\U000000e1rzea Paulista", "3556503"], + ["SP", "Vera Cruz", "3556602"], + ["SP", "Vinhedo", "3556701"], + ["SP", "Viradouro", "3556800"], + ["SP", "Vista Alegre do Alto", "3556909"], + ["SP", "Vit\U000000f3ria Brasil", "3556958"], + ["SP", "Votorantim", "3557006"], + ["SP", "Votuporanga", "3557105"], + ["SP", "Zacarias", "3557154"], + ["SE", "Amparo do S\U000000e3o Francisco", "2800100"], + ["SE", "Aquidab\U000000e3", "2800209"], + ["SE", "Aracaju", "2800308"], + ["SE", "Arau\U000000e1", "2800407"], + ["SE", "Areia Branca", "2800506"], + ["SE", "Barra dos Coqueiros", "2800605"], + ["SE", "Boquim", "2800670"], + ["SE", "Brejo Grande", "2800704"], + ["SE", "Campo do Brito", "2801009"], + ["SE", "Canhoba", "2801108"], + ["SE", "Canind\U000000e9 de S\U000000e3o Francisco", "2801207"], + ["SE", "Capela", "2801306"], + ["SE", "Carira", "2801405"], + ["SE", "Carm\U000000f3polis", "2801504"], + ["SE", "Cedro de S\U000000e3o Jo\U000000e3o", "2801603"], + ["SE", "Cristin\U000000e1polis", "2801702"], + ["SE", "Cumbe", "2801900"], + ["SE", "Divina Pastora", "2802007"], + ["SE", "Est\U000000e2ncia", "2802106"], + ["SE", "Feira Nova", "2802205"], + ["SE", "Frei Paulo", "2802304"], + ["SE", "Gararu", "2802403"], + ["SE", "General Maynard", "2802502"], + ["SE", "Graccho Cardoso", "2802601"], + ["SE", "Ilha das Flores", "2802700"], + ["SE", "Indiaroba", "2802809"], + ["SE", "Itabaiana", "2802908"], + ["SE", "Itabaianinha", "2803005"], + ["SE", "Itabi", "2803104"], + ["SE", "Itaporanga d'Ajuda", "2803203"], + ["SE", "Japaratuba", "2803302"], + ["SE", "Japoat\U000000e3", "2803401"], + ["SE", "Lagarto", "2803500"], + ["SE", "Laranjeiras", "2803609"], + ["SE", "Macambira", "2803708"], + ["SE", "Malhada dos Bois", "2803807"], + ["SE", "Malhador", "2803906"], + ["SE", "Maruim", "2804003"], + ["SE", "Moita Bonita", "2804102"], + ["SE", "Monte Alegre de Sergipe", "2804201"], + ["SE", "Muribeca", "2804300"], + ["SE", "Ne\U000000f3polis", "2804409"], + ["SE", "Nossa Senhora Aparecida", "2804458"], + ["SE", "Nossa Senhora da Gl\U000000f3ria", "2804508"], + ["SE", "Nossa Senhora das Dores", "2804607"], + ["SE", "Nossa Senhora de Lourdes", "2804706"], + ["SE", "Nossa Senhora do Socorro", "2804805"], + ["SE", "Pacatuba", "2804904"], + ["SE", "Pedra Mole", "2805000"], + ["SE", "Pedrinhas", "2805109"], + ["SE", "Pinh\U000000e3o", "2805208"], + ["SE", "Pirambu", "2805307"], + ["SE", "Po\U000000e7o Redondo", "2805406"], + ["SE", "Po\U000000e7o Verde", "2805505"], + ["SE", "Porto da Folha", "2805604"], + ["SE", "Propri\U000000e1", "2805703"], + ["SE", "Riach\U000000e3o do Dantas", "2805802"], + ["SE", "Riachuelo", "2805901"], + ["SE", "Ribeir\U000000f3polis", "2806008"], + ["SE", "Ros\U000000e1rio do Catete", "2806107"], + ["SE", "Salgado", "2806206"], + ["SE", "Santa Luzia do Itanhy", "2806305"], + ["SE", "Santa Rosa de Lima", "2806503"], + ["SE", "Santana do S\U000000e3o Francisco", "2806404"], + ["SE", "Santo Amaro das Brotas", "2806602"], + ["SE", "S\U000000e3o Crist\U000000f3v\U000000e3o", "2806701"], + ["SE", "S\U000000e3o Domingos", "2806800"], + ["SE", "S\U000000e3o Francisco", "2806909"], + ["SE", "S\U000000e3o Miguel do Aleixo", "2807006"], + ["SE", "Sim\U000000e3o Dias", "2807105"], + ["SE", "Siriri", "2807204"], + ["SE", "Telha", "2807303"], + ["SE", "Tobias Barreto", "2807402"], + ["SE", "Tomar do Geru", "2807501"], + ["SE", "Umba\U000000faba", "2807600"], + ["TO", "Abreul\U000000e2ndia", "1700251"], + ["TO", "Aguiarn\U000000f3polis", "1700301"], + ["TO", "Alian\U000000e7a do Tocantins", "1700350"], + ["TO", "Almas", "1700400"], + ["TO", "Alvorada", "1700707"], + ["TO", "Anan\U000000e1s", "1701002"], + ["TO", "Angico", "1701051"], + ["TO", "Aparecida do Rio Negro", "1701101"], + ["TO", "Aragominas", "1701309"], + ["TO", "Araguacema", "1701903"], + ["TO", "Aragua\U000000e7u", "1702000"], + ["TO", "Aragua\U000000edna", "1702109"], + ["TO", "Araguan\U000000e3", "1702158"], + ["TO", "Araguatins", "1702208"], + ["TO", "Arapoema", "1702307"], + ["TO", "Arraias", "1702406"], + ["TO", "Augustin\U000000f3polis", "1702554"], + ["TO", "Aurora do Tocantins", "1702703"], + ["TO", "Axix\U000000e1 do Tocantins", "1702901"], + ["TO", "Baba\U000000e7ul\U000000e2ndia", "1703008"], + ["TO", "Bandeirantes do Tocantins", "1703057"], + ["TO", "Barra do Ouro", "1703073"], + ["TO", "Barrol\U000000e2ndia", "1703107"], + ["TO", "Bernardo Say\U000000e3o", "1703206"], + ["TO", "Bom Jesus do Tocantins", "1703305"], + ["TO", "Brasil\U000000e2ndia do Tocantins", "1703602"], + ["TO", "Brejinho de Nazar\U000000e9", "1703701"], + ["TO", "Buriti do Tocantins", "1703800"], + ["TO", "Cachoeirinha", "1703826"], + ["TO", "Campos Lindos", "1703842"], + ["TO", "Cariri do Tocantins", "1703867"], + ["TO", "Carmol\U000000e2ndia", "1703883"], + ["TO", "Carrasco Bonito", "1703891"], + ["TO", "Caseara", "1703909"], + ["TO", "Centen\U000000e1rio", "1704105"], + ["TO", "Chapada da Natividade", "1705102"], + ["TO", "Chapada de Areia", "1704600"], + ["TO", "Colinas do Tocantins", "1705508"], + ["TO", "Colm\U000000e9ia", "1716703"], + ["TO", "Combinado", "1705557"], + ["TO", "Concei\U000000e7\U000000e3o do Tocantins", "1705607"], + ["TO", "Couto Magalh\U000000e3es", "1706001"], + ["TO", "Cristal\U000000e2ndia", "1706100"], + ["TO", "Crix\U000000e1s do Tocantins", "1706258"], + ["TO", "Darcin\U000000f3polis", "1706506"], + ["TO", "Dian\U000000f3polis", "1707009"], + ["TO", "Divin\U000000f3polis do Tocantins", "1707108"], + ["TO", "Dois Irm\U000000e3os do Tocantins", "1707207"], + ["TO", "Duer\U000000e9", "1707306"], + ["TO", "Esperantina", "1707405"], + ["TO", "F\U000000e1tima", "1707553"], + ["TO", "Figueir\U000000f3polis", "1707652"], + ["TO", "Filad\U000000e9lfia", "1707702"], + ["TO", "Formoso do Araguaia", "1708205"], + ["TO", "Goianorte", "1708304"], + ["TO", "Goiatins", "1709005"], + ["TO", "Guara\U000000ed", "1709302"], + ["TO", "Gurupi", "1709500"], + ["TO", "Ipueiras", "1709807"], + ["TO", "Itacaj\U000000e1", "1710508"], + ["TO", "Itaguatins", "1710706"], + ["TO", "Itapiratins", "1710904"], + ["TO", "Itapor\U000000e3 do Tocantins", "1711100"], + ["TO", "Ja\U000000fa do Tocantins", "1711506"], + ["TO", "Juarina", "1711803"], + ["TO", "Lagoa da Confus\U000000e3o", "1711902"], + ["TO", "Lagoa do Tocantins", "1711951"], + ["TO", "Lajeado", "1712009"], + ["TO", "Lavandeira", "1712157"], + ["TO", "Lizarda", "1712405"], + ["TO", "Luzin\U000000f3polis", "1712454"], + ["TO", "Marian\U000000f3polis do Tocantins", "1712504"], + ["TO", "Mateiros", "1712702"], + ["TO", "Mauril\U000000e2ndia do Tocantins", "1712801"], + ["TO", "Miracema do Tocantins", "1713205"], + ["TO", "Miranorte", "1713304"], + ["TO", "Monte do Carmo", "1713601"], + ["TO", "Monte Santo do Tocantins", "1713700"], + ["TO", "Muricil\U000000e2ndia", "1713957"], + ["TO", "Natividade", "1714203"], + ["TO", "Nazar\U000000e9", "1714302"], + ["TO", "Nova Olinda", "1714880"], + ["TO", "Nova Rosal\U000000e2ndia", "1715002"], + ["TO", "Novo Acordo", "1715101"], + ["TO", "Novo Alegre", "1715150"], + ["TO", "Novo Jardim", "1715259"], + ["TO", "Oliveira de F\U000000e1tima", "1715507"], + ["TO", "Palmas", "1721000"], + ["TO", "Palmeirante", "1715705"], + ["TO", "Palmeiras do Tocantins", "1713809"], + ["TO", "Palmeir\U000000f3polis", "1715754"], + ["TO", "Para\U000000edso do Tocantins", "1716109"], + ["TO", "Paran\U000000e3", "1716208"], + ["TO", "Pau D'Arco", "1716307"], + ["TO", "Pedro Afonso", "1716505"], + ["TO", "Peixe", "1716604"], + ["TO", "Pequizeiro", "1716653"], + ["TO", "Pindorama do Tocantins", "1717008"], + ["TO", "Piraqu\U000000ea", "1717206"], + ["TO", "Pium", "1717503"], + ["TO", "Ponte Alta do Bom Jesus", "1717800"], + ["TO", "Ponte Alta do Tocantins", "1717909"], + ["TO", "Porto Alegre do Tocantins", "1718006"], + ["TO", "Porto Nacional", "1718204"], + ["TO", "Praia Norte", "1718303"], + ["TO", "Presidente Kennedy", "1718402"], + ["TO", "Pugmil", "1718451"], + ["TO", "Recursol\U000000e2ndia", "1718501"], + ["TO", "Riachinho", "1718550"], + ["TO", "Rio da Concei\U000000e7\U000000e3o", "1718659"], + ["TO", "Rio dos Bois", "1718709"], + ["TO", "Rio Sono", "1718758"], + ["TO", "Sampaio", "1718808"], + ["TO", "Sandol\U000000e2ndia", "1718840"], + ["TO", "Santa F\U000000e9 do Araguaia", "1718865"], + ["TO", "Santa Maria do Tocantins", "1718881"], + ["TO", "Santa Rita do Tocantins", "1718899"], + ["TO", "Santa Rosa do Tocantins", "1718907"], + ["TO", "Santa Tereza do Tocantins", "1719004"], + ["TO", "Santa Terezinha do Tocantins", "1720002"], + ["TO", "S\U000000e3o Bento do Tocantins", "1720101"], + ["TO", "S\U000000e3o F\U000000e9lix do Tocantins", "1720150"], + ["TO", "S\U000000e3o Miguel do Tocantins", "1720200"], + ["TO", "S\U000000e3o Salvador do Tocantins", "1720259"], + ["TO", "S\U000000e3o Sebasti\U000000e3o do Tocantins", "1720309"], + ["TO", "S\U000000e3o Val\U000000e9rio", "1720499"], + ["TO", "Silvan\U000000f3polis", "1720655"], + ["TO", "S\U000000edtio Novo do Tocantins", "1720804"], + ["TO", "Sucupira", "1720853"], + ["TO", "Taboc\U000000e3o", "1708254"], + ["TO", "Taguatinga", "1720903"], + ["TO", "Taipas do Tocantins", "1720937"], + ["TO", "Talism\U000000e3", "1720978"], + ["TO", "Tocant\U000000ednia", "1721109"], + ["TO", "Tocantin\U000000f3polis", "1721208"], + ["TO", "Tupirama", "1721257"], + ["TO", "Tupiratins", "1721307"], + ["TO", "Wanderl\U000000e2ndia", "1722081"], + ["TO", "Xambio\U000000e1", "1722107"], + ], + [ + ("AC", [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21]), + ("AL", [22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123]), + ("AP", [124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139]), + ("AM", [140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201]), + ("BA", [202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, 443, 444, 445, 446, 447, 448, 449, 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, 495, 496, 497, 498, 499, 500, 501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, 519, 520, 521, 522, 523, 524, 525, 526, 527, 528, 529, 530, 531, 532, 533, 534, 535, 536, 537, 538, 539, 540, 541, 542, 543, 544, 545, 546, 547, 548, 549, 550, 551, 552, 553, 554, 555, 556, 557, 558, 559, 560, 561, 562, 563, 564, 565, 566, 567, 568, 569, 570, 571, 572, 573, 574, 575, 576, 577, 578, 579, 580, 581, 582, 583, 584, 585, 586, 587, 588, 589, 590, 591, 592, 593, 594, 595, 596, 597, 598, 599, 600, 601, 602, 603, 604, 605, 606, 607, 608, 609, 610, 611, 612, 613, 614, 615, 616, 617, 618]), + ("CE", [619, 620, 621, 622, 623, 624, 625, 626, 627, 628, 629, 630, 631, 632, 633, 634, 635, 636, 637, 638, 639, 640, 641, 642, 643, 644, 645, 646, 647, 648, 649, 650, 651, 652, 653, 654, 655, 656, 657, 658, 659, 660, 661, 662, 663, 664, 665, 666, 667, 668, 669, 670, 671, 672, 673, 674, 675, 676, 677, 678, 679, 680, 681, 682, 683, 684, 685, 686, 687, 688, 689, 690, 691, 692, 693, 694, 695, 696, 697, 698, 699, 700, 701, 702, 703, 704, 705, 706, 707, 708, 709, 710, 711, 712, 713, 714, 715, 716, 717, 718, 719, 720, 721, 722, 723, 724, 725, 726, 727, 728, 729, 730, 731, 732, 733, 734, 735, 736, 737, 738, 739, 740, 741, 742, 743, 744, 745, 746, 747, 748, 749, 750, 751, 752, 753, 754, 755, 756, 757, 758, 759, 760, 761, 762, 763, 764, 765, 766, 767, 768, 769, 770, 771, 772, 773, 774, 775, 776, 777, 778, 779, 780, 781, 782, 783, 784, 785, 786, 787, 788, 789, 790, 791, 792, 793, 794, 795, 796, 797, 798, 799, 800, 801, 802]), + ("DF", [803]), + ("ES", [804, 805, 806, 807, 808, 809, 810, 811, 812, 813, 814, 815, 816, 817, 818, 819, 820, 821, 822, 823, 824, 825, 826, 827, 828, 829, 830, 831, 832, 833, 834, 835, 836, 837, 838, 839, 840, 841, 842, 843, 844, 845, 846, 847, 848, 849, 850, 851, 852, 853, 854, 855, 856, 857, 858, 859, 860, 861, 862, 863, 864, 865, 866, 867, 868, 869, 870, 871, 872, 873, 874, 875, 876, 877, 878, 879, 880, 881]), + ("GO", [882, 883, 884, 885, 886, 887, 888, 889, 890, 891, 892, 893, 894, 895, 896, 897, 898, 899, 900, 901, 902, 903, 904, 905, 906, 907, 908, 909, 910, 911, 912, 913, 914, 915, 916, 917, 918, 919, 920, 921, 922, 923, 924, 925, 926, 927, 928, 929, 930, 931, 932, 933, 934, 935, 936, 937, 938, 939, 940, 941, 942, 943, 944, 945, 946, 947, 948, 949, 950, 951, 952, 953, 954, 955, 956, 957, 958, 959, 960, 961, 962, 963, 964, 965, 966, 967, 968, 969, 970, 971, 972, 973, 974, 975, 976, 977, 978, 979, 980, 981, 982, 983, 984, 985, 986, 987, 988, 989, 990, 991, 992, 993, 994, 995, 996, 997, 998, 999, 1000, 1001, 1002, 1003, 1004, 1005, 1006, 1007, 1008, 1009, 1010, 1011, 1012, 1013, 1014, 1015, 1016, 1017, 1018, 1019, 1020, 1021, 1022, 1023, 1024, 1025, 1026, 1027, 1028, 1029, 1030, 1031, 1032, 1033, 1034, 1035, 1036, 1037, 1038, 1039, 1040, 1041, 1042, 1043, 1044, 1045, 1046, 1047, 1048, 1049, 1050, 1051, 1052, 1053, 1054, 1055, 1056, 1057, 1058, 1059, 1060, 1061, 1062, 1063, 1064, 1065, 1066, 1067, 1068, 1069, 1070, 1071, 1072, 1073, 1074, 1075, 1076, 1077, 1078, 1079, 1080, 1081, 1082, 1083, 1084, 1085, 1086, 1087, 1088, 1089, 1090, 1091, 1092, 1093, 1094, 1095, 1096, 1097, 1098, 1099, 1100, 1101, 1102, 1103, 1104, 1105, 1106, 1107, 1108, 1109, 1110, 1111, 1112, 1113, 1114, 1115, 1116, 1117, 1118, 1119, 1120, 1121, 1122, 1123, 1124, 1125, 1126, 1127]), + ("MA", [1128, 1129, 1130, 1131, 1132, 1133, 1134, 1135, 1136, 1137, 1138, 1139, 1140, 1141, 1142, 1143, 1144, 1145, 1146, 1147, 1148, 1149, 1150, 1151, 1152, 1153, 1154, 1155, 1156, 1157, 1158, 1159, 1160, 1161, 1162, 1163, 1164, 1165, 1166, 1167, 1168, 1169, 1170, 1171, 1172, 1173, 1174, 1175, 1176, 1177, 1178, 1179, 1180, 1181, 1182, 1183, 1184, 1185, 1186, 1187, 1188, 1189, 1190, 1191, 1192, 1193, 1194, 1195, 1196, 1197, 1198, 1199, 1200, 1201, 1202, 1203, 1204, 1205, 1206, 1207, 1208, 1209, 1210, 1211, 1212, 1213, 1214, 1215, 1216, 1217, 1218, 1219, 1220, 1221, 1222, 1223, 1224, 1225, 1226, 1227, 1228, 1229, 1230, 1231, 1232, 1233, 1234, 1235, 1236, 1237, 1238, 1239, 1240, 1241, 1242, 1243, 1244, 1245, 1246, 1247, 1248, 1249, 1250, 1251, 1252, 1253, 1254, 1255, 1256, 1257, 1258, 1259, 1260, 1261, 1262, 1263, 1264, 1265, 1266, 1267, 1268, 1269, 1270, 1271, 1272, 1273, 1274, 1275, 1276, 1277, 1278, 1279, 1280, 1281, 1282, 1283, 1284, 1285, 1286, 1287, 1288, 1289, 1290, 1291, 1292, 1293, 1294, 1295, 1296, 1297, 1298, 1299, 1300, 1301, 1302, 1303, 1304, 1305, 1306, 1307, 1308, 1309, 1310, 1311, 1312, 1313, 1314, 1315, 1316, 1317, 1318, 1319, 1320, 1321, 1322, 1323, 1324, 1325, 1326, 1327, 1328, 1329, 1330, 1331, 1332, 1333, 1334, 1335, 1336, 1337, 1338, 1339, 1340, 1341, 1342, 1343, 1344]), + ("MT", [1345, 1346, 1347, 1348, 1349, 1350, 1351, 1352, 1353, 1354, 1355, 1356, 1357, 1358, 1359, 1360, 1361, 1362, 1363, 1364, 1365, 1366, 1367, 1368, 1369, 1370, 1371, 1372, 1373, 1374, 1375, 1376, 1377, 1378, 1379, 1380, 1381, 1382, 1383, 1384, 1385, 1386, 1387, 1388, 1389, 1390, 1391, 1392, 1393, 1394, 1395, 1396, 1397, 1398, 1399, 1400, 1401, 1402, 1403, 1404, 1405, 1406, 1407, 1408, 1409, 1410, 1411, 1412, 1413, 1414, 1415, 1416, 1417, 1418, 1419, 1420, 1421, 1422, 1423, 1424, 1425, 1426, 1427, 1428, 1429, 1430, 1431, 1432, 1433, 1434, 1435, 1436, 1437, 1438, 1439, 1440, 1441, 1442, 1443, 1444, 1445, 1446, 1447, 1448, 1449, 1450, 1451, 1452, 1453, 1454, 1455, 1456, 1457, 1458, 1459, 1460, 1461, 1462, 1463, 1464, 1465, 1466, 1467, 1468, 1469, 1470, 1471, 1472, 1473, 1474, 1475, 1476, 1477, 1478, 1479, 1480, 1481, 1482, 1483, 1484, 1485, 1486]), + ("MS", [1487, 1488, 1489, 1490, 1491, 1492, 1493, 1494, 1495, 1496, 1497, 1498, 1499, 1500, 1501, 1502, 1503, 1504, 1505, 1506, 1507, 1508, 1509, 1510, 1511, 1512, 1513, 1514, 1515, 1516, 1517, 1518, 1519, 1520, 1521, 1522, 1523, 1524, 1525, 1526, 1527, 1528, 1529, 1530, 1531, 1532, 1533, 1534, 1535, 1536, 1537, 1538, 1539, 1540, 1541, 1542, 1543, 1544, 1545, 1546, 1547, 1548, 1549, 1550, 1551, 1552, 1553, 1554, 1555, 1556, 1557, 1558, 1559, 1560, 1561, 1562, 1563, 1564, 1565]), + ("MG", [1566, 1567, 1568, 1569, 1570, 1571, 1572, 1573, 1574, 1575, 1576, 1577, 1578, 1579, 1580, 1581, 1582, 1583, 1584, 1585, 1586, 1587, 1588, 1589, 1590, 1591, 1592, 1593, 1594, 1595, 1596, 1597, 1598, 1599, 1600, 1601, 1602, 1603, 1604, 1605, 1606, 1607, 1608, 1609, 1610, 1611, 1612, 1613, 1614, 1615, 1616, 1617, 1618, 1619, 1620, 1621, 1622, 1623, 1624, 1625, 1626, 1627, 1628, 1629, 1630, 1631, 1632, 1633, 1634, 1635, 1636, 1637, 1638, 1639, 1640, 1641, 1642, 1643, 1644, 1645, 1646, 1647, 1648, 1649, 1650, 1651, 1652, 1653, 1654, 1655, 1656, 1657, 1658, 1659, 1660, 1661, 1662, 1663, 1664, 1665, 1666, 1667, 1668, 1669, 1670, 1671, 1672, 1673, 1674, 1675, 1676, 1677, 1678, 1679, 1680, 1681, 1682, 1683, 1684, 1685, 1686, 1687, 1688, 1689, 1690, 1691, 1692, 1693, 1694, 1695, 1696, 1697, 1698, 1699, 1700, 1701, 1702, 1703, 1704, 1705, 1706, 1707, 1708, 1709, 1710, 1711, 1712, 1713, 1714, 1715, 1716, 1717, 1718, 1719, 1720, 1721, 1722, 1723, 1724, 1725, 1726, 1727, 1728, 1729, 1730, 1731, 1732, 1733, 1734, 1735, 1736, 1737, 1738, 1739, 1740, 1741, 1742, 1743, 1744, 1745, 1746, 1747, 1748, 1749, 1750, 1751, 1752, 1753, 1754, 1755, 1756, 1757, 1758, 1759, 1760, 1761, 1762, 1763, 1764, 1765, 1766, 1767, 1768, 1769, 1770, 1771, 1772, 1773, 1774, 1775, 1776, 1777, 1778, 1779, 1780, 1781, 1782, 1783, 1784, 1785, 1786, 1787, 1788, 1789, 1790, 1791, 1792, 1793, 1794, 1795, 1796, 1797, 1798, 1799, 1800, 1801, 1802, 1803, 1804, 1805, 1806, 1807, 1808, 1809, 1810, 1811, 1812, 1813, 1814, 1815, 1816, 1817, 1818, 1819, 1820, 1821, 1822, 1823, 1824, 1825, 1826, 1827, 1828, 1829, 1830, 1831, 1832, 1833, 1834, 1835, 1836, 1837, 1838, 1839, 1840, 1841, 1842, 1843, 1844, 1845, 1846, 1847, 1848, 1849, 1850, 1851, 1852, 1853, 1854, 1855, 1856, 1857, 1858, 1859, 1860, 1861, 1862, 1863, 1864, 1865, 1866, 1867, 1868, 1869, 1870, 1871, 1872, 1873, 1874, 1875, 1876, 1877, 1878, 1879, 1880, 1881, 1882, 1883, 1884, 1885, 1886, 1887, 1888, 1889, 1890, 1891, 1892, 1893, 1894, 1895, 1896, 1897, 1898, 1899, 1900, 1901, 1902, 1903, 1904, 1905, 1906, 1907, 1908, 1909, 1910, 1911, 1912, 1913, 1914, 1915, 1916, 1917, 1918, 1919, 1920, 1921, 1922, 1923, 1924, 1925, 1926, 1927, 1928, 1929, 1930, 1931, 1932, 1933, 1934, 1935, 1936, 1937, 1938, 1939, 1940, 1941, 1942, 1943, 1944, 1945, 1946, 1947, 1948, 1949, 1950, 1951, 1952, 1953, 1954, 1955, 1956, 1957, 1958, 1959, 1960, 1961, 1962, 1963, 1964, 1965, 1966, 1967, 1968, 1969, 1970, 1971, 1972, 1973, 1974, 1975, 1976, 1977, 1978, 1979, 1980, 1981, 1982, 1983, 1984, 1985, 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020, 2021, 2022, 2023, 2024, 2025, 2026, 2027, 2028, 2029, 2030, 2031, 2032, 2033, 2034, 2035, 2036, 2037, 2038, 2039, 2040, 2041, 2042, 2043, 2044, 2045, 2046, 2047, 2048, 2049, 2050, 2051, 2052, 2053, 2054, 2055, 2056, 2057, 2058, 2059, 2060, 2061, 2062, 2063, 2064, 2065, 2066, 2067, 2068, 2069, 2070, 2071, 2072, 2073, 2074, 2075, 2076, 2077, 2078, 2079, 2080, 2081, 2082, 2083, 2084, 2085, 2086, 2087, 2088, 2089, 2090, 2091, 2092, 2093, 2094, 2095, 2096, 2097, 2098, 2099, 2100, 2101, 2102, 2103, 2104, 2105, 2106, 2107, 2108, 2109, 2110, 2111, 2112, 2113, 2114, 2115, 2116, 2117, 2118, 2119, 2120, 2121, 2122, 2123, 2124, 2125, 2126, 2127, 2128, 2129, 2130, 2131, 2132, 2133, 2134, 2135, 2136, 2137, 2138, 2139, 2140, 2141, 2142, 2143, 2144, 2145, 2146, 2147, 2148, 2149, 2150, 2151, 2152, 2153, 2154, 2155, 2156, 2157, 2158, 2159, 2160, 2161, 2162, 2163, 2164, 2165, 2166, 2167, 2168, 2169, 2170, 2171, 2172, 2173, 2174, 2175, 2176, 2177, 2178, 2179, 2180, 2181, 2182, 2183, 2184, 2185, 2186, 2187, 2188, 2189, 2190, 2191, 2192, 2193, 2194, 2195, 2196, 2197, 2198, 2199, 2200, 2201, 2202, 2203, 2204, 2205, 2206, 2207, 2208, 2209, 2210, 2211, 2212, 2213, 2214, 2215, 2216, 2217, 2218, 2219, 2220, 2221, 2222, 2223, 2224, 2225, 2226, 2227, 2228, 2229, 2230, 2231, 2232, 2233, 2234, 2235, 2236, 2237, 2238, 2239, 2240, 2241, 2242, 2243, 2244, 2245, 2246, 2247, 2248, 2249, 2250, 2251, 2252, 2253, 2254, 2255, 2256, 2257, 2258, 2259, 2260, 2261, 2262, 2263, 2264, 2265, 2266, 2267, 2268, 2269, 2270, 2271, 2272, 2273, 2274, 2275, 2276, 2277, 2278, 2279, 2280, 2281, 2282, 2283, 2284, 2285, 2286, 2287, 2288, 2289, 2290, 2291, 2292, 2293, 2294, 2295, 2296, 2297, 2298, 2299, 2300, 2301, 2302, 2303, 2304, 2305, 2306, 2307, 2308, 2309, 2310, 2311, 2312, 2313, 2314, 2315, 2316, 2317, 2318, 2319, 2320, 2321, 2322, 2323, 2324, 2325, 2326, 2327, 2328, 2329, 2330, 2331, 2332, 2333, 2334, 2335, 2336, 2337, 2338, 2339, 2340, 2341, 2342, 2343, 2344, 2345, 2346, 2347, 2348, 2349, 2350, 2351, 2352, 2353, 2354, 2355, 2356, 2357, 2358, 2359, 2360, 2361, 2362, 2363, 2364, 2365, 2366, 2367, 2368, 2369, 2370, 2371, 2372, 2373, 2374, 2375, 2376, 2377, 2378, 2379, 2380, 2381, 2382, 2383, 2384, 2385, 2386, 2387, 2388, 2389, 2390, 2391, 2392, 2393, 2394, 2395, 2396, 2397, 2398, 2399, 2400, 2401, 2402, 2403, 2404, 2405, 2406, 2407, 2408, 2409, 2410, 2411, 2412, 2413, 2414, 2415, 2416, 2417, 2418]), + ("PA", [2419, 2420, 2421, 2422, 2423, 2424, 2425, 2426, 2427, 2428, 2429, 2430, 2431, 2432, 2433, 2434, 2435, 2436, 2437, 2438, 2439, 2440, 2441, 2442, 2443, 2444, 2445, 2446, 2447, 2448, 2449, 2450, 2451, 2452, 2453, 2454, 2455, 2456, 2457, 2458, 2459, 2460, 2461, 2462, 2463, 2464, 2465, 2466, 2467, 2468, 2469, 2470, 2471, 2472, 2473, 2474, 2475, 2476, 2477, 2478, 2479, 2480, 2481, 2482, 2483, 2484, 2485, 2486, 2487, 2488, 2489, 2490, 2491, 2492, 2493, 2494, 2495, 2496, 2497, 2498, 2499, 2500, 2501, 2502, 2503, 2504, 2505, 2506, 2507, 2508, 2509, 2510, 2511, 2512, 2513, 2514, 2515, 2516, 2517, 2518, 2519, 2520, 2521, 2522, 2523, 2524, 2525, 2526, 2527, 2528, 2529, 2530, 2531, 2532, 2533, 2534, 2535, 2536, 2537, 2538, 2539, 2540, 2541, 2542, 2543, 2544, 2545, 2546, 2547, 2548, 2549, 2550, 2551, 2552, 2553, 2554, 2555, 2556, 2557, 2558, 2559, 2560, 2561, 2562]), + ("PB", [2563, 2564, 2565, 2566, 2567, 2568, 2569, 2570, 2571, 2572, 2573, 2574, 2575, 2576, 2577, 2578, 2579, 2580, 2581, 2582, 2583, 2584, 2585, 2586, 2587, 2588, 2589, 2590, 2591, 2592, 2593, 2594, 2595, 2596, 2597, 2598, 2599, 2600, 2601, 2602, 2603, 2604, 2605, 2606, 2607, 2608, 2609, 2610, 2611, 2612, 2613, 2614, 2615, 2616, 2617, 2618, 2619, 2620, 2621, 2622, 2623, 2624, 2625, 2626, 2627, 2628, 2629, 2630, 2631, 2632, 2633, 2634, 2635, 2636, 2637, 2638, 2639, 2640, 2641, 2642, 2643, 2644, 2645, 2646, 2647, 2648, 2649, 2650, 2651, 2652, 2653, 2654, 2655, 2656, 2657, 2658, 2659, 2660, 2661, 2662, 2663, 2664, 2665, 2666, 2667, 2668, 2669, 2670, 2671, 2672, 2673, 2674, 2675, 2676, 2677, 2678, 2679, 2680, 2681, 2682, 2683, 2684, 2685, 2686, 2687, 2688, 2689, 2690, 2691, 2692, 2693, 2694, 2695, 2696, 2697, 2698, 2699, 2700, 2701, 2702, 2703, 2704, 2705, 2706, 2707, 2708, 2709, 2710, 2711, 2712, 2713, 2714, 2715, 2716, 2717, 2718, 2719, 2720, 2721, 2722, 2723, 2724, 2725, 2726, 2727, 2728, 2729, 2730, 2731, 2732, 2733, 2734, 2735, 2736, 2737, 2738, 2739, 2740, 2741, 2742, 2743, 2744, 2745, 2746, 2747, 2748, 2749, 2750, 2751, 2752, 2753, 2754, 2755, 2756, 2757, 2758, 2759, 2760, 2761, 2762, 2763, 2764, 2765, 2766, 2767, 2768, 2769, 2770, 2771, 2772, 2773, 2774, 2775, 2776, 2777, 2778, 2779, 2780, 2781, 2782, 2783, 2784, 2785]), + ("PR", [2786, 2787, 2788, 2789, 2790, 2791, 2792, 2793, 2794, 2795, 2796, 2797, 2798, 2799, 2800, 2801, 2802, 2803, 2804, 2805, 2806, 2807, 2808, 2809, 2810, 2811, 2812, 2813, 2814, 2815, 2816, 2817, 2818, 2819, 2820, 2821, 2822, 2823, 2824, 2825, 2826, 2827, 2828, 2829, 2830, 2831, 2832, 2833, 2834, 2835, 2836, 2837, 2838, 2839, 2840, 2841, 2842, 2843, 2844, 2845, 2846, 2847, 2848, 2849, 2850, 2851, 2852, 2853, 2854, 2855, 2856, 2857, 2858, 2859, 2860, 2861, 2862, 2863, 2864, 2865, 2866, 2867, 2868, 2869, 2870, 2871, 2872, 2873, 2874, 2875, 2876, 2877, 2878, 2879, 2880, 2881, 2882, 2883, 2884, 2885, 2886, 2887, 2888, 2889, 2890, 2891, 2892, 2893, 2894, 2895, 2896, 2897, 2898, 2899, 2900, 2901, 2902, 2903, 2904, 2905, 2906, 2907, 2908, 2909, 2910, 2911, 2912, 2913, 2914, 2915, 2916, 2917, 2918, 2919, 2920, 2921, 2922, 2923, 2924, 2925, 2926, 2927, 2928, 2929, 2930, 2931, 2932, 2933, 2934, 2935, 2936, 2937, 2938, 2939, 2940, 2941, 2942, 2943, 2944, 2945, 2946, 2947, 2948, 2949, 2950, 2951, 2952, 2953, 2954, 2955, 2956, 2957, 2958, 2959, 2960, 2961, 2962, 2963, 2964, 2965, 2966, 2967, 2968, 2969, 2970, 2971, 2972, 2973, 2974, 2975, 2976, 2977, 2978, 2979, 2980, 2981, 2982, 2983, 2984, 2985, 2986, 2987, 2988, 2989, 2990, 2991, 2992, 2993, 2994, 2995, 2996, 2997, 2998, 2999, 3000, 3001, 3002, 3003, 3004, 3005, 3006, 3007, 3008, 3009, 3010, 3011, 3012, 3013, 3014, 3015, 3016, 3017, 3018, 3019, 3020, 3021, 3022, 3023, 3024, 3025, 3026, 3027, 3028, 3029, 3030, 3031, 3032, 3033, 3034, 3035, 3036, 3037, 3038, 3039, 3040, 3041, 3042, 3043, 3044, 3045, 3046, 3047, 3048, 3049, 3050, 3051, 3052, 3053, 3054, 3055, 3056, 3057, 3058, 3059, 3060, 3061, 3062, 3063, 3064, 3065, 3066, 3067, 3068, 3069, 3070, 3071, 3072, 3073, 3074, 3075, 3076, 3077, 3078, 3079, 3080, 3081, 3082, 3083, 3084, 3085, 3086, 3087, 3088, 3089, 3090, 3091, 3092, 3093, 3094, 3095, 3096, 3097, 3098, 3099, 3100, 3101, 3102, 3103, 3104, 3105, 3106, 3107, 3108, 3109, 3110, 3111, 3112, 3113, 3114, 3115, 3116, 3117, 3118, 3119, 3120, 3121, 3122, 3123, 3124, 3125, 3126, 3127, 3128, 3129, 3130, 3131, 3132, 3133, 3134, 3135, 3136, 3137, 3138, 3139, 3140, 3141, 3142, 3143, 3144, 3145, 3146, 3147, 3148, 3149, 3150, 3151, 3152, 3153, 3154, 3155, 3156, 3157, 3158, 3159, 3160, 3161, 3162, 3163, 3164, 3165, 3166, 3167, 3168, 3169, 3170, 3171, 3172, 3173, 3174, 3175, 3176, 3177, 3178, 3179, 3180, 3181, 3182, 3183, 3184]), + ("PE", [3185, 3186, 3187, 3188, 3189, 3190, 3191, 3192, 3193, 3194, 3195, 3196, 3197, 3198, 3199, 3200, 3201, 3202, 3203, 3204, 3205, 3206, 3207, 3208, 3209, 3210, 3211, 3212, 3213, 3214, 3215, 3216, 3217, 3218, 3219, 3220, 3221, 3222, 3223, 3224, 3225, 3226, 3227, 3228, 3229, 3230, 3231, 3232, 3233, 3234, 3235, 3236, 3237, 3238, 3239, 3240, 3241, 3242, 3243, 3244, 3245, 3246, 3247, 3248, 3249, 3250, 3251, 3252, 3253, 3254, 3255, 3256, 3257, 3258, 3259, 3260, 3261, 3262, 3263, 3264, 3265, 3266, 3267, 3268, 3269, 3270, 3271, 3272, 3273, 3274, 3275, 3276, 3277, 3278, 3279, 3280, 3281, 3282, 3283, 3284, 3285, 3286, 3287, 3288, 3289, 3290, 3291, 3292, 3293, 3294, 3295, 3296, 3297, 3298, 3299, 3300, 3301, 3302, 3303, 3304, 3305, 3306, 3307, 3308, 3309, 3310, 3311, 3312, 3313, 3314, 3315, 3316, 3317, 3318, 3319, 3320, 3321, 3322, 3323, 3324, 3325, 3326, 3327, 3328, 3329, 3330, 3331, 3332, 3333, 3334, 3335, 3336, 3337, 3338, 3339, 3340, 3341, 3342, 3343, 3344, 3345, 3346, 3347, 3348, 3349, 3350, 3351, 3352, 3353, 3354, 3355, 3356, 3357, 3358, 3359, 3360, 3361, 3362, 3363, 3364, 3365, 3366, 3367, 3368, 3369]), + ("PI", [3370, 3371, 3372, 3373, 3374, 3375, 3376, 3377, 3378, 3379, 3380, 3381, 3382, 3383, 3384, 3385, 3386, 3387, 3388, 3389, 3390, 3391, 3392, 3393, 3394, 3395, 3396, 3397, 3398, 3399, 3400, 3401, 3402, 3403, 3404, 3405, 3406, 3407, 3408, 3409, 3410, 3411, 3412, 3413, 3414, 3415, 3416, 3417, 3418, 3419, 3420, 3421, 3422, 3423, 3424, 3425, 3426, 3427, 3428, 3429, 3430, 3431, 3432, 3433, 3434, 3435, 3436, 3437, 3438, 3439, 3440, 3441, 3442, 3443, 3444, 3445, 3446, 3447, 3448, 3449, 3450, 3451, 3452, 3453, 3454, 3455, 3456, 3457, 3458, 3459, 3460, 3461, 3462, 3463, 3464, 3465, 3466, 3467, 3468, 3469, 3470, 3471, 3472, 3473, 3474, 3475, 3476, 3477, 3478, 3479, 3480, 3481, 3482, 3483, 3484, 3485, 3486, 3487, 3488, 3489, 3490, 3491, 3492, 3493, 3494, 3495, 3496, 3497, 3498, 3499, 3500, 3501, 3502, 3503, 3504, 3505, 3506, 3507, 3508, 3509, 3510, 3511, 3512, 3513, 3514, 3515, 3516, 3517, 3518, 3519, 3520, 3521, 3522, 3523, 3524, 3525, 3526, 3527, 3528, 3529, 3530, 3531, 3532, 3533, 3534, 3535, 3536, 3537, 3538, 3539, 3540, 3541, 3542, 3543, 3544, 3545, 3546, 3547, 3548, 3549, 3550, 3551, 3552, 3553, 3554, 3555, 3556, 3557, 3558, 3559, 3560, 3561, 3562, 3563, 3564, 3565, 3566, 3567, 3568, 3569, 3570, 3571, 3572, 3573, 3574, 3575, 3576, 3577, 3578, 3579, 3580, 3581, 3582, 3583, 3584, 3585, 3586, 3587, 3588, 3589, 3590, 3591, 3592, 3593]), + ("RJ", [3594, 3595, 3596, 3597, 3598, 3599, 3600, 3601, 3602, 3603, 3604, 3605, 3606, 3607, 3608, 3609, 3610, 3611, 3612, 3613, 3614, 3615, 3616, 3617, 3618, 3619, 3620, 3621, 3622, 3623, 3624, 3625, 3626, 3627, 3628, 3629, 3630, 3631, 3632, 3633, 3634, 3635, 3636, 3637, 3638, 3639, 3640, 3641, 3642, 3643, 3644, 3645, 3646, 3647, 3648, 3649, 3650, 3651, 3652, 3653, 3654, 3655, 3656, 3657, 3658, 3659, 3660, 3661, 3662, 3663, 3664, 3665, 3666, 3667, 3668, 3669, 3670, 3671, 3672, 3673, 3674, 3675, 3676, 3677, 3678, 3679, 3680, 3681, 3682, 3683, 3684, 3685]), + ("RN", [3686, 3687, 3688, 3689, 3690, 3691, 3692, 3693, 3694, 3695, 3696, 3697, 3698, 3699, 3700, 3701, 3702, 3703, 3704, 3705, 3706, 3707, 3708, 3709, 3710, 3711, 3712, 3713, 3714, 3715, 3716, 3717, 3718, 3719, 3720, 3721, 3722, 3723, 3724, 3725, 3726, 3727, 3728, 3729, 3730, 3731, 3732, 3733, 3734, 3735, 3736, 3737, 3738, 3739, 3740, 3741, 3742, 3743, 3744, 3745, 3746, 3747, 3748, 3749, 3750, 3751, 3752, 3753, 3754, 3755, 3756, 3757, 3758, 3759, 3760, 3761, 3762, 3763, 3764, 3765, 3766, 3767, 3768, 3769, 3770, 3771, 3772, 3773, 3774, 3775, 3776, 3777, 3778, 3779, 3780, 3781, 3782, 3783, 3784, 3785, 3786, 3787, 3788, 3789, 3790, 3791, 3792, 3793, 3794, 3795, 3796, 3797, 3798, 3799, 3800, 3801, 3802, 3803, 3804, 3805, 3806, 3807, 3808, 3809, 3810, 3811, 3812, 3813, 3814, 3815, 3816, 3817, 3818, 3819, 3820, 3821, 3822, 3823, 3824, 3825, 3826, 3827, 3828, 3829, 3830, 3831, 3832, 3833, 3834, 3835, 3836, 3837, 3838, 3839, 3840, 3841, 3842, 3843, 3844, 3845, 3846, 3847, 3848, 3849, 3850, 3851, 3852]), + ("RS", [3853, 3854, 3855, 3856, 3857, 3858, 3859, 3860, 3861, 3862, 3863, 3864, 3865, 3866, 3867, 3868, 3869, 3870, 3871, 3872, 3873, 3874, 3875, 3876, 3877, 3878, 3879, 3880, 3881, 3882, 3883, 3884, 3885, 3886, 3887, 3888, 3889, 3890, 3891, 3892, 3893, 3894, 3895, 3896, 3897, 3898, 3899, 3900, 3901, 3902, 3903, 3904, 3905, 3906, 3907, 3908, 3909, 3910, 3911, 3912, 3913, 3914, 3915, 3916, 3917, 3918, 3919, 3920, 3921, 3922, 3923, 3924, 3925, 3926, 3927, 3928, 3929, 3930, 3931, 3932, 3933, 3934, 3935, 3936, 3937, 3938, 3939, 3940, 3941, 3942, 3943, 3944, 3945, 3946, 3947, 3948, 3949, 3950, 3951, 3952, 3953, 3954, 3955, 3956, 3957, 3958, 3959, 3960, 3961, 3962, 3963, 3964, 3965, 3966, 3967, 3968, 3969, 3970, 3971, 3972, 3973, 3974, 3975, 3976, 3977, 3978, 3979, 3980, 3981, 3982, 3983, 3984, 3985, 3986, 3987, 3988, 3989, 3990, 3991, 3992, 3993, 3994, 3995, 3996, 3997, 3998, 3999, 4000, 4001, 4002, 4003, 4004, 4005, 4006, 4007, 4008, 4009, 4010, 4011, 4012, 4013, 4014, 4015, 4016, 4017, 4018, 4019, 4020, 4021, 4022, 4023, 4024, 4025, 4026, 4027, 4028, 4029, 4030, 4031, 4032, 4033, 4034, 4035, 4036, 4037, 4038, 4039, 4040, 4041, 4042, 4043, 4044, 4045, 4046, 4047, 4048, 4049, 4050, 4051, 4052, 4053, 4054, 4055, 4056, 4057, 4058, 4059, 4060, 4061, 4062, 4063, 4064, 4065, 4066, 4067, 4068, 4069, 4070, 4071, 4072, 4073, 4074, 4075, 4076, 4077, 4078, 4079, 4080, 4081, 4082, 4083, 4084, 4085, 4086, 4087, 4088, 4089, 4090, 4091, 4092, 4093, 4094, 4095, 4096, 4097, 4098, 4099, 4100, 4101, 4102, 4103, 4104, 4105, 4106, 4107, 4108, 4109, 4110, 4111, 4112, 4113, 4114, 4115, 4116, 4117, 4118, 4119, 4120, 4121, 4122, 4123, 4124, 4125, 4126, 4127, 4128, 4129, 4130, 4131, 4132, 4133, 4134, 4135, 4136, 4137, 4138, 4139, 4140, 4141, 4142, 4143, 4144, 4145, 4146, 4147, 4148, 4149, 4150, 4151, 4152, 4153, 4154, 4155, 4156, 4157, 4158, 4159, 4160, 4161, 4162, 4163, 4164, 4165, 4166, 4167, 4168, 4169, 4170, 4171, 4172, 4173, 4174, 4175, 4176, 4177, 4178, 4179, 4180, 4181, 4182, 4183, 4184, 4185, 4186, 4187, 4188, 4189, 4190, 4191, 4192, 4193, 4194, 4195, 4196, 4197, 4198, 4199, 4200, 4201, 4202, 4203, 4204, 4205, 4206, 4207, 4208, 4209, 4210, 4211, 4212, 4213, 4214, 4215, 4216, 4217, 4218, 4219, 4220, 4221, 4222, 4223, 4224, 4225, 4226, 4227, 4228, 4229, 4230, 4231, 4232, 4233, 4234, 4235, 4236, 4237, 4238, 4239, 4240, 4241, 4242, 4243, 4244, 4245, 4246, 4247, 4248, 4249, 4250, 4251, 4252, 4253, 4254, 4255, 4256, 4257, 4258, 4259, 4260, 4261, 4262, 4263, 4264, 4265, 4266, 4267, 4268, 4269, 4270, 4271, 4272, 4273, 4274, 4275, 4276, 4277, 4278, 4279, 4280, 4281, 4282, 4283, 4284, 4285, 4286, 4287, 4288, 4289, 4290, 4291, 4292, 4293, 4294, 4295, 4296, 4297, 4298, 4299, 4300, 4301, 4302, 4303, 4304, 4305, 4306, 4307, 4308, 4309, 4310, 4311, 4312, 4313, 4314, 4315, 4316, 4317, 4318, 4319, 4320, 4321, 4322, 4323, 4324, 4325, 4326, 4327, 4328, 4329, 4330, 4331, 4332, 4333, 4334, 4335, 4336, 4337, 4338, 4339, 4340, 4341, 4342, 4343, 4344, 4345, 4346, 4347, 4348, 4349]), + ("RO", [4350, 4351, 4352, 4353, 4354, 4355, 4356, 4357, 4358, 4359, 4360, 4361, 4362, 4363, 4364, 4365, 4366, 4367, 4368, 4369, 4370, 4371, 4372, 4373, 4374, 4375, 4376, 4377, 4378, 4379, 4380, 4381, 4382, 4383, 4384, 4385, 4386, 4387, 4388, 4389, 4390, 4391, 4392, 4393, 4394, 4395, 4396, 4397, 4398, 4399, 4400, 4401]), + ("RR", [4402, 4403, 4404, 4405, 4406, 4407, 4408, 4409, 4410, 4411, 4412, 4413, 4414, 4415, 4416]), + ("SC", [4417, 4418, 4419, 4420, 4421, 4422, 4423, 4424, 4425, 4426, 4427, 4428, 4429, 4430, 4431, 4432, 4433, 4434, 4435, 4436, 4437, 4438, 4439, 4440, 4441, 4442, 4443, 4444, 4445, 4446, 4447, 4448, 4449, 4450, 4451, 4452, 4453, 4454, 4455, 4456, 4457, 4458, 4459, 4460, 4461, 4462, 4463, 4464, 4465, 4466, 4467, 4468, 4469, 4470, 4471, 4472, 4473, 4474, 4475, 4476, 4477, 4478, 4479, 4480, 4481, 4482, 4483, 4484, 4485, 4486, 4487, 4488, 4489, 4490, 4491, 4492, 4493, 4494, 4495, 4496, 4497, 4498, 4499, 4500, 4501, 4502, 4503, 4504, 4505, 4506, 4507, 4508, 4509, 4510, 4511, 4512, 4513, 4514, 4515, 4516, 4517, 4518, 4519, 4520, 4521, 4522, 4523, 4524, 4525, 4526, 4527, 4528, 4529, 4530, 4531, 4532, 4533, 4534, 4535, 4536, 4537, 4538, 4539, 4540, 4541, 4542, 4543, 4544, 4545, 4546, 4547, 4548, 4549, 4550, 4551, 4552, 4553, 4554, 4555, 4556, 4557, 4558, 4559, 4560, 4561, 4562, 4563, 4564, 4565, 4566, 4567, 4568, 4569, 4570, 4571, 4572, 4573, 4574, 4575, 4576, 4577, 4578, 4579, 4580, 4581, 4582, 4583, 4584, 4585, 4586, 4587, 4588, 4589, 4590, 4591, 4592, 4593, 4594, 4595, 4596, 4597, 4598, 4599, 4600, 4601, 4602, 4603, 4604, 4605, 4606, 4607, 4608, 4609, 4610, 4611, 4612, 4613, 4614, 4615, 4616, 4617, 4618, 4619, 4620, 4621, 4622, 4623, 4624, 4625, 4626, 4627, 4628, 4629, 4630, 4631, 4632, 4633, 4634, 4635, 4636, 4637, 4638, 4639, 4640, 4641, 4642, 4643, 4644, 4645, 4646, 4647, 4648, 4649, 4650, 4651, 4652, 4653, 4654, 4655, 4656, 4657, 4658, 4659, 4660, 4661, 4662, 4663, 4664, 4665, 4666, 4667, 4668, 4669, 4670, 4671, 4672, 4673, 4674, 4675, 4676, 4677, 4678, 4679, 4680, 4681, 4682, 4683, 4684, 4685, 4686, 4687, 4688, 4689, 4690, 4691, 4692, 4693, 4694, 4695, 4696, 4697, 4698, 4699, 4700, 4701, 4702, 4703, 4704, 4705, 4706, 4707, 4708, 4709, 4710, 4711]), + ("SP", [4712, 4713, 4714, 4715, 4716, 4717, 4718, 4719, 4720, 4721, 4722, 4723, 4724, 4725, 4726, 4727, 4728, 4729, 4730, 4731, 4732, 4733, 4734, 4735, 4736, 4737, 4738, 4739, 4740, 4741, 4742, 4743, 4744, 4745, 4746, 4747, 4748, 4749, 4750, 4751, 4752, 4753, 4754, 4755, 4756, 4757, 4758, 4759, 4760, 4761, 4762, 4763, 4764, 4765, 4766, 4767, 4768, 4769, 4770, 4771, 4772, 4773, 4774, 4775, 4776, 4777, 4778, 4779, 4780, 4781, 4782, 4783, 4784, 4785, 4786, 4787, 4788, 4789, 4790, 4791, 4792, 4793, 4794, 4795, 4796, 4797, 4798, 4799, 4800, 4801, 4802, 4803, 4804, 4805, 4806, 4807, 4808, 4809, 4810, 4811, 4812, 4813, 4814, 4815, 4816, 4817, 4818, 4819, 4820, 4821, 4822, 4823, 4824, 4825, 4826, 4827, 4828, 4829, 4830, 4831, 4832, 4833, 4834, 4835, 4836, 4837, 4838, 4839, 4840, 4841, 4842, 4843, 4844, 4845, 4846, 4847, 4848, 4849, 4850, 4851, 4852, 4853, 4854, 4855, 4856, 4857, 4858, 4859, 4860, 4861, 4862, 4863, 4864, 4865, 4866, 4867, 4868, 4869, 4870, 4871, 4872, 4873, 4874, 4875, 4876, 4877, 4878, 4879, 4880, 4881, 4882, 4883, 4884, 4885, 4886, 4887, 4888, 4889, 4890, 4891, 4892, 4893, 4894, 4895, 4896, 4897, 4898, 4899, 4900, 4901, 4902, 4903, 4904, 4905, 4906, 4907, 4908, 4909, 4910, 4911, 4912, 4913, 4914, 4915, 4916, 4917, 4918, 4919, 4920, 4921, 4922, 4923, 4924, 4925, 4926, 4927, 4928, 4929, 4930, 4931, 4932, 4933, 4934, 4935, 4936, 4937, 4938, 4939, 4940, 4941, 4942, 4943, 4944, 4945, 4946, 4947, 4948, 4949, 4950, 4951, 4952, 4953, 4954, 4955, 4956, 4957, 4958, 4959, 4960, 4961, 4962, 4963, 4964, 4965, 4966, 4967, 4968, 4969, 4970, 4971, 4972, 4973, 4974, 4975, 4976, 4977, 4978, 4979, 4980, 4981, 4982, 4983, 4984, 4985, 4986, 4987, 4988, 4989, 4990, 4991, 4992, 4993, 4994, 4995, 4996, 4997, 4998, 4999, 5000, 5001, 5002, 5003, 5004, 5005, 5006, 5007, 5008, 5009, 5010, 5011, 5012, 5013, 5014, 5015, 5016, 5017, 5018, 5019, 5020, 5021, 5022, 5023, 5024, 5025, 5026, 5027, 5028, 5029, 5030, 5031, 5032, 5033, 5034, 5035, 5036, 5037, 5038, 5039, 5040, 5041, 5042, 5043, 5044, 5045, 5046, 5047, 5048, 5049, 5050, 5051, 5052, 5053, 5054, 5055, 5056, 5057, 5058, 5059, 5060, 5061, 5062, 5063, 5064, 5065, 5066, 5067, 5068, 5069, 5070, 5071, 5072, 5073, 5074, 5075, 5076, 5077, 5078, 5079, 5080, 5081, 5082, 5083, 5084, 5085, 5086, 5087, 5088, 5089, 5090, 5091, 5092, 5093, 5094, 5095, 5096, 5097, 5098, 5099, 5100, 5101, 5102, 5103, 5104, 5105, 5106, 5107, 5108, 5109, 5110, 5111, 5112, 5113, 5114, 5115, 5116, 5117, 5118, 5119, 5120, 5121, 5122, 5123, 5124, 5125, 5126, 5127, 5128, 5129, 5130, 5131, 5132, 5133, 5134, 5135, 5136, 5137, 5138, 5139, 5140, 5141, 5142, 5143, 5144, 5145, 5146, 5147, 5148, 5149, 5150, 5151, 5152, 5153, 5154, 5155, 5156, 5157, 5158, 5159, 5160, 5161, 5162, 5163, 5164, 5165, 5166, 5167, 5168, 5169, 5170, 5171, 5172, 5173, 5174, 5175, 5176, 5177, 5178, 5179, 5180, 5181, 5182, 5183, 5184, 5185, 5186, 5187, 5188, 5189, 5190, 5191, 5192, 5193, 5194, 5195, 5196, 5197, 5198, 5199, 5200, 5201, 5202, 5203, 5204, 5205, 5206, 5207, 5208, 5209, 5210, 5211, 5212, 5213, 5214, 5215, 5216, 5217, 5218, 5219, 5220, 5221, 5222, 5223, 5224, 5225, 5226, 5227, 5228, 5229, 5230, 5231, 5232, 5233, 5234, 5235, 5236, 5237, 5238, 5239, 5240, 5241, 5242, 5243, 5244, 5245, 5246, 5247, 5248, 5249, 5250, 5251, 5252, 5253, 5254, 5255, 5256, 5257, 5258, 5259, 5260, 5261, 5262, 5263, 5264, 5265, 5266, 5267, 5268, 5269, 5270, 5271, 5272, 5273, 5274, 5275, 5276, 5277, 5278, 5279, 5280, 5281, 5282, 5283, 5284, 5285, 5286, 5287, 5288, 5289, 5290, 5291, 5292, 5293, 5294, 5295, 5296, 5297, 5298, 5299, 5300, 5301, 5302, 5303, 5304, 5305, 5306, 5307, 5308, 5309, 5310, 5311, 5312, 5313, 5314, 5315, 5316, 5317, 5318, 5319, 5320, 5321, 5322, 5323, 5324, 5325, 5326, 5327, 5328, 5329, 5330, 5331, 5332, 5333, 5334, 5335, 5336, 5337, 5338, 5339, 5340, 5341, 5342, 5343, 5344, 5345, 5346, 5347, 5348, 5349, 5350, 5351, 5352, 5353, 5354, 5355, 5356]), + ("SE", [5357, 5358, 5359, 5360, 5361, 5362, 5363, 5364, 5365, 5366, 5367, 5368, 5369, 5370, 5371, 5372, 5373, 5374, 5375, 5376, 5377, 5378, 5379, 5380, 5381, 5382, 5383, 5384, 5385, 5386, 5387, 5388, 5389, 5390, 5391, 5392, 5393, 5394, 5395, 5396, 5397, 5398, 5399, 5400, 5401, 5402, 5403, 5404, 5405, 5406, 5407, 5408, 5409, 5410, 5411, 5412, 5413, 5414, 5415, 5416, 5417, 5418, 5419, 5420, 5421, 5422, 5423, 5424, 5425, 5426, 5427, 5428, 5429, 5430, 5431]), + ("TO", [5432, 5433, 5434, 5435, 5436, 5437, 5438, 5439, 5440, 5441, 5442, 5443, 5444, 5445, 5446, 5447, 5448, 5449, 5450, 5451, 5452, 5453, 5454, 5455, 5456, 5457, 5458, 5459, 5460, 5461, 5462, 5463, 5464, 5465, 5466, 5467, 5468, 5469, 5470, 5471, 5472, 5473, 5474, 5475, 5476, 5477, 5478, 5479, 5480, 5481, 5482, 5483, 5484, 5485, 5486, 5487, 5488, 5489, 5490, 5491, 5492, 5493, 5494, 5495, 5496, 5497, 5498, 5499, 5500, 5501, 5502, 5503, 5504, 5505, 5506, 5507, 5508, 5509, 5510, 5511, 5512, 5513, 5514, 5515, 5516, 5517, 5518, 5519, 5520, 5521, 5522, 5523, 5524, 5525, 5526, 5527, 5528, 5529, 5530, 5531, 5532, 5533, 5534, 5535, 5536, 5537, 5538, 5539, 5540, 5541, 5542, 5543, 5544, 5545, 5546, 5547, 5548, 5549, 5550, 5551, 5552, 5553, 5554, 5555, 5556, 5557, 5558, 5559, 5560, 5561, 5562, 5563, 5564, 5565, 5566, 5567, 5568, 5569, 5570]), + ], + [882, 1566, 883, 1567, 2419, 619, 202, 203, 2786, 4417, 2420, 4418, 1568, 3185, 5432, 1569, 1128, 204, 2421, 620, 621, 3686, 3370, 3853, 622, 1345, 0, 884, 1570, 4712, 885, 4713, 2787, 205, 3186, 3687, 804, 1129, 3187, 2422, 3188, 3371, 4419, 4420, 2423, 1346, 1571, 22, 2563, 3372, 1487, 1572, 4421, 1130, 805, 206, 886, 887, 3688, 3189, 3854, 4714, 1573, 3190, 4715, 4422, 4716, 4717, 4718, 1574, 4423, 888, 4424, 1575, 3855, 4719, 2788, 806, 2564, 5433, 1576, 207, 623, 1577, 3856, 1578, 2565, 2566, 2567, 3191, 3373, 208, 4720, 1579, 1131, 624, 2568, 1488, 209, 1132, 3857, 807, 3858, 3374, 3859, 1580, 2424, 3689, 889, 1581, 808, 4721, 1582, 4425, 2569, 2570, 3192, 5434, 210, 5435, 2425, 1583, 3690, 2789, 3860, 890, 1584, 3861, 1585, 1347, 4350, 4722, 2426, 1133, 2790, 625, 1586, 3193, 4723, 3862, 4402, 4724, 1134, 1135, 4351, 1348, 4426, 1349, 1587, 3691, 3863, 1350, 891, 1588, 3375, 1351, 2791, 4352, 892, 2792, 1136, 2793, 1589, 809, 626, 1352, 2794, 3376, 4725, 140, 1590, 4726, 4727, 4728, 4729, 1591, 3864, 5436, 4353, 1592, 3377, 893, 2795, 4403, 1489, 124, 1137, 2796, 3194, 3865, 894, 3378, 1138, 211, 141, 212, 213, 4730, 895, 4731, 4732, 3866, 627, 896, 2571, 4733, 5357, 1593, 2797, 23, 214, 2798, 2427, 1139, 4734, 142, 5437, 2428, 897, 2429, 1140, 1490, 1491, 810, 4427, 215, 2799, 216, 1594, 4735, 3867, 1595, 4736, 1596, 1492, 3195, 4428, 217, 3379, 5438, 3692, 3594, 218, 2800, 898, 4737, 4738, 899, 3380, 4429, 4430, 143, 3868, 219, 2801, 628, 3381, 220, 1597, 4431, 1598, 221, 1493, 3693, 2802, 3869, 1599, 2572, 4739, 4740, 900, 901, 5439, 1494, 3595, 811, 1353, 4741, 1141, 4432, 3694, 222, 902, 223, 2803, 144, 629, 5358, 1495, 630, 4433, 2573, 1600, 5359, 4742, 224, 631, 225, 4743, 226, 1601, 632, 3196, 4744, 812, 903, 1602, 904, 905, 5440, 5441, 5442, 1354, 5443, 1355, 1142, 5444, 906, 1603, 5445, 1143, 1496, 227, 3870, 1144, 4745, 4746, 1604, 4747, 24, 5446, 1605, 2804, 1606, 2805, 1607, 2806, 1356, 4434, 2574, 4435, 4748, 4749, 633, 1145, 3871, 634, 3197, 3596, 2575, 2807, 228, 3872, 635, 229, 5360, 2808, 1608, 1609, 1610, 4750, 1611, 3198, 1612, 3597, 4751, 2576, 3695, 5361, 2577, 2578, 4752, 4753, 1357, 907, 3696, 1613, 1614, 1615, 1358, 4354, 4754, 2809, 3598, 4436, 636, 3382, 2579, 3383, 3384, 3599, 5447, 3873, 3874, 3875, 3876, 3877, 3878, 4437, 4755, 908, 4756, 4438, 3879, 4439, 4757, 2810, 637, 4758, 1, 2811, 3697, 2580, 3385, 1616, 2812, 25, 2813, 145, 4440, 1617, 4759, 813, 5448, 2430, 1618, 3880, 3881, 230, 4760, 909, 638, 4441, 2431, 5449, 146, 4761, 4762, 4763, 2432, 3386, 910, 1146, 5450, 5451, 1147, 1148, 1149, 1150, 4764, 1619, 3882, 2433, 2581, 3698, 231, 2434, 232, 3387, 639, 814, 4765, 1620, 911, 4442, 4443, 4444, 4445, 4446, 3883, 4447, 2814, 4766, 1151, 1621, 640, 4767, 2582, 1622, 1623, 4448, 1497, 2815, 5452, 2435, 233, 3884, 4768, 1624, 3885, 1152, 1359, 1625, 3886, 2583, 3699, 1626, 641, 4769, 2816, 2436, 3700, 147, 4770, 234, 4449, 4771, 3388, 235, 3199, 2584, 2585, 26, 815, 27, 2586, 1360, 4772, 236, 1153, 1361, 3887, 2817, 237, 5453, 3600, 3888, 3889, 3890, 238, 4773, 5362, 3891, 1627, 3601, 4450, 2818, 3892, 3389, 642, 239, 3390, 148, 1154, 3200, 4774, 4775, 643, 240, 912, 3391, 241, 242, 5454, 644, 3893, 1628, 4776, 4777, 1498, 28, 3392, 4778, 1499, 645, 4779, 2587, 4780, 646, 647, 1500, 2819, 913, 1629, 1155, 2820, 3393, 4451, 1156, 29, 2437, 2588, 3201, 2589, 3394, 3202, 3602, 1630, 243, 4452, 244, 1631, 3203, 30, 1632, 1633, 2438, 3395, 1157, 4453, 2439, 149, 3894, 4781, 3701, 3895, 1158, 1634, 1635, 2590, 4782, 1159, 5455, 4783, 3396, 1636, 150, 3204, 3397, 1637, 3205, 1638, 1639, 4454, 4784, 1640, 4785, 4786, 245, 2821, 4455, 816, 1641, 2822, 2823, 1362, 4787, 3398, 246, 2591, 2824, 648, 2592, 4404, 2825, 3896, 3897, 3898, 1160, 3899, 151, 3900, 247, 31, 152, 3399, 4788, 1642, 4456, 1643, 2826, 3702, 3206, 1501, 4789, 4790, 3207, 1644, 1161, 3208, 3603, 4457, 914, 1645, 2593, 3400, 3703, 3901, 4458, 248, 1646, 249, 1162, 915, 1647, 1363, 1648, 3604, 817, 4459, 2827, 2440, 5456, 4791, 1163, 3902, 3401, 3903, 1649, 4460, 3904, 1650, 2594, 2828, 4792, 2829, 4461, 1651, 4405, 3402, 916, 1652, 250, 251, 1502, 2441, 3209, 1653, 2595, 917, 2596, 3905, 3403, 5363, 252, 4793, 4794, 153, 2597, 4795, 1654, 4796, 2830, 3906, 1655, 4797, 1656, 253, 4462, 3907, 4463, 4464, 3908, 2442, 4798, 2831, 32, 1657, 2443, 1503, 1658, 2832, 5457, 2, 3404, 803, 1659, 1364, 4799, 1660, 918, 1661, 3210, 818, 3211, 3704, 5458, 1164, 4800, 3212, 1165, 2598, 3405, 2599, 5364, 2444, 649, 254, 255, 2445, 2446, 919, 3909, 4801, 4802, 256, 1662, 257, 4465, 4466, 1663, 1664, 3213, 258, 1665, 3214, 3, 2447, 4803, 4804, 1166, 920, 1167, 921, 5459, 3406, 3407, 1168, 922, 259, 1169, 1666, 4355, 4805, 1667, 3910, 154, 2600, 1504, 260, 2601, 261, 1668, 923, 3408, 2602, 4356, 3215, 3605, 1669, 4806, 4807, 3216, 4467, 4808, 3911, 4357, 3912, 1365, 262, 924, 1670, 925, 1671, 1672, 2448, 2449, 3913, 2603, 926, 1673, 1170, 4809, 3606, 3217, 3914, 5460, 819, 2604, 2605, 2606, 33, 3915, 4358, 4810, 927, 263, 264, 1674, 265, 1675, 3218, 266, 267, 2833, 2834, 4811, 2835, 4812, 1676, 928, 3916, 4468, 2607, 3917, 3705, 3706, 3707, 4813, 268, 4814, 4815, 1171, 1172, 4816, 2608, 3409, 2609, 4817, 34, 3410, 1677, 4818, 3219, 125, 1678, 2610, 929, 930, 269, 3411, 2836, 4469, 3220, 270, 271, 1679, 2611, 272, 1680, 1505, 3918, 3221, 3919, 2837, 3920, 2838, 2839, 4470, 3607, 1681, 1682, 2450, 650, 3222, 1683, 1684, 35, 1685, 3921, 931, 1173, 2840, 3922, 4819, 2841, 2612, 2842, 1686, 932, 1366, 4820, 3412, 3923, 933, 36, 4471, 934, 273, 3413, 1687, 1688, 4472, 3924, 2843, 5365, 1689, 2844, 4473, 1690, 274, 37, 1506, 3708, 3414, 2845, 3415, 935, 4821, 2846, 3416, 2847, 3925, 4359, 1367, 3709, 1368, 1691, 936, 3926, 1369, 4822, 3608, 1692, 5461, 4474, 4823, 651, 937, 3223, 1693, 1694, 2451, 1370, 4824, 38, 275, 1695, 276, 1371, 4825, 3417, 277, 278, 279, 1696, 4360, 3927, 280, 2848, 3928, 1174, 4826, 4827, 281, 3929, 2849, 3930, 4475, 3710, 3931, 5366, 3224, 652, 5367, 4828, 3932, 4476, 282, 4406, 1697, 2850, 3609, 1175, 3418, 283, 3933, 155, 2452, 2851, 4477, 4829, 3934, 3935, 3936, 3937, 1698, 39, 5368, 3938, 4830, 284, 1699, 1700, 1701, 2613, 1702, 285, 1703, 4478, 1176, 653, 3939, 1704, 3419, 1705, 3420, 2852, 2453, 1706, 4831, 4479, 3940, 4, 3225, 1707, 3941, 4407, 1507, 3421, 4832, 1708, 286, 2853, 1709, 1710, 1711, 3610, 4833, 1712, 156, 2614, 3711, 3422, 287, 3942, 1713, 288, 4834, 3611, 1714, 157, 158, 820, 654, 3423, 289, 5369, 655, 5462, 656, 657, 1372, 2854, 3943, 1715, 3944, 1716, 3612, 1717, 1718, 1719, 1720, 1721, 1722, 938, 5463, 5370, 1723, 3226, 3712, 3713, 658, 3227, 1724, 40, 4408, 1177, 3228, 1725, 2615, 5464, 3229, 1178, 1726, 1727, 4835, 1728, 290, 3945, 1729, 659, 2855, 5465, 3946, 3613, 3230, 2616, 1730, 4836, 1508, 2454, 1373, 4361, 939, 821, 3424, 4837, 2856, 291, 1731, 940, 4838, 2857, 4480, 660, 1732, 1733, 3231, 4839, 2617, 292, 2618, 293, 3947, 1734, 661, 941, 294, 2619, 1735, 662, 942, 1736, 4481, 1179, 3948, 3425, 3714, 1180, 4840, 663, 3232, 5371, 1737, 4482, 3949, 5466, 2858, 295, 1738, 1181, 1739, 1182, 1183, 4362, 943, 4841, 4842, 3950, 2859, 3951, 3715, 3952, 3953, 3954, 4483, 4843, 2860, 944, 3233, 3234, 41, 1740, 1741, 3955, 5467, 5468, 1742, 1374, 1743, 945, 4484, 1509, 1184, 4485, 4844, 3956, 3957, 664, 4845, 2455, 1744, 3958, 2861, 665, 666, 296, 3959, 4363, 3960, 2862, 297, 2863, 946, 1185, 3961, 298, 1745, 3962, 1746, 1747, 1375, 1748, 4846, 2864, 299, 159, 3426, 3427, 4486, 3428, 1376, 947, 300, 160, 1186, 1187, 1749, 42, 3429, 2456, 822, 1377, 4847, 1188, 3963, 948, 5469, 5470, 1378, 4848, 2865, 3430, 3431, 43, 2866, 3964, 4364, 1750, 5471, 1751, 3614, 1752, 1379, 2620, 1753, 823, 1754, 301, 1755, 1756, 1757, 3615, 302, 2457, 3432, 824, 303, 304, 1189, 1758, 1759, 1760, 5472, 1761, 4849, 4850, 4487, 2458, 2621, 3235, 305, 2622, 306, 3965, 1762, 1763, 1380, 2623, 1764, 1765, 1766, 2867, 1767, 1381, 1768, 2868, 1769, 1770, 3966, 1771, 2869, 307, 1772, 3967, 44, 3968, 1773, 308, 2870, 3616, 4851, 309, 4488, 1774, 1775, 667, 2624, 1510, 310, 1776, 2871, 1777, 4852, 1190, 1778, 3969, 3970, 2872, 3716, 1779, 4489, 3717, 311, 3433, 4853, 4490, 1780, 1781, 3971, 1511, 2873, 1782, 1783, 1784, 949, 1785, 1786, 4491, 3434, 3236, 312, 3237, 1512, 950, 951, 4854, 2874, 4365, 4492, 45, 4855, 4856, 4366, 1513, 313, 4857, 3972, 1382, 1787, 5473, 3973, 1514, 2625, 46, 668, 669, 4858, 314, 4493, 1788, 315, 3974, 1789, 4859, 3975, 3976, 5474, 3435, 1790, 952, 1791, 953, 1792, 5372, 3436, 316, 954, 5475, 670, 955, 1793, 671, 3977, 317, 2626, 2875, 4860, 3978, 4861, 1794, 2876, 2877, 5, 2878, 3979, 3718, 1795, 2879, 4862, 2627, 1383, 2628, 2629, 2630, 4367, 956, 3238, 2459, 5373, 4863, 4494, 4495, 1796, 3239, 318, 3437, 2460, 2880, 4496, 2881, 3438, 3719, 2631, 1797, 3439, 2632, 2461, 3440, 2462, 2463, 1191, 1384, 1798, 3240, 126, 957, 2633, 958, 5476, 319, 1799, 3980, 959, 1192, 1800, 1801, 47, 1802, 3441, 1385, 1515, 672, 3981, 4864, 4497, 1803, 2634, 1804, 1805, 3982, 4865, 2635, 2882, 2883, 2884, 1806, 1386, 5477, 320, 3983, 1807, 1808, 4498, 960, 4866, 3442, 5374, 1809, 1810, 1811, 825, 4867, 1812, 1813, 961, 5478, 1814, 1815, 1816, 4868, 4869, 3984, 3985, 1516, 5479, 3986, 48, 2885, 4870, 1387, 321, 1817, 1818, 2464, 3443, 3987, 3444, 1819, 322, 3988, 1193, 3989, 1820, 1821, 826, 3445, 4499, 1822, 3990, 2636, 1823, 1824, 1825, 827, 1826, 1827, 3241, 1517, 2886, 4871, 1828, 1518, 2887, 3991, 4500, 3992, 3720, 2888, 962, 4872, 4873, 3617, 2637, 5480, 4874, 1194, 3618, 1829, 4875, 828, 963, 964, 161, 1519, 4876, 2465, 3993, 3446, 4877, 3447, 4878, 323, 1830, 2638, 4879, 4880, 4881, 4882, 3994, 3721, 324, 3995, 2889, 2890, 1831, 4883, 1832, 3619, 3996, 1833, 325, 4501, 1834, 2891, 3997, 3998, 162, 6, 3722, 3999, 4000, 673, 326, 4502, 4001, 4002, 4003, 4503, 1835, 3242, 4004, 1836, 1837, 2639, 4005, 2892, 3448, 5481, 1195, 2893, 4368, 1838, 3723, 1839, 4884, 4885, 327, 4006, 4007, 5375, 4008, 4009, 1840, 4886, 1196, 4010, 4887, 1841, 49, 1842, 965, 4888, 1843, 4011, 328, 4889, 4012, 1844, 329, 674, 1845, 1846, 3724, 3243, 2640, 4013, 966, 1847, 1848, 675, 2466, 2894, 4014, 4890, 3449, 330, 5482, 1520, 2895, 4015, 4504, 4016, 967, 2896, 4017, 7, 331, 332, 50, 3244, 5376, 1197, 1849, 3725, 1850, 1851, 4018, 51, 1388, 2897, 2898, 1852, 3245, 1198, 3726, 4891, 4892, 4893, 4894, 127, 3246, 1853, 1854, 2899, 1521, 5483, 1389, 333, 5484, 334, 968, 52, 2900, 4505, 4895, 2901, 3727, 4896, 3247, 4019, 969, 3450, 2902, 3248, 335, 2467, 3451, 1855, 2903, 3452, 4020, 4506, 2904, 4897, 4898, 163, 4021, 1856, 4022, 970, 1199, 2905, 336, 4507, 971, 1857, 5485, 4023, 676, 4508, 677, 1858, 1200, 4024, 678, 1201, 1859, 2906, 2907, 4509, 4899, 3453, 2908, 3454, 1860, 2909, 3728, 1861, 3455, 4900, 1862, 3456, 1863, 4901, 679, 4025, 1864, 1865, 1866, 2641, 3249, 5377, 4510, 1867, 1868, 3457, 1869, 1870, 3729, 829, 1871, 4902, 2642, 4903, 1872, 3730, 4511, 3250, 972, 1873, 337, 3251, 5378, 4904, 4026, 4512, 2468, 4027, 4513, 4514, 4905, 1390, 4028, 338, 4906, 3458, 4029, 1391, 2910, 5379, 4907, 680, 4030, 339, 4908, 4031, 3459, 53, 4032, 1874, 4909, 340, 1392, 1522, 3252, 4033, 1202, 2911, 1875, 3253, 1876, 973, 974, 975, 2469, 976, 3731, 977, 5486, 978, 5487, 979, 2912, 2913, 1877, 1203, 341, 1878, 1879, 980, 1204, 4515, 3732, 1205, 1206, 4369, 830, 1207, 342, 1208, 1209, 1880, 681, 1210, 5380, 1211, 4034, 4035, 4036, 2914, 3254, 682, 683, 1881, 4516, 3255, 4037, 4517, 684, 3733, 1882, 4038, 4518, 831, 3460, 4039, 4910, 4911, 2915, 4912, 2916, 685, 164, 4370, 343, 3734, 2917, 344, 1883, 1884, 4913, 4914, 3620, 2918, 981, 4040, 2919, 4915, 2643, 4916, 2920, 4917, 1885, 4519, 686, 1886, 5488, 982, 687, 4520, 1887, 1888, 4918, 4041, 983, 2921, 4919, 1393, 832, 2922, 2923, 1889, 4920, 4921, 345, 4922, 2924, 1890, 4923, 4924, 3461, 984, 4925, 4521, 4926, 4522, 4927, 1891, 1523, 1892, 1212, 1893, 1394, 1894, 1895, 2644, 2645, 2470, 5489, 4928, 4042, 985, 1896, 346, 4929, 4043, 4523, 4044, 688, 986, 987, 4930, 2925, 689, 4045, 4931, 3462, 4046, 165, 4047, 1213, 4932, 988, 4933, 347, 1897, 4934, 3256, 2926, 4048, 690, 4935, 54, 833, 2927, 1898, 1899, 4049, 1900, 4524, 691, 2646, 348, 349, 4525, 350, 351, 692, 3257, 352, 353, 2928, 354, 4936, 1901, 1902, 834, 4050, 3258, 4526, 355, 356, 4051, 4937, 357, 1903, 4052, 358, 4938, 835, 359, 1904, 1905, 4939, 360, 693, 4527, 1906, 2929, 1214, 4940, 361, 694, 836, 3735, 4941, 55, 362, 4942, 2647, 4943, 1907, 1215, 1216, 2471, 2472, 3259, 4944, 1908, 363, 56, 4053, 3621, 364, 4945, 2930, 3260, 1909, 1524, 695, 2931, 1910, 4054, 4946, 5381, 3261, 3463, 4947, 4948, 365, 4528, 1911, 4055, 2648, 4529, 2932, 4056, 1912, 4530, 2933, 4531, 4057, 1217, 2934, 989, 2935, 3262, 1913, 1914, 4532, 4949, 696, 4058, 4950, 1915, 2936, 4951, 990, 5382, 1395, 2649, 1916, 3263, 4059, 366, 2473, 57, 1917, 1918, 3464, 991, 1919, 1525, 4952, 4533, 1920, 992, 1921, 3736, 697, 1922, 698, 4953, 4060, 367, 4954, 4955, 1923, 368, 4956, 4534, 369, 2937, 993, 1396, 3465, 4061, 166, 2474, 3264, 994, 2938, 4535, 4957, 699, 4958, 4536, 3265, 3737, 700, 5490, 1924, 4537, 370, 701, 4409, 2939, 4959, 4538, 4062, 1925, 371, 372, 167, 4539, 4960, 4961, 373, 374, 2940, 4540, 702, 375, 2941, 4541, 2475, 837, 3466, 995, 4542, 4063, 2650, 5383, 5384, 376, 4962, 377, 996, 5385, 1926, 1927, 1928, 3622, 378, 5491, 1929, 1930, 379, 168, 3266, 4064, 380, 381, 382, 383, 838, 384, 3623, 2942, 1931, 997, 998, 5492, 4963, 3267, 703, 3467, 4543, 1218, 1932, 2943, 704, 2476, 999, 3738, 4544, 4964, 4965, 385, 1933, 386, 3624, 387, 1934, 169, 1935, 388, 1936, 2944, 389, 2945, 3268, 1937, 1938, 1939, 390, 4966, 1940, 1397, 391, 1941, 1942, 4967, 3625, 1000, 1943, 705, 392, 393, 394, 1944, 4968, 1219, 2946, 4545, 839, 2947, 3626, 3269, 395, 4969, 1945, 4970, 4971, 396, 706, 4972, 170, 4546, 1001, 4973, 5493, 3270, 397, 707, 4547, 4974, 1526, 5494, 2651, 4975, 5386, 2652, 4371, 4065, 4976, 4977, 1002, 4978, 398, 4066, 1527, 3271, 840, 399, 4979, 708, 4980, 1003, 4067, 3627, 1946, 4981, 4068, 400, 4982, 709, 2653, 3739, 1947, 1398, 128, 1004, 3468, 1948, 2948, 1949, 1950, 1220, 1399, 4983, 4984, 401, 402, 4985, 403, 4986, 404, 405, 1951, 1952, 1005, 1953, 4987, 2477, 4548, 1954, 1955, 4988, 406, 841, 2949, 2950, 2951, 2952, 1528, 1006, 4069, 4070, 3272, 4549, 407, 4989, 2953, 4071, 4990, 1956, 3740, 408, 2654, 58, 2478, 4991, 2954, 4992, 1400, 1957, 4550, 409, 3469, 1958, 59, 4072, 2479, 4993, 1959, 4073, 2955, 410, 1960, 4074, 411, 842, 710, 4075, 2956, 711, 712, 412, 4994, 713, 4551, 1961, 3470, 4995, 4996, 1962, 1963, 1007, 2957, 413, 3741, 4997, 3742, 1401, 2958, 1964, 3743, 1965, 60, 5387, 3628, 3744, 2959, 5388, 1966, 1529, 171, 2960, 3273, 4076, 1008, 4552, 1530, 61, 714, 1531, 2961, 3745, 3746, 3471, 3747, 2962, 4553, 4998, 4077, 4999, 4372, 1009, 2963, 3274, 1532, 715, 1221, 3275, 3472, 5000, 5495, 1010, 1402, 1967, 1968, 1222, 1969, 62, 414, 1970, 1971, 1972, 415, 2655, 5001, 843, 3473, 1973, 2964, 1011, 4373, 716, 416, 417, 4554, 1974, 1975, 5002, 3276, 3748, 3474, 3749, 418, 1223, 1976, 844, 2656, 1977, 5003, 1978, 63, 3277, 3475, 2965, 2657, 3476, 4078, 4555, 1979, 8, 4556, 5004, 3750, 3477, 1980, 1981, 1224, 1982, 1012, 1403, 2658, 5496, 1983, 2659, 419, 717, 3478, 718, 3278, 420, 3751, 1404, 1984, 3479, 4079, 5005, 5006, 1225, 2660, 64, 3752, 5007, 2966, 65, 5008, 3279, 4557, 5009, 5010, 1985, 2967, 3280, 3480, 2661, 2662, 172, 1986, 1405, 2480, 1406, 421, 1013, 2968, 422, 423, 173, 1533, 1987, 2969, 174, 4558, 1988, 1534, 424, 1989, 5389, 4559, 1226, 1227, 1228, 1229, 2663, 3481, 4080, 3753, 66, 5497, 1990, 2664, 3281, 3754, 3482, 3755, 3483, 3282, 1230, 3283, 3484, 3485, 5498, 3284, 1991, 4081, 1992, 1993, 1994, 3285, 1231, 3756, 425, 3757, 1014, 1995, 2665, 4082, 4083, 5011, 3486, 4560, 1535, 426, 3629, 4084, 5499, 4085, 4561, 1232, 427, 428, 3286, 429, 3758, 3759, 1996, 430, 1997, 1407, 1998, 3487, 2970, 431, 845, 1999, 2971, 129, 5012, 5390, 2972, 2000, 2666, 4562, 432, 4563, 5500, 5013, 2001, 719, 4086, 5014, 2002, 4564, 5015, 2003, 433, 5016, 4565, 2004, 1015, 2973, 4087, 2005, 434, 2974, 1233, 2006, 5017, 2007, 3287, 67, 2481, 720, 2975, 5018, 4566, 4088, 4089, 846, 5019, 2667, 435, 5501, 2976, 2977, 2668, 2978, 2008, 4567, 5020, 1234, 5021, 5022, 1408, 5023, 2669, 5024, 1409, 3760, 5025, 3488, 1235, 436, 3761, 2009, 2010, 4568, 2979, 5026, 2011, 2980, 5027, 2981, 5028, 2012, 4569, 1016, 3489, 5502, 3630, 3762, 437, 4090, 5391, 130, 3288, 438, 5029, 3763, 5030, 439, 5031, 68, 2013, 4091, 4374, 2014, 3289, 4570, 3631, 440, 721, 3490, 441, 2015, 2670, 2482, 442, 4571, 2483, 1236, 5032, 3632, 443, 444, 5033, 5034, 1017, 4572, 69, 3764, 4573, 2016, 445, 446, 5392, 5393, 2982, 2671, 2672, 1018, 2983, 2017, 4092, 175, 2673, 176, 3290, 177, 9, 2984, 2985, 2986, 5035, 2987, 2018, 3633, 2988, 2019, 2020, 178, 3491, 2989, 10, 4093, 447, 448, 2021, 847, 4094, 2022, 70, 1019, 179, 2484, 5036, 1237, 5037, 4574, 1536, 2485, 722, 449, 71, 450, 3291, 1238, 723, 1239, 2486, 5038, 4095, 848, 4096, 451, 72, 4575, 2023, 2674, 1410, 4097, 3765, 452, 724, 3492, 3493, 2990, 73, 849, 11, 4576, 2675, 2024, 2991, 2992, 2025, 4098, 4099, 5503, 5039, 74, 3634, 2026, 850, 2993, 2994, 5040, 2995, 2996, 5041, 2027, 2997, 2998, 2028, 2487, 2676, 2029, 2999, 2030, 4100, 3000, 2031, 725, 5042, 3766, 2032, 5394, 3001, 1020, 453, 726, 3494, 2677, 4577, 4101, 454, 75, 1240, 2033, 5043, 2678, 5504, 3002, 2034, 2035, 2036, 2037, 2038, 3495, 455, 1241, 2679, 3003, 2039, 4102, 2680, 4103, 4104, 3004, 2040, 1242, 1243, 4578, 2041, 1021, 76, 1411, 2681, 2042, 5044, 3005, 180, 1022, 5505, 727, 3767, 4105, 131, 2043, 456, 3006, 2488, 2044, 4579, 2489, 3635, 2045, 5045, 3007, 2046, 5046, 728, 5047, 2047, 3636, 77, 3768, 3496, 457, 3497, 3637, 5048, 458, 729, 1244, 730, 3498, 1023, 851, 1024, 78, 4106, 2048, 2049, 1025, 5049, 4375, 5050, 2050, 5051, 3638, 5506, 1245, 3008, 2051, 4107, 2052, 731, 1537, 1246, 3292, 5052, 459, 5507, 460, 4376, 5053, 3009, 5054, 1412, 5055, 2053, 4580, 1247, 3010, 732, 2490, 5056, 4581, 2054, 2055, 2682, 5057, 5058, 5059, 1026, 5395, 2491, 2492, 733, 5060, 1248, 5061, 4582, 5062, 2056, 3499, 3500, 2057, 734, 2683, 2058, 852, 3769, 4108, 2493, 3770, 1027, 2059, 5396, 3501, 5063, 4109, 5064, 5065, 2060, 5066, 2061, 4110, 4583, 2062, 4584, 5067, 3771, 5508, 2063, 2684, 5068, 4377, 461, 2064, 5509, 2065, 2685, 5069, 79, 4111, 1249, 2066, 1028, 2067, 1029, 1030, 735, 2068, 736, 3293, 3011, 3294, 4112, 462, 3012, 737, 1031, 4113, 5070, 1032, 3502, 4585, 2069, 463, 3503, 2070, 4586, 4114, 4115, 1250, 464, 5071, 1033, 3772, 4116, 5072, 1034, 2494, 4410, 738, 465, 4117, 466, 853, 4118, 4119, 739, 2686, 467, 468, 1035, 1538, 2071, 3013, 469, 854, 470, 855, 2072, 5397, 80, 3504, 5510, 471, 5073, 472, 2073, 1036, 2074, 2075, 5074, 2076, 4120, 2077, 5075, 3773, 2078, 2079, 3639, 5511, 5076, 2687, 4587, 1539, 473, 5512, 3295, 3505, 5077, 2080, 2688, 3506, 1037, 5398, 2081, 1038, 5078, 181, 5079, 4121, 474, 3640, 1251, 2082, 1540, 5080, 1039, 3774, 3641, 1413, 4122, 475, 4411, 1414, 5399, 5400, 5401, 3014, 5402, 3507, 1415, 5403, 3508, 5081, 3015, 4123, 1541, 1040, 3016, 1542, 4124, 1041, 3017, 1416, 4125, 2083, 4126, 1417, 4378, 4127, 5082, 476, 1418, 5083, 4128, 3018, 5084, 1252, 1042, 3775, 2084, 4588, 3019, 2495, 3020, 4129, 5085, 477, 3021, 2689, 3642, 1043, 5086, 1419, 5087, 4130, 478, 3643, 1044, 5088, 1253, 2496, 4589, 479, 1420, 3022, 2085, 3023, 5089, 4379, 1421, 1422, 2086, 1423, 1424, 1425, 5090, 1426, 3024, 740, 2690, 5513, 1254, 182, 4131, 4132, 2691, 4133, 2087, 2088, 4134, 3025, 4135, 480, 2089, 1045, 4136, 5514, 741, 3026, 1427, 3509, 4137, 3027, 2090, 481, 3028, 2497, 4590, 1428, 2091, 4380, 856, 1046, 4591, 482, 1429, 5091, 5515, 183, 5516, 184, 4138, 1047, 4139, 2092, 1048, 4140, 483, 4592, 5092, 1430, 4381, 1543, 3029, 5517, 81, 4141, 1431, 742, 2093, 3510, 1049, 2498, 2499, 1432, 3511, 1433, 4142, 484, 4143, 2094, 5093, 2500, 743, 5094, 3512, 2501, 132, 2095, 5095, 2692, 1255, 82, 3776, 83, 3513, 84, 2096, 5096, 2097, 3296, 1256, 485, 2693, 2098, 5518, 486, 2099, 85, 2100, 5097, 2101, 5098, 5099, 2502, 2102, 1050, 5100, 4593, 3297, 3298, 744, 3030, 5101, 5102, 4144, 5103, 4594, 2503, 487, 3299, 2504, 5104, 3031, 4595, 86, 2103, 3777, 2104, 2105, 4382, 2694, 4596, 5105, 1051, 2106, 3032, 5106, 488, 1052, 5107, 2505, 745, 4412, 746, 5404, 1257, 747, 748, 1053, 2107, 3514, 2108, 3515, 2109, 4597, 3033, 4145, 2110, 4598, 2111, 2112, 3516, 87, 5108, 1054, 2506, 749, 4599, 2113, 4600, 750, 3300, 4146, 5109, 3034, 5519, 489, 3035, 4601, 5110, 4147, 3517, 88, 3518, 1258, 5520, 490, 1055, 5521, 3301, 5522, 1056, 1057, 3036, 5111, 4148, 4602, 2114, 3037, 1058, 4149, 857, 3302, 5112, 4150, 89, 2115, 4603, 3519, 2116, 3644, 2117, 751, 2507, 2118, 5113, 4151, 3645, 1259, 5114, 752, 4604, 5115, 1544, 3038, 4152, 5523, 2119, 753, 491, 754, 3778, 5524, 3039, 3040, 1545, 1059, 1434, 5116, 3041, 5117, 3303, 1435, 3042, 1546, 2120, 5118, 2695, 492, 3646, 3779, 2508, 1060, 3780, 5119, 4153, 4383, 3781, 90, 185, 493, 91, 5120, 5121, 3520, 3521, 3304, 3782, 1260, 4154, 3783, 2121, 4155, 2122, 2123, 2124, 2696, 3784, 1261, 3522, 3305, 92, 4605, 4156, 4157, 2125, 4606, 1262, 2126, 3043, 3044, 2697, 2127, 3523, 2128, 2129, 5122, 3785, 3647, 494, 2509, 5525, 3524, 3786, 3306, 186, 2130, 3045, 5123, 5124, 1263, 2698, 3307, 3525, 5125, 2131, 495, 4158, 5126, 3046, 93, 4607, 1264, 2132, 4159, 3526, 496, 3047, 2133, 5127, 3308, 2134, 5128, 2135, 755, 2699, 133, 2136, 2137, 2138, 3787, 2700, 5405, 1436, 3788, 2139, 5129, 497, 4160, 2701, 2140, 4608, 5130, 5131, 1265, 5406, 5132, 2141, 5526, 498, 3789, 858, 5133, 1266, 1547, 3527, 3528, 2142, 4161, 2702, 2143, 3790, 5527, 2510, 1437, 4162, 4163, 756, 1267, 5134, 3791, 94, 4609, 757, 2144, 2145, 5528, 2146, 2147, 2148, 5135, 5136, 758, 1268, 2149, 4610, 1269, 3048, 3049, 3050, 1061, 5137, 2150, 4611, 3309, 3310, 4612, 3311, 1062, 3648, 95, 5138, 2703, 499, 2151, 4164, 2511, 3529, 2704, 5139, 2152, 2153, 2154, 2155, 3051, 500, 96, 2705, 1063, 5140, 2706, 3792, 2707, 2156, 4384, 3530, 4385, 501, 5141, 1270, 97, 502, 5142, 5529, 759, 2157, 3052, 4165, 4166, 3053, 4167, 3054, 4613, 5143, 3055, 5407, 3649, 4168, 1271, 4169, 4614, 859, 503, 4170, 2158, 3531, 1272, 5144, 760, 5145, 5146, 1064, 2159, 5147, 3532, 3650, 504, 3056, 5148, 2160, 5149, 5408, 2161, 5150, 2162, 2163, 98, 1065, 1273, 2164, 4171, 2165, 5151, 5152, 3057, 5530, 5153, 4172, 5154, 4615, 2166, 1066, 1067, 761, 505, 3533, 506, 2708, 3058, 3059, 5155, 2167, 2709, 5531, 860, 2168, 2512, 12, 1068, 3060, 507, 508, 3061, 4173, 5156, 4616, 1438, 2169, 5157, 5158, 3312, 1274, 2710, 3793, 2711, 4174, 99, 2712, 2170, 5409, 5410, 509, 1439, 2171, 2172, 510, 5159, 2713, 3313, 4617, 5160, 2173, 5161, 2513, 3062, 1548, 5162, 1440, 3063, 1069, 5163, 4175, 4618, 5532, 4619, 5533, 1441, 2174, 4176, 4620, 1442, 5164, 861, 2175, 2176, 511, 5165, 762, 5166, 1070, 3651, 3064, 3794, 4177, 1071, 763, 2177, 2514, 1072, 3534, 13, 4178, 1443, 3535, 5534, 3065, 3066, 4621, 100, 5411, 2515, 101, 3795, 1444, 1445, 1446, 5167, 5168, 2178, 1275, 134, 4179, 4180, 1549, 5535, 3652, 102, 3067, 1276, 512, 4622, 4386, 4181, 3068, 14, 4182, 1073, 2179, 764, 5169, 513, 5170, 765, 2180, 2181, 4183, 4623, 1447, 5171, 135, 514, 3069, 5172, 2182, 4624, 5173, 5536, 2516, 3070, 2183, 2714, 3536, 5174, 2184, 2185, 5175, 2186, 5176, 4625, 3071, 515, 1277, 5177, 187, 4626, 516, 1278, 2187, 862, 5537, 2188, 4184, 1279, 4387, 4627, 2189, 5178, 1280, 517, 1281, 5179, 2517, 3314, 4388, 1448, 1282, 3072, 4628, 2715, 1074, 4185, 5180, 5412, 4186, 2190, 3073, 5538, 3796, 4187, 2716, 5181, 4188, 2191, 3074, 5182, 3075, 2518, 3653, 3076, 4189, 3077, 103, 3078, 3537, 518, 2717, 3654, 5183, 5184, 2192, 1449, 3079, 4190, 519, 4629, 3080, 5185, 4191, 3315, 1075, 3655, 3081, 766, 2718, 3316, 520, 767, 768, 769, 770, 3797, 3798, 521, 5186, 3082, 5187, 3083, 3084, 4630, 1283, 2193, 2194, 3085, 3086, 3317, 2195, 5539, 771, 2519, 5188, 3538, 4192, 2196, 3539, 5189, 5190, 5191, 4193, 522, 2719, 3087, 772, 3656, 2197, 3088, 1450, 3089, 2198, 2199, 5192, 4194, 523, 1284, 2720, 524, 2721, 5413, 525, 2722, 2200, 5540, 3799, 3318, 526, 3800, 2723, 2724, 2201, 3540, 3801, 5414, 1076, 1077, 1285, 1550, 5193, 527, 3541, 528, 3319, 5194, 5195, 1451, 3090, 5196, 2202, 529, 3091, 5197, 5198, 5199, 5200, 5201, 2203, 1452, 3542, 5415, 5202, 5203, 5204, 2204, 3092, 863, 3093, 3657, 3094, 15, 1453, 3095, 3096, 1551, 2205, 3658, 5205, 4389, 5541, 4631, 3659, 3660, 5206, 530, 3661, 531, 4632, 3802, 4633, 532, 2206, 4634, 2207, 5542, 4635, 4195, 2208, 3320, 4636, 4196, 5207, 3543, 104, 2209, 2520, 4637, 1552, 3097, 2210, 864, 2211, 4197, 2212, 2213, 2214, 2215, 188, 1078, 533, 4638, 5543, 2725, 1079, 1553, 2216, 5208, 4198, 4639, 2217, 5209, 4199, 1554, 2218, 4640, 4200, 2219, 534, 3803, 16, 4201, 3098, 4202, 4390, 2220, 4641, 3099, 4203, 4204, 1454, 3100, 2521, 1455, 4205, 4413, 5210, 1286, 2221, 5416, 3101, 4206, 1456, 5211, 105, 2222, 5212, 1080, 2223, 5213, 2522, 773, 535, 3804, 2224, 3102, 5214, 2225, 774, 2226, 4207, 5215, 3321, 4208, 5216, 5217, 5218, 4642, 2726, 3322, 5417, 2727, 3103, 3323, 2227, 536, 2523, 775, 5219, 3324, 4643, 5220, 5221, 2228, 5222, 1457, 3104, 4209, 3105, 5223, 4644, 537, 4210, 4211, 2524, 1287, 5544, 4212, 1081, 5545, 5224, 4645, 3325, 4213, 5225, 5226, 3106, 538, 2229, 5227, 1082, 2230, 2231, 2525, 4214, 2232, 5228, 539, 1458, 2728, 4646, 3107, 4215, 5229, 4216, 2729, 3326, 3805, 540, 3327, 5230, 5231, 541, 5232, 1083, 2233, 3108, 2234, 2526, 3328, 2235, 3544, 5233, 4217, 1459, 3545, 2236, 5234, 3109, 1084, 2237, 5546, 5235, 3329, 3546, 1288, 5236, 1289, 2730, 3110, 4647, 1085, 2238, 542, 1290, 2731, 3111, 1086, 5237, 3112, 189, 3113, 2527, 2239, 865, 3114, 5238, 3547, 543, 1291, 2240, 2732, 4391, 5418, 106, 2528, 1292, 2241, 4218, 3806, 4219, 3330, 5239, 544, 2529, 2242, 866, 3331, 4220, 3115, 2530, 2243, 2244, 5547, 3662, 3116, 5240, 3117, 776, 1293, 1294, 2733, 5241, 2245, 545, 2246, 2247, 2248, 1087, 2249, 1088, 1555, 5242, 2250, 5548, 1460, 4221, 2251, 1089, 4648, 5419, 5243, 3548, 17, 4649, 5549, 5244, 867, 2734, 4222, 1090, 3118, 5550, 546, 1461, 3332, 4650, 1091, 3119, 4651, 5551, 2252, 4223, 547, 136, 548, 4224, 5245, 2253, 2254, 2735, 5246, 2255, 777, 2531, 778, 2256, 2257, 107, 3120, 2258, 2259, 1295, 3807, 108, 2260, 3549, 2261, 5420, 3808, 2736, 2262, 549, 2532, 2533, 4225, 4652, 1462, 550, 4653, 5421, 1296, 5247, 2737, 5248, 4226, 3809, 5249, 1092, 4227, 3121, 4228, 1093, 551, 1463, 3550, 3663, 5250, 2263, 5251, 2264, 3122, 1094, 2265, 190, 2266, 2267, 5252, 1464, 2268, 4229, 3123, 5253, 4230, 2269, 2270, 3124, 2534, 1297, 3551, 4231, 4232, 552, 5254, 4233, 2271, 3125, 3552, 5255, 5256, 2272, 779, 1298, 3333, 2738, 1299, 2739, 2273, 3810, 5257, 4654, 5552, 3811, 3334, 4655, 1300, 5258, 4656, 4234, 109, 2274, 3553, 2535, 5259, 3335, 4657, 5260, 3126, 5422, 4658, 553, 554, 1095, 2740, 4659, 5423, 2275, 2536, 1301, 2537, 2741, 1302, 868, 2276, 4235, 555, 4392, 556, 1303, 2277, 1465, 557, 3554, 5553, 2538, 3812, 3664, 2278, 2742, 5261, 5424, 4236, 3555, 1096, 3665, 2279, 4237, 2280, 1304, 558, 2281, 4393, 1305, 3813, 2539, 3556, 4660, 559, 4238, 191, 869, 1556, 2282, 2283, 2540, 2284, 3666, 2285, 780, 3814, 3557, 2286, 3558, 2287, 2288, 2289, 560, 2290, 4239, 3127, 3128, 3336, 1306, 4661, 2291, 1097, 4414, 3667, 5262, 3559, 3560, 2292, 2293, 1098, 2541, 2294, 3561, 4240, 3562, 5263, 2295, 5264, 3668, 2542, 2296, 2543, 3563, 3129, 2743, 1307, 4662, 3130, 781, 2297, 2298, 4663, 2299, 2300, 1308, 2301, 5265, 3564, 4241, 2744, 3815, 1309, 4664, 2745, 3131, 1310, 2302, 2303, 4665, 5266, 2304, 3337, 4242, 3132, 3133, 3134, 4666, 2305, 5267, 3135, 3338, 2746, 110, 2306, 2307, 111, 2308, 561, 4243, 3136, 2747, 2748, 3816, 2749, 2750, 1311, 3669, 2309, 5268, 3339, 2751, 2752, 870, 3817, 4667, 4668, 2310, 3565, 3340, 2311, 4244, 4245, 4246, 562, 2312, 2313, 4247, 4248, 3566, 3567, 1466, 1467, 5269, 5270, 2753, 3818, 4249, 3670, 1468, 4250, 1312, 5271, 2754, 3137, 1469, 2755, 3568, 4251, 2314, 3341, 5272, 4669, 3569, 4252, 4670, 1313, 1099, 782, 3570, 112, 1314, 4415, 1100, 5273, 4253, 2756, 3138, 5274, 4254, 4255, 4671, 4256, 871, 1315, 3139, 3819, 5275, 3571, 4672, 563, 4257, 2757, 5425, 2315, 1101, 3572, 3820, 2544, 4394, 3140, 4673, 1102, 3573, 5554, 113, 114, 4258, 1103, 5276, 4259, 192, 3821, 3822, 5277, 1316, 3671, 1470, 4260, 2316, 4261, 4674, 4262, 3141, 3142, 3143, 3574, 2317, 4263, 5278, 1317, 2318, 3823, 1318, 1319, 3575, 1320, 2319, 5279, 2320, 872, 5555, 115, 5280, 3144, 2321, 2545, 5281, 2322, 2758, 3672, 2323, 4264, 2324, 2325, 2326, 564, 2327, 2328, 5556, 193, 2759, 4265, 1104, 5282, 2329, 2330, 3145, 3824, 2331, 4266, 4267, 5557, 4268, 4269, 3825, 5283, 2332, 2760, 4270, 1321, 3342, 2761, 565, 1471, 4271, 3146, 2333, 2546, 3673, 4272, 3674, 3147, 4273, 5284, 2334, 5285, 2335, 566, 116, 1322, 567, 3148, 4675, 568, 4676, 569, 4677, 5286, 3576, 570, 3577, 4274, 4275, 4276, 4277, 1557, 2336, 18, 1323, 2337, 1105, 2338, 3826, 2339, 3827, 19, 2340, 2547, 1324, 2341, 783, 117, 784, 4278, 3149, 571, 2342, 2343, 2344, 4279, 572, 4280, 2345, 4395, 4281, 2346, 3675, 873, 4678, 5287, 2347, 2762, 3828, 2763, 2348, 3829, 3830, 137, 573, 2349, 2350, 574, 2764, 5288, 3831, 1472, 575, 2765, 3343, 5289, 2351, 1325, 1106, 2352, 3150, 2353, 2766, 576, 3832, 3833, 3344, 2354, 577, 3151, 3345, 3152, 4282, 4283, 2767, 5290, 5291, 4284, 2355, 1558, 2356, 4285, 3834, 5292, 4679, 1559, 3578, 3676, 1107, 5558, 4286, 2357, 5293, 194, 2358, 5426, 2359, 3579, 578, 1108, 2360, 3580, 4287, 1473, 3153, 3346, 5427, 1109, 579, 580, 1326, 3835, 5559, 581, 4288, 2768, 785, 2361, 5294, 3581, 2769, 2770, 4289, 2362, 3347, 786, 4680, 1560, 874, 5295, 1474, 2771, 2548, 2772, 582, 5560, 1327, 1328, 5296, 4681, 3154, 5297, 2773, 3677, 3348, 3582, 5298, 5299, 4290, 1475, 5300, 195, 5301, 3349, 5302, 5561, 583, 3836, 2363, 787, 3350, 3351, 5303, 2774, 1561, 5304, 5562, 5305, 2549, 4682, 2364, 5563, 3837, 5306, 5564, 3352, 3155, 5307, 3156, 788, 3583, 5308, 3838, 4683, 1476, 3678, 584, 118, 3584, 585, 586, 2365, 196, 3157, 4291, 4292, 587, 2775, 4293, 2366, 3158, 2367, 5309, 588, 5310, 1477, 4294, 2368, 5311, 1110, 119, 4295, 5312, 3353, 5313, 5314, 4296, 1562, 5315, 20, 789, 138, 5316, 2369, 1329, 5317, 790, 5318, 2776, 4297, 197, 2777, 589, 3159, 2370, 4396, 791, 5319, 3160, 5428, 3839, 3840, 4298, 2778, 590, 5320, 591, 2371, 592, 120, 1563, 3585, 1111, 3679, 3354, 1112, 2550, 3161, 4299, 593, 3355, 1478, 3162, 3163, 5321, 2551, 1479, 4300, 4397, 792, 3164, 3841, 3842, 5322, 4684, 4685, 3165, 3356, 3843, 4686, 1330, 4687, 4688, 5323, 1331, 2372, 4301, 2373, 4302, 2374, 5429, 5565, 5566, 2375, 2376, 2377, 3166, 5430, 3167, 2378, 2552, 198, 3357, 1480, 4303, 5324, 4304, 5325, 3844, 5326, 2553, 3358, 121, 2554, 793, 3680, 4305, 4306, 594, 5327, 4307, 4689, 3168, 4308, 2379, 4309, 4310, 4311, 5328, 1564, 2380, 4312, 4313, 2381, 1113, 3681, 4690, 4691, 4692, 1114, 3359, 4314, 2779, 3360, 4315, 3845, 1332, 1115, 4693, 4694, 595, 2555, 4316, 2556, 1333, 5329, 2382, 4695, 4317, 3169, 3170, 1334, 5330, 2383, 3361, 4318, 4319, 4320, 4321, 3362, 3171, 5331, 5567, 5568, 1335, 1336, 5332, 2384, 5333, 4322, 794, 1116, 1117, 3172, 4696, 2385, 1337, 199, 596, 2386, 2387, 597, 598, 795, 2388, 5334, 599, 5335, 2389, 2390, 5336, 3173, 4323, 5337, 600, 4416, 1118, 2780, 2557, 796, 3846, 5431, 601, 2391, 2781, 797, 3174, 602, 2392, 3586, 4324, 3175, 2393, 4697, 1481, 122, 5338, 3176, 4325, 3847, 3177, 603, 5339, 1338, 5340, 1119, 1120, 2394, 2558, 4698, 798, 2395, 200, 604, 3587, 2396, 201, 4326, 799, 4398, 4699, 5341, 4700, 1121, 605, 4327, 1482, 4399, 4400, 4328, 4329, 4330, 606, 3682, 3588, 607, 5342, 5343, 5344, 1122, 4331, 4701, 4702, 5345, 2397, 875, 2398, 4703, 1339, 2399, 5346, 5347, 2400, 1123, 2401, 800, 3683, 2782, 3848, 801, 3589, 2402, 608, 609, 1483, 3590, 610, 5348, 611, 2403, 3684, 2404, 4332, 876, 3849, 3178, 3363, 1484, 612, 3850, 4333, 5349, 3179, 3591, 4334, 3364, 2405, 3180, 613, 2406, 2407, 2408, 3365, 3366, 2409, 4335, 4336, 4337, 877, 1340, 1124, 3367, 4338, 1565, 1125, 123, 2410, 3851, 802, 4339, 4704, 4705, 2411, 2783, 2559, 1485, 1126, 3852, 4340, 4341, 4342, 3592, 4343, 1341, 878, 1127, 1486, 879, 880, 4401, 5350, 5351, 2412, 2413, 2414, 2415, 3181, 2416, 2560, 4344, 5352, 4345, 4346, 2784, 4706, 881, 5353, 614, 4347, 3368, 139, 1342, 2561, 3182, 1343, 2417, 3685, 5354, 5355, 615, 3593, 5569, 616, 2418, 3183, 617, 4348, 4707, 5570, 3184, 4349, 4708, 21, 4709, 4710, 3369, 2562, 618, 2785, 5356, 1344, 4711], +) + + +def row_to_municipality(row: List[str]) -> Municipality: + """Reads one dataset row as a municipality. + """ + return Municipality(code=row[2], name=row[1], state_code=row[0]) + + +def get_municipalities(state_code: Optional[str] = None) -> List[Municipality]: + """Returns Brazilian municipalities published by the IBGE, optionally filtered by state. + + If `stateCode` is provided, only municipalities of that state are returned. If it is + omitted, every municipality of every state is returned, sorted with `localeCompare` in the + "pt-BR" locale so accented names land where a Brazilian reader expects them. Every per-state + list is sorted the same way. + + Only an omitted (or `undefined`) `stateCode` asks for the full list: any other value that is + not a known state code, `null` and `""` included, returns `[]`. + + The state code is matched exactly, case included: `getMunicipalities("sp")` returns `[]` where + `getMunicipalities("SP")` returns the 645 São Paulo municipalities. + + @see Official: https://servicodados.ibge.gov.br/api/docs/localidades + """ + municipalities = [] + rows = data_all(MUNICIPALITIES) + if (state_code is not None): + rows = data_rows(MUNICIPALITIES, state_code) + for row in rows: + municipalities.append(row_to_municipality(row)) + return municipalities diff --git a/spec/bridge/out/python/brutils_bridge/is_valid_cnpj.py b/spec/bridge/out/python/brutils_bridge/is_valid_cnpj.py new file mode 100644 index 000000000..2a62a73d4 --- /dev/null +++ b/spec/bridge/out/python/brutils_bridge/is_valid_cnpj.py @@ -0,0 +1,136 @@ +# Code generated from spec/bridge/source/is-valid-cnpj.ts. DO NOT EDIT. +"""`isValidCnpj`, written once.""" + +from dataclasses import dataclass +from typing import Any, List, Optional + +from .runtime import ( + CharClass, + PatternStep, + any_failed_with, + as_string, + class_has, + code_at, + data_all, + data_rows, + first_success, + http_get, + is_list, + is_number, + is_truthy, + js_trim, + json_int, + json_is_true, + json_string, + json_truthy, + keep_class, + list_has, + make_dataset, + pad_start, + pattern_test, + start_all, +) + +class0: CharClass = ((0x30, 0x39), (0x41, 0x5a),) +class1: CharClass = ((0x9, 0xd), (0x20, 0x20), (0x2d, 0x2f), (0xa0, 0xa0), (0x1680, 0x1680), (0x2000, 0x200a), (0x2028, 0x2029), (0x202f, 0x202f), (0x205f, 0x205f), (0x3000, 0x3000), (0xfeff, 0xfeff),) +class2: CharClass = ((0x30, 0x39),) +class3: CharClass = ((0x41, 0x5a),) +class4: CharClass = ((0x30, 0x39), (0x41, 0x5a), (0x61, 0x7a),) + +PATTERN_ALPHANUMERIC_FORMAT = ( + PatternStep(class0, 2, 2, False), + PatternStep(class1, 0, -1, False), + PatternStep(class0, 3, 3, False), + PatternStep(class1, 0, -1, False), + PatternStep(class0, 3, 3, False), + PatternStep(class1, 0, -1, False), + PatternStep(class0, 4, 4, False), + PatternStep(class1, 0, -1, False), + PatternStep(class2, 2, 2, False), +) + +PATTERN_NUMERIC_FORMAT = ( + PatternStep(class2, 2, 2, False), + PatternStep(class1, 0, -1, False), + PatternStep(class2, 3, 3, False), + PatternStep(class1, 0, -1, False), + PatternStep(class2, 3, 3, False), + PatternStep(class1, 0, -1, False), + PatternStep(class2, 4, 4, False), + PatternStep(class1, 0, -1, False), + PatternStep(class2, 2, 2, False), +) + +FIRST_DIGIT_WEIGHTS = [5, 4, 3, 2, 9, 8, 7, 6, 5, 4, 3, 2] +SECOND_DIGIT_WEIGHTS = [6, 5, 4, 3, 2, 9, 8, 7, 6, 5, 4, 3, 2] + + + + + +@dataclass +class IsValidCnpjOptions: + """Options of `isValidCnpj`.""" + + # Which CNPJ format to accept: `1` numeric only, `2` alphanumeric (default: `1`). + version: Optional[int] = None + + + + + +def is_valid_cnpj(cnpj: Any, options: Optional[IsValidCnpjOptions] = None) -> bool: + """Validates if a CNPJ (Cadastro Nacional da Pessoa Jurídica) is valid. + + Supports both numeric (version 1) and alphanumeric (version 2) CNPJ formats, and accepts the + usual mask characters (`.`, `-`, `/`) and whitespace around and between groups. + """ + options_version = -1 + if options is not None and options.version is not None: + options_version = options.version + if not isinstance(cnpj, str): + return False + trimmed = js_trim(cnpj) + if (options_version == 2): + cleaned = keep_class(class4, cnpj).upper() + if class_has(class3, cleaned): + if not pattern_test(PATTERN_ALPHANUMERIC_FORMAT, trimmed.upper()): + return False + return has_valid_checksum(cleaned) + numeric = keep_class(class2, cnpj) + if not pattern_test(PATTERN_NUMERIC_FORMAT, trimmed): + return False + if is_repeated(numeric): + return False + return has_valid_checksum(numeric) + + +def check_digit(base: str, weights: List[int]) -> int: + """Computes one CNPJ check digit from the base and its weight vector. + """ + sum = 0 + for index in range(0, len(weights)): + sum = (sum + ((code_at(base, index) - 48) * weights[index])) + remainder = (sum % 11) + if (remainder < 2): + return 0 + return (11 - remainder) + + +def has_valid_checksum(cnpj: str) -> bool: + """Whether both check digits of a sanitized 14 character CNPJ match its base. + """ + if ((code_at(cnpj, 12) - 48) != check_digit(cnpj, FIRST_DIGIT_WEIGHTS)): + return False + return ((code_at(cnpj, 13) - 48) == check_digit(cnpj, SECOND_DIGIT_WEIGHTS)) + + +def is_repeated(value: str) -> bool: + """Whether every character of the value is the same one. + """ + if (len(value) == 0): + return False + for index in range(1, len(value)): + if (code_at(value, index) != code_at(value, 0)): + return False + return True diff --git a/spec/bridge/out/python/brutils_bridge/runtime.py b/spec/bridge/out/python/brutils_bridge/runtime.py new file mode 100644 index 000000000..ed312c95a --- /dev/null +++ b/spec/bridge/out/python/brutils_bridge/runtime.py @@ -0,0 +1,322 @@ +"""The portable runtime for the Python target. + +Everything the generated code needs that is not plain syntax lives here. The compiled character +classes and patterns are passed in as data, so this file never changes when a utility does. +""" + +import json +import os +import queue +import re +import threading +import time +import urllib.error +import urllib.request +from typing import Any, List, Optional, Sequence, Tuple + +CharClass = Sequence[Tuple[int, int]] + +# The code points JavaScript's `trim()` strips. Python's `str.strip()` is a different set, so +# the set is spelled out here rather than inherited from the host. +_JS_WHITESPACE = frozenset( + [0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x20, 0xA0, 0x1680, 0x2028, 0x2029, 0x202F, 0x205F, 0x3000, 0xFEFF] + + list(range(0x2000, 0x200B)) +) + + +class PatternStep: + """One step of a compiled pattern: repeat a class between `min` and `max` times.""" + + __slots__ = ("char_class", "min", "max", "capture") + + def __init__(self, char_class: CharClass, minimum: int, maximum: int, capture: bool) -> None: + self.char_class = char_class + self.min = minimum + self.max = maximum + self.capture = capture + + +def in_class(char_class: CharClass, code: int) -> bool: + """Whether a code point belongs to a class.""" + for start, end in char_class: + if start <= code <= end: + return True + + return False + + +def code_at(value: str, index: int) -> int: + """Reads one code unit, or -1 when the index is out of range.""" + if index < 0 or index >= len(value): + return -1 + + return ord(value[index]) + + +def class_has(char_class: CharClass, value: str) -> bool: + """Whether any character of the value belongs to the class.""" + for char in value: + if in_class(char_class, ord(char)): + return True + + return False + + +def keep_class(char_class: CharClass, value: str) -> str: + """Keeps only the characters of the value that belong to the class.""" + return "".join(char for char in value if in_class(char_class, ord(char))) + + +def pattern_test(steps: Sequence[PatternStep], value: str) -> bool: + """Runs a compiled pattern against the whole value, greedily and without backtracking.""" + index = 0 + + for step in steps: + count = 0 + + while ( + (step.max < 0 or count < step.max) + and index < len(value) + and in_class(step.char_class, ord(value[index])) + ): + index += 1 + count += 1 + + if count < step.min: + return False + + return index == len(value) + + +def js_trim(value: str) -> str: + """Strips the code points JavaScript's `trim()` strips.""" + start = 0 + end = len(value) + + while start < end and ord(value[start]) in _JS_WHITESPACE: + start += 1 + while end > start and ord(value[end - 1]) in _JS_WHITESPACE: + end -= 1 + + return value[start:end] + + +def pad_start(value: str, length: int, filler: str) -> str: + """Left pads the value with a filler up to a length.""" + return value.rjust(length, filler) + + +def as_string(value: Any) -> str: + """Reads a value as a string the way JavaScript's `String(value)` does.""" + if isinstance(value, str): + return value + if value is True: + return "true" + if value is False: + return "false" + if value is None: + return "null" + if isinstance(value, int): + return str(value) + if isinstance(value, float): + return str(int(value)) if value.is_integer() else str(value) + + try: + return str(value) + except Exception: # noqa: BLE001 - a value with no string form reads as empty, as in JavaScript + return "" + + +def is_truthy(value: Any) -> bool: + """Reads an optional flag the way JavaScript reads truthiness.""" + return bool(value) + + +def list_get(values: List[Any], index: int) -> Any: + """Reads one element, or None when the index is out of range.""" + if index < 0 or index >= len(values): + return None + + return values[index] + + +class Dataset: + """A dataset: the rows in the baked full order, and the rows of each key.""" + + __slots__ = ("all", "by_key") + + def __init__(self, rows, groups, full_order): + self.all = [rows[index] for index in full_order] + self.by_key = {key: [rows[index] for index in indexes] for key, indexes in groups} + + +def make_dataset(rows, groups, full_order): + """Materialises a dataset, resolving both orders once.""" + return Dataset(rows, groups, full_order) + + +def data_all(table): + """Every row of a dataset, in the baked full order.""" + return table.all + + +def data_rows(table, key): + """The rows whose first column is the key given, empty when the key is unknown.""" + return table.by_key.get(key, []) + + +class HttpResponse: + """What a provider answered: the HTTP status, whether it counts as a success, and the body.""" + + __slots__ = ("status", "ok", "body") + + def __init__(self, status, ok, body): + self.status = status + self.ok = ok + self.body = body + + +def _http_target(url): + """The origin every request is sent to instead of its own, when one is set. + + This is the conformance hook: the cross language replay points all seven targets at one + local server, the same way the JavaScript suite points `fetch` at a mock. + """ + base = os.environ.get("BRUTILS_BRIDGE_HTTP_ORIGIN", "") + + if base == "": + return url + + return base + "/" + re.sub(r"^https?://", "", url) + + +def http_get(url, retries, retry_delay_ms): + """Performs an HTTP GET, retrying a transient transport failure with a linear backoff.""" + target = _http_target(url) + attempt = 0 + + while True: + try: + with urllib.request.urlopen(target, timeout=15) as response: + raw = response.read() + status = response.status + except urllib.error.HTTPError as error: + raw = error.read() + status = error.code + except Exception: + if attempt >= retries: + return HttpResponse(0, False, None) + + time.sleep(retry_delay_ms * (attempt + 1) / 1000) + attempt += 1 + continue + + try: + body = json.loads(raw.decode("utf-8")) + except Exception: + body = None + + return HttpResponse(status, 200 <= status < 300, body) + + +def is_number(value): + """Whether the caller handed a number where a string or a number was declared.""" + return isinstance(value, (int, float)) and not isinstance(value, bool) + + +def is_list(value): + """Whether a value is a list.""" + return isinstance(value, (list, tuple)) + + +def list_has(items, value): + """Whether a list holds a value.""" + return value in items + + +def _json_field(body, key): + """Reads one field of a JSON body, treating anything that is not an object as empty.""" + if not isinstance(body, dict): + return None + + return body.get(key) + + +def json_string(body, key): + """Reads a string field of a JSON body, answering "" when it is missing or not a string.""" + found = _json_field(body, key) + + return found if isinstance(found, str) else "" + + +def json_int(body, key): + """Reads an integer field of a JSON body, answering -1 when it is missing or not a number.""" + found = _json_field(body, key) + + if isinstance(found, bool) or not isinstance(found, (int, float)): + return -1 + + return int(found) + + +def json_truthy(body, key): + """Whether a field of a JSON body is truthy, the way JavaScript reads truthiness.""" + return bool(_json_field(body, key)) + + +def json_is_true(body, key): + """Whether a field of a JSON body is exactly True.""" + return _json_field(body, key) is True + + +class Attempts: + """The running attempts of a race, and what each one ended with.""" + + __slots__ = ("settled", "total", "outcomes") + + def __init__(self, total): + self.settled = queue.Queue() + self.total = total + self.outcomes = [] + + +def _kinds_of(error): + """The error name and every name it inherits from, which is what a failure is matched on.""" + return [kind.__name__ for kind in type(error).__mro__ if kind is not object] + + +def start_all(run, items, argument): + """Starts one attempt per item, all at once. + + This is the only concurrency primitive of the portable subset. Python has no promise to + colour a function with, so the work goes on threads and the caller simply waits. + """ + attempts = Attempts(len(items)) + + for item in items: + def work(item=item): + try: + attempts.settled.put((True, run(item, argument), [])) + except Exception as error: # noqa: BLE001 + attempts.settled.put((False, None, _kinds_of(error))) + + threading.Thread(target=work, daemon=True).start() + + return attempts + + +def first_success(attempts): + """The value of the first attempt that succeeds, or None once every attempt has failed.""" + while len(attempts.outcomes) < attempts.total: + outcome = attempts.settled.get() + attempts.outcomes.append(outcome) + + if outcome[0]: + return outcome[1] + + return None + + +def any_failed_with(attempts, kind): + """Whether any attempt failed with a given error kind.""" + return any(not ok and kind in kinds for ok, _value, kinds in attempts.outcomes) diff --git a/spec/bridge/out/python/conformance.py b/spec/bridge/out/python/conformance.py new file mode 100644 index 000000000..898964d01 --- /dev/null +++ b/spec/bridge/out/python/conformance.py @@ -0,0 +1,223 @@ +# Code generated by spec/bridge/conformance/drivers.ts. DO NOT EDIT. +"""Replays the recorded tables against the generated Python.""" + +import sys + +import brutils_bridge as bridge + +TARGET = "python" + +NOT_A_LIST = {"!null": None, "!string": "viacep", "!number": 5, "!object": {}, "!boolean": True} + + +def unescape(value): + """Reads back the three characters the table format escapes.""" + return value.replace("\\t", "\t").replace("\\n", "\n").replace("\\\\", "\\") + + +def runs(targets): + """Whether this target can express the call a row describes.""" + return targets == "*" or TARGET in targets.split("|") + + +def report(fn, actual, expected, tally): + """Counts one comparison, and shows the first few that disagree.""" + if actual == expected: + tally[0] += 1 + + return + + tally[1] += 1 + + if tally[1] <= 3: + print(f"FAIL {fn} expected {expected[:120]!r} got {actual[:120]!r}", file=sys.stderr) + + +def renderGetAddressInfoByCepAddressInfo(value): + return "|".join([value.cep, value.state, value.city, value.neighborhood, value.street]) + + +def renderGetMunicipalitiesMunicipality(value): + return "|".join([value.code, value.name, value.state_code]) + + +def renderListGetMunicipalitiesMunicipality(items): + return "\n".join([str(len(items))] + [renderGetMunicipalitiesMunicipality(item) for item in items]) + + +def check_format_cnpj(): + """Replays what `formatCnpj` answers.""" + tally = [0, 0, 0] + + with open("../../conformance/recorded/format-cnpj.tsv", encoding="utf-8") as handle: + rows = handle.read().split("\n")[1:] + + for line in rows: + if line == "": + continue + + parts = line.split("\t") + + if not runs(parts[0]): + tally[2] += 1 + + continue + + argument0 = (int(unescape(parts[1])) if parts[2] == "number" else unescape(parts[1])) + options = bridge.FormatCnpjOptions() + given = False + + if parts[3] != "": + options.pad = parts[3] == "1" + given = True + if parts[4] != "": + options.version = int(parts[4]) + given = True + if parts[5] != "": + options.obfuscate = parts[5] == "1" + given = True + + try: + actual = bridge.format_cnpj(argument0, options if given else None) + except Exception as error: # noqa: BLE001 + actual = "!" + type(error).__name__ + "|" + str(error) + + report("formatCnpj", actual, unescape(parts[6]), tally) + + return tally + + +def check_get_address_info_by_cep(): + """Replays what `getAddressInfoByCep` answers.""" + tally = [0, 0, 0] + + with open("../../conformance/recorded/get-address-info-by-cep.tsv", encoding="utf-8") as handle: + rows = handle.read().split("\n")[1:] + + for line in rows: + if line == "": + continue + + parts = line.split("\t") + + if not runs(parts[0]): + tally[2] += 1 + + continue + + argument0 = (int(unescape(parts[1])) if parts[2] == "number" else unescape(parts[1])) + options = bridge.GetAddressInfoByCepOptions() + given = False + + if parts[3] != "": + options.providers = NOT_A_LIST[parts[3]] if parts[3] in NOT_A_LIST else ([] if parts[3] == "[]" else parts[3].split("|")) + given = True + + try: + actual = renderGetAddressInfoByCepAddressInfo(bridge.get_address_info_by_cep(argument0, options if given else None)) + except Exception as error: # noqa: BLE001 + actual = "!" + type(error).__name__ + "|" + str(error) + + report("getAddressInfoByCep", actual, unescape(parts[4]), tally) + + return tally + + +def check_get_municipalities(): + """Replays what `getMunicipalities` answers.""" + tally = [0, 0, 0] + + with open("../../conformance/recorded/get-municipalities.tsv", encoding="utf-8") as handle: + rows = handle.read().split("\n")[1:] + + for line in rows: + if line == "": + continue + + parts = line.split("\t") + + if not runs(parts[0]): + tally[2] += 1 + + continue + + argument0 = unescape(parts[2]) if parts[1] == "1" else None + + try: + actual = renderListGetMunicipalitiesMunicipality(bridge.get_municipalities(argument0)) + except Exception as error: # noqa: BLE001 + actual = "!" + type(error).__name__ + "|" + str(error) + + report("getMunicipalities", actual, unescape(parts[3]), tally) + + return tally + + +def check_is_valid_cnpj(): + """Replays what `isValidCnpj` answers.""" + tally = [0, 0, 0] + + with open("../../conformance/recorded/is-valid-cnpj.tsv", encoding="utf-8") as handle: + rows = handle.read().split("\n")[1:] + + for line in rows: + if line == "": + continue + + parts = line.split("\t") + + if not runs(parts[0]): + tally[2] += 1 + + continue + + argument0 = (int(unescape(parts[1])) if parts[2] == "number" else unescape(parts[1])) + options = bridge.IsValidCnpjOptions() + given = False + + if parts[3] != "": + options.version = int(parts[3]) + given = True + + try: + actual = ("true" if bridge.is_valid_cnpj(argument0, options if given else None) else "false") + except Exception as error: # noqa: BLE001 + actual = "!" + type(error).__name__ + "|" + str(error) + + report("isValidCnpj", actual, unescape(parts[4]), tally) + + return tally + + +FAILED = 0 + +TALLY = check_format_cnpj() +FAILED += TALLY[1] +print( + f"{TARGET}: formatCnpj {TALLY[0]}/{TALLY[0] + TALLY[1]} matched" + + ("" if TALLY[2] == 0 else f" ({TALLY[2]} not expressible)") +) + +TALLY = check_get_address_info_by_cep() +FAILED += TALLY[1] +print( + f"{TARGET}: getAddressInfoByCep {TALLY[0]}/{TALLY[0] + TALLY[1]} matched" + + ("" if TALLY[2] == 0 else f" ({TALLY[2]} not expressible)") +) + +TALLY = check_get_municipalities() +FAILED += TALLY[1] +print( + f"{TARGET}: getMunicipalities {TALLY[0]}/{TALLY[0] + TALLY[1]} matched" + + ("" if TALLY[2] == 0 else f" ({TALLY[2]} not expressible)") +) + +TALLY = check_is_valid_cnpj() +FAILED += TALLY[1] +print( + f"{TARGET}: isValidCnpj {TALLY[0]}/{TALLY[0] + TALLY[1]} matched" + + ("" if TALLY[2] == 0 else f" ({TALLY[2]} not expressible)") +) + +if FAILED > 0: + sys.exit(1) diff --git a/spec/bridge/out/ruby/conformance.rb b/spec/bridge/out/ruby/conformance.rb new file mode 100644 index 000000000..c32ac4533 --- /dev/null +++ b/spec/bridge/out/ruby/conformance.rb @@ -0,0 +1,218 @@ +# frozen_string_literal: true + +# Code generated by spec/bridge/conformance/drivers.ts. DO NOT EDIT. + +require_relative 'lib/brazilian_utils_bridge/format_cnpj' +require_relative 'lib/brazilian_utils_bridge/get_address_info_by_cep' +require_relative 'lib/brazilian_utils_bridge/get_municipalities' +require_relative 'lib/brazilian_utils_bridge/is_valid_cnpj' + +TARGET = 'ruby' + +NOT_A_LIST = { "!null" => nil, "!string" => 'viacep', "!number" => 5, "!object" => {}, "!boolean" => true }.freeze + +# Reads back the three characters the table format escapes. +def unescape(value) + value.gsub('\\t', "\t").gsub('\\n', "\n").gsub('\\\\', '\\') +end + +# Whether this target can express the call a row describes. +def runs(targets) + targets == '*' || targets.split('|').include?(TARGET) +end + +# Counts one comparison, and shows the first few that disagree. +def report(fn, actual, expected, tally) + if actual == expected + tally[0] += 1 + + return + end + + tally[1] += 1 + + warn("FAIL #{fn} expected #{expected[0, 120].inspect} got #{actual[0, 120].inspect}") if tally[1] <= 3 +end + +def render_get_address_info_by_cep_address_info(value) + [value.cep, value.state, value.city, value.neighborhood, value.street].join('|') +end + +def render_get_municipalities_municipality(value) + [value.code, value.name, value.state_code].join('|') +end + +def render_list_get_municipalities_municipality(items) + ([items.length.to_s] + items.map { |item| render_get_municipalities_municipality(item) }).join("\n") +end + +# Replays what `formatCnpj` answers. +def check_format_cnpj + tally = [0, 0, 0] + + File.read('../../conformance/recorded/format-cnpj.tsv', encoding: 'UTF-8').split("\n").drop(1).each do |line| + next if line.empty? + + parts = line.split("\t", -1) + + unless runs(parts[0]) + tally[2] += 1 + + next + end + + argument0 = (parts[2] == 'number' ? unescape(parts[1]).to_i : unescape(parts[1])) + options = BrazilianUtilsBridge::FormatCnpj::FormatCnpjOptions.new + given = false + + unless parts[3].empty? + options.pad = parts[3] == '1' + given = true + end + + unless parts[4].empty? + options.version = parts[4].to_i + given = true + end + + unless parts[5].empty? + options.obfuscate = parts[5] == '1' + given = true + end + + begin + actual = BrazilianUtilsBridge::FormatCnpj.format_cnpj(argument0, given ? options : nil) + rescue StandardError => e + actual = "!#{e.class.name.split('::').last}|#{e.message}" + end + + report('formatCnpj', actual, unescape(parts[6]), tally) + end + + tally +end + +# Replays what `getAddressInfoByCep` answers. +def check_get_address_info_by_cep + tally = [0, 0, 0] + + File.read('../../conformance/recorded/get-address-info-by-cep.tsv', encoding: 'UTF-8').split("\n").drop(1).each do |line| + next if line.empty? + + parts = line.split("\t", -1) + + unless runs(parts[0]) + tally[2] += 1 + + next + end + + argument0 = (parts[2] == 'number' ? unescape(parts[1]).to_i : unescape(parts[1])) + options = BrazilianUtilsBridge::GetAddressInfoByCep::GetAddressInfoByCepOptions.new + given = false + + unless parts[3].empty? + options.providers = NOT_A_LIST.key?(parts[3]) ? NOT_A_LIST[parts[3]] : (parts[3] == '[]' ? [] : parts[3].split('|')) + given = true + end + + begin + actual = render_get_address_info_by_cep_address_info(BrazilianUtilsBridge::GetAddressInfoByCep.get_address_info_by_cep(argument0, given ? options : nil)) + rescue StandardError => e + actual = "!#{e.class.name.split('::').last}|#{e.message}" + end + + report('getAddressInfoByCep', actual, unescape(parts[4]), tally) + end + + tally +end + +# Replays what `getMunicipalities` answers. +def check_get_municipalities + tally = [0, 0, 0] + + File.read('../../conformance/recorded/get-municipalities.tsv', encoding: 'UTF-8').split("\n").drop(1).each do |line| + next if line.empty? + + parts = line.split("\t", -1) + + unless runs(parts[0]) + tally[2] += 1 + + next + end + + argument0 = parts[1] == '1' ? unescape(parts[2]) : nil + + begin + actual = render_list_get_municipalities_municipality(BrazilianUtilsBridge::GetMunicipalities.get_municipalities(argument0)) + rescue StandardError => e + actual = "!#{e.class.name.split('::').last}|#{e.message}" + end + + report('getMunicipalities', actual, unescape(parts[3]), tally) + end + + tally +end + +# Replays what `isValidCnpj` answers. +def check_is_valid_cnpj + tally = [0, 0, 0] + + File.read('../../conformance/recorded/is-valid-cnpj.tsv', encoding: 'UTF-8').split("\n").drop(1).each do |line| + next if line.empty? + + parts = line.split("\t", -1) + + unless runs(parts[0]) + tally[2] += 1 + + next + end + + argument0 = (parts[2] == 'number' ? unescape(parts[1]).to_i : unescape(parts[1])) + options = BrazilianUtilsBridge::IsValidCnpj::IsValidCnpjOptions.new + given = false + + unless parts[3].empty? + options.version = parts[3].to_i + given = true + end + + begin + actual = (BrazilianUtilsBridge::IsValidCnpj.is_valid_cnpj(argument0, given ? options : nil) ? 'true' : 'false') + rescue StandardError => e + actual = "!#{e.class.name.split('::').last}|#{e.message}" + end + + report('isValidCnpj', actual, unescape(parts[4]), tally) + end + + tally +end + +failed = 0 + +tally = check_format_cnpj +failed += tally[1] +puts("#{TARGET}: formatCnpj #{tally[0]}/#{tally[0] + tally[1]} matched" + + (tally[2].zero? ? '' : " (#{tally[2]} not expressible)")) + +tally = check_get_address_info_by_cep +failed += tally[1] +puts("#{TARGET}: getAddressInfoByCep #{tally[0]}/#{tally[0] + tally[1]} matched" + + (tally[2].zero? ? '' : " (#{tally[2]} not expressible)")) + +tally = check_get_municipalities +failed += tally[1] +puts("#{TARGET}: getMunicipalities #{tally[0]}/#{tally[0] + tally[1]} matched" + + (tally[2].zero? ? '' : " (#{tally[2]} not expressible)")) + +tally = check_is_valid_cnpj +failed += tally[1] +puts("#{TARGET}: isValidCnpj #{tally[0]}/#{tally[0] + tally[1]} matched" + + (tally[2].zero? ? '' : " (#{tally[2]} not expressible)")) + +exit(1) if failed.positive? diff --git a/spec/bridge/out/ruby/lib/brazilian_utils_bridge/format_cnpj.rb b/spec/bridge/out/ruby/lib/brazilian_utils_bridge/format_cnpj.rb new file mode 100644 index 000000000..84542ed49 --- /dev/null +++ b/spec/bridge/out/ruby/lib/brazilian_utils_bridge/format_cnpj.rb @@ -0,0 +1,81 @@ +# frozen_string_literal: true + +# Code generated from spec/bridge/source/format-cnpj.ts. DO NOT EDIT. + +require_relative 'runtime' + +module BrazilianUtilsBridge + # `formatCnpj`, written once. + module FormatCnpj + CLASS0 = [[0x30, 0x39]].freeze + CLASS1 = [[0x30, 0x39], [0x41, 0x5a], [0x61, 0x7a]].freeze + + + + PATTERN = "00.000.000/0000-00".freeze + OBFUSCATED_PATTERN = "**.000.000/0000-**".freeze + + + + # Options of `formatCnpj`. + FormatCnpjOptions = Struct.new(:pad, :version, :obfuscate, keyword_init: true) + + + + # Formats a given CNPJ (Cadastro Nacional da Pessoa Jurídica) value. + def self.format_cnpj(value, options = nil) + options_version = -1 + options_version = options.version unless options.nil? || options.version.nil? + options_obfuscate = false + options_obfuscate = options.obfuscate unless options.nil? || options.obfuscate.nil? + options_pad = false + options_pad = options.pad unless options.nil? || options.pad.nil? + return "" if value.nil? + text = Runtime.as_string(value) + cleaned = Runtime.keep_class(CLASS0, text) + if (options_version == 2) + cleaned = Runtime.keep_class(CLASS1, text).upcase + end + pattern = PATTERN + if Runtime.is_truthy(options_obfuscate) + pattern = OBFUSCATED_PATTERN + end + return layout(cleaned, pattern, Runtime.is_truthy(options_pad)) + end + + # Lays a value over a pattern. + def self.layout(value, pattern, pad) + slots = 0 + (0...pattern.length).each do |index| + if ((Runtime.code_at(pattern, index) == 48) || (Runtime.code_at(pattern, index) == 42)) + slots = (slots + 1) + end + end + padded = value + if pad + padded = Runtime.pad_start(value, slots, "0") + end + formatted = "" + cursor = 0 + (0...pattern.length).each do |index| + slot = Runtime.code_at(pattern, index) + if ((slot == 48) || (slot == 42)) + if (cursor >= padded.length) + return formatted + end + if (slot == 42) + formatted = (formatted + "*") + else + formatted = (formatted + padded[cursor...(cursor + 1)]) + end + cursor = (cursor + 1) + else + if (cursor < padded.length) + formatted = (formatted + pattern[index...(index + 1)]) + end + end + end + return formatted + end + end +end diff --git a/spec/bridge/out/ruby/lib/brazilian_utils_bridge/get_address_info_by_cep.rb b/spec/bridge/out/ruby/lib/brazilian_utils_bridge/get_address_info_by_cep.rb new file mode 100644 index 000000000..4ffe0d015 --- /dev/null +++ b/spec/bridge/out/ruby/lib/brazilian_utils_bridge/get_address_info_by_cep.rb @@ -0,0 +1,156 @@ +# frozen_string_literal: true + +# Code generated from spec/bridge/source/get-address-info-by-cep.ts. DO NOT EDIT. + +require_relative 'runtime' + +module BrazilianUtilsBridge + # Address lookup by CEP, written once. + module GetAddressInfoByCep + CLASS0 = [[0x30, 0x39]].freeze + + PATTERN_CEP_FORMAT = [ + Runtime::PatternStep.new(CLASS0, 8, 8, false), + ].freeze + + DEFAULT_PROVIDERS = ["viacep", "brasilapi"].freeze + KNOWN_PROVIDERS = ["viacep", "widenet", "brasilapi"].freeze + BRASIL_API_NOT_FOUND_STATUS = 404.freeze + HTTP_RETRIES = 2.freeze + HTTP_RETRY_DELAY_MS = 250.freeze + + # Base class of every error `getAddressInfoByCep` rejects with. + class GetAddressInfoByCepError < StandardError; end + + # Thrown by `getAddressInfoByCep` when the value given is not a valid CEP. + class GetAddressInfoByCepValidationError < GetAddressInfoByCepError; end + + # Thrown by `getAddressInfoByCep` when no CEP service knows the CEP. + class GetAddressInfoByCepNotFoundError < GetAddressInfoByCepError; end + + # Thrown by `getAddressInfoByCep` when every CEP service failed to answer. + class GetAddressInfoByCepServiceError < GetAddressInfoByCepError; end + + # Raised inside a provider that did not answer. Only whether a failure was a not found is looked at when the provider failures are aggregated, so this one never leaves the module. + class CepProviderFailure < StandardError; end + + # The address `getAddressInfoByCep` returns for a CEP. + AddressInfo = Struct.new(:cep, :state, :city, :neighborhood, :street, keyword_init: true) + + # Options of `getAddressInfoByCep`. + GetAddressInfoByCepOptions = Struct.new(:providers, keyword_init: true) + + + + # Reads the address ViaCEP answers with. + # + # @see Based on: https://viacep.com.br/ + def self.fetch_via_cep(cep) + response = Runtime.http_get((("https://viacep.com.br/ws/" + cep) + "/json/"), HTTP_RETRIES, HTTP_RETRY_DELAY_MS) + if !response.ok + raise CepProviderFailure, "ViaCEP request failed" + end + found = Runtime.json_string(response.body, "cep") + if (Runtime.json_truthy(response.body, "erro") || (found == "")) + raise GetAddressInfoByCepNotFoundError, "CEP n\u{e3}o encontrado" + end + return AddressInfo.new(cep: Runtime.keep_class(CLASS0, found), state: Runtime.json_string(response.body, "uf"), city: Runtime.json_string(response.body, "localidade"), neighborhood: Runtime.json_string(response.body, "bairro"), street: Runtime.json_string(response.body, "logradouro")) + end + + # Reads the address Widenet answers with. + def self.fetch_widenet(cep) + response = Runtime.http_get((("https://apps.widenet.com.br/busca-cep/api/cep/" + cep) + ".json"), HTTP_RETRIES, HTTP_RETRY_DELAY_MS) + if !response.ok + raise CepProviderFailure, "Widenet request failed" + end + found = Runtime.json_string(response.body, "code") + if (((Runtime.json_int(response.body, "status") != 200) || !Runtime.json_is_true(response.body, "ok")) || (found == "")) + raise GetAddressInfoByCepNotFoundError, "CEP n\u{e3}o encontrado" + end + return AddressInfo.new(cep: Runtime.keep_class(CLASS0, found), state: Runtime.json_string(response.body, "state"), city: Runtime.json_string(response.body, "city"), neighborhood: Runtime.json_string(response.body, "district"), street: Runtime.json_string(response.body, "address")) + end + + # Reads the address BrasilAPI answers with. + # + # @see Based on: https://brasilapi.com.br/docs#tag/CEP + def self.fetch_brasil_api(cep) + response = Runtime.http_get((("https://brasilapi.com.br/api/cep/v1/" + cep) + ""), HTTP_RETRIES, HTTP_RETRY_DELAY_MS) + if (response.status == BRASIL_API_NOT_FOUND_STATUS) + raise GetAddressInfoByCepNotFoundError, "CEP n\u{e3}o encontrado" + end + if !response.ok + raise CepProviderFailure, "BrasilAPI request failed" + end + found = Runtime.json_string(response.body, "cep") + if (Runtime.json_truthy(response.body, "errors") || (found == "")) + raise GetAddressInfoByCepNotFoundError, "CEP n\u{e3}o encontrado" + end + return AddressInfo.new(cep: Runtime.keep_class(CLASS0, found), state: Runtime.json_string(response.body, "state"), city: Runtime.json_string(response.body, "city"), neighborhood: Runtime.json_string(response.body, "neighborhood"), street: Runtime.json_string(response.body, "street")) + end + + # Asks one named provider for a CEP. + def self.fetch_provider(provider, cep) + if (provider == "viacep") + return fetch_via_cep(cep) + end + if (provider == "widenet") + return fetch_widenet(cep) + end + return fetch_brasil_api(cep) + end + + # The providers of a list that are known, in the order they were given. + def self.known_providers(given) + kept = [] + given.each do |provider| + if Runtime.list_has(KNOWN_PROVIDERS, provider) + kept.push(provider) + end + end + return kept + end + + # Fetches address information for a given CEP using multiple providers simultaneously. + # Returns the result from the first provider that responds successfully. + # + # The providers are started together and raced, not tried one after the other, so a provider + # that is retrying delays nothing for the others: its retries only push back the moment its own + # failure lands, and therefore the moment an all-failed rejection can surface. + # + # @see Official: https://www.correios.com.br/enviar/precisa-de-ajuda/tudo-sobre-cep + # @see Based on: https://viacep.com.br/ + # ViaCEP, one of the two default providers. A third-party service, not a Correios one. + # @see Based on: https://brasilapi.com.br/docs#tag/CEP + # BrasilAPI, the other default provider. A third-party service, not a Correios one. + def self.get_address_info_by_cep(cep, options = nil) + options_providers = nil + options_providers = options.providers unless options.nil? || options.providers.nil? + digits = Runtime.keep_class(CLASS0, Runtime.as_string(cep)) + if Runtime.is_number(cep) + digits = Runtime.pad_start(digits, 8, "0") + end + if !Runtime.pattern_test(PATTERN_CEP_FORMAT, digits) + raise GetAddressInfoByCepValidationError, "CEP inv\u{e1}lido" + end + chosen = DEFAULT_PROVIDERS + if !options_providers.nil? + if !Runtime.is_list(options_providers) + raise GetAddressInfoByCepValidationError, "Nenhum provedor v\u{e1}lido especificado" + end + chosen = known_providers(options_providers) + if (chosen.length == 0) + raise GetAddressInfoByCepValidationError, "Nenhum provedor v\u{e1}lido especificado" + end + end + attempts = Runtime.start_all(method(:fetch_provider), chosen, digits) + found = Runtime.first_success(attempts) + if !found.nil? + return found + end + if Runtime.any_failed_with(attempts, "GetAddressInfoByCepNotFoundError") + raise GetAddressInfoByCepNotFoundError, "CEP n\u{e3}o encontrado em nenhum servi\u{e7}o" + end + raise GetAddressInfoByCepServiceError, "Todos os servi\u{e7}os est\u{e3}o fora de servi\u{e7}o ou indispon\u{ed}veis" + end + end +end diff --git a/spec/bridge/out/ruby/lib/brazilian_utils_bridge/get_municipalities.rb b/spec/bridge/out/ruby/lib/brazilian_utils_bridge/get_municipalities.rb new file mode 100644 index 000000000..c849574b7 --- /dev/null +++ b/spec/bridge/out/ruby/lib/brazilian_utils_bridge/get_municipalities.rb @@ -0,0 +1,5659 @@ +# frozen_string_literal: true + +# Code generated from spec/bridge/source/get-municipalities.ts. DO NOT EDIT. + +require_relative 'runtime' + +module BrazilianUtilsBridge + # Brazilian municipalities, written once. + module GetMunicipalities + + + + + + + + + # One Brazilian municipality, as the IBGE publishes it. + Municipality = Struct.new(:code, :name, :state_code, keyword_init: true) + + # Brazilian municipalities published by the IBGE, by state, in the pt-BR collation order the JavaScript package returns. + MUNICIPALITIES = Runtime.make_dataset( + [ + ["AC", "Acrel\u{e2}ndia", "1200013"], + ["AC", "Assis Brasil", "1200054"], + ["AC", "Brasil\u{e9}ia", "1200104"], + ["AC", "Bujari", "1200138"], + ["AC", "Capixaba", "1200179"], + ["AC", "Cruzeiro do Sul", "1200203"], + ["AC", "Epitaciol\u{e2}ndia", "1200252"], + ["AC", "Feij\u{f3}", "1200302"], + ["AC", "Jord\u{e3}o", "1200328"], + ["AC", "M\u{e2}ncio Lima", "1200336"], + ["AC", "Manoel Urbano", "1200344"], + ["AC", "Marechal Thaumaturgo", "1200351"], + ["AC", "Pl\u{e1}cido de Castro", "1200385"], + ["AC", "Porto Acre", "1200807"], + ["AC", "Porto Walter", "1200393"], + ["AC", "Rio Branco", "1200401"], + ["AC", "Rodrigues Alves", "1200427"], + ["AC", "Santa Rosa do Purus", "1200435"], + ["AC", "Sena Madureira", "1200500"], + ["AC", "Senador Guiomard", "1200450"], + ["AC", "Tarauac\u{e1}", "1200609"], + ["AC", "Xapuri", "1200708"], + ["AL", "\u{c1}gua Branca", "2700102"], + ["AL", "Anadia", "2700201"], + ["AL", "Arapiraca", "2700300"], + ["AL", "Atalaia", "2700409"], + ["AL", "Barra de Santo Ant\u{f4}nio", "2700508"], + ["AL", "Barra de S\u{e3}o Miguel", "2700607"], + ["AL", "Batalha", "2700706"], + ["AL", "Bel\u{e9}m", "2700805"], + ["AL", "Belo Monte", "2700904"], + ["AL", "Boca da Mata", "2701001"], + ["AL", "Branquinha", "2701100"], + ["AL", "Cacimbinhas", "2701209"], + ["AL", "Cajueiro", "2701308"], + ["AL", "Campestre", "2701357"], + ["AL", "Campo Alegre", "2701407"], + ["AL", "Campo Grande", "2701506"], + ["AL", "Canapi", "2701605"], + ["AL", "Capela", "2701704"], + ["AL", "Carneiros", "2701803"], + ["AL", "Ch\u{e3} Preta", "2701902"], + ["AL", "Coit\u{e9} do N\u{f3}ia", "2702009"], + ["AL", "Col\u{f4}nia Leopoldina", "2702108"], + ["AL", "Coqueiro Seco", "2702207"], + ["AL", "Coruripe", "2702306"], + ["AL", "Cra\u{ed}bas", "2702355"], + ["AL", "Delmiro Gouveia", "2702405"], + ["AL", "Dois Riachos", "2702504"], + ["AL", "Estrela de Alagoas", "2702553"], + ["AL", "Feira Grande", "2702603"], + ["AL", "Feliz Deserto", "2702702"], + ["AL", "Flexeiras", "2702801"], + ["AL", "Girau do Ponciano", "2702900"], + ["AL", "Ibateguara", "2703007"], + ["AL", "Igaci", "2703106"], + ["AL", "Igreja Nova", "2703205"], + ["AL", "Inhapi", "2703304"], + ["AL", "Jacar\u{e9} dos Homens", "2703403"], + ["AL", "Jacu\u{ed}pe", "2703502"], + ["AL", "Japaratinga", "2703601"], + ["AL", "Jaramataia", "2703700"], + ["AL", "Jequi\u{e1} da Praia", "2703759"], + ["AL", "Joaquim Gomes", "2703809"], + ["AL", "Jundi\u{e1}", "2703908"], + ["AL", "Junqueiro", "2704005"], + ["AL", "Lagoa da Canoa", "2704104"], + ["AL", "Limoeiro de Anadia", "2704203"], + ["AL", "Macei\u{f3}", "2704302"], + ["AL", "Major Isidoro", "2704401"], + ["AL", "Mar Vermelho", "2704906"], + ["AL", "Maragogi", "2704500"], + ["AL", "Maravilha", "2704609"], + ["AL", "Marechal Deodoro", "2704708"], + ["AL", "Maribondo", "2704807"], + ["AL", "Mata Grande", "2705002"], + ["AL", "Matriz de Camaragibe", "2705101"], + ["AL", "Messias", "2705200"], + ["AL", "Minador do Negr\u{e3}o", "2705309"], + ["AL", "Monteir\u{f3}polis", "2705408"], + ["AL", "Murici", "2705507"], + ["AL", "Novo Lino", "2705606"], + ["AL", "Olho d'\u{c1}gua das Flores", "2705705"], + ["AL", "Olho d'\u{c1}gua do Casado", "2705804"], + ["AL", "Olho d'\u{c1}gua Grande", "2705903"], + ["AL", "Oliven\u{e7}a", "2706000"], + ["AL", "Ouro Branco", "2706109"], + ["AL", "Palestina", "2706208"], + ["AL", "Palmeira dos \u{cd}ndios", "2706307"], + ["AL", "P\u{e3}o de A\u{e7}\u{fa}car", "2706406"], + ["AL", "Pariconha", "2706422"], + ["AL", "Paripueira", "2706448"], + ["AL", "Passo de Camaragibe", "2706505"], + ["AL", "Paulo Jacinto", "2706604"], + ["AL", "Penedo", "2706703"], + ["AL", "Pia\u{e7}abu\u{e7}u", "2706802"], + ["AL", "Pilar", "2706901"], + ["AL", "Pindoba", "2707008"], + ["AL", "Piranhas", "2707107"], + ["AL", "Po\u{e7}o das Trincheiras", "2707206"], + ["AL", "Porto Calvo", "2707305"], + ["AL", "Porto de Pedras", "2707404"], + ["AL", "Porto Real do Col\u{e9}gio", "2707503"], + ["AL", "Quebrangulo", "2707602"], + ["AL", "Rio Largo", "2707701"], + ["AL", "Roteiro", "2707800"], + ["AL", "Santa Luzia do Norte", "2707909"], + ["AL", "Santana do Ipanema", "2708006"], + ["AL", "Santana do Munda\u{fa}", "2708105"], + ["AL", "S\u{e3}o Br\u{e1}s", "2708204"], + ["AL", "S\u{e3}o Jos\u{e9} da Laje", "2708303"], + ["AL", "S\u{e3}o Jos\u{e9} da Tapera", "2708402"], + ["AL", "S\u{e3}o Lu\u{ed}s do Quitunde", "2708501"], + ["AL", "S\u{e3}o Miguel dos Campos", "2708600"], + ["AL", "S\u{e3}o Miguel dos Milagres", "2708709"], + ["AL", "S\u{e3}o Sebasti\u{e3}o", "2708808"], + ["AL", "Satuba", "2708907"], + ["AL", "Senador Rui Palmeira", "2708956"], + ["AL", "Tanque d'Arca", "2709004"], + ["AL", "Taquarana", "2709103"], + ["AL", "Teot\u{f4}nio Vilela", "2709152"], + ["AL", "Traipu", "2709202"], + ["AL", "Uni\u{e3}o dos Palmares", "2709301"], + ["AL", "Vi\u{e7}osa", "2709400"], + ["AP", "Amap\u{e1}", "1600105"], + ["AP", "Cal\u{e7}oene", "1600204"], + ["AP", "Cutias", "1600212"], + ["AP", "Ferreira Gomes", "1600238"], + ["AP", "Itaubal", "1600253"], + ["AP", "Laranjal do Jari", "1600279"], + ["AP", "Macap\u{e1}", "1600303"], + ["AP", "Mazag\u{e3}o", "1600402"], + ["AP", "Oiapoque", "1600501"], + ["AP", "Pedra Branca do Amapari", "1600154"], + ["AP", "Porto Grande", "1600535"], + ["AP", "Pracu\u{fa}ba", "1600550"], + ["AP", "Santana", "1600600"], + ["AP", "Serra do Navio", "1600055"], + ["AP", "Tartarugalzinho", "1600709"], + ["AP", "Vit\u{f3}ria do Jari", "1600808"], + ["AM", "Alvar\u{e3}es", "1300029"], + ["AM", "Amatur\u{e1}", "1300060"], + ["AM", "Anam\u{e3}", "1300086"], + ["AM", "Anori", "1300102"], + ["AM", "Apu\u{ed}", "1300144"], + ["AM", "Atalaia do Norte", "1300201"], + ["AM", "Autazes", "1300300"], + ["AM", "Barcelos", "1300409"], + ["AM", "Barreirinha", "1300508"], + ["AM", "Benjamin Constant", "1300607"], + ["AM", "Beruri", "1300631"], + ["AM", "Boa Vista do Ramos", "1300680"], + ["AM", "Boca do Acre", "1300706"], + ["AM", "Borba", "1300805"], + ["AM", "Caapiranga", "1300839"], + ["AM", "Canutama", "1300904"], + ["AM", "Carauari", "1301001"], + ["AM", "Careiro", "1301100"], + ["AM", "Careiro da V\u{e1}rzea", "1301159"], + ["AM", "Coari", "1301209"], + ["AM", "Codaj\u{e1}s", "1301308"], + ["AM", "Eirunep\u{e9}", "1301407"], + ["AM", "Envira", "1301506"], + ["AM", "Fonte Boa", "1301605"], + ["AM", "Guajar\u{e1}", "1301654"], + ["AM", "Humait\u{e1}", "1301704"], + ["AM", "Ipixuna", "1301803"], + ["AM", "Iranduba", "1301852"], + ["AM", "Itacoatiara", "1301902"], + ["AM", "Itamarati", "1301951"], + ["AM", "Itapiranga", "1302009"], + ["AM", "Japur\u{e1}", "1302108"], + ["AM", "Juru\u{e1}", "1302207"], + ["AM", "Juta\u{ed}", "1302306"], + ["AM", "L\u{e1}brea", "1302405"], + ["AM", "Manacapuru", "1302504"], + ["AM", "Manaquiri", "1302553"], + ["AM", "Manaus", "1302603"], + ["AM", "Manicor\u{e9}", "1302702"], + ["AM", "Mara\u{e3}", "1302801"], + ["AM", "Mau\u{e9}s", "1302900"], + ["AM", "Nhamund\u{e1}", "1303007"], + ["AM", "Nova Olinda do Norte", "1303106"], + ["AM", "Novo Air\u{e3}o", "1303205"], + ["AM", "Novo Aripuan\u{e3}", "1303304"], + ["AM", "Parintins", "1303403"], + ["AM", "Pauini", "1303502"], + ["AM", "Presidente Figueiredo", "1303536"], + ["AM", "Rio Preto da Eva", "1303569"], + ["AM", "Santa Isabel do Rio Negro", "1303601"], + ["AM", "Santo Ant\u{f4}nio do I\u{e7}\u{e1}", "1303700"], + ["AM", "S\u{e3}o Gabriel da Cachoeira", "1303809"], + ["AM", "S\u{e3}o Paulo de Oliven\u{e7}a", "1303908"], + ["AM", "S\u{e3}o Sebasti\u{e3}o do Uatum\u{e3}", "1303957"], + ["AM", "Silves", "1304005"], + ["AM", "Tabatinga", "1304062"], + ["AM", "Tapau\u{e1}", "1304104"], + ["AM", "Tef\u{e9}", "1304203"], + ["AM", "Tonantins", "1304237"], + ["AM", "Uarini", "1304260"], + ["AM", "Urucar\u{e1}", "1304302"], + ["AM", "Urucurituba", "1304401"], + ["BA", "Aba\u{ed}ra", "2900108"], + ["BA", "Abar\u{e9}", "2900207"], + ["BA", "Acajutiba", "2900306"], + ["BA", "Adustina", "2900355"], + ["BA", "\u{c1}gua Fria", "2900405"], + ["BA", "Aiquara", "2900603"], + ["BA", "Alagoinhas", "2900702"], + ["BA", "Alcoba\u{e7}a", "2900801"], + ["BA", "Almadina", "2900900"], + ["BA", "Amargosa", "2901007"], + ["BA", "Am\u{e9}lia Rodrigues", "2901106"], + ["BA", "Am\u{e9}rica Dourada", "2901155"], + ["BA", "Anag\u{e9}", "2901205"], + ["BA", "Andara\u{ed}", "2901304"], + ["BA", "Andorinha", "2901353"], + ["BA", "Angical", "2901403"], + ["BA", "Anguera", "2901502"], + ["BA", "Antas", "2901601"], + ["BA", "Ant\u{f4}nio Cardoso", "2901700"], + ["BA", "Ant\u{f4}nio Gon\u{e7}alves", "2901809"], + ["BA", "Apor\u{e1}", "2901908"], + ["BA", "Apuarema", "2901957"], + ["BA", "Ara\u{e7}\u{e1}s", "2902054"], + ["BA", "Aracatu", "2902005"], + ["BA", "Araci", "2902104"], + ["BA", "Aramari", "2902203"], + ["BA", "Arataca", "2902252"], + ["BA", "Aratu\u{ed}pe", "2902302"], + ["BA", "Aurelino Leal", "2902401"], + ["BA", "Baian\u{f3}polis", "2902500"], + ["BA", "Baixa Grande", "2902609"], + ["BA", "Banza\u{ea}", "2902658"], + ["BA", "Barra", "2902708"], + ["BA", "Barra da Estiva", "2902807"], + ["BA", "Barra do Cho\u{e7}a", "2902906"], + ["BA", "Barra do Mendes", "2903003"], + ["BA", "Barra do Rocha", "2903102"], + ["BA", "Barreiras", "2903201"], + ["BA", "Barro Alto", "2903235"], + ["BA", "Barro Preto", "2903300"], + ["BA", "Barrocas", "2903276"], + ["BA", "Belmonte", "2903409"], + ["BA", "Belo Campo", "2903508"], + ["BA", "Biritinga", "2903607"], + ["BA", "Boa Nova", "2903706"], + ["BA", "Boa Vista do Tupim", "2903805"], + ["BA", "Bom Jesus da Lapa", "2903904"], + ["BA", "Bom Jesus da Serra", "2903953"], + ["BA", "Boninal", "2904001"], + ["BA", "Bonito", "2904050"], + ["BA", "Boquira", "2904100"], + ["BA", "Botupor\u{e3}", "2904209"], + ["BA", "Brej\u{f5}es", "2904308"], + ["BA", "Brejol\u{e2}ndia", "2904407"], + ["BA", "Brotas de Maca\u{fa}bas", "2904506"], + ["BA", "Brumado", "2904605"], + ["BA", "Buerarema", "2904704"], + ["BA", "Buritirama", "2904753"], + ["BA", "Caatiba", "2904803"], + ["BA", "Cabaceiras do Paragua\u{e7}u", "2904852"], + ["BA", "Cachoeira", "2904902"], + ["BA", "Cacul\u{e9}", "2905008"], + ["BA", "Ca\u{e9}m", "2905107"], + ["BA", "Caetanos", "2905156"], + ["BA", "Caetit\u{e9}", "2905206"], + ["BA", "Cafarnaum", "2905305"], + ["BA", "Cairu", "2905404"], + ["BA", "Caldeir\u{e3}o Grande", "2905503"], + ["BA", "Camacan", "2905602"], + ["BA", "Cama\u{e7}ari", "2905701"], + ["BA", "Camamu", "2905800"], + ["BA", "Campo Alegre de Lourdes", "2905909"], + ["BA", "Campo Formoso", "2906006"], + ["BA", "Can\u{e1}polis", "2906105"], + ["BA", "Canarana", "2906204"], + ["BA", "Canavieiras", "2906303"], + ["BA", "Candeal", "2906402"], + ["BA", "Candeias", "2906501"], + ["BA", "Candiba", "2906600"], + ["BA", "C\u{e2}ndido Sales", "2906709"], + ["BA", "Cansan\u{e7}\u{e3}o", "2906808"], + ["BA", "Canudos", "2906824"], + ["BA", "Capela do Alto Alegre", "2906857"], + ["BA", "Capim Grosso", "2906873"], + ["BA", "Cara\u{ed}bas", "2906899"], + ["BA", "Caravelas", "2906907"], + ["BA", "Cardeal da Silva", "2907004"], + ["BA", "Carinhanha", "2907103"], + ["BA", "Casa Nova", "2907202"], + ["BA", "Castro Alves", "2907301"], + ["BA", "Catol\u{e2}ndia", "2907400"], + ["BA", "Catu", "2907509"], + ["BA", "Caturama", "2907558"], + ["BA", "Central", "2907608"], + ["BA", "Chorroch\u{f3}", "2907707"], + ["BA", "C\u{ed}cero Dantas", "2907806"], + ["BA", "Cip\u{f3}", "2907905"], + ["BA", "Coaraci", "2908002"], + ["BA", "Cocos", "2908101"], + ["BA", "Concei\u{e7}\u{e3}o da Feira", "2908200"], + ["BA", "Concei\u{e7}\u{e3}o do Almeida", "2908309"], + ["BA", "Concei\u{e7}\u{e3}o do Coit\u{e9}", "2908408"], + ["BA", "Concei\u{e7}\u{e3}o do Jacu\u{ed}pe", "2908507"], + ["BA", "Conde", "2908606"], + ["BA", "Conde\u{fa}ba", "2908705"], + ["BA", "Contendas do Sincor\u{e1}", "2908804"], + ["BA", "Cora\u{e7}\u{e3}o de Maria", "2908903"], + ["BA", "Cordeiros", "2909000"], + ["BA", "Coribe", "2909109"], + ["BA", "Coronel Jo\u{e3}o S\u{e1}", "2909208"], + ["BA", "Correntina", "2909307"], + ["BA", "Cotegipe", "2909406"], + ["BA", "Cravol\u{e2}ndia", "2909505"], + ["BA", "Cris\u{f3}polis", "2909604"], + ["BA", "Crist\u{f3}polis", "2909703"], + ["BA", "Cruz das Almas", "2909802"], + ["BA", "Cura\u{e7}\u{e1}", "2909901"], + ["BA", "D\u{e1}rio Meira", "2910008"], + ["BA", "Dias d'\u{c1}vila", "2910057"], + ["BA", "Dom Bas\u{ed}lio", "2910107"], + ["BA", "Dom Macedo Costa", "2910206"], + ["BA", "El\u{ed}sio Medrado", "2910305"], + ["BA", "Encruzilhada", "2910404"], + ["BA", "Entre Rios", "2910503"], + ["BA", "\u{c9}rico Cardoso", "2900504"], + ["BA", "Esplanada", "2910602"], + ["BA", "Euclides da Cunha", "2910701"], + ["BA", "Eun\u{e1}polis", "2910727"], + ["BA", "F\u{e1}tima", "2910750"], + ["BA", "Feira da Mata", "2910776"], + ["BA", "Feira de Santana", "2910800"], + ["BA", "Filad\u{e9}lfia", "2910859"], + ["BA", "Firmino Alves", "2910909"], + ["BA", "Floresta Azul", "2911006"], + ["BA", "Formosa do Rio Preto", "2911105"], + ["BA", "Gandu", "2911204"], + ["BA", "Gavi\u{e3}o", "2911253"], + ["BA", "Gentio do Ouro", "2911303"], + ["BA", "Gl\u{f3}ria", "2911402"], + ["BA", "Gongogi", "2911501"], + ["BA", "Governador Mangabeira", "2911600"], + ["BA", "Guajeru", "2911659"], + ["BA", "Guanambi", "2911709"], + ["BA", "Guaratinga", "2911808"], + ["BA", "Heli\u{f3}polis", "2911857"], + ["BA", "Ia\u{e7}u", "2911907"], + ["BA", "Ibiassuc\u{ea}", "2912004"], + ["BA", "Ibicara\u{ed}", "2912103"], + ["BA", "Ibicoara", "2912202"], + ["BA", "Ibicu\u{ed}", "2912301"], + ["BA", "Ibipeba", "2912400"], + ["BA", "Ibipitanga", "2912509"], + ["BA", "Ibiquera", "2912608"], + ["BA", "Ibirapitanga", "2912707"], + ["BA", "Ibirapu\u{e3}", "2912806"], + ["BA", "Ibirataia", "2912905"], + ["BA", "Ibitiara", "2913002"], + ["BA", "Ibitit\u{e1}", "2913101"], + ["BA", "Ibotirama", "2913200"], + ["BA", "Ichu", "2913309"], + ["BA", "Igapor\u{e3}", "2913408"], + ["BA", "Igrapi\u{fa}na", "2913457"], + ["BA", "Igua\u{ed}", "2913507"], + ["BA", "Ilh\u{e9}us", "2913606"], + ["BA", "Inhambupe", "2913705"], + ["BA", "Ipecaet\u{e1}", "2913804"], + ["BA", "Ipia\u{fa}", "2913903"], + ["BA", "Ipir\u{e1}", "2914000"], + ["BA", "Ipupiara", "2914109"], + ["BA", "Irajuba", "2914208"], + ["BA", "Iramaia", "2914307"], + ["BA", "Iraquara", "2914406"], + ["BA", "Irar\u{e1}", "2914505"], + ["BA", "Irec\u{ea}", "2914604"], + ["BA", "Itabela", "2914653"], + ["BA", "Itaberaba", "2914703"], + ["BA", "Itabuna", "2914802"], + ["BA", "Itacar\u{e9}", "2914901"], + ["BA", "Itaet\u{e9}", "2915007"], + ["BA", "Itagi", "2915106"], + ["BA", "Itagib\u{e1}", "2915205"], + ["BA", "Itagimirim", "2915304"], + ["BA", "Itagua\u{e7}u da Bahia", "2915353"], + ["BA", "Itaju do Col\u{f4}nia", "2915403"], + ["BA", "Itaju\u{ed}pe", "2915502"], + ["BA", "Itamaraju", "2915601"], + ["BA", "Itamari", "2915700"], + ["BA", "Itamb\u{e9}", "2915809"], + ["BA", "Itanagra", "2915908"], + ["BA", "Itanh\u{e9}m", "2916005"], + ["BA", "Itaparica", "2916104"], + ["BA", "Itap\u{e9}", "2916203"], + ["BA", "Itapebi", "2916302"], + ["BA", "Itapetinga", "2916401"], + ["BA", "Itapicuru", "2916500"], + ["BA", "Itapitanga", "2916609"], + ["BA", "Itaquara", "2916708"], + ["BA", "Itarantim", "2916807"], + ["BA", "Itatim", "2916856"], + ["BA", "Itiru\u{e7}u", "2916906"], + ["BA", "Iti\u{fa}ba", "2917003"], + ["BA", "Itoror\u{f3}", "2917102"], + ["BA", "Itua\u{e7}u", "2917201"], + ["BA", "Ituber\u{e1}", "2917300"], + ["BA", "Iuiu", "2917334"], + ["BA", "Jaborandi", "2917359"], + ["BA", "Jacaraci", "2917409"], + ["BA", "Jacobina", "2917508"], + ["BA", "Jaguaquara", "2917607"], + ["BA", "Jaguarari", "2917706"], + ["BA", "Jaguaripe", "2917805"], + ["BA", "Janda\u{ed}ra", "2917904"], + ["BA", "Jequi\u{e9}", "2918001"], + ["BA", "Jeremoabo", "2918100"], + ["BA", "Jiquiri\u{e7}\u{e1}", "2918209"], + ["BA", "Jita\u{fa}na", "2918308"], + ["BA", "Jo\u{e3}o Dourado", "2918357"], + ["BA", "Juazeiro", "2918407"], + ["BA", "Jucuru\u{e7}u", "2918456"], + ["BA", "Jussara", "2918506"], + ["BA", "Jussari", "2918555"], + ["BA", "Jussiape", "2918605"], + ["BA", "Lafaiete Coutinho", "2918704"], + ["BA", "Lagoa Real", "2918753"], + ["BA", "Laje", "2918803"], + ["BA", "Lajed\u{e3}o", "2918902"], + ["BA", "Lajedinho", "2919009"], + ["BA", "Lajedo do Tabocal", "2919058"], + ["BA", "Lamar\u{e3}o", "2919108"], + ["BA", "Lap\u{e3}o", "2919157"], + ["BA", "Lauro de Freitas", "2919207"], + ["BA", "Len\u{e7}\u{f3}is", "2919306"], + ["BA", "Lic\u{ed}nio de Almeida", "2919405"], + ["BA", "Livramento de Nossa Senhora", "2919504"], + ["BA", "Lu\u{ed}s Eduardo Magalh\u{e3}es", "2919553"], + ["BA", "Macajuba", "2919603"], + ["BA", "Macarani", "2919702"], + ["BA", "Maca\u{fa}bas", "2919801"], + ["BA", "Macurur\u{e9}", "2919900"], + ["BA", "Madre de Deus", "2919926"], + ["BA", "Maetinga", "2919959"], + ["BA", "Maiquinique", "2920007"], + ["BA", "Mairi", "2920106"], + ["BA", "Malhada", "2920205"], + ["BA", "Malhada de Pedras", "2920304"], + ["BA", "Manoel Vitorino", "2920403"], + ["BA", "Mansid\u{e3}o", "2920452"], + ["BA", "Marac\u{e1}s", "2920502"], + ["BA", "Maragogipe", "2920601"], + ["BA", "Mara\u{fa}", "2920700"], + ["BA", "Marcion\u{ed}lio Souza", "2920809"], + ["BA", "Mascote", "2920908"], + ["BA", "Mata de S\u{e3}o Jo\u{e3}o", "2921005"], + ["BA", "Matina", "2921054"], + ["BA", "Medeiros Neto", "2921104"], + ["BA", "Miguel Calmon", "2921203"], + ["BA", "Milagres", "2921302"], + ["BA", "Mirangaba", "2921401"], + ["BA", "Mirante", "2921450"], + ["BA", "Monte Santo", "2921500"], + ["BA", "Morpar\u{e1}", "2921609"], + ["BA", "Morro do Chap\u{e9}u", "2921708"], + ["BA", "Mortugaba", "2921807"], + ["BA", "Mucug\u{ea}", "2921906"], + ["BA", "Mucuri", "2922003"], + ["BA", "Mulungu do Morro", "2922052"], + ["BA", "Mundo Novo", "2922102"], + ["BA", "Muniz Ferreira", "2922201"], + ["BA", "Muqu\u{e9}m do S\u{e3}o Francisco", "2922250"], + ["BA", "Muritiba", "2922300"], + ["BA", "Mutu\u{ed}pe", "2922409"], + ["BA", "Nazar\u{e9}", "2922508"], + ["BA", "Nilo Pe\u{e7}anha", "2922607"], + ["BA", "Nordestina", "2922656"], + ["BA", "Nova Cana\u{e3}", "2922706"], + ["BA", "Nova F\u{e1}tima", "2922730"], + ["BA", "Nova Ibi\u{e1}", "2922755"], + ["BA", "Nova Itarana", "2922805"], + ["BA", "Nova Reden\u{e7}\u{e3}o", "2922854"], + ["BA", "Nova Soure", "2922904"], + ["BA", "Nova Vi\u{e7}osa", "2923001"], + ["BA", "Novo Horizonte", "2923035"], + ["BA", "Novo Triunfo", "2923050"], + ["BA", "Olindina", "2923100"], + ["BA", "Oliveira dos Brejinhos", "2923209"], + ["BA", "Ouri\u{e7}angas", "2923308"], + ["BA", "Ourol\u{e2}ndia", "2923357"], + ["BA", "Palmas de Monte Alto", "2923407"], + ["BA", "Palmeiras", "2923506"], + ["BA", "Paramirim", "2923605"], + ["BA", "Paratinga", "2923704"], + ["BA", "Paripiranga", "2923803"], + ["BA", "Pau Brasil", "2923902"], + ["BA", "Paulo Afonso", "2924009"], + ["BA", "P\u{e9} de Serra", "2924058"], + ["BA", "Pedr\u{e3}o", "2924108"], + ["BA", "Pedro Alexandre", "2924207"], + ["BA", "Piat\u{e3}", "2924306"], + ["BA", "Pil\u{e3}o Arcado", "2924405"], + ["BA", "Pinda\u{ed}", "2924504"], + ["BA", "Pindoba\u{e7}u", "2924603"], + ["BA", "Pintadas", "2924652"], + ["BA", "Pira\u{ed} do Norte", "2924678"], + ["BA", "Pirip\u{e1}", "2924702"], + ["BA", "Piritiba", "2924801"], + ["BA", "Planaltino", "2924900"], + ["BA", "Planalto", "2925006"], + ["BA", "Po\u{e7}\u{f5}es", "2925105"], + ["BA", "Pojuca", "2925204"], + ["BA", "Ponto Novo", "2925253"], + ["BA", "Porto Seguro", "2925303"], + ["BA", "Potiragu\u{e1}", "2925402"], + ["BA", "Prado", "2925501"], + ["BA", "Presidente Dutra", "2925600"], + ["BA", "Presidente J\u{e2}nio Quadros", "2925709"], + ["BA", "Presidente Tancredo Neves", "2925758"], + ["BA", "Queimadas", "2925808"], + ["BA", "Quijingue", "2925907"], + ["BA", "Quixabeira", "2925931"], + ["BA", "Rafael Jambeiro", "2925956"], + ["BA", "Remanso", "2926004"], + ["BA", "Retirol\u{e2}ndia", "2926103"], + ["BA", "Riach\u{e3}o das Neves", "2926202"], + ["BA", "Riach\u{e3}o do Jacu\u{ed}pe", "2926301"], + ["BA", "Riacho de Santana", "2926400"], + ["BA", "Ribeira do Amparo", "2926509"], + ["BA", "Ribeira do Pombal", "2926608"], + ["BA", "Ribeir\u{e3}o do Largo", "2926657"], + ["BA", "Rio de Contas", "2926707"], + ["BA", "Rio do Ant\u{f4}nio", "2926806"], + ["BA", "Rio do Pires", "2926905"], + ["BA", "Rio Real", "2927002"], + ["BA", "Rodelas", "2927101"], + ["BA", "Ruy Barbosa", "2927200"], + ["BA", "Salinas da Margarida", "2927309"], + ["BA", "Salvador", "2927408"], + ["BA", "Santa B\u{e1}rbara", "2927507"], + ["BA", "Santa Br\u{ed}gida", "2927606"], + ["BA", "Santa Cruz Cabr\u{e1}lia", "2927705"], + ["BA", "Santa Cruz da Vit\u{f3}ria", "2927804"], + ["BA", "Santa In\u{ea}s", "2927903"], + ["BA", "Santa Luzia", "2928059"], + ["BA", "Santa Maria da Vit\u{f3}ria", "2928109"], + ["BA", "Santa Rita de C\u{e1}ssia", "2928406"], + ["BA", "Santa Terezinha", "2928505"], + ["BA", "Santaluz", "2928000"], + ["BA", "Santana", "2928208"], + ["BA", "Santan\u{f3}polis", "2928307"], + ["BA", "Santo Amaro", "2928604"], + ["BA", "Santo Ant\u{f4}nio de Jesus", "2928703"], + ["BA", "Santo Est\u{ea}v\u{e3}o", "2928802"], + ["BA", "S\u{e3}o Desid\u{e9}rio", "2928901"], + ["BA", "S\u{e3}o Domingos", "2928950"], + ["BA", "S\u{e3}o Felipe", "2929107"], + ["BA", "S\u{e3}o F\u{e9}lix", "2929008"], + ["BA", "S\u{e3}o F\u{e9}lix do Coribe", "2929057"], + ["BA", "S\u{e3}o Francisco do Conde", "2929206"], + ["BA", "S\u{e3}o Gabriel", "2929255"], + ["BA", "S\u{e3}o Gon\u{e7}alo dos Campos", "2929305"], + ["BA", "S\u{e3}o Jos\u{e9} da Vit\u{f3}ria", "2929354"], + ["BA", "S\u{e3}o Jos\u{e9} do Jacu\u{ed}pe", "2929370"], + ["BA", "S\u{e3}o Miguel das Matas", "2929404"], + ["BA", "S\u{e3}o Sebasti\u{e3}o do Pass\u{e9}", "2929503"], + ["BA", "Sapea\u{e7}u", "2929602"], + ["BA", "S\u{e1}tiro Dias", "2929701"], + ["BA", "Saubara", "2929750"], + ["BA", "Sa\u{fa}de", "2929800"], + ["BA", "Seabra", "2929909"], + ["BA", "Sebasti\u{e3}o Laranjeiras", "2930006"], + ["BA", "Senhor do Bonfim", "2930105"], + ["BA", "Sento S\u{e9}", "2930204"], + ["BA", "Serra do Ramalho", "2930154"], + ["BA", "Serra Dourada", "2930303"], + ["BA", "Serra Preta", "2930402"], + ["BA", "Serrinha", "2930501"], + ["BA", "Serrol\u{e2}ndia", "2930600"], + ["BA", "Sim\u{f5}es Filho", "2930709"], + ["BA", "S\u{ed}tio do Mato", "2930758"], + ["BA", "S\u{ed}tio do Quinto", "2930766"], + ["BA", "Sobradinho", "2930774"], + ["BA", "Souto Soares", "2930808"], + ["BA", "Tabocas do Brejo Velho", "2930907"], + ["BA", "Tanha\u{e7}u", "2931004"], + ["BA", "Tanque Novo", "2931053"], + ["BA", "Tanquinho", "2931103"], + ["BA", "Tapero\u{e1}", "2931202"], + ["BA", "Tapiramut\u{e1}", "2931301"], + ["BA", "Teixeira de Freitas", "2931350"], + ["BA", "Teodoro Sampaio", "2931400"], + ["BA", "Teofil\u{e2}ndia", "2931509"], + ["BA", "Teol\u{e2}ndia", "2931608"], + ["BA", "Terra Nova", "2931707"], + ["BA", "Tremedal", "2931806"], + ["BA", "Tucano", "2931905"], + ["BA", "Uau\u{e1}", "2932002"], + ["BA", "Uba\u{ed}ra", "2932101"], + ["BA", "Ubaitaba", "2932200"], + ["BA", "Ubat\u{e3}", "2932309"], + ["BA", "Uiba\u{ed}", "2932408"], + ["BA", "Umburanas", "2932457"], + ["BA", "Una", "2932507"], + ["BA", "Urandi", "2932606"], + ["BA", "Uru\u{e7}uca", "2932705"], + ["BA", "Utinga", "2932804"], + ["BA", "Valen\u{e7}a", "2932903"], + ["BA", "Valente", "2933000"], + ["BA", "V\u{e1}rzea da Ro\u{e7}a", "2933059"], + ["BA", "V\u{e1}rzea do Po\u{e7}o", "2933109"], + ["BA", "V\u{e1}rzea Nova", "2933158"], + ["BA", "Varzedo", "2933174"], + ["BA", "Vera Cruz", "2933208"], + ["BA", "Vereda", "2933257"], + ["BA", "Vit\u{f3}ria da Conquista", "2933307"], + ["BA", "Wagner", "2933406"], + ["BA", "Wanderley", "2933455"], + ["BA", "Wenceslau Guimar\u{e3}es", "2933505"], + ["BA", "Xique-Xique", "2933604"], + ["CE", "Abaiara", "2300101"], + ["CE", "Acarape", "2300150"], + ["CE", "Acara\u{fa}", "2300200"], + ["CE", "Acopiara", "2300309"], + ["CE", "Aiuaba", "2300408"], + ["CE", "Alc\u{e2}ntaras", "2300507"], + ["CE", "Altaneira", "2300606"], + ["CE", "Alto Santo", "2300705"], + ["CE", "Amontada", "2300754"], + ["CE", "Antonina do Norte", "2300804"], + ["CE", "Apuiar\u{e9}s", "2300903"], + ["CE", "Aquiraz", "2301000"], + ["CE", "Aracati", "2301109"], + ["CE", "Aracoiaba", "2301208"], + ["CE", "Ararend\u{e1}", "2301257"], + ["CE", "Araripe", "2301307"], + ["CE", "Aratuba", "2301406"], + ["CE", "Arneiroz", "2301505"], + ["CE", "Assar\u{e9}", "2301604"], + ["CE", "Aurora", "2301703"], + ["CE", "Baixio", "2301802"], + ["CE", "Banabui\u{fa}", "2301851"], + ["CE", "Barbalha", "2301901"], + ["CE", "Barreira", "2301950"], + ["CE", "Barro", "2302008"], + ["CE", "Barroquinha", "2302057"], + ["CE", "Baturit\u{e9}", "2302107"], + ["CE", "Beberibe", "2302206"], + ["CE", "Bela Cruz", "2302305"], + ["CE", "Boa Viagem", "2302404"], + ["CE", "Brejo Santo", "2302503"], + ["CE", "Camocim", "2302602"], + ["CE", "Campos Sales", "2302701"], + ["CE", "Canind\u{e9}", "2302800"], + ["CE", "Capistrano", "2302909"], + ["CE", "Caridade", "2303006"], + ["CE", "Carir\u{e9}", "2303105"], + ["CE", "Cariria\u{e7}u", "2303204"], + ["CE", "Cari\u{fa}s", "2303303"], + ["CE", "Carnaubal", "2303402"], + ["CE", "Cascavel", "2303501"], + ["CE", "Catarina", "2303600"], + ["CE", "Catunda", "2303659"], + ["CE", "Caucaia", "2303709"], + ["CE", "Cedro", "2303808"], + ["CE", "Chaval", "2303907"], + ["CE", "Chor\u{f3}", "2303931"], + ["CE", "Chorozinho", "2303956"], + ["CE", "Corea\u{fa}", "2304004"], + ["CE", "Crate\u{fa}s", "2304103"], + ["CE", "Crato", "2304202"], + ["CE", "Croat\u{e1}", "2304236"], + ["CE", "Cruz", "2304251"], + ["CE", "Deputado Irapuan Pinheiro", "2304269"], + ["CE", "Erer\u{e9}", "2304277"], + ["CE", "Eus\u{e9}bio", "2304285"], + ["CE", "Farias Brito", "2304301"], + ["CE", "Forquilha", "2304350"], + ["CE", "Fortaleza", "2304400"], + ["CE", "Fortim", "2304459"], + ["CE", "Frecheirinha", "2304509"], + ["CE", "General Sampaio", "2304608"], + ["CE", "Gra\u{e7}a", "2304657"], + ["CE", "Granja", "2304707"], + ["CE", "Granjeiro", "2304806"], + ["CE", "Groa\u{ed}ras", "2304905"], + ["CE", "Guai\u{fa}ba", "2304954"], + ["CE", "Guaraciaba do Norte", "2305001"], + ["CE", "Guaramiranga", "2305100"], + ["CE", "Hidrol\u{e2}ndia", "2305209"], + ["CE", "Horizonte", "2305233"], + ["CE", "Ibaretama", "2305266"], + ["CE", "Ibiapina", "2305308"], + ["CE", "Ibicuitinga", "2305332"], + ["CE", "Icapu\u{ed}", "2305357"], + ["CE", "Ic\u{f3}", "2305407"], + ["CE", "Iguatu", "2305506"], + ["CE", "Independ\u{ea}ncia", "2305605"], + ["CE", "Ipaporanga", "2305654"], + ["CE", "Ipaumirim", "2305704"], + ["CE", "Ipu", "2305803"], + ["CE", "Ipueiras", "2305902"], + ["CE", "Iracema", "2306009"], + ["CE", "Irau\u{e7}uba", "2306108"], + ["CE", "Itai\u{e7}aba", "2306207"], + ["CE", "Itaitinga", "2306256"], + ["CE", "Itapaj\u{e9}", "2306306"], + ["CE", "Itapipoca", "2306405"], + ["CE", "Itapi\u{fa}na", "2306504"], + ["CE", "Itarema", "2306553"], + ["CE", "Itatira", "2306603"], + ["CE", "Jaguaretama", "2306702"], + ["CE", "Jaguaribara", "2306801"], + ["CE", "Jaguaribe", "2306900"], + ["CE", "Jaguaruana", "2307007"], + ["CE", "Jardim", "2307106"], + ["CE", "Jati", "2307205"], + ["CE", "Jijoca de Jericoacoara", "2307254"], + ["CE", "Juazeiro do Norte", "2307304"], + ["CE", "Juc\u{e1}s", "2307403"], + ["CE", "Lavras da Mangabeira", "2307502"], + ["CE", "Limoeiro do Norte", "2307601"], + ["CE", "Madalena", "2307635"], + ["CE", "Maracana\u{fa}", "2307650"], + ["CE", "Maranguape", "2307700"], + ["CE", "Marco", "2307809"], + ["CE", "Martin\u{f3}pole", "2307908"], + ["CE", "Massap\u{ea}", "2308005"], + ["CE", "Mauriti", "2308104"], + ["CE", "Meruoca", "2308203"], + ["CE", "Milagres", "2308302"], + ["CE", "Milh\u{e3}", "2308351"], + ["CE", "Mira\u{ed}ma", "2308377"], + ["CE", "Miss\u{e3}o Velha", "2308401"], + ["CE", "Momba\u{e7}a", "2308500"], + ["CE", "Monsenhor Tabosa", "2308609"], + ["CE", "Morada Nova", "2308708"], + ["CE", "Mora\u{fa}jo", "2308807"], + ["CE", "Morrinhos", "2308906"], + ["CE", "Mucambo", "2309003"], + ["CE", "Mulungu", "2309102"], + ["CE", "Nova Olinda", "2309201"], + ["CE", "Nova Russas", "2309300"], + ["CE", "Novo Oriente", "2309409"], + ["CE", "Ocara", "2309458"], + ["CE", "Or\u{f3}s", "2309508"], + ["CE", "Pacajus", "2309607"], + ["CE", "Pacatuba", "2309706"], + ["CE", "Pacoti", "2309805"], + ["CE", "Pacuj\u{e1}", "2309904"], + ["CE", "Palhano", "2310001"], + ["CE", "Palm\u{e1}cia", "2310100"], + ["CE", "Paracuru", "2310209"], + ["CE", "Paraipaba", "2310258"], + ["CE", "Parambu", "2310308"], + ["CE", "Paramoti", "2310407"], + ["CE", "Pedra Branca", "2310506"], + ["CE", "Penaforte", "2310605"], + ["CE", "Pentecoste", "2310704"], + ["CE", "Pereiro", "2310803"], + ["CE", "Pindoretama", "2310852"], + ["CE", "Piquet Carneiro", "2310902"], + ["CE", "Pires Ferreira", "2310951"], + ["CE", "Poranga", "2311009"], + ["CE", "Porteiras", "2311108"], + ["CE", "Potengi", "2311207"], + ["CE", "Potiretama", "2311231"], + ["CE", "Quiterian\u{f3}polis", "2311264"], + ["CE", "Quixad\u{e1}", "2311306"], + ["CE", "Quixel\u{f4}", "2311355"], + ["CE", "Quixeramobim", "2311405"], + ["CE", "Quixer\u{e9}", "2311504"], + ["CE", "Reden\u{e7}\u{e3}o", "2311603"], + ["CE", "Reriutaba", "2311702"], + ["CE", "Russas", "2311801"], + ["CE", "Saboeiro", "2311900"], + ["CE", "Salitre", "2311959"], + ["CE", "Santa Quit\u{e9}ria", "2312205"], + ["CE", "Santana do Acara\u{fa}", "2312007"], + ["CE", "Santana do Cariri", "2312106"], + ["CE", "S\u{e3}o Benedito", "2312304"], + ["CE", "S\u{e3}o Gon\u{e7}alo do Amarante", "2312403"], + ["CE", "S\u{e3}o Jo\u{e3}o do Jaguaribe", "2312502"], + ["CE", "S\u{e3}o Lu\u{ed}s do Curu", "2312601"], + ["CE", "Senador Pompeu", "2312700"], + ["CE", "Senador S\u{e1}", "2312809"], + ["CE", "Sobral", "2312908"], + ["CE", "Solon\u{f3}pole", "2313005"], + ["CE", "Tabuleiro do Norte", "2313104"], + ["CE", "Tamboril", "2313203"], + ["CE", "Tarrafas", "2313252"], + ["CE", "Tau\u{e1}", "2313302"], + ["CE", "Teju\u{e7}uoca", "2313351"], + ["CE", "Tiangu\u{e1}", "2313401"], + ["CE", "Trairi", "2313500"], + ["CE", "Tururu", "2313559"], + ["CE", "Ubajara", "2313609"], + ["CE", "Umari", "2313708"], + ["CE", "Umirim", "2313757"], + ["CE", "Uruburetama", "2313807"], + ["CE", "Uruoca", "2313906"], + ["CE", "Varjota", "2313955"], + ["CE", "V\u{e1}rzea Alegre", "2314003"], + ["CE", "Vi\u{e7}osa do Cear\u{e1}", "2314102"], + ["DF", "Bras\u{ed}lia", "5300108"], + ["ES", "Afonso Cl\u{e1}udio", "3200102"], + ["ES", "\u{c1}gua Doce do Norte", "3200169"], + ["ES", "\u{c1}guia Branca", "3200136"], + ["ES", "Alegre", "3200201"], + ["ES", "Alfredo Chaves", "3200300"], + ["ES", "Alto Rio Novo", "3200359"], + ["ES", "Anchieta", "3200409"], + ["ES", "Apiac\u{e1}", "3200508"], + ["ES", "Aracruz", "3200607"], + ["ES", "At\u{ed}lio Viv\u{e1}cqua", "3200706"], + ["ES", "Baixo Guandu", "3200805"], + ["ES", "Barra de S\u{e3}o Francisco", "3200904"], + ["ES", "Boa Esperan\u{e7}a", "3201001"], + ["ES", "Bom Jesus do Norte", "3201100"], + ["ES", "Brejetuba", "3201159"], + ["ES", "Cachoeiro de Itapemirim", "3201209"], + ["ES", "Cariacica", "3201308"], + ["ES", "Castelo", "3201407"], + ["ES", "Colatina", "3201506"], + ["ES", "Concei\u{e7}\u{e3}o da Barra", "3201605"], + ["ES", "Concei\u{e7}\u{e3}o do Castelo", "3201704"], + ["ES", "Divino de S\u{e3}o Louren\u{e7}o", "3201803"], + ["ES", "Domingos Martins", "3201902"], + ["ES", "Dores do Rio Preto", "3202009"], + ["ES", "Ecoporanga", "3202108"], + ["ES", "Fund\u{e3}o", "3202207"], + ["ES", "Governador Lindenberg", "3202256"], + ["ES", "Gua\u{e7}u\u{ed}", "3202306"], + ["ES", "Guarapari", "3202405"], + ["ES", "Ibatiba", "3202454"], + ["ES", "Ibira\u{e7}u", "3202504"], + ["ES", "Ibitirama", "3202553"], + ["ES", "Iconha", "3202603"], + ["ES", "Irupi", "3202652"], + ["ES", "Itagua\u{e7}u", "3202702"], + ["ES", "Itapemirim", "3202801"], + ["ES", "Itarana", "3202900"], + ["ES", "I\u{fa}na", "3203007"], + ["ES", "Jaguar\u{e9}", "3203056"], + ["ES", "Jer\u{f4}nimo Monteiro", "3203106"], + ["ES", "Jo\u{e3}o Neiva", "3203130"], + ["ES", "Laranja da Terra", "3203163"], + ["ES", "Linhares", "3203205"], + ["ES", "Manten\u{f3}polis", "3203304"], + ["ES", "Marata\u{ed}zes", "3203320"], + ["ES", "Marechal Floriano", "3203346"], + ["ES", "Maril\u{e2}ndia", "3203353"], + ["ES", "Mimoso do Sul", "3203403"], + ["ES", "Montanha", "3203502"], + ["ES", "Mucurici", "3203601"], + ["ES", "Muniz Freire", "3203700"], + ["ES", "Muqui", "3203809"], + ["ES", "Nova Ven\u{e9}cia", "3203908"], + ["ES", "Pancas", "3204005"], + ["ES", "Pedro Can\u{e1}rio", "3204054"], + ["ES", "Pinheiros", "3204104"], + ["ES", "Pi\u{fa}ma", "3204203"], + ["ES", "Ponto Belo", "3204252"], + ["ES", "Presidente Kennedy", "3204302"], + ["ES", "Rio Bananal", "3204351"], + ["ES", "Rio Novo do Sul", "3204401"], + ["ES", "Santa Leopoldina", "3204500"], + ["ES", "Santa Maria de Jetib\u{e1}", "3204559"], + ["ES", "Santa Teresa", "3204609"], + ["ES", "S\u{e3}o Domingos do Norte", "3204658"], + ["ES", "S\u{e3}o Gabriel da Palha", "3204708"], + ["ES", "S\u{e3}o Jos\u{e9} do Cal\u{e7}ado", "3204807"], + ["ES", "S\u{e3}o Mateus", "3204906"], + ["ES", "S\u{e3}o Roque do Cana\u{e3}", "3204955"], + ["ES", "Serra", "3205002"], + ["ES", "Sooretama", "3205010"], + ["ES", "Vargem Alta", "3205036"], + ["ES", "Venda Nova do Imigrante", "3205069"], + ["ES", "Viana", "3205101"], + ["ES", "Vila Pav\u{e3}o", "3205150"], + ["ES", "Vila Val\u{e9}rio", "3205176"], + ["ES", "Vila Velha", "3205200"], + ["ES", "Vit\u{f3}ria", "3205309"], + ["GO", "Abadia de Goi\u{e1}s", "5200050"], + ["GO", "Abadi\u{e2}nia", "5200100"], + ["GO", "Acre\u{fa}na", "5200134"], + ["GO", "Adel\u{e2}ndia", "5200159"], + ["GO", "\u{c1}gua Fria de Goi\u{e1}s", "5200175"], + ["GO", "\u{c1}gua Limpa", "5200209"], + ["GO", "\u{c1}guas Lindas de Goi\u{e1}s", "5200258"], + ["GO", "Alex\u{e2}nia", "5200308"], + ["GO", "Alo\u{e2}ndia", "5200506"], + ["GO", "Alto Horizonte", "5200555"], + ["GO", "Alto Para\u{ed}so de Goi\u{e1}s", "5200605"], + ["GO", "Alvorada do Norte", "5200803"], + ["GO", "Amaralina", "5200829"], + ["GO", "Americano do Brasil", "5200852"], + ["GO", "Amorin\u{f3}polis", "5200902"], + ["GO", "An\u{e1}polis", "5201108"], + ["GO", "Anhanguera", "5201207"], + ["GO", "Anicuns", "5201306"], + ["GO", "Aparecida de Goi\u{e2}nia", "5201405"], + ["GO", "Aparecida do Rio Doce", "5201454"], + ["GO", "Apor\u{e9}", "5201504"], + ["GO", "Ara\u{e7}u", "5201603"], + ["GO", "Aragar\u{e7}as", "5201702"], + ["GO", "Aragoi\u{e2}nia", "5201801"], + ["GO", "Araguapaz", "5202155"], + ["GO", "Aren\u{f3}polis", "5202353"], + ["GO", "Aruan\u{e3}", "5202502"], + ["GO", "Auril\u{e2}ndia", "5202601"], + ["GO", "Avelin\u{f3}polis", "5202809"], + ["GO", "Baliza", "5203104"], + ["GO", "Barro Alto", "5203203"], + ["GO", "Bela Vista de Goi\u{e1}s", "5203302"], + ["GO", "Bom Jardim de Goi\u{e1}s", "5203401"], + ["GO", "Bom Jesus de Goi\u{e1}s", "5203500"], + ["GO", "Bonfin\u{f3}polis", "5203559"], + ["GO", "Bon\u{f3}polis", "5203575"], + ["GO", "Brazabrantes", "5203609"], + ["GO", "Brit\u{e2}nia", "5203807"], + ["GO", "Buriti Alegre", "5203906"], + ["GO", "Buriti de Goi\u{e1}s", "5203939"], + ["GO", "Buritin\u{f3}polis", "5203962"], + ["GO", "Cabeceiras", "5204003"], + ["GO", "Cachoeira Alta", "5204102"], + ["GO", "Cachoeira de Goi\u{e1}s", "5204201"], + ["GO", "Cachoeira Dourada", "5204250"], + ["GO", "Ca\u{e7}u", "5204300"], + ["GO", "Caiap\u{f4}nia", "5204409"], + ["GO", "Caldas Novas", "5204508"], + ["GO", "Caldazinha", "5204557"], + ["GO", "Campestre de Goi\u{e1}s", "5204607"], + ["GO", "Campina\u{e7}u", "5204656"], + ["GO", "Campinorte", "5204706"], + ["GO", "Campo Alegre de Goi\u{e1}s", "5204805"], + ["GO", "Campo Limpo de Goi\u{e1}s", "5204854"], + ["GO", "Campos Belos", "5204904"], + ["GO", "Campos Verdes", "5204953"], + ["GO", "Carmo do Rio Verde", "5205000"], + ["GO", "Castel\u{e2}ndia", "5205059"], + ["GO", "Catal\u{e3}o", "5205109"], + ["GO", "Catura\u{ed}", "5205208"], + ["GO", "Cavalcante", "5205307"], + ["GO", "Ceres", "5205406"], + ["GO", "Cezarina", "5205455"], + ["GO", "Chapad\u{e3}o do C\u{e9}u", "5205471"], + ["GO", "Cidade Ocidental", "5205497"], + ["GO", "Cocalzinho de Goi\u{e1}s", "5205513"], + ["GO", "Colinas do Sul", "5205521"], + ["GO", "C\u{f3}rrego do Ouro", "5205703"], + ["GO", "Corumb\u{e1} de Goi\u{e1}s", "5205802"], + ["GO", "Corumba\u{ed}ba", "5205901"], + ["GO", "Cristalina", "5206206"], + ["GO", "Cristian\u{f3}polis", "5206305"], + ["GO", "Crix\u{e1}s", "5206404"], + ["GO", "Crom\u{ed}nia", "5206503"], + ["GO", "Cumari", "5206602"], + ["GO", "Damian\u{f3}polis", "5206701"], + ["GO", "Damol\u{e2}ndia", "5206800"], + ["GO", "Davin\u{f3}polis", "5206909"], + ["GO", "Diorama", "5207105"], + ["GO", "Divin\u{f3}polis de Goi\u{e1}s", "5208301"], + ["GO", "Doverl\u{e2}ndia", "5207253"], + ["GO", "Edealina", "5207352"], + ["GO", "Ed\u{e9}ia", "5207402"], + ["GO", "Estrela do Norte", "5207501"], + ["GO", "Faina", "5207535"], + ["GO", "Fazenda Nova", "5207600"], + ["GO", "Firmin\u{f3}polis", "5207808"], + ["GO", "Flores de Goi\u{e1}s", "5207907"], + ["GO", "Formosa", "5208004"], + ["GO", "Formoso", "5208103"], + ["GO", "Gameleira de Goi\u{e1}s", "5208152"], + ["GO", "Goian\u{e1}polis", "5208400"], + ["GO", "Goiandira", "5208509"], + ["GO", "Goian\u{e9}sia", "5208608"], + ["GO", "Goi\u{e2}nia", "5208707"], + ["GO", "Goianira", "5208806"], + ["GO", "Goi\u{e1}s", "5208905"], + ["GO", "Goiatuba", "5209101"], + ["GO", "Gouvel\u{e2}ndia", "5209150"], + ["GO", "Guap\u{f3}", "5209200"], + ["GO", "Guara\u{ed}ta", "5209291"], + ["GO", "Guarani de Goi\u{e1}s", "5209408"], + ["GO", "Guarinos", "5209457"], + ["GO", "Heitora\u{ed}", "5209606"], + ["GO", "Hidrol\u{e2}ndia", "5209705"], + ["GO", "Hidrolina", "5209804"], + ["GO", "Iaciara", "5209903"], + ["GO", "Inaciol\u{e2}ndia", "5209937"], + ["GO", "Indiara", "5209952"], + ["GO", "Inhumas", "5210000"], + ["GO", "Ipameri", "5210109"], + ["GO", "Ipiranga de Goi\u{e1}s", "5210158"], + ["GO", "Ipor\u{e1}", "5210208"], + ["GO", "Israel\u{e2}ndia", "5210307"], + ["GO", "Itabera\u{ed}", "5210406"], + ["GO", "Itaguari", "5210562"], + ["GO", "Itaguaru", "5210604"], + ["GO", "Itaj\u{e1}", "5210802"], + ["GO", "Itapaci", "5210901"], + ["GO", "Itapirapu\u{e3}", "5211008"], + ["GO", "Itapuranga", "5211206"], + ["GO", "Itarum\u{e3}", "5211305"], + ["GO", "Itau\u{e7}u", "5211404"], + ["GO", "Itumbiara", "5211503"], + ["GO", "Ivol\u{e2}ndia", "5211602"], + ["GO", "Jandaia", "5211701"], + ["GO", "Jaragu\u{e1}", "5211800"], + ["GO", "Jata\u{ed}", "5211909"], + ["GO", "Jaupaci", "5212006"], + ["GO", "Jes\u{fa}polis", "5212055"], + ["GO", "Jovi\u{e2}nia", "5212105"], + ["GO", "Jussara", "5212204"], + ["GO", "Lagoa Santa", "5212253"], + ["GO", "Leopoldo de Bulh\u{f5}es", "5212303"], + ["GO", "Luzi\u{e2}nia", "5212501"], + ["GO", "Mairipotaba", "5212600"], + ["GO", "Mamba\u{ed}", "5212709"], + ["GO", "Mara Rosa", "5212808"], + ["GO", "Marzag\u{e3}o", "5212907"], + ["GO", "Matrinch\u{e3}", "5212956"], + ["GO", "Mauril\u{e2}ndia", "5213004"], + ["GO", "Mimoso de Goi\u{e1}s", "5213053"], + ["GO", "Mina\u{e7}u", "5213087"], + ["GO", "Mineiros", "5213103"], + ["GO", "Moipor\u{e1}", "5213400"], + ["GO", "Monte Alegre de Goi\u{e1}s", "5213509"], + ["GO", "Montes Claros de Goi\u{e1}s", "5213707"], + ["GO", "Montividiu", "5213756"], + ["GO", "Montividiu do Norte", "5213772"], + ["GO", "Morrinhos", "5213806"], + ["GO", "Morro Agudo de Goi\u{e1}s", "5213855"], + ["GO", "Moss\u{e2}medes", "5213905"], + ["GO", "Mozarl\u{e2}ndia", "5214002"], + ["GO", "Mundo Novo", "5214051"], + ["GO", "Mutun\u{f3}polis", "5214101"], + ["GO", "Naz\u{e1}rio", "5214408"], + ["GO", "Ner\u{f3}polis", "5214507"], + ["GO", "Niquel\u{e2}ndia", "5214606"], + ["GO", "Nova Am\u{e9}rica", "5214705"], + ["GO", "Nova Aurora", "5214804"], + ["GO", "Nova Crix\u{e1}s", "5214838"], + ["GO", "Nova Gl\u{f3}ria", "5214861"], + ["GO", "Nova Igua\u{e7}u de Goi\u{e1}s", "5214879"], + ["GO", "Nova Roma", "5214903"], + ["GO", "Nova Veneza", "5215009"], + ["GO", "Novo Brasil", "5215207"], + ["GO", "Novo Gama", "5215231"], + ["GO", "Novo Planalto", "5215256"], + ["GO", "Orizona", "5215306"], + ["GO", "Ouro Verde de Goi\u{e1}s", "5215405"], + ["GO", "Ouvidor", "5215504"], + ["GO", "Padre Bernardo", "5215603"], + ["GO", "Palestina de Goi\u{e1}s", "5215652"], + ["GO", "Palmeiras de Goi\u{e1}s", "5215702"], + ["GO", "Palmelo", "5215801"], + ["GO", "Palmin\u{f3}polis", "5215900"], + ["GO", "Panam\u{e1}", "5216007"], + ["GO", "Paranaiguara", "5216304"], + ["GO", "Para\u{fa}na", "5216403"], + ["GO", "Perol\u{e2}ndia", "5216452"], + ["GO", "Petrolina de Goi\u{e1}s", "5216809"], + ["GO", "Pilar de Goi\u{e1}s", "5216908"], + ["GO", "Piracanjuba", "5217104"], + ["GO", "Piranhas", "5217203"], + ["GO", "Piren\u{f3}polis", "5217302"], + ["GO", "Pires do Rio", "5217401"], + ["GO", "Planaltina", "5217609"], + ["GO", "Pontalina", "5217708"], + ["GO", "Porangatu", "5218003"], + ["GO", "Porteir\u{e3}o", "5218052"], + ["GO", "Portel\u{e2}ndia", "5218102"], + ["GO", "Posse", "5218300"], + ["GO", "Professor Jamil", "5218391"], + ["GO", "Quirin\u{f3}polis", "5218508"], + ["GO", "Rialma", "5218607"], + ["GO", "Rian\u{e1}polis", "5218706"], + ["GO", "Rio Quente", "5218789"], + ["GO", "Rio Verde", "5218805"], + ["GO", "Rubiataba", "5218904"], + ["GO", "Sanclerl\u{e2}ndia", "5219001"], + ["GO", "Santa B\u{e1}rbara de Goi\u{e1}s", "5219100"], + ["GO", "Santa Cruz de Goi\u{e1}s", "5219209"], + ["GO", "Santa F\u{e9} de Goi\u{e1}s", "5219258"], + ["GO", "Santa Helena de Goi\u{e1}s", "5219308"], + ["GO", "Santa Isabel", "5219357"], + ["GO", "Santa Rita do Araguaia", "5219407"], + ["GO", "Santa Rita do Novo Destino", "5219456"], + ["GO", "Santa Rosa de Goi\u{e1}s", "5219506"], + ["GO", "Santa Tereza de Goi\u{e1}s", "5219605"], + ["GO", "Santa Terezinha de Goi\u{e1}s", "5219704"], + ["GO", "Santo Ant\u{f4}nio da Barra", "5219712"], + ["GO", "Santo Ant\u{f4}nio de Goi\u{e1}s", "5219738"], + ["GO", "Santo Ant\u{f4}nio do Descoberto", "5219753"], + ["GO", "S\u{e3}o Domingos", "5219803"], + ["GO", "S\u{e3}o Francisco de Goi\u{e1}s", "5219902"], + ["GO", "S\u{e3}o Jo\u{e3}o d'Alian\u{e7}a", "5220009"], + ["GO", "S\u{e3}o Jo\u{e3}o da Para\u{fa}na", "5220058"], + ["GO", "S\u{e3}o Lu\u{ed}s de Montes Belos", "5220108"], + ["GO", "S\u{e3}o Luiz do Norte", "5220157"], + ["GO", "S\u{e3}o Miguel do Araguaia", "5220207"], + ["GO", "S\u{e3}o Miguel do Passa Quatro", "5220264"], + ["GO", "S\u{e3}o Patr\u{ed}cio", "5220280"], + ["GO", "S\u{e3}o Sim\u{e3}o", "5220405"], + ["GO", "Senador Canedo", "5220454"], + ["GO", "Serran\u{f3}polis", "5220504"], + ["GO", "Silv\u{e2}nia", "5220603"], + ["GO", "Simol\u{e2}ndia", "5220686"], + ["GO", "S\u{ed}tio d'Abadia", "5220702"], + ["GO", "Taquaral de Goi\u{e1}s", "5221007"], + ["GO", "Teresina de Goi\u{e1}s", "5221080"], + ["GO", "Terez\u{f3}polis de Goi\u{e1}s", "5221197"], + ["GO", "Tr\u{ea}s Ranchos", "5221304"], + ["GO", "Trindade", "5221403"], + ["GO", "Trombas", "5221452"], + ["GO", "Turv\u{e2}nia", "5221502"], + ["GO", "Turvel\u{e2}ndia", "5221551"], + ["GO", "Uirapuru", "5221577"], + ["GO", "Urua\u{e7}u", "5221601"], + ["GO", "Uruana", "5221700"], + ["GO", "Uruta\u{ed}", "5221809"], + ["GO", "Valpara\u{ed}so de Goi\u{e1}s", "5221858"], + ["GO", "Varj\u{e3}o", "5221908"], + ["GO", "Vian\u{f3}polis", "5222005"], + ["GO", "Vicentin\u{f3}polis", "5222054"], + ["GO", "Vila Boa", "5222203"], + ["GO", "Vila Prop\u{ed}cio", "5222302"], + ["MA", "A\u{e7}ail\u{e2}ndia", "2100055"], + ["MA", "Afonso Cunha", "2100105"], + ["MA", "\u{c1}gua Doce do Maranh\u{e3}o", "2100154"], + ["MA", "Alc\u{e2}ntara", "2100204"], + ["MA", "Aldeias Altas", "2100303"], + ["MA", "Altamira do Maranh\u{e3}o", "2100402"], + ["MA", "Alto Alegre do Maranh\u{e3}o", "2100436"], + ["MA", "Alto Alegre do Pindar\u{e9}", "2100477"], + ["MA", "Alto Parna\u{ed}ba", "2100501"], + ["MA", "Amap\u{e1} do Maranh\u{e3}o", "2100550"], + ["MA", "Amarante do Maranh\u{e3}o", "2100600"], + ["MA", "Anajatuba", "2100709"], + ["MA", "Anapurus", "2100808"], + ["MA", "Apicum-A\u{e7}u", "2100832"], + ["MA", "Araguan\u{e3}", "2100873"], + ["MA", "Araioses", "2100907"], + ["MA", "Arame", "2100956"], + ["MA", "Arari", "2101004"], + ["MA", "Axix\u{e1}", "2101103"], + ["MA", "Bacabal", "2101202"], + ["MA", "Bacabeira", "2101251"], + ["MA", "Bacuri", "2101301"], + ["MA", "Bacurituba", "2101350"], + ["MA", "Balsas", "2101400"], + ["MA", "Bar\u{e3}o de Graja\u{fa}", "2101509"], + ["MA", "Barra do Corda", "2101608"], + ["MA", "Barreirinhas", "2101707"], + ["MA", "Bela Vista do Maranh\u{e3}o", "2101772"], + ["MA", "Bel\u{e1}gua", "2101731"], + ["MA", "Benedito Leite", "2101806"], + ["MA", "Bequim\u{e3}o", "2101905"], + ["MA", "Bernardo do Mearim", "2101939"], + ["MA", "Boa Vista do Gurupi", "2101970"], + ["MA", "Bom Jardim", "2102002"], + ["MA", "Bom Jesus das Selvas", "2102036"], + ["MA", "Bom Lugar", "2102077"], + ["MA", "Brejo", "2102101"], + ["MA", "Brejo de Areia", "2102150"], + ["MA", "Buriti", "2102200"], + ["MA", "Buriti Bravo", "2102309"], + ["MA", "Buriticupu", "2102325"], + ["MA", "Buritirana", "2102358"], + ["MA", "Cachoeira Grande", "2102374"], + ["MA", "Cajapi\u{f3}", "2102408"], + ["MA", "Cajari", "2102507"], + ["MA", "Campestre do Maranh\u{e3}o", "2102556"], + ["MA", "C\u{e2}ndido Mendes", "2102606"], + ["MA", "Cantanhede", "2102705"], + ["MA", "Capinzal do Norte", "2102754"], + ["MA", "Carolina", "2102804"], + ["MA", "Carutapera", "2102903"], + ["MA", "Caxias", "2103000"], + ["MA", "Cedral", "2103109"], + ["MA", "Central do Maranh\u{e3}o", "2103125"], + ["MA", "Centro do Guilherme", "2103158"], + ["MA", "Centro Novo do Maranh\u{e3}o", "2103174"], + ["MA", "Chapadinha", "2103208"], + ["MA", "Cidel\u{e2}ndia", "2103257"], + ["MA", "Cod\u{f3}", "2103307"], + ["MA", "Coelho Neto", "2103406"], + ["MA", "Colinas", "2103505"], + ["MA", "Concei\u{e7}\u{e3}o do Lago-A\u{e7}u", "2103554"], + ["MA", "Coroat\u{e1}", "2103604"], + ["MA", "Cururupu", "2103703"], + ["MA", "Davin\u{f3}polis", "2103752"], + ["MA", "Dom Pedro", "2103802"], + ["MA", "Duque Bacelar", "2103901"], + ["MA", "Esperantin\u{f3}polis", "2104008"], + ["MA", "Estreito", "2104057"], + ["MA", "Feira Nova do Maranh\u{e3}o", "2104073"], + ["MA", "Fernando Falc\u{e3}o", "2104081"], + ["MA", "Formosa da Serra Negra", "2104099"], + ["MA", "Fortaleza dos Nogueiras", "2104107"], + ["MA", "Fortuna", "2104206"], + ["MA", "Godofredo Viana", "2104305"], + ["MA", "Gon\u{e7}alves Dias", "2104404"], + ["MA", "Governador Archer", "2104503"], + ["MA", "Governador Edison Lob\u{e3}o", "2104552"], + ["MA", "Governador Eug\u{ea}nio Barros", "2104602"], + ["MA", "Governador Luiz Rocha", "2104628"], + ["MA", "Governador Newton Bello", "2104651"], + ["MA", "Governador Nunes Freire", "2104677"], + ["MA", "Gra\u{e7}a Aranha", "2104701"], + ["MA", "Graja\u{fa}", "2104800"], + ["MA", "Guimar\u{e3}es", "2104909"], + ["MA", "Humberto de Campos", "2105005"], + ["MA", "Icatu", "2105104"], + ["MA", "Igarap\u{e9} do Meio", "2105153"], + ["MA", "Igarap\u{e9} Grande", "2105203"], + ["MA", "Imperatriz", "2105302"], + ["MA", "Itaipava do Graja\u{fa}", "2105351"], + ["MA", "Itapecuru Mirim", "2105401"], + ["MA", "Itinga do Maranh\u{e3}o", "2105427"], + ["MA", "Jatob\u{e1}", "2105450"], + ["MA", "Jenipapo dos Vieiras", "2105476"], + ["MA", "Jo\u{e3}o Lisboa", "2105500"], + ["MA", "Josel\u{e2}ndia", "2105609"], + ["MA", "Junco do Maranh\u{e3}o", "2105658"], + ["MA", "Lago da Pedra", "2105708"], + ["MA", "Lago do Junco", "2105807"], + ["MA", "Lago dos Rodrigues", "2105948"], + ["MA", "Lago Verde", "2105906"], + ["MA", "Lagoa do Mato", "2105922"], + ["MA", "Lagoa Grande do Maranh\u{e3}o", "2105963"], + ["MA", "Lajeado Novo", "2105989"], + ["MA", "Lima Campos", "2106003"], + ["MA", "Loreto", "2106102"], + ["MA", "Lu\u{ed}s Domingues", "2106201"], + ["MA", "Magalh\u{e3}es de Almeida", "2106300"], + ["MA", "Maraca\u{e7}um\u{e9}", "2106326"], + ["MA", "Maraj\u{e1} do Sena", "2106359"], + ["MA", "Maranh\u{e3}ozinho", "2106375"], + ["MA", "Mata Roma", "2106409"], + ["MA", "Matinha", "2106508"], + ["MA", "Mat\u{f5}es", "2106607"], + ["MA", "Mat\u{f5}es do Norte", "2106631"], + ["MA", "Milagres do Maranh\u{e3}o", "2106672"], + ["MA", "Mirador", "2106706"], + ["MA", "Miranda do Norte", "2106755"], + ["MA", "Mirinzal", "2106805"], + ["MA", "Mon\u{e7}\u{e3}o", "2106904"], + ["MA", "Montes Altos", "2107001"], + ["MA", "Morros", "2107100"], + ["MA", "Nina Rodrigues", "2107209"], + ["MA", "Nova Colinas", "2107258"], + ["MA", "Nova Iorque", "2107308"], + ["MA", "Nova Olinda do Maranh\u{e3}o", "2107357"], + ["MA", "Olho d'\u{c1}gua das Cunh\u{e3}s", "2107407"], + ["MA", "Olinda Nova do Maranh\u{e3}o", "2107456"], + ["MA", "Pa\u{e7}o do Lumiar", "2107506"], + ["MA", "Palmeir\u{e2}ndia", "2107605"], + ["MA", "Paraibano", "2107704"], + ["MA", "Parnarama", "2107803"], + ["MA", "Passagem Franca", "2107902"], + ["MA", "Pastos Bons", "2108009"], + ["MA", "Paulino Neves", "2108058"], + ["MA", "Paulo Ramos", "2108108"], + ["MA", "Pedreiras", "2108207"], + ["MA", "Pedro do Ros\u{e1}rio", "2108256"], + ["MA", "Penalva", "2108306"], + ["MA", "Peri Mirim", "2108405"], + ["MA", "Peritor\u{f3}", "2108454"], + ["MA", "Pindar\u{e9}-Mirim", "2108504"], + ["MA", "Pinheiro", "2108603"], + ["MA", "Pio XII", "2108702"], + ["MA", "Pirapemas", "2108801"], + ["MA", "Po\u{e7}\u{e3}o de Pedras", "2108900"], + ["MA", "Porto Franco", "2109007"], + ["MA", "Porto Rico do Maranh\u{e3}o", "2109056"], + ["MA", "Presidente Dutra", "2109106"], + ["MA", "Presidente Juscelino", "2109205"], + ["MA", "Presidente M\u{e9}dici", "2109239"], + ["MA", "Presidente Sarney", "2109270"], + ["MA", "Presidente Vargas", "2109304"], + ["MA", "Primeira Cruz", "2109403"], + ["MA", "Raposa", "2109452"], + ["MA", "Riach\u{e3}o", "2109502"], + ["MA", "Ribamar Fiquene", "2109551"], + ["MA", "Ros\u{e1}rio", "2109601"], + ["MA", "Samba\u{ed}ba", "2109700"], + ["MA", "Santa Filomena do Maranh\u{e3}o", "2109759"], + ["MA", "Santa Helena", "2109809"], + ["MA", "Santa In\u{ea}s", "2109908"], + ["MA", "Santa Luzia", "2110005"], + ["MA", "Santa Luzia do Paru\u{e1}", "2110039"], + ["MA", "Santa Quit\u{e9}ria do Maranh\u{e3}o", "2110104"], + ["MA", "Santa Rita", "2110203"], + ["MA", "Santana do Maranh\u{e3}o", "2110237"], + ["MA", "Santo Amaro do Maranh\u{e3}o", "2110278"], + ["MA", "Santo Ant\u{f4}nio dos Lopes", "2110302"], + ["MA", "S\u{e3}o Benedito do Rio Preto", "2110401"], + ["MA", "S\u{e3}o Bento", "2110500"], + ["MA", "S\u{e3}o Bernardo", "2110609"], + ["MA", "S\u{e3}o Domingos do Azeit\u{e3}o", "2110658"], + ["MA", "S\u{e3}o Domingos do Maranh\u{e3}o", "2110708"], + ["MA", "S\u{e3}o F\u{e9}lix de Balsas", "2110807"], + ["MA", "S\u{e3}o Francisco do Brej\u{e3}o", "2110856"], + ["MA", "S\u{e3}o Francisco do Maranh\u{e3}o", "2110906"], + ["MA", "S\u{e3}o Jo\u{e3}o Batista", "2111003"], + ["MA", "S\u{e3}o Jo\u{e3}o do Car\u{fa}", "2111029"], + ["MA", "S\u{e3}o Jo\u{e3}o do Para\u{ed}so", "2111052"], + ["MA", "S\u{e3}o Jo\u{e3}o do Soter", "2111078"], + ["MA", "S\u{e3}o Jo\u{e3}o dos Patos", "2111102"], + ["MA", "S\u{e3}o Jos\u{e9} de Ribamar", "2111201"], + ["MA", "S\u{e3}o Jos\u{e9} dos Bas\u{ed}lios", "2111250"], + ["MA", "S\u{e3}o Lu\u{ed}s", "2111300"], + ["MA", "S\u{e3}o Lu\u{ed}s Gonzaga do Maranh\u{e3}o", "2111409"], + ["MA", "S\u{e3}o Mateus do Maranh\u{e3}o", "2111508"], + ["MA", "S\u{e3}o Pedro da \u{c1}gua Branca", "2111532"], + ["MA", "S\u{e3}o Pedro dos Crentes", "2111573"], + ["MA", "S\u{e3}o Raimundo das Mangabeiras", "2111607"], + ["MA", "S\u{e3}o Raimundo do Doca Bezerra", "2111631"], + ["MA", "S\u{e3}o Roberto", "2111672"], + ["MA", "S\u{e3}o Vicente Ferrer", "2111706"], + ["MA", "Satubinha", "2111722"], + ["MA", "Senador Alexandre Costa", "2111748"], + ["MA", "Senador La Rocque", "2111763"], + ["MA", "Serrano do Maranh\u{e3}o", "2111789"], + ["MA", "S\u{ed}tio Novo", "2111805"], + ["MA", "Sucupira do Norte", "2111904"], + ["MA", "Sucupira do Riach\u{e3}o", "2111953"], + ["MA", "Tasso Fragoso", "2112001"], + ["MA", "Timbiras", "2112100"], + ["MA", "Timon", "2112209"], + ["MA", "Trizidela do Vale", "2112233"], + ["MA", "Tufil\u{e2}ndia", "2112274"], + ["MA", "Tuntum", "2112308"], + ["MA", "Turia\u{e7}u", "2112407"], + ["MA", "Turil\u{e2}ndia", "2112456"], + ["MA", "Tut\u{f3}ia", "2112506"], + ["MA", "Urbano Santos", "2112605"], + ["MA", "Vargem Grande", "2112704"], + ["MA", "Viana", "2112803"], + ["MA", "Vila Nova dos Mart\u{ed}rios", "2112852"], + ["MA", "Vit\u{f3}ria do Mearim", "2112902"], + ["MA", "Vitorino Freire", "2113009"], + ["MA", "Z\u{e9} Doca", "2114007"], + ["MT", "Acorizal", "5100102"], + ["MT", "\u{c1}gua Boa", "5100201"], + ["MT", "Alta Floresta", "5100250"], + ["MT", "Alto Araguaia", "5100300"], + ["MT", "Alto Boa Vista", "5100359"], + ["MT", "Alto Gar\u{e7}as", "5100409"], + ["MT", "Alto Paraguai", "5100508"], + ["MT", "Alto Taquari", "5100607"], + ["MT", "Apiac\u{e1}s", "5100805"], + ["MT", "Araguaiana", "5101001"], + ["MT", "Araguainha", "5101209"], + ["MT", "Araputanga", "5101258"], + ["MT", "Aren\u{e1}polis", "5101308"], + ["MT", "Aripuan\u{e3}", "5101407"], + ["MT", "Bar\u{e3}o de Melga\u{e7}o", "5101605"], + ["MT", "Barra do Bugres", "5101704"], + ["MT", "Barra do Gar\u{e7}as", "5101803"], + ["MT", "Boa Esperan\u{e7}a do Norte", "5101837"], + ["MT", "Bom Jesus do Araguaia", "5101852"], + ["MT", "Brasnorte", "5101902"], + ["MT", "C\u{e1}ceres", "5102504"], + ["MT", "Campin\u{e1}polis", "5102603"], + ["MT", "Campo Novo do Parecis", "5102637"], + ["MT", "Campo Verde", "5102678"], + ["MT", "Campos de J\u{fa}lio", "5102686"], + ["MT", "Canabrava do Norte", "5102694"], + ["MT", "Canarana", "5102702"], + ["MT", "Carlinda", "5102793"], + ["MT", "Castanheira", "5102850"], + ["MT", "Chapada dos Guimar\u{e3}es", "5103007"], + ["MT", "Cl\u{e1}udia", "5103056"], + ["MT", "Cocalinho", "5103106"], + ["MT", "Col\u{ed}der", "5103205"], + ["MT", "Colniza", "5103254"], + ["MT", "Comodoro", "5103304"], + ["MT", "Confresa", "5103353"], + ["MT", "Conquista D'Oeste", "5103361"], + ["MT", "Cotrigua\u{e7}u", "5103379"], + ["MT", "Cuiab\u{e1}", "5103403"], + ["MT", "Curvel\u{e2}ndia", "5103437"], + ["MT", "Denise", "5103452"], + ["MT", "Diamantino", "5103502"], + ["MT", "Dom Aquino", "5103601"], + ["MT", "Feliz Natal", "5103700"], + ["MT", "Figueir\u{f3}polis D'Oeste", "5103809"], + ["MT", "Ga\u{fa}cha do Norte", "5103858"], + ["MT", "General Carneiro", "5103908"], + ["MT", "Gl\u{f3}ria D'Oeste", "5103957"], + ["MT", "Guarant\u{e3} do Norte", "5104104"], + ["MT", "Guiratinga", "5104203"], + ["MT", "Indiava\u{ed}", "5104500"], + ["MT", "Ipiranga do Norte", "5104526"], + ["MT", "Itanhang\u{e1}", "5104542"], + ["MT", "Ita\u{fa}ba", "5104559"], + ["MT", "Itiquira", "5104609"], + ["MT", "Jaciara", "5104807"], + ["MT", "Jangada", "5104906"], + ["MT", "Jauru", "5105002"], + ["MT", "Juara", "5105101"], + ["MT", "Ju\u{ed}na", "5105150"], + ["MT", "Juruena", "5105176"], + ["MT", "Juscimeira", "5105200"], + ["MT", "Lambari D'Oeste", "5105234"], + ["MT", "Lucas do Rio Verde", "5105259"], + ["MT", "Luciara", "5105309"], + ["MT", "Marcel\u{e2}ndia", "5105580"], + ["MT", "Matup\u{e1}", "5105606"], + ["MT", "Mirassol d'Oeste", "5105622"], + ["MT", "Nobres", "5105903"], + ["MT", "Nortel\u{e2}ndia", "5106000"], + ["MT", "Nossa Senhora do Livramento", "5106109"], + ["MT", "Nova Bandeirantes", "5106158"], + ["MT", "Nova Brasil\u{e2}ndia", "5106208"], + ["MT", "Nova Cana\u{e3} do Norte", "5106216"], + ["MT", "Nova Guarita", "5108808"], + ["MT", "Nova Lacerda", "5106182"], + ["MT", "Nova Maril\u{e2}ndia", "5108857"], + ["MT", "Nova Maring\u{e1}", "5108907"], + ["MT", "Nova Monte Verde", "5108956"], + ["MT", "Nova Mutum", "5106224"], + ["MT", "Nova Nazar\u{e9}", "5106174"], + ["MT", "Nova Ol\u{ed}mpia", "5106232"], + ["MT", "Nova Santa Helena", "5106190"], + ["MT", "Nova Ubirat\u{e3}", "5106240"], + ["MT", "Nova Xavantina", "5106257"], + ["MT", "Novo Horizonte do Norte", "5106273"], + ["MT", "Novo Mundo", "5106265"], + ["MT", "Novo Santo Ant\u{f4}nio", "5106315"], + ["MT", "Novo S\u{e3}o Joaquim", "5106281"], + ["MT", "Parana\u{ed}ta", "5106299"], + ["MT", "Paranatinga", "5106307"], + ["MT", "Pedra Preta", "5106372"], + ["MT", "Peixoto de Azevedo", "5106422"], + ["MT", "Planalto da Serra", "5106455"], + ["MT", "Pocon\u{e9}", "5106505"], + ["MT", "Pontal do Araguaia", "5106653"], + ["MT", "Ponte Branca", "5106703"], + ["MT", "Pontes e Lacerda", "5106752"], + ["MT", "Porto Alegre do Norte", "5106778"], + ["MT", "Porto dos Ga\u{fa}chos", "5106802"], + ["MT", "Porto Esperidi\u{e3}o", "5106828"], + ["MT", "Porto Estrela", "5106851"], + ["MT", "Poxor\u{e9}u", "5107008"], + ["MT", "Primavera do Leste", "5107040"], + ["MT", "Quer\u{ea}ncia", "5107065"], + ["MT", "Reserva do Caba\u{e7}al", "5107156"], + ["MT", "Ribeir\u{e3}o Cascalheira", "5107180"], + ["MT", "Ribeir\u{e3}ozinho", "5107198"], + ["MT", "Rio Branco", "5107206"], + ["MT", "Rondol\u{e2}ndia", "5107578"], + ["MT", "Rondon\u{f3}polis", "5107602"], + ["MT", "Ros\u{e1}rio Oeste", "5107701"], + ["MT", "Salto do C\u{e9}u", "5107750"], + ["MT", "Santa Carmem", "5107248"], + ["MT", "Santa Cruz do Xingu", "5107743"], + ["MT", "Santa Rita do Trivelato", "5107768"], + ["MT", "Santa Terezinha", "5107776"], + ["MT", "Santo Afonso", "5107263"], + ["MT", "Santo Ant\u{f4}nio de Leverger", "5107800"], + ["MT", "Santo Ant\u{f4}nio do Leste", "5107792"], + ["MT", "S\u{e3}o F\u{e9}lix do Araguaia", "5107859"], + ["MT", "S\u{e3}o Jos\u{e9} do Povo", "5107297"], + ["MT", "S\u{e3}o Jos\u{e9} do Rio Claro", "5107305"], + ["MT", "S\u{e3}o Jos\u{e9} do Xingu", "5107354"], + ["MT", "S\u{e3}o Jos\u{e9} dos Quatro Marcos", "5107107"], + ["MT", "S\u{e3}o Pedro da Cipa", "5107404"], + ["MT", "Sapezal", "5107875"], + ["MT", "Serra Nova Dourada", "5107883"], + ["MT", "Sinop", "5107909"], + ["MT", "Sorriso", "5107925"], + ["MT", "Tabapor\u{e3}", "5107941"], + ["MT", "Tangar\u{e1} da Serra", "5107958"], + ["MT", "Tapurah", "5108006"], + ["MT", "Terra Nova do Norte", "5108055"], + ["MT", "Tesouro", "5108105"], + ["MT", "Torixor\u{e9}u", "5108204"], + ["MT", "Uni\u{e3}o do Sul", "5108303"], + ["MT", "Vale de S\u{e3}o Domingos", "5108352"], + ["MT", "V\u{e1}rzea Grande", "5108402"], + ["MT", "Vera", "5108501"], + ["MT", "Vila Bela da Sant\u{ed}ssima Trindade", "5105507"], + ["MT", "Vila Rica", "5108600"], + ["MS", "\u{c1}gua Clara", "5000203"], + ["MS", "Alcin\u{f3}polis", "5000252"], + ["MS", "Amambai", "5000609"], + ["MS", "Anast\u{e1}cio", "5000708"], + ["MS", "Anauril\u{e2}ndia", "5000807"], + ["MS", "Ang\u{e9}lica", "5000856"], + ["MS", "Ant\u{f4}nio Jo\u{e3}o", "5000906"], + ["MS", "Aparecida do Taboado", "5001003"], + ["MS", "Aquidauana", "5001102"], + ["MS", "Aral Moreira", "5001243"], + ["MS", "Bandeirantes", "5001508"], + ["MS", "Bataguassu", "5001904"], + ["MS", "Bataypor\u{e3}", "5002001"], + ["MS", "Bela Vista", "5002100"], + ["MS", "Bodoquena", "5002159"], + ["MS", "Bonito", "5002209"], + ["MS", "Brasil\u{e2}ndia", "5002308"], + ["MS", "Caarap\u{f3}", "5002407"], + ["MS", "Camapu\u{e3}", "5002605"], + ["MS", "Campo Grande", "5002704"], + ["MS", "Caracol", "5002803"], + ["MS", "Cassil\u{e2}ndia", "5002902"], + ["MS", "Chapad\u{e3}o do Sul", "5002951"], + ["MS", "Corguinho", "5003108"], + ["MS", "Coronel Sapucaia", "5003157"], + ["MS", "Corumb\u{e1}", "5003207"], + ["MS", "Costa Rica", "5003256"], + ["MS", "Coxim", "5003306"], + ["MS", "Deod\u{e1}polis", "5003454"], + ["MS", "Dois Irm\u{e3}os do Buriti", "5003488"], + ["MS", "Douradina", "5003504"], + ["MS", "Dourados", "5003702"], + ["MS", "Eldorado", "5003751"], + ["MS", "F\u{e1}tima do Sul", "5003801"], + ["MS", "Figueir\u{e3}o", "5003900"], + ["MS", "Gl\u{f3}ria de Dourados", "5004007"], + ["MS", "Guia Lopes da Laguna", "5004106"], + ["MS", "Iguatemi", "5004304"], + ["MS", "Inoc\u{ea}ncia", "5004403"], + ["MS", "Itapor\u{e3}", "5004502"], + ["MS", "Itaquira\u{ed}", "5004601"], + ["MS", "Ivinhema", "5004700"], + ["MS", "Japor\u{e3}", "5004809"], + ["MS", "Jaraguari", "5004908"], + ["MS", "Jardim", "5005004"], + ["MS", "Jate\u{ed}", "5005103"], + ["MS", "Juti", "5005152"], + ["MS", "Lad\u{e1}rio", "5005202"], + ["MS", "Laguna Carap\u{e3}", "5005251"], + ["MS", "Maracaju", "5005400"], + ["MS", "Miranda", "5005608"], + ["MS", "Mundo Novo", "5005681"], + ["MS", "Navira\u{ed}", "5005707"], + ["MS", "Nioaque", "5005806"], + ["MS", "Nova Alvorada do Sul", "5006002"], + ["MS", "Nova Andradina", "5006200"], + ["MS", "Novo Horizonte do Sul", "5006259"], + ["MS", "Para\u{ed}so das \u{c1}guas", "5006275"], + ["MS", "Parana\u{ed}ba", "5006309"], + ["MS", "Paranhos", "5006358"], + ["MS", "Pedro Gomes", "5006408"], + ["MS", "Ponta Por\u{e3}", "5006606"], + ["MS", "Porto Murtinho", "5006903"], + ["MS", "Ribas do Rio Pardo", "5007109"], + ["MS", "Rio Brilhante", "5007208"], + ["MS", "Rio Negro", "5007307"], + ["MS", "Rio Verde de Mato Grosso", "5007406"], + ["MS", "Rochedo", "5007505"], + ["MS", "Santa Rita do Pardo", "5007554"], + ["MS", "S\u{e3}o Gabriel do Oeste", "5007695"], + ["MS", "Selv\u{ed}ria", "5007802"], + ["MS", "Sete Quedas", "5007703"], + ["MS", "Sidrol\u{e2}ndia", "5007901"], + ["MS", "Sonora", "5007935"], + ["MS", "Tacuru", "5007950"], + ["MS", "Taquarussu", "5007976"], + ["MS", "Terenos", "5008008"], + ["MS", "Tr\u{ea}s Lagoas", "5008305"], + ["MS", "Vicentina", "5008404"], + ["MG", "Abadia dos Dourados", "3100104"], + ["MG", "Abaet\u{e9}", "3100203"], + ["MG", "Abre Campo", "3100302"], + ["MG", "Acaiaca", "3100401"], + ["MG", "A\u{e7}ucena", "3100500"], + ["MG", "\u{c1}gua Boa", "3100609"], + ["MG", "\u{c1}gua Comprida", "3100708"], + ["MG", "Aguanil", "3100807"], + ["MG", "\u{c1}guas Formosas", "3100906"], + ["MG", "\u{c1}guas Vermelhas", "3101003"], + ["MG", "Aimor\u{e9}s", "3101102"], + ["MG", "Aiuruoca", "3101201"], + ["MG", "Alagoa", "3101300"], + ["MG", "Albertina", "3101409"], + ["MG", "Al\u{e9}m Para\u{ed}ba", "3101508"], + ["MG", "Alfenas", "3101607"], + ["MG", "Alfredo Vasconcelos", "3101631"], + ["MG", "Almenara", "3101706"], + ["MG", "Alpercata", "3101805"], + ["MG", "Alpin\u{f3}polis", "3101904"], + ["MG", "Alterosa", "3102001"], + ["MG", "Alto Capara\u{f3}", "3102050"], + ["MG", "Alto Jequitib\u{e1}", "3153509"], + ["MG", "Alto Rio Doce", "3102100"], + ["MG", "Alvarenga", "3102209"], + ["MG", "Alvin\u{f3}polis", "3102308"], + ["MG", "Alvorada de Minas", "3102407"], + ["MG", "Amparo do Serra", "3102506"], + ["MG", "Andradas", "3102605"], + ["MG", "Andrel\u{e2}ndia", "3102803"], + ["MG", "Angel\u{e2}ndia", "3102852"], + ["MG", "Ant\u{f4}nio Carlos", "3102902"], + ["MG", "Ant\u{f4}nio Dias", "3103009"], + ["MG", "Ant\u{f4}nio Prado de Minas", "3103108"], + ["MG", "Ara\u{e7}a\u{ed}", "3103207"], + ["MG", "Aracitaba", "3103306"], + ["MG", "Ara\u{e7}ua\u{ed}", "3103405"], + ["MG", "Araguari", "3103504"], + ["MG", "Arantina", "3103603"], + ["MG", "Araponga", "3103702"], + ["MG", "Arapor\u{e3}", "3103751"], + ["MG", "Arapu\u{e1}", "3103801"], + ["MG", "Ara\u{fa}jos", "3103900"], + ["MG", "Arax\u{e1}", "3104007"], + ["MG", "Arceburgo", "3104106"], + ["MG", "Arcos", "3104205"], + ["MG", "Areado", "3104304"], + ["MG", "Argirita", "3104403"], + ["MG", "Aricanduva", "3104452"], + ["MG", "Arinos", "3104502"], + ["MG", "Astolfo Dutra", "3104601"], + ["MG", "Atal\u{e9}ia", "3104700"], + ["MG", "Augusto de Lima", "3104809"], + ["MG", "Baependi", "3104908"], + ["MG", "Baldim", "3105004"], + ["MG", "Bambu\u{ed}", "3105103"], + ["MG", "Bandeira", "3105202"], + ["MG", "Bandeira do Sul", "3105301"], + ["MG", "Bar\u{e3}o de Cocais", "3105400"], + ["MG", "Bar\u{e3}o do Monte Alto", "3105509"], + ["MG", "Barbacena", "3105608"], + ["MG", "Barra Longa", "3105707"], + ["MG", "Barroso", "3105905"], + ["MG", "Bela Vista de Minas", "3106002"], + ["MG", "Belmiro Braga", "3106101"], + ["MG", "Belo Horizonte", "3106200"], + ["MG", "Belo Oriente", "3106309"], + ["MG", "Belo Vale", "3106408"], + ["MG", "Berilo", "3106507"], + ["MG", "Berizal", "3106655"], + ["MG", "Bert\u{f3}polis", "3106606"], + ["MG", "Betim", "3106705"], + ["MG", "Bias Fortes", "3106804"], + ["MG", "Bicas", "3106903"], + ["MG", "Biquinhas", "3107000"], + ["MG", "Boa Esperan\u{e7}a", "3107109"], + ["MG", "Bocaina de Minas", "3107208"], + ["MG", "Bocai\u{fa}va", "3107307"], + ["MG", "Bom Despacho", "3107406"], + ["MG", "Bom Jardim de Minas", "3107505"], + ["MG", "Bom Jesus da Penha", "3107604"], + ["MG", "Bom Jesus do Amparo", "3107703"], + ["MG", "Bom Jesus do Galho", "3107802"], + ["MG", "Bom Repouso", "3107901"], + ["MG", "Bom Sucesso", "3108008"], + ["MG", "Bonfim", "3108107"], + ["MG", "Bonfin\u{f3}polis de Minas", "3108206"], + ["MG", "Bonito de Minas", "3108255"], + ["MG", "Borda da Mata", "3108305"], + ["MG", "Botelhos", "3108404"], + ["MG", "Botumirim", "3108503"], + ["MG", "Br\u{e1}s Pires", "3108701"], + ["MG", "Brasil\u{e2}ndia de Minas", "3108552"], + ["MG", "Bras\u{ed}lia de Minas", "3108602"], + ["MG", "Bra\u{fa}nas", "3108800"], + ["MG", "Braz\u{f3}polis", "3108909"], + ["MG", "Brumadinho", "3109006"], + ["MG", "Bueno Brand\u{e3}o", "3109105"], + ["MG", "Buen\u{f3}polis", "3109204"], + ["MG", "Bugre", "3109253"], + ["MG", "Buritis", "3109303"], + ["MG", "Buritizeiro", "3109402"], + ["MG", "Cabeceira Grande", "3109451"], + ["MG", "Cabo Verde", "3109501"], + ["MG", "Cachoeira da Prata", "3109600"], + ["MG", "Cachoeira de Minas", "3109709"], + ["MG", "Cachoeira de Paje\u{fa}", "3102704"], + ["MG", "Cachoeira Dourada", "3109808"], + ["MG", "Caetan\u{f3}polis", "3109907"], + ["MG", "Caet\u{e9}", "3110004"], + ["MG", "Caiana", "3110103"], + ["MG", "Cajuri", "3110202"], + ["MG", "Caldas", "3110301"], + ["MG", "Camacho", "3110400"], + ["MG", "Camanducaia", "3110509"], + ["MG", "Cambu\u{ed}", "3110608"], + ["MG", "Cambuquira", "3110707"], + ["MG", "Campan\u{e1}rio", "3110806"], + ["MG", "Campanha", "3110905"], + ["MG", "Campestre", "3111002"], + ["MG", "Campina Verde", "3111101"], + ["MG", "Campo Azul", "3111150"], + ["MG", "Campo Belo", "3111200"], + ["MG", "Campo do Meio", "3111309"], + ["MG", "Campo Florido", "3111408"], + ["MG", "Campos Altos", "3111507"], + ["MG", "Campos Gerais", "3111606"], + ["MG", "Cana Verde", "3111903"], + ["MG", "Cana\u{e3}", "3111705"], + ["MG", "Can\u{e1}polis", "3111804"], + ["MG", "Candeias", "3112000"], + ["MG", "Cantagalo", "3112059"], + ["MG", "Capara\u{f3}", "3112109"], + ["MG", "Capela Nova", "3112208"], + ["MG", "Capelinha", "3112307"], + ["MG", "Capetinga", "3112406"], + ["MG", "Capim Branco", "3112505"], + ["MG", "Capin\u{f3}polis", "3112604"], + ["MG", "Capit\u{e3}o Andrade", "3112653"], + ["MG", "Capit\u{e3}o En\u{e9}as", "3112703"], + ["MG", "Capit\u{f3}lio", "3112802"], + ["MG", "Caputira", "3112901"], + ["MG", "Cara\u{ed}", "3113008"], + ["MG", "Carana\u{ed}ba", "3113107"], + ["MG", "Caranda\u{ed}", "3113206"], + ["MG", "Carangola", "3113305"], + ["MG", "Caratinga", "3113404"], + ["MG", "Carbonita", "3113503"], + ["MG", "Carea\u{e7}u", "3113602"], + ["MG", "Carlos Chagas", "3113701"], + ["MG", "Carm\u{e9}sia", "3113800"], + ["MG", "Carmo da Cachoeira", "3113909"], + ["MG", "Carmo da Mata", "3114006"], + ["MG", "Carmo de Minas", "3114105"], + ["MG", "Carmo do Cajuru", "3114204"], + ["MG", "Carmo do Parana\u{ed}ba", "3114303"], + ["MG", "Carmo do Rio Claro", "3114402"], + ["MG", "Carm\u{f3}polis de Minas", "3114501"], + ["MG", "Carneirinho", "3114550"], + ["MG", "Carrancas", "3114600"], + ["MG", "Carvalh\u{f3}polis", "3114709"], + ["MG", "Carvalhos", "3114808"], + ["MG", "Casa Grande", "3114907"], + ["MG", "Cascalho Rico", "3115003"], + ["MG", "C\u{e1}ssia", "3115102"], + ["MG", "Cataguases", "3115300"], + ["MG", "Catas Altas", "3115359"], + ["MG", "Catas Altas da Noruega", "3115409"], + ["MG", "Catuji", "3115458"], + ["MG", "Catuti", "3115474"], + ["MG", "Caxambu", "3115508"], + ["MG", "Cedro do Abaet\u{e9}", "3115607"], + ["MG", "Central de Minas", "3115706"], + ["MG", "Centralina", "3115805"], + ["MG", "Ch\u{e1}cara", "3115904"], + ["MG", "Chal\u{e9}", "3116001"], + ["MG", "Chapada do Norte", "3116100"], + ["MG", "Chapada Ga\u{fa}cha", "3116159"], + ["MG", "Chiador", "3116209"], + ["MG", "Cipot\u{e2}nea", "3116308"], + ["MG", "Claraval", "3116407"], + ["MG", "Claro dos Po\u{e7}\u{f5}es", "3116506"], + ["MG", "Cl\u{e1}udio", "3116605"], + ["MG", "Coimbra", "3116704"], + ["MG", "Coluna", "3116803"], + ["MG", "Comendador Gomes", "3116902"], + ["MG", "Comercinho", "3117009"], + ["MG", "Concei\u{e7}\u{e3}o da Aparecida", "3117108"], + ["MG", "Concei\u{e7}\u{e3}o da Barra de Minas", "3115201"], + ["MG", "Concei\u{e7}\u{e3}o das Alagoas", "3117306"], + ["MG", "Concei\u{e7}\u{e3}o das Pedras", "3117207"], + ["MG", "Concei\u{e7}\u{e3}o de Ipanema", "3117405"], + ["MG", "Concei\u{e7}\u{e3}o do Mato Dentro", "3117504"], + ["MG", "Concei\u{e7}\u{e3}o do Par\u{e1}", "3117603"], + ["MG", "Concei\u{e7}\u{e3}o do Rio Verde", "3117702"], + ["MG", "Concei\u{e7}\u{e3}o dos Ouros", "3117801"], + ["MG", "C\u{f4}nego Marinho", "3117836"], + ["MG", "Confins", "3117876"], + ["MG", "Congonhal", "3117900"], + ["MG", "Congonhas", "3118007"], + ["MG", "Congonhas do Norte", "3118106"], + ["MG", "Conquista", "3118205"], + ["MG", "Conselheiro Lafaiete", "3118304"], + ["MG", "Conselheiro Pena", "3118403"], + ["MG", "Consola\u{e7}\u{e3}o", "3118502"], + ["MG", "Contagem", "3118601"], + ["MG", "Coqueiral", "3118700"], + ["MG", "Cora\u{e7}\u{e3}o de Jesus", "3118809"], + ["MG", "Cordisburgo", "3118908"], + ["MG", "Cordisl\u{e2}ndia", "3119005"], + ["MG", "Corinto", "3119104"], + ["MG", "Coroaci", "3119203"], + ["MG", "Coromandel", "3119302"], + ["MG", "Coronel Fabriciano", "3119401"], + ["MG", "Coronel Murta", "3119500"], + ["MG", "Coronel Pacheco", "3119609"], + ["MG", "Coronel Xavier Chaves", "3119708"], + ["MG", "C\u{f3}rrego Danta", "3119807"], + ["MG", "C\u{f3}rrego do Bom Jesus", "3119906"], + ["MG", "C\u{f3}rrego Fundo", "3119955"], + ["MG", "C\u{f3}rrego Novo", "3120003"], + ["MG", "Couto de Magalh\u{e3}es de Minas", "3120102"], + ["MG", "Cris\u{f3}lita", "3120151"], + ["MG", "Cristais", "3120201"], + ["MG", "Crist\u{e1}lia", "3120300"], + ["MG", "Cristiano Otoni", "3120409"], + ["MG", "Cristina", "3120508"], + ["MG", "Crucil\u{e2}ndia", "3120607"], + ["MG", "Cruzeiro da Fortaleza", "3120706"], + ["MG", "Cruz\u{ed}lia", "3120805"], + ["MG", "Cuparaque", "3120839"], + ["MG", "Curral de Dentro", "3120870"], + ["MG", "Curvelo", "3120904"], + ["MG", "Datas", "3121001"], + ["MG", "Delfim Moreira", "3121100"], + ["MG", "Delfin\u{f3}polis", "3121209"], + ["MG", "Delta", "3121258"], + ["MG", "Descoberto", "3121308"], + ["MG", "Desterro de Entre Rios", "3121407"], + ["MG", "Desterro do Melo", "3121506"], + ["MG", "Diamantina", "3121605"], + ["MG", "Diogo de Vasconcelos", "3121704"], + ["MG", "Dion\u{ed}sio", "3121803"], + ["MG", "Divin\u{e9}sia", "3121902"], + ["MG", "Divino", "3122009"], + ["MG", "Divino das Laranjeiras", "3122108"], + ["MG", "Divinol\u{e2}ndia de Minas", "3122207"], + ["MG", "Divin\u{f3}polis", "3122306"], + ["MG", "Divisa Alegre", "3122355"], + ["MG", "Divisa Nova", "3122405"], + ["MG", "Divis\u{f3}polis", "3122454"], + ["MG", "Dom Bosco", "3122470"], + ["MG", "Dom Cavati", "3122504"], + ["MG", "Dom Joaquim", "3122603"], + ["MG", "Dom Silv\u{e9}rio", "3122702"], + ["MG", "Dom Vi\u{e7}oso", "3122801"], + ["MG", "Dona Euz\u{e9}bia", "3122900"], + ["MG", "Dores de Campos", "3123007"], + ["MG", "Dores de Guanh\u{e3}es", "3123106"], + ["MG", "Dores do Indai\u{e1}", "3123205"], + ["MG", "Dores do Turvo", "3123304"], + ["MG", "Dores\u{f3}polis", "3123403"], + ["MG", "Douradoquara", "3123502"], + ["MG", "Durand\u{e9}", "3123528"], + ["MG", "El\u{f3}i Mendes", "3123601"], + ["MG", "Engenheiro Caldas", "3123700"], + ["MG", "Engenheiro Navarro", "3123809"], + ["MG", "Entre Folhas", "3123858"], + ["MG", "Entre Rios de Minas", "3123908"], + ["MG", "Erv\u{e1}lia", "3124005"], + ["MG", "Esmeraldas", "3124104"], + ["MG", "Espera Feliz", "3124203"], + ["MG", "Espinosa", "3124302"], + ["MG", "Esp\u{ed}rito Santo do Dourado", "3124401"], + ["MG", "Estiva", "3124500"], + ["MG", "Estrela Dalva", "3124609"], + ["MG", "Estrela do Indai\u{e1}", "3124708"], + ["MG", "Estrela do Sul", "3124807"], + ["MG", "Eugen\u{f3}polis", "3124906"], + ["MG", "Ewbank da C\u{e2}mara", "3125002"], + ["MG", "Extrema", "3125101"], + ["MG", "Fama", "3125200"], + ["MG", "Faria Lemos", "3125309"], + ["MG", "Fel\u{ed}cio dos Santos", "3125408"], + ["MG", "Felisburgo", "3125606"], + ["MG", "Felixl\u{e2}ndia", "3125705"], + ["MG", "Fernandes Tourinho", "3125804"], + ["MG", "Ferros", "3125903"], + ["MG", "Fervedouro", "3125952"], + ["MG", "Florestal", "3126000"], + ["MG", "Formiga", "3126109"], + ["MG", "Formoso", "3126208"], + ["MG", "Fortaleza de Minas", "3126307"], + ["MG", "Fortuna de Minas", "3126406"], + ["MG", "Francisco Badar\u{f3}", "3126505"], + ["MG", "Francisco Dumont", "3126604"], + ["MG", "Francisco S\u{e1}", "3126703"], + ["MG", "Francisc\u{f3}polis", "3126752"], + ["MG", "Frei Gaspar", "3126802"], + ["MG", "Frei Inoc\u{ea}ncio", "3126901"], + ["MG", "Frei Lagonegro", "3126950"], + ["MG", "Fronteira", "3127008"], + ["MG", "Fronteira dos Vales", "3127057"], + ["MG", "Fruta de Leite", "3127073"], + ["MG", "Frutal", "3127107"], + ["MG", "Funil\u{e2}ndia", "3127206"], + ["MG", "Galil\u{e9}ia", "3127305"], + ["MG", "Gameleiras", "3127339"], + ["MG", "Glaucil\u{e2}ndia", "3127354"], + ["MG", "Goiabeira", "3127370"], + ["MG", "Goian\u{e1}", "3127388"], + ["MG", "Gon\u{e7}alves", "3127404"], + ["MG", "Gonzaga", "3127503"], + ["MG", "Gouveia", "3127602"], + ["MG", "Governador Valadares", "3127701"], + ["MG", "Gr\u{e3}o Mogol", "3127800"], + ["MG", "Grupiara", "3127909"], + ["MG", "Guanh\u{e3}es", "3128006"], + ["MG", "Guap\u{e9}", "3128105"], + ["MG", "Guaraciaba", "3128204"], + ["MG", "Guaraciama", "3128253"], + ["MG", "Guaran\u{e9}sia", "3128303"], + ["MG", "Guarani", "3128402"], + ["MG", "Guarar\u{e1}", "3128501"], + ["MG", "Guarda-Mor", "3128600"], + ["MG", "Guaxup\u{e9}", "3128709"], + ["MG", "Guidoval", "3128808"], + ["MG", "Guimar\u{e2}nia", "3128907"], + ["MG", "Guiricema", "3129004"], + ["MG", "Gurinhat\u{e3}", "3129103"], + ["MG", "Heliodora", "3129202"], + ["MG", "Iapu", "3129301"], + ["MG", "Ibertioga", "3129400"], + ["MG", "Ibi\u{e1}", "3129509"], + ["MG", "Ibia\u{ed}", "3129608"], + ["MG", "Ibiracatu", "3129657"], + ["MG", "Ibiraci", "3129707"], + ["MG", "Ibirit\u{e9}", "3129806"], + ["MG", "Ibiti\u{fa}ra de Minas", "3129905"], + ["MG", "Ibituruna", "3130002"], + ["MG", "Icara\u{ed} de Minas", "3130051"], + ["MG", "Igarap\u{e9}", "3130101"], + ["MG", "Igaratinga", "3130200"], + ["MG", "Iguatama", "3130309"], + ["MG", "Ijaci", "3130408"], + ["MG", "Ilic\u{ed}nea", "3130507"], + ["MG", "Imb\u{e9} de Minas", "3130556"], + ["MG", "Inconfidentes", "3130606"], + ["MG", "Indaiabira", "3130655"], + ["MG", "Indian\u{f3}polis", "3130705"], + ["MG", "Inga\u{ed}", "3130804"], + ["MG", "Inhapim", "3130903"], + ["MG", "Inha\u{fa}ma", "3131000"], + ["MG", "Inimutaba", "3131109"], + ["MG", "Ipaba", "3131158"], + ["MG", "Ipanema", "3131208"], + ["MG", "Ipatinga", "3131307"], + ["MG", "Ipia\u{e7}u", "3131406"], + ["MG", "Ipui\u{fa}na", "3131505"], + ["MG", "Ira\u{ed} de Minas", "3131604"], + ["MG", "Itabira", "3131703"], + ["MG", "Itabirinha", "3131802"], + ["MG", "Itabirito", "3131901"], + ["MG", "Itacambira", "3132008"], + ["MG", "Itacarambi", "3132107"], + ["MG", "Itaguara", "3132206"], + ["MG", "Itaip\u{e9}", "3132305"], + ["MG", "Itajub\u{e1}", "3132404"], + ["MG", "Itamarandiba", "3132503"], + ["MG", "Itamarati de Minas", "3132602"], + ["MG", "Itambacuri", "3132701"], + ["MG", "Itamb\u{e9} do Mato Dentro", "3132800"], + ["MG", "Itamogi", "3132909"], + ["MG", "Itamonte", "3133006"], + ["MG", "Itanhandu", "3133105"], + ["MG", "Itanhomi", "3133204"], + ["MG", "Itaobim", "3133303"], + ["MG", "Itapagipe", "3133402"], + ["MG", "Itapecerica", "3133501"], + ["MG", "Itapeva", "3133600"], + ["MG", "Itatiaiu\u{e7}u", "3133709"], + ["MG", "Ita\u{fa} de Minas", "3133758"], + ["MG", "Ita\u{fa}na", "3133808"], + ["MG", "Itaverava", "3133907"], + ["MG", "Itinga", "3134004"], + ["MG", "Itueta", "3134103"], + ["MG", "Ituiutaba", "3134202"], + ["MG", "Itumirim", "3134301"], + ["MG", "Iturama", "3134400"], + ["MG", "Itutinga", "3134509"], + ["MG", "Jaboticatubas", "3134608"], + ["MG", "Jacinto", "3134707"], + ["MG", "Jacu\u{ed}", "3134806"], + ["MG", "Jacutinga", "3134905"], + ["MG", "Jaguara\u{e7}u", "3135001"], + ["MG", "Ja\u{ed}ba", "3135050"], + ["MG", "Jampruca", "3135076"], + ["MG", "Jana\u{fa}ba", "3135100"], + ["MG", "Janu\u{e1}ria", "3135209"], + ["MG", "Japara\u{ed}ba", "3135308"], + ["MG", "Japonvar", "3135357"], + ["MG", "Jeceaba", "3135407"], + ["MG", "Jenipapo de Minas", "3135456"], + ["MG", "Jequeri", "3135506"], + ["MG", "Jequita\u{ed}", "3135605"], + ["MG", "Jequitib\u{e1}", "3135704"], + ["MG", "Jequitinhonha", "3135803"], + ["MG", "Jesu\u{e2}nia", "3135902"], + ["MG", "Joa\u{ed}ma", "3136009"], + ["MG", "Joan\u{e9}sia", "3136108"], + ["MG", "Jo\u{e3}o Monlevade", "3136207"], + ["MG", "Jo\u{e3}o Pinheiro", "3136306"], + ["MG", "Joaquim Fel\u{ed}cio", "3136405"], + ["MG", "Jord\u{e2}nia", "3136504"], + ["MG", "Jos\u{e9} Gon\u{e7}alves de Minas", "3136520"], + ["MG", "Jos\u{e9} Raydan", "3136553"], + ["MG", "Josen\u{f3}polis", "3136579"], + ["MG", "Juatuba", "3136652"], + ["MG", "Juiz de Fora", "3136702"], + ["MG", "Juramento", "3136801"], + ["MG", "Juruaia", "3136900"], + ["MG", "Juven\u{ed}lia", "3136959"], + ["MG", "Ladainha", "3137007"], + ["MG", "Lagamar", "3137106"], + ["MG", "Lagoa da Prata", "3137205"], + ["MG", "Lagoa dos Patos", "3137304"], + ["MG", "Lagoa Dourada", "3137403"], + ["MG", "Lagoa Formosa", "3137502"], + ["MG", "Lagoa Grande", "3137536"], + ["MG", "Lagoa Santa", "3137601"], + ["MG", "Lajinha", "3137700"], + ["MG", "Lambari", "3137809"], + ["MG", "Lamim", "3137908"], + ["MG", "Laranjal", "3138005"], + ["MG", "Lassance", "3138104"], + ["MG", "Lavras", "3138203"], + ["MG", "Leandro Ferreira", "3138302"], + ["MG", "Leme do Prado", "3138351"], + ["MG", "Leopoldina", "3138401"], + ["MG", "Liberdade", "3138500"], + ["MG", "Lima Duarte", "3138609"], + ["MG", "Limeira do Oeste", "3138625"], + ["MG", "Lontra", "3138658"], + ["MG", "Luisburgo", "3138674"], + ["MG", "Luisl\u{e2}ndia", "3138682"], + ["MG", "Lumin\u{e1}rias", "3138708"], + ["MG", "Luz", "3138807"], + ["MG", "Machacalis", "3138906"], + ["MG", "Machado", "3139003"], + ["MG", "Madre de Deus de Minas", "3139102"], + ["MG", "Malacacheta", "3139201"], + ["MG", "Mamonas", "3139250"], + ["MG", "Manga", "3139300"], + ["MG", "Manhua\u{e7}u", "3139409"], + ["MG", "Manhumirim", "3139508"], + ["MG", "Mantena", "3139607"], + ["MG", "Mar de Espanha", "3139805"], + ["MG", "Maravilhas", "3139706"], + ["MG", "Maria da F\u{e9}", "3139904"], + ["MG", "Mariana", "3140001"], + ["MG", "Marilac", "3140100"], + ["MG", "M\u{e1}rio Campos", "3140159"], + ["MG", "Marip\u{e1} de Minas", "3140209"], + ["MG", "Marli\u{e9}ria", "3140308"], + ["MG", "Marmel\u{f3}polis", "3140407"], + ["MG", "Martinho Campos", "3140506"], + ["MG", "Martins Soares", "3140530"], + ["MG", "Mata Verde", "3140555"], + ["MG", "Materl\u{e2}ndia", "3140605"], + ["MG", "Mateus Leme", "3140704"], + ["MG", "Mathias Lobato", "3171501"], + ["MG", "Matias Barbosa", "3140803"], + ["MG", "Matias Cardoso", "3140852"], + ["MG", "Matip\u{f3}", "3140902"], + ["MG", "Mato Verde", "3141009"], + ["MG", "Matozinhos", "3141108"], + ["MG", "Matutina", "3141207"], + ["MG", "Medeiros", "3141306"], + ["MG", "Medina", "3141405"], + ["MG", "Mendes Pimentel", "3141504"], + ["MG", "Merc\u{ea}s", "3141603"], + ["MG", "Mesquita", "3141702"], + ["MG", "Minas Novas", "3141801"], + ["MG", "Minduri", "3141900"], + ["MG", "Mirabela", "3142007"], + ["MG", "Miradouro", "3142106"], + ["MG", "Mira\u{ed}", "3142205"], + ["MG", "Mirav\u{e2}nia", "3142254"], + ["MG", "Moeda", "3142304"], + ["MG", "Moema", "3142403"], + ["MG", "Monjolos", "3142502"], + ["MG", "Monsenhor Paulo", "3142601"], + ["MG", "Montalv\u{e2}nia", "3142700"], + ["MG", "Monte Alegre de Minas", "3142809"], + ["MG", "Monte Azul", "3142908"], + ["MG", "Monte Belo", "3143005"], + ["MG", "Monte Carmelo", "3143104"], + ["MG", "Monte Formoso", "3143153"], + ["MG", "Monte Santo de Minas", "3143203"], + ["MG", "Monte Si\u{e3}o", "3143401"], + ["MG", "Montes Claros", "3143302"], + ["MG", "Montezuma", "3143450"], + ["MG", "Morada Nova de Minas", "3143500"], + ["MG", "Morro da Gar\u{e7}a", "3143609"], + ["MG", "Morro do Pilar", "3143708"], + ["MG", "Munhoz", "3143807"], + ["MG", "Muria\u{e9}", "3143906"], + ["MG", "Mutum", "3144003"], + ["MG", "Muzambinho", "3144102"], + ["MG", "Nacip Raydan", "3144201"], + ["MG", "Nanuque", "3144300"], + ["MG", "Naque", "3144359"], + ["MG", "Natal\u{e2}ndia", "3144375"], + ["MG", "Nat\u{e9}rcia", "3144409"], + ["MG", "Nazareno", "3144508"], + ["MG", "Nepomuceno", "3144607"], + ["MG", "Ninheira", "3144656"], + ["MG", "Nova Bel\u{e9}m", "3144672"], + ["MG", "Nova Era", "3144706"], + ["MG", "Nova Lima", "3144805"], + ["MG", "Nova M\u{f3}dica", "3144904"], + ["MG", "Nova Ponte", "3145000"], + ["MG", "Nova Porteirinha", "3145059"], + ["MG", "Nova Resende", "3145109"], + ["MG", "Nova Serrana", "3145208"], + ["MG", "Nova Uni\u{e3}o", "3136603"], + ["MG", "Novo Cruzeiro", "3145307"], + ["MG", "Novo Oriente de Minas", "3145356"], + ["MG", "Novorizonte", "3145372"], + ["MG", "Olaria", "3145406"], + ["MG", "Olhos-d'\u{c1}gua", "3145455"], + ["MG", "Ol\u{ed}mpio Noronha", "3145505"], + ["MG", "Oliveira", "3145604"], + ["MG", "Oliveira Fortes", "3145703"], + ["MG", "On\u{e7}a de Pitangui", "3145802"], + ["MG", "Orat\u{f3}rios", "3145851"], + ["MG", "Oriz\u{e2}nia", "3145877"], + ["MG", "Ouro Branco", "3145901"], + ["MG", "Ouro Fino", "3146008"], + ["MG", "Ouro Preto", "3146107"], + ["MG", "Ouro Verde de Minas", "3146206"], + ["MG", "Padre Carvalho", "3146255"], + ["MG", "Padre Para\u{ed}so", "3146305"], + ["MG", "Pai Pedro", "3146552"], + ["MG", "Paineiras", "3146404"], + ["MG", "Pains", "3146503"], + ["MG", "Paiva", "3146602"], + ["MG", "Palma", "3146701"], + ["MG", "Palm\u{f3}polis", "3146750"], + ["MG", "Papagaios", "3146909"], + ["MG", "Par\u{e1} de Minas", "3147105"], + ["MG", "Paracatu", "3147006"], + ["MG", "Paragua\u{e7}u", "3147204"], + ["MG", "Parais\u{f3}polis", "3147303"], + ["MG", "Paraopeba", "3147402"], + ["MG", "Passa Quatro", "3147600"], + ["MG", "Passa Tempo", "3147709"], + ["MG", "Passa Vinte", "3147808"], + ["MG", "Passab\u{e9}m", "3147501"], + ["MG", "Passos", "3147907"], + ["MG", "Patis", "3147956"], + ["MG", "Patos de Minas", "3148004"], + ["MG", "Patroc\u{ed}nio", "3148103"], + ["MG", "Patroc\u{ed}nio do Muria\u{e9}", "3148202"], + ["MG", "Paula C\u{e2}ndido", "3148301"], + ["MG", "Paulistas", "3148400"], + ["MG", "Pav\u{e3}o", "3148509"], + ["MG", "Pe\u{e7}anha", "3148608"], + ["MG", "Pedra Azul", "3148707"], + ["MG", "Pedra Bonita", "3148756"], + ["MG", "Pedra do Anta", "3148806"], + ["MG", "Pedra do Indai\u{e1}", "3148905"], + ["MG", "Pedra Dourada", "3149002"], + ["MG", "Pedralva", "3149101"], + ["MG", "Pedras de Maria da Cruz", "3149150"], + ["MG", "Pedrin\u{f3}polis", "3149200"], + ["MG", "Pedro Leopoldo", "3149309"], + ["MG", "Pedro Teixeira", "3149408"], + ["MG", "Pequeri", "3149507"], + ["MG", "Pequi", "3149606"], + ["MG", "Perdig\u{e3}o", "3149705"], + ["MG", "Perdizes", "3149804"], + ["MG", "Perd\u{f5}es", "3149903"], + ["MG", "Periquito", "3149952"], + ["MG", "Pescador", "3150000"], + ["MG", "Piau", "3150109"], + ["MG", "Piedade de Caratinga", "3150158"], + ["MG", "Piedade de Ponte Nova", "3150208"], + ["MG", "Piedade do Rio Grande", "3150307"], + ["MG", "Piedade dos Gerais", "3150406"], + ["MG", "Pimenta", "3150505"], + ["MG", "Pingo-d'\u{c1}gua", "3150539"], + ["MG", "Pint\u{f3}polis", "3150570"], + ["MG", "Piracema", "3150604"], + ["MG", "Pirajuba", "3150703"], + ["MG", "Piranga", "3150802"], + ["MG", "Pirangu\u{e7}u", "3150901"], + ["MG", "Piranguinho", "3151008"], + ["MG", "Pirapetinga", "3151107"], + ["MG", "Pirapora", "3151206"], + ["MG", "Pira\u{fa}ba", "3151305"], + ["MG", "Pitangui", "3151404"], + ["MG", "Piumhi", "3151503"], + ["MG", "Planura", "3151602"], + ["MG", "Po\u{e7}o Fundo", "3151701"], + ["MG", "Po\u{e7}os de Caldas", "3151800"], + ["MG", "Pocrane", "3151909"], + ["MG", "Pomp\u{e9}u", "3152006"], + ["MG", "Ponte Nova", "3152105"], + ["MG", "Ponto Chique", "3152131"], + ["MG", "Ponto dos Volantes", "3152170"], + ["MG", "Porteirinha", "3152204"], + ["MG", "Porto Firme", "3152303"], + ["MG", "Pot\u{e9}", "3152402"], + ["MG", "Pouso Alegre", "3152501"], + ["MG", "Pouso Alto", "3152600"], + ["MG", "Prados", "3152709"], + ["MG", "Prata", "3152808"], + ["MG", "Prat\u{e1}polis", "3152907"], + ["MG", "Pratinha", "3153004"], + ["MG", "Presidente Bernardes", "3153103"], + ["MG", "Presidente Juscelino", "3153202"], + ["MG", "Presidente Kubitschek", "3153301"], + ["MG", "Presidente Oleg\u{e1}rio", "3153400"], + ["MG", "Prudente de Morais", "3153608"], + ["MG", "Quartel Geral", "3153707"], + ["MG", "Queluzito", "3153806"], + ["MG", "Raposos", "3153905"], + ["MG", "Raul Soares", "3154002"], + ["MG", "Recreio", "3154101"], + ["MG", "Reduto", "3154150"], + ["MG", "Resende Costa", "3154200"], + ["MG", "Resplendor", "3154309"], + ["MG", "Ressaquinha", "3154408"], + ["MG", "Riachinho", "3154457"], + ["MG", "Riacho dos Machados", "3154507"], + ["MG", "Ribeir\u{e3}o das Neves", "3154606"], + ["MG", "Ribeir\u{e3}o Vermelho", "3154705"], + ["MG", "Rio Acima", "3154804"], + ["MG", "Rio Casca", "3154903"], + ["MG", "Rio do Prado", "3155108"], + ["MG", "Rio Doce", "3155009"], + ["MG", "Rio Espera", "3155207"], + ["MG", "Rio Manso", "3155306"], + ["MG", "Rio Novo", "3155405"], + ["MG", "Rio Parana\u{ed}ba", "3155504"], + ["MG", "Rio Pardo de Minas", "3155603"], + ["MG", "Rio Piracicaba", "3155702"], + ["MG", "Rio Pomba", "3155801"], + ["MG", "Rio Preto", "3155900"], + ["MG", "Rio Vermelho", "3156007"], + ["MG", "Rit\u{e1}polis", "3156106"], + ["MG", "Rochedo de Minas", "3156205"], + ["MG", "Rodeiro", "3156304"], + ["MG", "Romaria", "3156403"], + ["MG", "Ros\u{e1}rio da Limeira", "3156452"], + ["MG", "Rubelita", "3156502"], + ["MG", "Rubim", "3156601"], + ["MG", "Sabar\u{e1}", "3156700"], + ["MG", "Sabin\u{f3}polis", "3156809"], + ["MG", "Sacramento", "3156908"], + ["MG", "Salinas", "3157005"], + ["MG", "Salto da Divisa", "3157104"], + ["MG", "Santa B\u{e1}rbara", "3157203"], + ["MG", "Santa B\u{e1}rbara do Leste", "3157252"], + ["MG", "Santa B\u{e1}rbara do Monte Verde", "3157278"], + ["MG", "Santa B\u{e1}rbara do Tug\u{fa}rio", "3157302"], + ["MG", "Santa Cruz de Minas", "3157336"], + ["MG", "Santa Cruz de Salinas", "3157377"], + ["MG", "Santa Cruz do Escalvado", "3157401"], + ["MG", "Santa Efig\u{ea}nia de Minas", "3157500"], + ["MG", "Santa F\u{e9} de Minas", "3157609"], + ["MG", "Santa Helena de Minas", "3157658"], + ["MG", "Santa Juliana", "3157708"], + ["MG", "Santa Luzia", "3157807"], + ["MG", "Santa Margarida", "3157906"], + ["MG", "Santa Maria de Itabira", "3158003"], + ["MG", "Santa Maria do Salto", "3158102"], + ["MG", "Santa Maria do Sua\u{e7}u\u{ed}", "3158201"], + ["MG", "Santa Rita de Caldas", "3159209"], + ["MG", "Santa Rita de Ibitipoca", "3159407"], + ["MG", "Santa Rita de Jacutinga", "3159308"], + ["MG", "Santa Rita de Minas", "3159357"], + ["MG", "Santa Rita do Itueto", "3159506"], + ["MG", "Santa Rita do Sapuca\u{ed}", "3159605"], + ["MG", "Santa Rosa da Serra", "3159704"], + ["MG", "Santa Vit\u{f3}ria", "3159803"], + ["MG", "Santana da Vargem", "3158300"], + ["MG", "Santana de Cataguases", "3158409"], + ["MG", "Santana de Pirapama", "3158508"], + ["MG", "Santana do Deserto", "3158607"], + ["MG", "Santana do Garamb\u{e9}u", "3158706"], + ["MG", "Santana do Jacar\u{e9}", "3158805"], + ["MG", "Santana do Manhua\u{e7}u", "3158904"], + ["MG", "Santana do Para\u{ed}so", "3158953"], + ["MG", "Santana do Riacho", "3159001"], + ["MG", "Santana dos Montes", "3159100"], + ["MG", "Santo Ant\u{f4}nio do Amparo", "3159902"], + ["MG", "Santo Ant\u{f4}nio do Aventureiro", "3160009"], + ["MG", "Santo Ant\u{f4}nio do Grama", "3160108"], + ["MG", "Santo Ant\u{f4}nio do Itamb\u{e9}", "3160207"], + ["MG", "Santo Ant\u{f4}nio do Jacinto", "3160306"], + ["MG", "Santo Ant\u{f4}nio do Monte", "3160405"], + ["MG", "Santo Ant\u{f4}nio do Retiro", "3160454"], + ["MG", "Santo Ant\u{f4}nio do Rio Abaixo", "3160504"], + ["MG", "Santo Hip\u{f3}lito", "3160603"], + ["MG", "Santos Dumont", "3160702"], + ["MG", "S\u{e3}o Bento Abade", "3160801"], + ["MG", "S\u{e3}o Br\u{e1}s do Sua\u{e7}u\u{ed}", "3160900"], + ["MG", "S\u{e3}o Domingos das Dores", "3160959"], + ["MG", "S\u{e3}o Domingos do Prata", "3161007"], + ["MG", "S\u{e3}o F\u{e9}lix de Minas", "3161056"], + ["MG", "S\u{e3}o Francisco", "3161106"], + ["MG", "S\u{e3}o Francisco de Paula", "3161205"], + ["MG", "S\u{e3}o Francisco de Sales", "3161304"], + ["MG", "S\u{e3}o Francisco do Gl\u{f3}ria", "3161403"], + ["MG", "S\u{e3}o Geraldo", "3161502"], + ["MG", "S\u{e3}o Geraldo da Piedade", "3161601"], + ["MG", "S\u{e3}o Geraldo do Baixio", "3161650"], + ["MG", "S\u{e3}o Gon\u{e7}alo do Abaet\u{e9}", "3161700"], + ["MG", "S\u{e3}o Gon\u{e7}alo do Par\u{e1}", "3161809"], + ["MG", "S\u{e3}o Gon\u{e7}alo do Rio Abaixo", "3161908"], + ["MG", "S\u{e3}o Gon\u{e7}alo do Rio Preto", "3125507"], + ["MG", "S\u{e3}o Gon\u{e7}alo do Sapuca\u{ed}", "3162005"], + ["MG", "S\u{e3}o Gotardo", "3162104"], + ["MG", "S\u{e3}o Jo\u{e3}o Batista do Gl\u{f3}ria", "3162203"], + ["MG", "S\u{e3}o Jo\u{e3}o da Lagoa", "3162252"], + ["MG", "S\u{e3}o Jo\u{e3}o da Mata", "3162302"], + ["MG", "S\u{e3}o Jo\u{e3}o da Ponte", "3162401"], + ["MG", "S\u{e3}o Jo\u{e3}o das Miss\u{f5}es", "3162450"], + ["MG", "S\u{e3}o Jo\u{e3}o del Rei", "3162500"], + ["MG", "S\u{e3}o Jo\u{e3}o do Manhua\u{e7}u", "3162559"], + ["MG", "S\u{e3}o Jo\u{e3}o do Manteninha", "3162575"], + ["MG", "S\u{e3}o Jo\u{e3}o do Oriente", "3162609"], + ["MG", "S\u{e3}o Jo\u{e3}o do Pacu\u{ed}", "3162658"], + ["MG", "S\u{e3}o Jo\u{e3}o do Para\u{ed}so", "3162708"], + ["MG", "S\u{e3}o Jo\u{e3}o Evangelista", "3162807"], + ["MG", "S\u{e3}o Jo\u{e3}o Nepomuceno", "3162906"], + ["MG", "S\u{e3}o Joaquim de Bicas", "3162922"], + ["MG", "S\u{e3}o Jos\u{e9} da Barra", "3162948"], + ["MG", "S\u{e3}o Jos\u{e9} da Lapa", "3162955"], + ["MG", "S\u{e3}o Jos\u{e9} da Safira", "3163003"], + ["MG", "S\u{e3}o Jos\u{e9} da Varginha", "3163102"], + ["MG", "S\u{e3}o Jos\u{e9} do Alegre", "3163201"], + ["MG", "S\u{e3}o Jos\u{e9} do Divino", "3163300"], + ["MG", "S\u{e3}o Jos\u{e9} do Goiabal", "3163409"], + ["MG", "S\u{e3}o Jos\u{e9} do Jacuri", "3163508"], + ["MG", "S\u{e3}o Jos\u{e9} do Mantimento", "3163607"], + ["MG", "S\u{e3}o Louren\u{e7}o", "3163706"], + ["MG", "S\u{e3}o Miguel do Anta", "3163805"], + ["MG", "S\u{e3}o Pedro da Uni\u{e3}o", "3163904"], + ["MG", "S\u{e3}o Pedro do Sua\u{e7}u\u{ed}", "3164100"], + ["MG", "S\u{e3}o Pedro dos Ferros", "3164001"], + ["MG", "S\u{e3}o Rom\u{e3}o", "3164209"], + ["MG", "S\u{e3}o Roque de Minas", "3164308"], + ["MG", "S\u{e3}o Sebasti\u{e3}o da Bela Vista", "3164407"], + ["MG", "S\u{e3}o Sebasti\u{e3}o da Vargem Alegre", "3164431"], + ["MG", "S\u{e3}o Sebasti\u{e3}o do Anta", "3164472"], + ["MG", "S\u{e3}o Sebasti\u{e3}o do Maranh\u{e3}o", "3164506"], + ["MG", "S\u{e3}o Sebasti\u{e3}o do Oeste", "3164605"], + ["MG", "S\u{e3}o Sebasti\u{e3}o do Para\u{ed}so", "3164704"], + ["MG", "S\u{e3}o Sebasti\u{e3}o do Rio Preto", "3164803"], + ["MG", "S\u{e3}o Sebasti\u{e3}o do Rio Verde", "3164902"], + ["MG", "S\u{e3}o Tiago", "3165008"], + ["MG", "S\u{e3}o Tom\u{e1}s de Aquino", "3165107"], + ["MG", "S\u{e3}o Tom\u{e9} das Letras", "3165206"], + ["MG", "S\u{e3}o Vicente de Minas", "3165305"], + ["MG", "Sapuca\u{ed}-Mirim", "3165404"], + ["MG", "Sardo\u{e1}", "3165503"], + ["MG", "Sarzedo", "3165537"], + ["MG", "Sem-Peixe", "3165560"], + ["MG", "Senador Amaral", "3165578"], + ["MG", "Senador Cortes", "3165602"], + ["MG", "Senador Firmino", "3165701"], + ["MG", "Senador Jos\u{e9} Bento", "3165800"], + ["MG", "Senador Modestino Gon\u{e7}alves", "3165909"], + ["MG", "Senhora de Oliveira", "3166006"], + ["MG", "Senhora do Porto", "3166105"], + ["MG", "Senhora dos Rem\u{e9}dios", "3166204"], + ["MG", "Sericita", "3166303"], + ["MG", "Seritinga", "3166402"], + ["MG", "Serra Azul de Minas", "3166501"], + ["MG", "Serra da Saudade", "3166600"], + ["MG", "Serra do Salitre", "3166808"], + ["MG", "Serra dos Aimor\u{e9}s", "3166709"], + ["MG", "Serrania", "3166907"], + ["MG", "Serran\u{f3}polis de Minas", "3166956"], + ["MG", "Serranos", "3167004"], + ["MG", "Serro", "3167103"], + ["MG", "Sete Lagoas", "3167202"], + ["MG", "Setubinha", "3165552"], + ["MG", "Silveir\u{e2}nia", "3167301"], + ["MG", "Silvian\u{f3}polis", "3167400"], + ["MG", "Sim\u{e3}o Pereira", "3167509"], + ["MG", "Simon\u{e9}sia", "3167608"], + ["MG", "Sobr\u{e1}lia", "3167707"], + ["MG", "Soledade de Minas", "3167806"], + ["MG", "Tabuleiro", "3167905"], + ["MG", "Taiobeiras", "3168002"], + ["MG", "Taparuba", "3168051"], + ["MG", "Tapira", "3168101"], + ["MG", "Tapira\u{ed}", "3168200"], + ["MG", "Taquara\u{e7}u de Minas", "3168309"], + ["MG", "Tarumirim", "3168408"], + ["MG", "Teixeiras", "3168507"], + ["MG", "Te\u{f3}filo Otoni", "3168606"], + ["MG", "Tim\u{f3}teo", "3168705"], + ["MG", "Tiradentes", "3168804"], + ["MG", "Tiros", "3168903"], + ["MG", "Tocantins", "3169000"], + ["MG", "Tocos do Moji", "3169059"], + ["MG", "Toledo", "3169109"], + ["MG", "Tombos", "3169208"], + ["MG", "Tr\u{ea}s Cora\u{e7}\u{f5}es", "3169307"], + ["MG", "Tr\u{ea}s Marias", "3169356"], + ["MG", "Tr\u{ea}s Pontas", "3169406"], + ["MG", "Tumiritinga", "3169505"], + ["MG", "Tupaciguara", "3169604"], + ["MG", "Turmalina", "3169703"], + ["MG", "Turvol\u{e2}ndia", "3169802"], + ["MG", "Ub\u{e1}", "3169901"], + ["MG", "Uba\u{ed}", "3170008"], + ["MG", "Ubaporanga", "3170057"], + ["MG", "Uberaba", "3170107"], + ["MG", "Uberl\u{e2}ndia", "3170206"], + ["MG", "Umburatiba", "3170305"], + ["MG", "Una\u{ed}", "3170404"], + ["MG", "Uni\u{e3}o de Minas", "3170438"], + ["MG", "Uruana de Minas", "3170479"], + ["MG", "Uruc\u{e2}nia", "3170503"], + ["MG", "Urucuia", "3170529"], + ["MG", "Vargem Alegre", "3170578"], + ["MG", "Vargem Bonita", "3170602"], + ["MG", "Vargem Grande do Rio Pardo", "3170651"], + ["MG", "Varginha", "3170701"], + ["MG", "Varj\u{e3}o de Minas", "3170750"], + ["MG", "V\u{e1}rzea da Palma", "3170800"], + ["MG", "Varzel\u{e2}ndia", "3170909"], + ["MG", "Vazante", "3171006"], + ["MG", "Verdel\u{e2}ndia", "3171030"], + ["MG", "Veredinha", "3171071"], + ["MG", "Ver\u{ed}ssimo", "3171105"], + ["MG", "Vermelho Novo", "3171154"], + ["MG", "Vespasiano", "3171204"], + ["MG", "Vi\u{e7}osa", "3171303"], + ["MG", "Vieiras", "3171402"], + ["MG", "Virgem da Lapa", "3171600"], + ["MG", "Virg\u{ed}nia", "3171709"], + ["MG", "Virgin\u{f3}polis", "3171808"], + ["MG", "Virgol\u{e2}ndia", "3171907"], + ["MG", "Visconde do Rio Branco", "3172004"], + ["MG", "Volta Grande", "3172103"], + ["MG", "Wenceslau Braz", "3172202"], + ["PA", "Abaetetuba", "1500107"], + ["PA", "Abel Figueiredo", "1500131"], + ["PA", "Acar\u{e1}", "1500206"], + ["PA", "Afu\u{e1}", "1500305"], + ["PA", "\u{c1}gua Azul do Norte", "1500347"], + ["PA", "Alenquer", "1500404"], + ["PA", "Almeirim", "1500503"], + ["PA", "Altamira", "1500602"], + ["PA", "Anaj\u{e1}s", "1500701"], + ["PA", "Ananindeua", "1500800"], + ["PA", "Anapu", "1500859"], + ["PA", "Augusto Corr\u{ea}a", "1500909"], + ["PA", "Aurora do Par\u{e1}", "1500958"], + ["PA", "Aveiro", "1501006"], + ["PA", "Bagre", "1501105"], + ["PA", "Bai\u{e3}o", "1501204"], + ["PA", "Bannach", "1501253"], + ["PA", "Barcarena", "1501303"], + ["PA", "Bel\u{e9}m", "1501402"], + ["PA", "Belterra", "1501451"], + ["PA", "Benevides", "1501501"], + ["PA", "Bom Jesus do Tocantins", "1501576"], + ["PA", "Bonito", "1501600"], + ["PA", "Bragan\u{e7}a", "1501709"], + ["PA", "Brasil Novo", "1501725"], + ["PA", "Brejo Grande do Araguaia", "1501758"], + ["PA", "Breu Branco", "1501782"], + ["PA", "Breves", "1501808"], + ["PA", "Bujaru", "1501907"], + ["PA", "Cachoeira do Arari", "1502004"], + ["PA", "Cachoeira do Piri\u{e1}", "1501956"], + ["PA", "Camet\u{e1}", "1502103"], + ["PA", "Cana\u{e3} dos Caraj\u{e1}s", "1502152"], + ["PA", "Capanema", "1502202"], + ["PA", "Capit\u{e3}o Po\u{e7}o", "1502301"], + ["PA", "Castanhal", "1502400"], + ["PA", "Chaves", "1502509"], + ["PA", "Colares", "1502608"], + ["PA", "Concei\u{e7}\u{e3}o do Araguaia", "1502707"], + ["PA", "Conc\u{f3}rdia do Par\u{e1}", "1502756"], + ["PA", "Cumaru do Norte", "1502764"], + ["PA", "Curion\u{f3}polis", "1502772"], + ["PA", "Curralinho", "1502806"], + ["PA", "Curu\u{e1}", "1502855"], + ["PA", "Curu\u{e7}\u{e1}", "1502905"], + ["PA", "Dom Eliseu", "1502939"], + ["PA", "Eldorado do Caraj\u{e1}s", "1502954"], + ["PA", "Faro", "1503002"], + ["PA", "Floresta do Araguaia", "1503044"], + ["PA", "Garraf\u{e3}o do Norte", "1503077"], + ["PA", "Goian\u{e9}sia do Par\u{e1}", "1503093"], + ["PA", "Gurup\u{e1}", "1503101"], + ["PA", "Igarap\u{e9}-A\u{e7}u", "1503200"], + ["PA", "Igarap\u{e9}-Miri", "1503309"], + ["PA", "Inhangapi", "1503408"], + ["PA", "Ipixuna do Par\u{e1}", "1503457"], + ["PA", "Irituia", "1503507"], + ["PA", "Itaituba", "1503606"], + ["PA", "Itupiranga", "1503705"], + ["PA", "Jacareacanga", "1503754"], + ["PA", "Jacund\u{e1}", "1503804"], + ["PA", "Juruti", "1503903"], + ["PA", "Limoeiro do Ajuru", "1504000"], + ["PA", "M\u{e3}e do Rio", "1504059"], + ["PA", "Magalh\u{e3}es Barata", "1504109"], + ["PA", "Marab\u{e1}", "1504208"], + ["PA", "Maracan\u{e3}", "1504307"], + ["PA", "Marapanim", "1504406"], + ["PA", "Marituba", "1504422"], + ["PA", "Medicil\u{e2}ndia", "1504455"], + ["PA", "Melga\u{e7}o", "1504505"], + ["PA", "Mocajuba", "1504604"], + ["PA", "Moju", "1504703"], + ["PA", "Moju\u{ed} dos Campos", "1504752"], + ["PA", "Monte Alegre", "1504802"], + ["PA", "Muan\u{e1}", "1504901"], + ["PA", "Nova Esperan\u{e7}a do Piri\u{e1}", "1504950"], + ["PA", "Nova Ipixuna", "1504976"], + ["PA", "Nova Timboteua", "1505007"], + ["PA", "Novo Progresso", "1505031"], + ["PA", "Novo Repartimento", "1505064"], + ["PA", "\u{d3}bidos", "1505106"], + ["PA", "Oeiras do Par\u{e1}", "1505205"], + ["PA", "Oriximin\u{e1}", "1505304"], + ["PA", "Our\u{e9}m", "1505403"], + ["PA", "Ouril\u{e2}ndia do Norte", "1505437"], + ["PA", "Pacaj\u{e1}", "1505486"], + ["PA", "Palestina do Par\u{e1}", "1505494"], + ["PA", "Paragominas", "1505502"], + ["PA", "Parauapebas", "1505536"], + ["PA", "Pau D'Arco", "1505551"], + ["PA", "Peixe-Boi", "1505601"], + ["PA", "Pi\u{e7}arra", "1505635"], + ["PA", "Placas", "1505650"], + ["PA", "Ponta de Pedras", "1505700"], + ["PA", "Portel", "1505809"], + ["PA", "Porto de Moz", "1505908"], + ["PA", "Prainha", "1506005"], + ["PA", "Primavera", "1506104"], + ["PA", "Quatipuru", "1506112"], + ["PA", "Reden\u{e7}\u{e3}o", "1506138"], + ["PA", "Rio Maria", "1506161"], + ["PA", "Rondon do Par\u{e1}", "1506187"], + ["PA", "Rur\u{f3}polis", "1506195"], + ["PA", "Salin\u{f3}polis", "1506203"], + ["PA", "Salvaterra", "1506302"], + ["PA", "Santa B\u{e1}rbara do Par\u{e1}", "1506351"], + ["PA", "Santa Cruz do Arari", "1506401"], + ["PA", "Santa Izabel do Par\u{e1}", "1506500"], + ["PA", "Santa Luzia do Par\u{e1}", "1506559"], + ["PA", "Santa Maria das Barreiras", "1506583"], + ["PA", "Santa Maria do Par\u{e1}", "1506609"], + ["PA", "Santana do Araguaia", "1506708"], + ["PA", "Santar\u{e9}m", "1506807"], + ["PA", "Santar\u{e9}m Novo", "1506906"], + ["PA", "Santo Ant\u{f4}nio do Tau\u{e1}", "1507003"], + ["PA", "S\u{e3}o Caetano de Odivelas", "1507102"], + ["PA", "S\u{e3}o Domingos do Araguaia", "1507151"], + ["PA", "S\u{e3}o Domingos do Capim", "1507201"], + ["PA", "S\u{e3}o F\u{e9}lix do Xingu", "1507300"], + ["PA", "S\u{e3}o Francisco do Par\u{e1}", "1507409"], + ["PA", "S\u{e3}o Geraldo do Araguaia", "1507458"], + ["PA", "S\u{e3}o Jo\u{e3}o da Ponta", "1507466"], + ["PA", "S\u{e3}o Jo\u{e3}o de Pirabas", "1507474"], + ["PA", "S\u{e3}o Jo\u{e3}o do Araguaia", "1507508"], + ["PA", "S\u{e3}o Miguel do Guam\u{e1}", "1507607"], + ["PA", "S\u{e3}o Sebasti\u{e3}o da Boa Vista", "1507706"], + ["PA", "Sapucaia", "1507755"], + ["PA", "Senador Jos\u{e9} Porf\u{ed}rio", "1507805"], + ["PA", "Soure", "1507904"], + ["PA", "Tail\u{e2}ndia", "1507953"], + ["PA", "Terra Alta", "1507961"], + ["PA", "Terra Santa", "1507979"], + ["PA", "Tom\u{e9}-A\u{e7}u", "1508001"], + ["PA", "Tracuateua", "1508035"], + ["PA", "Trair\u{e3}o", "1508050"], + ["PA", "Tucum\u{e3}", "1508084"], + ["PA", "Tucuru\u{ed}", "1508100"], + ["PA", "Ulian\u{f3}polis", "1508126"], + ["PA", "Uruar\u{e1}", "1508159"], + ["PA", "Vigia", "1508209"], + ["PA", "Viseu", "1508308"], + ["PA", "Vit\u{f3}ria do Xingu", "1508357"], + ["PA", "Xinguara", "1508407"], + ["PB", "\u{c1}gua Branca", "2500106"], + ["PB", "Aguiar", "2500205"], + ["PB", "Alagoa Grande", "2500304"], + ["PB", "Alagoa Nova", "2500403"], + ["PB", "Alagoinha", "2500502"], + ["PB", "Alcantil", "2500536"], + ["PB", "Algod\u{e3}o de Janda\u{ed}ra", "2500577"], + ["PB", "Alhandra", "2500601"], + ["PB", "Amparo", "2500734"], + ["PB", "Aparecida", "2500775"], + ["PB", "Ara\u{e7}agi", "2500809"], + ["PB", "Arara", "2500908"], + ["PB", "Araruna", "2501005"], + ["PB", "Areia", "2501104"], + ["PB", "Areia de Bara\u{fa}nas", "2501153"], + ["PB", "Areial", "2501203"], + ["PB", "Aroeiras", "2501302"], + ["PB", "Assun\u{e7}\u{e3}o", "2501351"], + ["PB", "Ba\u{ed}a da Trai\u{e7}\u{e3}o", "2501401"], + ["PB", "Bananeiras", "2501500"], + ["PB", "Bara\u{fa}na", "2501534"], + ["PB", "Barra de Santa Rosa", "2501609"], + ["PB", "Barra de Santana", "2501575"], + ["PB", "Barra de S\u{e3}o Miguel", "2501708"], + ["PB", "Bayeux", "2501807"], + ["PB", "Bel\u{e9}m", "2501906"], + ["PB", "Bel\u{e9}m do Brejo do Cruz", "2502003"], + ["PB", "Bernardino Batista", "2502052"], + ["PB", "Boa Ventura", "2502102"], + ["PB", "Boa Vista", "2502151"], + ["PB", "Bom Jesus", "2502201"], + ["PB", "Bom Sucesso", "2502300"], + ["PB", "Bonito de Santa F\u{e9}", "2502409"], + ["PB", "Boqueir\u{e3}o", "2502508"], + ["PB", "Borborema", "2502706"], + ["PB", "Brejo do Cruz", "2502805"], + ["PB", "Brejo dos Santos", "2502904"], + ["PB", "Caapor\u{e3}", "2503001"], + ["PB", "Cabaceiras", "2503100"], + ["PB", "Cabedelo", "2503209"], + ["PB", "Cachoeira dos \u{cd}ndios", "2503308"], + ["PB", "Cacimba de Areia", "2503407"], + ["PB", "Cacimba de Dentro", "2503506"], + ["PB", "Cacimbas", "2503555"], + ["PB", "Cai\u{e7}ara", "2503605"], + ["PB", "Cajazeiras", "2503704"], + ["PB", "Cajazeirinhas", "2503753"], + ["PB", "Caldas Brand\u{e3}o", "2503803"], + ["PB", "Camala\u{fa}", "2503902"], + ["PB", "Campina Grande", "2504009"], + ["PB", "Capim", "2504033"], + ["PB", "Cara\u{fa}bas", "2504074"], + ["PB", "Carrapateira", "2504108"], + ["PB", "Casserengue", "2504157"], + ["PB", "Catingueira", "2504207"], + ["PB", "Catol\u{e9} do Rocha", "2504306"], + ["PB", "Caturit\u{e9}", "2504355"], + ["PB", "Concei\u{e7}\u{e3}o", "2504405"], + ["PB", "Condado", "2504504"], + ["PB", "Conde", "2504603"], + ["PB", "Congo", "2504702"], + ["PB", "Coremas", "2504801"], + ["PB", "Coxixola", "2504850"], + ["PB", "Cruz do Esp\u{ed}rito Santo", "2504900"], + ["PB", "Cubati", "2505006"], + ["PB", "Cuit\u{e9}", "2505105"], + ["PB", "Cuit\u{e9} de Mamanguape", "2505238"], + ["PB", "Cuitegi", "2505204"], + ["PB", "Curral de Cima", "2505279"], + ["PB", "Curral Velho", "2505303"], + ["PB", "Dami\u{e3}o", "2505352"], + ["PB", "Desterro", "2505402"], + ["PB", "Diamante", "2505600"], + ["PB", "Dona In\u{ea}s", "2505709"], + ["PB", "Duas Estradas", "2505808"], + ["PB", "Emas", "2505907"], + ["PB", "Esperan\u{e7}a", "2506004"], + ["PB", "Fagundes", "2506103"], + ["PB", "Frei Martinho", "2506202"], + ["PB", "Gado Bravo", "2506251"], + ["PB", "Guarabira", "2506301"], + ["PB", "Gurinh\u{e9}m", "2506400"], + ["PB", "Gurj\u{e3}o", "2506509"], + ["PB", "Ibiara", "2506608"], + ["PB", "Igaracy", "2502607"], + ["PB", "Imaculada", "2506707"], + ["PB", "Ing\u{e1}", "2506806"], + ["PB", "Itabaiana", "2506905"], + ["PB", "Itaporanga", "2507002"], + ["PB", "Itapororoca", "2507101"], + ["PB", "Itatuba", "2507200"], + ["PB", "Jacara\u{fa}", "2507309"], + ["PB", "Jeric\u{f3}", "2507408"], + ["PB", "Jo\u{e3}o Pessoa", "2507507"], + ["PB", "Joca Claudino", "2513653"], + ["PB", "Juarez T\u{e1}vora", "2507606"], + ["PB", "Juazeirinho", "2507705"], + ["PB", "Junco do Serid\u{f3}", "2507804"], + ["PB", "Juripiranga", "2507903"], + ["PB", "Juru", "2508000"], + ["PB", "Lagoa", "2508109"], + ["PB", "Lagoa de Dentro", "2508208"], + ["PB", "Lagoa Seca", "2508307"], + ["PB", "Lastro", "2508406"], + ["PB", "Livramento", "2508505"], + ["PB", "Logradouro", "2508554"], + ["PB", "Lucena", "2508604"], + ["PB", "M\u{e3}e d'\u{c1}gua", "2508703"], + ["PB", "Malta", "2508802"], + ["PB", "Mamanguape", "2508901"], + ["PB", "Mana\u{ed}ra", "2509008"], + ["PB", "Marca\u{e7}\u{e3}o", "2509057"], + ["PB", "Mari", "2509107"], + ["PB", "Mariz\u{f3}polis", "2509156"], + ["PB", "Massaranduba", "2509206"], + ["PB", "Mataraca", "2509305"], + ["PB", "Matinhas", "2509339"], + ["PB", "Mato Grosso", "2509370"], + ["PB", "Matur\u{e9}ia", "2509396"], + ["PB", "Mogeiro", "2509404"], + ["PB", "Montadas", "2509503"], + ["PB", "Monte Horebe", "2509602"], + ["PB", "Monteiro", "2509701"], + ["PB", "Mulungu", "2509800"], + ["PB", "Natuba", "2509909"], + ["PB", "Nazarezinho", "2510006"], + ["PB", "Nova Floresta", "2510105"], + ["PB", "Nova Olinda", "2510204"], + ["PB", "Nova Palmeira", "2510303"], + ["PB", "Olho d'\u{c1}gua", "2510402"], + ["PB", "Olivedos", "2510501"], + ["PB", "Ouro Velho", "2510600"], + ["PB", "Parari", "2510659"], + ["PB", "Passagem", "2510709"], + ["PB", "Patos", "2510808"], + ["PB", "Paulista", "2510907"], + ["PB", "Pedra Branca", "2511004"], + ["PB", "Pedra Lavrada", "2511103"], + ["PB", "Pedras de Fogo", "2511202"], + ["PB", "Pedro R\u{e9}gis", "2512721"], + ["PB", "Pianc\u{f3}", "2511301"], + ["PB", "Picu\u{ed}", "2511400"], + ["PB", "Pilar", "2511509"], + ["PB", "Pil\u{f5}es", "2511608"], + ["PB", "Pil\u{f5}ezinhos", "2511707"], + ["PB", "Pirpirituba", "2511806"], + ["PB", "Pitimbu", "2511905"], + ["PB", "Pocinhos", "2512002"], + ["PB", "Po\u{e7}o Dantas", "2512036"], + ["PB", "Po\u{e7}o de Jos\u{e9} de Moura", "2512077"], + ["PB", "Pombal", "2512101"], + ["PB", "Prata", "2512200"], + ["PB", "Princesa Isabel", "2512309"], + ["PB", "Puxinan\u{e3}", "2512408"], + ["PB", "Queimadas", "2512507"], + ["PB", "Quixaba", "2512606"], + ["PB", "Rem\u{ed}gio", "2512705"], + ["PB", "Riach\u{e3}o", "2512747"], + ["PB", "Riach\u{e3}o do Bacamarte", "2512754"], + ["PB", "Riach\u{e3}o do Po\u{e7}o", "2512762"], + ["PB", "Riacho de Santo Ant\u{f4}nio", "2512788"], + ["PB", "Riacho dos Cavalos", "2512804"], + ["PB", "Rio Tinto", "2512903"], + ["PB", "Salgadinho", "2513000"], + ["PB", "Salgado de S\u{e3}o F\u{e9}lix", "2513109"], + ["PB", "Santa Cec\u{ed}lia", "2513158"], + ["PB", "Santa Cruz", "2513208"], + ["PB", "Santa Helena", "2513307"], + ["PB", "Santa In\u{ea}s", "2513356"], + ["PB", "Santa Luzia", "2513406"], + ["PB", "Santa Rita", "2513703"], + ["PB", "Santa Teresinha", "2513802"], + ["PB", "Santana de Mangueira", "2513505"], + ["PB", "Santana dos Garrotes", "2513604"], + ["PB", "Santo Andr\u{e9}", "2513851"], + ["PB", "S\u{e3}o Bentinho", "2513927"], + ["PB", "S\u{e3}o Bento", "2513901"], + ["PB", "S\u{e3}o Domingos", "2513968"], + ["PB", "S\u{e3}o Domingos do Cariri", "2513943"], + ["PB", "S\u{e3}o Francisco", "2513984"], + ["PB", "S\u{e3}o Jo\u{e3}o do Cariri", "2514008"], + ["PB", "S\u{e3}o Jo\u{e3}o do Rio do Peixe", "2500700"], + ["PB", "S\u{e3}o Jo\u{e3}o do Tigre", "2514107"], + ["PB", "S\u{e3}o Jos\u{e9} da Lagoa Tapada", "2514206"], + ["PB", "S\u{e3}o Jos\u{e9} de Caiana", "2514305"], + ["PB", "S\u{e3}o Jos\u{e9} de Espinharas", "2514404"], + ["PB", "S\u{e3}o Jos\u{e9} de Piranhas", "2514503"], + ["PB", "S\u{e3}o Jos\u{e9} de Princesa", "2514552"], + ["PB", "S\u{e3}o Jos\u{e9} do Bonfim", "2514602"], + ["PB", "S\u{e3}o Jos\u{e9} do Brejo do Cruz", "2514651"], + ["PB", "S\u{e3}o Jos\u{e9} do Sabugi", "2514701"], + ["PB", "S\u{e3}o Jos\u{e9} dos Cordeiros", "2514800"], + ["PB", "S\u{e3}o Jos\u{e9} dos Ramos", "2514453"], + ["PB", "S\u{e3}o Mamede", "2514909"], + ["PB", "S\u{e3}o Miguel de Taipu", "2515005"], + ["PB", "S\u{e3}o Sebasti\u{e3}o de Lagoa de Ro\u{e7}a", "2515104"], + ["PB", "S\u{e3}o Sebasti\u{e3}o do Umbuzeiro", "2515203"], + ["PB", "S\u{e3}o Vicente do Serid\u{f3}", "2515401"], + ["PB", "Sap\u{e9}", "2515302"], + ["PB", "Serra Branca", "2515500"], + ["PB", "Serra da Raiz", "2515609"], + ["PB", "Serra Grande", "2515708"], + ["PB", "Serra Redonda", "2515807"], + ["PB", "Serraria", "2515906"], + ["PB", "Sert\u{e3}ozinho", "2515930"], + ["PB", "Sobrado", "2515971"], + ["PB", "Sol\u{e2}nea", "2516003"], + ["PB", "Soledade", "2516102"], + ["PB", "Soss\u{ea}go", "2516151"], + ["PB", "Sousa", "2516201"], + ["PB", "Sum\u{e9}", "2516300"], + ["PB", "Tacima", "2516409"], + ["PB", "Tapero\u{e1}", "2516508"], + ["PB", "Tavares", "2516607"], + ["PB", "Teixeira", "2516706"], + ["PB", "Ten\u{f3}rio", "2516755"], + ["PB", "Triunfo", "2516805"], + ["PB", "Uira\u{fa}na", "2516904"], + ["PB", "Umbuzeiro", "2517001"], + ["PB", "V\u{e1}rzea", "2517100"], + ["PB", "Vieir\u{f3}polis", "2517209"], + ["PB", "Vista Serrana", "2505501"], + ["PB", "Zabel\u{ea}", "2517407"], + ["PR", "Abati\u{e1}", "4100103"], + ["PR", "Adrian\u{f3}polis", "4100202"], + ["PR", "Agudos do Sul", "4100301"], + ["PR", "Almirante Tamandar\u{e9}", "4100400"], + ["PR", "Altamira do Paran\u{e1}", "4100459"], + ["PR", "Alto Para\u{ed}so", "4128625"], + ["PR", "Alto Paran\u{e1}", "4100608"], + ["PR", "Alto Piquiri", "4100707"], + ["PR", "Alt\u{f4}nia", "4100509"], + ["PR", "Alvorada do Sul", "4100806"], + ["PR", "Amapor\u{e3}", "4100905"], + ["PR", "Amp\u{e9}re", "4101002"], + ["PR", "Anahy", "4101051"], + ["PR", "Andir\u{e1}", "4101101"], + ["PR", "\u{c2}ngulo", "4101150"], + ["PR", "Antonina", "4101200"], + ["PR", "Ant\u{f4}nio Olinto", "4101309"], + ["PR", "Apucarana", "4101408"], + ["PR", "Arapongas", "4101507"], + ["PR", "Arapoti", "4101606"], + ["PR", "Arapu\u{e3}", "4101655"], + ["PR", "Araruna", "4101705"], + ["PR", "Arauc\u{e1}ria", "4101804"], + ["PR", "Ariranha do Iva\u{ed}", "4101853"], + ["PR", "Assa\u{ed}", "4101903"], + ["PR", "Assis Chateaubriand", "4102000"], + ["PR", "Astorga", "4102109"], + ["PR", "Atalaia", "4102208"], + ["PR", "Balsa Nova", "4102307"], + ["PR", "Bandeirantes", "4102406"], + ["PR", "Barbosa Ferraz", "4102505"], + ["PR", "Barra do Jacar\u{e9}", "4102703"], + ["PR", "Barrac\u{e3}o", "4102604"], + ["PR", "Bela Vista da Caroba", "4102752"], + ["PR", "Bela Vista do Para\u{ed}so", "4102802"], + ["PR", "Bituruna", "4102901"], + ["PR", "Boa Esperan\u{e7}a", "4103008"], + ["PR", "Boa Esperan\u{e7}a do Igua\u{e7}u", "4103024"], + ["PR", "Boa Ventura de S\u{e3}o Roque", "4103040"], + ["PR", "Boa Vista da Aparecida", "4103057"], + ["PR", "Bocai\u{fa}va do Sul", "4103107"], + ["PR", "Bom Jesus do Sul", "4103156"], + ["PR", "Bom Sucesso", "4103206"], + ["PR", "Bom Sucesso do Sul", "4103222"], + ["PR", "Borraz\u{f3}polis", "4103305"], + ["PR", "Braganey", "4103354"], + ["PR", "Brasil\u{e2}ndia do Sul", "4103370"], + ["PR", "Cafeara", "4103404"], + ["PR", "Cafel\u{e2}ndia", "4103453"], + ["PR", "Cafezal do Sul", "4103479"], + ["PR", "Calif\u{f3}rnia", "4103503"], + ["PR", "Cambar\u{e1}", "4103602"], + ["PR", "Camb\u{e9}", "4103701"], + ["PR", "Cambira", "4103800"], + ["PR", "Campina da Lagoa", "4103909"], + ["PR", "Campina do Sim\u{e3}o", "4103958"], + ["PR", "Campina Grande do Sul", "4104006"], + ["PR", "Campo Bonito", "4104055"], + ["PR", "Campo do Tenente", "4104105"], + ["PR", "Campo Largo", "4104204"], + ["PR", "Campo Magro", "4104253"], + ["PR", "Campo Mour\u{e3}o", "4104303"], + ["PR", "C\u{e2}ndido de Abreu", "4104402"], + ["PR", "Cand\u{f3}i", "4104428"], + ["PR", "Cantagalo", "4104451"], + ["PR", "Capanema", "4104501"], + ["PR", "Capit\u{e3}o Le\u{f4}nidas Marques", "4104600"], + ["PR", "Carambe\u{ed}", "4104659"], + ["PR", "Carl\u{f3}polis", "4104709"], + ["PR", "Cascavel", "4104808"], + ["PR", "Castro", "4104907"], + ["PR", "Catanduvas", "4105003"], + ["PR", "Centen\u{e1}rio do Sul", "4105102"], + ["PR", "Cerro Azul", "4105201"], + ["PR", "C\u{e9}u Azul", "4105300"], + ["PR", "Chopinzinho", "4105409"], + ["PR", "Cianorte", "4105508"], + ["PR", "Cidade Ga\u{fa}cha", "4105607"], + ["PR", "Clevel\u{e2}ndia", "4105706"], + ["PR", "Colombo", "4105805"], + ["PR", "Colorado", "4105904"], + ["PR", "Congonhinhas", "4106001"], + ["PR", "Conselheiro Mairinck", "4106100"], + ["PR", "Contenda", "4106209"], + ["PR", "Corb\u{e9}lia", "4106308"], + ["PR", "Corn\u{e9}lio Proc\u{f3}pio", "4106407"], + ["PR", "Coronel Domingos Soares", "4106456"], + ["PR", "Coronel Vivida", "4106506"], + ["PR", "Corumbata\u{ed} do Sul", "4106555"], + ["PR", "Cruz Machado", "4106803"], + ["PR", "Cruzeiro do Igua\u{e7}u", "4106571"], + ["PR", "Cruzeiro do Oeste", "4106605"], + ["PR", "Cruzeiro do Sul", "4106704"], + ["PR", "Cruzmaltina", "4106852"], + ["PR", "Curitiba", "4106902"], + ["PR", "Curi\u{fa}va", "4107009"], + ["PR", "Diamante D'Oeste", "4107157"], + ["PR", "Diamante do Norte", "4107108"], + ["PR", "Diamante do Sul", "4107124"], + ["PR", "Dois Vizinhos", "4107207"], + ["PR", "Douradina", "4107256"], + ["PR", "Doutor Camargo", "4107306"], + ["PR", "Doutor Ulysses", "4128633"], + ["PR", "En\u{e9}as Marques", "4107405"], + ["PR", "Engenheiro Beltr\u{e3}o", "4107504"], + ["PR", "Entre Rios do Oeste", "4107538"], + ["PR", "Esperan\u{e7}a Nova", "4107520"], + ["PR", "Espig\u{e3}o Alto do Igua\u{e7}u", "4107546"], + ["PR", "Farol", "4107553"], + ["PR", "Faxinal", "4107603"], + ["PR", "Fazenda Rio Grande", "4107652"], + ["PR", "F\u{ea}nix", "4107702"], + ["PR", "Fernandes Pinheiro", "4107736"], + ["PR", "Figueira", "4107751"], + ["PR", "Flor da Serra do Sul", "4107850"], + ["PR", "Flora\u{ed}", "4107801"], + ["PR", "Floresta", "4107900"], + ["PR", "Florest\u{f3}polis", "4108007"], + ["PR", "Fl\u{f3}rida", "4108106"], + ["PR", "Formosa do Oeste", "4108205"], + ["PR", "Foz do Igua\u{e7}u", "4108304"], + ["PR", "Foz do Jord\u{e3}o", "4108452"], + ["PR", "Francisco Alves", "4108320"], + ["PR", "Francisco Beltr\u{e3}o", "4108403"], + ["PR", "General Carneiro", "4108502"], + ["PR", "Godoy Moreira", "4108551"], + ["PR", "Goioer\u{ea}", "4108601"], + ["PR", "Goioxim", "4108650"], + ["PR", "Grandes Rios", "4108700"], + ["PR", "Gua\u{ed}ra", "4108809"], + ["PR", "Guaira\u{e7}\u{e1}", "4108908"], + ["PR", "Guamiranga", "4108957"], + ["PR", "Guapirama", "4109005"], + ["PR", "Guaporema", "4109104"], + ["PR", "Guaraci", "4109203"], + ["PR", "Guarania\u{e7}u", "4109302"], + ["PR", "Guarapuava", "4109401"], + ["PR", "Guaraque\u{e7}aba", "4109500"], + ["PR", "Guaratuba", "4109609"], + ["PR", "Hon\u{f3}rio Serpa", "4109658"], + ["PR", "Ibaiti", "4109708"], + ["PR", "Ibema", "4109757"], + ["PR", "Ibipor\u{e3}", "4109807"], + ["PR", "Icara\u{ed}ma", "4109906"], + ["PR", "Iguara\u{e7}u", "4110003"], + ["PR", "Iguatu", "4110052"], + ["PR", "Imba\u{fa}", "4110078"], + ["PR", "Imbituva", "4110102"], + ["PR", "In\u{e1}cio Martins", "4110201"], + ["PR", "Inaj\u{e1}", "4110300"], + ["PR", "Indian\u{f3}polis", "4110409"], + ["PR", "Ipiranga", "4110508"], + ["PR", "Ipor\u{e3}", "4110607"], + ["PR", "Iracema do Oeste", "4110656"], + ["PR", "Irati", "4110706"], + ["PR", "Iretama", "4110805"], + ["PR", "Itaguaj\u{e9}", "4110904"], + ["PR", "Itaipul\u{e2}ndia", "4110953"], + ["PR", "Itambarac\u{e1}", "4111001"], + ["PR", "Itamb\u{e9}", "4111100"], + ["PR", "Itapejara d'Oeste", "4111209"], + ["PR", "Itaperu\u{e7}u", "4111258"], + ["PR", "Ita\u{fa}na do Sul", "4111308"], + ["PR", "Iva\u{ed}", "4111407"], + ["PR", "Ivaipor\u{e3}", "4111506"], + ["PR", "Ivat\u{e9}", "4111555"], + ["PR", "Ivatuba", "4111605"], + ["PR", "Jaboti", "4111704"], + ["PR", "Jacarezinho", "4111803"], + ["PR", "Jaguapit\u{e3}", "4111902"], + ["PR", "Jaguaria\u{ed}va", "4112009"], + ["PR", "Jandaia do Sul", "4112108"], + ["PR", "Jani\u{f3}polis", "4112207"], + ["PR", "Japira", "4112306"], + ["PR", "Japur\u{e1}", "4112405"], + ["PR", "Jardim Alegre", "4112504"], + ["PR", "Jardim Olinda", "4112603"], + ["PR", "Jataizinho", "4112702"], + ["PR", "Jesu\u{ed}tas", "4112751"], + ["PR", "Joaquim T\u{e1}vora", "4112801"], + ["PR", "Jundia\u{ed} do Sul", "4112900"], + ["PR", "Juranda", "4112959"], + ["PR", "Jussara", "4113007"], + ["PR", "Kalor\u{e9}", "4113106"], + ["PR", "Lapa", "4113205"], + ["PR", "Laranjal", "4113254"], + ["PR", "Laranjeiras do Sul", "4113304"], + ["PR", "Le\u{f3}polis", "4113403"], + ["PR", "Lidian\u{f3}polis", "4113429"], + ["PR", "Lindoeste", "4113452"], + ["PR", "Loanda", "4113502"], + ["PR", "Lobato", "4113601"], + ["PR", "Londrina", "4113700"], + ["PR", "Luiziana", "4113734"], + ["PR", "Lunardelli", "4113759"], + ["PR", "Lupion\u{f3}polis", "4113809"], + ["PR", "Mallet", "4113908"], + ["PR", "Mambor\u{ea}", "4114005"], + ["PR", "Mandagua\u{e7}u", "4114104"], + ["PR", "Mandaguari", "4114203"], + ["PR", "Mandirituba", "4114302"], + ["PR", "Manfrin\u{f3}polis", "4114351"], + ["PR", "Mangueirinha", "4114401"], + ["PR", "Manoel Ribas", "4114500"], + ["PR", "Marechal C\u{e2}ndido Rondon", "4114609"], + ["PR", "Maria Helena", "4114708"], + ["PR", "Marialva", "4114807"], + ["PR", "Maril\u{e2}ndia do Sul", "4114906"], + ["PR", "Marilena", "4115002"], + ["PR", "Mariluz", "4115101"], + ["PR", "Maring\u{e1}", "4115200"], + ["PR", "Mari\u{f3}polis", "4115309"], + ["PR", "Marip\u{e1}", "4115358"], + ["PR", "Marmeleiro", "4115408"], + ["PR", "Marquinho", "4115457"], + ["PR", "Marumbi", "4115507"], + ["PR", "Matel\u{e2}ndia", "4115606"], + ["PR", "Matinhos", "4115705"], + ["PR", "Mato Rico", "4115739"], + ["PR", "Mau\u{e1} da Serra", "4115754"], + ["PR", "Medianeira", "4115804"], + ["PR", "Mercedes", "4115853"], + ["PR", "Mirador", "4115903"], + ["PR", "Miraselva", "4116000"], + ["PR", "Missal", "4116059"], + ["PR", "Moreira Sales", "4116109"], + ["PR", "Morretes", "4116208"], + ["PR", "Munhoz de Melo", "4116307"], + ["PR", "Nossa Senhora das Gra\u{e7}as", "4116406"], + ["PR", "Nova Alian\u{e7}a do Iva\u{ed}", "4116505"], + ["PR", "Nova Am\u{e9}rica da Colina", "4116604"], + ["PR", "Nova Aurora", "4116703"], + ["PR", "Nova Cantu", "4116802"], + ["PR", "Nova Esperan\u{e7}a", "4116901"], + ["PR", "Nova Esperan\u{e7}a do Sudoeste", "4116950"], + ["PR", "Nova F\u{e1}tima", "4117008"], + ["PR", "Nova Laranjeiras", "4117057"], + ["PR", "Nova Londrina", "4117107"], + ["PR", "Nova Ol\u{ed}mpia", "4117206"], + ["PR", "Nova Prata do Igua\u{e7}u", "4117255"], + ["PR", "Nova Santa B\u{e1}rbara", "4117214"], + ["PR", "Nova Santa Rosa", "4117222"], + ["PR", "Nova Tebas", "4117271"], + ["PR", "Novo Itacolomi", "4117297"], + ["PR", "Ortigueira", "4117305"], + ["PR", "Ourizona", "4117404"], + ["PR", "Ouro Verde do Oeste", "4117453"], + ["PR", "Pai\u{e7}andu", "4117503"], + ["PR", "Palmas", "4117602"], + ["PR", "Palmeira", "4117701"], + ["PR", "Palmital", "4117800"], + ["PR", "Palotina", "4117909"], + ["PR", "Para\u{ed}so do Norte", "4118006"], + ["PR", "Paranacity", "4118105"], + ["PR", "Paranagu\u{e1}", "4118204"], + ["PR", "Paranapoema", "4118303"], + ["PR", "Paranava\u{ed}", "4118402"], + ["PR", "Pato Bragado", "4118451"], + ["PR", "Pato Branco", "4118501"], + ["PR", "Paula Freitas", "4118600"], + ["PR", "Paulo Frontin", "4118709"], + ["PR", "Peabiru", "4118808"], + ["PR", "Perobal", "4118857"], + ["PR", "P\u{e9}rola", "4118907"], + ["PR", "P\u{e9}rola d'Oeste", "4119004"], + ["PR", "Pi\u{ea}n", "4119103"], + ["PR", "Pinhais", "4119152"], + ["PR", "Pinhal de S\u{e3}o Bento", "4119251"], + ["PR", "Pinhal\u{e3}o", "4119202"], + ["PR", "Pinh\u{e3}o", "4119301"], + ["PR", "Pira\u{ed} do Sul", "4119400"], + ["PR", "Piraquara", "4119509"], + ["PR", "Pitanga", "4119608"], + ["PR", "Pitangueiras", "4119657"], + ["PR", "Planaltina do Paran\u{e1}", "4119707"], + ["PR", "Planalto", "4119806"], + ["PR", "Ponta Grossa", "4119905"], + ["PR", "Pontal do Paran\u{e1}", "4119954"], + ["PR", "Porecatu", "4120002"], + ["PR", "Porto Amazonas", "4120101"], + ["PR", "Porto Barreiro", "4120150"], + ["PR", "Porto Rico", "4120200"], + ["PR", "Porto Vit\u{f3}ria", "4120309"], + ["PR", "Prado Ferreira", "4120333"], + ["PR", "Pranchita", "4120358"], + ["PR", "Presidente Castelo Branco", "4120408"], + ["PR", "Primeiro de Maio", "4120507"], + ["PR", "Prudent\u{f3}polis", "4120606"], + ["PR", "Quarto Centen\u{e1}rio", "4120655"], + ["PR", "Quatigu\u{e1}", "4120705"], + ["PR", "Quatro Barras", "4120804"], + ["PR", "Quatro Pontes", "4120853"], + ["PR", "Quedas do Igua\u{e7}u", "4120903"], + ["PR", "Quer\u{ea}ncia do Norte", "4121000"], + ["PR", "Quinta do Sol", "4121109"], + ["PR", "Quitandinha", "4121208"], + ["PR", "Ramil\u{e2}ndia", "4121257"], + ["PR", "Rancho Alegre", "4121307"], + ["PR", "Rancho Alegre D'Oeste", "4121356"], + ["PR", "Realeza", "4121406"], + ["PR", "Rebou\u{e7}as", "4121505"], + ["PR", "Renascen\u{e7}a", "4121604"], + ["PR", "Reserva", "4121703"], + ["PR", "Reserva do Igua\u{e7}u", "4121752"], + ["PR", "Ribeir\u{e3}o Claro", "4121802"], + ["PR", "Ribeir\u{e3}o do Pinhal", "4121901"], + ["PR", "Rio Azul", "4122008"], + ["PR", "Rio Bom", "4122107"], + ["PR", "Rio Bonito do Igua\u{e7}u", "4122156"], + ["PR", "Rio Branco do Iva\u{ed}", "4122172"], + ["PR", "Rio Branco do Sul", "4122206"], + ["PR", "Rio Negro", "4122305"], + ["PR", "Rol\u{e2}ndia", "4122404"], + ["PR", "Roncador", "4122503"], + ["PR", "Rondon", "4122602"], + ["PR", "Ros\u{e1}rio do Iva\u{ed}", "4122651"], + ["PR", "Sab\u{e1}udia", "4122701"], + ["PR", "Salgado Filho", "4122800"], + ["PR", "Salto do Itarar\u{e9}", "4122909"], + ["PR", "Salto do Lontra", "4123006"], + ["PR", "Santa Am\u{e9}lia", "4123105"], + ["PR", "Santa Cec\u{ed}lia do Pav\u{e3}o", "4123204"], + ["PR", "Santa Cruz de Monte Castelo", "4123303"], + ["PR", "Santa F\u{e9}", "4123402"], + ["PR", "Santa Helena", "4123501"], + ["PR", "Santa In\u{ea}s", "4123600"], + ["PR", "Santa Isabel do Iva\u{ed}", "4123709"], + ["PR", "Santa Izabel do Oeste", "4123808"], + ["PR", "Santa L\u{fa}cia", "4123824"], + ["PR", "Santa Maria do Oeste", "4123857"], + ["PR", "Santa Mariana", "4123907"], + ["PR", "Santa M\u{f4}nica", "4123956"], + ["PR", "Santa Tereza do Oeste", "4124020"], + ["PR", "Santa Terezinha de Itaipu", "4124053"], + ["PR", "Santana do Itarar\u{e9}", "4124004"], + ["PR", "Santo Ant\u{f4}nio da Platina", "4124103"], + ["PR", "Santo Ant\u{f4}nio do Caiu\u{e1}", "4124202"], + ["PR", "Santo Ant\u{f4}nio do Para\u{ed}so", "4124301"], + ["PR", "Santo Ant\u{f4}nio do Sudoeste", "4124400"], + ["PR", "Santo In\u{e1}cio", "4124509"], + ["PR", "S\u{e3}o Carlos do Iva\u{ed}", "4124608"], + ["PR", "S\u{e3}o Jer\u{f4}nimo da Serra", "4124707"], + ["PR", "S\u{e3}o Jo\u{e3}o", "4124806"], + ["PR", "S\u{e3}o Jo\u{e3}o do Caiu\u{e1}", "4124905"], + ["PR", "S\u{e3}o Jo\u{e3}o do Iva\u{ed}", "4125001"], + ["PR", "S\u{e3}o Jo\u{e3}o do Triunfo", "4125100"], + ["PR", "S\u{e3}o Jorge d'Oeste", "4125209"], + ["PR", "S\u{e3}o Jorge do Iva\u{ed}", "4125308"], + ["PR", "S\u{e3}o Jorge do Patroc\u{ed}nio", "4125357"], + ["PR", "S\u{e3}o Jos\u{e9} da Boa Vista", "4125407"], + ["PR", "S\u{e3}o Jos\u{e9} das Palmeiras", "4125456"], + ["PR", "S\u{e3}o Jos\u{e9} dos Pinhais", "4125506"], + ["PR", "S\u{e3}o Manoel do Paran\u{e1}", "4125555"], + ["PR", "S\u{e3}o Mateus do Sul", "4125605"], + ["PR", "S\u{e3}o Miguel do Igua\u{e7}u", "4125704"], + ["PR", "S\u{e3}o Pedro do Igua\u{e7}u", "4125753"], + ["PR", "S\u{e3}o Pedro do Iva\u{ed}", "4125803"], + ["PR", "S\u{e3}o Pedro do Paran\u{e1}", "4125902"], + ["PR", "S\u{e3}o Sebasti\u{e3}o da Amoreira", "4126009"], + ["PR", "S\u{e3}o Tom\u{e9}", "4126108"], + ["PR", "Sapopema", "4126207"], + ["PR", "Sarandi", "4126256"], + ["PR", "Saudade do Igua\u{e7}u", "4126272"], + ["PR", "Seng\u{e9}s", "4126306"], + ["PR", "Serran\u{f3}polis do Igua\u{e7}u", "4126355"], + ["PR", "Sertaneja", "4126405"], + ["PR", "Sertan\u{f3}polis", "4126504"], + ["PR", "Siqueira Campos", "4126603"], + ["PR", "Sulina", "4126652"], + ["PR", "Tamarana", "4126678"], + ["PR", "Tamboara", "4126702"], + ["PR", "Tapejara", "4126801"], + ["PR", "Tapira", "4126900"], + ["PR", "Teixeira Soares", "4127007"], + ["PR", "Tel\u{ea}maco Borba", "4127106"], + ["PR", "Terra Boa", "4127205"], + ["PR", "Terra Rica", "4127304"], + ["PR", "Terra Roxa", "4127403"], + ["PR", "Tibagi", "4127502"], + ["PR", "Tijucas do Sul", "4127601"], + ["PR", "Toledo", "4127700"], + ["PR", "Tomazina", "4127809"], + ["PR", "Tr\u{ea}s Barras do Paran\u{e1}", "4127858"], + ["PR", "Tunas do Paran\u{e1}", "4127882"], + ["PR", "Tuneiras do Oeste", "4127908"], + ["PR", "Tup\u{e3}ssi", "4127957"], + ["PR", "Turvo", "4127965"], + ["PR", "Ubirat\u{e3}", "4128005"], + ["PR", "Umuarama", "4128104"], + ["PR", "Uni\u{e3}o da Vit\u{f3}ria", "4128203"], + ["PR", "Uniflor", "4128302"], + ["PR", "Ura\u{ed}", "4128401"], + ["PR", "Ventania", "4128534"], + ["PR", "Vera Cruz do Oeste", "4128559"], + ["PR", "Ver\u{ea}", "4128609"], + ["PR", "Virmond", "4128658"], + ["PR", "Vitorino", "4128708"], + ["PR", "Wenceslau Braz", "4128500"], + ["PR", "Xambr\u{ea}", "4128807"], + ["PE", "Abreu e Lima", "2600054"], + ["PE", "Afogados da Ingazeira", "2600104"], + ["PE", "Afr\u{e2}nio", "2600203"], + ["PE", "Agrestina", "2600302"], + ["PE", "\u{c1}gua Preta", "2600401"], + ["PE", "\u{c1}guas Belas", "2600500"], + ["PE", "Alagoinha", "2600609"], + ["PE", "Alian\u{e7}a", "2600708"], + ["PE", "Altinho", "2600807"], + ["PE", "Amaraji", "2600906"], + ["PE", "Angelim", "2601003"], + ["PE", "Ara\u{e7}oiaba", "2601052"], + ["PE", "Araripina", "2601102"], + ["PE", "Arcoverde", "2601201"], + ["PE", "Barra de Guabiraba", "2601300"], + ["PE", "Barreiros", "2601409"], + ["PE", "Bel\u{e9}m de Maria", "2601508"], + ["PE", "Bel\u{e9}m do S\u{e3}o Francisco", "2601607"], + ["PE", "Belo Jardim", "2601706"], + ["PE", "Bet\u{e2}nia", "2601805"], + ["PE", "Bezerros", "2601904"], + ["PE", "Bodoc\u{f3}", "2602001"], + ["PE", "Bom Conselho", "2602100"], + ["PE", "Bom Jardim", "2602209"], + ["PE", "Bonito", "2602308"], + ["PE", "Brej\u{e3}o", "2602407"], + ["PE", "Brejinho", "2602506"], + ["PE", "Brejo da Madre de Deus", "2602605"], + ["PE", "Buenos Aires", "2602704"], + ["PE", "Bu\u{ed}que", "2602803"], + ["PE", "Cabo de Santo Agostinho", "2602902"], + ["PE", "Cabrob\u{f3}", "2603009"], + ["PE", "Cachoeirinha", "2603108"], + ["PE", "Caet\u{e9}s", "2603207"], + ["PE", "Cal\u{e7}ado", "2603306"], + ["PE", "Calumbi", "2603405"], + ["PE", "Camaragibe", "2603454"], + ["PE", "Camocim de S\u{e3}o F\u{e9}lix", "2603504"], + ["PE", "Camutanga", "2603603"], + ["PE", "Canhotinho", "2603702"], + ["PE", "Capoeiras", "2603801"], + ["PE", "Carna\u{ed}ba", "2603900"], + ["PE", "Carnaubeira da Penha", "2603926"], + ["PE", "Carpina", "2604007"], + ["PE", "Caruaru", "2604106"], + ["PE", "Casinhas", "2604155"], + ["PE", "Catende", "2604205"], + ["PE", "Cedro", "2604304"], + ["PE", "Ch\u{e3} de Alegria", "2604403"], + ["PE", "Ch\u{e3} Grande", "2604502"], + ["PE", "Condado", "2604601"], + ["PE", "Correntes", "2604700"], + ["PE", "Cort\u{ea}s", "2604809"], + ["PE", "Cumaru", "2604908"], + ["PE", "Cupira", "2605004"], + ["PE", "Cust\u{f3}dia", "2605103"], + ["PE", "Dormentes", "2605152"], + ["PE", "Escada", "2605202"], + ["PE", "Exu", "2605301"], + ["PE", "Feira Nova", "2605400"], + ["PE", "Fernando de Noronha", "2605459"], + ["PE", "Ferreiros", "2605509"], + ["PE", "Flores", "2605608"], + ["PE", "Floresta", "2605707"], + ["PE", "Frei Miguelinho", "2605806"], + ["PE", "Gameleira", "2605905"], + ["PE", "Garanhuns", "2606002"], + ["PE", "Gl\u{f3}ria do Goit\u{e1}", "2606101"], + ["PE", "Goiana", "2606200"], + ["PE", "Granito", "2606309"], + ["PE", "Gravat\u{e1}", "2606408"], + ["PE", "Iati", "2606507"], + ["PE", "Ibimirim", "2606606"], + ["PE", "Ibirajuba", "2606705"], + ["PE", "Igarassu", "2606804"], + ["PE", "Iguaracy", "2606903"], + ["PE", "Ilha de Itamarac\u{e1}", "2607604"], + ["PE", "Inaj\u{e1}", "2607000"], + ["PE", "Ingazeira", "2607109"], + ["PE", "Ipojuca", "2607208"], + ["PE", "Ipubi", "2607307"], + ["PE", "Itacuruba", "2607406"], + ["PE", "Ita\u{ed}ba", "2607505"], + ["PE", "Itamb\u{e9}", "2607653"], + ["PE", "Itapetim", "2607703"], + ["PE", "Itapissuma", "2607752"], + ["PE", "Itaquitinga", "2607802"], + ["PE", "Jaboat\u{e3}o dos Guararapes", "2607901"], + ["PE", "Jaqueira", "2607950"], + ["PE", "Jata\u{fa}ba", "2608008"], + ["PE", "Jatob\u{e1}", "2608057"], + ["PE", "Jo\u{e3}o Alfredo", "2608107"], + ["PE", "Joaquim Nabuco", "2608206"], + ["PE", "Jucati", "2608255"], + ["PE", "Jupi", "2608305"], + ["PE", "Jurema", "2608404"], + ["PE", "Lagoa de Itaenga", "2608503"], + ["PE", "Lagoa do Carro", "2608453"], + ["PE", "Lagoa do Ouro", "2608602"], + ["PE", "Lagoa dos Gatos", "2608701"], + ["PE", "Lagoa Grande", "2608750"], + ["PE", "Lajedo", "2608800"], + ["PE", "Limoeiro", "2608909"], + ["PE", "Macaparana", "2609006"], + ["PE", "Machados", "2609105"], + ["PE", "Manari", "2609154"], + ["PE", "Maraial", "2609204"], + ["PE", "Mirandiba", "2609303"], + ["PE", "Moreil\u{e2}ndia", "2614303"], + ["PE", "Moreno", "2609402"], + ["PE", "Nazar\u{e9} da Mata", "2609501"], + ["PE", "Olinda", "2609600"], + ["PE", "Orob\u{f3}", "2609709"], + ["PE", "Oroc\u{f3}", "2609808"], + ["PE", "Ouricuri", "2609907"], + ["PE", "Palmares", "2610004"], + ["PE", "Palmeirina", "2610103"], + ["PE", "Panelas", "2610202"], + ["PE", "Paranatama", "2610301"], + ["PE", "Parnamirim", "2610400"], + ["PE", "Passira", "2610509"], + ["PE", "Paudalho", "2610608"], + ["PE", "Paulista", "2610707"], + ["PE", "Pedra", "2610806"], + ["PE", "Pesqueira", "2610905"], + ["PE", "Petrol\u{e2}ndia", "2611002"], + ["PE", "Petrolina", "2611101"], + ["PE", "Po\u{e7}\u{e3}o", "2611200"], + ["PE", "Pombos", "2611309"], + ["PE", "Primavera", "2611408"], + ["PE", "Quipap\u{e1}", "2611507"], + ["PE", "Quixaba", "2611533"], + ["PE", "Recife", "2611606"], + ["PE", "Riacho das Almas", "2611705"], + ["PE", "Ribeir\u{e3}o", "2611804"], + ["PE", "Rio Formoso", "2611903"], + ["PE", "Sair\u{e9}", "2612000"], + ["PE", "Salgadinho", "2612109"], + ["PE", "Salgueiro", "2612208"], + ["PE", "Salo\u{e1}", "2612307"], + ["PE", "Sanhar\u{f3}", "2612406"], + ["PE", "Santa Cruz", "2612455"], + ["PE", "Santa Cruz da Baixa Verde", "2612471"], + ["PE", "Santa Cruz do Capibaribe", "2612505"], + ["PE", "Santa Filomena", "2612554"], + ["PE", "Santa Maria da Boa Vista", "2612604"], + ["PE", "Santa Maria do Cambuc\u{e1}", "2612703"], + ["PE", "Santa Terezinha", "2612802"], + ["PE", "S\u{e3}o Benedito do Sul", "2612901"], + ["PE", "S\u{e3}o Bento do Una", "2613008"], + ["PE", "S\u{e3}o Caitano", "2613107"], + ["PE", "S\u{e3}o Jo\u{e3}o", "2613206"], + ["PE", "S\u{e3}o Joaquim do Monte", "2613305"], + ["PE", "S\u{e3}o Jos\u{e9} da Coroa Grande", "2613404"], + ["PE", "S\u{e3}o Jos\u{e9} do Belmonte", "2613503"], + ["PE", "S\u{e3}o Jos\u{e9} do Egito", "2613602"], + ["PE", "S\u{e3}o Louren\u{e7}o da Mata", "2613701"], + ["PE", "S\u{e3}o Vicente F\u{e9}rrer", "2613800"], + ["PE", "Serra Talhada", "2613909"], + ["PE", "Serrita", "2614006"], + ["PE", "Sert\u{e2}nia", "2614105"], + ["PE", "Sirinha\u{e9}m", "2614204"], + ["PE", "Solid\u{e3}o", "2614402"], + ["PE", "Surubim", "2614501"], + ["PE", "Tabira", "2614600"], + ["PE", "Tacaimb\u{f3}", "2614709"], + ["PE", "Tacaratu", "2614808"], + ["PE", "Tamandar\u{e9}", "2614857"], + ["PE", "Taquaritinga do Norte", "2615003"], + ["PE", "Terezinha", "2615102"], + ["PE", "Terra Nova", "2615201"], + ["PE", "Timba\u{fa}ba", "2615300"], + ["PE", "Toritama", "2615409"], + ["PE", "Tracunha\u{e9}m", "2615508"], + ["PE", "Trindade", "2615607"], + ["PE", "Triunfo", "2615706"], + ["PE", "Tupanatinga", "2615805"], + ["PE", "Tuparetama", "2615904"], + ["PE", "Venturosa", "2616001"], + ["PE", "Verdejante", "2616100"], + ["PE", "Vertente do L\u{e9}rio", "2616183"], + ["PE", "Vertentes", "2616209"], + ["PE", "Vic\u{ea}ncia", "2616308"], + ["PE", "Vit\u{f3}ria de Santo Ant\u{e3}o", "2616407"], + ["PE", "Xex\u{e9}u", "2616506"], + ["PI", "Acau\u{e3}", "2200053"], + ["PI", "Agricol\u{e2}ndia", "2200103"], + ["PI", "\u{c1}gua Branca", "2200202"], + ["PI", "Alagoinha do Piau\u{ed}", "2200251"], + ["PI", "Alegrete do Piau\u{ed}", "2200277"], + ["PI", "Alto Long\u{e1}", "2200301"], + ["PI", "Altos", "2200400"], + ["PI", "Alvorada do Gurgu\u{e9}ia", "2200459"], + ["PI", "Amarante", "2200509"], + ["PI", "Angical do Piau\u{ed}", "2200608"], + ["PI", "An\u{ed}sio de Abreu", "2200707"], + ["PI", "Ant\u{f4}nio Almeida", "2200806"], + ["PI", "Aroazes", "2200905"], + ["PI", "Aroeiras do Itaim", "2200954"], + ["PI", "Arraial", "2201002"], + ["PI", "Assun\u{e7}\u{e3}o do Piau\u{ed}", "2201051"], + ["PI", "Avelino Lopes", "2201101"], + ["PI", "Baixa Grande do Ribeiro", "2201150"], + ["PI", "Barra D'Alc\u{e2}ntara", "2201176"], + ["PI", "Barras", "2201200"], + ["PI", "Barreiras do Piau\u{ed}", "2201309"], + ["PI", "Barro Duro", "2201408"], + ["PI", "Batalha", "2201507"], + ["PI", "Bela Vista do Piau\u{ed}", "2201556"], + ["PI", "Bel\u{e9}m do Piau\u{ed}", "2201572"], + ["PI", "Beneditinos", "2201606"], + ["PI", "Bertol\u{ed}nia", "2201705"], + ["PI", "Bet\u{e2}nia do Piau\u{ed}", "2201739"], + ["PI", "Boa Hora", "2201770"], + ["PI", "Bocaina", "2201804"], + ["PI", "Bom Jesus", "2201903"], + ["PI", "Bom Princ\u{ed}pio do Piau\u{ed}", "2201919"], + ["PI", "Bonfim do Piau\u{ed}", "2201929"], + ["PI", "Boqueir\u{e3}o do Piau\u{ed}", "2201945"], + ["PI", "Brasileira", "2201960"], + ["PI", "Brejo do Piau\u{ed}", "2201988"], + ["PI", "Buriti dos Lopes", "2202000"], + ["PI", "Buriti dos Montes", "2202026"], + ["PI", "Cabeceiras do Piau\u{ed}", "2202059"], + ["PI", "Cajazeiras do Piau\u{ed}", "2202075"], + ["PI", "Cajueiro da Praia", "2202083"], + ["PI", "Caldeir\u{e3}o Grande do Piau\u{ed}", "2202091"], + ["PI", "Campinas do Piau\u{ed}", "2202109"], + ["PI", "Campo Alegre do Fidalgo", "2202117"], + ["PI", "Campo Grande do Piau\u{ed}", "2202133"], + ["PI", "Campo Largo do Piau\u{ed}", "2202174"], + ["PI", "Campo Maior", "2202208"], + ["PI", "Canavieira", "2202251"], + ["PI", "Canto do Buriti", "2202307"], + ["PI", "Capit\u{e3}o de Campos", "2202406"], + ["PI", "Capit\u{e3}o Gerv\u{e1}sio Oliveira", "2202455"], + ["PI", "Caracol", "2202505"], + ["PI", "Cara\u{fa}bas do Piau\u{ed}", "2202539"], + ["PI", "Caridade do Piau\u{ed}", "2202554"], + ["PI", "Castelo do Piau\u{ed}", "2202604"], + ["PI", "Caxing\u{f3}", "2202653"], + ["PI", "Cocal", "2202703"], + ["PI", "Cocal de Telha", "2202711"], + ["PI", "Cocal dos Alves", "2202729"], + ["PI", "Coivaras", "2202737"], + ["PI", "Col\u{f4}nia do Gurgu\u{e9}ia", "2202752"], + ["PI", "Col\u{f4}nia do Piau\u{ed}", "2202778"], + ["PI", "Concei\u{e7}\u{e3}o do Canind\u{e9}", "2202802"], + ["PI", "Coronel Jos\u{e9} Dias", "2202851"], + ["PI", "Corrente", "2202901"], + ["PI", "Cristal\u{e2}ndia do Piau\u{ed}", "2203008"], + ["PI", "Cristino Castro", "2203107"], + ["PI", "Curimat\u{e1}", "2203206"], + ["PI", "Currais", "2203230"], + ["PI", "Curral Novo do Piau\u{ed}", "2203271"], + ["PI", "Curralinhos", "2203255"], + ["PI", "Demerval Lob\u{e3}o", "2203305"], + ["PI", "Dirceu Arcoverde", "2203354"], + ["PI", "Dom Expedito Lopes", "2203404"], + ["PI", "Dom Inoc\u{ea}ncio", "2203453"], + ["PI", "Domingos Mour\u{e3}o", "2203420"], + ["PI", "Elesb\u{e3}o Veloso", "2203503"], + ["PI", "Eliseu Martins", "2203602"], + ["PI", "Esperantina", "2203701"], + ["PI", "Fartura do Piau\u{ed}", "2203750"], + ["PI", "Flores do Piau\u{ed}", "2203800"], + ["PI", "Floresta do Piau\u{ed}", "2203859"], + ["PI", "Floriano", "2203909"], + ["PI", "Francin\u{f3}polis", "2204006"], + ["PI", "Francisco Ayres", "2204105"], + ["PI", "Francisco Macedo", "2204154"], + ["PI", "Francisco Santos", "2204204"], + ["PI", "Fronteiras", "2204303"], + ["PI", "Geminiano", "2204352"], + ["PI", "Gilbu\u{e9}s", "2204402"], + ["PI", "Guadalupe", "2204501"], + ["PI", "Guaribas", "2204550"], + ["PI", "Hugo Napole\u{e3}o", "2204600"], + ["PI", "Ilha Grande", "2204659"], + ["PI", "Inhuma", "2204709"], + ["PI", "Ipiranga do Piau\u{ed}", "2204808"], + ["PI", "Isa\u{ed}as Coelho", "2204907"], + ["PI", "Itain\u{f3}polis", "2205003"], + ["PI", "Itaueira", "2205102"], + ["PI", "Jacobina do Piau\u{ed}", "2205151"], + ["PI", "Jaic\u{f3}s", "2205201"], + ["PI", "Jardim do Mulato", "2205250"], + ["PI", "Jatob\u{e1} do Piau\u{ed}", "2205276"], + ["PI", "Jerumenha", "2205300"], + ["PI", "Jo\u{e3}o Costa", "2205359"], + ["PI", "Joaquim Pires", "2205409"], + ["PI", "Joca Marques", "2205458"], + ["PI", "Jos\u{e9} de Freitas", "2205508"], + ["PI", "Juazeiro do Piau\u{ed}", "2205516"], + ["PI", "J\u{fa}lio Borges", "2205524"], + ["PI", "Jurema", "2205532"], + ["PI", "Lagoa Alegre", "2205557"], + ["PI", "Lagoa de S\u{e3}o Francisco", "2205573"], + ["PI", "Lagoa do Barro do Piau\u{ed}", "2205565"], + ["PI", "Lagoa do Piau\u{ed}", "2205581"], + ["PI", "Lagoa do S\u{ed}tio", "2205599"], + ["PI", "Lagoinha do Piau\u{ed}", "2205540"], + ["PI", "Landri Sales", "2205607"], + ["PI", "Lu\u{ed}s Correia", "2205706"], + ["PI", "Luzil\u{e2}ndia", "2205805"], + ["PI", "Madeiro", "2205854"], + ["PI", "Manoel Em\u{ed}dio", "2205904"], + ["PI", "Marcol\u{e2}ndia", "2205953"], + ["PI", "Marcos Parente", "2206001"], + ["PI", "Massap\u{ea} do Piau\u{ed}", "2206050"], + ["PI", "Matias Ol\u{ed}mpio", "2206100"], + ["PI", "Miguel Alves", "2206209"], + ["PI", "Miguel Le\u{e3}o", "2206308"], + ["PI", "Milton Brand\u{e3}o", "2206357"], + ["PI", "Monsenhor Gil", "2206407"], + ["PI", "Monsenhor Hip\u{f3}lito", "2206506"], + ["PI", "Monte Alegre do Piau\u{ed}", "2206605"], + ["PI", "Morro Cabe\u{e7}a no Tempo", "2206654"], + ["PI", "Morro do Chap\u{e9}u do Piau\u{ed}", "2206670"], + ["PI", "Murici dos Portelas", "2206696"], + ["PI", "Nazar\u{e9} do Piau\u{ed}", "2206704"], + ["PI", "Naz\u{e1}ria", "2206720"], + ["PI", "Nossa Senhora de Nazar\u{e9}", "2206753"], + ["PI", "Nossa Senhora dos Rem\u{e9}dios", "2206803"], + ["PI", "Nova Santa Rita", "2207959"], + ["PI", "Novo Oriente do Piau\u{ed}", "2206902"], + ["PI", "Novo Santo Ant\u{f4}nio", "2206951"], + ["PI", "Oeiras", "2207009"], + ["PI", "Olho D'\u{c1}gua do Piau\u{ed}", "2207108"], + ["PI", "Padre Marcos", "2207207"], + ["PI", "Paes Landim", "2207306"], + ["PI", "Paje\u{fa} do Piau\u{ed}", "2207355"], + ["PI", "Palmeira do Piau\u{ed}", "2207405"], + ["PI", "Palmeirais", "2207504"], + ["PI", "Paquet\u{e1}", "2207553"], + ["PI", "Parnagu\u{e1}", "2207603"], + ["PI", "Parna\u{ed}ba", "2207702"], + ["PI", "Passagem Franca do Piau\u{ed}", "2207751"], + ["PI", "Patos do Piau\u{ed}", "2207777"], + ["PI", "Pau D'Arco do Piau\u{ed}", "2207793"], + ["PI", "Paulistana", "2207801"], + ["PI", "Pavussu", "2207850"], + ["PI", "Pedro II", "2207900"], + ["PI", "Pedro Laurentino", "2207934"], + ["PI", "Picos", "2208007"], + ["PI", "Pimenteiras", "2208106"], + ["PI", "Pio IX", "2208205"], + ["PI", "Piracuruca", "2208304"], + ["PI", "Piripiri", "2208403"], + ["PI", "Porto", "2208502"], + ["PI", "Porto Alegre do Piau\u{ed}", "2208551"], + ["PI", "Prata do Piau\u{ed}", "2208601"], + ["PI", "Queimada Nova", "2208650"], + ["PI", "Reden\u{e7}\u{e3}o do Gurgu\u{e9}ia", "2208700"], + ["PI", "Regenera\u{e7}\u{e3}o", "2208809"], + ["PI", "Riacho Frio", "2208858"], + ["PI", "Ribeira do Piau\u{ed}", "2208874"], + ["PI", "Ribeiro Gon\u{e7}alves", "2208908"], + ["PI", "Rio Grande do Piau\u{ed}", "2209005"], + ["PI", "Santa Cruz do Piau\u{ed}", "2209104"], + ["PI", "Santa Cruz dos Milagres", "2209153"], + ["PI", "Santa Filomena", "2209203"], + ["PI", "Santa Luz", "2209302"], + ["PI", "Santa Rosa do Piau\u{ed}", "2209377"], + ["PI", "Santana do Piau\u{ed}", "2209351"], + ["PI", "Santo Ant\u{f4}nio de Lisboa", "2209401"], + ["PI", "Santo Ant\u{f4}nio dos Milagres", "2209450"], + ["PI", "Santo In\u{e1}cio do Piau\u{ed}", "2209500"], + ["PI", "S\u{e3}o Braz do Piau\u{ed}", "2209559"], + ["PI", "S\u{e3}o F\u{e9}lix do Piau\u{ed}", "2209609"], + ["PI", "S\u{e3}o Francisco de Assis do Piau\u{ed}", "2209658"], + ["PI", "S\u{e3}o Francisco do Piau\u{ed}", "2209708"], + ["PI", "S\u{e3}o Gon\u{e7}alo do Gurgu\u{e9}ia", "2209757"], + ["PI", "S\u{e3}o Gon\u{e7}alo do Piau\u{ed}", "2209807"], + ["PI", "S\u{e3}o Jo\u{e3}o da Canabrava", "2209856"], + ["PI", "S\u{e3}o Jo\u{e3}o da Fronteira", "2209872"], + ["PI", "S\u{e3}o Jo\u{e3}o da Serra", "2209906"], + ["PI", "S\u{e3}o Jo\u{e3}o da Varjota", "2209955"], + ["PI", "S\u{e3}o Jo\u{e3}o do Arraial", "2209971"], + ["PI", "S\u{e3}o Jo\u{e3}o do Piau\u{ed}", "2210003"], + ["PI", "S\u{e3}o Jos\u{e9} do Divino", "2210052"], + ["PI", "S\u{e3}o Jos\u{e9} do Peixe", "2210102"], + ["PI", "S\u{e3}o Jos\u{e9} do Piau\u{ed}", "2210201"], + ["PI", "S\u{e3}o Juli\u{e3}o", "2210300"], + ["PI", "S\u{e3}o Louren\u{e7}o do Piau\u{ed}", "2210359"], + ["PI", "S\u{e3}o Luis do Piau\u{ed}", "2210375"], + ["PI", "S\u{e3}o Miguel da Baixa Grande", "2210383"], + ["PI", "S\u{e3}o Miguel do Fidalgo", "2210391"], + ["PI", "S\u{e3}o Miguel do Tapuio", "2210409"], + ["PI", "S\u{e3}o Pedro do Piau\u{ed}", "2210508"], + ["PI", "S\u{e3}o Raimundo Nonato", "2210607"], + ["PI", "Sebasti\u{e3}o Barros", "2210623"], + ["PI", "Sebasti\u{e3}o Leal", "2210631"], + ["PI", "Sigefredo Pacheco", "2210656"], + ["PI", "Sim\u{f5}es", "2210706"], + ["PI", "Simpl\u{ed}cio Mendes", "2210805"], + ["PI", "Socorro do Piau\u{ed}", "2210904"], + ["PI", "Sussuapara", "2210938"], + ["PI", "Tamboril do Piau\u{ed}", "2210953"], + ["PI", "Tanque do Piau\u{ed}", "2210979"], + ["PI", "Teresina", "2211001"], + ["PI", "Uni\u{e3}o", "2211100"], + ["PI", "Uru\u{e7}u\u{ed}", "2211209"], + ["PI", "Valen\u{e7}a do Piau\u{ed}", "2211308"], + ["PI", "V\u{e1}rzea Branca", "2211357"], + ["PI", "V\u{e1}rzea Grande", "2211407"], + ["PI", "Vera Mendes", "2211506"], + ["PI", "Vila Nova do Piau\u{ed}", "2211605"], + ["PI", "Wall Ferraz", "2211704"], + ["RJ", "Angra dos Reis", "3300100"], + ["RJ", "Aperib\u{e9}", "3300159"], + ["RJ", "Araruama", "3300209"], + ["RJ", "Areal", "3300225"], + ["RJ", "Arma\u{e7}\u{e3}o dos B\u{fa}zios", "3300233"], + ["RJ", "Arraial do Cabo", "3300258"], + ["RJ", "Barra do Pira\u{ed}", "3300308"], + ["RJ", "Barra Mansa", "3300407"], + ["RJ", "Belford Roxo", "3300456"], + ["RJ", "Bom Jardim", "3300506"], + ["RJ", "Bom Jesus do Itabapoana", "3300605"], + ["RJ", "Cabo Frio", "3300704"], + ["RJ", "Cachoeiras de Macacu", "3300803"], + ["RJ", "Cambuci", "3300902"], + ["RJ", "Campos dos Goytacazes", "3301009"], + ["RJ", "Cantagalo", "3301108"], + ["RJ", "Carapebus", "3300936"], + ["RJ", "Cardoso Moreira", "3301157"], + ["RJ", "Carmo", "3301207"], + ["RJ", "Casimiro de Abreu", "3301306"], + ["RJ", "Comendador Levy Gasparian", "3300951"], + ["RJ", "Concei\u{e7}\u{e3}o de Macabu", "3301405"], + ["RJ", "Cordeiro", "3301504"], + ["RJ", "Duas Barras", "3301603"], + ["RJ", "Duque de Caxias", "3301702"], + ["RJ", "Engenheiro Paulo de Frontin", "3301801"], + ["RJ", "Guapimirim", "3301850"], + ["RJ", "Iguaba Grande", "3301876"], + ["RJ", "Itabora\u{ed}", "3301900"], + ["RJ", "Itagua\u{ed}", "3302007"], + ["RJ", "Italva", "3302056"], + ["RJ", "Itaocara", "3302106"], + ["RJ", "Itaperuna", "3302205"], + ["RJ", "Itatiaia", "3302254"], + ["RJ", "Japeri", "3302270"], + ["RJ", "Laje do Muria\u{e9}", "3302304"], + ["RJ", "Maca\u{e9}", "3302403"], + ["RJ", "Macuco", "3302452"], + ["RJ", "Mag\u{e9}", "3302502"], + ["RJ", "Mangaratiba", "3302601"], + ["RJ", "Maric\u{e1}", "3302700"], + ["RJ", "Mendes", "3302809"], + ["RJ", "Mesquita", "3302858"], + ["RJ", "Miguel Pereira", "3302908"], + ["RJ", "Miracema", "3303005"], + ["RJ", "Natividade", "3303104"], + ["RJ", "Nil\u{f3}polis", "3303203"], + ["RJ", "Niter\u{f3}i", "3303302"], + ["RJ", "Nova Friburgo", "3303401"], + ["RJ", "Nova Igua\u{e7}u", "3303500"], + ["RJ", "Paracambi", "3303609"], + ["RJ", "Para\u{ed}ba do Sul", "3303708"], + ["RJ", "Paraty", "3303807"], + ["RJ", "Paty do Alferes", "3303856"], + ["RJ", "Petr\u{f3}polis", "3303906"], + ["RJ", "Pinheiral", "3303955"], + ["RJ", "Pira\u{ed}", "3304003"], + ["RJ", "Porci\u{fa}ncula", "3304102"], + ["RJ", "Porto Real", "3304110"], + ["RJ", "Quatis", "3304128"], + ["RJ", "Queimados", "3304144"], + ["RJ", "Quissam\u{e3}", "3304151"], + ["RJ", "Resende", "3304201"], + ["RJ", "Rio Bonito", "3304300"], + ["RJ", "Rio Claro", "3304409"], + ["RJ", "Rio das Flores", "3304508"], + ["RJ", "Rio das Ostras", "3304524"], + ["RJ", "Rio de Janeiro", "3304557"], + ["RJ", "Santa Maria Madalena", "3304607"], + ["RJ", "Santo Ant\u{f4}nio de P\u{e1}dua", "3304706"], + ["RJ", "S\u{e3}o Fid\u{e9}lis", "3304805"], + ["RJ", "S\u{e3}o Francisco de Itabapoana", "3304755"], + ["RJ", "S\u{e3}o Gon\u{e7}alo", "3304904"], + ["RJ", "S\u{e3}o Jo\u{e3}o da Barra", "3305000"], + ["RJ", "S\u{e3}o Jo\u{e3}o de Meriti", "3305109"], + ["RJ", "S\u{e3}o Jos\u{e9} de Ub\u{e1}", "3305133"], + ["RJ", "S\u{e3}o Jos\u{e9} do Vale do Rio Preto", "3305158"], + ["RJ", "S\u{e3}o Pedro da Aldeia", "3305208"], + ["RJ", "S\u{e3}o Sebasti\u{e3}o do Alto", "3305307"], + ["RJ", "Sapucaia", "3305406"], + ["RJ", "Saquarema", "3305505"], + ["RJ", "Serop\u{e9}dica", "3305554"], + ["RJ", "Silva Jardim", "3305604"], + ["RJ", "Sumidouro", "3305703"], + ["RJ", "Tangu\u{e1}", "3305752"], + ["RJ", "Teres\u{f3}polis", "3305802"], + ["RJ", "Trajano de Moraes", "3305901"], + ["RJ", "Tr\u{ea}s Rios", "3306008"], + ["RJ", "Valen\u{e7}a", "3306107"], + ["RJ", "Varre-Sai", "3306156"], + ["RJ", "Vassouras", "3306206"], + ["RJ", "Volta Redonda", "3306305"], + ["RN", "Acari", "2400109"], + ["RN", "Afonso Bezerra", "2400307"], + ["RN", "\u{c1}gua Nova", "2400406"], + ["RN", "Alexandria", "2400505"], + ["RN", "Almino Afonso", "2400604"], + ["RN", "Alto do Rodrigues", "2400703"], + ["RN", "Angicos", "2400802"], + ["RN", "Ant\u{f4}nio Martins", "2400901"], + ["RN", "Apodi", "2401008"], + ["RN", "Areia Branca", "2401107"], + ["RN", "Arez", "2401206"], + ["RN", "Ass\u{fa}", "2400208"], + ["RN", "Ba\u{ed}a Formosa", "2401404"], + ["RN", "Bara\u{fa}na", "2401453"], + ["RN", "Barcelona", "2401503"], + ["RN", "Bento Fernandes", "2401602"], + ["RN", "Bod\u{f3}", "2401651"], + ["RN", "Bom Jesus", "2401701"], + ["RN", "Brejinho", "2401800"], + ["RN", "Cai\u{e7}ara do Norte", "2401859"], + ["RN", "Cai\u{e7}ara do Rio do Vento", "2401909"], + ["RN", "Caic\u{f3}", "2402006"], + ["RN", "Campo Grande", "2401305"], + ["RN", "Campo Redondo", "2402105"], + ["RN", "Canguaretama", "2402204"], + ["RN", "Cara\u{fa}bas", "2402303"], + ["RN", "Carna\u{fa}ba dos Dantas", "2402402"], + ["RN", "Carnaubais", "2402501"], + ["RN", "Cear\u{e1}-Mirim", "2402600"], + ["RN", "Cerro Cor\u{e1}", "2402709"], + ["RN", "Coronel Ezequiel", "2402808"], + ["RN", "Coronel Jo\u{e3}o Pessoa", "2402907"], + ["RN", "Cruzeta", "2403004"], + ["RN", "Currais Novos", "2403103"], + ["RN", "Doutor Severiano", "2403202"], + ["RN", "Encanto", "2403301"], + ["RN", "Equador", "2403400"], + ["RN", "Esp\u{ed}rito Santo", "2403509"], + ["RN", "Extremoz", "2403608"], + ["RN", "Felipe Guerra", "2403707"], + ["RN", "Fernando Pedroza", "2403756"], + ["RN", "Flor\u{e2}nia", "2403806"], + ["RN", "Francisco Dantas", "2403905"], + ["RN", "Frutuoso Gomes", "2404002"], + ["RN", "Galinhos", "2404101"], + ["RN", "Goianinha", "2404200"], + ["RN", "Governador Dix-Sept Rosado", "2404309"], + ["RN", "Grossos", "2404408"], + ["RN", "Guamar\u{e9}", "2404507"], + ["RN", "Ielmo Marinho", "2404606"], + ["RN", "Ipangua\u{e7}u", "2404705"], + ["RN", "Ipueira", "2404804"], + ["RN", "Itaj\u{e1}", "2404853"], + ["RN", "Ita\u{fa}", "2404903"], + ["RN", "Ja\u{e7}an\u{e3}", "2405009"], + ["RN", "Janda\u{ed}ra", "2405108"], + ["RN", "Jandu\u{ed}s", "2405207"], + ["RN", "Janu\u{e1}rio Cicco", "2405306"], + ["RN", "Japi", "2405405"], + ["RN", "Jardim de Angicos", "2405504"], + ["RN", "Jardim de Piranhas", "2405603"], + ["RN", "Jardim do Serid\u{f3}", "2405702"], + ["RN", "Jo\u{e3}o C\u{e2}mara", "2405801"], + ["RN", "Jo\u{e3}o Dias", "2405900"], + ["RN", "Jos\u{e9} da Penha", "2406007"], + ["RN", "Jucurutu", "2406106"], + ["RN", "Jundi\u{e1}", "2406155"], + ["RN", "Lagoa d'Anta", "2406205"], + ["RN", "Lagoa de Pedras", "2406304"], + ["RN", "Lagoa de Velhos", "2406403"], + ["RN", "Lagoa Nova", "2406502"], + ["RN", "Lagoa Salgada", "2406601"], + ["RN", "Lajes", "2406700"], + ["RN", "Lajes Pintadas", "2406809"], + ["RN", "Lucr\u{e9}cia", "2406908"], + ["RN", "Lu\u{ed}s Gomes", "2407005"], + ["RN", "Maca\u{ed}ba", "2407104"], + ["RN", "Macau", "2407203"], + ["RN", "Major Sales", "2407252"], + ["RN", "Marcelino Vieira", "2407302"], + ["RN", "Martins", "2407401"], + ["RN", "Maxaranguape", "2407500"], + ["RN", "Messias Targino", "2407609"], + ["RN", "Montanhas", "2407708"], + ["RN", "Monte Alegre", "2407807"], + ["RN", "Monte das Gameleiras", "2407906"], + ["RN", "Mossor\u{f3}", "2408003"], + ["RN", "Natal", "2408102"], + ["RN", "N\u{ed}sia Floresta", "2408201"], + ["RN", "Nova Cruz", "2408300"], + ["RN", "Olho d'\u{c1}gua do Borges", "2408409"], + ["RN", "Ouro Branco", "2408508"], + ["RN", "Paran\u{e1}", "2408607"], + ["RN", "Para\u{fa}", "2408706"], + ["RN", "Parazinho", "2408805"], + ["RN", "Parelhas", "2408904"], + ["RN", "Parnamirim", "2403251"], + ["RN", "Passa e Fica", "2409100"], + ["RN", "Passagem", "2409209"], + ["RN", "Patu", "2409308"], + ["RN", "Pau dos Ferros", "2409407"], + ["RN", "Pedra Grande", "2409506"], + ["RN", "Pedra Preta", "2409605"], + ["RN", "Pedro Avelino", "2409704"], + ["RN", "Pedro Velho", "2409803"], + ["RN", "Pend\u{ea}ncias", "2409902"], + ["RN", "Pil\u{f5}es", "2410009"], + ["RN", "Po\u{e7}o Branco", "2410108"], + ["RN", "Portalegre", "2410207"], + ["RN", "Porto do Mangue", "2410256"], + ["RN", "Pureza", "2410405"], + ["RN", "Rafael Fernandes", "2410504"], + ["RN", "Rafael Godeiro", "2410603"], + ["RN", "Riacho da Cruz", "2410702"], + ["RN", "Riacho de Santana", "2410801"], + ["RN", "Riachuelo", "2410900"], + ["RN", "Rio do Fogo", "2408953"], + ["RN", "Rodolfo Fernandes", "2411007"], + ["RN", "Ruy Barbosa", "2411106"], + ["RN", "Santa Cruz", "2411205"], + ["RN", "Santa Maria", "2409332"], + ["RN", "Santana do Matos", "2411403"], + ["RN", "Santana do Serid\u{f3}", "2411429"], + ["RN", "Santo Ant\u{f4}nio", "2411502"], + ["RN", "S\u{e3}o Bento do Norte", "2411601"], + ["RN", "S\u{e3}o Bento do Trair\u{ed}", "2411700"], + ["RN", "S\u{e3}o Fernando", "2411809"], + ["RN", "S\u{e3}o Francisco do Oeste", "2411908"], + ["RN", "S\u{e3}o Gon\u{e7}alo do Amarante", "2412005"], + ["RN", "S\u{e3}o Jo\u{e3}o do Sabugi", "2412104"], + ["RN", "S\u{e3}o Jos\u{e9} de Mipibu", "2412203"], + ["RN", "S\u{e3}o Jos\u{e9} do Campestre", "2412302"], + ["RN", "S\u{e3}o Jos\u{e9} do Serid\u{f3}", "2412401"], + ["RN", "S\u{e3}o Miguel", "2412500"], + ["RN", "S\u{e3}o Miguel do Gostoso", "2412559"], + ["RN", "S\u{e3}o Paulo do Potengi", "2412609"], + ["RN", "S\u{e3}o Pedro", "2412708"], + ["RN", "S\u{e3}o Rafael", "2412807"], + ["RN", "S\u{e3}o Tom\u{e9}", "2412906"], + ["RN", "S\u{e3}o Vicente", "2413003"], + ["RN", "Senador El\u{f3}i de Souza", "2413102"], + ["RN", "Senador Georgino Avelino", "2413201"], + ["RN", "Serra Caiada", "2410306"], + ["RN", "Serra de S\u{e3}o Bento", "2413300"], + ["RN", "Serra do Mel", "2413359"], + ["RN", "Serra Negra do Norte", "2413409"], + ["RN", "Serrinha", "2413508"], + ["RN", "Serrinha dos Pintos", "2413557"], + ["RN", "Severiano Melo", "2413607"], + ["RN", "S\u{ed}tio Novo", "2413706"], + ["RN", "Taboleiro Grande", "2413805"], + ["RN", "Taipu", "2413904"], + ["RN", "Tangar\u{e1}", "2414001"], + ["RN", "Tenente Ananias", "2414100"], + ["RN", "Tenente Laurentino Cruz", "2414159"], + ["RN", "Tibau", "2411056"], + ["RN", "Tibau do Sul", "2414209"], + ["RN", "Timba\u{fa}ba dos Batistas", "2414308"], + ["RN", "Touros", "2414407"], + ["RN", "Triunfo Potiguar", "2414456"], + ["RN", "Umarizal", "2414506"], + ["RN", "Upanema", "2414605"], + ["RN", "V\u{e1}rzea", "2414704"], + ["RN", "Venha-Ver", "2414753"], + ["RN", "Vera Cruz", "2414803"], + ["RN", "Vi\u{e7}osa", "2414902"], + ["RN", "Vila Flor", "2415008"], + ["RS", "Acegu\u{e1}", "4300034"], + ["RS", "\u{c1}gua Santa", "4300059"], + ["RS", "Agudo", "4300109"], + ["RS", "Ajuricaba", "4300208"], + ["RS", "Alecrim", "4300307"], + ["RS", "Alegrete", "4300406"], + ["RS", "Alegria", "4300455"], + ["RS", "Almirante Tamandar\u{e9} do Sul", "4300471"], + ["RS", "Alpestre", "4300505"], + ["RS", "Alto Alegre", "4300554"], + ["RS", "Alto Feliz", "4300570"], + ["RS", "Alvorada", "4300604"], + ["RS", "Amaral Ferrador", "4300638"], + ["RS", "Ametista do Sul", "4300646"], + ["RS", "Andr\u{e9} da Rocha", "4300661"], + ["RS", "Anta Gorda", "4300703"], + ["RS", "Ant\u{f4}nio Prado", "4300802"], + ["RS", "Arambar\u{e9}", "4300851"], + ["RS", "Araric\u{e1}", "4300877"], + ["RS", "Aratiba", "4300901"], + ["RS", "Arroio do Meio", "4301008"], + ["RS", "Arroio do Padre", "4301073"], + ["RS", "Arroio do Sal", "4301057"], + ["RS", "Arroio do Tigre", "4301206"], + ["RS", "Arroio dos Ratos", "4301107"], + ["RS", "Arroio Grande", "4301305"], + ["RS", "Arvorezinha", "4301404"], + ["RS", "Augusto Pestana", "4301503"], + ["RS", "\u{c1}urea", "4301552"], + ["RS", "Bag\u{e9}", "4301602"], + ["RS", "Balne\u{e1}rio Pinhal", "4301636"], + ["RS", "Bar\u{e3}o", "4301651"], + ["RS", "Bar\u{e3}o de Cotegipe", "4301701"], + ["RS", "Bar\u{e3}o do Triunfo", "4301750"], + ["RS", "Barra do Guarita", "4301859"], + ["RS", "Barra do Quara\u{ed}", "4301875"], + ["RS", "Barra do Ribeiro", "4301909"], + ["RS", "Barra do Rio Azul", "4301925"], + ["RS", "Barra Funda", "4301958"], + ["RS", "Barrac\u{e3}o", "4301800"], + ["RS", "Barros Cassal", "4302006"], + ["RS", "Benjamin Constant do Sul", "4302055"], + ["RS", "Bento Gon\u{e7}alves", "4302105"], + ["RS", "Boa Vista das Miss\u{f5}es", "4302154"], + ["RS", "Boa Vista do Buric\u{e1}", "4302204"], + ["RS", "Boa Vista do Cadeado", "4302220"], + ["RS", "Boa Vista do Incra", "4302238"], + ["RS", "Boa Vista do Sul", "4302253"], + ["RS", "Bom Jesus", "4302303"], + ["RS", "Bom Princ\u{ed}pio", "4302352"], + ["RS", "Bom Progresso", "4302378"], + ["RS", "Bom Retiro do Sul", "4302402"], + ["RS", "Boqueir\u{e3}o do Le\u{e3}o", "4302451"], + ["RS", "Bossoroca", "4302501"], + ["RS", "Bozano", "4302584"], + ["RS", "Braga", "4302600"], + ["RS", "Brochier", "4302659"], + ["RS", "Buti\u{e1}", "4302709"], + ["RS", "Ca\u{e7}apava do Sul", "4302808"], + ["RS", "Cacequi", "4302907"], + ["RS", "Cachoeira do Sul", "4303004"], + ["RS", "Cachoeirinha", "4303103"], + ["RS", "Cacique Doble", "4303202"], + ["RS", "Caibat\u{e9}", "4303301"], + ["RS", "Cai\u{e7}ara", "4303400"], + ["RS", "Camaqu\u{e3}", "4303509"], + ["RS", "Camargo", "4303558"], + ["RS", "Cambar\u{e1} do Sul", "4303608"], + ["RS", "Campestre da Serra", "4303673"], + ["RS", "Campina das Miss\u{f5}es", "4303707"], + ["RS", "Campinas do Sul", "4303806"], + ["RS", "Campo Bom", "4303905"], + ["RS", "Campo Novo", "4304002"], + ["RS", "Campos Borges", "4304101"], + ["RS", "Candel\u{e1}ria", "4304200"], + ["RS", "C\u{e2}ndido God\u{f3}i", "4304309"], + ["RS", "Candiota", "4304358"], + ["RS", "Canela", "4304408"], + ["RS", "Cangu\u{e7}u", "4304507"], + ["RS", "Canoas", "4304606"], + ["RS", "Canudos do Vale", "4304614"], + ["RS", "Cap\u{e3}o Bonito do Sul", "4304622"], + ["RS", "Cap\u{e3}o da Canoa", "4304630"], + ["RS", "Cap\u{e3}o do Cip\u{f3}", "4304655"], + ["RS", "Cap\u{e3}o do Le\u{e3}o", "4304663"], + ["RS", "Capela de Santana", "4304689"], + ["RS", "Capit\u{e3}o", "4304697"], + ["RS", "Capivari do Sul", "4304671"], + ["RS", "Cara\u{e1}", "4304713"], + ["RS", "Carazinho", "4304705"], + ["RS", "Carlos Barbosa", "4304804"], + ["RS", "Carlos Gomes", "4304853"], + ["RS", "Casca", "4304903"], + ["RS", "Caseiros", "4304952"], + ["RS", "Catu\u{ed}pe", "4305009"], + ["RS", "Caxias do Sul", "4305108"], + ["RS", "Centen\u{e1}rio", "4305116"], + ["RS", "Cerrito", "4305124"], + ["RS", "Cerro Branco", "4305132"], + ["RS", "Cerro Grande", "4305157"], + ["RS", "Cerro Grande do Sul", "4305173"], + ["RS", "Cerro Largo", "4305207"], + ["RS", "Chapada", "4305306"], + ["RS", "Charqueadas", "4305355"], + ["RS", "Charrua", "4305371"], + ["RS", "Chiapetta", "4305405"], + ["RS", "Chu\u{ed}", "4305439"], + ["RS", "Chuvisca", "4305447"], + ["RS", "Cidreira", "4305454"], + ["RS", "Cir\u{ed}aco", "4305504"], + ["RS", "Colinas", "4305587"], + ["RS", "Colorado", "4305603"], + ["RS", "Condor", "4305702"], + ["RS", "Constantina", "4305801"], + ["RS", "Coqueiro Baixo", "4305835"], + ["RS", "Coqueiros do Sul", "4305850"], + ["RS", "Coronel Barros", "4305871"], + ["RS", "Coronel Bicaco", "4305900"], + ["RS", "Coronel Pilar", "4305934"], + ["RS", "Cotipor\u{e3}", "4305959"], + ["RS", "Coxilha", "4305975"], + ["RS", "Crissiumal", "4306007"], + ["RS", "Cristal", "4306056"], + ["RS", "Cristal do Sul", "4306072"], + ["RS", "Cruz Alta", "4306106"], + ["RS", "Cruzaltense", "4306130"], + ["RS", "Cruzeiro do Sul", "4306205"], + ["RS", "David Canabarro", "4306304"], + ["RS", "Derrubadas", "4306320"], + ["RS", "Dezesseis de Novembro", "4306353"], + ["RS", "Dilermando de Aguiar", "4306379"], + ["RS", "Dois Irm\u{e3}os", "4306403"], + ["RS", "Dois Irm\u{e3}os das Miss\u{f5}es", "4306429"], + ["RS", "Dois Lajeados", "4306452"], + ["RS", "Dom Feliciano", "4306502"], + ["RS", "Dom Pedrito", "4306601"], + ["RS", "Dom Pedro de Alc\u{e2}ntara", "4306551"], + ["RS", "Dona Francisca", "4306700"], + ["RS", "Doutor Maur\u{ed}cio Cardoso", "4306734"], + ["RS", "Doutor Ricardo", "4306759"], + ["RS", "Eldorado do Sul", "4306767"], + ["RS", "Encantado", "4306809"], + ["RS", "Encruzilhada do Sul", "4306908"], + ["RS", "Engenho Velho", "4306924"], + ["RS", "Entre Rios do Sul", "4306957"], + ["RS", "Entre-Iju\u{ed}s", "4306932"], + ["RS", "Erebango", "4306973"], + ["RS", "Erechim", "4307005"], + ["RS", "Ernestina", "4307054"], + ["RS", "Erval Grande", "4307203"], + ["RS", "Erval Seco", "4307302"], + ["RS", "Esmeralda", "4307401"], + ["RS", "Esperan\u{e7}a do Sul", "4307450"], + ["RS", "Espumoso", "4307500"], + ["RS", "Esta\u{e7}\u{e3}o", "4307559"], + ["RS", "Est\u{e2}ncia Velha", "4307609"], + ["RS", "Esteio", "4307708"], + ["RS", "Estrela", "4307807"], + ["RS", "Estrela Velha", "4307815"], + ["RS", "Eug\u{ea}nio de Castro", "4307831"], + ["RS", "Fagundes Varela", "4307864"], + ["RS", "Farroupilha", "4307906"], + ["RS", "Faxinal do Soturno", "4308003"], + ["RS", "Faxinalzinho", "4308052"], + ["RS", "Fazenda Vilanova", "4308078"], + ["RS", "Feliz", "4308102"], + ["RS", "Flores da Cunha", "4308201"], + ["RS", "Floriano Peixoto", "4308250"], + ["RS", "Fontoura Xavier", "4308300"], + ["RS", "Formigueiro", "4308409"], + ["RS", "Forquetinha", "4308433"], + ["RS", "Fortaleza dos Valos", "4308458"], + ["RS", "Frederico Westphalen", "4308508"], + ["RS", "Garibaldi", "4308607"], + ["RS", "Garruchos", "4308656"], + ["RS", "Gaurama", "4308706"], + ["RS", "General C\u{e2}mara", "4308805"], + ["RS", "Gentil", "4308854"], + ["RS", "Get\u{fa}lio Vargas", "4308904"], + ["RS", "Giru\u{e1}", "4309001"], + ["RS", "Glorinha", "4309050"], + ["RS", "Gramado", "4309100"], + ["RS", "Gramado dos Loureiros", "4309126"], + ["RS", "Gramado Xavier", "4309159"], + ["RS", "Gravata\u{ed}", "4309209"], + ["RS", "Guabiju", "4309258"], + ["RS", "Gua\u{ed}ba", "4309308"], + ["RS", "Guapor\u{e9}", "4309407"], + ["RS", "Guarani das Miss\u{f5}es", "4309506"], + ["RS", "Harmonia", "4309555"], + ["RS", "Herval", "4307104"], + ["RS", "Herveiras", "4309571"], + ["RS", "Horizontina", "4309605"], + ["RS", "Hulha Negra", "4309654"], + ["RS", "Humait\u{e1}", "4309704"], + ["RS", "Ibarama", "4309753"], + ["RS", "Ibia\u{e7}\u{e1}", "4309803"], + ["RS", "Ibiraiaras", "4309902"], + ["RS", "Ibirapuit\u{e3}", "4309951"], + ["RS", "Ibirub\u{e1}", "4310009"], + ["RS", "Igrejinha", "4310108"], + ["RS", "Iju\u{ed}", "4310207"], + ["RS", "Il\u{f3}polis", "4310306"], + ["RS", "Imb\u{e9}", "4310330"], + ["RS", "Imigrante", "4310363"], + ["RS", "Independ\u{ea}ncia", "4310405"], + ["RS", "Inhacor\u{e1}", "4310413"], + ["RS", "Ip\u{ea}", "4310439"], + ["RS", "Ipiranga do Sul", "4310462"], + ["RS", "Ira\u{ed}", "4310504"], + ["RS", "Itaara", "4310538"], + ["RS", "Itacurubi", "4310553"], + ["RS", "Itapuca", "4310579"], + ["RS", "Itaqui", "4310603"], + ["RS", "Itati", "4310652"], + ["RS", "Itatiba do Sul", "4310702"], + ["RS", "Ivor\u{e1}", "4310751"], + ["RS", "Ivoti", "4310801"], + ["RS", "Jaboticaba", "4310850"], + ["RS", "Jacuizinho", "4310876"], + ["RS", "Jacutinga", "4310900"], + ["RS", "Jaguar\u{e3}o", "4311007"], + ["RS", "Jaguari", "4311106"], + ["RS", "Jaquirana", "4311122"], + ["RS", "Jari", "4311130"], + ["RS", "J\u{f3}ia", "4311155"], + ["RS", "J\u{fa}lio de Castilhos", "4311205"], + ["RS", "Lagoa Bonita do Sul", "4311239"], + ["RS", "Lagoa dos Tr\u{ea}s Cantos", "4311270"], + ["RS", "Lagoa Vermelha", "4311304"], + ["RS", "Lago\u{e3}o", "4311254"], + ["RS", "Lajeado", "4311403"], + ["RS", "Lajeado do Bugre", "4311429"], + ["RS", "Lavras do Sul", "4311502"], + ["RS", "Liberato Salzano", "4311601"], + ["RS", "Lindolfo Collor", "4311627"], + ["RS", "Linha Nova", "4311643"], + ["RS", "Ma\u{e7}ambar\u{e1}", "4311718"], + ["RS", "Machadinho", "4311700"], + ["RS", "Mampituba", "4311734"], + ["RS", "Manoel Viana", "4311759"], + ["RS", "Maquin\u{e9}", "4311775"], + ["RS", "Marat\u{e1}", "4311791"], + ["RS", "Marau", "4311809"], + ["RS", "Marcelino Ramos", "4311908"], + ["RS", "Mariana Pimentel", "4311981"], + ["RS", "Mariano Moro", "4312005"], + ["RS", "Marques de Souza", "4312054"], + ["RS", "Mata", "4312104"], + ["RS", "Mato Castelhano", "4312138"], + ["RS", "Mato Leit\u{e3}o", "4312153"], + ["RS", "Mato Queimado", "4312179"], + ["RS", "Maximiliano de Almeida", "4312203"], + ["RS", "Minas do Le\u{e3}o", "4312252"], + ["RS", "Miragua\u{ed}", "4312302"], + ["RS", "Montauri", "4312351"], + ["RS", "Monte Alegre dos Campos", "4312377"], + ["RS", "Monte Belo do Sul", "4312385"], + ["RS", "Montenegro", "4312401"], + ["RS", "Morma\u{e7}o", "4312427"], + ["RS", "Morrinhos do Sul", "4312443"], + ["RS", "Morro Redondo", "4312450"], + ["RS", "Morro Reuter", "4312476"], + ["RS", "Mostardas", "4312500"], + ["RS", "Mu\u{e7}um", "4312609"], + ["RS", "Muitos Cap\u{f5}es", "4312617"], + ["RS", "Muliterno", "4312625"], + ["RS", "N\u{e3}o-Me-Toque", "4312658"], + ["RS", "Nicolau Vergueiro", "4312674"], + ["RS", "Nonoai", "4312708"], + ["RS", "Nova Alvorada", "4312757"], + ["RS", "Nova Ara\u{e7}\u{e1}", "4312807"], + ["RS", "Nova Bassano", "4312906"], + ["RS", "Nova Boa Vista", "4312955"], + ["RS", "Nova Br\u{e9}scia", "4313003"], + ["RS", "Nova Candel\u{e1}ria", "4313011"], + ["RS", "Nova Esperan\u{e7}a do Sul", "4313037"], + ["RS", "Nova Hartz", "4313060"], + ["RS", "Nova P\u{e1}dua", "4313086"], + ["RS", "Nova Palma", "4313102"], + ["RS", "Nova Petr\u{f3}polis", "4313201"], + ["RS", "Nova Prata", "4313300"], + ["RS", "Nova Ramada", "4313334"], + ["RS", "Nova Roma do Sul", "4313359"], + ["RS", "Nova Santa Rita", "4313375"], + ["RS", "Novo Barreiro", "4313490"], + ["RS", "Novo Cabrais", "4313391"], + ["RS", "Novo Hamburgo", "4313409"], + ["RS", "Novo Machado", "4313425"], + ["RS", "Novo Tiradentes", "4313441"], + ["RS", "Novo Xingu", "4313466"], + ["RS", "Os\u{f3}rio", "4313508"], + ["RS", "Paim Filho", "4313607"], + ["RS", "Palmares do Sul", "4313656"], + ["RS", "Palmeira das Miss\u{f5}es", "4313706"], + ["RS", "Palmitinho", "4313805"], + ["RS", "Panambi", "4313904"], + ["RS", "Pantano Grande", "4313953"], + ["RS", "Para\u{ed}", "4314001"], + ["RS", "Para\u{ed}so do Sul", "4314027"], + ["RS", "Pareci Novo", "4314035"], + ["RS", "Parob\u{e9}", "4314050"], + ["RS", "Passa Sete", "4314068"], + ["RS", "Passo do Sobrado", "4314076"], + ["RS", "Passo Fundo", "4314100"], + ["RS", "Paulo Bento", "4314134"], + ["RS", "Paverama", "4314159"], + ["RS", "Pedras Altas", "4314175"], + ["RS", "Pedro Os\u{f3}rio", "4314209"], + ["RS", "Peju\u{e7}ara", "4314308"], + ["RS", "Pelotas", "4314407"], + ["RS", "Picada Caf\u{e9}", "4314423"], + ["RS", "Pinhal", "4314456"], + ["RS", "Pinhal da Serra", "4314464"], + ["RS", "Pinhal Grande", "4314472"], + ["RS", "Pinheirinho do Vale", "4314498"], + ["RS", "Pinheiro Machado", "4314506"], + ["RS", "Pinto Bandeira", "4314548"], + ["RS", "Pirap\u{f3}", "4314555"], + ["RS", "Piratini", "4314605"], + ["RS", "Planalto", "4314704"], + ["RS", "Po\u{e7}o das Antas", "4314753"], + ["RS", "Pont\u{e3}o", "4314779"], + ["RS", "Ponte Preta", "4314787"], + ["RS", "Port\u{e3}o", "4314803"], + ["RS", "Porto Alegre", "4314902"], + ["RS", "Porto Lucena", "4315008"], + ["RS", "Porto Mau\u{e1}", "4315057"], + ["RS", "Porto Vera Cruz", "4315073"], + ["RS", "Porto Xavier", "4315107"], + ["RS", "Pouso Novo", "4315131"], + ["RS", "Presidente Lucena", "4315149"], + ["RS", "Progresso", "4315156"], + ["RS", "Prot\u{e1}sio Alves", "4315172"], + ["RS", "Putinga", "4315206"], + ["RS", "Quara\u{ed}", "4315305"], + ["RS", "Quatro Irm\u{e3}os", "4315313"], + ["RS", "Quevedos", "4315321"], + ["RS", "Quinze de Novembro", "4315354"], + ["RS", "Redentora", "4315404"], + ["RS", "Relvado", "4315453"], + ["RS", "Restinga S\u{ea}ca", "4315503"], + ["RS", "Rio dos \u{cd}ndios", "4315552"], + ["RS", "Rio Grande", "4315602"], + ["RS", "Rio Pardo", "4315701"], + ["RS", "Riozinho", "4315750"], + ["RS", "Roca Sales", "4315800"], + ["RS", "Rodeio Bonito", "4315909"], + ["RS", "Rolador", "4315958"], + ["RS", "Rolante", "4316006"], + ["RS", "Ronda Alta", "4316105"], + ["RS", "Rondinha", "4316204"], + ["RS", "Roque Gonzales", "4316303"], + ["RS", "Ros\u{e1}rio do Sul", "4316402"], + ["RS", "Sagrada Fam\u{ed}lia", "4316428"], + ["RS", "Saldanha Marinho", "4316436"], + ["RS", "Salto do Jacu\u{ed}", "4316451"], + ["RS", "Salvador das Miss\u{f5}es", "4316477"], + ["RS", "Salvador do Sul", "4316501"], + ["RS", "Sananduva", "4316600"], + ["RS", "Sant'Ana do Livramento", "4317103"], + ["RS", "Santa B\u{e1}rbara do Sul", "4316709"], + ["RS", "Santa Cec\u{ed}lia do Sul", "4316733"], + ["RS", "Santa Clara do Sul", "4316758"], + ["RS", "Santa Cruz do Sul", "4316808"], + ["RS", "Santa Margarida do Sul", "4316972"], + ["RS", "Santa Maria", "4316907"], + ["RS", "Santa Maria do Herval", "4316956"], + ["RS", "Santa Rosa", "4317202"], + ["RS", "Santa Tereza", "4317251"], + ["RS", "Santa Vit\u{f3}ria do Palmar", "4317301"], + ["RS", "Santana da Boa Vista", "4317004"], + ["RS", "Santiago", "4317400"], + ["RS", "Santo \u{c2}ngelo", "4317509"], + ["RS", "Santo Ant\u{f4}nio da Patrulha", "4317608"], + ["RS", "Santo Ant\u{f4}nio das Miss\u{f5}es", "4317707"], + ["RS", "Santo Ant\u{f4}nio do Palma", "4317558"], + ["RS", "Santo Ant\u{f4}nio do Planalto", "4317756"], + ["RS", "Santo Augusto", "4317806"], + ["RS", "Santo Cristo", "4317905"], + ["RS", "Santo Expedito do Sul", "4317954"], + ["RS", "S\u{e3}o Borja", "4318002"], + ["RS", "S\u{e3}o Domingos do Sul", "4318051"], + ["RS", "S\u{e3}o Francisco de Assis", "4318101"], + ["RS", "S\u{e3}o Francisco de Paula", "4318200"], + ["RS", "S\u{e3}o Gabriel", "4318309"], + ["RS", "S\u{e3}o Jer\u{f4}nimo", "4318408"], + ["RS", "S\u{e3}o Jo\u{e3}o da Urtiga", "4318424"], + ["RS", "S\u{e3}o Jo\u{e3}o do Pol\u{ea}sine", "4318432"], + ["RS", "S\u{e3}o Jorge", "4318440"], + ["RS", "S\u{e3}o Jos\u{e9} das Miss\u{f5}es", "4318457"], + ["RS", "S\u{e3}o Jos\u{e9} do Herval", "4318465"], + ["RS", "S\u{e3}o Jos\u{e9} do Hort\u{ea}ncio", "4318481"], + ["RS", "S\u{e3}o Jos\u{e9} do Inhacor\u{e1}", "4318499"], + ["RS", "S\u{e3}o Jos\u{e9} do Norte", "4318507"], + ["RS", "S\u{e3}o Jos\u{e9} do Ouro", "4318606"], + ["RS", "S\u{e3}o Jos\u{e9} do Sul", "4318614"], + ["RS", "S\u{e3}o Jos\u{e9} dos Ausentes", "4318622"], + ["RS", "S\u{e3}o Leopoldo", "4318705"], + ["RS", "S\u{e3}o Louren\u{e7}o do Sul", "4318804"], + ["RS", "S\u{e3}o Luiz Gonzaga", "4318903"], + ["RS", "S\u{e3}o Marcos", "4319000"], + ["RS", "S\u{e3}o Martinho", "4319109"], + ["RS", "S\u{e3}o Martinho da Serra", "4319125"], + ["RS", "S\u{e3}o Miguel das Miss\u{f5}es", "4319158"], + ["RS", "S\u{e3}o Nicolau", "4319208"], + ["RS", "S\u{e3}o Paulo das Miss\u{f5}es", "4319307"], + ["RS", "S\u{e3}o Pedro da Serra", "4319356"], + ["RS", "S\u{e3}o Pedro das Miss\u{f5}es", "4319364"], + ["RS", "S\u{e3}o Pedro do Buti\u{e1}", "4319372"], + ["RS", "S\u{e3}o Pedro do Sul", "4319406"], + ["RS", "S\u{e3}o Sebasti\u{e3}o do Ca\u{ed}", "4319505"], + ["RS", "S\u{e3}o Sep\u{e9}", "4319604"], + ["RS", "S\u{e3}o Valentim", "4319703"], + ["RS", "S\u{e3}o Valentim do Sul", "4319711"], + ["RS", "S\u{e3}o Val\u{e9}rio do Sul", "4319737"], + ["RS", "S\u{e3}o Vendelino", "4319752"], + ["RS", "S\u{e3}o Vicente do Sul", "4319802"], + ["RS", "Sapiranga", "4319901"], + ["RS", "Sapucaia do Sul", "4320008"], + ["RS", "Sarandi", "4320107"], + ["RS", "Seberi", "4320206"], + ["RS", "Sede Nova", "4320230"], + ["RS", "Segredo", "4320263"], + ["RS", "Selbach", "4320305"], + ["RS", "Senador Salgado Filho", "4320321"], + ["RS", "Sentinela do Sul", "4320354"], + ["RS", "Serafina Corr\u{ea}a", "4320404"], + ["RS", "S\u{e9}rio", "4320453"], + ["RS", "Sert\u{e3}o", "4320503"], + ["RS", "Sert\u{e3}o Santana", "4320552"], + ["RS", "Sete de Setembro", "4320578"], + ["RS", "Severiano de Almeida", "4320602"], + ["RS", "Silveira Martins", "4320651"], + ["RS", "Sinimbu", "4320677"], + ["RS", "Sobradinho", "4320701"], + ["RS", "Soledade", "4320800"], + ["RS", "Taba\u{ed}", "4320859"], + ["RS", "Tapejara", "4320909"], + ["RS", "Tapera", "4321006"], + ["RS", "Tapes", "4321105"], + ["RS", "Taquara", "4321204"], + ["RS", "Taquari", "4321303"], + ["RS", "Taquaru\u{e7}u do Sul", "4321329"], + ["RS", "Tavares", "4321352"], + ["RS", "Tenente Portela", "4321402"], + ["RS", "Terra de Areia", "4321436"], + ["RS", "Teut\u{f4}nia", "4321451"], + ["RS", "Tio Hugo", "4321469"], + ["RS", "Tiradentes do Sul", "4321477"], + ["RS", "Toropi", "4321493"], + ["RS", "Torres", "4321501"], + ["RS", "Tramanda\u{ed}", "4321600"], + ["RS", "Travesseiro", "4321626"], + ["RS", "Tr\u{ea}s Arroios", "4321634"], + ["RS", "Tr\u{ea}s Cachoeiras", "4321667"], + ["RS", "Tr\u{ea}s Coroas", "4321709"], + ["RS", "Tr\u{ea}s de Maio", "4321808"], + ["RS", "Tr\u{ea}s Forquilhas", "4321832"], + ["RS", "Tr\u{ea}s Palmeiras", "4321857"], + ["RS", "Tr\u{ea}s Passos", "4321907"], + ["RS", "Trindade do Sul", "4321956"], + ["RS", "Triunfo", "4322004"], + ["RS", "Tucunduva", "4322103"], + ["RS", "Tunas", "4322152"], + ["RS", "Tupanci do Sul", "4322186"], + ["RS", "Tupanciret\u{e3}", "4322202"], + ["RS", "Tupandi", "4322251"], + ["RS", "Tuparendi", "4322301"], + ["RS", "Turu\u{e7}u", "4322327"], + ["RS", "Ubiretama", "4322343"], + ["RS", "Uni\u{e3}o da Serra", "4322350"], + ["RS", "Unistalda", "4322376"], + ["RS", "Uruguaiana", "4322400"], + ["RS", "Vacaria", "4322509"], + ["RS", "Vale do Sol", "4322533"], + ["RS", "Vale Real", "4322541"], + ["RS", "Vale Verde", "4322525"], + ["RS", "Vanini", "4322558"], + ["RS", "Ven\u{e2}ncio Aires", "4322608"], + ["RS", "Vera Cruz", "4322707"], + ["RS", "Veran\u{f3}polis", "4322806"], + ["RS", "Vespasiano Corr\u{ea}a", "4322855"], + ["RS", "Viadutos", "4322905"], + ["RS", "Viam\u{e3}o", "4323002"], + ["RS", "Vicente Dutra", "4323101"], + ["RS", "Victor Graeff", "4323200"], + ["RS", "Vila Flores", "4323309"], + ["RS", "Vila L\u{e2}ngaro", "4323358"], + ["RS", "Vila Maria", "4323408"], + ["RS", "Vila Nova do Sul", "4323457"], + ["RS", "Vista Alegre", "4323507"], + ["RS", "Vista Alegre do Prata", "4323606"], + ["RS", "Vista Ga\u{fa}cha", "4323705"], + ["RS", "Vit\u{f3}ria das Miss\u{f5}es", "4323754"], + ["RS", "Westf\u{e1}lia", "4323770"], + ["RS", "Xangri-l\u{e1}", "4323804"], + ["RO", "Alta Floresta D'Oeste", "1100015"], + ["RO", "Alto Alegre dos Parecis", "1100379"], + ["RO", "Alto Para\u{ed}so", "1100403"], + ["RO", "Alvorada D'Oeste", "1100346"], + ["RO", "Ariquemes", "1100023"], + ["RO", "Buritis", "1100452"], + ["RO", "Cabixi", "1100031"], + ["RO", "Cacaul\u{e2}ndia", "1100601"], + ["RO", "Cacoal", "1100049"], + ["RO", "Campo Novo de Rond\u{f4}nia", "1100700"], + ["RO", "Candeias do Jamari", "1100809"], + ["RO", "Castanheiras", "1100908"], + ["RO", "Cerejeiras", "1100056"], + ["RO", "Chupinguaia", "1100924"], + ["RO", "Colorado do Oeste", "1100064"], + ["RO", "Corumbiara", "1100072"], + ["RO", "Costa Marques", "1100080"], + ["RO", "Cujubim", "1100940"], + ["RO", "Espig\u{e3}o D'Oeste", "1100098"], + ["RO", "Governador Jorge Teixeira", "1101005"], + ["RO", "Guajar\u{e1}-Mirim", "1100106"], + ["RO", "Itapu\u{e3} do Oeste", "1101104"], + ["RO", "Jaru", "1100114"], + ["RO", "Ji-Paran\u{e1}", "1100122"], + ["RO", "Machadinho D'Oeste", "1100130"], + ["RO", "Ministro Andreazza", "1101203"], + ["RO", "Mirante da Serra", "1101302"], + ["RO", "Monte Negro", "1101401"], + ["RO", "Nova Brasil\u{e2}ndia D'Oeste", "1100148"], + ["RO", "Nova Mamor\u{e9}", "1100338"], + ["RO", "Nova Uni\u{e3}o", "1101435"], + ["RO", "Novo Horizonte do Oeste", "1100502"], + ["RO", "Ouro Preto do Oeste", "1100155"], + ["RO", "Parecis", "1101450"], + ["RO", "Pimenta Bueno", "1100189"], + ["RO", "Pimenteiras do Oeste", "1101468"], + ["RO", "Porto Velho", "1100205"], + ["RO", "Presidente M\u{e9}dici", "1100254"], + ["RO", "Primavera de Rond\u{f4}nia", "1101476"], + ["RO", "Rio Crespo", "1100262"], + ["RO", "Rolim de Moura", "1100288"], + ["RO", "Santa Luzia D'Oeste", "1100296"], + ["RO", "S\u{e3}o Felipe D'Oeste", "1101484"], + ["RO", "S\u{e3}o Francisco do Guapor\u{e9}", "1101492"], + ["RO", "S\u{e3}o Miguel do Guapor\u{e9}", "1100320"], + ["RO", "Seringueiras", "1101500"], + ["RO", "Teixeir\u{f3}polis", "1101559"], + ["RO", "Theobroma", "1101609"], + ["RO", "Urup\u{e1}", "1101708"], + ["RO", "Vale do Anari", "1101757"], + ["RO", "Vale do Para\u{ed}so", "1101807"], + ["RO", "Vilhena", "1100304"], + ["RR", "Alto Alegre", "1400050"], + ["RR", "Amajari", "1400027"], + ["RR", "Boa Vista", "1400100"], + ["RR", "Bonfim", "1400159"], + ["RR", "Cant\u{e1}", "1400175"], + ["RR", "Caracara\u{ed}", "1400209"], + ["RR", "Caroebe", "1400233"], + ["RR", "Iracema", "1400282"], + ["RR", "Mucaja\u{ed}", "1400308"], + ["RR", "Normandia", "1400407"], + ["RR", "Pacaraima", "1400456"], + ["RR", "Rorain\u{f3}polis", "1400472"], + ["RR", "S\u{e3}o Jo\u{e3}o da Baliza", "1400506"], + ["RR", "S\u{e3}o Luiz do Anau\u{e1}", "1400605"], + ["RR", "Uiramut\u{e3}", "1400704"], + ["SC", "Abdon Batista", "4200051"], + ["SC", "Abelardo Luz", "4200101"], + ["SC", "Agrol\u{e2}ndia", "4200200"], + ["SC", "Agron\u{f4}mica", "4200309"], + ["SC", "\u{c1}gua Doce", "4200408"], + ["SC", "\u{c1}guas de Chapec\u{f3}", "4200507"], + ["SC", "\u{c1}guas Frias", "4200556"], + ["SC", "\u{c1}guas Mornas", "4200606"], + ["SC", "Alfredo Wagner", "4200705"], + ["SC", "Alto Bela Vista", "4200754"], + ["SC", "Anchieta", "4200804"], + ["SC", "Angelina", "4200903"], + ["SC", "Anita Garibaldi", "4201000"], + ["SC", "Anit\u{e1}polis", "4201109"], + ["SC", "Ant\u{f4}nio Carlos", "4201208"], + ["SC", "Api\u{fa}na", "4201257"], + ["SC", "Arabut\u{e3}", "4201273"], + ["SC", "Araquari", "4201307"], + ["SC", "Ararangu\u{e1}", "4201406"], + ["SC", "Armaz\u{e9}m", "4201505"], + ["SC", "Arroio Trinta", "4201604"], + ["SC", "Arvoredo", "4201653"], + ["SC", "Ascurra", "4201703"], + ["SC", "Atalanta", "4201802"], + ["SC", "Aurora", "4201901"], + ["SC", "Balne\u{e1}rio Arroio do Silva", "4201950"], + ["SC", "Balne\u{e1}rio Barra do Sul", "4202057"], + ["SC", "Balne\u{e1}rio Cambori\u{fa}", "4202008"], + ["SC", "Balne\u{e1}rio Gaivota", "4202073"], + ["SC", "Balne\u{e1}rio Pi\u{e7}arras", "4212809"], + ["SC", "Balne\u{e1}rio Rinc\u{e3}o", "4220000"], + ["SC", "Bandeirante", "4202081"], + ["SC", "Barra Bonita", "4202099"], + ["SC", "Barra Velha", "4202107"], + ["SC", "Bela Vista do Toldo", "4202131"], + ["SC", "Belmonte", "4202156"], + ["SC", "Benedito Novo", "4202206"], + ["SC", "Bigua\u{e7}u", "4202305"], + ["SC", "Blumenau", "4202404"], + ["SC", "Bocaina do Sul", "4202438"], + ["SC", "Bom Jardim da Serra", "4202503"], + ["SC", "Bom Jesus", "4202537"], + ["SC", "Bom Jesus do Oeste", "4202578"], + ["SC", "Bom Retiro", "4202602"], + ["SC", "Bombinhas", "4202453"], + ["SC", "Botuver\u{e1}", "4202701"], + ["SC", "Bra\u{e7}o do Norte", "4202800"], + ["SC", "Bra\u{e7}o do Trombudo", "4202859"], + ["SC", "Brun\u{f3}polis", "4202875"], + ["SC", "Brusque", "4202909"], + ["SC", "Ca\u{e7}ador", "4203006"], + ["SC", "Caibi", "4203105"], + ["SC", "Calmon", "4203154"], + ["SC", "Cambori\u{fa}", "4203204"], + ["SC", "Campo Alegre", "4203303"], + ["SC", "Campo Belo do Sul", "4203402"], + ["SC", "Campo Er\u{ea}", "4203501"], + ["SC", "Campos Novos", "4203600"], + ["SC", "Canelinha", "4203709"], + ["SC", "Canoinhas", "4203808"], + ["SC", "Cap\u{e3}o Alto", "4203253"], + ["SC", "Capinzal", "4203907"], + ["SC", "Capivari de Baixo", "4203956"], + ["SC", "Catanduvas", "4204004"], + ["SC", "Caxambu do Sul", "4204103"], + ["SC", "Celso Ramos", "4204152"], + ["SC", "Cerro Negro", "4204178"], + ["SC", "Chapad\u{e3}o do Lageado", "4204194"], + ["SC", "Chapec\u{f3}", "4204202"], + ["SC", "Cocal do Sul", "4204251"], + ["SC", "Conc\u{f3}rdia", "4204301"], + ["SC", "Cordilheira Alta", "4204350"], + ["SC", "Coronel Freitas", "4204400"], + ["SC", "Coronel Martins", "4204459"], + ["SC", "Correia Pinto", "4204558"], + ["SC", "Corup\u{e1}", "4204509"], + ["SC", "Crici\u{fa}ma", "4204608"], + ["SC", "Cunha Por\u{e3}", "4204707"], + ["SC", "Cunhata\u{ed}", "4204756"], + ["SC", "Curitibanos", "4204806"], + ["SC", "Descanso", "4204905"], + ["SC", "Dion\u{ed}sio Cerqueira", "4205001"], + ["SC", "Dona Emma", "4205100"], + ["SC", "Doutor Pedrinho", "4205159"], + ["SC", "Entre Rios", "4205175"], + ["SC", "Ermo", "4205191"], + ["SC", "Erval Velho", "4205209"], + ["SC", "Faxinal dos Guedes", "4205308"], + ["SC", "Flor do Sert\u{e3}o", "4205357"], + ["SC", "Florian\u{f3}polis", "4205407"], + ["SC", "Formosa do Sul", "4205431"], + ["SC", "Forquilhinha", "4205456"], + ["SC", "Fraiburgo", "4205506"], + ["SC", "Frei Rog\u{e9}rio", "4205555"], + ["SC", "Galv\u{e3}o", "4205605"], + ["SC", "Garopaba", "4205704"], + ["SC", "Garuva", "4205803"], + ["SC", "Gaspar", "4205902"], + ["SC", "Governador Celso Ramos", "4206009"], + ["SC", "Gr\u{e3}o-Par\u{e1}", "4206108"], + ["SC", "Gravatal", "4206207"], + ["SC", "Guabiruba", "4206306"], + ["SC", "Guaraciaba", "4206405"], + ["SC", "Guaramirim", "4206504"], + ["SC", "Guaruj\u{e1} do Sul", "4206603"], + ["SC", "Guatamb\u{fa}", "4206652"], + ["SC", "Herval d'Oeste", "4206702"], + ["SC", "Ibiam", "4206751"], + ["SC", "Ibicar\u{e9}", "4206801"], + ["SC", "Ibirama", "4206900"], + ["SC", "I\u{e7}ara", "4207007"], + ["SC", "Ilhota", "4207106"], + ["SC", "Imaru\u{ed}", "4207205"], + ["SC", "Imbituba", "4207304"], + ["SC", "Imbuia", "4207403"], + ["SC", "Indaial", "4207502"], + ["SC", "Iomer\u{ea}", "4207577"], + ["SC", "Ipira", "4207601"], + ["SC", "Ipor\u{e3} do Oeste", "4207650"], + ["SC", "Ipua\u{e7}u", "4207684"], + ["SC", "Ipumirim", "4207700"], + ["SC", "Iraceminha", "4207759"], + ["SC", "Irani", "4207809"], + ["SC", "Irati", "4207858"], + ["SC", "Irine\u{f3}polis", "4207908"], + ["SC", "It\u{e1}", "4208005"], + ["SC", "Itai\u{f3}polis", "4208104"], + ["SC", "Itaja\u{ed}", "4208203"], + ["SC", "Itapema", "4208302"], + ["SC", "Itapiranga", "4208401"], + ["SC", "Itapo\u{e1}", "4208450"], + ["SC", "Ituporanga", "4208500"], + ["SC", "Jabor\u{e1}", "4208609"], + ["SC", "Jacinto Machado", "4208708"], + ["SC", "Jaguaruna", "4208807"], + ["SC", "Jaragu\u{e1} do Sul", "4208906"], + ["SC", "Jardin\u{f3}polis", "4208955"], + ["SC", "Joa\u{e7}aba", "4209003"], + ["SC", "Joinville", "4209102"], + ["SC", "Jos\u{e9} Boiteux", "4209151"], + ["SC", "Jupi\u{e1}", "4209177"], + ["SC", "Lacerd\u{f3}polis", "4209201"], + ["SC", "Lages", "4209300"], + ["SC", "Laguna", "4209409"], + ["SC", "Lajeado Grande", "4209458"], + ["SC", "Laurentino", "4209508"], + ["SC", "Lauro M\u{fc}ller", "4209607"], + ["SC", "Lebon R\u{e9}gis", "4209706"], + ["SC", "Leoberto Leal", "4209805"], + ["SC", "Lind\u{f3}ia do Sul", "4209854"], + ["SC", "Lontras", "4209904"], + ["SC", "Luiz Alves", "4210001"], + ["SC", "Luzerna", "4210035"], + ["SC", "Macieira", "4210050"], + ["SC", "Mafra", "4210100"], + ["SC", "Major Gercino", "4210209"], + ["SC", "Major Vieira", "4210308"], + ["SC", "Maracaj\u{e1}", "4210407"], + ["SC", "Maravilha", "4210506"], + ["SC", "Marema", "4210555"], + ["SC", "Massaranduba", "4210605"], + ["SC", "Matos Costa", "4210704"], + ["SC", "Meleiro", "4210803"], + ["SC", "Mirim Doce", "4210852"], + ["SC", "Modelo", "4210902"], + ["SC", "Monda\u{ed}", "4211009"], + ["SC", "Monte Carlo", "4211058"], + ["SC", "Monte Castelo", "4211108"], + ["SC", "Morro da Fuma\u{e7}a", "4211207"], + ["SC", "Morro Grande", "4211256"], + ["SC", "Navegantes", "4211306"], + ["SC", "Nova Erechim", "4211405"], + ["SC", "Nova Itaberaba", "4211454"], + ["SC", "Nova Trento", "4211504"], + ["SC", "Nova Veneza", "4211603"], + ["SC", "Novo Horizonte", "4211652"], + ["SC", "Orleans", "4211702"], + ["SC", "Otac\u{ed}lio Costa", "4211751"], + ["SC", "Ouro", "4211801"], + ["SC", "Ouro Verde", "4211850"], + ["SC", "Paial", "4211876"], + ["SC", "Painel", "4211892"], + ["SC", "Palho\u{e7}a", "4211900"], + ["SC", "Palma Sola", "4212007"], + ["SC", "Palmeira", "4212056"], + ["SC", "Palmitos", "4212106"], + ["SC", "Papanduva", "4212205"], + ["SC", "Para\u{ed}so", "4212239"], + ["SC", "Passo de Torres", "4212254"], + ["SC", "Passos Maia", "4212270"], + ["SC", "Paulo Lopes", "4212304"], + ["SC", "Pedras Grandes", "4212403"], + ["SC", "Penha", "4212502"], + ["SC", "Peritiba", "4212601"], + ["SC", "Pescaria Brava", "4212650"], + ["SC", "Petrol\u{e2}ndia", "4212700"], + ["SC", "Pinhalzinho", "4212908"], + ["SC", "Pinheiro Preto", "4213005"], + ["SC", "Piratuba", "4213104"], + ["SC", "Planalto Alegre", "4213153"], + ["SC", "Pomerode", "4213203"], + ["SC", "Ponte Alta", "4213302"], + ["SC", "Ponte Alta do Norte", "4213351"], + ["SC", "Ponte Serrada", "4213401"], + ["SC", "Porto Belo", "4213500"], + ["SC", "Porto Uni\u{e3}o", "4213609"], + ["SC", "Pouso Redondo", "4213708"], + ["SC", "Praia Grande", "4213807"], + ["SC", "Presidente Castello Branco", "4213906"], + ["SC", "Presidente Get\u{fa}lio", "4214003"], + ["SC", "Presidente Nereu", "4214102"], + ["SC", "Princesa", "4214151"], + ["SC", "Quilombo", "4214201"], + ["SC", "Rancho Queimado", "4214300"], + ["SC", "Rio das Antas", "4214409"], + ["SC", "Rio do Campo", "4214508"], + ["SC", "Rio do Oeste", "4214607"], + ["SC", "Rio do Sul", "4214805"], + ["SC", "Rio dos Cedros", "4214706"], + ["SC", "Rio Fortuna", "4214904"], + ["SC", "Rio Negrinho", "4215000"], + ["SC", "Rio Rufino", "4215059"], + ["SC", "Riqueza", "4215075"], + ["SC", "Rodeio", "4215109"], + ["SC", "Romel\u{e2}ndia", "4215208"], + ["SC", "Salete", "4215307"], + ["SC", "Saltinho", "4215356"], + ["SC", "Salto Veloso", "4215406"], + ["SC", "Sang\u{e3}o", "4215455"], + ["SC", "Santa Cec\u{ed}lia", "4215505"], + ["SC", "Santa Helena", "4215554"], + ["SC", "Santa Rosa de Lima", "4215604"], + ["SC", "Santa Rosa do Sul", "4215653"], + ["SC", "Santa Terezinha", "4215679"], + ["SC", "Santa Terezinha do Progresso", "4215687"], + ["SC", "Santiago do Sul", "4215695"], + ["SC", "Santo Amaro da Imperatriz", "4215703"], + ["SC", "S\u{e3}o Bento do Sul", "4215802"], + ["SC", "S\u{e3}o Bernardino", "4215752"], + ["SC", "S\u{e3}o Bonif\u{e1}cio", "4215901"], + ["SC", "S\u{e3}o Carlos", "4216008"], + ["SC", "S\u{e3}o Crist\u{f3}v\u{e3}o do Sul", "4216057"], + ["SC", "S\u{e3}o Domingos", "4216107"], + ["SC", "S\u{e3}o Francisco do Sul", "4216206"], + ["SC", "S\u{e3}o Jo\u{e3}o Batista", "4216305"], + ["SC", "S\u{e3}o Jo\u{e3}o do Itaperi\u{fa}", "4216354"], + ["SC", "S\u{e3}o Jo\u{e3}o do Oeste", "4216255"], + ["SC", "S\u{e3}o Jo\u{e3}o do Sul", "4216404"], + ["SC", "S\u{e3}o Joaquim", "4216503"], + ["SC", "S\u{e3}o Jos\u{e9}", "4216602"], + ["SC", "S\u{e3}o Jos\u{e9} do Cedro", "4216701"], + ["SC", "S\u{e3}o Jos\u{e9} do Cerrito", "4216800"], + ["SC", "S\u{e3}o Louren\u{e7}o do Oeste", "4216909"], + ["SC", "S\u{e3}o Ludgero", "4217006"], + ["SC", "S\u{e3}o Martinho", "4217105"], + ["SC", "S\u{e3}o Miguel da Boa Vista", "4217154"], + ["SC", "S\u{e3}o Miguel do Oeste", "4217204"], + ["SC", "S\u{e3}o Pedro de Alc\u{e2}ntara", "4217253"], + ["SC", "Saudades", "4217303"], + ["SC", "Schroeder", "4217402"], + ["SC", "Seara", "4217501"], + ["SC", "Serra Alta", "4217550"], + ["SC", "Sider\u{f3}polis", "4217600"], + ["SC", "Sombrio", "4217709"], + ["SC", "Sul Brasil", "4217758"], + ["SC", "Tai\u{f3}", "4217808"], + ["SC", "Tangar\u{e1}", "4217907"], + ["SC", "Tigrinhos", "4217956"], + ["SC", "Tijucas", "4218004"], + ["SC", "Timb\u{e9} do Sul", "4218103"], + ["SC", "Timb\u{f3}", "4218202"], + ["SC", "Timb\u{f3} Grande", "4218251"], + ["SC", "Tr\u{ea}s Barras", "4218301"], + ["SC", "Treviso", "4218350"], + ["SC", "Treze de Maio", "4218400"], + ["SC", "Treze T\u{ed}lias", "4218509"], + ["SC", "Trombudo Central", "4218608"], + ["SC", "Tubar\u{e3}o", "4218707"], + ["SC", "Tun\u{e1}polis", "4218756"], + ["SC", "Turvo", "4218806"], + ["SC", "Uni\u{e3}o do Oeste", "4218855"], + ["SC", "Urubici", "4218905"], + ["SC", "Urupema", "4218954"], + ["SC", "Urussanga", "4219002"], + ["SC", "Varge\u{e3}o", "4219101"], + ["SC", "Vargem", "4219150"], + ["SC", "Vargem Bonita", "4219176"], + ["SC", "Vidal Ramos", "4219200"], + ["SC", "Videira", "4219309"], + ["SC", "Vitor Meireles", "4219358"], + ["SC", "Witmarsum", "4219408"], + ["SC", "Xanxer\u{ea}", "4219507"], + ["SC", "Xavantina", "4219606"], + ["SC", "Xaxim", "4219705"], + ["SC", "Zort\u{e9}a", "4219853"], + ["SP", "Adamantina", "3500105"], + ["SP", "Adolfo", "3500204"], + ["SP", "Agua\u{ed}", "3500303"], + ["SP", "\u{c1}guas da Prata", "3500402"], + ["SP", "\u{c1}guas de Lind\u{f3}ia", "3500501"], + ["SP", "\u{c1}guas de Santa B\u{e1}rbara", "3500550"], + ["SP", "\u{c1}guas de S\u{e3}o Pedro", "3500600"], + ["SP", "Agudos", "3500709"], + ["SP", "Alambari", "3500758"], + ["SP", "Alfredo Marcondes", "3500808"], + ["SP", "Altair", "3500907"], + ["SP", "Altin\u{f3}polis", "3501004"], + ["SP", "Alto Alegre", "3501103"], + ["SP", "Alum\u{ed}nio", "3501152"], + ["SP", "\u{c1}lvares Florence", "3501202"], + ["SP", "\u{c1}lvares Machado", "3501301"], + ["SP", "\u{c1}lvaro de Carvalho", "3501400"], + ["SP", "Alvinl\u{e2}ndia", "3501509"], + ["SP", "Americana", "3501608"], + ["SP", "Am\u{e9}rico Brasiliense", "3501707"], + ["SP", "Am\u{e9}rico de Campos", "3501806"], + ["SP", "Amparo", "3501905"], + ["SP", "Anal\u{e2}ndia", "3502002"], + ["SP", "Andradina", "3502101"], + ["SP", "Angatuba", "3502200"], + ["SP", "Anhembi", "3502309"], + ["SP", "Anhumas", "3502408"], + ["SP", "Aparecida", "3502507"], + ["SP", "Aparecida d'Oeste", "3502606"], + ["SP", "Apia\u{ed}", "3502705"], + ["SP", "Ara\u{e7}ariguama", "3502754"], + ["SP", "Ara\u{e7}atuba", "3502804"], + ["SP", "Ara\u{e7}oiaba da Serra", "3502903"], + ["SP", "Aramina", "3503000"], + ["SP", "Arandu", "3503109"], + ["SP", "Arape\u{ed}", "3503158"], + ["SP", "Araraquara", "3503208"], + ["SP", "Araras", "3503307"], + ["SP", "Arco-\u{cd}ris", "3503356"], + ["SP", "Arealva", "3503406"], + ["SP", "Areias", "3503505"], + ["SP", "Arei\u{f3}polis", "3503604"], + ["SP", "Ariranha", "3503703"], + ["SP", "Artur Nogueira", "3503802"], + ["SP", "Aruj\u{e1}", "3503901"], + ["SP", "Asp\u{e1}sia", "3503950"], + ["SP", "Assis", "3504008"], + ["SP", "Atibaia", "3504107"], + ["SP", "Auriflama", "3504206"], + ["SP", "Ava\u{ed}", "3504305"], + ["SP", "Avanhandava", "3504404"], + ["SP", "Avar\u{e9}", "3504503"], + ["SP", "Bady Bassitt", "3504602"], + ["SP", "Balbinos", "3504701"], + ["SP", "B\u{e1}lsamo", "3504800"], + ["SP", "Bananal", "3504909"], + ["SP", "Bar\u{e3}o de Antonina", "3505005"], + ["SP", "Barbosa", "3505104"], + ["SP", "Bariri", "3505203"], + ["SP", "Barra Bonita", "3505302"], + ["SP", "Barra do Chap\u{e9}u", "3505351"], + ["SP", "Barra do Turvo", "3505401"], + ["SP", "Barretos", "3505500"], + ["SP", "Barrinha", "3505609"], + ["SP", "Barueri", "3505708"], + ["SP", "Bastos", "3505807"], + ["SP", "Batatais", "3505906"], + ["SP", "Bauru", "3506003"], + ["SP", "Bebedouro", "3506102"], + ["SP", "Bento de Abreu", "3506201"], + ["SP", "Bernardino de Campos", "3506300"], + ["SP", "Bertioga", "3506359"], + ["SP", "Bilac", "3506409"], + ["SP", "Birigui", "3506508"], + ["SP", "Biritiba Mirim", "3506607"], + ["SP", "Boa Esperan\u{e7}a do Sul", "3506706"], + ["SP", "Bocaina", "3506805"], + ["SP", "Bofete", "3506904"], + ["SP", "Boituva", "3507001"], + ["SP", "Bom Jesus dos Perd\u{f5}es", "3507100"], + ["SP", "Bom Sucesso de Itarar\u{e9}", "3507159"], + ["SP", "Bor\u{e1}", "3507209"], + ["SP", "Borac\u{e9}ia", "3507308"], + ["SP", "Borborema", "3507407"], + ["SP", "Borebi", "3507456"], + ["SP", "Botucatu", "3507506"], + ["SP", "Bragan\u{e7}a Paulista", "3507605"], + ["SP", "Bra\u{fa}na", "3507704"], + ["SP", "Brejo Alegre", "3507753"], + ["SP", "Brodowski", "3507803"], + ["SP", "Brotas", "3507902"], + ["SP", "Buri", "3508009"], + ["SP", "Buritama", "3508108"], + ["SP", "Buritizal", "3508207"], + ["SP", "Cabr\u{e1}lia Paulista", "3508306"], + ["SP", "Cabre\u{fa}va", "3508405"], + ["SP", "Ca\u{e7}apava", "3508504"], + ["SP", "Cachoeira Paulista", "3508603"], + ["SP", "Caconde", "3508702"], + ["SP", "Cafel\u{e2}ndia", "3508801"], + ["SP", "Caiabu", "3508900"], + ["SP", "Caieiras", "3509007"], + ["SP", "Caiu\u{e1}", "3509106"], + ["SP", "Cajamar", "3509205"], + ["SP", "Cajati", "3509254"], + ["SP", "Cajobi", "3509304"], + ["SP", "Cajuru", "3509403"], + ["SP", "Campina do Monte Alegre", "3509452"], + ["SP", "Campinas", "3509502"], + ["SP", "Campo Limpo Paulista", "3509601"], + ["SP", "Campos do Jord\u{e3}o", "3509700"], + ["SP", "Campos Novos Paulista", "3509809"], + ["SP", "Canan\u{e9}ia", "3509908"], + ["SP", "Canas", "3509957"], + ["SP", "C\u{e2}ndido Mota", "3510005"], + ["SP", "C\u{e2}ndido Rodrigues", "3510104"], + ["SP", "Canitar", "3510153"], + ["SP", "Cap\u{e3}o Bonito", "3510203"], + ["SP", "Capela do Alto", "3510302"], + ["SP", "Capivari", "3510401"], + ["SP", "Caraguatatuba", "3510500"], + ["SP", "Carapicu\u{ed}ba", "3510609"], + ["SP", "Cardoso", "3510708"], + ["SP", "Casa Branca", "3510807"], + ["SP", "C\u{e1}ssia dos Coqueiros", "3510906"], + ["SP", "Castilho", "3511003"], + ["SP", "Catanduva", "3511102"], + ["SP", "Catigu\u{e1}", "3511201"], + ["SP", "Cedral", "3511300"], + ["SP", "Cerqueira C\u{e9}sar", "3511409"], + ["SP", "Cerquilho", "3511508"], + ["SP", "Ces\u{e1}rio Lange", "3511607"], + ["SP", "Charqueada", "3511706"], + ["SP", "Chavantes", "3557204"], + ["SP", "Clementina", "3511904"], + ["SP", "Colina", "3512001"], + ["SP", "Col\u{f4}mbia", "3512100"], + ["SP", "Conchal", "3512209"], + ["SP", "Conchas", "3512308"], + ["SP", "Cordeir\u{f3}polis", "3512407"], + ["SP", "Coroados", "3512506"], + ["SP", "Coronel Macedo", "3512605"], + ["SP", "Corumbata\u{ed}", "3512704"], + ["SP", "Cosm\u{f3}polis", "3512803"], + ["SP", "Cosmorama", "3512902"], + ["SP", "Cotia", "3513009"], + ["SP", "Cravinhos", "3513108"], + ["SP", "Cristais Paulista", "3513207"], + ["SP", "Cruz\u{e1}lia", "3513306"], + ["SP", "Cruzeiro", "3513405"], + ["SP", "Cubat\u{e3}o", "3513504"], + ["SP", "Cunha", "3513603"], + ["SP", "Descalvado", "3513702"], + ["SP", "Diadema", "3513801"], + ["SP", "Dirce Reis", "3513850"], + ["SP", "Divinol\u{e2}ndia", "3513900"], + ["SP", "Dobrada", "3514007"], + ["SP", "Dois C\u{f3}rregos", "3514106"], + ["SP", "Dolcin\u{f3}polis", "3514205"], + ["SP", "Dourado", "3514304"], + ["SP", "Dracena", "3514403"], + ["SP", "Duartina", "3514502"], + ["SP", "Dumont", "3514601"], + ["SP", "Echapor\u{e3}", "3514700"], + ["SP", "Eldorado", "3514809"], + ["SP", "Elias Fausto", "3514908"], + ["SP", "Elisi\u{e1}rio", "3514924"], + ["SP", "Emba\u{fa}ba", "3514957"], + ["SP", "Embu das Artes", "3515004"], + ["SP", "Embu-Gua\u{e7}u", "3515103"], + ["SP", "Emilian\u{f3}polis", "3515129"], + ["SP", "Engenheiro Coelho", "3515152"], + ["SP", "Esp\u{ed}rito Santo do Pinhal", "3515186"], + ["SP", "Esp\u{ed}rito Santo do Turvo", "3515194"], + ["SP", "Estiva Gerbi", "3557303"], + ["SP", "Estrela d'Oeste", "3515202"], + ["SP", "Estrela do Norte", "3515301"], + ["SP", "Euclides da Cunha Paulista", "3515350"], + ["SP", "Fartura", "3515400"], + ["SP", "Fernando Prestes", "3515608"], + ["SP", "Fernand\u{f3}polis", "3515509"], + ["SP", "Fern\u{e3}o", "3515657"], + ["SP", "Ferraz de Vasconcelos", "3515707"], + ["SP", "Flora Rica", "3515806"], + ["SP", "Floreal", "3515905"], + ["SP", "Fl\u{f3}rida Paulista", "3516002"], + ["SP", "Flor\u{ed}nea", "3516101"], + ["SP", "Franca", "3516200"], + ["SP", "Francisco Morato", "3516309"], + ["SP", "Franco da Rocha", "3516408"], + ["SP", "Gabriel Monteiro", "3516507"], + ["SP", "G\u{e1}lia", "3516606"], + ["SP", "Gar\u{e7}a", "3516705"], + ["SP", "Gast\u{e3}o Vidigal", "3516804"], + ["SP", "Gavi\u{e3}o Peixoto", "3516853"], + ["SP", "General Salgado", "3516903"], + ["SP", "Getulina", "3517000"], + ["SP", "Glic\u{e9}rio", "3517109"], + ["SP", "Guai\u{e7}ara", "3517208"], + ["SP", "Guaimb\u{ea}", "3517307"], + ["SP", "Gua\u{ed}ra", "3517406"], + ["SP", "Guapia\u{e7}u", "3517505"], + ["SP", "Guapiara", "3517604"], + ["SP", "Guar\u{e1}", "3517703"], + ["SP", "Guara\u{e7}a\u{ed}", "3517802"], + ["SP", "Guaraci", "3517901"], + ["SP", "Guarani d'Oeste", "3518008"], + ["SP", "Guarant\u{e3}", "3518107"], + ["SP", "Guararapes", "3518206"], + ["SP", "Guararema", "3518305"], + ["SP", "Guaratinguet\u{e1}", "3518404"], + ["SP", "Guare\u{ed}", "3518503"], + ["SP", "Guariba", "3518602"], + ["SP", "Guaruj\u{e1}", "3518701"], + ["SP", "Guarulhos", "3518800"], + ["SP", "Guatapar\u{e1}", "3518859"], + ["SP", "Guzol\u{e2}ndia", "3518909"], + ["SP", "Hercul\u{e2}ndia", "3519006"], + ["SP", "Holambra", "3519055"], + ["SP", "Hortol\u{e2}ndia", "3519071"], + ["SP", "Iacanga", "3519105"], + ["SP", "Iacri", "3519204"], + ["SP", "Iaras", "3519253"], + ["SP", "Ibat\u{e9}", "3519303"], + ["SP", "Ibir\u{e1}", "3519402"], + ["SP", "Ibirarema", "3519501"], + ["SP", "Ibitinga", "3519600"], + ["SP", "Ibi\u{fa}na", "3519709"], + ["SP", "Ic\u{e9}m", "3519808"], + ["SP", "Iep\u{ea}", "3519907"], + ["SP", "Igara\u{e7}u do Tiet\u{ea}", "3520004"], + ["SP", "Igarapava", "3520103"], + ["SP", "Igarat\u{e1}", "3520202"], + ["SP", "Iguape", "3520301"], + ["SP", "Ilha Comprida", "3520426"], + ["SP", "Ilha Solteira", "3520442"], + ["SP", "Ilhabela", "3520400"], + ["SP", "Indaiatuba", "3520509"], + ["SP", "Indiana", "3520608"], + ["SP", "Indiapor\u{e3}", "3520707"], + ["SP", "In\u{fa}bia Paulista", "3520806"], + ["SP", "Ipaussu", "3520905"], + ["SP", "Iper\u{f3}", "3521002"], + ["SP", "Ipe\u{fa}na", "3521101"], + ["SP", "Ipigu\u{e1}", "3521150"], + ["SP", "Iporanga", "3521200"], + ["SP", "Ipu\u{e3}", "3521309"], + ["SP", "Iracem\u{e1}polis", "3521408"], + ["SP", "Irapu\u{e3}", "3521507"], + ["SP", "Irapuru", "3521606"], + ["SP", "Itaber\u{e1}", "3521705"], + ["SP", "Ita\u{ed}", "3521804"], + ["SP", "Itajobi", "3521903"], + ["SP", "Itaju", "3522000"], + ["SP", "Itanha\u{e9}m", "3522109"], + ["SP", "Itaoca", "3522158"], + ["SP", "Itapecerica da Serra", "3522208"], + ["SP", "Itapetininga", "3522307"], + ["SP", "Itapeva", "3522406"], + ["SP", "Itapevi", "3522505"], + ["SP", "Itapira", "3522604"], + ["SP", "Itapirapu\u{e3} Paulista", "3522653"], + ["SP", "It\u{e1}polis", "3522703"], + ["SP", "Itaporanga", "3522802"], + ["SP", "Itapu\u{ed}", "3522901"], + ["SP", "Itapura", "3523008"], + ["SP", "Itaquaquecetuba", "3523107"], + ["SP", "Itarar\u{e9}", "3523206"], + ["SP", "Itariri", "3523305"], + ["SP", "Itatiba", "3523404"], + ["SP", "Itatinga", "3523503"], + ["SP", "Itirapina", "3523602"], + ["SP", "Itirapu\u{e3}", "3523701"], + ["SP", "Itobi", "3523800"], + ["SP", "Itu", "3523909"], + ["SP", "Itupeva", "3524006"], + ["SP", "Ituverava", "3524105"], + ["SP", "Jaborandi", "3524204"], + ["SP", "Jaboticabal", "3524303"], + ["SP", "Jacare\u{ed}", "3524402"], + ["SP", "Jaci", "3524501"], + ["SP", "Jacupiranga", "3524600"], + ["SP", "Jaguari\u{fa}na", "3524709"], + ["SP", "Jales", "3524808"], + ["SP", "Jambeiro", "3524907"], + ["SP", "Jandira", "3525003"], + ["SP", "Jardin\u{f3}polis", "3525102"], + ["SP", "Jarinu", "3525201"], + ["SP", "Ja\u{fa}", "3525300"], + ["SP", "Jeriquara", "3525409"], + ["SP", "Joan\u{f3}polis", "3525508"], + ["SP", "Jo\u{e3}o Ramalho", "3525607"], + ["SP", "Jos\u{e9} Bonif\u{e1}cio", "3525706"], + ["SP", "J\u{fa}lio Mesquita", "3525805"], + ["SP", "Jumirim", "3525854"], + ["SP", "Jundia\u{ed}", "3525904"], + ["SP", "Junqueir\u{f3}polis", "3526001"], + ["SP", "Juqui\u{e1}", "3526100"], + ["SP", "Juquitiba", "3526209"], + ["SP", "Lagoinha", "3526308"], + ["SP", "Laranjal Paulista", "3526407"], + ["SP", "Lav\u{ed}nia", "3526506"], + ["SP", "Lavrinhas", "3526605"], + ["SP", "Leme", "3526704"], + ["SP", "Len\u{e7}\u{f3}is Paulista", "3526803"], + ["SP", "Limeira", "3526902"], + ["SP", "Lind\u{f3}ia", "3527009"], + ["SP", "Lins", "3527108"], + ["SP", "Lorena", "3527207"], + ["SP", "Lourdes", "3527256"], + ["SP", "Louveira", "3527306"], + ["SP", "Luc\u{e9}lia", "3527405"], + ["SP", "Lucian\u{f3}polis", "3527504"], + ["SP", "Lu\u{ed}s Ant\u{f4}nio", "3527603"], + ["SP", "Luizi\u{e2}nia", "3527702"], + ["SP", "Lup\u{e9}rcio", "3527801"], + ["SP", "Lut\u{e9}cia", "3527900"], + ["SP", "Macatuba", "3528007"], + ["SP", "Macaubal", "3528106"], + ["SP", "Maced\u{f4}nia", "3528205"], + ["SP", "Magda", "3528304"], + ["SP", "Mairinque", "3528403"], + ["SP", "Mairipor\u{e3}", "3528502"], + ["SP", "Manduri", "3528601"], + ["SP", "Marab\u{e1} Paulista", "3528700"], + ["SP", "Maraca\u{ed}", "3528809"], + ["SP", "Marapoama", "3528858"], + ["SP", "Mari\u{e1}polis", "3528908"], + ["SP", "Mar\u{ed}lia", "3529005"], + ["SP", "Marin\u{f3}polis", "3529104"], + ["SP", "Martin\u{f3}polis", "3529203"], + ["SP", "Mat\u{e3}o", "3529302"], + ["SP", "Mau\u{e1}", "3529401"], + ["SP", "Mendon\u{e7}a", "3529500"], + ["SP", "Meridiano", "3529609"], + ["SP", "Mes\u{f3}polis", "3529658"], + ["SP", "Miguel\u{f3}polis", "3529708"], + ["SP", "Mineiros do Tiet\u{ea}", "3529807"], + ["SP", "Mira Estrela", "3530003"], + ["SP", "Miracatu", "3529906"], + ["SP", "Mirand\u{f3}polis", "3530102"], + ["SP", "Mirante do Paranapanema", "3530201"], + ["SP", "Mirassol", "3530300"], + ["SP", "Mirassol\u{e2}ndia", "3530409"], + ["SP", "Mococa", "3530508"], + ["SP", "Mogi das Cruzes", "3530607"], + ["SP", "Mogi Gua\u{e7}u", "3530706"], + ["SP", "Mogi Mirim", "3530805"], + ["SP", "Mombuca", "3530904"], + ["SP", "Mon\u{e7}\u{f5}es", "3531001"], + ["SP", "Mongagu\u{e1}", "3531100"], + ["SP", "Monte Alegre do Sul", "3531209"], + ["SP", "Monte Alto", "3531308"], + ["SP", "Monte Apraz\u{ed}vel", "3531407"], + ["SP", "Monte Azul Paulista", "3531506"], + ["SP", "Monte Castelo", "3531605"], + ["SP", "Monte Mor", "3531803"], + ["SP", "Monteiro Lobato", "3531704"], + ["SP", "Morro Agudo", "3531902"], + ["SP", "Morungaba", "3532009"], + ["SP", "Motuca", "3532058"], + ["SP", "Murutinga do Sul", "3532108"], + ["SP", "Nantes", "3532157"], + ["SP", "Narandiba", "3532207"], + ["SP", "Natividade da Serra", "3532306"], + ["SP", "Nazar\u{e9} Paulista", "3532405"], + ["SP", "Neves Paulista", "3532504"], + ["SP", "Nhandeara", "3532603"], + ["SP", "Nipo\u{e3}", "3532702"], + ["SP", "Nova Alian\u{e7}a", "3532801"], + ["SP", "Nova Campina", "3532827"], + ["SP", "Nova Cana\u{e3} Paulista", "3532843"], + ["SP", "Nova Castilho", "3532868"], + ["SP", "Nova Europa", "3532900"], + ["SP", "Nova Granada", "3533007"], + ["SP", "Nova Guataporanga", "3533106"], + ["SP", "Nova Independ\u{ea}ncia", "3533205"], + ["SP", "Nova Luzit\u{e2}nia", "3533304"], + ["SP", "Nova Odessa", "3533403"], + ["SP", "Novais", "3533254"], + ["SP", "Novo Horizonte", "3533502"], + ["SP", "Nuporanga", "3533601"], + ["SP", "Ocau\u{e7}u", "3533700"], + ["SP", "\u{d3}leo", "3533809"], + ["SP", "Ol\u{ed}mpia", "3533908"], + ["SP", "Onda Verde", "3534005"], + ["SP", "Oriente", "3534104"], + ["SP", "Orindi\u{fa}va", "3534203"], + ["SP", "Orl\u{e2}ndia", "3534302"], + ["SP", "Osasco", "3534401"], + ["SP", "Oscar Bressane", "3534500"], + ["SP", "Osvaldo Cruz", "3534609"], + ["SP", "Ourinhos", "3534708"], + ["SP", "Ouro Verde", "3534807"], + ["SP", "Ouroeste", "3534757"], + ["SP", "Pacaembu", "3534906"], + ["SP", "Palestina", "3535002"], + ["SP", "Palmares Paulista", "3535101"], + ["SP", "Palmeira d'Oeste", "3535200"], + ["SP", "Palmital", "3535309"], + ["SP", "Panorama", "3535408"], + ["SP", "Paragua\u{e7}u Paulista", "3535507"], + ["SP", "Paraibuna", "3535606"], + ["SP", "Para\u{ed}so", "3535705"], + ["SP", "Paranapanema", "3535804"], + ["SP", "Paranapu\u{e3}", "3535903"], + ["SP", "Parapu\u{e3}", "3536000"], + ["SP", "Pardinho", "3536109"], + ["SP", "Pariquera-A\u{e7}u", "3536208"], + ["SP", "Parisi", "3536257"], + ["SP", "Patroc\u{ed}nio Paulista", "3536307"], + ["SP", "Paulic\u{e9}ia", "3536406"], + ["SP", "Paul\u{ed}nia", "3536505"], + ["SP", "Paulist\u{e2}nia", "3536570"], + ["SP", "Paulo de Faria", "3536604"], + ["SP", "Pederneiras", "3536703"], + ["SP", "Pedra Bela", "3536802"], + ["SP", "Pedran\u{f3}polis", "3536901"], + ["SP", "Pedregulho", "3537008"], + ["SP", "Pedreira", "3537107"], + ["SP", "Pedrinhas Paulista", "3537156"], + ["SP", "Pedro de Toledo", "3537206"], + ["SP", "Pen\u{e1}polis", "3537305"], + ["SP", "Pereira Barreto", "3537404"], + ["SP", "Pereiras", "3537503"], + ["SP", "Peru\u{ed}be", "3537602"], + ["SP", "Piacatu", "3537701"], + ["SP", "Piedade", "3537800"], + ["SP", "Pilar do Sul", "3537909"], + ["SP", "Pindamonhangaba", "3538006"], + ["SP", "Pindorama", "3538105"], + ["SP", "Pinhalzinho", "3538204"], + ["SP", "Piquerobi", "3538303"], + ["SP", "Piquete", "3538501"], + ["SP", "Piracaia", "3538600"], + ["SP", "Piracicaba", "3538709"], + ["SP", "Piraju", "3538808"], + ["SP", "Piraju\u{ed}", "3538907"], + ["SP", "Pirangi", "3539004"], + ["SP", "Pirapora do Bom Jesus", "3539103"], + ["SP", "Pirapozinho", "3539202"], + ["SP", "Pirassununga", "3539301"], + ["SP", "Piratininga", "3539400"], + ["SP", "Pitangueiras", "3539509"], + ["SP", "Planalto", "3539608"], + ["SP", "Platina", "3539707"], + ["SP", "Po\u{e1}", "3539806"], + ["SP", "Poloni", "3539905"], + ["SP", "Pomp\u{e9}ia", "3540002"], + ["SP", "Ponga\u{ed}", "3540101"], + ["SP", "Pontal", "3540200"], + ["SP", "Pontalinda", "3540259"], + ["SP", "Pontes Gestal", "3540309"], + ["SP", "Populina", "3540408"], + ["SP", "Porangaba", "3540507"], + ["SP", "Porto Feliz", "3540606"], + ["SP", "Porto Ferreira", "3540705"], + ["SP", "Potim", "3540754"], + ["SP", "Potirendaba", "3540804"], + ["SP", "Pracinha", "3540853"], + ["SP", "Prad\u{f3}polis", "3540903"], + ["SP", "Praia Grande", "3541000"], + ["SP", "Prat\u{e2}nia", "3541059"], + ["SP", "Presidente Alves", "3541109"], + ["SP", "Presidente Bernardes", "3541208"], + ["SP", "Presidente Epit\u{e1}cio", "3541307"], + ["SP", "Presidente Prudente", "3541406"], + ["SP", "Presidente Venceslau", "3541505"], + ["SP", "Promiss\u{e3}o", "3541604"], + ["SP", "Quadra", "3541653"], + ["SP", "Quat\u{e1}", "3541703"], + ["SP", "Queiroz", "3541802"], + ["SP", "Queluz", "3541901"], + ["SP", "Quintana", "3542008"], + ["SP", "Rafard", "3542107"], + ["SP", "Rancharia", "3542206"], + ["SP", "Reden\u{e7}\u{e3}o da Serra", "3542305"], + ["SP", "Regente Feij\u{f3}", "3542404"], + ["SP", "Regin\u{f3}polis", "3542503"], + ["SP", "Registro", "3542602"], + ["SP", "Restinga", "3542701"], + ["SP", "Ribeira", "3542800"], + ["SP", "Ribeir\u{e3}o Bonito", "3542909"], + ["SP", "Ribeir\u{e3}o Branco", "3543006"], + ["SP", "Ribeir\u{e3}o Corrente", "3543105"], + ["SP", "Ribeir\u{e3}o do Sul", "3543204"], + ["SP", "Ribeir\u{e3}o dos \u{cd}ndios", "3543238"], + ["SP", "Ribeir\u{e3}o Grande", "3543253"], + ["SP", "Ribeir\u{e3}o Pires", "3543303"], + ["SP", "Ribeir\u{e3}o Preto", "3543402"], + ["SP", "Rifaina", "3543600"], + ["SP", "Rinc\u{e3}o", "3543709"], + ["SP", "Rin\u{f3}polis", "3543808"], + ["SP", "Rio Claro", "3543907"], + ["SP", "Rio das Pedras", "3544004"], + ["SP", "Rio Grande da Serra", "3544103"], + ["SP", "Riol\u{e2}ndia", "3544202"], + ["SP", "Riversul", "3543501"], + ["SP", "Rosana", "3544251"], + ["SP", "Roseira", "3544301"], + ["SP", "Rubi\u{e1}cea", "3544400"], + ["SP", "Rubin\u{e9}ia", "3544509"], + ["SP", "Sabino", "3544608"], + ["SP", "Sagres", "3544707"], + ["SP", "Sales", "3544806"], + ["SP", "Sales Oliveira", "3544905"], + ["SP", "Sales\u{f3}polis", "3545001"], + ["SP", "Salmour\u{e3}o", "3545100"], + ["SP", "Saltinho", "3545159"], + ["SP", "Salto", "3545209"], + ["SP", "Salto de Pirapora", "3545308"], + ["SP", "Salto Grande", "3545407"], + ["SP", "Sandovalina", "3545506"], + ["SP", "Santa Ad\u{e9}lia", "3545605"], + ["SP", "Santa Albertina", "3545704"], + ["SP", "Santa B\u{e1}rbara d'Oeste", "3545803"], + ["SP", "Santa Branca", "3546009"], + ["SP", "Santa Clara d'Oeste", "3546108"], + ["SP", "Santa Cruz da Concei\u{e7}\u{e3}o", "3546207"], + ["SP", "Santa Cruz da Esperan\u{e7}a", "3546256"], + ["SP", "Santa Cruz das Palmeiras", "3546306"], + ["SP", "Santa Cruz do Rio Pardo", "3546405"], + ["SP", "Santa Ernestina", "3546504"], + ["SP", "Santa F\u{e9} do Sul", "3546603"], + ["SP", "Santa Gertrudes", "3546702"], + ["SP", "Santa Isabel", "3546801"], + ["SP", "Santa L\u{fa}cia", "3546900"], + ["SP", "Santa Maria da Serra", "3547007"], + ["SP", "Santa Mercedes", "3547106"], + ["SP", "Santa Rita d'Oeste", "3547403"], + ["SP", "Santa Rita do Passa Quatro", "3547502"], + ["SP", "Santa Rosa de Viterbo", "3547601"], + ["SP", "Santa Salete", "3547650"], + ["SP", "Santana da Ponte Pensa", "3547205"], + ["SP", "Santana de Parna\u{ed}ba", "3547304"], + ["SP", "Santo Anast\u{e1}cio", "3547700"], + ["SP", "Santo Andr\u{e9}", "3547809"], + ["SP", "Santo Ant\u{f4}nio da Alegria", "3547908"], + ["SP", "Santo Ant\u{f4}nio de Posse", "3548005"], + ["SP", "Santo Ant\u{f4}nio do Aracangu\u{e1}", "3548054"], + ["SP", "Santo Ant\u{f4}nio do Jardim", "3548104"], + ["SP", "Santo Ant\u{f4}nio do Pinhal", "3548203"], + ["SP", "Santo Expedito", "3548302"], + ["SP", "Sant\u{f3}polis do Aguape\u{ed}", "3548401"], + ["SP", "Santos", "3548500"], + ["SP", "S\u{e3}o Bento do Sapuca\u{ed}", "3548609"], + ["SP", "S\u{e3}o Bernardo do Campo", "3548708"], + ["SP", "S\u{e3}o Caetano do Sul", "3548807"], + ["SP", "S\u{e3}o Carlos", "3548906"], + ["SP", "S\u{e3}o Francisco", "3549003"], + ["SP", "S\u{e3}o Jo\u{e3}o da Boa Vista", "3549102"], + ["SP", "S\u{e3}o Jo\u{e3}o das Duas Pontes", "3549201"], + ["SP", "S\u{e3}o Jo\u{e3}o de Iracema", "3549250"], + ["SP", "S\u{e3}o Jo\u{e3}o do Pau d'Alho", "3549300"], + ["SP", "S\u{e3}o Joaquim da Barra", "3549409"], + ["SP", "S\u{e3}o Jos\u{e9} da Bela Vista", "3549508"], + ["SP", "S\u{e3}o Jos\u{e9} do Barreiro", "3549607"], + ["SP", "S\u{e3}o Jos\u{e9} do Rio Pardo", "3549706"], + ["SP", "S\u{e3}o Jos\u{e9} do Rio Preto", "3549805"], + ["SP", "S\u{e3}o Jos\u{e9} dos Campos", "3549904"], + ["SP", "S\u{e3}o Louren\u{e7}o da Serra", "3549953"], + ["SP", "S\u{e3}o Luiz do Paraitinga", "3550001"], + ["SP", "S\u{e3}o Manuel", "3550100"], + ["SP", "S\u{e3}o Miguel Arcanjo", "3550209"], + ["SP", "S\u{e3}o Paulo", "3550308"], + ["SP", "S\u{e3}o Pedro", "3550407"], + ["SP", "S\u{e3}o Pedro do Turvo", "3550506"], + ["SP", "S\u{e3}o Roque", "3550605"], + ["SP", "S\u{e3}o Sebasti\u{e3}o", "3550704"], + ["SP", "S\u{e3}o Sebasti\u{e3}o da Grama", "3550803"], + ["SP", "S\u{e3}o Sim\u{e3}o", "3550902"], + ["SP", "S\u{e3}o Vicente", "3551009"], + ["SP", "Sarapu\u{ed}", "3551108"], + ["SP", "Sarutai\u{e1}", "3551207"], + ["SP", "Sebastian\u{f3}polis do Sul", "3551306"], + ["SP", "Serra Azul", "3551405"], + ["SP", "Serra Negra", "3551603"], + ["SP", "Serrana", "3551504"], + ["SP", "Sert\u{e3}ozinho", "3551702"], + ["SP", "Sete Barras", "3551801"], + ["SP", "Sever\u{ed}nia", "3551900"], + ["SP", "Silveiras", "3552007"], + ["SP", "Socorro", "3552106"], + ["SP", "Sorocaba", "3552205"], + ["SP", "Sud Mennucci", "3552304"], + ["SP", "Sumar\u{e9}", "3552403"], + ["SP", "Suzan\u{e1}polis", "3552551"], + ["SP", "Suzano", "3552502"], + ["SP", "Tabapu\u{e3}", "3552601"], + ["SP", "Tabatinga", "3552700"], + ["SP", "Tabo\u{e3}o da Serra", "3552809"], + ["SP", "Taciba", "3552908"], + ["SP", "Tagua\u{ed}", "3553005"], + ["SP", "Taia\u{e7}u", "3553104"], + ["SP", "Tai\u{fa}va", "3553203"], + ["SP", "Tamba\u{fa}", "3553302"], + ["SP", "Tanabi", "3553401"], + ["SP", "Tapira\u{ed}", "3553500"], + ["SP", "Tapiratiba", "3553609"], + ["SP", "Taquaral", "3553658"], + ["SP", "Taquaritinga", "3553708"], + ["SP", "Taquarituba", "3553807"], + ["SP", "Taquariva\u{ed}", "3553856"], + ["SP", "Tarabai", "3553906"], + ["SP", "Tarum\u{e3}", "3553955"], + ["SP", "Tatu\u{ed}", "3554003"], + ["SP", "Taubat\u{e9}", "3554102"], + ["SP", "Tejup\u{e1}", "3554201"], + ["SP", "Teodoro Sampaio", "3554300"], + ["SP", "Terra Roxa", "3554409"], + ["SP", "Tiet\u{ea}", "3554508"], + ["SP", "Timburi", "3554607"], + ["SP", "Torre de Pedra", "3554656"], + ["SP", "Torrinha", "3554706"], + ["SP", "Trabiju", "3554755"], + ["SP", "Trememb\u{e9}", "3554805"], + ["SP", "Tr\u{ea}s Fronteiras", "3554904"], + ["SP", "Tuiuti", "3554953"], + ["SP", "Tup\u{e3}", "3555000"], + ["SP", "Tupi Paulista", "3555109"], + ["SP", "Turi\u{fa}ba", "3555208"], + ["SP", "Turmalina", "3555307"], + ["SP", "Ubarana", "3555356"], + ["SP", "Ubatuba", "3555406"], + ["SP", "Ubirajara", "3555505"], + ["SP", "Uchoa", "3555604"], + ["SP", "Uni\u{e3}o Paulista", "3555703"], + ["SP", "Ur\u{e2}nia", "3555802"], + ["SP", "Uru", "3555901"], + ["SP", "Urup\u{ea}s", "3556008"], + ["SP", "Valentim Gentil", "3556107"], + ["SP", "Valinhos", "3556206"], + ["SP", "Valpara\u{ed}so", "3556305"], + ["SP", "Vargem", "3556354"], + ["SP", "Vargem Grande do Sul", "3556404"], + ["SP", "Vargem Grande Paulista", "3556453"], + ["SP", "V\u{e1}rzea Paulista", "3556503"], + ["SP", "Vera Cruz", "3556602"], + ["SP", "Vinhedo", "3556701"], + ["SP", "Viradouro", "3556800"], + ["SP", "Vista Alegre do Alto", "3556909"], + ["SP", "Vit\u{f3}ria Brasil", "3556958"], + ["SP", "Votorantim", "3557006"], + ["SP", "Votuporanga", "3557105"], + ["SP", "Zacarias", "3557154"], + ["SE", "Amparo do S\u{e3}o Francisco", "2800100"], + ["SE", "Aquidab\u{e3}", "2800209"], + ["SE", "Aracaju", "2800308"], + ["SE", "Arau\u{e1}", "2800407"], + ["SE", "Areia Branca", "2800506"], + ["SE", "Barra dos Coqueiros", "2800605"], + ["SE", "Boquim", "2800670"], + ["SE", "Brejo Grande", "2800704"], + ["SE", "Campo do Brito", "2801009"], + ["SE", "Canhoba", "2801108"], + ["SE", "Canind\u{e9} de S\u{e3}o Francisco", "2801207"], + ["SE", "Capela", "2801306"], + ["SE", "Carira", "2801405"], + ["SE", "Carm\u{f3}polis", "2801504"], + ["SE", "Cedro de S\u{e3}o Jo\u{e3}o", "2801603"], + ["SE", "Cristin\u{e1}polis", "2801702"], + ["SE", "Cumbe", "2801900"], + ["SE", "Divina Pastora", "2802007"], + ["SE", "Est\u{e2}ncia", "2802106"], + ["SE", "Feira Nova", "2802205"], + ["SE", "Frei Paulo", "2802304"], + ["SE", "Gararu", "2802403"], + ["SE", "General Maynard", "2802502"], + ["SE", "Graccho Cardoso", "2802601"], + ["SE", "Ilha das Flores", "2802700"], + ["SE", "Indiaroba", "2802809"], + ["SE", "Itabaiana", "2802908"], + ["SE", "Itabaianinha", "2803005"], + ["SE", "Itabi", "2803104"], + ["SE", "Itaporanga d'Ajuda", "2803203"], + ["SE", "Japaratuba", "2803302"], + ["SE", "Japoat\u{e3}", "2803401"], + ["SE", "Lagarto", "2803500"], + ["SE", "Laranjeiras", "2803609"], + ["SE", "Macambira", "2803708"], + ["SE", "Malhada dos Bois", "2803807"], + ["SE", "Malhador", "2803906"], + ["SE", "Maruim", "2804003"], + ["SE", "Moita Bonita", "2804102"], + ["SE", "Monte Alegre de Sergipe", "2804201"], + ["SE", "Muribeca", "2804300"], + ["SE", "Ne\u{f3}polis", "2804409"], + ["SE", "Nossa Senhora Aparecida", "2804458"], + ["SE", "Nossa Senhora da Gl\u{f3}ria", "2804508"], + ["SE", "Nossa Senhora das Dores", "2804607"], + ["SE", "Nossa Senhora de Lourdes", "2804706"], + ["SE", "Nossa Senhora do Socorro", "2804805"], + ["SE", "Pacatuba", "2804904"], + ["SE", "Pedra Mole", "2805000"], + ["SE", "Pedrinhas", "2805109"], + ["SE", "Pinh\u{e3}o", "2805208"], + ["SE", "Pirambu", "2805307"], + ["SE", "Po\u{e7}o Redondo", "2805406"], + ["SE", "Po\u{e7}o Verde", "2805505"], + ["SE", "Porto da Folha", "2805604"], + ["SE", "Propri\u{e1}", "2805703"], + ["SE", "Riach\u{e3}o do Dantas", "2805802"], + ["SE", "Riachuelo", "2805901"], + ["SE", "Ribeir\u{f3}polis", "2806008"], + ["SE", "Ros\u{e1}rio do Catete", "2806107"], + ["SE", "Salgado", "2806206"], + ["SE", "Santa Luzia do Itanhy", "2806305"], + ["SE", "Santa Rosa de Lima", "2806503"], + ["SE", "Santana do S\u{e3}o Francisco", "2806404"], + ["SE", "Santo Amaro das Brotas", "2806602"], + ["SE", "S\u{e3}o Crist\u{f3}v\u{e3}o", "2806701"], + ["SE", "S\u{e3}o Domingos", "2806800"], + ["SE", "S\u{e3}o Francisco", "2806909"], + ["SE", "S\u{e3}o Miguel do Aleixo", "2807006"], + ["SE", "Sim\u{e3}o Dias", "2807105"], + ["SE", "Siriri", "2807204"], + ["SE", "Telha", "2807303"], + ["SE", "Tobias Barreto", "2807402"], + ["SE", "Tomar do Geru", "2807501"], + ["SE", "Umba\u{fa}ba", "2807600"], + ["TO", "Abreul\u{e2}ndia", "1700251"], + ["TO", "Aguiarn\u{f3}polis", "1700301"], + ["TO", "Alian\u{e7}a do Tocantins", "1700350"], + ["TO", "Almas", "1700400"], + ["TO", "Alvorada", "1700707"], + ["TO", "Anan\u{e1}s", "1701002"], + ["TO", "Angico", "1701051"], + ["TO", "Aparecida do Rio Negro", "1701101"], + ["TO", "Aragominas", "1701309"], + ["TO", "Araguacema", "1701903"], + ["TO", "Aragua\u{e7}u", "1702000"], + ["TO", "Aragua\u{ed}na", "1702109"], + ["TO", "Araguan\u{e3}", "1702158"], + ["TO", "Araguatins", "1702208"], + ["TO", "Arapoema", "1702307"], + ["TO", "Arraias", "1702406"], + ["TO", "Augustin\u{f3}polis", "1702554"], + ["TO", "Aurora do Tocantins", "1702703"], + ["TO", "Axix\u{e1} do Tocantins", "1702901"], + ["TO", "Baba\u{e7}ul\u{e2}ndia", "1703008"], + ["TO", "Bandeirantes do Tocantins", "1703057"], + ["TO", "Barra do Ouro", "1703073"], + ["TO", "Barrol\u{e2}ndia", "1703107"], + ["TO", "Bernardo Say\u{e3}o", "1703206"], + ["TO", "Bom Jesus do Tocantins", "1703305"], + ["TO", "Brasil\u{e2}ndia do Tocantins", "1703602"], + ["TO", "Brejinho de Nazar\u{e9}", "1703701"], + ["TO", "Buriti do Tocantins", "1703800"], + ["TO", "Cachoeirinha", "1703826"], + ["TO", "Campos Lindos", "1703842"], + ["TO", "Cariri do Tocantins", "1703867"], + ["TO", "Carmol\u{e2}ndia", "1703883"], + ["TO", "Carrasco Bonito", "1703891"], + ["TO", "Caseara", "1703909"], + ["TO", "Centen\u{e1}rio", "1704105"], + ["TO", "Chapada da Natividade", "1705102"], + ["TO", "Chapada de Areia", "1704600"], + ["TO", "Colinas do Tocantins", "1705508"], + ["TO", "Colm\u{e9}ia", "1716703"], + ["TO", "Combinado", "1705557"], + ["TO", "Concei\u{e7}\u{e3}o do Tocantins", "1705607"], + ["TO", "Couto Magalh\u{e3}es", "1706001"], + ["TO", "Cristal\u{e2}ndia", "1706100"], + ["TO", "Crix\u{e1}s do Tocantins", "1706258"], + ["TO", "Darcin\u{f3}polis", "1706506"], + ["TO", "Dian\u{f3}polis", "1707009"], + ["TO", "Divin\u{f3}polis do Tocantins", "1707108"], + ["TO", "Dois Irm\u{e3}os do Tocantins", "1707207"], + ["TO", "Duer\u{e9}", "1707306"], + ["TO", "Esperantina", "1707405"], + ["TO", "F\u{e1}tima", "1707553"], + ["TO", "Figueir\u{f3}polis", "1707652"], + ["TO", "Filad\u{e9}lfia", "1707702"], + ["TO", "Formoso do Araguaia", "1708205"], + ["TO", "Goianorte", "1708304"], + ["TO", "Goiatins", "1709005"], + ["TO", "Guara\u{ed}", "1709302"], + ["TO", "Gurupi", "1709500"], + ["TO", "Ipueiras", "1709807"], + ["TO", "Itacaj\u{e1}", "1710508"], + ["TO", "Itaguatins", "1710706"], + ["TO", "Itapiratins", "1710904"], + ["TO", "Itapor\u{e3} do Tocantins", "1711100"], + ["TO", "Ja\u{fa} do Tocantins", "1711506"], + ["TO", "Juarina", "1711803"], + ["TO", "Lagoa da Confus\u{e3}o", "1711902"], + ["TO", "Lagoa do Tocantins", "1711951"], + ["TO", "Lajeado", "1712009"], + ["TO", "Lavandeira", "1712157"], + ["TO", "Lizarda", "1712405"], + ["TO", "Luzin\u{f3}polis", "1712454"], + ["TO", "Marian\u{f3}polis do Tocantins", "1712504"], + ["TO", "Mateiros", "1712702"], + ["TO", "Mauril\u{e2}ndia do Tocantins", "1712801"], + ["TO", "Miracema do Tocantins", "1713205"], + ["TO", "Miranorte", "1713304"], + ["TO", "Monte do Carmo", "1713601"], + ["TO", "Monte Santo do Tocantins", "1713700"], + ["TO", "Muricil\u{e2}ndia", "1713957"], + ["TO", "Natividade", "1714203"], + ["TO", "Nazar\u{e9}", "1714302"], + ["TO", "Nova Olinda", "1714880"], + ["TO", "Nova Rosal\u{e2}ndia", "1715002"], + ["TO", "Novo Acordo", "1715101"], + ["TO", "Novo Alegre", "1715150"], + ["TO", "Novo Jardim", "1715259"], + ["TO", "Oliveira de F\u{e1}tima", "1715507"], + ["TO", "Palmas", "1721000"], + ["TO", "Palmeirante", "1715705"], + ["TO", "Palmeiras do Tocantins", "1713809"], + ["TO", "Palmeir\u{f3}polis", "1715754"], + ["TO", "Para\u{ed}so do Tocantins", "1716109"], + ["TO", "Paran\u{e3}", "1716208"], + ["TO", "Pau D'Arco", "1716307"], + ["TO", "Pedro Afonso", "1716505"], + ["TO", "Peixe", "1716604"], + ["TO", "Pequizeiro", "1716653"], + ["TO", "Pindorama do Tocantins", "1717008"], + ["TO", "Piraqu\u{ea}", "1717206"], + ["TO", "Pium", "1717503"], + ["TO", "Ponte Alta do Bom Jesus", "1717800"], + ["TO", "Ponte Alta do Tocantins", "1717909"], + ["TO", "Porto Alegre do Tocantins", "1718006"], + ["TO", "Porto Nacional", "1718204"], + ["TO", "Praia Norte", "1718303"], + ["TO", "Presidente Kennedy", "1718402"], + ["TO", "Pugmil", "1718451"], + ["TO", "Recursol\u{e2}ndia", "1718501"], + ["TO", "Riachinho", "1718550"], + ["TO", "Rio da Concei\u{e7}\u{e3}o", "1718659"], + ["TO", "Rio dos Bois", "1718709"], + ["TO", "Rio Sono", "1718758"], + ["TO", "Sampaio", "1718808"], + ["TO", "Sandol\u{e2}ndia", "1718840"], + ["TO", "Santa F\u{e9} do Araguaia", "1718865"], + ["TO", "Santa Maria do Tocantins", "1718881"], + ["TO", "Santa Rita do Tocantins", "1718899"], + ["TO", "Santa Rosa do Tocantins", "1718907"], + ["TO", "Santa Tereza do Tocantins", "1719004"], + ["TO", "Santa Terezinha do Tocantins", "1720002"], + ["TO", "S\u{e3}o Bento do Tocantins", "1720101"], + ["TO", "S\u{e3}o F\u{e9}lix do Tocantins", "1720150"], + ["TO", "S\u{e3}o Miguel do Tocantins", "1720200"], + ["TO", "S\u{e3}o Salvador do Tocantins", "1720259"], + ["TO", "S\u{e3}o Sebasti\u{e3}o do Tocantins", "1720309"], + ["TO", "S\u{e3}o Val\u{e9}rio", "1720499"], + ["TO", "Silvan\u{f3}polis", "1720655"], + ["TO", "S\u{ed}tio Novo do Tocantins", "1720804"], + ["TO", "Sucupira", "1720853"], + ["TO", "Taboc\u{e3}o", "1708254"], + ["TO", "Taguatinga", "1720903"], + ["TO", "Taipas do Tocantins", "1720937"], + ["TO", "Talism\u{e3}", "1720978"], + ["TO", "Tocant\u{ed}nia", "1721109"], + ["TO", "Tocantin\u{f3}polis", "1721208"], + ["TO", "Tupirama", "1721257"], + ["TO", "Tupiratins", "1721307"], + ["TO", "Wanderl\u{e2}ndia", "1722081"], + ["TO", "Xambio\u{e1}", "1722107"], + ], + [ + ["AC", [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21]], + ["AL", [22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123]], + ["AP", [124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139]], + ["AM", [140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201]], + ["BA", [202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, 443, 444, 445, 446, 447, 448, 449, 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, 495, 496, 497, 498, 499, 500, 501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, 519, 520, 521, 522, 523, 524, 525, 526, 527, 528, 529, 530, 531, 532, 533, 534, 535, 536, 537, 538, 539, 540, 541, 542, 543, 544, 545, 546, 547, 548, 549, 550, 551, 552, 553, 554, 555, 556, 557, 558, 559, 560, 561, 562, 563, 564, 565, 566, 567, 568, 569, 570, 571, 572, 573, 574, 575, 576, 577, 578, 579, 580, 581, 582, 583, 584, 585, 586, 587, 588, 589, 590, 591, 592, 593, 594, 595, 596, 597, 598, 599, 600, 601, 602, 603, 604, 605, 606, 607, 608, 609, 610, 611, 612, 613, 614, 615, 616, 617, 618]], + ["CE", [619, 620, 621, 622, 623, 624, 625, 626, 627, 628, 629, 630, 631, 632, 633, 634, 635, 636, 637, 638, 639, 640, 641, 642, 643, 644, 645, 646, 647, 648, 649, 650, 651, 652, 653, 654, 655, 656, 657, 658, 659, 660, 661, 662, 663, 664, 665, 666, 667, 668, 669, 670, 671, 672, 673, 674, 675, 676, 677, 678, 679, 680, 681, 682, 683, 684, 685, 686, 687, 688, 689, 690, 691, 692, 693, 694, 695, 696, 697, 698, 699, 700, 701, 702, 703, 704, 705, 706, 707, 708, 709, 710, 711, 712, 713, 714, 715, 716, 717, 718, 719, 720, 721, 722, 723, 724, 725, 726, 727, 728, 729, 730, 731, 732, 733, 734, 735, 736, 737, 738, 739, 740, 741, 742, 743, 744, 745, 746, 747, 748, 749, 750, 751, 752, 753, 754, 755, 756, 757, 758, 759, 760, 761, 762, 763, 764, 765, 766, 767, 768, 769, 770, 771, 772, 773, 774, 775, 776, 777, 778, 779, 780, 781, 782, 783, 784, 785, 786, 787, 788, 789, 790, 791, 792, 793, 794, 795, 796, 797, 798, 799, 800, 801, 802]], + ["DF", [803]], + ["ES", [804, 805, 806, 807, 808, 809, 810, 811, 812, 813, 814, 815, 816, 817, 818, 819, 820, 821, 822, 823, 824, 825, 826, 827, 828, 829, 830, 831, 832, 833, 834, 835, 836, 837, 838, 839, 840, 841, 842, 843, 844, 845, 846, 847, 848, 849, 850, 851, 852, 853, 854, 855, 856, 857, 858, 859, 860, 861, 862, 863, 864, 865, 866, 867, 868, 869, 870, 871, 872, 873, 874, 875, 876, 877, 878, 879, 880, 881]], + ["GO", [882, 883, 884, 885, 886, 887, 888, 889, 890, 891, 892, 893, 894, 895, 896, 897, 898, 899, 900, 901, 902, 903, 904, 905, 906, 907, 908, 909, 910, 911, 912, 913, 914, 915, 916, 917, 918, 919, 920, 921, 922, 923, 924, 925, 926, 927, 928, 929, 930, 931, 932, 933, 934, 935, 936, 937, 938, 939, 940, 941, 942, 943, 944, 945, 946, 947, 948, 949, 950, 951, 952, 953, 954, 955, 956, 957, 958, 959, 960, 961, 962, 963, 964, 965, 966, 967, 968, 969, 970, 971, 972, 973, 974, 975, 976, 977, 978, 979, 980, 981, 982, 983, 984, 985, 986, 987, 988, 989, 990, 991, 992, 993, 994, 995, 996, 997, 998, 999, 1000, 1001, 1002, 1003, 1004, 1005, 1006, 1007, 1008, 1009, 1010, 1011, 1012, 1013, 1014, 1015, 1016, 1017, 1018, 1019, 1020, 1021, 1022, 1023, 1024, 1025, 1026, 1027, 1028, 1029, 1030, 1031, 1032, 1033, 1034, 1035, 1036, 1037, 1038, 1039, 1040, 1041, 1042, 1043, 1044, 1045, 1046, 1047, 1048, 1049, 1050, 1051, 1052, 1053, 1054, 1055, 1056, 1057, 1058, 1059, 1060, 1061, 1062, 1063, 1064, 1065, 1066, 1067, 1068, 1069, 1070, 1071, 1072, 1073, 1074, 1075, 1076, 1077, 1078, 1079, 1080, 1081, 1082, 1083, 1084, 1085, 1086, 1087, 1088, 1089, 1090, 1091, 1092, 1093, 1094, 1095, 1096, 1097, 1098, 1099, 1100, 1101, 1102, 1103, 1104, 1105, 1106, 1107, 1108, 1109, 1110, 1111, 1112, 1113, 1114, 1115, 1116, 1117, 1118, 1119, 1120, 1121, 1122, 1123, 1124, 1125, 1126, 1127]], + ["MA", [1128, 1129, 1130, 1131, 1132, 1133, 1134, 1135, 1136, 1137, 1138, 1139, 1140, 1141, 1142, 1143, 1144, 1145, 1146, 1147, 1148, 1149, 1150, 1151, 1152, 1153, 1154, 1155, 1156, 1157, 1158, 1159, 1160, 1161, 1162, 1163, 1164, 1165, 1166, 1167, 1168, 1169, 1170, 1171, 1172, 1173, 1174, 1175, 1176, 1177, 1178, 1179, 1180, 1181, 1182, 1183, 1184, 1185, 1186, 1187, 1188, 1189, 1190, 1191, 1192, 1193, 1194, 1195, 1196, 1197, 1198, 1199, 1200, 1201, 1202, 1203, 1204, 1205, 1206, 1207, 1208, 1209, 1210, 1211, 1212, 1213, 1214, 1215, 1216, 1217, 1218, 1219, 1220, 1221, 1222, 1223, 1224, 1225, 1226, 1227, 1228, 1229, 1230, 1231, 1232, 1233, 1234, 1235, 1236, 1237, 1238, 1239, 1240, 1241, 1242, 1243, 1244, 1245, 1246, 1247, 1248, 1249, 1250, 1251, 1252, 1253, 1254, 1255, 1256, 1257, 1258, 1259, 1260, 1261, 1262, 1263, 1264, 1265, 1266, 1267, 1268, 1269, 1270, 1271, 1272, 1273, 1274, 1275, 1276, 1277, 1278, 1279, 1280, 1281, 1282, 1283, 1284, 1285, 1286, 1287, 1288, 1289, 1290, 1291, 1292, 1293, 1294, 1295, 1296, 1297, 1298, 1299, 1300, 1301, 1302, 1303, 1304, 1305, 1306, 1307, 1308, 1309, 1310, 1311, 1312, 1313, 1314, 1315, 1316, 1317, 1318, 1319, 1320, 1321, 1322, 1323, 1324, 1325, 1326, 1327, 1328, 1329, 1330, 1331, 1332, 1333, 1334, 1335, 1336, 1337, 1338, 1339, 1340, 1341, 1342, 1343, 1344]], + ["MT", [1345, 1346, 1347, 1348, 1349, 1350, 1351, 1352, 1353, 1354, 1355, 1356, 1357, 1358, 1359, 1360, 1361, 1362, 1363, 1364, 1365, 1366, 1367, 1368, 1369, 1370, 1371, 1372, 1373, 1374, 1375, 1376, 1377, 1378, 1379, 1380, 1381, 1382, 1383, 1384, 1385, 1386, 1387, 1388, 1389, 1390, 1391, 1392, 1393, 1394, 1395, 1396, 1397, 1398, 1399, 1400, 1401, 1402, 1403, 1404, 1405, 1406, 1407, 1408, 1409, 1410, 1411, 1412, 1413, 1414, 1415, 1416, 1417, 1418, 1419, 1420, 1421, 1422, 1423, 1424, 1425, 1426, 1427, 1428, 1429, 1430, 1431, 1432, 1433, 1434, 1435, 1436, 1437, 1438, 1439, 1440, 1441, 1442, 1443, 1444, 1445, 1446, 1447, 1448, 1449, 1450, 1451, 1452, 1453, 1454, 1455, 1456, 1457, 1458, 1459, 1460, 1461, 1462, 1463, 1464, 1465, 1466, 1467, 1468, 1469, 1470, 1471, 1472, 1473, 1474, 1475, 1476, 1477, 1478, 1479, 1480, 1481, 1482, 1483, 1484, 1485, 1486]], + ["MS", [1487, 1488, 1489, 1490, 1491, 1492, 1493, 1494, 1495, 1496, 1497, 1498, 1499, 1500, 1501, 1502, 1503, 1504, 1505, 1506, 1507, 1508, 1509, 1510, 1511, 1512, 1513, 1514, 1515, 1516, 1517, 1518, 1519, 1520, 1521, 1522, 1523, 1524, 1525, 1526, 1527, 1528, 1529, 1530, 1531, 1532, 1533, 1534, 1535, 1536, 1537, 1538, 1539, 1540, 1541, 1542, 1543, 1544, 1545, 1546, 1547, 1548, 1549, 1550, 1551, 1552, 1553, 1554, 1555, 1556, 1557, 1558, 1559, 1560, 1561, 1562, 1563, 1564, 1565]], + ["MG", [1566, 1567, 1568, 1569, 1570, 1571, 1572, 1573, 1574, 1575, 1576, 1577, 1578, 1579, 1580, 1581, 1582, 1583, 1584, 1585, 1586, 1587, 1588, 1589, 1590, 1591, 1592, 1593, 1594, 1595, 1596, 1597, 1598, 1599, 1600, 1601, 1602, 1603, 1604, 1605, 1606, 1607, 1608, 1609, 1610, 1611, 1612, 1613, 1614, 1615, 1616, 1617, 1618, 1619, 1620, 1621, 1622, 1623, 1624, 1625, 1626, 1627, 1628, 1629, 1630, 1631, 1632, 1633, 1634, 1635, 1636, 1637, 1638, 1639, 1640, 1641, 1642, 1643, 1644, 1645, 1646, 1647, 1648, 1649, 1650, 1651, 1652, 1653, 1654, 1655, 1656, 1657, 1658, 1659, 1660, 1661, 1662, 1663, 1664, 1665, 1666, 1667, 1668, 1669, 1670, 1671, 1672, 1673, 1674, 1675, 1676, 1677, 1678, 1679, 1680, 1681, 1682, 1683, 1684, 1685, 1686, 1687, 1688, 1689, 1690, 1691, 1692, 1693, 1694, 1695, 1696, 1697, 1698, 1699, 1700, 1701, 1702, 1703, 1704, 1705, 1706, 1707, 1708, 1709, 1710, 1711, 1712, 1713, 1714, 1715, 1716, 1717, 1718, 1719, 1720, 1721, 1722, 1723, 1724, 1725, 1726, 1727, 1728, 1729, 1730, 1731, 1732, 1733, 1734, 1735, 1736, 1737, 1738, 1739, 1740, 1741, 1742, 1743, 1744, 1745, 1746, 1747, 1748, 1749, 1750, 1751, 1752, 1753, 1754, 1755, 1756, 1757, 1758, 1759, 1760, 1761, 1762, 1763, 1764, 1765, 1766, 1767, 1768, 1769, 1770, 1771, 1772, 1773, 1774, 1775, 1776, 1777, 1778, 1779, 1780, 1781, 1782, 1783, 1784, 1785, 1786, 1787, 1788, 1789, 1790, 1791, 1792, 1793, 1794, 1795, 1796, 1797, 1798, 1799, 1800, 1801, 1802, 1803, 1804, 1805, 1806, 1807, 1808, 1809, 1810, 1811, 1812, 1813, 1814, 1815, 1816, 1817, 1818, 1819, 1820, 1821, 1822, 1823, 1824, 1825, 1826, 1827, 1828, 1829, 1830, 1831, 1832, 1833, 1834, 1835, 1836, 1837, 1838, 1839, 1840, 1841, 1842, 1843, 1844, 1845, 1846, 1847, 1848, 1849, 1850, 1851, 1852, 1853, 1854, 1855, 1856, 1857, 1858, 1859, 1860, 1861, 1862, 1863, 1864, 1865, 1866, 1867, 1868, 1869, 1870, 1871, 1872, 1873, 1874, 1875, 1876, 1877, 1878, 1879, 1880, 1881, 1882, 1883, 1884, 1885, 1886, 1887, 1888, 1889, 1890, 1891, 1892, 1893, 1894, 1895, 1896, 1897, 1898, 1899, 1900, 1901, 1902, 1903, 1904, 1905, 1906, 1907, 1908, 1909, 1910, 1911, 1912, 1913, 1914, 1915, 1916, 1917, 1918, 1919, 1920, 1921, 1922, 1923, 1924, 1925, 1926, 1927, 1928, 1929, 1930, 1931, 1932, 1933, 1934, 1935, 1936, 1937, 1938, 1939, 1940, 1941, 1942, 1943, 1944, 1945, 1946, 1947, 1948, 1949, 1950, 1951, 1952, 1953, 1954, 1955, 1956, 1957, 1958, 1959, 1960, 1961, 1962, 1963, 1964, 1965, 1966, 1967, 1968, 1969, 1970, 1971, 1972, 1973, 1974, 1975, 1976, 1977, 1978, 1979, 1980, 1981, 1982, 1983, 1984, 1985, 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020, 2021, 2022, 2023, 2024, 2025, 2026, 2027, 2028, 2029, 2030, 2031, 2032, 2033, 2034, 2035, 2036, 2037, 2038, 2039, 2040, 2041, 2042, 2043, 2044, 2045, 2046, 2047, 2048, 2049, 2050, 2051, 2052, 2053, 2054, 2055, 2056, 2057, 2058, 2059, 2060, 2061, 2062, 2063, 2064, 2065, 2066, 2067, 2068, 2069, 2070, 2071, 2072, 2073, 2074, 2075, 2076, 2077, 2078, 2079, 2080, 2081, 2082, 2083, 2084, 2085, 2086, 2087, 2088, 2089, 2090, 2091, 2092, 2093, 2094, 2095, 2096, 2097, 2098, 2099, 2100, 2101, 2102, 2103, 2104, 2105, 2106, 2107, 2108, 2109, 2110, 2111, 2112, 2113, 2114, 2115, 2116, 2117, 2118, 2119, 2120, 2121, 2122, 2123, 2124, 2125, 2126, 2127, 2128, 2129, 2130, 2131, 2132, 2133, 2134, 2135, 2136, 2137, 2138, 2139, 2140, 2141, 2142, 2143, 2144, 2145, 2146, 2147, 2148, 2149, 2150, 2151, 2152, 2153, 2154, 2155, 2156, 2157, 2158, 2159, 2160, 2161, 2162, 2163, 2164, 2165, 2166, 2167, 2168, 2169, 2170, 2171, 2172, 2173, 2174, 2175, 2176, 2177, 2178, 2179, 2180, 2181, 2182, 2183, 2184, 2185, 2186, 2187, 2188, 2189, 2190, 2191, 2192, 2193, 2194, 2195, 2196, 2197, 2198, 2199, 2200, 2201, 2202, 2203, 2204, 2205, 2206, 2207, 2208, 2209, 2210, 2211, 2212, 2213, 2214, 2215, 2216, 2217, 2218, 2219, 2220, 2221, 2222, 2223, 2224, 2225, 2226, 2227, 2228, 2229, 2230, 2231, 2232, 2233, 2234, 2235, 2236, 2237, 2238, 2239, 2240, 2241, 2242, 2243, 2244, 2245, 2246, 2247, 2248, 2249, 2250, 2251, 2252, 2253, 2254, 2255, 2256, 2257, 2258, 2259, 2260, 2261, 2262, 2263, 2264, 2265, 2266, 2267, 2268, 2269, 2270, 2271, 2272, 2273, 2274, 2275, 2276, 2277, 2278, 2279, 2280, 2281, 2282, 2283, 2284, 2285, 2286, 2287, 2288, 2289, 2290, 2291, 2292, 2293, 2294, 2295, 2296, 2297, 2298, 2299, 2300, 2301, 2302, 2303, 2304, 2305, 2306, 2307, 2308, 2309, 2310, 2311, 2312, 2313, 2314, 2315, 2316, 2317, 2318, 2319, 2320, 2321, 2322, 2323, 2324, 2325, 2326, 2327, 2328, 2329, 2330, 2331, 2332, 2333, 2334, 2335, 2336, 2337, 2338, 2339, 2340, 2341, 2342, 2343, 2344, 2345, 2346, 2347, 2348, 2349, 2350, 2351, 2352, 2353, 2354, 2355, 2356, 2357, 2358, 2359, 2360, 2361, 2362, 2363, 2364, 2365, 2366, 2367, 2368, 2369, 2370, 2371, 2372, 2373, 2374, 2375, 2376, 2377, 2378, 2379, 2380, 2381, 2382, 2383, 2384, 2385, 2386, 2387, 2388, 2389, 2390, 2391, 2392, 2393, 2394, 2395, 2396, 2397, 2398, 2399, 2400, 2401, 2402, 2403, 2404, 2405, 2406, 2407, 2408, 2409, 2410, 2411, 2412, 2413, 2414, 2415, 2416, 2417, 2418]], + ["PA", [2419, 2420, 2421, 2422, 2423, 2424, 2425, 2426, 2427, 2428, 2429, 2430, 2431, 2432, 2433, 2434, 2435, 2436, 2437, 2438, 2439, 2440, 2441, 2442, 2443, 2444, 2445, 2446, 2447, 2448, 2449, 2450, 2451, 2452, 2453, 2454, 2455, 2456, 2457, 2458, 2459, 2460, 2461, 2462, 2463, 2464, 2465, 2466, 2467, 2468, 2469, 2470, 2471, 2472, 2473, 2474, 2475, 2476, 2477, 2478, 2479, 2480, 2481, 2482, 2483, 2484, 2485, 2486, 2487, 2488, 2489, 2490, 2491, 2492, 2493, 2494, 2495, 2496, 2497, 2498, 2499, 2500, 2501, 2502, 2503, 2504, 2505, 2506, 2507, 2508, 2509, 2510, 2511, 2512, 2513, 2514, 2515, 2516, 2517, 2518, 2519, 2520, 2521, 2522, 2523, 2524, 2525, 2526, 2527, 2528, 2529, 2530, 2531, 2532, 2533, 2534, 2535, 2536, 2537, 2538, 2539, 2540, 2541, 2542, 2543, 2544, 2545, 2546, 2547, 2548, 2549, 2550, 2551, 2552, 2553, 2554, 2555, 2556, 2557, 2558, 2559, 2560, 2561, 2562]], + ["PB", [2563, 2564, 2565, 2566, 2567, 2568, 2569, 2570, 2571, 2572, 2573, 2574, 2575, 2576, 2577, 2578, 2579, 2580, 2581, 2582, 2583, 2584, 2585, 2586, 2587, 2588, 2589, 2590, 2591, 2592, 2593, 2594, 2595, 2596, 2597, 2598, 2599, 2600, 2601, 2602, 2603, 2604, 2605, 2606, 2607, 2608, 2609, 2610, 2611, 2612, 2613, 2614, 2615, 2616, 2617, 2618, 2619, 2620, 2621, 2622, 2623, 2624, 2625, 2626, 2627, 2628, 2629, 2630, 2631, 2632, 2633, 2634, 2635, 2636, 2637, 2638, 2639, 2640, 2641, 2642, 2643, 2644, 2645, 2646, 2647, 2648, 2649, 2650, 2651, 2652, 2653, 2654, 2655, 2656, 2657, 2658, 2659, 2660, 2661, 2662, 2663, 2664, 2665, 2666, 2667, 2668, 2669, 2670, 2671, 2672, 2673, 2674, 2675, 2676, 2677, 2678, 2679, 2680, 2681, 2682, 2683, 2684, 2685, 2686, 2687, 2688, 2689, 2690, 2691, 2692, 2693, 2694, 2695, 2696, 2697, 2698, 2699, 2700, 2701, 2702, 2703, 2704, 2705, 2706, 2707, 2708, 2709, 2710, 2711, 2712, 2713, 2714, 2715, 2716, 2717, 2718, 2719, 2720, 2721, 2722, 2723, 2724, 2725, 2726, 2727, 2728, 2729, 2730, 2731, 2732, 2733, 2734, 2735, 2736, 2737, 2738, 2739, 2740, 2741, 2742, 2743, 2744, 2745, 2746, 2747, 2748, 2749, 2750, 2751, 2752, 2753, 2754, 2755, 2756, 2757, 2758, 2759, 2760, 2761, 2762, 2763, 2764, 2765, 2766, 2767, 2768, 2769, 2770, 2771, 2772, 2773, 2774, 2775, 2776, 2777, 2778, 2779, 2780, 2781, 2782, 2783, 2784, 2785]], + ["PR", [2786, 2787, 2788, 2789, 2790, 2791, 2792, 2793, 2794, 2795, 2796, 2797, 2798, 2799, 2800, 2801, 2802, 2803, 2804, 2805, 2806, 2807, 2808, 2809, 2810, 2811, 2812, 2813, 2814, 2815, 2816, 2817, 2818, 2819, 2820, 2821, 2822, 2823, 2824, 2825, 2826, 2827, 2828, 2829, 2830, 2831, 2832, 2833, 2834, 2835, 2836, 2837, 2838, 2839, 2840, 2841, 2842, 2843, 2844, 2845, 2846, 2847, 2848, 2849, 2850, 2851, 2852, 2853, 2854, 2855, 2856, 2857, 2858, 2859, 2860, 2861, 2862, 2863, 2864, 2865, 2866, 2867, 2868, 2869, 2870, 2871, 2872, 2873, 2874, 2875, 2876, 2877, 2878, 2879, 2880, 2881, 2882, 2883, 2884, 2885, 2886, 2887, 2888, 2889, 2890, 2891, 2892, 2893, 2894, 2895, 2896, 2897, 2898, 2899, 2900, 2901, 2902, 2903, 2904, 2905, 2906, 2907, 2908, 2909, 2910, 2911, 2912, 2913, 2914, 2915, 2916, 2917, 2918, 2919, 2920, 2921, 2922, 2923, 2924, 2925, 2926, 2927, 2928, 2929, 2930, 2931, 2932, 2933, 2934, 2935, 2936, 2937, 2938, 2939, 2940, 2941, 2942, 2943, 2944, 2945, 2946, 2947, 2948, 2949, 2950, 2951, 2952, 2953, 2954, 2955, 2956, 2957, 2958, 2959, 2960, 2961, 2962, 2963, 2964, 2965, 2966, 2967, 2968, 2969, 2970, 2971, 2972, 2973, 2974, 2975, 2976, 2977, 2978, 2979, 2980, 2981, 2982, 2983, 2984, 2985, 2986, 2987, 2988, 2989, 2990, 2991, 2992, 2993, 2994, 2995, 2996, 2997, 2998, 2999, 3000, 3001, 3002, 3003, 3004, 3005, 3006, 3007, 3008, 3009, 3010, 3011, 3012, 3013, 3014, 3015, 3016, 3017, 3018, 3019, 3020, 3021, 3022, 3023, 3024, 3025, 3026, 3027, 3028, 3029, 3030, 3031, 3032, 3033, 3034, 3035, 3036, 3037, 3038, 3039, 3040, 3041, 3042, 3043, 3044, 3045, 3046, 3047, 3048, 3049, 3050, 3051, 3052, 3053, 3054, 3055, 3056, 3057, 3058, 3059, 3060, 3061, 3062, 3063, 3064, 3065, 3066, 3067, 3068, 3069, 3070, 3071, 3072, 3073, 3074, 3075, 3076, 3077, 3078, 3079, 3080, 3081, 3082, 3083, 3084, 3085, 3086, 3087, 3088, 3089, 3090, 3091, 3092, 3093, 3094, 3095, 3096, 3097, 3098, 3099, 3100, 3101, 3102, 3103, 3104, 3105, 3106, 3107, 3108, 3109, 3110, 3111, 3112, 3113, 3114, 3115, 3116, 3117, 3118, 3119, 3120, 3121, 3122, 3123, 3124, 3125, 3126, 3127, 3128, 3129, 3130, 3131, 3132, 3133, 3134, 3135, 3136, 3137, 3138, 3139, 3140, 3141, 3142, 3143, 3144, 3145, 3146, 3147, 3148, 3149, 3150, 3151, 3152, 3153, 3154, 3155, 3156, 3157, 3158, 3159, 3160, 3161, 3162, 3163, 3164, 3165, 3166, 3167, 3168, 3169, 3170, 3171, 3172, 3173, 3174, 3175, 3176, 3177, 3178, 3179, 3180, 3181, 3182, 3183, 3184]], + ["PE", [3185, 3186, 3187, 3188, 3189, 3190, 3191, 3192, 3193, 3194, 3195, 3196, 3197, 3198, 3199, 3200, 3201, 3202, 3203, 3204, 3205, 3206, 3207, 3208, 3209, 3210, 3211, 3212, 3213, 3214, 3215, 3216, 3217, 3218, 3219, 3220, 3221, 3222, 3223, 3224, 3225, 3226, 3227, 3228, 3229, 3230, 3231, 3232, 3233, 3234, 3235, 3236, 3237, 3238, 3239, 3240, 3241, 3242, 3243, 3244, 3245, 3246, 3247, 3248, 3249, 3250, 3251, 3252, 3253, 3254, 3255, 3256, 3257, 3258, 3259, 3260, 3261, 3262, 3263, 3264, 3265, 3266, 3267, 3268, 3269, 3270, 3271, 3272, 3273, 3274, 3275, 3276, 3277, 3278, 3279, 3280, 3281, 3282, 3283, 3284, 3285, 3286, 3287, 3288, 3289, 3290, 3291, 3292, 3293, 3294, 3295, 3296, 3297, 3298, 3299, 3300, 3301, 3302, 3303, 3304, 3305, 3306, 3307, 3308, 3309, 3310, 3311, 3312, 3313, 3314, 3315, 3316, 3317, 3318, 3319, 3320, 3321, 3322, 3323, 3324, 3325, 3326, 3327, 3328, 3329, 3330, 3331, 3332, 3333, 3334, 3335, 3336, 3337, 3338, 3339, 3340, 3341, 3342, 3343, 3344, 3345, 3346, 3347, 3348, 3349, 3350, 3351, 3352, 3353, 3354, 3355, 3356, 3357, 3358, 3359, 3360, 3361, 3362, 3363, 3364, 3365, 3366, 3367, 3368, 3369]], + ["PI", [3370, 3371, 3372, 3373, 3374, 3375, 3376, 3377, 3378, 3379, 3380, 3381, 3382, 3383, 3384, 3385, 3386, 3387, 3388, 3389, 3390, 3391, 3392, 3393, 3394, 3395, 3396, 3397, 3398, 3399, 3400, 3401, 3402, 3403, 3404, 3405, 3406, 3407, 3408, 3409, 3410, 3411, 3412, 3413, 3414, 3415, 3416, 3417, 3418, 3419, 3420, 3421, 3422, 3423, 3424, 3425, 3426, 3427, 3428, 3429, 3430, 3431, 3432, 3433, 3434, 3435, 3436, 3437, 3438, 3439, 3440, 3441, 3442, 3443, 3444, 3445, 3446, 3447, 3448, 3449, 3450, 3451, 3452, 3453, 3454, 3455, 3456, 3457, 3458, 3459, 3460, 3461, 3462, 3463, 3464, 3465, 3466, 3467, 3468, 3469, 3470, 3471, 3472, 3473, 3474, 3475, 3476, 3477, 3478, 3479, 3480, 3481, 3482, 3483, 3484, 3485, 3486, 3487, 3488, 3489, 3490, 3491, 3492, 3493, 3494, 3495, 3496, 3497, 3498, 3499, 3500, 3501, 3502, 3503, 3504, 3505, 3506, 3507, 3508, 3509, 3510, 3511, 3512, 3513, 3514, 3515, 3516, 3517, 3518, 3519, 3520, 3521, 3522, 3523, 3524, 3525, 3526, 3527, 3528, 3529, 3530, 3531, 3532, 3533, 3534, 3535, 3536, 3537, 3538, 3539, 3540, 3541, 3542, 3543, 3544, 3545, 3546, 3547, 3548, 3549, 3550, 3551, 3552, 3553, 3554, 3555, 3556, 3557, 3558, 3559, 3560, 3561, 3562, 3563, 3564, 3565, 3566, 3567, 3568, 3569, 3570, 3571, 3572, 3573, 3574, 3575, 3576, 3577, 3578, 3579, 3580, 3581, 3582, 3583, 3584, 3585, 3586, 3587, 3588, 3589, 3590, 3591, 3592, 3593]], + ["RJ", [3594, 3595, 3596, 3597, 3598, 3599, 3600, 3601, 3602, 3603, 3604, 3605, 3606, 3607, 3608, 3609, 3610, 3611, 3612, 3613, 3614, 3615, 3616, 3617, 3618, 3619, 3620, 3621, 3622, 3623, 3624, 3625, 3626, 3627, 3628, 3629, 3630, 3631, 3632, 3633, 3634, 3635, 3636, 3637, 3638, 3639, 3640, 3641, 3642, 3643, 3644, 3645, 3646, 3647, 3648, 3649, 3650, 3651, 3652, 3653, 3654, 3655, 3656, 3657, 3658, 3659, 3660, 3661, 3662, 3663, 3664, 3665, 3666, 3667, 3668, 3669, 3670, 3671, 3672, 3673, 3674, 3675, 3676, 3677, 3678, 3679, 3680, 3681, 3682, 3683, 3684, 3685]], + ["RN", [3686, 3687, 3688, 3689, 3690, 3691, 3692, 3693, 3694, 3695, 3696, 3697, 3698, 3699, 3700, 3701, 3702, 3703, 3704, 3705, 3706, 3707, 3708, 3709, 3710, 3711, 3712, 3713, 3714, 3715, 3716, 3717, 3718, 3719, 3720, 3721, 3722, 3723, 3724, 3725, 3726, 3727, 3728, 3729, 3730, 3731, 3732, 3733, 3734, 3735, 3736, 3737, 3738, 3739, 3740, 3741, 3742, 3743, 3744, 3745, 3746, 3747, 3748, 3749, 3750, 3751, 3752, 3753, 3754, 3755, 3756, 3757, 3758, 3759, 3760, 3761, 3762, 3763, 3764, 3765, 3766, 3767, 3768, 3769, 3770, 3771, 3772, 3773, 3774, 3775, 3776, 3777, 3778, 3779, 3780, 3781, 3782, 3783, 3784, 3785, 3786, 3787, 3788, 3789, 3790, 3791, 3792, 3793, 3794, 3795, 3796, 3797, 3798, 3799, 3800, 3801, 3802, 3803, 3804, 3805, 3806, 3807, 3808, 3809, 3810, 3811, 3812, 3813, 3814, 3815, 3816, 3817, 3818, 3819, 3820, 3821, 3822, 3823, 3824, 3825, 3826, 3827, 3828, 3829, 3830, 3831, 3832, 3833, 3834, 3835, 3836, 3837, 3838, 3839, 3840, 3841, 3842, 3843, 3844, 3845, 3846, 3847, 3848, 3849, 3850, 3851, 3852]], + ["RS", [3853, 3854, 3855, 3856, 3857, 3858, 3859, 3860, 3861, 3862, 3863, 3864, 3865, 3866, 3867, 3868, 3869, 3870, 3871, 3872, 3873, 3874, 3875, 3876, 3877, 3878, 3879, 3880, 3881, 3882, 3883, 3884, 3885, 3886, 3887, 3888, 3889, 3890, 3891, 3892, 3893, 3894, 3895, 3896, 3897, 3898, 3899, 3900, 3901, 3902, 3903, 3904, 3905, 3906, 3907, 3908, 3909, 3910, 3911, 3912, 3913, 3914, 3915, 3916, 3917, 3918, 3919, 3920, 3921, 3922, 3923, 3924, 3925, 3926, 3927, 3928, 3929, 3930, 3931, 3932, 3933, 3934, 3935, 3936, 3937, 3938, 3939, 3940, 3941, 3942, 3943, 3944, 3945, 3946, 3947, 3948, 3949, 3950, 3951, 3952, 3953, 3954, 3955, 3956, 3957, 3958, 3959, 3960, 3961, 3962, 3963, 3964, 3965, 3966, 3967, 3968, 3969, 3970, 3971, 3972, 3973, 3974, 3975, 3976, 3977, 3978, 3979, 3980, 3981, 3982, 3983, 3984, 3985, 3986, 3987, 3988, 3989, 3990, 3991, 3992, 3993, 3994, 3995, 3996, 3997, 3998, 3999, 4000, 4001, 4002, 4003, 4004, 4005, 4006, 4007, 4008, 4009, 4010, 4011, 4012, 4013, 4014, 4015, 4016, 4017, 4018, 4019, 4020, 4021, 4022, 4023, 4024, 4025, 4026, 4027, 4028, 4029, 4030, 4031, 4032, 4033, 4034, 4035, 4036, 4037, 4038, 4039, 4040, 4041, 4042, 4043, 4044, 4045, 4046, 4047, 4048, 4049, 4050, 4051, 4052, 4053, 4054, 4055, 4056, 4057, 4058, 4059, 4060, 4061, 4062, 4063, 4064, 4065, 4066, 4067, 4068, 4069, 4070, 4071, 4072, 4073, 4074, 4075, 4076, 4077, 4078, 4079, 4080, 4081, 4082, 4083, 4084, 4085, 4086, 4087, 4088, 4089, 4090, 4091, 4092, 4093, 4094, 4095, 4096, 4097, 4098, 4099, 4100, 4101, 4102, 4103, 4104, 4105, 4106, 4107, 4108, 4109, 4110, 4111, 4112, 4113, 4114, 4115, 4116, 4117, 4118, 4119, 4120, 4121, 4122, 4123, 4124, 4125, 4126, 4127, 4128, 4129, 4130, 4131, 4132, 4133, 4134, 4135, 4136, 4137, 4138, 4139, 4140, 4141, 4142, 4143, 4144, 4145, 4146, 4147, 4148, 4149, 4150, 4151, 4152, 4153, 4154, 4155, 4156, 4157, 4158, 4159, 4160, 4161, 4162, 4163, 4164, 4165, 4166, 4167, 4168, 4169, 4170, 4171, 4172, 4173, 4174, 4175, 4176, 4177, 4178, 4179, 4180, 4181, 4182, 4183, 4184, 4185, 4186, 4187, 4188, 4189, 4190, 4191, 4192, 4193, 4194, 4195, 4196, 4197, 4198, 4199, 4200, 4201, 4202, 4203, 4204, 4205, 4206, 4207, 4208, 4209, 4210, 4211, 4212, 4213, 4214, 4215, 4216, 4217, 4218, 4219, 4220, 4221, 4222, 4223, 4224, 4225, 4226, 4227, 4228, 4229, 4230, 4231, 4232, 4233, 4234, 4235, 4236, 4237, 4238, 4239, 4240, 4241, 4242, 4243, 4244, 4245, 4246, 4247, 4248, 4249, 4250, 4251, 4252, 4253, 4254, 4255, 4256, 4257, 4258, 4259, 4260, 4261, 4262, 4263, 4264, 4265, 4266, 4267, 4268, 4269, 4270, 4271, 4272, 4273, 4274, 4275, 4276, 4277, 4278, 4279, 4280, 4281, 4282, 4283, 4284, 4285, 4286, 4287, 4288, 4289, 4290, 4291, 4292, 4293, 4294, 4295, 4296, 4297, 4298, 4299, 4300, 4301, 4302, 4303, 4304, 4305, 4306, 4307, 4308, 4309, 4310, 4311, 4312, 4313, 4314, 4315, 4316, 4317, 4318, 4319, 4320, 4321, 4322, 4323, 4324, 4325, 4326, 4327, 4328, 4329, 4330, 4331, 4332, 4333, 4334, 4335, 4336, 4337, 4338, 4339, 4340, 4341, 4342, 4343, 4344, 4345, 4346, 4347, 4348, 4349]], + ["RO", [4350, 4351, 4352, 4353, 4354, 4355, 4356, 4357, 4358, 4359, 4360, 4361, 4362, 4363, 4364, 4365, 4366, 4367, 4368, 4369, 4370, 4371, 4372, 4373, 4374, 4375, 4376, 4377, 4378, 4379, 4380, 4381, 4382, 4383, 4384, 4385, 4386, 4387, 4388, 4389, 4390, 4391, 4392, 4393, 4394, 4395, 4396, 4397, 4398, 4399, 4400, 4401]], + ["RR", [4402, 4403, 4404, 4405, 4406, 4407, 4408, 4409, 4410, 4411, 4412, 4413, 4414, 4415, 4416]], + ["SC", [4417, 4418, 4419, 4420, 4421, 4422, 4423, 4424, 4425, 4426, 4427, 4428, 4429, 4430, 4431, 4432, 4433, 4434, 4435, 4436, 4437, 4438, 4439, 4440, 4441, 4442, 4443, 4444, 4445, 4446, 4447, 4448, 4449, 4450, 4451, 4452, 4453, 4454, 4455, 4456, 4457, 4458, 4459, 4460, 4461, 4462, 4463, 4464, 4465, 4466, 4467, 4468, 4469, 4470, 4471, 4472, 4473, 4474, 4475, 4476, 4477, 4478, 4479, 4480, 4481, 4482, 4483, 4484, 4485, 4486, 4487, 4488, 4489, 4490, 4491, 4492, 4493, 4494, 4495, 4496, 4497, 4498, 4499, 4500, 4501, 4502, 4503, 4504, 4505, 4506, 4507, 4508, 4509, 4510, 4511, 4512, 4513, 4514, 4515, 4516, 4517, 4518, 4519, 4520, 4521, 4522, 4523, 4524, 4525, 4526, 4527, 4528, 4529, 4530, 4531, 4532, 4533, 4534, 4535, 4536, 4537, 4538, 4539, 4540, 4541, 4542, 4543, 4544, 4545, 4546, 4547, 4548, 4549, 4550, 4551, 4552, 4553, 4554, 4555, 4556, 4557, 4558, 4559, 4560, 4561, 4562, 4563, 4564, 4565, 4566, 4567, 4568, 4569, 4570, 4571, 4572, 4573, 4574, 4575, 4576, 4577, 4578, 4579, 4580, 4581, 4582, 4583, 4584, 4585, 4586, 4587, 4588, 4589, 4590, 4591, 4592, 4593, 4594, 4595, 4596, 4597, 4598, 4599, 4600, 4601, 4602, 4603, 4604, 4605, 4606, 4607, 4608, 4609, 4610, 4611, 4612, 4613, 4614, 4615, 4616, 4617, 4618, 4619, 4620, 4621, 4622, 4623, 4624, 4625, 4626, 4627, 4628, 4629, 4630, 4631, 4632, 4633, 4634, 4635, 4636, 4637, 4638, 4639, 4640, 4641, 4642, 4643, 4644, 4645, 4646, 4647, 4648, 4649, 4650, 4651, 4652, 4653, 4654, 4655, 4656, 4657, 4658, 4659, 4660, 4661, 4662, 4663, 4664, 4665, 4666, 4667, 4668, 4669, 4670, 4671, 4672, 4673, 4674, 4675, 4676, 4677, 4678, 4679, 4680, 4681, 4682, 4683, 4684, 4685, 4686, 4687, 4688, 4689, 4690, 4691, 4692, 4693, 4694, 4695, 4696, 4697, 4698, 4699, 4700, 4701, 4702, 4703, 4704, 4705, 4706, 4707, 4708, 4709, 4710, 4711]], + ["SP", [4712, 4713, 4714, 4715, 4716, 4717, 4718, 4719, 4720, 4721, 4722, 4723, 4724, 4725, 4726, 4727, 4728, 4729, 4730, 4731, 4732, 4733, 4734, 4735, 4736, 4737, 4738, 4739, 4740, 4741, 4742, 4743, 4744, 4745, 4746, 4747, 4748, 4749, 4750, 4751, 4752, 4753, 4754, 4755, 4756, 4757, 4758, 4759, 4760, 4761, 4762, 4763, 4764, 4765, 4766, 4767, 4768, 4769, 4770, 4771, 4772, 4773, 4774, 4775, 4776, 4777, 4778, 4779, 4780, 4781, 4782, 4783, 4784, 4785, 4786, 4787, 4788, 4789, 4790, 4791, 4792, 4793, 4794, 4795, 4796, 4797, 4798, 4799, 4800, 4801, 4802, 4803, 4804, 4805, 4806, 4807, 4808, 4809, 4810, 4811, 4812, 4813, 4814, 4815, 4816, 4817, 4818, 4819, 4820, 4821, 4822, 4823, 4824, 4825, 4826, 4827, 4828, 4829, 4830, 4831, 4832, 4833, 4834, 4835, 4836, 4837, 4838, 4839, 4840, 4841, 4842, 4843, 4844, 4845, 4846, 4847, 4848, 4849, 4850, 4851, 4852, 4853, 4854, 4855, 4856, 4857, 4858, 4859, 4860, 4861, 4862, 4863, 4864, 4865, 4866, 4867, 4868, 4869, 4870, 4871, 4872, 4873, 4874, 4875, 4876, 4877, 4878, 4879, 4880, 4881, 4882, 4883, 4884, 4885, 4886, 4887, 4888, 4889, 4890, 4891, 4892, 4893, 4894, 4895, 4896, 4897, 4898, 4899, 4900, 4901, 4902, 4903, 4904, 4905, 4906, 4907, 4908, 4909, 4910, 4911, 4912, 4913, 4914, 4915, 4916, 4917, 4918, 4919, 4920, 4921, 4922, 4923, 4924, 4925, 4926, 4927, 4928, 4929, 4930, 4931, 4932, 4933, 4934, 4935, 4936, 4937, 4938, 4939, 4940, 4941, 4942, 4943, 4944, 4945, 4946, 4947, 4948, 4949, 4950, 4951, 4952, 4953, 4954, 4955, 4956, 4957, 4958, 4959, 4960, 4961, 4962, 4963, 4964, 4965, 4966, 4967, 4968, 4969, 4970, 4971, 4972, 4973, 4974, 4975, 4976, 4977, 4978, 4979, 4980, 4981, 4982, 4983, 4984, 4985, 4986, 4987, 4988, 4989, 4990, 4991, 4992, 4993, 4994, 4995, 4996, 4997, 4998, 4999, 5000, 5001, 5002, 5003, 5004, 5005, 5006, 5007, 5008, 5009, 5010, 5011, 5012, 5013, 5014, 5015, 5016, 5017, 5018, 5019, 5020, 5021, 5022, 5023, 5024, 5025, 5026, 5027, 5028, 5029, 5030, 5031, 5032, 5033, 5034, 5035, 5036, 5037, 5038, 5039, 5040, 5041, 5042, 5043, 5044, 5045, 5046, 5047, 5048, 5049, 5050, 5051, 5052, 5053, 5054, 5055, 5056, 5057, 5058, 5059, 5060, 5061, 5062, 5063, 5064, 5065, 5066, 5067, 5068, 5069, 5070, 5071, 5072, 5073, 5074, 5075, 5076, 5077, 5078, 5079, 5080, 5081, 5082, 5083, 5084, 5085, 5086, 5087, 5088, 5089, 5090, 5091, 5092, 5093, 5094, 5095, 5096, 5097, 5098, 5099, 5100, 5101, 5102, 5103, 5104, 5105, 5106, 5107, 5108, 5109, 5110, 5111, 5112, 5113, 5114, 5115, 5116, 5117, 5118, 5119, 5120, 5121, 5122, 5123, 5124, 5125, 5126, 5127, 5128, 5129, 5130, 5131, 5132, 5133, 5134, 5135, 5136, 5137, 5138, 5139, 5140, 5141, 5142, 5143, 5144, 5145, 5146, 5147, 5148, 5149, 5150, 5151, 5152, 5153, 5154, 5155, 5156, 5157, 5158, 5159, 5160, 5161, 5162, 5163, 5164, 5165, 5166, 5167, 5168, 5169, 5170, 5171, 5172, 5173, 5174, 5175, 5176, 5177, 5178, 5179, 5180, 5181, 5182, 5183, 5184, 5185, 5186, 5187, 5188, 5189, 5190, 5191, 5192, 5193, 5194, 5195, 5196, 5197, 5198, 5199, 5200, 5201, 5202, 5203, 5204, 5205, 5206, 5207, 5208, 5209, 5210, 5211, 5212, 5213, 5214, 5215, 5216, 5217, 5218, 5219, 5220, 5221, 5222, 5223, 5224, 5225, 5226, 5227, 5228, 5229, 5230, 5231, 5232, 5233, 5234, 5235, 5236, 5237, 5238, 5239, 5240, 5241, 5242, 5243, 5244, 5245, 5246, 5247, 5248, 5249, 5250, 5251, 5252, 5253, 5254, 5255, 5256, 5257, 5258, 5259, 5260, 5261, 5262, 5263, 5264, 5265, 5266, 5267, 5268, 5269, 5270, 5271, 5272, 5273, 5274, 5275, 5276, 5277, 5278, 5279, 5280, 5281, 5282, 5283, 5284, 5285, 5286, 5287, 5288, 5289, 5290, 5291, 5292, 5293, 5294, 5295, 5296, 5297, 5298, 5299, 5300, 5301, 5302, 5303, 5304, 5305, 5306, 5307, 5308, 5309, 5310, 5311, 5312, 5313, 5314, 5315, 5316, 5317, 5318, 5319, 5320, 5321, 5322, 5323, 5324, 5325, 5326, 5327, 5328, 5329, 5330, 5331, 5332, 5333, 5334, 5335, 5336, 5337, 5338, 5339, 5340, 5341, 5342, 5343, 5344, 5345, 5346, 5347, 5348, 5349, 5350, 5351, 5352, 5353, 5354, 5355, 5356]], + ["SE", [5357, 5358, 5359, 5360, 5361, 5362, 5363, 5364, 5365, 5366, 5367, 5368, 5369, 5370, 5371, 5372, 5373, 5374, 5375, 5376, 5377, 5378, 5379, 5380, 5381, 5382, 5383, 5384, 5385, 5386, 5387, 5388, 5389, 5390, 5391, 5392, 5393, 5394, 5395, 5396, 5397, 5398, 5399, 5400, 5401, 5402, 5403, 5404, 5405, 5406, 5407, 5408, 5409, 5410, 5411, 5412, 5413, 5414, 5415, 5416, 5417, 5418, 5419, 5420, 5421, 5422, 5423, 5424, 5425, 5426, 5427, 5428, 5429, 5430, 5431]], + ["TO", [5432, 5433, 5434, 5435, 5436, 5437, 5438, 5439, 5440, 5441, 5442, 5443, 5444, 5445, 5446, 5447, 5448, 5449, 5450, 5451, 5452, 5453, 5454, 5455, 5456, 5457, 5458, 5459, 5460, 5461, 5462, 5463, 5464, 5465, 5466, 5467, 5468, 5469, 5470, 5471, 5472, 5473, 5474, 5475, 5476, 5477, 5478, 5479, 5480, 5481, 5482, 5483, 5484, 5485, 5486, 5487, 5488, 5489, 5490, 5491, 5492, 5493, 5494, 5495, 5496, 5497, 5498, 5499, 5500, 5501, 5502, 5503, 5504, 5505, 5506, 5507, 5508, 5509, 5510, 5511, 5512, 5513, 5514, 5515, 5516, 5517, 5518, 5519, 5520, 5521, 5522, 5523, 5524, 5525, 5526, 5527, 5528, 5529, 5530, 5531, 5532, 5533, 5534, 5535, 5536, 5537, 5538, 5539, 5540, 5541, 5542, 5543, 5544, 5545, 5546, 5547, 5548, 5549, 5550, 5551, 5552, 5553, 5554, 5555, 5556, 5557, 5558, 5559, 5560, 5561, 5562, 5563, 5564, 5565, 5566, 5567, 5568, 5569, 5570]], + ], + [882, 1566, 883, 1567, 2419, 619, 202, 203, 2786, 4417, 2420, 4418, 1568, 3185, 5432, 1569, 1128, 204, 2421, 620, 621, 3686, 3370, 3853, 622, 1345, 0, 884, 1570, 4712, 885, 4713, 2787, 205, 3186, 3687, 804, 1129, 3187, 2422, 3188, 3371, 4419, 4420, 2423, 1346, 1571, 22, 2563, 3372, 1487, 1572, 4421, 1130, 805, 206, 886, 887, 3688, 3189, 3854, 4714, 1573, 3190, 4715, 4422, 4716, 4717, 4718, 1574, 4423, 888, 4424, 1575, 3855, 4719, 2788, 806, 2564, 5433, 1576, 207, 623, 1577, 3856, 1578, 2565, 2566, 2567, 3191, 3373, 208, 4720, 1579, 1131, 624, 2568, 1488, 209, 1132, 3857, 807, 3858, 3374, 3859, 1580, 2424, 3689, 889, 1581, 808, 4721, 1582, 4425, 2569, 2570, 3192, 5434, 210, 5435, 2425, 1583, 3690, 2789, 3860, 890, 1584, 3861, 1585, 1347, 4350, 4722, 2426, 1133, 2790, 625, 1586, 3193, 4723, 3862, 4402, 4724, 1134, 1135, 4351, 1348, 4426, 1349, 1587, 3691, 3863, 1350, 891, 1588, 3375, 1351, 2791, 4352, 892, 2792, 1136, 2793, 1589, 809, 626, 1352, 2794, 3376, 4725, 140, 1590, 4726, 4727, 4728, 4729, 1591, 3864, 5436, 4353, 1592, 3377, 893, 2795, 4403, 1489, 124, 1137, 2796, 3194, 3865, 894, 3378, 1138, 211, 141, 212, 213, 4730, 895, 4731, 4732, 3866, 627, 896, 2571, 4733, 5357, 1593, 2797, 23, 214, 2798, 2427, 1139, 4734, 142, 5437, 2428, 897, 2429, 1140, 1490, 1491, 810, 4427, 215, 2799, 216, 1594, 4735, 3867, 1595, 4736, 1596, 1492, 3195, 4428, 217, 3379, 5438, 3692, 3594, 218, 2800, 898, 4737, 4738, 899, 3380, 4429, 4430, 143, 3868, 219, 2801, 628, 3381, 220, 1597, 4431, 1598, 221, 1493, 3693, 2802, 3869, 1599, 2572, 4739, 4740, 900, 901, 5439, 1494, 3595, 811, 1353, 4741, 1141, 4432, 3694, 222, 902, 223, 2803, 144, 629, 5358, 1495, 630, 4433, 2573, 1600, 5359, 4742, 224, 631, 225, 4743, 226, 1601, 632, 3196, 4744, 812, 903, 1602, 904, 905, 5440, 5441, 5442, 1354, 5443, 1355, 1142, 5444, 906, 1603, 5445, 1143, 1496, 227, 3870, 1144, 4745, 4746, 1604, 4747, 24, 5446, 1605, 2804, 1606, 2805, 1607, 2806, 1356, 4434, 2574, 4435, 4748, 4749, 633, 1145, 3871, 634, 3197, 3596, 2575, 2807, 228, 3872, 635, 229, 5360, 2808, 1608, 1609, 1610, 4750, 1611, 3198, 1612, 3597, 4751, 2576, 3695, 5361, 2577, 2578, 4752, 4753, 1357, 907, 3696, 1613, 1614, 1615, 1358, 4354, 4754, 2809, 3598, 4436, 636, 3382, 2579, 3383, 3384, 3599, 5447, 3873, 3874, 3875, 3876, 3877, 3878, 4437, 4755, 908, 4756, 4438, 3879, 4439, 4757, 2810, 637, 4758, 1, 2811, 3697, 2580, 3385, 1616, 2812, 25, 2813, 145, 4440, 1617, 4759, 813, 5448, 2430, 1618, 3880, 3881, 230, 4760, 909, 638, 4441, 2431, 5449, 146, 4761, 4762, 4763, 2432, 3386, 910, 1146, 5450, 5451, 1147, 1148, 1149, 1150, 4764, 1619, 3882, 2433, 2581, 3698, 231, 2434, 232, 3387, 639, 814, 4765, 1620, 911, 4442, 4443, 4444, 4445, 4446, 3883, 4447, 2814, 4766, 1151, 1621, 640, 4767, 2582, 1622, 1623, 4448, 1497, 2815, 5452, 2435, 233, 3884, 4768, 1624, 3885, 1152, 1359, 1625, 3886, 2583, 3699, 1626, 641, 4769, 2816, 2436, 3700, 147, 4770, 234, 4449, 4771, 3388, 235, 3199, 2584, 2585, 26, 815, 27, 2586, 1360, 4772, 236, 1153, 1361, 3887, 2817, 237, 5453, 3600, 3888, 3889, 3890, 238, 4773, 5362, 3891, 1627, 3601, 4450, 2818, 3892, 3389, 642, 239, 3390, 148, 1154, 3200, 4774, 4775, 643, 240, 912, 3391, 241, 242, 5454, 644, 3893, 1628, 4776, 4777, 1498, 28, 3392, 4778, 1499, 645, 4779, 2587, 4780, 646, 647, 1500, 2819, 913, 1629, 1155, 2820, 3393, 4451, 1156, 29, 2437, 2588, 3201, 2589, 3394, 3202, 3602, 1630, 243, 4452, 244, 1631, 3203, 30, 1632, 1633, 2438, 3395, 1157, 4453, 2439, 149, 3894, 4781, 3701, 3895, 1158, 1634, 1635, 2590, 4782, 1159, 5455, 4783, 3396, 1636, 150, 3204, 3397, 1637, 3205, 1638, 1639, 4454, 4784, 1640, 4785, 4786, 245, 2821, 4455, 816, 1641, 2822, 2823, 1362, 4787, 3398, 246, 2591, 2824, 648, 2592, 4404, 2825, 3896, 3897, 3898, 1160, 3899, 151, 3900, 247, 31, 152, 3399, 4788, 1642, 4456, 1643, 2826, 3702, 3206, 1501, 4789, 4790, 3207, 1644, 1161, 3208, 3603, 4457, 914, 1645, 2593, 3400, 3703, 3901, 4458, 248, 1646, 249, 1162, 915, 1647, 1363, 1648, 3604, 817, 4459, 2827, 2440, 5456, 4791, 1163, 3902, 3401, 3903, 1649, 4460, 3904, 1650, 2594, 2828, 4792, 2829, 4461, 1651, 4405, 3402, 916, 1652, 250, 251, 1502, 2441, 3209, 1653, 2595, 917, 2596, 3905, 3403, 5363, 252, 4793, 4794, 153, 2597, 4795, 1654, 4796, 2830, 3906, 1655, 4797, 1656, 253, 4462, 3907, 4463, 4464, 3908, 2442, 4798, 2831, 32, 1657, 2443, 1503, 1658, 2832, 5457, 2, 3404, 803, 1659, 1364, 4799, 1660, 918, 1661, 3210, 818, 3211, 3704, 5458, 1164, 4800, 3212, 1165, 2598, 3405, 2599, 5364, 2444, 649, 254, 255, 2445, 2446, 919, 3909, 4801, 4802, 256, 1662, 257, 4465, 4466, 1663, 1664, 3213, 258, 1665, 3214, 3, 2447, 4803, 4804, 1166, 920, 1167, 921, 5459, 3406, 3407, 1168, 922, 259, 1169, 1666, 4355, 4805, 1667, 3910, 154, 2600, 1504, 260, 2601, 261, 1668, 923, 3408, 2602, 4356, 3215, 3605, 1669, 4806, 4807, 3216, 4467, 4808, 3911, 4357, 3912, 1365, 262, 924, 1670, 925, 1671, 1672, 2448, 2449, 3913, 2603, 926, 1673, 1170, 4809, 3606, 3217, 3914, 5460, 819, 2604, 2605, 2606, 33, 3915, 4358, 4810, 927, 263, 264, 1674, 265, 1675, 3218, 266, 267, 2833, 2834, 4811, 2835, 4812, 1676, 928, 3916, 4468, 2607, 3917, 3705, 3706, 3707, 4813, 268, 4814, 4815, 1171, 1172, 4816, 2608, 3409, 2609, 4817, 34, 3410, 1677, 4818, 3219, 125, 1678, 2610, 929, 930, 269, 3411, 2836, 4469, 3220, 270, 271, 1679, 2611, 272, 1680, 1505, 3918, 3221, 3919, 2837, 3920, 2838, 2839, 4470, 3607, 1681, 1682, 2450, 650, 3222, 1683, 1684, 35, 1685, 3921, 931, 1173, 2840, 3922, 4819, 2841, 2612, 2842, 1686, 932, 1366, 4820, 3412, 3923, 933, 36, 4471, 934, 273, 3413, 1687, 1688, 4472, 3924, 2843, 5365, 1689, 2844, 4473, 1690, 274, 37, 1506, 3708, 3414, 2845, 3415, 935, 4821, 2846, 3416, 2847, 3925, 4359, 1367, 3709, 1368, 1691, 936, 3926, 1369, 4822, 3608, 1692, 5461, 4474, 4823, 651, 937, 3223, 1693, 1694, 2451, 1370, 4824, 38, 275, 1695, 276, 1371, 4825, 3417, 277, 278, 279, 1696, 4360, 3927, 280, 2848, 3928, 1174, 4826, 4827, 281, 3929, 2849, 3930, 4475, 3710, 3931, 5366, 3224, 652, 5367, 4828, 3932, 4476, 282, 4406, 1697, 2850, 3609, 1175, 3418, 283, 3933, 155, 2452, 2851, 4477, 4829, 3934, 3935, 3936, 3937, 1698, 39, 5368, 3938, 4830, 284, 1699, 1700, 1701, 2613, 1702, 285, 1703, 4478, 1176, 653, 3939, 1704, 3419, 1705, 3420, 2852, 2453, 1706, 4831, 4479, 3940, 4, 3225, 1707, 3941, 4407, 1507, 3421, 4832, 1708, 286, 2853, 1709, 1710, 1711, 3610, 4833, 1712, 156, 2614, 3711, 3422, 287, 3942, 1713, 288, 4834, 3611, 1714, 157, 158, 820, 654, 3423, 289, 5369, 655, 5462, 656, 657, 1372, 2854, 3943, 1715, 3944, 1716, 3612, 1717, 1718, 1719, 1720, 1721, 1722, 938, 5463, 5370, 1723, 3226, 3712, 3713, 658, 3227, 1724, 40, 4408, 1177, 3228, 1725, 2615, 5464, 3229, 1178, 1726, 1727, 4835, 1728, 290, 3945, 1729, 659, 2855, 5465, 3946, 3613, 3230, 2616, 1730, 4836, 1508, 2454, 1373, 4361, 939, 821, 3424, 4837, 2856, 291, 1731, 940, 4838, 2857, 4480, 660, 1732, 1733, 3231, 4839, 2617, 292, 2618, 293, 3947, 1734, 661, 941, 294, 2619, 1735, 662, 942, 1736, 4481, 1179, 3948, 3425, 3714, 1180, 4840, 663, 3232, 5371, 1737, 4482, 3949, 5466, 2858, 295, 1738, 1181, 1739, 1182, 1183, 4362, 943, 4841, 4842, 3950, 2859, 3951, 3715, 3952, 3953, 3954, 4483, 4843, 2860, 944, 3233, 3234, 41, 1740, 1741, 3955, 5467, 5468, 1742, 1374, 1743, 945, 4484, 1509, 1184, 4485, 4844, 3956, 3957, 664, 4845, 2455, 1744, 3958, 2861, 665, 666, 296, 3959, 4363, 3960, 2862, 297, 2863, 946, 1185, 3961, 298, 1745, 3962, 1746, 1747, 1375, 1748, 4846, 2864, 299, 159, 3426, 3427, 4486, 3428, 1376, 947, 300, 160, 1186, 1187, 1749, 42, 3429, 2456, 822, 1377, 4847, 1188, 3963, 948, 5469, 5470, 1378, 4848, 2865, 3430, 3431, 43, 2866, 3964, 4364, 1750, 5471, 1751, 3614, 1752, 1379, 2620, 1753, 823, 1754, 301, 1755, 1756, 1757, 3615, 302, 2457, 3432, 824, 303, 304, 1189, 1758, 1759, 1760, 5472, 1761, 4849, 4850, 4487, 2458, 2621, 3235, 305, 2622, 306, 3965, 1762, 1763, 1380, 2623, 1764, 1765, 1766, 2867, 1767, 1381, 1768, 2868, 1769, 1770, 3966, 1771, 2869, 307, 1772, 3967, 44, 3968, 1773, 308, 2870, 3616, 4851, 309, 4488, 1774, 1775, 667, 2624, 1510, 310, 1776, 2871, 1777, 4852, 1190, 1778, 3969, 3970, 2872, 3716, 1779, 4489, 3717, 311, 3433, 4853, 4490, 1780, 1781, 3971, 1511, 2873, 1782, 1783, 1784, 949, 1785, 1786, 4491, 3434, 3236, 312, 3237, 1512, 950, 951, 4854, 2874, 4365, 4492, 45, 4855, 4856, 4366, 1513, 313, 4857, 3972, 1382, 1787, 5473, 3973, 1514, 2625, 46, 668, 669, 4858, 314, 4493, 1788, 315, 3974, 1789, 4859, 3975, 3976, 5474, 3435, 1790, 952, 1791, 953, 1792, 5372, 3436, 316, 954, 5475, 670, 955, 1793, 671, 3977, 317, 2626, 2875, 4860, 3978, 4861, 1794, 2876, 2877, 5, 2878, 3979, 3718, 1795, 2879, 4862, 2627, 1383, 2628, 2629, 2630, 4367, 956, 3238, 2459, 5373, 4863, 4494, 4495, 1796, 3239, 318, 3437, 2460, 2880, 4496, 2881, 3438, 3719, 2631, 1797, 3439, 2632, 2461, 3440, 2462, 2463, 1191, 1384, 1798, 3240, 126, 957, 2633, 958, 5476, 319, 1799, 3980, 959, 1192, 1800, 1801, 47, 1802, 3441, 1385, 1515, 672, 3981, 4864, 4497, 1803, 2634, 1804, 1805, 3982, 4865, 2635, 2882, 2883, 2884, 1806, 1386, 5477, 320, 3983, 1807, 1808, 4498, 960, 4866, 3442, 5374, 1809, 1810, 1811, 825, 4867, 1812, 1813, 961, 5478, 1814, 1815, 1816, 4868, 4869, 3984, 3985, 1516, 5479, 3986, 48, 2885, 4870, 1387, 321, 1817, 1818, 2464, 3443, 3987, 3444, 1819, 322, 3988, 1193, 3989, 1820, 1821, 826, 3445, 4499, 1822, 3990, 2636, 1823, 1824, 1825, 827, 1826, 1827, 3241, 1517, 2886, 4871, 1828, 1518, 2887, 3991, 4500, 3992, 3720, 2888, 962, 4872, 4873, 3617, 2637, 5480, 4874, 1194, 3618, 1829, 4875, 828, 963, 964, 161, 1519, 4876, 2465, 3993, 3446, 4877, 3447, 4878, 323, 1830, 2638, 4879, 4880, 4881, 4882, 3994, 3721, 324, 3995, 2889, 2890, 1831, 4883, 1832, 3619, 3996, 1833, 325, 4501, 1834, 2891, 3997, 3998, 162, 6, 3722, 3999, 4000, 673, 326, 4502, 4001, 4002, 4003, 4503, 1835, 3242, 4004, 1836, 1837, 2639, 4005, 2892, 3448, 5481, 1195, 2893, 4368, 1838, 3723, 1839, 4884, 4885, 327, 4006, 4007, 5375, 4008, 4009, 1840, 4886, 1196, 4010, 4887, 1841, 49, 1842, 965, 4888, 1843, 4011, 328, 4889, 4012, 1844, 329, 674, 1845, 1846, 3724, 3243, 2640, 4013, 966, 1847, 1848, 675, 2466, 2894, 4014, 4890, 3449, 330, 5482, 1520, 2895, 4015, 4504, 4016, 967, 2896, 4017, 7, 331, 332, 50, 3244, 5376, 1197, 1849, 3725, 1850, 1851, 4018, 51, 1388, 2897, 2898, 1852, 3245, 1198, 3726, 4891, 4892, 4893, 4894, 127, 3246, 1853, 1854, 2899, 1521, 5483, 1389, 333, 5484, 334, 968, 52, 2900, 4505, 4895, 2901, 3727, 4896, 3247, 4019, 969, 3450, 2902, 3248, 335, 2467, 3451, 1855, 2903, 3452, 4020, 4506, 2904, 4897, 4898, 163, 4021, 1856, 4022, 970, 1199, 2905, 336, 4507, 971, 1857, 5485, 4023, 676, 4508, 677, 1858, 1200, 4024, 678, 1201, 1859, 2906, 2907, 4509, 4899, 3453, 2908, 3454, 1860, 2909, 3728, 1861, 3455, 4900, 1862, 3456, 1863, 4901, 679, 4025, 1864, 1865, 1866, 2641, 3249, 5377, 4510, 1867, 1868, 3457, 1869, 1870, 3729, 829, 1871, 4902, 2642, 4903, 1872, 3730, 4511, 3250, 972, 1873, 337, 3251, 5378, 4904, 4026, 4512, 2468, 4027, 4513, 4514, 4905, 1390, 4028, 338, 4906, 3458, 4029, 1391, 2910, 5379, 4907, 680, 4030, 339, 4908, 4031, 3459, 53, 4032, 1874, 4909, 340, 1392, 1522, 3252, 4033, 1202, 2911, 1875, 3253, 1876, 973, 974, 975, 2469, 976, 3731, 977, 5486, 978, 5487, 979, 2912, 2913, 1877, 1203, 341, 1878, 1879, 980, 1204, 4515, 3732, 1205, 1206, 4369, 830, 1207, 342, 1208, 1209, 1880, 681, 1210, 5380, 1211, 4034, 4035, 4036, 2914, 3254, 682, 683, 1881, 4516, 3255, 4037, 4517, 684, 3733, 1882, 4038, 4518, 831, 3460, 4039, 4910, 4911, 2915, 4912, 2916, 685, 164, 4370, 343, 3734, 2917, 344, 1883, 1884, 4913, 4914, 3620, 2918, 981, 4040, 2919, 4915, 2643, 4916, 2920, 4917, 1885, 4519, 686, 1886, 5488, 982, 687, 4520, 1887, 1888, 4918, 4041, 983, 2921, 4919, 1393, 832, 2922, 2923, 1889, 4920, 4921, 345, 4922, 2924, 1890, 4923, 4924, 3461, 984, 4925, 4521, 4926, 4522, 4927, 1891, 1523, 1892, 1212, 1893, 1394, 1894, 1895, 2644, 2645, 2470, 5489, 4928, 4042, 985, 1896, 346, 4929, 4043, 4523, 4044, 688, 986, 987, 4930, 2925, 689, 4045, 4931, 3462, 4046, 165, 4047, 1213, 4932, 988, 4933, 347, 1897, 4934, 3256, 2926, 4048, 690, 4935, 54, 833, 2927, 1898, 1899, 4049, 1900, 4524, 691, 2646, 348, 349, 4525, 350, 351, 692, 3257, 352, 353, 2928, 354, 4936, 1901, 1902, 834, 4050, 3258, 4526, 355, 356, 4051, 4937, 357, 1903, 4052, 358, 4938, 835, 359, 1904, 1905, 4939, 360, 693, 4527, 1906, 2929, 1214, 4940, 361, 694, 836, 3735, 4941, 55, 362, 4942, 2647, 4943, 1907, 1215, 1216, 2471, 2472, 3259, 4944, 1908, 363, 56, 4053, 3621, 364, 4945, 2930, 3260, 1909, 1524, 695, 2931, 1910, 4054, 4946, 5381, 3261, 3463, 4947, 4948, 365, 4528, 1911, 4055, 2648, 4529, 2932, 4056, 1912, 4530, 2933, 4531, 4057, 1217, 2934, 989, 2935, 3262, 1913, 1914, 4532, 4949, 696, 4058, 4950, 1915, 2936, 4951, 990, 5382, 1395, 2649, 1916, 3263, 4059, 366, 2473, 57, 1917, 1918, 3464, 991, 1919, 1525, 4952, 4533, 1920, 992, 1921, 3736, 697, 1922, 698, 4953, 4060, 367, 4954, 4955, 1923, 368, 4956, 4534, 369, 2937, 993, 1396, 3465, 4061, 166, 2474, 3264, 994, 2938, 4535, 4957, 699, 4958, 4536, 3265, 3737, 700, 5490, 1924, 4537, 370, 701, 4409, 2939, 4959, 4538, 4062, 1925, 371, 372, 167, 4539, 4960, 4961, 373, 374, 2940, 4540, 702, 375, 2941, 4541, 2475, 837, 3466, 995, 4542, 4063, 2650, 5383, 5384, 376, 4962, 377, 996, 5385, 1926, 1927, 1928, 3622, 378, 5491, 1929, 1930, 379, 168, 3266, 4064, 380, 381, 382, 383, 838, 384, 3623, 2942, 1931, 997, 998, 5492, 4963, 3267, 703, 3467, 4543, 1218, 1932, 2943, 704, 2476, 999, 3738, 4544, 4964, 4965, 385, 1933, 386, 3624, 387, 1934, 169, 1935, 388, 1936, 2944, 389, 2945, 3268, 1937, 1938, 1939, 390, 4966, 1940, 1397, 391, 1941, 1942, 4967, 3625, 1000, 1943, 705, 392, 393, 394, 1944, 4968, 1219, 2946, 4545, 839, 2947, 3626, 3269, 395, 4969, 1945, 4970, 4971, 396, 706, 4972, 170, 4546, 1001, 4973, 5493, 3270, 397, 707, 4547, 4974, 1526, 5494, 2651, 4975, 5386, 2652, 4371, 4065, 4976, 4977, 1002, 4978, 398, 4066, 1527, 3271, 840, 399, 4979, 708, 4980, 1003, 4067, 3627, 1946, 4981, 4068, 400, 4982, 709, 2653, 3739, 1947, 1398, 128, 1004, 3468, 1948, 2948, 1949, 1950, 1220, 1399, 4983, 4984, 401, 402, 4985, 403, 4986, 404, 405, 1951, 1952, 1005, 1953, 4987, 2477, 4548, 1954, 1955, 4988, 406, 841, 2949, 2950, 2951, 2952, 1528, 1006, 4069, 4070, 3272, 4549, 407, 4989, 2953, 4071, 4990, 1956, 3740, 408, 2654, 58, 2478, 4991, 2954, 4992, 1400, 1957, 4550, 409, 3469, 1958, 59, 4072, 2479, 4993, 1959, 4073, 2955, 410, 1960, 4074, 411, 842, 710, 4075, 2956, 711, 712, 412, 4994, 713, 4551, 1961, 3470, 4995, 4996, 1962, 1963, 1007, 2957, 413, 3741, 4997, 3742, 1401, 2958, 1964, 3743, 1965, 60, 5387, 3628, 3744, 2959, 5388, 1966, 1529, 171, 2960, 3273, 4076, 1008, 4552, 1530, 61, 714, 1531, 2961, 3745, 3746, 3471, 3747, 2962, 4553, 4998, 4077, 4999, 4372, 1009, 2963, 3274, 1532, 715, 1221, 3275, 3472, 5000, 5495, 1010, 1402, 1967, 1968, 1222, 1969, 62, 414, 1970, 1971, 1972, 415, 2655, 5001, 843, 3473, 1973, 2964, 1011, 4373, 716, 416, 417, 4554, 1974, 1975, 5002, 3276, 3748, 3474, 3749, 418, 1223, 1976, 844, 2656, 1977, 5003, 1978, 63, 3277, 3475, 2965, 2657, 3476, 4078, 4555, 1979, 8, 4556, 5004, 3750, 3477, 1980, 1981, 1224, 1982, 1012, 1403, 2658, 5496, 1983, 2659, 419, 717, 3478, 718, 3278, 420, 3751, 1404, 1984, 3479, 4079, 5005, 5006, 1225, 2660, 64, 3752, 5007, 2966, 65, 5008, 3279, 4557, 5009, 5010, 1985, 2967, 3280, 3480, 2661, 2662, 172, 1986, 1405, 2480, 1406, 421, 1013, 2968, 422, 423, 173, 1533, 1987, 2969, 174, 4558, 1988, 1534, 424, 1989, 5389, 4559, 1226, 1227, 1228, 1229, 2663, 3481, 4080, 3753, 66, 5497, 1990, 2664, 3281, 3754, 3482, 3755, 3483, 3282, 1230, 3283, 3484, 3485, 5498, 3284, 1991, 4081, 1992, 1993, 1994, 3285, 1231, 3756, 425, 3757, 1014, 1995, 2665, 4082, 4083, 5011, 3486, 4560, 1535, 426, 3629, 4084, 5499, 4085, 4561, 1232, 427, 428, 3286, 429, 3758, 3759, 1996, 430, 1997, 1407, 1998, 3487, 2970, 431, 845, 1999, 2971, 129, 5012, 5390, 2972, 2000, 2666, 4562, 432, 4563, 5500, 5013, 2001, 719, 4086, 5014, 2002, 4564, 5015, 2003, 433, 5016, 4565, 2004, 1015, 2973, 4087, 2005, 434, 2974, 1233, 2006, 5017, 2007, 3287, 67, 2481, 720, 2975, 5018, 4566, 4088, 4089, 846, 5019, 2667, 435, 5501, 2976, 2977, 2668, 2978, 2008, 4567, 5020, 1234, 5021, 5022, 1408, 5023, 2669, 5024, 1409, 3760, 5025, 3488, 1235, 436, 3761, 2009, 2010, 4568, 2979, 5026, 2011, 2980, 5027, 2981, 5028, 2012, 4569, 1016, 3489, 5502, 3630, 3762, 437, 4090, 5391, 130, 3288, 438, 5029, 3763, 5030, 439, 5031, 68, 2013, 4091, 4374, 2014, 3289, 4570, 3631, 440, 721, 3490, 441, 2015, 2670, 2482, 442, 4571, 2483, 1236, 5032, 3632, 443, 444, 5033, 5034, 1017, 4572, 69, 3764, 4573, 2016, 445, 446, 5392, 5393, 2982, 2671, 2672, 1018, 2983, 2017, 4092, 175, 2673, 176, 3290, 177, 9, 2984, 2985, 2986, 5035, 2987, 2018, 3633, 2988, 2019, 2020, 178, 3491, 2989, 10, 4093, 447, 448, 2021, 847, 4094, 2022, 70, 1019, 179, 2484, 5036, 1237, 5037, 4574, 1536, 2485, 722, 449, 71, 450, 3291, 1238, 723, 1239, 2486, 5038, 4095, 848, 4096, 451, 72, 4575, 2023, 2674, 1410, 4097, 3765, 452, 724, 3492, 3493, 2990, 73, 849, 11, 4576, 2675, 2024, 2991, 2992, 2025, 4098, 4099, 5503, 5039, 74, 3634, 2026, 850, 2993, 2994, 5040, 2995, 2996, 5041, 2027, 2997, 2998, 2028, 2487, 2676, 2029, 2999, 2030, 4100, 3000, 2031, 725, 5042, 3766, 2032, 5394, 3001, 1020, 453, 726, 3494, 2677, 4577, 4101, 454, 75, 1240, 2033, 5043, 2678, 5504, 3002, 2034, 2035, 2036, 2037, 2038, 3495, 455, 1241, 2679, 3003, 2039, 4102, 2680, 4103, 4104, 3004, 2040, 1242, 1243, 4578, 2041, 1021, 76, 1411, 2681, 2042, 5044, 3005, 180, 1022, 5505, 727, 3767, 4105, 131, 2043, 456, 3006, 2488, 2044, 4579, 2489, 3635, 2045, 5045, 3007, 2046, 5046, 728, 5047, 2047, 3636, 77, 3768, 3496, 457, 3497, 3637, 5048, 458, 729, 1244, 730, 3498, 1023, 851, 1024, 78, 4106, 2048, 2049, 1025, 5049, 4375, 5050, 2050, 5051, 3638, 5506, 1245, 3008, 2051, 4107, 2052, 731, 1537, 1246, 3292, 5052, 459, 5507, 460, 4376, 5053, 3009, 5054, 1412, 5055, 2053, 4580, 1247, 3010, 732, 2490, 5056, 4581, 2054, 2055, 2682, 5057, 5058, 5059, 1026, 5395, 2491, 2492, 733, 5060, 1248, 5061, 4582, 5062, 2056, 3499, 3500, 2057, 734, 2683, 2058, 852, 3769, 4108, 2493, 3770, 1027, 2059, 5396, 3501, 5063, 4109, 5064, 5065, 2060, 5066, 2061, 4110, 4583, 2062, 4584, 5067, 3771, 5508, 2063, 2684, 5068, 4377, 461, 2064, 5509, 2065, 2685, 5069, 79, 4111, 1249, 2066, 1028, 2067, 1029, 1030, 735, 2068, 736, 3293, 3011, 3294, 4112, 462, 3012, 737, 1031, 4113, 5070, 1032, 3502, 4585, 2069, 463, 3503, 2070, 4586, 4114, 4115, 1250, 464, 5071, 1033, 3772, 4116, 5072, 1034, 2494, 4410, 738, 465, 4117, 466, 853, 4118, 4119, 739, 2686, 467, 468, 1035, 1538, 2071, 3013, 469, 854, 470, 855, 2072, 5397, 80, 3504, 5510, 471, 5073, 472, 2073, 1036, 2074, 2075, 5074, 2076, 4120, 2077, 5075, 3773, 2078, 2079, 3639, 5511, 5076, 2687, 4587, 1539, 473, 5512, 3295, 3505, 5077, 2080, 2688, 3506, 1037, 5398, 2081, 1038, 5078, 181, 5079, 4121, 474, 3640, 1251, 2082, 1540, 5080, 1039, 3774, 3641, 1413, 4122, 475, 4411, 1414, 5399, 5400, 5401, 3014, 5402, 3507, 1415, 5403, 3508, 5081, 3015, 4123, 1541, 1040, 3016, 1542, 4124, 1041, 3017, 1416, 4125, 2083, 4126, 1417, 4378, 4127, 5082, 476, 1418, 5083, 4128, 3018, 5084, 1252, 1042, 3775, 2084, 4588, 3019, 2495, 3020, 4129, 5085, 477, 3021, 2689, 3642, 1043, 5086, 1419, 5087, 4130, 478, 3643, 1044, 5088, 1253, 2496, 4589, 479, 1420, 3022, 2085, 3023, 5089, 4379, 1421, 1422, 2086, 1423, 1424, 1425, 5090, 1426, 3024, 740, 2690, 5513, 1254, 182, 4131, 4132, 2691, 4133, 2087, 2088, 4134, 3025, 4135, 480, 2089, 1045, 4136, 5514, 741, 3026, 1427, 3509, 4137, 3027, 2090, 481, 3028, 2497, 4590, 1428, 2091, 4380, 856, 1046, 4591, 482, 1429, 5091, 5515, 183, 5516, 184, 4138, 1047, 4139, 2092, 1048, 4140, 483, 4592, 5092, 1430, 4381, 1543, 3029, 5517, 81, 4141, 1431, 742, 2093, 3510, 1049, 2498, 2499, 1432, 3511, 1433, 4142, 484, 4143, 2094, 5093, 2500, 743, 5094, 3512, 2501, 132, 2095, 5095, 2692, 1255, 82, 3776, 83, 3513, 84, 2096, 5096, 2097, 3296, 1256, 485, 2693, 2098, 5518, 486, 2099, 85, 2100, 5097, 2101, 5098, 5099, 2502, 2102, 1050, 5100, 4593, 3297, 3298, 744, 3030, 5101, 5102, 4144, 5103, 4594, 2503, 487, 3299, 2504, 5104, 3031, 4595, 86, 2103, 3777, 2104, 2105, 4382, 2694, 4596, 5105, 1051, 2106, 3032, 5106, 488, 1052, 5107, 2505, 745, 4412, 746, 5404, 1257, 747, 748, 1053, 2107, 3514, 2108, 3515, 2109, 4597, 3033, 4145, 2110, 4598, 2111, 2112, 3516, 87, 5108, 1054, 2506, 749, 4599, 2113, 4600, 750, 3300, 4146, 5109, 3034, 5519, 489, 3035, 4601, 5110, 4147, 3517, 88, 3518, 1258, 5520, 490, 1055, 5521, 3301, 5522, 1056, 1057, 3036, 5111, 4148, 4602, 2114, 3037, 1058, 4149, 857, 3302, 5112, 4150, 89, 2115, 4603, 3519, 2116, 3644, 2117, 751, 2507, 2118, 5113, 4151, 3645, 1259, 5114, 752, 4604, 5115, 1544, 3038, 4152, 5523, 2119, 753, 491, 754, 3778, 5524, 3039, 3040, 1545, 1059, 1434, 5116, 3041, 5117, 3303, 1435, 3042, 1546, 2120, 5118, 2695, 492, 3646, 3779, 2508, 1060, 3780, 5119, 4153, 4383, 3781, 90, 185, 493, 91, 5120, 5121, 3520, 3521, 3304, 3782, 1260, 4154, 3783, 2121, 4155, 2122, 2123, 2124, 2696, 3784, 1261, 3522, 3305, 92, 4605, 4156, 4157, 2125, 4606, 1262, 2126, 3043, 3044, 2697, 2127, 3523, 2128, 2129, 5122, 3785, 3647, 494, 2509, 5525, 3524, 3786, 3306, 186, 2130, 3045, 5123, 5124, 1263, 2698, 3307, 3525, 5125, 2131, 495, 4158, 5126, 3046, 93, 4607, 1264, 2132, 4159, 3526, 496, 3047, 2133, 5127, 3308, 2134, 5128, 2135, 755, 2699, 133, 2136, 2137, 2138, 3787, 2700, 5405, 1436, 3788, 2139, 5129, 497, 4160, 2701, 2140, 4608, 5130, 5131, 1265, 5406, 5132, 2141, 5526, 498, 3789, 858, 5133, 1266, 1547, 3527, 3528, 2142, 4161, 2702, 2143, 3790, 5527, 2510, 1437, 4162, 4163, 756, 1267, 5134, 3791, 94, 4609, 757, 2144, 2145, 5528, 2146, 2147, 2148, 5135, 5136, 758, 1268, 2149, 4610, 1269, 3048, 3049, 3050, 1061, 5137, 2150, 4611, 3309, 3310, 4612, 3311, 1062, 3648, 95, 5138, 2703, 499, 2151, 4164, 2511, 3529, 2704, 5139, 2152, 2153, 2154, 2155, 3051, 500, 96, 2705, 1063, 5140, 2706, 3792, 2707, 2156, 4384, 3530, 4385, 501, 5141, 1270, 97, 502, 5142, 5529, 759, 2157, 3052, 4165, 4166, 3053, 4167, 3054, 4613, 5143, 3055, 5407, 3649, 4168, 1271, 4169, 4614, 859, 503, 4170, 2158, 3531, 1272, 5144, 760, 5145, 5146, 1064, 2159, 5147, 3532, 3650, 504, 3056, 5148, 2160, 5149, 5408, 2161, 5150, 2162, 2163, 98, 1065, 1273, 2164, 4171, 2165, 5151, 5152, 3057, 5530, 5153, 4172, 5154, 4615, 2166, 1066, 1067, 761, 505, 3533, 506, 2708, 3058, 3059, 5155, 2167, 2709, 5531, 860, 2168, 2512, 12, 1068, 3060, 507, 508, 3061, 4173, 5156, 4616, 1438, 2169, 5157, 5158, 3312, 1274, 2710, 3793, 2711, 4174, 99, 2712, 2170, 5409, 5410, 509, 1439, 2171, 2172, 510, 5159, 2713, 3313, 4617, 5160, 2173, 5161, 2513, 3062, 1548, 5162, 1440, 3063, 1069, 5163, 4175, 4618, 5532, 4619, 5533, 1441, 2174, 4176, 4620, 1442, 5164, 861, 2175, 2176, 511, 5165, 762, 5166, 1070, 3651, 3064, 3794, 4177, 1071, 763, 2177, 2514, 1072, 3534, 13, 4178, 1443, 3535, 5534, 3065, 3066, 4621, 100, 5411, 2515, 101, 3795, 1444, 1445, 1446, 5167, 5168, 2178, 1275, 134, 4179, 4180, 1549, 5535, 3652, 102, 3067, 1276, 512, 4622, 4386, 4181, 3068, 14, 4182, 1073, 2179, 764, 5169, 513, 5170, 765, 2180, 2181, 4183, 4623, 1447, 5171, 135, 514, 3069, 5172, 2182, 4624, 5173, 5536, 2516, 3070, 2183, 2714, 3536, 5174, 2184, 2185, 5175, 2186, 5176, 4625, 3071, 515, 1277, 5177, 187, 4626, 516, 1278, 2187, 862, 5537, 2188, 4184, 1279, 4387, 4627, 2189, 5178, 1280, 517, 1281, 5179, 2517, 3314, 4388, 1448, 1282, 3072, 4628, 2715, 1074, 4185, 5180, 5412, 4186, 2190, 3073, 5538, 3796, 4187, 2716, 5181, 4188, 2191, 3074, 5182, 3075, 2518, 3653, 3076, 4189, 3077, 103, 3078, 3537, 518, 2717, 3654, 5183, 5184, 2192, 1449, 3079, 4190, 519, 4629, 3080, 5185, 4191, 3315, 1075, 3655, 3081, 766, 2718, 3316, 520, 767, 768, 769, 770, 3797, 3798, 521, 5186, 3082, 5187, 3083, 3084, 4630, 1283, 2193, 2194, 3085, 3086, 3317, 2195, 5539, 771, 2519, 5188, 3538, 4192, 2196, 3539, 5189, 5190, 5191, 4193, 522, 2719, 3087, 772, 3656, 2197, 3088, 1450, 3089, 2198, 2199, 5192, 4194, 523, 1284, 2720, 524, 2721, 5413, 525, 2722, 2200, 5540, 3799, 3318, 526, 3800, 2723, 2724, 2201, 3540, 3801, 5414, 1076, 1077, 1285, 1550, 5193, 527, 3541, 528, 3319, 5194, 5195, 1451, 3090, 5196, 2202, 529, 3091, 5197, 5198, 5199, 5200, 5201, 2203, 1452, 3542, 5415, 5202, 5203, 5204, 2204, 3092, 863, 3093, 3657, 3094, 15, 1453, 3095, 3096, 1551, 2205, 3658, 5205, 4389, 5541, 4631, 3659, 3660, 5206, 530, 3661, 531, 4632, 3802, 4633, 532, 2206, 4634, 2207, 5542, 4635, 4195, 2208, 3320, 4636, 4196, 5207, 3543, 104, 2209, 2520, 4637, 1552, 3097, 2210, 864, 2211, 4197, 2212, 2213, 2214, 2215, 188, 1078, 533, 4638, 5543, 2725, 1079, 1553, 2216, 5208, 4198, 4639, 2217, 5209, 4199, 1554, 2218, 4640, 4200, 2219, 534, 3803, 16, 4201, 3098, 4202, 4390, 2220, 4641, 3099, 4203, 4204, 1454, 3100, 2521, 1455, 4205, 4413, 5210, 1286, 2221, 5416, 3101, 4206, 1456, 5211, 105, 2222, 5212, 1080, 2223, 5213, 2522, 773, 535, 3804, 2224, 3102, 5214, 2225, 774, 2226, 4207, 5215, 3321, 4208, 5216, 5217, 5218, 4642, 2726, 3322, 5417, 2727, 3103, 3323, 2227, 536, 2523, 775, 5219, 3324, 4643, 5220, 5221, 2228, 5222, 1457, 3104, 4209, 3105, 5223, 4644, 537, 4210, 4211, 2524, 1287, 5544, 4212, 1081, 5545, 5224, 4645, 3325, 4213, 5225, 5226, 3106, 538, 2229, 5227, 1082, 2230, 2231, 2525, 4214, 2232, 5228, 539, 1458, 2728, 4646, 3107, 4215, 5229, 4216, 2729, 3326, 3805, 540, 3327, 5230, 5231, 541, 5232, 1083, 2233, 3108, 2234, 2526, 3328, 2235, 3544, 5233, 4217, 1459, 3545, 2236, 5234, 3109, 1084, 2237, 5546, 5235, 3329, 3546, 1288, 5236, 1289, 2730, 3110, 4647, 1085, 2238, 542, 1290, 2731, 3111, 1086, 5237, 3112, 189, 3113, 2527, 2239, 865, 3114, 5238, 3547, 543, 1291, 2240, 2732, 4391, 5418, 106, 2528, 1292, 2241, 4218, 3806, 4219, 3330, 5239, 544, 2529, 2242, 866, 3331, 4220, 3115, 2530, 2243, 2244, 5547, 3662, 3116, 5240, 3117, 776, 1293, 1294, 2733, 5241, 2245, 545, 2246, 2247, 2248, 1087, 2249, 1088, 1555, 5242, 2250, 5548, 1460, 4221, 2251, 1089, 4648, 5419, 5243, 3548, 17, 4649, 5549, 5244, 867, 2734, 4222, 1090, 3118, 5550, 546, 1461, 3332, 4650, 1091, 3119, 4651, 5551, 2252, 4223, 547, 136, 548, 4224, 5245, 2253, 2254, 2735, 5246, 2255, 777, 2531, 778, 2256, 2257, 107, 3120, 2258, 2259, 1295, 3807, 108, 2260, 3549, 2261, 5420, 3808, 2736, 2262, 549, 2532, 2533, 4225, 4652, 1462, 550, 4653, 5421, 1296, 5247, 2737, 5248, 4226, 3809, 5249, 1092, 4227, 3121, 4228, 1093, 551, 1463, 3550, 3663, 5250, 2263, 5251, 2264, 3122, 1094, 2265, 190, 2266, 2267, 5252, 1464, 2268, 4229, 3123, 5253, 4230, 2269, 2270, 3124, 2534, 1297, 3551, 4231, 4232, 552, 5254, 4233, 2271, 3125, 3552, 5255, 5256, 2272, 779, 1298, 3333, 2738, 1299, 2739, 2273, 3810, 5257, 4654, 5552, 3811, 3334, 4655, 1300, 5258, 4656, 4234, 109, 2274, 3553, 2535, 5259, 3335, 4657, 5260, 3126, 5422, 4658, 553, 554, 1095, 2740, 4659, 5423, 2275, 2536, 1301, 2537, 2741, 1302, 868, 2276, 4235, 555, 4392, 556, 1303, 2277, 1465, 557, 3554, 5553, 2538, 3812, 3664, 2278, 2742, 5261, 5424, 4236, 3555, 1096, 3665, 2279, 4237, 2280, 1304, 558, 2281, 4393, 1305, 3813, 2539, 3556, 4660, 559, 4238, 191, 869, 1556, 2282, 2283, 2540, 2284, 3666, 2285, 780, 3814, 3557, 2286, 3558, 2287, 2288, 2289, 560, 2290, 4239, 3127, 3128, 3336, 1306, 4661, 2291, 1097, 4414, 3667, 5262, 3559, 3560, 2292, 2293, 1098, 2541, 2294, 3561, 4240, 3562, 5263, 2295, 5264, 3668, 2542, 2296, 2543, 3563, 3129, 2743, 1307, 4662, 3130, 781, 2297, 2298, 4663, 2299, 2300, 1308, 2301, 5265, 3564, 4241, 2744, 3815, 1309, 4664, 2745, 3131, 1310, 2302, 2303, 4665, 5266, 2304, 3337, 4242, 3132, 3133, 3134, 4666, 2305, 5267, 3135, 3338, 2746, 110, 2306, 2307, 111, 2308, 561, 4243, 3136, 2747, 2748, 3816, 2749, 2750, 1311, 3669, 2309, 5268, 3339, 2751, 2752, 870, 3817, 4667, 4668, 2310, 3565, 3340, 2311, 4244, 4245, 4246, 562, 2312, 2313, 4247, 4248, 3566, 3567, 1466, 1467, 5269, 5270, 2753, 3818, 4249, 3670, 1468, 4250, 1312, 5271, 2754, 3137, 1469, 2755, 3568, 4251, 2314, 3341, 5272, 4669, 3569, 4252, 4670, 1313, 1099, 782, 3570, 112, 1314, 4415, 1100, 5273, 4253, 2756, 3138, 5274, 4254, 4255, 4671, 4256, 871, 1315, 3139, 3819, 5275, 3571, 4672, 563, 4257, 2757, 5425, 2315, 1101, 3572, 3820, 2544, 4394, 3140, 4673, 1102, 3573, 5554, 113, 114, 4258, 1103, 5276, 4259, 192, 3821, 3822, 5277, 1316, 3671, 1470, 4260, 2316, 4261, 4674, 4262, 3141, 3142, 3143, 3574, 2317, 4263, 5278, 1317, 2318, 3823, 1318, 1319, 3575, 1320, 2319, 5279, 2320, 872, 5555, 115, 5280, 3144, 2321, 2545, 5281, 2322, 2758, 3672, 2323, 4264, 2324, 2325, 2326, 564, 2327, 2328, 5556, 193, 2759, 4265, 1104, 5282, 2329, 2330, 3145, 3824, 2331, 4266, 4267, 5557, 4268, 4269, 3825, 5283, 2332, 2760, 4270, 1321, 3342, 2761, 565, 1471, 4271, 3146, 2333, 2546, 3673, 4272, 3674, 3147, 4273, 5284, 2334, 5285, 2335, 566, 116, 1322, 567, 3148, 4675, 568, 4676, 569, 4677, 5286, 3576, 570, 3577, 4274, 4275, 4276, 4277, 1557, 2336, 18, 1323, 2337, 1105, 2338, 3826, 2339, 3827, 19, 2340, 2547, 1324, 2341, 783, 117, 784, 4278, 3149, 571, 2342, 2343, 2344, 4279, 572, 4280, 2345, 4395, 4281, 2346, 3675, 873, 4678, 5287, 2347, 2762, 3828, 2763, 2348, 3829, 3830, 137, 573, 2349, 2350, 574, 2764, 5288, 3831, 1472, 575, 2765, 3343, 5289, 2351, 1325, 1106, 2352, 3150, 2353, 2766, 576, 3832, 3833, 3344, 2354, 577, 3151, 3345, 3152, 4282, 4283, 2767, 5290, 5291, 4284, 2355, 1558, 2356, 4285, 3834, 5292, 4679, 1559, 3578, 3676, 1107, 5558, 4286, 2357, 5293, 194, 2358, 5426, 2359, 3579, 578, 1108, 2360, 3580, 4287, 1473, 3153, 3346, 5427, 1109, 579, 580, 1326, 3835, 5559, 581, 4288, 2768, 785, 2361, 5294, 3581, 2769, 2770, 4289, 2362, 3347, 786, 4680, 1560, 874, 5295, 1474, 2771, 2548, 2772, 582, 5560, 1327, 1328, 5296, 4681, 3154, 5297, 2773, 3677, 3348, 3582, 5298, 5299, 4290, 1475, 5300, 195, 5301, 3349, 5302, 5561, 583, 3836, 2363, 787, 3350, 3351, 5303, 2774, 1561, 5304, 5562, 5305, 2549, 4682, 2364, 5563, 3837, 5306, 5564, 3352, 3155, 5307, 3156, 788, 3583, 5308, 3838, 4683, 1476, 3678, 584, 118, 3584, 585, 586, 2365, 196, 3157, 4291, 4292, 587, 2775, 4293, 2366, 3158, 2367, 5309, 588, 5310, 1477, 4294, 2368, 5311, 1110, 119, 4295, 5312, 3353, 5313, 5314, 4296, 1562, 5315, 20, 789, 138, 5316, 2369, 1329, 5317, 790, 5318, 2776, 4297, 197, 2777, 589, 3159, 2370, 4396, 791, 5319, 3160, 5428, 3839, 3840, 4298, 2778, 590, 5320, 591, 2371, 592, 120, 1563, 3585, 1111, 3679, 3354, 1112, 2550, 3161, 4299, 593, 3355, 1478, 3162, 3163, 5321, 2551, 1479, 4300, 4397, 792, 3164, 3841, 3842, 5322, 4684, 4685, 3165, 3356, 3843, 4686, 1330, 4687, 4688, 5323, 1331, 2372, 4301, 2373, 4302, 2374, 5429, 5565, 5566, 2375, 2376, 2377, 3166, 5430, 3167, 2378, 2552, 198, 3357, 1480, 4303, 5324, 4304, 5325, 3844, 5326, 2553, 3358, 121, 2554, 793, 3680, 4305, 4306, 594, 5327, 4307, 4689, 3168, 4308, 2379, 4309, 4310, 4311, 5328, 1564, 2380, 4312, 4313, 2381, 1113, 3681, 4690, 4691, 4692, 1114, 3359, 4314, 2779, 3360, 4315, 3845, 1332, 1115, 4693, 4694, 595, 2555, 4316, 2556, 1333, 5329, 2382, 4695, 4317, 3169, 3170, 1334, 5330, 2383, 3361, 4318, 4319, 4320, 4321, 3362, 3171, 5331, 5567, 5568, 1335, 1336, 5332, 2384, 5333, 4322, 794, 1116, 1117, 3172, 4696, 2385, 1337, 199, 596, 2386, 2387, 597, 598, 795, 2388, 5334, 599, 5335, 2389, 2390, 5336, 3173, 4323, 5337, 600, 4416, 1118, 2780, 2557, 796, 3846, 5431, 601, 2391, 2781, 797, 3174, 602, 2392, 3586, 4324, 3175, 2393, 4697, 1481, 122, 5338, 3176, 4325, 3847, 3177, 603, 5339, 1338, 5340, 1119, 1120, 2394, 2558, 4698, 798, 2395, 200, 604, 3587, 2396, 201, 4326, 799, 4398, 4699, 5341, 4700, 1121, 605, 4327, 1482, 4399, 4400, 4328, 4329, 4330, 606, 3682, 3588, 607, 5342, 5343, 5344, 1122, 4331, 4701, 4702, 5345, 2397, 875, 2398, 4703, 1339, 2399, 5346, 5347, 2400, 1123, 2401, 800, 3683, 2782, 3848, 801, 3589, 2402, 608, 609, 1483, 3590, 610, 5348, 611, 2403, 3684, 2404, 4332, 876, 3849, 3178, 3363, 1484, 612, 3850, 4333, 5349, 3179, 3591, 4334, 3364, 2405, 3180, 613, 2406, 2407, 2408, 3365, 3366, 2409, 4335, 4336, 4337, 877, 1340, 1124, 3367, 4338, 1565, 1125, 123, 2410, 3851, 802, 4339, 4704, 4705, 2411, 2783, 2559, 1485, 1126, 3852, 4340, 4341, 4342, 3592, 4343, 1341, 878, 1127, 1486, 879, 880, 4401, 5350, 5351, 2412, 2413, 2414, 2415, 3181, 2416, 2560, 4344, 5352, 4345, 4346, 2784, 4706, 881, 5353, 614, 4347, 3368, 139, 1342, 2561, 3182, 1343, 2417, 3685, 5354, 5355, 615, 3593, 5569, 616, 2418, 3183, 617, 4348, 4707, 5570, 3184, 4349, 4708, 21, 4709, 4710, 3369, 2562, 618, 2785, 5356, 1344, 4711] + ) + + # Reads one dataset row as a municipality. + def self.row_to_municipality(row) + return Municipality.new(code: row[2], name: row[1], state_code: row[0]) + end + + # Returns Brazilian municipalities published by the IBGE, optionally filtered by state. + # + # If `stateCode` is provided, only municipalities of that state are returned. If it is + # omitted, every municipality of every state is returned, sorted with `localeCompare` in the + # "pt-BR" locale so accented names land where a Brazilian reader expects them. Every per-state + # list is sorted the same way. + # + # Only an omitted (or `undefined`) `stateCode` asks for the full list: any other value that is + # not a known state code, `null` and `""` included, returns `[]`. + # + # The state code is matched exactly, case included: `getMunicipalities("sp")` returns `[]` where + # `getMunicipalities("SP")` returns the 645 São Paulo municipalities. + # + # @see Official: https://servicodados.ibge.gov.br/api/docs/localidades + def self.get_municipalities(state_code = nil) + municipalities = [] + rows = Runtime.data_all(MUNICIPALITIES) + if !state_code.nil? + rows = Runtime.data_rows(MUNICIPALITIES, state_code) + end + rows.each do |row| + municipalities.push(row_to_municipality(row)) + end + return municipalities + end + end +end diff --git a/spec/bridge/out/ruby/lib/brazilian_utils_bridge/is_valid_cnpj.rb b/spec/bridge/out/ruby/lib/brazilian_utils_bridge/is_valid_cnpj.rb new file mode 100644 index 000000000..0217daf8e --- /dev/null +++ b/spec/bridge/out/ruby/lib/brazilian_utils_bridge/is_valid_cnpj.rb @@ -0,0 +1,112 @@ +# frozen_string_literal: true + +# Code generated from spec/bridge/source/is-valid-cnpj.ts. DO NOT EDIT. + +require_relative 'runtime' + +module BrazilianUtilsBridge + # `isValidCnpj`, written once. + module IsValidCnpj + CLASS0 = [[0x30, 0x39], [0x41, 0x5a]].freeze + CLASS1 = [[0x9, 0xd], [0x20, 0x20], [0x2d, 0x2f], [0xa0, 0xa0], [0x1680, 0x1680], [0x2000, 0x200a], [0x2028, 0x2029], [0x202f, 0x202f], [0x205f, 0x205f], [0x3000, 0x3000], [0xfeff, 0xfeff]].freeze + CLASS2 = [[0x30, 0x39]].freeze + CLASS3 = [[0x41, 0x5a]].freeze + CLASS4 = [[0x30, 0x39], [0x41, 0x5a], [0x61, 0x7a]].freeze + + PATTERN_ALPHANUMERIC_FORMAT = [ + Runtime::PatternStep.new(CLASS0, 2, 2, false), + Runtime::PatternStep.new(CLASS1, 0, -1, false), + Runtime::PatternStep.new(CLASS0, 3, 3, false), + Runtime::PatternStep.new(CLASS1, 0, -1, false), + Runtime::PatternStep.new(CLASS0, 3, 3, false), + Runtime::PatternStep.new(CLASS1, 0, -1, false), + Runtime::PatternStep.new(CLASS0, 4, 4, false), + Runtime::PatternStep.new(CLASS1, 0, -1, false), + Runtime::PatternStep.new(CLASS2, 2, 2, false), + ].freeze + + PATTERN_NUMERIC_FORMAT = [ + Runtime::PatternStep.new(CLASS2, 2, 2, false), + Runtime::PatternStep.new(CLASS1, 0, -1, false), + Runtime::PatternStep.new(CLASS2, 3, 3, false), + Runtime::PatternStep.new(CLASS1, 0, -1, false), + Runtime::PatternStep.new(CLASS2, 3, 3, false), + Runtime::PatternStep.new(CLASS1, 0, -1, false), + Runtime::PatternStep.new(CLASS2, 4, 4, false), + Runtime::PatternStep.new(CLASS1, 0, -1, false), + Runtime::PatternStep.new(CLASS2, 2, 2, false), + ].freeze + + FIRST_DIGIT_WEIGHTS = [5, 4, 3, 2, 9, 8, 7, 6, 5, 4, 3, 2].freeze + SECOND_DIGIT_WEIGHTS = [6, 5, 4, 3, 2, 9, 8, 7, 6, 5, 4, 3, 2].freeze + + + + # Options of `isValidCnpj`. + IsValidCnpjOptions = Struct.new(:version, keyword_init: true) + + + + # Validates if a CNPJ (Cadastro Nacional da Pessoa Jurídica) is valid. + # + # Supports both numeric (version 1) and alphanumeric (version 2) CNPJ formats, and accepts the + # usual mask characters (`.`, `-`, `/`) and whitespace around and between groups. + def self.is_valid_cnpj(cnpj, options = nil) + options_version = -1 + options_version = options.version unless options.nil? || options.version.nil? + return false if !cnpj.is_a?(String) + trimmed = Runtime.js_trim(cnpj) + if (options_version == 2) + cleaned = Runtime.keep_class(CLASS4, cnpj).upcase + if Runtime.class_has(CLASS3, cleaned) + if !Runtime.pattern_test(PATTERN_ALPHANUMERIC_FORMAT, trimmed.upcase) + return false + end + return has_valid_checksum(cleaned) + end + end + numeric = Runtime.keep_class(CLASS2, cnpj) + if !Runtime.pattern_test(PATTERN_NUMERIC_FORMAT, trimmed) + return false + end + if is_repeated(numeric) + return false + end + return has_valid_checksum(numeric) + end + + # Computes one CNPJ check digit from the base and its weight vector. + def self.check_digit(base, weights) + sum = 0 + (0...weights.length).each do |index| + sum = (sum + ((Runtime.code_at(base, index) - 48) * weights[index])) + end + remainder = (sum % 11) + if (remainder < 2) + return 0 + end + return (11 - remainder) + end + + # Whether both check digits of a sanitized 14 character CNPJ match its base. + def self.has_valid_checksum(cnpj) + if ((Runtime.code_at(cnpj, 12) - 48) != check_digit(cnpj, FIRST_DIGIT_WEIGHTS)) + return false + end + return ((Runtime.code_at(cnpj, 13) - 48) == check_digit(cnpj, SECOND_DIGIT_WEIGHTS)) + end + + # Whether every character of the value is the same one. + def self.is_repeated(value) + if (value.length == 0) + return false + end + (1...value.length).each do |index| + if (Runtime.code_at(value, index) != Runtime.code_at(value, 0)) + return false + end + end + return true + end + end +end diff --git a/spec/bridge/out/ruby/lib/brazilian_utils_bridge/runtime.rb b/spec/bridge/out/ruby/lib/brazilian_utils_bridge/runtime.rb new file mode 100644 index 000000000..8e17a8f32 --- /dev/null +++ b/spec/bridge/out/ruby/lib/brazilian_utils_bridge/runtime.rb @@ -0,0 +1,287 @@ +# frozen_string_literal: true + +require 'json' +require 'net/http' +require 'uri' + +# The portable runtime for the Ruby target. +# +# Ruby indexes strings by character, which is what the generated code expects; everything else +# the code needs that is not plain syntax lives here. +module BrazilianUtilsBridge + # Helpers shared by the generated utilities. + module Runtime + # The code points JavaScript's trim() strips. Ruby's String#strip is a different set. + JS_WHITESPACE = [ + [0x09, 0x0d], [0x20, 0x20], [0xa0, 0xa0], [0x1680, 0x1680], [0x2000, 0x200a], + [0x2028, 0x2029], [0x202f, 0x202f], [0x205f, 0x205f], [0x3000, 0x3000], [0xfeff, 0xfeff] + ].freeze + + # One step of a compiled pattern: repeat a class between min and max times. + PatternStep = Struct.new(:char_class, :min, :max, :capture) + + # Whether a code point belongs to a class. + def self.in_class(char_class, code) + char_class.each do |span| + return true if code >= span[0] && code <= span[1] + end + + false + end + + # Reads one code point, or -1 when the index is out of range. + def self.code_at(value, index) + return -1 if index.negative? || index >= value.length + + value[index].ord + end + + # Whether any character of the value belongs to the class. + def self.class_has(char_class, value) + value.each_char.any? { |char| in_class(char_class, char.ord) } + end + + # Keeps only the characters of the value that belong to the class. + def self.keep_class(char_class, value) + value.each_char.select { |char| in_class(char_class, char.ord) }.join + end + + # Runs a compiled pattern against the whole value, greedily and without backtracking. + def self.pattern_test(steps, value) + chars = value.chars + index = 0 + + steps.each do |step| + count = 0 + + while (step.max.negative? || count < step.max) && index < chars.length && + in_class(step.char_class, chars[index].ord) + index += 1 + count += 1 + end + + return false if count < step.min + end + + index == chars.length + end + + # Strips the code points JavaScript's trim() strips. + def self.js_trim(value) + chars = value.chars + start = 0 + last = chars.length + + start += 1 while start < last && in_class(JS_WHITESPACE, chars[start].ord) + last -= 1 while last > start && in_class(JS_WHITESPACE, chars[last - 1].ord) + + chars[start...last].join + end + + # Left pads the value with a filler up to a length. + def self.pad_start(value, length, filler) + value.rjust(length, filler) + end + + # Reads a value as a string the way JavaScript's String(value) does. + def self.as_string(value) + return value if value.is_a?(String) + return 'true' if value == true + return 'false' if value == false + return 'null' if value.nil? + return value.to_s if value.is_a?(Integer) + + if value.is_a?(Float) + return value.to_i.to_s if value == value.to_i + + return value.to_s + end + + value.to_s + end + + # Reads an optional flag the way JavaScript reads truthiness. + def self.is_truthy(value) + !value.nil? && value != false + end + + # A dataset: the rows in the baked full order, and the rows of each key. + class Dataset + attr_reader :all, :by_key + + def initialize(rows, groups, full_order) + @all = full_order.map { |index| rows[index] } + @by_key = {} + groups.each { |key, indexes| @by_key[key] = indexes.map { |index| rows[index] } } + freeze + end + end + + # Materialises a dataset, resolving both orders once. + def self.make_dataset(rows, groups, full_order) + Dataset.new(rows, groups, full_order) + end + + # Every row of a dataset, in the baked full order. + def self.data_all(table) + table.all + end + + # The rows whose first column is the key given, empty when the key is unknown. + def self.data_rows(table, key) + table.by_key.fetch(key, []) + end + + # What a provider answered: the HTTP status, whether it counts as a success, and the body. + HttpResponse = Struct.new(:status, :ok, :body) + + # The origin every request is sent to instead of its own, when one is set. + # + # This is the conformance hook: the cross language replay points all seven targets at one + # local server, the same way the JavaScript suite points fetch at a mock. + def self.http_target(url) + base = ENV.fetch('BRUTILS_BRIDGE_HTTP_ORIGIN', '') + + return url if base.empty? + + "#{base}/#{url.sub(%r{\Ahttps?://}, '')}" + end + + # Performs an HTTP GET, retrying a transient transport failure with a linear backoff. + def self.http_get(url, retries, retry_delay_ms) + target = URI.parse(http_target(url)) + attempt = 0 + + loop do + begin + answer = Net::HTTP.get_response(target) + rescue StandardError + return HttpResponse.new(0, false, nil) if attempt >= retries + + sleep(retry_delay_ms * (attempt + 1) / 1000.0) + attempt += 1 + next + end + + status = answer.code.to_i + body = begin + JSON.parse(answer.body) + rescue StandardError + nil + end + + return HttpResponse.new(status, status >= 200 && status < 300, body) + end + end + + # Whether the caller handed a number where a string or a number was declared. + def self.is_number(value) + value.is_a?(Numeric) + end + + # Whether a value is a list. + def self.is_list(value) + value.is_a?(Array) + end + + # Whether a list holds a value. + def self.list_has(items, value) + items.include?(value) + end + + # Reads one field of a JSON body, treating anything that is not an object as empty. + def self.json_field(body, key) + return nil unless body.is_a?(Hash) + + body[key] + end + + # Reads a string field of a JSON body, answering '' when it is missing or not a string. + def self.json_string(body, key) + found = json_field(body, key) + + found.is_a?(String) ? found : '' + end + + # Reads an integer field of a JSON body, answering -1 when it is missing or not a number. + def self.json_int(body, key) + found = json_field(body, key) + + found.is_a?(Numeric) && !found.is_a?(TrueClass) ? found.to_i : -1 + end + + # Whether a field of a JSON body is truthy, the way JavaScript reads truthiness. + def self.json_truthy(body, key) + found = json_field(body, key) + + !(found.nil? || found == false || found == 0 || found == '') + end + + # Whether a field of a JSON body is exactly true. + def self.json_is_true(body, key) + json_field(body, key) == true + end + + # The running attempts of a race, and what each one ended with. + class Attempts + attr_reader :settled, :total + attr_accessor :outcomes + + def initialize(total) + @settled = Queue.new + @total = total + @outcomes = [] + end + end + + # The error name and every name it inherits from, which is what a failure is matched on. + def self.kinds_of(error) + kinds = [] + current = error.class + + while current + kinds.push(current.name.to_s.split('::').last) + current = current.superclass + end + + kinds + end + + # Starts one attempt per item, all at once. + # + # This is the only concurrency primitive of the portable subset. Ruby has no promise to + # colour a function with, so the work goes on threads and the caller simply waits. + def self.start_all(run, items, argument) + attempts = Attempts.new(items.length) + + items.each do |item| + Thread.new do + begin + attempts.settled.push([true, run.call(item, argument), []]) + rescue StandardError => e + attempts.settled.push([false, nil, kinds_of(e)]) + end + end + end + + attempts + end + + # The value of the first attempt that succeeds, or nil once every attempt has failed. + def self.first_success(attempts) + while attempts.outcomes.length < attempts.total + outcome = attempts.settled.pop + attempts.outcomes.push(outcome) + + return outcome[1] if outcome[0] + end + + nil + end + + # Whether any attempt failed with a given error kind. + def self.any_failed_with(attempts, kind) + attempts.outcomes.any? { |ok, _value, kinds| !ok && kinds.include?(kind) } + end + end +end diff --git a/spec/bridge/out/rust/Cargo.toml b/spec/bridge/out/rust/Cargo.toml new file mode 100644 index 000000000..fbff52c34 --- /dev/null +++ b/spec/bridge/out/rust/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "brazilian_utils_bridge" +version = "0.0.0" +edition = "2021" +publish = false + +[dependencies] +serde_json = "1" +ureq = "3" + +[lib] +path = "src/lib.rs" +# lib for a Rust caller, cdylib and staticlib for every binding that is not Rust. +crate-type = ["lib", "cdylib", "staticlib"] diff --git a/spec/bridge/out/rust/conformance_cabi.c b/spec/bridge/out/rust/conformance_cabi.c new file mode 100644 index 000000000..41961fbf5 --- /dev/null +++ b/spec/bridge/out/rust/conformance_cabi.c @@ -0,0 +1,226 @@ +/* Code generated by spec/bridge/conformance/drivers.ts. DO NOT EDIT. + * + * Replays the recorded tables over the C ABI the Rust crate exposes: the same surface a + * hand-written binding in Python, Ruby, C#, Java or Erlang would call. Only the utilities the + * ABI can carry appear here; the rest need a richer surface than pointers and integers. + */ +#include +#include +#include +#include + +#include "include/format_cnpj.h" +#include "include/is_valid_cnpj.h" + +#define MAX_LINE (1 << 20) + +static const char *TARGET = "cabi"; + +struct tally { + int passed; + int failed; + int skipped; +}; + +/* Reads back the three characters the table format escapes, in place. */ +static void unescape(char *value) { + char *write = value; + + for (const char *read = value; *read != '\0'; read++) { + if (*read != '\\' || read[1] == '\0') { + *write++ = *read; + + continue; + } + + read++; + *write++ = *read == 't' ? '\t' : *read == 'n' ? '\n' : *read; + } + + *write = '\0'; +} + +/* Splits a line on tabs, in place. */ +static int split(char *line, char **fields, int max) { + int count = 0; + + fields[count++] = line; + + for (char *cursor = line; *cursor != '\0'; cursor++) { + if (*cursor == '\t' && count < max) { + *cursor = '\0'; + fields[count++] = cursor + 1; + } + } + + return count; +} + +/* Whether this target can express the call a row describes. */ +static int runs(const char *targets) { + if (strcmp(targets, "*") == 0) { + return 1; + } + + const char *cursor = targets; + size_t width = strlen(TARGET); + + while (cursor != NULL) { + if (strncmp(cursor, TARGET, width) == 0 && (cursor[width] == '\0' || cursor[width] == '|')) { + return 1; + } + + cursor = strchr(cursor, '|'); + + if (cursor != NULL) { + cursor++; + } + } + + return 0; +} + +/* Counts one comparison, and shows the first few that disagree. */ +static void report(const char *fn, const char *actual, const char *expected, struct tally *counts) { + if (strcmp(actual, expected) == 0) { + counts->passed++; + + return; + } + + counts->failed++; + + if (counts->failed <= 3) { + fprintf(stderr, "FAIL %s expected %.120s got %.120s\n", fn, expected, actual); + } +} + +/* Replays what formatCnpj answers, over the C ABI. */ +static struct tally check_format_cnpj(void) { + struct tally counts = {0, 0, 0}; + FILE *table = fopen("../../conformance/recorded/format-cnpj.tsv", "r"); + + if (table == NULL) { + perror("../../conformance/recorded/format-cnpj.tsv"); + exit(1); + } + + char *line = malloc(MAX_LINE); + char *fields[64]; + + /* The header. */ + if (fgets(line, MAX_LINE, table) == NULL) { + exit(1); + } + + while (fgets(line, MAX_LINE, table) != NULL) { + line[strcspn(line, "\n")] = '\0'; + + if (line[0] == '\0') { + continue; + } + + split(line, fields, 64); + + if (!runs(fields[0])) { + counts.skipped++; + + continue; + } + + unescape(fields[1]); + unescape(fields[6]); + + uint8_t answer[512]; + intptr_t length = format_cnpj((const uint8_t *)fields[1], strlen(fields[1]), fields[4][0] == '\0' ? -1 : (atoll(fields[4])), fields[5][0] == '\0' ? 0 : (strcmp(fields[5], "1") == 0), fields[3][0] == '\0' ? 0 : (strcmp(fields[3], "1") == 0), answer, sizeof answer - 1); + + if (length < 0 || (size_t)length >= sizeof answer) { + length = 0; + } + + answer[length] = '\0'; + + const char *actual = (const char *)answer; + + report("formatCnpj", actual, fields[6], &counts); + } + + free(line); + fclose(table); + + return counts; +} + +/* Replays what isValidCnpj answers, over the C ABI. */ +static struct tally check_is_valid_cnpj(void) { + struct tally counts = {0, 0, 0}; + FILE *table = fopen("../../conformance/recorded/is-valid-cnpj.tsv", "r"); + + if (table == NULL) { + perror("../../conformance/recorded/is-valid-cnpj.tsv"); + exit(1); + } + + char *line = malloc(MAX_LINE); + char *fields[64]; + + /* The header. */ + if (fgets(line, MAX_LINE, table) == NULL) { + exit(1); + } + + while (fgets(line, MAX_LINE, table) != NULL) { + line[strcspn(line, "\n")] = '\0'; + + if (line[0] == '\0') { + continue; + } + + split(line, fields, 64); + + if (!runs(fields[0])) { + counts.skipped++; + + continue; + } + + unescape(fields[1]); + unescape(fields[4]); + + const char *actual = is_valid_cnpj((const uint8_t *)fields[1], strlen(fields[1]), fields[3][0] == '\0' ? -1 : (atoll(fields[3]))) ? "true" : "false"; + + report("isValidCnpj", actual, fields[4], &counts); + } + + free(line); + fclose(table); + + return counts; +} + +int main(void) { + int failed = 0; + struct tally counts; + + counts = check_format_cnpj(); + failed += counts.failed; + printf("%s: formatCnpj %d/%d matched", TARGET, counts.passed, counts.passed + counts.failed); + + if (counts.skipped > 0) { + printf(" (%d not expressible)", counts.skipped); + } + + printf("\n"); + + counts = check_is_valid_cnpj(); + failed += counts.failed; + printf("%s: isValidCnpj %d/%d matched", TARGET, counts.passed, counts.passed + counts.failed); + + if (counts.skipped > 0) { + printf(" (%d not expressible)", counts.skipped); + } + + printf("\n"); + + return failed == 0 ? 0 : 1; +} diff --git a/spec/bridge/out/rust/include/format_cnpj.h b/spec/bridge/out/rust/include/format_cnpj.h new file mode 100644 index 000000000..948f5c074 --- /dev/null +++ b/spec/bridge/out/rust/include/format_cnpj.h @@ -0,0 +1,28 @@ +/* Code generated from spec/bridge/source/format-cnpj.ts. DO NOT EDIT. + * + * The C surface of the shared core. A binding hands in pointers, lengths and integers; it owns + * every buffer, and the core allocates nothing on its behalf. + * + * An option that was not given is passed as its "unset" sentinel: -1 for a number, 0 for a flag. + * A function that answers text writes into `out` and returns the byte length; when the buffer + * is too small nothing is written and the length needed is returned, so the caller can size it + * and call again. + */ +#ifndef BRAZILIAN_UTILS_FORMAT_CNPJ_H +#define BRAZILIAN_UTILS_FORMAT_CNPJ_H + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* Formats a given CNPJ (Cadastro Nacional da Pessoa Jurídica) value. */ +intptr_t format_cnpj(const uint8_t * value_ptr, size_t value_len, int64_t options_version, int32_t options_obfuscate, int32_t options_pad, uint8_t *out, size_t out_len); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/spec/bridge/out/rust/include/is_valid_cnpj.h b/spec/bridge/out/rust/include/is_valid_cnpj.h new file mode 100644 index 000000000..da6375867 --- /dev/null +++ b/spec/bridge/out/rust/include/is_valid_cnpj.h @@ -0,0 +1,28 @@ +/* Code generated from spec/bridge/source/is-valid-cnpj.ts. DO NOT EDIT. + * + * The C surface of the shared core. A binding hands in pointers, lengths and integers; it owns + * every buffer, and the core allocates nothing on its behalf. + * + * An option that was not given is passed as its "unset" sentinel: -1 for a number, 0 for a flag. + * A function that answers text writes into `out` and returns the byte length; when the buffer + * is too small nothing is written and the length needed is returned, so the caller can size it + * and call again. + */ +#ifndef BRAZILIAN_UTILS_IS_VALID_CNPJ_H +#define BRAZILIAN_UTILS_IS_VALID_CNPJ_H + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* Validates if a CNPJ (Cadastro Nacional da Pessoa Jurídica) is valid. */ +int32_t is_valid_cnpj(const uint8_t * cnpj_ptr, size_t cnpj_len, int64_t options_version); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/spec/bridge/out/rust/src/bin/conformance.rs b/spec/bridge/out/rust/src/bin/conformance.rs new file mode 100644 index 000000000..01058e04f --- /dev/null +++ b/spec/bridge/out/rust/src/bin/conformance.rs @@ -0,0 +1,263 @@ +// Code generated by spec/bridge/conformance/drivers.ts. DO NOT EDIT. +// +// Replays the recorded tables against the generated Rust. + +use brazilian_utils_bridge::format_cnpj; +use brazilian_utils_bridge::get_address_info_by_cep; +use brazilian_utils_bridge::get_municipalities; +use brazilian_utils_bridge::is_valid_cnpj; + +const TARGET: &str = "rust"; + +#[derive(Default)] +struct Tally { + passed: usize, + failed: usize, + skipped: usize, +} + +/// Reads back the three characters the table format escapes. +fn unescape(value: &str) -> String { + value + .replace("\\t", "\t") + .replace("\\n", "\n") + .replace("\\\\", "\\") +} + +/// Whether this target can express the call a row describes. +fn runs(targets: &str) -> bool { + targets == "*" || targets.split('|').any(|name| name == TARGET) +} + +/// Counts one comparison, and shows the first few that disagree. +fn report(name: &str, actual: &str, expected: &str, counts: &mut Tally) { + if actual == expected { + counts.passed += 1; + + return; + } + + counts.failed += 1; + + if counts.failed <= 3 { + eprintln!( + "FAIL {} expected {:?} got {:?}", + name, + &expected[..expected.len().min(120)], + &actual[..actual.len().min(120)] + ); + } +} + +fn render_get_address_info_by_cep_address_info(value: &get_address_info_by_cep::AddressInfo) -> String { + format!("{}|{}|{}|{}|{}", value.cep.to_string(), value.state.to_string(), value.city.to_string(), value.neighborhood.to_string(), value.street.to_string()) +} + +fn render_get_municipalities_municipality(value: &get_municipalities::Municipality) -> String { + format!("{}|{}|{}", value.code.to_string(), value.name.to_string(), value.state_code.to_string()) +} + +fn render_list_get_municipalities_municipality(items: &[get_municipalities::Municipality]) -> String { + let mut out = items.len().to_string(); + + for item in items { + out.push('\n'); + out.push_str(&render_get_municipalities_municipality(&item.clone())); + } + + out +} + +/// Replays what `formatCnpj` answers. +fn check_format_cnpj() -> Tally { + let table = std::fs::read_to_string("../../conformance/recorded/format-cnpj.tsv").expect("the recorded table"); + let mut counts = Tally::default(); + + for line in table.lines().skip(1) { + if line.is_empty() { + continue; + } + + let parts: Vec<&str> = line.split('\t').collect(); + + if !runs(parts[0]) { + counts.skipped += 1; + + continue; + } + + let argument0 = unescape(parts[1]); + let mut options = format_cnpj::FormatCnpjOptions::default(); + let mut given = false; + + if !parts[3].is_empty() { + options.pad = Some(parts[3] == "1"); + given = true; + } + + if !parts[4].is_empty() { + options.version = Some(parts[4].parse().expect("a number")); + given = true; + } + + if !parts[5].is_empty() { + options.obfuscate = Some(parts[5] == "1"); + given = true; + } + + let actual = format_cnpj::format_cnpj(argument0.as_str(), if given { Some(&options) } else { None }).to_string(); + + report("formatCnpj", &actual, &unescape(parts[6]), &mut counts); + } + + counts +} + +/// Replays what `getAddressInfoByCep` answers. +fn check_get_address_info_by_cep() -> Tally { + let table = std::fs::read_to_string("../../conformance/recorded/get-address-info-by-cep.tsv").expect("the recorded table"); + let mut counts = Tally::default(); + + for line in table.lines().skip(1) { + if line.is_empty() { + continue; + } + + let parts: Vec<&str> = line.split('\t').collect(); + + if !runs(parts[0]) { + counts.skipped += 1; + + continue; + } + + let argument0 = unescape(parts[1]); + let mut options = get_address_info_by_cep::GetAddressInfoByCepOptions::default(); + let mut given = false; + + if !parts[3].is_empty() { + options.providers = Some(if parts[3] == "[]" { Vec::new() } else { parts[3].split('|').map(str::to_string).collect() }); + given = true; + } + + let actual = match get_address_info_by_cep::get_address_info_by_cep(argument0.as_str(), if given { Some(&options) } else { None }) { + Ok(found) => render_get_address_info_by_cep_address_info(&found), + Err(error) => format!("!{}|{}", error.kind(), error.message), + }; + + report("getAddressInfoByCep", &actual, &unescape(parts[4]), &mut counts); + } + + counts +} + +/// Replays what `getMunicipalities` answers. +fn check_get_municipalities() -> Tally { + let table = std::fs::read_to_string("../../conformance/recorded/get-municipalities.tsv").expect("the recorded table"); + let mut counts = Tally::default(); + + for line in table.lines().skip(1) { + if line.is_empty() { + continue; + } + + let parts: Vec<&str> = line.split('\t').collect(); + + if !runs(parts[0]) { + counts.skipped += 1; + + continue; + } + + let argument0 = if parts[1] == "1" { Some(unescape(parts[2])) } else { None }; + + let actual = render_list_get_municipalities_municipality(&get_municipalities::get_municipalities(argument0.as_deref())); + + report("getMunicipalities", &actual, &unescape(parts[3]), &mut counts); + } + + counts +} + +/// Replays what `isValidCnpj` answers. +fn check_is_valid_cnpj() -> Tally { + let table = std::fs::read_to_string("../../conformance/recorded/is-valid-cnpj.tsv").expect("the recorded table"); + let mut counts = Tally::default(); + + for line in table.lines().skip(1) { + if line.is_empty() { + continue; + } + + let parts: Vec<&str> = line.split('\t').collect(); + + if !runs(parts[0]) { + counts.skipped += 1; + + continue; + } + + let argument0 = unescape(parts[1]); + let mut options = is_valid_cnpj::IsValidCnpjOptions::default(); + let mut given = false; + + if !parts[3].is_empty() { + options.version = Some(parts[3].parse().expect("a number")); + given = true; + } + + let actual = is_valid_cnpj::is_valid_cnpj(argument0.as_str(), if given { Some(&options) } else { None }).to_string(); + + report("isValidCnpj", &actual, &unescape(parts[4]), &mut counts); + } + + counts +} + +fn main() { + let mut failed = 0; + + let counts = check_format_cnpj(); + failed += counts.failed; + println!( + "{}: formatCnpj {}/{} matched{}", + TARGET, + counts.passed, + counts.passed + counts.failed, + if counts.skipped == 0 { String::new() } else { format!(" ({} not expressible)", counts.skipped) } + ); + + let counts = check_get_address_info_by_cep(); + failed += counts.failed; + println!( + "{}: getAddressInfoByCep {}/{} matched{}", + TARGET, + counts.passed, + counts.passed + counts.failed, + if counts.skipped == 0 { String::new() } else { format!(" ({} not expressible)", counts.skipped) } + ); + + let counts = check_get_municipalities(); + failed += counts.failed; + println!( + "{}: getMunicipalities {}/{} matched{}", + TARGET, + counts.passed, + counts.passed + counts.failed, + if counts.skipped == 0 { String::new() } else { format!(" ({} not expressible)", counts.skipped) } + ); + + let counts = check_is_valid_cnpj(); + failed += counts.failed; + println!( + "{}: isValidCnpj {}/{} matched{}", + TARGET, + counts.passed, + counts.passed + counts.failed, + if counts.skipped == 0 { String::new() } else { format!(" ({} not expressible)", counts.skipped) } + ); + + if failed > 0 { + std::process::exit(1); + } +} diff --git a/spec/bridge/out/rust/src/cabi_format_cnpj.rs b/spec/bridge/out/rust/src/cabi_format_cnpj.rs new file mode 100644 index 000000000..4121be77c --- /dev/null +++ b/spec/bridge/out/rust/src/cabi_format_cnpj.rs @@ -0,0 +1,35 @@ +// Code generated from spec/bridge/source/format-cnpj.ts. DO NOT EDIT. +// +// The C ABI of this module: what a hand-written binding in Python, Ruby, C#, Java or Erlang +// calls. Everything is a pointer, a length or an integer, and nothing crosses that either side +// has to free. + +use crate::format_cnpj; + +/// Formats a given CNPJ (Cadastro Nacional da Pessoa Jurídica) value. +#[no_mangle] +pub unsafe extern "C" fn format_cnpj(value_ptr: *const u8, value_len: usize, options_version: i64, options_obfuscate: i32, options_pad: i32, out: *mut u8, out_len: usize) -> isize { + let value_value = match std::str::from_utf8(unsafe { + std::slice::from_raw_parts(value_ptr, value_len) + }) { + Ok(value) => value, + Err(_) => return -1, + }; + let options = format_cnpj::FormatCnpjOptions { + version: if options_version == -1 { None } else { Some(options_version) }, + obfuscate: if options_obfuscate == 0 { None } else { Some(options_obfuscate != 0) }, + pad: if options_pad == 0 { None } else { Some(options_pad != 0) }, + ..Default::default() + }; + let answer = format_cnpj::format_cnpj(value_value, Some(&options)); + let bytes = answer.as_bytes(); + + if out.is_null() || out_len < bytes.len() { + // The caller sizes its own buffer: answering the length lets it try again. + return bytes.len() as isize; + } + + unsafe { std::ptr::copy_nonoverlapping(bytes.as_ptr(), out, bytes.len()) }; + + bytes.len() as isize +} diff --git a/spec/bridge/out/rust/src/cabi_is_valid_cnpj.rs b/spec/bridge/out/rust/src/cabi_is_valid_cnpj.rs new file mode 100644 index 000000000..ccb042a72 --- /dev/null +++ b/spec/bridge/out/rust/src/cabi_is_valid_cnpj.rs @@ -0,0 +1,23 @@ +// Code generated from spec/bridge/source/is-valid-cnpj.ts. DO NOT EDIT. +// +// The C ABI of this module: what a hand-written binding in Python, Ruby, C#, Java or Erlang +// calls. Everything is a pointer, a length or an integer, and nothing crosses that either side +// has to free. + +use crate::is_valid_cnpj; + +/// Validates if a CNPJ (Cadastro Nacional da Pessoa Jurídica) is valid. +#[no_mangle] +pub unsafe extern "C" fn is_valid_cnpj(cnpj_ptr: *const u8, cnpj_len: usize, options_version: i64) -> i32 { + let cnpj_value = match std::str::from_utf8(unsafe { + std::slice::from_raw_parts(cnpj_ptr, cnpj_len) + }) { + Ok(value) => value, + Err(_) => return 0, + }; + let options = is_valid_cnpj::IsValidCnpjOptions { + version: if options_version == -1 { None } else { Some(options_version) }, + ..Default::default() + }; + i32::from(is_valid_cnpj::is_valid_cnpj(cnpj_value, Some(&options))) +} diff --git a/spec/bridge/out/rust/src/format_cnpj.rs b/spec/bridge/out/rust/src/format_cnpj.rs new file mode 100644 index 000000000..d7c5396fe --- /dev/null +++ b/spec/bridge/out/rust/src/format_cnpj.rs @@ -0,0 +1,89 @@ +// Code generated from spec/bridge/source/format-cnpj.ts. DO NOT EDIT. + +//! `formatCnpj`, written once. + +use crate::runtime; + +const CLASS0: runtime::CharClass = &[(0x30, 0x39)]; +const CLASS1: runtime::CharClass = &[(0x30, 0x39), (0x41, 0x5a), (0x61, 0x7a)]; + + + +const PATTERN: &str = "00.000.000/0000-00"; +const OBFUSCATED_PATTERN: &str = "**.000.000/0000-**"; + + + +/// Options of `formatCnpj`. +#[derive(Debug, Default, Clone, PartialEq, Eq)] +pub struct FormatCnpjOptions { + /// Whether to left pad the value with zeros up to the number of slots in the pattern (default: `false`). + pub pad: Option, + /// Which CNPJ format to read: `1` numeric only, `2` alphanumeric (default: `1`). + pub version: Option, + /// Whether to hide the first 2 digits and the 2 check digits with `*` (default: `false`). + pub obfuscate: Option, +} + + + +/// Formats a given CNPJ (Cadastro Nacional da Pessoa Jurídica) value. +pub fn format_cnpj(value: &str, options: Option<&FormatCnpjOptions>) -> String { + let options_version = match options { + None => -1, + Some(value) => value.version.unwrap_or(-1), + }; + let options_obfuscate = match options { + None => false, + Some(value) => value.obfuscate.unwrap_or(false), + }; + let options_pad = match options { + None => false, + Some(value) => value.pad.unwrap_or(false), + }; + let text: String = value.to_string(); + let mut cleaned: String = runtime::keep_class(CLASS0, &text); + if (options_version == 2) { + cleaned = runtime::upper(&runtime::keep_class(CLASS1, &text)); + } + let mut pattern: String = PATTERN.to_string(); + if options_obfuscate { + pattern = OBFUSCATED_PATTERN.to_string(); + } + return layout(&cleaned, &pattern, options_pad); +} + +/// Lays a value over a pattern. +pub fn layout(value: &str, pattern: &str, pad: bool) -> String { + let mut slots: i64 = 0; + for index in 0..runtime::len(&pattern) { + if ((runtime::code_at(&pattern, index) == 48) || (runtime::code_at(&pattern, index) == 42)) { + slots = (slots + 1); + } + } + let mut padded: String = value.to_string(); + if pad { + padded = runtime::pad_start(&value, slots, "0"); + } + let mut formatted: String = "".to_string(); + let mut cursor: i64 = 0; + for index in 0..runtime::len(&pattern) { + let slot: i64 = runtime::code_at(&pattern, index); + if ((slot == 48) || (slot == 42)) { + if (cursor >= runtime::len(&padded)) { + return formatted; + } + if (slot == 42) { + formatted = format!("{}{}", formatted, "*"); + } else { + formatted = format!("{}{}", formatted, runtime::slice(&padded, cursor, (cursor + 1))); + } + cursor = (cursor + 1); + } else { + if (cursor < runtime::len(&padded)) { + formatted = format!("{}{}", formatted, runtime::slice(&pattern, index, (index + 1))); + } + } + } + return formatted; +} diff --git a/spec/bridge/out/rust/src/get_address_info_by_cep.rs b/spec/bridge/out/rust/src/get_address_info_by_cep.rs new file mode 100644 index 000000000..fd02936f6 --- /dev/null +++ b/spec/bridge/out/rust/src/get_address_info_by_cep.rs @@ -0,0 +1,194 @@ +// Code generated from spec/bridge/source/get-address-info-by-cep.ts. DO NOT EDIT. + +//! Address lookup by CEP, written once. + +use crate::runtime; + +const CLASS0: runtime::CharClass = &[(0x30, 0x39)]; + +const PATTERN_CEP_FORMAT: &[runtime::PatternStep] = &[ + runtime::PatternStep { class: CLASS0, min: 8, max: 8, capture: false }, +]; + +const DEFAULT_PROVIDERS: &[&str] = &["viacep", "brasilapi"]; +const KNOWN_PROVIDERS: &[&str] = &["viacep", "widenet", "brasilapi"]; +const BRASIL_API_NOT_FOUND_STATUS: i64 = 404; +const HTTP_RETRIES: i64 = 2; +const HTTP_RETRY_DELAY_MS: i64 = 250; + +/// Base class of every error `getAddressInfoByCep` rejects with. +pub const GET_ADDRESS_INFO_BY_CEP_ERROR_KINDS: &[&str] = &["GetAddressInfoByCepError"]; + +/// Whether a failure is a GetAddressInfoByCepError. +pub fn is_get_address_info_by_cep_error(error: &runtime::Error) -> bool { + error.is_kind("GetAddressInfoByCepError") +} + +/// Thrown by `getAddressInfoByCep` when the value given is not a valid CEP. +pub const GET_ADDRESS_INFO_BY_CEP_VALIDATION_ERROR_KINDS: &[&str] = &["GetAddressInfoByCepValidationError", "GetAddressInfoByCepError"]; + +/// Whether a failure is a GetAddressInfoByCepValidationError. +pub fn is_get_address_info_by_cep_validation_error(error: &runtime::Error) -> bool { + error.is_kind("GetAddressInfoByCepValidationError") +} + +/// Thrown by `getAddressInfoByCep` when no CEP service knows the CEP. +pub const GET_ADDRESS_INFO_BY_CEP_NOT_FOUND_ERROR_KINDS: &[&str] = &["GetAddressInfoByCepNotFoundError", "GetAddressInfoByCepError"]; + +/// Whether a failure is a GetAddressInfoByCepNotFoundError. +pub fn is_get_address_info_by_cep_not_found_error(error: &runtime::Error) -> bool { + error.is_kind("GetAddressInfoByCepNotFoundError") +} + +/// Thrown by `getAddressInfoByCep` when every CEP service failed to answer. +pub const GET_ADDRESS_INFO_BY_CEP_SERVICE_ERROR_KINDS: &[&str] = &["GetAddressInfoByCepServiceError", "GetAddressInfoByCepError"]; + +/// Whether a failure is a GetAddressInfoByCepServiceError. +pub fn is_get_address_info_by_cep_service_error(error: &runtime::Error) -> bool { + error.is_kind("GetAddressInfoByCepServiceError") +} + +/// Raised inside a provider that did not answer. Only whether a failure was a not found is looked at when the provider failures are aggregated, so this one never leaves the module. +pub const CEP_PROVIDER_FAILURE_KINDS: &[&str] = &["CepProviderFailure"]; + +/// Whether a failure is a CepProviderFailure. +pub fn is_cep_provider_failure(error: &runtime::Error) -> bool { + error.is_kind("CepProviderFailure") +} + +/// The address `getAddressInfoByCep` returns for a CEP. +#[derive(Debug, Default, Clone, PartialEq, Eq)] +pub struct AddressInfo { + /// The 8 digit CEP, no mask. + pub cep: String, + /// Two letter state code, e.g. "SP". + pub state: String, + /// City name. + pub city: String, + /// Neighborhood name, empty when the CEP covers a whole city. + pub neighborhood: String, + /// Street name, empty when the CEP covers a whole city. + pub street: String, +} + +/// Options of `getAddressInfoByCep`. +#[derive(Debug, Default, Clone, PartialEq, Eq)] +pub struct GetAddressInfoByCepOptions { + /// Which CEP services to race, in the order given (default: `["viacep", "brasilapi"]`; the deprecated `"widenet"` provider is excluded from the default list, but can still be requested explicitly). + pub providers: Option>, +} + + + +/// Reads the address ViaCEP answers with. +/// +/// @see Based on: https://viacep.com.br/ +pub fn fetch_via_cep(cep: &str) -> Result { + let response: runtime::HttpResponse = runtime::http_get(&format!("{}{}", format!("{}{}", "https://viacep.com.br/ws/", cep), "/json/"), HTTP_RETRIES, HTTP_RETRY_DELAY_MS); + if !response.ok { + return Err(runtime::Error::new(CEP_PROVIDER_FAILURE_KINDS, "ViaCEP request failed")); + } + let found: String = runtime::json_string(&response.body, "cep"); + if (runtime::json_truthy(&response.body, "erro") || (found == "")) { + return Err(runtime::Error::new(GET_ADDRESS_INFO_BY_CEP_NOT_FOUND_ERROR_KINDS, "CEP n\u{e3}o encontrado")); + } + return Ok(AddressInfo { cep: runtime::keep_class(CLASS0, &found), state: runtime::json_string(&response.body, "uf"), city: runtime::json_string(&response.body, "localidade"), neighborhood: runtime::json_string(&response.body, "bairro"), street: runtime::json_string(&response.body, "logradouro") }); +} + +/// Reads the address Widenet answers with. +pub fn fetch_widenet(cep: &str) -> Result { + let response: runtime::HttpResponse = runtime::http_get(&format!("{}{}", format!("{}{}", "https://apps.widenet.com.br/busca-cep/api/cep/", cep), ".json"), HTTP_RETRIES, HTTP_RETRY_DELAY_MS); + if !response.ok { + return Err(runtime::Error::new(CEP_PROVIDER_FAILURE_KINDS, "Widenet request failed")); + } + let found: String = runtime::json_string(&response.body, "code"); + if (((runtime::json_int(&response.body, "status") != 200) || !runtime::json_is_true(&response.body, "ok")) || (found == "")) { + return Err(runtime::Error::new(GET_ADDRESS_INFO_BY_CEP_NOT_FOUND_ERROR_KINDS, "CEP n\u{e3}o encontrado")); + } + return Ok(AddressInfo { cep: runtime::keep_class(CLASS0, &found), state: runtime::json_string(&response.body, "state"), city: runtime::json_string(&response.body, "city"), neighborhood: runtime::json_string(&response.body, "district"), street: runtime::json_string(&response.body, "address") }); +} + +/// Reads the address BrasilAPI answers with. +/// +/// @see Based on: https://brasilapi.com.br/docs#tag/CEP +pub fn fetch_brasil_api(cep: &str) -> Result { + let response: runtime::HttpResponse = runtime::http_get(&format!("{}{}", format!("{}{}", "https://brasilapi.com.br/api/cep/v1/", cep), ""), HTTP_RETRIES, HTTP_RETRY_DELAY_MS); + if (response.status == BRASIL_API_NOT_FOUND_STATUS) { + return Err(runtime::Error::new(GET_ADDRESS_INFO_BY_CEP_NOT_FOUND_ERROR_KINDS, "CEP n\u{e3}o encontrado")); + } + if !response.ok { + return Err(runtime::Error::new(CEP_PROVIDER_FAILURE_KINDS, "BrasilAPI request failed")); + } + let found: String = runtime::json_string(&response.body, "cep"); + if (runtime::json_truthy(&response.body, "errors") || (found == "")) { + return Err(runtime::Error::new(GET_ADDRESS_INFO_BY_CEP_NOT_FOUND_ERROR_KINDS, "CEP n\u{e3}o encontrado")); + } + return Ok(AddressInfo { cep: runtime::keep_class(CLASS0, &found), state: runtime::json_string(&response.body, "state"), city: runtime::json_string(&response.body, "city"), neighborhood: runtime::json_string(&response.body, "neighborhood"), street: runtime::json_string(&response.body, "street") }); +} + +/// Asks one named provider for a CEP. +pub fn fetch_provider(provider: &str, cep: &str) -> Result { + if (provider == "viacep") { + return fetch_via_cep(&cep); + } + if (provider == "widenet") { + return fetch_widenet(&cep); + } + return fetch_brasil_api(&cep); +} + +/// The providers of a list that are known, in the order they were given. +pub fn known_providers(given: &[String]) -> Vec { + let mut kept: Vec = vec![]; + for provider in given { + if runtime::list_has(KNOWN_PROVIDERS, &provider) { + kept.push(provider.to_string()); + } + } + return kept; +} + +/// Fetches address information for a given CEP using multiple providers simultaneously. +/// Returns the result from the first provider that responds successfully. +/// +/// The providers are started together and raced, not tried one after the other, so a provider +/// that is retrying delays nothing for the others: its retries only push back the moment its own +/// failure lands, and therefore the moment an all-failed rejection can surface. +/// +/// @see Official: https://www.correios.com.br/enviar/precisa-de-ajuda/tudo-sobre-cep +/// @see Based on: https://viacep.com.br/ +/// ViaCEP, one of the two default providers. A third-party service, not a Correios one. +/// @see Based on: https://brasilapi.com.br/docs#tag/CEP +/// BrasilAPI, the other default provider. A third-party service, not a Correios one. +pub fn get_address_info_by_cep(cep: &str, options: Option<&GetAddressInfoByCepOptions>) -> Result { + let options_providers = match options { + None => None, + Some(value) => value.providers.clone(), + }; + let mut digits: String = runtime::keep_class(CLASS0, &cep.to_string()); + if false { + digits = runtime::pad_start(&digits, 8, "0"); + } + if !runtime::pattern_test(PATTERN_CEP_FORMAT, &digits) { + return Err(runtime::Error::new(GET_ADDRESS_INFO_BY_CEP_VALIDATION_ERROR_KINDS, "CEP inv\u{e1}lido")); + } + let mut chosen: Vec = DEFAULT_PROVIDERS.iter().map(|value| value.to_string()).collect(); + if options_providers.is_some() { + if !true { + return Err(runtime::Error::new(GET_ADDRESS_INFO_BY_CEP_VALIDATION_ERROR_KINDS, "Nenhum provedor v\u{e1}lido especificado")); + } + chosen = known_providers(&options_providers.clone().unwrap()); + if ((chosen.len() as i64) == 0) { + return Err(runtime::Error::new(GET_ADDRESS_INFO_BY_CEP_VALIDATION_ERROR_KINDS, "Nenhum provedor v\u{e1}lido especificado")); + } + } + let mut attempts: runtime::Attempts = runtime::start_all(fetch_provider, &chosen, &digits); + let found: Option = runtime::first_success(&mut attempts); + if found.is_some() { + return Ok(found.clone().unwrap()); + } + if runtime::any_failed_with(&attempts, "GetAddressInfoByCepNotFoundError") { + return Err(runtime::Error::new(GET_ADDRESS_INFO_BY_CEP_NOT_FOUND_ERROR_KINDS, "CEP n\u{e3}o encontrado em nenhum servi\u{e7}o")); + } + return Err(runtime::Error::new(GET_ADDRESS_INFO_BY_CEP_SERVICE_ERROR_KINDS, "Todos os servi\u{e7}os est\u{e3}o fora de servi\u{e7}o ou indispon\u{ed}veis")); +} diff --git a/spec/bridge/out/rust/src/get_municipalities.rs b/spec/bridge/out/rust/src/get_municipalities.rs new file mode 100644 index 000000000..bbc8d553b --- /dev/null +++ b/spec/bridge/out/rust/src/get_municipalities.rs @@ -0,0 +1,5668 @@ +// Code generated from spec/bridge/source/get-municipalities.ts. DO NOT EDIT. + +//! Brazilian municipalities, written once. + +use crate::runtime; + + + + + + + + + +/// One Brazilian municipality, as the IBGE publishes it. +#[derive(Debug, Default, Clone, PartialEq, Eq)] +pub struct Municipality { + /// The 7-digit IBGE municipality code. + pub code: String, + /// The municipality name. + pub name: String, + /// The two-letter code of the state the municipality belongs to. + pub state_code: String, +} + +static MUNICIPALITIES_ROWS: &[runtime::Row] = &[ + &["AC", "Acrel\u{e2}ndia", "1200013"], + &["AC", "Assis Brasil", "1200054"], + &["AC", "Brasil\u{e9}ia", "1200104"], + &["AC", "Bujari", "1200138"], + &["AC", "Capixaba", "1200179"], + &["AC", "Cruzeiro do Sul", "1200203"], + &["AC", "Epitaciol\u{e2}ndia", "1200252"], + &["AC", "Feij\u{f3}", "1200302"], + &["AC", "Jord\u{e3}o", "1200328"], + &["AC", "M\u{e2}ncio Lima", "1200336"], + &["AC", "Manoel Urbano", "1200344"], + &["AC", "Marechal Thaumaturgo", "1200351"], + &["AC", "Pl\u{e1}cido de Castro", "1200385"], + &["AC", "Porto Acre", "1200807"], + &["AC", "Porto Walter", "1200393"], + &["AC", "Rio Branco", "1200401"], + &["AC", "Rodrigues Alves", "1200427"], + &["AC", "Santa Rosa do Purus", "1200435"], + &["AC", "Sena Madureira", "1200500"], + &["AC", "Senador Guiomard", "1200450"], + &["AC", "Tarauac\u{e1}", "1200609"], + &["AC", "Xapuri", "1200708"], + &["AL", "\u{c1}gua Branca", "2700102"], + &["AL", "Anadia", "2700201"], + &["AL", "Arapiraca", "2700300"], + &["AL", "Atalaia", "2700409"], + &["AL", "Barra de Santo Ant\u{f4}nio", "2700508"], + &["AL", "Barra de S\u{e3}o Miguel", "2700607"], + &["AL", "Batalha", "2700706"], + &["AL", "Bel\u{e9}m", "2700805"], + &["AL", "Belo Monte", "2700904"], + &["AL", "Boca da Mata", "2701001"], + &["AL", "Branquinha", "2701100"], + &["AL", "Cacimbinhas", "2701209"], + &["AL", "Cajueiro", "2701308"], + &["AL", "Campestre", "2701357"], + &["AL", "Campo Alegre", "2701407"], + &["AL", "Campo Grande", "2701506"], + &["AL", "Canapi", "2701605"], + &["AL", "Capela", "2701704"], + &["AL", "Carneiros", "2701803"], + &["AL", "Ch\u{e3} Preta", "2701902"], + &["AL", "Coit\u{e9} do N\u{f3}ia", "2702009"], + &["AL", "Col\u{f4}nia Leopoldina", "2702108"], + &["AL", "Coqueiro Seco", "2702207"], + &["AL", "Coruripe", "2702306"], + &["AL", "Cra\u{ed}bas", "2702355"], + &["AL", "Delmiro Gouveia", "2702405"], + &["AL", "Dois Riachos", "2702504"], + &["AL", "Estrela de Alagoas", "2702553"], + &["AL", "Feira Grande", "2702603"], + &["AL", "Feliz Deserto", "2702702"], + &["AL", "Flexeiras", "2702801"], + &["AL", "Girau do Ponciano", "2702900"], + &["AL", "Ibateguara", "2703007"], + &["AL", "Igaci", "2703106"], + &["AL", "Igreja Nova", "2703205"], + &["AL", "Inhapi", "2703304"], + &["AL", "Jacar\u{e9} dos Homens", "2703403"], + &["AL", "Jacu\u{ed}pe", "2703502"], + &["AL", "Japaratinga", "2703601"], + &["AL", "Jaramataia", "2703700"], + &["AL", "Jequi\u{e1} da Praia", "2703759"], + &["AL", "Joaquim Gomes", "2703809"], + &["AL", "Jundi\u{e1}", "2703908"], + &["AL", "Junqueiro", "2704005"], + &["AL", "Lagoa da Canoa", "2704104"], + &["AL", "Limoeiro de Anadia", "2704203"], + &["AL", "Macei\u{f3}", "2704302"], + &["AL", "Major Isidoro", "2704401"], + &["AL", "Mar Vermelho", "2704906"], + &["AL", "Maragogi", "2704500"], + &["AL", "Maravilha", "2704609"], + &["AL", "Marechal Deodoro", "2704708"], + &["AL", "Maribondo", "2704807"], + &["AL", "Mata Grande", "2705002"], + &["AL", "Matriz de Camaragibe", "2705101"], + &["AL", "Messias", "2705200"], + &["AL", "Minador do Negr\u{e3}o", "2705309"], + &["AL", "Monteir\u{f3}polis", "2705408"], + &["AL", "Murici", "2705507"], + &["AL", "Novo Lino", "2705606"], + &["AL", "Olho d'\u{c1}gua das Flores", "2705705"], + &["AL", "Olho d'\u{c1}gua do Casado", "2705804"], + &["AL", "Olho d'\u{c1}gua Grande", "2705903"], + &["AL", "Oliven\u{e7}a", "2706000"], + &["AL", "Ouro Branco", "2706109"], + &["AL", "Palestina", "2706208"], + &["AL", "Palmeira dos \u{cd}ndios", "2706307"], + &["AL", "P\u{e3}o de A\u{e7}\u{fa}car", "2706406"], + &["AL", "Pariconha", "2706422"], + &["AL", "Paripueira", "2706448"], + &["AL", "Passo de Camaragibe", "2706505"], + &["AL", "Paulo Jacinto", "2706604"], + &["AL", "Penedo", "2706703"], + &["AL", "Pia\u{e7}abu\u{e7}u", "2706802"], + &["AL", "Pilar", "2706901"], + &["AL", "Pindoba", "2707008"], + &["AL", "Piranhas", "2707107"], + &["AL", "Po\u{e7}o das Trincheiras", "2707206"], + &["AL", "Porto Calvo", "2707305"], + &["AL", "Porto de Pedras", "2707404"], + &["AL", "Porto Real do Col\u{e9}gio", "2707503"], + &["AL", "Quebrangulo", "2707602"], + &["AL", "Rio Largo", "2707701"], + &["AL", "Roteiro", "2707800"], + &["AL", "Santa Luzia do Norte", "2707909"], + &["AL", "Santana do Ipanema", "2708006"], + &["AL", "Santana do Munda\u{fa}", "2708105"], + &["AL", "S\u{e3}o Br\u{e1}s", "2708204"], + &["AL", "S\u{e3}o Jos\u{e9} da Laje", "2708303"], + &["AL", "S\u{e3}o Jos\u{e9} da Tapera", "2708402"], + &["AL", "S\u{e3}o Lu\u{ed}s do Quitunde", "2708501"], + &["AL", "S\u{e3}o Miguel dos Campos", "2708600"], + &["AL", "S\u{e3}o Miguel dos Milagres", "2708709"], + &["AL", "S\u{e3}o Sebasti\u{e3}o", "2708808"], + &["AL", "Satuba", "2708907"], + &["AL", "Senador Rui Palmeira", "2708956"], + &["AL", "Tanque d'Arca", "2709004"], + &["AL", "Taquarana", "2709103"], + &["AL", "Teot\u{f4}nio Vilela", "2709152"], + &["AL", "Traipu", "2709202"], + &["AL", "Uni\u{e3}o dos Palmares", "2709301"], + &["AL", "Vi\u{e7}osa", "2709400"], + &["AP", "Amap\u{e1}", "1600105"], + &["AP", "Cal\u{e7}oene", "1600204"], + &["AP", "Cutias", "1600212"], + &["AP", "Ferreira Gomes", "1600238"], + &["AP", "Itaubal", "1600253"], + &["AP", "Laranjal do Jari", "1600279"], + &["AP", "Macap\u{e1}", "1600303"], + &["AP", "Mazag\u{e3}o", "1600402"], + &["AP", "Oiapoque", "1600501"], + &["AP", "Pedra Branca do Amapari", "1600154"], + &["AP", "Porto Grande", "1600535"], + &["AP", "Pracu\u{fa}ba", "1600550"], + &["AP", "Santana", "1600600"], + &["AP", "Serra do Navio", "1600055"], + &["AP", "Tartarugalzinho", "1600709"], + &["AP", "Vit\u{f3}ria do Jari", "1600808"], + &["AM", "Alvar\u{e3}es", "1300029"], + &["AM", "Amatur\u{e1}", "1300060"], + &["AM", "Anam\u{e3}", "1300086"], + &["AM", "Anori", "1300102"], + &["AM", "Apu\u{ed}", "1300144"], + &["AM", "Atalaia do Norte", "1300201"], + &["AM", "Autazes", "1300300"], + &["AM", "Barcelos", "1300409"], + &["AM", "Barreirinha", "1300508"], + &["AM", "Benjamin Constant", "1300607"], + &["AM", "Beruri", "1300631"], + &["AM", "Boa Vista do Ramos", "1300680"], + &["AM", "Boca do Acre", "1300706"], + &["AM", "Borba", "1300805"], + &["AM", "Caapiranga", "1300839"], + &["AM", "Canutama", "1300904"], + &["AM", "Carauari", "1301001"], + &["AM", "Careiro", "1301100"], + &["AM", "Careiro da V\u{e1}rzea", "1301159"], + &["AM", "Coari", "1301209"], + &["AM", "Codaj\u{e1}s", "1301308"], + &["AM", "Eirunep\u{e9}", "1301407"], + &["AM", "Envira", "1301506"], + &["AM", "Fonte Boa", "1301605"], + &["AM", "Guajar\u{e1}", "1301654"], + &["AM", "Humait\u{e1}", "1301704"], + &["AM", "Ipixuna", "1301803"], + &["AM", "Iranduba", "1301852"], + &["AM", "Itacoatiara", "1301902"], + &["AM", "Itamarati", "1301951"], + &["AM", "Itapiranga", "1302009"], + &["AM", "Japur\u{e1}", "1302108"], + &["AM", "Juru\u{e1}", "1302207"], + &["AM", "Juta\u{ed}", "1302306"], + &["AM", "L\u{e1}brea", "1302405"], + &["AM", "Manacapuru", "1302504"], + &["AM", "Manaquiri", "1302553"], + &["AM", "Manaus", "1302603"], + &["AM", "Manicor\u{e9}", "1302702"], + &["AM", "Mara\u{e3}", "1302801"], + &["AM", "Mau\u{e9}s", "1302900"], + &["AM", "Nhamund\u{e1}", "1303007"], + &["AM", "Nova Olinda do Norte", "1303106"], + &["AM", "Novo Air\u{e3}o", "1303205"], + &["AM", "Novo Aripuan\u{e3}", "1303304"], + &["AM", "Parintins", "1303403"], + &["AM", "Pauini", "1303502"], + &["AM", "Presidente Figueiredo", "1303536"], + &["AM", "Rio Preto da Eva", "1303569"], + &["AM", "Santa Isabel do Rio Negro", "1303601"], + &["AM", "Santo Ant\u{f4}nio do I\u{e7}\u{e1}", "1303700"], + &["AM", "S\u{e3}o Gabriel da Cachoeira", "1303809"], + &["AM", "S\u{e3}o Paulo de Oliven\u{e7}a", "1303908"], + &["AM", "S\u{e3}o Sebasti\u{e3}o do Uatum\u{e3}", "1303957"], + &["AM", "Silves", "1304005"], + &["AM", "Tabatinga", "1304062"], + &["AM", "Tapau\u{e1}", "1304104"], + &["AM", "Tef\u{e9}", "1304203"], + &["AM", "Tonantins", "1304237"], + &["AM", "Uarini", "1304260"], + &["AM", "Urucar\u{e1}", "1304302"], + &["AM", "Urucurituba", "1304401"], + &["BA", "Aba\u{ed}ra", "2900108"], + &["BA", "Abar\u{e9}", "2900207"], + &["BA", "Acajutiba", "2900306"], + &["BA", "Adustina", "2900355"], + &["BA", "\u{c1}gua Fria", "2900405"], + &["BA", "Aiquara", "2900603"], + &["BA", "Alagoinhas", "2900702"], + &["BA", "Alcoba\u{e7}a", "2900801"], + &["BA", "Almadina", "2900900"], + &["BA", "Amargosa", "2901007"], + &["BA", "Am\u{e9}lia Rodrigues", "2901106"], + &["BA", "Am\u{e9}rica Dourada", "2901155"], + &["BA", "Anag\u{e9}", "2901205"], + &["BA", "Andara\u{ed}", "2901304"], + &["BA", "Andorinha", "2901353"], + &["BA", "Angical", "2901403"], + &["BA", "Anguera", "2901502"], + &["BA", "Antas", "2901601"], + &["BA", "Ant\u{f4}nio Cardoso", "2901700"], + &["BA", "Ant\u{f4}nio Gon\u{e7}alves", "2901809"], + &["BA", "Apor\u{e1}", "2901908"], + &["BA", "Apuarema", "2901957"], + &["BA", "Ara\u{e7}\u{e1}s", "2902054"], + &["BA", "Aracatu", "2902005"], + &["BA", "Araci", "2902104"], + &["BA", "Aramari", "2902203"], + &["BA", "Arataca", "2902252"], + &["BA", "Aratu\u{ed}pe", "2902302"], + &["BA", "Aurelino Leal", "2902401"], + &["BA", "Baian\u{f3}polis", "2902500"], + &["BA", "Baixa Grande", "2902609"], + &["BA", "Banza\u{ea}", "2902658"], + &["BA", "Barra", "2902708"], + &["BA", "Barra da Estiva", "2902807"], + &["BA", "Barra do Cho\u{e7}a", "2902906"], + &["BA", "Barra do Mendes", "2903003"], + &["BA", "Barra do Rocha", "2903102"], + &["BA", "Barreiras", "2903201"], + &["BA", "Barro Alto", "2903235"], + &["BA", "Barro Preto", "2903300"], + &["BA", "Barrocas", "2903276"], + &["BA", "Belmonte", "2903409"], + &["BA", "Belo Campo", "2903508"], + &["BA", "Biritinga", "2903607"], + &["BA", "Boa Nova", "2903706"], + &["BA", "Boa Vista do Tupim", "2903805"], + &["BA", "Bom Jesus da Lapa", "2903904"], + &["BA", "Bom Jesus da Serra", "2903953"], + &["BA", "Boninal", "2904001"], + &["BA", "Bonito", "2904050"], + &["BA", "Boquira", "2904100"], + &["BA", "Botupor\u{e3}", "2904209"], + &["BA", "Brej\u{f5}es", "2904308"], + &["BA", "Brejol\u{e2}ndia", "2904407"], + &["BA", "Brotas de Maca\u{fa}bas", "2904506"], + &["BA", "Brumado", "2904605"], + &["BA", "Buerarema", "2904704"], + &["BA", "Buritirama", "2904753"], + &["BA", "Caatiba", "2904803"], + &["BA", "Cabaceiras do Paragua\u{e7}u", "2904852"], + &["BA", "Cachoeira", "2904902"], + &["BA", "Cacul\u{e9}", "2905008"], + &["BA", "Ca\u{e9}m", "2905107"], + &["BA", "Caetanos", "2905156"], + &["BA", "Caetit\u{e9}", "2905206"], + &["BA", "Cafarnaum", "2905305"], + &["BA", "Cairu", "2905404"], + &["BA", "Caldeir\u{e3}o Grande", "2905503"], + &["BA", "Camacan", "2905602"], + &["BA", "Cama\u{e7}ari", "2905701"], + &["BA", "Camamu", "2905800"], + &["BA", "Campo Alegre de Lourdes", "2905909"], + &["BA", "Campo Formoso", "2906006"], + &["BA", "Can\u{e1}polis", "2906105"], + &["BA", "Canarana", "2906204"], + &["BA", "Canavieiras", "2906303"], + &["BA", "Candeal", "2906402"], + &["BA", "Candeias", "2906501"], + &["BA", "Candiba", "2906600"], + &["BA", "C\u{e2}ndido Sales", "2906709"], + &["BA", "Cansan\u{e7}\u{e3}o", "2906808"], + &["BA", "Canudos", "2906824"], + &["BA", "Capela do Alto Alegre", "2906857"], + &["BA", "Capim Grosso", "2906873"], + &["BA", "Cara\u{ed}bas", "2906899"], + &["BA", "Caravelas", "2906907"], + &["BA", "Cardeal da Silva", "2907004"], + &["BA", "Carinhanha", "2907103"], + &["BA", "Casa Nova", "2907202"], + &["BA", "Castro Alves", "2907301"], + &["BA", "Catol\u{e2}ndia", "2907400"], + &["BA", "Catu", "2907509"], + &["BA", "Caturama", "2907558"], + &["BA", "Central", "2907608"], + &["BA", "Chorroch\u{f3}", "2907707"], + &["BA", "C\u{ed}cero Dantas", "2907806"], + &["BA", "Cip\u{f3}", "2907905"], + &["BA", "Coaraci", "2908002"], + &["BA", "Cocos", "2908101"], + &["BA", "Concei\u{e7}\u{e3}o da Feira", "2908200"], + &["BA", "Concei\u{e7}\u{e3}o do Almeida", "2908309"], + &["BA", "Concei\u{e7}\u{e3}o do Coit\u{e9}", "2908408"], + &["BA", "Concei\u{e7}\u{e3}o do Jacu\u{ed}pe", "2908507"], + &["BA", "Conde", "2908606"], + &["BA", "Conde\u{fa}ba", "2908705"], + &["BA", "Contendas do Sincor\u{e1}", "2908804"], + &["BA", "Cora\u{e7}\u{e3}o de Maria", "2908903"], + &["BA", "Cordeiros", "2909000"], + &["BA", "Coribe", "2909109"], + &["BA", "Coronel Jo\u{e3}o S\u{e1}", "2909208"], + &["BA", "Correntina", "2909307"], + &["BA", "Cotegipe", "2909406"], + &["BA", "Cravol\u{e2}ndia", "2909505"], + &["BA", "Cris\u{f3}polis", "2909604"], + &["BA", "Crist\u{f3}polis", "2909703"], + &["BA", "Cruz das Almas", "2909802"], + &["BA", "Cura\u{e7}\u{e1}", "2909901"], + &["BA", "D\u{e1}rio Meira", "2910008"], + &["BA", "Dias d'\u{c1}vila", "2910057"], + &["BA", "Dom Bas\u{ed}lio", "2910107"], + &["BA", "Dom Macedo Costa", "2910206"], + &["BA", "El\u{ed}sio Medrado", "2910305"], + &["BA", "Encruzilhada", "2910404"], + &["BA", "Entre Rios", "2910503"], + &["BA", "\u{c9}rico Cardoso", "2900504"], + &["BA", "Esplanada", "2910602"], + &["BA", "Euclides da Cunha", "2910701"], + &["BA", "Eun\u{e1}polis", "2910727"], + &["BA", "F\u{e1}tima", "2910750"], + &["BA", "Feira da Mata", "2910776"], + &["BA", "Feira de Santana", "2910800"], + &["BA", "Filad\u{e9}lfia", "2910859"], + &["BA", "Firmino Alves", "2910909"], + &["BA", "Floresta Azul", "2911006"], + &["BA", "Formosa do Rio Preto", "2911105"], + &["BA", "Gandu", "2911204"], + &["BA", "Gavi\u{e3}o", "2911253"], + &["BA", "Gentio do Ouro", "2911303"], + &["BA", "Gl\u{f3}ria", "2911402"], + &["BA", "Gongogi", "2911501"], + &["BA", "Governador Mangabeira", "2911600"], + &["BA", "Guajeru", "2911659"], + &["BA", "Guanambi", "2911709"], + &["BA", "Guaratinga", "2911808"], + &["BA", "Heli\u{f3}polis", "2911857"], + &["BA", "Ia\u{e7}u", "2911907"], + &["BA", "Ibiassuc\u{ea}", "2912004"], + &["BA", "Ibicara\u{ed}", "2912103"], + &["BA", "Ibicoara", "2912202"], + &["BA", "Ibicu\u{ed}", "2912301"], + &["BA", "Ibipeba", "2912400"], + &["BA", "Ibipitanga", "2912509"], + &["BA", "Ibiquera", "2912608"], + &["BA", "Ibirapitanga", "2912707"], + &["BA", "Ibirapu\u{e3}", "2912806"], + &["BA", "Ibirataia", "2912905"], + &["BA", "Ibitiara", "2913002"], + &["BA", "Ibitit\u{e1}", "2913101"], + &["BA", "Ibotirama", "2913200"], + &["BA", "Ichu", "2913309"], + &["BA", "Igapor\u{e3}", "2913408"], + &["BA", "Igrapi\u{fa}na", "2913457"], + &["BA", "Igua\u{ed}", "2913507"], + &["BA", "Ilh\u{e9}us", "2913606"], + &["BA", "Inhambupe", "2913705"], + &["BA", "Ipecaet\u{e1}", "2913804"], + &["BA", "Ipia\u{fa}", "2913903"], + &["BA", "Ipir\u{e1}", "2914000"], + &["BA", "Ipupiara", "2914109"], + &["BA", "Irajuba", "2914208"], + &["BA", "Iramaia", "2914307"], + &["BA", "Iraquara", "2914406"], + &["BA", "Irar\u{e1}", "2914505"], + &["BA", "Irec\u{ea}", "2914604"], + &["BA", "Itabela", "2914653"], + &["BA", "Itaberaba", "2914703"], + &["BA", "Itabuna", "2914802"], + &["BA", "Itacar\u{e9}", "2914901"], + &["BA", "Itaet\u{e9}", "2915007"], + &["BA", "Itagi", "2915106"], + &["BA", "Itagib\u{e1}", "2915205"], + &["BA", "Itagimirim", "2915304"], + &["BA", "Itagua\u{e7}u da Bahia", "2915353"], + &["BA", "Itaju do Col\u{f4}nia", "2915403"], + &["BA", "Itaju\u{ed}pe", "2915502"], + &["BA", "Itamaraju", "2915601"], + &["BA", "Itamari", "2915700"], + &["BA", "Itamb\u{e9}", "2915809"], + &["BA", "Itanagra", "2915908"], + &["BA", "Itanh\u{e9}m", "2916005"], + &["BA", "Itaparica", "2916104"], + &["BA", "Itap\u{e9}", "2916203"], + &["BA", "Itapebi", "2916302"], + &["BA", "Itapetinga", "2916401"], + &["BA", "Itapicuru", "2916500"], + &["BA", "Itapitanga", "2916609"], + &["BA", "Itaquara", "2916708"], + &["BA", "Itarantim", "2916807"], + &["BA", "Itatim", "2916856"], + &["BA", "Itiru\u{e7}u", "2916906"], + &["BA", "Iti\u{fa}ba", "2917003"], + &["BA", "Itoror\u{f3}", "2917102"], + &["BA", "Itua\u{e7}u", "2917201"], + &["BA", "Ituber\u{e1}", "2917300"], + &["BA", "Iuiu", "2917334"], + &["BA", "Jaborandi", "2917359"], + &["BA", "Jacaraci", "2917409"], + &["BA", "Jacobina", "2917508"], + &["BA", "Jaguaquara", "2917607"], + &["BA", "Jaguarari", "2917706"], + &["BA", "Jaguaripe", "2917805"], + &["BA", "Janda\u{ed}ra", "2917904"], + &["BA", "Jequi\u{e9}", "2918001"], + &["BA", "Jeremoabo", "2918100"], + &["BA", "Jiquiri\u{e7}\u{e1}", "2918209"], + &["BA", "Jita\u{fa}na", "2918308"], + &["BA", "Jo\u{e3}o Dourado", "2918357"], + &["BA", "Juazeiro", "2918407"], + &["BA", "Jucuru\u{e7}u", "2918456"], + &["BA", "Jussara", "2918506"], + &["BA", "Jussari", "2918555"], + &["BA", "Jussiape", "2918605"], + &["BA", "Lafaiete Coutinho", "2918704"], + &["BA", "Lagoa Real", "2918753"], + &["BA", "Laje", "2918803"], + &["BA", "Lajed\u{e3}o", "2918902"], + &["BA", "Lajedinho", "2919009"], + &["BA", "Lajedo do Tabocal", "2919058"], + &["BA", "Lamar\u{e3}o", "2919108"], + &["BA", "Lap\u{e3}o", "2919157"], + &["BA", "Lauro de Freitas", "2919207"], + &["BA", "Len\u{e7}\u{f3}is", "2919306"], + &["BA", "Lic\u{ed}nio de Almeida", "2919405"], + &["BA", "Livramento de Nossa Senhora", "2919504"], + &["BA", "Lu\u{ed}s Eduardo Magalh\u{e3}es", "2919553"], + &["BA", "Macajuba", "2919603"], + &["BA", "Macarani", "2919702"], + &["BA", "Maca\u{fa}bas", "2919801"], + &["BA", "Macurur\u{e9}", "2919900"], + &["BA", "Madre de Deus", "2919926"], + &["BA", "Maetinga", "2919959"], + &["BA", "Maiquinique", "2920007"], + &["BA", "Mairi", "2920106"], + &["BA", "Malhada", "2920205"], + &["BA", "Malhada de Pedras", "2920304"], + &["BA", "Manoel Vitorino", "2920403"], + &["BA", "Mansid\u{e3}o", "2920452"], + &["BA", "Marac\u{e1}s", "2920502"], + &["BA", "Maragogipe", "2920601"], + &["BA", "Mara\u{fa}", "2920700"], + &["BA", "Marcion\u{ed}lio Souza", "2920809"], + &["BA", "Mascote", "2920908"], + &["BA", "Mata de S\u{e3}o Jo\u{e3}o", "2921005"], + &["BA", "Matina", "2921054"], + &["BA", "Medeiros Neto", "2921104"], + &["BA", "Miguel Calmon", "2921203"], + &["BA", "Milagres", "2921302"], + &["BA", "Mirangaba", "2921401"], + &["BA", "Mirante", "2921450"], + &["BA", "Monte Santo", "2921500"], + &["BA", "Morpar\u{e1}", "2921609"], + &["BA", "Morro do Chap\u{e9}u", "2921708"], + &["BA", "Mortugaba", "2921807"], + &["BA", "Mucug\u{ea}", "2921906"], + &["BA", "Mucuri", "2922003"], + &["BA", "Mulungu do Morro", "2922052"], + &["BA", "Mundo Novo", "2922102"], + &["BA", "Muniz Ferreira", "2922201"], + &["BA", "Muqu\u{e9}m do S\u{e3}o Francisco", "2922250"], + &["BA", "Muritiba", "2922300"], + &["BA", "Mutu\u{ed}pe", "2922409"], + &["BA", "Nazar\u{e9}", "2922508"], + &["BA", "Nilo Pe\u{e7}anha", "2922607"], + &["BA", "Nordestina", "2922656"], + &["BA", "Nova Cana\u{e3}", "2922706"], + &["BA", "Nova F\u{e1}tima", "2922730"], + &["BA", "Nova Ibi\u{e1}", "2922755"], + &["BA", "Nova Itarana", "2922805"], + &["BA", "Nova Reden\u{e7}\u{e3}o", "2922854"], + &["BA", "Nova Soure", "2922904"], + &["BA", "Nova Vi\u{e7}osa", "2923001"], + &["BA", "Novo Horizonte", "2923035"], + &["BA", "Novo Triunfo", "2923050"], + &["BA", "Olindina", "2923100"], + &["BA", "Oliveira dos Brejinhos", "2923209"], + &["BA", "Ouri\u{e7}angas", "2923308"], + &["BA", "Ourol\u{e2}ndia", "2923357"], + &["BA", "Palmas de Monte Alto", "2923407"], + &["BA", "Palmeiras", "2923506"], + &["BA", "Paramirim", "2923605"], + &["BA", "Paratinga", "2923704"], + &["BA", "Paripiranga", "2923803"], + &["BA", "Pau Brasil", "2923902"], + &["BA", "Paulo Afonso", "2924009"], + &["BA", "P\u{e9} de Serra", "2924058"], + &["BA", "Pedr\u{e3}o", "2924108"], + &["BA", "Pedro Alexandre", "2924207"], + &["BA", "Piat\u{e3}", "2924306"], + &["BA", "Pil\u{e3}o Arcado", "2924405"], + &["BA", "Pinda\u{ed}", "2924504"], + &["BA", "Pindoba\u{e7}u", "2924603"], + &["BA", "Pintadas", "2924652"], + &["BA", "Pira\u{ed} do Norte", "2924678"], + &["BA", "Pirip\u{e1}", "2924702"], + &["BA", "Piritiba", "2924801"], + &["BA", "Planaltino", "2924900"], + &["BA", "Planalto", "2925006"], + &["BA", "Po\u{e7}\u{f5}es", "2925105"], + &["BA", "Pojuca", "2925204"], + &["BA", "Ponto Novo", "2925253"], + &["BA", "Porto Seguro", "2925303"], + &["BA", "Potiragu\u{e1}", "2925402"], + &["BA", "Prado", "2925501"], + &["BA", "Presidente Dutra", "2925600"], + &["BA", "Presidente J\u{e2}nio Quadros", "2925709"], + &["BA", "Presidente Tancredo Neves", "2925758"], + &["BA", "Queimadas", "2925808"], + &["BA", "Quijingue", "2925907"], + &["BA", "Quixabeira", "2925931"], + &["BA", "Rafael Jambeiro", "2925956"], + &["BA", "Remanso", "2926004"], + &["BA", "Retirol\u{e2}ndia", "2926103"], + &["BA", "Riach\u{e3}o das Neves", "2926202"], + &["BA", "Riach\u{e3}o do Jacu\u{ed}pe", "2926301"], + &["BA", "Riacho de Santana", "2926400"], + &["BA", "Ribeira do Amparo", "2926509"], + &["BA", "Ribeira do Pombal", "2926608"], + &["BA", "Ribeir\u{e3}o do Largo", "2926657"], + &["BA", "Rio de Contas", "2926707"], + &["BA", "Rio do Ant\u{f4}nio", "2926806"], + &["BA", "Rio do Pires", "2926905"], + &["BA", "Rio Real", "2927002"], + &["BA", "Rodelas", "2927101"], + &["BA", "Ruy Barbosa", "2927200"], + &["BA", "Salinas da Margarida", "2927309"], + &["BA", "Salvador", "2927408"], + &["BA", "Santa B\u{e1}rbara", "2927507"], + &["BA", "Santa Br\u{ed}gida", "2927606"], + &["BA", "Santa Cruz Cabr\u{e1}lia", "2927705"], + &["BA", "Santa Cruz da Vit\u{f3}ria", "2927804"], + &["BA", "Santa In\u{ea}s", "2927903"], + &["BA", "Santa Luzia", "2928059"], + &["BA", "Santa Maria da Vit\u{f3}ria", "2928109"], + &["BA", "Santa Rita de C\u{e1}ssia", "2928406"], + &["BA", "Santa Terezinha", "2928505"], + &["BA", "Santaluz", "2928000"], + &["BA", "Santana", "2928208"], + &["BA", "Santan\u{f3}polis", "2928307"], + &["BA", "Santo Amaro", "2928604"], + &["BA", "Santo Ant\u{f4}nio de Jesus", "2928703"], + &["BA", "Santo Est\u{ea}v\u{e3}o", "2928802"], + &["BA", "S\u{e3}o Desid\u{e9}rio", "2928901"], + &["BA", "S\u{e3}o Domingos", "2928950"], + &["BA", "S\u{e3}o Felipe", "2929107"], + &["BA", "S\u{e3}o F\u{e9}lix", "2929008"], + &["BA", "S\u{e3}o F\u{e9}lix do Coribe", "2929057"], + &["BA", "S\u{e3}o Francisco do Conde", "2929206"], + &["BA", "S\u{e3}o Gabriel", "2929255"], + &["BA", "S\u{e3}o Gon\u{e7}alo dos Campos", "2929305"], + &["BA", "S\u{e3}o Jos\u{e9} da Vit\u{f3}ria", "2929354"], + &["BA", "S\u{e3}o Jos\u{e9} do Jacu\u{ed}pe", "2929370"], + &["BA", "S\u{e3}o Miguel das Matas", "2929404"], + &["BA", "S\u{e3}o Sebasti\u{e3}o do Pass\u{e9}", "2929503"], + &["BA", "Sapea\u{e7}u", "2929602"], + &["BA", "S\u{e1}tiro Dias", "2929701"], + &["BA", "Saubara", "2929750"], + &["BA", "Sa\u{fa}de", "2929800"], + &["BA", "Seabra", "2929909"], + &["BA", "Sebasti\u{e3}o Laranjeiras", "2930006"], + &["BA", "Senhor do Bonfim", "2930105"], + &["BA", "Sento S\u{e9}", "2930204"], + &["BA", "Serra do Ramalho", "2930154"], + &["BA", "Serra Dourada", "2930303"], + &["BA", "Serra Preta", "2930402"], + &["BA", "Serrinha", "2930501"], + &["BA", "Serrol\u{e2}ndia", "2930600"], + &["BA", "Sim\u{f5}es Filho", "2930709"], + &["BA", "S\u{ed}tio do Mato", "2930758"], + &["BA", "S\u{ed}tio do Quinto", "2930766"], + &["BA", "Sobradinho", "2930774"], + &["BA", "Souto Soares", "2930808"], + &["BA", "Tabocas do Brejo Velho", "2930907"], + &["BA", "Tanha\u{e7}u", "2931004"], + &["BA", "Tanque Novo", "2931053"], + &["BA", "Tanquinho", "2931103"], + &["BA", "Tapero\u{e1}", "2931202"], + &["BA", "Tapiramut\u{e1}", "2931301"], + &["BA", "Teixeira de Freitas", "2931350"], + &["BA", "Teodoro Sampaio", "2931400"], + &["BA", "Teofil\u{e2}ndia", "2931509"], + &["BA", "Teol\u{e2}ndia", "2931608"], + &["BA", "Terra Nova", "2931707"], + &["BA", "Tremedal", "2931806"], + &["BA", "Tucano", "2931905"], + &["BA", "Uau\u{e1}", "2932002"], + &["BA", "Uba\u{ed}ra", "2932101"], + &["BA", "Ubaitaba", "2932200"], + &["BA", "Ubat\u{e3}", "2932309"], + &["BA", "Uiba\u{ed}", "2932408"], + &["BA", "Umburanas", "2932457"], + &["BA", "Una", "2932507"], + &["BA", "Urandi", "2932606"], + &["BA", "Uru\u{e7}uca", "2932705"], + &["BA", "Utinga", "2932804"], + &["BA", "Valen\u{e7}a", "2932903"], + &["BA", "Valente", "2933000"], + &["BA", "V\u{e1}rzea da Ro\u{e7}a", "2933059"], + &["BA", "V\u{e1}rzea do Po\u{e7}o", "2933109"], + &["BA", "V\u{e1}rzea Nova", "2933158"], + &["BA", "Varzedo", "2933174"], + &["BA", "Vera Cruz", "2933208"], + &["BA", "Vereda", "2933257"], + &["BA", "Vit\u{f3}ria da Conquista", "2933307"], + &["BA", "Wagner", "2933406"], + &["BA", "Wanderley", "2933455"], + &["BA", "Wenceslau Guimar\u{e3}es", "2933505"], + &["BA", "Xique-Xique", "2933604"], + &["CE", "Abaiara", "2300101"], + &["CE", "Acarape", "2300150"], + &["CE", "Acara\u{fa}", "2300200"], + &["CE", "Acopiara", "2300309"], + &["CE", "Aiuaba", "2300408"], + &["CE", "Alc\u{e2}ntaras", "2300507"], + &["CE", "Altaneira", "2300606"], + &["CE", "Alto Santo", "2300705"], + &["CE", "Amontada", "2300754"], + &["CE", "Antonina do Norte", "2300804"], + &["CE", "Apuiar\u{e9}s", "2300903"], + &["CE", "Aquiraz", "2301000"], + &["CE", "Aracati", "2301109"], + &["CE", "Aracoiaba", "2301208"], + &["CE", "Ararend\u{e1}", "2301257"], + &["CE", "Araripe", "2301307"], + &["CE", "Aratuba", "2301406"], + &["CE", "Arneiroz", "2301505"], + &["CE", "Assar\u{e9}", "2301604"], + &["CE", "Aurora", "2301703"], + &["CE", "Baixio", "2301802"], + &["CE", "Banabui\u{fa}", "2301851"], + &["CE", "Barbalha", "2301901"], + &["CE", "Barreira", "2301950"], + &["CE", "Barro", "2302008"], + &["CE", "Barroquinha", "2302057"], + &["CE", "Baturit\u{e9}", "2302107"], + &["CE", "Beberibe", "2302206"], + &["CE", "Bela Cruz", "2302305"], + &["CE", "Boa Viagem", "2302404"], + &["CE", "Brejo Santo", "2302503"], + &["CE", "Camocim", "2302602"], + &["CE", "Campos Sales", "2302701"], + &["CE", "Canind\u{e9}", "2302800"], + &["CE", "Capistrano", "2302909"], + &["CE", "Caridade", "2303006"], + &["CE", "Carir\u{e9}", "2303105"], + &["CE", "Cariria\u{e7}u", "2303204"], + &["CE", "Cari\u{fa}s", "2303303"], + &["CE", "Carnaubal", "2303402"], + &["CE", "Cascavel", "2303501"], + &["CE", "Catarina", "2303600"], + &["CE", "Catunda", "2303659"], + &["CE", "Caucaia", "2303709"], + &["CE", "Cedro", "2303808"], + &["CE", "Chaval", "2303907"], + &["CE", "Chor\u{f3}", "2303931"], + &["CE", "Chorozinho", "2303956"], + &["CE", "Corea\u{fa}", "2304004"], + &["CE", "Crate\u{fa}s", "2304103"], + &["CE", "Crato", "2304202"], + &["CE", "Croat\u{e1}", "2304236"], + &["CE", "Cruz", "2304251"], + &["CE", "Deputado Irapuan Pinheiro", "2304269"], + &["CE", "Erer\u{e9}", "2304277"], + &["CE", "Eus\u{e9}bio", "2304285"], + &["CE", "Farias Brito", "2304301"], + &["CE", "Forquilha", "2304350"], + &["CE", "Fortaleza", "2304400"], + &["CE", "Fortim", "2304459"], + &["CE", "Frecheirinha", "2304509"], + &["CE", "General Sampaio", "2304608"], + &["CE", "Gra\u{e7}a", "2304657"], + &["CE", "Granja", "2304707"], + &["CE", "Granjeiro", "2304806"], + &["CE", "Groa\u{ed}ras", "2304905"], + &["CE", "Guai\u{fa}ba", "2304954"], + &["CE", "Guaraciaba do Norte", "2305001"], + &["CE", "Guaramiranga", "2305100"], + &["CE", "Hidrol\u{e2}ndia", "2305209"], + &["CE", "Horizonte", "2305233"], + &["CE", "Ibaretama", "2305266"], + &["CE", "Ibiapina", "2305308"], + &["CE", "Ibicuitinga", "2305332"], + &["CE", "Icapu\u{ed}", "2305357"], + &["CE", "Ic\u{f3}", "2305407"], + &["CE", "Iguatu", "2305506"], + &["CE", "Independ\u{ea}ncia", "2305605"], + &["CE", "Ipaporanga", "2305654"], + &["CE", "Ipaumirim", "2305704"], + &["CE", "Ipu", "2305803"], + &["CE", "Ipueiras", "2305902"], + &["CE", "Iracema", "2306009"], + &["CE", "Irau\u{e7}uba", "2306108"], + &["CE", "Itai\u{e7}aba", "2306207"], + &["CE", "Itaitinga", "2306256"], + &["CE", "Itapaj\u{e9}", "2306306"], + &["CE", "Itapipoca", "2306405"], + &["CE", "Itapi\u{fa}na", "2306504"], + &["CE", "Itarema", "2306553"], + &["CE", "Itatira", "2306603"], + &["CE", "Jaguaretama", "2306702"], + &["CE", "Jaguaribara", "2306801"], + &["CE", "Jaguaribe", "2306900"], + &["CE", "Jaguaruana", "2307007"], + &["CE", "Jardim", "2307106"], + &["CE", "Jati", "2307205"], + &["CE", "Jijoca de Jericoacoara", "2307254"], + &["CE", "Juazeiro do Norte", "2307304"], + &["CE", "Juc\u{e1}s", "2307403"], + &["CE", "Lavras da Mangabeira", "2307502"], + &["CE", "Limoeiro do Norte", "2307601"], + &["CE", "Madalena", "2307635"], + &["CE", "Maracana\u{fa}", "2307650"], + &["CE", "Maranguape", "2307700"], + &["CE", "Marco", "2307809"], + &["CE", "Martin\u{f3}pole", "2307908"], + &["CE", "Massap\u{ea}", "2308005"], + &["CE", "Mauriti", "2308104"], + &["CE", "Meruoca", "2308203"], + &["CE", "Milagres", "2308302"], + &["CE", "Milh\u{e3}", "2308351"], + &["CE", "Mira\u{ed}ma", "2308377"], + &["CE", "Miss\u{e3}o Velha", "2308401"], + &["CE", "Momba\u{e7}a", "2308500"], + &["CE", "Monsenhor Tabosa", "2308609"], + &["CE", "Morada Nova", "2308708"], + &["CE", "Mora\u{fa}jo", "2308807"], + &["CE", "Morrinhos", "2308906"], + &["CE", "Mucambo", "2309003"], + &["CE", "Mulungu", "2309102"], + &["CE", "Nova Olinda", "2309201"], + &["CE", "Nova Russas", "2309300"], + &["CE", "Novo Oriente", "2309409"], + &["CE", "Ocara", "2309458"], + &["CE", "Or\u{f3}s", "2309508"], + &["CE", "Pacajus", "2309607"], + &["CE", "Pacatuba", "2309706"], + &["CE", "Pacoti", "2309805"], + &["CE", "Pacuj\u{e1}", "2309904"], + &["CE", "Palhano", "2310001"], + &["CE", "Palm\u{e1}cia", "2310100"], + &["CE", "Paracuru", "2310209"], + &["CE", "Paraipaba", "2310258"], + &["CE", "Parambu", "2310308"], + &["CE", "Paramoti", "2310407"], + &["CE", "Pedra Branca", "2310506"], + &["CE", "Penaforte", "2310605"], + &["CE", "Pentecoste", "2310704"], + &["CE", "Pereiro", "2310803"], + &["CE", "Pindoretama", "2310852"], + &["CE", "Piquet Carneiro", "2310902"], + &["CE", "Pires Ferreira", "2310951"], + &["CE", "Poranga", "2311009"], + &["CE", "Porteiras", "2311108"], + &["CE", "Potengi", "2311207"], + &["CE", "Potiretama", "2311231"], + &["CE", "Quiterian\u{f3}polis", "2311264"], + &["CE", "Quixad\u{e1}", "2311306"], + &["CE", "Quixel\u{f4}", "2311355"], + &["CE", "Quixeramobim", "2311405"], + &["CE", "Quixer\u{e9}", "2311504"], + &["CE", "Reden\u{e7}\u{e3}o", "2311603"], + &["CE", "Reriutaba", "2311702"], + &["CE", "Russas", "2311801"], + &["CE", "Saboeiro", "2311900"], + &["CE", "Salitre", "2311959"], + &["CE", "Santa Quit\u{e9}ria", "2312205"], + &["CE", "Santana do Acara\u{fa}", "2312007"], + &["CE", "Santana do Cariri", "2312106"], + &["CE", "S\u{e3}o Benedito", "2312304"], + &["CE", "S\u{e3}o Gon\u{e7}alo do Amarante", "2312403"], + &["CE", "S\u{e3}o Jo\u{e3}o do Jaguaribe", "2312502"], + &["CE", "S\u{e3}o Lu\u{ed}s do Curu", "2312601"], + &["CE", "Senador Pompeu", "2312700"], + &["CE", "Senador S\u{e1}", "2312809"], + &["CE", "Sobral", "2312908"], + &["CE", "Solon\u{f3}pole", "2313005"], + &["CE", "Tabuleiro do Norte", "2313104"], + &["CE", "Tamboril", "2313203"], + &["CE", "Tarrafas", "2313252"], + &["CE", "Tau\u{e1}", "2313302"], + &["CE", "Teju\u{e7}uoca", "2313351"], + &["CE", "Tiangu\u{e1}", "2313401"], + &["CE", "Trairi", "2313500"], + &["CE", "Tururu", "2313559"], + &["CE", "Ubajara", "2313609"], + &["CE", "Umari", "2313708"], + &["CE", "Umirim", "2313757"], + &["CE", "Uruburetama", "2313807"], + &["CE", "Uruoca", "2313906"], + &["CE", "Varjota", "2313955"], + &["CE", "V\u{e1}rzea Alegre", "2314003"], + &["CE", "Vi\u{e7}osa do Cear\u{e1}", "2314102"], + &["DF", "Bras\u{ed}lia", "5300108"], + &["ES", "Afonso Cl\u{e1}udio", "3200102"], + &["ES", "\u{c1}gua Doce do Norte", "3200169"], + &["ES", "\u{c1}guia Branca", "3200136"], + &["ES", "Alegre", "3200201"], + &["ES", "Alfredo Chaves", "3200300"], + &["ES", "Alto Rio Novo", "3200359"], + &["ES", "Anchieta", "3200409"], + &["ES", "Apiac\u{e1}", "3200508"], + &["ES", "Aracruz", "3200607"], + &["ES", "At\u{ed}lio Viv\u{e1}cqua", "3200706"], + &["ES", "Baixo Guandu", "3200805"], + &["ES", "Barra de S\u{e3}o Francisco", "3200904"], + &["ES", "Boa Esperan\u{e7}a", "3201001"], + &["ES", "Bom Jesus do Norte", "3201100"], + &["ES", "Brejetuba", "3201159"], + &["ES", "Cachoeiro de Itapemirim", "3201209"], + &["ES", "Cariacica", "3201308"], + &["ES", "Castelo", "3201407"], + &["ES", "Colatina", "3201506"], + &["ES", "Concei\u{e7}\u{e3}o da Barra", "3201605"], + &["ES", "Concei\u{e7}\u{e3}o do Castelo", "3201704"], + &["ES", "Divino de S\u{e3}o Louren\u{e7}o", "3201803"], + &["ES", "Domingos Martins", "3201902"], + &["ES", "Dores do Rio Preto", "3202009"], + &["ES", "Ecoporanga", "3202108"], + &["ES", "Fund\u{e3}o", "3202207"], + &["ES", "Governador Lindenberg", "3202256"], + &["ES", "Gua\u{e7}u\u{ed}", "3202306"], + &["ES", "Guarapari", "3202405"], + &["ES", "Ibatiba", "3202454"], + &["ES", "Ibira\u{e7}u", "3202504"], + &["ES", "Ibitirama", "3202553"], + &["ES", "Iconha", "3202603"], + &["ES", "Irupi", "3202652"], + &["ES", "Itagua\u{e7}u", "3202702"], + &["ES", "Itapemirim", "3202801"], + &["ES", "Itarana", "3202900"], + &["ES", "I\u{fa}na", "3203007"], + &["ES", "Jaguar\u{e9}", "3203056"], + &["ES", "Jer\u{f4}nimo Monteiro", "3203106"], + &["ES", "Jo\u{e3}o Neiva", "3203130"], + &["ES", "Laranja da Terra", "3203163"], + &["ES", "Linhares", "3203205"], + &["ES", "Manten\u{f3}polis", "3203304"], + &["ES", "Marata\u{ed}zes", "3203320"], + &["ES", "Marechal Floriano", "3203346"], + &["ES", "Maril\u{e2}ndia", "3203353"], + &["ES", "Mimoso do Sul", "3203403"], + &["ES", "Montanha", "3203502"], + &["ES", "Mucurici", "3203601"], + &["ES", "Muniz Freire", "3203700"], + &["ES", "Muqui", "3203809"], + &["ES", "Nova Ven\u{e9}cia", "3203908"], + &["ES", "Pancas", "3204005"], + &["ES", "Pedro Can\u{e1}rio", "3204054"], + &["ES", "Pinheiros", "3204104"], + &["ES", "Pi\u{fa}ma", "3204203"], + &["ES", "Ponto Belo", "3204252"], + &["ES", "Presidente Kennedy", "3204302"], + &["ES", "Rio Bananal", "3204351"], + &["ES", "Rio Novo do Sul", "3204401"], + &["ES", "Santa Leopoldina", "3204500"], + &["ES", "Santa Maria de Jetib\u{e1}", "3204559"], + &["ES", "Santa Teresa", "3204609"], + &["ES", "S\u{e3}o Domingos do Norte", "3204658"], + &["ES", "S\u{e3}o Gabriel da Palha", "3204708"], + &["ES", "S\u{e3}o Jos\u{e9} do Cal\u{e7}ado", "3204807"], + &["ES", "S\u{e3}o Mateus", "3204906"], + &["ES", "S\u{e3}o Roque do Cana\u{e3}", "3204955"], + &["ES", "Serra", "3205002"], + &["ES", "Sooretama", "3205010"], + &["ES", "Vargem Alta", "3205036"], + &["ES", "Venda Nova do Imigrante", "3205069"], + &["ES", "Viana", "3205101"], + &["ES", "Vila Pav\u{e3}o", "3205150"], + &["ES", "Vila Val\u{e9}rio", "3205176"], + &["ES", "Vila Velha", "3205200"], + &["ES", "Vit\u{f3}ria", "3205309"], + &["GO", "Abadia de Goi\u{e1}s", "5200050"], + &["GO", "Abadi\u{e2}nia", "5200100"], + &["GO", "Acre\u{fa}na", "5200134"], + &["GO", "Adel\u{e2}ndia", "5200159"], + &["GO", "\u{c1}gua Fria de Goi\u{e1}s", "5200175"], + &["GO", "\u{c1}gua Limpa", "5200209"], + &["GO", "\u{c1}guas Lindas de Goi\u{e1}s", "5200258"], + &["GO", "Alex\u{e2}nia", "5200308"], + &["GO", "Alo\u{e2}ndia", "5200506"], + &["GO", "Alto Horizonte", "5200555"], + &["GO", "Alto Para\u{ed}so de Goi\u{e1}s", "5200605"], + &["GO", "Alvorada do Norte", "5200803"], + &["GO", "Amaralina", "5200829"], + &["GO", "Americano do Brasil", "5200852"], + &["GO", "Amorin\u{f3}polis", "5200902"], + &["GO", "An\u{e1}polis", "5201108"], + &["GO", "Anhanguera", "5201207"], + &["GO", "Anicuns", "5201306"], + &["GO", "Aparecida de Goi\u{e2}nia", "5201405"], + &["GO", "Aparecida do Rio Doce", "5201454"], + &["GO", "Apor\u{e9}", "5201504"], + &["GO", "Ara\u{e7}u", "5201603"], + &["GO", "Aragar\u{e7}as", "5201702"], + &["GO", "Aragoi\u{e2}nia", "5201801"], + &["GO", "Araguapaz", "5202155"], + &["GO", "Aren\u{f3}polis", "5202353"], + &["GO", "Aruan\u{e3}", "5202502"], + &["GO", "Auril\u{e2}ndia", "5202601"], + &["GO", "Avelin\u{f3}polis", "5202809"], + &["GO", "Baliza", "5203104"], + &["GO", "Barro Alto", "5203203"], + &["GO", "Bela Vista de Goi\u{e1}s", "5203302"], + &["GO", "Bom Jardim de Goi\u{e1}s", "5203401"], + &["GO", "Bom Jesus de Goi\u{e1}s", "5203500"], + &["GO", "Bonfin\u{f3}polis", "5203559"], + &["GO", "Bon\u{f3}polis", "5203575"], + &["GO", "Brazabrantes", "5203609"], + &["GO", "Brit\u{e2}nia", "5203807"], + &["GO", "Buriti Alegre", "5203906"], + &["GO", "Buriti de Goi\u{e1}s", "5203939"], + &["GO", "Buritin\u{f3}polis", "5203962"], + &["GO", "Cabeceiras", "5204003"], + &["GO", "Cachoeira Alta", "5204102"], + &["GO", "Cachoeira de Goi\u{e1}s", "5204201"], + &["GO", "Cachoeira Dourada", "5204250"], + &["GO", "Ca\u{e7}u", "5204300"], + &["GO", "Caiap\u{f4}nia", "5204409"], + &["GO", "Caldas Novas", "5204508"], + &["GO", "Caldazinha", "5204557"], + &["GO", "Campestre de Goi\u{e1}s", "5204607"], + &["GO", "Campina\u{e7}u", "5204656"], + &["GO", "Campinorte", "5204706"], + &["GO", "Campo Alegre de Goi\u{e1}s", "5204805"], + &["GO", "Campo Limpo de Goi\u{e1}s", "5204854"], + &["GO", "Campos Belos", "5204904"], + &["GO", "Campos Verdes", "5204953"], + &["GO", "Carmo do Rio Verde", "5205000"], + &["GO", "Castel\u{e2}ndia", "5205059"], + &["GO", "Catal\u{e3}o", "5205109"], + &["GO", "Catura\u{ed}", "5205208"], + &["GO", "Cavalcante", "5205307"], + &["GO", "Ceres", "5205406"], + &["GO", "Cezarina", "5205455"], + &["GO", "Chapad\u{e3}o do C\u{e9}u", "5205471"], + &["GO", "Cidade Ocidental", "5205497"], + &["GO", "Cocalzinho de Goi\u{e1}s", "5205513"], + &["GO", "Colinas do Sul", "5205521"], + &["GO", "C\u{f3}rrego do Ouro", "5205703"], + &["GO", "Corumb\u{e1} de Goi\u{e1}s", "5205802"], + &["GO", "Corumba\u{ed}ba", "5205901"], + &["GO", "Cristalina", "5206206"], + &["GO", "Cristian\u{f3}polis", "5206305"], + &["GO", "Crix\u{e1}s", "5206404"], + &["GO", "Crom\u{ed}nia", "5206503"], + &["GO", "Cumari", "5206602"], + &["GO", "Damian\u{f3}polis", "5206701"], + &["GO", "Damol\u{e2}ndia", "5206800"], + &["GO", "Davin\u{f3}polis", "5206909"], + &["GO", "Diorama", "5207105"], + &["GO", "Divin\u{f3}polis de Goi\u{e1}s", "5208301"], + &["GO", "Doverl\u{e2}ndia", "5207253"], + &["GO", "Edealina", "5207352"], + &["GO", "Ed\u{e9}ia", "5207402"], + &["GO", "Estrela do Norte", "5207501"], + &["GO", "Faina", "5207535"], + &["GO", "Fazenda Nova", "5207600"], + &["GO", "Firmin\u{f3}polis", "5207808"], + &["GO", "Flores de Goi\u{e1}s", "5207907"], + &["GO", "Formosa", "5208004"], + &["GO", "Formoso", "5208103"], + &["GO", "Gameleira de Goi\u{e1}s", "5208152"], + &["GO", "Goian\u{e1}polis", "5208400"], + &["GO", "Goiandira", "5208509"], + &["GO", "Goian\u{e9}sia", "5208608"], + &["GO", "Goi\u{e2}nia", "5208707"], + &["GO", "Goianira", "5208806"], + &["GO", "Goi\u{e1}s", "5208905"], + &["GO", "Goiatuba", "5209101"], + &["GO", "Gouvel\u{e2}ndia", "5209150"], + &["GO", "Guap\u{f3}", "5209200"], + &["GO", "Guara\u{ed}ta", "5209291"], + &["GO", "Guarani de Goi\u{e1}s", "5209408"], + &["GO", "Guarinos", "5209457"], + &["GO", "Heitora\u{ed}", "5209606"], + &["GO", "Hidrol\u{e2}ndia", "5209705"], + &["GO", "Hidrolina", "5209804"], + &["GO", "Iaciara", "5209903"], + &["GO", "Inaciol\u{e2}ndia", "5209937"], + &["GO", "Indiara", "5209952"], + &["GO", "Inhumas", "5210000"], + &["GO", "Ipameri", "5210109"], + &["GO", "Ipiranga de Goi\u{e1}s", "5210158"], + &["GO", "Ipor\u{e1}", "5210208"], + &["GO", "Israel\u{e2}ndia", "5210307"], + &["GO", "Itabera\u{ed}", "5210406"], + &["GO", "Itaguari", "5210562"], + &["GO", "Itaguaru", "5210604"], + &["GO", "Itaj\u{e1}", "5210802"], + &["GO", "Itapaci", "5210901"], + &["GO", "Itapirapu\u{e3}", "5211008"], + &["GO", "Itapuranga", "5211206"], + &["GO", "Itarum\u{e3}", "5211305"], + &["GO", "Itau\u{e7}u", "5211404"], + &["GO", "Itumbiara", "5211503"], + &["GO", "Ivol\u{e2}ndia", "5211602"], + &["GO", "Jandaia", "5211701"], + &["GO", "Jaragu\u{e1}", "5211800"], + &["GO", "Jata\u{ed}", "5211909"], + &["GO", "Jaupaci", "5212006"], + &["GO", "Jes\u{fa}polis", "5212055"], + &["GO", "Jovi\u{e2}nia", "5212105"], + &["GO", "Jussara", "5212204"], + &["GO", "Lagoa Santa", "5212253"], + &["GO", "Leopoldo de Bulh\u{f5}es", "5212303"], + &["GO", "Luzi\u{e2}nia", "5212501"], + &["GO", "Mairipotaba", "5212600"], + &["GO", "Mamba\u{ed}", "5212709"], + &["GO", "Mara Rosa", "5212808"], + &["GO", "Marzag\u{e3}o", "5212907"], + &["GO", "Matrinch\u{e3}", "5212956"], + &["GO", "Mauril\u{e2}ndia", "5213004"], + &["GO", "Mimoso de Goi\u{e1}s", "5213053"], + &["GO", "Mina\u{e7}u", "5213087"], + &["GO", "Mineiros", "5213103"], + &["GO", "Moipor\u{e1}", "5213400"], + &["GO", "Monte Alegre de Goi\u{e1}s", "5213509"], + &["GO", "Montes Claros de Goi\u{e1}s", "5213707"], + &["GO", "Montividiu", "5213756"], + &["GO", "Montividiu do Norte", "5213772"], + &["GO", "Morrinhos", "5213806"], + &["GO", "Morro Agudo de Goi\u{e1}s", "5213855"], + &["GO", "Moss\u{e2}medes", "5213905"], + &["GO", "Mozarl\u{e2}ndia", "5214002"], + &["GO", "Mundo Novo", "5214051"], + &["GO", "Mutun\u{f3}polis", "5214101"], + &["GO", "Naz\u{e1}rio", "5214408"], + &["GO", "Ner\u{f3}polis", "5214507"], + &["GO", "Niquel\u{e2}ndia", "5214606"], + &["GO", "Nova Am\u{e9}rica", "5214705"], + &["GO", "Nova Aurora", "5214804"], + &["GO", "Nova Crix\u{e1}s", "5214838"], + &["GO", "Nova Gl\u{f3}ria", "5214861"], + &["GO", "Nova Igua\u{e7}u de Goi\u{e1}s", "5214879"], + &["GO", "Nova Roma", "5214903"], + &["GO", "Nova Veneza", "5215009"], + &["GO", "Novo Brasil", "5215207"], + &["GO", "Novo Gama", "5215231"], + &["GO", "Novo Planalto", "5215256"], + &["GO", "Orizona", "5215306"], + &["GO", "Ouro Verde de Goi\u{e1}s", "5215405"], + &["GO", "Ouvidor", "5215504"], + &["GO", "Padre Bernardo", "5215603"], + &["GO", "Palestina de Goi\u{e1}s", "5215652"], + &["GO", "Palmeiras de Goi\u{e1}s", "5215702"], + &["GO", "Palmelo", "5215801"], + &["GO", "Palmin\u{f3}polis", "5215900"], + &["GO", "Panam\u{e1}", "5216007"], + &["GO", "Paranaiguara", "5216304"], + &["GO", "Para\u{fa}na", "5216403"], + &["GO", "Perol\u{e2}ndia", "5216452"], + &["GO", "Petrolina de Goi\u{e1}s", "5216809"], + &["GO", "Pilar de Goi\u{e1}s", "5216908"], + &["GO", "Piracanjuba", "5217104"], + &["GO", "Piranhas", "5217203"], + &["GO", "Piren\u{f3}polis", "5217302"], + &["GO", "Pires do Rio", "5217401"], + &["GO", "Planaltina", "5217609"], + &["GO", "Pontalina", "5217708"], + &["GO", "Porangatu", "5218003"], + &["GO", "Porteir\u{e3}o", "5218052"], + &["GO", "Portel\u{e2}ndia", "5218102"], + &["GO", "Posse", "5218300"], + &["GO", "Professor Jamil", "5218391"], + &["GO", "Quirin\u{f3}polis", "5218508"], + &["GO", "Rialma", "5218607"], + &["GO", "Rian\u{e1}polis", "5218706"], + &["GO", "Rio Quente", "5218789"], + &["GO", "Rio Verde", "5218805"], + &["GO", "Rubiataba", "5218904"], + &["GO", "Sanclerl\u{e2}ndia", "5219001"], + &["GO", "Santa B\u{e1}rbara de Goi\u{e1}s", "5219100"], + &["GO", "Santa Cruz de Goi\u{e1}s", "5219209"], + &["GO", "Santa F\u{e9} de Goi\u{e1}s", "5219258"], + &["GO", "Santa Helena de Goi\u{e1}s", "5219308"], + &["GO", "Santa Isabel", "5219357"], + &["GO", "Santa Rita do Araguaia", "5219407"], + &["GO", "Santa Rita do Novo Destino", "5219456"], + &["GO", "Santa Rosa de Goi\u{e1}s", "5219506"], + &["GO", "Santa Tereza de Goi\u{e1}s", "5219605"], + &["GO", "Santa Terezinha de Goi\u{e1}s", "5219704"], + &["GO", "Santo Ant\u{f4}nio da Barra", "5219712"], + &["GO", "Santo Ant\u{f4}nio de Goi\u{e1}s", "5219738"], + &["GO", "Santo Ant\u{f4}nio do Descoberto", "5219753"], + &["GO", "S\u{e3}o Domingos", "5219803"], + &["GO", "S\u{e3}o Francisco de Goi\u{e1}s", "5219902"], + &["GO", "S\u{e3}o Jo\u{e3}o d'Alian\u{e7}a", "5220009"], + &["GO", "S\u{e3}o Jo\u{e3}o da Para\u{fa}na", "5220058"], + &["GO", "S\u{e3}o Lu\u{ed}s de Montes Belos", "5220108"], + &["GO", "S\u{e3}o Luiz do Norte", "5220157"], + &["GO", "S\u{e3}o Miguel do Araguaia", "5220207"], + &["GO", "S\u{e3}o Miguel do Passa Quatro", "5220264"], + &["GO", "S\u{e3}o Patr\u{ed}cio", "5220280"], + &["GO", "S\u{e3}o Sim\u{e3}o", "5220405"], + &["GO", "Senador Canedo", "5220454"], + &["GO", "Serran\u{f3}polis", "5220504"], + &["GO", "Silv\u{e2}nia", "5220603"], + &["GO", "Simol\u{e2}ndia", "5220686"], + &["GO", "S\u{ed}tio d'Abadia", "5220702"], + &["GO", "Taquaral de Goi\u{e1}s", "5221007"], + &["GO", "Teresina de Goi\u{e1}s", "5221080"], + &["GO", "Terez\u{f3}polis de Goi\u{e1}s", "5221197"], + &["GO", "Tr\u{ea}s Ranchos", "5221304"], + &["GO", "Trindade", "5221403"], + &["GO", "Trombas", "5221452"], + &["GO", "Turv\u{e2}nia", "5221502"], + &["GO", "Turvel\u{e2}ndia", "5221551"], + &["GO", "Uirapuru", "5221577"], + &["GO", "Urua\u{e7}u", "5221601"], + &["GO", "Uruana", "5221700"], + &["GO", "Uruta\u{ed}", "5221809"], + &["GO", "Valpara\u{ed}so de Goi\u{e1}s", "5221858"], + &["GO", "Varj\u{e3}o", "5221908"], + &["GO", "Vian\u{f3}polis", "5222005"], + &["GO", "Vicentin\u{f3}polis", "5222054"], + &["GO", "Vila Boa", "5222203"], + &["GO", "Vila Prop\u{ed}cio", "5222302"], + &["MA", "A\u{e7}ail\u{e2}ndia", "2100055"], + &["MA", "Afonso Cunha", "2100105"], + &["MA", "\u{c1}gua Doce do Maranh\u{e3}o", "2100154"], + &["MA", "Alc\u{e2}ntara", "2100204"], + &["MA", "Aldeias Altas", "2100303"], + &["MA", "Altamira do Maranh\u{e3}o", "2100402"], + &["MA", "Alto Alegre do Maranh\u{e3}o", "2100436"], + &["MA", "Alto Alegre do Pindar\u{e9}", "2100477"], + &["MA", "Alto Parna\u{ed}ba", "2100501"], + &["MA", "Amap\u{e1} do Maranh\u{e3}o", "2100550"], + &["MA", "Amarante do Maranh\u{e3}o", "2100600"], + &["MA", "Anajatuba", "2100709"], + &["MA", "Anapurus", "2100808"], + &["MA", "Apicum-A\u{e7}u", "2100832"], + &["MA", "Araguan\u{e3}", "2100873"], + &["MA", "Araioses", "2100907"], + &["MA", "Arame", "2100956"], + &["MA", "Arari", "2101004"], + &["MA", "Axix\u{e1}", "2101103"], + &["MA", "Bacabal", "2101202"], + &["MA", "Bacabeira", "2101251"], + &["MA", "Bacuri", "2101301"], + &["MA", "Bacurituba", "2101350"], + &["MA", "Balsas", "2101400"], + &["MA", "Bar\u{e3}o de Graja\u{fa}", "2101509"], + &["MA", "Barra do Corda", "2101608"], + &["MA", "Barreirinhas", "2101707"], + &["MA", "Bela Vista do Maranh\u{e3}o", "2101772"], + &["MA", "Bel\u{e1}gua", "2101731"], + &["MA", "Benedito Leite", "2101806"], + &["MA", "Bequim\u{e3}o", "2101905"], + &["MA", "Bernardo do Mearim", "2101939"], + &["MA", "Boa Vista do Gurupi", "2101970"], + &["MA", "Bom Jardim", "2102002"], + &["MA", "Bom Jesus das Selvas", "2102036"], + &["MA", "Bom Lugar", "2102077"], + &["MA", "Brejo", "2102101"], + &["MA", "Brejo de Areia", "2102150"], + &["MA", "Buriti", "2102200"], + &["MA", "Buriti Bravo", "2102309"], + &["MA", "Buriticupu", "2102325"], + &["MA", "Buritirana", "2102358"], + &["MA", "Cachoeira Grande", "2102374"], + &["MA", "Cajapi\u{f3}", "2102408"], + &["MA", "Cajari", "2102507"], + &["MA", "Campestre do Maranh\u{e3}o", "2102556"], + &["MA", "C\u{e2}ndido Mendes", "2102606"], + &["MA", "Cantanhede", "2102705"], + &["MA", "Capinzal do Norte", "2102754"], + &["MA", "Carolina", "2102804"], + &["MA", "Carutapera", "2102903"], + &["MA", "Caxias", "2103000"], + &["MA", "Cedral", "2103109"], + &["MA", "Central do Maranh\u{e3}o", "2103125"], + &["MA", "Centro do Guilherme", "2103158"], + &["MA", "Centro Novo do Maranh\u{e3}o", "2103174"], + &["MA", "Chapadinha", "2103208"], + &["MA", "Cidel\u{e2}ndia", "2103257"], + &["MA", "Cod\u{f3}", "2103307"], + &["MA", "Coelho Neto", "2103406"], + &["MA", "Colinas", "2103505"], + &["MA", "Concei\u{e7}\u{e3}o do Lago-A\u{e7}u", "2103554"], + &["MA", "Coroat\u{e1}", "2103604"], + &["MA", "Cururupu", "2103703"], + &["MA", "Davin\u{f3}polis", "2103752"], + &["MA", "Dom Pedro", "2103802"], + &["MA", "Duque Bacelar", "2103901"], + &["MA", "Esperantin\u{f3}polis", "2104008"], + &["MA", "Estreito", "2104057"], + &["MA", "Feira Nova do Maranh\u{e3}o", "2104073"], + &["MA", "Fernando Falc\u{e3}o", "2104081"], + &["MA", "Formosa da Serra Negra", "2104099"], + &["MA", "Fortaleza dos Nogueiras", "2104107"], + &["MA", "Fortuna", "2104206"], + &["MA", "Godofredo Viana", "2104305"], + &["MA", "Gon\u{e7}alves Dias", "2104404"], + &["MA", "Governador Archer", "2104503"], + &["MA", "Governador Edison Lob\u{e3}o", "2104552"], + &["MA", "Governador Eug\u{ea}nio Barros", "2104602"], + &["MA", "Governador Luiz Rocha", "2104628"], + &["MA", "Governador Newton Bello", "2104651"], + &["MA", "Governador Nunes Freire", "2104677"], + &["MA", "Gra\u{e7}a Aranha", "2104701"], + &["MA", "Graja\u{fa}", "2104800"], + &["MA", "Guimar\u{e3}es", "2104909"], + &["MA", "Humberto de Campos", "2105005"], + &["MA", "Icatu", "2105104"], + &["MA", "Igarap\u{e9} do Meio", "2105153"], + &["MA", "Igarap\u{e9} Grande", "2105203"], + &["MA", "Imperatriz", "2105302"], + &["MA", "Itaipava do Graja\u{fa}", "2105351"], + &["MA", "Itapecuru Mirim", "2105401"], + &["MA", "Itinga do Maranh\u{e3}o", "2105427"], + &["MA", "Jatob\u{e1}", "2105450"], + &["MA", "Jenipapo dos Vieiras", "2105476"], + &["MA", "Jo\u{e3}o Lisboa", "2105500"], + &["MA", "Josel\u{e2}ndia", "2105609"], + &["MA", "Junco do Maranh\u{e3}o", "2105658"], + &["MA", "Lago da Pedra", "2105708"], + &["MA", "Lago do Junco", "2105807"], + &["MA", "Lago dos Rodrigues", "2105948"], + &["MA", "Lago Verde", "2105906"], + &["MA", "Lagoa do Mato", "2105922"], + &["MA", "Lagoa Grande do Maranh\u{e3}o", "2105963"], + &["MA", "Lajeado Novo", "2105989"], + &["MA", "Lima Campos", "2106003"], + &["MA", "Loreto", "2106102"], + &["MA", "Lu\u{ed}s Domingues", "2106201"], + &["MA", "Magalh\u{e3}es de Almeida", "2106300"], + &["MA", "Maraca\u{e7}um\u{e9}", "2106326"], + &["MA", "Maraj\u{e1} do Sena", "2106359"], + &["MA", "Maranh\u{e3}ozinho", "2106375"], + &["MA", "Mata Roma", "2106409"], + &["MA", "Matinha", "2106508"], + &["MA", "Mat\u{f5}es", "2106607"], + &["MA", "Mat\u{f5}es do Norte", "2106631"], + &["MA", "Milagres do Maranh\u{e3}o", "2106672"], + &["MA", "Mirador", "2106706"], + &["MA", "Miranda do Norte", "2106755"], + &["MA", "Mirinzal", "2106805"], + &["MA", "Mon\u{e7}\u{e3}o", "2106904"], + &["MA", "Montes Altos", "2107001"], + &["MA", "Morros", "2107100"], + &["MA", "Nina Rodrigues", "2107209"], + &["MA", "Nova Colinas", "2107258"], + &["MA", "Nova Iorque", "2107308"], + &["MA", "Nova Olinda do Maranh\u{e3}o", "2107357"], + &["MA", "Olho d'\u{c1}gua das Cunh\u{e3}s", "2107407"], + &["MA", "Olinda Nova do Maranh\u{e3}o", "2107456"], + &["MA", "Pa\u{e7}o do Lumiar", "2107506"], + &["MA", "Palmeir\u{e2}ndia", "2107605"], + &["MA", "Paraibano", "2107704"], + &["MA", "Parnarama", "2107803"], + &["MA", "Passagem Franca", "2107902"], + &["MA", "Pastos Bons", "2108009"], + &["MA", "Paulino Neves", "2108058"], + &["MA", "Paulo Ramos", "2108108"], + &["MA", "Pedreiras", "2108207"], + &["MA", "Pedro do Ros\u{e1}rio", "2108256"], + &["MA", "Penalva", "2108306"], + &["MA", "Peri Mirim", "2108405"], + &["MA", "Peritor\u{f3}", "2108454"], + &["MA", "Pindar\u{e9}-Mirim", "2108504"], + &["MA", "Pinheiro", "2108603"], + &["MA", "Pio XII", "2108702"], + &["MA", "Pirapemas", "2108801"], + &["MA", "Po\u{e7}\u{e3}o de Pedras", "2108900"], + &["MA", "Porto Franco", "2109007"], + &["MA", "Porto Rico do Maranh\u{e3}o", "2109056"], + &["MA", "Presidente Dutra", "2109106"], + &["MA", "Presidente Juscelino", "2109205"], + &["MA", "Presidente M\u{e9}dici", "2109239"], + &["MA", "Presidente Sarney", "2109270"], + &["MA", "Presidente Vargas", "2109304"], + &["MA", "Primeira Cruz", "2109403"], + &["MA", "Raposa", "2109452"], + &["MA", "Riach\u{e3}o", "2109502"], + &["MA", "Ribamar Fiquene", "2109551"], + &["MA", "Ros\u{e1}rio", "2109601"], + &["MA", "Samba\u{ed}ba", "2109700"], + &["MA", "Santa Filomena do Maranh\u{e3}o", "2109759"], + &["MA", "Santa Helena", "2109809"], + &["MA", "Santa In\u{ea}s", "2109908"], + &["MA", "Santa Luzia", "2110005"], + &["MA", "Santa Luzia do Paru\u{e1}", "2110039"], + &["MA", "Santa Quit\u{e9}ria do Maranh\u{e3}o", "2110104"], + &["MA", "Santa Rita", "2110203"], + &["MA", "Santana do Maranh\u{e3}o", "2110237"], + &["MA", "Santo Amaro do Maranh\u{e3}o", "2110278"], + &["MA", "Santo Ant\u{f4}nio dos Lopes", "2110302"], + &["MA", "S\u{e3}o Benedito do Rio Preto", "2110401"], + &["MA", "S\u{e3}o Bento", "2110500"], + &["MA", "S\u{e3}o Bernardo", "2110609"], + &["MA", "S\u{e3}o Domingos do Azeit\u{e3}o", "2110658"], + &["MA", "S\u{e3}o Domingos do Maranh\u{e3}o", "2110708"], + &["MA", "S\u{e3}o F\u{e9}lix de Balsas", "2110807"], + &["MA", "S\u{e3}o Francisco do Brej\u{e3}o", "2110856"], + &["MA", "S\u{e3}o Francisco do Maranh\u{e3}o", "2110906"], + &["MA", "S\u{e3}o Jo\u{e3}o Batista", "2111003"], + &["MA", "S\u{e3}o Jo\u{e3}o do Car\u{fa}", "2111029"], + &["MA", "S\u{e3}o Jo\u{e3}o do Para\u{ed}so", "2111052"], + &["MA", "S\u{e3}o Jo\u{e3}o do Soter", "2111078"], + &["MA", "S\u{e3}o Jo\u{e3}o dos Patos", "2111102"], + &["MA", "S\u{e3}o Jos\u{e9} de Ribamar", "2111201"], + &["MA", "S\u{e3}o Jos\u{e9} dos Bas\u{ed}lios", "2111250"], + &["MA", "S\u{e3}o Lu\u{ed}s", "2111300"], + &["MA", "S\u{e3}o Lu\u{ed}s Gonzaga do Maranh\u{e3}o", "2111409"], + &["MA", "S\u{e3}o Mateus do Maranh\u{e3}o", "2111508"], + &["MA", "S\u{e3}o Pedro da \u{c1}gua Branca", "2111532"], + &["MA", "S\u{e3}o Pedro dos Crentes", "2111573"], + &["MA", "S\u{e3}o Raimundo das Mangabeiras", "2111607"], + &["MA", "S\u{e3}o Raimundo do Doca Bezerra", "2111631"], + &["MA", "S\u{e3}o Roberto", "2111672"], + &["MA", "S\u{e3}o Vicente Ferrer", "2111706"], + &["MA", "Satubinha", "2111722"], + &["MA", "Senador Alexandre Costa", "2111748"], + &["MA", "Senador La Rocque", "2111763"], + &["MA", "Serrano do Maranh\u{e3}o", "2111789"], + &["MA", "S\u{ed}tio Novo", "2111805"], + &["MA", "Sucupira do Norte", "2111904"], + &["MA", "Sucupira do Riach\u{e3}o", "2111953"], + &["MA", "Tasso Fragoso", "2112001"], + &["MA", "Timbiras", "2112100"], + &["MA", "Timon", "2112209"], + &["MA", "Trizidela do Vale", "2112233"], + &["MA", "Tufil\u{e2}ndia", "2112274"], + &["MA", "Tuntum", "2112308"], + &["MA", "Turia\u{e7}u", "2112407"], + &["MA", "Turil\u{e2}ndia", "2112456"], + &["MA", "Tut\u{f3}ia", "2112506"], + &["MA", "Urbano Santos", "2112605"], + &["MA", "Vargem Grande", "2112704"], + &["MA", "Viana", "2112803"], + &["MA", "Vila Nova dos Mart\u{ed}rios", "2112852"], + &["MA", "Vit\u{f3}ria do Mearim", "2112902"], + &["MA", "Vitorino Freire", "2113009"], + &["MA", "Z\u{e9} Doca", "2114007"], + &["MT", "Acorizal", "5100102"], + &["MT", "\u{c1}gua Boa", "5100201"], + &["MT", "Alta Floresta", "5100250"], + &["MT", "Alto Araguaia", "5100300"], + &["MT", "Alto Boa Vista", "5100359"], + &["MT", "Alto Gar\u{e7}as", "5100409"], + &["MT", "Alto Paraguai", "5100508"], + &["MT", "Alto Taquari", "5100607"], + &["MT", "Apiac\u{e1}s", "5100805"], + &["MT", "Araguaiana", "5101001"], + &["MT", "Araguainha", "5101209"], + &["MT", "Araputanga", "5101258"], + &["MT", "Aren\u{e1}polis", "5101308"], + &["MT", "Aripuan\u{e3}", "5101407"], + &["MT", "Bar\u{e3}o de Melga\u{e7}o", "5101605"], + &["MT", "Barra do Bugres", "5101704"], + &["MT", "Barra do Gar\u{e7}as", "5101803"], + &["MT", "Boa Esperan\u{e7}a do Norte", "5101837"], + &["MT", "Bom Jesus do Araguaia", "5101852"], + &["MT", "Brasnorte", "5101902"], + &["MT", "C\u{e1}ceres", "5102504"], + &["MT", "Campin\u{e1}polis", "5102603"], + &["MT", "Campo Novo do Parecis", "5102637"], + &["MT", "Campo Verde", "5102678"], + &["MT", "Campos de J\u{fa}lio", "5102686"], + &["MT", "Canabrava do Norte", "5102694"], + &["MT", "Canarana", "5102702"], + &["MT", "Carlinda", "5102793"], + &["MT", "Castanheira", "5102850"], + &["MT", "Chapada dos Guimar\u{e3}es", "5103007"], + &["MT", "Cl\u{e1}udia", "5103056"], + &["MT", "Cocalinho", "5103106"], + &["MT", "Col\u{ed}der", "5103205"], + &["MT", "Colniza", "5103254"], + &["MT", "Comodoro", "5103304"], + &["MT", "Confresa", "5103353"], + &["MT", "Conquista D'Oeste", "5103361"], + &["MT", "Cotrigua\u{e7}u", "5103379"], + &["MT", "Cuiab\u{e1}", "5103403"], + &["MT", "Curvel\u{e2}ndia", "5103437"], + &["MT", "Denise", "5103452"], + &["MT", "Diamantino", "5103502"], + &["MT", "Dom Aquino", "5103601"], + &["MT", "Feliz Natal", "5103700"], + &["MT", "Figueir\u{f3}polis D'Oeste", "5103809"], + &["MT", "Ga\u{fa}cha do Norte", "5103858"], + &["MT", "General Carneiro", "5103908"], + &["MT", "Gl\u{f3}ria D'Oeste", "5103957"], + &["MT", "Guarant\u{e3} do Norte", "5104104"], + &["MT", "Guiratinga", "5104203"], + &["MT", "Indiava\u{ed}", "5104500"], + &["MT", "Ipiranga do Norte", "5104526"], + &["MT", "Itanhang\u{e1}", "5104542"], + &["MT", "Ita\u{fa}ba", "5104559"], + &["MT", "Itiquira", "5104609"], + &["MT", "Jaciara", "5104807"], + &["MT", "Jangada", "5104906"], + &["MT", "Jauru", "5105002"], + &["MT", "Juara", "5105101"], + &["MT", "Ju\u{ed}na", "5105150"], + &["MT", "Juruena", "5105176"], + &["MT", "Juscimeira", "5105200"], + &["MT", "Lambari D'Oeste", "5105234"], + &["MT", "Lucas do Rio Verde", "5105259"], + &["MT", "Luciara", "5105309"], + &["MT", "Marcel\u{e2}ndia", "5105580"], + &["MT", "Matup\u{e1}", "5105606"], + &["MT", "Mirassol d'Oeste", "5105622"], + &["MT", "Nobres", "5105903"], + &["MT", "Nortel\u{e2}ndia", "5106000"], + &["MT", "Nossa Senhora do Livramento", "5106109"], + &["MT", "Nova Bandeirantes", "5106158"], + &["MT", "Nova Brasil\u{e2}ndia", "5106208"], + &["MT", "Nova Cana\u{e3} do Norte", "5106216"], + &["MT", "Nova Guarita", "5108808"], + &["MT", "Nova Lacerda", "5106182"], + &["MT", "Nova Maril\u{e2}ndia", "5108857"], + &["MT", "Nova Maring\u{e1}", "5108907"], + &["MT", "Nova Monte Verde", "5108956"], + &["MT", "Nova Mutum", "5106224"], + &["MT", "Nova Nazar\u{e9}", "5106174"], + &["MT", "Nova Ol\u{ed}mpia", "5106232"], + &["MT", "Nova Santa Helena", "5106190"], + &["MT", "Nova Ubirat\u{e3}", "5106240"], + &["MT", "Nova Xavantina", "5106257"], + &["MT", "Novo Horizonte do Norte", "5106273"], + &["MT", "Novo Mundo", "5106265"], + &["MT", "Novo Santo Ant\u{f4}nio", "5106315"], + &["MT", "Novo S\u{e3}o Joaquim", "5106281"], + &["MT", "Parana\u{ed}ta", "5106299"], + &["MT", "Paranatinga", "5106307"], + &["MT", "Pedra Preta", "5106372"], + &["MT", "Peixoto de Azevedo", "5106422"], + &["MT", "Planalto da Serra", "5106455"], + &["MT", "Pocon\u{e9}", "5106505"], + &["MT", "Pontal do Araguaia", "5106653"], + &["MT", "Ponte Branca", "5106703"], + &["MT", "Pontes e Lacerda", "5106752"], + &["MT", "Porto Alegre do Norte", "5106778"], + &["MT", "Porto dos Ga\u{fa}chos", "5106802"], + &["MT", "Porto Esperidi\u{e3}o", "5106828"], + &["MT", "Porto Estrela", "5106851"], + &["MT", "Poxor\u{e9}u", "5107008"], + &["MT", "Primavera do Leste", "5107040"], + &["MT", "Quer\u{ea}ncia", "5107065"], + &["MT", "Reserva do Caba\u{e7}al", "5107156"], + &["MT", "Ribeir\u{e3}o Cascalheira", "5107180"], + &["MT", "Ribeir\u{e3}ozinho", "5107198"], + &["MT", "Rio Branco", "5107206"], + &["MT", "Rondol\u{e2}ndia", "5107578"], + &["MT", "Rondon\u{f3}polis", "5107602"], + &["MT", "Ros\u{e1}rio Oeste", "5107701"], + &["MT", "Salto do C\u{e9}u", "5107750"], + &["MT", "Santa Carmem", "5107248"], + &["MT", "Santa Cruz do Xingu", "5107743"], + &["MT", "Santa Rita do Trivelato", "5107768"], + &["MT", "Santa Terezinha", "5107776"], + &["MT", "Santo Afonso", "5107263"], + &["MT", "Santo Ant\u{f4}nio de Leverger", "5107800"], + &["MT", "Santo Ant\u{f4}nio do Leste", "5107792"], + &["MT", "S\u{e3}o F\u{e9}lix do Araguaia", "5107859"], + &["MT", "S\u{e3}o Jos\u{e9} do Povo", "5107297"], + &["MT", "S\u{e3}o Jos\u{e9} do Rio Claro", "5107305"], + &["MT", "S\u{e3}o Jos\u{e9} do Xingu", "5107354"], + &["MT", "S\u{e3}o Jos\u{e9} dos Quatro Marcos", "5107107"], + &["MT", "S\u{e3}o Pedro da Cipa", "5107404"], + &["MT", "Sapezal", "5107875"], + &["MT", "Serra Nova Dourada", "5107883"], + &["MT", "Sinop", "5107909"], + &["MT", "Sorriso", "5107925"], + &["MT", "Tabapor\u{e3}", "5107941"], + &["MT", "Tangar\u{e1} da Serra", "5107958"], + &["MT", "Tapurah", "5108006"], + &["MT", "Terra Nova do Norte", "5108055"], + &["MT", "Tesouro", "5108105"], + &["MT", "Torixor\u{e9}u", "5108204"], + &["MT", "Uni\u{e3}o do Sul", "5108303"], + &["MT", "Vale de S\u{e3}o Domingos", "5108352"], + &["MT", "V\u{e1}rzea Grande", "5108402"], + &["MT", "Vera", "5108501"], + &["MT", "Vila Bela da Sant\u{ed}ssima Trindade", "5105507"], + &["MT", "Vila Rica", "5108600"], + &["MS", "\u{c1}gua Clara", "5000203"], + &["MS", "Alcin\u{f3}polis", "5000252"], + &["MS", "Amambai", "5000609"], + &["MS", "Anast\u{e1}cio", "5000708"], + &["MS", "Anauril\u{e2}ndia", "5000807"], + &["MS", "Ang\u{e9}lica", "5000856"], + &["MS", "Ant\u{f4}nio Jo\u{e3}o", "5000906"], + &["MS", "Aparecida do Taboado", "5001003"], + &["MS", "Aquidauana", "5001102"], + &["MS", "Aral Moreira", "5001243"], + &["MS", "Bandeirantes", "5001508"], + &["MS", "Bataguassu", "5001904"], + &["MS", "Bataypor\u{e3}", "5002001"], + &["MS", "Bela Vista", "5002100"], + &["MS", "Bodoquena", "5002159"], + &["MS", "Bonito", "5002209"], + &["MS", "Brasil\u{e2}ndia", "5002308"], + &["MS", "Caarap\u{f3}", "5002407"], + &["MS", "Camapu\u{e3}", "5002605"], + &["MS", "Campo Grande", "5002704"], + &["MS", "Caracol", "5002803"], + &["MS", "Cassil\u{e2}ndia", "5002902"], + &["MS", "Chapad\u{e3}o do Sul", "5002951"], + &["MS", "Corguinho", "5003108"], + &["MS", "Coronel Sapucaia", "5003157"], + &["MS", "Corumb\u{e1}", "5003207"], + &["MS", "Costa Rica", "5003256"], + &["MS", "Coxim", "5003306"], + &["MS", "Deod\u{e1}polis", "5003454"], + &["MS", "Dois Irm\u{e3}os do Buriti", "5003488"], + &["MS", "Douradina", "5003504"], + &["MS", "Dourados", "5003702"], + &["MS", "Eldorado", "5003751"], + &["MS", "F\u{e1}tima do Sul", "5003801"], + &["MS", "Figueir\u{e3}o", "5003900"], + &["MS", "Gl\u{f3}ria de Dourados", "5004007"], + &["MS", "Guia Lopes da Laguna", "5004106"], + &["MS", "Iguatemi", "5004304"], + &["MS", "Inoc\u{ea}ncia", "5004403"], + &["MS", "Itapor\u{e3}", "5004502"], + &["MS", "Itaquira\u{ed}", "5004601"], + &["MS", "Ivinhema", "5004700"], + &["MS", "Japor\u{e3}", "5004809"], + &["MS", "Jaraguari", "5004908"], + &["MS", "Jardim", "5005004"], + &["MS", "Jate\u{ed}", "5005103"], + &["MS", "Juti", "5005152"], + &["MS", "Lad\u{e1}rio", "5005202"], + &["MS", "Laguna Carap\u{e3}", "5005251"], + &["MS", "Maracaju", "5005400"], + &["MS", "Miranda", "5005608"], + &["MS", "Mundo Novo", "5005681"], + &["MS", "Navira\u{ed}", "5005707"], + &["MS", "Nioaque", "5005806"], + &["MS", "Nova Alvorada do Sul", "5006002"], + &["MS", "Nova Andradina", "5006200"], + &["MS", "Novo Horizonte do Sul", "5006259"], + &["MS", "Para\u{ed}so das \u{c1}guas", "5006275"], + &["MS", "Parana\u{ed}ba", "5006309"], + &["MS", "Paranhos", "5006358"], + &["MS", "Pedro Gomes", "5006408"], + &["MS", "Ponta Por\u{e3}", "5006606"], + &["MS", "Porto Murtinho", "5006903"], + &["MS", "Ribas do Rio Pardo", "5007109"], + &["MS", "Rio Brilhante", "5007208"], + &["MS", "Rio Negro", "5007307"], + &["MS", "Rio Verde de Mato Grosso", "5007406"], + &["MS", "Rochedo", "5007505"], + &["MS", "Santa Rita do Pardo", "5007554"], + &["MS", "S\u{e3}o Gabriel do Oeste", "5007695"], + &["MS", "Selv\u{ed}ria", "5007802"], + &["MS", "Sete Quedas", "5007703"], + &["MS", "Sidrol\u{e2}ndia", "5007901"], + &["MS", "Sonora", "5007935"], + &["MS", "Tacuru", "5007950"], + &["MS", "Taquarussu", "5007976"], + &["MS", "Terenos", "5008008"], + &["MS", "Tr\u{ea}s Lagoas", "5008305"], + &["MS", "Vicentina", "5008404"], + &["MG", "Abadia dos Dourados", "3100104"], + &["MG", "Abaet\u{e9}", "3100203"], + &["MG", "Abre Campo", "3100302"], + &["MG", "Acaiaca", "3100401"], + &["MG", "A\u{e7}ucena", "3100500"], + &["MG", "\u{c1}gua Boa", "3100609"], + &["MG", "\u{c1}gua Comprida", "3100708"], + &["MG", "Aguanil", "3100807"], + &["MG", "\u{c1}guas Formosas", "3100906"], + &["MG", "\u{c1}guas Vermelhas", "3101003"], + &["MG", "Aimor\u{e9}s", "3101102"], + &["MG", "Aiuruoca", "3101201"], + &["MG", "Alagoa", "3101300"], + &["MG", "Albertina", "3101409"], + &["MG", "Al\u{e9}m Para\u{ed}ba", "3101508"], + &["MG", "Alfenas", "3101607"], + &["MG", "Alfredo Vasconcelos", "3101631"], + &["MG", "Almenara", "3101706"], + &["MG", "Alpercata", "3101805"], + &["MG", "Alpin\u{f3}polis", "3101904"], + &["MG", "Alterosa", "3102001"], + &["MG", "Alto Capara\u{f3}", "3102050"], + &["MG", "Alto Jequitib\u{e1}", "3153509"], + &["MG", "Alto Rio Doce", "3102100"], + &["MG", "Alvarenga", "3102209"], + &["MG", "Alvin\u{f3}polis", "3102308"], + &["MG", "Alvorada de Minas", "3102407"], + &["MG", "Amparo do Serra", "3102506"], + &["MG", "Andradas", "3102605"], + &["MG", "Andrel\u{e2}ndia", "3102803"], + &["MG", "Angel\u{e2}ndia", "3102852"], + &["MG", "Ant\u{f4}nio Carlos", "3102902"], + &["MG", "Ant\u{f4}nio Dias", "3103009"], + &["MG", "Ant\u{f4}nio Prado de Minas", "3103108"], + &["MG", "Ara\u{e7}a\u{ed}", "3103207"], + &["MG", "Aracitaba", "3103306"], + &["MG", "Ara\u{e7}ua\u{ed}", "3103405"], + &["MG", "Araguari", "3103504"], + &["MG", "Arantina", "3103603"], + &["MG", "Araponga", "3103702"], + &["MG", "Arapor\u{e3}", "3103751"], + &["MG", "Arapu\u{e1}", "3103801"], + &["MG", "Ara\u{fa}jos", "3103900"], + &["MG", "Arax\u{e1}", "3104007"], + &["MG", "Arceburgo", "3104106"], + &["MG", "Arcos", "3104205"], + &["MG", "Areado", "3104304"], + &["MG", "Argirita", "3104403"], + &["MG", "Aricanduva", "3104452"], + &["MG", "Arinos", "3104502"], + &["MG", "Astolfo Dutra", "3104601"], + &["MG", "Atal\u{e9}ia", "3104700"], + &["MG", "Augusto de Lima", "3104809"], + &["MG", "Baependi", "3104908"], + &["MG", "Baldim", "3105004"], + &["MG", "Bambu\u{ed}", "3105103"], + &["MG", "Bandeira", "3105202"], + &["MG", "Bandeira do Sul", "3105301"], + &["MG", "Bar\u{e3}o de Cocais", "3105400"], + &["MG", "Bar\u{e3}o do Monte Alto", "3105509"], + &["MG", "Barbacena", "3105608"], + &["MG", "Barra Longa", "3105707"], + &["MG", "Barroso", "3105905"], + &["MG", "Bela Vista de Minas", "3106002"], + &["MG", "Belmiro Braga", "3106101"], + &["MG", "Belo Horizonte", "3106200"], + &["MG", "Belo Oriente", "3106309"], + &["MG", "Belo Vale", "3106408"], + &["MG", "Berilo", "3106507"], + &["MG", "Berizal", "3106655"], + &["MG", "Bert\u{f3}polis", "3106606"], + &["MG", "Betim", "3106705"], + &["MG", "Bias Fortes", "3106804"], + &["MG", "Bicas", "3106903"], + &["MG", "Biquinhas", "3107000"], + &["MG", "Boa Esperan\u{e7}a", "3107109"], + &["MG", "Bocaina de Minas", "3107208"], + &["MG", "Bocai\u{fa}va", "3107307"], + &["MG", "Bom Despacho", "3107406"], + &["MG", "Bom Jardim de Minas", "3107505"], + &["MG", "Bom Jesus da Penha", "3107604"], + &["MG", "Bom Jesus do Amparo", "3107703"], + &["MG", "Bom Jesus do Galho", "3107802"], + &["MG", "Bom Repouso", "3107901"], + &["MG", "Bom Sucesso", "3108008"], + &["MG", "Bonfim", "3108107"], + &["MG", "Bonfin\u{f3}polis de Minas", "3108206"], + &["MG", "Bonito de Minas", "3108255"], + &["MG", "Borda da Mata", "3108305"], + &["MG", "Botelhos", "3108404"], + &["MG", "Botumirim", "3108503"], + &["MG", "Br\u{e1}s Pires", "3108701"], + &["MG", "Brasil\u{e2}ndia de Minas", "3108552"], + &["MG", "Bras\u{ed}lia de Minas", "3108602"], + &["MG", "Bra\u{fa}nas", "3108800"], + &["MG", "Braz\u{f3}polis", "3108909"], + &["MG", "Brumadinho", "3109006"], + &["MG", "Bueno Brand\u{e3}o", "3109105"], + &["MG", "Buen\u{f3}polis", "3109204"], + &["MG", "Bugre", "3109253"], + &["MG", "Buritis", "3109303"], + &["MG", "Buritizeiro", "3109402"], + &["MG", "Cabeceira Grande", "3109451"], + &["MG", "Cabo Verde", "3109501"], + &["MG", "Cachoeira da Prata", "3109600"], + &["MG", "Cachoeira de Minas", "3109709"], + &["MG", "Cachoeira de Paje\u{fa}", "3102704"], + &["MG", "Cachoeira Dourada", "3109808"], + &["MG", "Caetan\u{f3}polis", "3109907"], + &["MG", "Caet\u{e9}", "3110004"], + &["MG", "Caiana", "3110103"], + &["MG", "Cajuri", "3110202"], + &["MG", "Caldas", "3110301"], + &["MG", "Camacho", "3110400"], + &["MG", "Camanducaia", "3110509"], + &["MG", "Cambu\u{ed}", "3110608"], + &["MG", "Cambuquira", "3110707"], + &["MG", "Campan\u{e1}rio", "3110806"], + &["MG", "Campanha", "3110905"], + &["MG", "Campestre", "3111002"], + &["MG", "Campina Verde", "3111101"], + &["MG", "Campo Azul", "3111150"], + &["MG", "Campo Belo", "3111200"], + &["MG", "Campo do Meio", "3111309"], + &["MG", "Campo Florido", "3111408"], + &["MG", "Campos Altos", "3111507"], + &["MG", "Campos Gerais", "3111606"], + &["MG", "Cana Verde", "3111903"], + &["MG", "Cana\u{e3}", "3111705"], + &["MG", "Can\u{e1}polis", "3111804"], + &["MG", "Candeias", "3112000"], + &["MG", "Cantagalo", "3112059"], + &["MG", "Capara\u{f3}", "3112109"], + &["MG", "Capela Nova", "3112208"], + &["MG", "Capelinha", "3112307"], + &["MG", "Capetinga", "3112406"], + &["MG", "Capim Branco", "3112505"], + &["MG", "Capin\u{f3}polis", "3112604"], + &["MG", "Capit\u{e3}o Andrade", "3112653"], + &["MG", "Capit\u{e3}o En\u{e9}as", "3112703"], + &["MG", "Capit\u{f3}lio", "3112802"], + &["MG", "Caputira", "3112901"], + &["MG", "Cara\u{ed}", "3113008"], + &["MG", "Carana\u{ed}ba", "3113107"], + &["MG", "Caranda\u{ed}", "3113206"], + &["MG", "Carangola", "3113305"], + &["MG", "Caratinga", "3113404"], + &["MG", "Carbonita", "3113503"], + &["MG", "Carea\u{e7}u", "3113602"], + &["MG", "Carlos Chagas", "3113701"], + &["MG", "Carm\u{e9}sia", "3113800"], + &["MG", "Carmo da Cachoeira", "3113909"], + &["MG", "Carmo da Mata", "3114006"], + &["MG", "Carmo de Minas", "3114105"], + &["MG", "Carmo do Cajuru", "3114204"], + &["MG", "Carmo do Parana\u{ed}ba", "3114303"], + &["MG", "Carmo do Rio Claro", "3114402"], + &["MG", "Carm\u{f3}polis de Minas", "3114501"], + &["MG", "Carneirinho", "3114550"], + &["MG", "Carrancas", "3114600"], + &["MG", "Carvalh\u{f3}polis", "3114709"], + &["MG", "Carvalhos", "3114808"], + &["MG", "Casa Grande", "3114907"], + &["MG", "Cascalho Rico", "3115003"], + &["MG", "C\u{e1}ssia", "3115102"], + &["MG", "Cataguases", "3115300"], + &["MG", "Catas Altas", "3115359"], + &["MG", "Catas Altas da Noruega", "3115409"], + &["MG", "Catuji", "3115458"], + &["MG", "Catuti", "3115474"], + &["MG", "Caxambu", "3115508"], + &["MG", "Cedro do Abaet\u{e9}", "3115607"], + &["MG", "Central de Minas", "3115706"], + &["MG", "Centralina", "3115805"], + &["MG", "Ch\u{e1}cara", "3115904"], + &["MG", "Chal\u{e9}", "3116001"], + &["MG", "Chapada do Norte", "3116100"], + &["MG", "Chapada Ga\u{fa}cha", "3116159"], + &["MG", "Chiador", "3116209"], + &["MG", "Cipot\u{e2}nea", "3116308"], + &["MG", "Claraval", "3116407"], + &["MG", "Claro dos Po\u{e7}\u{f5}es", "3116506"], + &["MG", "Cl\u{e1}udio", "3116605"], + &["MG", "Coimbra", "3116704"], + &["MG", "Coluna", "3116803"], + &["MG", "Comendador Gomes", "3116902"], + &["MG", "Comercinho", "3117009"], + &["MG", "Concei\u{e7}\u{e3}o da Aparecida", "3117108"], + &["MG", "Concei\u{e7}\u{e3}o da Barra de Minas", "3115201"], + &["MG", "Concei\u{e7}\u{e3}o das Alagoas", "3117306"], + &["MG", "Concei\u{e7}\u{e3}o das Pedras", "3117207"], + &["MG", "Concei\u{e7}\u{e3}o de Ipanema", "3117405"], + &["MG", "Concei\u{e7}\u{e3}o do Mato Dentro", "3117504"], + &["MG", "Concei\u{e7}\u{e3}o do Par\u{e1}", "3117603"], + &["MG", "Concei\u{e7}\u{e3}o do Rio Verde", "3117702"], + &["MG", "Concei\u{e7}\u{e3}o dos Ouros", "3117801"], + &["MG", "C\u{f4}nego Marinho", "3117836"], + &["MG", "Confins", "3117876"], + &["MG", "Congonhal", "3117900"], + &["MG", "Congonhas", "3118007"], + &["MG", "Congonhas do Norte", "3118106"], + &["MG", "Conquista", "3118205"], + &["MG", "Conselheiro Lafaiete", "3118304"], + &["MG", "Conselheiro Pena", "3118403"], + &["MG", "Consola\u{e7}\u{e3}o", "3118502"], + &["MG", "Contagem", "3118601"], + &["MG", "Coqueiral", "3118700"], + &["MG", "Cora\u{e7}\u{e3}o de Jesus", "3118809"], + &["MG", "Cordisburgo", "3118908"], + &["MG", "Cordisl\u{e2}ndia", "3119005"], + &["MG", "Corinto", "3119104"], + &["MG", "Coroaci", "3119203"], + &["MG", "Coromandel", "3119302"], + &["MG", "Coronel Fabriciano", "3119401"], + &["MG", "Coronel Murta", "3119500"], + &["MG", "Coronel Pacheco", "3119609"], + &["MG", "Coronel Xavier Chaves", "3119708"], + &["MG", "C\u{f3}rrego Danta", "3119807"], + &["MG", "C\u{f3}rrego do Bom Jesus", "3119906"], + &["MG", "C\u{f3}rrego Fundo", "3119955"], + &["MG", "C\u{f3}rrego Novo", "3120003"], + &["MG", "Couto de Magalh\u{e3}es de Minas", "3120102"], + &["MG", "Cris\u{f3}lita", "3120151"], + &["MG", "Cristais", "3120201"], + &["MG", "Crist\u{e1}lia", "3120300"], + &["MG", "Cristiano Otoni", "3120409"], + &["MG", "Cristina", "3120508"], + &["MG", "Crucil\u{e2}ndia", "3120607"], + &["MG", "Cruzeiro da Fortaleza", "3120706"], + &["MG", "Cruz\u{ed}lia", "3120805"], + &["MG", "Cuparaque", "3120839"], + &["MG", "Curral de Dentro", "3120870"], + &["MG", "Curvelo", "3120904"], + &["MG", "Datas", "3121001"], + &["MG", "Delfim Moreira", "3121100"], + &["MG", "Delfin\u{f3}polis", "3121209"], + &["MG", "Delta", "3121258"], + &["MG", "Descoberto", "3121308"], + &["MG", "Desterro de Entre Rios", "3121407"], + &["MG", "Desterro do Melo", "3121506"], + &["MG", "Diamantina", "3121605"], + &["MG", "Diogo de Vasconcelos", "3121704"], + &["MG", "Dion\u{ed}sio", "3121803"], + &["MG", "Divin\u{e9}sia", "3121902"], + &["MG", "Divino", "3122009"], + &["MG", "Divino das Laranjeiras", "3122108"], + &["MG", "Divinol\u{e2}ndia de Minas", "3122207"], + &["MG", "Divin\u{f3}polis", "3122306"], + &["MG", "Divisa Alegre", "3122355"], + &["MG", "Divisa Nova", "3122405"], + &["MG", "Divis\u{f3}polis", "3122454"], + &["MG", "Dom Bosco", "3122470"], + &["MG", "Dom Cavati", "3122504"], + &["MG", "Dom Joaquim", "3122603"], + &["MG", "Dom Silv\u{e9}rio", "3122702"], + &["MG", "Dom Vi\u{e7}oso", "3122801"], + &["MG", "Dona Euz\u{e9}bia", "3122900"], + &["MG", "Dores de Campos", "3123007"], + &["MG", "Dores de Guanh\u{e3}es", "3123106"], + &["MG", "Dores do Indai\u{e1}", "3123205"], + &["MG", "Dores do Turvo", "3123304"], + &["MG", "Dores\u{f3}polis", "3123403"], + &["MG", "Douradoquara", "3123502"], + &["MG", "Durand\u{e9}", "3123528"], + &["MG", "El\u{f3}i Mendes", "3123601"], + &["MG", "Engenheiro Caldas", "3123700"], + &["MG", "Engenheiro Navarro", "3123809"], + &["MG", "Entre Folhas", "3123858"], + &["MG", "Entre Rios de Minas", "3123908"], + &["MG", "Erv\u{e1}lia", "3124005"], + &["MG", "Esmeraldas", "3124104"], + &["MG", "Espera Feliz", "3124203"], + &["MG", "Espinosa", "3124302"], + &["MG", "Esp\u{ed}rito Santo do Dourado", "3124401"], + &["MG", "Estiva", "3124500"], + &["MG", "Estrela Dalva", "3124609"], + &["MG", "Estrela do Indai\u{e1}", "3124708"], + &["MG", "Estrela do Sul", "3124807"], + &["MG", "Eugen\u{f3}polis", "3124906"], + &["MG", "Ewbank da C\u{e2}mara", "3125002"], + &["MG", "Extrema", "3125101"], + &["MG", "Fama", "3125200"], + &["MG", "Faria Lemos", "3125309"], + &["MG", "Fel\u{ed}cio dos Santos", "3125408"], + &["MG", "Felisburgo", "3125606"], + &["MG", "Felixl\u{e2}ndia", "3125705"], + &["MG", "Fernandes Tourinho", "3125804"], + &["MG", "Ferros", "3125903"], + &["MG", "Fervedouro", "3125952"], + &["MG", "Florestal", "3126000"], + &["MG", "Formiga", "3126109"], + &["MG", "Formoso", "3126208"], + &["MG", "Fortaleza de Minas", "3126307"], + &["MG", "Fortuna de Minas", "3126406"], + &["MG", "Francisco Badar\u{f3}", "3126505"], + &["MG", "Francisco Dumont", "3126604"], + &["MG", "Francisco S\u{e1}", "3126703"], + &["MG", "Francisc\u{f3}polis", "3126752"], + &["MG", "Frei Gaspar", "3126802"], + &["MG", "Frei Inoc\u{ea}ncio", "3126901"], + &["MG", "Frei Lagonegro", "3126950"], + &["MG", "Fronteira", "3127008"], + &["MG", "Fronteira dos Vales", "3127057"], + &["MG", "Fruta de Leite", "3127073"], + &["MG", "Frutal", "3127107"], + &["MG", "Funil\u{e2}ndia", "3127206"], + &["MG", "Galil\u{e9}ia", "3127305"], + &["MG", "Gameleiras", "3127339"], + &["MG", "Glaucil\u{e2}ndia", "3127354"], + &["MG", "Goiabeira", "3127370"], + &["MG", "Goian\u{e1}", "3127388"], + &["MG", "Gon\u{e7}alves", "3127404"], + &["MG", "Gonzaga", "3127503"], + &["MG", "Gouveia", "3127602"], + &["MG", "Governador Valadares", "3127701"], + &["MG", "Gr\u{e3}o Mogol", "3127800"], + &["MG", "Grupiara", "3127909"], + &["MG", "Guanh\u{e3}es", "3128006"], + &["MG", "Guap\u{e9}", "3128105"], + &["MG", "Guaraciaba", "3128204"], + &["MG", "Guaraciama", "3128253"], + &["MG", "Guaran\u{e9}sia", "3128303"], + &["MG", "Guarani", "3128402"], + &["MG", "Guarar\u{e1}", "3128501"], + &["MG", "Guarda-Mor", "3128600"], + &["MG", "Guaxup\u{e9}", "3128709"], + &["MG", "Guidoval", "3128808"], + &["MG", "Guimar\u{e2}nia", "3128907"], + &["MG", "Guiricema", "3129004"], + &["MG", "Gurinhat\u{e3}", "3129103"], + &["MG", "Heliodora", "3129202"], + &["MG", "Iapu", "3129301"], + &["MG", "Ibertioga", "3129400"], + &["MG", "Ibi\u{e1}", "3129509"], + &["MG", "Ibia\u{ed}", "3129608"], + &["MG", "Ibiracatu", "3129657"], + &["MG", "Ibiraci", "3129707"], + &["MG", "Ibirit\u{e9}", "3129806"], + &["MG", "Ibiti\u{fa}ra de Minas", "3129905"], + &["MG", "Ibituruna", "3130002"], + &["MG", "Icara\u{ed} de Minas", "3130051"], + &["MG", "Igarap\u{e9}", "3130101"], + &["MG", "Igaratinga", "3130200"], + &["MG", "Iguatama", "3130309"], + &["MG", "Ijaci", "3130408"], + &["MG", "Ilic\u{ed}nea", "3130507"], + &["MG", "Imb\u{e9} de Minas", "3130556"], + &["MG", "Inconfidentes", "3130606"], + &["MG", "Indaiabira", "3130655"], + &["MG", "Indian\u{f3}polis", "3130705"], + &["MG", "Inga\u{ed}", "3130804"], + &["MG", "Inhapim", "3130903"], + &["MG", "Inha\u{fa}ma", "3131000"], + &["MG", "Inimutaba", "3131109"], + &["MG", "Ipaba", "3131158"], + &["MG", "Ipanema", "3131208"], + &["MG", "Ipatinga", "3131307"], + &["MG", "Ipia\u{e7}u", "3131406"], + &["MG", "Ipui\u{fa}na", "3131505"], + &["MG", "Ira\u{ed} de Minas", "3131604"], + &["MG", "Itabira", "3131703"], + &["MG", "Itabirinha", "3131802"], + &["MG", "Itabirito", "3131901"], + &["MG", "Itacambira", "3132008"], + &["MG", "Itacarambi", "3132107"], + &["MG", "Itaguara", "3132206"], + &["MG", "Itaip\u{e9}", "3132305"], + &["MG", "Itajub\u{e1}", "3132404"], + &["MG", "Itamarandiba", "3132503"], + &["MG", "Itamarati de Minas", "3132602"], + &["MG", "Itambacuri", "3132701"], + &["MG", "Itamb\u{e9} do Mato Dentro", "3132800"], + &["MG", "Itamogi", "3132909"], + &["MG", "Itamonte", "3133006"], + &["MG", "Itanhandu", "3133105"], + &["MG", "Itanhomi", "3133204"], + &["MG", "Itaobim", "3133303"], + &["MG", "Itapagipe", "3133402"], + &["MG", "Itapecerica", "3133501"], + &["MG", "Itapeva", "3133600"], + &["MG", "Itatiaiu\u{e7}u", "3133709"], + &["MG", "Ita\u{fa} de Minas", "3133758"], + &["MG", "Ita\u{fa}na", "3133808"], + &["MG", "Itaverava", "3133907"], + &["MG", "Itinga", "3134004"], + &["MG", "Itueta", "3134103"], + &["MG", "Ituiutaba", "3134202"], + &["MG", "Itumirim", "3134301"], + &["MG", "Iturama", "3134400"], + &["MG", "Itutinga", "3134509"], + &["MG", "Jaboticatubas", "3134608"], + &["MG", "Jacinto", "3134707"], + &["MG", "Jacu\u{ed}", "3134806"], + &["MG", "Jacutinga", "3134905"], + &["MG", "Jaguara\u{e7}u", "3135001"], + &["MG", "Ja\u{ed}ba", "3135050"], + &["MG", "Jampruca", "3135076"], + &["MG", "Jana\u{fa}ba", "3135100"], + &["MG", "Janu\u{e1}ria", "3135209"], + &["MG", "Japara\u{ed}ba", "3135308"], + &["MG", "Japonvar", "3135357"], + &["MG", "Jeceaba", "3135407"], + &["MG", "Jenipapo de Minas", "3135456"], + &["MG", "Jequeri", "3135506"], + &["MG", "Jequita\u{ed}", "3135605"], + &["MG", "Jequitib\u{e1}", "3135704"], + &["MG", "Jequitinhonha", "3135803"], + &["MG", "Jesu\u{e2}nia", "3135902"], + &["MG", "Joa\u{ed}ma", "3136009"], + &["MG", "Joan\u{e9}sia", "3136108"], + &["MG", "Jo\u{e3}o Monlevade", "3136207"], + &["MG", "Jo\u{e3}o Pinheiro", "3136306"], + &["MG", "Joaquim Fel\u{ed}cio", "3136405"], + &["MG", "Jord\u{e2}nia", "3136504"], + &["MG", "Jos\u{e9} Gon\u{e7}alves de Minas", "3136520"], + &["MG", "Jos\u{e9} Raydan", "3136553"], + &["MG", "Josen\u{f3}polis", "3136579"], + &["MG", "Juatuba", "3136652"], + &["MG", "Juiz de Fora", "3136702"], + &["MG", "Juramento", "3136801"], + &["MG", "Juruaia", "3136900"], + &["MG", "Juven\u{ed}lia", "3136959"], + &["MG", "Ladainha", "3137007"], + &["MG", "Lagamar", "3137106"], + &["MG", "Lagoa da Prata", "3137205"], + &["MG", "Lagoa dos Patos", "3137304"], + &["MG", "Lagoa Dourada", "3137403"], + &["MG", "Lagoa Formosa", "3137502"], + &["MG", "Lagoa Grande", "3137536"], + &["MG", "Lagoa Santa", "3137601"], + &["MG", "Lajinha", "3137700"], + &["MG", "Lambari", "3137809"], + &["MG", "Lamim", "3137908"], + &["MG", "Laranjal", "3138005"], + &["MG", "Lassance", "3138104"], + &["MG", "Lavras", "3138203"], + &["MG", "Leandro Ferreira", "3138302"], + &["MG", "Leme do Prado", "3138351"], + &["MG", "Leopoldina", "3138401"], + &["MG", "Liberdade", "3138500"], + &["MG", "Lima Duarte", "3138609"], + &["MG", "Limeira do Oeste", "3138625"], + &["MG", "Lontra", "3138658"], + &["MG", "Luisburgo", "3138674"], + &["MG", "Luisl\u{e2}ndia", "3138682"], + &["MG", "Lumin\u{e1}rias", "3138708"], + &["MG", "Luz", "3138807"], + &["MG", "Machacalis", "3138906"], + &["MG", "Machado", "3139003"], + &["MG", "Madre de Deus de Minas", "3139102"], + &["MG", "Malacacheta", "3139201"], + &["MG", "Mamonas", "3139250"], + &["MG", "Manga", "3139300"], + &["MG", "Manhua\u{e7}u", "3139409"], + &["MG", "Manhumirim", "3139508"], + &["MG", "Mantena", "3139607"], + &["MG", "Mar de Espanha", "3139805"], + &["MG", "Maravilhas", "3139706"], + &["MG", "Maria da F\u{e9}", "3139904"], + &["MG", "Mariana", "3140001"], + &["MG", "Marilac", "3140100"], + &["MG", "M\u{e1}rio Campos", "3140159"], + &["MG", "Marip\u{e1} de Minas", "3140209"], + &["MG", "Marli\u{e9}ria", "3140308"], + &["MG", "Marmel\u{f3}polis", "3140407"], + &["MG", "Martinho Campos", "3140506"], + &["MG", "Martins Soares", "3140530"], + &["MG", "Mata Verde", "3140555"], + &["MG", "Materl\u{e2}ndia", "3140605"], + &["MG", "Mateus Leme", "3140704"], + &["MG", "Mathias Lobato", "3171501"], + &["MG", "Matias Barbosa", "3140803"], + &["MG", "Matias Cardoso", "3140852"], + &["MG", "Matip\u{f3}", "3140902"], + &["MG", "Mato Verde", "3141009"], + &["MG", "Matozinhos", "3141108"], + &["MG", "Matutina", "3141207"], + &["MG", "Medeiros", "3141306"], + &["MG", "Medina", "3141405"], + &["MG", "Mendes Pimentel", "3141504"], + &["MG", "Merc\u{ea}s", "3141603"], + &["MG", "Mesquita", "3141702"], + &["MG", "Minas Novas", "3141801"], + &["MG", "Minduri", "3141900"], + &["MG", "Mirabela", "3142007"], + &["MG", "Miradouro", "3142106"], + &["MG", "Mira\u{ed}", "3142205"], + &["MG", "Mirav\u{e2}nia", "3142254"], + &["MG", "Moeda", "3142304"], + &["MG", "Moema", "3142403"], + &["MG", "Monjolos", "3142502"], + &["MG", "Monsenhor Paulo", "3142601"], + &["MG", "Montalv\u{e2}nia", "3142700"], + &["MG", "Monte Alegre de Minas", "3142809"], + &["MG", "Monte Azul", "3142908"], + &["MG", "Monte Belo", "3143005"], + &["MG", "Monte Carmelo", "3143104"], + &["MG", "Monte Formoso", "3143153"], + &["MG", "Monte Santo de Minas", "3143203"], + &["MG", "Monte Si\u{e3}o", "3143401"], + &["MG", "Montes Claros", "3143302"], + &["MG", "Montezuma", "3143450"], + &["MG", "Morada Nova de Minas", "3143500"], + &["MG", "Morro da Gar\u{e7}a", "3143609"], + &["MG", "Morro do Pilar", "3143708"], + &["MG", "Munhoz", "3143807"], + &["MG", "Muria\u{e9}", "3143906"], + &["MG", "Mutum", "3144003"], + &["MG", "Muzambinho", "3144102"], + &["MG", "Nacip Raydan", "3144201"], + &["MG", "Nanuque", "3144300"], + &["MG", "Naque", "3144359"], + &["MG", "Natal\u{e2}ndia", "3144375"], + &["MG", "Nat\u{e9}rcia", "3144409"], + &["MG", "Nazareno", "3144508"], + &["MG", "Nepomuceno", "3144607"], + &["MG", "Ninheira", "3144656"], + &["MG", "Nova Bel\u{e9}m", "3144672"], + &["MG", "Nova Era", "3144706"], + &["MG", "Nova Lima", "3144805"], + &["MG", "Nova M\u{f3}dica", "3144904"], + &["MG", "Nova Ponte", "3145000"], + &["MG", "Nova Porteirinha", "3145059"], + &["MG", "Nova Resende", "3145109"], + &["MG", "Nova Serrana", "3145208"], + &["MG", "Nova Uni\u{e3}o", "3136603"], + &["MG", "Novo Cruzeiro", "3145307"], + &["MG", "Novo Oriente de Minas", "3145356"], + &["MG", "Novorizonte", "3145372"], + &["MG", "Olaria", "3145406"], + &["MG", "Olhos-d'\u{c1}gua", "3145455"], + &["MG", "Ol\u{ed}mpio Noronha", "3145505"], + &["MG", "Oliveira", "3145604"], + &["MG", "Oliveira Fortes", "3145703"], + &["MG", "On\u{e7}a de Pitangui", "3145802"], + &["MG", "Orat\u{f3}rios", "3145851"], + &["MG", "Oriz\u{e2}nia", "3145877"], + &["MG", "Ouro Branco", "3145901"], + &["MG", "Ouro Fino", "3146008"], + &["MG", "Ouro Preto", "3146107"], + &["MG", "Ouro Verde de Minas", "3146206"], + &["MG", "Padre Carvalho", "3146255"], + &["MG", "Padre Para\u{ed}so", "3146305"], + &["MG", "Pai Pedro", "3146552"], + &["MG", "Paineiras", "3146404"], + &["MG", "Pains", "3146503"], + &["MG", "Paiva", "3146602"], + &["MG", "Palma", "3146701"], + &["MG", "Palm\u{f3}polis", "3146750"], + &["MG", "Papagaios", "3146909"], + &["MG", "Par\u{e1} de Minas", "3147105"], + &["MG", "Paracatu", "3147006"], + &["MG", "Paragua\u{e7}u", "3147204"], + &["MG", "Parais\u{f3}polis", "3147303"], + &["MG", "Paraopeba", "3147402"], + &["MG", "Passa Quatro", "3147600"], + &["MG", "Passa Tempo", "3147709"], + &["MG", "Passa Vinte", "3147808"], + &["MG", "Passab\u{e9}m", "3147501"], + &["MG", "Passos", "3147907"], + &["MG", "Patis", "3147956"], + &["MG", "Patos de Minas", "3148004"], + &["MG", "Patroc\u{ed}nio", "3148103"], + &["MG", "Patroc\u{ed}nio do Muria\u{e9}", "3148202"], + &["MG", "Paula C\u{e2}ndido", "3148301"], + &["MG", "Paulistas", "3148400"], + &["MG", "Pav\u{e3}o", "3148509"], + &["MG", "Pe\u{e7}anha", "3148608"], + &["MG", "Pedra Azul", "3148707"], + &["MG", "Pedra Bonita", "3148756"], + &["MG", "Pedra do Anta", "3148806"], + &["MG", "Pedra do Indai\u{e1}", "3148905"], + &["MG", "Pedra Dourada", "3149002"], + &["MG", "Pedralva", "3149101"], + &["MG", "Pedras de Maria da Cruz", "3149150"], + &["MG", "Pedrin\u{f3}polis", "3149200"], + &["MG", "Pedro Leopoldo", "3149309"], + &["MG", "Pedro Teixeira", "3149408"], + &["MG", "Pequeri", "3149507"], + &["MG", "Pequi", "3149606"], + &["MG", "Perdig\u{e3}o", "3149705"], + &["MG", "Perdizes", "3149804"], + &["MG", "Perd\u{f5}es", "3149903"], + &["MG", "Periquito", "3149952"], + &["MG", "Pescador", "3150000"], + &["MG", "Piau", "3150109"], + &["MG", "Piedade de Caratinga", "3150158"], + &["MG", "Piedade de Ponte Nova", "3150208"], + &["MG", "Piedade do Rio Grande", "3150307"], + &["MG", "Piedade dos Gerais", "3150406"], + &["MG", "Pimenta", "3150505"], + &["MG", "Pingo-d'\u{c1}gua", "3150539"], + &["MG", "Pint\u{f3}polis", "3150570"], + &["MG", "Piracema", "3150604"], + &["MG", "Pirajuba", "3150703"], + &["MG", "Piranga", "3150802"], + &["MG", "Pirangu\u{e7}u", "3150901"], + &["MG", "Piranguinho", "3151008"], + &["MG", "Pirapetinga", "3151107"], + &["MG", "Pirapora", "3151206"], + &["MG", "Pira\u{fa}ba", "3151305"], + &["MG", "Pitangui", "3151404"], + &["MG", "Piumhi", "3151503"], + &["MG", "Planura", "3151602"], + &["MG", "Po\u{e7}o Fundo", "3151701"], + &["MG", "Po\u{e7}os de Caldas", "3151800"], + &["MG", "Pocrane", "3151909"], + &["MG", "Pomp\u{e9}u", "3152006"], + &["MG", "Ponte Nova", "3152105"], + &["MG", "Ponto Chique", "3152131"], + &["MG", "Ponto dos Volantes", "3152170"], + &["MG", "Porteirinha", "3152204"], + &["MG", "Porto Firme", "3152303"], + &["MG", "Pot\u{e9}", "3152402"], + &["MG", "Pouso Alegre", "3152501"], + &["MG", "Pouso Alto", "3152600"], + &["MG", "Prados", "3152709"], + &["MG", "Prata", "3152808"], + &["MG", "Prat\u{e1}polis", "3152907"], + &["MG", "Pratinha", "3153004"], + &["MG", "Presidente Bernardes", "3153103"], + &["MG", "Presidente Juscelino", "3153202"], + &["MG", "Presidente Kubitschek", "3153301"], + &["MG", "Presidente Oleg\u{e1}rio", "3153400"], + &["MG", "Prudente de Morais", "3153608"], + &["MG", "Quartel Geral", "3153707"], + &["MG", "Queluzito", "3153806"], + &["MG", "Raposos", "3153905"], + &["MG", "Raul Soares", "3154002"], + &["MG", "Recreio", "3154101"], + &["MG", "Reduto", "3154150"], + &["MG", "Resende Costa", "3154200"], + &["MG", "Resplendor", "3154309"], + &["MG", "Ressaquinha", "3154408"], + &["MG", "Riachinho", "3154457"], + &["MG", "Riacho dos Machados", "3154507"], + &["MG", "Ribeir\u{e3}o das Neves", "3154606"], + &["MG", "Ribeir\u{e3}o Vermelho", "3154705"], + &["MG", "Rio Acima", "3154804"], + &["MG", "Rio Casca", "3154903"], + &["MG", "Rio do Prado", "3155108"], + &["MG", "Rio Doce", "3155009"], + &["MG", "Rio Espera", "3155207"], + &["MG", "Rio Manso", "3155306"], + &["MG", "Rio Novo", "3155405"], + &["MG", "Rio Parana\u{ed}ba", "3155504"], + &["MG", "Rio Pardo de Minas", "3155603"], + &["MG", "Rio Piracicaba", "3155702"], + &["MG", "Rio Pomba", "3155801"], + &["MG", "Rio Preto", "3155900"], + &["MG", "Rio Vermelho", "3156007"], + &["MG", "Rit\u{e1}polis", "3156106"], + &["MG", "Rochedo de Minas", "3156205"], + &["MG", "Rodeiro", "3156304"], + &["MG", "Romaria", "3156403"], + &["MG", "Ros\u{e1}rio da Limeira", "3156452"], + &["MG", "Rubelita", "3156502"], + &["MG", "Rubim", "3156601"], + &["MG", "Sabar\u{e1}", "3156700"], + &["MG", "Sabin\u{f3}polis", "3156809"], + &["MG", "Sacramento", "3156908"], + &["MG", "Salinas", "3157005"], + &["MG", "Salto da Divisa", "3157104"], + &["MG", "Santa B\u{e1}rbara", "3157203"], + &["MG", "Santa B\u{e1}rbara do Leste", "3157252"], + &["MG", "Santa B\u{e1}rbara do Monte Verde", "3157278"], + &["MG", "Santa B\u{e1}rbara do Tug\u{fa}rio", "3157302"], + &["MG", "Santa Cruz de Minas", "3157336"], + &["MG", "Santa Cruz de Salinas", "3157377"], + &["MG", "Santa Cruz do Escalvado", "3157401"], + &["MG", "Santa Efig\u{ea}nia de Minas", "3157500"], + &["MG", "Santa F\u{e9} de Minas", "3157609"], + &["MG", "Santa Helena de Minas", "3157658"], + &["MG", "Santa Juliana", "3157708"], + &["MG", "Santa Luzia", "3157807"], + &["MG", "Santa Margarida", "3157906"], + &["MG", "Santa Maria de Itabira", "3158003"], + &["MG", "Santa Maria do Salto", "3158102"], + &["MG", "Santa Maria do Sua\u{e7}u\u{ed}", "3158201"], + &["MG", "Santa Rita de Caldas", "3159209"], + &["MG", "Santa Rita de Ibitipoca", "3159407"], + &["MG", "Santa Rita de Jacutinga", "3159308"], + &["MG", "Santa Rita de Minas", "3159357"], + &["MG", "Santa Rita do Itueto", "3159506"], + &["MG", "Santa Rita do Sapuca\u{ed}", "3159605"], + &["MG", "Santa Rosa da Serra", "3159704"], + &["MG", "Santa Vit\u{f3}ria", "3159803"], + &["MG", "Santana da Vargem", "3158300"], + &["MG", "Santana de Cataguases", "3158409"], + &["MG", "Santana de Pirapama", "3158508"], + &["MG", "Santana do Deserto", "3158607"], + &["MG", "Santana do Garamb\u{e9}u", "3158706"], + &["MG", "Santana do Jacar\u{e9}", "3158805"], + &["MG", "Santana do Manhua\u{e7}u", "3158904"], + &["MG", "Santana do Para\u{ed}so", "3158953"], + &["MG", "Santana do Riacho", "3159001"], + &["MG", "Santana dos Montes", "3159100"], + &["MG", "Santo Ant\u{f4}nio do Amparo", "3159902"], + &["MG", "Santo Ant\u{f4}nio do Aventureiro", "3160009"], + &["MG", "Santo Ant\u{f4}nio do Grama", "3160108"], + &["MG", "Santo Ant\u{f4}nio do Itamb\u{e9}", "3160207"], + &["MG", "Santo Ant\u{f4}nio do Jacinto", "3160306"], + &["MG", "Santo Ant\u{f4}nio do Monte", "3160405"], + &["MG", "Santo Ant\u{f4}nio do Retiro", "3160454"], + &["MG", "Santo Ant\u{f4}nio do Rio Abaixo", "3160504"], + &["MG", "Santo Hip\u{f3}lito", "3160603"], + &["MG", "Santos Dumont", "3160702"], + &["MG", "S\u{e3}o Bento Abade", "3160801"], + &["MG", "S\u{e3}o Br\u{e1}s do Sua\u{e7}u\u{ed}", "3160900"], + &["MG", "S\u{e3}o Domingos das Dores", "3160959"], + &["MG", "S\u{e3}o Domingos do Prata", "3161007"], + &["MG", "S\u{e3}o F\u{e9}lix de Minas", "3161056"], + &["MG", "S\u{e3}o Francisco", "3161106"], + &["MG", "S\u{e3}o Francisco de Paula", "3161205"], + &["MG", "S\u{e3}o Francisco de Sales", "3161304"], + &["MG", "S\u{e3}o Francisco do Gl\u{f3}ria", "3161403"], + &["MG", "S\u{e3}o Geraldo", "3161502"], + &["MG", "S\u{e3}o Geraldo da Piedade", "3161601"], + &["MG", "S\u{e3}o Geraldo do Baixio", "3161650"], + &["MG", "S\u{e3}o Gon\u{e7}alo do Abaet\u{e9}", "3161700"], + &["MG", "S\u{e3}o Gon\u{e7}alo do Par\u{e1}", "3161809"], + &["MG", "S\u{e3}o Gon\u{e7}alo do Rio Abaixo", "3161908"], + &["MG", "S\u{e3}o Gon\u{e7}alo do Rio Preto", "3125507"], + &["MG", "S\u{e3}o Gon\u{e7}alo do Sapuca\u{ed}", "3162005"], + &["MG", "S\u{e3}o Gotardo", "3162104"], + &["MG", "S\u{e3}o Jo\u{e3}o Batista do Gl\u{f3}ria", "3162203"], + &["MG", "S\u{e3}o Jo\u{e3}o da Lagoa", "3162252"], + &["MG", "S\u{e3}o Jo\u{e3}o da Mata", "3162302"], + &["MG", "S\u{e3}o Jo\u{e3}o da Ponte", "3162401"], + &["MG", "S\u{e3}o Jo\u{e3}o das Miss\u{f5}es", "3162450"], + &["MG", "S\u{e3}o Jo\u{e3}o del Rei", "3162500"], + &["MG", "S\u{e3}o Jo\u{e3}o do Manhua\u{e7}u", "3162559"], + &["MG", "S\u{e3}o Jo\u{e3}o do Manteninha", "3162575"], + &["MG", "S\u{e3}o Jo\u{e3}o do Oriente", "3162609"], + &["MG", "S\u{e3}o Jo\u{e3}o do Pacu\u{ed}", "3162658"], + &["MG", "S\u{e3}o Jo\u{e3}o do Para\u{ed}so", "3162708"], + &["MG", "S\u{e3}o Jo\u{e3}o Evangelista", "3162807"], + &["MG", "S\u{e3}o Jo\u{e3}o Nepomuceno", "3162906"], + &["MG", "S\u{e3}o Joaquim de Bicas", "3162922"], + &["MG", "S\u{e3}o Jos\u{e9} da Barra", "3162948"], + &["MG", "S\u{e3}o Jos\u{e9} da Lapa", "3162955"], + &["MG", "S\u{e3}o Jos\u{e9} da Safira", "3163003"], + &["MG", "S\u{e3}o Jos\u{e9} da Varginha", "3163102"], + &["MG", "S\u{e3}o Jos\u{e9} do Alegre", "3163201"], + &["MG", "S\u{e3}o Jos\u{e9} do Divino", "3163300"], + &["MG", "S\u{e3}o Jos\u{e9} do Goiabal", "3163409"], + &["MG", "S\u{e3}o Jos\u{e9} do Jacuri", "3163508"], + &["MG", "S\u{e3}o Jos\u{e9} do Mantimento", "3163607"], + &["MG", "S\u{e3}o Louren\u{e7}o", "3163706"], + &["MG", "S\u{e3}o Miguel do Anta", "3163805"], + &["MG", "S\u{e3}o Pedro da Uni\u{e3}o", "3163904"], + &["MG", "S\u{e3}o Pedro do Sua\u{e7}u\u{ed}", "3164100"], + &["MG", "S\u{e3}o Pedro dos Ferros", "3164001"], + &["MG", "S\u{e3}o Rom\u{e3}o", "3164209"], + &["MG", "S\u{e3}o Roque de Minas", "3164308"], + &["MG", "S\u{e3}o Sebasti\u{e3}o da Bela Vista", "3164407"], + &["MG", "S\u{e3}o Sebasti\u{e3}o da Vargem Alegre", "3164431"], + &["MG", "S\u{e3}o Sebasti\u{e3}o do Anta", "3164472"], + &["MG", "S\u{e3}o Sebasti\u{e3}o do Maranh\u{e3}o", "3164506"], + &["MG", "S\u{e3}o Sebasti\u{e3}o do Oeste", "3164605"], + &["MG", "S\u{e3}o Sebasti\u{e3}o do Para\u{ed}so", "3164704"], + &["MG", "S\u{e3}o Sebasti\u{e3}o do Rio Preto", "3164803"], + &["MG", "S\u{e3}o Sebasti\u{e3}o do Rio Verde", "3164902"], + &["MG", "S\u{e3}o Tiago", "3165008"], + &["MG", "S\u{e3}o Tom\u{e1}s de Aquino", "3165107"], + &["MG", "S\u{e3}o Tom\u{e9} das Letras", "3165206"], + &["MG", "S\u{e3}o Vicente de Minas", "3165305"], + &["MG", "Sapuca\u{ed}-Mirim", "3165404"], + &["MG", "Sardo\u{e1}", "3165503"], + &["MG", "Sarzedo", "3165537"], + &["MG", "Sem-Peixe", "3165560"], + &["MG", "Senador Amaral", "3165578"], + &["MG", "Senador Cortes", "3165602"], + &["MG", "Senador Firmino", "3165701"], + &["MG", "Senador Jos\u{e9} Bento", "3165800"], + &["MG", "Senador Modestino Gon\u{e7}alves", "3165909"], + &["MG", "Senhora de Oliveira", "3166006"], + &["MG", "Senhora do Porto", "3166105"], + &["MG", "Senhora dos Rem\u{e9}dios", "3166204"], + &["MG", "Sericita", "3166303"], + &["MG", "Seritinga", "3166402"], + &["MG", "Serra Azul de Minas", "3166501"], + &["MG", "Serra da Saudade", "3166600"], + &["MG", "Serra do Salitre", "3166808"], + &["MG", "Serra dos Aimor\u{e9}s", "3166709"], + &["MG", "Serrania", "3166907"], + &["MG", "Serran\u{f3}polis de Minas", "3166956"], + &["MG", "Serranos", "3167004"], + &["MG", "Serro", "3167103"], + &["MG", "Sete Lagoas", "3167202"], + &["MG", "Setubinha", "3165552"], + &["MG", "Silveir\u{e2}nia", "3167301"], + &["MG", "Silvian\u{f3}polis", "3167400"], + &["MG", "Sim\u{e3}o Pereira", "3167509"], + &["MG", "Simon\u{e9}sia", "3167608"], + &["MG", "Sobr\u{e1}lia", "3167707"], + &["MG", "Soledade de Minas", "3167806"], + &["MG", "Tabuleiro", "3167905"], + &["MG", "Taiobeiras", "3168002"], + &["MG", "Taparuba", "3168051"], + &["MG", "Tapira", "3168101"], + &["MG", "Tapira\u{ed}", "3168200"], + &["MG", "Taquara\u{e7}u de Minas", "3168309"], + &["MG", "Tarumirim", "3168408"], + &["MG", "Teixeiras", "3168507"], + &["MG", "Te\u{f3}filo Otoni", "3168606"], + &["MG", "Tim\u{f3}teo", "3168705"], + &["MG", "Tiradentes", "3168804"], + &["MG", "Tiros", "3168903"], + &["MG", "Tocantins", "3169000"], + &["MG", "Tocos do Moji", "3169059"], + &["MG", "Toledo", "3169109"], + &["MG", "Tombos", "3169208"], + &["MG", "Tr\u{ea}s Cora\u{e7}\u{f5}es", "3169307"], + &["MG", "Tr\u{ea}s Marias", "3169356"], + &["MG", "Tr\u{ea}s Pontas", "3169406"], + &["MG", "Tumiritinga", "3169505"], + &["MG", "Tupaciguara", "3169604"], + &["MG", "Turmalina", "3169703"], + &["MG", "Turvol\u{e2}ndia", "3169802"], + &["MG", "Ub\u{e1}", "3169901"], + &["MG", "Uba\u{ed}", "3170008"], + &["MG", "Ubaporanga", "3170057"], + &["MG", "Uberaba", "3170107"], + &["MG", "Uberl\u{e2}ndia", "3170206"], + &["MG", "Umburatiba", "3170305"], + &["MG", "Una\u{ed}", "3170404"], + &["MG", "Uni\u{e3}o de Minas", "3170438"], + &["MG", "Uruana de Minas", "3170479"], + &["MG", "Uruc\u{e2}nia", "3170503"], + &["MG", "Urucuia", "3170529"], + &["MG", "Vargem Alegre", "3170578"], + &["MG", "Vargem Bonita", "3170602"], + &["MG", "Vargem Grande do Rio Pardo", "3170651"], + &["MG", "Varginha", "3170701"], + &["MG", "Varj\u{e3}o de Minas", "3170750"], + &["MG", "V\u{e1}rzea da Palma", "3170800"], + &["MG", "Varzel\u{e2}ndia", "3170909"], + &["MG", "Vazante", "3171006"], + &["MG", "Verdel\u{e2}ndia", "3171030"], + &["MG", "Veredinha", "3171071"], + &["MG", "Ver\u{ed}ssimo", "3171105"], + &["MG", "Vermelho Novo", "3171154"], + &["MG", "Vespasiano", "3171204"], + &["MG", "Vi\u{e7}osa", "3171303"], + &["MG", "Vieiras", "3171402"], + &["MG", "Virgem da Lapa", "3171600"], + &["MG", "Virg\u{ed}nia", "3171709"], + &["MG", "Virgin\u{f3}polis", "3171808"], + &["MG", "Virgol\u{e2}ndia", "3171907"], + &["MG", "Visconde do Rio Branco", "3172004"], + &["MG", "Volta Grande", "3172103"], + &["MG", "Wenceslau Braz", "3172202"], + &["PA", "Abaetetuba", "1500107"], + &["PA", "Abel Figueiredo", "1500131"], + &["PA", "Acar\u{e1}", "1500206"], + &["PA", "Afu\u{e1}", "1500305"], + &["PA", "\u{c1}gua Azul do Norte", "1500347"], + &["PA", "Alenquer", "1500404"], + &["PA", "Almeirim", "1500503"], + &["PA", "Altamira", "1500602"], + &["PA", "Anaj\u{e1}s", "1500701"], + &["PA", "Ananindeua", "1500800"], + &["PA", "Anapu", "1500859"], + &["PA", "Augusto Corr\u{ea}a", "1500909"], + &["PA", "Aurora do Par\u{e1}", "1500958"], + &["PA", "Aveiro", "1501006"], + &["PA", "Bagre", "1501105"], + &["PA", "Bai\u{e3}o", "1501204"], + &["PA", "Bannach", "1501253"], + &["PA", "Barcarena", "1501303"], + &["PA", "Bel\u{e9}m", "1501402"], + &["PA", "Belterra", "1501451"], + &["PA", "Benevides", "1501501"], + &["PA", "Bom Jesus do Tocantins", "1501576"], + &["PA", "Bonito", "1501600"], + &["PA", "Bragan\u{e7}a", "1501709"], + &["PA", "Brasil Novo", "1501725"], + &["PA", "Brejo Grande do Araguaia", "1501758"], + &["PA", "Breu Branco", "1501782"], + &["PA", "Breves", "1501808"], + &["PA", "Bujaru", "1501907"], + &["PA", "Cachoeira do Arari", "1502004"], + &["PA", "Cachoeira do Piri\u{e1}", "1501956"], + &["PA", "Camet\u{e1}", "1502103"], + &["PA", "Cana\u{e3} dos Caraj\u{e1}s", "1502152"], + &["PA", "Capanema", "1502202"], + &["PA", "Capit\u{e3}o Po\u{e7}o", "1502301"], + &["PA", "Castanhal", "1502400"], + &["PA", "Chaves", "1502509"], + &["PA", "Colares", "1502608"], + &["PA", "Concei\u{e7}\u{e3}o do Araguaia", "1502707"], + &["PA", "Conc\u{f3}rdia do Par\u{e1}", "1502756"], + &["PA", "Cumaru do Norte", "1502764"], + &["PA", "Curion\u{f3}polis", "1502772"], + &["PA", "Curralinho", "1502806"], + &["PA", "Curu\u{e1}", "1502855"], + &["PA", "Curu\u{e7}\u{e1}", "1502905"], + &["PA", "Dom Eliseu", "1502939"], + &["PA", "Eldorado do Caraj\u{e1}s", "1502954"], + &["PA", "Faro", "1503002"], + &["PA", "Floresta do Araguaia", "1503044"], + &["PA", "Garraf\u{e3}o do Norte", "1503077"], + &["PA", "Goian\u{e9}sia do Par\u{e1}", "1503093"], + &["PA", "Gurup\u{e1}", "1503101"], + &["PA", "Igarap\u{e9}-A\u{e7}u", "1503200"], + &["PA", "Igarap\u{e9}-Miri", "1503309"], + &["PA", "Inhangapi", "1503408"], + &["PA", "Ipixuna do Par\u{e1}", "1503457"], + &["PA", "Irituia", "1503507"], + &["PA", "Itaituba", "1503606"], + &["PA", "Itupiranga", "1503705"], + &["PA", "Jacareacanga", "1503754"], + &["PA", "Jacund\u{e1}", "1503804"], + &["PA", "Juruti", "1503903"], + &["PA", "Limoeiro do Ajuru", "1504000"], + &["PA", "M\u{e3}e do Rio", "1504059"], + &["PA", "Magalh\u{e3}es Barata", "1504109"], + &["PA", "Marab\u{e1}", "1504208"], + &["PA", "Maracan\u{e3}", "1504307"], + &["PA", "Marapanim", "1504406"], + &["PA", "Marituba", "1504422"], + &["PA", "Medicil\u{e2}ndia", "1504455"], + &["PA", "Melga\u{e7}o", "1504505"], + &["PA", "Mocajuba", "1504604"], + &["PA", "Moju", "1504703"], + &["PA", "Moju\u{ed} dos Campos", "1504752"], + &["PA", "Monte Alegre", "1504802"], + &["PA", "Muan\u{e1}", "1504901"], + &["PA", "Nova Esperan\u{e7}a do Piri\u{e1}", "1504950"], + &["PA", "Nova Ipixuna", "1504976"], + &["PA", "Nova Timboteua", "1505007"], + &["PA", "Novo Progresso", "1505031"], + &["PA", "Novo Repartimento", "1505064"], + &["PA", "\u{d3}bidos", "1505106"], + &["PA", "Oeiras do Par\u{e1}", "1505205"], + &["PA", "Oriximin\u{e1}", "1505304"], + &["PA", "Our\u{e9}m", "1505403"], + &["PA", "Ouril\u{e2}ndia do Norte", "1505437"], + &["PA", "Pacaj\u{e1}", "1505486"], + &["PA", "Palestina do Par\u{e1}", "1505494"], + &["PA", "Paragominas", "1505502"], + &["PA", "Parauapebas", "1505536"], + &["PA", "Pau D'Arco", "1505551"], + &["PA", "Peixe-Boi", "1505601"], + &["PA", "Pi\u{e7}arra", "1505635"], + &["PA", "Placas", "1505650"], + &["PA", "Ponta de Pedras", "1505700"], + &["PA", "Portel", "1505809"], + &["PA", "Porto de Moz", "1505908"], + &["PA", "Prainha", "1506005"], + &["PA", "Primavera", "1506104"], + &["PA", "Quatipuru", "1506112"], + &["PA", "Reden\u{e7}\u{e3}o", "1506138"], + &["PA", "Rio Maria", "1506161"], + &["PA", "Rondon do Par\u{e1}", "1506187"], + &["PA", "Rur\u{f3}polis", "1506195"], + &["PA", "Salin\u{f3}polis", "1506203"], + &["PA", "Salvaterra", "1506302"], + &["PA", "Santa B\u{e1}rbara do Par\u{e1}", "1506351"], + &["PA", "Santa Cruz do Arari", "1506401"], + &["PA", "Santa Izabel do Par\u{e1}", "1506500"], + &["PA", "Santa Luzia do Par\u{e1}", "1506559"], + &["PA", "Santa Maria das Barreiras", "1506583"], + &["PA", "Santa Maria do Par\u{e1}", "1506609"], + &["PA", "Santana do Araguaia", "1506708"], + &["PA", "Santar\u{e9}m", "1506807"], + &["PA", "Santar\u{e9}m Novo", "1506906"], + &["PA", "Santo Ant\u{f4}nio do Tau\u{e1}", "1507003"], + &["PA", "S\u{e3}o Caetano de Odivelas", "1507102"], + &["PA", "S\u{e3}o Domingos do Araguaia", "1507151"], + &["PA", "S\u{e3}o Domingos do Capim", "1507201"], + &["PA", "S\u{e3}o F\u{e9}lix do Xingu", "1507300"], + &["PA", "S\u{e3}o Francisco do Par\u{e1}", "1507409"], + &["PA", "S\u{e3}o Geraldo do Araguaia", "1507458"], + &["PA", "S\u{e3}o Jo\u{e3}o da Ponta", "1507466"], + &["PA", "S\u{e3}o Jo\u{e3}o de Pirabas", "1507474"], + &["PA", "S\u{e3}o Jo\u{e3}o do Araguaia", "1507508"], + &["PA", "S\u{e3}o Miguel do Guam\u{e1}", "1507607"], + &["PA", "S\u{e3}o Sebasti\u{e3}o da Boa Vista", "1507706"], + &["PA", "Sapucaia", "1507755"], + &["PA", "Senador Jos\u{e9} Porf\u{ed}rio", "1507805"], + &["PA", "Soure", "1507904"], + &["PA", "Tail\u{e2}ndia", "1507953"], + &["PA", "Terra Alta", "1507961"], + &["PA", "Terra Santa", "1507979"], + &["PA", "Tom\u{e9}-A\u{e7}u", "1508001"], + &["PA", "Tracuateua", "1508035"], + &["PA", "Trair\u{e3}o", "1508050"], + &["PA", "Tucum\u{e3}", "1508084"], + &["PA", "Tucuru\u{ed}", "1508100"], + &["PA", "Ulian\u{f3}polis", "1508126"], + &["PA", "Uruar\u{e1}", "1508159"], + &["PA", "Vigia", "1508209"], + &["PA", "Viseu", "1508308"], + &["PA", "Vit\u{f3}ria do Xingu", "1508357"], + &["PA", "Xinguara", "1508407"], + &["PB", "\u{c1}gua Branca", "2500106"], + &["PB", "Aguiar", "2500205"], + &["PB", "Alagoa Grande", "2500304"], + &["PB", "Alagoa Nova", "2500403"], + &["PB", "Alagoinha", "2500502"], + &["PB", "Alcantil", "2500536"], + &["PB", "Algod\u{e3}o de Janda\u{ed}ra", "2500577"], + &["PB", "Alhandra", "2500601"], + &["PB", "Amparo", "2500734"], + &["PB", "Aparecida", "2500775"], + &["PB", "Ara\u{e7}agi", "2500809"], + &["PB", "Arara", "2500908"], + &["PB", "Araruna", "2501005"], + &["PB", "Areia", "2501104"], + &["PB", "Areia de Bara\u{fa}nas", "2501153"], + &["PB", "Areial", "2501203"], + &["PB", "Aroeiras", "2501302"], + &["PB", "Assun\u{e7}\u{e3}o", "2501351"], + &["PB", "Ba\u{ed}a da Trai\u{e7}\u{e3}o", "2501401"], + &["PB", "Bananeiras", "2501500"], + &["PB", "Bara\u{fa}na", "2501534"], + &["PB", "Barra de Santa Rosa", "2501609"], + &["PB", "Barra de Santana", "2501575"], + &["PB", "Barra de S\u{e3}o Miguel", "2501708"], + &["PB", "Bayeux", "2501807"], + &["PB", "Bel\u{e9}m", "2501906"], + &["PB", "Bel\u{e9}m do Brejo do Cruz", "2502003"], + &["PB", "Bernardino Batista", "2502052"], + &["PB", "Boa Ventura", "2502102"], + &["PB", "Boa Vista", "2502151"], + &["PB", "Bom Jesus", "2502201"], + &["PB", "Bom Sucesso", "2502300"], + &["PB", "Bonito de Santa F\u{e9}", "2502409"], + &["PB", "Boqueir\u{e3}o", "2502508"], + &["PB", "Borborema", "2502706"], + &["PB", "Brejo do Cruz", "2502805"], + &["PB", "Brejo dos Santos", "2502904"], + &["PB", "Caapor\u{e3}", "2503001"], + &["PB", "Cabaceiras", "2503100"], + &["PB", "Cabedelo", "2503209"], + &["PB", "Cachoeira dos \u{cd}ndios", "2503308"], + &["PB", "Cacimba de Areia", "2503407"], + &["PB", "Cacimba de Dentro", "2503506"], + &["PB", "Cacimbas", "2503555"], + &["PB", "Cai\u{e7}ara", "2503605"], + &["PB", "Cajazeiras", "2503704"], + &["PB", "Cajazeirinhas", "2503753"], + &["PB", "Caldas Brand\u{e3}o", "2503803"], + &["PB", "Camala\u{fa}", "2503902"], + &["PB", "Campina Grande", "2504009"], + &["PB", "Capim", "2504033"], + &["PB", "Cara\u{fa}bas", "2504074"], + &["PB", "Carrapateira", "2504108"], + &["PB", "Casserengue", "2504157"], + &["PB", "Catingueira", "2504207"], + &["PB", "Catol\u{e9} do Rocha", "2504306"], + &["PB", "Caturit\u{e9}", "2504355"], + &["PB", "Concei\u{e7}\u{e3}o", "2504405"], + &["PB", "Condado", "2504504"], + &["PB", "Conde", "2504603"], + &["PB", "Congo", "2504702"], + &["PB", "Coremas", "2504801"], + &["PB", "Coxixola", "2504850"], + &["PB", "Cruz do Esp\u{ed}rito Santo", "2504900"], + &["PB", "Cubati", "2505006"], + &["PB", "Cuit\u{e9}", "2505105"], + &["PB", "Cuit\u{e9} de Mamanguape", "2505238"], + &["PB", "Cuitegi", "2505204"], + &["PB", "Curral de Cima", "2505279"], + &["PB", "Curral Velho", "2505303"], + &["PB", "Dami\u{e3}o", "2505352"], + &["PB", "Desterro", "2505402"], + &["PB", "Diamante", "2505600"], + &["PB", "Dona In\u{ea}s", "2505709"], + &["PB", "Duas Estradas", "2505808"], + &["PB", "Emas", "2505907"], + &["PB", "Esperan\u{e7}a", "2506004"], + &["PB", "Fagundes", "2506103"], + &["PB", "Frei Martinho", "2506202"], + &["PB", "Gado Bravo", "2506251"], + &["PB", "Guarabira", "2506301"], + &["PB", "Gurinh\u{e9}m", "2506400"], + &["PB", "Gurj\u{e3}o", "2506509"], + &["PB", "Ibiara", "2506608"], + &["PB", "Igaracy", "2502607"], + &["PB", "Imaculada", "2506707"], + &["PB", "Ing\u{e1}", "2506806"], + &["PB", "Itabaiana", "2506905"], + &["PB", "Itaporanga", "2507002"], + &["PB", "Itapororoca", "2507101"], + &["PB", "Itatuba", "2507200"], + &["PB", "Jacara\u{fa}", "2507309"], + &["PB", "Jeric\u{f3}", "2507408"], + &["PB", "Jo\u{e3}o Pessoa", "2507507"], + &["PB", "Joca Claudino", "2513653"], + &["PB", "Juarez T\u{e1}vora", "2507606"], + &["PB", "Juazeirinho", "2507705"], + &["PB", "Junco do Serid\u{f3}", "2507804"], + &["PB", "Juripiranga", "2507903"], + &["PB", "Juru", "2508000"], + &["PB", "Lagoa", "2508109"], + &["PB", "Lagoa de Dentro", "2508208"], + &["PB", "Lagoa Seca", "2508307"], + &["PB", "Lastro", "2508406"], + &["PB", "Livramento", "2508505"], + &["PB", "Logradouro", "2508554"], + &["PB", "Lucena", "2508604"], + &["PB", "M\u{e3}e d'\u{c1}gua", "2508703"], + &["PB", "Malta", "2508802"], + &["PB", "Mamanguape", "2508901"], + &["PB", "Mana\u{ed}ra", "2509008"], + &["PB", "Marca\u{e7}\u{e3}o", "2509057"], + &["PB", "Mari", "2509107"], + &["PB", "Mariz\u{f3}polis", "2509156"], + &["PB", "Massaranduba", "2509206"], + &["PB", "Mataraca", "2509305"], + &["PB", "Matinhas", "2509339"], + &["PB", "Mato Grosso", "2509370"], + &["PB", "Matur\u{e9}ia", "2509396"], + &["PB", "Mogeiro", "2509404"], + &["PB", "Montadas", "2509503"], + &["PB", "Monte Horebe", "2509602"], + &["PB", "Monteiro", "2509701"], + &["PB", "Mulungu", "2509800"], + &["PB", "Natuba", "2509909"], + &["PB", "Nazarezinho", "2510006"], + &["PB", "Nova Floresta", "2510105"], + &["PB", "Nova Olinda", "2510204"], + &["PB", "Nova Palmeira", "2510303"], + &["PB", "Olho d'\u{c1}gua", "2510402"], + &["PB", "Olivedos", "2510501"], + &["PB", "Ouro Velho", "2510600"], + &["PB", "Parari", "2510659"], + &["PB", "Passagem", "2510709"], + &["PB", "Patos", "2510808"], + &["PB", "Paulista", "2510907"], + &["PB", "Pedra Branca", "2511004"], + &["PB", "Pedra Lavrada", "2511103"], + &["PB", "Pedras de Fogo", "2511202"], + &["PB", "Pedro R\u{e9}gis", "2512721"], + &["PB", "Pianc\u{f3}", "2511301"], + &["PB", "Picu\u{ed}", "2511400"], + &["PB", "Pilar", "2511509"], + &["PB", "Pil\u{f5}es", "2511608"], + &["PB", "Pil\u{f5}ezinhos", "2511707"], + &["PB", "Pirpirituba", "2511806"], + &["PB", "Pitimbu", "2511905"], + &["PB", "Pocinhos", "2512002"], + &["PB", "Po\u{e7}o Dantas", "2512036"], + &["PB", "Po\u{e7}o de Jos\u{e9} de Moura", "2512077"], + &["PB", "Pombal", "2512101"], + &["PB", "Prata", "2512200"], + &["PB", "Princesa Isabel", "2512309"], + &["PB", "Puxinan\u{e3}", "2512408"], + &["PB", "Queimadas", "2512507"], + &["PB", "Quixaba", "2512606"], + &["PB", "Rem\u{ed}gio", "2512705"], + &["PB", "Riach\u{e3}o", "2512747"], + &["PB", "Riach\u{e3}o do Bacamarte", "2512754"], + &["PB", "Riach\u{e3}o do Po\u{e7}o", "2512762"], + &["PB", "Riacho de Santo Ant\u{f4}nio", "2512788"], + &["PB", "Riacho dos Cavalos", "2512804"], + &["PB", "Rio Tinto", "2512903"], + &["PB", "Salgadinho", "2513000"], + &["PB", "Salgado de S\u{e3}o F\u{e9}lix", "2513109"], + &["PB", "Santa Cec\u{ed}lia", "2513158"], + &["PB", "Santa Cruz", "2513208"], + &["PB", "Santa Helena", "2513307"], + &["PB", "Santa In\u{ea}s", "2513356"], + &["PB", "Santa Luzia", "2513406"], + &["PB", "Santa Rita", "2513703"], + &["PB", "Santa Teresinha", "2513802"], + &["PB", "Santana de Mangueira", "2513505"], + &["PB", "Santana dos Garrotes", "2513604"], + &["PB", "Santo Andr\u{e9}", "2513851"], + &["PB", "S\u{e3}o Bentinho", "2513927"], + &["PB", "S\u{e3}o Bento", "2513901"], + &["PB", "S\u{e3}o Domingos", "2513968"], + &["PB", "S\u{e3}o Domingos do Cariri", "2513943"], + &["PB", "S\u{e3}o Francisco", "2513984"], + &["PB", "S\u{e3}o Jo\u{e3}o do Cariri", "2514008"], + &["PB", "S\u{e3}o Jo\u{e3}o do Rio do Peixe", "2500700"], + &["PB", "S\u{e3}o Jo\u{e3}o do Tigre", "2514107"], + &["PB", "S\u{e3}o Jos\u{e9} da Lagoa Tapada", "2514206"], + &["PB", "S\u{e3}o Jos\u{e9} de Caiana", "2514305"], + &["PB", "S\u{e3}o Jos\u{e9} de Espinharas", "2514404"], + &["PB", "S\u{e3}o Jos\u{e9} de Piranhas", "2514503"], + &["PB", "S\u{e3}o Jos\u{e9} de Princesa", "2514552"], + &["PB", "S\u{e3}o Jos\u{e9} do Bonfim", "2514602"], + &["PB", "S\u{e3}o Jos\u{e9} do Brejo do Cruz", "2514651"], + &["PB", "S\u{e3}o Jos\u{e9} do Sabugi", "2514701"], + &["PB", "S\u{e3}o Jos\u{e9} dos Cordeiros", "2514800"], + &["PB", "S\u{e3}o Jos\u{e9} dos Ramos", "2514453"], + &["PB", "S\u{e3}o Mamede", "2514909"], + &["PB", "S\u{e3}o Miguel de Taipu", "2515005"], + &["PB", "S\u{e3}o Sebasti\u{e3}o de Lagoa de Ro\u{e7}a", "2515104"], + &["PB", "S\u{e3}o Sebasti\u{e3}o do Umbuzeiro", "2515203"], + &["PB", "S\u{e3}o Vicente do Serid\u{f3}", "2515401"], + &["PB", "Sap\u{e9}", "2515302"], + &["PB", "Serra Branca", "2515500"], + &["PB", "Serra da Raiz", "2515609"], + &["PB", "Serra Grande", "2515708"], + &["PB", "Serra Redonda", "2515807"], + &["PB", "Serraria", "2515906"], + &["PB", "Sert\u{e3}ozinho", "2515930"], + &["PB", "Sobrado", "2515971"], + &["PB", "Sol\u{e2}nea", "2516003"], + &["PB", "Soledade", "2516102"], + &["PB", "Soss\u{ea}go", "2516151"], + &["PB", "Sousa", "2516201"], + &["PB", "Sum\u{e9}", "2516300"], + &["PB", "Tacima", "2516409"], + &["PB", "Tapero\u{e1}", "2516508"], + &["PB", "Tavares", "2516607"], + &["PB", "Teixeira", "2516706"], + &["PB", "Ten\u{f3}rio", "2516755"], + &["PB", "Triunfo", "2516805"], + &["PB", "Uira\u{fa}na", "2516904"], + &["PB", "Umbuzeiro", "2517001"], + &["PB", "V\u{e1}rzea", "2517100"], + &["PB", "Vieir\u{f3}polis", "2517209"], + &["PB", "Vista Serrana", "2505501"], + &["PB", "Zabel\u{ea}", "2517407"], + &["PR", "Abati\u{e1}", "4100103"], + &["PR", "Adrian\u{f3}polis", "4100202"], + &["PR", "Agudos do Sul", "4100301"], + &["PR", "Almirante Tamandar\u{e9}", "4100400"], + &["PR", "Altamira do Paran\u{e1}", "4100459"], + &["PR", "Alto Para\u{ed}so", "4128625"], + &["PR", "Alto Paran\u{e1}", "4100608"], + &["PR", "Alto Piquiri", "4100707"], + &["PR", "Alt\u{f4}nia", "4100509"], + &["PR", "Alvorada do Sul", "4100806"], + &["PR", "Amapor\u{e3}", "4100905"], + &["PR", "Amp\u{e9}re", "4101002"], + &["PR", "Anahy", "4101051"], + &["PR", "Andir\u{e1}", "4101101"], + &["PR", "\u{c2}ngulo", "4101150"], + &["PR", "Antonina", "4101200"], + &["PR", "Ant\u{f4}nio Olinto", "4101309"], + &["PR", "Apucarana", "4101408"], + &["PR", "Arapongas", "4101507"], + &["PR", "Arapoti", "4101606"], + &["PR", "Arapu\u{e3}", "4101655"], + &["PR", "Araruna", "4101705"], + &["PR", "Arauc\u{e1}ria", "4101804"], + &["PR", "Ariranha do Iva\u{ed}", "4101853"], + &["PR", "Assa\u{ed}", "4101903"], + &["PR", "Assis Chateaubriand", "4102000"], + &["PR", "Astorga", "4102109"], + &["PR", "Atalaia", "4102208"], + &["PR", "Balsa Nova", "4102307"], + &["PR", "Bandeirantes", "4102406"], + &["PR", "Barbosa Ferraz", "4102505"], + &["PR", "Barra do Jacar\u{e9}", "4102703"], + &["PR", "Barrac\u{e3}o", "4102604"], + &["PR", "Bela Vista da Caroba", "4102752"], + &["PR", "Bela Vista do Para\u{ed}so", "4102802"], + &["PR", "Bituruna", "4102901"], + &["PR", "Boa Esperan\u{e7}a", "4103008"], + &["PR", "Boa Esperan\u{e7}a do Igua\u{e7}u", "4103024"], + &["PR", "Boa Ventura de S\u{e3}o Roque", "4103040"], + &["PR", "Boa Vista da Aparecida", "4103057"], + &["PR", "Bocai\u{fa}va do Sul", "4103107"], + &["PR", "Bom Jesus do Sul", "4103156"], + &["PR", "Bom Sucesso", "4103206"], + &["PR", "Bom Sucesso do Sul", "4103222"], + &["PR", "Borraz\u{f3}polis", "4103305"], + &["PR", "Braganey", "4103354"], + &["PR", "Brasil\u{e2}ndia do Sul", "4103370"], + &["PR", "Cafeara", "4103404"], + &["PR", "Cafel\u{e2}ndia", "4103453"], + &["PR", "Cafezal do Sul", "4103479"], + &["PR", "Calif\u{f3}rnia", "4103503"], + &["PR", "Cambar\u{e1}", "4103602"], + &["PR", "Camb\u{e9}", "4103701"], + &["PR", "Cambira", "4103800"], + &["PR", "Campina da Lagoa", "4103909"], + &["PR", "Campina do Sim\u{e3}o", "4103958"], + &["PR", "Campina Grande do Sul", "4104006"], + &["PR", "Campo Bonito", "4104055"], + &["PR", "Campo do Tenente", "4104105"], + &["PR", "Campo Largo", "4104204"], + &["PR", "Campo Magro", "4104253"], + &["PR", "Campo Mour\u{e3}o", "4104303"], + &["PR", "C\u{e2}ndido de Abreu", "4104402"], + &["PR", "Cand\u{f3}i", "4104428"], + &["PR", "Cantagalo", "4104451"], + &["PR", "Capanema", "4104501"], + &["PR", "Capit\u{e3}o Le\u{f4}nidas Marques", "4104600"], + &["PR", "Carambe\u{ed}", "4104659"], + &["PR", "Carl\u{f3}polis", "4104709"], + &["PR", "Cascavel", "4104808"], + &["PR", "Castro", "4104907"], + &["PR", "Catanduvas", "4105003"], + &["PR", "Centen\u{e1}rio do Sul", "4105102"], + &["PR", "Cerro Azul", "4105201"], + &["PR", "C\u{e9}u Azul", "4105300"], + &["PR", "Chopinzinho", "4105409"], + &["PR", "Cianorte", "4105508"], + &["PR", "Cidade Ga\u{fa}cha", "4105607"], + &["PR", "Clevel\u{e2}ndia", "4105706"], + &["PR", "Colombo", "4105805"], + &["PR", "Colorado", "4105904"], + &["PR", "Congonhinhas", "4106001"], + &["PR", "Conselheiro Mairinck", "4106100"], + &["PR", "Contenda", "4106209"], + &["PR", "Corb\u{e9}lia", "4106308"], + &["PR", "Corn\u{e9}lio Proc\u{f3}pio", "4106407"], + &["PR", "Coronel Domingos Soares", "4106456"], + &["PR", "Coronel Vivida", "4106506"], + &["PR", "Corumbata\u{ed} do Sul", "4106555"], + &["PR", "Cruz Machado", "4106803"], + &["PR", "Cruzeiro do Igua\u{e7}u", "4106571"], + &["PR", "Cruzeiro do Oeste", "4106605"], + &["PR", "Cruzeiro do Sul", "4106704"], + &["PR", "Cruzmaltina", "4106852"], + &["PR", "Curitiba", "4106902"], + &["PR", "Curi\u{fa}va", "4107009"], + &["PR", "Diamante D'Oeste", "4107157"], + &["PR", "Diamante do Norte", "4107108"], + &["PR", "Diamante do Sul", "4107124"], + &["PR", "Dois Vizinhos", "4107207"], + &["PR", "Douradina", "4107256"], + &["PR", "Doutor Camargo", "4107306"], + &["PR", "Doutor Ulysses", "4128633"], + &["PR", "En\u{e9}as Marques", "4107405"], + &["PR", "Engenheiro Beltr\u{e3}o", "4107504"], + &["PR", "Entre Rios do Oeste", "4107538"], + &["PR", "Esperan\u{e7}a Nova", "4107520"], + &["PR", "Espig\u{e3}o Alto do Igua\u{e7}u", "4107546"], + &["PR", "Farol", "4107553"], + &["PR", "Faxinal", "4107603"], + &["PR", "Fazenda Rio Grande", "4107652"], + &["PR", "F\u{ea}nix", "4107702"], + &["PR", "Fernandes Pinheiro", "4107736"], + &["PR", "Figueira", "4107751"], + &["PR", "Flor da Serra do Sul", "4107850"], + &["PR", "Flora\u{ed}", "4107801"], + &["PR", "Floresta", "4107900"], + &["PR", "Florest\u{f3}polis", "4108007"], + &["PR", "Fl\u{f3}rida", "4108106"], + &["PR", "Formosa do Oeste", "4108205"], + &["PR", "Foz do Igua\u{e7}u", "4108304"], + &["PR", "Foz do Jord\u{e3}o", "4108452"], + &["PR", "Francisco Alves", "4108320"], + &["PR", "Francisco Beltr\u{e3}o", "4108403"], + &["PR", "General Carneiro", "4108502"], + &["PR", "Godoy Moreira", "4108551"], + &["PR", "Goioer\u{ea}", "4108601"], + &["PR", "Goioxim", "4108650"], + &["PR", "Grandes Rios", "4108700"], + &["PR", "Gua\u{ed}ra", "4108809"], + &["PR", "Guaira\u{e7}\u{e1}", "4108908"], + &["PR", "Guamiranga", "4108957"], + &["PR", "Guapirama", "4109005"], + &["PR", "Guaporema", "4109104"], + &["PR", "Guaraci", "4109203"], + &["PR", "Guarania\u{e7}u", "4109302"], + &["PR", "Guarapuava", "4109401"], + &["PR", "Guaraque\u{e7}aba", "4109500"], + &["PR", "Guaratuba", "4109609"], + &["PR", "Hon\u{f3}rio Serpa", "4109658"], + &["PR", "Ibaiti", "4109708"], + &["PR", "Ibema", "4109757"], + &["PR", "Ibipor\u{e3}", "4109807"], + &["PR", "Icara\u{ed}ma", "4109906"], + &["PR", "Iguara\u{e7}u", "4110003"], + &["PR", "Iguatu", "4110052"], + &["PR", "Imba\u{fa}", "4110078"], + &["PR", "Imbituva", "4110102"], + &["PR", "In\u{e1}cio Martins", "4110201"], + &["PR", "Inaj\u{e1}", "4110300"], + &["PR", "Indian\u{f3}polis", "4110409"], + &["PR", "Ipiranga", "4110508"], + &["PR", "Ipor\u{e3}", "4110607"], + &["PR", "Iracema do Oeste", "4110656"], + &["PR", "Irati", "4110706"], + &["PR", "Iretama", "4110805"], + &["PR", "Itaguaj\u{e9}", "4110904"], + &["PR", "Itaipul\u{e2}ndia", "4110953"], + &["PR", "Itambarac\u{e1}", "4111001"], + &["PR", "Itamb\u{e9}", "4111100"], + &["PR", "Itapejara d'Oeste", "4111209"], + &["PR", "Itaperu\u{e7}u", "4111258"], + &["PR", "Ita\u{fa}na do Sul", "4111308"], + &["PR", "Iva\u{ed}", "4111407"], + &["PR", "Ivaipor\u{e3}", "4111506"], + &["PR", "Ivat\u{e9}", "4111555"], + &["PR", "Ivatuba", "4111605"], + &["PR", "Jaboti", "4111704"], + &["PR", "Jacarezinho", "4111803"], + &["PR", "Jaguapit\u{e3}", "4111902"], + &["PR", "Jaguaria\u{ed}va", "4112009"], + &["PR", "Jandaia do Sul", "4112108"], + &["PR", "Jani\u{f3}polis", "4112207"], + &["PR", "Japira", "4112306"], + &["PR", "Japur\u{e1}", "4112405"], + &["PR", "Jardim Alegre", "4112504"], + &["PR", "Jardim Olinda", "4112603"], + &["PR", "Jataizinho", "4112702"], + &["PR", "Jesu\u{ed}tas", "4112751"], + &["PR", "Joaquim T\u{e1}vora", "4112801"], + &["PR", "Jundia\u{ed} do Sul", "4112900"], + &["PR", "Juranda", "4112959"], + &["PR", "Jussara", "4113007"], + &["PR", "Kalor\u{e9}", "4113106"], + &["PR", "Lapa", "4113205"], + &["PR", "Laranjal", "4113254"], + &["PR", "Laranjeiras do Sul", "4113304"], + &["PR", "Le\u{f3}polis", "4113403"], + &["PR", "Lidian\u{f3}polis", "4113429"], + &["PR", "Lindoeste", "4113452"], + &["PR", "Loanda", "4113502"], + &["PR", "Lobato", "4113601"], + &["PR", "Londrina", "4113700"], + &["PR", "Luiziana", "4113734"], + &["PR", "Lunardelli", "4113759"], + &["PR", "Lupion\u{f3}polis", "4113809"], + &["PR", "Mallet", "4113908"], + &["PR", "Mambor\u{ea}", "4114005"], + &["PR", "Mandagua\u{e7}u", "4114104"], + &["PR", "Mandaguari", "4114203"], + &["PR", "Mandirituba", "4114302"], + &["PR", "Manfrin\u{f3}polis", "4114351"], + &["PR", "Mangueirinha", "4114401"], + &["PR", "Manoel Ribas", "4114500"], + &["PR", "Marechal C\u{e2}ndido Rondon", "4114609"], + &["PR", "Maria Helena", "4114708"], + &["PR", "Marialva", "4114807"], + &["PR", "Maril\u{e2}ndia do Sul", "4114906"], + &["PR", "Marilena", "4115002"], + &["PR", "Mariluz", "4115101"], + &["PR", "Maring\u{e1}", "4115200"], + &["PR", "Mari\u{f3}polis", "4115309"], + &["PR", "Marip\u{e1}", "4115358"], + &["PR", "Marmeleiro", "4115408"], + &["PR", "Marquinho", "4115457"], + &["PR", "Marumbi", "4115507"], + &["PR", "Matel\u{e2}ndia", "4115606"], + &["PR", "Matinhos", "4115705"], + &["PR", "Mato Rico", "4115739"], + &["PR", "Mau\u{e1} da Serra", "4115754"], + &["PR", "Medianeira", "4115804"], + &["PR", "Mercedes", "4115853"], + &["PR", "Mirador", "4115903"], + &["PR", "Miraselva", "4116000"], + &["PR", "Missal", "4116059"], + &["PR", "Moreira Sales", "4116109"], + &["PR", "Morretes", "4116208"], + &["PR", "Munhoz de Melo", "4116307"], + &["PR", "Nossa Senhora das Gra\u{e7}as", "4116406"], + &["PR", "Nova Alian\u{e7}a do Iva\u{ed}", "4116505"], + &["PR", "Nova Am\u{e9}rica da Colina", "4116604"], + &["PR", "Nova Aurora", "4116703"], + &["PR", "Nova Cantu", "4116802"], + &["PR", "Nova Esperan\u{e7}a", "4116901"], + &["PR", "Nova Esperan\u{e7}a do Sudoeste", "4116950"], + &["PR", "Nova F\u{e1}tima", "4117008"], + &["PR", "Nova Laranjeiras", "4117057"], + &["PR", "Nova Londrina", "4117107"], + &["PR", "Nova Ol\u{ed}mpia", "4117206"], + &["PR", "Nova Prata do Igua\u{e7}u", "4117255"], + &["PR", "Nova Santa B\u{e1}rbara", "4117214"], + &["PR", "Nova Santa Rosa", "4117222"], + &["PR", "Nova Tebas", "4117271"], + &["PR", "Novo Itacolomi", "4117297"], + &["PR", "Ortigueira", "4117305"], + &["PR", "Ourizona", "4117404"], + &["PR", "Ouro Verde do Oeste", "4117453"], + &["PR", "Pai\u{e7}andu", "4117503"], + &["PR", "Palmas", "4117602"], + &["PR", "Palmeira", "4117701"], + &["PR", "Palmital", "4117800"], + &["PR", "Palotina", "4117909"], + &["PR", "Para\u{ed}so do Norte", "4118006"], + &["PR", "Paranacity", "4118105"], + &["PR", "Paranagu\u{e1}", "4118204"], + &["PR", "Paranapoema", "4118303"], + &["PR", "Paranava\u{ed}", "4118402"], + &["PR", "Pato Bragado", "4118451"], + &["PR", "Pato Branco", "4118501"], + &["PR", "Paula Freitas", "4118600"], + &["PR", "Paulo Frontin", "4118709"], + &["PR", "Peabiru", "4118808"], + &["PR", "Perobal", "4118857"], + &["PR", "P\u{e9}rola", "4118907"], + &["PR", "P\u{e9}rola d'Oeste", "4119004"], + &["PR", "Pi\u{ea}n", "4119103"], + &["PR", "Pinhais", "4119152"], + &["PR", "Pinhal de S\u{e3}o Bento", "4119251"], + &["PR", "Pinhal\u{e3}o", "4119202"], + &["PR", "Pinh\u{e3}o", "4119301"], + &["PR", "Pira\u{ed} do Sul", "4119400"], + &["PR", "Piraquara", "4119509"], + &["PR", "Pitanga", "4119608"], + &["PR", "Pitangueiras", "4119657"], + &["PR", "Planaltina do Paran\u{e1}", "4119707"], + &["PR", "Planalto", "4119806"], + &["PR", "Ponta Grossa", "4119905"], + &["PR", "Pontal do Paran\u{e1}", "4119954"], + &["PR", "Porecatu", "4120002"], + &["PR", "Porto Amazonas", "4120101"], + &["PR", "Porto Barreiro", "4120150"], + &["PR", "Porto Rico", "4120200"], + &["PR", "Porto Vit\u{f3}ria", "4120309"], + &["PR", "Prado Ferreira", "4120333"], + &["PR", "Pranchita", "4120358"], + &["PR", "Presidente Castelo Branco", "4120408"], + &["PR", "Primeiro de Maio", "4120507"], + &["PR", "Prudent\u{f3}polis", "4120606"], + &["PR", "Quarto Centen\u{e1}rio", "4120655"], + &["PR", "Quatigu\u{e1}", "4120705"], + &["PR", "Quatro Barras", "4120804"], + &["PR", "Quatro Pontes", "4120853"], + &["PR", "Quedas do Igua\u{e7}u", "4120903"], + &["PR", "Quer\u{ea}ncia do Norte", "4121000"], + &["PR", "Quinta do Sol", "4121109"], + &["PR", "Quitandinha", "4121208"], + &["PR", "Ramil\u{e2}ndia", "4121257"], + &["PR", "Rancho Alegre", "4121307"], + &["PR", "Rancho Alegre D'Oeste", "4121356"], + &["PR", "Realeza", "4121406"], + &["PR", "Rebou\u{e7}as", "4121505"], + &["PR", "Renascen\u{e7}a", "4121604"], + &["PR", "Reserva", "4121703"], + &["PR", "Reserva do Igua\u{e7}u", "4121752"], + &["PR", "Ribeir\u{e3}o Claro", "4121802"], + &["PR", "Ribeir\u{e3}o do Pinhal", "4121901"], + &["PR", "Rio Azul", "4122008"], + &["PR", "Rio Bom", "4122107"], + &["PR", "Rio Bonito do Igua\u{e7}u", "4122156"], + &["PR", "Rio Branco do Iva\u{ed}", "4122172"], + &["PR", "Rio Branco do Sul", "4122206"], + &["PR", "Rio Negro", "4122305"], + &["PR", "Rol\u{e2}ndia", "4122404"], + &["PR", "Roncador", "4122503"], + &["PR", "Rondon", "4122602"], + &["PR", "Ros\u{e1}rio do Iva\u{ed}", "4122651"], + &["PR", "Sab\u{e1}udia", "4122701"], + &["PR", "Salgado Filho", "4122800"], + &["PR", "Salto do Itarar\u{e9}", "4122909"], + &["PR", "Salto do Lontra", "4123006"], + &["PR", "Santa Am\u{e9}lia", "4123105"], + &["PR", "Santa Cec\u{ed}lia do Pav\u{e3}o", "4123204"], + &["PR", "Santa Cruz de Monte Castelo", "4123303"], + &["PR", "Santa F\u{e9}", "4123402"], + &["PR", "Santa Helena", "4123501"], + &["PR", "Santa In\u{ea}s", "4123600"], + &["PR", "Santa Isabel do Iva\u{ed}", "4123709"], + &["PR", "Santa Izabel do Oeste", "4123808"], + &["PR", "Santa L\u{fa}cia", "4123824"], + &["PR", "Santa Maria do Oeste", "4123857"], + &["PR", "Santa Mariana", "4123907"], + &["PR", "Santa M\u{f4}nica", "4123956"], + &["PR", "Santa Tereza do Oeste", "4124020"], + &["PR", "Santa Terezinha de Itaipu", "4124053"], + &["PR", "Santana do Itarar\u{e9}", "4124004"], + &["PR", "Santo Ant\u{f4}nio da Platina", "4124103"], + &["PR", "Santo Ant\u{f4}nio do Caiu\u{e1}", "4124202"], + &["PR", "Santo Ant\u{f4}nio do Para\u{ed}so", "4124301"], + &["PR", "Santo Ant\u{f4}nio do Sudoeste", "4124400"], + &["PR", "Santo In\u{e1}cio", "4124509"], + &["PR", "S\u{e3}o Carlos do Iva\u{ed}", "4124608"], + &["PR", "S\u{e3}o Jer\u{f4}nimo da Serra", "4124707"], + &["PR", "S\u{e3}o Jo\u{e3}o", "4124806"], + &["PR", "S\u{e3}o Jo\u{e3}o do Caiu\u{e1}", "4124905"], + &["PR", "S\u{e3}o Jo\u{e3}o do Iva\u{ed}", "4125001"], + &["PR", "S\u{e3}o Jo\u{e3}o do Triunfo", "4125100"], + &["PR", "S\u{e3}o Jorge d'Oeste", "4125209"], + &["PR", "S\u{e3}o Jorge do Iva\u{ed}", "4125308"], + &["PR", "S\u{e3}o Jorge do Patroc\u{ed}nio", "4125357"], + &["PR", "S\u{e3}o Jos\u{e9} da Boa Vista", "4125407"], + &["PR", "S\u{e3}o Jos\u{e9} das Palmeiras", "4125456"], + &["PR", "S\u{e3}o Jos\u{e9} dos Pinhais", "4125506"], + &["PR", "S\u{e3}o Manoel do Paran\u{e1}", "4125555"], + &["PR", "S\u{e3}o Mateus do Sul", "4125605"], + &["PR", "S\u{e3}o Miguel do Igua\u{e7}u", "4125704"], + &["PR", "S\u{e3}o Pedro do Igua\u{e7}u", "4125753"], + &["PR", "S\u{e3}o Pedro do Iva\u{ed}", "4125803"], + &["PR", "S\u{e3}o Pedro do Paran\u{e1}", "4125902"], + &["PR", "S\u{e3}o Sebasti\u{e3}o da Amoreira", "4126009"], + &["PR", "S\u{e3}o Tom\u{e9}", "4126108"], + &["PR", "Sapopema", "4126207"], + &["PR", "Sarandi", "4126256"], + &["PR", "Saudade do Igua\u{e7}u", "4126272"], + &["PR", "Seng\u{e9}s", "4126306"], + &["PR", "Serran\u{f3}polis do Igua\u{e7}u", "4126355"], + &["PR", "Sertaneja", "4126405"], + &["PR", "Sertan\u{f3}polis", "4126504"], + &["PR", "Siqueira Campos", "4126603"], + &["PR", "Sulina", "4126652"], + &["PR", "Tamarana", "4126678"], + &["PR", "Tamboara", "4126702"], + &["PR", "Tapejara", "4126801"], + &["PR", "Tapira", "4126900"], + &["PR", "Teixeira Soares", "4127007"], + &["PR", "Tel\u{ea}maco Borba", "4127106"], + &["PR", "Terra Boa", "4127205"], + &["PR", "Terra Rica", "4127304"], + &["PR", "Terra Roxa", "4127403"], + &["PR", "Tibagi", "4127502"], + &["PR", "Tijucas do Sul", "4127601"], + &["PR", "Toledo", "4127700"], + &["PR", "Tomazina", "4127809"], + &["PR", "Tr\u{ea}s Barras do Paran\u{e1}", "4127858"], + &["PR", "Tunas do Paran\u{e1}", "4127882"], + &["PR", "Tuneiras do Oeste", "4127908"], + &["PR", "Tup\u{e3}ssi", "4127957"], + &["PR", "Turvo", "4127965"], + &["PR", "Ubirat\u{e3}", "4128005"], + &["PR", "Umuarama", "4128104"], + &["PR", "Uni\u{e3}o da Vit\u{f3}ria", "4128203"], + &["PR", "Uniflor", "4128302"], + &["PR", "Ura\u{ed}", "4128401"], + &["PR", "Ventania", "4128534"], + &["PR", "Vera Cruz do Oeste", "4128559"], + &["PR", "Ver\u{ea}", "4128609"], + &["PR", "Virmond", "4128658"], + &["PR", "Vitorino", "4128708"], + &["PR", "Wenceslau Braz", "4128500"], + &["PR", "Xambr\u{ea}", "4128807"], + &["PE", "Abreu e Lima", "2600054"], + &["PE", "Afogados da Ingazeira", "2600104"], + &["PE", "Afr\u{e2}nio", "2600203"], + &["PE", "Agrestina", "2600302"], + &["PE", "\u{c1}gua Preta", "2600401"], + &["PE", "\u{c1}guas Belas", "2600500"], + &["PE", "Alagoinha", "2600609"], + &["PE", "Alian\u{e7}a", "2600708"], + &["PE", "Altinho", "2600807"], + &["PE", "Amaraji", "2600906"], + &["PE", "Angelim", "2601003"], + &["PE", "Ara\u{e7}oiaba", "2601052"], + &["PE", "Araripina", "2601102"], + &["PE", "Arcoverde", "2601201"], + &["PE", "Barra de Guabiraba", "2601300"], + &["PE", "Barreiros", "2601409"], + &["PE", "Bel\u{e9}m de Maria", "2601508"], + &["PE", "Bel\u{e9}m do S\u{e3}o Francisco", "2601607"], + &["PE", "Belo Jardim", "2601706"], + &["PE", "Bet\u{e2}nia", "2601805"], + &["PE", "Bezerros", "2601904"], + &["PE", "Bodoc\u{f3}", "2602001"], + &["PE", "Bom Conselho", "2602100"], + &["PE", "Bom Jardim", "2602209"], + &["PE", "Bonito", "2602308"], + &["PE", "Brej\u{e3}o", "2602407"], + &["PE", "Brejinho", "2602506"], + &["PE", "Brejo da Madre de Deus", "2602605"], + &["PE", "Buenos Aires", "2602704"], + &["PE", "Bu\u{ed}que", "2602803"], + &["PE", "Cabo de Santo Agostinho", "2602902"], + &["PE", "Cabrob\u{f3}", "2603009"], + &["PE", "Cachoeirinha", "2603108"], + &["PE", "Caet\u{e9}s", "2603207"], + &["PE", "Cal\u{e7}ado", "2603306"], + &["PE", "Calumbi", "2603405"], + &["PE", "Camaragibe", "2603454"], + &["PE", "Camocim de S\u{e3}o F\u{e9}lix", "2603504"], + &["PE", "Camutanga", "2603603"], + &["PE", "Canhotinho", "2603702"], + &["PE", "Capoeiras", "2603801"], + &["PE", "Carna\u{ed}ba", "2603900"], + &["PE", "Carnaubeira da Penha", "2603926"], + &["PE", "Carpina", "2604007"], + &["PE", "Caruaru", "2604106"], + &["PE", "Casinhas", "2604155"], + &["PE", "Catende", "2604205"], + &["PE", "Cedro", "2604304"], + &["PE", "Ch\u{e3} de Alegria", "2604403"], + &["PE", "Ch\u{e3} Grande", "2604502"], + &["PE", "Condado", "2604601"], + &["PE", "Correntes", "2604700"], + &["PE", "Cort\u{ea}s", "2604809"], + &["PE", "Cumaru", "2604908"], + &["PE", "Cupira", "2605004"], + &["PE", "Cust\u{f3}dia", "2605103"], + &["PE", "Dormentes", "2605152"], + &["PE", "Escada", "2605202"], + &["PE", "Exu", "2605301"], + &["PE", "Feira Nova", "2605400"], + &["PE", "Fernando de Noronha", "2605459"], + &["PE", "Ferreiros", "2605509"], + &["PE", "Flores", "2605608"], + &["PE", "Floresta", "2605707"], + &["PE", "Frei Miguelinho", "2605806"], + &["PE", "Gameleira", "2605905"], + &["PE", "Garanhuns", "2606002"], + &["PE", "Gl\u{f3}ria do Goit\u{e1}", "2606101"], + &["PE", "Goiana", "2606200"], + &["PE", "Granito", "2606309"], + &["PE", "Gravat\u{e1}", "2606408"], + &["PE", "Iati", "2606507"], + &["PE", "Ibimirim", "2606606"], + &["PE", "Ibirajuba", "2606705"], + &["PE", "Igarassu", "2606804"], + &["PE", "Iguaracy", "2606903"], + &["PE", "Ilha de Itamarac\u{e1}", "2607604"], + &["PE", "Inaj\u{e1}", "2607000"], + &["PE", "Ingazeira", "2607109"], + &["PE", "Ipojuca", "2607208"], + &["PE", "Ipubi", "2607307"], + &["PE", "Itacuruba", "2607406"], + &["PE", "Ita\u{ed}ba", "2607505"], + &["PE", "Itamb\u{e9}", "2607653"], + &["PE", "Itapetim", "2607703"], + &["PE", "Itapissuma", "2607752"], + &["PE", "Itaquitinga", "2607802"], + &["PE", "Jaboat\u{e3}o dos Guararapes", "2607901"], + &["PE", "Jaqueira", "2607950"], + &["PE", "Jata\u{fa}ba", "2608008"], + &["PE", "Jatob\u{e1}", "2608057"], + &["PE", "Jo\u{e3}o Alfredo", "2608107"], + &["PE", "Joaquim Nabuco", "2608206"], + &["PE", "Jucati", "2608255"], + &["PE", "Jupi", "2608305"], + &["PE", "Jurema", "2608404"], + &["PE", "Lagoa de Itaenga", "2608503"], + &["PE", "Lagoa do Carro", "2608453"], + &["PE", "Lagoa do Ouro", "2608602"], + &["PE", "Lagoa dos Gatos", "2608701"], + &["PE", "Lagoa Grande", "2608750"], + &["PE", "Lajedo", "2608800"], + &["PE", "Limoeiro", "2608909"], + &["PE", "Macaparana", "2609006"], + &["PE", "Machados", "2609105"], + &["PE", "Manari", "2609154"], + &["PE", "Maraial", "2609204"], + &["PE", "Mirandiba", "2609303"], + &["PE", "Moreil\u{e2}ndia", "2614303"], + &["PE", "Moreno", "2609402"], + &["PE", "Nazar\u{e9} da Mata", "2609501"], + &["PE", "Olinda", "2609600"], + &["PE", "Orob\u{f3}", "2609709"], + &["PE", "Oroc\u{f3}", "2609808"], + &["PE", "Ouricuri", "2609907"], + &["PE", "Palmares", "2610004"], + &["PE", "Palmeirina", "2610103"], + &["PE", "Panelas", "2610202"], + &["PE", "Paranatama", "2610301"], + &["PE", "Parnamirim", "2610400"], + &["PE", "Passira", "2610509"], + &["PE", "Paudalho", "2610608"], + &["PE", "Paulista", "2610707"], + &["PE", "Pedra", "2610806"], + &["PE", "Pesqueira", "2610905"], + &["PE", "Petrol\u{e2}ndia", "2611002"], + &["PE", "Petrolina", "2611101"], + &["PE", "Po\u{e7}\u{e3}o", "2611200"], + &["PE", "Pombos", "2611309"], + &["PE", "Primavera", "2611408"], + &["PE", "Quipap\u{e1}", "2611507"], + &["PE", "Quixaba", "2611533"], + &["PE", "Recife", "2611606"], + &["PE", "Riacho das Almas", "2611705"], + &["PE", "Ribeir\u{e3}o", "2611804"], + &["PE", "Rio Formoso", "2611903"], + &["PE", "Sair\u{e9}", "2612000"], + &["PE", "Salgadinho", "2612109"], + &["PE", "Salgueiro", "2612208"], + &["PE", "Salo\u{e1}", "2612307"], + &["PE", "Sanhar\u{f3}", "2612406"], + &["PE", "Santa Cruz", "2612455"], + &["PE", "Santa Cruz da Baixa Verde", "2612471"], + &["PE", "Santa Cruz do Capibaribe", "2612505"], + &["PE", "Santa Filomena", "2612554"], + &["PE", "Santa Maria da Boa Vista", "2612604"], + &["PE", "Santa Maria do Cambuc\u{e1}", "2612703"], + &["PE", "Santa Terezinha", "2612802"], + &["PE", "S\u{e3}o Benedito do Sul", "2612901"], + &["PE", "S\u{e3}o Bento do Una", "2613008"], + &["PE", "S\u{e3}o Caitano", "2613107"], + &["PE", "S\u{e3}o Jo\u{e3}o", "2613206"], + &["PE", "S\u{e3}o Joaquim do Monte", "2613305"], + &["PE", "S\u{e3}o Jos\u{e9} da Coroa Grande", "2613404"], + &["PE", "S\u{e3}o Jos\u{e9} do Belmonte", "2613503"], + &["PE", "S\u{e3}o Jos\u{e9} do Egito", "2613602"], + &["PE", "S\u{e3}o Louren\u{e7}o da Mata", "2613701"], + &["PE", "S\u{e3}o Vicente F\u{e9}rrer", "2613800"], + &["PE", "Serra Talhada", "2613909"], + &["PE", "Serrita", "2614006"], + &["PE", "Sert\u{e2}nia", "2614105"], + &["PE", "Sirinha\u{e9}m", "2614204"], + &["PE", "Solid\u{e3}o", "2614402"], + &["PE", "Surubim", "2614501"], + &["PE", "Tabira", "2614600"], + &["PE", "Tacaimb\u{f3}", "2614709"], + &["PE", "Tacaratu", "2614808"], + &["PE", "Tamandar\u{e9}", "2614857"], + &["PE", "Taquaritinga do Norte", "2615003"], + &["PE", "Terezinha", "2615102"], + &["PE", "Terra Nova", "2615201"], + &["PE", "Timba\u{fa}ba", "2615300"], + &["PE", "Toritama", "2615409"], + &["PE", "Tracunha\u{e9}m", "2615508"], + &["PE", "Trindade", "2615607"], + &["PE", "Triunfo", "2615706"], + &["PE", "Tupanatinga", "2615805"], + &["PE", "Tuparetama", "2615904"], + &["PE", "Venturosa", "2616001"], + &["PE", "Verdejante", "2616100"], + &["PE", "Vertente do L\u{e9}rio", "2616183"], + &["PE", "Vertentes", "2616209"], + &["PE", "Vic\u{ea}ncia", "2616308"], + &["PE", "Vit\u{f3}ria de Santo Ant\u{e3}o", "2616407"], + &["PE", "Xex\u{e9}u", "2616506"], + &["PI", "Acau\u{e3}", "2200053"], + &["PI", "Agricol\u{e2}ndia", "2200103"], + &["PI", "\u{c1}gua Branca", "2200202"], + &["PI", "Alagoinha do Piau\u{ed}", "2200251"], + &["PI", "Alegrete do Piau\u{ed}", "2200277"], + &["PI", "Alto Long\u{e1}", "2200301"], + &["PI", "Altos", "2200400"], + &["PI", "Alvorada do Gurgu\u{e9}ia", "2200459"], + &["PI", "Amarante", "2200509"], + &["PI", "Angical do Piau\u{ed}", "2200608"], + &["PI", "An\u{ed}sio de Abreu", "2200707"], + &["PI", "Ant\u{f4}nio Almeida", "2200806"], + &["PI", "Aroazes", "2200905"], + &["PI", "Aroeiras do Itaim", "2200954"], + &["PI", "Arraial", "2201002"], + &["PI", "Assun\u{e7}\u{e3}o do Piau\u{ed}", "2201051"], + &["PI", "Avelino Lopes", "2201101"], + &["PI", "Baixa Grande do Ribeiro", "2201150"], + &["PI", "Barra D'Alc\u{e2}ntara", "2201176"], + &["PI", "Barras", "2201200"], + &["PI", "Barreiras do Piau\u{ed}", "2201309"], + &["PI", "Barro Duro", "2201408"], + &["PI", "Batalha", "2201507"], + &["PI", "Bela Vista do Piau\u{ed}", "2201556"], + &["PI", "Bel\u{e9}m do Piau\u{ed}", "2201572"], + &["PI", "Beneditinos", "2201606"], + &["PI", "Bertol\u{ed}nia", "2201705"], + &["PI", "Bet\u{e2}nia do Piau\u{ed}", "2201739"], + &["PI", "Boa Hora", "2201770"], + &["PI", "Bocaina", "2201804"], + &["PI", "Bom Jesus", "2201903"], + &["PI", "Bom Princ\u{ed}pio do Piau\u{ed}", "2201919"], + &["PI", "Bonfim do Piau\u{ed}", "2201929"], + &["PI", "Boqueir\u{e3}o do Piau\u{ed}", "2201945"], + &["PI", "Brasileira", "2201960"], + &["PI", "Brejo do Piau\u{ed}", "2201988"], + &["PI", "Buriti dos Lopes", "2202000"], + &["PI", "Buriti dos Montes", "2202026"], + &["PI", "Cabeceiras do Piau\u{ed}", "2202059"], + &["PI", "Cajazeiras do Piau\u{ed}", "2202075"], + &["PI", "Cajueiro da Praia", "2202083"], + &["PI", "Caldeir\u{e3}o Grande do Piau\u{ed}", "2202091"], + &["PI", "Campinas do Piau\u{ed}", "2202109"], + &["PI", "Campo Alegre do Fidalgo", "2202117"], + &["PI", "Campo Grande do Piau\u{ed}", "2202133"], + &["PI", "Campo Largo do Piau\u{ed}", "2202174"], + &["PI", "Campo Maior", "2202208"], + &["PI", "Canavieira", "2202251"], + &["PI", "Canto do Buriti", "2202307"], + &["PI", "Capit\u{e3}o de Campos", "2202406"], + &["PI", "Capit\u{e3}o Gerv\u{e1}sio Oliveira", "2202455"], + &["PI", "Caracol", "2202505"], + &["PI", "Cara\u{fa}bas do Piau\u{ed}", "2202539"], + &["PI", "Caridade do Piau\u{ed}", "2202554"], + &["PI", "Castelo do Piau\u{ed}", "2202604"], + &["PI", "Caxing\u{f3}", "2202653"], + &["PI", "Cocal", "2202703"], + &["PI", "Cocal de Telha", "2202711"], + &["PI", "Cocal dos Alves", "2202729"], + &["PI", "Coivaras", "2202737"], + &["PI", "Col\u{f4}nia do Gurgu\u{e9}ia", "2202752"], + &["PI", "Col\u{f4}nia do Piau\u{ed}", "2202778"], + &["PI", "Concei\u{e7}\u{e3}o do Canind\u{e9}", "2202802"], + &["PI", "Coronel Jos\u{e9} Dias", "2202851"], + &["PI", "Corrente", "2202901"], + &["PI", "Cristal\u{e2}ndia do Piau\u{ed}", "2203008"], + &["PI", "Cristino Castro", "2203107"], + &["PI", "Curimat\u{e1}", "2203206"], + &["PI", "Currais", "2203230"], + &["PI", "Curral Novo do Piau\u{ed}", "2203271"], + &["PI", "Curralinhos", "2203255"], + &["PI", "Demerval Lob\u{e3}o", "2203305"], + &["PI", "Dirceu Arcoverde", "2203354"], + &["PI", "Dom Expedito Lopes", "2203404"], + &["PI", "Dom Inoc\u{ea}ncio", "2203453"], + &["PI", "Domingos Mour\u{e3}o", "2203420"], + &["PI", "Elesb\u{e3}o Veloso", "2203503"], + &["PI", "Eliseu Martins", "2203602"], + &["PI", "Esperantina", "2203701"], + &["PI", "Fartura do Piau\u{ed}", "2203750"], + &["PI", "Flores do Piau\u{ed}", "2203800"], + &["PI", "Floresta do Piau\u{ed}", "2203859"], + &["PI", "Floriano", "2203909"], + &["PI", "Francin\u{f3}polis", "2204006"], + &["PI", "Francisco Ayres", "2204105"], + &["PI", "Francisco Macedo", "2204154"], + &["PI", "Francisco Santos", "2204204"], + &["PI", "Fronteiras", "2204303"], + &["PI", "Geminiano", "2204352"], + &["PI", "Gilbu\u{e9}s", "2204402"], + &["PI", "Guadalupe", "2204501"], + &["PI", "Guaribas", "2204550"], + &["PI", "Hugo Napole\u{e3}o", "2204600"], + &["PI", "Ilha Grande", "2204659"], + &["PI", "Inhuma", "2204709"], + &["PI", "Ipiranga do Piau\u{ed}", "2204808"], + &["PI", "Isa\u{ed}as Coelho", "2204907"], + &["PI", "Itain\u{f3}polis", "2205003"], + &["PI", "Itaueira", "2205102"], + &["PI", "Jacobina do Piau\u{ed}", "2205151"], + &["PI", "Jaic\u{f3}s", "2205201"], + &["PI", "Jardim do Mulato", "2205250"], + &["PI", "Jatob\u{e1} do Piau\u{ed}", "2205276"], + &["PI", "Jerumenha", "2205300"], + &["PI", "Jo\u{e3}o Costa", "2205359"], + &["PI", "Joaquim Pires", "2205409"], + &["PI", "Joca Marques", "2205458"], + &["PI", "Jos\u{e9} de Freitas", "2205508"], + &["PI", "Juazeiro do Piau\u{ed}", "2205516"], + &["PI", "J\u{fa}lio Borges", "2205524"], + &["PI", "Jurema", "2205532"], + &["PI", "Lagoa Alegre", "2205557"], + &["PI", "Lagoa de S\u{e3}o Francisco", "2205573"], + &["PI", "Lagoa do Barro do Piau\u{ed}", "2205565"], + &["PI", "Lagoa do Piau\u{ed}", "2205581"], + &["PI", "Lagoa do S\u{ed}tio", "2205599"], + &["PI", "Lagoinha do Piau\u{ed}", "2205540"], + &["PI", "Landri Sales", "2205607"], + &["PI", "Lu\u{ed}s Correia", "2205706"], + &["PI", "Luzil\u{e2}ndia", "2205805"], + &["PI", "Madeiro", "2205854"], + &["PI", "Manoel Em\u{ed}dio", "2205904"], + &["PI", "Marcol\u{e2}ndia", "2205953"], + &["PI", "Marcos Parente", "2206001"], + &["PI", "Massap\u{ea} do Piau\u{ed}", "2206050"], + &["PI", "Matias Ol\u{ed}mpio", "2206100"], + &["PI", "Miguel Alves", "2206209"], + &["PI", "Miguel Le\u{e3}o", "2206308"], + &["PI", "Milton Brand\u{e3}o", "2206357"], + &["PI", "Monsenhor Gil", "2206407"], + &["PI", "Monsenhor Hip\u{f3}lito", "2206506"], + &["PI", "Monte Alegre do Piau\u{ed}", "2206605"], + &["PI", "Morro Cabe\u{e7}a no Tempo", "2206654"], + &["PI", "Morro do Chap\u{e9}u do Piau\u{ed}", "2206670"], + &["PI", "Murici dos Portelas", "2206696"], + &["PI", "Nazar\u{e9} do Piau\u{ed}", "2206704"], + &["PI", "Naz\u{e1}ria", "2206720"], + &["PI", "Nossa Senhora de Nazar\u{e9}", "2206753"], + &["PI", "Nossa Senhora dos Rem\u{e9}dios", "2206803"], + &["PI", "Nova Santa Rita", "2207959"], + &["PI", "Novo Oriente do Piau\u{ed}", "2206902"], + &["PI", "Novo Santo Ant\u{f4}nio", "2206951"], + &["PI", "Oeiras", "2207009"], + &["PI", "Olho D'\u{c1}gua do Piau\u{ed}", "2207108"], + &["PI", "Padre Marcos", "2207207"], + &["PI", "Paes Landim", "2207306"], + &["PI", "Paje\u{fa} do Piau\u{ed}", "2207355"], + &["PI", "Palmeira do Piau\u{ed}", "2207405"], + &["PI", "Palmeirais", "2207504"], + &["PI", "Paquet\u{e1}", "2207553"], + &["PI", "Parnagu\u{e1}", "2207603"], + &["PI", "Parna\u{ed}ba", "2207702"], + &["PI", "Passagem Franca do Piau\u{ed}", "2207751"], + &["PI", "Patos do Piau\u{ed}", "2207777"], + &["PI", "Pau D'Arco do Piau\u{ed}", "2207793"], + &["PI", "Paulistana", "2207801"], + &["PI", "Pavussu", "2207850"], + &["PI", "Pedro II", "2207900"], + &["PI", "Pedro Laurentino", "2207934"], + &["PI", "Picos", "2208007"], + &["PI", "Pimenteiras", "2208106"], + &["PI", "Pio IX", "2208205"], + &["PI", "Piracuruca", "2208304"], + &["PI", "Piripiri", "2208403"], + &["PI", "Porto", "2208502"], + &["PI", "Porto Alegre do Piau\u{ed}", "2208551"], + &["PI", "Prata do Piau\u{ed}", "2208601"], + &["PI", "Queimada Nova", "2208650"], + &["PI", "Reden\u{e7}\u{e3}o do Gurgu\u{e9}ia", "2208700"], + &["PI", "Regenera\u{e7}\u{e3}o", "2208809"], + &["PI", "Riacho Frio", "2208858"], + &["PI", "Ribeira do Piau\u{ed}", "2208874"], + &["PI", "Ribeiro Gon\u{e7}alves", "2208908"], + &["PI", "Rio Grande do Piau\u{ed}", "2209005"], + &["PI", "Santa Cruz do Piau\u{ed}", "2209104"], + &["PI", "Santa Cruz dos Milagres", "2209153"], + &["PI", "Santa Filomena", "2209203"], + &["PI", "Santa Luz", "2209302"], + &["PI", "Santa Rosa do Piau\u{ed}", "2209377"], + &["PI", "Santana do Piau\u{ed}", "2209351"], + &["PI", "Santo Ant\u{f4}nio de Lisboa", "2209401"], + &["PI", "Santo Ant\u{f4}nio dos Milagres", "2209450"], + &["PI", "Santo In\u{e1}cio do Piau\u{ed}", "2209500"], + &["PI", "S\u{e3}o Braz do Piau\u{ed}", "2209559"], + &["PI", "S\u{e3}o F\u{e9}lix do Piau\u{ed}", "2209609"], + &["PI", "S\u{e3}o Francisco de Assis do Piau\u{ed}", "2209658"], + &["PI", "S\u{e3}o Francisco do Piau\u{ed}", "2209708"], + &["PI", "S\u{e3}o Gon\u{e7}alo do Gurgu\u{e9}ia", "2209757"], + &["PI", "S\u{e3}o Gon\u{e7}alo do Piau\u{ed}", "2209807"], + &["PI", "S\u{e3}o Jo\u{e3}o da Canabrava", "2209856"], + &["PI", "S\u{e3}o Jo\u{e3}o da Fronteira", "2209872"], + &["PI", "S\u{e3}o Jo\u{e3}o da Serra", "2209906"], + &["PI", "S\u{e3}o Jo\u{e3}o da Varjota", "2209955"], + &["PI", "S\u{e3}o Jo\u{e3}o do Arraial", "2209971"], + &["PI", "S\u{e3}o Jo\u{e3}o do Piau\u{ed}", "2210003"], + &["PI", "S\u{e3}o Jos\u{e9} do Divino", "2210052"], + &["PI", "S\u{e3}o Jos\u{e9} do Peixe", "2210102"], + &["PI", "S\u{e3}o Jos\u{e9} do Piau\u{ed}", "2210201"], + &["PI", "S\u{e3}o Juli\u{e3}o", "2210300"], + &["PI", "S\u{e3}o Louren\u{e7}o do Piau\u{ed}", "2210359"], + &["PI", "S\u{e3}o Luis do Piau\u{ed}", "2210375"], + &["PI", "S\u{e3}o Miguel da Baixa Grande", "2210383"], + &["PI", "S\u{e3}o Miguel do Fidalgo", "2210391"], + &["PI", "S\u{e3}o Miguel do Tapuio", "2210409"], + &["PI", "S\u{e3}o Pedro do Piau\u{ed}", "2210508"], + &["PI", "S\u{e3}o Raimundo Nonato", "2210607"], + &["PI", "Sebasti\u{e3}o Barros", "2210623"], + &["PI", "Sebasti\u{e3}o Leal", "2210631"], + &["PI", "Sigefredo Pacheco", "2210656"], + &["PI", "Sim\u{f5}es", "2210706"], + &["PI", "Simpl\u{ed}cio Mendes", "2210805"], + &["PI", "Socorro do Piau\u{ed}", "2210904"], + &["PI", "Sussuapara", "2210938"], + &["PI", "Tamboril do Piau\u{ed}", "2210953"], + &["PI", "Tanque do Piau\u{ed}", "2210979"], + &["PI", "Teresina", "2211001"], + &["PI", "Uni\u{e3}o", "2211100"], + &["PI", "Uru\u{e7}u\u{ed}", "2211209"], + &["PI", "Valen\u{e7}a do Piau\u{ed}", "2211308"], + &["PI", "V\u{e1}rzea Branca", "2211357"], + &["PI", "V\u{e1}rzea Grande", "2211407"], + &["PI", "Vera Mendes", "2211506"], + &["PI", "Vila Nova do Piau\u{ed}", "2211605"], + &["PI", "Wall Ferraz", "2211704"], + &["RJ", "Angra dos Reis", "3300100"], + &["RJ", "Aperib\u{e9}", "3300159"], + &["RJ", "Araruama", "3300209"], + &["RJ", "Areal", "3300225"], + &["RJ", "Arma\u{e7}\u{e3}o dos B\u{fa}zios", "3300233"], + &["RJ", "Arraial do Cabo", "3300258"], + &["RJ", "Barra do Pira\u{ed}", "3300308"], + &["RJ", "Barra Mansa", "3300407"], + &["RJ", "Belford Roxo", "3300456"], + &["RJ", "Bom Jardim", "3300506"], + &["RJ", "Bom Jesus do Itabapoana", "3300605"], + &["RJ", "Cabo Frio", "3300704"], + &["RJ", "Cachoeiras de Macacu", "3300803"], + &["RJ", "Cambuci", "3300902"], + &["RJ", "Campos dos Goytacazes", "3301009"], + &["RJ", "Cantagalo", "3301108"], + &["RJ", "Carapebus", "3300936"], + &["RJ", "Cardoso Moreira", "3301157"], + &["RJ", "Carmo", "3301207"], + &["RJ", "Casimiro de Abreu", "3301306"], + &["RJ", "Comendador Levy Gasparian", "3300951"], + &["RJ", "Concei\u{e7}\u{e3}o de Macabu", "3301405"], + &["RJ", "Cordeiro", "3301504"], + &["RJ", "Duas Barras", "3301603"], + &["RJ", "Duque de Caxias", "3301702"], + &["RJ", "Engenheiro Paulo de Frontin", "3301801"], + &["RJ", "Guapimirim", "3301850"], + &["RJ", "Iguaba Grande", "3301876"], + &["RJ", "Itabora\u{ed}", "3301900"], + &["RJ", "Itagua\u{ed}", "3302007"], + &["RJ", "Italva", "3302056"], + &["RJ", "Itaocara", "3302106"], + &["RJ", "Itaperuna", "3302205"], + &["RJ", "Itatiaia", "3302254"], + &["RJ", "Japeri", "3302270"], + &["RJ", "Laje do Muria\u{e9}", "3302304"], + &["RJ", "Maca\u{e9}", "3302403"], + &["RJ", "Macuco", "3302452"], + &["RJ", "Mag\u{e9}", "3302502"], + &["RJ", "Mangaratiba", "3302601"], + &["RJ", "Maric\u{e1}", "3302700"], + &["RJ", "Mendes", "3302809"], + &["RJ", "Mesquita", "3302858"], + &["RJ", "Miguel Pereira", "3302908"], + &["RJ", "Miracema", "3303005"], + &["RJ", "Natividade", "3303104"], + &["RJ", "Nil\u{f3}polis", "3303203"], + &["RJ", "Niter\u{f3}i", "3303302"], + &["RJ", "Nova Friburgo", "3303401"], + &["RJ", "Nova Igua\u{e7}u", "3303500"], + &["RJ", "Paracambi", "3303609"], + &["RJ", "Para\u{ed}ba do Sul", "3303708"], + &["RJ", "Paraty", "3303807"], + &["RJ", "Paty do Alferes", "3303856"], + &["RJ", "Petr\u{f3}polis", "3303906"], + &["RJ", "Pinheiral", "3303955"], + &["RJ", "Pira\u{ed}", "3304003"], + &["RJ", "Porci\u{fa}ncula", "3304102"], + &["RJ", "Porto Real", "3304110"], + &["RJ", "Quatis", "3304128"], + &["RJ", "Queimados", "3304144"], + &["RJ", "Quissam\u{e3}", "3304151"], + &["RJ", "Resende", "3304201"], + &["RJ", "Rio Bonito", "3304300"], + &["RJ", "Rio Claro", "3304409"], + &["RJ", "Rio das Flores", "3304508"], + &["RJ", "Rio das Ostras", "3304524"], + &["RJ", "Rio de Janeiro", "3304557"], + &["RJ", "Santa Maria Madalena", "3304607"], + &["RJ", "Santo Ant\u{f4}nio de P\u{e1}dua", "3304706"], + &["RJ", "S\u{e3}o Fid\u{e9}lis", "3304805"], + &["RJ", "S\u{e3}o Francisco de Itabapoana", "3304755"], + &["RJ", "S\u{e3}o Gon\u{e7}alo", "3304904"], + &["RJ", "S\u{e3}o Jo\u{e3}o da Barra", "3305000"], + &["RJ", "S\u{e3}o Jo\u{e3}o de Meriti", "3305109"], + &["RJ", "S\u{e3}o Jos\u{e9} de Ub\u{e1}", "3305133"], + &["RJ", "S\u{e3}o Jos\u{e9} do Vale do Rio Preto", "3305158"], + &["RJ", "S\u{e3}o Pedro da Aldeia", "3305208"], + &["RJ", "S\u{e3}o Sebasti\u{e3}o do Alto", "3305307"], + &["RJ", "Sapucaia", "3305406"], + &["RJ", "Saquarema", "3305505"], + &["RJ", "Serop\u{e9}dica", "3305554"], + &["RJ", "Silva Jardim", "3305604"], + &["RJ", "Sumidouro", "3305703"], + &["RJ", "Tangu\u{e1}", "3305752"], + &["RJ", "Teres\u{f3}polis", "3305802"], + &["RJ", "Trajano de Moraes", "3305901"], + &["RJ", "Tr\u{ea}s Rios", "3306008"], + &["RJ", "Valen\u{e7}a", "3306107"], + &["RJ", "Varre-Sai", "3306156"], + &["RJ", "Vassouras", "3306206"], + &["RJ", "Volta Redonda", "3306305"], + &["RN", "Acari", "2400109"], + &["RN", "Afonso Bezerra", "2400307"], + &["RN", "\u{c1}gua Nova", "2400406"], + &["RN", "Alexandria", "2400505"], + &["RN", "Almino Afonso", "2400604"], + &["RN", "Alto do Rodrigues", "2400703"], + &["RN", "Angicos", "2400802"], + &["RN", "Ant\u{f4}nio Martins", "2400901"], + &["RN", "Apodi", "2401008"], + &["RN", "Areia Branca", "2401107"], + &["RN", "Arez", "2401206"], + &["RN", "Ass\u{fa}", "2400208"], + &["RN", "Ba\u{ed}a Formosa", "2401404"], + &["RN", "Bara\u{fa}na", "2401453"], + &["RN", "Barcelona", "2401503"], + &["RN", "Bento Fernandes", "2401602"], + &["RN", "Bod\u{f3}", "2401651"], + &["RN", "Bom Jesus", "2401701"], + &["RN", "Brejinho", "2401800"], + &["RN", "Cai\u{e7}ara do Norte", "2401859"], + &["RN", "Cai\u{e7}ara do Rio do Vento", "2401909"], + &["RN", "Caic\u{f3}", "2402006"], + &["RN", "Campo Grande", "2401305"], + &["RN", "Campo Redondo", "2402105"], + &["RN", "Canguaretama", "2402204"], + &["RN", "Cara\u{fa}bas", "2402303"], + &["RN", "Carna\u{fa}ba dos Dantas", "2402402"], + &["RN", "Carnaubais", "2402501"], + &["RN", "Cear\u{e1}-Mirim", "2402600"], + &["RN", "Cerro Cor\u{e1}", "2402709"], + &["RN", "Coronel Ezequiel", "2402808"], + &["RN", "Coronel Jo\u{e3}o Pessoa", "2402907"], + &["RN", "Cruzeta", "2403004"], + &["RN", "Currais Novos", "2403103"], + &["RN", "Doutor Severiano", "2403202"], + &["RN", "Encanto", "2403301"], + &["RN", "Equador", "2403400"], + &["RN", "Esp\u{ed}rito Santo", "2403509"], + &["RN", "Extremoz", "2403608"], + &["RN", "Felipe Guerra", "2403707"], + &["RN", "Fernando Pedroza", "2403756"], + &["RN", "Flor\u{e2}nia", "2403806"], + &["RN", "Francisco Dantas", "2403905"], + &["RN", "Frutuoso Gomes", "2404002"], + &["RN", "Galinhos", "2404101"], + &["RN", "Goianinha", "2404200"], + &["RN", "Governador Dix-Sept Rosado", "2404309"], + &["RN", "Grossos", "2404408"], + &["RN", "Guamar\u{e9}", "2404507"], + &["RN", "Ielmo Marinho", "2404606"], + &["RN", "Ipangua\u{e7}u", "2404705"], + &["RN", "Ipueira", "2404804"], + &["RN", "Itaj\u{e1}", "2404853"], + &["RN", "Ita\u{fa}", "2404903"], + &["RN", "Ja\u{e7}an\u{e3}", "2405009"], + &["RN", "Janda\u{ed}ra", "2405108"], + &["RN", "Jandu\u{ed}s", "2405207"], + &["RN", "Janu\u{e1}rio Cicco", "2405306"], + &["RN", "Japi", "2405405"], + &["RN", "Jardim de Angicos", "2405504"], + &["RN", "Jardim de Piranhas", "2405603"], + &["RN", "Jardim do Serid\u{f3}", "2405702"], + &["RN", "Jo\u{e3}o C\u{e2}mara", "2405801"], + &["RN", "Jo\u{e3}o Dias", "2405900"], + &["RN", "Jos\u{e9} da Penha", "2406007"], + &["RN", "Jucurutu", "2406106"], + &["RN", "Jundi\u{e1}", "2406155"], + &["RN", "Lagoa d'Anta", "2406205"], + &["RN", "Lagoa de Pedras", "2406304"], + &["RN", "Lagoa de Velhos", "2406403"], + &["RN", "Lagoa Nova", "2406502"], + &["RN", "Lagoa Salgada", "2406601"], + &["RN", "Lajes", "2406700"], + &["RN", "Lajes Pintadas", "2406809"], + &["RN", "Lucr\u{e9}cia", "2406908"], + &["RN", "Lu\u{ed}s Gomes", "2407005"], + &["RN", "Maca\u{ed}ba", "2407104"], + &["RN", "Macau", "2407203"], + &["RN", "Major Sales", "2407252"], + &["RN", "Marcelino Vieira", "2407302"], + &["RN", "Martins", "2407401"], + &["RN", "Maxaranguape", "2407500"], + &["RN", "Messias Targino", "2407609"], + &["RN", "Montanhas", "2407708"], + &["RN", "Monte Alegre", "2407807"], + &["RN", "Monte das Gameleiras", "2407906"], + &["RN", "Mossor\u{f3}", "2408003"], + &["RN", "Natal", "2408102"], + &["RN", "N\u{ed}sia Floresta", "2408201"], + &["RN", "Nova Cruz", "2408300"], + &["RN", "Olho d'\u{c1}gua do Borges", "2408409"], + &["RN", "Ouro Branco", "2408508"], + &["RN", "Paran\u{e1}", "2408607"], + &["RN", "Para\u{fa}", "2408706"], + &["RN", "Parazinho", "2408805"], + &["RN", "Parelhas", "2408904"], + &["RN", "Parnamirim", "2403251"], + &["RN", "Passa e Fica", "2409100"], + &["RN", "Passagem", "2409209"], + &["RN", "Patu", "2409308"], + &["RN", "Pau dos Ferros", "2409407"], + &["RN", "Pedra Grande", "2409506"], + &["RN", "Pedra Preta", "2409605"], + &["RN", "Pedro Avelino", "2409704"], + &["RN", "Pedro Velho", "2409803"], + &["RN", "Pend\u{ea}ncias", "2409902"], + &["RN", "Pil\u{f5}es", "2410009"], + &["RN", "Po\u{e7}o Branco", "2410108"], + &["RN", "Portalegre", "2410207"], + &["RN", "Porto do Mangue", "2410256"], + &["RN", "Pureza", "2410405"], + &["RN", "Rafael Fernandes", "2410504"], + &["RN", "Rafael Godeiro", "2410603"], + &["RN", "Riacho da Cruz", "2410702"], + &["RN", "Riacho de Santana", "2410801"], + &["RN", "Riachuelo", "2410900"], + &["RN", "Rio do Fogo", "2408953"], + &["RN", "Rodolfo Fernandes", "2411007"], + &["RN", "Ruy Barbosa", "2411106"], + &["RN", "Santa Cruz", "2411205"], + &["RN", "Santa Maria", "2409332"], + &["RN", "Santana do Matos", "2411403"], + &["RN", "Santana do Serid\u{f3}", "2411429"], + &["RN", "Santo Ant\u{f4}nio", "2411502"], + &["RN", "S\u{e3}o Bento do Norte", "2411601"], + &["RN", "S\u{e3}o Bento do Trair\u{ed}", "2411700"], + &["RN", "S\u{e3}o Fernando", "2411809"], + &["RN", "S\u{e3}o Francisco do Oeste", "2411908"], + &["RN", "S\u{e3}o Gon\u{e7}alo do Amarante", "2412005"], + &["RN", "S\u{e3}o Jo\u{e3}o do Sabugi", "2412104"], + &["RN", "S\u{e3}o Jos\u{e9} de Mipibu", "2412203"], + &["RN", "S\u{e3}o Jos\u{e9} do Campestre", "2412302"], + &["RN", "S\u{e3}o Jos\u{e9} do Serid\u{f3}", "2412401"], + &["RN", "S\u{e3}o Miguel", "2412500"], + &["RN", "S\u{e3}o Miguel do Gostoso", "2412559"], + &["RN", "S\u{e3}o Paulo do Potengi", "2412609"], + &["RN", "S\u{e3}o Pedro", "2412708"], + &["RN", "S\u{e3}o Rafael", "2412807"], + &["RN", "S\u{e3}o Tom\u{e9}", "2412906"], + &["RN", "S\u{e3}o Vicente", "2413003"], + &["RN", "Senador El\u{f3}i de Souza", "2413102"], + &["RN", "Senador Georgino Avelino", "2413201"], + &["RN", "Serra Caiada", "2410306"], + &["RN", "Serra de S\u{e3}o Bento", "2413300"], + &["RN", "Serra do Mel", "2413359"], + &["RN", "Serra Negra do Norte", "2413409"], + &["RN", "Serrinha", "2413508"], + &["RN", "Serrinha dos Pintos", "2413557"], + &["RN", "Severiano Melo", "2413607"], + &["RN", "S\u{ed}tio Novo", "2413706"], + &["RN", "Taboleiro Grande", "2413805"], + &["RN", "Taipu", "2413904"], + &["RN", "Tangar\u{e1}", "2414001"], + &["RN", "Tenente Ananias", "2414100"], + &["RN", "Tenente Laurentino Cruz", "2414159"], + &["RN", "Tibau", "2411056"], + &["RN", "Tibau do Sul", "2414209"], + &["RN", "Timba\u{fa}ba dos Batistas", "2414308"], + &["RN", "Touros", "2414407"], + &["RN", "Triunfo Potiguar", "2414456"], + &["RN", "Umarizal", "2414506"], + &["RN", "Upanema", "2414605"], + &["RN", "V\u{e1}rzea", "2414704"], + &["RN", "Venha-Ver", "2414753"], + &["RN", "Vera Cruz", "2414803"], + &["RN", "Vi\u{e7}osa", "2414902"], + &["RN", "Vila Flor", "2415008"], + &["RS", "Acegu\u{e1}", "4300034"], + &["RS", "\u{c1}gua Santa", "4300059"], + &["RS", "Agudo", "4300109"], + &["RS", "Ajuricaba", "4300208"], + &["RS", "Alecrim", "4300307"], + &["RS", "Alegrete", "4300406"], + &["RS", "Alegria", "4300455"], + &["RS", "Almirante Tamandar\u{e9} do Sul", "4300471"], + &["RS", "Alpestre", "4300505"], + &["RS", "Alto Alegre", "4300554"], + &["RS", "Alto Feliz", "4300570"], + &["RS", "Alvorada", "4300604"], + &["RS", "Amaral Ferrador", "4300638"], + &["RS", "Ametista do Sul", "4300646"], + &["RS", "Andr\u{e9} da Rocha", "4300661"], + &["RS", "Anta Gorda", "4300703"], + &["RS", "Ant\u{f4}nio Prado", "4300802"], + &["RS", "Arambar\u{e9}", "4300851"], + &["RS", "Araric\u{e1}", "4300877"], + &["RS", "Aratiba", "4300901"], + &["RS", "Arroio do Meio", "4301008"], + &["RS", "Arroio do Padre", "4301073"], + &["RS", "Arroio do Sal", "4301057"], + &["RS", "Arroio do Tigre", "4301206"], + &["RS", "Arroio dos Ratos", "4301107"], + &["RS", "Arroio Grande", "4301305"], + &["RS", "Arvorezinha", "4301404"], + &["RS", "Augusto Pestana", "4301503"], + &["RS", "\u{c1}urea", "4301552"], + &["RS", "Bag\u{e9}", "4301602"], + &["RS", "Balne\u{e1}rio Pinhal", "4301636"], + &["RS", "Bar\u{e3}o", "4301651"], + &["RS", "Bar\u{e3}o de Cotegipe", "4301701"], + &["RS", "Bar\u{e3}o do Triunfo", "4301750"], + &["RS", "Barra do Guarita", "4301859"], + &["RS", "Barra do Quara\u{ed}", "4301875"], + &["RS", "Barra do Ribeiro", "4301909"], + &["RS", "Barra do Rio Azul", "4301925"], + &["RS", "Barra Funda", "4301958"], + &["RS", "Barrac\u{e3}o", "4301800"], + &["RS", "Barros Cassal", "4302006"], + &["RS", "Benjamin Constant do Sul", "4302055"], + &["RS", "Bento Gon\u{e7}alves", "4302105"], + &["RS", "Boa Vista das Miss\u{f5}es", "4302154"], + &["RS", "Boa Vista do Buric\u{e1}", "4302204"], + &["RS", "Boa Vista do Cadeado", "4302220"], + &["RS", "Boa Vista do Incra", "4302238"], + &["RS", "Boa Vista do Sul", "4302253"], + &["RS", "Bom Jesus", "4302303"], + &["RS", "Bom Princ\u{ed}pio", "4302352"], + &["RS", "Bom Progresso", "4302378"], + &["RS", "Bom Retiro do Sul", "4302402"], + &["RS", "Boqueir\u{e3}o do Le\u{e3}o", "4302451"], + &["RS", "Bossoroca", "4302501"], + &["RS", "Bozano", "4302584"], + &["RS", "Braga", "4302600"], + &["RS", "Brochier", "4302659"], + &["RS", "Buti\u{e1}", "4302709"], + &["RS", "Ca\u{e7}apava do Sul", "4302808"], + &["RS", "Cacequi", "4302907"], + &["RS", "Cachoeira do Sul", "4303004"], + &["RS", "Cachoeirinha", "4303103"], + &["RS", "Cacique Doble", "4303202"], + &["RS", "Caibat\u{e9}", "4303301"], + &["RS", "Cai\u{e7}ara", "4303400"], + &["RS", "Camaqu\u{e3}", "4303509"], + &["RS", "Camargo", "4303558"], + &["RS", "Cambar\u{e1} do Sul", "4303608"], + &["RS", "Campestre da Serra", "4303673"], + &["RS", "Campina das Miss\u{f5}es", "4303707"], + &["RS", "Campinas do Sul", "4303806"], + &["RS", "Campo Bom", "4303905"], + &["RS", "Campo Novo", "4304002"], + &["RS", "Campos Borges", "4304101"], + &["RS", "Candel\u{e1}ria", "4304200"], + &["RS", "C\u{e2}ndido God\u{f3}i", "4304309"], + &["RS", "Candiota", "4304358"], + &["RS", "Canela", "4304408"], + &["RS", "Cangu\u{e7}u", "4304507"], + &["RS", "Canoas", "4304606"], + &["RS", "Canudos do Vale", "4304614"], + &["RS", "Cap\u{e3}o Bonito do Sul", "4304622"], + &["RS", "Cap\u{e3}o da Canoa", "4304630"], + &["RS", "Cap\u{e3}o do Cip\u{f3}", "4304655"], + &["RS", "Cap\u{e3}o do Le\u{e3}o", "4304663"], + &["RS", "Capela de Santana", "4304689"], + &["RS", "Capit\u{e3}o", "4304697"], + &["RS", "Capivari do Sul", "4304671"], + &["RS", "Cara\u{e1}", "4304713"], + &["RS", "Carazinho", "4304705"], + &["RS", "Carlos Barbosa", "4304804"], + &["RS", "Carlos Gomes", "4304853"], + &["RS", "Casca", "4304903"], + &["RS", "Caseiros", "4304952"], + &["RS", "Catu\u{ed}pe", "4305009"], + &["RS", "Caxias do Sul", "4305108"], + &["RS", "Centen\u{e1}rio", "4305116"], + &["RS", "Cerrito", "4305124"], + &["RS", "Cerro Branco", "4305132"], + &["RS", "Cerro Grande", "4305157"], + &["RS", "Cerro Grande do Sul", "4305173"], + &["RS", "Cerro Largo", "4305207"], + &["RS", "Chapada", "4305306"], + &["RS", "Charqueadas", "4305355"], + &["RS", "Charrua", "4305371"], + &["RS", "Chiapetta", "4305405"], + &["RS", "Chu\u{ed}", "4305439"], + &["RS", "Chuvisca", "4305447"], + &["RS", "Cidreira", "4305454"], + &["RS", "Cir\u{ed}aco", "4305504"], + &["RS", "Colinas", "4305587"], + &["RS", "Colorado", "4305603"], + &["RS", "Condor", "4305702"], + &["RS", "Constantina", "4305801"], + &["RS", "Coqueiro Baixo", "4305835"], + &["RS", "Coqueiros do Sul", "4305850"], + &["RS", "Coronel Barros", "4305871"], + &["RS", "Coronel Bicaco", "4305900"], + &["RS", "Coronel Pilar", "4305934"], + &["RS", "Cotipor\u{e3}", "4305959"], + &["RS", "Coxilha", "4305975"], + &["RS", "Crissiumal", "4306007"], + &["RS", "Cristal", "4306056"], + &["RS", "Cristal do Sul", "4306072"], + &["RS", "Cruz Alta", "4306106"], + &["RS", "Cruzaltense", "4306130"], + &["RS", "Cruzeiro do Sul", "4306205"], + &["RS", "David Canabarro", "4306304"], + &["RS", "Derrubadas", "4306320"], + &["RS", "Dezesseis de Novembro", "4306353"], + &["RS", "Dilermando de Aguiar", "4306379"], + &["RS", "Dois Irm\u{e3}os", "4306403"], + &["RS", "Dois Irm\u{e3}os das Miss\u{f5}es", "4306429"], + &["RS", "Dois Lajeados", "4306452"], + &["RS", "Dom Feliciano", "4306502"], + &["RS", "Dom Pedrito", "4306601"], + &["RS", "Dom Pedro de Alc\u{e2}ntara", "4306551"], + &["RS", "Dona Francisca", "4306700"], + &["RS", "Doutor Maur\u{ed}cio Cardoso", "4306734"], + &["RS", "Doutor Ricardo", "4306759"], + &["RS", "Eldorado do Sul", "4306767"], + &["RS", "Encantado", "4306809"], + &["RS", "Encruzilhada do Sul", "4306908"], + &["RS", "Engenho Velho", "4306924"], + &["RS", "Entre Rios do Sul", "4306957"], + &["RS", "Entre-Iju\u{ed}s", "4306932"], + &["RS", "Erebango", "4306973"], + &["RS", "Erechim", "4307005"], + &["RS", "Ernestina", "4307054"], + &["RS", "Erval Grande", "4307203"], + &["RS", "Erval Seco", "4307302"], + &["RS", "Esmeralda", "4307401"], + &["RS", "Esperan\u{e7}a do Sul", "4307450"], + &["RS", "Espumoso", "4307500"], + &["RS", "Esta\u{e7}\u{e3}o", "4307559"], + &["RS", "Est\u{e2}ncia Velha", "4307609"], + &["RS", "Esteio", "4307708"], + &["RS", "Estrela", "4307807"], + &["RS", "Estrela Velha", "4307815"], + &["RS", "Eug\u{ea}nio de Castro", "4307831"], + &["RS", "Fagundes Varela", "4307864"], + &["RS", "Farroupilha", "4307906"], + &["RS", "Faxinal do Soturno", "4308003"], + &["RS", "Faxinalzinho", "4308052"], + &["RS", "Fazenda Vilanova", "4308078"], + &["RS", "Feliz", "4308102"], + &["RS", "Flores da Cunha", "4308201"], + &["RS", "Floriano Peixoto", "4308250"], + &["RS", "Fontoura Xavier", "4308300"], + &["RS", "Formigueiro", "4308409"], + &["RS", "Forquetinha", "4308433"], + &["RS", "Fortaleza dos Valos", "4308458"], + &["RS", "Frederico Westphalen", "4308508"], + &["RS", "Garibaldi", "4308607"], + &["RS", "Garruchos", "4308656"], + &["RS", "Gaurama", "4308706"], + &["RS", "General C\u{e2}mara", "4308805"], + &["RS", "Gentil", "4308854"], + &["RS", "Get\u{fa}lio Vargas", "4308904"], + &["RS", "Giru\u{e1}", "4309001"], + &["RS", "Glorinha", "4309050"], + &["RS", "Gramado", "4309100"], + &["RS", "Gramado dos Loureiros", "4309126"], + &["RS", "Gramado Xavier", "4309159"], + &["RS", "Gravata\u{ed}", "4309209"], + &["RS", "Guabiju", "4309258"], + &["RS", "Gua\u{ed}ba", "4309308"], + &["RS", "Guapor\u{e9}", "4309407"], + &["RS", "Guarani das Miss\u{f5}es", "4309506"], + &["RS", "Harmonia", "4309555"], + &["RS", "Herval", "4307104"], + &["RS", "Herveiras", "4309571"], + &["RS", "Horizontina", "4309605"], + &["RS", "Hulha Negra", "4309654"], + &["RS", "Humait\u{e1}", "4309704"], + &["RS", "Ibarama", "4309753"], + &["RS", "Ibia\u{e7}\u{e1}", "4309803"], + &["RS", "Ibiraiaras", "4309902"], + &["RS", "Ibirapuit\u{e3}", "4309951"], + &["RS", "Ibirub\u{e1}", "4310009"], + &["RS", "Igrejinha", "4310108"], + &["RS", "Iju\u{ed}", "4310207"], + &["RS", "Il\u{f3}polis", "4310306"], + &["RS", "Imb\u{e9}", "4310330"], + &["RS", "Imigrante", "4310363"], + &["RS", "Independ\u{ea}ncia", "4310405"], + &["RS", "Inhacor\u{e1}", "4310413"], + &["RS", "Ip\u{ea}", "4310439"], + &["RS", "Ipiranga do Sul", "4310462"], + &["RS", "Ira\u{ed}", "4310504"], + &["RS", "Itaara", "4310538"], + &["RS", "Itacurubi", "4310553"], + &["RS", "Itapuca", "4310579"], + &["RS", "Itaqui", "4310603"], + &["RS", "Itati", "4310652"], + &["RS", "Itatiba do Sul", "4310702"], + &["RS", "Ivor\u{e1}", "4310751"], + &["RS", "Ivoti", "4310801"], + &["RS", "Jaboticaba", "4310850"], + &["RS", "Jacuizinho", "4310876"], + &["RS", "Jacutinga", "4310900"], + &["RS", "Jaguar\u{e3}o", "4311007"], + &["RS", "Jaguari", "4311106"], + &["RS", "Jaquirana", "4311122"], + &["RS", "Jari", "4311130"], + &["RS", "J\u{f3}ia", "4311155"], + &["RS", "J\u{fa}lio de Castilhos", "4311205"], + &["RS", "Lagoa Bonita do Sul", "4311239"], + &["RS", "Lagoa dos Tr\u{ea}s Cantos", "4311270"], + &["RS", "Lagoa Vermelha", "4311304"], + &["RS", "Lago\u{e3}o", "4311254"], + &["RS", "Lajeado", "4311403"], + &["RS", "Lajeado do Bugre", "4311429"], + &["RS", "Lavras do Sul", "4311502"], + &["RS", "Liberato Salzano", "4311601"], + &["RS", "Lindolfo Collor", "4311627"], + &["RS", "Linha Nova", "4311643"], + &["RS", "Ma\u{e7}ambar\u{e1}", "4311718"], + &["RS", "Machadinho", "4311700"], + &["RS", "Mampituba", "4311734"], + &["RS", "Manoel Viana", "4311759"], + &["RS", "Maquin\u{e9}", "4311775"], + &["RS", "Marat\u{e1}", "4311791"], + &["RS", "Marau", "4311809"], + &["RS", "Marcelino Ramos", "4311908"], + &["RS", "Mariana Pimentel", "4311981"], + &["RS", "Mariano Moro", "4312005"], + &["RS", "Marques de Souza", "4312054"], + &["RS", "Mata", "4312104"], + &["RS", "Mato Castelhano", "4312138"], + &["RS", "Mato Leit\u{e3}o", "4312153"], + &["RS", "Mato Queimado", "4312179"], + &["RS", "Maximiliano de Almeida", "4312203"], + &["RS", "Minas do Le\u{e3}o", "4312252"], + &["RS", "Miragua\u{ed}", "4312302"], + &["RS", "Montauri", "4312351"], + &["RS", "Monte Alegre dos Campos", "4312377"], + &["RS", "Monte Belo do Sul", "4312385"], + &["RS", "Montenegro", "4312401"], + &["RS", "Morma\u{e7}o", "4312427"], + &["RS", "Morrinhos do Sul", "4312443"], + &["RS", "Morro Redondo", "4312450"], + &["RS", "Morro Reuter", "4312476"], + &["RS", "Mostardas", "4312500"], + &["RS", "Mu\u{e7}um", "4312609"], + &["RS", "Muitos Cap\u{f5}es", "4312617"], + &["RS", "Muliterno", "4312625"], + &["RS", "N\u{e3}o-Me-Toque", "4312658"], + &["RS", "Nicolau Vergueiro", "4312674"], + &["RS", "Nonoai", "4312708"], + &["RS", "Nova Alvorada", "4312757"], + &["RS", "Nova Ara\u{e7}\u{e1}", "4312807"], + &["RS", "Nova Bassano", "4312906"], + &["RS", "Nova Boa Vista", "4312955"], + &["RS", "Nova Br\u{e9}scia", "4313003"], + &["RS", "Nova Candel\u{e1}ria", "4313011"], + &["RS", "Nova Esperan\u{e7}a do Sul", "4313037"], + &["RS", "Nova Hartz", "4313060"], + &["RS", "Nova P\u{e1}dua", "4313086"], + &["RS", "Nova Palma", "4313102"], + &["RS", "Nova Petr\u{f3}polis", "4313201"], + &["RS", "Nova Prata", "4313300"], + &["RS", "Nova Ramada", "4313334"], + &["RS", "Nova Roma do Sul", "4313359"], + &["RS", "Nova Santa Rita", "4313375"], + &["RS", "Novo Barreiro", "4313490"], + &["RS", "Novo Cabrais", "4313391"], + &["RS", "Novo Hamburgo", "4313409"], + &["RS", "Novo Machado", "4313425"], + &["RS", "Novo Tiradentes", "4313441"], + &["RS", "Novo Xingu", "4313466"], + &["RS", "Os\u{f3}rio", "4313508"], + &["RS", "Paim Filho", "4313607"], + &["RS", "Palmares do Sul", "4313656"], + &["RS", "Palmeira das Miss\u{f5}es", "4313706"], + &["RS", "Palmitinho", "4313805"], + &["RS", "Panambi", "4313904"], + &["RS", "Pantano Grande", "4313953"], + &["RS", "Para\u{ed}", "4314001"], + &["RS", "Para\u{ed}so do Sul", "4314027"], + &["RS", "Pareci Novo", "4314035"], + &["RS", "Parob\u{e9}", "4314050"], + &["RS", "Passa Sete", "4314068"], + &["RS", "Passo do Sobrado", "4314076"], + &["RS", "Passo Fundo", "4314100"], + &["RS", "Paulo Bento", "4314134"], + &["RS", "Paverama", "4314159"], + &["RS", "Pedras Altas", "4314175"], + &["RS", "Pedro Os\u{f3}rio", "4314209"], + &["RS", "Peju\u{e7}ara", "4314308"], + &["RS", "Pelotas", "4314407"], + &["RS", "Picada Caf\u{e9}", "4314423"], + &["RS", "Pinhal", "4314456"], + &["RS", "Pinhal da Serra", "4314464"], + &["RS", "Pinhal Grande", "4314472"], + &["RS", "Pinheirinho do Vale", "4314498"], + &["RS", "Pinheiro Machado", "4314506"], + &["RS", "Pinto Bandeira", "4314548"], + &["RS", "Pirap\u{f3}", "4314555"], + &["RS", "Piratini", "4314605"], + &["RS", "Planalto", "4314704"], + &["RS", "Po\u{e7}o das Antas", "4314753"], + &["RS", "Pont\u{e3}o", "4314779"], + &["RS", "Ponte Preta", "4314787"], + &["RS", "Port\u{e3}o", "4314803"], + &["RS", "Porto Alegre", "4314902"], + &["RS", "Porto Lucena", "4315008"], + &["RS", "Porto Mau\u{e1}", "4315057"], + &["RS", "Porto Vera Cruz", "4315073"], + &["RS", "Porto Xavier", "4315107"], + &["RS", "Pouso Novo", "4315131"], + &["RS", "Presidente Lucena", "4315149"], + &["RS", "Progresso", "4315156"], + &["RS", "Prot\u{e1}sio Alves", "4315172"], + &["RS", "Putinga", "4315206"], + &["RS", "Quara\u{ed}", "4315305"], + &["RS", "Quatro Irm\u{e3}os", "4315313"], + &["RS", "Quevedos", "4315321"], + &["RS", "Quinze de Novembro", "4315354"], + &["RS", "Redentora", "4315404"], + &["RS", "Relvado", "4315453"], + &["RS", "Restinga S\u{ea}ca", "4315503"], + &["RS", "Rio dos \u{cd}ndios", "4315552"], + &["RS", "Rio Grande", "4315602"], + &["RS", "Rio Pardo", "4315701"], + &["RS", "Riozinho", "4315750"], + &["RS", "Roca Sales", "4315800"], + &["RS", "Rodeio Bonito", "4315909"], + &["RS", "Rolador", "4315958"], + &["RS", "Rolante", "4316006"], + &["RS", "Ronda Alta", "4316105"], + &["RS", "Rondinha", "4316204"], + &["RS", "Roque Gonzales", "4316303"], + &["RS", "Ros\u{e1}rio do Sul", "4316402"], + &["RS", "Sagrada Fam\u{ed}lia", "4316428"], + &["RS", "Saldanha Marinho", "4316436"], + &["RS", "Salto do Jacu\u{ed}", "4316451"], + &["RS", "Salvador das Miss\u{f5}es", "4316477"], + &["RS", "Salvador do Sul", "4316501"], + &["RS", "Sananduva", "4316600"], + &["RS", "Sant'Ana do Livramento", "4317103"], + &["RS", "Santa B\u{e1}rbara do Sul", "4316709"], + &["RS", "Santa Cec\u{ed}lia do Sul", "4316733"], + &["RS", "Santa Clara do Sul", "4316758"], + &["RS", "Santa Cruz do Sul", "4316808"], + &["RS", "Santa Margarida do Sul", "4316972"], + &["RS", "Santa Maria", "4316907"], + &["RS", "Santa Maria do Herval", "4316956"], + &["RS", "Santa Rosa", "4317202"], + &["RS", "Santa Tereza", "4317251"], + &["RS", "Santa Vit\u{f3}ria do Palmar", "4317301"], + &["RS", "Santana da Boa Vista", "4317004"], + &["RS", "Santiago", "4317400"], + &["RS", "Santo \u{c2}ngelo", "4317509"], + &["RS", "Santo Ant\u{f4}nio da Patrulha", "4317608"], + &["RS", "Santo Ant\u{f4}nio das Miss\u{f5}es", "4317707"], + &["RS", "Santo Ant\u{f4}nio do Palma", "4317558"], + &["RS", "Santo Ant\u{f4}nio do Planalto", "4317756"], + &["RS", "Santo Augusto", "4317806"], + &["RS", "Santo Cristo", "4317905"], + &["RS", "Santo Expedito do Sul", "4317954"], + &["RS", "S\u{e3}o Borja", "4318002"], + &["RS", "S\u{e3}o Domingos do Sul", "4318051"], + &["RS", "S\u{e3}o Francisco de Assis", "4318101"], + &["RS", "S\u{e3}o Francisco de Paula", "4318200"], + &["RS", "S\u{e3}o Gabriel", "4318309"], + &["RS", "S\u{e3}o Jer\u{f4}nimo", "4318408"], + &["RS", "S\u{e3}o Jo\u{e3}o da Urtiga", "4318424"], + &["RS", "S\u{e3}o Jo\u{e3}o do Pol\u{ea}sine", "4318432"], + &["RS", "S\u{e3}o Jorge", "4318440"], + &["RS", "S\u{e3}o Jos\u{e9} das Miss\u{f5}es", "4318457"], + &["RS", "S\u{e3}o Jos\u{e9} do Herval", "4318465"], + &["RS", "S\u{e3}o Jos\u{e9} do Hort\u{ea}ncio", "4318481"], + &["RS", "S\u{e3}o Jos\u{e9} do Inhacor\u{e1}", "4318499"], + &["RS", "S\u{e3}o Jos\u{e9} do Norte", "4318507"], + &["RS", "S\u{e3}o Jos\u{e9} do Ouro", "4318606"], + &["RS", "S\u{e3}o Jos\u{e9} do Sul", "4318614"], + &["RS", "S\u{e3}o Jos\u{e9} dos Ausentes", "4318622"], + &["RS", "S\u{e3}o Leopoldo", "4318705"], + &["RS", "S\u{e3}o Louren\u{e7}o do Sul", "4318804"], + &["RS", "S\u{e3}o Luiz Gonzaga", "4318903"], + &["RS", "S\u{e3}o Marcos", "4319000"], + &["RS", "S\u{e3}o Martinho", "4319109"], + &["RS", "S\u{e3}o Martinho da Serra", "4319125"], + &["RS", "S\u{e3}o Miguel das Miss\u{f5}es", "4319158"], + &["RS", "S\u{e3}o Nicolau", "4319208"], + &["RS", "S\u{e3}o Paulo das Miss\u{f5}es", "4319307"], + &["RS", "S\u{e3}o Pedro da Serra", "4319356"], + &["RS", "S\u{e3}o Pedro das Miss\u{f5}es", "4319364"], + &["RS", "S\u{e3}o Pedro do Buti\u{e1}", "4319372"], + &["RS", "S\u{e3}o Pedro do Sul", "4319406"], + &["RS", "S\u{e3}o Sebasti\u{e3}o do Ca\u{ed}", "4319505"], + &["RS", "S\u{e3}o Sep\u{e9}", "4319604"], + &["RS", "S\u{e3}o Valentim", "4319703"], + &["RS", "S\u{e3}o Valentim do Sul", "4319711"], + &["RS", "S\u{e3}o Val\u{e9}rio do Sul", "4319737"], + &["RS", "S\u{e3}o Vendelino", "4319752"], + &["RS", "S\u{e3}o Vicente do Sul", "4319802"], + &["RS", "Sapiranga", "4319901"], + &["RS", "Sapucaia do Sul", "4320008"], + &["RS", "Sarandi", "4320107"], + &["RS", "Seberi", "4320206"], + &["RS", "Sede Nova", "4320230"], + &["RS", "Segredo", "4320263"], + &["RS", "Selbach", "4320305"], + &["RS", "Senador Salgado Filho", "4320321"], + &["RS", "Sentinela do Sul", "4320354"], + &["RS", "Serafina Corr\u{ea}a", "4320404"], + &["RS", "S\u{e9}rio", "4320453"], + &["RS", "Sert\u{e3}o", "4320503"], + &["RS", "Sert\u{e3}o Santana", "4320552"], + &["RS", "Sete de Setembro", "4320578"], + &["RS", "Severiano de Almeida", "4320602"], + &["RS", "Silveira Martins", "4320651"], + &["RS", "Sinimbu", "4320677"], + &["RS", "Sobradinho", "4320701"], + &["RS", "Soledade", "4320800"], + &["RS", "Taba\u{ed}", "4320859"], + &["RS", "Tapejara", "4320909"], + &["RS", "Tapera", "4321006"], + &["RS", "Tapes", "4321105"], + &["RS", "Taquara", "4321204"], + &["RS", "Taquari", "4321303"], + &["RS", "Taquaru\u{e7}u do Sul", "4321329"], + &["RS", "Tavares", "4321352"], + &["RS", "Tenente Portela", "4321402"], + &["RS", "Terra de Areia", "4321436"], + &["RS", "Teut\u{f4}nia", "4321451"], + &["RS", "Tio Hugo", "4321469"], + &["RS", "Tiradentes do Sul", "4321477"], + &["RS", "Toropi", "4321493"], + &["RS", "Torres", "4321501"], + &["RS", "Tramanda\u{ed}", "4321600"], + &["RS", "Travesseiro", "4321626"], + &["RS", "Tr\u{ea}s Arroios", "4321634"], + &["RS", "Tr\u{ea}s Cachoeiras", "4321667"], + &["RS", "Tr\u{ea}s Coroas", "4321709"], + &["RS", "Tr\u{ea}s de Maio", "4321808"], + &["RS", "Tr\u{ea}s Forquilhas", "4321832"], + &["RS", "Tr\u{ea}s Palmeiras", "4321857"], + &["RS", "Tr\u{ea}s Passos", "4321907"], + &["RS", "Trindade do Sul", "4321956"], + &["RS", "Triunfo", "4322004"], + &["RS", "Tucunduva", "4322103"], + &["RS", "Tunas", "4322152"], + &["RS", "Tupanci do Sul", "4322186"], + &["RS", "Tupanciret\u{e3}", "4322202"], + &["RS", "Tupandi", "4322251"], + &["RS", "Tuparendi", "4322301"], + &["RS", "Turu\u{e7}u", "4322327"], + &["RS", "Ubiretama", "4322343"], + &["RS", "Uni\u{e3}o da Serra", "4322350"], + &["RS", "Unistalda", "4322376"], + &["RS", "Uruguaiana", "4322400"], + &["RS", "Vacaria", "4322509"], + &["RS", "Vale do Sol", "4322533"], + &["RS", "Vale Real", "4322541"], + &["RS", "Vale Verde", "4322525"], + &["RS", "Vanini", "4322558"], + &["RS", "Ven\u{e2}ncio Aires", "4322608"], + &["RS", "Vera Cruz", "4322707"], + &["RS", "Veran\u{f3}polis", "4322806"], + &["RS", "Vespasiano Corr\u{ea}a", "4322855"], + &["RS", "Viadutos", "4322905"], + &["RS", "Viam\u{e3}o", "4323002"], + &["RS", "Vicente Dutra", "4323101"], + &["RS", "Victor Graeff", "4323200"], + &["RS", "Vila Flores", "4323309"], + &["RS", "Vila L\u{e2}ngaro", "4323358"], + &["RS", "Vila Maria", "4323408"], + &["RS", "Vila Nova do Sul", "4323457"], + &["RS", "Vista Alegre", "4323507"], + &["RS", "Vista Alegre do Prata", "4323606"], + &["RS", "Vista Ga\u{fa}cha", "4323705"], + &["RS", "Vit\u{f3}ria das Miss\u{f5}es", "4323754"], + &["RS", "Westf\u{e1}lia", "4323770"], + &["RS", "Xangri-l\u{e1}", "4323804"], + &["RO", "Alta Floresta D'Oeste", "1100015"], + &["RO", "Alto Alegre dos Parecis", "1100379"], + &["RO", "Alto Para\u{ed}so", "1100403"], + &["RO", "Alvorada D'Oeste", "1100346"], + &["RO", "Ariquemes", "1100023"], + &["RO", "Buritis", "1100452"], + &["RO", "Cabixi", "1100031"], + &["RO", "Cacaul\u{e2}ndia", "1100601"], + &["RO", "Cacoal", "1100049"], + &["RO", "Campo Novo de Rond\u{f4}nia", "1100700"], + &["RO", "Candeias do Jamari", "1100809"], + &["RO", "Castanheiras", "1100908"], + &["RO", "Cerejeiras", "1100056"], + &["RO", "Chupinguaia", "1100924"], + &["RO", "Colorado do Oeste", "1100064"], + &["RO", "Corumbiara", "1100072"], + &["RO", "Costa Marques", "1100080"], + &["RO", "Cujubim", "1100940"], + &["RO", "Espig\u{e3}o D'Oeste", "1100098"], + &["RO", "Governador Jorge Teixeira", "1101005"], + &["RO", "Guajar\u{e1}-Mirim", "1100106"], + &["RO", "Itapu\u{e3} do Oeste", "1101104"], + &["RO", "Jaru", "1100114"], + &["RO", "Ji-Paran\u{e1}", "1100122"], + &["RO", "Machadinho D'Oeste", "1100130"], + &["RO", "Ministro Andreazza", "1101203"], + &["RO", "Mirante da Serra", "1101302"], + &["RO", "Monte Negro", "1101401"], + &["RO", "Nova Brasil\u{e2}ndia D'Oeste", "1100148"], + &["RO", "Nova Mamor\u{e9}", "1100338"], + &["RO", "Nova Uni\u{e3}o", "1101435"], + &["RO", "Novo Horizonte do Oeste", "1100502"], + &["RO", "Ouro Preto do Oeste", "1100155"], + &["RO", "Parecis", "1101450"], + &["RO", "Pimenta Bueno", "1100189"], + &["RO", "Pimenteiras do Oeste", "1101468"], + &["RO", "Porto Velho", "1100205"], + &["RO", "Presidente M\u{e9}dici", "1100254"], + &["RO", "Primavera de Rond\u{f4}nia", "1101476"], + &["RO", "Rio Crespo", "1100262"], + &["RO", "Rolim de Moura", "1100288"], + &["RO", "Santa Luzia D'Oeste", "1100296"], + &["RO", "S\u{e3}o Felipe D'Oeste", "1101484"], + &["RO", "S\u{e3}o Francisco do Guapor\u{e9}", "1101492"], + &["RO", "S\u{e3}o Miguel do Guapor\u{e9}", "1100320"], + &["RO", "Seringueiras", "1101500"], + &["RO", "Teixeir\u{f3}polis", "1101559"], + &["RO", "Theobroma", "1101609"], + &["RO", "Urup\u{e1}", "1101708"], + &["RO", "Vale do Anari", "1101757"], + &["RO", "Vale do Para\u{ed}so", "1101807"], + &["RO", "Vilhena", "1100304"], + &["RR", "Alto Alegre", "1400050"], + &["RR", "Amajari", "1400027"], + &["RR", "Boa Vista", "1400100"], + &["RR", "Bonfim", "1400159"], + &["RR", "Cant\u{e1}", "1400175"], + &["RR", "Caracara\u{ed}", "1400209"], + &["RR", "Caroebe", "1400233"], + &["RR", "Iracema", "1400282"], + &["RR", "Mucaja\u{ed}", "1400308"], + &["RR", "Normandia", "1400407"], + &["RR", "Pacaraima", "1400456"], + &["RR", "Rorain\u{f3}polis", "1400472"], + &["RR", "S\u{e3}o Jo\u{e3}o da Baliza", "1400506"], + &["RR", "S\u{e3}o Luiz do Anau\u{e1}", "1400605"], + &["RR", "Uiramut\u{e3}", "1400704"], + &["SC", "Abdon Batista", "4200051"], + &["SC", "Abelardo Luz", "4200101"], + &["SC", "Agrol\u{e2}ndia", "4200200"], + &["SC", "Agron\u{f4}mica", "4200309"], + &["SC", "\u{c1}gua Doce", "4200408"], + &["SC", "\u{c1}guas de Chapec\u{f3}", "4200507"], + &["SC", "\u{c1}guas Frias", "4200556"], + &["SC", "\u{c1}guas Mornas", "4200606"], + &["SC", "Alfredo Wagner", "4200705"], + &["SC", "Alto Bela Vista", "4200754"], + &["SC", "Anchieta", "4200804"], + &["SC", "Angelina", "4200903"], + &["SC", "Anita Garibaldi", "4201000"], + &["SC", "Anit\u{e1}polis", "4201109"], + &["SC", "Ant\u{f4}nio Carlos", "4201208"], + &["SC", "Api\u{fa}na", "4201257"], + &["SC", "Arabut\u{e3}", "4201273"], + &["SC", "Araquari", "4201307"], + &["SC", "Ararangu\u{e1}", "4201406"], + &["SC", "Armaz\u{e9}m", "4201505"], + &["SC", "Arroio Trinta", "4201604"], + &["SC", "Arvoredo", "4201653"], + &["SC", "Ascurra", "4201703"], + &["SC", "Atalanta", "4201802"], + &["SC", "Aurora", "4201901"], + &["SC", "Balne\u{e1}rio Arroio do Silva", "4201950"], + &["SC", "Balne\u{e1}rio Barra do Sul", "4202057"], + &["SC", "Balne\u{e1}rio Cambori\u{fa}", "4202008"], + &["SC", "Balne\u{e1}rio Gaivota", "4202073"], + &["SC", "Balne\u{e1}rio Pi\u{e7}arras", "4212809"], + &["SC", "Balne\u{e1}rio Rinc\u{e3}o", "4220000"], + &["SC", "Bandeirante", "4202081"], + &["SC", "Barra Bonita", "4202099"], + &["SC", "Barra Velha", "4202107"], + &["SC", "Bela Vista do Toldo", "4202131"], + &["SC", "Belmonte", "4202156"], + &["SC", "Benedito Novo", "4202206"], + &["SC", "Bigua\u{e7}u", "4202305"], + &["SC", "Blumenau", "4202404"], + &["SC", "Bocaina do Sul", "4202438"], + &["SC", "Bom Jardim da Serra", "4202503"], + &["SC", "Bom Jesus", "4202537"], + &["SC", "Bom Jesus do Oeste", "4202578"], + &["SC", "Bom Retiro", "4202602"], + &["SC", "Bombinhas", "4202453"], + &["SC", "Botuver\u{e1}", "4202701"], + &["SC", "Bra\u{e7}o do Norte", "4202800"], + &["SC", "Bra\u{e7}o do Trombudo", "4202859"], + &["SC", "Brun\u{f3}polis", "4202875"], + &["SC", "Brusque", "4202909"], + &["SC", "Ca\u{e7}ador", "4203006"], + &["SC", "Caibi", "4203105"], + &["SC", "Calmon", "4203154"], + &["SC", "Cambori\u{fa}", "4203204"], + &["SC", "Campo Alegre", "4203303"], + &["SC", "Campo Belo do Sul", "4203402"], + &["SC", "Campo Er\u{ea}", "4203501"], + &["SC", "Campos Novos", "4203600"], + &["SC", "Canelinha", "4203709"], + &["SC", "Canoinhas", "4203808"], + &["SC", "Cap\u{e3}o Alto", "4203253"], + &["SC", "Capinzal", "4203907"], + &["SC", "Capivari de Baixo", "4203956"], + &["SC", "Catanduvas", "4204004"], + &["SC", "Caxambu do Sul", "4204103"], + &["SC", "Celso Ramos", "4204152"], + &["SC", "Cerro Negro", "4204178"], + &["SC", "Chapad\u{e3}o do Lageado", "4204194"], + &["SC", "Chapec\u{f3}", "4204202"], + &["SC", "Cocal do Sul", "4204251"], + &["SC", "Conc\u{f3}rdia", "4204301"], + &["SC", "Cordilheira Alta", "4204350"], + &["SC", "Coronel Freitas", "4204400"], + &["SC", "Coronel Martins", "4204459"], + &["SC", "Correia Pinto", "4204558"], + &["SC", "Corup\u{e1}", "4204509"], + &["SC", "Crici\u{fa}ma", "4204608"], + &["SC", "Cunha Por\u{e3}", "4204707"], + &["SC", "Cunhata\u{ed}", "4204756"], + &["SC", "Curitibanos", "4204806"], + &["SC", "Descanso", "4204905"], + &["SC", "Dion\u{ed}sio Cerqueira", "4205001"], + &["SC", "Dona Emma", "4205100"], + &["SC", "Doutor Pedrinho", "4205159"], + &["SC", "Entre Rios", "4205175"], + &["SC", "Ermo", "4205191"], + &["SC", "Erval Velho", "4205209"], + &["SC", "Faxinal dos Guedes", "4205308"], + &["SC", "Flor do Sert\u{e3}o", "4205357"], + &["SC", "Florian\u{f3}polis", "4205407"], + &["SC", "Formosa do Sul", "4205431"], + &["SC", "Forquilhinha", "4205456"], + &["SC", "Fraiburgo", "4205506"], + &["SC", "Frei Rog\u{e9}rio", "4205555"], + &["SC", "Galv\u{e3}o", "4205605"], + &["SC", "Garopaba", "4205704"], + &["SC", "Garuva", "4205803"], + &["SC", "Gaspar", "4205902"], + &["SC", "Governador Celso Ramos", "4206009"], + &["SC", "Gr\u{e3}o-Par\u{e1}", "4206108"], + &["SC", "Gravatal", "4206207"], + &["SC", "Guabiruba", "4206306"], + &["SC", "Guaraciaba", "4206405"], + &["SC", "Guaramirim", "4206504"], + &["SC", "Guaruj\u{e1} do Sul", "4206603"], + &["SC", "Guatamb\u{fa}", "4206652"], + &["SC", "Herval d'Oeste", "4206702"], + &["SC", "Ibiam", "4206751"], + &["SC", "Ibicar\u{e9}", "4206801"], + &["SC", "Ibirama", "4206900"], + &["SC", "I\u{e7}ara", "4207007"], + &["SC", "Ilhota", "4207106"], + &["SC", "Imaru\u{ed}", "4207205"], + &["SC", "Imbituba", "4207304"], + &["SC", "Imbuia", "4207403"], + &["SC", "Indaial", "4207502"], + &["SC", "Iomer\u{ea}", "4207577"], + &["SC", "Ipira", "4207601"], + &["SC", "Ipor\u{e3} do Oeste", "4207650"], + &["SC", "Ipua\u{e7}u", "4207684"], + &["SC", "Ipumirim", "4207700"], + &["SC", "Iraceminha", "4207759"], + &["SC", "Irani", "4207809"], + &["SC", "Irati", "4207858"], + &["SC", "Irine\u{f3}polis", "4207908"], + &["SC", "It\u{e1}", "4208005"], + &["SC", "Itai\u{f3}polis", "4208104"], + &["SC", "Itaja\u{ed}", "4208203"], + &["SC", "Itapema", "4208302"], + &["SC", "Itapiranga", "4208401"], + &["SC", "Itapo\u{e1}", "4208450"], + &["SC", "Ituporanga", "4208500"], + &["SC", "Jabor\u{e1}", "4208609"], + &["SC", "Jacinto Machado", "4208708"], + &["SC", "Jaguaruna", "4208807"], + &["SC", "Jaragu\u{e1} do Sul", "4208906"], + &["SC", "Jardin\u{f3}polis", "4208955"], + &["SC", "Joa\u{e7}aba", "4209003"], + &["SC", "Joinville", "4209102"], + &["SC", "Jos\u{e9} Boiteux", "4209151"], + &["SC", "Jupi\u{e1}", "4209177"], + &["SC", "Lacerd\u{f3}polis", "4209201"], + &["SC", "Lages", "4209300"], + &["SC", "Laguna", "4209409"], + &["SC", "Lajeado Grande", "4209458"], + &["SC", "Laurentino", "4209508"], + &["SC", "Lauro M\u{fc}ller", "4209607"], + &["SC", "Lebon R\u{e9}gis", "4209706"], + &["SC", "Leoberto Leal", "4209805"], + &["SC", "Lind\u{f3}ia do Sul", "4209854"], + &["SC", "Lontras", "4209904"], + &["SC", "Luiz Alves", "4210001"], + &["SC", "Luzerna", "4210035"], + &["SC", "Macieira", "4210050"], + &["SC", "Mafra", "4210100"], + &["SC", "Major Gercino", "4210209"], + &["SC", "Major Vieira", "4210308"], + &["SC", "Maracaj\u{e1}", "4210407"], + &["SC", "Maravilha", "4210506"], + &["SC", "Marema", "4210555"], + &["SC", "Massaranduba", "4210605"], + &["SC", "Matos Costa", "4210704"], + &["SC", "Meleiro", "4210803"], + &["SC", "Mirim Doce", "4210852"], + &["SC", "Modelo", "4210902"], + &["SC", "Monda\u{ed}", "4211009"], + &["SC", "Monte Carlo", "4211058"], + &["SC", "Monte Castelo", "4211108"], + &["SC", "Morro da Fuma\u{e7}a", "4211207"], + &["SC", "Morro Grande", "4211256"], + &["SC", "Navegantes", "4211306"], + &["SC", "Nova Erechim", "4211405"], + &["SC", "Nova Itaberaba", "4211454"], + &["SC", "Nova Trento", "4211504"], + &["SC", "Nova Veneza", "4211603"], + &["SC", "Novo Horizonte", "4211652"], + &["SC", "Orleans", "4211702"], + &["SC", "Otac\u{ed}lio Costa", "4211751"], + &["SC", "Ouro", "4211801"], + &["SC", "Ouro Verde", "4211850"], + &["SC", "Paial", "4211876"], + &["SC", "Painel", "4211892"], + &["SC", "Palho\u{e7}a", "4211900"], + &["SC", "Palma Sola", "4212007"], + &["SC", "Palmeira", "4212056"], + &["SC", "Palmitos", "4212106"], + &["SC", "Papanduva", "4212205"], + &["SC", "Para\u{ed}so", "4212239"], + &["SC", "Passo de Torres", "4212254"], + &["SC", "Passos Maia", "4212270"], + &["SC", "Paulo Lopes", "4212304"], + &["SC", "Pedras Grandes", "4212403"], + &["SC", "Penha", "4212502"], + &["SC", "Peritiba", "4212601"], + &["SC", "Pescaria Brava", "4212650"], + &["SC", "Petrol\u{e2}ndia", "4212700"], + &["SC", "Pinhalzinho", "4212908"], + &["SC", "Pinheiro Preto", "4213005"], + &["SC", "Piratuba", "4213104"], + &["SC", "Planalto Alegre", "4213153"], + &["SC", "Pomerode", "4213203"], + &["SC", "Ponte Alta", "4213302"], + &["SC", "Ponte Alta do Norte", "4213351"], + &["SC", "Ponte Serrada", "4213401"], + &["SC", "Porto Belo", "4213500"], + &["SC", "Porto Uni\u{e3}o", "4213609"], + &["SC", "Pouso Redondo", "4213708"], + &["SC", "Praia Grande", "4213807"], + &["SC", "Presidente Castello Branco", "4213906"], + &["SC", "Presidente Get\u{fa}lio", "4214003"], + &["SC", "Presidente Nereu", "4214102"], + &["SC", "Princesa", "4214151"], + &["SC", "Quilombo", "4214201"], + &["SC", "Rancho Queimado", "4214300"], + &["SC", "Rio das Antas", "4214409"], + &["SC", "Rio do Campo", "4214508"], + &["SC", "Rio do Oeste", "4214607"], + &["SC", "Rio do Sul", "4214805"], + &["SC", "Rio dos Cedros", "4214706"], + &["SC", "Rio Fortuna", "4214904"], + &["SC", "Rio Negrinho", "4215000"], + &["SC", "Rio Rufino", "4215059"], + &["SC", "Riqueza", "4215075"], + &["SC", "Rodeio", "4215109"], + &["SC", "Romel\u{e2}ndia", "4215208"], + &["SC", "Salete", "4215307"], + &["SC", "Saltinho", "4215356"], + &["SC", "Salto Veloso", "4215406"], + &["SC", "Sang\u{e3}o", "4215455"], + &["SC", "Santa Cec\u{ed}lia", "4215505"], + &["SC", "Santa Helena", "4215554"], + &["SC", "Santa Rosa de Lima", "4215604"], + &["SC", "Santa Rosa do Sul", "4215653"], + &["SC", "Santa Terezinha", "4215679"], + &["SC", "Santa Terezinha do Progresso", "4215687"], + &["SC", "Santiago do Sul", "4215695"], + &["SC", "Santo Amaro da Imperatriz", "4215703"], + &["SC", "S\u{e3}o Bento do Sul", "4215802"], + &["SC", "S\u{e3}o Bernardino", "4215752"], + &["SC", "S\u{e3}o Bonif\u{e1}cio", "4215901"], + &["SC", "S\u{e3}o Carlos", "4216008"], + &["SC", "S\u{e3}o Crist\u{f3}v\u{e3}o do Sul", "4216057"], + &["SC", "S\u{e3}o Domingos", "4216107"], + &["SC", "S\u{e3}o Francisco do Sul", "4216206"], + &["SC", "S\u{e3}o Jo\u{e3}o Batista", "4216305"], + &["SC", "S\u{e3}o Jo\u{e3}o do Itaperi\u{fa}", "4216354"], + &["SC", "S\u{e3}o Jo\u{e3}o do Oeste", "4216255"], + &["SC", "S\u{e3}o Jo\u{e3}o do Sul", "4216404"], + &["SC", "S\u{e3}o Joaquim", "4216503"], + &["SC", "S\u{e3}o Jos\u{e9}", "4216602"], + &["SC", "S\u{e3}o Jos\u{e9} do Cedro", "4216701"], + &["SC", "S\u{e3}o Jos\u{e9} do Cerrito", "4216800"], + &["SC", "S\u{e3}o Louren\u{e7}o do Oeste", "4216909"], + &["SC", "S\u{e3}o Ludgero", "4217006"], + &["SC", "S\u{e3}o Martinho", "4217105"], + &["SC", "S\u{e3}o Miguel da Boa Vista", "4217154"], + &["SC", "S\u{e3}o Miguel do Oeste", "4217204"], + &["SC", "S\u{e3}o Pedro de Alc\u{e2}ntara", "4217253"], + &["SC", "Saudades", "4217303"], + &["SC", "Schroeder", "4217402"], + &["SC", "Seara", "4217501"], + &["SC", "Serra Alta", "4217550"], + &["SC", "Sider\u{f3}polis", "4217600"], + &["SC", "Sombrio", "4217709"], + &["SC", "Sul Brasil", "4217758"], + &["SC", "Tai\u{f3}", "4217808"], + &["SC", "Tangar\u{e1}", "4217907"], + &["SC", "Tigrinhos", "4217956"], + &["SC", "Tijucas", "4218004"], + &["SC", "Timb\u{e9} do Sul", "4218103"], + &["SC", "Timb\u{f3}", "4218202"], + &["SC", "Timb\u{f3} Grande", "4218251"], + &["SC", "Tr\u{ea}s Barras", "4218301"], + &["SC", "Treviso", "4218350"], + &["SC", "Treze de Maio", "4218400"], + &["SC", "Treze T\u{ed}lias", "4218509"], + &["SC", "Trombudo Central", "4218608"], + &["SC", "Tubar\u{e3}o", "4218707"], + &["SC", "Tun\u{e1}polis", "4218756"], + &["SC", "Turvo", "4218806"], + &["SC", "Uni\u{e3}o do Oeste", "4218855"], + &["SC", "Urubici", "4218905"], + &["SC", "Urupema", "4218954"], + &["SC", "Urussanga", "4219002"], + &["SC", "Varge\u{e3}o", "4219101"], + &["SC", "Vargem", "4219150"], + &["SC", "Vargem Bonita", "4219176"], + &["SC", "Vidal Ramos", "4219200"], + &["SC", "Videira", "4219309"], + &["SC", "Vitor Meireles", "4219358"], + &["SC", "Witmarsum", "4219408"], + &["SC", "Xanxer\u{ea}", "4219507"], + &["SC", "Xavantina", "4219606"], + &["SC", "Xaxim", "4219705"], + &["SC", "Zort\u{e9}a", "4219853"], + &["SP", "Adamantina", "3500105"], + &["SP", "Adolfo", "3500204"], + &["SP", "Agua\u{ed}", "3500303"], + &["SP", "\u{c1}guas da Prata", "3500402"], + &["SP", "\u{c1}guas de Lind\u{f3}ia", "3500501"], + &["SP", "\u{c1}guas de Santa B\u{e1}rbara", "3500550"], + &["SP", "\u{c1}guas de S\u{e3}o Pedro", "3500600"], + &["SP", "Agudos", "3500709"], + &["SP", "Alambari", "3500758"], + &["SP", "Alfredo Marcondes", "3500808"], + &["SP", "Altair", "3500907"], + &["SP", "Altin\u{f3}polis", "3501004"], + &["SP", "Alto Alegre", "3501103"], + &["SP", "Alum\u{ed}nio", "3501152"], + &["SP", "\u{c1}lvares Florence", "3501202"], + &["SP", "\u{c1}lvares Machado", "3501301"], + &["SP", "\u{c1}lvaro de Carvalho", "3501400"], + &["SP", "Alvinl\u{e2}ndia", "3501509"], + &["SP", "Americana", "3501608"], + &["SP", "Am\u{e9}rico Brasiliense", "3501707"], + &["SP", "Am\u{e9}rico de Campos", "3501806"], + &["SP", "Amparo", "3501905"], + &["SP", "Anal\u{e2}ndia", "3502002"], + &["SP", "Andradina", "3502101"], + &["SP", "Angatuba", "3502200"], + &["SP", "Anhembi", "3502309"], + &["SP", "Anhumas", "3502408"], + &["SP", "Aparecida", "3502507"], + &["SP", "Aparecida d'Oeste", "3502606"], + &["SP", "Apia\u{ed}", "3502705"], + &["SP", "Ara\u{e7}ariguama", "3502754"], + &["SP", "Ara\u{e7}atuba", "3502804"], + &["SP", "Ara\u{e7}oiaba da Serra", "3502903"], + &["SP", "Aramina", "3503000"], + &["SP", "Arandu", "3503109"], + &["SP", "Arape\u{ed}", "3503158"], + &["SP", "Araraquara", "3503208"], + &["SP", "Araras", "3503307"], + &["SP", "Arco-\u{cd}ris", "3503356"], + &["SP", "Arealva", "3503406"], + &["SP", "Areias", "3503505"], + &["SP", "Arei\u{f3}polis", "3503604"], + &["SP", "Ariranha", "3503703"], + &["SP", "Artur Nogueira", "3503802"], + &["SP", "Aruj\u{e1}", "3503901"], + &["SP", "Asp\u{e1}sia", "3503950"], + &["SP", "Assis", "3504008"], + &["SP", "Atibaia", "3504107"], + &["SP", "Auriflama", "3504206"], + &["SP", "Ava\u{ed}", "3504305"], + &["SP", "Avanhandava", "3504404"], + &["SP", "Avar\u{e9}", "3504503"], + &["SP", "Bady Bassitt", "3504602"], + &["SP", "Balbinos", "3504701"], + &["SP", "B\u{e1}lsamo", "3504800"], + &["SP", "Bananal", "3504909"], + &["SP", "Bar\u{e3}o de Antonina", "3505005"], + &["SP", "Barbosa", "3505104"], + &["SP", "Bariri", "3505203"], + &["SP", "Barra Bonita", "3505302"], + &["SP", "Barra do Chap\u{e9}u", "3505351"], + &["SP", "Barra do Turvo", "3505401"], + &["SP", "Barretos", "3505500"], + &["SP", "Barrinha", "3505609"], + &["SP", "Barueri", "3505708"], + &["SP", "Bastos", "3505807"], + &["SP", "Batatais", "3505906"], + &["SP", "Bauru", "3506003"], + &["SP", "Bebedouro", "3506102"], + &["SP", "Bento de Abreu", "3506201"], + &["SP", "Bernardino de Campos", "3506300"], + &["SP", "Bertioga", "3506359"], + &["SP", "Bilac", "3506409"], + &["SP", "Birigui", "3506508"], + &["SP", "Biritiba Mirim", "3506607"], + &["SP", "Boa Esperan\u{e7}a do Sul", "3506706"], + &["SP", "Bocaina", "3506805"], + &["SP", "Bofete", "3506904"], + &["SP", "Boituva", "3507001"], + &["SP", "Bom Jesus dos Perd\u{f5}es", "3507100"], + &["SP", "Bom Sucesso de Itarar\u{e9}", "3507159"], + &["SP", "Bor\u{e1}", "3507209"], + &["SP", "Borac\u{e9}ia", "3507308"], + &["SP", "Borborema", "3507407"], + &["SP", "Borebi", "3507456"], + &["SP", "Botucatu", "3507506"], + &["SP", "Bragan\u{e7}a Paulista", "3507605"], + &["SP", "Bra\u{fa}na", "3507704"], + &["SP", "Brejo Alegre", "3507753"], + &["SP", "Brodowski", "3507803"], + &["SP", "Brotas", "3507902"], + &["SP", "Buri", "3508009"], + &["SP", "Buritama", "3508108"], + &["SP", "Buritizal", "3508207"], + &["SP", "Cabr\u{e1}lia Paulista", "3508306"], + &["SP", "Cabre\u{fa}va", "3508405"], + &["SP", "Ca\u{e7}apava", "3508504"], + &["SP", "Cachoeira Paulista", "3508603"], + &["SP", "Caconde", "3508702"], + &["SP", "Cafel\u{e2}ndia", "3508801"], + &["SP", "Caiabu", "3508900"], + &["SP", "Caieiras", "3509007"], + &["SP", "Caiu\u{e1}", "3509106"], + &["SP", "Cajamar", "3509205"], + &["SP", "Cajati", "3509254"], + &["SP", "Cajobi", "3509304"], + &["SP", "Cajuru", "3509403"], + &["SP", "Campina do Monte Alegre", "3509452"], + &["SP", "Campinas", "3509502"], + &["SP", "Campo Limpo Paulista", "3509601"], + &["SP", "Campos do Jord\u{e3}o", "3509700"], + &["SP", "Campos Novos Paulista", "3509809"], + &["SP", "Canan\u{e9}ia", "3509908"], + &["SP", "Canas", "3509957"], + &["SP", "C\u{e2}ndido Mota", "3510005"], + &["SP", "C\u{e2}ndido Rodrigues", "3510104"], + &["SP", "Canitar", "3510153"], + &["SP", "Cap\u{e3}o Bonito", "3510203"], + &["SP", "Capela do Alto", "3510302"], + &["SP", "Capivari", "3510401"], + &["SP", "Caraguatatuba", "3510500"], + &["SP", "Carapicu\u{ed}ba", "3510609"], + &["SP", "Cardoso", "3510708"], + &["SP", "Casa Branca", "3510807"], + &["SP", "C\u{e1}ssia dos Coqueiros", "3510906"], + &["SP", "Castilho", "3511003"], + &["SP", "Catanduva", "3511102"], + &["SP", "Catigu\u{e1}", "3511201"], + &["SP", "Cedral", "3511300"], + &["SP", "Cerqueira C\u{e9}sar", "3511409"], + &["SP", "Cerquilho", "3511508"], + &["SP", "Ces\u{e1}rio Lange", "3511607"], + &["SP", "Charqueada", "3511706"], + &["SP", "Chavantes", "3557204"], + &["SP", "Clementina", "3511904"], + &["SP", "Colina", "3512001"], + &["SP", "Col\u{f4}mbia", "3512100"], + &["SP", "Conchal", "3512209"], + &["SP", "Conchas", "3512308"], + &["SP", "Cordeir\u{f3}polis", "3512407"], + &["SP", "Coroados", "3512506"], + &["SP", "Coronel Macedo", "3512605"], + &["SP", "Corumbata\u{ed}", "3512704"], + &["SP", "Cosm\u{f3}polis", "3512803"], + &["SP", "Cosmorama", "3512902"], + &["SP", "Cotia", "3513009"], + &["SP", "Cravinhos", "3513108"], + &["SP", "Cristais Paulista", "3513207"], + &["SP", "Cruz\u{e1}lia", "3513306"], + &["SP", "Cruzeiro", "3513405"], + &["SP", "Cubat\u{e3}o", "3513504"], + &["SP", "Cunha", "3513603"], + &["SP", "Descalvado", "3513702"], + &["SP", "Diadema", "3513801"], + &["SP", "Dirce Reis", "3513850"], + &["SP", "Divinol\u{e2}ndia", "3513900"], + &["SP", "Dobrada", "3514007"], + &["SP", "Dois C\u{f3}rregos", "3514106"], + &["SP", "Dolcin\u{f3}polis", "3514205"], + &["SP", "Dourado", "3514304"], + &["SP", "Dracena", "3514403"], + &["SP", "Duartina", "3514502"], + &["SP", "Dumont", "3514601"], + &["SP", "Echapor\u{e3}", "3514700"], + &["SP", "Eldorado", "3514809"], + &["SP", "Elias Fausto", "3514908"], + &["SP", "Elisi\u{e1}rio", "3514924"], + &["SP", "Emba\u{fa}ba", "3514957"], + &["SP", "Embu das Artes", "3515004"], + &["SP", "Embu-Gua\u{e7}u", "3515103"], + &["SP", "Emilian\u{f3}polis", "3515129"], + &["SP", "Engenheiro Coelho", "3515152"], + &["SP", "Esp\u{ed}rito Santo do Pinhal", "3515186"], + &["SP", "Esp\u{ed}rito Santo do Turvo", "3515194"], + &["SP", "Estiva Gerbi", "3557303"], + &["SP", "Estrela d'Oeste", "3515202"], + &["SP", "Estrela do Norte", "3515301"], + &["SP", "Euclides da Cunha Paulista", "3515350"], + &["SP", "Fartura", "3515400"], + &["SP", "Fernando Prestes", "3515608"], + &["SP", "Fernand\u{f3}polis", "3515509"], + &["SP", "Fern\u{e3}o", "3515657"], + &["SP", "Ferraz de Vasconcelos", "3515707"], + &["SP", "Flora Rica", "3515806"], + &["SP", "Floreal", "3515905"], + &["SP", "Fl\u{f3}rida Paulista", "3516002"], + &["SP", "Flor\u{ed}nea", "3516101"], + &["SP", "Franca", "3516200"], + &["SP", "Francisco Morato", "3516309"], + &["SP", "Franco da Rocha", "3516408"], + &["SP", "Gabriel Monteiro", "3516507"], + &["SP", "G\u{e1}lia", "3516606"], + &["SP", "Gar\u{e7}a", "3516705"], + &["SP", "Gast\u{e3}o Vidigal", "3516804"], + &["SP", "Gavi\u{e3}o Peixoto", "3516853"], + &["SP", "General Salgado", "3516903"], + &["SP", "Getulina", "3517000"], + &["SP", "Glic\u{e9}rio", "3517109"], + &["SP", "Guai\u{e7}ara", "3517208"], + &["SP", "Guaimb\u{ea}", "3517307"], + &["SP", "Gua\u{ed}ra", "3517406"], + &["SP", "Guapia\u{e7}u", "3517505"], + &["SP", "Guapiara", "3517604"], + &["SP", "Guar\u{e1}", "3517703"], + &["SP", "Guara\u{e7}a\u{ed}", "3517802"], + &["SP", "Guaraci", "3517901"], + &["SP", "Guarani d'Oeste", "3518008"], + &["SP", "Guarant\u{e3}", "3518107"], + &["SP", "Guararapes", "3518206"], + &["SP", "Guararema", "3518305"], + &["SP", "Guaratinguet\u{e1}", "3518404"], + &["SP", "Guare\u{ed}", "3518503"], + &["SP", "Guariba", "3518602"], + &["SP", "Guaruj\u{e1}", "3518701"], + &["SP", "Guarulhos", "3518800"], + &["SP", "Guatapar\u{e1}", "3518859"], + &["SP", "Guzol\u{e2}ndia", "3518909"], + &["SP", "Hercul\u{e2}ndia", "3519006"], + &["SP", "Holambra", "3519055"], + &["SP", "Hortol\u{e2}ndia", "3519071"], + &["SP", "Iacanga", "3519105"], + &["SP", "Iacri", "3519204"], + &["SP", "Iaras", "3519253"], + &["SP", "Ibat\u{e9}", "3519303"], + &["SP", "Ibir\u{e1}", "3519402"], + &["SP", "Ibirarema", "3519501"], + &["SP", "Ibitinga", "3519600"], + &["SP", "Ibi\u{fa}na", "3519709"], + &["SP", "Ic\u{e9}m", "3519808"], + &["SP", "Iep\u{ea}", "3519907"], + &["SP", "Igara\u{e7}u do Tiet\u{ea}", "3520004"], + &["SP", "Igarapava", "3520103"], + &["SP", "Igarat\u{e1}", "3520202"], + &["SP", "Iguape", "3520301"], + &["SP", "Ilha Comprida", "3520426"], + &["SP", "Ilha Solteira", "3520442"], + &["SP", "Ilhabela", "3520400"], + &["SP", "Indaiatuba", "3520509"], + &["SP", "Indiana", "3520608"], + &["SP", "Indiapor\u{e3}", "3520707"], + &["SP", "In\u{fa}bia Paulista", "3520806"], + &["SP", "Ipaussu", "3520905"], + &["SP", "Iper\u{f3}", "3521002"], + &["SP", "Ipe\u{fa}na", "3521101"], + &["SP", "Ipigu\u{e1}", "3521150"], + &["SP", "Iporanga", "3521200"], + &["SP", "Ipu\u{e3}", "3521309"], + &["SP", "Iracem\u{e1}polis", "3521408"], + &["SP", "Irapu\u{e3}", "3521507"], + &["SP", "Irapuru", "3521606"], + &["SP", "Itaber\u{e1}", "3521705"], + &["SP", "Ita\u{ed}", "3521804"], + &["SP", "Itajobi", "3521903"], + &["SP", "Itaju", "3522000"], + &["SP", "Itanha\u{e9}m", "3522109"], + &["SP", "Itaoca", "3522158"], + &["SP", "Itapecerica da Serra", "3522208"], + &["SP", "Itapetininga", "3522307"], + &["SP", "Itapeva", "3522406"], + &["SP", "Itapevi", "3522505"], + &["SP", "Itapira", "3522604"], + &["SP", "Itapirapu\u{e3} Paulista", "3522653"], + &["SP", "It\u{e1}polis", "3522703"], + &["SP", "Itaporanga", "3522802"], + &["SP", "Itapu\u{ed}", "3522901"], + &["SP", "Itapura", "3523008"], + &["SP", "Itaquaquecetuba", "3523107"], + &["SP", "Itarar\u{e9}", "3523206"], + &["SP", "Itariri", "3523305"], + &["SP", "Itatiba", "3523404"], + &["SP", "Itatinga", "3523503"], + &["SP", "Itirapina", "3523602"], + &["SP", "Itirapu\u{e3}", "3523701"], + &["SP", "Itobi", "3523800"], + &["SP", "Itu", "3523909"], + &["SP", "Itupeva", "3524006"], + &["SP", "Ituverava", "3524105"], + &["SP", "Jaborandi", "3524204"], + &["SP", "Jaboticabal", "3524303"], + &["SP", "Jacare\u{ed}", "3524402"], + &["SP", "Jaci", "3524501"], + &["SP", "Jacupiranga", "3524600"], + &["SP", "Jaguari\u{fa}na", "3524709"], + &["SP", "Jales", "3524808"], + &["SP", "Jambeiro", "3524907"], + &["SP", "Jandira", "3525003"], + &["SP", "Jardin\u{f3}polis", "3525102"], + &["SP", "Jarinu", "3525201"], + &["SP", "Ja\u{fa}", "3525300"], + &["SP", "Jeriquara", "3525409"], + &["SP", "Joan\u{f3}polis", "3525508"], + &["SP", "Jo\u{e3}o Ramalho", "3525607"], + &["SP", "Jos\u{e9} Bonif\u{e1}cio", "3525706"], + &["SP", "J\u{fa}lio Mesquita", "3525805"], + &["SP", "Jumirim", "3525854"], + &["SP", "Jundia\u{ed}", "3525904"], + &["SP", "Junqueir\u{f3}polis", "3526001"], + &["SP", "Juqui\u{e1}", "3526100"], + &["SP", "Juquitiba", "3526209"], + &["SP", "Lagoinha", "3526308"], + &["SP", "Laranjal Paulista", "3526407"], + &["SP", "Lav\u{ed}nia", "3526506"], + &["SP", "Lavrinhas", "3526605"], + &["SP", "Leme", "3526704"], + &["SP", "Len\u{e7}\u{f3}is Paulista", "3526803"], + &["SP", "Limeira", "3526902"], + &["SP", "Lind\u{f3}ia", "3527009"], + &["SP", "Lins", "3527108"], + &["SP", "Lorena", "3527207"], + &["SP", "Lourdes", "3527256"], + &["SP", "Louveira", "3527306"], + &["SP", "Luc\u{e9}lia", "3527405"], + &["SP", "Lucian\u{f3}polis", "3527504"], + &["SP", "Lu\u{ed}s Ant\u{f4}nio", "3527603"], + &["SP", "Luizi\u{e2}nia", "3527702"], + &["SP", "Lup\u{e9}rcio", "3527801"], + &["SP", "Lut\u{e9}cia", "3527900"], + &["SP", "Macatuba", "3528007"], + &["SP", "Macaubal", "3528106"], + &["SP", "Maced\u{f4}nia", "3528205"], + &["SP", "Magda", "3528304"], + &["SP", "Mairinque", "3528403"], + &["SP", "Mairipor\u{e3}", "3528502"], + &["SP", "Manduri", "3528601"], + &["SP", "Marab\u{e1} Paulista", "3528700"], + &["SP", "Maraca\u{ed}", "3528809"], + &["SP", "Marapoama", "3528858"], + &["SP", "Mari\u{e1}polis", "3528908"], + &["SP", "Mar\u{ed}lia", "3529005"], + &["SP", "Marin\u{f3}polis", "3529104"], + &["SP", "Martin\u{f3}polis", "3529203"], + &["SP", "Mat\u{e3}o", "3529302"], + &["SP", "Mau\u{e1}", "3529401"], + &["SP", "Mendon\u{e7}a", "3529500"], + &["SP", "Meridiano", "3529609"], + &["SP", "Mes\u{f3}polis", "3529658"], + &["SP", "Miguel\u{f3}polis", "3529708"], + &["SP", "Mineiros do Tiet\u{ea}", "3529807"], + &["SP", "Mira Estrela", "3530003"], + &["SP", "Miracatu", "3529906"], + &["SP", "Mirand\u{f3}polis", "3530102"], + &["SP", "Mirante do Paranapanema", "3530201"], + &["SP", "Mirassol", "3530300"], + &["SP", "Mirassol\u{e2}ndia", "3530409"], + &["SP", "Mococa", "3530508"], + &["SP", "Mogi das Cruzes", "3530607"], + &["SP", "Mogi Gua\u{e7}u", "3530706"], + &["SP", "Mogi Mirim", "3530805"], + &["SP", "Mombuca", "3530904"], + &["SP", "Mon\u{e7}\u{f5}es", "3531001"], + &["SP", "Mongagu\u{e1}", "3531100"], + &["SP", "Monte Alegre do Sul", "3531209"], + &["SP", "Monte Alto", "3531308"], + &["SP", "Monte Apraz\u{ed}vel", "3531407"], + &["SP", "Monte Azul Paulista", "3531506"], + &["SP", "Monte Castelo", "3531605"], + &["SP", "Monte Mor", "3531803"], + &["SP", "Monteiro Lobato", "3531704"], + &["SP", "Morro Agudo", "3531902"], + &["SP", "Morungaba", "3532009"], + &["SP", "Motuca", "3532058"], + &["SP", "Murutinga do Sul", "3532108"], + &["SP", "Nantes", "3532157"], + &["SP", "Narandiba", "3532207"], + &["SP", "Natividade da Serra", "3532306"], + &["SP", "Nazar\u{e9} Paulista", "3532405"], + &["SP", "Neves Paulista", "3532504"], + &["SP", "Nhandeara", "3532603"], + &["SP", "Nipo\u{e3}", "3532702"], + &["SP", "Nova Alian\u{e7}a", "3532801"], + &["SP", "Nova Campina", "3532827"], + &["SP", "Nova Cana\u{e3} Paulista", "3532843"], + &["SP", "Nova Castilho", "3532868"], + &["SP", "Nova Europa", "3532900"], + &["SP", "Nova Granada", "3533007"], + &["SP", "Nova Guataporanga", "3533106"], + &["SP", "Nova Independ\u{ea}ncia", "3533205"], + &["SP", "Nova Luzit\u{e2}nia", "3533304"], + &["SP", "Nova Odessa", "3533403"], + &["SP", "Novais", "3533254"], + &["SP", "Novo Horizonte", "3533502"], + &["SP", "Nuporanga", "3533601"], + &["SP", "Ocau\u{e7}u", "3533700"], + &["SP", "\u{d3}leo", "3533809"], + &["SP", "Ol\u{ed}mpia", "3533908"], + &["SP", "Onda Verde", "3534005"], + &["SP", "Oriente", "3534104"], + &["SP", "Orindi\u{fa}va", "3534203"], + &["SP", "Orl\u{e2}ndia", "3534302"], + &["SP", "Osasco", "3534401"], + &["SP", "Oscar Bressane", "3534500"], + &["SP", "Osvaldo Cruz", "3534609"], + &["SP", "Ourinhos", "3534708"], + &["SP", "Ouro Verde", "3534807"], + &["SP", "Ouroeste", "3534757"], + &["SP", "Pacaembu", "3534906"], + &["SP", "Palestina", "3535002"], + &["SP", "Palmares Paulista", "3535101"], + &["SP", "Palmeira d'Oeste", "3535200"], + &["SP", "Palmital", "3535309"], + &["SP", "Panorama", "3535408"], + &["SP", "Paragua\u{e7}u Paulista", "3535507"], + &["SP", "Paraibuna", "3535606"], + &["SP", "Para\u{ed}so", "3535705"], + &["SP", "Paranapanema", "3535804"], + &["SP", "Paranapu\u{e3}", "3535903"], + &["SP", "Parapu\u{e3}", "3536000"], + &["SP", "Pardinho", "3536109"], + &["SP", "Pariquera-A\u{e7}u", "3536208"], + &["SP", "Parisi", "3536257"], + &["SP", "Patroc\u{ed}nio Paulista", "3536307"], + &["SP", "Paulic\u{e9}ia", "3536406"], + &["SP", "Paul\u{ed}nia", "3536505"], + &["SP", "Paulist\u{e2}nia", "3536570"], + &["SP", "Paulo de Faria", "3536604"], + &["SP", "Pederneiras", "3536703"], + &["SP", "Pedra Bela", "3536802"], + &["SP", "Pedran\u{f3}polis", "3536901"], + &["SP", "Pedregulho", "3537008"], + &["SP", "Pedreira", "3537107"], + &["SP", "Pedrinhas Paulista", "3537156"], + &["SP", "Pedro de Toledo", "3537206"], + &["SP", "Pen\u{e1}polis", "3537305"], + &["SP", "Pereira Barreto", "3537404"], + &["SP", "Pereiras", "3537503"], + &["SP", "Peru\u{ed}be", "3537602"], + &["SP", "Piacatu", "3537701"], + &["SP", "Piedade", "3537800"], + &["SP", "Pilar do Sul", "3537909"], + &["SP", "Pindamonhangaba", "3538006"], + &["SP", "Pindorama", "3538105"], + &["SP", "Pinhalzinho", "3538204"], + &["SP", "Piquerobi", "3538303"], + &["SP", "Piquete", "3538501"], + &["SP", "Piracaia", "3538600"], + &["SP", "Piracicaba", "3538709"], + &["SP", "Piraju", "3538808"], + &["SP", "Piraju\u{ed}", "3538907"], + &["SP", "Pirangi", "3539004"], + &["SP", "Pirapora do Bom Jesus", "3539103"], + &["SP", "Pirapozinho", "3539202"], + &["SP", "Pirassununga", "3539301"], + &["SP", "Piratininga", "3539400"], + &["SP", "Pitangueiras", "3539509"], + &["SP", "Planalto", "3539608"], + &["SP", "Platina", "3539707"], + &["SP", "Po\u{e1}", "3539806"], + &["SP", "Poloni", "3539905"], + &["SP", "Pomp\u{e9}ia", "3540002"], + &["SP", "Ponga\u{ed}", "3540101"], + &["SP", "Pontal", "3540200"], + &["SP", "Pontalinda", "3540259"], + &["SP", "Pontes Gestal", "3540309"], + &["SP", "Populina", "3540408"], + &["SP", "Porangaba", "3540507"], + &["SP", "Porto Feliz", "3540606"], + &["SP", "Porto Ferreira", "3540705"], + &["SP", "Potim", "3540754"], + &["SP", "Potirendaba", "3540804"], + &["SP", "Pracinha", "3540853"], + &["SP", "Prad\u{f3}polis", "3540903"], + &["SP", "Praia Grande", "3541000"], + &["SP", "Prat\u{e2}nia", "3541059"], + &["SP", "Presidente Alves", "3541109"], + &["SP", "Presidente Bernardes", "3541208"], + &["SP", "Presidente Epit\u{e1}cio", "3541307"], + &["SP", "Presidente Prudente", "3541406"], + &["SP", "Presidente Venceslau", "3541505"], + &["SP", "Promiss\u{e3}o", "3541604"], + &["SP", "Quadra", "3541653"], + &["SP", "Quat\u{e1}", "3541703"], + &["SP", "Queiroz", "3541802"], + &["SP", "Queluz", "3541901"], + &["SP", "Quintana", "3542008"], + &["SP", "Rafard", "3542107"], + &["SP", "Rancharia", "3542206"], + &["SP", "Reden\u{e7}\u{e3}o da Serra", "3542305"], + &["SP", "Regente Feij\u{f3}", "3542404"], + &["SP", "Regin\u{f3}polis", "3542503"], + &["SP", "Registro", "3542602"], + &["SP", "Restinga", "3542701"], + &["SP", "Ribeira", "3542800"], + &["SP", "Ribeir\u{e3}o Bonito", "3542909"], + &["SP", "Ribeir\u{e3}o Branco", "3543006"], + &["SP", "Ribeir\u{e3}o Corrente", "3543105"], + &["SP", "Ribeir\u{e3}o do Sul", "3543204"], + &["SP", "Ribeir\u{e3}o dos \u{cd}ndios", "3543238"], + &["SP", "Ribeir\u{e3}o Grande", "3543253"], + &["SP", "Ribeir\u{e3}o Pires", "3543303"], + &["SP", "Ribeir\u{e3}o Preto", "3543402"], + &["SP", "Rifaina", "3543600"], + &["SP", "Rinc\u{e3}o", "3543709"], + &["SP", "Rin\u{f3}polis", "3543808"], + &["SP", "Rio Claro", "3543907"], + &["SP", "Rio das Pedras", "3544004"], + &["SP", "Rio Grande da Serra", "3544103"], + &["SP", "Riol\u{e2}ndia", "3544202"], + &["SP", "Riversul", "3543501"], + &["SP", "Rosana", "3544251"], + &["SP", "Roseira", "3544301"], + &["SP", "Rubi\u{e1}cea", "3544400"], + &["SP", "Rubin\u{e9}ia", "3544509"], + &["SP", "Sabino", "3544608"], + &["SP", "Sagres", "3544707"], + &["SP", "Sales", "3544806"], + &["SP", "Sales Oliveira", "3544905"], + &["SP", "Sales\u{f3}polis", "3545001"], + &["SP", "Salmour\u{e3}o", "3545100"], + &["SP", "Saltinho", "3545159"], + &["SP", "Salto", "3545209"], + &["SP", "Salto de Pirapora", "3545308"], + &["SP", "Salto Grande", "3545407"], + &["SP", "Sandovalina", "3545506"], + &["SP", "Santa Ad\u{e9}lia", "3545605"], + &["SP", "Santa Albertina", "3545704"], + &["SP", "Santa B\u{e1}rbara d'Oeste", "3545803"], + &["SP", "Santa Branca", "3546009"], + &["SP", "Santa Clara d'Oeste", "3546108"], + &["SP", "Santa Cruz da Concei\u{e7}\u{e3}o", "3546207"], + &["SP", "Santa Cruz da Esperan\u{e7}a", "3546256"], + &["SP", "Santa Cruz das Palmeiras", "3546306"], + &["SP", "Santa Cruz do Rio Pardo", "3546405"], + &["SP", "Santa Ernestina", "3546504"], + &["SP", "Santa F\u{e9} do Sul", "3546603"], + &["SP", "Santa Gertrudes", "3546702"], + &["SP", "Santa Isabel", "3546801"], + &["SP", "Santa L\u{fa}cia", "3546900"], + &["SP", "Santa Maria da Serra", "3547007"], + &["SP", "Santa Mercedes", "3547106"], + &["SP", "Santa Rita d'Oeste", "3547403"], + &["SP", "Santa Rita do Passa Quatro", "3547502"], + &["SP", "Santa Rosa de Viterbo", "3547601"], + &["SP", "Santa Salete", "3547650"], + &["SP", "Santana da Ponte Pensa", "3547205"], + &["SP", "Santana de Parna\u{ed}ba", "3547304"], + &["SP", "Santo Anast\u{e1}cio", "3547700"], + &["SP", "Santo Andr\u{e9}", "3547809"], + &["SP", "Santo Ant\u{f4}nio da Alegria", "3547908"], + &["SP", "Santo Ant\u{f4}nio de Posse", "3548005"], + &["SP", "Santo Ant\u{f4}nio do Aracangu\u{e1}", "3548054"], + &["SP", "Santo Ant\u{f4}nio do Jardim", "3548104"], + &["SP", "Santo Ant\u{f4}nio do Pinhal", "3548203"], + &["SP", "Santo Expedito", "3548302"], + &["SP", "Sant\u{f3}polis do Aguape\u{ed}", "3548401"], + &["SP", "Santos", "3548500"], + &["SP", "S\u{e3}o Bento do Sapuca\u{ed}", "3548609"], + &["SP", "S\u{e3}o Bernardo do Campo", "3548708"], + &["SP", "S\u{e3}o Caetano do Sul", "3548807"], + &["SP", "S\u{e3}o Carlos", "3548906"], + &["SP", "S\u{e3}o Francisco", "3549003"], + &["SP", "S\u{e3}o Jo\u{e3}o da Boa Vista", "3549102"], + &["SP", "S\u{e3}o Jo\u{e3}o das Duas Pontes", "3549201"], + &["SP", "S\u{e3}o Jo\u{e3}o de Iracema", "3549250"], + &["SP", "S\u{e3}o Jo\u{e3}o do Pau d'Alho", "3549300"], + &["SP", "S\u{e3}o Joaquim da Barra", "3549409"], + &["SP", "S\u{e3}o Jos\u{e9} da Bela Vista", "3549508"], + &["SP", "S\u{e3}o Jos\u{e9} do Barreiro", "3549607"], + &["SP", "S\u{e3}o Jos\u{e9} do Rio Pardo", "3549706"], + &["SP", "S\u{e3}o Jos\u{e9} do Rio Preto", "3549805"], + &["SP", "S\u{e3}o Jos\u{e9} dos Campos", "3549904"], + &["SP", "S\u{e3}o Louren\u{e7}o da Serra", "3549953"], + &["SP", "S\u{e3}o Luiz do Paraitinga", "3550001"], + &["SP", "S\u{e3}o Manuel", "3550100"], + &["SP", "S\u{e3}o Miguel Arcanjo", "3550209"], + &["SP", "S\u{e3}o Paulo", "3550308"], + &["SP", "S\u{e3}o Pedro", "3550407"], + &["SP", "S\u{e3}o Pedro do Turvo", "3550506"], + &["SP", "S\u{e3}o Roque", "3550605"], + &["SP", "S\u{e3}o Sebasti\u{e3}o", "3550704"], + &["SP", "S\u{e3}o Sebasti\u{e3}o da Grama", "3550803"], + &["SP", "S\u{e3}o Sim\u{e3}o", "3550902"], + &["SP", "S\u{e3}o Vicente", "3551009"], + &["SP", "Sarapu\u{ed}", "3551108"], + &["SP", "Sarutai\u{e1}", "3551207"], + &["SP", "Sebastian\u{f3}polis do Sul", "3551306"], + &["SP", "Serra Azul", "3551405"], + &["SP", "Serra Negra", "3551603"], + &["SP", "Serrana", "3551504"], + &["SP", "Sert\u{e3}ozinho", "3551702"], + &["SP", "Sete Barras", "3551801"], + &["SP", "Sever\u{ed}nia", "3551900"], + &["SP", "Silveiras", "3552007"], + &["SP", "Socorro", "3552106"], + &["SP", "Sorocaba", "3552205"], + &["SP", "Sud Mennucci", "3552304"], + &["SP", "Sumar\u{e9}", "3552403"], + &["SP", "Suzan\u{e1}polis", "3552551"], + &["SP", "Suzano", "3552502"], + &["SP", "Tabapu\u{e3}", "3552601"], + &["SP", "Tabatinga", "3552700"], + &["SP", "Tabo\u{e3}o da Serra", "3552809"], + &["SP", "Taciba", "3552908"], + &["SP", "Tagua\u{ed}", "3553005"], + &["SP", "Taia\u{e7}u", "3553104"], + &["SP", "Tai\u{fa}va", "3553203"], + &["SP", "Tamba\u{fa}", "3553302"], + &["SP", "Tanabi", "3553401"], + &["SP", "Tapira\u{ed}", "3553500"], + &["SP", "Tapiratiba", "3553609"], + &["SP", "Taquaral", "3553658"], + &["SP", "Taquaritinga", "3553708"], + &["SP", "Taquarituba", "3553807"], + &["SP", "Taquariva\u{ed}", "3553856"], + &["SP", "Tarabai", "3553906"], + &["SP", "Tarum\u{e3}", "3553955"], + &["SP", "Tatu\u{ed}", "3554003"], + &["SP", "Taubat\u{e9}", "3554102"], + &["SP", "Tejup\u{e1}", "3554201"], + &["SP", "Teodoro Sampaio", "3554300"], + &["SP", "Terra Roxa", "3554409"], + &["SP", "Tiet\u{ea}", "3554508"], + &["SP", "Timburi", "3554607"], + &["SP", "Torre de Pedra", "3554656"], + &["SP", "Torrinha", "3554706"], + &["SP", "Trabiju", "3554755"], + &["SP", "Trememb\u{e9}", "3554805"], + &["SP", "Tr\u{ea}s Fronteiras", "3554904"], + &["SP", "Tuiuti", "3554953"], + &["SP", "Tup\u{e3}", "3555000"], + &["SP", "Tupi Paulista", "3555109"], + &["SP", "Turi\u{fa}ba", "3555208"], + &["SP", "Turmalina", "3555307"], + &["SP", "Ubarana", "3555356"], + &["SP", "Ubatuba", "3555406"], + &["SP", "Ubirajara", "3555505"], + &["SP", "Uchoa", "3555604"], + &["SP", "Uni\u{e3}o Paulista", "3555703"], + &["SP", "Ur\u{e2}nia", "3555802"], + &["SP", "Uru", "3555901"], + &["SP", "Urup\u{ea}s", "3556008"], + &["SP", "Valentim Gentil", "3556107"], + &["SP", "Valinhos", "3556206"], + &["SP", "Valpara\u{ed}so", "3556305"], + &["SP", "Vargem", "3556354"], + &["SP", "Vargem Grande do Sul", "3556404"], + &["SP", "Vargem Grande Paulista", "3556453"], + &["SP", "V\u{e1}rzea Paulista", "3556503"], + &["SP", "Vera Cruz", "3556602"], + &["SP", "Vinhedo", "3556701"], + &["SP", "Viradouro", "3556800"], + &["SP", "Vista Alegre do Alto", "3556909"], + &["SP", "Vit\u{f3}ria Brasil", "3556958"], + &["SP", "Votorantim", "3557006"], + &["SP", "Votuporanga", "3557105"], + &["SP", "Zacarias", "3557154"], + &["SE", "Amparo do S\u{e3}o Francisco", "2800100"], + &["SE", "Aquidab\u{e3}", "2800209"], + &["SE", "Aracaju", "2800308"], + &["SE", "Arau\u{e1}", "2800407"], + &["SE", "Areia Branca", "2800506"], + &["SE", "Barra dos Coqueiros", "2800605"], + &["SE", "Boquim", "2800670"], + &["SE", "Brejo Grande", "2800704"], + &["SE", "Campo do Brito", "2801009"], + &["SE", "Canhoba", "2801108"], + &["SE", "Canind\u{e9} de S\u{e3}o Francisco", "2801207"], + &["SE", "Capela", "2801306"], + &["SE", "Carira", "2801405"], + &["SE", "Carm\u{f3}polis", "2801504"], + &["SE", "Cedro de S\u{e3}o Jo\u{e3}o", "2801603"], + &["SE", "Cristin\u{e1}polis", "2801702"], + &["SE", "Cumbe", "2801900"], + &["SE", "Divina Pastora", "2802007"], + &["SE", "Est\u{e2}ncia", "2802106"], + &["SE", "Feira Nova", "2802205"], + &["SE", "Frei Paulo", "2802304"], + &["SE", "Gararu", "2802403"], + &["SE", "General Maynard", "2802502"], + &["SE", "Graccho Cardoso", "2802601"], + &["SE", "Ilha das Flores", "2802700"], + &["SE", "Indiaroba", "2802809"], + &["SE", "Itabaiana", "2802908"], + &["SE", "Itabaianinha", "2803005"], + &["SE", "Itabi", "2803104"], + &["SE", "Itaporanga d'Ajuda", "2803203"], + &["SE", "Japaratuba", "2803302"], + &["SE", "Japoat\u{e3}", "2803401"], + &["SE", "Lagarto", "2803500"], + &["SE", "Laranjeiras", "2803609"], + &["SE", "Macambira", "2803708"], + &["SE", "Malhada dos Bois", "2803807"], + &["SE", "Malhador", "2803906"], + &["SE", "Maruim", "2804003"], + &["SE", "Moita Bonita", "2804102"], + &["SE", "Monte Alegre de Sergipe", "2804201"], + &["SE", "Muribeca", "2804300"], + &["SE", "Ne\u{f3}polis", "2804409"], + &["SE", "Nossa Senhora Aparecida", "2804458"], + &["SE", "Nossa Senhora da Gl\u{f3}ria", "2804508"], + &["SE", "Nossa Senhora das Dores", "2804607"], + &["SE", "Nossa Senhora de Lourdes", "2804706"], + &["SE", "Nossa Senhora do Socorro", "2804805"], + &["SE", "Pacatuba", "2804904"], + &["SE", "Pedra Mole", "2805000"], + &["SE", "Pedrinhas", "2805109"], + &["SE", "Pinh\u{e3}o", "2805208"], + &["SE", "Pirambu", "2805307"], + &["SE", "Po\u{e7}o Redondo", "2805406"], + &["SE", "Po\u{e7}o Verde", "2805505"], + &["SE", "Porto da Folha", "2805604"], + &["SE", "Propri\u{e1}", "2805703"], + &["SE", "Riach\u{e3}o do Dantas", "2805802"], + &["SE", "Riachuelo", "2805901"], + &["SE", "Ribeir\u{f3}polis", "2806008"], + &["SE", "Ros\u{e1}rio do Catete", "2806107"], + &["SE", "Salgado", "2806206"], + &["SE", "Santa Luzia do Itanhy", "2806305"], + &["SE", "Santa Rosa de Lima", "2806503"], + &["SE", "Santana do S\u{e3}o Francisco", "2806404"], + &["SE", "Santo Amaro das Brotas", "2806602"], + &["SE", "S\u{e3}o Crist\u{f3}v\u{e3}o", "2806701"], + &["SE", "S\u{e3}o Domingos", "2806800"], + &["SE", "S\u{e3}o Francisco", "2806909"], + &["SE", "S\u{e3}o Miguel do Aleixo", "2807006"], + &["SE", "Sim\u{e3}o Dias", "2807105"], + &["SE", "Siriri", "2807204"], + &["SE", "Telha", "2807303"], + &["SE", "Tobias Barreto", "2807402"], + &["SE", "Tomar do Geru", "2807501"], + &["SE", "Umba\u{fa}ba", "2807600"], + &["TO", "Abreul\u{e2}ndia", "1700251"], + &["TO", "Aguiarn\u{f3}polis", "1700301"], + &["TO", "Alian\u{e7}a do Tocantins", "1700350"], + &["TO", "Almas", "1700400"], + &["TO", "Alvorada", "1700707"], + &["TO", "Anan\u{e1}s", "1701002"], + &["TO", "Angico", "1701051"], + &["TO", "Aparecida do Rio Negro", "1701101"], + &["TO", "Aragominas", "1701309"], + &["TO", "Araguacema", "1701903"], + &["TO", "Aragua\u{e7}u", "1702000"], + &["TO", "Aragua\u{ed}na", "1702109"], + &["TO", "Araguan\u{e3}", "1702158"], + &["TO", "Araguatins", "1702208"], + &["TO", "Arapoema", "1702307"], + &["TO", "Arraias", "1702406"], + &["TO", "Augustin\u{f3}polis", "1702554"], + &["TO", "Aurora do Tocantins", "1702703"], + &["TO", "Axix\u{e1} do Tocantins", "1702901"], + &["TO", "Baba\u{e7}ul\u{e2}ndia", "1703008"], + &["TO", "Bandeirantes do Tocantins", "1703057"], + &["TO", "Barra do Ouro", "1703073"], + &["TO", "Barrol\u{e2}ndia", "1703107"], + &["TO", "Bernardo Say\u{e3}o", "1703206"], + &["TO", "Bom Jesus do Tocantins", "1703305"], + &["TO", "Brasil\u{e2}ndia do Tocantins", "1703602"], + &["TO", "Brejinho de Nazar\u{e9}", "1703701"], + &["TO", "Buriti do Tocantins", "1703800"], + &["TO", "Cachoeirinha", "1703826"], + &["TO", "Campos Lindos", "1703842"], + &["TO", "Cariri do Tocantins", "1703867"], + &["TO", "Carmol\u{e2}ndia", "1703883"], + &["TO", "Carrasco Bonito", "1703891"], + &["TO", "Caseara", "1703909"], + &["TO", "Centen\u{e1}rio", "1704105"], + &["TO", "Chapada da Natividade", "1705102"], + &["TO", "Chapada de Areia", "1704600"], + &["TO", "Colinas do Tocantins", "1705508"], + &["TO", "Colm\u{e9}ia", "1716703"], + &["TO", "Combinado", "1705557"], + &["TO", "Concei\u{e7}\u{e3}o do Tocantins", "1705607"], + &["TO", "Couto Magalh\u{e3}es", "1706001"], + &["TO", "Cristal\u{e2}ndia", "1706100"], + &["TO", "Crix\u{e1}s do Tocantins", "1706258"], + &["TO", "Darcin\u{f3}polis", "1706506"], + &["TO", "Dian\u{f3}polis", "1707009"], + &["TO", "Divin\u{f3}polis do Tocantins", "1707108"], + &["TO", "Dois Irm\u{e3}os do Tocantins", "1707207"], + &["TO", "Duer\u{e9}", "1707306"], + &["TO", "Esperantina", "1707405"], + &["TO", "F\u{e1}tima", "1707553"], + &["TO", "Figueir\u{f3}polis", "1707652"], + &["TO", "Filad\u{e9}lfia", "1707702"], + &["TO", "Formoso do Araguaia", "1708205"], + &["TO", "Goianorte", "1708304"], + &["TO", "Goiatins", "1709005"], + &["TO", "Guara\u{ed}", "1709302"], + &["TO", "Gurupi", "1709500"], + &["TO", "Ipueiras", "1709807"], + &["TO", "Itacaj\u{e1}", "1710508"], + &["TO", "Itaguatins", "1710706"], + &["TO", "Itapiratins", "1710904"], + &["TO", "Itapor\u{e3} do Tocantins", "1711100"], + &["TO", "Ja\u{fa} do Tocantins", "1711506"], + &["TO", "Juarina", "1711803"], + &["TO", "Lagoa da Confus\u{e3}o", "1711902"], + &["TO", "Lagoa do Tocantins", "1711951"], + &["TO", "Lajeado", "1712009"], + &["TO", "Lavandeira", "1712157"], + &["TO", "Lizarda", "1712405"], + &["TO", "Luzin\u{f3}polis", "1712454"], + &["TO", "Marian\u{f3}polis do Tocantins", "1712504"], + &["TO", "Mateiros", "1712702"], + &["TO", "Mauril\u{e2}ndia do Tocantins", "1712801"], + &["TO", "Miracema do Tocantins", "1713205"], + &["TO", "Miranorte", "1713304"], + &["TO", "Monte do Carmo", "1713601"], + &["TO", "Monte Santo do Tocantins", "1713700"], + &["TO", "Muricil\u{e2}ndia", "1713957"], + &["TO", "Natividade", "1714203"], + &["TO", "Nazar\u{e9}", "1714302"], + &["TO", "Nova Olinda", "1714880"], + &["TO", "Nova Rosal\u{e2}ndia", "1715002"], + &["TO", "Novo Acordo", "1715101"], + &["TO", "Novo Alegre", "1715150"], + &["TO", "Novo Jardim", "1715259"], + &["TO", "Oliveira de F\u{e1}tima", "1715507"], + &["TO", "Palmas", "1721000"], + &["TO", "Palmeirante", "1715705"], + &["TO", "Palmeiras do Tocantins", "1713809"], + &["TO", "Palmeir\u{f3}polis", "1715754"], + &["TO", "Para\u{ed}so do Tocantins", "1716109"], + &["TO", "Paran\u{e3}", "1716208"], + &["TO", "Pau D'Arco", "1716307"], + &["TO", "Pedro Afonso", "1716505"], + &["TO", "Peixe", "1716604"], + &["TO", "Pequizeiro", "1716653"], + &["TO", "Pindorama do Tocantins", "1717008"], + &["TO", "Piraqu\u{ea}", "1717206"], + &["TO", "Pium", "1717503"], + &["TO", "Ponte Alta do Bom Jesus", "1717800"], + &["TO", "Ponte Alta do Tocantins", "1717909"], + &["TO", "Porto Alegre do Tocantins", "1718006"], + &["TO", "Porto Nacional", "1718204"], + &["TO", "Praia Norte", "1718303"], + &["TO", "Presidente Kennedy", "1718402"], + &["TO", "Pugmil", "1718451"], + &["TO", "Recursol\u{e2}ndia", "1718501"], + &["TO", "Riachinho", "1718550"], + &["TO", "Rio da Concei\u{e7}\u{e3}o", "1718659"], + &["TO", "Rio dos Bois", "1718709"], + &["TO", "Rio Sono", "1718758"], + &["TO", "Sampaio", "1718808"], + &["TO", "Sandol\u{e2}ndia", "1718840"], + &["TO", "Santa F\u{e9} do Araguaia", "1718865"], + &["TO", "Santa Maria do Tocantins", "1718881"], + &["TO", "Santa Rita do Tocantins", "1718899"], + &["TO", "Santa Rosa do Tocantins", "1718907"], + &["TO", "Santa Tereza do Tocantins", "1719004"], + &["TO", "Santa Terezinha do Tocantins", "1720002"], + &["TO", "S\u{e3}o Bento do Tocantins", "1720101"], + &["TO", "S\u{e3}o F\u{e9}lix do Tocantins", "1720150"], + &["TO", "S\u{e3}o Miguel do Tocantins", "1720200"], + &["TO", "S\u{e3}o Salvador do Tocantins", "1720259"], + &["TO", "S\u{e3}o Sebasti\u{e3}o do Tocantins", "1720309"], + &["TO", "S\u{e3}o Val\u{e9}rio", "1720499"], + &["TO", "Silvan\u{f3}polis", "1720655"], + &["TO", "S\u{ed}tio Novo do Tocantins", "1720804"], + &["TO", "Sucupira", "1720853"], + &["TO", "Taboc\u{e3}o", "1708254"], + &["TO", "Taguatinga", "1720903"], + &["TO", "Taipas do Tocantins", "1720937"], + &["TO", "Talism\u{e3}", "1720978"], + &["TO", "Tocant\u{ed}nia", "1721109"], + &["TO", "Tocantin\u{f3}polis", "1721208"], + &["TO", "Tupirama", "1721257"], + &["TO", "Tupiratins", "1721307"], + &["TO", "Wanderl\u{e2}ndia", "1722081"], + &["TO", "Xambio\u{e1}", "1722107"], +]; + +static MUNICIPALITIES_GROUPS: &[(&str, &[usize])] = &[ + ("AC", &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21]), + ("AL", &[22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123]), + ("AP", &[124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139]), + ("AM", &[140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201]), + ("BA", &[202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, 443, 444, 445, 446, 447, 448, 449, 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, 495, 496, 497, 498, 499, 500, 501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, 519, 520, 521, 522, 523, 524, 525, 526, 527, 528, 529, 530, 531, 532, 533, 534, 535, 536, 537, 538, 539, 540, 541, 542, 543, 544, 545, 546, 547, 548, 549, 550, 551, 552, 553, 554, 555, 556, 557, 558, 559, 560, 561, 562, 563, 564, 565, 566, 567, 568, 569, 570, 571, 572, 573, 574, 575, 576, 577, 578, 579, 580, 581, 582, 583, 584, 585, 586, 587, 588, 589, 590, 591, 592, 593, 594, 595, 596, 597, 598, 599, 600, 601, 602, 603, 604, 605, 606, 607, 608, 609, 610, 611, 612, 613, 614, 615, 616, 617, 618]), + ("CE", &[619, 620, 621, 622, 623, 624, 625, 626, 627, 628, 629, 630, 631, 632, 633, 634, 635, 636, 637, 638, 639, 640, 641, 642, 643, 644, 645, 646, 647, 648, 649, 650, 651, 652, 653, 654, 655, 656, 657, 658, 659, 660, 661, 662, 663, 664, 665, 666, 667, 668, 669, 670, 671, 672, 673, 674, 675, 676, 677, 678, 679, 680, 681, 682, 683, 684, 685, 686, 687, 688, 689, 690, 691, 692, 693, 694, 695, 696, 697, 698, 699, 700, 701, 702, 703, 704, 705, 706, 707, 708, 709, 710, 711, 712, 713, 714, 715, 716, 717, 718, 719, 720, 721, 722, 723, 724, 725, 726, 727, 728, 729, 730, 731, 732, 733, 734, 735, 736, 737, 738, 739, 740, 741, 742, 743, 744, 745, 746, 747, 748, 749, 750, 751, 752, 753, 754, 755, 756, 757, 758, 759, 760, 761, 762, 763, 764, 765, 766, 767, 768, 769, 770, 771, 772, 773, 774, 775, 776, 777, 778, 779, 780, 781, 782, 783, 784, 785, 786, 787, 788, 789, 790, 791, 792, 793, 794, 795, 796, 797, 798, 799, 800, 801, 802]), + ("DF", &[803]), + ("ES", &[804, 805, 806, 807, 808, 809, 810, 811, 812, 813, 814, 815, 816, 817, 818, 819, 820, 821, 822, 823, 824, 825, 826, 827, 828, 829, 830, 831, 832, 833, 834, 835, 836, 837, 838, 839, 840, 841, 842, 843, 844, 845, 846, 847, 848, 849, 850, 851, 852, 853, 854, 855, 856, 857, 858, 859, 860, 861, 862, 863, 864, 865, 866, 867, 868, 869, 870, 871, 872, 873, 874, 875, 876, 877, 878, 879, 880, 881]), + ("GO", &[882, 883, 884, 885, 886, 887, 888, 889, 890, 891, 892, 893, 894, 895, 896, 897, 898, 899, 900, 901, 902, 903, 904, 905, 906, 907, 908, 909, 910, 911, 912, 913, 914, 915, 916, 917, 918, 919, 920, 921, 922, 923, 924, 925, 926, 927, 928, 929, 930, 931, 932, 933, 934, 935, 936, 937, 938, 939, 940, 941, 942, 943, 944, 945, 946, 947, 948, 949, 950, 951, 952, 953, 954, 955, 956, 957, 958, 959, 960, 961, 962, 963, 964, 965, 966, 967, 968, 969, 970, 971, 972, 973, 974, 975, 976, 977, 978, 979, 980, 981, 982, 983, 984, 985, 986, 987, 988, 989, 990, 991, 992, 993, 994, 995, 996, 997, 998, 999, 1000, 1001, 1002, 1003, 1004, 1005, 1006, 1007, 1008, 1009, 1010, 1011, 1012, 1013, 1014, 1015, 1016, 1017, 1018, 1019, 1020, 1021, 1022, 1023, 1024, 1025, 1026, 1027, 1028, 1029, 1030, 1031, 1032, 1033, 1034, 1035, 1036, 1037, 1038, 1039, 1040, 1041, 1042, 1043, 1044, 1045, 1046, 1047, 1048, 1049, 1050, 1051, 1052, 1053, 1054, 1055, 1056, 1057, 1058, 1059, 1060, 1061, 1062, 1063, 1064, 1065, 1066, 1067, 1068, 1069, 1070, 1071, 1072, 1073, 1074, 1075, 1076, 1077, 1078, 1079, 1080, 1081, 1082, 1083, 1084, 1085, 1086, 1087, 1088, 1089, 1090, 1091, 1092, 1093, 1094, 1095, 1096, 1097, 1098, 1099, 1100, 1101, 1102, 1103, 1104, 1105, 1106, 1107, 1108, 1109, 1110, 1111, 1112, 1113, 1114, 1115, 1116, 1117, 1118, 1119, 1120, 1121, 1122, 1123, 1124, 1125, 1126, 1127]), + ("MA", &[1128, 1129, 1130, 1131, 1132, 1133, 1134, 1135, 1136, 1137, 1138, 1139, 1140, 1141, 1142, 1143, 1144, 1145, 1146, 1147, 1148, 1149, 1150, 1151, 1152, 1153, 1154, 1155, 1156, 1157, 1158, 1159, 1160, 1161, 1162, 1163, 1164, 1165, 1166, 1167, 1168, 1169, 1170, 1171, 1172, 1173, 1174, 1175, 1176, 1177, 1178, 1179, 1180, 1181, 1182, 1183, 1184, 1185, 1186, 1187, 1188, 1189, 1190, 1191, 1192, 1193, 1194, 1195, 1196, 1197, 1198, 1199, 1200, 1201, 1202, 1203, 1204, 1205, 1206, 1207, 1208, 1209, 1210, 1211, 1212, 1213, 1214, 1215, 1216, 1217, 1218, 1219, 1220, 1221, 1222, 1223, 1224, 1225, 1226, 1227, 1228, 1229, 1230, 1231, 1232, 1233, 1234, 1235, 1236, 1237, 1238, 1239, 1240, 1241, 1242, 1243, 1244, 1245, 1246, 1247, 1248, 1249, 1250, 1251, 1252, 1253, 1254, 1255, 1256, 1257, 1258, 1259, 1260, 1261, 1262, 1263, 1264, 1265, 1266, 1267, 1268, 1269, 1270, 1271, 1272, 1273, 1274, 1275, 1276, 1277, 1278, 1279, 1280, 1281, 1282, 1283, 1284, 1285, 1286, 1287, 1288, 1289, 1290, 1291, 1292, 1293, 1294, 1295, 1296, 1297, 1298, 1299, 1300, 1301, 1302, 1303, 1304, 1305, 1306, 1307, 1308, 1309, 1310, 1311, 1312, 1313, 1314, 1315, 1316, 1317, 1318, 1319, 1320, 1321, 1322, 1323, 1324, 1325, 1326, 1327, 1328, 1329, 1330, 1331, 1332, 1333, 1334, 1335, 1336, 1337, 1338, 1339, 1340, 1341, 1342, 1343, 1344]), + ("MT", &[1345, 1346, 1347, 1348, 1349, 1350, 1351, 1352, 1353, 1354, 1355, 1356, 1357, 1358, 1359, 1360, 1361, 1362, 1363, 1364, 1365, 1366, 1367, 1368, 1369, 1370, 1371, 1372, 1373, 1374, 1375, 1376, 1377, 1378, 1379, 1380, 1381, 1382, 1383, 1384, 1385, 1386, 1387, 1388, 1389, 1390, 1391, 1392, 1393, 1394, 1395, 1396, 1397, 1398, 1399, 1400, 1401, 1402, 1403, 1404, 1405, 1406, 1407, 1408, 1409, 1410, 1411, 1412, 1413, 1414, 1415, 1416, 1417, 1418, 1419, 1420, 1421, 1422, 1423, 1424, 1425, 1426, 1427, 1428, 1429, 1430, 1431, 1432, 1433, 1434, 1435, 1436, 1437, 1438, 1439, 1440, 1441, 1442, 1443, 1444, 1445, 1446, 1447, 1448, 1449, 1450, 1451, 1452, 1453, 1454, 1455, 1456, 1457, 1458, 1459, 1460, 1461, 1462, 1463, 1464, 1465, 1466, 1467, 1468, 1469, 1470, 1471, 1472, 1473, 1474, 1475, 1476, 1477, 1478, 1479, 1480, 1481, 1482, 1483, 1484, 1485, 1486]), + ("MS", &[1487, 1488, 1489, 1490, 1491, 1492, 1493, 1494, 1495, 1496, 1497, 1498, 1499, 1500, 1501, 1502, 1503, 1504, 1505, 1506, 1507, 1508, 1509, 1510, 1511, 1512, 1513, 1514, 1515, 1516, 1517, 1518, 1519, 1520, 1521, 1522, 1523, 1524, 1525, 1526, 1527, 1528, 1529, 1530, 1531, 1532, 1533, 1534, 1535, 1536, 1537, 1538, 1539, 1540, 1541, 1542, 1543, 1544, 1545, 1546, 1547, 1548, 1549, 1550, 1551, 1552, 1553, 1554, 1555, 1556, 1557, 1558, 1559, 1560, 1561, 1562, 1563, 1564, 1565]), + ("MG", &[1566, 1567, 1568, 1569, 1570, 1571, 1572, 1573, 1574, 1575, 1576, 1577, 1578, 1579, 1580, 1581, 1582, 1583, 1584, 1585, 1586, 1587, 1588, 1589, 1590, 1591, 1592, 1593, 1594, 1595, 1596, 1597, 1598, 1599, 1600, 1601, 1602, 1603, 1604, 1605, 1606, 1607, 1608, 1609, 1610, 1611, 1612, 1613, 1614, 1615, 1616, 1617, 1618, 1619, 1620, 1621, 1622, 1623, 1624, 1625, 1626, 1627, 1628, 1629, 1630, 1631, 1632, 1633, 1634, 1635, 1636, 1637, 1638, 1639, 1640, 1641, 1642, 1643, 1644, 1645, 1646, 1647, 1648, 1649, 1650, 1651, 1652, 1653, 1654, 1655, 1656, 1657, 1658, 1659, 1660, 1661, 1662, 1663, 1664, 1665, 1666, 1667, 1668, 1669, 1670, 1671, 1672, 1673, 1674, 1675, 1676, 1677, 1678, 1679, 1680, 1681, 1682, 1683, 1684, 1685, 1686, 1687, 1688, 1689, 1690, 1691, 1692, 1693, 1694, 1695, 1696, 1697, 1698, 1699, 1700, 1701, 1702, 1703, 1704, 1705, 1706, 1707, 1708, 1709, 1710, 1711, 1712, 1713, 1714, 1715, 1716, 1717, 1718, 1719, 1720, 1721, 1722, 1723, 1724, 1725, 1726, 1727, 1728, 1729, 1730, 1731, 1732, 1733, 1734, 1735, 1736, 1737, 1738, 1739, 1740, 1741, 1742, 1743, 1744, 1745, 1746, 1747, 1748, 1749, 1750, 1751, 1752, 1753, 1754, 1755, 1756, 1757, 1758, 1759, 1760, 1761, 1762, 1763, 1764, 1765, 1766, 1767, 1768, 1769, 1770, 1771, 1772, 1773, 1774, 1775, 1776, 1777, 1778, 1779, 1780, 1781, 1782, 1783, 1784, 1785, 1786, 1787, 1788, 1789, 1790, 1791, 1792, 1793, 1794, 1795, 1796, 1797, 1798, 1799, 1800, 1801, 1802, 1803, 1804, 1805, 1806, 1807, 1808, 1809, 1810, 1811, 1812, 1813, 1814, 1815, 1816, 1817, 1818, 1819, 1820, 1821, 1822, 1823, 1824, 1825, 1826, 1827, 1828, 1829, 1830, 1831, 1832, 1833, 1834, 1835, 1836, 1837, 1838, 1839, 1840, 1841, 1842, 1843, 1844, 1845, 1846, 1847, 1848, 1849, 1850, 1851, 1852, 1853, 1854, 1855, 1856, 1857, 1858, 1859, 1860, 1861, 1862, 1863, 1864, 1865, 1866, 1867, 1868, 1869, 1870, 1871, 1872, 1873, 1874, 1875, 1876, 1877, 1878, 1879, 1880, 1881, 1882, 1883, 1884, 1885, 1886, 1887, 1888, 1889, 1890, 1891, 1892, 1893, 1894, 1895, 1896, 1897, 1898, 1899, 1900, 1901, 1902, 1903, 1904, 1905, 1906, 1907, 1908, 1909, 1910, 1911, 1912, 1913, 1914, 1915, 1916, 1917, 1918, 1919, 1920, 1921, 1922, 1923, 1924, 1925, 1926, 1927, 1928, 1929, 1930, 1931, 1932, 1933, 1934, 1935, 1936, 1937, 1938, 1939, 1940, 1941, 1942, 1943, 1944, 1945, 1946, 1947, 1948, 1949, 1950, 1951, 1952, 1953, 1954, 1955, 1956, 1957, 1958, 1959, 1960, 1961, 1962, 1963, 1964, 1965, 1966, 1967, 1968, 1969, 1970, 1971, 1972, 1973, 1974, 1975, 1976, 1977, 1978, 1979, 1980, 1981, 1982, 1983, 1984, 1985, 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020, 2021, 2022, 2023, 2024, 2025, 2026, 2027, 2028, 2029, 2030, 2031, 2032, 2033, 2034, 2035, 2036, 2037, 2038, 2039, 2040, 2041, 2042, 2043, 2044, 2045, 2046, 2047, 2048, 2049, 2050, 2051, 2052, 2053, 2054, 2055, 2056, 2057, 2058, 2059, 2060, 2061, 2062, 2063, 2064, 2065, 2066, 2067, 2068, 2069, 2070, 2071, 2072, 2073, 2074, 2075, 2076, 2077, 2078, 2079, 2080, 2081, 2082, 2083, 2084, 2085, 2086, 2087, 2088, 2089, 2090, 2091, 2092, 2093, 2094, 2095, 2096, 2097, 2098, 2099, 2100, 2101, 2102, 2103, 2104, 2105, 2106, 2107, 2108, 2109, 2110, 2111, 2112, 2113, 2114, 2115, 2116, 2117, 2118, 2119, 2120, 2121, 2122, 2123, 2124, 2125, 2126, 2127, 2128, 2129, 2130, 2131, 2132, 2133, 2134, 2135, 2136, 2137, 2138, 2139, 2140, 2141, 2142, 2143, 2144, 2145, 2146, 2147, 2148, 2149, 2150, 2151, 2152, 2153, 2154, 2155, 2156, 2157, 2158, 2159, 2160, 2161, 2162, 2163, 2164, 2165, 2166, 2167, 2168, 2169, 2170, 2171, 2172, 2173, 2174, 2175, 2176, 2177, 2178, 2179, 2180, 2181, 2182, 2183, 2184, 2185, 2186, 2187, 2188, 2189, 2190, 2191, 2192, 2193, 2194, 2195, 2196, 2197, 2198, 2199, 2200, 2201, 2202, 2203, 2204, 2205, 2206, 2207, 2208, 2209, 2210, 2211, 2212, 2213, 2214, 2215, 2216, 2217, 2218, 2219, 2220, 2221, 2222, 2223, 2224, 2225, 2226, 2227, 2228, 2229, 2230, 2231, 2232, 2233, 2234, 2235, 2236, 2237, 2238, 2239, 2240, 2241, 2242, 2243, 2244, 2245, 2246, 2247, 2248, 2249, 2250, 2251, 2252, 2253, 2254, 2255, 2256, 2257, 2258, 2259, 2260, 2261, 2262, 2263, 2264, 2265, 2266, 2267, 2268, 2269, 2270, 2271, 2272, 2273, 2274, 2275, 2276, 2277, 2278, 2279, 2280, 2281, 2282, 2283, 2284, 2285, 2286, 2287, 2288, 2289, 2290, 2291, 2292, 2293, 2294, 2295, 2296, 2297, 2298, 2299, 2300, 2301, 2302, 2303, 2304, 2305, 2306, 2307, 2308, 2309, 2310, 2311, 2312, 2313, 2314, 2315, 2316, 2317, 2318, 2319, 2320, 2321, 2322, 2323, 2324, 2325, 2326, 2327, 2328, 2329, 2330, 2331, 2332, 2333, 2334, 2335, 2336, 2337, 2338, 2339, 2340, 2341, 2342, 2343, 2344, 2345, 2346, 2347, 2348, 2349, 2350, 2351, 2352, 2353, 2354, 2355, 2356, 2357, 2358, 2359, 2360, 2361, 2362, 2363, 2364, 2365, 2366, 2367, 2368, 2369, 2370, 2371, 2372, 2373, 2374, 2375, 2376, 2377, 2378, 2379, 2380, 2381, 2382, 2383, 2384, 2385, 2386, 2387, 2388, 2389, 2390, 2391, 2392, 2393, 2394, 2395, 2396, 2397, 2398, 2399, 2400, 2401, 2402, 2403, 2404, 2405, 2406, 2407, 2408, 2409, 2410, 2411, 2412, 2413, 2414, 2415, 2416, 2417, 2418]), + ("PA", &[2419, 2420, 2421, 2422, 2423, 2424, 2425, 2426, 2427, 2428, 2429, 2430, 2431, 2432, 2433, 2434, 2435, 2436, 2437, 2438, 2439, 2440, 2441, 2442, 2443, 2444, 2445, 2446, 2447, 2448, 2449, 2450, 2451, 2452, 2453, 2454, 2455, 2456, 2457, 2458, 2459, 2460, 2461, 2462, 2463, 2464, 2465, 2466, 2467, 2468, 2469, 2470, 2471, 2472, 2473, 2474, 2475, 2476, 2477, 2478, 2479, 2480, 2481, 2482, 2483, 2484, 2485, 2486, 2487, 2488, 2489, 2490, 2491, 2492, 2493, 2494, 2495, 2496, 2497, 2498, 2499, 2500, 2501, 2502, 2503, 2504, 2505, 2506, 2507, 2508, 2509, 2510, 2511, 2512, 2513, 2514, 2515, 2516, 2517, 2518, 2519, 2520, 2521, 2522, 2523, 2524, 2525, 2526, 2527, 2528, 2529, 2530, 2531, 2532, 2533, 2534, 2535, 2536, 2537, 2538, 2539, 2540, 2541, 2542, 2543, 2544, 2545, 2546, 2547, 2548, 2549, 2550, 2551, 2552, 2553, 2554, 2555, 2556, 2557, 2558, 2559, 2560, 2561, 2562]), + ("PB", &[2563, 2564, 2565, 2566, 2567, 2568, 2569, 2570, 2571, 2572, 2573, 2574, 2575, 2576, 2577, 2578, 2579, 2580, 2581, 2582, 2583, 2584, 2585, 2586, 2587, 2588, 2589, 2590, 2591, 2592, 2593, 2594, 2595, 2596, 2597, 2598, 2599, 2600, 2601, 2602, 2603, 2604, 2605, 2606, 2607, 2608, 2609, 2610, 2611, 2612, 2613, 2614, 2615, 2616, 2617, 2618, 2619, 2620, 2621, 2622, 2623, 2624, 2625, 2626, 2627, 2628, 2629, 2630, 2631, 2632, 2633, 2634, 2635, 2636, 2637, 2638, 2639, 2640, 2641, 2642, 2643, 2644, 2645, 2646, 2647, 2648, 2649, 2650, 2651, 2652, 2653, 2654, 2655, 2656, 2657, 2658, 2659, 2660, 2661, 2662, 2663, 2664, 2665, 2666, 2667, 2668, 2669, 2670, 2671, 2672, 2673, 2674, 2675, 2676, 2677, 2678, 2679, 2680, 2681, 2682, 2683, 2684, 2685, 2686, 2687, 2688, 2689, 2690, 2691, 2692, 2693, 2694, 2695, 2696, 2697, 2698, 2699, 2700, 2701, 2702, 2703, 2704, 2705, 2706, 2707, 2708, 2709, 2710, 2711, 2712, 2713, 2714, 2715, 2716, 2717, 2718, 2719, 2720, 2721, 2722, 2723, 2724, 2725, 2726, 2727, 2728, 2729, 2730, 2731, 2732, 2733, 2734, 2735, 2736, 2737, 2738, 2739, 2740, 2741, 2742, 2743, 2744, 2745, 2746, 2747, 2748, 2749, 2750, 2751, 2752, 2753, 2754, 2755, 2756, 2757, 2758, 2759, 2760, 2761, 2762, 2763, 2764, 2765, 2766, 2767, 2768, 2769, 2770, 2771, 2772, 2773, 2774, 2775, 2776, 2777, 2778, 2779, 2780, 2781, 2782, 2783, 2784, 2785]), + ("PR", &[2786, 2787, 2788, 2789, 2790, 2791, 2792, 2793, 2794, 2795, 2796, 2797, 2798, 2799, 2800, 2801, 2802, 2803, 2804, 2805, 2806, 2807, 2808, 2809, 2810, 2811, 2812, 2813, 2814, 2815, 2816, 2817, 2818, 2819, 2820, 2821, 2822, 2823, 2824, 2825, 2826, 2827, 2828, 2829, 2830, 2831, 2832, 2833, 2834, 2835, 2836, 2837, 2838, 2839, 2840, 2841, 2842, 2843, 2844, 2845, 2846, 2847, 2848, 2849, 2850, 2851, 2852, 2853, 2854, 2855, 2856, 2857, 2858, 2859, 2860, 2861, 2862, 2863, 2864, 2865, 2866, 2867, 2868, 2869, 2870, 2871, 2872, 2873, 2874, 2875, 2876, 2877, 2878, 2879, 2880, 2881, 2882, 2883, 2884, 2885, 2886, 2887, 2888, 2889, 2890, 2891, 2892, 2893, 2894, 2895, 2896, 2897, 2898, 2899, 2900, 2901, 2902, 2903, 2904, 2905, 2906, 2907, 2908, 2909, 2910, 2911, 2912, 2913, 2914, 2915, 2916, 2917, 2918, 2919, 2920, 2921, 2922, 2923, 2924, 2925, 2926, 2927, 2928, 2929, 2930, 2931, 2932, 2933, 2934, 2935, 2936, 2937, 2938, 2939, 2940, 2941, 2942, 2943, 2944, 2945, 2946, 2947, 2948, 2949, 2950, 2951, 2952, 2953, 2954, 2955, 2956, 2957, 2958, 2959, 2960, 2961, 2962, 2963, 2964, 2965, 2966, 2967, 2968, 2969, 2970, 2971, 2972, 2973, 2974, 2975, 2976, 2977, 2978, 2979, 2980, 2981, 2982, 2983, 2984, 2985, 2986, 2987, 2988, 2989, 2990, 2991, 2992, 2993, 2994, 2995, 2996, 2997, 2998, 2999, 3000, 3001, 3002, 3003, 3004, 3005, 3006, 3007, 3008, 3009, 3010, 3011, 3012, 3013, 3014, 3015, 3016, 3017, 3018, 3019, 3020, 3021, 3022, 3023, 3024, 3025, 3026, 3027, 3028, 3029, 3030, 3031, 3032, 3033, 3034, 3035, 3036, 3037, 3038, 3039, 3040, 3041, 3042, 3043, 3044, 3045, 3046, 3047, 3048, 3049, 3050, 3051, 3052, 3053, 3054, 3055, 3056, 3057, 3058, 3059, 3060, 3061, 3062, 3063, 3064, 3065, 3066, 3067, 3068, 3069, 3070, 3071, 3072, 3073, 3074, 3075, 3076, 3077, 3078, 3079, 3080, 3081, 3082, 3083, 3084, 3085, 3086, 3087, 3088, 3089, 3090, 3091, 3092, 3093, 3094, 3095, 3096, 3097, 3098, 3099, 3100, 3101, 3102, 3103, 3104, 3105, 3106, 3107, 3108, 3109, 3110, 3111, 3112, 3113, 3114, 3115, 3116, 3117, 3118, 3119, 3120, 3121, 3122, 3123, 3124, 3125, 3126, 3127, 3128, 3129, 3130, 3131, 3132, 3133, 3134, 3135, 3136, 3137, 3138, 3139, 3140, 3141, 3142, 3143, 3144, 3145, 3146, 3147, 3148, 3149, 3150, 3151, 3152, 3153, 3154, 3155, 3156, 3157, 3158, 3159, 3160, 3161, 3162, 3163, 3164, 3165, 3166, 3167, 3168, 3169, 3170, 3171, 3172, 3173, 3174, 3175, 3176, 3177, 3178, 3179, 3180, 3181, 3182, 3183, 3184]), + ("PE", &[3185, 3186, 3187, 3188, 3189, 3190, 3191, 3192, 3193, 3194, 3195, 3196, 3197, 3198, 3199, 3200, 3201, 3202, 3203, 3204, 3205, 3206, 3207, 3208, 3209, 3210, 3211, 3212, 3213, 3214, 3215, 3216, 3217, 3218, 3219, 3220, 3221, 3222, 3223, 3224, 3225, 3226, 3227, 3228, 3229, 3230, 3231, 3232, 3233, 3234, 3235, 3236, 3237, 3238, 3239, 3240, 3241, 3242, 3243, 3244, 3245, 3246, 3247, 3248, 3249, 3250, 3251, 3252, 3253, 3254, 3255, 3256, 3257, 3258, 3259, 3260, 3261, 3262, 3263, 3264, 3265, 3266, 3267, 3268, 3269, 3270, 3271, 3272, 3273, 3274, 3275, 3276, 3277, 3278, 3279, 3280, 3281, 3282, 3283, 3284, 3285, 3286, 3287, 3288, 3289, 3290, 3291, 3292, 3293, 3294, 3295, 3296, 3297, 3298, 3299, 3300, 3301, 3302, 3303, 3304, 3305, 3306, 3307, 3308, 3309, 3310, 3311, 3312, 3313, 3314, 3315, 3316, 3317, 3318, 3319, 3320, 3321, 3322, 3323, 3324, 3325, 3326, 3327, 3328, 3329, 3330, 3331, 3332, 3333, 3334, 3335, 3336, 3337, 3338, 3339, 3340, 3341, 3342, 3343, 3344, 3345, 3346, 3347, 3348, 3349, 3350, 3351, 3352, 3353, 3354, 3355, 3356, 3357, 3358, 3359, 3360, 3361, 3362, 3363, 3364, 3365, 3366, 3367, 3368, 3369]), + ("PI", &[3370, 3371, 3372, 3373, 3374, 3375, 3376, 3377, 3378, 3379, 3380, 3381, 3382, 3383, 3384, 3385, 3386, 3387, 3388, 3389, 3390, 3391, 3392, 3393, 3394, 3395, 3396, 3397, 3398, 3399, 3400, 3401, 3402, 3403, 3404, 3405, 3406, 3407, 3408, 3409, 3410, 3411, 3412, 3413, 3414, 3415, 3416, 3417, 3418, 3419, 3420, 3421, 3422, 3423, 3424, 3425, 3426, 3427, 3428, 3429, 3430, 3431, 3432, 3433, 3434, 3435, 3436, 3437, 3438, 3439, 3440, 3441, 3442, 3443, 3444, 3445, 3446, 3447, 3448, 3449, 3450, 3451, 3452, 3453, 3454, 3455, 3456, 3457, 3458, 3459, 3460, 3461, 3462, 3463, 3464, 3465, 3466, 3467, 3468, 3469, 3470, 3471, 3472, 3473, 3474, 3475, 3476, 3477, 3478, 3479, 3480, 3481, 3482, 3483, 3484, 3485, 3486, 3487, 3488, 3489, 3490, 3491, 3492, 3493, 3494, 3495, 3496, 3497, 3498, 3499, 3500, 3501, 3502, 3503, 3504, 3505, 3506, 3507, 3508, 3509, 3510, 3511, 3512, 3513, 3514, 3515, 3516, 3517, 3518, 3519, 3520, 3521, 3522, 3523, 3524, 3525, 3526, 3527, 3528, 3529, 3530, 3531, 3532, 3533, 3534, 3535, 3536, 3537, 3538, 3539, 3540, 3541, 3542, 3543, 3544, 3545, 3546, 3547, 3548, 3549, 3550, 3551, 3552, 3553, 3554, 3555, 3556, 3557, 3558, 3559, 3560, 3561, 3562, 3563, 3564, 3565, 3566, 3567, 3568, 3569, 3570, 3571, 3572, 3573, 3574, 3575, 3576, 3577, 3578, 3579, 3580, 3581, 3582, 3583, 3584, 3585, 3586, 3587, 3588, 3589, 3590, 3591, 3592, 3593]), + ("RJ", &[3594, 3595, 3596, 3597, 3598, 3599, 3600, 3601, 3602, 3603, 3604, 3605, 3606, 3607, 3608, 3609, 3610, 3611, 3612, 3613, 3614, 3615, 3616, 3617, 3618, 3619, 3620, 3621, 3622, 3623, 3624, 3625, 3626, 3627, 3628, 3629, 3630, 3631, 3632, 3633, 3634, 3635, 3636, 3637, 3638, 3639, 3640, 3641, 3642, 3643, 3644, 3645, 3646, 3647, 3648, 3649, 3650, 3651, 3652, 3653, 3654, 3655, 3656, 3657, 3658, 3659, 3660, 3661, 3662, 3663, 3664, 3665, 3666, 3667, 3668, 3669, 3670, 3671, 3672, 3673, 3674, 3675, 3676, 3677, 3678, 3679, 3680, 3681, 3682, 3683, 3684, 3685]), + ("RN", &[3686, 3687, 3688, 3689, 3690, 3691, 3692, 3693, 3694, 3695, 3696, 3697, 3698, 3699, 3700, 3701, 3702, 3703, 3704, 3705, 3706, 3707, 3708, 3709, 3710, 3711, 3712, 3713, 3714, 3715, 3716, 3717, 3718, 3719, 3720, 3721, 3722, 3723, 3724, 3725, 3726, 3727, 3728, 3729, 3730, 3731, 3732, 3733, 3734, 3735, 3736, 3737, 3738, 3739, 3740, 3741, 3742, 3743, 3744, 3745, 3746, 3747, 3748, 3749, 3750, 3751, 3752, 3753, 3754, 3755, 3756, 3757, 3758, 3759, 3760, 3761, 3762, 3763, 3764, 3765, 3766, 3767, 3768, 3769, 3770, 3771, 3772, 3773, 3774, 3775, 3776, 3777, 3778, 3779, 3780, 3781, 3782, 3783, 3784, 3785, 3786, 3787, 3788, 3789, 3790, 3791, 3792, 3793, 3794, 3795, 3796, 3797, 3798, 3799, 3800, 3801, 3802, 3803, 3804, 3805, 3806, 3807, 3808, 3809, 3810, 3811, 3812, 3813, 3814, 3815, 3816, 3817, 3818, 3819, 3820, 3821, 3822, 3823, 3824, 3825, 3826, 3827, 3828, 3829, 3830, 3831, 3832, 3833, 3834, 3835, 3836, 3837, 3838, 3839, 3840, 3841, 3842, 3843, 3844, 3845, 3846, 3847, 3848, 3849, 3850, 3851, 3852]), + ("RS", &[3853, 3854, 3855, 3856, 3857, 3858, 3859, 3860, 3861, 3862, 3863, 3864, 3865, 3866, 3867, 3868, 3869, 3870, 3871, 3872, 3873, 3874, 3875, 3876, 3877, 3878, 3879, 3880, 3881, 3882, 3883, 3884, 3885, 3886, 3887, 3888, 3889, 3890, 3891, 3892, 3893, 3894, 3895, 3896, 3897, 3898, 3899, 3900, 3901, 3902, 3903, 3904, 3905, 3906, 3907, 3908, 3909, 3910, 3911, 3912, 3913, 3914, 3915, 3916, 3917, 3918, 3919, 3920, 3921, 3922, 3923, 3924, 3925, 3926, 3927, 3928, 3929, 3930, 3931, 3932, 3933, 3934, 3935, 3936, 3937, 3938, 3939, 3940, 3941, 3942, 3943, 3944, 3945, 3946, 3947, 3948, 3949, 3950, 3951, 3952, 3953, 3954, 3955, 3956, 3957, 3958, 3959, 3960, 3961, 3962, 3963, 3964, 3965, 3966, 3967, 3968, 3969, 3970, 3971, 3972, 3973, 3974, 3975, 3976, 3977, 3978, 3979, 3980, 3981, 3982, 3983, 3984, 3985, 3986, 3987, 3988, 3989, 3990, 3991, 3992, 3993, 3994, 3995, 3996, 3997, 3998, 3999, 4000, 4001, 4002, 4003, 4004, 4005, 4006, 4007, 4008, 4009, 4010, 4011, 4012, 4013, 4014, 4015, 4016, 4017, 4018, 4019, 4020, 4021, 4022, 4023, 4024, 4025, 4026, 4027, 4028, 4029, 4030, 4031, 4032, 4033, 4034, 4035, 4036, 4037, 4038, 4039, 4040, 4041, 4042, 4043, 4044, 4045, 4046, 4047, 4048, 4049, 4050, 4051, 4052, 4053, 4054, 4055, 4056, 4057, 4058, 4059, 4060, 4061, 4062, 4063, 4064, 4065, 4066, 4067, 4068, 4069, 4070, 4071, 4072, 4073, 4074, 4075, 4076, 4077, 4078, 4079, 4080, 4081, 4082, 4083, 4084, 4085, 4086, 4087, 4088, 4089, 4090, 4091, 4092, 4093, 4094, 4095, 4096, 4097, 4098, 4099, 4100, 4101, 4102, 4103, 4104, 4105, 4106, 4107, 4108, 4109, 4110, 4111, 4112, 4113, 4114, 4115, 4116, 4117, 4118, 4119, 4120, 4121, 4122, 4123, 4124, 4125, 4126, 4127, 4128, 4129, 4130, 4131, 4132, 4133, 4134, 4135, 4136, 4137, 4138, 4139, 4140, 4141, 4142, 4143, 4144, 4145, 4146, 4147, 4148, 4149, 4150, 4151, 4152, 4153, 4154, 4155, 4156, 4157, 4158, 4159, 4160, 4161, 4162, 4163, 4164, 4165, 4166, 4167, 4168, 4169, 4170, 4171, 4172, 4173, 4174, 4175, 4176, 4177, 4178, 4179, 4180, 4181, 4182, 4183, 4184, 4185, 4186, 4187, 4188, 4189, 4190, 4191, 4192, 4193, 4194, 4195, 4196, 4197, 4198, 4199, 4200, 4201, 4202, 4203, 4204, 4205, 4206, 4207, 4208, 4209, 4210, 4211, 4212, 4213, 4214, 4215, 4216, 4217, 4218, 4219, 4220, 4221, 4222, 4223, 4224, 4225, 4226, 4227, 4228, 4229, 4230, 4231, 4232, 4233, 4234, 4235, 4236, 4237, 4238, 4239, 4240, 4241, 4242, 4243, 4244, 4245, 4246, 4247, 4248, 4249, 4250, 4251, 4252, 4253, 4254, 4255, 4256, 4257, 4258, 4259, 4260, 4261, 4262, 4263, 4264, 4265, 4266, 4267, 4268, 4269, 4270, 4271, 4272, 4273, 4274, 4275, 4276, 4277, 4278, 4279, 4280, 4281, 4282, 4283, 4284, 4285, 4286, 4287, 4288, 4289, 4290, 4291, 4292, 4293, 4294, 4295, 4296, 4297, 4298, 4299, 4300, 4301, 4302, 4303, 4304, 4305, 4306, 4307, 4308, 4309, 4310, 4311, 4312, 4313, 4314, 4315, 4316, 4317, 4318, 4319, 4320, 4321, 4322, 4323, 4324, 4325, 4326, 4327, 4328, 4329, 4330, 4331, 4332, 4333, 4334, 4335, 4336, 4337, 4338, 4339, 4340, 4341, 4342, 4343, 4344, 4345, 4346, 4347, 4348, 4349]), + ("RO", &[4350, 4351, 4352, 4353, 4354, 4355, 4356, 4357, 4358, 4359, 4360, 4361, 4362, 4363, 4364, 4365, 4366, 4367, 4368, 4369, 4370, 4371, 4372, 4373, 4374, 4375, 4376, 4377, 4378, 4379, 4380, 4381, 4382, 4383, 4384, 4385, 4386, 4387, 4388, 4389, 4390, 4391, 4392, 4393, 4394, 4395, 4396, 4397, 4398, 4399, 4400, 4401]), + ("RR", &[4402, 4403, 4404, 4405, 4406, 4407, 4408, 4409, 4410, 4411, 4412, 4413, 4414, 4415, 4416]), + ("SC", &[4417, 4418, 4419, 4420, 4421, 4422, 4423, 4424, 4425, 4426, 4427, 4428, 4429, 4430, 4431, 4432, 4433, 4434, 4435, 4436, 4437, 4438, 4439, 4440, 4441, 4442, 4443, 4444, 4445, 4446, 4447, 4448, 4449, 4450, 4451, 4452, 4453, 4454, 4455, 4456, 4457, 4458, 4459, 4460, 4461, 4462, 4463, 4464, 4465, 4466, 4467, 4468, 4469, 4470, 4471, 4472, 4473, 4474, 4475, 4476, 4477, 4478, 4479, 4480, 4481, 4482, 4483, 4484, 4485, 4486, 4487, 4488, 4489, 4490, 4491, 4492, 4493, 4494, 4495, 4496, 4497, 4498, 4499, 4500, 4501, 4502, 4503, 4504, 4505, 4506, 4507, 4508, 4509, 4510, 4511, 4512, 4513, 4514, 4515, 4516, 4517, 4518, 4519, 4520, 4521, 4522, 4523, 4524, 4525, 4526, 4527, 4528, 4529, 4530, 4531, 4532, 4533, 4534, 4535, 4536, 4537, 4538, 4539, 4540, 4541, 4542, 4543, 4544, 4545, 4546, 4547, 4548, 4549, 4550, 4551, 4552, 4553, 4554, 4555, 4556, 4557, 4558, 4559, 4560, 4561, 4562, 4563, 4564, 4565, 4566, 4567, 4568, 4569, 4570, 4571, 4572, 4573, 4574, 4575, 4576, 4577, 4578, 4579, 4580, 4581, 4582, 4583, 4584, 4585, 4586, 4587, 4588, 4589, 4590, 4591, 4592, 4593, 4594, 4595, 4596, 4597, 4598, 4599, 4600, 4601, 4602, 4603, 4604, 4605, 4606, 4607, 4608, 4609, 4610, 4611, 4612, 4613, 4614, 4615, 4616, 4617, 4618, 4619, 4620, 4621, 4622, 4623, 4624, 4625, 4626, 4627, 4628, 4629, 4630, 4631, 4632, 4633, 4634, 4635, 4636, 4637, 4638, 4639, 4640, 4641, 4642, 4643, 4644, 4645, 4646, 4647, 4648, 4649, 4650, 4651, 4652, 4653, 4654, 4655, 4656, 4657, 4658, 4659, 4660, 4661, 4662, 4663, 4664, 4665, 4666, 4667, 4668, 4669, 4670, 4671, 4672, 4673, 4674, 4675, 4676, 4677, 4678, 4679, 4680, 4681, 4682, 4683, 4684, 4685, 4686, 4687, 4688, 4689, 4690, 4691, 4692, 4693, 4694, 4695, 4696, 4697, 4698, 4699, 4700, 4701, 4702, 4703, 4704, 4705, 4706, 4707, 4708, 4709, 4710, 4711]), + ("SP", &[4712, 4713, 4714, 4715, 4716, 4717, 4718, 4719, 4720, 4721, 4722, 4723, 4724, 4725, 4726, 4727, 4728, 4729, 4730, 4731, 4732, 4733, 4734, 4735, 4736, 4737, 4738, 4739, 4740, 4741, 4742, 4743, 4744, 4745, 4746, 4747, 4748, 4749, 4750, 4751, 4752, 4753, 4754, 4755, 4756, 4757, 4758, 4759, 4760, 4761, 4762, 4763, 4764, 4765, 4766, 4767, 4768, 4769, 4770, 4771, 4772, 4773, 4774, 4775, 4776, 4777, 4778, 4779, 4780, 4781, 4782, 4783, 4784, 4785, 4786, 4787, 4788, 4789, 4790, 4791, 4792, 4793, 4794, 4795, 4796, 4797, 4798, 4799, 4800, 4801, 4802, 4803, 4804, 4805, 4806, 4807, 4808, 4809, 4810, 4811, 4812, 4813, 4814, 4815, 4816, 4817, 4818, 4819, 4820, 4821, 4822, 4823, 4824, 4825, 4826, 4827, 4828, 4829, 4830, 4831, 4832, 4833, 4834, 4835, 4836, 4837, 4838, 4839, 4840, 4841, 4842, 4843, 4844, 4845, 4846, 4847, 4848, 4849, 4850, 4851, 4852, 4853, 4854, 4855, 4856, 4857, 4858, 4859, 4860, 4861, 4862, 4863, 4864, 4865, 4866, 4867, 4868, 4869, 4870, 4871, 4872, 4873, 4874, 4875, 4876, 4877, 4878, 4879, 4880, 4881, 4882, 4883, 4884, 4885, 4886, 4887, 4888, 4889, 4890, 4891, 4892, 4893, 4894, 4895, 4896, 4897, 4898, 4899, 4900, 4901, 4902, 4903, 4904, 4905, 4906, 4907, 4908, 4909, 4910, 4911, 4912, 4913, 4914, 4915, 4916, 4917, 4918, 4919, 4920, 4921, 4922, 4923, 4924, 4925, 4926, 4927, 4928, 4929, 4930, 4931, 4932, 4933, 4934, 4935, 4936, 4937, 4938, 4939, 4940, 4941, 4942, 4943, 4944, 4945, 4946, 4947, 4948, 4949, 4950, 4951, 4952, 4953, 4954, 4955, 4956, 4957, 4958, 4959, 4960, 4961, 4962, 4963, 4964, 4965, 4966, 4967, 4968, 4969, 4970, 4971, 4972, 4973, 4974, 4975, 4976, 4977, 4978, 4979, 4980, 4981, 4982, 4983, 4984, 4985, 4986, 4987, 4988, 4989, 4990, 4991, 4992, 4993, 4994, 4995, 4996, 4997, 4998, 4999, 5000, 5001, 5002, 5003, 5004, 5005, 5006, 5007, 5008, 5009, 5010, 5011, 5012, 5013, 5014, 5015, 5016, 5017, 5018, 5019, 5020, 5021, 5022, 5023, 5024, 5025, 5026, 5027, 5028, 5029, 5030, 5031, 5032, 5033, 5034, 5035, 5036, 5037, 5038, 5039, 5040, 5041, 5042, 5043, 5044, 5045, 5046, 5047, 5048, 5049, 5050, 5051, 5052, 5053, 5054, 5055, 5056, 5057, 5058, 5059, 5060, 5061, 5062, 5063, 5064, 5065, 5066, 5067, 5068, 5069, 5070, 5071, 5072, 5073, 5074, 5075, 5076, 5077, 5078, 5079, 5080, 5081, 5082, 5083, 5084, 5085, 5086, 5087, 5088, 5089, 5090, 5091, 5092, 5093, 5094, 5095, 5096, 5097, 5098, 5099, 5100, 5101, 5102, 5103, 5104, 5105, 5106, 5107, 5108, 5109, 5110, 5111, 5112, 5113, 5114, 5115, 5116, 5117, 5118, 5119, 5120, 5121, 5122, 5123, 5124, 5125, 5126, 5127, 5128, 5129, 5130, 5131, 5132, 5133, 5134, 5135, 5136, 5137, 5138, 5139, 5140, 5141, 5142, 5143, 5144, 5145, 5146, 5147, 5148, 5149, 5150, 5151, 5152, 5153, 5154, 5155, 5156, 5157, 5158, 5159, 5160, 5161, 5162, 5163, 5164, 5165, 5166, 5167, 5168, 5169, 5170, 5171, 5172, 5173, 5174, 5175, 5176, 5177, 5178, 5179, 5180, 5181, 5182, 5183, 5184, 5185, 5186, 5187, 5188, 5189, 5190, 5191, 5192, 5193, 5194, 5195, 5196, 5197, 5198, 5199, 5200, 5201, 5202, 5203, 5204, 5205, 5206, 5207, 5208, 5209, 5210, 5211, 5212, 5213, 5214, 5215, 5216, 5217, 5218, 5219, 5220, 5221, 5222, 5223, 5224, 5225, 5226, 5227, 5228, 5229, 5230, 5231, 5232, 5233, 5234, 5235, 5236, 5237, 5238, 5239, 5240, 5241, 5242, 5243, 5244, 5245, 5246, 5247, 5248, 5249, 5250, 5251, 5252, 5253, 5254, 5255, 5256, 5257, 5258, 5259, 5260, 5261, 5262, 5263, 5264, 5265, 5266, 5267, 5268, 5269, 5270, 5271, 5272, 5273, 5274, 5275, 5276, 5277, 5278, 5279, 5280, 5281, 5282, 5283, 5284, 5285, 5286, 5287, 5288, 5289, 5290, 5291, 5292, 5293, 5294, 5295, 5296, 5297, 5298, 5299, 5300, 5301, 5302, 5303, 5304, 5305, 5306, 5307, 5308, 5309, 5310, 5311, 5312, 5313, 5314, 5315, 5316, 5317, 5318, 5319, 5320, 5321, 5322, 5323, 5324, 5325, 5326, 5327, 5328, 5329, 5330, 5331, 5332, 5333, 5334, 5335, 5336, 5337, 5338, 5339, 5340, 5341, 5342, 5343, 5344, 5345, 5346, 5347, 5348, 5349, 5350, 5351, 5352, 5353, 5354, 5355, 5356]), + ("SE", &[5357, 5358, 5359, 5360, 5361, 5362, 5363, 5364, 5365, 5366, 5367, 5368, 5369, 5370, 5371, 5372, 5373, 5374, 5375, 5376, 5377, 5378, 5379, 5380, 5381, 5382, 5383, 5384, 5385, 5386, 5387, 5388, 5389, 5390, 5391, 5392, 5393, 5394, 5395, 5396, 5397, 5398, 5399, 5400, 5401, 5402, 5403, 5404, 5405, 5406, 5407, 5408, 5409, 5410, 5411, 5412, 5413, 5414, 5415, 5416, 5417, 5418, 5419, 5420, 5421, 5422, 5423, 5424, 5425, 5426, 5427, 5428, 5429, 5430, 5431]), + ("TO", &[5432, 5433, 5434, 5435, 5436, 5437, 5438, 5439, 5440, 5441, 5442, 5443, 5444, 5445, 5446, 5447, 5448, 5449, 5450, 5451, 5452, 5453, 5454, 5455, 5456, 5457, 5458, 5459, 5460, 5461, 5462, 5463, 5464, 5465, 5466, 5467, 5468, 5469, 5470, 5471, 5472, 5473, 5474, 5475, 5476, 5477, 5478, 5479, 5480, 5481, 5482, 5483, 5484, 5485, 5486, 5487, 5488, 5489, 5490, 5491, 5492, 5493, 5494, 5495, 5496, 5497, 5498, 5499, 5500, 5501, 5502, 5503, 5504, 5505, 5506, 5507, 5508, 5509, 5510, 5511, 5512, 5513, 5514, 5515, 5516, 5517, 5518, 5519, 5520, 5521, 5522, 5523, 5524, 5525, 5526, 5527, 5528, 5529, 5530, 5531, 5532, 5533, 5534, 5535, 5536, 5537, 5538, 5539, 5540, 5541, 5542, 5543, 5544, 5545, 5546, 5547, 5548, 5549, 5550, 5551, 5552, 5553, 5554, 5555, 5556, 5557, 5558, 5559, 5560, 5561, 5562, 5563, 5564, 5565, 5566, 5567, 5568, 5569, 5570]), +]; + +static MUNICIPALITIES_ORDER: &[usize] = &[882, 1566, 883, 1567, 2419, 619, 202, 203, 2786, 4417, 2420, 4418, 1568, 3185, 5432, 1569, 1128, 204, 2421, 620, 621, 3686, 3370, 3853, 622, 1345, 0, 884, 1570, 4712, 885, 4713, 2787, 205, 3186, 3687, 804, 1129, 3187, 2422, 3188, 3371, 4419, 4420, 2423, 1346, 1571, 22, 2563, 3372, 1487, 1572, 4421, 1130, 805, 206, 886, 887, 3688, 3189, 3854, 4714, 1573, 3190, 4715, 4422, 4716, 4717, 4718, 1574, 4423, 888, 4424, 1575, 3855, 4719, 2788, 806, 2564, 5433, 1576, 207, 623, 1577, 3856, 1578, 2565, 2566, 2567, 3191, 3373, 208, 4720, 1579, 1131, 624, 2568, 1488, 209, 1132, 3857, 807, 3858, 3374, 3859, 1580, 2424, 3689, 889, 1581, 808, 4721, 1582, 4425, 2569, 2570, 3192, 5434, 210, 5435, 2425, 1583, 3690, 2789, 3860, 890, 1584, 3861, 1585, 1347, 4350, 4722, 2426, 1133, 2790, 625, 1586, 3193, 4723, 3862, 4402, 4724, 1134, 1135, 4351, 1348, 4426, 1349, 1587, 3691, 3863, 1350, 891, 1588, 3375, 1351, 2791, 4352, 892, 2792, 1136, 2793, 1589, 809, 626, 1352, 2794, 3376, 4725, 140, 1590, 4726, 4727, 4728, 4729, 1591, 3864, 5436, 4353, 1592, 3377, 893, 2795, 4403, 1489, 124, 1137, 2796, 3194, 3865, 894, 3378, 1138, 211, 141, 212, 213, 4730, 895, 4731, 4732, 3866, 627, 896, 2571, 4733, 5357, 1593, 2797, 23, 214, 2798, 2427, 1139, 4734, 142, 5437, 2428, 897, 2429, 1140, 1490, 1491, 810, 4427, 215, 2799, 216, 1594, 4735, 3867, 1595, 4736, 1596, 1492, 3195, 4428, 217, 3379, 5438, 3692, 3594, 218, 2800, 898, 4737, 4738, 899, 3380, 4429, 4430, 143, 3868, 219, 2801, 628, 3381, 220, 1597, 4431, 1598, 221, 1493, 3693, 2802, 3869, 1599, 2572, 4739, 4740, 900, 901, 5439, 1494, 3595, 811, 1353, 4741, 1141, 4432, 3694, 222, 902, 223, 2803, 144, 629, 5358, 1495, 630, 4433, 2573, 1600, 5359, 4742, 224, 631, 225, 4743, 226, 1601, 632, 3196, 4744, 812, 903, 1602, 904, 905, 5440, 5441, 5442, 1354, 5443, 1355, 1142, 5444, 906, 1603, 5445, 1143, 1496, 227, 3870, 1144, 4745, 4746, 1604, 4747, 24, 5446, 1605, 2804, 1606, 2805, 1607, 2806, 1356, 4434, 2574, 4435, 4748, 4749, 633, 1145, 3871, 634, 3197, 3596, 2575, 2807, 228, 3872, 635, 229, 5360, 2808, 1608, 1609, 1610, 4750, 1611, 3198, 1612, 3597, 4751, 2576, 3695, 5361, 2577, 2578, 4752, 4753, 1357, 907, 3696, 1613, 1614, 1615, 1358, 4354, 4754, 2809, 3598, 4436, 636, 3382, 2579, 3383, 3384, 3599, 5447, 3873, 3874, 3875, 3876, 3877, 3878, 4437, 4755, 908, 4756, 4438, 3879, 4439, 4757, 2810, 637, 4758, 1, 2811, 3697, 2580, 3385, 1616, 2812, 25, 2813, 145, 4440, 1617, 4759, 813, 5448, 2430, 1618, 3880, 3881, 230, 4760, 909, 638, 4441, 2431, 5449, 146, 4761, 4762, 4763, 2432, 3386, 910, 1146, 5450, 5451, 1147, 1148, 1149, 1150, 4764, 1619, 3882, 2433, 2581, 3698, 231, 2434, 232, 3387, 639, 814, 4765, 1620, 911, 4442, 4443, 4444, 4445, 4446, 3883, 4447, 2814, 4766, 1151, 1621, 640, 4767, 2582, 1622, 1623, 4448, 1497, 2815, 5452, 2435, 233, 3884, 4768, 1624, 3885, 1152, 1359, 1625, 3886, 2583, 3699, 1626, 641, 4769, 2816, 2436, 3700, 147, 4770, 234, 4449, 4771, 3388, 235, 3199, 2584, 2585, 26, 815, 27, 2586, 1360, 4772, 236, 1153, 1361, 3887, 2817, 237, 5453, 3600, 3888, 3889, 3890, 238, 4773, 5362, 3891, 1627, 3601, 4450, 2818, 3892, 3389, 642, 239, 3390, 148, 1154, 3200, 4774, 4775, 643, 240, 912, 3391, 241, 242, 5454, 644, 3893, 1628, 4776, 4777, 1498, 28, 3392, 4778, 1499, 645, 4779, 2587, 4780, 646, 647, 1500, 2819, 913, 1629, 1155, 2820, 3393, 4451, 1156, 29, 2437, 2588, 3201, 2589, 3394, 3202, 3602, 1630, 243, 4452, 244, 1631, 3203, 30, 1632, 1633, 2438, 3395, 1157, 4453, 2439, 149, 3894, 4781, 3701, 3895, 1158, 1634, 1635, 2590, 4782, 1159, 5455, 4783, 3396, 1636, 150, 3204, 3397, 1637, 3205, 1638, 1639, 4454, 4784, 1640, 4785, 4786, 245, 2821, 4455, 816, 1641, 2822, 2823, 1362, 4787, 3398, 246, 2591, 2824, 648, 2592, 4404, 2825, 3896, 3897, 3898, 1160, 3899, 151, 3900, 247, 31, 152, 3399, 4788, 1642, 4456, 1643, 2826, 3702, 3206, 1501, 4789, 4790, 3207, 1644, 1161, 3208, 3603, 4457, 914, 1645, 2593, 3400, 3703, 3901, 4458, 248, 1646, 249, 1162, 915, 1647, 1363, 1648, 3604, 817, 4459, 2827, 2440, 5456, 4791, 1163, 3902, 3401, 3903, 1649, 4460, 3904, 1650, 2594, 2828, 4792, 2829, 4461, 1651, 4405, 3402, 916, 1652, 250, 251, 1502, 2441, 3209, 1653, 2595, 917, 2596, 3905, 3403, 5363, 252, 4793, 4794, 153, 2597, 4795, 1654, 4796, 2830, 3906, 1655, 4797, 1656, 253, 4462, 3907, 4463, 4464, 3908, 2442, 4798, 2831, 32, 1657, 2443, 1503, 1658, 2832, 5457, 2, 3404, 803, 1659, 1364, 4799, 1660, 918, 1661, 3210, 818, 3211, 3704, 5458, 1164, 4800, 3212, 1165, 2598, 3405, 2599, 5364, 2444, 649, 254, 255, 2445, 2446, 919, 3909, 4801, 4802, 256, 1662, 257, 4465, 4466, 1663, 1664, 3213, 258, 1665, 3214, 3, 2447, 4803, 4804, 1166, 920, 1167, 921, 5459, 3406, 3407, 1168, 922, 259, 1169, 1666, 4355, 4805, 1667, 3910, 154, 2600, 1504, 260, 2601, 261, 1668, 923, 3408, 2602, 4356, 3215, 3605, 1669, 4806, 4807, 3216, 4467, 4808, 3911, 4357, 3912, 1365, 262, 924, 1670, 925, 1671, 1672, 2448, 2449, 3913, 2603, 926, 1673, 1170, 4809, 3606, 3217, 3914, 5460, 819, 2604, 2605, 2606, 33, 3915, 4358, 4810, 927, 263, 264, 1674, 265, 1675, 3218, 266, 267, 2833, 2834, 4811, 2835, 4812, 1676, 928, 3916, 4468, 2607, 3917, 3705, 3706, 3707, 4813, 268, 4814, 4815, 1171, 1172, 4816, 2608, 3409, 2609, 4817, 34, 3410, 1677, 4818, 3219, 125, 1678, 2610, 929, 930, 269, 3411, 2836, 4469, 3220, 270, 271, 1679, 2611, 272, 1680, 1505, 3918, 3221, 3919, 2837, 3920, 2838, 2839, 4470, 3607, 1681, 1682, 2450, 650, 3222, 1683, 1684, 35, 1685, 3921, 931, 1173, 2840, 3922, 4819, 2841, 2612, 2842, 1686, 932, 1366, 4820, 3412, 3923, 933, 36, 4471, 934, 273, 3413, 1687, 1688, 4472, 3924, 2843, 5365, 1689, 2844, 4473, 1690, 274, 37, 1506, 3708, 3414, 2845, 3415, 935, 4821, 2846, 3416, 2847, 3925, 4359, 1367, 3709, 1368, 1691, 936, 3926, 1369, 4822, 3608, 1692, 5461, 4474, 4823, 651, 937, 3223, 1693, 1694, 2451, 1370, 4824, 38, 275, 1695, 276, 1371, 4825, 3417, 277, 278, 279, 1696, 4360, 3927, 280, 2848, 3928, 1174, 4826, 4827, 281, 3929, 2849, 3930, 4475, 3710, 3931, 5366, 3224, 652, 5367, 4828, 3932, 4476, 282, 4406, 1697, 2850, 3609, 1175, 3418, 283, 3933, 155, 2452, 2851, 4477, 4829, 3934, 3935, 3936, 3937, 1698, 39, 5368, 3938, 4830, 284, 1699, 1700, 1701, 2613, 1702, 285, 1703, 4478, 1176, 653, 3939, 1704, 3419, 1705, 3420, 2852, 2453, 1706, 4831, 4479, 3940, 4, 3225, 1707, 3941, 4407, 1507, 3421, 4832, 1708, 286, 2853, 1709, 1710, 1711, 3610, 4833, 1712, 156, 2614, 3711, 3422, 287, 3942, 1713, 288, 4834, 3611, 1714, 157, 158, 820, 654, 3423, 289, 5369, 655, 5462, 656, 657, 1372, 2854, 3943, 1715, 3944, 1716, 3612, 1717, 1718, 1719, 1720, 1721, 1722, 938, 5463, 5370, 1723, 3226, 3712, 3713, 658, 3227, 1724, 40, 4408, 1177, 3228, 1725, 2615, 5464, 3229, 1178, 1726, 1727, 4835, 1728, 290, 3945, 1729, 659, 2855, 5465, 3946, 3613, 3230, 2616, 1730, 4836, 1508, 2454, 1373, 4361, 939, 821, 3424, 4837, 2856, 291, 1731, 940, 4838, 2857, 4480, 660, 1732, 1733, 3231, 4839, 2617, 292, 2618, 293, 3947, 1734, 661, 941, 294, 2619, 1735, 662, 942, 1736, 4481, 1179, 3948, 3425, 3714, 1180, 4840, 663, 3232, 5371, 1737, 4482, 3949, 5466, 2858, 295, 1738, 1181, 1739, 1182, 1183, 4362, 943, 4841, 4842, 3950, 2859, 3951, 3715, 3952, 3953, 3954, 4483, 4843, 2860, 944, 3233, 3234, 41, 1740, 1741, 3955, 5467, 5468, 1742, 1374, 1743, 945, 4484, 1509, 1184, 4485, 4844, 3956, 3957, 664, 4845, 2455, 1744, 3958, 2861, 665, 666, 296, 3959, 4363, 3960, 2862, 297, 2863, 946, 1185, 3961, 298, 1745, 3962, 1746, 1747, 1375, 1748, 4846, 2864, 299, 159, 3426, 3427, 4486, 3428, 1376, 947, 300, 160, 1186, 1187, 1749, 42, 3429, 2456, 822, 1377, 4847, 1188, 3963, 948, 5469, 5470, 1378, 4848, 2865, 3430, 3431, 43, 2866, 3964, 4364, 1750, 5471, 1751, 3614, 1752, 1379, 2620, 1753, 823, 1754, 301, 1755, 1756, 1757, 3615, 302, 2457, 3432, 824, 303, 304, 1189, 1758, 1759, 1760, 5472, 1761, 4849, 4850, 4487, 2458, 2621, 3235, 305, 2622, 306, 3965, 1762, 1763, 1380, 2623, 1764, 1765, 1766, 2867, 1767, 1381, 1768, 2868, 1769, 1770, 3966, 1771, 2869, 307, 1772, 3967, 44, 3968, 1773, 308, 2870, 3616, 4851, 309, 4488, 1774, 1775, 667, 2624, 1510, 310, 1776, 2871, 1777, 4852, 1190, 1778, 3969, 3970, 2872, 3716, 1779, 4489, 3717, 311, 3433, 4853, 4490, 1780, 1781, 3971, 1511, 2873, 1782, 1783, 1784, 949, 1785, 1786, 4491, 3434, 3236, 312, 3237, 1512, 950, 951, 4854, 2874, 4365, 4492, 45, 4855, 4856, 4366, 1513, 313, 4857, 3972, 1382, 1787, 5473, 3973, 1514, 2625, 46, 668, 669, 4858, 314, 4493, 1788, 315, 3974, 1789, 4859, 3975, 3976, 5474, 3435, 1790, 952, 1791, 953, 1792, 5372, 3436, 316, 954, 5475, 670, 955, 1793, 671, 3977, 317, 2626, 2875, 4860, 3978, 4861, 1794, 2876, 2877, 5, 2878, 3979, 3718, 1795, 2879, 4862, 2627, 1383, 2628, 2629, 2630, 4367, 956, 3238, 2459, 5373, 4863, 4494, 4495, 1796, 3239, 318, 3437, 2460, 2880, 4496, 2881, 3438, 3719, 2631, 1797, 3439, 2632, 2461, 3440, 2462, 2463, 1191, 1384, 1798, 3240, 126, 957, 2633, 958, 5476, 319, 1799, 3980, 959, 1192, 1800, 1801, 47, 1802, 3441, 1385, 1515, 672, 3981, 4864, 4497, 1803, 2634, 1804, 1805, 3982, 4865, 2635, 2882, 2883, 2884, 1806, 1386, 5477, 320, 3983, 1807, 1808, 4498, 960, 4866, 3442, 5374, 1809, 1810, 1811, 825, 4867, 1812, 1813, 961, 5478, 1814, 1815, 1816, 4868, 4869, 3984, 3985, 1516, 5479, 3986, 48, 2885, 4870, 1387, 321, 1817, 1818, 2464, 3443, 3987, 3444, 1819, 322, 3988, 1193, 3989, 1820, 1821, 826, 3445, 4499, 1822, 3990, 2636, 1823, 1824, 1825, 827, 1826, 1827, 3241, 1517, 2886, 4871, 1828, 1518, 2887, 3991, 4500, 3992, 3720, 2888, 962, 4872, 4873, 3617, 2637, 5480, 4874, 1194, 3618, 1829, 4875, 828, 963, 964, 161, 1519, 4876, 2465, 3993, 3446, 4877, 3447, 4878, 323, 1830, 2638, 4879, 4880, 4881, 4882, 3994, 3721, 324, 3995, 2889, 2890, 1831, 4883, 1832, 3619, 3996, 1833, 325, 4501, 1834, 2891, 3997, 3998, 162, 6, 3722, 3999, 4000, 673, 326, 4502, 4001, 4002, 4003, 4503, 1835, 3242, 4004, 1836, 1837, 2639, 4005, 2892, 3448, 5481, 1195, 2893, 4368, 1838, 3723, 1839, 4884, 4885, 327, 4006, 4007, 5375, 4008, 4009, 1840, 4886, 1196, 4010, 4887, 1841, 49, 1842, 965, 4888, 1843, 4011, 328, 4889, 4012, 1844, 329, 674, 1845, 1846, 3724, 3243, 2640, 4013, 966, 1847, 1848, 675, 2466, 2894, 4014, 4890, 3449, 330, 5482, 1520, 2895, 4015, 4504, 4016, 967, 2896, 4017, 7, 331, 332, 50, 3244, 5376, 1197, 1849, 3725, 1850, 1851, 4018, 51, 1388, 2897, 2898, 1852, 3245, 1198, 3726, 4891, 4892, 4893, 4894, 127, 3246, 1853, 1854, 2899, 1521, 5483, 1389, 333, 5484, 334, 968, 52, 2900, 4505, 4895, 2901, 3727, 4896, 3247, 4019, 969, 3450, 2902, 3248, 335, 2467, 3451, 1855, 2903, 3452, 4020, 4506, 2904, 4897, 4898, 163, 4021, 1856, 4022, 970, 1199, 2905, 336, 4507, 971, 1857, 5485, 4023, 676, 4508, 677, 1858, 1200, 4024, 678, 1201, 1859, 2906, 2907, 4509, 4899, 3453, 2908, 3454, 1860, 2909, 3728, 1861, 3455, 4900, 1862, 3456, 1863, 4901, 679, 4025, 1864, 1865, 1866, 2641, 3249, 5377, 4510, 1867, 1868, 3457, 1869, 1870, 3729, 829, 1871, 4902, 2642, 4903, 1872, 3730, 4511, 3250, 972, 1873, 337, 3251, 5378, 4904, 4026, 4512, 2468, 4027, 4513, 4514, 4905, 1390, 4028, 338, 4906, 3458, 4029, 1391, 2910, 5379, 4907, 680, 4030, 339, 4908, 4031, 3459, 53, 4032, 1874, 4909, 340, 1392, 1522, 3252, 4033, 1202, 2911, 1875, 3253, 1876, 973, 974, 975, 2469, 976, 3731, 977, 5486, 978, 5487, 979, 2912, 2913, 1877, 1203, 341, 1878, 1879, 980, 1204, 4515, 3732, 1205, 1206, 4369, 830, 1207, 342, 1208, 1209, 1880, 681, 1210, 5380, 1211, 4034, 4035, 4036, 2914, 3254, 682, 683, 1881, 4516, 3255, 4037, 4517, 684, 3733, 1882, 4038, 4518, 831, 3460, 4039, 4910, 4911, 2915, 4912, 2916, 685, 164, 4370, 343, 3734, 2917, 344, 1883, 1884, 4913, 4914, 3620, 2918, 981, 4040, 2919, 4915, 2643, 4916, 2920, 4917, 1885, 4519, 686, 1886, 5488, 982, 687, 4520, 1887, 1888, 4918, 4041, 983, 2921, 4919, 1393, 832, 2922, 2923, 1889, 4920, 4921, 345, 4922, 2924, 1890, 4923, 4924, 3461, 984, 4925, 4521, 4926, 4522, 4927, 1891, 1523, 1892, 1212, 1893, 1394, 1894, 1895, 2644, 2645, 2470, 5489, 4928, 4042, 985, 1896, 346, 4929, 4043, 4523, 4044, 688, 986, 987, 4930, 2925, 689, 4045, 4931, 3462, 4046, 165, 4047, 1213, 4932, 988, 4933, 347, 1897, 4934, 3256, 2926, 4048, 690, 4935, 54, 833, 2927, 1898, 1899, 4049, 1900, 4524, 691, 2646, 348, 349, 4525, 350, 351, 692, 3257, 352, 353, 2928, 354, 4936, 1901, 1902, 834, 4050, 3258, 4526, 355, 356, 4051, 4937, 357, 1903, 4052, 358, 4938, 835, 359, 1904, 1905, 4939, 360, 693, 4527, 1906, 2929, 1214, 4940, 361, 694, 836, 3735, 4941, 55, 362, 4942, 2647, 4943, 1907, 1215, 1216, 2471, 2472, 3259, 4944, 1908, 363, 56, 4053, 3621, 364, 4945, 2930, 3260, 1909, 1524, 695, 2931, 1910, 4054, 4946, 5381, 3261, 3463, 4947, 4948, 365, 4528, 1911, 4055, 2648, 4529, 2932, 4056, 1912, 4530, 2933, 4531, 4057, 1217, 2934, 989, 2935, 3262, 1913, 1914, 4532, 4949, 696, 4058, 4950, 1915, 2936, 4951, 990, 5382, 1395, 2649, 1916, 3263, 4059, 366, 2473, 57, 1917, 1918, 3464, 991, 1919, 1525, 4952, 4533, 1920, 992, 1921, 3736, 697, 1922, 698, 4953, 4060, 367, 4954, 4955, 1923, 368, 4956, 4534, 369, 2937, 993, 1396, 3465, 4061, 166, 2474, 3264, 994, 2938, 4535, 4957, 699, 4958, 4536, 3265, 3737, 700, 5490, 1924, 4537, 370, 701, 4409, 2939, 4959, 4538, 4062, 1925, 371, 372, 167, 4539, 4960, 4961, 373, 374, 2940, 4540, 702, 375, 2941, 4541, 2475, 837, 3466, 995, 4542, 4063, 2650, 5383, 5384, 376, 4962, 377, 996, 5385, 1926, 1927, 1928, 3622, 378, 5491, 1929, 1930, 379, 168, 3266, 4064, 380, 381, 382, 383, 838, 384, 3623, 2942, 1931, 997, 998, 5492, 4963, 3267, 703, 3467, 4543, 1218, 1932, 2943, 704, 2476, 999, 3738, 4544, 4964, 4965, 385, 1933, 386, 3624, 387, 1934, 169, 1935, 388, 1936, 2944, 389, 2945, 3268, 1937, 1938, 1939, 390, 4966, 1940, 1397, 391, 1941, 1942, 4967, 3625, 1000, 1943, 705, 392, 393, 394, 1944, 4968, 1219, 2946, 4545, 839, 2947, 3626, 3269, 395, 4969, 1945, 4970, 4971, 396, 706, 4972, 170, 4546, 1001, 4973, 5493, 3270, 397, 707, 4547, 4974, 1526, 5494, 2651, 4975, 5386, 2652, 4371, 4065, 4976, 4977, 1002, 4978, 398, 4066, 1527, 3271, 840, 399, 4979, 708, 4980, 1003, 4067, 3627, 1946, 4981, 4068, 400, 4982, 709, 2653, 3739, 1947, 1398, 128, 1004, 3468, 1948, 2948, 1949, 1950, 1220, 1399, 4983, 4984, 401, 402, 4985, 403, 4986, 404, 405, 1951, 1952, 1005, 1953, 4987, 2477, 4548, 1954, 1955, 4988, 406, 841, 2949, 2950, 2951, 2952, 1528, 1006, 4069, 4070, 3272, 4549, 407, 4989, 2953, 4071, 4990, 1956, 3740, 408, 2654, 58, 2478, 4991, 2954, 4992, 1400, 1957, 4550, 409, 3469, 1958, 59, 4072, 2479, 4993, 1959, 4073, 2955, 410, 1960, 4074, 411, 842, 710, 4075, 2956, 711, 712, 412, 4994, 713, 4551, 1961, 3470, 4995, 4996, 1962, 1963, 1007, 2957, 413, 3741, 4997, 3742, 1401, 2958, 1964, 3743, 1965, 60, 5387, 3628, 3744, 2959, 5388, 1966, 1529, 171, 2960, 3273, 4076, 1008, 4552, 1530, 61, 714, 1531, 2961, 3745, 3746, 3471, 3747, 2962, 4553, 4998, 4077, 4999, 4372, 1009, 2963, 3274, 1532, 715, 1221, 3275, 3472, 5000, 5495, 1010, 1402, 1967, 1968, 1222, 1969, 62, 414, 1970, 1971, 1972, 415, 2655, 5001, 843, 3473, 1973, 2964, 1011, 4373, 716, 416, 417, 4554, 1974, 1975, 5002, 3276, 3748, 3474, 3749, 418, 1223, 1976, 844, 2656, 1977, 5003, 1978, 63, 3277, 3475, 2965, 2657, 3476, 4078, 4555, 1979, 8, 4556, 5004, 3750, 3477, 1980, 1981, 1224, 1982, 1012, 1403, 2658, 5496, 1983, 2659, 419, 717, 3478, 718, 3278, 420, 3751, 1404, 1984, 3479, 4079, 5005, 5006, 1225, 2660, 64, 3752, 5007, 2966, 65, 5008, 3279, 4557, 5009, 5010, 1985, 2967, 3280, 3480, 2661, 2662, 172, 1986, 1405, 2480, 1406, 421, 1013, 2968, 422, 423, 173, 1533, 1987, 2969, 174, 4558, 1988, 1534, 424, 1989, 5389, 4559, 1226, 1227, 1228, 1229, 2663, 3481, 4080, 3753, 66, 5497, 1990, 2664, 3281, 3754, 3482, 3755, 3483, 3282, 1230, 3283, 3484, 3485, 5498, 3284, 1991, 4081, 1992, 1993, 1994, 3285, 1231, 3756, 425, 3757, 1014, 1995, 2665, 4082, 4083, 5011, 3486, 4560, 1535, 426, 3629, 4084, 5499, 4085, 4561, 1232, 427, 428, 3286, 429, 3758, 3759, 1996, 430, 1997, 1407, 1998, 3487, 2970, 431, 845, 1999, 2971, 129, 5012, 5390, 2972, 2000, 2666, 4562, 432, 4563, 5500, 5013, 2001, 719, 4086, 5014, 2002, 4564, 5015, 2003, 433, 5016, 4565, 2004, 1015, 2973, 4087, 2005, 434, 2974, 1233, 2006, 5017, 2007, 3287, 67, 2481, 720, 2975, 5018, 4566, 4088, 4089, 846, 5019, 2667, 435, 5501, 2976, 2977, 2668, 2978, 2008, 4567, 5020, 1234, 5021, 5022, 1408, 5023, 2669, 5024, 1409, 3760, 5025, 3488, 1235, 436, 3761, 2009, 2010, 4568, 2979, 5026, 2011, 2980, 5027, 2981, 5028, 2012, 4569, 1016, 3489, 5502, 3630, 3762, 437, 4090, 5391, 130, 3288, 438, 5029, 3763, 5030, 439, 5031, 68, 2013, 4091, 4374, 2014, 3289, 4570, 3631, 440, 721, 3490, 441, 2015, 2670, 2482, 442, 4571, 2483, 1236, 5032, 3632, 443, 444, 5033, 5034, 1017, 4572, 69, 3764, 4573, 2016, 445, 446, 5392, 5393, 2982, 2671, 2672, 1018, 2983, 2017, 4092, 175, 2673, 176, 3290, 177, 9, 2984, 2985, 2986, 5035, 2987, 2018, 3633, 2988, 2019, 2020, 178, 3491, 2989, 10, 4093, 447, 448, 2021, 847, 4094, 2022, 70, 1019, 179, 2484, 5036, 1237, 5037, 4574, 1536, 2485, 722, 449, 71, 450, 3291, 1238, 723, 1239, 2486, 5038, 4095, 848, 4096, 451, 72, 4575, 2023, 2674, 1410, 4097, 3765, 452, 724, 3492, 3493, 2990, 73, 849, 11, 4576, 2675, 2024, 2991, 2992, 2025, 4098, 4099, 5503, 5039, 74, 3634, 2026, 850, 2993, 2994, 5040, 2995, 2996, 5041, 2027, 2997, 2998, 2028, 2487, 2676, 2029, 2999, 2030, 4100, 3000, 2031, 725, 5042, 3766, 2032, 5394, 3001, 1020, 453, 726, 3494, 2677, 4577, 4101, 454, 75, 1240, 2033, 5043, 2678, 5504, 3002, 2034, 2035, 2036, 2037, 2038, 3495, 455, 1241, 2679, 3003, 2039, 4102, 2680, 4103, 4104, 3004, 2040, 1242, 1243, 4578, 2041, 1021, 76, 1411, 2681, 2042, 5044, 3005, 180, 1022, 5505, 727, 3767, 4105, 131, 2043, 456, 3006, 2488, 2044, 4579, 2489, 3635, 2045, 5045, 3007, 2046, 5046, 728, 5047, 2047, 3636, 77, 3768, 3496, 457, 3497, 3637, 5048, 458, 729, 1244, 730, 3498, 1023, 851, 1024, 78, 4106, 2048, 2049, 1025, 5049, 4375, 5050, 2050, 5051, 3638, 5506, 1245, 3008, 2051, 4107, 2052, 731, 1537, 1246, 3292, 5052, 459, 5507, 460, 4376, 5053, 3009, 5054, 1412, 5055, 2053, 4580, 1247, 3010, 732, 2490, 5056, 4581, 2054, 2055, 2682, 5057, 5058, 5059, 1026, 5395, 2491, 2492, 733, 5060, 1248, 5061, 4582, 5062, 2056, 3499, 3500, 2057, 734, 2683, 2058, 852, 3769, 4108, 2493, 3770, 1027, 2059, 5396, 3501, 5063, 4109, 5064, 5065, 2060, 5066, 2061, 4110, 4583, 2062, 4584, 5067, 3771, 5508, 2063, 2684, 5068, 4377, 461, 2064, 5509, 2065, 2685, 5069, 79, 4111, 1249, 2066, 1028, 2067, 1029, 1030, 735, 2068, 736, 3293, 3011, 3294, 4112, 462, 3012, 737, 1031, 4113, 5070, 1032, 3502, 4585, 2069, 463, 3503, 2070, 4586, 4114, 4115, 1250, 464, 5071, 1033, 3772, 4116, 5072, 1034, 2494, 4410, 738, 465, 4117, 466, 853, 4118, 4119, 739, 2686, 467, 468, 1035, 1538, 2071, 3013, 469, 854, 470, 855, 2072, 5397, 80, 3504, 5510, 471, 5073, 472, 2073, 1036, 2074, 2075, 5074, 2076, 4120, 2077, 5075, 3773, 2078, 2079, 3639, 5511, 5076, 2687, 4587, 1539, 473, 5512, 3295, 3505, 5077, 2080, 2688, 3506, 1037, 5398, 2081, 1038, 5078, 181, 5079, 4121, 474, 3640, 1251, 2082, 1540, 5080, 1039, 3774, 3641, 1413, 4122, 475, 4411, 1414, 5399, 5400, 5401, 3014, 5402, 3507, 1415, 5403, 3508, 5081, 3015, 4123, 1541, 1040, 3016, 1542, 4124, 1041, 3017, 1416, 4125, 2083, 4126, 1417, 4378, 4127, 5082, 476, 1418, 5083, 4128, 3018, 5084, 1252, 1042, 3775, 2084, 4588, 3019, 2495, 3020, 4129, 5085, 477, 3021, 2689, 3642, 1043, 5086, 1419, 5087, 4130, 478, 3643, 1044, 5088, 1253, 2496, 4589, 479, 1420, 3022, 2085, 3023, 5089, 4379, 1421, 1422, 2086, 1423, 1424, 1425, 5090, 1426, 3024, 740, 2690, 5513, 1254, 182, 4131, 4132, 2691, 4133, 2087, 2088, 4134, 3025, 4135, 480, 2089, 1045, 4136, 5514, 741, 3026, 1427, 3509, 4137, 3027, 2090, 481, 3028, 2497, 4590, 1428, 2091, 4380, 856, 1046, 4591, 482, 1429, 5091, 5515, 183, 5516, 184, 4138, 1047, 4139, 2092, 1048, 4140, 483, 4592, 5092, 1430, 4381, 1543, 3029, 5517, 81, 4141, 1431, 742, 2093, 3510, 1049, 2498, 2499, 1432, 3511, 1433, 4142, 484, 4143, 2094, 5093, 2500, 743, 5094, 3512, 2501, 132, 2095, 5095, 2692, 1255, 82, 3776, 83, 3513, 84, 2096, 5096, 2097, 3296, 1256, 485, 2693, 2098, 5518, 486, 2099, 85, 2100, 5097, 2101, 5098, 5099, 2502, 2102, 1050, 5100, 4593, 3297, 3298, 744, 3030, 5101, 5102, 4144, 5103, 4594, 2503, 487, 3299, 2504, 5104, 3031, 4595, 86, 2103, 3777, 2104, 2105, 4382, 2694, 4596, 5105, 1051, 2106, 3032, 5106, 488, 1052, 5107, 2505, 745, 4412, 746, 5404, 1257, 747, 748, 1053, 2107, 3514, 2108, 3515, 2109, 4597, 3033, 4145, 2110, 4598, 2111, 2112, 3516, 87, 5108, 1054, 2506, 749, 4599, 2113, 4600, 750, 3300, 4146, 5109, 3034, 5519, 489, 3035, 4601, 5110, 4147, 3517, 88, 3518, 1258, 5520, 490, 1055, 5521, 3301, 5522, 1056, 1057, 3036, 5111, 4148, 4602, 2114, 3037, 1058, 4149, 857, 3302, 5112, 4150, 89, 2115, 4603, 3519, 2116, 3644, 2117, 751, 2507, 2118, 5113, 4151, 3645, 1259, 5114, 752, 4604, 5115, 1544, 3038, 4152, 5523, 2119, 753, 491, 754, 3778, 5524, 3039, 3040, 1545, 1059, 1434, 5116, 3041, 5117, 3303, 1435, 3042, 1546, 2120, 5118, 2695, 492, 3646, 3779, 2508, 1060, 3780, 5119, 4153, 4383, 3781, 90, 185, 493, 91, 5120, 5121, 3520, 3521, 3304, 3782, 1260, 4154, 3783, 2121, 4155, 2122, 2123, 2124, 2696, 3784, 1261, 3522, 3305, 92, 4605, 4156, 4157, 2125, 4606, 1262, 2126, 3043, 3044, 2697, 2127, 3523, 2128, 2129, 5122, 3785, 3647, 494, 2509, 5525, 3524, 3786, 3306, 186, 2130, 3045, 5123, 5124, 1263, 2698, 3307, 3525, 5125, 2131, 495, 4158, 5126, 3046, 93, 4607, 1264, 2132, 4159, 3526, 496, 3047, 2133, 5127, 3308, 2134, 5128, 2135, 755, 2699, 133, 2136, 2137, 2138, 3787, 2700, 5405, 1436, 3788, 2139, 5129, 497, 4160, 2701, 2140, 4608, 5130, 5131, 1265, 5406, 5132, 2141, 5526, 498, 3789, 858, 5133, 1266, 1547, 3527, 3528, 2142, 4161, 2702, 2143, 3790, 5527, 2510, 1437, 4162, 4163, 756, 1267, 5134, 3791, 94, 4609, 757, 2144, 2145, 5528, 2146, 2147, 2148, 5135, 5136, 758, 1268, 2149, 4610, 1269, 3048, 3049, 3050, 1061, 5137, 2150, 4611, 3309, 3310, 4612, 3311, 1062, 3648, 95, 5138, 2703, 499, 2151, 4164, 2511, 3529, 2704, 5139, 2152, 2153, 2154, 2155, 3051, 500, 96, 2705, 1063, 5140, 2706, 3792, 2707, 2156, 4384, 3530, 4385, 501, 5141, 1270, 97, 502, 5142, 5529, 759, 2157, 3052, 4165, 4166, 3053, 4167, 3054, 4613, 5143, 3055, 5407, 3649, 4168, 1271, 4169, 4614, 859, 503, 4170, 2158, 3531, 1272, 5144, 760, 5145, 5146, 1064, 2159, 5147, 3532, 3650, 504, 3056, 5148, 2160, 5149, 5408, 2161, 5150, 2162, 2163, 98, 1065, 1273, 2164, 4171, 2165, 5151, 5152, 3057, 5530, 5153, 4172, 5154, 4615, 2166, 1066, 1067, 761, 505, 3533, 506, 2708, 3058, 3059, 5155, 2167, 2709, 5531, 860, 2168, 2512, 12, 1068, 3060, 507, 508, 3061, 4173, 5156, 4616, 1438, 2169, 5157, 5158, 3312, 1274, 2710, 3793, 2711, 4174, 99, 2712, 2170, 5409, 5410, 509, 1439, 2171, 2172, 510, 5159, 2713, 3313, 4617, 5160, 2173, 5161, 2513, 3062, 1548, 5162, 1440, 3063, 1069, 5163, 4175, 4618, 5532, 4619, 5533, 1441, 2174, 4176, 4620, 1442, 5164, 861, 2175, 2176, 511, 5165, 762, 5166, 1070, 3651, 3064, 3794, 4177, 1071, 763, 2177, 2514, 1072, 3534, 13, 4178, 1443, 3535, 5534, 3065, 3066, 4621, 100, 5411, 2515, 101, 3795, 1444, 1445, 1446, 5167, 5168, 2178, 1275, 134, 4179, 4180, 1549, 5535, 3652, 102, 3067, 1276, 512, 4622, 4386, 4181, 3068, 14, 4182, 1073, 2179, 764, 5169, 513, 5170, 765, 2180, 2181, 4183, 4623, 1447, 5171, 135, 514, 3069, 5172, 2182, 4624, 5173, 5536, 2516, 3070, 2183, 2714, 3536, 5174, 2184, 2185, 5175, 2186, 5176, 4625, 3071, 515, 1277, 5177, 187, 4626, 516, 1278, 2187, 862, 5537, 2188, 4184, 1279, 4387, 4627, 2189, 5178, 1280, 517, 1281, 5179, 2517, 3314, 4388, 1448, 1282, 3072, 4628, 2715, 1074, 4185, 5180, 5412, 4186, 2190, 3073, 5538, 3796, 4187, 2716, 5181, 4188, 2191, 3074, 5182, 3075, 2518, 3653, 3076, 4189, 3077, 103, 3078, 3537, 518, 2717, 3654, 5183, 5184, 2192, 1449, 3079, 4190, 519, 4629, 3080, 5185, 4191, 3315, 1075, 3655, 3081, 766, 2718, 3316, 520, 767, 768, 769, 770, 3797, 3798, 521, 5186, 3082, 5187, 3083, 3084, 4630, 1283, 2193, 2194, 3085, 3086, 3317, 2195, 5539, 771, 2519, 5188, 3538, 4192, 2196, 3539, 5189, 5190, 5191, 4193, 522, 2719, 3087, 772, 3656, 2197, 3088, 1450, 3089, 2198, 2199, 5192, 4194, 523, 1284, 2720, 524, 2721, 5413, 525, 2722, 2200, 5540, 3799, 3318, 526, 3800, 2723, 2724, 2201, 3540, 3801, 5414, 1076, 1077, 1285, 1550, 5193, 527, 3541, 528, 3319, 5194, 5195, 1451, 3090, 5196, 2202, 529, 3091, 5197, 5198, 5199, 5200, 5201, 2203, 1452, 3542, 5415, 5202, 5203, 5204, 2204, 3092, 863, 3093, 3657, 3094, 15, 1453, 3095, 3096, 1551, 2205, 3658, 5205, 4389, 5541, 4631, 3659, 3660, 5206, 530, 3661, 531, 4632, 3802, 4633, 532, 2206, 4634, 2207, 5542, 4635, 4195, 2208, 3320, 4636, 4196, 5207, 3543, 104, 2209, 2520, 4637, 1552, 3097, 2210, 864, 2211, 4197, 2212, 2213, 2214, 2215, 188, 1078, 533, 4638, 5543, 2725, 1079, 1553, 2216, 5208, 4198, 4639, 2217, 5209, 4199, 1554, 2218, 4640, 4200, 2219, 534, 3803, 16, 4201, 3098, 4202, 4390, 2220, 4641, 3099, 4203, 4204, 1454, 3100, 2521, 1455, 4205, 4413, 5210, 1286, 2221, 5416, 3101, 4206, 1456, 5211, 105, 2222, 5212, 1080, 2223, 5213, 2522, 773, 535, 3804, 2224, 3102, 5214, 2225, 774, 2226, 4207, 5215, 3321, 4208, 5216, 5217, 5218, 4642, 2726, 3322, 5417, 2727, 3103, 3323, 2227, 536, 2523, 775, 5219, 3324, 4643, 5220, 5221, 2228, 5222, 1457, 3104, 4209, 3105, 5223, 4644, 537, 4210, 4211, 2524, 1287, 5544, 4212, 1081, 5545, 5224, 4645, 3325, 4213, 5225, 5226, 3106, 538, 2229, 5227, 1082, 2230, 2231, 2525, 4214, 2232, 5228, 539, 1458, 2728, 4646, 3107, 4215, 5229, 4216, 2729, 3326, 3805, 540, 3327, 5230, 5231, 541, 5232, 1083, 2233, 3108, 2234, 2526, 3328, 2235, 3544, 5233, 4217, 1459, 3545, 2236, 5234, 3109, 1084, 2237, 5546, 5235, 3329, 3546, 1288, 5236, 1289, 2730, 3110, 4647, 1085, 2238, 542, 1290, 2731, 3111, 1086, 5237, 3112, 189, 3113, 2527, 2239, 865, 3114, 5238, 3547, 543, 1291, 2240, 2732, 4391, 5418, 106, 2528, 1292, 2241, 4218, 3806, 4219, 3330, 5239, 544, 2529, 2242, 866, 3331, 4220, 3115, 2530, 2243, 2244, 5547, 3662, 3116, 5240, 3117, 776, 1293, 1294, 2733, 5241, 2245, 545, 2246, 2247, 2248, 1087, 2249, 1088, 1555, 5242, 2250, 5548, 1460, 4221, 2251, 1089, 4648, 5419, 5243, 3548, 17, 4649, 5549, 5244, 867, 2734, 4222, 1090, 3118, 5550, 546, 1461, 3332, 4650, 1091, 3119, 4651, 5551, 2252, 4223, 547, 136, 548, 4224, 5245, 2253, 2254, 2735, 5246, 2255, 777, 2531, 778, 2256, 2257, 107, 3120, 2258, 2259, 1295, 3807, 108, 2260, 3549, 2261, 5420, 3808, 2736, 2262, 549, 2532, 2533, 4225, 4652, 1462, 550, 4653, 5421, 1296, 5247, 2737, 5248, 4226, 3809, 5249, 1092, 4227, 3121, 4228, 1093, 551, 1463, 3550, 3663, 5250, 2263, 5251, 2264, 3122, 1094, 2265, 190, 2266, 2267, 5252, 1464, 2268, 4229, 3123, 5253, 4230, 2269, 2270, 3124, 2534, 1297, 3551, 4231, 4232, 552, 5254, 4233, 2271, 3125, 3552, 5255, 5256, 2272, 779, 1298, 3333, 2738, 1299, 2739, 2273, 3810, 5257, 4654, 5552, 3811, 3334, 4655, 1300, 5258, 4656, 4234, 109, 2274, 3553, 2535, 5259, 3335, 4657, 5260, 3126, 5422, 4658, 553, 554, 1095, 2740, 4659, 5423, 2275, 2536, 1301, 2537, 2741, 1302, 868, 2276, 4235, 555, 4392, 556, 1303, 2277, 1465, 557, 3554, 5553, 2538, 3812, 3664, 2278, 2742, 5261, 5424, 4236, 3555, 1096, 3665, 2279, 4237, 2280, 1304, 558, 2281, 4393, 1305, 3813, 2539, 3556, 4660, 559, 4238, 191, 869, 1556, 2282, 2283, 2540, 2284, 3666, 2285, 780, 3814, 3557, 2286, 3558, 2287, 2288, 2289, 560, 2290, 4239, 3127, 3128, 3336, 1306, 4661, 2291, 1097, 4414, 3667, 5262, 3559, 3560, 2292, 2293, 1098, 2541, 2294, 3561, 4240, 3562, 5263, 2295, 5264, 3668, 2542, 2296, 2543, 3563, 3129, 2743, 1307, 4662, 3130, 781, 2297, 2298, 4663, 2299, 2300, 1308, 2301, 5265, 3564, 4241, 2744, 3815, 1309, 4664, 2745, 3131, 1310, 2302, 2303, 4665, 5266, 2304, 3337, 4242, 3132, 3133, 3134, 4666, 2305, 5267, 3135, 3338, 2746, 110, 2306, 2307, 111, 2308, 561, 4243, 3136, 2747, 2748, 3816, 2749, 2750, 1311, 3669, 2309, 5268, 3339, 2751, 2752, 870, 3817, 4667, 4668, 2310, 3565, 3340, 2311, 4244, 4245, 4246, 562, 2312, 2313, 4247, 4248, 3566, 3567, 1466, 1467, 5269, 5270, 2753, 3818, 4249, 3670, 1468, 4250, 1312, 5271, 2754, 3137, 1469, 2755, 3568, 4251, 2314, 3341, 5272, 4669, 3569, 4252, 4670, 1313, 1099, 782, 3570, 112, 1314, 4415, 1100, 5273, 4253, 2756, 3138, 5274, 4254, 4255, 4671, 4256, 871, 1315, 3139, 3819, 5275, 3571, 4672, 563, 4257, 2757, 5425, 2315, 1101, 3572, 3820, 2544, 4394, 3140, 4673, 1102, 3573, 5554, 113, 114, 4258, 1103, 5276, 4259, 192, 3821, 3822, 5277, 1316, 3671, 1470, 4260, 2316, 4261, 4674, 4262, 3141, 3142, 3143, 3574, 2317, 4263, 5278, 1317, 2318, 3823, 1318, 1319, 3575, 1320, 2319, 5279, 2320, 872, 5555, 115, 5280, 3144, 2321, 2545, 5281, 2322, 2758, 3672, 2323, 4264, 2324, 2325, 2326, 564, 2327, 2328, 5556, 193, 2759, 4265, 1104, 5282, 2329, 2330, 3145, 3824, 2331, 4266, 4267, 5557, 4268, 4269, 3825, 5283, 2332, 2760, 4270, 1321, 3342, 2761, 565, 1471, 4271, 3146, 2333, 2546, 3673, 4272, 3674, 3147, 4273, 5284, 2334, 5285, 2335, 566, 116, 1322, 567, 3148, 4675, 568, 4676, 569, 4677, 5286, 3576, 570, 3577, 4274, 4275, 4276, 4277, 1557, 2336, 18, 1323, 2337, 1105, 2338, 3826, 2339, 3827, 19, 2340, 2547, 1324, 2341, 783, 117, 784, 4278, 3149, 571, 2342, 2343, 2344, 4279, 572, 4280, 2345, 4395, 4281, 2346, 3675, 873, 4678, 5287, 2347, 2762, 3828, 2763, 2348, 3829, 3830, 137, 573, 2349, 2350, 574, 2764, 5288, 3831, 1472, 575, 2765, 3343, 5289, 2351, 1325, 1106, 2352, 3150, 2353, 2766, 576, 3832, 3833, 3344, 2354, 577, 3151, 3345, 3152, 4282, 4283, 2767, 5290, 5291, 4284, 2355, 1558, 2356, 4285, 3834, 5292, 4679, 1559, 3578, 3676, 1107, 5558, 4286, 2357, 5293, 194, 2358, 5426, 2359, 3579, 578, 1108, 2360, 3580, 4287, 1473, 3153, 3346, 5427, 1109, 579, 580, 1326, 3835, 5559, 581, 4288, 2768, 785, 2361, 5294, 3581, 2769, 2770, 4289, 2362, 3347, 786, 4680, 1560, 874, 5295, 1474, 2771, 2548, 2772, 582, 5560, 1327, 1328, 5296, 4681, 3154, 5297, 2773, 3677, 3348, 3582, 5298, 5299, 4290, 1475, 5300, 195, 5301, 3349, 5302, 5561, 583, 3836, 2363, 787, 3350, 3351, 5303, 2774, 1561, 5304, 5562, 5305, 2549, 4682, 2364, 5563, 3837, 5306, 5564, 3352, 3155, 5307, 3156, 788, 3583, 5308, 3838, 4683, 1476, 3678, 584, 118, 3584, 585, 586, 2365, 196, 3157, 4291, 4292, 587, 2775, 4293, 2366, 3158, 2367, 5309, 588, 5310, 1477, 4294, 2368, 5311, 1110, 119, 4295, 5312, 3353, 5313, 5314, 4296, 1562, 5315, 20, 789, 138, 5316, 2369, 1329, 5317, 790, 5318, 2776, 4297, 197, 2777, 589, 3159, 2370, 4396, 791, 5319, 3160, 5428, 3839, 3840, 4298, 2778, 590, 5320, 591, 2371, 592, 120, 1563, 3585, 1111, 3679, 3354, 1112, 2550, 3161, 4299, 593, 3355, 1478, 3162, 3163, 5321, 2551, 1479, 4300, 4397, 792, 3164, 3841, 3842, 5322, 4684, 4685, 3165, 3356, 3843, 4686, 1330, 4687, 4688, 5323, 1331, 2372, 4301, 2373, 4302, 2374, 5429, 5565, 5566, 2375, 2376, 2377, 3166, 5430, 3167, 2378, 2552, 198, 3357, 1480, 4303, 5324, 4304, 5325, 3844, 5326, 2553, 3358, 121, 2554, 793, 3680, 4305, 4306, 594, 5327, 4307, 4689, 3168, 4308, 2379, 4309, 4310, 4311, 5328, 1564, 2380, 4312, 4313, 2381, 1113, 3681, 4690, 4691, 4692, 1114, 3359, 4314, 2779, 3360, 4315, 3845, 1332, 1115, 4693, 4694, 595, 2555, 4316, 2556, 1333, 5329, 2382, 4695, 4317, 3169, 3170, 1334, 5330, 2383, 3361, 4318, 4319, 4320, 4321, 3362, 3171, 5331, 5567, 5568, 1335, 1336, 5332, 2384, 5333, 4322, 794, 1116, 1117, 3172, 4696, 2385, 1337, 199, 596, 2386, 2387, 597, 598, 795, 2388, 5334, 599, 5335, 2389, 2390, 5336, 3173, 4323, 5337, 600, 4416, 1118, 2780, 2557, 796, 3846, 5431, 601, 2391, 2781, 797, 3174, 602, 2392, 3586, 4324, 3175, 2393, 4697, 1481, 122, 5338, 3176, 4325, 3847, 3177, 603, 5339, 1338, 5340, 1119, 1120, 2394, 2558, 4698, 798, 2395, 200, 604, 3587, 2396, 201, 4326, 799, 4398, 4699, 5341, 4700, 1121, 605, 4327, 1482, 4399, 4400, 4328, 4329, 4330, 606, 3682, 3588, 607, 5342, 5343, 5344, 1122, 4331, 4701, 4702, 5345, 2397, 875, 2398, 4703, 1339, 2399, 5346, 5347, 2400, 1123, 2401, 800, 3683, 2782, 3848, 801, 3589, 2402, 608, 609, 1483, 3590, 610, 5348, 611, 2403, 3684, 2404, 4332, 876, 3849, 3178, 3363, 1484, 612, 3850, 4333, 5349, 3179, 3591, 4334, 3364, 2405, 3180, 613, 2406, 2407, 2408, 3365, 3366, 2409, 4335, 4336, 4337, 877, 1340, 1124, 3367, 4338, 1565, 1125, 123, 2410, 3851, 802, 4339, 4704, 4705, 2411, 2783, 2559, 1485, 1126, 3852, 4340, 4341, 4342, 3592, 4343, 1341, 878, 1127, 1486, 879, 880, 4401, 5350, 5351, 2412, 2413, 2414, 2415, 3181, 2416, 2560, 4344, 5352, 4345, 4346, 2784, 4706, 881, 5353, 614, 4347, 3368, 139, 1342, 2561, 3182, 1343, 2417, 3685, 5354, 5355, 615, 3593, 5569, 616, 2418, 3183, 617, 4348, 4707, 5570, 3184, 4349, 4708, 21, 4709, 4710, 3369, 2562, 618, 2785, 5356, 1344, 4711]; + +/// Brazilian municipalities published by the IBGE, by state, in the pt-BR collation order the JavaScript package returns. +fn municipalities_table() -> &'static runtime::Dataset { + static TABLE: std::sync::OnceLock = std::sync::OnceLock::new(); + + TABLE.get_or_init(|| runtime::Dataset::new(MUNICIPALITIES_ROWS, MUNICIPALITIES_GROUPS, MUNICIPALITIES_ORDER)) +} + +/// Reads one dataset row as a municipality. +pub fn row_to_municipality(row: runtime::Row) -> Municipality { + return Municipality { code: row[2 as usize].to_string(), name: row[1 as usize].to_string(), state_code: row[0 as usize].to_string() }; +} + +/// Returns Brazilian municipalities published by the IBGE, optionally filtered by state. +/// +/// If `stateCode` is provided, only municipalities of that state are returned. If it is +/// omitted, every municipality of every state is returned, sorted with `localeCompare` in the +/// "pt-BR" locale so accented names land where a Brazilian reader expects them. Every per-state +/// list is sorted the same way. +/// +/// Only an omitted (or `undefined`) `stateCode` asks for the full list: any other value that is +/// not a known state code, `null` and `""` included, returns `[]`. +/// +/// The state code is matched exactly, case included: `getMunicipalities("sp")` returns `[]` where +/// `getMunicipalities("SP")` returns the 645 São Paulo municipalities. +/// +/// @see Official: https://servicodados.ibge.gov.br/api/docs/localidades +pub fn get_municipalities(state_code: Option<&str>) -> Vec { + let mut municipalities: Vec = vec![]; + let mut rows: Vec = runtime::data_all(municipalities_table()); + if state_code.is_some() { + rows = runtime::data_rows(municipalities_table(), &state_code.clone().unwrap()); + } + for row in rows { + municipalities.push(row_to_municipality(row)); + } + return municipalities; +} diff --git a/spec/bridge/out/rust/src/is_valid_cnpj.rs b/spec/bridge/out/rust/src/is_valid_cnpj.rs new file mode 100644 index 000000000..715d1f83f --- /dev/null +++ b/spec/bridge/out/rust/src/is_valid_cnpj.rs @@ -0,0 +1,112 @@ +// Code generated from spec/bridge/source/is-valid-cnpj.ts. DO NOT EDIT. + +//! `isValidCnpj`, written once. + +use crate::runtime; + +const CLASS0: runtime::CharClass = &[(0x30, 0x39), (0x41, 0x5a)]; +const CLASS1: runtime::CharClass = &[(0x9, 0xd), (0x20, 0x20), (0x2d, 0x2f), (0xa0, 0xa0), (0x1680, 0x1680), (0x2000, 0x200a), (0x2028, 0x2029), (0x202f, 0x202f), (0x205f, 0x205f), (0x3000, 0x3000), (0xfeff, 0xfeff)]; +const CLASS2: runtime::CharClass = &[(0x30, 0x39)]; +const CLASS3: runtime::CharClass = &[(0x41, 0x5a)]; +const CLASS4: runtime::CharClass = &[(0x30, 0x39), (0x41, 0x5a), (0x61, 0x7a)]; + +const PATTERN_ALPHANUMERIC_FORMAT: &[runtime::PatternStep] = &[ + runtime::PatternStep { class: CLASS0, min: 2, max: 2, capture: false }, + runtime::PatternStep { class: CLASS1, min: 0, max: -1, capture: false }, + runtime::PatternStep { class: CLASS0, min: 3, max: 3, capture: false }, + runtime::PatternStep { class: CLASS1, min: 0, max: -1, capture: false }, + runtime::PatternStep { class: CLASS0, min: 3, max: 3, capture: false }, + runtime::PatternStep { class: CLASS1, min: 0, max: -1, capture: false }, + runtime::PatternStep { class: CLASS0, min: 4, max: 4, capture: false }, + runtime::PatternStep { class: CLASS1, min: 0, max: -1, capture: false }, + runtime::PatternStep { class: CLASS2, min: 2, max: 2, capture: false }, +]; + +const PATTERN_NUMERIC_FORMAT: &[runtime::PatternStep] = &[ + runtime::PatternStep { class: CLASS2, min: 2, max: 2, capture: false }, + runtime::PatternStep { class: CLASS1, min: 0, max: -1, capture: false }, + runtime::PatternStep { class: CLASS2, min: 3, max: 3, capture: false }, + runtime::PatternStep { class: CLASS1, min: 0, max: -1, capture: false }, + runtime::PatternStep { class: CLASS2, min: 3, max: 3, capture: false }, + runtime::PatternStep { class: CLASS1, min: 0, max: -1, capture: false }, + runtime::PatternStep { class: CLASS2, min: 4, max: 4, capture: false }, + runtime::PatternStep { class: CLASS1, min: 0, max: -1, capture: false }, + runtime::PatternStep { class: CLASS2, min: 2, max: 2, capture: false }, +]; + +const FIRST_DIGIT_WEIGHTS: [i64; 12] = [5, 4, 3, 2, 9, 8, 7, 6, 5, 4, 3, 2]; +const SECOND_DIGIT_WEIGHTS: [i64; 13] = [6, 5, 4, 3, 2, 9, 8, 7, 6, 5, 4, 3, 2]; + + + +/// Options of `isValidCnpj`. +#[derive(Debug, Default, Clone, PartialEq, Eq)] +pub struct IsValidCnpjOptions { + /// Which CNPJ format to accept: `1` numeric only, `2` alphanumeric (default: `1`). + pub version: Option, +} + + + +/// Validates if a CNPJ (Cadastro Nacional da Pessoa Jurídica) is valid. +/// +/// Supports both numeric (version 1) and alphanumeric (version 2) CNPJ formats, and accepts the +/// usual mask characters (`.`, `-`, `/`) and whitespace around and between groups. +pub fn is_valid_cnpj(cnpj: &str, options: Option<&IsValidCnpjOptions>) -> bool { + let options_version = match options { + None => -1, + Some(value) => value.version.unwrap_or(-1), + }; + let trimmed: String = runtime::js_trim(&cnpj); + if (options_version == 2) { + let cleaned: String = runtime::upper(&runtime::keep_class(CLASS4, &cnpj)); + if runtime::class_has(CLASS3, &cleaned) { + if !runtime::pattern_test(PATTERN_ALPHANUMERIC_FORMAT, &runtime::upper(&trimmed)) { + return false; + } + return has_valid_checksum(&cleaned); + } + } + let numeric: String = runtime::keep_class(CLASS2, &cnpj); + if !runtime::pattern_test(PATTERN_NUMERIC_FORMAT, &trimmed) { + return false; + } + if is_repeated(&numeric) { + return false; + } + return has_valid_checksum(&numeric); +} + +/// Computes one CNPJ check digit from the base and its weight vector. +pub fn check_digit(base: &str, weights: &[i64]) -> i64 { + let mut sum: i64 = 0; + for index in 0..(weights.len() as i64) { + sum = (sum + ((runtime::code_at(&base, index) - 48) * weights[index as usize])); + } + let remainder: i64 = (sum % 11); + if (remainder < 2) { + return 0; + } + return (11 - remainder); +} + +/// Whether both check digits of a sanitized 14 character CNPJ match its base. +pub fn has_valid_checksum(cnpj: &str) -> bool { + if ((runtime::code_at(&cnpj, 12) - 48) != check_digit(&cnpj, &FIRST_DIGIT_WEIGHTS)) { + return false; + } + return ((runtime::code_at(&cnpj, 13) - 48) == check_digit(&cnpj, &SECOND_DIGIT_WEIGHTS)); +} + +/// Whether every character of the value is the same one. +pub fn is_repeated(value: &str) -> bool { + if (runtime::len(&value) == 0) { + return false; + } + for index in 1..runtime::len(&value) { + if (runtime::code_at(&value, index) != runtime::code_at(&value, 0)) { + return false; + } + } + return true; +} diff --git a/spec/bridge/out/rust/src/lib.rs b/spec/bridge/out/rust/src/lib.rs new file mode 100644 index 000000000..d5ca8e6b0 --- /dev/null +++ b/spec/bridge/out/rust/src/lib.rs @@ -0,0 +1,13 @@ +// Code generated from spec/bridge/source. DO NOT EDIT. + +//! Generated Brazilian Utils. + +pub mod runtime; +pub mod format_cnpj; +pub mod get_address_info_by_cep; +pub mod get_municipalities; +pub mod is_valid_cnpj; + +// The C ABI, for the ecosystems that bind to this crate instead of generating their own source. +pub mod cabi_format_cnpj; +pub mod cabi_is_valid_cnpj; diff --git a/spec/bridge/out/rust/src/runtime.rs b/spec/bridge/out/rust/src/runtime.rs new file mode 100644 index 000000000..78852747d --- /dev/null +++ b/spec/bridge/out/rust/src/runtime.rs @@ -0,0 +1,405 @@ +//! The portable runtime for the Rust target. +//! +//! Strings are indexed by code point, not by byte, so the generated code means the same thing +//! it does in the other targets. + +/// A set of code points, as sorted non overlapping ranges. +pub type CharClass = &'static [(u32, u32)]; + +/// Repeats a class between `min` and `max` times; `max` -1 means unbounded. +pub struct PatternStep { + pub class: CharClass, + pub min: i64, + pub max: i64, + pub capture: bool, +} + +/// The code points JavaScript's `trim()` strips. +const JS_WHITESPACE: CharClass = &[ + (0x09, 0x0d), + (0x20, 0x20), + (0xa0, 0xa0), + (0x1680, 0x1680), + (0x2000, 0x200a), + (0x2028, 0x2029), + (0x202f, 0x202f), + (0x205f, 0x205f), + (0x3000, 0x3000), + (0xfeff, 0xfeff), +]; + +/// Whether a code point belongs to a class. +pub fn in_class(class: CharClass, code: u32) -> bool { + class.iter().any(|(from, to)| code >= *from && code <= *to) +} + +/// Counts the code points of a value. +pub fn len(value: &str) -> i64 { + value.chars().count() as i64 +} + +/// Reads one code point, or -1 when the index is out of range. +pub fn code_at(value: &str, index: i64) -> i64 { + if index < 0 { + return -1; + } + + match value.chars().nth(index as usize) { + None => -1, + Some(char) => char as i64, + } +} + +/// Takes the code points between two indexes. +pub fn slice(value: &str, from: i64, to: i64) -> String { + let chars: Vec = value.chars().collect(); + let start = from.max(0) as usize; + let end = (to.max(0) as usize).min(chars.len()); + + if start >= end { + return String::new(); + } + + chars[start..end].iter().collect() +} + +/// Whether any character of the value belongs to the class. +pub fn class_has(class: CharClass, value: &str) -> bool { + value.chars().any(|char| in_class(class, char as u32)) +} + +/// Keeps only the characters of the value that belong to the class. +pub fn keep_class(class: CharClass, value: &str) -> String { + value.chars().filter(|char| in_class(class, *char as u32)).collect() +} + +/// Runs a compiled pattern against the whole value, greedily and without backtracking. +pub fn pattern_test(steps: &[PatternStep], value: &str) -> bool { + let chars: Vec = value.chars().collect(); + let mut index = 0usize; + + for step in steps { + let mut count = 0i64; + + while (step.max < 0 || count < step.max) + && index < chars.len() + && in_class(step.class, chars[index] as u32) + { + index += 1; + count += 1; + } + + if count < step.min { + return false; + } + } + + index == chars.len() +} + +/// Strips the code points JavaScript's `trim()` strips. +pub fn js_trim(value: &str) -> String { + value + .trim_matches(|char: char| in_class(JS_WHITESPACE, char as u32)) + .to_string() +} + +/// Left pads the value with a filler up to a length, counted in code points. +pub fn pad_start(value: &str, length: i64, filler: &str) -> String { + let missing = length - len(value); + + if missing <= 0 { + return value.to_string(); + } + + format!("{}{}", filler.repeat(missing as usize), value) +} + +/// Uppercases a value. +pub fn upper(value: &str) -> String { + value.to_uppercase() +} + +/// Repeats a value. +pub fn repeat(value: &str, times: i64) -> String { + if times <= 0 { + return String::new(); + } + + value.repeat(times as usize) +} + +/// One row of a dataset: the cells, in column order. +pub type Row = &'static [&'static str]; + +/// A dataset: the rows in the baked full order, and the rows of each key. +pub struct Dataset { + all: Vec, + by_key: std::collections::HashMap<&'static str, Vec>, +} + +impl Dataset { + /// Materialises a dataset, resolving both orders once. + pub fn new( + rows: &'static [Row], + groups: &'static [(&'static str, &'static [usize])], + full_order: &'static [usize], + ) -> Self { + let mut by_key = std::collections::HashMap::with_capacity(groups.len()); + + for (key, indexes) in groups { + by_key.insert(*key, indexes.iter().map(|index| rows[*index]).collect()); + } + + Self { + all: full_order.iter().map(|index| rows[*index]).collect(), + by_key, + } + } +} + +/// Every row of a dataset, in the baked full order. +pub fn data_all(table: &'static Dataset) -> Vec { + table.all.clone() +} + +/// The rows whose first column is the key given, empty when the key is unknown. +pub fn data_rows(table: &'static Dataset, key: &str) -> Vec { + match table.by_key.get(key) { + Some(rows) => rows.clone(), + None => Vec::new(), + } +} + +/// What a provider answered: the HTTP status, whether it counts as a success, and the body. +pub struct HttpResponse { + pub status: i64, + pub ok: bool, + pub body: serde_json::Value, +} + +/// The origin every request is sent to instead of its own, when one is set. +/// +/// This is the conformance hook: the cross language replay points all seven targets at one +/// local server, the same way the JavaScript suite points fetch at a mock. +fn http_target(url: &str) -> String { + let base = std::env::var("BRUTILS_BRIDGE_HTTP_ORIGIN").unwrap_or_default(); + + if base.is_empty() { + return url.to_string(); + } + + let without_scheme = url + .strip_prefix("https://") + .or_else(|| url.strip_prefix("http://")) + .unwrap_or(url); + + format!("{}/{}", base, without_scheme) +} + +/// Performs an HTTP GET, retrying a transient transport failure with a linear backoff. +pub fn http_get(url: &str, retries: i64, retry_delay_ms: i64) -> HttpResponse { + let target = http_target(url); + let agent: ureq::Agent = ureq::Agent::config_builder() + .http_status_as_error(false) + .timeout_global(Some(std::time::Duration::from_secs(15))) + .build() + .into(); + let mut attempt: i64 = 0; + + loop { + match agent.get(&target).call() { + Ok(mut answer) => { + let status = i64::from(answer.status().as_u16()); + let body = answer + .body_mut() + .read_to_string() + .ok() + .and_then(|text| serde_json::from_str(&text).ok()) + .unwrap_or(serde_json::Value::Null); + + return HttpResponse { + status, + ok: (200..300).contains(&status), + body, + }; + } + Err(_) => { + if attempt >= retries { + return HttpResponse { + status: 0, + ok: false, + body: serde_json::Value::Null, + }; + } + + std::thread::sleep(std::time::Duration::from_millis( + (retry_delay_ms * (attempt + 1)) as u64, + )); + attempt += 1; + } + } + } +} + +/// Whether a list holds a value. +pub fn list_has(items: &[&str], value: &str) -> bool { + items.iter().any(|item| *item == value) +} + +/// Reads one field of a JSON body, treating anything that is not an object as empty. +fn json_field<'a>(body: &'a serde_json::Value, key: &str) -> Option<&'a serde_json::Value> { + body.as_object().and_then(|object| object.get(key)) +} + +/// Reads a string field of a JSON body, answering "" when it is missing or not a string. +pub fn json_string(body: &serde_json::Value, key: &str) -> String { + match json_field(body, key).and_then(serde_json::Value::as_str) { + Some(found) => found.to_string(), + None => String::new(), + } +} + +/// Reads an integer field of a JSON body, answering -1 when it is missing or not a number. +pub fn json_int(body: &serde_json::Value, key: &str) -> i64 { + match json_field(body, key).and_then(serde_json::Value::as_f64) { + Some(found) => found as i64, + None => -1, + } +} + +/// Whether a field of a JSON body is truthy, the way JavaScript reads truthiness. +pub fn json_truthy(body: &serde_json::Value, key: &str) -> bool { + match json_field(body, key) { + None | Some(serde_json::Value::Null) => false, + Some(serde_json::Value::Bool(found)) => *found, + Some(serde_json::Value::Number(found)) => found.as_f64().unwrap_or(0.0) != 0.0, + Some(serde_json::Value::String(found)) => !found.is_empty(), + Some(_) => true, + } +} + +/// Whether a field of a JSON body is exactly true. +pub fn json_is_true(body: &serde_json::Value, key: &str) -> bool { + json_field(body, key) == Some(&serde_json::Value::Bool(true)) +} + +/// A failure raised by the generated code. Rust has no exception hierarchy, so the kinds the +/// source declared travel with the value. +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct Error { + pub kinds: Vec<&'static str>, + pub message: String, +} + +impl Error { + /// Builds a failure of the given kinds. + pub fn new(kinds: &[&'static str], message: &str) -> Self { + Self { + kinds: kinds.to_vec(), + message: message.to_string(), + } + } + + /// The most specific kind of the failure. + pub fn kind(&self) -> &str { + self.kinds.first().copied().unwrap_or("") + } + + /// Whether the failure is of a kind, its bases included. + pub fn is_kind(&self, kind: &str) -> bool { + self.kinds.iter().any(|candidate| *candidate == kind) + } +} + +impl std::fmt::Display for Error { + fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(formatter, "{}", self.message) + } +} + +impl std::error::Error for Error {} + +/// What one attempt of a race ended with. +pub struct Outcome { + pub ok: bool, + pub value: Option, + pub kinds: Vec<&'static str>, +} + +/// The running attempts of a race, and what each one ended with. +pub struct Attempts { + settled: std::sync::mpsc::Receiver>, + total: usize, + pub outcomes: Vec>, +} + +/// Starts one attempt per item, all at once. +/// +/// This is the only concurrency primitive of the portable subset. Rust has no runtime to await +/// on by default, so the work goes on threads and the caller simply waits. +pub fn start_all( + run: fn(&str, &str) -> Result, + items: &[String], + argument: &str, +) -> Attempts { + let (sender, settled) = std::sync::mpsc::channel(); + + for item in items { + let sender = sender.clone(); + let item = item.clone(); + let argument = argument.to_string(); + + std::thread::spawn(move || { + let outcome = match run(&item, &argument) { + Ok(value) => Outcome { + ok: true, + value: Some(value), + kinds: Vec::new(), + }, + Err(error) => Outcome { + ok: false, + value: None, + kinds: error.kinds, + }, + }; + + let _ = sender.send(outcome); + }); + } + + Attempts { + settled, + total: items.len(), + outcomes: Vec::new(), + } +} + +/// The value of the first attempt that succeeds, or nothing once every attempt has failed. +pub fn first_success(attempts: &mut Attempts) -> Option { + while attempts.outcomes.len() < attempts.total { + let Ok(mut outcome) = attempts.settled.recv() else { + return None; + }; + + if outcome.ok { + let value = outcome.value.take(); + + attempts.outcomes.push(outcome); + + return value; + } + + attempts.outcomes.push(outcome); + } + + None +} + +/// Whether any attempt failed with a given error kind. +pub fn any_failed_with(attempts: &Attempts, kind: &str) -> bool { + attempts + .outcomes + .iter() + .any(|outcome| !outcome.ok && outcome.kinds.iter().any(|candidate| *candidate == kind)) +} diff --git a/spec/bridge/out/typescript/_bridge/_runtime.ts b/spec/bridge/out/typescript/_bridge/_runtime.ts new file mode 100644 index 000000000..8d27ee1e2 --- /dev/null +++ b/spec/bridge/out/typescript/_bridge/_runtime.ts @@ -0,0 +1,458 @@ +/** + * The portable runtime for the TypeScript target. + * + * Everything the generated code needs that is not plain syntax lives here: the compiled + * character classes and patterns are passed in as data, so this file never changes when a + * utility does. + */ + +/** A character class: sorted, non overlapping code point ranges. */ +export type CharClass = readonly (readonly [number, number])[]; + +/** One step of a compiled pattern: repeat a class between `min` and `max` times. */ +export type PatternStep = { + readonly charClass: CharClass; + readonly min: number; + readonly max: number; + readonly capture: boolean; +}; + +/** + * Whether a code point belongs to a class. + * + * @param {CharClass} charClass - The class to test against. + * @param {number} code - The code point. + * @returns {boolean} True when the class covers the code point. + */ +export const inClass = (charClass: CharClass, code: number): boolean => { + for (const [from, to] of charClass) { + if (code >= from && code <= to) return true; + } + + return false; +}; + +/** + * Reads one code unit, or -1 when the index is out of range. + * + * @param {string} value - The string to read. + * @param {number} index - The index. + * @returns {number} The code unit, or -1. + */ +export const codeAt = (value: string, index: number): number => + index >= 0 && index < value.length ? value.charCodeAt(index) : -1; + +/** + * Whether any character of the value belongs to the class. + * + * @param {CharClass} charClass - The class to look for. + * @param {string} value - The string to scan. + * @returns {boolean} True when at least one character matches. + */ +export const classHas = (charClass: CharClass, value: string): boolean => { + for (let index = 0; index < value.length; index++) { + if (inClass(charClass, value.charCodeAt(index))) return true; + } + + return false; +}; + +/** + * Keeps only the characters of the value that belong to the class. + * + * @param {CharClass} charClass - The class to keep. + * @param {string} value - The string to filter. + * @returns {string} The filtered string. + */ +export const keepClass = (charClass: CharClass, value: string): string => { + let kept = ""; + + for (let index = 0; index < value.length; index++) { + if (inClass(charClass, value.charCodeAt(index))) kept += value.charAt(index); + } + + return kept; +}; + +/** + * Runs a compiled pattern against the whole value. + * + * The scan is greedy and never backtracks, which the compiler guarantees is correct by + * refusing any pattern whose consecutive classes overlap. + * + * @param {PatternStep[]} steps - The compiled steps. + * @param {string} value - The string to match. + * @returns {boolean} True when the whole value matches. + */ +export const patternTest = (steps: readonly PatternStep[], value: string): boolean => { + let index = 0; + + for (const step of steps) { + let count = 0; + + while ( + (step.max < 0 || count < step.max) && + index < value.length && + inClass(step.charClass, value.charCodeAt(index)) + ) { + index++; + count++; + } + + if (count < step.min) return false; + } + + return index === value.length; +}; + +/** + * Left pads the value with a filler up to a length. + * + * @param {string} value - The value to pad. + * @param {number} length - The target length. + * @param {string} filler - The single character filler. + * @returns {string} The padded value. + */ +export const padStart = (value: string, length: number, filler: string): string => + value.padStart(length, filler); + +/** + * Reads a value as a string the way `String(value)` does, answering `""` when the value has no + * string conversion at all. + * + * @param {string|number} value - The value to read. + * @returns {string} The string form. + */ +export const asString = (value: string | number): string => { + try { + return String(value); + } catch { + return ""; + } +}; + +/** + * Reads an optional flag the way JavaScript reads truthiness. + * + * @param {boolean} [value] - The flag. + * @returns {boolean} Whether the flag is set. + */ +export const isTruthy = (value?: boolean): boolean => Boolean(value); + +/** A dataset: string rows, the row indexes grouped by the first column, and the full order. */ +export type Dataset = { + readonly all: string[][]; + readonly byKey: ReadonlyMap; +}; + +/** + * Materialises a dataset, resolving both orders once. + * + * A `Map` rather than an object literal is what makes `dataRows(table, "toString")` answer with + * no rows instead of an inherited property. + * + * @param {string[][]} rows - The table. + * @param {Array} groups - The `[key, rowIndexes]` pairs. + * @param {number[]} fullOrder - The order the rows are returned in when no key is given. + * @returns {Dataset} The dataset. + */ +export const makeDataset = ( + rows: string[][], + groups: [string, number[]][], + fullOrder: number[], +): Dataset => ({ + all: fullOrder.map((index) => rows[index]), + byKey: new Map(groups.map(([key, indexes]) => [key, indexes.map((index) => rows[index])])), +}); + +/** + * Every row of a dataset, in the baked full order. + * + * @param {Dataset} table - The dataset. + * @returns {string[][]} The rows. + */ +export const dataAll = (table: Dataset): string[][] => table.all; + +/** + * The rows whose first column is the key given, in the baked per key order. + * + * @param {Dataset} table - The dataset. + * @param {string} key - The value of the first column. + * @returns {string[][]} The rows, empty when the key is unknown. + */ +export const dataRows = (table: Dataset, key: string): string[][] => table.byKey.get(key) ?? []; + +/** What a provider answered: the HTTP status, whether it counts as a success, and the body. */ +export type HttpResponse = { + readonly status: number; + readonly ok: boolean; + readonly body: unknown; +}; + +/** + * The transport failures worth retrying. `fetch` reports them on the error or on its cause, + * and a failure that is not one of these is an answer, not a hiccup. + */ +const RETRYABLE_ERROR_CODES = new Set([ + "UND_ERR_SOCKET", + "UND_ERR_CONNECT_TIMEOUT", + "UND_ERR_HEADERS_TIMEOUT", + "UND_ERR_BODY_TIMEOUT", + "ECONNRESET", + "ECONNREFUSED", + "EHOSTUNREACH", + "ENETUNREACH", + "ETIMEDOUT", +]); + +/** The `code` of an error, or of its cause. */ +const errorCode = (error: unknown): string | undefined => { + if (error === null || typeof error !== "object") return undefined; + + const code = "code" in error ? error.code : undefined; + + if (typeof code === "string") return code; + + const cause = "cause" in error ? error.cause : undefined; + + if (cause === null || cause === undefined || typeof cause !== "object") return undefined; + + const causeCode = "code" in cause ? cause.code : undefined; + + return typeof causeCode === "string" ? causeCode : undefined; +}; + +/** Whether a `fetch` rejection is a transient transport failure. */ +const isRetryable = (error: unknown): boolean => { + const code = errorCode(error); + + if (code !== undefined && RETRYABLE_ERROR_CODES.has(code)) return true; + if (!(error instanceof Error)) return false; + + return error.message.toLowerCase().includes("fetch failed"); +}; + +/** + * The origin every request is sent to instead of its own, when one is set. + * + * This is the conformance hook: the cross language replay points all seven targets at one local + * server, the same way the JavaScript suite points `fetch` at a mock. + */ +const origin = (url: string): string => { + const base = globalThis.process?.env?.["BRUTILS_BRIDGE_HTTP_ORIGIN"]; + + if (base === undefined || base === "") return url; + + return `${base}/${url.replace(/^https?:\/\//, "")}`; +}; + +/** + * Performs an HTTP GET, retrying a transient transport failure with a linear backoff. + * + * @param {string} url - The URL to read. + * @param {number} retries - How many retries follow the first attempt. + * @param {number} retryDelayMs - The base delay, multiplied by the attempt number. + * @returns {Promise} The response; `status` is 0 when nothing reached the server. + */ +export const httpGet = async ( + url: string, + retries: number, + retryDelayMs: number, +): Promise => { + const target = origin(url); + + for (let attempt = 0; ; attempt++) { + try { + const response = await fetch(target); + let body: unknown; + + try { + body = await response.json(); + } catch { + body = undefined; + } + + return { status: response.status, ok: response.ok, body }; + } catch (error) { + if (attempt >= retries || !isRetryable(error)) + return { status: 0, ok: false, body: undefined }; + } + + const delay = retryDelayMs * (attempt + 1); + + await new Promise((resolve) => { + setTimeout(resolve, delay); + }); + } +}; + +/** + * Whether the caller handed a number where a `string | number` was declared. + * + * @param {unknown} value - The value. + * @returns {boolean} True when it is a number. + */ +export const isNumber = (value: unknown): boolean => typeof value === "number"; + +/** + * Whether a value is a list. + * + * @param {unknown} value - The value. + * @returns {boolean} True when it is a list. + */ +export const isList = (value: unknown): value is unknown[] => Array.isArray(value); + +/** + * Whether a list holds a value. + * + * @param {string[]} list - The list. + * @param {string} value - The value to look for. + * @returns {boolean} True when the list holds it. + */ +export const listHas = (list: readonly string[], value: string): boolean => list.includes(value); + +/** Reads one field of a JSON body, treating anything that is not an object as empty. */ +const jsonField = (body: unknown, key: string): unknown => { + if (body === null || typeof body !== "object" || Array.isArray(body)) return undefined; + + return Object.hasOwn(body, key) ? (body as Record)[key] : undefined; +}; + +/** + * Reads a string field of a JSON body, answering `""` when it is missing or not a string. + * + * @param {unknown} body - The body. + * @param {string} key - The field name. + * @returns {string} The value, or `""`. + */ +export const jsonString = (body: unknown, key: string): string => { + const found = jsonField(body, key); + + return typeof found === "string" ? found : ""; +}; + +/** + * Reads an integer field of a JSON body, answering `-1` when it is missing or not a number. + * + * @param {unknown} body - The body. + * @param {string} key - The field name. + * @returns {number} The value, or `-1`. + */ +export const jsonInt = (body: unknown, key: string): number => { + const found = jsonField(body, key); + + return typeof found === "number" ? Math.trunc(found) : -1; +}; + +/** + * Whether a field of a JSON body is truthy, the way JavaScript reads truthiness. + * + * @param {unknown} body - The body. + * @param {string} key - The field name. + * @returns {boolean} True when the field is set and truthy. + */ +export const jsonTruthy = (body: unknown, key: string): boolean => Boolean(jsonField(body, key)); + +/** + * Whether a field of a JSON body is exactly `true`. + * + * @param {unknown} body - The body. + * @param {string} key - The field name. + * @returns {boolean} True when the field is the boolean `true`. + */ +export const jsonIsTrue = (body: unknown, key: string): boolean => jsonField(body, key) === true; + +/** What one attempt of a race ended with. */ +type Outcome = { ok: boolean; value?: T; kinds: string[] }; + +/** The running attempts of a race, and what each one ended with. */ +export type Attempts = { settled: Promise>[]; outcomes: Outcome[] }; + +/** The error name and every name it inherits from, which is what a failure is matched on. */ +const kindsOf = (error: unknown): string[] => { + const kinds: string[] = []; + + for ( + let current: unknown = error; + current instanceof Error; + current = Object.getPrototypeOf(current) as unknown + ) { + const name = (current.constructor as { name?: string } | undefined)?.name; + + if (name !== undefined && name !== "" && !kinds.includes(name)) kinds.push(name); + } + + return kinds; +}; + +/** + * Starts one attempt per item, all at once. + * + * @param {Function} run - The function to run per item. + * @param {string[]} items - The items. + * @param {string} argument - A second argument handed to every call. + * @returns {Attempts} The running attempts. + */ +export const startAll = ( + run: (item: never, argument: string) => T | Promise, + items: readonly string[], + argument: string, +): Attempts => { + const attempts: Attempts = { settled: [], outcomes: [] }; + + for (const item of items) { + attempts.settled.push( + Promise.resolve() + .then(async (): Promise> => ({ + ok: true, + value: await run(item as never, argument), + kinds: [], + })) + .catch((error: unknown): Outcome => ({ ok: false, kinds: kindsOf(error) })) + .then((outcome) => { + attempts.outcomes.push(outcome); + + return outcome; + }), + ); + } + + return attempts; +}; + +/** + * The value of the first attempt that succeeds, or nothing once every attempt has failed. + * + * @param {Attempts} attempts - The running attempts. + * @returns {Promise} The value, or `undefined`. + */ +export const firstSuccess = async (attempts: Attempts): Promise => { + const waiting = new Map( + attempts.settled.map((settled, index) => [ + index, + settled.then((outcome) => ({ index, outcome })), + ]), + ); + + while (waiting.size > 0) { + // The attempts are already running; this only picks whichever lands first. + // eslint-disable-next-line no-await-in-loop + const { index, outcome } = await Promise.race(waiting.values()); + + waiting.delete(index); + + if (outcome.ok) return outcome.value; + } + + return undefined; +}; + +/** + * Whether any attempt failed with a given error kind. + * + * @param {Attempts} attempts - The attempts. + * @param {string} kind - The error name to look for. + * @returns {boolean} True when at least one attempt failed with it. + */ +export const anyFailedWith = (attempts: Attempts, kind: string): boolean => + attempts.outcomes.some((outcome) => !outcome.ok && outcome.kinds.includes(kind)); diff --git a/spec/bridge/out/typescript/_bridge/format-cnpj.ts b/spec/bridge/out/typescript/_bridge/format-cnpj.ts new file mode 100644 index 000000000..fb8eae484 --- /dev/null +++ b/spec/bridge/out/typescript/_bridge/format-cnpj.ts @@ -0,0 +1,105 @@ +// Code generated from spec/bridge/source/format-cnpj.ts. DO NOT EDIT. + +/** `formatCnpj`, written once. */ + +import { asString, codeAt, isTruthy, keepClass, padStart, type CharClass } from "./_runtime.ts"; + +const class0: CharClass = [[0x30, 0x39]]; +const class1: CharClass = [[0x30, 0x39], [0x41, 0x5a], [0x61, 0x7a]]; + + + +const PATTERN = "00.000.000/0000-00"; +const OBFUSCATED_PATTERN = "**.000.000/0000-**"; + + + + + +/** Options of `formatCnpj`. */ +export type FormatCnpjOptions = { + /** Whether to left pad the value with zeros up to the number of slots in the pattern (default: `false`). */ + pad?: boolean; + /** Which CNPJ format to read: `1` numeric only, `2` alphanumeric (default: `1`). */ + version?: 1 | 2; + /** Whether to hide the first 2 digits and the 2 check digits with `*` (default: `false`). */ + obfuscate?: boolean; +}; + + + +/** + * Formats a given CNPJ (Cadastro Nacional da Pessoa Jurídica) value. + * + * @param {string} value - The CNPJ value to be formatted. + * @param {FormatCnpjOptions} [options] - Optional configuration for formatting the CNPJ. + * @returns {string} The formatted CNPJ string in the pattern "00.000.000/0000-00". + * + * @example + * ```typescript + * formatCnpj("12345678000195"); // "12.345.678/0001-95" + * formatCnpj("12345678", { pad: true }); // "00.000.012/3456-78" + * formatCnpj("q0SLFMBD7VX439", { version: 2 }); // "Q0.SLF.MBD/7VX4-39" + * formatCnpj("12345678000195", { obfuscate: true }); // "**.345.678/0001-**" + * ``` + */ +export const formatCnpj = (value: string | number, options?: FormatCnpjOptions): string => { + const optionsVersion = options?.version ?? -1; + const optionsObfuscate = options?.obfuscate ?? false; + const optionsPad = options?.pad ?? false; + if (value === null || value === undefined) { + return ""; + } + const text = asString(value); + let cleaned = keepClass(class0, text); + if ((optionsVersion === 2)) { + cleaned = keepClass(class1, text).toUpperCase(); + } + let pattern = PATTERN; + if (isTruthy(optionsObfuscate)) { + pattern = OBFUSCATED_PATTERN; + } + return layout(cleaned, pattern, isTruthy(optionsPad)); +}; + +/** + * Lays a value over a pattern. + * + * @param {string} value - The sanitized value. + * @param {string} pattern - The mask. + * @param {boolean} pad - Whether to left pad the value with zeros up to the number of slots. + * @returns {string} The masked value, cut short where the value runs out. + */ +const layout = (value: string, pattern: string, pad: boolean): string => { + let slots = 0; + for (let index = 0; index < pattern.length; index++) { + if (((codeAt(pattern, index) === 48) || (codeAt(pattern, index) === 42))) { + slots = (slots + 1); + } + } + let padded = value; + if (pad) { + padded = padStart(value, slots, "0"); + } + let formatted = ""; + let cursor = 0; + for (let index = 0; index < pattern.length; index++) { + const slot = codeAt(pattern, index); + if (((slot === 48) || (slot === 42))) { + if ((cursor >= padded.length)) { + return formatted; + } + if ((slot === 42)) { + formatted = (formatted + "*"); + } else { + formatted = (formatted + padded.slice(cursor, (cursor + 1))); + } + cursor = (cursor + 1); + } else { + if ((cursor < padded.length)) { + formatted = (formatted + pattern.slice(index, (index + 1))); + } + } + } + return formatted; +}; diff --git a/spec/bridge/out/typescript/_bridge/get-address-info-by-cep.ts b/spec/bridge/out/typescript/_bridge/get-address-info-by-cep.ts new file mode 100644 index 000000000..6976ccb5c --- /dev/null +++ b/spec/bridge/out/typescript/_bridge/get-address-info-by-cep.ts @@ -0,0 +1,252 @@ +// Code generated from spec/bridge/source/get-address-info-by-cep.ts. DO NOT EDIT. + +/** Address lookup by CEP, written once. */ + +import { anyFailedWith, asString, firstSuccess, httpGet, isList, isNumber, jsonInt, jsonIsTrue, jsonString, jsonTruthy, keepClass, listHas, padStart, patternTest, startAll, type Attempts, type CharClass, type PatternStep } from "./_runtime.ts"; + +const class0: CharClass = [[0x30, 0x39]]; + +const PATTERN_CEP_FORMAT: readonly PatternStep[] = [ + { charClass: class0, min: 8, max: 8, capture: false }, +]; + +const DEFAULT_PROVIDERS: CepProvider[] = ["viacep", "brasilapi"]; +const KNOWN_PROVIDERS: CepProvider[] = ["viacep", "widenet", "brasilapi"]; +const BRASIL_API_NOT_FOUND_STATUS = 404; +const HTTP_RETRIES = 2; +const HTTP_RETRY_DELAY_MS = 250; + +/** + * The CEP services `getAddressInfoByCep` can query. + */ +export type CepProvider = + | "viacep" + | "widenet" + | "brasilapi"; + +/** Base class of every error `getAddressInfoByCep` rejects with. */ +export class GetAddressInfoByCepError extends Error { + public constructor(message: string) { + super(message); + this.name = "GetAddressInfoByCepError"; + } +} + +/** Thrown by `getAddressInfoByCep` when the value given is not a valid CEP. */ +export class GetAddressInfoByCepValidationError extends GetAddressInfoByCepError { + public constructor(message: string) { + super(message); + this.name = "GetAddressInfoByCepValidationError"; + } +} + +/** Thrown by `getAddressInfoByCep` when no CEP service knows the CEP. */ +export class GetAddressInfoByCepNotFoundError extends GetAddressInfoByCepError { + public constructor(message: string) { + super(message); + this.name = "GetAddressInfoByCepNotFoundError"; + } +} + +/** Thrown by `getAddressInfoByCep` when every CEP service failed to answer. */ +export class GetAddressInfoByCepServiceError extends GetAddressInfoByCepError { + public constructor(message: string) { + super(message); + this.name = "GetAddressInfoByCepServiceError"; + } +} + +/** Raised inside a provider that did not answer. Only whether a failure was a not found is looked at when the provider failures are aggregated, so this one never leaves the module. */ +class CepProviderFailure extends Error { + public constructor(message: string) { + super(message); + this.name = "CepProviderFailure"; + } +} + +/** The address `getAddressInfoByCep` returns for a CEP. */ +export type AddressInfo = { + /** The 8 digit CEP, no mask. */ + cep: string; + /** Two letter state code, e.g. "SP". */ + state: string; + /** City name. */ + city: string; + /** Neighborhood name, empty when the CEP covers a whole city. */ + neighborhood: string; + /** Street name, empty when the CEP covers a whole city. */ + street: string; +}; + +/** Options of `getAddressInfoByCep`. */ +export type GetAddressInfoByCepOptions = { + /** Which CEP services to race, in the order given (default: `["viacep", "brasilapi"]`; the deprecated `"widenet"` provider is excluded from the default list, but can still be requested explicitly). */ + providers?: CepProvider[]; +}; + + + +/** + * Reads the address ViaCEP answers with. + * + * @param {string} cep - The 8 digit CEP. + * @returns {AddressInfo} The address. + * + * @see Based on: https://viacep.com.br/ + */ +const fetchViaCep = async (cep: string): Promise => { + const response = await httpGet((("https://viacep.com.br/ws/" + cep) + "/json/"), HTTP_RETRIES, HTTP_RETRY_DELAY_MS); + if (!response.ok) { + throw new CepProviderFailure("ViaCEP request failed"); + } + const found = jsonString(response.body, "cep"); + if ((jsonTruthy(response.body, "erro") || (found === ""))) { + throw new GetAddressInfoByCepNotFoundError("CEP n\u{e3}o encontrado"); + } + return { cep: keepClass(class0, found), state: jsonString(response.body, "uf"), city: jsonString(response.body, "localidade"), neighborhood: jsonString(response.body, "bairro"), street: jsonString(response.body, "logradouro") }; +}; + +/** + * Reads the address Widenet answers with. + * + * @param {string} cep - The 8 digit CEP. + * @returns {AddressInfo} The address. + */ +const fetchWidenet = async (cep: string): Promise => { + const response = await httpGet((("https://apps.widenet.com.br/busca-cep/api/cep/" + cep) + ".json"), HTTP_RETRIES, HTTP_RETRY_DELAY_MS); + if (!response.ok) { + throw new CepProviderFailure("Widenet request failed"); + } + const found = jsonString(response.body, "code"); + if ((((jsonInt(response.body, "status") !== 200) || !jsonIsTrue(response.body, "ok")) || (found === ""))) { + throw new GetAddressInfoByCepNotFoundError("CEP n\u{e3}o encontrado"); + } + return { cep: keepClass(class0, found), state: jsonString(response.body, "state"), city: jsonString(response.body, "city"), neighborhood: jsonString(response.body, "district"), street: jsonString(response.body, "address") }; +}; + +/** + * Reads the address BrasilAPI answers with. + * + * @param {string} cep - The 8 digit CEP. + * @returns {AddressInfo} The address. + * + * @see Based on: https://brasilapi.com.br/docs#tag/CEP + */ +const fetchBrasilApi = async (cep: string): Promise => { + const response = await httpGet((("https://brasilapi.com.br/api/cep/v1/" + cep) + ""), HTTP_RETRIES, HTTP_RETRY_DELAY_MS); + if ((response.status === BRASIL_API_NOT_FOUND_STATUS)) { + throw new GetAddressInfoByCepNotFoundError("CEP n\u{e3}o encontrado"); + } + if (!response.ok) { + throw new CepProviderFailure("BrasilAPI request failed"); + } + const found = jsonString(response.body, "cep"); + if ((jsonTruthy(response.body, "errors") || (found === ""))) { + throw new GetAddressInfoByCepNotFoundError("CEP n\u{e3}o encontrado"); + } + return { cep: keepClass(class0, found), state: jsonString(response.body, "state"), city: jsonString(response.body, "city"), neighborhood: jsonString(response.body, "neighborhood"), street: jsonString(response.body, "street") }; +}; + +/** + * Asks one named provider for a CEP. + * + * @param {CepProvider} provider - The provider name. + * @param {string} cep - The 8 digit CEP. + * @returns {AddressInfo} The address. + */ +const fetchProvider = async (provider: CepProvider, cep: string): Promise => { + if ((provider === "viacep")) { + return await fetchViaCep(cep); + } + if ((provider === "widenet")) { + return await fetchWidenet(cep); + } + return await fetchBrasilApi(cep); +}; + +/** + * The providers of a list that are known, in the order they were given. + * + * @param {CepProvider[]} given - The names the caller asked for. + * @returns {CepProvider[]} The known ones. + */ +const knownProviders = (given: CepProvider[]): CepProvider[] => { + const kept: CepProvider[] = []; + for (const provider of given) { + if (listHas(KNOWN_PROVIDERS, provider)) { + kept.push(provider); + } + } + return kept; +}; + +/** + * Fetches address information for a given CEP using multiple providers simultaneously. + * Returns the result from the first provider that responds successfully. + * + * The providers are started together and raced, not tried one after the other, so a provider + * that is retrying delays nothing for the others: its retries only push back the moment its own + * failure lands, and therefore the moment an all-failed rejection can surface. + * + * @param {string|number} cep - The CEP (Brazilian postal code) to search for. Can be a string or number. + * @param {GetAddressInfoByCepOptions} options - Optional configuration for the function. + * @param {CepProvider[]} options.providers - List of providers to use. Defaults to `["viacep", "brasilapi"]` + * if not specified (the deprecated `"widenet"` provider is excluded from the default list, but can still + * be requested explicitly). + * @returns {Promise} A promise that resolves to the address information. + * @throws {GetAddressInfoByCepValidationError} If the CEP format is invalid, or if + * `options.providers` is given and names no known provider: an empty array, an array of unknown + * names, and a value that is not an array at all (`null` included) all reject this way rather + * than with a raw `TypeError`. + * @throws {GetAddressInfoByCepNotFoundError} If the CEP is not found in any of the services. + * @throws {GetAddressInfoByCepServiceError} If all services are unavailable. + * + * @example + * ```typescript + * // Using the default providers (["viacep", "brasilapi"]) + * const address = await getAddressInfoByCep("01310100"); + * + * // Using specific providers + * const address = await getAddressInfoByCep("01310-100", { + * providers: ["viacep", "brasilapi"] + * }); + * + * // Using number input + * const address = await getAddressInfoByCep(1310100); + * ``` + * + * @see Official: https://www.correios.com.br/enviar/precisa-de-ajuda/tudo-sobre-cep + * @see Based on: https://viacep.com.br/ + * ViaCEP, one of the two default providers. A third-party service, not a Correios one. + * @see Based on: https://brasilapi.com.br/docs#tag/CEP + * BrasilAPI, the other default provider. A third-party service, not a Correios one. + */ +export const getAddressInfoByCep = async (cep: string | number, options?: GetAddressInfoByCepOptions): Promise => { + const optionsProviders = options?.providers; + let digits = keepClass(class0, asString(cep)); + if (isNumber(cep)) { + digits = padStart(digits, 8, "0"); + } + if (!patternTest(PATTERN_CEP_FORMAT, digits)) { + throw new GetAddressInfoByCepValidationError("CEP inv\u{e1}lido"); + } + let chosen = DEFAULT_PROVIDERS; + if ((optionsProviders !== undefined)) { + if (!isList(optionsProviders)) { + throw new GetAddressInfoByCepValidationError("Nenhum provedor v\u{e1}lido especificado"); + } + chosen = knownProviders(optionsProviders); + if ((chosen.length === 0)) { + throw new GetAddressInfoByCepValidationError("Nenhum provedor v\u{e1}lido especificado"); + } + } + const attempts = startAll(fetchProvider, chosen, digits); + const found = await firstSuccess(attempts); + if ((found !== undefined)) { + return found; + } + if (anyFailedWith(attempts, "GetAddressInfoByCepNotFoundError")) { + throw new GetAddressInfoByCepNotFoundError("CEP n\u{e3}o encontrado em nenhum servi\u{e7}o"); + } + throw new GetAddressInfoByCepServiceError("Todos os servi\u{e7}os est\u{e3}o fora de servi\u{e7}o ou indispon\u{ed}veis"); +}; diff --git a/spec/bridge/out/typescript/_bridge/get-municipalities.ts b/spec/bridge/out/typescript/_bridge/get-municipalities.ts new file mode 100644 index 000000000..174faebcd --- /dev/null +++ b/spec/bridge/out/typescript/_bridge/get-municipalities.ts @@ -0,0 +1,5713 @@ +// Code generated from spec/bridge/source/get-municipalities.ts. DO NOT EDIT. + +/** Brazilian municipalities, written once. */ + +import { dataAll, dataRows, makeDataset } from "./_runtime.ts"; + + + + + + + +/** + * The two letter code of a Brazilian state. Checked against the dataset by `data/build.ts`, so the union and the table can never drift apart. + */ +export type StateCode = + | "AC" + | "AL" + | "AP" + | "AM" + | "BA" + | "CE" + | "DF" + | "ES" + | "GO" + | "MA" + | "MT" + | "MS" + | "MG" + | "PA" + | "PB" + | "PR" + | "PE" + | "PI" + | "RJ" + | "RN" + | "RS" + | "RO" + | "RR" + | "SC" + | "SP" + | "SE" + | "TO"; + + + +/** One Brazilian municipality, as the IBGE publishes it. */ +export type Municipality = { + /** The 7-digit IBGE municipality code. */ + code: string; + /** The municipality name. */ + name: string; + /** The two-letter code of the state the municipality belongs to. */ + stateCode: StateCode; +}; + +/** Brazilian municipalities published by the IBGE, by state, in the pt-BR collation order the JavaScript package returns. */ +const MUNICIPALITIES = makeDataset( + [ + ["AC", "Acrel\u{e2}ndia", "1200013"], + ["AC", "Assis Brasil", "1200054"], + ["AC", "Brasil\u{e9}ia", "1200104"], + ["AC", "Bujari", "1200138"], + ["AC", "Capixaba", "1200179"], + ["AC", "Cruzeiro do Sul", "1200203"], + ["AC", "Epitaciol\u{e2}ndia", "1200252"], + ["AC", "Feij\u{f3}", "1200302"], + ["AC", "Jord\u{e3}o", "1200328"], + ["AC", "M\u{e2}ncio Lima", "1200336"], + ["AC", "Manoel Urbano", "1200344"], + ["AC", "Marechal Thaumaturgo", "1200351"], + ["AC", "Pl\u{e1}cido de Castro", "1200385"], + ["AC", "Porto Acre", "1200807"], + ["AC", "Porto Walter", "1200393"], + ["AC", "Rio Branco", "1200401"], + ["AC", "Rodrigues Alves", "1200427"], + ["AC", "Santa Rosa do Purus", "1200435"], + ["AC", "Sena Madureira", "1200500"], + ["AC", "Senador Guiomard", "1200450"], + ["AC", "Tarauac\u{e1}", "1200609"], + ["AC", "Xapuri", "1200708"], + ["AL", "\u{c1}gua Branca", "2700102"], + ["AL", "Anadia", "2700201"], + ["AL", "Arapiraca", "2700300"], + ["AL", "Atalaia", "2700409"], + ["AL", "Barra de Santo Ant\u{f4}nio", "2700508"], + ["AL", "Barra de S\u{e3}o Miguel", "2700607"], + ["AL", "Batalha", "2700706"], + ["AL", "Bel\u{e9}m", "2700805"], + ["AL", "Belo Monte", "2700904"], + ["AL", "Boca da Mata", "2701001"], + ["AL", "Branquinha", "2701100"], + ["AL", "Cacimbinhas", "2701209"], + ["AL", "Cajueiro", "2701308"], + ["AL", "Campestre", "2701357"], + ["AL", "Campo Alegre", "2701407"], + ["AL", "Campo Grande", "2701506"], + ["AL", "Canapi", "2701605"], + ["AL", "Capela", "2701704"], + ["AL", "Carneiros", "2701803"], + ["AL", "Ch\u{e3} Preta", "2701902"], + ["AL", "Coit\u{e9} do N\u{f3}ia", "2702009"], + ["AL", "Col\u{f4}nia Leopoldina", "2702108"], + ["AL", "Coqueiro Seco", "2702207"], + ["AL", "Coruripe", "2702306"], + ["AL", "Cra\u{ed}bas", "2702355"], + ["AL", "Delmiro Gouveia", "2702405"], + ["AL", "Dois Riachos", "2702504"], + ["AL", "Estrela de Alagoas", "2702553"], + ["AL", "Feira Grande", "2702603"], + ["AL", "Feliz Deserto", "2702702"], + ["AL", "Flexeiras", "2702801"], + ["AL", "Girau do Ponciano", "2702900"], + ["AL", "Ibateguara", "2703007"], + ["AL", "Igaci", "2703106"], + ["AL", "Igreja Nova", "2703205"], + ["AL", "Inhapi", "2703304"], + ["AL", "Jacar\u{e9} dos Homens", "2703403"], + ["AL", "Jacu\u{ed}pe", "2703502"], + ["AL", "Japaratinga", "2703601"], + ["AL", "Jaramataia", "2703700"], + ["AL", "Jequi\u{e1} da Praia", "2703759"], + ["AL", "Joaquim Gomes", "2703809"], + ["AL", "Jundi\u{e1}", "2703908"], + ["AL", "Junqueiro", "2704005"], + ["AL", "Lagoa da Canoa", "2704104"], + ["AL", "Limoeiro de Anadia", "2704203"], + ["AL", "Macei\u{f3}", "2704302"], + ["AL", "Major Isidoro", "2704401"], + ["AL", "Mar Vermelho", "2704906"], + ["AL", "Maragogi", "2704500"], + ["AL", "Maravilha", "2704609"], + ["AL", "Marechal Deodoro", "2704708"], + ["AL", "Maribondo", "2704807"], + ["AL", "Mata Grande", "2705002"], + ["AL", "Matriz de Camaragibe", "2705101"], + ["AL", "Messias", "2705200"], + ["AL", "Minador do Negr\u{e3}o", "2705309"], + ["AL", "Monteir\u{f3}polis", "2705408"], + ["AL", "Murici", "2705507"], + ["AL", "Novo Lino", "2705606"], + ["AL", "Olho d'\u{c1}gua das Flores", "2705705"], + ["AL", "Olho d'\u{c1}gua do Casado", "2705804"], + ["AL", "Olho d'\u{c1}gua Grande", "2705903"], + ["AL", "Oliven\u{e7}a", "2706000"], + ["AL", "Ouro Branco", "2706109"], + ["AL", "Palestina", "2706208"], + ["AL", "Palmeira dos \u{cd}ndios", "2706307"], + ["AL", "P\u{e3}o de A\u{e7}\u{fa}car", "2706406"], + ["AL", "Pariconha", "2706422"], + ["AL", "Paripueira", "2706448"], + ["AL", "Passo de Camaragibe", "2706505"], + ["AL", "Paulo Jacinto", "2706604"], + ["AL", "Penedo", "2706703"], + ["AL", "Pia\u{e7}abu\u{e7}u", "2706802"], + ["AL", "Pilar", "2706901"], + ["AL", "Pindoba", "2707008"], + ["AL", "Piranhas", "2707107"], + ["AL", "Po\u{e7}o das Trincheiras", "2707206"], + ["AL", "Porto Calvo", "2707305"], + ["AL", "Porto de Pedras", "2707404"], + ["AL", "Porto Real do Col\u{e9}gio", "2707503"], + ["AL", "Quebrangulo", "2707602"], + ["AL", "Rio Largo", "2707701"], + ["AL", "Roteiro", "2707800"], + ["AL", "Santa Luzia do Norte", "2707909"], + ["AL", "Santana do Ipanema", "2708006"], + ["AL", "Santana do Munda\u{fa}", "2708105"], + ["AL", "S\u{e3}o Br\u{e1}s", "2708204"], + ["AL", "S\u{e3}o Jos\u{e9} da Laje", "2708303"], + ["AL", "S\u{e3}o Jos\u{e9} da Tapera", "2708402"], + ["AL", "S\u{e3}o Lu\u{ed}s do Quitunde", "2708501"], + ["AL", "S\u{e3}o Miguel dos Campos", "2708600"], + ["AL", "S\u{e3}o Miguel dos Milagres", "2708709"], + ["AL", "S\u{e3}o Sebasti\u{e3}o", "2708808"], + ["AL", "Satuba", "2708907"], + ["AL", "Senador Rui Palmeira", "2708956"], + ["AL", "Tanque d'Arca", "2709004"], + ["AL", "Taquarana", "2709103"], + ["AL", "Teot\u{f4}nio Vilela", "2709152"], + ["AL", "Traipu", "2709202"], + ["AL", "Uni\u{e3}o dos Palmares", "2709301"], + ["AL", "Vi\u{e7}osa", "2709400"], + ["AP", "Amap\u{e1}", "1600105"], + ["AP", "Cal\u{e7}oene", "1600204"], + ["AP", "Cutias", "1600212"], + ["AP", "Ferreira Gomes", "1600238"], + ["AP", "Itaubal", "1600253"], + ["AP", "Laranjal do Jari", "1600279"], + ["AP", "Macap\u{e1}", "1600303"], + ["AP", "Mazag\u{e3}o", "1600402"], + ["AP", "Oiapoque", "1600501"], + ["AP", "Pedra Branca do Amapari", "1600154"], + ["AP", "Porto Grande", "1600535"], + ["AP", "Pracu\u{fa}ba", "1600550"], + ["AP", "Santana", "1600600"], + ["AP", "Serra do Navio", "1600055"], + ["AP", "Tartarugalzinho", "1600709"], + ["AP", "Vit\u{f3}ria do Jari", "1600808"], + ["AM", "Alvar\u{e3}es", "1300029"], + ["AM", "Amatur\u{e1}", "1300060"], + ["AM", "Anam\u{e3}", "1300086"], + ["AM", "Anori", "1300102"], + ["AM", "Apu\u{ed}", "1300144"], + ["AM", "Atalaia do Norte", "1300201"], + ["AM", "Autazes", "1300300"], + ["AM", "Barcelos", "1300409"], + ["AM", "Barreirinha", "1300508"], + ["AM", "Benjamin Constant", "1300607"], + ["AM", "Beruri", "1300631"], + ["AM", "Boa Vista do Ramos", "1300680"], + ["AM", "Boca do Acre", "1300706"], + ["AM", "Borba", "1300805"], + ["AM", "Caapiranga", "1300839"], + ["AM", "Canutama", "1300904"], + ["AM", "Carauari", "1301001"], + ["AM", "Careiro", "1301100"], + ["AM", "Careiro da V\u{e1}rzea", "1301159"], + ["AM", "Coari", "1301209"], + ["AM", "Codaj\u{e1}s", "1301308"], + ["AM", "Eirunep\u{e9}", "1301407"], + ["AM", "Envira", "1301506"], + ["AM", "Fonte Boa", "1301605"], + ["AM", "Guajar\u{e1}", "1301654"], + ["AM", "Humait\u{e1}", "1301704"], + ["AM", "Ipixuna", "1301803"], + ["AM", "Iranduba", "1301852"], + ["AM", "Itacoatiara", "1301902"], + ["AM", "Itamarati", "1301951"], + ["AM", "Itapiranga", "1302009"], + ["AM", "Japur\u{e1}", "1302108"], + ["AM", "Juru\u{e1}", "1302207"], + ["AM", "Juta\u{ed}", "1302306"], + ["AM", "L\u{e1}brea", "1302405"], + ["AM", "Manacapuru", "1302504"], + ["AM", "Manaquiri", "1302553"], + ["AM", "Manaus", "1302603"], + ["AM", "Manicor\u{e9}", "1302702"], + ["AM", "Mara\u{e3}", "1302801"], + ["AM", "Mau\u{e9}s", "1302900"], + ["AM", "Nhamund\u{e1}", "1303007"], + ["AM", "Nova Olinda do Norte", "1303106"], + ["AM", "Novo Air\u{e3}o", "1303205"], + ["AM", "Novo Aripuan\u{e3}", "1303304"], + ["AM", "Parintins", "1303403"], + ["AM", "Pauini", "1303502"], + ["AM", "Presidente Figueiredo", "1303536"], + ["AM", "Rio Preto da Eva", "1303569"], + ["AM", "Santa Isabel do Rio Negro", "1303601"], + ["AM", "Santo Ant\u{f4}nio do I\u{e7}\u{e1}", "1303700"], + ["AM", "S\u{e3}o Gabriel da Cachoeira", "1303809"], + ["AM", "S\u{e3}o Paulo de Oliven\u{e7}a", "1303908"], + ["AM", "S\u{e3}o Sebasti\u{e3}o do Uatum\u{e3}", "1303957"], + ["AM", "Silves", "1304005"], + ["AM", "Tabatinga", "1304062"], + ["AM", "Tapau\u{e1}", "1304104"], + ["AM", "Tef\u{e9}", "1304203"], + ["AM", "Tonantins", "1304237"], + ["AM", "Uarini", "1304260"], + ["AM", "Urucar\u{e1}", "1304302"], + ["AM", "Urucurituba", "1304401"], + ["BA", "Aba\u{ed}ra", "2900108"], + ["BA", "Abar\u{e9}", "2900207"], + ["BA", "Acajutiba", "2900306"], + ["BA", "Adustina", "2900355"], + ["BA", "\u{c1}gua Fria", "2900405"], + ["BA", "Aiquara", "2900603"], + ["BA", "Alagoinhas", "2900702"], + ["BA", "Alcoba\u{e7}a", "2900801"], + ["BA", "Almadina", "2900900"], + ["BA", "Amargosa", "2901007"], + ["BA", "Am\u{e9}lia Rodrigues", "2901106"], + ["BA", "Am\u{e9}rica Dourada", "2901155"], + ["BA", "Anag\u{e9}", "2901205"], + ["BA", "Andara\u{ed}", "2901304"], + ["BA", "Andorinha", "2901353"], + ["BA", "Angical", "2901403"], + ["BA", "Anguera", "2901502"], + ["BA", "Antas", "2901601"], + ["BA", "Ant\u{f4}nio Cardoso", "2901700"], + ["BA", "Ant\u{f4}nio Gon\u{e7}alves", "2901809"], + ["BA", "Apor\u{e1}", "2901908"], + ["BA", "Apuarema", "2901957"], + ["BA", "Ara\u{e7}\u{e1}s", "2902054"], + ["BA", "Aracatu", "2902005"], + ["BA", "Araci", "2902104"], + ["BA", "Aramari", "2902203"], + ["BA", "Arataca", "2902252"], + ["BA", "Aratu\u{ed}pe", "2902302"], + ["BA", "Aurelino Leal", "2902401"], + ["BA", "Baian\u{f3}polis", "2902500"], + ["BA", "Baixa Grande", "2902609"], + ["BA", "Banza\u{ea}", "2902658"], + ["BA", "Barra", "2902708"], + ["BA", "Barra da Estiva", "2902807"], + ["BA", "Barra do Cho\u{e7}a", "2902906"], + ["BA", "Barra do Mendes", "2903003"], + ["BA", "Barra do Rocha", "2903102"], + ["BA", "Barreiras", "2903201"], + ["BA", "Barro Alto", "2903235"], + ["BA", "Barro Preto", "2903300"], + ["BA", "Barrocas", "2903276"], + ["BA", "Belmonte", "2903409"], + ["BA", "Belo Campo", "2903508"], + ["BA", "Biritinga", "2903607"], + ["BA", "Boa Nova", "2903706"], + ["BA", "Boa Vista do Tupim", "2903805"], + ["BA", "Bom Jesus da Lapa", "2903904"], + ["BA", "Bom Jesus da Serra", "2903953"], + ["BA", "Boninal", "2904001"], + ["BA", "Bonito", "2904050"], + ["BA", "Boquira", "2904100"], + ["BA", "Botupor\u{e3}", "2904209"], + ["BA", "Brej\u{f5}es", "2904308"], + ["BA", "Brejol\u{e2}ndia", "2904407"], + ["BA", "Brotas de Maca\u{fa}bas", "2904506"], + ["BA", "Brumado", "2904605"], + ["BA", "Buerarema", "2904704"], + ["BA", "Buritirama", "2904753"], + ["BA", "Caatiba", "2904803"], + ["BA", "Cabaceiras do Paragua\u{e7}u", "2904852"], + ["BA", "Cachoeira", "2904902"], + ["BA", "Cacul\u{e9}", "2905008"], + ["BA", "Ca\u{e9}m", "2905107"], + ["BA", "Caetanos", "2905156"], + ["BA", "Caetit\u{e9}", "2905206"], + ["BA", "Cafarnaum", "2905305"], + ["BA", "Cairu", "2905404"], + ["BA", "Caldeir\u{e3}o Grande", "2905503"], + ["BA", "Camacan", "2905602"], + ["BA", "Cama\u{e7}ari", "2905701"], + ["BA", "Camamu", "2905800"], + ["BA", "Campo Alegre de Lourdes", "2905909"], + ["BA", "Campo Formoso", "2906006"], + ["BA", "Can\u{e1}polis", "2906105"], + ["BA", "Canarana", "2906204"], + ["BA", "Canavieiras", "2906303"], + ["BA", "Candeal", "2906402"], + ["BA", "Candeias", "2906501"], + ["BA", "Candiba", "2906600"], + ["BA", "C\u{e2}ndido Sales", "2906709"], + ["BA", "Cansan\u{e7}\u{e3}o", "2906808"], + ["BA", "Canudos", "2906824"], + ["BA", "Capela do Alto Alegre", "2906857"], + ["BA", "Capim Grosso", "2906873"], + ["BA", "Cara\u{ed}bas", "2906899"], + ["BA", "Caravelas", "2906907"], + ["BA", "Cardeal da Silva", "2907004"], + ["BA", "Carinhanha", "2907103"], + ["BA", "Casa Nova", "2907202"], + ["BA", "Castro Alves", "2907301"], + ["BA", "Catol\u{e2}ndia", "2907400"], + ["BA", "Catu", "2907509"], + ["BA", "Caturama", "2907558"], + ["BA", "Central", "2907608"], + ["BA", "Chorroch\u{f3}", "2907707"], + ["BA", "C\u{ed}cero Dantas", "2907806"], + ["BA", "Cip\u{f3}", "2907905"], + ["BA", "Coaraci", "2908002"], + ["BA", "Cocos", "2908101"], + ["BA", "Concei\u{e7}\u{e3}o da Feira", "2908200"], + ["BA", "Concei\u{e7}\u{e3}o do Almeida", "2908309"], + ["BA", "Concei\u{e7}\u{e3}o do Coit\u{e9}", "2908408"], + ["BA", "Concei\u{e7}\u{e3}o do Jacu\u{ed}pe", "2908507"], + ["BA", "Conde", "2908606"], + ["BA", "Conde\u{fa}ba", "2908705"], + ["BA", "Contendas do Sincor\u{e1}", "2908804"], + ["BA", "Cora\u{e7}\u{e3}o de Maria", "2908903"], + ["BA", "Cordeiros", "2909000"], + ["BA", "Coribe", "2909109"], + ["BA", "Coronel Jo\u{e3}o S\u{e1}", "2909208"], + ["BA", "Correntina", "2909307"], + ["BA", "Cotegipe", "2909406"], + ["BA", "Cravol\u{e2}ndia", "2909505"], + ["BA", "Cris\u{f3}polis", "2909604"], + ["BA", "Crist\u{f3}polis", "2909703"], + ["BA", "Cruz das Almas", "2909802"], + ["BA", "Cura\u{e7}\u{e1}", "2909901"], + ["BA", "D\u{e1}rio Meira", "2910008"], + ["BA", "Dias d'\u{c1}vila", "2910057"], + ["BA", "Dom Bas\u{ed}lio", "2910107"], + ["BA", "Dom Macedo Costa", "2910206"], + ["BA", "El\u{ed}sio Medrado", "2910305"], + ["BA", "Encruzilhada", "2910404"], + ["BA", "Entre Rios", "2910503"], + ["BA", "\u{c9}rico Cardoso", "2900504"], + ["BA", "Esplanada", "2910602"], + ["BA", "Euclides da Cunha", "2910701"], + ["BA", "Eun\u{e1}polis", "2910727"], + ["BA", "F\u{e1}tima", "2910750"], + ["BA", "Feira da Mata", "2910776"], + ["BA", "Feira de Santana", "2910800"], + ["BA", "Filad\u{e9}lfia", "2910859"], + ["BA", "Firmino Alves", "2910909"], + ["BA", "Floresta Azul", "2911006"], + ["BA", "Formosa do Rio Preto", "2911105"], + ["BA", "Gandu", "2911204"], + ["BA", "Gavi\u{e3}o", "2911253"], + ["BA", "Gentio do Ouro", "2911303"], + ["BA", "Gl\u{f3}ria", "2911402"], + ["BA", "Gongogi", "2911501"], + ["BA", "Governador Mangabeira", "2911600"], + ["BA", "Guajeru", "2911659"], + ["BA", "Guanambi", "2911709"], + ["BA", "Guaratinga", "2911808"], + ["BA", "Heli\u{f3}polis", "2911857"], + ["BA", "Ia\u{e7}u", "2911907"], + ["BA", "Ibiassuc\u{ea}", "2912004"], + ["BA", "Ibicara\u{ed}", "2912103"], + ["BA", "Ibicoara", "2912202"], + ["BA", "Ibicu\u{ed}", "2912301"], + ["BA", "Ibipeba", "2912400"], + ["BA", "Ibipitanga", "2912509"], + ["BA", "Ibiquera", "2912608"], + ["BA", "Ibirapitanga", "2912707"], + ["BA", "Ibirapu\u{e3}", "2912806"], + ["BA", "Ibirataia", "2912905"], + ["BA", "Ibitiara", "2913002"], + ["BA", "Ibitit\u{e1}", "2913101"], + ["BA", "Ibotirama", "2913200"], + ["BA", "Ichu", "2913309"], + ["BA", "Igapor\u{e3}", "2913408"], + ["BA", "Igrapi\u{fa}na", "2913457"], + ["BA", "Igua\u{ed}", "2913507"], + ["BA", "Ilh\u{e9}us", "2913606"], + ["BA", "Inhambupe", "2913705"], + ["BA", "Ipecaet\u{e1}", "2913804"], + ["BA", "Ipia\u{fa}", "2913903"], + ["BA", "Ipir\u{e1}", "2914000"], + ["BA", "Ipupiara", "2914109"], + ["BA", "Irajuba", "2914208"], + ["BA", "Iramaia", "2914307"], + ["BA", "Iraquara", "2914406"], + ["BA", "Irar\u{e1}", "2914505"], + ["BA", "Irec\u{ea}", "2914604"], + ["BA", "Itabela", "2914653"], + ["BA", "Itaberaba", "2914703"], + ["BA", "Itabuna", "2914802"], + ["BA", "Itacar\u{e9}", "2914901"], + ["BA", "Itaet\u{e9}", "2915007"], + ["BA", "Itagi", "2915106"], + ["BA", "Itagib\u{e1}", "2915205"], + ["BA", "Itagimirim", "2915304"], + ["BA", "Itagua\u{e7}u da Bahia", "2915353"], + ["BA", "Itaju do Col\u{f4}nia", "2915403"], + ["BA", "Itaju\u{ed}pe", "2915502"], + ["BA", "Itamaraju", "2915601"], + ["BA", "Itamari", "2915700"], + ["BA", "Itamb\u{e9}", "2915809"], + ["BA", "Itanagra", "2915908"], + ["BA", "Itanh\u{e9}m", "2916005"], + ["BA", "Itaparica", "2916104"], + ["BA", "Itap\u{e9}", "2916203"], + ["BA", "Itapebi", "2916302"], + ["BA", "Itapetinga", "2916401"], + ["BA", "Itapicuru", "2916500"], + ["BA", "Itapitanga", "2916609"], + ["BA", "Itaquara", "2916708"], + ["BA", "Itarantim", "2916807"], + ["BA", "Itatim", "2916856"], + ["BA", "Itiru\u{e7}u", "2916906"], + ["BA", "Iti\u{fa}ba", "2917003"], + ["BA", "Itoror\u{f3}", "2917102"], + ["BA", "Itua\u{e7}u", "2917201"], + ["BA", "Ituber\u{e1}", "2917300"], + ["BA", "Iuiu", "2917334"], + ["BA", "Jaborandi", "2917359"], + ["BA", "Jacaraci", "2917409"], + ["BA", "Jacobina", "2917508"], + ["BA", "Jaguaquara", "2917607"], + ["BA", "Jaguarari", "2917706"], + ["BA", "Jaguaripe", "2917805"], + ["BA", "Janda\u{ed}ra", "2917904"], + ["BA", "Jequi\u{e9}", "2918001"], + ["BA", "Jeremoabo", "2918100"], + ["BA", "Jiquiri\u{e7}\u{e1}", "2918209"], + ["BA", "Jita\u{fa}na", "2918308"], + ["BA", "Jo\u{e3}o Dourado", "2918357"], + ["BA", "Juazeiro", "2918407"], + ["BA", "Jucuru\u{e7}u", "2918456"], + ["BA", "Jussara", "2918506"], + ["BA", "Jussari", "2918555"], + ["BA", "Jussiape", "2918605"], + ["BA", "Lafaiete Coutinho", "2918704"], + ["BA", "Lagoa Real", "2918753"], + ["BA", "Laje", "2918803"], + ["BA", "Lajed\u{e3}o", "2918902"], + ["BA", "Lajedinho", "2919009"], + ["BA", "Lajedo do Tabocal", "2919058"], + ["BA", "Lamar\u{e3}o", "2919108"], + ["BA", "Lap\u{e3}o", "2919157"], + ["BA", "Lauro de Freitas", "2919207"], + ["BA", "Len\u{e7}\u{f3}is", "2919306"], + ["BA", "Lic\u{ed}nio de Almeida", "2919405"], + ["BA", "Livramento de Nossa Senhora", "2919504"], + ["BA", "Lu\u{ed}s Eduardo Magalh\u{e3}es", "2919553"], + ["BA", "Macajuba", "2919603"], + ["BA", "Macarani", "2919702"], + ["BA", "Maca\u{fa}bas", "2919801"], + ["BA", "Macurur\u{e9}", "2919900"], + ["BA", "Madre de Deus", "2919926"], + ["BA", "Maetinga", "2919959"], + ["BA", "Maiquinique", "2920007"], + ["BA", "Mairi", "2920106"], + ["BA", "Malhada", "2920205"], + ["BA", "Malhada de Pedras", "2920304"], + ["BA", "Manoel Vitorino", "2920403"], + ["BA", "Mansid\u{e3}o", "2920452"], + ["BA", "Marac\u{e1}s", "2920502"], + ["BA", "Maragogipe", "2920601"], + ["BA", "Mara\u{fa}", "2920700"], + ["BA", "Marcion\u{ed}lio Souza", "2920809"], + ["BA", "Mascote", "2920908"], + ["BA", "Mata de S\u{e3}o Jo\u{e3}o", "2921005"], + ["BA", "Matina", "2921054"], + ["BA", "Medeiros Neto", "2921104"], + ["BA", "Miguel Calmon", "2921203"], + ["BA", "Milagres", "2921302"], + ["BA", "Mirangaba", "2921401"], + ["BA", "Mirante", "2921450"], + ["BA", "Monte Santo", "2921500"], + ["BA", "Morpar\u{e1}", "2921609"], + ["BA", "Morro do Chap\u{e9}u", "2921708"], + ["BA", "Mortugaba", "2921807"], + ["BA", "Mucug\u{ea}", "2921906"], + ["BA", "Mucuri", "2922003"], + ["BA", "Mulungu do Morro", "2922052"], + ["BA", "Mundo Novo", "2922102"], + ["BA", "Muniz Ferreira", "2922201"], + ["BA", "Muqu\u{e9}m do S\u{e3}o Francisco", "2922250"], + ["BA", "Muritiba", "2922300"], + ["BA", "Mutu\u{ed}pe", "2922409"], + ["BA", "Nazar\u{e9}", "2922508"], + ["BA", "Nilo Pe\u{e7}anha", "2922607"], + ["BA", "Nordestina", "2922656"], + ["BA", "Nova Cana\u{e3}", "2922706"], + ["BA", "Nova F\u{e1}tima", "2922730"], + ["BA", "Nova Ibi\u{e1}", "2922755"], + ["BA", "Nova Itarana", "2922805"], + ["BA", "Nova Reden\u{e7}\u{e3}o", "2922854"], + ["BA", "Nova Soure", "2922904"], + ["BA", "Nova Vi\u{e7}osa", "2923001"], + ["BA", "Novo Horizonte", "2923035"], + ["BA", "Novo Triunfo", "2923050"], + ["BA", "Olindina", "2923100"], + ["BA", "Oliveira dos Brejinhos", "2923209"], + ["BA", "Ouri\u{e7}angas", "2923308"], + ["BA", "Ourol\u{e2}ndia", "2923357"], + ["BA", "Palmas de Monte Alto", "2923407"], + ["BA", "Palmeiras", "2923506"], + ["BA", "Paramirim", "2923605"], + ["BA", "Paratinga", "2923704"], + ["BA", "Paripiranga", "2923803"], + ["BA", "Pau Brasil", "2923902"], + ["BA", "Paulo Afonso", "2924009"], + ["BA", "P\u{e9} de Serra", "2924058"], + ["BA", "Pedr\u{e3}o", "2924108"], + ["BA", "Pedro Alexandre", "2924207"], + ["BA", "Piat\u{e3}", "2924306"], + ["BA", "Pil\u{e3}o Arcado", "2924405"], + ["BA", "Pinda\u{ed}", "2924504"], + ["BA", "Pindoba\u{e7}u", "2924603"], + ["BA", "Pintadas", "2924652"], + ["BA", "Pira\u{ed} do Norte", "2924678"], + ["BA", "Pirip\u{e1}", "2924702"], + ["BA", "Piritiba", "2924801"], + ["BA", "Planaltino", "2924900"], + ["BA", "Planalto", "2925006"], + ["BA", "Po\u{e7}\u{f5}es", "2925105"], + ["BA", "Pojuca", "2925204"], + ["BA", "Ponto Novo", "2925253"], + ["BA", "Porto Seguro", "2925303"], + ["BA", "Potiragu\u{e1}", "2925402"], + ["BA", "Prado", "2925501"], + ["BA", "Presidente Dutra", "2925600"], + ["BA", "Presidente J\u{e2}nio Quadros", "2925709"], + ["BA", "Presidente Tancredo Neves", "2925758"], + ["BA", "Queimadas", "2925808"], + ["BA", "Quijingue", "2925907"], + ["BA", "Quixabeira", "2925931"], + ["BA", "Rafael Jambeiro", "2925956"], + ["BA", "Remanso", "2926004"], + ["BA", "Retirol\u{e2}ndia", "2926103"], + ["BA", "Riach\u{e3}o das Neves", "2926202"], + ["BA", "Riach\u{e3}o do Jacu\u{ed}pe", "2926301"], + ["BA", "Riacho de Santana", "2926400"], + ["BA", "Ribeira do Amparo", "2926509"], + ["BA", "Ribeira do Pombal", "2926608"], + ["BA", "Ribeir\u{e3}o do Largo", "2926657"], + ["BA", "Rio de Contas", "2926707"], + ["BA", "Rio do Ant\u{f4}nio", "2926806"], + ["BA", "Rio do Pires", "2926905"], + ["BA", "Rio Real", "2927002"], + ["BA", "Rodelas", "2927101"], + ["BA", "Ruy Barbosa", "2927200"], + ["BA", "Salinas da Margarida", "2927309"], + ["BA", "Salvador", "2927408"], + ["BA", "Santa B\u{e1}rbara", "2927507"], + ["BA", "Santa Br\u{ed}gida", "2927606"], + ["BA", "Santa Cruz Cabr\u{e1}lia", "2927705"], + ["BA", "Santa Cruz da Vit\u{f3}ria", "2927804"], + ["BA", "Santa In\u{ea}s", "2927903"], + ["BA", "Santa Luzia", "2928059"], + ["BA", "Santa Maria da Vit\u{f3}ria", "2928109"], + ["BA", "Santa Rita de C\u{e1}ssia", "2928406"], + ["BA", "Santa Terezinha", "2928505"], + ["BA", "Santaluz", "2928000"], + ["BA", "Santana", "2928208"], + ["BA", "Santan\u{f3}polis", "2928307"], + ["BA", "Santo Amaro", "2928604"], + ["BA", "Santo Ant\u{f4}nio de Jesus", "2928703"], + ["BA", "Santo Est\u{ea}v\u{e3}o", "2928802"], + ["BA", "S\u{e3}o Desid\u{e9}rio", "2928901"], + ["BA", "S\u{e3}o Domingos", "2928950"], + ["BA", "S\u{e3}o Felipe", "2929107"], + ["BA", "S\u{e3}o F\u{e9}lix", "2929008"], + ["BA", "S\u{e3}o F\u{e9}lix do Coribe", "2929057"], + ["BA", "S\u{e3}o Francisco do Conde", "2929206"], + ["BA", "S\u{e3}o Gabriel", "2929255"], + ["BA", "S\u{e3}o Gon\u{e7}alo dos Campos", "2929305"], + ["BA", "S\u{e3}o Jos\u{e9} da Vit\u{f3}ria", "2929354"], + ["BA", "S\u{e3}o Jos\u{e9} do Jacu\u{ed}pe", "2929370"], + ["BA", "S\u{e3}o Miguel das Matas", "2929404"], + ["BA", "S\u{e3}o Sebasti\u{e3}o do Pass\u{e9}", "2929503"], + ["BA", "Sapea\u{e7}u", "2929602"], + ["BA", "S\u{e1}tiro Dias", "2929701"], + ["BA", "Saubara", "2929750"], + ["BA", "Sa\u{fa}de", "2929800"], + ["BA", "Seabra", "2929909"], + ["BA", "Sebasti\u{e3}o Laranjeiras", "2930006"], + ["BA", "Senhor do Bonfim", "2930105"], + ["BA", "Sento S\u{e9}", "2930204"], + ["BA", "Serra do Ramalho", "2930154"], + ["BA", "Serra Dourada", "2930303"], + ["BA", "Serra Preta", "2930402"], + ["BA", "Serrinha", "2930501"], + ["BA", "Serrol\u{e2}ndia", "2930600"], + ["BA", "Sim\u{f5}es Filho", "2930709"], + ["BA", "S\u{ed}tio do Mato", "2930758"], + ["BA", "S\u{ed}tio do Quinto", "2930766"], + ["BA", "Sobradinho", "2930774"], + ["BA", "Souto Soares", "2930808"], + ["BA", "Tabocas do Brejo Velho", "2930907"], + ["BA", "Tanha\u{e7}u", "2931004"], + ["BA", "Tanque Novo", "2931053"], + ["BA", "Tanquinho", "2931103"], + ["BA", "Tapero\u{e1}", "2931202"], + ["BA", "Tapiramut\u{e1}", "2931301"], + ["BA", "Teixeira de Freitas", "2931350"], + ["BA", "Teodoro Sampaio", "2931400"], + ["BA", "Teofil\u{e2}ndia", "2931509"], + ["BA", "Teol\u{e2}ndia", "2931608"], + ["BA", "Terra Nova", "2931707"], + ["BA", "Tremedal", "2931806"], + ["BA", "Tucano", "2931905"], + ["BA", "Uau\u{e1}", "2932002"], + ["BA", "Uba\u{ed}ra", "2932101"], + ["BA", "Ubaitaba", "2932200"], + ["BA", "Ubat\u{e3}", "2932309"], + ["BA", "Uiba\u{ed}", "2932408"], + ["BA", "Umburanas", "2932457"], + ["BA", "Una", "2932507"], + ["BA", "Urandi", "2932606"], + ["BA", "Uru\u{e7}uca", "2932705"], + ["BA", "Utinga", "2932804"], + ["BA", "Valen\u{e7}a", "2932903"], + ["BA", "Valente", "2933000"], + ["BA", "V\u{e1}rzea da Ro\u{e7}a", "2933059"], + ["BA", "V\u{e1}rzea do Po\u{e7}o", "2933109"], + ["BA", "V\u{e1}rzea Nova", "2933158"], + ["BA", "Varzedo", "2933174"], + ["BA", "Vera Cruz", "2933208"], + ["BA", "Vereda", "2933257"], + ["BA", "Vit\u{f3}ria da Conquista", "2933307"], + ["BA", "Wagner", "2933406"], + ["BA", "Wanderley", "2933455"], + ["BA", "Wenceslau Guimar\u{e3}es", "2933505"], + ["BA", "Xique-Xique", "2933604"], + ["CE", "Abaiara", "2300101"], + ["CE", "Acarape", "2300150"], + ["CE", "Acara\u{fa}", "2300200"], + ["CE", "Acopiara", "2300309"], + ["CE", "Aiuaba", "2300408"], + ["CE", "Alc\u{e2}ntaras", "2300507"], + ["CE", "Altaneira", "2300606"], + ["CE", "Alto Santo", "2300705"], + ["CE", "Amontada", "2300754"], + ["CE", "Antonina do Norte", "2300804"], + ["CE", "Apuiar\u{e9}s", "2300903"], + ["CE", "Aquiraz", "2301000"], + ["CE", "Aracati", "2301109"], + ["CE", "Aracoiaba", "2301208"], + ["CE", "Ararend\u{e1}", "2301257"], + ["CE", "Araripe", "2301307"], + ["CE", "Aratuba", "2301406"], + ["CE", "Arneiroz", "2301505"], + ["CE", "Assar\u{e9}", "2301604"], + ["CE", "Aurora", "2301703"], + ["CE", "Baixio", "2301802"], + ["CE", "Banabui\u{fa}", "2301851"], + ["CE", "Barbalha", "2301901"], + ["CE", "Barreira", "2301950"], + ["CE", "Barro", "2302008"], + ["CE", "Barroquinha", "2302057"], + ["CE", "Baturit\u{e9}", "2302107"], + ["CE", "Beberibe", "2302206"], + ["CE", "Bela Cruz", "2302305"], + ["CE", "Boa Viagem", "2302404"], + ["CE", "Brejo Santo", "2302503"], + ["CE", "Camocim", "2302602"], + ["CE", "Campos Sales", "2302701"], + ["CE", "Canind\u{e9}", "2302800"], + ["CE", "Capistrano", "2302909"], + ["CE", "Caridade", "2303006"], + ["CE", "Carir\u{e9}", "2303105"], + ["CE", "Cariria\u{e7}u", "2303204"], + ["CE", "Cari\u{fa}s", "2303303"], + ["CE", "Carnaubal", "2303402"], + ["CE", "Cascavel", "2303501"], + ["CE", "Catarina", "2303600"], + ["CE", "Catunda", "2303659"], + ["CE", "Caucaia", "2303709"], + ["CE", "Cedro", "2303808"], + ["CE", "Chaval", "2303907"], + ["CE", "Chor\u{f3}", "2303931"], + ["CE", "Chorozinho", "2303956"], + ["CE", "Corea\u{fa}", "2304004"], + ["CE", "Crate\u{fa}s", "2304103"], + ["CE", "Crato", "2304202"], + ["CE", "Croat\u{e1}", "2304236"], + ["CE", "Cruz", "2304251"], + ["CE", "Deputado Irapuan Pinheiro", "2304269"], + ["CE", "Erer\u{e9}", "2304277"], + ["CE", "Eus\u{e9}bio", "2304285"], + ["CE", "Farias Brito", "2304301"], + ["CE", "Forquilha", "2304350"], + ["CE", "Fortaleza", "2304400"], + ["CE", "Fortim", "2304459"], + ["CE", "Frecheirinha", "2304509"], + ["CE", "General Sampaio", "2304608"], + ["CE", "Gra\u{e7}a", "2304657"], + ["CE", "Granja", "2304707"], + ["CE", "Granjeiro", "2304806"], + ["CE", "Groa\u{ed}ras", "2304905"], + ["CE", "Guai\u{fa}ba", "2304954"], + ["CE", "Guaraciaba do Norte", "2305001"], + ["CE", "Guaramiranga", "2305100"], + ["CE", "Hidrol\u{e2}ndia", "2305209"], + ["CE", "Horizonte", "2305233"], + ["CE", "Ibaretama", "2305266"], + ["CE", "Ibiapina", "2305308"], + ["CE", "Ibicuitinga", "2305332"], + ["CE", "Icapu\u{ed}", "2305357"], + ["CE", "Ic\u{f3}", "2305407"], + ["CE", "Iguatu", "2305506"], + ["CE", "Independ\u{ea}ncia", "2305605"], + ["CE", "Ipaporanga", "2305654"], + ["CE", "Ipaumirim", "2305704"], + ["CE", "Ipu", "2305803"], + ["CE", "Ipueiras", "2305902"], + ["CE", "Iracema", "2306009"], + ["CE", "Irau\u{e7}uba", "2306108"], + ["CE", "Itai\u{e7}aba", "2306207"], + ["CE", "Itaitinga", "2306256"], + ["CE", "Itapaj\u{e9}", "2306306"], + ["CE", "Itapipoca", "2306405"], + ["CE", "Itapi\u{fa}na", "2306504"], + ["CE", "Itarema", "2306553"], + ["CE", "Itatira", "2306603"], + ["CE", "Jaguaretama", "2306702"], + ["CE", "Jaguaribara", "2306801"], + ["CE", "Jaguaribe", "2306900"], + ["CE", "Jaguaruana", "2307007"], + ["CE", "Jardim", "2307106"], + ["CE", "Jati", "2307205"], + ["CE", "Jijoca de Jericoacoara", "2307254"], + ["CE", "Juazeiro do Norte", "2307304"], + ["CE", "Juc\u{e1}s", "2307403"], + ["CE", "Lavras da Mangabeira", "2307502"], + ["CE", "Limoeiro do Norte", "2307601"], + ["CE", "Madalena", "2307635"], + ["CE", "Maracana\u{fa}", "2307650"], + ["CE", "Maranguape", "2307700"], + ["CE", "Marco", "2307809"], + ["CE", "Martin\u{f3}pole", "2307908"], + ["CE", "Massap\u{ea}", "2308005"], + ["CE", "Mauriti", "2308104"], + ["CE", "Meruoca", "2308203"], + ["CE", "Milagres", "2308302"], + ["CE", "Milh\u{e3}", "2308351"], + ["CE", "Mira\u{ed}ma", "2308377"], + ["CE", "Miss\u{e3}o Velha", "2308401"], + ["CE", "Momba\u{e7}a", "2308500"], + ["CE", "Monsenhor Tabosa", "2308609"], + ["CE", "Morada Nova", "2308708"], + ["CE", "Mora\u{fa}jo", "2308807"], + ["CE", "Morrinhos", "2308906"], + ["CE", "Mucambo", "2309003"], + ["CE", "Mulungu", "2309102"], + ["CE", "Nova Olinda", "2309201"], + ["CE", "Nova Russas", "2309300"], + ["CE", "Novo Oriente", "2309409"], + ["CE", "Ocara", "2309458"], + ["CE", "Or\u{f3}s", "2309508"], + ["CE", "Pacajus", "2309607"], + ["CE", "Pacatuba", "2309706"], + ["CE", "Pacoti", "2309805"], + ["CE", "Pacuj\u{e1}", "2309904"], + ["CE", "Palhano", "2310001"], + ["CE", "Palm\u{e1}cia", "2310100"], + ["CE", "Paracuru", "2310209"], + ["CE", "Paraipaba", "2310258"], + ["CE", "Parambu", "2310308"], + ["CE", "Paramoti", "2310407"], + ["CE", "Pedra Branca", "2310506"], + ["CE", "Penaforte", "2310605"], + ["CE", "Pentecoste", "2310704"], + ["CE", "Pereiro", "2310803"], + ["CE", "Pindoretama", "2310852"], + ["CE", "Piquet Carneiro", "2310902"], + ["CE", "Pires Ferreira", "2310951"], + ["CE", "Poranga", "2311009"], + ["CE", "Porteiras", "2311108"], + ["CE", "Potengi", "2311207"], + ["CE", "Potiretama", "2311231"], + ["CE", "Quiterian\u{f3}polis", "2311264"], + ["CE", "Quixad\u{e1}", "2311306"], + ["CE", "Quixel\u{f4}", "2311355"], + ["CE", "Quixeramobim", "2311405"], + ["CE", "Quixer\u{e9}", "2311504"], + ["CE", "Reden\u{e7}\u{e3}o", "2311603"], + ["CE", "Reriutaba", "2311702"], + ["CE", "Russas", "2311801"], + ["CE", "Saboeiro", "2311900"], + ["CE", "Salitre", "2311959"], + ["CE", "Santa Quit\u{e9}ria", "2312205"], + ["CE", "Santana do Acara\u{fa}", "2312007"], + ["CE", "Santana do Cariri", "2312106"], + ["CE", "S\u{e3}o Benedito", "2312304"], + ["CE", "S\u{e3}o Gon\u{e7}alo do Amarante", "2312403"], + ["CE", "S\u{e3}o Jo\u{e3}o do Jaguaribe", "2312502"], + ["CE", "S\u{e3}o Lu\u{ed}s do Curu", "2312601"], + ["CE", "Senador Pompeu", "2312700"], + ["CE", "Senador S\u{e1}", "2312809"], + ["CE", "Sobral", "2312908"], + ["CE", "Solon\u{f3}pole", "2313005"], + ["CE", "Tabuleiro do Norte", "2313104"], + ["CE", "Tamboril", "2313203"], + ["CE", "Tarrafas", "2313252"], + ["CE", "Tau\u{e1}", "2313302"], + ["CE", "Teju\u{e7}uoca", "2313351"], + ["CE", "Tiangu\u{e1}", "2313401"], + ["CE", "Trairi", "2313500"], + ["CE", "Tururu", "2313559"], + ["CE", "Ubajara", "2313609"], + ["CE", "Umari", "2313708"], + ["CE", "Umirim", "2313757"], + ["CE", "Uruburetama", "2313807"], + ["CE", "Uruoca", "2313906"], + ["CE", "Varjota", "2313955"], + ["CE", "V\u{e1}rzea Alegre", "2314003"], + ["CE", "Vi\u{e7}osa do Cear\u{e1}", "2314102"], + ["DF", "Bras\u{ed}lia", "5300108"], + ["ES", "Afonso Cl\u{e1}udio", "3200102"], + ["ES", "\u{c1}gua Doce do Norte", "3200169"], + ["ES", "\u{c1}guia Branca", "3200136"], + ["ES", "Alegre", "3200201"], + ["ES", "Alfredo Chaves", "3200300"], + ["ES", "Alto Rio Novo", "3200359"], + ["ES", "Anchieta", "3200409"], + ["ES", "Apiac\u{e1}", "3200508"], + ["ES", "Aracruz", "3200607"], + ["ES", "At\u{ed}lio Viv\u{e1}cqua", "3200706"], + ["ES", "Baixo Guandu", "3200805"], + ["ES", "Barra de S\u{e3}o Francisco", "3200904"], + ["ES", "Boa Esperan\u{e7}a", "3201001"], + ["ES", "Bom Jesus do Norte", "3201100"], + ["ES", "Brejetuba", "3201159"], + ["ES", "Cachoeiro de Itapemirim", "3201209"], + ["ES", "Cariacica", "3201308"], + ["ES", "Castelo", "3201407"], + ["ES", "Colatina", "3201506"], + ["ES", "Concei\u{e7}\u{e3}o da Barra", "3201605"], + ["ES", "Concei\u{e7}\u{e3}o do Castelo", "3201704"], + ["ES", "Divino de S\u{e3}o Louren\u{e7}o", "3201803"], + ["ES", "Domingos Martins", "3201902"], + ["ES", "Dores do Rio Preto", "3202009"], + ["ES", "Ecoporanga", "3202108"], + ["ES", "Fund\u{e3}o", "3202207"], + ["ES", "Governador Lindenberg", "3202256"], + ["ES", "Gua\u{e7}u\u{ed}", "3202306"], + ["ES", "Guarapari", "3202405"], + ["ES", "Ibatiba", "3202454"], + ["ES", "Ibira\u{e7}u", "3202504"], + ["ES", "Ibitirama", "3202553"], + ["ES", "Iconha", "3202603"], + ["ES", "Irupi", "3202652"], + ["ES", "Itagua\u{e7}u", "3202702"], + ["ES", "Itapemirim", "3202801"], + ["ES", "Itarana", "3202900"], + ["ES", "I\u{fa}na", "3203007"], + ["ES", "Jaguar\u{e9}", "3203056"], + ["ES", "Jer\u{f4}nimo Monteiro", "3203106"], + ["ES", "Jo\u{e3}o Neiva", "3203130"], + ["ES", "Laranja da Terra", "3203163"], + ["ES", "Linhares", "3203205"], + ["ES", "Manten\u{f3}polis", "3203304"], + ["ES", "Marata\u{ed}zes", "3203320"], + ["ES", "Marechal Floriano", "3203346"], + ["ES", "Maril\u{e2}ndia", "3203353"], + ["ES", "Mimoso do Sul", "3203403"], + ["ES", "Montanha", "3203502"], + ["ES", "Mucurici", "3203601"], + ["ES", "Muniz Freire", "3203700"], + ["ES", "Muqui", "3203809"], + ["ES", "Nova Ven\u{e9}cia", "3203908"], + ["ES", "Pancas", "3204005"], + ["ES", "Pedro Can\u{e1}rio", "3204054"], + ["ES", "Pinheiros", "3204104"], + ["ES", "Pi\u{fa}ma", "3204203"], + ["ES", "Ponto Belo", "3204252"], + ["ES", "Presidente Kennedy", "3204302"], + ["ES", "Rio Bananal", "3204351"], + ["ES", "Rio Novo do Sul", "3204401"], + ["ES", "Santa Leopoldina", "3204500"], + ["ES", "Santa Maria de Jetib\u{e1}", "3204559"], + ["ES", "Santa Teresa", "3204609"], + ["ES", "S\u{e3}o Domingos do Norte", "3204658"], + ["ES", "S\u{e3}o Gabriel da Palha", "3204708"], + ["ES", "S\u{e3}o Jos\u{e9} do Cal\u{e7}ado", "3204807"], + ["ES", "S\u{e3}o Mateus", "3204906"], + ["ES", "S\u{e3}o Roque do Cana\u{e3}", "3204955"], + ["ES", "Serra", "3205002"], + ["ES", "Sooretama", "3205010"], + ["ES", "Vargem Alta", "3205036"], + ["ES", "Venda Nova do Imigrante", "3205069"], + ["ES", "Viana", "3205101"], + ["ES", "Vila Pav\u{e3}o", "3205150"], + ["ES", "Vila Val\u{e9}rio", "3205176"], + ["ES", "Vila Velha", "3205200"], + ["ES", "Vit\u{f3}ria", "3205309"], + ["GO", "Abadia de Goi\u{e1}s", "5200050"], + ["GO", "Abadi\u{e2}nia", "5200100"], + ["GO", "Acre\u{fa}na", "5200134"], + ["GO", "Adel\u{e2}ndia", "5200159"], + ["GO", "\u{c1}gua Fria de Goi\u{e1}s", "5200175"], + ["GO", "\u{c1}gua Limpa", "5200209"], + ["GO", "\u{c1}guas Lindas de Goi\u{e1}s", "5200258"], + ["GO", "Alex\u{e2}nia", "5200308"], + ["GO", "Alo\u{e2}ndia", "5200506"], + ["GO", "Alto Horizonte", "5200555"], + ["GO", "Alto Para\u{ed}so de Goi\u{e1}s", "5200605"], + ["GO", "Alvorada do Norte", "5200803"], + ["GO", "Amaralina", "5200829"], + ["GO", "Americano do Brasil", "5200852"], + ["GO", "Amorin\u{f3}polis", "5200902"], + ["GO", "An\u{e1}polis", "5201108"], + ["GO", "Anhanguera", "5201207"], + ["GO", "Anicuns", "5201306"], + ["GO", "Aparecida de Goi\u{e2}nia", "5201405"], + ["GO", "Aparecida do Rio Doce", "5201454"], + ["GO", "Apor\u{e9}", "5201504"], + ["GO", "Ara\u{e7}u", "5201603"], + ["GO", "Aragar\u{e7}as", "5201702"], + ["GO", "Aragoi\u{e2}nia", "5201801"], + ["GO", "Araguapaz", "5202155"], + ["GO", "Aren\u{f3}polis", "5202353"], + ["GO", "Aruan\u{e3}", "5202502"], + ["GO", "Auril\u{e2}ndia", "5202601"], + ["GO", "Avelin\u{f3}polis", "5202809"], + ["GO", "Baliza", "5203104"], + ["GO", "Barro Alto", "5203203"], + ["GO", "Bela Vista de Goi\u{e1}s", "5203302"], + ["GO", "Bom Jardim de Goi\u{e1}s", "5203401"], + ["GO", "Bom Jesus de Goi\u{e1}s", "5203500"], + ["GO", "Bonfin\u{f3}polis", "5203559"], + ["GO", "Bon\u{f3}polis", "5203575"], + ["GO", "Brazabrantes", "5203609"], + ["GO", "Brit\u{e2}nia", "5203807"], + ["GO", "Buriti Alegre", "5203906"], + ["GO", "Buriti de Goi\u{e1}s", "5203939"], + ["GO", "Buritin\u{f3}polis", "5203962"], + ["GO", "Cabeceiras", "5204003"], + ["GO", "Cachoeira Alta", "5204102"], + ["GO", "Cachoeira de Goi\u{e1}s", "5204201"], + ["GO", "Cachoeira Dourada", "5204250"], + ["GO", "Ca\u{e7}u", "5204300"], + ["GO", "Caiap\u{f4}nia", "5204409"], + ["GO", "Caldas Novas", "5204508"], + ["GO", "Caldazinha", "5204557"], + ["GO", "Campestre de Goi\u{e1}s", "5204607"], + ["GO", "Campina\u{e7}u", "5204656"], + ["GO", "Campinorte", "5204706"], + ["GO", "Campo Alegre de Goi\u{e1}s", "5204805"], + ["GO", "Campo Limpo de Goi\u{e1}s", "5204854"], + ["GO", "Campos Belos", "5204904"], + ["GO", "Campos Verdes", "5204953"], + ["GO", "Carmo do Rio Verde", "5205000"], + ["GO", "Castel\u{e2}ndia", "5205059"], + ["GO", "Catal\u{e3}o", "5205109"], + ["GO", "Catura\u{ed}", "5205208"], + ["GO", "Cavalcante", "5205307"], + ["GO", "Ceres", "5205406"], + ["GO", "Cezarina", "5205455"], + ["GO", "Chapad\u{e3}o do C\u{e9}u", "5205471"], + ["GO", "Cidade Ocidental", "5205497"], + ["GO", "Cocalzinho de Goi\u{e1}s", "5205513"], + ["GO", "Colinas do Sul", "5205521"], + ["GO", "C\u{f3}rrego do Ouro", "5205703"], + ["GO", "Corumb\u{e1} de Goi\u{e1}s", "5205802"], + ["GO", "Corumba\u{ed}ba", "5205901"], + ["GO", "Cristalina", "5206206"], + ["GO", "Cristian\u{f3}polis", "5206305"], + ["GO", "Crix\u{e1}s", "5206404"], + ["GO", "Crom\u{ed}nia", "5206503"], + ["GO", "Cumari", "5206602"], + ["GO", "Damian\u{f3}polis", "5206701"], + ["GO", "Damol\u{e2}ndia", "5206800"], + ["GO", "Davin\u{f3}polis", "5206909"], + ["GO", "Diorama", "5207105"], + ["GO", "Divin\u{f3}polis de Goi\u{e1}s", "5208301"], + ["GO", "Doverl\u{e2}ndia", "5207253"], + ["GO", "Edealina", "5207352"], + ["GO", "Ed\u{e9}ia", "5207402"], + ["GO", "Estrela do Norte", "5207501"], + ["GO", "Faina", "5207535"], + ["GO", "Fazenda Nova", "5207600"], + ["GO", "Firmin\u{f3}polis", "5207808"], + ["GO", "Flores de Goi\u{e1}s", "5207907"], + ["GO", "Formosa", "5208004"], + ["GO", "Formoso", "5208103"], + ["GO", "Gameleira de Goi\u{e1}s", "5208152"], + ["GO", "Goian\u{e1}polis", "5208400"], + ["GO", "Goiandira", "5208509"], + ["GO", "Goian\u{e9}sia", "5208608"], + ["GO", "Goi\u{e2}nia", "5208707"], + ["GO", "Goianira", "5208806"], + ["GO", "Goi\u{e1}s", "5208905"], + ["GO", "Goiatuba", "5209101"], + ["GO", "Gouvel\u{e2}ndia", "5209150"], + ["GO", "Guap\u{f3}", "5209200"], + ["GO", "Guara\u{ed}ta", "5209291"], + ["GO", "Guarani de Goi\u{e1}s", "5209408"], + ["GO", "Guarinos", "5209457"], + ["GO", "Heitora\u{ed}", "5209606"], + ["GO", "Hidrol\u{e2}ndia", "5209705"], + ["GO", "Hidrolina", "5209804"], + ["GO", "Iaciara", "5209903"], + ["GO", "Inaciol\u{e2}ndia", "5209937"], + ["GO", "Indiara", "5209952"], + ["GO", "Inhumas", "5210000"], + ["GO", "Ipameri", "5210109"], + ["GO", "Ipiranga de Goi\u{e1}s", "5210158"], + ["GO", "Ipor\u{e1}", "5210208"], + ["GO", "Israel\u{e2}ndia", "5210307"], + ["GO", "Itabera\u{ed}", "5210406"], + ["GO", "Itaguari", "5210562"], + ["GO", "Itaguaru", "5210604"], + ["GO", "Itaj\u{e1}", "5210802"], + ["GO", "Itapaci", "5210901"], + ["GO", "Itapirapu\u{e3}", "5211008"], + ["GO", "Itapuranga", "5211206"], + ["GO", "Itarum\u{e3}", "5211305"], + ["GO", "Itau\u{e7}u", "5211404"], + ["GO", "Itumbiara", "5211503"], + ["GO", "Ivol\u{e2}ndia", "5211602"], + ["GO", "Jandaia", "5211701"], + ["GO", "Jaragu\u{e1}", "5211800"], + ["GO", "Jata\u{ed}", "5211909"], + ["GO", "Jaupaci", "5212006"], + ["GO", "Jes\u{fa}polis", "5212055"], + ["GO", "Jovi\u{e2}nia", "5212105"], + ["GO", "Jussara", "5212204"], + ["GO", "Lagoa Santa", "5212253"], + ["GO", "Leopoldo de Bulh\u{f5}es", "5212303"], + ["GO", "Luzi\u{e2}nia", "5212501"], + ["GO", "Mairipotaba", "5212600"], + ["GO", "Mamba\u{ed}", "5212709"], + ["GO", "Mara Rosa", "5212808"], + ["GO", "Marzag\u{e3}o", "5212907"], + ["GO", "Matrinch\u{e3}", "5212956"], + ["GO", "Mauril\u{e2}ndia", "5213004"], + ["GO", "Mimoso de Goi\u{e1}s", "5213053"], + ["GO", "Mina\u{e7}u", "5213087"], + ["GO", "Mineiros", "5213103"], + ["GO", "Moipor\u{e1}", "5213400"], + ["GO", "Monte Alegre de Goi\u{e1}s", "5213509"], + ["GO", "Montes Claros de Goi\u{e1}s", "5213707"], + ["GO", "Montividiu", "5213756"], + ["GO", "Montividiu do Norte", "5213772"], + ["GO", "Morrinhos", "5213806"], + ["GO", "Morro Agudo de Goi\u{e1}s", "5213855"], + ["GO", "Moss\u{e2}medes", "5213905"], + ["GO", "Mozarl\u{e2}ndia", "5214002"], + ["GO", "Mundo Novo", "5214051"], + ["GO", "Mutun\u{f3}polis", "5214101"], + ["GO", "Naz\u{e1}rio", "5214408"], + ["GO", "Ner\u{f3}polis", "5214507"], + ["GO", "Niquel\u{e2}ndia", "5214606"], + ["GO", "Nova Am\u{e9}rica", "5214705"], + ["GO", "Nova Aurora", "5214804"], + ["GO", "Nova Crix\u{e1}s", "5214838"], + ["GO", "Nova Gl\u{f3}ria", "5214861"], + ["GO", "Nova Igua\u{e7}u de Goi\u{e1}s", "5214879"], + ["GO", "Nova Roma", "5214903"], + ["GO", "Nova Veneza", "5215009"], + ["GO", "Novo Brasil", "5215207"], + ["GO", "Novo Gama", "5215231"], + ["GO", "Novo Planalto", "5215256"], + ["GO", "Orizona", "5215306"], + ["GO", "Ouro Verde de Goi\u{e1}s", "5215405"], + ["GO", "Ouvidor", "5215504"], + ["GO", "Padre Bernardo", "5215603"], + ["GO", "Palestina de Goi\u{e1}s", "5215652"], + ["GO", "Palmeiras de Goi\u{e1}s", "5215702"], + ["GO", "Palmelo", "5215801"], + ["GO", "Palmin\u{f3}polis", "5215900"], + ["GO", "Panam\u{e1}", "5216007"], + ["GO", "Paranaiguara", "5216304"], + ["GO", "Para\u{fa}na", "5216403"], + ["GO", "Perol\u{e2}ndia", "5216452"], + ["GO", "Petrolina de Goi\u{e1}s", "5216809"], + ["GO", "Pilar de Goi\u{e1}s", "5216908"], + ["GO", "Piracanjuba", "5217104"], + ["GO", "Piranhas", "5217203"], + ["GO", "Piren\u{f3}polis", "5217302"], + ["GO", "Pires do Rio", "5217401"], + ["GO", "Planaltina", "5217609"], + ["GO", "Pontalina", "5217708"], + ["GO", "Porangatu", "5218003"], + ["GO", "Porteir\u{e3}o", "5218052"], + ["GO", "Portel\u{e2}ndia", "5218102"], + ["GO", "Posse", "5218300"], + ["GO", "Professor Jamil", "5218391"], + ["GO", "Quirin\u{f3}polis", "5218508"], + ["GO", "Rialma", "5218607"], + ["GO", "Rian\u{e1}polis", "5218706"], + ["GO", "Rio Quente", "5218789"], + ["GO", "Rio Verde", "5218805"], + ["GO", "Rubiataba", "5218904"], + ["GO", "Sanclerl\u{e2}ndia", "5219001"], + ["GO", "Santa B\u{e1}rbara de Goi\u{e1}s", "5219100"], + ["GO", "Santa Cruz de Goi\u{e1}s", "5219209"], + ["GO", "Santa F\u{e9} de Goi\u{e1}s", "5219258"], + ["GO", "Santa Helena de Goi\u{e1}s", "5219308"], + ["GO", "Santa Isabel", "5219357"], + ["GO", "Santa Rita do Araguaia", "5219407"], + ["GO", "Santa Rita do Novo Destino", "5219456"], + ["GO", "Santa Rosa de Goi\u{e1}s", "5219506"], + ["GO", "Santa Tereza de Goi\u{e1}s", "5219605"], + ["GO", "Santa Terezinha de Goi\u{e1}s", "5219704"], + ["GO", "Santo Ant\u{f4}nio da Barra", "5219712"], + ["GO", "Santo Ant\u{f4}nio de Goi\u{e1}s", "5219738"], + ["GO", "Santo Ant\u{f4}nio do Descoberto", "5219753"], + ["GO", "S\u{e3}o Domingos", "5219803"], + ["GO", "S\u{e3}o Francisco de Goi\u{e1}s", "5219902"], + ["GO", "S\u{e3}o Jo\u{e3}o d'Alian\u{e7}a", "5220009"], + ["GO", "S\u{e3}o Jo\u{e3}o da Para\u{fa}na", "5220058"], + ["GO", "S\u{e3}o Lu\u{ed}s de Montes Belos", "5220108"], + ["GO", "S\u{e3}o Luiz do Norte", "5220157"], + ["GO", "S\u{e3}o Miguel do Araguaia", "5220207"], + ["GO", "S\u{e3}o Miguel do Passa Quatro", "5220264"], + ["GO", "S\u{e3}o Patr\u{ed}cio", "5220280"], + ["GO", "S\u{e3}o Sim\u{e3}o", "5220405"], + ["GO", "Senador Canedo", "5220454"], + ["GO", "Serran\u{f3}polis", "5220504"], + ["GO", "Silv\u{e2}nia", "5220603"], + ["GO", "Simol\u{e2}ndia", "5220686"], + ["GO", "S\u{ed}tio d'Abadia", "5220702"], + ["GO", "Taquaral de Goi\u{e1}s", "5221007"], + ["GO", "Teresina de Goi\u{e1}s", "5221080"], + ["GO", "Terez\u{f3}polis de Goi\u{e1}s", "5221197"], + ["GO", "Tr\u{ea}s Ranchos", "5221304"], + ["GO", "Trindade", "5221403"], + ["GO", "Trombas", "5221452"], + ["GO", "Turv\u{e2}nia", "5221502"], + ["GO", "Turvel\u{e2}ndia", "5221551"], + ["GO", "Uirapuru", "5221577"], + ["GO", "Urua\u{e7}u", "5221601"], + ["GO", "Uruana", "5221700"], + ["GO", "Uruta\u{ed}", "5221809"], + ["GO", "Valpara\u{ed}so de Goi\u{e1}s", "5221858"], + ["GO", "Varj\u{e3}o", "5221908"], + ["GO", "Vian\u{f3}polis", "5222005"], + ["GO", "Vicentin\u{f3}polis", "5222054"], + ["GO", "Vila Boa", "5222203"], + ["GO", "Vila Prop\u{ed}cio", "5222302"], + ["MA", "A\u{e7}ail\u{e2}ndia", "2100055"], + ["MA", "Afonso Cunha", "2100105"], + ["MA", "\u{c1}gua Doce do Maranh\u{e3}o", "2100154"], + ["MA", "Alc\u{e2}ntara", "2100204"], + ["MA", "Aldeias Altas", "2100303"], + ["MA", "Altamira do Maranh\u{e3}o", "2100402"], + ["MA", "Alto Alegre do Maranh\u{e3}o", "2100436"], + ["MA", "Alto Alegre do Pindar\u{e9}", "2100477"], + ["MA", "Alto Parna\u{ed}ba", "2100501"], + ["MA", "Amap\u{e1} do Maranh\u{e3}o", "2100550"], + ["MA", "Amarante do Maranh\u{e3}o", "2100600"], + ["MA", "Anajatuba", "2100709"], + ["MA", "Anapurus", "2100808"], + ["MA", "Apicum-A\u{e7}u", "2100832"], + ["MA", "Araguan\u{e3}", "2100873"], + ["MA", "Araioses", "2100907"], + ["MA", "Arame", "2100956"], + ["MA", "Arari", "2101004"], + ["MA", "Axix\u{e1}", "2101103"], + ["MA", "Bacabal", "2101202"], + ["MA", "Bacabeira", "2101251"], + ["MA", "Bacuri", "2101301"], + ["MA", "Bacurituba", "2101350"], + ["MA", "Balsas", "2101400"], + ["MA", "Bar\u{e3}o de Graja\u{fa}", "2101509"], + ["MA", "Barra do Corda", "2101608"], + ["MA", "Barreirinhas", "2101707"], + ["MA", "Bela Vista do Maranh\u{e3}o", "2101772"], + ["MA", "Bel\u{e1}gua", "2101731"], + ["MA", "Benedito Leite", "2101806"], + ["MA", "Bequim\u{e3}o", "2101905"], + ["MA", "Bernardo do Mearim", "2101939"], + ["MA", "Boa Vista do Gurupi", "2101970"], + ["MA", "Bom Jardim", "2102002"], + ["MA", "Bom Jesus das Selvas", "2102036"], + ["MA", "Bom Lugar", "2102077"], + ["MA", "Brejo", "2102101"], + ["MA", "Brejo de Areia", "2102150"], + ["MA", "Buriti", "2102200"], + ["MA", "Buriti Bravo", "2102309"], + ["MA", "Buriticupu", "2102325"], + ["MA", "Buritirana", "2102358"], + ["MA", "Cachoeira Grande", "2102374"], + ["MA", "Cajapi\u{f3}", "2102408"], + ["MA", "Cajari", "2102507"], + ["MA", "Campestre do Maranh\u{e3}o", "2102556"], + ["MA", "C\u{e2}ndido Mendes", "2102606"], + ["MA", "Cantanhede", "2102705"], + ["MA", "Capinzal do Norte", "2102754"], + ["MA", "Carolina", "2102804"], + ["MA", "Carutapera", "2102903"], + ["MA", "Caxias", "2103000"], + ["MA", "Cedral", "2103109"], + ["MA", "Central do Maranh\u{e3}o", "2103125"], + ["MA", "Centro do Guilherme", "2103158"], + ["MA", "Centro Novo do Maranh\u{e3}o", "2103174"], + ["MA", "Chapadinha", "2103208"], + ["MA", "Cidel\u{e2}ndia", "2103257"], + ["MA", "Cod\u{f3}", "2103307"], + ["MA", "Coelho Neto", "2103406"], + ["MA", "Colinas", "2103505"], + ["MA", "Concei\u{e7}\u{e3}o do Lago-A\u{e7}u", "2103554"], + ["MA", "Coroat\u{e1}", "2103604"], + ["MA", "Cururupu", "2103703"], + ["MA", "Davin\u{f3}polis", "2103752"], + ["MA", "Dom Pedro", "2103802"], + ["MA", "Duque Bacelar", "2103901"], + ["MA", "Esperantin\u{f3}polis", "2104008"], + ["MA", "Estreito", "2104057"], + ["MA", "Feira Nova do Maranh\u{e3}o", "2104073"], + ["MA", "Fernando Falc\u{e3}o", "2104081"], + ["MA", "Formosa da Serra Negra", "2104099"], + ["MA", "Fortaleza dos Nogueiras", "2104107"], + ["MA", "Fortuna", "2104206"], + ["MA", "Godofredo Viana", "2104305"], + ["MA", "Gon\u{e7}alves Dias", "2104404"], + ["MA", "Governador Archer", "2104503"], + ["MA", "Governador Edison Lob\u{e3}o", "2104552"], + ["MA", "Governador Eug\u{ea}nio Barros", "2104602"], + ["MA", "Governador Luiz Rocha", "2104628"], + ["MA", "Governador Newton Bello", "2104651"], + ["MA", "Governador Nunes Freire", "2104677"], + ["MA", "Gra\u{e7}a Aranha", "2104701"], + ["MA", "Graja\u{fa}", "2104800"], + ["MA", "Guimar\u{e3}es", "2104909"], + ["MA", "Humberto de Campos", "2105005"], + ["MA", "Icatu", "2105104"], + ["MA", "Igarap\u{e9} do Meio", "2105153"], + ["MA", "Igarap\u{e9} Grande", "2105203"], + ["MA", "Imperatriz", "2105302"], + ["MA", "Itaipava do Graja\u{fa}", "2105351"], + ["MA", "Itapecuru Mirim", "2105401"], + ["MA", "Itinga do Maranh\u{e3}o", "2105427"], + ["MA", "Jatob\u{e1}", "2105450"], + ["MA", "Jenipapo dos Vieiras", "2105476"], + ["MA", "Jo\u{e3}o Lisboa", "2105500"], + ["MA", "Josel\u{e2}ndia", "2105609"], + ["MA", "Junco do Maranh\u{e3}o", "2105658"], + ["MA", "Lago da Pedra", "2105708"], + ["MA", "Lago do Junco", "2105807"], + ["MA", "Lago dos Rodrigues", "2105948"], + ["MA", "Lago Verde", "2105906"], + ["MA", "Lagoa do Mato", "2105922"], + ["MA", "Lagoa Grande do Maranh\u{e3}o", "2105963"], + ["MA", "Lajeado Novo", "2105989"], + ["MA", "Lima Campos", "2106003"], + ["MA", "Loreto", "2106102"], + ["MA", "Lu\u{ed}s Domingues", "2106201"], + ["MA", "Magalh\u{e3}es de Almeida", "2106300"], + ["MA", "Maraca\u{e7}um\u{e9}", "2106326"], + ["MA", "Maraj\u{e1} do Sena", "2106359"], + ["MA", "Maranh\u{e3}ozinho", "2106375"], + ["MA", "Mata Roma", "2106409"], + ["MA", "Matinha", "2106508"], + ["MA", "Mat\u{f5}es", "2106607"], + ["MA", "Mat\u{f5}es do Norte", "2106631"], + ["MA", "Milagres do Maranh\u{e3}o", "2106672"], + ["MA", "Mirador", "2106706"], + ["MA", "Miranda do Norte", "2106755"], + ["MA", "Mirinzal", "2106805"], + ["MA", "Mon\u{e7}\u{e3}o", "2106904"], + ["MA", "Montes Altos", "2107001"], + ["MA", "Morros", "2107100"], + ["MA", "Nina Rodrigues", "2107209"], + ["MA", "Nova Colinas", "2107258"], + ["MA", "Nova Iorque", "2107308"], + ["MA", "Nova Olinda do Maranh\u{e3}o", "2107357"], + ["MA", "Olho d'\u{c1}gua das Cunh\u{e3}s", "2107407"], + ["MA", "Olinda Nova do Maranh\u{e3}o", "2107456"], + ["MA", "Pa\u{e7}o do Lumiar", "2107506"], + ["MA", "Palmeir\u{e2}ndia", "2107605"], + ["MA", "Paraibano", "2107704"], + ["MA", "Parnarama", "2107803"], + ["MA", "Passagem Franca", "2107902"], + ["MA", "Pastos Bons", "2108009"], + ["MA", "Paulino Neves", "2108058"], + ["MA", "Paulo Ramos", "2108108"], + ["MA", "Pedreiras", "2108207"], + ["MA", "Pedro do Ros\u{e1}rio", "2108256"], + ["MA", "Penalva", "2108306"], + ["MA", "Peri Mirim", "2108405"], + ["MA", "Peritor\u{f3}", "2108454"], + ["MA", "Pindar\u{e9}-Mirim", "2108504"], + ["MA", "Pinheiro", "2108603"], + ["MA", "Pio XII", "2108702"], + ["MA", "Pirapemas", "2108801"], + ["MA", "Po\u{e7}\u{e3}o de Pedras", "2108900"], + ["MA", "Porto Franco", "2109007"], + ["MA", "Porto Rico do Maranh\u{e3}o", "2109056"], + ["MA", "Presidente Dutra", "2109106"], + ["MA", "Presidente Juscelino", "2109205"], + ["MA", "Presidente M\u{e9}dici", "2109239"], + ["MA", "Presidente Sarney", "2109270"], + ["MA", "Presidente Vargas", "2109304"], + ["MA", "Primeira Cruz", "2109403"], + ["MA", "Raposa", "2109452"], + ["MA", "Riach\u{e3}o", "2109502"], + ["MA", "Ribamar Fiquene", "2109551"], + ["MA", "Ros\u{e1}rio", "2109601"], + ["MA", "Samba\u{ed}ba", "2109700"], + ["MA", "Santa Filomena do Maranh\u{e3}o", "2109759"], + ["MA", "Santa Helena", "2109809"], + ["MA", "Santa In\u{ea}s", "2109908"], + ["MA", "Santa Luzia", "2110005"], + ["MA", "Santa Luzia do Paru\u{e1}", "2110039"], + ["MA", "Santa Quit\u{e9}ria do Maranh\u{e3}o", "2110104"], + ["MA", "Santa Rita", "2110203"], + ["MA", "Santana do Maranh\u{e3}o", "2110237"], + ["MA", "Santo Amaro do Maranh\u{e3}o", "2110278"], + ["MA", "Santo Ant\u{f4}nio dos Lopes", "2110302"], + ["MA", "S\u{e3}o Benedito do Rio Preto", "2110401"], + ["MA", "S\u{e3}o Bento", "2110500"], + ["MA", "S\u{e3}o Bernardo", "2110609"], + ["MA", "S\u{e3}o Domingos do Azeit\u{e3}o", "2110658"], + ["MA", "S\u{e3}o Domingos do Maranh\u{e3}o", "2110708"], + ["MA", "S\u{e3}o F\u{e9}lix de Balsas", "2110807"], + ["MA", "S\u{e3}o Francisco do Brej\u{e3}o", "2110856"], + ["MA", "S\u{e3}o Francisco do Maranh\u{e3}o", "2110906"], + ["MA", "S\u{e3}o Jo\u{e3}o Batista", "2111003"], + ["MA", "S\u{e3}o Jo\u{e3}o do Car\u{fa}", "2111029"], + ["MA", "S\u{e3}o Jo\u{e3}o do Para\u{ed}so", "2111052"], + ["MA", "S\u{e3}o Jo\u{e3}o do Soter", "2111078"], + ["MA", "S\u{e3}o Jo\u{e3}o dos Patos", "2111102"], + ["MA", "S\u{e3}o Jos\u{e9} de Ribamar", "2111201"], + ["MA", "S\u{e3}o Jos\u{e9} dos Bas\u{ed}lios", "2111250"], + ["MA", "S\u{e3}o Lu\u{ed}s", "2111300"], + ["MA", "S\u{e3}o Lu\u{ed}s Gonzaga do Maranh\u{e3}o", "2111409"], + ["MA", "S\u{e3}o Mateus do Maranh\u{e3}o", "2111508"], + ["MA", "S\u{e3}o Pedro da \u{c1}gua Branca", "2111532"], + ["MA", "S\u{e3}o Pedro dos Crentes", "2111573"], + ["MA", "S\u{e3}o Raimundo das Mangabeiras", "2111607"], + ["MA", "S\u{e3}o Raimundo do Doca Bezerra", "2111631"], + ["MA", "S\u{e3}o Roberto", "2111672"], + ["MA", "S\u{e3}o Vicente Ferrer", "2111706"], + ["MA", "Satubinha", "2111722"], + ["MA", "Senador Alexandre Costa", "2111748"], + ["MA", "Senador La Rocque", "2111763"], + ["MA", "Serrano do Maranh\u{e3}o", "2111789"], + ["MA", "S\u{ed}tio Novo", "2111805"], + ["MA", "Sucupira do Norte", "2111904"], + ["MA", "Sucupira do Riach\u{e3}o", "2111953"], + ["MA", "Tasso Fragoso", "2112001"], + ["MA", "Timbiras", "2112100"], + ["MA", "Timon", "2112209"], + ["MA", "Trizidela do Vale", "2112233"], + ["MA", "Tufil\u{e2}ndia", "2112274"], + ["MA", "Tuntum", "2112308"], + ["MA", "Turia\u{e7}u", "2112407"], + ["MA", "Turil\u{e2}ndia", "2112456"], + ["MA", "Tut\u{f3}ia", "2112506"], + ["MA", "Urbano Santos", "2112605"], + ["MA", "Vargem Grande", "2112704"], + ["MA", "Viana", "2112803"], + ["MA", "Vila Nova dos Mart\u{ed}rios", "2112852"], + ["MA", "Vit\u{f3}ria do Mearim", "2112902"], + ["MA", "Vitorino Freire", "2113009"], + ["MA", "Z\u{e9} Doca", "2114007"], + ["MT", "Acorizal", "5100102"], + ["MT", "\u{c1}gua Boa", "5100201"], + ["MT", "Alta Floresta", "5100250"], + ["MT", "Alto Araguaia", "5100300"], + ["MT", "Alto Boa Vista", "5100359"], + ["MT", "Alto Gar\u{e7}as", "5100409"], + ["MT", "Alto Paraguai", "5100508"], + ["MT", "Alto Taquari", "5100607"], + ["MT", "Apiac\u{e1}s", "5100805"], + ["MT", "Araguaiana", "5101001"], + ["MT", "Araguainha", "5101209"], + ["MT", "Araputanga", "5101258"], + ["MT", "Aren\u{e1}polis", "5101308"], + ["MT", "Aripuan\u{e3}", "5101407"], + ["MT", "Bar\u{e3}o de Melga\u{e7}o", "5101605"], + ["MT", "Barra do Bugres", "5101704"], + ["MT", "Barra do Gar\u{e7}as", "5101803"], + ["MT", "Boa Esperan\u{e7}a do Norte", "5101837"], + ["MT", "Bom Jesus do Araguaia", "5101852"], + ["MT", "Brasnorte", "5101902"], + ["MT", "C\u{e1}ceres", "5102504"], + ["MT", "Campin\u{e1}polis", "5102603"], + ["MT", "Campo Novo do Parecis", "5102637"], + ["MT", "Campo Verde", "5102678"], + ["MT", "Campos de J\u{fa}lio", "5102686"], + ["MT", "Canabrava do Norte", "5102694"], + ["MT", "Canarana", "5102702"], + ["MT", "Carlinda", "5102793"], + ["MT", "Castanheira", "5102850"], + ["MT", "Chapada dos Guimar\u{e3}es", "5103007"], + ["MT", "Cl\u{e1}udia", "5103056"], + ["MT", "Cocalinho", "5103106"], + ["MT", "Col\u{ed}der", "5103205"], + ["MT", "Colniza", "5103254"], + ["MT", "Comodoro", "5103304"], + ["MT", "Confresa", "5103353"], + ["MT", "Conquista D'Oeste", "5103361"], + ["MT", "Cotrigua\u{e7}u", "5103379"], + ["MT", "Cuiab\u{e1}", "5103403"], + ["MT", "Curvel\u{e2}ndia", "5103437"], + ["MT", "Denise", "5103452"], + ["MT", "Diamantino", "5103502"], + ["MT", "Dom Aquino", "5103601"], + ["MT", "Feliz Natal", "5103700"], + ["MT", "Figueir\u{f3}polis D'Oeste", "5103809"], + ["MT", "Ga\u{fa}cha do Norte", "5103858"], + ["MT", "General Carneiro", "5103908"], + ["MT", "Gl\u{f3}ria D'Oeste", "5103957"], + ["MT", "Guarant\u{e3} do Norte", "5104104"], + ["MT", "Guiratinga", "5104203"], + ["MT", "Indiava\u{ed}", "5104500"], + ["MT", "Ipiranga do Norte", "5104526"], + ["MT", "Itanhang\u{e1}", "5104542"], + ["MT", "Ita\u{fa}ba", "5104559"], + ["MT", "Itiquira", "5104609"], + ["MT", "Jaciara", "5104807"], + ["MT", "Jangada", "5104906"], + ["MT", "Jauru", "5105002"], + ["MT", "Juara", "5105101"], + ["MT", "Ju\u{ed}na", "5105150"], + ["MT", "Juruena", "5105176"], + ["MT", "Juscimeira", "5105200"], + ["MT", "Lambari D'Oeste", "5105234"], + ["MT", "Lucas do Rio Verde", "5105259"], + ["MT", "Luciara", "5105309"], + ["MT", "Marcel\u{e2}ndia", "5105580"], + ["MT", "Matup\u{e1}", "5105606"], + ["MT", "Mirassol d'Oeste", "5105622"], + ["MT", "Nobres", "5105903"], + ["MT", "Nortel\u{e2}ndia", "5106000"], + ["MT", "Nossa Senhora do Livramento", "5106109"], + ["MT", "Nova Bandeirantes", "5106158"], + ["MT", "Nova Brasil\u{e2}ndia", "5106208"], + ["MT", "Nova Cana\u{e3} do Norte", "5106216"], + ["MT", "Nova Guarita", "5108808"], + ["MT", "Nova Lacerda", "5106182"], + ["MT", "Nova Maril\u{e2}ndia", "5108857"], + ["MT", "Nova Maring\u{e1}", "5108907"], + ["MT", "Nova Monte Verde", "5108956"], + ["MT", "Nova Mutum", "5106224"], + ["MT", "Nova Nazar\u{e9}", "5106174"], + ["MT", "Nova Ol\u{ed}mpia", "5106232"], + ["MT", "Nova Santa Helena", "5106190"], + ["MT", "Nova Ubirat\u{e3}", "5106240"], + ["MT", "Nova Xavantina", "5106257"], + ["MT", "Novo Horizonte do Norte", "5106273"], + ["MT", "Novo Mundo", "5106265"], + ["MT", "Novo Santo Ant\u{f4}nio", "5106315"], + ["MT", "Novo S\u{e3}o Joaquim", "5106281"], + ["MT", "Parana\u{ed}ta", "5106299"], + ["MT", "Paranatinga", "5106307"], + ["MT", "Pedra Preta", "5106372"], + ["MT", "Peixoto de Azevedo", "5106422"], + ["MT", "Planalto da Serra", "5106455"], + ["MT", "Pocon\u{e9}", "5106505"], + ["MT", "Pontal do Araguaia", "5106653"], + ["MT", "Ponte Branca", "5106703"], + ["MT", "Pontes e Lacerda", "5106752"], + ["MT", "Porto Alegre do Norte", "5106778"], + ["MT", "Porto dos Ga\u{fa}chos", "5106802"], + ["MT", "Porto Esperidi\u{e3}o", "5106828"], + ["MT", "Porto Estrela", "5106851"], + ["MT", "Poxor\u{e9}u", "5107008"], + ["MT", "Primavera do Leste", "5107040"], + ["MT", "Quer\u{ea}ncia", "5107065"], + ["MT", "Reserva do Caba\u{e7}al", "5107156"], + ["MT", "Ribeir\u{e3}o Cascalheira", "5107180"], + ["MT", "Ribeir\u{e3}ozinho", "5107198"], + ["MT", "Rio Branco", "5107206"], + ["MT", "Rondol\u{e2}ndia", "5107578"], + ["MT", "Rondon\u{f3}polis", "5107602"], + ["MT", "Ros\u{e1}rio Oeste", "5107701"], + ["MT", "Salto do C\u{e9}u", "5107750"], + ["MT", "Santa Carmem", "5107248"], + ["MT", "Santa Cruz do Xingu", "5107743"], + ["MT", "Santa Rita do Trivelato", "5107768"], + ["MT", "Santa Terezinha", "5107776"], + ["MT", "Santo Afonso", "5107263"], + ["MT", "Santo Ant\u{f4}nio de Leverger", "5107800"], + ["MT", "Santo Ant\u{f4}nio do Leste", "5107792"], + ["MT", "S\u{e3}o F\u{e9}lix do Araguaia", "5107859"], + ["MT", "S\u{e3}o Jos\u{e9} do Povo", "5107297"], + ["MT", "S\u{e3}o Jos\u{e9} do Rio Claro", "5107305"], + ["MT", "S\u{e3}o Jos\u{e9} do Xingu", "5107354"], + ["MT", "S\u{e3}o Jos\u{e9} dos Quatro Marcos", "5107107"], + ["MT", "S\u{e3}o Pedro da Cipa", "5107404"], + ["MT", "Sapezal", "5107875"], + ["MT", "Serra Nova Dourada", "5107883"], + ["MT", "Sinop", "5107909"], + ["MT", "Sorriso", "5107925"], + ["MT", "Tabapor\u{e3}", "5107941"], + ["MT", "Tangar\u{e1} da Serra", "5107958"], + ["MT", "Tapurah", "5108006"], + ["MT", "Terra Nova do Norte", "5108055"], + ["MT", "Tesouro", "5108105"], + ["MT", "Torixor\u{e9}u", "5108204"], + ["MT", "Uni\u{e3}o do Sul", "5108303"], + ["MT", "Vale de S\u{e3}o Domingos", "5108352"], + ["MT", "V\u{e1}rzea Grande", "5108402"], + ["MT", "Vera", "5108501"], + ["MT", "Vila Bela da Sant\u{ed}ssima Trindade", "5105507"], + ["MT", "Vila Rica", "5108600"], + ["MS", "\u{c1}gua Clara", "5000203"], + ["MS", "Alcin\u{f3}polis", "5000252"], + ["MS", "Amambai", "5000609"], + ["MS", "Anast\u{e1}cio", "5000708"], + ["MS", "Anauril\u{e2}ndia", "5000807"], + ["MS", "Ang\u{e9}lica", "5000856"], + ["MS", "Ant\u{f4}nio Jo\u{e3}o", "5000906"], + ["MS", "Aparecida do Taboado", "5001003"], + ["MS", "Aquidauana", "5001102"], + ["MS", "Aral Moreira", "5001243"], + ["MS", "Bandeirantes", "5001508"], + ["MS", "Bataguassu", "5001904"], + ["MS", "Bataypor\u{e3}", "5002001"], + ["MS", "Bela Vista", "5002100"], + ["MS", "Bodoquena", "5002159"], + ["MS", "Bonito", "5002209"], + ["MS", "Brasil\u{e2}ndia", "5002308"], + ["MS", "Caarap\u{f3}", "5002407"], + ["MS", "Camapu\u{e3}", "5002605"], + ["MS", "Campo Grande", "5002704"], + ["MS", "Caracol", "5002803"], + ["MS", "Cassil\u{e2}ndia", "5002902"], + ["MS", "Chapad\u{e3}o do Sul", "5002951"], + ["MS", "Corguinho", "5003108"], + ["MS", "Coronel Sapucaia", "5003157"], + ["MS", "Corumb\u{e1}", "5003207"], + ["MS", "Costa Rica", "5003256"], + ["MS", "Coxim", "5003306"], + ["MS", "Deod\u{e1}polis", "5003454"], + ["MS", "Dois Irm\u{e3}os do Buriti", "5003488"], + ["MS", "Douradina", "5003504"], + ["MS", "Dourados", "5003702"], + ["MS", "Eldorado", "5003751"], + ["MS", "F\u{e1}tima do Sul", "5003801"], + ["MS", "Figueir\u{e3}o", "5003900"], + ["MS", "Gl\u{f3}ria de Dourados", "5004007"], + ["MS", "Guia Lopes da Laguna", "5004106"], + ["MS", "Iguatemi", "5004304"], + ["MS", "Inoc\u{ea}ncia", "5004403"], + ["MS", "Itapor\u{e3}", "5004502"], + ["MS", "Itaquira\u{ed}", "5004601"], + ["MS", "Ivinhema", "5004700"], + ["MS", "Japor\u{e3}", "5004809"], + ["MS", "Jaraguari", "5004908"], + ["MS", "Jardim", "5005004"], + ["MS", "Jate\u{ed}", "5005103"], + ["MS", "Juti", "5005152"], + ["MS", "Lad\u{e1}rio", "5005202"], + ["MS", "Laguna Carap\u{e3}", "5005251"], + ["MS", "Maracaju", "5005400"], + ["MS", "Miranda", "5005608"], + ["MS", "Mundo Novo", "5005681"], + ["MS", "Navira\u{ed}", "5005707"], + ["MS", "Nioaque", "5005806"], + ["MS", "Nova Alvorada do Sul", "5006002"], + ["MS", "Nova Andradina", "5006200"], + ["MS", "Novo Horizonte do Sul", "5006259"], + ["MS", "Para\u{ed}so das \u{c1}guas", "5006275"], + ["MS", "Parana\u{ed}ba", "5006309"], + ["MS", "Paranhos", "5006358"], + ["MS", "Pedro Gomes", "5006408"], + ["MS", "Ponta Por\u{e3}", "5006606"], + ["MS", "Porto Murtinho", "5006903"], + ["MS", "Ribas do Rio Pardo", "5007109"], + ["MS", "Rio Brilhante", "5007208"], + ["MS", "Rio Negro", "5007307"], + ["MS", "Rio Verde de Mato Grosso", "5007406"], + ["MS", "Rochedo", "5007505"], + ["MS", "Santa Rita do Pardo", "5007554"], + ["MS", "S\u{e3}o Gabriel do Oeste", "5007695"], + ["MS", "Selv\u{ed}ria", "5007802"], + ["MS", "Sete Quedas", "5007703"], + ["MS", "Sidrol\u{e2}ndia", "5007901"], + ["MS", "Sonora", "5007935"], + ["MS", "Tacuru", "5007950"], + ["MS", "Taquarussu", "5007976"], + ["MS", "Terenos", "5008008"], + ["MS", "Tr\u{ea}s Lagoas", "5008305"], + ["MS", "Vicentina", "5008404"], + ["MG", "Abadia dos Dourados", "3100104"], + ["MG", "Abaet\u{e9}", "3100203"], + ["MG", "Abre Campo", "3100302"], + ["MG", "Acaiaca", "3100401"], + ["MG", "A\u{e7}ucena", "3100500"], + ["MG", "\u{c1}gua Boa", "3100609"], + ["MG", "\u{c1}gua Comprida", "3100708"], + ["MG", "Aguanil", "3100807"], + ["MG", "\u{c1}guas Formosas", "3100906"], + ["MG", "\u{c1}guas Vermelhas", "3101003"], + ["MG", "Aimor\u{e9}s", "3101102"], + ["MG", "Aiuruoca", "3101201"], + ["MG", "Alagoa", "3101300"], + ["MG", "Albertina", "3101409"], + ["MG", "Al\u{e9}m Para\u{ed}ba", "3101508"], + ["MG", "Alfenas", "3101607"], + ["MG", "Alfredo Vasconcelos", "3101631"], + ["MG", "Almenara", "3101706"], + ["MG", "Alpercata", "3101805"], + ["MG", "Alpin\u{f3}polis", "3101904"], + ["MG", "Alterosa", "3102001"], + ["MG", "Alto Capara\u{f3}", "3102050"], + ["MG", "Alto Jequitib\u{e1}", "3153509"], + ["MG", "Alto Rio Doce", "3102100"], + ["MG", "Alvarenga", "3102209"], + ["MG", "Alvin\u{f3}polis", "3102308"], + ["MG", "Alvorada de Minas", "3102407"], + ["MG", "Amparo do Serra", "3102506"], + ["MG", "Andradas", "3102605"], + ["MG", "Andrel\u{e2}ndia", "3102803"], + ["MG", "Angel\u{e2}ndia", "3102852"], + ["MG", "Ant\u{f4}nio Carlos", "3102902"], + ["MG", "Ant\u{f4}nio Dias", "3103009"], + ["MG", "Ant\u{f4}nio Prado de Minas", "3103108"], + ["MG", "Ara\u{e7}a\u{ed}", "3103207"], + ["MG", "Aracitaba", "3103306"], + ["MG", "Ara\u{e7}ua\u{ed}", "3103405"], + ["MG", "Araguari", "3103504"], + ["MG", "Arantina", "3103603"], + ["MG", "Araponga", "3103702"], + ["MG", "Arapor\u{e3}", "3103751"], + ["MG", "Arapu\u{e1}", "3103801"], + ["MG", "Ara\u{fa}jos", "3103900"], + ["MG", "Arax\u{e1}", "3104007"], + ["MG", "Arceburgo", "3104106"], + ["MG", "Arcos", "3104205"], + ["MG", "Areado", "3104304"], + ["MG", "Argirita", "3104403"], + ["MG", "Aricanduva", "3104452"], + ["MG", "Arinos", "3104502"], + ["MG", "Astolfo Dutra", "3104601"], + ["MG", "Atal\u{e9}ia", "3104700"], + ["MG", "Augusto de Lima", "3104809"], + ["MG", "Baependi", "3104908"], + ["MG", "Baldim", "3105004"], + ["MG", "Bambu\u{ed}", "3105103"], + ["MG", "Bandeira", "3105202"], + ["MG", "Bandeira do Sul", "3105301"], + ["MG", "Bar\u{e3}o de Cocais", "3105400"], + ["MG", "Bar\u{e3}o do Monte Alto", "3105509"], + ["MG", "Barbacena", "3105608"], + ["MG", "Barra Longa", "3105707"], + ["MG", "Barroso", "3105905"], + ["MG", "Bela Vista de Minas", "3106002"], + ["MG", "Belmiro Braga", "3106101"], + ["MG", "Belo Horizonte", "3106200"], + ["MG", "Belo Oriente", "3106309"], + ["MG", "Belo Vale", "3106408"], + ["MG", "Berilo", "3106507"], + ["MG", "Berizal", "3106655"], + ["MG", "Bert\u{f3}polis", "3106606"], + ["MG", "Betim", "3106705"], + ["MG", "Bias Fortes", "3106804"], + ["MG", "Bicas", "3106903"], + ["MG", "Biquinhas", "3107000"], + ["MG", "Boa Esperan\u{e7}a", "3107109"], + ["MG", "Bocaina de Minas", "3107208"], + ["MG", "Bocai\u{fa}va", "3107307"], + ["MG", "Bom Despacho", "3107406"], + ["MG", "Bom Jardim de Minas", "3107505"], + ["MG", "Bom Jesus da Penha", "3107604"], + ["MG", "Bom Jesus do Amparo", "3107703"], + ["MG", "Bom Jesus do Galho", "3107802"], + ["MG", "Bom Repouso", "3107901"], + ["MG", "Bom Sucesso", "3108008"], + ["MG", "Bonfim", "3108107"], + ["MG", "Bonfin\u{f3}polis de Minas", "3108206"], + ["MG", "Bonito de Minas", "3108255"], + ["MG", "Borda da Mata", "3108305"], + ["MG", "Botelhos", "3108404"], + ["MG", "Botumirim", "3108503"], + ["MG", "Br\u{e1}s Pires", "3108701"], + ["MG", "Brasil\u{e2}ndia de Minas", "3108552"], + ["MG", "Bras\u{ed}lia de Minas", "3108602"], + ["MG", "Bra\u{fa}nas", "3108800"], + ["MG", "Braz\u{f3}polis", "3108909"], + ["MG", "Brumadinho", "3109006"], + ["MG", "Bueno Brand\u{e3}o", "3109105"], + ["MG", "Buen\u{f3}polis", "3109204"], + ["MG", "Bugre", "3109253"], + ["MG", "Buritis", "3109303"], + ["MG", "Buritizeiro", "3109402"], + ["MG", "Cabeceira Grande", "3109451"], + ["MG", "Cabo Verde", "3109501"], + ["MG", "Cachoeira da Prata", "3109600"], + ["MG", "Cachoeira de Minas", "3109709"], + ["MG", "Cachoeira de Paje\u{fa}", "3102704"], + ["MG", "Cachoeira Dourada", "3109808"], + ["MG", "Caetan\u{f3}polis", "3109907"], + ["MG", "Caet\u{e9}", "3110004"], + ["MG", "Caiana", "3110103"], + ["MG", "Cajuri", "3110202"], + ["MG", "Caldas", "3110301"], + ["MG", "Camacho", "3110400"], + ["MG", "Camanducaia", "3110509"], + ["MG", "Cambu\u{ed}", "3110608"], + ["MG", "Cambuquira", "3110707"], + ["MG", "Campan\u{e1}rio", "3110806"], + ["MG", "Campanha", "3110905"], + ["MG", "Campestre", "3111002"], + ["MG", "Campina Verde", "3111101"], + ["MG", "Campo Azul", "3111150"], + ["MG", "Campo Belo", "3111200"], + ["MG", "Campo do Meio", "3111309"], + ["MG", "Campo Florido", "3111408"], + ["MG", "Campos Altos", "3111507"], + ["MG", "Campos Gerais", "3111606"], + ["MG", "Cana Verde", "3111903"], + ["MG", "Cana\u{e3}", "3111705"], + ["MG", "Can\u{e1}polis", "3111804"], + ["MG", "Candeias", "3112000"], + ["MG", "Cantagalo", "3112059"], + ["MG", "Capara\u{f3}", "3112109"], + ["MG", "Capela Nova", "3112208"], + ["MG", "Capelinha", "3112307"], + ["MG", "Capetinga", "3112406"], + ["MG", "Capim Branco", "3112505"], + ["MG", "Capin\u{f3}polis", "3112604"], + ["MG", "Capit\u{e3}o Andrade", "3112653"], + ["MG", "Capit\u{e3}o En\u{e9}as", "3112703"], + ["MG", "Capit\u{f3}lio", "3112802"], + ["MG", "Caputira", "3112901"], + ["MG", "Cara\u{ed}", "3113008"], + ["MG", "Carana\u{ed}ba", "3113107"], + ["MG", "Caranda\u{ed}", "3113206"], + ["MG", "Carangola", "3113305"], + ["MG", "Caratinga", "3113404"], + ["MG", "Carbonita", "3113503"], + ["MG", "Carea\u{e7}u", "3113602"], + ["MG", "Carlos Chagas", "3113701"], + ["MG", "Carm\u{e9}sia", "3113800"], + ["MG", "Carmo da Cachoeira", "3113909"], + ["MG", "Carmo da Mata", "3114006"], + ["MG", "Carmo de Minas", "3114105"], + ["MG", "Carmo do Cajuru", "3114204"], + ["MG", "Carmo do Parana\u{ed}ba", "3114303"], + ["MG", "Carmo do Rio Claro", "3114402"], + ["MG", "Carm\u{f3}polis de Minas", "3114501"], + ["MG", "Carneirinho", "3114550"], + ["MG", "Carrancas", "3114600"], + ["MG", "Carvalh\u{f3}polis", "3114709"], + ["MG", "Carvalhos", "3114808"], + ["MG", "Casa Grande", "3114907"], + ["MG", "Cascalho Rico", "3115003"], + ["MG", "C\u{e1}ssia", "3115102"], + ["MG", "Cataguases", "3115300"], + ["MG", "Catas Altas", "3115359"], + ["MG", "Catas Altas da Noruega", "3115409"], + ["MG", "Catuji", "3115458"], + ["MG", "Catuti", "3115474"], + ["MG", "Caxambu", "3115508"], + ["MG", "Cedro do Abaet\u{e9}", "3115607"], + ["MG", "Central de Minas", "3115706"], + ["MG", "Centralina", "3115805"], + ["MG", "Ch\u{e1}cara", "3115904"], + ["MG", "Chal\u{e9}", "3116001"], + ["MG", "Chapada do Norte", "3116100"], + ["MG", "Chapada Ga\u{fa}cha", "3116159"], + ["MG", "Chiador", "3116209"], + ["MG", "Cipot\u{e2}nea", "3116308"], + ["MG", "Claraval", "3116407"], + ["MG", "Claro dos Po\u{e7}\u{f5}es", "3116506"], + ["MG", "Cl\u{e1}udio", "3116605"], + ["MG", "Coimbra", "3116704"], + ["MG", "Coluna", "3116803"], + ["MG", "Comendador Gomes", "3116902"], + ["MG", "Comercinho", "3117009"], + ["MG", "Concei\u{e7}\u{e3}o da Aparecida", "3117108"], + ["MG", "Concei\u{e7}\u{e3}o da Barra de Minas", "3115201"], + ["MG", "Concei\u{e7}\u{e3}o das Alagoas", "3117306"], + ["MG", "Concei\u{e7}\u{e3}o das Pedras", "3117207"], + ["MG", "Concei\u{e7}\u{e3}o de Ipanema", "3117405"], + ["MG", "Concei\u{e7}\u{e3}o do Mato Dentro", "3117504"], + ["MG", "Concei\u{e7}\u{e3}o do Par\u{e1}", "3117603"], + ["MG", "Concei\u{e7}\u{e3}o do Rio Verde", "3117702"], + ["MG", "Concei\u{e7}\u{e3}o dos Ouros", "3117801"], + ["MG", "C\u{f4}nego Marinho", "3117836"], + ["MG", "Confins", "3117876"], + ["MG", "Congonhal", "3117900"], + ["MG", "Congonhas", "3118007"], + ["MG", "Congonhas do Norte", "3118106"], + ["MG", "Conquista", "3118205"], + ["MG", "Conselheiro Lafaiete", "3118304"], + ["MG", "Conselheiro Pena", "3118403"], + ["MG", "Consola\u{e7}\u{e3}o", "3118502"], + ["MG", "Contagem", "3118601"], + ["MG", "Coqueiral", "3118700"], + ["MG", "Cora\u{e7}\u{e3}o de Jesus", "3118809"], + ["MG", "Cordisburgo", "3118908"], + ["MG", "Cordisl\u{e2}ndia", "3119005"], + ["MG", "Corinto", "3119104"], + ["MG", "Coroaci", "3119203"], + ["MG", "Coromandel", "3119302"], + ["MG", "Coronel Fabriciano", "3119401"], + ["MG", "Coronel Murta", "3119500"], + ["MG", "Coronel Pacheco", "3119609"], + ["MG", "Coronel Xavier Chaves", "3119708"], + ["MG", "C\u{f3}rrego Danta", "3119807"], + ["MG", "C\u{f3}rrego do Bom Jesus", "3119906"], + ["MG", "C\u{f3}rrego Fundo", "3119955"], + ["MG", "C\u{f3}rrego Novo", "3120003"], + ["MG", "Couto de Magalh\u{e3}es de Minas", "3120102"], + ["MG", "Cris\u{f3}lita", "3120151"], + ["MG", "Cristais", "3120201"], + ["MG", "Crist\u{e1}lia", "3120300"], + ["MG", "Cristiano Otoni", "3120409"], + ["MG", "Cristina", "3120508"], + ["MG", "Crucil\u{e2}ndia", "3120607"], + ["MG", "Cruzeiro da Fortaleza", "3120706"], + ["MG", "Cruz\u{ed}lia", "3120805"], + ["MG", "Cuparaque", "3120839"], + ["MG", "Curral de Dentro", "3120870"], + ["MG", "Curvelo", "3120904"], + ["MG", "Datas", "3121001"], + ["MG", "Delfim Moreira", "3121100"], + ["MG", "Delfin\u{f3}polis", "3121209"], + ["MG", "Delta", "3121258"], + ["MG", "Descoberto", "3121308"], + ["MG", "Desterro de Entre Rios", "3121407"], + ["MG", "Desterro do Melo", "3121506"], + ["MG", "Diamantina", "3121605"], + ["MG", "Diogo de Vasconcelos", "3121704"], + ["MG", "Dion\u{ed}sio", "3121803"], + ["MG", "Divin\u{e9}sia", "3121902"], + ["MG", "Divino", "3122009"], + ["MG", "Divino das Laranjeiras", "3122108"], + ["MG", "Divinol\u{e2}ndia de Minas", "3122207"], + ["MG", "Divin\u{f3}polis", "3122306"], + ["MG", "Divisa Alegre", "3122355"], + ["MG", "Divisa Nova", "3122405"], + ["MG", "Divis\u{f3}polis", "3122454"], + ["MG", "Dom Bosco", "3122470"], + ["MG", "Dom Cavati", "3122504"], + ["MG", "Dom Joaquim", "3122603"], + ["MG", "Dom Silv\u{e9}rio", "3122702"], + ["MG", "Dom Vi\u{e7}oso", "3122801"], + ["MG", "Dona Euz\u{e9}bia", "3122900"], + ["MG", "Dores de Campos", "3123007"], + ["MG", "Dores de Guanh\u{e3}es", "3123106"], + ["MG", "Dores do Indai\u{e1}", "3123205"], + ["MG", "Dores do Turvo", "3123304"], + ["MG", "Dores\u{f3}polis", "3123403"], + ["MG", "Douradoquara", "3123502"], + ["MG", "Durand\u{e9}", "3123528"], + ["MG", "El\u{f3}i Mendes", "3123601"], + ["MG", "Engenheiro Caldas", "3123700"], + ["MG", "Engenheiro Navarro", "3123809"], + ["MG", "Entre Folhas", "3123858"], + ["MG", "Entre Rios de Minas", "3123908"], + ["MG", "Erv\u{e1}lia", "3124005"], + ["MG", "Esmeraldas", "3124104"], + ["MG", "Espera Feliz", "3124203"], + ["MG", "Espinosa", "3124302"], + ["MG", "Esp\u{ed}rito Santo do Dourado", "3124401"], + ["MG", "Estiva", "3124500"], + ["MG", "Estrela Dalva", "3124609"], + ["MG", "Estrela do Indai\u{e1}", "3124708"], + ["MG", "Estrela do Sul", "3124807"], + ["MG", "Eugen\u{f3}polis", "3124906"], + ["MG", "Ewbank da C\u{e2}mara", "3125002"], + ["MG", "Extrema", "3125101"], + ["MG", "Fama", "3125200"], + ["MG", "Faria Lemos", "3125309"], + ["MG", "Fel\u{ed}cio dos Santos", "3125408"], + ["MG", "Felisburgo", "3125606"], + ["MG", "Felixl\u{e2}ndia", "3125705"], + ["MG", "Fernandes Tourinho", "3125804"], + ["MG", "Ferros", "3125903"], + ["MG", "Fervedouro", "3125952"], + ["MG", "Florestal", "3126000"], + ["MG", "Formiga", "3126109"], + ["MG", "Formoso", "3126208"], + ["MG", "Fortaleza de Minas", "3126307"], + ["MG", "Fortuna de Minas", "3126406"], + ["MG", "Francisco Badar\u{f3}", "3126505"], + ["MG", "Francisco Dumont", "3126604"], + ["MG", "Francisco S\u{e1}", "3126703"], + ["MG", "Francisc\u{f3}polis", "3126752"], + ["MG", "Frei Gaspar", "3126802"], + ["MG", "Frei Inoc\u{ea}ncio", "3126901"], + ["MG", "Frei Lagonegro", "3126950"], + ["MG", "Fronteira", "3127008"], + ["MG", "Fronteira dos Vales", "3127057"], + ["MG", "Fruta de Leite", "3127073"], + ["MG", "Frutal", "3127107"], + ["MG", "Funil\u{e2}ndia", "3127206"], + ["MG", "Galil\u{e9}ia", "3127305"], + ["MG", "Gameleiras", "3127339"], + ["MG", "Glaucil\u{e2}ndia", "3127354"], + ["MG", "Goiabeira", "3127370"], + ["MG", "Goian\u{e1}", "3127388"], + ["MG", "Gon\u{e7}alves", "3127404"], + ["MG", "Gonzaga", "3127503"], + ["MG", "Gouveia", "3127602"], + ["MG", "Governador Valadares", "3127701"], + ["MG", "Gr\u{e3}o Mogol", "3127800"], + ["MG", "Grupiara", "3127909"], + ["MG", "Guanh\u{e3}es", "3128006"], + ["MG", "Guap\u{e9}", "3128105"], + ["MG", "Guaraciaba", "3128204"], + ["MG", "Guaraciama", "3128253"], + ["MG", "Guaran\u{e9}sia", "3128303"], + ["MG", "Guarani", "3128402"], + ["MG", "Guarar\u{e1}", "3128501"], + ["MG", "Guarda-Mor", "3128600"], + ["MG", "Guaxup\u{e9}", "3128709"], + ["MG", "Guidoval", "3128808"], + ["MG", "Guimar\u{e2}nia", "3128907"], + ["MG", "Guiricema", "3129004"], + ["MG", "Gurinhat\u{e3}", "3129103"], + ["MG", "Heliodora", "3129202"], + ["MG", "Iapu", "3129301"], + ["MG", "Ibertioga", "3129400"], + ["MG", "Ibi\u{e1}", "3129509"], + ["MG", "Ibia\u{ed}", "3129608"], + ["MG", "Ibiracatu", "3129657"], + ["MG", "Ibiraci", "3129707"], + ["MG", "Ibirit\u{e9}", "3129806"], + ["MG", "Ibiti\u{fa}ra de Minas", "3129905"], + ["MG", "Ibituruna", "3130002"], + ["MG", "Icara\u{ed} de Minas", "3130051"], + ["MG", "Igarap\u{e9}", "3130101"], + ["MG", "Igaratinga", "3130200"], + ["MG", "Iguatama", "3130309"], + ["MG", "Ijaci", "3130408"], + ["MG", "Ilic\u{ed}nea", "3130507"], + ["MG", "Imb\u{e9} de Minas", "3130556"], + ["MG", "Inconfidentes", "3130606"], + ["MG", "Indaiabira", "3130655"], + ["MG", "Indian\u{f3}polis", "3130705"], + ["MG", "Inga\u{ed}", "3130804"], + ["MG", "Inhapim", "3130903"], + ["MG", "Inha\u{fa}ma", "3131000"], + ["MG", "Inimutaba", "3131109"], + ["MG", "Ipaba", "3131158"], + ["MG", "Ipanema", "3131208"], + ["MG", "Ipatinga", "3131307"], + ["MG", "Ipia\u{e7}u", "3131406"], + ["MG", "Ipui\u{fa}na", "3131505"], + ["MG", "Ira\u{ed} de Minas", "3131604"], + ["MG", "Itabira", "3131703"], + ["MG", "Itabirinha", "3131802"], + ["MG", "Itabirito", "3131901"], + ["MG", "Itacambira", "3132008"], + ["MG", "Itacarambi", "3132107"], + ["MG", "Itaguara", "3132206"], + ["MG", "Itaip\u{e9}", "3132305"], + ["MG", "Itajub\u{e1}", "3132404"], + ["MG", "Itamarandiba", "3132503"], + ["MG", "Itamarati de Minas", "3132602"], + ["MG", "Itambacuri", "3132701"], + ["MG", "Itamb\u{e9} do Mato Dentro", "3132800"], + ["MG", "Itamogi", "3132909"], + ["MG", "Itamonte", "3133006"], + ["MG", "Itanhandu", "3133105"], + ["MG", "Itanhomi", "3133204"], + ["MG", "Itaobim", "3133303"], + ["MG", "Itapagipe", "3133402"], + ["MG", "Itapecerica", "3133501"], + ["MG", "Itapeva", "3133600"], + ["MG", "Itatiaiu\u{e7}u", "3133709"], + ["MG", "Ita\u{fa} de Minas", "3133758"], + ["MG", "Ita\u{fa}na", "3133808"], + ["MG", "Itaverava", "3133907"], + ["MG", "Itinga", "3134004"], + ["MG", "Itueta", "3134103"], + ["MG", "Ituiutaba", "3134202"], + ["MG", "Itumirim", "3134301"], + ["MG", "Iturama", "3134400"], + ["MG", "Itutinga", "3134509"], + ["MG", "Jaboticatubas", "3134608"], + ["MG", "Jacinto", "3134707"], + ["MG", "Jacu\u{ed}", "3134806"], + ["MG", "Jacutinga", "3134905"], + ["MG", "Jaguara\u{e7}u", "3135001"], + ["MG", "Ja\u{ed}ba", "3135050"], + ["MG", "Jampruca", "3135076"], + ["MG", "Jana\u{fa}ba", "3135100"], + ["MG", "Janu\u{e1}ria", "3135209"], + ["MG", "Japara\u{ed}ba", "3135308"], + ["MG", "Japonvar", "3135357"], + ["MG", "Jeceaba", "3135407"], + ["MG", "Jenipapo de Minas", "3135456"], + ["MG", "Jequeri", "3135506"], + ["MG", "Jequita\u{ed}", "3135605"], + ["MG", "Jequitib\u{e1}", "3135704"], + ["MG", "Jequitinhonha", "3135803"], + ["MG", "Jesu\u{e2}nia", "3135902"], + ["MG", "Joa\u{ed}ma", "3136009"], + ["MG", "Joan\u{e9}sia", "3136108"], + ["MG", "Jo\u{e3}o Monlevade", "3136207"], + ["MG", "Jo\u{e3}o Pinheiro", "3136306"], + ["MG", "Joaquim Fel\u{ed}cio", "3136405"], + ["MG", "Jord\u{e2}nia", "3136504"], + ["MG", "Jos\u{e9} Gon\u{e7}alves de Minas", "3136520"], + ["MG", "Jos\u{e9} Raydan", "3136553"], + ["MG", "Josen\u{f3}polis", "3136579"], + ["MG", "Juatuba", "3136652"], + ["MG", "Juiz de Fora", "3136702"], + ["MG", "Juramento", "3136801"], + ["MG", "Juruaia", "3136900"], + ["MG", "Juven\u{ed}lia", "3136959"], + ["MG", "Ladainha", "3137007"], + ["MG", "Lagamar", "3137106"], + ["MG", "Lagoa da Prata", "3137205"], + ["MG", "Lagoa dos Patos", "3137304"], + ["MG", "Lagoa Dourada", "3137403"], + ["MG", "Lagoa Formosa", "3137502"], + ["MG", "Lagoa Grande", "3137536"], + ["MG", "Lagoa Santa", "3137601"], + ["MG", "Lajinha", "3137700"], + ["MG", "Lambari", "3137809"], + ["MG", "Lamim", "3137908"], + ["MG", "Laranjal", "3138005"], + ["MG", "Lassance", "3138104"], + ["MG", "Lavras", "3138203"], + ["MG", "Leandro Ferreira", "3138302"], + ["MG", "Leme do Prado", "3138351"], + ["MG", "Leopoldina", "3138401"], + ["MG", "Liberdade", "3138500"], + ["MG", "Lima Duarte", "3138609"], + ["MG", "Limeira do Oeste", "3138625"], + ["MG", "Lontra", "3138658"], + ["MG", "Luisburgo", "3138674"], + ["MG", "Luisl\u{e2}ndia", "3138682"], + ["MG", "Lumin\u{e1}rias", "3138708"], + ["MG", "Luz", "3138807"], + ["MG", "Machacalis", "3138906"], + ["MG", "Machado", "3139003"], + ["MG", "Madre de Deus de Minas", "3139102"], + ["MG", "Malacacheta", "3139201"], + ["MG", "Mamonas", "3139250"], + ["MG", "Manga", "3139300"], + ["MG", "Manhua\u{e7}u", "3139409"], + ["MG", "Manhumirim", "3139508"], + ["MG", "Mantena", "3139607"], + ["MG", "Mar de Espanha", "3139805"], + ["MG", "Maravilhas", "3139706"], + ["MG", "Maria da F\u{e9}", "3139904"], + ["MG", "Mariana", "3140001"], + ["MG", "Marilac", "3140100"], + ["MG", "M\u{e1}rio Campos", "3140159"], + ["MG", "Marip\u{e1} de Minas", "3140209"], + ["MG", "Marli\u{e9}ria", "3140308"], + ["MG", "Marmel\u{f3}polis", "3140407"], + ["MG", "Martinho Campos", "3140506"], + ["MG", "Martins Soares", "3140530"], + ["MG", "Mata Verde", "3140555"], + ["MG", "Materl\u{e2}ndia", "3140605"], + ["MG", "Mateus Leme", "3140704"], + ["MG", "Mathias Lobato", "3171501"], + ["MG", "Matias Barbosa", "3140803"], + ["MG", "Matias Cardoso", "3140852"], + ["MG", "Matip\u{f3}", "3140902"], + ["MG", "Mato Verde", "3141009"], + ["MG", "Matozinhos", "3141108"], + ["MG", "Matutina", "3141207"], + ["MG", "Medeiros", "3141306"], + ["MG", "Medina", "3141405"], + ["MG", "Mendes Pimentel", "3141504"], + ["MG", "Merc\u{ea}s", "3141603"], + ["MG", "Mesquita", "3141702"], + ["MG", "Minas Novas", "3141801"], + ["MG", "Minduri", "3141900"], + ["MG", "Mirabela", "3142007"], + ["MG", "Miradouro", "3142106"], + ["MG", "Mira\u{ed}", "3142205"], + ["MG", "Mirav\u{e2}nia", "3142254"], + ["MG", "Moeda", "3142304"], + ["MG", "Moema", "3142403"], + ["MG", "Monjolos", "3142502"], + ["MG", "Monsenhor Paulo", "3142601"], + ["MG", "Montalv\u{e2}nia", "3142700"], + ["MG", "Monte Alegre de Minas", "3142809"], + ["MG", "Monte Azul", "3142908"], + ["MG", "Monte Belo", "3143005"], + ["MG", "Monte Carmelo", "3143104"], + ["MG", "Monte Formoso", "3143153"], + ["MG", "Monte Santo de Minas", "3143203"], + ["MG", "Monte Si\u{e3}o", "3143401"], + ["MG", "Montes Claros", "3143302"], + ["MG", "Montezuma", "3143450"], + ["MG", "Morada Nova de Minas", "3143500"], + ["MG", "Morro da Gar\u{e7}a", "3143609"], + ["MG", "Morro do Pilar", "3143708"], + ["MG", "Munhoz", "3143807"], + ["MG", "Muria\u{e9}", "3143906"], + ["MG", "Mutum", "3144003"], + ["MG", "Muzambinho", "3144102"], + ["MG", "Nacip Raydan", "3144201"], + ["MG", "Nanuque", "3144300"], + ["MG", "Naque", "3144359"], + ["MG", "Natal\u{e2}ndia", "3144375"], + ["MG", "Nat\u{e9}rcia", "3144409"], + ["MG", "Nazareno", "3144508"], + ["MG", "Nepomuceno", "3144607"], + ["MG", "Ninheira", "3144656"], + ["MG", "Nova Bel\u{e9}m", "3144672"], + ["MG", "Nova Era", "3144706"], + ["MG", "Nova Lima", "3144805"], + ["MG", "Nova M\u{f3}dica", "3144904"], + ["MG", "Nova Ponte", "3145000"], + ["MG", "Nova Porteirinha", "3145059"], + ["MG", "Nova Resende", "3145109"], + ["MG", "Nova Serrana", "3145208"], + ["MG", "Nova Uni\u{e3}o", "3136603"], + ["MG", "Novo Cruzeiro", "3145307"], + ["MG", "Novo Oriente de Minas", "3145356"], + ["MG", "Novorizonte", "3145372"], + ["MG", "Olaria", "3145406"], + ["MG", "Olhos-d'\u{c1}gua", "3145455"], + ["MG", "Ol\u{ed}mpio Noronha", "3145505"], + ["MG", "Oliveira", "3145604"], + ["MG", "Oliveira Fortes", "3145703"], + ["MG", "On\u{e7}a de Pitangui", "3145802"], + ["MG", "Orat\u{f3}rios", "3145851"], + ["MG", "Oriz\u{e2}nia", "3145877"], + ["MG", "Ouro Branco", "3145901"], + ["MG", "Ouro Fino", "3146008"], + ["MG", "Ouro Preto", "3146107"], + ["MG", "Ouro Verde de Minas", "3146206"], + ["MG", "Padre Carvalho", "3146255"], + ["MG", "Padre Para\u{ed}so", "3146305"], + ["MG", "Pai Pedro", "3146552"], + ["MG", "Paineiras", "3146404"], + ["MG", "Pains", "3146503"], + ["MG", "Paiva", "3146602"], + ["MG", "Palma", "3146701"], + ["MG", "Palm\u{f3}polis", "3146750"], + ["MG", "Papagaios", "3146909"], + ["MG", "Par\u{e1} de Minas", "3147105"], + ["MG", "Paracatu", "3147006"], + ["MG", "Paragua\u{e7}u", "3147204"], + ["MG", "Parais\u{f3}polis", "3147303"], + ["MG", "Paraopeba", "3147402"], + ["MG", "Passa Quatro", "3147600"], + ["MG", "Passa Tempo", "3147709"], + ["MG", "Passa Vinte", "3147808"], + ["MG", "Passab\u{e9}m", "3147501"], + ["MG", "Passos", "3147907"], + ["MG", "Patis", "3147956"], + ["MG", "Patos de Minas", "3148004"], + ["MG", "Patroc\u{ed}nio", "3148103"], + ["MG", "Patroc\u{ed}nio do Muria\u{e9}", "3148202"], + ["MG", "Paula C\u{e2}ndido", "3148301"], + ["MG", "Paulistas", "3148400"], + ["MG", "Pav\u{e3}o", "3148509"], + ["MG", "Pe\u{e7}anha", "3148608"], + ["MG", "Pedra Azul", "3148707"], + ["MG", "Pedra Bonita", "3148756"], + ["MG", "Pedra do Anta", "3148806"], + ["MG", "Pedra do Indai\u{e1}", "3148905"], + ["MG", "Pedra Dourada", "3149002"], + ["MG", "Pedralva", "3149101"], + ["MG", "Pedras de Maria da Cruz", "3149150"], + ["MG", "Pedrin\u{f3}polis", "3149200"], + ["MG", "Pedro Leopoldo", "3149309"], + ["MG", "Pedro Teixeira", "3149408"], + ["MG", "Pequeri", "3149507"], + ["MG", "Pequi", "3149606"], + ["MG", "Perdig\u{e3}o", "3149705"], + ["MG", "Perdizes", "3149804"], + ["MG", "Perd\u{f5}es", "3149903"], + ["MG", "Periquito", "3149952"], + ["MG", "Pescador", "3150000"], + ["MG", "Piau", "3150109"], + ["MG", "Piedade de Caratinga", "3150158"], + ["MG", "Piedade de Ponte Nova", "3150208"], + ["MG", "Piedade do Rio Grande", "3150307"], + ["MG", "Piedade dos Gerais", "3150406"], + ["MG", "Pimenta", "3150505"], + ["MG", "Pingo-d'\u{c1}gua", "3150539"], + ["MG", "Pint\u{f3}polis", "3150570"], + ["MG", "Piracema", "3150604"], + ["MG", "Pirajuba", "3150703"], + ["MG", "Piranga", "3150802"], + ["MG", "Pirangu\u{e7}u", "3150901"], + ["MG", "Piranguinho", "3151008"], + ["MG", "Pirapetinga", "3151107"], + ["MG", "Pirapora", "3151206"], + ["MG", "Pira\u{fa}ba", "3151305"], + ["MG", "Pitangui", "3151404"], + ["MG", "Piumhi", "3151503"], + ["MG", "Planura", "3151602"], + ["MG", "Po\u{e7}o Fundo", "3151701"], + ["MG", "Po\u{e7}os de Caldas", "3151800"], + ["MG", "Pocrane", "3151909"], + ["MG", "Pomp\u{e9}u", "3152006"], + ["MG", "Ponte Nova", "3152105"], + ["MG", "Ponto Chique", "3152131"], + ["MG", "Ponto dos Volantes", "3152170"], + ["MG", "Porteirinha", "3152204"], + ["MG", "Porto Firme", "3152303"], + ["MG", "Pot\u{e9}", "3152402"], + ["MG", "Pouso Alegre", "3152501"], + ["MG", "Pouso Alto", "3152600"], + ["MG", "Prados", "3152709"], + ["MG", "Prata", "3152808"], + ["MG", "Prat\u{e1}polis", "3152907"], + ["MG", "Pratinha", "3153004"], + ["MG", "Presidente Bernardes", "3153103"], + ["MG", "Presidente Juscelino", "3153202"], + ["MG", "Presidente Kubitschek", "3153301"], + ["MG", "Presidente Oleg\u{e1}rio", "3153400"], + ["MG", "Prudente de Morais", "3153608"], + ["MG", "Quartel Geral", "3153707"], + ["MG", "Queluzito", "3153806"], + ["MG", "Raposos", "3153905"], + ["MG", "Raul Soares", "3154002"], + ["MG", "Recreio", "3154101"], + ["MG", "Reduto", "3154150"], + ["MG", "Resende Costa", "3154200"], + ["MG", "Resplendor", "3154309"], + ["MG", "Ressaquinha", "3154408"], + ["MG", "Riachinho", "3154457"], + ["MG", "Riacho dos Machados", "3154507"], + ["MG", "Ribeir\u{e3}o das Neves", "3154606"], + ["MG", "Ribeir\u{e3}o Vermelho", "3154705"], + ["MG", "Rio Acima", "3154804"], + ["MG", "Rio Casca", "3154903"], + ["MG", "Rio do Prado", "3155108"], + ["MG", "Rio Doce", "3155009"], + ["MG", "Rio Espera", "3155207"], + ["MG", "Rio Manso", "3155306"], + ["MG", "Rio Novo", "3155405"], + ["MG", "Rio Parana\u{ed}ba", "3155504"], + ["MG", "Rio Pardo de Minas", "3155603"], + ["MG", "Rio Piracicaba", "3155702"], + ["MG", "Rio Pomba", "3155801"], + ["MG", "Rio Preto", "3155900"], + ["MG", "Rio Vermelho", "3156007"], + ["MG", "Rit\u{e1}polis", "3156106"], + ["MG", "Rochedo de Minas", "3156205"], + ["MG", "Rodeiro", "3156304"], + ["MG", "Romaria", "3156403"], + ["MG", "Ros\u{e1}rio da Limeira", "3156452"], + ["MG", "Rubelita", "3156502"], + ["MG", "Rubim", "3156601"], + ["MG", "Sabar\u{e1}", "3156700"], + ["MG", "Sabin\u{f3}polis", "3156809"], + ["MG", "Sacramento", "3156908"], + ["MG", "Salinas", "3157005"], + ["MG", "Salto da Divisa", "3157104"], + ["MG", "Santa B\u{e1}rbara", "3157203"], + ["MG", "Santa B\u{e1}rbara do Leste", "3157252"], + ["MG", "Santa B\u{e1}rbara do Monte Verde", "3157278"], + ["MG", "Santa B\u{e1}rbara do Tug\u{fa}rio", "3157302"], + ["MG", "Santa Cruz de Minas", "3157336"], + ["MG", "Santa Cruz de Salinas", "3157377"], + ["MG", "Santa Cruz do Escalvado", "3157401"], + ["MG", "Santa Efig\u{ea}nia de Minas", "3157500"], + ["MG", "Santa F\u{e9} de Minas", "3157609"], + ["MG", "Santa Helena de Minas", "3157658"], + ["MG", "Santa Juliana", "3157708"], + ["MG", "Santa Luzia", "3157807"], + ["MG", "Santa Margarida", "3157906"], + ["MG", "Santa Maria de Itabira", "3158003"], + ["MG", "Santa Maria do Salto", "3158102"], + ["MG", "Santa Maria do Sua\u{e7}u\u{ed}", "3158201"], + ["MG", "Santa Rita de Caldas", "3159209"], + ["MG", "Santa Rita de Ibitipoca", "3159407"], + ["MG", "Santa Rita de Jacutinga", "3159308"], + ["MG", "Santa Rita de Minas", "3159357"], + ["MG", "Santa Rita do Itueto", "3159506"], + ["MG", "Santa Rita do Sapuca\u{ed}", "3159605"], + ["MG", "Santa Rosa da Serra", "3159704"], + ["MG", "Santa Vit\u{f3}ria", "3159803"], + ["MG", "Santana da Vargem", "3158300"], + ["MG", "Santana de Cataguases", "3158409"], + ["MG", "Santana de Pirapama", "3158508"], + ["MG", "Santana do Deserto", "3158607"], + ["MG", "Santana do Garamb\u{e9}u", "3158706"], + ["MG", "Santana do Jacar\u{e9}", "3158805"], + ["MG", "Santana do Manhua\u{e7}u", "3158904"], + ["MG", "Santana do Para\u{ed}so", "3158953"], + ["MG", "Santana do Riacho", "3159001"], + ["MG", "Santana dos Montes", "3159100"], + ["MG", "Santo Ant\u{f4}nio do Amparo", "3159902"], + ["MG", "Santo Ant\u{f4}nio do Aventureiro", "3160009"], + ["MG", "Santo Ant\u{f4}nio do Grama", "3160108"], + ["MG", "Santo Ant\u{f4}nio do Itamb\u{e9}", "3160207"], + ["MG", "Santo Ant\u{f4}nio do Jacinto", "3160306"], + ["MG", "Santo Ant\u{f4}nio do Monte", "3160405"], + ["MG", "Santo Ant\u{f4}nio do Retiro", "3160454"], + ["MG", "Santo Ant\u{f4}nio do Rio Abaixo", "3160504"], + ["MG", "Santo Hip\u{f3}lito", "3160603"], + ["MG", "Santos Dumont", "3160702"], + ["MG", "S\u{e3}o Bento Abade", "3160801"], + ["MG", "S\u{e3}o Br\u{e1}s do Sua\u{e7}u\u{ed}", "3160900"], + ["MG", "S\u{e3}o Domingos das Dores", "3160959"], + ["MG", "S\u{e3}o Domingos do Prata", "3161007"], + ["MG", "S\u{e3}o F\u{e9}lix de Minas", "3161056"], + ["MG", "S\u{e3}o Francisco", "3161106"], + ["MG", "S\u{e3}o Francisco de Paula", "3161205"], + ["MG", "S\u{e3}o Francisco de Sales", "3161304"], + ["MG", "S\u{e3}o Francisco do Gl\u{f3}ria", "3161403"], + ["MG", "S\u{e3}o Geraldo", "3161502"], + ["MG", "S\u{e3}o Geraldo da Piedade", "3161601"], + ["MG", "S\u{e3}o Geraldo do Baixio", "3161650"], + ["MG", "S\u{e3}o Gon\u{e7}alo do Abaet\u{e9}", "3161700"], + ["MG", "S\u{e3}o Gon\u{e7}alo do Par\u{e1}", "3161809"], + ["MG", "S\u{e3}o Gon\u{e7}alo do Rio Abaixo", "3161908"], + ["MG", "S\u{e3}o Gon\u{e7}alo do Rio Preto", "3125507"], + ["MG", "S\u{e3}o Gon\u{e7}alo do Sapuca\u{ed}", "3162005"], + ["MG", "S\u{e3}o Gotardo", "3162104"], + ["MG", "S\u{e3}o Jo\u{e3}o Batista do Gl\u{f3}ria", "3162203"], + ["MG", "S\u{e3}o Jo\u{e3}o da Lagoa", "3162252"], + ["MG", "S\u{e3}o Jo\u{e3}o da Mata", "3162302"], + ["MG", "S\u{e3}o Jo\u{e3}o da Ponte", "3162401"], + ["MG", "S\u{e3}o Jo\u{e3}o das Miss\u{f5}es", "3162450"], + ["MG", "S\u{e3}o Jo\u{e3}o del Rei", "3162500"], + ["MG", "S\u{e3}o Jo\u{e3}o do Manhua\u{e7}u", "3162559"], + ["MG", "S\u{e3}o Jo\u{e3}o do Manteninha", "3162575"], + ["MG", "S\u{e3}o Jo\u{e3}o do Oriente", "3162609"], + ["MG", "S\u{e3}o Jo\u{e3}o do Pacu\u{ed}", "3162658"], + ["MG", "S\u{e3}o Jo\u{e3}o do Para\u{ed}so", "3162708"], + ["MG", "S\u{e3}o Jo\u{e3}o Evangelista", "3162807"], + ["MG", "S\u{e3}o Jo\u{e3}o Nepomuceno", "3162906"], + ["MG", "S\u{e3}o Joaquim de Bicas", "3162922"], + ["MG", "S\u{e3}o Jos\u{e9} da Barra", "3162948"], + ["MG", "S\u{e3}o Jos\u{e9} da Lapa", "3162955"], + ["MG", "S\u{e3}o Jos\u{e9} da Safira", "3163003"], + ["MG", "S\u{e3}o Jos\u{e9} da Varginha", "3163102"], + ["MG", "S\u{e3}o Jos\u{e9} do Alegre", "3163201"], + ["MG", "S\u{e3}o Jos\u{e9} do Divino", "3163300"], + ["MG", "S\u{e3}o Jos\u{e9} do Goiabal", "3163409"], + ["MG", "S\u{e3}o Jos\u{e9} do Jacuri", "3163508"], + ["MG", "S\u{e3}o Jos\u{e9} do Mantimento", "3163607"], + ["MG", "S\u{e3}o Louren\u{e7}o", "3163706"], + ["MG", "S\u{e3}o Miguel do Anta", "3163805"], + ["MG", "S\u{e3}o Pedro da Uni\u{e3}o", "3163904"], + ["MG", "S\u{e3}o Pedro do Sua\u{e7}u\u{ed}", "3164100"], + ["MG", "S\u{e3}o Pedro dos Ferros", "3164001"], + ["MG", "S\u{e3}o Rom\u{e3}o", "3164209"], + ["MG", "S\u{e3}o Roque de Minas", "3164308"], + ["MG", "S\u{e3}o Sebasti\u{e3}o da Bela Vista", "3164407"], + ["MG", "S\u{e3}o Sebasti\u{e3}o da Vargem Alegre", "3164431"], + ["MG", "S\u{e3}o Sebasti\u{e3}o do Anta", "3164472"], + ["MG", "S\u{e3}o Sebasti\u{e3}o do Maranh\u{e3}o", "3164506"], + ["MG", "S\u{e3}o Sebasti\u{e3}o do Oeste", "3164605"], + ["MG", "S\u{e3}o Sebasti\u{e3}o do Para\u{ed}so", "3164704"], + ["MG", "S\u{e3}o Sebasti\u{e3}o do Rio Preto", "3164803"], + ["MG", "S\u{e3}o Sebasti\u{e3}o do Rio Verde", "3164902"], + ["MG", "S\u{e3}o Tiago", "3165008"], + ["MG", "S\u{e3}o Tom\u{e1}s de Aquino", "3165107"], + ["MG", "S\u{e3}o Tom\u{e9} das Letras", "3165206"], + ["MG", "S\u{e3}o Vicente de Minas", "3165305"], + ["MG", "Sapuca\u{ed}-Mirim", "3165404"], + ["MG", "Sardo\u{e1}", "3165503"], + ["MG", "Sarzedo", "3165537"], + ["MG", "Sem-Peixe", "3165560"], + ["MG", "Senador Amaral", "3165578"], + ["MG", "Senador Cortes", "3165602"], + ["MG", "Senador Firmino", "3165701"], + ["MG", "Senador Jos\u{e9} Bento", "3165800"], + ["MG", "Senador Modestino Gon\u{e7}alves", "3165909"], + ["MG", "Senhora de Oliveira", "3166006"], + ["MG", "Senhora do Porto", "3166105"], + ["MG", "Senhora dos Rem\u{e9}dios", "3166204"], + ["MG", "Sericita", "3166303"], + ["MG", "Seritinga", "3166402"], + ["MG", "Serra Azul de Minas", "3166501"], + ["MG", "Serra da Saudade", "3166600"], + ["MG", "Serra do Salitre", "3166808"], + ["MG", "Serra dos Aimor\u{e9}s", "3166709"], + ["MG", "Serrania", "3166907"], + ["MG", "Serran\u{f3}polis de Minas", "3166956"], + ["MG", "Serranos", "3167004"], + ["MG", "Serro", "3167103"], + ["MG", "Sete Lagoas", "3167202"], + ["MG", "Setubinha", "3165552"], + ["MG", "Silveir\u{e2}nia", "3167301"], + ["MG", "Silvian\u{f3}polis", "3167400"], + ["MG", "Sim\u{e3}o Pereira", "3167509"], + ["MG", "Simon\u{e9}sia", "3167608"], + ["MG", "Sobr\u{e1}lia", "3167707"], + ["MG", "Soledade de Minas", "3167806"], + ["MG", "Tabuleiro", "3167905"], + ["MG", "Taiobeiras", "3168002"], + ["MG", "Taparuba", "3168051"], + ["MG", "Tapira", "3168101"], + ["MG", "Tapira\u{ed}", "3168200"], + ["MG", "Taquara\u{e7}u de Minas", "3168309"], + ["MG", "Tarumirim", "3168408"], + ["MG", "Teixeiras", "3168507"], + ["MG", "Te\u{f3}filo Otoni", "3168606"], + ["MG", "Tim\u{f3}teo", "3168705"], + ["MG", "Tiradentes", "3168804"], + ["MG", "Tiros", "3168903"], + ["MG", "Tocantins", "3169000"], + ["MG", "Tocos do Moji", "3169059"], + ["MG", "Toledo", "3169109"], + ["MG", "Tombos", "3169208"], + ["MG", "Tr\u{ea}s Cora\u{e7}\u{f5}es", "3169307"], + ["MG", "Tr\u{ea}s Marias", "3169356"], + ["MG", "Tr\u{ea}s Pontas", "3169406"], + ["MG", "Tumiritinga", "3169505"], + ["MG", "Tupaciguara", "3169604"], + ["MG", "Turmalina", "3169703"], + ["MG", "Turvol\u{e2}ndia", "3169802"], + ["MG", "Ub\u{e1}", "3169901"], + ["MG", "Uba\u{ed}", "3170008"], + ["MG", "Ubaporanga", "3170057"], + ["MG", "Uberaba", "3170107"], + ["MG", "Uberl\u{e2}ndia", "3170206"], + ["MG", "Umburatiba", "3170305"], + ["MG", "Una\u{ed}", "3170404"], + ["MG", "Uni\u{e3}o de Minas", "3170438"], + ["MG", "Uruana de Minas", "3170479"], + ["MG", "Uruc\u{e2}nia", "3170503"], + ["MG", "Urucuia", "3170529"], + ["MG", "Vargem Alegre", "3170578"], + ["MG", "Vargem Bonita", "3170602"], + ["MG", "Vargem Grande do Rio Pardo", "3170651"], + ["MG", "Varginha", "3170701"], + ["MG", "Varj\u{e3}o de Minas", "3170750"], + ["MG", "V\u{e1}rzea da Palma", "3170800"], + ["MG", "Varzel\u{e2}ndia", "3170909"], + ["MG", "Vazante", "3171006"], + ["MG", "Verdel\u{e2}ndia", "3171030"], + ["MG", "Veredinha", "3171071"], + ["MG", "Ver\u{ed}ssimo", "3171105"], + ["MG", "Vermelho Novo", "3171154"], + ["MG", "Vespasiano", "3171204"], + ["MG", "Vi\u{e7}osa", "3171303"], + ["MG", "Vieiras", "3171402"], + ["MG", "Virgem da Lapa", "3171600"], + ["MG", "Virg\u{ed}nia", "3171709"], + ["MG", "Virgin\u{f3}polis", "3171808"], + ["MG", "Virgol\u{e2}ndia", "3171907"], + ["MG", "Visconde do Rio Branco", "3172004"], + ["MG", "Volta Grande", "3172103"], + ["MG", "Wenceslau Braz", "3172202"], + ["PA", "Abaetetuba", "1500107"], + ["PA", "Abel Figueiredo", "1500131"], + ["PA", "Acar\u{e1}", "1500206"], + ["PA", "Afu\u{e1}", "1500305"], + ["PA", "\u{c1}gua Azul do Norte", "1500347"], + ["PA", "Alenquer", "1500404"], + ["PA", "Almeirim", "1500503"], + ["PA", "Altamira", "1500602"], + ["PA", "Anaj\u{e1}s", "1500701"], + ["PA", "Ananindeua", "1500800"], + ["PA", "Anapu", "1500859"], + ["PA", "Augusto Corr\u{ea}a", "1500909"], + ["PA", "Aurora do Par\u{e1}", "1500958"], + ["PA", "Aveiro", "1501006"], + ["PA", "Bagre", "1501105"], + ["PA", "Bai\u{e3}o", "1501204"], + ["PA", "Bannach", "1501253"], + ["PA", "Barcarena", "1501303"], + ["PA", "Bel\u{e9}m", "1501402"], + ["PA", "Belterra", "1501451"], + ["PA", "Benevides", "1501501"], + ["PA", "Bom Jesus do Tocantins", "1501576"], + ["PA", "Bonito", "1501600"], + ["PA", "Bragan\u{e7}a", "1501709"], + ["PA", "Brasil Novo", "1501725"], + ["PA", "Brejo Grande do Araguaia", "1501758"], + ["PA", "Breu Branco", "1501782"], + ["PA", "Breves", "1501808"], + ["PA", "Bujaru", "1501907"], + ["PA", "Cachoeira do Arari", "1502004"], + ["PA", "Cachoeira do Piri\u{e1}", "1501956"], + ["PA", "Camet\u{e1}", "1502103"], + ["PA", "Cana\u{e3} dos Caraj\u{e1}s", "1502152"], + ["PA", "Capanema", "1502202"], + ["PA", "Capit\u{e3}o Po\u{e7}o", "1502301"], + ["PA", "Castanhal", "1502400"], + ["PA", "Chaves", "1502509"], + ["PA", "Colares", "1502608"], + ["PA", "Concei\u{e7}\u{e3}o do Araguaia", "1502707"], + ["PA", "Conc\u{f3}rdia do Par\u{e1}", "1502756"], + ["PA", "Cumaru do Norte", "1502764"], + ["PA", "Curion\u{f3}polis", "1502772"], + ["PA", "Curralinho", "1502806"], + ["PA", "Curu\u{e1}", "1502855"], + ["PA", "Curu\u{e7}\u{e1}", "1502905"], + ["PA", "Dom Eliseu", "1502939"], + ["PA", "Eldorado do Caraj\u{e1}s", "1502954"], + ["PA", "Faro", "1503002"], + ["PA", "Floresta do Araguaia", "1503044"], + ["PA", "Garraf\u{e3}o do Norte", "1503077"], + ["PA", "Goian\u{e9}sia do Par\u{e1}", "1503093"], + ["PA", "Gurup\u{e1}", "1503101"], + ["PA", "Igarap\u{e9}-A\u{e7}u", "1503200"], + ["PA", "Igarap\u{e9}-Miri", "1503309"], + ["PA", "Inhangapi", "1503408"], + ["PA", "Ipixuna do Par\u{e1}", "1503457"], + ["PA", "Irituia", "1503507"], + ["PA", "Itaituba", "1503606"], + ["PA", "Itupiranga", "1503705"], + ["PA", "Jacareacanga", "1503754"], + ["PA", "Jacund\u{e1}", "1503804"], + ["PA", "Juruti", "1503903"], + ["PA", "Limoeiro do Ajuru", "1504000"], + ["PA", "M\u{e3}e do Rio", "1504059"], + ["PA", "Magalh\u{e3}es Barata", "1504109"], + ["PA", "Marab\u{e1}", "1504208"], + ["PA", "Maracan\u{e3}", "1504307"], + ["PA", "Marapanim", "1504406"], + ["PA", "Marituba", "1504422"], + ["PA", "Medicil\u{e2}ndia", "1504455"], + ["PA", "Melga\u{e7}o", "1504505"], + ["PA", "Mocajuba", "1504604"], + ["PA", "Moju", "1504703"], + ["PA", "Moju\u{ed} dos Campos", "1504752"], + ["PA", "Monte Alegre", "1504802"], + ["PA", "Muan\u{e1}", "1504901"], + ["PA", "Nova Esperan\u{e7}a do Piri\u{e1}", "1504950"], + ["PA", "Nova Ipixuna", "1504976"], + ["PA", "Nova Timboteua", "1505007"], + ["PA", "Novo Progresso", "1505031"], + ["PA", "Novo Repartimento", "1505064"], + ["PA", "\u{d3}bidos", "1505106"], + ["PA", "Oeiras do Par\u{e1}", "1505205"], + ["PA", "Oriximin\u{e1}", "1505304"], + ["PA", "Our\u{e9}m", "1505403"], + ["PA", "Ouril\u{e2}ndia do Norte", "1505437"], + ["PA", "Pacaj\u{e1}", "1505486"], + ["PA", "Palestina do Par\u{e1}", "1505494"], + ["PA", "Paragominas", "1505502"], + ["PA", "Parauapebas", "1505536"], + ["PA", "Pau D'Arco", "1505551"], + ["PA", "Peixe-Boi", "1505601"], + ["PA", "Pi\u{e7}arra", "1505635"], + ["PA", "Placas", "1505650"], + ["PA", "Ponta de Pedras", "1505700"], + ["PA", "Portel", "1505809"], + ["PA", "Porto de Moz", "1505908"], + ["PA", "Prainha", "1506005"], + ["PA", "Primavera", "1506104"], + ["PA", "Quatipuru", "1506112"], + ["PA", "Reden\u{e7}\u{e3}o", "1506138"], + ["PA", "Rio Maria", "1506161"], + ["PA", "Rondon do Par\u{e1}", "1506187"], + ["PA", "Rur\u{f3}polis", "1506195"], + ["PA", "Salin\u{f3}polis", "1506203"], + ["PA", "Salvaterra", "1506302"], + ["PA", "Santa B\u{e1}rbara do Par\u{e1}", "1506351"], + ["PA", "Santa Cruz do Arari", "1506401"], + ["PA", "Santa Izabel do Par\u{e1}", "1506500"], + ["PA", "Santa Luzia do Par\u{e1}", "1506559"], + ["PA", "Santa Maria das Barreiras", "1506583"], + ["PA", "Santa Maria do Par\u{e1}", "1506609"], + ["PA", "Santana do Araguaia", "1506708"], + ["PA", "Santar\u{e9}m", "1506807"], + ["PA", "Santar\u{e9}m Novo", "1506906"], + ["PA", "Santo Ant\u{f4}nio do Tau\u{e1}", "1507003"], + ["PA", "S\u{e3}o Caetano de Odivelas", "1507102"], + ["PA", "S\u{e3}o Domingos do Araguaia", "1507151"], + ["PA", "S\u{e3}o Domingos do Capim", "1507201"], + ["PA", "S\u{e3}o F\u{e9}lix do Xingu", "1507300"], + ["PA", "S\u{e3}o Francisco do Par\u{e1}", "1507409"], + ["PA", "S\u{e3}o Geraldo do Araguaia", "1507458"], + ["PA", "S\u{e3}o Jo\u{e3}o da Ponta", "1507466"], + ["PA", "S\u{e3}o Jo\u{e3}o de Pirabas", "1507474"], + ["PA", "S\u{e3}o Jo\u{e3}o do Araguaia", "1507508"], + ["PA", "S\u{e3}o Miguel do Guam\u{e1}", "1507607"], + ["PA", "S\u{e3}o Sebasti\u{e3}o da Boa Vista", "1507706"], + ["PA", "Sapucaia", "1507755"], + ["PA", "Senador Jos\u{e9} Porf\u{ed}rio", "1507805"], + ["PA", "Soure", "1507904"], + ["PA", "Tail\u{e2}ndia", "1507953"], + ["PA", "Terra Alta", "1507961"], + ["PA", "Terra Santa", "1507979"], + ["PA", "Tom\u{e9}-A\u{e7}u", "1508001"], + ["PA", "Tracuateua", "1508035"], + ["PA", "Trair\u{e3}o", "1508050"], + ["PA", "Tucum\u{e3}", "1508084"], + ["PA", "Tucuru\u{ed}", "1508100"], + ["PA", "Ulian\u{f3}polis", "1508126"], + ["PA", "Uruar\u{e1}", "1508159"], + ["PA", "Vigia", "1508209"], + ["PA", "Viseu", "1508308"], + ["PA", "Vit\u{f3}ria do Xingu", "1508357"], + ["PA", "Xinguara", "1508407"], + ["PB", "\u{c1}gua Branca", "2500106"], + ["PB", "Aguiar", "2500205"], + ["PB", "Alagoa Grande", "2500304"], + ["PB", "Alagoa Nova", "2500403"], + ["PB", "Alagoinha", "2500502"], + ["PB", "Alcantil", "2500536"], + ["PB", "Algod\u{e3}o de Janda\u{ed}ra", "2500577"], + ["PB", "Alhandra", "2500601"], + ["PB", "Amparo", "2500734"], + ["PB", "Aparecida", "2500775"], + ["PB", "Ara\u{e7}agi", "2500809"], + ["PB", "Arara", "2500908"], + ["PB", "Araruna", "2501005"], + ["PB", "Areia", "2501104"], + ["PB", "Areia de Bara\u{fa}nas", "2501153"], + ["PB", "Areial", "2501203"], + ["PB", "Aroeiras", "2501302"], + ["PB", "Assun\u{e7}\u{e3}o", "2501351"], + ["PB", "Ba\u{ed}a da Trai\u{e7}\u{e3}o", "2501401"], + ["PB", "Bananeiras", "2501500"], + ["PB", "Bara\u{fa}na", "2501534"], + ["PB", "Barra de Santa Rosa", "2501609"], + ["PB", "Barra de Santana", "2501575"], + ["PB", "Barra de S\u{e3}o Miguel", "2501708"], + ["PB", "Bayeux", "2501807"], + ["PB", "Bel\u{e9}m", "2501906"], + ["PB", "Bel\u{e9}m do Brejo do Cruz", "2502003"], + ["PB", "Bernardino Batista", "2502052"], + ["PB", "Boa Ventura", "2502102"], + ["PB", "Boa Vista", "2502151"], + ["PB", "Bom Jesus", "2502201"], + ["PB", "Bom Sucesso", "2502300"], + ["PB", "Bonito de Santa F\u{e9}", "2502409"], + ["PB", "Boqueir\u{e3}o", "2502508"], + ["PB", "Borborema", "2502706"], + ["PB", "Brejo do Cruz", "2502805"], + ["PB", "Brejo dos Santos", "2502904"], + ["PB", "Caapor\u{e3}", "2503001"], + ["PB", "Cabaceiras", "2503100"], + ["PB", "Cabedelo", "2503209"], + ["PB", "Cachoeira dos \u{cd}ndios", "2503308"], + ["PB", "Cacimba de Areia", "2503407"], + ["PB", "Cacimba de Dentro", "2503506"], + ["PB", "Cacimbas", "2503555"], + ["PB", "Cai\u{e7}ara", "2503605"], + ["PB", "Cajazeiras", "2503704"], + ["PB", "Cajazeirinhas", "2503753"], + ["PB", "Caldas Brand\u{e3}o", "2503803"], + ["PB", "Camala\u{fa}", "2503902"], + ["PB", "Campina Grande", "2504009"], + ["PB", "Capim", "2504033"], + ["PB", "Cara\u{fa}bas", "2504074"], + ["PB", "Carrapateira", "2504108"], + ["PB", "Casserengue", "2504157"], + ["PB", "Catingueira", "2504207"], + ["PB", "Catol\u{e9} do Rocha", "2504306"], + ["PB", "Caturit\u{e9}", "2504355"], + ["PB", "Concei\u{e7}\u{e3}o", "2504405"], + ["PB", "Condado", "2504504"], + ["PB", "Conde", "2504603"], + ["PB", "Congo", "2504702"], + ["PB", "Coremas", "2504801"], + ["PB", "Coxixola", "2504850"], + ["PB", "Cruz do Esp\u{ed}rito Santo", "2504900"], + ["PB", "Cubati", "2505006"], + ["PB", "Cuit\u{e9}", "2505105"], + ["PB", "Cuit\u{e9} de Mamanguape", "2505238"], + ["PB", "Cuitegi", "2505204"], + ["PB", "Curral de Cima", "2505279"], + ["PB", "Curral Velho", "2505303"], + ["PB", "Dami\u{e3}o", "2505352"], + ["PB", "Desterro", "2505402"], + ["PB", "Diamante", "2505600"], + ["PB", "Dona In\u{ea}s", "2505709"], + ["PB", "Duas Estradas", "2505808"], + ["PB", "Emas", "2505907"], + ["PB", "Esperan\u{e7}a", "2506004"], + ["PB", "Fagundes", "2506103"], + ["PB", "Frei Martinho", "2506202"], + ["PB", "Gado Bravo", "2506251"], + ["PB", "Guarabira", "2506301"], + ["PB", "Gurinh\u{e9}m", "2506400"], + ["PB", "Gurj\u{e3}o", "2506509"], + ["PB", "Ibiara", "2506608"], + ["PB", "Igaracy", "2502607"], + ["PB", "Imaculada", "2506707"], + ["PB", "Ing\u{e1}", "2506806"], + ["PB", "Itabaiana", "2506905"], + ["PB", "Itaporanga", "2507002"], + ["PB", "Itapororoca", "2507101"], + ["PB", "Itatuba", "2507200"], + ["PB", "Jacara\u{fa}", "2507309"], + ["PB", "Jeric\u{f3}", "2507408"], + ["PB", "Jo\u{e3}o Pessoa", "2507507"], + ["PB", "Joca Claudino", "2513653"], + ["PB", "Juarez T\u{e1}vora", "2507606"], + ["PB", "Juazeirinho", "2507705"], + ["PB", "Junco do Serid\u{f3}", "2507804"], + ["PB", "Juripiranga", "2507903"], + ["PB", "Juru", "2508000"], + ["PB", "Lagoa", "2508109"], + ["PB", "Lagoa de Dentro", "2508208"], + ["PB", "Lagoa Seca", "2508307"], + ["PB", "Lastro", "2508406"], + ["PB", "Livramento", "2508505"], + ["PB", "Logradouro", "2508554"], + ["PB", "Lucena", "2508604"], + ["PB", "M\u{e3}e d'\u{c1}gua", "2508703"], + ["PB", "Malta", "2508802"], + ["PB", "Mamanguape", "2508901"], + ["PB", "Mana\u{ed}ra", "2509008"], + ["PB", "Marca\u{e7}\u{e3}o", "2509057"], + ["PB", "Mari", "2509107"], + ["PB", "Mariz\u{f3}polis", "2509156"], + ["PB", "Massaranduba", "2509206"], + ["PB", "Mataraca", "2509305"], + ["PB", "Matinhas", "2509339"], + ["PB", "Mato Grosso", "2509370"], + ["PB", "Matur\u{e9}ia", "2509396"], + ["PB", "Mogeiro", "2509404"], + ["PB", "Montadas", "2509503"], + ["PB", "Monte Horebe", "2509602"], + ["PB", "Monteiro", "2509701"], + ["PB", "Mulungu", "2509800"], + ["PB", "Natuba", "2509909"], + ["PB", "Nazarezinho", "2510006"], + ["PB", "Nova Floresta", "2510105"], + ["PB", "Nova Olinda", "2510204"], + ["PB", "Nova Palmeira", "2510303"], + ["PB", "Olho d'\u{c1}gua", "2510402"], + ["PB", "Olivedos", "2510501"], + ["PB", "Ouro Velho", "2510600"], + ["PB", "Parari", "2510659"], + ["PB", "Passagem", "2510709"], + ["PB", "Patos", "2510808"], + ["PB", "Paulista", "2510907"], + ["PB", "Pedra Branca", "2511004"], + ["PB", "Pedra Lavrada", "2511103"], + ["PB", "Pedras de Fogo", "2511202"], + ["PB", "Pedro R\u{e9}gis", "2512721"], + ["PB", "Pianc\u{f3}", "2511301"], + ["PB", "Picu\u{ed}", "2511400"], + ["PB", "Pilar", "2511509"], + ["PB", "Pil\u{f5}es", "2511608"], + ["PB", "Pil\u{f5}ezinhos", "2511707"], + ["PB", "Pirpirituba", "2511806"], + ["PB", "Pitimbu", "2511905"], + ["PB", "Pocinhos", "2512002"], + ["PB", "Po\u{e7}o Dantas", "2512036"], + ["PB", "Po\u{e7}o de Jos\u{e9} de Moura", "2512077"], + ["PB", "Pombal", "2512101"], + ["PB", "Prata", "2512200"], + ["PB", "Princesa Isabel", "2512309"], + ["PB", "Puxinan\u{e3}", "2512408"], + ["PB", "Queimadas", "2512507"], + ["PB", "Quixaba", "2512606"], + ["PB", "Rem\u{ed}gio", "2512705"], + ["PB", "Riach\u{e3}o", "2512747"], + ["PB", "Riach\u{e3}o do Bacamarte", "2512754"], + ["PB", "Riach\u{e3}o do Po\u{e7}o", "2512762"], + ["PB", "Riacho de Santo Ant\u{f4}nio", "2512788"], + ["PB", "Riacho dos Cavalos", "2512804"], + ["PB", "Rio Tinto", "2512903"], + ["PB", "Salgadinho", "2513000"], + ["PB", "Salgado de S\u{e3}o F\u{e9}lix", "2513109"], + ["PB", "Santa Cec\u{ed}lia", "2513158"], + ["PB", "Santa Cruz", "2513208"], + ["PB", "Santa Helena", "2513307"], + ["PB", "Santa In\u{ea}s", "2513356"], + ["PB", "Santa Luzia", "2513406"], + ["PB", "Santa Rita", "2513703"], + ["PB", "Santa Teresinha", "2513802"], + ["PB", "Santana de Mangueira", "2513505"], + ["PB", "Santana dos Garrotes", "2513604"], + ["PB", "Santo Andr\u{e9}", "2513851"], + ["PB", "S\u{e3}o Bentinho", "2513927"], + ["PB", "S\u{e3}o Bento", "2513901"], + ["PB", "S\u{e3}o Domingos", "2513968"], + ["PB", "S\u{e3}o Domingos do Cariri", "2513943"], + ["PB", "S\u{e3}o Francisco", "2513984"], + ["PB", "S\u{e3}o Jo\u{e3}o do Cariri", "2514008"], + ["PB", "S\u{e3}o Jo\u{e3}o do Rio do Peixe", "2500700"], + ["PB", "S\u{e3}o Jo\u{e3}o do Tigre", "2514107"], + ["PB", "S\u{e3}o Jos\u{e9} da Lagoa Tapada", "2514206"], + ["PB", "S\u{e3}o Jos\u{e9} de Caiana", "2514305"], + ["PB", "S\u{e3}o Jos\u{e9} de Espinharas", "2514404"], + ["PB", "S\u{e3}o Jos\u{e9} de Piranhas", "2514503"], + ["PB", "S\u{e3}o Jos\u{e9} de Princesa", "2514552"], + ["PB", "S\u{e3}o Jos\u{e9} do Bonfim", "2514602"], + ["PB", "S\u{e3}o Jos\u{e9} do Brejo do Cruz", "2514651"], + ["PB", "S\u{e3}o Jos\u{e9} do Sabugi", "2514701"], + ["PB", "S\u{e3}o Jos\u{e9} dos Cordeiros", "2514800"], + ["PB", "S\u{e3}o Jos\u{e9} dos Ramos", "2514453"], + ["PB", "S\u{e3}o Mamede", "2514909"], + ["PB", "S\u{e3}o Miguel de Taipu", "2515005"], + ["PB", "S\u{e3}o Sebasti\u{e3}o de Lagoa de Ro\u{e7}a", "2515104"], + ["PB", "S\u{e3}o Sebasti\u{e3}o do Umbuzeiro", "2515203"], + ["PB", "S\u{e3}o Vicente do Serid\u{f3}", "2515401"], + ["PB", "Sap\u{e9}", "2515302"], + ["PB", "Serra Branca", "2515500"], + ["PB", "Serra da Raiz", "2515609"], + ["PB", "Serra Grande", "2515708"], + ["PB", "Serra Redonda", "2515807"], + ["PB", "Serraria", "2515906"], + ["PB", "Sert\u{e3}ozinho", "2515930"], + ["PB", "Sobrado", "2515971"], + ["PB", "Sol\u{e2}nea", "2516003"], + ["PB", "Soledade", "2516102"], + ["PB", "Soss\u{ea}go", "2516151"], + ["PB", "Sousa", "2516201"], + ["PB", "Sum\u{e9}", "2516300"], + ["PB", "Tacima", "2516409"], + ["PB", "Tapero\u{e1}", "2516508"], + ["PB", "Tavares", "2516607"], + ["PB", "Teixeira", "2516706"], + ["PB", "Ten\u{f3}rio", "2516755"], + ["PB", "Triunfo", "2516805"], + ["PB", "Uira\u{fa}na", "2516904"], + ["PB", "Umbuzeiro", "2517001"], + ["PB", "V\u{e1}rzea", "2517100"], + ["PB", "Vieir\u{f3}polis", "2517209"], + ["PB", "Vista Serrana", "2505501"], + ["PB", "Zabel\u{ea}", "2517407"], + ["PR", "Abati\u{e1}", "4100103"], + ["PR", "Adrian\u{f3}polis", "4100202"], + ["PR", "Agudos do Sul", "4100301"], + ["PR", "Almirante Tamandar\u{e9}", "4100400"], + ["PR", "Altamira do Paran\u{e1}", "4100459"], + ["PR", "Alto Para\u{ed}so", "4128625"], + ["PR", "Alto Paran\u{e1}", "4100608"], + ["PR", "Alto Piquiri", "4100707"], + ["PR", "Alt\u{f4}nia", "4100509"], + ["PR", "Alvorada do Sul", "4100806"], + ["PR", "Amapor\u{e3}", "4100905"], + ["PR", "Amp\u{e9}re", "4101002"], + ["PR", "Anahy", "4101051"], + ["PR", "Andir\u{e1}", "4101101"], + ["PR", "\u{c2}ngulo", "4101150"], + ["PR", "Antonina", "4101200"], + ["PR", "Ant\u{f4}nio Olinto", "4101309"], + ["PR", "Apucarana", "4101408"], + ["PR", "Arapongas", "4101507"], + ["PR", "Arapoti", "4101606"], + ["PR", "Arapu\u{e3}", "4101655"], + ["PR", "Araruna", "4101705"], + ["PR", "Arauc\u{e1}ria", "4101804"], + ["PR", "Ariranha do Iva\u{ed}", "4101853"], + ["PR", "Assa\u{ed}", "4101903"], + ["PR", "Assis Chateaubriand", "4102000"], + ["PR", "Astorga", "4102109"], + ["PR", "Atalaia", "4102208"], + ["PR", "Balsa Nova", "4102307"], + ["PR", "Bandeirantes", "4102406"], + ["PR", "Barbosa Ferraz", "4102505"], + ["PR", "Barra do Jacar\u{e9}", "4102703"], + ["PR", "Barrac\u{e3}o", "4102604"], + ["PR", "Bela Vista da Caroba", "4102752"], + ["PR", "Bela Vista do Para\u{ed}so", "4102802"], + ["PR", "Bituruna", "4102901"], + ["PR", "Boa Esperan\u{e7}a", "4103008"], + ["PR", "Boa Esperan\u{e7}a do Igua\u{e7}u", "4103024"], + ["PR", "Boa Ventura de S\u{e3}o Roque", "4103040"], + ["PR", "Boa Vista da Aparecida", "4103057"], + ["PR", "Bocai\u{fa}va do Sul", "4103107"], + ["PR", "Bom Jesus do Sul", "4103156"], + ["PR", "Bom Sucesso", "4103206"], + ["PR", "Bom Sucesso do Sul", "4103222"], + ["PR", "Borraz\u{f3}polis", "4103305"], + ["PR", "Braganey", "4103354"], + ["PR", "Brasil\u{e2}ndia do Sul", "4103370"], + ["PR", "Cafeara", "4103404"], + ["PR", "Cafel\u{e2}ndia", "4103453"], + ["PR", "Cafezal do Sul", "4103479"], + ["PR", "Calif\u{f3}rnia", "4103503"], + ["PR", "Cambar\u{e1}", "4103602"], + ["PR", "Camb\u{e9}", "4103701"], + ["PR", "Cambira", "4103800"], + ["PR", "Campina da Lagoa", "4103909"], + ["PR", "Campina do Sim\u{e3}o", "4103958"], + ["PR", "Campina Grande do Sul", "4104006"], + ["PR", "Campo Bonito", "4104055"], + ["PR", "Campo do Tenente", "4104105"], + ["PR", "Campo Largo", "4104204"], + ["PR", "Campo Magro", "4104253"], + ["PR", "Campo Mour\u{e3}o", "4104303"], + ["PR", "C\u{e2}ndido de Abreu", "4104402"], + ["PR", "Cand\u{f3}i", "4104428"], + ["PR", "Cantagalo", "4104451"], + ["PR", "Capanema", "4104501"], + ["PR", "Capit\u{e3}o Le\u{f4}nidas Marques", "4104600"], + ["PR", "Carambe\u{ed}", "4104659"], + ["PR", "Carl\u{f3}polis", "4104709"], + ["PR", "Cascavel", "4104808"], + ["PR", "Castro", "4104907"], + ["PR", "Catanduvas", "4105003"], + ["PR", "Centen\u{e1}rio do Sul", "4105102"], + ["PR", "Cerro Azul", "4105201"], + ["PR", "C\u{e9}u Azul", "4105300"], + ["PR", "Chopinzinho", "4105409"], + ["PR", "Cianorte", "4105508"], + ["PR", "Cidade Ga\u{fa}cha", "4105607"], + ["PR", "Clevel\u{e2}ndia", "4105706"], + ["PR", "Colombo", "4105805"], + ["PR", "Colorado", "4105904"], + ["PR", "Congonhinhas", "4106001"], + ["PR", "Conselheiro Mairinck", "4106100"], + ["PR", "Contenda", "4106209"], + ["PR", "Corb\u{e9}lia", "4106308"], + ["PR", "Corn\u{e9}lio Proc\u{f3}pio", "4106407"], + ["PR", "Coronel Domingos Soares", "4106456"], + ["PR", "Coronel Vivida", "4106506"], + ["PR", "Corumbata\u{ed} do Sul", "4106555"], + ["PR", "Cruz Machado", "4106803"], + ["PR", "Cruzeiro do Igua\u{e7}u", "4106571"], + ["PR", "Cruzeiro do Oeste", "4106605"], + ["PR", "Cruzeiro do Sul", "4106704"], + ["PR", "Cruzmaltina", "4106852"], + ["PR", "Curitiba", "4106902"], + ["PR", "Curi\u{fa}va", "4107009"], + ["PR", "Diamante D'Oeste", "4107157"], + ["PR", "Diamante do Norte", "4107108"], + ["PR", "Diamante do Sul", "4107124"], + ["PR", "Dois Vizinhos", "4107207"], + ["PR", "Douradina", "4107256"], + ["PR", "Doutor Camargo", "4107306"], + ["PR", "Doutor Ulysses", "4128633"], + ["PR", "En\u{e9}as Marques", "4107405"], + ["PR", "Engenheiro Beltr\u{e3}o", "4107504"], + ["PR", "Entre Rios do Oeste", "4107538"], + ["PR", "Esperan\u{e7}a Nova", "4107520"], + ["PR", "Espig\u{e3}o Alto do Igua\u{e7}u", "4107546"], + ["PR", "Farol", "4107553"], + ["PR", "Faxinal", "4107603"], + ["PR", "Fazenda Rio Grande", "4107652"], + ["PR", "F\u{ea}nix", "4107702"], + ["PR", "Fernandes Pinheiro", "4107736"], + ["PR", "Figueira", "4107751"], + ["PR", "Flor da Serra do Sul", "4107850"], + ["PR", "Flora\u{ed}", "4107801"], + ["PR", "Floresta", "4107900"], + ["PR", "Florest\u{f3}polis", "4108007"], + ["PR", "Fl\u{f3}rida", "4108106"], + ["PR", "Formosa do Oeste", "4108205"], + ["PR", "Foz do Igua\u{e7}u", "4108304"], + ["PR", "Foz do Jord\u{e3}o", "4108452"], + ["PR", "Francisco Alves", "4108320"], + ["PR", "Francisco Beltr\u{e3}o", "4108403"], + ["PR", "General Carneiro", "4108502"], + ["PR", "Godoy Moreira", "4108551"], + ["PR", "Goioer\u{ea}", "4108601"], + ["PR", "Goioxim", "4108650"], + ["PR", "Grandes Rios", "4108700"], + ["PR", "Gua\u{ed}ra", "4108809"], + ["PR", "Guaira\u{e7}\u{e1}", "4108908"], + ["PR", "Guamiranga", "4108957"], + ["PR", "Guapirama", "4109005"], + ["PR", "Guaporema", "4109104"], + ["PR", "Guaraci", "4109203"], + ["PR", "Guarania\u{e7}u", "4109302"], + ["PR", "Guarapuava", "4109401"], + ["PR", "Guaraque\u{e7}aba", "4109500"], + ["PR", "Guaratuba", "4109609"], + ["PR", "Hon\u{f3}rio Serpa", "4109658"], + ["PR", "Ibaiti", "4109708"], + ["PR", "Ibema", "4109757"], + ["PR", "Ibipor\u{e3}", "4109807"], + ["PR", "Icara\u{ed}ma", "4109906"], + ["PR", "Iguara\u{e7}u", "4110003"], + ["PR", "Iguatu", "4110052"], + ["PR", "Imba\u{fa}", "4110078"], + ["PR", "Imbituva", "4110102"], + ["PR", "In\u{e1}cio Martins", "4110201"], + ["PR", "Inaj\u{e1}", "4110300"], + ["PR", "Indian\u{f3}polis", "4110409"], + ["PR", "Ipiranga", "4110508"], + ["PR", "Ipor\u{e3}", "4110607"], + ["PR", "Iracema do Oeste", "4110656"], + ["PR", "Irati", "4110706"], + ["PR", "Iretama", "4110805"], + ["PR", "Itaguaj\u{e9}", "4110904"], + ["PR", "Itaipul\u{e2}ndia", "4110953"], + ["PR", "Itambarac\u{e1}", "4111001"], + ["PR", "Itamb\u{e9}", "4111100"], + ["PR", "Itapejara d'Oeste", "4111209"], + ["PR", "Itaperu\u{e7}u", "4111258"], + ["PR", "Ita\u{fa}na do Sul", "4111308"], + ["PR", "Iva\u{ed}", "4111407"], + ["PR", "Ivaipor\u{e3}", "4111506"], + ["PR", "Ivat\u{e9}", "4111555"], + ["PR", "Ivatuba", "4111605"], + ["PR", "Jaboti", "4111704"], + ["PR", "Jacarezinho", "4111803"], + ["PR", "Jaguapit\u{e3}", "4111902"], + ["PR", "Jaguaria\u{ed}va", "4112009"], + ["PR", "Jandaia do Sul", "4112108"], + ["PR", "Jani\u{f3}polis", "4112207"], + ["PR", "Japira", "4112306"], + ["PR", "Japur\u{e1}", "4112405"], + ["PR", "Jardim Alegre", "4112504"], + ["PR", "Jardim Olinda", "4112603"], + ["PR", "Jataizinho", "4112702"], + ["PR", "Jesu\u{ed}tas", "4112751"], + ["PR", "Joaquim T\u{e1}vora", "4112801"], + ["PR", "Jundia\u{ed} do Sul", "4112900"], + ["PR", "Juranda", "4112959"], + ["PR", "Jussara", "4113007"], + ["PR", "Kalor\u{e9}", "4113106"], + ["PR", "Lapa", "4113205"], + ["PR", "Laranjal", "4113254"], + ["PR", "Laranjeiras do Sul", "4113304"], + ["PR", "Le\u{f3}polis", "4113403"], + ["PR", "Lidian\u{f3}polis", "4113429"], + ["PR", "Lindoeste", "4113452"], + ["PR", "Loanda", "4113502"], + ["PR", "Lobato", "4113601"], + ["PR", "Londrina", "4113700"], + ["PR", "Luiziana", "4113734"], + ["PR", "Lunardelli", "4113759"], + ["PR", "Lupion\u{f3}polis", "4113809"], + ["PR", "Mallet", "4113908"], + ["PR", "Mambor\u{ea}", "4114005"], + ["PR", "Mandagua\u{e7}u", "4114104"], + ["PR", "Mandaguari", "4114203"], + ["PR", "Mandirituba", "4114302"], + ["PR", "Manfrin\u{f3}polis", "4114351"], + ["PR", "Mangueirinha", "4114401"], + ["PR", "Manoel Ribas", "4114500"], + ["PR", "Marechal C\u{e2}ndido Rondon", "4114609"], + ["PR", "Maria Helena", "4114708"], + ["PR", "Marialva", "4114807"], + ["PR", "Maril\u{e2}ndia do Sul", "4114906"], + ["PR", "Marilena", "4115002"], + ["PR", "Mariluz", "4115101"], + ["PR", "Maring\u{e1}", "4115200"], + ["PR", "Mari\u{f3}polis", "4115309"], + ["PR", "Marip\u{e1}", "4115358"], + ["PR", "Marmeleiro", "4115408"], + ["PR", "Marquinho", "4115457"], + ["PR", "Marumbi", "4115507"], + ["PR", "Matel\u{e2}ndia", "4115606"], + ["PR", "Matinhos", "4115705"], + ["PR", "Mato Rico", "4115739"], + ["PR", "Mau\u{e1} da Serra", "4115754"], + ["PR", "Medianeira", "4115804"], + ["PR", "Mercedes", "4115853"], + ["PR", "Mirador", "4115903"], + ["PR", "Miraselva", "4116000"], + ["PR", "Missal", "4116059"], + ["PR", "Moreira Sales", "4116109"], + ["PR", "Morretes", "4116208"], + ["PR", "Munhoz de Melo", "4116307"], + ["PR", "Nossa Senhora das Gra\u{e7}as", "4116406"], + ["PR", "Nova Alian\u{e7}a do Iva\u{ed}", "4116505"], + ["PR", "Nova Am\u{e9}rica da Colina", "4116604"], + ["PR", "Nova Aurora", "4116703"], + ["PR", "Nova Cantu", "4116802"], + ["PR", "Nova Esperan\u{e7}a", "4116901"], + ["PR", "Nova Esperan\u{e7}a do Sudoeste", "4116950"], + ["PR", "Nova F\u{e1}tima", "4117008"], + ["PR", "Nova Laranjeiras", "4117057"], + ["PR", "Nova Londrina", "4117107"], + ["PR", "Nova Ol\u{ed}mpia", "4117206"], + ["PR", "Nova Prata do Igua\u{e7}u", "4117255"], + ["PR", "Nova Santa B\u{e1}rbara", "4117214"], + ["PR", "Nova Santa Rosa", "4117222"], + ["PR", "Nova Tebas", "4117271"], + ["PR", "Novo Itacolomi", "4117297"], + ["PR", "Ortigueira", "4117305"], + ["PR", "Ourizona", "4117404"], + ["PR", "Ouro Verde do Oeste", "4117453"], + ["PR", "Pai\u{e7}andu", "4117503"], + ["PR", "Palmas", "4117602"], + ["PR", "Palmeira", "4117701"], + ["PR", "Palmital", "4117800"], + ["PR", "Palotina", "4117909"], + ["PR", "Para\u{ed}so do Norte", "4118006"], + ["PR", "Paranacity", "4118105"], + ["PR", "Paranagu\u{e1}", "4118204"], + ["PR", "Paranapoema", "4118303"], + ["PR", "Paranava\u{ed}", "4118402"], + ["PR", "Pato Bragado", "4118451"], + ["PR", "Pato Branco", "4118501"], + ["PR", "Paula Freitas", "4118600"], + ["PR", "Paulo Frontin", "4118709"], + ["PR", "Peabiru", "4118808"], + ["PR", "Perobal", "4118857"], + ["PR", "P\u{e9}rola", "4118907"], + ["PR", "P\u{e9}rola d'Oeste", "4119004"], + ["PR", "Pi\u{ea}n", "4119103"], + ["PR", "Pinhais", "4119152"], + ["PR", "Pinhal de S\u{e3}o Bento", "4119251"], + ["PR", "Pinhal\u{e3}o", "4119202"], + ["PR", "Pinh\u{e3}o", "4119301"], + ["PR", "Pira\u{ed} do Sul", "4119400"], + ["PR", "Piraquara", "4119509"], + ["PR", "Pitanga", "4119608"], + ["PR", "Pitangueiras", "4119657"], + ["PR", "Planaltina do Paran\u{e1}", "4119707"], + ["PR", "Planalto", "4119806"], + ["PR", "Ponta Grossa", "4119905"], + ["PR", "Pontal do Paran\u{e1}", "4119954"], + ["PR", "Porecatu", "4120002"], + ["PR", "Porto Amazonas", "4120101"], + ["PR", "Porto Barreiro", "4120150"], + ["PR", "Porto Rico", "4120200"], + ["PR", "Porto Vit\u{f3}ria", "4120309"], + ["PR", "Prado Ferreira", "4120333"], + ["PR", "Pranchita", "4120358"], + ["PR", "Presidente Castelo Branco", "4120408"], + ["PR", "Primeiro de Maio", "4120507"], + ["PR", "Prudent\u{f3}polis", "4120606"], + ["PR", "Quarto Centen\u{e1}rio", "4120655"], + ["PR", "Quatigu\u{e1}", "4120705"], + ["PR", "Quatro Barras", "4120804"], + ["PR", "Quatro Pontes", "4120853"], + ["PR", "Quedas do Igua\u{e7}u", "4120903"], + ["PR", "Quer\u{ea}ncia do Norte", "4121000"], + ["PR", "Quinta do Sol", "4121109"], + ["PR", "Quitandinha", "4121208"], + ["PR", "Ramil\u{e2}ndia", "4121257"], + ["PR", "Rancho Alegre", "4121307"], + ["PR", "Rancho Alegre D'Oeste", "4121356"], + ["PR", "Realeza", "4121406"], + ["PR", "Rebou\u{e7}as", "4121505"], + ["PR", "Renascen\u{e7}a", "4121604"], + ["PR", "Reserva", "4121703"], + ["PR", "Reserva do Igua\u{e7}u", "4121752"], + ["PR", "Ribeir\u{e3}o Claro", "4121802"], + ["PR", "Ribeir\u{e3}o do Pinhal", "4121901"], + ["PR", "Rio Azul", "4122008"], + ["PR", "Rio Bom", "4122107"], + ["PR", "Rio Bonito do Igua\u{e7}u", "4122156"], + ["PR", "Rio Branco do Iva\u{ed}", "4122172"], + ["PR", "Rio Branco do Sul", "4122206"], + ["PR", "Rio Negro", "4122305"], + ["PR", "Rol\u{e2}ndia", "4122404"], + ["PR", "Roncador", "4122503"], + ["PR", "Rondon", "4122602"], + ["PR", "Ros\u{e1}rio do Iva\u{ed}", "4122651"], + ["PR", "Sab\u{e1}udia", "4122701"], + ["PR", "Salgado Filho", "4122800"], + ["PR", "Salto do Itarar\u{e9}", "4122909"], + ["PR", "Salto do Lontra", "4123006"], + ["PR", "Santa Am\u{e9}lia", "4123105"], + ["PR", "Santa Cec\u{ed}lia do Pav\u{e3}o", "4123204"], + ["PR", "Santa Cruz de Monte Castelo", "4123303"], + ["PR", "Santa F\u{e9}", "4123402"], + ["PR", "Santa Helena", "4123501"], + ["PR", "Santa In\u{ea}s", "4123600"], + ["PR", "Santa Isabel do Iva\u{ed}", "4123709"], + ["PR", "Santa Izabel do Oeste", "4123808"], + ["PR", "Santa L\u{fa}cia", "4123824"], + ["PR", "Santa Maria do Oeste", "4123857"], + ["PR", "Santa Mariana", "4123907"], + ["PR", "Santa M\u{f4}nica", "4123956"], + ["PR", "Santa Tereza do Oeste", "4124020"], + ["PR", "Santa Terezinha de Itaipu", "4124053"], + ["PR", "Santana do Itarar\u{e9}", "4124004"], + ["PR", "Santo Ant\u{f4}nio da Platina", "4124103"], + ["PR", "Santo Ant\u{f4}nio do Caiu\u{e1}", "4124202"], + ["PR", "Santo Ant\u{f4}nio do Para\u{ed}so", "4124301"], + ["PR", "Santo Ant\u{f4}nio do Sudoeste", "4124400"], + ["PR", "Santo In\u{e1}cio", "4124509"], + ["PR", "S\u{e3}o Carlos do Iva\u{ed}", "4124608"], + ["PR", "S\u{e3}o Jer\u{f4}nimo da Serra", "4124707"], + ["PR", "S\u{e3}o Jo\u{e3}o", "4124806"], + ["PR", "S\u{e3}o Jo\u{e3}o do Caiu\u{e1}", "4124905"], + ["PR", "S\u{e3}o Jo\u{e3}o do Iva\u{ed}", "4125001"], + ["PR", "S\u{e3}o Jo\u{e3}o do Triunfo", "4125100"], + ["PR", "S\u{e3}o Jorge d'Oeste", "4125209"], + ["PR", "S\u{e3}o Jorge do Iva\u{ed}", "4125308"], + ["PR", "S\u{e3}o Jorge do Patroc\u{ed}nio", "4125357"], + ["PR", "S\u{e3}o Jos\u{e9} da Boa Vista", "4125407"], + ["PR", "S\u{e3}o Jos\u{e9} das Palmeiras", "4125456"], + ["PR", "S\u{e3}o Jos\u{e9} dos Pinhais", "4125506"], + ["PR", "S\u{e3}o Manoel do Paran\u{e1}", "4125555"], + ["PR", "S\u{e3}o Mateus do Sul", "4125605"], + ["PR", "S\u{e3}o Miguel do Igua\u{e7}u", "4125704"], + ["PR", "S\u{e3}o Pedro do Igua\u{e7}u", "4125753"], + ["PR", "S\u{e3}o Pedro do Iva\u{ed}", "4125803"], + ["PR", "S\u{e3}o Pedro do Paran\u{e1}", "4125902"], + ["PR", "S\u{e3}o Sebasti\u{e3}o da Amoreira", "4126009"], + ["PR", "S\u{e3}o Tom\u{e9}", "4126108"], + ["PR", "Sapopema", "4126207"], + ["PR", "Sarandi", "4126256"], + ["PR", "Saudade do Igua\u{e7}u", "4126272"], + ["PR", "Seng\u{e9}s", "4126306"], + ["PR", "Serran\u{f3}polis do Igua\u{e7}u", "4126355"], + ["PR", "Sertaneja", "4126405"], + ["PR", "Sertan\u{f3}polis", "4126504"], + ["PR", "Siqueira Campos", "4126603"], + ["PR", "Sulina", "4126652"], + ["PR", "Tamarana", "4126678"], + ["PR", "Tamboara", "4126702"], + ["PR", "Tapejara", "4126801"], + ["PR", "Tapira", "4126900"], + ["PR", "Teixeira Soares", "4127007"], + ["PR", "Tel\u{ea}maco Borba", "4127106"], + ["PR", "Terra Boa", "4127205"], + ["PR", "Terra Rica", "4127304"], + ["PR", "Terra Roxa", "4127403"], + ["PR", "Tibagi", "4127502"], + ["PR", "Tijucas do Sul", "4127601"], + ["PR", "Toledo", "4127700"], + ["PR", "Tomazina", "4127809"], + ["PR", "Tr\u{ea}s Barras do Paran\u{e1}", "4127858"], + ["PR", "Tunas do Paran\u{e1}", "4127882"], + ["PR", "Tuneiras do Oeste", "4127908"], + ["PR", "Tup\u{e3}ssi", "4127957"], + ["PR", "Turvo", "4127965"], + ["PR", "Ubirat\u{e3}", "4128005"], + ["PR", "Umuarama", "4128104"], + ["PR", "Uni\u{e3}o da Vit\u{f3}ria", "4128203"], + ["PR", "Uniflor", "4128302"], + ["PR", "Ura\u{ed}", "4128401"], + ["PR", "Ventania", "4128534"], + ["PR", "Vera Cruz do Oeste", "4128559"], + ["PR", "Ver\u{ea}", "4128609"], + ["PR", "Virmond", "4128658"], + ["PR", "Vitorino", "4128708"], + ["PR", "Wenceslau Braz", "4128500"], + ["PR", "Xambr\u{ea}", "4128807"], + ["PE", "Abreu e Lima", "2600054"], + ["PE", "Afogados da Ingazeira", "2600104"], + ["PE", "Afr\u{e2}nio", "2600203"], + ["PE", "Agrestina", "2600302"], + ["PE", "\u{c1}gua Preta", "2600401"], + ["PE", "\u{c1}guas Belas", "2600500"], + ["PE", "Alagoinha", "2600609"], + ["PE", "Alian\u{e7}a", "2600708"], + ["PE", "Altinho", "2600807"], + ["PE", "Amaraji", "2600906"], + ["PE", "Angelim", "2601003"], + ["PE", "Ara\u{e7}oiaba", "2601052"], + ["PE", "Araripina", "2601102"], + ["PE", "Arcoverde", "2601201"], + ["PE", "Barra de Guabiraba", "2601300"], + ["PE", "Barreiros", "2601409"], + ["PE", "Bel\u{e9}m de Maria", "2601508"], + ["PE", "Bel\u{e9}m do S\u{e3}o Francisco", "2601607"], + ["PE", "Belo Jardim", "2601706"], + ["PE", "Bet\u{e2}nia", "2601805"], + ["PE", "Bezerros", "2601904"], + ["PE", "Bodoc\u{f3}", "2602001"], + ["PE", "Bom Conselho", "2602100"], + ["PE", "Bom Jardim", "2602209"], + ["PE", "Bonito", "2602308"], + ["PE", "Brej\u{e3}o", "2602407"], + ["PE", "Brejinho", "2602506"], + ["PE", "Brejo da Madre de Deus", "2602605"], + ["PE", "Buenos Aires", "2602704"], + ["PE", "Bu\u{ed}que", "2602803"], + ["PE", "Cabo de Santo Agostinho", "2602902"], + ["PE", "Cabrob\u{f3}", "2603009"], + ["PE", "Cachoeirinha", "2603108"], + ["PE", "Caet\u{e9}s", "2603207"], + ["PE", "Cal\u{e7}ado", "2603306"], + ["PE", "Calumbi", "2603405"], + ["PE", "Camaragibe", "2603454"], + ["PE", "Camocim de S\u{e3}o F\u{e9}lix", "2603504"], + ["PE", "Camutanga", "2603603"], + ["PE", "Canhotinho", "2603702"], + ["PE", "Capoeiras", "2603801"], + ["PE", "Carna\u{ed}ba", "2603900"], + ["PE", "Carnaubeira da Penha", "2603926"], + ["PE", "Carpina", "2604007"], + ["PE", "Caruaru", "2604106"], + ["PE", "Casinhas", "2604155"], + ["PE", "Catende", "2604205"], + ["PE", "Cedro", "2604304"], + ["PE", "Ch\u{e3} de Alegria", "2604403"], + ["PE", "Ch\u{e3} Grande", "2604502"], + ["PE", "Condado", "2604601"], + ["PE", "Correntes", "2604700"], + ["PE", "Cort\u{ea}s", "2604809"], + ["PE", "Cumaru", "2604908"], + ["PE", "Cupira", "2605004"], + ["PE", "Cust\u{f3}dia", "2605103"], + ["PE", "Dormentes", "2605152"], + ["PE", "Escada", "2605202"], + ["PE", "Exu", "2605301"], + ["PE", "Feira Nova", "2605400"], + ["PE", "Fernando de Noronha", "2605459"], + ["PE", "Ferreiros", "2605509"], + ["PE", "Flores", "2605608"], + ["PE", "Floresta", "2605707"], + ["PE", "Frei Miguelinho", "2605806"], + ["PE", "Gameleira", "2605905"], + ["PE", "Garanhuns", "2606002"], + ["PE", "Gl\u{f3}ria do Goit\u{e1}", "2606101"], + ["PE", "Goiana", "2606200"], + ["PE", "Granito", "2606309"], + ["PE", "Gravat\u{e1}", "2606408"], + ["PE", "Iati", "2606507"], + ["PE", "Ibimirim", "2606606"], + ["PE", "Ibirajuba", "2606705"], + ["PE", "Igarassu", "2606804"], + ["PE", "Iguaracy", "2606903"], + ["PE", "Ilha de Itamarac\u{e1}", "2607604"], + ["PE", "Inaj\u{e1}", "2607000"], + ["PE", "Ingazeira", "2607109"], + ["PE", "Ipojuca", "2607208"], + ["PE", "Ipubi", "2607307"], + ["PE", "Itacuruba", "2607406"], + ["PE", "Ita\u{ed}ba", "2607505"], + ["PE", "Itamb\u{e9}", "2607653"], + ["PE", "Itapetim", "2607703"], + ["PE", "Itapissuma", "2607752"], + ["PE", "Itaquitinga", "2607802"], + ["PE", "Jaboat\u{e3}o dos Guararapes", "2607901"], + ["PE", "Jaqueira", "2607950"], + ["PE", "Jata\u{fa}ba", "2608008"], + ["PE", "Jatob\u{e1}", "2608057"], + ["PE", "Jo\u{e3}o Alfredo", "2608107"], + ["PE", "Joaquim Nabuco", "2608206"], + ["PE", "Jucati", "2608255"], + ["PE", "Jupi", "2608305"], + ["PE", "Jurema", "2608404"], + ["PE", "Lagoa de Itaenga", "2608503"], + ["PE", "Lagoa do Carro", "2608453"], + ["PE", "Lagoa do Ouro", "2608602"], + ["PE", "Lagoa dos Gatos", "2608701"], + ["PE", "Lagoa Grande", "2608750"], + ["PE", "Lajedo", "2608800"], + ["PE", "Limoeiro", "2608909"], + ["PE", "Macaparana", "2609006"], + ["PE", "Machados", "2609105"], + ["PE", "Manari", "2609154"], + ["PE", "Maraial", "2609204"], + ["PE", "Mirandiba", "2609303"], + ["PE", "Moreil\u{e2}ndia", "2614303"], + ["PE", "Moreno", "2609402"], + ["PE", "Nazar\u{e9} da Mata", "2609501"], + ["PE", "Olinda", "2609600"], + ["PE", "Orob\u{f3}", "2609709"], + ["PE", "Oroc\u{f3}", "2609808"], + ["PE", "Ouricuri", "2609907"], + ["PE", "Palmares", "2610004"], + ["PE", "Palmeirina", "2610103"], + ["PE", "Panelas", "2610202"], + ["PE", "Paranatama", "2610301"], + ["PE", "Parnamirim", "2610400"], + ["PE", "Passira", "2610509"], + ["PE", "Paudalho", "2610608"], + ["PE", "Paulista", "2610707"], + ["PE", "Pedra", "2610806"], + ["PE", "Pesqueira", "2610905"], + ["PE", "Petrol\u{e2}ndia", "2611002"], + ["PE", "Petrolina", "2611101"], + ["PE", "Po\u{e7}\u{e3}o", "2611200"], + ["PE", "Pombos", "2611309"], + ["PE", "Primavera", "2611408"], + ["PE", "Quipap\u{e1}", "2611507"], + ["PE", "Quixaba", "2611533"], + ["PE", "Recife", "2611606"], + ["PE", "Riacho das Almas", "2611705"], + ["PE", "Ribeir\u{e3}o", "2611804"], + ["PE", "Rio Formoso", "2611903"], + ["PE", "Sair\u{e9}", "2612000"], + ["PE", "Salgadinho", "2612109"], + ["PE", "Salgueiro", "2612208"], + ["PE", "Salo\u{e1}", "2612307"], + ["PE", "Sanhar\u{f3}", "2612406"], + ["PE", "Santa Cruz", "2612455"], + ["PE", "Santa Cruz da Baixa Verde", "2612471"], + ["PE", "Santa Cruz do Capibaribe", "2612505"], + ["PE", "Santa Filomena", "2612554"], + ["PE", "Santa Maria da Boa Vista", "2612604"], + ["PE", "Santa Maria do Cambuc\u{e1}", "2612703"], + ["PE", "Santa Terezinha", "2612802"], + ["PE", "S\u{e3}o Benedito do Sul", "2612901"], + ["PE", "S\u{e3}o Bento do Una", "2613008"], + ["PE", "S\u{e3}o Caitano", "2613107"], + ["PE", "S\u{e3}o Jo\u{e3}o", "2613206"], + ["PE", "S\u{e3}o Joaquim do Monte", "2613305"], + ["PE", "S\u{e3}o Jos\u{e9} da Coroa Grande", "2613404"], + ["PE", "S\u{e3}o Jos\u{e9} do Belmonte", "2613503"], + ["PE", "S\u{e3}o Jos\u{e9} do Egito", "2613602"], + ["PE", "S\u{e3}o Louren\u{e7}o da Mata", "2613701"], + ["PE", "S\u{e3}o Vicente F\u{e9}rrer", "2613800"], + ["PE", "Serra Talhada", "2613909"], + ["PE", "Serrita", "2614006"], + ["PE", "Sert\u{e2}nia", "2614105"], + ["PE", "Sirinha\u{e9}m", "2614204"], + ["PE", "Solid\u{e3}o", "2614402"], + ["PE", "Surubim", "2614501"], + ["PE", "Tabira", "2614600"], + ["PE", "Tacaimb\u{f3}", "2614709"], + ["PE", "Tacaratu", "2614808"], + ["PE", "Tamandar\u{e9}", "2614857"], + ["PE", "Taquaritinga do Norte", "2615003"], + ["PE", "Terezinha", "2615102"], + ["PE", "Terra Nova", "2615201"], + ["PE", "Timba\u{fa}ba", "2615300"], + ["PE", "Toritama", "2615409"], + ["PE", "Tracunha\u{e9}m", "2615508"], + ["PE", "Trindade", "2615607"], + ["PE", "Triunfo", "2615706"], + ["PE", "Tupanatinga", "2615805"], + ["PE", "Tuparetama", "2615904"], + ["PE", "Venturosa", "2616001"], + ["PE", "Verdejante", "2616100"], + ["PE", "Vertente do L\u{e9}rio", "2616183"], + ["PE", "Vertentes", "2616209"], + ["PE", "Vic\u{ea}ncia", "2616308"], + ["PE", "Vit\u{f3}ria de Santo Ant\u{e3}o", "2616407"], + ["PE", "Xex\u{e9}u", "2616506"], + ["PI", "Acau\u{e3}", "2200053"], + ["PI", "Agricol\u{e2}ndia", "2200103"], + ["PI", "\u{c1}gua Branca", "2200202"], + ["PI", "Alagoinha do Piau\u{ed}", "2200251"], + ["PI", "Alegrete do Piau\u{ed}", "2200277"], + ["PI", "Alto Long\u{e1}", "2200301"], + ["PI", "Altos", "2200400"], + ["PI", "Alvorada do Gurgu\u{e9}ia", "2200459"], + ["PI", "Amarante", "2200509"], + ["PI", "Angical do Piau\u{ed}", "2200608"], + ["PI", "An\u{ed}sio de Abreu", "2200707"], + ["PI", "Ant\u{f4}nio Almeida", "2200806"], + ["PI", "Aroazes", "2200905"], + ["PI", "Aroeiras do Itaim", "2200954"], + ["PI", "Arraial", "2201002"], + ["PI", "Assun\u{e7}\u{e3}o do Piau\u{ed}", "2201051"], + ["PI", "Avelino Lopes", "2201101"], + ["PI", "Baixa Grande do Ribeiro", "2201150"], + ["PI", "Barra D'Alc\u{e2}ntara", "2201176"], + ["PI", "Barras", "2201200"], + ["PI", "Barreiras do Piau\u{ed}", "2201309"], + ["PI", "Barro Duro", "2201408"], + ["PI", "Batalha", "2201507"], + ["PI", "Bela Vista do Piau\u{ed}", "2201556"], + ["PI", "Bel\u{e9}m do Piau\u{ed}", "2201572"], + ["PI", "Beneditinos", "2201606"], + ["PI", "Bertol\u{ed}nia", "2201705"], + ["PI", "Bet\u{e2}nia do Piau\u{ed}", "2201739"], + ["PI", "Boa Hora", "2201770"], + ["PI", "Bocaina", "2201804"], + ["PI", "Bom Jesus", "2201903"], + ["PI", "Bom Princ\u{ed}pio do Piau\u{ed}", "2201919"], + ["PI", "Bonfim do Piau\u{ed}", "2201929"], + ["PI", "Boqueir\u{e3}o do Piau\u{ed}", "2201945"], + ["PI", "Brasileira", "2201960"], + ["PI", "Brejo do Piau\u{ed}", "2201988"], + ["PI", "Buriti dos Lopes", "2202000"], + ["PI", "Buriti dos Montes", "2202026"], + ["PI", "Cabeceiras do Piau\u{ed}", "2202059"], + ["PI", "Cajazeiras do Piau\u{ed}", "2202075"], + ["PI", "Cajueiro da Praia", "2202083"], + ["PI", "Caldeir\u{e3}o Grande do Piau\u{ed}", "2202091"], + ["PI", "Campinas do Piau\u{ed}", "2202109"], + ["PI", "Campo Alegre do Fidalgo", "2202117"], + ["PI", "Campo Grande do Piau\u{ed}", "2202133"], + ["PI", "Campo Largo do Piau\u{ed}", "2202174"], + ["PI", "Campo Maior", "2202208"], + ["PI", "Canavieira", "2202251"], + ["PI", "Canto do Buriti", "2202307"], + ["PI", "Capit\u{e3}o de Campos", "2202406"], + ["PI", "Capit\u{e3}o Gerv\u{e1}sio Oliveira", "2202455"], + ["PI", "Caracol", "2202505"], + ["PI", "Cara\u{fa}bas do Piau\u{ed}", "2202539"], + ["PI", "Caridade do Piau\u{ed}", "2202554"], + ["PI", "Castelo do Piau\u{ed}", "2202604"], + ["PI", "Caxing\u{f3}", "2202653"], + ["PI", "Cocal", "2202703"], + ["PI", "Cocal de Telha", "2202711"], + ["PI", "Cocal dos Alves", "2202729"], + ["PI", "Coivaras", "2202737"], + ["PI", "Col\u{f4}nia do Gurgu\u{e9}ia", "2202752"], + ["PI", "Col\u{f4}nia do Piau\u{ed}", "2202778"], + ["PI", "Concei\u{e7}\u{e3}o do Canind\u{e9}", "2202802"], + ["PI", "Coronel Jos\u{e9} Dias", "2202851"], + ["PI", "Corrente", "2202901"], + ["PI", "Cristal\u{e2}ndia do Piau\u{ed}", "2203008"], + ["PI", "Cristino Castro", "2203107"], + ["PI", "Curimat\u{e1}", "2203206"], + ["PI", "Currais", "2203230"], + ["PI", "Curral Novo do Piau\u{ed}", "2203271"], + ["PI", "Curralinhos", "2203255"], + ["PI", "Demerval Lob\u{e3}o", "2203305"], + ["PI", "Dirceu Arcoverde", "2203354"], + ["PI", "Dom Expedito Lopes", "2203404"], + ["PI", "Dom Inoc\u{ea}ncio", "2203453"], + ["PI", "Domingos Mour\u{e3}o", "2203420"], + ["PI", "Elesb\u{e3}o Veloso", "2203503"], + ["PI", "Eliseu Martins", "2203602"], + ["PI", "Esperantina", "2203701"], + ["PI", "Fartura do Piau\u{ed}", "2203750"], + ["PI", "Flores do Piau\u{ed}", "2203800"], + ["PI", "Floresta do Piau\u{ed}", "2203859"], + ["PI", "Floriano", "2203909"], + ["PI", "Francin\u{f3}polis", "2204006"], + ["PI", "Francisco Ayres", "2204105"], + ["PI", "Francisco Macedo", "2204154"], + ["PI", "Francisco Santos", "2204204"], + ["PI", "Fronteiras", "2204303"], + ["PI", "Geminiano", "2204352"], + ["PI", "Gilbu\u{e9}s", "2204402"], + ["PI", "Guadalupe", "2204501"], + ["PI", "Guaribas", "2204550"], + ["PI", "Hugo Napole\u{e3}o", "2204600"], + ["PI", "Ilha Grande", "2204659"], + ["PI", "Inhuma", "2204709"], + ["PI", "Ipiranga do Piau\u{ed}", "2204808"], + ["PI", "Isa\u{ed}as Coelho", "2204907"], + ["PI", "Itain\u{f3}polis", "2205003"], + ["PI", "Itaueira", "2205102"], + ["PI", "Jacobina do Piau\u{ed}", "2205151"], + ["PI", "Jaic\u{f3}s", "2205201"], + ["PI", "Jardim do Mulato", "2205250"], + ["PI", "Jatob\u{e1} do Piau\u{ed}", "2205276"], + ["PI", "Jerumenha", "2205300"], + ["PI", "Jo\u{e3}o Costa", "2205359"], + ["PI", "Joaquim Pires", "2205409"], + ["PI", "Joca Marques", "2205458"], + ["PI", "Jos\u{e9} de Freitas", "2205508"], + ["PI", "Juazeiro do Piau\u{ed}", "2205516"], + ["PI", "J\u{fa}lio Borges", "2205524"], + ["PI", "Jurema", "2205532"], + ["PI", "Lagoa Alegre", "2205557"], + ["PI", "Lagoa de S\u{e3}o Francisco", "2205573"], + ["PI", "Lagoa do Barro do Piau\u{ed}", "2205565"], + ["PI", "Lagoa do Piau\u{ed}", "2205581"], + ["PI", "Lagoa do S\u{ed}tio", "2205599"], + ["PI", "Lagoinha do Piau\u{ed}", "2205540"], + ["PI", "Landri Sales", "2205607"], + ["PI", "Lu\u{ed}s Correia", "2205706"], + ["PI", "Luzil\u{e2}ndia", "2205805"], + ["PI", "Madeiro", "2205854"], + ["PI", "Manoel Em\u{ed}dio", "2205904"], + ["PI", "Marcol\u{e2}ndia", "2205953"], + ["PI", "Marcos Parente", "2206001"], + ["PI", "Massap\u{ea} do Piau\u{ed}", "2206050"], + ["PI", "Matias Ol\u{ed}mpio", "2206100"], + ["PI", "Miguel Alves", "2206209"], + ["PI", "Miguel Le\u{e3}o", "2206308"], + ["PI", "Milton Brand\u{e3}o", "2206357"], + ["PI", "Monsenhor Gil", "2206407"], + ["PI", "Monsenhor Hip\u{f3}lito", "2206506"], + ["PI", "Monte Alegre do Piau\u{ed}", "2206605"], + ["PI", "Morro Cabe\u{e7}a no Tempo", "2206654"], + ["PI", "Morro do Chap\u{e9}u do Piau\u{ed}", "2206670"], + ["PI", "Murici dos Portelas", "2206696"], + ["PI", "Nazar\u{e9} do Piau\u{ed}", "2206704"], + ["PI", "Naz\u{e1}ria", "2206720"], + ["PI", "Nossa Senhora de Nazar\u{e9}", "2206753"], + ["PI", "Nossa Senhora dos Rem\u{e9}dios", "2206803"], + ["PI", "Nova Santa Rita", "2207959"], + ["PI", "Novo Oriente do Piau\u{ed}", "2206902"], + ["PI", "Novo Santo Ant\u{f4}nio", "2206951"], + ["PI", "Oeiras", "2207009"], + ["PI", "Olho D'\u{c1}gua do Piau\u{ed}", "2207108"], + ["PI", "Padre Marcos", "2207207"], + ["PI", "Paes Landim", "2207306"], + ["PI", "Paje\u{fa} do Piau\u{ed}", "2207355"], + ["PI", "Palmeira do Piau\u{ed}", "2207405"], + ["PI", "Palmeirais", "2207504"], + ["PI", "Paquet\u{e1}", "2207553"], + ["PI", "Parnagu\u{e1}", "2207603"], + ["PI", "Parna\u{ed}ba", "2207702"], + ["PI", "Passagem Franca do Piau\u{ed}", "2207751"], + ["PI", "Patos do Piau\u{ed}", "2207777"], + ["PI", "Pau D'Arco do Piau\u{ed}", "2207793"], + ["PI", "Paulistana", "2207801"], + ["PI", "Pavussu", "2207850"], + ["PI", "Pedro II", "2207900"], + ["PI", "Pedro Laurentino", "2207934"], + ["PI", "Picos", "2208007"], + ["PI", "Pimenteiras", "2208106"], + ["PI", "Pio IX", "2208205"], + ["PI", "Piracuruca", "2208304"], + ["PI", "Piripiri", "2208403"], + ["PI", "Porto", "2208502"], + ["PI", "Porto Alegre do Piau\u{ed}", "2208551"], + ["PI", "Prata do Piau\u{ed}", "2208601"], + ["PI", "Queimada Nova", "2208650"], + ["PI", "Reden\u{e7}\u{e3}o do Gurgu\u{e9}ia", "2208700"], + ["PI", "Regenera\u{e7}\u{e3}o", "2208809"], + ["PI", "Riacho Frio", "2208858"], + ["PI", "Ribeira do Piau\u{ed}", "2208874"], + ["PI", "Ribeiro Gon\u{e7}alves", "2208908"], + ["PI", "Rio Grande do Piau\u{ed}", "2209005"], + ["PI", "Santa Cruz do Piau\u{ed}", "2209104"], + ["PI", "Santa Cruz dos Milagres", "2209153"], + ["PI", "Santa Filomena", "2209203"], + ["PI", "Santa Luz", "2209302"], + ["PI", "Santa Rosa do Piau\u{ed}", "2209377"], + ["PI", "Santana do Piau\u{ed}", "2209351"], + ["PI", "Santo Ant\u{f4}nio de Lisboa", "2209401"], + ["PI", "Santo Ant\u{f4}nio dos Milagres", "2209450"], + ["PI", "Santo In\u{e1}cio do Piau\u{ed}", "2209500"], + ["PI", "S\u{e3}o Braz do Piau\u{ed}", "2209559"], + ["PI", "S\u{e3}o F\u{e9}lix do Piau\u{ed}", "2209609"], + ["PI", "S\u{e3}o Francisco de Assis do Piau\u{ed}", "2209658"], + ["PI", "S\u{e3}o Francisco do Piau\u{ed}", "2209708"], + ["PI", "S\u{e3}o Gon\u{e7}alo do Gurgu\u{e9}ia", "2209757"], + ["PI", "S\u{e3}o Gon\u{e7}alo do Piau\u{ed}", "2209807"], + ["PI", "S\u{e3}o Jo\u{e3}o da Canabrava", "2209856"], + ["PI", "S\u{e3}o Jo\u{e3}o da Fronteira", "2209872"], + ["PI", "S\u{e3}o Jo\u{e3}o da Serra", "2209906"], + ["PI", "S\u{e3}o Jo\u{e3}o da Varjota", "2209955"], + ["PI", "S\u{e3}o Jo\u{e3}o do Arraial", "2209971"], + ["PI", "S\u{e3}o Jo\u{e3}o do Piau\u{ed}", "2210003"], + ["PI", "S\u{e3}o Jos\u{e9} do Divino", "2210052"], + ["PI", "S\u{e3}o Jos\u{e9} do Peixe", "2210102"], + ["PI", "S\u{e3}o Jos\u{e9} do Piau\u{ed}", "2210201"], + ["PI", "S\u{e3}o Juli\u{e3}o", "2210300"], + ["PI", "S\u{e3}o Louren\u{e7}o do Piau\u{ed}", "2210359"], + ["PI", "S\u{e3}o Luis do Piau\u{ed}", "2210375"], + ["PI", "S\u{e3}o Miguel da Baixa Grande", "2210383"], + ["PI", "S\u{e3}o Miguel do Fidalgo", "2210391"], + ["PI", "S\u{e3}o Miguel do Tapuio", "2210409"], + ["PI", "S\u{e3}o Pedro do Piau\u{ed}", "2210508"], + ["PI", "S\u{e3}o Raimundo Nonato", "2210607"], + ["PI", "Sebasti\u{e3}o Barros", "2210623"], + ["PI", "Sebasti\u{e3}o Leal", "2210631"], + ["PI", "Sigefredo Pacheco", "2210656"], + ["PI", "Sim\u{f5}es", "2210706"], + ["PI", "Simpl\u{ed}cio Mendes", "2210805"], + ["PI", "Socorro do Piau\u{ed}", "2210904"], + ["PI", "Sussuapara", "2210938"], + ["PI", "Tamboril do Piau\u{ed}", "2210953"], + ["PI", "Tanque do Piau\u{ed}", "2210979"], + ["PI", "Teresina", "2211001"], + ["PI", "Uni\u{e3}o", "2211100"], + ["PI", "Uru\u{e7}u\u{ed}", "2211209"], + ["PI", "Valen\u{e7}a do Piau\u{ed}", "2211308"], + ["PI", "V\u{e1}rzea Branca", "2211357"], + ["PI", "V\u{e1}rzea Grande", "2211407"], + ["PI", "Vera Mendes", "2211506"], + ["PI", "Vila Nova do Piau\u{ed}", "2211605"], + ["PI", "Wall Ferraz", "2211704"], + ["RJ", "Angra dos Reis", "3300100"], + ["RJ", "Aperib\u{e9}", "3300159"], + ["RJ", "Araruama", "3300209"], + ["RJ", "Areal", "3300225"], + ["RJ", "Arma\u{e7}\u{e3}o dos B\u{fa}zios", "3300233"], + ["RJ", "Arraial do Cabo", "3300258"], + ["RJ", "Barra do Pira\u{ed}", "3300308"], + ["RJ", "Barra Mansa", "3300407"], + ["RJ", "Belford Roxo", "3300456"], + ["RJ", "Bom Jardim", "3300506"], + ["RJ", "Bom Jesus do Itabapoana", "3300605"], + ["RJ", "Cabo Frio", "3300704"], + ["RJ", "Cachoeiras de Macacu", "3300803"], + ["RJ", "Cambuci", "3300902"], + ["RJ", "Campos dos Goytacazes", "3301009"], + ["RJ", "Cantagalo", "3301108"], + ["RJ", "Carapebus", "3300936"], + ["RJ", "Cardoso Moreira", "3301157"], + ["RJ", "Carmo", "3301207"], + ["RJ", "Casimiro de Abreu", "3301306"], + ["RJ", "Comendador Levy Gasparian", "3300951"], + ["RJ", "Concei\u{e7}\u{e3}o de Macabu", "3301405"], + ["RJ", "Cordeiro", "3301504"], + ["RJ", "Duas Barras", "3301603"], + ["RJ", "Duque de Caxias", "3301702"], + ["RJ", "Engenheiro Paulo de Frontin", "3301801"], + ["RJ", "Guapimirim", "3301850"], + ["RJ", "Iguaba Grande", "3301876"], + ["RJ", "Itabora\u{ed}", "3301900"], + ["RJ", "Itagua\u{ed}", "3302007"], + ["RJ", "Italva", "3302056"], + ["RJ", "Itaocara", "3302106"], + ["RJ", "Itaperuna", "3302205"], + ["RJ", "Itatiaia", "3302254"], + ["RJ", "Japeri", "3302270"], + ["RJ", "Laje do Muria\u{e9}", "3302304"], + ["RJ", "Maca\u{e9}", "3302403"], + ["RJ", "Macuco", "3302452"], + ["RJ", "Mag\u{e9}", "3302502"], + ["RJ", "Mangaratiba", "3302601"], + ["RJ", "Maric\u{e1}", "3302700"], + ["RJ", "Mendes", "3302809"], + ["RJ", "Mesquita", "3302858"], + ["RJ", "Miguel Pereira", "3302908"], + ["RJ", "Miracema", "3303005"], + ["RJ", "Natividade", "3303104"], + ["RJ", "Nil\u{f3}polis", "3303203"], + ["RJ", "Niter\u{f3}i", "3303302"], + ["RJ", "Nova Friburgo", "3303401"], + ["RJ", "Nova Igua\u{e7}u", "3303500"], + ["RJ", "Paracambi", "3303609"], + ["RJ", "Para\u{ed}ba do Sul", "3303708"], + ["RJ", "Paraty", "3303807"], + ["RJ", "Paty do Alferes", "3303856"], + ["RJ", "Petr\u{f3}polis", "3303906"], + ["RJ", "Pinheiral", "3303955"], + ["RJ", "Pira\u{ed}", "3304003"], + ["RJ", "Porci\u{fa}ncula", "3304102"], + ["RJ", "Porto Real", "3304110"], + ["RJ", "Quatis", "3304128"], + ["RJ", "Queimados", "3304144"], + ["RJ", "Quissam\u{e3}", "3304151"], + ["RJ", "Resende", "3304201"], + ["RJ", "Rio Bonito", "3304300"], + ["RJ", "Rio Claro", "3304409"], + ["RJ", "Rio das Flores", "3304508"], + ["RJ", "Rio das Ostras", "3304524"], + ["RJ", "Rio de Janeiro", "3304557"], + ["RJ", "Santa Maria Madalena", "3304607"], + ["RJ", "Santo Ant\u{f4}nio de P\u{e1}dua", "3304706"], + ["RJ", "S\u{e3}o Fid\u{e9}lis", "3304805"], + ["RJ", "S\u{e3}o Francisco de Itabapoana", "3304755"], + ["RJ", "S\u{e3}o Gon\u{e7}alo", "3304904"], + ["RJ", "S\u{e3}o Jo\u{e3}o da Barra", "3305000"], + ["RJ", "S\u{e3}o Jo\u{e3}o de Meriti", "3305109"], + ["RJ", "S\u{e3}o Jos\u{e9} de Ub\u{e1}", "3305133"], + ["RJ", "S\u{e3}o Jos\u{e9} do Vale do Rio Preto", "3305158"], + ["RJ", "S\u{e3}o Pedro da Aldeia", "3305208"], + ["RJ", "S\u{e3}o Sebasti\u{e3}o do Alto", "3305307"], + ["RJ", "Sapucaia", "3305406"], + ["RJ", "Saquarema", "3305505"], + ["RJ", "Serop\u{e9}dica", "3305554"], + ["RJ", "Silva Jardim", "3305604"], + ["RJ", "Sumidouro", "3305703"], + ["RJ", "Tangu\u{e1}", "3305752"], + ["RJ", "Teres\u{f3}polis", "3305802"], + ["RJ", "Trajano de Moraes", "3305901"], + ["RJ", "Tr\u{ea}s Rios", "3306008"], + ["RJ", "Valen\u{e7}a", "3306107"], + ["RJ", "Varre-Sai", "3306156"], + ["RJ", "Vassouras", "3306206"], + ["RJ", "Volta Redonda", "3306305"], + ["RN", "Acari", "2400109"], + ["RN", "Afonso Bezerra", "2400307"], + ["RN", "\u{c1}gua Nova", "2400406"], + ["RN", "Alexandria", "2400505"], + ["RN", "Almino Afonso", "2400604"], + ["RN", "Alto do Rodrigues", "2400703"], + ["RN", "Angicos", "2400802"], + ["RN", "Ant\u{f4}nio Martins", "2400901"], + ["RN", "Apodi", "2401008"], + ["RN", "Areia Branca", "2401107"], + ["RN", "Arez", "2401206"], + ["RN", "Ass\u{fa}", "2400208"], + ["RN", "Ba\u{ed}a Formosa", "2401404"], + ["RN", "Bara\u{fa}na", "2401453"], + ["RN", "Barcelona", "2401503"], + ["RN", "Bento Fernandes", "2401602"], + ["RN", "Bod\u{f3}", "2401651"], + ["RN", "Bom Jesus", "2401701"], + ["RN", "Brejinho", "2401800"], + ["RN", "Cai\u{e7}ara do Norte", "2401859"], + ["RN", "Cai\u{e7}ara do Rio do Vento", "2401909"], + ["RN", "Caic\u{f3}", "2402006"], + ["RN", "Campo Grande", "2401305"], + ["RN", "Campo Redondo", "2402105"], + ["RN", "Canguaretama", "2402204"], + ["RN", "Cara\u{fa}bas", "2402303"], + ["RN", "Carna\u{fa}ba dos Dantas", "2402402"], + ["RN", "Carnaubais", "2402501"], + ["RN", "Cear\u{e1}-Mirim", "2402600"], + ["RN", "Cerro Cor\u{e1}", "2402709"], + ["RN", "Coronel Ezequiel", "2402808"], + ["RN", "Coronel Jo\u{e3}o Pessoa", "2402907"], + ["RN", "Cruzeta", "2403004"], + ["RN", "Currais Novos", "2403103"], + ["RN", "Doutor Severiano", "2403202"], + ["RN", "Encanto", "2403301"], + ["RN", "Equador", "2403400"], + ["RN", "Esp\u{ed}rito Santo", "2403509"], + ["RN", "Extremoz", "2403608"], + ["RN", "Felipe Guerra", "2403707"], + ["RN", "Fernando Pedroza", "2403756"], + ["RN", "Flor\u{e2}nia", "2403806"], + ["RN", "Francisco Dantas", "2403905"], + ["RN", "Frutuoso Gomes", "2404002"], + ["RN", "Galinhos", "2404101"], + ["RN", "Goianinha", "2404200"], + ["RN", "Governador Dix-Sept Rosado", "2404309"], + ["RN", "Grossos", "2404408"], + ["RN", "Guamar\u{e9}", "2404507"], + ["RN", "Ielmo Marinho", "2404606"], + ["RN", "Ipangua\u{e7}u", "2404705"], + ["RN", "Ipueira", "2404804"], + ["RN", "Itaj\u{e1}", "2404853"], + ["RN", "Ita\u{fa}", "2404903"], + ["RN", "Ja\u{e7}an\u{e3}", "2405009"], + ["RN", "Janda\u{ed}ra", "2405108"], + ["RN", "Jandu\u{ed}s", "2405207"], + ["RN", "Janu\u{e1}rio Cicco", "2405306"], + ["RN", "Japi", "2405405"], + ["RN", "Jardim de Angicos", "2405504"], + ["RN", "Jardim de Piranhas", "2405603"], + ["RN", "Jardim do Serid\u{f3}", "2405702"], + ["RN", "Jo\u{e3}o C\u{e2}mara", "2405801"], + ["RN", "Jo\u{e3}o Dias", "2405900"], + ["RN", "Jos\u{e9} da Penha", "2406007"], + ["RN", "Jucurutu", "2406106"], + ["RN", "Jundi\u{e1}", "2406155"], + ["RN", "Lagoa d'Anta", "2406205"], + ["RN", "Lagoa de Pedras", "2406304"], + ["RN", "Lagoa de Velhos", "2406403"], + ["RN", "Lagoa Nova", "2406502"], + ["RN", "Lagoa Salgada", "2406601"], + ["RN", "Lajes", "2406700"], + ["RN", "Lajes Pintadas", "2406809"], + ["RN", "Lucr\u{e9}cia", "2406908"], + ["RN", "Lu\u{ed}s Gomes", "2407005"], + ["RN", "Maca\u{ed}ba", "2407104"], + ["RN", "Macau", "2407203"], + ["RN", "Major Sales", "2407252"], + ["RN", "Marcelino Vieira", "2407302"], + ["RN", "Martins", "2407401"], + ["RN", "Maxaranguape", "2407500"], + ["RN", "Messias Targino", "2407609"], + ["RN", "Montanhas", "2407708"], + ["RN", "Monte Alegre", "2407807"], + ["RN", "Monte das Gameleiras", "2407906"], + ["RN", "Mossor\u{f3}", "2408003"], + ["RN", "Natal", "2408102"], + ["RN", "N\u{ed}sia Floresta", "2408201"], + ["RN", "Nova Cruz", "2408300"], + ["RN", "Olho d'\u{c1}gua do Borges", "2408409"], + ["RN", "Ouro Branco", "2408508"], + ["RN", "Paran\u{e1}", "2408607"], + ["RN", "Para\u{fa}", "2408706"], + ["RN", "Parazinho", "2408805"], + ["RN", "Parelhas", "2408904"], + ["RN", "Parnamirim", "2403251"], + ["RN", "Passa e Fica", "2409100"], + ["RN", "Passagem", "2409209"], + ["RN", "Patu", "2409308"], + ["RN", "Pau dos Ferros", "2409407"], + ["RN", "Pedra Grande", "2409506"], + ["RN", "Pedra Preta", "2409605"], + ["RN", "Pedro Avelino", "2409704"], + ["RN", "Pedro Velho", "2409803"], + ["RN", "Pend\u{ea}ncias", "2409902"], + ["RN", "Pil\u{f5}es", "2410009"], + ["RN", "Po\u{e7}o Branco", "2410108"], + ["RN", "Portalegre", "2410207"], + ["RN", "Porto do Mangue", "2410256"], + ["RN", "Pureza", "2410405"], + ["RN", "Rafael Fernandes", "2410504"], + ["RN", "Rafael Godeiro", "2410603"], + ["RN", "Riacho da Cruz", "2410702"], + ["RN", "Riacho de Santana", "2410801"], + ["RN", "Riachuelo", "2410900"], + ["RN", "Rio do Fogo", "2408953"], + ["RN", "Rodolfo Fernandes", "2411007"], + ["RN", "Ruy Barbosa", "2411106"], + ["RN", "Santa Cruz", "2411205"], + ["RN", "Santa Maria", "2409332"], + ["RN", "Santana do Matos", "2411403"], + ["RN", "Santana do Serid\u{f3}", "2411429"], + ["RN", "Santo Ant\u{f4}nio", "2411502"], + ["RN", "S\u{e3}o Bento do Norte", "2411601"], + ["RN", "S\u{e3}o Bento do Trair\u{ed}", "2411700"], + ["RN", "S\u{e3}o Fernando", "2411809"], + ["RN", "S\u{e3}o Francisco do Oeste", "2411908"], + ["RN", "S\u{e3}o Gon\u{e7}alo do Amarante", "2412005"], + ["RN", "S\u{e3}o Jo\u{e3}o do Sabugi", "2412104"], + ["RN", "S\u{e3}o Jos\u{e9} de Mipibu", "2412203"], + ["RN", "S\u{e3}o Jos\u{e9} do Campestre", "2412302"], + ["RN", "S\u{e3}o Jos\u{e9} do Serid\u{f3}", "2412401"], + ["RN", "S\u{e3}o Miguel", "2412500"], + ["RN", "S\u{e3}o Miguel do Gostoso", "2412559"], + ["RN", "S\u{e3}o Paulo do Potengi", "2412609"], + ["RN", "S\u{e3}o Pedro", "2412708"], + ["RN", "S\u{e3}o Rafael", "2412807"], + ["RN", "S\u{e3}o Tom\u{e9}", "2412906"], + ["RN", "S\u{e3}o Vicente", "2413003"], + ["RN", "Senador El\u{f3}i de Souza", "2413102"], + ["RN", "Senador Georgino Avelino", "2413201"], + ["RN", "Serra Caiada", "2410306"], + ["RN", "Serra de S\u{e3}o Bento", "2413300"], + ["RN", "Serra do Mel", "2413359"], + ["RN", "Serra Negra do Norte", "2413409"], + ["RN", "Serrinha", "2413508"], + ["RN", "Serrinha dos Pintos", "2413557"], + ["RN", "Severiano Melo", "2413607"], + ["RN", "S\u{ed}tio Novo", "2413706"], + ["RN", "Taboleiro Grande", "2413805"], + ["RN", "Taipu", "2413904"], + ["RN", "Tangar\u{e1}", "2414001"], + ["RN", "Tenente Ananias", "2414100"], + ["RN", "Tenente Laurentino Cruz", "2414159"], + ["RN", "Tibau", "2411056"], + ["RN", "Tibau do Sul", "2414209"], + ["RN", "Timba\u{fa}ba dos Batistas", "2414308"], + ["RN", "Touros", "2414407"], + ["RN", "Triunfo Potiguar", "2414456"], + ["RN", "Umarizal", "2414506"], + ["RN", "Upanema", "2414605"], + ["RN", "V\u{e1}rzea", "2414704"], + ["RN", "Venha-Ver", "2414753"], + ["RN", "Vera Cruz", "2414803"], + ["RN", "Vi\u{e7}osa", "2414902"], + ["RN", "Vila Flor", "2415008"], + ["RS", "Acegu\u{e1}", "4300034"], + ["RS", "\u{c1}gua Santa", "4300059"], + ["RS", "Agudo", "4300109"], + ["RS", "Ajuricaba", "4300208"], + ["RS", "Alecrim", "4300307"], + ["RS", "Alegrete", "4300406"], + ["RS", "Alegria", "4300455"], + ["RS", "Almirante Tamandar\u{e9} do Sul", "4300471"], + ["RS", "Alpestre", "4300505"], + ["RS", "Alto Alegre", "4300554"], + ["RS", "Alto Feliz", "4300570"], + ["RS", "Alvorada", "4300604"], + ["RS", "Amaral Ferrador", "4300638"], + ["RS", "Ametista do Sul", "4300646"], + ["RS", "Andr\u{e9} da Rocha", "4300661"], + ["RS", "Anta Gorda", "4300703"], + ["RS", "Ant\u{f4}nio Prado", "4300802"], + ["RS", "Arambar\u{e9}", "4300851"], + ["RS", "Araric\u{e1}", "4300877"], + ["RS", "Aratiba", "4300901"], + ["RS", "Arroio do Meio", "4301008"], + ["RS", "Arroio do Padre", "4301073"], + ["RS", "Arroio do Sal", "4301057"], + ["RS", "Arroio do Tigre", "4301206"], + ["RS", "Arroio dos Ratos", "4301107"], + ["RS", "Arroio Grande", "4301305"], + ["RS", "Arvorezinha", "4301404"], + ["RS", "Augusto Pestana", "4301503"], + ["RS", "\u{c1}urea", "4301552"], + ["RS", "Bag\u{e9}", "4301602"], + ["RS", "Balne\u{e1}rio Pinhal", "4301636"], + ["RS", "Bar\u{e3}o", "4301651"], + ["RS", "Bar\u{e3}o de Cotegipe", "4301701"], + ["RS", "Bar\u{e3}o do Triunfo", "4301750"], + ["RS", "Barra do Guarita", "4301859"], + ["RS", "Barra do Quara\u{ed}", "4301875"], + ["RS", "Barra do Ribeiro", "4301909"], + ["RS", "Barra do Rio Azul", "4301925"], + ["RS", "Barra Funda", "4301958"], + ["RS", "Barrac\u{e3}o", "4301800"], + ["RS", "Barros Cassal", "4302006"], + ["RS", "Benjamin Constant do Sul", "4302055"], + ["RS", "Bento Gon\u{e7}alves", "4302105"], + ["RS", "Boa Vista das Miss\u{f5}es", "4302154"], + ["RS", "Boa Vista do Buric\u{e1}", "4302204"], + ["RS", "Boa Vista do Cadeado", "4302220"], + ["RS", "Boa Vista do Incra", "4302238"], + ["RS", "Boa Vista do Sul", "4302253"], + ["RS", "Bom Jesus", "4302303"], + ["RS", "Bom Princ\u{ed}pio", "4302352"], + ["RS", "Bom Progresso", "4302378"], + ["RS", "Bom Retiro do Sul", "4302402"], + ["RS", "Boqueir\u{e3}o do Le\u{e3}o", "4302451"], + ["RS", "Bossoroca", "4302501"], + ["RS", "Bozano", "4302584"], + ["RS", "Braga", "4302600"], + ["RS", "Brochier", "4302659"], + ["RS", "Buti\u{e1}", "4302709"], + ["RS", "Ca\u{e7}apava do Sul", "4302808"], + ["RS", "Cacequi", "4302907"], + ["RS", "Cachoeira do Sul", "4303004"], + ["RS", "Cachoeirinha", "4303103"], + ["RS", "Cacique Doble", "4303202"], + ["RS", "Caibat\u{e9}", "4303301"], + ["RS", "Cai\u{e7}ara", "4303400"], + ["RS", "Camaqu\u{e3}", "4303509"], + ["RS", "Camargo", "4303558"], + ["RS", "Cambar\u{e1} do Sul", "4303608"], + ["RS", "Campestre da Serra", "4303673"], + ["RS", "Campina das Miss\u{f5}es", "4303707"], + ["RS", "Campinas do Sul", "4303806"], + ["RS", "Campo Bom", "4303905"], + ["RS", "Campo Novo", "4304002"], + ["RS", "Campos Borges", "4304101"], + ["RS", "Candel\u{e1}ria", "4304200"], + ["RS", "C\u{e2}ndido God\u{f3}i", "4304309"], + ["RS", "Candiota", "4304358"], + ["RS", "Canela", "4304408"], + ["RS", "Cangu\u{e7}u", "4304507"], + ["RS", "Canoas", "4304606"], + ["RS", "Canudos do Vale", "4304614"], + ["RS", "Cap\u{e3}o Bonito do Sul", "4304622"], + ["RS", "Cap\u{e3}o da Canoa", "4304630"], + ["RS", "Cap\u{e3}o do Cip\u{f3}", "4304655"], + ["RS", "Cap\u{e3}o do Le\u{e3}o", "4304663"], + ["RS", "Capela de Santana", "4304689"], + ["RS", "Capit\u{e3}o", "4304697"], + ["RS", "Capivari do Sul", "4304671"], + ["RS", "Cara\u{e1}", "4304713"], + ["RS", "Carazinho", "4304705"], + ["RS", "Carlos Barbosa", "4304804"], + ["RS", "Carlos Gomes", "4304853"], + ["RS", "Casca", "4304903"], + ["RS", "Caseiros", "4304952"], + ["RS", "Catu\u{ed}pe", "4305009"], + ["RS", "Caxias do Sul", "4305108"], + ["RS", "Centen\u{e1}rio", "4305116"], + ["RS", "Cerrito", "4305124"], + ["RS", "Cerro Branco", "4305132"], + ["RS", "Cerro Grande", "4305157"], + ["RS", "Cerro Grande do Sul", "4305173"], + ["RS", "Cerro Largo", "4305207"], + ["RS", "Chapada", "4305306"], + ["RS", "Charqueadas", "4305355"], + ["RS", "Charrua", "4305371"], + ["RS", "Chiapetta", "4305405"], + ["RS", "Chu\u{ed}", "4305439"], + ["RS", "Chuvisca", "4305447"], + ["RS", "Cidreira", "4305454"], + ["RS", "Cir\u{ed}aco", "4305504"], + ["RS", "Colinas", "4305587"], + ["RS", "Colorado", "4305603"], + ["RS", "Condor", "4305702"], + ["RS", "Constantina", "4305801"], + ["RS", "Coqueiro Baixo", "4305835"], + ["RS", "Coqueiros do Sul", "4305850"], + ["RS", "Coronel Barros", "4305871"], + ["RS", "Coronel Bicaco", "4305900"], + ["RS", "Coronel Pilar", "4305934"], + ["RS", "Cotipor\u{e3}", "4305959"], + ["RS", "Coxilha", "4305975"], + ["RS", "Crissiumal", "4306007"], + ["RS", "Cristal", "4306056"], + ["RS", "Cristal do Sul", "4306072"], + ["RS", "Cruz Alta", "4306106"], + ["RS", "Cruzaltense", "4306130"], + ["RS", "Cruzeiro do Sul", "4306205"], + ["RS", "David Canabarro", "4306304"], + ["RS", "Derrubadas", "4306320"], + ["RS", "Dezesseis de Novembro", "4306353"], + ["RS", "Dilermando de Aguiar", "4306379"], + ["RS", "Dois Irm\u{e3}os", "4306403"], + ["RS", "Dois Irm\u{e3}os das Miss\u{f5}es", "4306429"], + ["RS", "Dois Lajeados", "4306452"], + ["RS", "Dom Feliciano", "4306502"], + ["RS", "Dom Pedrito", "4306601"], + ["RS", "Dom Pedro de Alc\u{e2}ntara", "4306551"], + ["RS", "Dona Francisca", "4306700"], + ["RS", "Doutor Maur\u{ed}cio Cardoso", "4306734"], + ["RS", "Doutor Ricardo", "4306759"], + ["RS", "Eldorado do Sul", "4306767"], + ["RS", "Encantado", "4306809"], + ["RS", "Encruzilhada do Sul", "4306908"], + ["RS", "Engenho Velho", "4306924"], + ["RS", "Entre Rios do Sul", "4306957"], + ["RS", "Entre-Iju\u{ed}s", "4306932"], + ["RS", "Erebango", "4306973"], + ["RS", "Erechim", "4307005"], + ["RS", "Ernestina", "4307054"], + ["RS", "Erval Grande", "4307203"], + ["RS", "Erval Seco", "4307302"], + ["RS", "Esmeralda", "4307401"], + ["RS", "Esperan\u{e7}a do Sul", "4307450"], + ["RS", "Espumoso", "4307500"], + ["RS", "Esta\u{e7}\u{e3}o", "4307559"], + ["RS", "Est\u{e2}ncia Velha", "4307609"], + ["RS", "Esteio", "4307708"], + ["RS", "Estrela", "4307807"], + ["RS", "Estrela Velha", "4307815"], + ["RS", "Eug\u{ea}nio de Castro", "4307831"], + ["RS", "Fagundes Varela", "4307864"], + ["RS", "Farroupilha", "4307906"], + ["RS", "Faxinal do Soturno", "4308003"], + ["RS", "Faxinalzinho", "4308052"], + ["RS", "Fazenda Vilanova", "4308078"], + ["RS", "Feliz", "4308102"], + ["RS", "Flores da Cunha", "4308201"], + ["RS", "Floriano Peixoto", "4308250"], + ["RS", "Fontoura Xavier", "4308300"], + ["RS", "Formigueiro", "4308409"], + ["RS", "Forquetinha", "4308433"], + ["RS", "Fortaleza dos Valos", "4308458"], + ["RS", "Frederico Westphalen", "4308508"], + ["RS", "Garibaldi", "4308607"], + ["RS", "Garruchos", "4308656"], + ["RS", "Gaurama", "4308706"], + ["RS", "General C\u{e2}mara", "4308805"], + ["RS", "Gentil", "4308854"], + ["RS", "Get\u{fa}lio Vargas", "4308904"], + ["RS", "Giru\u{e1}", "4309001"], + ["RS", "Glorinha", "4309050"], + ["RS", "Gramado", "4309100"], + ["RS", "Gramado dos Loureiros", "4309126"], + ["RS", "Gramado Xavier", "4309159"], + ["RS", "Gravata\u{ed}", "4309209"], + ["RS", "Guabiju", "4309258"], + ["RS", "Gua\u{ed}ba", "4309308"], + ["RS", "Guapor\u{e9}", "4309407"], + ["RS", "Guarani das Miss\u{f5}es", "4309506"], + ["RS", "Harmonia", "4309555"], + ["RS", "Herval", "4307104"], + ["RS", "Herveiras", "4309571"], + ["RS", "Horizontina", "4309605"], + ["RS", "Hulha Negra", "4309654"], + ["RS", "Humait\u{e1}", "4309704"], + ["RS", "Ibarama", "4309753"], + ["RS", "Ibia\u{e7}\u{e1}", "4309803"], + ["RS", "Ibiraiaras", "4309902"], + ["RS", "Ibirapuit\u{e3}", "4309951"], + ["RS", "Ibirub\u{e1}", "4310009"], + ["RS", "Igrejinha", "4310108"], + ["RS", "Iju\u{ed}", "4310207"], + ["RS", "Il\u{f3}polis", "4310306"], + ["RS", "Imb\u{e9}", "4310330"], + ["RS", "Imigrante", "4310363"], + ["RS", "Independ\u{ea}ncia", "4310405"], + ["RS", "Inhacor\u{e1}", "4310413"], + ["RS", "Ip\u{ea}", "4310439"], + ["RS", "Ipiranga do Sul", "4310462"], + ["RS", "Ira\u{ed}", "4310504"], + ["RS", "Itaara", "4310538"], + ["RS", "Itacurubi", "4310553"], + ["RS", "Itapuca", "4310579"], + ["RS", "Itaqui", "4310603"], + ["RS", "Itati", "4310652"], + ["RS", "Itatiba do Sul", "4310702"], + ["RS", "Ivor\u{e1}", "4310751"], + ["RS", "Ivoti", "4310801"], + ["RS", "Jaboticaba", "4310850"], + ["RS", "Jacuizinho", "4310876"], + ["RS", "Jacutinga", "4310900"], + ["RS", "Jaguar\u{e3}o", "4311007"], + ["RS", "Jaguari", "4311106"], + ["RS", "Jaquirana", "4311122"], + ["RS", "Jari", "4311130"], + ["RS", "J\u{f3}ia", "4311155"], + ["RS", "J\u{fa}lio de Castilhos", "4311205"], + ["RS", "Lagoa Bonita do Sul", "4311239"], + ["RS", "Lagoa dos Tr\u{ea}s Cantos", "4311270"], + ["RS", "Lagoa Vermelha", "4311304"], + ["RS", "Lago\u{e3}o", "4311254"], + ["RS", "Lajeado", "4311403"], + ["RS", "Lajeado do Bugre", "4311429"], + ["RS", "Lavras do Sul", "4311502"], + ["RS", "Liberato Salzano", "4311601"], + ["RS", "Lindolfo Collor", "4311627"], + ["RS", "Linha Nova", "4311643"], + ["RS", "Ma\u{e7}ambar\u{e1}", "4311718"], + ["RS", "Machadinho", "4311700"], + ["RS", "Mampituba", "4311734"], + ["RS", "Manoel Viana", "4311759"], + ["RS", "Maquin\u{e9}", "4311775"], + ["RS", "Marat\u{e1}", "4311791"], + ["RS", "Marau", "4311809"], + ["RS", "Marcelino Ramos", "4311908"], + ["RS", "Mariana Pimentel", "4311981"], + ["RS", "Mariano Moro", "4312005"], + ["RS", "Marques de Souza", "4312054"], + ["RS", "Mata", "4312104"], + ["RS", "Mato Castelhano", "4312138"], + ["RS", "Mato Leit\u{e3}o", "4312153"], + ["RS", "Mato Queimado", "4312179"], + ["RS", "Maximiliano de Almeida", "4312203"], + ["RS", "Minas do Le\u{e3}o", "4312252"], + ["RS", "Miragua\u{ed}", "4312302"], + ["RS", "Montauri", "4312351"], + ["RS", "Monte Alegre dos Campos", "4312377"], + ["RS", "Monte Belo do Sul", "4312385"], + ["RS", "Montenegro", "4312401"], + ["RS", "Morma\u{e7}o", "4312427"], + ["RS", "Morrinhos do Sul", "4312443"], + ["RS", "Morro Redondo", "4312450"], + ["RS", "Morro Reuter", "4312476"], + ["RS", "Mostardas", "4312500"], + ["RS", "Mu\u{e7}um", "4312609"], + ["RS", "Muitos Cap\u{f5}es", "4312617"], + ["RS", "Muliterno", "4312625"], + ["RS", "N\u{e3}o-Me-Toque", "4312658"], + ["RS", "Nicolau Vergueiro", "4312674"], + ["RS", "Nonoai", "4312708"], + ["RS", "Nova Alvorada", "4312757"], + ["RS", "Nova Ara\u{e7}\u{e1}", "4312807"], + ["RS", "Nova Bassano", "4312906"], + ["RS", "Nova Boa Vista", "4312955"], + ["RS", "Nova Br\u{e9}scia", "4313003"], + ["RS", "Nova Candel\u{e1}ria", "4313011"], + ["RS", "Nova Esperan\u{e7}a do Sul", "4313037"], + ["RS", "Nova Hartz", "4313060"], + ["RS", "Nova P\u{e1}dua", "4313086"], + ["RS", "Nova Palma", "4313102"], + ["RS", "Nova Petr\u{f3}polis", "4313201"], + ["RS", "Nova Prata", "4313300"], + ["RS", "Nova Ramada", "4313334"], + ["RS", "Nova Roma do Sul", "4313359"], + ["RS", "Nova Santa Rita", "4313375"], + ["RS", "Novo Barreiro", "4313490"], + ["RS", "Novo Cabrais", "4313391"], + ["RS", "Novo Hamburgo", "4313409"], + ["RS", "Novo Machado", "4313425"], + ["RS", "Novo Tiradentes", "4313441"], + ["RS", "Novo Xingu", "4313466"], + ["RS", "Os\u{f3}rio", "4313508"], + ["RS", "Paim Filho", "4313607"], + ["RS", "Palmares do Sul", "4313656"], + ["RS", "Palmeira das Miss\u{f5}es", "4313706"], + ["RS", "Palmitinho", "4313805"], + ["RS", "Panambi", "4313904"], + ["RS", "Pantano Grande", "4313953"], + ["RS", "Para\u{ed}", "4314001"], + ["RS", "Para\u{ed}so do Sul", "4314027"], + ["RS", "Pareci Novo", "4314035"], + ["RS", "Parob\u{e9}", "4314050"], + ["RS", "Passa Sete", "4314068"], + ["RS", "Passo do Sobrado", "4314076"], + ["RS", "Passo Fundo", "4314100"], + ["RS", "Paulo Bento", "4314134"], + ["RS", "Paverama", "4314159"], + ["RS", "Pedras Altas", "4314175"], + ["RS", "Pedro Os\u{f3}rio", "4314209"], + ["RS", "Peju\u{e7}ara", "4314308"], + ["RS", "Pelotas", "4314407"], + ["RS", "Picada Caf\u{e9}", "4314423"], + ["RS", "Pinhal", "4314456"], + ["RS", "Pinhal da Serra", "4314464"], + ["RS", "Pinhal Grande", "4314472"], + ["RS", "Pinheirinho do Vale", "4314498"], + ["RS", "Pinheiro Machado", "4314506"], + ["RS", "Pinto Bandeira", "4314548"], + ["RS", "Pirap\u{f3}", "4314555"], + ["RS", "Piratini", "4314605"], + ["RS", "Planalto", "4314704"], + ["RS", "Po\u{e7}o das Antas", "4314753"], + ["RS", "Pont\u{e3}o", "4314779"], + ["RS", "Ponte Preta", "4314787"], + ["RS", "Port\u{e3}o", "4314803"], + ["RS", "Porto Alegre", "4314902"], + ["RS", "Porto Lucena", "4315008"], + ["RS", "Porto Mau\u{e1}", "4315057"], + ["RS", "Porto Vera Cruz", "4315073"], + ["RS", "Porto Xavier", "4315107"], + ["RS", "Pouso Novo", "4315131"], + ["RS", "Presidente Lucena", "4315149"], + ["RS", "Progresso", "4315156"], + ["RS", "Prot\u{e1}sio Alves", "4315172"], + ["RS", "Putinga", "4315206"], + ["RS", "Quara\u{ed}", "4315305"], + ["RS", "Quatro Irm\u{e3}os", "4315313"], + ["RS", "Quevedos", "4315321"], + ["RS", "Quinze de Novembro", "4315354"], + ["RS", "Redentora", "4315404"], + ["RS", "Relvado", "4315453"], + ["RS", "Restinga S\u{ea}ca", "4315503"], + ["RS", "Rio dos \u{cd}ndios", "4315552"], + ["RS", "Rio Grande", "4315602"], + ["RS", "Rio Pardo", "4315701"], + ["RS", "Riozinho", "4315750"], + ["RS", "Roca Sales", "4315800"], + ["RS", "Rodeio Bonito", "4315909"], + ["RS", "Rolador", "4315958"], + ["RS", "Rolante", "4316006"], + ["RS", "Ronda Alta", "4316105"], + ["RS", "Rondinha", "4316204"], + ["RS", "Roque Gonzales", "4316303"], + ["RS", "Ros\u{e1}rio do Sul", "4316402"], + ["RS", "Sagrada Fam\u{ed}lia", "4316428"], + ["RS", "Saldanha Marinho", "4316436"], + ["RS", "Salto do Jacu\u{ed}", "4316451"], + ["RS", "Salvador das Miss\u{f5}es", "4316477"], + ["RS", "Salvador do Sul", "4316501"], + ["RS", "Sananduva", "4316600"], + ["RS", "Sant'Ana do Livramento", "4317103"], + ["RS", "Santa B\u{e1}rbara do Sul", "4316709"], + ["RS", "Santa Cec\u{ed}lia do Sul", "4316733"], + ["RS", "Santa Clara do Sul", "4316758"], + ["RS", "Santa Cruz do Sul", "4316808"], + ["RS", "Santa Margarida do Sul", "4316972"], + ["RS", "Santa Maria", "4316907"], + ["RS", "Santa Maria do Herval", "4316956"], + ["RS", "Santa Rosa", "4317202"], + ["RS", "Santa Tereza", "4317251"], + ["RS", "Santa Vit\u{f3}ria do Palmar", "4317301"], + ["RS", "Santana da Boa Vista", "4317004"], + ["RS", "Santiago", "4317400"], + ["RS", "Santo \u{c2}ngelo", "4317509"], + ["RS", "Santo Ant\u{f4}nio da Patrulha", "4317608"], + ["RS", "Santo Ant\u{f4}nio das Miss\u{f5}es", "4317707"], + ["RS", "Santo Ant\u{f4}nio do Palma", "4317558"], + ["RS", "Santo Ant\u{f4}nio do Planalto", "4317756"], + ["RS", "Santo Augusto", "4317806"], + ["RS", "Santo Cristo", "4317905"], + ["RS", "Santo Expedito do Sul", "4317954"], + ["RS", "S\u{e3}o Borja", "4318002"], + ["RS", "S\u{e3}o Domingos do Sul", "4318051"], + ["RS", "S\u{e3}o Francisco de Assis", "4318101"], + ["RS", "S\u{e3}o Francisco de Paula", "4318200"], + ["RS", "S\u{e3}o Gabriel", "4318309"], + ["RS", "S\u{e3}o Jer\u{f4}nimo", "4318408"], + ["RS", "S\u{e3}o Jo\u{e3}o da Urtiga", "4318424"], + ["RS", "S\u{e3}o Jo\u{e3}o do Pol\u{ea}sine", "4318432"], + ["RS", "S\u{e3}o Jorge", "4318440"], + ["RS", "S\u{e3}o Jos\u{e9} das Miss\u{f5}es", "4318457"], + ["RS", "S\u{e3}o Jos\u{e9} do Herval", "4318465"], + ["RS", "S\u{e3}o Jos\u{e9} do Hort\u{ea}ncio", "4318481"], + ["RS", "S\u{e3}o Jos\u{e9} do Inhacor\u{e1}", "4318499"], + ["RS", "S\u{e3}o Jos\u{e9} do Norte", "4318507"], + ["RS", "S\u{e3}o Jos\u{e9} do Ouro", "4318606"], + ["RS", "S\u{e3}o Jos\u{e9} do Sul", "4318614"], + ["RS", "S\u{e3}o Jos\u{e9} dos Ausentes", "4318622"], + ["RS", "S\u{e3}o Leopoldo", "4318705"], + ["RS", "S\u{e3}o Louren\u{e7}o do Sul", "4318804"], + ["RS", "S\u{e3}o Luiz Gonzaga", "4318903"], + ["RS", "S\u{e3}o Marcos", "4319000"], + ["RS", "S\u{e3}o Martinho", "4319109"], + ["RS", "S\u{e3}o Martinho da Serra", "4319125"], + ["RS", "S\u{e3}o Miguel das Miss\u{f5}es", "4319158"], + ["RS", "S\u{e3}o Nicolau", "4319208"], + ["RS", "S\u{e3}o Paulo das Miss\u{f5}es", "4319307"], + ["RS", "S\u{e3}o Pedro da Serra", "4319356"], + ["RS", "S\u{e3}o Pedro das Miss\u{f5}es", "4319364"], + ["RS", "S\u{e3}o Pedro do Buti\u{e1}", "4319372"], + ["RS", "S\u{e3}o Pedro do Sul", "4319406"], + ["RS", "S\u{e3}o Sebasti\u{e3}o do Ca\u{ed}", "4319505"], + ["RS", "S\u{e3}o Sep\u{e9}", "4319604"], + ["RS", "S\u{e3}o Valentim", "4319703"], + ["RS", "S\u{e3}o Valentim do Sul", "4319711"], + ["RS", "S\u{e3}o Val\u{e9}rio do Sul", "4319737"], + ["RS", "S\u{e3}o Vendelino", "4319752"], + ["RS", "S\u{e3}o Vicente do Sul", "4319802"], + ["RS", "Sapiranga", "4319901"], + ["RS", "Sapucaia do Sul", "4320008"], + ["RS", "Sarandi", "4320107"], + ["RS", "Seberi", "4320206"], + ["RS", "Sede Nova", "4320230"], + ["RS", "Segredo", "4320263"], + ["RS", "Selbach", "4320305"], + ["RS", "Senador Salgado Filho", "4320321"], + ["RS", "Sentinela do Sul", "4320354"], + ["RS", "Serafina Corr\u{ea}a", "4320404"], + ["RS", "S\u{e9}rio", "4320453"], + ["RS", "Sert\u{e3}o", "4320503"], + ["RS", "Sert\u{e3}o Santana", "4320552"], + ["RS", "Sete de Setembro", "4320578"], + ["RS", "Severiano de Almeida", "4320602"], + ["RS", "Silveira Martins", "4320651"], + ["RS", "Sinimbu", "4320677"], + ["RS", "Sobradinho", "4320701"], + ["RS", "Soledade", "4320800"], + ["RS", "Taba\u{ed}", "4320859"], + ["RS", "Tapejara", "4320909"], + ["RS", "Tapera", "4321006"], + ["RS", "Tapes", "4321105"], + ["RS", "Taquara", "4321204"], + ["RS", "Taquari", "4321303"], + ["RS", "Taquaru\u{e7}u do Sul", "4321329"], + ["RS", "Tavares", "4321352"], + ["RS", "Tenente Portela", "4321402"], + ["RS", "Terra de Areia", "4321436"], + ["RS", "Teut\u{f4}nia", "4321451"], + ["RS", "Tio Hugo", "4321469"], + ["RS", "Tiradentes do Sul", "4321477"], + ["RS", "Toropi", "4321493"], + ["RS", "Torres", "4321501"], + ["RS", "Tramanda\u{ed}", "4321600"], + ["RS", "Travesseiro", "4321626"], + ["RS", "Tr\u{ea}s Arroios", "4321634"], + ["RS", "Tr\u{ea}s Cachoeiras", "4321667"], + ["RS", "Tr\u{ea}s Coroas", "4321709"], + ["RS", "Tr\u{ea}s de Maio", "4321808"], + ["RS", "Tr\u{ea}s Forquilhas", "4321832"], + ["RS", "Tr\u{ea}s Palmeiras", "4321857"], + ["RS", "Tr\u{ea}s Passos", "4321907"], + ["RS", "Trindade do Sul", "4321956"], + ["RS", "Triunfo", "4322004"], + ["RS", "Tucunduva", "4322103"], + ["RS", "Tunas", "4322152"], + ["RS", "Tupanci do Sul", "4322186"], + ["RS", "Tupanciret\u{e3}", "4322202"], + ["RS", "Tupandi", "4322251"], + ["RS", "Tuparendi", "4322301"], + ["RS", "Turu\u{e7}u", "4322327"], + ["RS", "Ubiretama", "4322343"], + ["RS", "Uni\u{e3}o da Serra", "4322350"], + ["RS", "Unistalda", "4322376"], + ["RS", "Uruguaiana", "4322400"], + ["RS", "Vacaria", "4322509"], + ["RS", "Vale do Sol", "4322533"], + ["RS", "Vale Real", "4322541"], + ["RS", "Vale Verde", "4322525"], + ["RS", "Vanini", "4322558"], + ["RS", "Ven\u{e2}ncio Aires", "4322608"], + ["RS", "Vera Cruz", "4322707"], + ["RS", "Veran\u{f3}polis", "4322806"], + ["RS", "Vespasiano Corr\u{ea}a", "4322855"], + ["RS", "Viadutos", "4322905"], + ["RS", "Viam\u{e3}o", "4323002"], + ["RS", "Vicente Dutra", "4323101"], + ["RS", "Victor Graeff", "4323200"], + ["RS", "Vila Flores", "4323309"], + ["RS", "Vila L\u{e2}ngaro", "4323358"], + ["RS", "Vila Maria", "4323408"], + ["RS", "Vila Nova do Sul", "4323457"], + ["RS", "Vista Alegre", "4323507"], + ["RS", "Vista Alegre do Prata", "4323606"], + ["RS", "Vista Ga\u{fa}cha", "4323705"], + ["RS", "Vit\u{f3}ria das Miss\u{f5}es", "4323754"], + ["RS", "Westf\u{e1}lia", "4323770"], + ["RS", "Xangri-l\u{e1}", "4323804"], + ["RO", "Alta Floresta D'Oeste", "1100015"], + ["RO", "Alto Alegre dos Parecis", "1100379"], + ["RO", "Alto Para\u{ed}so", "1100403"], + ["RO", "Alvorada D'Oeste", "1100346"], + ["RO", "Ariquemes", "1100023"], + ["RO", "Buritis", "1100452"], + ["RO", "Cabixi", "1100031"], + ["RO", "Cacaul\u{e2}ndia", "1100601"], + ["RO", "Cacoal", "1100049"], + ["RO", "Campo Novo de Rond\u{f4}nia", "1100700"], + ["RO", "Candeias do Jamari", "1100809"], + ["RO", "Castanheiras", "1100908"], + ["RO", "Cerejeiras", "1100056"], + ["RO", "Chupinguaia", "1100924"], + ["RO", "Colorado do Oeste", "1100064"], + ["RO", "Corumbiara", "1100072"], + ["RO", "Costa Marques", "1100080"], + ["RO", "Cujubim", "1100940"], + ["RO", "Espig\u{e3}o D'Oeste", "1100098"], + ["RO", "Governador Jorge Teixeira", "1101005"], + ["RO", "Guajar\u{e1}-Mirim", "1100106"], + ["RO", "Itapu\u{e3} do Oeste", "1101104"], + ["RO", "Jaru", "1100114"], + ["RO", "Ji-Paran\u{e1}", "1100122"], + ["RO", "Machadinho D'Oeste", "1100130"], + ["RO", "Ministro Andreazza", "1101203"], + ["RO", "Mirante da Serra", "1101302"], + ["RO", "Monte Negro", "1101401"], + ["RO", "Nova Brasil\u{e2}ndia D'Oeste", "1100148"], + ["RO", "Nova Mamor\u{e9}", "1100338"], + ["RO", "Nova Uni\u{e3}o", "1101435"], + ["RO", "Novo Horizonte do Oeste", "1100502"], + ["RO", "Ouro Preto do Oeste", "1100155"], + ["RO", "Parecis", "1101450"], + ["RO", "Pimenta Bueno", "1100189"], + ["RO", "Pimenteiras do Oeste", "1101468"], + ["RO", "Porto Velho", "1100205"], + ["RO", "Presidente M\u{e9}dici", "1100254"], + ["RO", "Primavera de Rond\u{f4}nia", "1101476"], + ["RO", "Rio Crespo", "1100262"], + ["RO", "Rolim de Moura", "1100288"], + ["RO", "Santa Luzia D'Oeste", "1100296"], + ["RO", "S\u{e3}o Felipe D'Oeste", "1101484"], + ["RO", "S\u{e3}o Francisco do Guapor\u{e9}", "1101492"], + ["RO", "S\u{e3}o Miguel do Guapor\u{e9}", "1100320"], + ["RO", "Seringueiras", "1101500"], + ["RO", "Teixeir\u{f3}polis", "1101559"], + ["RO", "Theobroma", "1101609"], + ["RO", "Urup\u{e1}", "1101708"], + ["RO", "Vale do Anari", "1101757"], + ["RO", "Vale do Para\u{ed}so", "1101807"], + ["RO", "Vilhena", "1100304"], + ["RR", "Alto Alegre", "1400050"], + ["RR", "Amajari", "1400027"], + ["RR", "Boa Vista", "1400100"], + ["RR", "Bonfim", "1400159"], + ["RR", "Cant\u{e1}", "1400175"], + ["RR", "Caracara\u{ed}", "1400209"], + ["RR", "Caroebe", "1400233"], + ["RR", "Iracema", "1400282"], + ["RR", "Mucaja\u{ed}", "1400308"], + ["RR", "Normandia", "1400407"], + ["RR", "Pacaraima", "1400456"], + ["RR", "Rorain\u{f3}polis", "1400472"], + ["RR", "S\u{e3}o Jo\u{e3}o da Baliza", "1400506"], + ["RR", "S\u{e3}o Luiz do Anau\u{e1}", "1400605"], + ["RR", "Uiramut\u{e3}", "1400704"], + ["SC", "Abdon Batista", "4200051"], + ["SC", "Abelardo Luz", "4200101"], + ["SC", "Agrol\u{e2}ndia", "4200200"], + ["SC", "Agron\u{f4}mica", "4200309"], + ["SC", "\u{c1}gua Doce", "4200408"], + ["SC", "\u{c1}guas de Chapec\u{f3}", "4200507"], + ["SC", "\u{c1}guas Frias", "4200556"], + ["SC", "\u{c1}guas Mornas", "4200606"], + ["SC", "Alfredo Wagner", "4200705"], + ["SC", "Alto Bela Vista", "4200754"], + ["SC", "Anchieta", "4200804"], + ["SC", "Angelina", "4200903"], + ["SC", "Anita Garibaldi", "4201000"], + ["SC", "Anit\u{e1}polis", "4201109"], + ["SC", "Ant\u{f4}nio Carlos", "4201208"], + ["SC", "Api\u{fa}na", "4201257"], + ["SC", "Arabut\u{e3}", "4201273"], + ["SC", "Araquari", "4201307"], + ["SC", "Ararangu\u{e1}", "4201406"], + ["SC", "Armaz\u{e9}m", "4201505"], + ["SC", "Arroio Trinta", "4201604"], + ["SC", "Arvoredo", "4201653"], + ["SC", "Ascurra", "4201703"], + ["SC", "Atalanta", "4201802"], + ["SC", "Aurora", "4201901"], + ["SC", "Balne\u{e1}rio Arroio do Silva", "4201950"], + ["SC", "Balne\u{e1}rio Barra do Sul", "4202057"], + ["SC", "Balne\u{e1}rio Cambori\u{fa}", "4202008"], + ["SC", "Balne\u{e1}rio Gaivota", "4202073"], + ["SC", "Balne\u{e1}rio Pi\u{e7}arras", "4212809"], + ["SC", "Balne\u{e1}rio Rinc\u{e3}o", "4220000"], + ["SC", "Bandeirante", "4202081"], + ["SC", "Barra Bonita", "4202099"], + ["SC", "Barra Velha", "4202107"], + ["SC", "Bela Vista do Toldo", "4202131"], + ["SC", "Belmonte", "4202156"], + ["SC", "Benedito Novo", "4202206"], + ["SC", "Bigua\u{e7}u", "4202305"], + ["SC", "Blumenau", "4202404"], + ["SC", "Bocaina do Sul", "4202438"], + ["SC", "Bom Jardim da Serra", "4202503"], + ["SC", "Bom Jesus", "4202537"], + ["SC", "Bom Jesus do Oeste", "4202578"], + ["SC", "Bom Retiro", "4202602"], + ["SC", "Bombinhas", "4202453"], + ["SC", "Botuver\u{e1}", "4202701"], + ["SC", "Bra\u{e7}o do Norte", "4202800"], + ["SC", "Bra\u{e7}o do Trombudo", "4202859"], + ["SC", "Brun\u{f3}polis", "4202875"], + ["SC", "Brusque", "4202909"], + ["SC", "Ca\u{e7}ador", "4203006"], + ["SC", "Caibi", "4203105"], + ["SC", "Calmon", "4203154"], + ["SC", "Cambori\u{fa}", "4203204"], + ["SC", "Campo Alegre", "4203303"], + ["SC", "Campo Belo do Sul", "4203402"], + ["SC", "Campo Er\u{ea}", "4203501"], + ["SC", "Campos Novos", "4203600"], + ["SC", "Canelinha", "4203709"], + ["SC", "Canoinhas", "4203808"], + ["SC", "Cap\u{e3}o Alto", "4203253"], + ["SC", "Capinzal", "4203907"], + ["SC", "Capivari de Baixo", "4203956"], + ["SC", "Catanduvas", "4204004"], + ["SC", "Caxambu do Sul", "4204103"], + ["SC", "Celso Ramos", "4204152"], + ["SC", "Cerro Negro", "4204178"], + ["SC", "Chapad\u{e3}o do Lageado", "4204194"], + ["SC", "Chapec\u{f3}", "4204202"], + ["SC", "Cocal do Sul", "4204251"], + ["SC", "Conc\u{f3}rdia", "4204301"], + ["SC", "Cordilheira Alta", "4204350"], + ["SC", "Coronel Freitas", "4204400"], + ["SC", "Coronel Martins", "4204459"], + ["SC", "Correia Pinto", "4204558"], + ["SC", "Corup\u{e1}", "4204509"], + ["SC", "Crici\u{fa}ma", "4204608"], + ["SC", "Cunha Por\u{e3}", "4204707"], + ["SC", "Cunhata\u{ed}", "4204756"], + ["SC", "Curitibanos", "4204806"], + ["SC", "Descanso", "4204905"], + ["SC", "Dion\u{ed}sio Cerqueira", "4205001"], + ["SC", "Dona Emma", "4205100"], + ["SC", "Doutor Pedrinho", "4205159"], + ["SC", "Entre Rios", "4205175"], + ["SC", "Ermo", "4205191"], + ["SC", "Erval Velho", "4205209"], + ["SC", "Faxinal dos Guedes", "4205308"], + ["SC", "Flor do Sert\u{e3}o", "4205357"], + ["SC", "Florian\u{f3}polis", "4205407"], + ["SC", "Formosa do Sul", "4205431"], + ["SC", "Forquilhinha", "4205456"], + ["SC", "Fraiburgo", "4205506"], + ["SC", "Frei Rog\u{e9}rio", "4205555"], + ["SC", "Galv\u{e3}o", "4205605"], + ["SC", "Garopaba", "4205704"], + ["SC", "Garuva", "4205803"], + ["SC", "Gaspar", "4205902"], + ["SC", "Governador Celso Ramos", "4206009"], + ["SC", "Gr\u{e3}o-Par\u{e1}", "4206108"], + ["SC", "Gravatal", "4206207"], + ["SC", "Guabiruba", "4206306"], + ["SC", "Guaraciaba", "4206405"], + ["SC", "Guaramirim", "4206504"], + ["SC", "Guaruj\u{e1} do Sul", "4206603"], + ["SC", "Guatamb\u{fa}", "4206652"], + ["SC", "Herval d'Oeste", "4206702"], + ["SC", "Ibiam", "4206751"], + ["SC", "Ibicar\u{e9}", "4206801"], + ["SC", "Ibirama", "4206900"], + ["SC", "I\u{e7}ara", "4207007"], + ["SC", "Ilhota", "4207106"], + ["SC", "Imaru\u{ed}", "4207205"], + ["SC", "Imbituba", "4207304"], + ["SC", "Imbuia", "4207403"], + ["SC", "Indaial", "4207502"], + ["SC", "Iomer\u{ea}", "4207577"], + ["SC", "Ipira", "4207601"], + ["SC", "Ipor\u{e3} do Oeste", "4207650"], + ["SC", "Ipua\u{e7}u", "4207684"], + ["SC", "Ipumirim", "4207700"], + ["SC", "Iraceminha", "4207759"], + ["SC", "Irani", "4207809"], + ["SC", "Irati", "4207858"], + ["SC", "Irine\u{f3}polis", "4207908"], + ["SC", "It\u{e1}", "4208005"], + ["SC", "Itai\u{f3}polis", "4208104"], + ["SC", "Itaja\u{ed}", "4208203"], + ["SC", "Itapema", "4208302"], + ["SC", "Itapiranga", "4208401"], + ["SC", "Itapo\u{e1}", "4208450"], + ["SC", "Ituporanga", "4208500"], + ["SC", "Jabor\u{e1}", "4208609"], + ["SC", "Jacinto Machado", "4208708"], + ["SC", "Jaguaruna", "4208807"], + ["SC", "Jaragu\u{e1} do Sul", "4208906"], + ["SC", "Jardin\u{f3}polis", "4208955"], + ["SC", "Joa\u{e7}aba", "4209003"], + ["SC", "Joinville", "4209102"], + ["SC", "Jos\u{e9} Boiteux", "4209151"], + ["SC", "Jupi\u{e1}", "4209177"], + ["SC", "Lacerd\u{f3}polis", "4209201"], + ["SC", "Lages", "4209300"], + ["SC", "Laguna", "4209409"], + ["SC", "Lajeado Grande", "4209458"], + ["SC", "Laurentino", "4209508"], + ["SC", "Lauro M\u{fc}ller", "4209607"], + ["SC", "Lebon R\u{e9}gis", "4209706"], + ["SC", "Leoberto Leal", "4209805"], + ["SC", "Lind\u{f3}ia do Sul", "4209854"], + ["SC", "Lontras", "4209904"], + ["SC", "Luiz Alves", "4210001"], + ["SC", "Luzerna", "4210035"], + ["SC", "Macieira", "4210050"], + ["SC", "Mafra", "4210100"], + ["SC", "Major Gercino", "4210209"], + ["SC", "Major Vieira", "4210308"], + ["SC", "Maracaj\u{e1}", "4210407"], + ["SC", "Maravilha", "4210506"], + ["SC", "Marema", "4210555"], + ["SC", "Massaranduba", "4210605"], + ["SC", "Matos Costa", "4210704"], + ["SC", "Meleiro", "4210803"], + ["SC", "Mirim Doce", "4210852"], + ["SC", "Modelo", "4210902"], + ["SC", "Monda\u{ed}", "4211009"], + ["SC", "Monte Carlo", "4211058"], + ["SC", "Monte Castelo", "4211108"], + ["SC", "Morro da Fuma\u{e7}a", "4211207"], + ["SC", "Morro Grande", "4211256"], + ["SC", "Navegantes", "4211306"], + ["SC", "Nova Erechim", "4211405"], + ["SC", "Nova Itaberaba", "4211454"], + ["SC", "Nova Trento", "4211504"], + ["SC", "Nova Veneza", "4211603"], + ["SC", "Novo Horizonte", "4211652"], + ["SC", "Orleans", "4211702"], + ["SC", "Otac\u{ed}lio Costa", "4211751"], + ["SC", "Ouro", "4211801"], + ["SC", "Ouro Verde", "4211850"], + ["SC", "Paial", "4211876"], + ["SC", "Painel", "4211892"], + ["SC", "Palho\u{e7}a", "4211900"], + ["SC", "Palma Sola", "4212007"], + ["SC", "Palmeira", "4212056"], + ["SC", "Palmitos", "4212106"], + ["SC", "Papanduva", "4212205"], + ["SC", "Para\u{ed}so", "4212239"], + ["SC", "Passo de Torres", "4212254"], + ["SC", "Passos Maia", "4212270"], + ["SC", "Paulo Lopes", "4212304"], + ["SC", "Pedras Grandes", "4212403"], + ["SC", "Penha", "4212502"], + ["SC", "Peritiba", "4212601"], + ["SC", "Pescaria Brava", "4212650"], + ["SC", "Petrol\u{e2}ndia", "4212700"], + ["SC", "Pinhalzinho", "4212908"], + ["SC", "Pinheiro Preto", "4213005"], + ["SC", "Piratuba", "4213104"], + ["SC", "Planalto Alegre", "4213153"], + ["SC", "Pomerode", "4213203"], + ["SC", "Ponte Alta", "4213302"], + ["SC", "Ponte Alta do Norte", "4213351"], + ["SC", "Ponte Serrada", "4213401"], + ["SC", "Porto Belo", "4213500"], + ["SC", "Porto Uni\u{e3}o", "4213609"], + ["SC", "Pouso Redondo", "4213708"], + ["SC", "Praia Grande", "4213807"], + ["SC", "Presidente Castello Branco", "4213906"], + ["SC", "Presidente Get\u{fa}lio", "4214003"], + ["SC", "Presidente Nereu", "4214102"], + ["SC", "Princesa", "4214151"], + ["SC", "Quilombo", "4214201"], + ["SC", "Rancho Queimado", "4214300"], + ["SC", "Rio das Antas", "4214409"], + ["SC", "Rio do Campo", "4214508"], + ["SC", "Rio do Oeste", "4214607"], + ["SC", "Rio do Sul", "4214805"], + ["SC", "Rio dos Cedros", "4214706"], + ["SC", "Rio Fortuna", "4214904"], + ["SC", "Rio Negrinho", "4215000"], + ["SC", "Rio Rufino", "4215059"], + ["SC", "Riqueza", "4215075"], + ["SC", "Rodeio", "4215109"], + ["SC", "Romel\u{e2}ndia", "4215208"], + ["SC", "Salete", "4215307"], + ["SC", "Saltinho", "4215356"], + ["SC", "Salto Veloso", "4215406"], + ["SC", "Sang\u{e3}o", "4215455"], + ["SC", "Santa Cec\u{ed}lia", "4215505"], + ["SC", "Santa Helena", "4215554"], + ["SC", "Santa Rosa de Lima", "4215604"], + ["SC", "Santa Rosa do Sul", "4215653"], + ["SC", "Santa Terezinha", "4215679"], + ["SC", "Santa Terezinha do Progresso", "4215687"], + ["SC", "Santiago do Sul", "4215695"], + ["SC", "Santo Amaro da Imperatriz", "4215703"], + ["SC", "S\u{e3}o Bento do Sul", "4215802"], + ["SC", "S\u{e3}o Bernardino", "4215752"], + ["SC", "S\u{e3}o Bonif\u{e1}cio", "4215901"], + ["SC", "S\u{e3}o Carlos", "4216008"], + ["SC", "S\u{e3}o Crist\u{f3}v\u{e3}o do Sul", "4216057"], + ["SC", "S\u{e3}o Domingos", "4216107"], + ["SC", "S\u{e3}o Francisco do Sul", "4216206"], + ["SC", "S\u{e3}o Jo\u{e3}o Batista", "4216305"], + ["SC", "S\u{e3}o Jo\u{e3}o do Itaperi\u{fa}", "4216354"], + ["SC", "S\u{e3}o Jo\u{e3}o do Oeste", "4216255"], + ["SC", "S\u{e3}o Jo\u{e3}o do Sul", "4216404"], + ["SC", "S\u{e3}o Joaquim", "4216503"], + ["SC", "S\u{e3}o Jos\u{e9}", "4216602"], + ["SC", "S\u{e3}o Jos\u{e9} do Cedro", "4216701"], + ["SC", "S\u{e3}o Jos\u{e9} do Cerrito", "4216800"], + ["SC", "S\u{e3}o Louren\u{e7}o do Oeste", "4216909"], + ["SC", "S\u{e3}o Ludgero", "4217006"], + ["SC", "S\u{e3}o Martinho", "4217105"], + ["SC", "S\u{e3}o Miguel da Boa Vista", "4217154"], + ["SC", "S\u{e3}o Miguel do Oeste", "4217204"], + ["SC", "S\u{e3}o Pedro de Alc\u{e2}ntara", "4217253"], + ["SC", "Saudades", "4217303"], + ["SC", "Schroeder", "4217402"], + ["SC", "Seara", "4217501"], + ["SC", "Serra Alta", "4217550"], + ["SC", "Sider\u{f3}polis", "4217600"], + ["SC", "Sombrio", "4217709"], + ["SC", "Sul Brasil", "4217758"], + ["SC", "Tai\u{f3}", "4217808"], + ["SC", "Tangar\u{e1}", "4217907"], + ["SC", "Tigrinhos", "4217956"], + ["SC", "Tijucas", "4218004"], + ["SC", "Timb\u{e9} do Sul", "4218103"], + ["SC", "Timb\u{f3}", "4218202"], + ["SC", "Timb\u{f3} Grande", "4218251"], + ["SC", "Tr\u{ea}s Barras", "4218301"], + ["SC", "Treviso", "4218350"], + ["SC", "Treze de Maio", "4218400"], + ["SC", "Treze T\u{ed}lias", "4218509"], + ["SC", "Trombudo Central", "4218608"], + ["SC", "Tubar\u{e3}o", "4218707"], + ["SC", "Tun\u{e1}polis", "4218756"], + ["SC", "Turvo", "4218806"], + ["SC", "Uni\u{e3}o do Oeste", "4218855"], + ["SC", "Urubici", "4218905"], + ["SC", "Urupema", "4218954"], + ["SC", "Urussanga", "4219002"], + ["SC", "Varge\u{e3}o", "4219101"], + ["SC", "Vargem", "4219150"], + ["SC", "Vargem Bonita", "4219176"], + ["SC", "Vidal Ramos", "4219200"], + ["SC", "Videira", "4219309"], + ["SC", "Vitor Meireles", "4219358"], + ["SC", "Witmarsum", "4219408"], + ["SC", "Xanxer\u{ea}", "4219507"], + ["SC", "Xavantina", "4219606"], + ["SC", "Xaxim", "4219705"], + ["SC", "Zort\u{e9}a", "4219853"], + ["SP", "Adamantina", "3500105"], + ["SP", "Adolfo", "3500204"], + ["SP", "Agua\u{ed}", "3500303"], + ["SP", "\u{c1}guas da Prata", "3500402"], + ["SP", "\u{c1}guas de Lind\u{f3}ia", "3500501"], + ["SP", "\u{c1}guas de Santa B\u{e1}rbara", "3500550"], + ["SP", "\u{c1}guas de S\u{e3}o Pedro", "3500600"], + ["SP", "Agudos", "3500709"], + ["SP", "Alambari", "3500758"], + ["SP", "Alfredo Marcondes", "3500808"], + ["SP", "Altair", "3500907"], + ["SP", "Altin\u{f3}polis", "3501004"], + ["SP", "Alto Alegre", "3501103"], + ["SP", "Alum\u{ed}nio", "3501152"], + ["SP", "\u{c1}lvares Florence", "3501202"], + ["SP", "\u{c1}lvares Machado", "3501301"], + ["SP", "\u{c1}lvaro de Carvalho", "3501400"], + ["SP", "Alvinl\u{e2}ndia", "3501509"], + ["SP", "Americana", "3501608"], + ["SP", "Am\u{e9}rico Brasiliense", "3501707"], + ["SP", "Am\u{e9}rico de Campos", "3501806"], + ["SP", "Amparo", "3501905"], + ["SP", "Anal\u{e2}ndia", "3502002"], + ["SP", "Andradina", "3502101"], + ["SP", "Angatuba", "3502200"], + ["SP", "Anhembi", "3502309"], + ["SP", "Anhumas", "3502408"], + ["SP", "Aparecida", "3502507"], + ["SP", "Aparecida d'Oeste", "3502606"], + ["SP", "Apia\u{ed}", "3502705"], + ["SP", "Ara\u{e7}ariguama", "3502754"], + ["SP", "Ara\u{e7}atuba", "3502804"], + ["SP", "Ara\u{e7}oiaba da Serra", "3502903"], + ["SP", "Aramina", "3503000"], + ["SP", "Arandu", "3503109"], + ["SP", "Arape\u{ed}", "3503158"], + ["SP", "Araraquara", "3503208"], + ["SP", "Araras", "3503307"], + ["SP", "Arco-\u{cd}ris", "3503356"], + ["SP", "Arealva", "3503406"], + ["SP", "Areias", "3503505"], + ["SP", "Arei\u{f3}polis", "3503604"], + ["SP", "Ariranha", "3503703"], + ["SP", "Artur Nogueira", "3503802"], + ["SP", "Aruj\u{e1}", "3503901"], + ["SP", "Asp\u{e1}sia", "3503950"], + ["SP", "Assis", "3504008"], + ["SP", "Atibaia", "3504107"], + ["SP", "Auriflama", "3504206"], + ["SP", "Ava\u{ed}", "3504305"], + ["SP", "Avanhandava", "3504404"], + ["SP", "Avar\u{e9}", "3504503"], + ["SP", "Bady Bassitt", "3504602"], + ["SP", "Balbinos", "3504701"], + ["SP", "B\u{e1}lsamo", "3504800"], + ["SP", "Bananal", "3504909"], + ["SP", "Bar\u{e3}o de Antonina", "3505005"], + ["SP", "Barbosa", "3505104"], + ["SP", "Bariri", "3505203"], + ["SP", "Barra Bonita", "3505302"], + ["SP", "Barra do Chap\u{e9}u", "3505351"], + ["SP", "Barra do Turvo", "3505401"], + ["SP", "Barretos", "3505500"], + ["SP", "Barrinha", "3505609"], + ["SP", "Barueri", "3505708"], + ["SP", "Bastos", "3505807"], + ["SP", "Batatais", "3505906"], + ["SP", "Bauru", "3506003"], + ["SP", "Bebedouro", "3506102"], + ["SP", "Bento de Abreu", "3506201"], + ["SP", "Bernardino de Campos", "3506300"], + ["SP", "Bertioga", "3506359"], + ["SP", "Bilac", "3506409"], + ["SP", "Birigui", "3506508"], + ["SP", "Biritiba Mirim", "3506607"], + ["SP", "Boa Esperan\u{e7}a do Sul", "3506706"], + ["SP", "Bocaina", "3506805"], + ["SP", "Bofete", "3506904"], + ["SP", "Boituva", "3507001"], + ["SP", "Bom Jesus dos Perd\u{f5}es", "3507100"], + ["SP", "Bom Sucesso de Itarar\u{e9}", "3507159"], + ["SP", "Bor\u{e1}", "3507209"], + ["SP", "Borac\u{e9}ia", "3507308"], + ["SP", "Borborema", "3507407"], + ["SP", "Borebi", "3507456"], + ["SP", "Botucatu", "3507506"], + ["SP", "Bragan\u{e7}a Paulista", "3507605"], + ["SP", "Bra\u{fa}na", "3507704"], + ["SP", "Brejo Alegre", "3507753"], + ["SP", "Brodowski", "3507803"], + ["SP", "Brotas", "3507902"], + ["SP", "Buri", "3508009"], + ["SP", "Buritama", "3508108"], + ["SP", "Buritizal", "3508207"], + ["SP", "Cabr\u{e1}lia Paulista", "3508306"], + ["SP", "Cabre\u{fa}va", "3508405"], + ["SP", "Ca\u{e7}apava", "3508504"], + ["SP", "Cachoeira Paulista", "3508603"], + ["SP", "Caconde", "3508702"], + ["SP", "Cafel\u{e2}ndia", "3508801"], + ["SP", "Caiabu", "3508900"], + ["SP", "Caieiras", "3509007"], + ["SP", "Caiu\u{e1}", "3509106"], + ["SP", "Cajamar", "3509205"], + ["SP", "Cajati", "3509254"], + ["SP", "Cajobi", "3509304"], + ["SP", "Cajuru", "3509403"], + ["SP", "Campina do Monte Alegre", "3509452"], + ["SP", "Campinas", "3509502"], + ["SP", "Campo Limpo Paulista", "3509601"], + ["SP", "Campos do Jord\u{e3}o", "3509700"], + ["SP", "Campos Novos Paulista", "3509809"], + ["SP", "Canan\u{e9}ia", "3509908"], + ["SP", "Canas", "3509957"], + ["SP", "C\u{e2}ndido Mota", "3510005"], + ["SP", "C\u{e2}ndido Rodrigues", "3510104"], + ["SP", "Canitar", "3510153"], + ["SP", "Cap\u{e3}o Bonito", "3510203"], + ["SP", "Capela do Alto", "3510302"], + ["SP", "Capivari", "3510401"], + ["SP", "Caraguatatuba", "3510500"], + ["SP", "Carapicu\u{ed}ba", "3510609"], + ["SP", "Cardoso", "3510708"], + ["SP", "Casa Branca", "3510807"], + ["SP", "C\u{e1}ssia dos Coqueiros", "3510906"], + ["SP", "Castilho", "3511003"], + ["SP", "Catanduva", "3511102"], + ["SP", "Catigu\u{e1}", "3511201"], + ["SP", "Cedral", "3511300"], + ["SP", "Cerqueira C\u{e9}sar", "3511409"], + ["SP", "Cerquilho", "3511508"], + ["SP", "Ces\u{e1}rio Lange", "3511607"], + ["SP", "Charqueada", "3511706"], + ["SP", "Chavantes", "3557204"], + ["SP", "Clementina", "3511904"], + ["SP", "Colina", "3512001"], + ["SP", "Col\u{f4}mbia", "3512100"], + ["SP", "Conchal", "3512209"], + ["SP", "Conchas", "3512308"], + ["SP", "Cordeir\u{f3}polis", "3512407"], + ["SP", "Coroados", "3512506"], + ["SP", "Coronel Macedo", "3512605"], + ["SP", "Corumbata\u{ed}", "3512704"], + ["SP", "Cosm\u{f3}polis", "3512803"], + ["SP", "Cosmorama", "3512902"], + ["SP", "Cotia", "3513009"], + ["SP", "Cravinhos", "3513108"], + ["SP", "Cristais Paulista", "3513207"], + ["SP", "Cruz\u{e1}lia", "3513306"], + ["SP", "Cruzeiro", "3513405"], + ["SP", "Cubat\u{e3}o", "3513504"], + ["SP", "Cunha", "3513603"], + ["SP", "Descalvado", "3513702"], + ["SP", "Diadema", "3513801"], + ["SP", "Dirce Reis", "3513850"], + ["SP", "Divinol\u{e2}ndia", "3513900"], + ["SP", "Dobrada", "3514007"], + ["SP", "Dois C\u{f3}rregos", "3514106"], + ["SP", "Dolcin\u{f3}polis", "3514205"], + ["SP", "Dourado", "3514304"], + ["SP", "Dracena", "3514403"], + ["SP", "Duartina", "3514502"], + ["SP", "Dumont", "3514601"], + ["SP", "Echapor\u{e3}", "3514700"], + ["SP", "Eldorado", "3514809"], + ["SP", "Elias Fausto", "3514908"], + ["SP", "Elisi\u{e1}rio", "3514924"], + ["SP", "Emba\u{fa}ba", "3514957"], + ["SP", "Embu das Artes", "3515004"], + ["SP", "Embu-Gua\u{e7}u", "3515103"], + ["SP", "Emilian\u{f3}polis", "3515129"], + ["SP", "Engenheiro Coelho", "3515152"], + ["SP", "Esp\u{ed}rito Santo do Pinhal", "3515186"], + ["SP", "Esp\u{ed}rito Santo do Turvo", "3515194"], + ["SP", "Estiva Gerbi", "3557303"], + ["SP", "Estrela d'Oeste", "3515202"], + ["SP", "Estrela do Norte", "3515301"], + ["SP", "Euclides da Cunha Paulista", "3515350"], + ["SP", "Fartura", "3515400"], + ["SP", "Fernando Prestes", "3515608"], + ["SP", "Fernand\u{f3}polis", "3515509"], + ["SP", "Fern\u{e3}o", "3515657"], + ["SP", "Ferraz de Vasconcelos", "3515707"], + ["SP", "Flora Rica", "3515806"], + ["SP", "Floreal", "3515905"], + ["SP", "Fl\u{f3}rida Paulista", "3516002"], + ["SP", "Flor\u{ed}nea", "3516101"], + ["SP", "Franca", "3516200"], + ["SP", "Francisco Morato", "3516309"], + ["SP", "Franco da Rocha", "3516408"], + ["SP", "Gabriel Monteiro", "3516507"], + ["SP", "G\u{e1}lia", "3516606"], + ["SP", "Gar\u{e7}a", "3516705"], + ["SP", "Gast\u{e3}o Vidigal", "3516804"], + ["SP", "Gavi\u{e3}o Peixoto", "3516853"], + ["SP", "General Salgado", "3516903"], + ["SP", "Getulina", "3517000"], + ["SP", "Glic\u{e9}rio", "3517109"], + ["SP", "Guai\u{e7}ara", "3517208"], + ["SP", "Guaimb\u{ea}", "3517307"], + ["SP", "Gua\u{ed}ra", "3517406"], + ["SP", "Guapia\u{e7}u", "3517505"], + ["SP", "Guapiara", "3517604"], + ["SP", "Guar\u{e1}", "3517703"], + ["SP", "Guara\u{e7}a\u{ed}", "3517802"], + ["SP", "Guaraci", "3517901"], + ["SP", "Guarani d'Oeste", "3518008"], + ["SP", "Guarant\u{e3}", "3518107"], + ["SP", "Guararapes", "3518206"], + ["SP", "Guararema", "3518305"], + ["SP", "Guaratinguet\u{e1}", "3518404"], + ["SP", "Guare\u{ed}", "3518503"], + ["SP", "Guariba", "3518602"], + ["SP", "Guaruj\u{e1}", "3518701"], + ["SP", "Guarulhos", "3518800"], + ["SP", "Guatapar\u{e1}", "3518859"], + ["SP", "Guzol\u{e2}ndia", "3518909"], + ["SP", "Hercul\u{e2}ndia", "3519006"], + ["SP", "Holambra", "3519055"], + ["SP", "Hortol\u{e2}ndia", "3519071"], + ["SP", "Iacanga", "3519105"], + ["SP", "Iacri", "3519204"], + ["SP", "Iaras", "3519253"], + ["SP", "Ibat\u{e9}", "3519303"], + ["SP", "Ibir\u{e1}", "3519402"], + ["SP", "Ibirarema", "3519501"], + ["SP", "Ibitinga", "3519600"], + ["SP", "Ibi\u{fa}na", "3519709"], + ["SP", "Ic\u{e9}m", "3519808"], + ["SP", "Iep\u{ea}", "3519907"], + ["SP", "Igara\u{e7}u do Tiet\u{ea}", "3520004"], + ["SP", "Igarapava", "3520103"], + ["SP", "Igarat\u{e1}", "3520202"], + ["SP", "Iguape", "3520301"], + ["SP", "Ilha Comprida", "3520426"], + ["SP", "Ilha Solteira", "3520442"], + ["SP", "Ilhabela", "3520400"], + ["SP", "Indaiatuba", "3520509"], + ["SP", "Indiana", "3520608"], + ["SP", "Indiapor\u{e3}", "3520707"], + ["SP", "In\u{fa}bia Paulista", "3520806"], + ["SP", "Ipaussu", "3520905"], + ["SP", "Iper\u{f3}", "3521002"], + ["SP", "Ipe\u{fa}na", "3521101"], + ["SP", "Ipigu\u{e1}", "3521150"], + ["SP", "Iporanga", "3521200"], + ["SP", "Ipu\u{e3}", "3521309"], + ["SP", "Iracem\u{e1}polis", "3521408"], + ["SP", "Irapu\u{e3}", "3521507"], + ["SP", "Irapuru", "3521606"], + ["SP", "Itaber\u{e1}", "3521705"], + ["SP", "Ita\u{ed}", "3521804"], + ["SP", "Itajobi", "3521903"], + ["SP", "Itaju", "3522000"], + ["SP", "Itanha\u{e9}m", "3522109"], + ["SP", "Itaoca", "3522158"], + ["SP", "Itapecerica da Serra", "3522208"], + ["SP", "Itapetininga", "3522307"], + ["SP", "Itapeva", "3522406"], + ["SP", "Itapevi", "3522505"], + ["SP", "Itapira", "3522604"], + ["SP", "Itapirapu\u{e3} Paulista", "3522653"], + ["SP", "It\u{e1}polis", "3522703"], + ["SP", "Itaporanga", "3522802"], + ["SP", "Itapu\u{ed}", "3522901"], + ["SP", "Itapura", "3523008"], + ["SP", "Itaquaquecetuba", "3523107"], + ["SP", "Itarar\u{e9}", "3523206"], + ["SP", "Itariri", "3523305"], + ["SP", "Itatiba", "3523404"], + ["SP", "Itatinga", "3523503"], + ["SP", "Itirapina", "3523602"], + ["SP", "Itirapu\u{e3}", "3523701"], + ["SP", "Itobi", "3523800"], + ["SP", "Itu", "3523909"], + ["SP", "Itupeva", "3524006"], + ["SP", "Ituverava", "3524105"], + ["SP", "Jaborandi", "3524204"], + ["SP", "Jaboticabal", "3524303"], + ["SP", "Jacare\u{ed}", "3524402"], + ["SP", "Jaci", "3524501"], + ["SP", "Jacupiranga", "3524600"], + ["SP", "Jaguari\u{fa}na", "3524709"], + ["SP", "Jales", "3524808"], + ["SP", "Jambeiro", "3524907"], + ["SP", "Jandira", "3525003"], + ["SP", "Jardin\u{f3}polis", "3525102"], + ["SP", "Jarinu", "3525201"], + ["SP", "Ja\u{fa}", "3525300"], + ["SP", "Jeriquara", "3525409"], + ["SP", "Joan\u{f3}polis", "3525508"], + ["SP", "Jo\u{e3}o Ramalho", "3525607"], + ["SP", "Jos\u{e9} Bonif\u{e1}cio", "3525706"], + ["SP", "J\u{fa}lio Mesquita", "3525805"], + ["SP", "Jumirim", "3525854"], + ["SP", "Jundia\u{ed}", "3525904"], + ["SP", "Junqueir\u{f3}polis", "3526001"], + ["SP", "Juqui\u{e1}", "3526100"], + ["SP", "Juquitiba", "3526209"], + ["SP", "Lagoinha", "3526308"], + ["SP", "Laranjal Paulista", "3526407"], + ["SP", "Lav\u{ed}nia", "3526506"], + ["SP", "Lavrinhas", "3526605"], + ["SP", "Leme", "3526704"], + ["SP", "Len\u{e7}\u{f3}is Paulista", "3526803"], + ["SP", "Limeira", "3526902"], + ["SP", "Lind\u{f3}ia", "3527009"], + ["SP", "Lins", "3527108"], + ["SP", "Lorena", "3527207"], + ["SP", "Lourdes", "3527256"], + ["SP", "Louveira", "3527306"], + ["SP", "Luc\u{e9}lia", "3527405"], + ["SP", "Lucian\u{f3}polis", "3527504"], + ["SP", "Lu\u{ed}s Ant\u{f4}nio", "3527603"], + ["SP", "Luizi\u{e2}nia", "3527702"], + ["SP", "Lup\u{e9}rcio", "3527801"], + ["SP", "Lut\u{e9}cia", "3527900"], + ["SP", "Macatuba", "3528007"], + ["SP", "Macaubal", "3528106"], + ["SP", "Maced\u{f4}nia", "3528205"], + ["SP", "Magda", "3528304"], + ["SP", "Mairinque", "3528403"], + ["SP", "Mairipor\u{e3}", "3528502"], + ["SP", "Manduri", "3528601"], + ["SP", "Marab\u{e1} Paulista", "3528700"], + ["SP", "Maraca\u{ed}", "3528809"], + ["SP", "Marapoama", "3528858"], + ["SP", "Mari\u{e1}polis", "3528908"], + ["SP", "Mar\u{ed}lia", "3529005"], + ["SP", "Marin\u{f3}polis", "3529104"], + ["SP", "Martin\u{f3}polis", "3529203"], + ["SP", "Mat\u{e3}o", "3529302"], + ["SP", "Mau\u{e1}", "3529401"], + ["SP", "Mendon\u{e7}a", "3529500"], + ["SP", "Meridiano", "3529609"], + ["SP", "Mes\u{f3}polis", "3529658"], + ["SP", "Miguel\u{f3}polis", "3529708"], + ["SP", "Mineiros do Tiet\u{ea}", "3529807"], + ["SP", "Mira Estrela", "3530003"], + ["SP", "Miracatu", "3529906"], + ["SP", "Mirand\u{f3}polis", "3530102"], + ["SP", "Mirante do Paranapanema", "3530201"], + ["SP", "Mirassol", "3530300"], + ["SP", "Mirassol\u{e2}ndia", "3530409"], + ["SP", "Mococa", "3530508"], + ["SP", "Mogi das Cruzes", "3530607"], + ["SP", "Mogi Gua\u{e7}u", "3530706"], + ["SP", "Mogi Mirim", "3530805"], + ["SP", "Mombuca", "3530904"], + ["SP", "Mon\u{e7}\u{f5}es", "3531001"], + ["SP", "Mongagu\u{e1}", "3531100"], + ["SP", "Monte Alegre do Sul", "3531209"], + ["SP", "Monte Alto", "3531308"], + ["SP", "Monte Apraz\u{ed}vel", "3531407"], + ["SP", "Monte Azul Paulista", "3531506"], + ["SP", "Monte Castelo", "3531605"], + ["SP", "Monte Mor", "3531803"], + ["SP", "Monteiro Lobato", "3531704"], + ["SP", "Morro Agudo", "3531902"], + ["SP", "Morungaba", "3532009"], + ["SP", "Motuca", "3532058"], + ["SP", "Murutinga do Sul", "3532108"], + ["SP", "Nantes", "3532157"], + ["SP", "Narandiba", "3532207"], + ["SP", "Natividade da Serra", "3532306"], + ["SP", "Nazar\u{e9} Paulista", "3532405"], + ["SP", "Neves Paulista", "3532504"], + ["SP", "Nhandeara", "3532603"], + ["SP", "Nipo\u{e3}", "3532702"], + ["SP", "Nova Alian\u{e7}a", "3532801"], + ["SP", "Nova Campina", "3532827"], + ["SP", "Nova Cana\u{e3} Paulista", "3532843"], + ["SP", "Nova Castilho", "3532868"], + ["SP", "Nova Europa", "3532900"], + ["SP", "Nova Granada", "3533007"], + ["SP", "Nova Guataporanga", "3533106"], + ["SP", "Nova Independ\u{ea}ncia", "3533205"], + ["SP", "Nova Luzit\u{e2}nia", "3533304"], + ["SP", "Nova Odessa", "3533403"], + ["SP", "Novais", "3533254"], + ["SP", "Novo Horizonte", "3533502"], + ["SP", "Nuporanga", "3533601"], + ["SP", "Ocau\u{e7}u", "3533700"], + ["SP", "\u{d3}leo", "3533809"], + ["SP", "Ol\u{ed}mpia", "3533908"], + ["SP", "Onda Verde", "3534005"], + ["SP", "Oriente", "3534104"], + ["SP", "Orindi\u{fa}va", "3534203"], + ["SP", "Orl\u{e2}ndia", "3534302"], + ["SP", "Osasco", "3534401"], + ["SP", "Oscar Bressane", "3534500"], + ["SP", "Osvaldo Cruz", "3534609"], + ["SP", "Ourinhos", "3534708"], + ["SP", "Ouro Verde", "3534807"], + ["SP", "Ouroeste", "3534757"], + ["SP", "Pacaembu", "3534906"], + ["SP", "Palestina", "3535002"], + ["SP", "Palmares Paulista", "3535101"], + ["SP", "Palmeira d'Oeste", "3535200"], + ["SP", "Palmital", "3535309"], + ["SP", "Panorama", "3535408"], + ["SP", "Paragua\u{e7}u Paulista", "3535507"], + ["SP", "Paraibuna", "3535606"], + ["SP", "Para\u{ed}so", "3535705"], + ["SP", "Paranapanema", "3535804"], + ["SP", "Paranapu\u{e3}", "3535903"], + ["SP", "Parapu\u{e3}", "3536000"], + ["SP", "Pardinho", "3536109"], + ["SP", "Pariquera-A\u{e7}u", "3536208"], + ["SP", "Parisi", "3536257"], + ["SP", "Patroc\u{ed}nio Paulista", "3536307"], + ["SP", "Paulic\u{e9}ia", "3536406"], + ["SP", "Paul\u{ed}nia", "3536505"], + ["SP", "Paulist\u{e2}nia", "3536570"], + ["SP", "Paulo de Faria", "3536604"], + ["SP", "Pederneiras", "3536703"], + ["SP", "Pedra Bela", "3536802"], + ["SP", "Pedran\u{f3}polis", "3536901"], + ["SP", "Pedregulho", "3537008"], + ["SP", "Pedreira", "3537107"], + ["SP", "Pedrinhas Paulista", "3537156"], + ["SP", "Pedro de Toledo", "3537206"], + ["SP", "Pen\u{e1}polis", "3537305"], + ["SP", "Pereira Barreto", "3537404"], + ["SP", "Pereiras", "3537503"], + ["SP", "Peru\u{ed}be", "3537602"], + ["SP", "Piacatu", "3537701"], + ["SP", "Piedade", "3537800"], + ["SP", "Pilar do Sul", "3537909"], + ["SP", "Pindamonhangaba", "3538006"], + ["SP", "Pindorama", "3538105"], + ["SP", "Pinhalzinho", "3538204"], + ["SP", "Piquerobi", "3538303"], + ["SP", "Piquete", "3538501"], + ["SP", "Piracaia", "3538600"], + ["SP", "Piracicaba", "3538709"], + ["SP", "Piraju", "3538808"], + ["SP", "Piraju\u{ed}", "3538907"], + ["SP", "Pirangi", "3539004"], + ["SP", "Pirapora do Bom Jesus", "3539103"], + ["SP", "Pirapozinho", "3539202"], + ["SP", "Pirassununga", "3539301"], + ["SP", "Piratininga", "3539400"], + ["SP", "Pitangueiras", "3539509"], + ["SP", "Planalto", "3539608"], + ["SP", "Platina", "3539707"], + ["SP", "Po\u{e1}", "3539806"], + ["SP", "Poloni", "3539905"], + ["SP", "Pomp\u{e9}ia", "3540002"], + ["SP", "Ponga\u{ed}", "3540101"], + ["SP", "Pontal", "3540200"], + ["SP", "Pontalinda", "3540259"], + ["SP", "Pontes Gestal", "3540309"], + ["SP", "Populina", "3540408"], + ["SP", "Porangaba", "3540507"], + ["SP", "Porto Feliz", "3540606"], + ["SP", "Porto Ferreira", "3540705"], + ["SP", "Potim", "3540754"], + ["SP", "Potirendaba", "3540804"], + ["SP", "Pracinha", "3540853"], + ["SP", "Prad\u{f3}polis", "3540903"], + ["SP", "Praia Grande", "3541000"], + ["SP", "Prat\u{e2}nia", "3541059"], + ["SP", "Presidente Alves", "3541109"], + ["SP", "Presidente Bernardes", "3541208"], + ["SP", "Presidente Epit\u{e1}cio", "3541307"], + ["SP", "Presidente Prudente", "3541406"], + ["SP", "Presidente Venceslau", "3541505"], + ["SP", "Promiss\u{e3}o", "3541604"], + ["SP", "Quadra", "3541653"], + ["SP", "Quat\u{e1}", "3541703"], + ["SP", "Queiroz", "3541802"], + ["SP", "Queluz", "3541901"], + ["SP", "Quintana", "3542008"], + ["SP", "Rafard", "3542107"], + ["SP", "Rancharia", "3542206"], + ["SP", "Reden\u{e7}\u{e3}o da Serra", "3542305"], + ["SP", "Regente Feij\u{f3}", "3542404"], + ["SP", "Regin\u{f3}polis", "3542503"], + ["SP", "Registro", "3542602"], + ["SP", "Restinga", "3542701"], + ["SP", "Ribeira", "3542800"], + ["SP", "Ribeir\u{e3}o Bonito", "3542909"], + ["SP", "Ribeir\u{e3}o Branco", "3543006"], + ["SP", "Ribeir\u{e3}o Corrente", "3543105"], + ["SP", "Ribeir\u{e3}o do Sul", "3543204"], + ["SP", "Ribeir\u{e3}o dos \u{cd}ndios", "3543238"], + ["SP", "Ribeir\u{e3}o Grande", "3543253"], + ["SP", "Ribeir\u{e3}o Pires", "3543303"], + ["SP", "Ribeir\u{e3}o Preto", "3543402"], + ["SP", "Rifaina", "3543600"], + ["SP", "Rinc\u{e3}o", "3543709"], + ["SP", "Rin\u{f3}polis", "3543808"], + ["SP", "Rio Claro", "3543907"], + ["SP", "Rio das Pedras", "3544004"], + ["SP", "Rio Grande da Serra", "3544103"], + ["SP", "Riol\u{e2}ndia", "3544202"], + ["SP", "Riversul", "3543501"], + ["SP", "Rosana", "3544251"], + ["SP", "Roseira", "3544301"], + ["SP", "Rubi\u{e1}cea", "3544400"], + ["SP", "Rubin\u{e9}ia", "3544509"], + ["SP", "Sabino", "3544608"], + ["SP", "Sagres", "3544707"], + ["SP", "Sales", "3544806"], + ["SP", "Sales Oliveira", "3544905"], + ["SP", "Sales\u{f3}polis", "3545001"], + ["SP", "Salmour\u{e3}o", "3545100"], + ["SP", "Saltinho", "3545159"], + ["SP", "Salto", "3545209"], + ["SP", "Salto de Pirapora", "3545308"], + ["SP", "Salto Grande", "3545407"], + ["SP", "Sandovalina", "3545506"], + ["SP", "Santa Ad\u{e9}lia", "3545605"], + ["SP", "Santa Albertina", "3545704"], + ["SP", "Santa B\u{e1}rbara d'Oeste", "3545803"], + ["SP", "Santa Branca", "3546009"], + ["SP", "Santa Clara d'Oeste", "3546108"], + ["SP", "Santa Cruz da Concei\u{e7}\u{e3}o", "3546207"], + ["SP", "Santa Cruz da Esperan\u{e7}a", "3546256"], + ["SP", "Santa Cruz das Palmeiras", "3546306"], + ["SP", "Santa Cruz do Rio Pardo", "3546405"], + ["SP", "Santa Ernestina", "3546504"], + ["SP", "Santa F\u{e9} do Sul", "3546603"], + ["SP", "Santa Gertrudes", "3546702"], + ["SP", "Santa Isabel", "3546801"], + ["SP", "Santa L\u{fa}cia", "3546900"], + ["SP", "Santa Maria da Serra", "3547007"], + ["SP", "Santa Mercedes", "3547106"], + ["SP", "Santa Rita d'Oeste", "3547403"], + ["SP", "Santa Rita do Passa Quatro", "3547502"], + ["SP", "Santa Rosa de Viterbo", "3547601"], + ["SP", "Santa Salete", "3547650"], + ["SP", "Santana da Ponte Pensa", "3547205"], + ["SP", "Santana de Parna\u{ed}ba", "3547304"], + ["SP", "Santo Anast\u{e1}cio", "3547700"], + ["SP", "Santo Andr\u{e9}", "3547809"], + ["SP", "Santo Ant\u{f4}nio da Alegria", "3547908"], + ["SP", "Santo Ant\u{f4}nio de Posse", "3548005"], + ["SP", "Santo Ant\u{f4}nio do Aracangu\u{e1}", "3548054"], + ["SP", "Santo Ant\u{f4}nio do Jardim", "3548104"], + ["SP", "Santo Ant\u{f4}nio do Pinhal", "3548203"], + ["SP", "Santo Expedito", "3548302"], + ["SP", "Sant\u{f3}polis do Aguape\u{ed}", "3548401"], + ["SP", "Santos", "3548500"], + ["SP", "S\u{e3}o Bento do Sapuca\u{ed}", "3548609"], + ["SP", "S\u{e3}o Bernardo do Campo", "3548708"], + ["SP", "S\u{e3}o Caetano do Sul", "3548807"], + ["SP", "S\u{e3}o Carlos", "3548906"], + ["SP", "S\u{e3}o Francisco", "3549003"], + ["SP", "S\u{e3}o Jo\u{e3}o da Boa Vista", "3549102"], + ["SP", "S\u{e3}o Jo\u{e3}o das Duas Pontes", "3549201"], + ["SP", "S\u{e3}o Jo\u{e3}o de Iracema", "3549250"], + ["SP", "S\u{e3}o Jo\u{e3}o do Pau d'Alho", "3549300"], + ["SP", "S\u{e3}o Joaquim da Barra", "3549409"], + ["SP", "S\u{e3}o Jos\u{e9} da Bela Vista", "3549508"], + ["SP", "S\u{e3}o Jos\u{e9} do Barreiro", "3549607"], + ["SP", "S\u{e3}o Jos\u{e9} do Rio Pardo", "3549706"], + ["SP", "S\u{e3}o Jos\u{e9} do Rio Preto", "3549805"], + ["SP", "S\u{e3}o Jos\u{e9} dos Campos", "3549904"], + ["SP", "S\u{e3}o Louren\u{e7}o da Serra", "3549953"], + ["SP", "S\u{e3}o Luiz do Paraitinga", "3550001"], + ["SP", "S\u{e3}o Manuel", "3550100"], + ["SP", "S\u{e3}o Miguel Arcanjo", "3550209"], + ["SP", "S\u{e3}o Paulo", "3550308"], + ["SP", "S\u{e3}o Pedro", "3550407"], + ["SP", "S\u{e3}o Pedro do Turvo", "3550506"], + ["SP", "S\u{e3}o Roque", "3550605"], + ["SP", "S\u{e3}o Sebasti\u{e3}o", "3550704"], + ["SP", "S\u{e3}o Sebasti\u{e3}o da Grama", "3550803"], + ["SP", "S\u{e3}o Sim\u{e3}o", "3550902"], + ["SP", "S\u{e3}o Vicente", "3551009"], + ["SP", "Sarapu\u{ed}", "3551108"], + ["SP", "Sarutai\u{e1}", "3551207"], + ["SP", "Sebastian\u{f3}polis do Sul", "3551306"], + ["SP", "Serra Azul", "3551405"], + ["SP", "Serra Negra", "3551603"], + ["SP", "Serrana", "3551504"], + ["SP", "Sert\u{e3}ozinho", "3551702"], + ["SP", "Sete Barras", "3551801"], + ["SP", "Sever\u{ed}nia", "3551900"], + ["SP", "Silveiras", "3552007"], + ["SP", "Socorro", "3552106"], + ["SP", "Sorocaba", "3552205"], + ["SP", "Sud Mennucci", "3552304"], + ["SP", "Sumar\u{e9}", "3552403"], + ["SP", "Suzan\u{e1}polis", "3552551"], + ["SP", "Suzano", "3552502"], + ["SP", "Tabapu\u{e3}", "3552601"], + ["SP", "Tabatinga", "3552700"], + ["SP", "Tabo\u{e3}o da Serra", "3552809"], + ["SP", "Taciba", "3552908"], + ["SP", "Tagua\u{ed}", "3553005"], + ["SP", "Taia\u{e7}u", "3553104"], + ["SP", "Tai\u{fa}va", "3553203"], + ["SP", "Tamba\u{fa}", "3553302"], + ["SP", "Tanabi", "3553401"], + ["SP", "Tapira\u{ed}", "3553500"], + ["SP", "Tapiratiba", "3553609"], + ["SP", "Taquaral", "3553658"], + ["SP", "Taquaritinga", "3553708"], + ["SP", "Taquarituba", "3553807"], + ["SP", "Taquariva\u{ed}", "3553856"], + ["SP", "Tarabai", "3553906"], + ["SP", "Tarum\u{e3}", "3553955"], + ["SP", "Tatu\u{ed}", "3554003"], + ["SP", "Taubat\u{e9}", "3554102"], + ["SP", "Tejup\u{e1}", "3554201"], + ["SP", "Teodoro Sampaio", "3554300"], + ["SP", "Terra Roxa", "3554409"], + ["SP", "Tiet\u{ea}", "3554508"], + ["SP", "Timburi", "3554607"], + ["SP", "Torre de Pedra", "3554656"], + ["SP", "Torrinha", "3554706"], + ["SP", "Trabiju", "3554755"], + ["SP", "Trememb\u{e9}", "3554805"], + ["SP", "Tr\u{ea}s Fronteiras", "3554904"], + ["SP", "Tuiuti", "3554953"], + ["SP", "Tup\u{e3}", "3555000"], + ["SP", "Tupi Paulista", "3555109"], + ["SP", "Turi\u{fa}ba", "3555208"], + ["SP", "Turmalina", "3555307"], + ["SP", "Ubarana", "3555356"], + ["SP", "Ubatuba", "3555406"], + ["SP", "Ubirajara", "3555505"], + ["SP", "Uchoa", "3555604"], + ["SP", "Uni\u{e3}o Paulista", "3555703"], + ["SP", "Ur\u{e2}nia", "3555802"], + ["SP", "Uru", "3555901"], + ["SP", "Urup\u{ea}s", "3556008"], + ["SP", "Valentim Gentil", "3556107"], + ["SP", "Valinhos", "3556206"], + ["SP", "Valpara\u{ed}so", "3556305"], + ["SP", "Vargem", "3556354"], + ["SP", "Vargem Grande do Sul", "3556404"], + ["SP", "Vargem Grande Paulista", "3556453"], + ["SP", "V\u{e1}rzea Paulista", "3556503"], + ["SP", "Vera Cruz", "3556602"], + ["SP", "Vinhedo", "3556701"], + ["SP", "Viradouro", "3556800"], + ["SP", "Vista Alegre do Alto", "3556909"], + ["SP", "Vit\u{f3}ria Brasil", "3556958"], + ["SP", "Votorantim", "3557006"], + ["SP", "Votuporanga", "3557105"], + ["SP", "Zacarias", "3557154"], + ["SE", "Amparo do S\u{e3}o Francisco", "2800100"], + ["SE", "Aquidab\u{e3}", "2800209"], + ["SE", "Aracaju", "2800308"], + ["SE", "Arau\u{e1}", "2800407"], + ["SE", "Areia Branca", "2800506"], + ["SE", "Barra dos Coqueiros", "2800605"], + ["SE", "Boquim", "2800670"], + ["SE", "Brejo Grande", "2800704"], + ["SE", "Campo do Brito", "2801009"], + ["SE", "Canhoba", "2801108"], + ["SE", "Canind\u{e9} de S\u{e3}o Francisco", "2801207"], + ["SE", "Capela", "2801306"], + ["SE", "Carira", "2801405"], + ["SE", "Carm\u{f3}polis", "2801504"], + ["SE", "Cedro de S\u{e3}o Jo\u{e3}o", "2801603"], + ["SE", "Cristin\u{e1}polis", "2801702"], + ["SE", "Cumbe", "2801900"], + ["SE", "Divina Pastora", "2802007"], + ["SE", "Est\u{e2}ncia", "2802106"], + ["SE", "Feira Nova", "2802205"], + ["SE", "Frei Paulo", "2802304"], + ["SE", "Gararu", "2802403"], + ["SE", "General Maynard", "2802502"], + ["SE", "Graccho Cardoso", "2802601"], + ["SE", "Ilha das Flores", "2802700"], + ["SE", "Indiaroba", "2802809"], + ["SE", "Itabaiana", "2802908"], + ["SE", "Itabaianinha", "2803005"], + ["SE", "Itabi", "2803104"], + ["SE", "Itaporanga d'Ajuda", "2803203"], + ["SE", "Japaratuba", "2803302"], + ["SE", "Japoat\u{e3}", "2803401"], + ["SE", "Lagarto", "2803500"], + ["SE", "Laranjeiras", "2803609"], + ["SE", "Macambira", "2803708"], + ["SE", "Malhada dos Bois", "2803807"], + ["SE", "Malhador", "2803906"], + ["SE", "Maruim", "2804003"], + ["SE", "Moita Bonita", "2804102"], + ["SE", "Monte Alegre de Sergipe", "2804201"], + ["SE", "Muribeca", "2804300"], + ["SE", "Ne\u{f3}polis", "2804409"], + ["SE", "Nossa Senhora Aparecida", "2804458"], + ["SE", "Nossa Senhora da Gl\u{f3}ria", "2804508"], + ["SE", "Nossa Senhora das Dores", "2804607"], + ["SE", "Nossa Senhora de Lourdes", "2804706"], + ["SE", "Nossa Senhora do Socorro", "2804805"], + ["SE", "Pacatuba", "2804904"], + ["SE", "Pedra Mole", "2805000"], + ["SE", "Pedrinhas", "2805109"], + ["SE", "Pinh\u{e3}o", "2805208"], + ["SE", "Pirambu", "2805307"], + ["SE", "Po\u{e7}o Redondo", "2805406"], + ["SE", "Po\u{e7}o Verde", "2805505"], + ["SE", "Porto da Folha", "2805604"], + ["SE", "Propri\u{e1}", "2805703"], + ["SE", "Riach\u{e3}o do Dantas", "2805802"], + ["SE", "Riachuelo", "2805901"], + ["SE", "Ribeir\u{f3}polis", "2806008"], + ["SE", "Ros\u{e1}rio do Catete", "2806107"], + ["SE", "Salgado", "2806206"], + ["SE", "Santa Luzia do Itanhy", "2806305"], + ["SE", "Santa Rosa de Lima", "2806503"], + ["SE", "Santana do S\u{e3}o Francisco", "2806404"], + ["SE", "Santo Amaro das Brotas", "2806602"], + ["SE", "S\u{e3}o Crist\u{f3}v\u{e3}o", "2806701"], + ["SE", "S\u{e3}o Domingos", "2806800"], + ["SE", "S\u{e3}o Francisco", "2806909"], + ["SE", "S\u{e3}o Miguel do Aleixo", "2807006"], + ["SE", "Sim\u{e3}o Dias", "2807105"], + ["SE", "Siriri", "2807204"], + ["SE", "Telha", "2807303"], + ["SE", "Tobias Barreto", "2807402"], + ["SE", "Tomar do Geru", "2807501"], + ["SE", "Umba\u{fa}ba", "2807600"], + ["TO", "Abreul\u{e2}ndia", "1700251"], + ["TO", "Aguiarn\u{f3}polis", "1700301"], + ["TO", "Alian\u{e7}a do Tocantins", "1700350"], + ["TO", "Almas", "1700400"], + ["TO", "Alvorada", "1700707"], + ["TO", "Anan\u{e1}s", "1701002"], + ["TO", "Angico", "1701051"], + ["TO", "Aparecida do Rio Negro", "1701101"], + ["TO", "Aragominas", "1701309"], + ["TO", "Araguacema", "1701903"], + ["TO", "Aragua\u{e7}u", "1702000"], + ["TO", "Aragua\u{ed}na", "1702109"], + ["TO", "Araguan\u{e3}", "1702158"], + ["TO", "Araguatins", "1702208"], + ["TO", "Arapoema", "1702307"], + ["TO", "Arraias", "1702406"], + ["TO", "Augustin\u{f3}polis", "1702554"], + ["TO", "Aurora do Tocantins", "1702703"], + ["TO", "Axix\u{e1} do Tocantins", "1702901"], + ["TO", "Baba\u{e7}ul\u{e2}ndia", "1703008"], + ["TO", "Bandeirantes do Tocantins", "1703057"], + ["TO", "Barra do Ouro", "1703073"], + ["TO", "Barrol\u{e2}ndia", "1703107"], + ["TO", "Bernardo Say\u{e3}o", "1703206"], + ["TO", "Bom Jesus do Tocantins", "1703305"], + ["TO", "Brasil\u{e2}ndia do Tocantins", "1703602"], + ["TO", "Brejinho de Nazar\u{e9}", "1703701"], + ["TO", "Buriti do Tocantins", "1703800"], + ["TO", "Cachoeirinha", "1703826"], + ["TO", "Campos Lindos", "1703842"], + ["TO", "Cariri do Tocantins", "1703867"], + ["TO", "Carmol\u{e2}ndia", "1703883"], + ["TO", "Carrasco Bonito", "1703891"], + ["TO", "Caseara", "1703909"], + ["TO", "Centen\u{e1}rio", "1704105"], + ["TO", "Chapada da Natividade", "1705102"], + ["TO", "Chapada de Areia", "1704600"], + ["TO", "Colinas do Tocantins", "1705508"], + ["TO", "Colm\u{e9}ia", "1716703"], + ["TO", "Combinado", "1705557"], + ["TO", "Concei\u{e7}\u{e3}o do Tocantins", "1705607"], + ["TO", "Couto Magalh\u{e3}es", "1706001"], + ["TO", "Cristal\u{e2}ndia", "1706100"], + ["TO", "Crix\u{e1}s do Tocantins", "1706258"], + ["TO", "Darcin\u{f3}polis", "1706506"], + ["TO", "Dian\u{f3}polis", "1707009"], + ["TO", "Divin\u{f3}polis do Tocantins", "1707108"], + ["TO", "Dois Irm\u{e3}os do Tocantins", "1707207"], + ["TO", "Duer\u{e9}", "1707306"], + ["TO", "Esperantina", "1707405"], + ["TO", "F\u{e1}tima", "1707553"], + ["TO", "Figueir\u{f3}polis", "1707652"], + ["TO", "Filad\u{e9}lfia", "1707702"], + ["TO", "Formoso do Araguaia", "1708205"], + ["TO", "Goianorte", "1708304"], + ["TO", "Goiatins", "1709005"], + ["TO", "Guara\u{ed}", "1709302"], + ["TO", "Gurupi", "1709500"], + ["TO", "Ipueiras", "1709807"], + ["TO", "Itacaj\u{e1}", "1710508"], + ["TO", "Itaguatins", "1710706"], + ["TO", "Itapiratins", "1710904"], + ["TO", "Itapor\u{e3} do Tocantins", "1711100"], + ["TO", "Ja\u{fa} do Tocantins", "1711506"], + ["TO", "Juarina", "1711803"], + ["TO", "Lagoa da Confus\u{e3}o", "1711902"], + ["TO", "Lagoa do Tocantins", "1711951"], + ["TO", "Lajeado", "1712009"], + ["TO", "Lavandeira", "1712157"], + ["TO", "Lizarda", "1712405"], + ["TO", "Luzin\u{f3}polis", "1712454"], + ["TO", "Marian\u{f3}polis do Tocantins", "1712504"], + ["TO", "Mateiros", "1712702"], + ["TO", "Mauril\u{e2}ndia do Tocantins", "1712801"], + ["TO", "Miracema do Tocantins", "1713205"], + ["TO", "Miranorte", "1713304"], + ["TO", "Monte do Carmo", "1713601"], + ["TO", "Monte Santo do Tocantins", "1713700"], + ["TO", "Muricil\u{e2}ndia", "1713957"], + ["TO", "Natividade", "1714203"], + ["TO", "Nazar\u{e9}", "1714302"], + ["TO", "Nova Olinda", "1714880"], + ["TO", "Nova Rosal\u{e2}ndia", "1715002"], + ["TO", "Novo Acordo", "1715101"], + ["TO", "Novo Alegre", "1715150"], + ["TO", "Novo Jardim", "1715259"], + ["TO", "Oliveira de F\u{e1}tima", "1715507"], + ["TO", "Palmas", "1721000"], + ["TO", "Palmeirante", "1715705"], + ["TO", "Palmeiras do Tocantins", "1713809"], + ["TO", "Palmeir\u{f3}polis", "1715754"], + ["TO", "Para\u{ed}so do Tocantins", "1716109"], + ["TO", "Paran\u{e3}", "1716208"], + ["TO", "Pau D'Arco", "1716307"], + ["TO", "Pedro Afonso", "1716505"], + ["TO", "Peixe", "1716604"], + ["TO", "Pequizeiro", "1716653"], + ["TO", "Pindorama do Tocantins", "1717008"], + ["TO", "Piraqu\u{ea}", "1717206"], + ["TO", "Pium", "1717503"], + ["TO", "Ponte Alta do Bom Jesus", "1717800"], + ["TO", "Ponte Alta do Tocantins", "1717909"], + ["TO", "Porto Alegre do Tocantins", "1718006"], + ["TO", "Porto Nacional", "1718204"], + ["TO", "Praia Norte", "1718303"], + ["TO", "Presidente Kennedy", "1718402"], + ["TO", "Pugmil", "1718451"], + ["TO", "Recursol\u{e2}ndia", "1718501"], + ["TO", "Riachinho", "1718550"], + ["TO", "Rio da Concei\u{e7}\u{e3}o", "1718659"], + ["TO", "Rio dos Bois", "1718709"], + ["TO", "Rio Sono", "1718758"], + ["TO", "Sampaio", "1718808"], + ["TO", "Sandol\u{e2}ndia", "1718840"], + ["TO", "Santa F\u{e9} do Araguaia", "1718865"], + ["TO", "Santa Maria do Tocantins", "1718881"], + ["TO", "Santa Rita do Tocantins", "1718899"], + ["TO", "Santa Rosa do Tocantins", "1718907"], + ["TO", "Santa Tereza do Tocantins", "1719004"], + ["TO", "Santa Terezinha do Tocantins", "1720002"], + ["TO", "S\u{e3}o Bento do Tocantins", "1720101"], + ["TO", "S\u{e3}o F\u{e9}lix do Tocantins", "1720150"], + ["TO", "S\u{e3}o Miguel do Tocantins", "1720200"], + ["TO", "S\u{e3}o Salvador do Tocantins", "1720259"], + ["TO", "S\u{e3}o Sebasti\u{e3}o do Tocantins", "1720309"], + ["TO", "S\u{e3}o Val\u{e9}rio", "1720499"], + ["TO", "Silvan\u{f3}polis", "1720655"], + ["TO", "S\u{ed}tio Novo do Tocantins", "1720804"], + ["TO", "Sucupira", "1720853"], + ["TO", "Taboc\u{e3}o", "1708254"], + ["TO", "Taguatinga", "1720903"], + ["TO", "Taipas do Tocantins", "1720937"], + ["TO", "Talism\u{e3}", "1720978"], + ["TO", "Tocant\u{ed}nia", "1721109"], + ["TO", "Tocantin\u{f3}polis", "1721208"], + ["TO", "Tupirama", "1721257"], + ["TO", "Tupiratins", "1721307"], + ["TO", "Wanderl\u{e2}ndia", "1722081"], + ["TO", "Xambio\u{e1}", "1722107"], + ], + [ + ["AC", [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21]], + ["AL", [22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123]], + ["AP", [124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139]], + ["AM", [140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201]], + ["BA", [202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, 443, 444, 445, 446, 447, 448, 449, 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, 495, 496, 497, 498, 499, 500, 501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, 519, 520, 521, 522, 523, 524, 525, 526, 527, 528, 529, 530, 531, 532, 533, 534, 535, 536, 537, 538, 539, 540, 541, 542, 543, 544, 545, 546, 547, 548, 549, 550, 551, 552, 553, 554, 555, 556, 557, 558, 559, 560, 561, 562, 563, 564, 565, 566, 567, 568, 569, 570, 571, 572, 573, 574, 575, 576, 577, 578, 579, 580, 581, 582, 583, 584, 585, 586, 587, 588, 589, 590, 591, 592, 593, 594, 595, 596, 597, 598, 599, 600, 601, 602, 603, 604, 605, 606, 607, 608, 609, 610, 611, 612, 613, 614, 615, 616, 617, 618]], + ["CE", [619, 620, 621, 622, 623, 624, 625, 626, 627, 628, 629, 630, 631, 632, 633, 634, 635, 636, 637, 638, 639, 640, 641, 642, 643, 644, 645, 646, 647, 648, 649, 650, 651, 652, 653, 654, 655, 656, 657, 658, 659, 660, 661, 662, 663, 664, 665, 666, 667, 668, 669, 670, 671, 672, 673, 674, 675, 676, 677, 678, 679, 680, 681, 682, 683, 684, 685, 686, 687, 688, 689, 690, 691, 692, 693, 694, 695, 696, 697, 698, 699, 700, 701, 702, 703, 704, 705, 706, 707, 708, 709, 710, 711, 712, 713, 714, 715, 716, 717, 718, 719, 720, 721, 722, 723, 724, 725, 726, 727, 728, 729, 730, 731, 732, 733, 734, 735, 736, 737, 738, 739, 740, 741, 742, 743, 744, 745, 746, 747, 748, 749, 750, 751, 752, 753, 754, 755, 756, 757, 758, 759, 760, 761, 762, 763, 764, 765, 766, 767, 768, 769, 770, 771, 772, 773, 774, 775, 776, 777, 778, 779, 780, 781, 782, 783, 784, 785, 786, 787, 788, 789, 790, 791, 792, 793, 794, 795, 796, 797, 798, 799, 800, 801, 802]], + ["DF", [803]], + ["ES", [804, 805, 806, 807, 808, 809, 810, 811, 812, 813, 814, 815, 816, 817, 818, 819, 820, 821, 822, 823, 824, 825, 826, 827, 828, 829, 830, 831, 832, 833, 834, 835, 836, 837, 838, 839, 840, 841, 842, 843, 844, 845, 846, 847, 848, 849, 850, 851, 852, 853, 854, 855, 856, 857, 858, 859, 860, 861, 862, 863, 864, 865, 866, 867, 868, 869, 870, 871, 872, 873, 874, 875, 876, 877, 878, 879, 880, 881]], + ["GO", [882, 883, 884, 885, 886, 887, 888, 889, 890, 891, 892, 893, 894, 895, 896, 897, 898, 899, 900, 901, 902, 903, 904, 905, 906, 907, 908, 909, 910, 911, 912, 913, 914, 915, 916, 917, 918, 919, 920, 921, 922, 923, 924, 925, 926, 927, 928, 929, 930, 931, 932, 933, 934, 935, 936, 937, 938, 939, 940, 941, 942, 943, 944, 945, 946, 947, 948, 949, 950, 951, 952, 953, 954, 955, 956, 957, 958, 959, 960, 961, 962, 963, 964, 965, 966, 967, 968, 969, 970, 971, 972, 973, 974, 975, 976, 977, 978, 979, 980, 981, 982, 983, 984, 985, 986, 987, 988, 989, 990, 991, 992, 993, 994, 995, 996, 997, 998, 999, 1000, 1001, 1002, 1003, 1004, 1005, 1006, 1007, 1008, 1009, 1010, 1011, 1012, 1013, 1014, 1015, 1016, 1017, 1018, 1019, 1020, 1021, 1022, 1023, 1024, 1025, 1026, 1027, 1028, 1029, 1030, 1031, 1032, 1033, 1034, 1035, 1036, 1037, 1038, 1039, 1040, 1041, 1042, 1043, 1044, 1045, 1046, 1047, 1048, 1049, 1050, 1051, 1052, 1053, 1054, 1055, 1056, 1057, 1058, 1059, 1060, 1061, 1062, 1063, 1064, 1065, 1066, 1067, 1068, 1069, 1070, 1071, 1072, 1073, 1074, 1075, 1076, 1077, 1078, 1079, 1080, 1081, 1082, 1083, 1084, 1085, 1086, 1087, 1088, 1089, 1090, 1091, 1092, 1093, 1094, 1095, 1096, 1097, 1098, 1099, 1100, 1101, 1102, 1103, 1104, 1105, 1106, 1107, 1108, 1109, 1110, 1111, 1112, 1113, 1114, 1115, 1116, 1117, 1118, 1119, 1120, 1121, 1122, 1123, 1124, 1125, 1126, 1127]], + ["MA", [1128, 1129, 1130, 1131, 1132, 1133, 1134, 1135, 1136, 1137, 1138, 1139, 1140, 1141, 1142, 1143, 1144, 1145, 1146, 1147, 1148, 1149, 1150, 1151, 1152, 1153, 1154, 1155, 1156, 1157, 1158, 1159, 1160, 1161, 1162, 1163, 1164, 1165, 1166, 1167, 1168, 1169, 1170, 1171, 1172, 1173, 1174, 1175, 1176, 1177, 1178, 1179, 1180, 1181, 1182, 1183, 1184, 1185, 1186, 1187, 1188, 1189, 1190, 1191, 1192, 1193, 1194, 1195, 1196, 1197, 1198, 1199, 1200, 1201, 1202, 1203, 1204, 1205, 1206, 1207, 1208, 1209, 1210, 1211, 1212, 1213, 1214, 1215, 1216, 1217, 1218, 1219, 1220, 1221, 1222, 1223, 1224, 1225, 1226, 1227, 1228, 1229, 1230, 1231, 1232, 1233, 1234, 1235, 1236, 1237, 1238, 1239, 1240, 1241, 1242, 1243, 1244, 1245, 1246, 1247, 1248, 1249, 1250, 1251, 1252, 1253, 1254, 1255, 1256, 1257, 1258, 1259, 1260, 1261, 1262, 1263, 1264, 1265, 1266, 1267, 1268, 1269, 1270, 1271, 1272, 1273, 1274, 1275, 1276, 1277, 1278, 1279, 1280, 1281, 1282, 1283, 1284, 1285, 1286, 1287, 1288, 1289, 1290, 1291, 1292, 1293, 1294, 1295, 1296, 1297, 1298, 1299, 1300, 1301, 1302, 1303, 1304, 1305, 1306, 1307, 1308, 1309, 1310, 1311, 1312, 1313, 1314, 1315, 1316, 1317, 1318, 1319, 1320, 1321, 1322, 1323, 1324, 1325, 1326, 1327, 1328, 1329, 1330, 1331, 1332, 1333, 1334, 1335, 1336, 1337, 1338, 1339, 1340, 1341, 1342, 1343, 1344]], + ["MT", [1345, 1346, 1347, 1348, 1349, 1350, 1351, 1352, 1353, 1354, 1355, 1356, 1357, 1358, 1359, 1360, 1361, 1362, 1363, 1364, 1365, 1366, 1367, 1368, 1369, 1370, 1371, 1372, 1373, 1374, 1375, 1376, 1377, 1378, 1379, 1380, 1381, 1382, 1383, 1384, 1385, 1386, 1387, 1388, 1389, 1390, 1391, 1392, 1393, 1394, 1395, 1396, 1397, 1398, 1399, 1400, 1401, 1402, 1403, 1404, 1405, 1406, 1407, 1408, 1409, 1410, 1411, 1412, 1413, 1414, 1415, 1416, 1417, 1418, 1419, 1420, 1421, 1422, 1423, 1424, 1425, 1426, 1427, 1428, 1429, 1430, 1431, 1432, 1433, 1434, 1435, 1436, 1437, 1438, 1439, 1440, 1441, 1442, 1443, 1444, 1445, 1446, 1447, 1448, 1449, 1450, 1451, 1452, 1453, 1454, 1455, 1456, 1457, 1458, 1459, 1460, 1461, 1462, 1463, 1464, 1465, 1466, 1467, 1468, 1469, 1470, 1471, 1472, 1473, 1474, 1475, 1476, 1477, 1478, 1479, 1480, 1481, 1482, 1483, 1484, 1485, 1486]], + ["MS", [1487, 1488, 1489, 1490, 1491, 1492, 1493, 1494, 1495, 1496, 1497, 1498, 1499, 1500, 1501, 1502, 1503, 1504, 1505, 1506, 1507, 1508, 1509, 1510, 1511, 1512, 1513, 1514, 1515, 1516, 1517, 1518, 1519, 1520, 1521, 1522, 1523, 1524, 1525, 1526, 1527, 1528, 1529, 1530, 1531, 1532, 1533, 1534, 1535, 1536, 1537, 1538, 1539, 1540, 1541, 1542, 1543, 1544, 1545, 1546, 1547, 1548, 1549, 1550, 1551, 1552, 1553, 1554, 1555, 1556, 1557, 1558, 1559, 1560, 1561, 1562, 1563, 1564, 1565]], + ["MG", [1566, 1567, 1568, 1569, 1570, 1571, 1572, 1573, 1574, 1575, 1576, 1577, 1578, 1579, 1580, 1581, 1582, 1583, 1584, 1585, 1586, 1587, 1588, 1589, 1590, 1591, 1592, 1593, 1594, 1595, 1596, 1597, 1598, 1599, 1600, 1601, 1602, 1603, 1604, 1605, 1606, 1607, 1608, 1609, 1610, 1611, 1612, 1613, 1614, 1615, 1616, 1617, 1618, 1619, 1620, 1621, 1622, 1623, 1624, 1625, 1626, 1627, 1628, 1629, 1630, 1631, 1632, 1633, 1634, 1635, 1636, 1637, 1638, 1639, 1640, 1641, 1642, 1643, 1644, 1645, 1646, 1647, 1648, 1649, 1650, 1651, 1652, 1653, 1654, 1655, 1656, 1657, 1658, 1659, 1660, 1661, 1662, 1663, 1664, 1665, 1666, 1667, 1668, 1669, 1670, 1671, 1672, 1673, 1674, 1675, 1676, 1677, 1678, 1679, 1680, 1681, 1682, 1683, 1684, 1685, 1686, 1687, 1688, 1689, 1690, 1691, 1692, 1693, 1694, 1695, 1696, 1697, 1698, 1699, 1700, 1701, 1702, 1703, 1704, 1705, 1706, 1707, 1708, 1709, 1710, 1711, 1712, 1713, 1714, 1715, 1716, 1717, 1718, 1719, 1720, 1721, 1722, 1723, 1724, 1725, 1726, 1727, 1728, 1729, 1730, 1731, 1732, 1733, 1734, 1735, 1736, 1737, 1738, 1739, 1740, 1741, 1742, 1743, 1744, 1745, 1746, 1747, 1748, 1749, 1750, 1751, 1752, 1753, 1754, 1755, 1756, 1757, 1758, 1759, 1760, 1761, 1762, 1763, 1764, 1765, 1766, 1767, 1768, 1769, 1770, 1771, 1772, 1773, 1774, 1775, 1776, 1777, 1778, 1779, 1780, 1781, 1782, 1783, 1784, 1785, 1786, 1787, 1788, 1789, 1790, 1791, 1792, 1793, 1794, 1795, 1796, 1797, 1798, 1799, 1800, 1801, 1802, 1803, 1804, 1805, 1806, 1807, 1808, 1809, 1810, 1811, 1812, 1813, 1814, 1815, 1816, 1817, 1818, 1819, 1820, 1821, 1822, 1823, 1824, 1825, 1826, 1827, 1828, 1829, 1830, 1831, 1832, 1833, 1834, 1835, 1836, 1837, 1838, 1839, 1840, 1841, 1842, 1843, 1844, 1845, 1846, 1847, 1848, 1849, 1850, 1851, 1852, 1853, 1854, 1855, 1856, 1857, 1858, 1859, 1860, 1861, 1862, 1863, 1864, 1865, 1866, 1867, 1868, 1869, 1870, 1871, 1872, 1873, 1874, 1875, 1876, 1877, 1878, 1879, 1880, 1881, 1882, 1883, 1884, 1885, 1886, 1887, 1888, 1889, 1890, 1891, 1892, 1893, 1894, 1895, 1896, 1897, 1898, 1899, 1900, 1901, 1902, 1903, 1904, 1905, 1906, 1907, 1908, 1909, 1910, 1911, 1912, 1913, 1914, 1915, 1916, 1917, 1918, 1919, 1920, 1921, 1922, 1923, 1924, 1925, 1926, 1927, 1928, 1929, 1930, 1931, 1932, 1933, 1934, 1935, 1936, 1937, 1938, 1939, 1940, 1941, 1942, 1943, 1944, 1945, 1946, 1947, 1948, 1949, 1950, 1951, 1952, 1953, 1954, 1955, 1956, 1957, 1958, 1959, 1960, 1961, 1962, 1963, 1964, 1965, 1966, 1967, 1968, 1969, 1970, 1971, 1972, 1973, 1974, 1975, 1976, 1977, 1978, 1979, 1980, 1981, 1982, 1983, 1984, 1985, 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020, 2021, 2022, 2023, 2024, 2025, 2026, 2027, 2028, 2029, 2030, 2031, 2032, 2033, 2034, 2035, 2036, 2037, 2038, 2039, 2040, 2041, 2042, 2043, 2044, 2045, 2046, 2047, 2048, 2049, 2050, 2051, 2052, 2053, 2054, 2055, 2056, 2057, 2058, 2059, 2060, 2061, 2062, 2063, 2064, 2065, 2066, 2067, 2068, 2069, 2070, 2071, 2072, 2073, 2074, 2075, 2076, 2077, 2078, 2079, 2080, 2081, 2082, 2083, 2084, 2085, 2086, 2087, 2088, 2089, 2090, 2091, 2092, 2093, 2094, 2095, 2096, 2097, 2098, 2099, 2100, 2101, 2102, 2103, 2104, 2105, 2106, 2107, 2108, 2109, 2110, 2111, 2112, 2113, 2114, 2115, 2116, 2117, 2118, 2119, 2120, 2121, 2122, 2123, 2124, 2125, 2126, 2127, 2128, 2129, 2130, 2131, 2132, 2133, 2134, 2135, 2136, 2137, 2138, 2139, 2140, 2141, 2142, 2143, 2144, 2145, 2146, 2147, 2148, 2149, 2150, 2151, 2152, 2153, 2154, 2155, 2156, 2157, 2158, 2159, 2160, 2161, 2162, 2163, 2164, 2165, 2166, 2167, 2168, 2169, 2170, 2171, 2172, 2173, 2174, 2175, 2176, 2177, 2178, 2179, 2180, 2181, 2182, 2183, 2184, 2185, 2186, 2187, 2188, 2189, 2190, 2191, 2192, 2193, 2194, 2195, 2196, 2197, 2198, 2199, 2200, 2201, 2202, 2203, 2204, 2205, 2206, 2207, 2208, 2209, 2210, 2211, 2212, 2213, 2214, 2215, 2216, 2217, 2218, 2219, 2220, 2221, 2222, 2223, 2224, 2225, 2226, 2227, 2228, 2229, 2230, 2231, 2232, 2233, 2234, 2235, 2236, 2237, 2238, 2239, 2240, 2241, 2242, 2243, 2244, 2245, 2246, 2247, 2248, 2249, 2250, 2251, 2252, 2253, 2254, 2255, 2256, 2257, 2258, 2259, 2260, 2261, 2262, 2263, 2264, 2265, 2266, 2267, 2268, 2269, 2270, 2271, 2272, 2273, 2274, 2275, 2276, 2277, 2278, 2279, 2280, 2281, 2282, 2283, 2284, 2285, 2286, 2287, 2288, 2289, 2290, 2291, 2292, 2293, 2294, 2295, 2296, 2297, 2298, 2299, 2300, 2301, 2302, 2303, 2304, 2305, 2306, 2307, 2308, 2309, 2310, 2311, 2312, 2313, 2314, 2315, 2316, 2317, 2318, 2319, 2320, 2321, 2322, 2323, 2324, 2325, 2326, 2327, 2328, 2329, 2330, 2331, 2332, 2333, 2334, 2335, 2336, 2337, 2338, 2339, 2340, 2341, 2342, 2343, 2344, 2345, 2346, 2347, 2348, 2349, 2350, 2351, 2352, 2353, 2354, 2355, 2356, 2357, 2358, 2359, 2360, 2361, 2362, 2363, 2364, 2365, 2366, 2367, 2368, 2369, 2370, 2371, 2372, 2373, 2374, 2375, 2376, 2377, 2378, 2379, 2380, 2381, 2382, 2383, 2384, 2385, 2386, 2387, 2388, 2389, 2390, 2391, 2392, 2393, 2394, 2395, 2396, 2397, 2398, 2399, 2400, 2401, 2402, 2403, 2404, 2405, 2406, 2407, 2408, 2409, 2410, 2411, 2412, 2413, 2414, 2415, 2416, 2417, 2418]], + ["PA", [2419, 2420, 2421, 2422, 2423, 2424, 2425, 2426, 2427, 2428, 2429, 2430, 2431, 2432, 2433, 2434, 2435, 2436, 2437, 2438, 2439, 2440, 2441, 2442, 2443, 2444, 2445, 2446, 2447, 2448, 2449, 2450, 2451, 2452, 2453, 2454, 2455, 2456, 2457, 2458, 2459, 2460, 2461, 2462, 2463, 2464, 2465, 2466, 2467, 2468, 2469, 2470, 2471, 2472, 2473, 2474, 2475, 2476, 2477, 2478, 2479, 2480, 2481, 2482, 2483, 2484, 2485, 2486, 2487, 2488, 2489, 2490, 2491, 2492, 2493, 2494, 2495, 2496, 2497, 2498, 2499, 2500, 2501, 2502, 2503, 2504, 2505, 2506, 2507, 2508, 2509, 2510, 2511, 2512, 2513, 2514, 2515, 2516, 2517, 2518, 2519, 2520, 2521, 2522, 2523, 2524, 2525, 2526, 2527, 2528, 2529, 2530, 2531, 2532, 2533, 2534, 2535, 2536, 2537, 2538, 2539, 2540, 2541, 2542, 2543, 2544, 2545, 2546, 2547, 2548, 2549, 2550, 2551, 2552, 2553, 2554, 2555, 2556, 2557, 2558, 2559, 2560, 2561, 2562]], + ["PB", [2563, 2564, 2565, 2566, 2567, 2568, 2569, 2570, 2571, 2572, 2573, 2574, 2575, 2576, 2577, 2578, 2579, 2580, 2581, 2582, 2583, 2584, 2585, 2586, 2587, 2588, 2589, 2590, 2591, 2592, 2593, 2594, 2595, 2596, 2597, 2598, 2599, 2600, 2601, 2602, 2603, 2604, 2605, 2606, 2607, 2608, 2609, 2610, 2611, 2612, 2613, 2614, 2615, 2616, 2617, 2618, 2619, 2620, 2621, 2622, 2623, 2624, 2625, 2626, 2627, 2628, 2629, 2630, 2631, 2632, 2633, 2634, 2635, 2636, 2637, 2638, 2639, 2640, 2641, 2642, 2643, 2644, 2645, 2646, 2647, 2648, 2649, 2650, 2651, 2652, 2653, 2654, 2655, 2656, 2657, 2658, 2659, 2660, 2661, 2662, 2663, 2664, 2665, 2666, 2667, 2668, 2669, 2670, 2671, 2672, 2673, 2674, 2675, 2676, 2677, 2678, 2679, 2680, 2681, 2682, 2683, 2684, 2685, 2686, 2687, 2688, 2689, 2690, 2691, 2692, 2693, 2694, 2695, 2696, 2697, 2698, 2699, 2700, 2701, 2702, 2703, 2704, 2705, 2706, 2707, 2708, 2709, 2710, 2711, 2712, 2713, 2714, 2715, 2716, 2717, 2718, 2719, 2720, 2721, 2722, 2723, 2724, 2725, 2726, 2727, 2728, 2729, 2730, 2731, 2732, 2733, 2734, 2735, 2736, 2737, 2738, 2739, 2740, 2741, 2742, 2743, 2744, 2745, 2746, 2747, 2748, 2749, 2750, 2751, 2752, 2753, 2754, 2755, 2756, 2757, 2758, 2759, 2760, 2761, 2762, 2763, 2764, 2765, 2766, 2767, 2768, 2769, 2770, 2771, 2772, 2773, 2774, 2775, 2776, 2777, 2778, 2779, 2780, 2781, 2782, 2783, 2784, 2785]], + ["PR", [2786, 2787, 2788, 2789, 2790, 2791, 2792, 2793, 2794, 2795, 2796, 2797, 2798, 2799, 2800, 2801, 2802, 2803, 2804, 2805, 2806, 2807, 2808, 2809, 2810, 2811, 2812, 2813, 2814, 2815, 2816, 2817, 2818, 2819, 2820, 2821, 2822, 2823, 2824, 2825, 2826, 2827, 2828, 2829, 2830, 2831, 2832, 2833, 2834, 2835, 2836, 2837, 2838, 2839, 2840, 2841, 2842, 2843, 2844, 2845, 2846, 2847, 2848, 2849, 2850, 2851, 2852, 2853, 2854, 2855, 2856, 2857, 2858, 2859, 2860, 2861, 2862, 2863, 2864, 2865, 2866, 2867, 2868, 2869, 2870, 2871, 2872, 2873, 2874, 2875, 2876, 2877, 2878, 2879, 2880, 2881, 2882, 2883, 2884, 2885, 2886, 2887, 2888, 2889, 2890, 2891, 2892, 2893, 2894, 2895, 2896, 2897, 2898, 2899, 2900, 2901, 2902, 2903, 2904, 2905, 2906, 2907, 2908, 2909, 2910, 2911, 2912, 2913, 2914, 2915, 2916, 2917, 2918, 2919, 2920, 2921, 2922, 2923, 2924, 2925, 2926, 2927, 2928, 2929, 2930, 2931, 2932, 2933, 2934, 2935, 2936, 2937, 2938, 2939, 2940, 2941, 2942, 2943, 2944, 2945, 2946, 2947, 2948, 2949, 2950, 2951, 2952, 2953, 2954, 2955, 2956, 2957, 2958, 2959, 2960, 2961, 2962, 2963, 2964, 2965, 2966, 2967, 2968, 2969, 2970, 2971, 2972, 2973, 2974, 2975, 2976, 2977, 2978, 2979, 2980, 2981, 2982, 2983, 2984, 2985, 2986, 2987, 2988, 2989, 2990, 2991, 2992, 2993, 2994, 2995, 2996, 2997, 2998, 2999, 3000, 3001, 3002, 3003, 3004, 3005, 3006, 3007, 3008, 3009, 3010, 3011, 3012, 3013, 3014, 3015, 3016, 3017, 3018, 3019, 3020, 3021, 3022, 3023, 3024, 3025, 3026, 3027, 3028, 3029, 3030, 3031, 3032, 3033, 3034, 3035, 3036, 3037, 3038, 3039, 3040, 3041, 3042, 3043, 3044, 3045, 3046, 3047, 3048, 3049, 3050, 3051, 3052, 3053, 3054, 3055, 3056, 3057, 3058, 3059, 3060, 3061, 3062, 3063, 3064, 3065, 3066, 3067, 3068, 3069, 3070, 3071, 3072, 3073, 3074, 3075, 3076, 3077, 3078, 3079, 3080, 3081, 3082, 3083, 3084, 3085, 3086, 3087, 3088, 3089, 3090, 3091, 3092, 3093, 3094, 3095, 3096, 3097, 3098, 3099, 3100, 3101, 3102, 3103, 3104, 3105, 3106, 3107, 3108, 3109, 3110, 3111, 3112, 3113, 3114, 3115, 3116, 3117, 3118, 3119, 3120, 3121, 3122, 3123, 3124, 3125, 3126, 3127, 3128, 3129, 3130, 3131, 3132, 3133, 3134, 3135, 3136, 3137, 3138, 3139, 3140, 3141, 3142, 3143, 3144, 3145, 3146, 3147, 3148, 3149, 3150, 3151, 3152, 3153, 3154, 3155, 3156, 3157, 3158, 3159, 3160, 3161, 3162, 3163, 3164, 3165, 3166, 3167, 3168, 3169, 3170, 3171, 3172, 3173, 3174, 3175, 3176, 3177, 3178, 3179, 3180, 3181, 3182, 3183, 3184]], + ["PE", [3185, 3186, 3187, 3188, 3189, 3190, 3191, 3192, 3193, 3194, 3195, 3196, 3197, 3198, 3199, 3200, 3201, 3202, 3203, 3204, 3205, 3206, 3207, 3208, 3209, 3210, 3211, 3212, 3213, 3214, 3215, 3216, 3217, 3218, 3219, 3220, 3221, 3222, 3223, 3224, 3225, 3226, 3227, 3228, 3229, 3230, 3231, 3232, 3233, 3234, 3235, 3236, 3237, 3238, 3239, 3240, 3241, 3242, 3243, 3244, 3245, 3246, 3247, 3248, 3249, 3250, 3251, 3252, 3253, 3254, 3255, 3256, 3257, 3258, 3259, 3260, 3261, 3262, 3263, 3264, 3265, 3266, 3267, 3268, 3269, 3270, 3271, 3272, 3273, 3274, 3275, 3276, 3277, 3278, 3279, 3280, 3281, 3282, 3283, 3284, 3285, 3286, 3287, 3288, 3289, 3290, 3291, 3292, 3293, 3294, 3295, 3296, 3297, 3298, 3299, 3300, 3301, 3302, 3303, 3304, 3305, 3306, 3307, 3308, 3309, 3310, 3311, 3312, 3313, 3314, 3315, 3316, 3317, 3318, 3319, 3320, 3321, 3322, 3323, 3324, 3325, 3326, 3327, 3328, 3329, 3330, 3331, 3332, 3333, 3334, 3335, 3336, 3337, 3338, 3339, 3340, 3341, 3342, 3343, 3344, 3345, 3346, 3347, 3348, 3349, 3350, 3351, 3352, 3353, 3354, 3355, 3356, 3357, 3358, 3359, 3360, 3361, 3362, 3363, 3364, 3365, 3366, 3367, 3368, 3369]], + ["PI", [3370, 3371, 3372, 3373, 3374, 3375, 3376, 3377, 3378, 3379, 3380, 3381, 3382, 3383, 3384, 3385, 3386, 3387, 3388, 3389, 3390, 3391, 3392, 3393, 3394, 3395, 3396, 3397, 3398, 3399, 3400, 3401, 3402, 3403, 3404, 3405, 3406, 3407, 3408, 3409, 3410, 3411, 3412, 3413, 3414, 3415, 3416, 3417, 3418, 3419, 3420, 3421, 3422, 3423, 3424, 3425, 3426, 3427, 3428, 3429, 3430, 3431, 3432, 3433, 3434, 3435, 3436, 3437, 3438, 3439, 3440, 3441, 3442, 3443, 3444, 3445, 3446, 3447, 3448, 3449, 3450, 3451, 3452, 3453, 3454, 3455, 3456, 3457, 3458, 3459, 3460, 3461, 3462, 3463, 3464, 3465, 3466, 3467, 3468, 3469, 3470, 3471, 3472, 3473, 3474, 3475, 3476, 3477, 3478, 3479, 3480, 3481, 3482, 3483, 3484, 3485, 3486, 3487, 3488, 3489, 3490, 3491, 3492, 3493, 3494, 3495, 3496, 3497, 3498, 3499, 3500, 3501, 3502, 3503, 3504, 3505, 3506, 3507, 3508, 3509, 3510, 3511, 3512, 3513, 3514, 3515, 3516, 3517, 3518, 3519, 3520, 3521, 3522, 3523, 3524, 3525, 3526, 3527, 3528, 3529, 3530, 3531, 3532, 3533, 3534, 3535, 3536, 3537, 3538, 3539, 3540, 3541, 3542, 3543, 3544, 3545, 3546, 3547, 3548, 3549, 3550, 3551, 3552, 3553, 3554, 3555, 3556, 3557, 3558, 3559, 3560, 3561, 3562, 3563, 3564, 3565, 3566, 3567, 3568, 3569, 3570, 3571, 3572, 3573, 3574, 3575, 3576, 3577, 3578, 3579, 3580, 3581, 3582, 3583, 3584, 3585, 3586, 3587, 3588, 3589, 3590, 3591, 3592, 3593]], + ["RJ", [3594, 3595, 3596, 3597, 3598, 3599, 3600, 3601, 3602, 3603, 3604, 3605, 3606, 3607, 3608, 3609, 3610, 3611, 3612, 3613, 3614, 3615, 3616, 3617, 3618, 3619, 3620, 3621, 3622, 3623, 3624, 3625, 3626, 3627, 3628, 3629, 3630, 3631, 3632, 3633, 3634, 3635, 3636, 3637, 3638, 3639, 3640, 3641, 3642, 3643, 3644, 3645, 3646, 3647, 3648, 3649, 3650, 3651, 3652, 3653, 3654, 3655, 3656, 3657, 3658, 3659, 3660, 3661, 3662, 3663, 3664, 3665, 3666, 3667, 3668, 3669, 3670, 3671, 3672, 3673, 3674, 3675, 3676, 3677, 3678, 3679, 3680, 3681, 3682, 3683, 3684, 3685]], + ["RN", [3686, 3687, 3688, 3689, 3690, 3691, 3692, 3693, 3694, 3695, 3696, 3697, 3698, 3699, 3700, 3701, 3702, 3703, 3704, 3705, 3706, 3707, 3708, 3709, 3710, 3711, 3712, 3713, 3714, 3715, 3716, 3717, 3718, 3719, 3720, 3721, 3722, 3723, 3724, 3725, 3726, 3727, 3728, 3729, 3730, 3731, 3732, 3733, 3734, 3735, 3736, 3737, 3738, 3739, 3740, 3741, 3742, 3743, 3744, 3745, 3746, 3747, 3748, 3749, 3750, 3751, 3752, 3753, 3754, 3755, 3756, 3757, 3758, 3759, 3760, 3761, 3762, 3763, 3764, 3765, 3766, 3767, 3768, 3769, 3770, 3771, 3772, 3773, 3774, 3775, 3776, 3777, 3778, 3779, 3780, 3781, 3782, 3783, 3784, 3785, 3786, 3787, 3788, 3789, 3790, 3791, 3792, 3793, 3794, 3795, 3796, 3797, 3798, 3799, 3800, 3801, 3802, 3803, 3804, 3805, 3806, 3807, 3808, 3809, 3810, 3811, 3812, 3813, 3814, 3815, 3816, 3817, 3818, 3819, 3820, 3821, 3822, 3823, 3824, 3825, 3826, 3827, 3828, 3829, 3830, 3831, 3832, 3833, 3834, 3835, 3836, 3837, 3838, 3839, 3840, 3841, 3842, 3843, 3844, 3845, 3846, 3847, 3848, 3849, 3850, 3851, 3852]], + ["RS", [3853, 3854, 3855, 3856, 3857, 3858, 3859, 3860, 3861, 3862, 3863, 3864, 3865, 3866, 3867, 3868, 3869, 3870, 3871, 3872, 3873, 3874, 3875, 3876, 3877, 3878, 3879, 3880, 3881, 3882, 3883, 3884, 3885, 3886, 3887, 3888, 3889, 3890, 3891, 3892, 3893, 3894, 3895, 3896, 3897, 3898, 3899, 3900, 3901, 3902, 3903, 3904, 3905, 3906, 3907, 3908, 3909, 3910, 3911, 3912, 3913, 3914, 3915, 3916, 3917, 3918, 3919, 3920, 3921, 3922, 3923, 3924, 3925, 3926, 3927, 3928, 3929, 3930, 3931, 3932, 3933, 3934, 3935, 3936, 3937, 3938, 3939, 3940, 3941, 3942, 3943, 3944, 3945, 3946, 3947, 3948, 3949, 3950, 3951, 3952, 3953, 3954, 3955, 3956, 3957, 3958, 3959, 3960, 3961, 3962, 3963, 3964, 3965, 3966, 3967, 3968, 3969, 3970, 3971, 3972, 3973, 3974, 3975, 3976, 3977, 3978, 3979, 3980, 3981, 3982, 3983, 3984, 3985, 3986, 3987, 3988, 3989, 3990, 3991, 3992, 3993, 3994, 3995, 3996, 3997, 3998, 3999, 4000, 4001, 4002, 4003, 4004, 4005, 4006, 4007, 4008, 4009, 4010, 4011, 4012, 4013, 4014, 4015, 4016, 4017, 4018, 4019, 4020, 4021, 4022, 4023, 4024, 4025, 4026, 4027, 4028, 4029, 4030, 4031, 4032, 4033, 4034, 4035, 4036, 4037, 4038, 4039, 4040, 4041, 4042, 4043, 4044, 4045, 4046, 4047, 4048, 4049, 4050, 4051, 4052, 4053, 4054, 4055, 4056, 4057, 4058, 4059, 4060, 4061, 4062, 4063, 4064, 4065, 4066, 4067, 4068, 4069, 4070, 4071, 4072, 4073, 4074, 4075, 4076, 4077, 4078, 4079, 4080, 4081, 4082, 4083, 4084, 4085, 4086, 4087, 4088, 4089, 4090, 4091, 4092, 4093, 4094, 4095, 4096, 4097, 4098, 4099, 4100, 4101, 4102, 4103, 4104, 4105, 4106, 4107, 4108, 4109, 4110, 4111, 4112, 4113, 4114, 4115, 4116, 4117, 4118, 4119, 4120, 4121, 4122, 4123, 4124, 4125, 4126, 4127, 4128, 4129, 4130, 4131, 4132, 4133, 4134, 4135, 4136, 4137, 4138, 4139, 4140, 4141, 4142, 4143, 4144, 4145, 4146, 4147, 4148, 4149, 4150, 4151, 4152, 4153, 4154, 4155, 4156, 4157, 4158, 4159, 4160, 4161, 4162, 4163, 4164, 4165, 4166, 4167, 4168, 4169, 4170, 4171, 4172, 4173, 4174, 4175, 4176, 4177, 4178, 4179, 4180, 4181, 4182, 4183, 4184, 4185, 4186, 4187, 4188, 4189, 4190, 4191, 4192, 4193, 4194, 4195, 4196, 4197, 4198, 4199, 4200, 4201, 4202, 4203, 4204, 4205, 4206, 4207, 4208, 4209, 4210, 4211, 4212, 4213, 4214, 4215, 4216, 4217, 4218, 4219, 4220, 4221, 4222, 4223, 4224, 4225, 4226, 4227, 4228, 4229, 4230, 4231, 4232, 4233, 4234, 4235, 4236, 4237, 4238, 4239, 4240, 4241, 4242, 4243, 4244, 4245, 4246, 4247, 4248, 4249, 4250, 4251, 4252, 4253, 4254, 4255, 4256, 4257, 4258, 4259, 4260, 4261, 4262, 4263, 4264, 4265, 4266, 4267, 4268, 4269, 4270, 4271, 4272, 4273, 4274, 4275, 4276, 4277, 4278, 4279, 4280, 4281, 4282, 4283, 4284, 4285, 4286, 4287, 4288, 4289, 4290, 4291, 4292, 4293, 4294, 4295, 4296, 4297, 4298, 4299, 4300, 4301, 4302, 4303, 4304, 4305, 4306, 4307, 4308, 4309, 4310, 4311, 4312, 4313, 4314, 4315, 4316, 4317, 4318, 4319, 4320, 4321, 4322, 4323, 4324, 4325, 4326, 4327, 4328, 4329, 4330, 4331, 4332, 4333, 4334, 4335, 4336, 4337, 4338, 4339, 4340, 4341, 4342, 4343, 4344, 4345, 4346, 4347, 4348, 4349]], + ["RO", [4350, 4351, 4352, 4353, 4354, 4355, 4356, 4357, 4358, 4359, 4360, 4361, 4362, 4363, 4364, 4365, 4366, 4367, 4368, 4369, 4370, 4371, 4372, 4373, 4374, 4375, 4376, 4377, 4378, 4379, 4380, 4381, 4382, 4383, 4384, 4385, 4386, 4387, 4388, 4389, 4390, 4391, 4392, 4393, 4394, 4395, 4396, 4397, 4398, 4399, 4400, 4401]], + ["RR", [4402, 4403, 4404, 4405, 4406, 4407, 4408, 4409, 4410, 4411, 4412, 4413, 4414, 4415, 4416]], + ["SC", [4417, 4418, 4419, 4420, 4421, 4422, 4423, 4424, 4425, 4426, 4427, 4428, 4429, 4430, 4431, 4432, 4433, 4434, 4435, 4436, 4437, 4438, 4439, 4440, 4441, 4442, 4443, 4444, 4445, 4446, 4447, 4448, 4449, 4450, 4451, 4452, 4453, 4454, 4455, 4456, 4457, 4458, 4459, 4460, 4461, 4462, 4463, 4464, 4465, 4466, 4467, 4468, 4469, 4470, 4471, 4472, 4473, 4474, 4475, 4476, 4477, 4478, 4479, 4480, 4481, 4482, 4483, 4484, 4485, 4486, 4487, 4488, 4489, 4490, 4491, 4492, 4493, 4494, 4495, 4496, 4497, 4498, 4499, 4500, 4501, 4502, 4503, 4504, 4505, 4506, 4507, 4508, 4509, 4510, 4511, 4512, 4513, 4514, 4515, 4516, 4517, 4518, 4519, 4520, 4521, 4522, 4523, 4524, 4525, 4526, 4527, 4528, 4529, 4530, 4531, 4532, 4533, 4534, 4535, 4536, 4537, 4538, 4539, 4540, 4541, 4542, 4543, 4544, 4545, 4546, 4547, 4548, 4549, 4550, 4551, 4552, 4553, 4554, 4555, 4556, 4557, 4558, 4559, 4560, 4561, 4562, 4563, 4564, 4565, 4566, 4567, 4568, 4569, 4570, 4571, 4572, 4573, 4574, 4575, 4576, 4577, 4578, 4579, 4580, 4581, 4582, 4583, 4584, 4585, 4586, 4587, 4588, 4589, 4590, 4591, 4592, 4593, 4594, 4595, 4596, 4597, 4598, 4599, 4600, 4601, 4602, 4603, 4604, 4605, 4606, 4607, 4608, 4609, 4610, 4611, 4612, 4613, 4614, 4615, 4616, 4617, 4618, 4619, 4620, 4621, 4622, 4623, 4624, 4625, 4626, 4627, 4628, 4629, 4630, 4631, 4632, 4633, 4634, 4635, 4636, 4637, 4638, 4639, 4640, 4641, 4642, 4643, 4644, 4645, 4646, 4647, 4648, 4649, 4650, 4651, 4652, 4653, 4654, 4655, 4656, 4657, 4658, 4659, 4660, 4661, 4662, 4663, 4664, 4665, 4666, 4667, 4668, 4669, 4670, 4671, 4672, 4673, 4674, 4675, 4676, 4677, 4678, 4679, 4680, 4681, 4682, 4683, 4684, 4685, 4686, 4687, 4688, 4689, 4690, 4691, 4692, 4693, 4694, 4695, 4696, 4697, 4698, 4699, 4700, 4701, 4702, 4703, 4704, 4705, 4706, 4707, 4708, 4709, 4710, 4711]], + ["SP", [4712, 4713, 4714, 4715, 4716, 4717, 4718, 4719, 4720, 4721, 4722, 4723, 4724, 4725, 4726, 4727, 4728, 4729, 4730, 4731, 4732, 4733, 4734, 4735, 4736, 4737, 4738, 4739, 4740, 4741, 4742, 4743, 4744, 4745, 4746, 4747, 4748, 4749, 4750, 4751, 4752, 4753, 4754, 4755, 4756, 4757, 4758, 4759, 4760, 4761, 4762, 4763, 4764, 4765, 4766, 4767, 4768, 4769, 4770, 4771, 4772, 4773, 4774, 4775, 4776, 4777, 4778, 4779, 4780, 4781, 4782, 4783, 4784, 4785, 4786, 4787, 4788, 4789, 4790, 4791, 4792, 4793, 4794, 4795, 4796, 4797, 4798, 4799, 4800, 4801, 4802, 4803, 4804, 4805, 4806, 4807, 4808, 4809, 4810, 4811, 4812, 4813, 4814, 4815, 4816, 4817, 4818, 4819, 4820, 4821, 4822, 4823, 4824, 4825, 4826, 4827, 4828, 4829, 4830, 4831, 4832, 4833, 4834, 4835, 4836, 4837, 4838, 4839, 4840, 4841, 4842, 4843, 4844, 4845, 4846, 4847, 4848, 4849, 4850, 4851, 4852, 4853, 4854, 4855, 4856, 4857, 4858, 4859, 4860, 4861, 4862, 4863, 4864, 4865, 4866, 4867, 4868, 4869, 4870, 4871, 4872, 4873, 4874, 4875, 4876, 4877, 4878, 4879, 4880, 4881, 4882, 4883, 4884, 4885, 4886, 4887, 4888, 4889, 4890, 4891, 4892, 4893, 4894, 4895, 4896, 4897, 4898, 4899, 4900, 4901, 4902, 4903, 4904, 4905, 4906, 4907, 4908, 4909, 4910, 4911, 4912, 4913, 4914, 4915, 4916, 4917, 4918, 4919, 4920, 4921, 4922, 4923, 4924, 4925, 4926, 4927, 4928, 4929, 4930, 4931, 4932, 4933, 4934, 4935, 4936, 4937, 4938, 4939, 4940, 4941, 4942, 4943, 4944, 4945, 4946, 4947, 4948, 4949, 4950, 4951, 4952, 4953, 4954, 4955, 4956, 4957, 4958, 4959, 4960, 4961, 4962, 4963, 4964, 4965, 4966, 4967, 4968, 4969, 4970, 4971, 4972, 4973, 4974, 4975, 4976, 4977, 4978, 4979, 4980, 4981, 4982, 4983, 4984, 4985, 4986, 4987, 4988, 4989, 4990, 4991, 4992, 4993, 4994, 4995, 4996, 4997, 4998, 4999, 5000, 5001, 5002, 5003, 5004, 5005, 5006, 5007, 5008, 5009, 5010, 5011, 5012, 5013, 5014, 5015, 5016, 5017, 5018, 5019, 5020, 5021, 5022, 5023, 5024, 5025, 5026, 5027, 5028, 5029, 5030, 5031, 5032, 5033, 5034, 5035, 5036, 5037, 5038, 5039, 5040, 5041, 5042, 5043, 5044, 5045, 5046, 5047, 5048, 5049, 5050, 5051, 5052, 5053, 5054, 5055, 5056, 5057, 5058, 5059, 5060, 5061, 5062, 5063, 5064, 5065, 5066, 5067, 5068, 5069, 5070, 5071, 5072, 5073, 5074, 5075, 5076, 5077, 5078, 5079, 5080, 5081, 5082, 5083, 5084, 5085, 5086, 5087, 5088, 5089, 5090, 5091, 5092, 5093, 5094, 5095, 5096, 5097, 5098, 5099, 5100, 5101, 5102, 5103, 5104, 5105, 5106, 5107, 5108, 5109, 5110, 5111, 5112, 5113, 5114, 5115, 5116, 5117, 5118, 5119, 5120, 5121, 5122, 5123, 5124, 5125, 5126, 5127, 5128, 5129, 5130, 5131, 5132, 5133, 5134, 5135, 5136, 5137, 5138, 5139, 5140, 5141, 5142, 5143, 5144, 5145, 5146, 5147, 5148, 5149, 5150, 5151, 5152, 5153, 5154, 5155, 5156, 5157, 5158, 5159, 5160, 5161, 5162, 5163, 5164, 5165, 5166, 5167, 5168, 5169, 5170, 5171, 5172, 5173, 5174, 5175, 5176, 5177, 5178, 5179, 5180, 5181, 5182, 5183, 5184, 5185, 5186, 5187, 5188, 5189, 5190, 5191, 5192, 5193, 5194, 5195, 5196, 5197, 5198, 5199, 5200, 5201, 5202, 5203, 5204, 5205, 5206, 5207, 5208, 5209, 5210, 5211, 5212, 5213, 5214, 5215, 5216, 5217, 5218, 5219, 5220, 5221, 5222, 5223, 5224, 5225, 5226, 5227, 5228, 5229, 5230, 5231, 5232, 5233, 5234, 5235, 5236, 5237, 5238, 5239, 5240, 5241, 5242, 5243, 5244, 5245, 5246, 5247, 5248, 5249, 5250, 5251, 5252, 5253, 5254, 5255, 5256, 5257, 5258, 5259, 5260, 5261, 5262, 5263, 5264, 5265, 5266, 5267, 5268, 5269, 5270, 5271, 5272, 5273, 5274, 5275, 5276, 5277, 5278, 5279, 5280, 5281, 5282, 5283, 5284, 5285, 5286, 5287, 5288, 5289, 5290, 5291, 5292, 5293, 5294, 5295, 5296, 5297, 5298, 5299, 5300, 5301, 5302, 5303, 5304, 5305, 5306, 5307, 5308, 5309, 5310, 5311, 5312, 5313, 5314, 5315, 5316, 5317, 5318, 5319, 5320, 5321, 5322, 5323, 5324, 5325, 5326, 5327, 5328, 5329, 5330, 5331, 5332, 5333, 5334, 5335, 5336, 5337, 5338, 5339, 5340, 5341, 5342, 5343, 5344, 5345, 5346, 5347, 5348, 5349, 5350, 5351, 5352, 5353, 5354, 5355, 5356]], + ["SE", [5357, 5358, 5359, 5360, 5361, 5362, 5363, 5364, 5365, 5366, 5367, 5368, 5369, 5370, 5371, 5372, 5373, 5374, 5375, 5376, 5377, 5378, 5379, 5380, 5381, 5382, 5383, 5384, 5385, 5386, 5387, 5388, 5389, 5390, 5391, 5392, 5393, 5394, 5395, 5396, 5397, 5398, 5399, 5400, 5401, 5402, 5403, 5404, 5405, 5406, 5407, 5408, 5409, 5410, 5411, 5412, 5413, 5414, 5415, 5416, 5417, 5418, 5419, 5420, 5421, 5422, 5423, 5424, 5425, 5426, 5427, 5428, 5429, 5430, 5431]], + ["TO", [5432, 5433, 5434, 5435, 5436, 5437, 5438, 5439, 5440, 5441, 5442, 5443, 5444, 5445, 5446, 5447, 5448, 5449, 5450, 5451, 5452, 5453, 5454, 5455, 5456, 5457, 5458, 5459, 5460, 5461, 5462, 5463, 5464, 5465, 5466, 5467, 5468, 5469, 5470, 5471, 5472, 5473, 5474, 5475, 5476, 5477, 5478, 5479, 5480, 5481, 5482, 5483, 5484, 5485, 5486, 5487, 5488, 5489, 5490, 5491, 5492, 5493, 5494, 5495, 5496, 5497, 5498, 5499, 5500, 5501, 5502, 5503, 5504, 5505, 5506, 5507, 5508, 5509, 5510, 5511, 5512, 5513, 5514, 5515, 5516, 5517, 5518, 5519, 5520, 5521, 5522, 5523, 5524, 5525, 5526, 5527, 5528, 5529, 5530, 5531, 5532, 5533, 5534, 5535, 5536, 5537, 5538, 5539, 5540, 5541, 5542, 5543, 5544, 5545, 5546, 5547, 5548, 5549, 5550, 5551, 5552, 5553, 5554, 5555, 5556, 5557, 5558, 5559, 5560, 5561, 5562, 5563, 5564, 5565, 5566, 5567, 5568, 5569, 5570]], + ], + [882, 1566, 883, 1567, 2419, 619, 202, 203, 2786, 4417, 2420, 4418, 1568, 3185, 5432, 1569, 1128, 204, 2421, 620, 621, 3686, 3370, 3853, 622, 1345, 0, 884, 1570, 4712, 885, 4713, 2787, 205, 3186, 3687, 804, 1129, 3187, 2422, 3188, 3371, 4419, 4420, 2423, 1346, 1571, 22, 2563, 3372, 1487, 1572, 4421, 1130, 805, 206, 886, 887, 3688, 3189, 3854, 4714, 1573, 3190, 4715, 4422, 4716, 4717, 4718, 1574, 4423, 888, 4424, 1575, 3855, 4719, 2788, 806, 2564, 5433, 1576, 207, 623, 1577, 3856, 1578, 2565, 2566, 2567, 3191, 3373, 208, 4720, 1579, 1131, 624, 2568, 1488, 209, 1132, 3857, 807, 3858, 3374, 3859, 1580, 2424, 3689, 889, 1581, 808, 4721, 1582, 4425, 2569, 2570, 3192, 5434, 210, 5435, 2425, 1583, 3690, 2789, 3860, 890, 1584, 3861, 1585, 1347, 4350, 4722, 2426, 1133, 2790, 625, 1586, 3193, 4723, 3862, 4402, 4724, 1134, 1135, 4351, 1348, 4426, 1349, 1587, 3691, 3863, 1350, 891, 1588, 3375, 1351, 2791, 4352, 892, 2792, 1136, 2793, 1589, 809, 626, 1352, 2794, 3376, 4725, 140, 1590, 4726, 4727, 4728, 4729, 1591, 3864, 5436, 4353, 1592, 3377, 893, 2795, 4403, 1489, 124, 1137, 2796, 3194, 3865, 894, 3378, 1138, 211, 141, 212, 213, 4730, 895, 4731, 4732, 3866, 627, 896, 2571, 4733, 5357, 1593, 2797, 23, 214, 2798, 2427, 1139, 4734, 142, 5437, 2428, 897, 2429, 1140, 1490, 1491, 810, 4427, 215, 2799, 216, 1594, 4735, 3867, 1595, 4736, 1596, 1492, 3195, 4428, 217, 3379, 5438, 3692, 3594, 218, 2800, 898, 4737, 4738, 899, 3380, 4429, 4430, 143, 3868, 219, 2801, 628, 3381, 220, 1597, 4431, 1598, 221, 1493, 3693, 2802, 3869, 1599, 2572, 4739, 4740, 900, 901, 5439, 1494, 3595, 811, 1353, 4741, 1141, 4432, 3694, 222, 902, 223, 2803, 144, 629, 5358, 1495, 630, 4433, 2573, 1600, 5359, 4742, 224, 631, 225, 4743, 226, 1601, 632, 3196, 4744, 812, 903, 1602, 904, 905, 5440, 5441, 5442, 1354, 5443, 1355, 1142, 5444, 906, 1603, 5445, 1143, 1496, 227, 3870, 1144, 4745, 4746, 1604, 4747, 24, 5446, 1605, 2804, 1606, 2805, 1607, 2806, 1356, 4434, 2574, 4435, 4748, 4749, 633, 1145, 3871, 634, 3197, 3596, 2575, 2807, 228, 3872, 635, 229, 5360, 2808, 1608, 1609, 1610, 4750, 1611, 3198, 1612, 3597, 4751, 2576, 3695, 5361, 2577, 2578, 4752, 4753, 1357, 907, 3696, 1613, 1614, 1615, 1358, 4354, 4754, 2809, 3598, 4436, 636, 3382, 2579, 3383, 3384, 3599, 5447, 3873, 3874, 3875, 3876, 3877, 3878, 4437, 4755, 908, 4756, 4438, 3879, 4439, 4757, 2810, 637, 4758, 1, 2811, 3697, 2580, 3385, 1616, 2812, 25, 2813, 145, 4440, 1617, 4759, 813, 5448, 2430, 1618, 3880, 3881, 230, 4760, 909, 638, 4441, 2431, 5449, 146, 4761, 4762, 4763, 2432, 3386, 910, 1146, 5450, 5451, 1147, 1148, 1149, 1150, 4764, 1619, 3882, 2433, 2581, 3698, 231, 2434, 232, 3387, 639, 814, 4765, 1620, 911, 4442, 4443, 4444, 4445, 4446, 3883, 4447, 2814, 4766, 1151, 1621, 640, 4767, 2582, 1622, 1623, 4448, 1497, 2815, 5452, 2435, 233, 3884, 4768, 1624, 3885, 1152, 1359, 1625, 3886, 2583, 3699, 1626, 641, 4769, 2816, 2436, 3700, 147, 4770, 234, 4449, 4771, 3388, 235, 3199, 2584, 2585, 26, 815, 27, 2586, 1360, 4772, 236, 1153, 1361, 3887, 2817, 237, 5453, 3600, 3888, 3889, 3890, 238, 4773, 5362, 3891, 1627, 3601, 4450, 2818, 3892, 3389, 642, 239, 3390, 148, 1154, 3200, 4774, 4775, 643, 240, 912, 3391, 241, 242, 5454, 644, 3893, 1628, 4776, 4777, 1498, 28, 3392, 4778, 1499, 645, 4779, 2587, 4780, 646, 647, 1500, 2819, 913, 1629, 1155, 2820, 3393, 4451, 1156, 29, 2437, 2588, 3201, 2589, 3394, 3202, 3602, 1630, 243, 4452, 244, 1631, 3203, 30, 1632, 1633, 2438, 3395, 1157, 4453, 2439, 149, 3894, 4781, 3701, 3895, 1158, 1634, 1635, 2590, 4782, 1159, 5455, 4783, 3396, 1636, 150, 3204, 3397, 1637, 3205, 1638, 1639, 4454, 4784, 1640, 4785, 4786, 245, 2821, 4455, 816, 1641, 2822, 2823, 1362, 4787, 3398, 246, 2591, 2824, 648, 2592, 4404, 2825, 3896, 3897, 3898, 1160, 3899, 151, 3900, 247, 31, 152, 3399, 4788, 1642, 4456, 1643, 2826, 3702, 3206, 1501, 4789, 4790, 3207, 1644, 1161, 3208, 3603, 4457, 914, 1645, 2593, 3400, 3703, 3901, 4458, 248, 1646, 249, 1162, 915, 1647, 1363, 1648, 3604, 817, 4459, 2827, 2440, 5456, 4791, 1163, 3902, 3401, 3903, 1649, 4460, 3904, 1650, 2594, 2828, 4792, 2829, 4461, 1651, 4405, 3402, 916, 1652, 250, 251, 1502, 2441, 3209, 1653, 2595, 917, 2596, 3905, 3403, 5363, 252, 4793, 4794, 153, 2597, 4795, 1654, 4796, 2830, 3906, 1655, 4797, 1656, 253, 4462, 3907, 4463, 4464, 3908, 2442, 4798, 2831, 32, 1657, 2443, 1503, 1658, 2832, 5457, 2, 3404, 803, 1659, 1364, 4799, 1660, 918, 1661, 3210, 818, 3211, 3704, 5458, 1164, 4800, 3212, 1165, 2598, 3405, 2599, 5364, 2444, 649, 254, 255, 2445, 2446, 919, 3909, 4801, 4802, 256, 1662, 257, 4465, 4466, 1663, 1664, 3213, 258, 1665, 3214, 3, 2447, 4803, 4804, 1166, 920, 1167, 921, 5459, 3406, 3407, 1168, 922, 259, 1169, 1666, 4355, 4805, 1667, 3910, 154, 2600, 1504, 260, 2601, 261, 1668, 923, 3408, 2602, 4356, 3215, 3605, 1669, 4806, 4807, 3216, 4467, 4808, 3911, 4357, 3912, 1365, 262, 924, 1670, 925, 1671, 1672, 2448, 2449, 3913, 2603, 926, 1673, 1170, 4809, 3606, 3217, 3914, 5460, 819, 2604, 2605, 2606, 33, 3915, 4358, 4810, 927, 263, 264, 1674, 265, 1675, 3218, 266, 267, 2833, 2834, 4811, 2835, 4812, 1676, 928, 3916, 4468, 2607, 3917, 3705, 3706, 3707, 4813, 268, 4814, 4815, 1171, 1172, 4816, 2608, 3409, 2609, 4817, 34, 3410, 1677, 4818, 3219, 125, 1678, 2610, 929, 930, 269, 3411, 2836, 4469, 3220, 270, 271, 1679, 2611, 272, 1680, 1505, 3918, 3221, 3919, 2837, 3920, 2838, 2839, 4470, 3607, 1681, 1682, 2450, 650, 3222, 1683, 1684, 35, 1685, 3921, 931, 1173, 2840, 3922, 4819, 2841, 2612, 2842, 1686, 932, 1366, 4820, 3412, 3923, 933, 36, 4471, 934, 273, 3413, 1687, 1688, 4472, 3924, 2843, 5365, 1689, 2844, 4473, 1690, 274, 37, 1506, 3708, 3414, 2845, 3415, 935, 4821, 2846, 3416, 2847, 3925, 4359, 1367, 3709, 1368, 1691, 936, 3926, 1369, 4822, 3608, 1692, 5461, 4474, 4823, 651, 937, 3223, 1693, 1694, 2451, 1370, 4824, 38, 275, 1695, 276, 1371, 4825, 3417, 277, 278, 279, 1696, 4360, 3927, 280, 2848, 3928, 1174, 4826, 4827, 281, 3929, 2849, 3930, 4475, 3710, 3931, 5366, 3224, 652, 5367, 4828, 3932, 4476, 282, 4406, 1697, 2850, 3609, 1175, 3418, 283, 3933, 155, 2452, 2851, 4477, 4829, 3934, 3935, 3936, 3937, 1698, 39, 5368, 3938, 4830, 284, 1699, 1700, 1701, 2613, 1702, 285, 1703, 4478, 1176, 653, 3939, 1704, 3419, 1705, 3420, 2852, 2453, 1706, 4831, 4479, 3940, 4, 3225, 1707, 3941, 4407, 1507, 3421, 4832, 1708, 286, 2853, 1709, 1710, 1711, 3610, 4833, 1712, 156, 2614, 3711, 3422, 287, 3942, 1713, 288, 4834, 3611, 1714, 157, 158, 820, 654, 3423, 289, 5369, 655, 5462, 656, 657, 1372, 2854, 3943, 1715, 3944, 1716, 3612, 1717, 1718, 1719, 1720, 1721, 1722, 938, 5463, 5370, 1723, 3226, 3712, 3713, 658, 3227, 1724, 40, 4408, 1177, 3228, 1725, 2615, 5464, 3229, 1178, 1726, 1727, 4835, 1728, 290, 3945, 1729, 659, 2855, 5465, 3946, 3613, 3230, 2616, 1730, 4836, 1508, 2454, 1373, 4361, 939, 821, 3424, 4837, 2856, 291, 1731, 940, 4838, 2857, 4480, 660, 1732, 1733, 3231, 4839, 2617, 292, 2618, 293, 3947, 1734, 661, 941, 294, 2619, 1735, 662, 942, 1736, 4481, 1179, 3948, 3425, 3714, 1180, 4840, 663, 3232, 5371, 1737, 4482, 3949, 5466, 2858, 295, 1738, 1181, 1739, 1182, 1183, 4362, 943, 4841, 4842, 3950, 2859, 3951, 3715, 3952, 3953, 3954, 4483, 4843, 2860, 944, 3233, 3234, 41, 1740, 1741, 3955, 5467, 5468, 1742, 1374, 1743, 945, 4484, 1509, 1184, 4485, 4844, 3956, 3957, 664, 4845, 2455, 1744, 3958, 2861, 665, 666, 296, 3959, 4363, 3960, 2862, 297, 2863, 946, 1185, 3961, 298, 1745, 3962, 1746, 1747, 1375, 1748, 4846, 2864, 299, 159, 3426, 3427, 4486, 3428, 1376, 947, 300, 160, 1186, 1187, 1749, 42, 3429, 2456, 822, 1377, 4847, 1188, 3963, 948, 5469, 5470, 1378, 4848, 2865, 3430, 3431, 43, 2866, 3964, 4364, 1750, 5471, 1751, 3614, 1752, 1379, 2620, 1753, 823, 1754, 301, 1755, 1756, 1757, 3615, 302, 2457, 3432, 824, 303, 304, 1189, 1758, 1759, 1760, 5472, 1761, 4849, 4850, 4487, 2458, 2621, 3235, 305, 2622, 306, 3965, 1762, 1763, 1380, 2623, 1764, 1765, 1766, 2867, 1767, 1381, 1768, 2868, 1769, 1770, 3966, 1771, 2869, 307, 1772, 3967, 44, 3968, 1773, 308, 2870, 3616, 4851, 309, 4488, 1774, 1775, 667, 2624, 1510, 310, 1776, 2871, 1777, 4852, 1190, 1778, 3969, 3970, 2872, 3716, 1779, 4489, 3717, 311, 3433, 4853, 4490, 1780, 1781, 3971, 1511, 2873, 1782, 1783, 1784, 949, 1785, 1786, 4491, 3434, 3236, 312, 3237, 1512, 950, 951, 4854, 2874, 4365, 4492, 45, 4855, 4856, 4366, 1513, 313, 4857, 3972, 1382, 1787, 5473, 3973, 1514, 2625, 46, 668, 669, 4858, 314, 4493, 1788, 315, 3974, 1789, 4859, 3975, 3976, 5474, 3435, 1790, 952, 1791, 953, 1792, 5372, 3436, 316, 954, 5475, 670, 955, 1793, 671, 3977, 317, 2626, 2875, 4860, 3978, 4861, 1794, 2876, 2877, 5, 2878, 3979, 3718, 1795, 2879, 4862, 2627, 1383, 2628, 2629, 2630, 4367, 956, 3238, 2459, 5373, 4863, 4494, 4495, 1796, 3239, 318, 3437, 2460, 2880, 4496, 2881, 3438, 3719, 2631, 1797, 3439, 2632, 2461, 3440, 2462, 2463, 1191, 1384, 1798, 3240, 126, 957, 2633, 958, 5476, 319, 1799, 3980, 959, 1192, 1800, 1801, 47, 1802, 3441, 1385, 1515, 672, 3981, 4864, 4497, 1803, 2634, 1804, 1805, 3982, 4865, 2635, 2882, 2883, 2884, 1806, 1386, 5477, 320, 3983, 1807, 1808, 4498, 960, 4866, 3442, 5374, 1809, 1810, 1811, 825, 4867, 1812, 1813, 961, 5478, 1814, 1815, 1816, 4868, 4869, 3984, 3985, 1516, 5479, 3986, 48, 2885, 4870, 1387, 321, 1817, 1818, 2464, 3443, 3987, 3444, 1819, 322, 3988, 1193, 3989, 1820, 1821, 826, 3445, 4499, 1822, 3990, 2636, 1823, 1824, 1825, 827, 1826, 1827, 3241, 1517, 2886, 4871, 1828, 1518, 2887, 3991, 4500, 3992, 3720, 2888, 962, 4872, 4873, 3617, 2637, 5480, 4874, 1194, 3618, 1829, 4875, 828, 963, 964, 161, 1519, 4876, 2465, 3993, 3446, 4877, 3447, 4878, 323, 1830, 2638, 4879, 4880, 4881, 4882, 3994, 3721, 324, 3995, 2889, 2890, 1831, 4883, 1832, 3619, 3996, 1833, 325, 4501, 1834, 2891, 3997, 3998, 162, 6, 3722, 3999, 4000, 673, 326, 4502, 4001, 4002, 4003, 4503, 1835, 3242, 4004, 1836, 1837, 2639, 4005, 2892, 3448, 5481, 1195, 2893, 4368, 1838, 3723, 1839, 4884, 4885, 327, 4006, 4007, 5375, 4008, 4009, 1840, 4886, 1196, 4010, 4887, 1841, 49, 1842, 965, 4888, 1843, 4011, 328, 4889, 4012, 1844, 329, 674, 1845, 1846, 3724, 3243, 2640, 4013, 966, 1847, 1848, 675, 2466, 2894, 4014, 4890, 3449, 330, 5482, 1520, 2895, 4015, 4504, 4016, 967, 2896, 4017, 7, 331, 332, 50, 3244, 5376, 1197, 1849, 3725, 1850, 1851, 4018, 51, 1388, 2897, 2898, 1852, 3245, 1198, 3726, 4891, 4892, 4893, 4894, 127, 3246, 1853, 1854, 2899, 1521, 5483, 1389, 333, 5484, 334, 968, 52, 2900, 4505, 4895, 2901, 3727, 4896, 3247, 4019, 969, 3450, 2902, 3248, 335, 2467, 3451, 1855, 2903, 3452, 4020, 4506, 2904, 4897, 4898, 163, 4021, 1856, 4022, 970, 1199, 2905, 336, 4507, 971, 1857, 5485, 4023, 676, 4508, 677, 1858, 1200, 4024, 678, 1201, 1859, 2906, 2907, 4509, 4899, 3453, 2908, 3454, 1860, 2909, 3728, 1861, 3455, 4900, 1862, 3456, 1863, 4901, 679, 4025, 1864, 1865, 1866, 2641, 3249, 5377, 4510, 1867, 1868, 3457, 1869, 1870, 3729, 829, 1871, 4902, 2642, 4903, 1872, 3730, 4511, 3250, 972, 1873, 337, 3251, 5378, 4904, 4026, 4512, 2468, 4027, 4513, 4514, 4905, 1390, 4028, 338, 4906, 3458, 4029, 1391, 2910, 5379, 4907, 680, 4030, 339, 4908, 4031, 3459, 53, 4032, 1874, 4909, 340, 1392, 1522, 3252, 4033, 1202, 2911, 1875, 3253, 1876, 973, 974, 975, 2469, 976, 3731, 977, 5486, 978, 5487, 979, 2912, 2913, 1877, 1203, 341, 1878, 1879, 980, 1204, 4515, 3732, 1205, 1206, 4369, 830, 1207, 342, 1208, 1209, 1880, 681, 1210, 5380, 1211, 4034, 4035, 4036, 2914, 3254, 682, 683, 1881, 4516, 3255, 4037, 4517, 684, 3733, 1882, 4038, 4518, 831, 3460, 4039, 4910, 4911, 2915, 4912, 2916, 685, 164, 4370, 343, 3734, 2917, 344, 1883, 1884, 4913, 4914, 3620, 2918, 981, 4040, 2919, 4915, 2643, 4916, 2920, 4917, 1885, 4519, 686, 1886, 5488, 982, 687, 4520, 1887, 1888, 4918, 4041, 983, 2921, 4919, 1393, 832, 2922, 2923, 1889, 4920, 4921, 345, 4922, 2924, 1890, 4923, 4924, 3461, 984, 4925, 4521, 4926, 4522, 4927, 1891, 1523, 1892, 1212, 1893, 1394, 1894, 1895, 2644, 2645, 2470, 5489, 4928, 4042, 985, 1896, 346, 4929, 4043, 4523, 4044, 688, 986, 987, 4930, 2925, 689, 4045, 4931, 3462, 4046, 165, 4047, 1213, 4932, 988, 4933, 347, 1897, 4934, 3256, 2926, 4048, 690, 4935, 54, 833, 2927, 1898, 1899, 4049, 1900, 4524, 691, 2646, 348, 349, 4525, 350, 351, 692, 3257, 352, 353, 2928, 354, 4936, 1901, 1902, 834, 4050, 3258, 4526, 355, 356, 4051, 4937, 357, 1903, 4052, 358, 4938, 835, 359, 1904, 1905, 4939, 360, 693, 4527, 1906, 2929, 1214, 4940, 361, 694, 836, 3735, 4941, 55, 362, 4942, 2647, 4943, 1907, 1215, 1216, 2471, 2472, 3259, 4944, 1908, 363, 56, 4053, 3621, 364, 4945, 2930, 3260, 1909, 1524, 695, 2931, 1910, 4054, 4946, 5381, 3261, 3463, 4947, 4948, 365, 4528, 1911, 4055, 2648, 4529, 2932, 4056, 1912, 4530, 2933, 4531, 4057, 1217, 2934, 989, 2935, 3262, 1913, 1914, 4532, 4949, 696, 4058, 4950, 1915, 2936, 4951, 990, 5382, 1395, 2649, 1916, 3263, 4059, 366, 2473, 57, 1917, 1918, 3464, 991, 1919, 1525, 4952, 4533, 1920, 992, 1921, 3736, 697, 1922, 698, 4953, 4060, 367, 4954, 4955, 1923, 368, 4956, 4534, 369, 2937, 993, 1396, 3465, 4061, 166, 2474, 3264, 994, 2938, 4535, 4957, 699, 4958, 4536, 3265, 3737, 700, 5490, 1924, 4537, 370, 701, 4409, 2939, 4959, 4538, 4062, 1925, 371, 372, 167, 4539, 4960, 4961, 373, 374, 2940, 4540, 702, 375, 2941, 4541, 2475, 837, 3466, 995, 4542, 4063, 2650, 5383, 5384, 376, 4962, 377, 996, 5385, 1926, 1927, 1928, 3622, 378, 5491, 1929, 1930, 379, 168, 3266, 4064, 380, 381, 382, 383, 838, 384, 3623, 2942, 1931, 997, 998, 5492, 4963, 3267, 703, 3467, 4543, 1218, 1932, 2943, 704, 2476, 999, 3738, 4544, 4964, 4965, 385, 1933, 386, 3624, 387, 1934, 169, 1935, 388, 1936, 2944, 389, 2945, 3268, 1937, 1938, 1939, 390, 4966, 1940, 1397, 391, 1941, 1942, 4967, 3625, 1000, 1943, 705, 392, 393, 394, 1944, 4968, 1219, 2946, 4545, 839, 2947, 3626, 3269, 395, 4969, 1945, 4970, 4971, 396, 706, 4972, 170, 4546, 1001, 4973, 5493, 3270, 397, 707, 4547, 4974, 1526, 5494, 2651, 4975, 5386, 2652, 4371, 4065, 4976, 4977, 1002, 4978, 398, 4066, 1527, 3271, 840, 399, 4979, 708, 4980, 1003, 4067, 3627, 1946, 4981, 4068, 400, 4982, 709, 2653, 3739, 1947, 1398, 128, 1004, 3468, 1948, 2948, 1949, 1950, 1220, 1399, 4983, 4984, 401, 402, 4985, 403, 4986, 404, 405, 1951, 1952, 1005, 1953, 4987, 2477, 4548, 1954, 1955, 4988, 406, 841, 2949, 2950, 2951, 2952, 1528, 1006, 4069, 4070, 3272, 4549, 407, 4989, 2953, 4071, 4990, 1956, 3740, 408, 2654, 58, 2478, 4991, 2954, 4992, 1400, 1957, 4550, 409, 3469, 1958, 59, 4072, 2479, 4993, 1959, 4073, 2955, 410, 1960, 4074, 411, 842, 710, 4075, 2956, 711, 712, 412, 4994, 713, 4551, 1961, 3470, 4995, 4996, 1962, 1963, 1007, 2957, 413, 3741, 4997, 3742, 1401, 2958, 1964, 3743, 1965, 60, 5387, 3628, 3744, 2959, 5388, 1966, 1529, 171, 2960, 3273, 4076, 1008, 4552, 1530, 61, 714, 1531, 2961, 3745, 3746, 3471, 3747, 2962, 4553, 4998, 4077, 4999, 4372, 1009, 2963, 3274, 1532, 715, 1221, 3275, 3472, 5000, 5495, 1010, 1402, 1967, 1968, 1222, 1969, 62, 414, 1970, 1971, 1972, 415, 2655, 5001, 843, 3473, 1973, 2964, 1011, 4373, 716, 416, 417, 4554, 1974, 1975, 5002, 3276, 3748, 3474, 3749, 418, 1223, 1976, 844, 2656, 1977, 5003, 1978, 63, 3277, 3475, 2965, 2657, 3476, 4078, 4555, 1979, 8, 4556, 5004, 3750, 3477, 1980, 1981, 1224, 1982, 1012, 1403, 2658, 5496, 1983, 2659, 419, 717, 3478, 718, 3278, 420, 3751, 1404, 1984, 3479, 4079, 5005, 5006, 1225, 2660, 64, 3752, 5007, 2966, 65, 5008, 3279, 4557, 5009, 5010, 1985, 2967, 3280, 3480, 2661, 2662, 172, 1986, 1405, 2480, 1406, 421, 1013, 2968, 422, 423, 173, 1533, 1987, 2969, 174, 4558, 1988, 1534, 424, 1989, 5389, 4559, 1226, 1227, 1228, 1229, 2663, 3481, 4080, 3753, 66, 5497, 1990, 2664, 3281, 3754, 3482, 3755, 3483, 3282, 1230, 3283, 3484, 3485, 5498, 3284, 1991, 4081, 1992, 1993, 1994, 3285, 1231, 3756, 425, 3757, 1014, 1995, 2665, 4082, 4083, 5011, 3486, 4560, 1535, 426, 3629, 4084, 5499, 4085, 4561, 1232, 427, 428, 3286, 429, 3758, 3759, 1996, 430, 1997, 1407, 1998, 3487, 2970, 431, 845, 1999, 2971, 129, 5012, 5390, 2972, 2000, 2666, 4562, 432, 4563, 5500, 5013, 2001, 719, 4086, 5014, 2002, 4564, 5015, 2003, 433, 5016, 4565, 2004, 1015, 2973, 4087, 2005, 434, 2974, 1233, 2006, 5017, 2007, 3287, 67, 2481, 720, 2975, 5018, 4566, 4088, 4089, 846, 5019, 2667, 435, 5501, 2976, 2977, 2668, 2978, 2008, 4567, 5020, 1234, 5021, 5022, 1408, 5023, 2669, 5024, 1409, 3760, 5025, 3488, 1235, 436, 3761, 2009, 2010, 4568, 2979, 5026, 2011, 2980, 5027, 2981, 5028, 2012, 4569, 1016, 3489, 5502, 3630, 3762, 437, 4090, 5391, 130, 3288, 438, 5029, 3763, 5030, 439, 5031, 68, 2013, 4091, 4374, 2014, 3289, 4570, 3631, 440, 721, 3490, 441, 2015, 2670, 2482, 442, 4571, 2483, 1236, 5032, 3632, 443, 444, 5033, 5034, 1017, 4572, 69, 3764, 4573, 2016, 445, 446, 5392, 5393, 2982, 2671, 2672, 1018, 2983, 2017, 4092, 175, 2673, 176, 3290, 177, 9, 2984, 2985, 2986, 5035, 2987, 2018, 3633, 2988, 2019, 2020, 178, 3491, 2989, 10, 4093, 447, 448, 2021, 847, 4094, 2022, 70, 1019, 179, 2484, 5036, 1237, 5037, 4574, 1536, 2485, 722, 449, 71, 450, 3291, 1238, 723, 1239, 2486, 5038, 4095, 848, 4096, 451, 72, 4575, 2023, 2674, 1410, 4097, 3765, 452, 724, 3492, 3493, 2990, 73, 849, 11, 4576, 2675, 2024, 2991, 2992, 2025, 4098, 4099, 5503, 5039, 74, 3634, 2026, 850, 2993, 2994, 5040, 2995, 2996, 5041, 2027, 2997, 2998, 2028, 2487, 2676, 2029, 2999, 2030, 4100, 3000, 2031, 725, 5042, 3766, 2032, 5394, 3001, 1020, 453, 726, 3494, 2677, 4577, 4101, 454, 75, 1240, 2033, 5043, 2678, 5504, 3002, 2034, 2035, 2036, 2037, 2038, 3495, 455, 1241, 2679, 3003, 2039, 4102, 2680, 4103, 4104, 3004, 2040, 1242, 1243, 4578, 2041, 1021, 76, 1411, 2681, 2042, 5044, 3005, 180, 1022, 5505, 727, 3767, 4105, 131, 2043, 456, 3006, 2488, 2044, 4579, 2489, 3635, 2045, 5045, 3007, 2046, 5046, 728, 5047, 2047, 3636, 77, 3768, 3496, 457, 3497, 3637, 5048, 458, 729, 1244, 730, 3498, 1023, 851, 1024, 78, 4106, 2048, 2049, 1025, 5049, 4375, 5050, 2050, 5051, 3638, 5506, 1245, 3008, 2051, 4107, 2052, 731, 1537, 1246, 3292, 5052, 459, 5507, 460, 4376, 5053, 3009, 5054, 1412, 5055, 2053, 4580, 1247, 3010, 732, 2490, 5056, 4581, 2054, 2055, 2682, 5057, 5058, 5059, 1026, 5395, 2491, 2492, 733, 5060, 1248, 5061, 4582, 5062, 2056, 3499, 3500, 2057, 734, 2683, 2058, 852, 3769, 4108, 2493, 3770, 1027, 2059, 5396, 3501, 5063, 4109, 5064, 5065, 2060, 5066, 2061, 4110, 4583, 2062, 4584, 5067, 3771, 5508, 2063, 2684, 5068, 4377, 461, 2064, 5509, 2065, 2685, 5069, 79, 4111, 1249, 2066, 1028, 2067, 1029, 1030, 735, 2068, 736, 3293, 3011, 3294, 4112, 462, 3012, 737, 1031, 4113, 5070, 1032, 3502, 4585, 2069, 463, 3503, 2070, 4586, 4114, 4115, 1250, 464, 5071, 1033, 3772, 4116, 5072, 1034, 2494, 4410, 738, 465, 4117, 466, 853, 4118, 4119, 739, 2686, 467, 468, 1035, 1538, 2071, 3013, 469, 854, 470, 855, 2072, 5397, 80, 3504, 5510, 471, 5073, 472, 2073, 1036, 2074, 2075, 5074, 2076, 4120, 2077, 5075, 3773, 2078, 2079, 3639, 5511, 5076, 2687, 4587, 1539, 473, 5512, 3295, 3505, 5077, 2080, 2688, 3506, 1037, 5398, 2081, 1038, 5078, 181, 5079, 4121, 474, 3640, 1251, 2082, 1540, 5080, 1039, 3774, 3641, 1413, 4122, 475, 4411, 1414, 5399, 5400, 5401, 3014, 5402, 3507, 1415, 5403, 3508, 5081, 3015, 4123, 1541, 1040, 3016, 1542, 4124, 1041, 3017, 1416, 4125, 2083, 4126, 1417, 4378, 4127, 5082, 476, 1418, 5083, 4128, 3018, 5084, 1252, 1042, 3775, 2084, 4588, 3019, 2495, 3020, 4129, 5085, 477, 3021, 2689, 3642, 1043, 5086, 1419, 5087, 4130, 478, 3643, 1044, 5088, 1253, 2496, 4589, 479, 1420, 3022, 2085, 3023, 5089, 4379, 1421, 1422, 2086, 1423, 1424, 1425, 5090, 1426, 3024, 740, 2690, 5513, 1254, 182, 4131, 4132, 2691, 4133, 2087, 2088, 4134, 3025, 4135, 480, 2089, 1045, 4136, 5514, 741, 3026, 1427, 3509, 4137, 3027, 2090, 481, 3028, 2497, 4590, 1428, 2091, 4380, 856, 1046, 4591, 482, 1429, 5091, 5515, 183, 5516, 184, 4138, 1047, 4139, 2092, 1048, 4140, 483, 4592, 5092, 1430, 4381, 1543, 3029, 5517, 81, 4141, 1431, 742, 2093, 3510, 1049, 2498, 2499, 1432, 3511, 1433, 4142, 484, 4143, 2094, 5093, 2500, 743, 5094, 3512, 2501, 132, 2095, 5095, 2692, 1255, 82, 3776, 83, 3513, 84, 2096, 5096, 2097, 3296, 1256, 485, 2693, 2098, 5518, 486, 2099, 85, 2100, 5097, 2101, 5098, 5099, 2502, 2102, 1050, 5100, 4593, 3297, 3298, 744, 3030, 5101, 5102, 4144, 5103, 4594, 2503, 487, 3299, 2504, 5104, 3031, 4595, 86, 2103, 3777, 2104, 2105, 4382, 2694, 4596, 5105, 1051, 2106, 3032, 5106, 488, 1052, 5107, 2505, 745, 4412, 746, 5404, 1257, 747, 748, 1053, 2107, 3514, 2108, 3515, 2109, 4597, 3033, 4145, 2110, 4598, 2111, 2112, 3516, 87, 5108, 1054, 2506, 749, 4599, 2113, 4600, 750, 3300, 4146, 5109, 3034, 5519, 489, 3035, 4601, 5110, 4147, 3517, 88, 3518, 1258, 5520, 490, 1055, 5521, 3301, 5522, 1056, 1057, 3036, 5111, 4148, 4602, 2114, 3037, 1058, 4149, 857, 3302, 5112, 4150, 89, 2115, 4603, 3519, 2116, 3644, 2117, 751, 2507, 2118, 5113, 4151, 3645, 1259, 5114, 752, 4604, 5115, 1544, 3038, 4152, 5523, 2119, 753, 491, 754, 3778, 5524, 3039, 3040, 1545, 1059, 1434, 5116, 3041, 5117, 3303, 1435, 3042, 1546, 2120, 5118, 2695, 492, 3646, 3779, 2508, 1060, 3780, 5119, 4153, 4383, 3781, 90, 185, 493, 91, 5120, 5121, 3520, 3521, 3304, 3782, 1260, 4154, 3783, 2121, 4155, 2122, 2123, 2124, 2696, 3784, 1261, 3522, 3305, 92, 4605, 4156, 4157, 2125, 4606, 1262, 2126, 3043, 3044, 2697, 2127, 3523, 2128, 2129, 5122, 3785, 3647, 494, 2509, 5525, 3524, 3786, 3306, 186, 2130, 3045, 5123, 5124, 1263, 2698, 3307, 3525, 5125, 2131, 495, 4158, 5126, 3046, 93, 4607, 1264, 2132, 4159, 3526, 496, 3047, 2133, 5127, 3308, 2134, 5128, 2135, 755, 2699, 133, 2136, 2137, 2138, 3787, 2700, 5405, 1436, 3788, 2139, 5129, 497, 4160, 2701, 2140, 4608, 5130, 5131, 1265, 5406, 5132, 2141, 5526, 498, 3789, 858, 5133, 1266, 1547, 3527, 3528, 2142, 4161, 2702, 2143, 3790, 5527, 2510, 1437, 4162, 4163, 756, 1267, 5134, 3791, 94, 4609, 757, 2144, 2145, 5528, 2146, 2147, 2148, 5135, 5136, 758, 1268, 2149, 4610, 1269, 3048, 3049, 3050, 1061, 5137, 2150, 4611, 3309, 3310, 4612, 3311, 1062, 3648, 95, 5138, 2703, 499, 2151, 4164, 2511, 3529, 2704, 5139, 2152, 2153, 2154, 2155, 3051, 500, 96, 2705, 1063, 5140, 2706, 3792, 2707, 2156, 4384, 3530, 4385, 501, 5141, 1270, 97, 502, 5142, 5529, 759, 2157, 3052, 4165, 4166, 3053, 4167, 3054, 4613, 5143, 3055, 5407, 3649, 4168, 1271, 4169, 4614, 859, 503, 4170, 2158, 3531, 1272, 5144, 760, 5145, 5146, 1064, 2159, 5147, 3532, 3650, 504, 3056, 5148, 2160, 5149, 5408, 2161, 5150, 2162, 2163, 98, 1065, 1273, 2164, 4171, 2165, 5151, 5152, 3057, 5530, 5153, 4172, 5154, 4615, 2166, 1066, 1067, 761, 505, 3533, 506, 2708, 3058, 3059, 5155, 2167, 2709, 5531, 860, 2168, 2512, 12, 1068, 3060, 507, 508, 3061, 4173, 5156, 4616, 1438, 2169, 5157, 5158, 3312, 1274, 2710, 3793, 2711, 4174, 99, 2712, 2170, 5409, 5410, 509, 1439, 2171, 2172, 510, 5159, 2713, 3313, 4617, 5160, 2173, 5161, 2513, 3062, 1548, 5162, 1440, 3063, 1069, 5163, 4175, 4618, 5532, 4619, 5533, 1441, 2174, 4176, 4620, 1442, 5164, 861, 2175, 2176, 511, 5165, 762, 5166, 1070, 3651, 3064, 3794, 4177, 1071, 763, 2177, 2514, 1072, 3534, 13, 4178, 1443, 3535, 5534, 3065, 3066, 4621, 100, 5411, 2515, 101, 3795, 1444, 1445, 1446, 5167, 5168, 2178, 1275, 134, 4179, 4180, 1549, 5535, 3652, 102, 3067, 1276, 512, 4622, 4386, 4181, 3068, 14, 4182, 1073, 2179, 764, 5169, 513, 5170, 765, 2180, 2181, 4183, 4623, 1447, 5171, 135, 514, 3069, 5172, 2182, 4624, 5173, 5536, 2516, 3070, 2183, 2714, 3536, 5174, 2184, 2185, 5175, 2186, 5176, 4625, 3071, 515, 1277, 5177, 187, 4626, 516, 1278, 2187, 862, 5537, 2188, 4184, 1279, 4387, 4627, 2189, 5178, 1280, 517, 1281, 5179, 2517, 3314, 4388, 1448, 1282, 3072, 4628, 2715, 1074, 4185, 5180, 5412, 4186, 2190, 3073, 5538, 3796, 4187, 2716, 5181, 4188, 2191, 3074, 5182, 3075, 2518, 3653, 3076, 4189, 3077, 103, 3078, 3537, 518, 2717, 3654, 5183, 5184, 2192, 1449, 3079, 4190, 519, 4629, 3080, 5185, 4191, 3315, 1075, 3655, 3081, 766, 2718, 3316, 520, 767, 768, 769, 770, 3797, 3798, 521, 5186, 3082, 5187, 3083, 3084, 4630, 1283, 2193, 2194, 3085, 3086, 3317, 2195, 5539, 771, 2519, 5188, 3538, 4192, 2196, 3539, 5189, 5190, 5191, 4193, 522, 2719, 3087, 772, 3656, 2197, 3088, 1450, 3089, 2198, 2199, 5192, 4194, 523, 1284, 2720, 524, 2721, 5413, 525, 2722, 2200, 5540, 3799, 3318, 526, 3800, 2723, 2724, 2201, 3540, 3801, 5414, 1076, 1077, 1285, 1550, 5193, 527, 3541, 528, 3319, 5194, 5195, 1451, 3090, 5196, 2202, 529, 3091, 5197, 5198, 5199, 5200, 5201, 2203, 1452, 3542, 5415, 5202, 5203, 5204, 2204, 3092, 863, 3093, 3657, 3094, 15, 1453, 3095, 3096, 1551, 2205, 3658, 5205, 4389, 5541, 4631, 3659, 3660, 5206, 530, 3661, 531, 4632, 3802, 4633, 532, 2206, 4634, 2207, 5542, 4635, 4195, 2208, 3320, 4636, 4196, 5207, 3543, 104, 2209, 2520, 4637, 1552, 3097, 2210, 864, 2211, 4197, 2212, 2213, 2214, 2215, 188, 1078, 533, 4638, 5543, 2725, 1079, 1553, 2216, 5208, 4198, 4639, 2217, 5209, 4199, 1554, 2218, 4640, 4200, 2219, 534, 3803, 16, 4201, 3098, 4202, 4390, 2220, 4641, 3099, 4203, 4204, 1454, 3100, 2521, 1455, 4205, 4413, 5210, 1286, 2221, 5416, 3101, 4206, 1456, 5211, 105, 2222, 5212, 1080, 2223, 5213, 2522, 773, 535, 3804, 2224, 3102, 5214, 2225, 774, 2226, 4207, 5215, 3321, 4208, 5216, 5217, 5218, 4642, 2726, 3322, 5417, 2727, 3103, 3323, 2227, 536, 2523, 775, 5219, 3324, 4643, 5220, 5221, 2228, 5222, 1457, 3104, 4209, 3105, 5223, 4644, 537, 4210, 4211, 2524, 1287, 5544, 4212, 1081, 5545, 5224, 4645, 3325, 4213, 5225, 5226, 3106, 538, 2229, 5227, 1082, 2230, 2231, 2525, 4214, 2232, 5228, 539, 1458, 2728, 4646, 3107, 4215, 5229, 4216, 2729, 3326, 3805, 540, 3327, 5230, 5231, 541, 5232, 1083, 2233, 3108, 2234, 2526, 3328, 2235, 3544, 5233, 4217, 1459, 3545, 2236, 5234, 3109, 1084, 2237, 5546, 5235, 3329, 3546, 1288, 5236, 1289, 2730, 3110, 4647, 1085, 2238, 542, 1290, 2731, 3111, 1086, 5237, 3112, 189, 3113, 2527, 2239, 865, 3114, 5238, 3547, 543, 1291, 2240, 2732, 4391, 5418, 106, 2528, 1292, 2241, 4218, 3806, 4219, 3330, 5239, 544, 2529, 2242, 866, 3331, 4220, 3115, 2530, 2243, 2244, 5547, 3662, 3116, 5240, 3117, 776, 1293, 1294, 2733, 5241, 2245, 545, 2246, 2247, 2248, 1087, 2249, 1088, 1555, 5242, 2250, 5548, 1460, 4221, 2251, 1089, 4648, 5419, 5243, 3548, 17, 4649, 5549, 5244, 867, 2734, 4222, 1090, 3118, 5550, 546, 1461, 3332, 4650, 1091, 3119, 4651, 5551, 2252, 4223, 547, 136, 548, 4224, 5245, 2253, 2254, 2735, 5246, 2255, 777, 2531, 778, 2256, 2257, 107, 3120, 2258, 2259, 1295, 3807, 108, 2260, 3549, 2261, 5420, 3808, 2736, 2262, 549, 2532, 2533, 4225, 4652, 1462, 550, 4653, 5421, 1296, 5247, 2737, 5248, 4226, 3809, 5249, 1092, 4227, 3121, 4228, 1093, 551, 1463, 3550, 3663, 5250, 2263, 5251, 2264, 3122, 1094, 2265, 190, 2266, 2267, 5252, 1464, 2268, 4229, 3123, 5253, 4230, 2269, 2270, 3124, 2534, 1297, 3551, 4231, 4232, 552, 5254, 4233, 2271, 3125, 3552, 5255, 5256, 2272, 779, 1298, 3333, 2738, 1299, 2739, 2273, 3810, 5257, 4654, 5552, 3811, 3334, 4655, 1300, 5258, 4656, 4234, 109, 2274, 3553, 2535, 5259, 3335, 4657, 5260, 3126, 5422, 4658, 553, 554, 1095, 2740, 4659, 5423, 2275, 2536, 1301, 2537, 2741, 1302, 868, 2276, 4235, 555, 4392, 556, 1303, 2277, 1465, 557, 3554, 5553, 2538, 3812, 3664, 2278, 2742, 5261, 5424, 4236, 3555, 1096, 3665, 2279, 4237, 2280, 1304, 558, 2281, 4393, 1305, 3813, 2539, 3556, 4660, 559, 4238, 191, 869, 1556, 2282, 2283, 2540, 2284, 3666, 2285, 780, 3814, 3557, 2286, 3558, 2287, 2288, 2289, 560, 2290, 4239, 3127, 3128, 3336, 1306, 4661, 2291, 1097, 4414, 3667, 5262, 3559, 3560, 2292, 2293, 1098, 2541, 2294, 3561, 4240, 3562, 5263, 2295, 5264, 3668, 2542, 2296, 2543, 3563, 3129, 2743, 1307, 4662, 3130, 781, 2297, 2298, 4663, 2299, 2300, 1308, 2301, 5265, 3564, 4241, 2744, 3815, 1309, 4664, 2745, 3131, 1310, 2302, 2303, 4665, 5266, 2304, 3337, 4242, 3132, 3133, 3134, 4666, 2305, 5267, 3135, 3338, 2746, 110, 2306, 2307, 111, 2308, 561, 4243, 3136, 2747, 2748, 3816, 2749, 2750, 1311, 3669, 2309, 5268, 3339, 2751, 2752, 870, 3817, 4667, 4668, 2310, 3565, 3340, 2311, 4244, 4245, 4246, 562, 2312, 2313, 4247, 4248, 3566, 3567, 1466, 1467, 5269, 5270, 2753, 3818, 4249, 3670, 1468, 4250, 1312, 5271, 2754, 3137, 1469, 2755, 3568, 4251, 2314, 3341, 5272, 4669, 3569, 4252, 4670, 1313, 1099, 782, 3570, 112, 1314, 4415, 1100, 5273, 4253, 2756, 3138, 5274, 4254, 4255, 4671, 4256, 871, 1315, 3139, 3819, 5275, 3571, 4672, 563, 4257, 2757, 5425, 2315, 1101, 3572, 3820, 2544, 4394, 3140, 4673, 1102, 3573, 5554, 113, 114, 4258, 1103, 5276, 4259, 192, 3821, 3822, 5277, 1316, 3671, 1470, 4260, 2316, 4261, 4674, 4262, 3141, 3142, 3143, 3574, 2317, 4263, 5278, 1317, 2318, 3823, 1318, 1319, 3575, 1320, 2319, 5279, 2320, 872, 5555, 115, 5280, 3144, 2321, 2545, 5281, 2322, 2758, 3672, 2323, 4264, 2324, 2325, 2326, 564, 2327, 2328, 5556, 193, 2759, 4265, 1104, 5282, 2329, 2330, 3145, 3824, 2331, 4266, 4267, 5557, 4268, 4269, 3825, 5283, 2332, 2760, 4270, 1321, 3342, 2761, 565, 1471, 4271, 3146, 2333, 2546, 3673, 4272, 3674, 3147, 4273, 5284, 2334, 5285, 2335, 566, 116, 1322, 567, 3148, 4675, 568, 4676, 569, 4677, 5286, 3576, 570, 3577, 4274, 4275, 4276, 4277, 1557, 2336, 18, 1323, 2337, 1105, 2338, 3826, 2339, 3827, 19, 2340, 2547, 1324, 2341, 783, 117, 784, 4278, 3149, 571, 2342, 2343, 2344, 4279, 572, 4280, 2345, 4395, 4281, 2346, 3675, 873, 4678, 5287, 2347, 2762, 3828, 2763, 2348, 3829, 3830, 137, 573, 2349, 2350, 574, 2764, 5288, 3831, 1472, 575, 2765, 3343, 5289, 2351, 1325, 1106, 2352, 3150, 2353, 2766, 576, 3832, 3833, 3344, 2354, 577, 3151, 3345, 3152, 4282, 4283, 2767, 5290, 5291, 4284, 2355, 1558, 2356, 4285, 3834, 5292, 4679, 1559, 3578, 3676, 1107, 5558, 4286, 2357, 5293, 194, 2358, 5426, 2359, 3579, 578, 1108, 2360, 3580, 4287, 1473, 3153, 3346, 5427, 1109, 579, 580, 1326, 3835, 5559, 581, 4288, 2768, 785, 2361, 5294, 3581, 2769, 2770, 4289, 2362, 3347, 786, 4680, 1560, 874, 5295, 1474, 2771, 2548, 2772, 582, 5560, 1327, 1328, 5296, 4681, 3154, 5297, 2773, 3677, 3348, 3582, 5298, 5299, 4290, 1475, 5300, 195, 5301, 3349, 5302, 5561, 583, 3836, 2363, 787, 3350, 3351, 5303, 2774, 1561, 5304, 5562, 5305, 2549, 4682, 2364, 5563, 3837, 5306, 5564, 3352, 3155, 5307, 3156, 788, 3583, 5308, 3838, 4683, 1476, 3678, 584, 118, 3584, 585, 586, 2365, 196, 3157, 4291, 4292, 587, 2775, 4293, 2366, 3158, 2367, 5309, 588, 5310, 1477, 4294, 2368, 5311, 1110, 119, 4295, 5312, 3353, 5313, 5314, 4296, 1562, 5315, 20, 789, 138, 5316, 2369, 1329, 5317, 790, 5318, 2776, 4297, 197, 2777, 589, 3159, 2370, 4396, 791, 5319, 3160, 5428, 3839, 3840, 4298, 2778, 590, 5320, 591, 2371, 592, 120, 1563, 3585, 1111, 3679, 3354, 1112, 2550, 3161, 4299, 593, 3355, 1478, 3162, 3163, 5321, 2551, 1479, 4300, 4397, 792, 3164, 3841, 3842, 5322, 4684, 4685, 3165, 3356, 3843, 4686, 1330, 4687, 4688, 5323, 1331, 2372, 4301, 2373, 4302, 2374, 5429, 5565, 5566, 2375, 2376, 2377, 3166, 5430, 3167, 2378, 2552, 198, 3357, 1480, 4303, 5324, 4304, 5325, 3844, 5326, 2553, 3358, 121, 2554, 793, 3680, 4305, 4306, 594, 5327, 4307, 4689, 3168, 4308, 2379, 4309, 4310, 4311, 5328, 1564, 2380, 4312, 4313, 2381, 1113, 3681, 4690, 4691, 4692, 1114, 3359, 4314, 2779, 3360, 4315, 3845, 1332, 1115, 4693, 4694, 595, 2555, 4316, 2556, 1333, 5329, 2382, 4695, 4317, 3169, 3170, 1334, 5330, 2383, 3361, 4318, 4319, 4320, 4321, 3362, 3171, 5331, 5567, 5568, 1335, 1336, 5332, 2384, 5333, 4322, 794, 1116, 1117, 3172, 4696, 2385, 1337, 199, 596, 2386, 2387, 597, 598, 795, 2388, 5334, 599, 5335, 2389, 2390, 5336, 3173, 4323, 5337, 600, 4416, 1118, 2780, 2557, 796, 3846, 5431, 601, 2391, 2781, 797, 3174, 602, 2392, 3586, 4324, 3175, 2393, 4697, 1481, 122, 5338, 3176, 4325, 3847, 3177, 603, 5339, 1338, 5340, 1119, 1120, 2394, 2558, 4698, 798, 2395, 200, 604, 3587, 2396, 201, 4326, 799, 4398, 4699, 5341, 4700, 1121, 605, 4327, 1482, 4399, 4400, 4328, 4329, 4330, 606, 3682, 3588, 607, 5342, 5343, 5344, 1122, 4331, 4701, 4702, 5345, 2397, 875, 2398, 4703, 1339, 2399, 5346, 5347, 2400, 1123, 2401, 800, 3683, 2782, 3848, 801, 3589, 2402, 608, 609, 1483, 3590, 610, 5348, 611, 2403, 3684, 2404, 4332, 876, 3849, 3178, 3363, 1484, 612, 3850, 4333, 5349, 3179, 3591, 4334, 3364, 2405, 3180, 613, 2406, 2407, 2408, 3365, 3366, 2409, 4335, 4336, 4337, 877, 1340, 1124, 3367, 4338, 1565, 1125, 123, 2410, 3851, 802, 4339, 4704, 4705, 2411, 2783, 2559, 1485, 1126, 3852, 4340, 4341, 4342, 3592, 4343, 1341, 878, 1127, 1486, 879, 880, 4401, 5350, 5351, 2412, 2413, 2414, 2415, 3181, 2416, 2560, 4344, 5352, 4345, 4346, 2784, 4706, 881, 5353, 614, 4347, 3368, 139, 1342, 2561, 3182, 1343, 2417, 3685, 5354, 5355, 615, 3593, 5569, 616, 2418, 3183, 617, 4348, 4707, 5570, 3184, 4349, 4708, 21, 4709, 4710, 3369, 2562, 618, 2785, 5356, 1344, 4711], +); + +/** + * Reads one dataset row as a municipality. + * + * @param {string[]} row - The `[stateCode, name, code]` row. + * @returns {Municipality} The municipality. + */ +const rowToMunicipality = (row: string[]): Municipality => { + return { code: row[2], name: row[1], stateCode: row[0] as StateCode }; +}; + +/** + * Returns Brazilian municipalities published by the IBGE, optionally filtered by state. + * + * If `stateCode` is provided, only municipalities of that state are returned. If it is + * omitted, every municipality of every state is returned, sorted with `localeCompare` in the + * "pt-BR" locale so accented names land where a Brazilian reader expects them. Every per-state + * list is sorted the same way. + * + * Only an omitted (or `undefined`) `stateCode` asks for the full list: any other value that is + * not a known state code, `null` and `""` included, returns `[]`. + * + * The state code is matched exactly, case included: `getMunicipalities("sp")` returns `[]` where + * `getMunicipalities("SP")` returns the 645 São Paulo municipalities. + * + * @param {StateCode} [stateCode] - The two letter code of the Brazilian state to filter by. + * @returns {Municipality[]} A fresh array of fresh `Municipality` objects. Empty when + * `stateCode` is not a known state. + * + * @example + * ```typescript + * getMunicipalities("SP")[0]; // { code: "3500105", name: "Adamantina", stateCode: "SP" } + * getMunicipalities().length; // every municipality of every state + * getMunicipalities("ZZ"); // [] + * getMunicipalities("sp"); // [] (the state code is case-sensitive here) + * getMunicipalities(null); // [] (only an omitted state code asks for the full list) + * ``` + * + * @see Official: https://servicodados.ibge.gov.br/api/docs/localidades + */ +export const getMunicipalities = (stateCode?: StateCode): Municipality[] => { + const municipalities: Municipality[] = []; + let rows = dataAll(MUNICIPALITIES); + if ((stateCode !== undefined)) { + rows = dataRows(MUNICIPALITIES, stateCode); + } + for (const row of rows) { + municipalities.push(rowToMunicipality(row)); + } + return municipalities; +}; diff --git a/spec/bridge/out/typescript/_bridge/is-valid-cnpj.ts b/spec/bridge/out/typescript/_bridge/is-valid-cnpj.ts new file mode 100644 index 000000000..ed071f350 --- /dev/null +++ b/spec/bridge/out/typescript/_bridge/is-valid-cnpj.ts @@ -0,0 +1,142 @@ +// Code generated from spec/bridge/source/is-valid-cnpj.ts. DO NOT EDIT. + +/** `isValidCnpj`, written once. */ + +import { classHas, codeAt, keepClass, patternTest, type CharClass, type PatternStep } from "./_runtime.ts"; + +const class0: CharClass = [[0x30, 0x39], [0x41, 0x5a]]; +const class1: CharClass = [[0x9, 0xd], [0x20, 0x20], [0x2d, 0x2f], [0xa0, 0xa0], [0x1680, 0x1680], [0x2000, 0x200a], [0x2028, 0x2029], [0x202f, 0x202f], [0x205f, 0x205f], [0x3000, 0x3000], [0xfeff, 0xfeff]]; +const class2: CharClass = [[0x30, 0x39]]; +const class3: CharClass = [[0x41, 0x5a]]; +const class4: CharClass = [[0x30, 0x39], [0x41, 0x5a], [0x61, 0x7a]]; + +const PATTERN_ALPHANUMERIC_FORMAT: readonly PatternStep[] = [ + { charClass: class0, min: 2, max: 2, capture: false }, + { charClass: class1, min: 0, max: -1, capture: false }, + { charClass: class0, min: 3, max: 3, capture: false }, + { charClass: class1, min: 0, max: -1, capture: false }, + { charClass: class0, min: 3, max: 3, capture: false }, + { charClass: class1, min: 0, max: -1, capture: false }, + { charClass: class0, min: 4, max: 4, capture: false }, + { charClass: class1, min: 0, max: -1, capture: false }, + { charClass: class2, min: 2, max: 2, capture: false }, +]; + +const PATTERN_NUMERIC_FORMAT: readonly PatternStep[] = [ + { charClass: class2, min: 2, max: 2, capture: false }, + { charClass: class1, min: 0, max: -1, capture: false }, + { charClass: class2, min: 3, max: 3, capture: false }, + { charClass: class1, min: 0, max: -1, capture: false }, + { charClass: class2, min: 3, max: 3, capture: false }, + { charClass: class1, min: 0, max: -1, capture: false }, + { charClass: class2, min: 4, max: 4, capture: false }, + { charClass: class1, min: 0, max: -1, capture: false }, + { charClass: class2, min: 2, max: 2, capture: false }, +]; + +const FIRST_DIGIT_WEIGHTS = [5, 4, 3, 2, 9, 8, 7, 6, 5, 4, 3, 2]; +const SECOND_DIGIT_WEIGHTS = [6, 5, 4, 3, 2, 9, 8, 7, 6, 5, 4, 3, 2]; + + + + + +/** Options of `isValidCnpj`. */ +export type IsValidCnpjOptions = { + /** Which CNPJ format to accept: `1` numeric only, `2` alphanumeric (default: `1`). */ + version?: 1 | 2; +}; + + + +/** + * Validates if a CNPJ (Cadastro Nacional da Pessoa Jurídica) is valid. + * + * Supports both numeric (version 1) and alphanumeric (version 2) CNPJ formats, and accepts the + * usual mask characters (`.`, `-`, `/`) and whitespace around and between groups. + * + * @param {string} cnpj - The CNPJ value to be validated. + * @param {IsValidCnpjOptions} [options] - Optional options. + * @returns {boolean} True if the CNPJ is valid, false otherwise. + * + * @example + * ```typescript + * isValidCnpj("12.345.678/0001-95"); // true + * isValidCnpj("q0slfmbd7vx439", { version: 2 }); // true + * isValidCnpj("00000000000000"); // false (reserved number) + * ``` + */ +export const isValidCnpj = (cnpj: string, options?: IsValidCnpjOptions): boolean => { + const optionsVersion = options?.version ?? -1; + if (typeof cnpj !== "string") { + return false; + } + const trimmed = cnpj.trim(); + if ((optionsVersion === 2)) { + const cleaned = keepClass(class4, cnpj).toUpperCase(); + if (classHas(class3, cleaned)) { + if (!patternTest(PATTERN_ALPHANUMERIC_FORMAT, trimmed.toUpperCase())) { + return false; + } + return hasValidChecksum(cleaned); + } + } + const numeric = keepClass(class2, cnpj); + if (!patternTest(PATTERN_NUMERIC_FORMAT, trimmed)) { + return false; + } + if (isRepeated(numeric)) { + return false; + } + return hasValidChecksum(numeric); +}; + +/** + * Computes one CNPJ check digit from the base and its weight vector. + * + * @param {string} base - The sanitized CNPJ, of which only the base is read. + * @param {number[]} weights - The weight vector of the digit being computed. + * @returns {number} The check digit. + */ +const checkDigit = (base: string, weights: number[]): number => { + let sum = 0; + for (let index = 0; index < weights.length; index++) { + sum = (sum + ((codeAt(base, index) - 48) * weights[index])); + } + const remainder = (sum % 11); + if ((remainder < 2)) { + return 0; + } + return (11 - remainder); +}; + +/** + * Whether both check digits of a sanitized 14 character CNPJ match its base. + * + * @param {string} cnpj - The sanitized CNPJ. + * @returns {boolean} True when both check digits match. + */ +const hasValidChecksum = (cnpj: string): boolean => { + if (((codeAt(cnpj, 12) - 48) !== checkDigit(cnpj, FIRST_DIGIT_WEIGHTS))) { + return false; + } + return ((codeAt(cnpj, 13) - 48) === checkDigit(cnpj, SECOND_DIGIT_WEIGHTS)); +}; + +/** + * Whether every character of the value is the same one. + * + * @param {string} value - The value. + * @returns {boolean} True when the value repeats one character. + */ +const isRepeated = (value: string): boolean => { + if ((value.length === 0)) { + return false; + } + for (let index = 1; index < value.length; index++) { + if ((codeAt(value, index) !== codeAt(value, 0))) { + return false; + } + } + return true; +}; diff --git a/spec/bridge/out/typescript/conformance.ts b/spec/bridge/out/typescript/conformance.ts new file mode 100644 index 000000000..dff70f23b --- /dev/null +++ b/spec/bridge/out/typescript/conformance.ts @@ -0,0 +1,219 @@ +// Code generated by spec/bridge/conformance/drivers.ts. DO NOT EDIT. +import { readFileSync } from "node:fs"; +import { resolve } from "node:path"; + +import { formatCnpj, type FormatCnpjOptions } from "./_bridge/format-cnpj.ts"; +import { getAddressInfoByCep, type AddressInfo, type GetAddressInfoByCepOptions, type CepProvider } from "./_bridge/get-address-info-by-cep.ts"; +import { getMunicipalities, type Municipality, type StateCode } from "./_bridge/get-municipalities.ts"; +import { isValidCnpj, type IsValidCnpjOptions } from "./_bridge/is-valid-cnpj.ts"; + +type Tally = { passed: number; failed: number; skipped: number }; + +const TARGET = "typescript"; + +const unescape = (value: string): string => + value.replaceAll("\\t", "\t").replaceAll("\\n", "\n").replaceAll("\\\\", "\\"); + +/** Whether this target can express the call a row describes. */ +const runs = (targets: string): boolean => targets === "*" || targets.split("|").includes(TARGET); + +/** The values a declared type does not allow, which only a run time check can still catch. */ +const NOT_A_LIST: Record = { "!null": null, "!string": "viacep", "!number": 5, "!object": {}, "!boolean": true }; + +const report = (fn: string, parts: string[], actual: string, expected: string, tally: Tally): void => { + if (actual === expected) { + tally.passed++; + + return; + } + + tally.failed++; + + if (tally.failed <= 3) + console.error(`FAIL ${fn}(${parts.slice(1, -1).join(", ")}) expected ${JSON.stringify(expected.slice(0, 120))} got ${JSON.stringify(actual.slice(0, 120))}`); +}; + +const renderGetAddressInfoByCepAddressInfo = (value: AddressInfo): string => + [value.cep, value.state, value.city, value.neighborhood, value.street].join("|"); + +const renderGetMunicipalitiesMunicipality = (value: Municipality): string => + [value.code, value.name, value.stateCode].join("|"); + +const renderListGetMunicipalitiesMunicipality = (items: readonly unknown[]): string => + [String(items.length), ...items.map((item) => renderGetMunicipalitiesMunicipality((item as Municipality)))].join("\n"); + +/** Replays what `formatCnpj` answers. */ +const checkFormatCnpj = async (): Promise => { + const table = readFileSync(resolve(import.meta.dirname, "../../conformance/recorded/format-cnpj.tsv"), "utf8"); + const tally: Tally = { passed: 0, failed: 0, skipped: 0 }; + + for (const line of table.split("\n").slice(1)) { + if (line === "") continue; + + const parts = line.split("\t"); + + if (!runs(parts[0])) { + tally.skipped++; + + continue; + } + + const argument0 = (parts[2] === "number" ? Number(unescape(parts[1])) : unescape(parts[1])) as string | number; + const options: FormatCnpjOptions = {}; + let given = false; + + if (parts[3] !== "") { + (options as Record)["pad"] = parts[3] === "1"; + given = true; + } + + if (parts[4] !== "") { + (options as Record)["version"] = Number(parts[4]); + given = true; + } + + if (parts[5] !== "") { + (options as Record)["obfuscate"] = parts[5] === "1"; + given = true; + } + + let actual: string; + + try { + actual = formatCnpj(argument0, given ? options : undefined); + } catch (error) { + actual = `!${(error as Error).constructor.name}|${(error as Error).message}`; + } + + report("formatCnpj", parts, actual, unescape(parts[6]), tally); + } + + return tally; +}; + +/** Replays what `getAddressInfoByCep` answers. */ +const checkGetAddressInfoByCep = async (): Promise => { + const table = readFileSync(resolve(import.meta.dirname, "../../conformance/recorded/get-address-info-by-cep.tsv"), "utf8"); + const tally: Tally = { passed: 0, failed: 0, skipped: 0 }; + + for (const line of table.split("\n").slice(1)) { + if (line === "") continue; + + const parts = line.split("\t"); + + if (!runs(parts[0])) { + tally.skipped++; + + continue; + } + + const argument0 = (parts[2] === "number" ? Number(unescape(parts[1])) : unescape(parts[1])) as string | number; + const options: GetAddressInfoByCepOptions = {}; + let given = false; + + if (parts[3] !== "") { + (options as Record)["providers"] = parts[3] in NOT_A_LIST ? NOT_A_LIST[parts[3]] : parts[3] === "[]" ? [] : parts[3].split("|"); + given = true; + } + + let actual: string; + + try { + actual = renderGetAddressInfoByCepAddressInfo(await getAddressInfoByCep(argument0, given ? options : undefined)); + } catch (error) { + actual = `!${(error as Error).constructor.name}|${(error as Error).message}`; + } + + report("getAddressInfoByCep", parts, actual, unescape(parts[4]), tally); + } + + return tally; +}; + +/** Replays what `getMunicipalities` answers. */ +const checkGetMunicipalities = async (): Promise => { + const table = readFileSync(resolve(import.meta.dirname, "../../conformance/recorded/get-municipalities.tsv"), "utf8"); + const tally: Tally = { passed: 0, failed: 0, skipped: 0 }; + + for (const line of table.split("\n").slice(1)) { + if (line === "") continue; + + const parts = line.split("\t"); + + if (!runs(parts[0])) { + tally.skipped++; + + continue; + } + + const argument0 = parts[1] === "1" ? (unescape(parts[2])) as string : undefined; + + let actual: string; + + try { + actual = renderListGetMunicipalitiesMunicipality(getMunicipalities(argument0)); + } catch (error) { + actual = `!${(error as Error).constructor.name}|${(error as Error).message}`; + } + + report("getMunicipalities", parts, actual, unescape(parts[3]), tally); + } + + return tally; +}; + +/** Replays what `isValidCnpj` answers. */ +const checkIsValidCnpj = async (): Promise => { + const table = readFileSync(resolve(import.meta.dirname, "../../conformance/recorded/is-valid-cnpj.tsv"), "utf8"); + const tally: Tally = { passed: 0, failed: 0, skipped: 0 }; + + for (const line of table.split("\n").slice(1)) { + if (line === "") continue; + + const parts = line.split("\t"); + + if (!runs(parts[0])) { + tally.skipped++; + + continue; + } + + const argument0 = (parts[2] === "number" ? Number(unescape(parts[1])) : unescape(parts[1])) as string; + const options: IsValidCnpjOptions = {}; + let given = false; + + if (parts[3] !== "") { + (options as Record)["version"] = Number(parts[3]); + given = true; + } + + let actual: string; + + try { + actual = String(isValidCnpj(argument0, given ? options : undefined)); + } catch (error) { + actual = `!${(error as Error).constructor.name}|${(error as Error).message}`; + } + + report("isValidCnpj", parts, actual, unescape(parts[4]), tally); + } + + return tally; +}; + +let failed = 0; + +const announce = (name: string, tally: Tally): void => { + failed += tally.failed; + + console.log( + `${TARGET}: ${name} ${tally.passed}/${tally.passed + tally.failed} matched${tally.skipped === 0 ? "" : ` (${tally.skipped} not expressible)`}`, + ); +}; + +announce("formatCnpj", await checkFormatCnpj()); +announce("getAddressInfoByCep", await checkGetAddressInfoByCep()); +announce("getMunicipalities", await checkGetMunicipalities()); +announce("isValidCnpj", await checkIsValidCnpj()); + +if (failed > 0) process.exit(1); diff --git a/spec/bridge/out/typescript/format-cnpj/format-cnpj.ts b/spec/bridge/out/typescript/format-cnpj/format-cnpj.ts new file mode 100644 index 000000000..0941fbbb3 --- /dev/null +++ b/spec/bridge/out/typescript/format-cnpj/format-cnpj.ts @@ -0,0 +1,2 @@ +// Code generated from spec/bridge/source/format-cnpj.ts. DO NOT EDIT. +export { formatCnpj, type FormatCnpjOptions } from "../_bridge/format-cnpj"; diff --git a/spec/bridge/out/typescript/get-address-info-by-cep/get-address-info-by-cep.ts b/spec/bridge/out/typescript/get-address-info-by-cep/get-address-info-by-cep.ts new file mode 100644 index 000000000..3edc01e99 --- /dev/null +++ b/spec/bridge/out/typescript/get-address-info-by-cep/get-address-info-by-cep.ts @@ -0,0 +1,2 @@ +// Code generated from spec/bridge/source/get-address-info-by-cep.ts. DO NOT EDIT. +export { getAddressInfoByCep, GetAddressInfoByCepError, GetAddressInfoByCepValidationError, GetAddressInfoByCepNotFoundError, GetAddressInfoByCepServiceError, type AddressInfo, type GetAddressInfoByCepOptions, type CepProvider } from "../_bridge/get-address-info-by-cep"; diff --git a/spec/bridge/out/typescript/get-municipalities/get-municipalities.ts b/spec/bridge/out/typescript/get-municipalities/get-municipalities.ts new file mode 100644 index 000000000..accb5abc3 --- /dev/null +++ b/spec/bridge/out/typescript/get-municipalities/get-municipalities.ts @@ -0,0 +1,2 @@ +// Code generated from spec/bridge/source/get-municipalities.ts. DO NOT EDIT. +export { getMunicipalities, type Municipality, type StateCode } from "../_bridge/get-municipalities"; diff --git a/spec/bridge/out/typescript/is-valid-cnpj/is-valid-cnpj.ts b/spec/bridge/out/typescript/is-valid-cnpj/is-valid-cnpj.ts new file mode 100644 index 000000000..ec8d37693 --- /dev/null +++ b/spec/bridge/out/typescript/is-valid-cnpj/is-valid-cnpj.ts @@ -0,0 +1,2 @@ +// Code generated from spec/bridge/source/is-valid-cnpj.ts. DO NOT EDIT. +export { isValidCnpj, type IsValidCnpjOptions } from "../_bridge/is-valid-cnpj"; diff --git a/vite.config.ts b/vite.config.ts index 157d718a4..637528cfd 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -183,7 +183,18 @@ export default defineConfig({ perf: "error", pedantic: "error", }, - ignorePatterns: ["dist", "coverage", "docs", "reports", ".stryker-tmp", ".claude"], + // `spec/bridge/out` is the compiler's own output, committed so it can be read. Linting + // generated code would be linting the emitters at one remove, and the emitters are + // already linted. + ignorePatterns: [ + "dist", + "coverage", + "docs", + "reports", + ".stryker-tmp", + ".claude", + "spec/bridge/out", + ], rules: { "eslint/complexity": ["error", { max: 20 }], "eslint/max-lines": "off", From 94b32644a2f4240bb3ea68fb07706d71c6b5f3c0 Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 21 Sep 2026 11:55:43 +0000 Subject: [PATCH 13/13] style(spec): close the gaps pruning leaves in the emitted files An emitter joins its sections with a blank line between them, so a module that reaches none of the constants, or none of the errors, came out with a run of up to five empty lines where they would have been. Harmless to a compiler and distracting to a reader, which matters now that the output is committed to be read. `cli.ts` collapses any run of three or more newlines as it writes, and leaves `.json`, `.toml` and `go.mod` alone. Every target spells a string literal with escapes rather than a real newline, so a run of blank lines in an emitted file is always layout and never content. 195 blank lines removed across the 66 generated files, nothing added, and all seven targets plus the C ABI still match the JavaScript package. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01UX1gTGeMTyoXQyr1qUoQKd --- spec/bridge/compiler/cli.ts | 25 +++++++++++++-- spec/bridge/out/csharp/FormatCnpjUtility.cs | 5 --- .../out/csharp/GetAddressInfoByCepUtility.cs | 2 -- .../out/csharp/GetMunicipalitiesUtility.cs | 6 ---- spec/bridge/out/csharp/IsValidCnpjUtility.cs | 3 -- spec/bridge/out/go/format_cnpj/format_cnpj.go | 6 ---- .../get_address_info_by_cep.go | 2 -- .../get_municipalities/get_municipalities.go | 8 ----- .../out/go/is_valid_cnpj/is_valid_cnpj.go | 4 --- spec/bridge/out/java/FormatCnpj.java | 4 --- spec/bridge/out/java/GetAddressInfoByCep.java | 2 -- spec/bridge/out/java/GetMunicipalities.java | 6 ---- spec/bridge/out/java/IsValidCnpj.java | 2 -- .../out/python/brutils_bridge/format_cnpj.py | 11 ------- .../brutils_bridge/get_address_info_by_cep.py | 16 ---------- .../brutils_bridge/get_municipalities.py | 13 -------- .../python/brutils_bridge/is_valid_cnpj.py | 11 ------- .../out/python/brutils_bridge/runtime.py | 31 ------------------- .../lib/brazilian_utils_bridge/format_cnpj.rb | 6 ---- .../get_address_info_by_cep.rb | 2 -- .../get_municipalities.rb | 7 ----- .../brazilian_utils_bridge/is_valid_cnpj.rb | 4 --- spec/bridge/out/rust/src/format_cnpj.rs | 6 ---- .../out/rust/src/get_address_info_by_cep.rs | 2 -- .../bridge/out/rust/src/get_municipalities.rs | 8 ----- spec/bridge/out/rust/src/is_valid_cnpj.rs | 4 --- .../out/typescript/_bridge/format-cnpj.ts | 8 ----- .../_bridge/get-address-info-by-cep.ts | 2 -- .../typescript/_bridge/get-municipalities.ts | 8 ----- .../out/typescript/_bridge/is-valid-cnpj.ts | 6 ---- 30 files changed, 23 insertions(+), 197 deletions(-) diff --git a/spec/bridge/compiler/cli.ts b/spec/bridge/compiler/cli.ts index 6cf66cb62..171590dcd 100644 --- a/spec/bridge/compiler/cli.ts +++ b/spec/bridge/compiler/cli.ts @@ -4,7 +4,7 @@ * Usage: `node compiler/cli.ts [target...]` */ import { mkdirSync, readdirSync, rmSync, writeFileSync } from "node:fs"; -import { dirname, resolve } from "node:path"; +import { dirname, extname, resolve } from "node:path"; import { compileModule } from "./frontend.ts"; import { type Module } from "./ir.ts"; @@ -18,6 +18,27 @@ import { emit as emitTypeScript } from "./targets/typescript.ts"; const root = resolve(import.meta.dirname, ".."); +/** The files whose blank lines are content rather than layout. */ +const VERBATIM = new Set([".json", ".toml", ".mod"]); + +/** + * Closes the gaps pruning leaves behind. + * + * An emitter joins its sections with a blank line between them, so a module that reaches none + * of the constants, or none of the errors, ends up with a run of empty lines where they would + * have been. Every target spells a string literal with escapes rather than a real newline, so + * a run of three or more newlines in an emitted file is always layout and never content. + * + * @param {string} path - The file being written, whose extension says whether to leave it be. + * @param {string} contents - What the emitter produced. + * @returns {string} The same file with at most one blank line in a row. + */ +const tidy = (path: string, contents: string): string => { + if (VERBATIM.has(extname(path))) return contents; + + return `${contents.replaceAll(/\n{3,}/g, "\n\n").trimEnd()}\n`; +}; + const targets: Record Record> = { typescript: emitTypeScript, python: emitPython, @@ -53,7 +74,7 @@ for (const target of selected) { const full = resolve(outDir, path); mkdirSync(dirname(full), { recursive: true }); - writeFileSync(full, contents); + writeFileSync(full, tidy(full, contents)); count++; } } diff --git a/spec/bridge/out/csharp/FormatCnpjUtility.cs b/spec/bridge/out/csharp/FormatCnpjUtility.cs index a05b95c50..1dfec01e1 100644 --- a/spec/bridge/out/csharp/FormatCnpjUtility.cs +++ b/spec/bridge/out/csharp/FormatCnpjUtility.cs @@ -3,7 +3,6 @@ namespace BrazilianUtils.Bridge { - /// Options of `formatCnpj`. public sealed class FormatCnpjOptions { @@ -23,13 +22,9 @@ public static class FormatCnpjUtility private static readonly int[][] CLASS0 = { new[] { 0x30, 0x39 } }; private static readonly int[][] CLASS1 = { new[] { 0x30, 0x39 }, new[] { 0x41, 0x5a }, new[] { 0x61, 0x7a } }; - - private const string PATTERN = "00.000.000/0000-00"; private const string OBFUSCATED_PATTERN = "**.000.000/0000-**"; - - /// /// Formats a given CNPJ (Cadastro Nacional da Pessoa Jurídica) value. /// diff --git a/spec/bridge/out/csharp/GetAddressInfoByCepUtility.cs b/spec/bridge/out/csharp/GetAddressInfoByCepUtility.cs index 6e3d2ef80..ff5027d20 100644 --- a/spec/bridge/out/csharp/GetAddressInfoByCepUtility.cs +++ b/spec/bridge/out/csharp/GetAddressInfoByCepUtility.cs @@ -93,8 +93,6 @@ public static class GetAddressInfoByCepUtility private const long HTTP_RETRIES = 2L; private const long HTTP_RETRY_DELAY_MS = 250L; - - /// /// Reads the address ViaCEP answers with. /// diff --git a/spec/bridge/out/csharp/GetMunicipalitiesUtility.cs b/spec/bridge/out/csharp/GetMunicipalitiesUtility.cs index f094fac6a..a69b7b922 100644 --- a/spec/bridge/out/csharp/GetMunicipalitiesUtility.cs +++ b/spec/bridge/out/csharp/GetMunicipalitiesUtility.cs @@ -3,7 +3,6 @@ namespace BrazilianUtils.Bridge { - /// One Brazilian municipality, as the IBGE publishes it. public sealed class Municipality { @@ -28,11 +27,6 @@ public Municipality(string code, string name, string stateCode) public static class GetMunicipalitiesUtility { - - - - - /// Brazilian municipalities published by the IBGE, by state, in the pt-BR collation order the JavaScript package returns. private static readonly Dataset MUNICIPALITIES = new Dataset( MunicipalitiesRows(), new[] { "AC", "AL", "AP", "AM", "BA", "CE", "DF", "ES", "GO", "MA", "MT", "MS", "MG", "PA", "PB", "PR", "PE", "PI", "RJ", "RN", "RS", "RO", "RR", "SC", "SP", "SE", "TO" }, MunicipalitiesGroups(), diff --git a/spec/bridge/out/csharp/IsValidCnpjUtility.cs b/spec/bridge/out/csharp/IsValidCnpjUtility.cs index 5edd105b6..3f8d79bb3 100644 --- a/spec/bridge/out/csharp/IsValidCnpjUtility.cs +++ b/spec/bridge/out/csharp/IsValidCnpjUtility.cs @@ -3,7 +3,6 @@ namespace BrazilianUtils.Bridge { - /// Options of `isValidCnpj`. public sealed class IsValidCnpjOptions { @@ -49,8 +48,6 @@ public static class IsValidCnpjUtility private static readonly long[] FIRST_DIGIT_WEIGHTS = new long[] { 5L, 4L, 3L, 2L, 9L, 8L, 7L, 6L, 5L, 4L, 3L, 2L }; private static readonly long[] SECOND_DIGIT_WEIGHTS = new long[] { 6L, 5L, 4L, 3L, 2L, 9L, 8L, 7L, 6L, 5L, 4L, 3L, 2L }; - - /// /// Validates if a CNPJ (Cadastro Nacional da Pessoa Jurídica) is valid. /// diff --git a/spec/bridge/out/go/format_cnpj/format_cnpj.go b/spec/bridge/out/go/format_cnpj/format_cnpj.go index aa03af747..51a897b6c 100644 --- a/spec/bridge/out/go/format_cnpj/format_cnpj.go +++ b/spec/bridge/out/go/format_cnpj/format_cnpj.go @@ -8,13 +8,9 @@ import "brazilianutils/bridge/runtime" var class0 = runtime.CharClass{{0x30, 0x39}} var class1 = runtime.CharClass{{0x30, 0x39}, {0x41, 0x5a}, {0x61, 0x7a}} - - const PATTERN = "00.000.000/0000-00" const OBFUSCATED_PATTERN = "**.000.000/0000-**" - - // FormatCnpjOptions Options of `formatCnpj`. type FormatCnpjOptions struct { // Whether to left pad the value with zeros up to the number of slots in the pattern (default: `false`). @@ -25,8 +21,6 @@ type FormatCnpjOptions struct { Obfuscate *bool } - - // FormatCnpj Formats a given CNPJ (Cadastro Nacional da Pessoa Jurídica) value. func FormatCnpj(value string, options *FormatCnpjOptions) string { var optionsVersion int64 = -1 diff --git a/spec/bridge/out/go/get_address_info_by_cep/get_address_info_by_cep.go b/spec/bridge/out/go/get_address_info_by_cep/get_address_info_by_cep.go index c0e4442d7..a63d701f3 100644 --- a/spec/bridge/out/go/get_address_info_by_cep/get_address_info_by_cep.go +++ b/spec/bridge/out/go/get_address_info_by_cep/get_address_info_by_cep.go @@ -77,8 +77,6 @@ type GetAddressInfoByCepOptions struct { Providers *[]string } - - // fetchViaCep Reads the address ViaCEP answers with. // // @see Based on: https://viacep.com.br/ diff --git a/spec/bridge/out/go/get_municipalities/get_municipalities.go b/spec/bridge/out/go/get_municipalities/get_municipalities.go index 2af828595..7983b8159 100644 --- a/spec/bridge/out/go/get_municipalities/get_municipalities.go +++ b/spec/bridge/out/go/get_municipalities/get_municipalities.go @@ -5,14 +5,6 @@ package get_municipalities import "brazilianutils/bridge/runtime" - - - - - - - - // Municipality One Brazilian municipality, as the IBGE publishes it. type Municipality struct { // The 7-digit IBGE municipality code. diff --git a/spec/bridge/out/go/is_valid_cnpj/is_valid_cnpj.go b/spec/bridge/out/go/is_valid_cnpj/is_valid_cnpj.go index dd670f68e..c5301f420 100644 --- a/spec/bridge/out/go/is_valid_cnpj/is_valid_cnpj.go +++ b/spec/bridge/out/go/is_valid_cnpj/is_valid_cnpj.go @@ -38,16 +38,12 @@ var PATTERN_NUMERIC_FORMAT = []runtime.PatternStep{ var FIRST_DIGIT_WEIGHTS = []int64{5, 4, 3, 2, 9, 8, 7, 6, 5, 4, 3, 2} var SECOND_DIGIT_WEIGHTS = []int64{6, 5, 4, 3, 2, 9, 8, 7, 6, 5, 4, 3, 2} - - // IsValidCnpjOptions Options of `isValidCnpj`. type IsValidCnpjOptions struct { // Which CNPJ format to accept: `1` numeric only, `2` alphanumeric (default: `1`). Version *int64 } - - // IsValidCnpj Validates if a CNPJ (Cadastro Nacional da Pessoa Jurídica) is valid. // // Supports both numeric (version 1) and alphanumeric (version 2) CNPJ formats, and accepts the diff --git a/spec/bridge/out/java/FormatCnpj.java b/spec/bridge/out/java/FormatCnpj.java index 2d0212974..ea0bb0a46 100644 --- a/spec/bridge/out/java/FormatCnpj.java +++ b/spec/bridge/out/java/FormatCnpj.java @@ -7,13 +7,9 @@ private FormatCnpj() {} private static final int[][] CLASS0 = {{0x30, 0x39}}; private static final int[][] CLASS1 = {{0x30, 0x39}, {0x41, 0x5a}, {0x61, 0x7a}}; - - private static final String PATTERN = "00.000.000/0000-00"; private static final String OBFUSCATED_PATTERN = "**.000.000/0000-**"; - - /** * Formats a given CNPJ (Cadastro Nacional da Pessoa Jurídica) value. */ diff --git a/spec/bridge/out/java/GetAddressInfoByCep.java b/spec/bridge/out/java/GetAddressInfoByCep.java index a2e10ffb5..45a7477a4 100644 --- a/spec/bridge/out/java/GetAddressInfoByCep.java +++ b/spec/bridge/out/java/GetAddressInfoByCep.java @@ -16,8 +16,6 @@ private GetAddressInfoByCep() {} private static final long HTTP_RETRIES = 2L; private static final long HTTP_RETRY_DELAY_MS = 250L; - - /** * Reads the address ViaCEP answers with. * diff --git a/spec/bridge/out/java/GetMunicipalities.java b/spec/bridge/out/java/GetMunicipalities.java index f18b11b8b..68125d902 100644 --- a/spec/bridge/out/java/GetMunicipalities.java +++ b/spec/bridge/out/java/GetMunicipalities.java @@ -4,12 +4,6 @@ public final class GetMunicipalities { private GetMunicipalities() {} - - - - - - /** Brazilian municipalities published by the IBGE, by state, in the pt-BR collation order the JavaScript package returns. */ private static final Runtime.Dataset MUNICIPALITIES = new Runtime.Dataset( municipalitiesRows(), new String[] {"AC", "AL", "AP", "AM", "BA", "CE", "DF", "ES", "GO", "MA", "MT", "MS", "MG", "PA", "PB", "PR", "PE", "PI", "RJ", "RN", "RS", "RO", "RR", "SC", "SP", "SE", "TO"}, municipalitiesGroups(), municipalitiesOrder()); diff --git a/spec/bridge/out/java/IsValidCnpj.java b/spec/bridge/out/java/IsValidCnpj.java index cc5d8f476..d6225cf0e 100644 --- a/spec/bridge/out/java/IsValidCnpj.java +++ b/spec/bridge/out/java/IsValidCnpj.java @@ -37,8 +37,6 @@ private IsValidCnpj() {} private static final long[] FIRST_DIGIT_WEIGHTS = new long[] {5L, 4L, 3L, 2L, 9L, 8L, 7L, 6L, 5L, 4L, 3L, 2L}; private static final long[] SECOND_DIGIT_WEIGHTS = new long[] {6L, 5L, 4L, 3L, 2L, 9L, 8L, 7L, 6L, 5L, 4L, 3L, 2L}; - - /** * Validates if a CNPJ (Cadastro Nacional da Pessoa Jurídica) is valid. * diff --git a/spec/bridge/out/python/brutils_bridge/format_cnpj.py b/spec/bridge/out/python/brutils_bridge/format_cnpj.py index b3692d81f..a62954d99 100644 --- a/spec/bridge/out/python/brutils_bridge/format_cnpj.py +++ b/spec/bridge/out/python/brutils_bridge/format_cnpj.py @@ -34,15 +34,9 @@ class0: CharClass = ((0x30, 0x39),) class1: CharClass = ((0x30, 0x39), (0x41, 0x5a), (0x61, 0x7a),) - - PATTERN = "00.000.000/0000-00" OBFUSCATED_PATTERN = "**.000.000/0000-**" - - - - @dataclass class FormatCnpjOptions: """Options of `formatCnpj`.""" @@ -54,10 +48,6 @@ class FormatCnpjOptions: # Whether to hide the first 2 digits and the 2 check digits with `*` (default: `false`). obfuscate: Optional[bool] = None - - - - def format_cnpj(value: Any, options: Optional[FormatCnpjOptions] = None) -> str: """Formats a given CNPJ (Cadastro Nacional da Pessoa Jurídica) value. """ @@ -81,7 +71,6 @@ def format_cnpj(value: Any, options: Optional[FormatCnpjOptions] = None) -> str: pattern = OBFUSCATED_PATTERN return layout(cleaned, pattern, is_truthy(options_pad)) - def layout(value: str, pattern: str, pad: bool) -> str: """Lays a value over a pattern. """ diff --git a/spec/bridge/out/python/brutils_bridge/get_address_info_by_cep.py b/spec/bridge/out/python/brutils_bridge/get_address_info_by_cep.py index 837e50d25..04ff77e76 100644 --- a/spec/bridge/out/python/brutils_bridge/get_address_info_by_cep.py +++ b/spec/bridge/out/python/brutils_bridge/get_address_info_by_cep.py @@ -43,27 +43,21 @@ HTTP_RETRIES = 2 HTTP_RETRY_DELAY_MS = 250 - class GetAddressInfoByCepError(Exception): """Base class of every error `getAddressInfoByCep` rejects with.""" - class GetAddressInfoByCepValidationError(GetAddressInfoByCepError): """Thrown by `getAddressInfoByCep` when the value given is not a valid CEP.""" - class GetAddressInfoByCepNotFoundError(GetAddressInfoByCepError): """Thrown by `getAddressInfoByCep` when no CEP service knows the CEP.""" - class GetAddressInfoByCepServiceError(GetAddressInfoByCepError): """Thrown by `getAddressInfoByCep` when every CEP service failed to answer.""" - class CepProviderFailure(Exception): """Raised inside a provider that did not answer. Only whether a failure was a not found is looked at when the provider failures are aggregated, so this one never leaves the module.""" - @dataclass class AddressInfo: """The address `getAddressInfoByCep` returns for a CEP.""" @@ -79,7 +73,6 @@ class AddressInfo: # Street name, empty when the CEP covers a whole city. street: str - @dataclass class GetAddressInfoByCepOptions: """Options of `getAddressInfoByCep`.""" @@ -87,10 +80,6 @@ class GetAddressInfoByCepOptions: # Which CEP services to race, in the order given (default: `["viacep", "brasilapi"]`; the deprecated `"widenet"` provider is excluded from the default list, but can still be requested explicitly). providers: Optional[List[str]] = None - - - - def fetch_via_cep(cep: str) -> AddressInfo: """Reads the address ViaCEP answers with. @@ -104,7 +93,6 @@ def fetch_via_cep(cep: str) -> AddressInfo: raise GetAddressInfoByCepNotFoundError("CEP n\U000000e3o encontrado") return AddressInfo(cep=keep_class(class0, found), state=json_string(response.body, "uf"), city=json_string(response.body, "localidade"), neighborhood=json_string(response.body, "bairro"), street=json_string(response.body, "logradouro")) - def fetch_widenet(cep: str) -> AddressInfo: """Reads the address Widenet answers with. """ @@ -116,7 +104,6 @@ def fetch_widenet(cep: str) -> AddressInfo: raise GetAddressInfoByCepNotFoundError("CEP n\U000000e3o encontrado") return AddressInfo(cep=keep_class(class0, found), state=json_string(response.body, "state"), city=json_string(response.body, "city"), neighborhood=json_string(response.body, "district"), street=json_string(response.body, "address")) - def fetch_brasil_api(cep: str) -> AddressInfo: """Reads the address BrasilAPI answers with. @@ -132,7 +119,6 @@ def fetch_brasil_api(cep: str) -> AddressInfo: raise GetAddressInfoByCepNotFoundError("CEP n\U000000e3o encontrado") return AddressInfo(cep=keep_class(class0, found), state=json_string(response.body, "state"), city=json_string(response.body, "city"), neighborhood=json_string(response.body, "neighborhood"), street=json_string(response.body, "street")) - def fetch_provider(provider: str, cep: str) -> AddressInfo: """Asks one named provider for a CEP. """ @@ -142,7 +128,6 @@ def fetch_provider(provider: str, cep: str) -> AddressInfo: return fetch_widenet(cep) return fetch_brasil_api(cep) - def known_providers(given: List[str]) -> List[str]: """The providers of a list that are known, in the order they were given. """ @@ -152,7 +137,6 @@ def known_providers(given: List[str]) -> List[str]: kept.append(provider) return kept - def get_address_info_by_cep(cep: Any, options: Optional[GetAddressInfoByCepOptions] = None) -> AddressInfo: """Fetches address information for a given CEP using multiple providers simultaneously. Returns the result from the first provider that responds successfully. diff --git a/spec/bridge/out/python/brutils_bridge/get_municipalities.py b/spec/bridge/out/python/brutils_bridge/get_municipalities.py index 722fbc55d..9d767cd2e 100644 --- a/spec/bridge/out/python/brutils_bridge/get_municipalities.py +++ b/spec/bridge/out/python/brutils_bridge/get_municipalities.py @@ -31,16 +31,6 @@ start_all, ) - - - - - - - - - - @dataclass class Municipality: """One Brazilian municipality, as the IBGE publishes it.""" @@ -52,7 +42,6 @@ class Municipality: # The two-letter code of the state the municipality belongs to. state_code: str - # Brazilian municipalities published by the IBGE, by state, in the pt-BR collation order the JavaScript package returns. MUNICIPALITIES = make_dataset( [ @@ -5660,13 +5649,11 @@ class Municipality: [882, 1566, 883, 1567, 2419, 619, 202, 203, 2786, 4417, 2420, 4418, 1568, 3185, 5432, 1569, 1128, 204, 2421, 620, 621, 3686, 3370, 3853, 622, 1345, 0, 884, 1570, 4712, 885, 4713, 2787, 205, 3186, 3687, 804, 1129, 3187, 2422, 3188, 3371, 4419, 4420, 2423, 1346, 1571, 22, 2563, 3372, 1487, 1572, 4421, 1130, 805, 206, 886, 887, 3688, 3189, 3854, 4714, 1573, 3190, 4715, 4422, 4716, 4717, 4718, 1574, 4423, 888, 4424, 1575, 3855, 4719, 2788, 806, 2564, 5433, 1576, 207, 623, 1577, 3856, 1578, 2565, 2566, 2567, 3191, 3373, 208, 4720, 1579, 1131, 624, 2568, 1488, 209, 1132, 3857, 807, 3858, 3374, 3859, 1580, 2424, 3689, 889, 1581, 808, 4721, 1582, 4425, 2569, 2570, 3192, 5434, 210, 5435, 2425, 1583, 3690, 2789, 3860, 890, 1584, 3861, 1585, 1347, 4350, 4722, 2426, 1133, 2790, 625, 1586, 3193, 4723, 3862, 4402, 4724, 1134, 1135, 4351, 1348, 4426, 1349, 1587, 3691, 3863, 1350, 891, 1588, 3375, 1351, 2791, 4352, 892, 2792, 1136, 2793, 1589, 809, 626, 1352, 2794, 3376, 4725, 140, 1590, 4726, 4727, 4728, 4729, 1591, 3864, 5436, 4353, 1592, 3377, 893, 2795, 4403, 1489, 124, 1137, 2796, 3194, 3865, 894, 3378, 1138, 211, 141, 212, 213, 4730, 895, 4731, 4732, 3866, 627, 896, 2571, 4733, 5357, 1593, 2797, 23, 214, 2798, 2427, 1139, 4734, 142, 5437, 2428, 897, 2429, 1140, 1490, 1491, 810, 4427, 215, 2799, 216, 1594, 4735, 3867, 1595, 4736, 1596, 1492, 3195, 4428, 217, 3379, 5438, 3692, 3594, 218, 2800, 898, 4737, 4738, 899, 3380, 4429, 4430, 143, 3868, 219, 2801, 628, 3381, 220, 1597, 4431, 1598, 221, 1493, 3693, 2802, 3869, 1599, 2572, 4739, 4740, 900, 901, 5439, 1494, 3595, 811, 1353, 4741, 1141, 4432, 3694, 222, 902, 223, 2803, 144, 629, 5358, 1495, 630, 4433, 2573, 1600, 5359, 4742, 224, 631, 225, 4743, 226, 1601, 632, 3196, 4744, 812, 903, 1602, 904, 905, 5440, 5441, 5442, 1354, 5443, 1355, 1142, 5444, 906, 1603, 5445, 1143, 1496, 227, 3870, 1144, 4745, 4746, 1604, 4747, 24, 5446, 1605, 2804, 1606, 2805, 1607, 2806, 1356, 4434, 2574, 4435, 4748, 4749, 633, 1145, 3871, 634, 3197, 3596, 2575, 2807, 228, 3872, 635, 229, 5360, 2808, 1608, 1609, 1610, 4750, 1611, 3198, 1612, 3597, 4751, 2576, 3695, 5361, 2577, 2578, 4752, 4753, 1357, 907, 3696, 1613, 1614, 1615, 1358, 4354, 4754, 2809, 3598, 4436, 636, 3382, 2579, 3383, 3384, 3599, 5447, 3873, 3874, 3875, 3876, 3877, 3878, 4437, 4755, 908, 4756, 4438, 3879, 4439, 4757, 2810, 637, 4758, 1, 2811, 3697, 2580, 3385, 1616, 2812, 25, 2813, 145, 4440, 1617, 4759, 813, 5448, 2430, 1618, 3880, 3881, 230, 4760, 909, 638, 4441, 2431, 5449, 146, 4761, 4762, 4763, 2432, 3386, 910, 1146, 5450, 5451, 1147, 1148, 1149, 1150, 4764, 1619, 3882, 2433, 2581, 3698, 231, 2434, 232, 3387, 639, 814, 4765, 1620, 911, 4442, 4443, 4444, 4445, 4446, 3883, 4447, 2814, 4766, 1151, 1621, 640, 4767, 2582, 1622, 1623, 4448, 1497, 2815, 5452, 2435, 233, 3884, 4768, 1624, 3885, 1152, 1359, 1625, 3886, 2583, 3699, 1626, 641, 4769, 2816, 2436, 3700, 147, 4770, 234, 4449, 4771, 3388, 235, 3199, 2584, 2585, 26, 815, 27, 2586, 1360, 4772, 236, 1153, 1361, 3887, 2817, 237, 5453, 3600, 3888, 3889, 3890, 238, 4773, 5362, 3891, 1627, 3601, 4450, 2818, 3892, 3389, 642, 239, 3390, 148, 1154, 3200, 4774, 4775, 643, 240, 912, 3391, 241, 242, 5454, 644, 3893, 1628, 4776, 4777, 1498, 28, 3392, 4778, 1499, 645, 4779, 2587, 4780, 646, 647, 1500, 2819, 913, 1629, 1155, 2820, 3393, 4451, 1156, 29, 2437, 2588, 3201, 2589, 3394, 3202, 3602, 1630, 243, 4452, 244, 1631, 3203, 30, 1632, 1633, 2438, 3395, 1157, 4453, 2439, 149, 3894, 4781, 3701, 3895, 1158, 1634, 1635, 2590, 4782, 1159, 5455, 4783, 3396, 1636, 150, 3204, 3397, 1637, 3205, 1638, 1639, 4454, 4784, 1640, 4785, 4786, 245, 2821, 4455, 816, 1641, 2822, 2823, 1362, 4787, 3398, 246, 2591, 2824, 648, 2592, 4404, 2825, 3896, 3897, 3898, 1160, 3899, 151, 3900, 247, 31, 152, 3399, 4788, 1642, 4456, 1643, 2826, 3702, 3206, 1501, 4789, 4790, 3207, 1644, 1161, 3208, 3603, 4457, 914, 1645, 2593, 3400, 3703, 3901, 4458, 248, 1646, 249, 1162, 915, 1647, 1363, 1648, 3604, 817, 4459, 2827, 2440, 5456, 4791, 1163, 3902, 3401, 3903, 1649, 4460, 3904, 1650, 2594, 2828, 4792, 2829, 4461, 1651, 4405, 3402, 916, 1652, 250, 251, 1502, 2441, 3209, 1653, 2595, 917, 2596, 3905, 3403, 5363, 252, 4793, 4794, 153, 2597, 4795, 1654, 4796, 2830, 3906, 1655, 4797, 1656, 253, 4462, 3907, 4463, 4464, 3908, 2442, 4798, 2831, 32, 1657, 2443, 1503, 1658, 2832, 5457, 2, 3404, 803, 1659, 1364, 4799, 1660, 918, 1661, 3210, 818, 3211, 3704, 5458, 1164, 4800, 3212, 1165, 2598, 3405, 2599, 5364, 2444, 649, 254, 255, 2445, 2446, 919, 3909, 4801, 4802, 256, 1662, 257, 4465, 4466, 1663, 1664, 3213, 258, 1665, 3214, 3, 2447, 4803, 4804, 1166, 920, 1167, 921, 5459, 3406, 3407, 1168, 922, 259, 1169, 1666, 4355, 4805, 1667, 3910, 154, 2600, 1504, 260, 2601, 261, 1668, 923, 3408, 2602, 4356, 3215, 3605, 1669, 4806, 4807, 3216, 4467, 4808, 3911, 4357, 3912, 1365, 262, 924, 1670, 925, 1671, 1672, 2448, 2449, 3913, 2603, 926, 1673, 1170, 4809, 3606, 3217, 3914, 5460, 819, 2604, 2605, 2606, 33, 3915, 4358, 4810, 927, 263, 264, 1674, 265, 1675, 3218, 266, 267, 2833, 2834, 4811, 2835, 4812, 1676, 928, 3916, 4468, 2607, 3917, 3705, 3706, 3707, 4813, 268, 4814, 4815, 1171, 1172, 4816, 2608, 3409, 2609, 4817, 34, 3410, 1677, 4818, 3219, 125, 1678, 2610, 929, 930, 269, 3411, 2836, 4469, 3220, 270, 271, 1679, 2611, 272, 1680, 1505, 3918, 3221, 3919, 2837, 3920, 2838, 2839, 4470, 3607, 1681, 1682, 2450, 650, 3222, 1683, 1684, 35, 1685, 3921, 931, 1173, 2840, 3922, 4819, 2841, 2612, 2842, 1686, 932, 1366, 4820, 3412, 3923, 933, 36, 4471, 934, 273, 3413, 1687, 1688, 4472, 3924, 2843, 5365, 1689, 2844, 4473, 1690, 274, 37, 1506, 3708, 3414, 2845, 3415, 935, 4821, 2846, 3416, 2847, 3925, 4359, 1367, 3709, 1368, 1691, 936, 3926, 1369, 4822, 3608, 1692, 5461, 4474, 4823, 651, 937, 3223, 1693, 1694, 2451, 1370, 4824, 38, 275, 1695, 276, 1371, 4825, 3417, 277, 278, 279, 1696, 4360, 3927, 280, 2848, 3928, 1174, 4826, 4827, 281, 3929, 2849, 3930, 4475, 3710, 3931, 5366, 3224, 652, 5367, 4828, 3932, 4476, 282, 4406, 1697, 2850, 3609, 1175, 3418, 283, 3933, 155, 2452, 2851, 4477, 4829, 3934, 3935, 3936, 3937, 1698, 39, 5368, 3938, 4830, 284, 1699, 1700, 1701, 2613, 1702, 285, 1703, 4478, 1176, 653, 3939, 1704, 3419, 1705, 3420, 2852, 2453, 1706, 4831, 4479, 3940, 4, 3225, 1707, 3941, 4407, 1507, 3421, 4832, 1708, 286, 2853, 1709, 1710, 1711, 3610, 4833, 1712, 156, 2614, 3711, 3422, 287, 3942, 1713, 288, 4834, 3611, 1714, 157, 158, 820, 654, 3423, 289, 5369, 655, 5462, 656, 657, 1372, 2854, 3943, 1715, 3944, 1716, 3612, 1717, 1718, 1719, 1720, 1721, 1722, 938, 5463, 5370, 1723, 3226, 3712, 3713, 658, 3227, 1724, 40, 4408, 1177, 3228, 1725, 2615, 5464, 3229, 1178, 1726, 1727, 4835, 1728, 290, 3945, 1729, 659, 2855, 5465, 3946, 3613, 3230, 2616, 1730, 4836, 1508, 2454, 1373, 4361, 939, 821, 3424, 4837, 2856, 291, 1731, 940, 4838, 2857, 4480, 660, 1732, 1733, 3231, 4839, 2617, 292, 2618, 293, 3947, 1734, 661, 941, 294, 2619, 1735, 662, 942, 1736, 4481, 1179, 3948, 3425, 3714, 1180, 4840, 663, 3232, 5371, 1737, 4482, 3949, 5466, 2858, 295, 1738, 1181, 1739, 1182, 1183, 4362, 943, 4841, 4842, 3950, 2859, 3951, 3715, 3952, 3953, 3954, 4483, 4843, 2860, 944, 3233, 3234, 41, 1740, 1741, 3955, 5467, 5468, 1742, 1374, 1743, 945, 4484, 1509, 1184, 4485, 4844, 3956, 3957, 664, 4845, 2455, 1744, 3958, 2861, 665, 666, 296, 3959, 4363, 3960, 2862, 297, 2863, 946, 1185, 3961, 298, 1745, 3962, 1746, 1747, 1375, 1748, 4846, 2864, 299, 159, 3426, 3427, 4486, 3428, 1376, 947, 300, 160, 1186, 1187, 1749, 42, 3429, 2456, 822, 1377, 4847, 1188, 3963, 948, 5469, 5470, 1378, 4848, 2865, 3430, 3431, 43, 2866, 3964, 4364, 1750, 5471, 1751, 3614, 1752, 1379, 2620, 1753, 823, 1754, 301, 1755, 1756, 1757, 3615, 302, 2457, 3432, 824, 303, 304, 1189, 1758, 1759, 1760, 5472, 1761, 4849, 4850, 4487, 2458, 2621, 3235, 305, 2622, 306, 3965, 1762, 1763, 1380, 2623, 1764, 1765, 1766, 2867, 1767, 1381, 1768, 2868, 1769, 1770, 3966, 1771, 2869, 307, 1772, 3967, 44, 3968, 1773, 308, 2870, 3616, 4851, 309, 4488, 1774, 1775, 667, 2624, 1510, 310, 1776, 2871, 1777, 4852, 1190, 1778, 3969, 3970, 2872, 3716, 1779, 4489, 3717, 311, 3433, 4853, 4490, 1780, 1781, 3971, 1511, 2873, 1782, 1783, 1784, 949, 1785, 1786, 4491, 3434, 3236, 312, 3237, 1512, 950, 951, 4854, 2874, 4365, 4492, 45, 4855, 4856, 4366, 1513, 313, 4857, 3972, 1382, 1787, 5473, 3973, 1514, 2625, 46, 668, 669, 4858, 314, 4493, 1788, 315, 3974, 1789, 4859, 3975, 3976, 5474, 3435, 1790, 952, 1791, 953, 1792, 5372, 3436, 316, 954, 5475, 670, 955, 1793, 671, 3977, 317, 2626, 2875, 4860, 3978, 4861, 1794, 2876, 2877, 5, 2878, 3979, 3718, 1795, 2879, 4862, 2627, 1383, 2628, 2629, 2630, 4367, 956, 3238, 2459, 5373, 4863, 4494, 4495, 1796, 3239, 318, 3437, 2460, 2880, 4496, 2881, 3438, 3719, 2631, 1797, 3439, 2632, 2461, 3440, 2462, 2463, 1191, 1384, 1798, 3240, 126, 957, 2633, 958, 5476, 319, 1799, 3980, 959, 1192, 1800, 1801, 47, 1802, 3441, 1385, 1515, 672, 3981, 4864, 4497, 1803, 2634, 1804, 1805, 3982, 4865, 2635, 2882, 2883, 2884, 1806, 1386, 5477, 320, 3983, 1807, 1808, 4498, 960, 4866, 3442, 5374, 1809, 1810, 1811, 825, 4867, 1812, 1813, 961, 5478, 1814, 1815, 1816, 4868, 4869, 3984, 3985, 1516, 5479, 3986, 48, 2885, 4870, 1387, 321, 1817, 1818, 2464, 3443, 3987, 3444, 1819, 322, 3988, 1193, 3989, 1820, 1821, 826, 3445, 4499, 1822, 3990, 2636, 1823, 1824, 1825, 827, 1826, 1827, 3241, 1517, 2886, 4871, 1828, 1518, 2887, 3991, 4500, 3992, 3720, 2888, 962, 4872, 4873, 3617, 2637, 5480, 4874, 1194, 3618, 1829, 4875, 828, 963, 964, 161, 1519, 4876, 2465, 3993, 3446, 4877, 3447, 4878, 323, 1830, 2638, 4879, 4880, 4881, 4882, 3994, 3721, 324, 3995, 2889, 2890, 1831, 4883, 1832, 3619, 3996, 1833, 325, 4501, 1834, 2891, 3997, 3998, 162, 6, 3722, 3999, 4000, 673, 326, 4502, 4001, 4002, 4003, 4503, 1835, 3242, 4004, 1836, 1837, 2639, 4005, 2892, 3448, 5481, 1195, 2893, 4368, 1838, 3723, 1839, 4884, 4885, 327, 4006, 4007, 5375, 4008, 4009, 1840, 4886, 1196, 4010, 4887, 1841, 49, 1842, 965, 4888, 1843, 4011, 328, 4889, 4012, 1844, 329, 674, 1845, 1846, 3724, 3243, 2640, 4013, 966, 1847, 1848, 675, 2466, 2894, 4014, 4890, 3449, 330, 5482, 1520, 2895, 4015, 4504, 4016, 967, 2896, 4017, 7, 331, 332, 50, 3244, 5376, 1197, 1849, 3725, 1850, 1851, 4018, 51, 1388, 2897, 2898, 1852, 3245, 1198, 3726, 4891, 4892, 4893, 4894, 127, 3246, 1853, 1854, 2899, 1521, 5483, 1389, 333, 5484, 334, 968, 52, 2900, 4505, 4895, 2901, 3727, 4896, 3247, 4019, 969, 3450, 2902, 3248, 335, 2467, 3451, 1855, 2903, 3452, 4020, 4506, 2904, 4897, 4898, 163, 4021, 1856, 4022, 970, 1199, 2905, 336, 4507, 971, 1857, 5485, 4023, 676, 4508, 677, 1858, 1200, 4024, 678, 1201, 1859, 2906, 2907, 4509, 4899, 3453, 2908, 3454, 1860, 2909, 3728, 1861, 3455, 4900, 1862, 3456, 1863, 4901, 679, 4025, 1864, 1865, 1866, 2641, 3249, 5377, 4510, 1867, 1868, 3457, 1869, 1870, 3729, 829, 1871, 4902, 2642, 4903, 1872, 3730, 4511, 3250, 972, 1873, 337, 3251, 5378, 4904, 4026, 4512, 2468, 4027, 4513, 4514, 4905, 1390, 4028, 338, 4906, 3458, 4029, 1391, 2910, 5379, 4907, 680, 4030, 339, 4908, 4031, 3459, 53, 4032, 1874, 4909, 340, 1392, 1522, 3252, 4033, 1202, 2911, 1875, 3253, 1876, 973, 974, 975, 2469, 976, 3731, 977, 5486, 978, 5487, 979, 2912, 2913, 1877, 1203, 341, 1878, 1879, 980, 1204, 4515, 3732, 1205, 1206, 4369, 830, 1207, 342, 1208, 1209, 1880, 681, 1210, 5380, 1211, 4034, 4035, 4036, 2914, 3254, 682, 683, 1881, 4516, 3255, 4037, 4517, 684, 3733, 1882, 4038, 4518, 831, 3460, 4039, 4910, 4911, 2915, 4912, 2916, 685, 164, 4370, 343, 3734, 2917, 344, 1883, 1884, 4913, 4914, 3620, 2918, 981, 4040, 2919, 4915, 2643, 4916, 2920, 4917, 1885, 4519, 686, 1886, 5488, 982, 687, 4520, 1887, 1888, 4918, 4041, 983, 2921, 4919, 1393, 832, 2922, 2923, 1889, 4920, 4921, 345, 4922, 2924, 1890, 4923, 4924, 3461, 984, 4925, 4521, 4926, 4522, 4927, 1891, 1523, 1892, 1212, 1893, 1394, 1894, 1895, 2644, 2645, 2470, 5489, 4928, 4042, 985, 1896, 346, 4929, 4043, 4523, 4044, 688, 986, 987, 4930, 2925, 689, 4045, 4931, 3462, 4046, 165, 4047, 1213, 4932, 988, 4933, 347, 1897, 4934, 3256, 2926, 4048, 690, 4935, 54, 833, 2927, 1898, 1899, 4049, 1900, 4524, 691, 2646, 348, 349, 4525, 350, 351, 692, 3257, 352, 353, 2928, 354, 4936, 1901, 1902, 834, 4050, 3258, 4526, 355, 356, 4051, 4937, 357, 1903, 4052, 358, 4938, 835, 359, 1904, 1905, 4939, 360, 693, 4527, 1906, 2929, 1214, 4940, 361, 694, 836, 3735, 4941, 55, 362, 4942, 2647, 4943, 1907, 1215, 1216, 2471, 2472, 3259, 4944, 1908, 363, 56, 4053, 3621, 364, 4945, 2930, 3260, 1909, 1524, 695, 2931, 1910, 4054, 4946, 5381, 3261, 3463, 4947, 4948, 365, 4528, 1911, 4055, 2648, 4529, 2932, 4056, 1912, 4530, 2933, 4531, 4057, 1217, 2934, 989, 2935, 3262, 1913, 1914, 4532, 4949, 696, 4058, 4950, 1915, 2936, 4951, 990, 5382, 1395, 2649, 1916, 3263, 4059, 366, 2473, 57, 1917, 1918, 3464, 991, 1919, 1525, 4952, 4533, 1920, 992, 1921, 3736, 697, 1922, 698, 4953, 4060, 367, 4954, 4955, 1923, 368, 4956, 4534, 369, 2937, 993, 1396, 3465, 4061, 166, 2474, 3264, 994, 2938, 4535, 4957, 699, 4958, 4536, 3265, 3737, 700, 5490, 1924, 4537, 370, 701, 4409, 2939, 4959, 4538, 4062, 1925, 371, 372, 167, 4539, 4960, 4961, 373, 374, 2940, 4540, 702, 375, 2941, 4541, 2475, 837, 3466, 995, 4542, 4063, 2650, 5383, 5384, 376, 4962, 377, 996, 5385, 1926, 1927, 1928, 3622, 378, 5491, 1929, 1930, 379, 168, 3266, 4064, 380, 381, 382, 383, 838, 384, 3623, 2942, 1931, 997, 998, 5492, 4963, 3267, 703, 3467, 4543, 1218, 1932, 2943, 704, 2476, 999, 3738, 4544, 4964, 4965, 385, 1933, 386, 3624, 387, 1934, 169, 1935, 388, 1936, 2944, 389, 2945, 3268, 1937, 1938, 1939, 390, 4966, 1940, 1397, 391, 1941, 1942, 4967, 3625, 1000, 1943, 705, 392, 393, 394, 1944, 4968, 1219, 2946, 4545, 839, 2947, 3626, 3269, 395, 4969, 1945, 4970, 4971, 396, 706, 4972, 170, 4546, 1001, 4973, 5493, 3270, 397, 707, 4547, 4974, 1526, 5494, 2651, 4975, 5386, 2652, 4371, 4065, 4976, 4977, 1002, 4978, 398, 4066, 1527, 3271, 840, 399, 4979, 708, 4980, 1003, 4067, 3627, 1946, 4981, 4068, 400, 4982, 709, 2653, 3739, 1947, 1398, 128, 1004, 3468, 1948, 2948, 1949, 1950, 1220, 1399, 4983, 4984, 401, 402, 4985, 403, 4986, 404, 405, 1951, 1952, 1005, 1953, 4987, 2477, 4548, 1954, 1955, 4988, 406, 841, 2949, 2950, 2951, 2952, 1528, 1006, 4069, 4070, 3272, 4549, 407, 4989, 2953, 4071, 4990, 1956, 3740, 408, 2654, 58, 2478, 4991, 2954, 4992, 1400, 1957, 4550, 409, 3469, 1958, 59, 4072, 2479, 4993, 1959, 4073, 2955, 410, 1960, 4074, 411, 842, 710, 4075, 2956, 711, 712, 412, 4994, 713, 4551, 1961, 3470, 4995, 4996, 1962, 1963, 1007, 2957, 413, 3741, 4997, 3742, 1401, 2958, 1964, 3743, 1965, 60, 5387, 3628, 3744, 2959, 5388, 1966, 1529, 171, 2960, 3273, 4076, 1008, 4552, 1530, 61, 714, 1531, 2961, 3745, 3746, 3471, 3747, 2962, 4553, 4998, 4077, 4999, 4372, 1009, 2963, 3274, 1532, 715, 1221, 3275, 3472, 5000, 5495, 1010, 1402, 1967, 1968, 1222, 1969, 62, 414, 1970, 1971, 1972, 415, 2655, 5001, 843, 3473, 1973, 2964, 1011, 4373, 716, 416, 417, 4554, 1974, 1975, 5002, 3276, 3748, 3474, 3749, 418, 1223, 1976, 844, 2656, 1977, 5003, 1978, 63, 3277, 3475, 2965, 2657, 3476, 4078, 4555, 1979, 8, 4556, 5004, 3750, 3477, 1980, 1981, 1224, 1982, 1012, 1403, 2658, 5496, 1983, 2659, 419, 717, 3478, 718, 3278, 420, 3751, 1404, 1984, 3479, 4079, 5005, 5006, 1225, 2660, 64, 3752, 5007, 2966, 65, 5008, 3279, 4557, 5009, 5010, 1985, 2967, 3280, 3480, 2661, 2662, 172, 1986, 1405, 2480, 1406, 421, 1013, 2968, 422, 423, 173, 1533, 1987, 2969, 174, 4558, 1988, 1534, 424, 1989, 5389, 4559, 1226, 1227, 1228, 1229, 2663, 3481, 4080, 3753, 66, 5497, 1990, 2664, 3281, 3754, 3482, 3755, 3483, 3282, 1230, 3283, 3484, 3485, 5498, 3284, 1991, 4081, 1992, 1993, 1994, 3285, 1231, 3756, 425, 3757, 1014, 1995, 2665, 4082, 4083, 5011, 3486, 4560, 1535, 426, 3629, 4084, 5499, 4085, 4561, 1232, 427, 428, 3286, 429, 3758, 3759, 1996, 430, 1997, 1407, 1998, 3487, 2970, 431, 845, 1999, 2971, 129, 5012, 5390, 2972, 2000, 2666, 4562, 432, 4563, 5500, 5013, 2001, 719, 4086, 5014, 2002, 4564, 5015, 2003, 433, 5016, 4565, 2004, 1015, 2973, 4087, 2005, 434, 2974, 1233, 2006, 5017, 2007, 3287, 67, 2481, 720, 2975, 5018, 4566, 4088, 4089, 846, 5019, 2667, 435, 5501, 2976, 2977, 2668, 2978, 2008, 4567, 5020, 1234, 5021, 5022, 1408, 5023, 2669, 5024, 1409, 3760, 5025, 3488, 1235, 436, 3761, 2009, 2010, 4568, 2979, 5026, 2011, 2980, 5027, 2981, 5028, 2012, 4569, 1016, 3489, 5502, 3630, 3762, 437, 4090, 5391, 130, 3288, 438, 5029, 3763, 5030, 439, 5031, 68, 2013, 4091, 4374, 2014, 3289, 4570, 3631, 440, 721, 3490, 441, 2015, 2670, 2482, 442, 4571, 2483, 1236, 5032, 3632, 443, 444, 5033, 5034, 1017, 4572, 69, 3764, 4573, 2016, 445, 446, 5392, 5393, 2982, 2671, 2672, 1018, 2983, 2017, 4092, 175, 2673, 176, 3290, 177, 9, 2984, 2985, 2986, 5035, 2987, 2018, 3633, 2988, 2019, 2020, 178, 3491, 2989, 10, 4093, 447, 448, 2021, 847, 4094, 2022, 70, 1019, 179, 2484, 5036, 1237, 5037, 4574, 1536, 2485, 722, 449, 71, 450, 3291, 1238, 723, 1239, 2486, 5038, 4095, 848, 4096, 451, 72, 4575, 2023, 2674, 1410, 4097, 3765, 452, 724, 3492, 3493, 2990, 73, 849, 11, 4576, 2675, 2024, 2991, 2992, 2025, 4098, 4099, 5503, 5039, 74, 3634, 2026, 850, 2993, 2994, 5040, 2995, 2996, 5041, 2027, 2997, 2998, 2028, 2487, 2676, 2029, 2999, 2030, 4100, 3000, 2031, 725, 5042, 3766, 2032, 5394, 3001, 1020, 453, 726, 3494, 2677, 4577, 4101, 454, 75, 1240, 2033, 5043, 2678, 5504, 3002, 2034, 2035, 2036, 2037, 2038, 3495, 455, 1241, 2679, 3003, 2039, 4102, 2680, 4103, 4104, 3004, 2040, 1242, 1243, 4578, 2041, 1021, 76, 1411, 2681, 2042, 5044, 3005, 180, 1022, 5505, 727, 3767, 4105, 131, 2043, 456, 3006, 2488, 2044, 4579, 2489, 3635, 2045, 5045, 3007, 2046, 5046, 728, 5047, 2047, 3636, 77, 3768, 3496, 457, 3497, 3637, 5048, 458, 729, 1244, 730, 3498, 1023, 851, 1024, 78, 4106, 2048, 2049, 1025, 5049, 4375, 5050, 2050, 5051, 3638, 5506, 1245, 3008, 2051, 4107, 2052, 731, 1537, 1246, 3292, 5052, 459, 5507, 460, 4376, 5053, 3009, 5054, 1412, 5055, 2053, 4580, 1247, 3010, 732, 2490, 5056, 4581, 2054, 2055, 2682, 5057, 5058, 5059, 1026, 5395, 2491, 2492, 733, 5060, 1248, 5061, 4582, 5062, 2056, 3499, 3500, 2057, 734, 2683, 2058, 852, 3769, 4108, 2493, 3770, 1027, 2059, 5396, 3501, 5063, 4109, 5064, 5065, 2060, 5066, 2061, 4110, 4583, 2062, 4584, 5067, 3771, 5508, 2063, 2684, 5068, 4377, 461, 2064, 5509, 2065, 2685, 5069, 79, 4111, 1249, 2066, 1028, 2067, 1029, 1030, 735, 2068, 736, 3293, 3011, 3294, 4112, 462, 3012, 737, 1031, 4113, 5070, 1032, 3502, 4585, 2069, 463, 3503, 2070, 4586, 4114, 4115, 1250, 464, 5071, 1033, 3772, 4116, 5072, 1034, 2494, 4410, 738, 465, 4117, 466, 853, 4118, 4119, 739, 2686, 467, 468, 1035, 1538, 2071, 3013, 469, 854, 470, 855, 2072, 5397, 80, 3504, 5510, 471, 5073, 472, 2073, 1036, 2074, 2075, 5074, 2076, 4120, 2077, 5075, 3773, 2078, 2079, 3639, 5511, 5076, 2687, 4587, 1539, 473, 5512, 3295, 3505, 5077, 2080, 2688, 3506, 1037, 5398, 2081, 1038, 5078, 181, 5079, 4121, 474, 3640, 1251, 2082, 1540, 5080, 1039, 3774, 3641, 1413, 4122, 475, 4411, 1414, 5399, 5400, 5401, 3014, 5402, 3507, 1415, 5403, 3508, 5081, 3015, 4123, 1541, 1040, 3016, 1542, 4124, 1041, 3017, 1416, 4125, 2083, 4126, 1417, 4378, 4127, 5082, 476, 1418, 5083, 4128, 3018, 5084, 1252, 1042, 3775, 2084, 4588, 3019, 2495, 3020, 4129, 5085, 477, 3021, 2689, 3642, 1043, 5086, 1419, 5087, 4130, 478, 3643, 1044, 5088, 1253, 2496, 4589, 479, 1420, 3022, 2085, 3023, 5089, 4379, 1421, 1422, 2086, 1423, 1424, 1425, 5090, 1426, 3024, 740, 2690, 5513, 1254, 182, 4131, 4132, 2691, 4133, 2087, 2088, 4134, 3025, 4135, 480, 2089, 1045, 4136, 5514, 741, 3026, 1427, 3509, 4137, 3027, 2090, 481, 3028, 2497, 4590, 1428, 2091, 4380, 856, 1046, 4591, 482, 1429, 5091, 5515, 183, 5516, 184, 4138, 1047, 4139, 2092, 1048, 4140, 483, 4592, 5092, 1430, 4381, 1543, 3029, 5517, 81, 4141, 1431, 742, 2093, 3510, 1049, 2498, 2499, 1432, 3511, 1433, 4142, 484, 4143, 2094, 5093, 2500, 743, 5094, 3512, 2501, 132, 2095, 5095, 2692, 1255, 82, 3776, 83, 3513, 84, 2096, 5096, 2097, 3296, 1256, 485, 2693, 2098, 5518, 486, 2099, 85, 2100, 5097, 2101, 5098, 5099, 2502, 2102, 1050, 5100, 4593, 3297, 3298, 744, 3030, 5101, 5102, 4144, 5103, 4594, 2503, 487, 3299, 2504, 5104, 3031, 4595, 86, 2103, 3777, 2104, 2105, 4382, 2694, 4596, 5105, 1051, 2106, 3032, 5106, 488, 1052, 5107, 2505, 745, 4412, 746, 5404, 1257, 747, 748, 1053, 2107, 3514, 2108, 3515, 2109, 4597, 3033, 4145, 2110, 4598, 2111, 2112, 3516, 87, 5108, 1054, 2506, 749, 4599, 2113, 4600, 750, 3300, 4146, 5109, 3034, 5519, 489, 3035, 4601, 5110, 4147, 3517, 88, 3518, 1258, 5520, 490, 1055, 5521, 3301, 5522, 1056, 1057, 3036, 5111, 4148, 4602, 2114, 3037, 1058, 4149, 857, 3302, 5112, 4150, 89, 2115, 4603, 3519, 2116, 3644, 2117, 751, 2507, 2118, 5113, 4151, 3645, 1259, 5114, 752, 4604, 5115, 1544, 3038, 4152, 5523, 2119, 753, 491, 754, 3778, 5524, 3039, 3040, 1545, 1059, 1434, 5116, 3041, 5117, 3303, 1435, 3042, 1546, 2120, 5118, 2695, 492, 3646, 3779, 2508, 1060, 3780, 5119, 4153, 4383, 3781, 90, 185, 493, 91, 5120, 5121, 3520, 3521, 3304, 3782, 1260, 4154, 3783, 2121, 4155, 2122, 2123, 2124, 2696, 3784, 1261, 3522, 3305, 92, 4605, 4156, 4157, 2125, 4606, 1262, 2126, 3043, 3044, 2697, 2127, 3523, 2128, 2129, 5122, 3785, 3647, 494, 2509, 5525, 3524, 3786, 3306, 186, 2130, 3045, 5123, 5124, 1263, 2698, 3307, 3525, 5125, 2131, 495, 4158, 5126, 3046, 93, 4607, 1264, 2132, 4159, 3526, 496, 3047, 2133, 5127, 3308, 2134, 5128, 2135, 755, 2699, 133, 2136, 2137, 2138, 3787, 2700, 5405, 1436, 3788, 2139, 5129, 497, 4160, 2701, 2140, 4608, 5130, 5131, 1265, 5406, 5132, 2141, 5526, 498, 3789, 858, 5133, 1266, 1547, 3527, 3528, 2142, 4161, 2702, 2143, 3790, 5527, 2510, 1437, 4162, 4163, 756, 1267, 5134, 3791, 94, 4609, 757, 2144, 2145, 5528, 2146, 2147, 2148, 5135, 5136, 758, 1268, 2149, 4610, 1269, 3048, 3049, 3050, 1061, 5137, 2150, 4611, 3309, 3310, 4612, 3311, 1062, 3648, 95, 5138, 2703, 499, 2151, 4164, 2511, 3529, 2704, 5139, 2152, 2153, 2154, 2155, 3051, 500, 96, 2705, 1063, 5140, 2706, 3792, 2707, 2156, 4384, 3530, 4385, 501, 5141, 1270, 97, 502, 5142, 5529, 759, 2157, 3052, 4165, 4166, 3053, 4167, 3054, 4613, 5143, 3055, 5407, 3649, 4168, 1271, 4169, 4614, 859, 503, 4170, 2158, 3531, 1272, 5144, 760, 5145, 5146, 1064, 2159, 5147, 3532, 3650, 504, 3056, 5148, 2160, 5149, 5408, 2161, 5150, 2162, 2163, 98, 1065, 1273, 2164, 4171, 2165, 5151, 5152, 3057, 5530, 5153, 4172, 5154, 4615, 2166, 1066, 1067, 761, 505, 3533, 506, 2708, 3058, 3059, 5155, 2167, 2709, 5531, 860, 2168, 2512, 12, 1068, 3060, 507, 508, 3061, 4173, 5156, 4616, 1438, 2169, 5157, 5158, 3312, 1274, 2710, 3793, 2711, 4174, 99, 2712, 2170, 5409, 5410, 509, 1439, 2171, 2172, 510, 5159, 2713, 3313, 4617, 5160, 2173, 5161, 2513, 3062, 1548, 5162, 1440, 3063, 1069, 5163, 4175, 4618, 5532, 4619, 5533, 1441, 2174, 4176, 4620, 1442, 5164, 861, 2175, 2176, 511, 5165, 762, 5166, 1070, 3651, 3064, 3794, 4177, 1071, 763, 2177, 2514, 1072, 3534, 13, 4178, 1443, 3535, 5534, 3065, 3066, 4621, 100, 5411, 2515, 101, 3795, 1444, 1445, 1446, 5167, 5168, 2178, 1275, 134, 4179, 4180, 1549, 5535, 3652, 102, 3067, 1276, 512, 4622, 4386, 4181, 3068, 14, 4182, 1073, 2179, 764, 5169, 513, 5170, 765, 2180, 2181, 4183, 4623, 1447, 5171, 135, 514, 3069, 5172, 2182, 4624, 5173, 5536, 2516, 3070, 2183, 2714, 3536, 5174, 2184, 2185, 5175, 2186, 5176, 4625, 3071, 515, 1277, 5177, 187, 4626, 516, 1278, 2187, 862, 5537, 2188, 4184, 1279, 4387, 4627, 2189, 5178, 1280, 517, 1281, 5179, 2517, 3314, 4388, 1448, 1282, 3072, 4628, 2715, 1074, 4185, 5180, 5412, 4186, 2190, 3073, 5538, 3796, 4187, 2716, 5181, 4188, 2191, 3074, 5182, 3075, 2518, 3653, 3076, 4189, 3077, 103, 3078, 3537, 518, 2717, 3654, 5183, 5184, 2192, 1449, 3079, 4190, 519, 4629, 3080, 5185, 4191, 3315, 1075, 3655, 3081, 766, 2718, 3316, 520, 767, 768, 769, 770, 3797, 3798, 521, 5186, 3082, 5187, 3083, 3084, 4630, 1283, 2193, 2194, 3085, 3086, 3317, 2195, 5539, 771, 2519, 5188, 3538, 4192, 2196, 3539, 5189, 5190, 5191, 4193, 522, 2719, 3087, 772, 3656, 2197, 3088, 1450, 3089, 2198, 2199, 5192, 4194, 523, 1284, 2720, 524, 2721, 5413, 525, 2722, 2200, 5540, 3799, 3318, 526, 3800, 2723, 2724, 2201, 3540, 3801, 5414, 1076, 1077, 1285, 1550, 5193, 527, 3541, 528, 3319, 5194, 5195, 1451, 3090, 5196, 2202, 529, 3091, 5197, 5198, 5199, 5200, 5201, 2203, 1452, 3542, 5415, 5202, 5203, 5204, 2204, 3092, 863, 3093, 3657, 3094, 15, 1453, 3095, 3096, 1551, 2205, 3658, 5205, 4389, 5541, 4631, 3659, 3660, 5206, 530, 3661, 531, 4632, 3802, 4633, 532, 2206, 4634, 2207, 5542, 4635, 4195, 2208, 3320, 4636, 4196, 5207, 3543, 104, 2209, 2520, 4637, 1552, 3097, 2210, 864, 2211, 4197, 2212, 2213, 2214, 2215, 188, 1078, 533, 4638, 5543, 2725, 1079, 1553, 2216, 5208, 4198, 4639, 2217, 5209, 4199, 1554, 2218, 4640, 4200, 2219, 534, 3803, 16, 4201, 3098, 4202, 4390, 2220, 4641, 3099, 4203, 4204, 1454, 3100, 2521, 1455, 4205, 4413, 5210, 1286, 2221, 5416, 3101, 4206, 1456, 5211, 105, 2222, 5212, 1080, 2223, 5213, 2522, 773, 535, 3804, 2224, 3102, 5214, 2225, 774, 2226, 4207, 5215, 3321, 4208, 5216, 5217, 5218, 4642, 2726, 3322, 5417, 2727, 3103, 3323, 2227, 536, 2523, 775, 5219, 3324, 4643, 5220, 5221, 2228, 5222, 1457, 3104, 4209, 3105, 5223, 4644, 537, 4210, 4211, 2524, 1287, 5544, 4212, 1081, 5545, 5224, 4645, 3325, 4213, 5225, 5226, 3106, 538, 2229, 5227, 1082, 2230, 2231, 2525, 4214, 2232, 5228, 539, 1458, 2728, 4646, 3107, 4215, 5229, 4216, 2729, 3326, 3805, 540, 3327, 5230, 5231, 541, 5232, 1083, 2233, 3108, 2234, 2526, 3328, 2235, 3544, 5233, 4217, 1459, 3545, 2236, 5234, 3109, 1084, 2237, 5546, 5235, 3329, 3546, 1288, 5236, 1289, 2730, 3110, 4647, 1085, 2238, 542, 1290, 2731, 3111, 1086, 5237, 3112, 189, 3113, 2527, 2239, 865, 3114, 5238, 3547, 543, 1291, 2240, 2732, 4391, 5418, 106, 2528, 1292, 2241, 4218, 3806, 4219, 3330, 5239, 544, 2529, 2242, 866, 3331, 4220, 3115, 2530, 2243, 2244, 5547, 3662, 3116, 5240, 3117, 776, 1293, 1294, 2733, 5241, 2245, 545, 2246, 2247, 2248, 1087, 2249, 1088, 1555, 5242, 2250, 5548, 1460, 4221, 2251, 1089, 4648, 5419, 5243, 3548, 17, 4649, 5549, 5244, 867, 2734, 4222, 1090, 3118, 5550, 546, 1461, 3332, 4650, 1091, 3119, 4651, 5551, 2252, 4223, 547, 136, 548, 4224, 5245, 2253, 2254, 2735, 5246, 2255, 777, 2531, 778, 2256, 2257, 107, 3120, 2258, 2259, 1295, 3807, 108, 2260, 3549, 2261, 5420, 3808, 2736, 2262, 549, 2532, 2533, 4225, 4652, 1462, 550, 4653, 5421, 1296, 5247, 2737, 5248, 4226, 3809, 5249, 1092, 4227, 3121, 4228, 1093, 551, 1463, 3550, 3663, 5250, 2263, 5251, 2264, 3122, 1094, 2265, 190, 2266, 2267, 5252, 1464, 2268, 4229, 3123, 5253, 4230, 2269, 2270, 3124, 2534, 1297, 3551, 4231, 4232, 552, 5254, 4233, 2271, 3125, 3552, 5255, 5256, 2272, 779, 1298, 3333, 2738, 1299, 2739, 2273, 3810, 5257, 4654, 5552, 3811, 3334, 4655, 1300, 5258, 4656, 4234, 109, 2274, 3553, 2535, 5259, 3335, 4657, 5260, 3126, 5422, 4658, 553, 554, 1095, 2740, 4659, 5423, 2275, 2536, 1301, 2537, 2741, 1302, 868, 2276, 4235, 555, 4392, 556, 1303, 2277, 1465, 557, 3554, 5553, 2538, 3812, 3664, 2278, 2742, 5261, 5424, 4236, 3555, 1096, 3665, 2279, 4237, 2280, 1304, 558, 2281, 4393, 1305, 3813, 2539, 3556, 4660, 559, 4238, 191, 869, 1556, 2282, 2283, 2540, 2284, 3666, 2285, 780, 3814, 3557, 2286, 3558, 2287, 2288, 2289, 560, 2290, 4239, 3127, 3128, 3336, 1306, 4661, 2291, 1097, 4414, 3667, 5262, 3559, 3560, 2292, 2293, 1098, 2541, 2294, 3561, 4240, 3562, 5263, 2295, 5264, 3668, 2542, 2296, 2543, 3563, 3129, 2743, 1307, 4662, 3130, 781, 2297, 2298, 4663, 2299, 2300, 1308, 2301, 5265, 3564, 4241, 2744, 3815, 1309, 4664, 2745, 3131, 1310, 2302, 2303, 4665, 5266, 2304, 3337, 4242, 3132, 3133, 3134, 4666, 2305, 5267, 3135, 3338, 2746, 110, 2306, 2307, 111, 2308, 561, 4243, 3136, 2747, 2748, 3816, 2749, 2750, 1311, 3669, 2309, 5268, 3339, 2751, 2752, 870, 3817, 4667, 4668, 2310, 3565, 3340, 2311, 4244, 4245, 4246, 562, 2312, 2313, 4247, 4248, 3566, 3567, 1466, 1467, 5269, 5270, 2753, 3818, 4249, 3670, 1468, 4250, 1312, 5271, 2754, 3137, 1469, 2755, 3568, 4251, 2314, 3341, 5272, 4669, 3569, 4252, 4670, 1313, 1099, 782, 3570, 112, 1314, 4415, 1100, 5273, 4253, 2756, 3138, 5274, 4254, 4255, 4671, 4256, 871, 1315, 3139, 3819, 5275, 3571, 4672, 563, 4257, 2757, 5425, 2315, 1101, 3572, 3820, 2544, 4394, 3140, 4673, 1102, 3573, 5554, 113, 114, 4258, 1103, 5276, 4259, 192, 3821, 3822, 5277, 1316, 3671, 1470, 4260, 2316, 4261, 4674, 4262, 3141, 3142, 3143, 3574, 2317, 4263, 5278, 1317, 2318, 3823, 1318, 1319, 3575, 1320, 2319, 5279, 2320, 872, 5555, 115, 5280, 3144, 2321, 2545, 5281, 2322, 2758, 3672, 2323, 4264, 2324, 2325, 2326, 564, 2327, 2328, 5556, 193, 2759, 4265, 1104, 5282, 2329, 2330, 3145, 3824, 2331, 4266, 4267, 5557, 4268, 4269, 3825, 5283, 2332, 2760, 4270, 1321, 3342, 2761, 565, 1471, 4271, 3146, 2333, 2546, 3673, 4272, 3674, 3147, 4273, 5284, 2334, 5285, 2335, 566, 116, 1322, 567, 3148, 4675, 568, 4676, 569, 4677, 5286, 3576, 570, 3577, 4274, 4275, 4276, 4277, 1557, 2336, 18, 1323, 2337, 1105, 2338, 3826, 2339, 3827, 19, 2340, 2547, 1324, 2341, 783, 117, 784, 4278, 3149, 571, 2342, 2343, 2344, 4279, 572, 4280, 2345, 4395, 4281, 2346, 3675, 873, 4678, 5287, 2347, 2762, 3828, 2763, 2348, 3829, 3830, 137, 573, 2349, 2350, 574, 2764, 5288, 3831, 1472, 575, 2765, 3343, 5289, 2351, 1325, 1106, 2352, 3150, 2353, 2766, 576, 3832, 3833, 3344, 2354, 577, 3151, 3345, 3152, 4282, 4283, 2767, 5290, 5291, 4284, 2355, 1558, 2356, 4285, 3834, 5292, 4679, 1559, 3578, 3676, 1107, 5558, 4286, 2357, 5293, 194, 2358, 5426, 2359, 3579, 578, 1108, 2360, 3580, 4287, 1473, 3153, 3346, 5427, 1109, 579, 580, 1326, 3835, 5559, 581, 4288, 2768, 785, 2361, 5294, 3581, 2769, 2770, 4289, 2362, 3347, 786, 4680, 1560, 874, 5295, 1474, 2771, 2548, 2772, 582, 5560, 1327, 1328, 5296, 4681, 3154, 5297, 2773, 3677, 3348, 3582, 5298, 5299, 4290, 1475, 5300, 195, 5301, 3349, 5302, 5561, 583, 3836, 2363, 787, 3350, 3351, 5303, 2774, 1561, 5304, 5562, 5305, 2549, 4682, 2364, 5563, 3837, 5306, 5564, 3352, 3155, 5307, 3156, 788, 3583, 5308, 3838, 4683, 1476, 3678, 584, 118, 3584, 585, 586, 2365, 196, 3157, 4291, 4292, 587, 2775, 4293, 2366, 3158, 2367, 5309, 588, 5310, 1477, 4294, 2368, 5311, 1110, 119, 4295, 5312, 3353, 5313, 5314, 4296, 1562, 5315, 20, 789, 138, 5316, 2369, 1329, 5317, 790, 5318, 2776, 4297, 197, 2777, 589, 3159, 2370, 4396, 791, 5319, 3160, 5428, 3839, 3840, 4298, 2778, 590, 5320, 591, 2371, 592, 120, 1563, 3585, 1111, 3679, 3354, 1112, 2550, 3161, 4299, 593, 3355, 1478, 3162, 3163, 5321, 2551, 1479, 4300, 4397, 792, 3164, 3841, 3842, 5322, 4684, 4685, 3165, 3356, 3843, 4686, 1330, 4687, 4688, 5323, 1331, 2372, 4301, 2373, 4302, 2374, 5429, 5565, 5566, 2375, 2376, 2377, 3166, 5430, 3167, 2378, 2552, 198, 3357, 1480, 4303, 5324, 4304, 5325, 3844, 5326, 2553, 3358, 121, 2554, 793, 3680, 4305, 4306, 594, 5327, 4307, 4689, 3168, 4308, 2379, 4309, 4310, 4311, 5328, 1564, 2380, 4312, 4313, 2381, 1113, 3681, 4690, 4691, 4692, 1114, 3359, 4314, 2779, 3360, 4315, 3845, 1332, 1115, 4693, 4694, 595, 2555, 4316, 2556, 1333, 5329, 2382, 4695, 4317, 3169, 3170, 1334, 5330, 2383, 3361, 4318, 4319, 4320, 4321, 3362, 3171, 5331, 5567, 5568, 1335, 1336, 5332, 2384, 5333, 4322, 794, 1116, 1117, 3172, 4696, 2385, 1337, 199, 596, 2386, 2387, 597, 598, 795, 2388, 5334, 599, 5335, 2389, 2390, 5336, 3173, 4323, 5337, 600, 4416, 1118, 2780, 2557, 796, 3846, 5431, 601, 2391, 2781, 797, 3174, 602, 2392, 3586, 4324, 3175, 2393, 4697, 1481, 122, 5338, 3176, 4325, 3847, 3177, 603, 5339, 1338, 5340, 1119, 1120, 2394, 2558, 4698, 798, 2395, 200, 604, 3587, 2396, 201, 4326, 799, 4398, 4699, 5341, 4700, 1121, 605, 4327, 1482, 4399, 4400, 4328, 4329, 4330, 606, 3682, 3588, 607, 5342, 5343, 5344, 1122, 4331, 4701, 4702, 5345, 2397, 875, 2398, 4703, 1339, 2399, 5346, 5347, 2400, 1123, 2401, 800, 3683, 2782, 3848, 801, 3589, 2402, 608, 609, 1483, 3590, 610, 5348, 611, 2403, 3684, 2404, 4332, 876, 3849, 3178, 3363, 1484, 612, 3850, 4333, 5349, 3179, 3591, 4334, 3364, 2405, 3180, 613, 2406, 2407, 2408, 3365, 3366, 2409, 4335, 4336, 4337, 877, 1340, 1124, 3367, 4338, 1565, 1125, 123, 2410, 3851, 802, 4339, 4704, 4705, 2411, 2783, 2559, 1485, 1126, 3852, 4340, 4341, 4342, 3592, 4343, 1341, 878, 1127, 1486, 879, 880, 4401, 5350, 5351, 2412, 2413, 2414, 2415, 3181, 2416, 2560, 4344, 5352, 4345, 4346, 2784, 4706, 881, 5353, 614, 4347, 3368, 139, 1342, 2561, 3182, 1343, 2417, 3685, 5354, 5355, 615, 3593, 5569, 616, 2418, 3183, 617, 4348, 4707, 5570, 3184, 4349, 4708, 21, 4709, 4710, 3369, 2562, 618, 2785, 5356, 1344, 4711], ) - def row_to_municipality(row: List[str]) -> Municipality: """Reads one dataset row as a municipality. """ return Municipality(code=row[2], name=row[1], state_code=row[0]) - def get_municipalities(state_code: Optional[str] = None) -> List[Municipality]: """Returns Brazilian municipalities published by the IBGE, optionally filtered by state. diff --git a/spec/bridge/out/python/brutils_bridge/is_valid_cnpj.py b/spec/bridge/out/python/brutils_bridge/is_valid_cnpj.py index 2a62a73d4..b78079c79 100644 --- a/spec/bridge/out/python/brutils_bridge/is_valid_cnpj.py +++ b/spec/bridge/out/python/brutils_bridge/is_valid_cnpj.py @@ -64,10 +64,6 @@ FIRST_DIGIT_WEIGHTS = [5, 4, 3, 2, 9, 8, 7, 6, 5, 4, 3, 2] SECOND_DIGIT_WEIGHTS = [6, 5, 4, 3, 2, 9, 8, 7, 6, 5, 4, 3, 2] - - - - @dataclass class IsValidCnpjOptions: """Options of `isValidCnpj`.""" @@ -75,10 +71,6 @@ class IsValidCnpjOptions: # Which CNPJ format to accept: `1` numeric only, `2` alphanumeric (default: `1`). version: Optional[int] = None - - - - def is_valid_cnpj(cnpj: Any, options: Optional[IsValidCnpjOptions] = None) -> bool: """Validates if a CNPJ (Cadastro Nacional da Pessoa Jurídica) is valid. @@ -104,7 +96,6 @@ def is_valid_cnpj(cnpj: Any, options: Optional[IsValidCnpjOptions] = None) -> bo return False return has_valid_checksum(numeric) - def check_digit(base: str, weights: List[int]) -> int: """Computes one CNPJ check digit from the base and its weight vector. """ @@ -116,7 +107,6 @@ def check_digit(base: str, weights: List[int]) -> int: return 0 return (11 - remainder) - def has_valid_checksum(cnpj: str) -> bool: """Whether both check digits of a sanitized 14 character CNPJ match its base. """ @@ -124,7 +114,6 @@ def has_valid_checksum(cnpj: str) -> bool: return False return ((code_at(cnpj, 13) - 48) == check_digit(cnpj, SECOND_DIGIT_WEIGHTS)) - def is_repeated(value: str) -> bool: """Whether every character of the value is the same one. """ diff --git a/spec/bridge/out/python/brutils_bridge/runtime.py b/spec/bridge/out/python/brutils_bridge/runtime.py index ed312c95a..17f4d59bd 100644 --- a/spec/bridge/out/python/brutils_bridge/runtime.py +++ b/spec/bridge/out/python/brutils_bridge/runtime.py @@ -23,7 +23,6 @@ + list(range(0x2000, 0x200B)) ) - class PatternStep: """One step of a compiled pattern: repeat a class between `min` and `max` times.""" @@ -35,7 +34,6 @@ def __init__(self, char_class: CharClass, minimum: int, maximum: int, capture: b self.max = maximum self.capture = capture - def in_class(char_class: CharClass, code: int) -> bool: """Whether a code point belongs to a class.""" for start, end in char_class: @@ -44,7 +42,6 @@ def in_class(char_class: CharClass, code: int) -> bool: return False - def code_at(value: str, index: int) -> int: """Reads one code unit, or -1 when the index is out of range.""" if index < 0 or index >= len(value): @@ -52,7 +49,6 @@ def code_at(value: str, index: int) -> int: return ord(value[index]) - def class_has(char_class: CharClass, value: str) -> bool: """Whether any character of the value belongs to the class.""" for char in value: @@ -61,12 +57,10 @@ def class_has(char_class: CharClass, value: str) -> bool: return False - def keep_class(char_class: CharClass, value: str) -> str: """Keeps only the characters of the value that belong to the class.""" return "".join(char for char in value if in_class(char_class, ord(char))) - def pattern_test(steps: Sequence[PatternStep], value: str) -> bool: """Runs a compiled pattern against the whole value, greedily and without backtracking.""" index = 0 @@ -87,7 +81,6 @@ def pattern_test(steps: Sequence[PatternStep], value: str) -> bool: return index == len(value) - def js_trim(value: str) -> str: """Strips the code points JavaScript's `trim()` strips.""" start = 0 @@ -100,12 +93,10 @@ def js_trim(value: str) -> str: return value[start:end] - def pad_start(value: str, length: int, filler: str) -> str: """Left pads the value with a filler up to a length.""" return value.rjust(length, filler) - def as_string(value: Any) -> str: """Reads a value as a string the way JavaScript's `String(value)` does.""" if isinstance(value, str): @@ -126,12 +117,10 @@ def as_string(value: Any) -> str: except Exception: # noqa: BLE001 - a value with no string form reads as empty, as in JavaScript return "" - def is_truthy(value: Any) -> bool: """Reads an optional flag the way JavaScript reads truthiness.""" return bool(value) - def list_get(values: List[Any], index: int) -> Any: """Reads one element, or None when the index is out of range.""" if index < 0 or index >= len(values): @@ -139,7 +128,6 @@ def list_get(values: List[Any], index: int) -> Any: return values[index] - class Dataset: """A dataset: the rows in the baked full order, and the rows of each key.""" @@ -149,22 +137,18 @@ def __init__(self, rows, groups, full_order): self.all = [rows[index] for index in full_order] self.by_key = {key: [rows[index] for index in indexes] for key, indexes in groups} - def make_dataset(rows, groups, full_order): """Materialises a dataset, resolving both orders once.""" return Dataset(rows, groups, full_order) - def data_all(table): """Every row of a dataset, in the baked full order.""" return table.all - def data_rows(table, key): """The rows whose first column is the key given, empty when the key is unknown.""" return table.by_key.get(key, []) - class HttpResponse: """What a provider answered: the HTTP status, whether it counts as a success, and the body.""" @@ -175,7 +159,6 @@ def __init__(self, status, ok, body): self.ok = ok self.body = body - def _http_target(url): """The origin every request is sent to instead of its own, when one is set. @@ -189,7 +172,6 @@ def _http_target(url): return base + "/" + re.sub(r"^https?://", "", url) - def http_get(url, retries, retry_delay_ms): """Performs an HTTP GET, retrying a transient transport failure with a linear backoff.""" target = _http_target(url) @@ -218,22 +200,18 @@ def http_get(url, retries, retry_delay_ms): return HttpResponse(status, 200 <= status < 300, body) - def is_number(value): """Whether the caller handed a number where a string or a number was declared.""" return isinstance(value, (int, float)) and not isinstance(value, bool) - def is_list(value): """Whether a value is a list.""" return isinstance(value, (list, tuple)) - def list_has(items, value): """Whether a list holds a value.""" return value in items - def _json_field(body, key): """Reads one field of a JSON body, treating anything that is not an object as empty.""" if not isinstance(body, dict): @@ -241,14 +219,12 @@ def _json_field(body, key): return body.get(key) - def json_string(body, key): """Reads a string field of a JSON body, answering "" when it is missing or not a string.""" found = _json_field(body, key) return found if isinstance(found, str) else "" - def json_int(body, key): """Reads an integer field of a JSON body, answering -1 when it is missing or not a number.""" found = _json_field(body, key) @@ -258,17 +234,14 @@ def json_int(body, key): return int(found) - def json_truthy(body, key): """Whether a field of a JSON body is truthy, the way JavaScript reads truthiness.""" return bool(_json_field(body, key)) - def json_is_true(body, key): """Whether a field of a JSON body is exactly True.""" return _json_field(body, key) is True - class Attempts: """The running attempts of a race, and what each one ended with.""" @@ -279,12 +252,10 @@ def __init__(self, total): self.total = total self.outcomes = [] - def _kinds_of(error): """The error name and every name it inherits from, which is what a failure is matched on.""" return [kind.__name__ for kind in type(error).__mro__ if kind is not object] - def start_all(run, items, argument): """Starts one attempt per item, all at once. @@ -304,7 +275,6 @@ def work(item=item): return attempts - def first_success(attempts): """The value of the first attempt that succeeds, or None once every attempt has failed.""" while len(attempts.outcomes) < attempts.total: @@ -316,7 +286,6 @@ def first_success(attempts): return None - def any_failed_with(attempts, kind): """Whether any attempt failed with a given error kind.""" return any(not ok and kind in kinds for ok, _value, kinds in attempts.outcomes) diff --git a/spec/bridge/out/ruby/lib/brazilian_utils_bridge/format_cnpj.rb b/spec/bridge/out/ruby/lib/brazilian_utils_bridge/format_cnpj.rb index 84542ed49..68255db46 100644 --- a/spec/bridge/out/ruby/lib/brazilian_utils_bridge/format_cnpj.rb +++ b/spec/bridge/out/ruby/lib/brazilian_utils_bridge/format_cnpj.rb @@ -10,18 +10,12 @@ module FormatCnpj CLASS0 = [[0x30, 0x39]].freeze CLASS1 = [[0x30, 0x39], [0x41, 0x5a], [0x61, 0x7a]].freeze - - PATTERN = "00.000.000/0000-00".freeze OBFUSCATED_PATTERN = "**.000.000/0000-**".freeze - - # Options of `formatCnpj`. FormatCnpjOptions = Struct.new(:pad, :version, :obfuscate, keyword_init: true) - - # Formats a given CNPJ (Cadastro Nacional da Pessoa Jurídica) value. def self.format_cnpj(value, options = nil) options_version = -1 diff --git a/spec/bridge/out/ruby/lib/brazilian_utils_bridge/get_address_info_by_cep.rb b/spec/bridge/out/ruby/lib/brazilian_utils_bridge/get_address_info_by_cep.rb index 4ffe0d015..9bcec37d3 100644 --- a/spec/bridge/out/ruby/lib/brazilian_utils_bridge/get_address_info_by_cep.rb +++ b/spec/bridge/out/ruby/lib/brazilian_utils_bridge/get_address_info_by_cep.rb @@ -40,8 +40,6 @@ class CepProviderFailure < StandardError; end # Options of `getAddressInfoByCep`. GetAddressInfoByCepOptions = Struct.new(:providers, keyword_init: true) - - # Reads the address ViaCEP answers with. # # @see Based on: https://viacep.com.br/ diff --git a/spec/bridge/out/ruby/lib/brazilian_utils_bridge/get_municipalities.rb b/spec/bridge/out/ruby/lib/brazilian_utils_bridge/get_municipalities.rb index c849574b7..ce988a4d0 100644 --- a/spec/bridge/out/ruby/lib/brazilian_utils_bridge/get_municipalities.rb +++ b/spec/bridge/out/ruby/lib/brazilian_utils_bridge/get_municipalities.rb @@ -8,13 +8,6 @@ module BrazilianUtilsBridge # Brazilian municipalities, written once. module GetMunicipalities - - - - - - - # One Brazilian municipality, as the IBGE publishes it. Municipality = Struct.new(:code, :name, :state_code, keyword_init: true) diff --git a/spec/bridge/out/ruby/lib/brazilian_utils_bridge/is_valid_cnpj.rb b/spec/bridge/out/ruby/lib/brazilian_utils_bridge/is_valid_cnpj.rb index 0217daf8e..0c8d995cf 100644 --- a/spec/bridge/out/ruby/lib/brazilian_utils_bridge/is_valid_cnpj.rb +++ b/spec/bridge/out/ruby/lib/brazilian_utils_bridge/is_valid_cnpj.rb @@ -40,13 +40,9 @@ module IsValidCnpj FIRST_DIGIT_WEIGHTS = [5, 4, 3, 2, 9, 8, 7, 6, 5, 4, 3, 2].freeze SECOND_DIGIT_WEIGHTS = [6, 5, 4, 3, 2, 9, 8, 7, 6, 5, 4, 3, 2].freeze - - # Options of `isValidCnpj`. IsValidCnpjOptions = Struct.new(:version, keyword_init: true) - - # Validates if a CNPJ (Cadastro Nacional da Pessoa Jurídica) is valid. # # Supports both numeric (version 1) and alphanumeric (version 2) CNPJ formats, and accepts the diff --git a/spec/bridge/out/rust/src/format_cnpj.rs b/spec/bridge/out/rust/src/format_cnpj.rs index d7c5396fe..5d300a7a3 100644 --- a/spec/bridge/out/rust/src/format_cnpj.rs +++ b/spec/bridge/out/rust/src/format_cnpj.rs @@ -7,13 +7,9 @@ use crate::runtime; const CLASS0: runtime::CharClass = &[(0x30, 0x39)]; const CLASS1: runtime::CharClass = &[(0x30, 0x39), (0x41, 0x5a), (0x61, 0x7a)]; - - const PATTERN: &str = "00.000.000/0000-00"; const OBFUSCATED_PATTERN: &str = "**.000.000/0000-**"; - - /// Options of `formatCnpj`. #[derive(Debug, Default, Clone, PartialEq, Eq)] pub struct FormatCnpjOptions { @@ -25,8 +21,6 @@ pub struct FormatCnpjOptions { pub obfuscate: Option, } - - /// Formats a given CNPJ (Cadastro Nacional da Pessoa Jurídica) value. pub fn format_cnpj(value: &str, options: Option<&FormatCnpjOptions>) -> String { let options_version = match options { diff --git a/spec/bridge/out/rust/src/get_address_info_by_cep.rs b/spec/bridge/out/rust/src/get_address_info_by_cep.rs index fd02936f6..064c9e475 100644 --- a/spec/bridge/out/rust/src/get_address_info_by_cep.rs +++ b/spec/bridge/out/rust/src/get_address_info_by_cep.rs @@ -78,8 +78,6 @@ pub struct GetAddressInfoByCepOptions { pub providers: Option>, } - - /// Reads the address ViaCEP answers with. /// /// @see Based on: https://viacep.com.br/ diff --git a/spec/bridge/out/rust/src/get_municipalities.rs b/spec/bridge/out/rust/src/get_municipalities.rs index bbc8d553b..e4568fdc3 100644 --- a/spec/bridge/out/rust/src/get_municipalities.rs +++ b/spec/bridge/out/rust/src/get_municipalities.rs @@ -4,14 +4,6 @@ use crate::runtime; - - - - - - - - /// One Brazilian municipality, as the IBGE publishes it. #[derive(Debug, Default, Clone, PartialEq, Eq)] pub struct Municipality { diff --git a/spec/bridge/out/rust/src/is_valid_cnpj.rs b/spec/bridge/out/rust/src/is_valid_cnpj.rs index 715d1f83f..92121ef36 100644 --- a/spec/bridge/out/rust/src/is_valid_cnpj.rs +++ b/spec/bridge/out/rust/src/is_valid_cnpj.rs @@ -37,8 +37,6 @@ const PATTERN_NUMERIC_FORMAT: &[runtime::PatternStep] = &[ const FIRST_DIGIT_WEIGHTS: [i64; 12] = [5, 4, 3, 2, 9, 8, 7, 6, 5, 4, 3, 2]; const SECOND_DIGIT_WEIGHTS: [i64; 13] = [6, 5, 4, 3, 2, 9, 8, 7, 6, 5, 4, 3, 2]; - - /// Options of `isValidCnpj`. #[derive(Debug, Default, Clone, PartialEq, Eq)] pub struct IsValidCnpjOptions { @@ -46,8 +44,6 @@ pub struct IsValidCnpjOptions { pub version: Option, } - - /// Validates if a CNPJ (Cadastro Nacional da Pessoa Jurídica) is valid. /// /// Supports both numeric (version 1) and alphanumeric (version 2) CNPJ formats, and accepts the diff --git a/spec/bridge/out/typescript/_bridge/format-cnpj.ts b/spec/bridge/out/typescript/_bridge/format-cnpj.ts index fb8eae484..1a4c034d5 100644 --- a/spec/bridge/out/typescript/_bridge/format-cnpj.ts +++ b/spec/bridge/out/typescript/_bridge/format-cnpj.ts @@ -7,15 +7,9 @@ import { asString, codeAt, isTruthy, keepClass, padStart, type CharClass } from const class0: CharClass = [[0x30, 0x39]]; const class1: CharClass = [[0x30, 0x39], [0x41, 0x5a], [0x61, 0x7a]]; - - const PATTERN = "00.000.000/0000-00"; const OBFUSCATED_PATTERN = "**.000.000/0000-**"; - - - - /** Options of `formatCnpj`. */ export type FormatCnpjOptions = { /** Whether to left pad the value with zeros up to the number of slots in the pattern (default: `false`). */ @@ -26,8 +20,6 @@ export type FormatCnpjOptions = { obfuscate?: boolean; }; - - /** * Formats a given CNPJ (Cadastro Nacional da Pessoa Jurídica) value. * diff --git a/spec/bridge/out/typescript/_bridge/get-address-info-by-cep.ts b/spec/bridge/out/typescript/_bridge/get-address-info-by-cep.ts index 6976ccb5c..4bc51f756 100644 --- a/spec/bridge/out/typescript/_bridge/get-address-info-by-cep.ts +++ b/spec/bridge/out/typescript/_bridge/get-address-info-by-cep.ts @@ -84,8 +84,6 @@ export type GetAddressInfoByCepOptions = { providers?: CepProvider[]; }; - - /** * Reads the address ViaCEP answers with. * diff --git a/spec/bridge/out/typescript/_bridge/get-municipalities.ts b/spec/bridge/out/typescript/_bridge/get-municipalities.ts index 174faebcd..8ed45c8f5 100644 --- a/spec/bridge/out/typescript/_bridge/get-municipalities.ts +++ b/spec/bridge/out/typescript/_bridge/get-municipalities.ts @@ -4,12 +4,6 @@ import { dataAll, dataRows, makeDataset } from "./_runtime.ts"; - - - - - - /** * The two letter code of a Brazilian state. Checked against the dataset by `data/build.ts`, so the union and the table can never drift apart. */ @@ -42,8 +36,6 @@ export type StateCode = | "SE" | "TO"; - - /** One Brazilian municipality, as the IBGE publishes it. */ export type Municipality = { /** The 7-digit IBGE municipality code. */ diff --git a/spec/bridge/out/typescript/_bridge/is-valid-cnpj.ts b/spec/bridge/out/typescript/_bridge/is-valid-cnpj.ts index ed071f350..f4e3ecdea 100644 --- a/spec/bridge/out/typescript/_bridge/is-valid-cnpj.ts +++ b/spec/bridge/out/typescript/_bridge/is-valid-cnpj.ts @@ -37,18 +37,12 @@ const PATTERN_NUMERIC_FORMAT: readonly PatternStep[] = [ const FIRST_DIGIT_WEIGHTS = [5, 4, 3, 2, 9, 8, 7, 6, 5, 4, 3, 2]; const SECOND_DIGIT_WEIGHTS = [6, 5, 4, 3, 2, 9, 8, 7, 6, 5, 4, 3, 2]; - - - - /** Options of `isValidCnpj`. */ export type IsValidCnpjOptions = { /** Which CNPJ format to accept: `1` numeric only, `2` alphanumeric (default: `1`). */ version?: 1 | 2; }; - - /** * Validates if a CNPJ (Cadastro Nacional da Pessoa Jurídica) is valid. *