江師とTCL

このようなまれな、あまり知られていないtclプログラミング言語があります。 ウィキペディアでは、よく書かれていますが、プログラムを書くときに疑問が生じます。

Jianshiji-これはそのような中国のゲーム(名前で判断)、「ピッキングストーン」として翻訳され、それ自体興味深いです。 各プレイヤーは、任意の山から任意の数の石を取り、同時に両方から同じ量を取ります。 最後の石を取る人が勝ちます。 より詳細な説明はこちらです。 バランスを維持するためのゲーム:一方で、ヒープ内の数値が異なる必要があり、その結果、差異が大きくなりすぎないようにします。 そもそもゲームには勝利戦略がありますが、その起源については考慮しません。 簡単な説明をしてください。 次の動きをするプレイヤーが負けるヒープサイズの組み合わせがあります。









角括弧は、部品全体のキャプチャを示します。 いいえ、最初の式はフィボナッチ数ではありませんが、係数は同じですが、ここでは幾何学的ではなく、算術級数です。 ペアの番号の差はnであることに注意してください。



以前のhabrには、TCLのリバーシが64行、TCLの15行10行であり、コンパクトで美しいコードがありましたが、ここではそのようなものは表示されません。 また、彼はおそらくマナーからは程遠い。 一般に、govnokodが好きなように思える場合は、おそらくそうです。 一方で、将来的に改善すべき点があるため、さらに良いことです。 言語が私にとって新しいものであるという事実もあり、説明を行うのがより便利になることもあります。 また、オプションのチェックもありません。

次はプログラムの一部です。 最適とはほど遠いですが、言語の機能と動作を示しています。



プログラムの始まりは次のとおりです。

#!/usr/bin/tclsh #---  (+ ab)    #---  ,   , (a + b)     namespace path {::tcl::mathop ::tcl::mathfunc} #---   proc lsum L {expr [join $L +]+0} proc random range {expr int(rand()*$range)}
      
      







ペアを失うためのコード:

 set n_max 20 ;#  for {set i 1} {[<= $i $n_max]} {incr i} { set q [/ [+ [sqrt 5] 1 ] 2] ;# " " set a [int [* $q $i]] ;#i-  a set b [+ $a $i] ;#ie  b lappend lPair1 "$a $b" ;#   lPair1  a  b }
      
      





次のようなリストを表示できます。

  puts lPair1; #    ;  ,  ,      
      
      





出力は次のとおりです。

{0 0} {1 2} {3 5} {4 7} {6 10} {8 13} {9 15} {11 18} {12 20} {14 23} {16 26} {17 28} {19 31} {21 34} {22 36} {24 39} {25 41} {27 44} {29 47} {30 49} {32 52}



そのため、個人のコースに応答するために使用するペアのリストがあります;特定のペアを選択する方法を学ぶ必要があります。 新しい状態に移行するには、3つのオプションがあります。



石だけを取るべきなので、石の合計は動きごとに減少します。

コンピューターの移動コマンドに移りましょう。



 #--- : #----st -  , #----lAns -             #----lPair -      , #--------------         proc turn {st lAns lPair} { set st_cur_sum [lsum $st] ;#   #---   ,    0    0, #---  ,      if {[== 0 $st_cur_sum]} {return {you win}} set a [lindex $st 0] ;#      set b [lindex $st 1] ;#      #---lindex -       , #---           set c [abs [- $a $b]] #--- ,     #---    ,     set a1 [min $a [lindex $lAns $b]] set b1 [min $b [lindex $lAns $a]] set cPair1 [lindex $lPair $c] #---      set a2 [random $a] set b2 [random $b] set c2 [random [+ 1 [min $a $b]]] set cPair2 [list [- $a $c2] [- $b $c2]] set st_next1 [list "$a $b1" [+ $a $b1]] set st_next2 [list "$a1 $b" [+ $a1 $b]] set st_next3 [list "$cPair1" [lsum $cPair1]] #---    set lst_next [list $st_next1 $st_next2 $st_next3] #---     set st_next [lindex [lsort -integer -index 1 $lst_next] 0] set st_next_sum [lindex $st_next 1] if {[== 0 $st_next_sum]} {return {i won}} ;#   -  ,   #--- ,     #---  ,    - , #--- :   ,      ,   #---   ,     if {[> $st_cur_sum $st_next_sum]} { return [lindex $st_next 0] } else { #---     -    switch [random 3] { 0 {return "$a $b2"} 1 {return "$a2 $b"} 2 {return "$cPair2"} } } }
      
      





lAnsとlPairについての簡単な説明。 勝利のリターンムーブは、上記の3つのオプションのいずれかと一致する必要があります。 さらに、最初の2つは、取得するヒープが異なるだけです。 最初のオプションを考えてみましょう。最初のヒープから取得します。つまり、2番目のヒープは変更されず、その中の石の数によって、最初のヒープのサイズを決定できます。 どれだけ取るかではなく、どれだけ去るか。 lAnsの内容は次のとおりです。

0 2 1 5 7 3 10 4 13 15 6 18 20 8 23 9 26 28 11 31 12 34 36 14 39 41 ...

リスト内のインデックスは、変化しないヒープ内のストーンの数です。このインデックスの値は、ヒープ内の新しいストーンの数であり、そこからストーンを取得します。

lPairの内容は、上記のlPair1の内容と変わりません。 この場合のインデックス値は、インデックスに等しい差を持つ石の新しいペアを表します。

次に、ユーザーとの対話を整理する方法を示します。

 puts {Enter heap sizes:} #--- ,     if {[< 0 [gets stdin state]]} { #---    set n_max [lindex [lsort -integer $state] end] #---    genAnsList $n_max lPair lAns #---   set state [turn $state $lAns $lPair] #   puts $state #---      while {[< 0 [gets stdin state]]} { set state [turn $state $lAns $lPair] puts $state } }
      
      







コード全体はpastebinで見ることができます。

言語の構文は参照によるものです。

リストの操作は重要です。対応するコマンドはドキュメントにあります

PS次のパートでは、もしそうであれば、コメント内の建設的なコメントが考慮されます。



All Articles