Balanced ternary: Difference between revisions

m
 
(17 intermediate revisions by 9 users not shown)
Line 29:
{{trans|Python}}
 
<syntaxhighlight lang="11l">T BalancedTernary
<lang 11l>F py_idiv(a, b)
. -:str2dig = [‘+’ = 1, ‘-’ = -1, ‘0’ = 0]
I a >= 0
. -:dig2str = [1 = ‘+’, -1 = ‘-’, 0 = ‘0’]
R a I/ b
. -:table = [(0, -1), (1, -1), (-1, 0), (0, 0), (1, 0), (-1, 1), (0, 1)]
R (a - b + 1) I/ b
 
F BalancedTernary_int2ternary(n)
I n == 0
R [Int]()
V n3 = ((n % 3) + 3) % 3
I n3 == 0 {R [0] [+] BalancedTernary_int2ternary(py_idiv(n, 3))}
I n3 == 1 {R [1] [+] BalancedTernary_int2ternary(py_idiv(n, 3))}
I n3 == 2 {R [-1] [+] BalancedTernary_int2ternary(py_idiv((n + 1), 3))}
X RuntimeError(‘’)
 
F BalancedTernary_neg(digs)
R digs.map(d -> -d)
 
V table = [(0, -1), (1, -1), (-1, 0), (0, 0), (1, 0), (-1, 1), (0, 1)]
 
F BalancedTernary_add(a, b, =c = 0)
I !(!a.empty & !b.empty)
I c == 0
R I !a.empty {a} E b
E
R BalancedTernary_add([c], I !a.empty {a} E b)
E
(V d, c) = :table[3 + (I !a.empty {a[0]} E 0) + (I !b.empty {b[0]} E 0) + c]
V res = BalancedTernary_add(a[1..], b[1..], c)
I !res.empty | d != 0
R [d] [+] res
E
R res
 
V BalancedTernary_str2dig = [‘+’ = 1, ‘-’ = -1, ‘0’ = 0]
V BalancedTernary_dig2str = [1 = ‘+’, -1 = ‘-’, 0 = ‘0’]
 
T BalancedTernary
[Int] digits
 
Line 72 ⟶ 40:
.digits = copy(inp)
E
X.throw ValueError(‘BalancedTernary: Wrong input digits.’)
 
F :from_str(inp)
R BalancedTernary(reversed(inp).map(c -> .:str2dig[c]))
 
. F :int2ternary(n)
I n == 0
R [Int]()
V n3 = ((n % 3) + 3) % 3
I n3 == 0 {R [0] [+] .:int2ternary(n -I/ 3)}
I n3 == 1 {R [1] [+] .:int2ternary(n -I/ 3)}
I n3 == 2 {R [-1] [+] .:int2ternary((n + 1) -I/ 3)}
X.throw RuntimeError(‘’)
 
F :from_int(inp)
R BalancedTernary(.:int2ternary(inp))
 
F to_int()
Line 80 ⟶ 63:
I .digits.empty
R ‘0’
R reversed(.digits).map(d -> BalancedTernary_dig2str.:dig2str[d]).join(‘’)
 
. F :neg(digs)
R digs.map(d -> -d)
 
F -()
R BalancedTernary(.:neg(.digits))
 
. F :add(a, b, =c = 0)
I !(!a.empty & !b.empty)
I c == 0
R I !a.empty {a} E b
E
R .:add([c], I !a.empty {a} E b)
E
(V d, c) = .:table[3 + (I !a.empty {a[0]} E 0) + (I !b.empty {b[0]} E 0) + c]
V res = .:add(a[1..], b[1..], c)
I !res.empty | d != 0
R [d] [+] res
E
R res
 
F +(b)
R BalancedTernary(BalancedTernary_add.:add(.digits, b.digits))
 
F -(b)
R (.) + BalancedTernary(BalancedTernary_neg(-b.digits))
 
F *(b)
Line 94 ⟶ 97:
E
[Int] x
I a[0] == -1 {x = BalancedTernary_neg.:neg(b)}
E I a[0] == 0 {}
E I a[0] == 1 {x = b}
Line 100 ⟶ 103:
assert(0B)
V y = [0] [+] @_mul(a[1..], b)
R BalancedTernary_add.:add(x, y)
 
R BalancedTernary(_mul(.digits, b.digits))
 
V a = BalancedTernary.from_str(‘+-0++0+’)
F createBalancedTernaryFromStr(inp)
R BalancedTernary(reversed(inp).map(c -> BalancedTernary_str2dig[c]))
F createBalancedTernaryFromInt(inp)
R BalancedTernary(BalancedTernary_int2ternary(inp))
 
V a = createBalancedTernaryFromStr(‘+-0++0+’)
print(‘a: ’a.to_int()‘ ’a)
 
V b = createBalancedTernaryFromIntBalancedTernary.from_int(-436)
print(‘b: ’b.to_int()‘ ’b)
 
V c = createBalancedTernaryFromStrBalancedTernary.from_str(‘+-++-’)
print(‘c: ’c.to_int()‘ ’c)
 
V r = a * (b - c)
print(‘a * (b - c): ’r.to_int()‘ ’r)</langsyntaxhighlight>
 
{{out}}
Line 131 ⟶ 129:
=={{header|Ada}}==
Specifications (bt.ads):
<langsyntaxhighlight Adalang="ada">with Ada.Finalization;
 
package BT is
Line 177 ⟶ 175:
procedure Finalize (Object : in out Balanced_Ternary);
end BT;</langsyntaxhighlight>
 
Implementation (bt.adb):
<langsyntaxhighlight Adalang="ada">with Ada.Unchecked_Deallocation;
 
package body BT is
Line 360 ⟶ 358:
end Initialize;
 
end BT;</langsyntaxhighlight>
 
Test task requirements (testbt.adb):
<langsyntaxhighlight Adalang="ada">with Ada.Text_Io; use Ada.Text_Io;
with Ada.Integer_Text_Io; use Ada.Integer_Text_Io;
with BT; use BT;
Line 381 ⟶ 379:
Put("a * (b - c) = "); Put(To_integer(Result), 4);
Put_Line (" " & To_String(Result));
end TestBT;</langsyntaxhighlight>
Output:
<pre>
Line 399 ⟶ 397:
To demonstrate the possibility, the ''integerFromBT'' and ''negateBT'' handlers here work by being tricksy with the characters' Unicode numbers. It's a more efficient way to deal with the characters. But I'm not sure how this'll be taken ''vis-à-vis'' not converting to native integers first, so the remaining handlers use a strictly if-then string comparison approach. Applescript's quite happy to convert automatically between integers, reals, numeric strings, and single-item lists containing numbers, so ''BTFromInteger'' accepts any of these forms, but the numbers represented must be whole-number values and must be small enough not to error AppleScript's ''as integer'' coercion. This coercion is error free for numbers in the range -(2 ^ 31) to 2 ^ 31 - 1, although actual integer class objects can only represent numbers in the range -(2 ^ 29) to 2 ^ 29 - 1. ''IntegerFromBT'' doesn't currently impose any integer-class size limit on its output.
 
<langsyntaxhighlight lang="applescript">-- Build a balanced ternary, as text, from an integer value or acceptable AppleScript substitute.
on BTFromInteger(n)
try
Line 566 ⟶ 564:
set line4 to "a * (b - c) = " & it & " or " & my integerFromBT(it)
 
return line1 & linefeed & line2 & linefeed & line3 & linefeed & line4</langsyntaxhighlight>
 
{{output}}
<langsyntaxhighlight lang="applescript">"a = 523
b = -436
c = 65
a * (b - c) = ----0+--0++0 or -262023"</langsyntaxhighlight>
 
=={{header|ATS}}==
<syntaxhighlight lang="ats">
<lang ATS>
(*
** This one is
Line 789 ⟶ 787:
//
} (* end of [main0] *)
</syntaxhighlight>
</lang>
Output:
<pre>
Line 799 ⟶ 797:
 
=={{header|AutoHotkey}}==
<langsyntaxhighlight AutoHotkeylang="autohotkey">BalancedTernary(n){
k = 0
if abs(n)<2
Line 820 ⟶ 818:
}
return r
}</langsyntaxhighlight>
Examples:<langsyntaxhighlight AutoHotkeylang="autohotkey">data =
(
523
Line 831 ⟶ 829:
result .= A_LoopField " : " BalancedTernary(A_LoopField) "`n"
MsgBox % result
return</langsyntaxhighlight>
Outputs:<pre>
523 : +-0++0+
Line 837 ⟶ 835:
65 : +-++-
-262023 : ----0+--0++0</pre>
 
=={{header|Bruijn}}==
The default syntax sugar for numbers in bruijn is balanced ternary. The implementation of respective arithmetic operators is in <code>std/Number/Ternary</code> and <code>std/Math</code>. Converting between bases can be accomplished using <code>std/Number/Conversion</code>. The following is a library excerpt to show how to define the most common operators (succ,pred,add,sub,mul,eq) efficiently. They can be easily converted to the notation of pure lambda calculus (as originally by Torben Mogensen in "An Investigation of Compact and Efficient Number Representations in the Pure Lambda Calculus").
 
<syntaxhighlight lang="bruijn">
:import std/Combinator .
:import std/Logic .
:import std/Pair .
 
# negative trit indicating coefficient of (-1)
t⁻ [[[2]]]
 
# positive trit indicating coefficient of (+1)
t⁺ [[[1]]]
 
# zero trit indicating coefficient of 0
t⁰ [[[0]]]
 
# shifts a negative trit into a balanced ternary number
↑⁻‣ [[[[[2 (4 3 2 1 0)]]]]]
 
# shifts a positive trit into a balanced ternary number
↑⁺‣ [[[[[1 (4 3 2 1 0)]]]]]
 
# shifts a zero trit into a balanced ternary number
↑⁰‣ [[[[[0 (4 3 2 1 0)]]]]]
 
# shifts a specified trit into a balanced ternary number
…↑… [[[[[[5 2 1 0 (4 3 2 1 0)]]]]]]
 
# negates a balanced ternary number
-‣ [[[[[4 3 1 2 0]]]]]
 
# increments a balanced ternary number (can introduce leading 0s)
++‣ [~(0 z a⁻ a⁺ a⁰)]
z (+0) : (+1)
a⁻ &[[↑⁻1 : ↑⁰1]]
a⁺ &[[↑⁺1 : ↑⁻0]]
a⁰ &[[↑⁰1 : ↑⁺1]]
 
# decrements a balanced ternary number (can introduce leading 0s)
--‣ [~(0 z a⁻ a⁺ a⁰)]
z (+0) : (-1)
a⁻ &[[↑⁻1 : ↑⁺0]]
a⁺ &[[↑⁺1 : ↑⁰1]]
a⁰ &[[↑⁰1 : ↑⁻1]]
 
# converts the normal balanced ternary representation into abstract form
→^‣ [0 z a⁻ a⁺ a⁰]
z (+0)
a⁻ [[[[[2 4]]]]]
a⁺ [[[[[1 4]]]]]
a⁰ [[[[[0 4]]]]]
 
# converts the abstracted balanced ternary representation back to normal
→_‣ y [[0 z a⁻ a⁺ a⁰]]
z (+0)
a⁻ [↑⁻(2 0)]
a⁺ [↑⁺(2 0)]
a⁰ [↑⁰(2 0)]
 
# adds two balanced ternary numbers (can introduce leading 0s)
…+… [[[c (0 z a⁻ a⁺ a⁰)] 1 →^0]]
b⁻ [1 ↑⁺(3 0 t⁻) ↑⁰(3 0 t⁰) ↑⁻(3 0 t⁰)]
b⁰ [1 ↑ (3 0 t⁰)]
b⁺ [1 ↑⁰(3 0 t⁰) ↑⁻(3 0 t⁺) ↑⁺(3 0 t⁰)]
a⁻ [[[1 (b⁻ 1) b⁻' b⁰ b⁻]]]
b⁻' [1 ↑⁰(3 0 t⁻) ↑⁻(3 0 t⁰) ↑⁺(3 0 t⁻)]
a⁺ [[[1 (b⁺ 1) b⁰ b⁺' b⁺]]]
b⁺' [1 ↑⁺(3 0 t⁰) ↑⁰(3 0 t⁺) ↑⁻(3 0 t⁺)]
a⁰ [[[1 (b⁰ 1) b⁻ b⁺ b⁰]]]
z [[0 --(→_1) ++(→_1) →_1]]
c [[1 0 t⁰]]
 
# subtracts two balanced ternary numbers (can introduce leading 0s)
…-… [[1 + -0]]
 
# multiplicates two balanced ternary numbers (can introduce leading 0s)
…⋅… [[1 z a⁻ a⁺ a⁰]]
z (+0)
a⁻ [↑⁰0 - 1]
a⁺ [↑⁰0 + 1]
a⁰ [↑⁰0]
 
# true if balanced ternary number is zero
=?‣ [0 true [false] [false] i]
 
# true if two balanced ternary numbers are equal
# → ignores leading 0s!
…=?… [[[0 z a⁻ a⁺ a⁰] 1 →^0]]
z [=?(→_0)]
a⁻ [[0 false [2 0] [false] [false]]]
a⁺ [[0 false [false] [2 0] [false]]]
a⁰ [[0 (1 0) [false] [false] [2 0]]]
 
main [[0]]
 
# --- tests/examples ---
 
:test ((-42) + (-1) =? (-43)) (true)
:test ((+1) + (+2) =? (+3)) (true)
:test ((-42) - (-1) =? (-41)) (true)
:test ((+1) - (+2) =? (-1)) (true)
:test ((-1) ⋅ (+42) =? (-42)) (true)
:test ((+3) ⋅ (+11) =? (+33)) (true)
</syntaxhighlight>
 
=={{header|C}}==
{{trans|Perl}}
<langsyntaxhighlight lang="c">#include <stdio.h>
#include <string.h>
 
Line 1,041 ⟶ 1,145:
 
return 0;
}</langsyntaxhighlight>
{{out}}
<pre> a: +-0++0+ 523
Line 1,049 ⟶ 1,153:
 
=={{header|C sharp|C#}}==
<langsyntaxhighlight lang="csharp">using System;
using System.Text;
using System.Collections.Generic;
Line 1,279 ⟶ 1,383:
return result;
}
}</langsyntaxhighlight>
output:
<pre>a: +-0++0+ = 523
Line 1,287 ⟶ 1,391:
 
=={{header|C++}}==
<langsyntaxhighlight lang="cpp">#include <iostream>
#include <string>
#include <climits>
Line 1,499 ⟶ 1,603:
return 0;
}
</syntaxhighlight>
</lang>
 
Output
Line 1,511 ⟶ 1,615:
 
=={{header|Common Lisp}}==
<langsyntaxhighlight lang="lisp">;;; balanced ternary
;;; represented as a list of 0, 1 or -1s, with least significant digit first
Line 1,603 ⟶ 1,707:
(bt-integer b) (bt-string b)
(bt-integer c) (bt-string c)
(bt-integer d) (bt-string d)))</langsyntaxhighlight>output<syntaxhighlight lang="text">a 523 +-0++0+
b -436 -++-0--
c 65 +-++-
a × (b − c) = -262023 ----0+--0++0</langsyntaxhighlight>
 
=={{header|D}}==
{{trans|Python}}
<langsyntaxhighlight lang="d">import std.stdio, std.bigint, std.range, std.algorithm;
 
struct BalancedTernary {
Line 1,753 ⟶ 1,857:
const /*immutable*/ r = a * (b - c);
writeln("a * (b - c): ", r.toBint, ' ', r);
}</langsyntaxhighlight>
{{out}}
<pre>a: 523 +-0++0+
Line 1,762 ⟶ 1,866:
=={{header|Elixir}}==
{{trans|Erlang}}
<langsyntaxhighlight lang="elixir">defmodule Ternary do
def to_string(t), do: ( for x <- t, do: to_char(x) ) |> List.to_string
Line 1,835 ⟶ 1,939:
IO.puts "b = #{bs} -> #{b}"
IO.puts "c = #{cs} -> #{c}"
IO.puts "a x (b - c) = #{rs} -> #{r}"</langsyntaxhighlight>
 
{{out}}
Line 1,846 ⟶ 1,950:
 
=={{header|Erlang}}==
<langsyntaxhighlight lang="erlang">
-module(ternary).
-compile(export_all).
Line 1,936 ⟶ 2,040:
add_util(1) -> [0,1];
add_util(0) -> [0,0].
</syntaxhighlight>
</lang>
'''Output'''
<langsyntaxhighlight lang="erlang">
234> ternary:test().
A = +-0++0+ -> 523
Line 1,945 ⟶ 2,049:
A x (B - C) = 0----0+--0++0 -> -262023
ok
</syntaxhighlight>
</lang>
 
 
Line 1,952 ⟶ 2,056:
{{trans|Ruby}}
{{trans|Common Lisp}}
{{works with|Factor|0.98}}
<lang factor>USING: kernel combinators locals formatting lint literals
<syntaxhighlight lang="factor">USING: kernel combinators locals formatting lint literals
sequences assocs strings arrays
math math.functions math.order ;
Line 2,014 ⟶ 2,119:
"c" c bt>integer c bt>string "%s: %d, %s\n" printf
"a*(b-c)" d bt>integer d bt>string "%s: %d, %s\n" printf
]</langsyntaxhighlight>
<syntaxhighlight lang="text">a: 523, +-0++0+
b: -436, -++-0--
c: 65, +-++-
a*(b-c): -262023, ----0+--0++0</langsyntaxhighlight>
 
=={{header|FreeBASIC}}==
{{trans|Liberty BASIC}}
<langsyntaxhighlight lang="freebasic">
#define MAX(a, b) iif((a) > (b), (a), (b))
Dim Shared As Integer pow, signo
Line 2,150 ⟶ 2,255:
Print "a*(b-c): ", a * (b - c)
Sleep
</syntaxhighlight>
</lang>
{{out}}
<pre>
Line 2,279 ⟶ 2,384:
</pre>
'''A crude English/Pidgin Algol translation of the above [[:Category:Glagol]] code.'''
<langsyntaxhighlight lang="algol68">PROGRAM Setun+;
USES
Parameter IS "...\Departments\Exchange\"
Line 2,391 ⟶ 2,496:
Output.ChTarget(" = %d.", InNumber(), 0, 0, 0);
Remove.Memory
END Setun.</langsyntaxhighlight>
 
=={{header|Go}}==
<langsyntaxhighlight lang="go">package main
 
import (
Line 2,617 ⟶ 2,722:
fmt.Println("int overflow")
}
}</langsyntaxhighlight>
{{out}}
<pre>
Line 2,628 ⟶ 2,733:
=={{header|Groovy}}==
Solution:
<langsyntaxhighlight lang="groovy">enum T {
m('-', -1), z('0', 0), p('+', 1)
 
Line 2,787 ⟶ 2,892:
 
String toString() { value }
}</langsyntaxhighlight>
 
Test:
<langsyntaxhighlight lang="groovy">BalancedTernaryInteger a = new BalancedTernaryInteger('+-0++0+')
BalancedTernaryInteger b = new BalancedTernaryInteger(-436)
BalancedTernaryInteger c = new BalancedTernaryInteger(T.p, T.m, T.p, T.p, T.m)
Line 2,805 ⟶ 2,910:
 
println "\nDemonstrate failure:"
assert (a * (b-c)) == a</langsyntaxhighlight>
 
Output:
Line 2,830 ⟶ 2,935:
=={{header|Haskell}}==
BTs are represented internally as lists of digits in integers from -1 to 1, but displayed as "+-0" strings.
<langsyntaxhighlight lang="haskell">data BalancedTernary = Bt [Int]
 
zeroTrim a = if null s then [0] else s where
Line 2,887 ⟶ 2,992:
print $ map btInt [a,b,c]
print $ r
print $ btInt r</langsyntaxhighlight>
 
=={{header|Icon}} and {{header|Unicon}}==
Line 2,894 ⟶ 2,999:
 
Works in both languages:
<langsyntaxhighlight lang="unicon">procedure main()
a := "+-0++0+"
write("a = +-0++0+"," = ",cvtFromBT("+-0++0+"))
Line 2,983 ⟶ 3,088:
}
return (\negate,map(mul,"+-","-+")) | mul
end</langsyntaxhighlight>
 
Output:
Line 2,999 ⟶ 3,104:
Implementation:
 
<langsyntaxhighlight lang="j">trigits=: 1+3 <.@^. 2 * 1&>.@|
trinOfN=: |.@((_1 + ] #: #.&1@] + [) #&3@trigits) :. nOfTrin
nOfTrin=: p.&3 :. trinOfN
Line 3,010 ⟶ 3,115:
add=: carry@(+/@,:)
neg=: -
mul=: trimLead0@carry@(+//.@(*/))</langsyntaxhighlight>
 
trinary numbers are represented as a sequence of polynomial coefficients. The coefficient values are limited to 1, 0, and -1. The polynomial's "variable" will always be 3 (which happens to illustrate an interesting absurdity in the terminology we use to describe polynomials -- one which might be an obstacle for learning, for some people).
Line 3,028 ⟶ 3,133:
Definitions for example:
 
<langsyntaxhighlight lang="j">a=: trinOfStr '+-0++0+'
b=: trinOfN -436
c=: trinOfStr '+-++-'</langsyntaxhighlight>
 
Required example:
 
<langsyntaxhighlight lang="j"> nOfTrin&> a;b;c
523 _436 65
 
Line 3,040 ⟶ 3,145:
----0+--0++0
nOfTrin a mul b (add -) c
_262023</langsyntaxhighlight>
 
=={{header|Java}}==
<langsyntaxhighlight lang="java">
/*
* Test case
Line 3,255 ⟶ 3,360:
}
}
</syntaxhighlight>
</lang>
 
Output:
Line 3,264 ⟶ 3,369:
 
result= ----0+--0++0 -262023
</pre>
 
=={{header|jq}}==
{{Works with|jq}}
 
'''Works with gojq, the Go implementation of jq'''
 
'''Adapted from [[#Wren|Wren]]'''
<syntaxhighlight lang="jq">
### Generic utilities
 
# Emit a stream of the constituent characters of the input string
def chars: explode[] | [.] | implode;
 
# Flip "+" and "-" in the input string, and change other characters to 0
def flip:
{"+": "-", "-": "+"} as $t
| reduce chars as $c (""; . + ($t[$c] // "0") );
 
### Balanced ternaries (BT)
 
# Input is assumed to be an integer (use `new` if checking is required)
def toBT:
# Helper - input should be an integer
def mod3:
if . > 0 then . % 3
else ((. % 3) + 3) % 3
end;
 
if . < 0 then - . | toBT | flip
else if . == 0 then ""
else mod3 as $rem
| if $rem == 0 then (. / 3 | toBT) + "0"
elif $rem == 1 then (. / 3 | toBT) + "+"
else ((. + 1) / 3 | toBT) + "-"
end
end
| sub("^00*";"")
| if . == "" then "0" end
end ;
 
# Input: BT
def integer:
. as $in
| length as $len
| { sum: 0,
pow: 1 }
| reduce range (0;$len) as $i (.;
$in[$len-$i-1: $len-$i] as $c
| (if $c == "+" then 1 elif $c == "-" then -1 else 0 end) as $digit
| if $digit != 0 then .sum += $digit * .pow else . end
| .pow *= 3 )
| .sum ;
 
# If the input is a string, check it is a valid BT, and trim leading 0s;
# if the input is an integer, convert it to a BT;
# otherwise raise an error.
def new:
if type == "string" and all(chars; IN("0", "+", "-"))
then sub("^00*"; "") | if . == "" then "0" end
elif type == "number" and trunc == .
then toBT
else "'new' given invalid input: \(.)" | error
end;
 
# . + $b
def plus($b):
# Helper functions:
def at($i): .[$i:$i+1];
# $a and $b should each be "0", "+" or "-"
def addDigits2($a; $b):
if $a == "0" then $b
elif $b == "0" then $a
elif $a == "+"
then if $b == "+" then "+-" else "0" end
elif $b == "+" then "0" else "-+"
end;
def addDigits3($a; $b; $carry):
addDigits2($a; $b) as $sum1
| addDigits2($sum1[-1:]; $carry) as $sum2
| if ($sum1|length) == 1
then $sum2
elif ($sum2|length) == 1
then $sum1[0:1] + $sum2
else $sum1[0:1]
end;
{ longer: (if length > ($b|length) then . else $b end),
shorter: (if length > ($b|length) then $b else . end) }
| until ( (.shorter|length) >= (.longer|length); .shorter = "0" + .shorter )
| .a = .longer
| .b = .shorter
| .carry = "0"
| .sum = ""
| reduce range(0; .a|length) as $i (.;
( (.a|length) - $i - 1) as $place
| addDigits3(.a | at($place); .b | at($place); .carry) as $digisum
| .carry = (if ($digisum|length) != 1 then $digisum[0:1] else "0" end)
| .sum = $digisum[-1:] + .sum )
| .carry + .sum
| new;
 
def minus: flip;
 
# . - $b
def minus($b): plus($b | flip);
 
def mult($b):
(1 | new) as $one
| (0 | new) as $zero
| { a: .,
$b,
mul: $zero,
flipFlag: false }
| if .b[0:1] == "-" # i.e. .b < 0
then .b |= minus
| .flipFlag = true
end
| .i = $one
| .in = 1
| (.b | integer) as $bn
| until ( .in > $bn;
.a as $a
| .mul |= plus($a)
| .i |= plus($one)
| .in += 1 )
| if .flipFlag then .mul | minus else .mul end ;
 
 
### Illustration
 
def a: "+-0++0+";
def b: -436 | new;
def c: "+-++-";
 
(a | integer) as $an
| (b | integer) as $bn
| (c | integer) as $cn
| ($an * ($bn - $cn)) as $in
| (a | mult( (b | minus(c)))) as $i
| "a = \($an)",
"b = \($bn)",
"c = \($cn)",
"a * (b - c) = \($i) ~ \($in) => \($in|new)"
</syntaxhighlight>
{{output}}
<pre>
a = 523
b = -436
c = 65
a * (b - c) = ----0+--0++0 ~ -262023 => ----0+--0++0
</pre>
 
Line 3,270 ⟶ 3,528:
{{trans|Python}}
 
<langsyntaxhighlight lang="julia">struct BalancedTernary <: Signed
digits::Vector{Int8}
end
Line 3,354 ⟶ 3,612:
println("a * (b - c): $(Int(r)), $r")
 
@assert Int(r) == Int(a) * (Int(b) - Int(c))</langsyntaxhighlight>
 
{{out}}
Line 3,362 ⟶ 3,620:
a * (b - c): -262023, ----0+--0++0</pre>
 
=={{header|Koka}}==
Based on the OCaml version
<syntaxhighlight lang="koka">
type btdigit
Pos
Zero
Neg
 
alias btern = list<btdigit>
 
fun to_string(n: btern): string
join(
n.reverse.map fn(d)
match d
Pos -> "+"
Zero -> "0"
Neg -> "-"
)
 
fun from_string(s: string): exn btern
var sl := Nil
s.foreach fn(c)
match c
'+' -> sl := Cons(Pos, sl)
'0' -> sl := Cons(Zero, sl)
'-' -> sl := Cons(Neg, sl)
_ -> throw("Invalid Character")
sl
 
fun to_int(n: btern): int
match n
Nil -> 0
Cons(Zero, Nil) -> 0
Cons(Pos, rst) -> 1+3*rst.to_int
Cons(Neg, rst) -> -1+3*rst.to_int
Cons(Zero, rst) -> 3*rst.to_int
 
fun from_int(n: int): <exn> btern
if n == 0 then [] else
match n % 3
0 -> Cons(Zero, from_int((n/3).unsafe-decreasing))
1 -> Cons(Pos, from_int(((n - 1)/3).unsafe-decreasing))
2 -> Cons(Neg, from_int(((n+1)/3).unsafe-decreasing))
_ -> throw("Impossible")
 
fun (+)(n1: btern, n2: btern): <exn,div> btern
match (n1, n2)
([], a) -> a
(a, []) -> a
(Cons(Pos, t1), Cons(Neg, t2)) ->
val sum = t1 + t2
if sum.is-nil then [] else Cons(Zero, sum)
(Cons(Neg, t1), Cons(Pos, t2)) ->
val sum = t1 + t2
if sum.is-nil then [] else Cons(Zero, sum)
(Cons(Zero, t1), Cons(Zero, t2)) ->
val sum = t1 + t2
if sum.is-nil then [] else Cons(Zero, sum)
(Cons(Pos, t1), Cons(Pos, t2)) -> Cons(Neg, t1 + t2 + [Pos])
(Cons(Neg, t1), Cons(Neg, t2)) -> Cons(Pos, t1 + t2 + [Neg])
(Cons(Zero, t1), Cons(h, t2)) -> Cons(h, t1 + t2)
(Cons(h, t1), Cons(Zero, t2)) -> Cons(h, t1 + t2)
_ -> throw("Impossible")
 
fun neg(n: btern)
n.map fn(d)
match d
Pos -> Neg
Zero -> Zero
Neg -> Pos
 
fun (-)(n1: btern, n2: btern): <exn,div> btern
n1 + neg(n2)
 
fun (*)(n1, n2)
match n2
[] -> []
[Pos] -> n1
[Neg] -> n1.neg
(Cons(Pos, t)) -> Cons(Zero, t*n1) + n1
(Cons(Neg, t)) -> Cons(Zero, t*n1) - n1
(Cons(Zero, t)) -> Cons(Zero, t*n1)
 
fun main()
val a = "+-0++0+".from_string
val b = (-436).from_int
val c = "+-++-".from_string
val d = a * (b - c)
println("a = " ++ a.to_int.show ++ "\nb = " ++ b.to_string ++ "\nc = " ++ c.to_int.show ++ "\na * (b - c) = " ++ d.to_string ++ " = " ++ d.to_int.show )
</syntaxhighlight>
 
{{out}}
<pre>
a = 523
b = -++-0--
c = 65
a * (b - c) = ----0+--0++0 = -262023
</pre>
=={{header|Kotlin}}==
This is based on the Java entry. However, I've added 'BigInteger' support as this is a current requirement of the task description even though it's not actually needed to process the test case:
<langsyntaxhighlight lang="scala">// version 1.1.3
 
import java.math.BigInteger
Line 3,507 ⟶ 3,863:
val iResult = bResult.toBigInteger()
println("a * (b - c) = $bResult = $iResult")
}</langsyntaxhighlight>
 
{{out}}
Line 3,518 ⟶ 3,874:
 
=={{header|Liberty BASIC}}==
<syntaxhighlight lang="lb">
<lang lb>
global tt$
tt$="-0+" '-1 0 1; +2 -> 1 2 3, instr
Line 3,656 ⟶ 4,012:
wend
end function
</syntaxhighlight>
</lang>
 
{{out}}
Line 3,671 ⟶ 4,027:
=={{header|Lua}}==
{{trans|C}}
<langsyntaxhighlight lang="lua">function to_bt(n)
local d = { '0', '+', '-' }
local v = { 0, 1, -1 }
Line 3,816 ⟶ 4,172:
end
 
main()</langsyntaxhighlight>
{{out}}
<pre> a: +-0++0+ 523
Line 3,824 ⟶ 4,180:
 
=={{header|Mathematica}} / {{header|Wolfram Language}}==
<langsyntaxhighlight lang="mathematica">frombt = FromDigits[StringCases[#, {"+" -> 1, "-" -> -1, "0" -> 0}],
3] &;
tobt = If[Quotient[#, 3, -1] == 0,
Line 3,845 ⟶ 4,201:
btnegate@#1],
If[StringLength@#2 == 1,
"0", #0[#1, StringDrop[#2, -1]] <> "0"]] &;</langsyntaxhighlight>
Examples:
<langsyntaxhighlight lang="mathematica">frombt[a = "+-0++0+"]
b = tobt@-436
frombt[c = "+-++-"]
btmultiply[a, btsubtract[b, c]]</langsyntaxhighlight>
Outputs:
<pre>523
Line 3,862 ⟶ 4,218:
=={{header|МК-61/52}}==
{{trans|Glagol}}
<langsyntaxhighlight lang="mk-61">ЗН П2 Вx |x| П0 0 П3 П4 1 П5
ИП0 /-/ x<0 80
ИП0 ^ ^ 3 / [x] П0 3 * - П1
Line 3,873 ⟶ 4,229:
ИП2 /-/ ПП 88 1 П3 БП 10
ИП3 x#0 86 ИП2 ПП 88 ИП4 С/П
8 + ИП5 * ИП4 + П4 ИП5 1 0 * П5 В/О</langsyntaxhighlight>
 
''Note: the "-", "0", "+" denotes by digits, respectively, the "7", "8", "9".''
 
=={{header|Nim}}==
<langsyntaxhighlight Nimlang="nim">import std/[strformat, tables]
import tables
 
type
Line 3,969 ⟶ 4,324:
 
func `*`*(a, b: BTernary): BTernary =
## Multiply towtwo BTernary numbers.
 
var start: BTernary
Line 4,055 ⟶ 4,410:
echo "a × (b - c):"
echo fmt"– in ternary: {x}"
echo fmt"– in decimal: {x.toInt}"</langsyntaxhighlight>
 
{{out}}
Line 4,073 ⟶ 4,428:
 
=={{header|OCaml}}==
<langsyntaxhighlight lang="ocaml">type btdigit = Pos | Zero | Neg
type btern = btdigit list
 
Line 4,124 ⟶ 4,479:
let _ =
Printf.printf "a = %d\nb = %d\nc = %d\na * (b - c) = %s = %d\n"
(to_int a) (to_int b) (to_int c) (to_string d) (to_int d);</langsyntaxhighlight>
Output:
<pre>a = 523
Line 4,132 ⟶ 4,487:
 
=={{header|Perl}}==
<langsyntaxhighlight lang="perl">use strict;
use warnings;
 
Line 4,206 ⟶ 4,561:
printf " c: %14s %10d\n", $c, from_bt( $c );
printf "a*(b-c): %14s %10d\n", $d, from_bt( $d );
</syntaxhighlight>
</lang>
{{out}}
<pre> a: +-0++0+ 523
Line 4,217 ⟶ 4,572:
Using strings to represent balanced ternary. Note that as implemented dec2bt and bt2dec are limited to Phix integers (~+/-1,000,000,000),
but it would probably be pretty trivial (albeit quite a bit slower) to replace them with (say) ba2bt and bt2ba which use/yield bigatoms.
<!--<langsyntaxhighlight Phixlang="phix">(phixonline)-->
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">bt2dec</span><span style="color: #0000FF;">(</span><span style="color: #004080;">string</span> <span style="color: #000000;">bt</span><span style="color: #0000FF;">)</span>
Line 4,310 ⟶ 4,665:
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"%7s: %12s %9d\n"</span><span style="color: #0000FF;">,{</span><span style="color: #008000;">"c"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">c</span><span style="color: #0000FF;">,</span><span style="color: #000000;">bt2dec</span><span style="color: #0000FF;">(</span><span style="color: #000000;">c</span><span style="color: #0000FF;">)})</span>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"%7s: %12s %9d\n"</span><span style="color: #0000FF;">,{</span><span style="color: #008000;">"a*(b-c)"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">res</span><span style="color: #0000FF;">,</span><span style="color: #000000;">bt2dec</span><span style="color: #0000FF;">(</span><span style="color: #000000;">res</span><span style="color: #0000FF;">)})</span>
<!--</langsyntaxhighlight>-->
{{out}}
<pre>
Line 4,322 ⟶ 4,677:
show it manages a 5000+digit multiplication and subtraction in about 0.2s, which I say is "reasonable", given that I didn't try very hard,
as evidenced by that daft addition lookup table!
<!--<langsyntaxhighlight Phixlang="phix">(phixonline)-->
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>
<span style="color: #004080;">atom</span> <span style="color: #000000;">t0</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">time</span><span style="color: #0000FF;">()</span>
Line 4,340 ⟶ 4,695:
<span style="color: #008080;">end</span> <span style="color: #008080;">while</span>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"It took %d subtractions to reach 0. (%3.2fs)\n"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">count</span><span style="color: #0000FF;">,</span><span style="color: #7060A8;">time</span><span style="color: #0000FF;">()-</span><span style="color: #000000;">t0</span><span style="color: #0000FF;">})</span>
<!--</langsyntaxhighlight>-->
{{out}}
<pre>
Line 4,348 ⟶ 4,703:
 
=={{header|PicoLisp}}==
<langsyntaxhighlight PicoLisplang="picolisp">(seed (in "/dev/urandom" (rd 8)))
 
(setq *G '((0 -1) (1 -1) (-1 0) (0 0) (1 0) (-1 1) (0 1)))
Line 4,469 ⟶ 4,824:
(println 'R (trih R) R) )
 
(bye)</langsyntaxhighlight>
 
=={{header|Prolog}}==
Line 4,476 ⟶ 4,831:
'''The conversion.'''<br>
Library '''clpfd''' is used so that '''bt_convert''' works in both ways Decimal => Ternary and Ternary ==> Decimal.
<langsyntaxhighlight Prologlang="prolog">:- module('bt_convert.pl', [bt_convert/2,
op(950, xfx, btconv),
btconv/2]).
Line 4,543 ⟶ 4,898:
R1 #= R - 3 * C1, % C1 #= 1,
convert(N1, C1, [R1 | LC], LF).
</langsyntaxhighlight><br>
'''The addition.''' <br>
The same predicate is used for addition and substraction.
<langsyntaxhighlight Prologlang="prolog">:- module('bt_add.pl', [bt_add/3,
bt_add1/3,
op(900, xfx, btplus),
Line 4,669 ⟶ 5,024:
strip_nombre(L) -->
L.
</syntaxhighlight>
</lang>
'''The multiplication.''' <br>
We give a predicate '''euclide(?A, +B, ?Q, ?R)''' which computes both the multiplication and the division, but it is very inefficient.<br>
The predicates '''multiplication(+B, +Q, -A)''' and '''division(+A, +B, -Q, -R)''' are much more efficient.
<langsyntaxhighlight Prologlang="prolog">:- module('bt_mult.pl', [op(850, xfx, btmult),
btmult/2,
multiplication/3
Line 4,844 ⟶ 5,199:
; mult_(B, Q1, A1, R, Resultat, Ajout)) .
 
</syntaxhighlight>
</lang>
Example of output :
<pre> ?- A btconv "+-0++0+".
Line 4,863 ⟶ 5,218:
=={{header|Python}}==
{{trans|Common Lisp}}
<langsyntaxhighlight lang="python">class BalancedTernary:
# Represented as a list of 0, 1 or -1s, with least significant digit first.
 
Line 4,957 ⟶ 5,312:
print "a * (b - c):", r.to_int(), r
 
main()</langsyntaxhighlight>
{{out}}
<pre>a: 523 +-0++0+
Line 4,965 ⟶ 5,320:
 
=={{header|Racket}}==
<langsyntaxhighlight lang="racket">#lang racket
 
;; Represent a balanced-ternary number as a list of 0's, 1's and -1's.
Line 5,040 ⟶ 5,395:
[description (list 'a 'b 'c "a×(b−c)")])
(printf "~a = ~a or ~a\n" description (bt->integer bt) (bt->string bt))))
</syntaxhighlight>
</lang>
 
{{output}}
Line 5,053 ⟶ 5,408:
(formerly Perl 6)
{{Works with|rakudo|2017.01}}
<syntaxhighlight lang="raku" perl6line>class BT {
has @.coeff;
 
Line 5,115 ⟶ 5,470:
say 'b == ', $b.Int;
say 'c == ', $c.Int;
say "a × (b − c) == ", ~$x, ' == ', $x.Int;</langsyntaxhighlight>
{{out}}
<pre>a == 523
Line 5,124 ⟶ 5,479:
=={{header|REXX}}==
The REXX program could be optimized by using &nbsp; (procedure) with &nbsp; '''expose''' &nbsp; and having the &nbsp; <big>'''$.'''</big> &nbsp; and &nbsp; <big>'''@.'''</big> &nbsp; variables set only once.
<langsyntaxhighlight lang="rexx">/*REXX program converts decimal ◄───► balanced ternary; it also performs arithmetic. */
numeric digits 10000 /*be able to handle gihugic numbers. */
Ao = '+-0++0+' ; Abt = Ao /* [↓] 2 literals used by subroutine*/
Line 5,174 ⟶ 5,529:
btNorm: _= strip(arg(1), 'L', 0); if _=='' then _=0; return _ /*normalize the number.*/
btSub: return btAdd( arg(1), btNeg( arg(2) ) ) /*subtract two BT args.*/
btShow: say center( arg(1), 9) right( arg(2), 20) @@ right( bt2d(arg(2)), 9) @; return</langsyntaxhighlight>
{{out|output|text=&nbsp; when using the default input:}}
<pre>
Line 5,182 ⟶ 5,537:
 
[a*(b-c)] ----0+--0++0 balanced ternary = -262023 (decimal)
</pre>
 
=={{header|RPL}}==
{{trans|Nim}}
{{works with|RPL|HP-48}}
« "-0+" SWAP POS 2 -
» '<span style="color:blue">CH→TR</span>' STO
« "-0+" SWAP 2 + DUP SUB
» '<span style="color:blue">TR→CH</span>' STO
« '''WHILE''' DUP SIZE OVER HEAD "0" == AND '''REPEAT''' TAIL '''END'''
» '<span style="color:blue">NOZEROS</span>' STO
« DUP SIZE → bt len
« 0
1 len '''FOR''' j
bt j DUP SUB <span style="color:blue">CH→TR</span>
3 len j - ^ * +
'''NEXT'''
» » '<span style="color:blue">BT→I</span>' STO
« DUP "" "0" IFTE
'''WHILE''' OVER '''REPEAT'''
OVER 3 MOD
1 ≤ LASTARG NEG IFTE <span style="color:grey>''@ convert 2 into -1''</span>
DUP <span style="color:blue">TR→CH</span> ROT - 3 / IP SWAP
'''END'''
SWAP DROP
» '<span style="color:blue">I→BT</span>' STO
« '''IF''' OVER SIZE OVER SIZE < '''THEN''' SWAP '''END'''
'''WHILE''' OVER SIZE OVER SIZE > '''REPEAT''' "0" SWAP + '''END'''
→ a b
« "" 0
a SIZE 1 '''FOR''' j
a j DUP SUB <span style="color:blue">CH→TR</span> + b j DUP SUB <span style="color:blue">CH→TR</span> +
'''IF''' DUP ABS 2 ≥ '''THEN'''
DUP 3 MOD 1 ≤ LASTARG NEG IFTE
SWAP SIGN
'''ELSE''' 0 '''END'''
SWAP <span style="color:blue">TR→CH</span> ROT + SWAP
-1 '''STEP'''
'''IF THEN''' LASTARG <span style="color:blue">TR→CH</span> SWAP + '''END'''
<span style="color:blue">NOZEROS</span>
» » '<span style="color:blue">ADDBT</span>' STO
« ""
1 3 PICK SIZE '''FOR''' j
OVER j DUP SUB
<span style="color:blue">CH→TR</span> NEG <span style="color:blue">TR→CH</span> +
'''NEXT'''
SWAP DROP
» '<span style="color:blue">NEGBT</span>' STO
« "" → a b shift
« "0"
a SIZE 1 '''FOR''' j
a j DUP SUB
'''IF''' DUP "0" ≠ '''THEN'''
b
'''IF''' SWAP "-" == '''THEN''' <span style="color:blue">NEGBT</span> '''END'''
'''END'''
shift + <span style="color:blue">ADDBT</span>
'shift' "0" STO+
-1 '''STEP'''
<span style="color:blue">NOZEROS</span>
» » '<span style="color:blue">MULBT</span>' STO
« "+-0++0+" -436 <span style="color:blue">I→BT</span> "+-++-" → a b c
« a <span style="color:blue">BT→I</span> b <span style="color:blue">BT→I</span> c <span style="color:blue">BT→I</span> 3 →LIST
a b c <span style="color:blue">NEGBT ADDBT MULBT</span>
» » '<span style="color:blue">TASK</span>' STO
{{out}}
<pre>
3: { 523 -436 65 }
2: "----0+--0++0"
1: -262023
</pre>
 
=={{header|Ruby}}==
<langsyntaxhighlight lang="ruby">class BalancedTernary
include Comparable
def initialize(str = "")
Line 5,307 ⟶ 5,740:
val = eval(exp)
puts "%8s :%13s,%8d" % [exp, val, val.to_i]
end</langsyntaxhighlight>
 
{{out}}
Line 5,318 ⟶ 5,751:
 
=={{header|Rust}}==
<langsyntaxhighlight lang="rust">use std::{
cmp::min,
convert::{TryFrom, TryInto},
Line 5,575 ⟶ 6,008:
}
}
</syntaxhighlight>
</lang>
 
Output
Line 5,587 ⟶ 6,020:
=={{header|Scala}}==
This implementation represents ternaries as a reversed list of bits. Also, there are plenty of implicit convertors
<langsyntaxhighlight lang="scala">
object TernaryBit {
val P = TernaryBit(+1)
Line 5,674 ⟶ 6,107:
implicit def intToTernary(i: Int): Ternary = valueOf(i)
}
</syntaxhighlight>
</lang>
 
Then these classes can be used in the following way:
<langsyntaxhighlight lang="scala">
object Main {
 
Line 5,692 ⟶ 6,125:
 
}
</syntaxhighlight>
</lang>
{{out}}
<pre>
Line 5,702 ⟶ 6,135:
 
Besides, we can easily check, that the code works for any input. This can be achieved with ScalaCheck:
<langsyntaxhighlight lang="scala">
object TernarySpecification extends Properties("Ternary") {
 
Line 5,718 ⟶ 6,151:
 
}
</syntaxhighlight>
</lang>
{{out}}
<pre>
Line 5,728 ⟶ 6,161:
=={{header|Tcl}}==
This directly uses the printable representation of the balanced ternary numbers, as Tcl's string operations are reasonably efficient.
<langsyntaxhighlight lang="tcl">package require Tcl 8.5
 
proc bt-int b {
Line 5,784 ⟶ 6,217:
- { return [bt-sub $sub $b] }
}
}</langsyntaxhighlight>
Demonstration code:
<langsyntaxhighlight lang="tcl">for {set i 0} {$i<=10} {incr i} {puts "$i = [int-bt $i]"}
puts "'+-+'+'+--' = [bt-add +-+ +--] = [bt-int [bt-add +-+ +--]]"
puts "'++'*'++' = [bt-mul ++ ++] = [bt-int [bt-mul ++ ++]]"
Line 5,795 ⟶ 6,228:
puts "a = [bt-int $a], b = [bt-int $b], c = [bt-int $c]"
set abc [bt-mul $a [bt-sub $b $c]]
puts "a*(b-c) = $abc (== [bt-int $abc])"</langsyntaxhighlight>
Output:
<pre>
Line 5,817 ⟶ 6,250:
=={{header|Visual Basic .NET}}==
{{trans|C#}}
<langsyntaxhighlight lang="vbnet">Imports System.Text
 
Module Module1
Line 6,004 ⟶ 6,437:
End Class
 
End Module</langsyntaxhighlight>
{{out}}
<pre>a: +-0++0+ = 523
Line 6,015 ⟶ 6,448:
{{libheader|Wren-big}}
{{libheader|Wren-trait}}
<langsyntaxhighlight ecmascriptlang="wren">import "./big" for BigInt
import "./trait" for Comparable
 
class BTernary is Comparable {
Line 6,139 ⟶ 6,572:
var bResult = a * (b - c)
var iResult = bResult.toBigInt
System.print("a * (b - c) = %(bResult) = %(iResult)")</langsyntaxhighlight>
 
{{out}}
1,471

edits