Summary Files Commits Branches @commit @diff @stats
path: root / Year 2 / Functional Programming / hw1.rkt
blob: 46bed912a5dace7820b411bbde10754181c356ed (plain) (blame)
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
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
#lang racket

;;; Задача 1

(define (sum-digits n)
  (define (calc-iter working-n total)
    (if (= working-n 0)
      total
      (calc-iter (quotient working-n 10) (+ total (remainder working-n 10)))))
  (calc-iter n 0))

(define (count-specials k a b)
  (if (or (<= k 0) (> a b))
    0
    (+ (count-specials k (add1 a) b)
       (if (and (= 0 (remainder a k)) (= 0 (remainder (sum-digits a) k)))
         1 0)))) ; ако е k-специално, добавяме единица към бройката, иначе не

;; Примери
(count-specials 3 3 9)
(count-specials 5 10 100)
(count-specials 8 100 200)
(count-specials 15 1000 2000)



;;; Задача 2

(define (^10 n)
  (define (calc-iter power val)
    (if (= power 0)
      val
      (calc-iter (sub1 power) (* val 10))))
  (calc-iter n 1))

(define (numlen n)
  (define (calc-iter working-n len)
    (if (= working-n 0)
      len
      (calc-iter (quotient working-n 10) (add1 len))))
  (calc-iter n 0))

(define (rotate-left n)
  (define 10^len-1 (^10 (sub1 (numlen n))))
  (+ (* (remainder n 10^len-1) 10) ; всичко без най-дясната цифра * 10
     (quotient n 10^len-1)))       ; най-дясната цифра

(define (rotate-left-preserved n d)
  (define 10^rotatelen (^10 (- (numlen n) d)))
  (define to-rotate (remainder n 10^rotatelen))
  (if (<= n 9)
    n
    (+ (- n to-rotate) ; незапазените цифри стават нули
       (if (< to-rotate (quotient 10^rotatelen 10))     ; ако to-rotate "започва" с нули
         (- (rotate-left (+ to-rotate 10^rotatelen)) 1) ; временно "долепяме" 1ца до левия край, за да може незапазените да се звъртят правилно
         (rotate-left to-rotate)))))                    ; иначе просто завъртаме незапазените

(define (max-rot n)
  (define len-1 (sub1 (numlen n)))
  (define (calc-iter preserved current biggest)
    (if (= preserved len-1) ; при равенство ще има само една цифра която ще може да бъде завъртяна
      biggest
      (calc-iter (add1 preserved)
                 (rotate-left-preserved current (add1 preserved))
                 (if (> current biggest) current biggest))))
  (calc-iter 0 (rotate-left n) 0))

;; Примери
(max-rot 56789)
(max-rot 12490)
(max-rot 38458215)
(max-rot 195881031)
(max-rot 896219342)
(max-rot 69418307)
(max-rot 257117280)