-
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
. -
x-reynik-x.
User deleted
bello questo esercizio! . -
.
Sembrano carini, appena ritaglio un pò di tempo me li guardo! . -
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. -
.
Ho ritrovato il post, così lo riuppo.
..e posto la mia soluzione in Java. Al momento controlla solamente se il numero è di Smith.CODICEimport 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. -
Red Eye.
User deleted
Sempre in java, ma seguendo tanti concetti diversi CODICEimport 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;
}
}CITAZIONEL'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 xDCITAZIONEIn 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.CODICEIl 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. -
.
è 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.. -
Red Eye.
User deleted
CITAZIONEè brutto tutto lo sviluppo nel main xD
Conta anche l'aspetto estetico del sorgente?CITAZIONEHo 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. -
.
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.CITAZIONEConta anche l'aspetto estetico del sorgente?
Bhe no.. in questo caso poi è irrilevante.. -
GnuFabio.
User deleted
CITAZIONE (Red Eye @ 4/2/2010, 22:34)Conta anche l'aspetto estetico del sorgente?
Beh io quando programmo cerco di rendere più bello esteticamente anche il codice XD. -
~{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
(Almeno fino a qualche tempo fa). -
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.CODICEdef 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.CODICEdef 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. -
.
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à. -
~{Skydrake™}».
User deleted
Ma quel test di primalità mi sembra abbastanza dispendioso... CODICEPrivate 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. -
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!.