Este Ricbit Jam convergiu bem rápido, logo nos primeiros dias várias pessoas mandaram a melhor resposta. Pelo critério de desempate, ganha quem mandou primeiro. Por uma vantagem de apenas dez minutos, o vencedor foi o Henrique Pereira (@ikkebr), parabéns!
Algumas pessoas mandaram respostas implementando o Quicksort com ZenoReduce, mas esse algoritmo não é bom na máquina de Zeno. As pessoas que conseguiram chegar no O(1) mandaram variações do Bubblesort e do Insertsort. A solução vencedora, com 76 bytes, foi a abaixo:
import zeno;zenosort=lambda x:zeno.zenoreduce(lambda r,e:sorted(r+[e]),x,[])
Não é óbvio que essa solução é O(1), afinal, ela usa o sorted() do python, que sabemos ser O(n log n). O truque é essa complexidade acaba sendo mascarada. A cada iteração ele adiciona um elemento usando o O(n log n), mas o n começa pequeno, e vai crescendo amortizado pela máquina de Zeno. No final, o tempo utilizado pelo algoritmo é o abaixo, para uma lista de tamanho n:
Uma condição suficiente para que o algoritmo seja O(1) é que essa série seja convergente. Para verificar a convergência, podemos usar o teste das razões, ou seja, o limite do módulo da razão de dois termos consecutivos tem que ser menor que um.
Como todo mundo é positivo, dá pra tirar o módulo. Também podemos jogar um 2 para fora, e a base do logaritmo cancela:
Esse limite é indeterminado da forma infinito/infinito, então dá pra usar o teorema de L'Hospital, ou seja, o limite da razão é igual ao limite da razão das derivadas:
Opa, esse limite também é da forma infinito/infinito, então dá pra usar o L'Hospital de novo:
Concluímos que o limite vale meio, logo ele é menor que um, portanto a série é convergente, e por isso o algoritmo é O(1), QED.
O objetivo deste Ricbit Jam é escrever a melhor função de ordenação de listas usando ZenoReduce.
Esse é um exemplo de solução válida:
Solução válida para o Ricbit Jam #2
As soluções serão rodadas da seguinte maneira:
>>> import zeno >>> import zenosort >>> zeno.run(lambda:zenosort.zenosort([3,1,4,-2])) ([-2, 1, 3, 4], 0.0, 0.0)
O placar abaixo será atualizado diariamente, conforme as soluções chegarem:
Posição | Nome | Complexidade | Tamanho |
1 | Henr"Ikke" Pereira | O(1) | 76 |
2 | girino | O(1) | 76 |
3 | Renato Cunha | O(1) | 76 |
4 | Leonardo Fischer | O(1) | 150 |
5 | Ricardo Bittencourt | O(N log N) | 95 |
6 | Not RMS | O(N log N) | 312 |
7 | Raoni Florentino da Silva Teixeira | O(N log N) | 382 |