Universidad de Costa Rica
Escuela de Ciencias de la Computación e Informática
CI-1201 Programación II - 2014b
Profesor Jeisson Hidalgo-Céspedes

Tarea 01

Usted ha sido integrado a un equipo de desarrollo de software libre. Actualmente el equipo está trabajando en un comando eficiente en C para reportar propiedades curiosas de números enteros positivos. Al programa se le ha llamado Number Gossip, pues realiza una funcionalidad similar a la aplicación web homónima superando la limitación de números hasta 9999.

Naturalmente el equipo mantiene el código del proyecto bajo control de versiones. El código fuente del Number Gossip se encuentra en la subcarpeta ngossip del repositorio:

https://github.com/jeissonh/Progra2-14b.git

Clone el repositorio en su máquina de trabajo. Requerirá tener instalado Git y si gusta algún cliente gráfico: TortoiseGit para Windows, RabbitVCS para Linux, SourceTree para OS X. Para clonar el repositorio en una terminal de Unix, emita:

# Vaya a la carpeta donde quiere crear el clon
# Si invoca `cd` sin parámetros, irá a la carpeta personal
$ cd

# Clone el repositorio ahí
$ git clone https://github.com/jeissonh/Progra2-14b.git

# Vaya al repositorio (puede usar la tecla Tab para completar)
$ cd Progra2-14b

# Listar el contenido. Verá una subcarpeta para el proyecto Number Gossip
$ ls -l
drwxr-xr-x 2 jhc jhc 4096 ago 22 15:25 ngossip

# Ir a esa carpeta y ver el contenido
$ cd ngossip
$ ls -l
total 368
-rw-r--r-- 1 jhc jhc 319984 ago 22 15:25 catch.hpp
-rw-r--r-- 1 jhc jhc     47 ago 22 15:25 main.c
-rw-r--r-- 1 jhc jhc   2784 ago 22 15:25 ngossip.c
-rw-r--r-- 1 jhc jhc  15837 ago 22 15:25 ngossip.h
-rw-r--r-- 1 jhc jhc    156 ago 22 15:25 ngossip.pro
-rw-r--r-- 1 jhc jhc  19166 ago 22 15:25 test.cpp
-rw-r--r-- 1 jhc jhc    159 ago 22 15:25 test.pro

$

La aplicación es modular, pues ha sido pensada con visión a largo plazo. Consta de 3 módulos:

  1. libngossip. Una biblioteca reutilizable de C que permite conocer las propiedades de números enteros invocando funciones libres.
  2. test. Un programa que prueba la biblioteca libngossip en busca de errores.
  3. ngossip. Un programa que permite a los usuarios conocer propiedades de números en línea de comandos.

Biblioteca libngossip

Consiste de un conjunto de funciones libres, una por cada propiedad de los números enteros. Las declaraciones se encuentran en el archivo de encabezado ngossip.h, y su implementación en ngossip.c. Se puede compilar independientemente. Como una biblioteca estática:

$ gcc -std=c11 -c ngossip.c -o ngossip.o
$ ar rcs libngossip.a ngossip.o

O como una biblioteca dinámica:

$ gcc -std=c11 -fPIC -c ngossip.c -o ngossip.o
$ gcc -shared -Wl,-soname,libngossip.so.1 -o libngossip.so.1.0.1 ngossip.o

Programa test

Es un programa ejecutable que al correrse prueba cada una de las funciones de la biblioteca libngossip. Consta del archivo test.cpp y dos bibliotecas: Catch Test Library (catch.hpp) y naturalmente nuestra biblioteca libngossip (ngossip.h y ngossip.c). Para generar el ejecutable test se debe utilizar el compilador de C++ por restricción de la biblioteca Catch:

# Compilar el programa de pruebas:
$ g++ -Wall -std=c++11 -o test test.cpp ngossip.c

# El comando anterior generará un ejecutable probablemente mayor a 1MB:
$ ls -lh test
-rwxr-xr-x 1 jhc jhc 1,1M ago 22 16:14 test

# Para correr todos los casos de prueba, se invoca el ejecutable sin parámetros:
$ ./test

# Para correr sólo un caso de prueba, por ejemplo, is_prime() se envía por parámetro:
$ ./test prime
All tests passed (15 assertions in 1 test case)

Si se quieren correr sólo ciertos casos de prueba, se envían los nombres de las funciones sin el prefijo is_ separadas por comas. Por ejemplo, ./test weird, prime

Usted debe agregar al menos una prueba en cada caso del archivo test.cpp. Introduzca un número grande (pero menor a 10000) en la aplicación web Number Gossip, y de acuerdo a los resultados actualice todos los casos de prueba para ese número. Puede buscar números más grandes en otras fuentes de la web y agregar más pruebas. Verifique que el programa de prueba compile y corre, aunque reporte errores. Comparta sus casos de prueba en el repositorio remoto como se indica en la sección Entrega de la solución.

Colabore con el equipo implementando sus dos propiedades de números enteros. Es decir, implementar el cuerpo de las dos funciones que le fueron asignadas en la tabla de abajo. Mientras implementa las funciones, ejecute con frecuencia el programa de pruebas ./test mifuncion con el fin de ver que pase las pruebas escogidas. Piense si se pueden realizar optimizaciones para que la función sea más eficiente y aplíquelas. Recuerde verificar que no se hayan roto los casos de prueba. Debe enviar al menos dos commits de Git: al menos uno por cada función implementada.

EstudianteProp1Prop2
Carlos Luis Rodríguez Núñezis_perfectis_primorial
Christopher Joseph Mora Románis_ecci1is_pentagonal
Daniel Alonso Arce Madrigalis_power_of_2is_persistent
Daniel Josué Rojas Leandrois_ecci2is_hypotenuse
Esteban Raúl Ortega Acuñais_twinis_happy
Fernando (Josué) Pereira Leivais_evilis_fermat
Fernando González Floresis_triangularis_palindrome
Geovanny de Jesús Zúñiga Salasis_deficientis_lazy_caterer
Heiner Gustavo Vindas Chinchillais_product_perfectis_narcissistic
Jairo Rojas Rojasis_squareis_square_free
Jefferson Cose Toruñois_fibonacciis_parasite
José Alberto Alfaro Quirósis_factorialis_mersenne
José Andrés Víquez Hernándezis_pronicis_easy_to_remember
José Manuel Matarrita Camposis_abundantis_automorphic
José Miguel Mesén Camposis_cubeis_undulating
Julián Andrés Calvo Murillois_compositorialis_catalan
Nicole Paola Mora Salazaris_odiousis_tetrahedral
Pablo (José) Vargas Corderois_repdigitis_cake

Programa ngossip

Escriba un comando en C llamado ngossip que aproveche la biblioteca libngossip para permitir a los usuarios obtener propiedades de números. Si el comando se invoca con el parámetro --help imprimirá ayuda:

$ ngossip --help
Usage: ngossip [-iltV] [NUMBERS] [PROPERTIES] [-i FILE]
Number Gossip: Show properties of positive integer NUMBERS. Options:

  -i FILE          Read numbers from FILE
  -l, --list       List all available properties
  -t, --transpose  For each PROPERTIES show applying numbers
  -v, --verbose    Show a short description of each property
      --version    Print version of this program

If not parameters are given, read numbers from standard input until EOF
NUMBERS can have ranges in form n1:n2, e.g: 80:120
$
Ayuda del programa (en inglés)

El programa lee números enteros uno tras otro separados por espacios en blanco. Hay tres fuentes donde el usuario puede indicar los números: (1) por parámetro de invocación:

$ ngossip 13 113 1024
13:
prime
fibonacci deficient happy lucky odious square-free twin ulam

113:
prime
deficient evil square-free

1024:
prime factors: 2^10
proper factors: 2 4 8 16 32 64 128 256 512
deficient odious power_of_2 powerful practical square
$

(2) en un archivo de texto con la opción -i. El archivo sólo debe contener números separados por espacios en blanco (los cambios en línea también son espacio en blanco):

$ cat nums.txt
248 131

$ ./ngossip -i nums.txt
248:
prime factors: 2^3 * 31
proper factors: 2 4 8 31 62 124
deficient odius untouchable

131:
prime
deficient odious palindrome square-free ulam undulating

(3) en la entrada estándar, cuando no se proveen números en ninguna de las dos fuentes anteriores. Si la entrada estándar no se redirecciona, el comando se comporta de forma interactiva y termina su ejecución cuando se ingresa el carácter fin de archivo (Ctrl+D en Unix, Ctrl+Z en MS-DOS):

$ ./ngossip
8888
8888:
prime factors: 2^2 * 3 * 823
proper factors: 2 3 4 6 12 823 1646 2469 3292 4938
abundant apocalyptic_power evil happy untouchable

777
777:
prime factors: 3 * 7 * 37
proper factors: 3 7 21 37 111 259
deficient evil lucky palindrome square_free undulating

^D

Para cada uno de los números ingresados, el comando lista en la salida estándar las propiedades que cumplen cada uno de esos números. El parámetro -v, imprime las propiedades con algún nivel más de detalle:

$ ./ngossip -v 100
100:
prime factors: 2^2 * 5^2
proper factors: 2 4 5 10 20 25 50
abundant: the sum of all its proper factors is more than n
happy: iterating the sum of the squares of its digits leads to 1
odious: has an odd number of 1's in its binary expansion
powerful: for every prime p dividing n, p^2 also divides n
practical: all numbers strictly less than n are sums of distinct divisors of n

La opción -l imprime en la salida estándar la lista de todas las propiedades disponibles en ngossip. Si el parámetro -v está disponible, la lista de propiedades se presenta además con la corta descripción, como en ejemplo anterior.

El usuario podría estar interesado en una o unas pocas propiedades que puede escribir por parámetro. En tal caso, el programa sólo prueba dichas propiedades. El usuario podría mezclar los parámetros en cualquier orden. Por ejemplo, la siguiente es una invocación válida que verifica únicamente las propiedades prime y fibonacci de los números 3, 33, 333 y 33333, en ese orden seguidos por los que se encuentren en el archivo mas.txt, y finalmente 3333. Los números que cumplan esas propiedades las desplegarán con detalles (-v) en la salida estándar.

$ ./ngossip 3 33 -v 333 prime 33333 fibonacci -i mas.txt 3333

Sin embargo, hay parámetros excluyentes de otros. El parámetro --help tiene la mayor prioridad. Si es provee se ignoran todos los demás. Lo mismo ocurre con los parámetros --version y -l que lista las propiedades. Los parámetros restantes pueden coexistir entre ellos. El parámetro -i FILE podría repetirse.

Reto 1. Si el usuario quiere probar muchos números secuenciales, tendrá que proveerlos uno a uno, lo cual es tedioso. Haga que el programa pueda entender rangos. Por ejemplo ngossip 1000:1500 muestra las características de los números entre 1000 y 1500 inclusive.

Reto 2. Si el usuario provee varios números o un rango de ellos, puede estar interesado en saber cuáles de ellos cumplen cierta propiedad. En lugar de imprimir las propiedades de cada número por separado, el usuario quiere ver la propiedad y cuales de los números dados la cumplen. A esto se llama transponer la salida, y se indica con el parámetro -t. Por ejemplo:

Evaluación

  1. [15%] Para un número escogido arbitrariamente, agrega una prueba en cada caso en el archivo test.cpp y lo envía al repositorio remoto de GitHub.
  2. [60%] Implementa sus dos funciones correctamente. Es decir, pasan las pruebas estipuladas.
  3. [10%] La implementación de las dos funciones es relativamente eficiente.
  4. [15%] Colabora con el equipo enviando su implementación al repositorio de control de versiones.

Entrega de la solución

Para presentar su solución, envíe su implementación al repositorio remoto de GitHub. Necesitará crear una cuenta en GitHub.com. Si utiliza un correo distinto al de Mediación Virtual, enviar su nombre de usuario o correo al profesor para agregarlo como colaborador en el repositorio. Luego deberá indicarle al cliente local de Git quién es usted (esto se hace sólo una vez). Por ejemplo:

$ git config --global user.name "Keylor Navas"
$ git config --global user.email "keylor@navas.com"

Los cambios que haya hecho estarán en el directorio de trabajo. Debe enviarlos a su repositorio local (el clon que hizo del repositorio de remoto) con un commit, y luego enviarlos al repositorio remoto con un push:

$ git commit -am 'Implementada la propiedad is_xxx()'
2 files changed, 28 insertions(+), 2 deletions(-)

Finalmente "empuje" los commits que haya hecho localmente hacia el repositorio remoto. No olvide actualizar su repositorio local con los cambios remotos antes de enviar los suyos:

$ git pull
Already up-to-date.

# Si Git dice algo diferente a lo anterior es porque hubo cambios en el repositorio
# remoto. Debe revisar que los dos programas y la biblioteca compilen y corran bien
# Si quiere puede ver los cambios con un cliente gráfico en la bitácora (log)
$ git push

La fecha límite para enviar sus funciones al repositorio de GitHub es el sábado 30 de agosto de 2014 a las 23:55. Si termina antes, puede ayudar en forma presencial a algún compañero(a) a que implemente sus funciones. No significa implementar las funciones de otra persona.