ハングマンで遊ぼう!


8

このページによると、英語の絞首刑執行人の単語を推測する最良の戦略は、条件を満たす単語リストの各文字のオッズを計算することです。しかし、私は本当に怠惰なので、自分で辞書のすべての単語を計算したくありません。しかし、私はあなたがいつも私を助けるためにここにいることを知っているので、あなたは私のためにそれを行うコードの王を私にすることができると確信しています。また、ハードディスクがほぼいっぱいになっているので、可能な限り最小のコードを使用します。これは、ことを意味し、これはコード・ゴルフ、そして勝つバイトの最低量で提出するだけでなく、最も正確なものです!

入出力

この単語リストからランダムな単語が取得されます。

プログラムは、引数で、またはユーザー入力(ポップアップ、標準入力、その他)を受け入れる必要があります。

  • 単語の長さ
  • 間違った文字は既に見つかりました。ゲームを開始したばかりで、間違った文字を提供していない場合は0
  • すでに見つかった文字と単語内での位置

例:./hangsolver 6 XBZ 1P 4P 2E 6Eここでは、「人」という言葉を選びました。明確にするために:PE _ P _ E(間違った文字はXBとZです)

つまり、1つのゲームで、スクリプトを何度も起動する必要があります。

出力は1文字です。次の試行です。

ルール

  • 他よりも少ない試行で10単語を推測する方が勝ちます。
  • 引き分けの場合、バイト単位の最短コードが優先されます。
  • それでも同点の場合は、最速のプログラムが勝ちます。
  • あなたは英語でこれらの単語だけがあると思うかもしれません
  • 単語リストから有効な単語のみを試します。
  • 私は良いコンピュータを持っています、CPUパワーは問題になりません(しかし、できるだけ早く答えるようにしてください!)
  • オンラインソルバーでは解決できませんが、ワードリストをダウンロードするか、引数として渡すことができます。「wordlist.txt」という名前で、スクリプトと同じディレクトリにあると想定できます。
  • コードは一般的なOSで実行できる必要があります。それは、windows、mac、ubuntu / debian / CentOS、Redhatのいずれかです。
  • 外部ソルバーは使用できません。
  • ただし、URLをワードリストに短縮できます。
  • このコードゴルフは9月1日に終了します。
  • 上記の方法を使用する必要があります。

幸運を !

SEでここに単語リストが見つかりまし


2
バイトでの最短のコードが勝つでしょう。これは、以前に使用されたことのないランダムな文字を単純に推測する私のプログラムは、実際に適切な推測を試みようとする他の誰かを打ち負かすことを意味します。あなたはあなたのスコアリングを再考したいと思うかもしれません、さもなければあなたはささいな答えを得ようとしています。
Level River St

「上記の方法を使用する必要があります。」、私はルールを引用します。しかし、私はそれを主要な勝利基準にするために編集します
WayToDoor '17

1
明確にするために、「上記の方法を使用する」とは、まだ推測されていない可能な単語の最大数に現れる文字を推測することを意味しますか?
isaacg 2015

はい、正確に。入力ミスの編集ありがとうございます!
WayToDoor 2015

1
あなたの例の入力データは「6 XBZ 1P 4P 2E 6E」であるべきではありませんか?
Razvan

回答:


5

PowerShell、248 246 241バイト

$a=$args;$c=$a[0];$b=$a[2..$c];((gc wordlist.txt)-match"^$((1..$c|%{$e=,"[^$($a[1])]"*$c}{$e[$_-1]=(((@($b)-match"^$_\D")[0]-split$_)[-1],$e[$_-1]-ne'')[0]}{$e-join''}))$"-join''-split'\B'|?{!(@($b)-match$_).Count}|group|sort count)[-1].Name

未ゴルフ

まあ、私はそれが機能する方法を変更せずにできる限り多く:

$a=$args
$c=$a[0]
$b=$a[2..$c]
(
    (gc wordlist.txt) -match "^$(
        (
            1..$c | ForEach-Object -Begin {
                $e = ,"[^$($a[1])]" * $c
            } -Process {
                $e[$_-1] = (
                    ( ( @($b) -match "^$_\D" )[0] -split $_ )[-1] , $e[$_-1] -ne ''
                )[0]
            } -End {
                $e-join''
            }
        )
    )$" -join '' -split'\B' |
    Where-Object {
        -not (@($b) -match $_).Count
    } | 
    Group-Object |
    Sort-Object count
)[-1].Name

壊す

ここで私が取ったアプローチは、最初に正規表現を生成して、単語リストから可能な単語を取得することでした。単語の長さと機能しなかった文字がわかっているので、それを使ってかなり簡単に正規表現を作成できます。

したがって、PEOPLEの例では、XBZが単語の一部ではない6文字で、を生成しようと思います^PE[^XBZ]P[^XBZ]E$

Get-Contentgc)が行の配列を返し-match、左側の配列で演算子を使用するとブール値の代わりに一致の配列が返されるという事実を利用しているので、候補者、私は正規表現を持っています。

正規表現を生成するには$e$c要素($c単語の文字数)を含む否定一致文字クラスの配列()から始めます。1からまでの数字を繰り返して、$cその位置に一致する文字があるかどうかを確認し、存在する場合は、要素$eをその文字に置き換えます。

すべての位置を繰り返した後、最終的な配列が-join(空の文字列で)edされ、正規表現ができました。

だから今私はそれがあり得るすべての可能な単語の配列を持っています。その-join上に空の文字列があるクイックは、すべての単語の1つの大きな連結文字列を与え、私は分割します\B(単語の境界ではなく、空の文字列で分割した場合、2つの余分な空白要素を取得します)。すべての可能な単語のすべての文字の。

それをパイプするWhere-Objectことで、すでに一致している文字をフィルターで除外できます。この部分は本当に痛かった。一致する文字(位置を含む)のリストを1要素、1要素以上、または0要素で処理$bする必要-matchがあったため、最初に配列に強制的に入れてすべての要素を操作できるようにしましたが、(この場合は残念ながら) )は配列を返すため、確認する必要があり.Countます。を使用すること!(thing).Countは、を使用するよりも少し小さいです(thing).Count-gt0

次に進むと、可能性のあるすべての単語から(stringsとしてではなくchar)すべての単一文字の配列から、すでに正しく推測された文字を除いたものが得られます。

これをパイプするGroup-Objectと、各文字のカウントが含まれるオブジェクトが得られるので、パイプをすばやくSort-Object count入れると、最大のカウントを簡単に取得できます。代わりに(thing|sort count -des)[0]使用できます(thing|sort count)[-1]。PowerShell [-1]では、最後の要素を取得します。この時点ではまだ元のオブジェクトを処理しているGroup-Objectので.Name、最も多く出現する文字であるプロパティを取得します。

ノート

  • PowerShell v3以降で動作するはずです。ほぼ間違いなく2を窒息させます。
  • PowerShellスクリプトを呼び出すときは、引数をコンマではなくスペースで渡してください。
  • ルールには記載されていませんwordlist.txtが、数バイトを削る可能性のあるファイル名を使用しているようです。
  • 速度は問題になりません。これは私にはすぐに実行されるようです。実行が最も遅い実行(.\hangman.ps1 7 0)は約350ミリ秒で実行されます。

1
プログラミングパズルとコードゴルフスタック交換へようこそ。:)
ドアノブ

@Doorknobどうもありがとう!
ブライアンティスト、2015

6

Python3、299バイト

import sys,collections as c;x,X,N,*Z=sys.argv;print([x for x in c.Counter(''.join([''.join(x)for x in map(set,filter(lambda l:len(l)==int(X)+1and all(x not in X.lower()for x in l)and all(l[int(x[0])-1]==x[1].lower()for x in Z),open('wordlist.txt')))]))if x not in ''.join(Z).lower()and x!='\n'][0])

これはさらにゴルフできると確信しています。

潜在的な一致についてワードリストをフィルタリングし、char頻度マップを作成し、まだ選択されていない最も頻繁に出現する文字を選択します。


''.join(..)s がたくさんあります。内部のすべての要素が長さ1の文字列の'..'[2::5]場合、アポストロフィがバッククォートであるに変更できます。
Kade、

3

Java、646 640 631 607 606(短)790 789 779(高速)バイト

ショート

import java.util.*;class I{public static void main(String[]a)throws Exception{char[]w=a[1].toCharArray(),p,q;int l=Integer.parseInt(a[0]),i,z=w.length,j;q=new char[l];for(i=2;i<a.length;i++)q[Character.getNumericValue(a[i].charAt(0))-1]=(char)(a[i].charAt(1)+32);java.io.File u=new java.io.File("wordlist.txt");Scanner s=new Scanner(u);while(s.hasNextLine()){p=s.nextLine().toCharArray();if(p.length==l)for(i=0;i<l;i++)if(p[i]==q[i]||q[i]=='\0'){if(i==l-1)y:for(i=0;i<l;i++)for(j=0;j<z;j++)if(!(p[i]==w[j])){if(j==z-1){System.out.print(p[new String(q).indexOf('\0')]);return;}}else break y;}else{break;}}}}

速い

import java.util.*;class I{public static void main(String[]a)throws Exception{char[]w=a[1].toCharArray(),p,q;int l=Integer.parseInt(a[0]),i,z=w.length,j,k,o,n[]=new int[255],r[];q=new char[l];for(i=2;i<a.length;i++)q[Character.getNumericValue(a[i].charAt(0))-1]=(char)(a[i].charAt(1)+32);String m=new String(q);java.io.File u=new java.io.File("wordlist.txt");Scanner s=new Scanner(u);while(s.hasNextLine()){p=s.nextLine().toCharArray();h:if(p.length==l)for(i=0;i<l;i++)if(p[i]==q[i]||q[i]=='\0'){if(i==l-1)y:for(i=0;i<l;i++)for(j=0;j<z;j++)if(p[i]!=w[j]){if(j==z-1){for(k=0;k<l-m.replace("\0","").length();k++)n[(int)p[new String(q).indexOf('\0',k)]]++;break h;}}else break y;}else{break;}}r=n.clone();Arrays.sort(n);for(o=0;o<255;o++)System.out.print(r[o]==n[254]?(char)o:"");}}

ワードリストファイルをフォルダに入れます。

ショートバージョンアルゴリズム

  1. 引数をロード
  2. 推測しようとしている単語を作成する{'p'、 'e'、 '\ 0'、 'p'、 '\ 0'、 'e'}
  3. WordListを読み込む
  4. WordListの各行を確認する
  5. 単語全体がこの条件p[i] == q[i] || q[i] == '\0'に一致することがわかったら停止します。ここで、pは単語リスト(char配列)の単語であり、qは推測しようとしている単語です。
  6. 間違った文字をループして単語と比較する
  7. 最初の欠けている文字を印刷する

長いバージョンのアルゴリズム

  1. 短いステップ1〜7
  2. 不足している文字のn配列の文字カウントをインクリメントします
  3. すべての単語が通過するまでループする
  4. 最も数の多い文字を印刷します

インポートを削除できますか?
RobertoAnićBanić15年

コードゴルフでJavaインポートを削除しても大丈夫ですか?
RobertoAnićBanić15年

あなたが指定する限り、それは問題ありません(それが明らかでない場合は、インポートする必要があります);)
WayToDoor

Kk。家に帰ったら更新します。新しいルーターを購入するつもりです:)およびCat5eの90フィート
RobertoAnićBanić15年

1
9文字を超える単語には効果がないと思います。入力「6 XBZ 1P 5P 6E 11E」でワードリストから「prospective」を使用してみてください。おそらく最初のループをq [Integer.parseInt(a [i] .substring(0、a [i] .length()-1)に変更します。 )-1] =(char)(a [i] .charAt(a [i] .length()-1)+32); また、ゴルフのヒント:Scanner s = new Scanner(new java.io.File( "wordlist.txt"));を使用してみてください。
bmarks 2015

2

PHP、346バイト

<?php $a='array_shift';$p='preg_match';$a($v=&$argv);$w=array_fill(1,$a($v),'(.)');$c=$a($v);foreach($v as$q)$p('/(\d+)(\w)/',$q,$m)&&$w[$m[1]]=$m[2];foreach(file('wordlist.txt')as$y)if($p("/^".implode($w)."$/",$y=strtoupper(trim($y)),$m)&&(!$c||!$p("/[$c]/",$y)))for($i=0;$i++<count($m);)($v=@++$g[$m[$i].$i])&&$v>@$t&&$t=$v&&$l=$m[$i];echo @$l;

次のように機能します。

  1. これまでに推測された文字を照合するための正規表現パターンを作成します
  2. ファイルの各単語を反復処理します
  3. 単語が正規表現と一致する場合、間違った文字が含まれていないことを確認します
  4. (位置に基づいて)その単語の可能な各文字のカウンターをインクリメントします。
  5. カウンターが最も高い文字を出力します

仮定:

  • PHP >=5.4
  • wordlist.txt現在のフォルダにファイルがあります

php hangman.php 6 YH 2E 6E 3O 1P 4P PHP Notice: Undefined offset: 2 in ./Desktop/hangman.php on line 1 Notice: Undefined offset: 2 in ./Desktop/hangman.php on line 1彼に人を推測させることを試みた
WayToDoor '17

1
指摘してくれてありがとう。コードに小さなバグがありました。更新しました(まだ346バイト)。
Razvan

1

Powershell、153バイト

ブライアンティストの回答に触発されました。

他の作家として、私はファイル名を使用しましたwordlist.txt。短い名前を選択することは可能でしたが。

param($l,$b,$c)((sls "^$(-join(1..$l|%{$p=$c|sls "$_."|% m*
("$p"[1],"[^$b$c]")[!$p]}))$" wordlist.txt|% l*e|% t*y|group|sort c*).Name-match"[^ $c]")[-1]

ゴルフのテストスクリプトが少ない:

$f = {

param($length,$bad,$chars)

$wordPattern=-join(1..$length|%{                  # join all subpatterns for $_ from 1 to $length
    $c=$chars|sls "$_."|% Matches                 # find subpattern in char array
    ("$c"[1],"[^$bad$chars]")[!$c]                # return a first char of subpattern if subpattern found, or bad characters
})

# Note 1: The word subpattern is similar to 'PE[^XBZ1P 4P 2E 6E]P[^XBZ1P 4P 2E 6E]E'
#         Spaces and digits does not affect the search for letters, only letters are important.
#
# Note 2: The same applies to 0. [^0] matches any letter.
#

$matches=sls "^$wordPattern$" wordlist.txt|% Line # find matched words in file wordlist.txt and return matched string only
$groups=$matches|% toCharArray|group|sort Count   # group all chars in matched words by count
$name=$groups.Name-match"[^ $chars]"              # select property Name from all grouped elements (chars itself) and return not matched to $chars only
$name[-1]                                         # return last element in the sorted array (most frequently found char)

# Note 3: The space is important in the regexp "[^ $chars]"
#         The space makes the regexp valid if the $chars array is empty

}

&$f 7 0 2o,5e,7t
&$f 7 nl 2o,5e,7t
&$f 6 XBZ 1P,4P,2E,6E

出力:

c
r
l

の変数値&$f 7 0 2o,5e,7t

$WordPattern: "[^02o 5e 7t]o[^02o 5e 7t][^02o 5e 7t]e[^02o 5e 7t]t"
$Matches: concept collect comment correct connect convert consent concert
$Groups:
    Count Name                      Group
    ----- ----                      -----
        1 p                         {p}
        1 v                         {v}
        1 s                         {s}
        2 m                         {m, m}
        2 l                         {l, l}
        4 r                         {r, r, r, r}
        8 n                         {n, n, n, n...}
        8 o                         {o, o, o, o...}
        8 t                         {t, t, t, t...}
        8 e                         {e, e, e, e...}
       13 c                         {c, c, c, c...}
$name: p v s m l r n c
$name[-1]: c
return: c
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.