Every solution I've found uses the following object.
function converter(num) {
var romanKeys =
{M:1000,CM:900,D:500,CD:400,C:100,XC:90,L:50,XL:40,X:10,IX:9,V:5,IV:4,I:1}
When attempting the problem myself, I wasn't too sure which roman numerals were redundant when constructing the object. Procedurally, how do we arrive to this object? e.g How do I know that
"VI: 6" is unnecessary but "IV: 4" is?
When a symbol appears after a larger (or equal) symbol it is added
Example: VI = V + I = 5 + 1 = 6
Example: LXX = L + X + X = 50 + 10 + 10 = 70
But if the symbol appears before a larger symbol it is subtracted
Example: IV = V − I = 5 − 1 = 4
Example: IX = X − I = 10 − 1 = 9
I can be placed before V (5) and X (10) to make 4 and 9.
X can be placed before L (50) and C (100) to make 40 and 90.
C can be placed before D (500) and M (1000) to make 400 and 900.
When you are scanning a roman number you are looking from left to right at each symbol and if it appears before a larger symbol, you take them together, do the substraction and add it to the result, then move to the symbol after them. Otherwise you take a single symbol and add its value to the result and move to the next symbol.
For example for XIV:
1) result = 0
2) X < I => result += 10 (result = 10)
3) I < V => result += (5-1) (result = 14)
Note that if you are using that mapping, you only need the combinations where the second symbol is greater than the first one for which the substraction rule applies, as noted above (CM, CD, XC, XL, IX, IV).
Having something like XI in that mapping would give you a wrong result. For XIV you will have XI (11) + V (5) = 16, not X (10) + IV (4) = 14.
I want convert a integer form base 10 to base 42 in Javascript,
by default Javascript can do to base 36 not more.
How can I do to resolve this problem ?
To begin you need some sort of symbol system to represent digits. In base 10 we have 10: 0 - 9. In base 16 you have 16 0 - 9 and A – F. Binary, of course you only have 2: 0 and 1.
So for base 42 you'll need 42 types of digit. Since this just seems like an exercise maybe include upper and lower case digits (I'm sure there's a better scheme if you put your mind to it):
const symbols = "0 1 2 3 4 5 6 7 8 9 A B C D E F G H I J K L M N O P Q R S T U V W X Y Z a b c d e f".split(" ")
So the numbers 0 - 41 will be 0 through f. 42 will start at 10 42**2 will be 100 etc.
To get the right-most digit, you can can take the number modulus the base. Then divide by the base (and take the floor) and do it again until your number is reduced to zero. With the above scheme here is counting to 100 base 42:
const symbols = "0 1 2 3 4 5 6 7 8 9 A B C D E F G H I J K L M N O P Q R S T U V W X Y Z a b c d e f".split(" ")
function toBase(n, base){
if (n === 0 ) return symbols[n]
res = ""
while (n) {
res = symbols[n % base] + res
n = Math.floor(n / base)
}
return res
}
console.log(Array.from({length: 100}, (_, i) => toBase(i, 42)).join(", "))
I answered a question yesterday and it got my mind thinking about an interesting (to me) puzzle
With the restriction of using lambdas, numbers, and + only (no if, ?:, or other language features), the goal is to implement some f and some g such that
// contract
f(x) => f'
g(y) => g'
f'(g') == g'(f')
// or more simply:
m(n) == n(m)
Here's what I came up with so far - this code is in JavaScript for the purpose of being able to demonstrate the code in the browser but answers in any functional language are acceptable (racket, clojure, ocaml, lambda calc, etc)
// f
const f = x => k =>
k(y => y + x)
// g
const g = y => k =>
k(x => x + y)
// make instance of each
const a = f(1)
const b = g(2)
console.log(a(b))
// x => x + y1
// should be 3
console.log(b(a))
// y => y + x2
// should be 3
I was able to fix one half of relationship, but the other side remains broken due f and g now being asymmetrical
// f
const f = x => k =>
k(y => y(x))
// g
const g = y => k =>
k(x => x + y)
// make instance of each
const a = f(1)
const b = g(2)
console.log(a(b))
// 3
// should be 3 (OK)
console.log(b(a))
// y => y + x2
// should be 3
I know why it's not working but I'm having trouble trying to fix it. Most importantly, if it's not possible, I'd be interested in learning why.
If you come up with a solution that breaks the restrictions, I'm still interested in seeing it ^_^
This answer assumes a strong non-unit type system (eg. Haskell, but I try to stick to JS-like syntax here).
If we stay in the realm of parametricity, we don't need (and cannot even use) numbers or conditions. The constant functions don't change anything, so I'll leave them out and deal with f and g directly.
First, observe that the equation
f(g) == g(f)
implies that both f and g have function types. Assuming both have different inputs we get that f: A -> X and g: B -> X == (A -> X) -> X == ((B -> X) -> X) -> X == ..., ie., you get an infinite type. I remember having read a paper about this exact construction (one can represent it as a pair of types, and I think it forms a category), but unfortunately forgot its name -- maybe there's more to say here.
A simpler solution would be to require A == B. Then f, g: A -> X, but since X == A by the symmetry equation, it follows that f, g: A -> A -- for arbitrary A, that is. One possibilitity fulfilling this is the identity function:
id(id) == id(id)
The other solutions arise when we specialize A to A -> A; then we search for functions of type (A -> A) -> (A -> A). These are, for one, the (specialized) identity function, which has already been found, but also all functions of the shape h => h o ... o h -- compositions ((o) = h => x => h(h(x))) of a function for a number of types. These "add their repetitions" on application, e.g.
(h => h o h)(h => h o h) == (h => h o h) o (h => h o h)
== h => h o h o h o h.
From this we see that we can choose
f == g == h => h,
f == g == h => h o h,
f == g == h => h o h o h,
f == g == ...
which are, I think, all functions of type forall A. (A -> A) -> (A -> A) (excluding nontermination).
There also seems to be a relation of the limit of this construction (infinite composition) to the infinite case mentined above (now in real Haskell):
Prelude> let g = \h -> h . g
<interactive>:11:19:
Occurs check: cannot construct the infinite type: b ~ (b -> c) -> c
This is the closest I've been able to get but it does use a ternary (?:) expression
const f = x => g =>
g === undefined ? x : g() + x
const g = y => f =>
f === undefined ? y : f() + y
const a = f(1)
const b = g(2)
console.log(a(b)) // 3
console.log(b(a)) // 3
Here f is completely equivalent to g and we could easily just use one or the other
const f = x => g =>
g === undefined ? x : g() + x
const a = f(1)
const b = f(2)
console.log(a(b)) // 3
console.log(b(a)) // 3
For this to happen obviously both f and g has to accept a function as an argument and return a same type value. However after tinkering a while it quickly strike me that i am dealing with infinite types.
Well unless your functions are Haskell's id like JS's x => x. So in Haskell i would do;
f :: a -> a
g :: a -> a
f = id
g = id
*Main> f(g)(+3) 2
5
*Main> g(f)(+3) 2
5
Can simply be implemented in JS as well.
I need to send a blob to the server with ajax, but it can end up getting somewhat large, and I'd like to decrease upload time. I've tried jszip already, but that just gave me an empty file inside the zip. I've also tried btoa(), but it turns out that the encoded value just ends up being [object Blob] instead of the actual blob data. What are my options for compressing blobs?
Here was the code I used for jszip:
var zip = new JSZip();
zip.file("recording.wav", blobFile);
var content = zip.generate();
I then appended "content" to a FormData object and sent it to the server. On the server side, I decoded the POST data (from base64). The zip file opened just fine, but recording.wav was a 0 length file.
Additionally, I've tried using the LZW implementation found here. This was the additional code I used to compress it:
var compressed;
var reader = new FileReader();
reader.onload = function(event){
compressed = LZW.compress(event.target.result);
};
reader.readAsText(blobFile);
However, decompressing it returns null.
Caveat: compressing things like audio files would be better done using an algorithm meant specifically for that type of data, perhaps something lossy. However, knowing how hard it was to find a reasonable lossless implementation as provided below, I'm very concerned that it will be hard to find a good implementation in Javascript for that type of data specifically that meets your needs.
In any case, I've had this general need for compression/decompression in Javascript as well, and I needed the same algorithm to work both client (browser) and server-side (node.js) and I needed it to work on very large files. I had checked out jszip and I also tried that LZW algorithm among at least five or six others none of which satisfied the requirements. I can't remember what the issue was with each specifically, but suffice to say it is surprisingly hard to find a good and FAST compressor/decompressor in javascript that works both server and client side and handles large files! I tried at least a dozen different implementations of various compression algorithms, and finally settled with this one - it hasn't failed me yet!
UPDATE
This is the original source:
https://code.google.com/p/jslzjb/source/browse/trunk/Iuppiter.js?r=2
By someone named Bear - thanks Bear, whoever you are, you're the best.
It is LZJB: http://en.wikipedia.org/wiki/LZJB
UPDATE 2
Corrected a problem with missing semicolon - should not give the object not a function error any longer.
This implementation stops working on data less than about 80 characters in length. So I updated the example to reflect that.
Realized the base64 encode/decode methods are in fact exposed on the object passed in for this version, so...
Currently seeing what we can do about specific blob types - what for example the best approach would be for a image versus audio etc as that would be useful for JS folks in general... will update here with what is found.
UPDATE 3
There is a much better wrapper around the original Iuppiter source from Bear than the one I posted below. It is written by cscott and on github here: https://github.com/cscott/lzjb
I'll be switching to this one, as it does streams as well.
Below is an example in Node.js of its use with a wav file. But before copying the example, let me give you the terrible news first, at least for this one wav file that I tried:
63128 Jun 19 14:09 beep-1.wav
63128 Jun 19 17:47 beep-2.wav
89997 Jun 19 17:47 beep-2.wav.compressed
So it successfully regenerated the wav (and it played). However, the compressed one appears to be larger than the original. Well shoot. In any case, might be good to try on your data, you never know, you might get lucky. Here's the code I used:
var fs = require('fs');
var lzjb = require('lzjb');
fs.readFile('beep-1.wav', function(err, wav){
// base 64 first
var encoded = wav.toString('base64');
// then utf8 - you don't want to go utf-8 directly
var data = new Buffer(encoded, 'utf8');
// now compress
var compressed = lzjb.compressFile(data, null, 9);
// the next two lines are unnecessary, but to see what kind of
// size is written to disk to compare with the original binary file
var compressedBuffer = new Buffer(compressed, 'binary');
fs.writeFile('beep-2.wav.compressed', compressedBuffer, 'binary', function(err) {});
// decompress
var uncompressed = lzjb.decompressFile(compressed);
// decode from utf8 back to base64
var encoded2 = new Buffer(uncompressed).toString('utf8');
// decode back to binary original from base64
var decoded = new Buffer(encoded2, 'base64');
// write it out, make sure it is identical
fs.writeFile('beep-2.wav', decoded, function(err) {});
});
At the end of the day, I think its going to be too difficult to achieve any level of compression on most forms of binary data that isn't clobbered by the resulting base64 encoding. The days of control characters for terminals still haunt us to this day. You could try upping to a different base, but that has its risks and issues as well.
See this for example:
What is the most efficient binary to text encoding?
And this:
Why don't people use base128?
One thing though, definitely before you accept the answer, please please try it out on your blob, I've mainly used it for compressing utf-8, and I'd like to be sure it works on your specific data.
In any case, here it is!
/**
$Id: Iuppiter.js 3026 2010-06-23 10:03:13Z Bear $
Copyright (c) 2010 Nuwa Information Co., Ltd, and individual contributors.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. Neither the name of Nuwa Information nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
$Author: Bear $
$Date: 2010-06-23 18:03:13 +0800 (星期三, 23 六月 2010) $
$Revision: 3026 $
*/
var fastcompressor = {};
(function (k) {
k.toByteArray = function (c) {
var h = [],
b, a;
for (b = 0; b < c.length; b++) a = c.charCodeAt(b), 127 >= a ? h.push(a) : (2047 >= a ? h.push(a >> 6 | 192) : (65535 >= a ? h.push(a >> 12 | 224) : (h.push(a >> 18 | 240), h.push(a >> 12 & 63 | 128)), h.push(a >> 6 & 63 | 128)), h.push(a & 63 | 128));
return h
};
k.Base64 = {
CA: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",
CAS: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_",
IA: Array(256),
IAS: Array(256),
init: function () {
var c;
for (c = 0; 256 > c; c++) k.Base64.IA[c] = -1, k.Base64.IAS[c] = -1;
c = 0;
for (iS = k.Base64.CA.length; c < iS; c++) k.Base64.IA[k.Base64.CA.charCodeAt(c)] = c, k.Base64.IAS[k.Base64.CAS.charCodeAt(c)] = c;
k.Base64.IA["="] = k.Base64.IAS["="] = 0
},
encode: function (c, h) {
var b, a, d, e, m, g, f, l, j;
b = h ? k.Base64.CAS : k.Base64.CA;
d = c.constructor == Array ? c : k.toByteArray(c);
e = d.length;
m = 3 * (e / 3);
g = (e - 1) / 3 + 1 << 2;
a = Array(g);
for (l = f = 0; f < m;) j = (d[f++] & 255) << 16 | (d[f++] & 255) << 8 | d[f++] & 255, a[l++] = b.charAt(j >> 18 & 63), a[l++] = b.charAt(j >> 12 & 63), a[l++] = b.charAt(j >> 6 & 63), a[l++] = b.charAt(j & 63);
f = e - m;
0 < f && (j = (d[m] &
255) << 10 | (2 == f ? (d[e - 1] & 255) << 2 : 0), a[g - 4] = b.charAt(j >> 12), a[g - 3] = b.charAt(j >> 6 & 63), a[g - 2] = 2 == f ? b.charAt(j & 63) : "=", a[g - 1] = "=");
return a.join("")
},
decode: function (c, h) {
var b, a, d, e, m, g, f, l, j, p, q, n;
b = h ? k.Base64.IAS : k.Base64.IA;
c.constructor == Array ? (d = c, m = !0) : (d = k.toByteArray(c), m = !1);
e = d.length;
g = 0;
for (f = e - 1; g < f && 0 > b[d[g]];) g++;
for (; 0 < f && 0 > b[d[f]];) f--;
l = "=" == d[f] ? "=" == d[f - 1] ? 2 : 1 : 0;
a = f - g + 1;
j = 76 < e ? ("\r" == d[76] ? a / 78 : 0) << 1 : 0;
e = (6 * (a - j) >> 3) - l;
a = Array(e);
q = p = 0;
for (eLen = 3 * (e / 3); p < eLen;) n = b[d[g++]] << 18 | b[d[g++]] <<
12 | b[d[g++]] << 6 | b[d[g++]], a[p++] = n >> 16 & 255, a[p++] = n >> 8 & 255, a[p++] = n & 255, 0 < j && 19 == ++q && (g += 2, q = 0);
if (p < e) {
for (j = n = 0; g <= f - l; j++) n |= b[d[g++]] << 18 - 6 * j;
for (b = 16; p < e; b -= 8) a[p++] = n >> b & 255
}
if (m) return a;
for (n = 0; n < a.length; n++) a[n] = String.fromCharCode(a[n]);
return a.join("")
}
};
k.Base64.init();
NBBY = 8;
MATCH_BITS = 6;
MATCH_MIN = 3;
MATCH_MAX = (1 << MATCH_BITS) + (MATCH_MIN - 1);
OFFSET_MASK = (1 << 16 - MATCH_BITS) - 1;
LEMPEL_SIZE = 256;
k.compress = function (c) {
var h = [],
b, a = 0,
d = 0,
e, m, g = 1 << NBBY - 1,
f, l, j = Array(LEMPEL_SIZE);
for (b = 0; b < LEMPEL_SIZE; b++) j[b] =
3435973836;
c = c.constructor == Array ? c : k.toByteArray(c);
for (b = c.length; a < b;) {
if ((g <<= 1) == 1 << NBBY) {
if (d >= b - 1 - 2 * NBBY) {
f = b;
for (d = a = 0; f; f--) h[d++] = c[a++];
break
}
g = 1;
m = d;
h[d++] = 0
}
if (a > b - MATCH_MAX) h[d++] = c[a++];
else if (e = (c[a] + 13 ^ c[a + 1] - 13 ^ c[a + 2]) & LEMPEL_SIZE - 1, l = a - j[e] & OFFSET_MASK, j[e] = a, e = a - l, 0 <= e && e != a && c[a] == c[e] && c[a + 1] == c[e + 1] && c[a + 2] == c[e + 2]) {
h[m] |= g;
for (f = MATCH_MIN; f < MATCH_MAX && c[a + f] == c[e + f]; f++);
h[d++] = f - MATCH_MIN << NBBY - MATCH_BITS | l >> NBBY;
h[d++] = l;
a += f
} else h[d++] = c[a++]
}
return h
};
k.decompress = function (c,
h) {
var b, a = [],
d, e = 0,
m = 0,
g, f, l = 1 << NBBY - 1,
j;
b = c.constructor == Array ? c : k.toByteArray(c);
for (d = b.length; e < d;) {
if ((l <<= 1) == 1 << NBBY) l = 1, f = b[e++];
if (f & l)
if (j = (b[e] >> NBBY - MATCH_BITS) + MATCH_MIN, g = (b[e] << NBBY | b[e + 1]) & OFFSET_MASK, e += 2, 0 <= (g = m - g))
for (; 0 <= --j;) a[m++] = a[g++];
else break;
else a[m++] = b[e++]
}
if (!("undefined" == typeof h ? 0 : h)) {
for (b = 0; b < m; b++) a[b] = String.fromCharCode(a[b]);
a = a.join("")
}
return a
}
})(fastcompressor);
And if memory serves... here's how you use it:
var compressed = fastcompressor.compress("0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789"); // data less than this length poses issues.
var decompressed = fastcompressor.decompress(compressed);
Rgds....Hoonto/Matt
Also, what I've posted is minified but beautified, and very slightly adapted for ease-of-use. Check the link in the update above for the original stuff.
JS Zip will work fine just correct your syntax..
function create_zip() {
var zip = new JSZip();
zip.add("recording.wav", blobfile);//here you have to give blobFile in the form of raw bits >> convert it in json notation.. or stream ..
zip.add("hello2.txt", "Hello Second World\n");//this is optional..
content = zip.generate();
location.href="data:application/zip;base64," + content;
}
you can add multiple files too..
Just zip.file will become zip.add
and then zip.generate() will do the rest.. as you have done,
or refer old Post its last part of JavaScript, and NativeBridge will be helpful if you can utilize, in this post user records using Objective C that you can ignore, but sends this object using JavaScript and Socket that you can/may utilize..
I hope this will do ... :)
I have a Javascript function like this:
function validateSessionName() {
var session_name = document.getElementById('session_name').value;
var submitButton = document.getElementById('submit');
document.getElementById('session_error').innerHTML='';
submitButton.removeAttribute('disabled');
var filter = /^[A-Za-z0-9]+$/;
if (filter.test(session_name)){
return true;
} else {
document.getElementById('session_error').innerHTML="Invalid Session Name!";
submitButton.setAttribute('disabled', 'disabled');
}
}
This validates that only numbers and alphanumerical characters are entered into the form. However, there might be a case when a session name can consist of !#$#$#(%*. All these characters are available on the keyboard. I don't want my application to accept these weird characters: 工具, which make my application crash. How can I do that? Thanks.
It depends what you mean by "English keyboard" and "weird characters".
You're probably thinking of limiting your input to ASCII characters, but even then you can get "weird" characters such as null, and a host of control characters. Perhaps limiting the characters to the ASCII range [32, 126] is what you're after? (Those are all printable characters that can be input on a US keyboard.)
/^[\x20-\x7E]+$/
The characters that match that regex are (note the leading space):
! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? # A B C D E F G H I J K L M N O P Q R S T U V W X Y Z [ \ ] ^ _ ` a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~
https://blogs.oracle.com/shankar/entry/how_to_handle_utf_8
How to remove invalid UTF-8 characters from a JavaScript string?
Or just google something to this like