What's the longest mirrorable place name?

Date: 2026-08-17

I was looking at street view in Paraguay, as you do, and spotted this place name sign on a roundabout:

Yatytay roundabout

You can read it from both sides, because YATYTAY is perfectly mirrorable: it's a palindrome where all the letters can be mirrored as well!

Are there any other place names like this?

Figuring that out

We want to find place names that, in all caps, are the exact same when read mirrored.

I started by Googling lists of city names. One of the top results was this set of "world cities" on GitHub: https://github.com/datasets/world-cities. It's a CSV of only like 1.5 megabytes, so I didn't expect to get a lot of results, but it'd get me started.

The shape is all like this:

name,country,subcountry,geonameid
les Escaldes,Andorra,Escaldes-Engordany,3040051
Andorra la Vella,Andorra,Andorra la Vella,3041563
Warīsān,United Arab Emirates,Dubai,290503

I'll use Rust to filter this list down.

We'll need to figure out if the letters are all symmetric (in caps). Symmetric letters include A, T, Y, among others:

/// Returns true if every letter in `value` has a symmetric capital.
fn is_symmetric_letters(value: &str) -> bool {
    value.chars().all(|c| matches!(
        c.to_ascii_uppercase(),
        'A' | 'H' | 'I' | 'M' | 'O' | 'T' | 'U' | 'V' | 'W' | 'X' | 'Y' |
        // account for some common non-letter characters
        '-' | ' ',
    ))
}

For the time being, I only care about the Latin transcription, mostly because it's easier. I think that most other widely used scripts have fewer mirrorable letters, though I could be wrong... Cyrillic has some of the same ones as Latin plus a couple that I haven't accounted for in this post. It might also be worthwhile to handle certain diacritics like ōā to get better results for Polynesian and Arabic place names in particular.

/// Returns true if `value` is the same when its UTF-8 characters are read in reverse.
fn is_palindrome(value: &str) -> bool {
    let from_start = value.chars();
    let from_end = value.chars().rev();

    let mut pairs = from_start.zip(from_end);
    pairs.all(|(start, end)| start.eq_ignore_ascii_case(&end))
}

We detect if something is a palindrome by walking the string forward and backward at the same time. Actually, you could stop in the middle, I didn't do that in my initial sketch of this function and found it more than fast enough this way. Sorry!

Then we read the CSV and filter it down to mirrorable names:

use std::fs::File;
use csv::ReaderBuilder;

#[derive(Debug)]
struct Record {
    city: String,
    region: String,
    country: String,
}

let file = File::open("world-cities.csv").unwrap();
let mut reader = ReaderBuilder::new().from_reader(file);

let iter = reader.records()
    .map(|record| record.unwrap())
    .filter_map(|record| {
        let city = record.get(0)?;
        let country = record.get(1)?;
        let region = record.get(2)?;

        (is_symmetric_letters(city) && is_palindrome(city)).then(|| Record {
            city: city.to_string(),
            country: country.to_string(),
            region: region.to_string(),
        })
    })
    .filter(|record| is_symmetric_letters(&record.city) && is_palindrome(&record.city));

And then we just dump the results:

for record in iter {
    println!("{record:?}");
}

gives:

Record { city: "Mutum", region: "Minas Gerais", country: "Brazil" }
Record { city: "Oyo", region: "Cuvette", country: "Congo" }
Record { city: "Mim", region: "Ahafo", country: "Ghana" }
Record { city: "Maham", region: "Haryana", country: "India" }
Record { city: "Ama", region: "Aichi", country: "Japan" }
Record { city: "Awa", region: "Tokushima", country: "Japan" }
Record { city: "Waw", region: "Bago Region", country: "Myanmar" }
Record { city: "Oyo", region: "Oyo State", country: "Nigeria" }
Record { city: "Owo", region: "Ondo State", country: "Nigeria" }
Record { city: "Matam", region: "Matam", country: "Senegal" }

Not bad for a first attempt. Oyo, Owo, and Matam will be familiar to many GeoGuessr players. The dataset is very small though, and doesn't even include Yatytay!

Expanding the data

I first went to GeoNames, which I know has a lot of...names...of places. I first grabbed their cities500 export, which has all town names with over 500 population that GeoNames knows about.

It's got a slightly different format, with several languages and some location data. It also has short codes for country and region instead of full names.

3038832 Vila    Vila    Casas Vila,Vila 42.53176        1.56654 P       PPL     AD              03                              1418            1318    Europe/Andorra  2024-11-04
3038999 Soldeu  Soldeu  Sol'deu,Soldeu,surudeu,swldw,Сольдеу,סולדאו,سولدو,スルデウ      42.57688        1.66769 P       PPL     AD              02                              602             1832    Europe/Andorra  2017-11-06
3039077 Sispony Sispony Sispony 42.53368        1.51613 P       PPL     AD              04                              833             1315    Europe/Andorra  2024-11-04
3039154 El Tarter       El Tarter       Ehl Tarter,El Tarter,El Tarter - Principau d'Andorra,El Tarter - Principáu d'Andorra,al tartr,Ел Тартер,Эл Тартер,ال تارتر      42.57952        1.65362 P       PPL     AD              02                            1003             1721    Europe/Andorra  2026-06-24

I figured I'd just adjust the shape of the data using xsv, as I already have it installed. I'm only now finding out that it's unmaintained, but it worked fine for this!

xsv select 2,9,11 -d"\t" cities500.txt > world-cities.csv

With this new world-cities.csv, we get a few more results. I added a sorting step so the longest name is at the end:

let iter = {
    let mut vec = iter.collect::<Vec<_>>();
    vec.sort_by_key(|record| record.city.chars().count());
    vec.into_iter()
};

Omitting short results, we get:

[...]
Record { city: "Tutut", region: "08", country: "ID" }
Record { city: "Maham", region: "10", country: "IN" }
Record { city: "Otuto", region: "06", country: "PE" }
Record { city: "Matam", region: "15", country: "SN" }
Record { city: "Hammah", region: "06", country: "DE" }
Record { city: "Tommot", region: "63", country: "RU" }

This is already a pretty fun result. Tommot is also quite famous among GeoGuessr players as well as fans of remote railways. It's a perfect mirror in both the Cyrillic and Latin alphabets! Sadly its very unique railway station is only barely visible from street view.

Otuto would also be fun, especially since Peru also uses capital letters only on its town direction signs. But it's too small and too far away from Street View coverage for us to see it on a sign.

But, we still don't see Yatytay here. It has way more than 500 inhabitants, but maybe GeoNames just doesn't have a population number for it?

Now, it turns out that GeoNames also exports an allCountries.txt, which is a 1.8GiB CSV that contains every name it knows about, whether it's towns or hills or rivers. It has the same shape as cities500.txt, so I figured I'd give that a shot too--we'll just have to do some manual checking on if the things we get back are actually towns.

xsv select 2,9,11 -d"\t" allCountries.txt > world-cities.csv

All the matches longer than 6 characters:

[...]
Record { city: "Aaaaaaa", region: "04", country: "TW" }
Record { city: "Amayama", region: "05", country: "JP" }
Record { city: "Amiyima", region: "53", country: "NG" }
Record { city: "Ayamaya", region: "04", country: "BO" }
Record { city: "Ayamaya", region: "04", country: "BO" }
Record { city: "Itamati", region: "21", country: "IN" }
Record { city: "Muhuhum", region: "11", country: "PG" }
Record { city: "Otototo", region: "G2", country: "NZ" }
Record { city: "Tamamat", region: "01", country: "NE" }
Record { city: "Yatytay", region: "11", country: "PY" }
Record { city: "Yatytay", region: "11", country: "PY" }
Record { city: "Mayavayam", region: "44", country: "RU" }
Record { city: "Owomomowo", region: "48", country: "NG" }
Record { city: "Owomomowo", region: "48", country: "NG" }
Record { city: "Tamahamat", region: "12070577", country: "ML" }
Record { city: "Tamahamat", region: "12070577", country: "ML" }
Record { city: "Tamahamat", region: "12070577", country: "ML" }

Theeere's Yatytay!

"Aaaaaaa" supposedly in Taiwan is clearly not a real place name. Let's go through the 9-letter ones:

This means that OWOMOMOWO is probably our real winner. It's a real beauty too, but I can't find anything about it :(

Out of the 7-letter ones, Ayamaya is a town in Bolivia and Muhuhum is a town in Papua New Guinea, but neither have Street View coverage. The other interesting one is Itamati in Odisha. ITAMATI would be a great candidate. You can see it in Street View on some shop signs in all caps and on the town entry sign in mixed case, but sadly the town doesn't have a roundabout!

So, Yatytay might not quite be the longest overall mirrorable place name in the Latin script, but it does look like it's the only one to actually make use of that fact.

Yatytay roundabout

(The shortest mirrorable place name is either Å, Norway or Ii, Finland depending on if you allow for 1-letter place names.)

Thanks to maccem for finding the Itamati town entry sign.