Página 1 de 1

Números Trimórficos

MensagemEnviado: Terça Dez 01, 2009 7:14 pm
por Bruno Oliveira
OK, este problema poderá ser um pouco redundante, até porque o prof. já colocou aqui um sobre números automórficos, que foi, inclusivé, o meu primeiro problema, pitónico :P , e, depois de revisitar esse mesmo problema e com umas consultas na wikipedia, descobri os números trimórficos :lol: .

NOTA: Este problema é mesmo muito fácil, e tem como único objectivo, incentivar mais alguns quarkianos a descobrirem o Python e a animar um pouco, em termos de problemas, a secção Pitónica aqui do fórum.

Problema:

Um número n é dito trimórfico, se a representação decimal de n^3, terminar no número n. Exemplos triviais destes números são os números de um só digito, nomeadamente, 1, 4, 5, 6, 9, dado que:
1^3 = 1
4^3 = 64
5^3 = 125
6^3 = 216
9^3 = 729.

O objectivo é calcular a soma de todos os números trimórficos de 5 dígitos. :)

PS: À boa moda dos programadores, e para os newbies que ainda não saibam, aconselho a subdividirem o problema em alíneas, isto é, escrevam um pedaço de código para gerar os números trimórficos, depois um pedaço de código (ou melhoramento do anterior) que vos dá apenas os números trimórficos de 5 dígitos, e por fim, é só somá-los. :wink:
Para quem não sabe, esta técnica de programação é designada de scaffolding, e é muito útil :D

Re: Números Trimórficos

MensagemEnviado: Terça Dez 01, 2009 10:48 pm
por jap
Boa! :hands:

Fico à espera dos vossos códigos! :wink:

Re: Números Trimórficos

MensagemEnviado: Quarta Dez 02, 2009 3:32 pm
por Tharis
Código: Seleccionar Todos
>>> sum( filter( lambda n: str(n**3).endswith(str(n)), range(10**4, 10**5)))
681248
>>> sum( [i for i in range(10**4, 10**5) if str(i**3).endswith(str(i))] )
681248


Serve? :)

Re: Números Trimórficos

MensagemEnviado: Quarta Dez 02, 2009 3:39 pm
por Bruno Oliveira
Eh eh,

Claro que sim! :D

Até porque tu sabes bem mais que eu, em termos de programação, e eu, para ser sincero, acho que serei sempre aquele programmer "old-school" que apenas recorre a if`s, funções, ciclos for, uso de files e claro faz uso das peculiaridades do Python, nomeadamente as ferramentas para tratamento de string`s que para mim são simplesmente AWESOME! :P

E, pelo que disse acima, e por não estar (ainda!) dentro da programação funcional, aqui vai o código que eu tinha feito para este simples problema:

Código: Seleccionar Todos
"""
Trimorphic Numbers:
Program that computes the sum of the trimorphic numbers with 5 digits.

@Bruno Oliveira 2009 Having a great time with Python :)

Always trying to improve and write truly Pythonic code :)

To be used by quarkonia.

"""


def trimorphic(n):
    if str(n**3).endswith(`n`):
        return n
    else:
        return 0


nmax=100000
L=[]
for k in range(1,nmax):
    if trimorphic(k)!=0 and len(str(k))==5:
        L.append(k)
print "Searching for trimorphic numbers with 5 digits..."
print "Found", len(L), "trimorphic numbers with 5 digits. They are:", L, "and their sum is:",sum(L)


Output:
Código: Seleccionar Todos
IDLE 2.6.4      ==== No Subprocess ====
>>>
Searching for trimorphic numbers with 5 digits...
Found 11 trimorphic numbers with 5 digits. They are: [18751, 31249, 40625, 49999, 50001, 59375, 68751, 81249, 90624, 90625, 99999] and their sum is: 681248
>>>


Não estará tão pitónico como o teu, Tharis, mas está bem melhor do que o meu código antigo para os automórficos! :lol:

Re: Números Trimórficos

MensagemEnviado: Quarta Dez 02, 2009 4:51 pm
por Tharis
O teu código está normal para um programa estruturado seguindo o paradigma imperativo.

Continuando, aí só tens uma coisinha menos bem que é começares a pesquisa em 1. ;)

Vou explicar o meu código:

Código: Seleccionar Todos
lambda n: str(n**3).endswith(str(n))


Uma função lambda que me diz se o número é trimórfico... Basicamente é equivalente a:

Código: Seleccionar Todos
def is_trimorphic(n):
    if str(n**3).endswith( str(n) ):
        return True
    else:
        return False



Código: Seleccionar Todos
range(10**4, 10**5)

Todos os números de 5 dígitos.


Depois entra o funcional. A função filter recebe um dois argumentos: uma função (esta função deve retornar True ou False) e um objecto iterável (lista, tupla, wtv). A função filter vai aplicar a função passada no 1º argumento a cada elemento do 2º argumento e cria uma nova lista com todos os elementos do 2º argumento para qual a função passada retorne True. (Como o próprio nome indica a função filter filtra o conteúdo).

E depois a função sum que dá a soma de todos os elementos de um iterável.


Na segunda uso listas por compreensão. É a mesma coisa só que escrito de outra maneira.

Re: Números Trimórficos

MensagemEnviado: Quarta Dez 02, 2009 4:56 pm
por Bruno Oliveira
Obrigado pela rápida resposta, Tharis.

Em relação ao facto de eu ter começado o ciclo for em 1, eu fi-lo de proposito, para poder incluir a função len(str(k))==5, embora dê mais trabalho ao computador... Por outro lado, se tivesse inicializado o ciclo em 10000 e terminado em 99999 ou neste caso 100000, não precisava sequer de incluir a função len... Foi piquinhice (omg, isto escreve-se assim?) minha! :P

Re: Números Trimórficos

MensagemEnviado: Quarta Dez 02, 2009 8:55 pm
por Bruno Oliveira
Já agora, posso também deixar aqui uma explicação detalhada do meu código para que os newbies não se assustem e, aliás, se divirtam a pegar no Python! :lol: Just like I did back in the day! :wink:

Código: Seleccionar Todos
"""
Trimorphic Numbers:
Program that computes the sum of the trimorphic numbers with 5 digits.

@Bruno Oliveira 2009 Having a great time with Python :)

Always trying to improve and write truly Pythonic code :)

To be used by quarkonia.

"""


Esta primeira parte do código, chama-se uma doc string. É aconselhável escrever uma doc string no ínicio de um programa (pitónico ou qualquer outro), já que esta serve como uma indicação do que irá fazer o programa. Uma espécie de resumo, se assim o quiserem entender. Como já disse o prof. jap, esta doc string é uma ferramenta de metaprogramação, que pode ser invocada a partir do próprio programa, que é algo, ao que consta, bastante útil, embora eu não saiba propriamente as implicações práticas disto... :roll:

Código: Seleccionar Todos
def trimorphic(n):
    if str(n**3).endswith(`n`):
        return n
    else:
        return 0


Este pedaço de código, é talvez o mais pitónico de todos! :lol:

Nele, está-se a definir uma função, (a sintaxe para criarmos uma função definida por nós é: def nome_da_funcao(args): ) onde def é a keyword para indicarmos que vamos definir uma função, nome_da_funcao é o nome da função, que neste caso se chama trimorphic, e (args) são os argumentos que a função recebe (podem ser um, vários ou até nenhum :shock: ).

A segunda linha deste bloco de código e simultaneamente a primeira linha da função propriamente dita, faz uso das potentes ferramentas para tratamento de strings do Python e creio que é bastante auto-explicativa. (Pode-se praticamente ler em português: Se o número n^3 terminar em n...) Esta função retorna o número n que nós estamos à procura se a condição se verificar, caso contrário, retorna o valor 0.

Código: Seleccionar Todos
nmax=100000
L=[]
for k in range(1,nmax):
    if trimorphic(k)!=0 and len(str(k))==5:
        L.append(k)
print "Searching for trimorphic numbers with 5 digits..."
print "Found", len(L), "trimorphic numbers with 5 digits. They are:", L, "and their sum is:",sum(L)


Este código, tem como principal finalidade somar os números automórficos de 5 dígitos, usando para o efeito um ciclo for.
O ciclo for, em Python, tem a sintaxe apresentada na terceira linha deste bloco de código e tem a finalidade de repetir uma dada tarefa nmax-1 vezes. Neste caso, vai avaliar o retorno da função trimorphic, e caso este seja diferente de 0 (!=0) e o número tenha 5 dígitos (len(str(k))==5) vai acrescentá-lo á lista L. (L.append(k)).

Notem que a instrução antes do ciclo for (L=[]) cria uma lista vazia, chamada L, à qual vamos adicionando elementos se as condições que impusemos se verifiquem :) .

Por fim, os print, não têm nada de transcendente, servem apenas para enviar mensagens como output. Basta apenas saberem que: len(L) nos dá o numero de elementos na lista, no final do ciclo for e que sum(L), tal como pretendido, soma todos os elementos da lista. :D

Espero que tenha ficado claro, e assim têm 2 abordagens distintas (imperativa, a minha e funcional, a do Tharis).

Re: Números Trimórficos

MensagemEnviado: Quarta Dez 02, 2009 8:58 pm
por Ivo_Timóteo
A eficiência é sempre algo a ter em conta quando estás a programar...

Principalmente quando as coisas começam a "crescer" de tamanho :)

Re: Números Trimórficos

MensagemEnviado: Quarta Dez 02, 2009 11:05 pm
por jap
A propósito os one-liners (como os programas do Tharis) não são considerados pelo BDFL lá como muito pitónicos, uma vez que uma das máximas do ZEN do Python é "Explicit is better than implicit".

One-liners são mais LISPónicos do que Pitónicos, mas são sempre um desafio interessante... Como escrever um programa numa só linha +- críptica, mas sem "side effects"? :P

Re: Números Trimórficos

MensagemEnviado: Quarta Dez 02, 2009 11:29 pm
por Bruno Oliveira
Se a pessoa começar a perder a sanidade mental, ou neste caso, o objectivo dos códigos pitónicos(que começo a apreender), bastam 2 simples palavrinhas no IDLE, para recuperar a orientação:

Código: Seleccionar Todos
>>> import this


:P