Related
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 just came across this problem and thought I would give it a try, but now I'm stuck and need help if possible.
The problem I keep facing is my return is usually off by 1 or 2 but I can't figure out why not. I have traced my code back but still can't figure it out
The problem :
You are to write a program to assist an architect in drawing the skyline of a city. Building are rectangular in shape, the height of each building is represented by an element in a given array.
The above skyline above is represented like
[1,3,2,1,2,1,5,3,3,4,2]
SO FAR HERE IS WHAT I AM WORKING WITH:
const skyline =(H)=> {
let stack = [];
let count = 0;
let height = 0;
const addBlock = (value) => {
if (value > height) {
stack.push(value - height);
height = value;
count += 1;
}
}
const pop = (value) => {
while (value < height) {
height -= stack.pop();
}
if (value > height) {
addBlock(value)
}
}
for (let i = 0; i < H.length; i += 1) {
let value = H[i];
if (value < height) {
pop(value)
} else if (value > height) {
addBlock(value)
}
}
return count
}
skyline([1,3,2,1,2,1,5,3,3,4,2]) //Expect 9
// Test CASES:
let strokes = [1,3,2,1,2,1,5,3,3,4,2] // Expect 9
// let strokes = [5,8] // Expect 8
// let strokes = [1,1,1,1] // Expect 1
skyline(strokes)
Is this the basic algorithm?
* Big eats small (and equal-sized)
* Small reduces big to small
adding the difference
* Count last one standing
Examples:
[5,8]
-> 8 eats 5, count 8
[1,1,1,1]
-> 1 eats 1 eats 1 eats 1
-> count 1
[1,3,2,1,2,1,5,3,3,4,2]
-> 3 eats 1
-> 2 reduces 3 to 2 and adds 3-2
-> 1 reduces 2 to 1 and adds 2-1
-> 2 eats 1
-> 1 reduces 2 to 1 and adds 2-1
-> 5 eats 1
-> 3 reduces 5 to 3 and adds 5-3
-> 3 eats 3
-> 4 eats 3
-> 2 reduces 4 to 2 and adds 4-2
-> count 2
Total: 1 + 1 + 1 + 2 + 2 + 2 = 9
JavaScript code:
function f(A){
let result = 0;
for (let i=1; i<A.length; i++)
result += Math.max(0, A[i-1] - A[i]);
return result + A[A.length-1];
}
console.log(f([1,3,2,1,2,1,5,3,3,4,2]));
console.log(f([5,8]));
console.log(f([1,1,1,1]));
One liner :)
function f(A){
return [0].concat(A).reduce((a,b,i,A) => a + Math.max(0, A[i-1] - b)) + A[A.length-1];
}
the current answer seems to solve the problem presented, additionally I would like to point that a way to tackle this kind of problems is to solve it by hand and take notes on which steps you took to solve it.
In this case, they ask you to draw horizontal lines without picking up the pencil and one way to do that by hand is to do all the posible strokes on the same row before passing on to the next, until there are no rows left to check.
On every row, you will surely check if the current spot (array element) is greater than 0, which means that it is part of the stroke.
Now in more concise words:
While there are rowsLeft I will traverse the array. on every
traversal I will:
check if the current position is greater than 0 which means there is a
newStroke, it also means there are rowsLeft and since you want to keep
moving forward you would like to decrease the current element by one.
then, if there is a newStroke and the current element is 0 (end of the
stroke) or if it is the end of the array, I would add 1 to my numOfStrokes
count and also state that since I have just finished the stroke then there is
no newStroke at the moment.
Well that's what I did to solve the case you posted, I believe you can code it from there and I hope it helps you, then again, bruce's answer seems to be right, I just wanted to add how you could came up with the solution, there are surely many ways f doing it.
function minimalNumberOfSkylinesIn(array) {
if(array.length == 0)
return 0;
let result = array[0];
for(let i=1; i<array.length; ++i) {
let differnce = array[i] - array[i-1];
result += difference > 0 ? difference : 0;
}
return result;
}
Given the triangle of consecutive odd numbers:
1
3 5
7 9 11
13 15 17 19
21 23 25 27 29
// Calculate the row sums of this triangle from the row index (starting at index 1) e.g.:
rowSumOddNumbers(1); // 1
rowSumOddNumbers(2); // 3 + 5 = 8
I tried to solve this using for loops:
function rowSumOddNumbers(n){
let result = [];
// generate the arrays of odd numbers
for(let i = 0; i < 30; i++){
// generate sub arrays by using another for loop
// and only pushing if the length is equal to current j
let sub = [];
for(let j = 1; j <= n; j++){
// if length === j (from 1 - n) keep pushing
if(sub[j - 1].length <= j){
// and if i is odd
if(i % 2 !== 0){
// push the i to sub (per length)
sub.push(i);
}
}
}
// push everything to the main array
result.push(sub);
}
// return sum of n
return result[n + 1].reduce(function(total, item){
return total += item;
});
}
My code above is not working. Basically I was planning to 1st generate an array of odd numbers less than 30. Next I need to create a sub array base on the length of iteration (j) that would from 1 - n (passed). Then finally push it to the main array. And then use reduce to get the sum of all the values in that index + 1 (since the index starts at 1).
Any idea what am I missing and how to make this work?
Most code problems involve some analysis first in order to spot patterns which you can then convert into code. Looking at the triangle, you'll see the sum of each row follows a pattern:
1: 1 === 1 ^ 3
2: 3 + 5 = 8 === 2 ^ 3
3: 7 + 9 + 11 = 27 === 3 ^ 3
... etc
So from the analysis above you can see that your code could probably be simplified slightly - I won't post an answer, but think about using Math.pow.
No need for any loops.
function rowSumOddNumbers(n) {
// how many numbers are there in the rows above n?
// sum of arithmetic sequence...
let numbers_before_n_count = (n - 1) * n / 2;
let first_number_in_nth_row = numbers_before_n_count * 2 + 1;
let last_number_in_nth_row = first_number_in_nth_row + 2 * (n - 1);
// sum of arithmetic sequence again...
return n * (first_number_in_nth_row + last_number_in_nth_row) / 2;
}
I need a Regular expression for Isracard (Israel Credit Card).
Would be very grateful for help, or maybe for some info how to make it.
Format of Isracard 8-9 digits.
ex. Picture of card - http://images.delcampe.com/img_large/auction/000/157/341/572_001.jpg
I found a validation for IsraCard:
<script>
var cardValid=function(cardNo){
var sum = 0, iNum;
for( var i in cardNo+='' ){
iNum = parseInt(cardNo[i]);
sum += i%2?iNum:iNum>4?iNum*2%10+1:iNum*2;
}
return !(sum%10);
};
</script>
Asp vb script IsraCard Credit Card number Validation (8 or 9 digits)
<%
Function IsraCardCheck(strNumber)
comp1 = "987654321"
comp2 = strNumber
srez = 0
if len(comp2) < 9 then comp2 = "0" & comp2
for i = 1 to 9
a = mid(comp1, i, 1)
b = mid(comp2, i, 1)
c = a * b
srez = srez + c
next
if srez mod 11 = 0 then
IsraCheck = true
else
IsraCheck = false
end if
End Function
%>
I just copied the code from there and for more information and details you may want to check the link itself: Anatomy of credit card number formats
Based on what I see here (and without any further guidelines from you on on what an Israel credit card number begins with), this should probably work
(3640|4580)-?([0-9]{4}-?){3}
A simple regex to check if it's a number with 8 or 9 digits:
^[0-9]{8,9}$
Or if a space or dash is allowed between the digits.
^[0-9](?:[ -]?[0-9]){7,8}$
To match for example :
1234-5678-9
1234 5678
1 2 3 4 5 6 7 8 9
1-2-3-4-5-6-7-8
12-34 56-78 9
But a pure regex can't do calculations, like f.e. a modulus check.
So extra code is needed to give a more accurate validation.
Javascript example snippet:
function checkIsracard(creditcardNo){
if(! /^[0-9](?:[ -]?[0-9]){7,8}$/.test(creditcardNo.toString())) return false;
let total = 0;
let cardDigits = creditcardNo.toString().match(/[0-9]/g);
cardDigits.forEach(function(digit, indx){
total += parseInt(digit,10)*(cardDigits.length - indx);
});
return (total%11 === 0);
}
console.log('1234-5678-9:\t'+checkIsracard('1234-5678-9'));
console.log('1234 5679:\t'+checkIsracard('1234 5679'));
console.log('123456789:\t'+checkIsracard(123456789));
console.log('12345679:\t'+checkIsracard(12345679));
console.log('123456781:\t'+checkIsracard('123456781')); // modulus check fail
console.log('12345671:\t'+checkIsracard('12345671')); // modulus check fail
console.log('1234567:\t'+checkIsracard('1234567')); // not enough digits
console.log('1234567890:\t'+checkIsracard('1234567890')); // too many digits
But if the question would be about the 16 digit visa credit card numbers?
For those, the more widely used luhn-algorithm is used.
So that algorithm would be a bit more complicated.
Algorithm explanation: https://web.archive.org/web/20140227235803/http://povolotski.me/2013/09/24/isracard-credit-card-number-validation-2/
function isracardCheck(num) {
if(typeof num !== 'number') num=''+num;
if(num.length < 8 || num.length > 9) return false;
var sum=0;
num.split('').forEach(function(val,key){
sum+=parseInt(val,10)*(num.length-key);
})
return sum % 11 == 0;
}
License: MIT, https://gist.github.com/avimar/e7421f96357bf06acc31d952c7baf84e
Maybe i am just not that good enough in math, but I am having a problem in converting a number into pure alphabetical Bijective Hexavigesimal just like how Microsoft Excel/OpenOffice Calc do it.
Here is a version of my code but did not give me the output i needed:
var toHexvg = function(a){
var x='';
var let="_abcdefghijklmnopqrstuvwxyz";
var len=let.length;
var b=a;
var cnt=0;
var y = Array();
do{
a=(a-(a%len))/len;
cnt++;
}while(a!=0)
a=b;
var vnt=0;
do{
b+=Math.pow((len),vnt)*Math.floor(a/Math.pow((len),vnt+1));
vnt++;
}while(vnt!=cnt)
var c=b;
do{
y.unshift( c%len );
c=(c-(c%len))/len;
}while(c!=0)
for(var i in y)x+=let[y[i]];
return x;
}
The best output of my efforts can get is: a b c d ... y z ba bb bc - though not the actual code above. The intended output is suppose to be a b c ... y z aa ab ac ... zz aaa aab aac ... zzzzz aaaaaa aaaaab, you get the picture.
Basically, my problem is more on doing the ''math'' rather than the function. Ultimately my question is: How to do the Math in Hexavigesimal conversion, till a [supposed] infinity, just like Microsoft Excel.
And if possible, a source code, thank you in advance.
Okay, here's my attempt, assuming you want the sequence to be start with "a" (representing 0) and going:
a, b, c, ..., y, z, aa, ab, ac, ..., zy, zz, aaa, aab, ...
This works and hopefully makes some sense. The funky line is there because it mathematically makes more sense for 0 to be represented by the empty string and then "a" would be 1, etc.
alpha = "abcdefghijklmnopqrstuvwxyz";
function hex(a) {
// First figure out how many digits there are.
a += 1; // This line is funky
c = 0;
var x = 1;
while (a >= x) {
c++;
a -= x;
x *= 26;
}
// Now you can do normal base conversion.
var s = "";
for (var i = 0; i < c; i++) {
s = alpha.charAt(a % 26) + s;
a = Math.floor(a/26);
}
return s;
}
However, if you're planning to simply print them out in order, there are far more efficient methods. For example, using recursion and/or prefixes and stuff.
Although #user826788 has already posted a working code (which is even a third quicker), I'll post my own work, that I did before finding the posts here (as i didnt know the word "hexavigesimal"). However it also includes the function for the other way round. Note that I use a = 1 as I use it to convert the starting list element from
aa) first
ab) second
to
<ol type="a" start="27">
<li>first</li>
<li>second</li>
</ol>
:
function linum2int(input) {
input = input.replace(/[^A-Za-z]/, '');
output = 0;
for (i = 0; i < input.length; i++) {
output = output * 26 + parseInt(input.substr(i, 1), 26 + 10) - 9;
}
console.log('linum', output);
return output;
}
function int2linum(input) {
var zeros = 0;
var next = input;
var generation = 0;
while (next >= 27) {
next = (next - 1) / 26 - (next - 1) % 26 / 26;
zeros += next * Math.pow(27, generation);
generation++;
}
output = (input + zeros).toString(27).replace(/./g, function ($0) {
return '_abcdefghijklmnopqrstuvwxyz'.charAt(parseInt($0, 27));
});
return output;
}
linum2int("aa"); // 27
int2linum(27); // "aa"
You could accomplish this with recursion, like this:
const toBijective = n => (n > 26 ? toBijective(Math.floor((n - 1) / 26)) : "") + ((n % 26 || 26) + 9).toString(36);
// Parsing is not recursive
const parseBijective = str => str.split("").reverse().reduce((acc, x, i) => acc + ((parseInt(x, 36) - 9) * (26 ** i)), 0);
toBijective(1) // "a"
toBijective(27) // "aa"
toBijective(703) // "aaa"
toBijective(18279) // "aaaa"
toBijective(127341046141) // "overflow"
parseBijective("Overflow") // 127341046141
I don't understand how to work it out from a formula, but I fooled around with it for a while and came up with the following algorithm to literally count up to the requested column number:
var getAlpha = (function() {
var alphas = [null, "a"],
highest = [1];
return function(decNum) {
if (alphas[decNum])
return alphas[decNum];
var d,
next,
carry,
i = alphas.length;
for(; i <= decNum; i++) {
next = "";
carry = true;
for(d = 0; d < highest.length; d++){
if (carry) {
if (highest[d] === 26) {
highest[d] = 1;
} else {
highest[d]++;
carry = false;
}
}
next = String.fromCharCode(
highest[d] + 96)
+ next;
}
if (carry) {
highest.push(1);
next = "a" + next;
}
alphas[i] = next;
}
return alphas[decNum];
};
})();
alert(getAlpha(27)); // "aa"
alert(getAlpha(100000)); // "eqxd"
Demo: http://jsfiddle.net/6SE2f/1/
The highest array holds the current highest number with an array element per "digit" (element 0 is the least significant "digit").
When I started the above it seemed a good idea to cache each value once calculated, to save time if the same value was requested again, but in practice (with Chrome) it only took about 3 seconds to calculate the 1,000,000th value (bdwgn) and about 20 seconds to calculate the 10,000,000th value (uvxxk). With the caching removed it took about 14 seconds to the 10,000,000th value.
Just finished writing this code earlier tonight, and I found this question while on a quest to figure out what to name the damn thing. Here it is (in case anybody feels like using it):
/**
* Convert an integer to bijective hexavigesimal notation (alphabetic base-26).
*
* #param {Number} int - A positive integer above zero
* #return {String} The number's value expressed in uppercased bijective base-26
*/
function bijectiveBase26(int){
const sequence = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
const length = sequence.length;
if(int <= 0) return int;
if(int <= length) return sequence[int - 1];
let index = (int % length) || length;
let result = [sequence[index - 1]];
while((int = Math.floor((int - 1) / length)) > 0){
index = (int % length) || length;
result.push(sequence[index - 1]);
}
return result.reverse().join("")
}
I had to solve this same problem today for work. My solution is written in Elixir and uses recursion, but I explain the thinking in plain English.
Here are some example transformations:
0 -> "A", 1 -> "B", 2 -> "C", 3 -> "D", ..
25 -> "Z", 26 -> "AA", 27 -> "AB", ...
At first glance it might seem like a normal 26-base counting system
but unfortunately it is not so simple.
The "problem" becomes clear when you realize:
A = 0
AA = 26
This is at odds with a normal counting system, where "0" does not behave
as "1" when it is in a decimal place other than then unit.
To understand the algorithm, consider a simpler but equivalent base-2 system:
A = 0
B = 1
AA = 2
AB = 3
BA = 4
BB = 5
AAA = 6
In a normal binary counting system we can determine the "value" of decimal places by
taking increasing powers of 2 (1, 2, 4, 8, 16) and the value of a binary number is
calculated by multiplying each digit by that digit place's value.
e.g. 10101 = 1 * (2 ^ 4) + 0 * (2 ^ 3) + 1 * (2 ^ 2) + 0 * (2 ^ 1) + 1 * (2 ^ 0) = 21
In our more complicated AB system, we can see by inspection that the decimal place values are:
1, 2, 6, 14, 30, 62
The pattern reveals itself to be (previous_unit_place_value + 1) * 2.
As such, to get the next lower unit place value, we divide by 2 and subtract 1.
This can be extended to a base-26 system. Simply divide by 26 and subtract 1.
Now a formula for transforming a normal base-10 number to special base-26 is apparent.
Say the input is x.
Create an accumulator list l.
If x is less than 26, set l = [x | l] and go to step 5. Otherwise, continue.
Divide x by 2. The floored result is d and the remainder is r.
Push the remainder as head on an accumulator list. i.e. l = [r | l]
Go to step 2 with with (d - 1) as input, e.g. x = d - 1
Convert """ all elements of l to their corresponding chars. 0 -> A, etc.
So, finally, here is my answer, written in Elixir:
defmodule BijectiveHexavigesimal do
def to_az_string(number, base \\ 26) do
number
|> to_list(base)
|> Enum.map(&to_char/1)
|> to_string()
end
def to_09_integer(string, base \\ 26) do
string
|> String.to_charlist()
|> Enum.reverse()
|> Enum.reduce({0, nil}, fn
char, {_total, nil} ->
{to_integer(char), 1}
char, {total, previous_place_value} ->
char_value = to_integer(char + 1)
place_value = previous_place_value * base
new_total = total + char_value * place_value
{new_total, place_value}
end)
|> elem(0)
end
def to_list(number, base, acc \\ []) do
if number < base do
[number | acc]
else
to_list(div(number, base) - 1, base, [rem(number, base) | acc])
end
end
defp to_char(x), do: x + 65
end
You use it simply as BijectiveHexavigesimal.to_az_string(420). It also accepts on optional "base" arg.
I know the OP asked about Javascript but I wanted to provide an Elixir solution for posterity.
I have published these functions in npm package here:
https://www.npmjs.com/package/#gkucmierz/utils
Converting bijective numeration to number both ways (also BigInt version is included).
https://github.com/gkucmierz/utils/blob/main/src/bijective-numeration.mjs