What I want to do is encrypt a string with this formula after making it lowercase and removing all the spaces: C_n = P_(n–1) * P_n + P_(n+1)
How do I go about doing this in JS?
assuming assignments for a=1, b=2, .. and that position wraps (meaning pos(-1) = 3 for a 4 letter word).
function encrypt(str) {
str = str.toLowerCase().replace(/[^a-z]/, '');
var len = str.length() - 1;
var P = (n) => {
if (n < 0) n = n+len;
if (n >= len) n = n-len;
return str.charCodeAt(n) - 64;
}
var result = '';
for (var n = 0; n < len, n++) {
var c = P(n-1) * P(n) + P(n+1);
result += String.fromCharCode(c);
}
return result;
}
Related
I have to make a pattern like this:
=========1=========
=======22122=======
====33322122333====
4444333221223334444
I have not found the logic yet. I tried to code it, but the output is different.
Here is the output of my working code snippet:
----1-----
---123----
--12345---
-1234567--
123456789-
function nomor3(input){
let temp = '';
for (let x = 1; x <= input; x++){
for (let y = input ; y > x; y--){
temp += "-";
}
for (let z = 1; z <= (x * 2) - 1; z++){
temp += z;
}
for (let k = input; k >= x; k--){
temp += "-";
}
temp += '\n';
}
return temp
}
console.log(nomor3(5));
The logic for each level - say 4th level - it begins with the digit of the level to the count of the digit, then one less and so on. So line 4 looks like 4444-333-22-1 and backwards (dashes added for demonstration).
So here we build each line like that, starting from the biggest so we know its length so we can center other lines with dashes. We use arrays here and reversing them because it's easier than strings. But lastly we join so we have a string.
function pyramide(level) {
var len = null;
var result = [];
while (level > 0) {
var arr = [];
for (var i = level; i > 1; i--) {
for (var repeat = 0; repeat < i; repeat++) {
arr.push(i)
}
}
var str_level = arr.join("") + "1" + arr.reverse().join("");
if (len === null) {
len = str_level.length;
}
while (str_level.length < len) {
str_level = "-" + str_level + "-";
}
result.push(str_level);
level--;
}
return result.reverse().join("\n");
}
console.log(pyramide(5))
function expandedForm(num) {
let len = num.toString().length;
let n = num.toString().split("");
let result = "";
for (let i = 0; i < len; i++) {
result += n[i] + "0".repeat(len -1 -i).join(" + ");
}
return result;
}
What I am trying to do is to separate numbers like this:
1220 = "1000 + 200 + 20"
221 = "200 + 20 + 1"
I have written the code (not the perfect one) where it gets me all the necessary values but I struggle with joining them together with "+". I tried using .join() but it did not work.
.join works on arrays only
function expandedForm(num) {
let len = num.toString().length;
let n = num.toString().split("");
let result = "";
let arr=[];
for (let i = 0; i < len; i++) {
arr[i] = n[i] + '0'.repeat(len-1-i);
console.log(arr[i]);
}
let ans=arr.join('+');
return ans;
}
console.log(expandedForm(1220))
Although there are a variety of approaches, here are some general tips for you:
Probably don't want to output a 0 term unless the input number is exactly 0 (only a leading 0 term is relevant, because it will be the only such term)
str.split('') can also be [...str]
No need to split a string into an array to access a character str.split('')[0] can also be just str[0]
Might want to assert that num is a whole number.
Make sure you provide enough test cases in your question to fully define the behaviour of your function. (How to handle trailing zeros, interstitial zeros, leading zeros, etc. Whether the input can be a string.)
function expandedForm(num) {
const s = num.toString();
const n = s.length - 1;
const result = [...s]
.map((char, index) => char + '0'.repeat(n - index))
.filter((str, index) => !index || +str)
.join(' + ');
return result;
}
console.log(expandedForm(1220));
console.log(expandedForm(221));
console.log(expandedForm(10203));
console.log(expandedForm(0));
console.log(expandedForm(2n**64n));
Join works with an array, not string. It stringifies two subsequent indexes for all indexes and you can decide what to add between them.
function expandedForm(num) { // num = 321
let len = num.toString().length; // len = 3
let n = num.toString().split(""); // [3,2,1]
let result = [];
for (let i = 0; i < len; i++) {
result.push(n[i] + "0".repeat(len -1 -i)); // pushing till result = ['300','20','10']
}
return num + ' = ' + result.join(' + ');
// connection result[0] + ' + ' result[1] + ' + ' result[2]
}
expandedForm(321); // output: "321 = 300 + 20 + 1"
Here's one way of doing it
let num = 221;
function expandedForm(num) {
let len = num.toString().length;
let n = num.toString().split("");
let result = "";
for (let i = 0; i < len; i++) {
let t = "0"
t = t.repeat(len-1-i)
if(result.length > 0){
n[i] !== '0'? result += '+'+ n[i] + t : result
} else {
n[i] !== '0'? result += n[i] + t : result
}
}
return result;
}
console.log(expandedForm(2200))
console.log(expandedForm(num))
below would be my approach in a more mathimatical but clean code that you can adjust to your needs.
let result = parseInt(num / 1000);
return result ;
}
function x100( num ) {
num = num % 1000;
let result = parseInt( num / 100);
return result;
}
function x10(num ) {
num = num % 1000;
num = num % 100;
let result = parseInt(num /10);
return result;
}
function x1( num ) {
num = num % 1000;
num = num % 100;
num = num % 10;
return num
}
num = 12150
console.log(num = `1000 x ${x1000(num)}, 100 x ${x100(num)}, 10 x ${x10(num)}`)```
I need my output to look like this:
The best I could achieve was that:
Here is my code:
let pyramidComplete = (rows) => {
let array = [];
let str = '';
for (let i = 1; i <= rows; i++) {
//Add the white space to the left
for (let k = 1; k <= (rows - i); k++) {
str += ' ';
}
//Add the '*' for each row
for (let j = 0; j != (2 * i - 1); j++) {
str += "#".repeat(2 * i - 1);
}
//Add the white space to the right
for (let k = i + 1; k <= rows; k++) {
str += ' ';
}
//Print the pyramid pattern for each row
array.push(str)
str = '';
}
}
pyramidComplete(5);
I thought of assembling a line per loop and then, pushing it into an array but, I can't get the desired result.
The logic is fairly direct: for each row, the number of whitespaces is n - i - 1 where i is the row number. The number of # per row is i + 1. You can produce these substrings using String#repeat. Concatenate the two chunks together per line and use the index argument to Array#map's callback to produce each row.
const pyramid = n => Array(n).fill().map((_, i) =>
" ".repeat(n - i - 1) + "#".repeat(i + 1)
);
console.log(pyramid(5));
If the functions used here are incomprehensible, this can be simplified to use rudimentary language features as follows. It's similar to your approach, but the counts for each character per row are different, I iterate from 0 < n rather than 1 <= n and str should be scoped to the outer loop block.
function pyramid (n) {
var result = [];
for (var i = 0; i < n; i++) {
var line = "";
for (var j = 0; j < n - i - 1; j++) {
line += " ";
}
for (var j = 0; j < i + 1; j++) {
line += "#";
}
result.push(line);
}
return result;
}
console.log(pyramid(5));
If you need a true pyramid (which your current output seems to be shooting for, contrary to the expected output):
const pyramid = n => Array(n).fill().map((_, i) => {
const size = i * 2 + 1;
const pad = n - size / 2;
return " ".repeat(pad) + "#".repeat(size) + " ".repeat(pad);
});
console.log(pyramid(5));
I think you want to do this:
let doc, htm, bod, nav, M, I, mobile, S, Q, CharPyr; // for use on other loads
addEventListener('load', ()=>{
doc = document; htm = doc.documentElement; bod = doc.body; nav = navigator; M = tag=>doc.createElement(tag); I = id=>doc.getElementById(id);
mobile = nav.userAgent.match(/Mobi/i) ? true : false;
S = (selector, within)=>{
var w = within || doc;
return w.querySelector(selector);
}
Q = (selector, within)=>{
var w = within || doc;
return w.querySelectorAll(selector);
}
CharPyr = function(char = '#', className = 'pyr'){
this.char = char; this.className = className;
this.build = (height = 9)=>{
const p = M('div');
p.className = this.className;
for(let i=0,c=this.char,x=c,d; i<height; i++){
d = M('div'); d.textContent = x; p.appendChild(d); x += c;
}
return p;
}
}
// magic happens here
const out1 = I('out1'), out2 = I('out2'), out3 = I('out3'), pyr = new CharPyr;
out1.appendChild(pyr.build(5)); out2.appendChild(pyr.build(7)); out3.appendChild(pyr.build());
}); // end load
*{
box-sizing:border-box;
}
.out{
margin-bottom:7px;
}
.pyr>div{
color:#070; text-align:center;
}
<div class='out' id='out1'></div>
<div class='out' id='out2'></div>
<div class='out' id='out3'></div>
Trying to solve this HackerRank challenge:
Lilah has a string, s, of lowercase English letters that she repeated infinitely many times.
Given an integer, n, find and print the number of letter a's in the first letters of Lilah's infinite string.
For example, if the string s = abcac and n = 10, the substring we consider is abcacabcac, the first 10 characters of her infinite string. There are 4 occurrences of "a" in the substring.
I wrote:
function repeatedString(s, n) {
s = s.repeat(n);
s = s.slice(0, n);
let array = Array.from(s);
let count = 0;
for (let i = 0; i < array.length; i++) {
let char = array[i];
if (char.match(/[a]/gi)) {
count++;
}
}
return count;
}
console.log(repeatedString("abcac", 10));
But HackerRank does not like s = s.repeat(n);, apparently:
I'm not sure how else to generate a string of an appropriate length to slice from. s = s.repeat(Infinity) does not work, and s is not already repeated an infinite number of times when it's passed in as a parameter.
I.e. console.logging(s), initially, logs
abcac
In this case.
I also tried:
function repeatedString(s, n) {
let j = n;
let newString = "";
while (n > 0) {
newString += s;
n--;
}
newString = newString.slice(0, j);
let count = 0;
let array = Array.from(newString);
for (let i = 0; i < array.length; i++) {
let char = array[i];
if (char.match(/[a]/gi)) {
count++;
}
}
return count;
}
console.log(repeatedString("abcac", 10));
But this caused a timeout error.
Any other ideas for how to create a string of valid length to slice from?
EDIT:
Constraints:
1 <= |s| <= 100
1 <= n <= 10^12
For 25% of the test cases, n <= 10^6
actually repeating the string n times is a tremendous waste of memory and runtime.
just compute how often the entire string would be repeated times how many as the string has plus the number of as in the part of s.slice(0, n%s.length)
And your runtime goes down to s.length instead of n
function repeatedString(s, n) {
var r = n % s.length,
m = (n - r) / s.length,
count = 0;
for (var i = 0; i < s.length; ++i) {
if (s[i] === "a") {
count += m + (i < r);
}
}
return count;
}
console.log(repeatedString("abcac", 1234567890));
function repeatedString(s, n) {
var r = n % s.length,
m = (n - r) / s.length,
count = 0;
for (var i = 0; i < s.length; ++i) {
if (s[i] === "a") {
count += m + (i < r);
}
}
return count;
}
console.log(repeatedString("abcac", 1234567890));
I tested this and knows it works. Essentially, I'm not creating a new string, I just find out how many times I have to multiply the original string in order to be able to truncate it. Then I multiply that number by how many a's there were in the original string.
function repeatedString(s, n) {
var charLength = s.length;
var repeat = Math.floor(n/charLength);
var remainder = n%(charLength);
var strCut = s.slice(0, remainder);
let count = 0;
let arrayX = Array.from(s);
for (let i = 0; i < arrayX.length; i++) {
let char = arrayX[i];
if (char.match(/[a]/gi)) {
count++;
}
}
count = count * repeat;
let arrayY = Array.from(strCut);
for (let i = 0; i < arrayY.length; i++) {
let char = arrayY[i];
if (char.match(/[a]/gi)) {
count++;
}
}
return count;
}
console.log(repeatedString("abcac", 10));
I tried a small solution with .repeat but as Thomas said, it's expensive and was taking ages to run tests.
function repeatedString(s, n) {
const allAs = s.match(/a/g);
if (!allAs) {
return 0;
}
if (s === 'a') {
return n;
}
const reps = s.repeat(Math.ceil(n/s.length)).slice(0, n).match(/a/g)
if (!reps) return 0;
return reps.length;
};
console.log(repeatedString('abc', 10));
console.log(repeatedString('abcde', 10));
But I followed Thomas idea and came up with a simpler solution
function repeatedString(s, n) {
const allAs = s.match(/a/g);
if (!allAs) {
return 0;
}
if (s === 'a') {
return n;
}
const rem = n % s.length;
const reps = (n-rem)/s.length;
let count = reps * allAs.length;
if (rem) {
const rest = s.slice(0, rem).match(/a/g);
if (rest) count = count + rest.length
}
return count;
}
console.log(repeatedString('a', 100000));
console.log(repeatedString('abcde', 10000000000));
You could use while loop to repeat original string until length is matched and then match to count the numbers of a.
function repeatedString(s, n) {
let i = 0, l = s.length;
while (s.length < n) s += s[i++ % l]
return s.match(/a/g).length;
}
console.log(repeatedString("abcac", 10));
I did this code and it worked well.
function repeatedString(s, n) {
let modulus = n % s.length;
let repetition = (n - modulus) / s.length;
let remainCounts = s.slice(0, modulus).split("").filter((item) => item == "a").length
return (s.split("").filter((item) => item == "a").length * repetition) + remainCounts
}
enter image description here
I am having an issue with the following code that simulates a card deck.
The deck is created properly (1 array containing 4 arrays (suits) containing 13 elements each (face values)) and when I use the G.test(); function it is correctly pulling 13 random cards but then returns 39x "Empty" (A total of 52).
I hate to ask for help, but I have left the problem overnight and then some and I still cannot find the reason that this is happening. I appreciate any and all insight that can be offered.
var G = {};
G.cards = [[], [], [], []];
G.newCard = function(v) { //currently a useless function, tried a few things
return v;
};
G.deck = {
n: function() { //new deck
var x; var list = [];
list.push(G.newCard("A"));
for (x = 2; x <= 10; x += 1) {
list.push(G.newCard(x.toString()));
}
list.push(G.newCard("J"), G.newCard("Q"), G.newCard("K"));
for (x = 0; x < G.cards.length; x += 1) {
G.cards[x] = list;
}
},
d: function() { //random card - returns suit & value
var s; var c; var v; var drawn = false; var n;
s = random(0, G.cards.length);
c = random(0, G.cards[s].length);
n = 0;
while (!drawn) {
if (G.cards[s].length > 0) {
if (G.cards[s][c]) {
v = G.cards[s].splice(c, 1);
drawn = true;
} else {
c = random(0, G.cards[s].length);
}
} else {
s = (s + 1 >= G.cards.length) ? 0 : s + 1;
n += 1;
console.log(s);
if (n >= G.cards.length) {
console.log(n);
return "Empty";
}
}
}
return {s: s, v: v[0]};
},
}; //G.deck
G.test = function() {
var x; var v;
G.deck.n();
for (x = 0; x < 52; x += 1) {
v = G.deck.d();
console.log(v);
}
};
Replace
for (x = 0; x < G.cards.length; x += 1) {
G.cards[x] = list;
}
with
for (x = 0; x < G.cards.length; x += 1) {
G.cards[x] = list.slice();
}
as this prevents all elements of G.cards[x] binding to the same (single) array instance.
If all elements bind to the same instance, mutating one element equals mutating all elements. list.slice() creates a new copy of list and thus a new array instance to prevent the aforementioned issue.
I won't go through your code, but I built a code that will do what you wanted. I only built this for one deck and not multiple deck play. There are two functions, one will generate the deck, and the other will drawn cards from the deck, bases on how many hands you need and how many cards you wanted for each hand. One a card is drawn, it will not be re-drawn. I might publish a short article for how a card dealing program work or similar in the short future at http://kevinhng86.iblog.website.
function random(min, max){
return Math.floor(Math.random() * (max - min)) + min;
}
function deckGenerate(){
var output = [];
var face = {1: "A", 11: "J", 12: "Q", 13: "K"};
// Heart Space Diamond & Club;
var suit = ["H", "S", "D", "C"];
// Delimiter between card identification and suit identification.
var d = "-";
for(i = 0; i < 4; i++){
output[i] = [];
for(ind = 0; ind < 13; ind++ ){
card = (ind + 1);
output[i][ind] = (card > 10) || (card === 1)? face[card] + d + suit[i] : card.toString() + d + suit[i];
}
}
return output;
}
function randomCard(deck, hand, card){
var output = [];
var randS = 0;
var randC = 0;
if( hand * card > 52 ) throw("Too many card, I built this for one deck only");
for(i = 0; i < hand; i++){
output[i] = [];
for(ind = 0; ind < card; ind++){
randS = random(0, deck.length);
randC = random(0, deck[randS].length);
output[i][ind] = deck[randS][randC];
deck[randS].splice(randC,1);
if(deck[randS].length === 0) deck.splice(randS,1);
}
}
document.write( JSON.stringify(deck, null, 2) );
return output;
}
var deck = deckGenerate()
document.write( JSON.stringify(deck, null, 2) );
document.write("<br><br>");
var randomhands = randomCard(deck, 5, 8);
document.write("<br><br>");
document.write("<br><br>");
document.write( JSON.stringify(randomhands, null, 2) );