Ajuda - exercicio de algoritmos

Isso é assim em todas as linguagens, pode existir mais ou menos estruturação, mais ou menos tipificação. Independentemente disso, vais fazer SEMPRE como alguém entendeu ser melhor, porque estás a usar uma linguagem que alguém criou. Se quiseres ir até ao nível mais baixo com 0's e 1's, até nisso, é o fabricante do processador que define que operações tens ou não disponíveis e como funcionam.

Convém no entanto referir, que aquilo a que chamas "simplicidade" tem o seu preço. Numa linguagem estruturada e tipificada existe maior controlo, o próprio compilador pode ajudar. Quando te dão "liberdade" essa análise não fica tão simples, sendo mais susceptível à ocorrência de erros. Porque em programas assim é fácil ir vendo, agora quando se fala em grande dimensão o caso muda de figura...

A meu ver, o importante é saber em que casos uma ou outra linguagem é melhor. Se ambas existem é porque têm pontos a favor e pontos contra. Acho que fazes estas afirmações porque deves desconhecer em mais pormenor outras linguagens (mas claro que posso estar enganado :p).
 
A tua maneira de resolver o problema é uma de N e não é necessariamente a melhor.
OK, aceito o desafio ;-)
Este script imprime os números Armstrong para as potências 1 a 7 e mostra o tempo necessário para efectuar os cálculos segundo os dois métodos: 1) pelos restos, como foi aqui sugerido, e 2) pelos digitos, como eu mostrei atrás.

Código:
#!/usr/bin/perl
# ficheiro: ppdi.pl
use strict;
use warnings;
use Time::HiRes qw/gettimeofday tv_interval/;

my $func = {
    1 => { LABEL => q|Pelos restos|,  FUNCAO => \&calc_res },
    2 => { LABEL => q|Pelos digitos|, FUNCAO => \&calc_dig },
};

FUNCAO: foreach my $funcao ( sort { $a <=> $b } keys %$func ) {

    my $t0 = [gettimeofday];
    print qq|\n|, uc( $func->{$funcao}->{LABEL} ), qq|\n|;

  POTENCIA: for my $pot ( 1 .. 7 ) {

        print "p = ", $pot, " : ";
        my $min = sprintf( "%.0f", ( 10**$pot - 1 ) / 10 ) - 1;
        my $max = 10**$pot - 1;
        my $t1  = [gettimeofday];

      NUMERO: for my $num ( $min .. $max ) {
            next NUMERO unless length($num) == length($max);
            print $num, " " if $func->{$funcao}->{FUNCAO}->($num);
        }

        print q| (|, sprintf( "%.3f", tv_interval( $t1, [gettimeofday] ) ),
          qq|)\n|;

    }

    print q|Tempo: |, sprintf( "%.3f", tv_interval( $t0, [gettimeofday] ) ),
      qq|\n|;
}

sub calc_res {

    my $num = shift;
    my @num = split //, $num;

    my $sum = 0;
    $sum += ( substr( $num, 0, length($num) - $_ ) % 10 )**length($num)
      for 0 .. $#num;
    $sum != $num ? return : return 1;

}

sub calc_dig {

    my $num = shift;

    my $sum = 0;
    $sum += $_**length($num) for split //, $num;
    $sum != $num ? return : return 1;

}

Output:
Código:
[me@mybox] ~/Perl: perl ppdi.pl

PELOS RESTOS
p = 1 : 0 1 2 3 4 5 6 7 8 9  (0.000)
p = 2 :  (0.001)
p = 3 : 153 370 371 407  (0.017)
p = 4 : 1634 8208 9474  (0.130)
p = 5 : 54748 92727 93084  (1.442)
p = 6 : 548834  (21.795)
p = 7 : 1741725 4210818 9800817 9926315  (196.532)
Tempo: 219.918

PELOS DIGITOS
p = 1 : 0 1 2 3 4 5 6 7 8 9  (0.000)
p = 2 :  (0.001)
p = 3 : 153 370 371 407  (0.006)
p = 4 : 1634 8208 9474  (0.086)
p = 5 : 54748 92727 93084  (0.911)
p = 6 : 548834  (10.544)
p = 7 : 1741725 4210818 9800817 9926315  (116.295)
Tempo: 127.843

Neste caso, a diferença entre os dois métodos é significativa.
Por outro lado, e voltando ao problema inicial (em que se pretende verificar se um dado número é um número de Armstrong) a diferença seria negligenciável.

Acho que fazes estas afirmações porque deves desconhecer em mais pormenor outras linguagens (mas claro que posso estar enganado ).
Não vás por aí ;-) Estamos a trocar ideias sobre algoritmos (e linguagens de programação) não sobre o que cada um conhece ou deixa de conhecer.
 
Última edição:
Quer dizer que é uma linguagem que te impõem um determinado paradigma de programação. Quando um paradigma é imposto tendemos a equacionar os problemas à luz dos constrangimentos desse mesmo paradigma: o programador perde liberdade para analisar e resolver problemas fora dos limites desse paradigma.

Pensei que isso já fosse claro pelos exemplos: Perl.

Mas claro que te impõem, o paradigma orientado a objectos. Então todas as outras linguagens orientadas a objectos (C++, C#, etc) também detestas?
Não estou a dizer que todos problemas se resolvem com Java, cada problema deve ser resolvido da melhor forma e o programador é que tem de ver o que melhor se aplica.

Eu trabalho em base de dados Oracle, e longe de mim dizer que o tratamento de dados que faço usando PL/SQL seria melhor feito ou mais rápido usando Java, ou outra linguagem qualquer, e eu adoro Java! Cada ferramenta para a sua função.

Se gostas de Perl, deves ser sysadmin ou algo do género, não?
 
Não vás por aí ;-) Estamos a trocar ideias sobre algoritmos (e linguagens de programação) não sobre o que cada um conhece ou deixa de conhecer.

Se estamos a trocar ideias, seja sobre algoritmos, seja sobre linguagens de programação, aquilo que conhecemos influencia aquilo que dizemos. Portanto, é importante saber se falas com conhecimento de causa, ou apenas à luz daquilo que consideras ser ou não verdade.

Quanto ao facto de usar os caracteres em vez dos restos, se reparares já tinha colocado isso como uma optimização porque há uma enorme diferença. Menor diferença é o facto de guardares o resultado dos cubos para não estares sempre a recalcular.

Em C++ podias fazer assim:
Código:
#include <iostream>
#include <string>

using namespace std;

int cubos[10] = { 0, 1, 4, 9, 16, 25, 36, 49, 64, 81 };

int main() {
	string numero;
	int res = 0, num = 0;
	
	cin >> numero;
	
	for( int i = 0; i < (int)numero.size(); ++i ) {
		res += cubos[ ( numero[i] & 0x0F ) ];
		num = num*10 + ( numero[i] & 0x0F );
	}
		
	if( res != num )
		cout << "Não é Armstrong: " << res << " != " << num << endl;
	else
		cout << "Armstrong" << endl;
}
 
Última edição:
Just getting fun:
Código:
[me@mybox:~ ] echo 1122763285329372541592822900204593 | perl -F -lane '$s+=$_**~~@F for@F;print" "x4 ."ARMSTRONG"^($s!=$_?"not":"_"x4)'
ARMSTRONG

[me@mybox:~ ] echo 11 | perl -F -lane '$s+=$_**~~@F for@F;print" "x4 ."ARMSTRONG"^($s!=$_?"not":"_"x4)'
NOT ARMSTRONG
 
[FONT=&quot]Exercício 1[/FONT]

[FONT=&quot]Elabore um algoritmo e descreva-o em pseudo-código que verifica se um dado número é número de Amstrong.[/FONT]
[FONT=&quot]Um número é de Amstrong se a soma dos cubos dos seus dígitos é igual ao próprio número.[/FONT]

[FONT=&quot]ED:[/FONT]
[FONT=&quot]soma, x, n, aux INTEIRO[/FONT]

[FONT=&quot]INICIO[/FONT]
[FONT=&quot] REPETIR [/FONT]
[FONT=&quot] LER (n)[/FONT]
[FONT=&quot] ENQUANTO (n<0)[/FONT]
[FONT=&quot] aux[/FONT]ß[FONT=&quot]n[/FONT]
[FONT=&quot]soma[/FONT]ß[FONT=&quot]0[/FONT]
[FONT=&quot] ENQUANTO (n/10≠0) FAZER[/FONT]
[FONT=&quot] X[/FONT]ß[FONT=&quot]N%10[/FONT]
[FONT=&quot] soma[/FONT]ß[FONT=&quot]soma+x^3[/FONT]
[FONT=&quot]N[/FONT]ß[FONT=&quot]n/10[/FONT]
[FONT=&quot]FIMENQUANTO[/FONT]
[FONT=&quot]SE (soma = aux) ENTAO[/FONT]
[FONT=&quot] ESCREVER (aux,” é número de Amstrong”)[/FONT]
[FONT=&quot] SENAO[/FONT]
[FONT=&quot] ESCREVER (aux,” não é número de Amstrong”)[/FONT]
[FONT=&quot]FIM


[/FONT]ß = atribuiçao
 
Já agora..

Claro que não é a mais eficiente, mas isto sim é uma solução bonita..

Código:
#include <stdio.h>

int arm(int n) {
  return n?(n%10)*(n%10)*(n%10)+arm(n/10):0;
}

int main() {
  int n;
  scanf("%d",&n);
  printf("%s\n",(arm(n)==n)?"Armstrong":"Nop");
  return 0;
}
 
Já agora, pq não lisp :D

Código:
(defun armstrong? (arg)
	(defun calc-armstrong (arg)
		(if (= arg 0)
			0
			(+ (exp (rem arg 10) 3) (calc-armstrong (truncate arg 10)))))
	(= arg (calc-armstrong arg)))
 
Vocês estão a esquecer-se de um pormaior: um número Armstrong é um número que, numa dada base, é igual ao somatário dos seus digitos elevado ao número de digitos. Ou seja, se o número tiver 3 digitos, o expoente é 3; se tiver 30 digitos o expoente é 30. Por outras palavras, o expoente é o comprimento da string.
 
O que é que isto faz ? :banjump:

Sendo numero uma variável do tipo string para armazenar um número, suponho que numero será um caracter representativo de um número, logo o seu código ASCII vai variar entre 48 ('0') e 57 ('9'). A operação & realiza um AND bit a bit entre o valor ASCII de numero e 0x0F. Imagina que numero tinha o caracter '3' (ASCII=51=00110011), e sabendo que 0x0F = 00001111, essa operação vai fazer:
Código:
     00110011
     00001111
_____________
&    00000011
Ou seja, vais obter o valor 00000011=3 (que é um inteiro).
Basicamente, faz a conversão do caracter armazenado em numero (neste caso, o caracter '3'), no respectivo inteiro (3).
 
Eu estou habituado a programar em java, onde existem funções para converter tipos de dados. Não existem em c++ ? só há esta forma ?

Obrigado :rolleyes:

Consulta a tabela ASCII.

Para passares um char para int, basta retirar ao char o valor ASCII do caracter '0':

Código:
#include <stdio.h>

int main() {
    char c = '3';
    int num;
    num = c - '0';
    printf("%d",num);
    return 0;
}

[COLOR=Red] Output: 3[/COLOR]
 
Back
Topo