Last active
March 4, 2019 10:35
-
-
Save okunishinishi/9bd81161665388ed2e62fb9914e902f6 to your computer and use it in GitHub Desktop.
婚活において積極的行動が必要な理由をGSアルゴリズムで検証してみる ref: https://qiita.com/okunishinishi@github/items/b26a1293dd510a302f37
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
const shuffle = require('shuffle-array') | |
function defineMembers (memberCount = 10) { | |
const men = shuffle(new Array(memberCount).fill(null).map((_, i) => ({ | |
name: `man#${i}`, | |
rejectedBy: [], // 自分を拒否した異性の名前 | |
likes: [], // 好みの異性 | |
}))) | |
const women = shuffle(new Array(memberCount).fill(null).map((_, i) => ({ | |
name: `woman#${i}`, | |
proposedBy: [], // プロポーズしてきた異性の名前 | |
keeps: null, // キープしている異性。最後まで残ったら結ばれる | |
likes: [], // 好みの異性 | |
}))) | |
for (const m of men) { | |
// 好みの順に異性を登録 | |
m.likes = shuffle(women).map(({name}) => name) | |
} | |
for (const w of women) { | |
// 好みの順に異性を登録 | |
w.likes = shuffle(men).map(({name}) => name) | |
} | |
return {men, women} | |
} |
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
const memberCount = 10 | |
const {men, women} = defineMembers(memberCount) | |
// 配列だけだと不便なのでnameをキーにした辞書を用意 | |
const menByName = Object.assign({}, ...men.map((man) => ({ | |
[man.name] : man | |
}))) | |
const womenByName = Object.assign({}, ...women.map((woman) => ({ | |
[woman.name] : woman | |
}))) | |
// 複数回ラウンドを行う | |
const rounds = 4 | |
for (let round = 0; round < rounds; round++) { | |
// Men側 | |
for (const m of men) { | |
const isKept = women.some(({keeps}) => keeps === m.name) | |
if (!isKept) { | |
// キープされていない孤独なmenはまだ自分をrejectしてない最良の相手を探す | |
const best = m.likes.find((name) => !m.rejectedBy.includes(name)) | |
if (best) { | |
// 最良のWomanにプロポーズする | |
womenByName[best].proposedBy.push(m.name) | |
} | |
} | |
} | |
// Women側 | |
for (const w of women) { | |
// プロポーズして来た相手を、暫定一位とその他に切り分ける | |
const [best, ...notGoodEnough] = w.proposedBy.sort((a, b) => | |
w.likes.indexOf(a) - w.likes.indexOf(b) | |
) | |
w.keeps = best || null // 一番良いのをキープ | |
for (const n of notGoodEnough) { | |
menByName[n].rejectedBy.push(w.name) // それ以外は拒否 | |
} | |
} | |
} | |
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
// ゲームが終わった時点でキープしている場合に成約とする | |
const couples = women | |
.map(({name, keeps}) => keeps ? [name, keeps] : null) | |
.filter(Boolean) | |
.map(([wName, mName]) => [ | |
womenByName[wName], | |
menByName[mName] | |
]) | |
const successCount = couples.length | |
const failureCount = memberCount - successCount | |
console.log(`${successCount} success, ${failureCount} failure`) | |
console.log( | |
couples.map(([w, m]) => [ | |
// それぞれの名前と、何番目に好みの相手と結ばれたかを表示する | |
w.name, w.likes.indexOf(m.name), m.name, m.likes.indexOf(w.name) | |
]) | |
) |
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
10 success, 0 failure | |
[ [ 'woman#1', 1, 'man#3', 0 ], | |
[ 'woman#2', 0, 'man#1', 1 ], | |
[ 'woman#7', 0, 'man#7', 0 ], | |
[ 'woman#5', 0, 'man#0', 1 ], | |
[ 'woman#8', 7, 'man#6', 2 ], | |
[ 'woman#3', 2, 'man#8', 0 ], | |
[ 'woman#4', 1, 'man#4', 1 ], | |
[ 'woman#9', 1, 'man#2', 0 ], | |
[ 'woman#0', 4, 'man#5', 1 ], | |
[ 'woman#6', 9, 'man#9', 2 ] ] |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment