エキスパートのようにNimボードを視覚化する


10

バックグラウンド

ニムのゲーム、プレイヤーは「山」から「石」を削除交互:各ターンに、プレイヤーから1とすべての石の間で削除する必要があり、単一の杭。Nimの目的は、最後の石を取るか、または惨めなバリエーションでは、対戦相手に強制することです-ただし、戦略はほぼ同じであることがわかります。

ニムは楽しいバーゲームを作ります。「石」にはマッチ棒やコインを使うことができ、「山」は通常一列に並べられます。以下は、パイルが1、3、5、および7のクラシックなセットアップです。

マッチ棒でニム

Nimをプレイしたことがない場合は、このチャレンジに挑戦する前に、Ni​​mを試してみてください。これは、"Pearls Before Swine"と呼ばれるバージョンです。

戦略

Nimの最適な戦略は十分にトリッキーであり、ほとんどの素人は常に専門家に負けますが、バイナリ演算で簡単に説明できます。

ただし、メンタルバイナリXOR演算を実行するのは難しいので、幸運なことに、酔っているときでもリアルタイムで実装しやすい正しい戦略を視覚化する同等の方法があります。

手順は3つだけです。

  1. 各行の「ストーン」を2の累乗のサイズのサブグループに精神的にグループ化します。可能な最大のサイズから始めます。ほとんどのゲームでは8、4、2、1で十分です。
  2. 各グループを別の行のツインと一致させて、すべてのグループがペアになるようにします。
  3. これが不可能な場合は、ペアになっていない "石"を1行から削除します(これは常に可能です-理由はWikipediaのリンクを参照してください)。これにより、手順2.が可能になります。

または、別の言い方をすると、「1つの山からいくつかの石を削除して、山を2の累乗にグループ化すると、すべてのグループが別の山のグループとペアになる場合があります。」2の大きな累乗を小さな累乗に分割できないことに注意してください。たとえば、8石のラインを4の2つのグループにグループ化することはできません。

たとえば、上記のボードを視覚化する方法は次のとおりです。

バランスのとれたマッチ棒

このボードは完全にバランスが取れているので、相手を先に動かしたいでしょう。

チャレンジ

Nimの「パイル」のサイズを表す正の整数のリストを指定すると、専門家が見たNimボードのプレーンテキストの視覚化を返します。

有効な視覚化を構成するものは、例によって最もよく説明されますが、次のことを行う必要があります。

  1. 各「2の累乗サブグループ」とそのペアに個別の文字を割り当て(ペアになっていないサブグループは対象外)、その文字を使用してサブグループとペアの両方の「石」を表します。
  2. ハイフンを使用して、ペアになっていない「ストーン」(つまり、エキスパートが通常のプレー時に削除するもの-不快ではない-Nim)を表します-

有効な視覚化を実現する方法は複数あり、すべて有効です。いくつかのテストケースを見てみましょう。

テストケース

入力:1、3、5、7

可能な出力1:

A
BBA
CCCCD
CCCCBBD

オプションで、文字の間にスペースを入れたり、行の間に空白行を入れたりできます。

可能な出力2:

A

B B A

C C C C D

C C C C B B D

入力:1、2、3、4、5、6、7、8、9、10

文字の順序と選択は好きなようにすることができます:

可能な出力1:

G
E E
E E G
C C C C
C C C C F
B B B B D D
B B B B D D F
H H I - - - - -
A A A A A A A A I
A A A A A A A A H H

Unicode記号も問題ありません。

可能な出力2:

◎
◈  ◈
◈  ◈  ◎
△  △  △  △
△  △  △  △  ◉
◐  ◐  ◐  ◐  ◀  ◀
◐  ◐  ◐  ◐  ◀  ◀  ◉
▽  ▽  ◒  -  -  -  -  -
▥  ▥  ▥  ▥  ▥  ▥  ▥  ▥  ◒ 
▥  ▥  ▥  ▥  ▥  ▥  ▥  ▥  ▽  ▽  

入力:7

ルールから、「単一パイル」は完全に取り除かれなければならないということになります。

可能な出力1:

-------

可能な出力2:

- - - - - - -

入力:5、5

可能な出力:

A A A A B
A A A A B

追加ルール

  • これは標準ルールのコードゴルフです。最短のコードが勝ちます。
  • 入力は柔軟で、リストに似た形式で取得できます。
  • 上記の例が示すように、出力も柔軟です。最も妥当なバリエーションが許可されます。何かわからないことがあるかどうか尋ねます。

1
各パイルに含まれる石の数、または視覚化に必要な個別の文字の数に制限はありますか?(極端な場合、たとえば、印刷可能なASCII文字の数以上、または255を超える個別の文字が必要な場合はどうなりますか?)
ドアノブ

@Doorknobあなたはそれが起こらないと仮定することができます。アルファベットの文字はすべての入力に十分であると想定することもできます。
ジョナ

@Jonahは2番目のテストケースの有効な出力でしょうか?["H","EE","EEH","CCCC","CCCCI","DDDDFF","DDDDFFI","AAAAAAAA","AAAAAAAA-","----------"]
ngn

1
@Οurous簡単な答えはイエスだと思います。技術的にAAAABBBBは実際には無効であり、無効でABBはありませんが、出力が読みにくくなるので、行内で減らすことを明示的なルールにするだけが最善だと思います。
ジョナ

1
@JonathanAllanはい、私は3つのステップすべてが同時に発生する必要があるというロジックに依存しています。したがって、ステップ1と2を実行してもステップ3を実行できない場合は、ソリューションをステップ1と2に調整する必要があります。以下に説明を追加しました。
ジョナ

回答:


2

ルビー、169の 164 148バイト

->a{s=eval a*?^
c=?@
m={}
a.map{|x|z=x-(x^s);[$><<?-*z,x-=z,s=0]if z>0
n=1
eval'x&1>0?[$><<(m[n]||c.next!)*n,m[n]=!m[n]&&c*1]:0;n*=2;x/=2;'*x
puts}}

オンラインでお試しください!

まず、初期化します

  • nim-sum with s=eval a*?^(より短いa.reduce:^
  • 変数c。最初の未使用の一意の文字を格納します
  • m2のべき乗の長さを表すために使用される文字にマップするマップ

次に、各パイルをループして、以下を実行します。

z=x-(x^s);[$><<?-*z,x-=z,s=0]if z>0

パーウィキペディアの戦略場合、NIM和XORパイルが未満である、私たちは、その長さになるようにその山から石を削除する必要がありNIM和XORパイル。変数zに差を格納することで、この差が正かどうかをテストして確認できます。正の場合は、1)その多くのダッシュを出力します。2)パイルから減算します。3)nim-sum変数を次のように設定します。さらなる石の除去を防ぐためにゼロ。

n=1
eval'[...];n*=2;x/=2;'*x

今、各ビットを超える「ループ」とは、繰り返し分割することによって、それらの値を追跡するxことで2、アキュムレータ乗じるnことによってを2。ループは実際には文字列が評価されたx回数でありlog2(x)、必要な回数よりもはるかに多くなりますが、害はありません(非効率性を除いて)。各ビットについて、ビットが1(x&1>0)の場合、以下を実行します。

$><<(m[n]||c.next!)*n

文字をn回印刷します。これだけ多くの石のペアになっていないグループを既に印刷している場合は、その文字を使用します。それ以外の場合は、次の未使用の文字を使用します(のcためにインプレースで前進し!ます)。

m[n]=!m[n]&&c*1

m[n]存在する場合(つまり、ペアを完成させたばかり)、m[n]リセットされます。それ以外の場合は、新しいペアを開始したばかりなので、m[n]使用した文字に設定します(*1のコピーを作成する簡単な方法ですc)。


4

パイソン2150の 196 206バイト

def f(p):
 c=48;s=[l*'.'for l in p];m=2**len(bin(l))
 while m:
  if sum(m*'.'in l for l in s)>1:
   for i,l in enumerate(s):s[i]=l.replace('.'*m,chr(c)*m,`s`.count(chr(c)*m)<2)
   c+=1
  else:m/=2
 return s

オンラインでお試しください!


私はこれがうまくいくとは思いません4, 9, 10
Neil

@ニールナイスキャッチ、今すぐ修正する必要がある
TFeld

1
申し訳ありませんが、私はなんとかして、今回はでそれをだますことができました14, 21, 35
Neil

[1、3、4、5]の場合も失敗し、2番目のパイル全体が削除されます。
ドアノブ

@Doorknob、それは必要ですか?ルールによるとThere will be multiple ways to achieve a valid visualization, and all are valid
TFeld '19年

1

JavaScript(ES6)、215バイト

f=
(a,c=0,x=eval(a.join`^`),i=a.findIndex(e=>(e^x)<e),b=a.map(_=>``),g=e=>(d=e&-e)&&a.map((e,i)=>e&d&&(a[i]-=d,b[i]=(c++>>1).toString(36).repeat(d)+b[i]))&&g(e-d))=>g(eval(a.join`|`),b[i]='-'.repeat(a[i]-(a[i]^=x)))||b
<textarea oninput=o.textContent=/\d/.test(this.value)?f(this.value.match(/\d+/g)).join`\n`:``></textarea><pre id=o>

最大36の異なるキャラクターのみを視覚化します。この作品はのために安心してい1, 3, 4, 5ます。


すごくいい。リアルタイムで遊ぶのも楽しいです。
ジョナ

1

クリーン、454バイト

まだゴルフ

import StdEnv,Text,Data.List
$p=join"\n"[{#toChar c+'-'\\c<-e}\\e<-[take i(e++[0,0..])\\e<-r[[~c\\c<-reverse e,_<-[1..c]]\\e<-hd[q\\q<-foldr(\h t=[[a:b]\\a<-h,b<-t])[[]][[c\\c<-subsequences(takeWhile((>=)k)(iterate((*)2)1))|sum c<=k]\\k<-p]|sum[1\\a<-q&b<-p|sum a<>b]<2&&foldr(bitxor)0(flatten q)==0]]1&i<-p]]
r[]_=[]
r[h:t]n|all((<)0)h=[h:r t n]
#[m:_]=removeDup[e\\e<-h|e<0]
#(a,[x:b])=span(all((<>)m))t
=r([[if(e==m)n e\\e<-k]\\k<-[h:a]++[x]]++b)(n+1)

オンラインでお試しください!

関数を定義し$ :: [Int] -> String、杭のサイズを取り、-削除する石を示す文字列を返します。グループは、から昇順のASCII文字で表され-ます。十分なグループが必要な場合、文字は最終的に折り返さfoldrれます。そのため、2番目のテストケースを実行するには、ギガバイトを超えるメモリが必要になります。

巨大な内包の字下げバージョン:

$p=join"\n"[
    {#
        toChar c+'-'
        \\c<-j
    }
    \\j<-[
        take i(e++[0,0..])
        \\e<-r[
            [
                ~c
                \\c<-reverse e
                ,_<-[1..c]
            ]
            \\e<-hd[
                q
                \\q<-foldr(\h t=[
                    [a:b]
                    \\a<-h
                    ,b<-t
                ])[[]][
                    [
                        c
                        \\c<-subsequences(takeWhile((>=)k)(iterate((*)2)1))
                        |sum c<=k
                    ]
                    \\k<-p
                ]
                |sum[
                    1
                    \\a<-q
                    &b<-p
                    |sum a<>b
                ]<2&&foldr(bitxor)0(flatten q)==0
            ]
        ]1
        &i<-p
    ]
]

奇妙なことに、Cleanはhaskellに似ているようです... Haskellに比べてその利点は何ですか?
ジョナ

1
@ジョナそれはかなり似ています、はい。私の頭の上では、低レベルの型操作、インラインIL /アセンブリ、およびCとの相互運用がすべてHaskellよりも簡単に実現されています。ただし、実際に使用する場合は、Cleanのあいまいさと実験的/学術的な性質のため、Haskellをお勧めします(これには、ライブラリおよび参照情報の点でもサポートが強化されています)。私はたまたまクリーンが好きです。
Οurous
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.