나는 여러 가지를 보았다기사기본 Linux 명령(grep 및 regex)이 Wordle 퍼즐을 해결하는 방법을 설명합니다. 게임을 처음 접하는 경우 이 질문 끝에 있는 메모를 확인하세요. 나는 이 목적으로 awk를 사용하기로 결정했습니다. 첫 번째 시도는 다음과 같습니다.
awk 'length($0)==5' /usr/share/dict/words | awk '!/\-|\x27|[A-Z]/' | awk '!/[isbou]/' | awk '/a/&&/l/&&/e/&&/e/&&/t/' | awk '/...a/' | cat -n
처음 두 개의 awk는 표준 Ubuntu 설치의 사전에서 5글자 단어 목록(대문자, 하이픈, 아포스트로피 제외)을 생성합니다.
awk '/a/&&/l/&&/e/&&/t/'
(노란색 글자의 경우) 글자가 있는 단어를 필터링합니다. 단어 안에는 있지만 쓰여진 위치에는 없습니다. 이 예에서는 문자 a, l, e, t
awk '!/[isbou]/'
(회색 문자의 경우) 이 예에서는 i, s, b, o, u 문자가 포함된 단어를 필터링합니다.
awk '/...a/'
(녹색 글자의 경우)은 글자가 있고 올바른 위치에 있음을 의미합니다.
나는 코드를 단순하게 유지하기 위해 5글자 단어 목록을 사전으로 사용하기로 결정했습니다. 여러 가지 방법으로 이러한 목록을 준비할 수 있습니다. 예를 들어:
awk 'length($0)==5' /usr/share/dict/words | awk '!/\-|\x27|[A-Z]/' > fives.txt
또는
curl -s 'https://random-word-api.herokuapp.com/word?number=100000' | awk -v RS=',' '{gsub(/[]["]+/,"")}1' | awk 'length($i)==5' > fives.txt
이 파일( Fives.txt )을 홈 디렉터리에 배치하면 명령이 더 짧아집니다.
cat ~/fives.txt | awk '!/[isbou]/' | awk '/a/&&/l/&&/e/&&/e/&&/t/' | awk '/...a/' | cat -n
이것은 훌륭하게 작동합니다. 그런데 이걸 단축할 수 있을까요? 다음 추측 명령을 편집할 때 노란색 문자 확인을 더욱 우아하게 만들고 오류가 발생할 가능성을 줄이려면 어떻게 해야 합니까?
참고: 규칙은 매우 간단합니다. 6번(보통 5번) 안에 숨겨진 단어를 추측해야 합니다. 먼저 첫 번째 줄에 아무 단어나 입력하세요. 문자가 올바르게 추측되고 올바른 위치에 있으면 녹색으로 강조 표시되고, 문자가 단어에 있지만 잘못된 위치에 있으면 노란색으로 강조 표시되고, 문자가 단어에 없으면 그대로 유지됩니다. 회색. 6번의 시도 끝에 숨겨진 단어를 맞힐 수 있나요?
답변1
모든 AWK 필터와 병합 기능을 결합하여 cat
이 시간을 단축 할 수 있습니다.
awk '!/[isbou]/ && /a/&&/l/&&/e/&&/t/ && /^...a.$/ { printf("%6d %s\n", ++i, $0) }' ~/fives.txt
구체적으로 5개 위치를 확인하기 위해 녹색 필터를 수정했습니다.
AWK 부분을 더 단순화하는 대신 세 가지 매개변수(회색 문자 목록, 노란색 문자 목록, 올바른 위치에 있는 녹색 문자)가 있는 쉘 스크립트를 사용하겠습니다.
#!/bin/bash
awkcmd=""
if [[ ${#1} -gt 0 ]]; then
awkcmd="${awkcmd}!/[$1]/ &&"
fi
if [[ ${#2} -gt 0 ]]; then
for (( i=0; i < ${#2}; i++ )); do
awkcmd="${awkcmd} /${2:$i:1}/ &&"
done
fi
if [[ ${#3} -gt 0 ]]; then
awkcmd="${awkcmd} /$3/"
else
awkcmd="${awkcmd} 1"
fi
awkcmd="${awkcmd} { printf(\"%6d %s\n\", ++i, \$0) }"
awk "$awkcmd" ~/fives.txt
보다 일반적인 단어 목록을 보려면 awkcmd="/^[a-z]{5}$/ &&"
3행에 사용하세요.
답변2
매우 조잡한 스크립트(스텁과 유사)는 다음과 같이 시작할 수 있습니다.
#!/bin/bash
conditions='/^[a-z]{5}$/'
while getopts "c:i:e:" opt; do case "${opt}" in
c) conditions+=" && /^${OPTARG,,}/" ;;
i) conditions+=$(sed 's|.| \&\& /&/|g' <<<"${OPTARG,,}") ;;
e) conditions+=" && !/[${OPTARG,,}]/" ;;
esac; done
shift $((OPTIND-1))
awk "${conditions} { print toupper(\$0) }" /usr/share/dict/words
호출 ./wordle.sh -c "...a" -i "alet" -e "isbou"
결과는 다음과 같습니다.
CLEAT
FETAL
METAL
PETAL
PLEAT
이 예에서 생성된 awk는 다음과 같습니다.
awk '/^[a-z]{5}$/ && /^...a/ && /a/ && /l/ && /e/ && /t/ && !/[isbou]/ { print toupper($0) }' /usr/share/dict/words
...스크립트에 대한 엉성한 호출은 다음과 같습니다../wordle.sh -c...a -ialet -eisbou
물론 { print toupper(\$0) }
스크립트 부분은 완전히 장식적이므로 제거할 수 있습니다. Wordle이 GUI에서 대문자만 사용하기로 선택했기 때문에 추가되었습니다. :)
답변3
이미 5글자 단어만 있으므로 아무것도 제외할 필요가 없으므로 다음을 !/[isbou]/
확인 하면 반복할 필요가 없으며 둘 다 확인하지 않고 하나만 확인하지만 동일한 일이 발생합니다. 두 배. 두 가지를 모두 포함하는 사례를 찾으려면 가 필요합니다 . 따라서 이 모든 것을 합치면 아마도 다음과 같을 것입니다./a/&&/l/&&/e/&&/e/&&/t/
/e/ && /e/
e
e
/e.*e/
awk '/...a./ && /l/ &&/e.*e/ && /t/{print ++k,$0}' ~/fives.txt
답변4
그냥 이렇게 쓰고 싶다면:
awk 'length($0)==5' /usr/share/dict/words | awk '!/[A-Z]/' | awk '/[:alpha:]/' | awk '!/[isbou]/' | awk '/a/&&/l/&&/e/&&/e/&&/t/' | awk '/...a/' | cat -n
더 간결하게 말하면 다음과 같습니다.
awk '!/[A-Zisbou]/ && /l/&&/e/&&/t/ && /^...a.$/ {print ++n, $0}' /usr/share/dict/words
그러나 소문자 이외의 알파벳 문자가 포함된 "단어"를 제외하려면 다음과 같이 하십시오.
awk '/^[[:lower:]]+$/ && /l/&&/e/&&/t/ && /^...a.$/ {print ++n, $0}' /usr/share/dict/words
또는 원하는 경우:
awk '/l/&&/e/&&/t/ && /^[[:lower:]]{3}a[[:lower:]]$/ {print ++n, $0}' /usr/share/dict/words