Найдите самый большой палиндром, сделанный из продукта двух трехзначных чисел - Javascript

Может ли кто-нибудь сказать мне, что не так с кодом. Найдите наибольший palindrome, сделанный из произведения двух трехзначных чисел.

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());

Этот ответ был близок к моему вопросу но все же я чувствую, как я делаю цикл, он должен вернуть мне самый большой продукт.

Ответ 1

Ваш не работает должным образом, так как он проверяет 999*999, затем 999*998, затем 999*997, пока не достигнет значения 999*583. Пока он не проверяет 997*995 или что-то ближе к началу который генерирует большее число

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());

Вот еще один подход, сохраните все palindrome, сгенерированные тремя числами в массиве, затем используйте Math.max on the array для получения наибольшего palindrome

Ответ 2

Я думаю, что если вы примените математику к проблеме, вы можете значительно уменьшить догадки.

Я напишу трехзначные числа как 1000 - a и 1000 - b, что означает, что палиндром 1 000 000 - 1000(a+b) + ab.

Сначала найдем решения, где ab < 1000. Затем три самые левые цифры: 1000 - (a+b), а три самые правые цифры - ab.

Тогда я скажу, что это палиндром с цифрами x,y,z:

100x+10y+z=ab
100z+10y+x=1000-a-b

Таким образом,

99x-99z = ab+a+b-1000
x-z = 1/99(ab+a+b-10)-10

Итак, тогда (ab + a + b-10) делится на 99, и мы также знаем, что цифры x и z лежат в левой части от -9 до 0 (весь shebang симметричен, поэтому мы можем предположить, что x <= z), поэтому 1/99(ab+a+b-10) находится между 1 и 9. Мы можем переписать ab+a+b-10 как ab+a+b+1-11=99p, поэтому (a+1)(b+1)=99p+11=11*(9p+1), где p пробегает от 1 до 9. Это очень просто:

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";
      }
    }
  }
}

Теперь это печатает только одно правильное решение.

Теперь мы знаем, что 906609 является решением, поэтому существует решение, где ab > 1000 и 1000 (a + b) - ab < 93391? Нет:)

Ответ 3

Как объяснено в комментарии @VisioN:

995*583 = 580085 является палиндром.

993*913 = 906609 также является (большим) палиндром.

Ваш код проверяет 995*583 до 993*913 и выходит из первого найденного палиндрома, поэтому он не возвращает самый большой палиндром.

Решение: получите наибольшие палиндромы, начиная с 999*999 = 998001 вниз, и проверьте, могут ли они быть записаны как xyz*abc.

Или просто используйте принятое решение из связанного с вами вопроса:). Ваше решение, но вместо того, чтобы возвращаться, когда вы находите первый палиндром, проверьте, больше ли он больше самого крупного, и в этом случае вам нужно его заменить. Вы можете остановить, как только самый большой палиндром больше, чем i*999.

Ответ 4

Более оптимизированная версия с комментариями. Обратите внимание: нет необходимости в быстром возврате, просто сохраните max и оптимизируйте циклы, чтобы не пересчитать j*i, если i*j уже проверен.

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());

Ответ 5

Предложение решения с использованием underscore.js. Сначала найдите все палиндромы, а затем пропустите их, начиная с самого большого, и верните тот, у которого два трехзначных простых фактора.

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;
})

Ответ 6

#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;
}

Причины, объясненные выше.

Мы можем пересчитать диапазон j, когда найдем палиндром продукта. Это должно быть быстрее.

Ответ 7

Вышеупомянутое решение будет работать отлично, но мы будем иметь вопрос ТОЛЬКО, когда мы попытаемся выяснить, что это за 2 числа (i = 913 и j = 993)

Я просто изменю решение, предложенное 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);

Ответ 8

Вот как я это сделал. Я использовал старомодный способ проверить палиндром. Кажется, он работает быстрее на моем компьютере, но я могу ошибаться. Нажатие на массив, как и в вышеприведенном сообщении, на моем компьютере было очень медленным. Заметное отставание на консоли. Я бы порекомендовал вам просто проверить, не превышает ли ваш продукт ваш текущий максимум, если он есть, сохраните это, а не нажимайте все на массив. Пожалуйста, не стесняйтесь исправить меня, если я ошибаюсь. Очень ценится.

//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("");
};

Ответ 9

Я думаю, вы можете пойти на код, указанный по этой ссылке http://www.mathblog.dk/project-euler-problem-4/

Так как это экономит ваш процессорный цикл от умножения, что является довольно дорогостоящей операцией.

Ну и в этом вы можете сделать еще немного, чтобы сделать его более похожим, вы можете немного изменить его цикл while

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;
        }
    }
}

Итак, вместо перехода от i=999 : 100, мы можем записать его как i=sqrt(palin):100, так как вы можете найти факториал числа в своем квадратном корне. См. Ссылку Как найти Number - простое число или нет!

А также вы можете изменить if(condition) на if(!(palin%i)), поскольку сравнение с нулем обычно не считается хорошей практикой, а также сравнение требует большего количества циклов процессора по сравнению с вашими простыми отрицательными битами.

Ответ 10

вместо создания Array или ArrayList для хранения всех палиндромов, я просто создал другую переменную max и сохранил в ней самый высокий палиндром.

Мой код находится на Java, но вы можете понять его логику. Вот мой код, чтобы лучше объяснить, что я сказал (читать комментарии):

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;
    }
}

То, что вы делаете, это возвращение и выход из цикла, как только вы получите первый палиндром. Что в вашем случае не является максимальным значением палиндрома.

Вместо этого используйте условие if и сохраняйте дорожку с максимальными значениями и продолжайте цикл до конца.

Я добавил условие if, которое позволяет запуску цикла и регистрирует значение.

Получил правильный ответ из этого кода.

PS. Спасибо Xan за ваш вклад. Наверное, я мог бы объяснить это лучше в первый раз.

Ответ 11

Я видел много сообщений для этого вопроса, это решение, которое я придумал:

  • Наименьшее число, состоящее из двух трехзначных цифр, 10000 (100 * 100)
  • Максимальное число, кратное двум 3-значным номерам, составляет 998001 (999 * 999)

Наш палиндром лежит между этими двумя цифрами, записывает программу, чтобы прокрутить это число, и всякий раз, когда вы получаете палиндром, проверьте, является ли его идеально делимое на 3-значное число, а частное - также на 3-значное число.

Ниже моя программа на С#, последний номер, который он печатает, является нашим необходимым ответом, наслаждайтесь.

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");
        }
    }
}

Ответ 12

Я считаю, что это должно быть оптимальным

#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

Ответ 13

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
.....

Ответ 14

Большинство ответов здесь правильные. Если вы хотите сохранить цикл 900 * 900, вы можете просто перебрать все палиндромы между 10000 и 998001 и определить, делятся ли они на трехзначное число.

 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;
}

Ответ 15

Как очень простое решение, этот работает

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;
}
}

Ответ 16

Еще одно простое решение в 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());

Ответ 17

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;
}

Ответ 18

Это лучше, потому что он использует O (N) временную сложность, чтобы найти весь палиндром (поскольку вычисление палиндрома из шести цифр не является постоянным), а O (N 2) почти, чтобы найти фактический палиндром, что слишком наихудший случай, когда его обнаружение Во-первых, нам не нужно больше вычислять, и здесь мы фактически используем наихудший случай из возможных палиндромных. Так что я думаю, что лучше

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;
            }
    }
    }
}

Ответ 19

Вот как я это сделал в Javascript. Просто и легко!

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]);

Ответ 20

Я проверяю это несколько раз с random.randint. В python 3.7.1 вы должны запустить его с CMD, и через 20 секунд вы получите правильный ответ.

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

Ответ 21

Читаемый вариант:

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));

Ответ 22

Наибольший палиндром, составленный из произведения двух трехзначных чисел, должен быть 997799, а затем 906609. Пожалуйста, объясните сценарий, стоящий за ним.