Вирішив спробувати через HashMap. Не проходить по 1 і 2 умові. З другою зрозуміло, там проблема в циклі, з 1 так і не зрозумів чому. Хто має бажання допомогти? :)
package ua.javarush.task.pro.task09.task0908;
import java.util.*;
import java.util.regex.Pattern;
/*
Двійково-шістнадцятковий конвертер
*/
public class Solution {
public static void main(String[] args) {
String binaryNumber = "100111010000";
System.out.println("Двійкове число " + binaryNumber + " дорівнює шістнадцятковому числу " + toHex(binaryNumber));
String hexNumber = "9d0";
System.out.println("Шістнадцяткове число " + hexNumber + " дорівнює двійковому числу " + toBinary(hexNumber));
}
public static String toHex(String binaryNumber) {
String hexNumber = ""; // присвоєння шістандцятковому числу початкового значення - пустий рядок.
/* перевірка значення двійкового числа на відмінність від значення пустого рядка чи null */
/* binaryNumber.isEmpty(), binaryNumber.equals(""), binaryNumber.equals(null) викидає помилку NPE,
якщо binaryNumber дійсно дорівнює null */
if (binaryNumber == null || binaryNumber == "") {
return hexNumber;
}
/* перевірка значення двійкового числа на наявність символів відмінних від '0' та '1' */
char[] charsOfBinaryNumber = binaryNumber.toCharArray();
for (char charOfBinaryNumber : charsOfBinaryNumber) {
if (charOfBinaryNumber != '0' && charOfBinaryNumber != '1') {
return hexNumber;
}
}
/* перевірка кратності кількості символів двійкового числа числу 4 і виправлення якщо є остача від ділення*/
int binaryNumberLength = binaryNumber.length();
int qtyOfMissedDigits = binaryNumberLength % 4;
if (qtyOfMissedDigits != 0) {
for (int i = 4; i > qtyOfMissedDigits; i--) {
binaryNumber = "0".concat(binaryNumber);
}
return binaryNumber;
}
// Реалізація конвертування двійкового значення числа в шістнадцяткове за допомогою класу HashMap
/* Cтворення об'єкту toHex класу HashMap з подальшим його наповненням парами елементів "ключ-значення"
"Ключем" виступає 4-бітна частина двійкового значення числа (всі її можливі варіанти), а "значенням"
виступає відповідний символ шістнадцяткового подання. Тип "значення" було прийнято робити String з метою
подальшої конкатенації рядків.
*/
HashMap<String, String> toHex = new HashMap<>();
toHex.put("0000", "0");
toHex.put("0001", "1");
toHex.put("0010", "2");
toHex.put("0011", "3");
toHex.put("0100", "4");
toHex.put("0101", "5");
toHex.put("0110", "6");
toHex.put("0111", "7");
toHex.put("1000", "8");
toHex.put("1001", "9");
toHex.put("1010", "a");
toHex.put("1011", "b");
toHex.put("1100", "c");
toHex.put("1101", "d");
toHex.put("1110", "e");
toHex.put("1111", "f");
/* Визначаємо кількість символів шістнадцяткового подання числа, виходячи з відомого значення довжини
двійкового подання числа та знання того що 1 символу шістнадцяткового подання відповідають 4 символи
двійкового подання */
int qtyOfHexChars = binaryNumberLength / 4;
/* Ініціалізуємо початковим значенням пустого рядка змінну, що позначатиме 4-бітну частину двійкового
подання числа */
String binaryPart = "";
/* Створюємо "тимчасовий" рядок класу StringBuilder, що є копією двійкового подання числа, для можливості
його зміни в циклі*/
StringBuilder temporary = new StringBuilder(binaryNumber);
/* Тут починається магія :) і 2 години реалізації... Створюємо цикл на 3 витка (саме стільки символів буде
в шістнадцятковому поданні числа. На кожному витку методом substring повертаємо частину елементів рядка
(4 біти), що позначає двійкове подання числа (з "тимчасового рядка"), та одразу ж видаляємо її,
щоб на наступному витку циклу знову не "захопити" цю саму частинку*/
for (int i = 0; i < qtyOfHexChars; i++) {
binaryPart = temporary.substring(0, (binaryNumberLength / qtyOfHexChars));
temporary.delete(0, (binaryNumberLength / qtyOfHexChars));
/* Повернену частину двійкового подання числа, на кожному витку циклу порівнюємо з множиною "ключів"
створеного об'єкту toHex класу HashMap. Коли метод equals() знаходить співпадіння, ми створємо рядок
hexPart, що фактично є частиною шістнадцяткового подання числа, а саме одним з його символів. В цьому ж
циклі програмуємо конкатенацію всіх hexPart-ів, що сформуються на основі роботи зовнішнього циклу.
Результатом конкатенації - буде рядок, що і буде результатом методу, а саме шістнадцяткове подання числа.
Було використано метод Set<Map.Entry<T key, T value>> entrySet() з рівня №14 (саме тут і прийшла ідея,
як вирішити цю задачу :)*/
for (var pair : toHex.entrySet()) {
if (binaryPart.equals(pair.getKey())) {
String hexPart = pair.getValue();
hexNumber = hexNumber.concat(hexPart);
}
}
}
return hexNumber;
}
public static String toBinary(String hexNumber) {
String binaryNumber = ""; // присвоєння двійковому числу початкового значення - пустий рядок.
/* перевірка значення шістнадцяткового числа на відмінність від значення пустого рядка чи null */
/* hexNumber.isEmpty(), hexNumber.equals(""), hexNumber.equals(null) викидає помилку NPE,
якщо hexNumber дійсно дорівнює null */
if (hexNumber == null || hexNumber == "") {
return binaryNumber;
}
/* перевірка шістнадцяткового числа на наявність символів відмінних від вказаних в множині HashSet.
ArrayList не було потреби створювати, оскільки колекції типу Set цілком достатньо.*/
char[] charsOfHexNumber = hexNumber.toCharArray();
HashSet<Character> hexNumberPossibleChars = new HashSet<>();
Collections.addAll(hexNumberPossibleChars, '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f');
for (char charOfHexNumber : charsOfHexNumber) {
if (!hexNumberPossibleChars.contains(charOfHexNumber)) {
return binaryNumber;
}
// Реалізація конвертування шістанадцяткового значення числа в двійкове за допомогою класу HashMap
/* Cтворення об'єкту toBinary класу HashMap з подальшим його наповненням парами елементів "ключ-значення"
"Ключем" виступає кожний з можливих символів шістнадцяткового подання числа, а "значенням" - відповідна
4-бітна частина двійкового значення числа */
HashMap<Character, String> toBinary = new HashMap<>();
toBinary.put('0', "0000");
toBinary.put('1', "0001");
toBinary.put('2', "0010");
toBinary.put('3', "0011");
toBinary.put('4', "0100");
toBinary.put('5', "0101");
toBinary.put('6', "0110");
toBinary.put('7', "0111");
toBinary.put('8', "1000");
toBinary.put('9', "1001");
toBinary.put('a', "1010");
toBinary.put('b', "1011");
toBinary.put('c', "1100");
toBinary.put('d', "1101");
toBinary.put('e', "1110");
toBinary.put('f', "1111");
/* Визначаємо кількість "4-бітних рядків" двійкового подання числа, виходячи з відомого значення довжини
шістнадцяткового подання числа та знання того що 1 символу шістнадцяткового подання відповідають 4 символи
двійкового подання */
int qtyOfBinaryStringParts = hexNumber.length();
/* А тут у мене ПРОБЛЕМА, компілятор тричі повертає двійкове число*/
for (int i = 0; i < qtyOfBinaryStringParts; i++) {
for (var pair : toBinary.entrySet()) {
if (hexNumber.charAt(i) == pair.getKey()) {
String binaryPart = pair.getValue();
binaryNumber = binaryNumber.concat(binaryPart);
}
}
}
}
return binaryNumber;
}
}