возраст 6 бит, количество курсов 3 бита 
Значит, биты будут:
0    пол
1    семейное положение (женат / не женат)
2–7  возраст (6 бит запишут значения 0..63 точно хватит?)
8–10 количество курсов
11   присутствие
Понадобятся функции кодировки данных в число, и декодировки:
const encode = (sex, family, age, classes, presence) => 
  (1  & sex)      << 0 |
  (1  & family)   << 1 |
  (63 & age)      << 2 |
  (7  & classes)  << 8 |
  (1  & presence) << 11
;
const decode = n => ({
  sex      : n >> 0  & 1,
  family   : n >> 1  & 1,
  age      : n >> 2  & 63,
  classes  : n >> 8  & 7,
  presence : n >> 11 & 1,
});
 неженатых женщин, с возрастом от 25 до 30 включительно, без курсов и с присутствием.
Тут сложность только с фильтром по возрасту. Если бы без диапазона возрастов, а с фиксированным возрастом,  например, 25, то так:
const mask = encode(1, 0, 25, 0, 1);
data.filter(n => n === mask); // нужно полное равенство маски и числа, как я понял?
Если в числе, в его других битах выше наших 12, хранится ещё какая-то информация, то сравнение в фильтре чуть иначе. Сравнивать только значимые «наши» биты:
data.filter(n => (n & 0xFFF) === mask);
С диапазоном возрастов придётся перечислить каждый из возрастов:
const masks = [];
for(let i=25; i<=30; i++) masks.push( encode(1, 0, i, 0, 1));
data.filter(n => masks.includes(n & 0xFFF));