from typing import List

from nucs.problems.problem import Problem
from nucs.propagators.propagators import ALG_AFFINE_EQ, ALG_ALLDIFFERENT

A = 0
B = 1
C = 2
D = 3
E = 4
F = 5
G = 6
H = 7
I = 8
J = 9
K = 10
L = 11
M = 12
N = 13
O = 14
P = 15
Q = 16
R = 17
S = 18
T = 19
U = 20
V = 21
W = 22
X = 23
Y = 24
Z = 25


class AlphaProblem(Problem):
    """
    This problem comes from the newsgroup rec.puzzle.
    The numbers from 1 to 26 are assigned to the letters of the alphabet.
    The numbers beside each word are the total of the values assigned to the letters in the word
    (e.g for LYRE: L,Y,R,E might be to equal 5,9,20 and 13 or any other combination that add up to 47).

    Find the value of each letter under the equations:
    BALLET  45     GLEE  66     POLKA      59     SONG     61
    CELLO   43     JAZZ  58     QUARTET    50     SOPRANO  82
    CONCERT 74     LYRE  47     SAXOPHONE 134     THEME    72
    FLUTE   30     OBOE  53     SCALE      51     VIOLIN  100
    FUGUE   50     OPERA 65     SOLO       37     WALTZ    34
    """

    def __init__(self) -> None:
        super().__init__(shr_domains=[(1, 26)] * 26, dom_indices=list(range(26)), dom_offsets=[0] * 26)
        self.set_propagators(
            [
                ([A, B, E, T, L], ALG_AFFINE_EQ, [1, 1, 1, 1, 2, 45]),
                ([C, E, O, L], ALG_AFFINE_EQ, [1, 1, 1, 2, 43]),
                ([E, O, N, R, T, C], ALG_AFFINE_EQ, [1, 1, 1, 1, 1, 2, 74]),
                ([E, F, L, U, T], ALG_AFFINE_EQ, [1, 1, 1, 1, 1, 30]),
                ([E, F, G, U], ALG_AFFINE_EQ, [1, 1, 1, 2, 50]),
                ([G, L, E], ALG_AFFINE_EQ, [1, 1, 2, 66]),
                ([A, J, Z], ALG_AFFINE_EQ, [1, 1, 2, 58]),
                ([E, L, R, Y], ALG_AFFINE_EQ, [1, 1, 1, 1, 47]),
                ([E, B, O], ALG_AFFINE_EQ, [1, 1, 2, 53]),
                ([A, E, P, O, R], ALG_AFFINE_EQ, [1, 1, 1, 1, 1, 65]),
                ([A, K, L, O, P], ALG_AFFINE_EQ, [1, 1, 1, 1, 1, 59]),
                ([A, E, Q, R, U, T], ALG_AFFINE_EQ, [1, 1, 1, 1, 1, 2, 50]),
                ([A, E, H, N, P, S, X, O], ALG_AFFINE_EQ, [1, 1, 1, 1, 1, 1, 1, 2, 134]),
                ([A, C, E, L, S], ALG_AFFINE_EQ, [1, 1, 1, 1, 1, 51]),
                ([L, S, O], ALG_AFFINE_EQ, [1, 1, 2, 37]),
                ([G, N, O, S], ALG_AFFINE_EQ, [1, 1, 1, 1, 61]),
                ([A, N, P, R, S, O], ALG_AFFINE_EQ, [1, 1, 1, 1, 1, 2, 82]),
                ([H, M, T, E], ALG_AFFINE_EQ, [1, 1, 1, 2, 72]),
                ([L, N, O, V, I], ALG_AFFINE_EQ, [1, 1, 1, 1, 2, 100]),
                ([A, L, T, W, Z], ALG_AFFINE_EQ, [1, 1, 1, 1, 1, 34]),
                ([A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z], ALG_ALLDIFFERENT, []),
            ]
        )

    def pretty_print_solution(self, solution: List[int]) -> None:
        print(
            {
                "A": solution[A],
                "B": solution[B],
                "C": solution[C],
                "D": solution[D],
                "E": solution[E],
                "F": solution[F],
                "G": solution[G],
                "H": solution[H],
                "I": solution[I],
                "J": solution[J],
                "K": solution[K],
                "L": solution[L],
                "M": solution[M],
                "N": solution[N],
                "O": solution[O],
                "P": solution[P],
                "Q": solution[Q],
                "R": solution[R],
                "S": solution[S],
                "T": solution[T],
                "U": solution[U],
                "V": solution[V],
                "W": solution[W],
                "X": solution[X],
                "Y": solution[Y],
                "Z": solution[Z],
            }
        )
