From 7f5a0cb63cdf5a526de95040950979c21792c106 Mon Sep 17 00:00:00 2001 From: Lilleman auf Larv Date: Sun, 11 Oct 2026 16:38:42 +0200 Subject: [PATCH] Answer prose round 1: one name for a place holding most of a postal code's land, the decision leaves the seeding to the code, and the test says what it checks --- AGENTS.md | 2 +- CHANGELOG.md | 6 +++--- README.md | 6 +++--- data-import/geo-us.py | 2 +- data-import/geo.py | 4 ++-- data_test.go | 6 +++--- docs/decisions.md | 15 ++++++--------- todo.md | 4 ++-- 8 files changed, 21 insertions(+), 24 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index ee4f1bb..4c4f438 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -90,7 +90,7 @@ In [docs/decisions.md](docs/decisions.md): - A path is walked once without drawing before it is walked for real - A country's postal codes and streets are siblings under its locality - A locale package imports its country's geo package, and its `Modules()` returns both -- The default embed holds every Swedish postort the import can place, a tenth of the US places that are a postal code's main town drawn by population, and a tenth of each place's streets, at least ten +- The default embed holds every Swedish postort the import can place, a population-weighted tenth of the US places that hold most of a postal code's land, and a tenth of each place's streets, at least ten - A locale's `address` binds its country's record once and prints it whole - A postort's kommun comes from its name, its tätort or its codes, never from distance - A highway designation is not a street, and a US postal code belongs to the place holding most of its land inside places diff --git a/CHANGELOG.md b/CHANGELOG.md index 2d57ef8..6e91b3d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -93,9 +93,9 @@ replacement, and each removed path, column or flag. `address` record binding one locality and drawing its street and postal code inside it. `sv_SE.address` and `en_US.address` bind those records once, so `en_US.address.street` no longer carries `name` and `suffix`, and a locale's `address` - reads its country's `geo` module. Every Swedish postort ships, and a tenth of the US - incorporated places that are a postal code's main town, drawn by population down to - villages of a hundred people, so a city of any size may be missing; each place carries + reads its country's `geo` module. Every Swedish postort the import can place and give + a street ships, and a tenth of the US incorporated places that hold most of some postal + code's land, drawn by population down to villages of a hundred people, so a city of any size may be missing; each place carries a tenth of its streets, at least ten. - `{date(from,to,'layout')}` and `{time('layout')}`: a second between two days, or within one, in a single-quoted Go layout, drawn in UTC; `from` may equal `to`. diff --git a/README.md b/README.md index 31c4512..935eb14 100644 --- a/README.md +++ b/README.md @@ -313,13 +313,13 @@ neighbouring one. | `municipality` | kommun, by code or name | county, by FIPS code or name | population | | `locality` | postort, by name; [`geo-se.py`](data-import/geo-se.py)'s `localities` picks the candidates, and one with no street is dropped | incorporated place, by GEOID or name; Hawaii has none | tätort population, the kommun's where the postort names it, else 200; place population | | `postal-code` | postnummer with street delivery, by code | ZCTA, by code | one; address ranges | -| `street` | gatunamn, the tenth with most road segments per postort, at least ten | street name, the tenth with most address ranges per place, at least ten | segments; address ranges | +| `street` | gatunamn, per postort the tenth with most road segments, at least ten | street name, per place the tenth with most address ranges, at least ten | segments; address ranges | `geo.SE.region[Skåne län].municipality` draws a kommun in Skåne, `geo.SE.locality[Lund].street` a street in Lund, and `geo.US.region[IL].locality[Springfield]` settles which Springfield. The US places are a -tenth of the incorporated places that are a postal code's main town, drawn with odds by -population, so a city of any size may be missing: look one up in +tenth of the incorporated places that hold most of some postal code's land, drawn with +odds by population, so a city of any size may be missing: look one up in [`locality.tsv`](data/geo/US/locality.tsv) before selecting it. A region row carries its `timezone`, the state's predominant zone, and a locality its `lat` and `lon`. What ports across countries is the five table names, the `name` column, diff --git a/data-import/geo-us.py b/data-import/geo-us.py index 07310d9..e0c3960 100644 --- a/data-import/geo-us.py +++ b/data-import/geo-us.py @@ -129,7 +129,7 @@ def localities(cache, counties): def drawn(places, share): """The share of the places with people, each drawn with odds by its population: Efraimidis and Spirakis's weighted - sampling without replacement. Each place's random number is seeded by its code, so a place added or dropped from + sampling without replacement. Each place's random number is seeded by its code, so a place added to or dropped from the sources moves only the places near the cut.""" peopled = [code for code, p in places.items() if p["population"] > 0] key = {code: math.log(1 - random.Random(code).random()) / places[code]["population"] for code in peopled} diff --git a/data-import/geo.py b/data-import/geo.py index ea0faba..7a608e7 100644 --- a/data-import/geo.py +++ b/data-import/geo.py @@ -64,8 +64,8 @@ class Nearest: def top_streets(count, share, minimum, column): - """count maps (locality, street name) to a count. Returns, per locality, rows for the share of its names counted - most, at least minimum of them, ties broken by name; each row holds its count under column.""" + """count maps (locality, street name) to a count. Returns, per locality, rows for its most-counted names, share of + them rounded up and at least minimum, ties broken by name; each row holds its count under column.""" of = collections.defaultdict(list) for (locality, name), n in count.items(): of[locality].append((n, name)) diff --git a/data_test.go b/data_test.go index 49e2378..c28469f 100644 --- a/data_test.go +++ b/data_test.go @@ -376,8 +376,8 @@ func TestShippedAddressIsOneNamedPick(t *testing.T) { } } -// TestShippedPlacesSpreadAddresses pins that a city ships a tenth of its streets, not ten, -// and that the US places reach below a town. +// TestShippedPlacesSpreadAddresses pins that a big city ships 100 streets or more, and that +// some US place holds under 2,500 people. func TestShippedPlacesSpreadAddresses(t *testing.T) { for country, city := range map[string]string{"SE": "Göteborg", "US": "3651000"} { streets := 0 @@ -387,7 +387,7 @@ func TestShippedPlacesSpreadAddresses(t *testing.T) { } } if streets < 100 { - t.Errorf("geo.%s: %s ships %d streets, want a tenth of its streets, at least 100", country, city, streets) + t.Errorf("geo.%s: %s ships %d streets, want at least 100", country, city, streets) } } header, _, _ := strings.Cut(geoTSV(t, "US", "locality"), "\n") diff --git a/docs/decisions.md b/docs/decisions.md index f47fc04..d9a7bb7 100644 --- a/docs/decisions.md +++ b/docs/decisions.md @@ -603,16 +603,13 @@ providing `geo.SE`'s paths, and without one `sv_SE.address` fails at first reach `FS` works against goal 6.2. Every package exports `Modules()`, so one spelling loads any of them; a data package imports only the packages it reads. -## The default embed holds every Swedish postort the import can place, a tenth of the US places that are a postal code's main town drawn by population, and a tenth of each place's streets, at least ten +## The default embed holds every Swedish postort the import can place, a population-weighted tenth of the US places that hold most of a postal code's land, and a tenth of each place's streets, at least ten -2026-10-11, Lilleman auf Larv. Goals 2 and 14: ten streets a place crowded 500 -Stockholm customers onto ten streets, and US places of 25,000 or more left out every -town and village. `geo-us.py` draws among the places that are some ZCTA's main town, the -place holding most of its land inside places, since any other place can carry no postal -code, with Efraimidis and Spirakis's weighted sampling. Each -place's random number is seeded by its GEOID, so a rerun on the same sources draws the -same places, and a place added to or dropped from the sources moves only the places near -the cut. The draw keeps 968 of the 1,584 places of 25,000 or more and 310 of those of +2026-10-11, Lilleman auf Larv. Goals 2 and 14: ten streets per place put 500 Stockholm +customers on ten streets, and US places of 25,000 or more left out every town and +village. `geo-us.py` draws with Efraimidis and Spirakis's weighted sampling. It draws +only among places holding most of some ZCTA's land, since no other place can carry a +postal code. The draw keeps 968 of the 1,584 places of 25,000 or more and 310 of those of 100,000 or more, and its smallest place holds 93 people. On 2026-10-11 the embed grew from 1.3 MB to 5.2 MB, and the first draw of `en_US.address` took 75 ms against 19 ms before, within goal 13. `--place-share`, `--street-share` and `--min-streets` on the diff --git a/todo.md b/todo.md index 9b4e3bb..1ed12ad 100644 --- a/todo.md +++ b/todo.md @@ -280,7 +280,7 @@ Nothing has shipped, so "no longer paths", "where it used to fail" and "where it ### 199. Decide whether every state capital, or every US place of 100,000 or more, ships beside the drawn tenth. -The draw by population leaves out about 25 of the 335 places of 100,000 or more, and some state capitals, so a test author pinning a city they know may hit `no row of locality`. Shipping them always would keep such selectors working across a refresh of the sources, at the cost of a draw that is no longer one rule. +The draw by population leaves out about 25 of the 335 places of 100,000 or more, and some state capitals, so a test author pinning a city they know may hit `no row of … has key or name`. Shipping them always would keep such selectors working across a refresh of the sources, so a refresh need not wait for a major to drop one, at the cost of a draw that is no longer one rule. ### 196. Name, in the error for a reference nothing loaded provides, the module the reader's manifest reads by default that would provide it, or say none does. @@ -422,7 +422,7 @@ Carries out the decision "The shipped data is Go packages a library imports by c ### 198. Fetch the TIGER files of every county a drawn US place spans, so a place's streets and postal codes cover all of it. -`streets()` in `geo-us.py` fetches only each drawn place's main county, the one holding most of its people. A ZCTA in a place's other counties then has no address range and is dropped: New York, under Kings County, ships Brooklyn's codes, one Manhattan code and none on Staten Island, and its streets are a tenth of mostly Brooklyn's. Whether a neighbouring county is fetched depends on which other places the draw picks. The fix reads every county in `localities`' `county_part`. +`streets()` in `geo-us.py` fetches only each drawn place's main county, the one holding most of its people. A ZCTA in a place's other counties then has no address range and is dropped: New York, under Kings County, ships Brooklyn's codes, one Manhattan code and none on Staten Island, and its streets are mostly Brooklyn's. Whether a neighbouring county is fetched depends on which other places the draw picks. The fix reads every county in `localities`' `county_part`. ### 92. Name the hyphenated field in a `calc`'s refusal, and say to rename it: today `{calc(postal-code * 2)}` reports `no field "postal"`.