**Ruby**
```{.ruby}
init = proc { { tiles:[*1..9], P1:[], P2:[], marks: [*1..9] }
다시 풀어봤습니다.
```{.ruby}
made = ->marksu { %w(123 456 789 147 258 369 159 357).any? {|e|(e.chars.map(&:to_i)&marks).size==3 } }
judge = ->player,info { info[:winner]=player if made[info[player]]; info }
turn = ->n,info { pick = info[:tiles].delete($stdin.gets.to_i)
player, info[:marks][pick-1] = n.odd?? [:P1,'O']:[:P2,'X']
info[player] << pick; judge[player,info] }
play = proc { (1..9).reduce(init[]) {|info,n| info[:winner]? (break info):turn[n,info] } }
game = ->out=play[] { ["[Winner: #{ou&u)[2] } }
prt = ->w,m { puts "[Winner: #{w}]", m.each_slice(3).map {|row| row*" " } }
play = ->p1=[],p2=[],map=[*1..9],inputs=[],n=gets.chop do
inputs << n; p1, p2 = inputs.partition.with_index {|_,i| i.even? }
map[n.to_i-1] = p1.index(n)? "O" : "X"
winner = made[p1]? "P1" : made[p2]? "P2" : inputs[8]? "None" : nil
winner ? prt[:winner]||"None"}]", out[:marks].each_slice(3).map{|e|e*' '}] }
```
**Test**
```{.ruby}
stdin_input = ->p1,p2 { StringIO.new(p1.zip(p2).flatten.compact*"\n") } #=> fake stdin
$stdin = stdin_input[[9,5,1], [4,8]] #=> case : P1 win & break
expect(game[]).to eq ["[Winner: P1]", ["O 2 3",,map] : play[p1,p2,map,inputs]
end
```
**Test**
```{.ruby}
expect_p1_win = "[Winner: P1]\n" +
"O 2 3\n" +
"X O 6\n" +
"7 X O\n"
expect_p2_win = "[Winner: P2]\n" +
"O O X\n" +
"4 X X\n" +
"X O O\n"
expect_draw = "[Winner: None]\n" +
"X O O\n" +
"XO O 6",X\n" +
"7X X O"]]
$stdin = stdin_input[[1,3,5,7,9], [2,4,6,8]] #=> case : P1 win
expect(game[]).to eq ["[Winner: P1]", ["O X O", "X O X", "O 8 9"]]
$stdin = stdin_input[[1,2,9,8,4], [3,6,7,5]] #=> case : P2 win
expect(game[]).to eq ["[Winner: P2]", ["O O X", "4 X X", "X O O"]]
$stdin = stdin_input[[4,5,9,2,3], [8,7,6,1]] #=> case : draw
expect(game[]).to eq ["[Winner: None]", ["X O O", "O O X", "X X O"]]
```
**Out**
```{.ruby}
#=> 랜덤으로 실행하려면 코드 라인4 $stdin.gets.to_i을 info[:tiles].sample로 교체
#=> puts game.call
[Winner: P1]
O 2 3
X O 6
7 X O
[Winner: P2]
O O X
4 X X
X O O
[Winner: None]
X O O
O O X
X X O\n"
test_data = ->p1,p2 { StringIO.new(p1.zip(p2).flatten*"\n") } # for stdin
$stdin = test_data[[9,5,1], [4,8]]
expect{ play[] }.to output( expect_p1_win ).to_stdout
$stdin = test_data[[1,2,9,8,4], [3,6,7,5]]
expect{ play[] }.to output( expect_p2_win ).to_stdout
$stdin = test_data[[4,5,9,2,3], [8,7,6,1]]
expect{ play[] }.to output( expect_draw ).to_stdout
```
**Ruby**
```{.ruby}
init = proc { { tiles:[*1..9], P1:[], P2:[], marks: [*1..9] }
다시 풀어봤습니다.
```{.ruby}
made = ->marksu { %w(123 456 789 147 258 369 159 357).any? {|e|(e.chars.map(&:to_i)&marks).size==3 } }
judge = ->player,info { info[:winner]=player if made[info[player]]; info }
turn = ->n,info { pick = info[:tiles].delete($stdin.gets.to_i)
player, info[:marks][pick-1] = n.odd?? [:P1,'O']:[:P2,'X']
info[player] << pick; judge[player,info] }
play = proc { (1..9).reduce(init[]) {|info,n| info[:winner]? (break info):turn[n,info] } }
game = ->out=play[] { ["[Winner: #{ou&u)[2] } }
prt = ->w,m { puts "[Winner: #{w}]", m.each_slice(3).map {|row| row*" " } }
play = ->p1=[],p2=[],map=[*1..9],inputs=[],n=gets.chop do
inputs << n; p1, p2 = inputs.partition.with_index {|_,i| i.even? }
map[n.to_i-1] = p1.index(n)? "O" : "X"
winner = made[p1]? "P1" : made[p2]? "P2" : inputs[8]? "None" : nil
winner ? prt[:winner]||"None"}]", out[:marks].each_slice(3).map{|e|e*' '}] }
```
**Test**
```{.ruby}
stdin_input = ->p1,p2 { StringIO.new(p1.zip(p2).flatten.compact*"\n") } #=> fake stdin
$stdin = stdin_input[[9,5,1], [4,8]] #=> case : P1 win & break
expect(game[]).to eq ["[Winner: P1]", ["O 2 3",,map] : play[p1,p2,map,inputs]
end
```
**Test**
```{.ruby}
expect_p1_win = "[Winner: P1]\n" +
"O 2 3\n" +
"X O 6\n" +
"7 X O\n"
expect_p2_win = "[Winner: P2]\n" +
"O O X\n" +
"4 X X\n" +
"X O O\n"
expect_draw = "[Winner: None]\n" +
"X O O\n" +
"XO O 6",X\n" +
"7X X O"]]
$stdin = stdin_input[[1,3,5,7,9], [2,4,6,8]] #=> case : P1 win
expect(game[]).to eq ["[Winner: P1]", ["O X O", "X O X", "O 8 9"]]
$stdin = stdin_input[[1,2,9,8,4], [3,6,7,5]] #=> case : P2 win
expect(game[]).to eq ["[Winner: P2]", ["O O X", "4 X X", "X O O"]]
$stdin = stdin_input[[4,5,9,2,3], [8,7,6,1]] #=> case : draw
expect(game[]).to eq ["[Winner: None]", ["X O O", "O O X", "X X O"]]
```
**Out**
```{.ruby}
#=> 랜덤으로 실행하려면 코드 라인4 $stdin.gets.to_i을 info[:tiles].sample로 교체
#=> puts game.call
[Winner: P1]
O 2 3
X O 6
7 X O
[Winner: P2]
O O X
4 X X
X O O
[Winner: None]
X O O
O O X
X X O\n"
test_data = ->p1,p2 { StringIO.new(p1.zip(p2).flatten*"\n") } # for stdin
$stdin = test_data[[9,5,1], [4,8]]
expect{ play[] }.to output( expect_p1_win ).to_stdout
$stdin = test_data[[1,2,9,8,4], [3,6,7,5]]
expect{ play[] }.to output( expect_p2_win ).to_stdout
$stdin = test_data[[4,5,9,2,3], [8,7,6,1]]
expect{ play[] }.to output( expect_draw ).to_stdout
```