Está en la página 1de 63

lica de Chile

Pontificia Universidad Cato


Escuela de Ingeniera
n
Departamento de Ciencia de la Computacio
IIC1103 Introducci
on a la Programaci
on

Captulo 6: Arreglos
Resumen te
orico
Arreglos
Hasta ahora poco a poco hemos podido almacenar y trabajar con informaci
on en java de manera cada vez
m
as eficiente.
Sin embargo, cuando tenemos que trabajar con muchos objetos del mismo tipo, el c
odigo se vuelve un poco
ineficiente. Por eso es que existen estructuras llamadas arreglos, que hacen las veces de vectores, donde se
puede almacenar informaci
on del mismo tipo.
Es como una caja seccionada, donde podemos guardar un dato en cada casilla. Supongamos que cada casilla
guarda la palabra que representa a un n
umero.

Algo importante es que al definir un arreglo, este asigna posiciones a cada uno de los datos almacenados
comenzando desde CERO, entonces si el arreglo llega hasta la posici
on n, tendr
a n+1 elementos.
Por ejemplo: Arreglo de Strings
Podemos definirlo asignando el n
umero de posiciones que tendr
a al instante.
//declaracion del arreglo
String[] nombres=new String[3];
nombres[0]="Juan";
nombres[1]="Pablo";
nombres[2]="Ana";
Podemos definirlo tambien de un largo determinado en un ciclo o directamente con sus elementos.
//declaracion del arreglo directamente
char[] iniciales={a,b,c};
Es com
un asignar valores a los arreglos recorriendo cada una de sus casillas.
//declaracion en un ciclo con los m
ultiplos de 17
int[] multiplos=new int[10];
for (int i=0; i<10; i++)
{
multiplos[i]=(i+1)*17;
}

IIC1103 Captulo 6: Arreglos

Para utilizar la informaci


on que guarda el arreglo en una determinada posici
on, lo llamamos de la siguiente
manera:
<identificador>[i]
Por ejemplo en el caso de los m
ultiplos, si yo quisiera averiguar el 5 deg m
ultiplo de 17, tengo que escribir:
int quinto=multiplos[4];
Entonces quinto = 5x17 (ojo con las posiciones que est
an definidas para el arreglo, comienzan desde cero).
Podemos tener arreglos de cualquier cosa, de String, int, char, objetos, arreglos, etc.
Importante: Para definir un arreglo se debe utilizar el smbolo [ ]. De la siguiente manera inicializamos el
arreglo:
<tipo>[ ] <identificador> = new <tipo>[n] ;
Aunque cada una de las posiciones por defecto est
a vaca o nula (null).
Al igual que los otros objetos podemos crearlo y no inicializarlo hasta que sea necesario, lo importante es que
ANTES de asignarle valores a cada espacio, debemos indicarle al arreglo su largo (a menos que lo creemos
directamente, lo que no es muy usual).
Existen algunos comandos que se utilizan con los arreglos, por ejemplo, para saber el largo del arreglo, tenemos:
<identificador>.length;
Que nos devolver
a el ndeg de valores que almacena el arreglo, es decir, al n
umero que ingresamos al declararlo. Por ejemplo, si nuestro arreglo tiene casillas 0, 1 y 2, lenght nos retornar
a 3.
Un arreglo NO se puede asignar a otro arreglo, por ejemplo, si se tiene que:
int[] Pares={2, 4, 6, 8, 10};
int[] num=new int[5];
No puedo hacer la asignaci
on siguiente:
num=Pares;
Esta asignaci
on no copiar
a los valores, si no que, al igual que en los objetos, cambiar
a la referencia num,
de manera que apunte a la misma direccion de memoria que Pares. Para todos los efectos, ambas variables
Pares y num estar
an apuntando al mismo arreglo. Para copiar los valores la forma correcta es:
for (int i=0; i<num.length; i++)
{
num[i]=Pares[i];
}

IIC1103 Captulo 6: Arreglos

Matrices
Las matrices no son mas que arreglos de arreglos, simplemente como un dato guardado en un espacio que
ahora no se define por una posici
on, sino por un par de coordenadas.

Las matrices pueden ser regulares o irregulares, es decir, puede que en cada fila, el n
umero de elementos sea
distinto, o pueden no ser cuadradas, etc.
La forma de definirlas es:
<tipo>[ ][ ] <identificador> = new <tipo>[ ][ ];

IIC1103 Captulo 6: Arreglos

Ejemplos
Problema 1: Preguntas Varias
Enunciado
Responda las siguientes preguntas:
1. Responda las siguientes preguntas en base al arreglo: int[] array = {0,1,2,3}:

a) Si se realiza la instrucci
on array[1] = array[2]; seguida por la instrucci
on array[2] = array[2]
+ 1;, cu
ales son los valores del arreglo array?por que?
b) Si se realiza la instrucci
on array[1] = array[2]; seguida por la instrucci
on array[2] = 4;,
cu
ales son los valores del arreglo array?por que?

2. Responda las siguientes preguntas en base al arreglo:


String [] array = { " las " ," los " , " el " ," un " };

a) Si se realiza la instrucci
on array[1] = array[2]; seguida por la instrucci
on array[2] = array[2]
+ "la";, cu
ales son los valores del arreglo array?por que?
b) Si se realiza la instrucci
on array[1] = array[2]; seguida por la instrucci
on array[2] = "la";,
cu
ales son los valores del arreglo array?por que?
3. Existe la clase Auto declarada de la siguiente forma:
class Auto {
private String color ;
private int agno ;
public Auto ( String _color , int _agno ) {...}
public String getColor () { return color ; }
public int getAgno () { return agno ; }
public void setColor ( String nuevo ) { color = nuevo ; }
public void setAgno ( int nuevo ) { agno = nuevo ; }
}

Responda las siguientes preguntas en base al arreglo:


Auto [] array = { new Auto ( " gris " , 2000) , new Auto ( " azul " , 1999) ,
new Auto ( " blanco " , 2005) , new Auto ( " rojo " , 2000)}:

a) Si se realiza la instrucci
on array[1] = array[2]; seguida por la instrucci
on
array[2].setAgno(array[2].getAgno()+1);, cu
ales son los valores de los atributos de los objetos del arreglo array?por que?
b) Si se realiza la instrucci
on array[1] = array[2]; seguida por la instrucci
on array[2] = new
Auto("negro", 2009);, cu
ales son los valores de los atributos de los objetos del arreglo array?por
que?
c) Si se realiza la instrucci
on array[3].setColor("gris") cu
al es el resultado de la comparaci
on
array[0] == array[3]?por que?
Criterios de soluci
on
En este ejercicio lo importante es tener claro cuando las variables se copian por valor y cuando por referencia.
En las dos primeras preguntas, al tratarse de arreglos de enteros y Strings las variables se copian por valor,
por lo que luego de copiadas quedan completamente independientes. Cuando se trata de objetos las variables
se copian por referencia, lo que implica que ambas (la original y la nueva copiada) referencian al mismo
objeto y los cambios que se hagan a una se reflejan tambien en la otra.
IIC1103 Captulo 6: Arreglos

Posible soluci
on
1. Soluci
on
a) 0,2,3,3
La primera instrucci
on hace una copia desde la posici
on 1 a la 2, y la segunda instrucci
on solamente modifica el valor en el casillero 2, ya que por ser int los casilleros 1 y 2 se mantienen
independientes.
b) 0,2,4,3
La misma justificaci
on anterior, como la primera instrucci
on realiza una copia del valor de la
casilla 2 a la 1, ambas se mantienen independientes.
2. Soluci
on
a) { " las " ," el " ," ella " ," un " };
La primera instrucci
on hace una copia de la referencia de la casilla 2 a la casilla 1, mostrando
ambos el mismo valor. La segunda instrucci
on modifica el String en la casilla 2, creando un nuevo
String (son inmutables) independiente del String en la casilla 1.
b) { " las " ," el " ," la " ," un " };
Al igual que la pregunta anterior, la primera instrucci
on hace una copia de la referencia de la
casilla 2 a la casilla 1, mostrando ambos el mismo valor. La segunda instrucci
on crea un nuevo
String en la casilla 2, independiente del String en la casilla 1.
3. Soluci
on
a) { Auto ( " gris " , 2000) , Auto ( " blanco " , 2006) ,
Auto ( " blanco " , 2006) , Auto ( " rojo " , 2000)}:

Con la primera instrucci


on, tanto la casilla 1 como la 2 del arreglo referencian al mismo objeto.
Al modificar este objeto con la segunda instrucci
on, cambian los atributos del objeto referenciado
tanto por la casilla 1 como por la 2, dado que son el mismo.
b) { Auto ( " gris " , 2000) , Auto ( " blanco " , 2005) ,
Auto ( " negro " , 2009) , Auto ( " rojo " , 2000)}:

Con la primera instrucci


on, tanto la casilla 1 como la 2 del arreglo referencian al mismo objeto.
Pero la segunda instrucci
on crea un nuevo objeto en la casilla 2, lo que hace que esta quede
independiente del objeto referenciado por la casilla 1. Por ende, la segunda instrucci
on no afecta
a la casilla 1.
c) La comparaci
on es a nivel de objetos, no de los valores de los atributos. Por ende, la comparaci
on
es false, ya que los objetos referenciados por la casilla 0 y por la casilla 3 son distintos (aunque
el valor de los atributos sea el mismo).

IIC1103 Captulo 6: Arreglos

Problema 2: M
as Repetidos
Enunciado
En esta pregunta usted debe implementar un metodo con encabezado:
public int repetidos ( int arreglo [])

que recibe como entrada un arreglo de n


umeros enteros mayores o iguales que cero, y retorna el valor en el
arreglo que aparece repetido un mayor n
umero de veces. Por ejemplo, si arreglo almacena la lista de n
umeros [1, 33, 4, 2, 4, 97, 0, 5, 4, 3, 48, 6, 4, 4, 3], entonces repetidos retorna el valor 4, ya que este es el n
umero
que aparece repetido una mayor cantidad de veces en arreglo.
Nota: Si hay dos o m
as n
umeros que satisfagan la condici
on mencionada arriba, entonces el metodo
repetidos tiene que retornar alguno de ellos.
Criterios de soluci
on
Una manera de resolver este ejercicio es utilizar un arreglo auxiliar que en la posici
on i almacene el n
umero
de veces que el n
umero i aparece en el arreglo original. Para hacer esto lo primero que debemos obtener
es el valor m
aximo que contiene el arreglo original pues este valor representar
a el largo de nuestro arreglo
auxiliar. Luego llenamos el arreglo auxiliar aumentando en uno la cuenta en la posici
on adecuada seg
un el
n
umero que aparezca en el arreglo original. Finalmente, revisamos el arreglo auxiliar y obtenemos el mayor
valor guardado, donde la posici
on nos dar
a el n
umero al que corresponde el mayor n
umero de repeticiones.
Posible soluci
on
public int r e p e t i d o s( int arreglo []) {
int i , max , indice ;
int aux [];
max = 0;
for ( i = 1; i < arreglo . length ; i ++) {
if ( arreglo [ i ] > max ) {
max = arreglo [ i ];
}
}
aux = new int [ max + 1];
for ( i = 0; i < max + 1; i ++) {
aux [ i ] = 0;
}
for ( i = 0; i < arreglo . length ; i ++) {
aux [ arreglo [ i ]]++;
}
max = aux [0];
indice = 0;
for ( i = 1; i < aux . length ; i ++) {
if ( aux [ i ] > max ) {
max = aux [ i ];
indice = i ;
}
}
return ( indice );
}

IIC1103 Captulo 6: Arreglos

Problema 3: Patrones
Enunciado
Se le ha pedido ayuda para escribir un programa que detecte patrones an
omalos en el funcionamiento de
maquinaria industrial en una f
abrica.
Cada da una m
aquina registra minuto a minuto su temperatura de funcionamiento, la cual es almacenada
en un arreglo como el que se muestra a continuaci
on:

Se han establecido dos condiciones que revelan un posible funcionamiento an


omalo en una m
aquina:
Oscilacion: la cual se reconoce cuando aumenta (o disminuye) la temperatura en dos intervalos consecutivos (t1 > t0 y t2 > t1) y luego disminuye (o aumenta) la temperatura en dos intervalos consecutivos
(t3 < t2 y t4 < t3). En el arreglo anterior, se pueden apreciar los dos tipos de oscilaciones: una
ascendente (a partir del instante 4) y otra descendente (a partir del instante 11).
Ciclicidad diaria: la cual se produce cuando en dos das seguidos se repite una secuencia de tres temperaturas en el mismo instante del da. Si el siguiente arreglo corresponde al da siguiente al del arreglo
anterior:
Entonces hay ciclicidad diaria a partir del instante 2, del instante 9 y del instante 16.
Escriba en lenguaje Java los siguientes metodos para ayudar a detectar comportamientos an
omalos:
a) DetectarOscilaciones
// Muestra en consola mensajes indicando oscilaciones
// Recibe un arreglo que contiene las temperaturas registradas en un d
a
// cualquiera
public static void DetectaOscilaciones(int[] regDia1) { ... }
En el caso anterior, debera desplegar los siguientes mensajes:
Oscilaci
on ascendente a partir del instante 4
Oscilaci
on descendente a partir del instante 11
b) DetectarCiclicidad
// Muestra en consola mensajes indicando ciclicidades
// Recibe dos arreglos que contienen las temperaturas de dos d
as
// consecutivos
public static void DetectaCiclicidad(int[] regDia1, int[] regDia2) { ... }
En el caso anterior, debera desplegar los siguientes mensajes:
Ciclicidad diaria a partir del instante 2
Ciclicidad diaria a partir del instante 9
Ciclicidad diaria a partir del instante 16

IIC1103 Captulo 6: Arreglos

Criterios de soluci
on
NOTA: el ndice de la u
ltima posici
on de un arreglo es, ocupando como ejemplo regDia1, regDia1.length-1,
ya que los ndices parten desde cero.
a) En este problema lo importante es darse cuenta de que s
olo hay que comparar enteros y la verdadera
dificultad se encuentra en sacar estos enteros de los arreglos. Por esto, para comparar el da t con el da t+1,
sacamos el entero t+1 del arreglo (regDia1[t+1]) y lo comparamos con el entero t del arreglo (regDia1[t]).
Esto luego se hace para t+2, t+3 y t+4 buscando la condici
on indicada por el enunciado. Es importante
notar que el for llega hasta la ante ante ante pen
ultima posici
on del arreglo (regDia1.length-4) ya que, o si
no, al pedir el entero regDia1[t+4] este estara fuera del arreglo.
b) Esto es muy similar al ejercicio anterior, la diferencia est
a en que, en vez de comparar enteros dentro de
un mismo arreglo, se comparan entre dos arreglos distintos.

Posible soluci
on
// Parte a )
// Muestra en consola mensajes i n d i c a n d o o s c i l a c i o n e s
// Recibe un arreglo que almacena la t e m p e r a t u r a en un dia c u a l q u i e r a
public static void D e t e c t a O s c i l a c i o n e s( int [] regDia1 ){
int t ;
for ( t =0; t < regDia1 . length -4; t ++) // llegamos solo hasta la a n t e p e n u l t i m a posicion
{ if ( regDia1 [ t +1] > regDia1 [ t ] &&
// si se cumple la c o n d i c i o n para a s c e n d e n t e
regDia1 [ t +2] > regDia1 [ t +1] &&
regDia1 [ t +3] < regDia1 [ t +2] &&
regDia1 [ t +4] < regDia1 [ t +3]){
Usuario . m e n s a j e C o n s o l a( " O s c i l a c i o n a s c e n d e n t e a partir del instante " + t );
} else if ( regDia1 [ t +1] < regDia1 [ t ] &&
// si se cumple la c o n d i c i o n para d e s c e n d e n t e
regDia1 [ t +2] < regDia1 [ t +1] &&
regDia1 [ t +3] > regDia1 [ t +2] &&
regDia1 [ t +4] > regDia1 [ t +3]){
Usuario . m e n s a j e C o n s o l a( " O s c i l a c i o n d e s c e n d e n t e a partir del instante " + t );
}
}
}
// Parte b )
// Muestra en consola mensajes i n d i c a n d o c i c l i c i d a d e s
// Recibe dos arreglos que a l m a c e n a n la t e m p e r a t u r a en dos dias // c o n s e c u t i v o s
public static void D e t e c t a C i c l i c i d a d( int [] regDia1 , int [] regDia2 ) {
int t ;
for ( t =0; t < regDia1 . length -2; t ++) {
if ( regDia1 [ t ] == regDia2 [ t ] &&
regDia1 [ t +1] == regDia2 [ t +1] &&
regDia1 [ t +2] == regDia2 [ t +2]) {
Usuario . m e n s a j e C o n s o l a( " C i c l i c i d a d diaria a partir del instante " + t );
}
}
}

IIC1103 Captulo 6: Arreglos

Problema 4: Lista N
umeros
Enunciado
Escriba la clase ListaNumeros que reciba un arreglo de enteros. Esta clase debe proveer los metodos
ElementoMayor() que retorna el mayor elemento dentro del arreglo, ElementoMenor(), que retorna el menor elemento dentro de la lista y ElementoMasRepetido() que retorna el valor del elemento que mas veces
aparece en el arreglo.
Criterios de soluci
on
Para el metodo ElementoMayor lo que tenemos que hacer es tener una variable donde almacenar el mayor
valor. Luego recorremos todo el arreglo y comparamos cada elemento con el mayor valor, si el elemento es
mayor entonces actualizamos el mayor valor. Al terminar el ciclo que recorre todo el arreglo, en la variable
estar
a el mayor valor del arreglo.
Para el metodo ElementoMenor hacemos lo mismo que para el metodo anterior pero comparamos si el
elemento del arreglo es menor que el valor guardado en nuestra variable que almacena el menor valor en este
caso.
Para el metodo ElementoMasRepetido ocupamos dos variables, una que guarde el n
umero que se ha repetido
m
as veces y otra para guardar cuantas veces se ha repetido. Con un ciclo recorremos todo el arreglo, para
cada elemento contamos (utilizando otro ciclo que recorra todo el arreglo) cuantas veces aparece. Luego
comparamos este n
umero de veces con el n
umero que hasta el momento tenga mayor n
umero de repeticiones
y actualizamos su valor si es necesario.
Posible soluci
on
public class L i s t a N u m e r o s {
private int [] a r r e g l o E n t e r o s;
public L i s t a N u m e r o s( int [] lista ) {
// Copiamos el arreglo
a r r e g l o E n t e r o s = new int [ lista . length ];
for ( int i = 0; i < a r r e g l o E n t e r o s. length ; i ++) {
a r r e g l o E n t e r o s[ i ] = lista [ i ];
}
}
public int E l e m e n t o M a y o r() {
int mayor = a r r e g l o E n t e r o s[0];
for ( int i = 1; i < a r r e g l o E n t e r o s. length ; i ++) {
if ( a r r e g l o E n t e r o s[ i ] > mayor ) {
mayor = a r r e g l o E n t e r o s[ i ];
}
}
return mayor ;
}
public int E l e m e n t o M e n o r() {
int menor = a r r e g l o E n t e r o s[0];
for ( int i = 1; i < a r r e g l o E n t e r o s. length ; i ++) {
if ( a r r e g l o E n t e r o s[ i ] < menor ) {
menor = a r r e g l o E n t e r o s[ i ];
}
}
return menor ;
}
public int E l e m e n t o M a s R e p e t i d o() {
// Buscamos cuantas veces aparece cada elemento , y g u a r d a m o s el que mas
// aparezca
int m a s R e p e t i d o = 0;
int masVeces = 0;
for ( int i = 0; i < a r r e g l o E n t e r o s. length ; i ++) {
// Reviso cuantas a p a r i c i o n e s tiene el elemento i
int contador = 0;
for ( int j = 0; j < a r r e g l o E n t e r o s. length ; j ++) {

IIC1103 Captulo 6: Arreglos

if ( a r r e g l o E n t e r o s[ i ] == a r r e g l o E n t e r o s[ j ]) {
contador ++;
}
}
// Veo si el elemento i tiene mas a p a r i c i o n e s que el con mas
// a p a r i c i o n e s hasta el momento
if ( contador > masVeces ) {
masVeces = contador ;
m a s R e p e t i d o = a r r e g l o E n t e r o s[ i ];
}
}
return m a s R e p e t i d o;
}
}

IIC1103 Captulo 6: Arreglos

10

Problema 5: Calcular Primos


Enunciado
Escriba un programa en JAVA que calcule los n
umeros primos del 1 al 100 utilizando la criba de Eratostenes.
Este algoritmo consiste en crear una lista con los n
umeros del 1 al 100 y luego ir descartando primero los
m
ultiplos de 2, luego los de 3, los de 4 y as sucesivamente hasta los m
ultiplos de 10.
Criterios de soluci
on
Siguiendo la descripci
on del algoritmo implementamos un ciclo que parta de 2 hasta 10 (para ir descartando
los m
ultiplos de estos n
umeros). Dentro de este ciclo implementamos otro que recorra todo el arreglo original
y revise para cada elemento si es m
ultiplo. Si lo es debemos sacarlo del arreglo, para lo que corremos todos
los elementos hacia la izquierda a partir del elemento que queremos borrar.
Finalmente imprimimos el arreglo con los n
umeros que nos quedan, siempre cuidando que al haber menos
elementos no podemos recorrer todo el arreglo sino s
olo hasta donde tenemos almacenados n
umeros.
Posible soluci
on
import i i c 1 1 0 3 P a c k a g e .*;
public class P r i n c i p a l {
public static void main ( String [] args ) {
int [] numeros = new int [100];
for ( int i = 0; i < numeros . length ; i ++)
numeros [ i ] = i + 1;
// Al comienzo decimos que todos son primos
int n u m P r i m o s = 100;
for ( int i = 2; i <= 10; i ++) {
for ( int j = 0; j < n u m P r i m o s; j ++) {
// R e v i s a m o s si el elemento j es multiplo del valor i
// En caso de que sea debemos sacarlo del arreglo
if ( numeros [ j ] % i == 0) {
// Debemos sacar el elemento j , para eso corremos todos los
// e l e m e n t o s hacia la i z q u i e r d a a partir del elemento j
for ( int k = j ; k < n u m P r i m o s - 1; k ++) {
numeros [ k ] = numeros [ k + 1];
}
// Tenemos un numero primo menos
numPrimos - -;
// Como corri todo hacia la i z q u i e r d a debo volver a reviser
// en la posicion j
j - -;
}
}
}
// M o s t r a m o s los numeros e n c o n t r a d o s
for ( int i = 0; i < n u m P r i m o s; i ++) {
Usuario . m e n s a j e C o n s o l a( numeros [ i ] + " es primo . " );
}
}
}

IIC1103 Captulo 6: Arreglos

11

Problema 6: C
odigo Desconocido
Enunciado
Indique lo que el siguiente c
odigo muestra en la consola
import i i c 1 1 0 3 P a c k a g e .*;
public class P r i n c i p a l {
public static void main ( String [] args ) {
int [] arreglo = { 171 , 472 , 96 , 443 , 112 , 78 , 352 , 320 , 70 };
Metodo ( arreglo );
}
public static void Metodo ( int [] arreglo ) {
int x = arreglo [0];
for ( int i = 1; i < arreglo . length ; i ++) {
if ( arreglo [ i ] > x ) {
x = arreglo [ i ];
}
}
for ( int n = 10; 10 * x / n > 0; n = n * 10) {
int [] temp = new int [10];
for ( int i = 0; i < temp . length ; i ++) {
temp [ i ] = 0;
}
for ( int i = 0; i < arreglo . length ; i ++) {
temp [( arreglo [ i ] % n ) / (( int ) ( n / 10))]++;
}
for ( int i = 1; i < temp . length ; i ++) {
temp [ i ] += temp [ i - 1];
}
Imprimir ( temp );
int [] aux = new int [ arreglo . length ];
for ( int i = arreglo . length - 1; i >= 0; i - -) {
aux [ temp [( arreglo [ i ] % n ) / (( int ) ( n / 10))] - 1] = arreglo [ i ];
temp [( arreglo [ i ] % n ) / (( int ) ( n / 10))] - -;
}
for ( int i = 0; i < arreglo . length ; i ++) {
arreglo [ i ] = aux [ i ];
}
Imprimir ( arreglo );
}
}
public static void Imprimir ( int [] arreglo ) {
String texto = " " ;
for ( int i = 0; i < arreglo . length ; i ++) {
texto += arreglo [ i ] + " " ;
}
Usuario . m e n s a j e C o n s o l a( texto );
}
}

Criterios de soluci
on
En este tipo de problemas es buena opci
on escribir a un lado una tabla con las variables, arreglos y objetos,
e ir anotando los cambios lnea a lnea, realizando una especie de debug manual. Se debe ser bastante
sistem
atico para no equivocarse, y cuidar interpretar correctamente los cambios en las variables, arreglos y
en los objetos.
Posible soluci
on
2 3 6 7 7 7 8 8 9 9
320 70 171 472 112 352 443 96 78
0 1 2 2 3 4 4 8 8 9
112 320 443 352 70 171 472 78 96
3 5 5 7 9 9 9 9 9 9
70 78 96 112 171 320 352 443 472

IIC1103 Captulo 6: Arreglos

12

Problema 7: Histograma
Enunciado
Un histograma es una representaci
on gr
afica (o como tabla) de las frecuencias de ciertos datos, distribuidos
en alguna cantidad de categoras. Por ejemplo en los siguientes datos:
0, 2, 4, 5, 3, 12, 1, 4, 5, 121, 78, 12, 56, 1, 7, 9, 12, 13, 25, 24, 28, 6, 65, 91, 14, 75, 10
. . . podramos definir las categoras x 20, 20 < x 50 y 50 < x, con lo que se produce el siguiente
histograma:
X
x 20
20 < x 50
50 < x

Frecuencia
18
3
6

Se le pide implementar la clase Histograma que permita crear un histograma de una serie de n
umeros
enteros comprendidos en un rango establecido al momento de inicializar el objeto, y usando como categoras
los mismos n
umeros, es decir, contar cuantas veces se repite cada n
umero en el rango. Use un metodo Agregar
que permita agregar un nuevo valor al Histograma.
Criterios de soluci
on
Para definir nuestra clase Histograma utilizamos como atributos un arreglo que lleve el conteo de las apariciones de los n
umeros y variables que nos permitan identificar el rango en el que se encuentran los n
umeros.
As nuestro arreglo debe ser del tama
no suficiente para almacenar el conteo de todos los valores posibles
dentro del rango definido.
Luego creamos un metodo Agregar como nos dice el enunciado que lo que hace es revisar en que posici
on
del arreglo se esta acumulando el valor recibido como par
ametro (la cual ser
a el valor ingresado menos el
lmite inferior del rango) y aumentamos la cantidad almacenada en esa posici
on en uno.
Para completar nuestra clase agregamos un metodo Mostrar que recorre el arreglo donde almacenamos el
conteo y muestra cada valor (correspondiente a la posicion en el arreglo m
as el lmite inferior) y la cantidad
almacenada en el.

IIC1103 Captulo 6: Arreglos

13

Posible soluci
on
import i i c 1 1 0 3 P a c k a g e .*;
public class H i s t o g r a m a {
private int [] conteo ;
private int limInf ;
private int limSup ;
private int cantidad ;
// Constructor , recibe los limites de los valores
public H i s t o g r a m a( int limInf , int limSup ) {
this . limInf = limInf ;
this . limSup = limSup ;
this . cantidad = limSup - limInf + 1;
conteo = new int [ cantidad ];
for ( int i = 0; i < conteo . length ; i ++) {
conteo [ i ] = 0;
}
}
// Agrega un valor al Histograma , para ello busca en que posicion del arreglo
// se esta a c u m u l a n d o ese valor
public void Agregar ( int valor ) {
conteo [ valor - limInf ] = conteo [ valor - limInf ] + 1;
}
public void Mostrar () {
int limite = limSup - limInf ;
int suma = 0;
for ( int i = 0; i < conteo . length ; i ++) {
Usuario . m e n s a j e C o n s o l a (( i + limInf ) + " : " + conteo [ i ]);
suma = suma + conteo [ i ];
}
Usuario . m e n s a j e C o n s o l a( " Suma : " + suma );
}
}

IIC1103 Captulo 6: Arreglos

14

Problema 8: Mejor Ubicaci


on
Enunciado
Implemente el metodo public int[] buscarMejorUbicacion(int[][] plano, int tam).
El primer par
ametro es un arreglo bidimensional que representa un plano, donde cada casilla del arreglo
indica la calidad asignada a esa posici
on en el plano. El metodo debe buscar la submatriz cuadrada de lado
tam, cuya calidad sea la m
axima. Debe retornar la ubicaci
on de la casilla superior izquierda (fila y columna).
En otras palabras, si tam es 2, debe buscar la matriz de 2x2 dentro del plano, cuya suma de las casillas es
mayor. Si hay m
as de una empatada, debe retornar cualquiera.
Asuma que el arreglo bidimensional siempre es regular (todas las filas tienen el mismo n
umero de columnas).
Ejemplo:
-1
2
0
1
-3

5
1
-3
-2
2

0
6
7
2
8

3
-3
-2
1
-2

7
6
11
0
4

-3
-4
-6
1
0

Si tam fuera 2, el metodo debe retornar el arreglo {0, 3}, ya que es la posicion donde comienza la matriz de
2x2, cuya suma es mayor (13). En cambio si tam fuera 3, el metodo debe retornar el arreglo {0, 2}, dado que
es la mayor suma (35).
Criterios de soluci
on
Lo primero que tenemos que hacer es recorrer la matriz por completo. Para eso utilizamos un doble ciclo pero
considerando que para no pasarnos de los lmites de la matriz tenemos que llegar a length-tam. Dentro de
este ciclo tenemos que recorrer la submatriz de tama
no tam, utilizando tambien un doble ciclo y calculando
la suma de sus posiciones. Luego, si esa suma es mayor que la encontrada hasta el momento actualizamos el
valor de la suma mayor y el valor de los ndices donde comienza la submatriz.
Posible soluci
on
public int [] b u s c a r M e j o r U b i c a c i o n( int [][] plano , int tam ) {
int [] indices = { -1 , -1 };
int max = 0;
for ( int i = 0; i <= plano . length - tam ; i ++) {
for ( int j = 0; j <= plano [ i ]. length - tam ; j ++) {
int suma = 0;
for ( int k = i ; k < i + tam ; k ++) {
for ( int m = j ; m < j + tam ; m ++) {
suma += plano [ k ][ m ];
}
}
if ( indices [0] == -1 || suma > max ) {
max = suma ;
indices [0] = i ;
indices [1] = j ;
}
}
}
return indices ;
}

IIC1103 Captulo 6: Arreglos

15

Problema 9: Output Desconocido


Enunciado
Indique el output que aparece en consola al ejecutar el siguientes c
odigo:
public class ClassA {
private int id ;
private String texto ;
public ClassA ( int n , String t ) {
id = n ;
texto = t ;
}
public int getId (){ return id ; }
public String getTexto (){ return texto ; }
public void a g r e g a r T e x t o( String t ) { texto = texto + t ; }
public ClassA copia () { return new ClassA ( id , texto ); }
}
public class ClassB {
private ClassA [] listaA ;
public ClassB ( int n , int id ) {
listaA = new ClassA [ n ];
for ( int i = 0; i < listaA . length - 1; i ++) {
listaA [ i ] = new ClassA ( id , " T " + i );
id = id + 1;
}
}
public void agregar ( ClassA a ) { listaA [ listaA . length -1] = a ; }
public ClassA getA ( int i ) { return listaA [ i ]; }
public String ver () {
String texto = " texto : " ;
for ( int i = 0; i < listaA . length ; i ++) {
if ( listaA [ i ] != null )
texto = texto + listaA [ i ]. getTexto () + " " ;
}
return texto ;
}
}
import i i c 1 1 0 3 P a c k a g e .*;
public class P r i n c i p a l {
public static void main ( String [] args ) {
int x = 1;
ClassB b1 = new ClassB (4 , x );
ClassB b2 = new ClassB (4 , x + 1);
Usuario . m e n s a j e C o n s o l a( " L1 : " + b1 . ver ());
Usuario . m e n s a j e C o n s o l a( " L2 : " + b2 . ver ());
b1 . agregar ( b2 . getA (2));
ClassA a1 = b1 . getA (3);
if ( a1 . getTexto (). equals ( b2 . getA (2). getTexto ())) {
a1 . a g r e g a r T e x t o( " S " );
} else {
a1 . a g r e g a r T e x t o( " N " );
}
Usuario . m e n s a j e C o n s o l a( " L3 : " + b1 . ver ());
Usuario . m e n s a j e C o n s o l a( " L4 : " + b2 . ver ());
ClassA a2 = b1 . getA (3). copia ();
a2 . a g r e g a r T e x t o( " P " + b2 . getA (1). getId ());
if ( a2 == b2 . getA (2)) {
a2 . a g r e g a r T e x t o( " S " );
} else if ( a2 . getId () == b2 . getA (2). getId ()) {
a2 . a g r e g a r T e x t o( " N " );
}
b2 . agregar ( a2 );
Usuario . m e n s a j e C o n s o l a( " L5 : " + b1 . ver ());
Usuario . m e n s a j e C o n s o l a( " L6 : " + b2 . ver ());
}
}

IIC1103 Captulo 6: Arreglos

16

Criterios de soluci
on
En este tipo de problemas es buena opci
on escribir a un lado una tabla con las variables, arreglos y objetos,
e ir anotando los cambios lnea a lnea, realizando una especie de debug manual. Se debe ser bastante
sistem
atico para no equivocarse, y cuidar interpretar correctamente los cambios en las variables, arreglos y
en los objetos.
Posible soluci
on
L1:texto:
L2:texto:
L3:texto:
L4:texto:
L5:texto:
L6:texto:

T0
T0
T0
T0
T0
T0

T1
T1
T1
T1
T1
T1

T2
T2
T2 T2S
T2S
T2 T2S
T2S T2SP3N

IIC1103 Captulo 6: Arreglos

17

Problema 10: Admin Palabras


Enunciado
Existe la clase AdminPalabras la cual posee una lista de palabras. Esta clase posee un metodo ContarPalabrasPosibles
el cual recibe un String y retorna la cantidad de palabras de la lista que son posibles de formar con las
letras del String recibido, cuidando que cada letra se puede usar una sola vez.
Usted debe implementar el metodo ContarPalabrasPosibles de la clase AdminPalabras. A continuacion
se presenta un esquema de esta clase, usted no puede modificar los atributos de la clase, ni cambiar la firma
del metodo. Si lo desea, puede agregar nuevos metodos a la clase.
public class A d m i n P a l a b r a s {
private String [] l i s t a P a l a b r a s;
public A d m i n P a l a b r a s( String [] lista ) {
l i s t a P a l a b r a s = lista ;
}
public int C o n t a r P a l a b r a s P o s i b l e s( String letras ) {...}
}

.
A continuaci
on se muestra un ejemplo de un main que utiliza esta clase y el output que produce.
public static void main ( String [] args ) {
String [] lista = { " auto " , " pato " , " palo " , " poto " , " amar " , " amor " ,
" loca " , " loco " , " polo " , " poco " , " poca " , " rota " , " roto " };
A d m i n P a l a b r a s admin = new A d m i n P a l a b r a s( lista );
String [] letras = { " escalopa " , " a u t o m o t o r" , " p e r c a t a d o" };
for ( int i = 0; i < letras . length ; i ++) {
int cont = admin . C o n t a r P a l a b r a s P o s i b l e s( letras [ i ]);
Usuario . m e n s a j e C o n s o l a( letras [ i ] + " : " + cont );
}
}

.
Output:
escalopa: 3
automotor: 4
percatado: 3
Criterios de soluci
on
Para implementar el metodo que nos piden necesitamos primero declarar una variable para ir contando.
Luego recorremos todas las palabras en la lista (con un f or por ejemplo) y para cada una revisamos si es
posible formarla con las letras recibidas. Para esto, dentro del ciclo que recorre la lista, creamos un arreglo
para saber que letras ya hemos utilizado, donde el largo del arreglo es el n
umero de letras disponibles y en
cada posicion del arreglo guardamos un true si esa letra ya se us
o o false si todava no se ha utilizado. Luego
recorremos todas las letras de la palabras y vemos si est
an en la letras disponibles sin haber sido usadas.
Cuando encontramos una letra la marcamos como no disponible. As, si pudimos conseguir todas las letras
aumentamos el contador en uno. Finalmente retornamos el contador.

IIC1103 Captulo 6: Arreglos

18

Posible soluci
on
public class A d m i n P a l a b r a s {
private String [] l i s t a P a l a b r a s;
public A d m i n P a l a b r a s( String [] lista ) {
l i s t a P a l a b r a s = lista ;
}
public int C o n t a r P a l a b r a s P o s i b l e s( String letras ) {
// Creamos una variable para ir contando
int contador = 0;
// R e c o r r e m o s todas las palabras en la lista y para cada una r e v i s a m o s
// si es posible formarla con las letras r e c i b i d a s
for ( int i = 0; i < l i s t a P a l a b r a s. length ; i ++) {
// Creamos un arreglo para saber que letras ya hemos utilizado ,
// lo i n i c i a m o s en false
boolean [] usadas = new boolean [ letras . length ()];
for ( int j = 0; j < usadas . length ; j ++) {
usadas [ j ] = false ;
}
// R e c o r r e m o s todas las letras de la palabra y vemos si estan en las
// letras d i s p o n i b l e s sin haber sido usadas
boolean e s P o s i b l e = true ;
for ( int j = 0; j < l i s t a P a l a b r a s[ i ]. length (); j ++) {
boolean e n c o n t r a d a = false ;
// Buscamos la letra entre las d i s p o n i b l e s
for ( int k = 0; k < letras . length () && ! e n c o n t r a d a; k ++) {
if (! usadas [ k ] && l i s t a P a l a b r a s[ i ]. charAt ( j ) == letras . charAt ( k )) {
// E n c o n t r a m o s la letra , la marcamos como u t i l i z a d a
e n c o n t r a d a = true ;
usadas [ k ] = true ;
}
}
if (! e n c o n t r a d a) {
// Indica que la letra no fue e n c o n t r a d a entre las d i s p o n i b l e s
e s P o s i b l e = false ;
}
}
// R e v i s a m o s si fue posible c o n s e g u i r todas las letras
if ( e s P o s i b l e) {
contador ++;
}
}
return contador ;
}
}

IIC1103 Captulo 6: Arreglos

19

Problema 11: El juego de la vida


Enunciado
El juego de la vida es un juego de cero jugadores inventado por el matem
atico John Conway en 1970. este se
juega en una grilla de celulas cuadradas (como un tablero de ajedrez) donde cada posici
on del tablero tiene
dos opciones, o tiene una celula o no. El objetivo de este juego (visto de una manera muy superficial) es
simular la vida, por esta misma raz
on hay reglas para determinar la supervivencia y muerte de las celulas.
Estas reglas son:
Una celula rodeada de menos de 2 celulas muere de soledad.

Una celula rodeada de 2 o 3 celulas sobrevive.

Una celula rodeada de m


as de 3 celular muere por sobrepoblaci
on.

En un espacio sin celulas solamente aparece (nace) una si es que est


a rodeada por exactamente 3
celulas.

Usted debe crear un programa que simule este juego. Debe mostrar el tablero en consola donde se deben
representar los espacios con celulas con unos y los vacos con ceros. Las posiciones de cada celula deben
ser generadas aleatoriamente al empezar cada juego y en cada iteraci
on de este se debe mostrar el tablero.
Puede escoger cualquier tama
no de tablero mientras sea mayor que 3x3. Para terminar, en cada iteraci
on
debe preguntar al usuario si desea continuar.
Ejemplo de tablero 8x8:

IIC1103 Captulo 6: Arreglos

20

Primera Iteracion
----------------|0|0|0|0|0|0|0|0|
----------------|0|0|0|0|0|1|0|1|
----------------|0|0|0|0|0|0|0|0|
----------------|0|0|0|0|0|0|0|0|
----------------|0|0|0|0|0|0|1|1|
----------------|0|1|0|0|1|0|0|0|
----------------|0|1|0|0|0|0|0|0|
----------------|0|0|0|0|0|0|0|0|
-----------------

Segunda Iteraci
on
----------------|0|0|0|0|0|0|0|0|
----------------|0|0|0|0|0|0|0|0|
----------------|0|0|0|0|0|0|0|0|
----------------|0|0|0|0|0|0|0|0|
----------------|0|0|0|0|0|0|0|0|
----------------|0|0|0|0|0|0|0|0|
----------------|0|0|0|0|0|0|0|0|
----------------|0|0|0|0|0|0|0|0|
-----------------

Criterios de soluci
on
Es claro que la grilla del juego puede ser representado por una matriz. Entonces lo primero que debemos
hacer es crear una matriz e inicializarla, esto lo hacemos con un doble for el cual tiene una probabilidad de
30 % de generar un celula en dicho espacio.
Luego, para revisar las condiciones, debemos contar la cantidad de unos que hay alrededor de cada una de
las celulas, una vez hecho esto podemos decidir si la celula muere o vive. El problema que queda es que esta
informaci
on no puede ser inmediatamente aplicada a nuestra matriz ya que debemos ocuparla, tal como est
a,
para calcular la condici
on de las otras celulas, es por esto que el siguiente estado de la matriz lo guardamos
en una matriz auxiliar. Luego esta matriz es guardada en la matriz original y se repite el proceso.

Posible soluci
on
import i i c 1 1 0 3 P a c k a g e .*;
public class P r i n c i p a l {
public static void
int numeroI = 8;
int numeroJ = 8;
int p r o b a b i l i d a d
int [][] matriz =
int [][] auxiliar

main ( String [] args ) {


// numero de columnas
// numero de filas
= 3; // p r o b a b i l i d a d de obtener un 1 en una posicion
new int [ numeroI ][ numeroJ ]; // aqui g u a r a d a m o s las p o s i c i o n e s de las celulas
= new int [ numeroI ][ numeroJ ]; // aqui g u a r d a m o s las p o s i c i o n e s nuevas

for ( int i = 0; i < numeroI ; i ++) { // creamos el tablero


Usuario . m e n s a j e C o n s o l a( " - - - - - - - - - - - - - - - - -" );
for ( int j = 0; j < numeroJ ; j ++) {
if ( A l e a t o r i o. entero (1 , 10) > p r o b a b i l i d a d) {
// si es mayor que la p r o b a b i l i d a d no creamos una celula
matriz [ i ][ j ] = 0;
} else {
matriz [ i ][ j ] = 1;
}
System . out . print ( " | " + matriz [ i ][ j ]);
}
Usuario . m e n s a j e C o n s o l a( " | " );
}
Usuario . m e n s a j e C o n s o l a( " - - - - - - - - - - - - - - - - -" );
Usuario . m e n s a j e C o n s o l a( " \ n \ n \ n " );
while ( true ) { // itera hasta que hacemos un break

IIC1103 Captulo 6: Arreglos

21

for ( int i = 0; i < numeroI ; i ++) { // vamos iterando por la matriz


for ( int j = 0; j < numeroJ ; j ++) {
// cuenta la cantidad de celulas que rodean a una posicion
int contador = 0;
if ( i != 0 && j != 0) {
// r e v i s a m o s que no estamos en la esquina superior
// izquierda , ya que o si no no p o d r i a m o s ver si es
// que tenemos una celula a en nuesta diagonal
// arriba hacia la i z q u i e r d a
if ( matriz [ i - 1][ j - 1] == 1) {
// si es que hay una celula arriba a
// mi i z q u i e r d a sumo 1 al contador
contador ++;
}
}
if ( i != 0) {
// reviso que no este en el borde superior del tablero
// ya que si estoy ahi no puedo mirar hacia la posicion
// que esta arriba mio
if ( matriz [ i - 1][ j ] == 1) {
// si es que hay una celula arriba mio
contador ++; // sumo 1 al contador
}
}
if ( i != 0 && j != ( numeroJ - 1)) {
// igual , pero esquina superior derecha
if ( matriz [ i - 1][ j + 1] == 1) {
contador ++;
}
}
if ( j != numeroJ - 1) {
// igual , pero borde derecho
if ( matriz [ i ][ j + 1] == 1) {
contador ++;
}
}
if ( i != ( numeroI - 1) && j != ( numeroJ - 1)) {
// igual pero esquina inferior derecha
if ( matriz [ i + 1][ j + 1] == 1) {
contador ++;
}
}
if ( i != ( numeroI - 1)) { // igual pero borde inferior
if ( matriz [ i + 1][ j ] == 1) {
contador ++;
}
}
if ( i != ( numeroI - 1) && j != 0) {
// igual pero esquina inferior i z q u i e r d a
if ( matriz [ i + 1][ j - 1] == 1) {
contador ++;
}
}
if ( j != 0) {
// igual pero borde i z q u i e r d o
if ( matriz [ i ][ j - 1] == 1) {
contador ++;
}
}
if ( matriz [ i ][ j ] == 0 && contador == 3) {
// si es que en la posicion no habia una y el contador es tres
auxiliar [ i ][ j ] = 1; // creamos una celula en la posicion
} else if ( matriz [ i ][ j ] == 1 && ( contador == 2 || contador == 3)) {
// si es que habia una y hay 2 0 3 celulas
auxiliar [ i ][ j ] = 1; // creamos la celular
} else {
// en c u a l q u i e r otro caso e l i m i n a m o s la celula
auxiliar [ i ][ j ] = 0;
}
}
}
for ( int i = 0; i < numeroI ; i ++) {
// i m p r i m i m o s la matriz e i g u a l a m o s auxiliar a matriz
Usuario . m e n s a j e C o n s o l a( " - - - - - - - - - - - - - - - - -" );
for ( int j = 0; j < numeroJ ; j ++) {
matriz [ i ][ j ] = auxiliar [ i ][ j ];
auxiliar [ i ][ j ] = 0;

IIC1103 Captulo 6: Arreglos

22

System . out . print ( " | " + matriz [ i ][ j ]);


}
Usuario . m e n s a j e C o n s o l a( " | " );
}
Usuario . m e n s a j e C o n s o l a( " - - - - - - - - - - - - - - - - -" );
Usuario . m e n s a j e C o n s o l a( " \ n \ n \ n " );
int c o n t i n u a r = Usuario . entero ( " Desea C o n t i n u a r? " );
if ( c o n t i n u a r == 0) {
break ;
}
}
}
}

IIC1103 Captulo 6: Arreglos

23

Problema 12: Validando un Sudoku


Enunciado
El objetivo del Sudoku es rellenar una cuadrcula de 9x9 celdas (81 casillas), dividida en 9 subcuadrculas de
3x3 casillas (estas subcuadrculas son conocidas como cajas o regiones) con las cifras del 1 al 9 manteniendo
las siguientes restricciones:
Dentro de una regi
on no puede repetirse ninguna cifra (cada regi
on tiene 9 celdas por lo que en cada
regi
on deben estar las 9 cifras posibles).
Cada fila dentro de la cuadrcula debe tener las 9 cifras posibles (como son 9 celdas por fila, solamente
debe haber una aparici
on de cada cifra en esa fila).
Cada columna dentro de la cuadrcula debe tener las 9 cifras posibles (como son 9 celdas por columna,
solamente debe haber una aparici
on de cada cifra en esa columna).
En la siguiente figura se muestra el tablero final del Sudoku, siendo los valores alrededor del tablero,
ndices que permiten identificar las filas y las columnas.

Usted debe escribir el metodo Validar que dado un tablero final de Sudoku chequea si este cumple con las
reglas arriba enunciadas.
boolean Validar(int[][] sudoku){...}
Recuerde chequear que la matriz sea valida, puede suponer que la matriz es regular y que ha sido inicializada,
pero debe chequear que tiene la cantidad correcta de filas y columnas.
Si lo considera conveniente, puede crear otros metodos y clases que le permitan resolver el problema y que
sean llamados desde el metodo Validar.
Criterios de soluci
on
Debemos ir revisando las condiciones de manera secuencial. Primero debemos comprobar que el tama
no del
arreglo sea correcto. Luego pasaremos por todos los casilleros, revisando que el n
umero este entre los valores
permitidos (1 y 9), y no se encuentre repetido en la fila o columna. Por ultimo revisaremos las submatrices
de 3x3, comprobando que no se repitan n
umeros. Si en cualquier caso una comprobaci
on falla, retornaremos
false, si pasa todas las validaciones, retornaremos true.

IIC1103 Captulo 6: Arreglos

24

Posible soluci
on
public static boolean Validar ( int [][] tabla ) {
// C o m p r o b a m o s que el tamano sea el c o r r e s p o n d i e n t e
if ( tabla . length != 9 || tabla [0]. length != 9) {
return false ;
}
for ( int k = 1; k < 10; k ++) {
// Elejimos un numero del 1 al 9
// Viajamos por una de las d i m e n s i o n e s del array
for ( int i = 0; i < tabla . length ; i ++) {
// S u p o n e m o s que el numero buscado no esta ni en las filas ni en las columnas
// para cada columna y fila r e s p e c t i v a m e n t e e i n i c i a l m e n t e
boolean e s t a f i l a s = false ;
boolean e s t a c o l u m n a s = false ;
for ( int j = 0; j < tabla [ i ]. length ; j ++) {
// C o m p r o b a m o s que el numero de la tabla este entre 1 y 9
if ( tabla [ i ][ j ] < 1 || tabla [ i ][ j ] > 9) {
return false ;
}
// V e r i f i c a m o s igualdad del numero en la tabla c o r r e s p o n d e
// al buscado en las filas
if ( tabla [ i ][ j ] == k ) {
// Si estaba a n t e r i o r m e n t e retorna false , sino graba que esta
if ( e s t a f i l a s) {
return false ;
}
e s t a f i l a s = true ;
}
// V e r i f i c a m o s igualdad del numero en la tabla c o r r e s p o n d e
// al buscado en las columnas
if ( tabla [ j ][ i ] == k ) {
// Si estaba a n t e r i o r m e n t e retorna false , sino graba que esta
if ( e s t a c o l u m n a s) {
return false ;
}
e s t a c o l u m n a s = true ;
}
}
}
// D i v i d i m o s la tabla en s u b m a t r i c e s de 3 x3
// R e c o r r e s m o s las s u b m a t r i c e s con los indices n y m
for ( int n = 0; n < 3; n ++) {
for ( int m = 0; m < 3; m ++) {
// S u p o n e m o s que el numero buscado no esta en el cuadrado
boolean e s t a c u a d r a d o = false ;
// R e c o r r e m o s la s u b m e t r i z con los indices i y j ,
// d e p e n d i e n t e s de n y m
for ( int i = 3 * n ; i < 3 * n + 3; i ++) {
for ( int j = 3 * m ; j < 3 * m + 3; j ++) {
// V e r i f i c a m o s igualdad del numero en la tabla
// c o r r e s p o n d e al buscado la s u b m a t r i z
if ( tabla [ j ][ i ] == k ) {
// Si estaba a n t e r i o r m e n t e retorna false ,
// sino graba que esta
if ( e s t a c u a d r a d o) {
return false ;
}
e s t a c u a d r a d o = true ;
}
}
}
}
}
}
return true ;
}

IIC1103 Captulo 6: Arreglos

25

Problema 13: Suavizar Imagen


Enunciado

Se le pide que dise


ne un algoritmo de suavizado para trabajar con una clase Imagen ya existente. Esta
posee
un atributo Pixel[][] bitmap que contiene todos los pixeles que conforman la imagen. Adem
as la clase

Pixel representa los pixeles seg


un su color RGB. Esta
tiene los siguientes metodos:
Pixel(int r, int g, int b) // constructor con los valores RGB ingresados
Pixel(int[] rgb) // constructor con los valores R = rgb [0], G = rgb[1], B = rgb[2]
int getAzul() // retorna el valor entero asociado al color azul
int getRojo() // retorna el valor entero asociado al color rojo
int getVerde() // retorna el valor entero asociado al color verde
El suavizado se realiza asignando a cada pixel el color promedio entre el y los 8 pixeles adyacentes.
Criterios de soluci
on
Primero observamos que debemos ver todos los pixeles que componen el bitmap, y para cada uno, revisar
todos los pixeles adyacentes, y obtener el promedio de sus colores. Adem
as notamos que los pixeles de los
bordes tendr
an menos pixeles adyacentes.
La forma de obtener el promedio de los colores es sumar determinada componente de todos los pixeles, y
dividirlo por el n
umero de pixeles, repitiendo el proceso con cada componente.
Tambien notamos que si realizamos las operaciones sobre la misma matriz, se modificar
a el resultado de los
pixeles adyacentes del siguiente pixel, por lo que es mejor opci
on realizar la tarea sobre un arreglo auxiliar.

Posible soluci
on
private void Suavizar () {
Pixel [][] n u e v o B i t m a p = new Pixel [ bitmap . length ][ bitmap [0]. length ];
for ( int x = 0; x < n u e v o B i t m a p. length ; x ++) {
for ( int y = 0; y < n u e v o B i t m a p [0]. length ; y ++) {
int r , g , b , pixeles ;
r = 0;
g = 0;
b = 0;
pixeles = 0;
for ( int i = x - 1; i < x + 1; i ++) {
for ( int j = y - 1; j < y + 1; j ++) {
if ( i >= 0 && i < n u e v o B i t m a p. length && j >= 0
&& j < n u e v o B i t m a p [0]. length ) {
pixeles ++;
r = r + bitmap [ i ][ j ]. getRojo ();
g = g + bitmap [ i ][ j ]. getVerde ();
b = b + bitmap [ i ][ j ]. getAzul ();
}
}
}
r = r / pixeles ;
g = g / pixeles ;
b = b / pixeles ;
n u e v o B i t m a p[ x ][ y ] = new Pixel (r , g , b );
}
}
bitmap = n u e v o B i t m a p;
}

IIC1103 Captulo 6: Arreglos

26

Problema 14: Combinar Im


agenes
Enunciado
Se requiere crear el metodo FusionEspecial de la clase Imagen, la cual est
a conformada por una matriz de
elementos de la clase Pixel. El metodo FusionEspecial permite fusionar la imagen con otra imagen recibida
como parametro, retornando una matriz de Pixel, que representa el resultado de la fusi
on. El siguiente es
el encabezado del metodo:
public Pixel[][] FusionEspecial(Imagen imagen, float ponderador)
El algoritmo para fusionar ambas im
agenes indica que cada pixel en la imagen resultante se calcula como la
ponderaci
on entre los pixeles de ambas im
agenes, multiplicando el pixel m
as fuerte por el ponderador y el
pixel m
as debil por la diferencia entre el ponderador y 1. El pixel m
as fuerte ser
a aquel cuya suma de las 3
intensidades que lo forman es mayor. Podramos expresar esto en la siguiente f
ormula:
R(i, j) = PM (i, j) + (1 ) Pm (i, j),
as fuerte y Pm (i, j) al m
as debil.
donde PM (i, j) corresponde al pixel m
La u
nica restricci
on para que se pueda realizar la fusi
on es que ambas im
agenes deben tener las mismas
dimensiones, de lo contrario el metodo retorna null.
A continuaci
on se describen la clase Pixel y la clase Imagen. Usted debe solamente implementar el metodo
FusionEspecial de la clase Imagen sin cambiar nada m
as de esta clase ni de la clase Pixel.
public class Pixel {
public Pixel ( int rojo , int verde , int azul ) {...}
public Pixel ( int [] colores ){...}
public int getRojo (){...}
public int getVerde (){...}
public int getAzul (){...}
}
public class Imagen {
private Pixel [][] pixeles ;
public Imagen ( Pixel [][] pixeles ) {
this . pixeles = pixeles ;
}
public Pixel [][] F u s i o n E s p e c i a l( Imagen imagen , float p o n d e r a d o r) {...}
public Pixel [][] g e t P i x e l e s() { return pixeles ; }
}

Criterios de soluci
on
Lo primero que tenemos que hacer es revisar si las dimensiones son las mismas, ya que esto es una restricci
on
de la fusi
on. Si no son iguales simplemente retornamos null. Si son iguales seguimos con el metodo.
Creamos la matriz de Pixeles donde guardaremos los resultados.
Implementamos un doble ciclo que nos permita recorrer toda la matriz de resultados para ir llenando cada
posici
on. Luego calculamos dos sumas: la suma de todos los colores del pixel de la primera imagen y la suma
de todos los colores del pixel de la segunda imagen. Revisamos cu
al suma es mayor y seg
un esto aplicamos
la f
ormula descrita en el enunciado para calcular el resultado y almacenarlo en la posicion de la matriz
resultante.
Finalmente retornamos la matriz resultante.

IIC1103 Captulo 6: Arreglos

27

Posible soluci
on
public Pixel [][] F u s i o n E s p e c i a l( Imagen imagen , float p o n d e r a d o r) {
Pixel [][] otros = imagen . g e t P i x e l e s ();
// R e v i s a m o s si las d i m e n s i o n e s son las mismas , ya que esto es una
// r e s t r i c c i o n de la fusion
if ( pixeles . length != otros . length || pixeles [0]. length != otros [0]. length ) {
return null ;
}
// Creamos la matriz de pixeles donde g u a r d a r e m o s los r e s u l t a d o s
Pixel [][] r e s u l t a d o = new Pixel [ pixeles . length ][ pixeles [0]. length ];
// R e c o r r e m o s la imagen r e s u l t a n t e creando el color para cada pixel de esta
for ( int i = 0; i < r e s u l t a d o. length ; i ++) {
for ( int j = 0; j < r e s u l t a d o[ i ]. length ; j ++) {
// Sumamos cada color para ver cual es mas fuerte
int suma1 = pixeles [ i ][ j ]. getRojo () + pixeles [ i ][ j ]. getVerde ()
+ pixeles [ i ][ j ]. getAzul ();
int suma2 = otros [ i ][ j ]. getRojo () + otros [ i ][ j ]. getVerde ()
+ otros [ i ][ j ]. getAzul ();
int rojo , verde , azul ;
if ( suma1 > suma2 ) {
rojo = ( int ) ( pixeles [ i ][ j ]. getRojo () * p o n d e r a d o r + (1 - p o n d e r a d o r)
* otros [ i ][ j ]. getRojo ());
verde = ( int ) ( pixeles [ i ][ j ]. getVerde () * p o n d e r a d o r + (1 - p o n d e r a d o r)
* otros [ i ][ j ]. getVerde ());
azul = ( int ) ( pixeles [ i ][ j ]. getAzul () * p o n d e r a d o r + (1 - p o n d e r a d o r)
* otros [ i ][ j ]. getAzul ());
} else {
rojo = ( int ) ( otros [ i ][ j ]. getRojo () * p o n d e r a d o r + (1 - p o n d e r a d o r)
* pixeles [ i ][ j ]. getRojo ());
verde = ( int ) ( otros [ i ][ j ]. getVerde () * p o n d e r a d o r + (1 - p o n d e r a d o r)
* pixeles [ i ][ j ]. getVerde ());
azul = ( int ) ( otros [ i ][ j ]. getAzul () * p o n d e r a d o r + (1 - p o n d e r a d o r)
* pixeles [ i ][ j ]. getAzul ());
}
// A g r e g a m o s el pixel al r e s u l t a d o
r e s u l t a d o[ i ][ j ] = new Pixel ( rojo , verde , azul );
}
}
return r e s u l t a d o;
}

IIC1103 Captulo 6: Arreglos

28

Problema 15: M
aquina de Bebidas
Enunciado
Una m
aquina expendedora de bebidas calientes vende 5 tipos de esta, cafe, chocolate, cortado, capuccino
y moka. La m
aquina recibe las monedas del cliente, procesa la opcion elegida, y si es posible le entrega el
producto, en conjunto con el vuelto correspondiente. La m
aquina acepta monedas de 10, 50, 100, 500, y
billetes de 1000 y 2000. La m
aquina solamente es capaz de dar vuelto si es posible hacerlo con la mnima
cantidad de monedas posibles (nunca se utilizan billetes para dar vuelto, s
olo monedas). Por ejemplo, si el
vuelto a dar son 1270, entonces la venta se realizar
a si y solo s la m
aquina posee al menos 2 monedas de
500, 2 monedas de 100, 1 moneda de 50 y 2 monedas de 10.
Implemente la clase Maquina la cual debe representar a esta maquina expendedora. Su clase debe tener
al menos un constructor que reciba un arreglo con los precios de las 5 bebidas, e inicialice las cantidades
iniciales para cada moneda, las cuales son 50 monedas de 10, 50, 100 y 500. Adem
as su clase debe tener el
metodo Vender el cual debe tener la siguiente firma:
public int[] Vender(int[] ingresados, int producto)
Donde ingresados representa a las monedas ingresadas por el cliente, en la posici
on 0 est
an las monedas
de 10, en la 1 las de 50 y as sucesivamente en forma creciente (si no se ingresan monedas de alg
un tipo,
entonces en la posici
on que le corresponde en el arreglo hay un 0). El par
ametro producto indica el ndice
de la bebida seleccionada, en el mismo orden indicado anteriormente. Este metodo debe retornar un arreglo
con las monedas (y billetes) que se deben dar de vuelto al usuario. En caso de no poder realizar la venta se
retorna null. La compra no se puede realizar en caso que no sea posible dar el vuelto o en caso que el dinero
ingresado no sea suficiente para la bebida seleccionada.
Puede agregar todos los metodos y atributos que quiera a su clase.
Criterios de soluci
on
Para cumplir con lo que nos piden en el enunciado la clase Maquina debera tener como atributos un arreglo
que contenga la cantidad de cada una de las monedas que hay actualmente en la m
aquina y otro arreglo que
contenga los precios de las 5 bebidas calientes.
Adem
as de esto la clase debe tener un constructor que reciba como par
ametro los precios de las bebidas y
los asigne al arreglo de precios que tiene como atributo. Adem
as debe inicializar la cantidad de monedas en
50 (datos obtenidos del enunciado).
Finalmente la clase debe tener un metodo Vender. En este metodo lo primero que hacemos es recorrer el
arreglo con las monedas ingresadas por el usuario y calcular el precio total ingresado, para esto utilizamos
un ciclo y multiplicamos el valor en cada posici
on del arreglo por el valor de la moneda que representa la
posici
on. Luego de esto actualizamos la cantidad de monedas que tiene la m
aquina recorriendo el arreglo de
ingresados y sumando las cantidades al atributo que contiene las cantidades de cada moneda. A continuaci
on
tenemos que verificar si es factible hacer la venta, para eso revisamos que el dinero total ingresado sea mayor
que el precio del producto y que contemos con dinero suficiente para entregar el vuelto. Si se cumple esto
entonces calculamos el vuelto y formamos el arreglo con las cantidades de cada moneda a devolver.

IIC1103 Captulo 6: Arreglos

29

Posible soluci
on
public class Maquina {
private int [] monedas ;
private int [] v a l o r M o n e d a s = { 10 , 50 , 100 , 500 , 1000 , 2000 };
private int [] precios ;
public Maquina ( int [] precios ) {
this . precios = new int [5];
for ( int i = 0; i < this . precios . length ; i ++) {
this . precios [ i ] = precios [ i ];
}
monedas = new int [6];
for ( int i = 0; i < monedas . length - 2; i ++) {
monedas [ i ] = 50;
}
}
public int [] Vender ( int [] ingresados , int producto ) {
int d i n e r o I n g r e s a d o = 0;
for ( int i = 0; i < i n g r e s a d o s. length ; i ++) {
d i n e r o I n g r e s a d o += i n g r e s a d o s[ i ]* v a l o r M o n e d a s[ i ];
}
int m a x V u e l t o = d i n e r o I n g r e s a d o - masCaro ();
for ( int i = 0; i < monedas . length ; i ++) {
monedas [ i ] += i n g r e s a d o s[ i ];
}
if ( v e r i f i c a r F a c t i b i l i d a d( m a x V u e l t o)
&& d i n e r o I n g r e s a d o >= precios [ producto ]) {
return d e v o l v e r D i n e r o( d i n e r o I n g r e s a d o - precios [ producto ]);
} else {
for ( int i = 0; i < monedas . length ; i ++) {
monedas [ i ] -= i n g r e s a d o s[ i ];
}
return null ;
}
}
public int masCaro () {
int masCaro = precios [0];
for ( int i = 1; i < precios . length ; i ++) {
if ( precios [ i ] > masCaro ) {
masCaro = precios [ i ];
}
}
return masCaro ;
}
public boolean v e r i f i c a r F a c t i b i l i d a d( int monto ) {
for ( int i = monedas . length - 1; i > 0; i - -) {
if ( monto / v a l o r M o n e d a s[ i ] > monedas [ i ]) {
return false ;
}
monto = monto % v a l o r M o n e d a s[ i ];
}
return true ;
}
public int [] d e v o l v e r D i n e r o( int dinero ) {
int [] vuelto = new int [ monedas . length ];
for ( int i = monedas . length - 1; i > 0; i - -) {
vuelto [ i ] = dinero / v a l o r M o n e d a s[ i ];
monedas [ i ] -= vuelto [ i ];
dinero = dinero % v a l o r M o n e d a s[ i ];
}
return vuelto ;
}
}

IIC1103 Captulo 6: Arreglos

30

Problema 16: C
odigo Misterioso
Enunciado
Para el siguiente c
odigo, indique el output que aparecera en la Consola.
public class ClassA {
private String id ;
private ClassA hijo ;
private int total ;
public ClassA ( String n ) {
id = n ;
total = 0;
}
public void setHijo ( ClassA h ) {
hijo = h ;
}
public ClassA getHijo () {
return hijo ;
}
public String getId () {
return id ;
}
public void aumentar ( int delta ) {
a u m e n t a r D e s d e P a d r e( delta );
if ( hijo != null )
hijo . a u m e n t a r D e s d e P a d r e( delta );
}
public void a u m e n t a r D e s d e P a d r e( int delta ) {
total += delta ;
}
public int getTotal () {
return total ;
}
}
public static void main ( String [] args ) {
ClassA [] l i s t a O b j e t o s = new ClassA [5];
for ( int i = 0; i < l i s t a O b j e t o s. length ; i ++) {
l i s t a O b j e t o s[ i ] = new ClassA ( " Objeto " + i );
if ( i % 2 == 1) {
l i s t a O b j e t o s[ i ]. setHijo ( l i s t a O b j e t o s[ i - 1]);
}
l i s t a O b j e t o s[ i ]. aumentar ( i );
}
for ( int i = 0; i < l i s t a O b j e t o s. length ; i ++) {
if ( l i s t a O b j e t o s[ i ]. getTotal () == 1) {
Usuario . m e n s a j e C o n s o l a( " L1 : " + l i s t a O b j e t o s[ i ]. getId ());
}
}
for ( int i = 0; i < l i s t a O b j e t o s. length ; i ++) {
if ( l i s t a O b j e t o s[ i ]. getHijo () == null ) {
l i s t a O b j e t o s[ i ]. setHijo ( l i s t a O b j e t o s[( i + 2)
% l i s t a O b j e t o s. length ]);
}
}
for ( int i = 0; i < l i s t a O b j e t o s. length ; i ++) {
l i s t a O b j e t o s[ i ]. aumentar ( l i s t a O b j e t o s[ i ]. getHijo (). getHijo (). getTotal ());
}
for ( int i = 0; i < l i s t a O b j e t o s. length ; i ++) {
Usuario . m e n s a j e C o n s o l a( " L2 : " + l i s t a O b j e t o s[ i ]. getId ()
+ " - Total : " + l i s t a O b j e t o s[ i ]. getTotal ());
}
}

IIC1103 Captulo 6: Arreglos

31

Criterios de soluci
on
En este tipo de problemas es buena opci
on escribir a un lado una tabla con las variables, arreglos y objetos,
e ir anotando los cambios lnea a lnea, realizando una especie de debug manual. Se debe ser bastante
sistem
atico para no equivocarse, y cuidar interpretar correctamente los cambios en las variables, arreglos y
en los objetos.
Posible soluci
on
L1:
L1:
L2:
L2:
L2:
L2:
L2:

Objeto0
Objeto1
Objeto0
Objeto1
Objeto2
Objeto3
Objeto4

Total:
Total:
Total:
Total:
Total:

14
24
33
17
28

IIC1103 Captulo 6: Arreglos

32

Problema 17: RunningUC


Enunciado
No s
olo el estudio hace al estudiante. Tambien es importante la vida universitaria. Dentro de esta, la actividad deportiva es algo que deberamos tener siempre en mente.
En este problema se le pide que realice un programa en Java que maneja la inscripci
on (de manera simplificada) del ya tradicional evento RunningUC1 . Para esto, se le entregan las clases P rincipal y Alumno, y
ud. debe completar los metodos correspondientes en la clase BBDD.
Considere que la informaci
on a desplegar debe ser lo m
as clara posible. En particular, el metodo inf oInscritoN ()
deber
a mostrar un mensaje tipo
Corredor Numero: 1 | Nombre: Ricardo | Edad: 23 | Categoria: Elite|
avisando si el corredor no existe.
Es decir, complete:
public class BBDD {
public void agregar ( Corredor al ) {...} // agrega un nuevo corredor al arreglo
public String i n f o I n s c r i t o N( int i ) {...} // muestra la i n f o r m a c i o n del i - esimo inscrito
public String m o s t r a r I n s c r i t o s() {...} // muestra todos los i n s c r i t o s
}

sin modificar:
public class Corredor {
// [ A T R I B U T O S]
private String nombre ; // nombre del corredor
private int edad ; // su edad
private int c a t e g o r i a; // 5 para 5k , 10 para 10 k , 11 para elite
// [ METODOS ]
// C o n s t r u c t o r
public Corredor ( String nombre , int edad , int c a t e g o r i a) {
this . nombre = nombre ;
this . edad = edad ;
this . c a t e g o r i a = c a t e g o r i a;
}
// getters
public int g e t C a t e g o r i a() {
return c a t e g o r i a;
}
public int getEdad () {
return edad ;
}
public String g e t N o m b r e() {
return nombre ;
}
}

1 para

esto y m
as visite www.runninguc.cl, o dirjase a deportes

IIC1103 Captulo 6: Arreglos

33

import i i c 1 1 0 3 P a c k a g e .*;
public class P r i n c i p a l {
/* * Programa para manejar la i n s c r i p c i o n para una corrida */
public static void main ( String [] args ) {
// String con los mensajes a mostrar
String b i e n v e n i d a = " B i e n v e n i d o a la i n s c r i p c i o n de soporte para el R u n n i n g U C" +
" \ nMas i n f o r m a c i o n en www . r u n n i n g u c. cl " ;
String d e s p e d i d a = " Nos vemos \ n ( mas info en www . r u n n i n g u c. cl ) " ;
String p e d i r N o m b b r e = " Ingrese el nombre " , p e d i r E d a d = " Ingrese la edad " ;
String p e d i r C a t e g o r i a = " Ingrese la c a t e g o r i a: " +
" \ n 1] 5 K \ n 2] 10 K \ n 3] Elite " ;
String menu = " Ingrese una opcion : " +
" \ n0 ) Salir \ n1 ) I n s c r i b i r\ n2 ) Mostrar i n f o r m a c i o n de un corredor \ n3 ) Mostrar i n s c r i t o s" ;
BBDD bd = new BBDD (); // creamos la base de datos ( i n i c i a l m e n t e vacia )
int opcion ;
Usuario . mensaje ( b i e n v e n i d a);
do {
opcion = Usuario . entero ( menu ); // pedimos una opcion
while ( opcion < 0 || opcion > 3){ // la v a l i d a m o s
Usuario . mensaje ( " Opcion i n c o r r e c t a! " );
opcion = Usuario . entero ( menu );
}
switch ( opcion ) { // hacemos lo que se pide
case 0: { Usuario . mensaje ( d e s p e d i d a); break ;} // Salir
case 1: { // I n s c r i b i r
// pedimos el nombre
String nombre = Usuario . texto ( p e d i r N o m b b r e);
// pedimos la edad
int edad = Usuario . entero ( p e d i r E d a d);
while ( edad < 0) { edad = Usuario . entero ( p e d i r E d a d );} // v a l i d a m o s que sea >0
// pedimos la c a t e g o r i a
int c a t e g o r i a = Usuario . entero ( p e d i r C a t e g o r i a);
// v e r i f i c a m o s que este entre 1 y 3
while ( c a t e g o r i a < 1 || c a t e g o r i a > 3 ) {
c a t e g o r i a = Usuario . entero ( p e d i r C a t e g o r i a);
}
Corredor al = new Corredor ( nombre , edad , c a t e g o r i a); // lo creamos
bd . agregar ( al ); // lo a g r e g a m o s
break ;
} case 2: { // Pedir i n f o r m a c i o n de un corredor
int numero = Usuario . entero ( " Ingrese el numero del corredor : " );
while ( numero < 1 ) // v a l i d a m o s que sea >= 1
numero = Usuario . entero ( " Ingrese el numero del corredor : " );
// buscamos esa posicion . Partimos de 0 , asi que restamos 1 al numero
Usuario . mensaje ( bd . i n f o I n s c r i t o N( numero -1));
break ;
} case 3: { Usuario . m e n s a j e C o n s o l a( bd . m o s t r a r I n s c r i t o s ()); break ;} // Mostrar todos
}
} while ( opcion != 0);
}
}

Criterios de soluci
on
Primero que todo, es importante reconocer los metodos que debemos implementar y su forma:
public void agregar(Corredor al) {...}
public String infoInscritoN(int i) {...}
public String mostrarInscritos() {...}
Adem
as, hay que llevar un registro con los corredores, i.e. es un arreglo de tipo Corredor, que como todos
los atributos ser
a privado: private Corredor[] inscritos.
Ahora bien, al momento de agregar un corredor se pueden tener 2 escenarios:
El arreglo estaba vaco, y se crea uno nuevo (contiene solo al nuevo corredor)
El arreglo ya tena corredores. Es necesario crear uno nuevo, de tama
no mayor en 1 al anterior, copiar
cada elemento del arreglo antiguo al nuevo, y finalmente, copiar el nuevo elemento al final de este nuevo
IIC1103 Captulo 6: Arreglos

34

arreglo 2 .
Por otro lado, la informaci
on que debemos mostrar emplea palabras para las categoras de los corredores,
por lo que debemos utilizar, por ejemplo, un switch para hacer la relacion.
Por u
ltimo, mostraremos un mensaje ad-hoc para la bienvenida, despedida, y en el caso que se pida informaci
on y la lista este vaca.
Posible soluci
on
public class BBDD {
private Corredor [] i n s c r i t o s;
// agrega un nuevo corredor al arreglo
public void agregar ( Corredor nuevo ) {
// si el arreglo estaba vacio
if ( this . i n s c r i t o s == null ) {
i n s c r i t o s = new Corredor [1]; // creamos un arreglo de tamanio 1
i n s c r i t o s[0] = nuevo ; // ponemos al Corredor en la posicion 0 ( la
// primera posicion )
} else {
a g r a n d a r A r r e g l o (); // a g r a n d a m o s el arreglo
// a g r e g a m o s al nuevo Corredor en la ultima casilla ( que la creamos
// vacia )
this . i n s c r i t o s[ this . i n s c r i t o s. length - 1] = nuevo ;
}
}
// hacemos el arreglo una casilla mas grande
// es privado porque solo se debe llamar desde metodos de esta clase
private void a g r a n d a r A r r e g l o() {
// creamos un arreglo auxiliar de largo lenght +1
Corredor [] aux = new Corredor [ this . i n s c r i t o s. length + 1];
// copiamos cada Corredor al arreglo auxiliar
for ( int i = 0; i < this . i n s c r i t o s. length ; i ++) {
aux [ i ] = this . i n s c r i t o s[ i ];
}
// la ultima posicion es null ( porque es 1 mas grande )
this . i n s c r i t o s = aux ;
}
// metodo para retornar la i n f o r m a c i o n del inscrito numero - esimo
public String i n f o I n s c r i t o N( int numero ) {
String info = " " ;
// si la lista esta vacia
if ( this . i n s c r i t o s == null ) {
info = " No hay i n s c r i t o s. " ; // decimos que no hay i n s c r i t o s
} else { // si la lista tiene por lo menos un inscrito
// avisamos si el numero esta fuera del largo del arreglo
if ( this . i n s c r i t o s. length <= numero ) {
info += " No se e n c u e n t r a el numero s o l i c i t a d o" ;
} else {
// es una posicion valida , asi que o b t e n e m o s su i n f o r m a c i o n
// llamamos a los gets () c o r r e s p o n d i e n t e s ( y a g r e g a m o s un "\ n ")
info += " Corredor Numero : " + ( numero + 1) + " | " ;
info += " Nombre : " + this . i n s c r i t o s[ numero ]. g e t N o m b r e() + " | " ;
info += " Edad : " + this . i n s c r i t o s[ numero ]. getEdad () + " | " ;
int c a t e g o r i a = this . i n s c r i t o s[ numero ]. g e t C a t e g o r i a ();
String cat = " " ; // m o s t r a r e m o s la c a t e g o r i a como el string que
// c o r r e s p o n d e
switch ( c a t e g o r i a) {
case 1:
cat = " 5 K " ;
break ;
case 2:
cat = " 10 K " ;
break ;
case 3:
cat = " Elite " ;
break ;
}
info += " C a t e g o r i a: " + cat + " | " ;
2 la

soluci
on que se muestra ac
a crea un m
etodo para esto

IIC1103 Captulo 6: Arreglos

35

}
}
return info ; // r e t o r n a m o s la i n f o r m a c i o n del inscrito
}
// metodo para mostrar todos los i n s c r i t o s que hay en ese momento
public String m o s t r a r I n s c r i t o s() {
String todos = " " ; // variable que guardara la i n f o r m a c i o n
// si el arreglo es null
if ( this . i n s c r i t o s == null ) {
todos = " No hay i n s c r i t o s. " ; // quiere decir que no hay i n s c r i t o s
} else { // hay por lo menos un inscrito
// r e c o r r e m o s el arreglo
for ( int i = 0; i < this . i n s c r i t o s. length ; i ++) {
// le a g r e g a m o s la i n f o r m a c i o n del i - esimo inscrito
todos += i n f o I n s c r i t o N( i ) + " \ n " ;
}
}
return todos ; // r e t o r n a m o s la i n f o r m a c i o n total
}
}

IIC1103 Captulo 6: Arreglos

36

Problema 18: Naipes


Enunciado
Uno de los nuevos casinos que entr
o en funcionamiento en las u
ltimas semanas le ha encargado que haga
una clase que le permita manejar cartas de un naipe ingles. Este naipe contiene 52 cartas, donde cada una
de ellas representa uno de los 13 valores posibles (i.e. 1 10, J, Q, K) combinado con alguna de las 4 pintas
(i.e. coraz
on, pica, trebol y diamante).
Una funcionalidad b
asica es poder barajar las cartas, para ello se puede escoger dos posiciones en el naipe
al azar e intercambiarlos el n
umero de veces que defina el usuario. Tambien es necesario poder repartir un
n
umero variable de cartas al usuario y actualizar el naipe (eliminando las cartas entregadas de el).
Usted deber
a implementar la clase Naipe definiendo sus atributos y los siguientes metodos:
public Naipe() constructor de la clase, inicializa el naipe con las 52 cartas posibles (no tendr
a Jocker).
public void barajar(int numero de intercambios) baraja escogiendo dos posiciones en el naipe al azar e intercambia las cartas, repite esta acci
on el n
umero de veces definido por el par
ametro
numero de intercambios.
public String[] repartir(int n) toma las primeras n cartas del naipe y las retorna como un
arreglo de String donde cada elemento representa una carta en el formato valor-pinta (e.g. 2-diamante,
J-trebol). Actualiza el naipe eliminando estas cartas. Debe retornar null si no hay suficientes cartas
para repartir.
Criterios de soluci
on
Lo primero que tenemos que hacer es declarar la clase y sus atributos, los cuales ser
an un arreglo que
represente las cartas y un entero para saber cuantas cartas quedan del mazo.
Para el constructor lo que tenemos que hacer es crear cada una de las cartas del naipe. Como son muchas
cartas lo mejor es utilizar un ciclo que vaya construyendo las cartas por pinta y por n
umero.
Para el metodo barajar tenemos que implementar un ciclo que se repita tantas veces como el n
umero de
intercambios ingresado por el usuario. Luego, dentro del ciclo, generamos dos n
umeros aleatorios que ser
an
las posiciones de los naipes que intercambiaremos. As, cambiamos los naipes de las posiciones aleatorias,
cuidando guardar el valor del primer naipe en una variable auxiliar para no perderlo al hacer el intercambio.
Para el metodo repartir primero revisamos que haya suficientes cartas en el mazo. Si las hay formamos el
arreglo con las cartas a repartir y con un ciclo movemos las cartas restantes hacia el inicio del arreglo, para
as eliminar las primeras y no volver a repartirlas. Actualizamos tambien el n
umero de cartas del mazo y
retornamos el arreglo de las repartidas.

IIC1103 Captulo 6: Arreglos

37

Posible soluci
on
import i i c 1 1 0 3 P a c k a g e .*;
public class Naipe {
String [] mazo ;
int n u m e r o _ c a r t a s;
public Naipe () {
n u m e r o _ c a r t a s = 52;
mazo = new String [ n u m e r o _ c a r t a s];
String [] pinta = { " corazon " , " pica " , " trebol " ,
String [] n u m e r o _ s i m b o l o = { " 1 " , " 2 " , " 3 " , " 4 " ,
" 9 " , " 10 " , " J " , " Q " , " K " };
for ( int i = 0; i < n u m e r o _ s i m b o l o. length ; i ++)
for ( int j = 0; j < pinta . length ; j ++) {
mazo [ i * 4 + j ] = n u m e r o _ s i m b o l o[ i ] + " " +
}
}
}

" diamante " };


"5", "6", "7", "8",
{
pinta [ j ];

public void barajar ( int n u m e r o _ d e _ i n t e r c a m b i o s) {


if ( n u m e r o _ c a r t a s < 2) {
return ;
}
String aux ;
for ( int i = 0; i < n u m e r o _ d e _ i n t e r c a m b i o s; i ++) {
int primero = A l e a t o r i o. entero (0 , n u m e r o _ c a r t a s - 1);
int segundo = A l e a t o r i o. entero (0 , n u m e r o _ c a r t a s - 1);
if ( primero != segundo ) {
aux = mazo [ primero ];
mazo [ primero ] = mazo [ segundo ];
mazo [ segundo ] = aux ;
}
}
}
public String [] repartir ( int n ) {
// n negativo o mayor que el numero de cartas en el mazo
if ( n < 1 || n u m e r o _ c a r t a s < n ) {
return null ;
}
// Arreglo con cartas r e p a r t i d a s
String [] mano = new String [ n ];
// Copio las cartas en el arreglo mano
for ( int j = 0; j < n ; j ++) {
mano [ j ] = mazo [ j ];
}
// Elimino cartas del mazo d e s p l a z a n d o las r e s t a n t e s hacia delante
for ( int i = 0; i < n u m e r o _ c a r t a s - n ; i ++) {
mazo [ i ] = mazo [ i + n ]; // copio
}
// O p c i o n a l m e n t e podra eliminar las r e p e t i d a s del final
// A c t u a l i z o la cantidad de cartas del mazo
numero_cartas = numero_cartas - n;
return mano ;
}
}

IIC1103 Captulo 6: Arreglos

38

Problema 19: Oficinas


Enunciado
Una empresa tiene oficinas distribuidas en varios edificios y quiere desarrollar un software que permita
monitorear la forma en la que distribuye el espacio en cada planta de estos. Para ello divide el espacio de
cada planta en varias oficinas, a cada una de las cuales debe asignarse un nombre y un tama
no en metros
cuadrados. Sin embargo, las salas asignadas a una planta del edificio no pueden exceder el tama
no total de
esta, ni se puede colocar mas de 20 oficinas por planta, por peque
nas que sean, por un tema logstico.
Genere un programa que permita representar este problema. En particular, incluya c
odigo en Java que al
ejecutar el siguiente main():
public static void main ( String [] args ) {
// Defino el tamanio de cada uno de los pisos del edificio .
int [] tamanos = { 120 , 120 , 80 };
Edificio s a n A g u s t i n = new Edificio ( " San Agustin " , tamanos );
// Agrego oficinas a un d e t e r m i n a d o piso , con un nombre y tamanio
// asignado .
s a n A g u s t i n. a g r e g a r O f i c i n a(0 , " Sala H1 " , 30);
s a n A g u s t i n. a g r e g a r O f i c i n a(0 , " Sala H2 " , 30);
s a n A g u s t i n. a g r e g a r O f i c i n a(0 , " Sala H3 " , 30);
s a n A g u s t i n. a g r e g a r O f i c i n a(0 , " Banio " , 15);
s a n A g u s t i n. a g r e g a r O f i c i n a(1 , " Finanzas " , 50);
s a n A g u s t i n. a g r e g a r O f i c i n a(1 , " C u b i c u l o s" , 50);
s a n A g u s t i n. a g r e g a r O f i c i n a(1 , " Sala que no cabe " , 50); // No hay espacio .
s a n A g u s t i n. a g r e g a r O f i c i n a(2 , " Gerencia " , 80);
s a n A g u s t i n. m o s t r a r E s t r u c t u r a();
}

Muestre el siguiente mensaje en consola:


D i r e c t o r i o del edificio San Agustin :
El piso 1 contiene :
- Sala H1 (30 mt2 )
- Sala H2 (30 mt2 )
- Sala H3 (30 mt2 )
- Banio (15 mt2 )
El piso 2 contiene :
- Finanzas (50 mt2 )
- C u b i c u l o s (50 mt2 )
El piso 3 contiene :
- Gerencia (80 mt2 )

Utilice todo su conocimiento para dar un buen dise


no a su soluci
on.
Criterios de soluci
on
Una posible soluci
on a este problema es implementar tres clases: Oficina, Piso y Edificio.
La clase Oficina como atributos debera tener el nombre y los metros cuadrados que ocupa, adem
as de un
constructor que reciba estos valores y los asigne a los atributos. Adem
as debera tener los getters necesarios
para obtenerlos.
La clase Piso como atributos debera tener un arreglo de Oficinas (de largo 20 pues es el m
aximo n
umero de
oficinas por piso), un entero para determinar el n
umero de oficinas que realmente hay en el piso y tambien
un entero para almacenar el n
umero de metros cuadrados disponibles. Adem
as debera tener los siguientes
metodos:
Constructor: Reciba como par
ametro el m
aximo n
umero de metros cuadrados que puede tener el piso
y cree el arreglo de oficinas.
Metodo agregarOficina: Revise que no se hayan completado las 20 oficinas y que todava queden
metros cuadrados. Si hay espacio crear una nueva oficina, agregarla al arreglo y actualizar el n
umero
IIC1103 Captulo 6: Arreglos

39

de metros cuadrados disponibles.


Metodo mostrarEstructura: Recorra todas las oficinas con un ciclo y muestre para cada una su
nombre y el n
umero de metros cuadrados que ocupa.
La clase Edificio debera tener como atributos el nombre del Edificio y un arreglo de Pisos. Adem
as debe
tener los siguientes metodos:
Constructor: Reciba como par
ametro el nombre del Edificio y un arreglo con el tama
no de cada uno de
los pisos. En el metodo debe crear el arreglo de pisos (seg
un el n
umero de elementos que contenga el
arreglo de tama
nos) y luego crear cada uno de los Pisos (con un ciclo) asignando el tama
no correcto.
Metodo agregarOficina: Reciba como parametros el ndice del piso, el nombre y los metros cuadrados. Revise que el ndice del piso es correcto y si es as llame al metodo agregarOficina del Piso
correspondiente.
Metodo mostrarEstructura: Mostrar en pantalla el nombre del edificio y con un ciclo mostrar lo que
contiene cada piso, llamando al metodo mostrarEstructura de cada piso.
Posible soluci
on
public class Oficina {
private String nombre ;
private int mt2 ;
public Oficina ( String nombre , int mt2 ) {
this . nombre = nombre ;
this . mt2 = mt2 ;
}
public int getMt2 () {
return mt2 ;
}
public String g e t N o m b r e() {
return nombre ;
}
}
public class Piso {
private Oficina [] piezas = new Oficina [20];
private int n u m P i e z a s = 0;
private int m t 2 L i b r e s;
public Piso ( int maxMt2 ) {
piezas = new Oficina [20];
n u m P i e z a s = 0;
m t 2 L i b r e s = maxMt2 ;
}
boolean a g r e g a r O f i c i n a( String nombre , int mt2 ) {
if ( n u m P i e z a s == 20 || m t 2 L i b r e s < mt2 ) {
return false ;
}
piezas [ n u m P i e z a s ++] = new Oficina ( nombre , mt2 );
m t 2 L i b r e s -= mt2 ;
return true ;
}
void m o s t r a r E s t r u c t u r a() {
for ( int i = 0; i < n u m P i e z a s; i ++) {
System . out . println ( " \ t \ t - " + piezas [ i ]. g e t N o m b r e() + " ( "
+ piezas [ i ]. getMt2 () + " mt2 ) " );
}
}
}

IIC1103 Captulo 6: Arreglos

40

public class Edificio {


private Piso [] pisos ;
private String nombre ;
public Edificio ( String nombre , int [] tamanos ) {
this . nombre = nombre ;
pisos = new Piso [ tamanos . length ];
for ( int i = 0; i < pisos . length ; i ++) {
this . pisos [ i ] = new Piso ( tamanos [ i ]);
}
}
boolean a g r e g a r O f i c i n a( int piso , String nombre , int mt2 ) {
if ( piso < 0 || piso >= pisos . length ) {
return false ;
}
return pisos [ piso ]. a g r e g a r O f i c i n a( nombre , mt2 );
}
void m o s t r a r E s t r u c t u r a() {
System . out . println ( " D i r e c t o r i o del edificio " + nombre + " : " );
for ( int i = 0; i < pisos . length ; i ++) {
System . out . println ( " \ tEl piso " + ( i + 1) + " contiene : " );
pisos [ i ]. m o s t r a r E s t r u c t u r a();
}
}
}

IIC1103 Captulo 6: Arreglos

41

Problema 20: Venta Pasajes EBE


Enunciado
La empresa de buses del estado (EBE) esta realizando una promoci
on en la venta de pasajes.
Para almacenar el costo de los recorridos entre ciudades, utiliza una matriz cuadrada donde cada ciudad
tiene asociado un n
umero que la identifica (entre 1 y N , siendo N el n
umero total de ciudades a las que
puede llegar la empresa). El elemento (x, y) de la matriz representa el costo que tiene realizar un viaje desde
la ciudad x a la ciudad y. Cuando no existe un recorrido entre estas ciudades se deja el costo en 1.
Adem
as la empresa posee por cada recorrido entre dos ciudades un arreglo que indica los asientos libres y
ocupados. Esto se debe a que la empresa ha destinado una fila completa del bus para esta promoci
on.
Para que una persona pueda obtener un pasaje debe dirigirse a la boletera y comprarlo. Esto significa que
el cajero a la hora de vender debe verificar si hay alg
un recorrido desde la ciudad x a la ciudad y y adem
as
si existe alg
un asiento disponible. En caso de disponibilidad simplemente marcar
a el asiento como ocupado.
En caso contrario informar
a al pasajero la no disponibilidad.

5000
2200

3000

6
2500

1500
800
6000

1
2
3
4
5
6

1
-1
-1
-1
-1
-1
-1

2
5000
-1
-1
-1
-1
-1

3
-1
3000
-1
-1
1500
-1

4
-1
-1
6000
-1
-1
-1

5
-1
-1
-1
-1
-1
2500

6
2200
-1
-1
800
-1
-1

El gr
afico de la izquierda muestra el esquema de recorridos para 6 ciudades, y a la derecha se muestra una
matriz que representa este esquema. En este ejemplo:
- Existe un recorrido desde la ciudad 1 hasta la ciudad 2 y tiene costo 5000, pero no existe un recorrido
desde la ciudad 2 hasta la ciudad 1 (costo es 1).
Para esta pregunta se le pide implementar la clase Ruta para representar los recorrido, de acuerdo a las
siguientes especificaciones:
a) Los atributos de la clase son la matriz donde se debe almacenar el costo de los recorridos entre las
ciudades y la matriz que indica la disponibilidad de asientos.
b) Implemente el metodo constructor de la clase Ruta. Este metodo debe solicitar al usuario que ingrese
la cantidad de ciudades. Luego debe solicitar el costo de viaje entre cada par de ciudades y almacenarlo
en la matriz de costos definida en la clase. Recuerde tener vaca la matriz de disponibilidad. Usted debe
pedirle al usuario que ingrese la cantidad de asientos disponibles en promoci
on, el cual es el mismo
para cada par de ciudades.
c) Implemente un metodo llamado costoRecorridoDirecto que retorne el costo de viaje entre dos ciudades.
Si el camino no existe el metodo debe retornar 1 e imprimir el error. Nota: verifique antes que exista
camino entre las dos ciudades.
Por ejemplo: si observamos el esquema de recorridos no existe camino directo entre 4 y 1, pues para
llegar a 4 antes debe recorrer las ciudades 2 y 3. Pero si existe camino directo entre 1 y 6 con costo
2200.
IIC1103 Captulo 6: Arreglos

42

d) Implemente un metodo ventaPasaje que determine si se puede o no vender un pasaje, esto s


olo si
existe disponibilidad de asientos para realizar un viaje entre varias ciudades. El metodo recibe como
par
ametro un arreglo de enteros que representa las ciudades que forman la ruta.
Por ejemplo: para la ruta [1, 6, 5], verifico que exista camino y disponibilidad de asientos. En ese caso
vendo el pasaje. Caso contrario, para la ruta [1, 2, 3, 4, 5] no existe ruta debido a que para llegar a 5
antes debera pasar por 6.
Criterios de soluci
on
El enunciado es bastante estructurado y nos indica que hacer. Primero declaramos la clase Ruta con dos
atributos: una matriz de dos dimensiones para almacenar el costo de los recorridos y otra matriz de tres
dimensiones para indicar la disponibilidad de un asiento desde una ruta hacia otra. Luego implementamos
los metodos que nos piden:
Constructor: En este metodo pedimos al usuario que ingrese el n
umero de rutas y el n
umero de asientos
disponibles. Con estos datos creamos la matriz de costos y la de disponibilidad. Luego, con un doble
ciclo inicializamos la matriz de costos, pidiendo para cada casilla el valor al usuario del costo de ir de
una ciudad a otra. Dentro del mismo ciclo inicializamos tambien la matriz de disponibilidad.
Metodo costoRecorridoDirecto: Este metodo debe recibir los ndices de las ciudades. Lo primero
que hacemos es revisar que dichos ndices sean v
alidos (no nos salgamos de la matriz de costos). Luego
obtenemos el valor en la posici
on de la matriz que corresponde al costo entre ambas ciudades y si este
costo es -1 le avisamos al usuario. Si no, retornamos el costo que corresponde.
Metodo ventaPasaje: Recibe como par
ametro un arreglo con las ciudades que forman la ruta. Lo
primero que hacemos es un ciclo para recorrer el arreglo recibido como parametro. Luego, dentro del
ciclo, revisamos si hay costo para ir de una ciudad a la siguiente en el arreglo (llamando al metodo
costoRecorridoDirecto). Luego revisamos si hay disponibilidad. Para esto revisamos la matriz de
disponibilidad seg
un las dos rutas, recorriendo en todos los posibles asientos de esas dos ciudades
hasta encontrar alguno que sea true. Si esto se cumple para todas las ciudades del arreglo entonces
actualizamos la disponibilidad de asientos.
Posible soluci
on
import i i c 1 1 0 3 P a c k a g e .*;
public class Ruta {
private int [][] r e c o r r i d o s;
private boolean [][][] d i s p o n i b i l i d a d;
public Ruta () {
int n = Usuario . entero ( " Ingrese numero de rutas : " );
int t = Usuario . entero ( " Ingrese numero de asientos d i s p o n i b l e s: " );
r e c o r r i d o s = new int [ n ][ n ];
d i s p o n i b i l i d a d = new boolean [ n ][ n ][ t ];
for ( int i = 0; i < n ; i ++)
for ( int j = 0; j < n ; j ++) {
r e c o r r i d o s[ i ][ j ] = Usuario . entero ( " Ingrese costo : " + i -1 + " ," + j -1);
for ( int k = 0; k < t ; k ++) {
if ( i == 5) {
d i s p o n i b i l i d a d[ i ][ j ][ k ] = false ;
} else {
d i s p o n i b i l i d a d[ i ][ j ][ k ] = true ;
}
}
}
}
public int c o s t o R e c o r r i d o D i r e c t o( int x , int y ) {
x = x - 1; // por los indices
y = y - 1;

IIC1103 Captulo 6: Arreglos

43

if ( x >= 0 && y >= 0 && x < r e c o r r i d o s. length && y < r e c o r r i d o s [0]. length )
{
if ( r e c o r r i d o s[ x ][ y ] == -1)
Usuario . m e n s a j e C o n s o l a( " No existe camino directo entre las ciudades . " );
return r e c o r r i d o s[ x ][ y ];
}
return -1;
}
private boolean h a y D i s p o n i b i l i d a d( int i , int j ) {
for ( int k = 0; k < d i s p o n i b i l i d a d [0][0]. length ; k ++) {
if ( d i s p o n i b i l i d a d[ i ][ j ][ k ]) {
return true ;
}
}
Usuario . mensaje (" no hay d i s p o n i b i l i d a d de " + i -1 + " a " + j -1);
return false ;
}
public void v e n t a P a s a j e( int [] x ) {
int total = 0;
boolean valida = true ;
for ( int i = 0; i < x . length - 1 && valida ; i ++) {
int costo = this . c o s t o R e c o r r i d o D i r e c t o( x [ i ] , x [ i + 1]);
if ( costo > 0 && h a y D i s p o n i b i l i d a d( x [ i ] , x [ i + 1]))
total = total + costo ;
else
valida = false ;
}
if ( valida )
{
for ( int i = 0; i < x . length - 1; i ++)
this . r e s t a r D i s p o n i b i l i d a d(i , i +1);
}
}
private void r e s t a r D i s p o n i b i l i d a d( int i , int j ) {
int k = 0;
boolean n o E n c o n t r e = true ;
while ( n o E n c o n t r e && k < d i s p o n i b i l i d a d [0][0]. length ) {
if ( d i s p o n i b i l i d a d[ i ][ j ][ k ]) {
n o E n c o n t r e = false ;
d i s p o n i b i l i d a d[ i ][ j ][ k ]= false ;
}
k = k + 1;
}
}
}

IIC1103 Captulo 6: Arreglos

44

Problema 21: Facebook


Enunciado
Dados los problemas de privacidad que actualmente tiene Facebook, le han pedido a un grupo de programadores implementar un prototipo de red social para la universidad. La idea gruesa es poder almacenar una
lista de contactos y luego almacenar cu
ales de dichos contactos son amigos entre s.
Al repartir el trabajo se decidi
o que usted no va a escribir el main() del programa, sino proveer la funcionalidad requerida de forma que este disponible para quien lo haga. Para ello, escriba las clases necesarias en
java que permitan la serie de operaciones mencionadas a continuaci
on:
Representar una lista de personas de un tama
no m
aximo predefinido, a entregar por el main().
Poder agregar un nuevo nombre a la lista de personas. Su metodo debe ingresar una nueva persona
con ese nombre y retornar a cambio un entero que sirva como identificador u
nico para la persona en el
sistema (para evitar problemas con nombres repetidos).
Poder hacer que dos personas se vuelvan amigos. Para ello se proporcionan a la lista los dos identificadores correspondientes. Considere y valide lo siguiente:
Que una persona no puede ser amigo de s misma.

Que la amistad es recproca, no puedo ser amigo de alguien sin que este sea amigo mo.

Que una persona podra tener un m


aximo de 200 amigos.
Poder obtener una persona teniendo su identificador.

Poder pedirle a una persona que imprima en consola su red de amistades. La red de amistades est
a compuesta no s
olo por sus amigos directos sino tambien por los amigos directos de sus amigos.
La persona original no debe obviamente aparecer en la lista, pese a ser amiga de sus amigos.

No importa si una misma persona aparece m


as de una vez en el listado (al ser amiga com
un de
dos o m
as amigos).
Criterios de soluci
on
Posible soluci
on
/* *
* Clase que almacena un contacto .
*/
public class Contacto {
private String nombre ;
private int id ;
private Contacto [] amigos ;
private int n u m A m i g o s;
/* * i n i c i a l i z a el contacto . I n i c i a l m e n t e se comienza con un numero base de
* @param nombre
* @param id
*/
public Contacto ( String nombreC , int idC ) {
nombre = nombreC ;
id = idC ;
amigos = new Contacto [200];
n u m A m i g o s = 0;
}

amigos .

/* *
* Agrega un nuevo amigo . El metodo intenta evitar tener que definir un
* arreglo muy largo . Por ende , parte de una base fija y va d u p l i c a n d o la
* c a p a c i d a d cuando se queda sin espacio .
* @param amigo El amigo a agregar .
*/

IIC1103 Captulo 6: Arreglos

45

public void a g r e g a r A m i g o( Contacto amigo ) {


// Evito agregar un amigo ya e x i s t e n t e .
for ( int i = 0; i < n u m A m i g o s; i ++) {
if ( amigos [ i ] == amigo ) {
return ;
}
}
// Asigno un nuevo amigo
amigos [ n u m A m i g o s ++] = amigo ;
}
/* *
* Imprime la red de este contacto , es decir , todos los amigos directos y
* los amigos de estos amigos .
*/
public void i m p r i m i r R e d D e A m i g o s() {
System . out . println ( " Red de amigos de " + nombre + " : " );
for ( int i = 0; i < n u m A m i g o s; i ++) {
System . out . println ( " \t - " + amigos [ i ]. nombre );
for ( int j = 0; j < amigos [ i ]. n u m A m i g o s; j ++) {
if ( amigos [ i ]. amigos [ j ] != this ) {
System . out . println ( " \ t \t - " + amigos [ i ]. amigos [ j ]. nombre );
}
}
}
}
/* *
* @return the nombre
*/
public String g e t N o m b r e() {
return nombre ;
}
/* *
* @return the id
*/
public int getId () {
return id ;
}
/* *
* @return the n u m A m i g o s
*/
public int g e t N u m A m i g o s() {
return n u m A m i g o s;
}
}
public class Facebook {
private Contacto [] c o n t a c t o s;
private int n u m C o n t a c t o s;
/* * C o n s t r u c t o r , facebook parte sin gente */
public Facebook ( int maximo ) {
c o n t a c t o s = new Contacto [ maximo ];
n u m C o n t a c t o s = 0;
}
/* *
* Agrega un contacto con el nombre indicado y le asigna un id del sistema ,
* que es r e t o r n a d o
*/
public int a g r e g a r C o n t a c t o( String nombre ) {
c o n t a c t o s[ n u m C o n t a c t o s] = new Contacto ( nombre , n u m C o n t a c t o s);
return n u m C o n t a c t o s ++;
}
/* *
* R e l a c i o n a a un contacto con otro , i n d i c a n d o que son amigos . La amistad
* es b i d i r e c c i o n a l
*/
public void a g r e g a r A m i g o( int contacto , int amigo ) {
if ( contacto < n u m C o n t a c t o s && amigo < n u m C o n t a c t o s
&& contacto != amigo ) {
c o n t a c t o s[ contacto ]. a g r e g a r A m i g o( c o n t a c t o s[ amigo ]);
c o n t a c t o s[ amigo ]. a g r e g a r A m i g o( c o n t a c t o s[ contacto ]);

IIC1103 Captulo 6: Arreglos

46

}
}
/* * Retorna el contacto pedido . */
public Contacto g e t C o n t a c t o( int id ) {
return c o n t a c t o s[ id ];
}
}

IIC1103 Captulo 6: Arreglos

47

Problema 22: Patrones Sala


Enunciado
Muchas veces es necesario organizar las salas para controles e interrogaciones, de forma que se minimice la
copia. Una de ellas es eliminar o habilitar algunos puestos de la sala, de forma que los alumnos se encuentren
a mayor distancia de lo normal.
Ud. deber
a implementar un programa que permita aplicar algunos patrones de ubicaciones de personas a
una sala en particular.
Para la realizaci
on del ejercicio cuenta con las siguientes clases ya implementadas. No debe modificar la clase
Principal.
public class Sala {
private int ancho ;
private int largo ;
private int [] r e p r e s e n t a c i o n S a l a;
public Sala ( int _ancho , int _largo ) {
ancho = _ancho ;
largo = _largo ;
r e p r e s e n t a c i o n S a l a = new int [ _ancho * _largo ];
for ( int i = 0; i < r e p r e s e n t a c i o n S a l a. length ; i ++) {
r e p r e s e n t a c i o n S a l a[ i ] = 0;
}
}
public int [] g e t R e p r e s e n t a c i o n S a l a() {
return r e p r e s e n t a c i o n S a l a;
}
public int getLargo () {
return largo ;
}
public int getAncho () {
return ancho ;
}
public void i m p r i m i r R e p r e s e n t a c i o n S a l a() {
System . out . println ( " PIZARRON " );
for ( int i = 0; i < r e p r e s e n t a c i o n S a l a. length ; i ++) {
if ( i % ancho == 0) {
System . out . println ();
}
if ( r e p r e s e n t a c i o n S a l a[ i ] == 1) {
System . out . print ( " X " );
} else {
System . out . print ( r e p r e s e n t a c i o n S a l a[ i ]);
}
System . out . print ( " " );
}
System . out . println ( " \ n " );
}
public int g e t I n d e x F i l a V e r t i c a l( int indexRep ) {
return indexRep % ancho ;
}
public int g e t I n d e x F i l a H o r i z o n t a l( int indexRep ) {
return indexRep / ancho ;
}
}

IIC1103 Captulo 6: Arreglos

48

import i i c 1 1 0 3 P a c k a g e .*;
public class P r i n c i p a l {
public static void main ( String [] args ) {
Patron [] _ p a t r o n e s = new Patron [4];
_ p a t r o n e s[0] = new Patron (1);
_ p a t r o n e s[1] = new Patron (2);
_ p a t r o n e s[2] = new Patron (3);
_ p a t r o n e s[3] = new Patron (4);
D i s t r i b u c i o n _dist = new D i s t r i b u c i o n( null , _ p a t r o n e s);
int opcion = 0;
while ( opcion != 5) {
opcion = Usuario . entero (" Ingrese opcion :\ n1 : Crear sala \ n2 : Aplicar patron \ n " +
" 3: D e s a p l i c a r patrones \ n4 : Ver info sala \ n5 : Salir " );
while ( opcion < 1 || opcion > 5) {
opcion = Usuario . entero ( " OPCION INVALIDA \ nIngrese opcion :\ n1 : Crear sala \ n " +
" 2: Aplicar patron \ n3 : D e s a p l i c a r patrones \ n4 : Ver info sala \ n5 : Salir " );
}
switch ( opcion ) {
case 1:
_dist . setSala ( c r e a r S a l a());
_dist . getSala (). i m p r i m i r R e p r e s e n t a c i o n S a l a ();
_dist . getSala (). i m p r i m i r I n f o S a l a ();
break ;
case 2:
if ( _dist . getSala () != null ) {
_dist . a p l i c a r P a t r o n( e s c o g e r P a t r o n ());
_dist . getSala (). i m p r i m i r R e p r e s e n t a c i o n S a l a ();
_dist . getSala (). i m p r i m i r I n f o S a l a ();
} else {
Usuario . mensaje ( " Debe crear una sala para usar esta opcion " );
}
break ;
case 3:
if ( _dist . getSala () != null ) {
_dist . d e s a p l i c a r P a t r o n e s();
_dist . getSala (). i m p r i m i r R e p r e s e n t a c i o n S a l a ();
_dist . getSala (). i m p r i m i r I n f o S a l a ();
} else {
Usuario . mensaje ( " Debe crear una sala para usar esta opcion " );
}
break ;
case 4:
if ( _dist . getSala () != null ) {
_dist . getSala (). i m p r i m i r R e p r e s e n t a c i o n S a l a ();
_dist . getSala (). i m p r i m i r I n f o S a l a ();
} else {
Usuario . mensaje ( " Debe crear una sala para usar esta opcion " );
}
break ;
}
}
}
public static int e s c o g e r P a t r o n() {
int opcion = 0;
opcion = Usuario . entero ( " Ingrese patron :\ n1 : Borrar filas h o r i z o n t a l e s impares \ n " +
" 2: Borrar filas v e r t i c a l e s impares \ n3 : Eliminar en cruz \ n " +
" 4: H a b i l i t a r puestos par / par o impar / impar " );
while ( opcion < 1 || opcion > 4) {
opcion = Usuario . entero (" OPCION INVALIDA \ nIngrese patron :\ n " +
" 1: Borrar filas h o r i z o n t a l e s impares \ n2 : Borrar filas v e r t i c a l e s impares \ n " +
" 3: Eliminar en cruz \ n4 : H a b i l i t a r puestos par / par o impar / impar " );
}
return opcion - 1;
}
public static Sala c r e a r S a l a() {
int ancho = Usuario . entero ( " Ingrese el ancho de la sala " );
int largo = Usuario . entero ( " Ingrese el largo de la sala ( desde el pizarron al fondo ) " );
return new Sala ( ancho , largo );
}
}

IIC1103 Captulo 6: Arreglos

49

El programa lo dividiremos en 3 subconjuntos incrementales. Le recomendamos no comenzar con el siguiente


subconjunto hasta terminar y probar el funcionamiento correcto del subconjunto actual.
Incremento 1
Para completar el primer incremento, deber
a completar la implementacion de la clase Sala. A continuacion
se detallan los metodos que deber
a tener esta clase para este incremento (algunos ya estan implementados):
1. Sala(int ancho, int largo) Constructor de la clase. Recibe el ancho y el largo (desde el pizarr
on
hasta atr
as) que tiene la sala (en puestos). Este metodo tambien inicializa un arreglo unidimensional
que representa a la sala, donde un 0 indica puesto disponible, y un 1 un puesto que no se puede usar.
Tenga en cuenta que el tama
no de este arreglo es ancho*largo.
2. int[] getRepresentacionSala() Retorna el arreglo unidimensional que representa a la sala.
3. int getLargo() Retorna el largo (en puestos) de la sala.
4. int getAncho() Retorna el ancho (en puestos) de la sala.
5. void imprimirRepresentacionSala() Imprime en consola el estado de la sala. Indica donde est
a el
pizarr
on, y los puestos deshabilitados est
an marcados con una X.
6. int getIndexFilaVertical(int indexRep) Retorna el ndice de fila vertical de la celda
representacionSala[indexRep].
7. int getIndexFilaHorizontal(int indexRep) Retorna el ndice de fila horizontal de la celda
representacionSala[indexRep].
Adem
as en este incremento deber
a implementar la clase Patron con los siguientes metodos (ud. deber
a crear
completamente esta clase):
1. Patron(int tipo) Constructor de la clase. Recibe el n
umero que representa el tipo del patr
on a
aplicar.
2. void setTipo(int tipo) Setea el tipo de patr
on.
3. void getTipo(int tipo) Retorna el tipo de patr
on.
4. void aplicarPatron(Sala sala) Aplica a sala el patr
on que tiene seteado. Los ndices parten
desde cero (fila horizontal 0, fila vertical 0). Los patrones que debe tener implementados son3 :
tipo 1: deshabilitar filas horizontales impares. Un ejemplo de aplicaci
on de este patr
on sera (para
una sala de ancho 10 y largo 6, a la que no se le han aplicado patrones):
PIZARRON
0 0 0 0 0 0 0 0 0 0
X X X X X X X X X X
0 0 0 0 0 0 0 0 0 0
X X X X X X X X X X
0 0 0 0 0 0 0 0 0 0
X X X X X X X X X X
3 Los ejemplos aqu
mostrados son outputs volcados en consola del resultado de la aplicaci
on de los distintos patrones sobre
una sala. En este m
etodo Ud. no debe implementar la impresi
on en pantalla, sino la asignaci
on correcta de los valores del arreglo
unidimensional que la representa.

IIC1103 Captulo 6: Arreglos

50

tipo 2: deshabilitar filas verticales impares. Un ejemplo de aplicaci


on de este patr
on sera (para
una sala de ancho 10 y largo 6, a la que no se le han aplicado otros patrones):
PIZARRON
0 X 0 X 0 X 0 X 0 X
0 X 0 X 0 X 0 X 0 X
0 X 0 X 0 X 0 X 0 X
0 X 0 X 0 X 0 X 0 X
0 X 0 X 0 X 0 X 0 X
0 X 0 X 0 X 0 X 0 X
tipo 3: deshabilitar asientos en cruz (diagonales). Ejemplos de aplicacion de este patr
on seran:
Para una sala de ancho 10 y largo 6, a la que no se le han aplicado otros patrones:
PIZARRON
X 0 0 0 0 0 0 0 0 X
0 X 0 0 0 0 0 0 X 0
0 0 X 0 0 0 0 X 0 0
0 0 0 X 0 0 X 0 0 0
0 0 0 0 X X 0 0 0 0
0 0 0 0 X X 0 0 0 0
Para una sala de ancho 3 y largo 6, a la que no se le han aplicado otros patrones:
PIZARRON
X 0 X
0 X 0
X 0 X
X 0 X
0 X 0
X 0 X
tipo 4: habilitar asientos donde los ndices de su posicion sean ambos pares, o ambos impares.
Ejemplo de aplicaci
on de este patr
on sera:
Para una sala de ancho 10 y largo 6, a la que previamente se le aplicaron los patrones 1 y 2:
PIZARRON
0 X 0 X 0 X 0 X 0 X
X 0 X 0 X 0 X 0 X 0
0 X 0 X 0 X 0 X 0 X
X 0 X 0 X 0 X 0 X 0
0 X 0 X 0 X 0 X 0 X
X 0 X 0 X 0 X 0 X 0
En esta iteracion se le pide que implemente los patrones 1 y 2.
Tambien deber
a implementar por completo la clase Distribucion, la que deber
a poseer los siguientes metodos:
1. Distribucion(Sala sala, Patron[] patrones) Constructor de la clase. Recibe un objeto de tipo
Sala y un arreglo de tipo Patron, con los patrones asociados a esta distribuci
on de asientos.
2. void setSala(Sala sala) Setea la sala.
3. Sala getSala() Retorna la sala asociada a la distribuci
on.
4. void aplicarPatron(int index) Aplica el patr
on almacenado en patrones[index] a la sala
previamente seteada.

IIC1103 Captulo 6: Arreglos

51

Incremento 2
Para completar el segundo incremento, Ud. debe agregar los siguientes metodos a la clase Sala:
1. int getCapacidadResultante() Retorna el n
umero de asientos disponibles (luego de haber aplicado alg
un patr
on, el n
umero de asientos disponibles vara).
2. void imprimirInfoSala() Muestra en pantalla con un mensaje, cierta informaci
on de la sala:
ancho, largo, capacidad total, capacidad resultante luego de aplicar patrones.
Adem
as deber
a implementar el patr
on # 4, dentro del metodo aplicarPatron(...) de la clase Patron.
Incremento 3
Para completar el tercer incremento, Ud. debe agregar los siguientes metodo a la clase Distribucion:
1. void aplicarPatrones() Aplica TODOS los patrones asociados a distribuci
on a la sala previamente seteada.
2. void desaplicarPatrones() Desaplica TODOS los patrones que se han aplicado a la sala de la
distribuci
on.
Adem
as deber
a implementar el patr
on # 3, dentro del metodo aplicarPatron(...) de la clase Patron.
Criterios de soluci
on
Posible soluci
on
public class D i s t r i b u c i o n {
private Sala sala ;
private Patron [] patrones ;
public D i s t r i b u c i o n( Sala sala , Patron [] patrones ) {
this . sala = sala ;
this . patrones = patrones ;
}
public void setSala ( Sala _sala ) {
sala = _sala ;
}
public Sala getSala () {
return sala ;
}
public void a p l i c a r P a t r o n e s () {
for ( int i = 0; i < patrones . length ; i ++) {
patrones [ i ]. a p l i c a r P a t r o n( sala );
}
}
public void d e s a p l i c a r P a t r o n e s() {
for ( int i = 0; i < sala . g e t R e p r e s e n t a c i o n S a l a (). length ; i ++) {
sala . g e t R e p r e s e n t a c i o n S a l a ()[ i ] = 0;
}
}
public void a p l i c a r P a t r o n( int index ) {
patrones [ index ]. a p l i c a r P a t r o n( sala );
}
}
public class Patron {
private int tipo ;
public Patron ( int _tipo ) {

IIC1103 Captulo 6: Arreglos

52

tipo = _tipo ;
}
public void setTipo ( int _tipo ) {
tipo = _tipo ;
}
public int getTipo () {
return tipo ;
}
public void a p l i c a r P a t r o n( Sala _sala ) {
if ( tipo == 1) {
// eliminar filas h o r i z o n t a l e s impares
for ( int i = 0; i < _sala . g e t R e p r e s e n t a c i o n S a l a (). length ; i ++) {
if ( _sala . g e t I n d e x F i l a H o r i z o n t a l( i ) % 2 != 0) {
_sala . g e t R e p r e s e n t a c i o n S a l a()[ i ] = 1;
}
}
} else if ( tipo == 2) {
// eliminar filas v e r t i c a l e s impares
for ( int i = 0; i < _sala . g e t R e p r e s e n t a c i o n S a l a (). length ; i ++) {
if ( _sala . g e t I n d e x F i l a V e r t i c a l( i ) % 2 != 0) {
_sala . g e t R e p r e s e n t a c i o n S a l a()[ i ] = 1;
}
}
} else if ( tipo == 3){
// e l i m i n a c i o n cruz
for ( int i = 0; i < _sala . g e t R e p r e s e n t a c i o n S a l a (). length ; i ++) {
int f i l a V e r t i c a l = _sala . g e t I n d e x F i l a V e r t i c a l( i );
int f i l a H o r i z o n t a l = _sala . g e t I n d e x F i l a H o r i z o n t a l( i );
if ( f i l a V e r t i c a l == f i l a H o r i z o n t a l % _sala . getAncho ()
|| _sala . getAncho () - 1 - f i l a V e r t i c a l == f i l a H o r i z o n t a l
% _sala . getAncho ()) {
_sala . g e t R e p r e s e n t a c i o n S a l a()[ i ] = 1;
}
}
} else if ( tipo == 4) {
// h a b i l i t a c i o n puestos par / par o impar / impar
for ( int i = 0; i < _sala . g e t R e p r e s e n t a c i o n S a l a (). length ; i ++) {
int f i l a V e r t i c a l = _sala . g e t I n d e x F i l a V e r t i c a l( i );
int f i l a H o r i z o n t a l = _sala . g e t I n d e x F i l a H o r i z o n t a l( i );
if ( f i l a V e r t i c a l % 2 == f i l a H o r i z o n t a l % 2) {
_sala . g e t R e p r e s e n t a c i o n S a l a()[ i ] = 0;
}
}
}
}
}
import i i c 1 1 0 3 P a c k a g e .*;
public class Sala {
private int ancho ;
private int largo ;
private int [] r e p r e s e n t a c i o n S a l a;
public Sala ( int _ancho , int _largo ) {
ancho = _ancho ;
largo = _largo ;
r e p r e s e n t a c i o n S a l a = new int [ _ancho * _largo ];
for ( int i = 0; i < r e p r e s e n t a c i o n S a l a. length ; i ++)
r e p r e s e n t a c i o n S a l a[ i ] = 0;
}
public int [] g e t R e p r e s e n t a c i o n S a l a() {
return r e p r e s e n t a c i o n S a l a;
}
public int getLargo () {
return largo ;
}

IIC1103 Captulo 6: Arreglos

53

public int getAncho () {


return ancho ;
}
public int g e t C a p a c i d a d R e s u l t a n t e() {
int c a p a c i d a d = 0;
for ( int i = 0; i < g e t R e p r e s e n t a c i o n S a l a (). length ; i ++) {
if ( g e t R e p r e s e n t a c i o n S a l a ()[ i ] == 0) {
c a p a c i d a d++;
}
}
return c a p a c i d a d;
}
public void i m p r i m i r R e p r e s e n t a c i o n S a l a() {
System . out . println ( " PIZARRON " );
for ( int i = 0; i < r e p r e s e n t a c i o n S a l a. length ; i ++) {
if ( i % ancho == 0) {
System . out . println ();
}
if ( r e p r e s e n t a c i o n S a l a[ i ] == 1) {
System . out . print ( " X " );
} else {
System . out . print ( r e p r e s e n t a c i o n S a l a[ i ]);
}
System . out . print ( " " );
}
System . out . println ( " \ n " );
}
public void i m p r i m i r I n f o S a l a() {
Usuario . mensaje ( " ancho : " + ancho + " \ nlargo : " + largo
+ " \ n c a p a c i d a d original : " + ( ancho * largo )
+ " \ n c a p a c i d a d luego de aplicar patrones : "
+ g e t C a p a c i d a d R e s u l t a n t e ());
}
public int g e t I n d e x F i l a V e r t i c a l( int indexRep ) {
return indexRep % ancho ;
}
public int g e t I n d e x F i l a H o r i z o n t a l( int indexRep ) {
return indexRep / ancho ;
}
}

IIC1103 Captulo 6: Arreglos

54

Problema 23: Ventas Centro Comercial


Enunciado
Usted deber
a implementar un programa que permita contabilizar las ventas realizadas por las tiendas en un
centro comercial. M
as especficamente deber
a implementar las clases Mall y Tienda que permitan al metodo
main ya implementado, poder extraer informaci
on sobre las ventas del centro comercial y las tiendas.
Para la realizaci
on del ejercicio cuenta con la siguiente clase, la cual no debe modificar.
import i i c 1 1 0 3 P a c k a g e .*;
public class P r i n c i p a l {
public static void main ( String [] args ) {
int m a x T i e n d a s = Usuario . entero ( " Ingrese el numero maximo de tiendas que puede " +
" tener el mall . " );
Mall shopping = new Mall ( m a x T i e n d a s);
int opcion = -1;
while ( opcion != 0) {
opcion = Usuario . entero (" Ingrese la opcion de lo que desea hacer : "
+ " \ n (1) Crear una nueva tienda "
+ " \ n (2) Realizar una compra "
+ " \ n (3) Ver el total de ventas del mall "
+ " \ n (4) Ver las tiendas cuyo promedio de ventas se e n c u e n t r a en un cierto rango "
+ " \ n (5) Ver cuantas ventas realizo la tienda con mas ventas "
+ " \ n (0) Salir " );
if ( opcion == 1) {
int m a x V e n t a s = Usuario . entero ( " Ingrese el numero maximo de "
+ " ventas para la tienda . " );
if ( shopping . c r e a r T i e n d a( m a x V e n t a s)) {
Usuario . mensaje ( " La tienda se creo con exito . " );
} else {
Usuario . mensaje ( " No fue posible crear la tienda . " );
}
} else if ( opcion == 2) {
int n u m T i e n d a = Usuario . entero ( " Ingrese el numero de la tienda . " );
int monto = Usuario . entero ( " Ingrese el monto de la compra . " );
if ( shopping . r e a l i z a r C o m p r a( numTienda , monto )) {
Usuario . mensaje ( " Compra r e a l i z a d a con exito . " );
} else {
Usuario . mensaje ( " No fue posible realizar la compra . " );
}
} else if ( opcion == 3) {
Usuario . mensaje ( " Las ventas totales del mall son : "
+ shopping . t o t a l V e n d i d o M a l l ());
} else if ( opcion == 4) {
double cantidad = Usuario . real ( " Ingrese la cantidad con la cual comparar . " );
double d i f e r e n c i a = Usuario . real ( " Ingrese la d i f e r e n c i a maxima p e r m i t i d a. " );
shopping . m o s t r a r C e r c a n o s( cantidad , d i f e r e n c i a);
} else if ( opcion == 5) {
Tienda m a s V e n t a s = shopping . m a s V e n t a s ();
if ( m a s V e n t a s == null ) {
Usuario . mensaje ( " Necesita agregar tiendas al mall . " );
} else {
Usuario . mensaje ( " La tienda con mas ventas ha r e a l i z a d o "
+ m a s V e n t a s. g e t N u m V e n t a s() + " ventas . " );
}
}
}
}
}

El programa lo dividiremos en 3 subconjuntos incrementales. Le recomendamos no comenzar con el siguiente


subconjunto hasta terminar y probar el funcionamiento correcto del subconjunto actual.
Incremento 1
Para completar el primer incremento, deber
a implementar la clase Tienda por completo. A continuaci
on se
detallan los metodos que deber
a tener esta clase.

IIC1103 Captulo 6: Arreglos

55

1. Tienda(int maxVentas) Constructor de la clase. Recibe la cantidad m


axima de ventas que puede
realizar la tienda.
2. int getNumVentas() Retorna la cantidad de ventas realizadas por la tienda.
3. boolean agregarVenta(int monto Agrega una nueva venta a la tienda, seg
un el monto recibido.
Retorna false si no es posible agregar la venta (ya se cumpli
o la cantidad m
axima).
4. int totalVendido() Retorna el monto total de las ventas realizadas.
5. double promedioVentas() Retorna el promedio de las ventas realizadas.
6. int maxVenta() Retorna la venta realizada por la tienda con el mayor monto.
Adem
as en este incremento deber
a implementar la clase Mall con los siguientes metodos:
1. Mall(int max) Constructor de la clase. Recibe la cantidad m
axima de tiendas que puede haber en
el centro comercial.
2. boolean crearTienda(int maxVentas) Permite agregar una nueva tienda al centro comercial.
Recibe como par
ametro la cantidad m
axima de ventas que puede realizar la nueva tienda. Retorna
false en caso de que no sea posible agregar la nueva tienda (ya se tiene la cantidad m
axima de tiendas
posibles).
3. boolean realizarCompra(int numTienda, int monto) Permite realizar una compra en una tienda determinada. Recibe el ndice de la tienda (la tienda 0 es la primera que se agreg
o, la tienda 1 es
la segunda y as sucesivamente), ademas recibe el monto de la compra que se quiere realizar. Retorna
false en caso de no poder realizar la compra en la tienda.
Incremento 2
Para completar el segundo incremento, su programa debe agregar los siguientes metodos a la clase Mall:
1. Tienda masVentas() Permite obtener la tienda que ha realizado mas ventas. Si no hay tiendas en
el centro comercial retorna null.
2. int totalVendidoMall() Retorna el monto total de las ventas en el centro comercial, el cual se
obtiene de la suma de las ventas totales de todas las tiendas.
Incremento 3
Para completar el tercer incremento, su programa debe cumplir con los siguientes requisitos:
1. void mostrarCercanos(double cantidad, double diferencia) Muestra en la consola aquellas
tiendas cuyo promedio de ventas se diferencia de cantidad en a lo m
as diferencia. Al mostrar en la
consola se debe mostrar el ndice de la tienda y el promedio real de la tienda. Despues el metodo debe
mostrar en un mensaje la cantidad de tiendas que cumplieron con el requisito buscado.
Criterios de soluci
on
Posible soluci
on
public class Tienda {
private int [] ventas ;
private int v e n t a A c t u a l;
public Tienda ( int m a x V e n t a s) {
// Al comienzo no hay ventas
v e n t a A c t u a l = 0;

IIC1103 Captulo 6: Arreglos

56

// I n i c i a l i z a m o s el arreglo donde g u a r d a r e m o s las ventas


ventas = new int [ m a x V e n t a s];
}
public int g e t N u m V e n t a s() {
return v e n t a A c t u a l;
}
public boolean a g r e g a r V e n t a( int monto ) {
if ( v e n t a A c t u a l == ventas . length ) {
return false ;
}
ventas [ v e n t a A c t u a l] = monto ;
v e n t a A c t u a l++;
return true ;
}
public int t o t a l V e n d i d o() {
// D e f i n i m o s una variable de a c u m u l a d o r
int total = 0;
// Sumamos todas las ventas que ya se han r e a l i z a d o
for ( int i = 0; i < v e n t a A c t u a l; i ++) {
total += ventas [ i ];
}
return total ;
}
public double p r o m e d i o V e n t a s() {
// Si no hay ventas se retorna 0
if ( v e n t a A c t u a l == 0) {
return 0;
}
// El promedio estara dado por el total de ventas dividido en la
// cantidad
// de ventas r e a l i z a d a s
double prom = t o t a l V e n d i d o();
prom = prom / v e n t a A c t u a l;
return prom ;
}
public int maxVenta () {
// D e f i n i m o s una variable donde g u a r d a r e m o s el maximo
int max = 0;
for ( int i = 0; i < v e n t a A c t u a l; i ++) {
if ( ventas [ i ] > max ) {
max = ventas [ i ];
}
}
return max ;
}
}
import i i c 1 1 0 3 P a c k a g e .*;
public class Mall {
private Tienda [] tiendas ;
private int t i e n d a A c t u a l;
public Mall ( int max ) {
t i e n d a A c t u a l = 0;
// I n i c i a l i z a m o s el arreglo con el tamanio maximo
tiendas = new Tienda [ max ];
}
public boolean c r e a r T i e n d a( int m a x V e n t a s) {
// R e v i s a m o s si aun se pueden agregar nuevas tiendas
if ( t i e n d a A c t u a l == tiendas . length ) {
return false ;
}
// A g r e g a m o s la nueva tienda en la posicion Actual
tiendas [ t i e n d a A c t u a l] = new Tienda ( m a x V e n t a s);
t i e n d a A c t u a l++;
return true ;

IIC1103 Captulo 6: Arreglos

57

}
public boolean r e a l i z a r C o m p r a( int numTienda , int monto ) {
// R e v i s a m o s que la tienda sea valida
if ( n u m T i e n d a >= t i e n d a A c t u a l) {
return false ;
}
// R e t o r n a m o s el valor devuelto por el metodo agregar venta de la
// clase tienda , ya que de no poder a g r e g a r s e mas ventas este debe
// retornar
// false .
return tiendas [ n u m T i e n d a ]. a g r e g a r V e n t a( monto );
}
public Tienda m a s V e n t a s() {
// Buscamos la Tienda que tienes mas ventas r e a l i z a d a s
// Si no hay tiendas r e t o r n a m o s null
if ( t i e n d a A c t u a l == 0) {
return null ;
}
Tienda max = tiendas [0];
// R e c o r r e m o s todas las tiendas para ver cual es la con mas ventas
for ( int i = 1; i < t i e n d a A c t u a l; i ++) {
if ( tiendas [ i ]. g e t N u m V e n t a s() > max . g e t N u m V e n t a s()) {
max = tiendas [ i ];
}
}
return max ;
}
public int t o t a l V e n d i d o M a l l () {
// Si no hay tiendas entonces no hay ventas
if ( t i e n d a A c t u a l == 0) {
return 0;
}
// D e f i n i m o s una variable quesirva de a c u m u l a d o r
int total = 0;
for ( int i = 0; i < t i e n d a A c t u a l; i ++) {
total += tiendas [ i ]. t o t a l V e n d i d o ();
}
return total ;
}
public void m o s t r a r C e r c a n o s( double cantidad , double d i f e r e n c i a) {
// D e f i n i m o s una variable para contar las tiendas que poseen la
// d i f e r e n c i a indicada .
int contador = 0;
// R e c o r r e m o s todas las tiendas y m o s t r a m o s aquellas cuyo promedio
// se d i f e r e n c i a en a lo mas la d i f e r e n c i a indicada con la cantidad
// recibida .
for ( int i = 0; i < t i e n d a A c t u a l; i ++) {
// C a l c u l a m o s la d i f e r e n c i a entre el promedio de la tienda y la
// cantidad
// recibida . Le a p l i c a m o s valor absoluto para que no importe si es
// positivo o negativo
if ( Math . abs ( cantidad - tiendas [ i ]. p r o m e d i o V e n t a s()) <= d i f e r e n c i a) {
contador ++;
Usuario . m e n s a j e C o n s o l a( " La tienda " + i
+ " tiene un promedio de " + " ventas de "
+ tiendas [ i ]. p r o m e d i o V e n t a s ());
}
}
// M o s t r a m o s el mensaje resumen
Usuario . mensaje ( " Se e n c o n t r a r o n " + contador
+ " tiendas cuyo promedio de "
+ " ventas se d i f e r e n c i a b a por a lo mas " + d i f e r e n c i a
+ " con respecto a " + cantidad );
}
}

IIC1103 Captulo 6: Arreglos

58

Problema 24: MasterMind


Enunciado
En este ejercicio usted deber
a construir el juego mundialmente conocido MasterMind (Toque y Fama). Para
esto cuenta con una clase que se encargara del manejo de la interfaz con el usuario, por lo que usted solamente deber
a preocuparse de la l
ogica del juego. La clase InterfazMasterMind mostrada a continuaci
on debe
utilizarla pero no modificarla
import i i c 1 1 0 3 P a c k a g e .*;
/* * Clase que sirve como interfaz grafica simple del juego M a s t e r M i n d
*/
public class I n t e r f a z M a s t e r M i n d {
/* *
* Muestra el estado de un jugador y un menu de opciones
* @param t a b l e r o J u e g o : el tablero del jugador
* @param t a b l e r o A y u d a s : el tablero con las ayudas
* @param i n t e n t o s F a l t a n t e s : la cantidad de intentos que le quedan por hacer
* @return : opcion del usuario
*/
public int M o s t r a r E s t a d o J u g a d o r( int [][] tableroJuego , int [][] tableroAyudas , int i n t e n t o s F a l t a n t e s)
{ ... }
/* *
* Funcion que muestra en pantalla el codigo
* @param codigo : el codigo
*/
public void M o s t r a r C o d i g o( int [] codigo ) { ... }
/* *
* Pide al usuario los numeros del codigo , y retorna un arreglo con ellos
* @param rangoMax : el entero maximo que puede ingresar
* @param c a n t N u m e r o s : la cantidad de numeros a pedir
* @return
*/
public int [] O b t e n e r I n t e n t o( int rangoMax , int c a n t N u m e r o s) { ... }
/* *
* Revisa si un numero ya esta en un arreglo
* @param num : el numero a revisar
* @param intento : el arreglo
* @return true si estaba , false si no
*/
public boolean YaEsta ( int num , int [] intento ) { ... }
/* *
* Arma un string con el tablero y lo retorna
* @param t a b l e r o J u e g o : el tablero a mostrar ( el juego )
* @param t a b l e r o A y u d a s: el tablero con las ayudas
* @return un string con el tablero r e p r e s e n t a d o
*/
private String g e t S t r i n g T a b l e r o( int [][] tableroJuego , int [][] t a b l e r o A y u d a s) { ... }
}

.
El juego consiste en que se genera un c
odigo de un largo predeterminado de n
umeros, y luego el usuario
intenta adivinar el c
odigo generado. Para ello ingresa secuencias de n
umeros del mismo largo que el c
odigo.
Para cada secuencia el juego le indica la cantidad de toques y la cantidad de famas que obtuvo, ambos valores
obtenidos de la comparaci
on del c
odigo ingresado por el usuario con el c
odigo secreto generado por el juego.
Una fama se produce cuando uno de los valores indicados por el usuario est
a justo en la misma posici
on que
el mismo valor en el c
odigo secreto. Por su parte, un toque se produce cuando el c
odigo del usuario contiene
un valor que se encuentra en el c
odigo secreto, pero no est
an en la misma posici
on.
Por ejemplo, si el c
odigo fuera de largo 4, el c
odigo secreto fuese {1, 2, 3, 4} y el usuario ingresa el codigo
{2, 6, 3, 1}, se le debiera indicar al usuario que obtuvo una fama (producto de que el 3 se encuentra en ambos
codigos en la misma posici
on), y 2 toques, provocados por los n
umeros 1 y 2.

IIC1103 Captulo 6: Arreglos

59

Para esta versi


on, el codigo siempre contendr
a valores diferentes.
El jugador tendr
a un m
aximo de intentos para lograr adivinar, perdiendo el juego si no logra dar con el
n
umero.
El programa lo dividiremos en 3 subconjuntos incrementales. Le recomendamos no comenzar con el siguiente
subconjunto hasta terminar y probar el funcionamiento correcto del subconjunto actual.
Incremento 1
En este incremento deber
a crear los siguientes metodos de la clase MasterMind. Esta clase representa a
la l
ogica del juego. Debe contener atributos que permitan guardar el c
odigo secreto, otros que permitan
guardar los valores indicados por el usuario en los diferentes intentos, as como el n
umero de toques y famas
en cada intento. Por u
ltimo, deber
a tener un objeto de la clase InterfazMasterMind, la cual se encargar
a de
interactuar con el usuario. Fjese en los par
ametros que reciben los metodos de la clase InterfazMasterMind
para que se haga una idea de como puede guardar la informaci
on en su clase.
MasterMind() Constructor de la clase.
void InicializarTablero(int maxIntentos, int largoCodigo) Metodo que inicializa los atributos encargados de guardar los c
odigos ingresados por el usuario, as como los resultados generados
por estos c
odigos. Recibe como par
ametros el n
umero m
aximo de intentos y el largo del c
odigo.
void GenerarCodigo(int largoCodigo, int rangoMax) Genera el c
odigo que deber
a adivinar el
usuario. Obtiene los n
umeros de forma aleatoria y verificando que todos sean distintos. Recibe el largo
del codigo y el valor m
aximo para cada n
umero del c
odigo (el mnimo siempre es 1).
void IniciarJuego(int maxIntentos, int largoCodigo, int rangoMax) Permite comenzar a
jugar, manteniendo el ciclo del juego. Debe inicializar el tablero as como calcular el c
odigo. Luego debe
mostrar el tablero utilizando el metodo MostrarEstadoJugador de la clase InterfazMasterMind. Este
metodo retorna la opci
on seleccionada por el usuario, de la cual solamente debe considerar la opci
on 2 y
3. La opci
on 2 permite al usuario ver el c
odigo, para lo cual se debe invocar el metodo MostrarCodigo
de la Interfaz del juego. La opci
on 3 indica que se debe salir del programa.
Adem
as debe crear el main del programa, el cual debe crear un MasterMind, pedir los valores al usuario para
el m
aximo de intentos, el largo del c
odigo y el valor m
aximo de los n
umeros (debe verificar que este u
ltimo
sea mayor o igual al largo del c
odigo).
Incremento 2
Debe agregar a la clase MasterMind el siguiente metodo:
boolean Adivinar(int[] intento) Indica que el usuario desea adivinar el c
odigo secreto. Recibe
como parametro un arreglo con los valores indicados por el usuario, y retorna true en caso de adivinar
completamente el c
odigo, o false en otro caso. Debe comparar el codigo del usuario con el codigo
secreto, calcular el n
umero de toques y famas, guard
andolos donde corresponda, y luego retorna el
valor correspondiente. Recuerde que si el largo del c
odigo es N , entonces en caso de tener N famas
indica que el usuario acerto el codigo.
Incremento 3
Debe agregar al metodo IniciarJuego la posibilidad de manejar la opci
on 1 indicada por el usuario, la
cual indica que desea adivinar el c
odigo. Luego debe llamar al metodo ObtenerIntento de la interfaz, para
luego revisar el intento con el metodo Adivinar. Luego si el usuario adivina se le debe mostrar un mensaje
IIC1103 Captulo 6: Arreglos

60

indic
andole esto y terminar el programa. En caso de que no adivine debe revisarse si a
un le quedan intentos,
si no le quedan se debe mostrar un mensaje indic
andole que perdi
o.
Criterios de soluci
on
Posible soluci
on
import i i c 1 1 0 3 P a c k a g e .*;
public class M a s t e r M i n d {
private int [] codigo ;
private int [][] t a b l e r o J u e g o;
private int [][] t a b l e r o A y u d a s;
private I n t e r f a z M a s t e r M i n d GUI ;
private int n u m I n t e n t o s;
/* * C o n s t r u c t o r */
public M a s t e r M i n d() {
GUI = new I n t e r f a z M a s t e r M i n d();
n u m I n t e n t o s = 0;
}
/* * Metodo que i n i c i a l i z a los valores en el tablero del juego
* @param m a x I n t e n t o s : numero maximo de intentos
* @param l a r g o C o d i g o : numero de valores que forman el codigo
*/
public void I n i c i a l i z a r T a b l e r o( int maxIntentos , int l a r g o C o d i g o) {
// Creamos tablero , i n i c i a l i z a d o en -1
t a b l e r o J u e g o = new int [ m a x I n t e n t o s][ l a r g o C o d i g o];
for ( int i = 0; i < t a b l e r o J u e g o. length ; i ++) {
for ( int j = 0; j < t a b l e r o J u e g o[ i ]. length ; j ++) {
t a b l e r o J u e g o[ i ][ j ] = -1;
}
}
// Creamos tablero de ayudas , i n i c i a l i z a d o en -1
t a b l e r o A y u d a s = new int [ m a x I n t e n t o s ][2];
for ( int i = 0; i < t a b l e r o J u e g o. length ; i ++) {
for ( int j = 0; j < 2; j ++) {
t a b l e r o A y u d a s[ i ][ j ] = -1;
}
}
}
/* *
* Metodo que genera un codigo de forma a l e a t o r i a con todos los valores
* distintos
* @param l a r g o C o d i g o : numero de valores que forman el codigo
* @param rangoMax : valor maximo para cada uno de los numeros que forman el codigo
*/
public void G e n e r a r C o d i g o( int largoCodigo , int rangoMax ) {
// Creamos el arreglo
codigo = new int [ l a r g o C o d i g o];
// G e n e r a m o s los valores al azar , buscando que no se repitan
for ( int i = 0; i < codigo . length ; i ++) {
boolean aceptado = false ;
// Lo c o m p a r a m o s con los valores a n t e r i o r e s
while (! aceptado ) {
codigo [ i ] = A l e a t o r i o. entero (1 , rangoMax );
aceptado = true ;
for ( int j = i - 1; j >= 0; j - -) {
if ( codigo [ j ] == codigo [ i ]) {
aceptado = false ;
}
}
}
}
}
/* *
* Intenta adivinar el codigo
* @param intento : un arreglo con el intento de adivinar el codigo
* @return si gano o todavia no
*/
public boolean Adivinar ( int [] intento ) {
// O b t e n e m o s intento del jugador y lo ponemos en el tablero

IIC1103 Captulo 6: Arreglos

61

for ( int i = 0; i < t a b l e r o J u e g o[ n u m I n t e n t o s]. length ; i ++) {


t a b l e r o J u e g o[ n u m I n t e n t o s][ i ] = intento [ i ];
}
// R e v i s a m o s el intento y armamos las ayudas
t a b l e r o A y u d a s[ n u m I n t e n t o s][0] = 0;
t a b l e r o A y u d a s[ n u m I n t e n t o s][1] = 0;
for ( int i = 0; i < codigo . length ; i ++) {
// R e v i s a m o s si esta el numero correcto en el lugar correcto
if ( codigo [ i ] == t a b l e r o J u e g o[ n u m I n t e n t o s][ i ]) {
t a b l e r o A y u d a s[ n u m I n t e n t o s ][1]++; // Le achunto al numero , y en
// el lugar adecuado
} else {
// Si no esta en el lugar correcto , buscamos si al menos esta en
// otro lugar
for ( int j = 0; j < t a b l e r o J u e g o[ n u m I n t e n t o s]. length ; j ++) {
if (( i != j ) && ( t a b l e r o J u e g o[ n u m I n t e n t o s][ i ] == codigo [ j ])) {
t a b l e r o A y u d a s[ n u m I n t e n t o s ][0]++;
// Le achunto al numero , pero no en el lugar adecuado
}
}
}
}
// R e v i s a m o s si gano
boolean gano = false ;
if ( t a b l e r o A y u d a s[ n u m I n t e n t o s ][1] == codigo . length ) {
gano = true ;
}
// A v a n z a m o s y r e t o r n a m o s
n u m I n t e n t o s++;
return gano ;
}
/* * Metodo p r i n c i p a l del juego
* @param m a x I n t e n t o s : numero maximo de intentos
* @param l a r g o C o d i g o : numero de valores que forman el codigo
* @param rangoMax : valor maximo para cada uno de los numeros que forman el codigo
*/
public void I n i c i a r J u e g o( int maxIntentos , int largoCodigo , int rangoMax ) {
I n i c i a l i z a r T a b l e r o( maxIntentos , l a r g o C o d i g o);
G e n e r a r C o d i g o( largoCodigo , rangoMax );
// Ciclo p r i n c i p a l
boolean salir = false ;
while (! salir ) {
// M o s t r a m o s tablero , o b t e n e m o s opcion y r e v i s a m o s
int opcion = GUI . M o s t r a r E s t a d o J u g a d o r( tableroJuego , tableroAyudas ,
m a x I n t e n t o s - n u m I n t e n t o s);
if ( opcion == 1) {
// O b t e n e m o s c o o r d e n a d a s y marcamos
int [] intento = GUI . O b t e n e r I n t e n t o( rangoMax , l a r g o C o d i g o);
boolean gano = Adivinar ( intento );
// Revisa si gano o perdio , si ya marco todas
if ( gano ) {
Usuario . mensaje ( " A d i v i n a s t e! Ganaste el juego . " );
GUI . M o s t r a r C o d i g o( codigo );
return ;
} else if ( n u m I n t e n t o s == t a b l e r o J u e g o. length ) {
Usuario . mensaje ( " Se te acabaron los intentos ! Perdiste el juego . " );
GUI . M o s t r a r C o d i g o( codigo );
return ;
}
} else if ( opcion == 2) {
GUI . M o s t r a r C o d i g o( codigo );
} else if ( opcion == 3) {
salir = true ;
}
}
}
}
import i i c 1 1 0 3 P a c k a g e .*;
public class P r i n c i p a l {
public static void main ( String [] args ) {
// Crea el objeto del juego

IIC1103 Captulo 6: Arreglos

62

M a s t e r M i n d juego = new M a s t e r M i n d();


// Pedimos al usuario los datos c o r r e s p o n d i e n t e s
int m a x I n t e n t o s = Usuario . entero ( " Ingrese el numero maximo de intentos : " );
int l a r g o C o d i g o = Usuario . entero ( " Ingrese el largo del codigo : " );
int maxRango = Usuario . entero ( " Ingrese el maximo para los valores del codigo : " );
// R e v i s a m o s que sea mayor o igual al largo
while ( maxRango < l a r g o C o d i g o) {
maxRango = Usuario . entero ( " Ingrese el maximo para los valores del codigo : " );
}
// Comienza el juego
juego . I n i c i a r J u e g o( maxIntentos , largoCodigo , maxRango );
}
}

IIC1103 Captulo 6: Arreglos

63

También podría gustarte