Форум программистов, компьютерный форум, киберфорум
Языки JVM
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.88/8: Рейтинг темы: голосов - 8, средняя оценка - 4.88
4699 / 4394 / 380
Регистрация: 12.05.2012
Сообщений: 3,096
1

Clojure Project Euler: Largest palindrome product

23.11.2014, 13:54. Показов 1614. Ответов 11
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Число-палиндром с обеих сторон (справа налево и слева направо) читается одинаково. Самое большое число-палиндром, полученное умножением двух двузначных чисел – 9009 = 91 × 99. Найдите самый большой палиндром, полученный умножением двух трёхзначных чисел.
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
23.11.2014, 13:54
Ответы с готовыми решениями:

Clojure Project Euler: Largest product in a series
Project Euler: Largest product in a series Наибольшее произведение четырех последовательных...

Clojure Project Euler: Largest prime factor
Простые делители числа 13195 - это 5, 7, 13 и 29. Каков самый большой делитель числа 600851475143,...

Clojure Project Euler: Multiples of 3 and 5
Если выписать все натуральные числа меньше 10, кратные 3 или 5, то получим 3, 5, 6 и 9. Сумма этих...

Clojure Project Euler: Smallest multiple
Project Euler: Smallest multiple 2520 - самое маленькое число, которое делится без остатка на...

11
505 / 511 / 42
Регистрация: 12.12.2013
Сообщений: 484
23.11.2014, 14:14 2
Лучший ответ Сообщение было отмечено _sg как решение

Решение

Clojure:
Lisp
1
2
3
4
5
6
(apply max (for [x (range 100 1000)
                 y (range 100 1000)
                 :let [tmp (str (* x y))]
                 :when (= (seq tmp) (reverse tmp))]
             (Long/valueOf tmp)))
;; => 906609
2
Эксперт функциональных языков программированияЭксперт Java
4486 / 2721 / 485
Регистрация: 28.04.2012
Сообщений: 8,590
23.11.2014, 14:23 3
Цитата Сообщение от _sg Посмотреть сообщение
Найдите самый большой палиндром, полученный умножением двух трёхзначных чисел.
Эти два числа должны быть разными, я так понимаю?
0
4699 / 4394 / 380
Регистрация: 12.05.2012
Сообщений: 3,096
23.11.2014, 15:12  [ТС] 4
korvin_, вроде, нет такого ограничения.

Lisp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
defun make-palindrome (n &aux (m (write-to-string n)))
  (parse-integer (concatenate 'string m (reverse m))))
 
(defun largest-divisor (p m &aux (z (/ p m)))
  (when (> m 99) (if (and (integerp z) (< z 1000))
                     (list (list p m z))
                     (largest-divisor p (1- m)))))
 
(defun largest-palindrome-product (n m)
  (car (loop for a from n downto m
             nconc (largest-divisor (make-palindrome a) 999))))
 
> (largest-palindrome-product 998 800)
(906609 993 913)
Lisp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
(defun make-palindrome (n &aux (m (write-to-string n)))
  (parse-integer (concatenate 'string m (reverse m))))
 
(defun largest-divisor (p m &aux (z (/ p m)))
  (when (> m 99) (if (and (integerp z) (< z 1000))
                     (list p m z)
                     (largest-divisor p (1- m)))))
 
(defun largest-palindrome-product
    (n m &aux (z (largest-divisor (make-palindrome n) 999)))
  (when (> n m) (if z z (largest-palindrome-product (1- n) m))))
 
> (largest-palindrome-product 998 800)
(906609 993 913)
2
Эксперт функциональных языков программированияЭксперт Java
4486 / 2721 / 485
Регистрация: 28.04.2012
Сообщений: 8,590
23.11.2014, 17:09 5
Лучший ответ Сообщение было отмечено _sg как решение

Решение

Менее красивый, но чуть более быстрый алгоритм:

Lisp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
(defvar *low*  100)
(defvar *high* 999)
 
(defvar *iterations* 0)
 
(defun max-palindrome ()
  (multiple-value-bind (xy x y) (first-palindrome *high* *low*)
    (let ((x0 (1- x)))
      (loop (multiple-value-bind (ab a b) (first-palindrome x0 y)
              (cond ((> ab xy)
                     (setf xy ab x a y b)
                     (setf x0 (1- x)))
                    ((<= x0 y)
                     (return-from max-palindrome (values xy x y)))
                    (t
                     (decf x0))))))))
 
(defun first-palindrome (high low)
  (loop :for x :from high :downto low :do
        (loop :for y :from x :downto low :do
              (let ((xy (* x y)))
                (incf *iterations*)
                (when (palindromep xy)
                  (return-from first-palindrome (values xy x y))))))
  (values 0 0 0))
 
(defun palindromep (num)
  (let* ((str (write-to-string num))
         (len (length str))
         (max (1- len)))
    (dotimes (i (floor len 2))
      (unless (char= (char str i) (char str (- max i)))
        (return-from palindromep nil)))
    t))
Тест:

Lisp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
(defun pal ()
  (labels ((test (x y) (> (car x) (car y))))
    (let (xys)
      (loop :for x :from *low* :to *high* :append
            (loop :for y :from *low* :to *high*
                  :do (incf *iterations*)
                  :when (palindromep (* x y))
                  :do (push (list (* x y) x y) xys)))
      (destructuring-bind (xy x y) (first (sort xys #'test))
        (values xy x y)))))
 
(defmacro stats ((fn &rest args))
  `(let ((*iterations* 0))
     (multiple-value-bind (xy x y) (time (,fn ,@args))
       (format t "; ~a result: ~a (~a * ~a)~%" ',fn xy x y)
       (format t "; iterations: ~a~%~%" *iterations*))))
 
(defun test ()
  (stats (pal))
  (stats (max-palindrome)))
 
(defun tests ()
  (let ((*low* 100) (*high* 999))
    (test))
  (let ((*low* 1000) (*high* 9999))
    (test)))
Lisp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
(tests)
Timing the evaluation of (PAL)
 
User time    =        1.294
System time  =        0.000
Elapsed time =        1.291
Allocation   = 16363112 bytes
0 Page faults
; PAL result: 906609 (993 * 913)
; iterations: 810000
 
Timing the evaluation of (MAX-PALINDROME)
 
User time    =        0.062
System time  =        0.000
Elapsed time =        0.065
Allocation   = 825172 bytes
0 Page faults
; MAX-PALINDROME result: 906609 (993 * 913)
; iterations: 41039
 
Timing the evaluation of (PAL)
 
User time    =  0:02:14.223
System time  =        0.015
Elapsed time =  0:02:14.215
Allocation   = 1945473240 bytes
0 Page faults
; PAL result: 99000099 (9999 * 9901)
; iterations: 81000000
 
Timing the evaluation of (MAX-PALINDROME)
 
User time    =        0.265
System time  =        0.000
Elapsed time =        0.268
Allocation   = 3886740 bytes
0 Page faults
; MAX-PALINDROME result: 99000099 (9999 * 9901)
; iterations: 161799
Добавлено через 11 минут
Для алгоритма _sg:

Lisp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
(defun make-palindrome (n &aux (m (write-to-string n)))
  (parse-integer (concatenate 'string m (reverse m))))
 
(defun largest-divisor (p m &aux (z (/ p m)))
  (when (>= m *low*)
    (if (and (integerp z) (< z *high*))
        (list p m z)
        (largest-divisor p (1- m)))))
 
(defun largest-palindrome-product
    (n m &aux (z (largest-divisor (make-palindrome n) *high*)))
  (when (> n m)
    (if z
        z
        (progn
          (incf *iterations*)
          (largest-palindrome-product (1- n) m)))))
 
(defun largest-palindrome ()
  (destructuring-bind (xy x y) (largest-palindrome-product *high* *low*)
    (values xy x y)))
 
(defun test ()
  ;(stats (pal))
  (stats (max-palindrome))
  (stats (largest-palindrome)))
 
(defun tests ()
  (let ((*low* 10000) (*high* 99999))
    (test)))
Lisp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
(tests)
Timing the evaluation of (MAX-PALINDROME)
 
User time    =       13.572
System time  =        0.000
Elapsed time =       13.564
Allocation   = 303 228 652 bytes
0 Page faults
; MAX-PALINDROME result: 9966006699 (99979 * 99681)
; iterations: 5416431
 
Timing the evaluation of (LARGEST-PALINDROME)
 
User time    =       12.214
System time  =        0.015
Elapsed time =       12.280
Allocation   = 825 990 504 bytes
0 Page faults
; LARGEST-PALINDROME result: 9966006699 (99979 * 99681)
; iterations: 339
Лучше по времени, но хуже по использованию памяти.

Добавлено через 26 минут
_sg, я оптимизировал твой алгоритм =)

Lisp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
(defun lp2 ()
  (loop :for n :from *high* :downto *low* :do
        (let ((p (make-palindrome n)))
          (multiple-value-bind (x y) (find-divisors p)
            (when x
              (return-from lp2 (values p x y))))))
  (values 0 0 0))
 
(defun find-divisors (n)
  (loop :for x :from *low* :to (min (ceiling (sqrt n)) *high*) :do
        (incf *iterations*)
        (multiple-value-bind (y rem) (floor n x)
          (when (and (<= *low* y *high*) (= rem 0))
            (return-from find-divisors (values x y)))))
  (values nil nil))
Lisp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
(tests)
Timing the evaluation of (MAX-PALINDROME)
 
User time    =       13.650
System time  =        0.000
Elapsed time =       13.670
Allocation   = 303 202 460 bytes
0 Page faults
; MAX-PALINDROME result: 9966006699 (99979 * 99681)
; iterations: 5 416 431
 
Timing the evaluation of (LARGEST-PALINDROME)
 
User time    =       12.729
System time  =        0.015
Elapsed time =       12.755
Allocation   = 825 919 808 bytes
0 Page faults
; LARGEST-PALINDROME result: 9966006699 (99979 * 99681)
; iterations: 30 510 360
 
Timing the evaluation of (LP2)
 
User time    =        6.723
System time  =        0.000
Elapsed time =        6.719
Allocation   = 137 268 bytes
0 Page faults
; LP2 result: 9966006699 (99681 * 99979)
; iterations: 30 571 435
Думаю, в моем MAX-PALINDROME итерации неправильно считаются, как-то их слишком меньше при большем времени.

Добавлено через 2 минуты
А не, все правильно. =/
2
Модератор
Эксперт функциональных языков программированияЭксперт Python
36601 / 20330 / 4220
Регистрация: 12.02.2012
Сообщений: 33,641
Записей в блоге: 13
23.11.2014, 17:19 6
Лучший ответ Сообщение было отмечено _sg как решение

Решение

Lisp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
(defun is-pal (n)
  (let ((s (fix2str n))) (eq s (strRev s))))
 
(defun task ()
 (let ((s nil) (p 0))
  (iter (for i from 999 to 900 by -1)
    (iter (for j from 999 to 900 by -1)
      (setq p (* i j))
      (when (is-Pal p) (setq s (list i j)) (return t)))
    (when s (return (cons p s))))))
 
 
==> task
 
(task)
 
==> (906609 993 913)
1
1978 / 1082 / 87
Регистрация: 29.11.2013
Сообщений: 3,353
23.11.2014, 17:47 7
К задаче можно подойти совсем иным путем. 999 * 999 = 998001, ищем ближайший снизу палиндром и его трехзначные делители нацело, если таких делителей нет, ищем следующий. Оптимизируем программу так, чтобы она проверяла числа, только вида i...i. Уже на 6-разрядных числах вместо заданных 3-разрядных окончания программы не дождался. Оптимизировать еще есть куда, например, установить нижний предел для потенциальных кандидатов палиндромов, а вот поиск делителей оптимизировать не удастся. Числодробилка же, не тот язык.
Lisp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
;; rakcket-lang.org
(define (palindrome? n)
  (let ((num (string->list (number->string n))))
    (equal? num (reverse num))))
 
(define (divisiors n max-arity)
  (let loop ((m (sub1 (expt 10 max-arity)))
             (minimum-number (expt 10 (sub1 max-arity))))
    (let ((temp-value (/ n m)))
      (cond [(integer? temp-value) (list m temp-value)]
            [(< m minimum-number) null]
            [else (loop (sub1 m) minimum-number)]))))
 
(define (log10 n) (/ (log n) (log 10)))
 
(define (extract-first-and-last n)
  (list (inexact->exact 
         (floor
          (exact->inexact 
           (/ n 
              (expt 10 (sub1 (inexact->exact (round (log10 n)))))))))
        (remainder n 10)))
 
(define (next-palindrome n)
  (let ((first-and-last (extract-first-and-last n)))
    (let loop ((m n) (first (car first-and-last)) (last (cadr first-and-last)))
      (if (palindrome? m)
          m
          (let* ((k (- m (- (if (<= last first) (+ 10 last) last) first)))
                 (first-and-last (extract-first-and-last k)))
            (loop k (car first-and-last) (cadr first-and-last)))))))
 
(define (main n)
  (let* ((max-arity n)
         (max-num (sub1 (expt 10 max-arity)))
         (palindrome (next-palindrome (* max-num max-num))))
    (let loop ((pal palindrome) (div (divisiors palindrome max-arity)))
      (cond [(< pal max-num) "not found!"]
            [(or (null? div) (ormap (curryr > max-num) div))
             (let ((tmp (next-palindrome (sub1 pal))))
               (loop tmp (divisiors tmp max-arity)))]
            [else (cons pal div)]))))
 
> (time (main 3))
cpu time: 17 real time: 17 gc time: 0
'(906609 993 913)
> (time (main 4))
cpu time: 231 real time: 232 gc time: 21
'(99000099 9999 9901)
> (time (main 5))
cpu time: 8753 real time: 8766 gc time: 506
'(9966006699 99979 99681)
>
1
Эксперт функциональных языков программированияЭксперт Java
4486 / 2721 / 485
Регистрация: 28.04.2012
Сообщений: 8,590
23.11.2014, 18:03 8
Цитата Сообщение от castorsky Посмотреть сообщение
Уже на 6-разрядных числах вместо заданных 3-разрядных окончания программы не дождался
Попробуй минуты 3--4 подождать.

Lisp
1
2
3
4
5
6
7
8
9
Timing the evaluation of (LP2)
 
User time    =  0:03:29.805
System time  =        0.000
Elapsed time =  0:03:29.838
Allocation   = 4 355 815 628 bytes
0 Page faults
; LP2 result: 999000000999 (999001 * 999999)
; iterations: 899 750 896
Добавлено через 41 секунду
Думаю там проблема из-за перехода к bignum.
0
1978 / 1082 / 87
Регистрация: 29.11.2013
Сообщений: 3,353
23.11.2014, 18:14 9
Lisp
1
2
3
4
5
6
7
> (map (λ (i) (time (main i))) '(3 4 5 6))
cpu time: 17 real time: 17 gc time: 0
cpu time: 1062 real time: 1066 gc time: 830
cpu time: 8669 real time: 8700 gc time: 452
cpu time: 287925 real time: 288501 gc time: 17565
'((906609 993 913) (99000099 9999 9901) (9966006699 99979 99681) (999000000999 999999 999001))
>

Не по теме:

Catstail, Вы, как "лицо приближенное к императору" =) поставьте вопрос возможности лямбда-символа в коде.

0
Модератор
Эксперт функциональных языков программированияЭксперт Python
36601 / 20330 / 4220
Регистрация: 12.02.2012
Сообщений: 33,641
Записей в блоге: 13
23.11.2014, 18:43 10
Так: https://www.cyberforum.ru/cgi-bin/latex.cgi?\lambda ???
0
Эксперт функциональных языков программированияЭксперт Java
4486 / 2721 / 485
Регистрация: 28.04.2012
Сообщений: 8,590
23.11.2014, 18:57 11
Цитата Сообщение от castorsky Посмотреть сообщение
Числодробилка же, не тот язык.
А вообще да, Go:

Bash
1
2
3
4
5
6
7
% palindromes
9966006699 (99681 * 99979)
463.0265ms
% palindromes
999000000999 (999001 * 999999)
13.4957719s
%
Добавлено через 57 секунд
castorsky, это миллисекунды, как я понимаю?

Не по теме:

Блин, не уж-то разработчикам Racket так сложно нормально форматировать время в выводе time?



Добавлено через 5 минут
P.S. И это при том, что Go в общем-то тоже не для числодробилок.
1
1978 / 1082 / 87
Регистрация: 29.11.2013
Сообщений: 3,353
23.11.2014, 21:27 12
Цитата Сообщение от Catstail Посмотреть сообщение
Да, только чтобы в тегах было, типа тегLISP λ тег/LISP.
Цитата Сообщение от korvin_ Посмотреть сообщение
это миллисекунды, как я понимаю?
ага
0
23.11.2014, 21:27
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
23.11.2014, 21:27
Помогаю со студенческими работами здесь

Clojure Project Euler: 10001st prime
Выписав первые шесть простых чисел, получим 2, 3, 5, 7, 11 и 13. Очевидно, что 6-ое простое число -...

Clojure Project Euler - large sum
Найдите первые 10 цифр суммы следующих ста пятидесятизначных чисел: ...

Clojure Project Euler: Summation of primes
Сумма простых чисел меньше 10 - это 2 + 3 + 5 + 7 = 17. Найдите сумму всех простых чисел меньше...

Clojure Project Euler: Power digit sum
(expt 2 15) = 32768, сумма цифр 3 + 2 + 7 + 6 + 8 = 26. Какова сумма цифр числа (expt 2 1000)?


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
12
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru