Numeri di Smith

« Older   Newer »
 
  Share  
.
  1. Ace.
     
    .

    User deleted


    Dato un numero intero positivo se la somma delle relative cifre è uguale alla somma delle cifre nella relativa fattorizzazione allora il numero è un numero di Smith.
    Un esempio di numero di smith è il 4 infatti 4 è scomponibile in 2x2 e la somma delle cifre dei fattori è uguale alla somma delle cifre di 4, anche 202 soddisfa la condizione infatti 101x2 =202. un altro esempio 27=3x3x3 e così via.
    Ecco il link di wikipedia link.
    Potete svolgerlo come volete:
    -stampare a video i primi n numeri della serie
    -dato un numero intero in input, stabilire se è un numero di Smith.
    Un'altra cosa: i numeri primi sono esclusi dall'insieme dei numeri di Smith, poiché è evidente che tutti soddisfano banalmente la condizione richiesta.
    SPOILER (click to view)
    Io ho già fatto il programma che stampa a video i primi 30 numeri della serie, ma aspetto a postarlo per non condizionare le vostre soluzioni. Se volete però posso postarlo se vi può aiutare ;)

     
    Top
    .
  2. x-reynik-x
     
    .

    User deleted


    bello questo esercizio!
     
    Top
    .
  3.  
    .
    Avatar

    Senior Member

    Group
    Staff
    Posts
    10,796

    Status
    Anonymous
    Sembrano carini, appena ritaglio un pò di tempo me li guardo! ;)
     
    Top
    .
  4. Ace.
     
    .

    User deleted


    CITAZIONE (x-reynik-x @ 27/11/2009, 16:40)
    bello questo esercizio!

    CITAZIONE (RootkitNeo @ 28/11/2009, 18:18)
    Sembrano carini, appena ritaglio un pò di tempo me li guardo! ;)

    Io mi sono divertito a fare questo esercizio, ve lo consiglio :D
     
    Top
    .
  5.  
    .
    Avatar

    Senior Member

    Group
    Staff
    Posts
    10,796

    Status
    Anonymous
    Ho ritrovato il post, così lo riuppo.

    ..e posto la mia soluzione in Java. Al momento controlla solamente se il numero è di Smith.

    CODICE
    import java.util.Scanner;

    class SmithNumber implements Runnable {
     private int n;
     private int sumN=0,sumScomp=0;
     Thread t;
     public SmithNumber(int n) {
       this.n = n;
           // Assegno a t un riferimento al thread corrente
           t = new Thread(this);
     }
     // Verifici la primalità
     private boolean isPrime(int m) {
       if(m==2) return true;
           if(m%2==0) return false;
           else {
             for(int i=3; i<(int)Math.sqrt(m); i+=2) {
               if(m%­i==0) return false;
             }
           }
           return true;
     }
     // Effettuo la scomposizione e sommo le cifre ottenute
     private void scomponi() {
       int k=2;
           String Sc = "";
        /*
         * Se k è divisiible per n, k è un suo multiplo
         * qindi controllo se k è un numero primo.
         */
       while(n!=1) {
         if((n%­k==0)&&(isPrime(k)==true)) {
           n/=k;
                   /*
                    * Devo utilizzare una stringa in modo da contare
                    * ogni singola cifra.
                    */
               Sc+=""+k;
           k=2;
         } else {
           k+=1;
         }
           }
           // Conto le cifre
           for(int i=0; i<Sc.length(); i++) {
             sumScomp+=Character.digit(Sc.charAt(i),10);
           }
     }
     // Sommo le cifre del numero
     private void sommaN() {
       String n1 =""+n;
           for(int i=0; i<n1.length(); i++) {
             sumN+=Character.digit(n1.charAt(i),10);
           }
     }
     // Avvio il Thread
     public void run() {
       sommaN();
           scomponi();
     }
     boolean isEqual() {
       if(sumN==sumScomp) return true;
           else return false;
     }
    }
    class NumeriSmith {
     public static void main(String args[]) {
       System.out.println("nInserisci un numero e verifica se e' di Smith:");
       Scanner input = new Scanner(System.in);
       int numero = input.nextInt();        
       SmithNumber sn = new SmithNumber(numero);
           // Avvio il Thread
           sn.t.start();
           try {
             // Attendo la fine del Thread
             sn.t.join();
           } catch(InterruptedException e) {}
           
           System.out.println((sn.isEqual()) ? "n"+numero+" e' un numero di Smith." : "n"+numero+" il numero non e' di Smith.");
     }
    }


    L'efficienza non è il massimo dato che devo ottenere ogni singola cifra chiamando Character.digit(char,int), tuttavia è la prima soluzione che ho pensato. In realtà avevo pensato ad effettuare la somma utilizzando k, ma siccome la somma deve essere su ogni singola cifra avrei dovuto controllare il numero e ottenere anche da esso ogni cifra.. quindi ho preferito così.

    Il Multithreading non è stata una grande idea, dato che per i calcoli che devo effettuare perdo più tempo per lo scambio di contesto che per i calcoli ^^

    Edited by RootkitNeo - 4/2/2010, 17:10
     
    Top
    .
  6. Red Eye
     
    .

    User deleted


    Sempre in java, ma seguendo tanti concetti diversi :D
    CODICE
    import java.util.Scanner;


    public class NumeriSmith {
           
           public static void main(String[] args) {
                   System.out.println("Inserire un numero: ");
                   
                   Scanner input = new Scanner(System.in);
                   
                   int num = input.nextInt();
                   
                   
                   int sommaFattori = sommaFattori(num);
                   
                   int sommaCifre = sommaDeiNumeri(num);
                   
                   System.out.println("nSomma delle cifre dei fattori: "+sommaFattori);
                   
                   System.out.println("Somma delle cifre del numero: "+sommaCifre);
                   
                   System.out.println("Il numero "+num+" "+(sommaFattori==sommaCifre?"è ":"non è ")+"un numero di Smith");
                   
           }
           
           private static int sommaFattori(int num) {
                   if(num == 1){  //altrimenti l'algoritmo restituirebbe 0
                           return 1;
                   }
                   
                   int sommaNum = 0;
                   
                   System.out.print("Fattori: ");
                   
                   //Trucco per evitare di considerare in seguito i numeri pari
                   while (num % 2 == 0) {
                           System.out.print(2+" ");
                           
                           num/=2;
                           sommaNum+=2;
                   }
                   
                   int i = 3;
                   while(num > 1){
                           if(num % i == 0){
                                   System.out.print(i+" ");
                                   sommaNum += sommaDeiNumeri(i);
                                   num/=i;
                           }else{
                                   i+=2;
                           }
                   }
                   System.out.println();
                   return sommaNum;
           }
           
           private static int sommaDeiNumeri(int numero){
                   int somma = 0;
                   
                   while(numero >= 1){
                           somma += numero%10;
                           numero/=10;
                   }
                   
                   return somma;
           }
           
    }


    CITAZIONE
    L'efficienza non è il massimo dato che devo ottenere ogni singola cifra chiamando Character.digit(char,int), tuttavia è la prima soluzione che ho pensato.

    Non avevo nemmeno pensato a convertirli in stringhe xD

    CITAZIONE
    In realtà avevo pensato ad effettuare la somma utilizzando k, ma siccome la somma deve essere su ogni singola cifra avrei dovuto controllare il numero e ottenere anche da esso ogni cifra.. quindi ho preferito così.

    Per questo, ho preferito continuare a dividere il numero per 10, ottenendo tramite l'operatore modulo le unità del numero. Poi li ho sommati.
    CODICE
    Il Multithreading non è stata una grande idea, dato che per i calcoli che devo effettuare perdo più tempo per lo scambio di contesto che per i calcoli ^^

    Utilizza il multithreading sono nel caso in cui 2 calcoli possono essere effettuati in parallelo (non dipendono l'uno dall'altro). L'unica ottimizzazione multithread che mi viene in mente è quella di sommare le cifre del numero inserito intanto che avviene la sua fattorizzazione... ma si sprecano più risorse e tempo per chiamare il thread piuttosto che effettuare i calcoli l'uno dopo l'altro.

    CODICE
    // Verifici la primalità
    private boolean isPrime(int m) {
      if(m==2) return true;
          if(m%2==0) return false;
          else {
            for(int i=3; i<(int)Math.sqrt(m); i+=2) {
              if(m%­i==0) return false;
            }
          }
          return true;
    }


    Penso che il controllo del fatto che il numero divisore sia primo non ti serva: dimmi un numero non primo di cui fattori non vengono considerati prima di arrivare a quel numero. prova a pensare ad esempio al numero 15; i suoi fattori sono 3 e 5, ma se il numero inserito li contiene già, questi verranno considerati (e divisi per il numero) prima di arrivare a 15; per cui il numero 15 verrà sempre saltato. E poi, il controllo ti fa eseguire un sacco di operazioni in più che rallentano tutto l'algoritmo qualora si dovesse lavorare con dei BigInteger.

    Edited by Red Eye - 4/2/2010, 22:57
     
    Top
    .
  7.  
    .
    Avatar

    Senior Member

    Group
    Staff
    Posts
    10,796

    Status
    Anonymous
    è brutto tutto lo sviluppo nel main xD

    Non sono ancora riuscito a guardarmi tutto il tuo codice.. ho gli occhi e la testa che non reggono, per cui quello che sto per dire potrsti averlo anche fatto.

    Ho parlato con un programmatore, e un altro approccio potrebbe essere trovare tutti i numeri primi in modo da non dover continuamente ricalcolarli.
    Successivamente trovare la fattorizzazione completa del numero (testando i vari fattori primi fino alla radice quadrata del numero n, magari in modo ricorsivo) ed infine farei la somma delle cifre.
     
    Top
    .
  8. Red Eye
     
    .

    User deleted


    CITAZIONE
    è brutto tutto lo sviluppo nel main xD

    Conta anche l'aspetto estetico del sorgente? :blink:

    CITAZIONE
    Ho parlato con un programmatore, e un altro approccio potrebbe essere trovare tutti i numeri primi in modo da non dover continuamente ricalcolarli.

    No so se sia vantaggioso in termini di tempo: la ricerca e lettura del file richiede del tempo e forse ci si impiega di meno a generare i numeri piuttosto che leggerli da un file (l'unica a risentirne sarà la CPU).

    Sui computer molto molto vecchi la lettura del file è la scelta migliore.

    EDIT: modificato il sorgente del post precedente; ora l'algoritmo non crea l'ArrayList di interi (abbattuto un ciclo for).

    Il main ora è più "bello" ;)

    Edited by Red Eye - 4/2/2010, 22:54
     
    Top
    .
  9.  
    .
    Avatar

    Senior Member

    Group
    Staff
    Posts
    10,796

    Status
    Anonymous
    Bè si può salvare anche in un ArrayList, o in un LinkedList.
    Però chiamare continuamente il metodo per trovare il primo è comunque dispendioso in termini di tempo.

    CITAZIONE
    Conta anche l'aspetto estetico del sorgente? :blink:

    Bhe no.. in questo caso poi è irrilevante.
     
    Top
    .
  10. GnuFabio
     
    .

    User deleted


    CITAZIONE (Red Eye @ 4/2/2010, 22:34)
    Conta anche l'aspetto estetico del sorgente? :blink:

    Beh io quando programmo cerco di rendere più bello esteticamente anche il codice XD
     
    Top
    .
  11. ~{Skydrake™}»
     
    .

    User deleted


    CITAZIONE (GnuFabio @ 5/2/2010, 13:58)
    Beh io quando programmo cerco di rendere più bello esteticamente anche il codice XD

    Ma non ci riesci mai :P
    (Almeno fino a qualche tempo fa)
     
    Top
    .
  12. x-reynik-x
     
    .

    User deleted


    Questa è la mia soluzione in Python.
    Si compone di due parti: una che scompone in fattori primi il numero, l'altra che verifica se la somma delle cifre del numero é uguale alla somma dei fattori.
    CODICE
    def scomponi(n):
           r = []
           d = 2
           while n > 1:
                   while n % d == 0:
                           r.append(d)
                           n //= d
                   d += 1
           return r

    def primo(n):
       if n == 2:
           return True
       if n % 2 == 0:
           return False
       for x in xrange(3, int(n**0.5)+1, 2):
           if n % x == 0:
               return False
       return True

    def Smith(n):
           if primo(n):
                   return False
           if sum(map(int, list(str(n)))) == sum([int(y) for x in scomponi(n) for y in str(x)]):
                   return True
           return False


    Questa calcola i numeri di Smith minori o uguali a n. Non è il massimo dell'efficienza, poiché controlla uno per uno i numeri, ma non conosco altro modo.
    Si basa sulle funzioni precedenti.

    CODICE
    def stampa_smith(n):
           for x in xrange(1, n+1):
                   if Smith(x):
                           print x


    Edited by x-reynik-x - 6/2/2010, 10:22
     
    Top
    .
  13.  
    .
    Avatar

    Senior Member

    Group
    Staff
    Posts
    10,796

    Status
    Anonymous
    In Python è comunque più performante dato che semplifica molte operazioni.

    Noto che hai modificato il programma ed il codice sorgente aggiungendo il test di primalità ;)
     
    Top
    .
  14. ~{Skydrake™}»
     
    .

    User deleted


    Ma quel test di primalità mi sembra abbastanza dispendioso...
    CODICE
    Private Function Primo(ByVal n As UInt16) As Boolean
           For x As UInt16 = 2 To Math.Sqrt(n)
               x += (x Mod 2 = 0)
               If n Mod x = 0 Then Return False
           Next
    Return True
       End Function

    L'ho scritto in Vb.NET, ma lo ritengo facilmente comprensibile. E' chiaro che in questo modo il ciclo salta tutte le x pari (eccetto il 2), ma senza utilizzare un if.
    Al momento mi viene in mente questo, poi se lo migliorerò vi aggiornerò.

    Edited by ~{Skydrake™}» - 10/2/2010, 22:06
     
    Top
    .
  15. x-reynik-x
     
    .

    User deleted


    CITAZIONE (RootkitNeo @ 5/2/2010, 17:08)
    In Python è comunque più performante dato che semplifica molte operazioni.

    Noto che hai modificato il programma ed il codice sorgente aggiungendo il test di primalità ;)

    Non avevo visto che i primi non erano considerati numeri di Smith!! ;)


    E poi cos'ha il mio test di più dispendioso del tuo? Anche il mio salta tutti i pari!
     
    Top
    .
35 replies since 27/11/2009, 15:02   566 views
  Share  
.