Smith Number
Last Updated :
29 Feb, 2024
Given a number n, the task is to find out whether this number is smith or not. A Smith Number is a composite number whose sum of digits is equal to the sum of digits in its prime factorization.
Examples:
Input : n = 4
Output : Yes
Prime factorization = 2, 2 and 2 + 2 = 4
Therefore, 4 is a smith number
Input : n = 6
Output : No
Prime factorization = 2, 3 and 2 + 3 is
not 6. Therefore, 6 is not a smith number
Input : n = 666
Output : Yes
Prime factorization = 2, 3, 3, 37 and
2 + 3 + 3 + (3 + 7) = 6 + 6 + 6 = 18
Therefore, 666 is a smith number
Input : n = 13
Output : No
Prime factorization = 13 and 13 = 13,
But 13 is not a smith number as it is not
a composite number
The idea is first find all prime numbers below a limit using Sieve of Sundaram (This is especially useful when we want to check multiple numbers for Smith). Now for every input to be checked for Smith, we go through all prime factors of it and find sum of digits of every prime factor. We also find sum of digits in given number. Finally we compare two sums. If they are same, we return true.
C++
#include<bits/stdc++.h>
using namespace std;
const int MAX = 10000;
vector < int > primes;
void sieveSundaram()
{
bool marked[MAX/2 + 100] = {0};
for ( int i=1; i<=( sqrt (MAX)-1)/2; i++)
for ( int j=(i*(i+1))<<1; j<=MAX/2; j=j+2*i+1)
marked[j] = true ;
primes.push_back(2);
for ( int i=1; i<=MAX/2; i++)
if (marked[i] == false )
primes.push_back(2*i + 1);
}
bool isSmith( int n)
{
int original_no = n;
int pDigitSum = 0;
for ( int i = 0; primes[i] <= n/2; i++)
{
while (n % primes[i] == 0)
{
int p = primes[i];
n = n/p;
while (p > 0)
{
pDigitSum += (p % 10);
p = p/10;
}
}
}
if (n != 1 && n != original_no)
{
while (n > 0)
{
pDigitSum = pDigitSum + n%10;
n = n/10;
}
}
int sumDigits = 0;
while (original_no > 0)
{
sumDigits = sumDigits + original_no % 10;
original_no = original_no/10;
}
return (pDigitSum == sumDigits);
}
int main()
{
sieveSundaram();
cout << "Printing first few Smith Numbers"
" using isSmith()n" ;
for ( int i=1; i<500; i++)
if (isSmith(i))
cout << i << " " ;
return 0;
}
|
Java
import java.util.Vector;
class Test
{
static int MAX = 10000 ;
static Vector <Integer> primes = new Vector<>();
static void sieveSundaram()
{
boolean marked[] = new boolean [MAX/ 2 + 100 ];
for ( int i= 1 ; i<=(Math.sqrt(MAX)- 1 )/ 2 ; i++)
for ( int j=(i*(i+ 1 ))<< 1 ; j<=MAX/ 2 ; j=j+ 2 *i+ 1 )
marked[j] = true ;
primes.addElement( 2 );
for ( int i= 1 ; i<=MAX/ 2 ; i++)
if (marked[i] == false )
primes.addElement( 2 *i + 1 );
}
static boolean isSmith( int n)
{
int original_no = n;
int pDigitSum = 0 ;
for ( int i = 0 ; primes.get(i) <= n/ 2 ; i++)
{
while (n % primes.get(i) == 0 )
{
int p = primes.get(i);
n = n/p;
while (p > 0 )
{
pDigitSum += (p % 10 );
p = p/ 10 ;
}
}
}
if (n != 1 && n != original_no)
{
while (n > 0 )
{
pDigitSum = pDigitSum + n% 10 ;
n = n/ 10 ;
}
}
int sumDigits = 0 ;
while (original_no > 0 )
{
sumDigits = sumDigits + original_no % 10 ;
original_no = original_no/ 10 ;
}
return (pDigitSum == sumDigits);
}
public static void main(String[] args)
{
sieveSundaram();
System.out.println( "Printing first few Smith Numbers" +
" using isSmith()" );
for ( int i= 1 ; i< 500 ; i++)
if (isSmith(i))
System.out.print(i + " " );
}
}
|
Python
import math
MAX = 10000
primes = []
def sieveSundaram ():
marked = [ 0 ] * (( MAX / 2 ) + 100 )
i = 1
while i < = ((math.sqrt ( MAX ) - 1 ) / 2 ) :
j = (i * (i + 1 )) << 1
while j < = MAX / 2 :
marked[j] = 1
j = j + 2 * i + 1
i = i + 1
primes.append ( 2 )
i = 1
while i < = MAX / 2 :
if marked[i] = = 0 :
primes.append( 2 * i + 1 )
i = i + 1
def isSmith( n) :
original_no = n
pDigitSum = 0 ;
i = 0
while (primes[i] < = n / 2 ) :
while n % primes[i] = = 0 :
p = primes[i]
n = n / p
while p > 0 :
pDigitSum + = (p % 10 )
p = p / 10
i = i + 1
if not n = = 1 and not n = = original_no :
while n > 0 :
pDigitSum = pDigitSum + n % 10
n = n / 10
sumDigits = 0
while original_no > 0 :
sumDigits = sumDigits + original_no % 10
original_no = original_no / 10
return pDigitSum = = sumDigits
sieveSundaram();
print "Printing first few Smith Numbers using isSmith()"
i = 1
while i< 500 :
if isSmith(i) :
print i,
i = i + 1
|
C#
using System;
using System.Collections;
class Test
{
static int MAX = 10000;
static ArrayList primes = new ArrayList(10);
static void sieveSundaram()
{
bool [] marked = new bool [MAX/2 + 100];
for ( int i=1; i<=(Math.Sqrt(MAX)-1)/2; i++)
for ( int j=(i*(i+1))<<1; j<=MAX/2; j=j+2*i+1)
marked[j] = true ;
primes.Add(2);
for ( int i=1; i<=MAX/2; i++)
if (marked[i] == false )
primes.Add(2*i + 1);
}
static bool isSmith( int n)
{
int original_no = n;
int pDigitSum = 0;
for ( int i = 0; ( int )primes[i] <= n/2; i++)
{
while (n % ( int )primes[i] == 0)
{
int p = ( int )primes[i];
n = n/p;
while (p > 0)
{
pDigitSum += (p % 10);
p = p/10;
}
}
}
if (n != 1 && n != original_no)
{
while (n > 0)
{
pDigitSum = pDigitSum + n%10;
n = n/10;
}
}
int sumDigits = 0;
while (original_no > 0)
{
sumDigits = sumDigits + original_no % 10;
original_no = original_no/10;
}
return (pDigitSum == sumDigits);
}
public static void Main()
{
sieveSundaram();
Console.WriteLine( "Printing first few Smith Numbers" +
" using isSmith()" );
for ( int i=1; i<500; i++)
if (isSmith(i))
Console.Write(i + " " );
}
}
|
Javascript
let MAX = 10000;
let primes = [];
function sieveSundaram(){
let LEN = Math.floor(MAX/2) + 100;
let marked = [];
for (let i=0; i < LEN; i++) {
marked.push(0);
}
for (let i=1; i<=Math.floor((Math.sqrt(MAX)-1)/2); i++){
for (let j=(i*(i+1))<<1; j<=Math.floor(MAX/2); j=j+2*i+1){
marked[j] = 1;
}
}
primes.push(2);
for (let i=1; i<=Math.floor(MAX/2); i++){
if (marked[i] == 0){
primes.push(2*i + 1);
}
}
}
function isSmith(n){
let original_no = n;
let pDigitSum = 0;
for (let i = 0; primes[i] <= Math.floor(n/2); i++){
while (n % primes[i] == 0){
let p = primes[i];
n = Math.floor(n/p);
while (p > 0){
pDigitSum += (p % 10);
p = Math.floor(p/10);
}
}
}
if (n != 1 && n != original_no){
while (n > 0){
pDigitSum = pDigitSum + n%10;
n = Math.floor(n/10);
}
}
let sumDigits = 0;
while (original_no > 0){
sumDigits = sumDigits + original_no % 10;
original_no = Math.floor(original_no/10);
}
return (pDigitSum === sumDigits);
}
{
sieveSundaram();
console.log( "Printing first few Smith Numbers using isSmith() " );
for (let i=1; i<500; i++){
if (isSmith(i)){
console.log(i);
}
}
}
|
PHP
<?php
$MAX = 10000;
$primes = array ();
function sieveSundaram()
{
global $MAX , $primes ;
$marked = array_fill (0, ( $MAX / 2 + 100), false);
for ( $i = 1; $i <= (sqrt( $MAX ) - 1) / 2; $i ++)
for ( $j = ( $i * ( $i + 1)) << 1;
$j <= $MAX / 2; $j = $j + 2 * $i + 1)
$marked [ $j ] = true;
array_push ( $primes , 2);
for ( $i = 1; $i <= $MAX / 2; $i ++)
if ( $marked [ $i ] == false)
array_push ( $primes , 2 * $i + 1);
}
function isSmith( $n )
{
global $MAX , $primes ;
$original_no = $n ;
$pDigitSum = 0;
for ( $i = 0; $primes [ $i ] <= $n / 2; $i ++)
{
while ( $n % $primes [ $i ] == 0)
{
$p = $primes [ $i ];
$n = $n / $p ;
while ( $p > 0)
{
$pDigitSum += ( $p % 10);
$p = $p / 10;
}
}
}
if ( $n != 1 && $n != $original_no )
{
while ( $n > 0)
{
$pDigitSum = $pDigitSum + $n % 10;
$n = $n / 10;
}
}
$sumDigits = 0;
while ( $original_no > 0)
{
$sumDigits = $sumDigits + $original_no % 10;
$original_no = $original_no / 10;
}
return ( $pDigitSum == $sumDigits );
}
sieveSundaram();
echo "Printing first few Smith Numbers" .
" using isSmith()\n" ;
for ( $i = 1; $i < 500; $i ++)
if (isSmith( $i ))
echo $i . " " ;
?>
|
Output:
Printing first few Smith Numbers using isSmith()
4 22 27 58 85 94 121 166 202 265 274 319 346 355 378 382 391 438 454 483
Time Complexity: O(n log n)
Auxiliary Space: O(n)
Share your thoughts in the comments
Please Login to comment...