Javascript. Wrong comparison output - javascript

fs.readFile('./input.txt', (error, data) => {
if(error)
console.log(error);
const input = data.toString();
const dataArray = input.split(/[\n\r ]+/);
const lastItem = dataArray.length;
let accumulator = 0;
let counter = 0;
for(let i=0; i<lastItem-1; i++) {
let tempArray = dataArray[i];
let splitArray = tempArray.split('x');
let a = splitArray[0];//length
let b = splitArray[1];//width
let c = splitArray[2];//height
let d = a<b? (b<c?c:b) : (a<c?c:a);
let output = 0;
if(d === a)
output = (2*b + 2*c + a*b*c);
else if(d === b)
output = (2*a + 2*c + a*b*c);
else
output = (2*b + 2*a + a*b*c);
accumulator += output;
}})
Input:
3x11x24
13x5x19
1x9x27
This is my code and input. And I want to know why I'm getting wrong comparisons to get the 'd' number. I want 'd' to be the biggest of every 3 numbers in input.
And what is really strange for me is when i want to console.log(a < b) first input which should be true ( because 3 is less than 11 ) but gives me false and I cannot assign any good value to 'd' because I don't know what am I doing wrong with my comparisons.(and I'm using node to execute my code if that gives you any clue what is wrong) Please help :(

In your code a,b,c are strings. You're splitting a string, and you get a string as a result. You need to cast to a number.
let a = +splitArray[0];//length
let b = +splitArray[1];//width
let c = +splitArray[2];
Will cast the string into a number and your comparisons will work

Related

How to increment set of 2 letters based on word occurrences in the range using GAS?

I got this one that looks hairy to me, but I'm confident you guys can crack it while having fun.
The problem:
Check of Company exists in the range
If not, get the latest ID prefix, which looks like AA, AB, etc
Generate a new prefix, which would be the following, according to item above: AC
If that company occurs more than once, then increment the ID number sufix XX001, XX002, etc.
This is what I've come up with so far:
function generateID() {
const ss = SpreadsheetApp.getActiveSpreadsheet();
const clientSheet = ss.getSheetByName('Clients');
const dataRng = clientSheet.getRange(8, 1, clientSheet.getLastRow(), clientSheet.getLastColumn());
const values = dataRng.getValues();
const companies = values.map(e => e[0]);//Gets the company for counting
for (let a = 0; a < values.length; a++) {
let company = values[a][0];
//Counts the number of occurrences of that company in the range
var companyOccurrences = companies.reduce(function (a, b) {
return a + (b == company ? 1 : 0);
}, 0);
if (companyOccurrences > 1) {
let clientIdPrefix = values[a][2].substring(0, 2);//Gets the first 2 letters of the existing company's ID
} else {
//Generate ID prefix, incrementing on the existing ID Prefixes ('AA', 'AB', 'AC'...);
let clientIdPrefix = incrementChar(values[a][2].substring(0,1));
Logger.log('Incremented Prefixes: ' + clientIdPrefix)
}
}
}
//Increment passed letter
var alphabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'.split('')
function incrementChar(c) {
var index = alphabet.indexOf(c)
if (index == -1) return -1 // or whatever error value you want
return alphabet[index + 1 % alphabet.length]
}
...and this is borrowing from tckmn's answer, which deals with one letter only.
This is the expected result:
This is the link to the file, should anyone want to give it a shot.
Thank you!
In your situation, how about the following modification?
Modified script:
// Please run this function.
function generateID() {
const ss = SpreadsheetApp.getActiveSpreadsheet();
const sheet = ss.getSheetByName('Clients');
const dataRng = sheet.getRange(8, 1, sheet.getLastRow() - 7, 1);
const values = dataRng.getValues();
let temp = "";
let init = "";
let count = 0;
const res = values.map(([a], i) => {
count++;
if (temp != a) {
count = 1;
temp = a;
init = i == 0 ? "AA" : wrapper(init);
}
return [`${init}${count.toString().padStart(3, "0")}`];
});
console.log(res)
sheet.getRange(8, 4, res.length, 1).setValues(res);
}
//Increment
var alphabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'.split('')
function incrementChar(c) {
var index = alphabet.indexOf(c)
if (index == -1) return -1 // or whatever error value you want
return alphabet[index + 1 % alphabet.length]
}
// I added this function.
function wrapper(str) {
const [a, b] = [...str];
const r1 = incrementChar(a);
const r2 = incrementChar(b);
return (r2 ? [a, r2] : (r1 ? [r1, "A"] : ["over"])).join("");
}
In this modification, I added a wrapper function. This wrapper function uses your showing script of incrementChar.
When this script is run to your sample Spreadsheet, console.log(res) shows [["AA001"],["AA002"],["AA003"],["AA004"],["AA005"],["AB001"],["AB002"],["AB003"],["AC001"]]. And this value is put to the column "D".
Note:
This modified sample is for your provided Spreadsheet. So please be careful this.
Reference:
map()

How to change (manipulate) char string depend on giving value

i want to ask how to manipulate char in string depends on giving value
my string
"---x---x---x------x"
when im input a value = 2
char "x" was changed to "o" in 2 times
my expected value is
"---o---o---x------x"
thank you in advance
based on solution here:
var str = "---x---x---x------x"
var n = 0
var N = 2
var newStr = str.replace(/x/g,s => n++<N ? 'o' : s)
const x = "---x---x---x------x";
let input = 2;
let output = [];
for (const dashes of x.split("x")) {
output.push(dashes);
if (input > 0) {
input--;
output.push("o");
} else {
output.push("x");
}
}
output.pop();
output = output.join("");
console.log({ output });
You can just loop over the and replace x with o until value becomes 0(which is falsy value)
let str = "---x---x---x------x";
let value = 2;
while (value--) {
str = str.replace("x", "o");
}
console.log(str);

Bringing numbers to the front

(Javascript)
functionName(“2 plus 3 is = 5!”);
would produce following message in console:
235 plus is =
I am unable to bring the numbers to the front, I am a little stumped
function frontNum(str) {
let emptyArr = [];
let rev = str.split("");
let expression = /[\d]/g;
for(let i = 0; i < rev.length; i++) {
if (rev[i].match(expression)) {
emptyArr += rev.pop(rev[i]);
}
}
console.log(emptyArr + rev.join(''));
}
frontNum("2 plus 3 is = 5!");
Since this is your home work I won't give you the correct version, but give you some pointers instead:
your emptyArr is an array, but you are adding data to it as if it was a string.
take a look at this topic, your pop causing problems
you can use your expression to capture all the digits and remove them from the string without need converting the string into array and loop through it (it can be done with 2 lines of code)
a way todo that
'use strict'
function frontNum(str)
{
let s = ''
, n = ''
for (let x of str)
{
if (/[0-9]/.test(x)) n += x
else s += x
}
console.log( n + s.replace(/ +/g,' ') )
}
frontNum('2 plus 3 is = 5!')

Return multiple strings from function based on variable number

I have a string
var str = 'string'
I have a multiplier
var mult = 3
I want to return stringstringstring
The mult will change. Basically mult is kind of like a power but this is a string not a number. And I need to return multiple strings. I'm thinking of looping where mult = the number of times to loop and each would conceptually 'push' but I don't want an array or something like =+ but not a number. I'm thinking I could have the output push to an array the number of times = to mult, and then join the array - but I don't know if join is possible without a delimiter. I'm new at javascript and the below doesn't work but it's what I'm thinking. There's also no ability to input a function in the place I'm running javascript and also no libraries.
var loop = {
var str = 'string'
var arr = [];
var mult = 3;
var i = 0
for (i = 0, mult-1, i++) {
arr.push('string'[i]);
}
}
var finalString = arr.join(''); // I don't know how to get it out of an object first before joining
Not sure if what I want is ridiculous or if it's at all possible
You mean something like below,
var str = 'string'
var mult = 3
var str2 = ''
for(i = 0; i < mult; i++) {
str2 += str
}
console.log(str2)
var str = 'string'
var mult = 3;
var sol =""
while(mult--) {
sol +=str;
}
console.log(sol)
Using resusable function:
const concatStr= (str, mult)=>{
var sol =""
while(mult--) {
sol +=str;
}
console.log(sol)
}
concatStr("string",3)
Using the inbuilt Array.from method:
var str = "string"
var mult = 3
var sol = Array.from({length: mult}, ()=> str).join("")
console.log(sol)
function concatString(str, mult) {
var result = ''
for(i = 0; i < mult; i++) {
result = result.concat(str);
}
return result;
}
const value = concatString('string', 3);
console.log(value);
Also you can use array inbuilt methods,
const mult = 3, displayVal = 'str';
Array(mult).fill(displayVal).join('');
// the string object has a repeat method
console.log('string'.repeat(3));

Find minimum concat number of two strings

Alice has two strings, initial and goal. She can remove some number of characters from initial, which will give her a subsequence of that string. A string with no deletions is still considered a subsequence of itself. Given these two strings, can you find the minimum number of subsequences of initial that, when appended together, will form goal?
Functions
minimumConcat() has two parameters:
initial: the source string that you will get subsequences from
goal: the target string that needs to be formed
Input Format
For some of our templates, we have handled parsing for you. If we do not provide you a parsing function, you will need to parse the input directly. In this problem, our input format is as follows:
The first line is the initial String that we will be generating subsequences from
The second line is the goal String to form
Here is an example of the raw input:
abc
bcbac
Expected Output
Return the number of minimum possible subsequences of initial that can be appended together to form goal.
If there are no possible solutions, return -1.
Example minimumConcat() Input #1
initial: "xyz"
goal: "xzyxz"
Output: 3
function minimumConcat(initial, goal) {
//Put your code here.
return 0;
}
Loop the initial string array to form the goal string array.
function minimumConcat(initial, goal) {
initial = initial.split('');
goal = goal.split('');
let res,count=0;
while(true){
if(goal.length > 0){
res = checkChar(initial,goal);
if(false === res){
return -1;
}
}else{
return count;
}
goal = res;
count++;
}
}
function checkChar(initial,goal){
let started = false;
let foundIndex = 0;
for(let i=0; i<initial.length; i++){
if(initial[i] == goal[foundIndex]){
started = true;
foundIndex++;
}
}
if(started){
return goal.slice(foundIndex);
}else{
return false;
}
}
console.log(minimumConcat('abc','bcbac'));
Here you go!
function minimumConcat(initial, goal) {
let result = 0;
let pattern = '';
let count1 = Array.apply(null, Array(26)).map(Number.prototype.valueOf, 0);
let count2 = Array.apply(null, Array(26)).map(Number.prototype.valueOf, 0);
initial.split('').forEach(c => {
pattern = pattern + c
});
pattern = "^[" + pattern + "]*$";
if (!RegExp(pattern).test(goal)) return -1;
for (let i = 0; i < initial.length; i++) {
count1[initial.charCodeAt(i) - 97]++;
}
for (let i = 0; i < goal.length; i++) {
count2[goal.charCodeAt(i) - 97]++;
}
for (let i = 0; i < 26; i++) {
result += Math.abs(count1[i] - count2[i]);
}
return result;
}
console.log(minimumConcat("abc", "bcbac"));
Since this looks like homework I won't give the solution right away, instead here is a suggestion on how to solve it:
I think the hardest part is finding all the sub-strings if you are using Python that's simplified by itertools as mentioned here.
Edit, I didn't notice the javascript tag, you can get the substring set, without a library, with a couple of for loops.
After having all combinations from initial you can sort them to have the longest first. And then go one by one removing them from goal. Counting every time you remove. If, after iterating over all sub-strings, goal is not an empty string then no subsequence of initial can construct goal.
This answers your question using Java
public static int minimumConcat(String initial, String goal) {
HashSet<Character> set = new HashSet<>();
for(char c : initial.toCharArray()) set.add(c);
for(char c : goal.toCharArray()) {
if(!set.contains(c)) return -1;
}
int j = 0, result = 0;
for(int i = 0; i < goal.length();) {
char c = goal.charAt(i);
while(j < initial.length() && initial.charAt(j) != c) j++;
if(j == initial.length()) {
j = 0;
result++;
} else {
j++;
i++;
}
}
result++;
return result;
}
Here is what I've done with python
def minimumConcat(initial, goal):
#verify that goal has all character of initial
res = 0
for i in goal:
if i in initial:
pass
else:
res=-1;
if res != -1:
while goal!="":
a = removefirstGreatestSubstring(initial,goal)
goal=a["goal"];
if a["has"] ==True :
res=res+1
#find the greatest concat
print(res)
def removefirstGreatestSubstring(initial,goal):
has_subtring = False
start = 0
for car in initial:
if car == goal[start]:
has_subtring= True
start = start+1
finalgoal=goal[start:]
return {"goal": finalgoal, "has":has_subtring}
initial = "abc"
goal = "bcbac"
b = minimumConcat(initial, goal)
I've made it using a different approach with regular expressions.
Here a clean version of the code:
"use strict";
// Solution:
function minimumConcat(initial, goal) {
let result = -1;
let goal_slice = goal;
let exp = "", sub = "";
let initial_concat = "";
let matches = 0, count = 0;
let initial_arr = initial.split('');
for(let i = 0 ; i<initial_arr.length; i++){
for(let j = initial_arr.length ; j>i+1; j--){
sub = initial.slice(i,j);
exp = new RegExp(sub,"ig");
matches = (goal_slice.match(exp) || []).length;
if(matches>=1) {
count +=matches;
initial_concat+=sub.repeat(matches);
goal_slice = goal_slice.slice((goal_slice.lastIndexOf(sub)+sub.length));
}
}
}
result = (initial_concat==goal)? count : result;
return result;
}
// Test cases:
let test_cases = [
{initial:"abc", goal: "abcbc"}, // expected result 2
{initial:"abc", goal: "acdbc"}, // expected result -1
{initial:"bcx", goal: "bcbcbc"}, // expected result 3
{initial:"xyz", goal: "xyyz"}, // expected result 2
]
// Running the tests:
test_cases.forEach(function(item,index){
console.log(minimumConcat(item.initial, item.goal));
});
Also, I've included a debug flag to turn on/off console.log messages in order to anybody could easily understand what is happening on each iteration cycle.
"use strict";
// Shwitch for debugging:
const debug = true;
// Solution:
function minimumConcat(initial, goal) {
let exp = "";
let sub = "";
let match = 0;
let count = 0;
let result = -1;
let goal_slice = goal;
let initial_concat = "";
let initial_arr = initial.split('');
for(let i = 0 ; i<initial_arr.length; i++){
for(let j = initial_arr.length ; j>i+1; j--){
sub = initial.slice(i,j);
exp = new RegExp(sub,"ig");
match = (goal_slice.match(exp) || []).length;
if(match>=1) {
count +=match;
initial_concat+=sub.repeat(match);
goal_slice = goal_slice.slice((goal_slice.lastIndexOf(sub)+sub.length));
}
if(debug){
console.log("-----------------------------");
console.log(" i:", i, " - j:", j);
console.log(" exp:", exp);
console.log(" goal:", goal);
console.log(" goal_slice:", goal_slice);
console.log(" match:",match);
}
}
}
result = (initial_concat==goal)? count : result;
if(debug){
console.log("---RESULTS:--------------------------");
console.log("count:",count);
console.log("goal vs initial_concat: ", goal, " - ", initial_concat);
console.log("result: ", result);
}
return result;
}
// Test cases:
let test_cases = [
{initial:"abc", goal: "abcbc"}, // expected result 2
{initial:"abc", goal: "acdbc"}, // expected result -1
{initial:"bcx", goal: "bcbcbc"}, // expected result 3
{initial:"xyz", goal: "xyyz"}, // expected result 2
]
// Running the tests:
test_cases.forEach(function(item,index){
if(debug){
console.log("-----------------------------");
console.log("TEST CASE #",index,":");
console.table(item);
}
minimumConcat(item.initial, item.goal);
});
here is in php
public function index()
{
$init="abc";
$goal="abacabacabacacb";
$res=$this->minimum($init,$goal);
}
public function check($inital,$goal){
$inital=str_split( $inital);
$goal=str_split( $goal);
for($i=0;$i<sizeof($goal);$i++){
if(!in_array($goal[$i],$inital)){
return -1;
}
}
return 0;
}
public function minimum($inital,$goal){
$res=$this->check($inital,$goal);
if($res==-1){
return -1;
}
$counter=0;
$c=0;
$inital=str_split( $inital);
$goal=str_split( $goal);
for($i=0;$i<sizeof($goal);$i++){
for($j=0;$j<sizeof($inital);$j++){
if(($i+$c)<sizeof($goal)){
echo " ".$i." > ".$j." > ".$c." /// ";
if($goal[$i+$c]==$inital[$j]){
$c+=1;
}
}
}
$counter+=1;
if(($i+$c)>=sizeof($goal)){
break;
}
$c=$c-1;
}
return $counter;
}
Here is my python solution
def check_char(initial, goal):
N = len(initial)
started = False
found_index = 0
for i in range(N):
if (initial[i] == goal[found_index]):
started = True
found_index += 1
if(started):
return goal[found_index:]
else:
return '-'
def minimumConcat(initial, goal):
res = 0
count = 0
while(True):
if( len(goal) > 0 ):
res = check_char(initial, goal)
if(res == '-'):
print(-1)
break;
else:
print(count)
break;
goal = res
count += 1
initial = input()
goal = input()
minimumConcat(initial, goal)

Categories