Random Line from .txt file in Node.js [duplicate] - javascript

This question already has answers here:
Grabbing a random line from file
(4 answers)
Closed 1 year ago.
How can I grab a random line from a text file using Node.js?
What modifications do I need to make to my code?
const readline = require('readline');
const fs = require('fs');
var file = 'path.to.file';
var rl = readline.createInterface({
input: fs.createReadStream(file),
output: process.stdout,
terminal: false
});
rl.on('line', function (line) {
console.log(line) // print the content of the line on each linebreak
});

You could do worse than something like this. It:
0. Reads the file into memory as an array of lines
Randomly shuffles the corpus
Each call to next() returns the next line;
When the corpus is exhausted, repeats from step #1 (shuffling)
const fs = require('fs');
/**
*
* #param {*} min
* #param {*} max
* #returns random integer n such that min <= n <= max
*/
const randomInt = (min, max) => {
const range = max - min + 1;
const n = min + Math.floor( Math.random() * range );
return n;
}
exports = module.exports = class RandomLines {
constructor(pathToTextFile) {
this.path = pathToTextFile;
this.n = undefined;
this.lines = undefined;
}
next() {
if (!this.lines) {
this.lines = fs.readFileSync('./some/path/to/a/file.txt').split( /\r\n?|\n/g );
this.n = this.lines.length;
}
if (this.n >= this.lines.length) {
this.shuffleLines();
this.n = 0;
}
return this.lines[n++]
}
init() {
}
/**
* Shuffles the array lines
*/
shuffleLines() {
for (let i = this.lines.length - 1 ; i > 0 ; --i ) {
const j = randomInt(0, i );
const temp = this.lines[i];
this.lines[i] = this.lines[j];
this.lines[j] = this.lines[i];
}
}
}
Usage is pretty straightforward:
const RandomLines = require('./random-lines');
const randomLines = new RandomLines('./path/to/some/file.txt');
while (true) {
console.log( randomLines.next() );
}

Related

How to access the sum of values ​of an object built based on a constructor function

I am building a rpg character builder and first of all I am doing the logic in javascript. Each character has 10 points to distribute in their characteristics and choose advantages.
Character Constructor
function personagem(frc, hab, res, arm, pdf) {
this.frc = frc;
this.hab = hab;
this.res = res;
this.arm = arm;
this.pdf = pdf;
}
Building a Character
var eu = new personagem()
eu.frc = 1
eu.hab = 1
eu.res = 1
eu.arm = 1
eu.pdf = 1
eu.PV = eu.res * 5
eu.PM = eu.res * 5
I managed to make a function that adds all the numbers of the characteristics to check if they do not exceed the limit, but how do I get the cost of the advantages (vantagem.cost) to apply in that same function and see if the cost has been exceeded with the characteristics?
And how apply the bonus (For example, the Aceleração advantage adds +1 hab to the character)
Function with total points
var total = () => {
return eu.frc + eu.hab + eu.res + eu.arm + eu.pdf
}
const totalofPoints = () => {
if (total() > 10) {
console.log("You have exceeded the number of points")
} else {
console.log("You Did it!")
}
}
totalofPoints()
Advantages Consctructor
Assuming my character has these two advantages, how could I access the sum of them and add the first bonus
function vantagem(nome, custo, bonus) {
this.nome = nome;
this.custo = custo;
this.bonus = bonus
}
Example of Advantages
var aceleracao = new vantagem("Aceleração", 1, eu.hab + 1)
var adaptador = new vantagem("Aceleração", 1)
Think well about your structure. You currently have two components in your system: A Character and an Advantage. The character is probably the main component of the two, where the advantage only adds something to the character, like a plugin.
Give your character a method to add an advantage to a character. In that function calculate the bonus given by the advantage to the character.
I could not fully understand what some things in your code meant as they were in Spanish, so I tried to make a prototype based on what you tried to make.
First the function for creating an advantage. This function should indicate what property of the character it should adjust, and the values for the cost and bonus.
/**
* Advantage constructor
*
* #param {string} name Name of advantage.
* #param {string} stat Name of stat property.
* #param {number} cost Cost of advantage.
* #param {number} [bonus=0] Bonus added to character.
*/
function Advantage(name, stat, cost, bonus = 0) {
this.name = name;
this.stat = stat;
this.cost = cost;
this.bonus = bonus;
}
The Character needs a way to get advantages. So I've created a method called addAdvantage which takes an advantage and counts is up to the current stats.
/**
* Character constructor
*
* #param {string} name Name of the character.
*/
function Character(name) {
this.name = name;
this.stats = {
agility: 1,
dexterity: 1,
strength: 1,
speed: 1
};
this.life = 5;
this.mana = 5;
this.advantages = [];
this.pointsToSpend = 10;
}
/**
* Add a value to a single stat of the character and calculates
* the remaining points to spend
*
* #param {string} stat Stat to add value to.
* #param {number} value Value to increase stat with.
*/
Character.prototype.addStats = function(stat, value) {
if (this.stats[stat] !== undefined && this.pointsToSpend - value > 0) {
if (stat === 'strength') {
this.life += (value * 5);
} else if (stat === 'dexterity') {
this.mana += (value * 5);
}
this.stats[stat] += value;
this.pointsToSpend -= value;
}
}
/**
* Add an advantage to the character and calculates the advantage
* on top of the previous stats.
*
* #param {Advantage} advantage An Advantage instance.
*/
Character.prototype.addAdvantage = function(advantage) {
if (advantage instanceof Advantage) {
let { stat, cost, bonus } = advantage;
if (this.stats[stat] !== undefined && this.pointsToSpend - cost > 0) {
if (stat === 'strength') {
this.life += (bonus * 5);
} else if (stat === 'dexterity') {
this.mana += (bonus * 5);
}
this.stats[stat] += bonus;
this.pointsToSpend -= cost;
this.advantages.push(advantage);
}
}
}
Then put it all together by first creating the character, then creating the advantages and finally adding the advantages to the character with the addAdvantage method.
// Create the character.
const geralt = new Character('Geralt');
// Add stats to the character.
geralt.addStats('speed', 2);
geralt.addStats('strength', 3);
// Create advantages.
const agilityBoost = new Advantage('Agility Boost', 'agility', 1, 2);
const powerfulDexterityBoost = new Advantage('Powerful Dexterity Boost', 'dexterity', 2, 3);
// Add advantages to the character.
geralt.addAdvantage(agilityBoost);
geralt.addAdvantage(powerfulDexterityBoost);
Below is a snippet where it's all put together so you can try it out.
Small note: Functions that are supposed to be used with the new operator should start with a capital letter. This makes it obvious for the user how use this code.
function Advantage(name, stat, cost, bonus = 0) {
this.name = name;
this.stat = stat;
this.cost = cost;
this.bonus = bonus;
}
function Character(name) {
this.name = name;
this.stats = {
agility: 1,
dexterity: 1,
strength: 1,
speed: 1
};
this.life = 5;
this.mana = 5;
this.advantages = [];
this.pointsToSpend = 10;
}
Character.prototype.addStats = function(stat, value) {
if (this.stats[stat] !== undefined && this.pointsToSpend - value > 0) {
if (stat === 'strength') {
this.life += (value * 5);
} else if (stat === 'dexterity') {
this.mana += (value * 5);
}
this.stats[stat] += value;
this.pointsToSpend -= value;
}
}
Character.prototype.addAdvantage = function(advantage) {
if (advantage instanceof Advantage) {
let { stat, cost, bonus } = advantage;
if (this.stats[stat] !== undefined && this.pointsToSpend - cost > 0) {
if (stat === 'strength') {
this.life += (bonus * 5);
} else if (stat === 'dexterity') {
this.mana += (bonus * 5);
}
this.stats[stat] += bonus;
this.pointsToSpend -= cost;
this.advantages.push(advantage);
}
}
}
const geralt = new Character('Geralt');
geralt.addStats('speed', 2);
geralt.addStats('strength', 3);
const agilityBoost = new Advantage('Agility Boost', 'agility', 1, 2);
const powerfulDexterityBoost = new Advantage('Powerful Dexterity Boost', 'dexterity', 2, 3);
geralt.addAdvantage(agilityBoost);
geralt.addAdvantage(powerfulDexterityBoost);
console.log(geralt);

Add Two Number leetcode algo

I was doing following leetCode Problem: https://leetcode.com/problems/add-two-numbers/
And I am not sure why one of my test case is failing
So the question is
You are given two non-empty linked lists representing two non-negative
integers. The digits are stored in reverse order and each of their
nodes contain a single digit. Add the two numbers and return it as a
linked list.
You may assume the two numbers do not contain any leading zero, except
the number 0 itself.
For which I have written following algo
/**
* Definition for singly-linked list.
* function ListNode(val) {
* this.val = val;
* this.next = null;
* }
*/
/**
* #param {ListNode} l1
* #param {ListNode} l2
* #return {ListNode}
*/
const makeLinkedList = (inArr, i) => {
if (i < 0) return null
return { val:inArr[i], next:makeLinkedList(inArr, i-1)}
}
var addTwoNumbers = function(l1, l2) {
let sum = 0
let i = 1
while(l1 || l2) {
if (l1 && l2) {
sum = sum + l1.val*i + l2.val*i
l1 = l1.next
l2 = l2.next
} else {
if (l1) {
sum = l1.val*i + sum
l1 = l1.next
}
if (l2) {
sum = l2.val*i + sum
l2 = l2.next
}
}
i = i*10
}
const sumToString = sum.toLocaleString('fullwide', {useGrouping:false});
return makeLinkedList(sumToString, sumToString.length-1)
};
The reason in the above code I have used while loop instead of recursively calling functions is mainly to make it more optimized.
anyway, For the following input, my test case is failing
[1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1]
[5,6,4]
i.e my output is coming to be [0,3,NaN,NaN,1] instead of [6,6,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1]
As a note, leetCode compiler will convert array to linkedlist on input. Can someone help me in figuring out why my input might be failing?
When JavaScript stringifies a number in scientific notation, there will be a + sign for positive exponents. That sequence you see is 1E+30, the NaNs are standing for + and E (because of the reverted order). In fact you could have put a console.log(sum) or console.log(sumToString) and catch the issue without knowing this, just simply seeing what is there.
Not all languages tell you the maximum value they can store without loss in precision, but JavaScript in particular does, Number.MAX_SAFE_INTEGER contains the value 9 007 199 254 740 991 so it is a bit more than 9E+15, far less than 1 + 1E+30 (the longer number).
What you are expected to do is to add the numbers like you have learned in elementary school: add two digits, write one digit, and see if there is an 1 to carry to the next digit-pair you are going to add.
Iterative version:
function makeLinkedList(arr,i){
i=i || 0;
return i<arr.length?{val:arr[i], next:makeLinkedList(arr,i+1)}:null;
}
var addTwoNumbers = function(l1, l2) {
var snt={next:null};
var cur=snt;
var carry=0;
while(l1 || l2 || carry){
cur.next={next:null};
cur=cur.next;
var sum=(l1?l1.val:0)+(l2?l2.val:0)+carry;
if(sum<10){
cur.val=sum;
carry=0;
} else {
cur.val=sum-10;
carry=1;
}
l1=l1?l1.next:null;
l2=l2?l2.next:null;
}
return snt.next;
}
var a=[1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1];
var b=[5,6,4];
console.log(addTwoNumbers(makeLinkedList(a),makeLinkedList(b)));
a=[9,9];
b=[1,9];
console.log(addTwoNumbers(makeLinkedList(a),makeLinkedList(b)));
Recursive version:
function makeLinkedList(arr,i){
i=i || 0;
return i<arr.length?{val:arr[i], next:makeLinkedList(arr,i+1)}:null;
}
var addTwoNumbers = function(l1, l2, carry) {
if(!(l1 || l2 || carry))
return null;
carry=carry || 0;
var sum=(l1?l1.val:0)+(l2?l2.val:0)+carry;
return {
val: sum % 10,
next: addTwoNumbers(l1?l1.next:null,l2?l2.next:null,sum>9?1:0)
};
}
var a=[1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1];
var b=[5,6,4];
console.log(addTwoNumbers(makeLinkedList(a),makeLinkedList(b)));
a=[9,9];
b=[1,9];
console.log(addTwoNumbers(makeLinkedList(a),makeLinkedList(b)));
Solution for the problem in JavaScript.
var addTwoNumbers = function (l1, l2) {
let reminder = 0;
let l1Node = l1;
let l2Node = l2;
let list = new ListNode(0);
let currentNode = list;
while (l1Node || l2Node) {
const valueL1 = l1Node ? l1Node.val : 0;
const valueL2 = l2Node ? l2Node.val : 0;
let sum = valueL1 + valueL2 + reminder;
reminder = 0;
if (sum > 9) {
reminder = Math.floor(sum / 10);
sum = sum % 10;
}
currentNode.next = new ListNode(sum);
currentNode = currentNode.next;
l1Node = l1Node ? l1Node.next : null;
l2Node = l2Node ? l2Node.next : null;
}
if (reminder != 0) {
currentNode.next = new ListNode(reminder);
currentNode = currentNode.next;
}
return list.next;
};
function ListNode(val, next) {
this.val = (val === undefined ? 0 : val)
this.next = (next === undefined ? null : next)
}
const l1 = new ListNode(2, new ListNode(4, new ListNode(3)));
const l2 = new ListNode(5, new ListNode(6))
const res = addTwoNumbers(l1, l2);
console.log(res);

Constantly increasing memory usage when passing around huge arrays to webworker

I am currently doing some 3d modeling using babylonjs. I need to create a pressure map from given pressure at specific points. I am doing that using IDW. However this means that even with my map being a size of 70x90 grid requires me to have an array of 25200 (4 rgba values for each pixel) entries. Then this buffer is passed to a RawTexture for assigning it to a material, that is overlaid on the object
I am using a web worker, because I have to update the pressure values every 100ms and I don't want to block the main thread.The issue occurs when I am return that array (created in calculate function) from a service worker.
For some reason the memory usage just keeps going up, without stopping. It eventually goes up to around 1.5 gigabytes and I have to kill it.
The question : Is there any way to prevent this and what could be causing such high memory usage?
Worker:
// #flow
import { find, propEq, both } from 'ramda';
import { colorFromValue } from './color';
import { inverseDistance, distanceValues } from './math';
const findPoint = (x: number, y: number) =>
find(both(propEq('x', x), propEq('y', y)));
const distanceDict = {};
/* eslint-disable */
function calculate(options: Object, pList: Array<*>) {
const points = pList || [];
const { height, width } = options;
const gridWidth = width * 4;
const grid = new Uint8Array(options.width * options.height * 4);
for (let y = 0; y < height; y += 1) {
const rW = y * gridWidth;
for (let i = 0; i < gridWidth; i += 4) {
const index = i + rW;
const x = i / 4;
const dictKey = `${x}--${y}`;
let bottoms = distanceDict[dictKey];
if (bottoms === undefined) {
bottoms = distanceValues(points, x, y);
distanceDict[dictKey] = bottoms;
}
const point = findPoint(x, y)(points);
const value = point !== undefined && point !== null ?
point.value : inverseDistance(points, bottoms);
const color = colorFromValue(value);
grid[index] = color[0];
grid[index + 1] = color[1];
grid[index + 2] = color[2];
grid[index + 3] = 255;
}
}
return grid;
}
self.onmessage = (e) => {
const { points, options } = e.data;
const grid = calculate(options, points);
self.postMessage(grid.buffer, [grid.buffer]);
};
Painting:
modifyNodes = (points: Array<*>) => new Promise((res, rej) => {
this.worker.onmessage = (e) => {
this._texture.update(new Uint8Array(e.data));
res();
}
const data = {
options: this._options,
points,
};
this.worker.postMessage(data);
})
So it seems the issue was in the colorFromValue function that was memoized. Because the values had quite few decimal points it could create up to 9! new entries into cache, so it drove up the memory usage...

Generated nonce length is getting changed

I am trying to generate fixed length nonce (length 9).
But my code is printing sometimes nonce of 8 length and sometime 9 length.
this is what I am trying to do but with different approach (I have modified it for fixed nonce length)
I am not able to understand why it is printing nonce of length 8 when i am passing length as 9 as argument??
It would be great if someone can tell why this is happening.
Below is complete Nodejs code
var last_nonce = null;
var nonce_incr = null;
// if you call new Date to fast it will generate
// the same ms, helper to make sure the nonce is
// truly unique (supports up to 999 calls per ms).
module.exports = {
getNonce: function(length) {
if (length === undefined || !length) {
length = 8;
}
var MOD = Math.pow(10, length);
var now = (+new Date());
if (now !== last_nonce) {
nonce_incr = -1;
}
nonce_incr++;
last_nonce = now;
var nonce_multiplier = ((nonce_incr < 10) ? 10 : ((nonce_incr < 100) ? 100 : 1000));
var s = (((now % MOD) * nonce_multiplier) + nonce_incr) % MOD;
return s;
}
}
//test code
if(require.main === module) {
console.time("run time");
//importing async module
var async = require('async');
var arr = [];
//generating 1000 length array to use it in making 1000 async calls
//to getNonce function
for(var i=0; i<1000; i++) arr.push(i);
//this will call getNonce function 1000 time parallely
async.eachLimit(arr, 1000, function(item, cb) {
console.log(module.exports.getNonce(9));
cb();
}, function(err) {console.timeEnd("run time");});
}
Sample output:
708201864 --> nonce length 9
708201865
708201866
70820190 --> nonce length 8 (why it is coming 8?? when passed length is 9)
70820191
70820192
70820193
70820194
70820195
70820196
70820197
70820198
70820199
708201910
708201911
708201912
708201913
708201914
708201915
708201916
708201917
708201918
In case someone needs it, here is a nonce generator free from convoluted logic, allowing you to control both character sample and nonce size:
const generateNonce = (options) => {
const {
length = 32,
sample = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789',
} = options || {};
const getRand = () => Math.floor(Math.random() * sample.length);
return Array.from({ length }, () => sample.charAt(getRand())).join('');
};
If you prefer Typescript:
const generateNonce = (options?: { sample?: string, length?: number }) => {
const {
length = 32,
sample = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789',
} = options || {};
const getRand = () => Math.floor(Math.random() * sample.length);
return Array.from({ length }, () => sample.charAt(getRand())).join('');
};

Converting Javascript Map function to Swift 2 Map function

I am rewriting this question because my first one was quite vague. I am trying to conver the following javascript function using the map function into Swift 2.
Here is the javascript function.
function compute_correlations(timeseries, test_frequencies, sample_rate)
{
// 2pi * frequency gives the appropriate period to sine.
// timeseries index / sample_rate gives the appropriate time coordinate.
var scale_factor = 2 * Math.PI / sample_rate;
var amplitudes = test_frequencies.map
(
function(f)
{
var frequency = f.frequency;
// Represent a complex number as a length-2 array [ real, imaginary ].
var accumulator = [ 0, 0 ];
for (var t = 0; t < timeseries.length; t++)
{
accumulator[0] += timeseries[t] * Math.cos(scale_factor * frequency * t);
accumulator[1] += timeseries[t] * Math.sin(scale_factor * frequency * t);
}
return accumulator;
}
);
return amplitudes;
}
And here is my Swift function. I am getting an error and am not even sure I am doing it correctly. Error is noted in the code.
func compute_correlations(timeseries:[Double], test_frequencies:[NoteInfo], sample_rate:Double) -> [Double]
{
// 2pi * frequency gives the appropriate period to sine.
// timeseries index / sample_rate gives the appropriate time coordinate.
let scale_factor = 2 * pi / sample_rate;
let amplitudes: [Double] = test_frequencies.map { f in
let frequency = f.getFrequency()
// Represent a complex number as a length-2 array [ real, imaginary ].
var accumulator: [Double] = [ 0.0, 0.0 ]
for (var t = 0; t < timeseries.count; t++)
{
accumulator[0] += timeseries[t] * cos(scale_factor * frequency * Double(t))
accumulator[1] += timeseries[t] * sin(scale_factor * frequency * Double(t))
}
return accumulator //ERROR Cannot convert return expression of type '[Double]' to return type 'Double'
}
return amplitudes;
}
And if needed here is the NoteInfo class
class NoteInfo {
var frequency:Double!
var note_name:String!
init(theFrequency:Double, theNoteName:String){
frequency = theFrequency
note_name = theNoteName
}
func getFrequency()-> Double {
return frequency
}
func getNoteName()-> String {
return note_name
}
}
Here is where I am populating the test_frequencies
for (var i = 0; i < 30; i++)
{
let note_frequency = C2 * pow(2.0, Double(i) / 12.0)
let note_name = notes[i % 12]
let note = NoteInfo(theFrequency: note_frequency, theNoteName: note_name)
test_frequencies.append(note)
}
Your accumulator is a [Double], and so the result of your map becomes [[Double]]. You then try to assign it to a [Double].
You should either declare amplitudes accordingly:
let amplitudes: [[Double]] = test_frequencies.map { f in
or (depending on your needs) return only one of the accumulator fields inside your map, e.g.
return accumulator[0]

Categories

Resources