Alien Numbers es uno de lo primeros ejercicios prácticos que hay en el GCJ y es el más sencillo que he visto, pero sirve perfectamente para hacerse con la dinámica del concurso y conocer la forma de explicar los problemas. Además, lo que es la estructura básica para leer la entrada y obtener la salida (que es siempre similar) ya la tenemos casi programada y, como buen programador que eres, sabrás reutilizarla como si de un mini entorno de trabajo se tratara.
El problema está basado en una traducción entre distintos sistemas numéricos de distinta base. Literalmente dice:
El sistema numérico decimal está compuesto por diez dígitos que representamos como "0123456789" ordenados de menor a mayor. Imagina que descubres un sistema alienígena representado por los dígitos "oF8". Entonces los números desde el 1 al 10 se dirían como F, 8, Fo, FF, F8, 8o, 8F, 88, Foo, FoF. Nos gustaría ser capaces de trabajar con números en un sistema numérico alienígena arbitrario (del diccionario: que depende sólo de la voluntad o el capricho de una persona y no obedece a principios dictados por la razón, la lógica o las leyes). Generalizando, queremos ser capaces de convertir un número escrito en un sistema alienígena a otro sistema alienígena.
La entrada nos vendrá dada por una serie de líneas donde la primera especifica el número de casos a ejecutar, y las siguientes serán los datos para cada uno de los casos, siguiendo el siguiente formato:
número_alienígena lenguaje_fuente lenguaje_destino
Por ejemplo:
4 9 0123456789 oF8 Foo oF8 0123456789 13 0123456789abcdef 01 CODE O!CDE? A?JM!.
indica que hay 4 casos (primera línea). En el primer caso hay que convertir (traducir) el número "9" teniendo en cuenta que está escrita en el lenguaje alienígena fuente "0123456789" (¿te suena? no es tan alienígena...) y el lenguaje alienígena compuesto por los dígitos "oF8". Como vimos en el enunciado, el resultado para la novena posición ("9") es "Foo". Si tuviera más números se concatenarían.
Para la entrada del ejemplo, y como solución al ejercicio, habría que obtener como salida los números alienígenas traducidos de acuerdo a los lenguajes especificados:
Case #1: Foo Case #2: 9 Case #3: 10011 Case #4: JAM!
¿Fácil, verdad? Si has trabajado con distintos sistemas numéricos el problema lo habrás entendido, sobre todo el primer caso. Y si has hecho un conversor de BCD (código binario decimal) seguro que el primer caso lo resuelves rápidamente. Lo que es más raro es que te hayas enfrentado a dos códigos o lenguajes donde ninguno te es familiar...
Para mi solución, he tomado como lenguaje de referencia para trabajar el binario, por ser el más simple y porque el ordenador es todo un especialista en manejarlo :) Y el problema lo he resuelto en dos pasos: primero convirtiendo el número a binario desde el lenguaje fuente, y segundo,convirtiendo desde binario hasta el lenguaje destino. Para esto he creado una clase "Language" que se construye con la cadena que representa los digitos alienígena expresados en orden de peso ascendente de izquierda a derecha y que dispone de dos métodos para convertir cualquier número en ese lenguaje hasta binario y desde binario.
La idea es, con cada caso, construir los dos lenguajes especificados (origen y destino) y después usar simplemente el método toBinary() sobre el origen y el método fromBinary sobre el destino. La entrada y la salida estándar en C# es trivial y el código completo con la solución es el que muestro abajo.
En sucesivos problemas, el código procesar la entrada y la salida se puede aprovechar porque para el concurso va a ser siempre así. Que pena que no fuera en XML o algo más moderno, porque probablemente sería un handicap más para los que usan C++ (que son mayoría en el concurso) mientras que con C# disponemos de una API rica para estas lides ;)
- using System;
- using System.Text;
- namespace GCJ_01_Alien_Numbers
- {
- internal class AlienNumbers
- {
- [STAThread]
- static void Main(string[] args)
- {
- new AlienNumbers().Run();
- Console.ReadLine();
- }
- private void Run()
- {
- int cases = int.Parse(Console.ReadLine());
- for (int c = 1; c <= cases; c++)
- {
- string[] input = Console.ReadLine().Split(' ');
- Language langSrc = new Language(input[1]);
- Language langDst = new Language(input[2]);
- string translation = langDst.fromBinary(langSrc.toBinary(input[0]));
- Console.WriteLine(String.Format("Case #{0}: {1}", c, translation));
- }
- }
- }
- internal class Language
- {
- string characters;
- int baseLang;
- public Language(string characters)
- {
- this.characters = characters;
- baseLang = characters.Length;
- }
- public int toBinary (string number)
- {
- int binary = 0;
- int numberLength = number.Length;
- for (int c = 1; c <= numberLength; c++)
- {
- binary += characters.IndexOf(number[numberLength - c]) * this.Pow(this.baseLang, c - 1);
- }
- return binary;
- }
- public string fromBinary(int number)
- {
- StringBuilder digit = new StringBuilder();
- while (number > 0)
- {
- int remainder = number % this.baseLang;
- digit.Insert(0, this.characters[remainder]);
- number /= this.baseLang;
- }
- return digit.ToString();
- }
- private int Pow(int b, int e)
- {
- int result = 1;
- while (e-- > 0)
- {
- result *= b;
- }
- return result;
- }
- }
- }954 lecturas
Enviar un comentario nuevo