Сумма сбалансированных троичных строк - PullRequest
0 голосов
/ 09 января 2019

Мне нужно написать код, который суммирует две строки чисел, написанных в сбалансированной троичной форме (https://en.wikipedia.org/wiki/Balanced_ternary). Вместо использования -1 / 0 / + 1 я должен использовать - /. / + Поскольку я не могу преобразовать строково-троичные сбалансированные числа в целые-десятичные числа, Я должен вручную суммировать символы двух строк на входе , но я понятия не имею, как разобраться с керри, сгенерированным суммированием различных символов.

РЕДАКТИРОВАТЬ: Это то, что я до сих пор придумал - https://pastebin.com/R98RDHTQ Однако, если я суммирую - и -, коды дают. ++ вместо - ++. Это так, если суммировать частичный результат .- + с первым переносом .-. он не отслеживает второй перенос ... Как мне это исправить?

(define btr-sum  
  (lambda(a b)

    (cond
      ((< (string-length a)(string-length b))(btr-sum (normalize a b) b))
      ((> (string-length a)(string-length b))(btr-sum a (normalize b a)))
      ((and(char=? (string-ref a 0) #\. )(char=?(string-ref b 0)#\b))(btr-sum (substring a 1 )(substring b 1)))
      (else (real (normalize(real a b ".") (create-rip a b ".")) (create-rip a b ".") "."));; (+(+ a b) c)
      )    
    )
  )



(define real ;;sums strings a and b without carry
  (lambda(a b r);;strings
     (if (>(string-length a)1)
         (string-append

          (real ;;recursive
           (substring a 0 (-(string-length a)1))
           (substring b 0 (- (string-length b)1))
           r)


          (string(somma ;;sums last chars of strings
                 (string-ref a (-(string-length a)1))
                 (string-ref b (-(string-length b)1))
                 )
                 )
          )

         (string(somma (string-ref a 0)(string-ref b 0)))
         )


    )
  )




(define normalize ;;if the length of subj < length of obj, normalize fills stacks up subj with "."
  (lambda(subj obj)
    (if (not(= (string-length subj)(string-length obj)))
        (normalize (string-append "." subj) obj)
        subj
        )
    )
  )

(define create-rip ;;generates the carry of the sum of a and b
  (lambda (a b c)
    (if (> (string-length a) 1)
        (cond ;; if length>1 then do it again
          (
           (and (char=? #\+(string-ref a (-(string-length a)1)))(char=? #\+ (string-ref b (-(string-length b)1))));;if +/+, add one + in carry
           (create-rip (substring a 0 (-(string-length a)1))(substring b 0 (-(string-length b)1))(string-append "+" c))
           )

          (
           (and (char=? #\-(string-ref a (-(string-length a)1)))(char=? #\- (string-ref b (-(string-length b)1))))if -/-, add one - in carry
           (create-rip (substring a 0 (-(string-length a)1))(substring b 0 (-(string-length b)1))(string-append "-" c))
           )
          (else  (create-rip (substring a 0 (-(string-length a)1))(substring b 0 (-(string-length b)1))(string-append "." c)))
          )

        (cond ;;if it's the last char do it only once
          (
           (and (char=? #\+(string-ref a (-(string-length a)1)))(char=? #\+ (string-ref b (-(string-length b)1))))
           (string-append "+" c)
           )

          (
           (and (char=? #\-(string-ref a (-(string-length a)1)))(char=? #\- (string-ref b (-(string-length b)1))))
           (string-append "-" c)
           )
          (else  (string-append "." c))
          )
        )
    )
  )


(define somma ;;general procedure to sum two char without taking care of carry
  (lambda(a b)
    (cond
      ((and (char=? a  #\-)(char=? b #\-))#\+)
      ((and (char=? a  #\.) (char=? b #\-))#\-)
      ((and (char=? a  #\+)(char=? b #\-))#\.)

      ((and (char=? a  #\-)(char=? b #\+))#\.)
      ((and (char=? a  #\.)(char=? b #\+))#\+)
      ((and (char=? a  #\+)(char=? b #\+))#\-)

      ((and (char=? a  #\-)(char=? b #\.))#\-)
      ((and (char=? a  #\.)(char=? b #\.))#\.)
      ((and (char=? a  #\+)(char=? b #\.)) #\+)
        )
    )
  )




(btr-sum "-""--")

Ответы [ 2 ]

0 голосов
/ 09 января 2019

Начните с разработки таблицы троичного плюс; цитируемая вами статья в Википедии дает таблицу примерно на две трети пути вниз:

       -1      0      1
     ----   ----   ----
-1   -1 1     -1      0
0      -1      0      1
1       0      1   1 -1

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

РЕДАКТИРОВАТЬ: Оригинальный плакат спрашивает, как следить за переносом. Я не собираюсь писать код, но вы отслеживаете перенос так же, как при добавлении двух чисел вручную, во временную переменную; назовите это carry и инициализируйте это к нулю. Чтобы добавить два числа, работайте справа налево, используя следующую процедуру: Добавьте две триты в текущей позиции, используя приведенную выше таблицу троичного плюса, затем добавьте carry к результату. Трит младшего разряда результата переходит в текущую позицию, а трит старшего разряда заменяет carry. Будьте уверены, чтобы не потерять последний перенос в конце.

0 голосов
/ 09 января 2019

Используйте char->integer и integer->char для преобразования между символами и целыми числами.

...