Página 1 de 2

Somar output de uma função

MensagemEnviado: Quinta Fev 02, 2012 4:18 pm
por ruifm
Estava a resolver problemas do PE, mas só consegui alguns copiando o output para o EXCEL e somando (função SUM), o que é por vezes penoso quando o output tem cerca de 1000 parcelas.
Quando falo do out put de uma função é algo do estilo:
Código: Seleccionar Todos
def count(n):
if n<100:
    count(n+1)
    print n
count(0)

Tentei usar a built-in function SUM no python mas ela só funciona para strings e listas. Tentei transformar o output da função numa lista, o que também não funcionou.
Ao que parece:
Código: Seleccionar Todos
type(count())
<Non Type>

alguem tem uma forma de somar o output de uma função sem ser não usar uma função (e.g. usar um while block)?

Ah, mais uma coisa. O python dá-me um Runtime Error cada quando uso recursion um certo número de vezes. Ao que parece esse número de vezes é exactamente 977, ou seja, ele funciona sem erro se fizer recursion 977 vezes, e dá-me Runtime error se eu lhe mandar fazer 978 vezes. (O meu PC não é da idade da Pedra, tenho um Quadcore 2.3, e 2 GB de RAM livres)

Re: Somar output de uma função

MensagemEnviado: Quinta Fev 02, 2012 4:49 pm
por Bruno Oliveira
Depende da forma como montares a chamada recursiva da função e como a interligas com o resto do código!

Mas, se dizes que a função sum pode (e tens toda a razão!) ser usada em listas, então porque não metes o output da tua função numa lista? :roll:

Se quiseres mete aqui a função em causa, pode ser mais fácil ajudar!

Bruno

PS: Qual é o problema do Project Euler?

Re: Somar output de uma função

MensagemEnviado: Quinta Fev 02, 2012 5:00 pm
por ruifm
Bruno Oliveira Escreveu:Depende da forma como montares a chamada recursiva da função e como a interligas com o resto do código!

Mas, se dizes que a função sum pode (e tens toda a razão!) ser usada em listas, então porque não metes o output da tua função numa lista? :roll:

Se quiseres mete aqui a função em causa, pode ser mais fácil ajudar!

Bruno

PS: Qual é o problema do Project Euler?

são os 2 primeiros. Eu já os resolvi, mas queria faze-los sem exportar o output para o EXCEL...
Código: Seleccionar Todos
def count(n):
    if n<=977:
        count(n+1)
        if n%3==0 or n%5==0:
            print n
count(0)
def count2(n):
    if 977<n<=999:
        count2(n+1)
        if n%3==0 or n%5==0:
            print n
count2(978)

aqui eu fiz a mesma função 2 vezes para resolver aquele problema do overflow.
para transformar em string eu tentei fazer str(count(0)) mas não funcionou, quando fiz type(count(0)) continuou a aparecer non type. Que outras formas ha de passar algo para string?

Re: Somar output de uma função

MensagemEnviado: Quinta Fev 02, 2012 5:41 pm
por jap
Hum??? :roll:
Não percebi bem o teu problema. Acho que complicaste aquilo que é muito simples:

Código: Seleccionar Todos

"""
Project Euler
Problem #1
@jap 1 /1 /2012
"""


if __name__=="__main__":

    NMAX = 1000
   
    n = 1
    s = 0

    while n < NMAX:
        if not (n % 3 and n% 5):
            s += n
        n += 1
    print "The sum is",s


BTW, a tua função count não devolve nada, por isso o tipo do objecto devolvido é "None". Também por isso é que não podes transformá-lo numa string!

Ex:

Código: Seleccionar Todos
def count(n):
      print n


é uma função que não devolve qualquer objecto, apenas executa uma acção, neste caso uma "impressão". Daí que, por exemplo,

Código: Seleccionar Todos
type(count(5))


dê como resultado "None"

Já a seguinte função

Código: Seleccionar Todos
def count(n):
     return n

devolve um obecto e o tipo deste objecto é o tipo de n (se n for um inteiro será um inteiro).

Além disso a tua função recursiva "count" não funciona porque está errada, não é problema do limite de recursão do Python! :lol:

Diz-me o que pretendes que a tua função "count" faça que eu ensino a escrever-te essa função. :wink:

Se eu bem percebi, a tua linha algorítmica pretende implementar aquilo que em pitónico se desgina de um objecto gerador (ou iterador)... :D. O python tem formas muito cool de criar geradores...

Re: Somar output de uma função

MensagemEnviado: Quinta Fev 02, 2012 7:16 pm
por ruifm
eu queria que ela fizesse print de todos os multiplos de 3 e 5 até 1000. Funcionava bem ate 977, mas a partir dai da Runtime error.
depois queria que os somasse através da função SUM. Como ela só funciona para strings e int e float, eu tentei fazer concatenate (str()) à função, o que não resultou em nada.
Realmente essa forma é muito mais simples, arranjar uma iteration só para a soma (s += n) e depois fazer print. bem visto :hands:
eu agora ando numa "function fever" porque estou a ler um tutorial que foi recomendado aqui no forum, "Thinking like a Computer Scientist, Learning Python", e eles são muito apologistas das funções, ensinam a fazer tudo com funções, fartam-se de enumerar as suas vantagens, etc... E eu decidi experimentar no PE, só que deparei-me logo com o problema de somar o output :S.
Mas eu não percebi a diferença entre:
Código: Seleccionar Todos
print n

e
Código: Seleccionar Todos
return n

numa função. O "print" imprime o n, e o return devolve o valor de n. Não é a mesma coisa? Só com o return é que o valor de n passa a ser do tipo int?

Re: Somar output de uma função

MensagemEnviado: Quinta Fev 02, 2012 7:27 pm
por jap
Rui,

Sim, pode-se fazer tudo com funções, e isto até é uma boa ideia que levada ao extremo resulta naquilo que se designa de programação funcional (procura aqui no fórum por este nome que encontras vários exemplos).

Então vamos por partes.

Há uma diferença substancial entre

Código: Seleccionar Todos
def f(n):
   print n



e

Código: Seleccionar Todos
def f(n):
   return n


No primeiro caso a função executa uma acção que é a impressão (digamos no ecrã) da representação do objecto de nome n (no caso o objecto com este nome poderá ser um número). Esta função não cria nenhum objecto, apenas executa uma acção.

Já no segundo exemplo, a função cria um objecto que é devolvido para ser usado no programa principal (para aquilo que ti quiseres). Portanto há, de facto, uma grande diferença. No segundo caso há um objecto que foi criado, colocado numa zona de memória, à tua disposição (é só pedir ao gestor do armazém para o ir buscar :lol:). Já no 1º caso, a função não cria e não nos devolve objecto nenhum. Na realidade, não é bem assim.Todas as funções em Python têm de devolver um objecto, pelo que se uma função não devolve um objecto explicitamente com a instrução "return", o python devolve um objecto por defeito, mesmo sem nós pedrimos, que é o objecto nulo (None). Este objecto não aparece quando se executa a função, mas ele está lá. Queres uma prova: Vê o resultado de

Código: Seleccionar Todos
def f(n):
   print n

x = f(5)

print x


O resultado será:

Código: Seleccionar Todos
>>> x = f(5)
5
>>> print x
None
>>>


Percebeste? :roll:

Re: Somar output de uma função

MensagemEnviado: Quinta Fev 02, 2012 7:31 pm
por Bruno Oliveira
Não necessariamente, Rui!

Existe uma distinção bem definida para a diferença entre os statement return e print.

Ao usares o statement return, podes atribuir-lhe um identificador, e guardar na memória o valor retornado, isto é:

Se tiveres uma função que te retorne um valor, podes depois usar esse valor noutra expressão, ao passo que ao usares o statement print não podes fazer isso, visto que o "argumento" que for passado ao statement print, é directamente enviado para o ecrã, e não fica disponível para mais operações!

Costuma-se chamar função, se uma função retornar efectivamente algum valor, ou procedimento, caso se limite a enviá-lo para a saída-padrão, esta distinção pode ser algo tricky no ínicio, mas, é muito importante!

Re: Somar output de uma função

MensagemEnviado: Quinta Fev 02, 2012 7:33 pm
por jap
Ver meu post acima! :lol:

Tecnicamente todas as funções do Python devolvem um objecto. Se não houver uma instrução return no corpo da função, ela devolverá o objecto None! :mock:

Re: Somar output de uma função

MensagemEnviado: Quinta Fev 02, 2012 7:35 pm
por Bruno Oliveira
jap Escreveu:Ver meu post acima! :lol:

Tecnicamente todas as funções do Python devolvem um objecto. Se não houver uma instrução return no corpo da função, ela devolverá o objecto None! :mock:


Upps! :oops:

Nem me apercebi que o prof. já tinha respondido :P

Pois, isto são as minhas más influências do C a falarem mais alto! :lol:

Mas, é excelente o fórum estar finalmente mais animado!! :D E em particular a secção Pitónica! :hands:

Re: Somar output de uma função

MensagemEnviado: Quinta Fev 02, 2012 7:42 pm
por jap
Mais logo vou explicar aqui como se implementa a ideia original do Rui (julgo que percebi o que ele queria fazer! :inocent: ) que é o que tecnicamente se designa por um "gerador" - ele tentou implementá-lo de forma recursiva o que é uma ideia muito...má, em termos práticos! :lol: Mas os geradores pitónicos são a solução para o "problema de memória" que o Rui encontrou. Os geradores são muito giros e poderosos, mas são um tópico relativamente hardcore do python, muito pouco conhecidos mesmo entre os pitonistas.

Stay tuned!

Re: Somar output de uma função

MensagemEnviado: Quinta Fev 02, 2012 7:42 pm
por ruifm
percebi :)
então quando desenvolvemos um programa convém usar os 2? o print para sabermos o que está a acontecer e o return para a funcão "funcionar"?

eu já corrigi o meu codigo, para apenas devolver o resultado:
Código: Seleccionar Todos
def count(n):
    s=0
    while n<1000:
        if n%3==0 or n%5==0:
            s += n
        n += 1
        if n>=1000:
            return s

mas ainda não percebo porque é que eu tinha aquele runtime error, se fizesse a recursão 978 vezes, e não o obtia se o fizesse só 977:
Código: Seleccionar Todos
def crash(n):
    if n<=977:
        crash(n+1)
        if n%3==0 or n%5==0:
            print n

se em vez de 977 pusermos 978: erro... curioso ;)
já agora, no codigo acima, há alguma diferença entre usar if ou while? se a condição tiver sempre a ocorrer, então o if funciona como while, não?
e qual é a diferença entre um iterador do tipo n += 1 e uma recursão function(n+1)?
desculpem pelas duvidas basicas, só que não encontro nada que explique de forma clara a diferença.

Re: Somar output de uma função

MensagemEnviado: Quinta Fev 02, 2012 7:46 pm
por jap
ruifm Escreveu:desculpem pelas duvidas basicas, só que não encontro nada que explique de forma clara a diferença.


Há uma excelente razão para o teu crash, sim! :lol:

Vou explicar mais logo (vê o meu post anterior).

BTW o teu count fica melhor escrito assim:

Código: Seleccionar Todos
def count(n):
    s=0
    while n<1000:
        if n%3==0 or n%5==0:
            s += n
        n += 1
    return s


O if n >= 1000 não está lá a fazer nada... :lol: repara na indentação desta nova versão. Quando acaba o ciclo while, basta fazer return (se ele acabou é porque n >=1000, não é verdade?)

Re: Somar output de uma função

MensagemEnviado: Quinta Fev 02, 2012 7:56 pm
por ruifm
good point :lol:
curiosidade: quanto mais simples/curto/conciso fica o script, mais rapido fica o programa?

Re: Somar output de uma função

MensagemEnviado: Quinta Fev 02, 2012 8:36 pm
por Bruno Oliveira
Acho que isso é um pouco relativo :roll:

Um programa curto, mal escrito, pode demorar mais do que um programa um pouco maior mas mais bem estruturado!!

Aqui, a questão de rapidez de execução do código, está intimamente ligada ao desenvolvimento de um algoritmo eficiente (então no PE ainda mais verdade isto se torna, sobretudo nos problemas mais avançados), mas isso não deve ser algo com que te preocupes para já. Conhecer bem as estruturas de dados de uma linguagem e o estilo de programação dessa mesma linguagem, é algo muito importante para poder escrever bom código (juntamente com uma grande capacidade de análise matemática, no caso do PE), mas tem de se começar por algum lado :wink:

Eu próprio estou curioso em aprender sobre geradores, nunca me debruçei como deve de ser sobre eles, mas sei que são memory usage friendly :P

Re: Somar output de uma função

MensagemEnviado: Quinta Fev 02, 2012 8:48 pm
por Tharis
A razão do teu crash tem a ver com o abuso de memória. O Prof. jap depois deve explicar melhor, por isso digo-te apenas que a tua recursão gigante vai alocando memória da stack. Como esta é relativamente pequena, chegas a um momento que já não tens mais livre e ocorre um stack overflow.