NodeJS Zlib support for LZW ("compress") algorithm? - node.js

I've got a Node/ExpressJS server whose client software only has access to the "compress" (LZW) algorithm for de/compression.
As far as I can tell the Node 12.X zlib library does not support LZW. There also don't appear to be any modules in npm that handle LZW in a fast, general way on content larger than a few hundred bytes.
Does anyone know of a way to efficiently and, ideally, natively use LZW on a Node server? Is something in Zlib compatible with LZW? My use case is for data up to a few tens of kilobytes.
Everything is in Docker, so I could install ncompress on the host and use child_process to call it directly, or something, but that seems convoluted.

You could do this without any external library.
These are two LZW encode and decode functions.
function en(c) { var x = "charCodeAt", b, e = {}, f = c.split(""), d
= [], a = f[0], g = 256; for (b = 1; b < f.length; b++) c = f[b], null != e[a + c] ? a += c :(d.push(1 < a.length ? e[a] :ax),
e[a + c] = g, g++, a = c); d.push(1 < a.length ? e[a] :ax);
for (b = 0; b < d.length; b++) d[b] = String.fromCharCode(d[b]);
return d.join(""); }
function de(b) { var a, e = {}, d = b.split(""), c = f = d[0], g = [
c ], h = o = 256; for (b = 1; b < d.length; b++) a =
d[b].charCodeAt(0), a = h > a ? d[b] :e[a] ? e[a] :f + c,
g.push(a), c = a.charAt(0), e[o] = f + c, o++, f = a; return
g.join(""); }
Please note: These functions are for strings only.
Source: https://gist.github.com/JavaScript-Packer/bbf68a4dc0e1fd102221

Related

Problem with spec block in literate haskell file

I have this block of code on my literate haskell file
\end{code}
\paragraph{Valorização}
Codigo em C
\begin{spec}
double co(double x, int n){
double a = 1;
double b = -1 * x * x / 2;
double c = 12;
double d = 18;
for(; n > 0; n--){
a = a + b;
b = b * (-1 * x * x) / c;
c = c + d;
d = 8 + d;
}
return a;
}
\end{spec}
\subsection*{Problema 4}
What's happening is, when using lhs2tex and the pdflatex, what's inside the spec block is being completely ignored, and everything after it is forward, like it has a tab before it... Maybe this is something common? I'm not used to this... First time using it
By the way, if I remove the spec block everything else is formatted correctly
The following answer is based on speculation. If you would provide an MCVE—a short .lhs file that clearly demonstrates the issue—perhaps a better answer could emerge.
I think the issue is that lhs2TeX is not meant for C code. It gets confused by the spec block, thinks that it is Haskell code, and outputs problematic TeX commands. In fact, I can't even get your posted code past pdflatex—the .tex is that broken. You can use a different mechanism to output C code. The minted package should do.
\documentclass{article}
%include lhs2TeX.fmt
\usepackage{minted}
\setlength{\parindent}{0pt}
\begin{document}
Some C code:
\begin{minted}{c}
double co(double x, int n){
double a = 1;
double b = -1 * x * x / 2;
double c = 12;
double d = 18;
for(; n > 0; n--){
a = a + b;
b = b * (-1 * x * x) / c;
c = c + d;
d = 8 + d;
}
return a;
}
\end{minted}
It can be directly translated into Haskell:
\begin{code}
co :: Double -> Int -> Double
co x = worker 1 (-1 * x * x / 2) 12 18
where worker a _ _ _ 0 = a
worker a b c d n = worker (a + b) (b * (-1 * x * x) / c) (c + d) (8 + d) (n - 1)
\end{code}
As you can see, \textit{Haskell} code passes through just fine.
\end{document}
PS: The weird for-loop can be written while(n-- > 0) { ... }, no?

How to do an inline IF array constructor in Chapel?

I'd like to create a subset of a domain based on a conditional. I could do a loop, but I'm looking to see if I can use an inline if.
Just re-creating the array d looks like
var d = {1..8};
var e = [0.875, 0.625, 0.625, 1.0, 0.625, 0.875, 0.625, 0.625];
var p = 0.7;
var vs = for i in d do i;
writeln(" vs: ", vs);
However, I want to extract the d where e[d] < p into vs. Is there an approach like?
vs = [i in d where e[i] < p]
writeln(vs); // {2,3,5,7,8}
This should give you the desired result:
var vs = for i in d do
if e[i] < p then i;
Note that vs is an array and not a domain. If you want a domain that you can use, you should use an associative domain:
var vs : domain(int) = for i in d do
if e[i] < p then i;
This example will turn into something like this:
var vs : domain(int);
for i in d {
if e[i] < p then
vs.add(i);
}

adding strings as numbers

I'm trying to add together two large numbers, stored as strings.
Here's what I have so far:
function addBigNums(a,b){
c = ""; // output
o = 0; // carryover
startLen = a.length-1;
for(i = startLen; i >= 0; i--) {
sum = parseInt(a[i], 10) + parseInt(b[i], 10) + o;
c = (sum % 10) + c;
o = sum >= 10;
}
if(o === true) c = "1" + c;
return c;
}
I'm running into two issues:
1 ) my carry is not always functioning properly, primarily when:
2 ) the numbers length differ.
Right now I think I would have to prepend 0's onto the shorter number in order to get this to function as expected.
Any better alternatives to this?
Simple, straightforward integer addition like you would do it manually:
a = "123456"; // input a
b = "123456"; // input b
c = ""; // target-string
o = 0; // overflow-bit
// traverse string from right to left
for(i = a.length - 1; i >= 0; i--) {
// do the calculation (with overflow bit)
sum = parseInt(a[i]) + parseInt(b[i]) + o;
// prepend resulting digit to target
c = (sum % 10) + c;
// set overflow bit for next round
o = sum >= 10;
}
// prepend another "1" if last overflow-bit is true
if(o == true) c = "1" + c;
If strings a and b are not equal length (but you stated that they are), you should prepend the shorter string with zeros before calculation.
Consider both numbers to be an array of digits. Add them up right-to-left handling overflow flag. Demo. Assuming your numbers are of the same length
function getNumber(len) {
return Array.apply(null, new Array(len)).map(function(){
return Math.floor(Math.random()*9);
}).join('');
}
var len = 600,
a = getNumber(len), //use your numbers here
b = getNumber(len),
flag = 0;
var c = [].reduceRight.call(a, function(acc, val, idx) {
val = +val + (+b.charAt(idx)) + flag;
flag = val / 10 | 0;
val %= 10;
return val + acc;
}, '');
c = (flag ? 1: '') + c;
console.log(a, b, c);

Brute-force transposition decryption - word segmentation

I'm a 2nd year B. Comp. Sci. student and have a cryptography assignment that's really giving me grief. We've been given a text file of transposition-encrypted English phrases and an English dictionary file, then asked to write a program that deciphers the phrases automatically without any user input.
My first idea was to simply brute-force all possible permutations of the ciphertext, which should be trivial. However, I then have to decide which one is the most-likely to be the actual plaintext, and this is what I'm struggling with.
There's heaps of information on word segmentation here on SO, including this and this amongst other posts. Using this information and what I've already learned at uni, here's what I have so far:
string DecryptTransposition(const string& cipher, const string& dict)
{
vector<string> plain;
int sz = cipher.size();
int maxCols = ceil(sz / 2.0f);
int maxVotes = 0, key = 0;
// Iterate through all possible no.'s of cols.
for (int c = 2; c <= maxCols; c++)
{
int r = sz / c; // No. of complete rows if c is no. of cols.
int e = sz % c; // No. of extra letters if c is no. of cols.
string cipherCpy(cipher);
vector<string> table;
table.assign(r, string(c, ' '));
if (e > 0) table.push_back(string(e, ' '));
for (int y = 0; y < c; y++)
{
for (int x = 0; x <= r; x++)
{
if (x == r && e-- < 1) break;
table[x][y] = cipherCpy[0];
cipherCpy.erase(0, 1);
}
}
plain.push_back(accumulate(table.begin(),
table.end(), string("")));
// plain.back() now points to the plaintext
// generated from cipher with key = c
int votes = 0;
for (int i = 0, j = 2; (i + j) <= sz; )
{
string word = plain.back().substr(i, j);
if (dict.find('\n' + word + '\n') == string::npos) j++;
else
{
votes++;
i += j;
j = 2;
}
}
if (votes > maxVotes)
{
maxVotes = votes;
key = c;
}
}
return plain[key - 2]; // Minus 2 since we started from 2
}
There are two main problems with this algorithm:
It is incredibly slow, taking ~30 sec. to decrypt a 80-char. message.
It isn't completely accurate (I'd elaborate on this if I hadn't already taken up a whole page, but you can try it for yourself with the full VC++ 2012 project).
Any suggestions on how I could improve this algorithm would be greatly appreciated. MTIA :-)

Why is this integer not incrementing twice? [duplicate]

This question already has answers here:
C# Increment operator (++) question:Why am i getting wrong output?
(5 answers)
Closed 8 years ago.
I am confused by the results of the code below. Why does 'b' retain a seemingly incorrect value when doing these operations?
int a = 0;
int b = 5;
a = b++;
b = b++;
Console.WriteLine("For b = b++; b=" + b.ToString()); // b should be 7 but it's 6
a = 0;
b = 5;
a = b--;
b = b--;
Console.WriteLine("For b = b--; b=" + b.ToString()); // b should be 3 but it's 4
a = 0;
b = 5;
a = b + 1;
b = b + 1;
Console.WriteLine("For b = b++; b=" + b.ToString());
Output
b=6
b=4
b=6
Can anyone explain this behavior in C# and how it's working?
That's indeed the behavior of postfix operators, as detailed here.
For instance, when you write:
b = b++;
The following happens:
The current value of b is saved,
b is incremented,
The saved value of b is produced by the postfix ++ operator,
The value produced by the operator is assigned to b.
Therefore, b will indeed be assigned its original value, and the incremented value is lost.
Because the ++ and -- operators when placed after the value will evaluate to the value itself, and then increment/decrement the value after the evaluation.
So:
int a = 0;
int b = a++;
After running this code, b will equal 0 and a will equal 1.
This is as opposed to using the operators as prefixes:
int a = 0;
int b = ++a;
After running this code, b will equal 1 and a will equal 1.
This is documented behavior and has been around for a long time.
The instruction a=b++ is stored on the stack but not evaluated because it was not used after that.
To get the correct result, make that instruction have a sense fro example change that line:
Console.WriteLine("For b = b++; b=" + b.ToString());
by that one:
Console.WriteLine("For a = b++; a=" + a.ToString());
Console.WriteLine("For b = b++; b=" + b.ToString()); //should give 7
When you use
int a = 0;
int b = 5;
a = b++;
b = b++;
You set a to be 6, and after that you set b to be 6.
When you write b to commandline, it presents 6 because a was never used when incrementing b.
If you want to use a as well, you'd have to make
int a = 1;
int b = 5;
b = b++;
b += a;
Console.WriteLine("For b = a + b++; b=" + b.ToString());
But overall I don't see any use in this kind of incrementation.

Resources