Created
January 31, 2019 14:57
-
-
Save samsartor/66821f9b7e5812100e6c2693b8c184bf to your computer and use it in GitHub Desktop.
Connect-Four Bithacking
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#![allow(dead_code)] | |
const L_COL: u64 = 0xFF00000000000000; | |
const R_COL: u64 = 0x00000000000000FF; | |
const B_ROW: u64 = 0x0101010101010101; | |
const T_ROW: u64 = 0x8080808080808080; | |
const B_ROWS: u64 = !T_ROW; | |
const R_COLS: u64 = !L_COL; | |
/// Number of 4-in-a-rows for the given player | |
pub fn count(board: u64) -> u32 { | |
let mut ldag = board; | |
let mut rdag = board; | |
let mut hori = board; | |
let mut vert = board; | |
for _ in 0..3 { | |
vert &= (vert >> 1) & B_ROWS; | |
hori &= hori >> 8; | |
ldag &= (ldag >> 9) & B_ROWS; | |
rdag &= ((rdag & R_COLS) << 7) & B_ROWS; | |
} | |
ldag.count_ones() + rdag.count_ones() + hori.count_ones() + vert.count_ones() | |
} | |
#[test] | |
fn test_count_sides() { | |
let sides = L_COL | R_COL | B_ROW | T_ROW; | |
assert_eq!(count(sides), 5 * 4); | |
} | |
#[test] | |
fn test_count_x() { | |
let x = 0x0102040810204080 | 0x8040201008040201; | |
assert_eq!(count(x), 5 * 2); | |
} | |
/// The locations of left-diagonal, right-diagonal, horizontal, and | |
/// verical partial 4-in-a-rows for the given player | |
pub fn possibs(board: u64) -> [u64; 4] { | |
let mut ldag = board; | |
let mut rdag = board; | |
let mut hori = board; | |
let mut vert = board; | |
for _ in 1..4 { | |
vert |= (vert >> 1) & B_ROWS; | |
hori |= hori >> 8; | |
ldag |= (ldag >> 9) & B_ROWS; | |
rdag |= ((rdag & R_COLS) << 7) & B_ROWS; | |
} | |
[ldag, rdag, hori, vert] | |
} | |
#[test] | |
fn test_possibs() { | |
let x = 0x0000000800000000; | |
assert_eq!(possibs(x), [ | |
0x0000000804020100, | |
0x0102040800000000, | |
0x0000000808080800, | |
0x0000000F00000000, | |
]); | |
let x = 0x0000000004000000; | |
assert_eq!(possibs(x), [ | |
0x0000000004020100, | |
0x0000010204000000, | |
0x0000000004040404, | |
0x0000000007000000, | |
]); | |
} | |
fn print_board(a: u64) { | |
use board::Board; | |
println!("{}", Board { | |
one: a, | |
two: 0, | |
}.display()); | |
} | |
/// The number of unblocked in-progress 4-in-a-rows for each player, within the given area | |
pub fn opportunities(a: u64, b: u64, area: u64) -> (u32, u32) { | |
let posa = possibs(a); | |
let posb = possibs(b); | |
let asta = posb; | |
let astb = posa; | |
let mut opsa = 0; | |
let mut opsb = 0; | |
for i in 0..4 { | |
let mut posa = posa[i]; | |
let mut posb = posb[i]; | |
posa &= !asta[i]; | |
posa &= area; | |
opsa += posa.count_ones(); | |
posb &= !astb[i]; | |
posb &= area; | |
opsb += posb.count_ones(); | |
} | |
(opsa, opsb) | |
} | |
#[test] | |
fn test_opportunities() { | |
assert_eq!( | |
opportunities(0x0000000810000000, 0x0000001008000000, !0), | |
(8 + 5 + 2 + 2, 5 + 8 + 2 + 2) | |
); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment