Skip to content

Instantly share code, notes, and snippets.

@samsartor
Created January 31, 2019 14:57
Show Gist options
  • Save samsartor/66821f9b7e5812100e6c2693b8c184bf to your computer and use it in GitHub Desktop.
Save samsartor/66821f9b7e5812100e6c2693b8c184bf to your computer and use it in GitHub Desktop.
Connect-Four Bithacking
#![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