Created
April 29, 2021 06:55
-
-
Save mahpah/23ed4033dc877c1df6cb4c3de2bd8523 to your computer and use it in GitHub Desktop.
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
import crypto from 'crypto'; | |
import fs from 'fs'; | |
import path from 'path'; | |
const startingPrize = 30000; | |
const prizes = [0.7, 0.15, 0.1, 0.05]; | |
const price = 2; | |
const ranHex = (length: number) => { | |
return crypto | |
.randomBytes(Math.ceil(length / 2)) | |
.toString('hex') | |
.slice(0, length); | |
}; | |
const genRand = (max: number) => { | |
const hex = ranHex(64); | |
return parseInt('0x' + hex.substr(0, 8)) % max; | |
}; | |
const tryRand = (n: number, max: number, maxPowerBall: number) => { | |
const hex = ranHex(64); | |
const result: number[] = [(parseInt(`0x` + hex.substr(0, 8)) % max) + 1]; | |
let i = 1; | |
while (result.length < n && i < hex.length - 8) { | |
const a = (parseInt(`0x` + hex.substr(i++, 8)) % max) + 1; | |
if (!result.includes(a)) { | |
result.push(a); | |
} | |
} | |
result.push(parseInt('0x' + hex.substr(n + 1, 8)) % maxPowerBall + 1); | |
return result; | |
}; | |
const rand = (n: number, max: number, maxPowerBall: number) => { | |
let r: number[] = []; | |
do { | |
r = tryRand(n, max, maxPowerBall); | |
} while (r.length < n + 1); | |
return r; | |
}; | |
const match = (win: number[], ticket: number[]) => { | |
let count = 0; | |
const normalWinGroup = win.slice(0, win.length - 1); | |
const normalTicketGroup = ticket.slice(0, ticket.length - 1); | |
normalWinGroup.forEach((t) => { | |
if (normalTicketGroup.includes(t)) { | |
count++; | |
} | |
}); | |
if (count < 2) { | |
return 0 | |
} | |
if ( | |
count === win.length - 1 && | |
win[win.length - 1] === ticket[ticket.length - 1] | |
) { | |
return count + 1; | |
} | |
return count; | |
}; | |
const round = ( | |
n: number, | |
range: number, | |
powerBallMax: number, | |
ticketBought: number, | |
) => { | |
let winCount = prizes.map(_ => 0); | |
const winningNumbers = rand(n, range, powerBallMax); | |
console.log('Winning numbers', winningNumbers); | |
for (let index = 0; index < ticketBought; index++) { | |
const ticket = rand(n, range, powerBallMax); | |
const matchCount = match(winningNumbers, ticket); | |
if (matchCount) { | |
if (matchCount === n + 1) { | |
winCount[0] += 1 | |
} else { | |
winCount[n + 1 - matchCount] += 1; | |
} | |
} | |
} | |
return [winCount, winningNumbers]; | |
}; | |
const main = async () => { | |
const n = 4; | |
const max = 50; | |
const observeRound = 100; | |
const powerBallMax = 24; | |
const estTicketBought = 1e6 | |
const file = fs.createWriteStream( | |
path.resolve(process.cwd(), `${Date.now()}-result-${n}-${max}-${observeRound}-pb-${powerBallMax}.tsv`), | |
{ | |
flags: 'w', | |
}, | |
); | |
const heading = | |
[ | |
'#', | |
'Ticket bought', | |
'Jackpot', | |
`Winning numbers`, | |
'champion', | |
'runner-up', | |
'third place', | |
'4th', | |
'x', | |
].join('\t') + '\n'; | |
file.write(heading); | |
let totalPrize = startingPrize; | |
for (let roundIndex = 0; roundIndex < observeRound; roundIndex++) { | |
console.log('Round', roundIndex); | |
const ticketBought = genRand(estTicketBought); | |
console.log(ticketBought, 'tickets sold'); | |
let income = ticketBought * price; | |
totalPrize += income; | |
const jackpot = totalPrize * prizes[0]; | |
console.log('Total prize', totalPrize); | |
console.log('Jackpot', jackpot, prizes[0]); | |
const [winCount, winningNumbers] = round(n, max, powerBallMax, ticketBought); | |
console.log(winCount); | |
let prizePaid = 0; | |
winCount.forEach((count, index) => { | |
if (count && index === 0) { | |
console.log('BINGO!!!'); | |
} | |
if (count > 0) { | |
prizePaid += prizes[index] * totalPrize; | |
} | |
}); | |
console.log('Paid', prizePaid); | |
if (Math.round(Math.abs(totalPrize - prizePaid)) === 0) { | |
// sai so cua js | |
totalPrize = startingPrize; | |
} else { | |
totalPrize -= prizePaid; | |
} | |
const line = | |
[ | |
roundIndex, | |
ticketBought, | |
jackpot, | |
`(${winningNumbers.join('-')})`, | |
winCount[0], | |
winCount[1], | |
winCount[2], | |
winCount[3], | |
winCount[0] ? 'BINGO!!!' : '', | |
].join('\t') + '\n'; | |
file.write(line); | |
} | |
file.end(); | |
}; | |
main().catch(console.error); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment