Here is the Js Code:
n = o.length,
i = "";
for (e = 0; n > e; ++e) e % 3 === 0 && (i += o.substring(e, e + 1));
and C# Code is
int n = newTemp.Length;
string final = "";
for (int e = 0; n > e; ++e)
{
if( e%3==0 )
{
final += newTemp.Substring(e, e + 1);
}
}
but code of C# not giving the same result as JS does.
c# substring is different than js substring.
in js:
text.substring(startIndex, endIndex);
more details
in C#:
text.Substring(startIndex, subtextLength);
More Details
The problem with your C# version is that JS substring takes a start index and an end index, where in C# substring takes a start index and a substring length.
Also, for what your code is doing (only taking a single character), it might be better to do something like this:
int length = inputString.Length;
string result= "";
for (int i = 0; i < length; i++)
{
if (i%3 == 0) result += inputString[i];
}
(The changes to variable names and the for loop are just to make things more readable).
Related
I want to change a string with dashes placed randomly in between groups of characters to a string with dashes in between groups of n characters. I would like to keep this at a worst case of O(n) time complexity. The following soln works but I believe that the string concatenation is slow and would prefer a constant time operation in order to maintain O(n).
//Desired string is 15-678435-555339
let s = "1-5678-43-5555-339"
let newString = ""
let counter = 0
let n = 6
if(s.length === 1 || s.length < k) return s
for(let i = s.length-1; i >= 0; i--){
if(counter === 6) {
counter = 0;
newString = "-" + newString
}
if(s.charAt(i) !== "-") {
counter += 1
newString = s.charAt(i) + newString
}
}
As this is javascript you usually get the most performant solution with the least code, which would be:
function* chunk(iterable, size) {
for(let i = iterable.length; i >= 0; i -= size)
yield iterable.slice(Math.max(0, i - size), i);
}
let result = [...chunk(s.replace(/-/g, ""), 6)].reverse().join("-");
(But thats just speculation, that heavily depends on the engine)
Hmm, I thought that the string concat is expensive, making it well above o(n).
Usually yes, but some very agressive inlining might optimize it away.
If this is a real life problem and not homework with arbitrary constraints, you should just concatenate the strings. On a modern javascript, and especially for short strings like you've got there, this will not present a performance problem under normal conditions.
If you really wanted to minimize the number of strings created, you could construct an integer array of character codes using .charCodeAt(i), and then s = String.fromCharCode.apply(null, arrayOfIntegers). But this isn't something you'd normally have to do.
Not sure what language you are operating in, but most have some concept of a StringBuilder, which is just implemented as an ArrayList of strings underneath and concatenated when you ask for the resulting string - usually via a toString() method.
Here is a Java example: https://ideone.com/vHHdHH
public static void main(String[] args) {
String s = "1-5678-43-5555-339";
StringBuilder sb = new StringBuilder();
int dashPosition = 2;
int count = 0;
char[] ch = s.toCharArray();
for (int i = 0; i < ch.length; i++) {
if (Character.getNumericValue(ch[i]) != -1) {
sb.append(ch[i]);
count++;
if (count % dashPosition == 0) {
sb.append('-');
count = 0;
dashPosition = 6;
}
}
}
if (sb.charAt(sb.length() - 1) == '-') {
sb.deleteCharAt(sb.length() - 1);
}
//Desired string is 15-678435-555339
System.out.println(sb.toString());
}
I have found an algorithm written in js (That I don't know how to code with) then I tried to convert it to python after a conversation with some friends who know js
Javascript
function crack(code) {
var N = '';
var M = '';
for(var i = 0; i < code.length; i++) {
if(i%2 == 0) {
N += code[i];
} else {
M = code[i] + M;
}
}
var key = N + M;
key = window.atob(key);
key = key.substring(2);
return key;
}
Python
import base64
def crack(code):
N = ''
M = ''
i = 0
for letter in code:
i =code.find(letter)
if i%2 == 0:
N += code[i]
else:
M =code[i] + M
key = N + M
key = base64.b64decode(key)
key = key[2:]
print key
As you can see it's the same code but the problem here that not give the same result !!
The string here to try on is:
N=m=NAobdtHRRHwaOuiU8mvcZhWddH5bZhz1MWzLapyR5nibbhG19ynccl3RBXvediCV5mjcbh2d0HubZhW1cWvLM4j8ACxONwi8
After searching for a while about window.atob found this method decodes a string of data which has been encoded by the btoa() method.
Then searched about btoa found this method uses the "A-Z", "a-z", "0-9", "+", "/" and "=" characters to encode the string.
Now what to do to get the same result with python ??
No. It's not the same code.
for(var i = 0; i < code.length; i++) {
if(i%2 == 0) {
is NOT the same as
for letter in code:
i =code.find(letter)
if i%2 == 0:
What happens if all letters in the code is the same?
I didn't look further than this.
I recommend doing a "literal" translation first, and THEN attempting a "Pythonic" modification to the code.
You are searching for the first occurrence of letter in the code, in the line i =code.find(letter). As you want the index, I recommend using enumerate
Result:
import base64
def crack(code):
N = ''
M = ''
i = 0
for i, letter in enumerate(code):
if i%2 == 0:
N += code[i]
else:
M =code[i] + M
key = N + M
key = base64.b64decode(key)
key = key[2:]
print key
Seems correct:
>>> crack('N=m=NAobdtHRRHwaOuiU8mvcZhWddH5bZhz1MWzLapyR5nibbhG19ynccl3RBXvediCV5mjcbh2d0HubZhW1cWvLM4j8ACxONwi8')
http://egyg33k.blogspot.com.eg/2016/08/8-malwarebytes-anti-malware.html
I'm working with a system that integrates a Point of Sell (POS) device, I use chrome serial to scan ports and be able to read credit card data.
The problem I'm facing is that I need to concat the LRC from a string in this format:
STX = '\002' (2 HEX) (Start of text)
LLL = Length of data (doesn't include STX or ETX but command).
Command C50 {C = A message from PC to POS, 50 the actual code that "prints" a message on POS}
ETX = '\003' (3 HEX) (End of text)
LRC = Longitudinal Redundancy Check
A message example would be as follows:
'\002014C50HELLO WORLD\003'
Here we can see 002 as STX, 014 is the length from C50 to D, and 003 as ETX.
I found some algorithms in C# like this one or this one and even this one in Java, I even saw this question that was removed from SO on Google's cache, which actually asks the same as I but had no examples or answers.
I also made this Java algorithm:
private int calculateLRC(String str) {
int result = 0;
for (int i = 0; i < str.length(); i++) {
String char1 = str.substring(i, i + 1);
char[] char2 = char1.toCharArray();
int number = char2[0];
result = result ^ number;
}
return result;
}
and tried passing it to Javascript (where I have poor knowledge)
function calculateLRC2(str) {
var result = 0;
for (var i = 0; i < str.length; i++) {
var char1 = str.substring(i, i + 1);
//var char2[] = char1.join('');
var number = char1;
result = result ^ number;
}
return result.toString();
}
and after following the Wikipedia's pseudocode I tried doing this:
function calculateLRC(str) {
var buffer = convertStringToArrayBuffer(str);
var lrc;
for (var i = 0; i < str.length; i++) {
lrc = (lrc + buffer[i]) & 0xFF;
}
lrc = ((lrc ^ 0xFF) + 1) & 0xFF;
return lrc;
}
This is how I call the above method:
var finalMessage = '\002014C50HELLO WORLD\003'
var lrc = calculateLRC(finalMessage);
console.log('lrc: ' + lrc);
finalMessage = finalMessage.concat(lrc);
console.log('finalMessage: ' + finalMessage);
However after trying all these methods, I still can't send a message to POS correctly. I have 3 days now trying to fix this thing and can't do anything more unless I finish it.
Is there anyone that knows another way to calculate LRC or what am I doing wrong here? I need it to be with Javascritpt since POS comunicates with PC through NodeJS.
Oh btw the code from convertStringToArrayBuffer is on the chrome serial documentation which is this one:
var writeSerial=function(str) {
chrome.serial.send(connectionId, convertStringToArrayBuffer(str), onSend);
}
// Convert string to ArrayBuffer
var convertStringToArrayBuffer=function(str) {
var buf=new ArrayBuffer(str.length);
var bufView=new Uint8Array(buf);
for (var i=0; i<str.length; i++) {
bufView[i]=str.charCodeAt(i);
}
return buf;
}
Edit After testing I came with this algorithm which returns a 'z' (lower case) with the following input: \002007C50HOLA\003.
function calculateLRC (str) {
var bytes = [];
var lrc = 0;
for (var i = 0; i < str.length; i++) {
bytes.push(str.charCodeAt(i));
}
for (var i = 0; i < str.length; i++) {
lrc ^= bytes[i];
console.log('lrc: ' + lrc);
//console.log('lrcString: ' + String.fromCharCode(lrc));
}
console.log('bytes: ' + bytes);
return String.fromCharCode(lrc);
}
However with some longer inputs and specialy when trying to read card data, LRC becomes sometimes a Control Character which in my case that I use them on my String, might be a problem. Is there a way to force LRC to avoid those characters? Or maybe I'm doing it wrong and that's why I'm having those characters as output.
I solved LRC issue by calculating it with the following method, after reading #Jack A.'s answer and modifying it to this one:
function calculateLRC (str) {
var bytes = [];
var lrc = 0;
for (var i = 0; i < str.length; i++) {
bytes.push(str.charCodeAt(i));
}
for (var i = 0; i < str.length; i++) {
lrc ^= bytes[i];
}
return String.fromCharCode(lrc);
}
Explanation of what it does:
1st: it converts the string received to it's ASCII equivalent (charCodeAt()).
2nd: it calculates LRC by doing a XOR operation between last calculated LRC (0 on 1st iteration) and string's ASCII for each char.
3rd: it converts from ASCII to it's equivalent chat (fromCharCode()) and returns this char to main function (or whatever function called it).
Your pseudocode-based algorithm is using addition. For the XOR version, try this:
function calculateLRC(str) {
var buffer = convertStringToArrayBuffer(str);
var lrc = 0;
for (var i = 0; i < str.length; i++) {
lrc = (lrc ^ buffer[i]) & 0xFF;
}
return lrc;
}
I think your original attempt at the XOR version was failing because you needed to get the character code. The number variable still contained a string when you did result = result ^ number, so the results were probably not what you expected.
This is a SWAG since I don't have Node.JS installed at the moment so I can't verify it will work.
Another thing I would be concerned about is character encoding. JavaScript uses UTF-16 for text, so converting any non-ASCII characters to 8-bit bytes may give unexpected results.
I use this code to search and count vowels in the string,
a = "run forest, run";
a = a.split(" ");
var syl = 0;
for (var i = 0; i < a.length - 1; i++) {
for (var i2 = 0; i2 < a[i].length - 1; i2++) {
if ('aouie'.search(a[i][i2]) > -1) {
syl++;
}
}
}
alert(syl + " vowels")
Obviously it should alert up 4 vowels, but it returns 3.
What's wrong and how you can simplify it?
Try this:
var syl = ("|"+a+"|").split(/[aeiou]/i).length-1;
The | ensures there are no edge cases, such as having a vowel at the start or end of the string.
Regarding your code, your if condition needs no i2
if('aouie'.search(a[i]) > -1){
I wonder, why all that use of arrays and nested loops, the below regex could do it better,
var str = "run forest, run";
var matches = str.match(/[aeiou]/gi);
var count = matches ? matches.length : 0;
alert(count + " vowel(s)");
Demo
Try:
a = "run forest, run";
var syl = 0;
for(var i=0; i<a.length; i++) {
if('aouie'.search(a[i]) > -1){
syl++;
}
}
alert(syl+" vowels")
First, the split is useless since you can already cycle through every character.
Second: you need to use i<a.length, this gets the last character in the string, too.
The simplest way is
s.match(/[aeiou]/gi).length
You can use the .match to compare a string to a regular expression. g is global which will run through the entire string. i makes the string readable as upper and lower case.
function getVowels(str) {
var m = str.match(/[aeiou]/gi);
return m === null ? 0 : m.length;
}
BMP being Basic Multilingual Plane
According to JavaScript: the Good Parts:
JavaScript was built at a time when Unicode was a 16-bit character set, so all characters in JavaScript are 16 bits wide.
This leads me to believe that JavaScript uses UCS-2 (not UTF-16!) and can only handle characters up to U+FFFF.
Further investigation confirms this:
> String.fromCharCode(0x20001);
The fromCharCode method seems to only use the lowest 16 bits when returning the Unicode character. Trying to get U+20001 (CJK unified ideograph 20001) instead returns U+0001.
Question: is it at all possible to handle post-BMP characters in JavaScript?
2011-07-31: slide twelve from Unicode Support Shootout: The Good, The Bad, & the (mostly) Ugly covers issues related to this quite well:
Depends what you mean by βsupportβ. You can certainly put non-UCS-2 characters in a JS string using surrogates, and browsers will display them if they can.
But, each item in a JS string is a separate UTF-16 code unit. There is no language-level support for handling full characters: all the standard String members (length, split, slice etc) all deal with code units not characters, so will quite happily split surrogate pairs or hold invalid surrogate sequences.
If you want surrogate-aware methods, I'm afraid you're going to have to start writing them yourself! For example:
String.prototype.getCodePointLength= function() {
return this.length-this.split(/[\uD800-\uDBFF][\uDC00-\uDFFF]/g).length+1;
};
String.fromCodePoint= function() {
var chars= Array.prototype.slice.call(arguments);
for (var i= chars.length; i-->0;) {
var n = chars[i]-0x10000;
if (n>=0)
chars.splice(i, 1, 0xD800+(n>>10), 0xDC00+(n&0x3FF));
}
return String.fromCharCode.apply(null, chars);
};
I came to the same conclusion as bobince. If you want to work with strings containing unicode characters outside of the BMP, you have to reimplement javascript's String methods. This is because javascript counts characters as each 16-bit code value. Symbols outside of the BMP need two code values to be represented. You therefore run into a case where some symbols count as two characters and some count only as one.
I've reimplemented the following methods to treat each unicode code point as a single character: .length, .charCodeAt, .fromCharCode, .charAt, .indexOf, .lastIndexOf, .splice, and .split.
You can check it out on jsfiddle: http://jsfiddle.net/Y89Du/
Here's the code without comments. I tested it, but it may still have errors. Comments are welcome.
if (!String.prototype.ucLength) {
String.prototype.ucLength = function() {
// this solution was taken from
// http://stackoverflow.com/questions/3744721/javascript-strings-outside-of-the-bmp
return this.length - this.split(/[\uD800-\uDBFF][\uDC00-\uDFFF]/g).length + 1;
};
}
if (!String.prototype.codePointAt) {
String.prototype.codePointAt = function (ucPos) {
if (isNaN(ucPos)){
ucPos = 0;
}
var str = String(this);
var codePoint = null;
var pairFound = false;
var ucIndex = -1;
var i = 0;
while (i < str.length){
ucIndex += 1;
var code = str.charCodeAt(i);
var next = str.charCodeAt(i + 1);
pairFound = (0xD800 <= code && code <= 0xDBFF && 0xDC00 <= next && next <= 0xDFFF);
if (ucIndex == ucPos){
codePoint = pairFound ? ((code - 0xD800) * 0x400) + (next - 0xDC00) + 0x10000 : code;
break;
} else{
i += pairFound ? 2 : 1;
}
}
return codePoint;
};
}
if (!String.fromCodePoint) {
String.fromCodePoint = function () {
var strChars = [], codePoint, offset, codeValues, i;
for (i = 0; i < arguments.length; ++i) {
codePoint = arguments[i];
offset = codePoint - 0x10000;
if (codePoint > 0xFFFF){
codeValues = [0xD800 + (offset >> 10), 0xDC00 + (offset & 0x3FF)];
} else{
codeValues = [codePoint];
}
strChars.push(String.fromCharCode.apply(null, codeValues));
}
return strChars.join("");
};
}
if (!String.prototype.ucCharAt) {
String.prototype.ucCharAt = function (ucIndex) {
var str = String(this);
var codePoint = str.codePointAt(ucIndex);
var ucChar = String.fromCodePoint(codePoint);
return ucChar;
};
}
if (!String.prototype.ucIndexOf) {
String.prototype.ucIndexOf = function (searchStr, ucStart) {
if (isNaN(ucStart)){
ucStart = 0;
}
if (ucStart < 0){
ucStart = 0;
}
var str = String(this);
var strUCLength = str.ucLength();
searchStr = String(searchStr);
var ucSearchLength = searchStr.ucLength();
var i = ucStart;
while (i < strUCLength){
var ucSlice = str.ucSlice(i,i+ucSearchLength);
if (ucSlice == searchStr){
return i;
}
i++;
}
return -1;
};
}
if (!String.prototype.ucLastIndexOf) {
String.prototype.ucLastIndexOf = function (searchStr, ucStart) {
var str = String(this);
var strUCLength = str.ucLength();
if (isNaN(ucStart)){
ucStart = strUCLength - 1;
}
if (ucStart >= strUCLength){
ucStart = strUCLength - 1;
}
searchStr = String(searchStr);
var ucSearchLength = searchStr.ucLength();
var i = ucStart;
while (i >= 0){
var ucSlice = str.ucSlice(i,i+ucSearchLength);
if (ucSlice == searchStr){
return i;
}
i--;
}
return -1;
};
}
if (!String.prototype.ucSlice) {
String.prototype.ucSlice = function (ucStart, ucStop) {
var str = String(this);
var strUCLength = str.ucLength();
if (isNaN(ucStart)){
ucStart = 0;
}
if (ucStart < 0){
ucStart = strUCLength + ucStart;
if (ucStart < 0){ ucStart = 0;}
}
if (typeof(ucStop) == 'undefined'){
ucStop = strUCLength - 1;
}
if (ucStop < 0){
ucStop = strUCLength + ucStop;
if (ucStop < 0){ ucStop = 0;}
}
var ucChars = [];
var i = ucStart;
while (i < ucStop){
ucChars.push(str.ucCharAt(i));
i++;
}
return ucChars.join("");
};
}
if (!String.prototype.ucSplit) {
String.prototype.ucSplit = function (delimeter, limit) {
var str = String(this);
var strUCLength = str.ucLength();
var ucChars = [];
if (delimeter == ''){
for (var i = 0; i < strUCLength; i++){
ucChars.push(str.ucCharAt(i));
}
ucChars = ucChars.slice(0, 0 + limit);
} else{
ucChars = str.split(delimeter, limit);
}
return ucChars;
};
}
More recent JavaScript engines have String.fromCodePoint.
const ideograph = String.fromCodePoint( 0x20001 ); // outside the BMP
Also a code-point iterator, which gets you the code-point length.
function countCodePoints( str )
{
const i = str[Symbol.iterator]();
let count = 0;
while( !i.next().done ) ++count;
return count;
}
console.log( ideograph.length ); // gives '2'
console.log( countCodePoints(ideograph) ); // '1'
Yes, you can. Although support to non-BMP characters directly in source documents is optional according to the ECMAScript standard, modern browsers let you use them. Naturally, the document encoding must be properly declared, and for most practical purposes you would need to use the UTF-8 encoding. Moreover, you need an editor that can handle UTF-8, and you need some input method(s); see e.g. my Full Unicode Input utility.
Using suitable tools and settings, you can write var foo = 'π '.
The non-BMP characters will be internally represented as surrogate pairs, so each non-BMP character counts as 2 in the string length.
Using for (c of this) instruction, one can make various computations on a string that contains non-BMP characters. For instance, to compute the string length, and to get the nth character of the string:
String.prototype.magicLength = function()
{
var c, k;
k = 0;
for (c of this) // iterate each char of this
{
k++;
}
return k;
}
String.prototype.magicCharAt = function(n)
{
var c, k;
k = 0;
for (c of this) // iterate each char of this
{
if (k == n) return c + "";
k++;
}
return "";
}
This old topic has now a simple solution in ES6:
Split characters into an array
simple version
[..."π΄ππβπ ππ"] // ["π΄", "π", "π", "β", "π ", "π", "π"]
Then having each one separated you can handle them easily for most common cases.
Credit: DownGoat
Full solution
To overcome special emojis as the one in the comment, one can search for the connection charecter (char code 8205 in UTF-16) and make some modifications. Here is how:
let myStr = "π©βπ©βπ§βπ§ππ"
let arr = [...myStr]
for (i = arr.length-1; i--; i>= 0) {
if (arr[i].charCodeAt(0) == 8205) { // special combination character
arr[i-1] += arr[i] + arr[i+1]; // combine them back to a single emoji
arr.splice(i, 2)
}
}
console.log(arr.length) //3
Haven't found a case where this doesn't work. Comment if you do.
To conclude
it seems that JS uses the 8205 char code to represent UCS-2 characters as a UTF-16 combinations.