私は非常に大きな単語のリストを持っています。 Unixを使用して特定の文字共有基準に一致する複数の単語のインスタンスを見つける方法は?たとえば、単語1と2に同じ4番目と7番目の文字があり、単語2と3に同じ4番目と9番目の文字があり、単語3と4に同じ2番目、4番目、9番目の文字があります。したいです。
例:
aaadiigjlf
abcdefghij
aswdofflle
bbbbbbbbbb
bisofmlwpa
fsbdfopkld
gikfkwpspa
hogkellgis
戻ることができる
abcdefghij
aaadiigjlf
fsbdfopkld
aswdofflle
明確にするために、特定の場所で同じ文字を共有する単語を返すコードが必要です(例に示されている「d」と「g」)。また、すべての基準に一致しない単語を返すことを願っています。たとえば、与えられた例では、単語1と4は4番目の文字を共有しますが、必ずしも2番目、7番目、9番目の文字を共有するわけではありません。完成した形式で実行されているプログラムの場合、厳密な文字共有基準である9つに基づいて、非常に小さい単語のリスト(おそらく10のみ)が返されると予想されます。
編集者:いいですね。カードはテーブルの上にあります。それが私がどのようにして得るのかという問題です。
私は単語リストを受け取り、そのリストには次のようにグリッドに入れることができる10個の文字単語が10個あると言われました。
-112--3---
---2--3-4-
-5-2----4-
-5-2--6-4-
75-2--6---
75---8----
7----8----
79---8----
-9--0-----
-9--0---xx
すべての単語を読んでください。同じ数字(およびx)(すべて1、両方2など)を持つすべてのスペースは同じ文字です(他の数字は同じ文字にすることができますが、必ずしもそうではありません)。
更新:私はまだRalphのコードを実行しています。今は完了している可能性がありますが、外付けハードドライブに障害が発生した後にプロセスを再起動する必要がありました。ほぼ48時間が経過しましたが、まだ進行速度が遅いです。
答え1
ファイルのリストを複数回処理することは避けられませんが、各ルールを一度だけ処理すれば十分です。主なプロセスは、可能な「単語リスト」を拡張しながら、単語を10回繰り返すことです。ここで、各リストについて、i:番目の単語はそのリストのi:番目のルールと一致します。各単語がリストと一致すると、その単語が追加され、リストが展開されます。
bash
:R
このデータ構造を維持するには少し弱いですが、オプションで、「単語リスト」を拡張リストに適用する次の規則を表すカンマ区切りの単語シーケンスとして表すことができます。R
これはR
もちろん、リストの単語数に1を加えたものと同じです。これを基本データ構造として使用すると、次の基本プロセスが表示されることがあります。
N=0
M=0
cat $1 $1 $1 $1 $1 $1 $1 $1 $1 $1 | while read w || ending ; do
[ -z "$F" ] && F=$w # capture the first word
[ "$F" = "$w" ] && N=$((N+1)) # count first word appearances
Q=( )
matches $w 1 "" && Q=( ${w}:2 )
for p in ${P[@]} ; do
A="${Q[@]}" && [ "${A/$p/}" = "${A}" ] || continue # if duplicate
R=${p#*:} && [ $R -lt $M ] && continue # if path too short
Q=( ${Q[@]} $p ) # preserve this path for next word
[ "${p/$w/}" = "$p" ] || continue # if word already in path
p=${p%:*} # p is now the word list only
if matches $w $R $p ; then
Q=( ${Q[@]} $p,${w}:$((R+1)) )
M=$N
fi
done
P=( ${Q[@]} )
done
これは、単語がルールリストの適切な拡張であるかどうかmatches
を判断するためのルールの操作表現です。w
次のようなもの(メインプログラムの前にあります):p
R
matches() {
local w=$1
local p=$3
case $2 in
1) # -112--3---
eqchar $w 2 $w 3
;;
2) # ---2--3-4-
eqchar $w 4 $p 4 && eqchar $w 7 $p 7
;;
3) # -5-2----4-
eqchar $w 4 $p 4 && eqchar $w 9 $p $((11+9))
;;
4) # -5-2--6-4-
eqchar $w 2 $p $((22+2)) && eqchar $w 4 $p 4 &&
eqchar $w 9 $p $((11+9))
;;
5) # 75-2--6---
eqchar $w 2 $p $((22+2)) && eqchar $w 4 $p 4 &&
eqchar $w 7 $p $((11+7))
;;
6) # 6: 75---8----
eqchar $w 1 $p $((44+1)) && eqchar $w 2 $p $((22+2)) &&
eqchar $w 7 $p $((33+7))
;;
7) # 7: 7----8----
eqchar $w 1 $p $((44+1)) && eqchar $w 6 $p $((55+6))
;;
8) # 8: 79---8----
eqchar $w 1 $p $((44+1)) && eqchar $w 6 $p $((55+6))
;;
9) # 9: -9--0-----
eqchar $w 2 $p $((77+2))
;;
10) # 10: -9--0---xx
eqchar $w 2 $p $((77+2)) && eqchar $w 5 $p $((88+5)) &&
[ -z "${1#*xx}" ]
;;
*)
return 1
;;
esac
}
このeqchar
関数は、特定の位置にある最初の文字列の文字が、特定の位置にある2番目の文字列の文字と一致するかどうかをテストします。後者の文字列はコンマで区切られた順序の先頭の単語であるため、i*11+j
j:番目の文字(1ベース)からi:番目の単語(0ベース)へのインデックス付け方法を許可します。たとえば、インデックスは$((77+2))
8番目の単語の2番目の文字です。
eqchar() {
local w=$1
local p=$3
[ "${w:$(($2-1)):1}" = "${p:$(($4-1)):1}" ]
}
関数は関数の前に宣言する必要がeqchar
あり、基本プロシージャの前に宣言する必要があります。matches
最後に、メインプログラムにはending
最後に結果を印刷する機能が含まれています。予想される結果は、P
長さ10の「単語リスト」を保存することですが、通常、ルールに適合するP
可能matches
な限り長い単語のリストは実際にはすべて保存されます。関数ending
は必要な印刷物を生成して返し、句を終了する必要が1
ありますwhile
。
これは、O(N)(またはO(N * T)、Tは非常に高い場合は最初の規則と一致する数)を使用する「純粋な」bashソリューションです。
答え2
サンプルテキストを使用してワードファイルを作成しました。
-bash-4.2$ cat words
aaadiigjlf
abcdefghij
aswdofflle
bbbbbbbbbb
bisofmlwpa
fsbdfopkld
gikfkwpspa
hogkellgis
スクリプトは毎回最初の単語を設定する単語のリストを繰り返し、次に単語ファイルの内容を繰り返して4番目と7番目の文字を比較します。一致するものが見つかったら、一致を2番目の単語に設定し、これまでの解決策をエコーします。スクリプトはテンプレートなので、後続の入れ子になったループにそれぞれの制約を追加する必要があります。
-bash-4.2$ cat script
#!/bin/bash
for worda in $(cat ./words ); do
firstword=$worda
for wordb in $(cat ./words | grep -v $firstword); do
if [ $(echo $firstword | cut -c 4,7) = $(echo $wordb | cut -c 4,7) ]; then
secondword=$wordb
echo "$firstword $secondword"
fi
done
done
以下はスクリプトの出力です。
bash-4.2$ ./script
aaadiigjlf abcdefghij
abcdefghij aaadiigjlf
ヒント:4,7の2つの発生を4,9に変更し、これが出力にどのような影響があるかを確認してください。追加のforループをネストしてみることができます。
私はあなたのためにすべてをやりたくありませんが、(宿題のように見えるので)あなたを正しい道に導くのに十分です。私が提供したものを使ってここで手動でこれを行い、各制約を比較に挿入することができます。