I am experiencing something that is confusing me.
While working through problems in javascript on leetcode, I came across a solution that implemented a MaxPriorityQueue in the solution.
The posted solution was:
Finally, there's a Max/MinPriorityQueue for JavaScript!
add -> enqueue( )
remove -> dequeue( )
highest number (peek) -> front( )
.element -> actual value
var lastStoneWeight = function(stones) {
const m = new MaxPriorityQueue()
for(const w of stones) m.enqueue(w)
while(m.size() > 1){
const diff = m.dequeue().element - m.dequeue().element
if(diff > 0) m.enqueue(diff)
}
return m.size() === 0 ? 0 : m.front().element
};
I tried to implement this myself in my own environment and get:
const m = new MaxPriorityQueue();
^
ReferenceError: MaxPriorityQueue is not defined
at lastStoneWeight (C:\Users\steph\Desktop\coding-projects\learning-js\leetcode\last-stone-weight.js:55:13)
at Object.<anonymous> (C:\Users\steph\Desktop\coding-projects\learning-js\leetcode\last-stone-weight.js:66:13)
I went and plugged the same code into leetcode and it ran without a hitch.
I tried to find documentation on a MaxPriorityQueue object but anything using a MPQ was implemented from scratch.
If someone could shed a bit of light on why this will not run in my personal environment, (nodejs, VSCode), I would appreciate it.
This is because you have #datastructures-js/priority-queue library imported in the JS runtime by default. It is mentioned https://support.leetcode.com/hc/en-us/articles/360011833974-What-are-the-environments-for-the-programming-languages-.
In your own run time, you will have to import it as
const {
PriorityQueue,
MinPriorityQueue,
MaxPriorityQueue,
} = require('#datastructures-js/priority-queue');
or
import {
PriorityQueue,
MinPriorityQueue,
MaxPriorityQueue,
ICompare,
IGetCompareValue,
} from '#datastructures-js/priority-queue';
Related
Use case
This is a Cypress E2E test coded with JS and I'm trying to compare pre-production and production sitemap URL contents in order to find the differences. I have two data sets (fixture) one for production and the other for test env.
code snippet
let compareUrlsBetween = (prodSitemapUrls, testEnvSitemapUrls) => {
const pathFirstEnv = new Set(JSON.parse(prodSitemapUrls).map(url => (new URL(url)).pathname))
const pathSecondEnv = new Set(JSON.parse(testEnvSitemapUrls).map(url => (new URL(url)).pathname))
const diff = new Set(pathFirstEnv);
for (const path of pathSecondEnv) {
diff.delete(path);
}
return diff
}
// Check for differences
if (compareUrlsBetween.length > 0) {
let titi = typeof(compareUrlsBetween(prodSitemapUrls, testEnvSitemapUrls))
console.log(titi)
cy.log('text : ' , compareUrlsBetween (prodSitemapUrls, testEnvSitemapUrls)) // Returns null
//console.log(compareUrlsBetween(prodSitemapUrls, testEnvSitemapUrls))
//console.log('Production and test env sitemap urls are not ISO, ' + 'Here are the diffrences : ' , compareUrlsBetween (prodSitemapUrls, testEnvSitemapUrls))
//throw new Error()
} else {
expect(prodSitemapUrls).to.eq(testEnvSitemapUrls)
}
Test goal & the problem
Test goal is to fail the test in cas of diff between these two fixtures (.xml), throw a new error and show the diff as normal log (cy.log()). I've already tried multiple solutions like JSON.stringify(), data type convertion etc. but none of them solved my case.
Log I observe at this moment : logtext : , {}
PS : the other type of logs like console.log() or console.table() are working perfectly fine
Any help is much appreciated.
Solution
Convert the set into an array
cy.log('text : ' , [...compareUrlsBetween (prodSitemapUrls, testEnvSitemapUrls)])
Why?
I'm not 100% sure, but it seems like cy.log uses JSON.stringify underneath which causes sets to be converted to {}
message.channel.send(embed1).then((msgg) => setTimeout(() => {
const opponentData = userHit(opponentp, userPet.stats.strength, userPet, opponentPet, userp)
const userData = opponentHit(userp, opponentPet.stats.strength, userPet, opponentPet, opponentp)
if (opponentData.health >= 1) {
msgg.edit(opponentData.embed)
}
if (userData.health >= 1) {
msgg.edit(userData.embed)
}
}, 1000))
}
So ... I have this code, and I have been stumped for a few days. I need to loop these so they run one after the other until on hits 0 or lower without copy pasting them over and over. I need it to stop editing the message after it hits 0 or lower.
To loop this code you have to use simple do while method!Read more about this method here. Mozilla documentation is very helpful!I hope I helped you with this.Have a nice day!
i created multiple conditions by using map, but i think there are other methods to optimize this code:
if (content.risks) {
content.risks.map((risk) => {
if (risk.coverageCode === "PUB" || risk.coverageCode === "SPPI" || risk.coverageCode === "PROD" || risk.coverageCode === "PR" || risk.coverageCode === "DO") {
risk._class = "com.generali.gip.local.hk.domain.RiskPublicLiability";
}
if (risk.coverageCode === "PD") {
risk._class = "com.generali.gip.local.hk.domain.RiskMaterialDamage";
}
if (risk.coverageCode === "BI") {
risk._class = "com.generali.gip.local.hk.domain.RiskBusinessInterruption";
}
});
}
How i can to rewrite this code by using find or indexof?
My objective in software development is to express my intents in a way that is clear and unambiguous.
For this kind of "problems", I will always reach out for the humble map. There's no extra ceremonies (i.e. if/else, switch/case, etc.). It just says "if you give me an X, I'll give you a Y".
const risk_map =
{ PUB: "com.generali.gip.local.hk.domain.RiskPublicLiability"
, SPPI: "com.generali.gip.local.hk.domain.RiskPublicLiability"
, PROD: "com.generali.gip.local.hk.domain.RiskPublicLiability"
, PR: "com.generali.gip.local.hk.domain.RiskPublicLiability"
, DO: "com.generali.gip.local.hk.domain.RiskPublicLiability"
, PD: "com.generali.gip.local.hk.domain.RiskMaterialDamage";
, BI: "com.generali.gip.local.hk.domain.RiskBusinessInterruption"
};
Regardless of your programming background, the "time to get it" is low.
It can indeed lead to duplication but I don't think it comes at the expense of readability or maintenance. (How hard would it be to replace these duplicated strings with a constant for example?)
Now how can we "query" this map? Let's build a high-order function for that:
We say "Give me a map, then give me a key, I'll get you a value":
const get_value = map => key => map[key];
get_value(risk_map)("PUB");
//=> "com.generali.gip.local.hk.domain.RiskPublicLiability"
The get_value is a high-order function. We're meant to build specialised functions out of it. Let's just do that:
const get_risk = get_value(risk_map);
get_risk("PUB");
//=> "com.generali.gip.local.hk.domain.RiskPublicLiability"
With this we can solve your "problem" quite simply:
const content_risks =
content.risks
? content.risks.map(risk => get_risk(risk.coverageCode))
: null;
I'll leave it as an exercise to combine and adapt this to fit your exact needs.
Hope this helps though.
Suppose I have a function in Idris that does some computation. For simplicity, let it be stringly typed for now.
f: String -> String
How can I compile this function to JavaScript so that it can then be called from any ordinary JavaScript code?
If that is too easy, suppose f, instead of String, deals with Double or even a custom Idris data type.
I know I can compile a whole module with a Main.main function and a more or less inscrutable blob of JavaScript will be output. Can I maybe extract my function from there by hand? How should I go about it?
P.S. Despite my answering myself, I am still looking for a better solution, so welcome.
Using this example, it seems at least with the Node backend this is doable. I've marked interact as export and added a library descriptor:
module Main
import Data.String
f: Double -> Double
f x = x + 1
export interact: String -> String
interact s = let x = parseDouble s in
case x of
Nothing => "NaN"
Just x => show (f x)
main: IO ()
main = do
s <- getLine
putStrLn (interact s)
lib : FFI_Export FFI_JS "" []
lib = Data String "String" $
Fun interact "interact" $
Fun main "main" $
End
I have then compiled with the --interface flag (this fails with --codegen javascript...):
idris --codegen node --interface --output ExportToJS.js ExportToJS.idr
and the resulting .js file has this at the end:
module.exports = {
interact: Main__interact,
main: Main__interact
};
}.call(this))
This should allow you to do require("./ExportToJavaScript.js").interact("42") from Node, and there is probably an equivalent to use from a browser.
Yes, you can extract any function by hand.
Build a module as follows:
module Main
import Data.String
f: Double -> Double
f x = x + 1
interact: String -> String
interact s = let x = parseDouble s in
case x of
Nothing => "NaN"
Just x => show (f x)
main: IO ()
main = do
s <- getLine
putStrLn (interact s)
Compile it as follows:
% idris --codegen javascript --output Main.js Main.idr
A file called Main.js will be created. There will be several megabytes of more or less inscrutable JavaScript code, just as you say.
Edit this file by hand and edit it similarly to this:
--- Resistors.js
+++ Resistors-default.js
## -1,7 +1,5 ##
"use strict";
-(function(){
-
const $JSRTS = {
throw: function (x) {
throw x;
## -36130,7 +36128,3 ##
}
}
}
-
-
-$_0_runMain();
-}.call(this))
Now notice this JS file has comments in it marking the JS functions with their Idris names. For instance, corresponding to our interact function there will be located this JS function:
// Main.interact
function Main__interact($_0_arg){
const $_1_in = Data__String__parseDouble($_0_arg);
if(($_1_in.type === 1)) {
const $cg$3 = Main__bestMatch_39_($_1_in.$1, Main__manyResistors_39_());
let $cg$2 = null;
$cg$2 = $cg$3.$1;
return Prelude__Show__Main___64_Prelude__Show__Show_36_Schema_58__33_show_58_0($cg$2);
} else {
return "NaN";
}
}
If you attach this JS file to a web page as a script, you may then open JS console in a browser and interact with your Idris functions, like this:
Main__interact("10")
"11"
Hope this helps!
I already searched for similar issues but I didn't find anything that could help me yet.
I'm trying to reach a picture path (using JSON format) depending on the material type of the picked element. Actually, my code is built like this:
if (globalData.Material.Mat_type == "OSCILLOSCOPE") {
var picture = (globalData.Material.Oscilloscope.picture);
}
if (globalData.Material.Mat_type == "ALIMENTATION") {
var picture = (globalData.Material.Alim.picture);
}
But not optimized at all, so Im trying to make it this way :
var mat_type = (globalData.Material.Mat_type);
var picture = (globalData.Material[mat_type].picture);
But it doesn't work... Got some exception:
TypeError : globalData.Material[mat_type] is undefined.
I already tried a lot of things, have you got any idea? Thanks!
I outlined the issue with character case in the comment under the question, so presumably adjusting value of globalData.Material.Mat_type could do the trick:
var mat_type =
globalData.Material.Mat_type.charAt(0).toUpperCase() +
globalData.Material.Mat_type.substr(1).toLowerCase();
I can also see that this general rule may not be applicable in all cases. If it's not a typo, it won't work for the second case where Mat_type == "ALIMENTATION", because then you try to access Alim property of Material instead of Alimentation. In this case you could access property by prefix:
function pictureOf(material) {
if (!material || !String(material.Mat_type)) {
return null;
}
let mat_type = String(material.Mat_type).toUpperCase();
for (var propertyName in material) {
if (mat_type.startsWith(propertyName.toUpperCase())) {
return material[propertyName].picture || null;
}
}
return null;
}
console.log(pictureOf({
Mat_type: "OSCILLOSCOPE",
Oscilloscope: {
picture: "picture of oscilloscope"
}
}));
console.log(pictureOf({
Mat_type: "ALIMENTATION",
Alim: {
picture: "picture of alimentation"
}
}));
But this kind of approach can be error prone, if multiple properties share the same prefix. There's also a hidden issue with case-insensitive prefix matching in case you use some special unicode characters in property names. Lastly this method is not efficient, because it has to iterate over all properties of the object (worst case scenario). It can be replaced with much safer property mapping:
const matTypeMapping = {
"ALIMENTATION": "Alim"
};
function pictureOf(material) {
if (!material || !String(material.Mat_type)) {
return null;
}
let matType = String(material.Mat_type);
// find property mapping or apply general rule, if mapping not defined
let propertyName = matTypeMapping[matType] ||
matType.charAt(0).toUpperCase() + matType.substr(1).toLowerCase();
return material[propertyName].picture || null;
}
console.log(pictureOf({
Mat_type: "OSCILLOSCOPE",
Oscilloscope: {
picture: "picture of oscilloscope"
}
}));
console.log(pictureOf({
Mat_type: "ALIMENTATION",
Alim: {
picture: "picture of alimentation"
}
}));
NB: To avoid headaches, maybe you should prefer strict equality operator over loose equality operator.
Problem Solved
Peter Wolf was right ! It was a case-sensitive issue
I actually don't know how to promote his comment, sorry for this..
Anyway, thank you guys !
var mat_type = (globalData.Material.Mat_type);
if(mat_type!==undefined)
var picture = (globalData.Material[mat_type].picture)
Just do an existential check before accessing the value, for keys that may not be present.