Galton box animation: Difference between revisions
Content added Content deleted
SqrtNegInf (talk | contribs) (Added Perl example) |
|||
Line 1,697: | Line 1,697: | ||
| |o|o|o|o|o|o|o| | |
| |o|o|o|o|o|o|o| | |
||
| |o|o|o|o|o|o|o| |</pre> |
| |o|o|o|o|o|o|o| |</pre> |
||
=={{header|JavaScript}}== |
|||
Works with NodeJs |
|||
<lang JavaScript>const readline = require('readline'); |
|||
const galtonBox2 = (layers, balls) => { |
|||
const speed = 100; |
|||
const ball = 'o'; |
|||
const peg = '.'; |
|||
const result = []; |
|||
const sleep = ms => new Promise(resolve => { |
|||
setTimeout(resolve,ms) |
|||
}); |
|||
/** |
|||
* The board is represented as a 2D array. |
|||
* @type {Array<Array<string>>} |
|||
*/ |
|||
const board = [...Array(layers)] |
|||
.map((e, i) => { |
|||
const sides = Array(layers - i).fill(' '); |
|||
const a = Array(i + 1).fill(peg).join(' ').split(''); |
|||
return [...sides, ...a, ...sides]; |
|||
}); |
|||
/** |
|||
* @return {Array<string>} |
|||
*/ |
|||
const emptyRow = () => Array(board[0].length).fill(' '); |
|||
/** |
|||
* @param {number} i |
|||
* @returns {number} |
|||
*/ |
|||
const bounce = i => Math.round(Math.random()) ? i - 1 : i + 1; |
|||
/** |
|||
* Prints the current state of the board and the collector |
|||
*/ |
|||
const show = () => { |
|||
readline.cursorTo(process.stdout, 0, 0); |
|||
readline.clearScreenDown(process.stdout); |
|||
board.forEach(e => console.log(e.join(''))); |
|||
result.reverse(); |
|||
result.forEach(e => console.log(e.join(''))); |
|||
result.reverse(); |
|||
}; |
|||
/** |
|||
* Collect the result. |
|||
* @param idx |
|||
*/ |
|||
const appendToResult = idx => { |
|||
const row = result.find(e => e[idx] === ' '); |
|||
if (row) { |
|||
row[idx] = ball; |
|||
} else { |
|||
const newRow = emptyRow(); |
|||
newRow[idx] = ball; |
|||
result.push(newRow); |
|||
} |
|||
}; |
|||
/** |
|||
* Move the balls through the board |
|||
* @returns {boolean} True if the there are balls in the board. |
|||
*/ |
|||
const iter = () => { |
|||
let hasNext = false; |
|||
[...Array(bordSize)].forEach((e, i) => { |
|||
const rowIdx = (bordSize - 1) - i; |
|||
const idx = board[rowIdx].indexOf(ball); |
|||
if (idx > -1) { |
|||
board[rowIdx][idx] = ' '; |
|||
const nextRowIdx = rowIdx + 1; |
|||
if (nextRowIdx < bordSize) { |
|||
hasNext = true; |
|||
const nextRow = board[nextRowIdx]; |
|||
nextRow[bounce(idx)] = ball; |
|||
} else { |
|||
appendToResult(idx); |
|||
} |
|||
} |
|||
}); |
|||
return hasNext; |
|||
}; |
|||
board.unshift(emptyRow()); |
|||
result.unshift(emptyRow()); |
|||
const bordSize = board.length; |
|||
const apex = board[1].indexOf(peg); |
|||
return (async () => { |
|||
while (balls) { |
|||
board[0][apex] = ball; |
|||
balls = balls - 1; |
|||
await sleep(speed); |
|||
show(); |
|||
iter(); |
|||
} |
|||
await sleep(speed); |
|||
show(); |
|||
while (iter()) { |
|||
await sleep(speed); |
|||
show(); |
|||
} |
|||
await sleep(speed); |
|||
show(); |
|||
})().then(() => console.log('Done!')); |
|||
}; |
|||
galtonBox2(12, 50); |
|||
</lang> |
|||
{{out}} |
|||
<pre> |
|||
. |
|||
. . |
|||
. . . |
|||
. . . . |
|||
. . . . . |
|||
. . . . . . |
|||
. . . . . . . |
|||
. . . . . . . . |
|||
. . . . . . . . . |
|||
. . . . . . . . . . |
|||
. . . . . . . . . . . |
|||
. . . . . . . . . . . . |
|||
o |
|||
o |
|||
o |
|||
o |
|||
o o |
|||
o o |
|||
o o |
|||
o o o |
|||
o o o |
|||
o o o o |
|||
o o o o |
|||
o o o o o |
|||
o o o o o o |
|||
o o o o o o o |
|||
o o o o o o o o </pre> |
|||
=={{header|Julia}}== |
=={{header|Julia}}== |