Javascript Happy Numbers not working - javascript

Here I have a function that should take a number n into the disHappy(n) to check if all
n in [n-0) are happy.
Happy Numbers wikipedia
If I only run happyChecker(n), I can tell that 7 is happy, but disHappy(n) doesn't show it. It is as if it doesn't receive the true. I have used console.log()'s all over the place and happyChecker(n) shows a number that SHOULD return true. When I placed a console.log() above the return true; for if(newNum===1), it showed that it branched into that branch but it just didn't seem to return the true.
function happyChecker(n) {
var arr = [];
var newNum = 0;
//here I split a number into a string then into an array of strings//
num = n.toString().split("");
for (var i = 0; i < num.length; i++) {
arr[i] = parseInt(num[i], 10);
}
//here I square each number then add it to newNum//
for (var i = 0; i < arr.length; i++) {
newNum += Math.pow(arr[i], 2);
}
//here I noticed that all unhappy numbers eventually came into one of these three//
//( and more) numbers, so I chose them to shorten the checking. A temporary solution for sure//
if (newNum === 58 || newNum === 4 || newNum == 37) {
return false;
}
if (newNum === 1) {
return true;
} else {
happyChecker(newNum);
}
}
function disHappy(num) {
for (j = num; j > 0; j--) {
if (happyChecker(j)) {
console.log(j + " is a Happy Number. It's so happy!!!.");
}
}
}

When you recurse, you need to return the value returned:
if (newNum === 1) {
return true;
} else {
return happyChecker(newNum);
}
You also should declare "num" with var.
I'm ordinarily not a "code golfer", but this is a good example of how the (new-ish) iterator utility methods on the Array prototype can clean up code. You can use the .reduce() function to traverse the array of digit characters and do the work of squaring and summing all at once:
var newNum = n.toString()
.split('')
.reduce(function(sum, digit) {
return sum + (+digit * +digit);
}, 0);
The call to .toString() returns a string, then .split('') gives you an array. Then .reduce() starts with an initial sum of 0 and for each element of the array (each digit), it adds to it the square of that digit. (Instead of parseInt() I just used the + unary operator; we know for sure that each string will be a valid number and an integer.)

You need to add return to the happyChecker call.
return happyChecker(newNum);
see:
http://jsfiddle.net/YjgL8/2/

here is my implementation
var getSum = function (n) {
if (!n >= 0) return -1;
var digits = n.toString().split("");
var sum = 0;
for (var i = 0; i < digits.length; i++) {
var digit = parseInt(digits[i], 10);
sum += digit * digit;
}
return sum;
}
/**
* #param {number} n
* #return {boolean}
*/
var isHappy = function(n, visited) {
if (n < 0) return false;
if (n === 1) return true;
if (typeof visited === 'undefined') visited = {};
sum = getSum(n);
if (visited[sum]) return false; // cycle
visited[sum] = true;
return isHappy(sum, visited);
};

Complete Example of finding happy numbers in range of custom number.
function happyNumbers() {
var result = document.getElementById("happy-result")
var inputy = parseInt(document.getElementById("happyValue").value)
result.innerHTML=""
for (i = 1; i < inputy; i++) {
(happy(i, i))
}
}
function happy(value,value2) {
var result = document.getElementById("happy-result")
var lengthNum = value.toString().length;
var resultNumbers = 0
for (var b = 0 ; b < lengthNum; b++) {
resultNumbers = resultNumbers + parseInt(value.toString().charAt(b)) * parseInt(value.toString().charAt(b))
}
if (resultNumbers == 4) {
return false
} else if (resultNumbers == 1) {
result.innerHTML += "<br> happy number " + i
return true
}else{
happy(resultNumbers, value2);
}
}
window.onload=happyNumbers()
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<div class="panel panel-default">
<div class="panel-heading">happy numbers</div>
<div class="panel-body">
<label>Enter the number that you want ot have see happy numbers uo to it</label>
<input id="happyValue" oninput="happyNumbers()" value="100" class="form-control" />
<div id="happy-result"></div>
</div>
</div>

Related

Check Digit Sum Javascript- recursion [duplicate]

This question already has answers here:
Adding digits from a number, using recursivity - javascript
(6 answers)
Closed 8 months ago.
Looking for Javascript solution in recursion to get the sum of all digits in number until single digit come as result
For example, for the number is "55555" the sum of all digits is 25. Because this is not a single-digit number, 2 and 5 would be added, and the result, 7.
I tried the below solution based on the algorithm.
function getSum(n) {
let sum = 0;
while(n > 0 || sum > 9)
{
if(n == 0)
{
n = sum;
sum = 0;
}
sum += n % 10;
n /= 10;
}
return sum;
}
console.log(getSum("55555"));
This would kind of work, but I'm almost sure there's a beautiful one-line solution which I just don't see yet.
function singleDigitSum(str) {
str = [...str].reduce((acc, c) => { return Number(c) + acc }, 0)
while (str.toString().length > 1) {
str = singleDigitSum(str.toString());
}
return str
}
console.log(singleDigitSum("55555"))
Explanation:
As a first step in your function you reassign to the parameter passed to the function the result of a reducer function which sums up all numbers in your String. To be able to use Array.prototype.reduce() function, I'm spreading your str into an array using [...str].
Then, for as often as that reducer returns a value with more than one digit, rinse and repeat. When the while loop exits, the result is single digit and can be returned.
function checSumOfDigit(num, sum = "0") {
if (num.length == 1 && sum.length !== 1) {
return checSumOfDigit(Number(sum) + Number(num) + "", "0");
} else if (num.length == 1) {
return Number(sum) + Number(num);
}
num = num.split("")
sum = Number(sum) + Number(num.pop());
return checSumOfDigit(num.join(""), sum + "")
}
console.log(checSumOfDigit("567"));
console.log(checSumOfDigit("123"));
console.log(checSumOfDigit("55555"));
this code might be help you
If you need a recursion try this one
function CheckDigitSum(number) {
let nums = number.split('');
if (nums.length > 1) {
let sum = 0;
for (let i = 0; i < nums.length; i++) {
sum += Number(nums[i]);
}
return CheckDigitSum(sum.toString());
} else {
return parseInt(nums[0], 10);
}
}
Here you go:
function createCheckDigit(num) {
var output = Array.from(num.toString());
var sum = 0;
if (Array.isArray(output) && output.length) {
for ( i=0; i < output.length; i++){
sum = sum + parseInt(output[i]);
}
if ((sum/10) >= 1){
sum = createCheckDigit(sum);
}
}
return sum;
}
This can be calculated by recursive function.
function createCheckDigit(membershipId) {
// Write the code that goes here.
if(membershipId.length > 1){
var dgts = membershipId.split('');
var sum = 0;
dgts.forEach((dgt)=>{
sum += Number(dgt);
});
//console.log('Loop 1');
return createCheckDigit(sum + '');
}
else{
//console.log('Out of Loop 1');
return Number(membershipId);
}
}
console.log(createCheckDigit("5555555555"));
function checkid(num) {
let sum = 0;
let s = String(num);
for (i = 0; i < s.length; i++) {
sum = sum + Number(s[i]);
}
if(String(sum).length >= 2) return checkid(sum)
else return sum;
}
console.log(checkid(55555);

JavaScript Function Arrays

How would I use a function that returns the sum of a given array while getting the sum of the even numbers and sum the odd numbers? I'm not understanding how that is done. Can someone please explain a little more in depth?
Here is my entire code:
function main()
{
var evenNum = 0;
//need a total Even count
var oddNum = 0;
//need a total Odd count
var counter = 1;
var num = 0;
function isOdd(x) {
if ((num % 2) == 0)
{
return false;
}
else
{
return true;
}
}
function isEven(x) {
if ((num % 2) == 0)
{
return false;
}
else
{
return true;
}
}
for (counter = 1; counter <= 100; counter++)
{
num = Math.floor(1 + Math.random() * (100-1));
var total = 0;
for(var j = 0; j < length; j++)
total += a[j];//Array?
console.log(num);
console.log("The count of even number is " + evenNum);
console.log("The count of odd number is " + oddNum);
return 0;
}
main()
If I understand your question correctly, you need a function that returns two values, one for the sum of even numbers and one for the sum of odd numbers. It's not clear if you use even/odd referring to the index of the array or the values in array.
In both cases you can return an object that contains both values:
function sum(array) {
var evenSum = 0;
var oddSum = 0;
...calculate...
var res = {};
res.evenSum = evenSum;
res.oddSum = oddSum;
return res;
}
Hope this will help

How to find whether specific number of continuous consecutive numbers are contains in a string using javascript?

Suppose I want to know whether a string contains 5 or more continuous consecutive numbers.
var a = "ac39270982"; // False
var a = "000223344998"; // False
var a = "512345jj7"; // True - it contains 12345
var a = "aa456780"; // True - it contains 45678
Is there a RegEx available to accomplish this? Would it also be able to work in the following situation?
var a = "5111213141587"; // True
This should be true because it contains 11,12,13,14,15.
I'm not sure if it is possible to check the provided examples (single-digit, double-digit numbers) as well as larger numbers (triple-digit, etc.).
I took the time to make a 100% Javascript approach to your question. I made it to simply parse each character in the string and do integer only comparison. This works not only for five consecutive integers, but it works for checking for tenths as well (10's, 20's, etc). You can also increase/decrease the number of comparisons if you wish.
A fair warning: despite this method being potentially scalable if coded to look for all kinds of numeric sizes, you'd still be bound by computing power and number of comparisons. That is why I only provided the code for single digits and tenths, I leave it open to you/the community to decide how to expand from here.
jsFiddle
If you happen to need more details about how it works then let me know, I can further clarify its inner workings.
var str = "1111122asdgas222*&^%121314151617bdjfjahdi234bdce56789";
var consecutive = 5; // Number of comparisons
// Single digits
alert("It is " + consecutiveDigits(str, consecutive) + " that " + str + " contains " + consecutive + " consecutive digits.");
// Tenths digits
alert("It is " + consecutiveDigits(str, consecutive) + " that " + str + " contains " + consecutive + " consecutive tenths.");
function consecutiveDigits(str, consecutive){
var curr,
prev,
count = 0;
for(var i = 0; i < str.length; ++i) {
curr = parseInt(str.split('')[i]);
if(isNumeric(curr)) {
if(count === 0){
++count;
}
else if(prev + 1 === curr){
++count;
if(count === consecutive){
return true;
}
}
prev = curr;
}
}
return false;
}
function consecutiveTenths(str, consecutive, iterations){
var curr,
prev,
curr_tenth = 0,
prev_tenth = 0,
count = 0,
count_tenth = 0;
for(var i = 0; i < str.length; ++i) {
curr = parseInt(str.split('')[i]);
if(isNumeric(curr)) {
++count;
if(count === iterations){
curr_digit = (prev * 10) + curr;
alert(count_digit + " " + curr_digit + " " + prev_tenth);
if(count_digit === 0){
++count_digit;
}
else if(curr_tenth === (prev_tenth + 1)){
++count_digit;
if(count_digit === consecutive){
return true;
}
}
prev_digit = curr_digit;
count = 0;
}
else {
prev = curr;
}
}
else {
count = 0;
}
}
}
function isNumeric(n) {
return !isNaN(parseFloat(n)) && isFinite(n);
}
You can build regexp that will validate if it's true or not, but you might have a hard time retrieving the whole consecutive string. That said the RegExp will be a bit cumbersome, but you can create a function to create the regexp needed, depending on parameters wanted. See snippet:
function build_regexp(n) {
var string = "";
for (var i = 0; i <= 14 - n; i++) {
var start_num = i
for (var j = 0; j < n; j++) {
string += (start_num++).toString()
}
string += "|";
}
string = string.replace(/\|$/, '');
return string
}
document.getElementById('check').onclick = function() {
var regex = new RegExp(build_regexp(document.getElementById('cons').value), "g");
document.getElementById('regex').textContent = regex;
document.getElementById('result').innerHTML = (regex.exec(document.getElementById('to_check').value) || "false")
}
<div id="regex"></div>
<div>Enter wanted consecutive numbers: <input id="cons"></input></div>
<div>Enter string to check: <input id="to_check"></input></div>
<button id="check">check</button>
<div id="result"></div>
EDIT: Added a code snippet & fixed bug in numRegex
To answer the general case (i.e. contiguous sequence of arbitrary-length digits), you can do something like this:
http://jsfiddle.net/ksgLzL9u/8/
/* Find a sequence of n > 1 contiguously increasing integers in input
*
* If sequence is found, return an object:
* {
* start: <starting index of the sequence in input>,
* length: <length of the found sequence string>,
* first: <first number in the sequence>
* }
*
* Otherwise, return null
*/
function findSequence(input, n) {
var numRegex = /^(?:0|[1-9][0-9]*)$/;
// Try every starting position
for (var i = 0; i < input.length; ++i) {
// At the current starting position, try every length for the 1st number
for (var firstLen = 1; i + firstLen < input.length - 1; ++firstLen) {
var afterFirst = i + firstLen;
var first = input.slice(i, afterFirst);
// If the first string isn't an integer, move on
if (!numRegex.test(first)) {
continue;
}
// Convert the first string to an integer
var firstInt = parseInt(first, 10);
// Build what the rest of the string should look like following the
// first, in order to get a valid sequence
var rest = "";
for (var j = 1; j < n; ++j) {
rest = rest.concat(firstInt + j);
}
// Compare to what actually follows the starting string; if it
// matches, then we have our sequence; otherwise, continue on
if (input.slice(afterFirst, afterFirst + rest.length) === rest) {
return {
start: i,
length: first.length + rest.length,
first: first
};
}
}
}
return null;
}
$(function() {
function processChange() {
var input = $('#input').val();
var n = parseInt($('#n').val());
if (n > 1 && input.length) {
var result = findSequence(input, n);
if (result) {
$('#result').text(JSON.stringify(result, null, 2));
var afterFirst = result.start + result.first.length;
var afterSeq = result.start + result.length;
$('#highlighted').empty()
.append($('<span/>')
.text(input.slice(0, result.start)))
.append($('<span/>')
.addClass('sequence')
.append($('<span/>')
.addClass('first')
.text(result.first))
.append($('<span/>')
.text(input.slice(afterFirst, afterSeq))))
.append($('<span/>')
.text(input.slice(afterSeq)));
} else {
$('#result').text("No sequence found");
$('#highlighted').empty();
}
} else {
$('#result').text("");
$('#highlighted').empty();
}
}
$('input,n').on("keyup mouseup", processChange);
processChange();
});
#input {
width: 50%;
min-width: 200px;
}
#n {
width: 50px;
}
.highlighted-result {
font-family: monospace;
}
.highlighted-result .sequence {
background-color: yellow;
}
.highlighted-result .first {
border: solid black 1px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<h1>Input</h1>
<div>
<input id="input" type="text" value="111121314155" placeholder="input">
<input id="n" type="number" value="5" placeholder="n">
</div>
<h1>Results</h1>
<div id="highlighted" class="highlighted-result"></div>
<pre id="result"></pre>
I haven't attempted to optimize the solution (e.g. the firstLen iteration can be short-circuited, and the entire rest string doesn't need to be built up), but I left as-is to make the algorithm clearer.
function NstreamsOfNumberN (str) {
for (let i = 0; i < str.length; i++) {
let numBeingConsidered = Number(str[i]);
let numOfComparisonsToBeDone = numBeingConsidered - 1;
for (let j = i; j < numOfComparisonsToBeDone + i; j++) {
if (str[j] != str[j+1]) {break}//compare neigbourin nums
else if ((j - i + 1) === numOfComparisonsToBeDone)
{ let theNwithNstreams = numBeingConsidered
return [str, (theNwithNstreams), true]}
//(j - i + 1) equals num of comparisons that has been done.
}
}
return [str,null,false]
}
NstreamsOfNumberN('334775555583444582')
9 streams of the number 9
8 streams of the number 8
7 streams of the number 7 ...
3 streams of the number 3
2 streams of the number 2.
It is very difficult to do this with regex, but here is a tentative:
One digit
(?:0(?=1)|1(?=2)|2(?=3)|3(?=4)|4(?=5)|5(?=6)|6(?=7)|7(?=8)|8(?=9)){4,}\d
https://regex101.com/r/mw4bvG/1
Two digits
(?:(\d)(?:0(?=(?:\1)1)|1(?=(?:\1)2)|2(?=(?:\1)3)|3(?=(?:\1)4)|4(?=(?:\1)5)|5(?=(?:\1)6)|6(?=(?:\1)7)|7(?=(?:\1)8)|8(?=(?:\1)9))|09(?=10)|19(?=20)|29(?=30)|39(?=40)|49(?=50)|59(?=60)|69(?=70)|79(?=80)|89(?=90)){4,}\d{2}
https://regex101.com/r/Kcl9FC/1
Three digits
(?:(\d{2})(?:0(?=(?:\1)1)|1(?=(?:\1)2)|2(?=(?:\1)3)|3(?=(?:\1)4)|4(?=(?:\1)5)|5(?=(?:\1)6)|6(?=(?:\1)7)|7(?=(?:\1)8)|8(?=(?:\1)9))|(\d)(?:09(?=(?:\2)10)|19(?=(?:\2)20)|29(?=(?:\2)30)|39(?=(?:\2)40)|49(?=(?:\2)50)|59(?=(?:\2)60)|69(?=(?:\2)70)|79(?=(?:\2)80)|89(?=(?:\2)90))|099(?=100)|199(?=200)|299(?=300)|399(?=400)|499(?=500)|599(?=600)|699(?=700)|799(?=800)|899(?=900)){4,}\d{3}
https://regex101.com/r/joeWdR/1
All together
(?:0(?=1)|1(?=2)|2(?=3)|3(?=4)|4(?=5)|5(?=6)|6(?=7)|7(?=8)|8(?=9)){4,}\d|(?:(\d)(?:0(?=(?:\1)1)|1(?=(?:\1)2)|2(?=(?:\1)3)|3(?=(?:\1)4)|4(?=(?:\1)5)|5(?=(?:\1)6)|6(?=(?:\1)7)|7(?=(?:\1)8)|8(?=(?:\1)9))|09(?=10)|19(?=20)|29(?=30)|39(?=40)|49(?=50)|59(?=60)|69(?=70)|79(?=80)|89(?=90)){4,}\d{2}|(?:(\d{2})(?:0(?=(?:\2)1)|1(?=(?:\2)2)|2(?=(?:\2)3)|3(?=(?:\2)4)|4(?=(?:\2)5)|5(?=(?:\2)6)|6(?=(?:\2)7)|7(?=(?:\2)8)|8(?=(?:\2)9))|(\d)(?:09(?=(?:\3)10)|19(?=(?:\3)20)|29(?=(?:\3)30)|39(?=(?:\3)40)|49(?=(?:\3)50)|59(?=(?:\3)60)|69(?=(?:\3)70)|79(?=(?:\3)80)|89(?=(?:\3)90))|099(?=100)|199(?=200)|299(?=300)|399(?=400)|499(?=500)|599(?=600)|699(?=700)|799(?=800)|899(?=900)){4,}\d{3}
https://regex101.com/r/NyCLh6/1

all valid combinations of n-pair of parenthesis

I am learning js now..
I am trying to write a simple js programme..
what I am trying to do is to print all valid combinations of n-pair
of parenthesis(properly opened and closed)
eg (), (()()),(())
i have written the logic can you tell me whether its correct or not
https://jsfiddle.net/e7mcp6xb/
module.exports = Parentheses = (function() {
var _isParenthesesMatch = function(str) {
var parentheses = str.length;
var rightParentheses = '(';
var leftParentheses = ')';
var rightCount = 0;
var leftCount = 0;
for(i=0;i<=str.length;i++){
if(rightParentheses == str.charAt(i))
{
rightCount++;
}
else if(leftParentheses == str.charAt(i))
{
leftCount++;
}
}
if(rightCount == leftCount){
return true;
}
else(rightCount != leftCount){
return false;
}
}
}());
The check is wrong, but You can fix it easily: In each step of the for loop the number of opening parenthesis cannot be smaller than the number of closing ones:
if (rightCount < leftCount)
return false;
The whole function should look like this:
function(str) {
var rightParentheses = '(';
var leftParentheses = ')';
var rightCount = 0;
var leftCount = 0;
for (var i = 0; i <= str.length; i++) {
if (rightParentheses == str.charAt(i))
rightCount++;
else if (leftParentheses == str.charAt(i))
leftCount++;
if (rightCount < leftCount)
return false;
}
return rightCount == leftCount;
}
If You'd like to generate all valid strings, you can use this function:
function nPair(n) {
if (n == 0)
return [""];
var result = [];
for (var i = 0; i < n; ++i) {
var lefts = nPair(i);
var rights = nPair(n - i - 1);
for (var l = 0; l < lefts.length; ++l)
for (var r = 0; r < rights.length; ++r)
result.push("(" + lefts[l] + ")" + rights[r]);
}
return result;
}
// result of nPair(3):
// ["()()()", "()(())", "(())()", "(()())", "((()))"]
Try this, i have modified your code a little bit. Modification and its explanation is marked in comments.
module.exports = Parentheses = (function() {
var _isParenthesesMatch = function(str) {
var parentheses = str.length;
var rightParentheses = '(';
var leftParentheses = ')';
var count=0;
for(i=0;i<str.length;i++){
//this is to check valid combination start always from ( and end with )
if(str.charAt(0)==rightParentheses && str.length-1==leftParentheses)
{
if(rightParentheses == str.charAt(i))
{
count++; //this will calculate how many times rightParentheses is present & increment count by 1
}
else if(leftParentheses == str.charAt(i))
{
count--; //this will simply decrement count to match valid sequence
}
}
if(count==0){
return true;
}
}
}());
Your function is wrong, try checking if left and right parenthesis and balanced:
function isValid(str){
var stripedStr = str.replace(/[^\(\)]+/g, '');
return stripedStr.split('').reduce(function(a, b){
return a > -1 ? b === '(' ? a + 1 : a - 1 : -1;
}, 0) === 0;
}
stripedStr - use replace() to remove any characters that are not ( or ).
split('') - returns an array so we can use reduce.
reduce() - applies a function against an accumulator and each value of the array (from left-to-right) has to reduce it to a single value.
The reduce starts with 0 as initial value and in the reduce function we count parenthesis
(+1 for (, -1 for ) )
Our string is valid if our counter never goes below 0 and we end up with 0.
You can write the reduce function like this too:
function(previousValue, currentValue){
if (previousValue > -1){
if (currentValue === '('){
return previousValue + 1;
} else {
return previousValue - 1;
}
}
return -1;
}
This is equivalent to:
function(a, b){
return a > -1 ? b === '(' ? a + 1 : a - 1 : -1;
}
It is wrong, because your function will return true for this example ))(( or this ())(()

Find the largest palindrome made from the product of two 3-digit numbers - Javascript

Can anyone tell me what's wrong with the code. Find the largest palindrome made from the product of two 3-digit numbers.
function largestPalindrome(){
for(var i =999; i>100; i--){
for(var j = 999; j>100; j--){
var mul = j*i;
if(isPalin(mul)){
return i * j;
}
}
}
}
function isPalin(i){
return i.toString() == i.toString().split("").reverse().join("");
}
console.log(largestPalindrome());
This answer was close to my question
but still i feel the way i am doing the loop it should return me the largest product.
Yours doesn't work properly since it checks 999*999, then 999*998, then 999*997 until it reaches about 999*583. While it doesn't check 997*995 or something closer to the top
which generates a larger number
function largestPalindrome(){
var arr = [];
for(var i =999; i>100; i--){
for(var j = 999; j>100; j--){
var mul = j*i;
if(isPalin(mul)){
arr.push(j * i);
}
}
}
return Math.max.apply(Math, arr);
}
function isPalin(i){
return i.toString() == i.toString().split("").reverse().join("");
}
console.log(largestPalindrome());
Here is another approach, store all palindrome generated by 3 numbers in an array, then use Math.max on the array to get the largest palindrome
I think if you apply maths to the problem you can decrease the guesswork really significantly.
I will write the three digit numbers as 1000 - a and 1000 - b which means the palindrome is 1 000 000 - 1000(a+b) + ab.
First, let's find solutions where ab < 1000. Then the three leftmost digits are 1000 - (a+b) and the three rightmost digits are ab.
Then I will say this is a palindrome with digits x,y,z:
100x+10y+z=ab
100z+10y+x=1000-a-b
thus
99x-99z = ab+a+b-1000
x-z = 1/99(ab+a+b-10)-10
So then (ab+a+b-10) is divisible by 99 and we also know that x and z being digits the left side is between -9 and 0 (the whole shebang is symmetrical so we can presume x <= z) so then 1/99(ab+a+b-10) is between 1 and 9. We can rewrite ab+a+b-10 as ab+a+b+1-11=99p so (a+1)(b+1)=99p+11=11*(9p+1) where p runs between 1 and 9. That's really easy:
for ($p = 1; $p <= 9; $p++) {
$n = 9 * $p + 1;
// This could be vastly optimized further.
for ($j = 1; $j <= $n; $j++) {
if ($n % $j === 0) {
$a = 1001 - $n / $j;
$b = 1001 - 11 * $j;
$test = $a * $b;
if (strrev($test) === (string) $test) {
print "$a $b " . $a * $b . "\n";
}
}
}
}
Now this prints only one solution which is the correct one.
Now we know 906609 is a solution so then is there a solution where ab > 1000 and 1000(a+b) - ab < 93391 ? There is not :)
As explained in #VisioN's comment:
995*583 = 580085 is a palindrome.
993*913 = 906609 is also a (larger) palindrome.
Your code checks 995*583 before 993*913 and exits at the first palindrome found, so it doesn't return the largest palindrome.
Solution: get the largest palindromes starting from 999*999 = 998001 downwards and check if they can be written as xyz*abc.
Or simply use the accepted solution from the question you linked :). Your solution, but instead of returning when you find the first palindrome, check if it is larger than the largest one already found, in which case you need to replace it. You can stop as soon as the largest palindrome is larger than i*999.
A bit more optimized version with comments included. Notice, there is no need of fast return, just store the max and optimize the cycles to not recalculate j*i if i*j has already been checked.
function largestPalindrome() {
var max = 0;
// not using i >= 100 since 100*100 is not palindrome! :)
for (var i = 999; i > 100; i--) {
// because i * j === j * i, no need of both i and j
// to count down from 999
for (var j = i; j > 100; j--) {
var mul = j * i;
if (isPalin(mul) && mul > max) {
max = i * j;
}
}
}
return max;
}
function isPalin(i) {
// adding empty string to i instead using of .toString
// avoids unnecessary wrapping in String object on the left side
i = '' + i;
// don't rely on ==, use === instead
return i === i.split("").reverse().join("");
}
console.log(largestPalindrome());
Suggesting a solution using underscore.js. First, find all palindromes and then loop through them starting from the largest one and return the one which has two 3-digit prime factors.
function isPalindrome(num) {
var str = num.toString();
return str.split('').reverse().join('') === str;
}
function palindromes() {
var max = 999 * 999;
var min = 100 * 100;
return _.select(_.range(max, min, -1), isPalindrome);
}
palindromes().find(function (x) {
if (_.find(_.range(999, 100, -1), function (y) {
return (x % y === 0 && y != x / y && x / y < 1000) ? true : false;
})) return true;
})
#define MAX(a, b) ((a) > (b) ? (a) : (b))
int largestPalindrome()
{
int ret = 0;
for (int i = 999; i > 100; --i)
{
int jLimit = MAX(ret / i, 100);
for (int j = i; j > jLimit; --j)
{
int ans = i * j;
if (isPalin(ans))
{
ret = MAX(ans, ret);
}
}
}
return ret;
}
Reasons explained above.
We can recompute the range of j when we find a palindrome product.This should be faster.
The above solution will work perfectly fine but we will have issue ONLY when we try to find-out what are those 2 numbers (i = 913 and j = 993)
I will just modify the solution proposed by Azder
int max = 0;
int no1 = 0;
int no2 = 0;
// not using i >= 100 since 100*100 is not palindrome! :)
for (var i = 999; i > 100; i--) {
// because i * j === j * i, no need of both i and j
// to count down from 999
for (var j = i; j > 100; j--) {
var mul = j * i;
if (isPalin(mul)) {
if ((i+j) > max) {
max = i+j;
no1 = i; no2 = j;
}
}
}
}
//Now we can get the 2 numbers (no1=993 and no2=913)
return (no1*no2);
This is how I did it. I used the old fashioned way to check for a palindrome. It appears to run faster on my computer but I may be wrong. Pushing to an array, as in the above post, was definitely very slow on my computer. Noticeable lag at the console. I would recommend just checking to see if your product is greater than your current max, if it is, store that instead of pushing everything to an array. Please feel free to correct me if I'm wrong. Much appreciated.
//should find the largest palindrome made from the product of two 3 digit numbers
var largestPalindrome = function() {
var max = 0,
product = 0;
for (var num1 = 999; num1 >= 100; num1--) {
for (var num2 = 999; num2 >= 100; num2--) {
product = num1 * num2;
product > max && isPalindrome(product.toString()) ? max = product : 0;
}
}
return max;
};
//check to see if product is a palindrome
var isPalindrome = function(product) {
var palindromeCheck = true;
for (var i = 0; i < product.length / 2; i++) {
if (product[i] != product[product.length - i - 1])
palindromeCheck = false;
}
return palindromeCheck;
//return product === product.split("").reverse().join("");
};
I think you can go for code given at this link
http://www.mathblog.dk/project-euler-problem-4/
As this save your CPU cycle from multiplication, which is quite costly operation.
Well even in this you can make some more to make to make it more like, you can modify its while loop a bit
while (!found) {
firstHalf--;
palin = makePalindrome(firstHalf);
for (int i = 999; i > 99; i--) {
if ((palin / i) > 999 || i*i < palin) {
break;
}
if ((palin % i == 0)) {
found = true;
factors[0] = palin / i;
factors[1] = i;
break;
}
}
}
So here instead of moving from i=999 : 100, we can write it as i=sqrt(palin):100, as you can find factorial of number within its square root. Refer link How to find Number is prime number or not!
And also you can change if(condition) to if(!(palin%i)) as comparing with zero is usually not considered a good practice also comparing takes more CPU cycle compared to your simple negating bits.
instead of creating an Array or ArrayList to store all palindromes, I just created another variable max and stored highest valued palindrome in it.
My code is in Java, but you can understand the logic from it.
Here is my code to better explain what I said (read comments):
package euler;
import java.util.ArrayList; import java.util.Collections;
public class Problem4 {
public static void main (String[] args)
{
int product=0;
int max=0;
for(int i=999;i>100;i--)
{
for (int j=i;j>100;j--)
{
product=i*j;
if(isPalindrome(product))
{
//Just store maximum value of product.
//Following if loop is required in your code,in place of return i*j;
if(product>max)
{ max=product; }
}
}
}
System.out.println(max);
}
//might be inefficient to create StringBuilder and again String to compare.
public static boolean isPalindrome(int product)
{
boolean isPalindrome=false;
StringBuilder temp = new StringBuilder(Integer.toString(product)).reverse();
if(temp.toString().equals(Integer.toString(product)))
{
isPalindrome=true;
}
return isPalindrome;
}
}
What you are doing is returning and breaking out of the loop as soon as you get the first palindrome. Which in your case is not the maximum value palindrome.
Instead use an if condition and keep a track of maximum values and let the loop continue till end.
I have added the if condition that lets the loop running and registers the value.
Got the correct answer from this code.
PS. Thanks Xan for your input. I guess I could've explained it better first time.
I have seen a lot of posts for this question, this is the solution that i have come up with:
Smallest number that is multiple of two 3 digits number is 10000(100*100)
Largest number that is multiple of two 3 digits number is 998001(999*999)
Our palindrome lies between these two number, write a program to loop through these number and whenever you get a palindrome check whether its perfectly divisible by a 3 digit number and quotient is also a 3 digit number.
Below is my program in C#, the last number that it prints is our required answer, enjoy.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using System.Collections;
namespace E
{
public class Program
{
public static void Main(string[] args)
{
//Your code goes here
for(int i=10000;i<=998001;i++)
{
string s1 = i.ToString();
char[] array = s1.ToCharArray();
Array.Reverse(array);
string s2 = new String(array);
if(s1==s2)
{
for(int j=100;j<=999;j++)
{
if(i%j==0 && i/j <= 999)
{
System.Console.WriteLine(i);
continue;
}
}
}
}
System.Console.WriteLine("done");
}
}
}
I believe this should be optimal
#include <functional>
#include <algorithm>
#include <iostream>
using namespace std;
template <typename T>
bool IsPalindrome(const T num) {
T reverse = 0;
T n = num;
while (n > 0) {
reverse = (reverse * 10) + n % 10;
n /= 10;
}
return reverse == num;
}
template <typename T = long long int>
T LongestPalindromeFromProductOfNDigitNums(int n) {
T result = 0, val = 0, max_n_digit_num = std::pow(10, n)-1,
least_n_digit_num = std::pow(10, n-1);
int n_checks = 0;
for (T i = max_n_digit_num; i >= least_n_digit_num; --i) {
if ((i*i) < result) {//found the highest palindrome
break;
}
for (T j = i; j >= least_n_digit_num; --j) {
val = i*j;
++n_checks;
if (val < result) // any product i*j for the value of 'j' after this will be less than result
break;
if (IsPalindrome(val)) {
if (val > result)
result = val;
break; // whenever a palindrome is found break since we only need highest one
}
}
}
std::cout << " Total num of checks = " << n_checks << std::endl;
return result;
}
int main() {
int n = 3;
std::cout << " LongestPalindromeFromProductOfNDigitNums for n = "
<< n << " is " << LongestPalindromeFromProductOfNDigitNums(n) << std::endl;
n = 4;
std::cout << " LongestPalindromeFromProductOfNDigitNums for n = "
<< n << " is " << LongestPalindromeFromProductOfNDigitNums(n) << std::endl;
return 0;
}
http://ideone.com/WoNSJP
Swift 3:
// my approach is to make 6-digit palindrome first and then
// check if I can divide it by 3-digit number
// (you can see some visual listing at the end of the code)
// execution time on my laptop is around: 2.75409698486328 sec
import Foundation
func maxPalindrom() -> Int {
var result = 999999
var i = 9
var j = 9
var k = 9
while true {
while true {
while true {
print("in K loop: \(result) k = \(k)")
if isDivisible(number: result) {
return result
}
if k <= 0 {
k = 9
result += 9900
break
}
result -= 1100
k -= 1
}
print("in J loop: \(result)")
if isDivisible(number: result) {
return result
}
if j < 0 {
j = 9
result += 90090
break
}
result -= 10010
j -= 1
}
print("in I loop: \(result)")
if isDivisible(number: result) {
return result
}
if i < 0 {
break
}
result -= 100001
i -= 1
}
if result == 100001 {
return -1
}
return -1
}
func isDivisible(number: Int) -> Bool {
var i = 999
while true {
if number % i == 0 && number / i < 999 {
return true
}
if i < 500 {
return false
}
i -= 1
}
}
let start = NSDate()
print(maxPalindrom()) // 906609
let end = NSDate()
print("executio time: \(end.timeIntervalSince(start as Date)) sec") // ~ execution time: 2.75409698486328 sec
//in K loop: 999999 k = 9
//in K loop: 998899 k = 8
//in K loop: 997799 k = 7
//in K loop: 996699 k = 6
//in K loop: 995599 k = 5
//in K loop: 994499 k = 4
//in K loop: 993399 k = 3
//in K loop: 992299 k = 2
//in K loop: 991199 k = 1
//in K loop: 990099 k = 0
//in J loop: 999999
//in K loop: 989989 k = 9
//in K loop: 988889 k = 8
//in K loop: 987789 k = 7
//in K loop: 986689 k = 6
//in K loop: 985589 k = 5
//in K loop: 984489 k = 4
//in K loop: 983389 k = 3
.....
Most of the answers here are correct. If you want to save going through 900*900 loops, you can just loop through all palindromes between 10000 and 998001 and find if they are divisible by 3 digit number.
static void largestpalindromeproduct(){
int a=999,b=999,c=a*b,loopcounter=0;
while(c>10000){
loopcounter++;
c--;
if(isPalindrome(c))
if(isDivisible(c))
break;
}
System.out.println(" largest : " + c+ "\nloops:"+ loopcounter);
}
static boolean isDivisible(int n){
int a=999;
while(a>=100){
if(n%a==0){
if(secondDividerIs3Digit(n,a))
return true;
}
a--;
}
return false;
}
static boolean secondDividerIs3Digit(int n, int a){
Integer b=n/a;
if(b.toString().length()==3)
return true;
return false;
}
static boolean isPalindrome(int n){
Integer i=new Integer(n);
String p=i.toString();
StringBuffer s=new StringBuffer(i.toString());
s.reverse();
if(p.equals(s.toString()))
return true;
return false;
}
As a very simple solution, this one works
public class LargestPallendrome {
public static void main(String[] args) {
int a = 999;
int b = 999;
long max = 0;
while (a > 100) {
long num = a * b;
if (checkPallendrome(num)) {
if (num > max)
max = num;
}
if (b >= 100)
b--;
else {
a--;
b = 999;
}
}
System.out.println(max);
}
public static boolean checkPallendrome(long num) {
String a = num + "";
String b = new StringBuffer(num + "").reverse().toString();
if (a.equals(b))
return true;
return false;
}
}
Another Simple Solution in JavaScript
function reverseNumber(n)
{
n = n + "";
return n.split("").reverse().join("");
}
function palindrom(){
var r= 1 , y =1;
var largest = 0;
while(r <= 1000){
var num1 = r;
var num2 = 0;
while(num1 <= 1000 && num2 <= num1){
product = num1 * num2;
if (product == reverseNumber(product)){
console.log(`${num1} x ${num2} = ${product}`);
if(product > largest){
largest = product;
}
}
num1 = num1 + 1;
num2= num2 + 1;
}
r++;
}
console.log(``)
console.log(`The largest is ${largest}`);
}
console.log(palindrom());
public static void main(String[] args) {
int tempAns = 0;
int max = 999;
for (int i = 100; i <= max; i++) {
for (int j = max; j >= i; j--) {
if (findPalindrome(i * j) && (i * j) > tempAns) {
System.out.println("Palindrome: " + j + " * " + i + " = " + j * i);
tempAns = i * j;
}
}
}
}
private static boolean findPalindrome(int n) {
String nString = String.valueOf(n);
int j = 0;
int stringLength = nString.length() - 1;
for (int i = stringLength; i >= 0; i--) {
if (nString.charAt(j) == nString.charAt(i)) {
if (i == 0) {
return true;
}
j++;
} else if (nString.charAt(j) != nString.charAt(i)) {
return false;
}
}
return false;
}
This is better because its using O(N) time complexity to find all the palindrome (As calculating palindrome of a six digit no is constant) and O(N2) nearly to find the actual palindrome that too worst case the moment its finding its first no we don't have to do any more calculation and here we are actually using the worst case on possible palindromic no. So I think its better
package ProjectEuler;
import java.util.ArrayList;
import java.util.Arrays;
public class Largest_Palindrome_Product {
public static void main(String[] args) {
int count=0;
for(int i=10000;i<998002;i++) {
int x=i,c=0;
while(x!=0) {
c=c*10+x%10;
x/=10;
}
if(c==i) {
count++;
}
}
int a[]=new int[count],count1=0;
for(int i=10000;i<998002;i++) {
int x=i,c=0;
while(x!=0) {
c=c*10+x%10;
x/=10;
}
if(c==i) {
a[count1]=i;
count1++;
}
}
Arrays.sort(a);
tp:for(int i=count-1;i>=0;i--)
{
for(int j=999;j>100;j--)
if(a[i]%j==0&&a[i]/j<=999) {
System.out.println(a[i]+" "+j+" "+a[i]/j);
break tp;
}
}
}
}
This is how I did it in Javascript. Simple & easy!
let num1 = 999;
let num2 = 999;
let arr = [];
function check(x, y)
{
if(String(x*y) == String(x*y).split("").reverse().join(""))
{
return true;
}
return false;
}
for(let i=0; i<999999; i++)
{
if(check(num1, num2))
{
arr.push(num1*num2);
num1--;
num2 = num1+1;
}
num2--;
}
console.log(arr.sort((x, y) => y-x)[0]);
I check it some times with random.randint. In python 3.7.1, you should run it with CMD and after 20 sec you will get the right answer.
import random
x,y,z,a,b=100,100,' ','',0
while 100<=x<=999 and 100<=y<=999:
a=x*y
x=random.randint(900,999)
y=random.randint(900,999)
print(x,' x ',y,'=')
z=len(str(a))
if z==6:
if str(a)[0] == str(a)[5]:
if str(a)[1] == str(a)[4]:
if str(a)[2] == str(a)[3]:
print(a,'yes')
exit(a)
else:
pass
#906609
Readable option:
function maxPalindrome(num) {
let maxPalindrome = 1;
for (let i = num; i > 0; i--) {
for (let j = num; j > 0; j--) {
const product = i * j;
if (
product.toString() === product.toString().split("").reverse().join("")
&& product > maxPalindrome
) {
maxPalindrome = product;
}
}
}
return maxPalindrome;
}
console.log(maxPalindrome(999));
This is how I have done with C#:
public static void maxPali() {
int max = 0;
for (int i = 99; i >= 10; i--) {
for (int j = 99; j >= 10; j--) {
if (i*j == reverse(i*j))
max = max >= (i*j) ? max : (i*j);
}
}
Console.WriteLine(max);
}
public static int reverse(int num) {
int rev = 0;
while (num > 0) {
int rem = num % 10;
rev = (rev * 10) + rem;
num /= 10;
}
return rev;
}
JavaScript solution:
(function main() {
let start = 100,
stop = 999,
step = 1;
let arr = Array(Math.ceil((stop + step - start) /
step)).fill(start).map((x, y) => x + y * step);
let max = 0;
arr.slice(0).reverse().map(function(i) {
arr.slice(0).reverse().map(function(j) {
if (i*j == (i*j).toString().split('').reverse().join(''))
if (max < (i*j))
max = i*j;
});
});
console.log(max); }());

Categories

Resources