Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

OFMI 2023.5 #37

Merged
merged 2 commits into from
May 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
2 changes: 2 additions & 0 deletions 2023.5/dia-1/ofmi-2023-basquet/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
**/*.out
!tests/invalid-cases/*.out
133 changes: 133 additions & 0 deletions 2023.5/dia-1/ofmi-2023-basquet/case-generator.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
import os
import random

base_string = """
{arr}
""".strip(
" \t\n\r"
)

num_subtareas = 1
puntos_por_subtarea = [100]
casos_por_subtarea = [21]
subtarea_agrupada = [False for _ in range(num_subtareas)]
sample_case_names = ["sample", "sample2"]


def has_solution(arr):
for x in arr:
for y in arr:
z = 100 - x - y
if z in arr and x != y and x != z and y != z:
return True
return False


def generate_case(_, case_number):
n = 5
if case_number == 0:
# Generate impossible case
arr = [random.randint(1, 100) for _ in range(n)]
while len(arr) != len(set(arr)) or has_solution(arr):
arr = [random.randint(1, 100) for _ in range(n)]
else:
# Generate random case
a = random.randint(1, 100)
b = random.randint(1, 100)
a, b = min(a, b), max(a, b)
arr = [a, b - a, 100 - b]
while len(arr) != len(set(arr)):
a = random.randint(1, 100)
b = random.randint(1, 100)
a, b = min(a, b), max(a, b)
arr = [a, b - a, 100 - b]
# shuffle the array
random.shuffle(arr)
# add random numbers
for _ in range(n - 3):
x = random.randint(1, 100)
while x in arr:
x = random.randint(1, 100)
arr.append(x)
perm = case_number % 10
for i in range(n):
for j in range(i + 1, n):
perm -= 1
if perm == 0:
arr[i], arr[-2] = arr[-2], arr[i]
arr[j], arr[-1] = arr[-1], arr[j]
return {"arr": " ".join(map(str, arr))}


# This helper function will generate a number that is linearly increasing
# with the case number. This is useful to make cases bigger as the case_number
def linear_incremental(subtarea, case_number, max_number):
casos_subtarea = casos_por_subtarea[subtarea - 1]
# pendiente * casos_subtarea = max_number
pendiente = max_number // casos_subtarea
return pendiente * (case_number + 1)


# This helper function will generate a number that is k-power increasing
# with the case number. This is useful to make cases bigger as the case_number
def power_incremental(subtarea, case_number, max_number, k=4):
casos_subtarea = casos_por_subtarea[subtarea - 1]
# c* casos_subtarea^4 = max_number
c = max_number / (casos_subtarea**k)
return int(c * (case_number + 1) ** k)


def get_case_name(subtarea, case_number):
agrupados = subtarea_agrupada[subtarea - 1]
if agrupados:
return f"sub{subtarea}.{case_number}"
return f"sub{subtarea}_{case_number}"


def get_case_points(subtarea, case_number):
puntos_subtarea = puntos_por_subtarea[subtarea - 1]
casos_subtarea = casos_por_subtarea[subtarea - 1]
agrupados = subtarea_agrupada[subtarea - 1]
if agrupados:
return puntos_subtarea if case_number == 0 else 0
return puntos_subtarea // casos_subtarea + (
1 if puntos_subtarea % casos_subtarea > case_number else 0
)


def write_testplan():
assert len(sample_case_names) == len(set(sample_case_names))
with open("testplan", "w") as f:
for case_name in sample_case_names:
f.write(f"{case_name} 0\n")

for subtarea in range(1, num_subtareas + 1):
for case_number in range(casos_por_subtarea[subtarea - 1]):
case_name = get_case_name(subtarea, case_number)
case_points = get_case_points(subtarea, case_number)
assert case_name not in sample_case_names
with open("testplan", "a") as f:
f.write(f"{case_name} {case_points}\n")


def write_cases():
for subtarea in range(1, num_subtareas + 1):
for case_number in range(casos_por_subtarea[subtarea - 1]):
case_name = get_case_name(subtarea, case_number)
case_path = os.path.join("cases", case_name)
with open(f"{case_path}.in", "w") as f:
case = generate_case(subtarea, case_number)
case_string = base_string.format(**case)
f.write(f"{case_string}\n")


def main():
random.seed(348101)
assert num_subtareas == len(puntos_por_subtarea) == len(casos_por_subtarea)
assert sum(puntos_por_subtarea) == 100
write_testplan()
write_cases()


if __name__ == "__main__":
main()
1 change: 1 addition & 0 deletions 2023.5/dia-1/ofmi-2023-basquet/cases/sample.in
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
40 13 25 20 35
1 change: 1 addition & 0 deletions 2023.5/dia-1/ofmi-2023-basquet/cases/sample2.in
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
14 34 12 59 60
1 change: 1 addition & 0 deletions 2023.5/dia-1/ofmi-2023-basquet/cases/sub1_0.in
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
85 58 82 83 26
1 change: 1 addition & 0 deletions 2023.5/dia-1/ofmi-2023-basquet/cases/sub1_1.in
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
61 9 11 47 42
1 change: 1 addition & 0 deletions 2023.5/dia-1/ofmi-2023-basquet/cases/sub1_10.in
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
36 55 9 22 43
1 change: 1 addition & 0 deletions 2023.5/dia-1/ofmi-2023-basquet/cases/sub1_11.in
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
41 40 24 66 10
1 change: 1 addition & 0 deletions 2023.5/dia-1/ofmi-2023-basquet/cases/sub1_12.in
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
43 51 20 32 17
1 change: 1 addition & 0 deletions 2023.5/dia-1/ofmi-2023-basquet/cases/sub1_13.in
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
70 33 7 2 60
1 change: 1 addition & 0 deletions 2023.5/dia-1/ofmi-2023-basquet/cases/sub1_14.in
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
82 57 11 32 21
1 change: 1 addition & 0 deletions 2023.5/dia-1/ofmi-2023-basquet/cases/sub1_15.in
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
17 48 72 6 77
1 change: 1 addition & 0 deletions 2023.5/dia-1/ofmi-2023-basquet/cases/sub1_16.in
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
27 50 71 6 2
1 change: 1 addition & 0 deletions 2023.5/dia-1/ofmi-2023-basquet/cases/sub1_17.in
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
42 81 51 7 40
1 change: 1 addition & 0 deletions 2023.5/dia-1/ofmi-2023-basquet/cases/sub1_18.in
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
22 55 36 52 23
1 change: 1 addition & 0 deletions 2023.5/dia-1/ofmi-2023-basquet/cases/sub1_19.in
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
50 16 25 7 77
1 change: 1 addition & 0 deletions 2023.5/dia-1/ofmi-2023-basquet/cases/sub1_2.in
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
77 20 99 67 13
1 change: 1 addition & 0 deletions 2023.5/dia-1/ofmi-2023-basquet/cases/sub1_20.in
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
77 7 25 16 50
1 change: 1 addition & 0 deletions 2023.5/dia-1/ofmi-2023-basquet/cases/sub1_3.in
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
85 11 52 64 37
1 change: 1 addition & 0 deletions 2023.5/dia-1/ofmi-2023-basquet/cases/sub1_4.in
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
64 47 10 43 17
1 change: 1 addition & 0 deletions 2023.5/dia-1/ofmi-2023-basquet/cases/sub1_5.in
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
54 48 1 38 8
1 change: 1 addition & 0 deletions 2023.5/dia-1/ofmi-2023-basquet/cases/sub1_6.in
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
14 49 4 89 82
1 change: 1 addition & 0 deletions 2023.5/dia-1/ofmi-2023-basquet/cases/sub1_7.in
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
19 18 9 72 15
1 change: 1 addition & 0 deletions 2023.5/dia-1/ofmi-2023-basquet/cases/sub1_8.in
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
17 26 97 54 57
1 change: 1 addition & 0 deletions 2023.5/dia-1/ofmi-2023-basquet/cases/sub1_9.in
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
12 8 10 80 1
1 change: 1 addition & 0 deletions 2023.5/dia-1/ofmi-2023-basquet/examples/sample.in
1 change: 1 addition & 0 deletions 2023.5/dia-1/ofmi-2023-basquet/examples/sample2.in
25 changes: 25 additions & 0 deletions 2023.5/dia-1/ofmi-2023-basquet/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{
"title": "Basquetbol",
"source": "OFMI 2023.5 (Juan Carlos Sigler Priego)",
"limits": {
"TimeLimit": 1000,
"MemoryLimit": 134217728,
"InputLimit": 67108864,
"OutputLimit": 67108864,
"ExtraWallTime": 0,
"OverallWallTimeLimit": 60000
},
"validator": {
"name": "custom",
"limits": {
"TimeLimit": 1000
}
},
"misc": {
"alias": "ofmi-2023-basquet",
"visibility": "public",
"languages": "all",
"email_clarifications": 0,
"admin-groups": ["ofmi-2023-5"]
}
}
34 changes: 34 additions & 0 deletions 2023.5/dia-1/ofmi-2023-basquet/solutions/es.markdown
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
Este problema nos pide seleccionar, de entre $5$ números diferentes, $3$ cuya suma sea igual a $100$.

Si nombramos a los $5$ números de la entrada como $a, b, c, d$ y $e$, tenemos $10$ maneras diferentes de seleccionar la suma de tres de ellos:

- $a + b + c$
- $a + b + d$
- $a + b + e$
- $a + c + d$
- $a + c + e$
- $a + d + e$
- $b + c + d$
- $b + c + e$
- $b + d + e$
- $c + d + e$

Entonces, una forma de resolver el problema es calcular estas $10$ sumas y verificar si alguna de ellas es igual a $100$. El siguiente código implementa dicha idea.

<details><summary>Solución verificando las 10 sumas diferentes</summary>

{{solution.cpp}}

</details>

Una alternativa para resolver este problema es, en lugar de guardar los cinco números de la entrada como cinco variables distintas, guardarlos a todos en un arreglo, `playeras`, de tamaño $5$.

Si guardamos los números en las playeras de esa forma, encontrar $3$ de ellos que sumen $100$ equivale a encontrar $3$ índices distintos, $i, j, k$, uno para cada playera a elegir, que cumplan que `playeras[i] + playeras[j] + playeras[k] = 100`. Esto se puede lograr usando tres _fors_ anidados para iterar sobre todas las ternas $i, j, k$ posibles. El siguiente código implementa dicha solución.

<details><summary>Solución guardando los valores en un arreglo</summary>

{{solutionB.cpp}}

</details>

Nota que ambas soluciones prueban todas las formas posibles de seleccionar $3$ números distintos de entre los $5$ que son dados en la entrada, pero la primera solución guarda los números en $5$ variables diferentes mientras que la segunda solución los guarda en un arreglo.
22 changes: 22 additions & 0 deletions 2023.5/dia-1/ofmi-2023-basquet/solutions/parcial.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#include <iostream>

int playeras[6];
int suma_playeras;

int main() {
for (int i = 1; i <= 5; i++) std::cin >> playeras[i];

for (int i = 1; i <= 5; i++) {
for (int j = 2; j <= 5; j++) {
for (int k = 3; k <= 5; k++) {
suma_playeras = playeras[i] + playeras[j] + playeras[k];
if (suma_playeras == 100) {
std::cout << playeras[i] << " " << playeras[j] << " " << playeras[k];
return 0;
}
}
}
}

std::cout << -1;
}
66 changes: 66 additions & 0 deletions 2023.5/dia-1/ofmi-2023-basquet/solutions/solution.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
#include <iostream>

int main() {
// Leemos los 5 números a, b, c, d, e
int a, b, c, d, e;
std::cin >> a >> b >> c >> d >> e;

// Vamos a probar todas las combinaciones de 3 números
// En busca del primero que sume 100.
// En total son 10 combinaciones

// Primera combinación: a, b, c
if (a + b + c == 100) {
std::cout << a << ' ' << b << ' ' << c << '\n';
return 0;
}
// Segunda combinación: a, b, d
if (a + b + d == 100) {
std::cout << a << ' ' << b << ' ' << d << '\n';
return 0;
}
// Tercera combinación: a, b, e
if (a + b + e == 100) {
std::cout << a << ' ' << b << ' ' << e << '\n';
return 0;
}
// Cuarta combinación: a, c, d
if (a + c + d == 100) {
std::cout << a << ' ' << c << ' ' << d << '\n';
return 0;
}
// Quinta combinación: a, c, e
if (a + c + e == 100) {
std::cout << a << ' ' << c << ' ' << e << '\n';
return 0;
}
// Sexta combinación: a, d, e
if (a + d + e == 100) {
std::cout << a << ' ' << d << ' ' << e << '\n';
return 0;
}
// Séptima combinación: b, c, d
if (b + c + d == 100) {
std::cout << b << ' ' << c << ' ' << d << '\n';
return 0;
}
// Octava combinación: b, c, e
if (b + c + e == 100) {
std::cout << b << ' ' << c << ' ' << e << '\n';
return 0;
}
// Novena combinación: b, d, e
if (b + d + e == 100) {
std::cout << b << ' ' << d << ' ' << e << '\n';
return 0;
}
// Décima combinación: c, d, e
if (c + d + e == 100) {
std::cout << c << ' ' << d << ' ' << e << '\n';
return 0;
}

// Ninguna combinación sumó 100
std::cout << -1 << '\n';
return 0;
}
22 changes: 22 additions & 0 deletions 2023.5/dia-1/ofmi-2023-basquet/solutions/solutionB.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#include <iostream>

int playeras[6];
int suma_playeras;

int main() {
for (int i = 1; i <= 5; i++) std::cin >> playeras[i];

for (int i = 1; i <= 3; i++) {
for (int j = i + 1; j <= 4; j++) {
for (int k = j + 1; k <= 5; k++) {
suma_playeras = playeras[i] + playeras[j] + playeras[k];
if (suma_playeras == 100) {
std::cout << playeras[i] << " " << playeras[j] << " " << playeras[k];
return 0;
}
}
}
}

std::cout << -1;
}
Loading
Loading