在Clojure(/ Java)中表示国际象棋比特的一些可行方法是什么?
http://pages.cs.wisc.edu/~psilord/blog/data/chess-pages/rep.html
我需要能够访问各个位并执行按位操作。
我想过使用java.lang.Long,但由于标牌,这会导致1x10 ^ 63的问题。我也不确定如何访问特定索引处的位?
我也看了BitSet,但理想情况下我需要一个固定的长度。
答案 0 :(得分:7)
没有理由你不能长时间使用。正如你所指出的那样,问题在于java(并因此是clojure的)长签名,只允许63位为正数
默认情况下,Java允许算术溢出而不会出错。默认情况下,Clojure不允许算术溢出而不会出现错误(请参阅*unchecked-math*标志)。它增加了对算术运算和强制转换的额外检查,因此,例如,(byte 128)
将导致异常。从clojure v1.3.0开始,有类似(unchecked-byte)
的函数,它等同于java函数....
(unchecked-byte 128)
;=> -128 ; 2s-complement of 10000000
(unchecked-byte 2r10000001)
;=> -127 ; 2s-complement of 10000001
可提供大量unchecked-*
次操作(see clojuredocs)。
如果您使用笔直长和unchecked-*
操作,那么您可以使用bit-*
操作来旋转/检查位。
最后将棋盘存储在原子中是有意义的,然后用(swap! chessboard fn args)
(2013年2月15日更新,稍微更惯用的交换!来电)
e.g。
(inc Long/MAX_VALUE) ; java.lang.ArithmeticException
(unchecked-inc Long/MAX_VALUE) ; wraps.
-9223372036854775808
(def chessboard (atom 0))
@chessboard
;=> 0
(bit-test @chessboard 1)
;=> false
(swap! chessboard bit-flip 1)
;=> 2
(bit-test @chessboard 1)
;=> true
@chessboard
;=> 2
(reset! chessboard 0)
;=> 0
(swap! chessboard bit-flip 63)
;=> -9223372036854775808
(bit-test @chessboard 63)
;=> true
答案 1 :(得分:1)
=> (def chessboard (byte-array 8))
#'user/chessboard
=> (vec chessboard)
[0 0 0 0 0 0 0 0]
=> (for [row (range 8)] (aset-byte chessboard row (rand-int 8)))
(3 0 6 6 2 3 6 7)
=> (bigint chessboard)
216179404987106823N
=> (defn bigint-to-array
[bi]
(.toByteArray (biginteger bi)))
=> (vec (bigint-to-array 216179404987106823N))
[3 0 6 6 2 3 6 7]
Clojure以这种方式支持您需要的大多数功能。像所有的clojure数字一样,clojure.lang.BigInt支持二进制操作(bit-etc.等)。在字节数组上,您可以使用java.util.Arrays中的所有方法(搜索,填充,排序)。
请注意bigint fn强制执行clojure.lang.BigInt,并且biginteger fn强制执行java.math.BigInteger。如果你想使用java.math.BigInteger的方法,你需要通过biginteger来强制你的bigint或字节数组。