object B{
def main(a: Array[String]):Unit={
val v=false
val (m,l,k,r,n)=(()=>print("\033[H\033[2J\n"),a(0)toInt,a(1)toInt,scala.util.Random,print _)
val e=Seq.fill(k, l)(v)
m()
(0 to (l*k)/2-(l*k+1)%2).foldLeft(e){(q,_)=>
val a=q.zipWithIndex.map(r => r._1.zipWithIndex.filter(c=>
if(((r._2 % 2) + c._2)%2==0)!c._1 else v)).zipWithIndex.filter(_._1.length > 0)
val f=r.nextInt(a.length)
val s=r.nextInt(a(f)._1.length)
val i=(a(f)._2,a(f)._1(s)._2)
Thread.sleep(1000)
m()
val b=q.updated(i._1, q(i._1).updated(i._2, !v))
b.zipWithIndex.map{r=>
r._1.zipWithIndex.map(c=>if(c._1)n("X")else if(((r._2 % 2)+c._2)%2==0)n("O")else n("_"))
n("\n")
}
b
}
}
}
使い方
アルゴリズムはまず、2Dシーケンスに偽の値を入力します。入力されたコマンドライン引数に基づいて、反復(開いたボックス)の数を決定します。この値を上限として折り畳みを作成します。フォールドの整数値は、アルゴリズムが実行される反復回数をカウントする方法として暗黙的にのみ使用されます。前に作成した塗りつぶしシーケンスは、フォールドの開始シーケンスです。これは、対応する不確実性を持つ偽値の新しい2Dシーケンスを生成する際に使用されます。
例えば、
[[false, true],
[true, false],
[true, true]]
になります
[[(false, 0)], [(false, 1)]]
完全に真である(長さが0の)リストはすべて、結果リストから省略されることに注意してください。次に、アルゴリズムはこのリストを取得し、最も外側のリストからランダムなリストを選択します。ランダムリストは、選択したランダムな行になるように選択されます。そのランダムな行から、再び乱数、列インデックスを見つけます。これらの2つのランダムなインデックスを見つけたら、現在のスレッドを1000ミリ秒スリープします。
スリープが完了したら、画面をクリアし、作成true
したランダムインデックスで値が更新された新しいボードを作成します。
これを適切に印刷map
するには、コンテキストの中でそれを使用するために、マップのインデックスを使用して圧縮します。我々は、印刷すべきかどうかについての一連の真理値を使用するX
かのいずれかO
またはを_
。後者を選択するには、インデックス値をガイドとして使用します。
注意すべき興味深いこと
O
またはを印刷する必要があるかどうかを判断するため_
に、条件((r._2 % 2) + c._2) % 2 == 0
が使用されます。r._2
は現在の行インデックスをc._2
参照し、現在の列を参照します。1つが奇数行にある場合、1になります。r._2 % 2
したがってc._2
、条件付きで1つオフセットされます。これにより、奇数行では、意図したとおりに列が1ずつ移動します。
"\033[H\033[2J\n"
読んだStackoverflowの回答によると、文字列を出力すると画面がクリアされます。ターミナルにバイトを書き込んで、あまり理解できないファンキーなことをしています。しかし、私はそれが最も簡単な方法であることがわかりました。ただし、Intellij IDEAのコンソールエミュレーターでは機能しません。通常のターミナルを使用して実行する必要があります。
このコードを最初に見ると、奇妙なことに気付くかもしれない別の方程式があります(l * k) / 2 - (l * k + 1) % 2
。まず、変数名を分かりやすく説明しましょう。l
は、プログラムに渡される最初の引数をk
参照し、2番目の引数を参照します。それを翻訳するには、(first * second) / 2 - (first * second + 1) % 2
。この方程式の目標は、すべてのXのシーケンスを取得するために必要な正確な反復量を算出することです。初めてこれをやったとき、(first * second) / 2
それは理にかなっているようにした。n
各サブリストのすべての要素には、n / 2
ポップできるバブルがあります。ただし、次のような入力を処理する場合、これは壊れます。(11 13)
。2つの数値の積を計算し、偶数の場合は奇数にし、奇数の場合でも奇数にし、そのmodを2にする必要があります。これは、奇数の行と列が1回少ない反復を必要とするため最終結果を得るために。
map
forEach
文字数が少ないため、aの代わりに使用されます。
おそらく改善できるもの
このソリューションについて本当に私を悩ませていることの1つは、頻繁に使用することですzipWithIndex
。それは非常に多くのキャラクターを占めています。zipWithIndex
渡された値で実行する独自の1文字関数を定義できるようにしようとしました。しかし、Scalaでは匿名関数に型パラメーターを許可していません。おそらくzipWithIndex
私が使用せずにやっていることを行う別の方法がありますが、私はそれを行う賢い方法についてあまり考えていません。
現在、コードは2つのパスで実行されます。1つ目は新しいボードを生成し、2つ目のパスはそれを出力します。これら2つのパスを1つのパスに結合すると、数バイトを節約できると思います。
これは私がやった最初のコードゴルフですので、改善の余地があると確信しています。可能な限りバイトを最適化する前にコードをご覧になりたい場合は、こちらをご覧ください。
1
andの0
代わりにO
and を使用できますX
か?