UPDATE: 2022-12-03 11:09:22

モジュロ演算を使った基礎的な加工方法のメモ

人間とPCがじゃんけんをして、人間の判定結果を計算したい。 じゃんけんの9通りの場合分けを記述するのは面倒なので、モジュロ演算で判定する方法。 ここでは、グー(0)、チョキ(1)、パー(2)と対応しているとする。

人間(左)がPC(右)に勝つ場合は、下記の組み合わせが考えられる。

上から数値の差を考えると、1、1、2となって、最後の組み合わせが、対応している数値の影響で循環している。このような場合に、PCの数値に3を足して、人間の数値を引いて、3で割ったあまりを見ると、人間が勝利する場合の組み合わせが1として計算される。

library(tidyverse)

p <- expand.grid(x = c(0,1,2), y = c(0,1,2))
ref <- expand.grid(me = c('rock','scissors','paper'), 
                   pc = c('rock','scissors','paper'))
df <- tibble::tibble(p, ref)

df %>% 
  mutate(
    ref = paste(me, pc, sep = '-'),
    res =
           case_when(
             (y + 3 - x) %% 3 == 1 ~ 'win',
             x == y ~ 'draw',
             TRUE ~ 'lose'
           )
         ) %>% 
  select(x, y, res, ref)
## # A tibble: 9 × 4
##       x     y res   ref              
##   <dbl> <dbl> <chr> <chr>            
## 1     0     0 draw  rock-rock        
## 2     1     0 lose  scissors-rock    
## 3     2     0 win   paper-rock       
## 4     0     1 win   rock-scissors    
## 5     1     1 draw  scissors-scissors
## 6     2     1 lose  paper-scissors   
## 7     0     2 lose  rock-paper       
## 8     1     2 win   scissors-paper   
## 9     2     2 draw  paper-paper

途中の過程はこんな感じ。

df %>% 
  mutate(tmp1 = y + 3,
         tmp2 = tmp1 - x,
         tmp3 = tmp2 %% 3,
         TMP4 = tmp3 == 1,
         res =
           case_when(
             (y + 3 - x) %% 3 == 1 ~ 'win',
             x == y ~ 'draw',
             TRUE ~ 'lose'
           )
         )
## # A tibble: 9 × 9
##       x     y me       pc        tmp1  tmp2  tmp3 TMP4  res  
##   <dbl> <dbl> <fct>    <fct>    <dbl> <dbl> <dbl> <lgl> <chr>
## 1     0     0 rock     rock         3     3     0 FALSE draw 
## 2     1     0 scissors rock         3     2     2 FALSE lose 
## 3     2     0 paper    rock         3     1     1 TRUE  win  
## 4     0     1 rock     scissors     4     4     1 TRUE  win  
## 5     1     1 scissors scissors     4     3     0 FALSE draw 
## 6     2     1 paper    scissors     4     2     2 FALSE lose 
## 7     0     2 rock     paper        5     5     2 FALSE lose 
## 8     1     2 scissors paper        5     4     1 TRUE  win  
## 9     2     2 paper    paper        5     3     0 FALSE draw