/*   mr
     Author: Christian Gimenez

     Copyright (C) 2018 Christian Gimenez

     This program is free software: you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
     the Free Software Foundation, either version 3 of the License, or
     at your option) any later version.

     This program is distributed in the hope that it will be useful,
     but WITHOUT ANY WARRANTY; without even the implied warranty of
     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     GNU General Public License for more details.

     You should have received a copy of the GNU General Public License
     along with this program.  If not, see <http://www.gnu.org/licenses/>.

     14 sep 2018
*/


:- module(mr, [
	      msg/1,
	      mrprint/1,
	      to_num/2,
	      to_utf/2,
	      translate/2,
	      decrypt/0
	  ]).
/** <module> mr: Resolver un mensaje en ROT-13

Predicados para resolver el mensaje cifrado que aparece en Mr. Robot, episodio 
11 (ver foto de la página  https://www.geekwire.com/2016/mr-robot-rewind-code-
cracking-mysterious-mind-bending-episode-11/ con licencia: 
Copyright (C) 2011-2018 GeekWire, LLC.)

decrypt/0 realiza lo necesario para descifrar el mensaje en msg/1.
*/

/**
   letter(+C: int, ?Code: int) is det

Mapear un número a un caracter UTF-8/ASCII.

@see letteri/2
*/
letter(C, Code) :-
    Code is C + 65.

/**
   letteri(+Code: int, C: int) is det

Inverso a letter/2. Mapear un caracter UTF-8/ASCII a número.

@see letter/2
*/
letteri(Code, C) :-
    C is Code - 65.

/**
   rotletter(+C: int, ?N: int) is det

Realizar el ROT-14 descifrando el número de entrada.

@param C El número de entrada (¡no es el UTF-8/ASCII!).
*/
rotletter(C, N) :-
    N is (C - 14) mod 26.

/**
   translate(+Input: list, ?Output: list) is det

Aplicar el ROT-14 a una lista de números.

@param Input Una lista de números.
@param Output Una lista de números con ROT-14 aplicado.
*/
translate([], []).
translate([C|RC], [N|RN]) :-
    rotletter(C, N),!,
    translate(RC, RN).

/**
   to_utf(+NumList: list, ?Codes: codes) is det

Transformar una lista de números en códigos UTF-8/ASCII. Se utiliza letter/2 
para cada caracter.

@see letter/2
*/
to_utf([],[]).
to_utf([C|Rest],[CU|RU]) :-
    letter(C, CU),!,
    to_utf(Rest, RU).

/**
   to_num(+Codes: codes, ?NumList: list) is det

Transformar string de códigos en UTF-8/ASCII a números. Se utiliza letteri/2
para cada caracter.

@see letteri/2
*/
to_num([],[]).
to_num([Code|Rest], [Num|RN]) :-
    letteri(Code, Num), !,
    
    to_num(Rest, RN).

/**
   mrprint(C: list)

Imprimir en pantalla la lista de números en letras.

@param C Una lista de números donde la A es 00.
*/
mrprint(C) :-
    to_utf(C, CU),
    format('~s', [CU]).

/**
   msg(lstnums: list)

Mensaje que aparece en Mr. Robot, episodio 11.

Obtenido de la imagen del panfleto desde:
https://www.geekwire.com/2016/mr-robot-rewind-code-cracking-mysterious-mind-bending-episode-11/
con licencia: Copyright (C) 2011-2018 GeekWire, LLC.

@param lstnums La lista de números.
*/
msg([07,21,18,03,18,05,05,22,01,03,14,20,
    18,06,10,22,25,25,21,18,25,03,
    12,02,08,19,22,01,17,12,02,08,
    05,16,14,25,25,22,01,20,15,08,
    07,17,02,01,07,15,18,17,08,03,18,
    17,16,08,07,17,02,10,01,07,21,
    18,10,02,02,17,06,07,21,18,12,
    15,18,18,05,17,02,06]).

/**
   decrypt

Descifrar y mostrar el texto.
*/
decrypt :-
    msg(A), translate(A,B), mrprint(B).

%% A B C D
%% 1 2 3 
%% 07 21 
%% G
