Reputation: 27
Given 3 ternary (base 3) numbers of equal length (they can be padded on the left with zeros), is there a quick and simple way to compare each place value (or column) such that each column is composed of 3 different numbers or 3 of the same number.
For example:
Good pairs: || Bad pairs:
________________||________________
101 | 000 | 012 || 111 | 012 | 002
212 | 111 | 112 || 122 | 120 | 022
020 | 222 | 212 || 120 | 202 | 102
My best solution currently is to add up the 3 numbers, but add them like decimal numbers instead of (so the first good pair would become 333 instead of 1110). Then I check each individual number and check if it is divisible by 3.
At first I was checking if the entire number was divisible by 3, but that fails on a lot of numbers.
00
10
11
--
21 % 3 == 0
As you can see just dividing by 3 isn't a good enough check since you can tell with a quick glance that the columns actually fail the rules I've set. Here's the method I wrote that checks it the correct way I explained:
//The 3 numbers are originally decimal numbers
private static boolean ternary(int a, int b, int c)
{
//Convert each number to a ternary number, add them and assign the result to a string
//This is the best base conversion code I was able to find using native java
String ternary = Integer.toString(Integer.parseInt(Integer.toString(a, 3))
+ Integer.parseInt(Integer.toString(b, 3))
+ Integer.parseInt(Integer.toString(c, 3)));
//For each digit in the number, check if it is divisible by 3. If not, return false
for (int i = 0; i < ternary.length(); i++)
if (Integer.parseInt(ternary.charAt(i) + "") % 3 != 0)
return false;
//If all the numbers passed the test, return true
return true;
}
I have also messed around with adding the numbers as decimal and converting the result to a ternary number and trying to check the properties to no avail. I have a second method that acts like the above but without using Strings. Instead it divides the number by 10000, 1000, etc. since you cannot do .charAt() on a number.
My intuition tells me there needs to be a much simpler way to do this, but I have yet to discover it. I have spent way too much trying to come up with an elegant solution, but I'm quite stuck. This may be more of a math question than a programming one, but I think someone here might be able to point me in the right direction. Thanks :)
Upvotes: 2
Views: 192
Reputation: 29710
You essentially have a 3x3 matrix where each column must sum to either 0
(all elements in the column are 0
), 3
(all elements in the column are 1
or the elements in the column are a permutation of 0
, 1
, and 2
), or 6
(all elements in the column are 2
).
Because the columns must sum to either 0
, 3
, or 6
, we can simply check that the sum is divisible by 3
.
The code to check this would be as follows:
private static boolean ternary(int a, int b, int c) {
for (int i = 0; i < 3; i++) {
if ((a % 3 + b % 3 + c % 3) % 3 != 0) {
return false;
}
a /= 3;
b /= 3;
c /= 3;
}
return true;
}
Because a
, b
, and c
are input as decimal (base-10), we can use n % 3
(on each value) to get the least significant ternary digits, and return false
if their sum is not divisible by 3
.
However, we then need to divide each value by 3
to effectively drop the least significant ternary digit.
This is also personal preference, but the calls to a /= 3
, b /= 3
, and c /= 3
can be moved into the increment portion of the for-loop:
private static boolean ternary(int a, int b, int c) {
for (int i = 0; i < 3; i++, a /= 3, b /= 3, c /= 3) {
if ((a % 3 + b % 3 + c % 3) % 3 != 0) {
return false;
}
}
return true;
}
Upvotes: 1