Convert between balanced bases!
Mathematica, 85 bytes
#~FromDigits~#2~IntegerDigits~#3//.{p___,a_:0,b_,q___}/;b>⌊#3/2⌋:>{p,a+1,b-#3,q}&
Explanation
#~FromDigits~#2
Convert #1
(1 is implied--input 1, a list of digits) into an integer base #2
(input 2).
... ~IntegerDigits~#3
Convert the resulting integer into base #3
(input 3), creating a list of digits.
... //.{p___,a_:0,b_,q___}/;b>⌊#3/2⌋:>{p,a+1,b-#3,q}
Repeatedly replace the list of digits; if a digit is greater than floor(#3
/2), then subtract #3
from it and add 1
to the digit to the left. If there is nothing on the left, insert a 0
and add 1
.
APL (Dyalog Unicode), 47 bytes
{z↓⍨⊥⍨0=⌽z←m+u⊤v-⍺⊥m←⌈.5×1-u←⍺⍴⍨1+⌈⍺⍟1⌈|v←⍺⍺⊥⍵}
Try it online!
A dop that takes n
, b
, c
as three separate values. Call it like c (b f) n
where f
is the submission.
Dyalog APL has a dfns library function bt
that does various arithmetic in balanced ternary. Part of it is encode/decode, i.e. conversion between balanced ternary and plain integer:
encode←{ ⍝ balanced ternary from integer.
digs←1+⌈3⍟1⌈|⍵ ⍝ number of ternary digits.
tlz ¯1+(digs⍴3)⊤⍵+3⊥digs⍴1 ⍝ vector of bt digits.
} ⍝ :: ∇ num → bt
decode←{3⊥⍵} ⍝ integer from balanced ternary.
(the hidden function tlz
trims leading zeros.)
This submission is just a generalization of the above code.
Ungolfed with comments
{ ⍝ Input: ⍵←n, ⍺⍺←b, ⍺←c
v←⍺⍺⊥⍵ ⍝ v← plain integer from base b
u←⍺⍴⍨1+⌈⍺⍟1⌈|v ⍝ u← copies of c with the size enough to fit the answer
1⌈|v ⍝ max(1,abs(v)) so that it works well with log(⍟)
⌈⍺⍟ ⍝ number of digits enough to fit v in plain base c
1+ ⍝ ...enough to fit v in balanced base c
⍺⍴⍨ ⍝ that many copies of c
m←⌈.5×1-u ⍝ m← the minimum value in balanced base c with that many digits
z←m+u⊤v-⍺⊥m ⍝ z← n in balanced base c, possibly with leading zeros
⍺⊥m ⍝ m as plain integer
v- ⍝ subtract from v (or, since m<0, add abs(m) to v)
u⊤ ⍝ encode that value to plain base c, with that many digits
m+ ⍝ revert the offset
z↓⍨⊥⍨0=⌽z ⍝ remove leading zeros from z and return it
⊥⍨0=⌽z ⍝ count trailing zeros (⊥⍨) on reversed z
z↓⍨ ⍝ drop that many items from z
}
Perl 6, 121 bytes
->\n,\b,\c{sub f{sum [R,](@^n)Z*($^b X**0..*)}
first {f(b,n)==f c,$_},map {[$_-($_>floor c/2)*c for .base(c).comb]},0..*}
Slow brute-force solution.
How it works:
map {[ .base(c).comb]}, 0..*
-- Generate the lazy infinite sequence of natural numbers in basec
, with each number represented as an array of digits.$_ - ($_ > floor c/2) * c
-- Transform it by subtractingc
from each digit that is greater than floor(c / 2).first { f(b, n) == f(c, $_) }, ...
-- Get the first array of that sequence which when interpreted as a basec
number, equals the input arrayn
interpreted as a baseb
number.sub f { sum [R,](@^n) Z* ($^b X** 0..*) }
-- Helper function that turns an array@^n
into a number in base$^b
, by taking the sum of the products yielded by zipping the reversed array with the sequence of powers of the base.