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

Submissão do problema 01 #32

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
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
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions submissions/justgigio/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
FROM python:3.12-slim

RUN pip install psutil

ADD ./instances /instances

WORKDIR /app

CMD ["bash"]
35 changes: 35 additions & 0 deletions submissions/justgigio/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# Como rodar

>*Nota:* talvez seja necessário rodar `chmod +x run* problema*`

## Com Docker

Primeiro é necessário fazer o build da imagem (é uma versão slim, então pode ficar de boa que vai ser rápido e ocupar pouquíssimo espaço)

`$ ./run.sh build`

Depois basta rodar o mesmo script passando o número problema desejado ou nada para rodar todos:

`$ ./run.sh 2` ou simplesmente `$ ./run.sh`

Também é possível rodar o bash no container para fins de debug ou simplesmente ter mais controle:

`$ ./run.sh bash`

Em seguida, para rodar o script deve-se usar o python diretamente:

`$ python run.py [numero_do_problema]`

## Sem Docker

O arquivo `run.py` foi feito pra encontrar as entradas e saídas da forma como elas são copiadas dentro do container/imagem.

Ou seja, para rodar sem o Docker deve-se rodar diretamente o problema desejado passando a entrada desejada por `stdin`. Exemplo:

`$ python problema-3.py < ../../resources/instances/problem_03/exemplo_02.txt`

A respota vai ser direcionada para o `stdout` (nese caso, print no terminal)

Nesse caso é possível comparar o resultado com a resposta dessa forma:

`$ diff -s <(cat ../../resources/instances/problem_01/resultados.txt | grep exemplo_01 | sed 's/exemplo_01.txt\s*//') <(python problema-1.py < ../../resources/instances/problem_01/exemplo_01.txt)` :sweat_smile:
80 changes: 80 additions & 0 deletions submissions/justgigio/problema-1.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@

from collections import defaultdict


def seeds_who_fits_by_size(ss, sp):
res = {}
for size, prices in ss.items():
res[size] = []
sm = 0
prices.sort(reverse=True)
for p in prices:
if sm + size <= sp:
sm += size
res[size].append(p)

return res


def price_avg_by_size(ss, sp):
res = {}
avsizes = []
change_avg = False
for size, prices in ss.items():
if len(prices) > 0:
avsizes.append(size)
if len(avsizes) > 1:
avsizes.sort()
change_avg = (avsizes[0] + avsizes[1]) > sp

for size, prices in ss.items():
if len(prices) > 0:
avg = sum(prices) * 1.0 / len(prices)

if not change_avg:
avg = avg / size

res[size] = avg
else:
res[size] = 0

return res


def get_max_key(ss):
mxk = list(ss.keys())[0]
for key in ss.keys():
if ss[key] > ss[mxk]:
mxk = key

return mxk


seeds = defaultdict(list)

seeds_count, spaces = map(int, input().split())

for i in range(seeds_count):
space, price = map(int, input().split())
seeds[space].append(price)

profit = 0
filled = 0

while filled < spaces:

fits = seeds_who_fits_by_size(seeds, spaces - filled)
avg = price_avg_by_size(fits, spaces - filled)

if sum(avg.values()) == 0:
break

space = get_max_key(avg)
price = fits[space].pop(0)

seeds[space].remove(price)

profit += price
filled += space

print(profit)
112 changes: 112 additions & 0 deletions submissions/justgigio/run.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
#!/usr/bin/env python3

import sys
import math
import time
import psutil
from os import path, listdir
from subprocess import Popen, PIPE, call, DEVNULL

IO_FOLDER = '../instances'

GREEN = '\033[92m'
RED = '\033[91m'
ENDCOLOR = '\033[0m'


def profile_script(script, stdin):
t0 = time.time()
popen = Popen(script, stdin=open(stdin, 'rb'), stdout=PIPE, stderr=PIPE)
process = psutil.Process(popen.pid)
max_mem = 0
while popen.poll() is None:
try:
curr_mem = process.memory_full_info().uss
if curr_mem > max_mem:
max_mem = curr_mem
except psutil.NoSuchProcess:
break
execution_time = time.time() - t0
status_code = popen.poll()
script_ouput = popen.stdout.read().decode('utf-8')[:-1]
if status_code != 0:
raise Exception(script_ouput + popen.stderr.read().decode('utf-8'))
popen.terminate()
return [script_ouput, execution_time, max_mem]


def convert_size(size_bytes):
# https://stackoverflow.com/a/14822210/4288138
if size_bytes == 0:
return "0B"
size_name = ("B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB")
i = int(math.floor(math.log(size_bytes, 1024)))
p = math.pow(1024, i)
s = round(size_bytes / p, 2)
return "%s %s" % (s, size_name[i])


def run_script(number):
script_name = f"problema-{number}.py"
io_path = path.join(IO_FOLDER, f"problem_{number:0>2}")
results_file = path.join(io_path, "resultados.txt")

if not path.isfile(script_name):
print(f"{RED}ERROR: No file {script_name} found!{ENDCOLOR}")
return

if not path.isfile(results_file):
print(f"{RED}ERROR: No results found for {script_name}{ENDCOLOR}")
return

results = {}
with open(results_file, "r") as fr:
for line in fr.readlines():
key, value = line.split()
results[key] = value

examples = [f for f in listdir(io_path) if path.isfile(path.join(io_path, f)) and f.startswith("exemplo_")]
examples = sorted(examples)

if len(examples) == 0:
print(f"{RED}ERROR: No examples found for {script_name}{ENDCOLOR}")
return

print('=' * 30)
print(f"# {script_name: <26} #")
print('=' * 30)

for example in examples:
try:
script_ouput, execution_time, memory_used = profile_script(["python", f"{script_name}"], f"{path.join(io_path, example)}")
except Exception as e:
title = f"{script_name} < {example} !!"
print(f"{RED} - FAILED :: {title}{ENDCOLOR}")
print(f" {e}")
continue

cmd = f"diff -q <(echo \"{results[example]}\") <(echo \"{script_ouput}\")"
exit_code = call(["/bin/bash", "-c", cmd], stdout=DEVNULL)

title = f"{script_name} < {example} :: [{execution_time:.4f}s | {convert_size(memory_used)}]"

if exit_code == 0:
print(f"{GREEN} - OK :: {title}{ENDCOLOR}")
else:
print(f"{RED} - FAILED :: {title}{ENDCOLOR}")
print(f" Expected: {results[example]}")
print(f" Found: {script_ouput}")


if len(sys.argv) > 1:
number = int(sys.argv[1])
run_script(number)
else:
scripts = [f for f in listdir() if path.isfile(f) and f.startswith("problema-")]
scripts = sorted(scripts)

for script in scripts:
_, num_ext = script.split('-')
num, ext = num_ext.split('.')

run_script(num)
13 changes: 13 additions & 0 deletions submissions/justgigio/run.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#!/bin/bash


if [ "$1" = "build" ]; then
mkdir instances
cp -r ../../resources/instances/* instances
docker build -t rinha-run . --no-cache
rm -rf instances
elif [ "$1" = "bash" ]; then
docker run --rm -it --cpus=2 --memory=2GB -v $(pwd):/app rinha-run bash
else
docker run --rm -it --cpus=2 --memory=2GB -v $(pwd):/app rinha-run /bin/bash -c "python run.py $1"
fi