首页 > 解决方案 > 使用 crunch 生成所有可能的 IATA 代码组合

问题描述

我真的不知道如何制定这个,但我有一堆 IATA 代码,我想生成所有可能的组合,例如:JFK/LAX、BOS/JFK、...等,由一个字符分隔,例如“/”或“|”。

标签: crunch

解决方案


这里我们假设您的 IATA 代码存储在文件中file;每行一个代码。

crunch具有-q从文件生成行排列的选项。但是,在此模式下会crunch忽略大多数其他选项,例如<max-len>,这对于仅打印成对的代码很重要。

因此,...</p>

使用不同的东西crunch

例如,尝试

join -j2 -t/ -o 1.1 2.1 file file | awk -F/ '$1!=$2'

如果你真的、真的、真的想要,你可以……</p>

将输入翻译成crunch可以使用的东西

我们将每一行从file转换为一个唯一的单个字符,将该字符列表提供给crunch,然后将结果转换回来。

crunch支持 Unicode 字符,因此超过 255 行的文件完全可以。在这里,我们按字符枚举fileUnicode 的补充私人使用区域-A中的行。因此,file最多可能有 65'534 行。
如果您需要更多行,您可以组合多个 Unicode 平面,但在某些时候您可能会遇到ARG_MAX问题。此外,使用 65'534 行,您已经生成(略少于)65'534^2 = 4'294'705'156 对,转换为 IATA 代码对时占用超过 34 GB。

我怀疑反向翻译是一个巨大的减速,所以上述替代方案似乎在各个方面都更好(效率、简洁性、可维护性......)。

# This assumes your locale is using any Unicode encoding,
# e.g. UTF-8, UTF-16, … (doesn't matter which one).

file=...
((offset=0xF0000))
charset=$(
  echo -en "$(bc <<< "obase=16;
    max=$offset+$(wc -l < "$file");
    for(i=$offset;i<max;i++) {\"\U\"; i}" |
    tr -d \\n
  )"
)
crunch 2 2 "$charset" -d 1@ --stdout |
iconv -t UTF-32 |
od -j4 -tu4 -An -w12 -v |
awk -v o="$offset" 'NR==FNR{a[o+NR-1]=$0;next} {print a[$1]"/"a[$2]}' "$file" -

推荐阅读