Skip to content

Instantly share code, notes, and snippets.

@Shinichi-Ohki
Last active March 26, 2025 12:19
Show Gist options
  • Save Shinichi-Ohki/34c98f316b5abe28281267d4196e598e to your computer and use it in GitHub Desktop.
Save Shinichi-Ohki/34c98f316b5abe28281267d4196e598e to your computer and use it in GitHub Desktop.
逆順駅名を探せ

逆順駅名を探せ

「田町」「町田」のように、逆にしても成立する日本の駅名を探します。

  1. 国土数値情報ダウンロードサイト国土数値情報 鉄道データから最新のデータ(現時点ではN02-23_GML.zip)をダウンロードします。
  2. zipファイルを展開してできたフォルダの中のutf-8フォルダの中にjson-to-csv-script.rbとstation-anagram-finder.rbをコピーします。
  3. ruby json-to-csv-script.rb N02-23_Station.geojson を実行します。geojsonファイルの名前は適宜変更してください。
  4. station-anagram-finder.rb を実行します
  5. 逆順駅名のセットとアナグラム駅名のセットが出力されます
#!/usr/bin/env ruby
require 'json'
require 'csv'
# コマンドライン引数からファイル名を取得
input_file = ARGV[0] || 'input.json'
output_file = ARGV[1] || 'output.csv'
puts "JSONファイル「#{input_file}」からCSVファイル「#{output_file}」へ変換中..."
# JSONファイルを読み込む
json_data = File.read(input_file)
# 「"type": "Feature"」が含まれるJSONか、GeoJSONのFeatureCollection内のFeatureかを判断
begin
data = JSON.parse(json_data)
features = []
if data.is_a?(Hash) && data['type'] == 'FeatureCollection' && data['features'].is_a?(Array)
# GeoJSON FeatureCollection
features = data['features']
elsif data.is_a?(Hash) && data['type'] == 'Feature'
# 単一のFeature
features = [data]
elsif data.is_a?(Array)
# 複数のFeatureを含む配列
features = data.select { |item| item.is_a?(Hash) && item['type'] == 'Feature' }
else
puts "警告: サポートされているGeoJSON形式ではありません。処理を続行します..."
features = [data] # とりあえず渡されたデータで試す
end
# CSVにN02_003, N02_004, N02_005の値を書き込む
CSV.open(output_file, 'w') do |csv|
# ヘッダー行を書き込む
csv << ['事業者名', '路線名', '駅名']
# 各フィーチャーからデータを抽出
features.each do |feature|
if feature.is_a?(Hash) && feature['properties'].is_a?(Hash)
props = feature['properties']
route_name = props['N02_003'] || ''
operator = props['N02_004'] || ''
station = props['N02_005'] || ''
# CSVに行を追加
csv << [operator, route_name, station]
end
end
end
puts "変換完了! #{features.count}件のデータを抽出しました!"
rescue JSON::ParserError => e
puts "エラー: JSONのパースに失敗しました。#{e.message}"
exit 1
rescue => e
puts "エラー: 処理中に問題が発生しました。#{e.message}"
exit 1
end
#!/usr/bin/env ruby
# encoding: UTF-8
require 'csv'
# 処理開始メッセージ
puts "日本の駅名の逆順とアナグラムのペアを探すプログラムを実行します..."
# CSVファイルから駅名を読み込む
stations = []
begin
CSV.foreach('output.csv', headers: true, encoding: 'UTF-8') do |row|
if row['駅名'] && !row['駅名'].empty?
stations << {
name: row['駅名'],
company: row['事業者名'],
line: row['路線名']
}
end
end
puts "#{stations.size}個の駅情報を読み込みました"
rescue => e
puts "エラー: CSVファイルの読み込みに失敗しました - #{e.message}"
exit 1
end
# 駅名だけの配列を作成
station_names = stations.map { |s| s[:name] }
# 駅名から情報を素早く引き出せるようにハッシュを作成
station_info = {}
stations.each do |station|
name = station[:name]
# 同じ駅名が複数ある場合は配列に追加
if station_info[name]
station_info[name] << station
else
station_info[name] = [station]
end
end
# 重複を削除
unique_station_names = station_names.uniq
puts "重複を除いた駅名は#{unique_station_names.size}個です"
# 完全な逆順ペアとアナグラムペアを保存する配列
complete_reverse_pairs = []
anagram_pairs = []
# 効率化のための駅名ハッシュを作成
station_hash = {}
unique_station_names.each do |name|
# 1文字の駅名はスキップ
next if name.length <= 1
# 駅名の文字を逆順にした文字列
reversed = name.chars.reverse.join
# 駅名の文字をソートした文字列
sorted = name.chars.sort.join
station_hash[name] = {
reversed: reversed,
sorted: sorted
}
end
puts "駅名の解析中..."
# 完全な逆順ペアを探す
station_hash.each_key do |name1|
# 自分自身が回文(逆から読んでも同じ)の場合はスキップ
next if name1 == station_hash[name1][:reversed]
# 逆順の駅名がリストにあるかチェック
reversed_name = station_hash[name1][:reversed]
if station_hash.key?(reversed_name) && name1 < reversed_name
complete_reverse_pairs << [name1, reversed_name]
end
end
# アナグラムペアを探す(同じ文字を使った別の駅名)
station_names = station_hash.keys.sort
station_names.each_with_index do |name1, i|
(i+1...station_names.length).each do |j|
name2 = station_names[j]
# 同じ文字セットを持つかチェック(逆順ペアでないもの)
if name1 != station_hash[name2][:reversed] &&
station_hash[name1][:sorted] == station_hash[name2][:sorted]
anagram_pairs << [name1, name2]
end
end
end
# 駅名ペアの詳細情報を表示するメソッド
def print_station_pair(pair, station_info)
station1, station2 = pair
puts "『#{station1}』 - 『#{station2}』"
puts " 【#{station1}】"
station_info[station1].each do |info|
puts " #{info[:company]} - #{info[:line]}"
end
puts " 【#{station2}】"
station_info[station2].each do |info|
puts " #{info[:company]} - #{info[:line]}"
end
puts "" # 空行を入れて見やすくする
end
# 結果を出力
puts "\n==== 完全な逆順のペア(#{complete_reverse_pairs.size}個)===="
if complete_reverse_pairs.empty?
puts "該当するペアが見つかりませんでした。"
else
complete_reverse_pairs.each do |pair|
print_station_pair(pair, station_info)
end
end
puts "\n==== アナグラム(同じ文字を使った別の駅名)のペア(#{anagram_pairs.size}個)===="
if anagram_pairs.empty?
puts "該当するペアが見つかりませんでした。"
else
# 結果が多すぎる場合は制限する
display_limit = 100
pairs_to_display = anagram_pairs.take(display_limit)
pairs_to_display.each do |pair|
print_station_pair(pair, station_info)
end
if anagram_pairs.size > display_limit
puts "...他 #{anagram_pairs.size - display_limit}件"
end
end
puts "\n処理が完了しました!"
日本の駅名の逆順とアナグラムのペアを探すプログラムを実行します...
10240個の駅情報を読み込みました
重複を除いた駅名は8513個です
駅名の解析中...
==== 完全な逆順のペア(69個)====
『吉田』 - 『田吉』
【吉田】
近畿日本鉄道 - けいはんな線
東日本旅客鉄道 - 越後線
東日本旅客鉄道 - 弥彦線
【田吉】
九州旅客鉄道 - 宮崎空港線
九州旅客鉄道 - 日南線
『上田』 - 『田上』
【上田】
しなの鉄道 - しなの鉄道線
上田電鉄 - 別所線
東日本旅客鉄道 - 北陸新幹線
【田上】
東日本旅客鉄道 - 信越線
『原向』 - 『向原』
【原向】
わたらせ渓谷鐵道 - わたらせ渓谷線
【向原】
西日本旅客鉄道 - 芸備線
東京都 - 荒川線
『中野』 - 『野中』
【中野】
わたらせ渓谷鐵道 - わたらせ渓谷線
上田電鉄 - 別所線
東京地下鉄 - 5号線東西線
東日本旅客鉄道 - 中央線
東日本旅客鉄道 - 中央線
東日本旅客鉄道 - 中央線
【野中】
松浦鉄道 - 西九州線
『山西』 - 『西山』
【山西】
伊予鉄道 - 高浜線
【西山】
筑豊電気鉄道 - 筑豊電気鉄道線
東日本旅客鉄道 - 越後線
『木野』 - 『野木』
【木野】
叡山電鉄 - 鞍馬線
【野木】
東日本旅客鉄道 - 東北線
『中田』 - 『田中』
【中田】
横浜市 - 1号線
四国旅客鉄道 - 牟岐線
東日本旅客鉄道 - 五能線
【田中】
しなの鉄道 - しなの鉄道線
『田町』 - 『町田』
【田町】
岡山電気軌道 - 清輝橋線
東日本旅客鉄道 - 東海道線
【町田】
小田急電鉄 - 小田原線
東日本旅客鉄道 - 横浜線
『山田』 - 『田山』
【山田】
京王電鉄 - 高尾線
阪急電鉄 - 千里線
大阪モノレール - 大阪モノレール線
長良川鉄道 - 越美南線
【田山】
東日本旅客鉄道 - 花輪線
『北浜』 - 『浜北』
【北浜】
京阪電気鉄道 - 京阪本線
大阪市高速電気軌道 - 6号線(堺筋線)
北海道旅客鉄道 - 釧網線
【浜北】
遠州鉄道 - 鉄道線
『海神』 - 『神海』
【海神】
京成電鉄 - 本線
【神海】
樽見鉄道 - 樽見線
『北山』 - 『山北』
【北山】
京都市 - 烏丸線
真岡鐵道 - 真岡線
とさでん交通 - 伊野線
東日本旅客鉄道 - 仙山線
【山北】
東海旅客鉄道 - 御殿場線
『瀬高』 - 『高瀬』
【瀬高】
九州旅客鉄道 - 鹿児島線
【高瀬】
四国旅客鉄道 - 予讃線
東日本旅客鉄道 - 仙山線
『原田』 - 『田原』
【原田】
九州旅客鉄道 - 鹿児島線
九州旅客鉄道 - 筑豊線
天竜浜名湖鉄道 - 天竜浜名湖線
【田原】
北条鉄道 - 北条線
『木葉』 - 『葉木』
【木葉】
九州旅客鉄道 - 鹿児島線
【葉木】
九州旅客鉄道 - 肥薩線
『山本』 - 『本山』
【山本】
九州旅客鉄道 - 筑肥線
九州旅客鉄道 - 唐津線
阪急電鉄 - 宝塚線
【本山】
四国旅客鉄道 - 予讃線
松浦鉄道 - 西九州線
名古屋市 - 1号線東山線
名古屋市 - 4号線名城線
『浦田』 - 『田浦』
【浦田】
九州旅客鉄道 - 筑豊線
水島臨海鉄道 - 水島本線
【田浦】
東日本旅客鉄道 - 横須賀線
『市布』 - 『布市』
【市布】
九州旅客鉄道 - 長崎線
【布市】
富山地方鉄道 - 上滝線
『添田』 - 『田添』
【添田】
九州旅客鉄道 - 日田彦山線
【田添】
富山地方鉄道 - 立山線
『吉富』 - 『富吉』
【吉富】
九州旅客鉄道 - 日豊線
西日本旅客鉄道 - 山陰線
【富吉】
近畿日本鉄道 - 名古屋線
『田野』 - 『野田』
【田野】
九州旅客鉄道 - 日豊線
土佐くろしお鉄道 - 阿佐線
【野田】
阪神電気鉄道 - 本線
西日本旅客鉄道 - 大阪環状線
『原水』 - 『水原』
【原水】
九州旅客鉄道 - 豊肥線
【水原】
東日本旅客鉄道 - 羽越線
『原市』 - 『市原』
【原市】
埼玉新都市交通 - 伊奈線
【市原】
叡山電鉄 - 鞍馬線
『妻鹿』 - 『鹿妻』
【妻鹿】
山陽電気鉄道 - 本線
【鹿妻】
東日本旅客鉄道 - 仙石線
『出目』 - 『目出』
【出目】
四国旅客鉄道 - 予土線
【目出】
西日本旅客鉄道 - 小野田線
『中郡』 - 『郡中』
【中郡】
鹿児島市 - 唐湊線
東日本旅客鉄道 - 米坂線
【郡中】
伊予鉄道 - 郡中線
『山谷』 - 『谷山』
【山谷】
松浦鉄道 - 西九州線
【谷山】
九州旅客鉄道 - 指宿枕崎線
鹿児島市 - 谷山線
『城東』 - 『東城』
【城東】
上毛電気鉄道 - 上毛線
【東城】
西日本旅客鉄道 - 芸備線
『上浦』 - 『浦上』
【上浦】
西日本鉄道 - 甘木線
【浦上】
九州旅客鉄道 - 長崎線
『中浜』 - 『浜中』
【中浜】
西日本旅客鉄道 - 境線
【浜中】
北海道旅客鉄道 - 根室線
『上道』 - 『道上』
【上道】
西日本旅客鉄道 - 境線
西日本旅客鉄道 - 山陽線
【道上】
西日本旅客鉄道 - 福塩線
『安浦』 - 『浦安』
【安浦】
西日本旅客鉄道 - 呉線
【浦安】
西日本旅客鉄道 - 山陰線
東京地下鉄 - 5号線東西線
『矢野』 - 『野矢』
【矢野】
西日本旅客鉄道 - 呉線
【野矢】
九州旅客鉄道 - 久大線
『下松』 - 『松下』
【下松】
西日本旅客鉄道 - 阪和線
西日本旅客鉄道 - 山陽線
【松下】
東海旅客鉄道 - 参宮線
『和知』 - 『知和』
【和知】
西日本旅客鉄道 - 山陰線
【知和】
西日本旅客鉄道 - 因美線
『下山』 - 『山下』
【下山】
西日本旅客鉄道 - 山陰線
土佐くろしお鉄道 - 阿佐線
【山下】
東急電鉄 - 世田谷線
東日本旅客鉄道 - 常磐線
能勢電鉄 - 日生線
能勢電鉄 - 妙見線
『地福』 - 『福地』
【地福】
西日本旅客鉄道 - 山口線
【福地】
名古屋鉄道 - 西尾線
『島田』 - 『田島』
【島田】
西日本旅客鉄道 - 山陽線
東海旅客鉄道 - 東海道線
【田島】
東武鉄道 - 佐野線
『山崎』 - 『崎山』
【山崎】
西日本旅客鉄道 - 東海道線
北海道旅客鉄道 - 函館線
名古屋鉄道 - 尾西線
【崎山】
平成筑豊鉄道 - 田川線
『稲荷』 - 『荷稲』
【稲荷】
西日本旅客鉄道 - 奈良線
【荷稲】
土佐くろしお鉄道 - 中村線
『保谷』 - 『谷保』
【保谷】
西武鉄道 - 池袋線
【谷保】
東日本旅客鉄道 - 南武線
『井川』 - 『川井』
【井川】
大井川鐵道 - 井川線
【川井】
東日本旅客鉄道 - 青梅線
『家山』 - 『山家』
【家山】
大井川鐵道 - 大井川本線
【山家】
西日本旅客鉄道 - 山陰線
『出戸』 - 『戸出』
【出戸】
大阪市高速電気軌道 - 2号線(谷町線)
【戸出】
西日本旅客鉄道 - 城端線
『宮川』 - 『川宮』
【宮川】
東海旅客鉄道 - 参宮線
【川宮】
名古屋ガイドウェイバス - ガイドウェイバス志段味線
『田立』 - 『立田』
【田立】
東海旅客鉄道 - 中央線
【立田】
土佐くろしお鉄道 - 阿佐線
『田畑』 - 『畑田』
【田畑】
東海旅客鉄道 - 飯田線
【畑田】
高松琴平電気鉄道 - 琴平線
『切石』 - 『石切』
【切石】
東海旅客鉄道 - 飯田線
【石切】
近畿日本鉄道 - 奈良線
『上野』 - 『野上』
【上野】
東京地下鉄 - 2号線日比谷線
東京地下鉄 - 3号線銀座線
東日本旅客鉄道 - 東北新幹線
東日本旅客鉄道 - 東北線
東日本旅客鉄道 - 東北線
東日本旅客鉄道 - 東北線
東日本旅客鉄道 - 東北線
【野上】
秩父鉄道 - 秩父本線
『戸越』 - 『越戸』
【戸越】
東京都 - 1号線浅草線
【越戸】
名古屋鉄道 - 三河線
『内野』 - 『野内』
【内野】
東日本旅客鉄道 - 越後線
【野内】
青い森鉄道 - 青い森鉄道線
『前山』 - 『山前』
【前山】
東日本旅客鉄道 - 奥羽線
【山前】
東日本旅客鉄道 - 両毛線
『沼田』 - 『田沼』
【沼田】
東日本旅客鉄道 - 上越線
【田沼】
東武鉄道 - 佐野線
『羽鳥』 - 『鳥羽』
【羽鳥】
東日本旅客鉄道 - 常磐線
【鳥羽】
近畿日本鉄道 - 志摩線
近畿日本鉄道 - 鳥羽線
東海旅客鉄道 - 参宮線
『佐和』 - 『和佐』
【佐和】
東日本旅客鉄道 - 常磐線
【和佐】
西日本旅客鉄道 - 紀勢線
『古津』 - 『津古』
【古津】
東日本旅客鉄道 - 信越線
【津古】
西日本鉄道 - 天神大牟田線
『前川』 - 『川前』
【前川】
東日本旅客鉄道 - 信越線
【川前】
東日本旅客鉄道 - 磐越東線
『中豊』 - 『豊中』
【中豊】
東日本旅客鉄道 - 水郡線
【豊中】
阪急電鉄 - 宝塚線
『沢田』 - 『田沢』
【沢田】
東日本旅客鉄道 - 石巻線
【田沢】
東日本旅客鉄道 - 篠ノ井線
『下馬』 - 『馬下』
【下馬】
東日本旅客鉄道 - 仙石線
【馬下】
東日本旅客鉄道 - 磐越西線
『津谷』 - 『谷津』
【津谷】
東日本旅客鉄道 - 陸羽西線
【谷津】
京成電鉄 - 本線
『坂戸』 - 『戸坂』
【坂戸】
東武鉄道 - 越生線
東武鉄道 - 東上本線
【戸坂】
西日本旅客鉄道 - 芸備線
『川角』 - 『角川』
【川角】
東武鉄道 - 越生線
【角川】
東海旅客鉄道 - 高山線
『明神』 - 『神明』
【明神】
東武鉄道 - 日光線
【神明】
福井鉄道 - 福武線
『島松』 - 『松島』
【島松】
北海道旅客鉄道 - 千歳線
【松島】
東日本旅客鉄道 - 東北線
『田神』 - 『神田』
【田神】
名古屋鉄道 - 各務原線
【神田】
松浦鉄道 - 西九州線
東京地下鉄 - 3号線銀座線
東日本旅客鉄道 - 中央線
東日本旅客鉄道 - 東北線
『山岡』 - 『岡山』
【山岡】
明知鉄道 - 明知線
【岡山】
西日本旅客鉄道 - 宇野線
西日本旅客鉄道 - 吉備線
西日本旅客鉄道 - 山陽新幹線
西日本旅客鉄道 - 山陽線
西日本旅客鉄道 - 津山線
『川辺』 - 『辺川』
【川辺】
由利高原鉄道 - 鳥海山ろく線
【辺川】
四国旅客鉄道 - 牟岐線
『山東』 - 『東山』
【山東】
和歌山電鐵 - 貴志川線
【東山】
京都市 - 東西線
近畿日本鉄道 - 生駒線
==== アナグラム(同じ文字を使った別の駅名)のペア(6個)====
『三木里』 - 『三里木』
【三木里】
東海旅客鉄道 - 紀勢線
【三里木】
九州旅客鉄道 - 豊肥線
『上野原』 - 『野上原』
【上野原】
東日本旅客鉄道 - 中央線
【野上原】
東日本旅客鉄道 - 水郡線
『中野東』 - 『東中野』
【中野東】
西日本旅客鉄道 - 山陽線
【東中野】
東京都 - 12号線大江戸線
東日本旅客鉄道 - 中央線
『光善寺』 - 『善光寺』
【光善寺】
京阪電気鉄道 - 京阪本線
【善光寺】
東海旅客鉄道 - 身延線
『光洋台』 - 『洋光台』
【光洋台】
四国旅客鉄道 - 予讃線
【洋光台】
東日本旅客鉄道 - 根岸線
『南草津』 - 『草津南』
【南草津】
西日本旅客鉄道 - 東海道線
【草津南】
広島電鉄 - 宮島線
処理が完了しました!
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment