Need to check does "X" or "O" has more occurrences. The values of the array possibilities should be compared against the row value of the moves array. As we find the value of the occurrence reaches 3, we need to stop the iteration.
const possibilities = [
[0, 1, 2],
[3, 4, 5],
...
];
const moves = [{
"row": 0,
"type": "X",
},
{
"row": 1,
"type": "O",
},
{
"row": 2,
"type": "O",
},
{
"row": 3,
"type": "X",
},
{
"row": 4,
"type": "O",
},
{
"row": 5,
"type": "X",
}];
Code as follows:
let count = 0;
possibilities.forEach((possibility) => {
let type = null;
for (let index = 0; index < possibility.length; index++) {
console.log(possibility[index], "index")
for (let j = 0; j < moves; j++) {
if (moves[j].row === possibility[index]) {
console.log(moves[j], "j")
if (type === null) {
type = moves[j].type;
} else if (type === moves[j].type) {
++count;
} else {
type = null;
count = 0;
}
}
}
}
})
This code may help you.
If this did not work. Please write a comment. So I can edit my answer.
This code is not fully optimized!! But I can do that if the code works for you.
let counts = {}
for(const possibility of possibilities) {
for(const move of moves) {
if(possibility.includes(move.row)) {
if(!(move.type in counts)) counts[move.type] = 0
counts[move.type]++
}
}
}
console.log(counts)
let heightsValue = -1
let heightsType = '-'
for(const type in counts) {
if(counts[type] > heightsValue) {
heightsType = type
heightsValue = counts[type]
}
}
console.log(heightsType)
If I understand correctly, you want to iterate over possibilities to see if at least 3 of their moves are type 'X'.
Predispositions...
const possibilities = [
[0, 1, 2], // ['X', 'O', 'O'] -> false
[3, 4, 5], // ['X', 'O', 'X'] -> false
[0, 3, 5], // ['X', 'X', 'X'] -> true
];
const moves = [{
"row": 0,
"type": "X",
}, {
"row": 1,
"type": "O",
}, {
"row": 2,
"type": "O",
}, {
"row": 3,
"type": "X",
}, {
"row": 4,
"type": "O",
}, {
"row": 5,
"type": "X",
}];
match moves
let result = possibilities.map((possibility) =>
possibility.map((row) => moves.find(r => r.row === row).type)
);
// [ [ 'X', 'O', 'O' ], [ 'X', 'O', 'X' ], [ 'X', 'X', 'X' ] ]
find out how many Xs
result = result.map((posibility) =>
posibility.filter(moveType => moveType === 'X').length
);
// [1, 2, 3]
compare there at at least 3 Xs
result = result.map((xMoves) => xMoves >= 3);
// [false, false, true]
All in one
let result = possibilities.map((possibility) =>
possibility.map((row) => moves.find(r => r.row === row).type)
.filter(moveType => moveType === 'X')
.length >= 3
);
// [false, false, true]
The 3rd values in possibilities (possibilities[2] is the winner)
Related
Im making a poker game and i need to find a sequence of 5 cards into a array with 7 cards. As some cards are figures like a Queen, King or Ace, i mapped the values into a separate Array that i use to compare. On the case in question it found the right answer. But if i try to make a straight with A, 2, 3, 4, 5 as the poker rules are, i can't.
const CARD_VALUE_MAP = {
"2": 2,
"3": 3,
"4": 4,
"5": 5,
"6": 6,
"7": 7,
"8": 8,
"9": 9,
"10": 10,
J: 11,
Q: 12,
K: 13,
A: 14,
}
And then i use this mapping to go through the cards with this code
for(let i=0; i<6; i++){
if(CARD_VALUE_MAP[finalhand[i].value] === CARD_VALUE_MAP[finalhand[i+1].value]-1){
count++;
if(count === 5){
console.log("straight");
return 500;
}
}
}
finalhand looks like this:
finalhand = [{suit: '♥', value: '3'},
{suit: '♥', value: 'J'},
{suit: '♥', value: 'Q'},
{suit: '♥', value: 'K'},
{suit: '♥', value: 'A'}
{suit: '♥', value: '10'},
{suit: '♦', value: '4'}]
There's a lot of different way to do this, but based on what you already have, here is the simplest changes: First, set A: 14 and then sort the finalhand (which it appears you are already doing).
Then change the code like so:
count = 0;
if (CARD_VALUE_MAP[finalhand[0].value] = "2" && CARD_VALUE_MAP[finalhand[6].value] = A) {
count++;
}
for(let i=0; i<6; i++){
if(CARD_VALUE_MAP[finalhand[i].value] === CARD_VALUE_MAP[finalhand[i+1].value]-1){
count++;
if(count === 4){
console.log("straight");
return 500;
}
else{
count = 0;
}
}
}
This does an initial check at the low-end for an Ace and if it exists, increments the count before the loop starts.
I also added the else { count = 0; } branch because just having five adjacent cards in hand is not a straight if there are any gaps between them.
Here is a Proof-Of-Concept (POC) card value solution to get you started. It works, but it's not the best code.
const CARD_VALUE_MAP = {
"2": 2,
"3": 3,
"4": 4,
"5": 5,
"6": 6,
"7": 7,
"8": 8,
"9": 9,
"10": 10,
J: 11,
Q: 12,
K: 13,
}
const aceValues = function() {
return Object.assign(
Object.assign({}, CARD_VALUE_MAP),
{
AL: CARD_VALUE_MAP[2] - 1, // Ace Low
AH: CARD_VALUE_MAP["K"] + 1, // Ace High
},
);
}();
function rankStraight(hand) {
if (hand.length < 5) {
return [];
}
let cards = [];
for (let card of hand) {
if (card === "A") {
cards.push("AL");
card = "AH";
}
cards.push(card);
}
cards.sort(function(a, b) {
return aceValues[b] - aceValues[a];
});
let straight = [cards[0]];
for (let [i, card] of cards.entries()) {
let last = straight[straight.length - 1];
if (card === last) {
continue;
}
if ((aceValues[last] - aceValues[card]) !== 1) {
straight = [card];
continue
}
if (straight.push(card) >= 5) {
break;
}
if ((straight.length + (cards.length - (i + 1))) < 5) {
break;
}
}
if (straight.length != 5) {
return [];
}
if (straight[0] === "AH") {
straight[0] = "A";
}
if (straight[straight.length - 1] === "AL") {
straight[straight.length - 1] = "A";
}
return straight;
}
let hand = [];
hand = ["A", "K", "Q","J",10];
console.log(rankStraight(hand));
hand = [5, 4, 3, 2, "A"];
console.log(rankStraight(hand));
hand = ["A", 5, 4, 3, 2];
console.log(rankStraight(hand));
hand = ["A", 5, 7, 4, 3, "K", 2, "A"];
console.log(rankStraight(hand));
$ node poker.js
[ 'A', 'K', 'Q', 'J', 10 ]
[ 5, 4, 3, 2, 'A' ]
[ 5, 4, 3, 2, 'A' ]
[ 5, 4, 3, 2, 'A' ]
$
Input:
[7,"a","b",5, 0.1, "c", 0.5, 9, 1, "e", "m", 0.3, 8.5, 74, 89,"f","r",0.5 ,"x", "y", 4, 7]
Output:
["a", "b", "c", "e", "m", "f", "r", "x", "y", 0.1, 0.5, 0.3, 8.5, 0.5, 7, 5, 9, 1, 74, 89, 4, 7]
function sorter(arr) {
var arr1, arr2, arr3;
arr1 = [];
arr2 = [];
arr3 = [];
for (var i = 0; i < arr.length; i++) {
if (typeof arr[i] === "string") {
arr1.push(arr[i]);
} else if (typeof arr[i] === 'number' && !isNaN(arr[i])) {
if (Number.isInteger(arr[i])) {
arr3.push(arr[i]);
} else {
arr2.push(arr[i]);
}
}
}
return [...arr1, ...arr2, ...arr3];
}
An approach based on a single sort comparator callback ...
function orderByItemTypeOnly(a, b) {
const precedences = {
'string': 1,
'float': 2,
'int': 3,
};
const getType = val =>
((typeof val === 'number') && Number.isFinite(val))
? Number.isInteger(val) && 'int' || 'float'
: (typeof val);
const aType = getType(a);
const bType = getType(b);
return (
(precedences[aType] || 4) - (precedences[bType] || 4)
);
}
console.log([
7, "a", "b", 5, 0.1, "c", 0.5, 9, 1, "e", "m",
0.3, 8.5, 74, 89, "f", "r", 0.5, "x", "y", 4, 7
].sort(orderByItemTypeOnly));
.as-console-wrapper { min-height: 100%!important; top: 0; }
There is also the possibility of solving this task not by sort but based on a reduce approach ...
function collectAndShiftItemByType(list, item, idx, arr) {
if (list.length === 0) {
list.push([], [], [], []);
}
const typeListIndex = ((typeof item === 'number') && Number.isFinite(item))
? (Number.isInteger(item) && 2 || 1)
: (typeof item === 'string') ? 0 : 3;
// push into sub lists ... [0]string, [1]float, [2]integer, [3]unknown.
list[typeListIndex].push(item);
if (idx >= arr.length - 1) {
list = list[0]
.concat(list[1])
.concat(list[2])
.concat(list[3]);
}
return list;
}
console.log([
7, "a", "b", 5, 0.1, "c", 0.5, 9, 1, "e", "m",
0.3, 8.5, 74, 89, "f", "r", 0.5, "x", "y", 4, 7
].reduce(collectAndShiftItemByType, []));
.as-console-wrapper { min-height: 100%!important; top: 0; }
Use the sort() method with a comparison function that compares types rather than values.
function sorter(arr) {
function type_index(val) {
const types = ["string", "float", "integer"];
let type;
if (typeof val == "string") {
type = "string";
} else if (typeof val == "number" && Number.isInteger(val)) {
type = "integer";
} else if (typeof val == "number" && !isNaN(val)) {
type = "float";
}
return types.indexOf(type);
}
return arr.sort((a, b) => type_index(a) - type_index(b));
}
console.log(sorter([7,"a","b",5, 0.1, "c", 0.5, 9, 1, "e", "m", 0.3, 8.5, 74, 89,"f","r",0.5 ,"x", "y", 4, 7]));
How can I count all objects in an array that match a condition: is_read == true?
This is how my array looks like:
[
{
"id": 1,
"is_read": true,
},
{
"id": 2,
"is_read": true,
},
{
"id": 3,
"is_read": false,
},
{
"id": 4,
"is_read": true,
},
]
Just use filter method by passing a callback function and use length property applied for the result of filtering.
let data = [ { "id": 1, "is_read": true, }, { "id": 2, "is_read": true, }, { "id": 3, "is_read": false, }, { "id": 4, "is_read": true, }, ],
length = data.filter(function(item){
return item.is_read;
}).length;
console.log(length);
You can also use a lambda expression.
let data = [ { "id": 1, "is_read": true, }, { "id": 2, "is_read": true, }, { "id": 3, "is_read": false, }, { "id": 4, "is_read": true, }, ],
length = data.filter(d => d.is_read).length;
console.log(length);
Filter
const count = (arr, condition) => arr.filter(condition).length;
const arr = [ { is_read: true }, { is_read: false} ]
console.log(count(arr, (o) => o.is_read));
Array#reduce
const count = (arr, condition) => arr.reduce((acc, c) => condition(c) ? ++acc : acc, 0);
const arr = [ { is_read: true }, { is_read: false } ]
console.log(count(arr, (o) => o.is_read));
Recursive
const count = ([first, ...rest], condition, acc = 0) =>
(condition(first) && ++acc,
rest.length ? count(rest, condition, acc) : acc);
const arr = [ { is_read: true }, { is_read: false } ]
console.log(count(arr, (o) => o.is_read));
Using Array.reduce
const r = (sum, obj) => sum + (obj.is_read == true ? 1 : 0);
const count = arr.reduce(r, 0);
console.log(count);
Use array filter method.
//ES6
const arr = [
{
"id": 1,
"is_read": true,
},
{
"id": 2,
"is_read": true,
},
{
"id": 3,
"is_read": false,
},
{
"id": 4,
"is_read": true,
},
]
const size = arr.filter(obj => obj.is_read).length
You can use Array#reduce, starting from 0 and adding the result of the predicate for each element. This works because true can be coerced to 1 and false to 0.
const getMatchCount = (arr, predicate)=>arr.reduce((a,b)=>a + predicate(b), 0);
console.log(getMatchCount([{ "id": 1, "is_read": true, }, { "id": 2, "is_read": true, }, { "id": 3, "is_read": false, }, { "id": 4, "is_read": true, }],
x => x.is_read));
// get number of objects in the array whose "is_read" property is true
console.log(getMatchCount([1, 2, 3, 6, 13, -2, 9, 9],
x => x % 2 === 1));
// get number of odd numbers in array
Similar to other answers, but turned into a TypeScript function:
const arr = [
{
"id": 1,
"is_read": true,
},
{
"id": 2,
"is_read": true,
},
{
"id": 3,
"is_read": false,
},
{
"id": 4,
"is_read": true,
},
]
function arrayCount<T>(arr: T[], predicate: (elem: T, idx: number) => boolean) {
return arr.reduce((prev, curr, idx) => prev + (predicate(curr, idx) ? 1 : 0), 0)
}
console.log(arrayCount(arr, x => x.is_read)) // 3
Following is an object array that has a value v, its input i and output o.
var data = [
{
v: 1,
i: [],
o: [1, 2, 3]
},
{
v: 2,
i: [2],
o: [4, 5, 6]
]
},
{
v: 3,
i: [1, 4],
o: [7, 8]
},
{
v: 4,
i: [],
o: [3]
}
]
The final JSON structure is created by checking the input and outputs of each v, i.e. the parent child relations...
Final JSON structure..
[
{
v: 1,
children: [
{
v: 2
},
{
v: 3
}
]
},
{
v: 4
}
]
I tried by the following code, but it's not transforming the object array properly...
function checkForOutputs(outputs, groupedValueChainEntityLists) {
for (var i = 0; i < outputs.length; i++) {
for (var j = 0; j < groupedValueChainEntityLists[j].inputs.length; j++) {
var val_Chain = groupedValueChainEntityLists[j].inputs.map((item) => {
if (outputs[i].o === item.o) {
return groupedValueChainEntityLists[j];
}
});
return val_Chain;
}
}
}
function constructValueChainRelations(data) {
var valueChainArray = new Array();
var result = data.map((item) => {
if (item.i.length === 0) {
valueChainArray.push(item);
return checkForOutputs(item.o, data);
}
});
console.log(result);
}
I think that you are making this too difficult. Simply map the values.
var data = [{
v: 1,
i: [],
o: [1, 2, 3]
}, {
v: 2,
i: [2],
o: [4, 5, 6]
}, {
v: 3,
i: [1, 4],
o: [7, 8]
}, {
v: 4,
i: [],
o: [3]
}];
function transform(verticies, idProp, childProp) {
return verticies.map(function(vertex) {
return {
v: vertex[idProp],
children: vertex[childProp].filter(function(childVertex) {
return childVertex !== vertex[idProp];
}).map(function(childVertex) {
return {
v: childVertex
};
})
}
});
}
var transformed = transform(data, 'v', 'o');
document.body.innerHTML = '<pre>' + JSON.stringify(transformed, null, 4) + '</pre>';
Result
[{
"v": 1,
"children": [{
"v": 2
}, {
"v": 3
}]
}, {
"v": 2,
"children": [{
"v": 4
}, {
"v": 5
}, {
"v": 6
}]
}, {
"v": 3,
"children": [{
"v": 7
}, {
"v": 8
}]
}, {
"v": 4,
"children": [{
"v": 3
}]
}]
You could use some loops and a look up mechanism with this.
var data = [{ v: 1, i: [], o: [1, 2, 3] }, { v: 2, i: [2], o: [4, 5, 6] }, { v: 3, i: [1, 4], o: [7, 8] }, { v: 4, i: [], o: [3] }],
result = [];
data.forEach(function (a) {
if (!this[a.v]) {
this[a.v] = { v: a.v, children: [] };
result.push(this[a.v]);
}
a.o.forEach(function (b) {
var k = a.v + '|' + b;
if (a.v !== b && !this[k]) {
this[k] = { v: b };
this[a.v].children.push(this[k]);
}
}, this);
}, {});
document.write('<pre>' + JSON.stringify(result, 0, 4) + '</pre>');
Here's another way that is working..
Sample Code
function populateChildrenRecursively(outputTypeId, valueChainEntities, parentValueChainEntity) {
for (var i = 0; i < valueChainEntities.length; i++) {
if (valueChainEntities[i].valueChainEntity.valueChainEntityId != parentValueChainEntity.valueChainEntity.valueChainEntityId && hasInput(outputTypeId, valueChainEntities[i].inputs)) {
parentValueChainEntity.valueChainEntity.items.push(valueChainEntities[i]);
if (valueChainEntities[i].outputs.length > 0) {
valueChainEntities[i].valueChainEntity.items = [];
for (var j = 0; j < valueChainEntities[i].outputs.length; j++) {
populateChildrenRecursively(valueChainEntities[i].outputs[j].outputTypeId, valueChainEntities, valueChainEntities[i]);
}
}
}
}
}
JSON Conversion
I do not know how to implement the following query in CouchDB:
chr.letter between two objects/dicts in chr are not the same and no X, and
the document must be in range 200000 - 2000000, but I guess it has to be done with startkey and endkey in the view.
The example output could look like this:
{"_id":"7", "sub_name":"B01", "name":"A", "pos":828288, "s_type":1}
{"_id":"8", "sub_name":"B01", "name":"A", "pos":171878, "s_type":3} will not meet range condition in the view
{"_id":"9", "sub_name":"B01", "name":"A", "pos":871963, "s_type":3}
Document 10 is not valid, because chr.no = 6 has chr.letter = X.
And document 14 is not valid, because chr.no = 5 and chr.no = 6 both have the same chr.letter = G
The database contains following documents:
{
"_id":"10",
"_rev":"3-5288068d2c4ef3e6a9d3f8ff4e3377dd",
"sub_name":"B01",
"name":"A",
"pos":1932523,
"s_type":1,
"chr":[
{
"letter":"T",
"no":4
},
{
"letter":"A",
"no":5
},
{
"letter":"X",
"no":6
}
],
"type":"Test"
}{
"_id":"14",
"_rev":"3-21300d06c31224416b8ff71b71b304d8",
"sub_name":"B01",
"name":"A",
"pos":667214,
"s_type":1,
"chr":[
{
"letter":"T",
"no":4
},
{
"letter":"G",
"no":5
},
{
"letter":"G",
"no":6
}
],
"type":"Test"
}{
"_id":"7",
"_rev":"2-1516ba547bdd21724158bc854f39f66b",
"sub_name":"B01",
"name":"A",
"pos":828288,
"s_type":1,
"chr":[
{
"letter":"C",
"no":5
},
{
"letter":"T",
"no":6
}
],
"type":"Test"
}{
"_id":"8",
"_rev":"2-750078ccc9e74616f33a2537e41b8414",
"sub_name":"B01",
"name":"A",
"pos":171878,
"s_type":3,
"chr":[
{
"letter":"C",
"no":5
},
{
"letter":"T",
"no":6
}
],
"type":"Test"
}{
"_id":"9",
"_rev":"2-3d68352a2d98c56fd322ae674fb7c38a",
"sub_name":"B01",
"name":"A",
"pos":871963,
"s_type":3,
"chr":[
{
"letter":"A",
"no":5
},
{
"letter":"G",
"no":6
}
],
"type":"Test"
}
The above database has been created with the below script:
import couchdb
# $ sudo systemctl start couchdb
# http://localhost:5984/_utils/
server = couchdb.Server()
db = server.create("test")
# except couchdb.http.ResourceConflict:
#db = server["test"]
r = [["Test", "A", "B01", 828288, 1, 7, 'C', 5],
["Test", "A", "B01", 828288, 1, 7, 'T', 6],
["Test", "A", "B01", 171878, 3, 8, 'C', 5],
["Test", "A", "B01", 171878, 3, 8, 'T', 6],
["Test", "A", "B01", 871963, 3, 9, 'A', 5],
["Test", "A", "B01", 871963, 3, 9, 'G', 6],
["Test", "A", "B01", 1932523, 1, 10, 'T', 4],
["Test", "A", "B01", 1932523, 1, 10, 'A', 5],
["Test", "A", "B01", 1932523, 1, 10, 'X', 6],
["Test", "A", "B01", 667214, 1, 14, 'T', 4],
["Test", "A", "B01", 667214, 1, 14, 'G', 5],
["Test", "A", "B01", 667214, 1, 14, 'G', 6]]
# _id = None
for i in r:
_id = str(i[5])
doc = db.get(_id)
if doc is None:
doc = {
'type': i[0],
'name': i[1],
'sub_name': i[2],
'pos': i[3],
's_type': i[4],
'_id': _id,
'chr':[]
}
doc['chr'].append({
"letter":i[6],
"no":i[7]
})
else:
doc['chr'].append({
"letter":i[6],
"no":i[7]
})
db.save(doc)
How is it possible to implement the above query or does the documents structure has to be change to make the query possible?
Solution thanks to https://stackoverflow.com/a/26436244/977828
function(doc) {
var judge = function (doc) {
var unexpect = "X";
var letter1 = unexpect, letter2 = unexpect;
for (var i in doc.chr) {
var chr = doc.chr[i];
if (chr.no == 5) {
letter1 = chr.letter;
} else if (chr.no == 6) {
letter2 = chr.letter;
}
}
if (letter1 != letter2 && letter1 != unexpect && letter2 != unexpect) {
return true;
}
return false;
};
if (judge(doc)) {
emit(doc);
}
}