refactor: LowestBasePalindrome (#5385)

This commit is contained in:
Alex Klymenko
2024-08-25 09:16:14 +02:00
committed by GitHub
parent 0b0b26e3fe
commit 69e1fe9cfb
2 changed files with 102 additions and 86 deletions

View File

@ -1,6 +1,7 @@
package com.thealgorithms.others; package com.thealgorithms.others;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List;
/** /**
* @brief Class for finding the lowest base in which a given integer is a palindrome. * @brief Class for finding the lowest base in which a given integer is a palindrome.
@ -10,45 +11,61 @@ public final class LowestBasePalindrome {
private LowestBasePalindrome() { private LowestBasePalindrome() {
} }
/**
* Validates the base, ensuring it is greater than 1.
*
* @param base the base to be checked
* @throws IllegalArgumentException if the base is less than or equal to 1
*/
private static void checkBase(int base) { private static void checkBase(int base) {
if (base <= 1) { if (base <= 1) {
throw new IllegalArgumentException("base must be greater than 1."); throw new IllegalArgumentException("Base must be greater than 1.");
} }
} }
/**
* Validates the number, ensuring it is non-negative.
*
* @param number the number to be checked
* @throws IllegalArgumentException if the number is negative
*/
private static void checkNumber(int number) { private static void checkNumber(int number) {
if (number < 0) { if (number < 0) {
throw new IllegalArgumentException("number must be nonnegative."); throw new IllegalArgumentException("Number must be non-negative.");
} }
} }
/** /**
* @brief computes the representation of the input number in given base * Computes the digits of a given number in a specified base.
* @param number the input number *
* @param base the given base * @param number the number to be converted
* @exception IllegalArgumentException number is negative or base is less than 2 * @param base the base to be used for the conversion
* @return the list containing the digits of the input number in the given base, the most * @return a list of digits representing the number in the given base, with the most
* significant digit is at the end of the array * significant digit at the end of the list
* @throws IllegalArgumentException if the number is negative or the base is less than 2
*/ */
public static ArrayList<Integer> computeDigitsInBase(int number, int base) { public static List<Integer> computeDigitsInBase(int number, int base) {
checkNumber(number); checkNumber(number);
checkBase(base); checkBase(base);
var result = new ArrayList<Integer>();
List<Integer> digits = new ArrayList<>();
while (number > 0) { while (number > 0) {
result.add(number % base); digits.add(number % base);
number /= base; number /= base;
} }
return result; return digits;
} }
/** /**
* @brief checks if the input array is a palindrome * Checks if a list of integers is palindromic.
* @brief list the input array *
* @return true, if the input array is a palindrome, false otherwise * @param list the list of integers to be checked
* @return {@code true} if the list is a palindrome, {@code false} otherwise
*/ */
public static boolean isPalindromic(ArrayList<Integer> list) { public static boolean isPalindromic(List<Integer> list) {
for (int pos = 0; pos < list.size() / 2; ++pos) { int size = list.size();
if (list.get(pos) != list.get(list.size() - 1 - pos)) { for (int i = 0; i < size / 2; i++) {
if (!list.get(i).equals(list.get(size - 1 - i))) {
return false; return false;
} }
} }
@ -56,12 +73,12 @@ public final class LowestBasePalindrome {
} }
/** /**
* @brief checks if representation of the input number in given base is a palindrome * Checks if the representation of a given number in a specified base is palindromic.
* @param number the input number *
* @param base the given base * @param number the number to be checked
* @exception IllegalArgumentException number is negative or base is less than 2 * @param base the base in which the number will be represented
* @return true, if the input number represented in the given base is a palindrome, false * @return {@code true} if the number is palindromic in the specified base, {@code false} otherwise
* otherwise * @throws IllegalArgumentException if the number is negative or the base is less than 2
*/ */
public static boolean isPalindromicInBase(int number, int base) { public static boolean isPalindromicInBase(int number, int base) {
checkNumber(number); checkNumber(number);
@ -72,7 +89,7 @@ public final class LowestBasePalindrome {
} }
if (number % base == 0) { if (number % base == 0) {
// the last digit of number written in base is 0 // If the last digit of the number in the given base is 0, it can't be palindromic
return false; return false;
} }
@ -80,16 +97,18 @@ public final class LowestBasePalindrome {
} }
/** /**
* @brief finds the smallest base for which the representation of the input number is a * Finds the smallest base in which the representation of a given number is palindromic.
* palindrome *
* @param number the input number * @param number the number to be checked
* @exception IllegalArgumentException number is negative * @return the smallest base in which the number is a palindrome
* @return the smallest base for which the representation of the input number is a palindrome * @throws IllegalArgumentException if the number is negative
*/ */
public static int lowestBasePalindrome(int number) { public static int lowestBasePalindrome(int number) {
checkNumber(number);
int base = 2; int base = 2;
while (!isPalindromicInBase(number, base)) { while (!isPalindromicInBase(number, base)) {
++base; base++;
} }
return base; return base;
} }

View File

@ -2,79 +2,76 @@ package com.thealgorithms.others;
import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.assertTrue;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.HashMap; import java.util.List;
import org.junit.jupiter.api.Test; import java.util.stream.Stream;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
public class LowestBasePalindromeTest { public class LowestBasePalindromeTest {
@Test
public void testIsPalindromicPositive() { @ParameterizedTest
assertTrue(LowestBasePalindrome.isPalindromic(new ArrayList<Integer>())); @MethodSource("provideListsForIsPalindromicPositive")
assertTrue(LowestBasePalindrome.isPalindromic(new ArrayList<Integer>(Arrays.asList(1)))); public void testIsPalindromicPositive(List<Integer> list) {
assertTrue(LowestBasePalindrome.isPalindromic(new ArrayList<Integer>(Arrays.asList(1, 1)))); assertTrue(LowestBasePalindrome.isPalindromic(list));
assertTrue(LowestBasePalindrome.isPalindromic(new ArrayList<Integer>(Arrays.asList(1, 2, 1))));
assertTrue(LowestBasePalindrome.isPalindromic(new ArrayList<Integer>(Arrays.asList(1, 2, 2, 1))));
} }
@Test @ParameterizedTest
public void testIsPalindromicNegative() { @MethodSource("provideListsForIsPalindromicNegative")
assertFalse(LowestBasePalindrome.isPalindromic(new ArrayList<Integer>(Arrays.asList(1, 2)))); public void testIsPalindromicNegative(List<Integer> list) {
assertFalse(LowestBasePalindrome.isPalindromic(new ArrayList<Integer>(Arrays.asList(1, 2, 1, 1)))); assertFalse(LowestBasePalindrome.isPalindromic(list));
} }
@Test @ParameterizedTest
public void testIsPalindromicInBasePositive() { @MethodSource("provideNumbersAndBasesForIsPalindromicInBasePositive")
assertTrue(LowestBasePalindrome.isPalindromicInBase(101, 10)); public void testIsPalindromicInBasePositive(int number, int base) {
assertTrue(LowestBasePalindrome.isPalindromicInBase(1, 190)); assertTrue(LowestBasePalindrome.isPalindromicInBase(number, base));
assertTrue(LowestBasePalindrome.isPalindromicInBase(0, 11));
assertTrue(LowestBasePalindrome.isPalindromicInBase(10101, 10));
assertTrue(LowestBasePalindrome.isPalindromicInBase(23, 22));
} }
@Test @ParameterizedTest
public void testIsPalindromicInBaseNegative() { @MethodSource("provideNumbersAndBasesForIsPalindromicInBaseNegative")
assertFalse(LowestBasePalindrome.isPalindromicInBase(1010, 10)); public void testIsPalindromicInBaseNegative(int number, int base) {
assertFalse(LowestBasePalindrome.isPalindromicInBase(123, 10)); assertFalse(LowestBasePalindrome.isPalindromicInBase(number, base));
} }
@Test @ParameterizedTest
public void testIsPalindromicInBaseThrowsExceptionForNegativeNumbers() { @MethodSource("provideNumbersAndBasesForExceptions")
assertThrows(IllegalArgumentException.class, () -> LowestBasePalindrome.isPalindromicInBase(-1, 5)); public void testIsPalindromicInBaseThrowsException(int number, int base) {
org.junit.jupiter.api.Assertions.assertThrows(IllegalArgumentException.class, () -> LowestBasePalindrome.isPalindromicInBase(number, base));
} }
@Test @ParameterizedTest
public void testIsPalindromicInBaseThrowsExceptionForWrongBases() { @MethodSource("provideNumbersForLowestBasePalindrome")
assertThrows(IllegalArgumentException.class, () -> LowestBasePalindrome.isPalindromicInBase(10, 1)); public void testLowestBasePalindrome(int number, int expectedBase) {
assertEquals(expectedBase, LowestBasePalindrome.lowestBasePalindrome(number));
} }
@Test private static Stream<Arguments> provideListsForIsPalindromicPositive() {
public void testLowestBasePalindrome() { return Stream.of(Arguments.of(new ArrayList<>()), Arguments.of(new ArrayList<>(List.of(1))), Arguments.of(new ArrayList<>(Arrays.asList(1, 1))), Arguments.of(new ArrayList<>(Arrays.asList(1, 2, 1))), Arguments.of(new ArrayList<>(Arrays.asList(1, 2, 2, 1))));
HashMap<Integer, Integer> testCases = new HashMap<>();
testCases.put(0, 2);
testCases.put(1, 2);
testCases.put(2, 3);
testCases.put(3, 2);
testCases.put(10, 3);
testCases.put(11, 10);
testCases.put(15, 2);
testCases.put(39, 12);
testCases.put(44, 10);
testCases.put(58, 28);
testCases.put(69, 22);
testCases.put(79, 78);
testCases.put(87, 28);
testCases.put(90, 14);
testCases.put(5591, 37);
testCases.put(5895, 130);
testCases.put(9950, 198);
testCases.put(9974, 4986);
for (final var tc : testCases.entrySet()) {
assertEquals(LowestBasePalindrome.lowestBasePalindrome(tc.getKey()), tc.getValue());
} }
private static Stream<Arguments> provideListsForIsPalindromicNegative() {
return Stream.of(Arguments.of(new ArrayList<>(Arrays.asList(1, 2))), Arguments.of(new ArrayList<>(Arrays.asList(1, 2, 1, 1))));
}
private static Stream<Arguments> provideNumbersAndBasesForIsPalindromicInBasePositive() {
return Stream.of(Arguments.of(101, 10), Arguments.of(1, 190), Arguments.of(0, 11), Arguments.of(10101, 10), Arguments.of(23, 22));
}
private static Stream<Arguments> provideNumbersAndBasesForIsPalindromicInBaseNegative() {
return Stream.of(Arguments.of(1010, 10), Arguments.of(123, 10));
}
private static Stream<Arguments> provideNumbersAndBasesForExceptions() {
return Stream.of(Arguments.of(-1, 5), Arguments.of(10, 1));
}
private static Stream<Arguments> provideNumbersForLowestBasePalindrome() {
return Stream.of(Arguments.of(0, 2), Arguments.of(1, 2), Arguments.of(2, 3), Arguments.of(3, 2), Arguments.of(10, 3), Arguments.of(11, 10), Arguments.of(15, 2), Arguments.of(39, 12), Arguments.of(44, 10), Arguments.of(58, 28), Arguments.of(69, 22), Arguments.of(79, 78), Arguments.of(87, 28),
Arguments.of(90, 14), Arguments.of(5591, 37), Arguments.of(5895, 130), Arguments.of(9950, 198), Arguments.of(9974, 4986));
} }
} }