02.003.32ary xor over scores - MCJE-Tech-Community/Datapack-WIki GitHub Wiki
❇️ スコアの32項XOR
概要
XORとは排他的論理和のことです。
ビットの2項(2入力)XOR演算$⊕$は以下のように定義されます。
\begin{align*}
0 ⊕ 0 &= 0 \\
0 ⊕ 1 &= 1 \\
1 ⊕ 0 &= 1 \\
1 ⊕ 1 &= 0
\end{align*}
$⊕$は直観的には繰り上がりを無視したビットの足し算と考えることができます。
スコアの2項XOR演算$\texttt{xor}$はビット単位でXOR演算を行う演算で、$⊕$を用いて以下のように定義されます。
$a_i$はスコア$a$の下位から数えて$i$番目のビットを表します。
\begin{align*}
(a \ \texttt{xor} \ b)_i &= a_i ⊕ b_i \\
&& または \\
a \ \texttt{xor} \ b &= \sum_{i=0}^{31} 2^i (a_i ⊕ b_i)
\end{align*}
スコアの32項XOR演算$\texttt{xor}_{32}$は$\texttt{xor}$を用いて以下のように定義されます。
\begin{align*}
\texttt{xor}_{32}(a^0, a^1, \cdots, a^{31}) &= a^0 \ \texttt{xor} \ a^1 \ \texttt{xor} \ \cdots \ \texttt{xor} \ a^{31}
\end{align*}
実装
⚠️ ワイルドカード(
*)を使っているため、スコアホルダーの増加によるパフォーマンスの低下に注意してください。
#> initialize.mcfunction
# 定数用のオブジェクティブ
scoreboard objectives add const dummy
# 一時変数用のオブジェクティブ
scoreboard objectives add temp dummy
# 入出力用のオブジェクティブ
scoreboard objectives add user dummy
# ワイルドカード(*)によるスコアの一括加算に用いる定数
scoreboard players set $00 const 0
# ビットシフトに用いる定数($i = 1 << i)
scoreboard players set $01 const 2
scoreboard players set $02 const 4
scoreboard players set $03 const 8
scoreboard players set $04 const 16
scoreboard players set $05 const 32
scoreboard players set $06 const 64
scoreboard players set $07 const 128
scoreboard players set $08 const 256
scoreboard players set $09 const 512
scoreboard players set $10 const 1024
scoreboard players set $11 const 2048
scoreboard players set $12 const 4096
scoreboard players set $13 const 8192
scoreboard players set $14 const 16384
scoreboard players set $15 const 32768
scoreboard players set $16 const 65536
scoreboard players set $17 const 131072
scoreboard players set $18 const 262144
scoreboard players set $19 const 524288
scoreboard players set $20 const 1048576
scoreboard players set $21 const 2097152
scoreboard players set $22 const 4194304
scoreboard players set $23 const 8388608
scoreboard players set $24 const 16777216
scoreboard players set $25 const 33554432
scoreboard players set $26 const 67108864
scoreboard players set $27 const 134217728
scoreboard players set $28 const 268435456
scoreboard players set $29 const 536870912
scoreboard players set $30 const 1073741824
scoreboard players set $31 const -2147483648
#> xor32.mcfunction
# 全ての一時変数を0に初期化
scoreboard players set * temp 0
# 0番目の一時変数に全ての入力の和を代入
# ビットに対するXORは繰り上がりを無視した足し算であると考えられるため
# 0番目の一時変数の0番目のビットは全入力の0番目のビットの32項XORの結果となる
scoreboard players operation $00 temp += * user
# 1番目のビットに対して同様の操作を行うために、全入力を2で割ることで右に1ビットシフトする
# これにより1番目のビットが0番目に移動する
scoreboard players operation * user /= $01 const
# 以降、31番目のビットまで同様の操作を行う
scoreboard players operation $01 temp += * user
scoreboard players operation * user /= $01 const
scoreboard players operation $02 temp += * user
scoreboard players operation * user /= $01 const
scoreboard players operation $03 temp += * user
scoreboard players operation * user /= $01 const
scoreboard players operation $04 temp += * user
scoreboard players operation * user /= $01 const
scoreboard players operation $05 temp += * user
scoreboard players operation * user /= $01 const
scoreboard players operation $06 temp += * user
scoreboard players operation * user /= $01 const
scoreboard players operation $07 temp += * user
scoreboard players operation * user /= $01 const
scoreboard players operation $08 temp += * user
scoreboard players operation * user /= $01 const
scoreboard players operation $09 temp += * user
scoreboard players operation * user /= $01 const
scoreboard players operation $10 temp += * user
scoreboard players operation * user /= $01 const
scoreboard players operation $11 temp += * user
scoreboard players operation * user /= $01 const
scoreboard players operation $12 temp += * user
scoreboard players operation * user /= $01 const
scoreboard players operation $13 temp += * user
scoreboard players operation * user /= $01 const
scoreboard players operation $14 temp += * user
scoreboard players operation * user /= $01 const
scoreboard players operation $15 temp += * user
scoreboard players operation * user /= $01 const
scoreboard players operation $16 temp += * user
scoreboard players operation * user /= $01 const
scoreboard players operation $17 temp += * user
scoreboard players operation * user /= $01 const
scoreboard players operation $18 temp += * user
scoreboard players operation * user /= $01 const
scoreboard players operation $19 temp += * user
scoreboard players operation * user /= $01 const
scoreboard players operation $20 temp += * user
scoreboard players operation * user /= $01 const
scoreboard players operation $21 temp += * user
scoreboard players operation * user /= $01 const
scoreboard players operation $22 temp += * user
scoreboard players operation * user /= $01 const
scoreboard players operation $23 temp += * user
scoreboard players operation * user /= $01 const
scoreboard players operation $24 temp += * user
scoreboard players operation * user /= $01 const
scoreboard players operation $25 temp += * user
scoreboard players operation * user /= $01 const
scoreboard players operation $26 temp += * user
scoreboard players operation * user /= $01 const
scoreboard players operation $27 temp += * user
scoreboard players operation * user /= $01 const
scoreboard players operation $28 temp += * user
scoreboard players operation * user /= $01 const
scoreboard players operation $29 temp += * user
scoreboard players operation * user /= $01 const
scoreboard players operation $30 temp += * user
scoreboard players operation * user /= $01 const
scoreboard players operation $31 temp += * user
# この時点でi番目の一時変数の0番目のビットは全入力のi番目のビットの32項XORの結果となっている
# ただし、i番目の一時変数の0番目以外のビットには繰り上がりによるゴミが残っている可能性があるため
# 全ての一時変数に自身を2で割った余りを代入することで、0番目以外のビットを0にする
scoreboard players operation * temp %= $01 const
# ここからはi番目の一時変数の0番目のビットをi番目に移動させる操作を行う
# 0番目の一時変数は元から0番目のビットが0番目にあるため、何もしなくて良い
# 1番目の一時変数の0番目のビットを、自身を足すことで左に1ビットシフトして1番目に移動させる
scoreboard players operation $01 temp += $01 temp
# 以降、i番目の一時変数の0番目のビットを、定数2^iを掛けることで左にiビットシフトしてi番目に移動させていく
scoreboard players operation $02 temp *= $02 const
scoreboard players operation $03 temp *= $03 const
scoreboard players operation $04 temp *= $04 const
scoreboard players operation $05 temp *= $05 const
scoreboard players operation $06 temp *= $06 const
scoreboard players operation $07 temp *= $07 const
scoreboard players operation $08 temp *= $08 const
scoreboard players operation $09 temp *= $09 const
scoreboard players operation $10 temp *= $10 const
scoreboard players operation $11 temp *= $11 const
scoreboard players operation $12 temp *= $12 const
scoreboard players operation $13 temp *= $13 const
scoreboard players operation $14 temp *= $14 const
scoreboard players operation $15 temp *= $15 const
scoreboard players operation $16 temp *= $16 const
scoreboard players operation $17 temp *= $17 const
scoreboard players operation $18 temp *= $18 const
scoreboard players operation $19 temp *= $19 const
scoreboard players operation $20 temp *= $20 const
scoreboard players operation $21 temp *= $21 const
scoreboard players operation $22 temp *= $22 const
scoreboard players operation $23 temp *= $23 const
scoreboard players operation $24 temp *= $24 const
scoreboard players operation $25 temp *= $25 const
scoreboard players operation $26 temp *= $26 const
scoreboard players operation $27 temp *= $27 const
scoreboard players operation $28 temp *= $28 const
scoreboard players operation $29 temp *= $29 const
scoreboard players operation $30 temp *= $30 const
scoreboard players operation $31 temp *= $31 const
# この時点でi番目の一時変数のi番目のビットには全入力のi番目のビットの32項XORの結果が、
# それ以外のビットには0が入っている状態になる
# あとは全ての一時変数を足し合わせることで、全入力のスコアに対する32項XORの結果を得ることができる
execute store result score $00 user run scoreboard players operation * temp += $00 const