Maratona de Programação

Opa,

Eu achei uns exercícios da maratona de 2007 perdidos aqui:

Maratona de Programação da SBC-ACM ICPC-2007 3

[color=black][size=18]Problema B

Rouba-Monte

Nome do arquivo fonte: rouba.c, rouba.cpp, rouba.java ou rouba.pas[/size][/color]

Um dos jogos de cartas mais divertidos para crianças pequenas, pela simplicidade, é Rouba-
Monte. O jogo utiliza um ou mais baralhos normais e tem regras muito simples. Cartas
são distinguidas apenas pelo valor (ás, dois, três, . . .), ou seja, os naipes das cartas não são
considerados (por exemplo, ás de paus e ás de ouro têm o mesmo valor).
Inicialmente as cartas são embaralhadas e colocadas em uma pilha na mesa de jogo, chamada
de pilha de compra, com face voltada para baixo. Durante o jogo, cada jogador mantém um
monte de cartas, com face voltada para cima; em um dado momento o monte de um jogador
pode conter zero ou mais cartas. No inécio do jogo, todos os montes dos jogadores têm zero
cartas. Ao lado da pilha de compras encontra-se uma área denomindada de área de descarte,
inicialmente vazia, e todas as cartas colocadas na área de descarte são colocadas lado a lado
com a face para cima (ou seja, não são empilhadas).
Os jogadores, dispostos em um círculo ao redor da mesa de jogo, jogam em sequência, em
sentido horário. As jogadas prosseguem da seguinte forma:

  • O jogador que tem a vez de jogar retira a carta de cima da pilha de compras e a mostra
    aos outros jogadores; vamos chamar essa carta de carta da vez.

  • Se a carta da vez for igual a alguma carta presente na área de descarte, o jogador retira
    essa carta da área de descarte colocando-a, juntamente com a carta da vez, no topo de
    seu monte, com as faces voltada para cima, e continua a jogada (ou seja, retira outra
    carta da pilha de compras e repete o processo).

  • Se a carta da vez for igual à carta de cima de um monte de um outro jogador, o jogador
    "rouba" esse monte, empilhando-o em seu próprio monte, coloca a carta da vez no topo
    do seu monte, face para cima, e continua a jogada.

  • Se a carta da vez for igual à carta no topo de seu próprio monte, o jogador coloca a carta
    da vez no topo de seu próprio monte, com a face para cima, e continua a jogada.

  • Se a carta da vez for diferente das cartas da área de descarte e das cartas nos topos dos
    montes, o jogador a coloca na área de descarte, face para cima, e a jogada se encerra
    (ou seja, o próximo jogador efetua a sua jogada). Note que esse é o único caso em que o
    jogador não continua a jogada.

O jogo termina quando não há mais cartas na pilha de compras. O jogador que tiver o
maior monte (o monte contendo o maior número de cartas) ganha o jogo. Se houver empate,
todos os jogadores com o monte contendo o maior número de cartas ganham o jogo.

[color=black][size=18]Entrada[/size][/color]

A entrada é composta de vários casos de teste. A primeira linha de um caso de teste contém dois
inteiros N e J, representando respectivamente o número de cartas no baralho (2 <= N <= 10.000)
é o número de jogadores (2 <= J <= 20 e J <= N). As cartas do baralho são representadas por
números inteiros de 1 a 13 e os jogadores são identificados por inteiros de 1 a J. O primeiro
jogador a jogar é o de número 1, seguido no jogador de número 2, . . ., seguido pelo jogador
de número J, seguido pelo jogador de número 1, seguido do jogador de número 2, e assim
por diante enquanto houver cartas na pilha de compras. A segunda linha de um caso de teste
contém N inteiros entre 1 e 13, separados por um espaço em branco, representando as cartas
na pilha de compras. As cartas são retiradas da pilha de compras na ordem em que aparecem
na entrada. O final da entrada é indicado por uma linha com N = J = 0.
A entrada deve ser lida da entrada padrão.

[color=black][size=18]Saida[/size][/color]

Para cada caso de teste seu programa deve imprimir uma linha, contendo o número de cartas
do monte do jogador ou jogadores que ganharam a partida, seguido de um espaço em branco,
seguido do(s) identificador(es) dos jogadores que ganharam a partida. Se há mais de um jogador
vencedor imprima os identificadores dos jogadores em ordem crescente, separados por um espa¸co
em branco.

[color=black][size=18]A saída deve ser escrita na saída padrão.[/size][/color]

Exemplo de entrada
4 2
10 7 2 5
6 3
1 2 1 2 1 2
8 2
3 3 1 1 2 3 4 5
0 0

Saída para o exemplo de entrada
0 1 2
5 1
3 2

O treinamento foi nos dado pelos [size=24][color=black]GRANDES[/color] [/size] mestres:

Ciro Cirne Trindade
Emmanuel K. Illunga

[]'s

Os problemas são estilo os do TopCoder então?

Marky,

Não conheço os problemas do TopCoder, mas na página da competição tem as provas dos anos anteriores para você comparar.

A forma de ler as entradas é diferente do TopCoder, mas os problemas são dentro dos moldes. Tanto do TopCoder como do Google Code Jam e da OBI.

[quote=alankelon][quote=juliocbq][quote=Loiane]Para a maratona, aconselho altamente usar C ou C++.
Java só para usar para problemas com BigDecimal, BigNumber, etc.
Na maratona, Java perde muito em relação à performance e memória, por conta da orientação a objetos. E nesse tipo de contest, vai ser muuuuito raro precisar usar uma instância de uma classe criada. Programação “procedural” dá conta do recado numa boa.

Já teve caso de quando participei fazer o programa em java, não passar (resposta errada), aí tentamos em C (o mesmo algoritmo) e passou.
Bem, em todo caso, não custa ir sabendo C/C++. Se não der certo com um, tenta com outro! :slight_smile: [/quote]

A questão dos números de grande precisão podem ser resolvidos como o Andre falou (long long).

[/quote]

Tenta resolver estes dois problemas com long long :wink:

É trivial e você ainda pode levar rotinas normalmente utilizadas por escrito.
[/quote]

Se não puder resolver um problema com long long pode-se alocar memória com malloc e criar um outro tipo. Isso não é nenhum problema.

Levar rotinas predefinidas? Isso não deixa mais trabalhoso de se usar c?

[quote=alankelon]De 2008 pra cá, posso afirmar que o tempo é o mesmo para todas as linguagens de programação. Muito provavelmente, sempre foi assim. [/quote] Antes do jit java ficava 5x ou mais vezes atraz de um assembly nativo. Hoje pode rodar até mais rápido que um programa c graças ao LLVM.
http://llvm.org/

Não tem como comparar java com c, é uma coisa completamente diferente, é uma plataforma diferente. Por mais que você se esforce, não tem como você otimizar seu código mais que o jit facilmente. Podemos até fazer uma brincadeira aqui para testar…

O seguinte software é a implementação do fibonacci. Refiz o mesmo algoritmo em c(médio nível) e c++(alto nível). O programa c++ resolve o problema em 520ms, o c resolve em 600 ml, c# resolve em 360 ms e java em 270 ms em uma máquina dual core com 2gb(O tempo de resposta vai variar conforme o processador, mas a vai seguir o mesmo ponto de referência. Se você acha que é justo comparar uma plataforma como java a uma outra como c, pode tentar bater o tempo do java. Se conseguir, observe a dificuldade que teve para otimizar uma coisa que pode ser feita em menos de 1min em java.

[quote=alankelon]Para empolgar mais, recentemente dois ex-maratonistas do Centro de Informática da UFPE foram contratados pela Google, vide http://www2.cin.ufpe.br/site/lerNoticia.php?s=1&c=94&id=349 e http://www2.cin.ufpe.br/site/lerNoticia.php?s=1&c=94&id=352

C, C++ e Java.

Sim, porque todos os times possuem acesso às mesmas linguagens e APIs. Cabe a cada time escolher qual a linguagem utilizará no momento da submissão de cada problema, podendo alterar a linguagem a cada nova submissão se achar necessário.

É permitido levar quaisquer materiais impressos, por exemplo, livros, apostilas e trechos de códigos, porém não podem acessar Internet nem levar material magnético (pen drive e CD-ROM). Todo time que se preze possui um bom notebook (cadernos com rotinas prontas). Geralmente, utiliza-se C ou C++ por questão de cultura (da mesma forma que desenvolvedor ágil deveria utilizar Ruby e R. on Rails) e comodidade porque já há muito material escrito nestas linguagens.

A linguagem de programação termina sendo é irrelevante para os tipos de problema da maratona. A solução de um problema com um algoritmo ruim não será aceito, nem que o sujeito escreva o código em Assembly.

É a mesma: compara-se a saída gerada pela solução submetida com a solução esperada. Se as respostas forem iguais, a solução é aceita, senão rejeitada. [/quote]

  1. Se somente as saídas forem comparadas, a competição se torna muito injusta por questões de sintaxe das linguagems.

  2. Eu entendi que todos podem usar as mesmas linguagem. Mas porque alguém escolheria c ao invés de java? Estou tentando imaginar uma boa razão para alguém usar c numa competição que só verifica as saídas e o tempo de execução do programa(A não ser que o tempo de execução seja medido em unidades, e não em ciclos de um processador).

[quote=juliocbq]Se não puder resolver um problema com long long pode-se alocar memória com malloc e criar um outro tipo. Isso não é nenhum problema.

Levar rotinas predefinidas? Isso não deixa mais trabalhoso de se usar c?

[/quote]
Levar rotinas predefinidas é levar algoritmos já escritos em papel. Vide aqui alguns pdfs interessantes: http://maratona.viniciusfortuna.com/Notebooks

E sobre os números… Com malloc acho que ainda não resolve. Existe um algoritmo que, pra variar, não consigo me lembrar o nome, onde você pega um número muito grande e soma com outro tão grande quanto. Não só operação de soma, mas subtração, multiplicação e divisão também. Senão me engano o algoritmo consiste em pegar de 4 em 4 dígitos e ir fazendo operações nestes, ao invés de no número como um todo. No que eu ache o algoritmo volto a postar aqui (a memória tá fraca).

Julio, não verifica só as saídas. Se estourar o tempo limite ou memória, já é motivo de erro. Se for pra mostrar só a saída não tem graça :stuck_out_tongue:

[quote=Andre Brito][quote=juliocbq]Se não puder resolver um problema com long long pode-se alocar memória com malloc e criar um outro tipo. Isso não é nenhum problema.

Levar rotinas predefinidas? Isso não deixa mais trabalhoso de se usar c?

[/quote]
Levar rotinas predefinidas é levar algoritmos já escritos em papel. Vide aqui alguns pdfs interessantes: http://maratona.viniciusfortuna.com/Notebooks

E sobre os números… Com malloc acho que ainda não resolve. Existe um algoritmo que, pra variar, não consigo me lembrar o nome, onde você pega um número muito grande e soma com outro tão grande quanto. Não só operação de soma, mas subtração, multiplicação e divisão também. Senão me engano o algoritmo consiste em pegar de 4 em 4 dígitos e ir fazendo operações nestes, ao invés de no número como um todo. No que eu ache o algoritmo volto a postar aqui (a memória tá fraca).

Julio, não verifica só as saídas. Se estourar o tempo limite ou memória, já é motivo de erro. Se for pra mostrar só a saída não tem graça :p[/quote]

ahh sim, aí é outra coisa. Senão quem usa java tem muita vantagem.

Pois é. O Petr, primeiro colocado do TopCoder e GCJ (algumas vezes), usava Pascal quando participava de Maratonas da ACM. Numa entrevista, ele fala que a única coisa que ele sente pesar é de não ter Pascal no TopCoder. Quando perguntado porque usava Java, a resposta foi muito legal:

Pois é. O Petr, primeiro colocado do TopCoder e GCJ (algumas vezes), usava Pascal quando participava de Maratonas da ACM. Numa entrevista, ele fala que a única coisa que ele sente pesar é de não ter Pascal no TopCoder. Quando perguntado porque usava Java, a resposta foi muito legal:

com certeza… Se não houver critérios diferentes na análise o competidor vai ter que ser muito bom em c para ganhar de um que não possui tantos conhecimentos em algoritmos.
Java facilita muito.

Repito: a linguagem de programação é completamente irrelevante para os problemas da Maratona de Programação.

juliocbq, saia do campo das suposições, submeta o programa que você programa que você escreveu, veja o resultado e depois volte aqui para comentar.

[quote=alankelon]Repito: a linguagem de programação é completamente irrelevante para os problemas da Maratona de Programação.

juliocbq, saia do campo das suposições, submeta o programa que você programa que você escreveu, veja o resultado e depois volte aqui para comentar.[/quote]

Não é nenhuma suposição não, é um fato. O programa foi postado lá no alto para qualquer pessoa analizar. É um simples fibonacci.
Se você conseguir otimizar o mesmo algoritmo em uma linguagem diferente(c, c++ …) sem alguma dificuldade poste para nós. Aliás vou aprender muito com isso.

Insisto que você resolva os problemas sugeridos para entender que sua fala não faz sentido no contexto da Maratona de Programação.

Outro problema que mostra que o mais importante é o algoritmo e não a linguagem de programação é http://br.spoj.pl/problems/PRIME1

Divirta-se.

[quote=juliocbq][quote=alankelon]Repito: a linguagem de programação é completamente irrelevante para os problemas da Maratona de Programação.

juliocbq, saia do campo das suposições, submeta o programa que você programa que você escreveu, veja o resultado e depois volte aqui para comentar.[/quote]

Não é nenhuma suposição não, é um fato. O programa foi postado lá no alto para qualquer pessoa analizar. É um simples fibonacci.
Se você conseguir otimizar o mesmo algoritmo em uma linguagem diferente(c, c++ …) sem alguma dificuldade poste para nós. Aliás vou aprender muito com isso.[/quote]

Simples: reescreva a função fibonacci de forma iterativa e use memoization.

[quote=alankelon][quote=juliocbq][quote=alankelon]Repito: a linguagem de programação é completamente irrelevante para os problemas da Maratona de Programação.

juliocbq, saia do campo das suposições, submeta o programa que você programa que você escreveu, veja o resultado e depois volte aqui para comentar.[/quote]

Não é nenhuma suposição não, é um fato. O programa foi postado lá no alto para qualquer pessoa analizar. É um simples fibonacci.
Se você conseguir otimizar o mesmo algoritmo em uma linguagem diferente(c, c++ …) sem alguma dificuldade poste para nós. Aliás vou aprender muito com isso.[/quote]

Simples: reescreva a função fibonacci de forma iterativa e use memoization. [/quote]

Tá bom, então faça lá e compare seu resultado com o do jit. Poste para nós vermos. Como é simples para você, não vai ter nenhum trabalho além poder colaborar e ajudar o guj a entender o problema proposto.

Eu levei 3 dias para poder compará-lo com a otimização do jit, e pelo visto você já levou um dia falando.

Você não leu o que eu escrevi no post lá em cima ou se fez de mal entendido?

A minha dúvida é: “Qual é a vantagem de usar c ao invés de java?”

O que eu propus foi usar uma linguagem como c ou c++ em um algoritmo como fibobacci e observar como o seu relativo(ou melhor a mesma implementação) em java é muito mais otimizado que nas primeiras linguagens. Isso porque o jit otimiza seu código, e pelo visto você não sabe disso.

A idéia é você implementar o mesmo software em c e ver se você consegue rodar mais rápido que o equivalente java sem sofrer um bocado para otimizá-lo.

Se você pelo menos tentar otimizar para você mesmo e comparar os resultados vai ver como é difícil competir com um otimizador do nível do jit e do LLVM também usados no hotspot.

É isso.

“We should forget about small efficiencies, say about 97% of the time: premature optimization is the root of all evil. Yet we should not pass up our opportunities in that critical 3%. A good programmer will not be lulled into complacency by such reasoning, he will be wise to look carefully at the critical code; but only after that code has been identified” (Donald Knuth)

Você está tentando transferir sua responsabilidade de análise e projeto de algoritmos para a linguagem de programação, enquanto deveria pensar na complexidade do algoritmo. Para entradas pequenas, tudo funcionará.

O importante é abordar o problema da forma correta. As otimizações de compilação e execução de A ou B pouco importam para a Maratona de Programação e, via de regra, para otimização de qualquer sistema computacional.

[quote=alankelon]“We should forget about small efficiencies, say about 97% of the time: premature optimization is the root of all evil. Yet we should not pass up our opportunities in that critical 3%. A good programmer will not be lulled into complacency by such reasoning, he will be wise to look carefully at the critical code; but only after that code has been identified” (Donald Knuth)

Você está tentando transferir sua responsabilidade de análise e projeto de algoritmos para a linguagem de programação, enquanto deveria pensar na complexidade do algoritmo. Para entradas pequenas, tudo funcionará.

O importante é abordar o problema da forma correta. As otimizações de compilação e execução de A ou B pouco importam para a Maratona de Programação e, via de regra, para otimização de qualquer sistema computacional.

[/quote]

Não estou tentando transferir a responsabilidade do algoritmo para a linguagem. Estou te dizendo que java já faz isso automáticamente na plataforma.

A otimização prematura que o Knuth está dizendo é quando um programador implementa o algoritmo já visando otimizá-lo, e isso é prejudicial para ele mesmo porque se torna mais passível a erros.

Mas só me fala uma coisa. O executável final é analizado ou somente o código fonte?