Algoritmo para distribuir cursos en tabla
This commit is contained in:
parent
77f6d638bc
commit
76f723a097
247
__tests__/celdas.ts
Normal file
247
__tests__/celdas.ts
Normal file
@ -0,0 +1,247 @@
|
||||
|
||||
interface Curso {
|
||||
// Nombre completo del curso
|
||||
nombre: string,
|
||||
// Nombre del curso abreviado
|
||||
abreviado: string,
|
||||
// Información de las horas de teoria
|
||||
Teoria: {
|
||||
// grupo es una letra: A, B, C, D
|
||||
[grupo: string]: DatosGrupo,
|
||||
},
|
||||
// Información de las horas de laboratorio
|
||||
Laboratorio?: {
|
||||
// grupo es una letra: A, B, C, D
|
||||
[grupo: string]: DatosGrupo,
|
||||
},
|
||||
}
|
||||
|
||||
interface DatosGrupo {
|
||||
// Nombre del docente de este grupo
|
||||
Docente: string,
|
||||
/*
|
||||
Las horas del curso en el siguiente formato: DD_HHMM
|
||||
DD puede ser Lu, Ma, Mi, Ju, Vi
|
||||
Ejm: Ma0850, Vi1640, Ju1550
|
||||
*/
|
||||
Horas: string[]
|
||||
}
|
||||
|
||||
// Exclusivo de un unico dia
|
||||
type Input = {
|
||||
horaInicio: number,
|
||||
nroHoras: number,
|
||||
}
|
||||
|
||||
type Output = {
|
||||
horaInicio: number,
|
||||
nroHoras: number,
|
||||
offset: number, // 0, 1, 2
|
||||
fraccion: number, // por cuanto dividir la celda. 1, 2, 3, ...
|
||||
}
|
||||
|
||||
class MapaCeldas {
|
||||
// Almacena referencias a input
|
||||
private mapa: Map<number, Map<number, Input>> = new Map();
|
||||
|
||||
private disponible(nroFila: number, nroColumna: number): boolean {
|
||||
if (!this.mapa.has(nroFila)) return true;
|
||||
|
||||
const fila = this.mapa.get(nroFila)!;
|
||||
|
||||
return fila.has(nroColumna) === false;
|
||||
}
|
||||
|
||||
private obtenerFilaOCrear(nro: number): Map<number, Input> {
|
||||
if (!this.mapa.has(nro)) {
|
||||
const m = new Map<number, Input>();
|
||||
this.mapa.set(nro, m);
|
||||
return m;
|
||||
}
|
||||
|
||||
return this.mapa.get(nro)!;
|
||||
}
|
||||
|
||||
// Devuelve el offset
|
||||
public solicitar(inicio: number, cantidad: number, input: Input): number {
|
||||
const filas = [];
|
||||
for (let i = 0; i < cantidad; i += 1) filas.push(inicio + i);
|
||||
|
||||
for (let offsetActual = 0; offsetActual < 8; offsetActual += 1) {
|
||||
let todasCeldasDisponibles = true;
|
||||
for (const fila of filas) {
|
||||
if (!this.disponible(fila, offsetActual)) {
|
||||
todasCeldasDisponibles = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (todasCeldasDisponibles) {
|
||||
// Crear estas celdas y almacenar
|
||||
filas.forEach((nroFila) => {
|
||||
const fila = this.obtenerFilaOCrear(nroFila);
|
||||
fila.set(offsetActual, input);
|
||||
});
|
||||
|
||||
// Devolver nro de offset
|
||||
return offsetActual;
|
||||
}
|
||||
}
|
||||
|
||||
throw new Error("Limite de celdas alcanzado");
|
||||
}
|
||||
|
||||
public generarFraccion(nroFila: number, nroColumna: number, cantidad: number): number {
|
||||
let fraccionActual = 1;
|
||||
for (let i = 0; i < cantidad; i += 1) {
|
||||
const nroFilaActual = nroFila + i;
|
||||
const filaActual = this.mapa.get(nroFilaActual)!;
|
||||
const numeroColumnas = filaActual.size;
|
||||
if (numeroColumnas > fraccionActual) {
|
||||
fraccionActual = numeroColumnas;
|
||||
}
|
||||
}
|
||||
|
||||
return fraccionActual;
|
||||
}
|
||||
}
|
||||
|
||||
function generarMapaCeldas(entrada: Readonly<Array<Input>>): Array<Output> {
|
||||
const mapa = new MapaCeldas();
|
||||
const salida: Array<Output> = [];
|
||||
|
||||
// Obtener los offsets de cada curso
|
||||
for (const input of entrada) {
|
||||
const offset = mapa.solicitar(input.horaInicio, input.nroHoras, input);
|
||||
salida.push({
|
||||
...input,
|
||||
offset,
|
||||
fraccion: -1,
|
||||
});
|
||||
}
|
||||
|
||||
// Generar las fracciones de cada curso
|
||||
for (const output of salida) {
|
||||
output.fraccion = mapa.generarFraccion(output.horaInicio, output.offset, output.nroHoras);
|
||||
}
|
||||
|
||||
return salida;
|
||||
}
|
||||
|
||||
describe("generarMapaCeldas", () => {
|
||||
it("vacio si input es vacio", () => {
|
||||
const input: Array<Input> = [];
|
||||
const output = generarMapaCeldas(input);
|
||||
expect(output.length).toBe(0);
|
||||
});
|
||||
|
||||
it("funciona con 1 curso", () => {
|
||||
const input: Array<Input> = [
|
||||
{
|
||||
horaInicio: 0,
|
||||
nroHoras: 2,
|
||||
},
|
||||
];
|
||||
const output = generarMapaCeldas(input)[0];
|
||||
expect(output).not.toBeUndefined();
|
||||
expect(output.offset).toBe(0);
|
||||
expect(output.fraccion).toBe(1);
|
||||
});
|
||||
|
||||
it("funciona con 2 cursos", () => {
|
||||
const input: Array<Input> = [
|
||||
{
|
||||
horaInicio: 0,
|
||||
nroHoras: 2,
|
||||
},
|
||||
{
|
||||
horaInicio: 1,
|
||||
nroHoras: 3,
|
||||
},
|
||||
];
|
||||
|
||||
const output1 = generarMapaCeldas(input)[0];
|
||||
expect(output1.offset).toBe(0);
|
||||
expect(output1.fraccion).toBe(2);
|
||||
|
||||
const output2 = generarMapaCeldas(input)[1];
|
||||
expect(output2.offset).toBe(1);
|
||||
expect(output2.fraccion).toBe(2);
|
||||
});
|
||||
});
|
||||
|
||||
describe("MapaCeldas", () => {
|
||||
it("crea 1", () => {
|
||||
const mapa = new MapaCeldas();
|
||||
const input = {} as unknown as Input;
|
||||
const offset = mapa.solicitar(0, 2, input);
|
||||
expect(offset).toBe(0);
|
||||
});
|
||||
|
||||
it("crea varios que no se solapan", () => {
|
||||
const mapa = new MapaCeldas();
|
||||
const input = {} as unknown as Input;
|
||||
let offset = mapa.solicitar(0, 2, input);
|
||||
expect(offset).toBe(0);
|
||||
offset = mapa.solicitar(4, 3, input);
|
||||
expect(offset).toBe(0);
|
||||
offset = mapa.solicitar(7, 4, input);
|
||||
expect(offset).toBe(0);
|
||||
});
|
||||
|
||||
it("crea varios que se solapan", () => {
|
||||
const mapa = new MapaCeldas();
|
||||
const input = {} as unknown as Input;
|
||||
let offset = mapa.solicitar(0, 2, input);
|
||||
expect(offset).toBe(0);
|
||||
offset = mapa.solicitar(0, 2, input);
|
||||
expect(offset).toBe(1);
|
||||
offset = mapa.solicitar(0, 4, input);
|
||||
expect(offset).toBe(2);
|
||||
});
|
||||
|
||||
it("crea varios que se solapan de formas diferentes", () => {
|
||||
/*
|
||||
x
|
||||
x x x
|
||||
y x x
|
||||
y x x
|
||||
y z x
|
||||
z
|
||||
z
|
||||
*/
|
||||
const mapa = new MapaCeldas();
|
||||
const input = {} as unknown as Input;
|
||||
let offset = mapa.solicitar(0, 2, input);
|
||||
expect(offset).toBe(0);
|
||||
offset = mapa.solicitar(1, 3, input);
|
||||
expect(offset).toBe(1);
|
||||
offset = mapa.solicitar(1, 4, input);
|
||||
expect(offset).toBe(2);
|
||||
offset = mapa.solicitar(2, 3, input);
|
||||
expect(offset).toBe(0);
|
||||
offset = mapa.solicitar(4, 2, input);
|
||||
expect(offset).toBe(1);
|
||||
});
|
||||
|
||||
it("genera offsets", () => {
|
||||
const mapa = new MapaCeldas();
|
||||
const input = {} as unknown as Input;
|
||||
let offset = mapa.solicitar(0, 2, input);
|
||||
expect(offset).toBe(0);
|
||||
let fraccion = mapa.generarFraccion(0, offset, 2);
|
||||
expect(fraccion).toBe(1);
|
||||
|
||||
offset = mapa.solicitar(1, 3, input);
|
||||
fraccion = mapa.generarFraccion(1, offset, 3);
|
||||
expect(fraccion).toBe(2);
|
||||
|
||||
mapa.solicitar(1, 4, input);
|
||||
mapa.solicitar(2, 3, input);
|
||||
offset = mapa.solicitar(4, 2, input);
|
||||
fraccion = mapa.generarFraccion(4, offset, 2);
|
||||
expect(fraccion).toBe(3);
|
||||
});
|
||||
});
|
||||
|
||||
export {};
|
@ -12,9 +12,11 @@
|
||||
"component-register": "0.7.x",
|
||||
"eslint": "^7.22.0",
|
||||
"eslint-plugin-react": "^7.23.1",
|
||||
"jest": "^29.1.2",
|
||||
"normalize.css": "^8.0.1",
|
||||
"solid-app-router": "^0.3.2",
|
||||
"solid-js": "^1.3.12",
|
||||
"ts-jest": "^29.0.3",
|
||||
"typescript": "^4.6.2",
|
||||
"vite": "^2.8.6",
|
||||
"vite-plugin-solid": "^2.2.6"
|
||||
|
1562
pnpm-lock.yaml
1562
pnpm-lock.yaml
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user