Как проще описать логику из таблицы на языке Java?

введите сюда описание изображения На input1 могут поступить или два одинаковых сигнала (aa) или разные сигналы (ab). На input2 могут поступить или два одинаковых сигнала (аа) или bb (если они не равны сигналам на input1), или разные сигналы (ab, bc, ac и cd - в зависимости от того, равны они или нет сигналам на input1). На input3 могут поступать различные парные комбинации из сигналов a, b, c, d. В зависимости от комбинаций сигналов на input 1, input 2 и input 3 на выходе output формируется сигнал с кодом 1, 2, 3, 4, 5, 6, 7, 8, 9 или 10, согласно логике из таблицs. Как проще описать данную логику на Javа?


Ответы (2 шт):

Автор решения: Дмитрий

Я бы не заморачивался по поводу "эмуляции" табличных данных хотя бы просто потому, что это представление только визуально выглядит как таблица, но если вы ее сравните к примеру с таблицей Пифагора, то быстро поймете, что таблица Пифагора по сути отличается кардинально (в ней данные ищут на пересечении заглавной первой строки и заглавного первого столбца, как в любой классической таблице, а в вашей это не так). Таким образом, ваша "таблица" не является классическим применением таблицы, это просто кому-то показалось удачным отобразить данные именно так.

Посему, на мой взгляд, на много проще прибегнуть к помощи хешированных структур данных. Вариаций данных всего 10, описать их не составляет труда. И это в любом случае проще, чем эмулировать логически таблицу или любую обработку данных.

Посему делаем достаточно простой класс:

import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.Value;

public class Decoder {

    private final static Map<InputDataWrapper, Integer> MAP = new HashMap<>();   
    private final static Map<String, String> CONVERTER = new HashMap<>();
    
    static{        
        MAP.put(new InputDataWrapper("aa", "aa", "aa"), 1);
        MAP.put(new InputDataWrapper("aa", "ab", "aa"), 2);
        MAP.put(new InputDataWrapper("aa", "ab", "ab"), 3);
        MAP.put(new InputDataWrapper("aa", "bb", "ab"), 4);
        MAP.put(new InputDataWrapper("aa", "bc", "ab"), 5);
        MAP.put(new InputDataWrapper("ab", "ab", "aa"), 6);
        MAP.put(new InputDataWrapper("ab", "ab", "ab"), 7);
        MAP.put(new InputDataWrapper("ab", "ac", "ab"), 8);
        MAP.put(new InputDataWrapper("ab", "ac", "aa"), 9);
        MAP.put(new InputDataWrapper("ab", "cd", "ac"), 10);
        
        CONVERTER.put("ba", "ab");
        CONVERTER.put("ca", "ac");
        CONVERTER.put("cb", "bc");
        CONVERTER.put("dc", "cd");
    }

    private Optional<Integer> get(String arg1, String arg2, String arg3, String arg4, String arg5, String arg6) {
        try {
            return Optional.ofNullable(MAP.get(new InputData(arg1, arg2, arg3, arg4, arg5, arg6).toInput()));
        } catch (Exception e) {
            return Optional.empty();
        }
    }
    
    @Value
    private static class InputDataWrapper {        
        private String input1;
        private String input2;
        private String input3;
    }
    
    @Value
    private static class InputData{
        
        private final static List<String> MASK = Arrays.asList("a", "b", "c", "d");
        
        private String inputA1;
        private String inputA2;
        
        private String inputB1;
        private String inputB2;
        
        private String inputC1;
        private String inputC2;
        
        @Getter(AccessLevel.NONE)
        private Map<String, String> maskMap = new HashMap<>();

        public InputData(String inputA1, String inputA2, String inputB1, String inputB2, String inputC1, String inputC2) {
            this.inputA1 = inputA1;
            this.inputA2 = inputA2;
            this.inputB1 = inputB1;
            this.inputB2 = inputB2;
            this.inputC1 = inputC1;
            this.inputC2 = inputC2;         
            Iterator<String> maskIterator = MASK.iterator();
            for (String value : new String[]{inputA1, inputA2, inputC1, inputC2, inputB1, inputB2}) {
                if(!maskMap.containsKey(value)) maskMap.put(value, maskIterator.next());
            }
        }
        
        public InputDataWrapper toInput(){
            return new InputDataWrapper(convert(inputA1, inputA2), convert(inputB1, inputB2), convert(inputC1, inputC2));
        }
        
        private String convert(String arg1, String arg2){
            String value = maskMap.getOrDefault(arg1, "") + maskMap.getOrDefault(arg2, "");
            return CONVERTER.getOrDefault(value, value);
        }
        
    }
    
}

И теперь вызываем единственный публичный метод, передавая сигналы:

Decoder decoder = new Decoder();
Optional<Integer> result = decoder.get("слон", "сова", "слон", "волк", "слон", "сова");
→ Ссылка
Автор решения: Stanislav Volodarskiy

Сложная задача. До начала решения три аргумента переводятся в массив из шести элементов. Для этого массива перебираются все возможные перестановки внутри последовательных пар - (0, 1), (2, 3), (4, 5). Каждая перестановка сравнивается в каждым из десяти образцов:

import java.util.HashMap;
import java.util.Map;

public class Temp {
    private static String[] table = {
        "aaaaaa",
        "aaabaa",
        "aaabab",
        "aabbab",
        "aabcab",
        "ababaa",
        "ababab",
        "abacab",
        "abacaa",
        "abcdac"
    };

    private static void parse(String[] board, int i, String input) {
        input = input.trim();
        int len = input.length();
        int half = len / 2;
        board[i    ] = input.substring(0, half);
        board[i + 1] = input.substring(len - half);
    }

    private static boolean matchPattern(String pattern, String[] board) {
        assert pattern.length() == board.length;
        Map<String, Character> map_bp = new HashMap<>();
        Map<Character, String> map_pb = new HashMap<>();
        for (int i = 0; i < pattern.length(); ++i) {
            char c = pattern.charAt(i);
            String s = board[i];
            if (map_bp.containsKey(s)) {
                if (!map_pb.containsKey(c)) {
                    return false;
                }
                if ((char)map_bp.get(s) != c) {
                    return false;
                }
                if (!map_pb.get(c).equals(s)) {
                    return false;
                }
            } else {
                if (map_pb.containsKey(c)) {
                    return false;
                }
                map_bp.put(s, c);
                map_pb.put(c, s);
            }
        }
        return true;
    }

    private static int findPattern(String[] board) {
        for (int i = 0; i < table.length; ++i) {
            if (matchPattern(table[i], board)) {
                return i;
            }
        }
        return -1;
    }

    private static int shuffleBoard(String[] board, int i) {
        if (i == board.length) {
            return findPattern(board);
        }
        int j = shuffleBoard(board, i + 2);
        if (j != -1) {
            return j;
        }
        String s = board[i];
        board[i] = board[i + 1];
        board[i + 1] = s;
        return shuffleBoard(board, i + 2);
    }

    private static int decode(String i1, String i2, String i3) {
        String[] board = new String[6];
        parse(board, 0, i1);
        parse(board, 2, i2);
        parse(board, 4, i3);
        return shuffleBoard(board, 0) + 1;
    }

    private static void test(String i1, String i2, String i3) {
        System.out.println(String.format(
            "%d <- \"%s\", \"%s\", \"%s\"",
            decode(i1, i2, i3),
            i1,
            i2,
            i3
        ));
    }

    public static void main(String... args){
        test("ab", "ab", "ab");
        test("3 попугая 5 попугаев", "3 попугая 5 попугаев ", "3 попугая 5 попугаев ");
        test("2п 7п", "7п 2п ", "2п 7п ");
        test("4п 9п", "9п 4п ", "9п 4п ");
        test("ab", "ac", "ab");
        test("4п 7п", "4п 9п", "4п 7п");
        test("7п 4п", "2п 4п", "4п 7п");
        test("ab", "cd", "ac");
        test("ab", "cd", "aa");
    }
}
$ javac Temp.java && java -ea Temp
7 <- "ab", "ab", "ab"
7 <- "3 попугая 5 попугаев", "3 попугая 5 попугаев ", "3 попугая 5 попугаев "
7 <- "2п 7п", "7п 2п ", "2п 7п "
7 <- "4п 9п", "9п 4п ", "9п 4п "
8 <- "ab", "ac", "ab"
8 <- "4п 7п", "4п 9п", "4п 7п"
8 <- "7п 4п", "2п 4п", "4п 7п"
10 <- "ab", "cd", "ac"
0 <- "ab", "cd", "aa"

P.S. Сомнительное место - разбиение строк на "половинки". У меня это просто половинки. Для всех ваших примеров работает, но выглядит рискованно.

→ Ссылка