I am trying to solve a DFS problem in javascript, the problem is to determine whether the given graph has a path between the given source and destination.
Here is the solution in java
import java.io.*;
import java.util.*;
public class Main {
static class Edge {
int src;
int nbr;
int wt;
Edge(int src, int nbr, int wt){
this.src = src;
this.nbr = nbr;
this.wt = wt;
}
}
public static void main(String[] args) throws Exception {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int vtces = Integer.parseInt(br.readLine());
ArrayList<Edge>[] graph = new ArrayList[vtces];
for(int i = 0; i < vtces; i++){
graph[i] = new ArrayList<>();
}
int edges = Integer.parseInt(br.readLine());
for(int i = 0; i < edges; i++){
String[] parts = br.readLine().split(" ");
int v1 = Integer.parseInt(parts[0]);
int v2 = Integer.parseInt(parts[1]);
int wt = Integer.parseInt(parts[2]);
graph[v1].add(new Edge(v1, v2, wt));
graph[v2].add(new Edge(v2, v1, wt));
}
int src = Integer.parseInt(br.readLine());
int dest = Integer.parseInt(br.readLine());
boolean visited[] = new boolean[vtces];
boolean ans = hasPath(graph , src, dest,visited);
System.out.println(ans);
}
static boolean hasPath( ArrayList<Edge> graph[] ,int src,int dest, boolean[] visited){
if(src == dest){
return true;
}
visited[src] = true;
for(Edge edge : graph[src]){
if( visited[edge.nbr] ){
continue;
}
boolean nbrHasPath = hasPath(graph, edge.nbr, dest, visited);
if(nbrHasPath){
return true;
}
}
return false;
}
}
And here is the JavaScript solution
'use strict';
process.stdin.resume();
process.stdin.setEncoding('utf-8');
let inputString = '';
let currentLine = 0;
process.stdin.on('data', (inputStdin) => {
inputString += inputStdin;
});
process.stdin.on('end', (_) => {
inputString = inputString
.trim()
.split('\n')
.map((string) => {
return string.trim();
});
main();
});
function readline() {
return inputString[currentLine++];
}
function readIntArray() {
return readline()
.split(' ')
.map((num) => parseInt(num));
}
function readFloatArray() {
return readline()
.split(' ')
.map((num) => parseFloat(num));
}
/*=====================START CODING HERE=====================*/
class Edge {
constructor(source, neighbour, weight){
this.source = source
this.neighbour = neighbour
this.weight = weight
}
}
function main() {
const vertices = parseInt(readline());
const edges = parseInt(readline());
const graph = new Array(vertices).fill([])
for(let i = 0 ; i < edges; i++){
let [s, d, w] = readIntArray()
graph[s].push(new Edge(s,d,w))
graph[d].push(new Edge(d,s,w))
}
const source = parseInt(readline());
const destination = parseInt(readline());
let visited = new Array(vertices).fill(false)
console.log(hasPath( graph, source, destination,visited ))
}
function hasPath(graph, source, dest, visited){
if(source === dest){
return true
}
visited[source] = true
for(let i = 0; i < graph[source].length; i++){
let edge = graph[source][i]
if( visited[edge.neighbour] ){
continue;
}
let nbrHasPath = hasPath(graph, edge.neighbour, dest , visited)
if(nbrHasPath){
return true
}
}
return false
}
The function haspath is the point of interest here, the java solution passes all the test cases, the javascript solution however fails in one test case that is :
7
7
0 1 10
1 2 10
2 3 10
0 3 10
4 5 10
5 6 10
4 6 10
0
6
The function is required to return a boolean value, for the above-mentioned test case, the java solution returns false whereas the js solution returns true
I am not able to figure out what am I doing wrong in JavaScript, Any help is appreciated.
There is a subtle bug on this line:
const graph = new Array(vertices).fill([]);
This creates only two arrays. new Array(vertices) creates the first new array, and then .fill([]) creates the second and fills the first with references to the second.
So every array in graph is actually the same array. Try running this code to see:
const graph = new Array(5).fill([]);
graph[0].push('hello');
console.log(graph[0][0]); // prints "hello";
console.log(graph[1][0]); // also prints "hello";
console.log(graph[2][0]); // also prints "hello";
console.log(graph[3][0]); // also prints "hello";
console.log(graph[4][0]); // also prints "hello";
You can do this to fix that:
const graph = new Array(vertices).fill().map(() => []);
There may be other problems as well but that's what jumped out at me.
Related
Hi one of my trainer asked me to solve this mysterious question which is related to hashing, and this question is so uncommon that i'm not able to find any good source to solve and learn logic behind it.
Given a string of bytes, which when encoded in hexadecimal notation look like this:
f064b8b61422a3456cb273a474a1fb0cabb04200a6a82a9426bd01f56c97fbf8c4ef58634fd5cf21af29e7db3406de4f886fe71408696789f853af9932a84b79
Find a 4-byte prefix so that, a SHA256 hash of the prefix combined with the original string of bytes, has two last bytes as 0xca, 0xfe.
I tried an attempt. I work with strings I'm sure it's not the most efficient. But Let's see if it works.
async function sha256(message) {
const msgBuffer = new TextEncoder().encode(message);
const hashBuffer = await crypto.subtle.digest('SHA-256', msgBuffer);
const hashArray = Array.from(new Uint8Array(hashBuffer));
const hashHex = hashArray.map(b => b.toString(16).padStart(2, '0')).join('');
return hashHex;
}
function hexToString(hex) {
for (var bytes = [], c = 0; c < hex.length; c += 2) {
bytes.push(parseInt(hex.substr(c, 2), 16));
}
return bytes.map(function(byte) {
return String.fromCharCode(byte)
}).join("")
// return bytes;
}
function hex32(val) {
val &= 0xFFFFFFFF;
var hex = val.toString(16).toUpperCase();
return ("00000000" + hex).slice(-8);
}
var str = "f064b8b61422a3456cb273a474a1fb0cabb04200a6a82a9426bd01f56c97fbf8c4ef58634fd5cf21af29e7db3406de4f886fe71408696789f853af9932a84b79";
var original = hexToString(str);
var found = false;
async function search() {
for (var i = 0; i < 0xffffffff; i++) {
var prefix = hexToString(hex32(i))
await sha256(prefix + original).then(function(result) {
// console.log(result.slice(-4))
if (result.slice(-4) == 'cafe') {
console.log(`found a prefix: "${prefix}"`);
found = true;
}
});
if (found) {
break;
}
}
}
search();
all.
I've an issue that I cannot understand why it happens.
I have to download a file that is stored in hex, so I have to read it in hex, convert it in bin and then write it on an Android/iOS device.
To reach that goal, in my React project I read the file from the machine, convert it to bin and then send it to the native code to write the file.
This is my code on React (NOT React native) project.
Here I read the file:
async readFileContent(path: string, isNotBin = true): Promise<string> {
if (this._isDownloadingFile) {
return Promise.reject();
}
let attempts = 0;
let pos = 0;
let fileContent = '';
let fileDownloadCompleted = false;
this.stopped = false;
let contentRead = '';
const chunkRead = [];
while (!fileDownloadCompleted && !this.stopped && attempts < 3) {
try {
const command = this.createReadFileCommand(path, pos);
const response: CommandResponse<FileReadResponse> = await utilityService.timeoutPromise(
this.bridgeService.sendCommand<
FileReadCommand,
FileReadResponse
>(command),
5000
);
if (response.retval == CommandResponseCode.OK) {
let newContent = response.data.data;
contentRead += newContent;
chunkRead.push(response.data);
const bytesCount = parseInt(response.data.count, 10);
const charsCount = bytesCount * 2;
if (response.data.count === "0") {
fileDownloadCompleted = true;
} else if (charsCount < newContent.length) {
newContent = newContent.substr(0, charsCount);
}
pos += bytesCount;
fileContent += this.hex2bin(newContent);
attempts = 0;
} else {
attempts++;
}
} catch {
attempts++;
}
}
this._isDownloadingFile = false;
if (fileDownloadCompleted) {
return Promise.resolve(fileContent);
} else {
return Promise.reject();
}
}
Here I do the translation:
private hex2bin(hex: string): string | string[] | Uint8Array {
const view = new Uint8Array(hex.length / 2);
for (let i = 0; i < hex.length; i += 2) {
view[i / 2] = parseInt(hex.substring(i, i + 2), 16);
}
const bin = String.fromCharCode.apply(String, view);
return bin;
}
Here I send it to the native code:
viewFile(content: string, fileName: string): Promise<ViewFileResult> {
return new Promise<ViewFileResult>((resolve, reject) => {
this.sendNativeCommand('viewFile', [content, fileName]);
this.viewFileResultChange.subscribe(response =>
response !== undefined && response !== null
? resolve(response)
: reject()
);
});
}
Until there it seems all ok.
If I do a console.log(content) in viewFile function, the conten is correct.
But if I print what I receive in native viewFile function, there are a lot of characters added without any reason (that in hex code are equivalent to C2) and some part (not the final one) is cut off.
Does someone have any idea?
If I do a console.log(content) in viewFile function, the conten is correct.
I don't think so. A string in JavaScript is a sequence of UTF-16 chars, that is, a sequence of 2/4/8byte sequences, each one containing a char.
If you need to write a binary file, you should write binary content.
The hex2bin function should convert the hexadecimal string in input to a byte array; that is, it should just return view. The return type of hex2bin should accordingly be changed in Uint8Array.
You will need to change sendNativeContent (which is not shown, AFAICT) to use a binary signature, accepting a content that can be a Uint8Array.
Any conversion of a binary sequence into a JavaScript string is going to permanently mangle the result.
I have code that I am trying to refactor. Im new to javascript so Im tring to make more readable code using functions in libraries like underscore.
The function below can detect when string
contains 3 or more ordered characters such as (234, efg, LmN)
and
when string contains 3 or more repeated (lll, 444, MMm, ###)
const input = "Dfdf123125";
const myStr = input.toLowerCase();
const n = 3;
let isRepeating = false;
let isSequential = false;
for (let i = 0; i < myStr.length; i++) {
if (i + (n - 1) <= myStr.length) {
let isRepeatingTemp = false;
let isSequentialTemp = false;
for (let j = i; j < i + n; j++) {
(myStr.charCodeAt(i) === myStr.charCodeAt(j)) ? isRepeatingTemp = true: isRepeatingTemp = false;
(myStr.charCodeAt(i) === myStr.charCodeAt(j) - (n - 1)) ? isSequentialTemp = true : isSequentialTemp = false;
}
if (isRepeatingTemp) isRepeating = true;
if (isSequentialTemp) isSequential = true;
}
}
Im trying to to see if I can optimize this and make it more readable with underscore and/or even make time/space complexity better. I know this can also be done with regx but im trying to get it done without it.
Instead of the inner for loop, I chunked the string to n using Array.prototype.slice() to see ahead n characters. I used Array.prototype.indexOf() to find if it's sequential based off the abc and num constants(ref). To see if it's repeating, I used Array.prototype.every() that loops through the chunk and check if they're similar and return a boolean based on the expression.
The result gives the output of each instance found, and if it was sequential or repeating.
const input = "Dfdf123125";
function RepSeq(str, n) {
var rep = false;
var seq = false;
var result = [];
const num = '0123456789';
const abc = 'abcdefghijklmnopqrstuvqxyz';
if (str.length < n) return false;
for (var i = 0; i < str.length; i++) {
if (i + n > str.length) break;
var chunk = str.slice(i, i + n);
var seqABC = abc.indexOf(chunk) > -1;
var seq123 = num.indexOf(chunk) > -1;
if (seq123 || seqABC) {
seq = true;
result.push(chunk);
}
if ([...chunk].every(v => v.toLowerCase() === chunk[0].toLowerCase())) {
rep = true;
result.push(chunk);
}
}
return {
repetition: rep,
sequential: seq,
out: result
};
}
console.log(RepSeq(input, 3));
// Output:
// {
// out: ["123"],
// repetition: false,
// sequential: true
// }
With this method, we're peeking at the string one block(i+n) at a time. Ex(n=3):
1. [Dfd]f123125
2. D[fdf]123125
3. Df[df1]23125
4. Dfd[f12]3125
5. Dfdf[123]125 - Sequential!
6. Dfdf1[231]25
7. Dfdf12[312]5
8. Dfdf123[125]
I'm trying to pass an array of strings from JS to C using Emscripten. I pass my array to C but when I try to deference, it does not work, it raises "index out of bounds". I've tried many different things so I'll post the minimal amount of code that can reproduce the issue (at least on my machine!). I'm sure I missed something...
Basically trying to put a string into an array (of strings) and give that to C for printing (I'm doing other stuff of course). Feel free to change the "gmp_" or "mpz_" to your (that's not the problem).
Javascript:
var nbData = 1;
var nbColPerData = 1;
var data = new Uint32Array(nbColPerData);
data[0] = this.i2wasm(this.mod);
var nBytes = data.length * data.BYTES_PER_ELEMENT;
var dataPtr = Module._malloc(nBytes);
var dataHeap = new Uint8Array(Module.HEAP8.buffer,dataPtr,nBytes);
dataHeap.set(new Uint8Array(data.buffer));
// create array of pointers
var pointers = new Uint32Array(nbData);
for (var i =0; i < pointers.length; i++) {
pointers[i] = dataPtr + i * data.BYTES_PER_ELEMENT;
console.log("pointers["+i+"] = " + pointers[i].toString(16));
}
// create pointer array on the heap
var nPointerBytes= pointers.length * pointers.BYTES_PER_ELEMENT;
var pointerPtr = Module._malloc(nPointerBytes);
var pointerHeap = new Uint8Array(Module.HEAP8.buffer, pointerPtr,nPointerBytes);
pointerHeap.set( new Uint8Array(pointers.buffer));
printIntMatrix(pointerHeap,nbData)
Module._free(pointerHeap.byteOffset);
Module._free(dataHeap.byteOffset);
i2wasm (hexadecimal string to int array for wasm, works properly):
return allocate(intArrayFromString(integer),'i8',ALLOC_NORMAL);
C code:
void EMSCRIPTEN_KEEPALIVE printInt(char *hex) {
mpz_t n;
mpz_init(n);
printf("printing INT at %p\n",hex);
/////////////////////////////////////
// HERE IT PANICS !
/////////////////////////////////////
printf("printing INT value: %c\n",*hex);
if (mpz_set_str(n,hex,16) != 0) {
printf("hexadecimal invalid");
return;
}
gmp_printf("printInt: %Zd\n",n);
mpz_clear(n);
}
void EMSCRIPTEN_KEEPALIVE printIntMatrix(char **mat, int n) {
printf("printIntMatrix !!\n");
for(int i = 0; i < n; i++) {
printf("matrix[%d] => \n",i);
printf("matrix[%d] => %p\n",i,mat[i]);
printInt(mat[i]);
printf("matrix[%d] => %p DONE\n",i,mat[i]);
}
}
i2wasm() returns char*, so dataPtr is char**.
And _printIntMatrix(pointerHeap, nbData) means _printIntMatrix(pointerHeap | 0, nbData), eventually it is _printIntMatrix(NULL, nbData).
So if printIntMatrix doesn't need char ***mat, _printIntMatrix(dataPtr, nbData); would work.
i´m trying to bring a simple text parser from Java to Javascript.
The requierement is to transform a given csv file in to another format. The original file list a number of values according to one id in certain lines:
for example:
11111; 12; 23; 23 ;....
11111; 32; 12; 12 ;....
So the first value is an Id and the other values are according to this Id.
Now I need the same file with alle the values according to the one Id in a single line.
the result should be something like:
11111;12; 23; 23; 32; 12; 12 ;....
I already achieved this with a simple Java class:
public static void main(String[] args) throws Exception {
PrintWriter writer = new PrintWriter("t2_lines.csv", "UTF-8");
BufferedReader br = new BufferedReader(new FileReader("t2.csv"));
String previousId="";
String line;
while ((line = br.readLine()) != null) {
String [] words = line.split(";");
String id = words[0];
if (previousId.equals(id)){
// the loop starts at 4 to cut out some unneded values
for(int i=4;i<words.length;i++) {
writer.print(words[i]+";");
}
}else{
writer.println("");
for(String word : words)
writer.print(word+";");
previousId = id;
}
}
br.close();
writer.close();
}
and now I try to rebuild this thing in Javascript by read in a file from the client and present the result in a textfield - but unfortunately i´ve never implemented anything in Javascript before...
This is my approach so far:
window.onload = function () {
var fileInput = document.getElementById('fileInput');
var origFileDisplayArea = document.getElementById('origFileDisplayArea');
var reformatFileDisplayArea= document.getElementById('reformatFileDisplayArea');
fileInput.addEventListener('change', function (e) {
var file = fileInput.files[0];
var textType = /text.*/;
if (file.type.match(textType)) {
var reader = new FileReader();
reader.readAsText(file);
reader.onload = function (e) {
var result = reader.result;
var table = parse(result);
origFileDisplayArea.innerText = table;
}
} else {
origFileDisplayArea.innerText = "File not supported!"
}
});
}
function parse(input) {
var previousId = "";
var table = "";
if (typeof input !== "undefined")
var lines = input.split("\n");
for (var i = 0; i <= lines.length; i++) {
var line = lines[i];
if (typeof line !== "undefined")
var words = line.split(";");
console.log("words length: ", words.length);
for (var j = 0; j <= words.length; j++ ) {
var word = words[j];
if (typeof word !== "undefined") {
word.toString();
var id = words[0];
if (previousId === id) {
for (var jj = 4; jj <=words.length; jj++){
console.log("jj: " + jj)
table += words[jj]+";";
}
}else {
table += "\n";
for (var word in words) {
table += word + ";";
previousId = id;
}
}
}
}
}
return table;
}
But unfortunately i´m stucked now with undefined values and the whole thing took ages to run.
So any hints/help would be greatly appreciated.
Thanks in advance
Yes for the FileReader, I can't see a way to avoid that in this context. That doesn't look like where you have the problem.
As for parse, the split method can use up a lot of memory so I'd avoid using it on the whole file, and for..in is not designed for looping over an Array.
function parse(str_in) {
var i = -1, j = -1,
str_out = '',
last_id = '',
words;
str_in += '\n'; // not sure if necessary - let the last line pass `while`
// loop by seeking out the next new line
// i = old_index + 1
// j = next \n after old_index
// .slice(i, j) gives just the line
while (-1 !== (j = str_in.indexOf('\n', i = j + 1))) {
words = str_in.slice(i, j).split(';')
// loop words to trim whitespace here if you want
if (last_id === words[0]) // throw away first item if on the same id
words = words.slice(1);
else {
last_id = words[0];
if (str_out.length) // lazy prevent first char newline
str_out += '\n';
}
str_out += words.join(';'); // if you trimmed witespace, re-add here
// if you don't have a final semicolon, add it too
}
return str_out;
}
Now
parse('11111; 12; 23; 23 ;\n11111; 32; 12; 12 ;');
// "11111; 12; 23; 23 ; 32; 12; 12 ;"
Alternatively, you might find it easier to write methods similar to what you're used to in Java so you can work with minimal changes, e.g.
function ReadLineGenerator(text) {
var start = -1, end = -1;
return function readLine() {
if (end < start) {
start = end = -1;
return null;
}
start = end + 1;
end = text.indexOf('\n', start);
if (end !== -1)
return text.slice(start, end);
else
return text.slice(start);
};
}
// example usage
var str = 'a\nb\nc',
f = ReadLineGenerator(str),
line;
while (null !== (line = f()))
console.log(line);
// "a", "b", "c" logged
// line === null