Advertisement
Guest User

Untitled

a guest
Sep 20th, 2018
84
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Racket 6.41 KB | None | 0 0
  1. #lang racket
  2.  
  3. (define (build a b)
  4.   (let* ([a (reverse a)]
  5.          [b (reverse b)])
  6.     (build-list (length b) (lambda (n) (build-list (length a) (lambda (m) (* (list-ref b n) (list-ref a m))))))))
  7.  
  8.  
  9. (define (get-carried-value v n new-list)
  10.   (if (= n (length new-list))
  11.       v
  12.       (+ v (last new-list))))
  13.  
  14.  
  15. (define (carry n old-list new-list)  
  16.   (if (= (length old-list) n)
  17.       new-list
  18.       (let-values ([(v c) (let ([v (get-carried-value (list-ref old-list n) n new-list)])
  19.                             (if (or (< v 10) (= (sub1 (length old-list)) n))
  20.                                 (values v 0)
  21.                                 (let ([rem (remainder v 10)])
  22.                                   (values rem (/ (- v rem) 10)))))])
  23.         (if (= c 0)
  24.             (if (< n (length new-list))
  25.                 (carry (add1 n) old-list (append (reverse (rest (reverse new-list))) (list v)))
  26.                 (carry (add1 n) old-list (append new-list (list v))))
  27.             (if (< n (length new-list))
  28.                 (carry (add1 n) old-list (append (reverse (rest (reverse new-list))) (list v c)))
  29.                 (carry (add1 n) old-list (append new-list (list v c))))))))
  30.  
  31.  
  32. (define (multiply a b)
  33.   (let ([t (build a b)])
  34.     (build-list (length b) (lambda (n) (append (reverse (carry 0 (list-ref t n) '())) (make-list n 0))))))
  35.  
  36.  
  37. (define (find-sum t i j csum sum c lf lf-i)
  38.   (if (= j (length (first t)))
  39.       (values sum lf)
  40.       (let ([s (list-ref t i)])
  41.         (if (< j (length s))
  42.             (if (eq? s (last t))
  43.                 (let* ([total (+ csum (list-ref s j) c)]
  44.                        [carried (let ([rem (remainder total 10)])
  45.                                   (/ (- total rem) 10))])
  46.                   (if (= lf-i j)
  47.                       (find-sum t 0 (add1 j) 0 (append sum (list (- total (* carried 10)))) carried total lf-i)
  48.                       (find-sum t 0 (add1 j) 0 (append sum (list (- total (* carried 10)))) carried lf lf-i)))
  49.                 (find-sum t (add1 i) j (+ csum (list-ref s j)) sum c lf lf-i))
  50.             (let* ([total (+ csum c)]
  51.                    [carried (let ([rem (remainder total 10)])
  52.                               (/ (- total rem) 10))])
  53.               (find-sum t 0 (add1 j) 0 (append sum (list (- total (* carried 10)))) carried lf lf-i))))))
  54.  
  55.  
  56. (define (extract-next t s i max)
  57.   (if (= i max)
  58.       s
  59.       (extract-next t (append s (list (list-ref (list-ref t i) (sub1 i)))) (add1 i) max)))
  60.  
  61.  
  62. (define (list->integer t n i)
  63.   (if (= i (length t))
  64.       n
  65.       (list->integer t (string-append n (number->string(list-ref t i))) (add1 i))))
  66.  
  67.  
  68. (define (display-multiplication a b t)
  69.   (display (make-string (max (- (length (last t)) (string-length (list->integer a "" 0))) 0)))
  70.   (display (list->integer a "" 0))
  71.   (display #\newline)
  72.  
  73.   (display (make-string (max (- (length (last t)) (string-length (list->integer b "" 0))) 0)))
  74.   (display (list->integer b "" 0))
  75.   (display #\newline)
  76.  
  77.   (display (make-string (max (- (length (last t)) (max (string-length (list->integer a "" 0)) (string-length (list->integer b "" 0)))) 0)))
  78.   (display (make-string (max (string-length (list->integer a "" 0)) (string-length (list->integer b "" 0))) #\-))
  79.   (display #\newline)
  80.    
  81.   (for ([s t])
  82.     (display (make-string (max (- (length (last t)) (string-length (list->integer s "" 0))) 0)))
  83.     (display (display (list->integer s "" 0)))
  84.     (display #\newline))
  85.  
  86.   (display (make-string (length (last t)) #\-))
  87.   (display #\newline)
  88.  
  89.   (let-values ([(sum last-full) (find-sum (reverse (map (lambda (s) (reverse s)) t)) 0 0 0 '() 0 0 (sub1 (string-length (list->integer b "" 0))))])
  90.     (display (list->integer (reverse sum) "" 0)))
  91.  
  92.   (display #\newline))
  93.  
  94.  
  95. (define (perform-multiplication a b d)
  96.   (let ([t (multiply a b)])
  97.     (if d
  98.         (display-multiplication a b t)
  99.         (let-values ([(sum last-full) (find-sum (reverse (map (lambda (s) (reverse s)) t)) 0 0 0 '() 0 0 (sub1 (length b)))])
  100.           (values (reverse sum) (extract-next t '() 1 (length b)) last-full)))))
  101.  
  102. (define (solve-for-digits sum)  
  103.   (if (or (and (>= sum 2) (even? sum)) (and (>= sum 5) (odd? sum)))
  104.       (if (= (remainder sum 5) 0)
  105.           (values 0 (/ sum 5))
  106.           (let ([rem (remainder sum 10)])
  107.             (if (even? sum)
  108.                 (values (/ rem 2) (/ (- sum rem) 5))
  109.                 (if (< rem 5)
  110.                     (let ([num-5s (quotient (- sum 5) 5)])
  111.                       (values (/ (- sum (* 5 num-5s)) 2) num-5s))
  112.                     (let ([num-5s (quotient sum 5)])
  113.                       (values (/ (- sum (* 5 num-5s)) 2) num-5s))))))
  114.       (solve-for-digits (+ sum 10))))
  115.  
  116.  
  117. (define (next-digits a b n)
  118.   (if (= n 0)
  119.       (values a b)
  120.       (let-values ([(sum next prev) (perform-multiplication a b #f)])
  121.         (let* ([carried (quotient prev 10)]
  122.                [r-sum (+ (apply + next) carried)])
  123.          
  124.           (let-values ([(p q) (solve-for-digits (- 10 r-sum))])
  125.             (next-digits (append (list p) a) (append (list q) b) (sub1 n)))))))
  126.  
  127.  
  128. (let-values ([(a b) (next-digits (list 5) (list 2) 10)])
  129.   (display (current-process-milliseconds (current-thread)))
  130.   (display #\newline)
  131.  
  132.   (display (list->integer a "" 0))
  133.   (display #\newline)
  134.   (display (list->integer b "" 0)))
  135.  
  136.  
  137. ;; 1   374ms
  138. ;; 5   405ms
  139. ;; 10  437ms
  140. ;; 50  468ms
  141. ;; 100 1357ms
  142. ;; 200 15831ms
  143. ;; 250 29280ms
  144. ;; 500 424412ms
  145.  
  146. ;; 500 digits of a: 413011120000221120312111300434302404330330443312300424322041024442442211044244331130232320244412312443003020310421032322234130223211122013340401411342044031042124241001101332411222203112324231330303022240232410122121011221344403034044344143040221423143400130003040043113444410130431312324220130330301003030000443201122044141213120122140343442043341432221300203122233430221043142013443310301034130213240040014032301402142410244110233110010111112204020434411221203430120141320003313012421131134033203125
  147. ;;               b: 011110101222100002000001111101021010012002010000122110110201201000100100110010000011101111110011001110110202101101110110010012010001010201002110011010111211210100101111111000011011121000001111102011100101100011100001201011110021111101001100201000011000021112120211111011101011001110000100011102002011120102221010021111110010101001100112111100201001010001012111011010111101111000210101001121101102100001102101111110021010001101001100112212010010111101000111001110002012101102110100101011000000210010112
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement